From d829f80236c36b0c5de492a2446955b0fe3b78b4 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 20 Oct 2019 15:27:50 +0200 Subject: [PATCH] Reworked the emulation of the NCR 5380 family of SCSI controllers to fix numerous bugs; Updated makefile.local to reflect the current list of the logging #define's. --- src/Makefile.local | 28 +- src/scsi/scsi_ncr5380.c | 1192 ++++++++++++++------------------------- 2 files changed, 440 insertions(+), 780 deletions(-) diff --git a/src/Makefile.local b/src/Makefile.local index 6b7bee698..9774208a7 100644 --- a/src/Makefile.local +++ b/src/Makefile.local @@ -10,7 +10,7 @@ # settings, so we can avoid changing the main one for all of # our local setups. # -# Version: @(#)Makefile.local 1.0.21 2019/03/03 +# Version: @(#)Makefile.local 1.0.22 2019/10/20 # # Author: Fred N. van Kempen, # @@ -35,13 +35,15 @@ STUFF := # -DENABLE_VRAM_DUMP enables Video Ram dumping. # -DENABLE_LOG_BREAKPOINT enables extra logging. # Root logging: +# -DENABLE_APM_LOG=N sets logging level at N. # -DENABLE_BUGGER_LOG=N sets logging level at N. # -DENABLE_CONFIG_LOG=N sets logging level at N. # -DENABLE_DEVICE_LOG=N sets logging level at N. -# -DENABLE_KEYBOARD_AT_LOG=N sets logging level at N. # -DENABLE_IO_LOG=N sets logging level at N. +# -DENABLE_PIIX_LOG=N sets logging level at N. # -DENABLE_ISAMEM_LOG=N sets logging level at N. # -DENABLE_ISARTC_LOG=N sets logging level at N. +# -DENABLE_KEYBOARD_AT_LOG=N sets logging level at N. # -DENABLE_MEM_LOG=N sets logging level at N. # -DENABLE_MOUSE_LOG=N sets logging level at N. # -DENABLE_MOUSE_BUS_LOG=N sets logging level at N. @@ -51,12 +53,13 @@ STUFF := # -DENABLE_PC_LOG=N sets logging level at N. # -DENABLE_PCI_LOG=N sets logging level at N. # -DENABLE_PIC_LOG=N sets logging level at N. -# -DENABLE_PIIX_LOG=N sets logging level at N. # -DENABLE_ROM_LOG=N sets logging level at N. # -DENABLE_SERIAL_LOG=N sets logging level at N. # -DENABLE_VNC_LOG=N sets logging level at N. +# -DENABLE_VNC_KEYMAP_LOG=N sets logging level at N. # cdrom/ logging: # -DENABLE_CDROM_LOG=N sets logging level at N. +# -DENABLE_CDROM_DOSBOX_LOG=N sets logging level at N. # -DENABLE_CDROM_IMAGE_LOG=N sets logging level at N. # cpu/ logging: # -DENABLE_386_LOG=N sets logging level at N. @@ -64,12 +67,17 @@ STUFF := # -DENABLE_808X_LOG=N sets logging level at N. # -DENABLE_FPU_LOG=N sets logging level at N. # -DENABLE_X86SEG_LOG=N sets logging level at N. +# cpu_new/ logging: +# -DENABLE_386_COMMON_LOG=N sets logging level at N. +# chipset/ logging: +# -DENABLE_NEAT_LOG=N sets logging level at N. # disk/ logging: # -DENABLE_ESDI_AT_LOG=N sets logging level at N. # -DENABLE_ESDI_MCA_LOG=N sets logging level at N. # -DENABLE_HDC_LOG=N sets logging level at N. # -DENABLE_HDD_IMAGE_LOG=N sets logging level at N. # -DENABLE_IDE_LOG=N sets logging level at N. +# -DENABLE_SFF_LOG=N sets logging level at N. # -DENABLE_ST506_AT_LOG=N sets logging level at N. # -DENABLE_ST506_XT_LOG=N sets logging level at N. # -DENABLE_XTA_LOG=N sets logging level at N. @@ -83,20 +91,21 @@ STUFF := # -DENABLE_IMD_LOG=N sets logging level at N. # -DENABLE_IMG_LOG=N sets logging level at N. # -DENABLE_JSON_LOG=N sets logging level at N. +# -DENABLE_MFM_LOG=N sets logging level at N. # -DENABLE_TD0_LOG=N sets logging level at N. # machine/ logging: # -DENABLE_AMSTRAD_LOG=N sets logging level at N. # -DENABLE_EUROPC_LOG=N sets logging level at N. # -DENABLE_M24VID_LOG=N sets logging level at N. # -DENABLE_MACHINE_LOG=N sets logging level at N. -# -DENABLE_NEAT_LOG=N sets logging level at N. # -DENABLE_PS1_HDC_LOG=N sets logging level at N. # -DENABLE_PS2_MCA_LOG=N sets logging level at N. +# -DENABLE_TANDY_LOG=N sets logging level at N. # -DENABLE_T1000_LOG=N sets logging level at N. # -DENABLE_T3100E_LOG=N sets logging level at N. -# -DENABLE_TANDY_LOG=N sets logging level at N. # network/ logging: # -DENABLE_3COM503_LOG=N sets logging level at N. +# -DENABLE_DP8390_LOG=N sets logging level at N. # -DENABLE_NETWORK_LOG=N sets logging level at N. # -DENABLE_NIC_LOG=N sets logging level at N. # -DENABLE_PCAP_LOG=N sets logging level at N. @@ -105,10 +114,10 @@ STUFF := # scsi/ logging: # -DENABLE_AHA154X_LOG=N sets logging level at N. # -DENABLE_BUSLOGIC_LOG=N sets logging level at N. -# -DENABLE_NCR5380_LOG=N sets logging level at N. -# -DENABLE_NCR53C810_LOG=N sets logging level at N. # -DENABLE_SCSI_CDROM_LOG=N sets logging level at N. # -DENABLE_SCSI_DISK_LOG=N sets logging level at N. +# -DENABLE_NCR5380_LOG=N sets logging level at N. +# -DENABLE_NCR53C8XX_LOG=N sets logging level at N. # -DENABLE_X54X_LOG=N sets logging level at N. # sound/ logging: # -DENABLE_ADLIB_LOG=N sets logging level at N. @@ -122,6 +131,7 @@ STUFF := # video/ logging: # -DENABLE_ATI28800_LOG=N sets logging level at N. # -DENABLE_MACH64_LOG=N sets logging level at N. +# -DENABLE_COMPAQ_CGA_LOG=N sets logging level at N. # -DENABLE_ET4000W32_LOG=N sets logging level at N. # -DENABLE_HT216_LOG=N sets logging level at N. # -DENABLE_ICD2061_LOG=N sets logging level at N. @@ -132,13 +142,15 @@ STUFF := # -DENABLE_VOODOO_LOG=N sets logging level at N. # -DENABLE_VRAM_DUMP=N sets logging level at N. # win/ logging: +# -DENABLE_WIN_LOG=N sets logging level at N. # -DENABLE_D2D_LOG=N sets logging level at N. # -DENABLE_DDRAW_LOG=N sets logging level at N. # -DENABLE_DYNLD_LOG=N sets logging level at N. # -DENABLE_JOYSTICK_LOG=N sets logging level at N. +# -DENABLE_LOG_BREAKPOINT=N sets logging level at N. +# -DENABLE_LOG_TOGGLES=N sets logging level at N. # -DENABLE_SDL_LOG=N sets logging level at N. # -DENABLE_SETTINGS_LOG=N sets logging level at N. -# -DENABLE_WIN_LOG=N sets logging level at N. EXTRAS := diff --git a/src/scsi/scsi_ncr5380.c b/src/scsi/scsi_ncr5380.c index 3851a52ec..20420ca71 100644 --- a/src/scsi/scsi_ncr5380.c +++ b/src/scsi/scsi_ncr5380.c @@ -9,15 +9,15 @@ * Implementation of the NCR 5380 series of SCSI Host Adapters * made by NCR. These controllers were designed for the ISA bus. * - * Version: @(#)scsi_ncr5380.c 1.0.24 2018/10/28 + * Version: @(#)scsi_ncr5380.c 1.0.25 2019/10/16 * * Authors: Sarah Walker, * TheCollector1995, * Fred N. van Kempen, * - * Copyright 2017,2018 Sarah Walker. - * Copyright 2017,2018 TheCollector1995. - * Copyright 2017,2018 Fred N. van Kempen. + * Copyright 2017-2019 Sarah Walker. + * Copyright 2017-2019 TheCollector1995. + * Copyright 2017-2019 Fred N. van Kempen. */ #include #include @@ -46,9 +46,6 @@ #define LCS6821N_ROM L"roms/scsi/ncr5380/Longshine LCS-6821N - BIOS version 1.04.bin" #define RT1000B_ROM L"roms/scsi/ncr5380/Rancho_RT1000_RTBios_version_8.10R.bin" #define T130B_ROM L"roms/scsi/ncr5380/trantor_t130b_bios_v2.14.bin" -#if defined(DEV_BRANCH) && defined(USE_SUMO) -#define SCSIAT_ROM L"roms/scsi/ncr5380/sumo_scsiat_bios_v6.3.bin" -#endif #define NCR_CURDATA 0 /* current SCSI data (read only) */ @@ -96,29 +93,14 @@ #define STATUS_53C80_ACCESSIBLE 0x80 typedef struct { - uint8_t icr; - uint8_t mode; - uint8_t tcr; - uint8_t ser; - uint8_t isr; - uint8_t output_data; + uint8_t icr, mode, tcr, data_wait; + uint8_t isr, output_data, target_id, tx_data; - uint8_t target_id; + uint8_t command[20]; - int dma_mode; - - int bus_host, cur_bus, bus_in; - int new_phase; - int state; - - int clear_req, wait_data, wait_complete; - - int command_pos; - uint8_t command[20]; - int data_pos; - uint8_t tx_data; - - uint8_t unk_08, unk_08_ret; + int dma_mode, cur_bus, bus_in, new_phase; + int state, clear_req, wait_data, wait_complete; + int command_pos, data_pos; } ncr_t; typedef struct { @@ -150,18 +132,17 @@ typedef struct { pc_timer_t timer; double period; - int timer_enabled; int ncr_busy; } ncr5380_t; -#define STATE_IDLE 0 -#define STATE_COMMAND 1 -#define STATE_DATAIN 2 -#define STATE_DATAOUT 3 -#define STATE_STATUS 4 -#define STATE_MESSAGEIN 5 -#define STATE_SELECT 6 +#define STATE_IDLE 0 +#define STATE_COMMAND 1 +#define STATE_DATAIN 2 +#define STATE_DATAOUT 3 +#define STATE_STATUS 4 +#define STATE_MESSAGEIN 5 +#define STATE_SELECT 6 #define DMA_IDLE 0 #define DMA_SEND 1 @@ -217,45 +198,86 @@ ncr_reset(ncr_t *ncr) } +static void +dma_timer_on(ncr5380_t *ncr_dev) +{ + ncr_t *ncr = &ncr_dev->ncr; + double period = ncr_dev->period; + + /* DMA Timer on: 1 wait period + 64 byte periods + 64 byte periods if first time. */ + if (ncr->data_wait & 2) { + ncr->data_wait &= ~2; + period *= 128.0; + } else + period *= 64.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); +} + + static uint32_t get_bus_host(ncr_t *ncr) { uint32_t bus_host = 0; - if (ncr->icr & ICR_DBP) { - ncr_log("Data bus phase\n"); + if (ncr->icr & ICR_DBP) bus_host |= BUS_DBP; - } - if (ncr->icr & ICR_SEL) { - ncr_log("Selection phase\n"); + + if (ncr->icr & ICR_SEL) bus_host |= BUS_SEL; - } - if (ncr->tcr & TCR_IO) { - ncr_log("Data phase\n"); + + if (ncr->tcr & TCR_IO) bus_host |= BUS_IO; - } - if (ncr->tcr & TCR_CD) { - ncr_log("Command phase\n"); + + if (ncr->tcr & TCR_CD) bus_host |= BUS_CD; - } - if (ncr->tcr & TCR_MSG) { - ncr_log("Message phase\n"); + + if (ncr->tcr & TCR_MSG) bus_host |= BUS_MSG; - } - if (ncr->tcr & TCR_REQ) { - ncr_log("Request phase\n"); + + if (ncr->tcr & TCR_REQ) bus_host |= BUS_REQ; - } - if (ncr->icr & ICR_BSY) { - ncr_log("Busy phase\n"); + + if (ncr->icr & ICR_BSY) bus_host |= BUS_BSY; - } + if (ncr->icr & ICR_ATN) bus_host |= BUS_ATN; - if (ncr->icr & ICR_ACK) { - ncr_log("ACK phase\n"); + + if (ncr->icr & ICR_ACK) bus_host |= BUS_ACK; - } + if (ncr->mode & MODE_ARBITRATE) bus_host |= BUS_ARB; @@ -264,13 +286,13 @@ get_bus_host(ncr_t *ncr) static void -ncr_wait_process(ncr5380_t *ncr_dev) +ncr_bus_read(ncr5380_t *ncr_dev) { ncr_t *ncr = &ncr_dev->ncr; scsi_device_t *dev; + int phase; /*Wait processes to handle bus requests*/ - ncr_log("Clear REQ=%d\n", ncr->clear_req); if (ncr->clear_req) { ncr->clear_req--; if (!ncr->clear_req) { @@ -285,31 +307,27 @@ ncr_wait_process(ncr5380_t *ncr_dev) if (!ncr->wait_data) { dev = &scsi_devices[ncr->target_id]; SET_BUS_STATE(ncr, ncr->new_phase); + phase = (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN); - if (ncr->new_phase == SCSI_PHASE_DATA_IN) { - ncr_log("Data In bus phase\n"); + if (phase == SCSI_PHASE_DATA_IN) { ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; ncr->state = STATE_DATAIN; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP; - } else if (ncr->new_phase == SCSI_PHASE_STATUS) { - ncr_log("Status bus phase\n"); + } else if (phase == SCSI_PHASE_DATA_OUT) { + if (ncr->new_phase & BUS_IDLE) { + ncr->state = STATE_IDLE; + ncr->cur_bus &= ~BUS_BSY; + } else + ncr->state = STATE_DATAOUT; + } else if (phase == SCSI_PHASE_STATUS) { ncr->cur_bus |= BUS_REQ; ncr->state = STATE_STATUS; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->status) | BUS_DBP; - } else if (ncr->new_phase == SCSI_PHASE_MESSAGE_IN) { - ncr_log("Message In bus phase\n"); + } else if (phase == SCSI_PHASE_MESSAGE_IN) { ncr->state = STATE_MESSAGEIN; ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP; - } else { - if (ncr->new_phase & BUS_IDLE) { - ncr_log("Bus Idle phase\n"); - ncr->state = STATE_IDLE; - ncr->cur_bus &= ~BUS_BSY; - } else { - ncr->state = STATE_DATAOUT; - ncr_log("Data Out bus phase\n"); - } - } + } else + fatal("Bad new phase: %i\n", phase); } } @@ -318,8 +336,159 @@ ncr_wait_process(ncr5380_t *ncr_dev) if (!ncr->wait_complete) ncr->cur_bus |= BUS_REQ; } +} - ncr->bus_host = ncr->cur_bus; + +static void +ncr_bus_update(void *priv, int bus) +{ + ncr5380_t *ncr_dev = (ncr5380_t *)priv; + ncr_t *ncr = &ncr_dev->ncr; + scsi_device_t *dev = &scsi_devices[ncr->target_id]; + double p; + uint8_t sel_data; + + /*Start the SCSI command layer, which will also make the timings*/ + if (bus & BUS_ARB) + ncr->state = STATE_IDLE; + + if (ncr->state == STATE_IDLE) { + ncr->clear_req = ncr->wait_data = ncr->wait_complete = 0; + if ((bus & BUS_SEL) && !(bus & BUS_BSY)) { + ncr_log("Selection phase\n"); + sel_data = BUS_GETDATA(bus); + + ncr->target_id = get_dev_id(sel_data); + + ncr_log("Select - target ID = %i\n", ncr->target_id); + + /*Once the device has been found and selected, mark it as busy*/ + if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr->target_id])) { + ncr->cur_bus |= BUS_BSY; + ncr->state = STATE_SELECT; + } + } + } else if (ncr->state == STATE_SELECT) { + if (!(bus & BUS_SEL)) { + if (!(bus & BUS_ATN)) { + if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr->target_id])) { + ncr_log("Device found at ID %i, Current Bus BSY=%02x\n", ncr->target_id, ncr->cur_bus); + ncr->state = STATE_COMMAND; + ncr->cur_bus = BUS_BSY | BUS_REQ; + ncr_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); + ncr->command_pos = 0; + SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); + picint(1 << ncr_dev->irq); + } else { + ncr->state = STATE_IDLE; + ncr->cur_bus = 0; + } + } else + fatal("Dropped selection with ATN\n"); + } + } else if (ncr->state == STATE_COMMAND) { + if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { + /*Write command byte to the output data register*/ + ncr->command[ncr->command_pos++] = BUS_GETDATA(bus); + ncr->clear_req = 3; + ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN; + ncr->cur_bus &= ~BUS_REQ; + + ncr_log("Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(bus)); + + if (ncr->command_pos == cmd_len[(ncr->command[0] >> 5) & 7]) { + /*Reset data position to default*/ + ncr->data_pos = 0; + + dev = &scsi_devices[ncr->target_id]; + + ncr_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->status); + dev->buffer_length = -1; + 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->wait_data = 4; + ncr->data_wait = 0; + + if (dev->status == SCSI_STATUS_OK) { + /*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 + ncr_dev->period = p / ((double) dev->buffer_length); + ncr->data_wait |= 2; + } + } + + ncr->new_phase = dev->phase; + } + } + } else if (ncr->state == STATE_DATAIN) { + dev = &scsi_devices[ncr->target_id]; + if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { + if (ncr->data_pos >= dev->buffer_length) { + ncr->cur_bus &= ~BUS_REQ; + scsi_device_command_phase1(dev); + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; + 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) { + ncr->data_wait |= 1; + wait_timer_on(ncr_dev); + } else + ncr->clear_req = 3; + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_DATA_IN; + } + } + } else if (ncr->state == 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); + + if (ncr->data_pos >= dev->buffer_length) { + ncr->cur_bus &= ~BUS_REQ; + scsi_device_command_phase1(dev); + ncr->new_phase = SCSI_PHASE_STATUS; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } else { + /*More data is to be transferred, place a request*/ + if (ncr->dma_mode == DMA_IDLE) { + ncr->data_wait |= 1; + wait_timer_on(ncr_dev); + } else + ncr->clear_req = 3; + ncr->cur_bus &= ~BUS_REQ; + ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); + } + } + } else if (ncr->state == STATE_STATUS) { + if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { + /*All transfers done, wait until next transfer*/ + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = SCSI_PHASE_MESSAGE_IN; + ncr->wait_data = 4; + ncr->wait_complete = 8; + } + } else if (ncr->state == STATE_MESSAGEIN) { + if ((bus & BUS_ACK) && !(ncr->bus_in & BUS_ACK)) { + ncr->cur_bus &= ~BUS_REQ; + ncr->new_phase = BUS_IDLE; + ncr->wait_data = 4; + } + } + + ncr->bus_in = bus; } @@ -328,6 +497,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *)priv; ncr_t *ncr = &ncr_dev->ncr; + int bus_host = 0; ncr_log("NCR5380 write(%04x,%02x)\n",port & 7,val); @@ -339,9 +509,12 @@ ncr_write(uint16_t port, uint8_t val, void *priv) case 1: /* Initiator Command Register */ ncr_log("Write: Initiator command register\n"); + if ((val & 0x80) && !(ncr->icr & 0x80)) { + ncr_log("Resetting the 53c400\n"); + picint(1 << ncr_dev->irq); + ncr_reset(&ncr_dev->ncr); + } ncr->icr = val; - - ncr_dev->timer_enabled = 1; break; case 2: /* Mode register */ @@ -352,6 +525,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) } ncr->mode = val; + dma_changed(ncr_dev, ncr->dma_mode, ncr->mode & MODE_DMA); /*If it's not DMA mode, don't do anything*/ if (!(ncr->mode & MODE_DMA)) { @@ -376,6 +550,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv) 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); break; case 7: /* start DMA Initiator Receive */ @@ -383,12 +558,16 @@ ncr_write(uint16_t port, uint8_t val, void *priv) ncr_log("Read 6 or 10, block count loaded=%d\n", ncr_dev->block_count_loaded); /*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); break; default: ncr_log("NCR5380: bad write %04x %02x\n", port, val); break; } + + bus_host = get_bus_host(ncr); + ncr_bus_update(priv, bus_host); } @@ -398,6 +577,7 @@ ncr_read(uint16_t port, void *priv) ncr5380_t *ncr_dev = (ncr5380_t *)priv; ncr_t *ncr = &ncr_dev->ncr; uint8_t ret = 0xff; + int bus, bus_state; switch (port & 7) { case 0: /* Current SCSI data */ @@ -408,15 +588,14 @@ ncr_read(uint16_t port, void *priv) ret = ncr->output_data; } else { /*Return the data from the SCSI bus*/ - ncr_wait_process(ncr_dev); - ncr_log("NCR GetData=%02x\n", BUS_GETDATA(ncr->bus_host)); - ret = BUS_GETDATA(ncr->bus_host); + ncr_bus_read(ncr_dev); + ncr_log("NCR GetData=%02x\n", BUS_GETDATA(ncr->cur_bus)); + ret = BUS_GETDATA(ncr->cur_bus); } break; case 1: /* Initiator Command Register */ - ncr_log("Read: Initiator Command register\n"); - ncr_log("NCR ICR Read=%02x\n", ncr->icr); + ncr_log("Read: Initiator Command register, NCR ICR Read=%02x\n", ncr->icr); ret = ncr->icr; break; @@ -427,60 +606,54 @@ ncr_read(uint16_t port, void *priv) break; case 3: /* Target Command Register */ - ncr_log("Read: Target Command register\n"); - ncr_log("NCR target stat=%02x\n", ncr->tcr); + ncr_log("Read: Target Command register, NCR target stat=%02x\n", ncr->tcr); ret = ncr->tcr; break; case 4: /* Current SCSI Bus status */ ncr_log("Read: SCSI bus status register\n"); ret = 0; - ncr_wait_process(ncr_dev); - ncr_log("NCR cur bus stat=%02x\n", ncr->bus_host & 0xff); - ret |= (ncr->bus_host & 0xff); + ncr_bus_read(ncr_dev); + ncr_log("NCR cur bus stat=%02x\n", ncr->cur_bus & 0xff); + ret |= (ncr->cur_bus & 0xff); break; case 5: /* Bus and Status register */ ncr_log("Read: Bus and Status register\n"); ret = 0; - ncr->bus_host = get_bus_host(ncr); + bus = get_bus_host(ncr); ncr_log("Get host from Interrupt\n"); /*Check if the phase in process matches with TCR's*/ - if ((ncr->bus_host & SCSI_PHASE_MESSAGE_IN) == - (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN)) - { + if ((bus & SCSI_PHASE_MESSAGE_IN) == (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN)) { ncr_log("Phase match\n"); ret |= STATUS_PHASE_MATCH; - } - else + } else picint(1 << ncr_dev->irq); - ncr_wait_process(ncr_dev); + ncr_bus_read(ncr_dev); + bus = ncr->cur_bus; - if (ncr->bus_host & BUS_ACK) + if (bus & BUS_ACK) ret |= STATUS_ACK; - if ((ncr->bus_host & BUS_REQ) && (ncr->mode & MODE_DMA)) { + if ((bus & BUS_REQ) && (ncr->mode & MODE_DMA)) { ncr_log("Entering DMA mode\n"); ret |= STATUS_DRQ; - int bus = 0; + bus_state = 0; - if (ncr->bus_host & BUS_IO) - bus |= TCR_IO; - if (ncr->bus_host & BUS_CD) - bus |= TCR_CD; - if (ncr->bus_host & BUS_MSG) - bus |= TCR_MSG; - if ((ncr->tcr & 7) != bus) - { + if (bus & BUS_IO) + bus_state |= TCR_IO; + if (bus & BUS_CD) + bus_state |= TCR_CD; + if (bus & BUS_MSG) + bus_state |= TCR_MSG; + if ((ncr->tcr & 7) != bus_state) ncr->isr |= STATUS_INT; - } } - if (!(ncr->bus_host & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) - { + if (!(bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { ncr_log("Busy error\n"); ret |= STATUS_BUSY_ERROR; } @@ -512,9 +685,6 @@ memio_read(uint32_t addr, void *priv) uint8_t ret = 0xff; addr &= 0x3fff; -#if ENABLE_NCR5380_LOG - ncr_log("memio_read %08x\n", addr); -#endif if (addr < 0x2000) ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; @@ -538,18 +708,12 @@ memio_read(uint32_t addr, void *priv) break; case 0x3900: - ncr_log("Read 3900 host pos %i status ctrl %02x\n", ncr_dev->buffer_host_pos, ncr_dev->status_ctrl); - ncr_log("Read port 0x3900-0x397f\n"); - if (ncr_dev->buffer_host_pos >= 128 || !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) ret = 0xff; else { ret = ncr_dev->buffer[ncr_dev->buffer_host_pos++]; - ncr_log("Read host buffer=%d\n", ncr_dev->buffer_host_pos); - - if (ncr_dev->buffer_host_pos == 128) - { + if (ncr_dev->buffer_host_pos == 128) { ncr_log("Not ready\n"); ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; } @@ -559,12 +723,10 @@ memio_read(uint32_t addr, void *priv) case 0x3980: switch (addr) { case 0x3980: /* status */ - ret = ncr_dev->status_ctrl;// | 0x80; + ret = ncr_dev->status_ctrl; ncr_log("NCR status ctrl read=%02x\n", ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY); if (!ncr_dev->ncr_busy) - { ret |= STATUS_53C80_ACCESSIBLE; - } break; case 0x3981: /* block counter register*/ @@ -605,25 +767,18 @@ memio_write(uint32_t addr, uint8_t val, void *priv) ncr_dev->ext_ram[addr - 0x3a00] = val; else switch (addr & 0x3f80) { case 0x3800: -#if 0 - ncr_log("Write intram %02x %02x\n", addr & 0x3f, val); -#endif ncr_dev->int_ram[addr & 0x3f] = val; break; case 0x3880: -#if ENABLE_NCR5380_LOG - ncr_log("Write 53c80 %04x %02x\n", addr, val); -#endif ncr_write(addr, val, ncr_dev); break; case 0x3900: if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR) && ncr_dev->buffer_host_pos < 128) { ncr_dev->buffer[ncr_dev->buffer_host_pos++] = val; - - if (ncr_dev->buffer_host_pos == 128) - { + + if (ncr_dev->buffer_host_pos == 128) { ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; ncr_dev->ncr_busy = 1; } @@ -633,20 +788,17 @@ memio_write(uint32_t addr, uint8_t val, void *priv) case 0x3980: switch (addr) { case 0x3980: /* Control */ - ncr_log("Write 0x3980: val=%02x\n", val); - if (val & 0x80) - { + if (val & 0x80) { ncr_log("Resetting the 53c400\n"); picint(1 << ncr_dev->irq); + ncr_reset(&ncr_dev->ncr); } if ((val & CTRL_DATA_DIR) && !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { - ncr_log("Pos 128\n"); ncr_dev->buffer_host_pos = 128; ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; } else if (!(val & CTRL_DATA_DIR) && (ncr_dev->status_ctrl & CTRL_DATA_DIR)) { - ncr_log("Pos 0\n"); ncr_dev->buffer_host_pos = 0; ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; } @@ -654,18 +806,15 @@ memio_write(uint32_t addr, uint8_t val, void *priv) break; case 0x3981: /* block counter register */ - ncr_log("Write 0x3981: val=%d\n", val); + ncr_log("Write block counter register: val=%d\n", val); 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); - ncr_log("Timer for transfers=%02x\n", ncr_dev->timer_enabled); - if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { - ncr_log("Data Read\n"); ncr_dev->buffer_host_pos = 128; ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; } else { - ncr_log("Data Write\n"); ncr_dev->buffer_host_pos = 0; ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; } @@ -686,10 +835,10 @@ t130b_read(uint32_t addr, void *priv) addr &= 0x3fff; if (addr < 0x1800) ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; - else - if (addr < 0x1880) + else if (addr >= 0x1800 && addr < 0x1880) ret = ncr_dev->ext_ram[addr & 0x7f]; + ncr_log("MEM: Reading %02X from %08X\n", ret, addr); return(ret); } @@ -701,6 +850,7 @@ t130b_write(uint32_t addr, uint8_t val, void *priv) ncr5380_t *ncr_dev = (ncr5380_t *)priv; addr &= 0x3fff; + ncr_log("MEM: Writing %02X to %08X\n", val, addr); if (addr >= 0x1800 && addr < 0x1880) ncr_dev->ext_ram[addr & 0x7f] = val; } @@ -713,30 +863,21 @@ t130b_in(uint16_t port, void *priv) uint8_t ret = 0xff; switch (port & 0x0f) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: + case 0x00: case 0x01: case 0x02: case 0x03: ret = memio_read((port & 7) | 0x3980, ncr_dev); break; - case 0x04: - case 0x05: + case 0x04: case 0x05: ret = memio_read(0x3900, ncr_dev); break; - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: ret = ncr_read(port, ncr_dev); break; } + ncr_log("I/O: Reading %02X from %04X\n", ret, port); return(ret); } @@ -746,509 +887,94 @@ t130b_out(uint16_t port, uint8_t val, void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *)priv; + ncr_log("I/O: Writing %02X to %04X\n", val, port); + switch (port & 0x0f) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: + case 0x00: case 0x01: case 0x02: case 0x03: memio_write((port & 7) | 0x3980, val, ncr_dev); break; - case 0x04: - case 0x05: + case 0x04: case 0x05: memio_write(0x3900, val, ncr_dev); break; - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: case 0x0f: ncr_write(port, val, ncr_dev); break; } } -#if defined(DEV_BRANCH) && defined(USE_SUMO) -static uint8_t -scsiat_in(uint16_t port, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - uint8_t ret = 0xff; - - switch (port & 0x0f) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - ret = ncr_read(port, ncr_dev); - break; - } - - ncr_log("SCSI AT read=0x%03x, ret=%02x\n", port, ret); - - return(ret); -} - - -static void -scsiat_out(uint16_t port, uint8_t val, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr->target_id]; - - ncr_log("SCSI AT write=0x%03x, val=%02x\n", port, val); - switch (port & 0x0f) { - case 0x08: - ncr->unk_08 = val; - - if (ncr->unk_08 & 0x08) - { - if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) - { - while (ncr_dev->buffer_host_pos < 128) - { - uint8_t temp; - - temp = ncr_dev->buffer[ncr_dev->buffer_host_pos++]; - - ncr_log("Read Buffer host=%d\n", ncr_dev->buffer_host_pos); - - ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; - ncr->bus_host |= BUS_SETDATA(temp); - - if (ncr_dev->buffer_host_pos == 128) - break; - } - } - else if (ncr->dma_mode == DMA_SEND) - { - while (ncr_dev->buffer_host_pos < 128) - { - /* Data ready. */ - uint8_t temp; - - ncr_wait_process(ncr_dev); - temp = BUS_GETDATA(ncr->bus_host); - ncr->bus_host = get_bus_host(ncr); - - ncr_dev->buffer[ncr_dev->buffer_host_pos++] = temp; - - ncr_log("Write Buffer host=%d\n", ncr_dev->buffer_host_pos); - - if (ncr_dev->buffer_host_pos == 128) - { - - break; - } - } - } - } - - if (ncr->unk_08 & 0x01) - { - ncr_dev->block_count_loaded = 1; - ncr_dev->block_count = dev->buffer_length / 128; - } - break; - - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - ncr_write(port, val, ncr_dev); - break; - } -} -#endif - - static void ncr_callback(void *priv) { ncr5380_t *ncr_dev = (ncr5380_t *)priv; ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &scsi_devices[ncr->target_id]; - int req_len, c = 0; - double p; + int bus, bt = 0, c = 0; uint8_t temp, data; ncr_log("DMA mode=%d\n", ncr->dma_mode); - ncr_dev->timer_enabled = 0; + if (ncr->data_wait & 1) + ncr->clear_req = 3; - if (((ncr->state == STATE_DATAIN) || (ncr->state == STATE_DATAOUT)) && (ncr->dma_mode != DMA_IDLE)) - timer_on(&ncr_dev->timer, ncr_dev->period, 0); - else - timer_on(&ncr_dev->timer, 40.0, 0); + if (ncr->dma_mode != DMA_IDLE) + dma_timer_on(ncr_dev); - if (ncr->dma_mode == DMA_IDLE) { - ncr->bus_host = get_bus_host(ncr); - - /*Start the SCSI command layer, which will also make the timings*/ - if (ncr->bus_host & BUS_ARB) { - ncr_log("Arbitration\n"); - ncr->state = STATE_IDLE; - } - - if (ncr->state == STATE_IDLE) { - ncr->clear_req = ncr->wait_data = ncr->wait_complete = 0; - if ((ncr->bus_host & BUS_SEL) && !(ncr->bus_host & BUS_BSY)) { - ncr_log("Selection phase\n"); - uint8_t sel_data = BUS_GETDATA(ncr->bus_host); - - ncr->target_id = get_dev_id(sel_data); - - ncr_log("Select - target ID = %i\n", ncr->target_id); - - /*Once the device has been found and selected, mark it as busy*/ - if ((ncr->target_id != (uint8_t)-1) && scsi_device_present(&scsi_devices[ncr->target_id])) { - ncr->cur_bus |= BUS_BSY; - ncr_log("Device found at ID %i\n", ncr->target_id); - ncr_log("Current Bus BSY=%02x\n", ncr->cur_bus); - ncr->state = STATE_COMMAND; - ncr->cur_bus = BUS_BSY | BUS_REQ; - ncr_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); - ncr->command_pos = 0; - SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); - picint(1 << ncr_dev->irq); - } else { - ncr->state = STATE_IDLE; - ncr->cur_bus = 0; - } - } - } else if (ncr->state == STATE_COMMAND) { - /*Command phase, make sure the ICR ACK bit is set to keep on, - because the device must be acknowledged by ICR*/ - ncr_log("NCR ICR for Command=%02x\n", ncr->bus_host & BUS_ACK); - if ((ncr->bus_host & BUS_ACK) && (ncr->command_pos < cmd_len[(ncr->command[0] >> 5) & 7])) { - /*Write command byte to the output data register*/ - ncr->command[ncr->command_pos++] = BUS_GETDATA(ncr->bus_host); - - ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN; - ncr->clear_req = 3; - ncr_log("Current bus for command request=%02x\n", ncr->cur_bus & BUS_REQ); - ncr->cur_bus &= ~BUS_REQ; - - ncr_log("Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(ncr->bus_host)); - - if (ncr->command_pos == cmd_len[(ncr->command[0] >> 5) & 7]) { - /*Reset data position to default*/ - ncr->data_pos = 0; - - dev = &scsi_devices[ncr->target_id]; - - ncr_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->status); - - dev->buffer_length = -1; - - /*Now, execute the given SCSI command*/ - 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); - - if (dev->status != SCSI_STATUS_OK) { - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - return; - } - - /*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); - req_len = MIN(64, dev->buffer_length); - if (p <= 0.0) - ncr_dev->period = 0.2 * ((double) req_len); - else - ncr_dev->period = (p / ((double) dev->buffer_length)) * ((double) req_len); - } - - if (dev->phase == SCSI_PHASE_DATA_OUT) { - /* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */ - ncr_log("Next state is data out\n"); - ncr->new_phase = SCSI_PHASE_DATA_OUT; - ncr->wait_data = 4; - ncr->clear_req = 4; - } else { - /* Other command - execute immediately. */ - ncr->new_phase = dev->phase; - ncr->wait_data = 4; - } - } - } - } else if (ncr->state == STATE_DATAIN) { - dev = &scsi_devices[ncr->target_id]; - ncr_log("Data In ACK=%02x\n", ncr->bus_host & BUS_ACK); - if (ncr->bus_host & BUS_ACK) { - if (ncr->data_pos >= dev->buffer_length) { - scsi_device_command_phase1(dev); - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - ncr->clear_req = 3; - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_DATA_IN; - } - } - } else if (ncr->state == STATE_DATAOUT) { - dev = &scsi_devices[ncr->target_id]; - - ncr_log("Data Out ACK=%02x\n", ncr->bus_host & BUS_ACK); - if (ncr->bus_host & BUS_ACK) { - dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); - - if (ncr->data_pos >= dev->buffer_length) { - scsi_device_command_phase1(dev); - ncr->cur_bus &= ~BUS_REQ; - ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - /*More data is to be transferred, place a request*/ - ncr->cur_bus |= BUS_REQ; - ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); - } - } - } else if (ncr->state == STATE_STATUS) { - if (ncr->bus_host & BUS_ACK) { - /*All transfers done, wait until next transfer*/ - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_MESSAGE_IN; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } - } else if (ncr->state == STATE_MESSAGEIN) { - if (ncr->bus_host & BUS_ACK) { - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = BUS_IDLE; - ncr->wait_data = 4; - } - } - ncr->bus_in = ncr->bus_host; + if (ncr->data_wait & 1) { + ncr->data_wait &= ~1; + if (ncr->dma_mode == DMA_IDLE) + return; } - if (ncr_dev->type < 3) { - if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) { - if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { - ncr_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); - return; + switch(ncr->dma_mode) { + case DMA_SEND: + if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { + ncr_log("DMA_SEND with DMA direction set wrong\n"); + break; } - ncr_log("Status for reading=%02x\n", ncr_dev->status_ctrl); + ncr_log("Status for writing=%02x\n", ncr_dev->status_ctrl); - if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) return; + if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) { + ncr_log("Buffer ready\n"); + break; + } - if (!ncr_dev->block_count_loaded) return; - - while (c < 64) { - /* Data ready. */ - ncr_wait_process(ncr_dev); - temp = BUS_GETDATA(ncr->bus_host); - ncr->bus_host = get_bus_host(ncr); - - if (ncr->data_pos >= dev->buffer_length) { - scsi_device_command_phase1(dev); - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - ncr->clear_req = 3; - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_DATA_IN; - } - - ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; - ncr_log("Buffer pos for reading=%d\n", ncr_dev->buffer_pos); - - c++; - - 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; - 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->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); - } - } - break; - } - } - } else if (ncr->dma_mode == DMA_SEND) { - if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { - ncr_log("DMA_SEND with DMA direction set wrong\n"); - return; - } - - 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"); - return; - } - - if (!ncr_dev->block_count_loaded) return; - - while (c < 64) { - /* Data ready. */ - data = ncr_dev->buffer[ncr_dev->buffer_pos]; - ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; - ncr->bus_host |= BUS_SETDATA(data); - - dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); - - if (ncr->data_pos >= dev->buffer_length) { - scsi_device_command_phase1(dev); - ncr->cur_bus &= ~BUS_REQ; - ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - /*More data is to be transferred, place a request*/ - ncr->cur_bus |= BUS_REQ; - ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); - } - - c++; - - 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; - 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->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); - } - } - break; - } - } - } - } else { - if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) { - if (!(ncr_dev->block_count_loaded)) - return; - - while (c < 64) { - /* Data ready. */ - ncr_wait_process(ncr_dev); - temp = BUS_GETDATA(ncr->bus_host); - ncr->bus_host = get_bus_host(ncr); - - if (ncr->data_pos >= dev->buffer_length) { - scsi_device_command_phase1(dev); - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - ncr->tx_data = dev->sc->temp_buffer[ncr->data_pos++]; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - ncr->clear_req = 3; - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_DATA_IN; - } - - ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; - ncr_log("Buffer pos for reading=%d\n", ncr_dev->buffer_pos); - - c++; - - if (ncr_dev->buffer_pos == 128) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - 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; - 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->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); - } - } - break; - } - } - } else if (ncr->dma_mode == DMA_SEND) { if (!ncr_dev->block_count_loaded) - return; + break; + + while (bt < 64) { + for (c = 0; c < 10; c++) { + ncr_bus_read(ncr_dev); + if (ncr->cur_bus & BUS_REQ) + break; + } + + if (c == 10) + break; - while (c < 64) { /* Data ready. */ data = ncr_dev->buffer[ncr_dev->buffer_pos]; - ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; - ncr->bus_host |= BUS_SETDATA(data); + bus = get_bus_host(ncr) & ~BUS_DATAMASK; + bus |= BUS_SETDATA(data); - dev->sc->temp_buffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); + ncr_bus_update(priv, bus | BUS_ACK); + ncr_bus_update(priv, bus & ~BUS_ACK); - if (ncr->data_pos >= dev->buffer_length) { - scsi_device_command_phase1(dev); - ncr->cur_bus &= ~BUS_REQ; - ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - /*More data is to be transferred, place a request*/ - ncr->cur_bus |= BUS_REQ; - ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); - } - - c++; + bt++; 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; @@ -1261,15 +987,78 @@ ncr_callback(void *priv) } break; } - } - } + } + break; + + case DMA_INITIATOR_RECEIVE: + if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { + ncr_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); + break; + } + + ncr_log("Status for reading=%02x\n", ncr_dev->status_ctrl); + + if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) + break; + + if (!ncr_dev->block_count_loaded) + break; + + while (bt < 64) { + 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; + bt++; + + 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->isr |= STATUS_INT; + picint(1 << ncr_dev->irq); + } + } + break; + } + } + break; } - ncr_wait_process(ncr_dev); - if (!(ncr->bus_host & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { + ncr_bus_read(ncr_dev); + + if (!(ncr->cur_bus & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { 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); } } @@ -1320,35 +1109,17 @@ ncr_init(const device_t *info) ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); mem_mapping_disable(&ncr_dev->bios_rom.mapping); - - mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, - t130b_read, NULL, NULL, - t130b_write, NULL, NULL, - ncr_dev->bios_rom.rom, 0, ncr_dev); + + if (ncr_dev->rom_addr > 0x00000) { + mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, + t130b_read, NULL, NULL, + t130b_write, NULL, NULL, + ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev); + } io_sethandler(ncr_dev->base, 16, t130b_in,NULL,NULL, t130b_out,NULL,NULL, ncr_dev); break; - -#if defined(DEV_BRANCH) && defined(USE_SUMO) - case 3: /* Sumo SCSI-AT */ - ncr_dev->base = device_get_config_hex16("base"); - ncr_dev->irq = device_get_config_int("irq"); - ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); - rom_init(&ncr_dev->bios_rom, SCSIAT_ROM, - ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - - mem_mapping_disable(&ncr_dev->bios_rom.mapping); - - mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, - t130b_read, NULL, NULL, - t130b_write, NULL, NULL, - ncr_dev->bios_rom.rom, 0, ncr_dev); - - io_sethandler(ncr_dev->base, 16, - scsiat_in,NULL,NULL, scsiat_out,NULL,NULL, ncr_dev); - break; -#endif } sprintf(temp, "%s: BIOS=%05X", ncr_dev->name, ncr_dev->rom_addr); @@ -1362,9 +1133,7 @@ ncr_init(const device_t *info) ncr_dev->status_ctrl = STATUS_BUFFER_NOT_READY; ncr_dev->buffer_host_pos = 128; - timer_add(&ncr_dev->timer, ncr_callback, ncr_dev, 1); - ncr_dev->timer.period = 10.0; - timer_set_delay_u64(&ncr_dev->timer, (uint64_t) (ncr_dev->timer.period * ((double) TIMER_USEC))); + timer_add(&ncr_dev->timer, ncr_callback, ncr_dev, 0); return(ncr_dev); } @@ -1378,7 +1147,6 @@ ncr_close(void *priv) if (ncr_dev) { /* Tell the timer to terminate. */ timer_stop(&ncr_dev->timer); - ncr_dev->timer_enabled = 0; free(ncr_dev); ncr_dev = NULL; @@ -1407,15 +1175,6 @@ t130b_available(void) } -#if defined(DEV_BRANCH) && defined(USE_SUMO) -static int -scsiat_available(void) -{ - return(rom_present(SCSIAT_ROM)); -} -#endif - - static const device_config_t ncr5380_mmio_config[] = { { "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, @@ -1511,104 +1270,6 @@ static const device_config_t t130b_config[] = { } }; -#if defined(DEV_BRANCH) && defined(USE_SUMO) -static const device_config_t scsiat_config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x0310, - { - { - "None", 0 - }, - { - "300H", 0x0300 - }, - { - "310H", 0x0310 - }, - { - "320H", 0x0320 - }, - { - "330H", 0x0330 - }, - { - "340H", 0x0340 - }, - { - "350H", 0x0350 - }, - { - "360H", 0x0360 - }, - { - "370H", 0x0370 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, - { - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, - }, - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, - { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "CC00H", 0xcc000 - }, - { - "D800H", 0xd8000 - }, - { - "DC00H", 0xdc000 - }, - { - "" - } - }, - }, - { - "", "", -1 - } -}; -#endif - const device_t scsi_lcs6821n_device = { @@ -1642,16 +1303,3 @@ const device_t scsi_t130b_device = NULL, NULL, t130b_config }; - -#if defined(DEV_BRANCH) && defined(USE_SUMO) -const device_t scsi_scsiat_device = -{ - "Sumo SCSI-AT", - DEVICE_ISA, - 3, - ncr_init, ncr_close, NULL, - scsiat_available, - NULL, NULL, - scsiat_config -}; -#endif