diff --git a/src/86box.c b/src/86box.c index b42a15656..bf9be5086 100644 --- a/src/86box.c +++ b/src/86box.c @@ -236,6 +236,9 @@ int efscrnsz_y = SCREEN_RES_Y; static wchar_t mouse_msg[3][200]; +static int do_pause_ack = 0; +static volatile int pause_ack = 0; + #ifndef RELEASE_BUILD static char buff[1024]; static int seen = 0; @@ -1353,6 +1356,15 @@ _ui_window_title(void *s) } #endif +void +ack_pause(void) +{ + if (do_pause_ack) { + do_pause_ack = 0; + pause_ack = 1; + } +} + void pc_run(void) { @@ -1369,6 +1381,7 @@ pc_run(void) /* Run a block of code. */ startblit(); cpu_exec((int32_t) cpu_s->rspeed / 100); + ack_pause(); #ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */ if (gdbstub_step == GDBSTUB_EXEC) { #endif @@ -1562,3 +1575,16 @@ get_actual_size_y(void) { return (efscrnsz_y); } + +void +do_pause(int p) +{ + if (p) + do_pause_ack = p; + dopause = p; + if (p) { + while (!pause_ack) + ; + } + pause_ack = 0; +} diff --git a/src/acpi.c b/src/acpi.c index 723ffcd9c..d4b48e263 100644 --- a/src/acpi.c +++ b/src/acpi.c @@ -1657,7 +1657,7 @@ acpi_reset(void *priv) } /* Power on always generates a resume event. */ - dev->regs.pmsts |= 0x8000; + dev->regs.pmsts |= 0x8100; acpi_rtc_status = 0; diff --git a/src/cdrom/cdrom.c b/src/cdrom/cdrom.c index ff8ca0b30..22cefb991 100644 --- a/src/cdrom/cdrom.c +++ b/src/cdrom/cdrom.c @@ -1112,7 +1112,7 @@ read_toc_session(cdrom_t *dev, unsigned char *b, int msf) b[len++] = 0; /* NEC CDR-260 speaks BCD. */ - if (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.01") || (!strcmp(cdrom_drive_types[dev->type].internal_name, "NEC_CD-ROM_DRIVE260_1.00"))) { /*NEC*/ + if ((dev->type == CDROM_TYPE_NEC_260_100) || (dev->type == CDROM_TYPE_NEC_260_101)) { /*NEC*/ m = ti.m; s = ti.s; f = ti.f; @@ -1374,6 +1374,7 @@ cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, in int m = 0; int s = 0; int f = 0; + uint32_t temp; dev->ops->get_tracks(dev, &first_track, &last_track); @@ -1413,11 +1414,32 @@ cdrom_read_disc_info_toc(cdrom_t *dev, unsigned char *b, unsigned char track, in b[3] = ti.attr; cdrom_log("CD-ROM %i: Returned Toshiba/NEC disc information (type 2) at %02i:%02i.%02i, track=%d, m=%02i,s=%02i,f=%02i, tno=%02x.\n", dev->id, b[0], b[1], b[2], bcd2bin(track), m, s, f, ti.attr); break; - case 3: - b[0] = 0x00; /*TODO: correct it further, mark it as CD-Audio/CD-ROM disc for now*/ - b[1] = 0; - b[2] = 0; - b[3] = 0; + case 3: /*Undocumented on NEC CD-ROM's, from information based on sr_vendor.c from Android's source code*/ + switch (dev->type) { + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: + dev->ops->get_track_info(dev, 1, 0, &ti); + b[0x0e] = 0; + temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + b[0x0f] = temp >> 24; + b[0x10] = temp >> 16; + b[0x11] = temp >> 8; + b[0x12] = temp; + break; + + default: + dev->ops->get_track_info(dev, 1, 0, &ti); + b[0] = 0; + temp = MSFtoLBA(ti.m, ti.s, ti.f) - 150; + b[1] = temp >> 24; + b[2] = temp >> 16; + b[3] = temp >> 8; + break; + } break; default: break; diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 53ed617d2..e5b90d861 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1600,7 +1600,10 @@ piix_init(const device_t *info) dev->port_92 = device_add(&port_92_pci_device); - cpu_set_isa_pci_div(4); + if (cpu_busspeed > 50000000) + cpu_set_isa_pci_div(4); + else + cpu_set_isa_pci_div(3); dma_alias_set(); diff --git a/src/chipset/via_vt82c49x.c b/src/chipset/via_vt82c49x.c index e25fdbfa0..de55f7060 100644 --- a/src/chipset/via_vt82c49x.c +++ b/src/chipset/via_vt82c49x.c @@ -30,6 +30,7 @@ #include <86box/mem.h> #include <86box/smram.h> #include <86box/pic.h> +#include <86box/timer.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/port_92.h> diff --git a/src/config.c b/src/config.c index db9fcb31b..09133c6da 100644 --- a/src/config.c +++ b/src/config.c @@ -876,6 +876,7 @@ load_hard_disks(void) break; case HDD_BUS_SCSI: + case HDD_BUS_ATAPI: max_spt = 255; max_hpc = 255; max_tracks = 266305; @@ -893,6 +894,8 @@ load_hard_disks(void) switch (hdd[c].bus) { case HDD_BUS_IDE: case HDD_BUS_ESDI: + case HDD_BUS_ATAPI: + case HDD_BUS_SCSI: sprintf(tmp2, "1997_5400rpm"); break; default: @@ -925,7 +928,7 @@ load_hard_disks(void) /* IDE */ sprintf(temp, "hdd_%02i_ide_channel", c + 1); - if (hdd[c].bus == HDD_BUS_IDE) { + if ((hdd[c].bus == HDD_BUS_IDE) || (hdd[c].bus == HDD_BUS_ATAPI)) { sprintf(tmp2, "%01u:%01u", c >> 1, c & 1); p = ini_section_get_string(cat, temp, tmp2); sscanf(p, "%01u:%01u", &board, &dev); @@ -2396,7 +2399,7 @@ save_hard_disks(void) ini_section_delete_var(cat, temp); sprintf(temp, "hdd_%02i_ide_channel", c + 1); - if (!hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_IDE)) + if (!hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_IDE) && (hdd[c].bus != HDD_BUS_ATAPI))) ini_section_delete_var(cat, temp); else { sprintf(tmp2, "%01u:%01u", hdd[c].ide_channel >> 1, hdd[c].ide_channel & 1); @@ -2439,7 +2442,8 @@ save_hard_disks(void) ini_section_delete_var(cat, temp); sprintf(temp, "hdd_%02i_speed", c + 1); - if (!hdd_is_valid(c) || (hdd[c].bus != HDD_BUS_IDE && hdd[c].bus != HDD_BUS_ESDI)) + if (!hdd_is_valid(c) || ((hdd[c].bus != HDD_BUS_ESDI) && (hdd[c].bus != HDD_BUS_IDE) && + (hdd[c].bus != HDD_BUS_SCSI) && (hdd[c].bus != HDD_BUS_ATAPI))) ini_section_delete_var(cat, temp); else ini_section_set_string(cat, temp, hdd_preset_get_internal_name(hdd[c].speed_preset)); diff --git a/src/disk/hdc.c b/src/disk/hdc.c index 8df617187..07df9d0e6 100644 --- a/src/disk/hdc.c +++ b/src/disk/hdc.c @@ -24,6 +24,7 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/machine.h> +#include <86box/timer.h> #include <86box/device.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 8cd0d9885..2dffeeec3 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -110,18 +110,7 @@ #define IDE_TIME 10.0 -typedef struct ide_board_t { - int bit32; - int cur_dev; - int irq; - int inited; - int diag; - int force_ata3; - uint16_t base_main; - uint16_t side_main; - pc_timer_t timer; - ide_t *ide[2]; -} ide_board_t; +#define IDE_ATAPI_IS_EARLY ide->sc->pad0 typedef struct ide_bm_t { int (*dma)(uint8_t *data, int transfer_length, int out, void *priv); @@ -129,8 +118,24 @@ typedef struct ide_bm_t { void *priv; } ide_bm_t; -static ide_board_t *ide_boards[4] = { NULL, NULL, NULL, NULL }; -static ide_bm_t *ide_bm[4] = { NULL, NULL, NULL, NULL }; +typedef struct ide_board_t { + uint8_t devctl; + uint8_t pad; + uint16_t base[2]; + int bit32; + int cur_dev; + int irq; + int inited; + int diag; + int force_ata3; + + pc_timer_t timer; + + ide_t *ide[2]; + ide_bm_t *bm; +} ide_board_t; + +ide_board_t *ide_boards[IDE_BUS_MAX]; static uint8_t ide_ter_pnp_rom[] = { 0x09, 0xf8, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, /* BOX0001, serial 0, dummy checksum (filled in by isapnp_add_card) */ @@ -207,7 +212,7 @@ ide_log(const char *fmt, ...) uint8_t getstat(ide_t *ide) { - return ide->atastat; + return ide->tf->atastat; } ide_t * @@ -330,25 +335,39 @@ ide_atapi_get_period(uint8_t channel) return ide_get_xfer_time(ide, 1); } +static void +ide_irq_update(ide_board_t *dev) +{ + ide_t *ide; + uint8_t set; + + if (dev == NULL) + return; + + ide_log("IDE %i: IRQ update (%i)\n", dev->cur_dev >> 1, dev->irq); + + ide = ide_drives[dev->cur_dev]; + set = !(ide_boards[ide->board]->devctl & 2) && ide->irqstat; + + if (!dev->force_ata3 && dev->bm && dev->bm->set_irq) + dev->bm->set_irq(set << 2, dev->bm->priv); + else if (ide_boards[ide->board]->irq != -1) + picint_common(1 << dev->irq, PIC_IRQ_EDGE, set, NULL); +} + void ide_irq_raise(ide_t *ide) { if (!ide_boards[ide->board]) return; - /* ide_log("Raising IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); */ - - ide_log("IDE %i: IRQ raise\n", ide->board); - - if (!(ide->fdisk & 2) && ide->selected) { - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) - ide_bm[ide->board]->set_irq(0x04, ide_bm[ide->board]->priv); - else if (ide_boards[ide->board]->irq != -1) - picint(1 << ide_boards[ide->board]->irq); - } + ide_log("IDE %i: IRQ raise\n", ide->channel); ide->irqstat = 1; ide->service = 1; + + if (ide->selected) + ide_irq_update(ide_boards[ide->board]); } void @@ -357,44 +376,12 @@ ide_irq_lower(ide_t *ide) if (!ide_boards[ide->board]) return; - /* ide_log("Lowering IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); */ - - // ide_log("IDE %i: IRQ lower\n", ide->board); - - if (ide->irqstat && ide->selected) { - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) - ide_bm[ide->board]->set_irq(0x00, ide_bm[ide->board]->priv); - else if (ide_boards[ide->board]->irq != -1) - picintc(1 << ide_boards[ide->board]->irq); - } + ide_log("IDE %i: IRQ lower\n", ide->channel); ide->irqstat = 0; -} -static void -ide_irq_update(ide_t *ide) -{ - if (!ide_boards[ide->board]) - return; - - /* ide_log("Raising IRQ %i (board %i)\n", ide_boards[ide->board]->irq, ide->board); */ - - if (!(ide->fdisk & 2) && ide->irqstat) { - ide_log("IDE %i: IRQ update raise\n", ide->board); - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) { - ide_bm[ide->board]->set_irq(0x00, ide_bm[ide->board]->priv); - ide_bm[ide->board]->set_irq(0x04, ide_bm[ide->board]->priv); - } else if (ide_boards[ide->board]->irq != -1) { - picintc(1 << ide_boards[ide->board]->irq); - picint(1 << ide_boards[ide->board]->irq); - } - } else if ((ide->fdisk & 2) || !ide->irqstat) { - ide_log("IDE %i: IRQ update lower\n", ide->board); - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->set_irq) - ide_bm[ide->board]->set_irq(0x00, ide_bm[ide->board]->priv); - else if (ide_boards[ide->board]->irq != -1) - picintc(1 << ide_boards[ide->board]->irq); - } + if (ide->selected) + ide_irq_update(ide_boards[ide->board]); } /** @@ -443,59 +430,37 @@ ide_padstr8(uint8_t *buf, int buf_size, const char *src) static int ide_get_max(ide_t *ide, int type) { + int ret = -1; + ide_bm_t *bm = ide_boards[ide->board]->bm; + int ata_4 = (!ide_boards[ide->board]->force_ata3 && (bm != NULL)); + int max[2][4] = { { 0, -1, -1, -1 }, { 4, 2, 2, 5 } }; + if (ide->type == IDE_ATAPI) - return ide->get_max(!ide->sc->pad0 && !ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL), type); + ret = ide->get_max(!IDE_ATAPI_IS_EARLY && ata_4, type); + else if (type <= TYPE_UDMA) + ret = max[ata_4][type]; + else + fatal("Unknown transfer type: %i\n", type); - switch (type) { - case TYPE_PIO: /* PIO */ - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 4; - - return 0; /* Maximum PIO 0 for legacy PIO-only drive. */ - case TYPE_SDMA: /* SDMA */ - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 2; - - return -1; - case TYPE_MDMA: /* MDMA */ - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 2; - - return -1; - case TYPE_UDMA: /* UDMA */ - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 5; - - return -1; - default: - fatal("Unknown transfer type: %i\n", type); - return -1; - } + return ret; } static int ide_get_timings(ide_t *ide, int type) { + int ret = 0; + ide_bm_t *bm = ide_boards[ide->board]->bm; + int ata_4 = (!ide_boards[ide->board]->force_ata3 && (bm != NULL)); + int timings[2][3] = { { 0, 0, 0 }, { 120, 120, 0 } }; + if (ide->type == IDE_ATAPI) - return ide->get_timings(!ide->sc->pad0 && !ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL), type); + ret = ide->get_timings(!IDE_ATAPI_IS_EARLY && ata_4, type); + else if (type <= TIMINGS_PIO_FC) + ret = timings[ata_4][type]; + else + fatal("Unknown transfer type: %i\n", type); - switch (type) { - case TIMINGS_DMA: - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 120; - - return 0; - case TIMINGS_PIO: - if (!ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)) - return 120; - - return 0; - case TIMINGS_PIO_FC: - return 0; - default: - fatal("Unknown transfer type: %i\n", type); - return 0; - } + return ret; } /** @@ -505,11 +470,13 @@ static void ide_hd_identify(ide_t *ide) { char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; + ide_bm_t *bm = ide_boards[ide->board]->bm; uint32_t d_hpc; uint32_t d_spt; uint32_t d_tracks; - uint64_t full_size = (((uint64_t) hdd[ide->hdd_num].tracks) * hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + uint64_t full_size = (((uint64_t) hdd[ide->hdd_num].tracks) * + hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); device_identify[6] = (ide->hdd_num / 10) + 0x30; device_identify[7] = (ide->hdd_num % 10) + 0x30; @@ -538,13 +505,20 @@ ide_hd_identify(ide_t *ide) } ide_log("Default CHS translation: %i, %i, %i\n", ide->buffer[1], ide->buffer[3], ide->buffer[6]); - ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ - ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ - ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ - ide->buffer[0] = (1 << 6); /*Fixed drive*/ - ide->buffer[20] = 3; /*Buffer type*/ - ide->buffer[21] = hdd[ide->hdd_num].cache.num_segments * hdd[ide->hdd_num].cache.segment_size; /*Buffer size*/ - ide->buffer[50] = 0x4000; /* Capabilities */ + /* Serial Number */ + ide_padstr((char *) (ide->buffer + 10), "", 20); + /* Firmware */ + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); + /* Model */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); + /* Fixed drive */ + ide->buffer[0] = (1 << 6); + /* Buffer type */ + ide->buffer[20] = 3; + /* Buffer size */ + ide->buffer[21] = hdd[ide->hdd_num].cache.num_segments * hdd[ide->hdd_num].cache.segment_size; + /* Capabilities */ + ide->buffer[50] = 0x4000; ide->buffer[59] = ide->blocksize ? (ide->blocksize | 0x100) : 0; if ((ide->tracks >= 1024) || (ide->hpc > 16) || (ide->spt > 63)) { @@ -556,9 +530,10 @@ ide_hd_identify(ide_t *ide) ide_log("Full size: %" PRIu64 "\n", full_size); /* - Bit 0 = The fields reported in words 54-58 are valid; - Bit 1 = The fields reported in words 64-70 are valid; - Bit 2 = The fields reported in word 88 are valid. */ + Bit 0 = The fields reported in words 54-58 are valid; + Bit 1 = The fields reported in words 64-70 are valid; + Bit 2 = The fields reported in word 88 are valid. + */ ide->buffer[53] = 1; if (ide->cfg_spt != 0) { @@ -577,16 +552,19 @@ ide_hd_identify(ide_t *ide) } } - full_size = ((uint64_t) ide->buffer[54]) * ((uint64_t) ide->buffer[55]) * ((uint64_t) ide->buffer[56]); + full_size = ((uint64_t) ide->buffer[54]) * ((uint64_t) ide->buffer[55]) * + ((uint64_t) ide->buffer[56]); - ide->buffer[57] = full_size & 0xFFFF; /* Total addressable sectors (LBA) */ + /* Total addressable sectors (LBA) */ + ide->buffer[57] = full_size & 0xFFFF; ide->buffer[58] = (full_size >> 16) & 0x0FFF; ide_log("Current CHS translation: %i, %i, %i\n", ide->buffer[54], ide->buffer[55], ide->buffer[56]); } - ide->buffer[47] = hdd[ide->hdd_num].max_multiple_block | 0x8000; /*Max sectors on multiple transfer command*/ - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board]) { + /* Max sectors on multiple transfer command */ + ide->buffer[47] = hdd[ide->hdd_num].max_multiple_block | 0x8000; + if (!ide_boards[ide->board]->force_ata3 && (bm != NULL)) { ide->buffer[80] = 0x7e; /*ATA-1 to ATA-6 supported*/ ide->buffer[81] = 0x19; /*ATA-6 revision 3a supported*/ } else { @@ -604,13 +582,14 @@ ide_identify(ide_t *ide) int max_mdma; int max_udma; const ide_t *ide_other = ide_drives[ide->channel ^ 1]; + ide_bm_t *bm = ide_boards[ide->board]->bm; ide_log("IDE IDENTIFY or IDENTIFY PACKET DEVICE on board %i (channel %i)\n", ide->board, ide->channel); memset(ide->buffer, 0, 512); if (ide->type == IDE_ATAPI) - ide->identify(ide, !ide->sc->pad0 && !ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL)); + ide->identify(ide, !IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && (bm != NULL)); else if (ide->type != IDE_NONE) ide_hd_identify(ide); else { @@ -668,7 +647,8 @@ ide_identify(ide_t *ide) } if ((max_sdma != -1) || (max_mdma != -1) || (max_udma != -1)) { - ide->buffer[49] |= 0x100; /* DMA supported */ + /* DMA supported */ + ide->buffer[49] |= 0x100; ide->buffer[52] = ide_get_timings(ide, TIMINGS_DMA); } @@ -708,9 +688,10 @@ ide_get_sector(ide_t *ide) heads = ide->cfg_hpc; sectors = ide->cfg_spt; - uint8_t sector = ide->sector ? ide->sector : 1; + uint8_t sector = ide->sector ? (ide->sector - 1) : 0; - return ((((off64_t) ide->cylinder * heads) + ide->head) * sectors) + (sector - 1); + return ((((off64_t) ide->tf->cylinder * heads) + (off64_t) ide->head) * sectors) + + (off64_t) sector; } } @@ -724,12 +705,12 @@ ide_next_sector(ide_t *ide) ide->lba_addr++; else { ide->sector++; - if (ide->sector == (ide->cfg_spt + 1)) { + if ((ide->sector == 0) || (ide->sector == (ide->cfg_spt + 1))) { ide->sector = 1; ide->head++; - if (ide->head == ide->cfg_hpc) { + if ((ide->head == 0) || (ide->head == ide->cfg_hpc)) { ide->head = 0; - ide->cylinder++; + ide->tf->cylinder++; } } } @@ -755,23 +736,16 @@ loadhd(ide_t *ide, int d, UNUSED(const char *fn)) void ide_set_signature(ide_t *ide) { + uint16_t ide_signatures[3] = { /* 0xffff */ 0x7f7f, 0x0000, 0xeb14 }; + ide->sector = 1; ide->head = 0; - if (ide->type == IDE_ATAPI) { - ide->sc->phase = 1; - ide->sc->request_length = 0xEB14; - ide->secount = ide->sc->phase; - ide->cylinder = ide->sc->request_length; - } else { - ide->secount = 1; -#if 0 - ide->cylinder = ((ide->type == IDE_HDD) ? 0 : 0xFFFF); -#endif - ide->cylinder = ((ide->type == IDE_HDD) ? 0 : 0x7F7F); - if (ide->type == IDE_HDD) - ide->drive = 0; - } + ide->tf->secount = 1; + ide->tf->cylinder = ide_signatures[ide->type]; + + if (ide->type == IDE_HDD) + ide->drive = 0; } static int @@ -783,10 +757,8 @@ ide_set_features(ide_t *ide) int submode; int max; - features = ide->cylprecomp; - features_data = ide->secount; - - ide_log("Features code %02X\n", features); + features = ide->tf->cylprecomp; + features_data = ide->tf->secount; ide_log("IDE %02X: Set features: %02X, %02X\n", ide->channel, features, features_data); @@ -803,7 +775,8 @@ ide_set_features(ide_t *ide) return 0; max = ide_get_max(ide, TYPE_PIO); ide->mdma_mode = (1 << max); - ide_log("IDE %02X: Setting DPIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + ide_log("IDE %02X: Setting DPIO mode: %02X, %08X\n", ide->channel, + submode, ide->mdma_mode); break; case 0x01: /* PIO mode */ @@ -811,7 +784,8 @@ ide_set_features(ide_t *ide) if (submode > max) return 0; ide->mdma_mode = (1 << submode); - ide_log("IDE %02X: Setting PIO mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + ide_log("IDE %02X: Setting PIO mode: %02X, %08X\n", ide->channel, + submode, ide->mdma_mode); break; case 0x02: /* Singleword DMA mode */ @@ -819,7 +793,8 @@ ide_set_features(ide_t *ide) if (submode > max) return 0; ide->mdma_mode = (1 << submode) | 0x100; - ide_log("IDE %02X: Setting SDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + ide_log("IDE %02X: Setting SDMA mode: %02X, %08X\n", ide->channel, + submode, ide->mdma_mode); break; case 0x04: /* Multiword DMA mode */ @@ -827,7 +802,8 @@ ide_set_features(ide_t *ide) if (submode > max) return 0; ide->mdma_mode = (1 << submode) | 0x200; - ide_log("IDE %02X: Setting MDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + ide_log("IDE %02X: Setting MDMA mode: %02X, %08X\n", ide->channel, + submode, ide->mdma_mode); break; case 0x08: /* Ultra DMA mode */ @@ -835,7 +811,8 @@ ide_set_features(ide_t *ide) if (submode > max) return 0; ide->mdma_mode = (1 << submode) | 0x300; - ide_log("IDE %02X: Setting UDMA mode: %02X, %08X\n", ide->channel, submode, ide->mdma_mode); + ide_log("IDE %02X: Setting UDMA mode: %02X, %08X\n", ide->channel, + submode, ide->mdma_mode); break; default: @@ -870,15 +847,15 @@ ide_set_sector(ide_t *ide, int64_t sector_num) unsigned int cyl; unsigned int r; if (ide->lba) { - ide->head = (sector_num >> 24); - ide->cylinder = (sector_num >> 8); - ide->sector = sector_num; + ide->head = (sector_num >> 24) & 0xff; + ide->tf->cylinder = (sector_num >> 8) & 0xffff; + ide->sector = sector_num & 0xff; } else { - cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); - r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); - ide->cylinder = cyl; - ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f); - ide->sector = (r % hdd[ide->hdd_num].spt) + 1; + cyl = sector_num / (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + r = sector_num % (hdd[ide->hdd_num].hpc * hdd[ide->hdd_num].spt); + ide->tf->cylinder = cyl & 0xffff; + ide->head = ((r / hdd[ide->hdd_num].spt) & 0x0f) & 0xff; + ide->sector = ((r % hdd[ide->hdd_num].spt) + 1) & 0xff; } } @@ -886,14 +863,16 @@ static void ide_zero(int d) { ide_t *dev; + if (ide_drives[d] == NULL) - ide_drives[d] = (ide_t *) malloc(sizeof(ide_t)); - memset(ide_drives[d], 0, sizeof(ide_t)); + ide_drives[d] = (ide_t *) calloc(1, sizeof(ide_t)); + dev = ide_drives[d]; + dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); dev->channel = d; dev->type = IDE_NONE; dev->hdd_num = -1; - dev->atastat = DRDY_STAT | DSC_STAT; + dev->tf->atastat = DRDY_STAT | DSC_STAT; dev->service = 0; dev->board = d >> 1; dev->selected = !(d & 1); @@ -905,31 +884,31 @@ void ide_allocate_buffer(ide_t *dev) { if (dev->buffer == NULL) - dev->buffer = (uint16_t *) malloc(65536 * sizeof(uint16_t)); - memset(dev->buffer, 0, 65536 * sizeof(uint16_t)); + dev->buffer = (uint16_t *) calloc(1, 65536 * sizeof(uint16_t)); } void ide_atapi_attach(ide_t *ide) { + ide_bm_t *bm = ide_boards[ide->board]->bm; + if (ide->type != IDE_NONE) return; ide->type = IDE_ATAPI; ide_allocate_buffer(ide); ide_set_signature(ide); - ide->mdma_mode = (1 << ide->get_max(!ide->sc->pad0 && !ide_boards[ide->board]->force_ata3 && (ide_bm[ide->board] != NULL), TYPE_PIO)); - ide->error = 1; + ide->mdma_mode = (1 << ide->get_max(!IDE_ATAPI_IS_EARLY && + !ide_boards[ide->board]->force_ata3 && (bm != NULL), TYPE_PIO)); + ide->tf->error = 1; ide->cfg_spt = ide->cfg_hpc = 0; -#ifndef EARLY_ATAPI - ide->sc->status = 0; -#endif + if (!IDE_ATAPI_IS_EARLY) + ide->tf->atastat = 0; } void ide_set_callback(ide_t *ide, double callback) { - if (!ide) { ide_log("ide_set_callback(NULL): Set callback failed\n"); return; @@ -964,9 +943,9 @@ ide_set_board_callback(uint8_t board, double callback) static void ide_atapi_command_bus(ide_t *ide) { - ide->sc->status = BUSY_STAT; - ide->sc->phase = 1; - ide->sc->pos = 0; + ide->tf->atastat = BUSY_STAT; + ide->tf->phase = 1; + ide->tf->pos = 0; ide->sc->callback = 1.0 * IDE_TIME; ide_set_callback(ide, ide->sc->callback); } @@ -976,90 +955,85 @@ ide_atapi_callback(ide_t *ide) { int out; int ret = 0; + ide_bm_t *bm = ide_boards[ide->board]->bm; +#ifdef ENABLE_IDE_LOG + char *phases[7] = { "Idle", "Command", "Data in", "Data out", "Data in DMA", "Data out DMA", + "Complete" }; + char *phase; + + if (ide->sc->packet_status <= PHASE_COMPLETE) + phase = phases[ide->sc->packet_status]; + else if (ide->sc->packet_status == PHASE_ERROR) + phase = "Error"; + else if (ide->sc->packet_status == PHASE_NONE) + phase = "None"; + else + phase = "Unknown"; + + ide_log("Phase: %02X (%s)\n", ide->sc->packet_status, phase); +#endif switch (ide->sc->packet_status) { + default: + break; + case PHASE_IDLE: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_IDLE\n"); -#endif - ide->sc->pos = 0; - ide->sc->phase = 1; - ide->sc->status = READY_STAT | DRQ_STAT | (ide->sc->status & ERR_STAT); - return; + ide->tf->pos = 0; + ide->tf->phase = 1; + ide->tf->atastat = READY_STAT | DRQ_STAT | (ide->tf->atastat & ERR_STAT); + break; case PHASE_COMMAND: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_COMMAND\n"); -#endif - ide->sc->status = BUSY_STAT | (ide->sc->status & ERR_STAT); + ide->tf->atastat = BUSY_STAT | (ide->tf->atastat & ERR_STAT); if (ide->packet_command) { ide->packet_command(ide->sc, ide->sc->atapi_cdb); if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) ide_atapi_callback(ide); } - return; + break; case PHASE_COMPLETE: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_COMPLETE\n"); -#endif - ide->sc->status = READY_STAT; - ide->sc->phase = 3; + case PHASE_ERROR: + ide->tf->atastat = READY_STAT; + if (ide->sc->packet_status == PHASE_ERROR) + ide->tf->atastat |= ERR_STAT; + ide->tf->phase = 3; ide->sc->packet_status = PHASE_NONE; ide_irq_raise(ide); - return; + break; case PHASE_DATA_IN: case PHASE_DATA_OUT: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_DATA_IN or PHASE_DATA_OUT\n"); -#endif - ide->sc->status = READY_STAT | DRQ_STAT | (ide->sc->status & ERR_STAT); - ide->sc->phase = !(ide->sc->packet_status & 0x01) << 1; + ide->tf->atastat = READY_STAT | DRQ_STAT | (ide->tf->atastat & ERR_STAT); + ide->tf->phase = !(ide->sc->packet_status & 0x01) << 1; ide_irq_raise(ide); - return; + break; case PHASE_DATA_IN_DMA: case PHASE_DATA_OUT_DMA: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_DATA_IN_DMA or PHASE_DATA_OUT_DMA\n"); -#endif out = (ide->sc->packet_status & 0x01); - if (!ide->sc->pad0 && !ide_boards[ide->board]->force_ata3 && - ide_bm[ide->board] && ide_bm[ide->board]->dma) { - ret = ide_bm[ide->board]->dma(ide->sc->temp_buffer, ide->sc->packet_len, - out, ide_bm[ide->board]->priv); - } else { - /* DMA command without a bus master. */ - if (ide->bus_master_error) - ide->bus_master_error(ide->sc); - return; + if (!IDE_ATAPI_IS_EARLY && !ide_boards[ide->board]->force_ata3 && + (bm != NULL) && bm->dma) { + ret = bm->dma(ide->sc->temp_buffer, ide->sc->packet_len, out, bm->priv); } + /* Else, DMA command without a bus master, ret = 0 (default). */ - if (ret == 0) { - if (ide->bus_master_error) - ide->bus_master_error(ide->sc); - } else if (ret == 1) { - if (out && ide->phase_data_out) - ret = ide->phase_data_out(ide->sc); - else if (!out && ide->command_stop) - ide->command_stop(ide->sc); + switch (ret) { + case 0: + if (ide->bus_master_error) + ide->bus_master_error(ide->sc); + break; + case 1: + if (out && ide->phase_data_out) + ret = ide->phase_data_out(ide->sc); + else if (!out && ide->command_stop) + ide->command_stop(ide->sc); - if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) - ide_atapi_callback(ide); - } else if (ret == 2) - ide_atapi_command_bus(ide); - - return; - case PHASE_ERROR: -#ifdef ENABLE_IDE_LOG - ide_log("PHASE_ERROR\n"); -#endif - ide->sc->status = READY_STAT | ERR_STAT; - ide->sc->phase = 3; - ide->sc->packet_status = PHASE_NONE; - ide_irq_raise(ide); - return; - default: - ide_log("PHASE_UNKNOWN %02X\n", ide->sc->packet_status); - return; + if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) + ide_atapi_callback(ide); + break; + case 2: + ide_atapi_command_bus(ide); + break; + } + break; } } @@ -1071,12 +1045,12 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) ide_irq_lower(ide); - dev->status = BSY_STAT; + ide->tf->atastat = BSY_STAT; - if (dev->pos >= dev->packet_len) { - ide_log("%i bytes %s, command done\n", dev->pos, out ? "written" : "read"); + if (ide->tf->pos >= dev->packet_len) { + ide_log("%i bytes %s, command done\n", ide->tf->pos, out ? "written" : "read"); - dev->pos = dev->request_pos = 0; + ide->tf->pos = dev->request_pos = 0; if (out && ide->phase_data_out) ide->phase_data_out(dev); else if (!out && ide->command_stop) @@ -1085,23 +1059,23 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) if ((ide->sc->packet_status == PHASE_COMPLETE) && (ide->sc->callback == 0.0)) ide_atapi_callback(ide); } else { - ide_log("%i bytes %s, %i bytes are still left\n", dev->pos, - out ? "written" : "read", dev->packet_len - dev->pos); + ide_log("%i bytes %s, %i bytes are still left\n", ide->tf->pos, + out ? "written" : "read", dev->packet_len - ide->tf->pos); /* If less than (packet length) bytes are remaining, update packet length accordingly. */ - if ((dev->packet_len - dev->pos) < (dev->max_transfer_len)) { - dev->max_transfer_len = dev->packet_len - dev->pos; + if ((dev->packet_len - ide->tf->pos) < (dev->max_transfer_len)) { + dev->max_transfer_len = dev->packet_len - ide->tf->pos; /* Also update the request length so the host knows how many bytes to transfer. */ - dev->request_length = dev->max_transfer_len; + ide->tf->request_length = dev->max_transfer_len; } ide_log("CD-ROM %i: Packet length %i, request length %i\n", dev->id, dev->packet_len, dev->max_transfer_len); dev->packet_status = PHASE_DATA_IN | out; - dev->status = BSY_STAT; - dev->phase = 1; + ide->tf->atastat = BSY_STAT; + ide->tf->phase = 1; ide_atapi_callback(ide); ide_set_callback(ide, 0.0); @@ -1109,169 +1083,122 @@ ide_atapi_pio_request(ide_t *ide, uint8_t out) } } -static uint32_t +static uint16_t ide_atapi_packet_read(ide_t *ide, int length) { scsi_common_t *dev = ide->sc; - const uint16_t *bufferw; - const uint32_t *bufferl; + uint16_t ret = 0; - uint32_t temp = 0; + if (dev && dev->temp_buffer && (dev->packet_status == PHASE_DATA_IN)) { + ide_log("PHASE_DATA_IN read: %i, %i, %i, %i\n", + dev->request_pos, dev->max_transfer_len, ide->tf->pos, dev->packet_len); - if (!dev || !dev->temp_buffer || (dev->packet_status != PHASE_DATA_IN)) - return 0; + bufferw = (uint16_t *) dev->temp_buffer; - if (dev->packet_status == PHASE_DATA_IN) - ide_log("PHASE_DATA_IN read: %i, %i, %i, %i\n", dev->request_pos, dev->max_transfer_len, dev->pos, dev->packet_len); - - bufferw = (uint16_t *) dev->temp_buffer; - bufferl = (uint32_t *) dev->temp_buffer; - - /* Make sure we return a 0 and don't attempt to read from the buffer if we're transferring bytes beyond it, - which can happen when issuing media access commands with an allocated length below minimum request length - (which is 1 sector = 2048 bytes). */ - switch (length) { - case 1: - temp = (dev->pos < dev->packet_len) ? dev->temp_buffer[dev->pos] : 0; - dev->pos++; - dev->request_pos++; - break; - case 2: - temp = (dev->pos < dev->packet_len) ? bufferw[dev->pos >> 1] : 0; - dev->pos += 2; + /* Make sure we return a 0 and don't attempt to read from the buffer if + we're transferring bytes beyond it, which can happen when issuing media + access commands with an allocated length below minimum request length + (which is 1 sector = 2048 bytes). */ + if (length == 2) { + ret = (ide->tf->pos < dev->packet_len) ? bufferw[ide->tf->pos >> 1] : 0; + ide->tf->pos += 2; dev->request_pos += 2; - break; - case 4: - temp = (dev->pos < dev->packet_len) ? bufferl[dev->pos >> 2] : 0; - dev->pos += 4; - dev->request_pos += 4; - break; - default: - return 0; - } + } else { + ret = (ide->tf->pos < dev->packet_len) ? dev->temp_buffer[ide->tf->pos] : 0; + ide->tf->pos++; + dev->request_pos++; + } - if (dev->packet_status == PHASE_DATA_IN) { - if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { + if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) { /* Time for a DRQ. */ ide_atapi_pio_request(ide, 0); } - return temp; - } else - return 0; + } + + return ret; } static void -ide_atapi_packet_write(ide_t *ide, uint32_t val, int length) +ide_atapi_packet_write(ide_t *ide, uint16_t val, int length) { scsi_common_t *dev = ide->sc; - uint8_t *bufferb; - uint16_t *bufferw; - uint32_t *bufferl; + uint8_t *bufferb = NULL; + uint16_t *bufferw = NULL; - if (!dev) - return; - - if (dev->packet_status == PHASE_IDLE) - bufferb = dev->atapi_cdb; - else { - if (dev->temp_buffer) + if (dev) { + if (dev->packet_status == PHASE_IDLE) + bufferb = dev->atapi_cdb; + else if (dev->temp_buffer) bufferb = dev->temp_buffer; - else - return; + + bufferw = (uint16_t *) bufferb; } - bufferw = (uint16_t *) bufferb; - bufferl = (uint32_t *) bufferb; - - if (dev->packet_status == PHASE_DATA_IN) - return; - - switch (length) { - case 1: - bufferb[dev->pos] = val & 0xff; - dev->pos++; - dev->request_pos++; - break; - case 2: - bufferw[dev->pos >> 1] = val & 0xffff; - dev->pos += 2; + if ((bufferb != NULL) && (dev->packet_status != PHASE_DATA_IN)) { + if (length == 2) { + bufferw[ide->tf->pos >> 1] = val & 0xffff; + ide->tf->pos += 2; dev->request_pos += 2; - break; - case 4: - bufferl[dev->pos >> 2] = val; - dev->pos += 4; - dev->request_pos += 4; - break; - default: - return; - } + } else { + bufferb[ide->tf->pos] = val & 0xff; + ide->tf->pos++; + dev->request_pos++; + } - if (dev->packet_status == PHASE_DATA_OUT) { - if ((dev->request_pos >= dev->max_transfer_len) || (dev->pos >= dev->packet_len)) { - /* Time for a DRQ. */ - ide_atapi_pio_request(ide, 1); + if (dev->packet_status == PHASE_DATA_OUT) { + if ((dev->request_pos >= dev->max_transfer_len) || (ide->tf->pos >= dev->packet_len)) { + /* Time for a DRQ. */ + ide_atapi_pio_request(ide, 1); + } + } else if (dev->packet_status == PHASE_IDLE) { + if (ide->tf->pos >= 12) { + ide->tf->pos = 0; + ide->tf->atastat = BSY_STAT; + dev->packet_status = PHASE_COMMAND; + ide_atapi_callback(ide); + } } - return; - } else if (dev->packet_status == PHASE_IDLE) { - if (dev->pos >= 12) { - dev->pos = 0; - dev->status = BSY_STAT; - dev->packet_status = PHASE_COMMAND; - ide_atapi_callback(ide); - } - return; } } -void -ide_write_data(ide_t *ide, uint32_t val, int length) +static void +ide_write_data(ide_t *ide, uint16_t val, int length) { uint8_t *idebufferb = (uint8_t *) ide->buffer; uint16_t *idebufferw = ide->buffer; - uint32_t *idebufferl = (uint32_t *) ide->buffer; if (ide->command == WIN_PACKETCMD) { - ide->pos = 0; - if (ide->type == IDE_ATAPI) ide_atapi_packet_write(ide, val, length); + else + ide->tf->pos = 0; } else { - switch (length) { - case 1: - idebufferb[ide->pos] = val & 0xff; - ide->pos++; - break; - case 2: - idebufferw[ide->pos >> 1] = val & 0xffff; - ide->pos += 2; - break; - case 4: - idebufferl[ide->pos >> 2] = val; - ide->pos += 4; - break; - default: - return; + if (length == 2) { + idebufferw[ide->tf->pos >> 1] = val & 0xffff; + ide->tf->pos += 2; + } else { + idebufferb[ide->tf->pos] = val & 0xff; + ide->tf->pos++; } - if (ide->pos >= 512) { - ide->pos = 0; - ide->atastat = BSY_STAT; + if (ide->tf->pos >= 512) { + ide->tf->pos = 0; + ide->tf->atastat = BSY_STAT; double seek_time = hdd_timing_write(&hdd[ide->hdd_num], ide_get_sector(ide), 1); double xfer_time = ide_get_xfer_time(ide, 512); double wait_time = seek_time + xfer_time; if (ide->command == WIN_WRITE_MULTIPLE) { - if ((ide->blockcount + 1) >= ide->blocksize || ide->secount == 1) { + if ((ide->blockcount + 1) >= ide->blocksize || ide->tf->secount == 1) { ide_set_callback(ide, seek_time + xfer_time + ide->pending_delay); ide->pending_delay = 0; } else { ide->pending_delay += wait_time; ide_callback(ide); } - } else { + } else ide_set_callback(ide, wait_time); - } } } } @@ -1287,7 +1214,7 @@ ide_writew(uint16_t addr, uint16_t val, void *priv) ch = dev->cur_dev; ide = ide_drives[ch]; - ide_log("ide_writew %04X %04X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); + ide_log("ide_writew(%04X, %04X, %08X)\n", addr, val, priv); addr &= 0x7; @@ -1319,7 +1246,7 @@ ide_writel(uint16_t addr, uint32_t val, void *priv) ch = dev->cur_dev; ide = ide_drives[ch]; - ide_log("ide_writel %04X %08X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); + ide_log("ide_writel(%04X, %08X, %08X)\n", addr, val, priv); addr &= 0x7; @@ -1368,14 +1295,14 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) ide = ide_drives[ch]; ide_other = ide_drives[ch ^ 1]; - ide_log("ide_write_devctl %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); + ide_log("ide_write_devctl(%04X, %02X, %08X)\n", addr, val, priv); if ((ide->type == IDE_NONE) && (ide_other->type == IDE_NONE)) return; dev->diag = 0; - if ((val & 4) && !(ide->fdisk & 4)) { + if ((val & 4) && !(dev->devctl & 4)) { /* Reset toggled from 0 to 1, initiate reset procedure. */ if (ide->type == IDE_ATAPI) ide->sc->callback = 0.0; @@ -1386,44 +1313,28 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) some 286 and 386 machines error out. */ if (!(ch & 1)) { if (ide->type != IDE_NONE) { - ide->atastat = BSY_STAT; - ide->error = 1; - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; - ide->sc->error = 1; - } + ide->tf->atastat = BSY_STAT; + ide->tf->error = 1; } if (ide_other->type != IDE_NONE) { - ide_other->atastat = BSY_STAT; - ide_other->error = 1; - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->status = BSY_STAT; - ide_other->sc->error = 1; - } + ide_other->tf->atastat = BSY_STAT; + ide_other->tf->error = 1; } } - } else if (!(val & 4) && (ide->fdisk & 4)) { + } else if (!(val & 4) && (dev->devctl & 4)) { /* Reset toggled from 1 to 0. */ if (!(ch & 1)) { /* Currently active device is 0, use the device 0 reset protocol. */ /* Device 0. */ dev_reset(ide); - ide->atastat = BSY_STAT; - ide->error = 1; - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; - ide->sc->error = 1; - } + ide->tf->atastat = BSY_STAT; + ide->tf->error = 1; /* Device 1. */ dev_reset(ide_other); - ide_other->atastat = BSY_STAT; - ide_other->error = 1; - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->status = BSY_STAT; - ide_other->sc->error = 1; - } + ide_other->tf->atastat = BSY_STAT; + ide_other->tf->error = 1; /* Fire the timer. */ dev->diag = 0; @@ -1434,12 +1345,8 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) } else { /* Currently active device is 1, simply reset the status and the active device. */ dev_reset(ide); - ide->atastat = DRDY_STAT | DSC_STAT; - ide->error = 1; - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | DSC_STAT; - ide->sc->error = 1; - } + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide->tf->error = 1; dev->cur_dev &= ~1; ch = dev->cur_dev; @@ -1451,111 +1358,114 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) } } - old = ide->fdisk; - ide->fdisk = ide_other->fdisk = val; - if (!(val & 0x02) && (old & 0x02) && ide->irqstat) - ide_irq_update(ide); + old = dev->devctl; + dev->devctl = val; + if (!(val & 0x02) && (old & 0x02)) + ide_irq_update(ide_boards[ide->board]); +} + +static void +ide_reset_registers(ide_t *ide) +{ + uint16_t ide_signatures[3] = { /* 0xffff */ 0x7f7f, 0x0000, 0xeb14 }; + + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide->tf->error = 1; + ide->tf->secount = 1; + ide->tf->cylinder = ide_signatures[ide->type]; + + ide->sector = 1; + ide->head = 0; + ide->reset = 0; + + if (ide->type == IDE_ATAPI) + ide->sc->callback = 0.0; + + ide_set_callback(ide, 0.0); } void ide_writeb(uint16_t addr, uint8_t val, void *priv) { ide_board_t *dev = (ide_board_t *) priv; - ide_t *ide; ide_t *ide_other; int ch; + int absent = 0; + int bad = 0; + int reset = 0; ch = dev->cur_dev; ide = ide_drives[ch]; ide_other = ide_drives[ch ^ 1]; - ide_log("ide_write %04X %02X from %04X(%08X):%08X\n", addr, val, CS, cs, cpu_state.pc); + /* Absent and is master or both are absent. */ + if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1))) + absent = 1; + /* Absent and is slave and master is present. */ + else if ((ide->type == IDE_NONE) && (ch & 1)) + absent = 2; + + ide_log("ide_writeb(%04X, %02X, %08X)\n", addr, val, priv); addr &= 0x7; - if ((ide->type == IDE_NONE) && ((addr == 0x0) || (addr == 0x7))) - return; - - switch (addr) { + if ((absent != 1) || ((addr != 0x0) && (addr != 0x7))) switch (addr) { case 0x0: /* Data */ - ide_write_data(ide, val | (val << 8), 2); - return; + if (absent == 0) + ide_write_data(ide, val | (val << 8), 2); + break; /* Note to self: for ATAPI, bit 0 of this is DMA if set, PIO if clear. */ case 0x1: /* Features */ - if (ide->type == IDE_ATAPI) { + ide->tf->cylprecomp = val; + if (ide->type == IDE_ATAPI) ide_log("ATAPI transfer mode: %s\n", (val & 1) ? "DMA" : "PIO"); - ide->sc->features = val; - } - ide->cylprecomp = val; /* The ATA-3 specification says this register is the parameter for the command and is unclear as to whether or not it's written to both devices at once. Writing it to both devices at once breaks CD boot on the AMI Apollo. */ #ifdef WRITE_PARAM_TO_BOTH_DEVICES - if (ide_other->type == IDE_ATAPI) - ide_other->sc->features = val; - ide_other->cylprecomp = val; + ide_other->tf->cylprecomp = val; #endif return; case 0x2: /* Sector count */ - if (ide->type == IDE_ATAPI) { - ide_log("Sector count write: %i\n", val); - ide->sc->phase = val; - } - ide->secount = val; - - if (ide_other->type == IDE_ATAPI) { - ide_log("Other sector count write: %i\n", val); - ide_other->sc->phase = val; - } - ide_other->secount = val; - return; + ide->tf->secount = val; + ide_other->tf->secount = val; + break; case 0x3: /* Sector */ ide->sector = val; - ide->lba_addr = (ide->lba_addr & 0xFFFFF00) | 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_other->lba_addr = (ide_other->lba_addr & 0xfffff00) | val; + break; case 0x4: /* Cylinder low */ - if (ide->type == IDE_ATAPI) { - ide->sc->request_length &= 0xFF00; - ide->sc->request_length |= val; - } - ide->cylinder = (ide->cylinder & 0xFF00) | val; - ide->lba_addr = (ide->lba_addr & 0xFFF00FF) | (val << 8); + ide->tf->cylinder = (ide->tf->cylinder & 0xff00) | val; + ide->lba_addr = (ide->lba_addr & 0xfff00ff) | (val << 8); - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->request_length &= 0xFF00; - ide_other->sc->request_length |= val; - } - ide_other->cylinder = (ide_other->cylinder & 0xFF00) | val; - ide_other->lba_addr = (ide_other->lba_addr & 0xFFF00FF) | (val << 8); - return; + ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff00) | val; + ide_other->lba_addr = (ide_other->lba_addr & 0xfff00ff) | (val << 8); + break; case 0x5: /* Cylinder high */ - if (ide->type == IDE_ATAPI) { - ide->sc->request_length &= 0xFF; - ide->sc->request_length |= (val << 8); - } - ide->cylinder = (ide->cylinder & 0xFF) | (val << 8); - ide->lba_addr = (ide->lba_addr & 0xF00FFFF) | (val << 16); + ide->tf->cylinder = (ide->tf->cylinder & 0xff) | (val << 8); + ide->lba_addr = (ide->lba_addr & 0xf00ffff) | (val << 16); - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->request_length &= 0xFF; - ide_other->sc->request_length |= (val << 8); - } - ide_other->cylinder = (ide_other->cylinder & 0xFF) | (val << 8); - ide_other->lba_addr = (ide_other->lba_addr & 0xF00FFFF) | (val << 16); - return; + ide_other->tf->cylinder = (ide_other->tf->cylinder & 0xff) | (val << 8); + ide_other->lba_addr = (ide_other->lba_addr & 0xf00ffff) | (val << 16); + break; case 0x6: /* Drive/Head */ if (ch != ((val >> 4) & 1) + (ide->board << 1)) { + if (!ide->reset && !ide_other->reset && ide->irqstat) { + ide_irq_lower(ide); + ide->irqstat = 1; + } + ide_boards[ide->board]->cur_dev = ((val >> 4) & 1) + (ide->board << 1); ch = ide_boards[ide->board]->cur_dev; @@ -1566,87 +1476,60 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide_other->selected = 0; if (ide->reset || ide_other->reset) { - ide->atastat = ide_other->atastat = DRDY_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_reset_registers(ide); + ide_reset_registers(ide_other); - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | DSC_STAT; - ide->sc->error = 1; - ide->sc->phase = 1; - ide->sc->request_length = 0xEB14; - ide->sc->callback = 0.0; - ide->cylinder = 0xEB14; - } - - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->status = DRDY_STAT | DSC_STAT; - ide_other->sc->error = 1; - ide_other->sc->phase = 1; - ide_other->sc->request_length = 0xEB14; - ide_other->sc->callback = 0.0; - ide_other->cylinder = 0xEB14; - } - - ide_set_callback(ide, 0.0); - ide_set_callback(ide_other, 0.0); ide_set_board_callback(ide->board, 0.0); - return; - } + reset = 1; + } else + ide_irq_update(ide_boards[ide->board]); } - ide->head = val & 0xF; - ide->lba = val & 0x40; - ide_other->head = val & 0xF; - ide_other->lba = val & 0x40; + if (!reset) { + ide->head = ide_other->head = val & 0xF; + ide->lba = 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_irq_update(ide); - return; + ide->lba_addr = (ide->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); + ide_other->lba_addr = (ide_other->lba_addr & 0x0FFFFFF) | ((val & 0xF) << 24); + } + break; case 0x7: /* Command register */ - if (ide->type == IDE_NONE) - return; + if (absent != 0) + break; ide_irq_lower(ide); ide->command = val; - ide->error = 0; - if (ide->type == IDE_ATAPI) - ide->sc->error = 0; - - if (((val >= WIN_RECAL) && (val <= 0x1F)) || ((val >= WIN_SEEK) && (val <= 0x7F))) { - if (ide->type == IDE_ATAPI) - ide->sc->status = DRDY_STAT; - else - ide->atastat = READY_STAT | BSY_STAT; - - if (ide->type == IDE_ATAPI) { - ide->sc->callback = 100.0 * IDE_TIME; - ide_set_callback(ide, 100.0 * IDE_TIME); - } else { - double seek_time = hdd_seek_get_time(&hdd[ide->hdd_num], ide_get_sector(ide), HDD_OP_SEEK, 0, 0.0); - ide_set_callback(ide, seek_time); - } - return; - } + ide->tf->error = 0; switch (val) { + case WIN_RECAL ... 0x1F: + case WIN_SEEK ... 0x7F: + if (ide->type == IDE_ATAPI) + ide->tf->atastat = DRDY_STAT; + else + ide->tf->atastat = READY_STAT | BSY_STAT; + + if (ide->type == IDE_ATAPI) { + ide->sc->callback = 100.0 * IDE_TIME; + ide_set_callback(ide, 100.0 * IDE_TIME); + } else { + double seek_time = hdd_seek_get_time(&hdd[ide->hdd_num], (val & 0x60) ? + ide_get_sector(ide) : 0, HDD_OP_SEEK, 0, 0.0); + ide_set_callback(ide, seek_time); + } + break; + case WIN_SRST: /* ATAPI Device Reset */ if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; + ide->tf->atastat = BSY_STAT; ide->sc->callback = 100.0 * IDE_TIME; } else - ide->atastat = DRDY_STAT; + ide->tf->atastat = DRDY_STAT; ide_set_callback(ide, 100.0 * IDE_TIME); - return; + break; case WIN_READ_MULTIPLE: /* Fatal removed in accordance with the official ATAPI reference: @@ -1661,34 +1544,36 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) case WIN_READ_NORETRY: case WIN_READ_DMA: case WIN_READ_DMA_ALT: - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; + ide->tf->atastat = BSY_STAT; + + if (ide->type == IDE_ATAPI) ide->sc->callback = 200.0 * IDE_TIME; - } else - ide->atastat = BSY_STAT; if (ide->type == IDE_HDD) { ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); uint32_t sec_count; double wait_time; if ((val == WIN_READ_DMA) || (val == WIN_READ_DMA_ALT)) { - // TODO make DMA timing more accurate - sec_count = ide->secount ? ide->secount : 256; - double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count); + /* TODO make DMA timing more accurate */ + sec_count = ide->tf->secount ? ide->tf->secount : 256; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), sec_count); double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); wait_time = seek_time > xfer_time ? seek_time : xfer_time; } else if ((val == WIN_READ_MULTIPLE) && (ide->blocksize > 0)) { - sec_count = ide->secount ? ide->secount : 256; + sec_count = ide->tf->secount ? ide->tf->secount : 256; if (sec_count > ide->blocksize) sec_count = ide->blocksize; - double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count); + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), sec_count); double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); wait_time = seek_time + xfer_time; } else if ((val == WIN_READ_MULTIPLE) && (ide->blocksize == 0)) wait_time = 200.0; else { sec_count = 1; - double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count); + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), sec_count); double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); wait_time = seek_time + xfer_time; } @@ -1696,7 +1581,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) } else ide_set_callback(ide, 200.0 * IDE_TIME); ide->do_initial_read = 1; - return; + break; case WIN_WRITE_MULTIPLE: /* Fatal removed for the same reason as for WIN_READ_MULTIPLE. */ @@ -1708,14 +1593,9 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) case WIN_WRITE: case WIN_WRITE_NORETRY: - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRQ_STAT | DSC_STAT | DRDY_STAT; - ide->sc->pos = 0; - } else { - ide->atastat = DRQ_STAT | DSC_STAT | DRDY_STAT; - ide->pos = 0; - } - return; + ide->tf->atastat = DRQ_STAT | DSC_STAT | DRDY_STAT; + ide->tf->pos = 0; + break; case WIN_WRITE_DMA: case WIN_WRITE_DMA_ALT: @@ -1724,46 +1604,47 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) case WIN_IDENTIFY: /* Identify Device */ case WIN_SET_FEATURES: /* Set Features */ case WIN_READ_NATIVE_MAX: - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; + ide->tf->atastat = BSY_STAT; + + if (ide->type == IDE_ATAPI) ide->sc->callback = 200.0 * IDE_TIME; - } else - ide->atastat = BSY_STAT; if ((ide->type == IDE_HDD) && ((val == WIN_WRITE_DMA) || (val == WIN_WRITE_DMA_ALT))) { - uint32_t sec_count = ide->secount ? ide->secount : 256; - double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count); + uint32_t sec_count = ide->tf->secount ? ide->tf->secount : 256; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), sec_count); double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); double wait_time = seek_time > xfer_time ? seek_time : xfer_time; ide_set_callback(ide, wait_time); - } else if ((ide->type == IDE_HDD) && ((val == WIN_VERIFY) || (val == WIN_VERIFY_ONCE))) { - uint32_t sec_count = ide->secount ? ide->secount : 256; - double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count); + } else if ((ide->type == IDE_HDD) && ((val == WIN_VERIFY) || + (val == WIN_VERIFY_ONCE))) { + uint32_t sec_count = ide->tf->secount ? ide->tf->secount : 256; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), sec_count); ide_set_callback(ide, seek_time + ide_get_xfer_time(ide, 2)); } else if ((val == WIN_IDENTIFY) || (val == WIN_SET_FEATURES)) ide_callback(ide); else ide_set_callback(ide, 200.0 * IDE_TIME); - return; + break; case WIN_FORMAT: if (ide->type == IDE_ATAPI) - goto ide_bad_command; + bad = 1; else { - ide->atastat = DRQ_STAT; - ide->pos = 0; + ide->tf->atastat = DRQ_STAT; + ide->tf->pos = 0; } - return; + break; case WIN_SPECIFY: /* Initialize Drive Parameters */ - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; + ide->tf->atastat = BSY_STAT; + + if (ide->type == IDE_ATAPI) ide->sc->callback = 30.0 * IDE_TIME; - } else - ide->atastat = BSY_STAT; ide_set_callback(ide, 30.0 * IDE_TIME); - return; + break; case WIN_DRIVE_DIAGNOSTICS: /* Execute Drive Diagnostics */ dev->cur_dev &= ~1; @@ -1774,21 +1655,13 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) /* Device 0. */ dev_reset(ide); - ide->atastat = BSY_STAT; - ide->error = 1; - if (ide->type == IDE_ATAPI) { - ide->sc->status = BSY_STAT; - ide->sc->error = 1; - } + ide->tf->atastat = BSY_STAT; + ide->tf->error = 1; /* Device 1. */ dev_reset(ide_other); - ide_other->atastat = BSY_STAT; - ide_other->error = 1; - if (ide_other->type == IDE_ATAPI) { - ide_other->sc->status = BSY_STAT; - ide_other->sc->error = 1; - } + ide_other->tf->atastat = BSY_STAT; + ide_other->tf->error = 1; /* Fire the timer. */ dev->diag = 1; @@ -1796,51 +1669,45 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide_set_callback(ide, 0.0); ide_set_callback(ide_other, 0.0); ide_set_board_callback(ide->board, 200.0 * IDE_TIME); - return; + break; case WIN_PIDENTIFY: /* Identify Packet Device */ case WIN_SET_MULTIPLE_MODE: /* Set Multiple Mode */ case WIN_NOP: case WIN_STANDBYNOW1: case WIN_IDLENOW1: - case WIN_SETIDLE1: /* Idle */ + case WIN_SETIDLE1: /* Idle */ case WIN_CHECKPOWERMODE1: case WIN_SLEEP1: - if (ide->type == IDE_ATAPI) - ide->sc->status = BSY_STAT; - else - ide->atastat = BSY_STAT; + ide->tf->atastat = BSY_STAT; ide_callback(ide); - return; + break; case WIN_PACKETCMD: /* ATAPI Packet */ /* Skip the command callback wait, and process immediately. */ + ide->tf->pos = 0; if (ide->type == IDE_ATAPI) { ide->sc->packet_status = PHASE_IDLE; - ide->sc->pos = 0; - ide->sc->phase = 1; - ide->sc->status = DRDY_STAT | DRQ_STAT; + ide->tf->secount = 1; + ide->tf->atastat = DRDY_STAT | DRQ_STAT; if (ide->interrupt_drq) ide_irq_raise(ide); /* Interrupt DRQ, requires IRQ on any DRQ. */ } else { - ide->atastat = BSY_STAT; + ide->tf->atastat = BSY_STAT; ide_set_callback(ide, 200.0 * IDE_TIME); - ide->pos = 0; } - return; + break; - case 0xF0: + case 0xf0: default: -ide_bad_command: - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | ERR_STAT | DSC_STAT; - ide->sc->error = ABRT_ERR; - } else { - ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; - ide->error = ABRT_ERR; - } - ide_irq_raise(ide); - return; + bad = 1; + break; + } + + if (bad) { + ide->tf->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; + ide->tf->error = ABRT_ERR; + ide_irq_raise(ide); } return; @@ -1849,136 +1716,130 @@ ide_bad_command: } } -static uint32_t +static uint16_t ide_read_data(ide_t *ide, int length) { - uint32_t temp = 0; - - if (!ide->buffer) { - switch (length) { - case 1: - return 0xff; - case 2: - return 0xffff; - case 4: - return 0xffffffff; - default: - return 0; - } - } - const uint8_t *idebufferb = (uint8_t *) ide->buffer; const uint16_t *idebufferw = ide->buffer; - const uint32_t *idebufferl = (uint32_t *) ide->buffer; + int ch = ide->channel; + uint16_t ret = 0; - if (ide->command == WIN_PACKETCMD) { - ide->pos = 0; - if (ide->type == IDE_ATAPI) - temp = ide_atapi_packet_read(ide, length); - else { - ide_log("Drive not ATAPI (position: %i)\n", ide->pos); - return 0; - } - } else { - switch (length) { - case 1: - temp = idebufferb[ide->pos]; - ide->pos++; - break; - case 2: - temp = idebufferw[ide->pos >> 1]; - ide->pos += 2; - break; - case 4: - temp = idebufferl[ide->pos >> 2]; - ide->pos += 4; - break; - default: - return 0; - } - } - if ((ide->pos >= 512) && (ide->command != WIN_PACKETCMD)) { - ide->pos = 0; - ide->atastat = DRDY_STAT | DSC_STAT; - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | DSC_STAT; - ide->sc->packet_status = PHASE_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 = BSY_STAT | READY_STAT | DSC_STAT; - if (ide->command == WIN_READ_MULTIPLE) { - if (!ide->blockcount) { - uint32_t sec_count = ide->secount ? ide->secount : 256; - if (sec_count > ide->blocksize) - sec_count = ide->blocksize; - double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), sec_count); - double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); - ide_set_callback(ide, seek_time + xfer_time); - } else { - ide_callback(ide); - } - } else { - double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), 1); - double xfer_time = ide_get_xfer_time(ide, 512); - ide_set_callback(ide, seek_time + xfer_time); + /* Absent and is master or both are absent. */ + if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1))) { + if (length == 2) + ret = 0xff7f; + else + ret = 0x7f; + /* Absent and is slave and master is present. */ + } else if ((ide->type != IDE_NONE) || !(ch & 1)) { + if (!ide->buffer) { + if (length == 2) + ret = 0xffff; + else + ret = 0xff; + } else if (ide->command == WIN_PACKETCMD) { + if (ide->type == IDE_ATAPI) + ret = ide_atapi_packet_read(ide, length); + else { + ide_log("Drive not ATAPI (position: %i)\n", ide->tf->pos); + ide->tf->pos = 0; + } + } else { + if (length == 2) { + ret = idebufferw[ide->tf->pos >> 1]; + ide->tf->pos += 2; + } else { + ret = idebufferb[ide->tf->pos]; + ide->tf->pos++; + } + + if (ide->tf->pos >= 512) { + ide->tf->pos = 0; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + if (ide->type == IDE_ATAPI) + ide->sc->packet_status = PHASE_IDLE; + + if ((ide->command == WIN_READ) || (ide->command == WIN_READ_NORETRY) || + (ide->command == WIN_READ_MULTIPLE)) { + ide->tf->secount--; + + if (ide->tf->secount) { + ide_next_sector(ide); + ide->tf->atastat = BSY_STAT | READY_STAT | DSC_STAT; + if (ide->command == WIN_READ_MULTIPLE) { + if (!ide->blockcount) { + uint32_t sec_count = ide->tf->secount ? ide->tf->secount : 256; + if (sec_count > ide->blocksize) + sec_count = ide->blocksize; + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], + ide_get_sector(ide), sec_count); + double xfer_time = ide_get_xfer_time(ide, 512 * sec_count); + ide_set_callback(ide, seek_time + xfer_time); + } else + ide_callback(ide); + } else { + double seek_time = hdd_timing_read(&hdd[ide->hdd_num], ide_get_sector(ide), 1); + double xfer_time = ide_get_xfer_time(ide, 512); + ide_set_callback(ide, seek_time + xfer_time); + } + } else + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); } - } else - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } } } - return temp; + return ret; } static uint8_t ide_status(ide_t *ide, ide_t *ide_other, int ch) { - if ((ide->type == IDE_NONE) && ((ide_other->type == IDE_NONE) || !(ch & 1))) - return 0x7f; /* Bit 7 pulled down, all other bits pulled up, per the spec. */ - else if ((ide->type == IDE_NONE) && (ch & 1)) - return 0x7f /*0x00*/; /* On real hardware, a slave with a present master always returns a status of 0x00. */ - else if (ide->type == IDE_ATAPI) - return (ide->sc->status & ~DSC_STAT) | (ide->service ? SERVICE_STAT : 0); - else - return ide->atastat; + uint8_t ret; + + /* Absent and is master or both are absent. */ + if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1))) { + /* Bit 7 pulled down, all other bits pulled up, per the spec. */ + ret = 0x7f; + /* Absent and is slave and master is present. */ + } else if ((ide->type == IDE_NONE) && (ch & 1)) { + /* On real hardware, a slave with a present master always + returns a status of 0x00. + Confirmed by the ATA-3 and ATA-4 specifications. */ + ret = 0x00; + } else { + ret = ide->tf->atastat; + if (ide->type == IDE_ATAPI) + ret = (ret & ~DSC_STAT) | (ide->service << 4); + } + + return ret; } uint8_t ide_readb(uint16_t addr, void *priv) { const ide_board_t *dev = (ide_board_t *) priv; - int ch; int absent = 0; ide_t *ide; + ide_t *ide_other; + uint8_t ret = 0xff; ch = dev->cur_dev; ide = ide_drives[ch]; + ide_other = ide_drives[ch ^ 1]; - uint8_t temp = 0xff; - uint16_t tempw; - - addr |= 0x90; - addr &= 0xFFF7; - + /* Absent and is master or both are absent. */ if ((ide->type == IDE_NONE) && ((ide_drives[ch ^ 1]->type == IDE_NONE) || !(ch & 1))) - absent = 1; /* Absent and is master or both are absent. */ + absent = 1; + /* Absent and is slave and master is present. */ else if ((ide->type == IDE_NONE) && (ch & 1)) - absent = 2; /* Absent and is slave and master is present. */ + absent = 2; switch (addr & 0x7) { case 0x0: /* Data */ - if (absent == 1) - temp = 0x7f; - else if (absent == 2) - temp = 0x00; - else { - tempw = ide_read_data(ide, 2); - temp = tempw & 0xff; - } + ret = ide_read_data(ide, 2) & 0xff; break; /* For ATAPI: Bits 7-4 = sense key, bit 3 = MCR (media change requested), @@ -1986,13 +1847,9 @@ ide_readb(uint16_t addr, void *priv) and Bit 0 = ILI (illegal length indication). */ case 0x1: /* Error */ if (absent == 1) - temp = 0x7f; - else if (absent == 2) - temp = 0x01; - else if (ide->type == IDE_ATAPI) - temp = ide->sc->error; + ret = 0x7f; else - temp = ide->error; + ret = ide->tf->error; break; /* For ATAPI: @@ -2010,74 +1867,66 @@ ide_readb(uint16_t addr, void *priv) 1 0 1 Status. */ case 0x2: /* Sector count */ if (absent == 1) - temp = 0x7f; + ret = 0x7f; else if (absent == 2) - temp = 0x01; - else if (ide->type == IDE_ATAPI) - temp = ide->sc->phase; + ret = ide_other->tf->secount; else - temp = ide->secount; + ret = ide->tf->secount; break; case 0x3: /* Sector */ if (absent == 1) - temp = 0x7f; + ret = 0x7f; else if (absent == 2) - temp = 0x01; + ret = (uint8_t) ide_other->sector; else - temp = (uint8_t) ide->sector; + ret = (uint8_t) ide->sector; break; case 0x4: /* Cylinder low */ if (absent == 1) - temp = 0x7f; + ret = 0x7f; else if (absent == 2) - temp = 0x00; - else if (ide->type == IDE_ATAPI) - temp = ide->sc->request_length & 0xff; + ret = ide_other->tf->cylinder & 0xff; else - temp = ide->cylinder & 0xff; + ret = ide->tf->cylinder & 0xff; break; case 0x5: /* Cylinder high */ if (absent == 1) - temp = 0x7f; + ret = 0x7f; else if (absent == 2) - temp = 0x00; - else if (ide->type == IDE_ATAPI) - temp = ide->sc->request_length >> 8; + ret = ide_other->tf->cylinder >> 8; else - temp = ide->cylinder >> 8; + ret = ide->tf->cylinder >> 8; break; case 0x6: /* Drive/Head */ if (absent == 1) - temp = 0x7f; - else if (absent == 2) - temp = 0xb0; + ret = 0x7f; else - temp = (uint8_t) (ide->head | ((ch & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); + ret = (uint8_t) (ide->head | ((ch & 1) ? 0x10 : 0) | (ide->lba ? 0x40 : 0) | 0xa0); break; /* For ATAPI: Bit 5 is DMA ready, but without overlapped or interlaved DMA, it is DF (drive fault). */ case 0x7: /* Status */ ide_irq_lower(ide); - temp = ide_status(ide, ide_drives[ch ^ 1], ch); + ret = ide_status(ide, ide_drives[ch ^ 1], ch); break; default: break; } - ide_log("ide_readb(%04X, %08X) = %02X\n", addr, priv, temp); - return temp; + ide_log("ide_readb(%04X, %08X) = %02X\n", addr, priv, ret); + return ret; } uint8_t ide_read_alt_status(UNUSED(uint16_t addr), void *priv) { - uint8_t temp = 0xff; + uint8_t ret = 0xff; const ide_board_t *dev = (ide_board_t *) priv; @@ -2089,16 +1938,16 @@ ide_read_alt_status(UNUSED(uint16_t addr), void *priv) /* Per the Seagate ATA-3 specification: Reading the alternate status does *NOT* clear the IRQ. */ - temp = ide_status(ide, ide_drives[ch ^ 1], ch); + ret = ide_status(ide, ide_drives[ch ^ 1], ch); - ide_log("ide_read_alt_status(%04X, %08X) = %02X\n", addr, priv, temp); - return temp; + ide_log("ide_read_alt_status(%04X, %08X) = %02X\n", addr, priv, ret); + return ret; } uint16_t ide_readw(uint16_t addr, void *priv) { - uint16_t temp = 0xffff; + uint16_t ret = 0xffff; const ide_board_t *dev = (ide_board_t *) priv; @@ -2110,86 +1959,80 @@ ide_readw(uint16_t addr, void *priv) switch (addr & 0x7) { case 0x0: /* Data */ - temp = ide_read_data(ide, 2); + ret = ide_read_data(ide, 2); break; case 0x7: - temp = ide_readb(addr, priv) | 0xff00; + ret = ide_readb(addr, priv) | 0xff00; break; default: - temp = ide_readb(addr, priv) | (ide_readb(addr + 1, priv) << 8); + ret = ide_readb(addr, priv) | (ide_readb(addr + 1, priv) << 8); break; } - ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, temp); - return temp; + ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, ret); + return ret; } static uint32_t ide_readl(uint16_t addr, void *priv) { - uint16_t temp2; - uint32_t temp = 0xffffffff; - - const ide_board_t *dev = (ide_board_t *) priv; - ide_t *ide; int ch; + uint32_t ret = 0xffffffff; + + const ide_board_t *dev = (ide_board_t *) priv; ch = dev->cur_dev; ide = ide_drives[ch]; switch (addr & 0x7) { case 0x0: /* Data */ - temp2 = ide_read_data(ide, 2); + ret = ide_read_data(ide, 2); if (dev->bit32) - temp = temp2 | (ide_read_data(ide, 2) << 16); + ret |= (ide_read_data(ide, 2) << 16); else - temp = temp2 | (ide_readw(addr + 2, priv) << 16); + ret |= (ide_readw(addr + 2, priv) << 16); break; case 0x6: case 0x7: - temp = ide_readw(addr, priv) | 0xffff0000; + ret = ide_readw(addr, priv) | 0xffff0000; break; default: - temp = ide_readw(addr, priv) | (ide_readw(addr + 2, priv) << 16); + ret = ide_readw(addr, priv) | (ide_readw(addr + 2, priv) << 16); break; } - ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, temp); - return temp; + ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, ret); + return ret; } static void ide_board_callback(void *priv) { ide_board_t *dev = (ide_board_t *) priv; + ide_t *ide; #ifdef ENABLE_IDE_LOG - ide_log("CALLBACK RESET\n"); + ide_log("ide_board_callback(%i)\n", dev->cur_dev >> 1); #endif - dev->ide[0]->atastat = DRDY_STAT | DSC_STAT; - if (dev->ide[0]->type == IDE_ATAPI) { - if (dev->ide[0]->sc->pad0) - dev->ide[0]->sc->status = DRDY_STAT | DSC_STAT; - else - dev->ide[0]->sc->status = 0; - } - - dev->ide[1]->atastat = DRDY_STAT | DSC_STAT; - if (dev->ide[1]->type == IDE_ATAPI) { - if (dev->ide[1]->sc->pad0) - dev->ide[1]->sc->status = DRDY_STAT | DSC_STAT; - else - dev->ide[1]->sc->status = 0; + for (uint8_t i = 0; i < 2; i++) { + ide = dev->ide[i]; + if (ide->type == IDE_ATAPI) { + ide->tf->atastat = 0; + if (IDE_ATAPI_IS_EARLY) + ide->tf->atastat |= DRDY_STAT | DSC_STAT; + } else + ide->tf->atastat = DRDY_STAT | DSC_STAT; } dev->cur_dev &= ~1; + ide = dev->ide[0]; if (dev->diag) { dev->diag = 0; - if ((dev->ide[0]->type != IDE_ATAPI) || dev->ide[0]->sc->pad0) - ide_irq_raise(dev->ide[0]); + if ((ide->type != IDE_ATAPI) || IDE_ATAPI_IS_EARLY) + ide_irq_raise(ide); } } @@ -2197,15 +2040,10 @@ static void atapi_error_no_ready(ide_t *ide) { ide->command = 0; - if (ide->type == IDE_ATAPI) { - ide->sc->status = ERR_STAT | DSC_STAT; - ide->sc->error = ABRT_ERR; - ide->sc->pos = 0; - } else { - ide->atastat = ERR_STAT | DSC_STAT; - ide->error = ABRT_ERR; - ide->pos = 0; - } + ide->tf->atastat = ERR_STAT | DSC_STAT; + ide->tf->error = ABRT_ERR; + ide->tf->pos = 0; + ide_irq_raise(ide); } @@ -2214,150 +2052,151 @@ ide_callback(void *priv) { int snum; int ret = 0; - + uint8_t err = 0x00; + int chk_chs = 0; ide_t *ide = (ide_t *) priv; + ide_bm_t *bm = ide_boards[ide->board]->bm; - ide_log("CALLBACK %02X %i %i\n", ide->command, ide->reset, ide->channel); - - if (((ide->command >= WIN_RECAL) && (ide->command <= 0x1F)) || ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F))) { - if (ide->type != IDE_HDD) { - atapi_error_no_ready(ide); - return; - } - if ((ide->command >= WIN_SEEK) && (ide->command <= 0x7F) && !ide->lba) { - if ((ide->cylinder >= ide->tracks) || (ide->head >= ide->hpc) || !ide->sector || (ide->sector > ide->spt)) - goto id_not_found; - } - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - } + ide_log("ide_callback(%i): %02X\n", ide->channel, ide->command); 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 */ + case WIN_SEEK ... 0x7F: + chk_chs = !ide->lba; + if (ide->type == IDE_ATAPI) + atapi_error_no_ready(ide); + else { + if (chk_chs && ((ide->tf->cylinder >= ide->tracks) || (ide->head >= ide->hpc) || + !ide->sector || (ide->sector > ide->spt))) + err = IDNF_ERR; + else { + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + } + break; - ide->atastat = DRDY_STAT | DSC_STAT; - ide->error = 1; /*Device passed*/ - ide->secount = 1; - ide->sector = 1; + case WIN_RECAL ... 0x1F: + if (ide->type == IDE_ATAPI) + atapi_error_no_ready(ide); + else { + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + break; + + /* 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->tf->error = 1; /*Device passed*/ + + ide->tf->secount = 1; + ide->sector = 1; ide_set_signature(ide); + ide->tf->atastat = DRDY_STAT | DSC_STAT; if (ide->type == IDE_ATAPI) { - ide->sc->error = 1; if (ide->device_reset) ide->device_reset(ide->sc); - if (ide->sc->pad0) /* pad0 = early */ - ide->sc->status = DRDY_STAT | DSC_STAT; - else - ide->sc->status = 0; + if (!IDE_ATAPI_IS_EARLY) + ide->tf->atastat = 0; } + ide_irq_raise(ide); - if ((ide->type == IDE_ATAPI) && !ide->sc->pad0) + + if ((ide->type == IDE_ATAPI) && !IDE_ATAPI_IS_EARLY) ide->service = 0; - return; + break; case WIN_NOP: case WIN_STANDBYNOW1: case WIN_IDLENOW1: case WIN_SETIDLE1: - if (ide->type == IDE_ATAPI) - ide->sc->status = DRDY_STAT | DSC_STAT; - else - ide->atastat = DRDY_STAT | DSC_STAT; + ide->tf->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); - return; + break; case WIN_CHECKPOWERMODE1: case WIN_SLEEP1: - if (ide->type == IDE_ATAPI) { - ide->sc->phase = 0xFF; - ide->sc->status = DRDY_STAT | DSC_STAT; - } - ide->secount = 0xFF; - ide->atastat = DRDY_STAT | DSC_STAT; + ide->tf->secount = 0xff; + ide->tf->atastat = DRDY_STAT | DSC_STAT; ide_irq_raise(ide); - return; + break; case WIN_READ: case WIN_READ_NORETRY: if (ide->type == IDE_ATAPI) { ide_set_signature(ide); - goto abort_cmd; + err = ABRT_ERR; + } else if (!ide->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + if (ide->do_initial_read) { + ide->do_initial_read = 0; + ide->sector_pos = 0; + hdd_image_read(ide->hdd_num, ide_get_sector(ide), + ide->tf->secount ? ide->tf->secount : 256, ide->sector_buffer); + } + + memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos * 512], 512); + + ide->sector_pos++; + + ide->tf->pos = 0; + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + + ide_irq_raise(ide); + + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); } - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; - - if (ide->do_initial_read) { - ide->do_initial_read = 0; - ide->sector_pos = 0; - if (ide->secount) - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); - else - hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); - } - - memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos * 512], 512); - - ide->sector_pos++; - ide->pos = 0; - - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - - ide_irq_raise(ide); - - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; + break; case WIN_READ_DMA: case WIN_READ_DMA_ALT: - if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || !ide_bm[ide->board]) { + if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || (bm == NULL)) { ide_log("IDE %i: DMA read aborted (bad device or board)\n", ide->channel); - goto abort_cmd; - } - if (!ide->lba && (ide->cfg_spt == 0)) { + err = ABRT_ERR; + } else if (!ide->lba && (ide->cfg_spt == 0)) { ide_log("IDE %i: DMA read aborted (SPECIFY failed)\n", ide->channel); - goto id_not_found; - } - - ide->sector_pos = 0; - if (ide->secount) - ide->sector_pos = ide->secount; - else - ide->sector_pos = 256; - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); - - ide->pos = 0; - - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->dma) { - /* We should not abort - we should simply wait for the host to start DMA. */ - ret = ide_bm[ide->board]->dma(ide->sector_buffer, ide->sector_pos * 512, - 0, ide_bm[ide->board]->priv); - if (ret == 2) { - /* Bus master DMA disabled, simply wait for the host to enable DMA. */ - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - ide_set_callback(ide, 6.0 * IDE_TIME); - return; - } else if (ret == 1) { - /*DMA successful*/ - ide_log("IDE %i: DMA read successful\n", ide->channel); - - ide->atastat = DRDY_STAT | DSC_STAT; - - ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } else { - /* Bus master DMAS error, abort the command. */ - ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); - goto abort_cmd; - } + err = IDNF_ERR; } else { - ide_log("IDE %i: DMA read aborted (no bus master)\n", ide->channel); - goto abort_cmd; + ide->sector_pos = 0; + if (ide->tf->secount) + ide->sector_pos = ide->tf->secount; + else + ide->sector_pos = 256; + hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); + + ide->tf->pos = 0; + + if (!ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { + /* We should not abort - we should simply wait for the host to start DMA. */ + ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 0, bm->priv); + if (ret == 2) { + /* Bus master DMA disabled, simply wait for the host to enable DMA. */ + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_set_callback(ide, 6.0 * IDE_TIME); + return; + } else if (ret == 1) { + /* DMA successful */ + ide_log("IDE %i: DMA read successful\n", ide->channel); + + ide->tf->atastat = DRDY_STAT | DSC_STAT; + + ide_irq_raise(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } else { + /* Bus master DMAS error, abort the command. */ + ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); + err = ABRT_ERR; + } + } else { + ide_log("IDE %i: DMA read aborted (no bus master)\n", ide->channel); + err = ABRT_ERR; + } } - return; + break; case WIN_READ_MULTIPLE: /* According to the official ATA reference: @@ -2367,98 +2206,97 @@ ide_callback(void *priv) disabled, the Read Multiple operation is rejected with an Aborted Com- mand error. */ if ((ide->type == IDE_ATAPI) || !ide->blocksize) - goto abort_cmd; - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; + err = ABRT_ERR; + else if (!ide->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + if (ide->do_initial_read) { + ide->do_initial_read = 0; + ide->sector_pos = 0; + hdd_image_read(ide->hdd_num, ide_get_sector(ide), + ide->tf->secount ? ide->tf->secount : 256, ide->sector_buffer); + } - if (ide->do_initial_read) { - ide->do_initial_read = 0; - ide->sector_pos = 0; - if (ide->secount) - hdd_image_read(ide->hdd_num, ide_get_sector(ide), ide->secount, ide->sector_buffer); - else - hdd_image_read(ide->hdd_num, ide_get_sector(ide), 256, ide->sector_buffer); + memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos * 512], 512); + + ide->sector_pos++; + ide->tf->pos = 0; + + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + if (!ide->blockcount) + ide_irq_raise(ide); + ide->blockcount++; + if (ide->blockcount >= ide->blocksize) + ide->blockcount = 0; } - - memcpy(ide->buffer, &ide->sector_buffer[ide->sector_pos * 512], 512); - - ide->sector_pos++; - ide->pos = 0; - - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - if (!ide->blockcount) - ide_irq_raise(ide); - ide->blockcount++; - if (ide->blockcount >= ide->blocksize) - ide->blockcount = 0; - return; + break; case WIN_WRITE: case WIN_WRITE_NORETRY: if (ide->type == IDE_ATAPI) - goto abort_cmd; - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; - hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); - ide_irq_raise(ide); - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) { - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - ide->pos = 0; - ide_next_sector(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - } else { - ide->atastat = DRDY_STAT | DSC_STAT; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + err = ABRT_ERR; + else if (!ide->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); + ide_irq_raise(ide); + ide->tf->secount--; + if (ide->tf->secount) { + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide->tf->pos = 0; + ide_next_sector(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + } else { + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } } - return; + break; case WIN_WRITE_DMA: case WIN_WRITE_DMA_ALT: - if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || !ide_bm[ide->board]) { + if ((ide->type == IDE_ATAPI) || ide_boards[ide->board]->force_ata3 || (bm == NULL)) { ide_log("IDE %i: DMA write aborted (bad device type or board)\n", ide->channel); - goto abort_cmd; - } - if (!ide->lba && (ide->cfg_spt == 0)) { + err = ABRT_ERR; + } else if (!ide->lba && (ide->cfg_spt == 0)) { ide_log("IDE %i: DMA write aborted (SPECIFY failed)\n", ide->channel); - goto id_not_found; - } - - if (!ide_boards[ide->board]->force_ata3 && ide_bm[ide->board] && ide_bm[ide->board]->dma) { - if (ide->secount) - ide->sector_pos = ide->secount; - else - ide->sector_pos = 256; - - ret = ide_bm[ide->board]->dma(ide->sector_buffer, ide->sector_pos * 512, - 1, ide_bm[ide->board]->priv); - - if (ret == 2) { - /* Bus master DMA disabled, simply wait for the host to enable DMA. */ - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - ide_set_callback(ide, 6.0 * IDE_TIME); - return; - } else if (ret == 1) { - /*DMA successful*/ - ide_log("IDE %i: DMA write successful\n", ide->channel); - - hdd_image_write(ide->hdd_num, ide_get_sector(ide), ide->sector_pos, ide->sector_buffer); - - ide->atastat = DRDY_STAT | DSC_STAT; - - ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } else { - /* Bus master DMA error, abort the command. */ - ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); - goto abort_cmd; - } + err = IDNF_ERR; } else { - ide_log("IDE %i: DMA write aborted (no bus master)\n", ide->channel); - goto abort_cmd; - } + if (!ide_boards[ide->board]->force_ata3 && (bm != NULL) && bm->dma) { + if (ide->tf->secount) + ide->sector_pos = ide->tf->secount; + else + ide->sector_pos = 256; - return; + ret = bm->dma(ide->sector_buffer, ide->sector_pos * 512, 1, bm->priv); + + if (ret == 2) { + /* Bus master DMA disabled, simply wait for the host to enable DMA. */ + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_set_callback(ide, 6.0 * IDE_TIME); + return; + } else if (ret == 1) { + /* DMA successful */ + ide_log("IDE %i: DMA write successful\n", ide->channel); + + hdd_image_write(ide->hdd_num, ide_get_sector(ide), + ide->sector_pos, ide->sector_buffer); + + ide->tf->atastat = DRDY_STAT | DSC_STAT; + + ide_irq_raise(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } else { + /* Bus master DMA error, abort the command. */ + ide_log("IDE %i: DMA read aborted (failed)\n", ide->channel); + err = ABRT_ERR; + } + } else { + ide_log("IDE %i: DMA write aborted (no bus master)\n", ide->channel); + err = ABRT_ERR; + } + } + break; case WIN_WRITE_MULTIPLE: /* According to the official ATA reference: @@ -2468,157 +2306,154 @@ ide_callback(void *priv) disabled, the Read Multiple operation is rejected with an Aborted Com- mand error. */ if ((ide->type == IDE_ATAPI) || !ide->blocksize) - goto abort_cmd; - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; - hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); - ide->blockcount++; - if (ide->blockcount >= ide->blocksize || ide->secount == 1) { - ide->blockcount = 0; - ide_irq_raise(ide); + err = ABRT_ERR; + else if (!ide->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + hdd_image_write(ide->hdd_num, ide_get_sector(ide), 1, (uint8_t *) ide->buffer); + ide->blockcount++; + if (ide->blockcount >= ide->blocksize || ide->tf->secount == 1) { + ide->blockcount = 0; + ide_irq_raise(ide); + } + ide->tf->secount--; + if (ide->tf->secount) { + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide->tf->pos = 0; + ide_next_sector(ide); + } else { + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); + } } - ide->secount = (ide->secount - 1) & 0xff; - if (ide->secount) { - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; - ide->pos = 0; - ide_next_sector(ide); - } else { - ide->atastat = DRDY_STAT | DSC_STAT; - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 0); - } - return; + break; case WIN_VERIFY: case WIN_VERIFY_ONCE: if (ide->type == IDE_ATAPI) - goto abort_cmd; - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; - ide->pos = 0; - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; + err = ABRT_ERR; + else if (!ide->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + ide->tf->pos = 0; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + } + break; case WIN_FORMAT: if (ide->type == IDE_ATAPI) - goto abort_cmd; - if (!ide->lba && (ide->cfg_spt == 0)) - goto id_not_found; - hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->secount); + err = ABRT_ERR; + else if (!ide->lba && (ide->cfg_spt == 0)) + err = IDNF_ERR; + else { + hdd_image_zero(ide->hdd_num, ide_get_sector(ide), ide->tf->secount); - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); - ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); - return; + ui_sb_update_icon(SB_HDD | hdd[ide->hdd_num].bus, 1); + } + break; case WIN_SPECIFY: /* Initialize Drive Parameters */ if (ide->type == IDE_ATAPI) - goto abort_cmd; - if (ide->cfg_spt == 0) { - /* Only accept after RESET or DIAG. */ - ide->cfg_spt = ide->secount; - ide->cfg_hpc = ide->head + 1; + err = ABRT_ERR; + else { + if (ide->cfg_spt == 0) { + /* Only accept after RESET or DIAG. */ + ide->cfg_spt = ide->tf->secount; + ide->cfg_hpc = ide->head + 1; + } + ide->command = 0x00; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide->tf->error = 1; + ide_irq_raise(ide); } - ide->command = 0x00; - ide->atastat = DRDY_STAT | DSC_STAT; - ide->error = 1; - ide_irq_raise(ide); - return; + break; case WIN_PIDENTIFY: /* Identify Packet Device */ if (ide->type == IDE_ATAPI) { ide_identify(ide); - ide->pos = 0; - ide->sc->phase = 2; - ide->sc->pos = 0; - ide->sc->error = 0; - ide->sc->status = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide->tf->pos = 0; + ide->tf->phase = 2; + ide->tf->error = 0; + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; ide_irq_raise(ide); - return; - } - goto abort_cmd; + } else + err = ABRT_ERR; + break; case WIN_SET_MULTIPLE_MODE: - if (ide->type == IDE_ATAPI) - goto abort_cmd; - if ((ide->secount < 2) || (ide->secount > hdd[ide->hdd_num].max_multiple_block)) - goto abort_cmd; - ide->blocksize = ide->secount; - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; + if ((ide->type == IDE_ATAPI) || (ide->tf->secount < 2) || + (ide->tf->secount > hdd[ide->hdd_num].max_multiple_block)) + err = ABRT_ERR; + else { + ide->blocksize = ide->tf->secount; + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } + break; case WIN_SET_FEATURES: if ((ide->type == IDE_NONE) || !ide_set_features(ide)) - goto abort_cmd; + err = ABRT_ERR; + else { + ide->tf->atastat = DRDY_STAT | DSC_STAT; - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | DSC_STAT; - ide->sc->pos = 0; - } + if (ide->type == IDE_ATAPI) + ide->tf->pos = 0; - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - - case WIN_READ_NATIVE_MAX: - if (ide->type != IDE_HDD) - goto abort_cmd; - snum = hdd[ide->hdd_num].spt; - snum *= hdd[ide->hdd_num].hpc; - snum *= hdd[ide->hdd_num].tracks; - ide_set_sector(ide, snum - 1); - ide->atastat = DRDY_STAT | DSC_STAT; - ide_irq_raise(ide); - return; - - case WIN_IDENTIFY: /* Identify Device */ - if (ide->type != IDE_HDD) { - ide_set_signature(ide); - goto abort_cmd; - } else { - ide_identify(ide); - ide->pos = 0; - ide->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; ide_irq_raise(ide); } - return; + break; + + case WIN_READ_NATIVE_MAX: + if (ide->type == IDE_HDD) { + snum = hdd[ide->hdd_num].spt; + snum *= hdd[ide->hdd_num].hpc; + snum *= hdd[ide->hdd_num].tracks; + ide_set_sector(ide, snum - 1); + ide->tf->atastat = DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } else + err = ABRT_ERR; + break; + + case WIN_IDENTIFY: /* Identify Device */ + if (ide->type == IDE_HDD) { + ide_identify(ide); + ide->tf->pos = 0; + ide->tf->atastat = DRQ_STAT | DRDY_STAT | DSC_STAT; + ide_irq_raise(ide); + } else { + ide_set_signature(ide); + err = ABRT_ERR; + } + break; case WIN_PACKETCMD: /* ATAPI Packet */ - if (ide->type != IDE_ATAPI) - goto abort_cmd; - - ide_atapi_callback(ide); - return; - - case 0xFF: - goto abort_cmd; + if (ide->type == IDE_ATAPI) + ide_atapi_callback(ide); + else + err = ABRT_ERR; + break; default: + case 0xff: + err = ABRT_ERR; break; } -abort_cmd: - ide->command = 0; - if (ide->type == IDE_ATAPI) { - ide->sc->status = DRDY_STAT | ERR_STAT | DSC_STAT; - ide->sc->error = ABRT_ERR; - ide->sc->pos = 0; - } else { - ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; - ide->error = ABRT_ERR; - ide->pos = 0; - } - ide_irq_raise(ide); - return; + if (err != 0x00) { + ide->tf->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; + ide->tf->error = err; -id_not_found: - ide->atastat = DRDY_STAT | ERR_STAT | DSC_STAT; - ide->error = IDNF_ERR; - ide->pos = 0; - ide_irq_raise(ide); + ide->tf->pos = 0; + + ide_irq_raise(ide); + } } uint8_t @@ -2661,130 +2496,74 @@ ide_read_ali_76(void) ide0 = ide_drives[ch0]; ide1 = ide_drives[ch1]; - if (ide1->atastat & BSY_STAT) + if (ide1->tf->atastat & BSY_STAT) ret |= 0x40; - if (ide1->atastat & DRQ_STAT) + if (ide1->tf->atastat & DRQ_STAT) ret |= 0x20; - if (ide1->atastat & ERR_STAT) + if (ide1->tf->atastat & ERR_STAT) ret |= 0x10; - if (ide0->atastat & BSY_STAT) + if (ide0->tf->atastat & BSY_STAT) ret |= 0x04; - if (ide0->atastat & DRQ_STAT) + if (ide0->tf->atastat & DRQ_STAT) ret |= 0x02; - if (ide0->atastat & ERR_STAT) + if (ide0->tf->atastat & ERR_STAT) ret |= 0x01; return ret; } void -ide_set_handlers(uint8_t board) +ide_handlers(uint8_t board, int set) { - if (ide_boards[board] == NULL) - return; + if (ide_boards[board] != NULL) { + if (ide_boards[board]->base[0]) { + io_handler(set, ide_boards[board]->base[0], 8, + ide_readb, ide_readw, ide_readl, + ide_writeb, ide_writew, ide_writel, + ide_boards[board]); + } - if (ide_boards[board]->base_main) { - io_sethandler(ide_boards[board]->base_main, 8, - ide_readb, ide_readw, ide_readl, - ide_writeb, ide_writew, ide_writel, - ide_boards[board]); - } - - if (ide_boards[board]->side_main) { - io_sethandler(ide_boards[board]->side_main, 1, - ide_read_alt_status, NULL, NULL, - ide_write_devctl, NULL, NULL, - ide_boards[board]); + if (ide_boards[board]->base[1]) { + io_handler(set, ide_boards[board]->base[1], 1, + ide_read_alt_status, NULL, NULL, + ide_write_devctl, NULL, NULL, + ide_boards[board]); + } } } void -ide_remove_handlers(uint8_t board) +ide_set_base_addr(int board, int base, uint16_t port) { - if (ide_boards[board] == NULL) - return; + ide_log("ide_set_base_addr(%i, %i, %04X)\n", board, base, port); - if (ide_boards[board]->base_main) { - io_removehandler(ide_boards[board]->base_main, 8, - ide_readb, ide_readw, ide_readl, - ide_writeb, ide_writew, ide_writel, - ide_boards[board]); - } - - if (ide_boards[board]->side_main) { - io_removehandler(ide_boards[board]->side_main, 1, - ide_read_alt_status, NULL, NULL, - ide_write_devctl, NULL, NULL, - ide_boards[board]); - } -} - -void -ide_pri_enable(void) -{ - ide_set_handlers(0); -} - -void -ide_pri_disable(void) -{ - ide_remove_handlers(0); -} - -void -ide_sec_enable(void) -{ - ide_set_handlers(1); -} - -void -ide_sec_disable(void) -{ - ide_remove_handlers(1); -} - -void -ide_set_base(int board, uint16_t port) -{ - ide_log("ide_set_base(%i, %04X)\n", board, port); - - if (ide_boards[board] == NULL) - return; - - ide_boards[board]->base_main = port; -} - -void -ide_set_side(int board, uint16_t port) -{ - ide_log("ide_set_side(%i, %04X)\n", board, port); - - if (ide_boards[board] == NULL) - return; - - ide_boards[board]->side_main = port; + if (ide_boards[board] != NULL) + ide_boards[board]->base[base] = port; } static void ide_clear_bus_master(int board) { - if (ide_bm[board]) { - free(ide_bm[board]); - ide_bm[board] = NULL; + ide_bm_t *bm = ide_boards[board]->bm; + + if (bm != NULL) { + free(bm); + ide_boards[board]->bm = NULL; } } -/* This so drives can be forced to ATA-3 (no DMA) for machines that hide the on-board PCI IDE controller - (eg. Packard Bell PB640 and ASUS P/I-P54TP4XE), breaking DMA drivers unless this is done. */ +/* + This so drives can be forced to ATA-3 (no DMA) for machines that hide the + on-board PCI IDE controller (eg. Packard Bell PB640 and ASUS P/I-P54TP4XE), + breaking DMA drivers unless this is done. + */ extern void ide_board_set_force_ata3(int board, int force_ata3) { ide_log("ide_board_set_force_ata3(%i, %i)\n", board, force_ata3); - if ((ide_boards[board] == NULL) || !ide_boards[board]->inited) - return; - - ide_boards[board]->force_ata3 = force_ata3; + if ((ide_boards[board] != NULL) && ide_boards[board]->inited) + ide_boards[board]->force_ata3 = force_ata3; } static void @@ -2812,28 +2591,31 @@ ide_board_close(int board) dev = ide_drives[c]; - if (dev == NULL) - continue; + if (dev != NULL) { + if ((dev->type == IDE_HDD) && (dev->hdd_num != -1)) + hdd_image_close(dev->hdd_num); - if ((dev->type == IDE_HDD) && (dev->hdd_num != -1)) - hdd_image_close(dev->hdd_num); + if (dev->type == IDE_ATAPI) + dev->tf->atastat = DRDY_STAT | DSC_STAT; + else if (dev->tf != NULL) { + free(dev->tf); + dev->tf = NULL; + } - if (dev->type == IDE_ATAPI) - dev->sc->status = DRDY_STAT | DSC_STAT; + if (dev->buffer) { + free(dev->buffer); + dev->buffer = NULL; + } - if (dev->buffer) { - free(dev->buffer); - dev->buffer = NULL; - } + if (dev->sector_buffer) { + free(dev->sector_buffer); + dev->buffer = NULL; + } - if (dev->sector_buffer) { - free(dev->sector_buffer); - dev->buffer = NULL; - } - - if (dev) { - free(dev); - ide_drives[c] = NULL; + if (dev) { + free(dev); + ide_drives[c] = NULL; + } } } @@ -2877,8 +2659,7 @@ ide_board_setup(int board) ide_log("Found IDE hard disk on channel %i\n", ch); loadhd(ide_drives[ch], d, hdd[d].fn); if (ide_drives[ch]->sector_buffer == NULL) - ide_drives[ch]->sector_buffer = (uint8_t *) malloc(256 * 512); - memset(ide_drives[ch]->sector_buffer, 0, 256 * 512); + ide_drives[ch]->sector_buffer = (uint8_t *) calloc(1, 256 * 512); if (++c >= 2) break; } @@ -2897,7 +2678,7 @@ ide_board_setup(int board) ide_set_signature(dev); dev->mdma_mode = (1 << ide_get_max(dev, TYPE_PIO)); - dev->error = 1; + dev->tf->error = 1; if (dev->type != IDE_HDD) dev->cfg_spt = dev->cfg_hpc = 0; if (dev->type == IDE_HDD) @@ -2916,15 +2697,14 @@ ide_board_init(int board, int irq, int base_main, int side_main, int type) ide_log("IDE: Initializing board %i...\n", board); if (ide_boards[board] == NULL) - ide_boards[board] = (ide_board_t *) malloc(sizeof(ide_board_t)); + ide_boards[board] = (ide_board_t *) calloc(1, sizeof(ide_board_t)); - memset(ide_boards[board], 0, sizeof(ide_board_t)); ide_boards[board]->irq = irq; ide_boards[board]->cur_dev = board << 1; if (type & 6) ide_boards[board]->bit32 = 1; - ide_boards[board]->base_main = base_main; - ide_boards[board]->side_main = side_main; + ide_boards[board]->base[0] = base_main; + ide_boards[board]->base[1] = side_main; ide_set_handlers(board); timer_add(&ide_boards[board]->timer, ide_board_callback, ide_boards[board], 0); @@ -2942,18 +2722,20 @@ ide_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) if (ld) return; - if (ide_boards[board]->base_main || ide_boards[board]->side_main) { + if (ide_boards[board]->base[0] || ide_boards[board]->base[1]) { ide_remove_handlers(board); - ide_boards[board]->base_main = ide_boards[board]->side_main = 0; + ide_boards[board]->base[0] = ide_boards[board]->base[1] = 0; } ide_boards[board]->irq = -1; if (config->activate) { - ide_boards[board]->base_main = (config->io[0].base != ISAPNP_IO_DISABLED) ? config->io[0].base : 0x0000; - ide_boards[board]->side_main = (config->io[1].base != ISAPNP_IO_DISABLED) ? config->io[1].base : 0x0000; + ide_boards[board]->base[0] = (config->io[0].base != ISAPNP_IO_DISABLED) ? + config->io[0].base : 0x0000; + ide_boards[board]->base[1] = (config->io[1].base != ISAPNP_IO_DISABLED) ? + config->io[1].base : 0x0000; - if (ide_boards[board]->base_main && ide_boards[board]->side_main) + if (ide_boards[board]->base[0] && ide_boards[board]->base[1]) ide_set_handlers(board); if (config->irq[0].irq != ISAPNP_IRQ_DISABLED) @@ -2977,7 +2759,8 @@ ide_ter_init(const device_t *info) if (irq < 0) { ide_board_init(2, -1, 0, 0, 0); if (irq == -1) - isapnp_add_card(ide_ter_pnp_rom, sizeof(ide_ter_pnp_rom), ide_pnp_config_changed, NULL, NULL, NULL, (void *) 2); + isapnp_add_card(ide_ter_pnp_rom, sizeof(ide_ter_pnp_rom), + ide_pnp_config_changed, NULL, NULL, NULL, (void *) 2); } else { ide_board_init(2, irq, HDC_TERTIARY_BASE, HDC_TERTIARY_SIDE, 0); } @@ -3008,10 +2791,10 @@ ide_qua_init(const device_t *info) if (irq < 0) { ide_board_init(3, -1, 0, 0, 0); if (irq == -1) - isapnp_add_card(ide_qua_pnp_rom, sizeof(ide_qua_pnp_rom), ide_pnp_config_changed, NULL, NULL, NULL, (void *) 3); - } else { + isapnp_add_card(ide_qua_pnp_rom, sizeof(ide_qua_pnp_rom), + ide_pnp_config_changed, NULL, NULL, NULL, (void *) 3); + } else ide_board_init(3, irq, HDC_QUATERNARY_BASE, HDC_QUATERNARY_SIDE, 0); - } return (ide_boards[3]); } @@ -3042,12 +2825,17 @@ ide_set_bus_master(int board, int (*dma)(uint8_t *data, int transfer_length, int out, void *priv), void (*set_irq)(uint8_t status, void *priv), void *priv) { - if (ide_bm[board] == NULL) - ide_bm[board] = (ide_bm_t *) malloc(sizeof(ide_bm_t)); + ide_bm_t *bm; - ide_bm[board]->dma = dma; - ide_bm[board]->set_irq = set_irq; - ide_bm[board]->priv = priv; + if (ide_boards[board]->bm == NULL) { + bm = (ide_bm_t *) calloc(1, sizeof(ide_bm_t)); + ide_boards[board]->bm = bm; + } else + bm = ide_boards[board]->bm; + + bm->dma = dma; + bm->set_irq = set_irq; + bm->priv = priv; } static void * @@ -3056,12 +2844,7 @@ ide_init(const device_t *info) ide_log("Initializing IDE...\n"); switch (info->local) { - case 0: /* ISA, single-channel */ - case 1: /* ISA, dual-channel */ - case 2: /* VLB, single-channel */ - case 3: /* VLB, dual-channel */ - case 4: /* PCI, single-channel */ - case 5: /* PCI, dual-channel */ + case 0 ... 5: ide_board_init(0, 14, 0x1f0, 0x3f6, info->local); if (info->local & 1) @@ -3072,7 +2855,6 @@ ide_init(const device_t *info) break; } - // return ide_drives; return (void *) (intptr_t) -1; } @@ -3081,11 +2863,11 @@ ide_drive_reset(int d) { ide_log("Resetting IDE drive %i...\n", d); - ide_drives[d]->channel = d; - ide_drives[d]->atastat = DRDY_STAT | DSC_STAT; - ide_drives[d]->service = 0; - ide_drives[d]->board = d >> 1; - ide_drives[d]->selected = !(d & 1); + ide_drives[d]->channel = d; + ide_drives[d]->tf->atastat = DRDY_STAT | DSC_STAT; + ide_drives[d]->service = 0; + ide_drives[d]->board = d >> 1; + ide_drives[d]->selected = !(d & 1); timer_stop(&ide_drives[d]->timer); if (ide_boards[d >> 1]) { @@ -3125,11 +2907,10 @@ ide_reset(UNUSED(void *priv)) { ide_log("Resetting IDE...\n"); - if (ide_boards[0] != NULL) - ide_board_reset(0); - - if (ide_boards[1] != NULL) - ide_board_reset(1); + for (uint8_t i = 0; i < 2; i++) { + if (ide_boards[i] != NULL) + ide_board_reset(i); + } } /* Close a standalone IDE unit. */ @@ -3138,14 +2919,11 @@ ide_close(UNUSED(void *priv)) { ide_log("Closing IDE...\n"); - if (ide_boards[0] != NULL) { - ide_board_close(0); - ide_boards[0] = NULL; - } - - if (ide_boards[1] != NULL) { - ide_board_close(1); - ide_boards[1] = NULL; + for (uint8_t i = 0; i < 2; i++) { + if (ide_boards[i] != NULL) { + ide_board_close(i); + ide_boards[i] = NULL; + } } } diff --git a/src/disk/hdc_xtide.c b/src/disk/hdc_xtide.c index 91bf5a2e3..dfe5931f1 100644 --- a/src/disk/hdc_xtide.c +++ b/src/disk/hdc_xtide.c @@ -40,6 +40,7 @@ #include <86box/io.h> #include <86box/mem.h> #include <86box/rom.h> +#include <86box/timer.h> #include <86box/device.h> #include <86box/hdc.h> #include <86box/hdc_ide.h> diff --git a/src/disk/hdd.c b/src/disk/hdd.c index 5d9517747..3bb15c241 100644 --- a/src/disk/hdd.c +++ b/src/disk/hdd.c @@ -210,7 +210,7 @@ hdd_readahead_update(hard_disk_t *hdd) uint64_t elapsed_cycles; double elapsed_us; double seek_time; - uint32_t max_read_ahead; + int32_t max_read_ahead; uint32_t space_needed; hdd_cache_t *cache = &hdd->cache; @@ -224,7 +224,7 @@ hdd_readahead_update(hard_disk_t *hdd) seek_time = 0.0; - for (uint32_t i = 0; i < max_read_ahead; i++) { + for (int32_t i = 0; i < max_read_ahead; i++) { seek_time += hdd_seek_get_time(hdd, segment->ra_addr, HDD_OP_READ, 1, elapsed_us - seek_time); if (seek_time > elapsed_us) break; diff --git a/src/disk/mo.c b/src/disk/mo.c index 7d2a5c9e0..ad781a8ac 100644 --- a/src/disk/mo.c +++ b/src/disk/mo.c @@ -49,6 +49,8 @@ # include #endif +#define IDE_ATAPI_IS_EARLY id->sc->pad0 + mo_drive_t mo_drives[MO_NUM]; /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ @@ -443,11 +445,11 @@ mo_init(mo_t *dev) dev->drv->bus_mode |= 1; mo_log("MO %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); if (dev->drv->bus_type < MO_BUS_SCSI) { - dev->phase = 1; - dev->request_length = 0xEB14; + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; } - dev->status = READY_STAT | DSC_STAT; - dev->pos = 0; + dev->tf->status = READY_STAT | DSC_STAT; + dev->tf->pos = 0; dev->packet_status = PHASE_NONE; mo_sense_key = mo_asc = mo_ascq = dev->unit_attention = 0; } @@ -477,36 +479,9 @@ mo_current_mode(mo_t *dev) if (!mo_supports_pio(dev) && mo_supports_dma(dev)) return 2; if (mo_supports_pio(dev) && mo_supports_dma(dev)) { - mo_log("MO %i: Drive supports both, setting to %s\n", dev->id, (dev->features & 1) ? "DMA" : "PIO"); - return (dev->features & 1) ? 2 : 1; - } - - return 0; -} - -/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ -int -mo_atapi_phase_to_scsi(mo_t *dev) -{ - if (dev->status & 8) { - switch (dev->phase & 3) { - case 0: - return 0; - case 1: - return 2; - case 2: - return 1; - case 3: - return 7; - - default: - break; - } - } else { - if ((dev->phase & 3) == 3) - return 3; - else - return 4; + mo_log("MO %i: Drive supports both, setting to %s\n", dev->id, + (dev->tf->features & 1) ? "DMA" : "PIO"); + return (dev->tf->features & 1) ? 2 : 1; } return 0; @@ -622,7 +597,7 @@ mo_update_request_length(mo_t *dev, int len, int block_len) int bt; int min_len = 0; - dev->max_transfer_len = dev->request_length; + dev->max_transfer_len = dev->tf->request_length; /* For media access commands, make sure the requested DRQ length matches the block length. */ switch (dev->current_cdb[0]) { @@ -666,9 +641,9 @@ mo_update_request_length(mo_t *dev, int len, int block_len) dev->max_transfer_len = 65534; if ((len <= dev->max_transfer_len) && (len >= min_len)) - dev->request_length = dev->max_transfer_len = len; + dev->tf->request_length = dev->max_transfer_len = len; else if (len > dev->max_transfer_len) - dev->request_length = dev->max_transfer_len; + dev->tf->request_length = dev->max_transfer_len; return; } @@ -699,9 +674,9 @@ mo_command_common(mo_t *dev) double bytes_per_second; double period; - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; + dev->tf->status = BUSY_STAT; + dev->tf->phase = 1; + dev->tf->pos = 0; if (dev->packet_status == PHASE_COMPLETE) dev->callback = 0.0; else { @@ -763,8 +738,8 @@ static void mo_data_command_finish(mo_t *dev, int len, int block_len, int alloc_len, int direction) { mo_log("MO %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); - dev->pos = 0; + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->tf->request_length); + dev->tf->pos = 0; if (alloc_len >= 0) { if (alloc_len < len) len = alloc_len; @@ -793,7 +768,8 @@ mo_data_command_finish(mo_t *dev, int len, int block_len, int alloc_len, int dir } mo_log("MO %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); + dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, + dev->tf->phase); } static void @@ -818,14 +794,14 @@ static void mo_cmd_error(mo_t *dev) { mo_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = ((mo_sense_key & 0xf) << 4) | ABRT_ERR; + dev->tf->error = ((mo_sense_key & 0xf) << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * MO_TIME; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; + dev->packet_status = PHASE_ERROR; + dev->callback = 50.0 * MO_TIME; mo_set_callback(dev); ui_sb_update_icon(SB_MO | dev->id, 0); mo_log("MO %i: [%02X] ERROR: %02X/%02X/%02X\n", dev->id, dev->current_cdb[0], mo_sense_key, mo_asc, mo_ascq); @@ -835,14 +811,14 @@ static void mo_unit_attention(mo_t *dev) { mo_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * MO_TIME; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; + dev->packet_status = PHASE_ERROR; + dev->callback = 50.0 * MO_TIME; mo_set_callback(dev); ui_sb_update_icon(SB_MO | dev->id, 0); mo_log("MO %i: UNIT ATTENTION\n", dev->id); @@ -928,7 +904,7 @@ mo_invalid_field(mo_t *dev) mo_asc = ASC_INV_FIELD_IN_CMD_PACKET; mo_ascq = 0; mo_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } static void @@ -938,7 +914,7 @@ mo_invalid_field_pl(mo_t *dev) mo_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; mo_ascq = 0; mo_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } static int @@ -1112,7 +1088,8 @@ mo_pre_execution_check(mo_t *dev, uint8_t *cdb) int ready = 0; if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { - mo_log("MO %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, ((dev->request_length >> 5) & 7)); + mo_log("MO %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, + ((dev->tf->request_length >> 5) & 7)); mo_invalid_lun(dev); return 0; } @@ -1202,14 +1179,14 @@ mo_reset(scsi_common_t *sc) mo_t *dev = (mo_t *) sc; mo_rezero(dev); - dev->status = 0; - dev->callback = 0.0; + dev->tf->status = 0; + dev->callback = 0.0; mo_set_callback(dev); - dev->phase = 1; - dev->request_length = 0xEB14; - dev->packet_status = PHASE_NONE; - dev->unit_attention = 0; - dev->cur_lun = SCSI_LUN_USE_CDB; + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; + dev->packet_status = PHASE_NONE; + dev->unit_attention = 0; + dev->cur_lun = SCSI_LUN_USE_CDB; } static void @@ -1302,11 +1279,11 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type == MO_BUS_SCSI) { - BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; - dev->status &= ~ERR_STAT; + BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; + dev->tf->status &= ~ERR_STAT; } else { - BufLen = &blen; - dev->error = 0; + BufLen = &blen; + dev->tf->error = 0; } dev->packet_len = 0; @@ -1319,7 +1296,7 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) if (cdb[0] != 0) { mo_log("MO %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", dev->id, cdb[0], mo_sense_key, mo_asc, mo_ascq, dev->unit_attention); - mo_log("MO %i: Request length: %04X\n", dev->id, dev->request_length); + mo_log("MO %i: Request length: %04X\n", dev->id, dev->tf->request_length); mo_log("MO %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], @@ -1857,10 +1834,10 @@ mo_command(scsi_common_t *sc, uint8_t *cdb) } #if 0 - mo_log("MO %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length); + mo_log("MO %i: Phase: %02X, request length: %i\n", dev->id, dev->tf->phase, dev->tf->request_length); #endif - if (mo_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) + if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) mo_buf_free(dev); } @@ -2099,6 +2076,9 @@ mo_drive_reset(int c) dev->cur_lun = SCSI_LUN_USE_CDB; if (mo_drives[c].bus_type == MO_BUS_SCSI) { + if (!dev->tf) + dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); + /* SCSI MO, attach to the SCSI bus. */ sd = &scsi_devices[scsi_bus][scsi_id]; @@ -2117,6 +2097,8 @@ mo_drive_reset(int c) that's not attached to anything. */ if (id) { id->sc = (scsi_common_t *) dev; + dev->tf = id->tf; + IDE_ATAPI_IS_EARLY = 0; id->get_max = mo_get_max; id->get_timings = mo_get_timings; id->identify = mo_identify; @@ -2203,6 +2185,9 @@ mo_close(void) if (dev) { mo_disk_unload(dev); + if (dev->tf) + free(dev->tf); + free(dev); mo_drives[c].priv = NULL; } diff --git a/src/disk/zip.c b/src/disk/zip.c index c9a4fce18..c498383e8 100644 --- a/src/disk/zip.c +++ b/src/disk/zip.c @@ -36,6 +36,8 @@ #include <86box/hdc_ide.h> #include <86box/zip.h> +#define IDE_ATAPI_IS_EARLY id->sc->pad0 + zip_drive_t zip_drives[ZIP_NUM]; /* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ @@ -588,11 +590,11 @@ zip_init(zip_t *dev) dev->drv->bus_mode |= 1; zip_log("ZIP %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); if (dev->drv->bus_type < ZIP_BUS_SCSI) { - dev->phase = 1; - dev->request_length = 0xEB14; + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; } - dev->status = READY_STAT | DSC_STAT; - dev->pos = 0; + dev->tf->status = READY_STAT | DSC_STAT; + dev->tf->pos = 0; dev->packet_status = PHASE_NONE; zip_sense_key = zip_asc = zip_ascq = dev->unit_attention = 0; } @@ -622,36 +624,9 @@ zip_current_mode(zip_t *dev) if (!zip_supports_pio(dev) && zip_supports_dma(dev)) return 2; if (zip_supports_pio(dev) && zip_supports_dma(dev)) { - zip_log("ZIP %i: Drive supports both, setting to %s\n", dev->id, (dev->features & 1) ? "DMA" : "PIO"); - return (dev->features & 1) ? 2 : 1; - } - - return 0; -} - -/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ -int -zip_atapi_phase_to_scsi(zip_t *dev) -{ - if (dev->status & 8) { - switch (dev->phase & 3) { - case 0: - return 0; - case 1: - return 2; - case 2: - return 1; - case 3: - return 7; - - default: - break; - } - } else { - if ((dev->phase & 3) == 3) - return 3; - else - return 4; + zip_log("ZIP %i: Drive supports both, setting to %s\n", dev->id, + (dev->tf->features & 1) ? "DMA" : "PIO"); + return (dev->tf->features & 1) ? 2 : 1; } return 0; @@ -791,7 +766,7 @@ zip_update_request_length(zip_t *dev, int len, int block_len) int bt; int min_len = 0; - dev->max_transfer_len = dev->request_length; + dev->max_transfer_len = dev->tf->request_length; /* For media access commands, make sure the requested DRQ length matches the block length. */ switch (dev->current_cdb[0]) { @@ -835,9 +810,9 @@ zip_update_request_length(zip_t *dev, int len, int block_len) dev->max_transfer_len = 65534; if ((len <= dev->max_transfer_len) && (len >= min_len)) - dev->request_length = dev->max_transfer_len = len; + dev->tf->request_length = dev->max_transfer_len = len; else if (len > dev->max_transfer_len) - dev->request_length = dev->max_transfer_len; + dev->tf->request_length = dev->max_transfer_len; return; } @@ -868,9 +843,9 @@ zip_command_common(zip_t *dev) double bytes_per_second; double period; - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; + dev->tf->status = BUSY_STAT; + dev->tf->phase = 1; + dev->tf->pos = 0; if (dev->packet_status == PHASE_COMPLETE) dev->callback = 0.0; else { @@ -932,8 +907,8 @@ static void zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int direction) { zip_log("ZIP %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); - dev->pos = 0; + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->tf->request_length); + dev->tf->pos = 0; if (alloc_len >= 0) { if (alloc_len < len) len = alloc_len; @@ -962,7 +937,8 @@ zip_data_command_finish(zip_t *dev, int len, int block_len, int alloc_len, int d } zip_log("ZIP %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); + dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, + dev->tf->phase); } static void @@ -987,12 +963,12 @@ static void zip_cmd_error(zip_t *dev) { zip_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR; + dev->tf->error = ((zip_sense_key & 0xf) << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; dev->packet_status = PHASE_ERROR; dev->callback = 50.0 * ZIP_TIME; zip_set_callback(dev); @@ -1004,12 +980,12 @@ static void zip_unit_attention(zip_t *dev) { zip_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; dev->packet_status = PHASE_ERROR; dev->callback = 50.0 * ZIP_TIME; zip_set_callback(dev); @@ -1097,7 +1073,7 @@ zip_invalid_field(zip_t *dev) zip_asc = ASC_INV_FIELD_IN_CMD_PACKET; zip_ascq = 0; zip_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } static void @@ -1107,7 +1083,7 @@ zip_invalid_field_pl(zip_t *dev) zip_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; zip_ascq = 0; zip_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } static void @@ -1184,7 +1160,8 @@ zip_pre_execution_check(zip_t *dev, uint8_t *cdb) int ready = 0; if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { - zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, ((dev->request_length >> 5) & 7)); + zip_log("ZIP %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", dev->id, + ((dev->tf->request_length >> 5) & 7)); zip_invalid_lun(dev); return 0; } @@ -1274,14 +1251,14 @@ zip_reset(scsi_common_t *sc) zip_t *dev = (zip_t *) sc; zip_rezero(dev); - dev->status = 0; - dev->callback = 0.0; + dev->tf->status = 0; + dev->callback = 0.0; zip_set_callback(dev); - dev->phase = 1; - dev->request_length = 0xEB14; - dev->packet_status = PHASE_NONE; - dev->unit_attention = 0; - dev->cur_lun = SCSI_LUN_USE_CDB; + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; + dev->packet_status = PHASE_NONE; + dev->unit_attention = 0; + dev->cur_lun = SCSI_LUN_USE_CDB; } static void @@ -1373,11 +1350,11 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) uint8_t scsi_id = dev->drv->scsi_device_id & 0x0f; if (dev->drv->bus_type == ZIP_BUS_SCSI) { - BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; - dev->status &= ~ERR_STAT; + BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; + dev->tf->status &= ~ERR_STAT; } else { - BufLen = &blen; - dev->error = 0; + BufLen = &blen; + dev->tf->error = 0; } dev->packet_len = 0; @@ -1388,7 +1365,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) if (cdb[0] != 0) { zip_log("ZIP %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", dev->id, cdb[0], zip_sense_key, zip_asc, zip_ascq, dev->unit_attention); - zip_log("ZIP %i: Request length: %04X\n", dev->id, dev->request_length); + zip_log("ZIP %i: Request length: %04X\n", dev->id, dev->tf->request_length); zip_log("ZIP %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], @@ -1465,8 +1442,9 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) break; case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ + /* If there's a unit attention condition and there's a buffered not + ready, a standalone REQUEST SENSE should forget about the not + ready, and report unit attention straight away. */ zip_set_phase(dev, SCSI_PHASE_DATA_IN); max_len = cdb[4]; @@ -1507,7 +1485,14 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) switch (cdb[0]) { case GPCMD_READ_6: dev->sector_len = cdb[4]; - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + /* + For READ (6) and WRITE (6), a length of 0 indicates a + transfer of 256 sectors. + */ + if (dev->sector_len == 0) + dev->sector_len = 256; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | + (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; case GPCMD_READ_10: @@ -1516,14 +1501,21 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) zip_log("ZIP %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); break; case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; default: break; } + if (dev->sector_pos >= dev->drv->medium_size) { + zip_lba_out_of_range(dev); + return; + } + if (!dev->sector_len) { zip_set_phase(dev, SCSI_PHASE_STATUS); /* zip_log("ZIP %i: All done - callback set\n", dev->id); */ @@ -1534,9 +1526,13 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) } max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're reading all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ + /* + If we're reading all blocks in one go for DMA, why not also for + PIO, it should NOT matter anyway, this step should be identical + and only the way the read dat is transferred to the host should + be different. + */ + dev->requested_blocks = max_len; dev->packet_len = max_len * alloc_length; zip_buf_alloc(dev, dev->packet_len); @@ -1558,10 +1554,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) zip_data_command_finish(dev, alloc_length, 512, alloc_length, 0); - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_ZIP | dev->id, 1); - else - ui_sb_update_icon(SB_ZIP | dev->id, 0); + ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE); return; case GPCMD_VERIFY_6: @@ -1590,9 +1583,14 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) case GPCMD_VERIFY_6: case GPCMD_WRITE_6: dev->sector_len = cdb[4]; + /* + For READ (6) and WRITE (6), a length of 0 indicates a + transfer of 256 sectors. + */ if (dev->sector_len == 0) - dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */ - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + dev->sector_len = 256; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | + (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); break; case GPCMD_VERIFY_10: case GPCMD_WRITE_10: @@ -1604,17 +1602,17 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) case GPCMD_VERIFY_12: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; default: break; } - if ((dev->sector_pos >= dev->drv->medium_size) /* || - ((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)*/ - ) { + if (dev->sector_pos >= dev->drv->medium_size) { zip_lba_out_of_range(dev); return; } @@ -1629,9 +1627,13 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) } max_len = dev->sector_len; - dev->requested_blocks = max_len; /* If we're writing all blocks in one go for DMA, why not also for PIO, it should NOT - matter anyway, this step should be identical and only the way the read dat is - transferred to the host should be different. */ + /* + If we're writing all blocks in one go for DMA, why not also for + PIO, it should NOT matter anyway, this step should be identical + and only the way the read dat is transferred to the host should + be different. + */ + dev->requested_blocks = max_len; dev->packet_len = max_len * alloc_length; zip_buf_alloc(dev, dev->packet_len); @@ -1643,10 +1645,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) zip_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_ZIP | dev->id, 1); - else - ui_sb_update_icon(SB_ZIP | dev->id, 0); + ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE); return; case GPCMD_WRITE_SAME_10: @@ -1665,9 +1664,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) dev->sector_len = (cdb[7] << 8) | cdb[8]; dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - if ((dev->sector_pos >= dev->drv->medium_size) /* || - ((dev->sector_pos + dev->sector_len - 1) >= dev->drv->medium_size)*/ - ) { + if (dev->sector_pos >= dev->drv->medium_size) { zip_lba_out_of_range(dev); return; } @@ -1693,10 +1690,7 @@ zip_command(scsi_common_t *sc, uint8_t *cdb) zip_data_command_finish(dev, 512, 512, alloc_length, 1); - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_ZIP | dev->id, 1); - else - ui_sb_update_icon(SB_ZIP | dev->id, 0); + ui_sb_update_icon(SB_ZIP | dev->id, dev->packet_status != PHASE_COMPLETE); return; case GPCMD_MODE_SENSE_6: @@ -2034,10 +2028,10 @@ atapi_out: } #if 0 - zip_log("ZIP %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length); + zip_log("ZIP %i: Phase: %02X, request length: %i\n", dev->id, dev->tf->phase, dev->tf->request_length); #endif - if (zip_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) + if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) zip_buf_free(dev); } @@ -2321,6 +2315,9 @@ zip_drive_reset(int c) dev->cur_lun = SCSI_LUN_USE_CDB; if (zip_drives[c].bus_type == ZIP_BUS_SCSI) { + if (!dev->tf) + dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); + /* SCSI ZIP, attach to the SCSI bus. */ sd = &scsi_devices[scsi_bus][scsi_id]; @@ -2339,6 +2336,8 @@ zip_drive_reset(int c) that's not attached to anything. */ if (id) { id->sc = (scsi_common_t *) dev; + dev->tf = id->tf; + IDE_ATAPI_IS_EARLY = 0; id->get_max = zip_get_max; id->get_timings = zip_get_timings; id->identify = zip_identify; @@ -2425,6 +2424,9 @@ zip_close(void) if (dev) { zip_disk_unload(dev); + if (dev->tf) + free(dev->tf); + free(dev); zip_drives[c].priv = NULL; } diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index a8f4ac7f2..ae2ea260c 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -213,6 +213,9 @@ extern uint16_t get_last_addr(void); extern void sub_cycles(int c); extern void resub_cycles(int old_cycles); +extern void ack_pause(void); +extern void do_pause(int p); + extern double isa_timing; extern int io_delay; extern int framecountx; diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index b536772b9..d188c9243 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -86,7 +86,10 @@ enum CDROM_TYPE_CHINON_CDS431_H42, CDROM_TYPE_DEC_RRD45_0436, CDROM_TYPE_MATSHITA_501_10b, + CDROM_TYPE_NEC_25_10a, CDROM_TYPE_NEC_38_103, + CDROM_TYPE_NEC_75_103, + CDROM_TYPE_NEC_77_106, CDROM_TYPE_NEC_211_100, CDROM_TYPE_NEC_464_105, CDROM_TYPE_SONY_CDU541_10i, @@ -121,47 +124,50 @@ static const struct const char *internal_name; const int bus_type; } cdrom_drive_types[] = { - { "86BOX", "CD-ROM", "1.00", "86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_BOTH }, /*1*/ - { "AZT", "CDA46802I", "1.15", "AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE }, /*2*/ - { "BTC", "CD-ROM BCD36XH", "U1.0", "BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE }, /*3*/ - { "GOLDSTAR", "CRD-8160B", "3.14", "GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE }, /*4*/ - { "HITACHI", "CDR-8130", "0020", "HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE }, /*5*/ - { "KENWOOD", "CD-ROM UCR-421", "208E", "KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE }, /*6*/ - { "MATSHITA", "CD-ROM CR-587", "7S13", "MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE }, /*7*/ - { "MATSHITA", "CD-ROM CR-588", "LS15", "MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE }, /*8*/ - { "MATSHITA", "CR-571", "1.0e", "MATSHITA CR-571 1.0e", "MATSHITA_CR-571_1.0e", BUS_TYPE_IDE }, /*9*/ - { "MATSHITA", "CR-572", "1.0j", "MATSHITA CR-572 1.0j", "MATSHITA_CR-572_1.0j", BUS_TYPE_IDE }, /*10*/ - { "MITSUMI", "CRMC-FX4820T", "D02A", "MITSUMI CRMC-FX4820T D02A", "MITSUMI_CRMC-FX4820T_D02A", BUS_TYPE_IDE }, /*11*/ - { "NEC", "CD-ROM DRIVE:260", "1.00", "NEC CD-ROM DRIVE:260 1.00", "NEC_CD-ROM_DRIVE260_1.00", BUS_TYPE_IDE }, /*12*/ - { "NEC", "CD-ROM DRIVE:260", "1.01", "NEC CD-ROM DRIVE:260 1.01", "NEC_CD-ROM_DRIVE260_1.01", BUS_TYPE_IDE }, /*13*/ - { "NEC", "CD-ROM DRIVE:273", "4.20", "NEC CD-ROM DRIVE:273 4.20", "NEC_CD-ROM_DRIVE273_4.20", BUS_TYPE_IDE }, /*14*/ - { "NEC", "CD-ROM DRIVE:280", "1.05", "NEC CD-ROM DRIVE:280 1.05", "NEC_CD-ROM_DRIVE280_1.05", BUS_TYPE_IDE }, /*15*/ - { "NEC", "CD-ROM DRIVE:280", "3.08", "NEC CD-ROM DRIVE:280 3.08", "NEC_CD-ROM_DRIVE280_3.08", BUS_TYPE_IDE }, /*16*/ - { "PHILIPS", "CD-ROM PCA403CD", "U31P", "PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE }, /*17*/ - { "SONY", "CD-ROM CDU76", "1.0i", "SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE }, /*18*/ - { "SONY", "CD-ROM CDU311", "3.0h", "SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE }, /*19*/ - { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE }, /*20*/ - { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE }, /*21*/ - { "CHINON", "CD-ROM CDS-431", "H42 ", "CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI }, /*22*/ - { "DEC", "RRD45 (C) DEC", "0436", "DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI }, /*23*/ - { "MATSHITA", "CD-ROM CR-501", "1.0b", "MATSHITA CD-ROM CR-501 1.0b", "MATSHITA_CD-ROM_CR-501_1.0b", BUS_TYPE_SCSI }, /*24*/ - { "NEC", "CD-ROM DRIVE:38", "1.03", "NEC CD-ROM DRIVE:38 1.03", "NEC_CD-ROM_DRIVE38_1.03", BUS_TYPE_SCSI }, /*25*/ - { "NEC", "CD-ROM DRIVE:211", "1.00", "NEC CD-ROM DRIVE:211 1.00", "NEC_CD-ROM_DRIVE211_1.00", BUS_TYPE_SCSI }, /*26*/ - { "NEC", "CD-ROM DRIVE:464", "1.05", "NEC CD-ROM DRIVE:464 1.05", "NEC_CD-ROM_DRIVE464_1.05", BUS_TYPE_SCSI }, /*27*/ - { "SONY", "CD-ROM CDU-541", "1.0i", "SONY CD-ROM CDU-541 1.0i", "SONY_CD-ROM_CDU-541_1.0i", BUS_TYPE_SCSI }, /*28*/ - { "SONY", "CD-ROM CDU-561", "1.8k", "SONY CD-ROM CDU-561 1.8k", "SONY_CD-ROM_CDU-561_1.8k", BUS_TYPE_SCSI }, /*29*/ - { "SONY", "CD-ROM CDU-76S", "1.00", "SONY CD-ROM CDU-76S 1.00", "SONY_CD-ROM_CDU-76S_1.00", BUS_TYPE_SCSI }, /*30*/ - { "PHILIPS", "CDD2600", "1.07", "PHILIPS CDD2600 1.07", "PHILIPS_CDD2600_1.07", BUS_TYPE_SCSI }, /*31*/ - { "PIONEER", "CD-ROM DRM-604X", "2403", "PIONEER CD-ROM DRM-604X 2403", "PIONEER_CD-ROM_DRM-604X_2403", BUS_TYPE_SCSI }, /*32*/ - { "PLEXTOR", "CD-ROM PX-32TS", "1.03", "PLEXTOR CD-ROM PX-32TS 1.03", "PLEXTOR_CD-ROM_PX-32TS_1.03", BUS_TYPE_SCSI }, /*33*/ - { "TEAC", "CD 50", "1.00", "TEAC CD 50 1.00", "TEAC_CD_50_1.00", BUS_TYPE_SCSI }, /*34*/ - { "TEAC", "CD-ROM R55S", "1.0R", "TEAC CD-ROM R55S 1.0R", "TEAC_CD-ROM_R55S_1.0R", BUS_TYPE_SCSI }, /*35*/ - { "TEXEL", "CD-ROM DM-XX24", "1.00", "TEXEL CD-ROM DM-XX24 1.00", "TEXEL_CD-ROM_DM-XX24_1.00", BUS_TYPE_SCSI }, /*36*/ - { "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "TOSHIBA CD-ROM DRIVE:XM 3433", "TOSHIBA_CD-ROM_DRIVEXM_3433", BUS_TYPE_SCSI }, /*37*/ - { "TOSHIBA", "CD-ROM XM-3201B", "3232", "TOSHIBA CD-ROM XM-3201B 3232", "TOSHIBA_CD-ROM_XM-3201B_3232", BUS_TYPE_SCSI }, /*38*/ - { "TOSHIBA", "CD-ROM XM-3301TA", "0272", "TOSHIBA CD-ROM XM-3301TA 0272", "TOSHIBA_CD-ROM_XM-3301TA_0272", BUS_TYPE_SCSI }, /*39*/ - { "TOSHIBA", "CD-ROM XM-5701TA", "3136", "TOSHIBA CD-ROM XM-5701TA 3136", "TOSHIBA_CD-ROM_XM-5701TA_3136", BUS_TYPE_SCSI }, /*40*/ - { "TOSHIBA", "DVD-ROM SD-M1401", "1008", "TOSHIBA DVD-ROM SD-M1401 1008", "TOSHIBA_DVD-ROM_SD-M1401_1008", BUS_TYPE_SCSI }, /*41*/ + { "86BOX", "CD-ROM", "1.00", "86BOX CD-ROM 1.00", "86BOX_CD-ROM_1.00", BUS_TYPE_BOTH }, + { "AZT", "CDA46802I", "1.15", "AZT CDA46802I 1.15", "AZT_CDA46802I_1.15", BUS_TYPE_IDE }, + { "BTC", "CD-ROM BCD36XH", "U1.0", "BTC CD-ROM BCD36XH U1.0", "BTC_CD-ROM_BCD36XH_U1.0", BUS_TYPE_IDE }, + { "GOLDSTAR", "CRD-8160B", "3.14", "GOLDSTAR CRD-8160B 3.14", "GOLDSTAR_CRD-8160B_3.14", BUS_TYPE_IDE }, + { "HITACHI", "CDR-8130", "0020", "HITACHI CDR-8130 0020", "HITACHI_CDR-8130_0020", BUS_TYPE_IDE }, + { "KENWOOD", "CD-ROM UCR-421", "208E", "KENWOOD CD-ROM UCR-421 208E", "KENWOOD_CD-ROM_UCR-421_208E", BUS_TYPE_IDE }, + { "MATSHITA", "CD-ROM CR-587", "7S13", "MATSHITA CD-ROM CR-587 7S13", "MATSHITA_CD-ROM_CR-587_7S13", BUS_TYPE_IDE }, + { "MATSHITA", "CD-ROM CR-588", "LS15", "MATSHITA CD-ROM CR-588 LS15", "MATSHITA_CD-ROM_CR-588_LS15", BUS_TYPE_IDE }, + { "MATSHITA", "CR-571", "1.0e", "MATSHITA CR-571 1.0e", "MATSHITA_CR-571_1.0e", BUS_TYPE_IDE }, + { "MATSHITA", "CR-572", "1.0j", "MATSHITA CR-572 1.0j", "MATSHITA_CR-572_1.0j", BUS_TYPE_IDE }, + { "MITSUMI", "CRMC-FX4820T", "D02A", "MITSUMI CRMC-FX4820T D02A", "MITSUMI_CRMC-FX4820T_D02A", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:260", "1.00", "NEC CD-ROM DRIVE:260 1.00", "NEC_CD-ROM_DRIVE260_1.00", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:260", "1.01", "NEC CD-ROM DRIVE:260 1.01", "NEC_CD-ROM_DRIVE260_1.01", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:273", "4.20", "NEC CD-ROM DRIVE:273 4.20", "NEC_CD-ROM_DRIVE273_4.20", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:280", "1.05", "NEC CD-ROM DRIVE:280 1.05", "NEC_CD-ROM_DRIVE280_1.05", BUS_TYPE_IDE }, + { "NEC", "CD-ROM DRIVE:280", "3.08", "NEC CD-ROM DRIVE:280 3.08", "NEC_CD-ROM_DRIVE280_3.08", BUS_TYPE_IDE }, + { "PHILIPS", "CD-ROM PCA403CD", "U31P", "PHILIPS CD-ROM PCA403CD U31P", "PHILIPS_CD-ROM_PCA403CD_U31P", BUS_TYPE_IDE }, + { "SONY", "CD-ROM CDU76", "1.0i", "SONY CD-ROM CDU76 1.0i", "SONY_CD-ROM_CDU76_1.0i", BUS_TYPE_IDE }, + { "SONY", "CD-ROM CDU311", "3.0h", "SONY CD-ROM CDU311 3.0h", "SONY_CD-ROM_CDU311_3.0h", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-5302TA", "0305", "TOSHIBA CD-ROM XM-5302TA 0305", "TOSHIBA_CD-ROM_XM-5302TA_0305", BUS_TYPE_IDE }, + { "TOSHIBA", "CD-ROM XM-5702B", "TA70", "TOSHIBA CD-ROM XM-5702B TA70", "TOSHIBA_CD-ROM_XM-5702B_TA70", BUS_TYPE_IDE }, + { "CHINON", "CD-ROM CDS-431", "H42 ", "CHINON CD-ROM CDS-431 H42", "CHINON_CD-ROM_CDS-431_H42", BUS_TYPE_SCSI }, + { "DEC", "RRD45 (C) DEC", "0436", "DEC RRD45 0436", "DEC_RRD45_0436", BUS_TYPE_SCSI }, + { "MATSHITA", "CD-ROM CR-501", "1.0b", "MATSHITA CD-ROM CR-501 1.0b", "MATSHITA_CD-ROM_CR-501_1.0b", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:25", "1.0a", "NEC CD-ROM DRIVE:25 1.0a", "NEC_CD-ROM_DRIVE25_1.0a", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:38", "1.00", "NEC CD-ROM DRIVE:38 1.00", "NEC_CD-ROM_DRIVE38_1.00", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:75", "1.03", "NEC CD-ROM DRIVE:75 1.03", "NEC_CD-ROM_DRIVE75_1.03", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:77", "1.06", "NEC CD-ROM DRIVE:77 1.06", "NEC_CD-ROM_DRIVE77_1.06", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:211", "1.00", "NEC CD-ROM DRIVE:211 1.00", "NEC_CD-ROM_DRIVE211_1.00", BUS_TYPE_SCSI }, + { "NEC", "CD-ROM DRIVE:464", "1.05", "NEC CD-ROM DRIVE:464 1.05", "NEC_CD-ROM_DRIVE464_1.05", BUS_TYPE_SCSI }, + { "SONY", "CD-ROM CDU-541", "1.0i", "SONY CD-ROM CDU-541 1.0i", "SONY_CD-ROM_CDU-541_1.0i", BUS_TYPE_SCSI }, + { "SONY", "CD-ROM CDU-561", "1.8k", "SONY CD-ROM CDU-561 1.8k", "SONY_CD-ROM_CDU-561_1.8k", BUS_TYPE_SCSI }, + { "SONY", "CD-ROM CDU-76S", "1.00", "SONY CD-ROM CDU-76S 1.00", "SONY_CD-ROM_CDU-76S_1.00", BUS_TYPE_SCSI }, + { "PHILIPS", "CDD2600", "1.07", "PHILIPS CDD2600 1.07", "PHILIPS_CDD2600_1.07", BUS_TYPE_SCSI }, + { "PIONEER", "CD-ROM DRM-604X", "2403", "PIONEER CD-ROM DRM-604X 2403", "PIONEER_CD-ROM_DRM-604X_2403", BUS_TYPE_SCSI }, + { "PLEXTOR", "CD-ROM PX-32TS", "1.03", "PLEXTOR CD-ROM PX-32TS 1.03", "PLEXTOR_CD-ROM_PX-32TS_1.03", BUS_TYPE_SCSI }, + { "TEAC", "CD 50", "1.00", "TEAC CD 50 1.00", "TEAC_CD_50_1.00", BUS_TYPE_SCSI }, + { "TEAC", "CD-ROM R55S", "1.0R", "TEAC CD-ROM R55S 1.0R", "TEAC_CD-ROM_R55S_1.0R", BUS_TYPE_SCSI }, + { "TEXEL", "CD-ROM DM-XX24", "1.00", "TEXEL CD-ROM DM-XX24 1.00", "TEXEL_CD-ROM_DM-XX24_1.00", BUS_TYPE_SCSI }, + { "TOSHIBA", "CD-ROM DRIVE:XM", "3433", "TOSHIBA CD-ROM DRIVE:XM 3433", "TOSHIBA_CD-ROM_DRIVEXM_3433", BUS_TYPE_SCSI }, + { "TOSHIBA", "CD-ROM XM-3201B", "3232", "TOSHIBA CD-ROM XM-3201B 3232", "TOSHIBA_CD-ROM_XM-3201B_3232", BUS_TYPE_SCSI }, + { "TOSHIBA", "CD-ROM XM-3301TA", "0272", "TOSHIBA CD-ROM XM-3301TA 0272", "TOSHIBA_CD-ROM_XM-3301TA_0272", BUS_TYPE_SCSI }, + { "TOSHIBA", "CD-ROM XM-5701TA", "3136", "TOSHIBA CD-ROM XM-5701TA 3136", "TOSHIBA_CD-ROM_XM-5701TA_3136", BUS_TYPE_SCSI }, + { "TOSHIBA", "DVD-ROM SD-M1401", "1008", "TOSHIBA DVD-ROM SD-M1401 1008", "TOSHIBA_DVD-ROM_SD-M1401_1008", BUS_TYPE_SCSI }, { "", "", "", "", "", BUS_TYPE_NONE }, }; diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index 37b11da85..b1bff13b3 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -41,13 +41,46 @@ enum { IDE_ATAPI }; -#ifdef SCSI_DEVICE_H +typedef struct ide_tf_s { + union { + uint8_t cylprecomp; + uint8_t features; + }; + union { + uint8_t secount; + uint8_t phase; + }; + union { + uint16_t cylinder; + uint16_t request_length; + }; + union { + uint8_t atastat; + uint8_t status; + }; + uint8_t error; + uint16_t pad; + uint32_t pos; +} ide_tf_t; + +#ifdef _TIMER_H_ typedef struct ide_s { - uint8_t selected; +#ifdef ANCIENT_CODE + /* Task file. */ + uint8_t cylprecomp; + uint8_t secount; + uint16_t cylinder; uint8_t atastat; uint8_t error; + uint16_t pad; + uint32_t pos; +#endif + + /* The rest. */ + uint8_t selected; uint8_t command; - uint8_t fdisk; + uint8_t head; + uint8_t sector; int type; int board; int irqstat; @@ -56,18 +89,12 @@ typedef struct ide_s { int blockcount; int hdd_num; int channel; - int pos; int sector_pos; int lba; int reset; int mdma_mode; int do_initial_read; - uint32_t secount; - uint32_t sector; - uint32_t cylinder; - uint32_t head; uint32_t drive; - uint32_t cylprecomp; uint32_t cfg_spt; uint32_t cfg_hpc; uint32_t lba_addr; @@ -80,11 +107,19 @@ typedef struct ide_s { pc_timer_t timer; + /* Task file. */ + ide_tf_t * tf; + /* Stuff mostly used by ATAPI */ +#ifdef SCSI_DEVICE_H scsi_common_t *sc; +#else + void * sc; +#endif int interrupt_drq; double pending_delay; +#ifdef SCSI_DEVICE_H int (*get_max)(int ide_has_dma, int type); int (*get_timings)(int ide_has_dma, int type); void (*identify)(struct ide_s *ide, int ide_has_dma); @@ -94,10 +129,22 @@ typedef struct ide_s { uint8_t (*phase_data_out)(scsi_common_t *sc); void (*command_stop)(scsi_common_t *sc); void (*bus_master_error)(scsi_common_t *sc); +#else + void * get_max; + void * get_timings; + void * identify; + void * stop; + void * device_reset; + void * phase_data_out; + void * command_stop; + void * bus_master_error; +#endif } ide_t; +#ifdef EMU_HDC_H extern ide_t *ide_drives[IDE_NUM]; #endif +#endif /* Type: 0 = PIO, @@ -155,16 +202,9 @@ extern void ide_set_bus_master(int board, extern void win_cdrom_eject(uint8_t id); extern void win_cdrom_reload(uint8_t id); -extern void ide_set_base(int board, uint16_t port); -extern void ide_set_side(int board, uint16_t port); +extern void ide_set_base_addr(int board, int base, uint16_t port); -extern void ide_set_handlers(uint8_t board); -extern void ide_remove_handlers(uint8_t board); - -extern void ide_pri_enable(void); -extern void ide_pri_disable(void); -extern void ide_sec_enable(void); -extern void ide_sec_disable(void); +extern void ide_handlers(uint8_t board, int set); extern void ide_board_set_force_ata3(int board, int force_ata3); #ifdef EMU_ISAPNP_H @@ -183,4 +223,16 @@ extern void ide_padstr8(uint8_t *buf, int buf_size, const char *src); extern uint8_t ide_read_ali_75(void); extern uint8_t ide_read_ali_76(void); +/* Legacy #define's. */ +#define ide_set_base(board, port) ide_set_base_addr(board, 0, port) +#define ide_set_side(board, port) ide_set_base_addr(board, 1, port) + +#define ide_pri_enable() ide_handlers(0, 1) +#define ide_pri_disable() ide_handlers(0, 0) +#define ide_sec_enable() ide_handlers(1, 1) +#define ide_sec_disable() ide_handlers(1, 0) + +#define ide_set_handlers(board) ide_handlers(board, 1) +#define ide_remove_handlers(board) ide_handlers(board, 0) + #endif /*EMU_IDE_H*/ diff --git a/src/include/86box/hdd.h b/src/include/86box/hdd.h index 9874fb4aa..8c82209c7 100644 --- a/src/include/86box/hdd.h +++ b/src/include/86box/hdd.h @@ -148,7 +148,8 @@ typedef struct hard_disk_t { uint8_t scsi_id; }; uint8_t bus; - uint8_t res; /* Reserved for bus mode */ + uint8_t bus_mode; /* Bit 0 = PIO suported; + Bit 1 = DMA supportd. */ uint8_t wp; /* Disk has been mounted READ-ONLY */ uint8_t pad; uint8_t pad0; diff --git a/src/include/86box/mo.h b/src/include/86box/mo.h index 8071b80b5..5d4b723f3 100644 --- a/src/include/86box/mo.h +++ b/src/include/86box/mo.h @@ -128,23 +128,35 @@ typedef struct mo_t { mode_sense_pages_t ms_pages_saved; mo_drive_t *drv; +#ifdef EMU_IDE_H + ide_tf_t * tf; +#else + void * tf; +#endif uint8_t *buffer; uint8_t atapi_cdb[16]; uint8_t current_cdb[16]; uint8_t sense[256]; - uint8_t status; - uint8_t phase; - uint8_t error; - uint8_t id; +#ifdef ANCIENT_CODE + /* Task file. */ uint8_t features; + uint8_t phase; + uint16_t request_length; + uint8_t status; + uint8_t error; + uint16_t pad; + uint32_t pos; +#endif + + uint8_t id; uint8_t cur_lun; uint8_t pad0; uint8_t pad1; - uint16_t request_length; uint16_t max_transfer_len; + uint16_t pad2; int requested_blocks; int packet_status; @@ -158,7 +170,6 @@ typedef struct mo_t { uint32_t sector_pos; uint32_t sector_len; uint32_t packet_len; - uint32_t pos; double callback; } mo_t; diff --git a/src/include/86box/scsi_cdrom.h b/src/include/86box/scsi_cdrom.h index 35a4676e7..dec537429 100644 --- a/src/include/86box/scsi_cdrom.h +++ b/src/include/86box/scsi_cdrom.h @@ -26,24 +26,36 @@ typedef struct scsi_cdrom_t { /* Common block. */ mode_sense_pages_t ms_pages_saved; - cdrom_t *drv; + cdrom_t * drv; +#ifdef EMU_IDE_H + ide_tf_t *tf; +#else + void * tf; +#endif uint8_t *buffer; uint8_t atapi_cdb[16]; uint8_t current_cdb[16]; uint8_t sense[256]; - uint8_t status; - uint8_t phase; - uint8_t error; - uint8_t id; +#ifdef ANCIENT_CODE + /* Task file. */ uint8_t features; + uint8_t phase; + uint16_t request_length; + uint8_t status; + uint8_t error; + uint16_t pad; + uint32_t pos; +#endif + + uint8_t id; uint8_t cur_lun; uint8_t early; uint8_t pad1; - uint16_t request_length; uint16_t max_transfer_len; + uint16_t pad2; int requested_blocks; int packet_status; @@ -57,7 +69,6 @@ typedef struct scsi_cdrom_t { uint32_t sector_pos; uint32_t sector_len; uint32_t packet_len; - uint32_t pos; double callback; diff --git a/src/include/86box/scsi_device.h b/src/include/86box/scsi_device.h index e04cc058f..09f9ee2d9 100644 --- a/src/include/86box/scsi_device.h +++ b/src/include/86box/scsi_device.h @@ -149,6 +149,7 @@ #define GPCMD_PLAY_AUDIO_TRACK_RELATIVE_12_MATSUSHITA 0xe9 /* Matsushita Vendor Unique command */ /* Mode page codes for mode sense/set */ +#define GPMODE_UNIT_ATN_PAGE 0x00 #define GPMODE_R_W_ERROR_PAGE 0x01 #define GPMODE_DISCONNECT_PAGE 0x02 /* Disconnect/reconnect page */ #define GPMODE_FORMAT_DEVICE_PAGE 0x03 @@ -165,6 +166,7 @@ #define GPMODE_ALL_PAGES 0x3f /* Mode page codes for presence */ +#define GPMODEP_UNIT_ATN_PAGE 0x0000000000000001LL #define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL #define GPMODEP_DISCONNECT_PAGE 0x0000000000000004LL #define GPMODEP_FORMAT_DEVICE_PAGE 0x0000000000000008LL @@ -347,7 +349,12 @@ typedef struct mode_sense_pages_t { typedef struct scsi_common_s { mode_sense_pages_t ms_pages_saved; - void *priv; + void * priv; +#ifdef EMU_IDE_H + ide_tf_t *tf; +#else + void * tf; +#endif uint8_t *temp_buffer; uint8_t atapi_cdb[16]; /* This is atapi_cdb in ATAPI-supporting devices, @@ -355,17 +362,24 @@ typedef struct scsi_common_s { uint8_t current_cdb[16]; uint8_t sense[256]; - uint8_t status; - uint8_t phase; - uint8_t error; - uint8_t id; +#ifdef ANCIENT_CODE + /* Task file. */ uint8_t features; + uint8_t phase; + uint16_t request_length; + uint8_t status; + uint8_t error; + uint16_t pad; + uint32_t pos; +#endif + + uint8_t id; uint8_t cur_lun; uint8_t pad0; uint8_t pad1; - uint16_t request_length; uint16_t max_transfer_len; + uint16_t pad2; int requested_blocks; int packet_status; @@ -379,7 +393,6 @@ typedef struct scsi_common_s { uint32_t sector_pos; uint32_t sector_len; uint32_t packet_len; - uint32_t pos; double callback; } scsi_common_t; @@ -435,4 +448,7 @@ extern void scsi_device_init(void); extern void scsi_reset(void); extern uint8_t scsi_get_bus(void); +extern void scsi_bus_set_speed(uint8_t bus, double speed); +extern double scsi_bus_get_speed(uint8_t bus); + #endif /*SCSI_DEVICE_H*/ diff --git a/src/include/86box/scsi_disk.h b/src/include/86box/scsi_disk.h index 280899ade..a62bc9e20 100644 --- a/src/include/86box/scsi_disk.h +++ b/src/include/86box/scsi_disk.h @@ -20,38 +20,48 @@ typedef struct scsi_disk_t { mode_sense_pages_t ms_pages_saved; hard_disk_t *drv; +#ifdef EMU_IDE_H + ide_tf_t * tf; +#else + void * tf; +#endif uint8_t *temp_buffer; - uint8_t pad[16]; /* This is atapi_cdb in ATAPI-supporting devices, - and pad in SCSI-only devices. */ + uint8_t atapi_cdb[16]; uint8_t current_cdb[16]; uint8_t sense[256]; - uint8_t status; +#ifdef ANCIENT_CODE + /* Task file. */ + uint8_t features; uint8_t phase; - uint8_t error; - uint8_t id; - uint8_t pad0; - uint8_t cur_lun; - uint8_t pad1; - uint8_t pad2; - uint16_t request_length; - uint16_t pad4; + uint8_t status; + uint8_t error; + uint16_t pad; + uint32_t pos; +#endif + + uint8_t id; + uint8_t cur_lun; + uint8_t pad0; + uint8_t pad1; + + uint16_t max_transfer_len; + uint16_t pad2; int requested_blocks; int packet_status; int total_length; int do_page_save; int unit_attention; - int pad5; + int request_pos; int pad6; int pad7; uint32_t sector_pos; uint32_t sector_len; uint32_t packet_len; - uint32_t pos; double callback; } scsi_disk_t; diff --git a/src/include/86box/zip.h b/src/include/86box/zip.h index 2cadb2ff2..a4a4c341f 100644 --- a/src/include/86box/zip.h +++ b/src/include/86box/zip.h @@ -74,23 +74,35 @@ typedef struct zip_t { mode_sense_pages_t ms_pages_saved; zip_drive_t *drv; +#ifdef EMU_IDE_H + ide_tf_t * tf; +#else + void * tf; +#endif uint8_t *buffer; uint8_t atapi_cdb[16]; uint8_t current_cdb[16]; uint8_t sense[256]; - uint8_t status; - uint8_t phase; - uint8_t error; - uint8_t id; +#ifdef ANCIENT_CODE + /* Task file. */ uint8_t features; + uint8_t phase; + uint16_t request_length; + uint8_t status; + uint8_t error; + uint16_t pad; + uint32_t pos; +#endif + + uint8_t id; uint8_t cur_lun; uint8_t pad0; uint8_t pad1; - uint16_t request_length; uint16_t max_transfer_len; + uint16_t pad2; int requested_blocks; int packet_status; @@ -104,7 +116,6 @@ typedef struct zip_t { uint32_t sector_pos; uint32_t sector_len; uint32_t packet_len; - uint32_t pos; double callback; } zip_t; diff --git a/src/qt/qt_harddrive_common.cpp b/src/qt/qt_harddrive_common.cpp index eecc4e35b..dda36917f 100644 --- a/src/qt/qt_harddrive_common.cpp +++ b/src/qt/qt_harddrive_common.cpp @@ -75,8 +75,10 @@ Harddrives::populateSpeeds(QAbstractItemModel *model, int bus) int num_preset; switch (bus) { - case HDD_BUS_IDE: case HDD_BUS_ESDI: + case HDD_BUS_IDE: + case HDD_BUS_ATAPI: + case HDD_BUS_SCSI: num_preset = hdd_preset_get_num(); break; diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index e3eeb3fc4..598025795 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -137,6 +137,8 @@ main_thread_fn() } } else { /* Just so we dont overload the host OS. */ + if (dopause) + ack_pause(); std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 2aebc39ef..1d0b2451a 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -921,16 +921,10 @@ MainWindow::on_actionSettings_triggered() switch (settings.result()) { case QDialog::Accepted: - /* pc_reset_hard_close(); settings.save(); config_changed = 2; pc_reset_hard_init(); - */ - settings.save(); - config_changed = 2; - pc_reset_hard(); - break; case QDialog::Rejected: break; diff --git a/src/qt/qt_platform.cpp b/src/qt/qt_platform.cpp index 3a9db0310..f306b6138 100644 --- a/src/qt/qt_platform.cpp +++ b/src/qt/qt_platform.cpp @@ -382,7 +382,7 @@ plat_pause(int p) if ((p == 0) && (time_sync & TIME_SYNC_ENABLED)) nvr_time_sync(); - dopause = p; + do_pause(p); if (p) { if (mouse_capture) plat_mouse_capture(0); @@ -408,9 +408,6 @@ plat_pause(int p) #endif } -// because we can't include nvr.h because it's got fields named new -extern int nvr_save(void); - void plat_power_off(void) { diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index b1f358676..238fa7cb3 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -42,7 +42,8 @@ #include <86box/scsi_pcscsi.h> #include <86box/scsi_spock.h> -int scsi_card_current[SCSI_BUS_MAX] = { 0, 0 }; +int scsi_card_current[SCSI_BUS_MAX] = { 0, 0, 0, 0 }; +double scsi_bus_speed[SCSI_BUS_MAX] = { 0.0, 0.0, 0.0, 0.0 }; static uint8_t next_scsi_bus = 0; @@ -183,3 +184,15 @@ scsi_card_init(void) } } } + +void +scsi_bus_set_speed(uint8_t bus, double speed) +{ + scsi_bus_speed[bus] = speed; +} + +double +scsi_bus_get_speed(uint8_t bus) +{ + return scsi_bus_speed[bus]; +} diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 5bfe854b3..05b8b2726 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -1101,6 +1101,8 @@ aha_init(const device_t *info) break; } + scsi_bus_set_speed(dev->bus, dev->ha_bps); + /* Initialize ROM BIOS if needed. */ aha_setbios(dev); diff --git a/src/scsi/scsi_buslogic.c b/src/scsi/scsi_buslogic.c index 4e8600ac6..ac3b464a8 100644 --- a/src/scsi/scsi_buslogic.c +++ b/src/scsi/scsi_buslogic.c @@ -1706,9 +1706,10 @@ buslogic_init(const device_t *info) break; } - if ((dev->Base != 0) && !(dev->card_bus & DEVICE_MCA) && !(dev->card_bus & DEVICE_PCI)) { + scsi_bus_set_speed(dev->bus, dev->ha_bps); + + if ((dev->Base != 0) && !(dev->card_bus & DEVICE_MCA) && !(dev->card_bus & DEVICE_PCI)) x54x_io_set(dev, dev->Base, 4); - } memset(bl->AutoSCSIROM, 0xff, 32768); diff --git a/src/scsi/scsi_cdrom.c b/src/scsi/scsi_cdrom.c index df19f185a..056c7fdfe 100644 --- a/src/scsi/scsi_cdrom.c +++ b/src/scsi/scsi_cdrom.c @@ -41,6 +41,8 @@ #include <86box/scsi_cdrom.h> #include <86box/version.h> +#define IDE_ATAPI_IS_EARLY id->sc->pad0 + #pragma pack(push, 1) typedef struct gesn_cdb_t { uint8_t opcode; @@ -184,7 +186,7 @@ uint8_t scsi_cdrom_command_flags[0x100] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xF0-0xFF */ }; -static uint64_t scsi_cdrom_mode_sense_page_flags = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | GPMODEP_CDROM_PAGE | GPMODEP_CDROM_AUDIO_PAGE | (1ULL << 0x0fULL) | GPMODEP_CAPABILITIES_PAGE | GPMODEP_ALL_PAGES); +static uint64_t scsi_cdrom_mode_sense_page_flags = (GPMODEP_UNIT_ATN_PAGE | GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | GPMODEP_FORMAT_DEVICE_PAGE | GPMODEP_CDROM_PAGE | GPMODEP_CDROM_AUDIO_PAGE | (1ULL << 0x0fULL) | GPMODEP_CAPABILITIES_PAGE | GPMODEP_ALL_PAGES); static uint64_t scsi_cdrom_mode_sense_page_flags_sony = (GPMODEP_R_W_ERROR_PAGE | GPMODEP_DISCONNECT_PAGE | GPMODEP_CDROM_PAGE_SONY | GPMODEP_CDROM_AUDIO_PAGE_SONY | (1ULL << 0x0fULL) | GPMODEP_CAPABILITIES_PAGE | GPMODEP_ALL_PAGES); static uint64_t scsi_cdrom_drive_status_page_flags = ((1ULL << 0x01ULL) | (1ULL << 0x02ULL) | (1ULL << 0x0fULL) | GPMODEP_ALL_PAGES); @@ -281,10 +283,10 @@ static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default = { }; static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_scsi = { - {{ 0, 0 }, + {{ GPMODE_UNIT_ATN_PAGE, 6, 0, 0, 0, 0, 0, 0 }, /*Guess-work*/ { GPMODE_R_W_ERROR_PAGE, 6, 0, 5, 0, 0, 0, 0 }, { GPMODE_DISCONNECT_PAGE, 0x0e, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0 }, + { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -373,10 +375,10 @@ static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_default_sony_scsi = }; static const mode_sense_pages_t scsi_cdrom_mode_sense_pages_changeable = { - {{ 0, 0 }, + {{ GPMODE_UNIT_ATN_PAGE, 6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, /*Guess-work*/ { GPMODE_R_W_ERROR_PAGE, 6, 0xFF, 0xFF, 0, 0, 0, 0 }, { GPMODE_DISCONNECT_PAGE, 0x0E, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 }, - { 0, 0 }, + { GPMODE_FORMAT_DEVICE_PAGE, 0x16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, @@ -516,15 +518,17 @@ scsi_cdrom_init(scsi_cdrom_t *dev) dev->drv->bus_mode |= 2; if (dev->drv->bus_type < CDROM_BUS_SCSI) dev->drv->bus_mode |= 1; - scsi_cdrom_log("CD-ROM %i: Bus type %i, bus mode %i\n", dev->id, dev->drv->bus_type, dev->drv->bus_mode); + scsi_cdrom_log("CD-ROM %i: Bus type %i, bus mode %i\n", + dev->id, dev->drv->bus_type, dev->drv->bus_mode); dev->sense[0] = 0xf0; dev->sense[7] = 10; - if ((dev->drv->type == CDROM_TYPE_NEC_260_100) || (dev->drv->type == CDROM_TYPE_NEC_260_101)) /*NEC only*/ - dev->status = READY_STAT | DSC_STAT; + /* NEC only */ + if ((dev->drv->type == CDROM_TYPE_NEC_260_100) || (dev->drv->type == CDROM_TYPE_NEC_260_101)) + dev->tf->status = READY_STAT | DSC_STAT; else - dev->status = 0; - dev->pos = 0; + dev->tf->status = 0; + dev->tf->pos = 0; dev->packet_status = PHASE_NONE; scsi_cdrom_sense_key = scsi_cdrom_asc = scsi_cdrom_ascq = dev->unit_attention = 0; dev->drv->cur_speed = dev->drv->speed; @@ -541,37 +545,9 @@ scsi_cdrom_current_mode(scsi_cdrom_t *dev) return 2; else if (dev->drv->bus_type == CDROM_BUS_ATAPI) { scsi_cdrom_log("CD-ROM %i: ATAPI drive, setting to %s\n", dev->id, - (dev->features & 1) ? "DMA" : "PIO", + (dev->tf->features & 1) ? "DMA" : "PIO", dev->id); - return (dev->features & 1) ? 2 : 1; - } - - return 0; -} - -/* Translates ATAPI phase (DRQ, I/O, C/D) to SCSI phase (MSG, C/D, I/O). */ -int -scsi_cdrom_atapi_phase_to_scsi(scsi_cdrom_t *dev) -{ - if (dev->status & 8) { - switch (dev->phase & 3) { - case 0: - return 0; - case 1: - return 2; - case 2: - return 1; - case 3: - return 7; - - default: - break; - } - } else { - if ((dev->phase & 3) == 3) - return 3; - else - return 4; + return (dev->tf->features & 1) ? 2 : 1; } return 0; @@ -617,7 +593,8 @@ scsi_cdrom_get_volume(void *priv, int channel) case CDROM_TYPE_SONY_CDU561_18k: case CDROM_TYPE_SONY_CDU76S_100: case CDROM_TYPE_TEXEL_DMXX24_100: - ret = dev->ms_pages_saved_sony.pages[dev->sony_vendor ? GPMODE_CDROM_AUDIO_PAGE_SONY : GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; + ret = dev->ms_pages_saved_sony.pages[dev->sony_vendor ? GPMODE_CDROM_AUDIO_PAGE_SONY : + GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; break; default: ret = dev->ms_pages_saved.pages[GPMODE_CDROM_AUDIO_PAGE][channel ? 11 : 9]; @@ -640,13 +617,15 @@ scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev) case CDROM_TYPE_SONY_CDU76S_100: case CDROM_TYPE_TEXEL_DMXX24_100: memset(&dev->ms_pages_saved_sony, 0, sizeof(mode_sense_pages_t)); - memcpy(&dev->ms_pages_saved_sony, &scsi_cdrom_mode_sense_pages_default_sony_scsi, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_pages_saved_sony, &scsi_cdrom_mode_sense_pages_default_sony_scsi, + sizeof(mode_sense_pages_t)); memset(file_name, 0, 512); sprintf(file_name, "scsi_cdrom_%02i_mode_sense_sony_bin", dev->id); fp = plat_fopen(nvr_path(file_name), "rb"); if (fp) { - if (fread(dev->ms_pages_saved_sony.pages[GPMODE_CDROM_AUDIO_PAGE_SONY], 1, 0x10, fp) != 0x10) + if (fread(dev->ms_pages_saved_sony.pages[GPMODE_CDROM_AUDIO_PAGE_SONY], 1, + 0x10, fp) != 0x10) fatal("scsi_cdrom_mode_sense_load(): Error reading data\n"); fclose(fp); } @@ -654,9 +633,11 @@ scsi_cdrom_mode_sense_load(scsi_cdrom_t *dev) default: memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); if (dev->drv->bus_type == CDROM_BUS_SCSI) - memcpy(&dev->ms_pages_saved, &scsi_cdrom_mode_sense_pages_default_scsi, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_pages_saved, &scsi_cdrom_mode_sense_pages_default_scsi, + sizeof(mode_sense_pages_t)); else - memcpy(&dev->ms_pages_saved, &scsi_cdrom_mode_sense_pages_default, sizeof(mode_sense_pages_t)); + memcpy(&dev->ms_pages_saved, &scsi_cdrom_mode_sense_pages_default, + sizeof(mode_sense_pages_t)); memset(file_name, 0, 512); if (dev->drv->bus_type == CDROM_BUS_SCSI) @@ -839,14 +820,14 @@ scsi_cdrom_mode_sense(scsi_cdrom_t *dev, uint8_t *buf, uint32_t pos, uint8_t pag else { if ((i == GPMODE_CAPABILITIES_PAGE) && (j == 4)) { buf[pos] = scsi_cdrom_mode_sense_read(dev, page_control, i, 2 + j) & 0x1f; - /* The early CD-ROM drives we emulate (NEC CDR-260 for ATAPI and early vendor SCSI CD-ROM models) are - caddy drives, the later ones are tray drives. */ - if (dev->drv->bus_type == CDROM_BUS_SCSI) { + /* The early CD-ROM drives we emulate (NEC CDR-260 for ATAPI and + early vendor SCSI CD-ROM models) are caddy drives, the later + ones are tray drives. */ + if (dev->drv->bus_type == CDROM_BUS_SCSI) buf[pos++] |= ((dev->drv->type == CDROM_TYPE_86BOX_100) ? 0x20 : 0x00); - } else { + else buf[pos++] |= ((dev->drv->type == CDROM_TYPE_NEC_260_100) || ((dev->drv->type == CDROM_TYPE_NEC_260_101)) ? 0x00 : 0x20); - } } else if ((i == GPMODE_CAPABILITIES_PAGE) && (j >= 6) && (j <= 7)) { if (j & 1) buf[pos++] = ((dev->drv->speed * 176) & 0xff); @@ -881,7 +862,7 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, int block_len) int32_t min_len = 0; double dlen; - dev->max_transfer_len = dev->request_length; + dev->max_transfer_len = dev->tf->request_length; /* For media access commands, make sure the requested DRQ length matches the block length. */ switch (dev->current_cdb[0]) { @@ -936,9 +917,9 @@ scsi_cdrom_update_request_length(scsi_cdrom_t *dev, int len, int block_len) dev->max_transfer_len = 65534; if ((len <= dev->max_transfer_len) && (len >= min_len)) - dev->request_length = dev->max_transfer_len = len; + dev->tf->request_length = dev->max_transfer_len = len; else if (len > dev->max_transfer_len) - dev->request_length = dev->max_transfer_len; + dev->tf->request_length = dev->max_transfer_len; return; } @@ -969,10 +950,11 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) double bytes_per_second = 0.0; double period; - dev->status = BUSY_STAT; - dev->phase = 1; - dev->pos = 0; - dev->callback = 0; + /* MAP: BUSY_STAT, no DRQ, phase 1. */ + dev->tf->status = BUSY_STAT; + dev->tf->phase = 1; + dev->tf->pos = 0; + dev->callback = 0; scsi_cdrom_log("CD-ROM %i: Current speed: %ix\n", dev->id, dev->drv->cur_speed); @@ -1000,14 +982,10 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) dev->callback += period; fallthrough; case 0x25: - case 0x42: - case 0x43: - case 0x44: - case 0x51: - case 0x52: + case 0x42 ... 0x44: + case 0x51 ... 0x52: case 0xad: - case 0xb8: - case 0xb9: + case 0xb8 ... 0xb9: case 0xbe: if (dev->current_cdb[0] == 0x42) dev->callback += 40.0; @@ -1015,8 +993,7 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) bytes_per_second = 176.0 * 1024.0; bytes_per_second *= (double) dev->drv->cur_speed; break; - case 0xc6: - case 0xc7: + case 0xc6 ... 0xc7: switch (dev->drv->type) { case CDROM_TYPE_TOSHIBA_XM_3433: case CDROM_TYPE_TOSHIBA_XM3201B_3232: @@ -1050,8 +1027,7 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) bytes_per_second *= (double) dev->drv->cur_speed; break; } - case 0xc2: - case 0xc3: + case 0xc2 ... 0xc3: switch (dev->drv->type) { case CDROM_TYPE_DEC_RRD45_0436: case CDROM_TYPE_SONY_CDU541_10i: @@ -1065,10 +1041,12 @@ scsi_cdrom_command_common(scsi_cdrom_t *dev) bytes_per_second *= (double) dev->drv->cur_speed; break; } - case 0xdd: - case 0xde: + case 0xdd ... 0xde: switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_NEC_464_105: bytes_per_second = 176.0 * 1024.0; @@ -1100,7 +1078,7 @@ scsi_cdrom_command_complete(scsi_cdrom_t *dev) ui_sb_update_icon(SB_CDROM | dev->id, 0); dev->packet_status = PHASE_COMPLETE; scsi_cdrom_command_common(dev); - dev->phase = 3; + dev->tf->phase = 3; } static void @@ -1108,7 +1086,7 @@ scsi_cdrom_command_read(scsi_cdrom_t *dev) { dev->packet_status = PHASE_DATA_IN; scsi_cdrom_command_common(dev); - dev->phase = !(dev->packet_status & 0x01) << 1; + dev->tf->phase = !(dev->packet_status & 0x01) << 1; } static void @@ -1123,7 +1101,7 @@ scsi_cdrom_command_write(scsi_cdrom_t *dev) { dev->packet_status = PHASE_DATA_OUT; scsi_cdrom_command_common(dev); - dev->phase = !(dev->packet_status & 0x01) << 1; + dev->tf->phase = !(dev->packet_status & 0x01) << 1; } static void @@ -1142,8 +1120,9 @@ static void scsi_cdrom_data_command_finish(scsi_cdrom_t *dev, int len, int block_len, int alloc_len, int direction) { scsi_cdrom_log("CD-ROM %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", - dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); - dev->pos = 0; + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, + dev->tf->request_length); + dev->tf->pos = 0; if (alloc_len >= 0) { if (alloc_len < len) len = alloc_len; @@ -1172,7 +1151,8 @@ scsi_cdrom_data_command_finish(scsi_cdrom_t *dev, int len, int block_len, int al } scsi_cdrom_log("CD-ROM %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", - dev->id, dev->packet_status, dev->request_length, dev->packet_len, dev->pos, dev->phase); + dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, + dev->tf->phase); } static void @@ -1197,14 +1177,14 @@ static void scsi_cdrom_cmd_error(scsi_cdrom_t *dev) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = ((scsi_cdrom_sense_key & 0xf) << 4) | ABRT_ERR; + dev->tf->error = ((scsi_cdrom_sense_key & 0xf) << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; - dev->packet_status = PHASE_ERROR; - dev->callback = 50.0 * CDROM_TIME; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; + dev->packet_status = PHASE_ERROR; + dev->callback = 50.0 * CDROM_TIME; scsi_cdrom_set_callback(dev); ui_sb_update_icon(SB_CDROM | dev->id, 0); scsi_cdrom_log("CD-ROM %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq); @@ -1214,12 +1194,12 @@ static void scsi_cdrom_unit_attention(scsi_cdrom_t *dev) { scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; + dev->tf->error = (SENSE_UNIT_ATTENTION << 4) | ABRT_ERR; if (dev->unit_attention) - dev->error |= MCR_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->pos = 0; + dev->tf->error |= MCR_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; + dev->tf->pos = 0; dev->packet_status = PHASE_ERROR; dev->callback = 50.0 * CDROM_TIME; scsi_cdrom_set_callback(dev); @@ -1298,7 +1278,7 @@ scsi_cdrom_invalid_field(scsi_cdrom_t *dev) scsi_cdrom_asc = ASC_INV_FIELD_IN_CMD_PACKET; scsi_cdrom_ascq = 0; scsi_cdrom_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } static void @@ -1308,7 +1288,7 @@ scsi_cdrom_invalid_field_pl(scsi_cdrom_t *dev) scsi_cdrom_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; scsi_cdrom_ascq = 0; scsi_cdrom_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } static void @@ -1575,7 +1555,7 @@ scsi_cdrom_pre_execution_check(scsi_cdrom_t *dev, uint8_t *cdb) if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { scsi_cdrom_log("CD-ROM %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", - dev->id, ((dev->request_length >> 5) & 7)); + dev->id, ((dev->tf->request_length >> 5) & 7)); scsi_cdrom_invalid_lun(dev); return 0; } @@ -1674,14 +1654,14 @@ scsi_cdrom_reset(scsi_common_t *sc) return; scsi_cdrom_rezero(dev); - dev->status = 0; - dev->callback = 0.0; + dev->tf->status = 0; + dev->callback = 0.0; scsi_cdrom_set_callback(dev); - dev->phase = 1; - dev->request_length = 0xEB14; - dev->packet_status = PHASE_NONE; - dev->unit_attention = 0xff; - dev->cur_lun = SCSI_LUN_USE_CDB; + dev->tf->phase = 1; + dev->tf->request_length = 0xeb14; + dev->packet_status = PHASE_NONE; + dev->unit_attention = 0xff; + dev->cur_lun = SCSI_LUN_USE_CDB; } static void @@ -1793,10 +1773,10 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if (dev->drv->bus_type == CDROM_BUS_SCSI) { BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; - dev->status &= ~ERR_STAT; + dev->tf->status &= ~ERR_STAT; } else { BufLen = &blen; - dev->error = 0; + dev->tf->error = 0; } dev->packet_len = 0; @@ -1814,11 +1794,12 @@ scsi_cdrom_command(scsi_common_t *sc, uint8_t *cdb) if (cdb[0] != 0) { scsi_cdrom_log("CD-ROM %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X, Unit attention: %i\n", - dev->id, cdb[0], scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq, dev->unit_attention); - scsi_cdrom_log("CD-ROM %i: Request length: %04X\n", dev->id, dev->request_length); + dev->id, cdb[0], scsi_cdrom_sense_key, scsi_cdrom_asc, scsi_cdrom_ascq, + dev->unit_attention); + scsi_cdrom_log("CD-ROM %i: Request length: %04X\n", dev->id, dev->tf->request_length); - scsi_cdrom_log("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, - cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], + scsi_cdrom_log("CD-ROM %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", + dev->id, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]); } @@ -1868,7 +1849,10 @@ begin: case 0xDA: /*GPCMD_SPEED_ALT*/ switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_NEC_464_105: /*GPCMD_STILL_NEC*/ scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); @@ -2006,11 +1990,14 @@ begin: case 0xDE: switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_NEC_464_105: /*GPCMD_READ_DISC_INFORMATION_NEC*/ scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); - scsi_cdrom_buf_alloc(dev, 4); + scsi_cdrom_buf_alloc(dev, 22); /*NEC manual claims 4 bytes, but the Android source code (namely sr_vendor.c) actually states otherwise.*/ if (!dev->drv->ops) { scsi_cdrom_not_ready(dev); @@ -2018,7 +2005,7 @@ begin: } ret = cdrom_read_disc_info_toc(dev->drv, dev->buffer, cdb[2], cdb[1] & 3); - len = 4; + len = 22; if (!ret) { scsi_cdrom_invalid_field(dev); scsi_cdrom_buf_free(dev); @@ -2141,7 +2128,10 @@ begin: if ((cdb[0] == GPCMD_READ_10) || (cdb[0] == GPCMD_READ_12)) { switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_NEC_464_105: case CDROM_TYPE_TOSHIBA_XM_3433: @@ -2583,7 +2573,10 @@ begin: case 0xD8: switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_NEC_464_105: /*GPCMD_AUDIO_TRACK_SEARCH_NEC*/ scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); @@ -2686,7 +2679,10 @@ begin: case 0xD9: switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_NEC_464_105: /*GPCMD_PLAY_AUDIO_NEC*/ scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); @@ -2926,7 +2922,10 @@ begin: case 0xDD: switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_NEC_464_105: /*GPCMD_READ_SUBCODEQ_PLAYING_STATUS_NEC*/ scsi_cdrom_set_phase(dev, SCSI_PHASE_DATA_IN); @@ -3093,7 +3092,10 @@ begin: case 0xDC: switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_NEC_464_105: /*GPCMD_CADDY_EJECT_NEC*/ scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); @@ -3192,17 +3194,23 @@ begin: case CDROM_TYPE_CHINON_CDS431_H42: case CDROM_TYPE_DEC_RRD45_0436: case CDROM_TYPE_MATSHITA_501_10b: - case CDROM_TYPE_NEC_38_103: - case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_SONY_CDU541_10i: case CDROM_TYPE_SONY_CDU76S_100: case CDROM_TYPE_TEAC_CD50_100: case CDROM_TYPE_TEAC_R55S_10R: case CDROM_TYPE_TEXEL_DMXX24_100: case CDROM_TYPE_TOSHIBA_XM3201B_3232: - dev->buffer[2] = 0x01; + dev->buffer[2] = 0x00; dev->buffer[3] = 0x01; /*SCSI-1 compliant*/ break; + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: + dev->buffer[3] = 0x00; /*SCSI unknown version per NEC manuals*/ + break; default: dev->buffer[2] = 0x02; /*SCSI-2 compliant*/ break; @@ -3225,6 +3233,13 @@ begin: case CDROM_TYPE_PIONEER_DRM604X_2403: dev->buffer[4] = 42; break; + case CDROM_TYPE_NEC_25_10a: + case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: + case CDROM_TYPE_NEC_211_100: + case CDROM_TYPE_NEC_464_105: + break; default: dev->buffer[6] = 0x01; /* 16-bit transfers supported */ dev->buffer[7] = 0x20; /* Wide bus supported */ @@ -3345,7 +3360,10 @@ atapi_out: case 0xDB: switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_NEC_464_105: /*GPCMD_SET_STOP_TIME_NEC*/ scsi_cdrom_set_phase(dev, SCSI_PHASE_STATUS); @@ -3459,7 +3477,10 @@ atapi_out: dev->drv->seek_diff = ABS((int) (pos - dev->drv->seek_pos)); if (cdb[0] == GPCMD_SEEK_10) { switch (dev->drv->type) { + case CDROM_TYPE_NEC_25_10a: case CDROM_TYPE_NEC_38_103: + case CDROM_TYPE_NEC_75_103: + case CDROM_TYPE_NEC_77_106: case CDROM_TYPE_NEC_211_100: case CDROM_TYPE_NEC_464_105: case CDROM_TYPE_TOSHIBA_XM_3433: @@ -3727,9 +3748,10 @@ atapi_out: break; } - /* scsi_cdrom_log("CD-ROM %i: Phase: %02X, request length: %i\n", dev->phase, dev->request_length); */ + /* scsi_cdrom_log("CD-ROM %i: Phase: %02X, request length: %i\n", dev->tf->phase, + dev->tf->request_length); */ - if (scsi_cdrom_atapi_phase_to_scsi(dev) == SCSI_PHASE_STATUS) + if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) scsi_cdrom_buf_free(dev); } @@ -3905,6 +3927,9 @@ scsi_cdrom_close(void *priv) { scsi_cdrom_t *dev = (scsi_cdrom_t *) priv; + if (dev->tf) + free(dev->tf); + if (dev) free(dev); } @@ -4086,6 +4111,7 @@ scsi_cdrom_drive_reset(int c) ide_t *id; uint8_t scsi_bus = (drv->scsi_device_id >> 4) & 0x0f; uint8_t scsi_id = drv->scsi_device_id & 0x0f; + uint8_t valid = 0; if (drv->bus_type == CDROM_BUS_SCSI) { /* Make sure to ignore any SCSI CD-ROM drive that has an out of range SCSI bus. */ @@ -4118,9 +4144,12 @@ scsi_cdrom_drive_reset(int c) drv->get_channel = scsi_cdrom_get_channel; drv->close = scsi_cdrom_close; - scsi_cdrom_init(dev); - if (drv->bus_type == CDROM_BUS_SCSI) { + valid = 1; + + if (!dev->tf) + dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); + /* SCSI CD-ROM, attach to the SCSI bus. */ sd = &scsi_devices[scsi_bus][scsi_id]; @@ -4140,7 +4169,12 @@ scsi_cdrom_drive_reset(int c) otherwise, we do nothing - it's going to be a drive that's not attached to anything. */ if (id) { + valid = 1; + id->sc = (scsi_common_t *) dev; + dev->tf = id->tf; + if ((dev->drv->type == CDROM_TYPE_NEC_260_100) || (dev->drv->type == CDROM_TYPE_NEC_260_101)) + IDE_ATAPI_IS_EARLY = 1; id->get_max = scsi_cdrom_get_max; id->get_timings = scsi_cdrom_get_timings; id->identify = scsi_cdrom_identify; @@ -4158,4 +4192,7 @@ scsi_cdrom_drive_reset(int c) scsi_cdrom_log("ATAPI CD-ROM drive %i attached to IDE channel %i\n", c, cdrom[c].ide_channel); } + + if (valid) + scsi_cdrom_init(dev); } diff --git a/src/scsi/scsi_device.c b/src/scsi/scsi_device.c index 4fce9f989..4442b2680 100644 --- a/src/scsi/scsi_device.c +++ b/src/scsi/scsi_device.c @@ -23,6 +23,7 @@ #include <86box/86box.h> #include <86box/device.h> #include <86box/hdd.h> +#include <86box/hdc_ide.h> #include <86box/scsi.h> #include <86box/scsi_device.h> #include <86box/plat_unused.h> @@ -37,7 +38,7 @@ scsi_device_target_command(scsi_device_t *dev, uint8_t *cdb) if (dev->command) { dev->command(dev->sc, cdb); - if (dev->sc->status & ERR_STAT) + if (dev->sc->tf->status & ERR_STAT) return SCSI_STATUS_CHECK_CONDITION; else return SCSI_STATUS_OK; @@ -140,7 +141,7 @@ scsi_device_command_phase1(scsi_device_t *dev) } else scsi_device_command_stop(dev); - if (dev->sc->status & ERR_STAT) + if (dev->sc->tf->status & ERR_STAT) dev->status = SCSI_STATUS_CHECK_CONDITION; else dev->status = SCSI_STATUS_OK; diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index 3db3b729f..ee0c3fc00 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -12,27 +12,34 @@ * * Copyright 2017-2018 Miran Grca. */ +#include +#include +#include #include #include #include #include -#include #include #define HAVE_STDARG_H #include <86box/86box.h> +#include <86box/config.h> #include <86box/timer.h> #include <86box/device.h> -#include <86box/nvr.h> -#include <86box/hdd.h> -#include <86box/hdc.h> #include <86box/scsi.h> #include <86box/scsi_device.h> +#include <86box/machine.h> +#include <86box/nvr.h> +#include <86box/hdc.h> #include <86box/hdc_ide.h> +#include <86box/sound.h> #include <86box/plat.h> #include <86box/ui.h> +#include <86box/hdd.h> #include <86box/scsi_disk.h> #include <86box/version.h> +#define IDE_ATAPI_IS_EARLY id->sc->pad0 + #define scsi_disk_sense_error dev->sense[0] #define scsi_disk_sense_key dev->sense[2] #define scsi_disk_asc dev->sense[12] @@ -116,6 +123,13 @@ static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable = { [GPMODE_UNK_VENDOR_PAGE] = { 0xB0, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }} }; +static void scsi_disk_command_complete(scsi_disk_t *dev); + +static void scsi_disk_mode_sense_load(scsi_disk_t *dev); + +static void scsi_disk_init(scsi_disk_t *dev); +static void scsi_disk_reset(scsi_common_t *sc); + #ifdef ENABLE_SCSI_DISK_LOG int scsi_disk_do_log = ENABLE_SCSI_DISK_LOG; @@ -134,6 +148,59 @@ scsi_disk_log(const char *fmt, ...) # define scsi_disk_log(fmt, ...) #endif +static void +scsi_disk_set_callback(scsi_disk_t *dev) +{ + if (dev->drv->bus != HDD_BUS_SCSI) + ide_set_callback(ide_drives[dev->drv->ide_channel], dev->callback); +} + +static void +scsi_disk_init(scsi_disk_t *dev) +{ + if (!dev) + return; + + /* Do a reset (which will also rezero it). */ + scsi_disk_reset((scsi_common_t *) dev); + + /* Configure the drive. */ + dev->requested_blocks = 1; + + dev->drv->bus_mode = 0; + if (dev->drv->bus >= HDD_BUS_ATAPI) + dev->drv->bus_mode |= 2; + if (dev->drv->bus < HDD_BUS_SCSI) + dev->drv->bus_mode |= 1; + scsi_disk_log("SCSI HDD %i: Bus type %i, bus mode %i\n", + dev->id, dev->drv->bus, dev->drv->bus_mode); + + dev->sense[0] = 0xf0; + dev->sense[7] = 10; + /* NEC only */ + dev->tf->status = 0; + dev->tf->pos = 0; + dev->packet_status = PHASE_NONE; + scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = dev->unit_attention = 0; + scsi_disk_mode_sense_load(dev); +} + +/* Returns: 0 for none, 1 for PIO, 2 for DMA. */ +static int +scsi_disk_current_mode(scsi_disk_t *dev) +{ + if (dev->drv->bus == HDD_BUS_SCSI) + return 2; + else if (dev->drv->bus == HDD_BUS_ATAPI) { + scsi_disk_log("SCSI DISK %i: ATAPI drive, setting to %s\n", dev->id, + (dev->tf->features & 1) ? "DMA" : "PIO", + dev->id); + return (dev->tf->features & 1) ? 2 : 1; + } + + return 0; +} + void scsi_disk_mode_sense_load(scsi_disk_t *dev) { @@ -280,14 +347,166 @@ scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t page, } static void +scsi_disk_update_request_length(scsi_disk_t *dev, int len, int block_len) +{ + int bt; + int min_len = 0; + + dev->max_transfer_len = dev->tf->request_length; + + /* For media access commands, make sure the requested DRQ length matches the block length. */ + switch (dev->current_cdb[0]) { + case 0x08: + case 0x0a: + case 0x28: + case 0x2a: + case 0xa8: + case 0xaa: + /* Round it to the nearest 2048 bytes. */ + dev->max_transfer_len = (dev->max_transfer_len >> 9) << 9; + + /* Make sure total length is not bigger than sum of the lengths of + all the requested blocks. */ + bt = (dev->requested_blocks * block_len); + if (len > bt) + len = bt; + + min_len = block_len; + + if (len <= block_len) { + /* Total length is less or equal to block length. */ + if (dev->max_transfer_len < block_len) { + /* Transfer a minimum of (block size) bytes. */ + dev->max_transfer_len = block_len; + dev->packet_len = block_len; + break; + } + } + fallthrough; + + default: + dev->packet_len = len; + break; + } + /* If the DRQ length is odd, and the total remaining length is bigger, make sure it's even. */ + if ((dev->max_transfer_len & 1) && (dev->max_transfer_len < len)) + dev->max_transfer_len &= 0xfffe; + /* If the DRQ length is smaller or equal in size to the total remaining length, set it to that. */ + if (!dev->max_transfer_len) + dev->max_transfer_len = 65534; + + if ((len <= dev->max_transfer_len) && (len >= min_len)) + dev->tf->request_length = dev->max_transfer_len = len; + else if (len > dev->max_transfer_len) + dev->tf->request_length = dev->max_transfer_len; + + return; +} + +static double +scsi_disk_bus_speed(scsi_disk_t *dev) +{ + double ret = -1.0; + + if (dev && dev->drv && (dev->drv->bus == HDD_BUS_SCSI)) { + dev->callback = -1.0; /* Speed depends on SCSI controller */ + return 0.0; + } else { + if (dev && dev->drv) + ret = ide_atapi_get_period(dev->drv->ide_channel); + if (ret == -1.0) { + if (dev) + dev->callback = -1.0; + return 0.0; + } else + return ret * 1000000.0; + } +} + +void scsi_disk_command_common(scsi_disk_t *dev) { - dev->status = BUSY_STAT; - dev->phase = 1; - if (dev->packet_status == PHASE_COMPLETE) - dev->callback = 0.0; - else - dev->callback = -1.0; /* Speed depends on SCSI controller */ + double bytes_per_second = 0.0; + double period; + + /* MAP: BUSY_STAT, no DRQ, phase 1. */ + dev->tf->status = BUSY_STAT; + dev->tf->phase = 1; + dev->tf->pos = 0; + dev->callback = 0; + + if (dev->packet_status == PHASE_COMPLETE) { + switch (dev->current_cdb[0]) { + case GPCMD_VERIFY_6: + case GPCMD_VERIFY_10: + case GPCMD_VERIFY_12: + case GPCMD_WRITE_6: + case GPCMD_WRITE_10: + case GPCMD_WRITE_AND_VERIFY_10: + case GPCMD_WRITE_12: + case GPCMD_WRITE_AND_VERIFY_12: + case GPCMD_WRITE_SAME_10: + /* Seek time is in us. */ + period = hdd_timing_write(dev->drv, dev->sector_pos, dev->packet_len >> 9); + scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", + dev->id, (uint64_t) period); + dev->callback += period; + /* Account for seek time. */ + bytes_per_second = scsi_bus_get_speed(dev->drv->scsi_id >> 4); + + period = 1000000.0 / bytes_per_second; + scsi_disk_log("SCSI HD %i: Byte transfer period: %" PRIu64 " us\n", dev->id, + (uint64_t) period); + period = period * (double) (dev->packet_len); + scsi_disk_log("CD-ROM %i: Sector transfer period: %" PRIu64 " us\n", dev->id, + (uint64_t) period); + dev->callback += period; + break; + default: + dev->callback = 0; + break; + } + } else { + switch (dev->current_cdb[0]) { + case GPCMD_REZERO_UNIT: + case 0x0b: + case 0x2b: + /* Seek time is in us. */ + period = hdd_seek_get_time(dev->drv, (dev->current_cdb[0] == GPCMD_REZERO_UNIT) ? + 0 : dev->sector_pos, HDD_OP_SEEK, 0, 0.0); + scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", + dev->id, (uint64_t) period); + dev->callback += period; + scsi_disk_set_callback(dev); + return; + case 0x08: + case 0x28: + case 0xa8: + /* Seek time is in us. */ + period = hdd_timing_read(dev->drv, dev->sector_pos, dev->packet_len >> 9); + scsi_disk_log("SCSI HD %i: Seek period: %" PRIu64 " us\n", + dev->id, (uint64_t) period); + dev->callback += period; + /* Account for seek time. */ + bytes_per_second = scsi_bus_get_speed(dev->drv->scsi_id >> 4); + break; + case 0x25: + default: + bytes_per_second = scsi_disk_bus_speed(dev); + if (bytes_per_second == 0.0) { + dev->callback = -1; /* Speed depends on SCSI controller */ + return; + } + break; + } + + period = 1000000.0 / bytes_per_second; + scsi_disk_log("SCSI HD %i: Byte transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); + period = period * (double) (dev->packet_len); + scsi_disk_log("SCSI HD %i: Sector transfer period: %" PRIu64 " us\n", dev->id, (uint64_t) period); + dev->callback += period; + } + scsi_disk_set_callback(dev); } static void @@ -298,6 +517,13 @@ scsi_disk_command_complete(scsi_disk_t *dev) scsi_disk_command_common(dev); } +static void +scsi_disk_command_read(scsi_disk_t *dev) +{ + dev->packet_status = PHASE_DATA_IN; + scsi_disk_command_common(dev); +} + static void scsi_disk_command_read_dma(scsi_disk_t *dev) { @@ -305,6 +531,13 @@ scsi_disk_command_read_dma(scsi_disk_t *dev) scsi_disk_command_common(dev); } +static void +scsi_disk_command_write(scsi_disk_t *dev) +{ + dev->packet_status = PHASE_DATA_OUT; + scsi_disk_command_common(dev); +} + static void scsi_disk_command_write_dma(scsi_disk_t *dev) { @@ -312,23 +545,48 @@ scsi_disk_command_write_dma(scsi_disk_t *dev) scsi_disk_command_common(dev); } +/* id = Current ZIP device ID; + len = Total transfer length; + block_len = Length of a single block (why does it matter?!); + alloc_len = Allocated transfer length; + direction = Transfer direction (0 = read from host, 1 = write to host). */ static void -scsi_disk_data_command_finish(scsi_disk_t *dev, int len, UNUSED(int block_len), int alloc_len, int direction) +scsi_disk_data_command_finish(scsi_disk_t *dev, int len, int block_len, int alloc_len, int direction) { - scsi_disk_log("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", dev->id, - dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); + scsi_disk_log("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", + dev->id, dev->current_cdb[0], len, block_len, alloc_len, direction, + dev->tf->request_length); + dev->tf->pos = 0; if (alloc_len >= 0) { if (alloc_len < len) len = alloc_len; } - if (len == 0) + if ((len == 0) || (scsi_disk_current_mode(dev) == 0)) { + if (dev->drv->bus != HDD_BUS_SCSI) + dev->packet_len = 0; + scsi_disk_command_complete(dev); - else { - if (direction == 0) - scsi_disk_command_read_dma(dev); - else - scsi_disk_command_write_dma(dev); + } else { + if (scsi_disk_current_mode(dev) == 2) { + if (dev->drv->bus != HDD_BUS_SCSI) + dev->packet_len = alloc_len; + + if (direction == 0) + scsi_disk_command_read_dma(dev); + else + scsi_disk_command_write_dma(dev); + } else { + scsi_disk_update_request_length(dev, len, block_len); + if (direction == 0) + scsi_disk_command_read(dev); + else + scsi_disk_command_write(dev); + } } + + scsi_disk_log("SCSI HD %i: Status: %i, cylinder %i, packet length: %i, position: %i, phase: %i\n", + dev->id, dev->packet_status, dev->tf->request_length, dev->packet_len, dev->tf->pos, + dev->tf->phase); } static void @@ -353,15 +611,44 @@ static void scsi_disk_cmd_error(scsi_disk_t *dev) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = ((scsi_disk_sense_key & 0xf) << 4) | ABRT_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; + dev->tf->error = ((scsi_disk_sense_key & 0xf) << 4) | ABRT_ERR; + dev->tf->status = READY_STAT | ERR_STAT; + dev->tf->phase = 3; dev->packet_status = PHASE_ERROR; dev->callback = 50.0 * SCSI_TIME; + scsi_disk_set_callback(dev); ui_sb_update_icon(SB_HDD | dev->drv->bus, 0); scsi_disk_log("SCSI HD %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); } +static void +scsi_disk_buf_alloc(scsi_disk_t *dev, uint32_t len) +{ + scsi_disk_log("SCSI HD %i: Allocated buffer length: %i\n", dev->id, len); + if (!dev->temp_buffer) + dev->temp_buffer = (uint8_t *) malloc(len); +} + +static void +scsi_disk_buf_free(scsi_disk_t *dev) +{ + if (dev->temp_buffer) { + scsi_disk_log("SCSI HD %i: Freeing buffer...\n", dev->id); + free(dev->temp_buffer); + dev->temp_buffer = NULL; + } +} + +static void +scsi_disk_bus_master_error(scsi_common_t *sc) +{ + scsi_disk_t *dev = (scsi_disk_t *) sc; + + scsi_disk_buf_free(dev); + scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = 0; + scsi_disk_cmd_error(dev); +} + static void scsi_disk_invalid_lun(scsi_disk_t *dev) { @@ -397,7 +684,7 @@ scsi_disk_invalid_field(scsi_disk_t *dev) scsi_disk_asc = ASC_INV_FIELD_IN_CMD_PACKET; scsi_disk_ascq = 0; scsi_disk_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } static void @@ -407,7 +694,7 @@ scsi_disk_invalid_field_pl(scsi_disk_t *dev) scsi_disk_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; scsi_disk_ascq = 0; scsi_disk_cmd_error(dev); - dev->status = 0x53; + dev->tf->status = 0x53; } static void @@ -419,18 +706,56 @@ scsi_disk_data_phase_error(scsi_disk_t *dev) scsi_disk_cmd_error(dev); } +static int +scsi_disk_blocks(scsi_disk_t *dev, int32_t *len, UNUSED(int first_batch), int out) +{ + *len = 0; + uint32_t medium_size = hdd_image_get_last_sector(dev->id); + + if (!dev->sector_len) { + scsi_disk_command_complete(dev); + return -1; + } + + scsi_disk_log("%sing %i blocks starting from %i...\n", out ? "Writ" : "Read", + dev->requested_blocks, dev->sector_pos); + + if (dev->sector_pos >= medium_size) { + scsi_disk_log("SCSI HD %i: Trying to %s beyond the end of disk\n", dev->id, out ? "write" : "read"); + scsi_disk_lba_out_of_range(dev); + return 0; + } + + *len = dev->requested_blocks << 9; + + for (int i = 0; i < dev->requested_blocks; i++) { + if (out) + hdd_image_write(dev->id, dev->sector_pos + i, 1, dev->temp_buffer + (i << 9)); + else + hdd_image_read(dev->id, dev->sector_pos + i, 1, dev->temp_buffer + (i << 9)); + } + + scsi_disk_log("%s %i bytes of blocks...\n", out ? "Written" : "Read", *len); + + dev->sector_pos += dev->requested_blocks; + dev->sector_len -= dev->requested_blocks; + + return 1; +} + static int scsi_disk_pre_execution_check(scsi_disk_t *dev, uint8_t *cdb) { if ((cdb[0] != GPCMD_REQUEST_SENSE) && (dev->cur_lun == SCSI_LUN_USE_CDB) && (cdb[1] & 0xe0)) { scsi_disk_log("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", - dev->id, ((dev->request_length >> 5) & 7)); + dev->id, ((dev->tf->request_length >> 5) & 7)); scsi_disk_invalid_lun(dev); return 0; } if (!(scsi_disk_command_flags[cdb[0]] & IMPLEMENTED)) { - scsi_disk_log("SCSI HD %i: Attempting to execute unknown command %02X\n", dev->id, cdb[0]); + scsi_disk_log("SCSI HD %i: Attempting to execute unknown command %02X over %s\n", dev->id, cdb[0], + (dev->drv->bus == HDD_BUS_SCSI) ? "SCSI" : "ATAPI"); scsi_disk_illegal_opcode(dev); return 0; } @@ -468,10 +793,14 @@ scsi_disk_reset(scsi_common_t *sc) scsi_disk_t *dev = (scsi_disk_t *) sc; scsi_disk_rezero(dev); - dev->status = 0; - dev->callback = 0.0; - dev->packet_status = PHASE_NONE; - dev->cur_lun = SCSI_LUN_USE_CDB; + dev->tf->status = 0; + dev->callback = 0.0; + scsi_disk_set_callback(dev); + dev->tf->phase = 1; + dev->tf->request_length = 0xEB14; + dev->packet_status = PHASE_NONE; + dev->unit_attention = 0; + dev->cur_lun = SCSI_LUN_USE_CDB; } void @@ -507,32 +836,16 @@ scsi_disk_request_sense_for_scsi(scsi_common_t *sc, uint8_t *buffer, uint8_t all } static void -scsi_disk_set_buf_len(UNUSED(scsi_disk_t *dev), int32_t *BufLen, int32_t *src_len) +scsi_disk_set_buf_len(scsi_disk_t *dev, int32_t *BufLen, int32_t *src_len) { - if (*BufLen == -1) - *BufLen = *src_len; - else { - *BufLen = MIN(*src_len, *BufLen); - *src_len = *BufLen; - } - scsi_disk_log("SCSI HD %i: Actual transfer length: %i\n", dev->id, *BufLen); -} - -static void -scsi_disk_buf_alloc(scsi_disk_t *dev, uint32_t len) -{ - scsi_disk_log("SCSI HD %i: Allocated buffer length: %i\n", dev->id, len); - if (!dev->temp_buffer) - dev->temp_buffer = (uint8_t *) malloc(len); -} - -static void -scsi_disk_buf_free(scsi_disk_t *dev) -{ - if (dev->temp_buffer) { - scsi_disk_log("SCSI HD %i: Freeing buffer...\n", dev->id); - free(dev->temp_buffer); - dev->temp_buffer = NULL; + if (dev->drv->bus == HDD_BUS_SCSI) { + if (*BufLen == -1) + *BufLen = *src_len; + else { + *BufLen = MIN(*src_len, *BufLen); + *src_len = *BufLen; + } + scsi_disk_log("SCSI HD %i: Actual transfer length: %i\n", dev->id, *BufLen); } } @@ -540,6 +853,8 @@ static void scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) { scsi_disk_t *dev = (scsi_disk_t *) sc; + int ret; + int32_t blen = 0; int32_t *BufLen; int32_t len; int32_t max_len; @@ -555,12 +870,18 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) uint8_t scsi_bus = (dev->drv->scsi_id >> 4) & 0x0f; uint8_t scsi_id = dev->drv->scsi_id & 0x0f; - BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; + if (dev->drv->bus == HDD_BUS_SCSI) { + BufLen = &scsi_devices[scsi_bus][scsi_id].buffer_length; + dev->tf->status &= ~ERR_STAT; + } else { + BufLen = &blen; + dev->tf->error = 0; + } last_sector = hdd_image_get_last_sector(dev->id); - dev->status &= ~ERR_STAT; dev->packet_len = 0; + dev->request_pos = 0; device_identify[6] = (dev->id / 10) + 0x30; device_identify[7] = (dev->id % 10) + 0x30; @@ -576,7 +897,7 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) if (cdb[0] != 0) { scsi_disk_log("SCSI HD %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", dev->id, cdb[0], scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); - scsi_disk_log("SCSI HD %i: Request length: %04X\n", dev->id, dev->request_length); + scsi_disk_log("SCSI HD %i: Request length: %04X\n", dev->id, dev->tf->request_length); scsi_disk_log("SCSI HD %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], @@ -613,14 +934,16 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) break; case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ + /* If there's a unit attention condition and there's a buffered not + ready, a standalone REQUEST SENSE should forget about the not + ready, and report unit attention straight away. */ len = cdb[4]; if (!len) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); break; } @@ -653,63 +976,80 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) case GPCMD_READ_6: case GPCMD_READ_10: case GPCMD_READ_12: + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); + alloc_length = 512; + switch (cdb[0]) { case GPCMD_READ_6: dev->sector_len = cdb[4]; + /* + For READ (6) and WRITE (6), a length of 0 indicates a + transfer of 256 sectors. + */ if (dev->sector_len == 0) - dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */ - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + dev->sector_len = 256; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | + (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); break; case GPCMD_READ_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; break; case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; default: break; } - if ((dev->sector_pos > last_sector) /* || ((dev->sector_pos + dev->sector_len - 1) > last_sector)*/) { + if (dev->sector_pos > last_sector) { scsi_disk_lba_out_of_range(dev); return; } - if ((!dev->sector_len) || (*BufLen == 0)) { + if (!dev->sector_len) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_log("SCSI HD %i: All done - callback set\n", dev); + scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); break; } max_len = dev->sector_len; + /* + If we're reading all blocks in one go for DMA, why not also for + PIO, it should NOT matter anyway, this step should be identical + and only the way the read dat is transferred to the host should + be different. + */ dev->requested_blocks = max_len; - alloc_length = dev->packet_len = max_len << 9; + dev->packet_len = max_len * alloc_length; scsi_disk_buf_alloc(dev, dev->packet_len); - scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - if ((dev->requested_blocks > 0) && (*BufLen > 0)) { - if (dev->packet_len > (uint32_t) *BufLen) - hdd_image_read(dev->id, dev->sector_pos, *BufLen >> 9, dev->temp_buffer); - else - hdd_image_read(dev->id, dev->sector_pos, dev->requested_blocks, dev->temp_buffer); + ret = scsi_disk_blocks(dev, &alloc_length, 1, 0); + if (ret <= 0) { + scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); + dev->packet_status = PHASE_COMPLETE; + dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); + scsi_disk_buf_free(dev); + return; } - if (dev->requested_blocks > 1) - scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 0); - else - scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); + dev->requested_blocks = max_len; + dev->packet_len = alloc_length; - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_HDD | dev->drv->bus, 1); - else - ui_sb_update_icon(SB_HDD | dev->drv->bus, 0); + scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); + + scsi_disk_data_command_finish(dev, alloc_length, 512, alloc_length, 0); + + ui_sb_update_icon(SB_HDD | dev->drv->bus, dev->packet_status != PHASE_COMPLETE); return; case GPCMD_VERIFY_6: @@ -726,70 +1066,82 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) case GPCMD_WRITE_AND_VERIFY_10: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); + alloc_length = 512; + switch (cdb[0]) { case GPCMD_VERIFY_6: case GPCMD_WRITE_6: dev->sector_len = cdb[4]; + /* + For READ (6) and WRITE (6), a length of 0 indicates a + transfer of 256 sectors. + */ if (dev->sector_len == 0) - dev->sector_len = 256; /* For READ (6) and WRITE (6), a length of 0 indicates a transfer of 256 sector. */ - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + dev->sector_len = 256; + dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | + (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); + scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, + dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_10: case GPCMD_WRITE_10: case GPCMD_WRITE_AND_VERIFY_10: dev->sector_len = (cdb[7] << 8) | cdb[8]; dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); + scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, + dev->sector_len, dev->sector_pos); break; case GPCMD_VERIFY_12: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); + dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | + (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); + dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | + (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); break; default: break; } - if ((dev->sector_pos > last_sector) /* || - ((dev->sector_pos + dev->sector_len - 1) > last_sector)*/ - ) { + if (dev->sector_pos > last_sector) { scsi_disk_lba_out_of_range(dev); return; } - if ((!dev->sector_len) || (*BufLen == 0)) { + if (!dev->sector_len) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); break; } max_len = dev->sector_len; + /* + If we're writing all blocks in one go for DMA, why not also for + PIO, it should NOT matter anyway, this step should be identical + and only the way the read dat is transferred to the host should + be different. + */ dev->requested_blocks = max_len; - alloc_length = dev->packet_len = max_len << 9; + dev->packet_len = max_len * alloc_length; scsi_disk_buf_alloc(dev, dev->packet_len); - scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); + dev->requested_blocks = max_len; + dev->packet_len = max_len << 9; - if (dev->requested_blocks > 1) - scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 1); - else - scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 1); + scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_HDD | dev->drv->bus, 1); - else - ui_sb_update_icon(SB_HDD | dev->drv->bus, 0); + scsi_disk_data_command_finish(dev, dev->packet_len, 512, dev->packet_len, 1); + + ui_sb_update_icon(SB_HDD | dev->drv->bus, dev->packet_status != PHASE_COMPLETE); return; case GPCMD_WRITE_SAME_10: - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); alloc_length = 512; if ((cdb[1] & 6) == 6) { @@ -800,42 +1152,43 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) dev->sector_len = (cdb[7] << 8) | cdb[8]; dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - if ((dev->sector_pos > last_sector) /* || - ((dev->sector_pos + dev->sector_len - 1) > last_sector)*/ - ) { + if (dev->sector_pos > last_sector) { scsi_disk_lba_out_of_range(dev); return; } - if ((!dev->sector_len) || (*BufLen == 0)) { + if (!dev->sector_len) { scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); dev->packet_status = PHASE_COMPLETE; dev->callback = 20.0 * SCSI_TIME; + scsi_disk_set_callback(dev); break; } scsi_disk_buf_alloc(dev, alloc_length); - scsi_disk_set_buf_len(dev, BufLen, &alloc_length); + scsi_disk_set_buf_len(dev, BufLen, (int32_t *) &dev->packet_len); max_len = 1; dev->requested_blocks = 1; + dev->packet_len = alloc_length; + scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); scsi_disk_data_command_finish(dev, 512, 512, alloc_length, 1); - if (dev->packet_status != PHASE_COMPLETE) - ui_sb_update_icon(SB_HDD | dev->drv->bus, 1); - else - ui_sb_update_icon(SB_HDD | dev->drv->bus, 0); + ui_sb_update_icon(SB_HDD | dev->drv->bus, dev->packet_status != PHASE_COMPLETE); return; case GPCMD_MODE_SENSE_6: case GPCMD_MODE_SENSE_10: scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + if (dev->drv->bus == HDD_BUS_SCSI) + block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; + else + block_desc = 0; if (cdb[0] == GPCMD_MODE_SENSE_6) { len = cdb[4]; @@ -968,8 +1321,8 @@ scsi_disk_command(scsi_common_t *sc, uint8_t *cdb) memset(dev->temp_buffer, 0, 8); dev->temp_buffer[0] = 0; /*SCSI HD*/ dev->temp_buffer[1] = 0; /*Fixed*/ - dev->temp_buffer[2] = 0x02; /*SCSI-2 compliant*/ - dev->temp_buffer[3] = 0x02; + dev->temp_buffer[2] = (dev->drv->bus == HDD_BUS_SCSI) ? 0x02 : 0x00; /*SCSI-2 compliant*/ + dev->temp_buffer[3] = (dev->drv->bus == HDD_BUS_SCSI) ? 0x02 : 0x21; dev->temp_buffer[4] = 31; dev->temp_buffer[6] = 1; /* 16-bit transfers supported */ dev->temp_buffer[7] = 0x20; /* Wide bus supported */ @@ -1048,7 +1401,11 @@ atapi_out: break; } - /* scsi_disk_log("SCSI HD %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length); */ + /* scsi_disk_log("SCSI HD %i: Phase: %02X, request length: %i\n", dev->id, dev->tf->phase, + dev->tf->request_length); */ + + if ((dev->packet_status == PHASE_COMPLETE) || (dev->packet_status == PHASE_ERROR)) + scsi_disk_buf_free(dev); } static void @@ -1072,6 +1429,7 @@ scsi_disk_phase_data_out(scsi_common_t *sc) uint32_t c; uint32_t h; uint32_t s; + int len = 0; uint32_t last_to_write = 0; uint16_t block_desc_len; uint16_t pos; @@ -1100,12 +1458,8 @@ scsi_disk_phase_data_out(scsi_common_t *sc) case GPCMD_WRITE_AND_VERIFY_10: case GPCMD_WRITE_12: case GPCMD_WRITE_AND_VERIFY_12: - if ((dev->requested_blocks > 0) && (*BufLen > 0)) { - if (dev->packet_len > (uint32_t) *BufLen) - hdd_image_write(dev->id, dev->sector_pos, *BufLen >> 9, dev->temp_buffer); - else - hdd_image_write(dev->id, dev->sector_pos, dev->requested_blocks, dev->temp_buffer); - } + if (dev->requested_blocks > 0) + scsi_disk_blocks(dev, &len, 1, 1); break; case GPCMD_WRITE_SAME_10: if (!dev->current_cdb[7] && !dev->current_cdb[8]) @@ -1147,15 +1501,18 @@ scsi_disk_phase_data_out(scsi_common_t *sc) param_list_len = dev->current_cdb[4]; } - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = dev->temp_buffer[2]; - block_desc_len <<= 8; - block_desc_len |= dev->temp_buffer[3]; - } else { - block_desc_len = dev->temp_buffer[6]; - block_desc_len <<= 8; - block_desc_len |= dev->temp_buffer[7]; - } + if (dev->drv->bus == HDD_BUS_SCSI) { + if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { + block_desc_len = dev->temp_buffer[2]; + block_desc_len <<= 8; + block_desc_len |= dev->temp_buffer[3]; + } else { + block_desc_len = dev->temp_buffer[6]; + block_desc_len <<= 8; + block_desc_len |= dev->temp_buffer[7]; + } + } else + block_desc_len = 0; pos = hdr_len + block_desc_len; @@ -1210,15 +1567,99 @@ scsi_disk_phase_data_out(scsi_common_t *sc) return 1; } +static int +scsi_disk_get_max(int ide_has_dma, int type) +{ + int ret; + + switch (type) { + case TYPE_PIO: + ret = ide_has_dma ? 4 : 0; + break; + case TYPE_SDMA: + ret = ide_has_dma ? 2 : -1; + break; + case TYPE_MDMA: + ret = ide_has_dma ? 2 : -1; + break; + case TYPE_UDMA: + ret = ide_has_dma ? 5 : -1; + break; + default: + ret = -1; + break; + } + + return ret; +} + +static int +scsi_disk_get_timings(int ide_has_dma, int type) +{ + int ret; + + switch (type) { + case TIMINGS_DMA: + ret = ide_has_dma ? 120 : 0; + break; + case TIMINGS_PIO: + ret = ide_has_dma ? 120 : 0; + break; + case TIMINGS_PIO_FC: + ret = 0; + break; + default: + ret = 0; + break; + } + + return ret; +} + +/** + * Fill in ide->buffer with the output of the "IDENTIFY PACKET DEVICE" command + */ +static void +scsi_disk_identify(ide_t *ide, int ide_has_dma) +{ + const scsi_disk_t *dev; + char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; + + dev = (scsi_disk_t *) ide->sc; + + device_identify[7] = dev->id + 0x30; + scsi_disk_log("ATAPI Identify: %s\n", device_identify); + + /* ATAPI device, direct-access device, non-removable media, accelerated DRQ */ + ide->buffer[0] = 0x8000 | (0 << 8) | 0x00 | (2 << 5); + ide_padstr((char *) (ide->buffer + 10), "", 20); /* Serial Number */ + + ide_padstr((char *) (ide->buffer + 23), EMU_VERSION_EX, 8); /* Firmware */ + ide_padstr((char *) (ide->buffer + 27), device_identify, 40); /* Model */ + + ide->buffer[49] = 0x200; /* LBA supported */ + ide->buffer[126] = 0xfffe; /* Interpret zero byte count limit as maximum length */ + + if (ide_has_dma) { + ide->buffer[71] = 30; + ide->buffer[72] = 30; + ide->buffer[80] = 0x7e; /*ATA-1 to ATA-6 supported*/ + ide->buffer[81] = 0x19; /*ATA-6 revision 3a supported*/ + } +} + void scsi_disk_hard_reset(void) { scsi_disk_t *dev; scsi_device_t *sd; + ide_t *id; uint8_t scsi_bus; uint8_t scsi_id; + uint8_t valid = 0; for (uint8_t c = 0; c < HDD_NUM; c++) { + valid = 0; if (hdd[c].bus == HDD_BUS_SCSI) { scsi_disk_log("SCSI disk hard_reset drive=%d\n", c); @@ -1241,13 +1682,18 @@ scsi_disk_hard_reset(void) if (!hdd_image_load(c)) continue; - if (!hdd[c].priv) { - hdd[c].priv = (scsi_disk_t *) malloc(sizeof(scsi_disk_t)); - memset(hdd[c].priv, 0, sizeof(scsi_disk_t)); - } + valid = 1; + + hdd_preset_apply(c); + + if (!hdd[c].priv) + hdd[c].priv = (scsi_disk_t *) calloc(1, sizeof(scsi_disk_t)); dev = (scsi_disk_t *) hdd[c].priv; + if (!dev->tf) + dev->tf = (ide_tf_t *) calloc(1, sizeof(ide_tf_t)); + /* SCSI disk, attach to the SCSI bus. */ sd = &scsi_devices[scsi_bus][scsi_id]; @@ -1259,14 +1705,60 @@ scsi_disk_hard_reset(void) sd->command_stop = scsi_disk_command_stop; sd->type = SCSI_FIXED_DISK; - dev->id = c; - dev->drv = &hdd[c]; + scsi_disk_log("SCSI disk %i attached to SCSI ID %i\n", c, hdd[c].scsi_id); + } else if (hdd[c].bus == HDD_BUS_ATAPI) { + /* Make sure to ignore any SCSI disk whose image file name is empty. */ + if (strlen(hdd[c].fn) == 0) + continue; + + /* Make sure to ignore any SCSI disk whose image fails to load. */ + /* ATAPI hard disk, attach to the IDE bus. */ + id = ide_get_drive(hdd[c].ide_channel); + /* If the IDE channel is initialized, we attach to it, + otherwise, we do nothing - it's going to be a drive + that's not attached to anything. */ + if (id) { + if (!hdd_image_load(c)) + continue; + + valid = 1; + + hdd_preset_apply(c); + + if (!hdd[c].priv) + hdd[c].priv = (scsi_disk_t *) calloc(1, sizeof(scsi_disk_t)); + + dev = (scsi_disk_t *) hdd[c].priv; + + id->sc = (scsi_common_t *) dev; + dev->tf = id->tf; + IDE_ATAPI_IS_EARLY = 0; + id->get_max = scsi_disk_get_max; + id->get_timings = scsi_disk_get_timings; + id->identify = scsi_disk_identify; + id->stop = NULL; + id->packet_command = scsi_disk_command; + id->device_reset = scsi_disk_reset; + id->phase_data_out = scsi_disk_phase_data_out; + id->command_stop = scsi_disk_command_stop; + id->bus_master_error = scsi_disk_bus_master_error; + id->interrupt_drq = 0; + + ide_atapi_attach(id); + } + + scsi_disk_log("ATAPI hard disk drive %i attached to IDE channel %i\n", c, hdd[c].ide_channel); + } + + if (valid) { + dev->id = c; + dev->drv = &hdd[c]; dev->cur_lun = SCSI_LUN_USE_CDB; - scsi_disk_mode_sense_load(dev); + scsi_disk_init(dev); - scsi_disk_log("SCSI disk %i attached to SCSI ID %i\n", c, hdd[c].scsi_id); + scsi_disk_mode_sense_load(dev); } } } @@ -1279,17 +1771,22 @@ scsi_disk_close(void) uint8_t scsi_id; for (uint8_t c = 0; c < HDD_NUM; c++) { - if (hdd[c].bus == HDD_BUS_SCSI) { - scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; - scsi_id = hdd[c].scsi_id & 0x0f; + if ((hdd[c].bus == HDD_BUS_SCSI) || (hdd[c].bus == HDD_BUS_ATAPI)) { + if (hdd[c].bus == HDD_BUS_SCSI) { + scsi_bus = (hdd[c].scsi_id >> 4) & 0x0f; + scsi_id = hdd[c].scsi_id & 0x0f; - memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); + memset(&scsi_devices[scsi_bus][scsi_id], 0x00, sizeof(scsi_device_t)); + } hdd_image_close(c); dev = hdd[c].priv; if (dev) { + if (dev->tf) + free(dev->tf); + free(dev); hdd[c].priv = NULL; } diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 7e4145d9a..285c65c80 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -1658,6 +1658,8 @@ ncr_init(const device_t *info) } timer_add(&ncr_dev->timer, ncr_callback, ncr_dev, 0); + scsi_bus_set_speed(ncr_dev->bus, 5000000.0); + return ncr_dev; } diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index d863cb6f1..42925338d 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -2623,6 +2623,8 @@ ncr53c8xx_init(const device_t *info) timer_add(&dev->timer, ncr53c8xx_callback, dev, 0); + scsi_bus_set_speed(dev->bus, 10000000.0); + return dev; } diff --git a/src/scsi/scsi_pcscsi.c b/src/scsi/scsi_pcscsi.c index 68f7b2011..7bf06b1c0 100644 --- a/src/scsi/scsi_pcscsi.c +++ b/src/scsi/scsi_pcscsi.c @@ -1870,6 +1870,8 @@ dc390_init(UNUSED(const device_t *info)) timer_add(&dev->timer, esp_callback, dev, 0); + scsi_bus_set_speed(dev->bus, 10000000.0); + return dev; } @@ -2040,6 +2042,8 @@ ncr53c90_mca_init(UNUSED(const device_t *info)) timer_add(&dev->timer, esp_callback, dev, 0); + scsi_bus_set_speed(dev->bus, 5000000.0); + return dev; } diff --git a/src/scsi/scsi_spock.c b/src/scsi/scsi_spock.c index 57a39a8d3..ba2817fe3 100644 --- a/src/scsi/scsi_spock.c +++ b/src/scsi/scsi_spock.c @@ -1164,15 +1164,18 @@ spock_init(const device_t *info) scsi->cmd_timer = SPOCK_TIME * 50; scsi->status = STATUS_BUSY; - for (uint8_t c = 0; c < (SCSI_ID_MAX - 1); c++) { + for (uint8_t c = 0; c < (SCSI_ID_MAX - 1); c++) scsi->dev_id[c].phys_id = -1; - } scsi->dev_id[SCSI_ID_MAX - 1].phys_id = scsi->adapter_id; timer_add(&scsi->callback_timer, spock_callback, scsi, 1); scsi->callback_timer.period = 10.0; - timer_set_delay_u64(&scsi->callback_timer, (uint64_t) (scsi->callback_timer.period * ((double) TIMER_USEC))); + + timer_set_delay_u64(&scsi->callback_timer, + (uint64_t) (scsi->callback_timer.period * ((double) TIMER_USEC))); + + scsi_bus_set_speed(scsi->bus, 5000000.0); return scsi; } diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index bb889921b..5f9fb7f27 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -158,7 +158,6 @@ static uint8_t sb_16_pnp_rom[] = { // clang-format on }; -// #define ENABLE_SB_LOG 1 #ifdef ENABLE_SB_LOG int sb_do_log = ENABLE_SB_LOG; @@ -820,6 +819,14 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) sb->dsp.sb_irqm8 = 0; sb->dsp.sb_irqm16 = 0; sb->dsp.sb_irqm401 = 0; + + mixer->regs[0xfd] = 0x10; + mixer->regs[0xfe] = 0x06; + + mixer->regs[0xff] = sb->dsp.sb_16_dma_supported ? 0x05 : 0x03; + + sb_dsp_setdma16_enabled(&sb->dsp, 0x01); + sb_dsp_setdma16_translate(&sb->dsp, mixer->regs[0xff] & 0x02); } else mixer->regs[mixer->index] = val; @@ -938,11 +945,16 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv) break; case 0xff: - if (sb->dsp.sb_type >= SBAWE32) { - if (val != ISAPNP_DMA_DISABLED) - sb_dsp_setdma16_8(&sb->dsp, val & 0x07); + if (sb->dsp.sb_type >= SB16) { + /* + Bit 5: High DMA channel enabled (0 = yes, 1 = no); + Bit 2: ????; + Bit 1: ???? (16-bit to 8-bit translation?); + Bit 0: ???? + Seen values: 20, 05, 04, 03 + */ sb_dsp_setdma16_enabled(&sb->dsp, !(val & 0x20)); - sb_dsp_setdma16_translate(&sb->dsp, val != ISAPNP_DMA_DISABLED); + sb_dsp_setdma16_translate(&sb->dsp, val & 0x02); } break; @@ -1159,7 +1171,7 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv) - Register FF = FF: Volume playback normal. - Register FF = Not FF: Volume playback low unless bit 6 of 82h is set. */ - if (sb->dsp.sb_type >= SBAWE32) + if (sb->dsp.sb_type >= SB16) ret = mixer->regs[mixer->index]; break; diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 486d6eda6..6fc7815ab 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -502,6 +502,7 @@ sb_16_write_dma(void *priv, uint16_t val) void sb_dsp_setirq(sb_dsp_t *dsp, int irq) { + sb_dsp_log("IRQ now: %i\n", irq); dsp->sb_irqnum = irq; } diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index db86d273f..9e626ccb2 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -223,14 +223,14 @@ typedef struct s3_t { uint16_t subsys_cntl; uint16_t setup_md; uint8_t advfunc_cntl; - uint16_t cur_y, cur_y2, cur_y_bitres; - uint16_t cur_x, cur_x2, cur_x_bitres; + uint16_t cur_y, cur_y2; + uint16_t cur_x, cur_x2; uint16_t x2, ropmix; uint16_t pat_x, pat_y; int16_t desty_axstp, desty_axstp2; int16_t destx_distp; - int16_t err_term, err_term2; int16_t maj_axis_pcnt, maj_axis_pcnt2; + int16_t err_term, err_term2; uint16_t cmd, cmd2; uint16_t short_stroke; uint32_t pat_bg_color, pat_fg_color; @@ -811,7 +811,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0x92e9: s3->accel.err_term = (s3->accel.err_term & 0xff) | ((val & 0x3f) << 8); if (val & 0x20) - s3->accel.err_term |= ~0x3fff; + s3->accel.err_term |= ~0x1fff; break; case 0x914a: case 0x92ea: @@ -821,7 +821,7 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0x92eb: s3->accel.err_term2 = (s3->accel.err_term2 & 0xff) | ((val & 0x3f) << 8); if (val & 0x20) - s3->accel.err_term2 |= ~0x3fff; + s3->accel.err_term2 |= ~0x1fff; break; case 0x9548: @@ -831,8 +831,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0x9459: case 0x96e9: s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xff) | ((val & 0x0f) << 8); - if (val & 0x08) - s3->accel.maj_axis_pcnt |= ~0x0fff; break; case 0x954a: case 0x96ea: @@ -841,8 +839,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) case 0x954b: case 0x96eb: s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xff) | ((val & 0x0f) << 8); - if (val & 0x08) - s3->accel.maj_axis_pcnt2 |= ~0x0fff; break; case 0x9948: @@ -880,13 +876,6 @@ s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val) s3->accel.cx = s3->accel.cur_x & 0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_x & 0x1000) { - s3->accel.cx |= ~0xfff; - } - if (s3->accel.cur_y & 0x1000) { - s3->accel.cy |= ~0xfff; - } - if (s3->accel.cmd & 0x1000) { s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); @@ -1422,13 +1411,6 @@ s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val) s3->accel.cx = s3->accel.cur_x & 0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_x & 0x1000) { - s3->accel.cx |= ~0xfff; - } - if (s3->accel.cur_y & 0x1000) { - s3->accel.cy |= ~0xfff; - } - if (s3->accel.cmd & 0x1000) { s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke & 0xff); s3_short_stroke_start(-1, 0, 0xffffffff, 0, s3, s3->accel.short_stroke >> 8); @@ -6364,6 +6346,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } s3->accel.ssv_len--; + s3->accel.cx &= 0xfff; + s3->accel.cy &= 0xfff; } s3->accel.cur_x = s3->accel.cx; @@ -6375,13 +6359,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (!cpu_input) { s3->accel.cx = s3->accel.cur_x & 0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; - - if (s3->accel.cur_x & 0x1000) - s3->accel.cx |= ~0xfff; - - if (s3->accel.cur_y & 0x1000) - s3->accel.cy |= ~0xfff; - s3->accel.sy = s3->accel.maj_axis_pcnt; if (s3_cpu_src(s3)) @@ -6428,9 +6405,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ else cpu_dat >>= 16; - if (!s3->accel.sy) { + if (!s3->accel.sy) break; - } switch (s3->accel.cmd & 0xe0) { case 0x00: @@ -6466,6 +6442,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ break; } s3->accel.sy--; + s3->accel.cx &= 0xfff; + s3->accel.cy &= 0xfff; } s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; @@ -6526,9 +6504,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ cpu_dat >>= 16; } - if (!s3->accel.sy) { + if (!s3->accel.sy) break; - } if (s3->accel.err_term >= s3->accel.maj_axis_pcnt) { s3->accel.err_term += s3->accel.destx_distp; @@ -6597,6 +6574,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ break; } s3->accel.sy--; + s3->accel.cx &= 0xfff; + s3->accel.cy &= 0xfff; } s3->accel.cur_x = s3->accel.cx; s3->accel.cur_y = s3->accel.cy; @@ -6611,13 +6590,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx = s3->accel.cur_x & 0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_x & 0x1000) { - s3->accel.cx |= ~0xfff; - } - if (s3->accel.cur_y & 0x1000) { - s3->accel.cy |= ~0xfff; - } - s3->accel.dest = dstbase + s3->accel.cy * s3->width; if (s3_cpu_src(s3)) { @@ -6709,6 +6681,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ else s3->accel.cx--; + s3->accel.cx &= 0xfff; s3->accel.sx--; if (s3->accel.sx < 0) { if (s3->accel.cmd & 0x20) @@ -6722,6 +6695,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ else s3->accel.cy--; + s3->accel.cy &= 0xfff; s3->accel.dest = dstbase + s3->accel.cy * s3->width; s3->accel.sy--; @@ -6840,13 +6814,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx = s3->accel.cur_x & 0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_x & 0x1000) { - s3->accel.cx |= ~0xfff; - } - if (s3->accel.cur_y & 0x1000) { - s3->accel.cy |= ~0xfff; - } - s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; } @@ -6894,8 +6861,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ } } else { while (count-- && s3->accel.sy >= 0) { - /*This is almost required by OS/2's software cursor or we will risk writing/reading garbage around it.*/ - if ((s3->accel.dx) >= clip_l && (s3->accel.dx) <= clip_r && ((s3->accel.dy) >= clip_t && (s3->accel.dy) <= clip_b)) { + if ((s3->accel.dx & 0xfff) >= clip_l && (s3->accel.dx & 0xfff) <= clip_r && ((s3->accel.dy & 0xfff) >= clip_t && (s3->accel.dy & 0xfff) <= clip_b)) { if (vram_mask && (s3->accel.cmd & 0x10)) { READ(s3->accel.src + s3->accel.cx, mix_dat); mix_dat = ((mix_dat & rd_mask) == rd_mask); @@ -6952,13 +6918,12 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.sx--; if (s3->accel.sx < 0) { if (s3->accel.cmd & 0x20) { - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.cx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.dx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); } else { - s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.cx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.dx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); } - s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; if (s3->accel.cmd & 0x80) { @@ -6968,7 +6933,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy--; s3->accel.dy--; } - s3->accel.src = srcbase + s3->accel.cy * s3->width; s3->accel.dest = dstbase + s3->accel.dy * s3->width; @@ -7000,11 +6964,7 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dy |= ~0xfff; s3->accel.cx = s3->accel.cur_x & 0xfff; - if (s3->accel.cur_x & 0x1000) - s3->accel.cx |= ~0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_y & 0x1000) - s3->accel.cy |= ~0xfff; /*Align source with destination*/ s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx; @@ -7078,11 +7038,11 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.sx--; if (s3->accel.sx < 0) { if (s3->accel.cmd & 0x20) { - s3->accel.cx = ((s3->accel.cx - ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.cx = ((s3->accel.cx - (((s3->accel.maj_axis_pcnt & 0xfff) + 1))) & 7) | (s3->accel.cx & ~7); + s3->accel.dx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); } else { - s3->accel.cx = ((s3->accel.cx + ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7); - s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.cx = ((s3->accel.cx + (((s3->accel.maj_axis_pcnt & 0xfff) + 1))) & 7) | (s3->accel.cx & ~7); + s3->accel.dx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); } s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; @@ -7124,12 +7084,8 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff; - s3->accel.cx = s3->accel.cur_x; - if (s3->accel.cur_x & 0x1000) - s3->accel.cx |= ~0xfff; - s3->accel.cy = s3->accel.cur_y; - if (s3->accel.cur_y & 0x1000) - s3->accel.cy |= ~0xfff; + s3->accel.cx = s3->accel.cur_x & 0xfff; + s3->accel.cy = s3->accel.cur_y & 0xfff; } if ((s3->accel.cmd & 0x100) && !cpu_input) @@ -7159,12 +7115,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cy++; else s3->accel.cy--; - } + s3->accel.cy &= 0xfff; + } if (s3->accel.destx_distp > s3->accel.cur_x) s3->accel.cx++; else s3->accel.cx--; + + s3->accel.cx &= 0xfff; } } else { error = s3->accel.dy / 2; @@ -7190,11 +7149,15 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.cx++; else s3->accel.cx--; + + s3->accel.cx &= 0xfff; } if (s3->accel.desty_axstp > s3->accel.cur_y) s3->accel.cy++; else s3->accel.cy--; + + s3->accel.cy &= 0xfff; } } s3->accel.cur_x = s3->accel.cx; @@ -7316,18 +7279,10 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dy |= ~0xfff; s3->accel.cx = s3->accel.cur_x & 0xfff; - if (s3->accel.cur_x & 0x1000) - s3->accel.cx |= ~0xfff; s3->accel.cy = s3->accel.cur_y & 0xfff; - if (s3->accel.cur_y & 0x1000) - s3->accel.cy |= ~0xfff; s3->accel.px = s3->accel.pat_x & 0xfff; - if (s3->accel.pat_x & 0x1000) - s3->accel.px |= ~0xfff; s3->accel.py = s3->accel.pat_y & 0xfff; - if (s3->accel.pat_y & 0x1000) - s3->accel.py |= ~0xfff; s3->accel.dest = dstbase + (s3->accel.dy * s3->width); s3->accel.src = srcbase + (s3->accel.cy * s3->width); @@ -7428,13 +7383,13 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.sx--; if (s3->accel.sx < 0) { if (s3->accel.cmd & 0x20) { - s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.px -= (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.cx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.dx -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.px -= ((s3->accel.maj_axis_pcnt & 0xfff) + 1); } else { - s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1; - s3->accel.px += (s3->accel.maj_axis_pcnt & 0xfff) + 1; + s3->accel.cx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.dx += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); + s3->accel.px += ((s3->accel.maj_axis_pcnt & 0xfff) + 1); } s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff; @@ -7447,7 +7402,6 @@ s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_ s3->accel.dy--; s3->accel.py--; } - s3->accel.src = srcbase + (s3->accel.cy * s3->width); s3->accel.dest = dstbase + (s3->accel.dy * s3->width); s3->accel.pattern = (s3->accel.py * s3->width); diff --git a/src/video/vid_tgui9440.c b/src/video/vid_tgui9440.c index aa89f8681..0b5e99c4c 100644 --- a/src/video/vid_tgui9440.c +++ b/src/video/vid_tgui9440.c @@ -113,7 +113,7 @@ typedef struct tgui_t { struct { - int32_t src_x, src_y; + int16_t src_x, src_y; int16_t src_x_clip, src_y_clip; int16_t dst_x, dst_y; int16_t dst_y_clip, dst_x_clip; @@ -129,9 +129,9 @@ typedef struct tgui_t { int offset; uint16_t ger22; - int32_t err; + int16_t err; int16_t top, left, bottom, right; - int x, y, dx, dy; + int16_t x, y, cx, cy, dx, dy; uint32_t src, dst, src_old, dst_old; int pat_x, pat_y; int use_src; @@ -1699,49 +1699,47 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) break; case TGUI_SCANLINE: - { - if (count == -1) { - tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch); - tgui->accel.src = tgui->accel.src_old; + if (count == -1) { + tgui->accel.src_old = tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch); + tgui->accel.src = tgui->accel.src_old; - tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch); - tgui->accel.dst = tgui->accel.dst_old; + tgui->accel.dst_old = tgui->accel.dst_x + (tgui->accel.dst_y * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old; - tgui->accel.pat_x = tgui->accel.dst_x; - tgui->accel.pat_y = tgui->accel.dst_y; + tgui->accel.pat_x = tgui->accel.dst_x; + tgui->accel.pat_y = tgui->accel.dst_y; + } + + while (count--) { + READ(tgui->accel.src, src_dat); + READ(tgui->accel.dst, dst_dat); + + pat_dat = pattern_data[((tgui->accel.pat_y & 7) * 8) + (tgui->accel.pat_x & 7)]; + + if (tgui->accel.bpp == 0) + pat_dat &= 0xff; + else if (tgui->accel.bpp == 1) + pat_dat &= 0xffff; + + if (!(tgui->accel.flags & TGUI_TRANSENA) || (src_dat != trans_col)) { + MIX(); + + WRITE(tgui->accel.dst, out); } - while (count--) { - READ(tgui->accel.src, src_dat); - READ(tgui->accel.dst, dst_dat); + tgui->accel.src += xdir; + tgui->accel.dst += xdir; + tgui->accel.pat_x += xdir; - pat_dat = pattern_data[((tgui->accel.pat_y & 7) * 8) + (tgui->accel.pat_x & 7)]; + tgui->accel.x++; + if (tgui->accel.x > tgui->accel.size_x) { + tgui->accel.x = 0; - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; - - if (!(tgui->accel.flags & TGUI_TRANSENA) || (src_dat != trans_col)) { - MIX(); - - WRITE(tgui->accel.dst, out); - } - - tgui->accel.src += xdir; - tgui->accel.dst += xdir; - tgui->accel.pat_x += xdir; - - tgui->accel.x++; - if (tgui->accel.x > tgui->accel.size_x) { - tgui->accel.x = 0; - - tgui->accel.pat_x = tgui->accel.dst_x; - tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); - tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); - tgui->accel.pat_y += ydir; - return; - } + tgui->accel.pat_x = tgui->accel.dst_x; + tgui->accel.src = tgui->accel.src_old = tgui->accel.src_old + (ydir * tgui->accel.pitch); + tgui->accel.dst = tgui->accel.dst_old = tgui->accel.dst_old + (ydir * tgui->accel.pitch); + tgui->accel.pat_y += ydir; + return; } } break; @@ -1750,11 +1748,7 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) if (count == -1) { tgui->accel.dx = tgui->accel.dst_x & 0xfff; tgui->accel.dy = tgui->accel.dst_y & 0xfff; - - if (tgui->accel.dst_x & 0x1000) - tgui->accel.dx |= ~0xfff; - if (tgui->accel.dst_y & 0x1000) - tgui->accel.dy |= ~0xfff; + tgui->accel.y = tgui->accel.size_y; tgui->accel.left = tgui->accel.src_x_clip & 0xfff; tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; @@ -1770,113 +1764,74 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) } } -#if 0 - pclog("TGUI bres = %04x, err = %d, sizex = %d, sizey = %d, srcx = %d, srcy = %d.\n", tgui->accel.flags & 0x700, err, tgui->accel.size_x, tgui->accel.size_y, cx, tgui->accel.src_y); -#endif - while (count-- && (tgui->accel.y <= (tgui->accel.size_y))) { -#if 0 - READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch), src_dat); -#endif - + while (count--) { /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ - if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && tgui->accel.dx >= tgui->accel.left && tgui->accel.dx <= tgui->accel.right && tgui->accel.dy >= tgui->accel.top && tgui->accel.dy <= tgui->accel.bottom)) { + if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && ((tgui->accel.dx & 0xfff) >= tgui->accel.left) && ((tgui->accel.dx & 0xfff) <= tgui->accel.right) && ((tgui->accel.dy & 0xfff) >= tgui->accel.top) && ((tgui->accel.dy & 0xfff) <= tgui->accel.bottom))) { READ(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), dst_dat); pat_dat = tgui->accel.fg_col; - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; - MIX(); WRITE(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), out); } - if (tgui->accel.y == (tgui->accel.size_y & 0xfff)) { + if (!tgui->accel.y) break; - } - if (tgui->accel.err >= (tgui->accel.size_y & 0xfff)) { -#if 0 - pclog("Bres DEC: destx = %d, desty = %d, err = %d, sizey = %d.\n", tgui->accel.src_x, tgui->accel.src_y, tgui->accel.err, tgui->accel.size_y); -#endif - if ((tgui->accel.src_x >= 2048) && (tgui->accel.src_x < 4096)) - tgui->accel.err -= (4096 - tgui->accel.src_x); - else if ((tgui->accel.src_x >= 4096) && (tgui->accel.src_x < 32768)) - tgui->accel.err -= (32768 - tgui->accel.src_x); - else - tgui->accel.err += tgui->accel.src_x; + if (tgui->accel.size_x >= 0) { + tgui->accel.size_x += tgui->accel.src_x; /*Step minor axis*/ - switch (tgui->accel.flags & 0x700) { - case 0x300: - tgui->accel.dy--; - break; - case 0x100: - tgui->accel.dy--; - break; - case 0x700: - tgui->accel.dx--; - break; - case 0x500: - tgui->accel.dx++; - break; - case 0x200: + switch ((tgui->accel.flags >> 8) & 7) { + case 0: + case 2: tgui->accel.dy++; break; - case 0x000: - tgui->accel.dy++; + case 1: + case 3: + tgui->accel.dy--; break; - case 0x600: - tgui->accel.dx--; - break; - case 0x400: + case 4: + case 5: tgui->accel.dx++; break; + case 6: + case 7: + tgui->accel.dx--; + break; default: break; - } - } else { -#if 0 - pclog("Bres INC: desty = %d, destx = %d, err = %d, sizey = %d.\n", tgui->accel.src_y, tgui->accel.src_x, tgui->accel.err, tgui->accel.size_y); -#endif - tgui->accel.err += tgui->accel.src_y; - } + } + } else + tgui->accel.size_x += tgui->accel.src_y; /*Step major axis*/ - switch (tgui->accel.flags & 0x700) { - case 0x300: - tgui->accel.dx--; - break; - case 0x100: + switch ((tgui->accel.flags >> 8) & 7) { + case 0: + case 1: tgui->accel.dx++; break; - case 0x700: - tgui->accel.dy--; - break; - case 0x500: - tgui->accel.dy--; - break; - case 0x200: + case 2: + case 3: tgui->accel.dx--; break; - case 0x000: - tgui->accel.dx++; - break; - case 0x600: + case 4: + case 6: tgui->accel.dy++; break; - case 0x400: - tgui->accel.dy++; + case 5: + case 7: + tgui->accel.dy--; break; default: break; } - tgui->accel.y++; + tgui->accel.y--; + tgui->accel.dx &= 0xfff; + tgui->accel.dy &= 0xfff; } break; @@ -1884,11 +1839,7 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) if (count == -1) { tgui->accel.dx = tgui->accel.dst_x & 0xfff; tgui->accel.dy = tgui->accel.dst_y & 0xfff; - - if (tgui->accel.dst_x & 0x1000) - tgui->accel.dx |= ~0xfff; - if (tgui->accel.dst_y & 0x1000) - tgui->accel.dy |= ~0xfff; + tgui->accel.y = tgui->accel.sv_size_y & 0xfff; tgui->accel.left = tgui->accel.src_x_clip & 0xfff; tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; @@ -1904,28 +1855,19 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) } } - while (count-- && (tgui->accel.y <= (tgui->accel.sv_size_y & 0xfff))) { -#if 0 - READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch), src_dat); -#endif - + while (count--) { /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ - if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && tgui->accel.dx >= tgui->accel.left && tgui->accel.dx <= tgui->accel.right && tgui->accel.dy >= tgui->accel.top && tgui->accel.dy <= tgui->accel.bottom)) { + if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && ((tgui->accel.dx & 0xfff) >= tgui->accel.left) && ((tgui->accel.dx & 0xfff) <= tgui->accel.right) && ((tgui->accel.dy & 0xfff) >= tgui->accel.top) && ((tgui->accel.dy & 0xfff) <= tgui->accel.bottom))) { READ(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), dst_dat); pat_dat = tgui->accel.fg_col; - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; - MIX(); WRITE(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), out); } - if (tgui->accel.y == (tgui->accel.sv_size_y & 0xfff)) + if (!tgui->accel.y) break; switch ((tgui->accel.sv_size_y >> 8) & 0xe0) { @@ -1962,7 +1904,9 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) break; } - tgui->accel.y++; + tgui->accel.y--; + tgui->accel.dx &= 0xfff; + tgui->accel.dy &= 0xfff; } break; @@ -1973,11 +1917,7 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) if (count == -1) { tgui->accel.dx = tgui->accel.dst_x & 0xfff; tgui->accel.dy = tgui->accel.dst_y & 0xfff; - - if (tgui->accel.dst_x & 0x1000) - tgui->accel.dx |= ~0xfff; - if (tgui->accel.dst_y & 0x1000) - tgui->accel.dy |= ~0xfff; + tgui->accel.y = tgui->accel.size_y; tgui->accel.left = tgui->accel.src_x_clip & 0xfff; tgui->accel.right = tgui->accel.dst_x_clip & 0xfff; @@ -1993,28 +1933,19 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) } } - while (count-- && (tgui->accel.y <= (tgui->accel.size_y & 0xfff))) { -#if 0 - READ(tgui->accel.src_x + (tgui->accel.src_y * tgui->accel.pitch), src_dat); -#endif - + while (count--) { /*Note by TC1995: I suppose the x/y clipping max is always more than 0 in the TGUI 96xx, but the TGUI 9440 lacks clipping*/ - if (tgui->accel.dx >= tgui->accel.left && tgui->accel.dx <= tgui->accel.right && tgui->accel.dy >= tgui->accel.top && tgui->accel.dy <= tgui->accel.bottom) { + if ((tgui->type == TGUI_9440) || ((tgui->type >= TGUI_9660) && ((tgui->accel.dx & 0xfff) >= tgui->accel.left) && ((tgui->accel.dx & 0xfff) <= tgui->accel.right) && ((tgui->accel.dy & 0xfff) >= tgui->accel.top) && ((tgui->accel.dy & 0xfff) <= tgui->accel.bottom))) { READ(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), dst_dat); pat_dat = tgui->accel.fg_col; - if (tgui->accel.bpp == 0) - pat_dat &= 0xff; - else if (tgui->accel.bpp == 1) - pat_dat &= 0xffff; - MIX(); WRITE(tgui->accel.dx + (tgui->accel.dy * tgui->accel.pitch), out); } - if (tgui->accel.y == (tgui->accel.size_y & 0xfff)) + if (!tgui->accel.y) break; switch ((tgui->accel.size_y >> 8) & 0xe0) { @@ -2051,7 +1982,9 @@ tgui_accel_command(int count, uint32_t cpu_dat, tgui_t *tgui) break; } - tgui->accel.y++; + tgui->accel.y--; + tgui->accel.dx &= 0xfff; + tgui->accel.dy &= 0xfff; } break; @@ -2182,36 +2115,37 @@ tgui_accel_out(uint16_t addr, uint8_t val, void *priv) tgui->accel.dst_y = (tgui->accel.dst_y & 0xff) | (val << 8); break; - case 0x213c: /*Src X*/ - tgui->accel.src_x = (tgui->accel.src_x & 0xff00) | val; + case 0x213c: /*Src X, Diagonal Step Constant*/ + tgui->accel.src_x = (tgui->accel.src_x & 0x3f00) | val; break; - case 0x213d: /*Src X*/ - tgui->accel.src_x = (tgui->accel.src_x & 0xff) | (val << 8); + case 0x213d: /*Src X, Diagonal Step Constant*/ + tgui->accel.src_x = (tgui->accel.src_x & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + tgui->accel.src_x |= ~0x3fff; break; - case 0x213e: /*Src Y*/ - tgui->accel.src_y = (tgui->accel.src_y & 0xff00) | val; + case 0x213e: /*Src Y, Axial Step Constant*/ + tgui->accel.src_y = (tgui->accel.src_y & 0x3f00) | val; break; - case 0x213f: /*Src Y*/ - tgui->accel.src_y = (tgui->accel.src_y & 0xff) | (val << 8); + case 0x213f: /*Src Y, Axial Step Constant*/ + tgui->accel.src_y = (tgui->accel.src_y & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + tgui->accel.src_y |= ~0x3fff; break; - case 0x2140: /*Size X*/ - tgui->accel.size_x = (tgui->accel.size_x & 0xff00) | val; + case 0x2140: /*Size X, Line Error Term*/ + tgui->accel.size_x = (tgui->accel.size_x & 0x3f00) | val; break; - case 0x2141: /*Size X*/ - tgui->accel.size_x = (tgui->accel.size_x & 0xff) | (val << 8); - tgui->accel.err = tgui->accel.size_x; - if ((tgui->accel.err >= 2048) && (tgui->accel.err < 4096)) - tgui->accel.err -= 4096; - else if ((tgui->accel.err >= 4096) && (tgui->accel.err < 32768)) - tgui->accel.err -= 32768; + case 0x2141: /*Size X, Line Error Term*/ + tgui->accel.size_x = (tgui->accel.size_x & 0xff) | ((val & 0x3f) << 8); + if (val & 0x20) + tgui->accel.size_x |= ~0x1fff; break; - case 0x2142: /*Size Y*/ - tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val; + case 0x2142: /*Size Y, Major Axis Pixel Count*/ + tgui->accel.size_y = (tgui->accel.size_y & 0xf00) | val; tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff00) | val; break; - case 0x2143: /*Size Y*/ - tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8); + case 0x2143: /*Size Y, Major Axis Pixel Count*/ + tgui->accel.size_y = (tgui->accel.size_y & 0xff) | ((val & 0x0f) << 8); tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff) | (val << 8); break; @@ -2717,311 +2651,7 @@ tgui_accel_write(uint32_t addr, uint8_t val, void *priv) return; } - switch (addr & 0xff) { - case 0x22: - tgui_accel_out(0x2122, val, tgui); - break; - - case 0x23: - tgui_accel_out(0x2123, val, tgui); - break; - - case 0x24: /*Command*/ - tgui->accel.command = val; - tgui_accel_command(-1, 0, tgui); - break; - - case 0x27: /*ROP*/ - tgui->accel.rop = val; - tgui->accel.use_src = (val & 0x33) ^ ((val >> 2) & 0x33); - break; - - case 0x28: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0xffffff00) | val; - break; - case 0x29: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0xffff00ff) | (val << 8); - break; - case 0x2a: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0xff00ffff) | (val << 16); - break; - case 0x2b: /*Flags*/ - tgui->accel.flags = (tgui->accel.flags & 0x0000ffff) | (val << 24); - break; - - case 0x2c: /*Foreground colour*/ - case 0x78: - tgui->accel.fg_col = (tgui->accel.fg_col & 0xffffff00) | val; - break; - case 0x2d: /*Foreground colour*/ - case 0x79: - tgui->accel.fg_col = (tgui->accel.fg_col & 0xffff00ff) | (val << 8); - break; - case 0x2e: /*Foreground colour*/ - case 0x7a: - tgui->accel.fg_col = (tgui->accel.fg_col & 0xff00ffff) | (val << 16); - break; - case 0x2f: /*Foreground colour*/ - case 0x7b: - tgui->accel.fg_col = (tgui->accel.fg_col & 0x00ffffff) | (val << 24); - break; - - case 0x30: /*Background colour*/ - case 0x7c: - tgui->accel.bg_col = (tgui->accel.bg_col & 0xffffff00) | val; - break; - case 0x31: /*Background colour*/ - case 0x7d: - tgui->accel.bg_col = (tgui->accel.bg_col & 0xffff00ff) | (val << 8); - break; - case 0x32: /*Background colour*/ - case 0x7e: - tgui->accel.bg_col = (tgui->accel.bg_col & 0xff00ffff) | (val << 16); - break; - case 0x33: /*Background colour*/ - case 0x7f: - tgui->accel.bg_col = (tgui->accel.bg_col & 0x00ffffff) | (val << 24); - break; - - case 0x34: /*Pattern location*/ - tgui->accel.patloc = (tgui->accel.patloc & 0xff00) | val; - break; - case 0x35: /*Pattern location*/ - tgui->accel.patloc = (tgui->accel.patloc & 0xff) | (val << 8); - break; - - case 0x38: /*Dest X*/ - tgui->accel.dst_x = (tgui->accel.dst_x & 0xff00) | val; - break; - case 0x39: /*Dest X*/ - tgui->accel.dst_x = (tgui->accel.dst_x & 0xff) | (val << 8); - break; - case 0x3a: /*Dest Y*/ - tgui->accel.dst_y = (tgui->accel.dst_y & 0xff00) | val; - break; - case 0x3b: /*Dest Y*/ - tgui->accel.dst_y = (tgui->accel.dst_y & 0xff) | (val << 8); - break; - - case 0x3c: /*Src X*/ - tgui->accel.src_x = (tgui->accel.src_x & 0xff00) | val; - break; - case 0x3d: /*Src X*/ - tgui->accel.src_x = (tgui->accel.src_x & 0xff) | (val << 8); - break; - case 0x3e: /*Src Y*/ - tgui->accel.src_y = (tgui->accel.src_y & 0xff00) | val; - break; - case 0x3f: /*Src Y*/ - tgui->accel.src_y = (tgui->accel.src_y & 0xff) | (val << 8); - break; - - case 0x40: /*Size X*/ - tgui->accel.size_x = (tgui->accel.size_x & 0xff00) | val; - break; - case 0x41: /*Size X*/ - tgui->accel.size_x = (tgui->accel.size_x & 0xff) | (val << 8); - tgui->accel.err = tgui->accel.size_x; - if ((tgui->accel.err >= 2048) && (tgui->accel.err < 4096)) - tgui->accel.err -= 4096; - else if ((tgui->accel.err >= 4096) && (tgui->accel.err < 32768)) - tgui->accel.err -= 32768; - break; - case 0x42: /*Size Y*/ - tgui->accel.size_y = (tgui->accel.size_y & 0xff00) | val; - tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff00) | val; - break; - case 0x43: /*Size Y*/ - tgui->accel.size_y = (tgui->accel.size_y & 0xff) | (val << 8); - tgui->accel.sv_size_y = (tgui->accel.sv_size_y & 0xff) | (val << 8); - break; - - case 0x44: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0xffffff00) | val; - break; - case 0x45: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0xffff00ff) | (val << 8); - break; - case 0x46: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0xff00ffff) | (val << 16); - break; - case 0x47: /*Style*/ - tgui->accel.style = (tgui->accel.style & 0x00ffffff) | (val << 24); - break; - - case 0x48: /*Clip Src X*/ - tgui->accel.src_x_clip = (tgui->accel.src_x_clip & 0xff00) | val; - break; - case 0x49: /*Clip Src X*/ - tgui->accel.src_x_clip = (tgui->accel.src_x_clip & 0xff) | (val << 8); - break; - case 0x4a: /*Clip Src Y*/ - tgui->accel.src_y_clip = (tgui->accel.src_y_clip & 0xff00) | val; - break; - case 0x4b: /*Clip Src Y*/ - tgui->accel.src_y_clip = (tgui->accel.src_y_clip & 0xff) | (val << 8); - break; - - case 0x4c: /*Clip Dest X*/ - tgui->accel.dst_x_clip = (tgui->accel.dst_x_clip & 0xff00) | val; - break; - case 0x4d: /*Clip Dest X*/ - tgui->accel.dst_x_clip = (tgui->accel.dst_x_clip & 0xff) | (val << 8); - break; - case 0x4e: /*Clip Dest Y*/ - tgui->accel.dst_y_clip = (tgui->accel.dst_y_clip & 0xff00) | val; - break; - case 0x4f: /*Clip Dest Y*/ - tgui->accel.dst_y_clip = (tgui->accel.dst_y_clip & 0xff) | (val << 8); - break; - - case 0x68: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0xffffff00) | val; - break; - case 0x69: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0xffff00ff) | (val << 8); - break; - case 0x6a: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0xff00ffff) | (val << 16); - break; - case 0x6b: /*CKey*/ - tgui->accel.ckey = (tgui->accel.ckey & 0x00ffffff) | (val << 24); - break; - - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8a: - case 0x8b: - case 0x8c: - case 0x8d: - case 0x8e: - case 0x8f: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x98: - case 0x99: - case 0x9a: - case 0x9b: - case 0x9c: - case 0x9d: - case 0x9e: - case 0x9f: - case 0xa0: - case 0xa1: - case 0xa2: - case 0xa3: - case 0xa4: - case 0xa5: - case 0xa6: - case 0xa7: - case 0xa8: - case 0xa9: - case 0xaa: - case 0xab: - case 0xac: - case 0xad: - case 0xae: - case 0xaf: - case 0xb0: - case 0xb1: - case 0xb2: - case 0xb3: - case 0xb4: - case 0xb5: - case 0xb6: - case 0xb7: - case 0xb8: - case 0xb9: - case 0xba: - case 0xbb: - case 0xbc: - case 0xbd: - case 0xbe: - case 0xbf: - case 0xc0: - case 0xc1: - case 0xc2: - case 0xc3: - case 0xc4: - case 0xc5: - case 0xc6: - case 0xc7: - case 0xc8: - case 0xc9: - case 0xca: - case 0xcb: - case 0xcc: - case 0xcd: - case 0xce: - case 0xcf: - case 0xd0: - case 0xd1: - case 0xd2: - case 0xd3: - case 0xd4: - case 0xd5: - case 0xd6: - case 0xd7: - case 0xd8: - case 0xd9: - case 0xda: - case 0xdb: - case 0xdc: - case 0xdd: - case 0xde: - case 0xdf: - case 0xe0: - case 0xe1: - case 0xe2: - case 0xe3: - case 0xe4: - case 0xe5: - case 0xe6: - case 0xe7: - case 0xe8: - case 0xe9: - case 0xea: - case 0xeb: - case 0xec: - case 0xed: - case 0xee: - case 0xef: - case 0xf0: - case 0xf1: - case 0xf2: - case 0xf3: - case 0xf4: - case 0xf5: - case 0xf6: - case 0xf7: - case 0xf8: - case 0xf9: - case 0xfa: - case 0xfb: - case 0xfc: - case 0xfd: - case 0xfe: - case 0xff: - tgui->accel.pattern[addr & 0x7f] = val; - break; - - default: - break; - } + tgui_accel_out((addr & 0xff) + 0x2100, val, tgui); } static void