From 2a5a8f74317c1100ef20b542ceea8fd384126ab6 Mon Sep 17 00:00:00 2001 From: OBattler Date: Fri, 3 Nov 2023 05:54:30 +0100 Subject: [PATCH] Assorted IDE fixes and the PCI IDE bus master now also resets ATAPI hard disks. --- src/chipset/intel_piix.c | 2 -- src/disk/hdc_ide.c | 54 +++++++++++++++++------------------ src/disk/hdc_ide_sff8038i.c | 33 +++++++++------------ src/include/86box/hdc_ide.h | 6 ++-- src/include/86box/scsi_disk.h | 2 ++ src/scsi/scsi_disk.c | 3 +- 6 files changed, 48 insertions(+), 52 deletions(-) diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index e5b90d861..2094eefcf 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1172,8 +1172,6 @@ piix_read(int func, int addr, void *priv) if ((func <= dev->max_func) || ((func == 1) && (dev->max_func == 0))) { fregs = (uint8_t *) dev->regs[func]; ret = fregs[addr]; - if ((func == 2) && (addr == 0xff)) - ret |= 0xef; piix_log("PIIX function %i read: %02X from %02X\n", func, ret, addr); } diff --git a/src/disk/hdc_ide.c b/src/disk/hdc_ide.c index 2dffeeec3..049ebd259 100644 --- a/src/disk/hdc_ide.c +++ b/src/disk/hdc_ide.c @@ -336,7 +336,7 @@ ide_atapi_get_period(uint8_t channel) } static void -ide_irq_update(ide_board_t *dev) +ide_irq_update(ide_board_t *dev, int log) { ide_t *ide; uint8_t set; @@ -344,7 +344,10 @@ ide_irq_update(ide_board_t *dev) if (dev == NULL) return; - ide_log("IDE %i: IRQ update (%i)\n", dev->cur_dev >> 1, dev->irq); +#ifdef ENABLE_IDE_LOG + if (log) + ide_log("IDE %i: IRQ update (%i)\n", dev->cur_dev >> 1, dev->irq); +#endif ide = ide_drives[dev->cur_dev]; set = !(ide_boards[ide->board]->devctl & 2) && ide->irqstat; @@ -356,32 +359,22 @@ ide_irq_update(ide_board_t *dev) } void -ide_irq_raise(ide_t *ide) +ide_irq(ide_t *ide, int set, int log) { if (!ide_boards[ide->board]) return; - ide_log("IDE %i: IRQ raise\n", ide->channel); +#ifdef IDE_MORE_SPECIFIC_LOGS + ide_log("IDE %i: IRQ %s\n", set ? "raise" : "lower"); +#endif - ide->irqstat = 1; - ide->service = 1; + ide->irqstat = set; + + if (set) + ide->service = 1; if (ide->selected) - ide_irq_update(ide_boards[ide->board]); -} - -void -ide_irq_lower(ide_t *ide) -{ - if (!ide_boards[ide->board]) - return; - - ide_log("IDE %i: IRQ lower\n", ide->channel); - - ide->irqstat = 0; - - if (ide->selected) - ide_irq_update(ide_boards[ide->board]); + ide_irq_update(ide_boards[ide->board], log); } /** @@ -1214,7 +1207,9 @@ ide_writew(uint16_t addr, uint16_t val, void *priv) ch = dev->cur_dev; ide = ide_drives[ch]; +#ifdef IDE_MORE_SPECIFIC_LOGS ide_log("ide_writew(%04X, %04X, %08X)\n", addr, val, priv); +#endif addr &= 0x7; @@ -1246,7 +1241,9 @@ ide_writel(uint16_t addr, uint32_t val, void *priv) ch = dev->cur_dev; ide = ide_drives[ch]; +#ifdef IDE_MORE_SPECIFIC_LOGS ide_log("ide_writel(%04X, %08X, %08X)\n", addr, val, priv); +#endif addr &= 0x7; @@ -1361,7 +1358,7 @@ ide_write_devctl(UNUSED(uint16_t addr), uint8_t val, void *priv) old = dev->devctl; dev->devctl = val; if (!(val & 0x02) && (old & 0x02)) - ide_irq_update(ide_boards[ide->board]); + ide_irq_update(ide_boards[ide->board], 1); } static void @@ -1429,7 +1426,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) #ifdef WRITE_PARAM_TO_BOTH_DEVICES ide_other->tf->cylprecomp = val; #endif - return; + break; case 0x2: /* Sector count */ ide->tf->secount = val; @@ -1439,6 +1436,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) case 0x3: /* Sector */ ide->sector = val; ide->lba_addr = (ide->lba_addr & 0xfffff00) | val; + ide_other->sector = val; ide_other->lba_addr = (ide_other->lba_addr & 0xfffff00) | val; break; @@ -1482,7 +1480,7 @@ ide_writeb(uint16_t addr, uint8_t val, void *priv) ide_set_board_callback(ide->board, 0.0); reset = 1; } else - ide_irq_update(ide_boards[ide->board]); + ide_irq_update(ide_boards[ide->board], 1); } if (!reset) { @@ -1911,7 +1909,7 @@ ide_readb(uint16_t addr, void *priv) /* 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); + ide_irq(ide, 0, 0); ret = ide_status(ide, ide_drives[ch ^ 1], ch); break; @@ -1969,7 +1967,9 @@ ide_readw(uint16_t addr, void *priv) break; } +#ifdef IDE_MORE_SPECIFIC_LOGS ide_log("ide_readw(%04X, %08X) = %04X\n", addr, priv, ret); +#endif return ret; } @@ -2002,7 +2002,9 @@ ide_readl(uint16_t addr, void *priv) break; } +#ifdef IDE_MORE_SPECIFIC_LOGS ide_log("ide_readl(%04X, %08X) = %04X\n", addr, priv, ret); +#endif return ret; } @@ -2012,9 +2014,7 @@ ide_board_callback(void *priv) ide_board_t *dev = (ide_board_t *) priv; ide_t *ide; -#ifdef ENABLE_IDE_LOG ide_log("ide_board_callback(%i)\n", dev->cur_dev >> 1); -#endif for (uint8_t i = 0; i < 2; i++) { ide = dev->ide[i]; diff --git a/src/disk/hdc_ide_sff8038i.c b/src/disk/hdc_ide_sff8038i.c index 40cca95a9..3f43f80e6 100644 --- a/src/disk/hdc_ide_sff8038i.c +++ b/src/disk/hdc_ide_sff8038i.c @@ -27,7 +27,9 @@ #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/cdrom.h> +#include <86box/hdd.h> #include <86box/scsi_device.h> +#include <86box/scsi_disk.h> #include <86box/scsi_cdrom.h> #include <86box/dma.h> #include <86box/io.h> @@ -389,7 +391,6 @@ sff_bus_master_set_irq(uint8_t status, void *priv) { sff8038i_t *dev = (sff8038i_t *) priv; uint8_t irq = !!(status & 0x04); - int irq_shift = 0; if (!(dev->status & 0x04) || (status & 0x04)) dev->status = (dev->status & ~0x04) | status; @@ -410,16 +411,12 @@ sff_bus_master_set_irq(uint8_t status, void *priv) else pci_clear_irq(dev->slot, dev->irq_pin, &dev->irq_state); break; - case IRQ_MODE_MIRQ_0: - case IRQ_MODE_MIRQ_1: - /* MIRQ 0 or 1. */ - case IRQ_MODE_MIRQ_2: - case IRQ_MODE_MIRQ_3: - /* MIRQ 2 or 3. */ + case IRQ_MODE_MIRQ_0 ... IRQ_MODE_MIRQ_3: + /* MIRQ 0, 1, 2, or 3. */ if (irq) - pci_set_mirq((dev->irq_mode & 3) + irq_shift, 0, &dev->irq_state); + pci_set_mirq(dev->irq_mode & 3, 0, &dev->irq_state); else - pci_clear_mirq((dev->irq_mode & 3) + irq_shift, 0, &dev->irq_state); + pci_clear_mirq(dev->irq_mode & 3, 0, &dev->irq_state); break; /* TODO: Redo this as a MIRQ. */ case IRQ_MODE_PCI_IRQ_LINE: @@ -477,6 +474,10 @@ sff_reset(void *priv) sff_log("SFF8038i: Reset\n"); #endif + for (uint8_t i = 0; i < HDD_NUM; i++) { + if ((hdd[i].bus == HDD_BUS_ATAPI) && (hdd[i].ide_channel < 4) && hdd[i].priv) + scsi_disk_reset((scsi_common_t *) hdd[i].priv); + } for (uint8_t i = 0; i < CDROM_NUM; i++) { if ((cdrom[i].bus_type == CDROM_BUS_ATAPI) && (cdrom[i].ide_channel < 4) && cdrom[i].priv) scsi_cdrom_reset((scsi_common_t *) cdrom[i].priv); @@ -522,21 +523,15 @@ sff_set_irq_mode(sff8038i_t *dev, int irq_mode) default: case IRQ_MODE_LEGACY: /* Legacy IRQ mode. */ - sff_log("[%08X] Setting IRQ mode to legacy IRQ %i\n", dev, 14 + channel); + sff_log("[%08X] Setting IRQ mode to legacy IRQ %i\n", dev, dev->irq_line); break; case IRQ_MODE_PCI_IRQ_PIN: /* Native PCI IRQ mode with interrupt pin. */ sff_log("[%08X] Setting IRQ mode to native PCI INT%c\n", dev, 0x40 + dev->irq_pin); break; - case IRQ_MODE_MIRQ_0: - case IRQ_MODE_MIRQ_1: - /* MIRQ 0 or 1. */ - sff_log("[%08X] Setting IRQ mode to PCI MIRQ%i\n", dev, irq_mode & 1); - break; - case IRQ_MODE_MIRQ_2: - case IRQ_MODE_MIRQ_3: - /* MIRQ 0 or 1. */ - sff_log("[%08X] Setting IRQ mode to PCI MIRQ%i\n", dev, (irq_mode & 1) + 1); + case IRQ_MODE_MIRQ_0 ... IRQ_MODE_MIRQ_3: + /* MIRQ 0, 1, 2, or 3. */ + sff_log("[%08X] Setting IRQ mode to PCI MIRQ%i\n", dev, dev->irq_mode & 3); break; case IRQ_MODE_PCI_IRQ_LINE: /* Native PCI IRQ mode with specified interrupt line. */ diff --git a/src/include/86box/hdc_ide.h b/src/include/86box/hdc_ide.h index b1bff13b3..71ed9e448 100644 --- a/src/include/86box/hdc_ide.h +++ b/src/include/86box/hdc_ide.h @@ -179,8 +179,7 @@ extern int ide_qua_enabled; #ifdef SCSI_DEVICE_H extern ide_t *ide_get_drive(int ch); -extern void ide_irq_raise(ide_t *ide); -extern void ide_irq_lower(ide_t *ide); +extern void ide_irq(ide_t *ide, int set, int log); extern void ide_allocate_buffer(ide_t *dev); extern void ide_atapi_attach(ide_t *dev); #endif @@ -224,6 +223,9 @@ extern uint8_t ide_read_ali_75(void); extern uint8_t ide_read_ali_76(void); /* Legacy #define's. */ +#define ide_irq_raise(ide) ide_irq(ide, 1, 1) +#define ide_irq_lower(ide) ide_irq(ide, 0, 1) + #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) diff --git a/src/include/86box/scsi_disk.h b/src/include/86box/scsi_disk.h index a62bc9e20..eb4dc69a4 100644 --- a/src/include/86box/scsi_disk.h +++ b/src/include/86box/scsi_disk.h @@ -68,6 +68,8 @@ typedef struct scsi_disk_t { extern scsi_disk_t *scsi_disk[HDD_NUM]; +extern void scsi_disk_reset(scsi_common_t *sc); + extern void scsi_disk_hard_reset(void); extern void scsi_disk_close(void); diff --git a/src/scsi/scsi_disk.c b/src/scsi/scsi_disk.c index ee0c3fc00..93d29a672 100644 --- a/src/scsi/scsi_disk.c +++ b/src/scsi/scsi_disk.c @@ -128,7 +128,6 @@ 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; @@ -787,7 +786,7 @@ scsi_disk_rezero(scsi_disk_t *dev) scsi_disk_seek(dev, 0); } -static void +void scsi_disk_reset(scsi_common_t *sc) { scsi_disk_t *dev = (scsi_disk_t *) sc;