home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ddkx86v5.zip / DDKX86 / SRC / DEV / DASD / CDROM / ATAPI / ATAPINIT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-14  |  46.5 KB  |  1,515 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. /**************************************************************************
  13.  *
  14.  * SOURCE FILE NAME = ATAPINIT.C
  15.  *
  16.  * DESCRIPTION : ATAPI driver initialization
  17.  *
  18.  *
  19.  *
  20.  * VERSION = 1.0
  21.  *
  22.  * DATE
  23.  *
  24.  * DESCRIPTION :
  25.  *
  26.  * Purpose:
  27.  *
  28.  *
  29. */
  30.  
  31. #define INCL_NOBASEAPI
  32. #define INCL_NOPMAPI
  33. #define INCL_DOSERRORS
  34. #include "os2.h"
  35. #include "dos.h"
  36. #include "bseerr.h"
  37. #include "devclass.h"
  38. #include "dskinit.h"
  39.  
  40. #include "iorb.h"
  41. #include "addcalls.h"
  42. #include "dhcalls.h"
  43.  
  44. #define INCL_INITRP_ONLY
  45. #include "reqpkt.h"
  46.  
  47. #include "scsi.h"
  48. #include "cdbscsi.h"
  49.  
  50. #include "atapicon.h"
  51. #include "atapireg.h"
  52. #include "atapityp.h"
  53. #include "atapiext.h"
  54. #include "atapipro.h"
  55. #include "rmcalls.h"
  56.  
  57. static strnswap( PSZ d, PSZ s, USHORT n );
  58.  
  59. /*
  60. ╔══════════════════════════════════╗
  61. ║                                  ║
  62. ║                                  ║
  63. ║                                  ║
  64. ║                                  ║
  65. ║                                  ║
  66. ╚══════════════════════════════════╝
  67. */
  68. VOID FAR DriverInit( PRPINITIN  pRPH )
  69. {
  70.    PRPINITIN                     pRPI = (PRPINITIN)  pRPH;
  71.    PRPINITOUT                    pRPO = (PRPINITOUT) pRPH;
  72.    NPATBL                        npAT = AdapterTable;
  73.    NPACB                         npACB;
  74.    PDDD_PARM_LIST                pDDD_Parm_List;
  75.    PMACHINE_CONFIG_INFO          pMCHI;
  76.    USHORT                        iAdpt;
  77.    USHORT                        iUnit;
  78.    USHORT                        rc      = 0;
  79.    PBYTE                         pTimerPool;
  80.    struct DevClassTableStruc far *pDriverTable;
  81.  
  82.    /*┌──────────────────────────────────────────────────────┐
  83.      │Setup DevHelp service entry point for DHCALLS library │
  84.      └──────────────────────────────────────────────────────┘ */
  85.    Device_Help = pRPH->DevHlpEP;
  86.  
  87.    //┌────────────────────────────────────────┐
  88.    //│Put name from Config.sys in DrvrName of │
  89.    //│the DriverStruct structure.             │
  90.    //└────────────────────────────────────────┘
  91.  
  92.    RMGetDriverName (pRPI, DriverStruct.DrvrName, DrvrNameSize);
  93.  
  94.    /*┌────────────────────────────────────┐
  95.      │Point to intialization vector table │
  96.      │see h\dskinit.h for details         │
  97.      └────────────────────────────────────┘ */
  98.    pDDD_Parm_List = (PDDD_PARM_LIST) pRPI->InitArgs;
  99.  
  100.    /*┌──────────────────────────────────────────────┐
  101.      │Transfer information from Machine Info Packet │
  102.      └──────────────────────────────────────────────┘ */
  103.    pMCHI = MAKEP( SELECTOROF(pDDD_Parm_List),
  104.                                 (USHORT) pDDD_Parm_List->machine_config_table );
  105.  
  106.  
  107.    MachineID = (pMCHI->Model << 8) | pMCHI->SubModel;
  108.  
  109.    /*┌───────────────────────────────────────────┐
  110.      │Check the paramters on the config.sys line │
  111.      └───────────────────────────────────────────┘ */
  112.    if ( ParseCmdLine( pDDD_Parm_List ) )
  113.    {
  114.       TTYWrite( ParmErrMsg );
  115.    }
  116.  
  117.    pTimerPool = (PBYTE) InitAllocate( TIMER_POOL_SIZE );
  118.  
  119.    ADD_InitTimer( pTimerPool, TIMER_POOL_SIZE );
  120.  
  121.    SetupADDVars();
  122.  
  123.    /* ┌────────────────────────────────────────────┐
  124.       │ Find ATAPI Units that have been identified │
  125.       │ and claim them.                            │
  126.       └────────────────────────────────────────────┘ */
  127.  
  128.    GetATAPIUnits();
  129.  
  130.    if ( Installed )
  131.    {
  132.       if ( Verbose )
  133.       {
  134.          PrintInfo( AdapterTable );
  135.       }
  136.       pRPO->CodeEnd    = (USHORT) &DriverInit;
  137.       pRPO->DataEnd    = (USHORT) &BeginInitData;
  138.       pRPO->rph.Status = STDON;
  139.  
  140.       /*---------------------------------------------------------------*/
  141.       /* For the debug version do not release any of the data segment. */
  142.       /* The debug messages are at the end of it!!                        */
  143.       /*---------------------------------------------------------------*/
  144.  
  145.       #ifdef DEBUG
  146.          pData = (PBYTE)&DiskDDHeader;
  147.          DevHelp_GetDescInfo(SELECTOROF(pData),(PBYTE)&selinfo);
  148.          pRPO->DataEnd  = (USHORT)(selinfo.t3-1);
  149.       #endif
  150.  
  151.    }
  152.    else
  153.    {
  154.  
  155.       ADD_DeInstallTimer();
  156.  
  157.       npAT = AdapterTable;
  158.  
  159.       for (iAdpt = 0; iAdpt < MAX_ADAPTERS; iAdpt++, npAT++ )
  160.          if (npAT->Flags & ATBF_IRQINSTALLED)
  161.          {
  162.             DevHelp_UnSetIRQ ( npAT->IRQLevel );
  163.          }
  164.  
  165.       if ( Verbose )
  166.       {
  167.          TTYWrite( UninstallMsg );
  168.       }
  169.  
  170.  
  171.       pRPO->CodeEnd    = 0;
  172.       pRPO->DataEnd    = 0;
  173.       pRPO->rph.Status = STDON + STERR + ERROR_I24_QUIET_INIT_FAIL;
  174.  
  175.    }
  176.  
  177.    InitComplete = TRUE;
  178. }
  179.  
  180. /*
  181. ╔══════════════════════════════════╗
  182. ║                                  ║
  183. ║                                  ║
  184. ║                                  ║
  185. ║                                  ║
  186. ║                                  ║
  187. ╚══════════════════════════════════╝
  188. */
  189. VOID NEAR SetupADDVars()
  190. {
  191.    SELDESCINFO         SwapCodeDesc;
  192.  
  193.  
  194.    /*┌───────────────────────────────┐
  195.      │Linear Address of data segment │
  196.      └───────────────────────────────┘ */
  197.    (PBYTE) plDataSeg = (PBYTE) &plDataSeg;
  198.    if ( DevHelp_VirtToLin( (SEL)   SELECTOROF(plDataSeg),
  199.                            (ULONG) 0,
  200.                            (PLIN)  &plDataSeg            ) )
  201.    {
  202.       _asm { int 3 }
  203.    }
  204.  
  205.    plADDLockHandle = plDataSeg + (USHORT) &ADDLockHandle[0];
  206.  
  207.    /*┌───────────────────────────────────────┐
  208.      │Linear Address of swap code and length │
  209.      └───────────────────────────────────────┘ */
  210.    (PBYTE) plSwapCode = (PBYTE) &StartOSM;
  211.    if ( DevHelp_GetDescInfo( (SEL)   SELECTOROF (plSwapCode),
  212.                              (PBYTE) &SwapCodeDesc           ) )
  213.    {
  214.       _asm { int 3 }
  215.    }
  216.  
  217.    plSwapCode  = SwapCodeDesc.BaseAddr;
  218.    SwapCodeLen = SwapCodeDesc.Limit + 1;
  219.  
  220.    /*┌──────────────────────────────────────────┐
  221.      │Point to KERNEL Interrupt level indicator │
  222.      └──────────────────────────────────────────┘ */
  223.    if ( DevHelp_GetDOSVar( (USHORT) DHGETDOSV_INTERRUPTLEV,
  224.                            (USHORT) 0,
  225.                            (PPVOID) &pNestedIntCount             ) )
  226.    {
  227.       _asm { int 3 }
  228.    }
  229.    DevHelp_VirtToPhys( (PVOID) SenseDataBuf, (PULONG) &ppSenseDataBuf );
  230. }
  231.  
  232. /*
  233. ╔══════════════════════════════════╗
  234. ║                                  ║
  235. ║                                  ║
  236. ║                                  ║
  237. ║                                  ║
  238. ║                                  ║
  239. ╚══════════════════════════════════╝
  240. */
  241. NPBYTE FAR InitAllocate( USHORT Size )
  242. {
  243.    NPBYTE            p = (NPBYTE) -1;
  244.  
  245.    if ( Size < ACBPoolAvail )
  246.    {
  247.       p = (NPBYTE) npACBPool;
  248.  
  249.       setmem((PBYTE) npACBPool, 0, Size );
  250.  
  251.       npACBPool    += Size;
  252.       ACBPoolAvail -= Size;
  253.    }
  254.    return( p );
  255. }
  256.  
  257. /*
  258. ╔══════════════════════════════════╗
  259. ║                                  ║
  260. ║                                  ║
  261. ║                                  ║
  262. ║                                  ║
  263. ║                                  ║
  264. ╚══════════════════════════════════╝
  265. */
  266. VOID FAR InitDeAllocate( USHORT Size )
  267. {
  268.    npACBPool    -= Size;
  269.    ACBPoolAvail += Size;
  270. }
  271.  
  272. /*
  273. ╔══════════════════════════════════╗
  274. ║                                  ║
  275. ║                                  ║
  276. ║                                  ║
  277. ║                                  ║
  278. ║                                  ║
  279. ╚══════════════════════════════════╝
  280. */
  281. VOID NEAR PrintInfo( NPATBL npAT )
  282. {
  283.    NPACB   npACB;
  284.    NPUCB   npUCB;
  285.    NPUTBL  npUT;
  286.    USHORT  i, j, k, l;
  287.  
  288.    TTYWrite( VersionMsg );
  289.    for ( j = 0; j < MAX_ADAPTERS ; j++, npAT++ )
  290.    {
  291.       if ( !(npAT->Flags & ATBF_DISABLED) )
  292.       {
  293.          sprintf( (PUCHAR) StringBuffer,
  294.                   (PUCHAR) "Controller: %1d  Base Port: %4x  "
  295.                            "IRQ: %2x; Status = %s",
  296.                   (USHORT) j,
  297.                   (USHORT) npAT->BasePort,
  298.                   (USHORT) npAT->IRQLevel,
  299.                   (PSZ)    AdptMsgs[npAT->Status] );
  300.  
  301.          TTYWrite ( StringBuffer );
  302.  
  303.          if ( npACB = npAT->npACB )
  304.          {
  305.             for (i = 0; i < MAX_UNITS; i++ )
  306.             {
  307.                npUT = &npAT->Unit[i];
  308.                npUCB = &npACB->UnitCB[i];
  309.  
  310.                if ( npUT->Status==UTS_OK )
  311.                {
  312.                   sprintf( (PUCHAR) StringBuffer,
  313.                            (PUCHAR) "Unit %1d - Status = %s",
  314.                            (USHORT) i,
  315.                            (PSZ)    UnitMsgs[npUT->Status] );
  316.  
  317.                   TTYWrite ( StringBuffer );
  318.  
  319.                   sprintf( (PUCHAR) StringBuffer,
  320.                            (PUCHAR) "Model Number     : %s",
  321.                            (PSZ)     npUT->ModelNum);
  322.                   TTYWrite ( StringBuffer );
  323.  
  324.                   sprintf( (PUCHAR) StringBuffer,
  325.                            (PUCHAR) "Firmware Revision: %s",
  326.                            (PSZ)     npUT->Firmware);
  327.                   TTYWrite ( StringBuffer );
  328.  
  329.                   sprintf( (PUCHAR) StringBuffer,
  330.                            (PUCHAR) "Serial Number    : %s",
  331.                            (PSZ)     ((npUT->Serial[0]) ? npUT->Serial : "<None>" ));
  332.                   TTYWrite ( StringBuffer );
  333.  
  334.                   sprintf( StringBuffer, " " );
  335.                   TTYWrite( StringBuffer );
  336.                }
  337.             }
  338.          }
  339.       }
  340.    }
  341. }
  342.  
  343. /*
  344. ╔══════════════════════════════════╗
  345. ║                                  ║
  346. ║                                  ║
  347. ║                                  ║
  348. ║                                  ║
  349. ║                                  ║
  350. ╚══════════════════════════════════╝
  351. */
  352. VOID NEAR TTYWrite( PSZ Buf )
  353. {
  354.    InitMsg.MsgStrings[0] = Buf;
  355.  
  356.    DevHelp_Save_Message( (NPBYTE) &InitMsg );
  357. }
  358.  
  359. /*
  360. ╔══════════════════════════════════╗
  361. ║                                  ║
  362. ║                                  ║
  363. ║                                  ║
  364. ║                                  ║
  365. ║                                  ║
  366. ╚══════════════════════════════════╝
  367. */
  368. VOID NEAR GetATAPIUnits()
  369. {
  370.    NPATBL                npAT = AdapterTable;
  371.    NPUTBL                npUT;
  372.    NPIORB_CONFIGURATION  pIORB;
  373.    DEVICETABLE           *pDeviceTable;
  374.    NPADAPTERINFO         pAdapterInfo;
  375.    UNITINFO              OldUnitInfo;
  376.    NPACB                 npACB = 0;
  377.    NPUCB                 npUCB;
  378.    PRESOURCE_ENTRY       pRE;
  379.  
  380.    struct DevClassTableStruc far *pDriverTable;
  381.  
  382.    USHORT                rc, i, j, k;
  383.    USHORT                n = 0;
  384.  
  385.    USHORT                UnitFlags;
  386.    USHORT                UnitType;
  387.    USHORT                UnitHandle;
  388.    USHORT                DriveCount = 0;
  389.  
  390.    HANDLELIST            HandleList;
  391.    PSZ                   SearchKey = SearchKeytxt;
  392.    HADAPTER              hAdapter;
  393.    HDRIVER               hDevice;
  394.  
  395.    VOID                  (FAR * DriverEP) ();
  396.  
  397.    if ( rc = DevHelp_GetDOSVar((USHORT) DHGETDOSV_DEVICECLASSTABLE, 1,
  398.                                (PPVOID) &pDriverTable) )
  399.    {
  400.       _asm { int 3 }
  401.    }
  402.  
  403.    pDeviceTable = (DEVICETABLE *) ScratchBuf1;
  404.  
  405.    for (i = 0; i < pDriverTable->DCCount; i++)
  406.    {
  407.       pIORB = (NPIORB_CONFIGURATION) &InitIORB;
  408.       pIORB->iorbh.Length = sizeof(IORB_CONFIGURATION);
  409.       pIORB->iorbh.CommandCode = IOCC_CONFIGURATION;
  410.       pIORB->iorbh.CommandModifier = IOCM_GET_DEVICE_TABLE;
  411.       pIORB->iorbh.Status = 0;
  412.       pIORB->iorbh.RequestControl = 0;
  413.       pIORB->iorbh.NotifyAddress = 0;
  414.       pIORB->pDeviceTable = (PVOID) ScratchBuf1;
  415.       pIORB->DeviceTableLen = sizeof(ScratchBuf1);
  416.  
  417.       OFFSETOF(DriverEP) =  pDriverTable->DCTableEntries[i].DCOffset;
  418.       SELECTOROF(DriverEP) = pDriverTable->DCTableEntries[i].DCSelector;
  419.  
  420.       setmem( ScratchBuf, 0, sizeof(ScratchBuf1) );
  421.  
  422.       (*DriverEP) ((PVOID)(pIORB));
  423.  
  424.       while ( !(pIORB->iorbh.Status & IORB_DONE) )  /* Wait till done */
  425.          ;
  426.  
  427.       if (pIORB->iorbh.Status & IORB_ERROR )
  428.          continue;                                  /* Skip to next device */
  429.  
  430.       for (j = 0; j < pDeviceTable->TotalAdapters; j++ )
  431.       {
  432.          pAdapterInfo =  pDeviceTable->pAdapter[j];
  433.  
  434.          for (k = 0; k < pAdapterInfo->AdapterUnits; k++)
  435.          {
  436.             UnitType  = pAdapterInfo->UnitInfo[k].UnitType;
  437.             UnitHandle = pAdapterInfo->UnitInfo[k].UnitHandle;
  438.             if ( UnitType == UIB_TYPE_ATAPI )
  439.             {
  440.                if ( !Installed )
  441.                {
  442.                   Installed = TRUE;
  443.  
  444.                   if ( DevHelp_RegisterDeviceClass( (NPSZ)    AdapterName,
  445.                                                     (PFN)     &ATAPIADDEntry,
  446.                                                     (USHORT)  0,
  447.                                                     (USHORT)  1,
  448.                                                     (PUSHORT) &ADDHandle  ) )
  449.                   {
  450.                      _asm int 3
  451.                   }
  452.  
  453.                   //┌────────────────────────┐
  454.                   //│ Allocate Driver Handle │
  455.                   //└────────────────────────┘
  456.                   if(RMCreateDriver(&DriverStruct,
  457.                                     &hDriver))
  458.                   {
  459.                      _asm int 3
  460.                   }
  461.                }
  462.                if ( !npACB ) /* First ATAPI unit */
  463.                {
  464.                   npAT->Flags &= ~ATBF_DISABLED;
  465.                   npACB = npAT->npACB = (NPACB) InitAllocate( sizeof(ACB) );
  466.                   setmem((PBYTE) npACB, 0, sizeof(ACB) );
  467.                   ACBPtrs[cAdapters].npACB = npACB;
  468.                   npACB->IRQHandler = npAT->IRQHandler;
  469.                   npACB->ReqFlags |= ACBR_CONFIGURE_ACB;
  470.  
  471.                   npACB->ResourceFlags |= ACBRF_SHARED;
  472.  
  473.                   pRE = (PRESOURCE_ENTRY) ScratchBuf;
  474.                   setmem( ScratchBuf, 0, sizeof(ScratchBuf) );
  475.  
  476.                   if ( rc = Issue_ReportResources ( pRE, UnitHandle, DriverEP ) )
  477.                   {
  478.                      npAT->Flags |= ATBF_DISABLED;
  479.                      continue; /* go to next adapter */
  480.                   }
  481.  
  482.                   /* Is there an IRQ entry? */
  483.                   /* Is there a port entry? */
  484.  
  485.                   if ( ( pRE->Max_Resource_Entry < RE_PORT ) ||
  486.                        ( !pRE->cIRQ_Entries )                ||
  487.                        ( !pRE->cPort_Entries ))
  488.                   {
  489.                      rc = 1;
  490.                      npAT->Flags |= ATBF_DISABLED;
  491.                      continue; /* go to next adapter */
  492.                   }
  493.  
  494.                   npAT->BasePort = pRE->npPort_Entry->StartPort;
  495.                   npAT->IRQLevel = pRE->npIRQ_Entry->IRQ_Value;
  496.                   npAT->cUnits++;
  497.                   npAT->Flags   |= ATBF_ATAPI_PRESENT;
  498.                   npAT->Status   = ATS_OK;
  499.  
  500.                   if ( npACB->ReqFlags & ACBR_CONFIGURE_ACB )
  501.                   {
  502.                      ConfigureACB( npAT );
  503.                   }
  504.  
  505.                   npACB->SharedDriverEP         = DriverEP;
  506.                   npACB->SharedDriverUnitHandle = UnitHandle;
  507.  
  508.                   if ( !(npACB->ResourceFlags & ACBRF_CURR_OWNER ) )
  509.                   {
  510.                      if ( rc = InitSuspendOtherAdd( npACB ))
  511.                      {
  512.                         npACB->ResourceFlags &= ~ACBRF_CURR_OWNER;
  513.                         npAT->Flags |= ATBF_DISABLED;
  514.                         continue; /* go to next adapter */
  515.                      }
  516.                      npACB->suspended = 0;
  517.                      npACB->ResourceFlags |= ACBRF_CURR_OWNER;
  518.                   }
  519.                }
  520.                else
  521.                {
  522.                   npAT->cUnits++;
  523.                }
  524.                npUT = &npAT->Unit[k];
  525.                npUCB = npACB->npUCB = &npACB->UnitCB[k];
  526.                npUCB->npACB = npACB;
  527.                npUCB->UnitId = npACB->UnitId = k;
  528.  
  529.                memcopy ( (PVOID) &OldUnitInfo,
  530.                          (PVOID) &pAdapterInfo->UnitInfo[k],
  531.                          sizeof(UNITINFO) );
  532.                if (ClaimUnit( npAT, UnitHandle, (PUNITINFO)&OldUnitInfo,
  533.                               DriverEP ))
  534.                {
  535.                   npUT->Status = UTS_NOT_PRESENT;
  536.                }
  537.                else
  538.                {
  539.                   npUT->Status = UTS_OK;
  540.  
  541.                   HandleList.cMaxHandles = 1;
  542.  
  543.                   SearchKey[4] += j;
  544.  
  545.                   //┌───────────────────────────────────────────┐
  546.                   //│ Find the IDE adapter in the resource tree │
  547.                   //│ and attach a device                       │
  548.                   //└───────────────────────────────────────────┘
  549.  
  550.                   if ( !(RMKeyToHandleList ( HANDLE_PHYS_TREE,
  551.                                            SearchKey,
  552.                                            (PHANDLELIST) &HandleList )) )
  553.                   {
  554.                      if ( HandleList.cHandles )
  555.                      {
  556.                         if ( RMCreateDevice( hDriver,
  557.                                              &hDevice,
  558.                                              &DevStruct,
  559.                                              HandleList.Handles[0],
  560.                                              NULL ))
  561.                         {
  562.                            _asm int 3
  563.                         }
  564.                      }
  565.                   }
  566.                   DevStruct.DevDescriptName[6] += n;
  567.                   n++;
  568.                }
  569.             }
  570.          }
  571.          if ( npACB )
  572.          {
  573.             npAT->Flags |= ATBF_ATAPI_PRESENT;
  574.             cAdapters++;
  575.             /* resume other add if necessary */
  576.             if ( npAT->cUnits == pAdapterInfo->AdapterUnits )
  577.             {
  578.                /* tell the state machine to do no sharing protocol */
  579.                npAT->Flags &= ~ATBF_SHARED_ADAPTER;
  580.                npACB->ResourceFlags &= ~ACBRF_SHARED;
  581.                InitSuspendOtherAdd( npACB ); /* final suspend to st506 */
  582.                npACB->ResourceFlags |= ACBRF_CURR_OWNER;
  583.                npACB->suspended = 0;
  584.             }
  585.             else
  586.             {
  587.                npAT->Flags |= ATBF_SHARED_ADAPTER;
  588.                npACB->ResourceFlags |= ACBRF_SHARED;
  589.                npACB->suspended = 1;
  590.                InitResumeOtherAdd( npACB );
  591.                npACB->ResourceFlags &= ~ACBRF_CURR_OWNER;
  592.             }
  593.  
  594.             npAT++;
  595.             npACB = 0;
  596.          }
  597.       }
  598.    }
  599. }
  600.  
  601. /*
  602. ╔══════════════════════════════════╗
  603. ║                                  ║
  604. ║                                  ║
  605. ║                                  ║
  606. ║                                  ║
  607. ║                                  ║
  608. ╚══════════════════════════════════╝
  609. */
  610. USHORT NEAR ClaimUnit( NPATBL npAT, USHORT UnitHandle,
  611.                        PUNITINFO pOldUnitInfo, VOID (FAR *DriverEP)() )
  612. {
  613.    PUNITINFO            pUI;
  614.    NPACB                npACB;
  615.  
  616.    USHORT               rc = 0;
  617.    USHORT               UnitType;
  618.  
  619.    USHORT               FeatureReg;                                /*@V98451X*/
  620.  
  621.    npACB  = npAT->npACB;
  622.  
  623.    npACB->cUnits++;
  624.  
  625.    if ( !TimersCalibrated )
  626.    {
  627.      CalibrateTimers( npAT->npACB );
  628.      TimersCalibrated = 1;
  629.    }
  630.  
  631.    /* SONY CDs come up in DMA mode sometimes.  Therefore, we must force them */
  632.    /* into non-DMA mode.                                                     */
  633.  
  634.    FeatureReg = npAT->BasePort + 1;                                /*@V98451X*/
  635.    outp( FeatureReg, 0 );                                          /*@V98451X*/
  636.  
  637.    UnitType = ATAPIIdentify( npAT );
  638.  
  639.    if ( UnitType == UIB_TYPE_CDROM )
  640.    {
  641.       pUI = (PUNITINFO) InitAllocate ( sizeof(UNITINFO) );
  642.       setmem( ScratchBuf, 0, sizeof(ScratchBuf) );
  643.       memcopy( (PVOID) pUI, (PVOID) pOldUnitInfo, sizeof(UNITINFO));
  644.  
  645.       pUI->FilterADDHandle = ADDHandle;
  646.       pUI->UnitType        = UIB_TYPE_CDROM;
  647.       pUI->UnitHandle      = (USHORT)npACB->npUCB;
  648.       pUI->UnitFlags       = UF_REMOVABLE   | UF_CHANGELINE |
  649.                              UF_NODASD_SUPT | UF_NOSCSI_SUPT;
  650.  
  651.       if ( !( rc = Issue_AllocateUnit( UnitHandle, DriverEP )) )
  652.       {
  653.          rc = Issue_ChangeUnitInfo( pUI, UnitHandle, DriverEP );
  654.          if ( Issue_DeallocateUnit( UnitHandle, DriverEP ))
  655.          {
  656.             npAT->Flags |= ATBF_DISABLED;
  657.          }
  658.       }
  659.  
  660.       if ( rc )
  661.       {
  662.          npAT->Flags |= ATBF_DISABLED;
  663.       }
  664.    }
  665.  
  666.    ClaimUnitExit:
  667.  
  668.    return( rc );
  669. }
  670.  
  671. /*
  672. ╔══════════════════════════════════╗
  673. ║                                  ║
  674. ║                                  ║
  675. ║                                  ║
  676. ║                                  ║
  677. ║                                  ║
  678. ╚══════════════════════════════════╝
  679. */
  680. USHORT NEAR Issue_ReportResources( PRESOURCE_ENTRY pRE,
  681.                               USHORT UnitHandle, VOID (FAR *DriverEP)() )
  682. {
  683.    NPIORB_RESOURCE      npIORB;
  684.  
  685.    npIORB                        = (NPIORB_RESOURCE) &InitIORB;
  686.    setmem ( (PVOID) npIORB, 0, sizeof(InitIORB) );
  687.  
  688.    npIORB->iorbh.Length          = sizeof(IORB_RESOURCE);
  689.    npIORB->iorbh.UnitHandle      = UnitHandle;
  690.    npIORB->iorbh.CommandCode     = IOCC_RESOURCE;
  691.    npIORB->iorbh.CommandModifier = IOCM_REPORT_RESOURCES;
  692.    npIORB->iorbh.Status          = 0;
  693.    npIORB->iorbh.RequestControl  = 0;
  694.    npIORB->iorbh.NotifyAddress   = 0;
  695.    npIORB->ResourceEntryLen      = sizeof(ScratchBuf);
  696.    npIORB->pResourceEntry        = pRE;
  697.  
  698.    (*DriverEP) ((PVOID)(npIORB));
  699.    while ( !(npIORB->iorbh.Status & IORB_DONE) )  /* Wait till done */
  700.       ;
  701.  
  702.    return( npIORB->iorbh.ErrorCode );
  703.  
  704. }
  705.  
  706. /*
  707. ╔══════════════════════════════════╗
  708. ║                                  ║
  709. ║                                  ║
  710. ║                                  ║
  711. ║                                  ║
  712. ║                                  ║
  713. ╚══════════════════════════════════╝
  714. */
  715. USHORT NEAR Issue_AllocateUnit( USHORT UnitHandle, VOID (FAR *DriverEP)() )
  716. {
  717.    NPIORB_UNIT_CONTROL   npIORB;
  718.    PUCHAR                pWSFlags; /* work space flags */
  719.  
  720.    npIORB                        = (NPIORB_UNIT_CONTROL) &InitIORB;
  721.    pWSFlags = (PUCHAR) npIORB->iorbh.DMWorkSpace;
  722.    setmem ( (PVOID) npIORB, 0, sizeof(InitIORB) );
  723.  
  724.    npIORB->iorbh.Length          = sizeof(IORB_UNIT_CONTROL);
  725.    npIORB->iorbh.UnitHandle      = UnitHandle;
  726.    npIORB->iorbh.CommandCode     = IOCC_UNIT_CONTROL;
  727.    npIORB->iorbh.CommandModifier = IOCM_ALLOCATE_UNIT;
  728.    npIORB->iorbh.Status          = 0;
  729.    npIORB->iorbh.RequestControl  = IORB_ASYNC_POST;
  730.    npIORB->iorbh.NotifyAddress   = NotifyInitIORBDone;
  731.  
  732.    (*DriverEP) ((PVOID)(npIORB));
  733.  
  734.    DISABLE
  735.    *pWSFlags |= WSF_PROC_BLOCK;
  736.  
  737.    while( !(npIORB->iorbh.Status & IORB_DONE) )
  738.    {
  739.       DevHelp_ProcBlock( (ULONG) npIORB, 100, WAIT_IS_INTERRUPTABLE );
  740.       DISABLE
  741.    }
  742.  
  743.    ENABLE
  744.  
  745.    return( npIORB->iorbh.ErrorCode );
  746.  
  747. }
  748.  
  749. /*
  750. ╔══════════════════════════════════╗
  751. ║                                  ║
  752. ║                                  ║
  753. ║                                  ║
  754. ║                                  ║
  755. ║                                  ║
  756. ╚══════════════════════════════════╝
  757. */
  758. USHORT NEAR Issue_DeallocateUnit( USHORT UnitHandle, VOID (FAR *DriverEP)() )
  759. {
  760.    NPIORB_UNIT_CONTROL      npIORB;
  761.  
  762.    npIORB                        = (NPIORB_UNIT_CONTROL) &InitIORB;
  763.    setmem ( (PVOID) npIORB, 0, sizeof(InitIORB) );
  764.  
  765.    npIORB->iorbh.Length          = sizeof(IORB_UNIT_CONTROL);
  766.    npIORB->iorbh.UnitHandle      = UnitHandle;
  767.    npIORB->iorbh.CommandCode     = IOCC_UNIT_CONTROL;
  768.    npIORB->iorbh.CommandModifier = IOCM_DEALLOCATE_UNIT;
  769.    npIORB->iorbh.Status          = 0;
  770.    npIORB->iorbh.RequestControl  = 0;
  771.    npIORB->iorbh.NotifyAddress   = 0;
  772.  
  773.    (*DriverEP) ((PVOID)(npIORB));
  774.    while ( !(npIORB->iorbh.Status & IORB_DONE) )  /* Wait till done */
  775.       ;
  776.  
  777.    return( npIORB->iorbh.ErrorCode );
  778.  
  779. }
  780.  
  781. /*
  782. ╔══════════════════════════════════╗
  783. ║                                  ║
  784. ║                                  ║
  785. ║                                  ║
  786. ║                                  ║
  787. ║                                  ║
  788. ╚══════════════════════════════════╝
  789. */
  790. USHORT NEAR Issue_ChangeUnitInfo( PUNITINFO pUI, USHORT UnitHandle,
  791.                                    VOID (FAR *DriverEP)() )
  792. {
  793.    NPIORB_UNIT_CONTROL  npIORB;
  794.  
  795.    npIORB                        = (NPIORB_UNIT_CONTROL) &InitIORB;
  796.    setmem ( (PVOID) npIORB, 0, sizeof(InitIORB) );
  797.  
  798.    npIORB->iorbh.Length          = sizeof(IORB_UNIT_CONTROL);
  799.    npIORB->iorbh.UnitHandle      = UnitHandle;
  800.    npIORB->iorbh.CommandCode     = IOCC_UNIT_CONTROL;
  801.    npIORB->iorbh.CommandModifier = IOCM_CHANGE_UNITINFO;
  802.    npIORB->iorbh.Status          = 0;
  803.    npIORB->iorbh.RequestControl  = 0;
  804.    npIORB->iorbh.NotifyAddress   = 0;
  805.    npIORB->UnitInfoLen           = sizeof(ScratchBuf);
  806.    npIORB->pUnitInfo             = pUI;
  807.  
  808.    (*DriverEP) ((PVOID)(npIORB));
  809.    while ( !(npIORB->iorbh.Status & IORB_DONE) )  /* Wait unil done */
  810.       ;
  811.  
  812.    return( npIORB->iorbh.ErrorCode );
  813. }
  814.  
  815. /*
  816. ╔══════════════════════════════════╗
  817. ║                                  ║
  818. ║                                  ║
  819. ║                                  ║
  820. ║                                  ║
  821. ║                                  ║
  822. ╚══════════════════════════════════╝
  823. */
  824. VOID NEAR ConfigureACB( NPATBL npAT )
  825. {
  826.    NPACB       npACB;
  827.    UCHAR       i;
  828.  
  829.    npACB = npAT->npACB;
  830.  
  831.    for (i = FI_PDATA; i < FI_PDEVCON; i++ )
  832.    {
  833.       npACB->IOPorts[i] = npAT->BasePort + i;
  834.       npACB->IORegs[i]  = 0;
  835.    }
  836.    /*┌───────────────────────────────────────────────────────────┐
  837.      │ Error Register and Feature Register have the same address │
  838.      └───────────────────────────────────────────────────────────┘*/
  839.    npACB->IOPorts[FI_PERROR]  = npACB->IOPorts[FI_PFEATURE];
  840.  
  841.    /*┌────────────────────────────────────────────────────────────┐
  842.      │ Status Register and Command Register have the same address │
  843.      └────────────────────────────────────────────────────────────┘*/
  844.    npACB->IOPorts[FI_PSTATUS] = npACB->IOPorts[FI_PCMD];
  845.  
  846.    npACB->IOPorts[FI_PDEVCON] = npACB->IOPorts[FI_PDRVSLCT] | 0x300;
  847.  
  848.    npACB->IORegs[FI_PDEVCON] = DEFAULT_ATAPI_DEVCON_REG;
  849.  
  850.    npACB->IRQLevel   = npAT->IRQLevel;
  851.    npACB->IRQHandler = npAT->IRQHandler;
  852.  
  853.    npACB->TimeOut              = INIT_TIMEOUT_SHORT;
  854.    npACB->IRQTimeOut           = INIT_TIMEOUT_LONG;
  855.    npACB->DelayedResetInterval = DELAYED_RESET_INTERVAL;
  856.  
  857.    npACB->InternalCmd.IOSGPtrs.iPortAddress =npACB->IOPorts[FI_PDATA];
  858.    npACB->ExternalCmd.IOSGPtrs.iPortAddress =npACB->IOPorts[FI_PDATA];
  859.    npACB->npCmdIO = &npACB->ExternalCmd;
  860.  
  861.    if ( DevHelp_AllocateCtxHook((NPFN) StateCtxHookRtn,
  862.                                 (PULONG) &npACB->CtxHookHandle ) )
  863.    {
  864.       _asm int 3
  865.    }
  866.  
  867.    npACB->ReqFlags &= ~ACBR_CONFIGURE_ACB;
  868.  
  869.    if ( npAT->Flags & ATBF_SHARED_ADAPTER )
  870.    {
  871.       npACB->ResourceFlags |= ACBRF_SHARED;
  872.       npACB->suspended = 1;
  873.    }
  874.    else
  875.    {
  876.       npACB->suspended = 0;
  877.    }
  878. }
  879.  
  880. /*
  881. ╔══════════════════════════════════╗
  882. ║                                  ║
  883. ║                                  ║
  884. ║                                  ║
  885. ║                                  ║
  886. ║                                  ║
  887. ╚══════════════════════════════════╝
  888. */
  889. USHORT NEAR ATAPIIdentify( NPATBL npAT )
  890. {
  891.    NPIDENTIFYDATA    npID;
  892.    NPUTBL            npUT;
  893.    NPACB             npACB = npAT->npACB;
  894.    NPUCB             npUCB;
  895.    USHORT            rc;
  896.    USHORT            UnitType = 0xff;
  897.    USHORT            Model;
  898.    USHORT            UnitId;
  899.  
  900.    npID   = (NPIDENTIFYDATA) ScratchBuf;
  901.    UnitId = npACB->npUCB->UnitId;
  902.    npUT   = &npAT->Unit[UnitId];
  903.    npUCB  = npACB->npUCB;
  904.  
  905.    npUCB->Capabilities = 0;                                          /*@V93531*/
  906.  
  907.    if ( !(rc=GetIdentifyData( npACB, UnitId, (PBYTE) npID )))
  908.    {
  909. #define  DONTCARE        0
  910. #define  NEC_CDR_260     1
  911. #define  NEC_CDR_250     2
  912. #define  MATSHITA_CR_571 3
  913.  
  914.       if (strncmp("                    MATSHITA CR-571 0.2d",
  915.                   npID->ModelNum,sizeof(npID->ModelNum)))
  916.          Model = MATSHITA_CR_571;
  917.       else if (strncmp("NEC                 CD-ROM DRIVE:260    ",
  918.                   npID->ModelNum,sizeof(npID->ModelNum)))
  919.       {
  920.          Model = NEC_CDR_260;
  921.          strncpy( npUT->Firmware, npID->Firmware, sizeof(npID->Firmware));
  922.          if(strncmp("1.01    ",npID->Firmware, sizeof(npID->Firmware)))
  923.          {
  924.             npUCB->Capabilities |= UCBC_SPEC_REV_17B;
  925.             npUCB->Capabilities |= UCBC_IRQ_ON_ATA_COMPLETE;
  926.             npACB->IRQTimeOut   *= 4;
  927.          }
  928.       }
  929.       else if (strncmp("EN C                DCR-MOD IREV2:06    ",
  930.                   npID->ModelNum,sizeof(npID->ModelNum)))
  931.       {
  932.          Model = NEC_CDR_250;
  933.       }
  934.       else
  935.          Model = DONTCARE;
  936.  
  937.       /*
  938.       ┌────────────────────────────────────────┐
  939.       │ Save Model/Serial/Firmware Information │
  940.       └────────────────────────────────────────┘
  941.       */
  942.       if ( (Model == NEC_CDR_260 ) &&
  943.            ( npUCB->Capabilities & UCBC_SPEC_REV_17B) )
  944.       {
  945.          strncpy( npUT->ModelNum, npID->ModelNum, sizeof(npID->ModelNum));
  946.          strncpy( npUT->Serial,   npID->Serial,   sizeof(npID->Serial));
  947.       }
  948.       else
  949.       {
  950.          strnswap( npUT->ModelNum, npID->ModelNum, sizeof(npID->ModelNum)-2);
  951.          strnswap( npUT->Serial,   npID->Serial,   sizeof(npID->Serial)-2);
  952.          strnswap( npUT->Firmware, npID->Firmware, sizeof(npID->Firmware)-2);
  953.       }
  954.  
  955.       if(strncmp( npUT->Serial, (PSZ) "                    ",
  956.                                 sizeof(npID->Serial)))
  957.          npUT->Serial[0] = 0;
  958.  
  959.       switch (npID->GenConfig.CmdPktSize)
  960.       {
  961.          case 0 : npUCB->CmdPacketLength = 12;
  962.                   break;
  963.  
  964.          case 1 : npUCB->CmdPacketLength = 16;
  965.                   break;
  966.  
  967.          default: npUCB->CmdPacketLength = 00;
  968.                   rc = 1;
  969.       }
  970.  
  971.       switch (npID->GenConfig.CmdDRQType)
  972.       {
  973.          case 0 : npUCB->Capabilities |= UCBC_MICROPROCESSOR_DRQ;
  974.                   break;
  975.  
  976.          case 1 : npUCB->Capabilities |= UCBC_INTERRUPT_DRQ;
  977.                   break;
  978.  
  979.          case 2 : npUCB->Capabilities |= UCBC_ACCELERATED_DRQ;
  980.                   break;
  981.  
  982.          default: npUCB->Capabilities |= UCBC_MICROPROCESSOR_DRQ;
  983.                   rc = 1;
  984.       }
  985.  
  986.       switch (npID->GenConfig.ProtocolType)
  987.       {
  988.          case 0 :
  989.          case 1 : npUCB->Capabilities |= UCBC_ATA;
  990.                   break;
  991.  
  992.          case 2 :
  993.          case 3 : npUCB->Capabilities |= UCBC_ATAPI;
  994.                   break;
  995.  
  996.          default: npUCB->Capabilities |= UCBC_ATA;
  997.                   rc = 1;
  998.       }
  999.  
  1000.       switch ( UnitType = npID->GenConfig.DeviceType )
  1001.       {
  1002.          case UIB_TYPE_DISK :
  1003.                   npUCB->Capabilities |= UCBC_DIRECT_ACCESS_DEVICE;
  1004.                   break;
  1005.  
  1006.          case UIB_TYPE_CDROM :
  1007.                   npUCB->Capabilities |= UCBC_CDROM_DEVICE;
  1008.                   break;
  1009.  
  1010.          case UIB_TYPE_OPTICAL_MEMORY :
  1011.                   npUCB->Capabilities |= UCBC_OPTICAL_MEMORY_DEVICE;
  1012.                   break;
  1013.  
  1014.          default: npUCB->Capabilities &= ~(UCBC_DIRECT_ACCESS_DEVICE |
  1015.                                           UCBC_CDROM_DEVICE |
  1016.                                           UCBC_OPTICAL_MEMORY_DEVICE);
  1017.                   rc = 1;
  1018.       }
  1019.  
  1020.       if ( npID->Capabilities & IDD_DMASupported )
  1021.          npUCB->Capabilities |= UCBC_DMA;
  1022.       else
  1023.          npUCB->Capabilities &= ~UCBC_DMA;
  1024.  
  1025.       if ( npID->Capabilities & IDD_LBASupported )
  1026.          npUCB->Capabilities |= UCBC_LBA;
  1027.       else
  1028.          npUCB->Capabilities &= ~UCBC_LBA;
  1029.  
  1030.       if ( npID->Capabilities & IDD_IORDYSupported )
  1031.          npUCB->Capabilities |= UCBC_IORDY;
  1032.       else
  1033.          npUCB->Capabilities &= ~UCBC_IORDY;
  1034.  
  1035.       if ( npID->Capabilities & IDD_IORDYDisablable )
  1036.          npUCB->Capabilities |= UCBC_IORDY_DISABLE;
  1037.       else
  1038.          npUCB->Capabilities &= ~UCBC_IORDY_DISABLE;
  1039.  
  1040.       switch ( Model )
  1041.       {
  1042.          case NEC_CDR_260 :
  1043.          case NEC_CDR_250 :
  1044.             UnitType = 5;
  1045.             npUCB->CmdPacketLength = 12;
  1046.             npUCB->Capabilities |= UCBC_MICROPROCESSOR_DRQ |
  1047.                                    UCBC_ATAPI              |
  1048.                                    UCBC_CDROM_DEVICE;
  1049.             rc = 0;
  1050.             break;
  1051.  
  1052.          case MATSHITA_CR_571 :
  1053.             npUCB->Capabilities &= ~UCBC_SPEC_REV_17B;
  1054.             npUCB->Capabilities |= UCBC_IRQ_ON_ATA_COMPLETE;
  1055.             break;
  1056.  
  1057.          default:
  1058.             npUCB->Capabilities &= ~UCBC_SPEC_REV_17B;
  1059.             npUCB->Capabilities &= ~UCBC_IRQ_ON_ATA_COMPLETE;
  1060.       }
  1061.    }
  1062.  
  1063.    if ( rc )
  1064.    {
  1065.       return( -1 );
  1066.    }
  1067.  
  1068.    return( UnitType );
  1069. }
  1070.  
  1071. /*
  1072. ╔══════════════════════════════════╗
  1073. ║                                  ║
  1074. ║                                  ║
  1075. ║                                  ║
  1076. ║                                  ║
  1077. ║                                  ║
  1078. ╚══════════════════════════════════╝
  1079. */
  1080. USHORT GetIdentifyData( NPACB npACB, USHORT UnitId, PBYTE pID )
  1081. {
  1082.    NPIORB_ADAPTER_PASSTHRU  npIORB    = &InitIORB;
  1083.    NPUCB                    npUCB     = &npACB->UnitCB[UnitId];
  1084.    USHORT                   ErrorCode = 0;
  1085.    PUCHAR                pWSFlags; /* work space flags */
  1086.  
  1087.    if ( npACB->UnitCB[0].Flags & UCBF_IDENTIFYFAIL )
  1088.    {
  1089.       npUCB->Flags |= UCBF_IDENTIFYFAIL;
  1090.       ErrorCode     = IOERR_DEVICE_REQ_NOT_SUPPORTED;
  1091.    }
  1092.    else
  1093.    {
  1094.       npUCB->ReqFlags |= UCBR_IDENTIFY;
  1095.  
  1096.       if ( DevHelp_VirtToPhys( (PVOID) pID,
  1097.                                (PULONG) &IdentifySGList.ppXferBuf ) )
  1098.       {
  1099.          _asm { int 3 }
  1100.       }
  1101.  
  1102.       pWSFlags = (PUCHAR) npIORB->iorbh.DMWorkSpace;
  1103.       setmem( (PBYTE) npIORB, 0, sizeof(IORB_ADAPTER_PASSTHRU) );
  1104.  
  1105.       npIORB->iorbh.Length          = sizeof(IORB_ADAPTER_PASSTHRU);
  1106.       npIORB->iorbh.UnitHandle      = (USHORT) &npACB->UnitCB[UnitId];
  1107.       npIORB->iorbh.CommandCode     = IOCC_ADAPTER_PASSTHRU;
  1108.       npIORB->iorbh.CommandModifier = IOCM_EXECUTE_ATA;
  1109.       npIORB->iorbh.RequestControl  = IORB_ASYNC_POST;
  1110.       npIORB->iorbh.NotifyAddress   = NotifyInitIORBDone;
  1111.       npIORB->cSGList               = 1;
  1112.       npIORB->pSGList               = &IdentifySGList;
  1113.  
  1114.       ATAPIADDEntry( (PIORB) npIORB);
  1115.  
  1116.       DISABLE
  1117.       *pWSFlags |= WSF_PROC_BLOCK;
  1118.  
  1119.       while( !(npIORB->iorbh.Status & IORB_DONE) )
  1120.       {
  1121.          DevHelp_ProcBlock( (ULONG)(PIORB) npIORB, -1, WAIT_IS_NOT_INTERRUPTABLE );
  1122.          DISABLE
  1123.       }
  1124.  
  1125.       npUCB->ReqFlags &= ~UCBR_IDENTIFY;
  1126.  
  1127.       ENABLE
  1128.    }
  1129.  
  1130.    return( (npIORB->iorbh.Status & IORB_ERROR) ? npIORB->iorbh.ErrorCode : 0 );
  1131.  
  1132. }
  1133.  
  1134. /*
  1135. ╔══════════════════════════════════╗
  1136. ║                                  ║
  1137. ║                                  ║
  1138. ║                                  ║
  1139. ║                                  ║
  1140. ║                                  ║
  1141. ╚══════════════════════════════════╝
  1142. */
  1143. USHORT FAR CheckReady( NPACB npACB )
  1144. {
  1145.    ULONG WaitCount;
  1146.    USHORT Status;
  1147.  
  1148.    npACB->TimerFlags &= ~ACBT_BUSY;
  1149.  
  1150.    WaitCount = CheckReadyCount;
  1151.  
  1152.    while( WaitCount-- )
  1153.    {
  1154.       Status = GetRegister( npACB, FI_PSTATUS );
  1155.  
  1156.       if ( !(Status & FX_BUSY) && (Status & FX_READY) )
  1157.       {
  1158.          if ( !Calibrate )
  1159.             break;
  1160.       }
  1161.    }
  1162.  
  1163.    if ( Status & FX_BUSY )
  1164.    {
  1165.       npACB->TimerFlags |= ACBT_BUSY;
  1166.    }
  1167.  
  1168.    npACB->IORegs[FI_PSTATUS] = Status;
  1169.  
  1170.    return( ((npACB->TimerFlags & ACBT_BUSY) || !(Status & FX_READY)) ? 1 : 0);
  1171. }
  1172.  
  1173. /*
  1174. ╔══════════════════════════════════╗
  1175. ║                                  ║
  1176. ║                                  ║
  1177. ║                                  ║
  1178. ║                                  ║
  1179. ║                                  ║
  1180. ╚══════════════════════════════════╝
  1181. */
  1182. USHORT NEAR InitSuspendOtherAdd( NPACB npACB )
  1183. {
  1184.    PIORB_DEVICE_CONTROL  pIORB;
  1185.    PUCHAR                pWSFlags; /* work space flags */
  1186.  
  1187.    DISABLE
  1188.    if ( npACB->iorbinuse )
  1189.    {
  1190.       _asm int 3
  1191.    }
  1192.    npACB->iorbinuse = 1;
  1193.    ENABLE
  1194.  
  1195.    pIORB = (PIORB_DEVICE_CONTROL) &npACB->IORB;
  1196.    pWSFlags = pIORB->iorbh.DMWorkSpace;
  1197.    setmem( (PVOID) pIORB, 0, sizeof(npACB->IORB));
  1198.  
  1199.    pIORB->iorbh.Length          = sizeof(IORB_DEVICE_CONTROL);
  1200.    pIORB->iorbh.UnitHandle      = npACB->SharedDriverUnitHandle;
  1201.    pIORB->iorbh.CommandCode     = IOCC_DEVICE_CONTROL;
  1202.    pIORB->iorbh.CommandModifier = IOCM_SUSPEND;
  1203.    pIORB->iorbh.RequestControl  = IORB_ASYNC_POST;
  1204.    pIORB->iorbh.NotifyAddress   = NotifyInitIORBDone;
  1205.    pIORB->IRQHandlerAddress     = npACB->IRQHandler;                /*@V93531*/
  1206.    pIORB->Flags                 = DC_SUSPEND_IMMEDIATE              /*@V93531*/
  1207.                                   | DC_SUSPEND_IRQADDR_VALID;       /*@V93531*/
  1208.  
  1209.    (*npACB->SharedDriverEP) ((PVOID)(pIORB));
  1210.  
  1211.    DISABLE
  1212.    *pWSFlags |= WSF_PROC_BLOCK;
  1213.  
  1214.    while( !(pIORB->iorbh.Status & IORB_DONE) )
  1215.    {
  1216.       DevHelp_ProcBlock( (ULONG) pIORB, -1, WAIT_IS_NOT_INTERRUPTABLE );
  1217.       DISABLE
  1218.    }
  1219.  
  1220.    npACB->iorbinuse = 0;
  1221.    ENABLE
  1222.  
  1223.    return( pIORB->iorbh.ErrorCode );
  1224. }
  1225.  
  1226. /*
  1227. ╔══════════════════════════════════╗
  1228. ║                                  ║
  1229. ║                                  ║
  1230. ║                                  ║
  1231. ║                                  ║
  1232. ║                                  ║
  1233. ╚══════════════════════════════════╝
  1234. */
  1235. USHORT NEAR InitResumeOtherAdd( NPACB npACB )
  1236. {
  1237.    PIORB_DEVICE_CONTROL  pIORB;
  1238.    PUCHAR                pWSFlags; /* work space flags */
  1239.  
  1240.    DISABLE
  1241.    if ( npACB->iorbinuse )
  1242.    {
  1243.       _asm int 3
  1244.    }
  1245.    npACB->iorbinuse = 1;
  1246.    ENABLE
  1247.  
  1248.    pIORB = (PIORB_DEVICE_CONTROL) &npACB->IORB;
  1249.    pWSFlags = pIORB->iorbh.DMWorkSpace;
  1250.    setmem( (PVOID) pIORB, 0, sizeof(npACB->IORB));
  1251.  
  1252.    pIORB->iorbh.Length          = sizeof(IORB_DEVICE_CONTROL);
  1253.    pIORB->iorbh.UnitHandle      = npACB->SharedDriverUnitHandle;
  1254.    pIORB->iorbh.CommandCode     = IOCC_DEVICE_CONTROL;
  1255.    pIORB->iorbh.CommandModifier = IOCM_RESUME;
  1256.    pIORB->iorbh.RequestControl  = IORB_ASYNC_POST;
  1257.    pIORB->iorbh.NotifyAddress   = NotifyInitIORBDone;
  1258.  
  1259.    pIORB->Flags |= DC_SUSPEND_IMMEDIATE;
  1260.  
  1261.    (*npACB->SharedDriverEP) ((PVOID)(pIORB));
  1262.  
  1263.    DISABLE
  1264.    *pWSFlags |= WSF_PROC_BLOCK;
  1265.  
  1266.    while( !(pIORB->iorbh.Status & IORB_DONE) )
  1267.    {
  1268.       DevHelp_ProcBlock( (ULONG) pIORB, -1, WAIT_IS_NOT_INTERRUPTABLE );
  1269.       DISABLE
  1270.    }
  1271.  
  1272.    npACB->iorbinuse = 0;
  1273.    ENABLE
  1274.  
  1275. }
  1276.  
  1277. /*
  1278. ╔══════════════════════════════════╗
  1279. ║                                  ║
  1280. ║                                  ║
  1281. ║                                  ║
  1282. ║                                  ║
  1283. ║                                  ║
  1284. ╚══════════════════════════════════╝
  1285. */
  1286. VOID   FAR  _loadds NotifyInitIORBDone( PIORB pIORB )
  1287. {
  1288.    USHORT       AwakeCount;
  1289.    PUCHAR       pWSFlags; /* work space flags */
  1290.  
  1291.    pWSFlags = pIORB->DMWorkSpace;
  1292.  
  1293.    DISABLE
  1294.    if ( ( pIORB->Status & IORB_DONE ) && ( *pWSFlags & WSF_PROC_BLOCK ) )
  1295.    {
  1296.       *pWSFlags &= ~WSF_PROC_BLOCK;
  1297.       DevHelp_ProcRun( (ULONG) pIORB, &AwakeCount );
  1298.    }
  1299.    ENABLE
  1300. }
  1301.  
  1302. /*
  1303. ╔══════════════════════════════════╗
  1304. ║                                  ║
  1305. ║                                  ║
  1306. ║                                  ║
  1307. ║                                  ║
  1308. ║                                  ║
  1309. ╚══════════════════════════════════╝
  1310. */
  1311. USHORT NEAR ParseCmdLine( PDDD_PARM_LIST pADDParms )
  1312. {
  1313.    PSZ           pCmdLine;
  1314.    PSZ           pCurrChar;
  1315.    USHORT        LtoUval = 'a' - 'A';
  1316.    USHORT        rc = 0;
  1317.  
  1318.    pCmdLine = MAKEP( SELECTOROF(pADDParms),
  1319.                      (USHORT)   pADDParms->cmd_line_args );
  1320.  
  1321.  
  1322.    for ( pCurrChar = pCmdLine; *pCurrChar; pCurrChar++ )
  1323.    {
  1324.       /* Convert from lower case to upper case */
  1325.       if ( *pCurrChar >= 'a' && *pCurrChar <= 'z' )
  1326.          *pCurrChar = *pCurrChar - LtoUval;
  1327.  
  1328.       if ( *pCurrChar == '/')
  1329.       {
  1330.          pCurrChar++;
  1331.          if ( (*pCurrChar == 'V') || (*pCurrChar == 'v') )
  1332.          {
  1333.             Verbose = TRUE;
  1334.          }
  1335.          else
  1336.          {
  1337.             rc = 1;
  1338.             break;
  1339.          }
  1340.       }
  1341.    }
  1342.    return( rc );
  1343. }
  1344.  
  1345. /*
  1346. ╔══════════════════════════════════╗
  1347. ║                                  ║
  1348. ║                                  ║
  1349. ║                                  ║
  1350. ║                                  ║
  1351. ║                                  ║
  1352. ╚══════════════════════════════════╝
  1353. */
  1354. static strnswap( PSZ d, PSZ s, USHORT n )
  1355. {
  1356.   USHORT    j = 1;
  1357.  
  1358.   while( s[j] && n-- ) { *d++ = s[j]; j^=1; s+=(j*2); }
  1359.   *d = 0;
  1360.  
  1361.   return ( 0 );
  1362. }
  1363.  
  1364.  
  1365. /*------------------------------------------------------------------------*/
  1366. /*                                                                        */
  1367. /* Calibration Routines                                                   */
  1368. /*                                                                        */
  1369. /* These routines adjust the loop counts in various I/O                   */
  1370. /* workers to achieve the correct real-time delays and                    */
  1371. /* timeout values.                                                        */
  1372. /*                                                                        */
  1373. /*------------------------------------------------------------------------*/
  1374.  
  1375. /*------------------------------------*/
  1376. /* CalibrateTimers                    */
  1377. /*                                    */
  1378. /* This routine does calibration of   */
  1379. /* the IODelay and other timed        */
  1380. /* functions                          */
  1381. /*                                    */
  1382. /*------------------------------------*/
  1383.  
  1384. VOID FAR CalibrateTimers( NPACB npACB )
  1385. {
  1386.   /*----------------------------------------*/
  1387.   /* Set a known loop count for each worker */
  1388.   /*----------------------------------------*/
  1389.  
  1390.   CheckReadyCount = CALIBRATE_LOOP_COUNT;
  1391.   IODelayCount    = CALIBRATE_LOOP_COUNT;
  1392.   WaitDRQCount    = CALIBRATE_LOOP_COUNT;
  1393.   WaitBSYCount    = CALIBRATE_LOOP_COUNT;
  1394.  
  1395.   /*----------------------------------------------------*/
  1396.   /* CalibrateWorker returns the loop count for the     */
  1397.   /* worker routine to achieve a delay of 1ms.          */
  1398.   /*                                                    */
  1399.   /* This loop count is scaled up (or down) to achieve  */
  1400.   /* the requested realtime delay.                      */
  1401.   /*                                                    */
  1402.   /* Note: all timed functions are dependent on the     */
  1403.   /*       IODelay worker! Therefore IODelay must be    */
  1404.   /*       calibrated first.                            */
  1405.   /*----------------------------------------------------*/
  1406.  
  1407.   IODelayCount    = CalibrateWorker( npACB, (PCV) &IODelay ) / uSPerMS;
  1408.   if ( !IODelayCount )
  1409.      IODelayCount = 1;
  1410.  
  1411.   CheckReadyCount = CalibrateWorker( npACB, (PCV) &CheckReady ) * MAX_WAIT_READY;
  1412.   if ( !CheckReadyCount )
  1413.      CheckReadyCount = 100;
  1414.  
  1415.   WaitBSYCount = CalibrateWorker( npACB, (PCV) &CheckReady ) * MAX_WAIT_BSY;
  1416.   if ( !WaitBSYCount )
  1417.      WaitBSYCount = 1000;
  1418.  
  1419.   WaitDRQCount = CalibrateWorker( npACB, (PCV) &BSY_CLR_DRQ_SET_WAIT ) * MAX_WAIT_DRQ;
  1420.   if ( !WaitDRQCount )
  1421.      WaitDRQCount = 1000;
  1422.  
  1423. }
  1424.  
  1425.  
  1426. /*-----------------------------------------------*/
  1427. /* CalibrateWorker                               */
  1428. /*                                               */
  1429. /* We call the worker routine with a known loop  */
  1430. /* count for a known realtime interval.          */
  1431. /*                                               */
  1432. /*-----------------------------------------------*/
  1433. ULONG FAR CalibrateWorker( NPACB npACB, PCV pWorker )
  1434. {
  1435.   ULONG         CallCount      = 0;
  1436.  
  1437.   Calibrate      = 1;
  1438.   CallWorker     = 1;
  1439.   CallWorkerSync = 1;
  1440.  
  1441.   if ( ADD_StartTimerMS((PULONG) &CalibrateTimerHandle,
  1442.                         (ULONG)  CALIBRATE_TIMER_INTERVAL,
  1443.                         (PFN)    CalibrateTimer,
  1444.                         (ULONG)  0,
  1445.                         (ULONG)  0              ) )
  1446.   {
  1447.      _asm { int 3 }
  1448.   }
  1449.  
  1450.   /*--------------------------------------*/
  1451.   /* Synchronize with the begining of the */
  1452.   /* next timer interval                  */
  1453.   /*--------------------------------------*/
  1454.   while ( CallWorkerSync )
  1455.     ;
  1456.  
  1457.   /*--------------------------------------*/
  1458.   /* Call the worker until the interval   */
  1459.   /* expires.                             */
  1460.   /*--------------------------------------*/
  1461.   while ( CallWorker )
  1462.   {
  1463.     (*pWorker)( npACB );
  1464.  
  1465.     CallCount++;
  1466.   }
  1467.  
  1468.   ADD_CancelTimer( CalibrateTimerHandle );
  1469.  
  1470.   Calibrate = 0;
  1471.  
  1472.   /*-----------------------------------------------*/
  1473.   /* The number of calls to the worker times the   */
  1474.   /* known worker loop count divided by the        */
  1475.   /* realtime interval in miliseconds gives us     */
  1476.   /* the proper loop count for 1ms of delay.       */
  1477.   /*                                               */
  1478.   /* Note: The timer package adds 1 tick to the    */
  1479.   /*       calculated interval to compensate       */
  1480.   /*       for it not being aligned. We factor     */
  1481.   /*       this out by using this alternate        */
  1482.   /*       define for the interval.                */
  1483.   /*-----------------------------------------------*/
  1484.  
  1485.   CallCount *= CALIBRATE_LOOP_COUNT;
  1486.  
  1487.   return ( CallCount / CALIBRATE_INTERVAL_ACTUAL );
  1488. }
  1489.  
  1490.  
  1491. /*---------------------------------------*/
  1492. /* CalibrateTimer                        */
  1493. /*                                       */
  1494. /* This routine is called by the         */
  1495. /* timer handler each time a calibration */
  1496. /* interval expires                      */
  1497. /*                                       */
  1498. /* Normally two calibration intervals    */
  1499. /* elapse. One so that we can sync up    */
  1500. /* with the timer and one to do the      */
  1501. /* calibration.                          */
  1502. /*                                       */
  1503. /*---------------------------------------*/
  1504. VOID FAR CalibrateTimer( ULONG hCalibrateTimer, ULONG Unused1, ULONG Unused2 )
  1505. {
  1506.   if ( CallWorkerSync )
  1507.   {
  1508.     CallWorkerSync = 0;
  1509.   }
  1510.   else
  1511.   {
  1512.     CallWorker = 0;
  1513.   }
  1514. }
  1515.