From f8e654feb8dd0e47b8ed33ef9b3c8ba4e8af5e07 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Thu, 7 Jan 2021 17:43:27 +0100 Subject: [PATCH 1/2] BIOS BAR now properly working in the NCR 53c8xx PCI adapters. --- src/scsi/scsi_ncr53c8xx.c | 198 ++++++++++++++++++++++---------------- 1 file changed, 117 insertions(+), 81 deletions(-) diff --git a/src/scsi/scsi_ncr53c8xx.c b/src/scsi/scsi_ncr53c8xx.c index e898e7d76..2ec5932c2 100644 --- a/src/scsi/scsi_ncr53c8xx.c +++ b/src/scsi/scsi_ncr53c8xx.c @@ -10,9 +10,6 @@ * Adapters made by NCR and later Symbios and LSI. These * controllers were designed for the PCI bus. * - * To do: Identify the type of serial EEPROM used and its - * interface. - * * * * Authors: Paul Brook (QEMU) @@ -48,7 +45,17 @@ #include <86box/scsi_device.h> #include <86box/scsi_ncr53c8xx.h> -#define NCR53C8XX_ROM L"roms/scsi/ncr53c8xx/NCR307.BIN" + +#define NCR53C810_SDMS3_ROM L"roms/scsi/ncr53c8xx/810/NCR307.BIN" +#define SYM53C810_SDMS4_ROM L"roms/scsi/ncr53c8xx/810/8XX_64.ROM" +#define NCR53C815_SDMS3_ROM L"roms/scsi/ncr53c8xx/815/NCR307.BIN" +#define SYM53C815_SDMS4_ROM L"roms/scsi/ncr53c8xx/815/8XX_64.ROM" +#define NCR53C825A_SDMS3_ROM L"roms/scsi/ncr53c8xx/825A/NCR307.BIN" +#define SYM53C825A_SDMS4_ROM L"roms/scsi/ncr53c8xx/825A/8XX_64.ROM" +#define NCR53C860_SDMS3_ROM L"roms/scsi/ncr53c8xx/860/NCR307.BIN" +#define SYM53C860_SDMS4_ROM L"roms/scsi/ncr53c8xx/860/8XX_64.ROM" +#define NCR53C875_SDMS3_ROM L"roms/scsi/ncr53c8xx/875/NCR307.BIN" +#define SYM53C875_SDMS4_ROM L"roms/scsi/ncr53c8xx/875/8XX_64.ROM" #define HA_ID 7 @@ -2231,13 +2238,11 @@ ncr53c8xx_ram_set_addr(ncr53c8xx_t *dev, uint32_t base) } -#ifdef USE_BIOS_BAR static void ncr53c8xx_bios_set_addr(ncr53c8xx_t *dev, uint32_t base) { mem_mapping_set_addr(&dev->bios.mapping, base, 0x10000); } -#endif static void @@ -2254,13 +2259,11 @@ ncr53c8xx_ram_disable(ncr53c8xx_t *dev) } -#ifdef USE_BIOS_BAR static void ncr53c8xx_bios_disable(ncr53c8xx_t *dev) { mem_mapping_disable(&dev->bios.mapping); } -#endif uint8_t ncr53c8xx_pci_regs[256]; @@ -2324,47 +2327,37 @@ ncr53c8xx_pci_read(int func, int addr, void *p) case 0x18: return 0; /*Memory space*/ case 0x19: - if (dev->chip < CHIP_825) + if (dev->chip == CHIP_815 || dev->chip < CHIP_825) return 0; return ncr53c8xx_pci_bar[2].addr_regs[1]; case 0x1A: - if (dev->chip < CHIP_825) + if (dev->chip == CHIP_815 || dev->chip < CHIP_825) return 0; return ncr53c8xx_pci_bar[2].addr_regs[2]; case 0x1B: - if (dev->chip < CHIP_825) + if (dev->chip == CHIP_815 || dev->chip < CHIP_825) return 0; return ncr53c8xx_pci_bar[2].addr_regs[3]; case 0x2C: return 0x00; case 0x2D: - if (dev->chip >= CHIP_825) + if (dev->chip >= CHIP_825 || dev->chip != CHIP_815) return 0; return 0x10; case 0x2E: - if (dev->chip >= CHIP_825) + if (dev->chip >= CHIP_825 || dev->chip != CHIP_815) return 0; return 0x01; case 0x2F: return 0x00; -#ifdef USE_BIOS_BAR case 0x30: - if ((dev->chip < CHIP_825) || !dev->has_bios) - return 0; - return ncr53c8xx_pci_bar[3].addr_regs[0]; + return ncr53c8xx_pci_bar[3].addr_regs[0] & 0x01; case 0x31: - if ((dev->chip < CHIP_825) || !dev->has_bios) - return 0; return ncr53c8xx_pci_bar[3].addr_regs[1]; case 0x32: - if ((dev->chip < CHIP_825) || !dev->has_bios) - return 0; return ncr53c8xx_pci_bar[3].addr_regs[2]; case 0x33: - if ((dev->chip < CHIP_825) || !dev->has_bios) - return 0; return ncr53c8xx_pci_bar[3].addr_regs[3]; -#endif case 0x3C: return dev->irq; case 0x3D: @@ -2405,7 +2398,7 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) ncr53c8xx_mem_disable(dev); if ((dev->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) ncr53c8xx_mem_set_addr(dev, dev->MMIOBase); - if (dev->chip >= CHIP_825) { + if (dev->chip != CHIP_815 || dev->chip >= CHIP_825) { ncr53c8xx_ram_disable(dev); if ((dev->RAMBase != 0) && (val & PCI_COMMAND_MEM)) ncr53c8xx_ram_set_addr(dev, dev->RAMBase); @@ -2449,8 +2442,8 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) /* Then let's set the PCI regs. */ ncr53c8xx_pci_bar[1].addr_regs[addr & 3] = val; /* Then let's calculate the new I/O base. */ - ncr53c8xx_pci_bar[1].addr &= 0xffffc000; - dev->MMIOBase = ncr53c8xx_pci_bar[1].addr & 0xffffc000; + ncr53c8xx_pci_bar[1].addr &= 0xfffcf000; + dev->MMIOBase = ncr53c8xx_pci_bar[1].addr & 0xfffcf000; /* Log the new base. */ ncr53c8xx_log("NCR53c8xx: New MMIO base is %08X\n" , dev->MMIOBase); /* We're done, so get out of the here. */ @@ -2461,7 +2454,7 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) return; case 0x19: case 0x1A: case 0x1B: - if (dev->chip < CHIP_825) + if (dev->chip == CHIP_815 || dev->chip < CHIP_825) return; /* RAM Base set. */ /* First, remove the old I/O. */ @@ -2469,8 +2462,8 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) /* Then let's set the PCI regs. */ ncr53c8xx_pci_bar[2].addr_regs[addr & 3] = val; /* Then let's calculate the new I/O base. */ - ncr53c8xx_pci_bar[2].addr &= 0xffffc000; - dev->RAMBase = ncr53c8xx_pci_bar[2].addr & 0xffffc000; + ncr53c8xx_pci_bar[2].addr &= 0xfffcf000; + dev->RAMBase = ncr53c8xx_pci_bar[2].addr & 0xfffcf000; /* Log the new base. */ ncr53c8xx_log("NCR53c8xx: New RAM base is %08X\n" , dev->RAMBase); /* We're done, so get out of the here. */ @@ -2480,10 +2473,8 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) } return; -#ifdef USE_BIOS_BAR case 0x30: case 0x31: case 0x32: case 0x33: - return; - if ((dev->chip < CHIP_825) || !dev->has_bios) + if (dev->has_bios == 0) return; /* BIOS Base set. */ /* First, remove the old I/O. */ @@ -2491,15 +2482,15 @@ ncr53c8xx_pci_write(int func, int addr, uint8_t val, void *p) /* Then let's set the PCI regs. */ ncr53c8xx_pci_bar[3].addr_regs[addr & 3] = val; /* Then let's calculate the new I/O base. */ - ncr53c8xx_pci_bar[3].addr &= 0xffff0001; - dev->BIOSBase = ncr53c8xx_pci_bar[3].addr & 0xffff0000; + ncr53c8xx_pci_bar[3].addr &= 0xfffcf001; + dev->BIOSBase = ncr53c8xx_pci_bar[3].addr & 0xfffcf000; /* Log the new base. */ ncr53c8xx_log("NCR53c8xx: New BIOS base is %08X\n" , dev->BIOSBase); /* We're done, so get out of the here. */ - if (ncr53c8xx_pci_bar[3].addr & 0x00000001) + if (ncr53c8xx_pci_bar[3].addr_regs[0] & 0x01) { ncr53c8xx_bios_set_addr(dev, dev->BIOSBase); - return; -#endif + } + return; case 0x3C: ncr53c8xx_pci_regs[addr] = val; @@ -2518,52 +2509,74 @@ ncr53c8xx_init(const device_t *info) memset(dev, 0x00, sizeof(ncr53c8xx_t)); dev->chip_rev = 0; - // dev->pci_slot = pci_add_card(PCI_ADD_SCSI, ncr53c8xx_pci_read, ncr53c8xx_pci_write, dev); dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, ncr53c8xx_pci_read, ncr53c8xx_pci_write, dev); - ncr53c8xx_pci_bar[0].addr_regs[0] = 1; - ncr53c8xx_pci_bar[1].addr_regs[0] = 0; dev->chip = info->local & 0xff; - ncr53c8xx_pci_regs[0x04] = 3; - - ncr53c8xx_mem_init(dev, 0x0fffff00); - ncr53c8xx_mem_disable(dev); - if (info->local & 0x8000) dev->has_bios = 0; else dev->has_bios = device_get_config_int("bios"); - if (dev->has_bios) - rom_init(&dev->bios, NCR53C8XX_ROM, 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); - if (dev->chip >= CHIP_825) { - if (dev->chip == CHIP_875) { - dev->chip_rev = 0x04; - dev->nvr_path = L"ncr53c875.nvr"; - } else if (dev->chip == CHIP_860) { - dev->chip_rev = 0x04; - dev->nvr_path = L"ncr53c860.nvr"; - } else { - dev->chip_rev = 0x26; - dev->nvr_path = L"ncr53c825a.nvr"; - } - ncr53c8xx_pci_bar[2].addr_regs[0] = 0; - ncr53c8xx_pci_bar[3].addr = 0xffff0000; + if (dev->chip == CHIP_875) { + if (dev->has_bios == 2) + rom_init(&dev->bios, SYM53C875_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + else if (dev->has_bios == 1) + rom_init(&dev->bios, NCR53C875_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + dev->chip_rev = 0x04; + dev->nvr_path = L"ncr53c875.nvr"; + } else if (dev->chip == CHIP_860) { + if (dev->has_bios == 2) + rom_init(&dev->bios, SYM53C860_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + else if (dev->has_bios == 1) + rom_init(&dev->bios, NCR53C860_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + dev->chip_rev = 0x04; + dev->nvr_path = L"ncr53c860.nvr"; + } else if (dev->chip == CHIP_825) { + if (dev->has_bios == 2) + rom_init(&dev->bios, SYM53C825A_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + else if (dev->has_bios == 1) + rom_init(&dev->bios, NCR53C825A_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + dev->chip_rev = 0x26; + dev->nvr_path = L"ncr53c825a.nvr"; + } else if (dev->chip == CHIP_810) { + if (dev->has_bios == 2) + rom_init(&dev->bios, SYM53C810_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + else if (dev->has_bios == 1) + rom_init(&dev->bios, NCR53C810_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + dev->nvr_path = L"ncr53c810.nvr"; + } else if (dev->chip == CHIP_815) { + if (dev->has_bios == 2) + rom_init(&dev->bios, SYM53C815_SDMS4_ROM, 0xc8000, 0x10000, 0xffff, 0, MEM_MAPPING_EXTERNAL); + else if (dev->has_bios == 1) + rom_init(&dev->bios, NCR53C815_SDMS3_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + dev->chip_rev = 0x04; + dev->nvr_path = L"ncr53c815.nvr"; + } + + ncr53c8xx_pci_bar[0].addr_regs[0] = 1; + ncr53c8xx_pci_bar[1].addr_regs[0] = 0; + ncr53c8xx_pci_regs[0x04] = 3; + + if (dev->has_bios) { + ncr53c8xx_pci_bar[3].addr = 0xffffc000; + } else { + ncr53c8xx_pci_bar[3].addr = 0; + } + + ncr53c8xx_mem_init(dev, 0x0fffff00); + ncr53c8xx_mem_disable(dev); + + ncr53c8xx_pci_bar[2].addr_regs[0] = 0; + + if (dev->chip >= CHIP_825 || (dev->chip != CHIP_815)) { /* Need to make it align on a 16k boundary as that's this emulator's memory mapping granularity. */ ncr53c8xx_ram_init(dev, 0x0fffc000); ncr53c8xx_ram_disable(dev); - -#ifdef USE_BIOS_BAR - if (dev->has_bios) - ncr53c8xx_bios_disable(dev); -#endif - } else { - /* if (dev->has_bios) - rom_init(&dev->bios, NCR53C8XX_ROM, 0xc8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); */ - - dev->nvr_path = L"ncr53c810.nvr"; } + + if (dev->has_bios) + ncr53c8xx_bios_disable(dev); dev->i2c = i2c_gpio_init("nvr_ncr53c8xx"); dev->eeprom = i2c_eeprom_init(i2c_gpio_get_bus(dev->i2c), 0x50, dev->nvram, sizeof(dev->nvram), 1); @@ -2599,11 +2612,24 @@ ncr53c8xx_close(void *priv) } } - static const device_config_t ncr53c8xx_pci_config[] = { - { - "bios", "Enable BIOS", CONFIG_BINARY, "", 0 - }, + { + "bios", "BIOS", CONFIG_SELECTION, "", 1, "", { 0 }, + { + { + "SDMS 4.x BIOS", 2 + }, + { + "SDMS 3.x BIOS", 1 + }, + { + "Disable BIOS", 0 + }, + { + "" + } + }, + }, { "", "", -1 } @@ -2612,9 +2638,9 @@ static const device_config_t ncr53c8xx_pci_config[] = { const device_t ncr53c810_pci_device = { - "NCR 53C810", + "NCR 53c810", DEVICE_PCI, - 0x01, + CHIP_810, ncr53c8xx_init, ncr53c8xx_close, NULL, { NULL }, NULL, NULL, ncr53c8xx_pci_config @@ -2622,7 +2648,7 @@ const device_t ncr53c810_pci_device = const device_t ncr53c810_onboard_pci_device = { - "NCR 53C810 On-Board", + "NCR 53c810 On-Board", DEVICE_PCI, 0x8001, ncr53c8xx_init, ncr53c8xx_close, NULL, @@ -2630,9 +2656,19 @@ const device_t ncr53c810_onboard_pci_device = NULL }; +const device_t ncr53c815_pci_device = +{ + "NCR 53c815", + DEVICE_PCI, + CHIP_815, + ncr53c8xx_init, ncr53c8xx_close, NULL, + { NULL }, NULL, NULL, + ncr53c8xx_pci_config +}; + const device_t ncr53c825a_pci_device = { - "NCR 53C825A", + "NCR 53c825A", DEVICE_PCI, CHIP_825, ncr53c8xx_init, ncr53c8xx_close, NULL, @@ -2642,7 +2678,7 @@ const device_t ncr53c825a_pci_device = const device_t ncr53c860_pci_device = { - "NCR 53C860", + "NCR 53c860", DEVICE_PCI, CHIP_860, ncr53c8xx_init, ncr53c8xx_close, NULL, @@ -2652,7 +2688,7 @@ const device_t ncr53c860_pci_device = const device_t ncr53c875_pci_device = { - "NCR 53C875", + "NCR 53c875", DEVICE_PCI, CHIP_875, ncr53c8xx_init, ncr53c8xx_close, NULL, From 89377b48d2cecb706fb7fe5671627d615f56a263 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Sat, 9 Jan 2021 15:28:39 +0100 Subject: [PATCH 2/2] Fixed the inaccuracy of the 5380. --- src/scsi/scsi_ncr5380.c | 368 +++++++++++++++++++++------------------- 1 file changed, 189 insertions(+), 179 deletions(-) diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index c284272b2..defb56d16 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -122,7 +122,7 @@ typedef struct { int8_t irq; int8_t type; int8_t bios_ver; - uint8_t block_count; + uint16_t block_count, block_count_num; uint8_t status_ctrl; uint8_t pad[2]; @@ -181,6 +181,12 @@ ncr_log(const char *fmt, ...) #define SET_BUS_STATE(ncr, state) ncr->cur_bus = (ncr->cur_bus & ~(SCSI_PHASE_MESSAGE_IN)) | (state & (SCSI_PHASE_MESSAGE_IN)) +static void +ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr); + +static void +ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr); + static void ncr_callback(void *priv); @@ -235,55 +241,22 @@ ncr_reset(ncr5380_t *ncr_dev, ncr_t *ncr) ncr_irq(ncr_dev, ncr, 0); } - static void -dma_timer_on(ncr5380_t *ncr_dev) +ncr_timer_on(ncr5380_t *ncr_dev, ncr_t *ncr, int callback) { - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr->target_id]; - double period = ncr_dev->period; - - if (ncr->data_wait & 2) { + double p = ncr_dev->period; + + if (ncr->data_wait & 2) ncr->data_wait &= ~2; + + if (callback) { + p *= 128.0; } + + p += 1.0; - /* DMA Timer on: 1 wait period + 128 byte periods. Hard disk timings are not emulated at the moment */ - if (dev->type & 5) { - period *= 128.0; - } - - /* This is the 1 us wait period. */ - period += 1.0; - - timer_on_auto(&ncr_dev->timer, period); -} - - -static void -wait_timer_on(ncr5380_t *ncr_dev) -{ - /* PIO Wait Timer On: 1 period. */ - timer_on_auto(&ncr_dev->timer, ncr_dev->period); -} - - -static void -set_dma_enable(ncr5380_t *dev, int enable) -{ - if (enable) { - if (!timer_is_enabled(&dev->timer)) - dma_timer_on(dev); - } else - timer_stop(&dev->timer); -} - - -static void -dma_changed(ncr5380_t *dev, int mode, int enable) -{ - dev->dma_enabled = (mode && enable); - - set_dma_enable(dev, dev->dma_enabled && dev->block_count_loaded); + ncr_log("P = %lf\n", p); + timer_on_auto(&ncr_dev->timer, p); } @@ -397,6 +370,8 @@ ncr_bus_update(void *priv, int bus) if (bus & BUS_ARB) ncr->state = STATE_IDLE; + ncr_log("State = %i\n", ncr->state); + switch (ncr->state) { case STATE_IDLE: ncr->clear_req = ncr->wait_data = ncr->wait_complete = 0; @@ -468,7 +443,7 @@ ncr_bus_update(void *priv, int bus) scsi_device_command_phase0(dev, ncr->command); ncr_log("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->buffer_length, dev->phase); - ncr_dev->period = 1.0; /* 1 us default */ + ncr_dev->period = 1.0; ncr->wait_data = 4; ncr->data_wait = 0; @@ -476,14 +451,14 @@ ncr_bus_update(void *priv, int bus) /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ if (dev->buffer_length && (dev->phase == SCSI_PHASE_DATA_IN || dev->phase == SCSI_PHASE_DATA_OUT)) { p = scsi_device_get_callback(dev); - if (p <= 0.0) - ncr_dev->period = 0.2/* * ((double) dev->buffer_length) */; - else + if (p <= 0.0) { + ncr_dev->period = 0.2; + } else ncr_dev->period = p / ((double) dev->buffer_length); ncr->data_wait |= 2; + ncr_log("SCSI ID %i: command 0x%02x for p = %lf, update = %lf, len = %i\n", ncr->target_id, ncr->command[0], p, ncr_dev->period, dev->buffer_length); } } - ncr->new_phase = dev->phase; } } @@ -502,9 +477,10 @@ ncr_bus_update(void *priv, int bus) ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; if (ncr->data_wait & 2) ncr->data_wait &= ~2; - if (ncr->dma_mode == DMA_IDLE) { + if (ncr->dma_mode == DMA_IDLE) { /*If a data in command that is not read 6/10 has been issued*/ ncr->data_wait |= 1; - wait_timer_on(ncr_dev); + ncr_log("DMA mode idle in\n"); + timer_on_auto(&ncr_dev->timer, ncr_dev->period); } else ncr->clear_req = 3; ncr->cur_bus &= ~BUS_REQ; @@ -514,7 +490,6 @@ ncr_bus_update(void *priv, int bus) break; case STATE_DATAOUT: dev = &scsi_devices[ncr->target_id]; - if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(bus); @@ -526,11 +501,13 @@ ncr_bus_update(void *priv, int bus) ncr->wait_complete = 8; } else { /*More data is to be transferred, place a request*/ - if (ncr->dma_mode == DMA_IDLE) { + if (ncr->dma_mode == DMA_IDLE) { /*If a data out command that is not write 6/10 has been issued*/ ncr->data_wait |= 1; - wait_timer_on(ncr_dev); - } else + ncr_log("DMA mode idle out\n"); + timer_on_auto(&ncr_dev->timer, ncr_dev->period); + } else { ncr->clear_req = 3; + } ncr->cur_bus &= ~BUS_REQ; ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); } @@ -615,9 +592,11 @@ ncr_write(uint16_t port, uint8_t val, void *priv) ncr->mode = val; /*Don't stop the timer until it finishes the transfer*/ - if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA)) - dma_changed(ncr_dev, ncr->dma_mode, ncr->mode & MODE_DMA); - + if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { + ncr_log("Continuing DMA mode\n"); + ncr_timer_on(ncr_dev, ncr, 0); + } + /*When a pseudo-DMA transfer has completed (Send or Initiator Receive), mark it as complete and idle the status*/ if (!ncr_dev->block_count_loaded && !(ncr->mode & MODE_DMA)) { ncr_log("No DMA mode\n"); @@ -638,18 +617,20 @@ ncr_write(uint16_t port, uint8_t val, void *priv) case 5: /* start DMA Send */ ncr_log("Write: start DMA send register\n"); - ncr_log("Write 6 or 10, block count loaded=%d\n", ncr_dev->block_count_loaded); /*a Write 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_SEND; - dma_changed(ncr_dev, ncr->dma_mode, ncr->mode & MODE_DMA); + if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { + ncr_timer_on(ncr_dev, ncr, 0); + } break; case 7: /* start DMA Initiator Receive */ - ncr_log("Write: start DMA initiator receive register\n"); - ncr_log("Read 6 or 10, block count loaded=%d\n", ncr_dev->block_count_loaded); + ncr_log("Write: start DMA initiator receive register, dma? = %02x\n", ncr->mode & MODE_DMA); /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ ncr->dma_mode = DMA_INITIATOR_RECEIVE; - dma_changed(ncr_dev, ncr->dma_mode, ncr->mode & MODE_DMA); + if (ncr_dev->block_count_loaded && (ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) { + ncr_timer_on(ncr_dev, ncr, 0); + } break; default: @@ -657,8 +638,10 @@ ncr_write(uint16_t port, uint8_t val, void *priv) break; } - bus_host = get_bus_host(ncr); - ncr_bus_update(priv, bus_host); + if (ncr->dma_mode == DMA_IDLE) { + bus_host = get_bus_host(ncr); + ncr_bus_update(priv, bus_host); + } } @@ -710,7 +693,7 @@ ncr_read(uint16_t port, void *priv) case 5: /* Bus and Status register */ ncr_log("Read: Bus and Status register\n"); - ret = 0; + ret = 0; bus = get_bus_host(ncr); ncr_log("Get host from Interrupt\n"); @@ -726,6 +709,8 @@ ncr_read(uint16_t port, void *priv) if (bus & BUS_ACK) ret |= STATUS_ACK; + if (bus & BUS_ATN) + ret |= 0x02; if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA)) { ncr_log("Entering DMA mode\n"); @@ -739,8 +724,10 @@ ncr_read(uint16_t port, void *priv) bus_state |= TCR_CD; if (bus & BUS_MSG) bus_state |= TCR_MSG; - if ((ncr->tcr & 7) != bus_state) + if ((ncr->tcr & 7) != bus_state) { ncr_irq(ncr_dev, ncr, 1); + ncr_log("IRQ issued\n"); + } } if (!(bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { ncr_log("Busy error\n"); @@ -756,6 +743,7 @@ ncr_read(uint16_t port, void *priv) case 7: /* reset Parity/Interrupt */ ncr->isr &= ~(STATUS_BUSY_ERROR | 0x20); ncr_irq(ncr_dev, ncr, 0); + ncr_log("Reset Interrupt\n"); break; default: @@ -800,10 +788,11 @@ memio_read(uint32_t addr, void *priv) break; case 0x3900: - if (ncr_dev->buffer_host_pos >= 128 || !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) + if (ncr_dev->buffer_host_pos >= 128 || !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { ret = 0xff; - else { + } else { ret = ncr_dev->buffer[ncr_dev->buffer_host_pos++]; + ncr_log("Read Host pos = %i\n", ncr_dev->buffer_host_pos); if (ncr_dev->buffer_host_pos == 128) { ncr_log("Not ready\n"); @@ -850,6 +839,7 @@ static void memio_write(uint32_t addr, uint8_t val, void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *)priv; + ncr_t *ncr = &ncr_dev->ncr; addr &= 0x3fff; @@ -870,6 +860,8 @@ memio_write(uint32_t addr, uint8_t val, void *priv) if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR) && ncr_dev->buffer_host_pos < 128) { ncr_dev->buffer[ncr_dev->buffer_host_pos++] = val; + ncr_log("Write host pos = %i\n", ncr_dev->buffer_host_pos); + if (ncr_dev->buffer_host_pos == 128) { ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; ncr_dev->ncr_busy = 1; @@ -892,11 +884,15 @@ memio_write(uint32_t addr, uint8_t val, void *priv) break; case 0x3981: /* block counter register */ - ncr_log("Write block counter register: val=%d\n", val); + ncr_log("Write block counter register: val=%d, dma mode = %i, period = %lf\n", val, ncr->dma_mode, ncr_dev->period); ncr_dev->block_count = val; ncr_dev->block_count_loaded = 1; - set_dma_enable(ncr_dev, ncr_dev->dma_enabled && ncr_dev->block_count_loaded); + if (ncr->mode & MODE_DMA) { + ncr_log("Start timer, buffer not ready = %02x\n", !(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)); + ncr_timer_on(ncr_dev, ncr, 0); + } + if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { ncr_dev->buffer_host_pos = 128; ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; @@ -991,27 +987,131 @@ t130b_out(uint16_t port, uint8_t val, void *priv) } } +static void +ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr) +{ + scsi_device_t *dev = &scsi_devices[ncr->target_id]; + + int bus, c = 0; + uint8_t data; + + if (scsi_device_get_callback(dev) > 0.0) + ncr_timer_on(ncr_dev, ncr, 1); + + for (c = 0; c < 10; c++) { + ncr_bus_read(ncr_dev); + if (ncr->cur_bus & BUS_REQ) + break; + } + + if (c == 10) + return; + + /* Data ready. */ + data = ncr_dev->buffer[ncr_dev->buffer_pos]; + bus = get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(data); + + ncr_bus_update(ncr_dev, bus | BUS_ACK); + ncr_bus_update(ncr_dev, bus & ~BUS_ACK); + + ncr_dev->buffer_pos++; + ncr_log("Buffer pos for writing = %d\n", ncr_dev->buffer_pos); + + if (ncr_dev->buffer_pos == 128) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->ncr_busy = 0; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff; + ncr_log("Remaining blocks to be written=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + ncr_log("IO End of write transfer\n"); + ncr->tcr |= TCR_LAST_BYTE_SENT; + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&ncr_dev->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr_log("NCR write irq\n"); + ncr_irq(ncr_dev, ncr, 1); + } + } + return; + } + ncr_dma_send(ncr_dev, ncr); +} + +static void +ncr_dma_initiator_receive(ncr5380_t *ncr_dev, ncr_t *ncr) +{ + scsi_device_t *dev = &scsi_devices[ncr->target_id]; + + int bus, c = 0; + uint8_t temp; + + if (scsi_device_get_callback(dev) > 0.0) + ncr_timer_on(ncr_dev, ncr, 1); + + for (c = 0; c < 10; c++) { + ncr_bus_read(ncr_dev); + if (ncr->cur_bus & BUS_REQ) + break; + } + + if (c == 10) + return; + + /* Data ready. */ + ncr_bus_read(ncr_dev); + temp = BUS_GETDATA(ncr->cur_bus); + + bus = get_bus_host(ncr); + + ncr_bus_update(ncr_dev, bus | BUS_ACK); + ncr_bus_update(ncr_dev, bus & ~BUS_ACK); + + ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; + ncr_log("Buffer pos for reading = %d\n", ncr_dev->buffer_pos); + + if (ncr_dev->buffer_pos == 128) { + ncr_dev->buffer_pos = 0; + ncr_dev->buffer_host_pos = 0; + ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; + ncr_dev->block_count = (ncr_dev->block_count - 1) & 0xff; + ncr_log("Remaining blocks to be read=%d\n", ncr_dev->block_count); + if (!ncr_dev->block_count) { + ncr_dev->block_count_loaded = 0; + ncr_log("IO End of read transfer\n"); + ncr->isr |= STATUS_END_OF_DMA; + timer_stop(&ncr_dev->timer); + if (ncr->mode & MODE_ENA_EOP_INT) { + ncr_log("NCR read irq\n"); + ncr_irq(ncr_dev, ncr, 1); + } + } + return; + } + ncr_dma_initiator_receive(ncr_dev, ncr); +} static void ncr_callback(void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *)priv; ncr_t *ncr = &ncr_dev->ncr; - int bus, c = 0; - uint8_t temp, data; + scsi_device_t *dev = &scsi_devices[ncr->target_id]; - ncr_log("DMA mode=%d\n", ncr->dma_mode); + ncr_log("DMA mode=%d, status ctrl = %02x\n", ncr->dma_mode, ncr_dev->status_ctrl); - if (ncr->data_wait & 1) - ncr->clear_req = 3; - - if (ncr->dma_mode != DMA_IDLE) - dma_timer_on(ncr_dev); + if (ncr->dma_mode != DMA_IDLE && (ncr->mode & MODE_DMA) && ncr_dev->block_count_loaded && scsi_device_get_callback(dev) <= 0.0) + timer_on_auto(&ncr_dev->timer, 10.0); if (ncr->data_wait & 1) { + ncr->clear_req = 3; ncr->data_wait &= ~1; - if (ncr->dma_mode == DMA_IDLE) + if (ncr->dma_mode == DMA_IDLE) { return; + } } switch(ncr->dma_mode) { @@ -1020,62 +1120,16 @@ ncr_callback(void *priv) ncr_log("DMA_SEND with DMA direction set wrong\n"); break; } - - ncr_log("Status for writing=%02x\n", ncr_dev->status_ctrl); - + if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) { - ncr_log("Buffer ready\n"); + ncr_log("Write buffer status ready\n"); break; } if (!ncr_dev->block_count_loaded) break; -write_start: - { - for (c = 0; c < 10; c++) { - ncr_bus_read(ncr_dev); - if (ncr->cur_bus & BUS_REQ) - break; - } - - if (c == 10) - break; - - /* Data ready. */ - data = ncr_dev->buffer[ncr_dev->buffer_pos]; - bus = get_bus_host(ncr) & ~BUS_DATAMASK; - bus |= BUS_SETDATA(data); - - ncr_bus_update(priv, bus | BUS_ACK); - ncr_bus_update(priv, bus & ~BUS_ACK); - - ncr_dev->buffer_pos++; - ncr_log("Buffer pos for writing = %d\n", ncr_dev->buffer_pos); - - if (ncr_dev->buffer_pos == 128) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - ncr_dev->ncr_busy = 0; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; - ncr_log("Remaining blocks to be written=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - set_dma_enable(ncr_dev, 0); - ncr_log("IO End of write transfer\n"); - - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr_log("NCR write irq\n"); - ncr_irq(ncr_dev, ncr, 1); - } - } - break; - } - goto write_start; - } + ncr_dma_send(ncr_dev, ncr); break; case DMA_INITIATOR_RECEIVE: @@ -1084,59 +1138,15 @@ write_start: break; } - ncr_log("Status for reading=%02x\n", ncr_dev->status_ctrl); - - if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) + if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) { + ncr_log("Read buffer status ready\n"); break; + } if (!ncr_dev->block_count_loaded) break; -read_start: - { - for (c = 0; c < 10; c++) { - ncr_bus_read(ncr_dev); - if (ncr->cur_bus & BUS_REQ) - break; - } - - if (c == 10) - break; - - /* Data ready. */ - ncr_bus_read(ncr_dev); - temp = BUS_GETDATA(ncr->cur_bus); - - bus = get_bus_host(ncr); - - ncr_bus_update(priv, bus | BUS_ACK); - ncr_bus_update(priv, bus & ~BUS_ACK); - - ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; - - if (ncr_dev->buffer_pos == 128) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; - - ncr_log("Remaining blocks to be read=%d\n", ncr_dev->block_count); - - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - set_dma_enable(ncr_dev, 0); - ncr_log("IO End of read transfer\n"); - - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) { - ncr_log("NCR read irq\n"); - ncr_irq(ncr_dev, ncr, 1); - } - } - break; - } - goto read_start; - } + ncr_dma_initiator_receive(ncr_dev, ncr); break; } @@ -1146,7 +1156,7 @@ read_start: ncr_log("Updating DMA\n"); ncr->mode &= ~MODE_DMA; ncr->dma_mode = DMA_IDLE; - dma_changed(ncr_dev, ncr->dma_mode, ncr->mode & MODE_DMA); + timer_on_auto(&ncr_dev->timer, 10.0); } }