home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / DASD / OS2ASPI / ASPIINIT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-14  |  34.4 KB  |  891 lines

  1. /*DDK*************************************************************************/
  2. /*                                                                           */
  3. /* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
  4. /*                                                                           */
  5. /*    The following IBM OS/2 WARP source code is provided to you solely for  */
  6. /*    the purpose of assisting you in your development of OS/2 WARP device   */
  7. /*    drivers. You may use this code in accordance with the IBM License      */
  8. /*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
  9. /*    Copyright statement may not be removed.                                */
  10. /*                                                                           */
  11. /*****************************************************************************/
  12. /*static char *SCCSID = "src/dev/dasd/os2aspi/aspiinit.c, aspi, r206 93/03/20";*/
  13. /**************************************************************************
  14.  *
  15.  * SOURCE FILE NAME = ASPIINIT.C
  16.  *
  17.  * DESCRIPTIVE NAME = OS2ASPI.DMD - OS/2 ASPI Device Manager
  18.  *                    ASPI Device Manager - Initialization
  19.  *
  20.  *
  21.  * VERSION = V2.0
  22.  *
  23.  * DATE
  24.  *
  25.  * DESCRIPTION  Builds configuration dependent data in response to OS/2
  26.  *              KERNEL initialization request.
  27.  *
  28.  *
  29. */
  30.  
  31. #define INCL_NOBASEAPI
  32. #define INCL_NOPMAPI
  33. #include <os2.h>
  34.  
  35. #include <devcmd.h>
  36. #include <devclass.h>
  37.  
  38. #define INCL_INITRP_ONLY
  39. #include <reqpkt.h>
  40.  
  41. #include <iorb.h>
  42. #include <addcalls.h>
  43. #include <scsi.h>
  44. #include <dhcalls.h>
  45. #include <dskinit.h>
  46.  
  47. #include <aspi.h>
  48. #include <aspicons.h>
  49. #include <aspitype.h>
  50. #include <aspipro.h>
  51. #include <aspiextn.h>
  52.  
  53. #include <cmdparse.h>
  54. #include <cmdpdefs.h>
  55.  
  56. extern      USHORT               NumADDs;                /* number of adapter drivers */
  57. extern      UCHAR                numberOfASPIAdapters;
  58. extern      UCHAR                numberOfASPITargets;
  59. extern      USHORT               freeSRBSpace;           /* bytes available for SRBs  */
  60. extern      NPSRB_LINK           npSRBLinkFreeList;      /* pointer to available SRB  */
  61. extern      PVOID                pDataSeg;               /* Our data segment pointer  */
  62. extern      ULONG                ppDataSeg;              /* Our data segment pointer  */
  63. extern      UCHAR                Pool[];
  64. extern      IORBH                InitIORB;
  65. extern      UCHAR                deviceTableBuffer[MAX_DT_SIZE];
  66. extern      DEVICETABLE          *pDeviceTable;
  67. extern      NPACB                npLastACB;
  68. extern      NPACB                npACBAnchor;
  69. extern      NPATE                npLastATE;
  70. extern      NPATE                npFirstATE;
  71. extern      NPIORB_UNIT_CONTROL  npIORBUnitControl;
  72. extern      USHORT               allocationOverride;
  73. extern      USHORT               shareTargets;
  74. extern      OPTIONTABLE          opttable;
  75. extern      UCHAR                *invalidParameters;
  76. extern      USHORT               outbuf_len;
  77. extern      PBYTE                poutbuf;
  78. extern      MSGTABLE             InitMsg;
  79. extern      UCHAR                ASPI_PDDName[];
  80. extern      DIREXCEPT            DirTableExceptions[];
  81. extern      USHORT               MaxDirExceptions;
  82. extern      NPIORB_ADAPTER_PASSTHRU npIORBInq;
  83.  
  84. extern      USHORT SendIORBandWait( npIORB, pADD_IORB_Entry );
  85.  
  86. /*--------------------------------------------------*/
  87. /*                                                  */
  88. /* Process Base Initialization Request Packet       */
  89. /* ------------------------------------------       */
  90. /*                                                  */
  91. /*                                                  */
  92. /*--------------------------------------------------*/
  93.  
  94. /*********************************************************
  95. *                                                        *
  96. *   Procedure Name : ASPIInit                            *
  97. *                                                        *
  98. *   Description : This procedure initializes the ASPI    *
  99. *   device manager. All available SCSI devices will      *
  100. *   be allocated data structures to record their         *
  101. *   pertinent information.                               *
  102. *                                                        *
  103. *   Input :                                              *
  104. *         pRPI - A pointer to the initialization         *
  105. *            request packet.                             *
  106. *                                                        *
  107. *   Output :                                             *
  108. *                                                        *
  109. *********************************************************/
  110. USHORT ASPIInit(PRPINITIN pRPI)
  111.  
  112.    {
  113.    USHORT             rc;
  114.    USHORT             i;
  115.    struct DevClassTableStruc far *pDevClassTable;  /* ptr to registered ADD EPs */
  116.    struct DevClassTableEntry far *pTableADDEntry;
  117.    struct DevClassTableEntry far *pCurrentADDEntry;
  118.    VOID (FAR * pADD_IORB_Entry) ();                /* Driver entry point        */
  119.    PRPINITOUT   pRPO;
  120.    PDDD_PARM_LIST pDDD_Parm_List;
  121.  
  122.    InitComplete = 1;
  123.    pRPO = (PRPINITOUT) pRPI;
  124.    Device_Help = pRPI->DevHlpEP;
  125.    pDDD_Parm_List = (PDDD_PARM_LIST) pRPI->InitArgs;
  126.  
  127.    rc = DevHelp_GetDOSVar((USHORT) DHGETDOSV_DEVICECLASSTABLE,
  128.                            1,
  129.                           (PPVOID) &pDevClassTable);
  130.  
  131.    if (ParseCmdLine(pDDD_Parm_List))
  132.       {
  133.       TTYWrite(invalidParameters);
  134.       }
  135.  
  136.    /* Save the physical address of our data segment */
  137.    pDataSeg = (PVOID) &pDataSeg;                                     /*@V53752*/
  138.    OFFSETOF(pDataSeg) = 0;                                           /*@V53752*/
  139.                                                                      /*@V53752*/
  140.    rc = DevHelp_VirtToPhys(pDataSeg,                                 /*@V53752*/
  141.                            (PULONG) &ppDataSeg);                     /*@V53752*/
  142.  
  143.    if (!rc)
  144.       {
  145.       NumADDs   = pDevClassTable->DCCount;
  146.       pTableADDEntry = pCurrentADDEntry = pDevClassTable->DCTableEntries;
  147.  
  148.       /* Scan all ADD device tables for available devices */
  149.       for (i = 0; i < NumADDs; i++, pCurrentADDEntry++ )
  150.          {
  151.          OFFSETOF(pADD_IORB_Entry) = pCurrentADDEntry->DCOffset;
  152.          SELECTOROF(pADD_IORB_Entry) = pCurrentADDEntry->DCSelector;
  153.  
  154.          /* Get the device table for the current ADD */
  155.          if ( GetADDDeviceTable(pADD_IORB_Entry))
  156.             continue;
  157.  
  158.          /* Search the current table for SCSI devices */
  159.          ScanForSCSIAdapters(pADD_IORB_Entry,pTableADDEntry);
  160.          }
  161.       }
  162.  
  163.    /* Abort "quietly" because there are no available targets */
  164.    if (numberOfASPITargets == 0)
  165.       {
  166.       pRPO->Unit   = 0;
  167.       pRPO->CodeEnd = 0;
  168.       pRPO->DataEnd = 0;
  169.       return(0x8115);
  170.       }
  171.    else
  172.       {
  173.       /* Allocate space for all possible SRBs */
  174.       InitSRBPool();
  175.  
  176.       /* Register the entry point for VASPI.SYS */
  177.       DevHelp_RegisterPDD(ASPI_PDDName,&VirtualASPIEntry);
  178.  
  179.       /* All devices were successfully initialized. Return no errors */
  180.       /* and throw away any unnecessary code.                        */
  181.  
  182.       pRPO->Unit   = 0;
  183.       pRPO->CodeEnd = (USHORT) &ASPIInit;
  184.       pRPO->DataEnd = (USHORT) npConfigPool;
  185.  
  186.       return (STDON);
  187.       }
  188.    }
  189.  
  190.  
  191. /*********************************************************
  192. *                                                        *
  193. *   Procedure Name : GetADDDeviceTable                   *
  194. *                                                        *
  195. *   Description : This procedure retrieves the table     *
  196. *   of devices controlled by the current ADD.            *
  197. *                                                        *
  198. *   Input :                                              *
  199. *         pADD_IORB_Entry - A pointer to the ADD entry   *
  200. *            point.                                      *
  201. *                                                        *
  202. *   Output :                                             *
  203. *                                                        *
  204. *********************************************************/
  205. USHORT GetADDDeviceTable(VOID (FAR * pADD_IORB_Entry) (PIORB))
  206.  
  207.    {
  208.    NPIORB_CONFIGURATION pIORB = (NPIORB_CONFIGURATION) &InitIORB;
  209.  
  210.    /* Build an IORB and send it to the ADD */
  211.    pIORB->iorbh.Length          = sizeof(IORB_CONFIGURATION);
  212.    pIORB->iorbh.CommandCode     = IOCC_CONFIGURATION;
  213.    pIORB->iorbh.CommandModifier = IOCM_GET_DEVICE_TABLE;
  214.    pIORB->iorbh.Status          = 0;
  215.    pIORB->iorbh.ErrorCode       = 0;
  216.    pIORB->pDeviceTable          = pDeviceTable;
  217.    pIORB->DeviceTableLen        = sizeof(deviceTableBuffer);
  218.    pIORB->iorbh.NotifyAddress = &InitPost;
  219.  
  220.    return(SendIORBandWait((NPIORB) pIORB, pADD_IORB_Entry ));
  221.    }
  222.  
  223.  
  224. /*********************************************************
  225. *                                                        *
  226. *   Procedure Name : ScanforSCSIAdapters                 *
  227. *                                                        *
  228. *   Description : This procedure verifies the current    *
  229. *   ADD controls SCSI devices and records all the        *
  230. *   information about available devices.                 *
  231. *                                                        *
  232. *   Input :                                              *
  233. *         pADD_IORB_Entry - A pointer to the ADD entry   *
  234. *            point, assuming there is no filter.         *
  235. *         pADDEntryTable - A pointer to all the entry    *
  236. *            points for units attached to the ADD.       *
  237. *                                                        *
  238. *   Output :   This function returns zero if at least    *
  239. *   one available target is found in the current ADD.    *
  240. *   A non-zero value indicates some error was detected.  *
  241. *                                                        *
  242. *********************************************************/
  243. USHORT SCANforSCSIAdapters(VOID (FAR * pADD_IORB_Entry) (PIORB),
  244.                            struct DevClassTableEntry far *pADDEntryTable)
  245.    {
  246.    NPADAPTERINFO  npAI;
  247.    NPUNITINFO     npUI;
  248.  
  249.    USHORT         NumAdapters;      /* Number of adapters using current ADD */
  250.    USHORT         NumUnits;         /* Number of devices on current adapter */
  251.    USHORT         filterADDHandle;
  252.    UCHAR          DevBus;           /* Type of bus used by current adapter  */
  253.  
  254.    USHORT         i, j;             /* Loop control variables               */
  255.    USHORT         resultCode = -1;  /* Assume no targets will be found      */
  256.  
  257.  
  258.    NPACB          npACB;            /* Pointer to adapter control block created */
  259.    USHORT         allocationStatus; /* Result of allocating the current target */
  260.    VOID (FAR * pDevice_ADD_Entry) (PIORB);
  261.  
  262.    NumAdapters = pDeviceTable->TotalAdapters;
  263.  
  264.    /* Scan all adapters using the current ADD */
  265.    for (i = 0; i < NumAdapters; i++ )
  266.       {
  267.       npAI =  pDeviceTable->pAdapter[i];
  268.       DevBus = (UCHAR) npAI->AdapterDevBus;
  269.  
  270.       /* Make sure the adapter is SCSI */
  271.       if (DevBus == AI_DEVBUS_SCSI_1 || DevBus == AI_DEVBUS_SCSI_2 ||
  272.           DevBus == AI_DEVBUS_SCSI_3 )
  273.          {
  274.          NumUnits  = npAI->AdapterUnits;
  275.          npUI      = npAI->UnitInfo;
  276.  
  277.          /* Create an ACB for the current adapter */
  278.          if ((npACB = BuildACB(npAI)) != 0)
  279.             {
  280.             /* Reset last ATE pointer because no ATE have been created.*//*@V55762*/
  281.             npLastATE = 0;                                              //*@V55762*/
  282.  
  283.             /* Check all devices attached to the current adapter */
  284.             for (j = 0; j < NumUnits; j++, npUI++)
  285.                {
  286.                
  287.                /* If this target has a filter ADD, use that entry point */
  288.                filterADDHandle = npUI->FilterADDHandle;
  289.                if (filterADDHandle)
  290.                   {
  291.                   OFFSETOF(pDevice_ADD_Entry) =
  292.                            pADDEntryTable[filterADDHandle - 1].DCOffset;
  293.  
  294.                   SELECTOROF(pDevice_ADD_Entry) =
  295.                            pADDEntryTable[filterADDHandle - 1].DCSelector;
  296.                   }
  297.                else
  298.                   pDevice_ADD_Entry = pADD_IORB_Entry;
  299.  
  300.                /* Skip all devices already allocated unless the user has */
  301.                /* requested allocation override */
  302.                allocationStatus = CheckUnitAllocated(pDevice_ADD_Entry,npUI);
  303.  
  304.                if ((allocationStatus) && (!allocationOverride))
  305.                   continue;
  306.  
  307.                /* Build an ATE for each available device */
  308.                if (BuildATE(pDevice_ADD_Entry,
  309.                             npUI,
  310.                             allocationStatus) == 0)
  311.                   {
  312.                   resultCode = -1;      /* Target entry structure NOT built */
  313.                   break;
  314.                   }
  315.  
  316.                /* Remember at least one target was found */
  317.                resultCode = 0;
  318.                }
  319.             }
  320.           }
  321.       }
  322.  
  323.    return(resultCode);
  324.    }
  325.  
  326. /*********************************************************
  327. *                                                        *
  328. *   Procedure Name : CheckUnitAllocated                  *
  329. *                                                        *
  330. *   Description : This procedure confirms that the       *
  331. *   current unit is NOT allocated to another device      *
  332. *   manager.                                             *
  333. *                                                        *
  334. *   Input :                                              *
  335. *         pADD_IORB_Entry - A pointer to the ADD entry   *
  336. *            point.                                      *
  337. *         npUI - A pointer to the information on the     *
  338. *            current device.                             *
  339. *                                                        *
  340. *   Output :                                             *
  341. *                                                        *
  342. *********************************************************/
  343. USHORT CheckUnitAllocated( VOID (FAR * pADD_IORB_Entry) (PIORB),NPUNITINFO npUI )
  344.  
  345.    {
  346.    USHORT resultCode;
  347.  
  348.    /* Clean up the IORB before filling in appropriate fields */
  349.  
  350.    memset((PBYTE) npIORBUnitControl,
  351.           0,
  352.           sizeof(IORB_UNIT_CONTROL));
  353.  
  354.    /* Set up IORB to check unit allocation */
  355.  
  356.    npIORBUnitControl->iorbh.Length          = sizeof(IORB_UNIT_CONTROL);
  357.    npIORBUnitControl->iorbh.UnitHandle      = npUI->UnitHandle;
  358.    npIORBUnitControl->iorbh.CommandCode     = IOCC_UNIT_CONTROL;
  359.    npIORBUnitControl->iorbh.CommandModifier = IOCM_ALLOCATE_UNIT;
  360.    npIORBUnitControl->iorbh.Status          = 0;
  361.    npIORBUnitControl->iorbh.ErrorCode       = 0;
  362.    npIORBUnitControl->Flags                 = 0;
  363.    npIORBUnitControl->iorbh.NotifyAddress   = &InitPost;
  364.  
  365.    resultCode = SendIORBandWait((NPIORB) npIORBUnitControl,
  366.                                 pADD_IORB_Entry);
  367.  
  368.    /* If the unit was unallocated, release it before returning */
  369.  
  370.    if (!resultCode)
  371.       {
  372.       npIORBUnitControl->iorbh.UnitHandle      = npUI->UnitHandle;
  373.       npIORBUnitControl->iorbh.CommandModifier = IOCM_DEALLOCATE_UNIT;
  374.       npIORBUnitControl->iorbh.Status          = 0;
  375.       npIORBUnitControl->iorbh.ErrorCode       = 0;
  376.       npIORBUnitControl->Flags                 = 0;
  377.       npIORBUnitControl->iorbh.NotifyAddress   = &InitPost;
  378.       resultCode = SendIORBandWait((NPIORB) npIORBUnitControl,
  379.                                    pADD_IORB_Entry );
  380.       }
  381.  
  382.    return(resultCode);
  383.    }
  384.  
  385. /*********************************************************
  386. *                                                        *
  387. *   Procedure Name : BuildACB                            *
  388. *                                                        *
  389. *   Description : This procedure creates an adapter      *
  390. *   control block for the current adapter                *
  391. *                                                        *
  392. *   Input :                                              *
  393. *         npAI - A pointer to the information on the     *
  394. *            current adapter.                            *
  395. *                                                        *
  396. *   Output :   A pointer to the adapter control block    *
  397. *                                                        *
  398. *********************************************************/
  399. NPACB BuildACB(NPADAPTERINFO npAI )
  400.  
  401.    {
  402.    NPACB npACB;
  403.  
  404.    /* Allocate memory for the data structure */
  405.    if ((npACB = (NPACB) InitAllocate(sizeof(ACB))) != 0)
  406.       {
  407.       /* If this is the first adapter, make it the anchor */
  408.       if (!npACBAnchor)
  409.          npACBAnchor = npACB;
  410.       else
  411.          npLastACB->npNextACB = npACB;
  412.  
  413.       /* Initialize all fields of the ACB */
  414.       npLastACB = npACB;
  415.       npACB->npNextACB        = 0;
  416.       npACB->npFirstATE       = 0;
  417.       npACB->AdapterFlags     = npAI->AdapterFlags;
  418.       npACB->AdapterIndex     = numberOfASPIAdapters++;
  419.       npACB->AdapterTargetID  = npAI->AdapterSCSITargetID;
  420.       memcpy(npACB->AdapterName,
  421.              npAI->AdapterName,
  422.              sizeof(npACB->AdapterName));
  423.  
  424.       /* Assume the adapter supports residual byte count */           /*@V53040*/
  425.       /* and scatter/gather                              */           /*@V53040*/
  426.       npACB->AdapterFeatures     = ASPI_RESIDUAL_BYTE                 /*@V53040*/
  427.                                                 | ASPI_SCATTER_GATHER;/*@V53040*/
  428.  
  429.       /* Determine if the adapter can address > 16MB     */
  430.       if (!(npACB->AdapterFlags & AF_16M))
  431.          npACB->AdapterFeatures |= ASPI_ADDRESS_LIMITED;
  432.  
  433.       npACB->MaximumSGList       = npAI->MaxHWSGList;                 /*@V53040*/
  434.       npACB->MaximumCDBTransfer  = npAI->MaxCDBTransferLength;        /*@V53040*/
  435.       npACB->AdapterFlags        = npAI->AdapterFlags;
  436.       }
  437.    return(npACB);
  438.    }
  439.  
  440.  
  441. /*********************************************************
  442. *                                                        *
  443. *   Procedure Name : BuildATE                            *
  444. *                                                        *
  445. *   Description : This procedure creates an adapter      *
  446. *   target entry for the current unit                    *
  447. *                                                        *
  448. *   Input :                                              *
  449. *         pADD_IORB_Entry - A pointer to the ADD entry   *
  450. *            point for the current unit.                 *
  451. *         npUI - A pointer to the information on the     *
  452. *            current device.                             *
  453. *         allocationStatus - A record of whether the     *
  454. *            current device has already been allocated   *
  455. *            by another device manager.                  *
  456. *                                                        *
  457. *   Output :   A pointer to the adapter target entry     *
  458. *                                                        *
  459. *********************************************************/
  460. NPATE BuildATE(VOID (FAR * pADD_IORB_Entry) (PIORB), NPUNITINFO npUI,
  461.                USHORT allocationStatus)
  462.  
  463.    {
  464.    NPATE              npATE;
  465.    NPDIREXCEPT        npDIRE;
  466.    NPSCSI_INQDATA     npINQ;
  467.    USHORT             i, n;
  468.  
  469.    /* Allocate memory for the data structure */
  470.    if ((npATE = (NPATE) InitAllocate(sizeof(ATE))) != 0)
  471.       {
  472.       /* Remember which adapter owns this device */
  473.       npATE->npOwnerACB = npLastACB;
  474.  
  475.       /* If this is the first adapter, make it the anchor */
  476.       if (!npLastATE)
  477.          npLastACB->npFirstATE = npATE;
  478.       else
  479.          npLastATE->npNextATE = npATE;
  480.  
  481.       /* Initialize all fields of the ATE */
  482.       npLastATE = npATE;
  483.       npATE->SRBActiveQueueCount = 0;
  484.       npATE->npSRBActiveQueue = 0;
  485.       npATE->TargetADD_Entry  = pADD_IORB_Entry;
  486.       npATE->Flags            = 0;
  487.       npATE->UnitHandle       = npUI->UnitHandle;
  488.       npATE->QueuingCount     = npUI->QueuingCount;
  489.       npATE->DeviceTargetID   = npUI->UnitSCSITargetID;
  490.       npATE->DeviceTargetLUN  = npUI->UnitSCSILUN;
  491.       npATE->DeviceType       = (UCHAR) npUI->UnitType;
  492.       npATE->TargetFeatures   = 0;
  493.  
  494.       /**
  495.        ** Select a DATA TRANSFER direction table based
  496.        ** on the SCSI device type
  497.        **/
  498.       switch (npATE->DeviceType)
  499.          {
  500.           case UIB_TYPE_DISK:
  501.           case UIB_TYPE_CDROM:
  502.           case UIB_TYPE_WORM:
  503.           case UIB_TYPE_OPTICAL_MEMORY:
  504.             npATE->npDirTable = DirTableDASD;
  505.             break;
  506.           case UIB_TYPE_TAPE:
  507.             npATE->npDirTable = DirTableTAPE;
  508.             break;
  509.           case UIB_TYPE_PROCESSOR:
  510.             npATE->npDirTable = DirTablePROCESSOR;
  511.             break;
  512.           case UIB_TYPE_SCANNER:
  513.             npATE->npDirTable = DirTableSCANNER;
  514.             break;
  515.           case UIB_TYPE_PRINTER:
  516.             npATE->npDirTable = DirTablePRINTER;
  517.             break;
  518.           case UIB_TYPE_CHANGER:
  519.             npATE->npDirTable = DirTableCHANGER;
  520.             break;
  521.           case UIB_TYPE_COMM:
  522.             npATE->npDirTable = DirTableCOMM;
  523.             break;
  524.           default:
  525.             npATE->npDirTable = 0;
  526.           }
  527.  
  528.       /**
  529.        ** Obtain device inquiry data and determine if this
  530.        ** device matches anyone on the exception list
  531.        **/
  532.       if ( npINQ = GetInquiryData( npATE )  )
  533.          {
  534.          npDIRE = DirTableExceptions;
  535.          npATE->npDirExcept = 0;
  536.  
  537.          for (i = 0; i < MaxDirExceptions; i++, npDIRE++ )
  538.             {
  539.             n = strlength((PSZ) npDIRE->npVendorID);
  540.             if ( !strncmp( (PSZ) npDIRE->npVendorID, (PSZ) npINQ->VendorID, n ) )
  541.                {
  542.                continue;
  543.                }
  544.             n = strlength((PSZ) npDIRE->npProductID);
  545.             if ( !strncmp( (PSZ) npDIRE->npProductID, (PSZ) npINQ->ProductID, n ) )
  546.                {
  547.                continue;
  548.                }
  549.             npATE->npDirExcept = npDIRE->npExceptList;
  550.             }
  551.          }
  552.  
  553.       /* Remember that another ASPI target was found */
  554.       numberOfASPITargets++;
  555.  
  556.       /* Record the unit as allocated if the user wishes to share */
  557.       /* allocation with another device manager that has already  */
  558.       /* allocated the target. Remember that a device manager that */
  559.       /* loads AFTER this one may allocate the target as well. */
  560.       if (allocationStatus && allocationOverride)
  561.          {
  562.          npATE->Flags |= ATEF_IGNORE_ALLOCATION;
  563.          npATE->TargetFeatures |= ASPI_DEVICE_ALLOCATION_SHARED;
  564.  
  565.          }
  566.  
  567.       /* If the user wishes to share on a command basis and deallocate */
  568.       /* after each command, then record that here as well. */
  569.       /* Since deallocating a target that was permanently allocated by */
  570.       /* another manager may cause problems, we have to handle that too. */
  571.       /* The simplest thing to do is check the allocation status and if */
  572.       /* the device was already allocated, don't mark it as shared. */
  573.       if (shareTargets && !allocationStatus)
  574.          npATE->Flags |= ATEF_SHARE_ALLOCATION;
  575.       }
  576.  
  577.    return(npATE);
  578.    }
  579.  
  580. /*********************************************************
  581. *                                                        *
  582. *   Procedure Name : GetInquiryData                      *
  583. *                                                        *
  584. *                                                        *
  585. *                                                        *
  586. *                                                        *
  587. *                                                        *
  588. *********************************************************/
  589.  
  590. NPSCSI_INQDATA GetInquiryData( NPATE npATE )
  591.    {
  592.  
  593.    NPSCSI_INQDATA    npInqBuf;
  594.    NPBYTE            npCDB;
  595.    NPSCATGATENTRY    npSGList;
  596.    USHORT            rc, AllocStatus;
  597.  
  598.    memset((PBYTE) npIORBUnitControl,
  599.           0,
  600.           sizeof(IORB_UNIT_CONTROL));
  601.  
  602.    /* Set up IORB to check unit allocation */
  603.  
  604.    npIORBUnitControl->iorbh.Length          = sizeof(IORB_UNIT_CONTROL);
  605.    npIORBUnitControl->iorbh.UnitHandle      = npATE->UnitHandle;
  606.    npIORBUnitControl->iorbh.CommandCode     = IOCC_UNIT_CONTROL;
  607.    npIORBUnitControl->iorbh.CommandModifier = IOCM_ALLOCATE_UNIT;
  608.    npIORBUnitControl->iorbh.RequestControl  = IORB_ASYNC_POST;
  609.    npIORBUnitControl->iorbh.Status          = 0;
  610.    npIORBUnitControl->iorbh.ErrorCode       = 0;
  611.    npIORBUnitControl->Flags                 = 0;
  612.    npIORBUnitControl->iorbh.NotifyAddress   = &InitPost;
  613.  
  614.    AllocStatus = SendIORBandWait((NPIORB) npIORBUnitControl,
  615.                                           npATE->TargetADD_Entry);
  616.  
  617.    memset((PBYTE) npIORBInq,
  618.           0,
  619.           sizeof(IORB_ADAPTER_PASSTHRU)+sizeof(SCSI_INQDATA));
  620.  
  621.    /**
  622.     ** The Inquiry CDB and SGList are built in the IORB's
  623.     ** DMWorkSpace. The Inquiry data buffer immediately follows
  624.     ** the Adapter Passthru IORB.
  625.     **/
  626.    npCDB =    &npIORBInq->iorbh.DMWorkSpace[8];
  627.    npSGList = (NPSCATGATENTRY) &npIORBInq->iorbh.DMWorkSpace[0];
  628.    npInqBuf = (NPSCSI_INQDATA) (((NPBYTE) npIORBInq)
  629.                                          + sizeof(IORB_ADAPTER_PASSTHRU));
  630.  
  631.    /**
  632.     ** Setup the generic IORB fields
  633.     **/
  634.    npIORBInq->iorbh.Length          = sizeof(IORB_ADAPTER_PASSTHRU);
  635.    npIORBInq->iorbh.UnitHandle      = npATE->UnitHandle;
  636.    npIORBInq->iorbh.CommandCode     = IOCC_ADAPTER_PASSTHRU;
  637.    npIORBInq->iorbh.CommandModifier = IOCM_EXECUTE_CDB;
  638.    npIORBInq->iorbh.RequestControl  = IORB_ASYNC_POST;
  639.    npIORBInq->iorbh.Status          = 0;
  640.    npIORBInq->iorbh.ErrorCode       = 0;
  641.    npIORBInq->iorbh.NotifyAddress   = &InitPost;
  642.  
  643.    /**
  644.     ** Setup the Adapter Passthru IORB specific fields
  645.     **/
  646.    npIORBInq->cSGList               = 1;
  647.    npIORBInq->pSGList               = npSGList;
  648.    npIORBInq->ppSGLIST              = ppDataSeg + (USHORT) npSGList;
  649.    npIORBInq->ControllerCmdLen      = 6;
  650.    npIORBInq->pControllerCmd        = npCDB;
  651.    npIORBInq->Flags                 = PT_DIRECTION_IN;
  652.  
  653.    /**
  654.     ** Build the Inquiry CDB in the IORB DMWorkSpace
  655.     **/
  656.    npCDB[0] = 0x12;
  657.    npCDB[1] = npATE->DeviceTargetLUN << 4;
  658.    npCDB[4] = sizeof(SCSI_INQDATA);
  659.  
  660.    /**
  661.     ** Build the single entry SGList in the IORB DMWorkSpace
  662.     **/
  663.    npSGList->ppXferBuf  = ppDataSeg + (USHORT) npInqBuf;
  664.    npSGList->XferBufLen = sizeof(SCSI_INQDATA);
  665.  
  666.  
  667.    rc = SendIORBandWait((NPIORB) npIORBInq,
  668.                                  npATE->TargetADD_Entry);
  669.  
  670.    /* If the unit was unallocated, release it before returning */
  671.  
  672.    if (!AllocStatus)
  673.       {
  674.       npIORBUnitControl->iorbh.UnitHandle      = npATE->UnitHandle;
  675.       npIORBUnitControl->iorbh.CommandModifier = IOCM_DEALLOCATE_UNIT;
  676.       npIORBUnitControl->iorbh.RequestControl  = IORB_ASYNC_POST;
  677.       npIORBUnitControl->iorbh.Status          = 0;
  678.       npIORBUnitControl->iorbh.ErrorCode       = 0;
  679.       npIORBUnitControl->Flags                 = 0;
  680.       npIORBUnitControl->iorbh.NotifyAddress   = &InitPost;
  681.       SendIORBandWait((NPIORB) npIORBUnitControl,
  682.                                npATE->TargetADD_Entry);
  683.       }
  684.  
  685.    return( (rc) ? 0 : npInqBuf );
  686.    }
  687.  
  688.  
  689. /*********************************************************
  690. *                                                        *
  691. *   Procedure Name : InitAllocate                        *
  692. *                                                        *
  693. *   Description : This procedure releases some of the    *
  694. *   memory available for building data structures.       *
  695. *                                                        *
  696. *   Input :                                              *
  697. *         Size - The number of bytes requested           *
  698. *                                                        *
  699. *   Output :   A pointer to the memory allocated. If no  *
  700. *   memory is allocated, NULL is returned.               *
  701. *                                                        *
  702. *********************************************************/
  703. NPVOID NEAR InitAllocate( USHORT Size )
  704.  
  705.    {
  706.    NPVOID      PoolElement = 0;
  707.  
  708.    /* Is there enough memory left in the pool? */
  709.    if (ConfigPoolAvail >= Size)
  710.       {
  711.       /* Create a pointer and remove the memory from the pool */
  712.       PoolElement      = (NPVOID) npConfigPool;
  713.       ConfigPoolAvail -= Size;
  714.       npConfigPool    += Size;
  715.       }
  716.  
  717.    return(PoolElement);
  718.    }
  719.  
  720. /*********************************************************
  721. *                                                        *
  722. *   Procedure Name : InitSRBPool                         *
  723. *                                                        *
  724. *   Description : This procedure allocates memory for    *
  725. *   all the SRBs that are available to all the ATE.      *
  726. *                                                        *
  727. *   Input :                                              *
  728. *                                                        *
  729. *   Output :                                             *
  730. *                                                        *
  731. *********************************************************/
  732. VOID NEAR InitSRBPool(VOID)
  733.  
  734.    {
  735.    NPACB    currentACB;
  736.    NPATE    currentATE;
  737.    NPBYTE   npSRBLink;
  738.    USHORT   SRBPoolSize;
  739.    USHORT   numberOfSRBs = 0;
  740.    USHORT   i;
  741.  
  742.    /* Calculate the number of SRBs based on the queue count */
  743.    /* for each ATE.                                         */
  744.    currentACB = npACBAnchor;
  745.    while (currentACB)
  746.       {
  747.       currentATE = currentACB->npFirstATE;
  748.       while (currentATE)
  749.          {
  750.          if ((currentATE->QueuingCount > MAX_QUEUING_COUNT) ||
  751.              (currentATE->QueuingCount == 0))
  752.             numberOfSRBs += MAX_QUEUING_COUNT;
  753.          else
  754.             numberOfSRBs += currentATE->QueuingCount;
  755.  
  756.          currentATE = currentATE->npNextATE;
  757.          }
  758.       currentACB = currentACB->npNextACB;
  759.       }
  760.  
  761.    freeSRBSpace = (USHORT) &InitDataStart - (USHORT) npConfigPool;
  762.  
  763.    /* Make sure that the pool of SRBs is not greater than the */
  764.    /* space left in the data segment                          */
  765.    SRBPoolSize = numberOfSRBs * sizeof(SRB_LINK);
  766.    if ((ULONG) SRBPoolSize > (ULONG) freeSRBSpace)
  767.       {
  768.       numberOfSRBs = freeSRBSpace / sizeof(SRB_LINK);
  769.       SRBPoolSize = numberOfSRBs * sizeof(SRB_LINK);
  770.       }
  771.  
  772.    /* Initialize the SRB pool at the end of the ACB and ATE */
  773.    npSRBLinkFreeList = (NPSRB_LINK) npConfigPool;
  774.    npSRBLink = npConfigPool;
  775.  
  776.    for (i = 0;i < numberOfSRBs; i++)
  777.       {
  778.       /* Allocate one GDT selector for the SRB */                      /*@V58231*/
  779.       DevHelp_AllocGDTSelector((PSEL) (&((NPSRB_LINK) npSRBLink)->SRBGDTSelector), /*@V58231*/
  780.                                1);                                     /*@V58231*/
  781.                                                                        /*@V58231*/
  782.       /* Allocate one GDT selector for the SRB's scatter/gather list*/ /*@V58231*/
  783.       DevHelp_AllocGDTSelector((PSEL) (&((NPSRB_LINK) npSRBLink)->SGGDTSelector),  /*@V58231*/
  784.                                1);                                     /*@V58231*/
  785.  
  786.       ((NPSRB_LINK) npSRBLink)->npNextSRBLink = (NPSRB_LINK) (npSRBLink + sizeof(SRB_LINK));
  787.       npSRBLink += sizeof(SRB_LINK);
  788.       }
  789.  
  790.    ((PSRB_LINK) (npSRBLink - sizeof(SRB_LINK)))->npNextSRBLink = 0;
  791.  
  792.    /* Update the pointer to the end of valid data */
  793.  
  794.    npConfigPool += SRBPoolSize;
  795.    }
  796.  
  797. /*********************************************************
  798. *                                                        *
  799. *   Procedure Name : ParseCmdLine                        *
  800. *                                                        *
  801. *   Description : This procedure parses all command line *
  802. *   parameters that were specified.                      *
  803. *                                                        *
  804. *   Input :                                              *
  805. *         pADDParms - A pointer to the command line      *
  806. *                                                        *
  807. *   Output : This procedure returns 0 if it is successful*
  808. *   and a positive integer if an error is detected.      *
  809. *                                                        *
  810. *********************************************************/
  811. USHORT ParseCmdLine(PDDD_PARM_LIST pADDParms)
  812.    {
  813.    CC            cc;
  814.    PSZ           pOutBuf;
  815.  
  816.  
  817.    USHORT        rc = 0;
  818.    USHORT        Length;
  819.  
  820.    pOutBuf = poutbuf;
  821.  
  822.    cc = Command_Parser((PSZ) pADDParms,
  823.                        (POPTIONTABLE) &opttable,
  824.                        (PBYTE) pOutBuf,
  825.                        (USHORT) outbuf_len);
  826.  
  827.    if (cc.ret_code == NO_ERR)
  828.       {
  829.       while (!rc && pOutBuf[1] != (UCHAR) TOK_ID_END)
  830.          {
  831.          Length = pOutBuf[0];
  832.  
  833.          switch (pOutBuf[1])
  834.             {
  835.             case TOK_ID_ALL:
  836.                allocationOverride = TRUE;
  837.                break;
  838.  
  839.             case TOK_ID_SHARE:
  840.                shareTargets = TRUE;
  841.                break;
  842.  
  843.             default:
  844.  
  845.                rc = 1;
  846.                break;
  847.             }
  848.  
  849.          if (!rc)
  850.             pOutBuf += Length;
  851.  
  852.          }
  853.       }
  854.    else
  855.       if (cc.ret_code != NO_OPTIONS_FND_ERR)
  856.          rc = 1;
  857.  
  858.    return(rc);
  859.    }
  860.  
  861.  
  862. /*********************************************************
  863. *                                                        *
  864. *   Procedure Name : TTYWrite                            *
  865. *                                                        *
  866. *   Description : This procedure writes a message to the *
  867. *   screen. Since the driver runs at ring 0 this must    *
  868. *   be deferred until later and handled by the kernel.   *
  869. *                                                        *
  870. *   Input :                                              *
  871. *         Buf - A pointer to the message to be displayed *
  872. *                                                        *
  873. *   Output : None                                        *
  874. *                                                        *
  875. *********************************************************/
  876. VOID TTYWrite(PSZ Buf)
  877.    {
  878.    InitMsg.MsgStrings[0] = Buf;
  879.  
  880.    DevHelp_Save_Message((NPBYTE) &InitMsg);
  881.    }
  882.  
  883.  
  884.                                                                      /*@V64399*/
  885. VOID FAR _loadds InitPost(PIORB pIORB)                               /*@V64399*/
  886. {                                                                    /*@V64399*/
  887.   USHORT    AwakeCount;
  888.  
  889.   DevHelp_ProcRun( (ULONG) OFFSETOF(pIORB), &AwakeCount );           /*@V64399*/
  890. }                                                                    /*@V64399*/
  891.