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 / atapinit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-10  |  76.5 KB  |  1,954 lines

  1. /* SCCSID = %W% %E% */
  2. /**************************************************************************
  3.  *
  4.  * SOURCE FILE NAME = ATAPINIT.C
  5.  *
  6.  * DESCRIPTION : ATAPI driver initialization
  7.  *
  8.  *
  9.  * Copyright : COPYRIGHT IBM CORPORATION, 1991, 1992
  10.  *             LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
  11.  *             REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
  12.  *             RESTRICTED MATERIALS OF IBM
  13.  *             IBM CONFIDENTIAL
  14.  *
  15.  * VERSION = 1.0
  16.  *
  17.  * DATE
  18.  *
  19.  * DESCRIPTION :
  20.  *
  21.  * Purpose:
  22.  *
  23.  *
  24.  * CHANGE ACTIVITY =
  25.  *   DATE      FLAG        DEFECT  CHANGE DESCRIPTION
  26.  *   --------  ----------  ------  --------------------------------------
  27.  *   08/22/94  V@93531     93531   1) Suspend/Resume logic passes IRQ handler
  28.  *                                 address. 2) DRQ polling is not valid while
  29.  *                                 BSY bit set.
  30.  *   09/08/94  @V98451             Add Resource Manger
  31.  *   03/07/94  @V117508    117508  Remove unneeded ctxhook procedure and data
  32.  *   04/03/95  @V117508    117508  Add #defines to include MCA version of driver
  33.  *   05/10/95  @V121891    121891  Fix problem in 2 min time delay fix - most
  34.  *                                 of which was resolved in 117508.
  35.  *   11/30/95  @V132280   PJ19658  Fix so as not to claim non-CDROM units -
  36.  *                                 GetATAPIUnits().
  37.  *                                 Added HWRESOURCE to fix Suspend/Resume.
  38.  *   02/02/96  @V127556            BT update.  Got rid of extra Resume which
  39.  *                                 was being sent to IBM1S506.ADD at init.
  40.  *   04/05/96  @V151168            Merged warm dock/swap code.
  41.  *   05/09/96  @V153151            Moved some code and data from init to
  42.  *                                 run-time residency.
  43.  *   05/24/96  @V155162            Thinkpad docking/swapping IDE update.
  44.  *   06/18/96  @V156660            Synched search keys in RM between IBMIDECD
  45.  *                                 and IBM1S506.
  46.  *   08/26/96  @V162970            Fixed the DIAMOND 8X CDROM problem.
  47.  *   04/26/98  @V195083            Added Panasonic PD support.
  48.  ***************************************************************************/
  49.  
  50. #define INCL_NOBASEAPI
  51. #define INCL_NOPMAPI
  52. #define INCL_DOSERRORS
  53. #include "os2.h"
  54. #include "dos.h"
  55. #include "bseerr.h"
  56. #include "devclass.h"
  57. #include "dskinit.h"
  58.  
  59. #include "iorb.h"
  60. #include "addcalls.h"
  61. #include "dhcalls.h"
  62. #include "apmcalls.h"                                               /*@V151168*/
  63.  
  64. #define INCL_INITRP_ONLY
  65. #include "reqpkt.h"
  66.  
  67. #include "scsi.h"
  68. #include "cdbscsi.h"
  69.  
  70. #include "atapicon.h"
  71. #include "atapireg.h"
  72. #include "atapityp.h"
  73. #include "atapiext.h"
  74. #include "atapipro.h"
  75. #include "rmcalls.h"
  76.  
  77. static strnswap( PSZ d, PSZ s, USHORT n );
  78. VOID NEAR set_data_in_sg( PBYTE, PIORB_ADAPTER_PASSTHRU, USHORT );  /*@V151168*/
  79.  
  80. // If the CDROM is not present, use this code to Fake the           /*@V151168*/
  81. // operations so that OS2CDROM.DMD believes that a CD-ROM           /*@V151168*/
  82. // is really there but empty                                        /*@V151168*/
  83. int FakeATA(NPACB npACB)                                            /*@V151168*/
  84. {                                                                   /*@V151168*/
  85.     PBYTE pSGVirtBuf;    //virtual address of SG xfer buffer            /*@V151168*/
  86.    PSCATGATENTRY  pSGLIST;                                          /*@V151168*/
  87.     USHORT Flag;                                                     /*@V151168*/
  88.                                                                     /*@V151168*/
  89.     npACB->pIORB->Status = IORB_DONE;                                /*@V151168*/
  90.     npACB->pIORB->ErrorCode = 0;    // to be sure this succeeds        /*@V151168*/
  91.                                                                     /*@V151168*/
  92.    if (npACB->npUCB->ReqFlags & UCBR_IDENTIFY)                      /*@V151168*/
  93.     {                                                                /*@V151168*/
  94.       // Copy Fake ATA Identify Buffer and set request done         /*@V151168*/
  95.                                                                     /*@V151168*/
  96.         pSGLIST = ( (PIORB_ADAPTER_PASSTHRU)(npACB->pIORB))->pSGList; /*@V151168*/
  97.                                                                     /*@V151168*/
  98.         // SGlist has phys buffer pointer, convert to Virt to use     /*@V151168*/
  99.       if ( DevHelp_PhysToVirt( pSGLIST->ppXferBuf,                  /*@V151168*/
  100.             (USHORT)pSGLIST->XferBufLen,                               /*@V151168*/
  101.                 (PVOID) &pSGVirtBuf,                                    /*@V151168*/
  102.                 &Flag ) )                                               /*@V151168*/
  103.         {    // we should never get here....                            /*@V151168*/
  104.             _asm int 3                                                   /*@V151168*/
  105.         }                                                             /*@V151168*/
  106.       memcopy( (PBYTE)pSGVirtBuf,                                   /*@V151168*/
  107.             (PBYTE)&atapi_identify_data,                               /*@V151168*/
  108.             (USHORT)pSGLIST->XferBufLen);                              /*@V151168*/
  109.         return(0);                                                    /*@V151168*/
  110.     }                                                                /*@V151168*/
  111.                                                                     /*@V151168*/
  112.     if (npACB->npUCB->ReqFlags & UCBR_RESET)                         /*@V151168*/
  113.     {                                                                /*@V151168*/
  114.         //Make believe a reset hapened                                /*@V151168*/
  115.         return(0);                                                    /*@V151168*/
  116.                                                                     /*@V151168*/
  117.    }                                                                /*@V151168*/
  118.    npACB->pIORB->Status = IORB_DONE | IORB_ERROR;                   /*@V151168*/
  119.     npACB->pIORB->ErrorCode = IOERR_CMD_SYNTAX;    // Failure code     /*@V151168*/
  120.     return(1);    //error, unknown command                             /*@V151168*/
  121. }                                                                   /*@V151168*/
  122.                                                                     /*@V151168*/
  123. //                                                                  /*@V151168*/
  124. // Fake ATAPI requests                                              /*@V151168*/
  125. //                                                                  /*@V151168*/
  126. int FakeATAPI(NPACB npACB)                                          /*@V151168*/
  127. {                                                                   /*@V151168*/
  128.    UCHAR    Opcode;     /* ATAPI Packet Commands Opcode */             /*@V151168*/
  129.    PIORB_ADAPTER_PASSTHRU  pIORB_pass =                             /*@V151168*/
  130.                            (PIORB_ADAPTER_PASSTHRU)npACB->pIORB;    /*@V151168*/
  131.    PSCSI_REQSENSE_DATA  pSenseData; /* for setting return status */ /*@V151168*/
  132.    struct CDB_ModeSense_10 FAR *pCDB;                               /*@V151168*/
  133.    UCHAR                ASC;        /* additional sense code */     /*@V151168*/
  134.    /* pointer to the SCSI status block */                           /*@V151168*/
  135.    PSCSI_STATUS_BLOCK   pSCSISB;                                    /*@V151168*/
  136.                                                                     /*@V151168*/
  137.    /* ATAPI Commands for CD-ROM Drives */                           /*@V151168*/
  138.                                                                     /*@V151168*/
  139.                                                                     /*@V151168*/
  140.     Opcode = pIORB_pass->pControllerCmd[0];                          /*@V151168*/
  141.                                                                     /*@V151168*/
  142.    switch ( Opcode ) {                                              /*@V151168*/
  143.                                                                     /*@V151168*/
  144.    case SCSI_INQUIRY :                                              /*@V151168*/
  145.       /* set INQUIRY data in s/g list. */                           /*@V151168*/
  146.       set_data_in_sg( (PBYTE) &inquiry_data, pIORB_pass,            /*@V151168*/
  147.                         sizeof( SCSI_INQDATA ) );                   /*@V151168*/
  148.       pSenseData = &no_audio_status;       /* set OK status */      /*@V151168*/
  149.       break;                                                        /*@V151168*/
  150.                                                                     /*@V151168*/
  151.    case SCSI_MODE_SELECT_10 :                                       /*@V151168*/
  152.       /* set Invalid field in Command Packet */                     /*@V151168*/
  153.       pSenseData = &invalid_field_in_cmd_pkt;                       /*@V151168*/
  154.       break;                                                        /*@V151168*/
  155.                                                                     /*@V151168*/
  156.    case SCSI_MODE_SENSE_10 :                                        /*@V151168*/
  157.       pCDB = (struct CDB_ModeSense_10 FAR *)                        /*@V151168*/
  158.              pIORB_pass->pControllerCmd;                            /*@V151168*/
  159.                                                                     /*@V151168*/
  160.       if ( pCDB->page_code == PAGE_CAPABILITIES &&                  /*@V151168*/
  161.             ( pCDB->PC == PC_DEFAULT || pCDB->PC == PC_CURRENT ) ) {/*@V151168*/
  162.                                                                     /*@V151168*/
  163.          /* set mode sense data in s/g list. */                     /*@V151168*/
  164.          set_data_in_sg( (PBYTE) mode_sense_10_page_cap, pIORB_pass,/*@V151168*/
  165.                            LEN_MODE_SENSE_10 );                     /*@V151168*/
  166.          pSenseData = &no_audio_status;       /* set OK status */   /*@V151168*/
  167.                                                                     /*@V151168*/
  168.       }                                                             /*@V151168*/
  169.         else                                                          /*@V151168*/
  170.         {                                                             /*@V151168*/
  171.          /* set NOT-READY status */                                 /*@V151168*/
  172.          pSenseData = &medium_not_present;                          /*@V151168*/
  173.       }                                                             /*@V151168*/
  174.       break;                                                        /*@V151168*/
  175.                                                                     /*@V151168*/
  176.    case SCSI_REQUEST_SENSE :                                        /*@V151168*/
  177.       /* sense data is read in s/g list.* */                        /*@V151168*/
  178.       set_data_in_sg( (PBYTE) &medium_not_present, pIORB_pass,      /*@V151168*/
  179.                         sizeof( SCSI_REQSENSE_DATA ) );             /*@V151168*/
  180.       pSenseData = &no_audio_status;       /* set OK status */      /*@V151168*/
  181.       break;                                                        /*@V151168*/
  182.                                                                     /*@V151168*/
  183.    case SCSI_TEST_UNIT_READY :                                      /*@V151168*/
  184.    default :                                                        /*@V151168*/
  185.       /* set NOT-READY status */                                    /*@V151168*/
  186.       pSenseData = &medium_not_present;                             /*@V151168*/
  187.         break;                                                        /*@V151168*/
  188.                                                                     /*@V151168*/
  189.    } /* endswitch */                                                /*@V151168*/
  190.                                                                     /*@V151168*/
  191.                                                                     /*@V151168*/
  192.    /* set ErrorCode from additional Sense Code. */                  /*@V151168*/
  193.    /* pSenseData must be set appropriately. */                      /*@V151168*/
  194.                                                                     /*@V151168*/
  195.    ASC = pSenseData->AddSenseCode;                                  /*@V151168*/
  196.                                                                     /*@V151168*/
  197.     if ( ASC > MaxAddSenseDataEntry ) {                              /*@V151168*/
  198.       npACB->pIORB->ErrorCode = IOERR_ADAPTER_REFER_TO_STATUS;      /*@V151168*/
  199.    } else {                                                         /*@V151168*/
  200.       npACB->pIORB->ErrorCode = AddSenseDataMap[ASC];               /*@V151168*/
  201.    }                                                                /*@V151168*/
  202.    npACB->IORBError = npACB->pIORB->ErrorCode; /* make sure */      /*@V151168*/
  203.                                                                     /*@V151168*/
  204.    if ( npACB->pIORB->ErrorCode ) {                                 /*@V151168*/
  205.                                                                     /*@V151168*/
  206.       npACB->pIORB->Status |= IORB_ERROR | IORB_DONE;               /*@V151168*/
  207.                                                                     /*@V151168*/
  208.       /* return sense data if requested */                          /*@V151168*/
  209.                                                                     /*@V151168*/
  210.       if ( npACB->pIORB->RequestControl & IORB_REQ_STATUSBLOCK ) {  /*@V151168*/
  211.          pSCSISB = MAKEP( SELECTOROF(npACB->pIORB),                 /*@V151168*/
  212.                           (NPBYTE) npACB->pIORB->pStatusBlock);     /*@V151168*/
  213.          memcopy( (PBYTE) pSCSISB->SenseData,                       /*@V151168*/
  214.                   (PBYTE) pSenseData,                               /*@V151168*/
  215.                   ( pSCSISB->ReqSenseLen > SENSE_DATA_BYTES ) ?     /*@V151168*/
  216.                      /* min(a, b) */                                /*@V151168*/
  217.                      SENSE_DATA_BYTES : pSCSISB->ReqSenseLen );     /*@V151168*/
  218.                                                                     /*@V151168*/
  219.          /* sense data is vaild */                                  /*@V151168*/
  220.          pSCSISB->Flags |= STATUS_SENSEDATA_VALID;                  /*@V151168*/
  221.          /* status info returned */                                 /*@V151168*/
  222.          npACB->pIORB->Status |= IORB_STATUSBLOCK_AVAIL;            /*@V151168*/
  223.       }                                                             /*@V151168*/
  224.    } else {                                                         /*@V151168*/
  225.       npACB->pIORB->Status |= IORB_DONE;                            /*@V151168*/
  226.    }                                                                /*@V151168*/
  227.                                                                     /*@V151168*/
  228.    return( FALSE );                                                 /*@V151168*/
  229. }                                                                   /*@V151168*/
  230.                                                                     /*@V151168*/
  231. /*----------------------------------------------------------------*//*@V151168*/
  232. /* Function:   Copy data from buffer to S/G list.                 *//*@V151168*/
  233. /* Input:      pbuf, pIORB, buf_len                               *//*@V151168*/
  234. /* Output:     none                                               *//*@V151168*/
  235. /*----------------------------------------------------------------*//*@V151168*/
  236. VOID NEAR set_data_in_sg( PBYTE pbuf, PIORB_ADAPTER_PASSTHRU pIORB, /*@V151168*/
  237.                           USHORT buf_len )                          /*@V151168*/
  238. {                                                                   /*@V151168*/
  239.    UCHAR    i;                                                      /*@V151168*/
  240.    PSCATGATENTRY  pTempSGList;                                      /*@V151168*/
  241.    ULONG    ppSrcDst;            /* physical address */             /*@V151168*/
  242.    PBYTE    pSrcDst;             /* virtual address by PhysToVirt *//*@V151168*/
  243.    USHORT   XferCur;             /* segment length */               /*@V151168*/
  244.    USHORT   ModeFlag;            /* for PhysToVirt */               /*@V151168*/
  245.    USHORT   copy_bytes;                                             /*@V151168*/
  246.    USHORT   total_bytes; /* total_bytes + nokori_bytes == buf_len *//*@V151168*/
  247.    USHORT   nokori_bytes;                                           /*@V151168*/
  248.                                                                     /*@V151168*/
  249.    pTempSGList = pIORB->pSGList;                                    /*@V151168*/
  250.    total_bytes = 0;                                                 /*@V151168*/
  251.    nokori_bytes = buf_len;                                          /*@V151168*/
  252.                                                                     /*@V151168*/
  253.    for (i=0; i<pIORB->cSGList && total_bytes<buf_len ; i++,         /*@V151168*/
  254.         pTempSGList++) {                                            /*@V151168*/
  255.                                                                     /*@V151168*/
  256.       ppSrcDst = pTempSGList->ppXferBuf;                            /*@V151168*/
  257.       XferCur = pTempSGList->XferBufLen;                            /*@V151168*/
  258.                                                                     /*@V151168*/
  259.       if ( DevHelp_PhysToVirt( ppSrcDst, XferCur,                   /*@V151168*/
  260.                                (PVOID) &pSrcDst, &ModeFlag ) ) {    /*@V151168*/
  261. #ifdef DEBUG                                                        /*@V151168*/
  262.          INT3;                                                      /*@V151168*/
  263. #endif                                                              /*@V151168*/
  264.       }                                                             /*@V151168*/
  265.                                                                     /*@V151168*/
  266.       copy_bytes = ( XferCur < nokori_bytes ) ? XferCur :           /*@V151168*/
  267.                                                 nokori_bytes;       /*@V151168*/
  268.       memcopy( pSrcDst, pbuf, copy_bytes);                          /*@V151168*/
  269.                                                                     /*@V151168*/
  270.       total_bytes += copy_bytes;    /* update # of copied bytes */  /*@V151168*/
  271.       pbuf += copy_bytes;           /* increment pointer */         /*@V151168*/
  272.       nokori_bytes -= copy_bytes;/* update # of byte to be copied *//*@V151168*/
  273.    } /* endfor */                                                   /*@V151168*/
  274. }                                                                   /*@V151168*/
  275.  
  276. /*
  277. ╔══════════════════════════════════╗
  278. ║                                  ║
  279. ║                                  ║
  280. ║                                  ║
  281. ║                                  ║
  282. ║                                  ║
  283. ╚══════════════════════════════════╝
  284. */
  285. VOID   FAR  _loadds NotifyIORBDone( PIORB pIORB )                   /*@V153151*/
  286. {
  287.    USHORT       AwakeCount;
  288.    PUCHAR       pWSFlags; /* work space flags */
  289.  
  290.    pWSFlags = pIORB->DMWorkSpace;
  291.  
  292.    DISABLE
  293.    if ( ( pIORB->Status & IORB_DONE ) && ( *pWSFlags & WSF_PROC_BLOCK ) )
  294.    {
  295.       *pWSFlags &= ~WSF_PROC_BLOCK;
  296.       DevHelp_ProcRun( (ULONG) pIORB, &AwakeCount );
  297.    }
  298.    ENABLE
  299. }
  300.  
  301. /*
  302. ╔══════════════════════════════════╗
  303. ║                                  ║
  304. ║                                  ║
  305. ║                                  ║
  306. ║                                  ║
  307. ║                                  ║
  308. ╚══════════════════════════════════╝
  309. */
  310. USHORT GetIdentifyData( NPACB npACB, USHORT UnitId, PBYTE pID )
  311. {
  312.    NPIORB_ADAPTER_PASSTHRU  npIORB    = &InitIORB;
  313.    NPUCB                    npUCB     = &npACB->UnitCB[UnitId];
  314.    USHORT                   ErrorCode = 0;
  315.    PUCHAR                pWSFlags; /* work space flags */
  316.    NPIDENTIFYDATA    npID;                                          /*@V151168*/
  317.  
  318.    npUCB->ReqFlags |= UCBR_IDENTIFY;
  319.  
  320.    if ( DevHelp_VirtToPhys( (PVOID) pID,
  321.                             (PULONG) &IdentifySGList.ppXferBuf ) )
  322.    {
  323.       _asm { int 3 }
  324.    }
  325.  
  326.    pWSFlags = (PUCHAR) npIORB->iorbh.DMWorkSpace;
  327.    setmem( (PBYTE) npIORB, 0, sizeof(IORB_ADAPTER_PASSTHRU) );
  328.  
  329.    npIORB->iorbh.Length          = sizeof(IORB_ADAPTER_PASSTHRU);
  330.    npIORB->iorbh.UnitHandle      = (USHORT) &npACB->UnitCB[UnitId];
  331.    npIORB->iorbh.CommandCode     = IOCC_ADAPTER_PASSTHRU;
  332.    npIORB->iorbh.CommandModifier = IOCM_EXECUTE_ATA;
  333.    npIORB->iorbh.Status          = 0;                            /*@V132280*/
  334.    npIORB->iorbh.RequestControl  = IORB_ASYNC_POST;
  335.    npIORB->iorbh.NotifyAddress   = NotifyIORBDone;               /*@V153151*/
  336.    npIORB->cSGList               = 1;
  337.    npIORB->pSGList               = &IdentifySGList;
  338.  
  339.    ATAPIADDEntry( (PIORB) npIORB );
  340.  
  341.    DISABLE
  342.    *pWSFlags |= WSF_PROC_BLOCK;
  343.  
  344.    while( !(npIORB->iorbh.Status & IORB_DONE) )
  345.    {
  346.       DevHelp_ProcBlock( (ULONG)(PIORB) npIORB, -1, WAIT_IS_NOT_INTERRUPTABLE );
  347.       DISABLE
  348.    }
  349.  
  350.    npUCB->ReqFlags &= ~UCBR_IDENTIFY;
  351.  
  352.    ENABLE
  353.  
  354.     npID = (NPIDENTIFYDATA)pID;                                      /*@V151168*/
  355.                                                                     /*@V151168*/
  356.     if ( (npIORB->iorbh.Status & IORB_ERROR) ||                      /*@V151168*/
  357.         (npID->ModelNum[0] == 0) )                                  /*@V151168*/
  358.     {    // if failure, check if forced unit, if so set flag if        /*@V151168*/
  359.       // not present                                                /*@V151168*/
  360.         if( npUCB->Flags & UCBF_FORCE )                               /*@V155162*/
  361.       {                                                             /*@V151168*/
  362.             npUCB->Flags |= UCBF_NOTPRESENT;    //set fake flag           /*@V151168*/
  363.             npIORB->iorbh.Status |= IORB_ERROR;                        /*@V155162*/
  364.             npIORB->iorbh.ErrorCode = IOERR_UNIT_NOT_READY;            /*@V155162*/
  365.         }                                                             /*@V151168*/
  366.     }                                                                /*@V151168*/
  367.  
  368.    return( (npIORB->iorbh.Status & IORB_ERROR) ? npIORB->iorbh.ErrorCode : 0 );
  369.  
  370. }
  371.  
  372. /*
  373. ╔══════════════════════════════════╗
  374. ║                                  ║
  375. ║                                  ║
  376. ║                                  ║
  377. ║                                  ║
  378. ║                                  ║
  379. ╚══════════════════════════════════╝
  380. */
  381. static strnswap( PSZ d, PSZ s, USHORT n )
  382. {
  383.   USHORT    j = 1;
  384.  
  385.   while( s[j] && n-- ) { *d++ = s[j]; j^=1; s+=(j*2); }
  386.   *d = 0;
  387.  
  388.   return ( 0 );
  389. }
  390.  
  391. /*
  392. ╔══════════════════════════════════╗
  393. ║                                  ║
  394. ║                                  ║
  395. ║                                  ║
  396. ║                                  ║
  397. ║                                  ║
  398. ╚══════════════════════════════════╝
  399. */
  400. USHORT NEAR ATAPIIdentify( NPATBL npAT )
  401. {
  402.    NPIDENTIFYDATA    npID;
  403.    NPUTBL            npUT;
  404.    NPACB             npACB = npAT->npACB;
  405.    NPUCB             npUCB;
  406.    USHORT            rc;
  407.    USHORT            UnitType = 0xff;
  408.    USHORT            Model;
  409.    USHORT            UnitId;
  410.  
  411.    npID   = (NPIDENTIFYDATA) ScratchBuf;
  412.    UnitId = npACB->npUCB->UnitId;
  413.    npUT   = &npAT->Unit[UnitId];
  414.    npUCB  = npACB->npUCB;
  415.  
  416.    npUCB->Capabilities = 0;                                          /*@V93531*/
  417.  
  418.    if ( !(rc=GetIdentifyData( npACB, UnitId, (PBYTE) npID )))
  419.    {
  420. #define  DONTCARE        0
  421. #define  NEC_CDR_260     1
  422. #define  NEC_CDR_250     2
  423. #define  MATSHITA_CR_571 3
  424.  
  425.       if( strncmp( MatshitaID,                                      /*@V155162*/
  426.                    npID->ModelNum,sizeof(npID->ModelNum)))
  427.          Model = MATSHITA_CR_571;
  428.       else if( strncmp( Nec01ID,                                    /*@V155162*/
  429.                         npID->ModelNum,sizeof(npID->ModelNum)))
  430.       {
  431.          Model = NEC_CDR_260;
  432.          strncpy( npUT->Firmware, npID->Firmware, sizeof(npID->Firmware));
  433.          if( strncmp( Nec01FWID,                                    /*@V155162*/
  434.              npID->Firmware, sizeof(npID->Firmware)))
  435.          {
  436.             npUCB->Capabilities |= UCBC_SPEC_REV_17B;
  437.             npUCB->Capabilities |= UCBC_IRQ_ON_ATA_COMPLETE;
  438.             npACB->IRQTimeOut   *= 4;
  439.          }
  440.       }
  441.       else if( strncmp( Nec02ID,                                    /*@V155162*/
  442.                         npID->ModelNum,sizeof(npID->ModelNum)))
  443.       {
  444.          Model = NEC_CDR_250;
  445.       }
  446.       else
  447.          Model = DONTCARE;
  448.  
  449.       /*
  450.       ┌────────────────────────────────────────┐
  451.       │ Save Model/Serial/Firmware Information │
  452.       └────────────────────────────────────────┘
  453.       */
  454.       if ( (Model == NEC_CDR_260 ) &&
  455.            ( npUCB->Capabilities & UCBC_SPEC_REV_17B) )
  456.       {
  457.          strncpy( npUT->ModelNum, npID->ModelNum, sizeof(npID->ModelNum));
  458.          strncpy( npUT->Serial,   npID->Serial,   sizeof(npID->Serial));
  459.       }
  460.       else
  461.       {
  462.          strnswap( npUT->ModelNum, npID->ModelNum, sizeof(npID->ModelNum)-2);
  463.          strnswap( npUT->Serial,   npID->Serial,   sizeof(npID->Serial)-2);
  464.          strnswap( npUT->Firmware, npID->Firmware, sizeof(npID->Firmware)-2);
  465.       }
  466.  
  467.       if( strncmp( npUT->Serial, BlankSerial,                       /*@V155162*/
  468.                   sizeof(npID->Serial) ) )
  469.          npUT->Serial[0] = 0;
  470.  
  471.       switch (npID->GenConfig.CmdPktSize)
  472.       {
  473.          case 0 : npUCB->CmdPacketLength = 12;
  474.                   break;
  475.  
  476.          case 1 : npUCB->CmdPacketLength = 16;
  477.                   break;
  478.  
  479.          default: npUCB->CmdPacketLength = 00;
  480.                   rc = 1;
  481.       }
  482.  
  483.       switch (npID->GenConfig.CmdDRQType)
  484.       {
  485.          case 0 : npUCB->Capabilities |= UCBC_MICROPROCESSOR_DRQ;
  486.                   break;
  487.  
  488.          case 1 : npUCB->Capabilities |= UCBC_INTERRUPT_DRQ;
  489.                   break;
  490.  
  491.          case 2 : npUCB->Capabilities |= UCBC_ACCELERATED_DRQ;
  492.                   break;
  493.  
  494.          default: npUCB->Capabilities |= UCBC_MICROPROCESSOR_DRQ;
  495.                   rc = 1;
  496.       }
  497.  
  498.       switch (npID->GenConfig.ProtocolType)
  499.       {
  500.          case 0 :
  501.          case 1 : npUCB->Capabilities |= UCBC_ATA;
  502.                   break;
  503.  
  504.          case 2 :
  505.          case 3 : npUCB->Capabilities |= UCBC_ATAPI;
  506.                   break;
  507.  
  508.          default: npUCB->Capabilities |= UCBC_ATA;
  509.                   rc = 1;
  510.       }
  511.  
  512.       switch ( UnitType = npID->GenConfig.DeviceType )
  513.       {
  514.          case UIB_TYPE_DISK :
  515.                   npUCB->Capabilities |= UCBC_DIRECT_ACCESS_DEVICE;
  516.                   break;
  517.  
  518.          case UIB_TYPE_CDROM :
  519.                   npUCB->Capabilities |= UCBC_CDROM_DEVICE;
  520.                   break;
  521.  
  522.          case UIB_TYPE_OPTICAL_MEMORY :
  523.                   npUCB->Capabilities |= UCBC_OPTICAL_MEMORY_DEVICE;
  524.                   break;
  525.  
  526.          default: npUCB->Capabilities &= ~(UCBC_DIRECT_ACCESS_DEVICE |
  527.                                           UCBC_CDROM_DEVICE |
  528.                                           UCBC_OPTICAL_MEMORY_DEVICE);
  529.                   rc = 1;
  530.       }
  531.  
  532.       if ( npID->Capabilities & IDD_DMASupported )
  533.          npUCB->Capabilities |= UCBC_DMA;
  534.       else
  535.          npUCB->Capabilities &= ~UCBC_DMA;
  536.  
  537.       if ( npID->Capabilities & IDD_LBASupported )
  538.          npUCB->Capabilities |= UCBC_LBA;
  539.       else
  540.          npUCB->Capabilities &= ~UCBC_LBA;
  541.  
  542.       if ( npID->Capabilities & IDD_IORDYSupported )
  543.          npUCB->Capabilities |= UCBC_IORDY;
  544.       else
  545.          npUCB->Capabilities &= ~UCBC_IORDY;
  546.  
  547.       if ( npID->Capabilities & IDD_IORDYDisablable )
  548.          npUCB->Capabilities |= UCBC_IORDY_DISABLE;
  549.       else
  550.          npUCB->Capabilities &= ~UCBC_IORDY_DISABLE;
  551.  
  552.       switch ( Model )
  553.       {
  554.          case NEC_CDR_260 :
  555.          case NEC_CDR_250 :
  556.             UnitType = 5;
  557.             npUCB->CmdPacketLength = 12;
  558.             npUCB->Capabilities |= UCBC_MICROPROCESSOR_DRQ |
  559.                                    UCBC_ATAPI              |
  560.                                    UCBC_CDROM_DEVICE;
  561.             rc = 0;
  562.             break;
  563.  
  564.          case MATSHITA_CR_571 :
  565.             npUCB->Capabilities &= ~UCBC_SPEC_REV_17B;
  566.             npUCB->Capabilities |= UCBC_IRQ_ON_ATA_COMPLETE;
  567.             break;
  568.  
  569.          default:
  570.             npUCB->Capabilities &= ~UCBC_SPEC_REV_17B;
  571.             npUCB->Capabilities &= ~UCBC_IRQ_ON_ATA_COMPLETE;
  572.       }
  573.    }
  574.  
  575.    if ( rc )
  576.    {
  577.       return( -1 );
  578.    }
  579.  
  580.    return( UnitType );
  581. }
  582.  
  583. /*
  584. ╔══════════════════════════════════╗
  585. ║                                  ║
  586. ║                                  ║
  587. ║                                  ║
  588. ║                                  ║
  589. ║                                  ║
  590. ╚══════════════════════════════════╝
  591. */
  592. USHORT NEAR InitSuspendOtherAdd( NPACB npACB )
  593. {
  594.    PIORB_DEVICE_CONTROL  pIORB;
  595.    PUCHAR                pWSFlags; /* work space flags */
  596.  
  597.    DISABLE
  598.    if ( npACB->iorbinuse )
  599.    {
  600.       _asm int 3
  601.    }
  602.    npACB->iorbinuse = 1;
  603.    ENABLE
  604.  
  605.    pIORB = (PIORB_DEVICE_CONTROL) &npACB->IORB;
  606.    pWSFlags = pIORB->iorbh.DMWorkSpace;
  607.    setmem( (PVOID) pIORB, 0, sizeof(npACB->IORB));
  608.  
  609.    pIORB->iorbh.Length          = sizeof(IORB_DEVICE_CONTROL);
  610.    pIORB->iorbh.UnitHandle      = npACB->SharedDriverUnitHandle;
  611.    pIORB->iorbh.CommandCode     = IOCC_DEVICE_CONTROL;
  612.    pIORB->iorbh.CommandModifier = IOCM_SUSPEND;
  613.    pIORB->iorbh.Status          = 0;                                /*@V132280*/
  614.    pIORB->iorbh.RequestControl  = IORB_ASYNC_POST;
  615.    pIORB->iorbh.NotifyAddress   = NotifyIORBDone;                   /*@V153151*/
  616.    pIORB->IRQHandlerAddress     = npACB->IRQHandler;                /*@V93531*/
  617.    pIORB->Flags                 = DC_SUSPEND_IMMEDIATE              /*@V93531*/
  618.                                   | DC_SUSPEND_IRQADDR_VALID;       /*@V93531*/
  619.  
  620.    (*npACB->SharedDriverEP) ((PVOID)(pIORB));
  621.  
  622.    DISABLE
  623.    *pWSFlags |= WSF_PROC_BLOCK;
  624.  
  625.    while( !(pIORB->iorbh.Status & IORB_DONE) )
  626.    {
  627.       DevHelp_ProcBlock( (ULONG) pIORB, -1, WAIT_IS_NOT_INTERRUPTABLE );
  628.       DISABLE
  629.    }
  630.  
  631.    npACB->iorbinuse = 0;
  632.    ENABLE
  633.  
  634.    return( pIORB->iorbh.ErrorCode );
  635. }
  636.  
  637. /*
  638. ╔══════════════════════════════════╗
  639. ║                                  ║
  640. ║                                  ║
  641. ║                                  ║
  642. ║                                  ║
  643. ║                                  ║
  644. ╚══════════════════════════════════╝
  645. */
  646. USHORT NEAR InitResumeOtherAdd( NPACB npACB )
  647. {
  648.    PIORB_DEVICE_CONTROL  pIORB;
  649.    PUCHAR                pWSFlags; /* work space flags */
  650.  
  651.    DISABLE
  652.    if ( npACB->iorbinuse )
  653.    {
  654.       _asm int 3
  655.    }
  656.    npACB->iorbinuse = 1;
  657.    ENABLE
  658.  
  659.    pIORB = (PIORB_DEVICE_CONTROL) &npACB->IORB;
  660.    pWSFlags = pIORB->iorbh.DMWorkSpace;
  661.    setmem( (PVOID) pIORB, 0, sizeof(npACB->IORB));
  662.  
  663.    pIORB->iorbh.Length          = sizeof(IORB_DEVICE_CONTROL);
  664.    pIORB->iorbh.UnitHandle      = npACB->SharedDriverUnitHandle;
  665.    pIORB->iorbh.CommandCode     = IOCC_DEVICE_CONTROL;
  666.    pIORB->iorbh.CommandModifier = IOCM_RESUME;
  667.    pIORB->iorbh.Status          = 0;                                /*@V132280*/
  668.    pIORB->iorbh.RequestControl  = IORB_ASYNC_POST;
  669.    pIORB->iorbh.NotifyAddress   = NotifyIORBDone;                   /*@V153151*/
  670.  
  671.    pIORB->Flags |= DC_SUSPEND_IMMEDIATE;
  672.  
  673.    (*npACB->SharedDriverEP) ((PVOID)(pIORB));
  674.  
  675.    DISABLE
  676.    *pWSFlags |= WSF_PROC_BLOCK;
  677.  
  678.    while( !(pIORB->iorbh.Status & IORB_DONE) )
  679.    {
  680.       DevHelp_ProcBlock( (ULONG) pIORB, -1, WAIT_IS_NOT_INTERRUPTABLE );
  681.       DISABLE
  682.    }
  683.  
  684.    npACB->iorbinuse = 0;
  685.    ENABLE
  686.  
  687. }
  688.  
  689. /*
  690. ╔══════════════════════════════════╗
  691. ║                                  ║
  692. ║                                  ║
  693. ║                                  ║
  694. ║                                  ║
  695. ║                                  ║
  696. ╚══════════════════════════════════╝
  697. */
  698. USHORT FAR CheckReady( NPACB npACB )
  699. {
  700.    ULONG WaitCount;
  701.    USHORT Status;
  702.  
  703.    npACB->TimerFlags &= ~ACBT_BUSY;
  704.  
  705.    WaitCount = CheckReadyCount;
  706.  
  707.    while( WaitCount-- )
  708.    {
  709.       Status = GetRegister( npACB, FI_PSTATUS );
  710.  
  711.       if ( !(Status & FX_BUSY) && (Status & FX_READY) )
  712.       {
  713.          if ( !Calibrate )
  714.             break;
  715.       }
  716.    }
  717.  
  718.    if ( Status & FX_BUSY )
  719.    {
  720.       npACB->TimerFlags |= ACBT_BUSY;
  721.    }
  722.  
  723.    npACB->IORegs[FI_PSTATUS] = Status;
  724.  
  725.    return( ((npACB->TimerFlags & ACBT_BUSY) || !(Status & FX_READY)) ? 1 : 0);
  726. }
  727.  
  728.  
  729. /*------------------------------------------------------------------------*/
  730. /*                                                                        */
  731. /* Calibration Routines                                                   */
  732. /*                                                                        */
  733. /* These routines adjust the loop counts in various I/O                   */
  734. /* workers to achieve the correct real-time delays and                    */
  735. /* timeout values.                                                        */
  736. /*                                                                        */
  737. /*------------------------------------------------------------------------*/
  738.  
  739. /*------------------------------------*/
  740. /* CalibrateTimers                    */
  741. /*                                    */
  742. /* This routine does calibration of   */
  743. /* the IODelay and other timed        */
  744. /* functions                          */
  745. /*                                    */
  746. /*------------------------------------*/
  747.  
  748. VOID FAR CalibrateTimers( NPACB npACB )
  749. {
  750.   /*----------------------------------------*/
  751.   /* Set a known loop count for each worker */
  752.   /*----------------------------------------*/
  753.  
  754.   CheckReadyCount = CALIBRATE_LOOP_COUNT;
  755.   IODelayCount    = CALIBRATE_LOOP_COUNT;
  756.   WaitDRQCount    = CALIBRATE_LOOP_COUNT;
  757.   WaitBSYCount    = CALIBRATE_LOOP_COUNT;
  758.  
  759.   /*----------------------------------------------------*/
  760.   /* CalibrateWorker returns the loop count for the     */
  761.   /* worker routine to achieve a delay of 1ms.          */
  762.   /*                                                    */
  763.   /* This loop count is scaled up (or down) to achieve  */
  764.   /* the requested realtime delay.                      */
  765.   /*                                                    */
  766.   /* Note: all timed functions are dependent on the     */
  767.   /*       IODelay worker! Therefore IODelay must be    */
  768.   /*       calibrated first.                            */
  769.   /*----------------------------------------------------*/
  770.  
  771.   IODelayCount    = CalibrateWorker( npACB, (PCV) &IODelay ) / uSPerMS;
  772.   if ( !IODelayCount )
  773.      IODelayCount = 1;
  774.  
  775.   CheckReadyCount = CalibrateWorker( npACB, (PCV) &CheckReady ) * MAX_WAIT_READY;
  776.   if ( !CheckReadyCount )
  777.      CheckReadyCount = 100;
  778.  
  779.   WaitBSYCount = CalibrateWorker( npACB, (PCV) &CheckReady ) * MAX_WAIT_BSY;
  780.   if ( !WaitBSYCount )
  781.      WaitBSYCount = 1000;
  782.  
  783.   WaitDRQCount = CalibrateWorker( npACB, (PCV) &BSY_CLR_DRQ_SET_WAIT ) * MAX_WAIT_DRQ;
  784.   if ( !WaitDRQCount )
  785.      WaitDRQCount = 1000;
  786.  
  787. }
  788.  
  789. /*-----------------------------------------------*/
  790. /* CalibrateWorker                               */
  791. /*                                               */
  792. /* We call the worker routine with a known loop  */
  793. /* count for a known realtime interval.          */
  794. /*                                               */
  795. /*-----------------------------------------------*/
  796. ULONG FAR CalibrateWorker( NPACB npACB, PCV pWorker )
  797. {
  798.   ULONG         CallCount      = 0;
  799.  
  800.   Calibrate      = 1;
  801.   CallWorker     = 1;
  802.   CallWorkerSync = 1;
  803.  
  804.   if ( ADD_StartTimerMS((PULONG) &CalibrateTimerHandle,
  805.                         (ULONG)  CALIBRATE_TIMER_INTERVAL,
  806.                         (PFN)    CalibrateTimer,
  807.                         (ULONG)  0,
  808.                         (ULONG)  0              ) )
  809.   {
  810.      _asm { int 3 }
  811.   }
  812.  
  813.   /*--------------------------------------*/
  814.   /* Synchronize with the begining of the */
  815.   /* next timer interval                  */
  816.   /*--------------------------------------*/
  817.   while ( CallWorkerSync )
  818.     ;
  819.  
  820.   /*--------------------------------------*/
  821.   /* Call the worker until the interval   */
  822.   /* expires.                             */
  823.   /*--------------------------------------*/
  824.   while ( CallWorker )
  825.   {
  826.     (*pWorker)( npACB );
  827.  
  828.     CallCount++;
  829.   }
  830.  
  831.   ADD_CancelTimer( CalibrateTimerHandle );
  832.  
  833.   Calibrate = 0;
  834.  
  835.   /*-----------------------------------------------*/
  836.   /* The number of calls to the worker times the   */
  837.   /* known worker loop count divided by the        */
  838.   /* realtime interval in miliseconds gives us     */
  839.   /* the proper loop count for 1ms of delay.       */
  840.   /*                                               */
  841.   /* Note: The timer package adds 1 tick to the    */
  842.   /*       calculated interval to compensate       */
  843.   /*       for it not being aligned. We factor     */
  844.   /*       this out by using this alternate        */
  845.   /*       define for the interval.                */
  846.   /*-----------------------------------------------*/
  847.  
  848.   CallCount *= CALIBRATE_LOOP_COUNT;
  849.  
  850.   return ( CallCount / CALIBRATE_INTERVAL_ACTUAL );
  851. }
  852.  
  853. /*---------------------------------------*/
  854. /* CalibrateTimer                        */
  855. /*                                       */
  856. /* This routine is called by the         */
  857. /* timer handler each time a calibration */
  858. /* interval expires                      */
  859. /*                                       */
  860. /* Normally two calibration intervals    */
  861. /* elapse. One so that we can sync up    */
  862. /* with the timer and one to do the      */
  863. /* calibration.                          */
  864. /*                                       */
  865. /*---------------------------------------*/
  866. VOID FAR CalibrateTimer( ULONG hCalibrateTimer, ULONG Unused1, ULONG Unused2 )
  867. {
  868.   if ( CallWorkerSync )
  869.   {
  870.     CallWorkerSync = 0;
  871.   }
  872.   else
  873.   {
  874.     CallWorker = 0;
  875.   }
  876. }
  877.  
  878.  
  879. /*
  880. ** Called from: DriverInit() Resume = FALSE
  881. **              APMResume()  Resume = TRUE
  882. **
  883. ** With Resume = FALSE, issue IOCM_ALLOCATE_UNIT command to the device
  884. ** driver that identified the ATAPI unit.  The unit can be real or
  885. ** FORCEd but must be identified as an ATAPI device at power-on boot
  886. ** initialization. The IOCM_ALLOCATE_UNIT command is done only once at
  887. ** initialization time.  At APMResume(), Resume = TRUE, try to recognize
  888. ** and activate the drive that MAY now be present.  If UCBF_NOTPRESENT
  889. ** is set then unit is definitely not currently present.
  890. ** UCBF_NOTRPRESENT is always reset when this routine is called from
  891. ** APMResume().
  892. **
  893. ** Normaly the device's registers are defined for FORCEd adapters but
  894. ** in the case of PCMCIA attached adapters, it is possible the registers
  895. ** may not yet be defined in AdapterTable.  In this case short circuit
  896. ** ATAPIIdentify() and set the UCBF_NOTPRESENT and return.
  897. */
  898. USHORT NEAR ClaimUnit( NPATBL npAT, BOOL Resume, USHORT UnitHandle, /*@V155162*/
  899.                        PUNITINFO pOldUnitInfo, VOID (FAR *DriverEP)() )
  900. {
  901.    PUNITINFO            pUI;
  902.    NPACB                npACB;
  903.  
  904.    USHORT               rc = 0;
  905.    USHORT               UnitType;
  906.  
  907.    USHORT               FeatureReg;                                /*@V98451*/
  908.    ULONG                OldIRQTimeOut;                             /*@V117508*/
  909.    NPUCB                npUCB;                                      /*@V155162*///vbr
  910.    USHORT               l, num_retry;                               /*@V162970*/
  911.  
  912.    npACB = npAT->npACB;                                             /*@V155162*/
  913.    npUCB = npACB->npUCB;                                            /*@V155162*///vbr
  914.  
  915.    /*                                                                 @V155162
  916.    ** PCMCIA adapters may not have registers defined yet.             @V155162
  917.    ** If not then the FORCEd unit is definitely not present.          @V155162
  918.    ** The registers will be defined during PCMCIA card insertion      @V155162
  919.    ** event procssing for this driver.                                @V155162
  920.    */                                                               /*@V155162*/
  921.    if( !npAT->BasePort )                                            /*@V155162*/
  922.    {                                                                /*@V155162*/
  923.       npUCB->Flags |= UCBF_NOTPRESENT;                              /*@V155162*/
  924.    }                                                                /*@V155162*/
  925.    else if( npUCB->Flags & UCBF_NOTPRESENT )                        /*@V155162*/
  926.    {                                                                /*@V155162*/
  927.       UnitType = UIB_TYPE_CDROM;                                    /*@V155162*/
  928.    }                                                                /*@V155162*/
  929.    else                                                             /*@V155162*/
  930.    {                                                                /*@V155162*/
  931.       /*                                                                 @V127556
  932.       ** Suspend ATA driver so we can calibrate this driver to the HW.   @V127556
  933.       */                                                               /*@V127556*/
  934.       if( !(rc = InitSuspendOtherAdd( npACB )) )                       /*@V127556*/
  935.       {                                                                /*@V127556*/
  936.         npACB->suspended = 0;                                          /*@V127556*/
  937.         npACB->ResourceFlags |= ACBRF_CURR_OWNER;                      /*@V127556*/
  938.       }                                                                /*@V127556*/
  939.       else                                                             /*@V127556*/
  940.       {                                                                /*@V127556*/
  941.         goto ClaimUnitExit;                                            /*@V127556*/
  942.       }                                                                /*@V127556*/
  943.  
  944.       if ( !TimersCalibrated )
  945.       {
  946.         CalibrateTimers( npAT->npACB );
  947.         TimersCalibrated = 1;
  948.       }
  949.  
  950.       /* SONY CDs come up in DMA mode sometimes.  Therefore, we must force them */
  951.       /* into non-DMA mode.                                                     */
  952.  
  953.       FeatureReg = npAT->BasePort + 1;                                /*@V98451*/
  954.       outp( FeatureReg, 0 );                                          /*@V98451*/
  955.  
  956.       /*                                                                 @V127556
  957.       ** We are done with the HW, so resume ATA driver.                  @V127556
  958.       */                                                               /*@V127556*/
  959.       if( !(rc = InitResumeOtherAdd( npACB )) )                        /*@V127556*/
  960.       {                                                                /*@V127556*/
  961.         npACB->suspended = 1;                                          /*@V127556*/
  962.         npACB->ResourceFlags &= ~ACBRF_CURR_OWNER;                     /*@V127556*/
  963.       }                                                                /*@V127556*/
  964.       else                                                             /*@V127556*/
  965.       {                                                                /*@V127556*/
  966.         goto ClaimUnitExit;                                            /*@V127556*/
  967.       }                                                                /*@V127556*/
  968.  
  969.       OldIRQTimeOut = npACB->IRQTimeOut;                              /*@V121891*/
  970.       npACB->IRQTimeOut = INIT_TIMEOUT_SHORT;                         /*@V117508*/
  971.  
  972.       UnitType = ATAPIIdentify( npAT );
  973.                  /*@V155162*/
  974.                                                                       /*VVVVVVVV*/
  975.      if ( (UnitType == 0xffff) && (!(npUCB->Flags & UCBF_FORCE)) )                                        /*@V162970*/
  976.       {
  977.      /*
  978.       * If the ATAPIIdentify fail, we send the ATAPI Reset to recover it and
  979.       * retry again. For Diamond 8x cdrom, sometimes it needs to retry many times
  980.       * until there is no error.
  981.       */
  982.         for ( num_retry = 0; num_retry < ATAPI_NUM_RETRIES; num_retry++)
  983.         {
  984.           ATAPIReset( npAT );
  985.  
  986.            /* Wait 15 seconds */
  987.  
  988.            for ( l = 0; l < ATAPI_RESET_DELAY; l++ )                                                              /*@V159438*/
  989.            {
  990.               IODelay();
  991.            }
  992.  
  993.            UnitType = ATAPIIdentify( npAT );
  994.            if (UnitType != 0xffff)
  995.              break;
  996.          } /* end of for num_retry */
  997.       }                                                               /*@V162970*/
  998.                                                                       /*AAAAAAAA*/
  999.       npACB->IRQTimeOut = OldIRQTimeOut;                              /*@V117508*/
  1000.  
  1001.       // The above has determined the default timeout in ms.        /*@V195083*/
  1002.       // Henceforth, TimeOut, is the default timeout value.         /*@V195083*/
  1003.       // IRQTimeOut can be changed with each request to an IORB     /*@V195083*/
  1004.       // requested value.                                           /*@V195083*/
  1005.       npACB->TimeOut = npACB->IRQTimeOut;                           /*@V195083*/
  1006.  
  1007.    }                                                                /*@V155162*/
  1008.  
  1009.    if( !Resume && (UnitType == UIB_TYPE_CDROM) )                    /*@V155162*/
  1010.    {                                                                /*@V155162*/
  1011.       pUI = (PUNITINFO) InitAllocate ( sizeof(UNITINFO) );
  1012.       setmem( ScratchBuf, 0, sizeof(ScratchBuf) );
  1013.       memcopy( (PVOID) pUI, (PVOID) pOldUnitInfo, sizeof(UNITINFO));
  1014.  
  1015.       pUI->FilterADDHandle = ADDHandle;
  1016.       pUI->UnitType        = UIB_TYPE_CDROM;
  1017.       pUI->UnitHandle      = (USHORT)npACB->npUCB;
  1018.       pUI->UnitFlags       = UF_REMOVABLE   | UF_CHANGELINE |
  1019.                              UF_NODASD_SUPT | UF_NOSCSI_SUPT;
  1020.  
  1021.       if ( !( rc = Issue_AllocateUnit( UnitHandle, DriverEP )) )
  1022.       {
  1023.          rc = Issue_ChangeUnitInfo( pUI, UnitHandle, DriverEP );
  1024.          if ( Issue_DeallocateUnit( UnitHandle, DriverEP ))
  1025.          {
  1026.             npAT->Flags |= ATBF_DISABLED;
  1027.          }
  1028.          else                                                       /*@V155162*/
  1029.          {                                                          /*@V155162*/
  1030.             npACB->cUnits++;
  1031.          }                                                          /*@V155162*/
  1032.       }
  1033.  
  1034.       if ( rc )
  1035.       {
  1036.          npAT->Flags |= ATBF_DISABLED;
  1037.       }
  1038.    }
  1039.    else                                                            /*@V117508*/
  1040.    {                                                               /*@V117508*/
  1041.       rc = 1;                                                      /*@V117508*/
  1042.    }                                                               /*@V117508*/
  1043.  
  1044.    ClaimUnitExit:
  1045.  
  1046.    return( rc );
  1047. }
  1048. /*
  1049. ╔══════════════════════════════════╗
  1050. ║                                  ║
  1051. ║                                  ║
  1052. ║                                  ║
  1053. ║                                  ║
  1054. ║                                  ║
  1055. ╚══════════════════════════════════╝
  1056. */
  1057. VOID FAR DriverInit( PRPINITIN  pRPH )
  1058. {
  1059.    PRPINITIN                     pRPI = (PRPINITIN)  pRPH;
  1060.    PRPINITOUT                    pRPO = (PRPINITOUT) pRPH;
  1061.    NPATBL                        npAT = AdapterTable;
  1062.    NPACB                         npACB;
  1063.    PDDD_PARM_LIST                pDDD_Parm_List;
  1064.    PMACHINE_CONFIG_INFO          pMCHI;
  1065.    USHORT                        iAdpt;
  1066.    USHORT                        iUnit;
  1067.    USHORT                        rc      = 0;
  1068.    PBYTE                         pTimerPool;
  1069.    struct DevClassTableStruc far *pDriverTable;
  1070.  
  1071.    /*┌──────────────────────────────────────────────────────┐
  1072.      │Setup DevHelp service entry point for DHCALLS library │
  1073.      └──────────────────────────────────────────────────────┘ */
  1074.    Device_Help = pRPH->DevHlpEP;
  1075.  
  1076.    //┌────────────────────────────────────────┐
  1077.    //│Put name from Config.sys in DrvrName of │
  1078.    //│the DriverStruct structure.             │
  1079.    //└────────────────────────────────────────┘
  1080.  
  1081.    RMGetDriverName (pRPI, DriverStruct.DrvrName, DrvrNameSize);
  1082.  
  1083.    /*┌────────────────────────────────────┐
  1084.      │Point to intialization vector table │
  1085.      │see h\dskinit.h for details         │
  1086.      └────────────────────────────────────┘ */
  1087.    pDDD_Parm_List = (PDDD_PARM_LIST) pRPI->InitArgs;
  1088.  
  1089.    /*┌──────────────────────────────────────────────┐
  1090.      │Transfer information from Machine Info Packet │
  1091.      └──────────────────────────────────────────────┘ */
  1092.    pMCHI = MAKEP( SELECTOROF(pDDD_Parm_List),
  1093.                                 (USHORT) pDDD_Parm_List->machine_config_table );
  1094.  
  1095.  
  1096.    MachineID = (pMCHI->Model << 8) | pMCHI->SubModel;
  1097.  
  1098.    /*┌───────────────────────────────────────────────┐ */          /*@V117508*/
  1099.    /*│If this is a uChannel machine, share interrupt │ */          /*@V117508*/
  1100.    /*└───────────────────────────────────────────────┘ */          /*@V117508*/
  1101.    if ( pMCHI->BusInfo & BUSINFO_MCA )                             /*@V117508*/
  1102.    {                                                               /*@V117508*/
  1103.      LevelInterrupt= 1;                                            /*@V117508*/
  1104.    }                                                               /*@V117508*/
  1105.  
  1106.    /*┌───────────────────────────────────────────┐
  1107.      │Check the paramters on the config.sys line │
  1108.      └───────────────────────────────────────────┘ */
  1109.    if ( ParseCmdLine( pDDD_Parm_List ) )
  1110.    {
  1111.       TTYWrite( ParmErrMsg );
  1112.    }
  1113.  
  1114.    if (!(DevHelp_AttachDD("CMD640X$",(NPBYTE)&DDTable)))
  1115.    {
  1116.       if (Verbose)
  1117.       {
  1118.          TTYWrite ("CMD640X.ADD driver found.  IBM ATAPI filter not loaded.");
  1119.       }
  1120.  
  1121.       pRPO->CodeEnd    = 0;
  1122.       pRPO->DataEnd    = 0;
  1123.       pRPO->rph.Status = STDON + STERR + ERROR_I24_QUIET_INIT_FAIL;
  1124.  
  1125.       return;
  1126.    }
  1127.  
  1128.    pTimerPool = (PBYTE) InitAllocate( TIMER_POOL_SIZE );
  1129.  
  1130.    ADD_InitTimer( pTimerPool, TIMER_POOL_SIZE );
  1131.  
  1132.    SetupADDVars();
  1133.  
  1134.    /* ┌────────────────────────────────────────────┐
  1135.       │ Find ATAPI Units that have been identified │
  1136.       │ and claim them.                            │
  1137.       └────────────────────────────────────────────┘ */
  1138.  
  1139.    GetATAPIUnits();
  1140.  
  1141.    if ( Installed )
  1142.    {
  1143.       if ( Verbose )
  1144.       {
  1145.          PrintInfo( AdapterTable );
  1146.       }
  1147.       pRPO->CodeEnd    = (USHORT) &DriverInit;
  1148.       pRPO->DataEnd    = (USHORT) &BeginInitData;
  1149.       pRPO->rph.Status = STDON;
  1150.  
  1151.    }
  1152.    else
  1153.    {
  1154.  
  1155.       ADD_DeInstallTimer();
  1156.  
  1157.       npAT = AdapterTable;
  1158.  
  1159.       if ( Verbose )
  1160.       {
  1161.          TTYWrite( UninstallMsg );
  1162.       }
  1163.  
  1164.  
  1165.       pRPO->CodeEnd    = 0;
  1166.       pRPO->DataEnd    = 0;
  1167.       pRPO->rph.Status = STDON + STERR + ERROR_I24_QUIET_INIT_FAIL;
  1168.  
  1169.    }
  1170.  
  1171. }
  1172.  
  1173. /*
  1174. ╔══════════════════════════════════╗
  1175. ║                                  ║
  1176. ║                                  ║
  1177. ║                                  ║
  1178. ║                                  ║
  1179. ║                                  ║
  1180. ╚══════════════════════════════════╝
  1181. */
  1182. VOID NEAR SetupADDVars()
  1183. {
  1184.    SELDESCINFO         SwapCodeDesc;
  1185.  
  1186.  
  1187.    /*┌───────────────────────────────┐
  1188.      │Linear Address of data segment │
  1189.      └───────────────────────────────┘ */
  1190.    (PBYTE) plDataSeg = (PBYTE) &plDataSeg;
  1191.    if ( DevHelp_VirtToLin( (SEL)   SELECTOROF(plDataSeg),
  1192.                            (ULONG) 0,
  1193.                            (PLIN)  &plDataSeg            ) )
  1194.    {
  1195.       _asm { int 3 }
  1196.    }
  1197.  
  1198.    plADDLockHandle = plDataSeg + (USHORT) &ADDLockHandle[0];
  1199.  
  1200.    /*┌───────────────────────────────────────┐
  1201.      │Linear Address of swap code and length │
  1202.      └───────────────────────────────────────┘ */
  1203.    (PBYTE) plSwapCode = (PBYTE) &StartOSM;
  1204.    if ( DevHelp_GetDescInfo( (SEL)   SELECTOROF (plSwapCode),
  1205.                              (PBYTE) &SwapCodeDesc           ) )
  1206.    {
  1207.       _asm { int 3 }
  1208.    }
  1209.  
  1210.    plSwapCode  = SwapCodeDesc.BaseAddr;
  1211.    SwapCodeLen = SwapCodeDesc.Limit + 1;
  1212.  
  1213.    /*┌──────────────────────────────────────────┐
  1214.      │Point to KERNEL Interrupt level indicator │
  1215.      └──────────────────────────────────────────┘ */
  1216.    if ( DevHelp_GetDOSVar( (USHORT) DHGETDOSV_INTERRUPTLEV,
  1217.                            (USHORT) 0,
  1218.                            (PPVOID) &pNestedIntCount             ) )
  1219.    {
  1220.       _asm { int 3 }
  1221.    }
  1222.    DevHelp_VirtToPhys( (PVOID) SenseDataBuf, (PULONG) &ppSenseDataBuf );
  1223. }
  1224.  
  1225. /*
  1226. ╔══════════════════════════════════╗
  1227. ║                                  ║
  1228. ║                                  ║
  1229. ║                                  ║
  1230. ║                                  ║
  1231. ║                                  ║
  1232. ╚══════════════════════════════════╝
  1233. */
  1234. NPBYTE FAR InitAllocate( USHORT Size )
  1235. {
  1236.    NPBYTE            p = (NPBYTE) -1;
  1237.  
  1238.    if ( Size < ACBPoolAvail )
  1239.    {
  1240.       p = (NPBYTE) npACBPool;
  1241.  
  1242.       setmem((PBYTE) npACBPool, 0, Size );
  1243.  
  1244.       npACBPool    += Size;
  1245.       ACBPoolAvail -= Size;
  1246.    }
  1247.    return( p );
  1248. }
  1249.  
  1250. /*
  1251. ╔══════════════════════════════════╗
  1252. ║                                  ║
  1253. ║                                  ║
  1254. ║                                  ║
  1255. ║                                  ║
  1256. ║                                  ║
  1257. ╚══════════════════════════════════╝
  1258. */
  1259. VOID FAR InitDeAllocate( USHORT Size )
  1260. {
  1261.    npACBPool    -= Size;
  1262.    ACBPoolAvail += Size;
  1263. }
  1264.  
  1265. /*
  1266. ╔══════════════════════════════════╗
  1267. ║                                  ║
  1268. ║                                  ║
  1269. ║                                  ║
  1270. ║                                  ║
  1271. ║                                  ║
  1272. ╚══════════════════════════════════╝
  1273. */
  1274. VOID NEAR PrintInfo( NPATBL npAT )
  1275. {
  1276.    NPACB   npACB;
  1277.    NPUCB   npUCB;
  1278.    NPUTBL  npUT;
  1279.    USHORT  i, j, k, l;
  1280.  
  1281.    TTYWrite( VersionMsg );
  1282.    for ( j = 0; j < MAX_ADAPTERS ; j++, npAT++ )
  1283.    {
  1284.       if ( !(npAT->Flags & ATBF_DISABLED) )
  1285.       {
  1286.          sprintf( (PUCHAR) StringBuffer,
  1287.                   (PUCHAR) "Controller: %1d  Base Port: %4x  "
  1288.                            "IRQ: %2x; Status = %s",
  1289.                   (USHORT) j,
  1290.                   (USHORT) npAT->BasePort,
  1291.                   (USHORT) npAT->IRQLevel,
  1292.                   (PSZ)    AdptMsgs[npAT->Status] );
  1293.  
  1294.          TTYWrite ( StringBuffer );
  1295.  
  1296.          if ( npACB = npAT->npACB )
  1297.          {
  1298.             for (i = 0; i < MAX_UNITS; i++ )
  1299.             {
  1300.                npUT = &npAT->Unit[i];
  1301.                npUCB = &npACB->UnitCB[i];
  1302.  
  1303.                if ( npUT->Status==UTS_OK )
  1304.                {
  1305.                   sprintf( (PUCHAR) StringBuffer,
  1306.                            (PUCHAR) "Unit %1d - Status = %s%s",                 /* [001] */
  1307.                            (USHORT) i,
  1308.                            (PSZ)    UnitMsgs[npUT->Status],                     /* [001] */
  1309.                            (PSZ) ((npUCB->Flags&UCBF_BM_DMA) ? " - BM DMA ON" : "")); /* [001] */
  1310.  
  1311.                   TTYWrite ( StringBuffer );
  1312.  
  1313.                   sprintf( (PUCHAR) StringBuffer,
  1314.                            (PUCHAR) "Model Number     : %s",
  1315.                            (PSZ)     npUT->ModelNum);
  1316.                   TTYWrite ( StringBuffer );
  1317.  
  1318.                   sprintf( (PUCHAR) StringBuffer,
  1319.                            (PUCHAR) "Firmware Revision: %s",
  1320.                            (PSZ)     npUT->Firmware);
  1321.                   TTYWrite ( StringBuffer );
  1322.  
  1323.                   sprintf( (PUCHAR) StringBuffer,
  1324.                            (PUCHAR) "Serial Number    : %s",
  1325.                            (PSZ)     ((npUT->Serial[0]) ? npUT->Serial : "<None>" ));
  1326.                   TTYWrite ( StringBuffer );
  1327.  
  1328.                   sprintf( StringBuffer, " " );
  1329.                   TTYWrite( StringBuffer );
  1330. //                  sprintf( (PUCHAR) StringBuffer,
  1331. //                           (PUCHAR) "BMICOM = %4.4X, BMISTA = %4.4X, BMIDTP = %4.4X\n",
  1332. //                           npACB->BMICOM,
  1333. //                           npACB->BMISTA,
  1334. //                           npACB->BMIDTP );
  1335. //                  TTYWrite( StringBuffer );
  1336. //
  1337. //                  sprintf( (PUCHAR) StringBuffer,
  1338. //                           (PUCHAR) "PRD Address = %8.8lX, PRD Count = %d\n",
  1339. //                           npACB->BMDMA_SGList, npACB->BMDMA_SGListCount );
  1340. //                  TTYWrite( StringBuffer );
  1341.                }
  1342.             }
  1343.          }
  1344.       }
  1345.    }
  1346. }
  1347.  
  1348. /*
  1349. ╔══════════════════════════════════╗
  1350. ║                                  ║
  1351. ║                                  ║
  1352. ║                                  ║
  1353. ║                                  ║
  1354. ║                                  ║
  1355. ╚══════════════════════════════════╝
  1356. */
  1357. VOID NEAR TTYWrite( PSZ Buf )
  1358. {
  1359.    InitMsg.MsgStrings[0] = Buf;
  1360.  
  1361.    DevHelp_Save_Message( (NPBYTE) &InitMsg );
  1362. }
  1363.  
  1364. /*
  1365. ╔══════════════════════════════════╗
  1366. ║                                  ║
  1367. ║                                  ║
  1368. ║                                  ║
  1369. ║                                  ║
  1370. ║                                  ║
  1371. ╚══════════════════════════════════╝
  1372. */
  1373. VOID NEAR GetATAPIUnits()
  1374. {
  1375.    NPATBL                npAT = AdapterTable;
  1376.    NPUTBL                npUT;
  1377.    NPIORB_CONFIGURATION  pIORB;
  1378.    DEVICETABLE           *pDeviceTable;
  1379.    NPADAPTERINFO         pAdapterInfo;
  1380.    UNITINFO              OldUnitInfo;
  1381.    NPACB                 npACB = 0;
  1382.    NPUCB                 npUCB;
  1383.    PRESOURCE_ENTRY       pRE;
  1384.  
  1385.    struct DevClassTableStruc far *pDriverTable;
  1386.  
  1387.    USHORT                rc, i, j, k;
  1388.    USHORT                n = 0;
  1389.  
  1390.    USHORT                UnitFlags;
  1391.    USHORT                UnitType;
  1392.    USHORT                UnitHandle;
  1393.    USHORT                DriveCount = 0;
  1394.  
  1395.    HANDLELIST            HandleList;
  1396.    PSZ                   SearchKey = SearchKeytxt;
  1397.    HADAPTER              hAdapter;
  1398.    HDRIVER               hDevice;
  1399.  
  1400.    ULONG                 PhysAddr;                                  /* [001] */
  1401.    USHORT                Port, Data;                                /* [001] */
  1402.  
  1403.    VOID                  (FAR * DriverEP) ();
  1404.  
  1405.    if ( rc = DevHelp_GetDOSVar((USHORT) DHGETDOSV_DEVICECLASSTABLE, 1,
  1406.                                (PPVOID) &pDriverTable) )
  1407.    {
  1408.       _asm { int 3 }
  1409.    }
  1410.  
  1411.    pDeviceTable = (DEVICETABLE *) ScratchBuf1;
  1412.  
  1413.    for (i = 0; i < pDriverTable->DCCount; i++)
  1414.    {
  1415.       pIORB = (NPIORB_CONFIGURATION) &InitIORB;
  1416.       pIORB->iorbh.Length = sizeof(IORB_CONFIGURATION);
  1417.       pIORB->iorbh.CommandCode = IOCC_CONFIGURATION;
  1418.       pIORB->iorbh.CommandModifier = IOCM_GET_DEVICE_TABLE;
  1419.       pIORB->iorbh.Status = 0;
  1420.       pIORB->iorbh.RequestControl = 0;
  1421.       pIORB->iorbh.NotifyAddress = 0;
  1422.       pIORB->pDeviceTable = (PVOID) ScratchBuf1;
  1423.       pIORB->DeviceTableLen = sizeof(ScratchBuf1);
  1424.  
  1425.       OFFSETOF(DriverEP) =  pDriverTable->DCTableEntries[i].DCOffset;
  1426.       SELECTOROF(DriverEP) = pDriverTable->DCTableEntries[i].DCSelector;
  1427.  
  1428.       setmem( ScratchBuf1, 0, sizeof(ScratchBuf1) );                /*@V132280*/
  1429.  
  1430.       (*DriverEP) ((PVOID)(pIORB));
  1431.  
  1432.       while ( !(pIORB->iorbh.Status & IORB_DONE) )  /* Wait till done */
  1433.          ;
  1434.  
  1435.       if (pIORB->iorbh.Status & IORB_ERROR )
  1436.          continue;                                  /* Skip to next device */
  1437.  
  1438.       for (j = 0; j < pDeviceTable->TotalAdapters; j++ )
  1439.       {
  1440.          pAdapterInfo =  pDeviceTable->pAdapter[j];
  1441.  
  1442.          for (k = 0; k < pAdapterInfo->AdapterUnits; k++)
  1443.          {
  1444.             UnitType  = pAdapterInfo->UnitInfo[k].UnitType;
  1445.             UnitHandle = pAdapterInfo->UnitInfo[k].UnitHandle;
  1446.             UnitFlags = pAdapterInfo->UnitInfo[k].UnitFlags;        /*@V155162*/
  1447.             if ( UnitType == UIB_TYPE_ATAPI )
  1448.             {
  1449.                if ( !Installed )
  1450.                {
  1451.                   Installed = TRUE;
  1452.  
  1453.                   if ( DevHelp_RegisterDeviceClass( (NPSZ)    AdapterName,
  1454.                                                     (PFN)     &ATAPIADDEntry,
  1455.                                                     (USHORT)  0,
  1456.                                                     (USHORT)  1,
  1457.                                                     (PUSHORT) &ADDHandle  ) )
  1458.                   {
  1459.                      _asm int 3
  1460.                   }
  1461.  
  1462.                   //┌────────────────────────┐
  1463.                   //│ Allocate Driver Handle │
  1464.                   //└────────────────────────┘
  1465.                   if(RMCreateDriver(&DriverStruct,
  1466.                                     &hDriver))
  1467.                   {
  1468.                      _asm int 3
  1469.                   }
  1470.                }
  1471.                if ( !npACB )
  1472.                {
  1473.                   npAT->Flags &= ~ATBF_DISABLED;
  1474.                   npACB = npAT->npACB = (NPACB) InitAllocate( sizeof(ACB) );
  1475.                   setmem((PBYTE) npACB, 0, sizeof(ACB) );
  1476.                   ACBPtrs[cAdapters].npACB = npACB;
  1477.                   npACB->IRQHandler = npAT->IRQHandler;
  1478.                   npACB->ReqFlags |= ACBR_CONFIGURE_ACB;
  1479.  
  1480.                   npACB->ResourceFlags |= ACBRF_SHARED;
  1481.  
  1482.                   pRE = (PRESOURCE_ENTRY) ScratchBuf;
  1483.                   setmem( ScratchBuf, 0, sizeof(ScratchBuf) );
  1484.  
  1485.                   if ( rc = Issue_ReportResources ( pRE, UnitHandle, DriverEP ) )
  1486.                   {
  1487.                      npAT->Flags |= ATBF_DISABLED;
  1488.                      continue; /* go to next adapter */
  1489.                   }
  1490.  
  1491.                   /* Is there an IRQ entry? */
  1492.                   /* Is there a port entry? */
  1493.  
  1494.                   if ( ( pRE->Max_Resource_Entry < RE_PORT ) ||
  1495.                        ( !pRE->cIRQ_Entries )                ||
  1496.                        ( !pRE->cPort_Entries ))
  1497.                   {
  1498.                      rc = 1;
  1499.                      npAT->Flags |= ATBF_DISABLED;
  1500.                      continue; /* go to next adapter */
  1501.                   }
  1502.  
  1503.                   npAT->BasePort = pRE->npPort_Entry->StartPort;
  1504.                   npAT->IRQLevel = pRE->npIRQ_Entry->IRQ_Value;
  1505.                   npAT->cUnits++;
  1506.                   npAT->Flags   |= ATBF_ATAPI_PRESENT;
  1507.                   npAT->Status   = ATS_OK;
  1508.  
  1509.                   /* Begin [001] Get base address for Bus Master DMA */
  1510.  
  1511.                   if ( pRE->cPort_Entries > 2 )
  1512.                   {
  1513.                      npACB->BMICOM = (pRE->npPort_Entry)[2].StartPort;
  1514.                      npACB->BMISTA = npACB->BMICOM+2;
  1515.                      npACB->BMIDTP = npACB->BMISTA+2;
  1516.  
  1517.                      npACB->Flags |= ACBF_BM_DMA;
  1518.                      /* Allocate space for scatter/gather table. Disable Bus Master DMA if */
  1519.                      /* allocation fails */
  1520.  
  1521.                      if ( !DevHelp_AllocPhys( MR_4K_LIMIT, 0, &PhysAddr ) )
  1522.                      {
  1523.                         /* Calculate useable size of scatter/gather table. Restrictions are:
  1524.                          *
  1525.                          * 1) Cannot span a 4KB boundary
  1526.                          * 2) must be ULONG aligned
  1527.                          *
  1528.                          * store resulting physical address, size in bytes of useable area,
  1529.                          * and number of descriptors permitted.
  1530.                          */
  1531.  
  1532.                         if ( (npACB->BMDMA_SGListSize = (PhysAddr & (MR_4K_LIMIT-1))) <=
  1533.                              (MR_4K_LIMIT/2) )
  1534.                         {
  1535.                            /* Larger half is before 4KB boundary */
  1536.  
  1537.                            npACB->BMDMA_SGList = (PhysAddr & ~3L); /* ULONG align it */
  1538.                            if ( PhysAddr & 3 )
  1539.                            {
  1540.                               npACB->BMDMA_SGList += 4;         /* keep in boundaries */
  1541.                            }
  1542.                            npACB->BMDMA_SGListSize = MR_4K_LIMIT - npACB->BMDMA_SGListSize;
  1543.                            npACB->BMDMA_SGListSize &= ~3L;     /* adjust size for ULONGs */
  1544.                            if ( PhysAddr & 3 )
  1545.                            {
  1546.                               npACB->BMDMA_SGListSize -= 4;     /* keep in boundaries */
  1547.                            }
  1548.                         }
  1549.                         else
  1550.                         {
  1551.                            /* larger half is after 4KB boundary */
  1552.  
  1553.                            npACB->BMDMA_SGList = (PhysAddr - npACB->BMDMA_SGListSize) + MR_4K_LIMIT;
  1554.                            npACB->BMDMA_SGListSize &= ~3L;     /* adjust size for ULONGs */
  1555.                         }
  1556.                         npACB->BMDMA_SGListCount = npACB->BMDMA_SGListSize / 8;
  1557.                      }
  1558.                      else
  1559.                      {
  1560.                         npACB->Flags &= ~ACBF_BM_DMA;
  1561.                      }
  1562.                   }
  1563.  
  1564.                   /* End [001] */
  1565.  
  1566.                   if ( npACB->ReqFlags & ACBR_CONFIGURE_ACB )
  1567.                   {
  1568.                      ConfigureACB( npAT );
  1569.                   }
  1570.  
  1571.                   npACB->SharedDriverEP         = DriverEP;
  1572.                   npACB->SharedDriverUnitHandle = UnitHandle;
  1573.                }
  1574.                else
  1575.                {
  1576.                   npAT->cUnits++;
  1577.                }
  1578.                npUT = &npAT->Unit[k];
  1579.                npUCB = npACB->npUCB = &npACB->UnitCB[k];
  1580.  
  1581.                if( UnitFlags & UF_FORCE )                           /*@V155162*/
  1582.                {                                                    /*@V155162*/
  1583.                   npUCB->Flags |= UCBF_FORCE;                       /*@V155162*/
  1584.                   if( UnitFlags & UF_NOTPRESENT )                   /*@V155162*/
  1585.                   {                                                 /*@V155162*/
  1586.                      npUCB->Flags |= UCBF_NOTPRESENT;               /*@V155162*/
  1587.                   }                                                 /*@V155162*/
  1588.                }                                                    /*@V155162*/
  1589.  
  1590.                npUCB->npACB = npACB;
  1591.                npUCB->UnitId = npACB->UnitId = k;
  1592.  
  1593.                memcopy ( (PVOID) &OldUnitInfo,
  1594.                          (PVOID) &pAdapterInfo->UnitInfo[k],
  1595.                          sizeof(UNITINFO) );
  1596.                if (ClaimUnit( npAT, FALSE, UnitHandle,              /*@V155162*/
  1597.                               (PUNITINFO)&OldUnitInfo, DriverEP ))
  1598.                {
  1599.                   npUT->Status = UTS_NOT_PRESENT;
  1600.                   npAT->cUnits--;                           /* @V132280 */
  1601.                }
  1602.                else
  1603.                {
  1604.                   npUT->Status = UTS_OK;
  1605.  
  1606.                   HandleList.cMaxHandles = 1;
  1607.  
  1608.                   SearchKey[4] = '0' + j;                           /*@V156660 - modified */
  1609.  
  1610.                   //┌───────────────────────────────────────────┐
  1611.                   //│ Find the IDE adapter in the resource tree │
  1612.                   //│ and attach a device                       │
  1613.                   //└───────────────────────────────────────────┘
  1614.  
  1615.                   if ( !(RMKeyToHandleList ( HANDLE_PHYS_TREE,
  1616.                                            SearchKey,
  1617.                                            (PHANDLELIST) &HandleList )) )
  1618.                   {
  1619.                      if ( HandleList.cHandles )
  1620.                      {
  1621.                         if ( RMCreateDevice( hDriver,
  1622.                                              &hDevice,
  1623.                                              &DevStruct,
  1624.                                              HandleList.Handles[0],
  1625.                                              NULL ))
  1626.                         {
  1627.                            _asm int 3
  1628.                         }
  1629.                      }
  1630.                   }
  1631.                   DevStruct.DevDescriptName[6] = '0' + n;  //sam
  1632.                   n++;
  1633.                }
  1634.             }
  1635.  
  1636.             /* Begin [001] */
  1637.  
  1638.             if ( npACB && npACB->Flags & ACBF_BM_DMA )
  1639.             {
  1640.                Port = npACB->BMISTA;
  1641.                inp( Port, Data );
  1642.                if ( Data & ACBX_BMISTA_D0DMA )
  1643.                  npACB->UnitCB[0].Flags |= UCBF_BM_DMA;
  1644.                if ( Data & ACBX_BMISTA_D1DMA )
  1645.                  npACB->UnitCB[1].Flags |= UCBF_BM_DMA;
  1646.             }
  1647.  
  1648.             /* End [001] */
  1649.  
  1650.          }
  1651.          if ( npACB )
  1652.          {
  1653.             npAT->Flags |= ATBF_ATAPI_PRESENT;
  1654.             cAdapters++;
  1655.             npAT++;
  1656.             npACB = 0;
  1657.          }
  1658.       }
  1659.    }
  1660. }
  1661.  
  1662.  
  1663. /*
  1664. ╔══════════════════════════════════╗
  1665. ║                                  ║
  1666. ║                                  ║
  1667. ║                                  ║
  1668. ║                                  ║
  1669. ║                                  ║
  1670. ╚══════════════════════════════════╝
  1671. */
  1672. USHORT NEAR Issue_ReportResources( PRESOURCE_ENTRY pRE,
  1673.                               USHORT UnitHandle, VOID (FAR *DriverEP)() )
  1674. {
  1675.    NPIORB_RESOURCE      npIORB;
  1676.  
  1677.    npIORB                        = (NPIORB_RESOURCE) &InitIORB;
  1678.    setmem ( (PVOID) npIORB, 0, sizeof(InitIORB) );
  1679.  
  1680.    npIORB->iorbh.Length          = sizeof(IORB_RESOURCE);
  1681.    npIORB->iorbh.UnitHandle      = UnitHandle;
  1682.    npIORB->iorbh.CommandCode     = IOCC_RESOURCE;
  1683.    npIORB->iorbh.CommandModifier = IOCM_REPORT_RESOURCES;
  1684.    npIORB->iorbh.Status          = 0;
  1685.    npIORB->iorbh.RequestControl  = 0;
  1686.    npIORB->iorbh.NotifyAddress   = 0;
  1687.    npIORB->ResourceEntryLen      = sizeof(ScratchBuf);
  1688.    npIORB->pResourceEntry        = pRE;
  1689.  
  1690.    (*DriverEP) ((PVOID)(npIORB));
  1691.    while ( !(npIORB->iorbh.Status & IORB_DONE) )  /* Wait till done */
  1692.       ;
  1693.  
  1694.    return( npIORB->iorbh.ErrorCode );
  1695.  
  1696. }
  1697.  
  1698. /*
  1699. ╔══════════════════════════════════╗
  1700. ║                                  ║
  1701. ║                                  ║
  1702. ║                                  ║
  1703. ║                                  ║
  1704. ║                                  ║
  1705. ╚══════════════════════════════════╝
  1706. */
  1707. USHORT NEAR Issue_AllocateUnit( USHORT UnitHandle, VOID (FAR *DriverEP)() )
  1708. {
  1709.    NPIORB_UNIT_CONTROL   npIORB;
  1710.    PUCHAR                pWSFlags; /* work space flags */
  1711.  
  1712.    npIORB                        = (NPIORB_UNIT_CONTROL) &InitIORB;
  1713.    pWSFlags = (PUCHAR) npIORB->iorbh.DMWorkSpace;
  1714.    setmem ( (PVOID) npIORB, 0, sizeof(InitIORB) );
  1715.  
  1716.    npIORB->iorbh.Length          = sizeof(IORB_UNIT_CONTROL);
  1717.    npIORB->iorbh.UnitHandle      = UnitHandle;
  1718.    npIORB->iorbh.CommandCode     = IOCC_UNIT_CONTROL;
  1719.    npIORB->iorbh.CommandModifier = IOCM_ALLOCATE_UNIT;
  1720.    npIORB->iorbh.Status          = 0;
  1721.    npIORB->iorbh.RequestControl  = IORB_ASYNC_POST;
  1722.    npIORB->iorbh.NotifyAddress   = NotifyIORBDone;                  /*@V153151*/
  1723.  
  1724.    (*DriverEP) ((PVOID)(npIORB));
  1725.  
  1726.    DISABLE
  1727.    *pWSFlags |= WSF_PROC_BLOCK;
  1728.  
  1729.    while( !(npIORB->iorbh.Status & IORB_DONE) )
  1730.    {
  1731.       DevHelp_ProcBlock( (ULONG) npIORB, 100, WAIT_IS_INTERRUPTABLE );
  1732.       DISABLE
  1733.    }
  1734.  
  1735.    ENABLE
  1736.  
  1737.    return( npIORB->iorbh.ErrorCode );
  1738.  
  1739. }
  1740.  
  1741. /*
  1742. ╔══════════════════════════════════╗
  1743. ║                                  ║
  1744. ║                                  ║
  1745. ║                                  ║
  1746. ║                                  ║
  1747. ║                                  ║
  1748. ╚══════════════════════════════════╝
  1749. */
  1750. USHORT NEAR Issue_DeallocateUnit( USHORT UnitHandle, VOID (FAR *DriverEP)() )
  1751. {
  1752.    NPIORB_UNIT_CONTROL      npIORB;
  1753.  
  1754.    npIORB                        = (NPIORB_UNIT_CONTROL) &InitIORB;
  1755.    setmem ( (PVOID) npIORB, 0, sizeof(InitIORB) );
  1756.  
  1757.    npIORB->iorbh.Length          = sizeof(IORB_UNIT_CONTROL);
  1758.    npIORB->iorbh.UnitHandle      = UnitHandle;
  1759.    npIORB->iorbh.CommandCode     = IOCC_UNIT_CONTROL;
  1760.    npIORB->iorbh.CommandModifier = IOCM_DEALLOCATE_UNIT;
  1761.    npIORB->iorbh.Status          = 0;
  1762.    npIORB->iorbh.RequestControl  = 0;
  1763.    npIORB->iorbh.NotifyAddress   = 0;
  1764.  
  1765.    (*DriverEP) ((PVOID)(npIORB));
  1766.    while ( !(npIORB->iorbh.Status & IORB_DONE) )  /* Wait till done */
  1767.       ;
  1768.  
  1769.    return( npIORB->iorbh.ErrorCode );
  1770.  
  1771. }
  1772.  
  1773. /*
  1774. ╔══════════════════════════════════╗
  1775. ║                                  ║
  1776. ║                                  ║
  1777. ║                                  ║
  1778. ║                                  ║
  1779. ║                                  ║
  1780. ╚══════════════════════════════════╝
  1781. */
  1782. USHORT NEAR Issue_ChangeUnitInfo( PUNITINFO pUI, USHORT UnitHandle,
  1783.                                    VOID (FAR *DriverEP)() )
  1784. {
  1785.    NPIORB_UNIT_CONTROL  npIORB;
  1786.  
  1787.    npIORB                        = (NPIORB_UNIT_CONTROL) &InitIORB;
  1788.    setmem ( (PVOID) npIORB, 0, sizeof(InitIORB) );
  1789.  
  1790.    npIORB->iorbh.Length          = sizeof(IORB_UNIT_CONTROL);
  1791.    npIORB->iorbh.UnitHandle      = UnitHandle;
  1792.    npIORB->iorbh.CommandCode     = IOCC_UNIT_CONTROL;
  1793.    npIORB->iorbh.CommandModifier = IOCM_CHANGE_UNITINFO;
  1794.    npIORB->iorbh.Status          = 0;
  1795.    npIORB->iorbh.RequestControl  = 0;
  1796.    npIORB->iorbh.NotifyAddress   = 0;
  1797.    npIORB->UnitInfoLen           = sizeof(ScratchBuf);
  1798.    npIORB->pUnitInfo             = pUI;
  1799.  
  1800.    (*DriverEP) ((PVOID)(npIORB));
  1801.    while ( !(npIORB->iorbh.Status & IORB_DONE) )  /* Wait unil done */
  1802.       ;
  1803.  
  1804.    return( npIORB->iorbh.ErrorCode );
  1805. }
  1806.  
  1807.  
  1808. /*
  1809. ╔══════════════════════════════════╗
  1810. ║                                  ║
  1811. ║                                  ║
  1812. ║                                  ║
  1813. ║                                  ║
  1814. ║                                  ║
  1815. ╚══════════════════════════════════╝
  1816. */
  1817. VOID NEAR ConfigureACB( NPATBL npAT )
  1818. {
  1819.    NPACB       npACB;
  1820.    UCHAR       i;
  1821.  
  1822.    npACB = npAT->npACB;
  1823.  
  1824.    for (i = FI_PDATA; i < FI_PDEVCON; i++ )
  1825.    {
  1826.       npACB->IOPorts[i] = npAT->BasePort + i;
  1827.       npACB->IORegs[i]  = 0;
  1828.    }
  1829.    /*┌───────────────────────────────────────────────────────────┐
  1830.      │ Error Register and Feature Register have the same address │
  1831.      └───────────────────────────────────────────────────────────┘*/
  1832.    npACB->IOPorts[FI_PERROR]  = npACB->IOPorts[FI_PFEATURE];
  1833.  
  1834.    /*┌────────────────────────────────────────────────────────────┐
  1835.      │ Status Register and Command Register have the same address │
  1836.      └────────────────────────────────────────────────────────────┘*/
  1837.    npACB->IOPorts[FI_PSTATUS] = npACB->IOPorts[FI_PCMD];
  1838.  
  1839.    npACB->IOPorts[FI_PDEVCON] = npACB->IOPorts[FI_PDRVSLCT] | 0x300;
  1840.  
  1841.    npACB->IORegs[FI_PDEVCON] = DEFAULT_ATAPI_DEVCON_REG;
  1842.  
  1843.    npACB->IRQLevel   = npAT->IRQLevel;
  1844.    npACB->IRQHandler = npAT->IRQHandler;
  1845.  
  1846.    npACB->TimeOut              = IRQ_TIMEOUT_LENGTH;                 /*@V117508*/
  1847.    npACB->IRQTimeOut           = INIT_TIMEOUT_LONG;
  1848.    npACB->DelayedResetInterval = DELAYED_RESET_INTERVAL;
  1849.  
  1850.    npACB->InternalCmd.IOSGPtrs.iPortAddress =npACB->IOPorts[FI_PDATA];
  1851.    npACB->ExternalCmd.IOSGPtrs.iPortAddress =npACB->IOPorts[FI_PDATA];
  1852.    npACB->npCmdIO = &npACB->ExternalCmd;
  1853.  
  1854.    npACB->ReqFlags &= ~ACBR_CONFIGURE_ACB;
  1855.  
  1856.    if ( npAT->Flags & ATBF_SHARED_ADAPTER )
  1857.    {
  1858.       npACB->ResourceFlags |= ACBRF_SHARED;
  1859.       npACB->suspended = 1;
  1860.    }
  1861.    else
  1862.    {
  1863.       npACB->suspended = 0;
  1864.    }
  1865. }
  1866.  
  1867.  
  1868. /*
  1869. ╔══════════════════════════════════╗
  1870. ║                                  ║
  1871. ║                                  ║
  1872. ║                                  ║
  1873. ║                                  ║
  1874. ║                                  ║
  1875. ╚══════════════════════════════════╝
  1876. */
  1877. USHORT NEAR ParseCmdLine( PDDD_PARM_LIST pADDParms )
  1878. {
  1879.    PSZ           pCmdLine;
  1880.    PSZ           pCurrChar;
  1881.    USHORT        LtoUval = 'a' - 'A';
  1882.    USHORT        rc = 0;
  1883.  
  1884.    pCmdLine = MAKEP( SELECTOROF(pADDParms),
  1885.                      (USHORT)   pADDParms->cmd_line_args );
  1886.  
  1887.  
  1888.    for ( pCurrChar = pCmdLine; *pCurrChar; pCurrChar++ )
  1889.    {
  1890.       /* Convert from lower case to upper case */
  1891.       if ( *pCurrChar >= 'a' && *pCurrChar <= 'z' )
  1892.          *pCurrChar = *pCurrChar - LtoUval;
  1893.  
  1894.       if ( *pCurrChar == '/')
  1895.       {
  1896.          pCurrChar++;
  1897.          if ( (*pCurrChar == 'V') || (*pCurrChar == 'v') )
  1898.          {
  1899.             Verbose = TRUE;
  1900.          }
  1901.          else
  1902.          {
  1903.                 if ( *pCurrChar == 'F')                                 /*@V151168*/
  1904.                 {                                                       /*@V151168*/
  1905.                     Force = 1;                                           /*@V151168*/
  1906.                     AdaptersForced =     1;                                /*@V151168*/
  1907.                 }                                                       /*@V151168*/
  1908.                 else                                                    /*@V151168*/
  1909.                 {                                                       /*@V151168*/
  1910.                     rc = 1;
  1911.                 break;
  1912.                 }                                                       /*@V151168*/
  1913.          }
  1914.       }
  1915.    }
  1916.    return( rc );
  1917. }
  1918. /*------------------------------------*/                                      /*@V162970*/
  1919. /*                                    */                                      /*@VVVVVVV*/
  1920. /*                                    */
  1921. /*                                    */
  1922. /*------------------------------------*/
  1923. USHORT NEAR ATAPIReset(  NPATBL npAT )
  1924. {
  1925.    NPACB             npACB = npAT->npACB;
  1926.    USHORT rc = 0;
  1927.    USHORT Data;
  1928.    USHORT Port;
  1929.    USHORT i;
  1930.    USHORT            UnitId;
  1931.  
  1932.    UnitId = npACB->npUCB->UnitId;
  1933.  
  1934.    SelectUnit( npACB, UnitId );
  1935.  
  1936.    Data = FX_SOFTRESET;
  1937.    Port = npACB->IOPorts[FI_PCMD];
  1938.    outp( Port, Data );
  1939.  
  1940.    for ( i=0; i<8; i++ )
  1941.    {
  1942.       rc = CheckReady( npACB );
  1943.       if ( !rc )
  1944.       {
  1945.          break;
  1946.       }
  1947.    }
  1948.  
  1949.    return( rc );                                                        /*@AAAAAAA*/
  1950. }                                                                       /*@V162979*/
  1951.  
  1952.  
  1953.  
  1954.