home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cdrom.zip / DDK / BASE / SRC / DEV / DASD / CDROM / ATAPI / atapigen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-10  |  24.2 KB  |  639 lines

  1. /**************************************************************************
  2.  *
  3.  * SOURCE FILE NAME = ATAPIGEN.C
  4.  *
  5.  * DESCRIPTION : General functions for ATAPI driver
  6.  *
  7.  *
  8.  * Copyright : COPYRIGHT IBM CORPORATION, 1991, 1992
  9.  *             LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
  10.  *             REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
  11.  *             RESTRICTED MATERIALS OF IBM
  12.  *             IBM CONFIDENTIAL
  13.  *
  14.  * VERSION = 1.0
  15.  *
  16.  * DATE
  17.  *
  18.  * DESCRIPTION :
  19.  *
  20.  * Purpose:
  21.  *
  22.  *
  23.  * CHANGE ACTIVITY =
  24.  *   DATE      FLAG        DEFECT  CHANGE DESCRIPTION
  25.  *   --------  ----------  ------  --------------------------------------
  26.  *   08/22/94  V@93531     93531   1) Suspend/Resume logic passes IRQ handler
  27.  *                                 address. 2) DRQ polling is not valid while
  28.  *                                 BSY bit set.
  29.  *   04/03/94  @V117508    117508  Remove unneeded ctxhook procedure and data
  30.  *   04/05/96  @V151168            Merged warm dock/swap code.
  31.  *   05/24/96  @V155162            Thinkpad docking/swapping IDE update.
  32.  ***************************************************************************/
  33.  
  34. #define INCL_NOBASEAPI
  35. #define INCL_NOPMAPI
  36. #include "os2.h"
  37. #include "dos.h"
  38. #include "devcmd.h"
  39. #include "dskinit.h"
  40.  
  41. #include "iorb.h"
  42. #include "addcalls.h"
  43. #include "dhcalls.h"
  44.  
  45. // for APM                                                          /*@V151168*/
  46. #include "apmcalls.h"                                               /*@V151168*/
  47. #include "doccalls.h"                                               /*@V151168*/
  48.  
  49. #define INCL_INITRP_ONLY
  50. #include "reqpkt.h"
  51.  
  52. #include "scsi.h"
  53. #include "cdbscsi.h"
  54.  
  55. #include "atapicon.h"
  56. #include "atapireg.h"
  57. #include "atapityp.h"
  58. #include "atapiext.h"
  59. #include "atapipro.h"
  60.  
  61.  
  62. /*
  63. ╔══════════════════════════════════╗
  64. ║                                  ║
  65. ║  IODelay                         ║
  66. ║                                  ║
  67. ║  Wait for 1 µsec                 ║
  68. ║                                  ║
  69. ╚══════════════════════════════════╝
  70. */
  71. VOID FAR IODelay()
  72. {
  73.    ULONG IODelayCtr = IODelayCount;
  74.  
  75.    while( IODelayCtr--)
  76.       ;
  77. }
  78.  
  79. /*
  80. ╔════════════════════════════════════╗
  81. ║                                    ║
  82. ║  setmem                            ║
  83. ║                                    ║
  84. ║  Sets memory starting at location  ║
  85. ║  p, to the value c, for len bytes  ║
  86. ║                                    ║
  87. ╚════════════════════════════════════╝
  88. */
  89. VOID NEAR setmem( PBYTE d, USHORT c, USHORT len )
  90. {
  91.    USHORT   i;
  92.  
  93.    for ( i = 0; i < len ; i++ )
  94.       d[i] = (UCHAR) c;
  95.  
  96.    return;
  97. }
  98.  
  99. /*
  100. ╔══════════════════════════════════╗
  101. ║                                  ║
  102. ║  memcopy                         ║
  103. ║                                  ║
  104. ║  Copies the contents of memory   ║
  105. ║  at the source (s) to the        ║
  106. ║  destination (d), for len bytes  ║
  107. ║                                  ║
  108. ╚══════════════════════════════════╝
  109. */
  110. VOID NEAR memcopy( PBYTE d, PBYTE s, USHORT len )
  111. {
  112.    USHORT   i;
  113.    USHORT   j;
  114.  
  115.    j = len >> 1;
  116.  
  117.    for ( i = 0; i < j ; i++ )
  118.       ((PUSHORT) d)[i] = ((PUSHORT) s)[i];
  119.  
  120.    if ( j & 1 ) d[len-1] = s[len-1];
  121.  
  122.  
  123.    return;
  124. }
  125.  
  126. /*
  127. ╔══════════════════════════════════╗
  128. ║                                  ║
  129. ║  strncpy                         ║
  130. ║                                  ║
  131. ║  Copies the contents of string   ║
  132. ║  (s) to that of string (d) for   ║
  133. ║  (n) characters.  (d) is then    ║
  134. ║  null terminated.                ║
  135. ║                                  ║
  136. ╚══════════════════════════════════╝
  137. */
  138. VOID NEAR strncpy( PSZ d, PSZ s, USHORT n )
  139. {
  140.    while( *s && n-- ) *d++ = *s++;
  141.    *d = 0;
  142.  
  143.    return;
  144. }
  145.  
  146. /*
  147. ╔═══════════════════════════════════╗
  148. ║                                   ║
  149. ║  strncmp                          ║
  150. ║                                   ║
  151. ║  Compares the contents of string  ║
  152. ║  (s) to that of string (d) for    ║
  153. ║  (n) characters.                  ║
  154. ║                                   ║
  155. ╚═══════════════════════════════════╝
  156. */
  157. BOOL NEAR strncmp( PSZ d, PSZ s, USHORT n )
  158. {
  159.    BOOL  rc = TRUE;
  160.  
  161.    while( n-- )
  162.      if ( *d++ != *s++)
  163.      {
  164.         rc = FALSE;
  165.         break;
  166.      }
  167.  
  168.    return( rc );
  169. }
  170.  
  171. /*
  172. ╔══════════════════════════════════╗
  173. ║                                  ║
  174. ║  BSYWAIT                         ║
  175. ║                                  ║
  176. ║  Poll for BSY until success or   ║
  177. ║  until exceed max poll time      ║
  178. ║                                  ║
  179. ║  Returns True if BSY clear       ║
  180. ║  False if exceeded max poll time ║
  181. ║                                  ║
  182. ╚══════════════════════════════════╝
  183. */
  184. USHORT NEAR BSYWAIT ( NPACB npACB )
  185. {
  186.  
  187.    ULONG cMS = WaitBSYCount;                                         /*V@93531*/
  188.    USHORT Status;
  189.  
  190.    /*
  191.    ┌──────────────────────────────────────┐
  192.    │ Poll for BSY up to WaitBSYCount times│
  193.    └──────────────────────────────────────┘
  194.    */
  195.  
  196.    do
  197.    {
  198.       Status = GetRegister ( npACB, FI_PSTATUS );
  199.       IODelay();
  200.    } while (((Status & FX_BUSY) || Calibrate) && --cMS);
  201.  
  202.    return (cMS);
  203. }
  204.  
  205. /*
  206. ╔══════════════════════════════════╗
  207. ║                                  ║
  208. ║  DRQ_SET_WAIT                    ║
  209. ║                                  ║
  210. ║  Poll for DRQ until asserted or  ║
  211. ║  until exceed max poll time      ║
  212. ║                                  ║
  213. ║  Returns True if DRQ set         ║
  214. ║  False if exceeded max poll time ║
  215. ║                                  ║
  216. ╚══════════════════════════════════╝
  217. */                                                                   /*V@93531*/
  218. USHORT FAR BSY_CLR_DRQ_SET_WAIT( NPACB npACB )                       /*V@93531*/
  219. {                                                                    /*V@93531*/
  220.                                                                      /*V@93531*/
  221.    ULONG cMS = WaitDRQCount;                                         /*V@93531*/
  222.    USHORT Status;                                                    /*V@93531*/
  223.                                                                      /*V@93531*/
  224.    /*                                                                  V@93531*/
  225.    /*┌──────────────────────────────────────┐                          V@93531*/
  226.    /*│ Poll for DRQ up to WaitDRQCount times│                          V@93531*/
  227.    /*└──────────────────────────────────────┘                          V@93531*/
  228.                                                                      /*V@93531*/
  229.    do                                                                /*V@93531*/
  230.    {                                                                 /*V@93531*/
  231.       Status = GetRegister ( npACB, FI_PSTATUS );                    /*V@93531*/
  232.       IODelay();                                                     /*V@93531*/
  233.    } while ((  !(Status & FX_DRQ) ||
  234.                  Status & FX_BUSY ||
  235.                  Calibrate) &&
  236.             --cMS);                                                  /*V@93531*/
  237.                                                                      /*V@93531*/
  238.    return (cMS);                                                     /*V@93531*/
  239. }                                                                    /*V@93531*/
  240.                                                                      /*V@93531*/
  241. /*
  242. ╔══════════════════════════════════╗
  243. ║                                  ║
  244. ║  DRQ_AND_BSY_CLEAR_WAIT          ║
  245. ║                                  ║
  246. ║  Poll for DRQ and BSY until both ║
  247. ║  are clear or until exceed max   ║
  248. ║  poll time                       ║
  249. ║                                  ║
  250. ║  Returns True if DRQ AND BSY are ║
  251. ║  both clear,                     ║
  252. ║  False if exceeded max poll time ║
  253. ║                                  ║
  254. ╚══════════════════════════════════╝
  255. */                                                                   /*V@93531*/
  256. USHORT NEAR DRQ_AND_BSY_CLEAR_WAIT ( NPACB npACB )                   /*V@93531*/
  257. {                                                                    /*V@93531*/
  258.                                                                      /*V@93531*/
  259.    USHORT cMS = WaitDRQCount;                                        /*V@93531*/
  260.    USHORT Status;                                                    /*V@93531*/
  261.                                                                      /*V@93531*/
  262.    /*  ┌──────────────────────────────────────────────┐                V@93531*/
  263.    /*  │ Poll for DRQ and BSY up to WaitDRQCount times│                V@93531*/
  264.    /*  └──────────────────────────────────────────────┘                V@93531*/
  265.                                                                      /*V@93531*/
  266.    do                                                                /*V@93531*/
  267.    {                                                                 /*V@93531*/
  268.       Status = GetRegister ( npACB, FI_PSTATUS );                    /*V@93531*/
  269.       IODelay();                                                     /*V@93531*/
  270.    } while ((   (Status & FX_BUSY) ||
  271.                 (Status & FX_DRQ ) ||
  272.                 Calibrate) &&
  273.             --cMS);                                                  /*V@93531*/
  274.      /* enddo */                                                     /*V@93531*/
  275.                                                                      /*V@93531*/
  276.    return( (Status & (FX_BUSY | FX_DRQ)) ? FALSE : TRUE );           /*V@93531*//*@V155162*/
  277. }                                                                    /*V@93531*/
  278.  
  279.  
  280. /*
  281. ╔══════════════════════════════════════════════════════════════════╗
  282. ║                                                                  ║
  283. ║   VirtToPhys - Convert a virtual to physical address             ║
  284. ║                                                                  ║
  285. ║   Convert a virtual to a physical address.  This routine does    ║
  286. ║   not use DevHlp_VirtToPhys since that devhlp is not callable    ║
  287. ║   at interrupt time.                                             ║
  288. ║                                                                  ║
  289. ║   ULONG  VirtToPhys  (PBYTE VirtAddr)                            ║
  290. ║                                                                  ║
  291. ║   ENTRY:    VirtAddr         - 16:16 virutal address             ║
  292. ║                                                                  ║
  293. ║   RETURN:   ULONG            - 32 bit phys address               ║
  294. ║                                                                  ║
  295. ╚══════════════════════════════════════════════════════════════════╝
  296. */
  297.  
  298. ULONG VirtToPhys (PBYTE VirtAddr)
  299. {
  300.  
  301.    USHORT rc;
  302.    SCATGATENTRY ScatGatEntry;
  303.    ULONG VirtLinAddr;
  304.    ULONG ScatLinAddr;
  305.    ULONG PageListCount;
  306.  
  307.    rc = DevHelp_VirtToLin((USHORT) (SELECTOROF(VirtAddr)),
  308.                           (ULONG) (OFFSETOF(VirtAddr)),
  309.                           (PLIN) &VirtLinAddr);
  310.  
  311.    rc = DevHelp_VirtToLin((USHORT) ( ((ULONG)((PVOID) &ScatGatEntry)) >> 16),
  312.                           (ULONG)  ( (USHORT)((PVOID) &ScatGatEntry)),
  313.                           (PLIN) &ScatLinAddr);
  314.  
  315.    rc = DevHelp_LinToPageList(VirtLinAddr, 1, ScatLinAddr,
  316.                                               (PULONG) &PageListCount);
  317.  
  318.    return(ScatGatEntry.ppXferBuf);
  319.  
  320. }
  321.  
  322. /*
  323. ╔══════════════════════════════════╗
  324. ║                                  ║
  325. ║                                  ║
  326. ║                                  ║
  327. ║                                  ║
  328. ║                                  ║
  329. ╚══════════════════════════════════╝
  330. */
  331. VOID NEAR SelectUnit( NPACB npACB, USHORT UnitId )
  332. {
  333.    USHORT        Port;
  334.    USHORT        Data;
  335.  
  336.    Port                       = npACB->IOPorts[FI_PDRVSLCT];
  337.    npACB->IORegs[FI_PDRVSLCT] =
  338.                 DEFAULT_ATAPI_DRV_SLCT_REG | ((UnitId == 0) ? UNIT0 : UNIT1 );
  339.    Data                       = npACB->IORegs[FI_PDRVSLCT];
  340.  
  341.    outp( Port, Data );
  342.    IODelay();
  343. }
  344.  
  345. /*
  346. ╔══════════════════════════════════╗
  347. ║                                  ║
  348. ║                                  ║
  349. ║                                  ║
  350. ║                                  ║
  351. ║                                  ║
  352. ╚══════════════════════════════════╝
  353. */
  354. USHORT NEAR SuspendOtherAdd( NPACB npACB )
  355. {
  356.    PIORB_DEVICE_CONTROL  pIORB;
  357.    NPUSHORT              npUS;
  358.  
  359.    DISABLE
  360.    if ( npACB->iorbinuse )
  361.    {
  362.       _asm int 3
  363.    }
  364.    npACB->iorbinuse = 1;
  365.    ENABLE
  366.  
  367.    pIORB = (PIORB_DEVICE_CONTROL) &npACB->IORB;
  368.    setmem( (PVOID) pIORB, 0, sizeof(npACB->IORB));
  369.  
  370.    pIORB->iorbh.Length          = sizeof(IORB_DEVICE_CONTROL);
  371.    pIORB->iorbh.UnitHandle      = npACB->SharedDriverUnitHandle;
  372.    pIORB->iorbh.CommandCode     = IOCC_DEVICE_CONTROL;
  373.    pIORB->iorbh.CommandModifier = IOCM_SUSPEND;
  374.    pIORB->iorbh.RequestControl  = IORB_ASYNC_POST;
  375.    pIORB->iorbh.NotifyAddress   = NotifySuspendResumeDone;
  376.    pIORB->IRQHandlerAddress     = npACB->IRQHandler;                /*@V93531*/
  377.  
  378.    pIORB->Flags = DC_SUSPEND_DEFERRED | DC_SUSPEND_IRQADDR_VALID;   /*@V93531*/
  379.  
  380.    npUS = (NPUSHORT) pIORB->iorbh.DMWorkSpace;
  381.  
  382.    *npUS = (USHORT) npACB;
  383.  
  384.    (*npACB->SharedDriverEP) ((PVOID)(pIORB));
  385.  
  386. }
  387.  
  388. /*
  389. ╔══════════════════════════════════╗
  390. ║                                  ║
  391. ║                                  ║
  392. ║                                  ║
  393. ║                                  ║
  394. ║                                  ║
  395. ╚══════════════════════════════════╝
  396. */
  397. USHORT NEAR ResumeOtherAdd( NPACB npACB )
  398. {
  399.    PIORB_DEVICE_CONTROL  pIORB;
  400.    NPUSHORT              npUS;
  401.  
  402.    DISABLE
  403.    if ( npACB->iorbinuse )
  404.    {
  405.       _asm int 3
  406.    }
  407.    npACB->iorbinuse = 1;
  408.    ENABLE
  409.  
  410.    pIORB = (PIORB_DEVICE_CONTROL) &npACB->IORB;
  411.    setmem( (PVOID) pIORB, 0, sizeof(npACB->IORB));
  412.  
  413.    pIORB->iorbh.Length          = sizeof(IORB_DEVICE_CONTROL);
  414.    pIORB->iorbh.UnitHandle      = npACB->SharedDriverUnitHandle;
  415.    pIORB->iorbh.CommandCode     = IOCC_DEVICE_CONTROL;
  416.    pIORB->iorbh.CommandModifier = IOCM_RESUME;
  417.    pIORB->iorbh.RequestControl  = IORB_ASYNC_POST;
  418.    pIORB->iorbh.NotifyAddress   = NotifySuspendResumeDone;
  419.  
  420.    npUS = (NPUSHORT) pIORB->iorbh.DMWorkSpace;
  421.  
  422.    *npUS = (USHORT) npACB;
  423.  
  424.    (*npACB->SharedDriverEP) ((PVOID)(pIORB));
  425.  
  426. }
  427.  
  428. /*
  429. ╔══════════════════════════════════╗
  430. ║                                  ║
  431. ║                                  ║
  432. ║                                  ║
  433. ║                                  ║
  434. ║                                  ║
  435. ╚══════════════════════════════════╝
  436. */
  437. ULONG NEAR QueryOtherAdd( NPACB npACB )
  438. {
  439.    PIORB_DEVICE_CONTROL  pIORB;
  440.  
  441.    DISABLE
  442.    if ( npACB->iorbinuse )
  443.    {
  444.       _asm int 3
  445.    }
  446.    npACB->iorbinuse = 1;
  447.    ENABLE
  448.  
  449.    pIORB = (PIORB_DEVICE_CONTROL) &npACB->IORB;
  450.    setmem( (PVOID) pIORB, 0, sizeof(npACB->IORB));
  451.  
  452.    pIORB->iorbh.Length          = sizeof(IORB_DEVICE_CONTROL);
  453.    pIORB->iorbh.UnitHandle      = npACB->SharedDriverUnitHandle;
  454.    pIORB->iorbh.CommandCode     = IOCC_DEVICE_CONTROL;
  455.    pIORB->iorbh.CommandModifier = IOCM_GET_QUEUE_STATUS;
  456.    pIORB->iorbh.RequestControl  = 0;
  457.    pIORB->iorbh.NotifyAddress   = 0;
  458.  
  459.    (*npACB->SharedDriverEP) ((PVOID)(pIORB));
  460.    while ( !(pIORB->iorbh.Status & IORB_DONE) )  /* Wait till done */
  461.       ;
  462.  
  463.    npACB->iorbinuse = 0;
  464.    return( pIORB->QueueStatus );
  465. }
  466.  
  467. /*
  468. ╔══════════════════════════════════╗
  469. ║                                  ║
  470. ║                                  ║
  471. ║                                  ║
  472. ║                                  ║
  473. ║                                  ║
  474. ╚══════════════════════════════════╝
  475. */
  476. VOID   FAR  _loadds NotifySuspendResumeDone( PIORB pIORB )
  477. {
  478.    NPACB    npACB;
  479.  
  480.  
  481.    npACB = ((NPACB *) pIORB->DMWorkSpace)[0];
  482.  
  483.    npACB->iorbinuse = 0;
  484.  
  485. #ifdef DEBUG
  486.    if( !(pIORB->Status & IORB_DONE) || (pIORB->Status & IORB_ERROR) )
  487.    {
  488.       _asm int 3
  489.    }
  490. #endif
  491.  
  492.    StartOSM( npACB );
  493.  
  494. }
  495.  
  496. /*
  497. ╔══════════════════════════════════╗
  498. ║                                  ║
  499. ║  IDECDStr                        ║
  500. ║                                  ║
  501. ║  Stategy Routine for IBMIDECD    ║
  502. ║                                  ║
  503. ║  Accepts only the Init Base      ║
  504. ║  device drivers command (0x1B).  ║
  505. ║  Returns unknown command for     ║
  506. ║  all others.                     ║
  507. ║                                  ║
  508. ╚══════════════════════════════════╝
  509. */
  510. VOID NEAR IDECDStr()
  511. {
  512.    PRPH     pRPH;
  513.    USHORT   Cmd;
  514.  
  515.    _asm {
  516.            mov word ptr pRPH[0], bx       /*  pRPH is initialized to          */
  517.            mov word ptr pRPH[2], es       /*  ES:BX passed from the kernel    */
  518.         }
  519.  
  520.    pRPH->Status = STATUS_DONE;
  521.    Cmd = pRPH->Cmd;
  522.  
  523.    if( Cmd == CMDInitBase )
  524.    {
  525.       DriverInit( (PRPINITIN) pRPH );
  526.    }
  527.    else if( Cmd == CMDInitComplete )                                /*@V155162*/
  528.    {                                                                /*@V155162*/
  529.       if ( APMAttach() == 0 )                                       /*@V151168*//* moved for @V155162*/
  530.       {                                                             /*@V151168*//* moved for @V155162*/
  531.          APMRegister( APMEventHandler,                              /*@V151168*//* moved for @V155162*/
  532.                       APM_NOTIFYSETPWR | APM_NOTIFYNORMRESUME |     /*@V151168*//* moved for @V155162*/
  533.                       APM_NOTIFYCRITRESUME,(USHORT) 0);             /*@V151168*//* moved for @V155162*/
  534.       }                                                             /*@V151168*//* moved for @V155162*/
  535.    }                                                                /*@V155162*/
  536.    else if( Cmd == CMDInit )
  537.    {
  538.       _asm int 3
  539.       Device_Help = ((PRPINITIN)pRPH)->DevHlpEP;
  540.       TTYWrite ( UninstallMsg );
  541.       TTYWrite ( DevEqualsMsg );
  542.       pRPH->Status =  STATUS_DONE;
  543.    }
  544.    else
  545.    {
  546.       _asm int 3
  547.       pRPH->Status =  STATUS_DONE | STATUS_ERR_UNKCMD;
  548.    }
  549.    _asm {                                                           /*@V151168*/
  550.            leave
  551.            retf
  552.         }
  553. } /* IDECDStr */
  554.  
  555.  
  556. /*                                                                    @V151168
  557. ** Register for APM messages at the end of Initialization.            @V151168
  558. */                                                                  /*@V151168*/
  559. VOID NEAR ATAPICompleteInit( NPACB npACB )                          /*@V151168*/
  560. {                                                                   /*@V151168*/
  561.    npACB->OSMState = ACBOS_COMPLETE_IORB;
  562. }
  563.  
  564.  
  565. /*------------------------------------*/                            /*@V151168*/
  566. /* APM Suspend/Resume Support         */                            /*@V151168*/
  567. /* Reinitializes adapters and units   */                            /*@V151168*/
  568. /* following a resume event.          */                            /*@V151168*/
  569. /*------------------------------------*/                            /*@V151168*/
  570.                                                                     /*@V151168*/
  571. USHORT FAR APMEventHandler(PAPMEVENT Event)                         /*@V151168*/
  572. {                                                                   /*@V151168*/
  573.   USHORT Message = (USHORT)Event->ulParm1;                          /*@V151168*/
  574.   USHORT PwrState;                                                  /*@V151168*/
  575.                                                                     /*@V151168*/
  576.   if ( Message == APM_SETPWRSTATE )                                 /*@V151168*/
  577.   {                                                                 /*@V151168*/
  578.     PwrState = (USHORT)(Event->ulParm2 >> 16);                      /*@V151168*/
  579.     if (PwrState != APM_PWRSTATEREADY)                              /*@V151168*/
  580.     {                                                               /*@V151168*/
  581.       return ( APMSuspend() );                                      /*@V151168*/
  582.     }                                                               /*@V151168*/
  583.   }                                                                 /*@V151168*/
  584.   else if ( Message == APM_NORMRESUMEEVENT ||                       /*@V151168*/
  585.             Message == APM_CRITRESUMEEVENT )                        /*@V151168*/
  586.   {                                                                 /*@V151168*/
  587.     return(APMResume());                                            /*@V151168*/
  588.   }                                                                 /*@V151168*/
  589.   return 0;                                                         /*@V151168*/
  590. }                                                                   /*@V151168*/
  591.                                                                     /*@V151168*/
  592. /*                                                                    @V151168
  593.  * APMSuspend is currently a no-op                                    @V151168
  594.  */                                                                 /*@V151168*/
  595. USHORT NEAR APMSuspend()                                            /*@V151168*/
  596. {                                                                   /*@V151168*/
  597.   return 0;                                                         /*@V151168*/
  598. }                                                                   /*@V151168*/
  599.                                                                     /*@V151168*/
  600. USHORT NEAR APMResume()                                             /*@V151168*/
  601. {                                                                   /*@V151168*/
  602.   NPATBL npAT = AdapterTable;                                       /*@V151168*/
  603.   NPACB  npACB;                                                     /*@V151168*/
  604.   NPUCB  npUCB;                                                     /*@V151168*/
  605.   USHORT i;                                                         /*@V151168*/
  606.   USHORT j, rc;                                                     /*@V151168*/
  607.   USHORT Flags;                                                     /*@V155162*/
  608.                                                                     /*@V151168*/
  609.     for (i=0; i< cAdapters; i++, npAT++ )                            /*@V151168*/
  610.     {                                                                /*@V151168*/
  611.       if ( !(npAT->Flags & ATBF_DISABLED) )                         /*@V151168*/
  612.       {                                                             /*@V151168*/
  613.          if ( npACB = npAT->npACB )                                 /*@V151168*/
  614.          {                                                          /*@V151168*/
  615.             for (j = 0; j < MAX_UNITS; j++ )                        /*@V151168*/
  616.             {                                                       /*@V151168*/
  617.                npUCB = &npACB->UnitCB[j];                           /*@V151168*/
  618.                                                                     /*@V151168*/
  619.                if( npUCB->Flags & UCBF_FORCE )                      /*@V155162*/
  620.                {                                                    /*@V155162*/
  621.                   Flags = npUCB->Flags & UCBF_NOTPRESENT;           /*@V155162*/
  622.                         // Try to claim the unit, which does an identify  /*@V155162*/
  623.                   // command.  If this works, assume the drive is   /*@V155162*/
  624.                   // back.                                          /*@V155162*/
  625.                         npUCB->Flags &= ~UCBF_NOTPRESENT;                 /*@V155162*/
  626.                   rc = ClaimUnit( npAT, TRUE, 0, NULL, NULL );      /*@V155162*/
  627.                   if( Flags != (npUCB->Flags & UCBF_NOTPRESENT) )   /*@V155162*/
  628.                   {                                                 /*@V155162*/
  629.                      npUCB->Flags |= UCBF_MEDIACHANGED;             /*@V155162*/
  630.                   }                                                 /*@V155162*/
  631.                }                                                    /*@V155162*/
  632.                 }                                                       /*@V151168*/
  633.             }                                                          /*@V151168*/
  634.         }                                                             /*@V151168*/
  635.     }                                                                /*@V151168*/
  636.   return 0;                                                         /*@V151168*/
  637. }                                                                   /*@V151168*/
  638.  
  639.