From 4f7fd842298ffaec0fe77b3451c5477b2be979ea Mon Sep 17 00:00:00 2001 From: OBattler Date: Mon, 16 Jan 2017 01:49:19 +0100 Subject: [PATCH] Overhauled and unified CD-ROM emulation; Four CD-ROM drives are now emulated; ATAPI DMA is now emulated; Unified CD-ROM pass through to host drive handling; Applied all (applicable) mainline PCem commits. --- src/Makefile.mingw | 4 +- src/Makefile.mingw64 | 5 +- src/buslogic.c | 269 ++-- src/cdrom-ioctl.c | 1155 +++++++-------- src/cdrom-ioctl.h | 6 +- src/cdrom-iso.c | 414 ++++-- src/cdrom-iso.h | 10 +- src/cdrom-null.c | 93 +- src/cdrom-null.h | 6 +- src/cdrom.c | 2867 ++++++++++++++++++++++++++++++++++++++ src/cdrom.h | 219 ++- src/codegen_ops_x86-64.h | 208 ++- src/codegen_ops_x86.h | 6 +- src/codegen_x86-64.h | 2 +- src/disc_86f.c | 128 +- src/dma.c | 29 +- src/fdc.c | 125 +- src/ibm.h | 4 - src/ide.c | 2170 ++++++++--------------------- src/ide.h | 41 +- src/model.c | 27 +- src/mouse.h | 2 + src/ne2000.c | 2 + src/pc.c | 239 +++- src/pc.rc | 185 ++- src/piix.c | 47 +- src/resources.h | 206 ++- src/scsi.c | 19 +- src/scsi.h | 68 +- src/scsi_cdrom.c | 1677 ---------------------- src/sound.c | 130 +- src/sound_cms.c | 14 +- src/soundopenal.c | 19 +- src/vid_nv_riva128.c | 2 +- src/vid_voodoo.c | 11 +- src/win-config.c | 6 +- src/win-hdconf.c | 46 +- src/win.c | 596 ++++---- src/x86_ops_i686.h | 14 + src/x87_ops.h | 2 +- src/x87_ops_misc.h | 9 + 41 files changed, 5953 insertions(+), 5129 deletions(-) create mode 100644 src/cdrom.c delete mode 100644 src/scsi_cdrom.c diff --git a/src/Makefile.mingw b/src/Makefile.mingw index fc210da6e..20e97c053 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -4,13 +4,13 @@ CC = gcc.exe WINDRES = windres.exe CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign DFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o buslogic.o cdrom-ioctl.o cdrom-iso.o \ +OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o buslogic.o cdrom.o cdrom-ioctl.o cdrom-iso.o \ cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \ device.o disc.o disc_86f.o disc_fdi.o disc_imd.o disc_img.o disc_random.o disc_td0.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \ i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \ mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti495.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \ - scat.o scsi.o scsi_cdrom.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o \ + scat.o scsi.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o \ sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \ sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \ soundopenal.o tandy_eeprom.o tandy_rom.o timer.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ diff --git a/src/Makefile.mingw64 b/src/Makefile.mingw64 index a42aa3cc4..e1d682087 100644 --- a/src/Makefile.mingw64 +++ b/src/Makefile.mingw64 @@ -4,13 +4,13 @@ CC = gcc.exe WINDRES = windres.exe CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign DFLAGS = -O3 -fomit-frame-pointer -msse2 -mstackrealign -OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o buslogic.o cdrom-ioctl.o cdrom-iso.o \ +OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o buslogic.o cdrom.o cdrom-ioctl.o cdrom-iso.o \ cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \ device.o disc.o disc_86f.o disc_fdi.o disc_imd.o disc_img.o disc_random.o disc_td0.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \ i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \ keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \ mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti495.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o rtc.o \ - scat.o scsi.o scsi_cdrom.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o \ + scat.o scsi.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o \ sound_dbopl.o sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \ sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o sound_ym7128.o \ soundopenal.o tandy_eeprom.o tandy_rom.o timer.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ @@ -33,7 +33,6 @@ LIBS = -mwindows -lwinmm -lopenal -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 -lws 86Box64.exe: $(OBJ) $(DBOBJ) $(LZFOBJ) $(SIDOBJ) $(SLIRPOBJ) $(CC) $(OBJ) $(DBOBJ) $(LZFOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "86Box64.exe" $(LIBS) strip "86Box64.exe" - peflags --bigaddr=false 86Box64.exe all : 86Box64.exe diff --git a/src/buslogic.c b/src/buslogic.c index 229b4baef..5d263c8ae 100644 --- a/src/buslogic.c +++ b/src/buslogic.c @@ -3,6 +3,7 @@ */ /*Buslogic SCSI emulation (including Adaptec 154x ISA software backward compatibility) and the Adaptec 154x itself*/ +#include #include #include #include @@ -517,12 +518,13 @@ int scsi_base = 0x330; int scsi_dma = 6; int scsi_irq = 11; -int buslogic_do_log = 0; +int buslogic_do_log = 1; static void BuslogicStartMailbox(Buslogic_t *Buslogic); void BuslogicLog(const char *format, ...) { +#ifdef ENABLE_BUSLOGIC_LOG if (buslogic_do_log) { va_list ap; @@ -531,6 +533,7 @@ void BuslogicLog(const char *format, ...) va_end(ap); fflush(stdout); } +#endif } static void BuslogicClearInterrupt(Buslogic_t *Buslogic) @@ -678,6 +681,8 @@ static void BuslogicReadSGEntries(int Is24bit, uint32_t SGList, uint32_t Entries void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bit) { + uint32_t DataPointer, DataLength; + if (Is24bit) { DataPointer = ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataPointer); @@ -728,8 +733,8 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi BuslogicLog("Data to transfer (S/G) %d\n", DataToTransfer); - SCSIDevices[scsi_cdrom_id].InitLength = DataToTransfer; - SCSIDevices[scsi_cdrom_id].CmdBuffer[SCSIDevices[scsi_cdrom_id].pos++] = SCSIDevices[scsi_cdrom_id].InitLength; + SCSIDevices[BuslogicRequests->TargetID].InitLength = DataToTransfer; + SCSIDevices[BuslogicRequests->TargetID].CmdBuffer[SCSIDevices[BuslogicRequests->TargetID].pos++] = SCSIDevices[BuslogicRequests->TargetID].InitLength; //If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without //checking its length, so do this procedure for both no read/write commands. @@ -754,7 +759,7 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment; - DMAPageRead(Address, SCSIDevices[scsi_cdrom_id].CmdBuffer, DataToTransfer); + DMAPageRead(Address, SCSIDevices[BuslogicRequests->TargetID].CmdBuffer, DataToTransfer); } ScatterGatherAddrCurrent += ScatterGatherRead * (Is24bit ? sizeof(SGE) : sizeof(SGE32)); @@ -765,14 +770,26 @@ void BuslogicDataBufferAllocate(BuslogicRequests_t *BuslogicRequests, int Is24bi BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { uint32_t Address = DataPointer; - SCSIDevices[scsi_cdrom_id].InitLength = DataLength; - SCSIDevices[scsi_cdrom_id].CmdBuffer[SCSIDevices[scsi_cdrom_id].pos++] = SCSIDevices[scsi_cdrom_id].InitLength; + SCSIDevices[BuslogicRequests->TargetID].InitLength = DataLength; + SCSIDevices[BuslogicRequests->TargetID].CmdBuffer[SCSIDevices[BuslogicRequests->TargetID].pos++] = SCSIDevices[BuslogicRequests->TargetID].InitLength; - DMAPageRead(Address, SCSIDevices[scsi_cdrom_id].CmdBuffer, SCSIDevices[scsi_cdrom_id].InitLength); + DMAPageRead(Address, SCSIDevices[BuslogicRequests->TargetID].CmdBuffer, SCSIDevices[BuslogicRequests->TargetID].InitLength); } } } +uint32_t BuslogicGetDataLength(BuslogicRequests_t *BuslogicRequests) +{ + if (BuslogicRequests->Is24bit) + { + return ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength); + } + else + { + return BuslogicRequests->CmdBlock.new.DataLength; + } +} + void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) { if (BuslogicRequests->Is24bit) @@ -822,7 +839,7 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) Address = ScatterGatherBuffer[ScatterEntry].SegmentPointer; DataToTransfer = ScatterGatherBuffer[ScatterEntry].Segment; - DMAPageWrite(Address, SCSIDevices[scsi_cdrom_id].CmdBuffer, DataToTransfer); + DMAPageWrite(Address, SCSIDevices[BuslogicRequests->TargetID].CmdBuffer, DataToTransfer); } ScatterGatherAddrCurrent += ScatterGatherRead * (BuslogicRequests->Is24bit ? sizeof(SGE) : sizeof(SGE32)); @@ -832,11 +849,11 @@ void BuslogicDataBufferFree(BuslogicRequests_t *BuslogicRequests) BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { uint32_t Address = DataPointer; - DMAPageWrite(Address, SCSIDevices[scsi_cdrom_id].CmdBuffer, SCSIDevices[scsi_cdrom_id].InitLength); + DMAPageWrite(Address, SCSIDevices[BuslogicRequests->TargetID].CmdBuffer, SCSIDevices[BuslogicRequests->TargetID].InitLength); } } - SCSIDevices[scsi_cdrom_id].InitLength = 0; + SCSIDevices[BuslogicRequests->TargetID].InitLength = 0; } uint8_t BuslogicRead(uint16_t Port, void *p) @@ -885,8 +902,29 @@ uint8_t BuslogicRead(uint16_t Port, void *p) return Temp; } +int buslogic_scsi_drive_is_cdrom(uint8_t id) +{ + if (scsi_cdrom_drives[id] >= CDROM_NUM) + { + return 0; + } + else + { + if (cdrom_drives[scsi_cdrom_drives[id]].enabled && cdrom_drives[scsi_cdrom_drives[id]].bus_type && (cdrom_drives[scsi_cdrom_drives[id]].bus_mode & 2)) + { + return 1; + } + else + { + return 0; + } + } +} + void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) { + int i = 0; + Buslogic_t *Buslogic = (Buslogic_t *)p; BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests; BuslogicLog("Buslogic: Write Port 0x%02X, Value %02X\n", Port, Val); @@ -910,7 +948,13 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 1: if ((Val == 0x02) && (Buslogic->Command == 0xFF)) { - SCSICallback[scsi_cdrom_id] = 1; + for (i = 0; i < CDROM_NUM; i++) + { + if (buslogic_scsi_drive_is_cdrom(cdrom_drives[i].scsi_device_id)) + { + SCSICallback[cdrom_drives[i].scsi_device_id] = 1; + } + } break; } @@ -1047,10 +1091,10 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) break; case 0x0A: - if (scsi_cdrom_id < 8) + for (i = 0; i < 8; i++) { - if (SCSIDevices[scsi_cdrom_id].LunType == SCSI_CDROM) - Buslogic->DataBuf[scsi_cdrom_id] = 1; + if (buslogic_scsi_drive_is_cdrom(i)) + Buslogic->DataBuf[i] = 1; Buslogic->DataBuf[7] = 0; Buslogic->DataReplyLeft = 8; @@ -1091,10 +1135,10 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 0x23: - if (scsi_cdrom_id >= 8) + for (i = 0; i < 8; i++) { - if (SCSIDevices[scsi_cdrom_id].LunType == SCSI_CDROM) - Buslogic->DataBuf[scsi_cdrom_id] = 1; + if (buslogic_scsi_drive_is_cdrom(i)) + Buslogic->DataBuf[i] = 1; Buslogic->DataReplyLeft = 8; } @@ -1337,7 +1381,7 @@ static uint8_t BuslogicConvertSenseLength(uint8_t RequestSenseLength) { if (RequestSenseLength == 0) RequestSenseLength = 14; - else if (RequestSenseLength == 1) + else if ((RequestSenseLength >= 1) && (RequestSenseLength < 8)) RequestSenseLength = 0; BuslogicLog("Request Sense length %i\n", RequestSenseLength); @@ -1376,7 +1420,8 @@ static void BuslogicSenseBufferFree(BuslogicRequests_t *BuslogicRequests, int Co BuslogicLog("Request Sense address: %02X\n", SenseBufferAddress); - DMAPageWrite(SenseBufferAddress, BuslogicRequests->RequestSenseBuffer, SenseLength); + // DMAPageWrite(SenseBufferAddress, BuslogicRequests->RequestSenseBuffer, SenseLength); + DMAPageWrite(SenseBufferAddress, cdrom[BuslogicRequests->TargetID].sense, SenseLength); } //Free the sense buffer when needed. free(BuslogicRequests->RequestSenseBuffer); @@ -1387,6 +1432,11 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, BuslogicRequests_t *BuslogicRequests = &Buslogic->BuslogicRequests; uint8_t Id, Lun; + uint8_t cdrom_id; + uint8_t cdrom_phase; + + uint32_t temp = 0; + //Fetch data from the Command Control Block. DMAPageRead(CCBPointer, &BuslogicRequests->CmdBlock, sizeof(CCB32)); @@ -1399,8 +1449,10 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, BuslogicLog("Scanning SCSI Target ID %i\n", Id); //Only SCSI CD-ROMs are supported at the moment, SCSI hard disk support will come soon. - if (Id == scsi_cdrom_id && Lun == 0) + if (buslogic_scsi_drive_is_cdrom(Id) && Lun == 0) { + cdrom_id = scsi_cdrom_drives[Id]; + BuslogicLog("SCSI Target ID %i detected and working\n", Id); BuslogicRequests->CCBPointer = CCBPointer; @@ -1425,60 +1477,17 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, //This not ready/unit attention stuff below is only for the Buslogic! //The Adaptec one is in scsi_cdrom.c. - if (scsi_model) + if (!cdrom_drives[cdrom_id].check_on_execution) { if ((BuslogicRequests->CmdBlock.common.ControlByte != 0x03) && (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND)) { - if (cdrom->medium_changed()) + if (!cdrom_pre_execution_check(cdrom_id, BuslogicRequests->CmdBlock.common.Cdb)) { - pclog("Media changed\n"); - SCSICDROM_Insert(); - } - - if (!cdrom->ready() && SCSISense.UnitAttention) - { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - SCSISense.UnitAttention = 0; - } - - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ - if (SCSISense.UnitAttention == 1) - { - SCSISense.UnitAttention = 2; - if (!(SCSICommandTable[BuslogicRequests->CmdBlock.common.Cdb[0]] & ALLOW_UA)) - { - SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSICallback[Id]=50*SCSI_TIME; - BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); - return; - } - } - else if (SCSISense.UnitAttention == 2) - { - if (BuslogicRequests->CmdBlock.common.Cdb[0]!=GPCMD_REQUEST_SENSE) - { - SCSISense.UnitAttention = 0; - } - } - - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - clear the UNIT ATTENTION condition if it's set. */ - if (BuslogicRequests->CmdBlock.common.Cdb[0]!=GPCMD_REQUEST_SENSE) - { - SCSIClearSense(BuslogicRequests->CmdBlock.common.Cdb[0], 0); - } - - /* Next it's time for NOT READY. */ - if ((SCSICommandTable[BuslogicRequests->CmdBlock.common.Cdb[0]] & CHECK_READY) && !cdrom->ready()) - { - pclog("Not ready\n"); - SCSISenseCodeError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); SCSIStatus = SCSI_STATUS_CHECK_CONDITION; SCSICallback[Id]=50*SCSI_TIME; + SCSIDevices[BuslogicRequests->TargetID].InitLength = 0; + if (BuslogicRequests->RequestSenseBuffer) + BuslogicSenseBufferFree(BuslogicRequests, 1); BuslogicMailboxIn(Buslogic, BuslogicRequests->CCBPointer, &BuslogicRequests->CmdBlock, CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); return; } @@ -1488,61 +1497,73 @@ static void BuslogicSCSIRequestSetup(Buslogic_t *Buslogic, uint32_t CCBPointer, //First, get the data buffer otherwise putting it after the //exec function results into not getting read/write commands right and //failing to detect the device. - - if (BuslogicRequests->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) - { - SCSIRead(Id, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength); - } - else if (BuslogicRequests->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) - { - SCSIWrite(Id, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength); - } - + + /* Note by Tohka: After looking at the code, both functions do a copy of one part of the buffer to another, + with no purpose, whatsoever, and then end up with SCSIDevices.pos being equal to the InitLength. + SCSIReadData does not use pos at all, and the write code does, but in a useless way, therefore that + variable is going away. + All I am going to do at this point is zero the buffer. + Also, instead of directly calling SCSIReadData from here, this will be modified to call the CD-ROM + callback for the correct CD-ROM drive, and make that call SCSIReadData. + Since the new code will have the target ID and LUN inside the cdrom struct, as well as a copy of the Cdb + and the InitLength (in cdrom[id].request_length), it can be called from there and do everything needed. */ + + memset(SCSIDevices[Id].CmdBuffer, 0, 390144); + //Finally, execute the SCSI command immediately and get the transfer length. SCSIPhase = SCSI_PHASE_COMMAND; - SCSIExecCommand(Id, SCSIDevices[Id].CmdBuffer, BuslogicRequests->CmdBlock.common.Cdb); - SCSIGetLength(Id, &SCSIDevices[Id].InitLength); - - if (SCSIPhase == SCSI_PHASE_DATAIN) + cdrom_command(cdrom_id, BuslogicRequests->CmdBlock.common.Cdb); + // SCSIDevices[Id].InitLength = cdrom[cdrom_id].0; + // SCSIGetLength(Id, &SCSIDevices[Id].InitLength); + SCSIStatus = cdrom_CDROM_PHASE_to_scsi(cdrom_id); + if (SCSIStatus == SCSI_STATUS_OK) { - SCSIReadData(Id, BuslogicRequests->CmdBlock.common.Cdb, SCSIDevices[Id].CmdBuffer, SCSIDevices[Id].InitLength); - } - else if (SCSIPhase == SCSI_PHASE_DATAOUT) - { - if (BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_MODE_SELECT_6 || - BuslogicRequests->CmdBlock.common.Cdb[0] == GPCMD_MODE_SELECT_10) + cdrom_phase = cdrom_atapi_phase_to_scsi(cdrom_id); + if (cdrom_phase == 2) { - //Mode Sense/Select stuff - if ((SCSIDevices[Id].pos >= prefix_len+4) && (page_flags[page_current] & PAGE_CHANGEABLE)) - { - mode_pages_in[page_current][SCSIDevices[Id].pos - prefix_len - 4] = SCSIDevices[Id].CmdBuffer[SCSIDevices[Id].pos - 2]; - mode_pages_in[page_current][SCSIDevices[Id].pos - prefix_len - 3] = SCSIDevices[Id].CmdBuffer[SCSIDevices[Id].pos - 1]; - } + /* Command completed - call the phase callback to complete the command. */ + cdrom_phase_callback(cdrom_id); + } + else + { + /* Command first phase complete - call the callback to execute the second phase. */ + cdrom_phase_callback(cdrom_id); + SCSIStatus = cdrom_CDROM_PHASE_to_scsi(cdrom_id); + /* Command second phase complete - call the callback to complete the command. */ + cdrom_phase_callback(cdrom_id); } } - + else + { + /* Error (Check Condition) - call the phase callback to complete the command. */ + cdrom_phase_callback(cdrom_id); + } + SCSICallback[Id] = cdrom[cdrom_id].callback; + BuslogicDataBufferFree(BuslogicRequests); if (BuslogicRequests->RequestSenseBuffer) - BuslogicSenseBufferFree(BuslogicRequests, (SCSIStatus != SCSI_STATUS_OK)); + BuslogicSenseBufferFree(BuslogicRequests, (SCSIStatus != SCSI_STATUS_OK)); } pclog("Request complete\n"); - pclog("SCSI Status %02X, Sense %02X, Asc %02X, Ascq %02X\n", SCSIStatus, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq); + pclog("SCSI Status %02X, Sense %02X, Asc %02X, Ascq %02X\n", SCSIStatus, cdrom[cdrom_id].sense[2], cdrom[cdrom_id].sense[12], cdrom[cdrom_id].sense[13]); - if (BuslogicRequests->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES || BuslogicRequests->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) { + temp = BuslogicGetDataLength(BuslogicRequests); + temp -= SCSIDevices[Id].InitLength; + if (BuslogicRequests->Is24bit) { - U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, SCSIDevices[Id].InitLength); + U32_TO_ADDR(BuslogicRequests->CmdBlock.old.DataLength, temp); BuslogicLog("24-bit Residual data length for reading: %d\n", ADDR_TO_U32(BuslogicRequests->CmdBlock.old.DataLength)); } else { - BuslogicRequests->CmdBlock.new.DataLength = SCSIDevices[Id].InitLength; + BuslogicRequests->CmdBlock.new.DataLength = temp; BuslogicLog("32-bit Residual data length for reading: %d\n", BuslogicRequests->CmdBlock.new.DataLength); } } @@ -1634,17 +1655,37 @@ static void BuslogicStartMailbox(Buslogic_t *Buslogic) } } -void BuslogicCommandCallback(void *p) +void BuslogicCommandCallback(int Id, void *p) { Buslogic_t *Buslogic = (Buslogic_t *)p; - SCSICallback[scsi_cdrom_id] = 0; + SCSICallback[Id] = 0; if (Buslogic->MailboxCount) { BuslogicStartMailbox(Buslogic); } } +void BuslogicCommandCallback0(void *p) +{ + BuslogicCommandCallback(cdrom_drives[0].scsi_device_id, p); +} + +void BuslogicCommandCallback1(void *p) +{ + BuslogicCommandCallback(cdrom_drives[1].scsi_device_id, p); +} + +void BuslogicCommandCallback2(void *p) +{ + BuslogicCommandCallback(cdrom_drives[2].scsi_device_id, p); +} + +void BuslogicCommandCallback3(void *p) +{ + BuslogicCommandCallback(cdrom_drives[3].scsi_device_id, p); +} + void *BuslogicInit() { Buslogic_t *Buslogic = malloc(sizeof(Buslogic_t)); @@ -1654,7 +1695,29 @@ void *BuslogicInit() Buslogic->DmaChannel = scsi_dma; io_sethandler(scsi_base, 0x0004, BuslogicRead, NULL, NULL, BuslogicWrite, NULL, NULL, Buslogic); - timer_add(BuslogicCommandCallback, &SCSICallback[scsi_cdrom_id], &SCSICallback[scsi_cdrom_id], Buslogic); + + build_scsi_cdrom_map(); + + if (buslogic_scsi_drive_is_cdrom(cdrom_drives[0].scsi_device_id)) + { + SCSIDevices[cdrom_drives[0].scsi_device_id].LunType == SCSI_CDROM; + timer_add(BuslogicCommandCallback0, &SCSICallback[cdrom_drives[0].scsi_device_id], &SCSICallback[cdrom_drives[0].scsi_device_id], Buslogic); + } + if (buslogic_scsi_drive_is_cdrom(cdrom_drives[1].scsi_device_id)) + { + SCSIDevices[cdrom_drives[1].scsi_device_id].LunType == SCSI_CDROM; + timer_add(BuslogicCommandCallback1, &SCSICallback[cdrom_drives[1].scsi_device_id], &SCSICallback[cdrom_drives[1].scsi_device_id], Buslogic); + } + if (buslogic_scsi_drive_is_cdrom(cdrom_drives[2].scsi_device_id)) + { + SCSIDevices[cdrom_drives[2].scsi_device_id].LunType == SCSI_CDROM; + timer_add(BuslogicCommandCallback2, &SCSICallback[cdrom_drives[2].scsi_device_id], &SCSICallback[cdrom_drives[2].scsi_device_id], Buslogic); + } + if (buslogic_scsi_drive_is_cdrom(cdrom_drives[3].scsi_device_id)) + { + SCSIDevices[cdrom_drives[3].scsi_device_id].LunType == SCSI_CDROM; + timer_add(BuslogicCommandCallback3, &SCSICallback[cdrom_drives[3].scsi_device_id], &SCSICallback[cdrom_drives[3].scsi_device_id], Buslogic); + } BuslogicLog("Buslogic on port 0x%04X\n", scsi_base); diff --git a/src/cdrom-ioctl.c b/src/cdrom-ioctl.c index 37197b51f..12d8662ae 100644 --- a/src/cdrom-ioctl.c +++ b/src/cdrom-ioctl.c @@ -3,6 +3,7 @@ */ /*Win32 CD-ROM support via IOCTL*/ +#define WINVER 0x0600 #include #include #include "ntddcdrm.h" @@ -10,26 +11,24 @@ #include "ibm.h" #include "cdrom.h" #include "cdrom-ioctl.h" +#include "scsi.h" -int cdrom_drive; -int old_cdrom_drive; +#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) static CDROM ioctl_cdrom; -static uint32_t last_block = 0; -uint32_t cdrom_capacity = 0; -static int ioctl_inited = 0; -static char ioctl_path[8]; -void ioctl_close(void); -static HANDLE hIOCTL; -static CDROM_TOC toc; -static int tocvalid = 0; +typedef struct +{ + HANDLE hIOCTL; + CDROM_TOC toc; +} cdrom_ioctl_windows_t; + +cdrom_ioctl_windows_t cdrom_ioctl_windows[CDROM_NUM]; // #define MSFtoLBA(m,s,f) (((((m*60)+s)*75)+f)-150) /* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong: there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start of the audio while audio still plays. With an absolute conversion, the counter is fine. */ -#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) enum { @@ -38,82 +37,92 @@ enum CD_PAUSED }; -static int ioctl_cd_state = CD_STOPPED; -static uint32_t ioctl_cd_pos = 0, ioctl_cd_end = 0; +int cdrom_ioctl_do_log = 1; -#define BUF_SIZE 32768 -static int16_t cd_buffer[BUF_SIZE]; -static int cd_buflen = 0; -void ioctl_audio_callback(int16_t *output, int len) +void cdrom_ioctl_log(const char *format, ...) +{ +#ifdef ENABLE_CDROM_LOG + if (cdrom_ioctl_do_log) + { + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + fflush(stdout); + } +#endif +} + +void ioctl_audio_callback(uint8_t id, int16_t *output, int len) { RAW_READ_INFO in; DWORD count; // return; -// pclog("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount()); - if (ioctl_cd_state != CD_PLAYING) +// cdrom_ioctl_log("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount()); + if (cdrom_ioctl[id].cd_state != CD_PLAYING) { memset(output, 0, len * 2); return; } - while (cd_buflen < len) + while (cdrom_ioctl[id].cd_buflen < len) { - if (ioctl_cd_pos < ioctl_cd_end) + if (cdrom[id].seek_pos < cdrom_ioctl[id].cd_end) { - in.DiskOffset.LowPart = (ioctl_cd_pos - 150) * 2048; + in.DiskOffset.LowPart = (cdrom[id].seek_pos - 150) * 2048; in.DiskOffset.HighPart = 0; in.SectorCount = 1; in.TrackMode = CDDA; - ioctl_open(0); -// pclog("Read to %i\n", cd_buflen); - if (!DeviceIoControl(hIOCTL, IOCTL_CDROM_RAW_READ, &in, sizeof(in), &cd_buffer[cd_buflen], 2352, &count, NULL)) + ioctl_open(id, 0); +// cdrom_ioctl_log("Read to %i\n", cd_buflen); + if (!DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_RAW_READ, &in, sizeof(in), &(cdrom_ioctl[id].cd_buffer[cdrom_ioctl[id].cd_buflen]), 2352, &count, NULL)) { -// pclog("DeviceIoControl returned false\n"); - memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2); - ioctl_cd_state = CD_STOPPED; - cd_buflen = len; +// cdrom_ioctl_log("DeviceIoControl returned false\n"); + memset(&(cdrom_ioctl[id].cd_buffer[cdrom_ioctl[id].cd_buflen]), 0, (BUF_SIZE - cdrom_ioctl[id].cd_buflen) * 2); + cdrom_ioctl[id].cd_state = CD_STOPPED; + cdrom_ioctl[id].cd_buflen = len; } else { -// pclog("DeviceIoControl returned true\n"); - ioctl_cd_pos++; - cd_buflen += (2352 / 2); +// cdrom_ioctl_log("DeviceIoControl returned true\n"); + cdrom[id].seek_pos++; + cdrom_ioctl[id].cd_buflen += (2352 / 2); } - ioctl_close(); + ioctl_close(id); } else { - memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2); - ioctl_cd_state = CD_STOPPED; - cd_buflen = len; + memset(&(cdrom_ioctl[id].cd_buffer[cdrom_ioctl[id].cd_buflen]), 0, (BUF_SIZE - cdrom_ioctl[id].cd_buflen) * 2); + cdrom_ioctl[id].cd_state = CD_STOPPED; + cdrom_ioctl[id].cd_buflen = len; } } - memcpy(output, cd_buffer, len * 2); + memcpy(output, cdrom_ioctl[id].cd_buffer, len * 2); // for (c = 0; c < BUF_SIZE - len; c++) // cd_buffer[c] = cd_buffer[c + cd_buflen]; - memcpy(&cd_buffer[0], &cd_buffer[len], (BUF_SIZE - len) * 2); - cd_buflen -= len; -// pclog("Done %i\n", GetTickCount()); + memcpy(&cdrom_ioctl[id].cd_buffer[0], &(cdrom_ioctl[id].cd_buffer[len]), (BUF_SIZE - len) * 2); + cdrom_ioctl[id].cd_buflen -= len; +// cdrom_ioctl_log("Done %i\n", GetTickCount()); } -void ioctl_audio_stop() +void ioctl_audio_stop(uint8_t id) { - ioctl_cd_state = CD_STOPPED; + cdrom_ioctl[id].cd_state = CD_STOPPED; } -static int get_track_nr(uint32_t pos) +static int get_track_nr(uint8_t id, uint32_t pos) { int c; int track = 0; - if (!tocvalid) + if (!cdrom_ioctl[id].tocvalid) return 0; - for (c = toc.FirstTrack; c < toc.LastTrack; c++) + for (c = cdrom_ioctl_windows[id].toc.FirstTrack; c < cdrom_ioctl_windows[id].toc.LastTrack; c++) { - uint32_t track_address = toc.TrackData[c].Address[3] + - (toc.TrackData[c].Address[2] * 75) + - (toc.TrackData[c].Address[1] * 75 * 60); + uint32_t track_address = cdrom_ioctl_windows[id].toc.TrackData[c].Address[3] + + (cdrom_ioctl_windows[id].toc.TrackData[c].Address[2] * 75) + + (cdrom_ioctl_windows[id].toc.TrackData[c].Address[1] * 75 * 60); if (track_address <= pos) track = c; @@ -121,145 +130,142 @@ static int get_track_nr(uint32_t pos) return track; } -static void ioctl_playaudio(uint32_t pos, uint32_t len, int ismsf) +static uint32_t get_track_msf(uint8_t id, uint32_t track_no) { - if (!cdrom_drive) return; - // pclog("Play audio - %08X %08X %i\n", pos, len, ismsf); - if (ismsf) + int c; + int track = 0; + + if (!cdrom_ioctl[id].tocvalid) + return 0; + + for (c = cdrom_ioctl_windows[id].toc.FirstTrack; c < cdrom_ioctl_windows[id].toc.LastTrack; c++) { - int m = (pos >> 16) & 0xff; - int s = (pos >> 8) & 0xff; - int f = pos & 0xff; + if (c == track_no) + { + return cdrom_ioctl_windows[id].toc.TrackData[c].Address[3] + (cdrom_ioctl_windows[id].toc.TrackData[c].Address[2] << 8) + (cdrom_ioctl_windows[id].toc.TrackData[c].Address[1] << 16); + } + } + return 0xffffffff; +} + +static void ioctl_playaudio(uint8_t id, uint32_t pos, uint32_t len, int ismsf) +{ + if (!cdrom_drives[id].host_drive) return; + // cdrom_ioctl_log("Play audio - %08X %08X %i\n", pos, len, ismsf); + if (ismsf == 2) + { + uint32_t start_msf = get_track_msf(id, pos); + uint32_t end_msf = get_track_msf(id, len); + if (start_msf == 0xffffffff) + { + return; + } + if (end_msf == 0xffffffff) + { + return; + } + int m = (start_msf >> 16) & 0xff; + int s = (start_msf >> 8) & 0xff; + int f = start_msf & 0xff; pos = MSFtoLBA(m, s, f); + m = (end_msf >> 16) & 0xff; + s = (end_msf >> 8) & 0xff; + f = end_msf & 0xff; + len = MSFtoLBA(m, s, f); + } + else if (ismsf == 1) + { + int m = (pos >> 16) & 0xff; + int s = (pos >> 8) & 0xff; + int f = pos & 0xff; + + if (pos == 0xffffff) + { + cdrom_ioctl_log("Playing from current position (MSF)\n"); + pos = cdrom[id].seek_pos; + } + else + { + pos = MSFtoLBA(m, s, f); + } + m = (len >> 16) & 0xff; s = (len >> 8) & 0xff; f = len & 0xff; len = MSFtoLBA(m, s, f); - // pclog("MSF - pos = %08X len = %08X\n", pos, len); + // cdrom_ioctl_log("MSF - pos = %08X len = %08X\n", pos, len); } - else - len += pos; - ioctl_cd_pos = pos;// + 150; - ioctl_cd_end = len;// + 150; - if (ioctl_cd_pos < 150) + else if (ismsf == 0) + { + if (pos == 0xffffffff) + { + cdrom_ioctl_log("Playing from current position\n"); + pos = cdrom[id].seek_pos; + } + len += pos; + } + cdrom[id].seek_pos = pos;// + 150; + cdrom_ioctl[id].cd_end = len;// + 150; + if (cdrom[id].seek_pos < 150) { /* Adjust because the host expects a minimum adjusted LBA of 0 which is equivalent to an absolute LBA of 150. */ - ioctl_cd_pos = 150; + cdrom[id].seek_pos = 150; } - ioctl_cd_state = CD_PLAYING; - // pclog("Audio start %08X %08X %i %i %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len); -/* CDROM_PLAY_AUDIO_MSF msf; - long size; - BOOL b; - if (ismsf) - { - msf.StartingF=pos&0xFF; - msf.StartingS=(pos>>8)&0xFF; - msf.StartingM=(pos>>16)&0xFF; - msf.EndingF=len&0xFF; - msf.EndingS=(len>>8)&0xFF; - msf.EndingM=(len>>16)&0xFF; - } - else - { - msf.StartingF=(uint8_t)(addr%75); addr/=75; - msf.StartingS=(uint8_t)(addr%60); addr/=60; - msf.StartingM=(uint8_t)(addr); - addr=pos+len+150; - msf.EndingF=(uint8_t)(addr%75); addr/=75; - msf.EndingS=(uint8_t)(addr%60); addr/=60; - msf.EndingM=(uint8_t)(addr); - } - ioctl_open(0); - b = DeviceIoControl(hIOCTL,IOCTL_CDROM_PLAY_AUDIO_MSF,&msf,sizeof(msf),NULL,0,&size,NULL); - pclog("DeviceIoControl returns %i\n", (int) b); - ioctl_close();*/ + cdrom_ioctl[id].cd_state = CD_PLAYING; + // cdrom_ioctl_log("Audio start %08X %08X %i %i %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len); } -static void ioctl_pause(void) +static void ioctl_pause(uint8_t id) { - if (!cdrom_drive) return; - if (ioctl_cd_state == CD_PLAYING) - ioctl_cd_state = CD_PAUSED; -// ioctl_open(0); -// DeviceIoControl(hIOCTL,IOCTL_CDROM_PAUSE_AUDIO,NULL,0,NULL,0,&size,NULL); -// ioctl_close(); + if (!cdrom_drives[id].host_drive) return; + if (cdrom_ioctl[id].cd_state == CD_PLAYING) + cdrom_ioctl[id].cd_state = CD_PAUSED; } -static void ioctl_resume(void) +static void ioctl_resume(uint8_t id) { - if (!cdrom_drive) return; - if (ioctl_cd_state == CD_PAUSED) - ioctl_cd_state = CD_PLAYING; -// ioctl_open(0); -// DeviceIoControl(hIOCTL,IOCTL_CDROM_RESUME_AUDIO,NULL,0,NULL,0,&size,NULL); -// ioctl_close(); + if (!cdrom_drives[id].host_drive) return; + if (cdrom_ioctl[id].cd_state == CD_PAUSED) + cdrom_ioctl[id].cd_state = CD_PLAYING; } -static void ioctl_stop(void) +static void ioctl_stop(uint8_t id) { - if (!cdrom_drive) return; - ioctl_cd_state = CD_STOPPED; -// ioctl_open(0); -// DeviceIoControl(hIOCTL,IOCTL_CDROM_STOP_AUDIO,NULL,0,NULL,0,&size,NULL); -// ioctl_close(); + if (!cdrom_drives[id].host_drive) return; + cdrom_ioctl[id].cd_state = CD_STOPPED; } -static void ioctl_seek(uint32_t pos) -{ - if (!cdrom_drive) return; - // ioctl_cd_state = CD_STOPPED; - // pclog("Seek %08X\n", pos); - ioctl_cd_pos = pos; - ioctl_cd_state = CD_STOPPED; -/* pos+=150; - CDROM_SEEK_AUDIO_MSF msf; - msf.F=(uint8_t)(pos%75); pos/=75; - msf.S=(uint8_t)(pos%60); pos/=60; - msf.M=(uint8_t)(pos); -// pclog("Seek to %02i:%02i:%02i\n",msf.M,msf.S,msf.F); - ioctl_open(0); - DeviceIoControl(hIOCTL,IOCTL_CDROM_SEEK_AUDIO_MSF,&msf,sizeof(msf),NULL,0,&size,NULL); - ioctl_close();*/ -} - -static int ioctl_ready(void) +static int ioctl_ready(uint8_t id) { long size; int temp; CDROM_TOC ltoc; -// pclog("Ready? %i\n",cdrom_drive); - if (!cdrom_drive) return 0; - ioctl_open(0); - temp=DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,<oc,sizeof(ltoc),&size,NULL); - ioctl_close(); + // cdrom_ioctl_log("Ready? %i\n",cdrom_drives[id].host_drive); + if (!cdrom_drives[id].host_drive) return 0; + ioctl_open(id, 0); + temp=DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,<oc,sizeof(ltoc),&size,NULL); + ioctl_close(id); if (!temp) return 0; - //pclog("ioctl_ready(): Drive opened successfully\n"); - //if ((cdrom_drive != old_cdrom_drive)) pclog("Drive has changed\n"); - if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != toc.TrackData[toc.LastTrack].Address[1]) || - (ltoc.TrackData[ltoc.LastTrack].Address[2] != toc.TrackData[toc.LastTrack].Address[2]) || - (ltoc.TrackData[ltoc.LastTrack].Address[3] != toc.TrackData[toc.LastTrack].Address[3]) || - !tocvalid || (cdrom_drive != old_cdrom_drive)) + // cdrom_ioctl_log("ioctl_ready(): Drive opened successfully\n"); + // if ((cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive)) cdrom_ioctl_log("Drive has changed\n"); + if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[1]) || + (ltoc.TrackData[ltoc.LastTrack].Address[2] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[2]) || + (ltoc.TrackData[ltoc.LastTrack].Address[3] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[3]) || + !cdrom_ioctl[id].tocvalid || (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive)) { - //pclog("ioctl_ready(): Disc or drive changed\n"); - ioctl_cd_state = CD_STOPPED; - /* pclog("Not ready %02X %02X %02X %02X %02X %02X %i\n",ltoc.TrackData[ltoc.LastTrack].Address[1],ltoc.TrackData[ltoc.LastTrack].Address[2],ltoc.TrackData[ltoc.LastTrack].Address[3], - toc.TrackData[ltoc.LastTrack].Address[1], toc.TrackData[ltoc.LastTrack].Address[2], toc.TrackData[ltoc.LastTrack].Address[3],tocvalid);*/ - // atapi_discchanged(); -/* ioctl_open(0); - temp=DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&toc,sizeof(toc),&size,NULL); - ioctl_close();*/ - if (cdrom_drive != old_cdrom_drive) - old_cdrom_drive = cdrom_drive; - return 1; + // cdrom_ioctl_log("ioctl_ready(): Disc or drive changed\n"); + // cdrom_ioctl_log("ioctl_ready(): Stopped\n"); + cdrom_ioctl[id].cd_state = CD_STOPPED; + if (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive) + cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; + return 1; } -// pclog("IOCTL says ready\n"); -// pclog("ioctl_ready(): All is good\n"); + // cdrom_ioctl_log("ioctl_ready(): All is good\n"); return 1; } -static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, int single) +static int ioctl_get_last_block(uint8_t id, unsigned char starttrack, int msf, int maxlen, int single) { int len=4; long size; @@ -267,86 +273,77 @@ static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, i uint32_t temp; CDROM_TOC lbtoc; int lb=0; - if (!cdrom_drive) return 0; - ioctl_cd_state = CD_STOPPED; - // pclog("ioctl_readtoc(): IOCtl state now CD_STOPPED\n"); - ioctl_open(0); - DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&lbtoc,sizeof(lbtoc),&size,NULL); - ioctl_close(); - tocvalid=1; + if (!cdrom_drives[id].host_drive) return 0; + cdrom_ioctl[id].cd_state = CD_STOPPED; + // cdrom_ioctl_log("ioctl_readtoc(): IOCtl state now CD_STOPPED\n"); + ioctl_open(id, 0); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&lbtoc,sizeof(lbtoc),&size,NULL); + ioctl_close(id); + cdrom_ioctl[id].tocvalid=1; for (c=d;c<=lbtoc.LastTrack;c++) { uint32_t address; - address = MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]); + address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); if (address > lb) lb = address; } return lb; } -static int ioctl_medium_changed(void) +static int ioctl_medium_changed(uint8_t id) { long size; int temp; CDROM_TOC ltoc; - if (!cdrom_drive) return 0; /* This will be handled by the not ready handler instead. */ - ioctl_open(0); - temp=DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,<oc,sizeof(ltoc),&size,NULL); - ioctl_close(); + if (!cdrom_drives[id].host_drive) return 0; /* This will be handled by the not ready handler instead. */ + ioctl_open(id, 0); + temp=DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,<oc,sizeof(ltoc),&size,NULL); + ioctl_close(id); if (!temp) return 0; /* Drive empty, a not ready handler matter, not disc change. */ - if (!tocvalid || (cdrom_drive != old_cdrom_drive)) + if (!cdrom_ioctl[id].tocvalid || (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive)) { - ioctl_cd_state = CD_STOPPED; - toc = ltoc; - tocvalid = 1; - if (cdrom_drive != old_cdrom_drive) - old_cdrom_drive = cdrom_drive; - cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0); - if (cdrom_drive == old_cdrom_drive) - { - return 1; - } - else - { - return 0; - } + cdrom_ioctl[id].cd_state = CD_STOPPED; + cdrom_ioctl_windows[id].toc = ltoc; + cdrom_ioctl[id].tocvalid = 1; + if (cdrom_drives[id].host_drive != cdrom_drives[id].prev_host_drive) + cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; + cdrom_ioctl[id].cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); + return 1; } else { - if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != toc.TrackData[toc.LastTrack].Address[1]) || - (ltoc.TrackData[ltoc.LastTrack].Address[2] != toc.TrackData[toc.LastTrack].Address[2]) || - (ltoc.TrackData[ltoc.LastTrack].Address[3] != toc.TrackData[toc.LastTrack].Address[3])) + if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[1]) || + (ltoc.TrackData[ltoc.LastTrack].Address[2] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[2]) || + (ltoc.TrackData[ltoc.LastTrack].Address[3] != cdrom_ioctl_windows[id].toc.TrackData[cdrom_ioctl_windows[id].toc.LastTrack].Address[3])) { - ioctl_cd_state = CD_STOPPED; - toc = ltoc; - cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0); + cdrom_ioctl[id].cd_state = CD_STOPPED; + cdrom_ioctl_windows[id].toc = ltoc; + cdrom_ioctl[id].cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); return 1; /* TOC mismatches. */ } } return 0; /* None of the above, return 0. */ } -static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf) +static uint8_t ioctl_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) { CDROM_SUB_Q_DATA_FORMAT insub; SUB_Q_CHANNEL_DATA sub; long size; int pos=0; - if (!cdrom_drive) return 0; + if (!cdrom_drives[id].host_drive) return 0; insub.Format = IOCTL_CDROM_CURRENT_POSITION; - ioctl_open(0); - DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL,&insub,sizeof(insub),&sub,sizeof(sub),&size,NULL); - ioctl_close(); + ioctl_open(id, 0); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL,&insub,sizeof(insub),&sub,sizeof(sub),&size,NULL); + ioctl_close(id); - if (ioctl_cd_state == CD_PLAYING || ioctl_cd_state == CD_PAUSED) - { - uint32_t cdpos = ioctl_cd_pos; - int track = get_track_nr(cdpos); - uint32_t track_address = toc.TrackData[track].Address[3] + - (toc.TrackData[track].Address[2] * 75) + - (toc.TrackData[track].Address[1] * 75 * 60); + if (cdrom_ioctl[id].cd_state == CD_PLAYING || cdrom_ioctl[id].cd_state == CD_PAUSED) + { + uint32_t cdpos = cdrom[id].seek_pos; + int track = get_track_nr(id, cdpos); + uint32_t track_address = cdrom_ioctl_windows[id].toc.TrackData[track].Address[3] + (cdrom_ioctl_windows[id].toc.TrackData[track].Address[2] * 75) + (cdrom_ioctl_windows[id].toc.TrackData[track].Address[1] * 75 * 60); b[pos++] = sub.CurrentPosition.Control; b[pos++] = track + 1; @@ -380,7 +377,7 @@ static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf) b[pos++] = cdpos & 0xff; } - if (ioctl_cd_state == CD_PLAYING) return 0x11; + if (cdrom_ioctl[id].cd_state == CD_PLAYING) return 0x11; return 0x12; } @@ -413,46 +410,43 @@ static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf) return 0x13; } -static void ioctl_eject(void) +static void ioctl_eject(uint8_t id) { long size; - if (!cdrom_drive) return; - ioctl_cd_state = CD_STOPPED; - ioctl_open(0); - DeviceIoControl(hIOCTL,IOCTL_STORAGE_EJECT_MEDIA,NULL,0,NULL,0,&size,NULL); - ioctl_close(); + if (!cdrom_drives[id].host_drive) return; + cdrom_ioctl[id].cd_state = CD_STOPPED; + ioctl_open(id, 0); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_STORAGE_EJECT_MEDIA,NULL,0,NULL,0,&size,NULL); + ioctl_close(id); } -static void ioctl_load(void) +static void ioctl_load(uint8_t id) { long size; - if (!cdrom_drive) return; - ioctl_cd_state = CD_STOPPED; - ioctl_open(0); - DeviceIoControl(hIOCTL,IOCTL_STORAGE_LOAD_MEDIA,NULL,0,NULL,0,&size,NULL); - ioctl_close(); - cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0); + if (!cdrom_drives[id].host_drive) return; + cdrom_ioctl[id].cd_state = CD_STOPPED; + ioctl_open(id, 0); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_STORAGE_LOAD_MEDIA,NULL,0,NULL,0,&size,NULL); + ioctl_close(id); + cdrom_ioctl[id].cdrom_capacity = ioctl_get_last_block(id, 0, 0, 4096, 0); } -static int is_track_audio(uint32_t pos) +static int is_track_audio(uint8_t id, uint32_t pos) { int c; int control = 0; - if (!tocvalid) + if (!cdrom_ioctl[id].tocvalid) return 0; - // for (c = toc.FirstTrack; c <= toc.LastTrack; c++) - for (c = 0; c <= toc.LastTrack; c++) + for (c = 0; c <= cdrom_ioctl_windows[id].toc.LastTrack; c++) { - uint32_t track_address = MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]); - - // pclog("Track address: %i (%02X%02X%02X%02X), Position: %i\n", track_address, toc.TrackData[c].Address[0], toc.TrackData[c].Address[1], toc.TrackData[c].Address[2], toc.TrackData[c].Address[3], pos); + uint32_t track_address = MSFtoLBA(cdrom_ioctl_windows[id].toc.TrackData[c].Address[1],cdrom_ioctl_windows[id].toc.TrackData[c].Address[2],cdrom_ioctl_windows[id].toc.TrackData[c].Address[3]); if (track_address <= pos) - control = toc.TrackData[c].Control; + control = cdrom_ioctl_windows[id].toc.TrackData[c].Control; } - // pclog("Control: %i\n", control); + // cdrom_ioctl_log("Control: %i\n", control); if ((control & 0xd) == 0) { return 1; @@ -467,7 +461,7 @@ static int is_track_audio(uint32_t pos) } } -static int ioctl_is_track_audio(uint32_t pos, int ismsf) +static int ioctl_is_track_audio(uint8_t id, uint32_t pos, int ismsf) { if (ismsf) { @@ -480,196 +474,183 @@ static int ioctl_is_track_audio(uint32_t pos, int ismsf) { pos += 150; } - return is_track_audio(pos); + return is_track_audio(id, pos); } -static int SCSICommand(const UCHAR *cdb, UCHAR *buf, uint32_t len) +/* 00, 08, 10, 18, 20, 28, 30, 38 */ +int flags_to_size[5][32] = { { 0, 0, 2352, 2352, 2352, 2352, 2352, 2352, /* 00-38 (CD-DA) */ + 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352, /* 40-78 */ + 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352, /* 80-B8 */ + 2352, 2352, 2352, 2352, 2352, 2352, 2352, 2352 }, /* C0-F8 */ + { 0, 0, 2048, 2336, 4, -296, 2052, 2344, /* 00-38 (Mode 1) */ + 8, -296, 2048, 2048, 12, -296, 2052, 2052, /* 40-78 */ + -296, -296, -296, -296, 16, -296, 2064, 2344, /* 80-B8 */ + -296, -296, 2048, 2048, 24, -296, 2064, 2352 }, /* C0-F8 */ + { 0, 0, 2336, 2336, 4, -296, 2340, 2340, /* 00-38 (Mode 2 non-XA) */ + 8, -296, 2336, 2336, 12, -296, 2340, 2340, /* 40-78 */ + -296, -296, -296, -296, 16, -296, 2352, 2340, /* 80-B8 */ + -296, -296, 2336, 2336, 24, -296, 2352, 2352 }, /* C0-F8 */ + { 0, 0, 2048, 2336, 4, -296, -296, -296, /* 00-38 (Mode 2 Form 1) */ + 8, -296, 2056, 2344, 12, -296, 2060, 2340, /* 40-78 */ + -296, -296, -296, -296, 16, -296, -296, -296, /* 80-B8 */ + -296, -296, -296, -296, 24, -296, 2072, 2352 }, /* C0-F8 */ + { 0, 0, 2328, 2328, 4, -296, -296, -296, /* 00-38 (Mode 2 Form 2) */ + 8, -296, 2336, 2336, 12, -296, 2340, 2340, /* 40-78 */ + -296, -296, -296, -296, 16, -296, -296, -296, /* 80-B8 */ + -296, -296, -296, -296, 24, -296, 2352, 2352 } /* C0-F8 */ + }; + +static int ioctl_get_sector_data_type(uint8_t id, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, int ismsf); + +static void cdrom_illegal_mode(uint8_t id) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; + cdrom_ascq = 0; +} + +struct sptd_with_sense +{ + SCSI_PASS_THROUGH s; + ULONG Filler; + UCHAR sense[32]; + UCHAR data[64512]; +} sptd; + +static int SCSICommand(uint8_t id, const UCHAR *cdb, UCHAR *buf, uint32_t *len, int no_length_check) { HANDLE fh; DWORD ioctl_bytes; DWORD out_size; int ioctl_rv = 0; - UCHAR tbuf[65536]; - struct sptd_with_sense - { - SCSI_PASS_THROUGH_DIRECT s; - UCHAR sense[128]; - } sptd; + int sector_type = 0; + int temp_len = 0; + SCSISense.SenseKey = 0; + SCSISense.Asc = 0; + SCSISense.Ascq = 0; + + *len = 0; memset(&sptd, 0, sizeof(sptd)); - sptd.s.Length = sizeof(sptd.s); - // sptd.s.CdbLength = sizeof(cdb); + sptd.s.Length = sizeof(SCSI_PASS_THROUGH); sptd.s.CdbLength = 12; sptd.s.DataIn = SCSI_IOCTL_DATA_IN; - sptd.s.TimeOutValue = 30; - sptd.s.DataBuffer = tbuf; - sptd.s.DataTransferLength = len; - sptd.s.SenseInfoLength = sizeof(sptd.sense); - sptd.s.SenseInfoOffset = offsetof(struct sptd_with_sense, sense); - - // memcpy(sptd.s.Cdb, cdb, sizeof(cdb)); + sptd.s.TimeOutValue = 80 * 60; + goto bypass_check; + if (no_length_check) goto bypass_check; + switch (cdb[0]) + { + case 0x08: + case 0x28: + case 0xa8: + /* READ (6), READ (10), READ (12) */ + sptd.s.DataTransferLength = 2048 * cdrom[id].requested_blocks; + break; + case 0xb9: + sector_type = (cdb[1] >> 2) & 7; + if (sector_type == 0) + { + sector_type = ioctl_get_sector_data_type(id, 0, cdb[3], cdb[4], cdb[5], 1); + if (sector_type == 0) + { + cdrom_illegal_mode(id); + return 1; + } + } + goto common_handler; + case 0xbe: + /* READ CD MSF, READ CD */ + sector_type = (cdb[1] >> 2) & 7; + if (sector_type == 0) + { + sector_type = ioctl_get_sector_data_type(id, cdb[2], cdb[3], cdb[4], cdb[5], 0); + if (sector_type == 0) + { + cdrom_illegal_mode(id); + return 1; + } + } +common_handler: + temp_len = flags_to_size[sector_type - 1][cdb[9] >> 3]; + if ((cdb[9] & 6) == 2) + { + temp_len += 294; + } + else if ((cdb[9] & 6) == 4) + { + temp_len += 296; + } + if ((cdb[10] & 7) == 1) + { + temp_len += 96; + } + else if ((cdb[10] & 7) == 2) + { + temp_len += 16; + } + else if ((cdb[10] & 7) == 4) + { + temp_len += 96; + } + if (temp_len <= 0) + { + cdrom_illegal_mode(id); + return 1; + } + sptd.s.DataTransferLength = temp_len * cdrom[id].requested_blocks; + break; + default: +bypass_check: + /* Other commands */ + sptd.s.DataTransferLength = 64512; + break; + } + sptd.s.SenseInfoOffset = (uintptr_t)&sptd.sense - (uintptr_t)&sptd; + sptd.s.SenseInfoLength = 32; + sptd.s.DataBufferOffset = (uintptr_t)&sptd.data - (uintptr_t)&sptd; + memcpy(sptd.s.Cdb, cdb, 12); - ioctl_rv = DeviceIoControl(hIOCTL, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); - memcpy(buf, sptd.s.DataBuffer, len); + ioctl_rv = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_SCSI_PASS_THROUGH, &sptd, sizeof(sptd), &sptd, sizeof(sptd), &ioctl_bytes, NULL); + + if (sptd.s.SenseInfoLength) + { + cdrom_sense_key = sptd.sense[2]; + cdrom_asc = sptd.sense[12]; + cdrom_ascq = sptd.sense[13]; + } + + cdrom_ioctl_log("Transferred length: %i (command: %02X)\n", sptd.s.DataTransferLength, cdb[0]); + cdrom_ioctl_log("Sense length: %i (%02X %02X %02X %02X %02X)\n", sptd.s.SenseInfoLength, sptd.sense[0], sptd.sense[1], sptd.sense[2], sptd.sense[12], sptd.sense[13]); + cdrom_ioctl_log("IOCTL bytes: %i; SCSI status: %i, status: %i, LastError: %08X\n", ioctl_bytes, sptd.s.ScsiStatus, ioctl_rv, GetLastError()); + cdrom_ioctl_log("DATA: %02X %02X %02X %02X %02X %02X\n", sptd.data[0], sptd.data[1], sptd.data[2], sptd.data[3], sptd.data[4], sptd.data[5]); + cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.data[6], sptd.data[7], sptd.data[8], sptd.data[9], sptd.data[10], sptd.data[11]); + cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.data[12], sptd.data[13], sptd.data[14], sptd.data[15], sptd.data[16], sptd.data[17]); + cdrom_ioctl_log("SENSE: %02X %02X %02X %02X %02X %02X\n", sptd.sense[0], sptd.sense[1], sptd.sense[2], sptd.sense[3], sptd.sense[4], sptd.sense[5]); + cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.sense[6], sptd.sense[7], sptd.sense[8], sptd.sense[9], sptd.sense[10], sptd.sense[11]); + cdrom_ioctl_log(" %02X %02X %02X %02X %02X %02X\n", sptd.sense[12], sptd.sense[13], sptd.sense[14], sptd.sense[15], sptd.sense[16], sptd.sense[17]); + *len = sptd.s.DataTransferLength; + if (sptd.s.DataTransferLength != 0) + { + memcpy(buf, sptd.data, sptd.s.DataTransferLength); + } return ioctl_rv; } -static void ioctl_read_capacity(uint8_t *b) +static void ioctl_read_capacity(uint8_t id, uint8_t *b) { + int len = 0; + const UCHAR cdb[] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; UCHAR buf[16]; - ioctl_open(0); + ioctl_open(id, 0); - SCSICommand(cdb, buf, 16); - - memcpy(b, buf, 8); - - ioctl_close(); -} - -static void ioctl_read_subchannel(uint8_t *in_cdb, uint8_t *b) -{ - const UCHAR cdb[12]; - UCHAR buf[24]; - - ioctl_open(0); - - memcpy(cdb, in_cdb, 12); - SCSICommand(cdb, buf, 24); - - memcpy(b, buf, 24); - - ioctl_close(); -} - -static void ioctl_read_header(uint8_t *in_cdb, uint8_t *b) -{ - const UCHAR cdb[12]; - UCHAR buf[16]; - - ioctl_open(0); - - memcpy(cdb, in_cdb, 12); - SCSICommand(cdb, buf, 16); - - memcpy(b, buf, 8); - - ioctl_close(); -} - -static int ioctl_read_track_information(uint8_t *in_cdb, uint8_t *b) -{ - int maxlen = 0; - int len = 0; - - int ret = 0; - - const UCHAR cdb[12]; - UCHAR buf[65536]; - - maxlen = in_cdb[7]; - maxlen <<= 8; - maxlen |= in_cdb[8]; - - ioctl_open(0); - - memcpy(cdb, in_cdb, 12); - ret = SCSICommand(cdb, buf, 65535); - - if (!ret) - { - return 0; - } - - len = buf[0]; - len <<= 8; - len |= buf[1]; - len += 2; - - if (len > maxlen) - { - len = maxlen; - buf[0] = ((maxlen - 2) >> 8) * 0xff; - buf[1] = (maxlen - 2) & 0xff; - } + SCSICommand(id, cdb, buf, &len, 1); memcpy(b, buf, len); - ioctl_close(); - - return 1; -} - -static void ioctl_read_disc_information(uint8_t *b) -{ - const UCHAR cdb[] = { 0x51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - UCHAR buf[68]; - - ioctl_open(0); - - SCSICommand(cdb, buf, 68); - - memcpy(b, buf, 34); - - ioctl_close(); -} - -static int SCSIReadCommon(const UCHAR *cdb_0, const UCHAR *cdb_1, const UCHAR *cdb_2, const UCHAR *cdb_4, uint8_t *b, UCHAR *buf) -{ - int ioctl_rv; - - ioctl_open(0); - - /* Fill the buffer with zeroes. */ - memset(b, 0, 2856); - - ioctl_rv = SCSICommand(cdb_0, buf, 2856); - memcpy(b, buf, 2648); - - /* Next, try to read RAW subchannel data. */ - ioctl_rv += SCSICommand(cdb_1, buf, 2856); - memcpy(b + 2648, buf + 2648, 96); - - /* Next, try to read Q subchannel data. */ - ioctl_rv += SCSICommand(cdb_2, buf, 2856); - memcpy(b + 2648 + 96, buf + 2648, 16); - - /* Next, try to read R - W subchannel data. */ - ioctl_rv += SCSICommand(cdb_4, buf, 2856); - memcpy(b + 2648 + 96 + 16, buf + 2648, 96); - - ioctl_close(); - - // pclog("rv: %i\n", ioctl_rv); - - return ioctl_rv; -} - -/* Direct SCSI read in MSF mode. */ -static int SCSIReadMSF(uint8_t *b, int sector) -{ - const UCHAR cdb_0[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 0, 0 }; - const UCHAR cdb_1[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 1, 0 }; - const UCHAR cdb_2[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 2, 0 }; - const UCHAR cdb_4[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0xFC, 4, 0 }; - UCHAR buf[2856]; - - return SCSIReadCommon(cdb_0, cdb_1, cdb_2, cdb_4, b, buf); -} - -/* Direct SCSI read in LBA mode. */ -static void SCSIRead(uint8_t *b, int sector) -{ - const UCHAR cdb_0[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 0, 0 }; - const UCHAR cdb_1[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 1, 0 }; - const UCHAR cdb_2[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 2, 0 }; - const UCHAR cdb_4[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0xFC, 4, 0 }; - UCHAR buf[2856]; - - SCSIReadCommon(cdb_0, cdb_1, cdb_2, cdb_4, b, buf); - return; + ioctl_close(id); } static uint32_t msf_to_lba32(int lba) @@ -680,15 +661,17 @@ static uint32_t msf_to_lba32(int lba) return (m * 60 * 75) + (s * 75) + f; } -static int ioctl_get_type(UCHAR *cdb, UCHAR *buf) +static int ioctl_get_type(uint8_t id, UCHAR *cdb, UCHAR *buf) { int i = 0; int ioctl_rv = 0; + + int len = 0; for (i = 2; i <= 5; i++) { cdb[1] = i << 2; - ioctl_rv = SCSICommand(cdb, buf, 2352); + ioctl_rv = SCSICommand(id, cdb, buf, &len, 1); /* Bypass length check so we don't risk calling this again and getting stuck in an endless up. */ if (ioctl_rv) { return i; @@ -697,32 +680,32 @@ static int ioctl_get_type(UCHAR *cdb, UCHAR *buf) return 0; } -static int ioctl_sector_data_type(int sector, int ismsf) +static int ioctl_sector_data_type(uint8_t id, int sector, int ismsf) { int ioctl_rv = 0; const UCHAR cdb_lba[] = { 0xBE, 0, (sector >> 24), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0, 0, 1, 0x10, 0, 0 }; const UCHAR cdb_msf[] = { 0xB9, 0, 0, ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), ((sector >> 16) & 0xff), ((sector >> 8) & 0xff), (sector & 0xff), 0x10, 0, 0 }; UCHAR buf[2352]; - ioctl_open(0); + ioctl_open(id, 0); - if (ioctl_is_track_audio(sector, ismsf)) + if (ioctl_is_track_audio(id, sector, ismsf)) { return 1; } if (ismsf) { - ioctl_rv = ioctl_get_type(cdb_msf, buf); + ioctl_rv = ioctl_get_type(id, cdb_msf, buf); } else { - ioctl_rv = ioctl_get_type(cdb_lba, buf); + ioctl_rv = ioctl_get_type(id, cdb_lba, buf); } if (ioctl_rv) { - ioctl_close(); + ioctl_close(id); return ioctl_rv; } @@ -731,247 +714,75 @@ static int ioctl_sector_data_type(int sector, int ismsf) sector = msf_to_lba32(sector); if (sector < 150) { - ioctl_close(); + ioctl_close(id); return 0; } sector -= 150; - ioctl_rv = ioctl_get_type(cdb_lba, buf); + ioctl_rv = ioctl_get_type(id, cdb_lba, buf); } - ioctl_close(); + ioctl_close(id); return ioctl_rv; } -static void ioctl_readsector_raw(uint8_t *b, int sector, int ismsf) +static int ioctl_get_sector_data_type(uint8_t id, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, int ismsf) { - if (!cdrom_drive) return; - if (ioctl_cd_state == CD_PLAYING) - return; - - if (ismsf) - { - if (!SCSIReadMSF(b, sector)) - { - sector = msf_to_lba32(sector); - if (sector < 150) - { - memset(b, 0, 2856); - return; - } - sector -= 150; - SCSIRead(b, sector); - } - } - else - { - SCSIRead(b, sector); - } + int sector = b3; + sector |= ((uint32_t) b2) << 8; + sector |= ((uint32_t) b1) << 16; + sector |= ((uint32_t) b0) << 24; + return ioctl_sector_data_type(id, sector, ismsf); } -static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) +static void ioctl_validate_toc(uint8_t id) { - int len=4; - long size; - int c,d; - uint32_t temp; - if (!cdrom_drive) return 0; - ioctl_cd_state = CD_STOPPED; - ioctl_open(0); - DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&toc,sizeof(toc),&size,NULL); - ioctl_close(); - tocvalid=1; -// pclog("Read TOC done! %i\n",single); - b[2]=toc.FirstTrack; - b[3]=toc.LastTrack; - d=0; - for (c=0;c<=toc.LastTrack;c++) - { - if (toc.TrackData[c].TrackNumber>=starttrack) - { - d=c; - break; - } - } - b[2]=toc.TrackData[c].TrackNumber; - last_block = 0; - for (c=d;c<=toc.LastTrack;c++) - { - uint32_t address; - if ((len+8)>maxlen) break; -// pclog("Len %i max %i Track %02X - %02X %02X %i %i %i %i %08X\n",len,maxlen,toc.TrackData[c].TrackNumber,toc.TrackData[c].Adr,toc.TrackData[c].Control,toc.TrackData[c].Address[0],toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3],MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3])); - b[len++]=0; /*Reserved*/ - b[len++]=(toc.TrackData[c].Adr<<4)|toc.TrackData[c].Control; - b[len++]=toc.TrackData[c].TrackNumber; - b[len++]=0; /*Reserved*/ - address = MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]); - if (address > last_block) - last_block = address; - - if (msf) - { - b[len++]=toc.TrackData[c].Address[0]; - b[len++]=toc.TrackData[c].Address[1]; - b[len++]=toc.TrackData[c].Address[2]; - b[len++]=toc.TrackData[c].Address[3]; - } - else - { - temp=MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]); - b[len++]=temp>>24; - b[len++]=temp>>16; - b[len++]=temp>>8; - b[len++]=temp; - } - if (single) break; - } - if (len > maxlen) - { - len = maxlen; - } - b[0] = (uint8_t)(((len-2) >> 8) & 0xff); - b[1] = (uint8_t)((len-2) & 0xff); -/* pclog("Table of Contents (%i bytes) : \n",size); - pclog("First track - %02X\n",toc.FirstTrack); - pclog("Last track - %02X\n",toc.LastTrack); - for (c=0;c<=toc.LastTrack;c++) - pclog("Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n",c,toc.TrackData[c].TrackNumber,toc.TrackData[c].Control,toc.TrackData[c].Adr,toc.TrackData[c].Address[0],toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]); - for (c=0;c<=toc.LastTrack;c++) - pclog("Track %02X - number %02X control %02X adr %02X address %06X\n",c,toc.TrackData[c].TrackNumber,toc.TrackData[c].Control,toc.TrackData[c].Adr,MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]));*/ - return len; -} - -static int ioctl_readtoc_session(unsigned char *b, int msf, int maxlen) -{ - int len=4; - int size; - uint32_t temp; - CDROM_READ_TOC_EX toc_ex; - CDROM_TOC_SESSION_DATA toc; - if (!cdrom_drive) return 0; - ioctl_cd_state = CD_STOPPED; - memset(&toc_ex,0,sizeof(toc_ex)); - memset(&toc,0,sizeof(toc)); - toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_SESSION; - toc_ex.Msf=msf; - toc_ex.SessionTrack=0; - ioctl_open(0); - DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL); - ioctl_close(); -// pclog("Read TOC session - %i %02X %02X %i %i %02X %02X %02X\n",size,toc.Length[0],toc.Length[1],toc.FirstCompleteSession,toc.LastCompleteSession,toc.TrackData[0].Adr,toc.TrackData[0].Control,toc.TrackData[0].TrackNumber); - b[2]=toc.FirstCompleteSession; - b[3]=toc.LastCompleteSession; - b[len++]=0; /*Reserved*/ - b[len++]=(toc.TrackData[0].Adr<<4)|toc.TrackData[0].Control; - b[len++]=toc.TrackData[0].TrackNumber; - b[len++]=0; /*Reserved*/ - if (msf) - { - b[len++]=toc.TrackData[0].Address[0]; - b[len++]=toc.TrackData[0].Address[1]; - b[len++]=toc.TrackData[0].Address[2]; - b[len++]=toc.TrackData[0].Address[3]; - } - else - { - temp=MSFtoLBA(toc.TrackData[0].Address[1],toc.TrackData[0].Address[2],toc.TrackData[0].Address[3]); - b[len++]=temp>>24; - b[len++]=temp>>16; - b[len++]=temp>>8; - b[len++]=temp; - } - - if (len > maxlen) - { - len = maxlen; - } - b[0] = ((len - 2) >> 8) & 0xff; - b[1] = (len - 2) & 0xff; - return len; -} - -static void ioctl_readtoc_raw(uint8_t *b, int msf, int maxlen) -{ - UCHAR cdb[12]; - UCHAR buf[65536]; - - int len = 0; - - ioctl_open(0); - - cdb[0] = 0x43; - cdb[1] = msf ? 2 : 0; - cdb[2] = 2; - cdb[3] = cdb[4] = cdb[5] = cdb[6] = 0; - cdb[7] = (maxlen >> 8) & 0xff; - cdb[8] = maxlen & 0xff; - cdb[9] = cdb[10] = cdb[11] = 0; - - SCSICommand(cdb, buf, 65535); - - len = buf[0]; - len <<= 8; - len |= buf[1]; - len += 2; - - memcpy(b, buf, len); - - ioctl_close(); -} - -#if 0 -static int ioctl_readtoc_raw(unsigned char *b, int maxlen) -{ - int len=4; - int size; - uint32_t temp; - int i; - int BytesRead = 0; - CDROM_READ_TOC_EX toc_ex; - CDROM_TOC_FULL_TOC_DATA toc; - if (!cdrom_drive) return 0; - ioctl_cd_state = CD_STOPPED; - memset(&toc_ex,0,sizeof(toc_ex)); - memset(&toc,0,sizeof(toc)); - toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_FULL_TOC; - toc_ex.Msf=1; - toc_ex.SessionTrack=0; - ioctl_open(0); - DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL); - ioctl_close(); -// pclog("Read TOC session - %i %02X %02X %i %i %02X %02X %02X\n",size,toc.Length[0],toc.Length[1],toc.FirstCompleteSession,toc.LastCompleteSession,toc.TrackData[0].Adr,toc.TrackData[0].Control,toc.TrackData[0].TrackNumber); - b[2]=toc.FirstCompleteSession; - b[3]=toc.LastCompleteSession; - - size -= sizeof(CDROM_TOC_FULL_TOC_DATA); - size /= sizeof(toc.Descriptors[0]); - - for (i = 0; i <= size; i++) + long size; + if (!cdrom_drives[id].host_drive) { - b[len++]=toc.Descriptors[i].SessionNumber; - b[len++]=(toc.Descriptors[i].Adr<<4)|toc.Descriptors[i].Control; - b[len++]=0; - b[len++]=toc.Descriptors[i].Reserved1; /*Reserved*/ - b[len++]=toc.Descriptors[i].MsfExtra[0]; - b[len++]=toc.Descriptors[i].MsfExtra[1]; - b[len++]=toc.Descriptors[i].MsfExtra[2]; - b[len++]=toc.Descriptors[i].Zero; - b[len++]=toc.Descriptors[i].Msf[0]; - b[len++]=toc.Descriptors[i].Msf[1]; - b[len++]=toc.Descriptors[i].Msf[2]; + return; } - - b[0] = (len >> 8) & 0xff; - b[1] = len & 0xff; - - return len; + cdrom_ioctl[id].cd_state = CD_STOPPED; + ioctl_open(id, 0); + DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&cdrom_ioctl_windows[id].toc,sizeof(cdrom_ioctl_windows[id].toc),&size,NULL); + ioctl_close(id); + cdrom_ioctl[id].tocvalid=1; } -#endif -static uint32_t ioctl_size() +UCHAR buf[64512]; + +static int ioctl_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len) +{ + const UCHAR cdb[12]; + + int ret; + + if (cdb[0] == 0x43) + { + /* This is a read TOC, so we have to validate the TOC to make the rest of the emulator happy. */ + ioctl_validate_toc(id); + } + + ioctl_open(id, 0); + + memcpy(cdb, in_cdb, 12); + ret = SCSICommand(id, cdb, buf, len, 0); + + memcpy(b, buf, *len); + + cdrom_ioctl_log("IOCTL DATA: %02X %02X %02X %02X %02X %02X %02X %02X\n", b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]); + + ioctl_close(id); + + cdrom_ioctl_log("IOCTL Returned value: %i\n", ret); + + return ret; +} + +static uint32_t ioctl_size(uint8_t id) { uint8_t capacity_buffer[8]; uint32_t capacity = 0; - ioctl_read_capacity(capacity_buffer); + ioctl_read_capacity(id, capacity_buffer); capacity = ((uint32_t) capacity_buffer[0]) << 24; capacity |= ((uint32_t) capacity_buffer[1]) << 16; capacity |= ((uint32_t) capacity_buffer[2]) << 8; @@ -980,12 +791,12 @@ static uint32_t ioctl_size() // return cdrom_capacity; } -static int ioctl_status() +static int ioctl_status(uint8_t id) { - if (!(ioctl_ready) && (cdrom_drive <= 0)) + if (!(ioctl_ready(id)) && (cdrom_drives[id].host_drive <= 0)) return CD_STATUS_EMPTY; - switch(ioctl_cd_state) + switch(cdrom_ioctl[id].cd_state) { case CD_PLAYING: return CD_STATUS_PLAYING; @@ -996,87 +807,81 @@ static int ioctl_status() } } -void ioctl_reset() +void ioctl_reset(uint8_t id) { CDROM_TOC ltoc; int temp; long size; - if (!cdrom_drive) + if (!cdrom_drives[id].host_drive) { - tocvalid = 0; + cdrom_ioctl[id].tocvalid = 0; return; } - ioctl_open(0); - temp = DeviceIoControl(hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc, sizeof(ltoc), &size, NULL); - ioctl_close(); + ioctl_open(id, 0); + temp = DeviceIoControl(cdrom_ioctl_windows[id].hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, <oc, sizeof(ltoc), &size, NULL); + ioctl_close(id); - toc = ltoc; - tocvalid = 1; + cdrom_ioctl_windows[id].toc = ltoc; + cdrom_ioctl[id].tocvalid = 1; } -int ioctl_open(char d) +int ioctl_open(uint8_t id, char d) { -// char s[8]; - if (!ioctl_inited) - { - sprintf(ioctl_path,"\\\\.\\%c:",d); - // pclog("Path is %s\n",ioctl_path); - tocvalid=0; - } -// pclog("Opening %s\n",ioctl_path); - // hIOCTL = CreateFile(/*"\\\\.\\g:"*/ioctl_path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL); - hIOCTL = CreateFile(ioctl_path, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL); - if (!hIOCTL) + // char s[8]; + if (!cdrom_ioctl[id].ioctl_inited) { - //fatal("IOCTL"); - } - cdrom=&ioctl_cdrom; - if (!ioctl_inited) - { - ioctl_inited=1; - CloseHandle(hIOCTL); - hIOCTL = NULL; - } - return 0; + sprintf(cdrom_ioctl[id].ioctl_path,"\\\\.\\%c:",d); + // cdrom_ioctl_log("Path is %s\n",ioctl_path); + cdrom_ioctl[id].tocvalid=0; + } + // cdrom_ioctl_log("Opening %s\n",ioctl_path); + cdrom_ioctl_windows[id].hIOCTL = CreateFile(cdrom_ioctl[id].ioctl_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (!cdrom_ioctl_windows[id].hIOCTL) + { + // fatal("IOCTL"); + } + cdrom_drives[id].handler = &ioctl_cdrom; + if (!cdrom_ioctl[id].ioctl_inited) + { + cdrom_ioctl[id].ioctl_inited=1; + CloseHandle(cdrom_ioctl_windows[id].hIOCTL); + cdrom_ioctl_windows[id].hIOCTL = NULL; + } + return 0; } -void ioctl_close(void) +void ioctl_close(uint8_t id) { - if (hIOCTL) - { - CloseHandle(hIOCTL); - hIOCTL = NULL; - } + if (cdrom_ioctl_windows[id].hIOCTL) + { + CloseHandle(cdrom_ioctl_windows[id].hIOCTL); + cdrom_ioctl_windows[id].hIOCTL = NULL; + } } -static void ioctl_exit(void) +static void ioctl_exit(uint8_t id) { - ioctl_stop(); - ioctl_inited=0; - tocvalid=0; + ioctl_stop(id); + cdrom_ioctl[id].ioctl_inited=0; + cdrom_ioctl[id].tocvalid=0; } static CDROM ioctl_cdrom= { ioctl_ready, ioctl_medium_changed, - ioctl_readtoc, - ioctl_readtoc_session, - ioctl_readtoc_raw, + ioctl_audio_callback, + ioctl_audio_stop, + NULL, + NULL, + NULL, ioctl_getcurrentsubchannel, - ioctl_read_capacity, - ioctl_read_subchannel, - ioctl_read_header, - ioctl_read_disc_information, - ioctl_read_track_information, + ioctl_pass_through, ioctl_sector_data_type, - ioctl_readsector_raw, + NULL, ioctl_playaudio, - ioctl_seek, ioctl_load, ioctl_eject, ioctl_pause, diff --git a/src/cdrom-ioctl.h b/src/cdrom-ioctl.h index 3c1f54981..e39f12ddf 100644 --- a/src/cdrom-ioctl.h +++ b/src/cdrom-ioctl.h @@ -9,9 +9,9 @@ extern uint32_t cdrom_capacity; -extern int ioctl_open(char d); -extern void ioctl_reset(); +extern int ioctl_open(uint8_t id, char d); +extern void ioctl_reset(uint8_t id); -extern void ioctl_close(void); +extern void ioctl_close(uint8_t id); #endif /* ! CDROM_IOCTL_H */ diff --git a/src/cdrom-iso.c b/src/cdrom-iso.c index 7847f81af..bb3d7c361 100644 --- a/src/cdrom-iso.c +++ b/src/cdrom-iso.c @@ -10,104 +10,71 @@ static CDROM iso_cdrom; -uint32_t last_block = 0; -static uint64_t image_size = 0; -static int iso_inited = 0; -char iso_path[1024]; -void iso_close(void); -static FILE* iso_image; -static int iso_changed = 0; +int cdrom_iso_do_log = 1; -static uint32_t lba = 0; +void cdrom_iso_log(const char *format, ...) +{ +#ifdef ENABLE_CDROM_ISO_LOG + if (cdrom_do_log) + { + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + fflush(stdout); + } +#endif +} -static uint32_t iso_cd_pos = 0, iso_cd_end = 0; +void iso_close(uint8_t id); -void iso_audio_callback(int16_t *output, int len) +void iso_audio_callback(uint8_t id, int16_t *output, int len) { memset(output, 0, len * 2); return; } -void iso_audio_stop() +void iso_audio_stop(uint8_t id) { - // pclog("iso_audio_stop stub\n"); + // cdrom_iso_log("iso_audio_stop stub\n"); } -static int get_track_nr(uint32_t pos) +static int iso_ready(uint8_t id) { - // pclog("get_track_nr stub\n"); - return 0; -} - -static void iso_playaudio(uint32_t pos, uint32_t len, int ismsf) -{ - // pclog("iso_playaudio stub\n"); - return; -} - -static void iso_pause(void) -{ - // pclog("iso_pause stub\n"); - return; -} - -static void iso_resume(void) -{ - // pclog("iso_resume stub\n"); - return; -} - -static void iso_stop(void) -{ - // pclog("iso_stop stub\n"); - return; -} - -static void iso_seek(uint32_t pos) -{ - // pclog("iso_seek stub\n"); - lba = pos; - return; -} - -static int iso_ready(void) -{ - if (strlen(iso_path) == 0) + if (strlen(cdrom_iso[id].iso_path) == 0) { return 0; } - if (old_cdrom_drive != cdrom_drive) + if (cdrom_drives[id].prev_host_drive != cdrom_drives[id].host_drive) { - // old_cdrom_drive = cdrom_drive; return 1; } - if (iso_changed) + if (cdrom_iso[id].iso_changed) { - iso_changed = 0; + cdrom_iso[id].iso_changed = 0; return 1; } return 1; } -/* Always return 0, because there is no way to change the ISO without unmounting and remounting it. */ -static int iso_medium_changed(void) +static int iso_medium_changed(uint8_t id) { - if (strlen(iso_path) == 0) + if (strlen(cdrom_iso[id].iso_path) == 0) { return 0; } - if (old_cdrom_drive != cdrom_drive) + if (cdrom_drives[id].prev_host_drive != cdrom_drives[id].host_drive) { - old_cdrom_drive = cdrom_drive; + cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; return 1; } - if (iso_changed) + if (cdrom_iso[id].iso_changed) { - iso_changed = 0; + cdrom_iso[id].iso_changed = 0; return 1; } @@ -122,11 +89,11 @@ static void lba_to_msf(uint8_t *buf, int lba) buf[2] = lba % 75; } -static uint8_t iso_getcurrentsubchannel(uint8_t *b, int msf) +static uint8_t iso_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) { long size; int pos=0; - if (strlen(iso_path) == 0) + if (strlen(cdrom_iso[id].iso_path) == 0) { return 0; } @@ -135,7 +102,7 @@ static uint8_t iso_getcurrentsubchannel(uint8_t *b, int msf) b[pos++]=0; b[pos++]=0; - int32_t temp = lba; + int32_t temp = cdrom[id].seek_pos; if (msf) { memset(&(b[pos]), 0, 8); @@ -156,48 +123,35 @@ static uint8_t iso_getcurrentsubchannel(uint8_t *b, int msf) b[pos++] = temp; } - return 0x13; + return 0x15; } -static void iso_eject(void) +static void iso_eject(uint8_t id) { - // pclog("iso_eject stub\n"); + // cdrom_iso_log("iso_eject stub\n"); } -static void iso_load(void) +static void iso_load(uint8_t id) { - // pclog("iso_load stub\n"); + // cdrom_iso_log("iso_load stub\n"); } -static int iso_sector_data_type(int sector, int ismsf) +static int iso_sector_data_type(uint8_t id, int sector, int ismsf) { return 2; /* Always Mode 1 */ } -static void iso_readsector_raw(uint8_t *b, int sector, int ismsf) +static void iso_readsector(uint8_t id, uint8_t *b, int sector) { uint32_t temp; uint64_t file_pos = sector; - if (!cdrom_drive) return; + if (!cdrom_drives[id].host_drive) return; file_pos <<= 11; memset(b, 0, 2856); - if (ismsf) - { - int m = (sector >> 16) & 0xff; - int s = (sector >> 8) & 0xff; - int f = sector & 0xff; - sector = (m * 60 * 75) + (s * 75) + f; - if (sector < 150) - { - memset(b, 0, 2856); - return; - } - sector -= 150; - } - iso_image = fopen(iso_path, "rb"); - fseeko64(iso_image, file_pos, SEEK_SET); - fread(b + 16, 2048, 1, iso_image); - fclose(iso_image); + cdrom_iso[id].iso_image = fopen(cdrom_iso[id].iso_path, "rb"); + fseeko64(cdrom_iso[id].iso_image, file_pos, SEEK_SET); + fread(b + 16, 2048, 1, cdrom_iso[id].iso_image); + fclose(cdrom_iso[id].iso_image); /* sync bytes */ b[0] = 0; @@ -213,7 +167,185 @@ static void iso_readsector_raw(uint8_t *b, int sector, int ismsf) memset(b, 0, 392); } -static int iso_readtoc(unsigned char *buf, unsigned char start_track, int msf, int maxlen, int single) +typedef struct __attribute__((packed)) +{ + uint8_t user_data[2048]; + uint8_t ecc[288]; +} m1_data_t; + +typedef struct __attribute__((packed)) +{ + uint8_t sub_header[8]; + uint8_t user_data[2328]; +} m2_data_t; + +typedef union __attribute__((packed)) +{ + m1_data_t m1_data; + m2_data_t m2_data; + uint8_t raw_data[2352]; +} sector_data_t; + +typedef struct __attribute__((packed)) +{ + uint8_t sync[12]; + uint8_t header[4]; + sector_data_t data; + uint8_t c2[296]; + uint8_t subchannel_raw[96]; + uint8_t subchannel_q[16]; + uint8_t subchannel_rw[96]; +} cdrom_sector_t; + +typedef union __attribute__((packed)) +{ + cdrom_sector_t cdrom_sector; + uint8_t buffer[2856]; +} sector_buffer_t; + +sector_buffer_t cdrom_sector_buffer; + +int cdrom_sector_size; + +static int iso_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len) +{ + int real_sector_type; + uint8_t *b; + uint8_t *temp_b; + int is_audio; + int real_pos; + + b = temp_b = buffer; + + *len = 0; + + if (ismsf) + { + real_pos = cdrom_lba_to_msf_accurate(sector); + } + else + { + real_pos = sector; + } + + memset(cdrom_sector_buffer.buffer, 0, 2856); + + if ((cdrom_sector_type == 1) || (cdrom_sector_type > 2)) + { + if (cdrom_sector_type == 1) + { + cdrom_iso_log("CD-ROM %i: Attempting to read an audio sector from an ISO\n", id); + } + if (cdrom_sector_type >= 2) + { + cdrom_iso_log("CD-ROM %i: Attempting to read a non-mode 1 data sector from an ISO\n", id); + } + return 0; + } + + if (!(cdrom_sector_flags & 0xf0)) /* 0x00 and 0x08 are illegal modes */ + { + cdrom_iso_log("CD-ROM %i: 0x00 and 0x08 are illegal modes\n", id); + return 0; + } + + if ((cdrom_sector_flags & 0x06) == 0x06) + { + cdrom_iso_log("CD-ROM %i: Invalid error flags\n", id); + return 0; + } + + if (((cdrom_sector_flags & 0x700) == 0x300) || ((cdrom_sector_flags & 0x700) > 0x400)) + { + cdrom_iso_log("CD-ROM %i: Invalid subchannel data flags (%02X)\n", id, cdrom_sector_flags & 0x700); + return 0; + } + + if ((cdrom_sector_flags & 0x18) == 0x08) /* EDC/ECC without user data is an illegal mode */ + { + cdrom_iso_log("CD-ROM %i: EDC/ECC without user data is an illegal mode\n", id); + return 0; + } + + iso_readsector(id, cdrom_sector_buffer.buffer, real_pos); + + cdrom_sector_size = 0; + + if (cdrom_sector_flags & 0x80) /* Sync */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.sync, 12); + cdrom_sector_size += 12; + temp_b += 12; + } + if (cdrom_sector_flags & 0x20) /* Header */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.header, 4); + cdrom_sector_size += 4; + temp_b += 4; + } + + /* Mode 1 sector, expected type is 1 type. */ + if (cdrom_sector_flags & 0x40) /* Sub-header */ + { + if (!(cdrom_sector_flags & 0x10)) /* No user data */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 8); + cdrom_sector_size += 8; + temp_b += 8; + } + } + if (cdrom_sector_flags & 0x10) /* User data */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 2048); + cdrom_sector_size += 2048; + temp_b += 2048; + } + if (cdrom_sector_flags & 0x08) /* EDC/ECC */ + { + memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.ecc, 288); + cdrom_sector_size += 288; + temp_b += 288; + } + + cdrom_iso_log("CD-ROM sector size: %i (%i, %i) [%04X]\n", cdrom_sector_size, cdrom_sector_type, real_sector_type, cdrom_sector_flags); + + if ((cdrom_sector_flags & 0x06) == 0x02) + { + /* Add error flags. */ + memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 294); + cdrom_sector_size += 294; + } + else if ((cdrom_sector_flags & 0x06) == 0x04) + { + /* Add error flags. */ + memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 296); + cdrom_sector_size += 296; + } + + if ((cdrom_sector_flags & 0x700) == 0x100) + { + memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_raw, 96); + cdrom_sector_size += 96; + } + else if ((cdrom_sector_flags & 0x700) == 0x200) + { + memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_q, 16); + cdrom_sector_size += 16; + } + else if ((cdrom_sector_flags & 0x700) == 0x400) + { + memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_rw, 96); + cdrom_sector_size += 96; + } + + memcpy(buffer, b, cdrom_sector_size); + + *len = cdrom_sector_size; + + return 1; +} + +static int iso_readtoc(uint8_t id, unsigned char *buf, unsigned char start_track, int msf, int maxlen, int single) { uint8_t *q; int len; @@ -245,16 +377,16 @@ static int iso_readtoc(unsigned char *buf, unsigned char start_track, int msf, i *q++ = 0x16; /* ADR, control */ *q++ = 0xaa; /* track number */ *q++ = 0; /* reserved */ - last_block = image_size >> 11; + cdrom_iso[id].last_block = cdrom_iso[id].image_size >> 11; if (msf) { *q++ = 0; /* reserved */ - lba_to_msf(q, last_block); + lba_to_msf(q, cdrom_iso[id].last_block); q += 3; } else { - *q++ = last_block >> 24; - *q++ = last_block >> 16; - *q++ = last_block >> 8; - *q++ = last_block; + *q++ = cdrom_iso[id].last_block >> 24; + *q++ = cdrom_iso[id].last_block >> 16; + *q++ = cdrom_iso[id].last_block >> 8; + *q++ = cdrom_iso[id].last_block; } len = q - buf; if (len > maxlen) @@ -266,7 +398,7 @@ static int iso_readtoc(unsigned char *buf, unsigned char start_track, int msf, i return len; } -static int iso_readtoc_session(unsigned char *buf, int msf, int maxlen) +static int iso_readtoc_session(uint8_t id, unsigned char *buf, int msf, int maxlen) { uint8_t *q; @@ -290,7 +422,7 @@ static int iso_readtoc_session(unsigned char *buf, int msf, int maxlen) return 12; } -static int iso_readtoc_raw(unsigned char *buf, int msf, int maxlen) +static int iso_readtoc_raw(uint8_t id, unsigned char *buf, int msf, int maxlen) { uint8_t *q; int len; @@ -330,20 +462,20 @@ static int iso_readtoc_raw(unsigned char *buf, int msf, int maxlen) *q++ = 0; /* min */ *q++ = 0; /* sec */ *q++ = 0; /* frame */ - last_block = image_size >> 11; + cdrom_iso[id].last_block = cdrom_iso[id].image_size >> 11; /* this is raw, must be msf */ if (msf) { *q++ = 0; /* reserved */ - lba_to_msf(q, last_block); + lba_to_msf(q, cdrom_iso[id].last_block); q += 3; } else { - *q++ = (last_block >> 24) & 0xff; - *q++ = (last_block >> 16) & 0xff; - *q++ = (last_block >> 8) & 0xff; - *q++ = last_block & 0xff; + *q++ = (cdrom_iso[id].last_block >> 24) & 0xff; + *q++ = (cdrom_iso[id].last_block >> 16) & 0xff; + *q++ = (cdrom_iso[id].last_block >> 8) & 0xff; + *q++ = cdrom_iso[id].last_block & 0xff; } *q++ = 1; /* session number */ @@ -378,72 +510,71 @@ static int iso_readtoc_raw(unsigned char *buf, int msf, int maxlen) return len; } -static uint32_t iso_size() +static uint32_t iso_size(uint8_t id) { uint64_t iso_size; - iso_image = fopen(iso_path, "rb"); - fseeko64(iso_image, 0, SEEK_END); - iso_size = ftello64(iso_image); + cdrom_iso[id].iso_image = fopen(cdrom_iso[id].iso_path, "rb"); + fseeko64(cdrom_iso[id].iso_image, 0, SEEK_END); + iso_size = ftello64(cdrom_iso[id].iso_image); iso_size >>= 11; - fclose(iso_image); + fclose(cdrom_iso[id].iso_image); return (uint32_t) (iso_size); } -static int iso_status() +static int iso_status(uint8_t id) { - if (!(iso_ready()) && (cdrom_drive != 200)) return CD_STATUS_EMPTY; + if (!(iso_ready(id)) && (cdrom_drives[id].host_drive != 200)) return CD_STATUS_EMPTY; return CD_STATUS_DATA_ONLY; } -void iso_reset() +void iso_reset(uint8_t id) { } -int iso_open(char *fn) +int iso_open(uint8_t id, char *fn) { struct stat st; - if (strcmp(fn, iso_path) != 0) + if (strcmp(fn, cdrom_iso[id].iso_path) != 0) { - iso_changed = 1; + cdrom_iso[id].iso_changed = 1; } /* Make sure iso_changed stays when changing from ISO to another ISO. */ - if (!iso_inited && (cdrom_drive != 200)) iso_changed = 0; - if (!iso_inited || iso_changed) + if (!cdrom_iso[id].iso_inited && (cdrom_drives[id].host_drive != 200)) cdrom_iso[id].iso_changed = 0; + if (!cdrom_iso[id].iso_inited || cdrom_iso[id].iso_changed) { - sprintf(iso_path, "%s", fn); - // pclog("Path is %s\n", iso_path); + sprintf(cdrom_iso[id].iso_path, "%s", fn); + // cdrom_iso_log("Path is %s\n", cdrom_iso[id].iso_path); } - iso_image = fopen(iso_path, "rb"); - cdrom = &iso_cdrom; - if (!iso_inited || iso_changed) + cdrom_iso[id].iso_image = fopen(cdrom_iso[id].iso_path, "rb"); + cdrom_drives[id].handler = &iso_cdrom; + if (!cdrom_iso[id].iso_inited || cdrom_iso[id].iso_changed) { - if (!iso_inited) iso_inited = 1; - fclose(iso_image); + if (!cdrom_iso[id].iso_inited) cdrom_iso[id].iso_inited = 1; + fclose(cdrom_iso[id].iso_image); } - stat(iso_path, &st); - image_size = st.st_size; + stat(cdrom_iso[id].iso_path, &st); + cdrom_iso[id].image_size = st.st_size; return 0; } -void iso_close(void) +void iso_close(uint8_t id) { - if (iso_image) fclose(iso_image); - memset(iso_path, 0, 1024); + if (cdrom_iso[id].iso_image) fclose(cdrom_iso[id].iso_image); + memset(cdrom_iso[id].iso_path, 0, 1024); } -static void iso_exit(void) +static void iso_exit(uint8_t id) { - // iso_stop(); - iso_inited = 0; + cdrom_iso[id].iso_inited = 0; } -static int iso_is_track_audio(uint32_t pos, int ismsf) +static int iso_is_track_audio(uint8_t id, uint32_t pos, int ismsf) { return 0; } @@ -452,26 +583,23 @@ static CDROM iso_cdrom = { iso_ready, iso_medium_changed, + NULL, + NULL, iso_readtoc, iso_readtoc_session, iso_readtoc_raw, iso_getcurrentsubchannel, NULL, - NULL, - NULL, - NULL, - NULL, iso_sector_data_type, iso_readsector_raw, - iso_playaudio, - iso_seek, + NULL, iso_load, iso_eject, - iso_pause, - iso_resume, + NULL, + NULL, iso_size, iso_status, iso_is_track_audio, - iso_stop, + NULL, iso_exit }; diff --git a/src/cdrom-iso.h b/src/cdrom-iso.h index 4dbcfca2e..c16ea0ebb 100644 --- a/src/cdrom-iso.h +++ b/src/cdrom-iso.h @@ -7,13 +7,9 @@ /* this header file lists the functions provided by various platform specific cdrom-ioctl files */ -extern uint32_t last_block; - -extern char iso_path[1024]; +extern int iso_open(uint8_t id, char *fn); +extern void iso_reset(uint8_t id); -extern int iso_open(char *fn); -extern void iso_reset(); - -extern void iso_close(void); +extern void iso_close(uint8_t id); #endif /* ! CDROM_ISO_H */ diff --git a/src/cdrom-null.c b/src/cdrom-null.c index 76ec0ab3c..6e886ed27 100644 --- a/src/cdrom-null.c +++ b/src/cdrom-null.c @@ -5,121 +5,97 @@ #include "cdrom.h" #include "cdrom-ioctl.h" -int cdrom_drive; - static CDROM null_cdrom; -void cdrom_null_audio_callback(int16_t *output, int len) -{ - memset(output, 0, len * 2); -} - -void cdrom_null_audio_stop() -{ -} - -static void null_playaudio(uint32_t pos, uint32_t len, int ismsf) -{ -} - -static void null_pause(void) -{ -} - -static void null_resume(void) -{ -} - -static void null_stop(void) -{ -} - -static void null_seek(uint32_t pos) -{ -} - -static int null_ready(void) +static int null_ready(uint8_t id) { return 0; } /* Always return 0, the contents of a null CD-ROM drive never change. */ -static int null_medium_changed(void) +static int null_medium_changed(uint8_t id) { return 0; } -static uint8_t null_getcurrentsubchannel(uint8_t *b, int msf) +static uint8_t null_getcurrentsubchannel(uint8_t id, uint8_t *b, int msf) { return 0x13; } -static void null_eject(void) +static void null_eject(uint8_t id) { } -static void null_load(void) +static void null_load(uint8_t id) { } -static int null_sector_data_type(int sector, int ismsf) +static int null_sector_data_type(uint8_t id, int sector, int ismsf) { return 0; } -static void null_readsector_raw(uint8_t *b, int sector, int ismsf) +static int null_readsector_raw(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len) { + *len = 0; + return 0; } -static int null_read_track_information(uint8_t *in_cdb, uint8_t *b) +static int null_read_track_information(uint8_t id, uint8_t *in_cdb, uint8_t *b) { return 0; } -static int null_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) +static int null_readtoc(uint8_t id, unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single) { return 0; } -static int null_readtoc_session(unsigned char *b, int msf, int maxlen) +static int null_readtoc_session(uint8_t id, unsigned char *b, int msf, int maxlen) { return 0; } -static int null_readtoc_raw(unsigned char *b, int msf, int maxlen) +static int null_readtoc_raw(uint8_t id, unsigned char *b, int msf, int maxlen) { return 0; } -static uint32_t null_size() +static uint32_t null_size(uint8_t id) { return 0; } -static int null_status() +static int null_status(uint8_t id) { return CD_STATUS_EMPTY; } -void cdrom_null_reset() +void cdrom_null_reset(uint8_t id) { } -int cdrom_null_open(char d) +int cdrom_null_open(uint8_t id, char d) { - cdrom = &null_cdrom; + cdrom_drives[id].handler = &null_cdrom; return 0; } -void null_close(void) +void null_close(uint8_t id) { } -static void null_exit(void) +static void null_exit(uint8_t id) { } -static int null_is_track_audio(uint32_t pos, int ismsf) +static int null_is_track_audio(uint8_t id, uint32_t pos, int ismsf) +{ + return 0; +} + +static int null_pass_through(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len) { return 0; } @@ -128,26 +104,23 @@ static CDROM null_cdrom = { null_ready, null_medium_changed, + NULL, + NULL, null_readtoc, null_readtoc_session, null_readtoc_raw, null_getcurrentsubchannel, - NULL, - NULL, - NULL, - NULL, - NULL, + null_pass_through, null_sector_data_type, null_readsector_raw, - null_playaudio, - null_seek, + NULL, null_load, null_eject, - null_pause, - null_resume, + NULL, + NULL, null_size, null_status, null_is_track_audio, - null_stop, + NULL, null_exit }; diff --git a/src/cdrom-null.h b/src/cdrom-null.h index 6900f3d23..7cc595089 100644 --- a/src/cdrom-null.h +++ b/src/cdrom-null.h @@ -7,8 +7,8 @@ /* this header file lists the functions provided by various platform specific cdrom-ioctl files */ -extern int cdrom_null_open(char d); -extern void cdrom_null_reset(); -extern void null_close(); +extern int cdrom_null_open(uint8_t id, char d); +extern void cdrom_null_reset(uint8_t id); +extern void null_close(uint8_t id); #endif /* ! CDROM_IOCTL_H */ diff --git a/src/cdrom.c b/src/cdrom.c new file mode 100644 index 000000000..da0f2b65a --- /dev/null +++ b/src/cdrom.c @@ -0,0 +1,2867 @@ +/* CD-ROM emulation, used by both ATAPI and SCSI */ + +#include +#include +#include + +#include "86box.h" +#include "cdrom.h" +#include "ibm.h" +#include "ide.h" +#include "scsi.h" +#include "timer.h" + +/* Bits of 'status' */ +#define ERR_STAT 0x01 +#define DRQ_STAT 0x08 /* Data request */ +#define DSC_STAT 0x10 +#define SERVICE_STAT 0x10 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +/* Bits of 'error' */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* Media change request */ + +#define MODE_SELECT_PHASE_IDLE 0 +#define MODE_SELECT_PHASE_HEADER 1 +#define MODE_SELECT_PHASE_PAGE_HEADER 2 +#define MODE_SELECT_PHASE_PAGE 3 + +cdrom_t cdrom[CDROM_NUM]; +cdrom_drive_t cdrom_drives[CDROM_NUM]; +uint8_t atapi_cdrom_drives[8] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; +uint8_t scsi_cdrom_drives[16] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + +static struct __attribute__((__packed__)) +{ + uint8_t opcode; + uint8_t polled; + uint8_t reserved2[2]; + uint8_t class; + uint8_t reserved3[2]; + uint16_t len; + uint8_t control; +} *gesn_cdb; + +static struct __attribute__((__packed__)) +{ + uint16_t len; + uint8_t notification_class; + uint8_t supported_events; +} *gesn_event_header; + +/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ +uint8_t cdrom_command_flags[0x100] = +{ + [GPCMD_TEST_UNIT_READY] = IMPLEMENTED | CHECK_READY | NONDATA, + [GPCMD_REZERO_UNIT] = IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, + [GPCMD_REQUEST_SENSE] = IMPLEMENTED | ALLOW_UA, + [GPCMD_READ_6] = IMPLEMENTED | CHECK_READY, + [GPCMD_SEEK_6] = IMPLEMENTED | CHECK_READY | NONDATA, + [GPCMD_INQUIRY] = IMPLEMENTED | ALLOW_UA, + [GPCMD_VERIFY_6] = IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, + [GPCMD_MODE_SELECT_6] = IMPLEMENTED, + [GPCMD_MODE_SENSE_6] = IMPLEMENTED, + [GPCMD_START_STOP_UNIT] = IMPLEMENTED | CHECK_READY, + [GPCMD_PREVENT_REMOVAL] = IMPLEMENTED | CHECK_READY, + [GPCMD_READ_CDROM_CAPACITY] = IMPLEMENTED | CHECK_READY, + [GPCMD_READ_10] = IMPLEMENTED | CHECK_READY, + [GPCMD_SEEK_10] = IMPLEMENTED | CHECK_READY | NONDATA, + [GPCMD_VERIFY_10] = IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, + [GPCMD_READ_SUBCHANNEL] = IMPLEMENTED | CHECK_READY, + [GPCMD_READ_TOC_PMA_ATIP] = IMPLEMENTED | CHECK_READY, /* Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS + NOTE: The ATAPI reference says otherwise, but I think this is a question of + interpreting things right - the UNIT ATTENTION condition we have here + is a tradition from not ready to ready, by definition the drive + eventually becomes ready, make the condition go away. */ + [GPCMD_READ_HEADER] = IMPLEMENTED | CHECK_READY, + [GPCMD_PLAY_AUDIO_10] = IMPLEMENTED | CHECK_READY, + [GPCMD_GET_CONFIGURATION] = IMPLEMENTED | ALLOW_UA, + [GPCMD_PLAY_AUDIO_MSF] = IMPLEMENTED | CHECK_READY, + [GPCMD_PLAY_AUDIO_TRACK_INDEX] = IMPLEMENTED | CHECK_READY, + [GPCMD_GET_EVENT_STATUS_NOTIFICATION] = IMPLEMENTED | ALLOW_UA, + [GPCMD_PAUSE_RESUME] = IMPLEMENTED | CHECK_READY, + [GPCMD_STOP_PLAY_SCAN] = IMPLEMENTED | CHECK_READY, + [GPCMD_READ_DISC_INFORMATION] = IMPLEMENTED | CHECK_READY, + [GPCMD_READ_TRACK_INFORMATION] = IMPLEMENTED | CHECK_READY, + [GPCMD_MODE_SELECT_10] = IMPLEMENTED, + [GPCMD_MODE_SENSE_10] = IMPLEMENTED, + [GPCMD_PLAY_AUDIO_12] = IMPLEMENTED | CHECK_READY, + [GPCMD_READ_12] = IMPLEMENTED | CHECK_READY, + [GPCMD_READ_DVD_STRUCTURE] = IMPLEMENTED | CHECK_READY, + [GPCMD_VERIFY_12] = IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, + [GPCMD_PLAY_CD_OLD] = IMPLEMENTED | CHECK_READY | ATAPI_ONLY, + [GPCMD_READ_CD_OLD] = IMPLEMENTED | CHECK_READY | ATAPI_ONLY, + [GPCMD_READ_CD_MSF] = IMPLEMENTED | CHECK_READY, + [GPCMD_SCAN] = IMPLEMENTED | CHECK_READY, + [GPCMD_SET_SPEED] = IMPLEMENTED, + [GPCMD_PLAY_CD] = IMPLEMENTED | CHECK_READY, + [GPCMD_MECHANISM_STATUS] = IMPLEMENTED, + [GPCMD_READ_CD] = IMPLEMENTED | CHECK_READY, + [GPCMD_SEND_DVD_STRUCTURE] = IMPLEMENTED | CHECK_READY, + [GPCMD_SCAN_ALT] = IMPLEMENTED | CHECK_READY | SCSI_ONLY, + [GPCMD_SET_SPEED_ALT] = IMPLEMENTED | SCSI_ONLY +}; + +uint8_t cdrom_mode_sense_page_flags[CDROM_NUM][0x40] = +{ + { [GPMODE_R_W_ERROR_PAGE] = IMPLEMENTED, + [GPMODE_CDROM_PAGE] = IMPLEMENTED, + [GPMODE_CDROM_AUDIO_PAGE] = IMPLEMENTED, + [GPMODE_CAPABILITIES_PAGE] = IMPLEMENTED, + [GPMODE_ALL_PAGES] = IMPLEMENTED }, + { [GPMODE_R_W_ERROR_PAGE] = IMPLEMENTED, + [GPMODE_CDROM_PAGE] = IMPLEMENTED, + [GPMODE_CDROM_AUDIO_PAGE] = IMPLEMENTED, + [GPMODE_CAPABILITIES_PAGE] = IMPLEMENTED, + [GPMODE_ALL_PAGES] = IMPLEMENTED }, + { [GPMODE_R_W_ERROR_PAGE] = IMPLEMENTED, + [GPMODE_CDROM_PAGE] = IMPLEMENTED, + [GPMODE_CDROM_AUDIO_PAGE] = IMPLEMENTED, + [GPMODE_CAPABILITIES_PAGE] = IMPLEMENTED, + [GPMODE_ALL_PAGES] = IMPLEMENTED }, + { [GPMODE_R_W_ERROR_PAGE] = IMPLEMENTED, + [GPMODE_CDROM_PAGE] = IMPLEMENTED, + [GPMODE_CDROM_AUDIO_PAGE] = IMPLEMENTED, + [GPMODE_CAPABILITIES_PAGE] = IMPLEMENTED, + [GPMODE_ALL_PAGES] = IMPLEMENTED } +}; + +const uint8_t cdrom_mode_sense_pages_default[CDROM_NUM][0x40][0x40] = +{ + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 0, 2, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } }, + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 0, 2, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } }, + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 0, 2, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } }, + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 0, 2, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } } +}; + +uint8_t cdrom_mode_sense_pages_changeable[CDROM_NUM][0x40][0x40] = +{ + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 0, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 0, 0, 0, 0, 0 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } +}; + +uint8_t cdrom_mode_sense_pages_saved[CDROM_NUM][0x40][0x40] = +{ + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 0, 2, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } }, + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 0, 2, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } }, + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 0, 2, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } }, + { [GPMODE_R_W_ERROR_PAGE] = { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, + [GPMODE_CDROM_PAGE] = { GPMODE_CDROM_PAGE, 6, 0, 1, 0, 60, 0, 75 }, + [GPMODE_CDROM_AUDIO_PAGE] = { 0x8E, 0xE, 4, 0, 0, 0, 0, 75, 1, 0xFF, 2, 0xFF, 0, 0, 0, 0 }, + [GPMODE_CAPABILITIES_PAGE] = { GPMODE_CAPABILITIES_PAGE, 0x12, 0, 0, 1, 0, 0, 0, 0x02, 0xC2, 0, 2, 0, 0, 0x02, 0xC2, 0, 0, 0, 0 } } +}; + +int cdrom_do_log = 1; + +void cdrom_log(const char *format, ...) +{ +#ifdef ENABLE_CDROM_LOG + if (cdrom_do_log) + { + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + fflush(stdout); + } +#endif +} + +int cdrom_mode_select_terminate(uint8_t id, int force); + +int find_cdrom_for_channel(uint8_t channel) +{ + uint8_t i = 0; + + for (i = 0; i < CDROM_NUM; i++) + { + if (!cdrom_drives[i].bus_type && (cdrom_drives[i].ide_channel == channel)) + { + return i; + } + } + return 0xff; +} + +void cdrom_init(int id, int cdb_len_setting, int bus_type); + +void build_atapi_cdrom_map() +{ + uint8_t i = 0; + + memset(atapi_cdrom_drives, 0xff, 8); + + for (i = 0; i < 8; i++) + { + atapi_cdrom_drives[i] = find_cdrom_for_channel(i); + if (atapi_cdrom_drives[i] != 0xff) + { + cdrom_init(atapi_cdrom_drives[i], 12, 0); + } + } +} + +int find_cdrom_for_scsi_id(uint8_t scsi_id) +{ + uint8_t i = 0; + + for (i = 0; i < CDROM_NUM; i++) + { + if (cdrom_drives[i].bus_type && (cdrom_drives[i].scsi_device_id == scsi_id)) + { + return i; + } + } + return 0xff; +} + +void build_scsi_cdrom_map() +{ + uint8_t i = 0; + + memset(scsi_cdrom_drives, 0xff, 16); + + for (i = 0; i < 16; i++) + { + scsi_cdrom_drives[i] = find_cdrom_for_scsi_id(i); + if (scsi_cdrom_drives[i] != 0xff) + { + cdrom_init(scsi_cdrom_drives[i], 12, 1); + } + } +} + +void cdrom_set_cdb_len(int id, int cdb_len) +{ + cdrom[id].cdb_len = cdb_len; +} + +void cdrom_reset_cdb_len(int id) +{ + cdrom[id].cdb_len = cdrom[id].cdb_len_setting ? 16 : 12; +} + +void cdrom_set_signature(int id) +{ + cdrom[id].phase = 1; + cdrom[id].request_length = 0xEB14; +} + +void cdrom_init(int id, int cdb_len_setting, int bus_type) +{ + if (id >= CDROM_NUM) + { + return; + } + memset(&(cdrom[id]), 0, sizeof(cdrom_t)); + cdrom[id].requested_blocks = 1; + if (cdb_len_setting <= 1) + { + cdrom[id].cdb_len_setting = cdb_len_setting; + } + cdrom_reset_cdb_len(id); + cdrom_mode_select_terminate(id, 1); + cdrom[id].cd_status = CD_STATUS_EMPTY; + cdrom[id].sense[0] = 0xf0; + cdrom[id].sense[7] = 10; + cdrom_drives[id].bus_mode = cdrom_drives[id].bus_type ? 2 : 3; + if (!cdrom_drives[id].bus_type) + { + cdrom_set_signature(id); + cdrom_drives[id].check_on_execution = 1; + cdrom_drives[id].max_blocks_at_once = 1; + } + else + { + cdrom_drives[id].check_on_execution = scsi_model ? 0 : 1; + cdrom_drives[id].max_blocks_at_once = 85; + } + cdrom[id].status = READY_STAT | DSC_STAT; + cdrom[id].pos = 0; + cdrom[id].packet_status = 0xff; + cdrom_sense_key = cdrom_asc = cdrom_ascq = cdrom[id].unit_attention = 0; + cdrom[id].cdb_len_setting = 0; + cdrom[id].cdb_len = 12; +} + +int cdrom_supports_pio(int id) +{ + return (cdrom_drives[id].bus_mode & 1); +} + +int cdrom_supports_dma(int id) +{ + return (cdrom_drives[id].bus_mode & 2); +} + +/* Returns: 0 for none, 1 for PIO, 2 for DMA. */ +int cdrom_current_mode(int id) +{ + if (!cdrom_supports_pio(id) && !cdrom_supports_dma(id)) + { + return 0; + } + if (cdrom_supports_pio(id) && !cdrom_supports_dma(id)) + { + return 1; + } + if (!cdrom_supports_pio(id) && cdrom_supports_dma(id)) + { + return 2; + } + if (cdrom_supports_pio(id) && cdrom_supports_dma(id)) + { + return (cdrom[id].features & 1) ? 2 : 1; + } +} + +/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ +int cdrom_CDROM_PHASE_to_scsi(uint8_t id) +{ + if (cdrom[id].status & ERR_STAT) + { + return SCSI_STATUS_CHECK_CONDITION; + } + else + { + return SCSI_STATUS_OK; + } +} + +/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ +int cdrom_atapi_phase_to_scsi(uint8_t id) +{ + if (cdrom[id].status & 8) + { + switch (cdrom[id].phase & 3) + { + case 0: + return 0; + case 1: + return 2; + case 2: + return 1; + case 3: + return 7; + } + } + else + { + if ((cdrom[id].phase & 3) == 3) + { + return 3; + } + else + { + /* Translate reserved ATAPI phase to reserved SCSI phase. */ + return 4; + } + } +} + +int cdrom_lba_to_msf_accurate(int lba) +{ + int temp_pos; + int m, s, f; + + temp_pos = lba + 150; + f = temp_pos % 75; + temp_pos -= f; + temp_pos /= 75; + s = temp_pos % 60; + temp_pos -= s; + temp_pos /= 60; + m = temp_pos; + + return ((m << 16) | (s << 8) | f); +} + +uint32_t cdrom_mode_sense_get_channel(uint8_t id, int channel) +{ + return cdrom_mode_sense_pages_saved[id][GPMODE_CDROM_AUDIO_PAGE][channel ? 10 : 8]; +} + +uint32_t cdrom_mode_sense_get_volume(uint8_t id, int channel) +{ + return cdrom_mode_sense_pages_saved[id][GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; +} + +void cdrom_mode_sense_load(uint8_t id) +{ + FILE *f; + switch(id) + { + case 0: + f = fopen(nvr_concat("cdrom_1_mode_sense.bin"), "rb"); + break; + case 1: + f = fopen(nvr_concat("cdrom_2_mode_sense.bin"), "rb"); + break; + case 2: + f = fopen(nvr_concat("cdrom_3_mode_sense.bin"), "rb"); + break; + case 3: + f = fopen(nvr_concat("cdrom_4_mode_sense.bin"), "rb"); + break; + } + if (!f) + { + return; + } + fread(cdrom_mode_sense_pages_saved[id][GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); + fclose(f); +} + +void cdrom_mode_sense_save(uint8_t id) +{ + FILE *f; + switch(id) + { + case 0: + f = fopen(nvr_concat("cdrom_1_mode_sense.bin"), "wb"); + break; + case 1: + f = fopen(nvr_concat("cdrom_2_mode_sense.bin"), "wb"); + break; + case 2: + f = fopen(nvr_concat("cdrom_3_mode_sense.bin"), "wb"); + break; + case 3: + f = fopen(nvr_concat("cdrom_4_mode_sense.bin"), "wb"); + break; + } + if (!f) + { + return; + } + fwrite(cdrom_mode_sense_pages_saved[id][GPMODE_CDROM_AUDIO_PAGE], 1, 0x10, f); + fclose(f); +} + +int cdrom_mode_select_init(uint8_t id, uint8_t command, uint16_t pl_length, uint8_t do_save) +{ + switch(command) + { + case GPCMD_MODE_SELECT_6: + cdrom[id].current_page_len = 4; + break; + case GPCMD_MODE_SELECT_10: + cdrom[id].current_page_len = 8; + break; + default: + cdrom_log("CD-ROM %i: Attempting to initialize MODE SELECT with unrecognized command: %02X\n", id, command); + return -1; + } + if (pl_length == 0) + { + cdrom_log("CD-ROM %i: Attempting to initialize MODE SELECT with zero parameter list length: %02X\n", id, command); + return -2; + } + cdrom[id].current_page_pos = 0; + cdrom[id].mode_select_phase = MODE_SELECT_PHASE_HEADER; + cdrom[id].total_length = pl_length; + cdrom[id].written_length = 0; + cdrom[id].do_page_save = do_save; + return 1; +} + +int cdrom_mode_select_terminate(uint8_t id, int force) +{ + if (((cdrom[id].written_length >= cdrom[id].total_length) || force) && (cdrom[id].mode_select_phase != MODE_SELECT_PHASE_IDLE)) + { + cdrom_log("CD-ROM %i: MODE SELECT terminate: %i\n", id, force); + if (!force && cdrom[id].do_page_save && (cdrom_mode_sense_pages_default[id][cdrom[id].current_page_pos][0] & 0x80)) + { + cdrom_mode_sense_save(id); + } + cdrom[id].current_page_pos = cdrom[id].current_page_len = 0; + cdrom[id].total_length = cdrom[id].written_length = 0; + cdrom[id].mode_select_phase = MODE_SELECT_PHASE_IDLE; + if (force) + { + cdrom_mode_sense_load(id); + } + return 1; + } + else + { + return 0; + } +} + +int cdrom_mode_select_header(uint8_t id) +{ + cdrom[id].current_page_pos++; + if (cdrom[id].current_page_pos >= cdrom[id].current_page_len) + { + cdrom[id].current_page_pos = 0; + cdrom[id].mode_select_phase = MODE_SELECT_PHASE_PAGE_HEADER; + } + return 1; +} + +static void cdrom_invalid_field_pl(uint8_t id); + +int cdrom_mode_select_page_header(uint8_t id, uint8_t val) +{ + if (cdrom[id].current_page_pos == 0) + { + cdrom[id].current_page_code = val & 0x3f; + if (cdrom_mode_sense_page_flags[id][cdrom[id].current_page_code] != IMPLEMENTED) + { + cdrom_log("CD-ROM %i: Trying to modify an unimplemented page: %02X\n", id, cdrom[id].current_page_code); + cdrom_mode_select_terminate(id, 1); + cdrom_invalid_field_pl(id); + } + cdrom[id].current_page_pos++; + } + else if (cdrom[id].current_page_pos == 1) + { + cdrom[id].current_page_pos = 0; + cdrom[id].current_page_len = val; + cdrom[id].mode_select_phase = MODE_SELECT_PHASE_PAGE; + } + return 1; +} + +int cdrom_mode_select_page(uint8_t id, uint8_t val) +{ + if (cdrom_mode_sense_pages_changeable[id][cdrom[id].current_page_code][cdrom[id].current_page_pos + 2] != 0xFF) + { + if (val != cdrom_mode_sense_pages_saved[id][cdrom[id].current_page_code][cdrom[id].current_page_pos + 2]) + { + /* Trying to change an unchangeable value. */ + cdrom_log("CD-ROM %i: Trying to change an unchangeable value: [%02X][%02X] = %02X (new: %02X)\n", id, cdrom[id].current_page_code, cdrom[id].current_page_pos + 2, cdrom_mode_sense_pages_saved[id][cdrom[id].current_page_code][cdrom[id].current_page_pos + 2], val); + cdrom_mode_select_terminate(id, 1); + cdrom_invalid_field_pl(id); + return 0; + } + } + else + { + if (cdrom[id].current_page_code == 0xE) + { + if ((cdrom[id].current_page_pos == 6) || (cdrom[id].current_page_pos == 8)) + { + if (val > 3) + { + /* Trying to set an unsupported audio channel. */ + cdrom_log("CD-ROM %i: Trying to set an unsupported value: [%02X][%02X] = %02X (new: %02X)\n", id, cdrom[id].current_page_code, cdrom[id].current_page_pos, cdrom_mode_sense_pages_saved[id][cdrom[id].current_page_code][cdrom[id].current_page_pos + 2], val); + return 0; + } + } + } + cdrom_mode_sense_pages_saved[id][cdrom[id].current_page_code][cdrom[id].current_page_pos + 2] = val; + } + cdrom[id].current_page_pos++; + if (cdrom[id].current_page_pos >= cdrom[id].current_page_len) + { + cdrom[id].current_page_pos = 0; + cdrom[id].mode_select_phase = MODE_SELECT_PHASE_PAGE_HEADER; + } + return 1; +} + +static void cdrom_command_complete(uint8_t id); + +int cdrom_mode_select_write(uint8_t id, uint8_t val) +{ + int ret = 0; + int ret2 = 0; + + if (id > CDROM_NUM) + { + cdrom_log("MODE SELECT: attempted write to wrong CD-ROM drive\n", val); + return -6; + } + + if (cdrom[id].total_length == 0) + { + cdrom_log("CD-ROM %i: MODE SELECT: attempted write when not initialized (%02X)\n", id, val); + return -3; + } + + cdrom[id].written_length++; + + switch (cdrom[id].mode_select_phase) + { + case MODE_SELECT_PHASE_IDLE: + cdrom_log("CD-ROM %i: MODE SELECT idle (%02X)\n", id, val); + ret = 1; + break; + case MODE_SELECT_PHASE_HEADER: + cdrom_log("CD-ROM %i: MODE SELECT header (%02X)\n", id, val); + ret = cdrom_mode_select_header(id); + break; + case MODE_SELECT_PHASE_PAGE_HEADER: + cdrom_log("CD-ROM %i: MODE SELECT page header (%02X)\n", id, val); + ret = cdrom_mode_select_page_header(id, val); + break; + case MODE_SELECT_PHASE_PAGE: + cdrom_log("CD-ROM %i: MODE SELECT page (%02X)\n", id, val); + ret = cdrom_mode_select_page(id, val); + break; + default: + cdrom_log("CD-ROM %i: MODE SELECT unknown phase (%02X)\n", id, val); + ret = -4; + break; + } + + /* On termination, override the return value, but only if it is 1. */ + ret2 = cdrom_mode_select_terminate(id, 0); + if (ret2) + { + cdrom_command_complete(id); + } + if (ret2 && (ret == 1)) + { + ret = -5; + } + + return ret; +} + +/*SCSI Mode Sense 6/10*/ +uint8_t cdrom_mode_sense_read(uint8_t id, uint8_t page_control, uint8_t page, uint8_t pos) +{ + switch (page_control) + { + case 0: + case 3: + return cdrom_mode_sense_pages_saved[id][page][pos]; + break; + case 1: + return cdrom_mode_sense_pages_changeable[id][page][pos]; + break; + case 2: + return cdrom_mode_sense_pages_default[id][page][pos]; + break; + } +} + +uint32_t cdrom_mode_sense(uint8_t id, uint8_t *buf, uint32_t pos, uint8_t type) +{ + uint8_t page_control = (type >> 6) & 3; + + int i = 0; + int j = 0; + + uint8_t msplen; + + type &= 0x3f; + + for (i = 0; i < 0x40; i++) + { + if ((type == GPMODE_ALL_PAGES) || (type == i)) + { + if (cdrom_mode_sense_page_flags[id][i] == IMPLEMENTED) + { + buf[pos++] = cdrom_mode_sense_read(id, page_control, i, 0); + msplen = cdrom_mode_sense_read(id, page_control, i, 1); + buf[pos++] = msplen; + cdrom_log("CD-ROM %i: MODE SENSE: Page [%02X] length %i\n", id, i, msplen); + for (j = 0; j < msplen; j++) + { + buf[pos++] = cdrom_mode_sense_read(id, page_control, i, 2 + j); + } + } + } + } + + return pos; +} + +void cdrom_update_request_length(uint8_t id, int len, int block_len) +{ + /* For media access commands, make sure the requested DRQ length matches the block length. */ + switch (cdrom[id].current_cdb[0]) + { + case 0x08: + case 0x28: + case 0xa8: + case 0xb9: + case 0xbe: + if (cdrom[id].request_length < block_len) + { + cdrom[id].request_length = block_len; + } + /* Make sure we respect the limit of how many blocks we can transfer at once. */ + if (cdrom[id].requested_blocks > cdrom_drives[id].max_blocks_at_once) + { + cdrom[id].requested_blocks = cdrom_drives[id].max_blocks_at_once; + } + cdrom[id].block_total = (cdrom[id].requested_blocks * block_len); + if (len > cdrom[id].block_total) + { + len = cdrom[id].block_total; + } + if (cdrom[id].packet_len == 0) + { + cdrom[id].packet_len = cdrom[id].sector_len * block_len; + } + cdrom_log("Packet length now: %i (%i * %i)\n", cdrom[id].packet_len, cdrom[id].sector_len, block_len); + break; + default: + cdrom[id].packet_len = len; + break; + } + /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ + if ((cdrom[id].request_length & 1) && (cdrom[id].request_length < len)) + { + cdrom[id].request_length &= 0xfffe; + } + /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + if (len <= cdrom[id].request_length) + { + cdrom[id].request_length = len; + } + return; +} + +static int cdrom_is_media_access(uint8_t id) +{ + switch (cdrom[id].current_cdb[0]) + { + case 0x08: + case 0x28: + case 0xa8: + case 0xb9: + case 0xbe: + return 1; + default: + return 0; + } +} + +static void cdrom_command_common(uint8_t id) +{ + cdrom[id].status = BUSY_STAT; + cdrom[id].phase = 1; + cdrom[id].pos = 0; + cdrom[id].callback = 60 * CDROM_TIME; +} + +static void cdrom_command_complete(uint8_t id) +{ + cdrom[id].packet_status = CDROM_PHASE_COMPLETE; + cdrom_command_common(id); +} + +static void cdrom_command_read(uint8_t id) +{ + cdrom[id].packet_status = CDROM_PHASE_DATA_IN; + cdrom_command_common(id); + cdrom[id].total_read = 0; +} + +static void cdrom_command_read_dma(uint8_t id) +{ + cdrom[id].packet_status = CDROM_PHASE_DATA_IN_DMA; + cdrom_command_common(id); + cdrom[id].total_read = 0; +} + +static void cdrom_command_write(uint8_t id) +{ + cdrom[id].packet_status = CDROM_PHASE_DATA_OUT; + cdrom_command_common(id); +} + +static void cdrom_command_write_dma(uint8_t id) +{ + cdrom[id].packet_status = CDROM_PHASE_DATA_OUT_DMA; + cdrom_command_common(id); +} + +static void cdrom_data_command_finish(uint8_t id, int len, int block_len, int alloc_len, int direction) +{ + cdrom_log("CD-ROM %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", id, cdrom[id].current_cdb[0], len, block_len, alloc_len, direction, cdrom[id].request_length); + cdrom[id].pos=0; + if (alloc_len >= 0) + { + if (alloc_len < len) + { + len = alloc_len; + } + } + if ((len == 0) || (cdrom_current_mode(id) == 0)) + { + cdrom_command_complete(id); + } + else + { + if (cdrom_current_mode(id) == 2) + { + if (cdrom_drives[id].bus_type) + { + if (cdrom_is_media_access(id)) + { + SCSIDevices[cdrom_drives[id].scsi_device_id].InitLength = alloc_len; + } + else + { + SCSIDevices[cdrom_drives[id].scsi_device_id].InitLength = alloc_len; + } + } + if (direction == 0) + { + cdrom_command_read_dma(id); + } + else + { + cdrom_command_write_dma(id); + } + } + else + { + cdrom_update_request_length(id, len, block_len); + if (direction == 0) + { + cdrom_command_read(id); + } + else + { + cdrom_command_write(id); + } + } + } + + cdrom_log("CD-ROM %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", id, cdrom[id].packet_status, cdrom[id].request_length, cdrom[id].packet_len, cdrom[id].pos, cdrom[id].phase); +} + +static void cdrom_sense_clear(int id, int command, int ignore_ua) +{ + if ((cdrom_sense_key == SENSE_UNIT_ATTENTION) || ignore_ua) + { + cdrom[id].previous_command = command; + cdrom_sense_key = cdrom_asc = cdrom_ascq = 0; + } +} + +static void cdrom_cmd_error(uint8_t id) +{ + cdrom[id].error = ((cdrom_sense_key & 0xf) << 4) | ABRT_ERR; + if (cdrom[id].unit_attention) + { + cdrom[id].error |= MCR_ERR; + } + cdrom[id].status = READY_STAT | ERR_STAT; + cdrom[id].phase = 3; + cdrom[id].packet_status = 0x80; + cdrom[id].callback = 50 * CDROM_TIME; +} + +static void cdrom_unit_attention(uint8_t id) +{ + cdrom[id].error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + if (cdrom[id].unit_attention) + { + cdrom[id].error |= MCR_ERR; + } + cdrom[id].status = READY_STAT | ERR_STAT; + cdrom[id].phase = 3; + cdrom[id].packet_status = 0x80; + cdrom[id].callback = 50 * CDROM_TIME; +} + +static void cdrom_not_ready(uint8_t id) +{ + cdrom_sense_key = SENSE_NOT_READY; + cdrom_asc = ASC_MEDIUM_NOT_PRESENT; + cdrom_ascq = 0; + cdrom_cmd_error(id); +} + +static void cdrom_illegal_opcode(uint8_t id) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_ILLEGAL_OPCODE; + cdrom_ascq = 0; + cdrom_cmd_error(id); +} + +static void cdrom_lba_out_of_range(uint8_t id) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_LBA_OUT_OF_RANGE; + cdrom_ascq = 0; + cdrom_cmd_error(id); +} + +static void cdrom_invalid_field(uint8_t id) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_INV_FIELD_IN_CMD_PACKET; + cdrom_ascq = 0; + cdrom_cmd_error(id); + cdrom[id].status = 0x53; +} + +static void cdrom_invalid_field_pl(uint8_t id) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; + cdrom_ascq = 0; + cdrom_cmd_error(id); + cdrom[id].status = 0x53; +} + +static void cdrom_illegal_mode(uint8_t id) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; + cdrom_ascq = 0; + cdrom_cmd_error(id); +} + +static void cdrom_incompatible_format(uint8_t id) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_INCOMPATIBLE_FORMAT; + cdrom_ascq = 0; + cdrom_cmd_error(id); +} + +static void cdrom_data_phase_error(uint8_t id) +{ + cdrom_sense_key = SENSE_ILLEGAL_REQUEST; + cdrom_asc = ASC_DATA_PHASE_ERROR; + cdrom_ascq = 0; + cdrom_cmd_error(id); +} + +static int cdrom_pass_through(uint8_t id, int *len) +{ + int ret = 0; + uint8_t *cdbufferb = (uint8_t *) cdrom[id].buffer; + + ret = cdrom_drives[id].handler->pass_through(id, cdrom[id].current_cdb, cdbufferb + cdrom[id].data_pos, len); + cdrom_log("CD-ROM %i: Data from pass through: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[cdrom[id].data_pos + 0], cdbufferb[cdrom[id].data_pos + 1], cdbufferb[cdrom[id].data_pos + 2], cdbufferb[cdrom[id].data_pos + 3], cdbufferb[cdrom[id].data_pos + 4], cdbufferb[cdrom[id].data_pos + 5], cdbufferb[cdrom[id].data_pos + 6], cdbufferb[cdrom[id].data_pos + 7]); + cdrom_log("CD-ROM %i: Returned value: %i\n", id, ret); + + if (!ret) + { + /* Command failed with OS error code, return illegal opcode. */ + cdrom_log("CD-ROM %i: Command failed with OS error code, return illegal opcode.\n", id); + cdrom_illegal_opcode(id); + return 0; + } + else + { + if ((cdrom_sense_key != 0) || (cdrom_asc != 0) || (cdrom_ascq != 0)) + { + /* Command failed with sense, error with that sense. */ + cdrom_log("CD-ROM %i: Command failed with sense, error with that sense.\n", id); + cdrom_cmd_error(id); + return 0; + } + else + { + /* Command was performed successfully. */ + cdrom_log("CD-ROM %i: Command was performed successfully.\n", id); + return 1; + } + } +} + +int cdrom_update_cdb(uint8_t id) +{ + int temp = 0; + + switch(cdrom[id].current_cdb[0]) + { + case GPCMD_READ_6: + cdrom[id].current_cdb[1] = (cdrom[id].sector_pos >> 16) & 0xff; + cdrom[id].current_cdb[2] = (cdrom[id].sector_pos >> 8) & 0xff; + cdrom[id].current_cdb[3] = cdrom[id].sector_pos & 0xff; + break; + + case GPCMD_READ_10: + cdrom[id].current_cdb[2] = (cdrom[id].sector_pos >> 24) & 0xff; + cdrom[id].current_cdb[3] = (cdrom[id].sector_pos >> 16) & 0xff; + cdrom[id].current_cdb[4] = (cdrom[id].sector_pos >> 8) & 0xff; + cdrom[id].current_cdb[5] = cdrom[id].sector_pos & 0xff; + cdrom[id].current_cdb[7] = (cdrom[id].requested_blocks >> 8) & 0xff; + cdrom[id].current_cdb[8] = cdrom[id].requested_blocks & 0xff; + break; + + case GPCMD_READ_12: + cdrom[id].current_cdb[2] = (cdrom[id].sector_pos >> 24) & 0xff; + cdrom[id].current_cdb[3] = (cdrom[id].sector_pos >> 16) & 0xff; + cdrom[id].current_cdb[4] = (cdrom[id].sector_pos >> 8) & 0xff; + cdrom[id].current_cdb[5] = cdrom[id].sector_pos & 0xff; + cdrom[id].current_cdb[6] = (cdrom[id].requested_blocks >> 24) & 0xff; + cdrom[id].current_cdb[7] = (cdrom[id].requested_blocks >> 16) & 0xff; + cdrom[id].current_cdb[8] = (cdrom[id].requested_blocks >> 8) & 0xff; + cdrom[id].current_cdb[9] = cdrom[id].requested_blocks & 0xff; + break; + + case GPCMD_READ_CD_MSF: + temp = cdrom_lba_to_msf_accurate(cdrom[id].sector_pos); + cdrom[id].current_cdb[3] = (temp >> 16) & 0xff; + cdrom[id].current_cdb[4] = (temp >> 8) & 0xff; + cdrom[id].current_cdb[5] = temp & 0xff; + + temp = cdrom_lba_to_msf_accurate(cdrom[id].sector_pos + cdrom[id].requested_blocks - 1); + cdrom[id].current_cdb[6] = (temp >> 16) & 0xff; + cdrom[id].current_cdb[7] = (temp >> 8) & 0xff; + cdrom[id].current_cdb[8] = temp & 0xff; + break; + + case GPCMD_READ_CD: + cdrom[id].current_cdb[2] = (cdrom[id].sector_pos >> 24) & 0xff; + cdrom[id].current_cdb[3] = (cdrom[id].sector_pos >> 16) & 0xff; + cdrom[id].current_cdb[4] = (cdrom[id].sector_pos >> 8) & 0xff; + cdrom[id].current_cdb[5] = cdrom[id].sector_pos & 0xff; + cdrom[id].current_cdb[6] = (cdrom[id].requested_blocks >> 16) & 0xff; + cdrom[id].current_cdb[7] = (cdrom[id].requested_blocks >> 8) & 0xff; + cdrom[id].current_cdb[8] = cdrom[id].requested_blocks & 0xff; + break; + } +} + +int cdrom_read_data(uint8_t id, int msf, int type, int flags, int *len) +{ + uint8_t *cdbufferb = (uint8_t *) cdrom[id].buffer; + + int ret = 0; + int cdsize = 0; + + int i = 0; + + if (cdrom_drives[id].handler->pass_through) + { + cdsize = cdrom_drives[id].handler->size(id); + + ret = cdrom_pass_through(id, len); + cdrom[id].data_pos += *len; + + if (!ret) + { + return 0; + } + + if (cdrom[id].sector_pos > (cdsize - 1)) + { + // cdrom_log("CD-ROM %i: Trying to read beyond the end of disc\n", id); + cdrom_lba_out_of_range(id); + return 0; + } + + cdrom[id].old_len = *len; + } + else + { + if (cdrom[id].sector_pos > (cdrom_drives[id].handler->size(id) - 1)) + { + // cdrom_log("CD-ROM %i: Trying to read beyond the end of disc\n", id); + cdrom_lba_out_of_range(id); + return 0; + } + + cdrom[id].old_len = 0; + + for (i = 0; i < cdrom[id].requested_blocks; i++) + { + ret = cdrom_drives[id].handler->readsector_raw(id, cdbufferb + cdrom[id].data_pos, cdrom[id].sector_pos, msf, type, flags, len); + + cdrom[id].data_pos += *len; + cdrom[id].old_len += *len; + + if (!ret) + { + cdrom_illegal_mode(id); + return 0; + } + } + + cdrom_log("CD-ROM %i: Data from raw sector read: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[cdrom[id].data_pos + 0], cdbufferb[cdrom[id].data_pos + 1], cdbufferb[cdrom[id].data_pos + 2], cdbufferb[cdrom[id].data_pos + 3], cdbufferb[cdrom[id].data_pos + 4], cdbufferb[cdrom[id].data_pos + 5], cdbufferb[cdrom[id].data_pos + 6], cdbufferb[cdrom[id].data_pos + 7]); + } + + return 1; +} + +int cdrom_read_blocks(uint8_t id, int *len, int first_batch) +{ + int i = 0; + int ret = 0; + + int msf = 0; + + int type = 0; + int flags = 0; + + if (cdrom[id].current_cdb[0] == 0xb9) + { + msf = 1; + } + + if ((cdrom[id].current_cdb[0] == 0xb9) || (cdrom[id].current_cdb[0] == 0xbe)) + { + type = (cdrom[id].current_cdb[1] >> 2) & 7; + flags = cdrom[id].current_cdb[9] || (((uint32_t) cdrom[id].current_cdb[10]) << 8); + } + else + { + type = 2; + flags = 0x10; + } + + cdrom[id].data_pos = 0; + + if (!cdrom[id].sector_len) + { + cdrom_command_complete(id); + return 0; + } + + cdrom_log("Reading %i blocks starting from %i...\n", cdrom[id].requested_blocks, cdrom[id].sector_pos); + + cdrom_update_cdb(id); + + ret = cdrom_read_data(id, msf, type, flags, len); + + cdrom_log("Read %i bytes of blocks...\n", *len); + + if (!ret || ((cdrom[id].old_len != *len) && !first_batch)) + { + if ((cdrom[id].old_len != *len) && !first_batch) + { + cdrom_illegal_mode(id); + } + + return 0; + } + + cdrom[id].sector_pos += cdrom[id].requested_blocks; + cdrom[id].sector_len -= cdrom[id].requested_blocks; + + return 1; +} + +/*SCSI Get Configuration*/ +uint8_t cdrom_set_profile(uint8_t *buf, uint8_t *index, uint16_t profile) +{ + uint8_t *buf_profile = buf + 12; /* start of profiles */ + + buf_profile += ((*index) * 4); /* start of indexed profile */ + buf_profile[0] = (profile >> 8) & 0xff; + buf_profile[1] = profile & 0xff; + buf_profile[2] = ((buf_profile[0] == buf[6]) && (buf_profile[1] == buf[7])); + + /* each profile adds 4 bytes to the response */ + (*index)++; + buf[11] += 4; /* Additional Length */ + + return 4; +} + +/*SCSI Read DVD Structure*/ +static int cdrom_read_dvd_structure(uint8_t id, int format, const uint8_t *packet, uint8_t *buf) +{ + int layer = packet[6]; + uint64_t total_sectors; + + switch (format) + { + case 0x00: /* Physical format information */ + total_sectors = (uint64_t) cdrom_drives[id].handler->size(id); + + if (layer != 0) + { + cdrom_invalid_field(id); + return 0; + } + + total_sectors >>= 2; + if (total_sectors == 0) + { + // return -ASC_MEDIUM_NOT_PRESENT; + cdrom_not_ready(id); + return 0; + } + + buf[4] = 1; /* DVD-ROM, part version 1 */ + buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ + buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ + buf[7] = 0; /* default densities */ + + /* FIXME: 0x30000 per spec? */ + buf[8] = buf[9] = buf[10] = buf[11] = 0; /* start sector */ + buf[12] = (total_sectors >> 24) & 0xff; /* end sector */ + buf[13] = (total_sectors >> 16) & 0xff; + buf[14] = (total_sectors >> 8) & 0xff; + buf[15] = total_sectors & 0xff; + + buf[16] = (total_sectors >> 24) & 0xff; /* l0 end sector */ + buf[17] = (total_sectors >> 16) & 0xff; + buf[18] = (total_sectors >> 8) & 0xff; + buf[19] = total_sectors & 0xff; + + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((2048 +2 ) >> 8) & 0xff; + buf[1] = (2048 + 2) & 0xff; + + /* 2k data + 4 byte header */ + return (2048 + 4); + + case 0x01: /* DVD copyright information */ + buf[4] = 0; /* no copyright data */ + buf[5] = 0; /* no region restrictions */ + + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((4 + 2) >> 8) & 0xff; + buf[1] = (4 + 2) & 0xff; + + /* 4 byte header + 4 byte data */ + return (4 + 4); + + case 0x03: /* BCA information - invalid field for no BCA info */ + cdrom_invalid_field(id); + return 0; + + case 0x04: /* DVD disc manufacturing information */ + /* Size of buffer, not including 2 byte size field */ + buf[0] = ((2048 + 2) >> 8) & 0xff; + buf[1] = (2048 + 2) & 0xff; + + /* 2k data + 4 byte header */ + return (2048 + 4); + + case 0xff: + /* + * This lists all the command capabilities above. Add new ones + * in order and update the length and buffer return values. + */ + + buf[4] = 0x00; /* Physical format */ + buf[5] = 0x40; /* Not writable, is readable */ + buf[6] = ((2048 + 4) >> 8) & 0xff; + buf[7] = (2048 + 4) & 0xff; + + buf[8] = 0x01; /* Copyright info */ + buf[9] = 0x40; /* Not writable, is readable */ + buf[10] = ((4 + 4) >> 8) & 0xff; + buf[11] = (4 + 4) & 0xff; + + buf[12] = 0x03; /* BCA info */ + buf[13] = 0x40; /* Not writable, is readable */ + buf[14] = ((188 + 4) >> 8) & 0xff; + buf[15] = (188 + 4) & 0xff; + + buf[16] = 0x04; /* Manufacturing info */ + buf[17] = 0x40; /* Not writable, is readable */ + buf[18] = ((2048 + 4) >> 8) & 0xff; + buf[19] = (2048 + 4) & 0xff; + + /* Size of buffer, not including 2 byte size field */ + buf[6] = ((16 + 2) >> 8) & 0xff; + buf[7] = (16 + 2) & 0xff; + + /* data written + 4 byte header */ + return (16 + 4); + + default: /* TODO: formats beyond DVD-ROM requires */ + cdrom_invalid_field(id); + return 0; + } +} + +/*SCSI Get Event Status Notification*/ +static uint32_t cdrom_get_event_status(uint8_t id, uint8_t *buffer) +{ + uint8_t event_code, media_status = 0; + + if (buffer[5]) + { + media_status = MS_TRAY_OPEN; + if (cdrom_drives[id].handler->stop) + { + cdrom_drives[id].handler->stop(id); + } + } + else + { + media_status = MS_MEDIA_PRESENT; + } + + event_code = MEC_NO_CHANGE; + if (media_status != MS_TRAY_OPEN) + { + if (!buffer[4]) + { + event_code = MEC_NEW_MEDIA; + cdrom_drives[id].handler->load(id); + } + else if (buffer[4]==2) + { + event_code = MEC_EJECT_REQUESTED; + cdrom_drives[id].handler->eject(id); + } + } + + buffer[4] = event_code; + buffer[5] = media_status; + buffer[6] = 0; + buffer[7] = 0; + + return 8; +} + +void cdrom_insert(uint8_t id) +{ + cdrom[id].unit_attention = 1; +} + +/*SCSI Sense Initialization*/ +void cdrom_sense_code_ok(uint8_t id) +{ + cdrom_sense_key = SENSE_NONE; + cdrom_asc = 0; + cdrom_ascq = 0; +} + +int cdrom_pre_execution_check(uint8_t id, uint8_t *cdb) +{ + int ready = 0; + + if (!(cdrom_command_flags[cdb[0]] & IMPLEMENTED)) + { + cdrom_log("CD-ROM %i: Attempting to unknown command %02X over %s\n", id, cdb[0], cdrom_drives[id].bus_type ? "SCSI" : "ATAPI"); + cdrom_illegal_opcode(id); + return 0; + } + + if (!cdrom_drives[id].bus_type && (cdrom_command_flags[cdb[0]] & SCSI_ONLY)) + { + cdrom_log("CD-ROM %i: Attempting to execute SCSI-only command %02X over ATAPI\n", id, cdb[0]); + cdrom_illegal_opcode(id); + return 0; + } + + if (cdrom_drives[id].bus_type && (cdrom_command_flags[cdb[0]] & ATAPI_ONLY)) + { + cdrom_log("CD-ROM %i: Attempting to execute ATAPI-only command %02X over SCSI\n", id, cdb[0]); + cdrom_illegal_opcode(id); + return 0; + } + + if (cdrom_drives[id].handler->medium_changed(id)) + { + // cdrom_log("CD-ROM %i: Medium has changed...\n", id); + cdrom_insert(id); + } + + ready = cdrom_drives[id].handler->ready(id); + + if (!ready && cdrom[id].unit_attention) + { + /* If the drive is not ready, there is no reason to keep the + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ + cdrom[id].unit_attention = 0; + } + + /* If the UNIT ATTENTION condition is set and the command does not allow + execution under it, error out and report the condition. */ + if (cdrom[id].unit_attention == 1) + { + // cdrom_log("CD-ROM %i: Unit attention now 2\n", id); + cdrom[id].unit_attention = 2; + if (!(cdrom_command_flags[cdb[0]] & ALLOW_UA)) + { + cdrom_log("CD-ROM %i: UNIT ATTENTION: Command %02X not allowed to pass through\n", id, cdb[0]); + cdrom_unit_attention(id); + return 0; + } + } + else if (cdrom[id].unit_attention == 2) + { + if (cdb[0] != GPCMD_REQUEST_SENSE) + { + // cdrom_log("CD-ROM %i: Unit attention now 0\n", id); + cdrom[id].unit_attention = 0; + } + } + + /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* + the UNIT ATTENTION condition if it's set. */ + if (cdb[0] != GPCMD_REQUEST_SENSE) + { + cdrom_sense_clear(id, cdb[0], 1); + } + + /* Next it's time for NOT READY. */ + if ((cdrom_command_flags[cdb[0]] & CHECK_READY) && !ready) + { + cdrom_log("CD-ROM %i: Not ready (%02X)\n", id, cdb[0]); + cdrom_not_ready(id); + return 0; + } + + cdrom_log("CD-ROM %i: Continuing with command\n", id); + + return 1; +} + +void cdrom_clear_callback(uint8_t channel) +{ + uint8_t id = atapi_cdrom_drives[channel]; + + if (id <= CDROM_NUM) + { + cdrom[id].callback = 0; + } +} + +static void cdrom_seek(uint8_t id, uint32_t pos) +{ + // cdrom_log("CD-ROM %i: Seek %08X\n", id, pos); + cdrom[id].seek_pos = pos; + if (cdrom_drives[id].handler->stop) + { + cdrom_drives[id].handler->stop(id); + } +} + +static void cdrom_rezero(uint8_t id) +{ + if (cdrom_drives[id].handler->stop) + { + cdrom_drives[id].handler->stop(id); + } + cdrom[id].sector_pos = cdrom[id].sector_len = 0; + cdrom_seek(id, 0); +} + +void cdrom_reset(uint8_t id) +{ + cdrom_rezero(id); + cdrom[id].status = 0; + cdrom[id].callback = 0; + cdrom[id].packet_status = 0xff; + cdrom[id].unit_attention = 0; +} + +void cdrom_command(uint8_t id, uint8_t *cdb) +{ + uint8_t *cdbufferb = (uint8_t *) cdrom[id].buffer; + uint8_t rcdmode = 0; + int c; + int len; + int msf; + int pos=0; + unsigned char temp; + uint32_t size; + uint8_t page_code; + int max_len; + int used_len; + unsigned idx = 0; + unsigned size_idx; + unsigned preamble_len; + int toc_format; + int temp_command; + int alloc_length; + int completed; + uint8_t index = 0; + int media; + int format; + int ret; + int real_pos; + int track = 0; + int ready = 0; + uint8_t device_identify[8] = { '8', '6', 'B', '_', 'C', 'D', '0', 0 }; + uint8_t device_identify_ex[14] = { '8', '6', 'B', '_', 'C', 'D', '0', ' ', 'v', '1', '.', '0', '0', 0 }; + + if (cdrom_drives[id].bus_type) + { + cdrom[id].status &= ~ERR_STAT; + } + + cdrom[id].packet_len = 0; + cdrom[id].request_pos = 0; + + device_identify[6] = id + 0x30; + + device_identify_ex[6] = id + 0x30; + device_identify_ex[9] = emulator_version[0]; + device_identify_ex[11] = emulator_version[2]; + device_identify_ex[12] = emulator_version[3]; + + cdrom[id].data_pos = 0; + + memcpy(cdrom[id].current_cdb, cdb, cdrom[id].cdb_len); + + cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n", id, cdb[0], cdrom_sense_key, cdrom_asc, cdrom_ascq, ins, cdrom[id].unit_attention); + cdrom_log("CD-ROM %i: Request length: %04X\n", id, cdrom[id].request_length); +#if 0 + + int CdbLength; + for (CdbLength = 1; CdbLength < cdrom[id].cdb_len; CdbLength++) + { + cdrom_log("CD-ROM %i: CDB[%d] = 0x%02X\n", id, CdbLength, cdb[CdbLength]); + } +#endif + + msf = cdb[1] & 2; + cdrom[id].sector_len = 0; + + /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ + if (cdrom_drives[id].check_on_execution) + { + if (cdrom_pre_execution_check(id, cdb) == 0) + { + return; + } + } + + cdrom[id].prev_status = cdrom[id].cd_status; + cdrom[id].cd_status = cdrom_drives[id].handler->status(id); + if (((cdrom[id].prev_status == CD_STATUS_PLAYING) || (cdrom[id].prev_status == CD_STATUS_PAUSED)) && ((cdrom[id].cd_status != CD_STATUS_PLAYING) && (cdrom[id].cd_status != CD_STATUS_PAUSED))) + { + completed = 1; + } + else + { + completed = 0; + } + + switch (cdb[0]) + { + case GPCMD_TEST_UNIT_READY: + cdrom_command_complete(id); + break; + + case GPCMD_REZERO_UNIT: + if (cdrom_drives[id].handler->stop) + { + cdrom_drives[id].handler->stop(id); + } + cdrom[id].sector_pos = cdrom[id].sector_len = 0; + cdrom_seek(id, 0); + break; + + case GPCMD_REQUEST_SENSE: /* Used by ROS 4+ */ + alloc_length = cdb[4]; + temp_command = cdb[0]; + + /*Will return 18 bytes of 0*/ + if (alloc_length != 0) + { + memset(cdbufferb, 0, alloc_length); + memcpy(cdbufferb, cdrom[id].sense, alloc_length); + } + + cdbufferb[0] = 0x70; + + if ((cdrom_sense_key > 0) && ((cdrom[id].cd_status < CD_STATUS_PLAYING) || (cdrom[id].cd_status == CD_STATUS_STOPPED)) && completed) + { + cdbufferb[2]=SENSE_ILLEGAL_REQUEST; + cdbufferb[12]=ASC_AUDIO_PLAY_OPERATION; + cdbufferb[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; + } + else if ((cdrom_sense_key == 0) && (cdrom[id].cd_status >= CD_STATUS_PLAYING) && (cdrom[id].cd_status != CD_STATUS_STOPPED)) + { + cdbufferb[2]=SENSE_ILLEGAL_REQUEST; + cdbufferb[12]=ASC_AUDIO_PLAY_OPERATION; + cdbufferb[13]=(cdrom[id].cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; + } + else + { + if (cdrom[id].unit_attention) + { + cdbufferb[2]=SENSE_UNIT_ATTENTION; + cdbufferb[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; + cdbufferb[13]=0; + } + } + + // cdrom_log("CD-ROM %i: Reporting sense: %02X %02X %02X\n", id, cdbufferb[2], cdbufferb[12], cdbufferb[13]); + + if (cdbufferb[2] == SENSE_UNIT_ATTENTION) + { + /* If the last remaining sense is unit attention, clear + that condition. */ + cdrom[id].unit_attention = 0; + } + + /* Clear the sense stuff as per the spec. */ + cdrom_sense_clear(id, temp_command, 0); + + cdrom_data_command_finish(id, 18, 18, alloc_length, 0); + break; + + case GPCMD_SET_SPEED: + case GPCMD_SET_SPEED_ALT: + cdrom_command_complete(id); + break; + + case GPCMD_MECHANISM_STATUS: + len = (cdbufferb[7] << 16) | (cdbufferb[8] << 8) | cdbufferb[9]; + + memset(cdbufferb, 0, 8); + cdbufferb[5] = 1; + + cdrom_data_command_finish(id, 8, 8, len, 0); + break; + + case GPCMD_READ_TOC_PMA_ATIP: + cdrom[id].toctimes++; + + if (cdrom_drives[id].handler->pass_through) + { + ret = cdrom_pass_through(id, &len); + if (!ret) + { + return; + } + } + else + { + toc_format = cdb[2] & 0xf; + + if (toc_format == 0) + { + toc_format = (cdb[9] >> 6) & 3; + } + + len = cdb[8] + (cdb[7] << 8); + + switch (toc_format) + { + case 0: /*Normal*/ + len = cdrom_drives[id].handler->readtoc(id, cdbufferb, cdb[6], msf, len, 0); + break; + case 1: /*Multi session*/ + len = cdrom_drives[id].handler->readtoc_session(id, cdbufferb, msf, len); + cdbufferb[0] = 0; cdbufferb[1] = 0xA; + break; + case 2: /*Raw*/ + len = cdrom_drives[id].handler->readtoc_raw(id, cdbufferb, msf, len); + break; + default: + cdrom_invalid_field(id); + return; + } + } + + cdrom_data_command_finish(id, len, len, len, 0); + // cdrom_log("CD-ROM %i: READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", id, toc_format, ide->cylinder, cdbufferb[1]); + return; + + case GPCMD_READ_CD_OLD: + cdrom[id].current_cdb[0] = 0xbe; /* IMPORTANT: Convert the command to new read CD for pass through purposes. */ + case GPCMD_READ_6: + case GPCMD_READ_10: + case GPCMD_READ_12: + case GPCMD_READ_CD: + case GPCMD_READ_CD_MSF: + switch(cdb[0]) + { + case GPCMD_READ_6: + cdrom[id].sector_len = cdb[4]; + cdrom[id].sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + msf = 0; + break; + case GPCMD_READ_10: + cdrom[id].sector_len = (cdb[7] << 8) | cdb[8]; + cdrom[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + cdrom_log("CD-ROM %i: Length: %i, LBA: %i\n", id, cdrom[id].sector_len, cdrom[id].sector_pos); + msf = 0; + break; + case GPCMD_READ_12: + cdrom[id].sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + cdrom[id].sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + msf = 0; + break; + case GPCMD_READ_CD_MSF: + // cdrom_log("CD-ROM %i: Read CD MSF: Start MSF %02X%02X%02X End MSF %02X%02X%02X Flags %02X\n", id, cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]); + cdrom[id].sector_len = MSFtoLBA(cdb[6], cdb[7], cdb[8]); + cdrom[id].sector_pos = MSFtoLBA(cdb[3], cdb[4], cdb[5]); + + cdrom[id].sector_len -= cdrom[id].sector_pos; + cdrom[id].sector_len++; + msf = 1; + break; + case GPCMD_READ_CD_OLD: + case GPCMD_READ_CD: + // cdrom_log("CD-ROM %i: Read CD: Start LBA %02X%02X%02X%02X Length %02X%02X%02X Flags %02X\n", id, cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]); + cdrom[id].sector_len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; + cdrom[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + + msf = 0; + break; + } + + if (!cdrom[id].sector_len) + { + // cdrom_log("CD-ROM %i: All done - callback set\n", id); + cdrom[id].packet_status = CDROM_PHASE_COMPLETE; + cdrom[id].callback = 20 * CDROM_TIME; + break; + } + + max_len = cdrom[id].sector_len; + if (cdrom_drives[id].bus_type) + { + cdrom[id].requested_blocks = max_len; + } + else + { + cdrom[id].requested_blocks = 1; + } + + ret = cdrom_read_blocks(id, &alloc_length, 1); + if (!ret) + { + return; + } + + cdrom[id].packet_len = max_len * alloc_length; + cdrom_data_command_finish(id, alloc_length * cdrom[id].requested_blocks, alloc_length, alloc_length * cdrom[id].requested_blocks, 0); + cdrom[id].all_blocks_total = cdrom[id].block_total; + if (cdrom[id].packet_status != CDROM_PHASE_COMPLETE) + { + readflash=1; + } + return; + + case GPCMD_READ_HEADER: + if (cdrom_drives[id].handler->pass_through) + { + ret = cdrom_pass_through(id, &len); + if (!ret) + { + return; + } + } + else + { + cdrom[id].sector_len = (cdb[7] << 8) | cdb[8]; + cdrom[id].sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4]<<8) | cdb[5]; + if (msf) + { + real_pos = cdrom_lba_to_msf_accurate(cdrom[id].sector_pos); + } + else + { + real_pos = cdrom[id].sector_pos; + } + cdbufferb[0] = 1; /*2048 bytes user data*/ + cdbufferb[1] = cdbufferb[2] = cdbufferb[3] = 0; + cdbufferb[4] = (real_pos >> 24); + cdbufferb[5] = ((real_pos >> 16) & 0xff); + cdbufferb[6] = ((real_pos >> 8) & 0xff); + cdbufferb[7] = real_pos & 0xff; + + len = 8; + } + + cdrom_data_command_finish(id, len, len, len, 0); + return; + + case GPCMD_MODE_SENSE_6: + case GPCMD_MODE_SENSE_10: + if (cdb[0] == GPCMD_MODE_SENSE_6) + { + len = cdb[4]; + } + else + { + len = (cdb[8] | (cdb[7] << 8)); + } + + if (!(cdrom_mode_sense_page_flags[id][cdb[2] & 0x3F] & IMPLEMENTED)) + { + cdrom_invalid_field(id); + return; + } + + memset(cdbufferb, 0, len); + alloc_length = len; + + if (cdb[0] == GPCMD_MODE_SENSE_6) + { + len = cdrom_mode_sense(id, cdbufferb, 4, cdb[2]); + cdbufferb[0] = len - 1; + cdbufferb[1] = 3; /*120mm data CD-ROM*/ + if (len > alloc_length) + { + len = alloc_length; + } + } + else + { + len = cdrom_mode_sense(id, cdbufferb, 8, cdb[2]); + if (len > alloc_length) + { + len = alloc_length; + } + cdbufferb[0]=(len - 2) >> 8; + cdbufferb[1]=(len - 2) & 255; + cdbufferb[2] = 3; /*120mm data CD-ROM*/ + if (len > alloc_length) + { + len = alloc_length; + } + } + + cdrom_log("CD-ROM %i: Reading mode page: %02X...\n", id, cdb[2]); + + cdrom_data_command_finish(id, len, len, alloc_length, 0); + return; + + case GPCMD_MODE_SELECT_6: + case GPCMD_MODE_SELECT_10: + if (cdb[0] == GPCMD_MODE_SELECT_6) + { + len = cdb[4]; + } + else + { + len = (cdb[7] << 8) | cdb[8]; + } + + ret = cdrom_mode_select_init(id, cdb[0], len, cdb[1] & 1); + + cdrom_data_command_finish(id, len, len, len, 1); + return; + + case GPCMD_GET_CONFIGURATION: + temp_command = cdb[0]; + /* XXX: could result in alignment problems in some architectures */ + len = (cdb[7] << 8) | cdb[8]; + alloc_length = len; + + index = 0; + + /* only feature 0 is supported */ + if (cdb[2] != 0 || cdb[3] != 0) + { + cdrom_invalid_field(id); + return; + } + + /* + * XXX: avoid overflow for io_buffer if len is bigger than + * the size of that buffer (dimensioned to max number of + * sectors to transfer at once) + * + * Only a problem if the feature/profiles grow. + */ + if (alloc_length > 512) /* XXX: assume 1 sector */ + { + alloc_length = 512; + } + + memset(cdbufferb, 0, alloc_length); + /* + * the number of sectors from the media tells us which profile + * to use as current. 0 means there is no media + */ + if (len > CD_MAX_SECTORS) + { + cdbufferb[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; + cdbufferb[7] = MMC_PROFILE_DVD_ROM & 0xff; + } + else if (len <= CD_MAX_SECTORS) + { + cdbufferb[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; + cdbufferb[7] = MMC_PROFILE_CD_ROM & 0xff; + } + cdbufferb[10] = 0x02 | 0x01; /* persistent and current */ + alloc_length = 12; /* headers: 8 + 4 */ + alloc_length += cdrom_set_profile(cdbufferb, &index, MMC_PROFILE_DVD_ROM); + alloc_length += cdrom_set_profile(cdbufferb, &index, MMC_PROFILE_CD_ROM); + cdbufferb[0] = ((alloc_length - 4) >> 24) & 0xff; + cdbufferb[1] = ((alloc_length - 4) >> 16) & 0xff; + cdbufferb[2] = ((alloc_length - 4) >> 8) & 0xff; + cdbufferb[3] = (alloc_length - 4) & 0xff; + + cdrom_data_command_finish(id, len, len, alloc_length, 0); + break; + + case GPCMD_GET_EVENT_STATUS_NOTIFICATION: + gesn_cdb = (void *) cdb; + gesn_event_header = (void *) cdbufferb; + + /* It is fine by the MMC spec to not support async mode operations. */ + if (!(gesn_cdb->polled & 0x01)) + { + /* asynchronous mode */ + /* Only polling is supported, asynchronous mode is not. */ + cdrom_invalid_field(id); + return; + } + + /* polling mode operation */ + + /* + * These are the supported events. + * + * We currently only support requests of the 'media' type. + * Notification class requests and supported event classes are bitmasks, + * but they are built from the same values as the "notification class" + * field. + */ + gesn_event_header->supported_events = 1 << GESN_MEDIA; + + /* + * We use |= below to set the class field; other bits in this byte + * are reserved now but this is useful to do if we have to use the + * reserved fields later. + */ + gesn_event_header->notification_class = 0; + + /* + * Responses to requests are to be based on request priority. The + * notification_class_request_type enum above specifies the + * priority: upper elements are higher prio than lower ones. + */ + if (gesn_cdb->class & (1 << GESN_MEDIA)) + { + gesn_event_header->notification_class |= GESN_MEDIA; + used_len = cdrom_get_event_status(id, cdbufferb); + } + else + { + gesn_event_header->notification_class = 0x80; /* No event available */ + used_len = sizeof(*gesn_event_header); + } + gesn_event_header->len = used_len - sizeof(*gesn_event_header); + + cdrom_data_command_finish(id, used_len, used_len, used_len, 0); + break; + + case GPCMD_READ_DISC_INFORMATION: + if (cdrom_drives[id].handler->pass_through) + { + ret = cdrom_pass_through(id, &len); + if (!ret) + { + return; + } + } + else + { + memset(cdbufferb, 0, 34); + memset(cdbufferb, 1, 9); + cdbufferb[0] = 0; + cdbufferb[1] = 32; + cdbufferb[2] = 0xe; /* last session complete, disc finalized */ + cdbufferb[7] = 0x20; /* unrestricted use */ + cdbufferb[8] = 0x00; /* CD-ROM */ + + len=34; + } + + cdrom_data_command_finish(id, len, len, alloc_length, 0); + break; + + case GPCMD_READ_TRACK_INFORMATION: + max_len = cdb[7]; + max_len <<= 8; + max_len |= cdb[8]; + + track = ((uint32_t) cdb[2]) << 24; + track |= ((uint32_t) cdb[3]) << 16; + track |= ((uint32_t) cdb[4]) << 8; + track |= (uint32_t) cdb[5]; + + if (cdrom_drives[id].handler->pass_through) + { + ret = cdrom_pass_through(id, &len); + if (!ret) + { + return; + } + } + else + { + if (((cdb[1] & 0x03) != 1) || (track != 1)) + { + cdrom_invalid_field(id); + return; + } + + len = 36; + + memset(cdbufferb, 0, 36); + cdbufferb[1] = 34; + cdbufferb[2] = 1; /* track number (LSB) */ + cdbufferb[3] = 1; /* session number (LSB) */ + cdbufferb[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ + cdbufferb[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ + cdbufferb[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ + cdbufferb[24] = (cdrom_drives[id].handler->size(id) >> 24) & 0xff; /* track size */ + cdbufferb[25] = (cdrom_drives[id].handler->size(id) >> 16) & 0xff; /* track size */ + cdbufferb[26] = (cdrom_drives[id].handler->size(id) >> 8) & 0xff; /* track size */ + cdbufferb[27] = cdrom_drives[id].handler->size(id) & 0xff; /* track size */ + + if (len > max_len) + { + len = max_len; + cdbufferb[0] = ((max_len - 2) >> 8) & 0xff; + cdbufferb[1] = (max_len - 2) & 0xff; + } + } + + cdrom_data_command_finish(id, len, len, alloc_length, 0); + break; + + case GPCMD_PLAY_AUDIO_10: + case GPCMD_PLAY_AUDIO_12: + case GPCMD_PLAY_AUDIO_MSF: + case GPCMD_PLAY_AUDIO_TRACK_INDEX: + switch(cdb[0]) + { + case GPCMD_PLAY_AUDIO_10: + msf = 0; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_PLAY_AUDIO_12: + msf = 0; + pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; + break; + case GPCMD_PLAY_AUDIO_MSF: + /* This is apparently deprecated in the ATAPI spec, and apparently + has been since 1995 (!). Hence I'm having to guess most of it. */ + msf = 1; + pos = (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; + len = (cdb[6] << 16) | (cdb[7] << 8) | cdb[8]; + break; + case GPCMD_PLAY_AUDIO_TRACK_INDEX: + msf = 2; + pos = (cdb[4] << 8) | cdb[5]; + len = (cdb[7] << 8) | cdb[8]; + break; + } + + if ((cdrom_drive < 1) || (cdrom_drive == CDROM_ISO) || (cdrom[id].cd_status <= CD_STATUS_DATA_ONLY) || + !cdrom_drives[id].handler->is_track_audio(id, pos, msf)) + { + cdrom_illegal_mode(id); + break; + } + + if (cdrom_drives[id].handler->playaudio) + { + cdrom_drives[id].handler->playaudio(id, pos, len, msf); + } + else + { + cdrom_illegal_mode(id); + break; + } + + cdrom_command_complete(id); + break; + + case GPCMD_READ_SUBCHANNEL: + cdrom_log("CD-ROM %i: Getting page %i\n", id, cdb[3]); + if (cdrom_drives[id].handler->pass_through) + { + ret = cdrom_pass_through(id, &len); + if (!ret) + { + return; + } + cdrom_log("CD-ROM %i: Audio status: %i\n", id, temp); + switch(cdrom[id].cd_status) + { + case CD_STATUS_PLAYING: + cdbufferb[1] = 0x11; + break; + case CD_STATUS_PAUSED: + cdbufferb[1] = 0x12; + break; + default: + if (completed) + { + cdbufferb[1] = 0x13; + } + else + { + cdbufferb[1] = 0x15; + } + break; + } + } + else + { + if (cdb[3] > 3) + { + // cdrom_log("CD-ROM %i: Read subchannel check condition %02X\n", id, cdb[3]); + cdrom_invalid_field(id); + return; + } + + switch(cdb[3]) + { + case 0: + alloc_length = 4; + break; + case 1: + alloc_length = 16; + break; + default: + alloc_length = 24; + break; + } + + memset(cdbufferb, 24, 0); + pos = 0; + cdbufferb[pos++] = 0; + cdbufferb[pos++] = 0; /*Audio status*/ + cdbufferb[pos++] = 0; cdbufferb[pos++] = 0; /*Subchannel length*/ + cdbufferb[pos++] = cdb[3] & 3; /*Format code*/ + if ((temp & 3) == 1) + { + cdbufferb[1] = cdrom_drives[id].handler->getcurrentsubchannel(id, &cdbufferb[5], msf); + if (((cdbufferb[1] == 0x13) && !completed) || (cd_status == CD_STATUS_DATA_ONLY)) + { + cdbufferb[1] = 0x15; + } + } + if (!(cdb[2] & 0x40) || ((cdb[3] & 3) == 0)) + { + len = 4; + } + else + { + len = alloc_length; + } + } + + cdrom_data_command_finish(id, len, len, len, 0); + break; + + case GPCMD_READ_DVD_STRUCTURE: + if (cdrom_drives[id].handler->pass_through) + { + ret = cdrom_pass_through(id, &len); + if (!ret) + { + return; + } + } + else + { + len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + alloc_length = len; + + if (cdb[7] < 0xff) + { + if (len <= CD_MAX_SECTORS) + { + cdrom_incompatible_format(id); + return; + } + else + { + cdrom_invalid_field(id); + return; + } + } + + memset(cdbufferb, 0, (alloc_length > 256 * 512 + 4) ? (256 * 512 + 4) : alloc_length); + + switch (cdb[7]) + { + case 0x00 ... 0x7f: + case 0xff: + if (cdb[1] == 0) + { + ret = cdrom_read_dvd_structure(id, format, cdb, cdbufferb); + + /* if (!ret) + { + cdrom_cmd_error(id, SENSE_ILLEGAL_REQUEST, -ret, 0); + } + else */ + if (ret) + { + cdrom_data_command_finish(id, len, len, alloc_length, 0); + } + return; + } + /* TODO: BD support, fall through for now */ + + /* Generic disk structures */ + case 0x80: /* TODO: AACS volume identifier */ + case 0x81: /* TODO: AACS media serial number */ + case 0x82: /* TODO: AACS media identifier */ + case 0x83: /* TODO: AACS media key block */ + case 0x90: /* TODO: List of recognized format layers */ + case 0xc0: /* TODO: Write protection status */ + default: + cdrom_invalid_field(id); + return; + } + } + break; + + case GPCMD_START_STOP_UNIT: + switch(cdbufferb[4] & 3) + { + case 0: /* Stop the disc. */ + if (cdrom_drives[id].handler->stop) + { + cdrom_drives[id].handler->stop(id); + } + break; + case 1: /* Start the disc and read the TOC. */ + cdrom_drives[id].handler->medium_changed(id); /* This causes a TOC reload. */ + break; + case 2: /* Eject the disc if possible. */ + if (cdrom_drives[id].handler->stop) + { + cdrom_drives[id].handler->stop(id); + } +#ifndef __unix + win_cdrom_eject(id); +#endif + break; + case 3: /* Load the disc (close tray). */ +#ifndef __unix + win_cdrom_reload(id); +#else + cdrom_drives[id].handler->load(id); +#endif + break; + } + + cdrom_command_complete(id); + break; + + case GPCMD_INQUIRY: + if (cdb[1] & 1) + { + preamble_len = 4; + size_idx = 3; + + cdbufferb[idx++] = 05; + cdbufferb[idx++] = cdb[2]; + cdbufferb[idx++] = 0; + + idx++; + + switch (cdb[2]) + { + case 0x00: + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 0x83; + break; + case 0x83: + if (idx + 24 > max_len) + { + cdrom_data_phase_error(id); + return; + } + + cdbufferb[idx++] = 0x02; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 20; + ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Serial */ + idx += 20; + + if (idx + 72 > cdb[4]) + { + goto atapi_out; + } + cdbufferb[idx++] = 0x02; + cdbufferb[idx++] = 0x01; + cdbufferb[idx++] = 0x00; + cdbufferb[idx++] = 68; + ide_padstr8(cdbufferb + idx, 8, "86Box"); /* Vendor */ + idx += 8; + ide_padstr8(cdbufferb + idx, 40, device_identify_ex); /* Product */ + idx += 40; + ide_padstr8(cdbufferb + idx, 20, "53R141"); /* Product */ + idx += 20; + break; + default: + cdrom_log("INQUIRY: Invalid page: %02X\n", cdb[2]); + cdrom_invalid_field(id); + return; + } + } + else + { + preamble_len = 5; + size_idx = 4; + + memset(cdbufferb, 0, 8); + cdbufferb[0] = 5; /*CD-ROM*/ + cdbufferb[1] = 0x80; /*Removable*/ + cdbufferb[3] = 0x21; + cdbufferb[4] = 31; + + ide_padstr8(cdbufferb + 8, 8, "86Box"); /* Vendor */ + ide_padstr8(cdbufferb + 16, 16, device_identify); /* Product */ + ide_padstr8(cdbufferb + 32, 4, emulator_version); /* Revision */ + idx = 36; + } + +atapi_out: + cdbufferb[size_idx] = idx - preamble_len; + len=idx; + + cdrom_data_command_finish(id, len, len, cdb[4], 0); + break; + + case GPCMD_PREVENT_REMOVAL: + cdrom_command_complete(id); + break; + + case GPCMD_PAUSE_RESUME: + if (cdb[8] & 1) + { + if (cdrom_drives[id].handler->resume) + { + cdrom_drives[id].handler->resume(id); + } + else + { + cdrom_illegal_mode(id); + break; + } + } + else + { + if (cdrom_drives[id].handler->pause) + { + cdrom_drives[id].handler->pause(id); + } + else + { + cdrom_illegal_mode(id); + break; + } + } + cdrom_command_complete(id); + break; + + case GPCMD_SEEK_6: + case GPCMD_SEEK_10: + switch(cdb[0]) + { + case GPCMD_SEEK_6: + pos = (cdb[2] << 8) | cdb[3]; + break; + case GPCMD_SEEK_10: + pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; + break; + } + cdrom_seek(id, pos); + cdrom_command_complete(id); + break; + + case GPCMD_READ_CDROM_CAPACITY: + if (cdrom_drives[id].handler->pass_through) + { + ret = cdrom_pass_through(id, &len); + if (!ret) + { + return; + } + } + else + { + size = cdrom_drives[id].handler->size(id) - 1; /* IMPORTANT: What's returned is the last LBA block. */ + memset(cdbufferb, 0, 8); + cdbufferb[0] = (size >> 24) & 0xff; + cdbufferb[1] = (size >> 16) & 0xff; + cdbufferb[2] = (size >> 8) & 0xff; + cdbufferb[3] = size & 0xff; + cdbufferb[6] = 8; /* 2048 = 0x0800 */ + len = 8; + } + + cdrom_data_command_finish(id, len, len, len, 0); + break; + + case GPCMD_STOP_PLAY_SCAN: + if (cdrom_drives[id].handler->stop) + { + cdrom_drives[id].handler->stop(id); + } + else + { + cdrom_illegal_mode(id); + break; + } + cdrom_command_complete(id); + break; + + default: + cdrom_illegal_opcode(id); + break; + } + + // cdrom_log("CD-ROM %i: Phase: %02X, request length: %i\n", cdrom[id].phase, cdrom[id].request_length); +} + +/* This is for block reads. */ +int cdrom_block_check(uint8_t id) +{ + int alloc_length = 0; + int ret = 0; + + /* If this is a media access command, and we hit the end of the block but not the entire length, + read the next block. */ + if (cdrom_is_media_access(id)) + { + /* We have finished the current block. */ + cdrom_log("CD-ROM %i: %i bytes total read, %i bytes all total\n", cdrom[id].total_read, cdrom[id].all_blocks_total); + if (cdrom[id].total_read >= cdrom[id].all_blocks_total) + { + cdrom_log("CD-ROM %i: %i bytes read, current block finished\n", id, cdrom[id].total_read); + /* Read the next block. */ + ret = cdrom_read_blocks(id, &alloc_length, 0); + if (!ret) + { + /* Return value is 0 - an error has occurred. */ + cdrom_log("CD-ROM %i: %i bytes read, error while reading blocks\n", id, cdrom[id].total_read); + cdrom[id].status = BUSY_STAT | (cdrom[id].status & ERR_STAT); + return 0; + } + else + { + /* Return value is 1 - sectors have been read successfully. */ + cdrom[id].pos = 0; + cdrom[id].all_blocks_total += cdrom[id].block_total; + cdrom_log("CD-ROM %i: %i bytes read, next block(s) read successfully, %i bytes are still left\n", id, cdrom[id].total_read, cdrom[id].all_blocks_total - cdrom[id].total_read); + return 1; + } + } + else + { + /* Blocks not exhausted, tell the host to check for buffer length. */ + cdrom_log("CD-ROM %i: Blocks not yet finished\n", id); + return 1; + } + } + else + { + /* Not a media access command, ALWAYS do the callback. */ + cdrom_log("CD-ROM %i: Not a media access command\n", id); + return 1; + } +} + +/* This is the general ATAPI callback. */ +void cdrom_callback(uint8_t id) /* Callback for non-Read CD commands */ +{ + int ret = 0; + int old_pos = 0; + + if (!cdrom_drives[id].bus_type) + { + cdrom_log("CD-ROM %i: Lowering IDE IRQ\n", id); + ide_irq_lower(&(ide_drives[cdrom_drives[id].ide_channel])); + } + + cdrom[id].status = BUSY_STAT; + + if (cdrom[id].total_read >= cdrom[id].packet_len) + { + cdrom_log("CD-ROM %i: %i bytes read, command done\n", id, cdrom[id].total_read); + + cdrom[id].pos = cdrom[id].request_pos = 0; + cdrom_command_complete(id); + } + else + { + cdrom_log("CD-ROM %i: %i bytes read, %i bytes are still left\n", id, cdrom[id].total_read, cdrom[id].packet_len - cdrom[id].total_read); + + /* Make sure to keep pos, and reset request_pos to 0. */ + /* Also make sure to not reset total_read. */ + old_pos = cdrom[id].pos; + cdrom[id].packet_status = CDROM_PHASE_DATA_IN; + cdrom_command_common(id); + cdrom[id].pos = old_pos; + cdrom[id].request_pos = 0; + } +} + +/* 0 = Continue transfer; 1 = Continue transfer, IRQ; -1 = Terminate transfer; -2 = Terminate transfer with error */ +int cdrom_mode_select_return(uint8_t id, int ret) +{ + switch(ret) + { + case 0: + /* Invalid field in parameter list. */ + cdrom_invalid_field_pl(id); + return -2; + case 1: + /* Successful, more data needed. */ + if (cdrom[id].pos >= (cdrom[id].packet_len + 2)) + { + cdrom[id].pos = 0; + cdrom_command_write(id); + return 1; + } + return 0; + case 2: + /* Successful, more data needed, second byte not yet processed. */ + return 0; + case -3: + /* Not initialized. */ + case -4: + /* Unknown phase. */ + cdrom_illegal_opcode(id); + return -2; + case -6: + /* Command terminated successfully. */ + cdrom_command_complete(id); + return -1; + } +} + +int cdrom_phase_callback(uint8_t id); + +int cdrom_read_from_ide_dma(uint8_t channel) +{ + uint8_t *cdbufferb; + + uint8_t id = atapi_cdrom_drives[channel]; + + cdbufferb = (uint8_t *) cdrom[id].buffer; + + if (id > CDROM_NUM) + { + return 0; + } + + if (ide_bus_master_write) + { + if (ide_bus_master_write(channel >> 1, cdbufferb, cdrom[id].request_length)) + { + cdrom_data_phase_error(id); + cdrom_phase_callback(id); + return 0; + } + else + { + return 1; + } + } +} + +int cdrom_read_from_scsi_dma(uint8_t scsi_id) +{ + uint8_t *cdbufferb; + + uint8_t id = scsi_cdrom_drives[scsi_id]; + + cdbufferb = (uint8_t *) cdrom[id].buffer; + + if (id > CDROM_NUM) + { + return 0; + } + + cdrom_log("Reading from SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, SCSIDevices[scsi_id].InitLength); + memcpy(cdbufferb, SCSIDevices[scsi_id].CmdBuffer, SCSIDevices[scsi_id].InitLength); + return 1; +} + +int cdrom_read_from_dma(uint8_t id) +{ + uint8_t *cdbufferb = (uint8_t *) cdrom[id].buffer; + + int i = 0; + int ret = 0; + + if (cdrom_drives[id].bus_type) + { + ret = cdrom_read_from_scsi_dma(cdrom_drives[id].scsi_device_id); + } + else + { + ret = cdrom_read_from_ide_dma(cdrom_drives[id].ide_channel); + } + + if (!ret) + { + return 0; + } + + for (i = 0; i < cdrom[id].request_length; i++) + { + ret = cdrom_mode_select_write(id, cdbufferb[i]); + ret = cdrom_mode_select_return(id, ret); + if (ret == -1) + { + return 1; + } + else if (ret == -2) + { + cdrom_phase_callback(id); + return 0; + } + } +} + +int cdrom_write_to_ide_dma(uint8_t channel) +{ + uint8_t *cdbufferb; + + uint8_t id = atapi_cdrom_drives[channel]; + + cdbufferb = (uint8_t *) cdrom[id].buffer; + + if (id > CDROM_NUM) + { + return 0; + } + + if (ide_bus_master_read) + { + if (ide_bus_master_read(channel >> 1, cdbufferb, cdrom[id].request_length)) + { + cdrom_data_phase_error(id); + cdrom_phase_callback(id); + return 0; + } + else + { + return 1; + } + } +} + +int cdrom_write_to_scsi_dma(uint8_t scsi_id) +{ + uint8_t *cdbufferb; + + uint8_t id = scsi_cdrom_drives[scsi_id]; + + cdbufferb = (uint8_t *) cdrom[id].buffer; + + if (id > CDROM_NUM) + { + return 0; + } + + cdrom_log("Writing to SCSI DMA: SCSI ID %02X, init length %i\n", scsi_id, SCSIDevices[scsi_id].InitLength); + memcpy(SCSIDevices[scsi_id].CmdBuffer, cdbufferb, SCSIDevices[scsi_id].InitLength); + cdrom_log("CD-ROM %i: Data from CD buffer: %02X %02X %02X %02X %02X %02X %02X %02X\n", id, cdbufferb[0], cdbufferb[1], cdbufferb[2], cdbufferb[3], cdbufferb[4], cdbufferb[5], cdbufferb[6], cdbufferb[7]); + cdrom_log("CD-ROM %i: Data from SCSI DMA : %02X %02X %02X %02X %02X %02X %02X %02X\n", id, SCSIDevices[scsi_id].CmdBuffer[0], SCSIDevices[scsi_id].CmdBuffer[1], SCSIDevices[scsi_id].CmdBuffer[2], SCSIDevices[scsi_id].CmdBuffer[3], SCSIDevices[scsi_id].CmdBuffer[4], SCSIDevices[scsi_id].CmdBuffer[5], SCSIDevices[scsi_id].CmdBuffer[6], SCSIDevices[scsi_id].CmdBuffer[7]); + return 1; +} + +int cdrom_write_to_dma(uint8_t id) +{ + int ret = 0; + + if (cdrom_drives[id].bus_type) + { + ret = cdrom_write_to_scsi_dma(cdrom_drives[id].scsi_device_id); + } + else + { + ret = cdrom_write_to_ide_dma(cdrom_drives[id].ide_channel); + } + + if (!ret) + { + return 0; + } + + return 1; +} + +/* If the result is 1, issue an IRQ, otherwise not. */ +int cdrom_phase_callback(uint8_t id) +{ + switch(cdrom[id].packet_status) + { + case CDROM_PHASE_IDLE: + // cdrom_log("CD-ROM %i: CDROM_PHASE_IDLE\n", id); + cdrom[id].pos=0; + cdrom[id].phase = 1; + cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT); + return 0; + case CDROM_PHASE_COMMAND: + // cdrom_log("CD-ROM %i: CDROM_PHASE_COMMAND\n", id); + cdrom[id].status = BUSY_STAT | (cdrom[id].status &ERR_STAT); + memcpy(cdrom[id].atapi_cdb, (uint8_t *) cdrom[id].buffer, cdrom[id].cdb_len); + cdrom_command(id, cdrom[id].atapi_cdb); + return 0; + case CDROM_PHASE_COMPLETE: + // cdrom_log("CD-ROM %i: CDROM_PHASE_COMPLETE\n", id); + cdrom[id].status = READY_STAT; + cdrom[id].phase = 3; + return 1; + case CDROM_PHASE_DATA_OUT: + // cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT\n", id); + cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT); + cdrom[id].phase = 0; + return 1; + case CDROM_PHASE_DATA_OUT_DMA: + // cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_OUT_DMA\n", id); + cdrom_read_from_dma(id); + cdrom[id].packet_status = CDROM_PHASE_COMPLETE; + cdrom[id].status = READY_STAT; + cdrom[id].phase = 3; + return 1; + case CDROM_PHASE_DATA_IN: + // cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN\n", id); + cdrom[id].status = READY_STAT | DRQ_STAT | (cdrom[id].status & ERR_STAT); + cdrom[id].phase = 2; + return 1; + case CDROM_PHASE_DATA_IN_DMA: + // cdrom_log("CD-ROM %i: CDROM_PHASE_DATA_IN_DMA\n", id); + cdrom_write_to_dma(id); + cdrom[id].packet_status = CDROM_PHASE_COMPLETE; + cdrom[id].status = READY_STAT; + cdrom[id].phase = 3; + return 1; + case CDROM_PHASE_ERROR: + // cdrom_log("CD-ROM %i: CDROM_PHASE_ERROR\n", id); + cdrom[id].status = READY_STAT | ERR_STAT; + cdrom[id].phase = 3; + return 1; + } +} + +uint32_t cdrom_read(uint8_t channel) +{ + uint8_t id = atapi_cdrom_drives[channel]; + + uint16_t temp = 0; + int ret = 0; + + if (id > CDROM_NUM) + { + return 0; + } + + temp = cdrom[id].buffer[cdrom[id].pos >> 1]; + + cdrom[id].pos += 2; + cdrom[id].request_pos += 2; + + if (cdrom[id].packet_status == CDROM_PHASE_DATA_IN) + { + cdrom[id].total_read += 2; + ret = cdrom_block_check(id); + /* If the block check has returned 0, this means all the requested blocks have been read, therefore the command has finished. */ + if (ret) + { + cdrom_log("CD-ROM %i: Return value is 1\n", id); + if (cdrom[id].request_pos >= cdrom[id].request_length) + { + /* Time for a DRQ. */ + cdrom_log("CD-ROM %i: Issuing read callback\n", id); + cdrom_callback(id); + } + else + { + cdrom_log("CD-ROM %i: Doing nothing\n", id); + } + } + else + { + cdrom_log("CD-ROM %i: Return value is 0\n", id); + } + cdrom_log("CD-ROM %i: Returning: %04X (buffer position: %i, request position: %i, total: %i)\n", id, temp, cdrom[id].pos, cdrom[id].request_pos, cdrom[id].total_read); + return temp; + } + else + { + cdrom_log("CD-ROM %i: Returning zero (buffer position: %i, request position: %i, total: %i)\n", id, cdrom[id].pos, cdrom[id].request_pos, cdrom[id].total_read); + return 0; + } +} + +/* If the result is 1, issue an IRQ, otherwise not. */ +int cdrom_write(uint8_t channel, uint16_t val) +{ + uint8_t id = atapi_cdrom_drives[channel]; + + int ret = 0; + + if (id > CDROM_NUM) + { + return 0; + } + + cdrom[id].buffer[cdrom[id].pos >> 1] = val; + cdrom[id].pos += 2; + + if (cdrom[id].packet_status == CDROM_PHASE_DATA_OUT) + { + ret = cdrom_mode_select_write(id, val & 0xff); + if (ret == 1) + { + ret = 2; + } + cdrom_mode_select_return(id, ret); + /* Make sure to not do another write, if it has terminated. */ + if (ret != -6) + { + cdrom_mode_select_write(id, val >> 8); + if (cdrom_mode_select_return(id, ret) == 1) + { + return 0; + } + } + return 0; + } + else if (cdrom[id].packet_status == CDROM_PHASE_IDLE) + { + if (cdrom[id].pos >= cdrom[id].cdb_len) + { + cdrom[id].pos=0; + cdrom[id].status = BUSY_STAT; + cdrom[id].packet_status = CDROM_PHASE_COMMAND; + timer_process(); + cdrom_phase_callback(id); + timer_update_outstanding(); + } + return 0; + } +} diff --git a/src/cdrom.h b/src/cdrom.h index e8103e5ca..f03fb7854 100644 --- a/src/cdrom.h +++ b/src/cdrom.h @@ -2,34 +2,203 @@ #define __CDROM_H__ /*CD-ROM stuff*/ +#define CDROM_NUM 4 + +#define CDROM_PHASE_IDLE 0 +#define CDROM_PHASE_COMMAND 1 +#define CDROM_PHASE_COMPLETE 2 +#define CDROM_PHASE_DATA_IN 3 +#define CDROM_PHASE_DATA_IN_DMA 4 +#define CDROM_PHASE_DATA_OUT 5 +#define CDROM_PHASE_DATA_OUT_DMA 6 +#define CDROM_PHASE_ERROR 0x80 + +#define BUF_SIZE 32768 + +#define CDROM_ISO 200 + +#define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT)) +#define CDROM_TIME (5 * 100 * (1 << TIMER_SHIFT)) + typedef struct CDROM { - int (*ready)(void); - int (*medium_changed)(void); - int (*readtoc)(uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); - int (*readtoc_session)(uint8_t *b, int msf, int maxlen); - int (*readtoc_raw)(uint8_t *b, int msf, int maxlen); - uint8_t (*getcurrentsubchannel)(uint8_t *b, int msf); - void (*read_capacity)(uint8_t *b); - void (*read_subchannel)(uint8_t *in_cdb, uint8_t *b); - void (*read_header)(uint8_t *in_cdb, uint8_t *b); - void (*read_disc_information)(uint8_t *b); - int (*read_track_information)(uint8_t *in_cdb, uint8_t *b); - int (*sector_data_type)(int sector, int ismsf); - void (*readsector_raw)(uint8_t *b, int sector, int ismsf); - void (*playaudio)(uint32_t pos, uint32_t len, int ismsf); - void (*seek)(uint32_t pos); - void (*load)(void); - void (*eject)(void); - void (*pause)(void); - void (*resume)(void); - uint32_t (*size)(void); - int (*status)(void); - int (*is_track_audio)(uint32_t pos, int ismsf); - void (*stop)(void); - void (*exit)(void); + int (*ready)(uint8_t id); + int (*medium_changed)(uint8_t id); + void (*audio_callback)(uint8_t id, int16_t *output, int len); + void (*audio_stop)(uint8_t id); + int (*readtoc)(uint8_t id, uint8_t *b, uint8_t starttrack, int msf, int maxlen, int single); + int (*readtoc_session)(uint8_t id, uint8_t *b, int msf, int maxlen); + int (*readtoc_raw)(uint8_t id, uint8_t *b, int msf, int maxlen); + uint8_t (*getcurrentsubchannel)(uint8_t id, uint8_t *b, int msf); + int (*pass_through)(uint8_t id, uint8_t *in_cdb, uint8_t *b, uint32_t *len); + int (*sector_data_type)(uint8_t id, int sector, int ismsf); + int (*readsector_raw)(uint8_t id, uint8_t *buffer, int sector, int ismsf, int cdrom_sector_type, int cdrom_sector_flags, int *len); + void (*playaudio)(uint8_t id, uint32_t pos, uint32_t len, int ismsf); + void (*load)(uint8_t id); + void (*eject)(uint8_t id); + void (*pause)(uint8_t id); + void (*resume)(uint8_t id); + uint32_t (*size)(uint8_t id); + int (*status)(uint8_t id); + int (*is_track_audio)(uint8_t id, uint32_t pos, int ismsf); + void (*stop)(uint8_t id); + void (*exit)(uint8_t id); } CDROM; -extern CDROM *cdrom; +typedef struct __attribute__((__packed__)) +{ + uint8_t previous_command; + int toctimes; + + int is_dma; + + int requested_blocks; /* This will be set to something other than 1 when block reads are implemented. */ + + int current_page_code; + int current_page_len; + + int current_page_pos; + + int mode_select_phase; + + int total_length; + int written_length; + + int do_page_save; + + uint8_t error; + uint8_t features; + uint16_t request_length; + uint8_t status; + uint8_t phase; + + uint32_t sector_pos; + uint32_t sector_len; + + uint32_t packet_len; + int packet_status; + + uint8_t atapi_cdb[16]; + uint8_t current_cdb[16]; + + uint32_t pos; + + int callback; + + int data_pos; + + int cdb_len_setting; + int cdb_len; + + int cd_status; + int prev_status; + + int unit_attention; + uint8_t sense[18]; + + int request_pos; + + uint16_t buffer[390144]; + + int times; + + uint32_t seek_pos; + + int total_read; + + int block_total; + int all_blocks_total; + + int old_len; +} cdrom_t; + +extern cdrom_t cdrom[CDROM_NUM]; + +typedef struct __attribute__((__packed__)) +{ + int enabled; + + int max_blocks_at_once; + + CDROM *handler; + + int host_drive; + int prev_host_drive; + + uint8_t bus_type; /* 0 = ATAPI, 1 = SCSI */ + uint8_t bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ + + uint8_t check_on_execution; /* 0 = Not Ready/Unit Attention checkeck is performed on the controller's side before command execution; + 1 = Not Ready/Unit Attention checkeck is performed on command execution. */ + + uint8_t ide_channel; + + uint8_t scsi_device_id; + + uint8_t sound_on; +} cdrom_drive_t; + +extern cdrom_drive_t cdrom_drives[CDROM_NUM]; + +extern uint8_t atapi_cdrom_drives[8]; + +extern uint8_t scsi_cdrom_drives[16]; + +extern int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); +extern int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); +extern void (*ide_bus_master_set_irq)(int channel); + +typedef struct +{ + uint32_t last_block; + uint64_t image_size; + int iso_inited; + char iso_path[1024]; + FILE* iso_image; + int iso_changed; + + uint32_t cd_pos; + uint32_t cd_end; +} cdrom_iso_t; + +cdrom_iso_t cdrom_iso[CDROM_NUM]; + +typedef struct +{ + uint32_t last_block; + uint32_t cdrom_capacity; + int ioctl_inited; + char ioctl_path[8]; + int tocvalid; + int cd_state; + uint32_t cd_end; + int16_t cd_buffer[BUF_SIZE]; + int cd_buflen; +} cdrom_ioctl_t; + +void ioctl_close(uint8_t id); + +cdrom_ioctl_t cdrom_ioctl[CDROM_NUM]; + +uint32_t cdrom_mode_sense_get_channel(uint8_t id, int channel); +uint32_t cdrom_mode_sense_get_volume(uint8_t id, int channel); +void build_atapi_cdrom_map(); +void build_scsi_cdrom_map(); +int cdrom_CDROM_PHASE_to_scsi(uint8_t id); +int cdrom_atapi_phase_to_scsi(uint8_t id); +void cdrom_command(uint8_t id, uint8_t *cdb); +int cdrom_phase_callback(uint8_t id); +uint32_t cdrom_read(uint8_t channel); +int cdrom_write(uint8_t channel, uint16_t val); +int cdrom_lba_to_msf_accurate(int lba); +void cdrom_reset(uint8_t id); +void cdrom_set_signature(int id); + +#define cdrom_sense_error cdrom[id].sense[0] +#define cdrom_sense_key cdrom[id].sense[2] +#define cdrom_asc cdrom[id].sense[12] +#define cdrom_ascq cdrom[id].sense[12] +#define cdrom_drive cdrom_drives[id].host_drive #endif \ No newline at end of file diff --git a/src/codegen_ops_x86-64.h b/src/codegen_ops_x86-64.h index 452241e81..8573ab495 100644 --- a/src/codegen_ops_x86-64.h +++ b/src/codegen_ops_x86-64.h @@ -3188,6 +3188,8 @@ static void TEST_NONZERO_JUMP_L(int host_reg, uint32_t new_pc, int taken_cycles) static int BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) { + uint8_t *jump1; + if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) { addbyte(0x83); /*CMP flags_res, 0*/ @@ -3203,10 +3205,8 @@ static int BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int no addbyte(0xc0); addbyte(0x75); /*JNZ +*/ } - if (not) - addbyte(12+2+2+7+5+(timing_bt ? 8 : 0)); - else - addbyte(12+2+2); + jump1 = &codeblock[block_current].data[block_pos]; + addbyte(0); CALL_FUNC(CF_SET); addbyte(0x85); /*TEST EAX,EAX*/ addbyte(0xc0); @@ -3215,6 +3215,9 @@ static int BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int no else addbyte(0x74); /*JZ +*/ addbyte(7+5+(timing_bt ? 4 : 0)); + + if (!not) + *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; addbyte(0xC7); /*MOVL [pc], new_pc*/ addbyte(0x45); addbyte(cpu_state_offset(pc)); @@ -3228,6 +3231,8 @@ static int BRANCH_COND_BE(int pc_offset, uint32_t op_pc, uint32_t offset, int no } addbyte(0xe9); /*JMP end*/ addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + if (not) + *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; } static int BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not) @@ -3268,6 +3273,7 @@ static int BRANCH_COND_L(int pc_offset, uint32_t op_pc, uint32_t offset, int not static int BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int not) { + uint8_t *jump1; if (codegen_flags_changed && cpu_state.flags_op != FLAGS_UNKNOWN) { addbyte(0x83); /*CMP flags_res, 0*/ @@ -3283,11 +3289,8 @@ static int BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int no addbyte(0xc0); addbyte(0x75); /*JNZ +*/ } - if (not) - addbyte(12+2+3+12+2+3+2+2+7+5+(timing_bt ? 8 : 0)); - else - addbyte(12+2+3+12+2+3+2+2); - + jump1 = &codeblock[block_current].data[block_pos]; + addbyte(0); CALL_FUNC(NF_SET); addbyte(0x85); /*TEST EAX,EAX*/ addbyte(0xc0); @@ -3307,6 +3310,8 @@ static int BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int no else addbyte(0x74); /*JZ +*/ addbyte(7+5+(timing_bt ? 4 : 0)); + if (!not) + *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; addbyte(0xC7); /*MOVL [pc], new_pc*/ addbyte(0x45); addbyte(cpu_state_offset(pc)); @@ -3320,6 +3325,8 @@ static int BRANCH_COND_LE(int pc_offset, uint32_t op_pc, uint32_t offset, int no } addbyte(0xe9); /*JMP end*/ addlong(BLOCK_EXIT_OFFSET - (block_pos + 4)); + if (not) + *jump1 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump1 - 1; } static int LOAD_VAR_W(uintptr_t addr) @@ -5241,7 +5248,7 @@ static void LOAD_EA() static void MEM_CHECK_WRITE(x86seg *seg) { - uint8_t *jump1, *jump2; + uint8_t *jump1, *jump2, *jump3; CHECK_SEG_WRITE(seg); @@ -5264,15 +5271,27 @@ static void MEM_CHECK_WRITE(x86seg *seg) /*seg = ESI, addr = EAX*/ + if (IS_32_ADDR(&cr0)) + { + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&cr0); + addbyte(0); + } + else + { + addbyte(0x48); /*MOV RDI, &cr0*/ + addbyte(0xbf); + addquad((uint64_t)&cr0); + addbyte(0x83); /*CMPL [RDI], 0*/ + addbyte(0x3f); + addbyte(0); + } addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ addbyte(0x8d); addbyte(0x3c); addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)&cr0); - addbyte(0); addbyte(0x79); /*JNS +*/ jump1 = &codeblock[block_current].data[block_pos]; addbyte(0); @@ -5284,17 +5303,32 @@ static void MEM_CHECK_WRITE(x86seg *seg) addbyte(0xfe); addbyte(-1); addbyte(0x74); /*JE slowpath*/ - addbyte(10); - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t)writelookup2); - addbyte(-1); + jump3 = &codeblock[block_current].data[block_pos]; + addbyte(0); + if (IS_32_ADDR(writelookup2)) + { + addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ + addbyte(0x3c); + addbyte(0xfd); + addlong((uint32_t)writelookup2); + addbyte(-1); + } + else + { + addbyte(0x48); /*MOV RCX, writelookup2*/ + addbyte(0xb9); + addquad((uint64_t)writelookup2); + addbyte(0x83); /*CMP [RCX+RDI*8], -1*/ + addbyte(0x3c); + addbyte(0xf9); + addbyte(-1); + } addbyte(0x75); /*JNE +*/ jump2 = &codeblock[block_current].data[block_pos]; addbyte(0); // addbyte(0xc3); /*RET*/ - + + *jump3 = (uintptr_t)&codeblock[block_current].data[block_pos] - (uintptr_t)jump3 - 1; /*slowpath:*/ addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ addbyte(0x8d); @@ -5358,15 +5392,27 @@ static void MEM_CHECK_WRITE_W(x86seg *seg) /*seg = ESI, addr = EAX*/ + if (IS_32_ADDR(&cr0)) + { + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&cr0); + addbyte(0); + } + else + { + addbyte(0x48); /*MOV RDI, &cr0*/ + addbyte(0xbf); + addquad((uint64_t)&cr0); + addbyte(0x83); /*CMPL [RDI], 0*/ + addbyte(0x3f); + addbyte(0); + } addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ addbyte(0x8d); addbyte(0x3c); addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)&cr0); - addbyte(0); addbyte(0x79); /*JNS +*/ jump1 = &codeblock[block_current].data[block_pos]; addbyte(0); @@ -5387,19 +5433,42 @@ static void MEM_CHECK_WRITE_W(x86seg *seg) addbyte(0xc1); /*SHR ESI, 12*/ addbyte(0xee); addbyte(12); - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t)writelookup2); - addbyte(-1); + if (IS_32_ADDR(writelookup2)) + { + addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ + addbyte(0x3c); + addbyte(0xfd); + addlong((uint32_t)writelookup2); + addbyte(-1); + } + else + { + addbyte(0x48); /*MOV RAX, writelookup2*/ + addbyte(0xb8); + addquad((uint64_t)writelookup2); + addbyte(0x83); /*CMP [RAX+RDI*8], -1*/ + addbyte(0x3c); + addbyte(0xf8); + addbyte(-1); + } addbyte(0x74); /*JE +*/ jump2 = &codeblock[block_current].data[block_pos]; addbyte(0); - addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ - addbyte(0x3c); - addbyte(0xf5); - addlong((uint32_t)writelookup2); - addbyte(-1); + if (IS_32_ADDR(writelookup2)) + { + addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ + addbyte(0x3c); + addbyte(0xfd); + addlong((uint32_t)writelookup2); + addbyte(-1); + } + else + { + addbyte(0x83); /*CMP [RAX+RSI*8], -1*/ + addbyte(0x3c); + addbyte(0xf0); + addbyte(-1); + } addbyte(0x75); /*JNE +*/ jump3 = &codeblock[block_current].data[block_pos]; addbyte(0); @@ -5460,15 +5529,27 @@ static void MEM_CHECK_WRITE_L(x86seg *seg) /*seg = ESI, addr = EAX*/ + if (IS_32_ADDR(&cr0)) + { + addbyte(0x83); /*CMP cr0, 0*/ + addbyte(0x3c); + addbyte(0x25); + addlong((uint32_t)&cr0); + addbyte(0); + } + else + { + addbyte(0x48); /*MOV RDI, &cr0*/ + addbyte(0xbf); + addquad((uint64_t)&cr0); + addbyte(0x83); /*CMPL [RDI], 0*/ + addbyte(0x3f); + addbyte(0); + } addbyte(0x67); /*LEA EDI, [EAX+ESI]*/ addbyte(0x8d); addbyte(0x3c); addbyte(0x30); - addbyte(0x83); /*CMP cr0, 0*/ - addbyte(0x3c); - addbyte(0x25); - addlong((uint32_t)&cr0); - addbyte(0); addbyte(0x79); /*JNS +*/ jump1 = &codeblock[block_current].data[block_pos]; addbyte(0); @@ -5489,19 +5570,42 @@ static void MEM_CHECK_WRITE_L(x86seg *seg) addbyte(0xc1); /*SHR ESI, 12*/ addbyte(0xee); addbyte(12); - addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ - addbyte(0x3c); - addbyte(0xfd); - addlong((uint32_t)writelookup2); - addbyte(-1); + if (IS_32_ADDR(writelookup2)) + { + addbyte(0x83); /*CMP writelookup2[RDI*8],-1*/ + addbyte(0x3c); + addbyte(0xfd); + addlong((uint32_t)writelookup2); + addbyte(-1); + } + else + { + addbyte(0x48); /*MOV RAX, writelookup2*/ + addbyte(0xb8); + addquad((uint64_t)writelookup2); + addbyte(0x83); /*CMP [RAX+RDI*8], -1*/ + addbyte(0x3c); + addbyte(0xf8); + addbyte(-1); + } addbyte(0x74); /*JE slowpath*/ jump2 = &codeblock[block_current].data[block_pos]; addbyte(0); - addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ - addbyte(0x3c); - addbyte(0xf5); - addlong((uint32_t)writelookup2); - addbyte(-1); + if (IS_32_ADDR(writelookup2)) + { + addbyte(0x83); /*CMP writelookup2[RSI*8],-1*/ + addbyte(0x3c); + addbyte(0xfd); + addlong((uint32_t)writelookup2); + addbyte(-1); + } + else + { + addbyte(0x83); /*CMP [RAX+RSI*8], -1*/ + addbyte(0x3c); + addbyte(0xf0); + addbyte(-1); + } addbyte(0x75); /*JNE +*/ jump3 = &codeblock[block_current].data[block_pos]; addbyte(0); diff --git a/src/codegen_ops_x86.h b/src/codegen_ops_x86.h index ac6111669..30c013856 100644 --- a/src/codegen_ops_x86.h +++ b/src/codegen_ops_x86.h @@ -3460,13 +3460,13 @@ static void MMX_ENTER() addbyte(0x45); addbyte(cpu_state_offset(ismmx)); addbyte(1); - addbyte(0x8b); /*MOV TOP, EAX*/ + addbyte(0x89); /*MOV TOP, EAX*/ addbyte(0x45); addbyte(cpu_state_offset(TOP)); - addbyte(0x8b); /*MOV tag, EAX*/ + addbyte(0x89); /*MOV tag, EAX*/ addbyte(0x45); addbyte(cpu_state_offset(tag[0])); - addbyte(0x8b); /*MOV tag+4, EAX*/ + addbyte(0x89); /*MOV tag+4, EAX*/ addbyte(0x45); addbyte(cpu_state_offset(tag[4])); diff --git a/src/codegen_x86-64.h b/src/codegen_x86-64.h index e8cd97015..648a30342 100644 --- a/src/codegen_x86-64.h +++ b/src/codegen_x86-64.h @@ -10,7 +10,7 @@ #define BLOCK_EXIT_OFFSET 0x7e0 #define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20) -#define BLOCK_MAX 1650 +#define BLOCK_MAX 1620 enum { diff --git a/src/disc_86f.c b/src/disc_86f.c index cfc898a52..17ae7dfcd 100644 --- a/src/disc_86f.c +++ b/src/disc_86f.c @@ -203,6 +203,22 @@ static struct __attribute__((packed)) uint32_t dma_over; } d86f[FDD_NUM]; +int d86f_do_log = 1; + +void d86f_log(const char *format, ...) +{ +#ifdef ENABLE_D86F_LOG + if (d86f_do_log) + { + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + fflush(stdout); + } +#endif +} + static void d86f_setupcrc(uint16_t poly) { int c = 256, bc; @@ -1107,7 +1123,7 @@ void d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_ { find->sync_marks++; find->sync_pos = d86f[drive].track_pos; - // pclog("Sync marks: %i\n", find->sync_marks); + // d86f_log("Sync marks: %i\n", find->sync_marks); return; } @@ -1120,7 +1136,7 @@ void d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_ disc_calccrc(decodefm(drive, d86f[drive].last_word[side]), &(d86f[drive].calc_crc)); find->sync_marks = find->bits_obtained = find->bytes_obtained = 0; find->sync_pos = 0xFFFFFFFF; - // pclog("AM found (%04X) (%02X)\n", req_am, d86f[drive].state); + // d86f_log("AM found (%04X) (%02X)\n", req_am, d86f[drive].state); d86f[drive].preceding_bit[side] = d86f[drive].last_word[side] & 1; d86f[drive].state++; return; @@ -1143,7 +1159,7 @@ void d86f_find_address_mark_mfm(int drive, int side, find_t *find, uint16_t req_ else { /* Not skip mode, process the sector anyway. */ - // pclog("Wrong AM found (%04X) (%02X)\n", other_am, d86f[drive].state); + // d86f_log("Wrong AM found (%04X) (%02X)\n", other_am, d86f[drive].state); fdc_set_wrong_am(); d86f[drive].preceding_bit[side] = d86f[drive].last_word[side] & 1; d86f[drive].state++; @@ -1247,12 +1263,12 @@ void d86f_read_sector_id(int drive, int side, int match) else { /* CRC is valid. */ - // pclog("Sector ID found: %08X; Requested: %08X\n", d86f[drive].last_sector.dword, d86f[drive].req_sector.dword); + // d86f_log("Sector ID found: %08X; Requested: %08X\n", d86f[drive].last_sector.dword, d86f[drive].req_sector.dword); d86f[drive].id_find.sync_marks = d86f[drive].id_find.bits_obtained = d86f[drive].id_find.bytes_obtained = 0; d86f[drive].id_found++; if ((d86f[drive].last_sector.dword == d86f[drive].req_sector.dword) || !match) { - // pclog("ID read (%02X)\n", d86f[drive].state); + // d86f_log("ID read (%02X)\n", d86f[drive].state); d86f_handler[drive].set_sector(drive, side, d86f[drive].last_sector.id.c, d86f[drive].last_sector.id.h, d86f[drive].last_sector.id.r, d86f[drive].last_sector.id.n); if (d86f[drive].state == STATE_02_READ_ID) { @@ -1274,12 +1290,12 @@ void d86f_read_sector_id(int drive, int side, int match) { if (d86f[drive].last_sector.id.c == 0xFF) { - // pclog("[State: %02X] [Side %i] Bad cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + // d86f_log("[State: %02X] [Side %i] Bad cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); d86f[drive].error_condition |= 8; } else { - // pclog("[State: %02X] [Side %i] Wrong cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + // d86f_log("[State: %02X] [Side %i] Wrong cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); d86f[drive].error_condition |= 0x10; } } @@ -1385,7 +1401,7 @@ void d86f_read_sector_data(int drive, int side) if (read_status == -1) { d86f[drive].dma_over++; - // pclog("DMA over now: %i\n", d86f[drive].dma_over); + // d86f_log("DMA over now: %i\n", d86f[drive].dma_over); } } } @@ -1403,7 +1419,7 @@ void d86f_read_sector_data(int drive, int side) /* We've got the data. */ if (d86f[drive].dma_over > 1) { - // pclog("DMA overrun while reading data!\n"); + // d86f_log("DMA overrun while reading data!\n"); d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; d86f[drive].error_condition = 0; d86f[drive].state = STATE_IDLE; @@ -1417,7 +1433,7 @@ void d86f_read_sector_data(int drive, int side) } else { - // pclog("Bytes over DMA: %i\n", d86f[drive].dma_over); + // d86f_log("Bytes over DMA: %i\n", d86f[drive].dma_over); } if ((d86f[drive].calc_crc.word != d86f[drive].track_crc.word) && (d86f[drive].state != STATE_02_READ_DATA)) @@ -1490,7 +1506,7 @@ void d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) { /* We're in the data field of the sector, use a CRC byte. */ d86f[drive].current_byte[side] = d86f[drive].calc_crc.bytes[(d86f[drive].data_find.bytes_obtained & 1)]; - // pclog("BO: %04X (%02X)\n", d86f[drive].data_find.bytes_obtained, d86f[drive].current_byte[side]); + // d86f_log("BO: %04X (%02X)\n", d86f[drive].data_find.bytes_obtained, d86f[drive].current_byte[side]); } d86f[drive].current_bit[side] = (15 - (d86f[drive].data_find.bits_obtained & 15)) >> 1; @@ -1574,7 +1590,7 @@ void d86f_write_sector_data(int drive, int side, int mfm, uint16_t am) { if (d86f[drive].dma_over > 1) { - // pclog("DMA overrun while writing data!\n"); + // d86f_log("DMA overrun while writing data!\n"); d86f[drive].data_find.sync_marks = d86f[drive].data_find.bits_obtained = d86f[drive].data_find.bytes_obtained = 0; d86f[drive].error_condition = 0; d86f[drive].state = STATE_IDLE; @@ -1611,7 +1627,7 @@ void d86f_advance_bit(int drive, int side) if (d86f[drive].state != STATE_IDLE) { d86f[drive].index_count++; - // pclog("Index count now: %i\n", d86f[drive].index_count); + // d86f_log("Index count now: %i\n", d86f[drive].index_count); } } } @@ -1721,7 +1737,7 @@ void d86f_format_finish(int drive, int side, int mfm, uint16_t sc, uint16_t gap_ d86f[drive].state = STATE_IDLE; d86f_handler[drive].writeback(drive); - // pclog("Format finished (%i) (%i)!\n", d86f[drive].track_pos, sc); + // d86f_log("Format finished (%i) (%i)!\n", d86f[drive].track_pos, sc); d86f[drive].error_condition = 0; d86f[drive].datac = 0; fdc_sector_finishread(); @@ -1784,11 +1800,11 @@ void d86f_format_track(int drive, int side) data = 0; } d86f[drive].format_sector_id.byte_array[d86f[drive].datac] = data & 0xff; - // pclog("format_sector_id[%i] = %i\n", d86f[drive].datac, d86f[drive].format_sector_id.byte_array[d86f[drive].datac]); + // d86f_log("format_sector_id[%i] = %i\n", d86f[drive].datac, d86f[drive].format_sector_id.byte_array[d86f[drive].datac]); if (d86f[drive].datac == 3) { fdc_stop_id_request(); - // pclog("Formatting sector: %08X (%i) (%i)...\n", d86f[drive].format_sector_id.dword, d86f[drive].track_pos, sc); + // d86f_log("Formatting sector: %08X (%i) (%i)...\n", d86f[drive].format_sector_id.dword, d86f[drive].track_pos, sc); } } case FMT_PRETRK_SYNC: @@ -1881,7 +1897,7 @@ void d86f_format_track(int drive, int side) if ((d86f[drive].index_count) && (d86f[drive].format_state < FMT_SECTOR_ID_SYNC) || (d86f[drive].format_state > FMT_SECTOR_GAP3)) { - // pclog("Format finished regularly\n"); + // d86f_log("Format finished regularly\n"); d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); return; } @@ -1903,7 +1919,7 @@ void d86f_format_track(int drive, int side) case FMT_POSTTRK_CHECK: if (d86f[drive].index_count) { - // pclog("Format finished with delay\n"); + // d86f_log("Format finished with delay\n"); d86f_format_finish(drive, side, mfm, sc, gap_fill, do_write); return; } @@ -1945,10 +1961,10 @@ void d86f_poll(int drive) { if (!d86f_can_read_address(drive)) { - /* if (fdc_get_bitcell_period() != d86f_get_bitcell_period(drive)) pclog("[%i, %i] Bitcell period mismatch (%i != %i)\n", drive, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive)); - if (!fdd_can_read_medium(real_drive(drive))) pclog("[%i, %i] Drive can not read medium (hole = %01X)\n", drive, side, d86f_hole(drive)); - if (fdc_is_mfm() != d86f_is_mfm(drive)) pclog("[%i, %i] Encoding mismatch\n", drive, side); - if (d86f_get_encoding(drive) > 1) pclog("[%i, %i] Image encoding (%s) not FM or MFM\n", drive, side, (d86f_get_encoding(drive) == 2) ? "M2FM" : "GCR"); */ + /* if (fdc_get_bitcell_period() != d86f_get_bitcell_period(drive)) d86f_log("[%i, %i] Bitcell period mismatch (%i != %i)\n", drive, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive)); + if (!fdd_can_read_medium(real_drive(drive))) d86f_log("[%i, %i] Drive can not read medium (hole = %01X)\n", drive, side, d86f_hole(drive)); + if (fdc_is_mfm() != d86f_is_mfm(drive)) d86f_log("[%i, %i] Encoding mismatch\n", drive, side); + if (d86f_get_encoding(drive) > 1) d86f_log("[%i, %i] Image encoding (%s) not FM or MFM\n", drive, side, (d86f_get_encoding(drive) == 2) ? "M2FM" : "GCR"); */ d86f[drive].state = STATE_SECTOR_NOT_FOUND; } @@ -2081,7 +2097,7 @@ void d86f_poll(int drive) if (d86f_wrong_densel(drive) && (d86f[drive].state != STATE_IDLE)) { - // pclog("[State: %02X] [Side %i] No ID address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + // d86f_log("[State: %02X] [Side %i] No ID address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); d86f[drive].state = STATE_IDLE; fdc_noidam(); return; @@ -2093,7 +2109,7 @@ void d86f_poll(int drive) { case STATE_0A_FIND_ID: case STATE_SECTOR_NOT_FOUND: - // pclog("[State: %02X] [Side %i] No ID address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + // d86f_log("[State: %02X] [Side %i] No ID address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); d86f[drive].state = STATE_IDLE; fdc_noidam(); break; @@ -2104,7 +2120,7 @@ void d86f_poll(int drive) case STATE_05_FIND_DATA: case STATE_09_FIND_DATA: case STATE_0C_FIND_DATA: - // pclog("[State: %02X] [Side %i] No data address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + // d86f_log("[State: %02X] [Side %i] No data address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); d86f[drive].state = STATE_IDLE; fdc_nodataam(); break; @@ -2128,24 +2144,24 @@ void d86f_poll(int drive) { if ((d86f[drive].error_condition & 0x18) == 0x08) { - // pclog("[State: %02X] [Side %i] Bad cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + // d86f_log("[State: %02X] [Side %i] Bad cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); fdc_badcylinder(); } if ((d86f[drive].error_condition & 0x10) == 0x10) { - // pclog("[State: %02X] [Side %i] Wrong cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + // d86f_log("[State: %02X] [Side %i] Wrong cylinder (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); fdc_wrongcylinder(); } } else { - // pclog("[State: %02X] [Side %i] Sector not found (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + // d86f_log("[State: %02X] [Side %i] Sector not found (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); fdc_nosector(); } } else { - // pclog("[State: %02X] [Side %i] No ID address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); + // d86f_log("[State: %02X] [Side %i] No ID address mark (%i != %i?) (%02X) (%08X) (%i)\n", d86f[drive].state, side, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), d86f_handler[drive].side_flags(drive), d86f[drive].req_sector.dword, d86f_handler[drive].get_raw_size(drive, side)); fdc_noidam(); } break; @@ -2580,7 +2596,7 @@ void d86f_seek(int drive, int track) void d86f_write_track(int drive, int side, uint16_t *da0, uint16_t *sa0) { - // pclog("Pos: %08X\n", ftell(d86f[drive].f)); + // d86f_log("Pos: %08X\n", ftell(d86f[drive].f)); fwrite(&(d86f[drive].side_flags[side]), 1, 2, d86f[drive].f); @@ -2598,7 +2614,7 @@ void d86f_write_track(int drive, int side, uint16_t *da0, uint16_t *sa0) fwrite(da0, 1, d86f_get_array_size(drive, side) << 1, d86f[drive].f); - // pclog("Pos: %08X\n", ftell(d86f[drive].f)); + // d86f_log("Pos: %08X\n", ftell(d86f[drive].f)); } int d86f_get_track_table_size(int drive) @@ -2639,9 +2655,9 @@ void d86f_writeback(int drive) fread(header, 1, header_size, d86f[drive].f); fseek(d86f[drive].f, 8, SEEK_SET); - // pclog("PosEx: %08X\n", ftell(d86f[drive].f)); + // d86f_log("PosEx: %08X\n", ftell(d86f[drive].f)); fwrite(d86f[drive].track_offset, 1, d86f_get_track_table_size(drive), d86f[drive].f); - // pclog("PosEx: %08X\n", ftell(d86f[drive].f)); + // d86f_log("PosEx: %08X\n", ftell(d86f[drive].f)); if (!fdd_doublestep_40(drive)) { @@ -2681,14 +2697,14 @@ void d86f_writeback(int drive) } if (d86f[drive].track_offset[logical_track]) { - // pclog("Writing track...\n"); + // d86f_log("Writing track...\n"); fseek(d86f[drive].f, d86f[drive].track_offset[logical_track], SEEK_SET); d86f_write_track(drive, side, d86f[drive].track_encoded_data[side], d86f[drive].track_surface_data[side]); } } } - // pclog("Position: %08X\n", ftell(d86f[drive].f)); + // d86f_log("Position: %08X\n", ftell(d86f[drive].f)); if (d86f[drive].is_compressed) { @@ -2715,7 +2731,7 @@ void d86f_writeback(int drive) // ret = d86f_zlib(cf, d86f[drive].f, 0); if (!ret) { - pclog("86F: Error compressing file\n"); + d86f_log("86F: Error compressing file\n"); } fwrite(d86f[drive].outbuf, 1, ret, cf); @@ -2772,7 +2788,7 @@ void d86f_writeback(int drive) } #endif - // pclog("d86f_writeback(): %08X\n", d86f[drive].track_offset[track]); + // d86f_log("d86f_writeback(): %08X\n", d86f[drive].track_offset[track]); } void d86f_stop(int drive) @@ -2782,7 +2798,7 @@ void d86f_stop(int drive) int d86f_common_command(int drive, int sector, int track, int side, int rate, int sector_size) { - // pclog("d86f_common_command (drive %i): fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", drive, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), rate, sector, track, side); + d86f_log("d86f_common_command (drive %i): fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", drive, fdc_get_bitcell_period(), d86f_get_bitcell_period(drive), rate, sector, track, side); d86f[drive].req_sector.id.c = track; d86f[drive].req_sector.id.h = side; @@ -2802,7 +2818,7 @@ int d86f_common_command(int drive, int sector, int track, int side, int rate, in if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) { - // pclog("Wrong side!\n"); + // d86f_log("Wrong side!\n"); fdc_noidam(); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; @@ -2863,11 +2879,11 @@ void d86f_comparesector(int drive, int sector, int track, int side, int rate, in void d86f_readaddress(int drive, int side, int rate) { - // pclog("Reading sector ID on drive %i...\n", drive); + // d86f_log("Reading sector ID on drive %i...\n", drive); if (fdd_get_head(drive) && (d86f_get_sides(drive) == 1)) { - // pclog("Trying to access the second side of a single-sided disk\n"); + // d86f_log("Trying to access the second side of a single-sided disk\n"); fdc_noidam(); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; @@ -2949,7 +2965,7 @@ void d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy) if (d86f[drive].cur_track > 256) { - // pclog("Track above 256\n"); + // d86f_log("Track above 256\n"); fdc_writeprotect(); d86f[drive].state = STATE_IDLE; d86f[drive].index_count = 0; @@ -2979,7 +2995,7 @@ void d86f_common_format(int drive, int side, int rate, uint8_t fill, int proxy) } } - // pclog("Formatting track %i side %i\n", track, side); + // d86f_log("Formatting track %i side %i\n", track, side); d86f[drive].fill = fill; @@ -3071,7 +3087,7 @@ void d86f_load(int drive, char *fn) if ((magic != 0x46423638) && (magic != 0x66623638)) { /* File is not of the valid format, abort. */ - pclog("86F: Unrecognized magic bytes: %08X\n", magic); + d86f_log("86F: Unrecognized magic bytes: %08X\n", magic); fclose(d86f[drive].f); return; } @@ -3083,22 +3099,22 @@ void d86f_load(int drive, char *fn) /* File is not of a recognized format version, abort. */ if (d86f[drive].version == 0x0063) { - pclog("86F: File has emulator-internal version 0.99, this version is not valid in a file\n"); + d86f_log("86F: File has emulator-internal version 0.99, this version is not valid in a file\n"); } else if ((d86f[drive].version >= 0x0100) && (d86f[drive].version < D86FVER)) { - pclog("86F: No longer supported development file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF); + d86f_log("86F: No longer supported development file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF); } else { - pclog("86F: Unrecognized file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF); + d86f_log("86F: Unrecognized file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF); } fclose(d86f[drive].f); return; } else { - pclog("86F: Recognized file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF); + d86f_log("86F: Recognized file version: %i.%02i\n", d86f[drive].version >> 8, d86f[drive].version & 0xFF); } fread(&(d86f[drive].disk_flags), 2, 1, d86f[drive].f); @@ -3128,7 +3144,7 @@ void d86f_load(int drive, char *fn) if (crc64 != read_crc64) { - pclog("86F: CRC64 error\n"); + d86f_log("86F: CRC64 error\n"); fclose(d86f[drive].f); return; } @@ -3145,7 +3161,7 @@ void d86f_load(int drive, char *fn) d86f[drive].f = fopen(temp_file_name, "wb"); if (!d86f[drive].f) { - pclog("86F: Unable to create temporary decompressed file\n"); + d86f_log("86F: Unable to create temporary decompressed file\n"); return; } @@ -3175,7 +3191,7 @@ void d86f_load(int drive, char *fn) if (!temp) { - pclog("86F: Error decompressing file\n"); + d86f_log("86F: Error decompressing file\n"); remove(temp_file_name); return; } @@ -3186,7 +3202,7 @@ void d86f_load(int drive, char *fn) if (d86f[drive].disk_flags & 0x100) { /* Zoned disk. */ - pclog("86F: Disk is zoned (Apple or Sony)\n"); + d86f_log("86F: Disk is zoned (Apple or Sony)\n"); fclose(d86f[drive].f); if (d86f[drive].is_compressed) { @@ -3198,7 +3214,7 @@ void d86f_load(int drive, char *fn) if (d86f[drive].disk_flags & 0x600) { /* Zone type is not 0 but the disk is fixed-RPM. */ - pclog("86F: Disk is fixed-RPM but zone type is not 0\n"); + d86f_log("86F: Disk is fixed-RPM but zone type is not 0\n"); fclose(d86f[drive].f); if (d86f[drive].is_compressed) { @@ -3234,7 +3250,7 @@ void d86f_load(int drive, char *fn) if (!(d86f[drive].track_offset[0])) { /* File has no track 0 side 0, abort. */ - pclog("86F: No Track 0 side 0\n"); + d86f_log("86F: No Track 0 side 0\n"); fclose(d86f[drive].f); return; } @@ -3242,7 +3258,7 @@ void d86f_load(int drive, char *fn) if ((d86f_get_sides(drive) == 2) && !(d86f[drive].track_offset[1])) { /* File is 2-sided but has no track 0 side 1, abort. */ - pclog("86F: No Track 0 side 0\n"); + d86f_log("86F: No Track 0 side 0\n"); fclose(d86f[drive].f); return; } @@ -3306,7 +3322,7 @@ void d86f_load(int drive, char *fn) d86f_common_handlers(drive); drives[drive].format = d86f_format; - pclog("86F: Disk is %scompressed and %s surface description data\n", d86f[drive].is_compressed ? "" : "not ", d86f_has_surface_desc(drive) ? "has" : "does not have"); + d86f_log("86F: Disk is %scompressed and %s surface description data\n", d86f[drive].is_compressed ? "" : "not ", d86f_has_surface_desc(drive) ? "has" : "does not have"); } void d86f_init() diff --git a/src/dma.c b/src/dma.c index 969ffca34..d61e22cc3 100644 --- a/src/dma.c +++ b/src/dma.c @@ -565,34 +565,39 @@ int dma_channel_write(int channel, uint16_t val) return 0; } +#if 0 static uint32_t PageLengthReadWrite(uint32_t PhysAddress, uint32_t TotalSize) { uint32_t LengthSize; uint32_t Page; Page = PhysAddress & 4095; - LengthSize = (Page + 4096) - PhysAddress; - if (LengthSize > TotalSize) - LengthSize = TotalSize; - return LengthSize; + if ((Page + TotalSize - 1) >= 4096) + { + TotalSize = 4096 - Page; + } + + return TotalSize; } +#endif //DMA Bus Master Page Read/Write void DMAPageRead(uint32_t PhysAddress, void *DataRead, uint32_t TotalSize) { - uint32_t PageLen = PageLengthReadWrite(PhysAddress, TotalSize); - memcpy(DataRead, &ram[PhysAddress], PageLen); - DataRead -= PageLen; - TotalSize += PageLen; + // uint32_t PageLen = PageLengthReadWrite(PhysAddress, TotalSize); + memcpy(DataRead, &ram[PhysAddress], TotalSize); + // DataRead -= PageLen; + DataRead -= TotalSize; } void DMAPageWrite(uint32_t PhysAddress, const void *DataWrite, uint32_t TotalSize) { - uint32_t PageLen = PageLengthReadWrite(PhysAddress, TotalSize); - memcpy(&ram[PhysAddress], DataWrite, PageLen); - DataWrite -= PageLen; - TotalSize += PageLen; + // uint32_t PageLen = PageLengthReadWrite(PhysAddress, TotalSize); + memcpy(&ram[PhysAddress], DataWrite, TotalSize); + mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1); + // DataWrite -= PageLen; + DataWrite -= TotalSize; } int dma_mode(int channel) diff --git a/src/fdc.c b/src/fdc.c index 8760285bd..cf4bd3413 100644 --- a/src/fdc.c +++ b/src/fdc.c @@ -115,6 +115,23 @@ int discmodified[4]; int discrate[4]; int discint; + +int fdc_do_log = 1; + +void fdc_log(const char *format, ...) +{ +#ifdef ENABLE_FDC_LOG + if (fdc_do_log) + { + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + fflush(stdout); + } +#endif +} + void fdc_reset() { fdc.stat=0x80; @@ -128,7 +145,7 @@ void fdc_reset() fdc.rate = 2; // fdc_update_rate(); } -// pclog("Reset FDC\n"); +// fdc_log("Reset FDC\n"); } sector_id_t fdc_get_read_track_sector() @@ -282,7 +299,7 @@ void fdc_fifo_buf_advance() { fdc.fifobufpos++; } - // pclog("FIFO buffer position = %02X\n", fdc.fifobufpos); + // fdc_log("FIFO buffer position = %02X\n", fdc.fifobufpos); } void fdc_fifo_buf_write(int val) @@ -305,7 +322,7 @@ static void fdc_int() { if (fdc.dor & 8) { - // pclog("FDC interrupt!\n"); + // fdc_log("FDC interrupt!\n"); picint(1 << 6); fdc.fintr = 1; } @@ -321,7 +338,7 @@ static void fdc_watchdog_poll(void *p) fdc->watchdog_timer += 1000 * TIMER_USEC; else { -// pclog("Watchdog timed out\n"); +// fdc_log("Watchdog timed out\n"); fdc->watchdog_timer = 0; if (fdc->dor & 0x20) @@ -460,7 +477,7 @@ void fdc_update_rate(int drive) } fdc.bitcell_period = 1000000 / bit_rate*2; /*Bitcell period in ns*/ - // pclog("fdc_update_rate: rate=%i bit_rate=%i bitcell_period=%i\n", fdc.rate, bit_rate, fdc.bitcell_period); + // fdc_log("fdc_update_rate: rate=%i bit_rate=%i bitcell_period=%i\n", fdc.rate, bit_rate, fdc.bitcell_period); } int fdc_get_bit_rate() @@ -573,7 +590,7 @@ void fdc_implied_seek() void fdc_write(uint16_t addr, uint8_t val, void *priv) { -// pclog("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i %i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate, fdc.data_ready); +// fdc_log("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i %i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate, fdc.data_ready); int drive, i, drive_num; int seek_time, seek_time_base; @@ -591,7 +608,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) fdc.watchdog_timer = 1000 * TIMER_USEC; fdc.watchdog_count = 1000; picintc(1 << 6); -// pclog("watchdog set %i %i\n", fdc.watchdog_timer, TIMER_USEC); +// fdc_log("watchdog set %i %i\n", fdc.watchdog_timer, TIMER_USEC); } if ((val & 0x80) && !(fdc.dor & 0x80)) { @@ -686,10 +703,10 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) fdc.perp &= 0xfc; fdc_reset(); } - // pclog("DSR now: %02X\n", val); + // fdc_log("DSR now: %02X\n", val); return; case 5: /*Command register*/ - // pclog("CMD now: %02X\n", val); + // fdc_log("CMD now: %02X\n", val); if ((fdc.stat & 0xf0) == 0xb0) { if (fdc.pcjr || !fdc.fifo) @@ -705,8 +722,8 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) break; } // if (fdc.inread) -// rpclog("c82c711_fdc_write : writing while inread! %02X\n", val); -// rpclog("Write command reg %i %i\n",fdc.pnum, fdc.ptot); +// rfdc_log("c82c711_fdc_write : writing while inread! %02X\n", val); +// rfdc_log("Write command reg %i %i\n",fdc.pnum, fdc.ptot); if (fdc.pnum==fdc.ptot) { // if ((fdc.stat & 0x10) || !fdc.stat) @@ -723,7 +740,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) fdc.command=val; fdc.stat |= 0x10; - // pclog("Starting FDC command %02X\n",fdc.command); + fdc_log("Starting FDC command %02X\n",fdc.command); switch (fdc.command&0x1F) { case 1: /*Mode*/ @@ -793,7 +810,7 @@ void fdc_write(uint16_t addr, uint8_t val, void *priv) fdc.stat |= 0x90; break; case 8: /*Sense interrupt status*/ - // if (!fdc.fintr && !fdc_reset_stat) pclog("Attempted SENSE INTERRUPT STATUS without FINTR\n"); + // if (!fdc.fintr && !fdc_reset_stat) fdc_log("Attempted SENSE INTERRUPT STATUS without FINTR\n"); if (!fdc.fintr && !fdc_reset_stat) goto bad_command; // printf("Sense interrupt status %i\n",curdrive); fdc.lastdrive = fdc.drive; @@ -898,7 +915,7 @@ bad_command: } if (fdc.pnum==fdc.ptot) { - // pclog("Got all params %02X\n", fdc.command); + fdc_log("Got all params %02X\n", fdc.command); discint=fdc.command&0x1F; timer_process(); disctime = 1024 * (1 << TIMER_SHIFT); @@ -921,7 +938,7 @@ bad_command: fdc.read_track_sector.id.n = fdc.params[4]; fdc_implied_seek(); fdc.rw_track = fdc.params[1]; -// pclog("Read a track track=%i head=%i sector=%i eot=%i\n", fdc.pcn[fdc.params[0] & 3], fdc.head, fdc.sector, fdc.eot[fdc.drive]); +// fdc_log("Read a track track=%i head=%i sector=%i eot=%i\n", fdc.pcn[fdc.params[0] & 3], fdc.head, fdc.sector, fdc.eot[fdc.drive]); disc_readsector(fdc.drive, SECTOR_FIRST, fdc.params[1], fdc.head, fdc.rate, fdc.params[4]); if (fdc.pcjr || !fdc.dma) { @@ -955,7 +972,7 @@ bad_command: fdc.perp &= 0xfc; fdc.perp |= (fdc.params[0] & 0x03); } - // pclog("PERPENDICULAR: Set to: %02X\n", fdc.perp); + // fdc_log("PERPENDICULAR: Set to: %02X\n", fdc.perp); disctime = 0; return; @@ -1039,11 +1056,11 @@ bad_command: fdc.dtl = fdc.params[7]; fdc_implied_seek(); fdc.rw_track = fdc.params[1]; - // pclog("Reading sector (drive %i) (%i) (%i %i %i %i) (%i %i %i)\n", fdc.drive, fdc.params[0], fdc.params[1], fdc.params[2], fdc.params[3], fdc.params[4], fdc.params[5], fdc.params[6], fdc.params[7]); + fdc_log("Reading sector (drive %i) (%i) (%i %i %i %i) (%i %i %i)\n", fdc.drive, fdc.params[0], fdc.params[1], fdc.params[2], fdc.params[3], fdc.params[4], fdc.params[5], fdc.params[6], fdc.params[7]); if (((dma_mode(2) & 0x0C) == 0x00) && !fdc.pcjr && fdc.dma) { /* DMA is in verify mode, treat this like a VERIFY command. */ - // pclog("Verify-mode read!\n"); + fdc_log("Verify-mode read!\n"); fdc.tc = 1; fdc.deleted |= 2; } @@ -1103,12 +1120,12 @@ bad_command: fdc.gap = fdc.params[3]; fdc.dtl = 4000000; fdc.format_sectors = fdc.params[2]; - // pclog("Formatting with %i sectors per track\n", fdc.format_sectors); + // fdc_log("Formatting with %i sectors per track\n", fdc.format_sectors); fdc.format_n = fdc.params[1]; fdc.format_state = 1; fdc.pos = 0; fdc.stat = 0x10; - // pclog("FDC FORMAT: %02X %02X %02X %02X %02X\n", fdc.params[0], fdc.params[1], fdc.params[2], fdc.params[3], fdc.params[4]); + // fdc_log("FDC FORMAT: %02X %02X %02X %02X %02X\n", fdc.params[0], fdc.params[1], fdc.params[2], fdc.params[3], fdc.params[4]); break; case 0xf: /*Seek*/ @@ -1181,7 +1198,7 @@ bad_command: } else { - // pclog("Seeking to track %i...\n", fdc.params[1]); + fdc_log("Seeking to track %i...\n", fdc.params[1]); seek_time = ((int) (fdc.params[1] - fdc.pcn[fdc.params[0] & 3])) * seek_time_base * TIMER_USEC; if ((fdc.params[1] - fdc.pcn[fdc.params[0] & 3]) == 0) @@ -1233,7 +1250,7 @@ bad_command: case 7: if (!AT) return; fdc.rate=val&3; - // pclog("Rate now: %i\n", val & 3); + // fdc_log("Rate now: %i\n", val & 3); disc_3f7=val; return; @@ -1271,7 +1288,7 @@ uint8_t fdc_read(uint16_t addr, void *priv) break; case 2: temp = fdc.dor; - // pclog("Read DOR: %02X\n", fdc.dor); + // fdc_log("Read DOR: %02X\n", fdc.dor); break; case 3: drive = real_drive(fdc.dor & 3); @@ -1301,7 +1318,7 @@ uint8_t fdc_read(uint16_t addr, void *priv) return 0; } temp=fdc.stat; - // pclog("Read MSR: %02X\n", fdc.stat); + // fdc_log("Read MSR: %02X\n", fdc.stat); break; case 5: /*Data*/ fdc.stat&=~0x80; @@ -1313,15 +1330,15 @@ uint8_t fdc_read(uint16_t addr, void *priv) { temp = fdc_fifo_buf_read(); } - // pclog("Read DAT: %02X\n", temp); + // fdc_log("Read DAT: %02X\n", temp); break; } if (paramstogo) { paramstogo--; temp=fdc.res[10 - paramstogo]; - // pclog("Read result: %02X\n", temp); -// pclog("Read param %i %02X\n",10-paramstogo,temp); + // fdc_log("Read result: %02X\n", temp); +// fdc_log("Read param %i %02X\n",10-paramstogo,temp); if (!paramstogo) { fdc.stat=0x80; @@ -1339,7 +1356,7 @@ uint8_t fdc_read(uint16_t addr, void *priv) fdc.stat = 0x80; lastbyte=0; temp=fdc.dat; - // pclog("Read DAT: %02X\n", temp); + // fdc_log("Read DAT: %02X\n", temp); fdc.data_ready = 0; } /* What the heck is this even doing?! */ @@ -1363,7 +1380,7 @@ uint8_t fdc_read(uint16_t addr, void *priv) { temp |= 0x7F; } - // pclog("Read CCR: %02X\n", temp); + // fdc_log("Read CCR: %02X\n", temp); // printf("- DC %i %02X %02X %i %i - ",fdc.dor & 3, fdc.dor, 0x10 << (fdc.dor & 3), discchanged[fdc.dor & 1], driveempty[fdc.dor & 1]); // discchanged[fdc.dor&1]=0; break; @@ -1457,14 +1474,14 @@ void fdc_callback() int old_sector = 0; int bad_end = 0; disctime = 0; -// pclog("fdc_callback %i %i\n", discint, disctime); +// fdc_log("fdc_callback %i %i\n", discint, disctime); // if (fdc.inread) -// rpclog("c82c711_fdc_callback : while inread! %08X %i %02X %i\n", discint, fdc.drive, fdc.st0, ins); +// rfdc_log("c82c711_fdc_callback : while inread! %08X %i %02X %i\n", discint, fdc.drive, fdc.st0, ins); switch (discint) { case -3: /*End of command with interrupt*/ // if (output) printf("EOC - interrupt!\n"); -//rpclog("EOC\n"); +//rfdc_log("EOC\n"); fdc_int(); fdc.stat = (fdc.stat & 0xf) | 0x80; return; @@ -1472,7 +1489,7 @@ void fdc_callback() fdc.stat = (fdc.stat & 0xf) | 0x80; return; case -1: /*Reset*/ -//rpclog("Reset\n"); +//rfdc_log("Reset\n"); fdc_int(); fdc.fintr = 0; memset(fdc.pcn, 0, 4); @@ -1487,7 +1504,7 @@ void fdc_callback() readflash = 1; fdc.eot[fdc.drive]--; fdc.read_track_sector.id.r++; -// pclog("Read a track callback, eot=%i\n", fdc.eot[fdc.drive]); +// fdc_log("Read a track callback, eot=%i\n", fdc.eot[fdc.drive]); if (!fdc.eot[fdc.drive] || fdc.tc) { fdc_poll_readwrite_finish(2); @@ -1531,7 +1548,7 @@ void fdc_callback() case 0x19: /*Scan low or equal*/ case 0x1C: /*Verify*/ case 0x1D: /*Scan high or equal*/ -// rpclog("Read data %i\n", fdc.tc); +// rfdc_log("Read data %i\n", fdc.tc); if ((discint == 0x11) || (discint == 0x19) || (discint == 0x1D)) { compare = 1; @@ -1687,7 +1704,7 @@ void fdc_callback() return; case 8: /*Sense interrupt status*/ -// pclog("Sense interrupt status %i\n", fdc_reset_stat); +// fdc_log("Sense interrupt status %i\n", fdc_reset_stat); fdc.stat = (fdc.stat & 0xf) | 0xd0; @@ -1718,7 +1735,7 @@ void fdc_callback() fdc.res[10] = fdc.pcn[fdc.res[9] & 3]; - // pclog("SENSE INTERRUPT STATUS: Results %02X %02X, ST0 %02X\n", fdc.res[9], fdc.res[10], fdc.st0); + // fdc_log("SENSE INTERRUPT STATUS: Results %02X %02X, ST0 %02X\n", fdc.res[9], fdc.res[10], fdc.st0); paramstogo = 2; discint = 0; @@ -1726,7 +1743,7 @@ void fdc_callback() return; case 0x0d: /*Format track*/ -// rpclog("Format\n"); +// rfdc_log("Format\n"); if (fdc.format_state == 1) { // ioc_fiq(IOC_FIQ_DISC_DATA); @@ -1737,7 +1754,7 @@ void fdc_callback() } else if (fdc.format_state == 2) { - // pclog("Format next stage track %i head %i n %i is_mfm %i gap %i sc %i\n", fdc.pcn[fdc.params[0] & 3], fdc.head, fdc_get_format_n(), fdc_is_mfm(), fdc_get_gap(), fdc_get_format_sectors()); + // fdc_log("Format next stage track %i head %i n %i is_mfm %i gap %i sc %i\n", fdc.pcn[fdc.params[0] & 3], fdc.head, fdc_get_format_n(), fdc_is_mfm(), fdc_get_gap(), fdc_get_format_sectors()); disc_format(fdc.drive, fdc.head, fdc.rate, fdc.params[4]); fdc.format_state = 3; } @@ -1768,7 +1785,7 @@ void fdc_callback() disctime = 2048 * (1 << TIMER_SHIFT); timer_update_outstanding(); fdc.stat = 0x80 | (1 << fdc.drive); -// pclog("Stat %02X ST0 %02X\n", fdc.stat, fdc.st0); +// fdc_log("Stat %02X ST0 %02X\n", fdc.stat, fdc.st0); return; case 0x0e: /*Dump registers*/ fdc.stat = (fdc.stat & 0xf) | 0xd0; @@ -1807,8 +1824,8 @@ void fdc_callback() fdc.pretrk = fdc.params[2]; fdc.fifo = (fdc.params[1] & 0x20) ? 0 : 1; fdc.tfifo = (fdc.params[1] & 0xF) + 1; - // pclog("CONFIGURE (%02X, %02X, %02X)\n", fdc.params[0], fdc.params[1], fdc.params[2]); - // pclog("FIFO is now %02X, threshold is %02X\n", fdc.fifo, fdc.tfifo); + // fdc_log("CONFIGURE (%02X, %02X, %02X)\n", fdc.params[0], fdc.params[1], fdc.params[2]); + // fdc_log("FIFO is now %02X, threshold is %02X\n", fdc.fifo, fdc.tfifo); fdc.stat = 0x80; disctime = 0; // picint(0x40); @@ -1840,7 +1857,7 @@ void fdc_callback() case 0xfc: /*Invalid*/ fdc.dat = fdc.st0 = 0x80; -// pclog("Inv!\n"); +// fdc_log("Inv!\n"); //picint(0x40); fdc.stat = (fdc.stat & 0xf) | 0xd0; // fdc.stat|=0xC0; @@ -1922,7 +1939,7 @@ int fdc_data(uint8_t data) if (fdc.data_ready) { fdc_overrun(); -// pclog("Overrun\n"); +// fdc_log("Overrun\n"); return -1; } @@ -1983,7 +2000,7 @@ void fdc_finishread() { fdc.inread = 0; // disctime = 200 * TIMER_USEC; -// rpclog("fdc_finishread\n"); +// rfdc_log("fdc_finishread\n"); } void fdc_track_finishread(int condition) @@ -1992,7 +2009,7 @@ void fdc_track_finishread(int condition) fdc.satisfying_sectors |= condition; fdc.inread = 0; fdc_callback(); -// rpclog("fdc_finishread\n"); +// rfdc_log("fdc_finishread\n"); } void fdc_sector_finishcompare(int satisfying) @@ -2001,7 +2018,7 @@ void fdc_sector_finishcompare(int satisfying) fdc.satisfying_sectors++; fdc.inread = 0; fdc_callback(); -// rpclog("fdc_finishread\n"); +// rfdc_log("fdc_finishread\n"); } void fdc_sector_finishread() @@ -2009,7 +2026,7 @@ void fdc_sector_finishread() fdc.stat = 0x10; fdc.inread = 0; fdc_callback(); -// rpclog("fdc_finishread\n"); +// rfdc_log("fdc_finishread\n"); } #if 0 @@ -2017,7 +2034,7 @@ void fdc_notfound() { fdc_error(5, 0); -// rpclog("c82c711_fdc_notfound\n"); +// rfdc_log("c82c711_fdc_notfound\n"); } #endif @@ -2050,14 +2067,14 @@ void fdc_datacrcerror() { fdc_error(0x20, 0x20); -// rpclog("c82c711_fdc_datacrcerror\n"); +// rfdc_log("c82c711_fdc_datacrcerror\n"); } void fdc_headercrcerror() { fdc_error(0x20, 0); -// rpclog("c82c711_fdc_headercrcerror\n"); +// rfdc_log("c82c711_fdc_headercrcerror\n"); } void fdc_wrongcylinder() @@ -2084,7 +2101,7 @@ int fdc_getdata(int last) if (fdc.written) { fdc_overrun(); -// pclog("Overrun\n"); +// fdc_log("Overrun\n"); return -1; } if (fdc.pcjr || !fdc.fifo) @@ -2129,7 +2146,7 @@ int fdc_getdata(int last) void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2) { - // pclog("SectorID %i %i %i %i\n", track, side, sector, size); + // fdc_log("SectorID %i %i %i %i\n", track, side, sector, size); fdc_int(); fdc.stat=0xD0; fdc.res[4]=(fdd_get_head(real_drive(fdc.drive))?4:0)|fdc.drive; @@ -2145,7 +2162,7 @@ void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uin void fdc_indexpulse() { // ioc_irqa(IOC_IRQA_DISC_INDEX); -// rpclog("c82c711_fdc_indexpulse\n"); +// rfdc_log("c82c711_fdc_indexpulse\n"); } void fdc_init() diff --git a/src/ibm.h b/src/ibm.h index 02779a5ba..d9dffeec3 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -535,11 +535,7 @@ int keybsenddelay; /*CD-ROM*/ -extern int cdrom_drive; -extern int old_cdrom_drive; extern int idecallback[4]; -extern int cdrom_enabled; -extern int scsi_cdrom_enabled; #define CD_STATUS_EMPTY 0 #define CD_STATUS_DATA_ONLY 1 diff --git a/src/ide.c b/src/ide.c index 6aa901a1c..7e641a3e4 100644 --- a/src/ide.c +++ b/src/ide.c @@ -1,9 +1,6 @@ /* Copyright holders: Sarah Walker, Tenshi, SA1988 see COPYING for more details */ -#define CDROM_ISO 200 -#define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT)) - #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE #define _GNU_SOURCE @@ -16,6 +13,7 @@ #include #include "86box.h" +#include "cdrom.h" #include "ibm.h" #include "io.h" #include "pic.h" @@ -66,18 +64,14 @@ #define WIN_READ_NATIVE_MAX 0xF8 /** Evaluate to non-zero if the currently selected drive is an ATAPI device */ -#define IDE_DRIVE_IS_CDROM(ide) (ide->type == IDE_CDROM) +// #define IDE_DRIVE_IS_CDROM(ide) (ide->type == IDE_CDROM) #define ATAPI_STATUS_IDLE 0 #define ATAPI_STATUS_COMMAND 1 #define ATAPI_STATUS_COMPLETE 2 -#define ATAPI_STATUS_DATA 3 -#define ATAPI_STATUS_PACKET_REQ 4 -#define ATAPI_STATUS_PACKET_RECEIVED 5 -#define ATAPI_STATUS_READCD 6 -#define ATAPI_STATUS_REQ_SENSE 7 +#define ATAPI_STATUS_DATA_IN 3 +#define ATAPI_STATUS_DATA_OUT 4 #define ATAPI_STATUS_ERROR 0x80 -#define ATAPI_STATUS_ERROR_2 0x81 enum { @@ -123,59 +117,60 @@ uint64_t hdt[128][3] = { { 306, 4, 17 }, { 615, 2, 17 }, { 306, 4, 26 }, { { 1930, 4, 62 }, { 967, 16, 31 }, { 1013, 10, 63 }, { 1218, 15, 36 }, { 654, 16, 63 }, { 659, 16, 63 }, { 702, 16, 63 }, { 1002, 13, 63 }, /* 112-119 */ { 854, 16, 63 }, { 987, 16, 63 }, { 995, 16, 63 }, { 1024, 16, 63 }, { 1036, 16, 63 }, { 1120, 16, 59 }, { 1054, 16, 63 }, { 0, 0, 0 } }; /* 119-127 */ -typedef struct IDE -{ - int type; - int board; - uint8_t atastat; - uint8_t error; - int secount,sector,cylinder,head,drive,cylprecomp; - uint8_t command; - uint8_t fdisk; - int pos; - int packlen; - int spt,hpc; - int tracks; - int packetstatus; - uint8_t asc; - int reset; - FILE *hdfile; - uint16_t buffer[65536]; - int irqstat; - int service; - int lba; - uint32_t lba_addr; - int skip512; - int blocksize, blockcount; - uint16_t dma_identify_data[3]; - int hdi,base; - int hdc_num; -} IDE; - IDE ide_drives[IDE_NUM]; IDE *ext_ide; char ide_fn[IDE_NUM][512]; -int (*ide_bus_master_read_sector)(int channel, uint8_t *data); -int (*ide_bus_master_write_sector)(int channel, uint8_t *data); +int (*ide_bus_master_read)(int channel, uint8_t *data, int transfer_length); +int (*ide_bus_master_write)(int channel, uint8_t *data, int transfer_length); void (*ide_bus_master_set_irq)(int channel); -static void callnonreadcd(IDE *ide); -static void callreadcd(IDE *ide); +static void atapi_callback(IDE *ide); static void atapicommand(int ide_board); int idecallback[4] = {0, 0, 0, 0}; int cur_ide[4]; -int atapi_command = 0; +int ide_do_log = 1; -int atapi_cdrom_channel = 2; +void ide_log(const char *format, ...) +{ +#ifdef ENABLE_CDROM_LOG + if (ide_do_log) + { + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + fflush(stdout); + } +#endif +} uint8_t getstat(IDE *ide) { return ide->atastat; } +int ide_drive_is_cdrom(IDE *ide) +{ + if (atapi_cdrom_drives[ide->channel] >= CDROM_NUM) + { + return 0; + } + else + { + if (cdrom_drives[atapi_cdrom_drives[ide->channel]].enabled && !cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_type && (cdrom_drives[atapi_cdrom_drives[ide->channel]].bus_mode & 1)) + { + return 1; + } + else + { + return 0; + } + } +} + int image_is_hdi(const char *s) { int i, len; @@ -210,12 +205,12 @@ static inline void ide_irq_raise(IDE *ide) return; } - // pclog("Raising IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); + // ide_log("Raising IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); if (!(ide->fdisk&2)) { picint(1 << ide_irq[ide->board]); - // if (ide->board && !ide->irqstat) pclog("IDE_IRQ_RAISE\n"); + // if (ide->board && !ide->irqstat) ide_log("IDE_IRQ_RAISE\n"); if (ide->board < 2) { @@ -228,17 +223,17 @@ static inline void ide_irq_raise(IDE *ide) ide->irqstat=1; ide->service=1; - // pclog("raising interrupt %i\n", 14 + ide->board); + // ide_log("raising interrupt %i\n", 14 + ide->board); } -static inline void ide_irq_lower(IDE *ide) +void ide_irq_lower(IDE *ide) { if ((ide->board > 3) || !(ide->irqstat)) { return; } - // pclog("Lowering IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); + // ide_log("Lowering IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); picintc(1 << ide_irq[ide->board]); ide->irqstat=0; @@ -258,7 +253,7 @@ void ide_irq_update(IDE *ide) mask = ide_irq[ide->board]; mask &= 7; - // pclog("Updating IRQ %i (%i) (board %i)\n", ide_irq[ide->board], mask, ide->board); + // ide_log("Updating IRQ %i (%i) (board %i)\n", ide_irq[ide->board], mask, ide->board); pending = (pic2.pend | pic2.ins); pending &= (1 << mask); @@ -309,8 +304,7 @@ ide_padstr(char *str, const char *src, int len) * this length will be padded with spaces. * @param src Source string */ -static void -ide_padstr8(uint8_t *buf, int buf_size, const char *src) +void ide_padstr8(uint8_t *buf, int buf_size, const char *src) { int i; @@ -333,6 +327,10 @@ ide_padstr8(uint8_t *buf, int buf_size, const char *src) static void ide_identify(IDE *ide) { int c, h, s; + uint8_t device_identify[8] = { '8', '6', 'B', '_', 'H', 'D', '0', 0 }; + + device_identify[6] = ide->channel + 0x30; + ide_log("IDE Identify: %s\n", device_identify); memset(ide->buffer, 0, 512); @@ -347,7 +345,7 @@ static void ide_identify(IDE *ide) ide->buffer[6] = hdc[cur_ide[ide->board]].spt; /* Sectors */ ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ ide_padstr((char *) (ide->buffer + 23), emulator_version, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "86BoxHD", 40); /* Model */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ ide->buffer[20] = 3; /*Buffer type*/ ide->buffer[21] = 512; /*Buffer size*/ ide->buffer[47] = 16; /*Max sectors on multiple transfer command*/ @@ -386,13 +384,27 @@ static void ide_identify(IDE *ide) static void ide_atapi_identify(IDE *ide) { memset(ide->buffer, 0, 512); + uint8_t device_identify[8] = { '8', '6', 'B', '_', 'C', 'D', '0', 0 }; + uint8_t cdrom_id = atapi_cdrom_drives[ide->channel]; + + device_identify[6] = cdrom_id + 0x30; + ide_log("ATAPI Identify: %s\n", device_identify); ide->buffer[0] = 0x8000 | (5<<8) | 0x80 | (2<<5); /* ATAPI device, CD-ROM drive, removable media, accelerated DRQ */ ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ ide_padstr((char *) (ide->buffer + 23), emulator_version, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), "86BoxCD", 40); /* Model */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ ide->buffer[49] = 0x200; /* LBA supported */ ide->buffer[51] = 2 << 8; /*PIO timing mode*/ + + if ((ide->board < 2) && (cdrom_drives[cdrom_id].bus_mode & 2)) + { + ide->buffer[49] |= 0x100; /* DMA supported */ + ide->buffer[52] = 2 << 8; /*DMA timing mode*/ + ide->buffer[62] = ide->dma_identify_data[0]; + ide->buffer[63] = ide->dma_identify_data[1]; + ide->buffer[88] = ide->dma_identify_data[2]; + } } /* @@ -531,19 +543,51 @@ static void loadhd(IDE *ide, int d, const char *fn) void ide_set_signature(IDE *ide) { - ide->secount=1; + uint8_t cdrom_id = atapi_cdrom_drives[cur_ide[ide->board]]; ide->sector=1; ide->head=0; - ide->cylinder=(IDE_DRIVE_IS_CDROM(ide) ? 0xEB14 : ((ide->type == IDE_HDD) ? 0 : 0xFFFF)); - if (ide->type == IDE_HDD) + if (ide_drive_is_cdrom(ide)) { - ide->drive = 0; + cdrom_set_signature(cdrom_id); } + else + { + ide->secount=1; + ide->cylinder=((ide->type == IDE_HDD) ? 0 : 0xFFFF); + if (ide->type == IDE_HDD) + { + ide->drive = 0; + } + } +} + +int ide_cdrom_is_pio_only(IDE *ide) +{ + uint8_t cdrom_id = atapi_cdrom_drives[cur_ide[ide->board]]; + if (!ide_drive_is_cdrom(ide)) + { + return 0; + } + if (cdrom_drives[cdrom_id].bus_mode & 2) + { + return 0; + } + return 1; } int ide_set_features(IDE *ide) { - uint8_t val = ide->secount & 7; + uint8_t cdrom_id = cur_ide[ide->board]; + uint8_t val = 0; + + if (ide_drive_is_cdrom(ide)) + { + val = cdrom[cdrom_id].phase & 7; + } + else + { + val = ide->secount & 7; + } if (ide->type == IDE_NONE) return 0; @@ -578,7 +622,7 @@ int ide_set_features(IDE *ide) ide->dma_identify_data[2] = 0x3f; break; case 2: - if ((ide->type == IDE_CDROM) || (ide->board >= 2)) + if (ide_cdrom_is_pio_only(ide) || (ide->board >= 2)) { return 0; } @@ -587,7 +631,7 @@ int ide_set_features(IDE *ide) ide->dma_identify_data[2] = 0x3f; break; case 4: - if ((ide->type == IDE_CDROM) || (ide->board >= 2)) + if (ide_cdrom_is_pio_only(ide) || (ide->board >= 2)) { return 0; } @@ -624,32 +668,34 @@ void ide_set_sector(IDE *ide, int64_t sector_num) void resetide(void) { int d; + + build_atapi_cdrom_map(); /* Close hard disk image files (if previously open) */ for (d = 0; d < IDE_NUM; d++) { + ide_drives[d].channel = d; ide_drives[d].type = IDE_NONE; if (ide_drives[d].hdfile != NULL) { fclose(ide_drives[d].hdfile); ide_drives[d].hdfile = NULL; } + if (ide_drive_is_cdrom(&ide_drives[d])) + { + cdrom[atapi_cdrom_drives[d]].status = READY_STAT | DSC_STAT; + } ide_drives[d].atastat = READY_STAT | DSC_STAT; ide_drives[d].service = 0; ide_drives[d].board = d >> 1; } - page_flags[GPMODE_CDROM_AUDIO_PAGE] &= 0xFD; /* Clear changed flag for CDROM AUDIO mode page. */ - memset(mode_pages_in[GPMODE_CDROM_AUDIO_PAGE], 0, 256); /* Clear the page itself. */ - idecallback[0]=idecallback[1]=0; idecallback[2]=idecallback[3]=0; for (d = 0; d < IDE_NUM; d++) { - ide_drives[d].packetstatus = 0xFF; - - if ((atapi_cdrom_channel == d) && cdrom_enabled && !scsi_cdrom_enabled) + if (ide_drive_is_cdrom(&ide_drives[d])) { ide_drives[d].type = IDE_CDROM; } @@ -674,85 +720,67 @@ void resetide(void) { cur_ide[d] = d << 1; } - - page_flags[GPMODE_CDROM_AUDIO_PAGE] &= ~PAGE_CHANGED; - - SCSISense.UnitAttention = 0; } -int idetimes=0; +int idetimes = 0; + void writeidew(int ide_board, uint16_t val) { + int ret = 0; IDE *ide = &ide_drives[cur_ide[ide_board]]; #if 0 - if (ide->type == IDE_CDROM) + if (ide_drive_is_cdrom(ide)) { - pclog("CD-ROM write data: %04X\n", val); + ide_log("CD-ROM write data: %04X\n", val); } #endif - /* Some software issue excess writes after the 12 bytes required by the command, this will have all of them ignored. */ - if (ide->packetstatus && (ide->packetstatus != ATAPI_STATUS_PACKET_REQ)) - { - return; - } - - // pclog("Write IDEw %04X\n",val); + // ide_log("Write IDEw %04X\n",val); ide->buffer[ide->pos >> 1] = val; - ide->pos+=2; + ide->pos += 2; - if (ide->packetstatus == ATAPI_STATUS_PACKET_REQ) + if (ide->command == WIN_PACKETCMD) { - if ((ide->pos>=prefix_len+4) && (page_flags[page_current] & PAGE_CHANGEABLE)) + if (!ide_drive_is_cdrom(ide)) { - mode_pages_in[page_current][ide->pos - prefix_len - 4] = ((uint8_t *) ide->buffer)[ide->pos - 2]; - mode_pages_in[page_current][ide->pos - prefix_len - 3] = ((uint8_t *) ide->buffer)[ide->pos - 1]; + return; } - if (ide->pos>=(ide->packlen+2)) + + if (cdrom_write(cur_ide[ide_board], val)) { - ide->packetstatus = ATAPI_STATUS_PACKET_RECEIVED; + ide_irq_raise(ide); + } + + if (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback) + { + idecallback[ide_board] = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback; + } + return; + } + else + { + if (ide->pos>=512) + { + ide->pos=0; + ide->atastat = BUSY_STAT; timer_process(); - idecallback[ide_board]=6*IDE_TIME; + if (ide->command == WIN_WRITE_MULTIPLE) + { + callbackide(ide_board); + } + else + { + idecallback[ide_board]=6*IDE_TIME; + } timer_update_outstanding(); - // pclog("Packet over!\n"); - ide_irq_lower(ide); } - return; - } - else if (ide->packetstatus == ATAPI_STATUS_PACKET_RECEIVED) - { - return; - } - else if (ide->command == WIN_PACKETCMD && ide->pos>=0xC) - { - ide->pos=0; - ide->atastat = BUSY_STAT; - ide->packetstatus = ATAPI_STATUS_COMMAND; - timer_process(); - callbackide(ide_board); - timer_update_outstanding(); - } - else if (ide->pos>=512) - { - ide->pos=0; - ide->atastat = BUSY_STAT; - timer_process(); - if (ide->command == WIN_WRITE_MULTIPLE) - { - callbackide(ide_board); - } - else - { - idecallback[ide_board]=6*IDE_TIME; - } - timer_update_outstanding(); } } void writeidel(int ide_board, uint32_t val) { - // pclog("WriteIDEl %08X\n", val); + // ide_log("WriteIDEl %08X\n", val); writeidew(ide_board, val); writeidew(ide_board, val >> 16); } @@ -762,7 +790,7 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) IDE *ide = &ide_drives[cur_ide[ide_board]]; IDE *ide_other = &ide_drives[cur_ide[ide_board] ^ 1]; - // pclog("WriteIDE %04X %02X from %04X(%08X):%08X %i\n", addr, val, CS, cs, cpu_state.pc, ins); + ide_log("WriteIDE %04X %02X from %04X(%08X):%08X %i\n", addr, val, CS, cs, cpu_state.pc, ins); addr|=0x90; addr&=0xFFF7; @@ -774,14 +802,47 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) writeidew(ide_board, val | (val << 8)); return; - case 0x1F1: /* Features */ - ide->cylprecomp = val; - ide_other->cylprecomp = val; + /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ + case 0x1F1: /* Features */ + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].features = val; + } + else + { + ide->cylprecomp = val; + } + + if (ide_drive_is_cdrom(ide_other)) + { + cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].features = val; + } + else + { + ide_other->cylprecomp = val; + } return; case 0x1F2: /* Sector count */ - ide->secount = val; - ide_other->secount = val; + if (ide_drive_is_cdrom(ide)) + { + ide_log("Sector count write: %i\n", val); + cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].phase = val; + } + else + { + ide->secount = val; + } + + if (ide_drive_is_cdrom(ide_other)) + { + ide_log("Other sector count write: %i\n", val); + cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].phase = val; + } + else + { + ide_other->secount = val; + } return; case 0x1F3: /* Sector */ @@ -792,17 +853,51 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) return; case 0x1F4: /* Cylinder low */ - ide->cylinder = (ide->cylinder & 0xFF00) | val; - ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8); - ide_other->cylinder = (ide_other->cylinder&0xFF00) | val; - ide_other->lba_addr = (ide_other->lba_addr&0xFFF00FF) | (val << 8); + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length &= 0xFF00; + cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length |= val; + } + else + { + ide->cylinder = (ide->cylinder & 0xFF00) | val; + ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8); + } + + if (ide_drive_is_cdrom(ide_other)) + { + cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF00; + cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length |= val; + } + else + { + ide_other->cylinder = (ide_other->cylinder&0xFF00) | val; + ide_other->lba_addr = (ide_other->lba_addr&0xFFF00FF) | (val << 8); + } return; case 0x1F5: /* Cylinder high */ - ide->cylinder = (ide->cylinder & 0xFF) | (val << 8); - ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16); - ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8); - ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16); + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length &= 0xFF; + cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length |= (val << 8); + } + else + { + ide->cylinder = (ide->cylinder & 0xFF) | (val << 8); + ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16); + } + + if (ide_drive_is_cdrom(ide_other)) + { + cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length &= 0xFF; + cdrom[atapi_cdrom_drives[cur_ide[ide_board] ^ 1]].request_length |= (val << 8); + } + else + { + ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8); + ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16); + } return; case 0x1F6: /* Drive/Head */ @@ -820,13 +915,21 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) ide->cylinder = ide_other->cylinder = 0; ide->reset = ide_other->reset = 0; - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { - ide->cylinder=0xEB14; + cdrom[atapi_cdrom_drives[ide->channel]].status = READY_STAT | DSC_STAT; + cdrom[atapi_cdrom_drives[ide->channel]].error = 1; + cdrom[atapi_cdrom_drives[ide->channel]].phase = 1; + cdrom[atapi_cdrom_drives[ide->channel]].request_length = 0xEB14; + cdrom[atapi_cdrom_drives[ide->channel]].callback = 0; } - if (IDE_DRIVE_IS_CDROM(ide_other)) + if (ide_drive_is_cdrom(ide_other)) { - ide_other->cylinder=0xEB14; + cdrom[atapi_cdrom_drives[ide_other->channel]].status = READY_STAT | DSC_STAT; + cdrom[atapi_cdrom_drives[ide_other->channel]].error = 1; + cdrom[atapi_cdrom_drives[ide_other->channel]].phase = 1; + cdrom[atapi_cdrom_drives[ide_other->channel]].request_length = 0xEB14; + cdrom[atapi_cdrom_drives[ide_other->channel]].callback = 0; } idecallback[ide_board] = 0; @@ -851,40 +954,59 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case 0x1F7: /* Command register */ if (ide->type == IDE_NONE) { + if (val == WIN_SRST) + { + callbackide(ide_board); + } ide->error=1; return; } #if 0 - if (ide->type == IDE_CDROM) + if (ide_drive_is_cdrom(ide_other)) { - pclog("Write CD-ROM ATA command: %02X\n", val); + ide_log("Write CD-ROM ATA command: %02X\n", val); } #endif ide_irq_lower(ide); ide->command=val; - // pclog("New IDE command - %02X %i %i\n",ide->command,cur_ide[ide_board],ide_board); + // ide_log("New IDE command - %02X %i %i\n",ide->command,cur_ide[ide_board],ide_board); ide->error=0; switch (val) { case WIN_SRST: /* ATAPI Device Reset */ - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { - ide->atastat = BUSY_STAT; + cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; } else { ide->atastat = READY_STAT; } timer_process(); + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].callback = 100*IDE_TIME; + } idecallback[ide_board]=100*IDE_TIME; timer_update_outstanding(); return; case WIN_RESTORE: case WIN_SEEK: - ide->atastat = READY_STAT; + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].status = READY_STAT; + } + else + { + ide->atastat = READY_STAT; + } timer_process(); + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].callback = 100*IDE_TIME; + } idecallback[ide_board]=100*IDE_TIME; timer_update_outstanding(); return; @@ -900,14 +1022,25 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_READ: case WIN_READ_NORETRY: case WIN_READ_DMA: - ide->atastat = BUSY_STAT; + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; + } + else + { + ide->atastat = BUSY_STAT; + } timer_process(); + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME; + } idecallback[ide_board]=200*IDE_TIME; timer_update_outstanding(); return; case WIN_WRITE_MULTIPLE: - if (!ide->blocksize && (ide->type != IDE_CDROM)) + if (!ide->blocksize && !ide_drive_is_cdrom(ide)) { fatal("Write_MULTIPLE - blocksize = 0\n"); } @@ -915,33 +1048,83 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_WRITE: case WIN_WRITE_NORETRY: - ide->atastat = DRQ_STAT | DSC_STAT | READY_STAT; - ide->pos=0; + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].status = DRQ_STAT | DSC_STAT | READY_STAT; + cdrom[atapi_cdrom_drives[ide->channel]].pos = 0; + } + else + { + ide->atastat = DRQ_STAT | DSC_STAT | READY_STAT; + ide->pos=0; + } return; case WIN_WRITE_DMA: - ide->atastat = BUSY_STAT; + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; + } + else + { + ide->atastat = BUSY_STAT; + } timer_process(); + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME; + } idecallback[ide_board]=200*IDE_TIME; timer_update_outstanding(); return; case WIN_VERIFY: case WIN_VERIFY_ONCE: - ide->atastat = BUSY_STAT; + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; + } + else + { + ide->atastat = BUSY_STAT; + } timer_process(); + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME; + } idecallback[ide_board]=200*IDE_TIME; timer_update_outstanding(); return; case WIN_FORMAT: - ide->atastat = DRQ_STAT; - ide->pos=0; + if (ide_drive_is_cdrom(ide)) + { + // cdrom[atapi_cdrom_drives[ide->channel]].status = DRQ_STAT; + // cdrom[atapi_cdrom_drives[ide->channel]].pos = 0; + goto ide_bad_command; + } + else + { + ide->atastat = DRQ_STAT; + ide->pos=0; + } return; case WIN_SPECIFY: /* Initialize Drive Parameters */ - ide->atastat = BUSY_STAT; + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; + } + else + { + ide->atastat = BUSY_STAT; + } timer_process(); + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].callback = 30*IDE_TIME; + } idecallback[ide_board]=30*IDE_TIME; timer_update_outstanding(); return; @@ -953,8 +1136,19 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_STANDBYNOW1: case WIN_SETIDLE1: /* Idle */ case WIN_CHECKPOWERMODE1: - ide->atastat = BUSY_STAT; + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; + } + else + { + ide->atastat = BUSY_STAT; + } timer_process(); + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].callback = 30*IDE_TIME; + } idecallback[ide_board]=30*IDE_TIME; timer_update_outstanding(); return; @@ -962,34 +1156,53 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_IDENTIFY: /* Identify Device */ case WIN_SET_FEATURES: case WIN_READ_NATIVE_MAX: - ide->atastat = BUSY_STAT; + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; + } + else + { + ide->atastat = BUSY_STAT; + } timer_process(); + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].callback = 200*IDE_TIME; + } idecallback[ide_board]=200*IDE_TIME; timer_update_outstanding(); return; case WIN_PACKETCMD: /* ATAPI Packet */ -#if 0 - ide->packetstatus = ATAPI_STATUS_IDLE; - ide->atastat = BUSY_STAT; - timer_process(); - // idecallback[ide_board]=1;//30*IDE_TIME; - idecallback[ide_board]=30*IDE_TIME; - timer_update_outstanding(); - ide->pos=0; -#endif - /* Skip the command callbackwait, and process immediately. */ - ide->packetstatus = ATAPI_STATUS_IDLE; - readcdmode=0; - ide->pos=0; - ide->secount = 1; - ide->atastat = READY_STAT | DRQ_STAT |(ide->atastat&ERR_STAT); + /* Skip the command callback wait, and process immediately. */ + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].packet_status = CDROM_PHASE_IDLE; + cdrom[atapi_cdrom_drives[ide->channel]].pos=0; + cdrom[atapi_cdrom_drives[ide->channel]].phase = 1; + cdrom[atapi_cdrom_drives[ide->channel]].status = READY_STAT | DRQ_STAT | (cdrom[cur_ide[ide_board]].status & ERR_STAT); + } + else + { + ide->pos=0; + ide->secount = 1; + ide->atastat = READY_STAT | DRQ_STAT |(ide->atastat&ERR_STAT); + } return; case 0xF0: default: - ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; - ide->error = ABRT_ERR; +ide_bad_command: + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].status = READY_STAT | ERR_STAT | DSC_STAT; + cdrom[atapi_cdrom_drives[ide->channel]].error = ABRT_ERR; + } + else + { + ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; + ide->error = ABRT_ERR; + } ide_irq_raise(ide); return; } @@ -999,6 +1212,10 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) if ((ide->fdisk & 4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) { timer_process(); + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].callback = 500*IDE_TIME; + } idecallback[ide_board]=500*IDE_TIME; timer_update_outstanding(); @@ -1010,8 +1227,12 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) { ide->reset = 1; } + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[ide->channel]].status = BUSY_STAT; + } ide->atastat = ide_other->atastat = BUSY_STAT; - // pclog("IDE Reset %i\n", ide_board); + // ide_log("IDE Reset %i\n", ide_board); } ide->fdisk = ide_other->fdisk = val; ide_irq_update(ide); @@ -1025,6 +1246,8 @@ uint8_t readide(int ide_board, uint16_t addr) IDE *ide = &ide_drives[cur_ide[ide_board]]; uint8_t temp; uint16_t tempw; + + uint8_t temp2; addr|=0x90; addr&=0xFFF7; @@ -1045,7 +1268,10 @@ uint8_t readide(int ide_board, uint16_t addr) tempw = readidew(ide_board); temp = tempw & 0xff; break; - + + /* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested), + Bit 2 = ABRT (aborted command), Bit 1 = EOM (end of media), + and Bit 0 = ILI (illegal length indication). */ case 0x1F1: /* Error */ if (ide->type == IDE_NONE) { @@ -1053,10 +1279,30 @@ uint8_t readide(int ide_board, uint16_t addr) } else { - temp = ide->error; + if (ide_drive_is_cdrom(ide)) + { + temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].error; + } + else + { + temp = ide->error; + } } break; + /* For ATAPI: + Bit 0: Command or Data: + Data if clear, Command if set; + Bit 1: I/OB + Direction: + To device if set; + From device if clear. + IO DRQ CoD + 0 1 1 Ready to accept command packet + 1 1 1 Message - ready to send message to host + 1 1 0 Data to host + 0 1 0 Data from host + 1 0 1 Status. */ case 0x1F2: /* Sector count */ if (ide->type == IDE_NONE) { @@ -1064,7 +1310,14 @@ uint8_t readide(int ide_board, uint16_t addr) } else { - temp = (uint8_t)ide->secount; + if (ide_drive_is_cdrom(ide)) + { + temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].phase; + } + else + { + temp = ide->secount; + } } break; @@ -1086,7 +1339,14 @@ uint8_t readide(int ide_board, uint16_t addr) } else { - temp = (uint8_t)(ide->cylinder&0xFF); + if (ide_drive_is_cdrom(ide)) + { + temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length & 0xff; + } + else + { + temp = ide->cylinder & 0xff; + } } break; @@ -1097,7 +1357,14 @@ uint8_t readide(int ide_board, uint16_t addr) } else { - temp = (uint8_t)(ide->cylinder>>8); + if (ide_drive_is_cdrom(ide)) + { + temp = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].request_length >> 8; + } + else + { + temp = ide->cylinder >> 8; + } } break; @@ -1112,12 +1379,14 @@ uint8_t readide(int ide_board, uint16_t addr) } break; + /* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is + DF (drive fault). */ case 0x1F7: /* Status */ ide_irq_lower(ide); - if (ide->type == IDE_CDROM) + if (ide_drive_is_cdrom(ide)) { - temp = (ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - // pclog("Read CD-ROM status: %02X\n", temp); + temp = (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); + // ide_log("Read CD-ROM status: %02X\n", temp); } else { @@ -1131,9 +1400,10 @@ uint8_t readide(int ide_board, uint16_t addr) temp = DSC_STAT; break; } - if (ide->type == IDE_CDROM) + if (ide_drive_is_cdrom(ide)) { - temp = (ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); + temp = (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); + // ide_log("Read CD-ROM alternate status: %02X\n", temp); } else { @@ -1141,65 +1411,82 @@ uint8_t readide(int ide_board, uint16_t addr) } break; } - // /* if (ide_board) */ pclog("Read IDEb %04X %02X %02X %02X %i %04X:%04X %i\n", addr, temp, ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,cpu_state.pc,ide_board); + /* if (ide_board) */ ide_log("Read IDEb %04X %02X %02X %02X %i %04X:%04X %i\n", addr, temp, ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,cpu_state.pc,ide_board); return temp; // fatal("Bad IDE read %04X\n", addr); } +uint8_t cdb[16]; + +int old_len = 0; + +int total_read = 0; + +int block_total = 0; +int all_blocks_total = 0; + uint16_t readidew(int ide_board) { IDE *ide = &ide_drives[cur_ide[ide_board]]; uint16_t temp; - + temp = ide->buffer[ide->pos >> 1]; - ide->pos+=2; - if ((ide->command == WIN_PACKETCMD) && ((ide->packetstatus == ATAPI_STATUS_REQ_SENSE) || (ide->packetstatus==8))) + ide->pos += 2; + + if (ide->command == WIN_PACKETCMD) { - callnonreadcd(ide); - return temp; + if (!ide_drive_is_cdrom(ide)) + { + ide_log("Drive not CD-ROM (position: %i)\n", ide->pos); + return 0; + } + temp = cdrom_read(cur_ide[ide_board]); + if (cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback) + { + idecallback[ide_board] = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback; + } } - if ((ide->pos>=512 && ide->command != WIN_PACKETCMD) || (ide->command == WIN_PACKETCMD && ide->pos>=ide->packlen)) + if (ide->pos>=512 && ide->command != WIN_PACKETCMD) { ide->pos=0; - if (ide->command == WIN_PACKETCMD)// && ide.packetstatus==6) + ide->atastat = READY_STAT | DSC_STAT; + if (ide_drive_is_cdrom(ide)) { - callreadcd(ide); + // cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].pos = 0; + cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].status = READY_STAT | DSC_STAT; + cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].packet_status = CDROM_PHASE_IDLE; } - else + ide->packetstatus = ATAPI_STATUS_IDLE; + if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY || ide->command == WIN_READ_MULTIPLE) { - ide->atastat = READY_STAT | DSC_STAT; - ide->packetstatus = ATAPI_STATUS_IDLE; - if (ide->command == WIN_READ || ide->command == WIN_READ_NORETRY || ide->command == WIN_READ_MULTIPLE) + ide->secount = (ide->secount - 1) & 0xff; + if (ide->secount) { - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) + ide_next_sector(ide); + ide->atastat = BUSY_STAT; + timer_process(); + if (ide->command == WIN_READ_MULTIPLE) { - ide_next_sector(ide); - ide->atastat = BUSY_STAT; - timer_process(); - if (ide->command == WIN_READ_MULTIPLE) - { - callbackide(ide_board); - } - else - { - idecallback[ide_board]=6*IDE_TIME; - } - timer_update_outstanding(); + callbackide(ide_board); } + else + { + idecallback[ide_board]=6*IDE_TIME; + } + timer_update_outstanding(); } } } - // pclog("Read IDEw %04X\n",temp); + // ide_log("Read IDEw %04X\n",temp); return temp; } uint32_t readidel(int ide_board) { uint16_t temp; - // pclog("Read IDEl %i\n", ide_board); + // ide_log("Read IDEl %i\n", ide_board); temp = readidew(ide_board); return temp | (readidew(ide_board) << 16); } @@ -1214,9 +1501,15 @@ void callbackide(int ide_board) int c; ext_ide = ide; int64_t snum; + int cdrom_id; + if (ide_drive_is_cdrom(ide)) + { + cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback = 0; + } + if (ide->command==0x30) times30++; - // /*if (ide_board) */pclog("CALLBACK %02X %i %i %i\n",ide->command,times30,ide->reset,cur_ide[ide_board]); + /*if (ide_board) */ide_log("CALLBACK %02X %i %i %i\n",ide->command,times30,ide->reset,cur_ide[ide_board]); if (ide->reset) { @@ -1228,30 +1521,44 @@ void callbackide(int ide_board) ide->cylinder = ide_other->cylinder = 0; ide->reset = ide_other->reset = 0; - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { - ide->cylinder=0xEB14; - cdrom->stop(); + cdrom_id = atapi_cdrom_drives[cur_ide[ide_board]]; + cdrom[cdrom_id].status = READY_STAT | DSC_STAT; + cdrom[cdrom_id].error = 1; + cdrom[cdrom_id].phase = 1; + cdrom[cdrom_id].request_length=0xEB14; + if (cdrom_drives[cdrom_id].handler->stop) + { + cdrom_drives[cdrom_id].handler->stop(cdrom_id); + } } if (ide->type == IDE_NONE) { ide->cylinder=0xFFFF; - cdrom->stop(); } - if (IDE_DRIVE_IS_CDROM(ide_other)) + if (ide_drive_is_cdrom(ide_other)) { - ide_other->cylinder=0xEB14; - cdrom->stop(); + cdrom_id = atapi_cdrom_drives[cur_ide[ide_board] ^ 1]; + cdrom[cdrom_id].status = READY_STAT | DSC_STAT; + cdrom[cdrom_id].error = 1; + cdrom[cdrom_id].phase = 1; + cdrom[cdrom_id].request_length=0xEB14; + if (cdrom_drives[cdrom_id].handler->stop) + { + cdrom_drives[cdrom_id].handler->stop(cdrom_id); + } } if (ide_other->type == IDE_NONE) { ide_other->cylinder=0xFFFF; - cdrom->stop(); } - // pclog("Reset callback\n"); + // ide_log("Reset callback\n"); return; } + cdrom_id = atapi_cdrom_drives[cur_ide[ide_board]]; + switch (ide->command) { /* Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, @@ -1262,12 +1569,12 @@ void callbackide(int ide_board) ide->secount = ide->sector = 1; ide_set_signature(ide); - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { - ide->atastat = 0; + cdrom_reset(cdrom_id); } ide_irq_raise(ide); - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { ide->service = 0; } @@ -1275,19 +1582,26 @@ void callbackide(int ide_board) case WIN_RESTORE: case WIN_SEEK: - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { goto abort_cmd; } case WIN_NOP: case WIN_STANDBYNOW1: case WIN_SETIDLE1: - ide->atastat = READY_STAT | DSC_STAT; + if (ide_drive_is_cdrom(ide)) + { + cdrom[cdrom_id].status = READY_STAT | DSC_STAT; + } + else + { + ide->atastat = READY_STAT | DSC_STAT; + } ide_irq_raise(ide); return; case WIN_CHECKPOWERMODE1: - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1298,7 +1612,7 @@ void callbackide(int ide_board) case WIN_READ: case WIN_READ_NORETRY: - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { ide_set_signature(ide); goto abort_cmd; @@ -1316,7 +1630,7 @@ void callbackide(int ide_board) return; case WIN_READ_DMA: - if (IDE_DRIVE_IS_CDROM(ide) || (ide->board >= 2)) + if (ide_drive_is_cdrom(ide) || (ide->board >= 2)) { goto abort_cmd; } @@ -1325,9 +1639,9 @@ void callbackide(int ide_board) fread(ide->buffer, 512, 1, ide->hdfile); ide->pos=0; - if (ide_bus_master_read_sector) + if (ide_bus_master_read) { - if (ide_bus_master_read_sector(ide_board, (uint8_t *)ide->buffer)) + if (ide_bus_master_read(ide_board, (uint8_t *)ide->buffer, 512)) { idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ } @@ -1360,7 +1674,7 @@ void callbackide(int ide_board) command has been executed or when Read Multiple commands are disabled, the Read Multiple operation is rejected with an Aborted Com- mand error. */ - if (IDE_DRIVE_IS_CDROM(ide) || !ide->blocksize) + if (ide_drive_is_cdrom(ide) || !ide->blocksize) { goto abort_cmd; } @@ -1372,7 +1686,7 @@ void callbackide(int ide_board) ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; if (!ide->blockcount) { - // pclog("Read multiple int\n"); + // ide_log("Read multiple int\n"); ide_irq_raise(ide); } ide->blockcount++; @@ -1386,7 +1700,7 @@ void callbackide(int ide_board) case WIN_WRITE: case WIN_WRITE_NORETRY: - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1410,14 +1724,14 @@ void callbackide(int ide_board) return; case WIN_WRITE_DMA: - if (IDE_DRIVE_IS_CDROM(ide) || (ide_board >= 2)) + if (ide_drive_is_cdrom(ide) || (ide_board >= 2)) { goto abort_cmd; } - if (ide_bus_master_write_sector) + if (ide_bus_master_write) { - if (ide_bus_master_write_sector(ide_board, (uint8_t *)ide->buffer)) + if (ide_bus_master_write(ide_board, (uint8_t *)ide->buffer, 512)) { idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ } @@ -1448,7 +1762,7 @@ void callbackide(int ide_board) return; case WIN_WRITE_MULTIPLE: - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1478,7 +1792,7 @@ void callbackide(int ide_board) case WIN_VERIFY: case WIN_VERIFY_ONCE: - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1489,12 +1803,12 @@ void callbackide(int ide_board) return; case WIN_FORMAT: - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { goto abort_cmd; } addr = ide_get_sector(ide) * 512; - // pclog("Format cyl %i head %i offset %08X %08X %08X secount %i\n",ide.cylinder,ide.head,addr,addr>>32,addr,ide.secount); + // ide_log("Format cyl %i head %i offset %08X %08X %08X secount %i\n",ide.cylinder,ide.head,addr,addr>>32,addr,ide.secount); fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); memset(ide->buffer, 0, 512); for (c=0;csecount;c++) @@ -1511,9 +1825,9 @@ void callbackide(int ide_board) ide_set_signature(ide); ide->error=1; /*No error detected*/ - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { - ide->atastat = 0; + cdrom[cdrom_id].status = 0; } else { @@ -1523,7 +1837,7 @@ void callbackide(int ide_board) return; case WIN_SPECIFY: /* Initialize Drive Parameters */ - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1534,25 +1848,26 @@ void callbackide(int ide_board) return; case WIN_PIDENTIFY: /* Identify Packet Device */ - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { ide_atapi_identify(ide); - ide->pos=0; - ide->error=0; - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + ide->pos = 0; + cdrom[cdrom_id].pos = 0; + cdrom[cdrom_id].error = 0; + cdrom[cdrom_id].status = DRQ_STAT | READY_STAT | DSC_STAT; ide_irq_raise(ide); return; } goto abort_cmd; case WIN_SET_MULTIPLE_MODE: - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { goto abort_cmd; } ide->blocksize = ide->secount; ide->atastat = READY_STAT | DSC_STAT; - // pclog("Set multiple mode - %i\n", ide->blocksize); + // ide_log("Set multiple mode - %i\n", ide->blocksize); ide_irq_raise(ide); return; @@ -1561,12 +1876,19 @@ void callbackide(int ide_board) { goto abort_cmd; } - ide->atastat = READY_STAT | DSC_STAT; + if (ide_drive_is_cdrom(ide)) + { + cdrom[cdrom_id].status = READY_STAT | DSC_STAT; + } + else + { + ide->atastat = READY_STAT | DSC_STAT; + } ide_irq_raise(ide); return; case WIN_READ_NATIVE_MAX: - if (ide->type != IDE_HDD) + if ((ide->type != IDE_HDD) || ide_drive_is_cdrom(ide)) { goto abort_cmd; } @@ -1584,7 +1906,7 @@ void callbackide(int ide_board) ide_set_signature(ide); goto abort_cmd; } - if (IDE_DRIVE_IS_CDROM(ide)) + if (ide_drive_is_cdrom(ide)) { ide_set_signature(ide); goto abort_cmd; @@ -1599,83 +1921,34 @@ void callbackide(int ide_board) return; case WIN_PACKETCMD: /* ATAPI Packet */ - if (!IDE_DRIVE_IS_CDROM(ide)) + if (!ide_drive_is_cdrom(ide)) { goto abort_cmd; } - if (ide->packetstatus == ATAPI_STATUS_IDLE) + if (cdrom_phase_callback(atapi_cdrom_drives[cur_ide[ide_board]])) { - // pclog("ATAPI_STATUS_IDLE\n"); - readcdmode=0; - ide->pos=0; - ide->secount = 1; - ide->atastat = READY_STAT | DRQ_STAT |(ide->atastat&ERR_STAT); - } - else if (ide->packetstatus == ATAPI_STATUS_COMMAND) - { - // pclog("ATAPI_STATUS_COMMAND\n"); - ide->atastat = BUSY_STAT|(ide->atastat&ERR_STAT); - atapicommand(ide_board); - } - else if (ide->packetstatus == ATAPI_STATUS_COMPLETE) - { - // pclog("ATAPI_STATUS_COMPLETE\n"); - ide->atastat = READY_STAT; - ide->secount=3; - ide_irq_raise(ide); - } - else if (ide->packetstatus == ATAPI_STATUS_DATA) - { - // pclog("ATAPI_STATUS_DATA\n"); - ide->atastat = READY_STAT|DRQ_STAT|(ide->atastat&ERR_STAT); - ide_irq_raise(ide); - ide->packetstatus=0xFF; - } - else if (ide->packetstatus == ATAPI_STATUS_PACKET_REQ) - { - // pclog("ATAPI_STATUS_PACKET_REQ\n"); - ide->atastat = 0x58 | (ide->atastat & ERR_STAT); - ide_irq_raise(ide); - ide->pos=2; - } - else if (ide->packetstatus == ATAPI_STATUS_PACKET_RECEIVED) - { - // pclog("ATAPI_STATUS_PACKET_RECEIVED\n"); - atapicommand(ide_board); - } - else if (ide->packetstatus == ATAPI_STATUS_READCD) /*READ CD callback*/ - { - // pclog("ATAPI_STATUS_READCD\n"); - ide->atastat = DRQ_STAT|(ide->atastat&ERR_STAT); - ide_irq_raise(ide); - } - else if (ide->packetstatus == ATAPI_STATUS_REQ_SENSE) /*REQUEST SENSE callback #1*/ - { - // pclog("ATAPI_STATUS_REQ_SENSE\n"); - ide->atastat = 0x58 | (ide->atastat & ERR_STAT); - ide_irq_raise(ide); - } - else if (ide->packetstatus == ATAPI_STATUS_ERROR) /*Error callback*/ - { - // pclog("ATAPI_STATUS_ERROR\n"); - ide->atastat = READY_STAT | ERR_STAT; - ide_irq_raise(ide); - } - else if (ide->packetstatus == ATAPI_STATUS_ERROR_2) /*Error callback with atastat already set - needed for the disc change stuff.*/ - { - // pclog("ATAPI_STATUS_ERROR_2\n"); - ide->atastat = ERR_STAT; ide_irq_raise(ide); } + idecallback[ide_board] = cdrom[atapi_cdrom_drives[cur_ide[ide_board]]].callback; + ide_log("IDE callback now: %i\n", idecallback[ide_board]); return; } abort_cmd: ide->command = 0; - ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; - ide->error = ABRT_ERR; - ide->pos = 0; + if (ide_drive_is_cdrom(ide)) + { + cdrom[cdrom_id].status = READY_STAT | ERR_STAT | DSC_STAT; + cdrom[cdrom_id].error = ABRT_ERR; + cdrom[cdrom_id].pos = 0; + } + else + { + ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; + ide->error = ABRT_ERR; + ide->pos = 0; + } ide_irq_raise(ide); } @@ -1703,1253 +1976,6 @@ void ide_callback_qua() callbackide(3); } -/*ATAPI CD-ROM emulation*/ -uint8_t atapi_prev; -int toctimes=0; - -void atapi_command_send_init(IDE *ide, uint8_t command, int req_length, int alloc_length) -{ - if (ide->cylinder == 0xffff) - { - ide->cylinder = 0xfffe; - } - - if ((ide->cylinder & 1) && !(alloc_length <= ide->cylinder)) - { - ide->cylinder--; - } - - if (alloc_length < 0) - { - fatal("Allocation length < 0\n"); - } - if (alloc_length == 0) - { - alloc_length = ide->cylinder; - } - - /* No atastat setting: PCem actually emulates the callback cycle. */ - if (alloc_length != 0) - { - ide->secount = 2; - } - - // no bytes transferred yet - ide->pos = 0; - - if ((ide->cylinder > req_length) || (ide->cylinder == 0)) - { - ide->cylinder = req_length; - } - if (ide->cylinder > alloc_length) - { - ide->cylinder = alloc_length; - } -} - -static void atapi_command_ready(int ide_board, int packlen) -{ - IDE *ide = &ide_drives[cur_ide[ide_board]]; - ide->packetstatus = ATAPI_STATUS_REQ_SENSE; - idecallback[ide_board]=60*IDE_TIME; - ide->packlen=packlen; -} - -static void atapi_sense_clear(int command, int ignore_ua) -{ - if ((SCSISense.SenseKey == SENSE_UNIT_ATTENTION) || ignore_ua) - { - atapi_prev=command; - SCSISense.SenseKey=0; - SCSISense.Asc=0; - SCSISense.Ascq=0; - } -} - -void atapi_cmd_error(IDE *ide, uint8_t sensekey, uint8_t asc, uint8_t ascq) -{ - ide->error = (sensekey << 4) | ABRT_ERR; - if (SCSISense.UnitAttention) - { - ide->error |= MCR_ERR; - } - ide->atastat = READY_STAT | ERR_STAT; - ide->secount = (ide->secount & ~7) | 3; - ide->packetstatus = 0x80; - idecallback[ide->board]=50*IDE_TIME; -} - -static void atapi_not_ready(IDE *ide) -{ - SCSISense.SenseKey = SENSE_NOT_READY; - SCSISense.Asc = ASC_MEDIUM_NOT_PRESENT; - SCSISense.Ascq = 0; - atapi_cmd_error(ide, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); -} - -static void atapi_illegal_opcode(IDE *ide) -{ - SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_ILLEGAL_OPCODE; - SCSISense.Ascq = 0; - atapi_cmd_error(ide, SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0); -} - -static void atapi_invalid_field(IDE *ide) -{ - SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_INV_FIELD_IN_CMD_PACKET; - SCSISense.Ascq = 0; - atapi_cmd_error(ide, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0); - ide->atastat = 0x53; -} - -static void atapi_illegal_mode(IDE *ide) -{ - SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; - SCSISense.Ascq = 0; - atapi_cmd_error(ide, SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_MODE_FOR_THIS_TRACK, 0); -} - -static void atapi_incompatible_format(IDE *ide) -{ - SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_INCOMPATIBLE_FORMAT; - SCSISense.Ascq = 0; - atapi_cmd_error(ide, SENSE_ILLEGAL_REQUEST, ASC_INCOMPATIBLE_FORMAT, 0); -} - -static void atapi_data_phase_error(IDE *ide) -{ - SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_DATA_PHASE_ERROR; - SCSISense.Ascq = 0; - atapi_cmd_error(ide, SENSE_ILLEGAL_REQUEST, ASC_DATA_PHASE_ERROR, 0); -} - -static void atapicommand(int ide_board) -{ - IDE *ide = &ide_drives[cur_ide[ide_board]]; - uint8_t *idebufferb = (uint8_t *) ide->buffer; - uint8_t rcdmode = 0; - int c; - int len; - int msf; - int pos=0; - unsigned char temp; - uint32_t size; - uint8_t page_code; - int max_len; - unsigned idx = 0; - unsigned size_idx; - unsigned preamble_len; - int toc_format; - int temp_command; - int alloc_length; - int completed; - uint8_t index = 0; - int media; - int format; - int ret; - int real_pos; - int track = 0; - uint8_t cdb[12]; - -#if 0 - pclog("ATAPI command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, %i, Unit attention: %i\n",idebufferb[0],SCSISense.SenseKey,SCSISense.Asc,SCSISense.Ascq,ins,SCSISense.UnitAttention); - - int CdbLength; - for (CdbLength = 1; CdbLength < 12; CdbLength++) - { - pclog("ATAPI CDB[%d] = 0x%02X\n", CdbLength, idebufferb[CdbLength]); - } -#endif - - memcpy(cdb, idebufferb, 12); - - msf=idebufferb[1]&2; - SectorLen=0; - - if (cdrom->medium_changed()) - { - // pclog("Medium has changed...\n"); - SCSICDROM_Insert(); - } - - if (!cdrom->ready() && SCSISense.UnitAttention) - { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - SCSISense.UnitAttention = 0; - } - - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ - if (SCSISense.UnitAttention == 1) - { - // pclog("Unit attention now 2\n"); - SCSISense.UnitAttention = 2; - if (!(SCSICommandTable[idebufferb[0]] & ALLOW_UA)) - { - // pclog("UNIT ATTENTION: Command not allowed to pass through\n"); - atapi_cmd_error(ide, SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - return; - } - } - else if (SCSISense.UnitAttention == 2) - { - if (idebufferb[0]!=GPCMD_REQUEST_SENSE) - { - // pclog("Unit attention now 0\n"); - SCSISense.UnitAttention = 0; - } - } - - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ - if (idebufferb[0]!=GPCMD_REQUEST_SENSE) - { - atapi_sense_clear(idebufferb[0], 1); - } - - /* Next it's time for NOT READY. */ - if ((SCSICommandTable[idebufferb[0]] & CHECK_READY) && !cdrom->ready()) - { - atapi_not_ready(ide); - return; - } - - // pclog("Continuing with command\n"); - - prev_status = cd_status; - cd_status = cdrom->status(); - if (((prev_status == CD_STATUS_PLAYING) || (prev_status == CD_STATUS_PAUSED)) && ((cd_status != CD_STATUS_PLAYING) && (cd_status != CD_STATUS_PAUSED))) - { - completed = 1; - } - else - { - completed = 0; - } - - switch (idebufferb[0]) - { - case GPCMD_TEST_UNIT_READY: - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - break; - - case GPCMD_REQUEST_SENSE: /* Used by ROS 4+ */ - alloc_length = idebufferb[4]; - temp_command = idebufferb[0]; - - /*Will return 18 bytes of 0*/ - if (alloc_length != 0) - { - memset(idebufferb, 0, alloc_length); - } - - idebufferb[0]=0x80|0x70; - - if ((SCSISense.SenseKey > 0) && ((cd_status < CD_STATUS_PLAYING) || (cd_status == CD_STATUS_STOPPED))) - { - if (completed) - { - idebufferb[2]=SENSE_ILLEGAL_REQUEST; - idebufferb[12]=ASC_AUDIO_PLAY_OPERATION; - idebufferb[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; - } - else - { - idebufferb[2]=SCSISense.SenseKey; - idebufferb[12]=SCSISense.Asc; - idebufferb[13]=SCSISense.Ascq; - } - } - else if ((SCSISense.SenseKey == 0) && (cd_status >= CD_STATUS_PLAYING) && (cd_status != CD_STATUS_STOPPED)) - { - idebufferb[2]=SENSE_ILLEGAL_REQUEST; - idebufferb[12]=ASC_AUDIO_PLAY_OPERATION; - idebufferb[13]=(cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; - } - else - { - if (SCSISense.UnitAttention) - { - idebufferb[2]=SENSE_UNIT_ATTENTION; - idebufferb[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - idebufferb[13]=0; - } - } - - // pclog("Reporting sense: %02X %02X %02X\n", idebufferb[2], idebufferb[12], idebufferb[13]); - - idebufferb[7]=10; - - if (idebufferb[2] == SENSE_UNIT_ATTENTION) - { - /* If the last remaining sense is unit attention, clear - that condition. */ - SCSISense.UnitAttention = 0; - } - - /* Clear the sense stuff as per the spec. */ - atapi_sense_clear(temp_command, 0); - - if (alloc_length == 0) - { - // pclog("REQUEST SENSE - empty allocation\n"); - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - } - else - { - atapi_command_send_init(ide, temp_command, 18, alloc_length); - atapi_command_ready(ide_board, 18); - } - break; - - case GPCMD_SET_SPEED: - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - break; - - case GPCMD_MECHANISM_STATUS: - len=(idebufferb[7]<<16)|(idebufferb[8]<<8)|idebufferb[9]; - - memset(idebufferb, 0, 8); - idebufferb[5] = 1; - - if (len == 0) - { - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - } - else - { - atapi_command_send_init(ide, cdb[0], 8, alloc_length); - atapi_command_ready(ide_board, 8); - } - break; - - case GPCMD_READ_TOC_PMA_ATIP: - toctimes++; - toc_format = idebufferb[2] & 0xf; - - if (toc_format == 0) - { - toc_format = (idebufferb[9]>>6) & 3; - } - - switch (toc_format) - { - case 0: /*Normal*/ - len=idebufferb[8]+(idebufferb[7]<<8); - len=cdrom->readtoc(idebufferb,idebufferb[6],msf,len,0); - break; - case 1: /*Multi session*/ - len=idebufferb[8]+(idebufferb[7]<<8); - len=cdrom->readtoc_session(idebufferb,msf,len); - idebufferb[0]=0; idebufferb[1]=0xA; - break; - case 2: /*Raw*/ - len=idebufferb[8]+(idebufferb[7]<<8); - len=cdrom->readtoc_raw(idebufferb,msf,len); - break; - default: - atapi_invalid_field(ide); - return; - } - - ide->packetstatus = ATAPI_STATUS_DATA; - ide->cylinder=len; - ide->secount=2; - ide->pos=0; - idecallback[ide_board]=60*IDE_TIME; - ide->packlen=len; - // pclog("READ_TOC_PMA_ATIP format %02X, length %i (%i)\n", toc_format, ide->cylinder, idebufferb[1]); - - if (len == 0) - { - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - } - return; - - case GPCMD_READ_CD: - case GPCMD_READ_CD_MSF: - // pclog("Read CD : start LBA %02X%02X%02X%02X Length %02X%02X%02X Flags %02X\n",idebufferb[2],idebufferb[3],idebufferb[4],idebufferb[5],idebufferb[6],idebufferb[7],idebufferb[8],idebufferb[9]); - if (idebufferb[0] == GPCMD_READ_CD_MSF) - { - SectorLBA=MSFtoLBA(idebufferb[3],idebufferb[4],idebufferb[5]); - SectorLen=MSFtoLBA(idebufferb[6],idebufferb[7],idebufferb[8]); - - SectorLen -= SectorLBA; - SectorLen++; - - cdrom_sector_ismsf = 1; - } - else - { - SectorLen=(idebufferb[6]<<16)|(idebufferb[7]<<8)|idebufferb[8]; - SectorLBA=(idebufferb[2]<<24)|(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5]; - - cdrom_sector_ismsf = 0; - } - - cdrom_sector_type = (idebufferb[1] >> 2) & 7; - cdrom_sector_flags = idebufferb[9] || (((uint32_t) idebufferb[10]) << 8); - - if (SectorLBA > (cdrom->size() - 1)) - { - // pclog("Trying to read beyond the end of disc\n"); - atapi_invalid_field(ide); - break; - } - - ret = cdrom_read_data(idebufferb); - - if (!ret) - { - atapi_invalid_field(ide); - break; - } - - readflash=1; - - SectorLBA++; - SectorLen--; - if (SectorLen >= 0) - { - ide->packetstatus = ATAPI_STATUS_READCD; - } - else - { - ide->packetstatus = ATAPI_STATUS_DATA; - } - ide->cylinder=cdrom_sector_size; - ide->secount=2; - ide->pos=0; - idecallback[ide_board]=60*IDE_TIME; - ide->packlen=cdrom_sector_size; - return; - - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - // pclog("Read 10 : start LBA %02X%02X%02X%02X Length %02X%02X%02X Flags %02X\n",idebufferb[2],idebufferb[3],idebufferb[4],idebufferb[5],idebufferb[6],idebufferb[7],idebufferb[8],idebufferb[9]); - cdrom_sector_ismsf = 0; - - if (idebufferb[0] == GPCMD_READ_6) - { - SectorLen=idebufferb[4]; - SectorLBA=((((uint32_t) idebufferb[1]) & 0x1f)<<16)|(((uint32_t) idebufferb[2])<<8)|((uint32_t) idebufferb[3]); - } - else if (idebufferb[0] == GPCMD_READ_10) - { - SectorLen=(idebufferb[7]<<8)|idebufferb[8]; - SectorLBA=(idebufferb[2]<<24)|(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5]; - } - else - { - SectorLen=(((uint32_t) idebufferb[6])<<24)|(((uint32_t) idebufferb[7])<<16)|(((uint32_t) idebufferb[8])<<8)|((uint32_t) idebufferb[9]); - SectorLBA=(((uint32_t) idebufferb[2])<<24)|(((uint32_t) idebufferb[3])<<16)|(((uint32_t) idebufferb[4])<<8)|((uint32_t) idebufferb[5]); - } - - // pclog("Reading sector: %i, length: %i\n", SectorLen, SectorLBA); - - if (SectorLBA > (cdrom->size() - 1)) - { - // pclog("Trying to read beyond the end of disc\n"); - atapi_invalid_field(ide); - break; - } - - if (!SectorLen) - { - // pclog("All done - callback set\n"); - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=20*IDE_TIME; - break; - } - - cdrom_sector_type = 6; - cdrom_sector_flags = 0x10; - - ret = cdrom_read_data(idebufferb); - - if (!ret) - { - atapi_invalid_field(ide); - break; - } - - readflash=1; - SectorLBA++; - SectorLen--; - if (SectorLen >= 0) - { - ide->packetstatus = ATAPI_STATUS_READCD; - } - else - { - ide->packetstatus = ATAPI_STATUS_DATA; - } - ide->cylinder=2048; - ide->secount=2; - ide->pos=0; - idecallback[ide_board]=60*IDE_TIME; - ide->packlen=2048; - return; - - case GPCMD_READ_HEADER: - if (cdrom->read_header) - { - cdrom->read_header(idebufferb, idebufferb); - } - else - { - SectorLen=(idebufferb[7]<<8)|idebufferb[8]; - SectorLBA=(idebufferb[2]<<24)|(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5]; - if (msf) - { - real_pos = cdrom_LBAtoMSF_accurate(ide); - } - else - { - real_pos = SectorLBA; - } - idebufferb[4] = (real_pos >> 24); - idebufferb[5] = ((real_pos >> 16) & 0xff); - idebufferb[6] = ((real_pos >> 8) & 0xff); - idebufferb[7] = real_pos & 0xff; - idebufferb[0]=1; /*2048 bytes user data*/ - idebufferb[1]=idebufferb[2]=idebufferb[3]=0; - } - - len = 8; - ide->packetstatus = ATAPI_STATUS_DATA; - ide->cylinder=8; - ide->secount=2; - ide->pos=0; - idecallback[ide_board]=60*IDE_TIME; - ide->packlen=8; - return; - - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - temp_command = idebufferb[0]; - - if (temp_command == GPCMD_MODE_SENSE_6) - { - len=idebufferb[4]; - } - else - { - len=(idebufferb[8]|(idebufferb[7]<<8)); - } - - temp=idebufferb[2] & 0x3F; - - memset(idebufferb, 0, len); - alloc_length = len; - - if (!(mode_sense_pages[temp] & IMPLEMENTED)) - { - atapi_invalid_field(ide); - return; - } - - if (temp_command == GPCMD_MODE_SENSE_6) - { - len = SCSICDROMModeSense(idebufferb,4,temp); - if (len > alloc_length) - { - len = alloc_length; - } - idebufferb[0] = len - 1; - idebufferb[1]=3; /*120mm data CD-ROM*/ - } - else - { - len = SCSICDROMModeSense(idebufferb,8,temp); - if (len > alloc_length) - { - len = alloc_length; - } - idebufferb[0]=(len - 2)>>8; - idebufferb[1]=(len - 2)&255; - idebufferb[2]=3; /*120mm data CD-ROM*/ - } - - atapi_command_send_init(ide, temp_command, len, alloc_length); - - atapi_command_ready(ide_board, len); - - if (len == 0) - { - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - } - return; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - if (ide->packetstatus == ATAPI_STATUS_PACKET_RECEIVED) - { - ide->atastat = READY_STAT; - ide->secount=3; - // pclog("Recieve data packet!\n"); - ide_irq_raise(ide); - ide->packetstatus=0xFF; - ide->pos=0; - } - else - { - if (idebufferb[0] == GPCMD_MODE_SELECT_6) - { - len=idebufferb[4]; - prefix_len = 6; - } - else - { - len=(idebufferb[7]<<8)|idebufferb[8]; - prefix_len = 10; - } - page_current = idebufferb[2]; - if (page_flags[page_current] & PAGE_CHANGEABLE) - { - page_flags[page_current] |= PAGE_CHANGED; - } - ide->packetstatus = ATAPI_STATUS_PACKET_REQ; - ide->cylinder=len; - ide->secount=0; - ide->pos=0; - idecallback[ide_board]=60*IDE_TIME; - ide->packlen=len; - - if (len == 0) - { - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - } - } - return; - - case GPCMD_GET_CONFIGURATION: - temp_command = idebufferb[0]; - /* XXX: could result in alignment problems in some architectures */ - len = (idebufferb[7]<<8)|idebufferb[8]; - alloc_length = len; - - index = 0; - - /* only feature 0 is supported */ - if (idebufferb[2] != 0 || idebufferb[3] != 0) - { - atapi_invalid_field(ide); - return; - } - - /* - * XXX: avoid overflow for io_buffer if len is bigger than - * the size of that buffer (dimensioned to max number of - * sectors to transfer at once) - * - * Only a problem if the feature/profiles grow. - */ - if (alloc_length > 512) /* XXX: assume 1 sector */ - { - alloc_length = 512; - } - - memset(idebufferb, 0, alloc_length); - /* - * the number of sectors from the media tells us which profile - * to use as current. 0 means there is no media - */ - if (len > CD_MAX_SECTORS) - { - idebufferb[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; - idebufferb[7] = MMC_PROFILE_DVD_ROM & 0xff; - } - else if (len <= CD_MAX_SECTORS) - { - idebufferb[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; - idebufferb[7] = MMC_PROFILE_CD_ROM & 0xff; - } - idebufferb[10] = 0x02 | 0x01; /* persistent and current */ - alloc_length = 12; /* headers: 8 + 4 */ - alloc_length += SCSICDROMSetProfile(idebufferb, &index, MMC_PROFILE_DVD_ROM); - alloc_length += SCSICDROMSetProfile(idebufferb, &index, MMC_PROFILE_CD_ROM); - idebufferb[0] = ((alloc_length-4) >> 24) & 0xff; - idebufferb[1] = ((alloc_length-4) >> 16) & 0xff; - idebufferb[2] = ((alloc_length-4) >> 8) & 0xff; - idebufferb[3] = (alloc_length-4) & 0xff; - - if (len == 0) - { - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - } - else - { - atapi_command_send_init(ide, temp_command, len, alloc_length); - atapi_command_ready(ide_board, len); - } - break; - - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: - gesn_cdb = (void *)idebufferb; - gesn_event_header = (void *)idebufferb; - - /* It is fine by the MMC spec to not support async mode operations. */ - if (!(gesn_cdb->polled & 0x01)) - { /* asynchronous mode */ - /* Only polling is supported, asynchronous mode is not. */ - atapi_invalid_field(ide); - return; - } - - /* polling mode operation */ - - /* - * These are the supported events. - * - * We currently only support requests of the 'media' type. - * Notification class requests and supported event classes are bitmasks, - * but they are built from the same values as the "notification class" - * field. - */ - gesn_event_header->supported_events = 1 << GESN_MEDIA; - - /* - * We use |= below to set the class field; other bits in this byte - * are reserved now but this is useful to do if we have to use the - * reserved fields later. - */ - gesn_event_header->notification_class = 0; - - /* - * Responses to requests are to be based on request priority. The - * notification_class_request_type enum above specifies the - * priority: upper elements are higher prio than lower ones. - */ - if (gesn_cdb->class & (1 << GESN_MEDIA)) - { - gesn_event_header->notification_class |= GESN_MEDIA; - used_len = SCSICDROMEventStatus(idebufferb); - } - else - { - gesn_event_header->notification_class = 0x80; /* No event available */ - used_len = sizeof(*gesn_event_header); - } - gesn_event_header->len = used_len - sizeof(*gesn_event_header); - - atapi_command_send_init(ide, cdb[0], used_len, used_len); - atapi_command_ready(ide_board, used_len); - break; - - case GPCMD_READ_DISC_INFORMATION: - if (cdrom->read_disc_information) - { - cdrom->read_disc_information(idebufferb); - } - else - { - memset(idebufferb, 0, 34); - memset(idebufferb, 1, 9); - idebufferb[0] = 0; - idebufferb[1] = 32; - idebufferb[2] = 0xe; /* last session complete, disc finalized */ - idebufferb[7] = 0x20; /* unrestricted use */ - idebufferb[8] = 0x00; /* CD-ROM */ - } - - len=34; - if (len > alloc_length) - { - len = alloc_length; - } - - if (len == 0) - { - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - } - else - { - ide->packetstatus = ATAPI_STATUS_DATA; - ide->secount=2; - ide->cylinder=len; - ide->pos=0; - ide->packlen=len; - idecallback[ide_board]=60*IDE_TIME; - } - break; - - case GPCMD_READ_TRACK_INFORMATION: - max_len = idebufferb[7]; - max_len <<= 8; - max_len |= idebufferb[8]; - - track = ((uint32_t) idebufferb[2]) << 24; - track |= ((uint32_t) idebufferb[3]) << 16; - track |= ((uint32_t) idebufferb[4]) << 8; - track |= (uint32_t) idebufferb[5]; - - if (cdrom->read_track_information) - { - ret = cdrom->read_track_information(idebufferb, idebufferb); - - if (!ret) - { - atapi_invalid_field(ide); - return; - } - - len = idebufferb[0]; - len <<= 8; - len |= idebufferb[1]; - len += 2; - } - else - { - if (((idebufferb[1] & 0x03) != 1) || (track != 1)) - { - atapi_invalid_field(ide); - return; - } - - len = 36; - - memset(idebufferb, 0, 36); - idebufferb[1] = 34; - idebufferb[2] = 1; /* track number (LSB) */ - idebufferb[3] = 1; /* session number (LSB) */ - idebufferb[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ - idebufferb[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ - idebufferb[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ - idebufferb[24] = (cdrom->size() >> 24) & 0xff; /* track size */ - idebufferb[25] = (cdrom->size() >> 16) & 0xff; /* track size */ - idebufferb[26] = (cdrom->size() >> 8) & 0xff; /* track size */ - idebufferb[27] = cdrom->size() & 0xff; /* track size */ - } - - if (len > max_len) - { - len = max_len; - idebufferb[0] = ((max_len - 2) >> 8) & 0xff; - idebufferb[1] = (max_len - 2) & 0xff; - } - - if (len == 0) - { - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - } - else - { - ide->packetstatus = ATAPI_STATUS_DATA; - ide->cylinder=len; - ide->secount=2; - ide->pos=0; - idecallback[ide_board]=60*IDE_TIME; - ide->packlen=len; - } - break; - - case GPCMD_PLAY_AUDIO_10: - case GPCMD_PLAY_AUDIO_12: - case GPCMD_PLAY_AUDIO_MSF: - if (idebufferb[0] == GPCMD_PLAY_AUDIO_10) - { - pos=(idebufferb[2]<<24)|(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5]; - len=(idebufferb[7]<<8)|idebufferb[8]; - } - else if (idebufferb[0] == GPCMD_PLAY_AUDIO_MSF) - { - /* This is apparently deprecated in the ATAPI spec, and apparently - has been since 1995 (!). Hence I'm having to guess most of it. */ - pos=(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5]; - len=(idebufferb[6]<<16)|(idebufferb[7]<<8)|idebufferb[8]; - } - else - { - pos=(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5]; - len=(idebufferb[7]<<16)|(idebufferb[8]<<8)|idebufferb[9]; - } - - if ((cdrom_drive < 1) || (cdrom_drive == CDROM_ISO) || (cd_status <= CD_STATUS_DATA_ONLY) || - !cdrom->is_track_audio(pos, (idebufferb[0] == GPCMD_PLAY_AUDIO_MSF) ? 1 : 0)) - { - atapi_illegal_mode(ide); - break; - } - - cdrom->playaudio(pos, len, (idebufferb[0] == GPCMD_PLAY_AUDIO_MSF) ? 1 : 0); - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - break; - - case GPCMD_READ_SUBCHANNEL: - if (idebufferb[3] > 3) - { - // pclog("Read subchannel check condition %02X\n",idebufferb[3]); - atapi_invalid_field(ide); - break; - } - - switch(idebufferb[3]) - { - case 0: - alloc_length = 4; - break; - case 1: - alloc_length = 16; - break; - default: - alloc_length = 24; - break; - } - - if (cdrom->read_subchannel) - { - cdrom->read_subchannel(idebufferb, idebufferb); - len = alloc_length; - } - else - { - temp = idebufferb[3] & 3; - temp |= (idebufferb[2] & 0x40); - memset(idebufferb, 24, 0); - pos = 0; - idebufferb[pos++]=0; - idebufferb[pos++]=0; /*Audio status*/ - idebufferb[pos++]=0; idebufferb[pos++]=0; /*Subchannel length*/ - idebufferb[pos++]=temp & 3; /*Format code*/ - if ((temp & 3) == 1) - { - idebufferb[1]=cdrom->getcurrentsubchannel(&idebufferb[5],msf); - } - if (!(temp & 0x40) || ((temp & 3) == 0)) - { - len=4; - } - else - { - len = alloc_length; - } - } - ide->packetstatus = ATAPI_STATUS_DATA; - ide->cylinder=len; - ide->secount=2; - ide->pos=0; - idecallback[ide_board]=1000*IDE_TIME; - ide->packlen=len; - break; - - case GPCMD_READ_DVD_STRUCTURE: - temp_command = idebufferb[0]; - media = idebufferb[1]; - format = idebufferb[7]; - - len = (((uint32_t) idebufferb[6])<<24)|(((uint32_t) idebufferb[7])<<16)|(((uint32_t) idebufferb[8])<<8)|((uint32_t) idebufferb[9]); - alloc_length = len; - - if (format < 0xff) - { - if (len <= CD_MAX_SECTORS) - { - atapi_incompatible_format(ide); - break; - } - else - { - atapi_invalid_field(ide); - return; - } - } - - memset(idebufferb, 0, (alloc_length > 256 * 512 + 4) ? (256 * 512 + 4) : alloc_length); - - switch (format) - { - case 0x00 ... 0x7f: - case 0xff: - - if (media == 0) - { - ret = SCSICDROMReadDVDStructure(format, idebufferb, idebufferb); - - if (ret < 0) - { - atapi_cmd_error(ide, SENSE_ILLEGAL_REQUEST, -ret, 0); - } - else - { - atapi_command_send_init(ide, temp_command, len, alloc_length); - atapi_command_ready(ide_board, len); - } - break; - } - /* TODO: BD support, fall through for now */ - - /* Generic disk structures */ - case 0x80: /* TODO: AACS volume identifier */ - case 0x81: /* TODO: AACS media serial number */ - case 0x82: /* TODO: AACS media identifier */ - case 0x83: /* TODO: AACS media key block */ - case 0x90: /* TODO: List of recognized format layers */ - case 0xc0: /* TODO: Write protection status */ - default: - atapi_invalid_field(ide); - return; - } - break; - - case GPCMD_START_STOP_UNIT: - switch(idebufferb[4] & 3) - { - case 0: /* Stop the disc. */ - cdrom->stop(); - break; - case 1: /* Start the disc and read the TOC. */ - cdrom->medium_changed(); /* This causes a TOC reload. */ - break; - case 2: /* Eject the disc if possible. */ - cdrom->stop(); -#ifndef __unix - win_cdrom_eject(); -#endif - break; - case 3: /* Load the disc (close tray). */ -#ifndef __unix - win_cdrom_reload(); -#else - cdrom->load(); -#endif - break; - } - - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - break; - - case GPCMD_INQUIRY: - page_code = idebufferb[2]; - max_len = idebufferb[4]; - alloc_length = max_len; - temp_command = idebufferb[0]; - - if (idebufferb[1] & 1) - { - preamble_len = 4; - size_idx = 3; - - idebufferb[idx++] = 05; - idebufferb[idx++] = page_code; - idebufferb[idx++] = 0; - - idx++; - - switch (page_code) - { - case 0x00: - idebufferb[idx++] = 0x00; - idebufferb[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) - { - atapi_data_phase_error(ide); - return; - } - - idebufferb[idx++] = 0x02; - idebufferb[idx++] = 0x00; - idebufferb[idx++] = 0x00; - idebufferb[idx++] = 20; - ide_padstr8(idebufferb + idx, 20, "53R141"); /* Serial */ - idx += 20; - - if (idx + 72 > max_len) - { - goto atapi_out; - } - idebufferb[idx++] = 0x02; - idebufferb[idx++] = 0x01; - idebufferb[idx++] = 0x00; - idebufferb[idx++] = 68; - ide_padstr8(idebufferb + idx, 8, "86Box"); /* Vendor */ - idx += 8; - ide_padstr8(idebufferb + idx, 40, "86BoxCD v1.0"); /* Product */ - idx += 40; - ide_padstr8(idebufferb + idx, 20, "53R141"); /* Product */ - idx += 20; - break; - default: - atapi_invalid_field(ide); - return; - } - } - else - { - preamble_len = 5; - size_idx = 4; - - memset(idebufferb, 0, 8); - idebufferb[0] = 5; /*CD-ROM*/ - idebufferb[1] = 0x80; /*Removable*/ - idebufferb[3] = 0x21; - idebufferb[4] = 31; - - ide_padstr8(idebufferb + 8, 8, "86Box"); /* Vendor */ - ide_padstr8(idebufferb + 16, 16, "86BoxCD"); /* Product */ - ide_padstr8(idebufferb + 32, 4, emulator_version); /* Revision */ - idx = 36; - } - -atapi_out: - idebufferb[size_idx] = idx - preamble_len; - len=idx; - if (len > alloc_length) - { - len = alloc_length; - } - - if (len == 0) - { - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - } - else - { - atapi_command_send_init(ide, temp_command, len, alloc_length); - atapi_command_ready(ide_board, len); - } - break; - - case GPCMD_PREVENT_REMOVAL: - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - break; - - case GPCMD_PAUSE_RESUME: - if (idebufferb[8] & 1) - { - cdrom->resume(); - } - else - { - cdrom->pause(); - } - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - break; - - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - if (idebufferb[0] == GPCMD_SEEK_6) - { - pos=(idebufferb[2]<<8)|idebufferb[3]; - } - else - { - pos=(idebufferb[2]<<24)|(idebufferb[3]<<16)|(idebufferb[4]<<8)|idebufferb[5]; - } - cdrom->seek(pos); - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - break; - - case GPCMD_READ_CDROM_CAPACITY: - atapi_command_send_init(ide, temp_command, 8, 8); - if (cdrom->read_capacity) - { - cdrom->read_capacity(idebufferb); - } - else - { - size = cdrom->size() - 1; /* IMPORTANT: What's returned is the last LBA block. */ - memset(idebufferb, 0, 8); - idebufferb[0] = (size >> 24) & 0xff; - idebufferb[1] = (size >> 16) & 0xff; - idebufferb[2] = (size >> 8) & 0xff; - idebufferb[3] = size & 0xff; - idebufferb[6] = 8; /* 2048 = 0x0800 */ - } - len=8; - atapi_command_ready(ide_board, len); - break; - - case GPCMD_STOP_PLAY_SCAN: - cdrom->stop(); - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - break; - - default: - atapi_illegal_opcode(ide); - break; - } - - // pclog("SCSI phase: %02X, length: %i\n", ide->secount, ide->cylinder); -} - -static void callnonreadcd(IDE *ide) /* Callabck for non-Read CD commands */ -{ - ide_irq_lower(ide); - if (ide->pos >= ide->packlen) - { - // pclog("Command finished, setting callback\n"); - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide->board]=20*IDE_TIME; - } - else - { - // pclog("Command not finished, keep sending data\n"); - ide->atastat = BUSY_STAT; - ide->packetstatus = ATAPI_STATUS_REQ_SENSE; - ide->cylinder=2; - ide->secount=2; - idecallback[ide->board]=60*IDE_TIME; - } -} - -static void callreadcd(IDE *ide) -{ - int ret; - - ide_irq_lower(ide); - if (SectorLen<=0) - { - // pclog("All done - callback set\n"); - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide->board]=20*IDE_TIME; - return; - } - // pclog("Continue readcd! %i blocks left\n",SectorLen); - // pclog("Reading sector: %i, length: %i\n", SectorLen, SectorLBA); - ide->atastat = BUSY_STAT; - - ret = cdrom_read_data((uint8_t *) ide->buffer); - readflash=1; - - SectorLBA++; - SectorLen--; - ide->packetstatus = ATAPI_STATUS_READCD; - ide->cylinder=cdrom_sector_size; - ide->secount=2; - ide->pos=0; - idecallback[ide->board]=60*IDE_TIME; - ide->packlen=cdrom_sector_size; -} - - void ide_write_pri(uint16_t addr, uint8_t val, void *priv) { writeide(0, addr, val); @@ -3120,15 +2146,15 @@ void ide_init() { ide_pri_enable(); ide_sec_enable(); - ide_bus_master_read_sector = ide_bus_master_write_sector = NULL; + ide_bus_master_read = ide_bus_master_write = NULL; timer_add(ide_callback_pri, &idecallback[0], &idecallback[0], NULL); timer_add(ide_callback_sec, &idecallback[1], &idecallback[1], NULL); } -void ide_set_bus_master(int (*read_sector)(int channel, uint8_t *data), int (*write_sector)(int channel, uint8_t *data), void (*set_irq)(int channel)) +void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length), int (*write)(int channel, uint8_t *data, int transfer_length), void (*set_irq)(int channel)) { - ide_bus_master_read_sector = read_sector; - ide_bus_master_write_sector = write_sector; + ide_bus_master_read = read; + ide_bus_master_write = write; ide_bus_master_set_irq = set_irq; } diff --git a/src/ide.h b/src/ide.h index c25fa5ce5..0bd0fcac0 100644 --- a/src/ide.h +++ b/src/ide.h @@ -4,7 +4,35 @@ #ifndef __IDE__ #define __IDE__ -struct IDE; +typedef struct IDE +{ + int type; + int board; + uint8_t atastat; + uint8_t error; + int secount,sector,cylinder,head,drive,cylprecomp; + uint8_t command; + uint8_t fdisk; + int pos; + int packlen; + int spt,hpc; + int tracks; + int packetstatus; + uint8_t asc; + int reset; + FILE *hdfile; + uint16_t buffer[65536]; + int irqstat; + int service; + int lba; + int channel; + uint32_t lba_addr; + int skip512; + int blocksize, blockcount; + uint16_t dma_identify_data[3]; + int hdi,base; + int hdc_num; +} IDE; extern void writeide(int ide_board, uint16_t addr, uint8_t val); extern void writeidew(int ide_board, uint16_t val); @@ -23,7 +51,7 @@ extern void ide_pri_disable(); extern void ide_sec_disable(); extern void ide_ter_disable(); extern void ide_qua_disable(); -extern void ide_set_bus_master(int (*read_sector)(int channel, uint8_t *data), int (*write_sector)(int channel, uint8_t *data), void (*set_irq)(int channel)); +extern void ide_set_bus_master(int (*read)(int channel, uint8_t *data, int transfer_length), int (*write)(int channel, uint8_t *data, int transfer_length), void (*set_irq)(int channel)); extern int ideboard; @@ -34,6 +62,13 @@ extern int idecallback[4]; extern char ide_fn[IDE_NUM][512]; -extern int atapi_cdrom_channel; +void ide_irq_lower(IDE *ide); + +IDE ide_drives[IDE_NUM]; + +void ide_padstr8(uint8_t *buf, int buf_size, const char *src); + +void win_cdrom_eject(uint8_t id); +void win_cdrom_reload(uint8_t id); #endif //__IDE__ diff --git a/src/model.c b/src/model.c index 1b9868484..64562f7a2 100644 --- a/src/model.c +++ b/src/model.c @@ -1,7 +1,11 @@ /* Copyright holders: Sarah Walker see COPYING for more details */ +#include +#include + #include "ibm.h" +#include "cdrom.h" #include "cpu.h" #include "mem.h" #include "model.h" @@ -403,11 +407,28 @@ void at_opti495_init() opti495_init(); } +void secondary_ide_check() +{ + int i = 0; + int secondary_cdroms = 0; + + for (i = 0; i < CDROM_NUM; i++) + { + if ((cdrom_drives[i].ide_channel >= 2) && (cdrom_drives[i].ide_channel <= 3) && !cdrom_drives[i].bus_type) + { + secondary_cdroms++; + } + if (!secondary_cdroms) ide_sec_disable(); + } +} + void at_ali1429_init() { + at_init(); ali1429_init(); - if (atapi_cdrom_channel <= 1) ide_sec_disable(); + + secondary_ide_check(); } /* void at_um8881f_init() @@ -422,7 +443,7 @@ void at_dtk486_init() at_init(); memregs_init(); sis85c471_init(); - if (atapi_cdrom_channel <= 1) ide_sec_disable(); + secondary_ide_check(); } void at_sis496_init() @@ -464,7 +485,7 @@ void at_586mc1_init() i430lx_init(); sio_init(1); device_add(&intel_flash_bxt_device); - if (atapi_cdrom_channel <= 1) ide_sec_disable(); + secondary_ide_check(); } void at_plato_init() diff --git a/src/mouse.h b/src/mouse.h index 29a19b78e..c91cf25ff 100644 --- a/src/mouse.h +++ b/src/mouse.h @@ -10,6 +10,8 @@ int mouse_get_type(int mouse); #define MOUSE_TYPE_AMSTRAD 2 #define MOUSE_TYPE_OLIM24 3 +#define MOUSE_TYPE_IF_MASK 3 + #define MOUSE_TYPE_3BUTTON (1 << 31) typedef struct diff --git a/src/ne2000.c b/src/ne2000.c index 961bff795..ca393b274 100644 --- a/src/ne2000.c +++ b/src/ne2000.c @@ -249,6 +249,7 @@ int ne2000_do_log = 0; void ne2000_log(const char *format, ...) { +#ifdef ENABLE_NE2000_LOG if (ne2000_do_log) { va_list ap; @@ -257,6 +258,7 @@ void ne2000_log(const char *format, ...) va_end(ap); fflush(stdout); } +#endif } static void ne2000_setirq(ne2000_t *ne2000, int irq) diff --git a/src/pc.c b/src/pc.c index 7e7a9e4e2..13408d206 100644 --- a/src/pc.c +++ b/src/pc.c @@ -9,6 +9,7 @@ #include "device.h" #include "ali1429.h" +#include "cdrom.h" #include "cdrom-ioctl.h" #include "disc.h" #include "mem.h" @@ -59,8 +60,6 @@ int window_w, window_h, window_x, window_y, window_remember; int start_in_fullscreen = 0; -int scsi_cdrom_enabled; -int cdrom_enabled; int CPUID; int vid_resize, vid_api; @@ -207,7 +206,7 @@ void initpc(int argc, char *argv[]) { char *p; char *config_file = NULL; - int c; + int c, i; FILE *ff; // allegro_init(); get_executable_name(pcempath,511); @@ -271,6 +270,41 @@ void initpc(int argc, char *argv[]) device_init(); timer_reset(); + + for (i = 0; i < CDROM_NUM; i++) + { + if (cdrom_drives[i].bus_type) + { + SCSIReset(cdrom_drives[i].scsi_device_id); + } + + if (cdrom_drives[i].host_drive == 0) + { + cdrom_null_open(i, cdrom_drives[i].host_drive); + } + else + { + if (cdrom_drives[i].host_drive == 200) + { + ff = fopen(cdrom_iso[i].iso_path, "rb"); + if (ff) + { + fclose(ff); + iso_open(i, cdrom_iso[i].iso_path); + } + else + { + cdrom_drives[i].host_drive = 0; + cdrom_null_open(i, cdrom_drives[i].host_drive); + } + } + else + { + ioctl_open(i, cdrom_drives[i].host_drive); + } + } + } + sound_reset(); fdc_init(); disc_init(); @@ -294,41 +328,13 @@ void initpc(int argc, char *argv[]) //loadfont(); loadnvr(); sound_init(); + resetide(); - if (buslogic_enabled) - { - SCSIReset(scsi_cdrom_id); - device_add(&BuslogicDevice); - } - - if ((cdrom_drive == -1) || (cdrom_drive == 0)) - cdrom_null_open(cdrom_drive); - else + if (buslogic_enabled) { - if (cdrom_drive == 200) - { - ff = fopen(iso_path, "rb"); - if (ff) - { - fclose(ff); - iso_open(iso_path); - } - else - { -#if __unix - cdrom_drive = -1; -#else - cdrom_drive = 0; -#endif - cdrom_null_open(cdrom_drive); - } - } - else - { - ioctl_open(cdrom_drive); - } - } - + device_add(&BuslogicDevice); + } + pit_reset(); /* if (romset==ROM_AMI386 || romset==ROM_AMI486) */fullspeed(); ali1429_reset(); @@ -336,18 +342,23 @@ void initpc(int argc, char *argv[]) // pclog("Init - CPUID %i %i\n",CPUID,cpuspeed); shadowbios=0; - if ((cdrom_drive == -1) || (cdrom_drive == 0)) - cdrom_null_reset(); - else + for (i = 0; i < CDROM_NUM; i++) { - if (cdrom_drive == 200) + if (cdrom_drives[i].host_drive == 0) + { + cdrom_null_reset(i); + } + else + { + if (cdrom_drives[i].host_drive == 200) { - iso_reset(); + iso_reset(i); } else { - ioctl_reset(); + ioctl_reset(i); } + } } } @@ -384,6 +395,8 @@ void resetpc_cad() void resetpchard() { + int i = 0; + savenvr(); saveconfig(); @@ -436,13 +449,19 @@ void resetpchard() device_add(&voodoo_device); pc_reset(); - resetide(); - - if (buslogic_enabled) + for (i = 0; i < CDROM_NUM; i++) + { + if (cdrom_drives[i].bus_type) { - SCSIReset(scsi_cdrom_id); - device_add(&BuslogicDevice); + SCSIReset(cdrom_drives[i].scsi_device_id); } + } + + resetide(); + if (buslogic_enabled) + { + device_add(&BuslogicDevice); + } loadnvr(); @@ -459,18 +478,23 @@ void resetpchard() // output=3; - if ((cdrom_drive == -1) || (cdrom_drive == 0)) - cdrom_null_reset(); - else + for (i = 0; i < CDROM_NUM; i++) { - if (cdrom_drive == 200) + if (cdrom_drives[i].host_drive == 0) + { + cdrom_null_reset(i); + } + else + { + if (cdrom_drives[i].host_drive == 200) { - iso_reset(); + iso_reset(i); } else { - ioctl_reset(); + ioctl_reset(i); } + } } } @@ -601,7 +625,11 @@ void speedchanged() void closepc() { - cdrom->exit(); + int i = 0; + for (i = 0; i < CDROM_NUM; i++) + { + cdrom_drives[i].handler->exit(i); + } // ioctl_close(); dumppic(); // output=7; @@ -701,19 +729,54 @@ void loadconfig(char *fn) if (mem_size < ((models[model].flags & MODEL_AT) ? models[model].min_ram*1024 : models[model].min_ram)) mem_size = ((models[model].flags & MODEL_AT) ? models[model].min_ram*1024 : models[model].min_ram); - cdrom_drive = config_get_int(NULL, "cdrom_drive", 0); - old_cdrom_drive = cdrom_drive; - cdrom_enabled = config_get_int(NULL, "cdrom_enabled", 0); + cdrom_drives[0].host_drive = config_get_int(NULL, "cdrom_1_host_drive", 0); + cdrom_drives[0].prev_host_drive = cdrom_drives[0].host_drive; + cdrom_drives[0].enabled = config_get_int(NULL, "cdrom_1_enabled", 0); + cdrom_drives[0].sound_on = config_get_int(NULL, "cdrom_1_sound_on", 1); + cdrom_drives[0].bus_type = config_get_int(NULL, "cdrom_1_bus_type", 0); + cdrom_drives[0].ide_channel = config_get_int(NULL, "cdrom_1_ide_channel", 2); + cdrom_drives[0].scsi_device_id = config_get_int(NULL, "cdrom_1_scsi_device_id", 2); - atapi_cdrom_channel = config_get_int(NULL, "atapi_cdrom_channel", 2); + p = (char *)config_get_string(NULL, "cdrom_1_iso_path", ""); + if (p) strcpy(cdrom_iso[0].iso_path, p); + else strcpy(cdrom_iso[0].iso_path, ""); + + cdrom_drives[1].host_drive = config_get_int(NULL, "cdrom_2_host_drive", 0); + cdrom_drives[1].prev_host_drive = cdrom_drives[1].host_drive; + cdrom_drives[1].enabled = config_get_int(NULL, "cdrom_2_enabled", 0); + cdrom_drives[1].sound_on = config_get_int(NULL, "cdrom_2_sound_on", 1); + cdrom_drives[1].bus_type = config_get_int(NULL, "cdrom_2_bus_type", 0); + cdrom_drives[1].ide_channel = config_get_int(NULL, "cdrom_2_ide_channel", 3); + cdrom_drives[1].scsi_device_id = config_get_int(NULL, "cdrom_2_scsi_device_id", 3); + + p = (char *)config_get_string(NULL, "cdrom_2_iso_path", ""); + if (p) strcpy(cdrom_iso[1].iso_path, p); + else strcpy(cdrom_iso[1].iso_path, ""); + + cdrom_drives[2].host_drive = config_get_int(NULL, "cdrom_3_host_drive", 0); + cdrom_drives[2].prev_host_drive = cdrom_drives[2].host_drive; + cdrom_drives[2].enabled = config_get_int(NULL, "cdrom_3_enabled", 0); + cdrom_drives[2].sound_on = config_get_int(NULL, "cdrom_3_sound_on", 1); + cdrom_drives[2].bus_type = config_get_int(NULL, "cdrom_3_bus_type", 0); + cdrom_drives[2].ide_channel = config_get_int(NULL, "cdrom_3_ide_channel", 4); + cdrom_drives[2].scsi_device_id = config_get_int(NULL, "cdrom_3_scsi_device_id", 4); + + p = (char *)config_get_string(NULL, "cdrom_3_iso_path", ""); + if (p) strcpy(cdrom_iso[2].iso_path, p); + else strcpy(cdrom_iso[2].iso_path, ""); + + cdrom_drives[3].host_drive = config_get_int(NULL, "cdrom_4_host_drive", 0); + cdrom_drives[3].prev_host_drive = cdrom_drives[3].host_drive; + cdrom_drives[3].enabled = config_get_int(NULL, "cdrom_4_enabled", 0); + cdrom_drives[3].sound_on = config_get_int(NULL, "cdrom_4_sound_on", 1); + cdrom_drives[3].bus_type = config_get_int(NULL, "cdrom_4_bus_type", 0); + cdrom_drives[3].ide_channel = config_get_int(NULL, "cdrom_4_ide_channel", 5); + cdrom_drives[3].scsi_device_id = config_get_int(NULL, "cdrom_4_scsi_device_id", 5); + + p = (char *)config_get_string(NULL, "cdrom_4_iso_path", ""); + if (p) strcpy(cdrom_iso[3].iso_path, p); + else strcpy(cdrom_iso[3].iso_path, ""); - scsi_cdrom_enabled = config_get_int(NULL, "scsi_cdrom_enabled", 0); - scsi_cdrom_id = config_get_int(NULL, "scsi_cdrom_id", 3); - - p = (char *)config_get_string(NULL, "cdrom_path", ""); - if (p) strcpy(iso_path, p); - else strcpy(iso_path, ""); - vid_resize = config_get_int(NULL, "vid_resize", 0); vid_api = config_get_int(NULL, "vid_api", 0); video_fullscreen_scale = config_get_int(NULL, "video_fullscreen_scale", 0); @@ -881,15 +944,43 @@ void saveconfig() config_set_string(NULL, "disc_4", discfns[3]); config_set_int(NULL, "disc_4_writeprot", ui_writeprot[3]); config_set_int(NULL, "mem_size", mem_size); - config_set_int(NULL, "cdrom_drive", cdrom_drive); - config_set_int(NULL, "cdrom_enabled", cdrom_enabled); - - config_set_int(NULL, "atapi_cdrom_channel", atapi_cdrom_channel); - - config_set_int(NULL, "scsi_cdrom_enabled", scsi_cdrom_enabled); - config_set_int(NULL, "scsi_cdrom_id", scsi_cdrom_id); - - config_set_string(NULL, "cdrom_path", iso_path); + + config_set_int(NULL, "cdrom_1_host_drive", cdrom_drives[0].host_drive); + config_set_int(NULL, "cdrom_1_enabled", cdrom_drives[0].enabled); + config_set_int(NULL, "cdrom_1_sound_on", cdrom_drives[0].sound_on); + config_set_int(NULL, "cdrom_1_bus_type", cdrom_drives[0].bus_type); + config_set_int(NULL, "cdrom_1_ide_channel", cdrom_drives[0].ide_channel); + config_set_int(NULL, "cdrom_1_scsi_device_id", cdrom_drives[0].scsi_device_id); + + config_set_string(NULL, "cdrom_1_iso_path", cdrom_iso[0].iso_path); + + config_set_int(NULL, "cdrom_2_host_drive", cdrom_drives[1].host_drive); + config_set_int(NULL, "cdrom_2_enabled", cdrom_drives[1].enabled); + config_set_int(NULL, "cdrom_2_sound_on", cdrom_drives[1].sound_on); + config_set_int(NULL, "cdrom_2_bus_type", cdrom_drives[1].bus_type); + config_set_int(NULL, "cdrom_2_ide_channel", cdrom_drives[1].ide_channel); + config_set_int(NULL, "cdrom_2_scsi_device_id", cdrom_drives[1].scsi_device_id); + + config_set_string(NULL, "cdrom_2_iso_path", cdrom_iso[1].iso_path); + + config_set_int(NULL, "cdrom_3_host_drive", cdrom_drives[2].host_drive); + config_set_int(NULL, "cdrom_3_enabled", cdrom_drives[2].enabled); + config_set_int(NULL, "cdrom_3_sound_on", cdrom_drives[2].sound_on); + config_set_int(NULL, "cdrom_3_bus_type", cdrom_drives[2].bus_type); + config_set_int(NULL, "cdrom_3_ide_channel", cdrom_drives[2].ide_channel); + config_set_int(NULL, "cdrom_3_scsi_device_id", cdrom_drives[2].scsi_device_id); + + config_set_string(NULL, "cdrom_3_iso_path", cdrom_iso[2].iso_path); + + config_set_int(NULL, "cdrom_4_host_drive", cdrom_drives[3].host_drive); + config_set_int(NULL, "cdrom_4_enabled", cdrom_drives[3].enabled); + config_set_int(NULL, "cdrom_4_sound_on", cdrom_drives[3].sound_on); + config_set_int(NULL, "cdrom_4_bus_type", cdrom_drives[3].bus_type); + config_set_int(NULL, "cdrom_4_ide_channel", cdrom_drives[3].ide_channel); + config_set_int(NULL, "cdrom_4_scsi_device_id", cdrom_drives[3].scsi_device_id); + + config_set_string(NULL, "cdrom_4_iso_path", cdrom_iso[3].iso_path); + config_set_int(NULL, "vid_resize", vid_resize); config_set_int(NULL, "vid_api", vid_api); config_set_int(NULL, "video_fullscreen_scale", video_fullscreen_scale); diff --git a/src/pc.rc b/src/pc.rc index fcb8741dc..65d8c4acf 100644 --- a/src/pc.rc +++ b/src/pc.rc @@ -35,15 +35,172 @@ BEGIN MENUITEM "E&ject FDD 4", IDM_EJECT_4 MENUITEM SEPARATOR MENUITEM "&Configure hard discs...",IDM_HDCONF - POPUP "C&D-ROM" + POPUP "C&D-ROM 1" BEGIN - MENUITEM "&Enabled", IDM_CDROM_ENABLED - MENUITEM "&SCSI", IDM_CDROM_SCSI + MENUITEM "&Enabled", IDM_CDROM_1_ENABLED + MENUITEM "S&ound enabled", IDM_CDROM_1_SOUND_ON MENUITEM SEPARATOR - MENUITEM "E&mpty",IDM_CDROM_EMPTY - MENUITEM "&Reload previous disc",IDM_CDROM_RELOAD + MENUITEM "&SCSI", IDM_CDROM_1_SCSI MENUITEM SEPARATOR - MENUITEM "&ISO...",IDM_CDROM_ISO + MENUITEM "E&mpty",IDM_CDROM_1_EMPTY + MENUITEM "&Reload previous disc",IDM_CDROM_1_RELOAD + MENUITEM SEPARATOR + POPUP "&IDE channel..." + BEGIN + MENUITEM "&C:",IDM_CDROM_1_C + MENUITEM "&D:",IDM_CDROM_1_D + MENUITEM "&E:",IDM_CDROM_1_E + MENUITEM "&F:",IDM_CDROM_1_F + MENUITEM "&G:",IDM_CDROM_1_G + MENUITEM "&H:",IDM_CDROM_1_H + MENUITEM "&I:",IDM_CDROM_1_I + MENUITEM "&J:",IDM_CDROM_1_J + END + POPUP "S&CSI ID..." + BEGIN + MENUITEM "&0",IDM_CDROM_1_0 + MENUITEM "&1",IDM_CDROM_1_1 + MENUITEM "&2",IDM_CDROM_1_2 + MENUITEM "&3",IDM_CDROM_1_3 + MENUITEM "&4",IDM_CDROM_1_4 + MENUITEM "&5",IDM_CDROM_1_5 + MENUITEM "&6",IDM_CDROM_1_6 + MENUITEM "&8",IDM_CDROM_1_8 + MENUITEM "&9",IDM_CDROM_1_9 + MENUITEM "10",IDM_CDROM_1_10 + MENUITEM "11",IDM_CDROM_1_11 + MENUITEM "12",IDM_CDROM_1_12 + MENUITEM "13",IDM_CDROM_1_13 + MENUITEM "14",IDM_CDROM_1_14 + MENUITEM "15",IDM_CDROM_1_15 + END + MENUITEM SEPARATOR + MENUITEM "&ISO...",IDM_CDROM_1_ISO + END + POPUP "CD-&ROM 2" + BEGIN + MENUITEM "&Enabled", IDM_CDROM_2_ENABLED + MENUITEM "S&ound enabled", IDM_CDROM_2_SOUND_ON + MENUITEM SEPARATOR + MENUITEM "&SCSI", IDM_CDROM_2_SCSI + MENUITEM SEPARATOR + MENUITEM "E&mpty",IDM_CDROM_2_EMPTY + MENUITEM "&Reload previous disc",IDM_CDROM_2_RELOAD + MENUITEM SEPARATOR + POPUP "&IDE channel..." + BEGIN + MENUITEM "&C:",IDM_CDROM_2_C + MENUITEM "&D:",IDM_CDROM_2_D + MENUITEM "&E:",IDM_CDROM_2_E + MENUITEM "&F:",IDM_CDROM_2_F + MENUITEM "&G:",IDM_CDROM_2_G + MENUITEM "&H:",IDM_CDROM_2_H + MENUITEM "&I:",IDM_CDROM_2_I + MENUITEM "&J:",IDM_CDROM_2_J + END + POPUP "S&CSI ID..." + BEGIN + MENUITEM "&0",IDM_CDROM_2_0 + MENUITEM "&1",IDM_CDROM_2_1 + MENUITEM "&2",IDM_CDROM_2_2 + MENUITEM "&3",IDM_CDROM_2_3 + MENUITEM "&4",IDM_CDROM_2_4 + MENUITEM "&5",IDM_CDROM_2_5 + MENUITEM "&6",IDM_CDROM_2_6 + MENUITEM "&8",IDM_CDROM_2_8 + MENUITEM "&9",IDM_CDROM_2_9 + MENUITEM "10",IDM_CDROM_2_10 + MENUITEM "11",IDM_CDROM_2_11 + MENUITEM "12",IDM_CDROM_2_12 + MENUITEM "13",IDM_CDROM_2_13 + MENUITEM "14",IDM_CDROM_2_14 + MENUITEM "15",IDM_CDROM_2_15 + END + MENUITEM SEPARATOR + MENUITEM "&ISO...",IDM_CDROM_2_ISO + END + POPUP "CD-R&OM 3" + BEGIN + MENUITEM "&Enabled", IDM_CDROM_3_ENABLED + MENUITEM "S&ound enabled", IDM_CDROM_3_SOUND_ON + MENUITEM SEPARATOR + MENUITEM "&SCSI", IDM_CDROM_3_SCSI + MENUITEM SEPARATOR + MENUITEM "E&mpty",IDM_CDROM_3_EMPTY + MENUITEM "&Reload previous disc",IDM_CDROM_3_RELOAD + MENUITEM SEPARATOR + POPUP "&IDE channel..." + BEGIN + MENUITEM "&C:",IDM_CDROM_3_C + MENUITEM "&D:",IDM_CDROM_3_D + MENUITEM "&E:",IDM_CDROM_3_E + MENUITEM "&F:",IDM_CDROM_3_F + MENUITEM "&G:",IDM_CDROM_3_G + MENUITEM "&H:",IDM_CDROM_3_H + MENUITEM "&I:",IDM_CDROM_3_I + MENUITEM "&J:",IDM_CDROM_3_J + END + POPUP "S&CSI ID..." + BEGIN + MENUITEM "&0",IDM_CDROM_3_0 + MENUITEM "&1",IDM_CDROM_3_1 + MENUITEM "&2",IDM_CDROM_3_2 + MENUITEM "&3",IDM_CDROM_3_3 + MENUITEM "&4",IDM_CDROM_3_4 + MENUITEM "&5",IDM_CDROM_3_5 + MENUITEM "&6",IDM_CDROM_3_6 + MENUITEM "&8",IDM_CDROM_3_8 + MENUITEM "&9",IDM_CDROM_3_9 + MENUITEM "10",IDM_CDROM_3_10 + MENUITEM "11",IDM_CDROM_3_11 + MENUITEM "12",IDM_CDROM_3_12 + MENUITEM "13",IDM_CDROM_3_13 + MENUITEM "14",IDM_CDROM_3_14 + MENUITEM "15",IDM_CDROM_3_15 + END + MENUITEM SEPARATOR + MENUITEM "&ISO...",IDM_CDROM_3_ISO + END + POPUP "CD-RO&M 4" + BEGIN + MENUITEM "&Enabled", IDM_CDROM_4_ENABLED + MENUITEM "S&ound enabled", IDM_CDROM_4_SOUND_ON + MENUITEM SEPARATOR + MENUITEM "&SCSI", IDM_CDROM_4_SCSI + MENUITEM "E&mpty",IDM_CDROM_4_EMPTY + MENUITEM "&Reload previous disc",IDM_CDROM_4_RELOAD + MENUITEM SEPARATOR + POPUP "&IDE channel..." + BEGIN + MENUITEM "&C:",IDM_CDROM_4_C + MENUITEM "&D:",IDM_CDROM_4_D + MENUITEM "&E:",IDM_CDROM_4_E + MENUITEM "&F:",IDM_CDROM_4_F + MENUITEM "&G:",IDM_CDROM_4_G + MENUITEM "&H:",IDM_CDROM_4_H + MENUITEM "&I:",IDM_CDROM_4_I + MENUITEM "&J:",IDM_CDROM_4_J + END + POPUP "S&CSI ID..." + BEGIN + MENUITEM "&0",IDM_CDROM_4_0 + MENUITEM "&1",IDM_CDROM_4_1 + MENUITEM "&2",IDM_CDROM_4_2 + MENUITEM "&3",IDM_CDROM_4_3 + MENUITEM "&4",IDM_CDROM_4_4 + MENUITEM "&5",IDM_CDROM_4_5 + MENUITEM "&6",IDM_CDROM_4_6 + MENUITEM "&8",IDM_CDROM_4_8 + MENUITEM "&9",IDM_CDROM_4_9 + MENUITEM "10",IDM_CDROM_4_10 + MENUITEM "11",IDM_CDROM_4_11 + MENUITEM "12",IDM_CDROM_4_12 + MENUITEM "13",IDM_CDROM_4_13 + MENUITEM "14",IDM_CDROM_4_14 + MENUITEM "15",IDM_CDROM_4_15 + END + MENUITEM SEPARATOR + MENUITEM "&ISO...",IDM_CDROM_4_ISO END POPUP "E&xtra IDE controllers" BEGIN @@ -218,8 +375,6 @@ HdConfDlg DIALOGEX 0, 0, 270, DLG_HEIGHT PUSHBUTTON "...",IDC_CFILE,7 + 136, C_BASE, 16, 14 PUSHBUTTON "New",IDC_CNEW,7 + 152, C_BASE, 24, 14 PUSHBUTTON "Eject", IDC_EJECTC, 7 + 176, C_BASE, 24, 14 - RADIOBUTTON "Hard drive", IDC_CHDD, 7+207, C_BASE, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_CCDROM, 7+207, C_BASE+16, 53, 12 , WS_TABSTOP EDITTEXT IDC_EDIT_C_SPT,15,C_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_C_HPC,48,C_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_C_CYL,81,C_BASE+16,28,12, WS_DISABLED @@ -233,8 +388,6 @@ HdConfDlg DIALOGEX 0, 0, 270, DLG_HEIGHT PUSHBUTTON "...",IDC_DFILE,7 + 136, D_BASE, 16, 14 PUSHBUTTON "New",IDC_DNEW,7 + 152, D_BASE, 24, 14 PUSHBUTTON "Eject", IDC_EJECTD, 7 + 176, D_BASE, 24, 14 - RADIOBUTTON "Hard drive", IDC_DHDD, 7+207, D_BASE, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_DCDROM, 7+207, D_BASE+16, 53, 12 , WS_TABSTOP EDITTEXT IDC_EDIT_D_SPT,15,D_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_D_HPC,48,D_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_D_CYL,81,D_BASE+16,28,12, WS_DISABLED @@ -248,8 +401,6 @@ HdConfDlg DIALOGEX 0, 0, 270, DLG_HEIGHT PUSHBUTTON "...",IDC_EFILE,7 + 136, E_BASE, 16, 14 PUSHBUTTON "New",IDC_ENEW,7 + 152, E_BASE, 24, 14 PUSHBUTTON "Eject", IDC_EJECTE, 7 + 176, E_BASE, 24, 14 - RADIOBUTTON "Hard drive", IDC_EHDD, 7+207, E_BASE, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_ECDROM, 7+207, E_BASE+16, 53, 12 , WS_TABSTOP EDITTEXT IDC_EDIT_E_SPT,15,E_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_E_HPC,48,E_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_E_CYL,81,E_BASE+16,28,12, WS_DISABLED @@ -263,8 +414,6 @@ HdConfDlg DIALOGEX 0, 0, 270, DLG_HEIGHT PUSHBUTTON "...",IDC_FFILE,7 + 136, F_BASE, 16, 14 PUSHBUTTON "New",IDC_FNEW,7 + 152, F_BASE, 24, 14 PUSHBUTTON "Eject", IDC_EJECTF, 7 + 176, F_BASE, 24, 14 - RADIOBUTTON "Hard drive", IDC_FHDD, 7+207, F_BASE, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_FCDROM, 7+207, F_BASE+16, 53, 12 , WS_TABSTOP EDITTEXT IDC_EDIT_F_SPT,15,F_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_F_HPC,48,F_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_F_CYL,81,F_BASE+16,28,12, WS_DISABLED @@ -278,8 +427,6 @@ HdConfDlg DIALOGEX 0, 0, 270, DLG_HEIGHT PUSHBUTTON "...",IDC_GFILE,7 + 136, G_BASE, 16, 14 PUSHBUTTON "New",IDC_GNEW,7 + 152, G_BASE, 24, 14 PUSHBUTTON "Eject", IDC_EJECTG, 7 + 176, G_BASE, 24, 14 - RADIOBUTTON "Hard drive", IDC_GHDD, 7+207, G_BASE, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_GCDROM, 7+207, G_BASE+16, 53, 12 , WS_TABSTOP EDITTEXT IDC_EDIT_G_SPT,15,G_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_G_HPC,48,G_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_G_CYL,81,G_BASE+16,28,12, WS_DISABLED @@ -293,8 +440,6 @@ HdConfDlg DIALOGEX 0, 0, 270, DLG_HEIGHT PUSHBUTTON "...",IDC_HFILE,7 + 136, H_BASE, 16, 14 PUSHBUTTON "New",IDC_HNEW,7 + 152, H_BASE, 24, 14 PUSHBUTTON "Eject", IDC_EJECTH, 7 + 176, H_BASE, 24, 14 - RADIOBUTTON "Hard drive", IDC_HHDD, 7+207, H_BASE, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_HCDROM, 7+207, H_BASE+16, 53, 12 , WS_TABSTOP EDITTEXT IDC_EDIT_H_SPT,15,H_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_H_HPC,48,H_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_H_CYL,81,H_BASE+16,28,12, WS_DISABLED @@ -308,8 +453,6 @@ HdConfDlg DIALOGEX 0, 0, 270, DLG_HEIGHT PUSHBUTTON "...",IDC_IFILE,7 + 136, I_BASE, 16, 14 PUSHBUTTON "New",IDC_INEW,7 + 152, I_BASE, 24, 14 PUSHBUTTON "Eject", IDC_EJECTI, 7 + 176, I_BASE, 24, 14 - RADIOBUTTON "Hard drive", IDC_IHDD, 7+207, I_BASE, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_ICDROM, 7+207, I_BASE+16, 53, 12 , WS_TABSTOP EDITTEXT IDC_EDIT_I_SPT,15,I_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_I_HPC,48,I_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_I_CYL,81,I_BASE+16,28,12, WS_DISABLED @@ -323,8 +466,6 @@ HdConfDlg DIALOGEX 0, 0, 270, DLG_HEIGHT PUSHBUTTON "...",IDC_JFILE,7 + 136, J_BASE, 16, 14 PUSHBUTTON "New",IDC_JNEW,7 + 152, J_BASE, 24, 14 PUSHBUTTON "Eject", IDC_EJECTJ, 7 + 176, J_BASE, 24, 14 - RADIOBUTTON "Hard drive", IDC_JHDD, 7+207, J_BASE, 53, 12 , WS_TABSTOP - RADIOBUTTON "CD-ROM", IDC_JCDROM, 7+207, J_BASE+16, 53, 12 , WS_TABSTOP EDITTEXT IDC_EDIT_J_SPT,15,J_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_J_HPC,48,J_BASE+16,16,12, WS_DISABLED EDITTEXT IDC_EDIT_J_CYL,81,J_BASE+16,28,12, WS_DISABLED diff --git a/src/piix.c b/src/piix.c index e1e41814c..ce3e33b0d 100644 --- a/src/piix.c +++ b/src/piix.c @@ -396,21 +396,21 @@ uint8_t piix_bus_master_read(uint16_t port, void *priv) return 0xff; } -int piix_bus_master_sector_read(int channel, uint8_t *data) +int piix_bus_master_dma_read(int channel, uint8_t *data, int transfer_length) { int transferred = 0; if (!(piix_busmaster[channel].status & 1)) return 1; /*DMA disabled*/ - while (transferred < 512) + while (transferred < transfer_length) { - if (piix_busmaster[channel].count < (512 - transferred) && piix_busmaster[channel].eot) - fatal("DMA on channel %i - Read count less than 512! Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); + if (piix_busmaster[channel].count < (transfer_length - transferred) && piix_busmaster[channel].eot) + fatal("DMA on channel %i - Read count less than transfer_length! Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); - mem_invalidate_range(piix_busmaster[channel].addr, piix_busmaster[channel].addr+511); + mem_invalidate_range(piix_busmaster[channel].addr, piix_busmaster[channel].addr + transfer_length - 1); - if (piix_busmaster[channel].count < (512 - transferred)) + if (piix_busmaster[channel].count < (transfer_length - transferred)) { // pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count); memcpy(&ram[piix_busmaster[channel].addr], data + transferred, piix_busmaster[channel].count); @@ -421,11 +421,11 @@ int piix_bus_master_sector_read(int channel, uint8_t *data) } else { -// pclog("Transferring larger - %i bytes\n", 512 - transferred); - memcpy(&ram[piix_busmaster[channel].addr], data + transferred, 512 - transferred); - piix_busmaster[channel].addr += (512 - transferred); - piix_busmaster[channel].count -= (512 - transferred); - transferred += (512 - transferred); +// pclog("Transferring larger - %i bytes\n", transfer_length - transferred); + memcpy(&ram[piix_busmaster[channel].addr], data + transferred, transfer_length - transferred); + piix_busmaster[channel].addr += (transfer_length - transferred); + piix_busmaster[channel].count -= (transfer_length - transferred); + transferred += (transfer_length - transferred); } // pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); @@ -444,19 +444,20 @@ int piix_bus_master_sector_read(int channel, uint8_t *data) } return 0; } -int piix_bus_master_sector_write(int channel, uint8_t *data) + +int piix_bus_master_dma_write(int channel, uint8_t *data, int transfer_length) { int transferred = 0; if (!(piix_busmaster[channel].status & 1)) return 1; /*DMA disabled*/ - while (transferred < 512) + while (transferred < transfer_length) { - if (piix_busmaster[channel].count < (512 - transferred) && piix_busmaster[channel].eot) - fatal("DMA on channel %i - Write count less than 512! Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); + if (piix_busmaster[channel].count < (transfer_length - transferred) && piix_busmaster[channel].eot) + fatal("DMA on channel %i - Write count less than transfer_length! Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); - if (piix_busmaster[channel].count < (512 - transferred)) + if (piix_busmaster[channel].count < (transfer_length - transferred)) { // pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count); memcpy(data + transferred, &ram[piix_busmaster[channel].addr], piix_busmaster[channel].count); @@ -467,11 +468,11 @@ int piix_bus_master_sector_write(int channel, uint8_t *data) } else { -// pclog("Transferring larger - %i bytes\n", 512 - transferred); - memcpy(data + transferred, &ram[piix_busmaster[channel].addr], 512 - transferred); - piix_busmaster[channel].addr += (512 - transferred); - piix_busmaster[channel].count -= (512 - transferred); - transferred += (512 - transferred); +// pclog("Transferring larger - %i bytes\n", transfer_length - transferred); + memcpy(data + transferred, &ram[piix_busmaster[channel].addr], transfer_length - transferred); + piix_busmaster[channel].addr += (transfer_length - transferred); + piix_busmaster[channel].count -= (transfer_length - transferred); + transferred += (transfer_length - transferred); } // pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); @@ -620,7 +621,7 @@ void piix_init(int card) piix_type = 1; - ide_set_bus_master(piix_bus_master_sector_read, piix_bus_master_sector_write, piix_bus_master_set_irq); + ide_set_bus_master(piix_bus_master_dma_read, piix_bus_master_dma_write, piix_bus_master_set_irq); io_sethandler(0x0cf9, 0x0001, rc_read, NULL, NULL, rc_write, NULL, NULL, NULL); @@ -641,7 +642,7 @@ void piix3_init(int card) piix_type = 3; - ide_set_bus_master(piix_bus_master_sector_read, piix_bus_master_sector_write, piix_bus_master_set_irq); + ide_set_bus_master(piix_bus_master_dma_read, piix_bus_master_dma_write, piix_bus_master_set_irq); io_sethandler(0x0cf9, 0x0001, rc_read, NULL, NULL, rc_write, NULL, NULL, NULL); diff --git a/src/resources.h b/src/resources.h index 864b12330..dbcaa228f 100644 --- a/src/resources.h +++ b/src/resources.h @@ -35,44 +35,158 @@ #define IDM_EJECT_4 40082 #define IDM_DISC_3_WP 40083 #define IDM_DISC_4_WP 40084 -#define IDM_CDROM_ISO 40100 -#define IDM_CDROM_RELOAD 40101 -#define IDM_CDROM_EMPTY 40200 -#define IDM_CDROM_REAL 40200 -#define IDM_CDROM_ENABLED 40300 -#define IDM_CDROM_SCSI 40400 -#define IDM_IDE_TER_ENABLED 40500 -#define IDM_IDE_TER_IRQ9 40501 -#define IDM_IDE_TER_IRQ10 40502 -#define IDM_IDE_TER_IRQ11 40503 -#define IDM_IDE_TER_IRQ12 40504 -#define IDM_IDE_TER_IRQ14 40505 -#define IDM_IDE_TER_IRQ15 40506 -#define IDM_IDE_QUA_ENABLED 40507 -#define IDM_IDE_QUA_IRQ9 40508 -#define IDM_IDE_QUA_IRQ10 40509 -#define IDM_IDE_QUA_IRQ11 40510 -#define IDM_IDE_QUA_IRQ12 40511 -#define IDM_IDE_QUA_IRQ14 40512 -#define IDM_IDE_QUA_IRQ15 40513 -#define IDM_SCSI_ENABLED 40600 -#define IDM_SCSI_MODEL0 40601 -#define IDM_SCSI_MODEL1 40602 -#define IDM_SCSI_BASE130 40603 -#define IDM_SCSI_BASE134 40604 -#define IDM_SCSI_BASE230 40605 -#define IDM_SCSI_BASE234 40606 -#define IDM_SCSI_BASE330 40607 -#define IDM_SCSI_BASE334 40608 -#define IDM_SCSI_IRQ9 40609 -#define IDM_SCSI_IRQ10 40610 -#define IDM_SCSI_IRQ11 40611 -#define IDM_SCSI_IRQ12 40612 -#define IDM_SCSI_IRQ14 40613 -#define IDM_SCSI_IRQ15 40614 -#define IDM_SCSI_DMA5 40615 -#define IDM_SCSI_DMA6 40616 -#define IDM_SCSI_DMA7 40617 +#define IDM_CDROM_1_ISO 40100 +#define IDM_CDROM_1_RELOAD 40101 +#define IDM_CDROM_1_EMPTY 40200 +#define IDM_CDROM_1_REAL 40200 +#define IDM_CDROM_1_ENABLED 40300 +#define IDM_CDROM_1_SOUND_ON 40400 +#define IDM_CDROM_1_SCSI 40500 +#define IDM_CDROM_1_C 40600 +#define IDM_CDROM_1_D 40601 +#define IDM_CDROM_1_E 40602 +#define IDM_CDROM_1_F 40603 +#define IDM_CDROM_1_G 40604 +#define IDM_CDROM_1_H 40605 +#define IDM_CDROM_1_I 40606 +#define IDM_CDROM_1_J 40607 +#define IDM_CDROM_1_0 40700 +#define IDM_CDROM_1_1 40701 +#define IDM_CDROM_1_2 40702 +#define IDM_CDROM_1_3 40703 +#define IDM_CDROM_1_4 40704 +#define IDM_CDROM_1_5 40705 +#define IDM_CDROM_1_6 40706 +#define IDM_CDROM_1_8 40708 +#define IDM_CDROM_1_9 40709 +#define IDM_CDROM_1_10 40710 +#define IDM_CDROM_1_11 40711 +#define IDM_CDROM_1_12 40712 +#define IDM_CDROM_1_13 40713 +#define IDM_CDROM_1_14 40714 +#define IDM_CDROM_1_15 40715 +#define IDM_CDROM_2_ISO 41100 +#define IDM_CDROM_2_RELOAD 41101 +#define IDM_CDROM_2_EMPTY 41200 +#define IDM_CDROM_2_REAL 41200 +#define IDM_CDROM_2_ENABLED 41300 +#define IDM_CDROM_2_SOUND_ON 41400 +#define IDM_CDROM_2_SCSI 41500 +#define IDM_CDROM_2_C 41600 +#define IDM_CDROM_2_D 41601 +#define IDM_CDROM_2_E 41602 +#define IDM_CDROM_2_F 41603 +#define IDM_CDROM_2_G 41604 +#define IDM_CDROM_2_H 41605 +#define IDM_CDROM_2_I 41606 +#define IDM_CDROM_2_J 41607 +#define IDM_CDROM_2_0 41700 +#define IDM_CDROM_2_1 41701 +#define IDM_CDROM_2_2 41702 +#define IDM_CDROM_2_3 41703 +#define IDM_CDROM_2_4 41704 +#define IDM_CDROM_2_5 41705 +#define IDM_CDROM_2_6 41706 +#define IDM_CDROM_2_8 41708 +#define IDM_CDROM_2_9 41709 +#define IDM_CDROM_2_10 41710 +#define IDM_CDROM_2_11 41711 +#define IDM_CDROM_2_12 41712 +#define IDM_CDROM_2_13 41713 +#define IDM_CDROM_2_14 41714 +#define IDM_CDROM_2_15 41715 +#define IDM_CDROM_3_ISO 42100 +#define IDM_CDROM_3_RELOAD 42101 +#define IDM_CDROM_3_EMPTY 42200 +#define IDM_CDROM_3_REAL 42200 +#define IDM_CDROM_3_ENABLED 42300 +#define IDM_CDROM_3_SOUND_ON 42400 +#define IDM_CDROM_3_SCSI 42500 +#define IDM_CDROM_3_C 42600 +#define IDM_CDROM_3_D 42601 +#define IDM_CDROM_3_E 42602 +#define IDM_CDROM_3_F 42603 +#define IDM_CDROM_3_G 42604 +#define IDM_CDROM_3_H 42605 +#define IDM_CDROM_3_I 42606 +#define IDM_CDROM_3_J 42607 +#define IDM_CDROM_3_0 42700 +#define IDM_CDROM_3_1 42701 +#define IDM_CDROM_3_2 42702 +#define IDM_CDROM_3_3 42703 +#define IDM_CDROM_3_4 42704 +#define IDM_CDROM_3_5 42705 +#define IDM_CDROM_3_6 42706 +#define IDM_CDROM_3_8 42708 +#define IDM_CDROM_3_9 42709 +#define IDM_CDROM_3_10 42710 +#define IDM_CDROM_3_11 42711 +#define IDM_CDROM_3_12 42712 +#define IDM_CDROM_3_13 42713 +#define IDM_CDROM_3_14 42714 +#define IDM_CDROM_3_15 42715 +#define IDM_CDROM_4_ISO 43100 +#define IDM_CDROM_4_RELOAD 43101 +#define IDM_CDROM_4_EMPTY 43200 +#define IDM_CDROM_4_REAL 43200 +#define IDM_CDROM_4_ENABLED 43300 +#define IDM_CDROM_4_SOUND_ON 43400 +#define IDM_CDROM_4_SCSI 43500 +#define IDM_CDROM_4_C 43600 +#define IDM_CDROM_4_D 43601 +#define IDM_CDROM_4_E 43602 +#define IDM_CDROM_4_F 43603 +#define IDM_CDROM_4_G 43604 +#define IDM_CDROM_4_H 43605 +#define IDM_CDROM_4_I 43606 +#define IDM_CDROM_4_J 43607 +#define IDM_CDROM_4_0 43700 +#define IDM_CDROM_4_1 43701 +#define IDM_CDROM_4_2 43702 +#define IDM_CDROM_4_3 43703 +#define IDM_CDROM_4_4 43704 +#define IDM_CDROM_4_5 43705 +#define IDM_CDROM_4_6 43706 +#define IDM_CDROM_4_8 43708 +#define IDM_CDROM_4_9 43709 +#define IDM_CDROM_4_10 43710 +#define IDM_CDROM_4_11 43711 +#define IDM_CDROM_4_12 43712 +#define IDM_CDROM_4_13 43713 +#define IDM_CDROM_4_14 43714 +#define IDM_CDROM_4_15 43715 +#define IDM_IDE_TER_ENABLED 44000 +#define IDM_IDE_TER_IRQ9 44009 +#define IDM_IDE_TER_IRQ10 44010 +#define IDM_IDE_TER_IRQ11 44011 +#define IDM_IDE_TER_IRQ12 44012 +#define IDM_IDE_TER_IRQ14 44014 +#define IDM_IDE_TER_IRQ15 44015 +#define IDM_IDE_QUA_ENABLED 44020 +#define IDM_IDE_QUA_IRQ9 44029 +#define IDM_IDE_QUA_IRQ10 44030 +#define IDM_IDE_QUA_IRQ11 44031 +#define IDM_IDE_QUA_IRQ12 44032 +#define IDM_IDE_QUA_IRQ14 44033 +#define IDM_IDE_QUA_IRQ15 44035 +#define IDM_SCSI_ENABLED 45000 +#define IDM_SCSI_MODEL0 45100 +#define IDM_SCSI_MODEL1 45101 +#define IDM_SCSI_BASE130 45200 + 0x130 +#define IDM_SCSI_BASE134 45200 + 0x134 +#define IDM_SCSI_BASE230 45200 + 0x230 +#define IDM_SCSI_BASE234 45200 + 0x234 +#define IDM_SCSI_BASE330 45200 + 0x330 +#define IDM_SCSI_BASE334 45200 + 0x334 +#define IDM_SCSI_IRQ9 45309 +#define IDM_SCSI_IRQ10 45310 +#define IDM_SCSI_IRQ11 45311 +#define IDM_SCSI_IRQ12 45312 +#define IDM_SCSI_IRQ14 45314 +#define IDM_SCSI_IRQ15 45315 +#define IDM_SCSI_DMA5 45405 +#define IDM_SCSI_DMA6 45406 +#define IDM_SCSI_DMA7 45407 #define IDC_COMBO1 1000 #define IDC_COMBOVID 1001 @@ -113,8 +227,6 @@ #define IDC_EDITC 1050 #define IDC_CFILE 1060 #define IDC_CNEW 1070 -#define IDC_CHDD 1080 -#define IDC_CCDROM 1090 #define IDC_EDIT_C_SPT 1200 #define IDC_EDIT_C_HPC 1210 #define IDC_EDIT_C_CYL 1220 @@ -125,8 +237,6 @@ #define IDC_EDITD 1051 #define IDC_DFILE 1061 #define IDC_DNEW 1071 -#define IDC_DHDD 1081 -#define IDC_DCDROM 1091 #define IDC_EDIT_D_SPT 1201 #define IDC_EDIT_D_HPC 1211 #define IDC_EDIT_D_CYL 1221 @@ -137,8 +247,6 @@ #define IDC_EDITE 1052 #define IDC_EFILE 1062 #define IDC_ENEW 1072 -#define IDC_EHDD 1082 -#define IDC_ECDROM 1092 #define IDC_EDIT_E_SPT 1202 #define IDC_EDIT_E_HPC 1212 #define IDC_EDIT_E_CYL 1222 @@ -149,8 +257,6 @@ #define IDC_EDITF 1053 #define IDC_FFILE 1063 #define IDC_FNEW 1073 -#define IDC_FHDD 1083 -#define IDC_FCDROM 1093 #define IDC_EDIT_F_SPT 1203 #define IDC_EDIT_F_HPC 1213 #define IDC_EDIT_F_CYL 1223 @@ -161,8 +267,6 @@ #define IDC_EDITG 1054 #define IDC_GFILE 1064 #define IDC_GNEW 1074 -#define IDC_GHDD 1084 -#define IDC_GCDROM 1094 #define IDC_EDIT_G_SPT 1204 #define IDC_EDIT_G_HPC 1214 #define IDC_EDIT_G_CYL 1224 @@ -173,8 +277,6 @@ #define IDC_EDITH 1055 #define IDC_HFILE 1065 #define IDC_HNEW 1075 -#define IDC_HHDD 1085 -#define IDC_HCDROM 1095 #define IDC_EDIT_H_SPT 1205 #define IDC_EDIT_H_HPC 1215 #define IDC_EDIT_H_CYL 1225 @@ -185,8 +287,6 @@ #define IDC_EDITI 1056 #define IDC_IFILE 1066 #define IDC_INEW 1076 -#define IDC_IHDD 1086 -#define IDC_ICDROM 1096 #define IDC_EDIT_I_SPT 1206 #define IDC_EDIT_I_HPC 1216 #define IDC_EDIT_I_CYL 1226 @@ -197,8 +297,6 @@ #define IDC_EDITJ 1057 #define IDC_JFILE 1067 #define IDC_JNEW 1077 -#define IDC_JHDD 1087 -#define IDC_JCDROM 1097 #define IDC_EDIT_J_SPT 1207 #define IDC_EDIT_J_HPC 1217 #define IDC_EDIT_J_CYL 1227 diff --git a/src/scsi.c b/src/scsi.c index 539c50791..5f709815d 100644 --- a/src/scsi.c +++ b/src/scsi.c @@ -13,6 +13,9 @@ #include "timer.h" +uint8_t SCSIPhase = SCSI_PHASE_BUS_FREE; +uint8_t SCSIStatus = SCSI_STATUS_OK; + int SCSICallback[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t scsi_cdrom_id = 3; /*common setting*/ @@ -22,6 +25,7 @@ void SCSIGetLength(uint8_t id, int *datalen) *datalen = SCSIDevices[id].CmdBufferLength; } +#if 0 //Execute SCSI command void SCSIExecCommand(uint8_t id, uint8_t *buffer, uint8_t *cdb) { @@ -72,25 +76,22 @@ void SCSIWrite(uint8_t Id, uint8_t *srcbuf, uint8_t *dstbuf, uint32_t len_size) } } ///// +#endif //Initialization function for the SCSI layer void SCSIReset(uint8_t Id) { - page_flags[GPMODE_CDROM_AUDIO_PAGE] &= 0xFD; /* Clear changed flag for CDROM AUDIO mode page. */ - memset(mode_pages_in[GPMODE_CDROM_AUDIO_PAGE], 0, 256); /* Clear the page itself. */ + uint8_t cdrom_id = scsi_cdrom_drives[Id]; - SCSICallback[Id]=0; - - if (cdrom_enabled && scsi_cdrom_enabled) + if (buslogic_scsi_drive_is_cdrom(Id)) { + SCSICallback[cdrom_id]=0; + + cdrom_reset(cdrom_id); SCSIDevices[Id].LunType = SCSI_CDROM; } else { SCSIDevices[Id].LunType = SCSI_NONE; } - - page_flags[GPMODE_CDROM_AUDIO_PAGE] &= ~PAGE_CHANGED; - - SCSISense.UnitAttention = 0; } diff --git a/src/scsi.h b/src/scsi.h index 44a3ddfd7..e59d5b60a 100644 --- a/src/scsi.h +++ b/src/scsi.h @@ -12,10 +12,12 @@ /* SCSI Commands */ #define GPCMD_TEST_UNIT_READY 0x00 +#define GPCMD_REZERO_UNIT 0x01 #define GPCMD_REQUEST_SENSE 0x03 #define GPCMD_READ_6 0x08 #define GPCMD_SEEK_6 0x0b #define GPCMD_INQUIRY 0x12 +#define GPCMD_VERIFY_6 0x13 #define GPCMD_MODE_SELECT_6 0x15 #define GPCMD_MODE_SENSE_6 0x1a #define GPCMD_START_STOP_UNIT 0x1b @@ -23,12 +25,14 @@ #define GPCMD_READ_CDROM_CAPACITY 0x25 #define GPCMD_READ_10 0x28 #define GPCMD_SEEK_10 0x2b +#define GPCMD_VERIFY_10 0x2f #define GPCMD_READ_SUBCHANNEL 0x42 #define GPCMD_READ_TOC_PMA_ATIP 0x43 #define GPCMD_READ_HEADER 0x44 #define GPCMD_PLAY_AUDIO_10 0x45 #define GPCMD_GET_CONFIGURATION 0x46 #define GPCMD_PLAY_AUDIO_MSF 0x47 +#define GPCMD_PLAY_AUDIO_TRACK_INDEX 0x48 #define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a #define GPCMD_PAUSE_RESUME 0x4b #define GPCMD_STOP_PLAY_SCAN 0x4e @@ -39,12 +43,18 @@ #define GPCMD_PLAY_AUDIO_12 0xa5 #define GPCMD_READ_12 0xa8 #define GPCMD_READ_DVD_STRUCTURE 0xad /* For reading. */ +#define GPCMD_VERIFY_12 0xaf +#define GPCMD_PLAY_CD_OLD 0xb4 +#define GPCMD_READ_CD_OLD 0xb8 #define GPCMD_READ_CD_MSF 0xb9 +#define GPCMD_SCAN 0xba #define GPCMD_SET_SPEED 0xbb #define GPCMD_PLAY_CD 0xbc #define GPCMD_MECHANISM_STATUS 0xbd #define GPCMD_READ_CD 0xbe #define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to PCem. */ +#define GPCMD_SCAN_ALT 0xcd /* Should be equivalent to 0xba */ +#define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */ /* Mode page codes for mode sense/set */ #define GPMODE_R_W_ERROR_PAGE 0x01 @@ -66,7 +76,9 @@ /* SCSI Additional Sense Codes */ #define ASC_AUDIO_PLAY_OPERATION 0x00 #define ASC_ILLEGAL_OPCODE 0x20 +#define ASC_LBA_OUT_OF_RANGE 0x21 #define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26 #define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 #define ASC_INCOMPATIBLE_FORMAT 0x30 #define ASC_MEDIUM_NOT_PRESENT 0x3a @@ -79,7 +91,7 @@ /* Tell RISC OS that we have a 4x CD-ROM drive (600kb/sec data, 706kb/sec raw). Not that it means anything */ -#define CDROM_SPEED 706 +#define CDROM_SPEED 706 /* 0x2C2 */ /* Some generally useful CD-ROM information */ #define CD_MINS 75 /* max. minutes per CD */ @@ -144,14 +156,15 @@ #define MMC_PROFILE_HDDVD_RW_DL 0x005A #define MMC_PROFILE_INVALID 0xFFFF +#define SCSI_ONLY 32 +#define ATAPI_ONLY 16 +#define IMPLEMENTED 8 #define NONDATA 4 #define CHECK_READY 2 #define ALLOW_UA 1 extern uint8_t SCSICommandTable[0x100]; -#define IMPLEMENTED 1 - extern uint8_t mode_sense_pages[0x40]; extern int readcdmode; @@ -197,47 +210,6 @@ extern int prev_status; #define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) -typedef struct __attribute__((packed)) -{ - uint8_t user_data[2048]; - uint8_t ecc[288]; -} m1_data_t; - -typedef struct __attribute__((packed)) -{ - uint8_t sub_header[8]; - uint8_t user_data[2328]; -} m2_data_t; - -typedef union __attribute__((packed)) -{ - m1_data_t m1_data; - m2_data_t m2_data; - uint8_t raw_data[2352]; -} sector_data_t; - -typedef struct __attribute__((packed)) -{ - uint8_t sync[12]; - uint8_t header[4]; - sector_data_t data; - uint8_t c2[296]; - uint8_t subchannel_raw[96]; - uint8_t subchannel_q[16]; - uint8_t subchannel_rw[96]; -} cdrom_sector_t; - -typedef union __attribute__((packed)) -{ - cdrom_sector_t cdrom_sector; - uint8_t buffer[2856]; -} sector_buffer_t; - -extern sector_buffer_t cdrom_sector_buffer; - -extern int cdrom_sector_type, cdrom_sector_flags; -extern int cdrom_sector_size, cdrom_sector_ismsf; - #define SCSI_PHASE_DATAOUT ( 0 ) #define SCSI_PHASE_DATAIN ( 1 ) #define SCSI_PHASE_COMMAND ( 2 ) @@ -250,7 +222,7 @@ extern int cdrom_sector_size, cdrom_sector_ismsf; struct { uint32_t pos; - uint8_t CmdBuffer[512*512]; + uint8_t CmdBuffer[390144]; uint32_t CmdBufferLength; int LunType; uint32_t InitLength; @@ -266,6 +238,10 @@ void SCSICDROM_Insert(); int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type); int cdrom_LBAtoMSF_accurate(); -int cdrom_read_data(uint8_t *buffer); +// int cdrom_read_data(uint8_t *buffer); + +int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save); +int mode_select_terminate(int force); +int mode_select_write(uint8_t val); #endif \ No newline at end of file diff --git a/src/scsi_cdrom.c b/src/scsi_cdrom.c deleted file mode 100644 index 1528fea91..000000000 --- a/src/scsi_cdrom.c +++ /dev/null @@ -1,1677 +0,0 @@ -/* Copyright holders: SA1988, Tenshi - see COPYING for more details -*/ -/*SCSI CD-ROM emulation*/ -#include -#include -#include "86box.h" -#include "ibm.h" - -#include "cdrom.h" -#include "scsi.h" - -sector_buffer_t cdrom_sector_buffer; - -int cdrom_sector_type, cdrom_sector_flags; -int cdrom_sector_size, cdrom_sector_ismsf; - -uint8_t SCSIPhase = SCSI_PHASE_BUS_FREE; -uint8_t SCSIStatus = SCSI_STATUS_OK; - -/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -uint8_t SCSICommandTable[0x100] = -{ - [GPCMD_TEST_UNIT_READY] = CHECK_READY | NONDATA, - [GPCMD_REQUEST_SENSE] = ALLOW_UA, - [GPCMD_READ_6] = CHECK_READY, - [GPCMD_SEEK_6] = CHECK_READY | NONDATA, - [GPCMD_INQUIRY] = ALLOW_UA, - [GPCMD_MODE_SELECT_6] = 0, - [GPCMD_MODE_SENSE_6] = 0, - [GPCMD_START_STOP_UNIT] = CHECK_READY, - [GPCMD_PREVENT_REMOVAL] = CHECK_READY, - [GPCMD_READ_CDROM_CAPACITY] = CHECK_READY, - [GPCMD_READ_10] = CHECK_READY, - [GPCMD_SEEK_10] = CHECK_READY | NONDATA, - [GPCMD_READ_SUBCHANNEL] = CHECK_READY, - [GPCMD_READ_TOC_PMA_ATIP] = CHECK_READY, /* Read TOC - can get through UNIT_ATTENTION, per VIDE-CDD.SYS - NOTE: The ATAPI reference says otherwise, but I think this is a question of - interpreting things right - the UNIT ATTENTION condition we have here - is a tradition from not ready to ready, by definition the drive - eventually becomes ready, make the condition go away. */ - [GPCMD_READ_HEADER] = CHECK_READY, - [GPCMD_PLAY_AUDIO_10] = CHECK_READY, - [GPCMD_GET_CONFIGURATION] = ALLOW_UA, - [GPCMD_PLAY_AUDIO_MSF] = CHECK_READY, - [GPCMD_GET_EVENT_STATUS_NOTIFICATION] = ALLOW_UA, - [GPCMD_PAUSE_RESUME] = CHECK_READY, - [GPCMD_STOP_PLAY_SCAN] = CHECK_READY, - [GPCMD_READ_DISC_INFORMATION] = CHECK_READY, - [GPCMD_READ_TRACK_INFORMATION] = CHECK_READY, - [GPCMD_MODE_SELECT_10] = 0, - [GPCMD_MODE_SENSE_10] = 0, - [GPCMD_PLAY_AUDIO_12] = CHECK_READY, - [GPCMD_READ_12] = CHECK_READY, - [GPCMD_READ_DVD_STRUCTURE] = CHECK_READY, - [GPCMD_READ_CD_MSF] = CHECK_READY, - [GPCMD_SET_SPEED] = 0, - [GPCMD_PLAY_CD] = CHECK_READY, - [GPCMD_MECHANISM_STATUS] = 0, - [GPCMD_READ_CD] = CHECK_READY, - [GPCMD_SEND_DVD_STRUCTURE] = CHECK_READY -}; - -uint8_t mode_sense_pages[0x40] = -{ - [GPMODE_R_W_ERROR_PAGE] = IMPLEMENTED, - [GPMODE_CDROM_PAGE] = IMPLEMENTED, - [GPMODE_CDROM_AUDIO_PAGE] = IMPLEMENTED, - [GPMODE_CAPABILITIES_PAGE] = IMPLEMENTED, - [GPMODE_ALL_PAGES] = IMPLEMENTED -}; - -uint8_t page_flags[256] = -{ - [GPMODE_R_W_ERROR_PAGE] = 0, - [GPMODE_CDROM_PAGE] = 0, - [GPMODE_CDROM_AUDIO_PAGE] = PAGE_CHANGEABLE, - [GPMODE_CAPABILITIES_PAGE] = 0, -}; - -CDROM *cdrom; - -int readcdmode = 0; - -uint8_t mode_pages_in[256][256]; -uint8_t prefix_len; -uint8_t page_current; - -/*SCSI Sense Initialization*/ -void SCSISenseCodeOk(void) -{ - SCSISense.SenseKey=SENSE_NONE; - SCSISense.Asc=0; - SCSISense.Ascq=0; -} - -void SCSISenseCodeError(uint8_t SenseKey, uint8_t Asc, uint8_t Ascq) -{ - SCSISense.SenseKey=SenseKey; - SCSISense.Asc=Asc; - SCSISense.Ascq=Ascq; - SCSIPhase = SCSI_PHASE_STATUS; /* This *HAS* to be done, SCSIPhase is the same thing that ATAPI returns in IDE sector count, so after any error, - status phase (3) is correct. */ -} - -static void -ScsiPadStr8(uint8_t *buf, int buf_size, const char *src) -{ - int i; - - for (i = 0; i < buf_size; i++) { - if (*src != '\0') { - buf[i] = *src++; - } else { - buf[i] = ' '; - } - } -} - -uint32_t SCSIGetCDChannel(int channel) -{ - return (page_flags[GPMODE_CDROM_AUDIO_PAGE] & PAGE_CHANGED) ? mode_pages_in[GPMODE_CDROM_AUDIO_PAGE][channel ? 8 : 6] : (channel + 1); -} - -uint32_t SCSIGetCDVolume(int channel) -{ - // return ((page_flags[GPMODE_CDROM_AUDIO_PAGE] & PAGE_CHANGED) && (mode_pages_in[GPMODE_CDROM_AUDIO_PAGE][channel ? 8 : 6] != 0)) ? mode_pages_in[GPMODE_CDROM_AUDIO_PAGE][channel ? 9 : 7] : 0xFF; - return (page_flags[GPMODE_CDROM_AUDIO_PAGE] & PAGE_CHANGED) ? mode_pages_in[GPMODE_CDROM_AUDIO_PAGE][channel ? 9 : 7] : 0xFF; -} - -/*SCSI Mode Sense 6/10*/ -uint32_t SCSICDROMModeSense(uint8_t *buf, uint32_t pos, uint8_t type) -{ - if (type==GPMODE_ALL_PAGES || type==GPMODE_R_W_ERROR_PAGE) - { - /* &01 - Read error recovery */ - buf[pos++] = GPMODE_R_W_ERROR_PAGE; - buf[pos++] = 6; /* Page length */ - buf[pos++] = 0; /* Error recovery parameters */ - buf[pos++] = 5; /* Read retry count */ - buf[pos++] = 0; /* Reserved */ - buf[pos++] = 0; /* Reserved */ - buf[pos++] = 0; /* Reserved */ - buf[pos++] = 0; /* Reserved */ - } - - if (type==GPMODE_ALL_PAGES || type==GPMODE_CDROM_PAGE) - { - /* &0D - CD-ROM Parameters */ - buf[pos++] = GPMODE_CDROM_PAGE; - buf[pos++] = 6; /* Page length */ - buf[pos++] = 0; /* Reserved */ - buf[pos++] = 1; /* Inactivity time multiplier *NEEDED BY RISCOS* value is a guess */ - buf[pos++] = 0; buf[pos++] = 60; /* MSF settings */ - buf[pos++] = 0; buf[pos++] = 75; /* MSF settings */ - } - - if (type==GPMODE_ALL_PAGES || type==GPMODE_CDROM_AUDIO_PAGE) - { - /* &0e - CD-ROM Audio Control Parameters */ - buf[pos++] = GPMODE_CDROM_AUDIO_PAGE; - buf[pos++] = 0xE; /* Page length */ - if (page_flags[GPMODE_CDROM_AUDIO_PAGE] & PAGE_CHANGED) - { - int i; - for (i = 0; i < 14; i++) - { - buf[pos++] = mode_pages_in[GPMODE_CDROM_AUDIO_PAGE][i]; - } - } - else - { - buf[pos++] = 4; /* Reserved */ - buf[pos++] = 0; /* Reserved */ - buf[pos++] = 0; /* Reserved */ - buf[pos++] = 0; /* Reserved */ - buf[pos++] = 0; buf[pos++] = 75; /* Logical audio block per second */ - buf[pos++] = 1; /* CDDA Output Port 0 Channel Selection */ - buf[pos++] = 0xFF; /* CDDA Output Port 0 Volume */ - buf[pos++] = 2; /* CDDA Output Port 1 Channel Selection */ - buf[pos++] = 0xFF; /* CDDA Output Port 1 Volume */ - buf[pos++] = 0; /* CDDA Output Port 2 Channel Selection */ - buf[pos++] = 0; /* CDDA Output Port 2 Volume */ - buf[pos++] = 0; /* CDDA Output Port 3 Channel Selection */ - buf[pos++] = 0; /* CDDA Output Port 3 Volume */ - } - } - - if (type==GPMODE_ALL_PAGES || type==GPMODE_CAPABILITIES_PAGE) - { -// pclog("Capabilities page\n"); - /* &2A - CD-ROM capabilities and mechanical status */ - buf[pos++] = GPMODE_CAPABILITIES_PAGE; - buf[pos++] = 0x12; /* Page length */ - buf[pos++] = 0; buf[pos++] = 0; /* CD-R methods */ - buf[pos++] = 1; /* Supports audio play, not multisession */ - buf[pos++] = 0; /* Some other stuff not supported */ - buf[pos++] = 0; /* Some other stuff not supported (lock state + eject) */ - buf[pos++] = 0; /* Some other stuff not supported */ - buf[pos++] = (uint8_t) (CDROM_SPEED >> 8); - buf[pos++] = (uint8_t) CDROM_SPEED; /* Maximum speed */ - buf[pos++] = 0; buf[pos++] = 2; /* Number of audio levels - on and off only */ - buf[pos++] = 0; buf[pos++] = 0; /* Buffer size - none */ - buf[pos++] = (uint8_t) (CDROM_SPEED >> 8); - buf[pos++] = (uint8_t) CDROM_SPEED; /* Current speed */ - buf[pos++] = 0; /* Reserved */ - buf[pos++] = 0; /* Drive digital format */ - buf[pos++] = 0; /* Reserved */ - buf[pos++] = 0; /* Reserved */ - } - - return pos; -} - -/*SCSI Get Configuration*/ -uint8_t SCSICDROMSetProfile(uint8_t *buf, uint8_t *index, uint16_t profile) -{ - uint8_t *buf_profile = buf + 12; /* start of profiles */ - - buf_profile += ((*index) * 4); /* start of indexed profile */ - buf_profile[0] = (profile >> 8) & 0xff; - buf_profile[1] = profile & 0xff; - buf_profile[2] = ((buf_profile[0] == buf[6]) && (buf_profile[1] == buf[7])); - - /* each profile adds 4 bytes to the response */ - (*index)++; - buf[11] += 4; /* Additional Length */ - - return 4; -} - -/*SCSI Read DVD Structure*/ -int SCSICDROMReadDVDStructure(int format, const uint8_t *packet, uint8_t *buf) -{ - switch (format) { - case 0x0: /* Physical format information */ - { - int layer = packet[6]; - uint64_t total_sectors; - total_sectors = (uint64_t) cdrom->size(); - - if (layer != 0) - return -ASC_INV_FIELD_IN_CMD_PACKET; - - total_sectors >>= 2; - if (total_sectors == 0) - return -ASC_MEDIUM_NOT_PRESENT; - - buf[4] = 1; /* DVD-ROM, part version 1 */ - buf[5] = 0xf; /* 120mm disc, minimum rate unspecified */ - buf[6] = 1; /* one layer, read-only (per MMC-2 spec) */ - buf[7] = 0; /* default densities */ - - /* FIXME: 0x30000 per spec? */ - buf[8] = buf[9] = buf[10] = buf[11] = 0; /* start sector */ - buf[12] = (total_sectors >> 24) & 0xff; /* end sector */ - buf[13] = (total_sectors >> 16) & 0xff; - buf[14] = (total_sectors >> 8) & 0xff; - buf[15] = total_sectors & 0xff; - - buf[16] = (total_sectors >> 24) & 0xff; /* l0 end sector */ - buf[17] = (total_sectors >> 16) & 0xff; - buf[18] = (total_sectors >> 8) & 0xff; - buf[19] = total_sectors & 0xff; - - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048+2)>>8)&0xff; - buf[1] = (2048+2)&0xff; - - /* 2k data + 4 byte header */ - return (2048 + 4); - } - - case 0x01: /* DVD copyright information */ - buf[4] = 0; /* no copyright data */ - buf[5] = 0; /* no region restrictions */ - - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((4+2)>>8)&0xff; - buf[1] = (4+2)&0xff; - - /* 4 byte header + 4 byte data */ - return (4 + 4); - - case 0x03: /* BCA information - invalid field for no BCA info */ - return -ASC_INV_FIELD_IN_CMD_PACKET; - - case 0x04: /* DVD disc manufacturing information */ - /* Size of buffer, not including 2 byte size field */ - buf[0] = ((2048+2)>>8)&0xff; - buf[1] = (2048+2)&0xff; - - /* 2k data + 4 byte header */ - return (2048 + 4); - - case 0xff: - /* - * This lists all the command capabilities above. Add new ones - * in order and update the length and buffer return values. - */ - - buf[4] = 0x00; /* Physical format */ - buf[5] = 0x40; /* Not writable, is readable */ - buf[6] = ((2048+4)>>8)&0xff; - buf[7] = (2048+4)&0xff; - - buf[8] = 0x01; /* Copyright info */ - buf[9] = 0x40; /* Not writable, is readable */ - buf[10] = ((4+4)>>8)&0xff; - buf[11] = (4+4)&0xff; - - buf[12] = 0x03; /* BCA info */ - buf[13] = 0x40; /* Not writable, is readable */ - buf[14] = ((188+4)>>8)&0xff; - buf[15] = (188+4)&0xff; - - buf[16] = 0x04; /* Manufacturing info */ - buf[17] = 0x40; /* Not writable, is readable */ - buf[18] = ((2048+4)>>8)&0xff; - buf[19] = (2048+4)&0xff; - - /* Size of buffer, not including 2 byte size field */ - buf[6] = ((16+2)>>8)&0xff; - buf[7] = (16+2)&0xff; - - /* data written + 4 byte header */ - return (16 + 4); - - default: /* TODO: formats beyond DVD-ROM requires */ - return -ASC_INV_FIELD_IN_CMD_PACKET; - } -} - -/*SCSI Get Event Status Notification*/ -uint32_t SCSICDROMEventStatus(uint8_t *buffer) -{ - uint8_t event_code, media_status = 0; - - if (buffer[5]) - { - media_status = MS_TRAY_OPEN; - cdrom->stop(); - } - else - { - media_status = MS_MEDIA_PRESENT; - } - - event_code = MEC_NO_CHANGE; - if (media_status != MS_TRAY_OPEN) - { - if (!buffer[4]) - { - event_code = MEC_NEW_MEDIA; - cdrom->load(); - } - else if (buffer[4]==2) - { - event_code = MEC_EJECT_REQUESTED; - cdrom->eject(); - } - } - - buffer[4] = event_code; - buffer[5] = media_status; - buffer[6] = 0; - buffer[7] = 0; - - return 8; -} - -void SCSICDROM_Insert() -{ - SCSISense.UnitAttention=1; -} - -int cd_status = CD_STATUS_EMPTY; -int prev_status; - -static uint8_t ScsiPrev; -static int SenseCompleted; - -int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type) -{ - if ((cdrom_sector_flags & 0x06) == 0x02) - { - /* Add error flags. */ - memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 294); - cdrom_sector_size += 294; - } - else if ((cdrom_sector_flags & 0x06) == 0x04) - { - /* Add error flags. */ - memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.c2, 296); - cdrom_sector_size += 296; - } - else if ((cdrom_sector_flags & 0x06) == 0x06) - { - // pclog("Invalid error flags\n"); - return 0; - } - - /* if (real_sector_type == 1) - { */ - if ((cdrom_sector_flags & 0x700) == 0x100) - { - memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_raw, 96); - cdrom_sector_size += 96; - } - else if ((cdrom_sector_flags & 0x700) == 0x200) - { - memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_q, 16); - cdrom_sector_size += 16; - } - else if ((cdrom_sector_flags & 0x700) == 0x400) - { - memcpy(b + cdrom_sector_size, cdrom_sector_buffer.cdrom_sector.subchannel_rw, 96); - cdrom_sector_size += 96; - } - else if (((cdrom_sector_flags & 0x700) == 0x300) || ((cdrom_sector_flags & 0x700) > 0x400)) - { - // pclog("Invalid subchannel data flags\n"); - return 0; - } - // } - - // pclog("CD-ROM sector size after processing: %i (%i, %i) [%04X]\n", cdrom_sector_size, cdrom_sector_type, real_sector_type, cdrom_sector_flags); - - return cdrom_sector_size; -} - -int cdrom_LBAtoMSF_accurate() -{ - int temp_pos; - int m, s, f; - - temp_pos = SectorLBA + 150; - f = temp_pos % 75; - temp_pos -= f; - temp_pos /= 75; - s = temp_pos % 60; - temp_pos -= s; - temp_pos /= 60; - m = temp_pos; - - return ((m << 16) | (s << 8) | f); -} - -int cdrom_read_data(uint8_t *buffer) -{ - int real_sector_type; - uint8_t *b; - uint8_t *temp_b; - int is_audio; - int real_pos; - - b = temp_b = buffer; - - if (cdrom_sector_ismsf) - { - real_pos = cdrom_LBAtoMSF_accurate(); - } - else - { - real_pos = SectorLBA; - } - - memset(cdrom_sector_buffer.buffer, 0, 2856); - - // is_audio = cdrom->is_track_audio(real_pos, cdrom_sector_ismsf); - real_sector_type = cdrom->sector_data_type(real_pos, cdrom_sector_ismsf); - // pclog("Sector type: %i\n", real_sector_type); - - if ((cdrom_sector_type > 0) && (cdrom_sector_type < 6)) - { - if (real_sector_type != cdrom_sector_type) - { - return 0; - } - } - else if (cdrom_sector_type == 6) - { - /* READ (6), READ (10), READ (12) */ - if ((real_sector_type != 2) && (real_sector_type != 4)) - { - return 0; - } - } - - if (!(cdrom_sector_flags & 0xf0)) /* 0x00 and 0x08 are illegal modes */ - { - return 0; - } - - cdrom->readsector_raw(cdrom_sector_buffer.buffer, real_pos, cdrom_sector_ismsf); - - if (real_sector_type == 1) - { - memcpy(b, cdrom_sector_buffer.buffer, 2352); - cdrom_sector_size = 2352; - } - else - { - if ((cdrom_sector_flags & 0x18) == 0x08) /* EDC/ECC without user data is an illegal mode */ - { - return 0; - } - - cdrom_sector_size = 0; - - if (cdrom_sector_flags & 0x80) /* Sync */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.sync, 12); - cdrom_sector_size += 12; - temp_b += 12; - } - if (cdrom_sector_flags & 0x20) /* Header */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.header, 4); - cdrom_sector_size += 4; - temp_b += 4; - } - - if (real_sector_type == 2) - { - /* Mode 1 sector, expected type is 1 type. */ - if (cdrom_sector_flags & 0x40) /* Sub-header */ - { - if (!(cdrom_sector_flags & 0x10)) /* No user data */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - } - if (cdrom_sector_flags & 0x10) /* User data */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.user_data, 2048); - cdrom_sector_size += 2048; - temp_b += 2048; - } - if (cdrom_sector_flags & 0x08) /* EDC/ECC */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m1_data.ecc, 288); - cdrom_sector_size += 288; - temp_b += 288; - } - } - else if (real_sector_type == 3) - { - /* Mode 2 sector, non-XA mode. */ - if (cdrom_sector_flags & 0x40) /* Sub-header */ - { - if (!(cdrom_sector_flags & 0x10)) /* No user data */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - } - if (cdrom_sector_flags & 0x10) /* User data */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 2328); - cdrom_sector_size += 8; - temp_b += 8; - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2328); - cdrom_sector_size += 2328; - temp_b += 2328; - } - } - else if (real_sector_type == 4) - { - /* Mode 2 sector, XA Form 1 mode */ - if ((cdrom_sector_flags & 0xf0) == 0x30) - { - return 0; - } - if (((cdrom_sector_flags & 0xf8) >= 0xa8) && ((cdrom_sector_flags & 0xf8) <= 0xd8)) - { - return 0; - } - if (cdrom_sector_flags & 0x40) /* Sub-header */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - if (cdrom_sector_flags & 0x10) /* User data */ - { - if ((cdrom_sector_flags & 0xf0) == 0x10) - { - /* The data is alone, include sub-header. */ - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2040); - cdrom_sector_size += 2040; - temp_b += 2040; - } - if (cdrom_sector_flags & 0x08) /* EDC/ECC */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data + 2040, 288); - cdrom_sector_size += 288; - temp_b += 288; - } - } - else if (real_sector_type == 5) - { - /* Mode 2 sector, XA Form 2 mode */ - if ((cdrom_sector_flags & 0xf0) == 0x30) - { - return 0; - } - if (((cdrom_sector_flags & 0xf8) >= 0xa8) || ((cdrom_sector_flags & 0xf8) <= 0xd8)) - { - return 0; - } - /* Mode 2 sector, XA Form 1 mode */ - if (cdrom_sector_flags & 0x40) /* Sub-header */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.sub_header, 8); - cdrom_sector_size += 8; - temp_b += 8; - } - if (cdrom_sector_flags & 0x10) /* User data */ - { - memcpy(temp_b, cdrom_sector_buffer.cdrom_sector.data.m2_data.user_data, 2328); - cdrom_sector_size += 2328; - temp_b += 2328; - } - } - else - { - return 0; - } - } - - pclog("CD-ROM sector size: %i (%i, %i) [%04X]\n", cdrom_sector_size, cdrom_sector_type, real_sector_type, cdrom_sector_flags); - return cdrom_add_error_and_subchannel(b, real_sector_type); -} - -void SCSIClearSense(uint8_t Command, uint8_t IgnoreUA) -{ - if ((SCSISense.SenseKey == SENSE_UNIT_ATTENTION) || IgnoreUA) - { - pclog("Sense cleared\n"); - ScsiPrev=Command; - SCSISenseCodeOk(); - } -} - -struct -{ - uint8_t opcode; - uint8_t polled; - uint8_t reserved2[2]; - uint8_t class; - uint8_t reserved3[2]; - uint16_t len; - uint8_t control; -} *gesn_cdb; - -struct -{ - uint16_t len; - uint8_t notification_class; - uint8_t supported_events; -} *gesn_event_header; - -static int SCSICDROM_TOC(uint8_t id, uint8_t *cdb) -{ - int TocFormat; - - TocFormat = cdb[2] & 0xf; - if (TocFormat == 0) - TocFormat = (cdb[9]>>6) & 3; - - return TocFormat; -} - -void SCSICDROM_Command(uint8_t id, uint8_t *cmdbuffer, uint8_t *cdb) -{ - int len; - int pos=0; - int DVDRet; - uint8_t Index = 0; - int real_pos; - int msf; - uint32_t Size; - unsigned Idx = 0; - unsigned SizeIndex; - unsigned PreambleLen; - unsigned char Temp; - int max_length = 0; - int track = 0; - int ret = 0; - - msf = cdb[1] & 2; - - //The not ready/unit attention stuff below is only for the Adaptec! - //The Buslogic one is located in buslogic.c. - - if (!scsi_model) - { - if (cdrom->medium_changed()) - { - pclog("Media changed\n"); - SCSICDROM_Insert(); - } - - if (!cdrom->ready() && SCSISense.UnitAttention) - { - /* If the drive is not ready, there is no reason to keep the - UNIT ATTENTION condition present, as we only use it to mark - disc changes. */ - SCSISense.UnitAttention = 0; - } - - /* If the UNIT ATTENTION condition is set and the command does not allow - execution under it, error out and report the condition. */ - if (SCSISense.UnitAttention == 1) - { - SCSISense.UnitAttention = 2; - if (!(SCSICommandTable[cdb[0]] & ALLOW_UA)) - { - SCSISenseCodeError(SENSE_UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED, 0); - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSICallback[id]=50*SCSI_TIME; - return; - } - } - else if (SCSISense.UnitAttention == 2) - { - if (cdb[0]!=GPCMD_REQUEST_SENSE) - { - SCSISense.UnitAttention = 0; - } - } - - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - clear the UNIT ATTENTION condition if it's set. */ - if (cdb[0]!=GPCMD_REQUEST_SENSE) - { - SCSIClearSense(cdb[0], 0); - } - - /* Next it's time for NOT READY. */ - if ((SCSICommandTable[cdb[0]] & CHECK_READY) && !cdrom->ready()) - { - pclog("Not ready\n"); - SCSISenseCodeError(SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSICallback[id]=50*SCSI_TIME; - return; - } - } - - prev_status = cd_status; - cd_status = cdrom->status(); - if (((prev_status == CD_STATUS_PLAYING) || (prev_status == CD_STATUS_PAUSED)) && ((cd_status != CD_STATUS_PLAYING) && (cd_status != CD_STATUS_PAUSED))) - { - SenseCompleted = 1; - } - else - { - SenseCompleted = 0; - } - - switch (cdb[0]) - { - case GPCMD_TEST_UNIT_READY: - SCSIPhase = SCSI_PHASE_STATUS; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=50*SCSI_TIME; - break; - - case GPCMD_REQUEST_SENSE: - len = cdb[4]; - - /*Will return 18 bytes of 0*/ - memset(cmdbuffer,0,512); - - cmdbuffer[0]=0x80|0x70; - - if ((SCSISense.SenseKey > 0) || (cd_status < CD_STATUS_PLAYING)) - { - if (SenseCompleted) - { - cmdbuffer[2]=SENSE_ILLEGAL_REQUEST; - cmdbuffer[12]=ASC_AUDIO_PLAY_OPERATION; - cmdbuffer[13]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; - } - else - { - cmdbuffer[2]=SCSISense.SenseKey; - cmdbuffer[12]=SCSISense.Asc; - cmdbuffer[13]=SCSISense.Ascq; - } - } - else if ((SCSISense.SenseKey == 0) && (cd_status >= CD_STATUS_PLAYING) && (cd_status != CD_STATUS_STOPPED)) - { - cmdbuffer[2]=SENSE_ILLEGAL_REQUEST; - cmdbuffer[12]=ASC_AUDIO_PLAY_OPERATION; - cmdbuffer[13]=(cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; - } - else - { - if (SCSISense.UnitAttention) - { - cmdbuffer[2]=SENSE_UNIT_ATTENTION; - cmdbuffer[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - cmdbuffer[13]=0; - } - } - - cmdbuffer[7]=10; - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = len; - - SCSIDMAResetPosition(id); - - if (cmdbuffer[2] == SENSE_UNIT_ATTENTION) - { - /* If the last remaining sense is unit attention, clear - that condition. */ - SCSISense.UnitAttention = 0; - } - - /* Clear the sense stuff as per the spec. */ - ScsiPrev=cdb[0]; - if (cdrom->ready()) - SCSISenseCodeOk(); - return; - - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - cdrom_sector_ismsf = 0; - - if (cdb[0] == GPCMD_READ_6) - { - SectorLen=cdb[4]; - SectorLBA=((((uint32_t) cdb[1]) & 0x1f)<<16)|(((uint32_t) cdb[2])<<8)|((uint32_t) cdb[3]); - } - else if (cdb[0] == GPCMD_READ_10) - { - SectorLen=(cdb[7]<<8)|cdb[8]; - SectorLBA=(cdb[2]<<24)|(cdb[3]<<16)|(cdb[4]<<8)|cdb[5]; - } - else - { - SectorLen=(((uint32_t) cdb[6])<<24)|(((uint32_t) cdb[7])<<16)|(((uint32_t) cdb[8])<<8)|((uint32_t) cdb[9]); - SectorLBA=(((uint32_t) cdb[2])<<24)|(((uint32_t) cdb[3])<<16)|(((uint32_t) cdb[4])<<8)|((uint32_t) cdb[5]); - } - - if (SectorLBA > (cdrom->size() - 1)) - { - pclog("Trying to read beyond the end of disc\n"); - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0); - SCSICallback[id]=50*SCSI_TIME; - break; - } - - if (!SectorLen) - { - SCSIPhase = SCSI_PHASE_STATUS; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=20*SCSI_TIME; - break; - } - - cdrom_sector_type = 6; - cdrom_sector_flags = 0x10; - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = SectorLen * 2048; - - SCSIDMAResetPosition(id); - return; - - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - if (cdb[0] == GPCMD_SEEK_6) - { - pos = ((((uint32_t) cdb[1]) & 0x1f)<<16)|(((uint32_t) cdb[2])<<8)|((uint32_t) cdb[3]); - } - else - { - pos = (cdb[2]<<24)|(cdb[3]<<16)|(cdb[4]<<8)|cdb[5]; - } - cdrom->seek(pos); - - SCSIPhase = SCSI_PHASE_STATUS; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=50*SCSI_TIME; - break; - - case GPCMD_INQUIRY: - max_length = cdb[4]; - len = max_length; - - if (cdb[1] & 1) - { - PreambleLen = 4; - SizeIndex = 3; - - cmdbuffer[Idx++] = 05; - cmdbuffer[Idx++] = cdb[2]; - cmdbuffer[Idx++] = 0; - - Idx++; - - switch (cdb[2]) - { - case 0x00: - cmdbuffer[Idx++] = 0x00; - cmdbuffer[Idx++] = 0x83; - break; - - case 0x83: - if (Idx + 24 > max_length) - { - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_DATA_PHASE_ERROR, 0x00); - SCSICallback[id]=50*SCSI_TIME; - return; - } - cmdbuffer[Idx++] = 0x02; - cmdbuffer[Idx++] = 0x00; - cmdbuffer[Idx++] = 0x00; - cmdbuffer[Idx++] = 20; - ScsiPadStr8(cmdbuffer + Idx, 20, "53R141"); /* Serial */ - Idx += 20; - - if (Idx + 72 > max_length) - { - goto SCSIOut; - } - cmdbuffer[Idx++] = 0x02; - cmdbuffer[Idx++] = 0x01; - cmdbuffer[Idx++] = 0x00; - cmdbuffer[Idx++] = 68; - ScsiPadStr8(cmdbuffer + Idx, 8, "86Box"); /* Vendor */ - Idx += 8; - ScsiPadStr8(cmdbuffer + Idx, 40, "86BoxCD 1.00"); /* Product */ - Idx += 40; - ScsiPadStr8(cmdbuffer + Idx, 20, "53R141"); /* Product */ - Idx += 20; - break; - - default: - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - return; - } - } - else - { - PreambleLen = 5; - SizeIndex = 4; - - cmdbuffer[0] = 0x05; /*CD-ROM*/ - cmdbuffer[1] = 0x80; /*Removable*/ - cmdbuffer[2] = 0; - cmdbuffer[3] = 0x21; - cmdbuffer[4] = 31; - cmdbuffer[5] = 0; - cmdbuffer[6] = 0; - cmdbuffer[7] = 0; - ScsiPadStr8(cmdbuffer + 8, 8, "86Box"); /* Vendor */ - ScsiPadStr8(cmdbuffer + 16, 16, "86BoxCD"); /* Product */ - ScsiPadStr8(cmdbuffer + 32, 4, emulator_version); /* Revision */ - - Idx = 36; - } - -SCSIOut: - cmdbuffer[SizeIndex] = Idx - PreambleLen; - len=Idx; - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = len; - - SCSIDMAResetPosition(id); - break; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - if (cdb[0] == GPCMD_MODE_SELECT_6) - { - len = cdb[4]; - prefix_len = 6; - } - else - { - len = (cdb[7]<<8)|cdb[8]; - prefix_len = 10; - } - - page_current = cdb[2]; - if (page_flags[page_current] & PAGE_CHANGEABLE) - page_flags[GPMODE_CDROM_AUDIO_PAGE] |= PAGE_CHANGED; - - SCSIPhase = SCSI_PHASE_DATAOUT; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = len; - - SCSIDMAResetPosition(id); - return; - - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - if (cdb[0] == GPCMD_MODE_SENSE_6) - len = cdb[4]; - else - len = (cdb[7]<<8)|cdb[8]; - - Temp = cdb[2] & 0x3F; - - memset(cmdbuffer, 0, len); - - if (!(mode_sense_pages[cdb[2] & 0x3f] & IMPLEMENTED)) - { - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - return; - } - - if (cdb[0] == GPCMD_MODE_SENSE_6) - { - len = SCSICDROMModeSense(cmdbuffer, 4, Temp); - cmdbuffer[0] = len - 1; - cmdbuffer[1] = 3; /*120mm data CD-ROM*/ - } - else - { - len = SCSICDROMModeSense(cmdbuffer, 8, Temp); - cmdbuffer[0] = (len - 2)>>8; - cmdbuffer[1] = (len - 2)&255; - cmdbuffer[2] = 3; /*120mm data CD-ROM*/ - } - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = len; - - SCSIDMAResetPosition(id); - return; - - case GPCMD_START_STOP_UNIT: - switch(cdb[4] & 3) - { - case 0: /* Stop the disc. */ - cdrom->stop(); - break; - case 1: /* Start the disc and read the TOC. */ - cdrom->medium_changed(); /* This causes a TOC reload. */ - break; - case 2: /* Eject the disc if possible. */ - cdrom->stop(); -#ifndef __unix - win_cdrom_eject(); -#endif - break; - case 3: /* Load the disc (close tray). */ -#ifndef __unix - win_cdrom_reload(); -#else - cdrom->load(); -#endif - break; - } - - SCSIPhase = SCSI_PHASE_STATUS; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=50*SCSI_TIME; - break; - - case GPCMD_PREVENT_REMOVAL: - SCSIPhase = SCSI_PHASE_STATUS; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=50*SCSI_TIME; - break; - - case GPCMD_READ_CDROM_CAPACITY: - if (cdrom->read_capacity) - { - cdrom->read_capacity(cmdbuffer); - } - else - { - Size = cdrom->size() - 1; /* IMPORTANT: What's returned is the last LBA block. */ - memset(cmdbuffer, 0, 8); - cmdbuffer[0] = (Size >> 24) & 0xff; - cmdbuffer[1] = (Size >> 16) & 0xff; - cmdbuffer[2] = (Size >> 8) & 0xff; - cmdbuffer[3] = Size & 0xff; - cmdbuffer[6] = 8; /* 2048 = 0x0800 */ - } - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = 8; - - SCSIDMAResetPosition(id); - break; - - case GPCMD_READ_SUBCHANNEL: - if (cdb[3] > 3) - { - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - break; - } - - switch(cdb[3]) - { - case 0: - Temp = 4; - break; - case 1: - Temp = 16; - break; - default: - Temp = 24; - break; - } - - if (cdrom->read_subchannel) - { - cdrom->read_subchannel(cdb, cmdbuffer); - len = Temp; - } - else - { - memset(cmdbuffer, 24, 0); - pos = 0; - cmdbuffer[pos++]=0; - cmdbuffer[pos++]=0; /*Audio status*/ - cmdbuffer[pos++]=0; cmdbuffer[pos++]=0; /*Subchannel length*/ - cmdbuffer[pos++]=cdb[3]; /*Format code*/ - if (!(cdb[2] & 0x40) || (cdb[3] == 0)) - { - len = 4; - } - else - { - len = Temp; - } - if (cdb[3] == 1) - { - cmdbuffer[1]=cdrom->getcurrentsubchannel(&cmdbuffer[5],msf); - } - } - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=1000*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = len; - - SCSIDMAResetPosition(id); - break; - - case GPCMD_READ_TOC_PMA_ATIP: - switch (SCSICDROM_TOC(id, cdb)) - { - case 0: /*Normal*/ - len = cdb[8]|(cdb[7]<<8); - len = cdrom->readtoc(cmdbuffer, cdb[6], msf, len, 0); - break; - - case 1: /*Multi session*/ - len = cdb[8]|(cdb[7]<<8); - len = cdrom->readtoc_session(cmdbuffer, msf, len); - cmdbuffer[0] = 0; - cmdbuffer[1] = 0xA; - break; - - case 2: /*Raw*/ - len = cdb[8]|(cdb[7]<<8); - len = cdrom->readtoc_raw(cmdbuffer, msf, len); - break; - - default: - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - return; - } - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = len; - - SCSIDMAResetPosition(id); - return; - - case GPCMD_READ_HEADER: - if (cdrom->read_header) - { - cdrom->read_header(cdb, cmdbuffer); - } - else - { - SectorLen=(cdb[7]<<8)|cdb[8]; - SectorLBA=(cdb[2]<<24)|(cdb[3]<<16)|(cdb[4]<<8)|cdb[5]; - if (msf) - { - real_pos = cdrom_LBAtoMSF_accurate(); - } - else - { - real_pos = SectorLBA; - } - cmdbuffer[4] = (real_pos >> 24); - cmdbuffer[5] = ((real_pos >> 16) & 0xff); - cmdbuffer[6] = ((real_pos >> 8) & 0xff); - cmdbuffer[7] = real_pos & 0xff; - cmdbuffer[0]=1; /*2048 bytes user data*/ - cmdbuffer[1]=cmdbuffer[2]=cmdbuffer[3]=0; - } - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = 8; - - SCSIDMAResetPosition(id); - break; - - case GPCMD_PLAY_AUDIO_10: - case GPCMD_PLAY_AUDIO_MSF: - case GPCMD_PLAY_AUDIO_12: - if (cdb[0] == GPCMD_PLAY_AUDIO_10) - { - pos = (cdb[2]<<24)|(cdb[3]<<16)|(cdb[4]<<8)|cdb[5]; - len = (cdb[7]<<8)|cdb[8]; - } - else if (cdb[0] == GPCMD_PLAY_AUDIO_MSF) - { - pos = (cdb[3]<<16)|(cdb[4]<<8)|cdb[5]; - len = (cdb[6]<<16)|(cdb[7]<<8)|cdb[8]; - } - else - { - pos = (cdb[3]<<16)|(cdb[4]<<8)|cdb[5]; - len = (cdb[7]<<16)|(cdb[8]<<8)|cdb[9]; - } - - if ((cdrom_drive < 1) || (cdrom_drive == 200) || (cd_status <= CD_STATUS_DATA_ONLY) || - !cdrom->is_track_audio(pos, (cdb[0] == GPCMD_PLAY_AUDIO_MSF) ? 1 : 0)) - { - pclog("Invalid mode for this track\n"); - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_MODE_FOR_THIS_TRACK, 0x00); - SCSICallback[id]=50*SCSI_TIME; - break; - } - - cdrom->playaudio(pos, len, (cdb[0] == GPCMD_PLAY_AUDIO_MSF) ? 1 : 0); - SCSIPhase = SCSI_PHASE_STATUS; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=50*SCSI_TIME; - break; - - case GPCMD_GET_CONFIGURATION: - len = (cdb[7]<<8)|cdb[8]; - - Index = 0; - - /* only feature 0 is supported */ - if (cdb[2] != 0 || cdb[3] != 0) - { - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - return; - } - - /* - * XXX: avoid overflow for io_buffer if length is bigger than - * the size of that buffer (dimensioned to max number of - * sectors to transfer at once) - * - * Only a problem if the feature/profiles grow. - */ - if (len > 512) /* XXX: assume 1 sector */ - len = 512; - - memset(cmdbuffer, 0, len); - /* - * the number of sectors from the media tells us which profile - * to use as current. 0 means there is no media - */ - if (len > CD_MAX_SECTORS ) - { - cmdbuffer[6] = (MMC_PROFILE_DVD_ROM >> 8) & 0xff; - cmdbuffer[7] = MMC_PROFILE_DVD_ROM & 0xff; - } - else if (len <= CD_MAX_SECTORS) - { - cmdbuffer[6] = (MMC_PROFILE_CD_ROM >> 8) & 0xff; - cmdbuffer[7] = MMC_PROFILE_CD_ROM & 0xff; - } - cmdbuffer[10] = 0x02 | 0x01; /* persistent and current */ - len = 12; /* headers: 8 + 4 */ - len += SCSICDROMSetProfile(cmdbuffer, &Index, MMC_PROFILE_DVD_ROM); - len += SCSICDROMSetProfile(cmdbuffer, &Index, MMC_PROFILE_CD_ROM); - cmdbuffer[0] = ((len-4) >> 24) & 0xff; - cmdbuffer[1] = ((len-4) >> 16) & 0xff; - cmdbuffer[2] = ((len-4) >> 8) & 0xff; - cmdbuffer[3] = (len-4) & 0xff; - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = len; - - SCSIDMAResetPosition(id); - break; - - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: - gesn_cdb = (void *)cdb; - gesn_event_header = (void *)cmdbuffer; - - /* It is fine by the MMC spec to not support async mode operations */ - if (!(gesn_cdb->polled & 0x01)) - { /* asynchronous mode */ - /* Only pollign is supported, asynchronous mode is not. */ - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - return; - } - - /* polling mode operation */ - - /* - * These are the supported events. - * - * We currently only support requests of the 'media' type. - * Notification class requests and supported event classes are bitmasks, - * but they are built from the same values as the "notification class" - * field. - */ - gesn_event_header->supported_events = 1 << GESN_MEDIA; - - /* - * We use |= below to set the class field; other bits in this byte - * are reserved now but this is useful to do if we have to use the - * reserved fields later. - */ - gesn_event_header->notification_class = 0; - - /* - * Responses to requests are to be based on request priority. The - * notification_class_request_type enum above specifies the - * priority: upper elements are higher prio than lower ones. - */ - if (gesn_cdb->class & (1 << GESN_MEDIA)) - { - gesn_event_header->notification_class |= GESN_MEDIA; - len = SCSICDROMEventStatus(cmdbuffer); - } - else - { - gesn_event_header->notification_class = 0x80; /* No event available */ - SCSIDevices[id].CmdBufferLength = sizeof(*gesn_event_header); - } - gesn_event_header->len = len - sizeof(*gesn_event_header); - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = len; - - SCSIDMAResetPosition(id); - break; - - case GPCMD_PAUSE_RESUME: - if (cdb[8]&1) cdrom->resume(); - else cdrom->pause(); - SCSIPhase = SCSI_PHASE_STATUS; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=50*SCSI_TIME; - break; - - case GPCMD_STOP_PLAY_SCAN: - cdrom->stop(); - SCSIPhase = SCSI_PHASE_STATUS; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=50*SCSI_TIME; - break; - - case GPCMD_READ_DISC_INFORMATION: - if (cdrom->read_disc_information) - { - cdrom->read_disc_information(cmdbuffer); - } - else - { - cmdbuffer[1] = 32; - cmdbuffer[2] = 0xe; /* last session complete, disc finalized */ - cmdbuffer[3] = 1; /* first track on disc */ - cmdbuffer[4] = 1; /* # of sessions */ - cmdbuffer[5] = 1; /* first track of last session */ - cmdbuffer[6] = 1; /* last track of last session */ - cmdbuffer[7] = 0x20; /* unrestricted use */ - cmdbuffer[8] = 0x00; /* CD-ROM */ - } - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = 34; - - SCSIDMAResetPosition(id); - break; - - case GPCMD_READ_TRACK_INFORMATION: - max_length = cdb[7]; - max_length <<= 8; - max_length |= cdb[8]; - - track = ((uint32_t) cdb[2]) << 24; - track |= ((uint32_t) cdb[3]) << 16; - track |= ((uint32_t) cdb[4]) << 8; - track |= (uint32_t) cdb[5]; - - if (cdrom->read_track_information) - { - ret = cdrom->read_track_information(cdb, cmdbuffer); - - if (!ret) - { - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - return; - } - - len = cmdbuffer[0]; - len <<= 8; - len |= cmdbuffer[1]; - len += 2; - } - else - { - if (((cdb[1] & 0x03) != 1) || (track != 1)) - { - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - return; - } - - len = 36; - cmdbuffer[1] = 34; - cmdbuffer[2] = 1; /* track number (LSB) */ - cmdbuffer[3] = 1; /* session number (LSB) */ - cmdbuffer[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ - cmdbuffer[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ - cmdbuffer[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ - cmdbuffer[8] = 0; /* track start address is 0 */ - cmdbuffer[24] = (cdrom->size() >> 24) & 0xff; /* track size */ - cmdbuffer[25] = (cdrom->size() >> 16) & 0xff; /* track size */ - cmdbuffer[26] = (cdrom->size() >> 8) & 0xff; /* track size */ - cmdbuffer[27] = cdrom->size() & 0xff; /* track size */ - cmdbuffer[32] = 0; /* track number (MSB) */ - cmdbuffer[33] = 0; /* session number (MSB) */ - } - - if (len > max_length) - { - len = max_length; - cmdbuffer[0] = ((max_length - 2) >> 8) & 0xff; - cmdbuffer[1] = (max_length - 2) & 0xff; - } - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = len; - - SCSIDMAResetPosition(id); - break; - - case GPCMD_READ_DVD_STRUCTURE: - len = (cdb[6]<<24)|(cdb[7]<<16)|(cdb[8]<<8)|cdb[9]; - - if (cdb[7] < 0xff) - { - if (len <= CD_MAX_SECTORS) - { - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INCOMPATIBLE_FORMAT, 0x00); - SCSICallback[id]=50*SCSI_TIME; - break; - } - else - { - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - return; - } - } - - memset(cmdbuffer, 0, len > 256 * 512 + 4 ? 256 * 512 + 4 : len); - - switch (cdb[7]) - { - case 0x00 ... 0x7f: - case 0xff: - if (cdb[1] == 0) - { - DVDRet = SCSICDROMReadDVDStructure(cdb[7], cdb, cmdbuffer); - - if (DVDRet < 0) - { - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, -DVDRet, 0x00); - SCSICallback[id]=50*SCSI_TIME; - return; - } - else - { - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = len; - - SCSIDMAResetPosition(id); - } - break; - } - /* TODO: BD support, fall through for now */ - - /* Generic disk structures */ - case 0x80: /* TODO: AACS volume identifier */ - case 0x81: /* TODO: AACS media serial number */ - case 0x82: /* TODO: AACS media identifier */ - case 0x83: /* TODO: AACS media key block */ - case 0x90: /* TODO: List of recognized format layers */ - case 0xc0: /* TODO: Write protection status */ - default: - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - return; - } - break; - - case GPCMD_READ_CD_MSF: - case GPCMD_READ_CD: - if (cdb[0] == GPCMD_READ_CD_MSF) - { - SectorLBA=MSFtoLBA(cdb[3],cdb[4],cdb[5]); - SectorLen=MSFtoLBA(cdb[6],cdb[7],cdb[8]); - - SectorLen -= SectorLBA; - SectorLen++; - - cdrom_sector_ismsf = 1; - } - else - { - SectorLen=(cdb[6]<<16)|(cdb[7]<<8)|cdb[8]; - SectorLBA=(cdb[2]<<24)|(cdb[3]<<16)|(cdb[4]<<8)|cdb[5]; - - cdrom_sector_ismsf = 0; - } - - if (SectorLBA > (cdrom->size() - 1)) - { - //pclog("Trying to read beyond the end of disc\n"); - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0); - SCSICallback[id]=50*SCSI_TIME; - break; - } - - cdrom_sector_type = (cdb[1] >> 2) & 7; - cdrom_sector_flags = cdb[9] || ((cdb[10]) << 8); - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = SectorLen * cdrom_sector_size; - - SCSIDMAResetPosition(id); - return; - - case GPCMD_SET_SPEED: - SCSIPhase = SCSI_PHASE_STATUS; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=50*SCSI_TIME; - break; - - case GPCMD_MECHANISM_STATUS: - cmdbuffer[0] = 0; - cmdbuffer[1] = 0; - cmdbuffer[2] = 0; - cmdbuffer[3] = 0; - cmdbuffer[4] = 0; - cmdbuffer[5] = 1; - cmdbuffer[6] = 0; - cmdbuffer[7] = 0; - - SCSIPhase = SCSI_PHASE_DATAIN; - SCSIStatus = SCSI_STATUS_OK; - SCSICallback[id]=60*SCSI_TIME; - SCSIDevices[id].CmdBufferLength = 8; - - SCSIDMAResetPosition(id); - break; - } - - -} - -void SCSICDROM_ReadData(uint8_t id, uint8_t *cdb, uint8_t *data, int datalen) -{ - int read_length = 0; - - switch (cdb[0]) - { - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - case GPCMD_READ_CD_MSF: - case GPCMD_READ_CD: - pclog("Total data length requested: %d\n", datalen); - while (datalen > 0) - { - read_length = cdrom_read_data(data); //Fill the buffer the data it needs - if (!read_length) - { - pclog("Invalid read\n"); - SCSIStatus = SCSI_STATUS_CHECK_CONDITION; - SCSISenseCodeError(SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0x00); - SCSICallback[id]=50*SCSI_TIME; - break; - } - else - { - //Continue reading data until the sector length is 0. - data += read_length; - datalen -= read_length; - } - - pclog("True LBA: %d, buffer half: %d\n", SectorLBA, SectorLen * cdrom_sector_size); - - SectorLBA++; - SectorLen--; - - if (SectorLen == 0) - break; - } - break; - } -} diff --git a/src/sound.c b/src/sound.c index 54d1bf032..97ee72733 100644 --- a/src/sound.c +++ b/src/sound.c @@ -1,6 +1,10 @@ +#include #include #include + +#include "cdrom.h" #include "ibm.h" + #include "device.h" #include "filters.h" @@ -89,7 +93,8 @@ int sound_pos_global = 0; int soundon = 1; -static int16_t cd_buffer[CD_BUFLEN * 2]; +static int16_t cd_buffer[CDROM_NUM][CD_BUFLEN * 2]; +static float cd_out_buffer[CD_BUFLEN * 2]; static thread_t *sound_cd_thread_h; static event_t *sound_cd_event; static unsigned int cd_vol_l, cd_vol_r; @@ -102,62 +107,81 @@ void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r) static void sound_cd_thread(void *param) { + int i = 0; + while (1) { - int c; + int c, has_audio; thread_wait_event(sound_cd_event, -1); - ioctl_audio_callback(cd_buffer, CD_BUFLEN*2); - if (soundon) - { - int32_t audio_vol_l = SCSIGetCDVolume(0); - int32_t audio_vol_r = SCSIGetCDVolume(1); - int channel_select[2]; + for (c = 0; c < CD_BUFLEN*2; c += 2) + { + cd_out_buffer[c] = 0; + cd_out_buffer[c+1] = 0; + } + for (i = 0; i < CDROM_NUM; i++) + { + has_audio = 0; + if (cdrom_drives[i].handler->audio_callback) + { + cdrom_drives[i].handler->audio_callback(i, cd_buffer[i], CD_BUFLEN*2); + has_audio = cdrom_drives[i].sound_on; + } + if (soundon && has_audio) + { + int32_t audio_vol_l = cdrom_mode_sense_get_volume(i, 0); + int32_t audio_vol_r = cdrom_mode_sense_get_volume(i, 1); + int channel_select[2]; + + channel_select[0] = cdrom_mode_sense_get_channel(i, 0); + channel_select[1] = cdrom_mode_sense_get_channel(i, 1); - channel_select[0] = SCSIGetCDChannel(0); - channel_select[1] = SCSIGetCDChannel(1); - - for (c = 0; c < CD_BUFLEN*2; c += 2) - { - int32_t cd_buffer_temp[2] = {0, 0}; + for (c = 0; c < CD_BUFLEN*2; c += 2) + { + int32_t cd_buffer_temp[2] = {0, 0}; + + /*First, adjust input from drive according to ATAPI/SCSI volume.*/ + cd_buffer[i][c] = ((int32_t)cd_buffer[i][c] * audio_vol_l) / 255; + cd_buffer[i][c+1] = ((int32_t)cd_buffer[i][c+1] * audio_vol_r) / 255; + + /*Apply ATAPI channel select*/ + if (channel_select[0] & 1) + cd_buffer_temp[0] += cd_buffer[i][c]; + if (channel_select[0] & 2) + cd_buffer_temp[1] += cd_buffer[i][c]; + if (channel_select[1] & 1) + cd_buffer_temp[0] += cd_buffer[i][c+1]; + if (channel_select[1] & 2) + cd_buffer_temp[1] += cd_buffer[i][c+1]; - /*First, adjust input from drive according to ATAPI/SCSI volume.*/ - cd_buffer[c] = ((int32_t)cd_buffer[c] * audio_vol_l) / 255; - cd_buffer[c+1] = ((int32_t)cd_buffer[c+1] * audio_vol_r) / 255; + /*Apply sound card CD volume*/ + cd_buffer_temp[0] = (cd_buffer_temp[0] * (int)cd_vol_l) / 65535; + cd_buffer_temp[1] = (cd_buffer_temp[1] * (int)cd_vol_r) / 65535; - /*Apply ATAPI channel select*/ - if (channel_select[0] & 1) - cd_buffer_temp[0] += cd_buffer[c]; - if (channel_select[0] & 2) - cd_buffer_temp[1] += cd_buffer[c]; - if (channel_select[1] & 1) - cd_buffer_temp[0] += cd_buffer[c+1]; - if (channel_select[1] & 2) - cd_buffer_temp[1] += cd_buffer[c+1]; - - /*Apply sound card CD volume*/ - cd_buffer_temp[0] = (cd_buffer_temp[0] * (int)cd_vol_l) / 65535; - cd_buffer_temp[1] = (cd_buffer_temp[1] * (int)cd_vol_r) / 65535; + if (cd_buffer_temp[0] > 32767) + cd_buffer_temp[0] = 32767; + if (cd_buffer_temp[0] < -32768) + cd_buffer_temp[0] = -32768; + if (cd_buffer_temp[1] > 32767) + cd_buffer_temp[1] = 32767; + if (cd_buffer_temp[1] < -32768) + cd_buffer_temp[1] = -32768; - if (cd_buffer_temp[0] > 32767) - cd_buffer_temp[0] = 32767; - if (cd_buffer_temp[0] < -32768) - cd_buffer_temp[0] = -32768; - if (cd_buffer_temp[1] > 32767) - cd_buffer_temp[1] = 32767; - if (cd_buffer_temp[1] < -32768) - cd_buffer_temp[1] = -32768; + cd_buffer[i][c] = cd_buffer_temp[0]; + cd_buffer[i][c+1] = cd_buffer_temp[1]; - cd_buffer[c] = cd_buffer_temp[0]; - cd_buffer[c+1] = cd_buffer_temp[1]; - } + cd_out_buffer[c] += ((float) cd_buffer[i][c]) / 32768.0; + cd_out_buffer[c+1] += ((float) cd_buffer[i][c+1]) / 32768.0; + } - givealbuffer_cd(cd_buffer); - } + } + } + givealbuffer_cd(cd_out_buffer); } } static int32_t *outbuffer; +static float *outbuffer_ex; void sound_init() { @@ -165,6 +189,7 @@ void sound_init() inital(); outbuffer = malloc(SOUNDBUFLEN * 2 * sizeof(int32_t)); + outbuffer_ex = malloc(SOUNDBUFLEN * 2 * sizeof(float)); sound_cd_event = thread_create_event(); sound_cd_thread_h = thread_create(sound_cd_thread, NULL); @@ -205,8 +230,13 @@ void sound_poll(void *priv) if (!soundf) soundf=fopen("sound.pcm","wb"); fwrite(buf16,(SOUNDBUFLEN)*2*2,1,soundf);*/ + + for (c = 0; c < SOUNDBUFLEN * 2; c++) + { + outbuffer_ex[c] = ((float) outbuffer[c]) / 32768.0; + } - if (soundon) givealbuffer(outbuffer); + if (soundon) givealbuffer(outbuffer_ex); thread_set_event(sound_cd_event); @@ -221,10 +251,20 @@ void sound_speed_changed() void sound_reset() { + int i = 0; + timer_add(sound_poll, &sound_poll_time, TIMER_ALWAYS_ENABLED, NULL); sound_handlers_num = 0; sound_set_cd_volume(65535, 65535); - ioctl_audio_stop(); + + for (i = 0; i < CDROM_NUM; i++) + { + pclog("Resetting audio for CD-ROM %i...\n", i); + if (cdrom_drives[i].handler->audio_stop) + { + cdrom_drives[i].handler->audio_stop(i); + } + } } diff --git a/src/sound_cms.c b/src/sound_cms.c index f38f46f9c..93a2aab1f 100644 --- a/src/sound_cms.c +++ b/src/sound_cms.c @@ -7,6 +7,8 @@ #include "sound.h" #include "sound_cms.h" +#define MASTER_CLOCK 7159090 + typedef struct cms_t { int addrs[2]; @@ -37,9 +39,9 @@ void cms_update(cms_t *cms) { switch (cms->noisetype[c >> 1][c & 1]) { - case 0: cms->noisefreq[c >> 1][c & 1] = 31250; break; - case 1: cms->noisefreq[c >> 1][c & 1] = 15625; break; - case 2: cms->noisefreq[c >> 1][c & 1] = 7812; break; + case 0: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/256; break; + case 1: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/512; break; + case 2: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/1024; break; case 3: cms->noisefreq[c >> 1][c & 1] = cms->freq[c >> 1][(c & 1) * 3]; break; } } @@ -124,14 +126,14 @@ void cms_write(uint16_t addr, uint8_t val, void *p) case 0x0B: case 0x0C: case 0x0D: voice = cms->addrs[chip] & 7; cms->latch[chip][voice] = (cms->latch[chip][voice] & 0x700) | val; - cms->freq[chip][voice] = (15625 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); + cms->freq[chip][voice] = (MASTER_CLOCK/512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); break; case 0x10: case 0x11: case 0x12: /*Octave*/ voice = (cms->addrs[chip] & 3) << 1; cms->latch[chip][voice] = (cms->latch[chip][voice] & 0xFF) | ((val & 7) << 8); cms->latch[chip][voice + 1] = (cms->latch[chip][voice + 1] & 0xFF) | ((val & 0x70) << 4); - cms->freq[chip][voice] = (15625 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); - cms->freq[chip][voice + 1] = (15625 << (cms->latch[chip][voice + 1] >> 8)) / (511 - (cms->latch[chip][voice + 1] & 255)); + cms->freq[chip][voice] = (MASTER_CLOCK/512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255)); + cms->freq[chip][voice + 1] = (MASTER_CLOCK/512 << (cms->latch[chip][voice + 1] >> 8)) / (511 - (cms->latch[chip][voice + 1] & 255)); break; case 0x16: /*Noise*/ cms->noisetype[chip][0] = val & 3; diff --git a/src/soundopenal.c b/src/soundopenal.c index 78f81ed87..29173b75b 100644 --- a/src/soundopenal.c +++ b/src/soundopenal.c @@ -5,6 +5,7 @@ #ifdef USE_OPENAL #include #include +#include #endif #include "ibm.h" #include "sound.h" @@ -84,7 +85,7 @@ void inital() { #ifdef USE_OPENAL int c; - int16_t buf[BUFLEN*2]; + float buf[BUFLEN*2]; // printf("1\n"); check(); @@ -118,8 +119,8 @@ void inital() // printf("5\n"); for (c = 0; c < 4; c++) { - alBufferData(buffers[c], AL_FORMAT_STEREO16, buf, BUFLEN*2*2, FREQ); - alBufferData(buffers_cd[c], AL_FORMAT_STEREO16, buf, CD_BUFLEN*2*2, CD_FREQ); + alBufferData(buffers[c], AL_FORMAT_STEREO_FLOAT32, buf, BUFLEN*2*sizeof(float), FREQ); + alBufferData(buffers_cd[c], AL_FORMAT_STEREO_FLOAT32, buf, CD_BUFLEN*2*sizeof(float), CD_FREQ); } alSourceQueueBuffers(source[0], 4, buffers); @@ -135,7 +136,7 @@ void inital() #endif } -void givealbuffer(int32_t *buf) +void givealbuffer(float *buf) { #ifdef USE_OPENAL int16_t buf16[BUFLEN*2]; @@ -174,7 +175,7 @@ void givealbuffer(int32_t *buf) // printf("U "); check(); - for (c=0;c> 16) & 0x1f; - if(riva128->pgraph.debug[1] & 0x10000 && ((riva128->pgraph.instance >> 4)) != riva128->pgraph.ctx_switch[3] && (new_class == 0x0d || new_class == 0x0e || new_class == 0x14 || new_class == 0x17 || offset == 0x0104) + if((riva128->pgraph.debug[1] & 0x10000) && ((riva128->pgraph.instance >> 4) != riva128->pgraph.ctx_switch[3]) && (new_class == 0x0d || new_class == 0x0e || new_class == 0x14 || new_class == 0x17 || offset == 0x0104)) { riva128->pgraph.ctx_switch[3] = riva128->pgraph.instance >> 4; riva128->pgraph.ctx_switch[1] = riva128->pramin[riva128->pgraph.instance + 4] & 0xffff; diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index d84de678d..3306a3fc3 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -190,6 +190,7 @@ typedef struct texture_t volatile int refcount, refcount_r[2]; int is16; uint32_t palette_checksum; + uint32_t addr_start, addr_end; uint32_t *data; } texture_t; @@ -1466,8 +1467,10 @@ static void use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu) else voodoo->texture_cache[tmu][c].palette_checksum = 0; - addr = voodoo->texture_cache[tmu][c].base + texture_offset[lod_min] * (voodoo->texture_cache[tmu][c].is16 ? 2 : 1); - addr_end = voodoo->texture_cache[tmu][c].base + texture_offset[lod_max+1] * (voodoo->texture_cache[tmu][c].is16 ? 2 : 1); + addr = voodoo->params.tex_base[tmu][lod_min]; + addr_end = voodoo->params.tex_base[tmu][lod_max+1]; + voodoo->texture_cache[tmu][c].addr_start = addr; + voodoo->texture_cache[tmu][c].addr_end = addr_end; for (; addr <= addr_end; addr += (1 << TEX_DIRTY_SHIFT)) voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1; @@ -1488,8 +1491,8 @@ static void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu) { int lod_min = (voodoo->texture_cache[tmu][c].tLOD >> 2) & 15; int lod_max = (voodoo->texture_cache[tmu][c].tLOD >> 8) & 15; - int addr_start = voodoo->texture_cache[tmu][c].base + texture_offset[lod_min] * (voodoo->texture_cache[tmu][c].is16 ? 2 : 1); - int addr_end = voodoo->texture_cache[tmu][c].base + texture_offset[lod_max+1] * (voodoo->texture_cache[tmu][c].is16 ? 2 : 1); + int addr_start = voodoo->texture_cache[tmu][c].addr_start; + int addr_end = voodoo->texture_cache[tmu][c].addr_end; if (dirty_addr >= (addr_start & voodoo->texture_mask & ~0x3ff) && dirty_addr < (((addr_end & voodoo->texture_mask) + 0x3ff) & ~0x3ff)) { diff --git a/src/win-config.c b/src/win-config.c index c542134ea..3badfebd5 100644 --- a/src/win-config.c +++ b/src/win-config.c @@ -32,11 +32,11 @@ static int settings_network_to_list[20], settings_list_to_network[20]; static int mouse_valid(int type, int model) { - if (type == MOUSE_TYPE_PS2 && !(models[model].flags & MODEL_PS2)) + if ((type & MOUSE_TYPE_IF_MASK) == MOUSE_TYPE_PS2 && !(models[model].flags & MODEL_PS2)) return 0; - if (type == MOUSE_TYPE_AMSTRAD && !(models[model].flags & MODEL_AMSTRAD)) + if ((type & MOUSE_TYPE_IF_MASK) == MOUSE_TYPE_AMSTRAD && !(models[model].flags & MODEL_AMSTRAD)) return 0; - if (type == MOUSE_TYPE_OLIM24 && !(models[model].flags & MODEL_OLIM24)) + if ((type & MOUSE_TYPE_IF_MASK) == MOUSE_TYPE_OLIM24 && !(models[model].flags & MODEL_OLIM24)) return 0; return 1; } diff --git a/src/win-hdconf.c b/src/win-hdconf.c index cc09df282..8ab21591e 100644 --- a/src/win-hdconf.c +++ b/src/win-hdconf.c @@ -19,20 +19,6 @@ static uint64_t hd_new_spt, hd_new_hpc, hd_new_cyl; static int hd_new_hdi; static int new_cdrom_channel; -static void update_hdd_cdrom(HWND hdlg) -{ - HWND h; - int drive_num = 0; - - for (drive_num = 0; drive_num < IDE_NUM; drive_num++) - { - h = GetDlgItem(hdlg, IDC_CHDD + drive_num); - SendMessage(h, BM_SETCHECK, (new_cdrom_channel == drive_num) ? 0 : 1, 0); - h = GetDlgItem(hdlg, IDC_CCDROM + drive_num); - SendMessage(h, BM_SETCHECK, (new_cdrom_channel == drive_num) ? 1 : 0, 0); - } -} - int hdnew_no_update = 0; hard_disk_t hdnew_temp_hd; @@ -556,16 +542,13 @@ static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR hd_changed = 0; - new_cdrom_channel = atapi_cdrom_channel; - - update_hdd_cdrom(hdlg); return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDOK: - if (hd_changed || atapi_cdrom_channel != new_cdrom_channel) + if (hd_changed) { if (MessageBox(NULL, "This will reset 86Box!\nOkay to continue?", "86Box", MB_OKCANCEL) == IDOK) { @@ -586,8 +569,6 @@ static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR hdc[drive_num] = hd[drive_num]; } - atapi_cdrom_channel = new_cdrom_channel; - saveconfig(); resetpchard(); @@ -645,31 +626,6 @@ static BOOL CALLBACK hdconf_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR drive_num = LOWORD(wParam) % 10; hdconf_edit_boxes(hdlg, drive_num, &(hd[drive_num])); return TRUE; - - case IDC_CHDD: - case IDC_DHDD: - case IDC_EHDD: - case IDC_FHDD: - case IDC_GHDD: - case IDC_HHDD: - case IDC_IHDD: - case IDC_JHDD: - if (new_cdrom_channel == (LOWORD(wParam) - IDC_CCDROM)) - new_cdrom_channel = -1; - update_hdd_cdrom(hdlg); - return TRUE; - - case IDC_CCDROM: - case IDC_DCDROM: - case IDC_ECDROM: - case IDC_FCDROM: - case IDC_GCDROM: - case IDC_HCDROM: - case IDC_ICDROM: - case IDC_JCDROM: - new_cdrom_channel = LOWORD(wParam) - IDC_CCDROM; - update_hdd_cdrom(hdlg); - return TRUE; } break; diff --git a/src/win.c b/src/win.c index c8ea78941..0fbb3f8fb 100644 --- a/src/win.c +++ b/src/win.c @@ -320,23 +320,27 @@ void thread_destroy_event(event_t *_event) static void initmenu(void) { - int c; - HMENU m; + int i, c; + HMENU dm, m; char s[32]; - m=GetSubMenu(menu,1); /*Disc*/ - m=GetSubMenu(m,17); /*CD-ROM*/ + dm=GetSubMenu(menu,1); /*Disc*/ - /* Loop through each Windows drive letter and test to see if - it's a CDROM */ - for (c='A';c<='Z';c++) - { - sprintf(s,"%c:\\",c); - if (GetDriveType(s)==DRIVE_CDROM) - { - sprintf(s, "Host CD/DVD Drive (%c:)", c); - AppendMenu(m,MF_STRING,IDM_CDROM_REAL+c,s); - } - } + for (i = 0; i < CDROM_NUM; i++) + { + m=GetSubMenu(dm,17+i); /*CD-ROM*/ + + /* Loop through each Windows drive letter and test to see if + it's a CDROM */ + for (c='A';c<='Z';c++) + { + sprintf(s,"%c:\\",c); + if (GetDriveType(s)==DRIVE_CDROM) + { + sprintf(s, "Host CD/DVD Drive (%c:)", c); + AppendMenu(m,MF_STRING,IDM_CDROM_1_REAL+c+(i * 1000),s); + } + } + } } void get_executable_name(char *s, int size) @@ -515,6 +519,28 @@ static void process_command_line() argv[argc] = NULL; } +int valid_models[2] = { 0, 1 }; +int valid_bases[6] = { 0x130, 0x134, 0x230, 0x234, 0x330, 0x334 }; +int valid_irqs[6] = { 9, 10, 11, 12, 14, 15 }; +int valid_dma_channels[3] = { 5, 6, 7 }; +int valid_ide_channels[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; +int valid_scsi_ids[15] = { 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15 }; + +int find_in_array(int *array, int val, int len, int menu_base) +{ + int i = 0; + int temp = 0; + for (i = 0; i < len; i++) + { + CheckMenuItem(menu, menu_base + array[i], MF_UNCHECKED); + if (array[i] == val) + { + temp = 1; + } + } + return temp; +} + HANDLE hinstAcc; int WINAPI WinMain (HINSTANCE hThisInstance, @@ -526,7 +552,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance, HWND hwnd; /* This is the handle for our window */ MSG messages; /* Here messages to the application are saved */ WNDCLASSEX wincl; /* Data structure for the windowclass */ - int c, d, bRet; + int c, d, e, bRet; char emulator_title[200]; LARGE_INTEGER qpc_freq; HACCEL haccel; /* Handle to accelerator table */ @@ -621,210 +647,90 @@ int WINAPI WinMain (HINSTANCE hThisInstance, // pclog("Checking CD-ROM menu item...\n"); /* Note by Kiririn: I've redone this since the CD-ROM can be disabled but still have something inside it. */ - if (cdrom_enabled) - CheckMenuItem(menu, IDM_CDROM_ENABLED, MF_CHECKED); + for (e = 0; e < CDROM_NUM; e++) + { + if (cdrom_drives[e].enabled) + CheckMenuItem(menu, IDM_CDROM_1_ENABLED + (e * 1000), MF_CHECKED); - if (scsi_cdrom_enabled) - CheckMenuItem(menu, IDM_CDROM_SCSI, MF_CHECKED); + if (cdrom_drives[e].sound_on) + CheckMenuItem(menu, IDM_CDROM_1_SOUND_ON + (e * 1000), MF_CHECKED); + + if (cdrom_drives[e].bus_type) + CheckMenuItem(menu, IDM_CDROM_1_SCSI + (e * 1000), MF_CHECKED); + + if (!find_in_array(valid_ide_channels, cdrom_drives[e].ide_channel, 8, IDM_CDROM_1_C + (e * 1000))) + { + fatal("Tertiary IDE controller: Invalid IRQ\n"); + } + + CheckMenuItem(menu, IDM_CDROM_1_C + (e * 1000) + cdrom_drives[e].ide_channel, MF_CHECKED); + + if (!find_in_array(valid_scsi_ids, cdrom_drives[e].scsi_device_id, 15, IDM_CDROM_1_0 + (e * 1000))) + { + fatal("Tertiary IDE controller: Invalid IRQ\n"); + } + + CheckMenuItem(menu, IDM_CDROM_1_0 + (e * 1000) + cdrom_drives[e].scsi_device_id, MF_CHECKED); + + if (cdrom_drives[e].host_drive == 200) + { + CheckMenuItem(menu, IDM_CDROM_1_ISO + (e * 1000), MF_CHECKED); + } + else + { + CheckMenuItem(menu, IDM_CDROM_1_REAL + (e * 1000) + cdrom_drives[e].host_drive, MF_CHECKED); + } + } if (ide_enable[2]) CheckMenuItem(menu, IDM_IDE_TER_ENABLED, MF_CHECKED); - CheckMenuItem(menu, IDM_IDE_TER_IRQ9, MF_UNCHECKED); - CheckMenuItem(menu, IDM_IDE_TER_IRQ10, MF_UNCHECKED); - CheckMenuItem(menu, IDM_IDE_TER_IRQ11, MF_UNCHECKED); - CheckMenuItem(menu, IDM_IDE_TER_IRQ12, MF_UNCHECKED); - CheckMenuItem(menu, IDM_IDE_TER_IRQ14, MF_UNCHECKED); - CheckMenuItem(menu, IDM_IDE_TER_IRQ15, MF_UNCHECKED); + if (!find_in_array(valid_irqs, ide_irq[2], 6, IDM_IDE_TER_IRQ9 - 9)) + { + fatal("Tertiary IDE controller: Invalid IRQ\n"); + } - if (ide_irq[2] == 9) - { - CheckMenuItem(menu, IDM_IDE_TER_IRQ9, MF_CHECKED); - } - else if (ide_irq[2] == 10) - { - CheckMenuItem(menu, IDM_IDE_TER_IRQ10, MF_CHECKED); - } - else if (ide_irq[2] == 11) - { - CheckMenuItem(menu, IDM_IDE_TER_IRQ11, MF_CHECKED); - } - else if (ide_irq[2] == 12) - { - CheckMenuItem(menu, IDM_IDE_TER_IRQ12, MF_CHECKED); - } - else if (ide_irq[2] == 14) - { - CheckMenuItem(menu, IDM_IDE_TER_IRQ14, MF_CHECKED); - } - else if (ide_irq[2] == 15) - { - CheckMenuItem(menu, IDM_IDE_TER_IRQ15, MF_CHECKED); - } - else - { - fatal("Unrecognized tertiary IDE controller IRQ\n"); - } + CheckMenuItem(menu, IDM_IDE_TER_IRQ9 - 9 + ide_irq[2], MF_CHECKED); if (ide_enable[3]) CheckMenuItem(menu, IDM_IDE_QUA_ENABLED, MF_CHECKED); - CheckMenuItem(menu, IDM_IDE_QUA_IRQ9, MF_UNCHECKED); - CheckMenuItem(menu, IDM_IDE_QUA_IRQ10, MF_UNCHECKED); - CheckMenuItem(menu, IDM_IDE_QUA_IRQ11, MF_UNCHECKED); - CheckMenuItem(menu, IDM_IDE_QUA_IRQ12, MF_UNCHECKED); - CheckMenuItem(menu, IDM_IDE_QUA_IRQ14, MF_UNCHECKED); - CheckMenuItem(menu, IDM_IDE_QUA_IRQ15, MF_UNCHECKED); + if (!find_in_array(valid_irqs, ide_irq[3], 6, IDM_IDE_QUA_IRQ9 - 9)) + { + fatal("Quaternary IDE controller: Invalid IRQ\n"); + } - if (ide_irq[3] == 9) - { - CheckMenuItem(menu, IDM_IDE_QUA_IRQ9, MF_CHECKED); - } - else if (ide_irq[3] == 10) - { - CheckMenuItem(menu, IDM_IDE_QUA_IRQ10, MF_CHECKED); - } - else if (ide_irq[3] == 11) - { - CheckMenuItem(menu, IDM_IDE_QUA_IRQ11, MF_CHECKED); - } - else if (ide_irq[3] == 12) - { - CheckMenuItem(menu, IDM_IDE_QUA_IRQ12, MF_CHECKED); - } - else if (ide_irq[3] == 14) - { - CheckMenuItem(menu, IDM_IDE_QUA_IRQ14, MF_CHECKED); - } - else if (ide_irq[3] == 15) - { - CheckMenuItem(menu, IDM_IDE_QUA_IRQ15, MF_CHECKED); - } - else - { - fatal("Unrecognized quaternary IDE controller IRQ\n"); - } + CheckMenuItem(menu, IDM_IDE_QUA_IRQ9 - 9 + ide_irq[3], MF_CHECKED); if (buslogic_enabled) CheckMenuItem(menu, IDM_SCSI_ENABLED, MF_CHECKED); - CheckMenuItem(menu, IDM_SCSI_MODEL0, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_MODEL1, MF_UNCHECKED); - - if (scsi_model == 0) + if (!find_in_array(valid_models, scsi_model, 2, IDM_SCSI_MODEL0)) { - CheckMenuItem(menu, IDM_SCSI_MODEL0, MF_CHECKED); - } - else if (scsi_model == 1) - { - CheckMenuItem(menu, IDM_SCSI_MODEL1, MF_CHECKED); - } - else - { - fatal("Unrecognized SCSI model\n"); + fatal("SCSI controller: Invalid model\n"); } - CheckMenuItem(menu, IDM_SCSI_BASE130, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_BASE134, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_BASE230, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_BASE234, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_BASE330, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_BASE334, MF_UNCHECKED); + CheckMenuItem(menu, IDM_SCSI_MODEL0 + scsi_model, MF_CHECKED); - if (scsi_base == 0x130) + if (!find_in_array(valid_bases, scsi_base, 6, IDM_SCSI_BASE130 - 0x130)) { - CheckMenuItem(menu, IDM_SCSI_BASE130, MF_CHECKED); - } - else if (scsi_base == 0x134) - { - CheckMenuItem(menu, IDM_SCSI_BASE134, MF_CHECKED); - } - else if (scsi_base == 0x230) - { - CheckMenuItem(menu, IDM_SCSI_BASE230, MF_CHECKED); - } - else if (scsi_base == 0x234) - { - CheckMenuItem(menu, IDM_SCSI_BASE234, MF_CHECKED); - } - else if (scsi_base == 0x330) - { - CheckMenuItem(menu, IDM_SCSI_BASE330, MF_CHECKED); - } - else if (scsi_base == 0x334) - { - CheckMenuItem(menu, IDM_SCSI_BASE334, MF_CHECKED); - } - else - { - fatal("Unrecognized SCSI base address\n"); + fatal("SCSI controller: Invalid base address\n"); } - CheckMenuItem(menu, IDM_SCSI_IRQ9, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_IRQ10, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_IRQ11, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_IRQ12, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_IRQ14, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_IRQ15, MF_UNCHECKED); + CheckMenuItem(menu, IDM_SCSI_BASE130 - 0x130 + scsi_base, MF_CHECKED); - if (scsi_irq == 9) + if (!find_in_array(valid_irqs, scsi_irq, 6, IDM_SCSI_IRQ9 - 9)) { - CheckMenuItem(menu, IDM_SCSI_IRQ9, MF_CHECKED); + fatal("SCSI controller: Invalid IRQ\n"); } - else if (scsi_irq == 10) + CheckMenuItem(menu, IDM_SCSI_IRQ9 - 9 + scsi_irq, MF_CHECKED); + + if (!find_in_array(valid_dma_channels, scsi_dma, 3, IDM_SCSI_DMA5 - 5)) { - CheckMenuItem(menu, IDM_SCSI_IRQ10, MF_CHECKED); - } - else if (scsi_irq == 11) - { - CheckMenuItem(menu, IDM_SCSI_IRQ11, MF_CHECKED); - } - else if (scsi_irq == 12) - { - CheckMenuItem(menu, IDM_SCSI_IRQ12, MF_CHECKED); - } - else if (scsi_irq == 14) - { - CheckMenuItem(menu, IDM_SCSI_IRQ14, MF_CHECKED); - } - else if (scsi_irq == 15) - { - CheckMenuItem(menu, IDM_SCSI_IRQ15, MF_CHECKED); - } - else - { - fatal("Unrecognized SCSI IRQ\n"); + fatal("SCSI controller: Invalid DMA channel\n"); } - CheckMenuItem(menu, IDM_SCSI_DMA5, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_DMA6, MF_UNCHECKED); - CheckMenuItem(menu, IDM_SCSI_DMA7, MF_UNCHECKED); - - if (scsi_dma == 5) - { - CheckMenuItem(menu, IDM_SCSI_DMA5, MF_CHECKED); - } - else if (scsi_dma == 6) - { - CheckMenuItem(menu, IDM_SCSI_DMA6, MF_CHECKED); - } - else if (scsi_dma == 7) - { - CheckMenuItem(menu, IDM_SCSI_DMA7, MF_CHECKED); - } - else - { - fatal("Unrecognized SCSI DMA address\n"); - } - - if (cdrom_drive == 200) - { - CheckMenuItem(menu, IDM_CDROM_ISO, MF_CHECKED); - } - else - { - CheckMenuItem(menu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED); - } + CheckMenuItem(menu, IDM_SCSI_DMA5 - 5 + scsi_dma, MF_CHECKED); CheckMenuItem(menu, IDM_VID_FORCE43, force_43 ? MF_CHECKED : MF_UNCHECKED); CheckMenuItem(menu, IDM_VID_OVERSCAN, enable_overscan ? MF_CHECKED : MF_UNCHECKED); @@ -1138,18 +1044,18 @@ LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam ) return CallNextHookEx( hKeyboardHook, nCode, wParam, lParam ); } -void cdrom_close(void) +void cdrom_close(uint8_t id) { - switch (cdrom_drive) + switch (cdrom_drives[id].host_drive) { case 0: - null_close(); + null_close(id); break; default: - ioctl_close(); + ioctl_close(id); break; case 200: - iso_close(); + iso_close(id); break; } } @@ -1312,73 +1218,90 @@ void video_toggle_option(HMENU hmenu, int *val, int id) saveconfig(); } -void win_cdrom_eject() +void win_cdrom_eject(uint8_t id) { HMENU hmenu; hmenu=GetMenu(ghwnd); - if (cdrom_drive == 0) + if (cdrom_drives[id].host_drive == 0) { /* Switch from empty to empty. Do nothing. */ return; } - cdrom->exit(); - cdrom_close(); - cdrom_null_open(0); - if (cdrom_enabled) + cdrom_drives[id].handler->exit(id); + cdrom_close(id); + cdrom_null_open(id, 0); + if (cdrom_drives[id].enabled) { /* Signal disc change to the emulated machine. */ - SCSICDROM_Insert(); + cdrom_insert(id); } - CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED); - CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); - old_cdrom_drive = cdrom_drive; - cdrom_drive=0; - CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_CHECKED); + CheckMenuItem(hmenu, IDM_CDROM_1_REAL + (id * 1000) + cdrom_drive, MF_UNCHECKED); + CheckMenuItem(hmenu, IDM_CDROM_1_ISO + (id * 1000), MF_UNCHECKED); + cdrom_drives[id].prev_host_drive = cdrom_drives[id].host_drive; + cdrom_drives[id].host_drive=0; + CheckMenuItem(hmenu, IDM_CDROM_1_EMPTY + (id * 1000), MF_CHECKED); saveconfig(); } -void win_cdrom_reload() +void win_cdrom_reload(uint8_t id) { HMENU hmenu; hmenu=GetMenu(ghwnd); int new_cdrom_drive; - if ((cdrom_drive == old_cdrom_drive) || (old_cdrom_drive == 0) || (cdrom_drive != 0)) + if ((cdrom_drives[id].host_drive == cdrom_drives[id].prev_host_drive) || (cdrom_drives[id].prev_host_drive == 0) || (cdrom_drives[id].host_drive != 0)) { /* Switch from empty to empty. Do nothing. */ return; } - if (old_cdrom_drive == 200) + cdrom_close(id); + if (cdrom_drives[id].prev_host_drive == 200) { - iso_open(iso_path); - if (cdrom_enabled) + iso_open(id, cdrom_iso[id].iso_path); + if (cdrom_drives[id].enabled) { /* Signal disc change to the emulated machine. */ - SCSICDROM_Insert(); + cdrom_insert(id); } - CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED); - // CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED); - CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); - cdrom_drive = 200; - CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_CHECKED); + CheckMenuItem(hmenu, IDM_CDROM_1_EMPTY + (id * 1000), MF_UNCHECKED); + cdrom_drives[id].host_drive = 200; + CheckMenuItem(hmenu, IDM_CDROM_1_ISO + (id * 1000), MF_CHECKED); saveconfig(); } else { - new_cdrom_drive = old_cdrom_drive; - ioctl_open(new_cdrom_drive); - if (cdrom_enabled) + new_cdrom_drive = cdrom_drives[id].prev_host_drive; + ioctl_open(id, new_cdrom_drive); + if (cdrom_drives[id].enabled) { /* Signal disc change to the emulated machine. */ - SCSICDROM_Insert(); + cdrom_insert(id); } - CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED); - CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); + CheckMenuItem(hmenu, IDM_CDROM_1_EMPTY + (id * 1000), MF_UNCHECKED); cdrom_drive = new_cdrom_drive; - CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED); + CheckMenuItem(hmenu, IDM_CDROM_1_REAL + (id * 1000) + cdrom_drives[id].host_drive, MF_CHECKED); saveconfig(); } } +int convert_cdrom_id(int original_id) +{ + int i = 0; + + if (original_id >= (CDROM_NUM * 1000)) + { + return 0; + } + + for (i = 0; i < CDROM_NUM; i++) + { + if (original_id == (i * 1000)) + { + return i; + } + } + return 0; +} + LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HMENU hmenu; @@ -1386,6 +1309,8 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM uint32_t ri_size = 0; char temp_iso_path[1024]; int new_cdrom_drive; + int cdrom_id = 0; + int menu_sub_param = 0; // pclog("Message %i %08X\n",message,message); switch (message) { @@ -1598,61 +1523,88 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM pause = 0; break; -#if 0 - case IDM_CDROM_DISABLED: - if (cdrom_enabled) - { - if (MessageBox(NULL,"This will reset 86Box!\nOkay to continue?","86Box",MB_OKCANCEL) != IDOK) - break; - } - if (!cdrom_enabled) - { - /* Switching from disabled to disabled. Do nothing. */ - break; - } - cdrom->exit(); - cdrom_close(); - cdrom_null_open(0); - CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED); - CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_CHECKED); - CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); - old_cdrom_drive = cdrom_drive; - cdrom_drive=0; - CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_UNCHECKED); - if (cdrom_enabled) - { - pause = 1; - Sleep(100); - cdrom_enabled = 0; - saveconfig(); - resetpchard(); - pause = 0; - } - break; -#endif - case IDM_CDROM_ENABLED: + case IDM_CDROM_1_ENABLED: + case IDM_CDROM_2_ENABLED: + case IDM_CDROM_3_ENABLED: + case IDM_CDROM_4_ENABLED: + cdrom_id = convert_cdrom_id(LOWORD(wParam) - IDM_CDROM_1_ENABLED); if (MessageBox(NULL,"This will reset 86Box!\nOkay to continue?","86Box",MB_OKCANCEL) != IDOK) { break; } pause = 1; Sleep(100); - cdrom_enabled ^= 1; - CheckMenuItem(hmenu, IDM_CDROM_ENABLED, cdrom_enabled ? MF_CHECKED : MF_UNCHECKED); + cdrom_drives[cdrom_id].enabled ^= 1; + CheckMenuItem(hmenu, IDM_CDROM_1_ENABLED + (cdrom_id * 1000), cdrom_drives[cdrom_id].enabled ? MF_CHECKED : MF_UNCHECKED); saveconfig(); resetpchard(); pause = 0; break; - case IDM_CDROM_SCSI: + case IDM_CDROM_1_SOUND_ON: + case IDM_CDROM_2_SOUND_ON: + case IDM_CDROM_3_SOUND_ON: + case IDM_CDROM_4_SOUND_ON: + cdrom_id = convert_cdrom_id(LOWORD(wParam) - IDM_CDROM_1_SOUND_ON); + Sleep(100); + cdrom_drives[cdrom_id].sound_on ^= 1; + CheckMenuItem(hmenu, IDM_CDROM_1_SOUND_ON + (cdrom_id * 1000), cdrom_drives[cdrom_id].enabled ? MF_CHECKED : MF_UNCHECKED); + saveconfig(); + break; + + case IDM_CDROM_1_SCSI: + case IDM_CDROM_2_SCSI: + case IDM_CDROM_3_SCSI: + case IDM_CDROM_4_SCSI: + cdrom_id = convert_cdrom_id(LOWORD(wParam) - IDM_CDROM_1_SCSI); if (MessageBox(NULL,"This will reset 86Box!\nOkay to continue?","86Box",MB_OKCANCEL) != IDOK) { break; } pause = 1; Sleep(100); - scsi_cdrom_enabled ^= 1; - CheckMenuItem(hmenu, IDM_CDROM_SCSI, scsi_cdrom_enabled ? MF_CHECKED : MF_UNCHECKED); + cdrom_drives[cdrom_id].bus_type ^= 1; + CheckMenuItem(hmenu, IDM_CDROM_1_SCSI + (cdrom_id * 1000), cdrom_drives[cdrom_id].bus_type ? MF_CHECKED : MF_UNCHECKED); + saveconfig(); + resetpchard(); + pause = 0; + break; + + case IDM_CDROM_1_C ... IDM_CDROM_1_H: + case IDM_CDROM_2_C ... IDM_CDROM_2_H: + case IDM_CDROM_3_C ... IDM_CDROM_3_H: + case IDM_CDROM_4_C ... IDM_CDROM_4_H: + menu_sub_param = LOWORD(wParam) % 100; + cdrom_id = convert_cdrom_id(LOWORD(wParam) - menu_sub_param - IDM_CDROM_1_C); + if (MessageBox(NULL,"This will reset 86Box!\nOkay to continue?","86Box",MB_OKCANCEL) != IDOK) + { + break; + } + pause = 1; + Sleep(100); + CheckMenuItem(hmenu, IDM_CDROM_1_C + (cdrom_id * 1000) + cdrom_drives[cdrom_id].ide_channel, MF_UNCHECKED); + cdrom_drives[cdrom_id].ide_channel = menu_sub_param; + CheckMenuItem(hmenu, IDM_CDROM_1_C + (cdrom_id * 1000) + cdrom_drives[cdrom_id].ide_channel, MF_CHECKED); + saveconfig(); + resetpchard(); + pause = 0; + break; + + case IDM_CDROM_1_0 ... IDM_CDROM_1_15: + case IDM_CDROM_2_0 ... IDM_CDROM_2_15: + case IDM_CDROM_3_0 ... IDM_CDROM_3_15: + case IDM_CDROM_4_0 ... IDM_CDROM_4_15: + menu_sub_param = LOWORD(wParam) % 100; + cdrom_id = convert_cdrom_id(LOWORD(wParam) - menu_sub_param - IDM_CDROM_1_0); + if (MessageBox(NULL,"This will reset 86Box!\nOkay to continue?","86Box",MB_OKCANCEL) != IDOK) + { + break; + } + pause = 1; + Sleep(100); + CheckMenuItem(hmenu, IDM_CDROM_1_0 + (cdrom_id * 1000) + cdrom_drives[cdrom_id].scsi_device_id, MF_UNCHECKED); + cdrom_drives[cdrom_id].scsi_device_id = menu_sub_param; + CheckMenuItem(hmenu, IDM_CDROM_1_0 + (cdrom_id * 1000) + cdrom_drives[cdrom_id].scsi_device_id, MF_CHECKED); saveconfig(); resetpchard(); pause = 0; @@ -1816,7 +1768,13 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM scsi_set_dma(hmenu, 7, IDM_SCSI_DMA7); break; - case IDM_CDROM_EMPTY: + case IDM_CDROM_1_EMPTY: + case IDM_CDROM_2_EMPTY: + case IDM_CDROM_3_EMPTY: + case IDM_CDROM_4_EMPTY: + cdrom_id = convert_cdrom_id(LOWORD(wParam) - IDM_CDROM_1_EMPTY); + win_cdrom_eject(cdrom_id); +#if 0 if (cdrom_drive == 0) { /* Switch from empty to empty. Do nothing. */ @@ -1836,93 +1794,79 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM cdrom_drive=0; CheckMenuItem(hmenu, IDM_CDROM_EMPTY, MF_CHECKED); saveconfig(); +#endif break; - case IDM_CDROM_RELOAD: - win_cdrom_reload(); + case IDM_CDROM_1_RELOAD: + case IDM_CDROM_2_RELOAD: + case IDM_CDROM_3_RELOAD: + case IDM_CDROM_4_RELOAD: + cdrom_id = convert_cdrom_id(LOWORD(wParam) - IDM_CDROM_1_RELOAD); + win_cdrom_reload(cdrom_id); break; - case IDM_CDROM_ISO: - if (!getfile(hwnd,"CD-ROM image (*.ISO)\0*.ISO\0All files (*.*)\0*.*\0",iso_path)) + case IDM_CDROM_1_ISO: + case IDM_CDROM_2_ISO: + case IDM_CDROM_3_ISO: + case IDM_CDROM_4_ISO: + cdrom_id = convert_cdrom_id(LOWORD(wParam) - IDM_CDROM_1_ISO); + if (!getfile(hwnd,"CD-ROM image (*.ISO)\0*.ISO\0All files (*.*)\0*.*\0",cdrom_iso[cdrom_id].iso_path)) { - /* if (!cdrom_enabled) - { - if (MessageBox(NULL,"This will reset 86Box!\nOkay to continue?","86Box",MB_OKCANCEL) != IDOK) - break; - } */ - old_cdrom_drive = cdrom_drive; + cdrom_drives[cdrom_id].prev_host_drive = cdrom_drives[cdrom_id].host_drive; strcpy(temp_iso_path, openfilestring); - // if ((strcmp(iso_path, temp_iso_path) == 0) && (cdrom_drive == 200) && cdrom_enabled) - if ((strcmp(iso_path, temp_iso_path) == 0) && (cdrom_drive == 200)) + if ((strcmp(cdrom_iso[cdrom_id].iso_path, temp_iso_path) == 0) && (cdrom_drives[cdrom_id].host_drive == 200)) { /* Switching from ISO to the same ISO. Do nothing. */ break; } - cdrom->exit(); - cdrom_close(); - iso_open(temp_iso_path); - if (cdrom_enabled) + cdrom_drives[cdrom_id].handler->exit(cdrom_id); + cdrom_close(cdrom_id); + iso_open(cdrom_id, temp_iso_path); + if (cdrom_drives[cdrom_id].enabled) { /* Signal disc change to the emulated machine. */ - SCSICDROM_Insert(); + cdrom_insert(cdrom_id); } - CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED); - // CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED); - CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); - cdrom_drive = 200; - CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_CHECKED); + CheckMenuItem(hmenu, IDM_CDROM_1_EMPTY + (cdrom_id * 1000), MF_UNCHECKED); + if ((cdrom_drives[cdrom_id].host_drive != 0) && (cdrom_drives[cdrom_id].host_drive != 200)) + { + CheckMenuItem(hmenu, IDM_CDROM_1_REAL + (cdrom_id * 1000) + cdrom_drives[cdrom_id].host_drive, MF_UNCHECKED); + } + cdrom_drives[cdrom_id].host_drive = 200; + CheckMenuItem(hmenu, IDM_CDROM_1_ISO + (cdrom_id * 1000), MF_CHECKED); saveconfig(); - /* if (!cdrom_enabled) - { - pause = 1; - Sleep(100); - cdrom_enabled = 1; - saveconfig(); - resetpchard(); - pause = 0; - } */ } break; default: - if (LOWORD(wParam)>IDM_CDROM_REAL && LOWORD(wParam)<(IDM_CDROM_REAL+100)) + menu_sub_param = LOWORD(wParam) % 100; + cdrom_id = convert_cdrom_id(LOWORD(wParam) - menu_sub_param - IDM_CDROM_1_REAL); + if ((LOWORD(wParam) > IDM_CDROM_1_REAL + (cdrom_id * 1000)) && (LOWORD(wParam) < (IDM_CDROM_1_REAL + (cdrom_id * 1000) + 100))) { - /* if (!cdrom_enabled) - { - if (MessageBox(NULL,"This will reset 86Box!\nOkay to continue?","86Box",MB_OKCANCEL) != IDOK) - break; - } */ - new_cdrom_drive = LOWORD(wParam)-IDM_CDROM_REAL; - // if ((cdrom_drive == new_cdrom_drive) && cdrom_enabled) - if (cdrom_drive == new_cdrom_drive) + new_cdrom_drive = menu_sub_param; + if (cdrom_drives[cdrom_id].host_drive == new_cdrom_drive) { /* Switching to the same drive. Do nothing. */ break; } - old_cdrom_drive = cdrom_drive; - cdrom->exit(); - cdrom_close(); - ioctl_open(new_cdrom_drive); - if (cdrom_enabled) + cdrom_drives[cdrom_id].prev_host_drive = cdrom_drives[cdrom_id].host_drive; + cdrom_drives[cdrom_id].handler->exit(cdrom_id); + cdrom_close(cdrom_id); + ioctl_open(cdrom_id, new_cdrom_drive); + if (cdrom_drives[cdrom_id].enabled) { /* Signal disc change to the emulated machine. */ - SCSICDROM_Insert(); + cdrom_insert(cdrom_id); } - CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_UNCHECKED); - // CheckMenuItem(hmenu, IDM_CDROM_DISABLED, MF_UNCHECKED); - CheckMenuItem(hmenu, IDM_CDROM_ISO, MF_UNCHECKED); - cdrom_drive = new_cdrom_drive; - CheckMenuItem(hmenu, IDM_CDROM_REAL + cdrom_drive, MF_CHECKED); + CheckMenuItem(hmenu, IDM_CDROM_1_EMPTY + (cdrom_id * 1000), MF_UNCHECKED); + if ((cdrom_drives[cdrom_id].host_drive != 0) && (cdrom_drives[cdrom_id].host_drive != 200)) + { + CheckMenuItem(hmenu, IDM_CDROM_1_REAL + (cdrom_id * 1000) + cdrom_drives[cdrom_id].host_drive, MF_UNCHECKED); + } + CheckMenuItem(hmenu, IDM_CDROM_1_ISO + (cdrom_id * 1000), MF_UNCHECKED); + cdrom_drives[cdrom_id].host_drive = new_cdrom_drive; + CheckMenuItem(hmenu, IDM_CDROM_1_REAL + (cdrom_id * 1000) + cdrom_drives[cdrom_id].host_drive, MF_CHECKED); saveconfig(); - /* if (!cdrom_enabled) - { - pause = 1; - Sleep(100); - cdrom_enabled = 1; - saveconfig(); - resetpchard(); - pause = 0; - } */ } break; } diff --git a/src/x86_ops_i686.h b/src/x86_ops_i686.h index 9afb0e5f0..74f8a7810 100644 --- a/src/x86_ops_i686.h +++ b/src/x86_ops_i686.h @@ -301,6 +301,13 @@ static int opFXSAVESTOR_a16(uint32_t fetchdat) cpu_state.eaaddr = old_eaaddr; + cpu_state.npxc = 0x37F; + cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); + cpu_state.npxs = 0; + *(uint64_t *)cpu_state.tag = 0x0303030303030303ll; + cpu_state.TOP = 0; + cpu_state.ismmx = 0; + CLOCK_CYCLES((cr0 & 1) ? 56 : 67); if(cpu_state.abrt) pclog("FXSAVE: abrt != 0\n"); @@ -477,6 +484,13 @@ static int opFXSAVESTOR_a32(uint32_t fetchdat) cpu_state.eaaddr = old_eaaddr; + cpu_state.npxc = 0x37F; + cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); + cpu_state.npxs = 0; + *(uint64_t *)cpu_state.tag = 0x0303030303030303ll; + cpu_state.TOP = 0; + cpu_state.ismmx = 0; + CLOCK_CYCLES((cr0 & 1) ? 56 : 67); if(cpu_state.abrt) pclog("FXSAVE: abrt != 0\n"); diff --git a/src/x87_ops.h b/src/x87_ops.h index 637c09968..704d0afca 100644 --- a/src/x87_ops.h +++ b/src/x87_ops.h @@ -41,7 +41,7 @@ static inline void x87_set_mmx() static inline void x87_emms() { - *cpu_state.tag = 0x0303030303030303ll; + *(uint64_t *)cpu_state.tag = 0x0303030303030303ll; cpu_state.ismmx = 0; } diff --git a/src/x87_ops_misc.h b/src/x87_ops_misc.h index ea31c74e0..178261fd5 100644 --- a/src/x87_ops_misc.h +++ b/src/x87_ops_misc.h @@ -36,6 +36,7 @@ static int opFINIT(uint32_t fetchdat) cpu_state.npxs = 0; *(uint64_t *)cpu_state.tag = 0x0303030303030303ll; cpu_state.TOP = 0; + cpu_state.ismmx = 0; CLOCK_CYCLES(17); return 0; } @@ -282,6 +283,14 @@ static int FSAVE() } break; } + + cpu_state.npxc = 0x37F; + cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00); + cpu_state.npxs = 0; + *(uint64_t *)cpu_state.tag = 0x0303030303030303ll; + cpu_state.TOP = 0; + cpu_state.ismmx = 0; + CLOCK_CYCLES((cr0 & 1) ? 56 : 67); return cpu_state.abrt; }