diff --git a/src/ide.c b/src/ide.c index 44e74a7..0cbad14 100644 --- a/src/ide.c +++ b/src/ide.c @@ -94,9 +94,10 @@ IDE *ext_ide; char ide_fn[7][512]; -int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size); -int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size); -void (*ide_bus_master_set_irq)(int channel); +int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size, void *p); +int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size, void *p); +void (*ide_bus_master_set_irq)(int channel, void *p); +void *ide_bus_master_p; pc_timer_t ide_timer[2]; @@ -111,7 +112,7 @@ void ide_irq_raise(IDE *ide) // if (ide->board && !ide->irqstat) pclog("IDE_IRQ_RAISE\n"); picint((ide->board)?(1<<15):(1<<14)); if (ide_bus_master_set_irq) - ide_bus_master_set_irq(ide->board); + ide_bus_master_set_irq(ide->board, ide_bus_master_p); } ide->irqstat=1; ide->service=1; @@ -905,7 +906,7 @@ void callbackide(int ide_board) if (ide_bus_master_read_data) { - if (ide_bus_master_read_data(ide_board, &ide->sector_buffer[ide->sector_pos*512], 512)) + if (ide_bus_master_read_data(ide_board, &ide->sector_buffer[ide->sector_pos*512], 512, ide_bus_master_p)) timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); /*DMA not performed, try again later*/ else { @@ -983,7 +984,7 @@ void callbackide(int ide_board) if (ide_bus_master_write_data) { - if (ide_bus_master_write_data(ide_board, (uint8_t *)ide->buffer, 512)) + if (ide_bus_master_write_data(ide_board, (uint8_t *)ide->buffer, 512, ide_bus_master_p)) timer_set_delay_u64(&ide_timer[ide_board], 6*IDE_TIME); /*DMA not performed, try again later*/ else { @@ -1270,11 +1271,12 @@ static void ide_close(void *p) { } -void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size), int (*write_data)(int channel, uint8_t *data, int size), void (*set_irq)(int channel)) +void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size, void *p), int (*write_data)(int channel, uint8_t *data, int size, void *p), void (*set_irq)(int channel, void *p), void *p) { ide_bus_master_read_data = read_data; ide_bus_master_write_data = write_data; ide_bus_master_set_irq = set_irq; + ide_bus_master_p = p; } device_t ide_device = diff --git a/src/ide.h b/src/ide.h index aed1200..0c2ce0b 100644 --- a/src/ide.h +++ b/src/ide.h @@ -16,12 +16,13 @@ extern void ide_pri_enable(); extern void ide_sec_enable(); extern void ide_pri_disable(); extern void ide_sec_disable(); -extern void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size), int (*write_data)(int channel, uint8_t *data, int size), void (*set_irq)(int channel)); +extern void ide_set_bus_master(int (*read_data)(int channel, uint8_t *data, int size, void *p), int (*write_data)(int channel, uint8_t *data, int size, void *p), void (*set_irq)(int channel, void *p), void *p); void ide_irq_raise(struct IDE *ide); -extern int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size); -extern int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size); -extern void (*ide_bus_master_set_irq)(int channel); +extern int (*ide_bus_master_read_data)(int channel, uint8_t *data, int size, void *p); +extern int (*ide_bus_master_write_data)(int channel, uint8_t *data, int size, void *p); +extern void (*ide_bus_master_set_irq)(int channel, void *p); +extern void *ide_bus_master_p; #include "ide_atapi.h" diff --git a/src/ide_atapi.c b/src/ide_atapi.c index ab4330e..78a648b 100644 --- a/src/ide_atapi.c +++ b/src/ide_atapi.c @@ -258,7 +258,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { if (ide_bus_master_write_data) { - if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos)) + if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos, ide_bus_master_p)) { atapi_dev->state = ATAPI_STATE_RETRY_WRITE_DMA; timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); @@ -430,7 +430,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) { if (ide_bus_master_read_data) { - if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos)) + if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos, ide_bus_master_p)) { atapi_dev->state = ATAPI_STATE_RETRY_READ_DMA; timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); @@ -535,7 +535,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) case ATAPI_STATE_RETRY_READ_DMA: { - if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos)) + if (ide_bus_master_read_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_write_pos, ide_bus_master_p)) { timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } @@ -549,7 +549,7 @@ void atapi_process_packet(atapi_device_t *atapi_dev) case ATAPI_STATE_RETRY_WRITE_DMA: { - if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos)) + if (ide_bus_master_write_data(atapi_dev->board, atapi_dev->data, atapi_dev->data_read_pos, ide_bus_master_p)) { timer_set_delay_u64(&ide_timer[atapi_dev->board], 1*IDE_TIME); } diff --git a/src/ide_sff8038i.c b/src/ide_sff8038i.c new file mode 100644 index 0000000..79eda27 --- /dev/null +++ b/src/ide_sff8038i.c @@ -0,0 +1,208 @@ +/*Emulation of SFF-8038i IDE bus mastering interface. + Used by PIIX and VT82C586B IDE controllers*/ +#include "ibm.h" +#include "ide.h" +#include "ide_sff8038i.h" +#include "mem.h" + +static void sff_bus_master_next_addr(sff_busmaster_t *busmaster, int channel) +{ + busmaster[channel].addr = (*(uint32_t *)(&ram[busmaster[channel].ptr_cur])) & ~1; + busmaster[channel].count = (*(uint32_t *)(&ram[busmaster[channel].ptr_cur + 4])) & 0xfffe; + if (!busmaster[channel].count) + busmaster[channel].count = 0x10000; + busmaster[channel].eot = (*(uint32_t *)(&ram[busmaster[channel].ptr_cur + 4])) >> 31; + busmaster[channel].ptr_cur += 8; +// pclog("New DMA settings on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); +} + +void sff_bus_master_write(uint16_t port, uint8_t val, void *p) +{ + sff_busmaster_t *busmaster = (sff_busmaster_t *)p; + int channel = (port & 8) ? 1 : 0; +// pclog("PIIX Bus Master write %04X %02X %04x:%08x\n", port, val, CS, pc); + switch (port & 7) + { + case 0: + if ((val & 1) && !(busmaster[channel].command & 1)) /*Start*/ + { + busmaster[channel].ptr_cur = busmaster[channel].ptr; + sff_bus_master_next_addr(busmaster, channel); + busmaster[channel].status |= 1; + } + if (!(val & 1) && (busmaster[channel].command & 1)) /*Stop*/ + busmaster[channel].status &= ~1; + + busmaster[channel].command = val; + break; + case 2: + busmaster[channel].status = (val & 0x60) | ((busmaster[channel].status & ~val) & 6) | (busmaster[channel].status & 1); + break; + case 4: + busmaster[channel].ptr = (busmaster[channel].ptr & 0xffffff00) | val; + break; + case 5: + busmaster[channel].ptr = (busmaster[channel].ptr & 0xffff00ff) | (val << 8); + break; + case 6: + busmaster[channel].ptr = (busmaster[channel].ptr & 0xff00ffff) | (val << 16); + break; + case 7: + busmaster[channel].ptr = (busmaster[channel].ptr & 0x00ffffff) | (val << 24); + break; + } +} + +uint8_t sff_bus_master_read(uint16_t port, void *p) +{ + sff_busmaster_t *busmaster = (sff_busmaster_t *)p; + int channel = (port & 8) ? 1 : 0; +// pclog("PIIX Bus Master read %04X %04x:%08x\n", port, CS, pc); + switch (port & 7) + { + case 0: + return busmaster[channel].command; + case 2: + return busmaster[channel].status; + case 4: + return busmaster[channel].ptr; + case 5: + return busmaster[channel].ptr >> 8; + case 6: + return busmaster[channel].ptr >> 16; + case 7: + return busmaster[channel].ptr >> 24; + } + return 0xff; +} + +static int sff_bus_master_data_read(int channel, uint8_t *data, int size, void *p) +{ + sff_busmaster_t *busmaster = (sff_busmaster_t *)p; + int transferred = 0; + + if (!(busmaster[channel].status & 1)) + return 1; /*DMA disabled*/ + + while (transferred < size) + { + if (busmaster[channel].count < (size - transferred) && busmaster[channel].eot) + fatal("DMA on channel %i - Read count less than size! Addr %08X Count %04X EOT %i size %i\n", channel, busmaster[channel].addr, busmaster[channel].count, busmaster[channel].eot, size); + + mem_invalidate_range(busmaster[channel].addr, busmaster[channel].addr+(size-1)); + + if (busmaster[channel].count < (size - transferred)) + { +// pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count); + if (busmaster[channel].addr < (mem_size * 1024)) + { + int count = busmaster[channel].count; + if ((busmaster[channel].addr + count) > (mem_size * 1024)) + count = (mem_size * 1024) - busmaster[channel].addr; + memcpy(&ram[busmaster[channel].addr], data + transferred, count); + } + transferred += busmaster[channel].count; + busmaster[channel].addr += busmaster[channel].count; + busmaster[channel].count = 0; + } + else + { +// pclog("Transferring larger - %i bytes\n", size - transferred); + if (busmaster[channel].addr < (mem_size * 1024)) + { + int count = size - transferred; + if ((busmaster[channel].addr + count) > (mem_size * 1024)) + count = (mem_size * 1024) - busmaster[channel].addr; + memcpy(&ram[busmaster[channel].addr], data + transferred, count); + } + busmaster[channel].addr += (size - transferred); + busmaster[channel].count -= (size - transferred); + transferred += (size - transferred); + } + +// pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); + + if (!busmaster[channel].count) + { +// pclog("DMA on channel %i - block over\n", channel); + if (busmaster[channel].eot) /*End of transfer?*/ + { +// pclog("DMA on channel %i - transfer over\n", channel); + busmaster[channel].status &= ~1; + } + else + sff_bus_master_next_addr(busmaster, channel); + } + } + return 0; +} +static int sff_bus_master_data_write(int channel, uint8_t *data, int size, void *p) +{ + sff_busmaster_t *busmaster = (sff_busmaster_t *)p; + int transferred = 0; + + if (!(busmaster[channel].status & 1)) + return 1; /*DMA disabled*/ + + while (transferred < size) + { + if (busmaster[channel].count < (size - transferred) && busmaster[channel].eot) + fatal("DMA on channel %i - Write count less than size! Addr %08X Count %04X EOT %i size %i\n", channel, busmaster[channel].addr, busmaster[channel].count, busmaster[channel].eot, size); + + if (busmaster[channel].count < (size - transferred)) + { +// pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count); + if (busmaster[channel].addr < (mem_size * 1024)) + { + int count = busmaster[channel].count; + if ((busmaster[channel].addr + count) > (mem_size * 1024)) + count = (mem_size * 1024) - busmaster[channel].addr; + memcpy(data + transferred, &ram[busmaster[channel].addr], count); + } + transferred += busmaster[channel].count; + busmaster[channel].addr += busmaster[channel].count; + busmaster[channel].count = 0; + } + else + { +// pclog("Transferring larger - %i bytes\n", size - transferred); + if (busmaster[channel].addr < (mem_size * 1024)) + { + int count = size - transferred; + if ((busmaster[channel].addr + count) > (mem_size * 1024)) + count = (mem_size * 1024) - busmaster[channel].addr; + memcpy(data + transferred, &ram[busmaster[channel].addr], count); + } + busmaster[channel].addr += (size - transferred); + busmaster[channel].count -= (size - transferred); + transferred += (size - transferred); + } + +// pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); + + if (!busmaster[channel].count) + { +// pclog("DMA on channel %i - block over\n", channel); + if (busmaster[channel].eot) /*End of transfer?*/ + { +// pclog("DMA on channel %i - transfer over\n", channel); + busmaster[channel].status &= ~1; + } + else + sff_bus_master_next_addr(busmaster, channel); + } + } + return 0; +} + +static void sff_bus_master_set_irq(int channel, void *p) +{ + sff_busmaster_t *busmaster = (sff_busmaster_t *)p; + + busmaster[channel].status |= 4; +} + +void sff_bus_master_init(sff_busmaster_t *busmaster) +{ + ide_set_bus_master(sff_bus_master_data_read, sff_bus_master_data_write, sff_bus_master_set_irq, busmaster); +} diff --git a/src/ide_sff8038i.h b/src/ide_sff8038i.h new file mode 100644 index 0000000..9ade5ad --- /dev/null +++ b/src/ide_sff8038i.h @@ -0,0 +1,13 @@ +typedef struct sff_busmaster_t +{ + uint8_t command; + uint8_t status; + uint32_t ptr, ptr_cur; + int count; + uint32_t addr; + int eot; +} sff_busmaster_t; + +uint8_t sff_bus_master_read(uint16_t port, void *p); +void sff_bus_master_write(uint16_t port, uint8_t val, void *p); +void sff_bus_master_init(sff_busmaster_t *busmaster); diff --git a/src/model.c b/src/model.c index 5fe572d..7d3a540 100644 --- a/src/model.c +++ b/src/model.c @@ -681,7 +681,7 @@ void model_init() { pclog("Initting as %s\n", model_getname()); AMSTRAD = AT = PCI = TANDY = 0; - ide_set_bus_master(NULL, NULL, NULL); + ide_set_bus_master(NULL, NULL, NULL, NULL); models[model].init(); if (models[model].device) diff --git a/src/piix.c b/src/piix.c index d8a2a18..73676cf 100644 --- a/src/piix.c +++ b/src/piix.c @@ -7,6 +7,7 @@ #include "ibm.h" #include "ide.h" +#include "ide_sff8038i.h" #include "io.h" #include "mem.h" #include "pci.h" @@ -14,10 +15,8 @@ #include "piix.h" -uint8_t piix_bus_master_read(uint16_t port, void *priv); -void piix_bus_master_write(uint16_t port, uint8_t val, void *priv); - static uint8_t card_piix[256], card_piix_ide[256]; +static sff_busmaster_t piix_busmaster[2]; void piix_write(int func, int addr, uint8_t val, void *priv) { @@ -62,9 +61,9 @@ void piix_write(int func, int addr, uint8_t val, void *priv) if (addr == 4 || (addr & ~3) == 0x20) /*Bus master base address*/ { uint16_t base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8); - io_removehandler(0, 0x10000, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); + io_removehandler(0, 0x10000, sff_bus_master_read, NULL, NULL, sff_bus_master_write, NULL, NULL, piix_busmaster); if (card_piix_ide[0x04] & 1) - io_sethandler(base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL); + io_sethandler(base, 0x10, sff_bus_master_read, NULL, NULL, sff_bus_master_write, NULL, NULL, piix_busmaster); } if (addr == 4 || addr == 0x41 || addr == 0x43) { @@ -140,206 +139,6 @@ uint8_t piix_read(int func, int addr, void *priv) return card_piix[addr]; } -struct -{ - uint8_t command; - uint8_t status; - uint32_t ptr, ptr_cur; - int count; - uint32_t addr; - int eot; -} piix_busmaster[2]; - -static void piix_bus_master_next_addr(int channel) -{ - piix_busmaster[channel].addr = (*(uint32_t *)(&ram[piix_busmaster[channel].ptr_cur])) & ~1; - piix_busmaster[channel].count = (*(uint32_t *)(&ram[piix_busmaster[channel].ptr_cur + 4])) & 0xfffe; - if (!piix_busmaster[channel].count) - piix_busmaster[channel].count = 0x10000; - piix_busmaster[channel].eot = (*(uint32_t *)(&ram[piix_busmaster[channel].ptr_cur + 4])) >> 31; - piix_busmaster[channel].ptr_cur += 8; -// pclog("New DMA settings on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); -} - -void piix_bus_master_write(uint16_t port, uint8_t val, void *priv) -{ - int channel = (port & 8) ? 1 : 0; -// pclog("PIIX Bus Master write %04X %02X %04x:%08x\n", port, val, CS, pc); - switch (port & 7) - { - case 0: - if ((val & 1) && !(piix_busmaster[channel].command & 1)) /*Start*/ - { - piix_busmaster[channel].ptr_cur = piix_busmaster[channel].ptr; - piix_bus_master_next_addr(channel); - piix_busmaster[channel].status |= 1; - } - if (!(val & 1) && (piix_busmaster[channel].command & 1)) /*Stop*/ - piix_busmaster[channel].status &= ~1; - - piix_busmaster[channel].command = val; - break; - case 2: - piix_busmaster[channel].status = (val & 0x60) | ((piix_busmaster[channel].status & ~val) & 6) | (piix_busmaster[channel].status & 1); - break; - case 4: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xffffff00) | val; - break; - case 5: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xffff00ff) | (val << 8); - break; - case 6: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0xff00ffff) | (val << 16); - break; - case 7: - piix_busmaster[channel].ptr = (piix_busmaster[channel].ptr & 0x00ffffff) | (val << 24); - break; - } -} - -uint8_t piix_bus_master_read(uint16_t port, void *priv) -{ - int channel = (port & 8) ? 1 : 0; -// pclog("PIIX Bus Master read %04X %04x:%08x\n", port, CS, pc); - switch (port & 7) - { - case 0: - return piix_busmaster[channel].command; - case 2: - return piix_busmaster[channel].status; - case 4: - return piix_busmaster[channel].ptr; - case 5: - return piix_busmaster[channel].ptr >> 8; - case 6: - return piix_busmaster[channel].ptr >> 16; - case 7: - return piix_busmaster[channel].ptr >> 24; - } - return 0xff; -} - -int piix_bus_master_data_read(int channel, uint8_t *data, int size) -{ - int transferred = 0; - - if (!(piix_busmaster[channel].status & 1)) - return 1; /*DMA disabled*/ - - while (transferred < size) - { - if (piix_busmaster[channel].count < (size - transferred) && piix_busmaster[channel].eot) - fatal("DMA on channel %i - Read count less than size! Addr %08X Count %04X EOT %i size %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot, size); - - mem_invalidate_range(piix_busmaster[channel].addr, piix_busmaster[channel].addr+(size-1)); - - if (piix_busmaster[channel].count < (size - transferred)) - { -// pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count); - if (piix_busmaster[channel].addr < (mem_size * 1024)) - { - int count = piix_busmaster[channel].count; - if ((piix_busmaster[channel].addr + count) > (mem_size * 1024)) - count = (mem_size * 1024) - piix_busmaster[channel].addr; - memcpy(&ram[piix_busmaster[channel].addr], data + transferred, count); - } - transferred += piix_busmaster[channel].count; - piix_busmaster[channel].addr += piix_busmaster[channel].count; - piix_busmaster[channel].count = 0; - } - else - { -// pclog("Transferring larger - %i bytes\n", size - transferred); - if (piix_busmaster[channel].addr < (mem_size * 1024)) - { - int count = size - transferred; - if ((piix_busmaster[channel].addr + count) > (mem_size * 1024)) - count = (mem_size * 1024) - piix_busmaster[channel].addr; - memcpy(&ram[piix_busmaster[channel].addr], data + transferred, count); - } - piix_busmaster[channel].addr += (size - transferred); - piix_busmaster[channel].count -= (size - transferred); - transferred += (size - transferred); - } - -// pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); - - if (!piix_busmaster[channel].count) - { -// pclog("DMA on channel %i - block over\n", channel); - if (piix_busmaster[channel].eot) /*End of transfer?*/ - { -// pclog("DMA on channel %i - transfer over\n", channel); - piix_busmaster[channel].status &= ~1; - } - else - piix_bus_master_next_addr(channel); - } - } - return 0; -} -int piix_bus_master_data_write(int channel, uint8_t *data, int size) -{ - int transferred = 0; - - if (!(piix_busmaster[channel].status & 1)) - return 1; /*DMA disabled*/ - - while (transferred < size) - { - if (piix_busmaster[channel].count < (size - transferred) && piix_busmaster[channel].eot) - fatal("DMA on channel %i - Write count less than size! Addr %08X Count %04X EOT %i size %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot, size); - - if (piix_busmaster[channel].count < (size - transferred)) - { -// pclog("Transferring smaller - %i bytes\n", piix_busmaster[channel].count); - if (piix_busmaster[channel].addr < (mem_size * 1024)) - { - int count = piix_busmaster[channel].count; - if ((piix_busmaster[channel].addr + count) > (mem_size * 1024)) - count = (mem_size * 1024) - piix_busmaster[channel].addr; - memcpy(data + transferred, &ram[piix_busmaster[channel].addr], count); - } - transferred += piix_busmaster[channel].count; - piix_busmaster[channel].addr += piix_busmaster[channel].count; - piix_busmaster[channel].count = 0; - } - else - { -// pclog("Transferring larger - %i bytes\n", size - transferred); - if (piix_busmaster[channel].addr < (mem_size * 1024)) - { - int count = size - transferred; - if ((piix_busmaster[channel].addr + count) > (mem_size * 1024)) - count = (mem_size * 1024) - piix_busmaster[channel].addr; - memcpy(data + transferred, &ram[piix_busmaster[channel].addr], count); - } - piix_busmaster[channel].addr += (size - transferred); - piix_busmaster[channel].count -= (size - transferred); - transferred += (size - transferred); - } - -// pclog("DMA on channel %i - Addr %08X Count %04X EOT %i\n", channel, piix_busmaster[channel].addr, piix_busmaster[channel].count, piix_busmaster[channel].eot); - - if (!piix_busmaster[channel].count) - { -// pclog("DMA on channel %i - block over\n", channel); - if (piix_busmaster[channel].eot) /*End of transfer?*/ - { -// pclog("DMA on channel %i - transfer over\n", channel); - piix_busmaster[channel].status &= ~1; - } - else - piix_bus_master_next_addr(channel); - } - } - return 0; -} - -void piix_bus_master_set_irq(int channel) -{ - piix_busmaster[channel].status |= 4; -} void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d) { @@ -379,8 +178,8 @@ void piix_init(int card, int pci_a, int pci_b, int pci_c, int pci_d) card_piix_ide[0x20] = 0x01; card_piix_ide[0x21] = card_piix_ide[0x22] = card_piix_ide[0x23] = 0x00; /*Bus master interface base address*/ card_piix_ide[0x40] = card_piix_ide[0x41] = 0x00; card_piix_ide[0x42] = card_piix_ide[0x43] = 0x00; - - ide_set_bus_master(piix_bus_master_data_read, piix_bus_master_data_write, piix_bus_master_set_irq); + + sff_bus_master_init(piix_busmaster); pci_set_card_routing(pci_a, PCI_INTA); pci_set_card_routing(pci_b, PCI_INTB); diff --git a/src/vt82c586b.c b/src/vt82c586b.c index fd67002..34a064b 100644 --- a/src/vt82c586b.c +++ b/src/vt82c586b.c @@ -1,6 +1,8 @@ #include #include "ibm.h" +#include "ide.h" +#include "ide_sff8038i.h" #include "io.h" #include "mem.h" #include "pci.h" @@ -16,6 +18,8 @@ static struct uint8_t power_regs[256]; uint8_t sysctrl; + + sff_busmaster_t busmaster[2]; } vt82c586b; static uint8_t vt82c586b_read(int func, int addr, void *priv) @@ -101,7 +105,7 @@ static void vt82c586b_pci_isa_bridge_write(int addr, uint8_t val) static void vt82c586b_ide_write(int addr, uint8_t val) { /*Read-only addresses*/ - if ((addr < 6) || (addr == 8) + if ((addr < 4) || (addr == 5) || (addr == 8) || (addr >= 0xa && addr < 0x0d) || (addr >= 0x0e && addr < 0x20) || (addr >= 0x22 && addr < 0x3c) @@ -114,7 +118,7 @@ static void vt82c586b_ide_write(int addr, uint8_t val) switch (addr) { case 4: - vt82c586b.ide_regs[4] = (val & 8) | 7; + vt82c586b.ide_regs[4] = val & 0x85; break; case 6: vt82c586b.ide_regs[6] &= ~(val & 0xb0); @@ -132,11 +136,32 @@ static void vt82c586b_ide_write(int addr, uint8_t val) vt82c586b.ide_regs[addr] = val; break; } + + if (addr == 4 || (addr & ~3) == 0x20) /*Bus master base address*/ + { + uint16_t base = (vt82c586b.ide_regs[0x20] & 0xf0) | (vt82c586b.ide_regs[0x21] << 8); + io_removehandler(0, 0x10000, sff_bus_master_read, NULL, NULL, sff_bus_master_write, NULL, NULL, vt82c586b.busmaster); + if (vt82c586b.ide_regs[0x04] & 1) + io_sethandler(base, 0x10, sff_bus_master_read, NULL, NULL, sff_bus_master_write, NULL, NULL, vt82c586b.busmaster); + } + if (addr == 4 || addr == 0x40) + { + ide_pri_disable(); + ide_sec_disable(); + if (vt82c586b.ide_regs[0x04] & 1) + { + if (vt82c586b.ide_regs[0x40] & 0x02) + ide_pri_enable(); + if (vt82c586b.ide_regs[0x40] & 0x01) + ide_sec_enable(); + } + } } static void vt82c586b_usb_write(int addr, uint8_t val) { /*Read-only addresses*/ - if ((addr < 7) || (addr >= 8 && addr < 0xd) + if ((addr < 4) || (addr == 5) || (addr == 6) + || (addr >= 8 && addr < 0xd) || (addr >= 0xe && addr < 0x20) || (addr >= 0x22 && addr < 0x3c) || (addr >= 0x3e && addr < 0x40) @@ -147,6 +172,9 @@ static void vt82c586b_usb_write(int addr, uint8_t val) switch (addr) { + case 4: + vt82c586b.usb_regs[4] = val & 0x97; + break; case 7: vt82c586b.usb_regs[7] = val & 0x7f; break; @@ -307,4 +335,9 @@ void vt82c586b_init(int card, int pci_a, int pci_b, int pci_c, int pci_d) pci_set_card_routing(pci_c, PCI_INTC); if (pci_d) pci_set_card_routing(pci_d, PCI_INTD); + + sff_bus_master_init(vt82c586b.busmaster); + + ide_pri_disable(); + ide_sec_disable(); }