--- BasiliskII/src/cdrom.cpp 1999/10/03 14:16:25 1.1.1.1 +++ BasiliskII/src/cdrom.cpp 2004/01/12 15:29:21 1.20 @@ -1,7 +1,7 @@ /* * cdrom.cpp - CD-ROM driver * - * Basilisk II (C) 1997-1999 Christian Bauer + * Basilisk II (C) 1997-2004 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,9 +28,15 @@ * Technote FL 36: "Apple Extensions to ISO 9660" */ +#include "sysdeps.h" + #include +#include + +#ifndef NO_STD_NAMESPACE +using std::vector; +#endif -#include "sysdeps.h" #include "cpu_emulation.h" #include "main.h" #include "macos_util.h" @@ -97,7 +103,7 @@ static const uint8 bin2bcd[256] = { }; static const uint8 bcd2bin[256] = { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -117,22 +123,17 @@ static const uint8 bcd2bin[256] = { // Struct for each drive -struct DriveInfo { - DriveInfo() - { - next = NULL; - num = 0; - fh = NULL; - start_byte = 0; - status = 0; - } +struct cdrom_drive_info { + cdrom_drive_info() : num(0), fh(NULL), start_byte(0), status(0) {} + cdrom_drive_info(void *fh_) : num(0), fh(fh_), start_byte(0), status(0) {} + + void close_fh(void) { SysAllowRemoval(fh); Sys_close(fh); } - DriveInfo *next; // Pointer to next DriveInfo (must be first in struct!) int num; // Drive number void *fh; // File handle int block_size; // CD-ROM block size int twok_offset; // Offset of beginning of 2K block to last Prime position - uint32 start_byte; // Start of HFS partition on disk + loff_t start_byte; // Start of HFS partition on disk bool to_be_mounted; // Flag: drive must be mounted in accRun bool mount_non_hfs; // Flag: Issue disk-inserted events for non-HFS disks @@ -145,26 +146,29 @@ struct DriveInfo { uint32 status; // Mac address of drive status record }; -// Linked list of DriveInfos -static DriveInfo *first_drive_info; +// List of drives handled by this driver +typedef vector drive_vec; +static drive_vec drives; // Icon address (Mac address space, set by PatchROM()) uint32 CDROMIconAddr; +// Flag: Control(accRun) has been called, interrupt routine is now active +static bool acc_run_called = false; + /* - * Get pointer to drive info, NULL = invalid drive number + * Get pointer to drive info or drives.end() if not found */ -static DriveInfo *get_drive_info(int num) +static drive_vec::iterator get_drive_info(int num) { - DriveInfo *info = first_drive_info; - while (info != NULL) { + drive_vec::iterator info, end = drives.end(); + for (info = drives.begin(); info != end; ++info) { if (info->num == num) return info; - info = info->next; } - return NULL; + return info; } @@ -172,29 +176,28 @@ static DriveInfo *get_drive_info(int num * Find HFS partition, set info->start_byte (0 = no HFS partition) */ -static void find_hfs_partition(DriveInfo *info) +static void find_hfs_partition(cdrom_drive_info &info) { - info->start_byte = 0; + info.start_byte = 0; uint8 *map = new uint8[512]; + D(bug("Looking for HFS partitions on CD-ROM...\n")); // Search first 64 blocks for HFS partition for (int i=0; i<64; i++) { - if (Sys_read(info->fh, map, i * 512, 512) != 512) + if (Sys_read(info.fh, map, i * 512, 512) != 512) break; + D(bug(" block %d, signature '%c%c' (%02x%02x)\n", i, map[0], map[1], map[0], map[1])); - // Skip driver descriptor - uint16 sig = ntohs(((uint16 *)map)[0]); - if (sig == 'ER') + // Not a partition map block? Then look at next block + uint16 sig = (map[0] << 8) | map[1]; + if (sig != 0x504d) continue; - // No partition map? Then look at next block - if (sig != 'PM') - continue; - - // Partition map found, Apple HFS partition? + // Partition map block found, Apple HFS partition? if (strcmp((char *)(map + 48), "Apple_HFS") == 0) { - info->start_byte = ntohl(((uint32 *)map)[2]) << 9; - D(bug(" HFS partition found at %ld, %ld blocks\n", info->start_byte, ntohl(((uint32 *)map)[3]))); + info.start_byte = (loff_t)((map[8] << 24) | (map[9] << 16) | (map[10] << 8) | map[11]) << 9; + uint32 num_blocks = (map[12] << 24) | (map[13] << 16) | (map[14] << 8) | map[15]; + D(bug(" HFS partition found at %d, %d blocks\n", info.start_byte, num_blocks)); break; } } @@ -206,26 +209,37 @@ static void find_hfs_partition(DriveInfo * Read TOC of disk and set lead_out */ -static void read_toc(DriveInfo *info) +static void read_toc(cdrom_drive_info &info) { // Read TOC - memset(&info->toc, 0, sizeof(info->toc)); - SysCDReadTOC(info->fh, info->toc); - D(bug(" TOC: %08lx %08lx\n", ntohl(((uint32 *)info->toc)[0]), ntohl(((uint32 *)info->toc)[1]))); + memset(info.toc, 0, sizeof(info.toc)); + SysCDReadTOC(info.fh, info.toc); + +#if DEBUG + // Dump TOC for debugging + D(bug(" TOC:\n %02x%02x%02x%02x : %d bytes, first track = %d, last track = %d\n", info.toc[0], info.toc[1], info.toc[2], info.toc[3], (info.toc[0] << 8) | info.toc[1], info.toc[2], info.toc[3])); + for (int i=4; i<804; i+=8) { + D(bug(" %02x%02x%02x%02x%02x%02x%02x%02x: ", info.toc[i+0], info.toc[i+1], info.toc[i+2], info.toc[i+3], info.toc[i+4], info.toc[i+5], info.toc[i+6], info.toc[i+7])); + const char *type = (info.toc[i+2] == 0xaa ? "lead-out" : (info.toc[i+1] & 0x04 ? "data" : "audio")); + D(bug("track %d (%s), addr/ctrl 0x%02x, M %d S %d F %d\n", info.toc[i+2], type, info.toc[i+1], info.toc[i+5], info.toc[i+6], info.toc[i+7])); + if (info.toc[i+2] == 0xaa) + break; + } +#endif // Find lead-out track - info->lead_out[0] = 0; - info->lead_out[1] = 0; - info->lead_out[2] = 0; + info.lead_out[0] = 0; + info.lead_out[1] = 0; + info.lead_out[2] = 0; for (int i=4; i<804; i+=8) { - if (info->toc[i+2] == 0xaa) { - info->stop_at[0] = info->lead_out[0] = info->toc[i+5]; - info->stop_at[1] = info->lead_out[1] = info->toc[i+6]; - info->stop_at[2] = info->lead_out[2] = info->toc[i+7]; + if (info.toc[i+2] == 0xaa) { + info.stop_at[0] = info.lead_out[0] = info.toc[i+5]; + info.stop_at[1] = info.lead_out[1] = info.toc[i+6]; + info.stop_at[2] = info.lead_out[2] = info.toc[i+7]; break; } } - D(bug(" Lead-Out M %d S %d F %d\n", info->lead_out[0], info->lead_out[1], info->lead_out[2])); + D(bug(" Lead-Out M %d S %d F %d\n", info.lead_out[0], info.lead_out[1], info.lead_out[2])); } @@ -234,7 +248,7 @@ static void read_toc(DriveInfo *info) * Return: false = error */ -static bool position2msf(DriveInfo *info, uint16 postype, uint32 pos, bool stopping, uint8 &m, uint8 &s, uint8 &f) +static bool position2msf(const cdrom_drive_info &info, uint16 postype, uint32 pos, bool stopping, uint8 &m, uint8 &s, uint8 &f) { switch (postype) { case 0: @@ -252,10 +266,10 @@ static bool position2msf(DriveInfo *info if (stopping) track++; for (int i=4; i<804; i+=8) { - if (info->toc[i+2] == track || info->toc[i+2] == 0xaa) { - m = info->toc[i+5]; - s = info->toc[i+6]; - f = info->toc[i+7]; + if (info.toc[i+2] == track || info.toc[i+2] == 0xaa) { + m = info.toc[i+5]; + s = info.toc[i+6]; + f = info.toc[i+7]; return true; } } @@ -273,25 +287,17 @@ static bool position2msf(DriveInfo *info void CDROMInit(void) { - first_drive_info = NULL; - // No drives specified in prefs? Then add defaults if (PrefsFindString("cdrom", 0) == NULL) SysAddCDROMPrefs(); // Add drives specified in preferences - int32 index = 0; + int index = 0; const char *str; while ((str = PrefsFindString("cdrom", index++)) != NULL) { void *fh = Sys_open(str, true); - if (fh) { - DriveInfo *info = new DriveInfo; - info->fh = fh; - DriveInfo *p = (DriveInfo *)&first_drive_info; - while (p->next != NULL) - p = p->next; - p->next = info; - } + if (fh) + drives.push_back(cdrom_drive_info(fh)); } } @@ -302,13 +308,10 @@ void CDROMInit(void) void CDROMExit(void) { - DriveInfo *info = first_drive_info, *next; - while (info != NULL) { - Sys_close(info->fh); - next = info->next; - delete info; - info = next; - } + drive_vec::iterator info, end = drives.end(); + for (info = drives.begin(); info != end; ++info) + info->close_fh(); + drives.clear(); } @@ -318,14 +321,15 @@ void CDROMExit(void) bool CDROMMountVolume(void *fh) { - DriveInfo *info; - for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ; - if (info) { + drive_vec::iterator info = drives.begin(), end = drives.end(); + while (info != end && info->fh != fh) + ++info; + if (info != end) { if (SysIsDiskInserted(info->fh)) { SysPreventRemoval(info->fh); WriteMacInt8(info->status + dsDiskInPlace, 1); - read_toc(info); - find_hfs_partition(info); + read_toc(*info); + find_hfs_partition(*info); if (info->start_byte != 0 || info->mount_non_hfs) info->to_be_mounted = true; } @@ -336,6 +340,37 @@ bool CDROMMountVolume(void *fh) /* + * Mount volumes for which the to_be_mounted flag is set + * (called during interrupt time) + */ + +static void mount_mountable_volumes(void) +{ + drive_vec::iterator info, end = drives.end(); + for (info = drives.begin(); info != end; ++info) { + + // Disk in drive? + if (ReadMacInt8(info->status + dsDiskInPlace) == 0) { + + // No, check if disk was inserted + if (SysIsDiskInserted(info->fh)) + CDROMMountVolume(info->fh); + } + + // Mount disk if flagged + if (info->to_be_mounted) { + D(bug(" mounting drive %d\n", info->num)); + M68kRegisters r; + r.d[0] = info->num; + r.a[0] = 7; // diskEvent + Execute68kTrap(0xa02f, &r); // PostEvent() + info->to_be_mounted = false; + } + } +} + + +/* * Driver Open() routine */ @@ -345,9 +380,11 @@ int16 CDROMOpen(uint32 pb, uint32 dce) // Set up DCE WriteMacInt32(dce + dCtlPosition, 0); + acc_run_called = false; // Install drives - for (DriveInfo *info = first_drive_info; info; info = info->next) { + drive_vec::iterator info, end = drives.end(); + for (info = drives.begin(); info != end; ++info) { info->num = FindFreeDriveNumber(1); info->to_be_mounted = false; @@ -377,8 +414,8 @@ int16 CDROMOpen(uint32 pb, uint32 dce) if (SysIsDiskInserted(info->fh)) { SysPreventRemoval(info->fh); WriteMacInt8(info->status + dsDiskInPlace, 1); - read_toc(info); - find_hfs_partition(info); + read_toc(*info); + find_hfs_partition(*info); info->to_be_mounted = true; } @@ -402,8 +439,8 @@ int16 CDROMPrime(uint32 pb, uint32 dce) WriteMacInt32(pb + ioActCount, 0); // Drive valid and disk inserted? - DriveInfo *info; - if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL) + drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum)); + if (info == drives.end()) return nsDrvErr; if (ReadMacInt8(info->status + dsDiskInPlace) == 0) return offLinErr; @@ -456,30 +493,10 @@ int16 CDROMControl(uint32 pb, uint32 dce case 1: // KillIO return noErr; - case 65: { // Periodic action ("insert" disks on startup and check for disk changes) - DriveInfo *info = first_drive_info; - while (info != NULL) { - - // Disk in drive? - if (ReadMacInt8(info->status + dsDiskInPlace) == 0) { - - // No, check if disk was inserted - if (SysIsDiskInserted(info->fh)) - CDROMMountVolume(info->fh); - } - - // Mount disk if flagged - if (info->to_be_mounted) { - D(bug(" mounting drive %d\n", info->num)); - M68kRegisters r; - r.d[0] = info->num; - r.a[0] = 7; // diskEvent - Execute68kTrap(0xa02f, &r); // PostEvent() - info->to_be_mounted = false; - } - - info = info->next; - } + case 65: { // Periodic action (accRun, "insert" disks on startup) + mount_mountable_volumes(); + WriteMacInt16(dce + dCtlFlags, ReadMacInt16(dce + dCtlFlags) & ~0x2000); // Disable periodic action + acc_run_called = true; return noErr; } @@ -489,12 +506,13 @@ int16 CDROMControl(uint32 pb, uint32 dce } // Drive valid? - DriveInfo *info; - if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL) - if (first_drive_info == NULL) + drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum)); + if (info == drives.end()) { + if (drives.empty()) return nsDrvErr; else - info = first_drive_info; // This is needed for Apple's Audio CD program + info = drives.begin(); // This is needed for Apple's Audio CD program + } // Drive-specific codes switch (code) { @@ -521,7 +539,7 @@ int16 CDROMControl(uint32 pb, uint32 dce WriteMacInt32(pb + csParam, CDROMIconAddr); return noErr; - case 23: // DriveInfo + case 23: // drive_info WriteMacInt32(pb + csParam, 0x00000b01); // Unspecified external removable SCSI disk return noErr; @@ -581,7 +599,7 @@ int16 CDROMControl(uint32 pb, uint32 dce break; case 3: { // Get track starting address - uint8 *buf = Mac2HostAddr(ReadMacInt32(pb + csParam + 2)); + uint32 buf = ReadMacInt32(pb + csParam + 2); uint16 buf_size = ReadMacInt16(pb + csParam + 6); int track = bcd2bin[ReadMacInt8(pb + csParam + 8)]; @@ -595,10 +613,10 @@ int16 CDROMControl(uint32 pb, uint32 dce // Fill buffer if (i != 804) while (buf_size > 0) { - *buf++ = info->toc[i+1] & 0x0f; // Control - *buf++ = bin2bcd[info->toc[i+5]]; // M - *buf++ = bin2bcd[info->toc[i+6]]; // S - *buf++ = bin2bcd[info->toc[i+7]]; // F + WriteMacInt8(buf, info->toc[i+1] & 0x0f); buf++; // Control + WriteMacInt8(buf, bin2bcd[info->toc[i+5]]); buf++; // M + WriteMacInt8(buf, bin2bcd[info->toc[i+6]]); buf++; // S + WriteMacInt8(buf, bin2bcd[info->toc[i+7]]); buf++; // F // Lead-Out? Then stop if (info->toc[i+2] == 0xaa) @@ -629,23 +647,23 @@ int16 CDROMControl(uint32 pb, uint32 dce case 101: { // ReadTheQSubcode if (ReadMacInt8(info->status + dsDiskInPlace) == 0) { - memset(Mac2HostAddr(pb + csParam), 0, 10); + Mac_memset(pb + csParam, 0, 10); return offLinErr; } uint8 pos[16]; if (SysCDGetPosition(info->fh, pos)) { - uint8 *p = Mac2HostAddr(pb + csParam); - *p++ = pos[5] & 0x0f; // Control - *p++ = bin2bcd[pos[6]]; // Track number - *p++ = bin2bcd[pos[7]]; // Index number - *p++ = bin2bcd[pos[13]]; // M (rel) - *p++ = bin2bcd[pos[14]]; // S (rel) - *p++ = bin2bcd[pos[15]]; // F (rel) - *p++ = bin2bcd[pos[9]]; // M (abs) - *p++ = bin2bcd[pos[10]]; // S (abs) - *p++ = bin2bcd[pos[11]]; // F (abs) - *p++ = 0; + uint32 p = pb + csParam; + WriteMacInt8(p, pos[5] & 0x0f); p++; // Control + WriteMacInt8(p, bin2bcd[pos[6]]); p++; // Track number + WriteMacInt8(p, bin2bcd[pos[7]]); p++; // Index number + WriteMacInt8(p, bin2bcd[pos[13]]); p++; // M (rel) + WriteMacInt8(p, bin2bcd[pos[14]]); p++; // S (rel) + WriteMacInt8(p, bin2bcd[pos[15]]); p++; // F (rel) + WriteMacInt8(p, bin2bcd[pos[9]]); p++; // M (abs) + WriteMacInt8(p, bin2bcd[pos[10]]); p++; // S (abs) + WriteMacInt8(p, bin2bcd[pos[11]]); p++; // F (abs) + WriteMacInt8(p, 0); return noErr; } else return ioErr; @@ -656,12 +674,12 @@ int16 CDROMControl(uint32 pb, uint32 dce return controlErr; case 103: { // AudioTrackSearch - D(bug(" AudioTrackSearch postype %d, pos %08lx, hold %d\n", ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), ReadMacInt16(pb + csParam + 6))); + D(bug(" AudioTrackSearch postype %d, pos %08x, hold %d\n", ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), ReadMacInt16(pb + csParam + 6))); if (ReadMacInt8(info->status + dsDiskInPlace) == 0) return offLinErr; uint8 start_m, start_s, start_f; - if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f)) + if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f)) return paramErr; info->play_mode = ReadMacInt8(pb + csParam + 9) & 0x0f; if (!SysCDPlay(info->fh, start_m, start_s, start_f, info->stop_at[0], info->stop_at[1], info->stop_at[2])) @@ -678,12 +696,12 @@ int16 CDROMControl(uint32 pb, uint32 dce if (ReadMacInt16(pb + csParam + 6)) { // Given stopping address - if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2])) + if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2])) return paramErr; } else { // Given starting address uint8 start_m, start_s, start_f; - if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f)) + if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f)) return paramErr; info->play_mode = ReadMacInt8(pb + csParam + 9) & 0x0f; if (!SysCDPlay(info->fh, start_m, start_s, start_f, info->stop_at[0], info->stop_at[1], info->stop_at[2])) @@ -720,7 +738,7 @@ int16 CDROMControl(uint32 pb, uint32 dce return paramErr; } else { // Given stopping address - if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2])) + if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2])) return paramErr; } return noErr; @@ -733,29 +751,30 @@ int16 CDROMControl(uint32 pb, uint32 dce if (!SysCDGetPosition(info->fh, pos)) return paramErr; - uint8 *p = Mac2HostAddr(pb + csParam); + uint32 p = pb + csParam; switch (pos[1]) { case 0x11: - *p++ = 0; // Audio play in progress + WriteMacInt8(p, 0); // Audio play in progress break; case 0x12: - *p++ = 1; // Audio play paused + WriteMacInt8(p, 1); // Audio play paused break; case 0x13: - *p++ = 3; // Audio play completed + WriteMacInt8(p, 3); // Audio play completed break; case 0x14: - *p++ = 4; // Error occurred + WriteMacInt8(p, 4); // Error occurred break; default: - *p++ = 5; // No audio play operation requested + WriteMacInt8(p, 5); // No audio play operation requested break; } - *p++ = info->play_mode; - *p++ = pos[5] & 0x0f; // Control - *p++ = bin2bcd[pos[9]]; // M (abs) - *p++ = bin2bcd[pos[10]]; // S (abs) - *p++ = bin2bcd[pos[11]]; // F (abs) + p++; + WriteMacInt8(p, info->play_mode); p++; + WriteMacInt8(p, pos[5] & 0x0f); p++; // Control + WriteMacInt8(p, bin2bcd[pos[9]]); p++; // M (abs) + WriteMacInt8(p, bin2bcd[pos[10]]); p++; // S (abs) + WriteMacInt8(p, bin2bcd[pos[11]]); p++; // F (abs) return noErr; } @@ -764,7 +783,7 @@ int16 CDROMControl(uint32 pb, uint32 dce return offLinErr; uint8 start_m, start_s, start_f; - if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f)) + if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f)) return paramErr; if (!SysCDScan(info->fh, start_m, start_s, start_f, ReadMacInt16(pb + csParam + 6))) @@ -842,48 +861,48 @@ int16 CDROMControl(uint32 pb, uint32 dce int16 CDROMStatus(uint32 pb, uint32 dce) { - DriveInfo *info = get_drive_info(ReadMacInt16(pb + ioVRefNum)); + drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum)); uint16 code = ReadMacInt16(pb + csCode); D(bug("CDROMStatus %d\n", code)); - // General codes + // General codes (we can get these even if the drive was invalid) switch (code) { case 43: { // DriverGestalt uint32 sel = ReadMacInt32(pb + csParam); D(bug(" driver gestalt %c%c%c%c\n", sel >> 24, sel >> 16, sel >> 8, sel)); switch (sel) { - case 'vers': // Version + case FOURCC('v','e','r','s'): // Version WriteMacInt32(pb + csParam + 4, 0x05208000); break; - case 'devt': // Device type - WriteMacInt32(pb + csParam + 4, 'cdrm'); + case FOURCC('d','e','v','t'): // Device type + WriteMacInt32(pb + csParam + 4, FOURCC('c','d','r','m')); break; - case 'intf': // Interface type - WriteMacInt32(pb + csParam + 4, 'basi'); + case FOURCC('i','n','t','f'): // Interface type + WriteMacInt32(pb + csParam + 4, EMULATOR_ID_4); break; - case 'sync': // Only synchronous operation? + case FOURCC('s','y','n','c'): // Only synchronous operation? WriteMacInt32(pb + csParam + 4, 0x01000000); break; - case 'boot': // Boot ID - if (info != NULL) + case FOURCC('b','o','o','t'): // Boot ID + if (info != drives.end()) WriteMacInt16(pb + csParam + 4, info->num); else WriteMacInt16(pb + csParam + 4, 0); WriteMacInt16(pb + csParam + 6, (uint16)CDROMRefNum); break; - case 'wide': // 64-bit access supported? + case FOURCC('w','i','d','e'): // 64-bit access supported? WriteMacInt16(pb + csParam + 4, 0); break; - case 'purg': // Purge flags + case FOURCC('p','u','r','g'): // Purge flags WriteMacInt32(pb + csParam + 4, 0); break; - case 'ejec': // Eject flags + case FOURCC('e','j','e','c'): // Eject flags WriteMacInt32(pb + csParam + 4, 0x00030003); // Don't eject on shutdown/restart break; - case 'flus': // Flush flags + case FOURCC('f','l','u','s'): // Flush flags WriteMacInt16(pb + csParam + 4, 0); break; - case 'vmop': // Virtual memory attributes + case FOURCC('v','m','o','p'): // Virtual memory attributes WriteMacInt32(pb + csParam + 4, 0); // Drive not available for VM break; default: @@ -894,16 +913,27 @@ int16 CDROMStatus(uint32 pb, uint32 dce) } // Drive valid? - if (info == NULL) - if (first_drive_info == NULL) + if (info == drives.end()) { + if (drives.empty()) return nsDrvErr; else - info = first_drive_info; // This is needed for Apple's Audio CD program + info = drives.begin(); // This is needed for Apple's Audio CD program + } // Drive-specific codes switch (code) { + case 6: // Return format list + if (ReadMacInt16(pb + csParam) > 0) { + uint32 adr = ReadMacInt32(pb + csParam + 2); + WriteMacInt16(pb + csParam, 1); // 1 format + WriteMacInt32(adr, SysGetFileSize(info->fh) / 512); // Number of blocks + WriteMacInt32(adr + 4, 0); // heads/track/sectors + return noErr; + } else + return paramErr; + case 8: // DriveStatus - memcpy(Mac2HostAddr(pb + csParam), Mac2HostAddr(info->status), 22); + Mac2Mac_memcpy(pb + csParam, info->status, 22); return noErr; case 70: // GetPowerMode @@ -939,3 +969,16 @@ int16 CDROMStatus(uint32 pb, uint32 dce) return statusErr; } } + + +/* + * Driver interrupt routine (1Hz) - check for volumes to be mounted + */ + +void CDROMInterrupt(void) +{ + if (!acc_run_called) + return; + + mount_mountable_volumes(); +}