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

  1. #define INCL_DOSINFOSEG
  2. #define INCL_NOPMAPI
  3. #define INCL_NO_SCB
  4. #define INCL_INITRP_ONLY
  5.  
  6. #include <os2.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <dos.h>
  10. #include <sas.h>
  11. #include "devcmd.h"
  12.  
  13. #include "iorb.h"
  14. #include "reqpkt.h"
  15. #include "addcalls.h"
  16. #include "dskinit.h"
  17.  
  18. #include <scsi.h>
  19. #include <cdbscsi.h>
  20. #include <cmd.h>
  21. #include <devhelp.h>
  22. #include <cdb.h>
  23. #include "proto.h"
  24.  #include <string.h>
  25.  #include <memory.h>
  26.  
  27.  
  28.  extern PGINFOSEG near PGinfo;
  29.  extern ULONG near DevHlp;
  30.  extern PUCHAR near Read_IOBuffer;
  31.  extern USHORT near IrqNum;
  32.  extern USHORT near DrvBlockSize;
  33.  UCHAR PreviousOpCode,PreviousStatus;
  34.  extern UCHAR near Mode;
  35.  extern UCHAR  near wDrvVer[4];
  36.  
  37.  
  38.       TOCINFO TOCInfoArea[101] = { {0,},};
  39.       UCHAR  bPlayFlag = FALSE ;
  40.       UCHAR  bPauseFlag = FALSE ;
  41.       UCHAR  bChangeFlag ;
  42.       UCHAR  bInfoFlag = 0 ;
  43.       UCHAR  bMedChgFlag = CHANGED ;
  44.       UCHAR  bMedChkFlag = FALSE ;
  45.       UCHAR  bMedChkCalled = FALSE ;
  46.       UCHAR  bStatus =0;
  47.       USHORT  bStatusFlag=0;
  48.       extern UCHAR near bCFlag, near last_data_byte;
  49.       UCHAR TOC_Cache=0;
  50.       UCHAR  bMinTno=0, bMaxTno =0,bChanged=0;
  51.       ULONG  ulVSSize =0;
  52.       ULONG  ulLeadOut =0;
  53.       UCHAR  CD_ID=0;
  54.       USHORT wBlkLen =0;
  55.       ULONG  Specialbuffer=NULL;
  56.  
  57. BOOL GetTocInfo()
  58. {
  59. USHORT i=0,state,First_Track_in_Session,Last_Track_in_Session,count,Status,q,Delta=0;
  60. CDROMSTAT Data ;
  61. BOOL Flag=FALSE,SeekRunning,ModeSetState;
  62. ULONG Clock=0L,Addr;
  63. UCHAR m,s,f;
  64. #define NoneFound  0
  65. #define FirstFound 1
  66. #define LastFound  2
  67. #define AllFound   3
  68. #define MaxFound   7
  69. #define LowTrack  0xa0
  70. #define HighTrack 0xa1
  71. #define BridgeTrk 0xb0
  72. #define MaxTrack 0x99
  73.  
  74.         CD_ID=0;
  75.         Addr=MinFrame;
  76.  
  77.         newloop:;
  78.  
  79.         SeekRunning=FALSE;
  80.         ModeSetState=FALSE;
  81.  
  82.         for(i=0; i<5; i++)
  83.           {
  84.           DPRINTF(("Seeking to %08lX\n",Addr));
  85.           bStatusFlag=DriveCommand(Seek,Addr,NULL,NULL,(USHORT)NULL);
  86.           DPRINTF(("Seeking to %08lX status=%04X\n",Addr,bStatusFlag));
  87.           if( !COMMANDCHECK(bStatusFlag) && !TIMEOUT(bStatusFlag))
  88.             {
  89.             SeekRunning=TRUE;
  90.             break;
  91.             } /* end if */
  92.           else
  93.             {
  94.             DUMMYWAIT;
  95.             if(i==3)
  96.               {
  97.               bStatusFlag=DriveCommand(Stop,NULL,NULL,NULL,(USHORT)NULL);
  98.               bStatusFlag=DriveCommand(SetDriveMode,(ULONG)MuteData,NULL,NULL,(USHORT)NULL);
  99.               goto newloop;
  100.               } /* end if */
  101.             }
  102.           } /* end for */
  103.  
  104.         if(SeekRunning)
  105.           {
  106.           for(i=0; i<8; i++)
  107.             {
  108.             DPRINTF(("Setting Drive mode\n"));
  109.             bStatusFlag=DriveCommand(SetDriveMode,(ULONG)(MuteData|TocData),NULL,NULL,(USHORT)NULL);
  110.             if(!COMMANDCHECK(bStatusFlag))
  111.               {
  112.               ModeSetState=TRUE;
  113.               break;
  114.               } /* end if */
  115.             } /* end for */
  116.           }
  117.  
  118.         DUMMYWAIT;
  119.  
  120.         if(SeekRunning)
  121.           {
  122.           DPRINTF(("Starting Track search for tracks %d thru %d\n", bMinTno+Delta,bMaxTno));
  123.           for(state=NoneFound,count=400,i=bMinTno+Delta;i<=bMaxTno && count ; count--)
  124.             {
  125.             DUMMYWAIT;
  126.             while(TIMEOUT(bStatusFlag=(UCHAR)(Status=DriveCommand(ReadSubQ,NULL,NULL,&Data,sizeof(Data.TrackInfo)))))
  127.               DUMMYWAIT;
  128.             DPRINTF(("SubqLoop status=%04X\n",bStatusFlag));
  129.             if(!TIMEOUT(Status))
  130.               {
  131.               if(!COMMANDCHECK(bStatusFlag) && !DISCCHANGE(bStatusFlag) && DISCIN(bStatusFlag) && !READERROR(bStatusFlag))
  132.                 {
  133.                 DPRINTF((" Q Status = %04X\n", bStatusFlag));
  134.                 DPRINTF(("Track Q info TNO = %02X, AMin= %02X, Index = %02X ADR=%02X\n",
  135.                                 Data.TrackInfo.TNO,
  136.                                 BCD2Bin(Data.TrackInfo.AMin),
  137.                                 Data.TrackInfo.Index,
  138.                                 Data.TrackInfo.S.ADR));
  139.                 if(Data.TrackInfo.TNO==0)
  140.                   {
  141.                   if(state!=MaxFound)
  142.                     {
  143.                     if(state!=AllFound)
  144.                       {
  145.                       if(Data.TrackInfo.Index==LowTrack)
  146.                         {
  147.                         if(!(state & FirstFound))
  148.                           {
  149.                           if(BCD2Bin(Data.TrackInfo.AMin)==i)
  150.                             {
  151.                             DPRINTF(("firsttrack index found = %d\n",BCD2Bin(Data.TrackInfo.AMin)));
  152.                             First_Track_in_Session=BCD2Bin(Data.TrackInfo.AMin);
  153.                             DPRINTF(("First=%d\n",First_Track_in_Session));
  154.                             state |= FirstFound;
  155.                             } /* end if */
  156.                           } /* end if */
  157.                         } /* end if */
  158.                       else if(Data.TrackInfo.Index==HighTrack)
  159.                         {
  160.                         if(!(state & LastFound))
  161.                           {
  162.                           DPRINTF(("lasttrack index found = %d\n",BCD2Bin(Data.TrackInfo.AMin)));
  163.                           Last_Track_in_Session=BCD2Bin(Data.TrackInfo.AMin);
  164.                           DPRINTF(("Last=%d\n",Last_Track_in_Session));
  165.                           state |= LastFound;
  166.                           } /* end if */
  167.                         } /* end else */
  168.                       } /* end if */
  169.                     else
  170.                       {
  171.                       if(Data.TrackInfo.Index<=MaxTrack)
  172.                         {
  173.                         if(i==BCD2Bin(Data.TrackInfo.Index))
  174.                           {
  175.                           DPRINTF(("Saving track info for Track %d\n",BCD2Bin(Data.TrackInfo.Index)));
  176.                           TOCInfoArea[BCD2Bin(Data.TrackInfo.Index)].Control=Data.TrackInfo.S.Control;
  177.                           TOCInfoArea[BCD2Bin(Data.TrackInfo.Index)].ADR=Data.TrackInfo.S.ADR;
  178.                           TOCInfoArea[BCD2Bin(Data.TrackInfo.Index)].min=BCD2Bin(Data.TrackInfo.AMin);
  179.                           TOCInfoArea[BCD2Bin(Data.TrackInfo.Index)].sec=BCD2Bin(Data.TrackInfo.ASec);
  180.                           TOCInfoArea[BCD2Bin(Data.TrackInfo.Index)].frame=BCD2Bin(Data.TrackInfo.AFrame);
  181.                           TOCInfoArea[BCD2Bin(Data.TrackInfo.Index)].start= MAKEULONG( MAKEUSHORT( BCD2Bin(Data.TrackInfo.AFrame),
  182.                                                                                              BCD2Bin(Data.TrackInfo.ASec ) ),
  183.                                                                                        MAKEUSHORT( BCD2Bin(Data.TrackInfo.AMin),
  184.                                                                                                    0 ) ) ;
  185.                           DevHelp_RAS( 184 ,i , sizeof(TOCINFO), &TOCInfoArea[i]);
  186.                           if(i==Last_Track_in_Session)                   // if last track in this session
  187.                             {                           // go for more
  188.                             state=MaxFound;
  189.                             DPRINTF(("Max Track in session found\n"));
  190.                             Delta=i;
  191.                             } /* end if */
  192.                           i++;
  193.                           } /* end if */
  194.                         } /* end if */
  195.                       } /* end else */
  196.                     } /* end if */
  197.                   else if(Data.TrackInfo.Index==BridgeTrk)
  198.                     {
  199.                     f =BCD2Bin(Data.TrackInfo.Frame);
  200.                     s =BCD2Bin(Data.TrackInfo.Sec);
  201.                     m =BCD2Bin(Data.TrackInfo.Min);
  202.                     s +=2;          // go two seconds into new area
  203.                     if(s>=60)       // if new seconds is >one minute would allow
  204.                       {
  205.                       m++;          // adjust minutes
  206.                       s-=60;        // adjust downward seconds
  207.                       } /* end if */
  208.                     Addr=MAKEULONG( MAKEUSHORT(f,s ),
  209.                                     MAKEUSHORT(m,0));
  210.                     DPRINTF(("Bridge track found = %08lX\n",Addr));
  211.                     while(TIMEOUT(DriveCommand(SetDriveMode,(ULONG)MuteData,NULL,NULL,(USHORT)NULL)));
  212.                     DUMMYWAIT;
  213.                     DUMMYWAIT;
  214.                     DUMMYWAIT;
  215.                     DUMMYWAIT;
  216.                     DUMMYWAIT;
  217.                     DUMMYWAIT;
  218.                     DUMMYWAIT;
  219.                     DUMMYWAIT;
  220.                     DPRINTF(("Seeking to last session now for tracks %d thru %d status=%04X\n",i,bMaxTno,bStatusFlag));
  221.                     goto newloop;
  222.                     } /* end if */
  223.                   } /* end if */
  224.                 } /* end if */
  225.               else
  226.                 {
  227.                 DevHelp_RAS( 183 ,0xaa , sizeof(PGinfo->msecs), &(PGinfo->msecs));
  228.                 DPRINTF(("Aborting track search Status=%04X\n",bStatusFlag));
  229.                 break;
  230.                 } /* end else */
  231.               } /* end if */
  232.             else
  233.               {
  234.               DevHelp_RAS( 183 ,0xab , sizeof(PGinfo->msecs), &(PGinfo->msecs));
  235.               DPRINTF(("Aborting track search timeout Status=%04X\n",bStatusFlag));
  236.               break;
  237.               }
  238.             } /* end for */
  239.           }
  240.         bStatusFlag=DriveCommand(SetDriveMode,(ULONG)MuteData,NULL,NULL,(USHORT)NULL);
  241. //      bStatusFlag=DriveCommand(Stop,0,NULL,NULL,NULL);
  242.         if(count==0 && i<bMaxTno)
  243.           {
  244.           goto newloop;
  245.           } /* end if */
  246.         if(state==MaxFound)
  247.           {
  248.           DevHelp_RAS( 184 ,0xaa , sizeof(PGinfo->msecs), &(PGinfo->msecs));
  249.           Flag=TRUE;
  250.           } /* end if */
  251.         return Flag;
  252. }
  253.  
  254. BOOL CacheTOC(PCDROMSTAT Data,UCHAR checksum)
  255. {
  256. BOOL Flag=TRUE;
  257.         DPRINTF(("Caching TOC\n"));
  258.         bInfoFlag &= CLR_VS;                    // clear the flag just to make sure
  259.         TOC_Cache=0;                            // clear toc indicator, just in case
  260.         ulVSSize = AdrRed2Hsg(MAKEULONG( MAKEUSHORT( BCD2Bin(Data->TOC.LeadoutFrame),
  261.                                          BCD2Bin(Data->TOC.LeadoutSec ) ),
  262.                              MAKEUSHORT( BCD2Bin(Data->TOC.LeadoutMin),
  263.                                          0 ) ) )-1;
  264.         bMinTno   =BCD2Bin(Data->TOC.FirstTrack);
  265.         bMaxTno   =BCD2Bin(Data->TOC.LastTrack);
  266.         DPRINTF(("FirstTrack=%d LastTrack=%d\n",bMinTno,bMaxTno));
  267.         TOCInfoArea[0].min=BCD2Bin(Data->TOC.LeadoutMin);
  268.         TOCInfoArea[0].sec=BCD2Bin(Data->TOC.LeadoutSec );
  269.         TOCInfoArea[0].frame=BCD2Bin(Data->TOC.LeadoutFrame);
  270.         TOCInfoArea[0].ADR =0;
  271.         TOCInfoArea[0].Control=AUDIODISC(bStatusFlag) ? TCI_AUDIO : TCI_DATA;
  272.         DPRINTF((" Low & high track = %d %d status=%02X\n",bMinTno,bMaxTno,bStatusFlag));
  273.         ulLeadOut = MAKEULONG( MAKEUSHORT( BCD2Bin(Data->TOC.LeadoutFrame),
  274.                                          BCD2Bin(Data->TOC.LeadoutSec ) ),
  275.                              MAKEUSHORT( BCD2Bin(Data->TOC.LeadoutMin),
  276.                                          0 ) ) ;
  277.  
  278.         TOCInfoArea[bMaxTno+1].start=ulLeadOut;     // start after last track, used in read SRD
  279.         TOCInfoArea[bMaxTno+1].Control=TCI_DATA;    // start after last track, used in read SRD
  280.         DPRINTF(("Getting TrackInfo\n"));
  281.         SetDataMode(SuspendData);
  282.         if(GetTocInfo())
  283.           {
  284.           DPRINTF(("TrackInfo completed ok\n"));
  285.           bInfoFlag |= SET_VS ;
  286.           TOC_Cache=checksum;
  287.           Flag=FALSE;
  288.           if(TOCInfoArea[bMinTno].Control & TCI_DATA)
  289.             {
  290.             while(TIMEOUT(DriveCommand( DriveConfig,MODEFLAG ,0, 0, 0)))
  291.               DUMMYWAIT;
  292.             while(TIMEOUT(DriveCommand( DriveConfig,IRQFLAG ,IrqNum?(PreIrq|ErrIrq):0, 0, 0)))
  293.               DUMMYWAIT;
  294.             if (wDrvVer[0]=='D')
  295.               {
  296.               while(TIMEOUT(DriveCommand( DriveConfig,RETRYCOUNT ,3, 0, 0)))
  297.                 DUMMYWAIT;
  298.               }
  299.             while(TIMEOUT(DriveCommand( SetDriveMode,MuteData ,0, 0, 0)))
  300.               DUMMYWAIT;
  301.             #ifndef TEST
  302.             #ifndef DEBUG
  303.             TryIrq(FALSE);
  304.             SpecialRead();
  305.             #endif
  306.             #endif
  307.             } /* end if */
  308.           }
  309.         else
  310.           {
  311.           DPRINTF(("TrackInfo failed\n"));
  312.           }
  313.      return Flag;
  314. }
  315.  
  316. BOOL ReadyHardware( PIORBH pIORB, USHORT OpCode )
  317. {
  318.       USHORT CmdCode = pIORB->CommandCode ;
  319.       USHORT SubCmd  = pIORB->CommandModifier ;
  320.       CDROMSTAT Data ;
  321.       UCHAR i,temp ;
  322.       PUCHAR t;
  323.  
  324.       for(i=1; i<15; i++)
  325.         {
  326.         bStatusFlag=DriveStatus(Spincount);       // get drives status
  327.  
  328.         if(COMMANDCHECK(bStatusFlag) || TIMEOUT(bStatusFlag) ||
  329.           ((PreviousOpCode==SCSI_MODE_SELECT) && (LOBYTE(bStatusFlag)==0) && (PreviousStatus!=0))
  330.           )
  331.           {
  332.           DevHelp_RAS( 160 ,OpCode<<8 | bStatusFlag , sizeof(PGinfo->msecs), &(PGinfo->msecs));
  333.           DUMMYWAIT;
  334.           } /* end if */
  335.         else
  336.           {
  337.           break;
  338.           } /* end else */
  339.         } /* end for */
  340.       PreviousOpCode=OpCode;
  341.       PreviousStatus=LOBYTE(bStatusFlag);
  342.       DevHelp_RAS( 160 ,OpCode<<8 | bStatusFlag , sizeof(PGinfo->msecs), &(PGinfo->msecs));
  343.       if(!COMMANDCHECK(bStatusFlag))            // no command error
  344.         {
  345.         if(DISCIN(bStatusFlag))                 // is there a disc in the drive?
  346.           {                                     // calculate checksum of toc data, should be only one match possible
  347.                                                 // get TOC
  348.           if(!(bInfoFlag & SET_VS))
  349.             {
  350.             bPlayFlag   = bPauseFlag = FALSE ;
  351.             bStatusFlag=DriveCommand(ReadToc,NULL,NULL,&Data,sizeof(Data.TOC));
  352.             if(!COMMANDCHECK(bStatusFlag) && !READERROR(bStatusFlag) && (Data.TOC.LastTrack<MaxTrack))
  353.               {
  354.               DevHelp_RAS( 184 ,0 , sizeof(Data.TOC), &Data);
  355.               DPRINTF(("Disk in drive\n"));
  356.               for(i=1,t=(PUCHAR)&Data,temp=*t,t++;i<sizeof(Data.TOC) ; i++,t++)
  357.                 {
  358.                 temp^=*t;
  359.                 } /* end for */
  360.               DPRINTF(("Checksum=%02X==Saved=%02X\n",temp,TOC_Cache));
  361. //            if(temp==TOC_Cache)                   // does the checksum matched the saved one?
  362. //              {
  363. //              DPRINTF(("Checksums match\n"));
  364. //              bInfoFlag |= SET_VS ;               // same disk as last time
  365. //              } /* end if */
  366. //            else
  367. //              {
  368.                 DPRINTF(("Checksums do NOT match\n"));
  369.                 IORB_CmdErr(IOERR_MEDIA_CHANGED, pIORB,SCSI_SK_UNITATTN,ASC_MEDIUM_CHANGED);
  370.                 if(CacheTOC(&Data,temp))            // did caching go ok?
  371.                   {
  372.                   DPRINTF(("Caching failed?\n"));
  373.                   switch (OpCode)                   // no failures for some non-disk dependant opcodes
  374.                     {
  375.                     case SCSI_READ_CAPACITY:
  376.                     case SCSI_MODE_SELECT:
  377.                     case SCSI_MODE_SENSE:
  378.                        break;
  379.                     default:
  380.                        IORB_CmdErr(IOERR_UNIT_NOT_READY, pIORB,SCSI_SK_NOTRDY,0);
  381.                        DevHelp_RAS( 162 ,OpCode<<8 | bStatusFlag , sizeof(PGinfo->msecs), &(PGinfo->msecs));
  382.                        return TRUE;
  383.                        break;
  384.                     } /* endswitch */
  385.                   } /* end if */
  386. //              } /* end else */
  387.               } /* end if */
  388.             else
  389.               {
  390.               DPRINTF(("TOC failed status=%02X\n",bStatusFlag));
  391.               DevHelp_RAS( 183 ,0xaa , sizeof(PGinfo->msecs), &(PGinfo->msecs));
  392.               IORB_CmdErr(IOERR_UNIT_NOT_READY, pIORB,SCSI_SK_NOTRDY,0);
  393.               DevHelp_RAS( 162 ,OpCode<<8 | bStatusFlag , sizeof(PGinfo->msecs), &(PGinfo->msecs));
  394.               return TRUE;
  395.               } /* end else */
  396.             } /* end if */
  397.           } /* end if */
  398.         else
  399.           {
  400.           DPRINTF(("NO Disk in drive\n"));
  401.           bPlayFlag   = bPauseFlag = FALSE ;
  402.           switch (OpCode)                       // no failures for some non-disk dependant opcodes
  403.             {
  404.             case SCSI_MODE_SELECT:
  405.             case SCSI_MODE_SENSE:
  406.             case SCSI_LOCK_UNLOCK:
  407.             case SCSI_START_STOP_UNIT:
  408.             case ADD_READ_DISK_INFO:           //rme - fix for photo CD
  409.                break;
  410.             default:
  411.                IORB_CmdErr(IOERR_MEDIA_NOT_PRESENT, pIORB,SCSI_SK_NOTRDY,0);
  412.                DevHelp_RAS( 162 ,OpCode<<8 | bStatusFlag ,sizeof(PGinfo->msecs), &(PGinfo->msecs) );
  413.                return TRUE;
  414.                break;
  415.             } /* endswitch */
  416.           } /* end else */
  417.         } /* end if */
  418.       else                                      // no disc present
  419.         {
  420.         DPRINTF(("Drive Status Command failed %02X\n",bStatusFlag));
  421.         switch (OpCode)                         // no failures for some non-disk dependant opcodes
  422.           {
  423.           case SCSI_READ_CAPACITY:
  424.           case SCSI_MODE_SELECT:
  425.           case SCSI_MODE_SENSE:
  426.              break;
  427.           default:
  428.              IORB_CmdErr(IOERR_UNIT_NOT_READY, pIORB,SCSI_SK_NOTRDY,0);
  429.              DevHelp_RAS( 162 ,OpCode<<8 | bStatusFlag , sizeof(PGinfo->msecs), &(PGinfo->msecs));
  430.              return TRUE;
  431.              break;
  432.           } /* endswitch */
  433.         } /* end else */
  434.  
  435.       return FALSE;
  436. }
  437.  
  438. void SpecialRead( void)
  439. {
  440. USHORT Status,i;
  441. CDROMSTAT c;
  442. UCHAR CurrentMode=Mode1;
  443. #define SpecialAddr 0x00000210L
  444. PRawSector SpecialBuffer;
  445.  
  446.         do
  447.           {
  448.           DUMMYWAIT;
  449.           Status=DriveCommand( ModeSet,Mode1 ,0, 0, 0);          // set mode 1 first
  450.           Mode = Mode1;
  451.           } while (TIMEOUT(Status)); /* end do */
  452.         DriveCommand( SetDriveMode,DataLength|EccBit|MuteData ,0, 0, 0);
  453.         if(!Specialbuffer)
  454.           {
  455. #if defined(DEBUG) | defined(TEST)
  456.           Specialbuffer=malloc(sizeof(RawSector));
  457. #else
  458.           DevHelp_AllocPhys(sizeof(RawSector),0, (PULONG)&Specialbuffer);
  459. #endif
  460.           } /* end if */
  461.         if(Specialbuffer)
  462.           {
  463. #if defined(DEBUG) | defined(TEST)
  464.           SpecialBuffer=(PRawSector)Specialbuffer;
  465. #else
  466.           DevHelp_PhysToGDT((ULONG)Specialbuffer, sizeof(RawSector), FP_SEG(Read_IOBuffer));
  467.           SpecialBuffer=(PRawSector)Read_IOBuffer;
  468. #endif
  469.           for(i=0; i<2; i++)
  470.             {
  471.             Status=DriveCommand( Read, SpecialAddr, 1,(PCDROMSTAT)SpecialBuffer ,sizeof(RawSector));   // read
  472.             if(!READERROR(Status) && !COMMANDCHECK(Status) && !TIMEOUT(Status))
  473.               {
  474.               if(Mode==Mode2)
  475.                 {
  476.                 DriveCommand( SetDriveMode,TestMode|MuteData ,0, 0, 0);
  477.                 while(TIMEOUT(DriveCommand( DriveConfig,BLOCKSIZE ,DrvBlockSize, 0, 0)))
  478.                   DUMMYWAIT;
  479.                 break;
  480.                 } /* end if */
  481.               else
  482.                 {
  483.                 Status=DriveCommand( ModeSet,Mode1 ,0, 0, 0);  // try mode 2 now
  484.                 DriveCommand( SetDriveMode,MuteData ,0, 0, 0);
  485.                 break;
  486.                 } /* end else */
  487.               } /* end if */
  488.             else
  489.               {
  490.               Mode=Mode2;
  491.               Status=DriveCommand( ModeSet,Mode2 ,0, 0, 0);  // try mode 2 now
  492.               } /* end else */
  493.             } /* end for */
  494.           } /* end if */
  495. }
  496.