/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1992 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 source code is provided to you solely for       */
/*    the purpose of assisting you in your development of OS/2 device        */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Developer Connection Device Driver       */
/*    Source Kit for OS/2. This Copyright statement may not be removed.      */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = SCSISTR1.C
 *
 * DESCRIPTIVE NAME = IBM2SCSI.ADD - Adapter Driver for IBM SCSI adapters.
 *                    Strat1 entry point.
 *
 *
 * VERSION = V2.0
 *
 * DATE
 *
 * DESCRIPTION  Handle strategy 1 requests from the kernel.
 *
*/

/*----------------------*/
/* System include files */
/*----------------------*/

#define INCL_NOBASEAPI
#define INCL_NOPMAPI
#include "os2.h"
#include "devcmd.h"
#include "error.h"
#include "dskinit.h"

/*----------------------*/
/* ADD include files    */
/*----------------------*/

#include "strat2.h"
#include "reqpkt.h"
#include "iorb.h"
#include "scb.h"
#include "scsi.h"
#include "abios.h"
#include "dhcalls.h"

/*----------------------*/
/* Local include files  */
/*----------------------*/

#include "mmscb.h"
#include "delivery.h"
#include "scsiadd.h"
#include "scsiextn.h"
#include "scsipro.h"


/********************** START OF SPECIFICATIONS ***************************/
/*                                                                        */
/* SUBROUTINE NAME:  SCSIStrat1                                           */
/*                                                                        */
/* DESCRIPTIVE NAME: SCSI ADD Strategy Routine.                           */
/*                                                                        */
/* FUNCTION: This routine is the strategy 1 entry point for an OS/2 DD.   */
/*           It supports only the INIT command.  All others are not       */
/*           supported and are returned with an unknown command error.    */
/*           Both ring 0 and ring 3 init commands are supported.          */
/*                                                                        */
/* ENTRY POINT:                                                           */
/*                                                                        */
/* LINKAGE: call far from the kernel                                      */
/*                                                                        */
/* INPUT: ES:BX - points to OS/2 DD request packet.                       */
/*                                                                        */
/* EXIT-NORMAL: Return to the kernel                                      */
/*                                                                        */
/* EXIT-ERROR:  Error status is set in RB.                                */
/*                                                                        */
/*********************** END OF SPECIFICATIONS ****************************/

/*------------------------------------------------------------------------*/
/* OS/2 Strategy Request Router                                           */
/* ----------------------------                                           */
/* This routine receives the OS/2 Initialization Request Packet. Any      */
/* other request types are rejected.                                      */
/*------------------------------------------------------------------------*/

VOID NEAR SCSIStrat1()
{
   PRPH    pRPH;                  /* Pointer to RPH (Request Packet Header) */
   USHORT  Cmd, rc, i;            /* Local variable                         */
   PMACHINE_CONFIG_INFO  pMInfo;  /* Ptr to machine config information pkt  */

   #ifdef DEBUG
      PBYTE pData;
      struct {
         USHORT t1;
         ULONG  t2;
         ULONG  t3;
         } selinfo;
   #endif

   _asm {
      mov word ptr pRPH[0], bx    /* pRPH is initialized to   */
      mov word ptr pRPH[2], es    /* ES:BX passed from        */
   }                              /* the kernel               */

   DBSTOP();
   _asm nop    ;                  /* for debug only           */

   pRPH->Status = 0;

   Cmd = pRPH->Cmd;

   /*------------------------------------------------------------------*/
   /*  Process a base or installable init command if not already done. */
   /*------------------------------------------------------------------*/

   if ((Cmd == CMDInitBase || Cmd == CMDInit) && !(ADDStatus & INITDONE)) {

      ADDStatus |= INITDONE;
      Device_Help = ((PRPINITIN)pRPH)->DevHlpEP;

      for (i=0; i<MAX_SUPPORTED_ADAPTERS; i++) {
         ACBTbl[i].status = 0;
      }

      /*------------------------------------------------------------*//*@81320*/
      /* Get the machine config info structure from the init packet *//*@81320*/
      /* and make sure that we are on a micro channel machine.  If  *//*@81320*/
      /* not then do a quiet fail (nonfatal).                       *//*@81320*/
      /*------------------------------------------------------------*//*@81320*/

      pMInfo           =                                              /*@81320*/
         (PMACHINE_CONFIG_INFO)((PRPINITIN)pRPH)->InitArgs;           /*@81320*/

      OFFSETOF(pMInfo) =                                              /*@81320*/
         ((PDDD_PARM_LIST)pMInfo)->machine_config_table;              /*@81320*/

      if (pMInfo->BusInfo & BUSINFO_MCA) {                            /*@81320*/

         /*------------------------------------------------------------*/
         /* Call GetInitParms before calling the scsi init routine.    */
         /* This will set global parameters needed before we initialize*/
         /* the scsi subsystem.  After init is done the call it again  */
         /* to allow device specific parameters to be set.             */
         /*------------------------------------------------------------*/

         GetInitParms((PRPINITIN)pRPH);   /* 1st time for global parms  */
         rc = SCSIInit();
         GetInitParms((PRPINITIN)pRPH);
      }
      else {                                                          /*@81320*/
         rc = ERROR + NONFATAL;   /* force a quiet failure below */   /*@81320*/
      }                                                               /*@81320*/

      /*-------------------------------------------------------*/
      /* If rc is 0 then there were no errors, so exit with no */
      /* error code.                                           */
      /*-------------------------------------------------------*/

      if (rc == 0) {
         ((PRPINITOUT)pRPH)->CodeEnd     = (USHORT)Code_End;
         ((PRPINITOUT)pRPH)->DataEnd     = (USHORT)free;

         /*---------------------------------------------------------------*/
         /* For the debug version do not release any of the data segment. */
         /* The debug messages are at the end of it!!                     */
         /*---------------------------------------------------------------*/

         #ifdef DEBUG
            pData = (PBYTE)&SCSIADDHeader;
            DevHelp_GetDescInfo(SELECTOROF(pData),(PBYTE)&selinfo);
            ((PRPINITOUT)pRPH)->DataEnd  = (USHORT)(selinfo.t3-1);
         #endif
         ((PRPINITOUT)pRPH)->rph.Status  = STDON;
      }

      /*--------------------------------------------------------------*/
      /* If the there was an error then see if the error was fatal or */
      /* non fatal.  If fatal the do a general failure, if not then   */
      /* do a quiet fail (no "press enter" message displayed)         */
      /*--------------------------------------------------------------*/

      else {
         ((PRPINITOUT)pRPH)->CodeEnd     = 0;
         ((PRPINITOUT)pRPH)->DataEnd     = 0;
         if (rc & NONFATAL) {
            ((PRPINITOUT)pRPH)->rph.Status  = ERROR_I24_QUIET_INIT_FAIL;
         }
         else {
            ((PRPINITOUT)pRPH)->rph.Status  = ERROR_I24_GEN_FAILURE;
         }
         ((PRPINITOUT)pRPH)->rph.Status |= STERR + STDON;

         if (ADDStatus & IRQSET) {
            DevHelp_UnSetIRQ(0x0e);
         }
      }
   }
   else {

      pRPH->Status = STATUS_DONE | STATUS_ERR_UNKCMD;

   }

   _asm { leave };
   _asm { retf };

}
