]> Shamusworld >> Repos - virtualjaguar/commitdiff
Added function implementation ;-)
authorShamus Hammons <jlhamm@acm.org>
Tue, 1 Jun 2004 19:20:35 +0000 (19:20 +0000)
committerShamus Hammons <jlhamm@acm.org>
Tue, 1 Jun 2004 19:20:35 +0000 (19:20 +0000)
src/cdintf_linux.cpp
src/cdintf_osx.cpp
src/cdintf_win32.cpp

index c418df592e0533d3b2550b3f44dde9939e14eeb3..eeeec30543624a260455e58f8b2df1686aaa815f 100644 (file)
@@ -3,3 +3,52 @@
 //
 // by James L. Hammons
 //
+
+//
+// Linux support functions
+//
+
+
+
+//
+// OS specific implementation of OS agnostic functions
+//
+
+bool CDIntfInit(void)
+{
+       WriteLog("CDINTF: Init unimplemented!\n");
+       return false;
+}
+
+void CDIntfDone(void)
+{
+}
+
+bool CDIntfReadBlock(uint32 sector, uint8 * buffer)
+{
+       WriteLog("CDINTF: ReadBlock unimplemented!\n");
+       return false;
+}
+
+uint32 CDIntfGetNumSessions(void)
+{
+       // Still need relevant code here... !!! FIX !!!
+       return 2;
+}
+
+void CDIntfSelectDrive(uint32 driveNum)
+{
+       WriteLog("CDINTF: SelectDrive unimplemented!\n");
+}
+
+uint32 CDIntfGetCurrentDrive(void)
+{
+       WriteLog("CDINTF: GetCurrentDrive unimplemented!\n");
+       return 0;
+}
+
+uint8 * CDIntfGetDriveName(uint32)
+{
+       WriteLog("CDINTF: GetDriveName unimplemented!\n");
+       return NULL;
+}
index 1ca290e9b6ce0f55066234e86c5f9bab95d91871..3692e7ec713d87fd753ec1a74531089fd7f9ca23 100644 (file)
@@ -1,5 +1,54 @@
 //
 // OS specific CDROM interface (Mac OS X)
 //
-// by ?
+// by James L. Hammons & ?
 //
+
+//
+// OS X support functions
+//
+
+
+
+//
+// OS specific implementation of OS agnostic functions
+//
+
+bool CDIntfInit(void)
+{
+       WriteLog("CDINTF: Init unimplemented!\n");
+       return false;
+}
+
+void CDIntfDone(void)
+{
+}
+
+bool CDIntfReadBlock(uint32 sector, uint8 * buffer)
+{
+       WriteLog("CDINTF: ReadBlock unimplemented!\n");
+       return false;
+}
+
+uint32 CDIntfGetNumSessions(void)
+{
+       // Still need relevant code here... !!! FIX !!!
+       return 2;
+}
+
+void CDIntfSelectDrive(uint32 driveNum)
+{
+       WriteLog("CDINTF: SelectDrive unimplemented!\n");
+}
+
+uint32 CDIntfGetCurrentDrive(void)
+{
+       WriteLog("CDINTF: GetCurrentDrive unimplemented!\n");
+       return 0;
+}
+
+uint8 * CDIntfGetDriveName(uint32)
+{
+       WriteLog("CDINTF: GetDriveName unimplemented!\n");
+       return NULL;
+}
index b075af56ceb32e5156f375ba62c098e3e9190f7c..405f6893c0c0aed432f9889c72643faad08e7353 100644 (file)
 //
 // by James L. Hammons
 //
+// Currently, we use the ASPI layer for Win32, but this may or may not
+// work on NT based Windows. If necessary, we'll put in the required
+// NT based code, but for now, it's ASPI or nothing.
+//
 
-// OS dependent CDROM stuffola
+// *** OS dependent CDROM stuffola ***
 #include <windows.h>
-#include <stdio.h>
 #include "wnaspi32.h"
 #include "scsidefs.h"
-// End OS dependent
-
+// *** End OS dependent ***
 #include "log.h"
 
 using namespace std;
 
 // Local variables
 
-DWORD remain = 0, sector = 0;
-BYTE cdBuf[2532 * 10];
+static uint8 maxHostAdapters = 0, numCDDrives = 0, driveNum;
+static uint8 haID[8], tID[8];
+static uint8 driveName[8][26];
+static uint8 tracks[100][3];                                           // One-based index
+static uint32 numTracks = 0;
+static uint8 sessions[40][5];                                          // Zero-based index
+static uint32 numSessions = 0;
+static bool readTOC = false;
 
-// Private function prototypes
+static HINSTANCE hASPILib = NULL;                                      // Handle to ASPI for Win32 (WNASPI.DLL)
+static uint32 (* ASPI_GetASPI32SupportInfo)(void);     // WNASPI.DLL function pointers
+static uint32 (* ASPI_SendASPI32Command)(LPSRB);
 
+// Private function prototypes
 
-HINSTANCE WNASPI32_handle = NULL;  //Handle to ASPI for Win32 (WNASPI.DLL)
-//WNASPI.DLL functions
-DWORD (*ASPI_GetASPI32SupportInfo)(VOID);
-DWORD (*ASPI_SendASPI32Command)(LPSRB);
-//BOOL  (*ASPI_GetASPI32Buffer)(PASPI32BUFF);
-//BOOL  (*ASPI_FreeASPI32Buffer)(PASPI32BUFF);
-//BOOL  (*ASPI_TranslateASPI32Address)(PDWORD, PDWORD);
+static bool InitASPI(void);
+static bool SendAsyncASPICmd(uint8, uint8, uint8 *, uint8, uint8 *, uint32, uint8);
+/*static*/ bool GetRawTOC(void);
 
-byte DataBuf[2352];  //Buffer for holding data to/from drive
-//************************************************************
-//End of globals
 
 //
-// Load the WNASPI32.DLL and import the required functions, then initialise
-// Win ASPI 32.
+// Initialize the Win32 ASPI layer
 //
-BOOL InitASPI()
+static bool InitASPI(void)
 {
-       DWORD dwSupportInfo;
-       SRB_GetSetTimeouts srbTimeouts;
+       hASPILib = LoadLibrary("WNASPI32");
+
+       if (!hASPILib)
+       {
+               WriteLog("CDINTF: Could not load WNASPI32.DLL!\n");
+               return false;
+       }
 
-       WNASPI32_handle = LoadLibrary("WNASPI32"); //WNASPI32.DLL
+       ASPI_GetASPI32SupportInfo = (uint32 (*)(void))GetProcAddress(hASPILib, "GetASPI32SupportInfo");
+       ASPI_SendASPI32Command = (uint32 (*)(LPSRB))GetProcAddress(hASPILib, "SendASPI32Command");
 
-       if (!WNASPI32_handle)
+       if (!ASPI_GetASPI32SupportInfo || !ASPI_SendASPI32Command)
        {
-               WriteLog("CDINTF: Could not load WNASPI32.DLL\n");
-               return FALSE;
-       };
-
-    /*
-    ** Get the ASPI entry points.  Note that only two functions are mandatory:
-    ** GetASPI32SupportInfo and SendASPI32Command.  The code will run if the
-    ** others are not present.
-    */
-    ASPI_GetASPI32SupportInfo = (DWORD (*)(void))GetProcAddress(WNASPI32_handle, "GetASPI32SupportInfo");
-    ASPI_SendASPI32Command = (DWORD (*)(LPSRB))GetProcAddress(WNASPI32_handle, "SendASPI32Command");
-    //ASPI_GetASPI32Buffer = (BOOL (*)(PASPI32BUFF))GetProcAddress(WNASPI32_handle, "GetASPI32Buffer");
-    //ASPI_FreeASPI32Buffer = (BOOL (*)(PASPI32BUFF))GetProcAddress(WNASPI32_handle, "FreeASPI32Buffer");
-    //ASPI_TranslateASPI32Address = (BOOL (*)(PDWORD, PDWORD))GetProcAddress(WNASPI32_handle, "TranslateASPI32Address");
-
-    //Check if the 2 functions were imported.
-    if(!ASPI_GetASPI32SupportInfo || !ASPI_SendASPI32Command)
-    {
-        WriteLog("Could not import GetASPI32SupportInfo & SendASPI32Command functions from WNASPI32.DLL\n");
-        return FALSE;
-    };
-
-    //Initialise Win ASPI 32 by calling ASPI_GetASPI32SupportInfo().
-    dwSupportInfo = ASPI_GetASPI32SupportInfo();
-    if (HIBYTE(LOWORD(dwSupportInfo)) != SS_COMP && HIBYTE(LOWORD(dwSupportInfo)) != SS_NO_ADAPTERS)
-    {
-        WriteLog("Could not initialise using GetASPI32SupportInfo function or no adapters\n");
-        return FALSE;
-    };
-
-    /*
-    ** Set timeouts for ALL devices to 15 seconds.  Nothing we deal with should
-    ** take that long to do ANYTHING.  We are just doing inquiries to most
-    ** devices, and then simple reads to CDs, disks, etc. so 10 seconds (even
-    ** if they have to spin up) should be plenty. 
-    */
-    memset(&srbTimeouts, 0, sizeof(SRB_GetSetTimeouts));
-    srbTimeouts.SRB_Cmd = SC_GETSET_TIMEOUTS;
-    srbTimeouts.SRB_HaId = 0xFF;
-    srbTimeouts.SRB_Flags = SRB_DIR_OUT;
-    srbTimeouts.SRB_Target = 0xFF;
-    srbTimeouts.SRB_Lun = 0xFF;
-    srbTimeouts.SRB_Timeout = 15 * 2;
-    ASPI_SendASPI32Command(&srbTimeouts);
-
-    return TRUE;
-};
-
-/*
-    Sends a SRB (SCSI Request Block) to Win ASPI32 driver for processing and
-    waits for completion.
-
-    The SRB contains the CDB (Command Descriptor Block) which has the
-    raw SCSI command/info you want to send to the drive.  So effectively
-    this is actually sending the SCSI command to the drive.
-
-    Note that this uses a Windows event to wait for the drive to reply back
-    which is efficient.  If an event is not available (which should never
-    happen really) a loop is used to poll for reply back.
-
-    Both methods will wait infinitely - so the drive must reply back otherwise
-    this software will appear to hang.  There seems to be no mechanism for
-    cancelling the SRB process - the Win ASPI 32 'SC_ABORT_SRB' command doesn't
-    seem to work.
-*/
-BOOL SendASPICMD_and_wait(BYTE HA_ID, BYTE Target_ID, BYTE SRB_flags, DWORD Buffer_len,
-       PBYTE Buffer, BYTE CDB_len, PBYTE CDB)
-{
-    DWORD           dwASPIStatus;
-    HANDLE          hevent_SRB;  //A handle for a new Windows event
-    SRB_ExecSCSICmd SRB;  //The SRB variable with CDB included
-    BOOL b_retry = TRUE;
-
-    //Clear & setup the SRB for this command..
-    memset(&SRB, 0, sizeof(SRB_ExecSCSICmd));  //Set it to zeroes
-    memcpy(SRB.CDBByte, CDB, CDB_len);  //Copy CDB into SRB
-
-    SRB.SRB_Cmd = SC_EXEC_SCSI_CMD;
-    SRB.SRB_HaId = HA_ID;
-    SRB.SRB_Target = Target_ID;
-    //SRB.SRB_Lun = 0;  //It's already zero
-    SRB.SRB_Flags = SRB_flags;
-    SRB.SRB_BufLen = Buffer_len;
-    SRB.SRB_BufPointer = Buffer;
-    SRB.SRB_SenseLen = SENSE_LEN;
-    SRB.SRB_CDBLen = CDB_len;
-
-    do
-    {
-        /*
-        ** Create an event (if possible) and issue the command.  After sending
-        ** the command, wait for completion.
-        */
-        hevent_SRB = CreateEvent(NULL, TRUE, FALSE, NULL);
-        if (hevent_SRB)
-        {
-            //Windows event method for waiting - efficient.
-
-            SRB.SRB_Flags |= SRB_EVENT_NOTIFY;
-            SRB.SRB_PostProc = (LPVOID)hevent_SRB;
-        
-            //Send the SRB for processing.
-            dwASPIStatus = ASPI_SendASPI32Command((LPSRB)&SRB);
-            if (dwASPIStatus == SS_PENDING)
-            {
-                //Wait for reply back.
-                WaitForSingleObject(hevent_SRB, INFINITE);
-            }
-            CloseHandle(hevent_SRB);
-        }
-        else
-        {
-            //Polling method for waiting - not very efficient.
-
-            //Send the SRB for processing.
-            ASPI_SendASPI32Command((LPSRB)&SRB);
-            //Wait for reply back.
-            while(SRB.SRB_Status == SS_PENDING);
-        };
-
-        /*
-        ** Check for errors.  We'll retry on unit attention condition.  Anything
-        ** else will generate an error msg.
-        */
-        if (SRB.SRB_Status != SS_COMP)
-        {
-                       if (b_retry && (SRB.SRB_TargStat != STATUS_CHKCOND
-                               || (SRB.SenseArea[2] & 0x0F) != KEY_UNITATT))
-                b_retry = FALSE;
-            else
-            {
-                WriteLog("SCSI command failed.\n");
-                return FALSE;
-            }
-        }
-    }
-    while (b_retry == FALSE);
-
-    return TRUE;
-};
-
-/*
-    Lists all available CDROM type drives.  This includes:
-        - CDROM drives
-        - CD rewriters/Combo
-        - DVD drives
-        - DVD rewriters
-        etc
-
-    It can only list the SCSI IDs not drive letters.  Win ASPI 32 does
-    not provide a mechanism for this.  You will have to use windows API
-    for this.
-*/
-VOID ListDevices()
-{
-    BYTE          HaId;
-    BYTE          Target;
-    BYTE          MaxHaId;
-    BYTE          MaxTarget;
-    BYTE          InquiryBuf[36];
-    BYTE          InquiryCDB[6];
-    CHAR          szVendor[9];
-    CHAR          szProduct[17];
-    CHAR          szRev[5];
-    BOOL          bSRB_exec;
-    DWORD         dwASPIStatus;
-    DWORD         dwMaxTransferBytes;    
-    SRB_HAInquiry srbHAInquiry;
-    SRB_GDEVBlock srbGDEVBlock;
-    DWORD         n_CDROM_drives=0;  //No of CDROM type drives found.
-
-    //Use support info for host adapter count and loop over all of them.
-    dwASPIStatus = ASPI_GetASPI32SupportInfo();
-    if(HIBYTE(LOWORD(dwASPIStatus)) == SS_COMP)
-    {
-        MaxHaId = LOBYTE(LOWORD(dwASPIStatus));
-        for(HaId = 0; HaId < MaxHaId; HaId++)
-        {
-            /*
-            ** Do a host adapter inquiry to get max target count.  If the 
-            ** target count isn't 8 or 16 then go with a default of 8.
-            */
-            memset(&srbHAInquiry, 0, sizeof(SRB_HAInquiry));
-            srbHAInquiry.SRB_Cmd = SC_HA_INQUIRY;
-            srbHAInquiry.SRB_HaId = HaId;
-
-            ASPI_SendASPI32Command((LPSRB)&srbHAInquiry);
-            if(srbHAInquiry.SRB_Status != SS_COMP)
-            {
-                continue;
-            };
-
-            MaxTarget = srbHAInquiry.HA_Unique[3];
-            if(MaxTarget != 8 && MaxTarget != 16)
-            {
-                MaxTarget = 8;
-            };
-
-            /*
-            ** Loop over all the targets on this host adapter.
-            */
-            for(Target = 0; Target < MaxTarget; Target++ )
-            {
-                /*
-                ** Issue get device type call to see if there is a device we're
-                ** interested in at this address.  We're interested in CDROMs.
-                */
-                memset(&srbGDEVBlock, 0, sizeof(SRB_GDEVBlock));
-                srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE;
-                srbGDEVBlock.SRB_HaId = HaId;
-                srbGDEVBlock.SRB_Target = Target;
-
-                ASPI_SendASPI32Command((LPSRB)&srbGDEVBlock);
-                if(srbGDEVBlock.SRB_Status != SS_COMP ||
-                  (srbGDEVBlock.SRB_DeviceType != DTYPE_CDROM))
-                {                    
-                    continue;
-                };
-
-                /*
-                ** Determine the max transfer count of this target.  It will
-                ** be the min of the host adapters min count and the size
-                ** of our global transfer buffer.
-                */
-                dwMaxTransferBytes = (DWORD)&srbHAInquiry.HA_Unique[4];
-
-                /*
-                ** Issue an INQUIRY.
-                */
-                memset(InquiryCDB, 0, 6);
-                InquiryCDB[0] = SCSI_INQUIRY;
-                InquiryCDB[4] = 36;  //Size in bytes of inquiry buffer.
-
-                //Send SCSI device inquiry command and wait for completion.
-                bSRB_exec = SendASPICMD_and_wait
-                (
-                    HaId,
-                    Target,
-                    SRB_DIR_IN,
-                    36,
-                    InquiryBuf,
-                    6,
-                    InquiryCDB
-                );
-
-                /*
-                ** Make sure the inquiry worked.  If it failed, or if the
-                ** inquiry data returns a different device type than we got
-                ** before (guards against certain device drivers and against
-                ** vendor unique devices).
-                */
-                if(!bSRB_exec || (InquiryBuf[0] != DTYPE_CDROM))
-                    continue;
-
-                /*
-                ** Add this target to the screen.
-                */
-                WriteLog("Host adapter ID: %ld\n", HaId);
-                WriteLog("Target ID      : %ld\n", Target);
-                WriteLog("LUN ID         : 0\n");
-                WriteLog("Max buffer size: %ld bytes\n", dwMaxTransferBytes);
-
-                memcpy(szVendor, InquiryBuf + 8, 8);                
-                szVendor[8] = '\0';  //Terminate the string
-
-                memcpy(szProduct, InquiryBuf + 16, 16);
-                szProduct[16] = '\0';  //Terminate the string
-
-                memcpy(szRev, InquiryBuf + 32, 4);
-                szRev[4] = '\0';  //Terminate the string
-
-                WriteLog("Vendor         : %s\n", szVendor);
-                WriteLog("Product        : %s\n", szProduct);
-                WriteLog("Revision       : %s\n\n", szRev);
-
-                n_CDROM_drives++;
-            }
-        }
-
-        if (n_CDROM_drives == 0)
-            WriteLog("No CDROM type drives found.\n");
-    }
+               WriteLog("CDINTF: Could not import functions from WNASPI32.DLL!\n");
+               return false;
+       }
+
+       uint32 supportInfo = ASPI_GetASPI32SupportInfo();       // Initialize ASPI layer
+       uint8 retCode = (supportInfo >> 8) & 0xFF;
+       maxHostAdapters = supportInfo & 0xFF;
+
+       if (retCode != SS_COMP && retCode != SS_NO_ADAPTERS)
+       {
+               WriteLog("CDINTF: Could not initialise using GetASPI32SupportInfo function!\n");
+               return false;
+       }
+
+       if (retCode == SS_NO_ADAPTERS)
+       {
+               WriteLog("CDINTF: ASPI initialized, but no host adapters were found!\n");
+               return false;
+       }
+
+/*     // Set timeouts for ALL devices to 15 seconds.  Nothing we deal with should
+       // take that long to do ANYTHING.  We are just doing inquiries to most
+       // devices, and then simple reads to CDs, disks, etc. so 10 seconds (even
+       // if they have to spin up) should be plenty. 
+
+       SRB_GetSetTimeouts srbTimeouts;
+//This doesn't seem to do anything, and isn't even mentioned in Adaptec's ASPI paper...
+//(It *is* mentioned elsewhere, in other Adaptec documentation, and it does nothing because it
+// errors out!)
+//It *does* return code $81 (SS_INVALID_HA) which means it doesn't like $FF for the HAID...
+//OK, it works with Adaptec's driver, but not the default MS driver...
+//Looks like we really don't need it anyway.
+//If we really wanted to, we could do it in CDIntfInit()...!
+       memset(&srbTimeouts, 0, sizeof(SRB_GetSetTimeouts));
+       srbTimeouts.SRB_Cmd = SC_GETSET_TIMEOUTS;
+       srbTimeouts.SRB_Flags = SRB_DIR_OUT;
+       srbTimeouts.SRB_HaId = 0xFF;
+       srbTimeouts.SRB_Target = 0xFF;
+       srbTimeouts.SRB_Lun = 0xFF;
+       srbTimeouts.SRB_Timeout = 15 * 2;
+       ASPI_SendASPI32Command(&srbTimeouts);
+       WriteLog("CDINTF: Set Timeout command returned %02X...\n", srbTimeouts.SRB_Status);//*/
+
+       WriteLog("CDINTF: Successfully initialized.\n");
+       return true;
 }
 
 //
-// 1. Sets up the CDB for MMC readcd (CDB12) command.
-// 2. Send the request to the drive.
-// 3. If success displays the sector data as hex on the screen.
+// Sends the passed in Command Description Block to the APSI layer for processing.
+// Since this uses the asynchronous EXEC_SCSI_CMD, we also wait for completion by
+// using a semaphore.
 //
-BOOL ReadCD(BYTE HA_ID, BYTE Target_ID, long int MMC_LBA_sector)
+static bool SendAsyncASPICmd(uint8 hostID, uint8 targID, uint8 * cdb, uint8 CDBLen,
+       uint8 * buffer, uint32 bufferLen, uint8 SRBFlags)
 {
-    BYTE read_CDB12[12];
-    long int MMC_LBA_sector2;    
-
-    //CDB with values for ReadCD CDB12 command.  The values were taken from MMC1 draft paper.
-    read_CDB12[0] = 0xBE;  //Code for ReadCD CDB12 command
-    read_CDB12[1] = 0;        
-
-    read_CDB12[5] = byte(MMC_LBA_sector);   //Least sig byte of LBA sector no. to read from CD
-    MMC_LBA_sector2 = MMC_LBA_sector >> 8;
-    read_CDB12[4] = byte(MMC_LBA_sector2);  //2nd byte of:
-    MMC_LBA_sector2 = MMC_LBA_sector2 >> 8;
-    read_CDB12[3] = byte(MMC_LBA_sector2);  //3rd byte of:
-    MMC_LBA_sector2 = MMC_LBA_sector2 >> 8;
-    read_CDB12[2] = byte(MMC_LBA_sector2);  //Most significant byte        
-
-    read_CDB12[6] = 0;  //No. of sectors to read from CD byte 2 (MSB)
-    read_CDB12[7] = 0;  //No. of sectors to read from CD byte 1
-    read_CDB12[8] = 1;  //No. of sectors to read from CD byte 0 (LSB)
-    read_CDB12[9] = 0xF8;  //Raw read, 2352 bytes per sector
-    read_CDB12[10] = 0;  //Sub-channel selection bits.
-    read_CDB12[11] = 0;
-
-       return SendASPICMD_and_wait(HA_ID, Target_ID, SRB_DIR_IN, 2352, DataBuf, 12, read_CDB12);
+       SRB_ExecSCSICmd SRB;                                                    // The SRB variable with CDB included
+
+       memset(&SRB, 0, sizeof(SRB));
+       memcpy(SRB.CDBByte, cdb, CDBLen);                               // Copy CDB into SRB's CDB
+
+       SRB.SRB_Cmd        = SC_EXEC_SCSI_CMD;
+       SRB.SRB_Flags      = SRBFlags | SRB_EVENT_NOTIFY;
+       SRB.SRB_HaId       = hostID;
+       SRB.SRB_Target     = targID;
+       SRB.SRB_BufPointer = buffer;
+       SRB.SRB_BufLen     = bufferLen;
+       SRB.SRB_CDBLen     = CDBLen;
+       SRB.SRB_SenseLen   = SENSE_LEN;
+
+       HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+       if (!hEvent)
+       {
+               WriteLog("CDINTF: Couldn't create event!\n");
+               return false;
+       }
+
+       SRB.SRB_PostProc = (void *)hEvent;
+       ASPI_SendASPI32Command(&SRB);
+
+       if (SRB.SRB_Status == SS_PENDING)
+               WaitForSingleObject(hEvent, INFINITE);
+
+       CloseHandle(hEvent);
+
+       if (SRB.SRB_Status != SS_COMP)
+       {
+               WriteLog("CDINTF: SCSI command %02X failed [Error: %02X].\n", SRB.CDBByte[0], SRB.SRB_Status);
+               return false;
+       }
+
+       return true;
 }
 
 //
-// Initialize the SDL sound system
+// OS specific implementation of OS agnostic functions
 //
-void __CDInit(void)
+
+bool CDIntfInit(void)
 {
        if (!InitASPI())
        {
-               WriteLog("Sound: Failed to init ASPI layer!\n");
-               exit(1);//bad!
+               WriteLog("CDINTF: Failed to init Win32 ASPI layer!\n");
+               return false;
+       }
+
+       SRB_HAInquiry srbHAInquiry;
+       SRB_GDEVBlock srbGDEVBlock;
+       uint8 inquiryCDB[6], inquiryBuf[36];
+
+       for(uint8 HAID=0; HAID<maxHostAdapters; HAID++)
+       {
+               memset(&srbHAInquiry, 0, sizeof(srbHAInquiry));
+               srbHAInquiry.SRB_Cmd = SC_HA_INQUIRY;
+               srbHAInquiry.SRB_HaId = HAID;
+
+               ASPI_SendASPI32Command(&srbHAInquiry);
+
+               if (srbHAInquiry.SRB_Status != SS_COMP)
+                       continue;
+
+               // Do a host adapter inquiry to get max target count.  If the 
+               // target count isn't 8 or 16 then go with a default of 8.
+
+               uint8 maxTargets = srbHAInquiry.HA_Unique[3];
+               if (maxTargets != 8 && maxTargets != 16)
+                       maxTargets = 8;
+
+               // Loop over all the targets on this host adapter.
+
+               for(uint8 target=0; target<maxTargets; target++)
+               {
+                       // Issue get device type call to see if there is a device we're
+                       // interested in at this address.  We're interested in CDROMs.
+
+                       memset(&srbGDEVBlock, 0, sizeof(srbGDEVBlock));
+                       srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE;
+                       srbGDEVBlock.SRB_HaId = HAID;
+                       srbGDEVBlock.SRB_Target = target;
+
+                       ASPI_SendASPI32Command(&srbGDEVBlock);
+
+                       if (srbGDEVBlock.SRB_Status != SS_COMP || srbGDEVBlock.SRB_DeviceType != DTYPE_CDROM)
+                               continue;
+
+                       memset(inquiryCDB, 0, 6);                               // Issue an INQUIRY.
+                       inquiryCDB[0] = SCSI_INQUIRY;
+                       inquiryCDB[4] = 36;                                             // Size in bytes of inquiry buffer.
+
+                       bool successful = SendAsyncASPICmd(HAID, target, inquiryCDB, 6, inquiryBuf, 36, SRB_DIR_IN);
+
+                       // Make sure the inquiry worked. Check if it failed, or if the inquiry data
+                       // returns a different device type than we got before (guards against certain
+                       // device drivers and against vendor unique devices).
+
+                       if (!successful || inquiryBuf[0] != DTYPE_CDROM)
+                               continue;
+
+                       haID[numCDDrives] = HAID, tID[numCDDrives] = target;
+
+                       // Here we do a 'stringTrimRight' on the vendor and product strings...
+
+                       uint32 vendorSize = 0, productSize = 0;
+
+                       for(int i=7; i>=0; i--)
+                       {
+                               if (inquiryBuf[8+i] != ' ')
+                               {
+                                       vendorSize = i + 1;
+                                       break;
+                               }
+                       }
+
+                       for(int i=15; i>=0; i--)
+                       {
+                               if (inquiryBuf[16+i] != ' ')
+                               {
+                                       productSize = i + 1;
+                                       break;
+                               }
+                       }
+
+                       memcpy(driveName[numCDDrives], inquiryBuf + 8, vendorSize);
+                       driveName[numCDDrives][vendorSize] = ' ';
+                       memcpy(driveName[numCDDrives] + vendorSize + 1, inquiryBuf + 16, productSize);
+                       driveName[numCDDrives][vendorSize + productSize + 1] = 0;
+
+                       WriteLog("CDINTF: Found CD-ROM device [%s]. HAID:%u, TID:%u LUN:0\n", driveName[numCDDrives], haID[numCDDrives], tID[numCDDrives]);
+
+                       numCDDrives++;
+               }
+       }
+
+       if (numCDDrives == 0)
+       {
+               WriteLog("CDINTF: No CDROM type drives found.\n");
+               return false;
        }
+
+//Most likely, will need to read a default out of the config file. But for now... !!! FIX !!!
+       driveNum = 0;                                                           // For now, default to first drive found
+
+       return true;
 }
 
-//
-// Close down the SDL sound subsystem
-//
-void __CDDone(void)
+void CDIntfDone(void)
 {
-    //Unload ASPI if it has been loaded.
-       if (WNASPI32_handle)
-               FreeLibrary(WNASPI32_handle);
+       if (hASPILib)
+               FreeLibrary(hASPILib);                                          // Unload ASPI library if it was loaded.
 }
 
-/*//
-// Sound card callback handler
-//
-void SDLSoundCallback(void * userdata, Uint8 * buffer, int length)
+bool CDIntfReadBlock(uint32 sector, uint8 * buffer)
+{
+       uint8 cdb[12];
+
+       memset(cdb, 0, sizeof(cdb));
+       // 0: command, 2-5: block # (hi->lo) 6-8: number of blocks to read, 9: read type,
+       // 10: subchannel select
+       cdb[0] = 0xBE;                                                                  // Code for ReadCD CDB12 command
+       cdb[2] = (sector >> 24) & 0xFF;
+       cdb[3] = (sector >> 16) & 0xFF;
+       cdb[4] = (sector >> 8) & 0xFF;
+       cdb[5] = sector & 0xFF;
+       cdb[8] = 1;                                                                             // No. of sectors to read from CD (LSB)
+       cdb[9] = 0xF8;                                                                  // Raw read, 2352 bytes per sector
+       cdb[10] = 1;                                                                    // Selects read RAW 96 bytes/sector sub-channel data (Raw P-W)
+
+       return SendAsyncASPICmd(haID[driveNum], tID[driveNum], cdb, 12, buffer, 2352+96, SRB_DIR_IN);
+}
+
+uint32 CDIntfGetNumSessions(void)
 {
-       if (remain > 0)
+//     WriteLog("CDINTF: GetNumSessions unimplemented!\n");
+       // Still need relevant code here... !!! FIX !!! [DONE]
+       if (!readTOC)
+               GetRawTOC();
+
+       return numSessions - 1;
+}
+
+void CDIntfSelectDrive(uint32 driveNum)
+{
+       if (driveNum < numCDDrives)
+               driveNum = driveNum;
+}
+
+uint32 CDIntfGetCurrentDrive(void)
+{
+       return driveNum;
+}
+
+const uint8 * CDIntfGetDriveName(uint32 driveNum)
+{
+       if (driveNum > numCDDrives)
+               return NULL;
+
+       return driveName[driveNum];
+}
+
+//This stuff could probably be OK in the unified cdintf.cpp file...
+uint8 CDIntfGetSessionInfo(uint32 session, uint32 offset)
+{
+// Need better error handling than this... !!! FIX !!!
+       if (!readTOC)
+               if (!GetRawTOC())
+                       return 0xFF;
+
+       if (session >= numSessions || offset > 4)
+               return 0xFF;                                                            // Bad index passed in...
+
+       return sessions[session][offset];
+}
+
+uint8 CDIntfGetTrackInfo(uint32 track, uint32 offset)
+{
+// Need better error handling than this... !!! FIX !!!
+       if (!readTOC)
+               if (!GetRawTOC())
+                       return 0xFF;
+
+       if (track > numTracks || offset > 2)
+               return 0xFF;                                                            // Bad index passed in...
+
+       return tracks[track][offset];
+}
+
+//OK, now the rest is OK, but this is still locking up like a MF!
+// Testing, testing...
+//Still don't know why this is locking up! Especially as the following function works! Aarrrgggghhhhh!
+//It was the dataLen. For some reason, it needs at *least* 11 more bytes (could be less!)
+/*static*/ bool GetRawTOC(void)
+{
+       uint8 cmd[10];
+       uint8 reqData[4];
+
+       // Read disk TOC length
+       memset(cmd, 0, 10);
+       cmd[0] = SCSI_READ_TOC;
+       cmd[2] = 2;                                                                             // Get session info also
+       cmd[6] = 1;                                                                             // Session # to start reading
+       cmd[8] = 4;                                                                             // Buffer length
+
+       if (!SendAsyncASPICmd(haID[driveNum], tID[driveNum], cmd, 10, reqData, 4, SRB_DIR_IN))
        {
-               memcpy(buffer, DataBuf + 2352 - remain, remain);
-               length -= remain;
-               buffer += remain;
-               remain = 0;
+               WriteLog("TOC: Cannot read disk TOC length.\n");
+               return false;
        }
 
-       while (length > 0)
+       // Header is total TOC space needed + header (0-1), min session (2), max session (3)
+//     uint32 dataLen = ((reqData[0] << 8) | reqData[1]);
+       uint32 dataLen = ((reqData[0] << 8) | reqData[1]) + 11; // Why the extra???
+  
+       WriteLog("TOC: Raw TOC data len: %d\n", dataLen);
+
+       uint8 * data = new uint8[dataLen];
+  
+       // Read disk TOC
+       cmd[7] = dataLen >> 8;
+       cmd[8] = dataLen;
+
+       if (!SendAsyncASPICmd(haID[driveNum], tID[driveNum], cmd, 10, data, dataLen, SRB_DIR_IN))
        {
-               ReadCD(0, 1, sector++);
-               memcpy(buffer, DataBuf, (length >= 2352 ? 2352 : length));
-               length -= 2352;
-               buffer += 2352;
+               delete[] data;
+               WriteLog("TOC: Cannot read disk TOC.\n");
+               return false;
        }
 
-       if (length < 0)
-               remain = -length;
-}*/
+       int numEntries = (((data[0] << 8) | data[1]) - 2) / 11;
+       uint8 * p = data + 4;
+
+       numSessions = data[3], numTracks = 0;
+       // Important entries are 0, 3, 8, 9, 10 (session #, track #, M, S, F)
+//     WriteLog("TOC: [Sess] [adrCtl] [?] [point] [?] [?] [?] [?] [pmin] [psec] [pframe]\n");
+       uint32 firstTrackOffset = 0;
+       for(int i=0; i<numEntries; i++, p+=11)
+       {
+/*             WriteLog("TOC: %d %02x %02d %2x %02d:%02d:%02d %02d %02d:%02d:%02d",
+                       p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10]);
+
+               if (p[3] > 0 && p[3] < 99)
+                       WriteLog("   <-- Track #%u", p[3]);
+
+               WriteLog("\n");//*/
+
+               // We do session # - 1 to make it zero-based, since this is what the Jaguar
+               // CD BIOS expects. We leave the tracks one-based.
+
+               uint32 s = p[0] - 1, t = p[3];
+
+               if (t < 100)
+               {
+                       if (t == 1)
+                               firstTrackOffset = (((p[8] * 60) + p[9]) * 75) + p[10];
+
+                       tracks[t][0] = p[8], tracks[t][1] = p[9], tracks[t][2] = p[10];
+
+                       // For some reason, the TOC returned from the "session TOC" command
+                       // causes all tracks to have a 150 block (from what I've seen) offset
+                       // from what's reported. Apparently it's not possible to read those
+                       // first 150 blocks using the current incarnation of CDIntf_ReadBlock.
+                       // So we subtract the offset out here...
+
+                       uint32 curTrack = (((tracks[t][0] * 60) + tracks[t][1]) * 75) + tracks[t][2];
+                       curTrack -= firstTrackOffset;
+                       tracks[t][2] = curTrack % 75;
+                       curTrack /= 75;
+                       tracks[t][1] = curTrack % 60;
+                       tracks[t][0] = curTrack / 60;
+
+                       if (t > numTracks)
+                               numTracks = t;
+               }
+               else if (t == 0xA0)
+                       sessions[s][0] = p[8];
+               else if (t == 0xA1)
+                       sessions[s][1] = p[8];
+               else if (t == 0xA2)
+                       sessions[s][2] = p[8], sessions[s][3] = p[9], sessions[s][4] = p[10];
+       }
+
+WriteLog("CDINTF: Disc summary\n        # of sessions: %u, # of tracks: %u\n", numSessions, numTracks);
+WriteLog("        Session info:\n");
+for(uint32 i=0; i<numSessions; i++)
+       WriteLog("        %u: min track=%2u, max track=%2u, lead out=%2d:%02d:%02d\n", i+1, sessions[i][0], sessions[i][1], sessions[i][2], sessions[i][3], sessions[i][4]);
+WriteLog("        Track info:\n");
+for(uint32 i=1; i<=numTracks; i++)
+       WriteLog("        %2u: start=%2d:%02d:%02d\n", i, tracks[i][0], tracks[i][1], tracks[i][2]);
+
+       delete[] data;
+       readTOC = true;
+
+       return true;
+}