home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cdrom.zip / DDK / BASE / SRC / DEV / DASD / CDROM / OS2CDROM / cdstrat1.c < prev    next >
C/C++ Source or Header  |  1996-06-18  |  60KB  |  1,786 lines

  1. /**************************************************************************
  2.  *
  3.  * SOURCE FILE NAME = CDSTRAT1.C
  4.  *
  5.  * DESCRIPTIVE NAME = Strategy 1 interface for OS/2 CDROM Device Manager
  6.  *
  7.  * Copyright : COPYRIGHT IBM CORPORATION, 1991, 1992
  8.  *             LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
  9.  *             REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
  10.  *             RESTRICTED MATERIALS OF IBM
  11.  *             IBM CONFIDENTIAL
  12.  *
  13.  * VERSION = V2.0
  14.  *
  15.  * DATE
  16.  *
  17.  * DESCRIPTION
  18.  *
  19.  *
  20.  * FUNCTIONS   Provides validation and routing of Strategy 1 requests
  21.  *             received from the OS/2 Kernel.
  22.  *
  23.  * ENTRY POINTS:
  24.  *
  25.  * DEPENDENCIES:
  26.  *
  27.  * NOTES
  28.  *
  29.  *
  30.  * STRUCTURES
  31.  *
  32.  * EXTERNAL REFERENCES
  33.  *
  34.  * EXTERNAL FUNCTIONS
  35.  *
  36.  * CHANGE ACTIVITY =
  37.  *  DATE      FLAG       DEFECT  CHANGE DESCRIPTION
  38.  *  --------  --------   ------  --------------------------------------
  39.  *  08/22/94  @V91985    91985   1) Mask errors for reads of sector 0 length 1
  40.  *                               from the kernel.  2) Pause while trying to
  41.  *                               access a not ready device.  3) Allow ATAPI
  42.  *                               devices to return lock status from device.
  43.  *  09/04/94  @V96674    96674   Change the fix for defect 91985 to: If the
  44.  *                               file system is attempting to read sector 0 and
  45.  *                               it fails, attempt to read the volume descriptor
  46.  *                               at sector 16 and return the error generated if
  47.  *                               any.  This will allow mounting of XAS disks but
  48.  *                               will also return the sector not found for audio
  49.  *                               discs at the earliest read.
  50.  *  09/08/95  @V135221           Sam Detweiler - CD-ROM changer support
  51.  *  11/15/95  @V132783           Fix trap while booting with CDI disk
  52.  *  11/15/95  @V142227           Fix read error on video CD after reading
  53.  *                               multisession CD.
  54.  *  04/23/96  @V151345           Breakup requests greater than 64K-1 to ATAPI
  55.  *                               devices
  56.  *  05/28/96  @V156096           Sam Detweiler - HP update
  57.  ****************************************************************************/
  58.  
  59.  
  60. #include "cdh.h"
  61.  
  62. USHORT NonSCSI_GetLastSessionAddr (NPUNITCB, ULONG FAR *);
  63.  
  64.  
  65. CMDFUNC functable[]=                                                    //SD@135221
  66. {                          /*--------------------------------------*/   //SD@135221
  67.   {CD_DriveInit,   TRUE }, /* 0x00  initialize                     */   //SD@135221
  68.   {CD_MediaCheck,  FALSE}, /* 0x01  check the media                */   //SD@135221
  69.   {CD_BuildBPB,    TRUE,}, /* 0x02  build BPB                      */   //SD@135221
  70.   {CmdErr,         TRUE }, /* 0x03  reserved                       */   //SD@135221
  71.   {CD_Read,        FALSE}, /* 0x04  read                           */   //SD@135221
  72.   {CmdErr,         TRUE }, /* 0x05  non-destructive read           */   //SD@135221
  73.   {CmdErr,         TRUE }, /* 0x06  input status                   */   //SD@135221
  74.   {CmdErr,         TRUE }, /* 0x07  input flush                    */   //SD@135221
  75.   {WriteErr,       TRUE }, /* 0x08  write                          */   //SD@135221
  76.   {WriteVErr,      TRUE }, /* 0x09  write with verify              */   //SD@135221
  77.   {CmdErr,         TRUE }, /* 0x0A  get output status              */   //SD@135221
  78.   {CmdErr,         TRUE }, /* 0x0B  flush output                   */   //SD@135221
  79.   {CmdErr,         TRUE }, /* 0x0C  reserved                       */   //SD@135221
  80.   {StatusComplete, TRUE }, /* 0x0D  open                           */   //SD@135221
  81.   {StatusComplete, TRUE }, /* 0x0E  close                          */   //SD@135221
  82.   {RemovableMedia, TRUE }, /* 0x0F  removable media                */   //SD@135221
  83.   {DriveGenIOCTL,  TRUE},  /* 0x10  generic IOCTL                  */   //SD@135221
  84.   {ResetMedia,     FALSE}, /* 0x11  reset uncertain media          */   //SD@135221
  85.   {GetLogDriveMap, TRUE }, /* 0x12  get Logical Drive Map          */   //SD@135221
  86.   {SetLogDriveMap, TRUE }, /* 0x13  set Logical Drive Map          */   //SD@135221
  87.   {CmdErr,         TRUE }, /* 0x14  de-Install this device         */   //SD@135221
  88.   {CmdErr,         TRUE }, /* 0x15  reserved                       */   //SD@135221
  89.   {PartFixedDisks, TRUE }, /* 0x16  get number of partitions       */   //SD@135221
  90.   {GetUnitMap,     TRUE }, /* 0x17  get unit map                   */   //SD@135221
  91.   {CD_Read,        FALSE}, /* 0x18  no caching read                */   //SD@135221
  92.   {WriteErr,       TRUE }, /* 0x19  no caching write               */   //SD@135221
  93.   {WriteVErr,      TRUE }, /* 0x1A  no caching write/verify        */   //SD@135221
  94.   {CD_DriveInit,   TRUE }, /* 0x1B  initialize                     */   //SD@135221
  95.   {StatusComplete, TRUE }, /* 0x1C  prepare for shutdown           */   //SD@135221
  96.   {CmdErr,         TRUE }, /* 0x1D  Get Driver Capabilities        */   //SD@135221
  97. };                    /*--------------------------------------*/        //SD@135221
  98.  
  99.  
  100. /****************************************************************************
  101.  *
  102.  * FUNCTION NAME = CD_Strat1
  103.  *
  104.  * DESCRIPTION   = OS2CDROM strategy 1 routine
  105.  *
  106.  * INPUT         = ES:BX     - pointer to Request Packet
  107.  *
  108.  * OUTPUT        =
  109.  *
  110.  * RETURN-NORMAL =
  111.  *
  112.  * RETURN-ERROR  =
  113.  *
  114.  ****************************************************************************/
  115.  
  116. void near CD_Strat1(pRPH)
  117.  
  118. PRPH pRPH;
  119. {
  120.   NPUNITCB      pUnitCB;
  121.   USHORT        Cmd, Status;
  122.  
  123.  
  124.   pRPH->Status = 0;
  125.   pRPH->Flags = 0;
  126.  
  127.   Cmd = pRPH->Cmd;
  128.  
  129.   /*
  130.   ** Filter out invalid requests
  131.   */
  132. /*
  133. **if (DDFlags & DDF_NO_MEDIA)
  134. **{
  135. **    Status = STDON + STERR + ERROR_I24_BAD_UNIT;
  136. **    goto ExitDiskDD;
  137. **}
  138. */
  139.   if (Cmd > MAX_DISKDD_CMD)
  140.   {
  141.      Status = STDON + STERR + ERROR_I24_BAD_COMMAND;
  142.      goto  ExitDiskDD;
  143.   }
  144.  
  145.   if ( (Get_UnitCB_Addr(pRPH->Unit, (NPUNITCB FAR *) &pUnitCB) != NO_ERROR) &&
  146.                      (Cmd != CMDInitBase) &&
  147.                      (Cmd != CMDInit) &&
  148.                      (Cmd != CMDPartfixeddisks) )
  149.   {
  150.       Status = STDON + STERR + ERROR_I24_BAD_UNIT;
  151.       goto ExitDiskDD;
  152.   }
  153.  
  154. /*
  155. **if ( (Cmd != CMDInitBase) && IsTraceOn() )
  156. **      Trace(TRACE_STRAT1 | TRACE_ENTRY, (PBYTE) pRPH, pUnitCB);
  157. */
  158.  
  159.   /*
  160.   ** Call Worker Routine
  161.   */
  162.   if((CDFlags & CDF_INIT_COMPLETE) &&                                   //SD@135221
  163.     (pUnitCB->DeviceInfo.Audio.capabilities & (DCAPS_CARTRIDGE_CHANGER |DCAPS_INDIVIDUAL_CHANGER)))//SD@135221
  164.     {                                                                   //SD@135221
  165.     // only ATAPI devices support this flag today                       //SD@135221
  166.     if(pUnitCB->pParentUnitCB)                                          //SD@135221
  167.       {                                                                 //SD@135221
  168.       // serialize here                                                 //SD@135221
  169.       #define SEM_INDEFINITE_WAIT ((ULONG)(-1L))                        //SD@135221
  170.       DevHelp_SemRequest((ULONG)(&pUnitCB->pParentUnitCB->Semaphore),SEM_INDEFINITE_WAIT);//SD@135221
  171.       // if we have a parent, and the active slot is not ours           //SD@135221
  172.       if(!(pUnitCB->DeviceInfo.Audio.capabilities & DCAPS_SINGLE_MODE)) //SD@135221
  173.         {                                                               //SD@135221
  174.         if(pUnitCB->pParentUnitCB && (pUnitCB->pParentUnitCB->DeviceInfo.Slots.Current!=pUnitCB->DeviceInfo.Slot))//SD@135221
  175.           {                                                             //SD@135221
  176.           // load cd for requested Unit, may fail (no disk etc)         //SD@135221
  177.           Status = MakeSlotActive(pUnitCB,(UCHAR)pUnitCB->DeviceInfo.Slot);//SD@135221
  178.           if(Status!=STDON && functable[Cmd].ChangerAllowed==TRUE)      //SD@135221
  179.             {                                                           //SD@135221
  180.             Status=STDON;                                               //SD@135221
  181.             } /* endif */                                               //SD@135221
  182.           }                                                             //SD@135221
  183.         else                                                            //SD@135221
  184.           {                                                             //SD@135221
  185.           Status=STDON;                                                 //SD@135221
  186.           }                                                             //SD@135221
  187.         } /* endif */                                                   //SD@135221
  188.       else                                                              //SD@135221
  189.         {                                                               //SD@135221
  190.         Status=STDON;                                                   //SD@135221
  191.         }                                                               //SD@135221
  192.       // if slot is now active one                                      //SD@135221
  193.       if(Status==STDON)                                                 //SD@135221
  194.         {                                                               //SD@135221
  195.         Status = (*functable[Cmd].Strat1Near)(pRPH, pUnitCB);           //SD@135221
  196.         } /* endif */                                                   //SD@135221
  197.       // deserialize here                                               //SD@135221
  198.       DevHelp_SemClear((ULONG)(&pUnitCB->pParentUnitCB->Semaphore));    //SD@135221
  199.       } /* endif */                                                     //SD@135221
  200.     } /* endif */                                                       //SD@135221
  201.   else                                                                  //SD@135221
  202.     Status = (*functable[Cmd].Strat1Near)(pRPH, pUnitCB);
  203.  
  204.   /*
  205.   ** Finish up by setting the Status word in the Request Packet Header
  206.   */
  207.  
  208. ExitDiskDD:  ;
  209.  
  210.   DISABLE;
  211.  
  212.   pRPH->Status = Status;                  /* Save status in Request Packet */
  213.  
  214.   ENABLE;
  215.  
  216. /*
  217. **if ( (TraceFlags != 0) && (pRPH->Status & STDON) && (Cmd != CMDInitBase) )
  218. **   Trace(TRACE_STRAT1 | TRACE_EXIT, (PBYTE) pRPH, pVolCB);
  219. */
  220.  
  221. }
  222.  
  223.  
  224. /****************************************************************************
  225.  *
  226.  * FUNCTION NAME = CD_MediaCheck
  227.  *
  228.  * DESCRIPTION   = Check the Media    (Command = 0x01)
  229.  *
  230.  *       Checks to see if the media in the drive has changed.
  231.  *
  232.  *       USHORT CD_MediaCheck   (PRP_MEDIACHECK pRP, NPUNITCB pUnitCB)
  233.  *
  234.  *       EFFECTS:  The Return Code in the Request Packet is set to one
  235.  *                 of the following:
  236.  *
  237.  *                     -1 = Media has been changed
  238.  *                      0 = Unsure if media has been changed
  239.  *                      1 = Media unchanged
  240.  *
  241.  * INPUT         = pRP              - Request Packet
  242.  *                 pUnitCB          - Pointer to UnitCB
  243.  *
  244.  * OUTPUT        = USHORT           - Packet Status word
  245.  *
  246.  * RETURN-NORMAL =
  247.  * RETURN-ERROR  =
  248.  *
  249.  ****************************************************************************/
  250.  
  251. USHORT NEAR CD_MediaCheck(pRP, pUnitCB)
  252.  
  253. PRP_MEDIACHECK    pRP;
  254. NPUNITCB          pUnitCB;
  255. {
  256.    USHORT rc;
  257.    USHORT cTries;                                                    /*V@91985*/
  258.    NPIORB pIORB;
  259.    BOOL   playing;                                                   //SD@135221
  260.  
  261.    if (pUnitCB->Flags & UCF_UNCERTAIN_MEDIA)
  262.    {
  263.       pRP->rc = -1;
  264.       return(STDON);
  265.    }
  266.  
  267.    if (pUnitCB->DeviceInfo.playing==FALSE &&                         //SD@135221
  268.       (pUnitCB->pParentUnitCB && pUnitCB->pParentUnitCB->DeviceInfo.Parentplaying))//SD@135221
  269.    {                                                                 //SD@135221
  270.       rc = GetPlayStatus(pUnitCB, &playing);                         //SD@135221
  271.                                                                      //SD@135221
  272.       if ( (rc == STDON) && playing)                                 //SD@135221
  273.       {                                                              //SD@135221
  274.          return(STDON + STERR + ERROR_I24_DEVICE_IN_USE);            //SD@135221
  275.       }                                                              //SD@135221
  276.    }                                                                 //SD@135221
  277.  
  278.    BuildCDB_TestUnitReady (pUnitCB, (NPIORB_CDB FAR *) &pIORB);
  279.  
  280.    rc = SubmitIORB_Wait (pUnitCB, pIORB);
  281.  
  282.    if(pIORB->Status & IORB_ERROR)
  283.      {
  284.  
  285.    if ( ((NPIORB_CDB)pIORB)->sense_data.additional_sense_code !=     /*@V91985*/
  286.                              ASC_MEDIUM_NOT_PRESENT )                /*@V91985*/
  287.    {                                                                 /*@V91985*/
  288.       if(pUnitCB->DeviceInfo.Audio.capabilities & (DCAPS_CARTRIDGE_CHANGER |DCAPS_INDIVIDUAL_CHANGER))//SD@135221
  289.         {                                                             //SD@135221
  290.         if(pUnitCB->DeviceInfo.product_id_code==TORISAN_C3G)          //SD@135221
  291.           {                                                           //SD@135221
  292.           UCHAR asc,ascq;                                             //SD@135221
  293.           asc=((NPIORB_CDB)pIORB)->sense_data.additional_sense_code;  //SD@135221
  294.           ascq=((NPIORB_CDB)pIORB)->sense_data.additional_sense_code_qualifier;//SD@135221
  295.           if(asc==ASC_MEDIUM_CHANGED && ascq==0)                      //SD@135221
  296.             {                                                         //SD@135221
  297.             // only ATAPI devices support this flag today             //SD@135221
  298.             // load cd for requested Unit, may fail (no disk etc)     //SD@135221
  299.             if(pUnitCB->DeviceInfo.Audio.capabilities & DCAPS_SINGLE_MODE)//SD@135221
  300.               {                                                           //SD@135221
  301.               MakeSlotActive(pUnitCB,(UCHAR)pUnitCB->pParentUnitCB->DeviceInfo.Slots.Current);//SD@135221
  302.               } /* endif */                                           //SD@135221
  303.             else                                                      //SD@135221
  304.               {                                                       //SD@135221
  305.               MakeSlotActive(pUnitCB,(UCHAR)pUnitCB->DeviceInfo.Slot);//SD@135221
  306.               } /* endelse */                                         //SD@135221
  307.             } /* endif */                                             //SD@135221
  308.           } /* endif */                                               //SD@135221
  309.         }                                                             //SD@135221
  310.       cTries = 0;                                                    /*@V91985*/
  311.       while ( (((NPIORB_CDB)pIORB)->sense_data.sense_key ==          /*@V91985*/
  312.                                             SCSI_SK_NOTRDY )         /*@V91985*/
  313.               && (cTries++ < MAX_NOT_READY_RETRIES ))                /*@V91985*/
  314.       {                                                              /*@V91985*/
  315.          FreeIORB (pUnitCB, (NPIORB_CDB) pIORB);                     /*@V91985*/
  316.          DevHelp_ProcBlock( (ULONG) pIORB, NOT_READY_WAIT,           /*@V91985*/
  317.                                     WAIT_IS_INTERRUPTABLE );         /*@V91985*/
  318.          BuildCDB_TestUnitReady (pUnitCB,                            /*@V91985*/
  319.                                  (NPIORB_CDB FAR *) &pIORB);         /*@V91985*/
  320.          rc = SubmitIORB_Wait (pUnitCB, pIORB);                      /*@V91985*/
  321.       }                                                              /*@V91985*/
  322.    }                                                                 /*@V91985*/
  323.      } /* endif */
  324.  
  325.    pRP->rc = ! (pUnitCB->Flags & UCF_UNCERTAIN_MEDIA);
  326.  
  327.    FreeIORB (pUnitCB, (NPIORB_CDB) pIORB);
  328.  
  329.    return(rc);
  330.  
  331. }
  332.  
  333.  
  334. /****************************************************************************
  335.  *
  336.  * FUNCTION NAME = CD_BuildBPB
  337.  *
  338.  * DESCRIPTION   = Build the BPB      (Command = 0x02)
  339.  *
  340.  *       Builds the BPB.  This is requested when the media has changed
  341.  *       of when the media type is uncertain.
  342.  *
  343.  *       USHORT BuildBPB   (PRP_BUILDBPB pRP, NPUNITCB pUnitCB)
  344.  *
  345.  * INPUT         = pRP              - Request Packet
  346.  *                 pUnitCB          - Pointer to UnitCB
  347.  *
  348.  * OUTPUT        = USHORT           - Packet status word
  349.  *
  350.  * RETURN-NORMAL =
  351.  * RETURN-ERROR  =
  352.  *
  353.  ****************************************************************************/
  354.  
  355. USHORT NEAR CD_BuildBPB(pRP, pUnitCB)
  356. PRP_BUILDBPB   pRP;
  357. NPUNITCB       pUnitCB;
  358. {
  359.    USHORT rc;
  360.    ULONG  volume_size;
  361.  
  362.    if ( (rc = GetVolumeSize (pUnitCB, (ULONG FAR *) &volume_size)) & STERR)
  363.       return(rc);
  364.  
  365.    DefaultBPB.BigTotalSectors = volume_size;
  366.  
  367.    pRP->bpb = (PVOID) &(DefaultBPB);
  368.  
  369.    return (rc);
  370. }
  371.  
  372.  
  373. /****************************************************************************
  374.  *
  375.  * FUNCTION NAME = CD_Read
  376.  *
  377.  * DESCRIPTION   = Read Command  (Command 0x04)
  378.  *
  379.  *         This is the basic strategy-1 I/O read routine for the driver.
  380.  *         The request is queued and sent to the adapter driver for
  381.  *         processing.
  382.  *
  383.  *         USHORT CD_Read   (PRP_RWV pRP, NPUNITCB pUnitCB)
  384.  *
  385.  * INPUT         = pRP              - Request Packet
  386.  *                 pUnitCB          - Pointer to UnitCB
  387.  *
  388.  * OUTPUT        = USHORT           - Packet Status word
  389.  *
  390.  * RETURN-NORMAL =
  391.  * RETURN-ERROR  =
  392.  *
  393.  ****************************************************************************/
  394.  
  395. USHORT CD_Read (pRP, pUnitCB)
  396.  
  397. PRP_RWV   pRP;
  398. NPUNITCB  pUnitCB;
  399. {
  400.    USHORT rc, disk_density;
  401.    ULONG  EndSector;
  402.    NPIORB_DMWORK pDMWork;
  403.    BOOL   playing,
  404.           MountDrive = FALSE;                                        /*@V91985*/
  405.    PULONG pBuff;                                                     /*@V91985*/
  406.    PULONG i;                                                         /*@V96674*/
  407.    USHORT ModeFlag;                                                  /*@V91985*/
  408.    NPIORB_CDB pIORB = 0, pModeIORB = 0;
  409.  
  410.    /*
  411.    ** Check for valid input parms
  412.    */
  413.    if (pRP->NumSectors == 0)
  414.       return (STDON);
  415. /*
  416. ** if ((pRP->rba + pRP->NumSectors) > pUnitCB->TotalSectors)
  417. **    return (STDON + STERR + ERROR_I24_SECTOR_NOT_FOUND);
  418. */
  419.    /*
  420.    ** Check for uncertain media
  421.    */
  422.    if (pUnitCB->Flags & UCF_UNCERTAIN_MEDIA)
  423.    {
  424.       pRP->NumSectors = 0;
  425.       return(STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA);
  426.    }
  427.  
  428.    /*
  429.    ** Cant read when unit is playing so check play status
  430.    */
  431.    if (pUnitCB->DeviceInfo.playing ||                           //SD@135221
  432.       (pUnitCB->pParentUnitCB && pUnitCB->pParentUnitCB->DeviceInfo.Parentplaying))//SD@135221
  433.    {                                                            //SD@135221
  434.       rc = GetPlayStatus(pUnitCB, &playing);
  435.  
  436.       if ( (rc == STDON) && playing)
  437.       {
  438.          pRP->NumSectors = 0;
  439.          return(STDON + STERR + ERROR_I24_DEVICE_IN_USE);
  440.       }
  441.    }                                                            //SD@135221
  442.  
  443.    /*
  444.    ** If multisession photo CD mounted and the target read is one of the
  445.    ** Volume Descriptor Sectors, then remap the RBA to the last session
  446.    */
  447.    if ( (pUnitCB->DeviceInfo.Audio.capabilities & DCAPS_MULTISESSION) &&
  448.         (pUnitCB->DeviceInfo.Audio.capabilities & DCAPS_MULTISESSION_MOUNTED) &&
  449.         (pRP->rba >= PRIMARY_VOL_DESCR_RBA) &&
  450.         (pRP->rba <= pUnitCB->DeviceInfo.volume_descr_terminator) )
  451.    {
  452.       pRP->rba = pRP->rba + pUnitCB->DeviceInfo.last_session_addr;
  453.    }
  454.  
  455.    /*                                                                  @V91985
  456.    ** Determine if the File System is attempting to mount the Drive.   @V91985
  457.    */                                                                /*@V91985*/
  458.                                                                      /*@V91985*/
  459.    if ( (pRP->rba == 0) &&                                           /*@V91985*/
  460.         (pRP->NumSectors == 1) )                                     /*@V91985*/
  461.    {                                                                 /*@V91985*/
  462.       if ( DevHelp_PhysToVirt( (ULONG) pRP->XferAddr,                /*@V91985*/
  463.                                (USHORT) 2048,                        /*@V96674*/
  464.                                (PVOID)  &pBuff,                      /*@V91985*/
  465.                                (PUSHORT) &ModeFlag   ) )             /*@V91985*/
  466.       {                                                              /*@V91985*/
  467.          _asm {int 3}                                                /*@V91985*/
  468.       }                                                              /*@V91985*/
  469.                                                                      /*@V91985*/
  470.       if (*pBuff == 0x544f4f42l) /* Boot Signature */                /*@V91985*/
  471.       {                                                              /*@V91985*/
  472.          MountDrive = TRUE;                                          /*@V91985*/
  473.       }                                                              /*@V91985*/
  474.    }                                                                 /*@V91985*/
  475.  
  476.  
  477.    /*
  478.    ** Toshiba 3301 & 3401 is vendor unique since we must make sure the
  479.    ** density code is set properly.
  480.    */
  481.    switch (pUnitCB->DeviceInfo.product_id_code)
  482.    {
  483.       case TOSHIBA_3301:
  484.       case TOSHIBA_3401:
  485.          rc = Tosh_Read_2048(pUnitCB, pRP->rba, pRP->NumSectors, pRP->XferAddr);
  486.          break;
  487.  
  488.  
  489.       default:
  490.  
  491.          if  ( (pUnitCB->DeviceInfo.current_block_size != 2048) &&
  492.                (pUnitCB->DeviceInfo.interface_type != INTERFACE_ATAPI) )
  493.  
  494.          {
  495.             rc = ChainModeSelectRead (pUnitCB, pRP->rba, pRP->NumSectors,
  496.                                                pRP->XferAddr, 2048, 0);
  497.          }
  498.          else
  499.          {
  500.             rc = ReadSector (pUnitCB, pRP->rba, pRP->NumSectors,
  501.                                                 pRP->XferAddr, 2048);
  502.          }
  503.    }
  504.  
  505.    /*
  506.    ** Sony 561 can't read 2048 byte Mode 2 Form 2 XA sectors with the
  507.    ** Read 6 command. We must issue the Read CD-XA command.
  508.    */
  509.    if ( (pUnitCB->DeviceInfo.product_id_code == SONY_561) &&
  510.         (rc == STDON + STERR + ERROR_I24_SECTOR_NOT_FOUND) )
  511.    {
  512.         rc = Sony_Read_2048(pUnitCB, pRP->rba, pRP->NumSectors, pRP->XferAddr);
  513.    }
  514.  
  515.    /*
  516.    ** If reading sector 0 on an NEC SCSI drive and it's an XA disk then change
  517.    ** the density code to XA, and reissue the read.
  518.    */
  519.    if ( (rc == STDON + STERR + ERROR_I24_READ_FAULT) &&
  520.         (pUnitCB->DeviceInfo.vendor_id_code == NEC) &&
  521.         (pUnitCB->DeviceInfo.interface_type == INTERFACE_SCSI) &&
  522.         (pRP->rba == 0) )
  523.    {
  524.       rc = ChainModeSelectRead (pUnitCB, pRP->rba, pRP->NumSectors,
  525.                                              pRP->XferAddr, 2048, 0x81);
  526.    }
  527.  
  528.    if (rc & STERR)
  529.       pRP->NumSectors = 0;
  530.  
  531.    if (rc == STDON + STERR + ERROR_I24_BAD_COMMAND)
  532.       rc = STDON + STERR + ERROR_I24_SECTOR_NOT_FOUND;
  533.  
  534.    /*
  535.    ** If we are mounting the volume, then check for multi-session disk
  536.    */
  537.    if ( (MountDrive) &&                                                 /*@142227*/
  538.         (pUnitCB->DeviceInfo.Audio.capabilities & DCAPS_MULTISESSION) ) /*@142227*/
  539.  
  540.    {
  541.       Check_MultiSession_Mounted(pUnitCB, pRP->XferAddr);
  542.    }
  543.  
  544.  
  545.    /*                                                                  @V91985
  546.    ** If the File System is attempting to mount the drive, and there   @V91985
  547.    ** was an error that was not a drive ready error, give the error    @V91985
  548.    ** (if any) from a read of the volumne descriptor.                  @V91985
  549.    ** Clear the buffer if the read was successful.                     @V91985
  550.    */                                                                /*@V91985*/
  551.                                                                      /*@V91985*/
  552.    if (MountDrive &&     // Atempting to mount a disc                /*@V96674*/
  553.       (rc != STDON) &&   // An error was encountered                 /*@V96674*/
  554.       (rc != STDON + STERR + ERROR_I24_NOT_READY) &&                 /*@V91985*/
  555.       (rc != STDON + STERR + ERROR_I24_DISK_CHANGE) &&               /*@V91985*/
  556.       (rc != STDON + STERR + ERROR_I24_UNCERTAIN_MEDIA) )            /*@V91985*/
  557.       {                                                              /*@V91985*/
  558.          if ((rc = ReadSector(        pUnitCB,                       /*@V96674*/
  559.                               (ULONG) PRIMARY_VOL_DESCR_RBA,         /*@V96674*/
  560.                                       1,                             /*@V96674*/
  561.                                       pRP->XferAddr,                 /*@V96674*/
  562.                                       2048)) == STDON )              /*@V96674*/
  563.  
  564.          {
  565.  
  566.             if ( DevHelp_PhysToVirt( (ULONG) pRP->XferAddr,          /*@V132783*/
  567.                                      (USHORT) 2048,                  /*@V132783*/
  568.                                      (PVOID)  &pBuff,                /*@V132783*/
  569.                                      (PUSHORT) &ModeFlag   ) )       /*@V132783*/
  570.             {                                                        /*@V132783*/
  571.                _asm {int 3}                                          /*@V132783*/
  572.             }                                                        /*@V132783*/
  573.                                                                      /*@V91985*/
  574.             /* zero out buffer (512 ULONGS = 2048 bytes) */
  575.             for (i=pBuff; i<pBuff+512; i++ )                         /*@V96674*/
  576.             {                                                        /*@V96674*/
  577.                *i = 0l;                                              /*@V96674*/
  578.             }                                                        /*@V96674*/
  579.  
  580.          } /* if rc=ReadSector */                                    /*@V96674*/
  581.       }                                                              /*@V91985*/
  582.  
  583.    return(rc);
  584. }
  585.  
  586.  
  587. /****************************************************************************
  588.  *
  589.  * FUNCTION NAME = RemovableMedia
  590.  *
  591.  * DESCRIPTION   = Check for Removable Media    (Command = 0x0F)
  592.  *
  593.  *        USHORT RemovableMedia (PRPH pRPH, NPUNITCB pUnitCB)
  594.  *
  595.  *        EFFECTS:  The busy bit of the status word is set as follows:
  596.  *
  597.  *                       1 = Media is non-removable
  598.  *                       0 = Media is removable
  599.  *
  600.  * INPUT         = pRPH             - Request Packet Header
  601.  *                 pUnitCB          - Pointer to UnitCB
  602.  *
  603.  * OUTPUT        = USHORT           - Packet Status word
  604.  *
  605.  * RETURN-NORMAL =
  606.  * RETURN-ERROR  =
  607.  *
  608.  ****************************************************************************/
  609.  
  610. USHORT RemovableMedia(pRPH, pUnitCB)
  611.  
  612. PRPH     pRPH;
  613. NPUNITCB pUnitCB;
  614. {
  615.    if (pUnitCB->UnitInfo.UnitFlags & UF_REMOVABLE)
  616.       return (STDON);
  617.    else
  618.       return (STDON + STBUI);
  619. }
  620.  
  621.  
  622.  
  623. /****************************************************************************
  624.  *
  625.  * FUNCTION NAME = ResetMedia
  626.  *
  627.  * DESCRIPTION   = Reset Uncertain Media  (Command = 0x11)
  628.  *
  629.  *                 USHORT ResetMedia (PRPH pRPH, NPUNITCB pUnitCB)
  630.  *
  631.  * INPUT         = pRPH             - Request Packet Header
  632.  *                 pUnitCB          - Pointer to UnitCB
  633.  *
  634.  * OUTPUT        = USHORT           - Packet Status word
  635.  *
  636.  * RETURN-NORMAL =
  637.  * RETURN-ERROR  =
  638.  *
  639.  ****************************************************************************/
  640.  
  641. USHORT ResetMedia (pRPH, pUnitCB)
  642.  
  643. PRPH     pRPH;
  644. NPUNITCB pUnitCB;
  645. {
  646.    USHORT rc;
  647.    BOOL playing;                                                //SD@135221
  648.  
  649.    if (pUnitCB->pParentUnitCB &&                                //SD@135221
  650.        pUnitCB->pParentUnitCB->DeviceInfo.Parentplaying)        //SD@135221
  651.    {                                                            //SD@135221
  652.       rc = GetPlayStatus(pUnitCB, &playing);                    //SD@135221
  653.                                                                 //SD@135221
  654.       if ( (rc == STDON) && playing)                            //SD@135221
  655.       {                                                         //SD@135221
  656.          return(STDON + STERR + ERROR_I24_DEVICE_IN_USE);       //SD@135221
  657.       }                                                         //SD@135221
  658.    }                                                            //SD@135221
  659.    pUnitCB->Flags &= ~UCF_UNCERTAIN_MEDIA;
  660.  
  661.    /*
  662.    ** Issue a Mode Select to set default density code to CD-ROM
  663.    ** and default block size to 2048 bytes.
  664.    */
  665.    if (!( pUnitCB->DeviceInfo.interface_type == INTERFACE_ATAPI ))
  666.       rc = Submit_ModeSelect (pUnitCB, CD_DENSITY_DEFAULT, 2048);
  667.  
  668.    return (STDON);
  669. }
  670.  
  671.  
  672. /****************************************************************************
  673.  *
  674.  * FUNCTION NAME = GetLogDriveMap
  675.  *
  676.  * DESCRIPTION   = Get Logical Drive Mapping  (Command = 0x12)
  677.  *
  678.  *        Returns which logical drive is currently mapped onto a particular
  679.  *        physical drive.  A zero is returned if only one logical drive is
  680.  *        mapped to the physical drive.
  681.  *
  682.  *        USHORT GetLogDriveMap (PRPH pRPH, NPUNITCB pUnitCB)
  683.  *
  684.  *        EFFECTS: The logical drive is returned in the unit field
  685.  *                 of the request packet header.  The logical drive
  686.  *                 is actually LogDriveNum + 1, which represents the
  687.  *                 drive letter, i.e. C: = 3.  A zero is returned
  688.  *                 if only one logical drive is mapped to the physical drive.
  689.  *
  690.  * INPUT         = pRPH             - Request Packet Header
  691.  *                 pUnitCB          - Pointer to UnitCB
  692.  *
  693.  * OUTPUT        = USHORT           - Packet Status word
  694.  *
  695.  * RETURN-NORMAL =
  696.  * RETURN-ERROR  =
  697.  *
  698.  ****************************************************************************/
  699.  
  700. USHORT GetLogDriveMap (pRPH, pUnitCB)
  701.  
  702. PRPH     pRPH;
  703. NPUNITCB pUnitCB;
  704. {
  705.  
  706.    pRPH->Unit = 0;                             /* ret 0 if one drive mapped */
  707.  
  708.    return (STDON);
  709.  
  710. }
  711.  
  712.  
  713. /****************************************************************************
  714.  *
  715.  * FUNCTION NAME = SetLogDriveMap
  716.  *
  717.  * DESCRIPTION   = Set Logical Drive Mapping  (Command = 0x13)
  718.  *
  719.  *         Maps the specified logical drive onto the physical drive.
  720.  *
  721.  *         USHORT SetLogDriveMap (PRPH pRPH, NPVOLCB pVolCB)
  722.  *
  723.  *         EFFECTS: The logical drive is returned in the unit field
  724.  *                  of the request packet header.  The logical drive
  725.  *                  is actually LogDriveNum + 1, which represents the
  726.  *                  drive letter, i.e. C: = 3.  A zero is returned
  727.  *                  if only one logical drive is mapped to the physical drive.
  728.  *
  729.  * INPUT         = pRPH             - Request Packet Header
  730.  *                 pUnitCB          - Pointer to UnitCB
  731.  *
  732.  * OUTPUT        = USHORT           - Packet Status word
  733.  *
  734.  * RETURN-NORMAL =
  735.  * RETURN-ERROR  =
  736.  *
  737.  ****************************************************************************/
  738.  
  739. USHORT SetLogDriveMap (pRPH, pUnitCB)
  740.  
  741. PRPH     pRPH;
  742. NPUNITCB pUnitCB;
  743.  
  744. {
  745.    pRPH->Unit = 0;                            /* only 1 drive can be mapped */
  746.  
  747.    return (STDON);
  748. }
  749.  
  750.  
  751. /****************************************************************************
  752.  *
  753.  * FUNCTION NAME = PartFixedDisks
  754.  *
  755.  * DESCRIPTION   = Get number of fixed disks  (Command = 0x16)
  756.  *
  757.  *        Returns the number of fixed disks supported by the driver.
  758.  *
  759.  *        USHORT PartFixedDisks (PRP_PARTFIXEDDISKS pRP, NPUNITCB pUnitCB)
  760.  *
  761.  * INPUT         = pRP              - Request Packet
  762.  *                 pUnitCB          - Pointer to UnitCB
  763.  *
  764.  * OUTPUT        = USHORT           - Packet Status word
  765.  *
  766.  * RETURN-NORMAL =
  767.  * RETURN-ERROR  =
  768.  *
  769.  ****************************************************************************/
  770.  
  771. USHORT PartFixedDisks (pRP, pUnitCB)
  772.  
  773. PRP_PARTFIXEDDISKS  pRP;
  774. NPUNITCB            pUnitCB;
  775. {
  776.    pRP->NumFixedDisks = 0;
  777.  
  778.    return (STDON);
  779. }
  780.  
  781.  
  782. /****************************************************************************
  783.  *
  784.  * FUNCTION NAME = GetUnitMap
  785.  *
  786.  * DESCRIPTION   = Get logical units mapped to a physical unit (Command = 0x17)
  787.  *
  788.  *        This command is only supported for disk media.
  789.  *
  790.  *        USHORT GetUnitMap (PRP_GETUNITMAP pRP, NPUNITCB pUnitCB)
  791.  *
  792.  * INPUT         = pRP              - Request Packet
  793.  *                 pUnitCB          - Pointer to UnitCB
  794.  *
  795.  * OUTPUT        = USHORT           - Packet Status word
  796.  *
  797.  * RETURN-NORMAL =
  798.  * RETURN-ERROR  =
  799.  *
  800.  ****************************************************************************/
  801.  
  802. USHORT GetUnitMap (pRP, pUnitCB)
  803.  
  804. PRP_GETUNITMAP  pRP;
  805. NPUNITCB        pUnitCB;
  806. {
  807.  
  808.    pRP->UnitMap = 0;                                     /* No units mapped */
  809.  
  810.    return (STDON);
  811. }
  812.  
  813.  
  814.  
  815. /*
  816. ** Near Entry Point to swappable IOCTL routine.
  817. */
  818.  
  819. /****************************************************************************
  820.  *
  821.  * FUNCTION NAME = DriveGenIOCTL
  822.  *
  823.  * DESCRIPTION   =
  824.  *
  825.  * INPUT         = pRP              - Request Packet
  826.  *                 pUnitCB          - Pointer to UnitCB
  827.  *
  828.  * OUTPUT        = USHORT           - Packet Status word
  829.  *
  830.  * RETURN-NORMAL =
  831.  * RETURN-ERROR  =
  832.  *
  833.  ****************************************************************************/
  834.  
  835. USHORT DriveGenIOCTL(pRP, pUnitCB)
  836.  
  837. PRP_GENIOCTL pRP;
  838. NPUNITCB     pUnitCB;
  839. {
  840.   USHORT rc;
  841.  
  842.   rc = f_CD_DriveGenIOCTL (pRP, pUnitCB);
  843.  
  844.   rc |= STDON;
  845.  
  846.   return(rc);
  847. }
  848.  
  849.  
  850. /*
  851. **   Packet Status return functions:
  852. **
  853. **   CmdErr, StatusError, StatusDevReady, StatusComplete
  854. */
  855.  
  856. /****************************************************************************
  857.  *
  858.  * FUNCTION NAME = CmdErr
  859.  *
  860.  * DESCRIPTION   =
  861.  *
  862.  * INPUT         = pRPH             - Request Packet Header
  863.  *                 pUnitCB          - Pointer to UnitCB
  864.  *
  865.  * OUTPUT        = USHORT           - Packet Status word
  866.  *
  867.  * RETURN-NORMAL =
  868.  * RETURN-ERROR  =
  869.  *
  870.  ****************************************************************************/
  871.  
  872. USHORT near CmdErr (pRPH, pUnitCB)
  873. PRPH     pRPH;
  874. NPUNITCB pUnitCB;
  875. {
  876.    return (STERR + STDON + ERROR_I24_BAD_COMMAND);
  877. }
  878.  
  879.  
  880. /****************************************************************************
  881.  *
  882.  * FUNCTION NAME = WriteErr
  883.  *
  884.  * DESCRIPTION   =
  885.  *
  886.  * INPUT         = pRPH             - Request Packet Header
  887.  *                 pUnitCB          - Pointer to UnitCB
  888.  *
  889.  * OUTPUT        = USHORT           - Packet Status word
  890.  *
  891.  * RETURN-NORMAL =
  892.  * RETURN-ERROR  =
  893.  *
  894.  ****************************************************************************/
  895.  
  896. USHORT near WriteErr (pRPH, pUnitCB)
  897. PRPH     pRPH;
  898. NPUNITCB pUnitCB;
  899. {
  900.    return (STERR + STDON + ERROR_I24_WRITE_FAULT);
  901. }
  902.  
  903.  
  904. /****************************************************************************
  905.  *
  906.  * FUNCTION NAME = WriteVErr
  907.  *
  908.  * DESCRIPTION   =
  909.  *
  910.  * INPUT         = pRPH             - Request Packet Header
  911.  *                 pUnitCB          - Pointer to UnitCB
  912.  *
  913.  * OUTPUT        = USHORT           - Packet Status word
  914.  *
  915.  * RETURN-NORMAL =
  916.  * RETURN-ERROR  =
  917.  *
  918.  ****************************************************************************/
  919.  
  920. USHORT near WriteVErr (pRPH, pUnitCB)
  921. PRPH     pRPH;
  922. NPUNITCB pUnitCB;
  923. {
  924.    return (STERR + STDON + ERROR_I24_WRITE_FAULT);
  925. }
  926.  
  927.  
  928. /****************************************************************************
  929.  *
  930.  * FUNCTION NAME = StatusDevReady
  931.  *
  932.  * DESCRIPTION   =
  933.  *
  934.  * INPUT         = pRPH             - Request Packet Header
  935.  *                 pUnitCB          - Pointer to UnitCB
  936.  *
  937.  * OUTPUT        = USHORT           - Packet Status word
  938.  *
  939.  * RETURN-NORMAL =
  940.  * RETURN-ERROR  =
  941.  *
  942.  ****************************************************************************/
  943.  
  944. USHORT StatusDevReady(pRPH, pUnitCB)
  945. PRPH     pRPH;
  946. NPUNITCB pUnitCB;
  947. {
  948.   return (STDON + STBUI);
  949. }
  950.  
  951.  
  952. /****************************************************************************
  953.  *
  954.  * FUNCTION NAME = StatusComplete
  955.  *
  956.  * DESCRIPTION   =
  957.  *
  958.  * INPUT         = pRPH             - Request Packet Header
  959.  *                 pUnitCB          - Pointer to UnitCB
  960.  *
  961.  * OUTPUT        = USHORT           - Packet Status word
  962.  *
  963.  * RETURN-NORMAL =
  964.  * RETURN-ERROR  =
  965.  *
  966.  ****************************************************************************/
  967.  
  968. USHORT StatusComplete(pRPH, pUnitCB)
  969. PRPH     pRPH;
  970. NPUNITCB pUnitCB;
  971. {
  972.   return (STDON);
  973. }
  974.  
  975.  
  976. /****************************************************************************
  977.  *
  978.  * FUNCTION NAME = StatusError
  979.  *
  980.  * DESCRIPTION   =
  981.  *
  982.  * INPUT         = pRPH             - Request Packet Header
  983.  *                 ErrorCode        - Error Code
  984.  *
  985.  * OUTPUT        = USHORT           - Packet Status word
  986.  *
  987.  * RETURN-NORMAL =
  988.  * RETURN-ERROR  =
  989.  *
  990.  ****************************************************************************/
  991.  
  992. USHORT StatusError( pRPH, ErrorCode )
  993.  
  994. PRPH    pRPH;
  995. USHORT  ErrorCode;
  996. {
  997.   return (STDON + STERR);
  998. }
  999.  
  1000.  
  1001. /****************************************************************************
  1002.  *
  1003.  * FUNCTION NAME = ChainModeSelectRead
  1004.  *
  1005.  * DESCRIPTION   = Chain Mode Select and Read Commands
  1006.  *
  1007.  *         USHORT ChainModeSelectRead (NPUNITCB pUnitCB, ULONG LBA,
  1008.  *                                     USHORT transfer_count, ULONG ppDataBuff,
  1009.  *                                     USHORT block_length, USHORT density)
  1010.  *
  1011.  * INPUT         = pUnitCB          - Pointer to UnitCB
  1012.  *                 LBA              - LBA
  1013.  *                 transfer_count   - count of sectors to transfer
  1014.  *                 ppDataBuff       - phys addr of data buffer
  1015.  *                 block_length     - block_length
  1016.  *                 density          - density code
  1017.  *
  1018.  * OUTPUT        = USHORT           - Packet Status word
  1019.  *
  1020.  * NOTES:  This routine should not be called for an ATAPI device since
  1021.  *         ATAPI drives do not support Mode Selects for density codes
  1022.  *         and block lengths.
  1023.  *
  1024.  * RETURN-NORMAL =
  1025.  * RETURN-ERROR  =
  1026.  *
  1027.  ****************************************************************************/
  1028.  
  1029. USHORT ChainModeSelectRead (pUnitCB, LBA, transfer_count, ppDataBuff,
  1030.                                           block_length, density)
  1031.  
  1032. NPUNITCB pUnitCB;
  1033. ULONG    LBA;
  1034. USHORT   transfer_count;
  1035. ULONG    ppDataBuff;
  1036. USHORT   block_length;
  1037. USHORT   density;
  1038.  
  1039. {
  1040.    USHORT rc;
  1041.  
  1042.    NPIORB_CDB pIORB = 0, pModeIORB = 0;
  1043.    NPIORB_DMWORK pDMWork;
  1044.  
  1045.    BuildCDB_ModeSelect (pUnitCB, density, block_length,
  1046.                                     (NPIORB_CDB FAR *) &pModeIORB);
  1047.  
  1048.    /*
  1049.    ** If transfer count < 255 sectors, issue Read (6) else issue Read (10)
  1050.    */
  1051.    if (transfer_count <= 255)
  1052.    {
  1053.       BuildCDB_Read_6  (pUnitCB, LBA, block_length,
  1054.                                   transfer_count, ppDataBuff,
  1055.                                   (NPIORB_CDB FAR *) &pIORB);
  1056.    }
  1057.    else
  1058.    {
  1059.       BuildCDB_Read_10 (pUnitCB, LBA, block_length,
  1060.                                  transfer_count, ppDataBuff,
  1061.                                  (NPIORB_CDB FAR *) &pIORB);
  1062.    }
  1063.  
  1064.    pDMWork = (NPIORB_DMWORK) &(pModeIORB->apt.iorbh.DMWorkSpace);
  1065.    pDMWork->pCoReqIORB = (NPIORB) pIORB;
  1066.  
  1067.    QueueIORB (pUnitCB, pModeIORB);
  1068.  
  1069.    rc = SubmitIORB_Wait(pUnitCB, pIORB);
  1070.  
  1071.    if ( !(pModeIORB->apt.iorbh.Status & IORB_ERROR) )
  1072.    {
  1073.       pUnitCB->DeviceInfo.current_density = density;
  1074.       pUnitCB->DeviceInfo.current_block_size = block_length;
  1075.  
  1076.    }
  1077.  
  1078.    FreeIORB (pUnitCB, pModeIORB);
  1079.    FreeIORB (pUnitCB, pIORB);
  1080.  
  1081.    return(rc);
  1082. }
  1083.  
  1084.  
  1085. /****************************************************************************
  1086.  *
  1087.  * FUNCTION NAME = ReadSector
  1088.  *
  1089.  * DESCRIPTION   = Issue Read Command
  1090.  *
  1091.  *        USHORT ReadSector (NPUNITCB pUnitCB, ULONG LBA,
  1092.  *                           USHORT transfer_count, ULONG ppDataBuff,
  1093.  *                           USHORT block_length)
  1094.  *
  1095.  * INPUT         = pUnitCB          - Pointer to UnitCB
  1096.  *                 LBA              - LBA
  1097.  *                 transfer_count   - count of sectors to transfer
  1098.  *                 ppDataBuff       - phys addr of data buffer
  1099.  *                 block_length     - block_length
  1100.  *
  1101.  * OUTPUT        = USHORT           - Packet Status word
  1102.  *
  1103.  * RETURN-NORMAL =
  1104.  * RETURN-ERROR  =
  1105.  *
  1106.  ****************************************************************************/
  1107.  
  1108. USHORT ReadSector (pUnitCB, LBA, transfer_count, ppDataBuff, block_length)
  1109.  
  1110. NPUNITCB pUnitCB;
  1111. ULONG    LBA;
  1112. USHORT   transfer_count;
  1113. ULONG    ppDataBuff;
  1114. USHORT   block_length;
  1115.  
  1116. {
  1117.    USHORT rc;
  1118.    NPIORB_CDB pIORB = 0;
  1119.    ULONG      nBytesRem;                                            /*@151345*/
  1120.    USHORT     partialBlockCount;                                    /*@151345*/
  1121.  
  1122.    /*
  1123.    ** If transfer count < 255 sectors, issue Read (6) else issue Read (10)
  1124.    ** ATAPI drives only support Read 10.
  1125.    */
  1126.    if ( (transfer_count <= 255) &&
  1127.         (pUnitCB->DeviceInfo.interface_type != INTERFACE_ATAPI) )
  1128.    {
  1129.       BuildCDB_Read_6 (pUnitCB, LBA, block_length,
  1130.                        transfer_count, ppDataBuff,
  1131.                        (NPIORB_CDB FAR *) &pIORB);
  1132.       rc = SubmitIORB_Wait(pUnitCB, pIORB);                         /*@151345*/
  1133.       FreeIORB (pUnitCB, pIORB);                                    /*@151345*/
  1134.    }
  1135.    else
  1136.    {
  1137.       nBytesRem = (ULONG)transfer_count * block_length;             /*@151345*/
  1138.       while( nBytesRem > 0 )                                        /*@151345*/
  1139.       {                                                             /*@151345*/
  1140.          if( nBytesRem > CDATAPI_LIMIT_64K )                        /*@151345*/
  1141.          {                                                          /*@151345*/
  1142.             /* Limit to blocks which fit in 64K */                  /*@151345*/
  1143.             partialBlockCount = CDATAPI_LIMIT_64K / block_length;   /*@151345*/
  1144.          }                                                          /*@151345*/
  1145.          else                                                       /*@151345*/
  1146.          {                                                          /*@151345*/
  1147.             /* Do the last partial read */                          /*@151345*/
  1148.             partialBlockCount = nBytesRem / block_length;           /*@151345*/
  1149.          }                                                          /*@151345*/
  1150.                                                                     /*@151345*/
  1151.          BuildCDB_Read_10 (pUnitCB, LBA, block_length,
  1152.                            partialBlockCount, ppDataBuff,           /*@151345*/
  1153.                            (NPIORB_CDB FAR *) &pIORB);
  1154.          rc = SubmitIORB_Wait(pUnitCB, pIORB);
  1155.          FreeIORB (pUnitCB, pIORB);
  1156.  
  1157.          /*                                                           @151345
  1158.          ** Adjust the buffer pointers for more requests.             @151345
  1159.          */                                                         /*@151345*/
  1160.          LBA += partialBlockCount;                                  /*@151345*/
  1161.          ppDataBuff += partialBlockCount * block_length;            /*@151345*/
  1162.          nBytesRem -= (ULONG)partialBlockCount * block_length;      /*@151345*/
  1163.       }
  1164.    }
  1165.  
  1166.  
  1167.    return(rc);
  1168. }
  1169.  
  1170.  
  1171. /****************************************************************************
  1172.  *
  1173.  * FUNCTION NAME = GetVolumeSize
  1174.  *
  1175.  * DESCRIPTION   = Get volume size
  1176.  *
  1177.  *       Return the volume size of the current CD
  1178.  *
  1179.  *       USHORT GetVolumeSize  (NPUNITCB pUnitCB, ULONG FAR * volume_size)
  1180.  *
  1181.  * INPUT         = pUnitCB          - Pointer to UnitCB
  1182.  *                 volume_size      - Pointer to return volume size
  1183.  *
  1184.  * OUTPUT        = USHORT           - Packet status word
  1185.  *
  1186.  * RETURN-NORMAL =
  1187.  * RETURN-ERROR  =
  1188.  *
  1189.  ****************************************************************************/
  1190.  
  1191. USHORT GetVolumeSize (pUnitCB, volume_size)
  1192.  
  1193. NPUNITCB  pUnitCB;
  1194. ULONG FAR * volume_size;
  1195.  
  1196. {
  1197.    USHORT rc;
  1198.    NPIORB_CDB pIORB;
  1199.    BOOL playing;                                         //SD@135221
  1200.  
  1201.    struct ReadCapacity_Data NEAR *pCDBData;
  1202.    union  ULONGB  ul_volume;
  1203.  
  1204.    if (pUnitCB->DeviceInfo.playing==FALSE &&             //SD@135221
  1205.       (pUnitCB->pParentUnitCB && pUnitCB->pParentUnitCB->DeviceInfo.Parentplaying))//SD@135221
  1206.    {                                                     //SD@135221
  1207.       rc = GetPlayStatus(pUnitCB, &playing);             //SD@135221
  1208.                                                          //SD@135221
  1209.       if ( (rc == STDON) && playing)                     //SD@135221
  1210.       {                                                  //SD@135221
  1211.          return(STDON + STERR + ERROR_I24_DEVICE_IN_USE);//SD@135221
  1212.       }
  1213.    }
  1214.  
  1215.    BuildCDB_ReadCapacity(pUnitCB, (NPIORB_CDB FAR *) &pIORB);
  1216.  
  1217.    pCDBData = (struct ReadCapacity_Data NEAR *) pIORB->CDB_data;
  1218.  
  1219.    rc = SubmitIORB_Wait(pUnitCB, pIORB);
  1220.  
  1221.    if (rc == STDON)
  1222.    {
  1223.       ul_volume.ulbytes.byte_3  =  pCDBData->capacity_LBA.ulbytes.byte_0;
  1224.       ul_volume.ulbytes.byte_2  =  pCDBData->capacity_LBA.ulbytes.byte_1;
  1225.       ul_volume.ulbytes.byte_1  =  pCDBData->capacity_LBA.ulbytes.byte_2;
  1226.       ul_volume.ulbytes.byte_0  =  pCDBData->capacity_LBA.ulbytes.byte_3;
  1227.  
  1228.       *volume_size = ul_volume.dword;
  1229.    }
  1230.    else if (rc == STDON + STERR + ERROR_I24_INVALID_PARAMETER)
  1231.       ul_volume.dword = 270000L;
  1232.  
  1233.  
  1234.    FreeIORB (pUnitCB, pIORB);
  1235.  
  1236.    return(rc);
  1237. }
  1238.  
  1239.  
  1240. /****************************************************************************
  1241.  *
  1242.  * FUNCTION NAME = ClearCheckCondition
  1243.  *
  1244.  * DESCRIPTION   = Clear check condition and return error code
  1245.  *
  1246.  *                 USHORT ClearCheckCondition  (NPUNITCB pUnitCB)
  1247.  *
  1248.  * INPUT         = pUnitCB          - Pointer to UnitCB
  1249.  *
  1250.  * OUTPUT        = USHORT           - Packet status word
  1251.  *
  1252.  * RETURN-NORMAL =
  1253.  * RETURN-ERROR  =
  1254.  *
  1255.  ****************************************************************************/
  1256.  
  1257. USHORT ClearCheckCondition (pUnitCB)
  1258.  
  1259. NPUNITCB pUnitCB;
  1260. {
  1261.    ULONG  volume_size;
  1262.  
  1263.    return(GetVolumeSize (pUnitCB, (ULONG FAR *) &volume_size) );
  1264. }
  1265.  
  1266.  
  1267. /****************************************************************************
  1268.  *
  1269.  * FUNCTION NAME = GetSectorMode
  1270.  *
  1271.  * DESCRIPTION   = Get mode for sector zero.
  1272.  *
  1273.  *       This routine returns the mode of sector zero by reading the header.
  1274.  *
  1275.  *       USHORT GetSectorMode  (NPUNITCB pUnitCB, USHORT FAR * mode)
  1276.  *
  1277.  * INPUT         = pUnitCB          - Pointer to UnitCB
  1278.  *                 mode             - mode
  1279.  *
  1280.  * OUTPUT        = USHORT           - Packet status word
  1281.  *
  1282.  * RETURN-NORMAL =
  1283.  * RETURN-ERROR  =
  1284.  *
  1285.  ****************************************************************************/
  1286.  
  1287. USHORT GetSectorMode (pUnitCB, mode)
  1288.  
  1289. NPUNITCB pUnitCB;
  1290. USHORT   FAR *mode;
  1291.  
  1292. {
  1293.    USHORT rc;
  1294.    NPIORB_CDB pIORB;
  1295.    struct ReadHeader_Data NEAR *pCDBData;
  1296.  
  1297.  
  1298.    BuildCDB_ReadHeader(pUnitCB, 0, (NPIORB_CDB FAR *) &pIORB);
  1299.  
  1300.    pCDBData = (struct ReadHeader_Data NEAR *) pIORB->CDB_data;
  1301.  
  1302.    rc = SubmitIORB_Wait(pUnitCB, pIORB);
  1303.  
  1304.    if (rc == STDON)
  1305.    {
  1306.       *mode = pCDBData->cdrom_data_mode;
  1307.    }
  1308.  
  1309.    FreeIORB (pUnitCB, pIORB);
  1310.    return (rc);
  1311. }
  1312.  
  1313.  
  1314. /****************************************************************************
  1315.  *
  1316.  * FUNCTION NAME = Check_MultiSession_Mounted
  1317.  *
  1318.  * DESCRIPTION   = Check if multisession mounted
  1319.  *
  1320.  *      This routine checks to see if a multisession photoCD disk is mounted.
  1321.  *      If it is, then the driver reads the volume descriptors until the
  1322.  *      volume descriptor terminator is found.  All subsequent reads from
  1323.  *      the Primary Volume Descriptor till the Volume Descriptor Terminator
  1324.  *      are mapped to the last session prior to the read.  This routine is
  1325.  *      only called if the multi_session_support bit is set in the UnitCB.
  1326.  *
  1327.  *      USHORT Check_MultiSession_Mounted  (NPUNITCB pUnitCB, ULONG physaddr)
  1328.  *
  1329.  * INPUT         = pUnitCB          - Pointer to UnitCB
  1330.  *                 physaddr         - physical address of I/O buffer
  1331.  *
  1332.  * OUTPUT        = USHORT           - Packet status word
  1333.  *
  1334.  * RETURN-NORMAL =
  1335.  * RETURN-ERROR  =
  1336.  *
  1337.  ****************************************************************************/
  1338.  
  1339. USHORT Check_MultiSession_Mounted (pUnitCB, physaddr)
  1340.  
  1341. NPUNITCB pUnitCB;
  1342. ULONG    physaddr;
  1343.  
  1344. {
  1345.    USHORT rc, n, mode_flag;
  1346.    ULONG session_addr;
  1347.    PBYTE pBuffer;
  1348.  
  1349.    BOOL term_found = FALSE;
  1350.  
  1351.    /*
  1352.    ** Initialize to not multisession disk
  1353.    */
  1354.    pUnitCB->DeviceInfo.Audio.capabilities &= ~DCAPS_MULTISESSION_MOUNTED;
  1355.    pUnitCB->DeviceInfo.last_session_addr = 0;
  1356.    pUnitCB->DeviceInfo.volume_descr_terminator = 0;
  1357.  
  1358.    switch (pUnitCB->DeviceInfo.product_id_code)
  1359.    {
  1360.       case TOSHIBA_3401:
  1361.          rc = Tosh_GetLastSessionAddr (pUnitCB, (ULONG FAR *) &session_addr);
  1362.          break;
  1363.  
  1364.       case SONY_561:
  1365.       case TEXEL_3024K:
  1366.       case PIONEER_604X:
  1367.       case HITACHI_6750:
  1368.       case LMS_215:
  1369.          rc = Sony_GetLastSessionAddr (pUnitCB, (ULONG FAR *) &session_addr);
  1370.          break;
  1371.  
  1372.       case CHINON_535:
  1373.          rc = Chinon_GetLastSessionAddr (pUnitCB, (ULONG FAR *) &session_addr);
  1374.          break;
  1375.  
  1376.       case NEC_84_1:
  1377.          rc = NEC_GetLastSessionAddr (pUnitCB, (ULONG FAR *) &session_addr);
  1378.          break;
  1379.  
  1380.       case HP_C4324:                                                       /*@V156096*/
  1381.          rc = HP_GetLastSessionAddr (pUnitCB, (ULONG FAR *) &session_addr);/*@V156096*/
  1382.          break;                                                            /*@V156096*/
  1383.  
  1384.       default:
  1385.          if (pUnitCB->DeviceInfo.interface_type == INTERFACE_PROPRIETARY)
  1386.             rc=NonSCSI_GetLastSessionAddr(pUnitCB, (ULONG FAR *) &session_addr);
  1387.          else if (pUnitCB->DeviceInfo.interface_type == INTERFACE_ATAPI)
  1388.             rc = Sony_GetLastSessionAddr (pUnitCB, (ULONG FAR *) &session_addr);
  1389.          else
  1390.             rc = STDON + STERR;
  1391.          break;
  1392.    }
  1393.    /*
  1394.    ** If no error, then multisession disk.  Read the volume descriptors
  1395.    ** till the terminator descriptor is found.
  1396.    */
  1397.    if (rc == STDON)
  1398.    {
  1399.       for (n = PRIMARY_VOL_DESCR_RBA; term_found != TRUE; n++)
  1400.       {
  1401.          if ((rc = ReadSector(pUnitCB, (ULONG) n, 1, physaddr, 2048)) != STDON)
  1402.             break;
  1403.          /*
  1404.          ** Check for the volume descriptor id of "CD001"
  1405.          */
  1406.          DevHelp_PhysToVirt (physaddr,
  1407.                             (USHORT) 2048,
  1408.                             (PBYTE FAR *) &pBuffer,
  1409.                             (USHORT FAR *) &mode_flag);
  1410.  
  1411.  
  1412.          if ( *(pBuffer+1) != 'C' || *(pBuffer+2) != 'D' ||
  1413.               *(pBuffer+3) != '0' || *(pBuffer+4) != '0' ||
  1414.               *(pBuffer+5) != '1' )
  1415.          {
  1416.             rc = STDON + STERR;
  1417.             break;
  1418.          }
  1419.          /*
  1420.          ** Check for terminator volume descriptor
  1421.          */
  1422.          if ( (UCHAR) *pBuffer == VOL_DESCR_TERMINATOR)
  1423.          {
  1424.            pUnitCB->DeviceInfo.Audio.capabilities |= DCAPS_MULTISESSION_MOUNTED;
  1425.            pUnitCB->DeviceInfo.last_session_addr = session_addr;
  1426.            pUnitCB->DeviceInfo.volume_descr_terminator = n;
  1427.            term_found = TRUE;
  1428.          }
  1429.       }
  1430.       /*
  1431.       ** Read back original sector 0
  1432.       */
  1433.       ReadSector (pUnitCB, (ULONG) 0, 1, physaddr, 2048);
  1434.    }
  1435. }
  1436.  
  1437.  
  1438. /****************************************************************************
  1439.  *
  1440.  * FUNCTION NAME = NonSCSI_GetLastSessionAddr
  1441.  *
  1442.  * DESCRIPTION   = Get address of last session on multisession disk
  1443.  *
  1444.  *  This routine returns the address of the last session of a multisession
  1445.  *  photo CD disk.  This routine should only be called is the drive is
  1446.  *  a non SCSI CD-ROM.
  1447.  *
  1448.  *  USHORT NonSCSI_GetLastSessionAddr(NPUNITCB pUnitCB, ULONG FAR *session_addr)
  1449.  *
  1450.  * INPUT         = pUnitCB          - Pointer to UnitCB
  1451.  *                 session_addr     - Pointer to returned session addr
  1452.  *
  1453.  * OUTPUT        = USHORT           - Packet status word
  1454.  *
  1455.  *                                    if the STERR bit is on, then the disk
  1456.  *                                      is not a multisession disk and the
  1457.  *                                      session_addr field is not valid
  1458.  *
  1459.  *                                    if the STERR bit is NOT set, then the
  1460.  *                                      disk is a multi-session disk and the
  1461.  *                                      session addr field is valid
  1462.  *
  1463.  * RETURN-NORMAL =
  1464.  * RETURN-ERROR  =
  1465.  *
  1466.  ****************************************************************************/
  1467.  
  1468. USHORT NonSCSI_GetLastSessionAddr (pUnitCB, session_addr)
  1469.  
  1470. NPUNITCB pUnitCB;
  1471. ULONG    FAR *session_addr;
  1472.  
  1473. {
  1474.    USHORT rc;
  1475.    NPIORB_CDB pIORB;
  1476.    union ADD_ReadDiskInfo_Data NEAR *pCDBData;
  1477.    union  AddressType last_session;
  1478.  
  1479.  
  1480.    ADD_BuildCDB_ReadDiskInfo (pUnitCB, TYPE_LASTSESSION_INFO,
  1481.                                         (NPIORB_CDB FAR *) &pIORB);
  1482.  
  1483.    pCDBData = (union ADD_ReadDiskInfo_Data NEAR *) pIORB->CDB_data;
  1484.  
  1485.    rc = SubmitIORB_Wait(pUnitCB, pIORB);
  1486.  
  1487.    if (rc == STDON)
  1488.    {
  1489.       /*
  1490.       ** If zero returned in data fields, then not multisession
  1491.       */
  1492.       if ( (pCDBData->last_session.amin == 0) &&
  1493.            (pCDBData->last_session.asec == 0) &&
  1494.            (pCDBData->last_session.aframe == 0) )
  1495.       {
  1496.          rc = STDON + STERR;
  1497.       }
  1498.       else
  1499.       {
  1500.          last_session.ul_redbook.min = pCDBData->last_session.amin;
  1501.          last_session.ul_redbook.sec = pCDBData->last_session.asec;
  1502.          last_session.ul_redbook.frame = pCDBData->last_session.aframe;
  1503.          last_session.ul_redbook.zero = 0;
  1504.  
  1505.          last_session.dword = RedBookToHSG (last_session.dword);
  1506.  
  1507.          *session_addr = last_session.dword;
  1508.       }
  1509.  
  1510.    }
  1511.    FreeIORB (pUnitCB, pIORB);
  1512.    return (rc);
  1513. }
  1514.  
  1515.  
  1516. /****************************************************************************
  1517.  *
  1518.  * FUNCTION NAME = GetPlayStatus
  1519.  *
  1520.  * DESCRIPTION   = Get play status
  1521.  *
  1522.  *                 USHORT GetPlayStatus  (NPUNITCB pUnitCB, BOOL FAR * playing)
  1523.  *
  1524.  * INPUT         = pUnitCB          - Pointer to UnitCB
  1525.  *                 playing          - returned play status
  1526.  *
  1527.  * OUTPUT        = USHORT           - Packet status word
  1528.  *
  1529.  * RETURN-NORMAL =
  1530.  * RETURN-ERROR  =
  1531.  *
  1532.  ****************************************************************************/
  1533.  
  1534. USHORT  GetPlayStatus (pUnitCB, playing)
  1535.  
  1536. NPUNITCB   pUnitCB;
  1537. BOOL FAR *playing;
  1538. {
  1539.    USHORT rc;
  1540.    NPIORB_CDB pIORB;
  1541.    struct SubChannel_Position NEAR *pCDBData;
  1542.  
  1543.    if(pUnitCB->DeviceInfo.playing==FALSE &&             //SD@135221
  1544.    (pUnitCB->pParentUnitCB && pUnitCB->pParentUnitCB->DeviceInfo.Parentplaying))//SD@135221
  1545.      {                                                  //SD@135221
  1546.      *playing=TRUE;                                     //SD@135221
  1547.      return STDON;                                      //SD@135221
  1548.      } /* endif */                                      //SD@135221
  1549.  
  1550.    BuildCDB_ReadSubChannel(pUnitCB, RSC_CURRENT_POSITION,
  1551.                                            (NPIORB_CDB FAR *) &pIORB);
  1552.  
  1553.    pCDBData = (struct SubChannel_Position NEAR *) pIORB->CDB_data;
  1554.  
  1555.    *playing = FALSE;
  1556.  
  1557.    if ( (rc = SubmitIORB_Wait(pUnitCB, pIORB)) == STDON)
  1558.    {
  1559.       if (pCDBData->sub_channel_hdr.audio_status == AS_PLAY_IN_PROGRESS)
  1560.          *playing = TRUE;
  1561.  
  1562.       pUnitCB->DeviceInfo.playing = *playing;
  1563.       if(pUnitCB->pParentUnitCB)                        //SD@135221
  1564.         {
  1565.         pUnitCB->pParentUnitCB->DeviceInfo.Parentplaying = pUnitCB->DeviceInfo.playing;//SD@135221
  1566.         } /* endif */                                   //SD@135221
  1567.    }
  1568.    FreeIORB (pUnitCB, pIORB);
  1569.  
  1570.    return(rc);
  1571. }
  1572.  
  1573.  
  1574. /****************************************************************************
  1575.  *
  1576.  * FUNCTION NAME = Submit_ModeSelect
  1577.  *
  1578.  * DESCRIPTION   = Submit a Mode Select command
  1579.  *
  1580.  *                 Submit_ModeSelect (NPUNITCB pUnitCB, USHORT density_code,
  1581.  *                                                      USHORT block_length)
  1582.  *
  1583.  * INPUT         = pUnitCB         - pointer to UnitCB
  1584.  *                 density_code    - density code
  1585.  *                 block_length    - block_length
  1586.  *                 pIORBOut        - returned pointer to IORB
  1587.  *
  1588.  * OUTPUT        = USHORT          - packet status
  1589.  *
  1590.  * RETURN-NORMAL =
  1591.  * RETURN-ERROR  =
  1592.  *
  1593.  ****************************************************************************/
  1594.  
  1595. USHORT Submit_ModeSelect (pUnitCB, density_code, block_length)
  1596.  
  1597. NPUNITCB   pUnitCB;
  1598. USHORT     density_code;
  1599. USHORT     block_length;
  1600. {
  1601.  
  1602.    USHORT rc;
  1603.    NPIORB_CDB pIORB;
  1604.  
  1605.    BuildCDB_ModeSelect (pUnitCB, density_code, block_length,
  1606.                                                 (NPIORB_CDB FAR *) &pIORB);
  1607.  
  1608.    rc = SubmitIORB_Wait (pUnitCB, pIORB);
  1609.  
  1610.    FreeIORB (pUnitCB, pIORB);
  1611.  
  1612.    if (rc == STDON)
  1613.    {
  1614.       pUnitCB->DeviceInfo.current_density    = density_code;
  1615.       pUnitCB->DeviceInfo.current_block_size = block_length;
  1616.    }
  1617.  
  1618.    return (rc);
  1619. }
  1620.  
  1621.  
  1622. /****************************************************************************
  1623.  *
  1624.  * FUNCTION NAME = Get_UnitCB_Addr
  1625.  *
  1626.  * DESCRIPTION   = Get UnitCB address
  1627.  *
  1628.  *       Return the address of the UnitCB for the specified unit.
  1629.  *
  1630.  *       USHORT Get_UnitCB_Addr  (UCHAR LogDriveNum, NPUNITCB FAR *pUnitCB)
  1631.  *
  1632.  * INPUT         = unit             - logical drive number
  1633.  *                 pUnitCB          - returned pointer to UnitCB
  1634.  *
  1635.  * OUTPUT        = USHORT           - Packet status word
  1636.  *
  1637.  * RETURN-NORMAL =
  1638.  * RETURN-ERROR  =
  1639.  *
  1640.  ****************************************************************************/
  1641.  
  1642. USHORT Get_UnitCB_Addr (LogDriveNum, pUnitCB)
  1643.  
  1644. UCHAR LogDriveNum;
  1645. NPUNITCB FAR *pUnitCB;
  1646.  
  1647. {
  1648.    NPUNITCB pUnitCBx;
  1649.    USHORT   found = FALSE;
  1650.  
  1651.    pUnitCBx = UnitCB_Head;
  1652.  
  1653.    while (pUnitCBx != NULL && found == FALSE)
  1654.    {
  1655.       if ( (UCHAR) pUnitCBx->LogDriveNum == LogDriveNum )
  1656.          found = TRUE;
  1657.       else
  1658.          pUnitCBx = pUnitCBx->pNextUnitCB;
  1659.    }
  1660.  
  1661.    if (found == TRUE)
  1662.    {
  1663.       *pUnitCB = pUnitCBx;
  1664.       return(NO_ERROR);
  1665.    }
  1666.    else
  1667.       return(ERROR);
  1668. }
  1669.  
  1670.  
  1671. /****************************************************************************
  1672.  *
  1673.  * FUNCTION NAME = Strncmp
  1674.  *
  1675.  * DESCRIPTION   = string compare
  1676.  *
  1677.  *                 Strncmp (NPBYTE string1, NPBYTE string2, USHORT length)
  1678.  *
  1679.  *                 This is like the standard C function, except it is boolean
  1680.  *
  1681.  * INPUT         = string1         - string 1
  1682.  *                 string2         - string 2
  1683.  *                 length          - length of string
  1684.  *
  1685.  * OUTPUT        = BOOLEAN, 1 if equal, 0 if not equal
  1686.  *
  1687.  * RETURN-NORMAL =
  1688.  * RETURN-ERROR  =
  1689.  *
  1690.  ****************************************************************************/
  1691.  
  1692. BOOL Strncmp ( string1, string2, length )
  1693.  
  1694. UCHAR   *string1, *string2;
  1695. USHORT  length;
  1696.  
  1697. {
  1698.     BOOL    equal = TRUE;
  1699.  
  1700.     while ( length-- > 0 )
  1701.     {
  1702.         if ( *string1++ != *string2++ )
  1703.         {
  1704.             equal = FALSE;
  1705.             break;
  1706.         }
  1707.     }
  1708.     return ( equal );
  1709. }
  1710.  
  1711.  
  1712. /****************************************************************************
  1713.  *
  1714.  * FUNCTION NAME = CD_Strat1b
  1715.  *
  1716.  * DESCRIPTION   = VOID CD_strat1b  ()
  1717.  *
  1718.  * INPUT         = ES:BX    - Request Packet
  1719.  *
  1720.  * OUTPUT        =
  1721.  *
  1722.  * RETURN-NORMAL =
  1723.  * RETURN-ERROR  =
  1724.  *
  1725.  ****************************************************************************/
  1726.  
  1727. VOID NEAR CD_Strat1b()
  1728. {
  1729.   PRP_GENIOCTL  pRP;
  1730.   USHORT        Cmd, Status;
  1731.   PRPINITOUT    pRPO;
  1732.  
  1733.   _asm
  1734.   {
  1735.      push es
  1736.      push bx
  1737.      mov word ptr pRP[0], bx
  1738.      mov word ptr pRP[2], es
  1739.   }
  1740.  
  1741.   pRPO = (PRPINITOUT) pRP;                  /* Output for Init RP           */
  1742.   Status = 0;
  1743.  
  1744.   Cmd = pRP->rph.Cmd;
  1745.  
  1746.   if (Cmd == CMDInitBase || Cmd == CMDInit)
  1747.   {
  1748.      pRPO->DataEnd = DataBreakAddress;
  1749.      pRPO->CodeEnd = CodeBreakAddress;
  1750.      if (CodeBreakAddress == 0)
  1751.         Status = STDON + STERR + ERROR_I24_QUIET_INIT_FAIL;
  1752.   }
  1753.   else if ( (Cmd == CMDGenIOCTL) && (pRP->Category == IOC_CDROM_2) &&
  1754.             (pRP->Function == IOCD_RETURN_DRIVE_LETTER) )
  1755.   {
  1756.  
  1757. /*   Status = VerifyParameters(pRP, 0, 4, ParamLockHandle, DataLockHandle);*/
  1758.  
  1759.      if (Status == 0)
  1760.      {
  1761.         ((struct DriveLetter_Data FAR *)pRP->DataPacket)->drive_count =
  1762.                                                            NumCDROMDrives;
  1763.  
  1764.         ((struct DriveLetter_Data FAR *)pRP->DataPacket)->first_drive_number =
  1765.                                                            FirstDriveNumber;
  1766.      }
  1767.   }
  1768.   else
  1769.      Status = STDON + STERR + ERROR_I24_BAD_COMMAND;
  1770.  
  1771.   DISABLE;
  1772.  
  1773.   pRP->rph.Status = Status | STDON ;         /*Save status in Request Packet */
  1774.  
  1775.   ENABLE;
  1776.  
  1777.   _asm
  1778.   {
  1779.      pop bx
  1780.      pop es
  1781.      LEAVE
  1782.      retf
  1783.   }
  1784. }
  1785.  
  1786.