From 03ee24cc6cd5eb7a1a87f1e0a6169805b5349597 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 29 Dec 2016 20:40:24 +0100 Subject: [PATCH] Quaternary IDE controller now works properly; Significantly cleaned up ide.c; Made disc_img.c actually compile again. --- src/disc_img.c | 8 +- src/ide.c | 3800 +++++++++++++++++++++++------------------------- src/ide.h | 4 +- src/pc.c | 20 +- src/win.c | 68 +- 5 files changed, 1834 insertions(+), 2066 deletions(-) diff --git a/src/disc_img.c b/src/disc_img.c index 3f43f3080..03034ed67 100644 --- a/src/disc_img.c +++ b/src/disc_img.c @@ -349,9 +349,9 @@ void img_load(int drive, char *fn) { rep_byte = fgetc(img[drive].f); block_len = -block_len; - if (img[drive].cqm_data + cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) + if ((cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) { - block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - (img[drive].cqm_data + cur_pos); + block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - cur_pos; memset(img[drive].cqm_data + cur_pos, rep_byte, block_len); break; } @@ -363,9 +363,9 @@ void img_load(int drive, char *fn) } else if (block_len > 0) { - if (img[drive].cqm_data + cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) + if ((cur_pos + block_len) > ((uint32_t) bpb_total) * ((uint32_t) bpb_bps)) { - block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - (img[drive].cqm_data + cur_pos); + block_len = ((uint32_t) bpb_total) * ((uint32_t) bpb_bps) - cur_pos; fread(img[drive].cqm_data + cur_pos, 1, block_len, img[drive].f); break; } diff --git a/src/ide.c b/src/ide.c index 0cd093255..c05b926c2 100644 --- a/src/ide.c +++ b/src/ide.c @@ -1,8 +1,6 @@ /* Copyright holders: Sarah Walker, Tenshi, SA1988 see COPYING for more details */ -//#define RPCEMU_IDE - #define CDROM_ISO 200 #define IDE_TIME (5 * 100 * (1 << TIMER_SHIFT)) @@ -17,17 +15,11 @@ #include -#ifdef RPCEMU_IDE - #include "rpcemu.h" - #include "iomd.h" - #include "arm.h" -#else - #include "86box.h" - #include "ibm.h" - #include "io.h" - #include "pic.h" - #include "timer.h" -#endif +#include "86box.h" +#include "ibm.h" +#include "io.h" +#include "pic.h" +#include "timer.h" #include "cdrom.h" #include "scsi.h" #include "ide.h" @@ -94,6 +86,26 @@ enum IDE_CDROM }; +static 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; + +static struct +{ + uint16_t len; + uint8_t notification_class; + uint8_t supported_events; +} *gesn_event_header; + +static unsigned int used_len; + uint64_t hdt[128][3] = { { 306, 4, 17 }, { 615, 2, 17 }, { 306, 4, 26 }, { 1024, 2, 17 }, { 697, 3, 17 }, { 306, 8, 17 }, { 614, 4, 17 }, { 615, 4, 17 }, /* 000-007 */ { 670, 4, 17 }, { 697, 4, 17 }, { 987, 3, 17 }, { 820, 4, 17 }, { 670, 5, 17 }, { 697, 5, 17 }, { 733, 5, 17 }, { 615, 6, 17 }, /* 008-015 */ { 462, 8, 17 }, { 306, 8, 26 }, { 615, 4, 26 }, { 1024, 4, 17 }, { 855, 5, 17 }, { 925, 5, 17 }, { 932, 5, 17 }, { 1024, 2, 40 }, /* 016-023 */ @@ -188,123 +200,77 @@ int image_is_hdi(const char *s) } } -int ide34_enable[2] = { 0, 0 }; -int ide34_irq[2] = { 10, 11 }; +int ide_enable[4] = { 1, 1, 0, 0 }; +int ide_irq[4] = { 14, 15, 10, 11 }; static inline void ide_irq_raise(IDE *ide) { -// pclog("IDE_IRQ_RAISE\n"); - if (!(ide->fdisk&2)) { -#ifdef RPCEMU_IDE - iomd.irqb.status |= IOMD_IRQB_IDE; - updateirqs(); -#else -// if (ide->board && !ide->irqstat) pclog("IDE_IRQ_RAISE\n"); -#ifdef MAINLINE - picint((ide->board)?(1<<15):(1<<14)); -#else - switch(ide->board) - { - case 0: - picint(1 << 14); - break; - case 1: - picint(1 << 15); - break; - case 2: - picint(1 << ide34_irq[0]); - break; - case 3: - picint(1 << ide34_irq[1]); - break; - } -#endif - if (ide->board < 2) - { - if (ide_bus_master_set_irq) - ide_bus_master_set_irq(ide->board); - } -#endif + if ((ide->board > 3) || ide->irqstat) + { + return; } + + // pclog("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 < 2) + { + if (ide_bus_master_set_irq) + { + ide_bus_master_set_irq(ide->board); + } + } + } + ide->irqstat=1; - ide->service=1; + ide->service=1; // pclog("raising interrupt %i\n", 14 + ide->board); } static inline void ide_irq_lower(IDE *ide) { -// pclog("IDE_IRQ_LOWER\n"); -// if (ide.board == 0) { -#ifdef RPCEMU_IDE - iomd.irqb.status &= ~IOMD_IRQB_IDE; - updateirqs(); -#else -#ifdef MAINLINE - picintc((ide->board)?(1<<15):(1<<14)); -#else - switch(ide->board) - { - case 0: - picintc(1 << 14); - break; - case 1: - picintc(1 << 15); - break; - case 2: - picintc(1 << ide34_irq[0]); - break; - case 3: - picintc(1 << ide34_irq[1]); - break; - } -#endif -#endif -// } + if ((ide->board > 3) || !(ide->irqstat)) + { + return; + } + + // pclog("Lowering IRQ %i (board %i)\n", ide_irq[ide->board], ide->board); + + picintc(1 << ide_irq[ide->board]); ide->irqstat=0; // ide->service=0; } -int get_irq(uint8_t board) -{ - if (board == 0) return 1 << 14; - else if (board == 1) return 1 << 15; - else if (board == 2) return 1 << ide34_irq[0]; - else if (board == 3) return 1 << ide34_irq[1]; -} - -int get_pic_mask(uint8_t board) -{ - if (board == 0) return 1 << 6; - else if (board == 1) return 1 << 7; - else if (board == 2) return 1 << (ide34_irq[0] & 7); - else if (board == 3) return 1 << (ide34_irq[1] & 7); -} - void ide_irq_update(IDE *ide) { -#ifdef RPCEMU_IDE - if (ide->irqstat && !(iomd.irqb.status & IOMD_IRQB_IDE) && !(ide->fdisk & 2)) { - iomd.irqb.status |= IOMD_IRQB_IDE; - updateirqs(); - } - else if (iomd.irqb.status & IOMD_IRQB_IDE) - { - iomd.irqb.status &= ~IOMD_IRQB_IDE; - updateirqs(); - } -#else -#ifdef MAINLINE - if (ide->irqstat && !((pic2.pend|pic2.ins)&0x40) && !(ide->fdisk & 2)) - picint((ide->board)?(1<<15):(1<<14)); - else if ((pic2.pend|pic2.ins)&0x40) - picintc((ide->board)?(1<<15):(1<<14)); -#else - if (ide->irqstat && !((pic2.pend|pic2.ins)&get_pic_mask(ide->board)) && !(ide->fdisk & 2)) - picint(get_irq(ide->board)); - else if ((pic2.pend|pic2.ins)&get_pic_mask(ide->board)) - picintc(get_irq(ide->board)); -#endif -#endif + int pending = 0; + int mask = 0; + + if (ide->board > 3) + { + return; + } + + mask = ide_irq[ide->board]; + mask &= 7; + + // pclog("Updating IRQ %i (%i) (board %i)\n", ide_irq[ide->board], mask, ide->board); + + pending = (pic2.pend | pic2.ins); + pending &= (1 << mask); + + if (ide->irqstat && !pending && !(ide->fdisk & 2)) + { + picint(1 << ide_irq[ide->board]); + } + else if (pending) + { + picintc(1 << ide_irq[ide->board]); + } } /** * Copy a string into a buffer, padding with spaces, and placing characters as @@ -320,10 +286,14 @@ ide_padstr(char *str, const char *src, int len) { int i, v; - for (i = 0; i < len; i++) { - if (*src != '\0') { + for (i = 0; i < len; i++) + { + if (*src != '\0') + { v = *src++; - } else { + } + else + { v = ' '; } str[i ^ 1] = v; @@ -344,10 +314,14 @@ ide_padstr8(uint8_t *buf, int buf_size, const char *src) { int i; - for (i = 0; i < buf_size; i++) { - if (*src != '\0') { + for (i = 0; i < buf_size; i++) + { + if (*src != '\0') + { buf[i] = *src++; - } else { + } + else + { buf[i] = ' '; } } @@ -378,7 +352,14 @@ static void ide_identify(IDE *ide) ide->buffer[21] = 512; /*Buffer size*/ ide->buffer[47] = 16; /*Max sectors on multiple transfer command*/ ide->buffer[48] = 1; /*Dword transfers supported*/ - ide->buffer[49] = (1 << 8); /* LBA and DMA supported */ + if (ide->board < 2) + { + ide->buffer[49] = (1 << 8); /* LBA and DMA supported */ + } + else + { + ide->buffer[49] = 0; + } if ((c > 1024) || (h > 16) || (s > 63)) { ide->buffer[49] |= (1 << 9); @@ -390,10 +371,13 @@ static void ide_identify(IDE *ide) ide->buffer[60] = (hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt) & 0xFFFF; /* Total addressable sectors (LBA) */ ide->buffer[61] = (hdc[cur_ide[ide->board]].tracks * hdc[cur_ide[ide->board]].hpc * hdc[cur_ide[ide->board]].spt) >> 16; // ide->buffer[63] = 7; /*Multiword DMA*/ - ide->buffer[62] = ide->dma_identify_data[0]; - ide->buffer[63] = ide->dma_identify_data[1]; - ide->buffer[80] = 0xe; /*ATA-1 to ATA-3 supported*/ - ide->buffer[88] = ide->dma_identify_data[2]; + if (ide->board < 2) + { + ide->buffer[62] = ide->dma_identify_data[0]; + ide->buffer[63] = ide->dma_identify_data[1]; + ide->buffer[80] = 0xe; /*ATA-1 to ATA-3 supported*/ + ide->buffer[88] = ide->dma_identify_data[2]; + } } /** @@ -442,15 +426,17 @@ static void ide_next_sector(IDE *ide) else { ide->sector++; - if (ide->sector == (ide->spt + 1)) { + if (ide->sector == (ide->spt + 1)) + { ide->sector = 1; ide->head++; - if (ide->head == ide->hpc) { + if (ide->head == ide->hpc) + { ide->head = 0; ide->cylinder++; - } + } + } } - } } static void loadhd(IDE *ide, int d, const char *fn) @@ -461,7 +447,8 @@ static void loadhd(IDE *ide, int d, const char *fn) int c; ide->base = 0; ide->hdi = 0; - if (ide->hdfile == NULL) { + if (ide->hdfile == NULL) + { /* Try to open existing hard disk image */ if (fn[0] == '.') { @@ -469,16 +456,17 @@ static void loadhd(IDE *ide, int d, const char *fn) return; } ide->hdfile = fopen64(fn, "rb+"); - if (ide->hdfile == NULL) { + if (ide->hdfile == NULL) + { /* Failed to open existing hard disk image */ - if (errno == ENOENT) { + if (errno == ENOENT) + { /* Failed because it does not exist, so try to create new file */ ide->hdfile = fopen64(fn, "wb+"); - if (ide->hdfile == NULL) { - ide->type = IDE_NONE; -/* fatal("Cannot create file '%s': %s", - fn, strerror(errno));*/ + if (ide->hdfile == NULL) + { + ide->type = IDE_NONE; return; } else @@ -503,11 +491,11 @@ static void loadhd(IDE *ide, int d, const char *fn) } ide->hdc_num = d; } - } else { + } + else + { /* Failed for another reason */ - ide->type = IDE_NONE; -/* fatal("Cannot open file '%s': %s", - fn, strerror(errno));*/ + ide->type = IDE_NONE; return; } } @@ -547,7 +535,10 @@ void ide_set_signature(IDE *ide) 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) ide->drive = 0; + if (ide->type == IDE_HDD) + { + ide->drive = 0; + } } int ide_set_features(IDE *ide) @@ -587,13 +578,19 @@ int ide_set_features(IDE *ide) ide->dma_identify_data[2] = 0x3f; break; case 2: - // if (ide->type == IDE_CDROM) return 0; + if ((ide->type == IDE_CDROM) || (ide->board >= 2)) + { + return 0; + } ide->dma_identify_data[0] = 7 | (1 << (val + 8)); ide->dma_identify_data[1] = 7; ide->dma_identify_data[2] = 0x3f; break; case 4: - // if (ide->type == IDE_CDROM) return 0; + if ((ide->type == IDE_CDROM) || (ide->board >= 2)) + { + return 0; + } ide->dma_identify_data[0] = 7; ide->dma_identify_data[1] = 7 | (1 << (val + 8)); ide->dma_identify_data[2] = 0x3f; @@ -626,19 +623,21 @@ void ide_set_sector(IDE *ide, int64_t sector_num) void resetide(void) { - int d; + int d; - /* Close hard disk image files (if previously open) */ - for (d = 0; d < IDE_NUM; d++) { - ide_drives[d].type = IDE_NONE; - if (ide_drives[d].hdfile != NULL) { - fclose(ide_drives[d].hdfile); - ide_drives[d].hdfile = NULL; - } - ide_drives[d].atastat = READY_STAT | DSC_STAT; - ide_drives[d].service = 0; - ide_drives[d].board = (d & 2) ? 1 : 0; - } + /* Close hard disk image files (if previously open) */ + for (d = 0; d < IDE_NUM; d++) + { + ide_drives[d].type = IDE_NONE; + if (ide_drives[d].hdfile != NULL) + { + fclose(ide_drives[d].hdfile); + ide_drives[d].hdfile = NULL; + } + 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. */ @@ -646,13 +645,7 @@ void resetide(void) idecallback[0]=idecallback[1]=0; idecallback[2]=idecallback[3]=0; -#ifdef MAINLINE -#define IDE_DRIVES 4 -#else -#define IDE_DRIVES IDE_NUM -#endif - - for (d = 0; d < IDE_DRIVES; d++) + for (d = 0; d < IDE_NUM; d++) { ide_drives[d].packetstatus = 0xFF; @@ -676,211 +669,200 @@ void resetide(void) ide_drives[d].error = 1; } - - cur_ide[0] = 0; - cur_ide[1] = 2; - cur_ide[2] = 4; - cur_ide[3] = 8; + for (d = 0; d < 4; d++) + { + cur_ide[d] = d << 1; + } -// ide_drives[1].type = IDE_CDROM; + page_flags[GPMODE_CDROM_AUDIO_PAGE] &= ~PAGE_CHANGED; - page_flags[GPMODE_CDROM_AUDIO_PAGE] &= ~PAGE_CHANGED; - - SCSISense.UnitAttention = 0; + SCSISense.UnitAttention = 0; } int idetimes=0; void writeidew(int ide_board, uint16_t val) { - IDE *ide = &ide_drives[cur_ide[ide_board]]; + IDE *ide = &ide_drives[cur_ide[ide_board]]; - /*Some software issue excess writes after the 12 bytes required by the command, this will have all of them ignored*/ + /* 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; + { + return; + } -// pclog("Write IDEw %04X\n",val); - ide->buffer[ide->pos >> 1] = val; - ide->pos+=2; + // pclog("Write IDEw %04X\n",val); + ide->buffer[ide->pos >> 1] = val; + ide->pos+=2; - if (ide->packetstatus == ATAPI_STATUS_PACKET_REQ) - { - if ((ide->pos>=prefix_len+4) && (page_flags[page_current] & PAGE_CHANGEABLE)) - { - 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]; - } - if (ide->pos>=(ide->packlen+2)) - { - ide->packetstatus = ATAPI_STATUS_PACKET_RECEIVED; - timer_process(); - 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; -/* idecallback[ide_board]=6*IDE_TIME;*/ + if (ide->packetstatus == ATAPI_STATUS_PACKET_REQ) + { + if ((ide->pos>=prefix_len+4) && (page_flags[page_current] & PAGE_CHANGEABLE)) + { + 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]; + } + if (ide->pos>=(ide->packlen+2)) + { + ide->packetstatus = ATAPI_STATUS_PACKET_RECEIVED; + timer_process(); + 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(); -// idecallback[ide_board]=60*IDE_TIME; -// if ((ide->buffer[0]&0xFF)==0x43) idecallback[ide_board]=1*IDE_TIME; -// pclog("Packet now waiting!\n"); -/* if (ide->buffer[0]==0x243) - { - idetimes++; - output=3; - }*/ - } - 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(); - } + 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); - writeidew(ide_board, val); - writeidew(ide_board, val >> 16); + // pclog("WriteIDEl %08X\n", val); + writeidew(ide_board, val); + writeidew(ide_board, val >> 16); } 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]; + IDE *ide = &ide_drives[cur_ide[ide_board]]; + IDE *ide_other = &ide_drives[cur_ide[ide_board] ^ 1]; -// if ((cr0&1) && !(eflags&VM_FLAG)) - // pclog("WriteIDE %04X %02X from %04X(%08X):%08X %i\n", addr, val, CS, cs, cpu_state.pc, ins); - // return; - addr|=0x80; - /* ONLY FOR EXPERIMENTAL */ - addr|=0x10; /* 1F0 | 10 = 1F0, 1E8 | 10 = 1F8 */ - addr&=0xFFF7; /* 1F0 & FFF7 = 1F0, 1F8 | FFF7 = 1F0 */ - // if (ide_board) pclog("Write IDEb %04X %02X %04X(%08X):%04X %i %02X %02X\n",addr,val,CS,cs,pc,ins,ide->atastat,ide_drives[0].atastat); - /*if (idedebug) */ -// pclog("Write IDE %08X %02X %04X:%08X\n",addr,val,CS,pc); -// int c; -// rpclog("Write IDE %08X %02X %08X %08X\n",addr,val,PC,armregs[12]); + // pclog("WriteIDE %04X %02X from %04X(%08X):%08X %i\n", addr, val, CS, cs, cpu_state.pc, ins); + addr|=0x90; + addr&=0xFFF7; - if (ide->type == IDE_NONE && (addr == 0x1f0 || addr == 0x1f7)) return; + if (ide->type == IDE_NONE && (addr == 0x1f0 || addr == 0x1f7)) return; - switch (addr) - { + switch (addr) + { case 0x1F0: /* Data */ - writeidew(ide_board, val | (val << 8)); - return; + writeidew(ide_board, val | (val << 8)); + return; case 0x1F1: /* Features */ - ide->cylprecomp = val; - ide_other->cylprecomp = val; - return; + ide->cylprecomp = val; + ide_other->cylprecomp = val; + return; case 0x1F2: /* Sector count */ - ide->secount = val; - ide_other->secount = val; - return; + ide->secount = val; + ide_other->secount = val; + return; case 0x1F3: /* Sector */ - ide->sector = val; - ide->lba_addr = (ide->lba_addr & 0xFFFFF00) | val; - ide_other->sector = val; - ide_other->lba_addr = (ide_other->lba_addr & 0xFFFFF00) | val; - return; + ide->sector = val; + ide->lba_addr = (ide->lba_addr & 0xFFFFF00) | val; + ide_other->sector = val; + ide_other->lba_addr = (ide_other->lba_addr & 0xFFFFF00) | 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); -// pclog("Write cylinder low %02X\n",val); - return; + 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); + 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); - return; + 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); + return; case 0x1F6: /* Drive/Head */ -/* if (val==0xB0) - { - dumpregs(); - exit(-1); - }*/ + if (cur_ide[ide_board] != ((val>>4)&1)+(ide_board<<1)) + { + cur_ide[ide_board]=((val>>4)&1)+(ide_board<<1); - if (cur_ide[ide_board] != ((val>>4)&1)+(ide_board<<1)) - { - cur_ide[ide_board]=((val>>4)&1)+(ide_board<<1); + if (ide->reset || ide_other->reset) + { + ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT; + ide->error = ide_other->error = 1; + ide->secount = ide_other->secount = 1; + ide->sector = ide_other->sector = 1; + ide->head = ide_other->head = 0; + ide->cylinder = ide_other->cylinder = 0; + ide->reset = ide_other->reset = 0; - if (ide->reset || ide_other->reset) - { - ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT; - ide->error = ide_other->error = 1; - ide->secount = ide_other->secount = 1; - ide->sector = ide_other->sector = 1; - ide->head = ide_other->head = 0; - ide->cylinder = ide_other->cylinder = 0; - ide->reset = ide_other->reset = 0; - // ide->blocksize = ide_other->blocksize = 0; - if (IDE_DRIVE_IS_CDROM(ide)) - ide->cylinder=0xEB14; - if (IDE_DRIVE_IS_CDROM(ide_other)) - ide_other->cylinder=0xEB14; + if (IDE_DRIVE_IS_CDROM(ide)) + { + ide->cylinder=0xEB14; + } + if (IDE_DRIVE_IS_CDROM(ide_other)) + { + ide_other->cylinder=0xEB14; + } - idecallback[ide_board] = 0; - timer_update_outstanding(); - return; - } + idecallback[ide_board] = 0; + timer_update_outstanding(); + return; + } - ide = &ide_drives[cur_ide[ide_board]]; - } + ide = &ide_drives[cur_ide[ide_board]]; + } - ide->head = val & 0xF; - ide->lba = val & 0x40; - ide_other->head = val & 0xF; - ide_other->lba = val & 0x40; + ide->head = val & 0xF; + ide->lba = val & 0x40; + ide_other->head = val & 0xF; + ide_other->lba = val & 0x40; - ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); - ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF)|((val & 0xF) << 24); + ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); + ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF)|((val & 0xF) << 24); - ide_irq_update(ide); - return; + ide_irq_update(ide); + return; case 0x1F7: /* Command register */ - if (ide->type == IDE_NONE) - { - ide->error=1; - return; - } -// pclog("IDE command %02X drive %i\n",val,ide.drive); - ide_irq_lower(ide); - ide->command=val; + if (ide->type == IDE_NONE) + { + ide->error=1; + return; + } + ide_irq_lower(ide); + ide->command=val; - // pclog("New IDE command - %02X %i %i\n",ide->command,cur_ide[ide_board],ide_board); - ide->error=0; - switch (val) - { + // pclog("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)) ide->atastat = BUSY_STAT; - else ide->atastat = READY_STAT; + if (IDE_DRIVE_IS_CDROM(ide)) + { + ide->atastat = BUSY_STAT; + } + else + { + ide->atastat = READY_STAT; + } timer_process(); idecallback[ide_board]=100*IDE_TIME; timer_update_outstanding(); @@ -888,7 +870,6 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) case WIN_RESTORE: case WIN_SEEK: -// pclog("WIN_RESTORE start\n"); ide->atastat = READY_STAT; timer_process(); idecallback[ide_board]=100*IDE_TIME; @@ -896,886 +877,766 @@ void writeide(int ide_board, uint16_t addr, uint8_t val) return; case WIN_READ_MULTIPLE: - /* Fatal removed in accordance with the official ATAPI reference: - - If the Read Multiple command is attempted before the Set Multiple Mode - 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->blocksize && (ide->type != IDE_CDROM)) - fatal("READ_MULTIPLE - blocksize = 0\n"); */ -#if 0 - if (ide->lba) pclog("Read Multiple %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr); - else pclog("Read Multiple %i sectors from sector %i cylinder %i head %i %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins); -#endif - ide->blockcount = 0; + /* Fatal removed in accordance with the official ATAPI reference: + If the Read Multiple command is attempted before the Set Multiple Mode + command has been executed or when Read Multiple commands are + disabled, the Read Multiple operation is rejected with an Aborted Com- + mand error. */ + ide->blockcount = 0; case WIN_READ: case WIN_READ_NORETRY: case WIN_READ_DMA: -/* if (ide.secount>1) - { - fatal("Read %i sectors from sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head); - }*/ -#if 0 - if (ide->lba) pclog("Read %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr); - else pclog("Read %i sectors from sector %i cylinder %i head %i %i\n",ide->secount,ide->sector,ide->cylinder,ide->head,ins); -#endif - ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); - return; + ide->atastat = BUSY_STAT; + timer_process(); + idecallback[ide_board]=200*IDE_TIME; + timer_update_outstanding(); + return; case WIN_WRITE_MULTIPLE: - if (!ide->blocksize && (ide->type != IDE_CDROM)) - fatal("Write_MULTIPLE - blocksize = 0\n"); -#if 0 - if (ide->lba) pclog("Write Multiple %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr); - else pclog("Write Multiple %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); -#endif - ide->blockcount = 0; + if (!ide->blocksize && (ide->type != IDE_CDROM)) + { + fatal("Write_MULTIPLE - blocksize = 0\n"); + } + ide->blockcount = 0; case WIN_WRITE: case WIN_WRITE_NORETRY: - /* if (ide.secount>1) - { - fatal("Write %i sectors to sector %i cylinder %i head %i\n",ide.secount,ide.sector,ide.cylinder,ide.head); - }*/ -#if 0 - if (ide->lba) pclog("Write %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr); - else pclog("Write %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); -#endif - ide->atastat = DRQ_STAT | DSC_STAT | READY_STAT; - ide->pos=0; - return; + ide->atastat = DRQ_STAT | DSC_STAT | READY_STAT; + ide->pos=0; + return; case WIN_WRITE_DMA: -#if 0 - if (ide->lba) pclog("Write %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr); - else pclog("Write %i sectors to sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); -#endif - ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); - return; + ide->atastat = BUSY_STAT; + timer_process(); + idecallback[ide_board]=200*IDE_TIME; + timer_update_outstanding(); + return; case WIN_VERIFY: case WIN_VERIFY_ONCE: -#if 0 - if (ide->lba) pclog("Read verify %i sectors from LBA addr %07X\n",ide->secount,ide->lba_addr); - else pclog("Read verify %i sectors from sector %i cylinder %i head %i\n",ide->secount,ide->sector,ide->cylinder,ide->head); -#endif - ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); - return; + ide->atastat = BUSY_STAT; + timer_process(); + idecallback[ide_board]=200*IDE_TIME; + timer_update_outstanding(); + return; case WIN_FORMAT: -// pclog("Format track %i head %i\n",ide.cylinder,ide.head); - ide->atastat = DRQ_STAT; -// idecallback[ide_board]=200; - ide->pos=0; - return; + ide->atastat = DRQ_STAT; + ide->pos=0; + return; case WIN_SPECIFY: /* Initialize Drive Parameters */ - ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=30*IDE_TIME; - timer_update_outstanding(); -// pclog("SPECIFY\n"); -// output=1; - return; + ide->atastat = BUSY_STAT; + timer_process(); + idecallback[ide_board]=30*IDE_TIME; + timer_update_outstanding(); + return; case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */ case WIN_PIDENTIFY: /* Identify Packet Device */ case WIN_SET_MULTIPLE_MODE: /*Set Multiple Mode*/ -// output=1; case WIN_NOP: case WIN_STANDBYNOW1: case WIN_SETIDLE1: /* Idle */ case WIN_CHECKPOWERMODE1: - ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=30*IDE_TIME; - // callbackide(ide_board); -// idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); - return; + ide->atastat = BUSY_STAT; + timer_process(); + idecallback[ide_board]=30*IDE_TIME; + timer_update_outstanding(); + return; case WIN_IDENTIFY: /* Identify Device */ case WIN_SET_FEATURES: case WIN_READ_NATIVE_MAX: -// output=3; -// timetolive=500; - ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=200*IDE_TIME; - timer_update_outstanding(); - return; + ide->atastat = BUSY_STAT; + timer_process(); + idecallback[ide_board]=200*IDE_TIME; + timer_update_outstanding(); + return; case WIN_PACKETCMD: /* ATAPI Packet */ - ide->packetstatus = ATAPI_STATUS_IDLE; - ide->atastat = BUSY_STAT; - timer_process(); - idecallback[ide_board]=1;//30*IDE_TIME; - timer_update_outstanding(); - ide->pos=0; - return; + ide->packetstatus = ATAPI_STATUS_IDLE; + ide->atastat = BUSY_STAT; + timer_process(); + idecallback[ide_board]=1;//30*IDE_TIME; + timer_update_outstanding(); + ide->pos=0; + return; case 0xF0: - default: + default: ide->atastat = READY_STAT | ERR_STAT | DSC_STAT; ide->error = ABRT_ERR; - ide_irq_raise(ide); -/* fatal("Bad IDE command %02X\n", val);*/ - // pclog("Bad IDE command %02X\n", val); - return; - } - - return; + ide_irq_raise(ide); + return; + } + return; case 0x3F6: /* Device control */ - if ((ide->fdisk&4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) - { - timer_process(); - idecallback[ide_board]=500*IDE_TIME; - timer_update_outstanding(); - if (ide->type != IDE_NONE) - { - ide->reset = 1; - } - if (ide_other->type != IDE_NONE) - { - ide->reset = 1; - } - ide->atastat = ide_other->atastat = BUSY_STAT; -// pclog("IDE Reset %i\n", ide_board); - } - ide->fdisk = ide_other->fdisk = val; - ide_irq_update(ide); - return; - } -// fatal("Bad IDE write %04X %02X\n", addr, val); + if ((ide->fdisk & 4) && !(val&4) && (ide->type != IDE_NONE || ide_other->type != IDE_NONE)) + { + timer_process(); + idecallback[ide_board]=500*IDE_TIME; + timer_update_outstanding(); + + if (ide->type != IDE_NONE) + { + ide->reset = 1; + } + if (ide_other->type != IDE_NONE) + { + ide->reset = 1; + } + ide->atastat = ide_other->atastat = BUSY_STAT; + // pclog("IDE Reset %i\n", ide_board); + } + ide->fdisk = ide_other->fdisk = val; + ide_irq_update(ide); + return; + } + // fatal("Bad IDE write %04X %02X\n", addr, val); } uint8_t readide(int ide_board, uint16_t addr) { - IDE *ide = &ide_drives[cur_ide[ide_board]]; - uint8_t temp; - uint16_t tempw; + IDE *ide = &ide_drives[cur_ide[ide_board]]; + uint8_t temp; + uint16_t tempw; - addr|=0x80; - /* ONLY FOR EXPERIMENTAL */ - addr|=0x10; /* 1F0 | 10 = 1F0, 1E8 | 10 = 1F8 */ - addr&=0xFFF7; /* 1F0 & FFF7 = 1F0, 1F8 | FFF7 = 1F0 */ + addr|=0x90; + addr&=0xFFF7; -// if ((cr0&1) && !(eflags&VM_FLAG)) -// pclog("ReadIDE %04X from %04X(%08X):%08X\n", addr, CS, cs, pc); -// return 0xFF; - - if (ide->type == IDE_NONE && (addr == 0x1f0 || addr == 0x1f7)) + if (ide->type == IDE_NONE && (addr == 0x1f0 || addr == 0x1f7)) + { + if (addr == 0x1f7) { - // pclog("Reading empty IDE channel (%04X)\n", addr); - if (addr == 0x1f7) - { - /* This is apparently required for an empty ID channel. */ - return 0x20; - } - return 0; + /* This is apparently required for an empty ID channel. */ + return 0x20; } -// /*if (addr!=0x1F7 && addr!=0x3F6) */pclog("Read IDEb %04X %02X %02X %i %04X:%04X %i %04X\n",addr,ide->atastat,(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0),cur_ide[ide_board],CS,pc,ide_board, BX); -//rpclog("Read IDE %08X %08X %02X\n",addr,PC,iomd.irqb.mask); - switch (addr) - { - case 0x1F0: /* Data */ - tempw = readidew(ide_board); -// pclog("Read IDEW %04X\n", tempw); - temp = tempw & 0xff; - break; + return 0; + } + + switch (addr) + { + case 0x1F0: /* Data */ + tempw = readidew(ide_board); + temp = tempw & 0xff; + break; - case 0x1F1: /* Error */ -// pclog("Read error %02X\n",ide.error); - if (ide->type == IDE_NONE) - { - temp = 1; - } - else - { - temp = ide->error; - } - break; + case 0x1F1: /* Error */ + if (ide->type == IDE_NONE) + { + temp = 1; + } + else + { + temp = ide->error; + } + break; - case 0x1F2: /* Sector count */ -// pclog("Read sector count %02X\n",ide->secount); - if (ide->type == IDE_NONE) - { - temp = 1; - } - else - { - temp = (uint8_t)ide->secount; - // pclog("Returning sector count: %i\n", temp); - } - break; + case 0x1F2: /* Sector count */ + if (ide->type == IDE_NONE) + { + temp = 1; + } + else + { + temp = (uint8_t)ide->secount; + } + break; - case 0x1F3: /* Sector */ - if (ide->type == IDE_NONE) - { - temp = 1; - } - else - { - temp = (uint8_t)ide->sector; - } - break; + case 0x1F3: /* Sector */ + if (ide->type == IDE_NONE) + { + temp = 1; + } + else + { + temp = (uint8_t)ide->sector; + } + break; - case 0x1F4: /* Cylinder low */ -// pclog("Read cyl low %02X\n",ide.cylinder&0xFF); - if (ide->type == IDE_NONE) - { - temp = 0xFF; - } - else - { - temp = (uint8_t)(ide->cylinder&0xFF); - } - break; + case 0x1F4: /* Cylinder low */ + if (ide->type == IDE_NONE) + { + temp = 0xFF; + } + else + { + temp = (uint8_t)(ide->cylinder&0xFF); + } + break; - case 0x1F5: /* Cylinder high */ -// pclog("Read cyl low %02X\n",ide.cylinder>>8); - if (ide->type == IDE_NONE) - { - temp = 0xFF; - } - else - { - temp = (uint8_t)(ide->cylinder>>8); - } - break; + case 0x1F5: /* Cylinder high */ + if (ide->type == IDE_NONE) + { + temp = 0xFF; + } + else + { + temp = (uint8_t)(ide->cylinder>>8); + } + break; - case 0x1F6: /* Drive/Head */ - if (ide->type == IDE_NONE) - { - temp = (uint8_t)(((cur_ide[ide_board] & 1) ? 0x10 : 0) | 0xa0); - } - else - { - temp = (uint8_t)(ide->head | ((cur_ide[ide_board] & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); - } - break; + case 0x1F6: /* Drive/Head */ + if (ide->type == IDE_NONE) + { + temp = (uint8_t)(((cur_ide[ide_board] & 1) ? 0x10 : 0) | 0xa0); + } + else + { + temp = (uint8_t)(ide->head | ((cur_ide[ide_board] & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); + } + break; - case 0x1F7: /* Status */ -#if 0 - if (ide->type == IDE_NONE) - { -// pclog("Return status 00\n"); - temp = DSC_STAT; - break; - } -#endif - ide_irq_lower(ide); - if (ide->type == IDE_CDROM) - { -// pclog("Read CDROM status %02X\n",(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0)); - temp = (ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - } - else - { -// && ide->service) return ide.atastat[ide.board]|SERVICE_STAT; -// pclog("Return status %02X %04X:%04X %02X %02X\n",ide->atastat, CS ,pc, AH, BH); - temp = ide->atastat; - } - break; + case 0x1F7: /* Status */ + ide_irq_lower(ide); + if (ide->type == IDE_CDROM) + { + temp = (ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); + } + else + { + temp = ide->atastat; + } + break; - case 0x3F6: /* Alternate Status */ -// pclog("3F6 read %02X\n",ide.atastat[ide.board]); -// if (output) output=0; - if (ide->type == IDE_NONE) - { -// pclog("Return status 00\n"); - temp = DSC_STAT; - break; - } - if (ide->type == IDE_CDROM) - { -// pclog("Read CDROM status %02X\n",(ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0)); - temp = (ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - } - else - { -// && ide->service) return ide.atastat[ide.board]|SERVICE_STAT; -// pclog("Return status %02X\n",ide->atastat); - temp = ide->atastat; - } - 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); - return temp; -// fatal("Bad IDE read %04X\n", addr); + case 0x3F6: /* Alternate Status */ + if (ide->type == IDE_NONE) + { + temp = DSC_STAT; + break; + } + if (ide->type == IDE_CDROM) + { + temp = (ide->atastat & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); + } + else + { + temp = ide->atastat; + } + 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); + return temp; + // fatal("Bad IDE read %04X\n", addr); } uint16_t readidew(int ide_board) { - IDE *ide = &ide_drives[cur_ide[ide_board]]; - uint16_t temp; + IDE *ide = &ide_drives[cur_ide[ide_board]]; + uint16_t temp; -// return 0xFFFF; -// pclog("Read IDEw %04X %04X:%04X %02X %i %i\n",ide->buffer[ide->pos >> 1],CS,pc,opcode,ins, ide->pos); - -//if (idedebug) pclog("Read IDEW %08X\n",PC); + temp = ide->buffer[ide->pos >> 1]; - temp = ide->buffer[ide->pos >> 1]; - - ide->pos+=2; + ide->pos+=2; if ((ide->command == WIN_PACKETCMD) && ((ide->packetstatus == ATAPI_STATUS_REQ_SENSE) || (ide->packetstatus==8))) { callnonreadcd(ide); return temp; } - if ((ide->pos>=512 && ide->command != WIN_PACKETCMD) || (ide->command == WIN_PACKETCMD && ide->pos>=ide->packlen)) - { -// pclog("Over! packlen %i %i\n",ide->packlen,ide->pos); - ide->pos=0; - if (ide->command == WIN_PACKETCMD)// && ide.packetstatus==6) - { -// pclog("Call readCD\n"); - callreadcd(ide); - } - else - { - 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_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(); -// pclog("set idecallback\n"); -// callbackide(ide_board); - } -// else -// pclog("readidew done %02X\n", ide->atastat); - } - } - } -// pclog("Read IDEw %04X\n",temp); - return temp; + if ((ide->pos>=512 && ide->command != WIN_PACKETCMD) || (ide->command == WIN_PACKETCMD && ide->pos>=ide->packlen)) + { + ide->pos=0; + if (ide->command == WIN_PACKETCMD)// && ide.packetstatus==6) + { + callreadcd(ide); + } + else + { + 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_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(); + } + } + } + } + + // pclog("Read IDEw %04X\n",temp); + return temp; } uint32_t readidel(int ide_board) { - uint16_t temp; -// pclog("Read IDEl %i\n", ide_board); - temp = readidew(ide_board); - return temp | (readidew(ide_board) << 16); + uint16_t temp; + // pclog("Read IDEl %i\n", ide_board); + temp = readidew(ide_board); + return temp | (readidew(ide_board) << 16); } int times30=0; void callbackide(int ide_board) { - IDE *ide = &ide_drives[cur_ide[ide_board]]; - IDE *ide_other = &ide_drives[cur_ide[ide_board] ^ 1]; - off64_t addr; - uint64_t faddr; - int c; - ext_ide = ide; - int64_t snum; -// return; - if (ide->command==0x30) times30++; -// if (times30==2240) output=1; - //if (times30==2471 && ide->command==0xA0) output=1; - ///*if (ide_board) */pclog("CALLBACK %02X %i %i %i\n",ide->command,times30,ide->reset,cur_ide[ide_board]); - // if (times30==1294) -// output=1; - if (ide->reset) - { - ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT; - ide->error = ide_other->error = 1; - ide->secount = ide_other->secount = 1; - ide->sector = ide_other->sector = 1; - ide->head = ide_other->head = 0; - ide->cylinder = ide_other->cylinder = 0; - ide->reset = ide_other->reset = 0; - if (IDE_DRIVE_IS_CDROM(ide)) - { - ide->cylinder=0xEB14; - cdrom->stop(); - } - if (ide->type == IDE_NONE) - { - ide->cylinder=0xFFFF; - cdrom->stop(); - } - if (IDE_DRIVE_IS_CDROM(ide_other)) - { - ide_other->cylinder=0xEB14; - cdrom->stop(); - } - if (ide_other->type == IDE_NONE) - { - ide_other->cylinder=0xFFFF; - cdrom->stop(); - } -// pclog("Reset callback\n"); - return; - } - switch (ide->command) - { - //Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, Cylinder Low = 14h, Cylinder High =EBh and Drive/Head = 00h. - case WIN_SRST: /*ATAPI Device Reset */ - ide->atastat = READY_STAT | DSC_STAT; - ide->error=1; /*Device passed*/ - ide->secount = ide->sector = 1; - ide_set_signature(ide); + IDE *ide = &ide_drives[cur_ide[ide_board]]; + IDE *ide_other = &ide_drives[cur_ide[ide_board] ^ 1]; + off64_t addr; + uint64_t faddr; + int c; + ext_ide = ide; + int64_t snum; + + 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->reset) + { + ide->atastat = ide_other->atastat = READY_STAT | DSC_STAT; + ide->error = ide_other->error = 1; + ide->secount = ide_other->secount = 1; + ide->sector = ide_other->sector = 1; + ide->head = ide_other->head = 0; + ide->cylinder = ide_other->cylinder = 0; + ide->reset = ide_other->reset = 0; + if (IDE_DRIVE_IS_CDROM(ide)) - ide->atastat = 0; - ide_irq_raise(ide); - if (IDE_DRIVE_IS_CDROM(ide)) - ide->service = 0; - return; + { + ide->cylinder=0xEB14; + cdrom->stop(); + } + if (ide->type == IDE_NONE) + { + ide->cylinder=0xFFFF; + cdrom->stop(); + } + if (IDE_DRIVE_IS_CDROM(ide_other)) + { + ide_other->cylinder=0xEB14; + cdrom->stop(); + } + if (ide_other->type == IDE_NONE) + { + ide_other->cylinder=0xFFFF; + cdrom->stop(); + } + // pclog("Reset callback\n"); + return; + } + + switch (ide->command) + { + /* Initialize the Task File Registers as follows: Status = 00h, Error = 01h, Sector Count = 01h, Sector Number = 01h, + Cylinder Low = 14h, Cylinder High =EBh and Drive/Head = 00h. */ + case WIN_SRST: /*ATAPI Device Reset */ + ide->atastat = READY_STAT | DSC_STAT; + ide->error=1; /*Device passed*/ + ide->secount = ide->sector = 1; + ide_set_signature(ide); + + if (IDE_DRIVE_IS_CDROM(ide)) + { + ide->atastat = 0; + } + ide_irq_raise(ide); + if (IDE_DRIVE_IS_CDROM(ide)) + { + ide->service = 0; + } + return; case WIN_RESTORE: case WIN_SEEK: - if (IDE_DRIVE_IS_CDROM(ide)) { - pclog("WIN_RESTORE callback on CD-ROM\n"); - goto abort_cmd; - } + if (IDE_DRIVE_IS_CDROM(ide)) + { + goto abort_cmd; + } case WIN_NOP: case WIN_STANDBYNOW1: case WIN_SETIDLE1: -// pclog("WIN_RESTORE callback\n"); - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; + ide->atastat = READY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; case WIN_CHECKPOWERMODE1: - if (IDE_DRIVE_IS_CDROM(ide)) { - goto abort_cmd; - } - ide->secount = 0xFF; - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; + if (IDE_DRIVE_IS_CDROM(ide)) + { + goto abort_cmd; + } + ide->secount = 0xFF; + ide->atastat = READY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; case WIN_READ: case WIN_READ_NORETRY: - if (IDE_DRIVE_IS_CDROM(ide)) { - ide_set_signature(ide); - goto abort_cmd; - } - addr = ide_get_sector(ide) * 512; -// pclog("Read %i %i %i %08X\n",ide.cylinder,ide.head,ide.sector,addr); - /* if (ide.cylinder || ide.head) - { - fatal("Read from other cylinder/head"); - }*/ - fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); - fread(ide->buffer, 512, 1, ide->hdfile); - ide->pos=0; - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; -// pclog("Read sector callback %i %i %i offset %08X %i left %i %02X\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount,ide.spt,ide.atastat[ide.board]); -// if (addr) output=3; - ide_irq_raise(ide); -#ifndef RPCEMU_IDE - readflash=1; -#endif - return; + if (IDE_DRIVE_IS_CDROM(ide)) + { + ide_set_signature(ide); + goto abort_cmd; + } + addr = ide_get_sector(ide) * 512; + + fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); + fread(ide->buffer, 512, 1, ide->hdfile); + ide->pos=0; + ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + + ide_irq_raise(ide); + + readflash=1; + return; case WIN_READ_DMA: - if (IDE_DRIVE_IS_CDROM(ide)) { - goto abort_cmd; - } - addr = ide_get_sector(ide) * 512; - fseeko64(ide->hdfile, addr, SEEK_SET); - fread(ide->buffer, 512, 1, ide->hdfile); - ide->pos=0; + if (IDE_DRIVE_IS_CDROM(ide) || (ide->board >= 2)) + { + goto abort_cmd; + } + addr = ide_get_sector(ide) * 512; + fseeko64(ide->hdfile, addr, SEEK_SET); + fread(ide->buffer, 512, 1, ide->hdfile); + ide->pos=0; - if (ide_bus_master_read_sector) - { - if (ide_bus_master_read_sector(ide_board, (uint8_t *)ide->buffer)) - idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ - else - { - /*DMA successful*/ - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + if (ide_bus_master_read_sector) + { + if (ide_bus_master_read_sector(ide_board, (uint8_t *)ide->buffer)) + { + idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ + } + else + { + /*DMA successful*/ + ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) - { - ide_next_sector(ide); - ide->atastat = BUSY_STAT; - idecallback[ide_board]=6*IDE_TIME; - } - else - { - ide_irq_raise(ide); - } - } - } -#ifndef RPCEMU_IDE - readflash=1; -#endif - return; + ide->secount = (ide->secount - 1) & 0xff; + if (ide->secount) + { + ide_next_sector(ide); + ide->atastat = BUSY_STAT; + idecallback[ide_board]=6*IDE_TIME; + } + else + { + ide_irq_raise(ide); + } + } + } + + readflash=1; + return; case WIN_READ_MULTIPLE: - /* According to the official ATA reference: + /* According to the official ATA reference: - If the Read Multiple command is attempted before the Set Multiple Mode - 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) { - goto abort_cmd; - } + If the Read Multiple command is attempted before the Set Multiple Mode + 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) + { + goto abort_cmd; + } - addr = ide_get_sector(ide) * 512; -// pclog("Read multiple from %08X %i (%i) %i\n", addr, ide->blockcount, ide->blocksize, ide->secount); - fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); - fread(ide->buffer, 512, 1, ide->hdfile); - ide->pos=0; - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - if (!ide->blockcount)// || ide->secount == 1) - { -// pclog("Read multiple int\n"); - ide_irq_raise(ide); - } - ide->blockcount++; - if (ide->blockcount >= ide->blocksize) - ide->blockcount = 0; -#ifndef RPCEMU_IDE - readflash=1; -#endif - return; + addr = ide_get_sector(ide) * 512; + fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); + fread(ide->buffer, 512, 1, ide->hdfile); + ide->pos=0; + ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + if (!ide->blockcount) + { + // pclog("Read multiple int\n"); + ide_irq_raise(ide); + } + ide->blockcount++; + if (ide->blockcount >= ide->blocksize) + { + ide->blockcount = 0; + } + + readflash=1; + return; case WIN_WRITE: case WIN_WRITE_NORETRY: - if (IDE_DRIVE_IS_CDROM(ide)) { - goto abort_cmd; - } - addr = ide_get_sector(ide) * 512; -// pclog("Write sector callback %i %i %i offset %08X %i left %i\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount,ide.spt); - fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); - fwrite(ide->buffer, 512, 1, ide->hdfile); - ide_irq_raise(ide); - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) - { - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - ide->pos=0; - ide_next_sector(ide); - } - else - ide->atastat = READY_STAT | DSC_STAT; -#ifndef RPCEMU_IDE - readflash=1; -#endif - return; + if (IDE_DRIVE_IS_CDROM(ide)) + { + goto abort_cmd; + } + addr = ide_get_sector(ide) * 512; + fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); + fwrite(ide->buffer, 512, 1, ide->hdfile); + ide_irq_raise(ide); + ide->secount = (ide->secount - 1) & 0xff; + if (ide->secount) + { + ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + ide->pos=0; + ide_next_sector(ide); + } + else + { + ide->atastat = READY_STAT | DSC_STAT; + } + + readflash=1; + return; case WIN_WRITE_DMA: - if (IDE_DRIVE_IS_CDROM(ide)) { - goto abort_cmd; - } + if (IDE_DRIVE_IS_CDROM(ide) || (ide_board >= 2)) + { + goto abort_cmd; + } - if (ide_bus_master_write_sector) - { - if (ide_bus_master_write_sector(ide_board, (uint8_t *)ide->buffer)) - idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ - else - { - /*DMA successful*/ - /*if(IDE_DRIVE_IS_CDROM(ide)) - { - } - else - {*/ - addr = ide_get_sector(ide) * 512; - fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); - fwrite(ide->buffer, 512, 1, ide->hdfile); - //} - - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + if (ide_bus_master_write_sector) + { + if (ide_bus_master_write_sector(ide_board, (uint8_t *)ide->buffer)) + { + idecallback[ide_board]=6*IDE_TIME; /*DMA not performed, try again later*/ + } + else + { + /*DMA successful*/ + addr = ide_get_sector(ide) * 512; + fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); + fwrite(ide->buffer, 512, 1, ide->hdfile); - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) - { - ide_next_sector(ide); - ide->atastat = BUSY_STAT; - idecallback[ide_board]=6*IDE_TIME; - } - else - { - ide_irq_raise(ide); - } - } - } -#ifndef RPCEMU_IDE - readflash=1; -#endif - return; + ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + + ide->secount = (ide->secount - 1) & 0xff; + if (ide->secount) + { + ide_next_sector(ide); + ide->atastat = BUSY_STAT; + idecallback[ide_board]=6*IDE_TIME; + } + else + { + ide_irq_raise(ide); + } + } + } + + readflash=1; + return; case WIN_WRITE_MULTIPLE: - if (IDE_DRIVE_IS_CDROM(ide)) { - goto abort_cmd; - } - addr = ide_get_sector(ide) * 512; -// pclog("Write sector callback %i %i %i offset %08X %i left %i\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount,ide.spt); - fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); - fwrite(ide->buffer, 512, 1, ide->hdfile); - ide->blockcount++; - if (ide->blockcount >= ide->blocksize || ide->secount == 1) - { - ide->blockcount = 0; - ide_irq_raise(ide); - } - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) - { - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - ide->pos=0; - ide_next_sector(ide); - } - else - ide->atastat = READY_STAT | DSC_STAT; -#ifndef RPCEMU_IDE - readflash=1; -#endif - return; + if (IDE_DRIVE_IS_CDROM(ide)) + { + goto abort_cmd; + } + addr = ide_get_sector(ide) * 512; + fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); + fwrite(ide->buffer, 512, 1, ide->hdfile); + ide->blockcount++; + if (ide->blockcount >= ide->blocksize || ide->secount == 1) + { + ide->blockcount = 0; + ide_irq_raise(ide); + } + ide->secount = (ide->secount - 1) & 0xff; + if (ide->secount) + { + ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + ide->pos=0; + ide_next_sector(ide); + } + else + { + ide->atastat = READY_STAT | DSC_STAT; + } + + readflash=1; + return; case WIN_VERIFY: case WIN_VERIFY_ONCE: - if (IDE_DRIVE_IS_CDROM(ide)) { - goto abort_cmd; - } - ide->pos=0; - ide->atastat = READY_STAT | DSC_STAT; -// pclog("Read verify callback %i %i %i offset %08X %i left\n",ide.sector,ide.cylinder,ide.head,addr,ide.secount); - ide_irq_raise(ide); -#ifndef RPCEMU_IDE - readflash=1; -#endif - return; - - case WIN_FORMAT: - 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); - fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); - memset(ide->buffer, 0, 512); - for (c=0;csecount;c++) - { - fwrite(ide->buffer, 512, 1, ide->hdfile); - } - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); -#ifndef RPCEMU_IDE - readflash=1; -#endif - return; - - case WIN_DRIVE_DIAGNOSTICS: - ide_set_signature(ide); - ide->error=1; /*No error detected*/ - if (IDE_DRIVE_IS_CDROM(ide)) - { - ide->atastat = 0; - } - else - { + if (IDE_DRIVE_IS_CDROM(ide)) + { + goto abort_cmd; + } + ide->pos=0; ide->atastat = READY_STAT | DSC_STAT; ide_irq_raise(ide); - } - return; + readflash=1; + return; + + case WIN_FORMAT: + 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); + fseeko64(ide->hdfile, ide->base + addr, SEEK_SET); + memset(ide->buffer, 0, 512); + for (c=0;csecount;c++) + { + fwrite(ide->buffer, 512, 1, ide->hdfile); + } + ide->atastat = READY_STAT | DSC_STAT; + ide_irq_raise(ide); + + readflash=1; + return; + + case WIN_DRIVE_DIAGNOSTICS: + ide_set_signature(ide); + ide->error=1; /*No error detected*/ + + if (IDE_DRIVE_IS_CDROM(ide)) + { + ide->atastat = 0; + } + else + { + ide->atastat = READY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + return; case WIN_SPECIFY: /* Initialize Drive Parameters */ - if (IDE_DRIVE_IS_CDROM(ide)) { - goto abort_cmd; - } - ide->spt=ide->secount; - ide->hpc=ide->head+1; -#if 0 - if (ide->hdi) - { - faddr = ftello64(ide->hdfile); - if (hdc[ide->hdc_num].spt != ide->spt) - { - fseeko64(ide->hdfile, 0x34, SEEK_SET); - fwrite(&(ide->spt), 1, 4, ide->hdfile); - } - if (hdc[ide->hdc_num].hpc != ide->hpc) - { - fseeko64(ide->hdfile, 0x38, SEEK_SET); - fwrite(&(ide->hpc), 1, 4, ide->hdfile); - } - fseeko64(ide->hdfile, faddr, SEEK_SET); - } -#endif -#if 0 - /* Make sure other parts of the emulator are aware the sectors and heads have changed. */ - hdc[ide->hdc_num].spt = ide->spt; - hdc[ide->hdc_num].hpc = ide->hpc; -#endif - ide->atastat = READY_STAT | DSC_STAT; -#ifndef RPCEMU_IDE -// pclog("SPECIFY - %i sectors per track, %i heads per cylinder %i %i\n",ide->spt,ide->hpc,cur_ide[ide_board],ide_board); -#endif - ide_irq_raise(ide); - return; + if (IDE_DRIVE_IS_CDROM(ide)) + { + goto abort_cmd; + } + ide->spt=ide->secount; + ide->hpc=ide->head+1; + ide->atastat = READY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; case WIN_PIDENTIFY: /* Identify Packet Device */ - if (IDE_DRIVE_IS_CDROM(ide)) { -// pclog("ATAPI identify\n"); - ide_atapi_identify(ide); - ide->pos=0; - ide->error=0; - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - } -// pclog("Not ATAPI\n"); - goto abort_cmd; + 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_irq_raise(ide); + return; + } + goto abort_cmd; case WIN_SET_MULTIPLE_MODE: - if (IDE_DRIVE_IS_CDROM(ide)) { - goto abort_cmd; - } - ide->blocksize = ide->secount; - ide->atastat = READY_STAT | DSC_STAT; -#ifndef RPCEMU_IDE - pclog("Set multiple mode - %i\n", ide->blocksize); -#endif - ide_irq_raise(ide); - return; - - - // case WIN_SETIDLE1: /* Idle */ - // goto abort_cmd; + 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_irq_raise(ide); + return; case WIN_SET_FEATURES: - if (!(ide_set_features(ide))) goto abort_cmd; - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; + if (!(ide_set_features(ide))) + { + goto abort_cmd; + } + ide->atastat = READY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; case WIN_READ_NATIVE_MAX: - if (ide->type != IDE_HDD) goto abort_cmd; - snum = hdc[cur_ide[ide->board]].spt; - snum *= hdc[cur_ide[ide->board]].hpc; - snum *= hdc[cur_ide[ide->board]].tracks; - ide_set_sector(ide, snum - 1); - ide->atastat = READY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; + if (ide->type != IDE_HDD) + { + goto abort_cmd; + } + snum = hdc[cur_ide[ide->board]].spt; + snum *= hdc[cur_ide[ide->board]].hpc; + snum *= hdc[cur_ide[ide->board]].tracks; + ide_set_sector(ide, snum - 1); + ide->atastat = READY_STAT | DSC_STAT; + ide_irq_raise(ide); + return; case WIN_IDENTIFY: /* Identify Device */ - if (ide->type == IDE_NONE) - { - ide_set_signature(ide); - goto abort_cmd; - } - if (IDE_DRIVE_IS_CDROM(ide)) - { - ide_set_signature(ide); - goto abort_cmd; - } - else - { - ide_identify(ide); - ide->pos=0; - ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; -// pclog("ID callback\n"); - ide_irq_raise(ide); - } - return; + if (ide->type == IDE_NONE) + { + ide_set_signature(ide); + goto abort_cmd; + } + if (IDE_DRIVE_IS_CDROM(ide)) + { + ide_set_signature(ide); + goto abort_cmd; + } + else + { + ide_identify(ide); + ide->pos=0; + ide->atastat = DRQ_STAT | READY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + return; case WIN_PACKETCMD: /* ATAPI Packet */ - if (!IDE_DRIVE_IS_CDROM(ide)) goto abort_cmd; - // pclog("Packet callback! %i %08X\n",ide->packetstatus,ide); + if (!IDE_DRIVE_IS_CDROM(ide)) + { + goto abort_cmd; + } - if (ide->packetstatus == ATAPI_STATUS_IDLE) - { - readcdmode=0; - ide->pos=0; - // ide->secount = (uint8_t)((ide->secount&0xF8)|1); - ide->secount = 1; - ide->atastat = READY_STAT | DRQ_STAT |(ide->atastat&ERR_STAT); - //ide_irq_raise(ide); -// pclog("1 Preparing to recieve packet max DRQ count %04X\n",ide->cylinder); - } - else if (ide->packetstatus == ATAPI_STATUS_COMMAND) - { - ide->atastat = BUSY_STAT|(ide->atastat&ERR_STAT); -// pclog("Running ATAPI command 2\n"); - atapicommand(ide_board); -// exit(-1); - } - else if (ide->packetstatus == ATAPI_STATUS_COMPLETE) - { -// pclog("packetstatus==2\n"); - ide->atastat = READY_STAT; - ide->secount=3; - ide_irq_raise(ide); -// if (iomd.irqb.mask&2) output=1; - } - else if (ide->packetstatus == ATAPI_STATUS_DATA) - { - ide->atastat = READY_STAT|DRQ_STAT|(ide->atastat&ERR_STAT); -// rpclog("Recieve data packet 3! %02X\n",ide->atastat); - ide_irq_raise(ide); - ide->packetstatus=0xFF; - } - else if (ide->packetstatus == ATAPI_STATUS_PACKET_REQ) - { - ide->atastat = 0x58 | (ide->atastat & ERR_STAT); -// pclog("Send data packet 4!\n"); - ide_irq_raise(ide); -// ide.packetstatus=5; - ide->pos=2; - } - else if (ide->packetstatus == ATAPI_STATUS_PACKET_RECEIVED) - { -// pclog("Packetstatus 5 !\n"); - atapicommand(ide_board); - } - else if (ide->packetstatus == ATAPI_STATUS_READCD) /*READ CD callback*/ - { - ide->atastat = DRQ_STAT|(ide->atastat&ERR_STAT); -// pclog("Recieve data packet 6!\n"); - ide_irq_raise(ide); -// ide.packetstatus=0xFF; - } - else if (ide->packetstatus == ATAPI_STATUS_REQ_SENSE) /*REQUEST SENSE callback #1*/ - { - // pclog("REQUEST SENSE callback #1: setting status to 0x5A\n"); - ide->atastat = 0x58 | (ide->atastat & ERR_STAT); - ide_irq_raise(ide); - } - else if (ide->packetstatus == ATAPI_STATUS_ERROR) /*Error callback*/ - { -// pclog("Packet 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("Packet check status\n"); - ide->atastat = ERR_STAT; - ide_irq_raise(ide); - } - return; - } + if (ide->packetstatus == ATAPI_STATUS_IDLE) + { + 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) + { + ide->atastat = BUSY_STAT|(ide->atastat&ERR_STAT); + atapicommand(ide_board); + } + else if (ide->packetstatus == ATAPI_STATUS_COMPLETE) + { + ide->atastat = READY_STAT; + ide->secount=3; + ide_irq_raise(ide); + } + else if (ide->packetstatus == ATAPI_STATUS_DATA) + { + 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) + { + ide->atastat = 0x58 | (ide->atastat & ERR_STAT); + ide_irq_raise(ide); + ide->pos=2; + } + else if (ide->packetstatus == ATAPI_STATUS_PACKET_RECEIVED) + { + atapicommand(ide_board); + } + else if (ide->packetstatus == ATAPI_STATUS_READCD) /*READ CD callback*/ + { + ide->atastat = DRQ_STAT|(ide->atastat&ERR_STAT); + ide_irq_raise(ide); + } + else if (ide->packetstatus == ATAPI_STATUS_REQ_SENSE) /*REQUEST SENSE callback #1*/ + { + ide->atastat = 0x58 | (ide->atastat & ERR_STAT); + ide_irq_raise(ide); + } + else if (ide->packetstatus == ATAPI_STATUS_ERROR) /*Error callback*/ + { + 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.*/ + { + ide->atastat = ERR_STAT; + ide_irq_raise(ide); + } + return; + } abort_cmd: ide->command = 0; @@ -1810,36 +1671,30 @@ void ide_callback_qua() } /*ATAPI CD-ROM emulation*/ -void atapi_cmd_error(IDE *ide, uint8_t sensekey, uint8_t asc, uint8_t ascq) -{ - ide->error = (sensekey << 4); - ide->atastat = READY_STAT | ERR_STAT; - ide->secount = (ide->secount & ~7) | 3; - ide->packetstatus = 0x80; - idecallback[ide->board]=50*IDE_TIME; -} - 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)) { - // pclog("Odd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%04x\n", ide->cylinder, command, ide->cylinder - 1); ide->cylinder--; } if (alloc_length < 0) + { fatal("Allocation length < 0\n"); + } if (alloc_length == 0) + { alloc_length = ide->cylinder; + } - // Status: 0x80 (busy), 0x08 (drq), 0x01 (err) - // Interrupt: 0x02 (i_o), 0x01 (c_d) /* No atastat setting: PCem actually emulates the callback cycle. */ ide->secount = 2; @@ -1847,12 +1702,13 @@ void atapi_command_send_init(IDE *ide, uint8_t command, int req_length, int allo ide->pos = 0; if ((ide->cylinder > req_length) || (ide->cylinder == 0)) + { ide->cylinder = req_length; + } if (ide->cylinder > alloc_length) + { ide->cylinder = alloc_length; - - //pclog("atapi_command_send_init(ide, %02X, %04X, %04X)\n", command, req_length, alloc_length); - //pclog("IDE settings: Pos=%08X, Secount=%08X, Cylinder=%08X\n", ide->pos, ide->secount, ide->cylinder); + } } static void atapi_command_ready(int ide_board, int packlen) @@ -1874,6 +1730,68 @@ static void atapi_sense_clear(int command, int ignore_ua) } } +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_ILLEGAL_OPCODE; + 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_OPCODE; + 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_ILLEGAL_OPCODE; + 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_ILLEGAL_OPCODE; + 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]]; @@ -1901,12 +1819,14 @@ static void atapicommand(int ide_board) int real_pos; int track = 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); - #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 msf=idebufferb[1]&2; @@ -1921,8 +1841,8 @@ static void atapicommand(int ide_board) 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. */ + UNIT ATTENTION condition present, as we only use it to mark + disc changes. */ SCSISense.UnitAttention = 0; } @@ -1950,11 +1870,7 @@ static void atapicommand(int ide_board) /* Next it's time for NOT READY. */ if ((SCSICommandTable[idebufferb[0]] & CHECK_READY) && !cdrom->ready()) { - // pclog("Not ready\n"); - atapi_cmd_error(ide, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); - SCSISense.SenseKey = SENSE_NOT_READY; - SCSISense.Asc = ASC_MEDIUM_NOT_PRESENT; - SCSISense.Ascq = 0; + atapi_not_ready(ide); return; } @@ -1973,152 +1889,129 @@ static void atapicommand(int ide_board) switch (idebufferb[0]) { - case GPCMD_TEST_UNIT_READY: - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - break; + 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]; - atapi_command_send_init(ide, temp_command, 18, alloc_length); + case GPCMD_REQUEST_SENSE: /* Used by ROS 4+ */ + alloc_length = idebufferb[4]; + temp_command = idebufferb[0]; + atapi_command_send_init(ide, temp_command, 18, alloc_length); - /*Will return 18 bytes of 0*/ - memset(idebufferb,0,512); + /*Will return 18 bytes of 0*/ + memset(idebufferb,0,512); - idebufferb[0]=0x80|0x70; + idebufferb[0]=0x80|0x70; - if ((SCSISense.SenseKey > 0) && ((cd_status < CD_STATUS_PLAYING) || (cd_status == CD_STATUS_STOPPED))) - { - if (completed) + 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]=ASCQ_AUDIO_PLAY_OPERATION_COMPLETED; + idebufferb[13]=(cd_status == CD_STATUS_PLAYING) ? ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS : ASCQ_AUDIO_PLAY_OPERATION_PAUSED; } else { - idebufferb[2]=SCSISense.SenseKey; - idebufferb[12]=SCSISense.Asc; - idebufferb[13]=SCSISense.Ascq; + if (SCSISense.UnitAttention) + { + idebufferb[2]=SENSE_UNIT_ATTENTION; + idebufferb[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; + idebufferb[13]=0; + } } - } - else if ((SCSISense.SenseKey == 0) && (cd_status >= CD_STATUS_PLAYING) && (cd_status != CD_STATUS_STOPPED)) - { - // pclog("CD-ROM drive is in audio phase\n"); - 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 - { - // pclog("Returning Unit Attention\n"); - if (SCSISense.UnitAttention) + + idebufferb[7]=10; + + atapi_command_ready(ide_board, 18); + + if (idebufferb[2] == SENSE_UNIT_ATTENTION) { - idebufferb[2]=SENSE_UNIT_ATTENTION; - idebufferb[12]=ASC_MEDIUM_MAY_HAVE_CHANGED; - idebufferb[13]=0; + /* If the last remaining sense is unit attention, clear + that condition. */ + SCSISense.UnitAttention = 0; } - } - idebufferb[7]=10; + /* Clear the sense stuff as per the spec. */ + atapi_sense_clear(temp_command, 0); + break; - // pclog("REQUEST SENSE start\n"); - atapi_command_ready(ide_board, 18); - - if (idebufferb[2] == SENSE_UNIT_ATTENTION) - { - /* If the last remaining sense is unit attention, clear - that condition. */ - // pclog("Unit attention cleared"); - SCSISense.UnitAttention = 0; - } - - /* Clear the sense stuff as per the spec. */ - atapi_sense_clear(temp_command, 0); - break; - - case GPCMD_SET_SPEED: - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - 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]; + len=(idebufferb[7]<<16)|(idebufferb[8]<<8)|idebufferb[9]; - if (len == 0) - fatal("Zero allocation length to MECHANISM STATUS not impl.\n"); + if (len == 0) + { + fatal("Zero allocation length to MECHANISM STATUS not impl.\n"); + } - atapi_command_send_init(ide, idebufferb[0], 8, alloc_length); + atapi_command_send_init(ide, idebufferb[0], 8, alloc_length); - idebufferb[0] = 0; - idebufferb[1] = 0; - idebufferb[2] = 0; - idebufferb[3] = 0; - idebufferb[4] = 0; - idebufferb[5] = 1; - idebufferb[6] = 0; - idebufferb[7] = 0; - // len = 8; - - atapi_command_ready(ide_board, 8); - break; - - case GPCMD_READ_TOC_PMA_ATIP: -// pclog("Read TOC ready? %08X\n",ide); - toctimes++; -// if (toctimes==2) output=3; -// pclog("Read TOC %02X\n",idebufferb[9]); - toc_format = idebufferb[2] & 0xf; - if (toc_format == 0) - toc_format = (idebufferb[9]>>6) & 3; - switch (toc_format) - { - case 0: /*Normal*/ - // pclog("ATAPI: READ TOC type requested: Normal\n"); - len=idebufferb[8]+(idebufferb[7]<<8); - len=cdrom->readtoc(idebufferb,idebufferb[6],msf,len,0); - break; - case 1: /*Multi session*/ - // pclog("ATAPI: READ TOC type requested: Multi-session\n"); - len=idebufferb[8]+(idebufferb[7]<<8); - len=cdrom->readtoc_session(idebufferb,msf,len); - idebufferb[0]=0; idebufferb[1]=0xA; - break; - case 2: /*Raw*/ - // pclog("ATAPI: READ TOC type requested: Raw TOC\n"); - len=idebufferb[8]+(idebufferb[7]<<8); - len=cdrom->readtoc_raw(idebufferb,msf,len); - break; - default: - // pclog("ATAPI: Unknown READ TOC type requested: %i\n", (idebufferb[9]>>6)); - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) - ide->error |= MCR_ERR; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - return; -/* pclog("Bad read TOC format\n"); - pclog("Packet data :\n"); - for (c=0;c<12;c++) - pclog("%02X ",idebufferb[c]); - pclog("\n"); - exit(-1);*/ - } -// pclog("ATAPI buffer len %i\n",len); - 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]); - return; + memset(idebufferb, 0, 8); + idebufferb[5] = 1; + + 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]); + return; - case GPCMD_READ_CD: + 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]); + // 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]); @@ -2143,15 +2036,7 @@ static void atapicommand(int ide_board) if (SectorLBA > (cdrom->size() - 1)) { pclog("Trying to read beyond the end of disc\n"); - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) - { - ide->error |= MCR_ERR; - } - SCSISense.Asc = ASC_ILLEGAL_OPCODE; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; + atapi_invalid_field(ide); break; } @@ -2159,28 +2044,22 @@ static void atapicommand(int ide_board) if (!ret) { - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - SCSISense.Asc = ASC_ILLEGAL_OPCODE; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; + atapi_invalid_field(ide); break; -// pclog("Bad flags bits %02X\n",idebufferb[9]); -// exit(-1); } -// pclog("Read at %08X %08X\n",ide.cdpos,ide.cdpos*2048); - -#ifndef RPCEMU_IDE readflash=1; -#endif 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; @@ -2191,772 +2070,665 @@ static void atapicommand(int ide_board) 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; + // 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]); - } - - if (SectorLBA > (cdrom->size() - 1)) - { - pclog("Trying to read beyond the end of disc\n"); - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) - { - ide->error |= MCR_ERR; - } - SCSISense.Asc = ASC_ILLEGAL_OPCODE; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - 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) - { - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - SCSISense.Asc = ASC_ILLEGAL_OPCODE; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - break; -// pclog("Bad flags bits %02X\n",idebufferb[9]); -// exit(-1); - } - -#ifndef RPCEMU_IDE - readflash=1; -#endif - 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; - // for (c=0;catastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - idecallback[ide_board]=50*IDE_TIME; - atapi_cmd_error(ide, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq); - ide->atastat = 0x53; - ide->packetstatus = ATAPI_STATUS_ERROR; - SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_INV_FIELD_IN_CMD_PACKET; - SCSISense.Ascq = 0; - return; - } - - if (temp_command == GPCMD_MODE_SENSE_6) - { - len = SCSICDROMModeSense(idebufferb,4,temp); - idebufferb[0] = len - 1; - idebufferb[1]=3; /*120mm data CD-ROM*/ - } - else - { - len = SCSICDROMModeSense(idebufferb,8,temp); - 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); - 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; - // pclog("Length - %02X%02X\n",idebufferb[0],idebufferb[1]); -// pclog("Page %02X length %02X\n",idebufferb[8],idebufferb[9]); - } - else - { - if (idebufferb[0] == GPCMD_MODE_SELECT_6) + if (idebufferb[0] == GPCMD_READ_6) { - len=idebufferb[4]; - prefix_len = 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 { - len=(idebufferb[7]<<8)|idebufferb[8]; - prefix_len = 10; + 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]); } - page_current = idebufferb[2]; - if (page_flags[page_current] & PAGE_CHANGEABLE) - page_flags[GPMODE_CDROM_AUDIO_PAGE] |= 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; -/* pclog("Waiting for ARM to send packet %i\n",len); - pclog("Packet data :\n"); - for (c=0;c<12;c++) - pclog("%02X ",idebufferb[c]); - pclog("\n");*/ - } - 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) - { - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) - ide->error |= MCR_ERR; - SCSISense.Asc = ASC_INV_FIELD_IN_CMD_PACKET; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - 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; - - atapi_command_send_init(ide, temp_command, len, alloc_length); - - atapi_command_ready(ide_board, len); - } - break; - - case GPCMD_GET_EVENT_STATUS_NOTIFICATION: - temp_command = idebufferb[0]; - alloc_length = len; - { - 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; - unsigned int used_len; - - 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 pollign is supported, asynchronous mode is not. */ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - idecallback[ide_board]=50*IDE_TIME; - atapi_cmd_error(ide, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq); - ide->atastat = 0x53; - ide->packetstatus=0x80; - SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_INV_FIELD_IN_CMD_PACKET; - SCSISense.Ascq = 0; - 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); - } + if (SectorLBA > (cdrom->size() - 1)) + { + // pclog("Trying to read beyond the end of disc\n"); + atapi_invalid_field(ide); + break; + } - atapi_command_send_init(ide, temp_command, len, alloc_length); + 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); - atapi_command_ready(ide_board, len); - break; - - case GPCMD_READ_DISC_INFORMATION: - if (cdrom->read_disc_information) - { - cdrom->read_disc_information(idebufferb); - } - else - { - idebufferb[1] = 32; - idebufferb[2] = 0xe; /* last session complete, disc finalized */ - idebufferb[3] = 1; /* first track on disc */ - idebufferb[4] = 1; /* # of sessions */ - idebufferb[5] = 1; /* first track of last session */ - idebufferb[6] = 1; /* last track of last session */ - idebufferb[7] = 0x20; /* unrestricted use */ - idebufferb[8] = 0x00; /* CD-ROM */ - } - - len=34; - 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_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) { - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - SCSISense.Asc = ASC_INV_FIELD_IN_CMD_PACKET; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - return; - } - - len = idebufferb[0]; - len <<= 8; - len |= idebufferb[1]; - len += 2; - } - else - { - if (((idebufferb[1] & 0x03) != 1) || (track != 1)) - { - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - SCSISense.Asc = ASC_INV_FIELD_IN_CMD_PACKET; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - return; + atapi_invalid_field(ide); + break; } - len = 36; - - idebufferb[0] = 0; - 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[8] = 0; /* track start address is 0 */ - 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 */ - idebufferb[32] = 0; /* track number (MSB) */ - idebufferb[33] = 0; /* session number (MSB) */ - } - - if (len > max_len) - { - len = max_len; - idebufferb[0] = ((max_len - 2) >> 8) & 0xff; - idebufferb[1] = (max_len - 2) & 0xff; - } - - 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)) - { - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_ILLEGAL_MODE_FOR_THIS_TRACK; - SCSISense.Ascq = 0; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - atapi_cmd_error(ide, SCSISense.SenseKey, SCSISense.Asc, SCSISense.Ascq); - 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: - temp=idebufferb[2]&0x40; - if (idebufferb[3]!=1) - { -// pclog("Read subchannel check condition %02X\n",idebufferb[3]); - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) - ide->error |= MCR_ERR; - SCSISense.Asc = ASC_ILLEGAL_OPCODE; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - break; -/* pclog("Bad read subchannel!\n"); - pclog("Packet data :\n"); - for (c=0;c<12;c++) - pclog("%02X\n",idebufferb[c]); - dumpregs(); - exit(-1);*/ - } - pos=0; - idebufferb[pos++]=0; - idebufferb[pos++]=0; /*Audio status*/ - idebufferb[pos++]=0; idebufferb[pos++]=0; /*Subchannel length*/ - idebufferb[pos++]=1; /*Format code*/ - idebufferb[1]=cdrom->getcurrentsubchannel(&idebufferb[5],msf); -// pclog("Read subchannel complete - audio status %02X\n",idebufferb[1]); - len=16; - if (!temp) len=4; - 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) { - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - SCSISense.Asc = ASC_INCOMPATIBLE_FORMAT; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - break; - } else { - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) - ide->error |= MCR_ERR; - SCSISense.Asc = ASC_INV_FIELD_IN_CMD_PACKET; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - 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: - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) - ide->error |= MCR_ERR; - SCSISense.Asc = ASC_INV_FIELD_IN_CMD_PACKET; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - return; - } - break; - - case GPCMD_START_STOP_UNIT: - if (idebufferb[4]!=2 && idebufferb[4]!=3 && idebufferb[4]) - { - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) - ide->error |= MCR_ERR; - SCSISense.Asc = ASC_ILLEGAL_OPCODE; - ide->packetstatus = ATAPI_STATUS_ERROR; - idecallback[ide_board]=50*IDE_TIME; - break; -/* pclog("Bad start/stop unit command\n"); - pclog("Packet data :\n"); - for (c=0;c<12;c++) - pclog("%02X\n",idebufferb[c]); - exit(-1);*/ - } - if (!idebufferb[4]) cdrom->stop(); - else if (idebufferb[4]==2) cdrom->eject(); - else cdrom->load(); - 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) + readflash=1; + SectorLBA++; + SectorLen--; + if (SectorLen >= 0) { - case 0x00: - idebufferb[idx++] = 0x00; - idebufferb[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) + 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) { - atapi_cmd_error(ide, SENSE_ILLEGAL_REQUEST, ASC_DATA_PHASE_ERROR, 0); - SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_DATA_PHASE_ERROR; - 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_cmd_error(ide, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 0); - SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_INV_FIELD_IN_CMD_PACKET; - return; - } - } - else - { - preamble_len = 5; - size_idx = 4; - - idebufferb[0] = 5; /*CD-ROM*/ - idebufferb[1] = 0x80; /*Removable*/ - idebufferb[2] = 0; - idebufferb[3] = 0x21; - idebufferb[4] = 31; - idebufferb[5] = 0; - idebufferb[6] = 0; - idebufferb[7] = 0; - 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; - - 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: - pos=(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); + real_pos = cdrom_LBAtoMSF_accurate(ide); } 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 */ + real_pos = SectorLBA; } - len=8; - atapi_command_ready(ide_board, len); - break; - - // case GPCMD_SEND_DVD_STRUCTURE: - default: - ide->atastat = READY_STAT | ERR_STAT; /*CHECK CONDITION*/ - ide->error = (SENSE_ILLEGAL_REQUEST << 4) | ABRT_ERR; - if (SCSISense.SenseKey == SENSE_UNIT_ATTENTION) - ide->error |= MCR_ERR; - SCSISense.SenseKey = SENSE_ILLEGAL_REQUEST; - SCSISense.Asc = ASC_ILLEGAL_OPCODE; - ide->packetstatus = ATAPI_STATUS_ERROR; - ide->secount = 3; - idecallback[ide_board]=50*IDE_TIME; - break; + 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; + } - case GPCMD_STOP_PLAY_SCAN: - cdrom->stop(); - ide->packetstatus = ATAPI_STATUS_COMPLETE; - idecallback[ide_board]=50*IDE_TIME; - break; -/* default: - pclog("Bad ATAPI command %02X\n",idebufferb[0]); - pclog("Packet data :\n"); - for (c=0;c<12;c++) - pclog("%02X\n",idebufferb[c]); - exit(-1);*/ - } + 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); + idebufferb[0] = len - 1; + idebufferb[1]=3; /*120mm data CD-ROM*/ + } + else + { + len = SCSICDROMModeSense(idebufferb,8,temp); + 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); + 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; + } + 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; + + atapi_command_send_init(ide, temp_command, len, alloc_length); + + atapi_command_ready(ide_board, len); + break; + + case GPCMD_GET_EVENT_STATUS_NOTIFICATION: + temp_command = idebufferb[0]; + alloc_length = len; + { + 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, temp_command, len, alloc_length); + + atapi_command_ready(ide_board, 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; + 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_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; + } + + 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: + temp=idebufferb[2]&0x40; + if (idebufferb[3]!=1) + { + // pclog("Read subchannel check condition %02X\n",idebufferb[3]); + atapi_illegal_opcode(ide); + break; + } + + pos=0; + idebufferb[pos++]=0; + idebufferb[pos++]=0; /*Audio status*/ + idebufferb[pos++]=0; idebufferb[pos++]=0; /*Subchannel length*/ + idebufferb[pos++]=1; /*Format code*/ + idebufferb[1]=cdrom->getcurrentsubchannel(&idebufferb[5],msf); + // pclog("Read subchannel complete - audio status %02X\n",idebufferb[1]); + len=16; + if (!temp) + { + len=4; + } + 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: + if ((idebufferb[4] != 2) && (idebufferb[4] != 3) && idebufferb[4]) + { + atapi_illegal_opcode(ide); + break; + } + if (!idebufferb[4]) + { + cdrom->stop(); + } + else if (idebufferb[4]==2) + { + cdrom->eject(); + } + else + { + cdrom->load(); + } + 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; + + 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: + pos=(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; + } } static void callnonreadcd(IDE *ide) /* Callabck for non-Read CD commands */ @@ -2981,37 +2753,33 @@ static void callnonreadcd(IDE *ide) /* Callabck for non-Read CD commands */ static void callreadcd(IDE *ide) { - int ret; + 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); - ide->atastat = BUSY_STAT; + 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); + ide->atastat = BUSY_STAT; - ret = cdrom_read_data((uint8_t *) ide->buffer); + ret = cdrom_read_data((uint8_t *) ide->buffer); + readflash=1; -#ifndef RPCEMU_IDE - readflash=1; -#endif - - 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; + 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); diff --git a/src/ide.h b/src/ide.h index b61b4b0df..c25fa5ce5 100644 --- a/src/ide.h +++ b/src/ide.h @@ -27,8 +27,8 @@ extern void ide_set_bus_master(int (*read_sector)(int channel, uint8_t *data), i extern int ideboard; -extern int ide34_enable[2]; -extern int ide34_irq[2]; +extern int ide_enable[4]; +extern int ide_irq[4]; extern int idecallback[4]; diff --git a/src/pc.c b/src/pc.c index 3477f95aa..88072edef 100644 --- a/src/pc.c +++ b/src/pc.c @@ -406,12 +406,12 @@ void resetpchard() ide_ter_disable(); ide_qua_disable(); - if (ide34_enable[0]) + if (ide_enable[2]) { ide_ter_init(); } - if (ide34_enable[1]) + if (ide_enable[3]) { ide_qua_init(); } @@ -761,10 +761,10 @@ void loadconfig(char *fn) if (p) strcpy(ide_fn[7], p); else strcpy(ide_fn[7], ""); - ide34_enable[0] = config_get_int(NULL, "ide_ter_enable", 0); - ide34_irq[0] = config_get_int(NULL, "ide_ter_irq", 10); - ide34_enable[1] = config_get_int(NULL, "ide_qua_enable", 0); - ide34_irq[1] = config_get_int(NULL, "ide_qua_irq", 11); + ide_enable[2] = config_get_int(NULL, "ide_ter_enable", 0); + ide_irq[2] = config_get_int(NULL, "ide_ter_irq", 10); + ide_enable[3] = config_get_int(NULL, "ide_qua_enable", 0); + ide_irq[3] = config_get_int(NULL, "ide_qua_irq", 11); fdd_set_type(0, config_get_int(NULL, "drive_a_type", 1)); fdd_set_type(1, config_get_int(NULL, "drive_b_type", 1)); @@ -920,10 +920,10 @@ void saveconfig() config_set_int(NULL, "hdj_cylinders", hdc[7].tracks); config_set_string(NULL, "hdj_fn", ide_fn[7]); - config_set_int(NULL, "ide_ter_enable", ide34_enable[0]); - config_set_int(NULL, "ide_ter_irq", ide34_irq[0]); - config_set_int(NULL, "ide_qua_enable", ide34_enable[1]); - config_set_int(NULL, "ide_qua_irq", ide34_irq[1]); + config_set_int(NULL, "ide_ter_enable", ide_enable[2]); + config_set_int(NULL, "ide_ter_irq", ide_irq[2]); + config_set_int(NULL, "ide_qua_enable", ide_enable[3]); + config_set_int(NULL, "ide_qua_irq", ide_irq[3]); config_set_int(NULL, "drive_a_type", fdd_get_type(0)); config_set_int(NULL, "drive_b_type", fdd_get_type(1)); diff --git a/src/win.c b/src/win.c index 0d2ee69cf..6ae987587 100644 --- a/src/win.c +++ b/src/win.c @@ -627,7 +627,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance, if (scsi_cdrom_enabled) CheckMenuItem(menu, IDM_CDROM_SCSI, MF_CHECKED); - if (ide34_enable[0]) + if (ide_enable[2]) CheckMenuItem(menu, IDM_IDE_TER_ENABLED, MF_CHECKED); CheckMenuItem(menu, IDM_IDE_TER_IRQ9, MF_UNCHECKED); @@ -637,27 +637,27 @@ int WINAPI WinMain (HINSTANCE hThisInstance, CheckMenuItem(menu, IDM_IDE_TER_IRQ14, MF_UNCHECKED); CheckMenuItem(menu, IDM_IDE_TER_IRQ15, MF_UNCHECKED); - if (ide34_irq[0] == 9) + if (ide_irq[2] == 9) { CheckMenuItem(menu, IDM_IDE_TER_IRQ9, MF_CHECKED); } - else if (ide34_irq[0] == 10) + else if (ide_irq[2] == 10) { CheckMenuItem(menu, IDM_IDE_TER_IRQ10, MF_CHECKED); } - else if (ide34_irq[0] == 11) + else if (ide_irq[2] == 11) { CheckMenuItem(menu, IDM_IDE_TER_IRQ11, MF_CHECKED); } - else if (ide34_irq[0] == 12) + else if (ide_irq[2] == 12) { CheckMenuItem(menu, IDM_IDE_TER_IRQ12, MF_CHECKED); } - else if (ide34_irq[0] == 14) + else if (ide_irq[2] == 14) { CheckMenuItem(menu, IDM_IDE_TER_IRQ14, MF_CHECKED); } - else if (ide34_irq[0] == 15) + else if (ide_irq[2] == 15) { CheckMenuItem(menu, IDM_IDE_TER_IRQ15, MF_CHECKED); } @@ -666,7 +666,7 @@ int WINAPI WinMain (HINSTANCE hThisInstance, fatal("Unrecognized tertiary IDE controller IRQ\n"); } - if (ide34_enable[1]) + if (ide_enable[3]) CheckMenuItem(menu, IDM_IDE_QUA_ENABLED, MF_CHECKED); CheckMenuItem(menu, IDM_IDE_QUA_IRQ9, MF_UNCHECKED); @@ -676,27 +676,27 @@ int WINAPI WinMain (HINSTANCE hThisInstance, CheckMenuItem(menu, IDM_IDE_QUA_IRQ14, MF_UNCHECKED); CheckMenuItem(menu, IDM_IDE_QUA_IRQ15, MF_UNCHECKED); - if (ide34_irq[1] == 9) + if (ide_irq[3] == 9) { CheckMenuItem(menu, IDM_IDE_QUA_IRQ9, MF_CHECKED); } - else if (ide34_irq[1] == 10) + else if (ide_irq[3] == 10) { CheckMenuItem(menu, IDM_IDE_QUA_IRQ10, MF_CHECKED); } - else if (ide34_irq[1] == 11) + else if (ide_irq[3] == 11) { CheckMenuItem(menu, IDM_IDE_QUA_IRQ11, MF_CHECKED); } - else if (ide34_irq[1] == 12) + else if (ide_irq[3] == 12) { CheckMenuItem(menu, IDM_IDE_QUA_IRQ12, MF_CHECKED); } - else if (ide34_irq[1] == 14) + else if (ide_irq[3] == 14) { CheckMenuItem(menu, IDM_IDE_QUA_IRQ14, MF_CHECKED); } - else if (ide34_irq[1] == 15) + else if (ide_irq[3] == 15) { CheckMenuItem(menu, IDM_IDE_QUA_IRQ15, MF_CHECKED); } @@ -1142,7 +1142,7 @@ char *floppy_image_extensions = "All floppy images (*.001;*.002;*.003;*.004;*.00 int ide_ter_set_irq(HMENU hmenu, int irq, int id) { - if (ide34_irq[0] == irq) + if (ide_irq[2] == irq) { return 0; } @@ -1152,7 +1152,7 @@ int ide_ter_set_irq(HMENU hmenu, int irq, int id) } pause = 1; Sleep(100); - ide34_irq[0] = irq; + ide_irq[2] = irq; CheckMenuItem(hmenu, IDM_IDE_TER_IRQ9, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_IDE_TER_IRQ10, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_IDE_TER_IRQ11, MF_UNCHECKED); @@ -1168,7 +1168,7 @@ int ide_ter_set_irq(HMENU hmenu, int irq, int id) int ide_qua_set_irq(HMENU hmenu, int irq, int id) { - if (ide34_irq[1] == irq) + if (ide_irq[3] == irq) { return 0; } @@ -1178,7 +1178,7 @@ int ide_qua_set_irq(HMENU hmenu, int irq, int id) } pause = 1; Sleep(100); - ide34_irq[1] = irq; + ide_irq[3] = irq; CheckMenuItem(hmenu, IDM_IDE_QUA_IRQ9, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_IDE_QUA_IRQ10, MF_UNCHECKED); CheckMenuItem(hmenu, IDM_IDE_QUA_IRQ11, MF_UNCHECKED); @@ -1560,35 +1560,35 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM } pause = 1; Sleep(100); - ide34_enable[0] ^= 1; - CheckMenuItem(hmenu, IDM_SCSI_ENABLED, ide34_enable[0] ? MF_CHECKED : MF_UNCHECKED); + ide_enable[2] ^= 1; + CheckMenuItem(hmenu, IDM_IDE_TER_ENABLED, ide_enable[2] ? MF_CHECKED : MF_UNCHECKED); saveconfig(); resetpchard(); pause = 0; break; case IDM_IDE_TER_IRQ9: - ide_ter_set_irq(hmenu, 9, IDM_SCSI_IRQ9); + ide_ter_set_irq(hmenu, 9, IDM_IDE_TER_IRQ9); break; case IDM_IDE_TER_IRQ10: - ide_ter_set_irq(hmenu, 10, IDM_SCSI_IRQ10); + ide_ter_set_irq(hmenu, 10, IDM_IDE_TER_IRQ10); break; case IDM_IDE_TER_IRQ11: - ide_ter_set_irq(hmenu, 11, IDM_SCSI_IRQ11); + ide_ter_set_irq(hmenu, 11, IDM_IDE_TER_IRQ11); break; case IDM_IDE_TER_IRQ12: - ide_ter_set_irq(hmenu, 12, IDM_SCSI_IRQ12); + ide_ter_set_irq(hmenu, 12, IDM_IDE_TER_IRQ12); break; case IDM_IDE_TER_IRQ14: - ide_ter_set_irq(hmenu, 14, IDM_SCSI_IRQ14); + ide_ter_set_irq(hmenu, 14, IDM_IDE_TER_IRQ14); break; case IDM_IDE_TER_IRQ15: - ide_ter_set_irq(hmenu, 15, IDM_SCSI_IRQ15); + ide_ter_set_irq(hmenu, 15, IDM_IDE_TER_IRQ15); break; case IDM_IDE_QUA_ENABLED: @@ -1598,35 +1598,35 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM } pause = 1; Sleep(100); - ide34_enable[1] ^= 1; - CheckMenuItem(hmenu, IDM_SCSI_ENABLED, ide34_enable[1] ? MF_CHECKED : MF_UNCHECKED); + ide_enable[3] ^= 1; + CheckMenuItem(hmenu, IDM_IDE_QUA_ENABLED, ide_enable[3] ? MF_CHECKED : MF_UNCHECKED); saveconfig(); resetpchard(); pause = 0; break; case IDM_IDE_QUA_IRQ9: - ide_qua_set_irq(hmenu, 9, IDM_SCSI_IRQ9); + ide_qua_set_irq(hmenu, 9, IDM_IDE_QUA_IRQ9); break; case IDM_IDE_QUA_IRQ10: - ide_qua_set_irq(hmenu, 10, IDM_SCSI_IRQ10); + ide_qua_set_irq(hmenu, 10, IDM_IDE_QUA_IRQ10); break; case IDM_IDE_QUA_IRQ11: - ide_qua_set_irq(hmenu, 11, IDM_SCSI_IRQ11); + ide_qua_set_irq(hmenu, 11, IDM_IDE_QUA_IRQ11); break; case IDM_IDE_QUA_IRQ12: - ide_qua_set_irq(hmenu, 12, IDM_SCSI_IRQ12); + ide_qua_set_irq(hmenu, 12, IDM_IDE_QUA_IRQ12); break; case IDM_IDE_QUA_IRQ14: - ide_qua_set_irq(hmenu, 14, IDM_SCSI_IRQ14); + ide_qua_set_irq(hmenu, 14, IDM_IDE_QUA_IRQ14); break; case IDM_IDE_QUA_IRQ15: - ide_qua_set_irq(hmenu, 15, IDM_SCSI_IRQ15); + ide_qua_set_irq(hmenu, 15, IDM_IDE_QUA_IRQ15); break; case IDM_SCSI_ENABLED: