From 9d4654aca95c056624bf269074d92686b7a859ba Mon Sep 17 00:00:00 2001 From: Dimitris Panokostas Date: Thu, 18 Jun 2020 00:28:44 +0200 Subject: [PATCH] Implemented some missing functions --- src/flashrom.cpp | 799 +++++++++++++++++++++++++++++++++++++++-------- src/gayle.cpp | 195 +++++++++++- src/ide.cpp | 30 ++ src/scsi.cpp | 70 ++--- 4 files changed, 923 insertions(+), 171 deletions(-) diff --git a/src/flashrom.cpp b/src/flashrom.cpp index 4aed37d2..f2c83d05 100644 --- a/src/flashrom.cpp +++ b/src/flashrom.cpp @@ -8,38 +8,288 @@ * (c) 2014 Toni Wilen */ +#include "sysconfig.h" #include "sysdeps.h" +#include "options.h" #include "zfile.h" #include "flashrom.h" +#include "memory.h" +#include "newcpu.h" #include "gui.h" -#include "uae.h" + +#define FLASH_LOG 0 +#define EEPROM_LOG 0 + +/* MICROWIRE EEPROM */ + +struct eeprom93xx_eeprom_t { + uint8_t tick; + uint8_t address; + uint8_t command; + uint8_t writeable; + + uint8_t eecs; + uint8_t eesk; + uint8_t eedo; + + uint8_t addrbits; + uint16_t size; + uint16_t data; + uint16_t contents[256]; + + uae_u8 *memory; + struct zfile *zf; +}; + +static const char *opstring[] = { "extended", "write", "read", "erase" }; + +void eeprom93xx_write(void *eepromp, int eecs, int eesk, int eedi) +{ + eeprom93xx_eeprom_t *eeprom = (eeprom93xx_eeprom_t*)eepromp; + uint8_t tick = eeprom->tick; + uint8_t eedo = eeprom->eedo; + uint16_t address = eeprom->address; + uint8_t command = eeprom->command; + +#if EEPROM_LOG + write_log("CS=%u SK=%u DI=%u DO=%u, tick = %u\n", eecs, eesk, eedi, eedo, tick); +#endif + + if (!eeprom->eecs && eecs) { + /* Start chip select cycle. */ +#if EEPROM_LOG + write_log("Cycle start, waiting for 1st start bit (0)\n"); +#endif + tick = 0; + command = 0x0; + address = 0x0; + } + else if (eeprom->eecs && !eecs) { + /* End chip select cycle. This triggers write / erase. */ + if (eeprom->writeable) { + uint8_t subcommand = address >> (eeprom->addrbits - 2); + if (command == 0 && subcommand == 2) { + /* Erase all. */ + for (address = 0; address < eeprom->size; address++) { + eeprom->contents[address] = 0xffff; + } + } + else if (command == 3) { + /* Erase word. */ + eeprom->contents[address] = 0xffff; + } + else if (tick >= 2 + 2 + eeprom->addrbits + 16) { + if (command == 1) { + /* Write word. */ + eeprom->contents[address] &= eeprom->data; + } + else if (command == 0 && subcommand == 1) { + /* Write all. */ + for (address = 0; address < eeprom->size; address++) { + eeprom->contents[address] &= eeprom->data; + } + } + } + } + /* Output DO is tristate, read results in 1. */ + eedo = 1; + } + else if (eecs && !eeprom->eesk && eesk) { + /* Raising edge of clock shifts data in. */ + if (tick == 0) { + /* Wait for 1st start bit. */ + if (eedi == 0) { +#if EEPROM_LOG + write_log("Got correct 1st start bit, waiting for 2nd start bit (1)\n"); +#endif + tick++; + } + else { +#if EEPROM_LOG + write_log("wrong 1st start bit (is 1, should be 0)\n"); +#endif + tick = 2; + //~ assert(!"wrong start bit"); + } + } + else if (tick == 1) { + /* Wait for 2nd start bit. */ + if (eedi != 0) { +#if EEPROM_LOG + write_log("Got correct 2nd start bit, getting command + address\n"); +#endif + tick++; + } + else { +#if EEPROM_LOG + + write_log("1st start bit is longer than needed\n"); +#endif + } + } + else if (tick < 2 + 2) { + /* Got 2 start bits, transfer 2 opcode bits. */ + tick++; + command <<= 1; + if (eedi) { + command += 1; + } + } + else if (tick < 2 + 2 + eeprom->addrbits) { + /* Got 2 start bits and 2 opcode bits, transfer all address bits. */ + tick++; + address = ((address << 1) | eedi); + if (tick == 2 + 2 + eeprom->addrbits) { +#if EEPROM_LOG + write_log("%s command, address = 0x%02x (value 0x%04x)\n", opstring[command], address, eeprom->contents[address]); +#endif + if (command == 2) { + eedo = 0; + } + address = address % eeprom->size; + if (command == 0) { + /* Command code in upper 2 bits of address. */ + switch (address >> (eeprom->addrbits - 2)) { + case 0: +#if EEPROM_LOG + write_log("write disable command\n"); +#endif + eeprom->writeable = 0; + break; + case 1: +#if EEPROM_LOG + write_log("write all command\n"); +#endif + break; + case 2: +#if EEPROM_LOG + write_log("erase all command\n"); +#endif + break; + case 3: +#if EEPROM_LOG + write_log("write enable command\n"); +#endif + eeprom->writeable = 1; + break; + } + } + else { + /* Read, write or erase word. */ + eeprom->data = eeprom->contents[address]; + } + } + } + else if (tick < 2 + 2 + eeprom->addrbits + 16) { + /* Transfer 16 data bits. */ + tick++; + if (command == 2) { + /* Read word. */ + eedo = ((eeprom->data & 0x8000) != 0); + } + eeprom->data <<= 1; + eeprom->data += eedi; + } + else { +#if EEPROM_LOG + write_log("additional unneeded tick, not processed\n"); +#endif + } + } + /* Save status of EEPROM. */ + eeprom->tick = tick; + eeprom->eecs = eecs; + eeprom->eesk = eesk; + eeprom->eedo = eedo; + eeprom->address = address; + eeprom->command = command; +} + +uae_u16 eeprom93xx_read(void *eepromp) +{ + eeprom93xx_eeprom_t *eeprom = (eeprom93xx_eeprom_t*)eepromp; + /* Return status of pin DO (0 or 1). */ +#if EEPROM_LOG + write_log("CS=%u DO=%u\n", eeprom->eecs, eeprom->eedo); +#endif + return eeprom->eedo; +} + +uae_u8 eeprom93xx_read_byte(void *eepromp, int offset) +{ + eeprom93xx_eeprom_t *eeprom = (eeprom93xx_eeprom_t*)eepromp; + if (offset & 1) + return eeprom->contents[offset / 2]; + else + return eeprom->contents[offset / 2] >> 8; +} + +void *eeprom93xx_new(const uae_u8 *memory, int nwords, struct zfile *zf) +{ + /* Add a new EEPROM (with 16, 64 or 256 words). */ + eeprom93xx_eeprom_t *eeprom; + uint8_t addrbits; + + switch (nwords) { + case 16: + case 64: + addrbits = 6; + break; + case 128: + case 256: + addrbits = 8; + break; + default: + return NULL; + } + + eeprom = (eeprom93xx_eeprom_t *)xcalloc(eeprom93xx_eeprom_t, 1); + eeprom->size = nwords; + eeprom->addrbits = addrbits; + for (int i = 0; i < nwords; i++) { + eeprom->contents[i] = (memory[i * 2 + 0] << 8) | memory[i * 2 + 1]; + } + /* Output DO is tristate, read results in 1. */ + eeprom->eedo = 1; +// write_log("eeprom = 0x%p, nwords = %u\n", eeprom, nwords); + return eeprom; +} + +void eeprom93xx_free(void *eepromp) +{ + eeprom93xx_eeprom_t *eeprom = (eeprom93xx_eeprom_t*)eepromp; + + /* Destroy EEPROM. */ +// write_log("eeprom = 0x%p\n", eeprom); + xfree(eeprom); +} /* I2C EEPROM */ #define NVRAM_PAGE_SIZE 16 typedef enum bitbang_i2c_state { - STOPPED = 0, - SENDING_BIT7, - SENDING_BIT6, - SENDING_BIT5, - SENDING_BIT4, - SENDING_BIT3, - SENDING_BIT2, - SENDING_BIT1, - SENDING_BIT0, - WAITING_FOR_ACK, - RECEIVING_BIT7, - RECEIVING_BIT6, - RECEIVING_BIT5, - RECEIVING_BIT4, - RECEIVING_BIT3, - RECEIVING_BIT2, - RECEIVING_BIT1, - RECEIVING_BIT0, - SENDING_ACK, - SENT_NACK + STOPPED = 0, + SENDING_BIT7, + SENDING_BIT6, + SENDING_BIT5, + SENDING_BIT4, + SENDING_BIT3, + SENDING_BIT2, + SENDING_BIT1, + SENDING_BIT0, + WAITING_FOR_ACK, + RECEIVING_BIT7, + RECEIVING_BIT6, + RECEIVING_BIT5, + RECEIVING_BIT4, + RECEIVING_BIT3, + RECEIVING_BIT2, + RECEIVING_BIT1, + RECEIVING_BIT0, + SENDING_ACK, + SENT_NACK } bitbang_i2c_state; typedef enum eeprom_state { @@ -49,12 +299,12 @@ typedef enum eeprom_state { } eeprom_state; struct bitbang_i2c_interface { - bitbang_i2c_state state; - int last_data; - int last_clock; - int device_out; - uint8_t buffer; - int current_addr; + bitbang_i2c_state state; + int last_data; + int last_clock; + int device_out; + uint8_t buffer; + int current_addr; uae_u8 device_address, device_address_mask; eeprom_state estate; @@ -82,8 +332,8 @@ static void bitbang_i2c_enter_stop(bitbang_i2c_interface *i2c) if (i2c->write_offset >= 0) nvram_write(i2c, i2c->write_offset, 16); i2c->write_offset = -1; - i2c->current_addr = -1; - i2c->state = STOPPED; + i2c->current_addr = -1; + i2c->state = STOPPED; i2c->estate = I2C_DEVICEADDR; } @@ -97,116 +347,131 @@ static int bitbang_i2c_ret(bitbang_i2c_interface *i2c, int level) /* Leave device data pin unodified. */ static int bitbang_i2c_nop(bitbang_i2c_interface *i2c) { - return bitbang_i2c_ret(i2c, i2c->device_out); + return bitbang_i2c_ret(i2c, i2c->device_out); } /* Returns data line level. */ int eeprom_i2c_set(void *fdv, int line, int level) { struct bitbang_i2c_interface *i2c = (bitbang_i2c_interface*)fdv; - int data; + int data; - if (line == BITBANG_I2C_SDA) { + if (line == BITBANG_I2C_SDA) { if (level < 0) level = i2c->last_data; - if (level == i2c->last_data) { - return bitbang_i2c_nop(i2c); - } - i2c->last_data = level; - if (i2c->last_clock == 0) { - return bitbang_i2c_nop(i2c); - } - if (level == 0) { + if (level == i2c->last_data) { + return bitbang_i2c_nop(i2c); + } + i2c->last_data = level; + if (i2c->last_clock == 0) { + return bitbang_i2c_nop(i2c); + } + if (level == 0) { +#if EEPROM_LOG + write_log(_T("I2C START\n")); +#endif /* START condition. */ - i2c->state = SENDING_BIT7; - i2c->current_addr = -1; + i2c->state = SENDING_BIT7; + i2c->current_addr = -1; + } else { + /* STOP condition. */ + bitbang_i2c_enter_stop(i2c); + } + return bitbang_i2c_ret(i2c, 1); } else { - /* STOP condition. */ - bitbang_i2c_enter_stop(i2c); - } - return bitbang_i2c_ret(i2c, 1); - } else { if (level < 0) level = i2c->last_clock; } - data = i2c->last_data; - if (i2c->last_clock == level) { - return bitbang_i2c_nop(i2c); - } - i2c->last_clock = level; - if (level == 0) { - /* State is set/read at the start of the clock pulse. - release the data line at the end. */ - return bitbang_i2c_ret(i2c, 1); - } - switch (i2c->state) { + data = i2c->last_data; + if (i2c->last_clock == level) { + return bitbang_i2c_nop(i2c); + } + i2c->last_clock = level; + if (level == 0) { + /* State is set/read at the start of the clock pulse. + release the data line at the end. */ + return bitbang_i2c_ret(i2c, 1); + } + switch (i2c->state) { case STOPPED: case SENT_NACK: - return bitbang_i2c_ret(i2c, 1); + return bitbang_i2c_ret(i2c, 1); - // Writing to EEPROM - case SENDING_BIT7: - case SENDING_BIT6: - case SENDING_BIT5: - case SENDING_BIT4: - case SENDING_BIT3: - case SENDING_BIT2: - case SENDING_BIT1: - case SENDING_BIT0: - i2c->buffer = (i2c->buffer << 1) | data; - /* will end up in WAITING_FOR_ACK */ - i2c->state = (bitbang_i2c_state)((int)i2c->state + 1); - return bitbang_i2c_ret(i2c, 1); + // Writing to EEPROM + case SENDING_BIT7: + case SENDING_BIT6: + case SENDING_BIT5: + case SENDING_BIT4: + case SENDING_BIT3: + case SENDING_BIT2: + case SENDING_BIT1: + case SENDING_BIT0: + i2c->buffer = (i2c->buffer << 1) | data; + /* will end up in WAITING_FOR_ACK */ + i2c->state = (bitbang_i2c_state)((int)i2c->state + 1); + return bitbang_i2c_ret(i2c, 1); case WAITING_FOR_ACK: - if (i2c->estate == I2C_DEVICEADDR) { - i2c->current_addr = i2c->buffer; - if ((i2c->current_addr & i2c->device_address_mask) != i2c->device_address) { - write_log (_T("I2C WARNING: device address != %02x\n"), i2c->device_address); - i2c->state = STOPPED; - return bitbang_i2c_ret(i2c, 0); - } - if (i2c->current_addr & 1) { - i2c->estate = I2C_DATA; - } else { - i2c->estate = I2C_WORDADDR; - i2c->eeprom_addr = ((i2c->buffer >> 1) & i2c->addressbitmask) << 8; - } - } else if (i2c->estate == I2C_WORDADDR) { - i2c->estate = I2C_DATA; - i2c->eeprom_addr &= i2c->addressbitmask << 8; - i2c->eeprom_addr |= i2c->buffer; - } else if (!(i2c->current_addr & 1)) { - if (i2c->write_offset < 0) - i2c->write_offset = i2c->eeprom_addr; - if (i2c->write_func) { - i2c->write_func(i2c->eeprom_addr, i2c->buffer); - } else { - i2c->memory[i2c->eeprom_addr] = i2c->buffer; - i2c->eeprom_addr = (i2c->eeprom_addr & ~(NVRAM_PAGE_SIZE - 1)) | (i2c->eeprom_addr + 1) & (NVRAM_PAGE_SIZE - 1); - gui_flicker_led (LED_MD, 0, 2); - } - } - if (i2c->current_addr & 1) { - i2c->state = RECEIVING_BIT7; - } else { - i2c->state = SENDING_BIT7; - } - return bitbang_i2c_ret(i2c, 0); + if (i2c->estate == I2C_DEVICEADDR) { + i2c->current_addr = i2c->buffer; +#if EEPROM_LOG + write_log(_T("I2C device address 0x%02x\n"), i2c->current_addr); +#endif + if ((i2c->current_addr & i2c->device_address_mask) != i2c->device_address) { + write_log (_T("I2C WARNING: device address != %02x\n"), i2c->device_address); + i2c->state = STOPPED; + return bitbang_i2c_ret(i2c, 0); + } + if (i2c->current_addr & 1) { + i2c->estate = I2C_DATA; + } else { + i2c->estate = I2C_WORDADDR; + i2c->eeprom_addr = ((i2c->buffer >> 1) & i2c->addressbitmask) << 8; + } + } else if (i2c->estate == I2C_WORDADDR) { + i2c->estate = I2C_DATA; + i2c->eeprom_addr &= i2c->addressbitmask << 8; + i2c->eeprom_addr |= i2c->buffer; +#if EEPROM_LOG + write_log(_T("I2C device address 0x%02x (Address %04x)\n"), i2c->buffer, i2c->eeprom_addr); +#endif + } else if (!(i2c->current_addr & 1)) { +#if EEPROM_LOG + write_log(_T("I2C sent %04x 0x%02x\n"), i2c->eeprom_addr, i2c->buffer); +#endif + if (i2c->write_offset < 0) + i2c->write_offset = i2c->eeprom_addr; + if (i2c->write_func) { + i2c->write_func(i2c->eeprom_addr, i2c->buffer); + } else { + i2c->memory[i2c->eeprom_addr] = i2c->buffer; + i2c->eeprom_addr = (i2c->eeprom_addr & ~(NVRAM_PAGE_SIZE - 1)) | (i2c->eeprom_addr + 1) & (NVRAM_PAGE_SIZE - 1); + gui_flicker_led(LED_MD, 0, 2); + } + } + if (i2c->current_addr & 1) { + i2c->state = RECEIVING_BIT7; + } else { + i2c->state = SENDING_BIT7; + } + return bitbang_i2c_ret(i2c, 0); - // Reading from EEPROM + // Reading from EEPROM case RECEIVING_BIT7: - if (i2c->read_func) { - i2c->buffer = i2c->read_func(i2c->eeprom_addr); - } else { - i2c->buffer = i2c->memory[i2c->eeprom_addr]; - } - //i2c->buffer = i2c_recv(i2c->bus); - i2c->eeprom_addr++; - i2c->eeprom_addr &= i2c->size - 1; - gui_flicker_led (LED_MD, 0, 1); - /* Fall through... */ + if (i2c->read_func) { + i2c->buffer = i2c->read_func(i2c->eeprom_addr); + } else { + i2c->buffer = i2c->memory[i2c->eeprom_addr]; + } + //i2c->buffer = i2c_recv(i2c->bus); +#if EEPROM_LOG + write_log(_T("I2C RX byte %04X 0x%02x\n"), i2c->eeprom_addr, i2c->buffer); +#endif + i2c->eeprom_addr++; + i2c->eeprom_addr &= i2c->size - 1; + gui_flicker_led (LED_MD, 0, 1); + /* Fall through... */ case RECEIVING_BIT6: case RECEIVING_BIT5: case RECEIVING_BIT4: @@ -214,23 +479,34 @@ int eeprom_i2c_set(void *fdv, int line, int level) case RECEIVING_BIT2: case RECEIVING_BIT1: case RECEIVING_BIT0: - data = i2c->buffer >> 7; - /* will end up in SENDING_ACK */ - i2c->state = (bitbang_i2c_state)((int)i2c->state + 1); - i2c->buffer <<= 1; - return bitbang_i2c_ret(i2c, data); + data = i2c->buffer >> 7; + /* will end up in SENDING_ACK */ + i2c->state = (bitbang_i2c_state)((int)i2c->state + 1); + i2c->buffer <<= 1; + return bitbang_i2c_ret(i2c, data); case SENDING_ACK: - i2c->state = RECEIVING_BIT7; - if (data != 0) { - i2c->state = SENT_NACK; - //i2c_nack(i2c->bus); - } - return bitbang_i2c_ret(i2c, 1); - } - target_startup_msg(_T("Internal error"), _T("eeprom_i2c_set: Unhandled case.")); - uae_restart(1, NULL); - return 0; + i2c->state = RECEIVING_BIT7; + if (data != 0) { +#if EEPROM_LOG > 1 + write_log(_T("I2C NACKED\n")); +#endif + i2c->state = SENT_NACK; + //i2c_nack(i2c->bus); + } else { + ; +#if EEPROM_LOG > 1 + write_log(_T("I2C ACKED\n")); +#endif + } + return bitbang_i2c_ret(i2c, 1); + } + abort(); +} + +int i2c_set(void *i2c, int line, int level) +{ + return eeprom_i2c_set(i2c, line, level); } void eeprom_reset(void *fdv) @@ -248,9 +524,9 @@ void eeprom_reset(void *fdv) void *eeprom_new(uae_u8 *memory, int size, struct zfile *zf) { - bitbang_i2c_interface *s; + bitbang_i2c_interface *s; - s = xcalloc(bitbang_i2c_interface, 1); + s = xcalloc(bitbang_i2c_interface, 1); eeprom_reset(s); @@ -261,7 +537,27 @@ void *eeprom_new(uae_u8 *memory, int size, struct zfile *zf) s->device_address = 0xa0; s->device_address_mask = 0xf0; - return s; + return s; +} + +void *i2c_new(uae_u8 device_address, int size, uae_u8 (*read_func)(uae_u8 addr), void (*write_func)(uae_u8 addr, uae_u8 v)) +{ + bitbang_i2c_interface *s; + + s = xcalloc(bitbang_i2c_interface, 1); + + eeprom_reset(s); + + s->memory = NULL; + s->size = size; + s->zf = NULL; + s->addressbitmask = 0; + s->device_address = 0xa2; + s->device_address_mask = 0xff; + + s->read_func = read_func; + s->write_func = write_func; + return s; } void eeprom_free(void *fdv) @@ -269,3 +565,236 @@ void eeprom_free(void *fdv) struct bitbang_i2c_interface *i2c = (bitbang_i2c_interface*)fdv; xfree(i2c); } + +void i2c_free(void *fdv) +{ + eeprom_free(fdv); +} + +void i2c_reset(void *fdv) +{ + struct bitbang_i2c_interface *i2c = (bitbang_i2c_interface*)fdv; + eeprom_reset(i2c); +} + +/* FLASH */ + +struct flashrom_data +{ + uae_u8 *rom; + int flashsize; + int allocsize; + int mask; + int state; + int modified; + int sectorsize; + uae_u8 devicecode, mfgcode; + int flags; + struct zfile *zf; +}; + +void *flash_new(uae_u8 *rom, int flashsize, int allocsize, uae_u8 mfgcode, uae_u8 devcode, struct zfile *zf, int flags) +{ + struct flashrom_data *fd = xcalloc(struct flashrom_data, 1); + fd->flashsize = flashsize; + fd->allocsize = allocsize; + fd->mask = fd->flashsize - 1; + fd->zf = zf; + fd->rom = rom; + fd->flags = flags; + fd->devicecode = devcode; + fd->mfgcode = mfgcode; + fd->sectorsize = devcode == 0x20 ? 16384 : 65536; + return fd; +} + +void flash_free(void *fdv) +{ + struct flashrom_data *fd = (struct flashrom_data*)fdv; + if (!fd) + return; + if (fd->zf && fd->modified) { + zfile_fseek(fd->zf, 0, SEEK_SET); + if (fd->flags & FLASHROM_EVERY_OTHER_BYTE) { + zfile_fseek(fd->zf, (fd->flags & FLASHROM_EVERY_OTHER_BYTE_ODD) ? 1 : 0, SEEK_SET); + for (int i = 0; i < fd->allocsize; i++) { + zfile_fwrite(&fd->rom[i * 2], 1, 1, fd->zf); + zfile_fseek(fd->zf, 1, SEEK_CUR); + } + } else { + zfile_fwrite(fd->rom, fd->allocsize, 1, fd->zf); + } + } + xfree(fdv); +} + +int flash_size(void *fdv) +{ + struct flashrom_data *fd = (struct flashrom_data*)fdv; + if (!fd) + return 0; + return fd->flashsize; +} + +bool flash_active(void *fdv, uaecptr addr) +{ + struct flashrom_data *fd = (struct flashrom_data*)fdv; + if (!fd) + return false; + return fd->state != 0; +} + +bool flash_write(void *fdv, uaecptr addr, uae_u8 v) +{ + struct flashrom_data *fd = (struct flashrom_data*)fdv; + int oldstate; + uae_u32 addr2; + int other_byte_mult = 1; + + if (!fd) + return false; + + if (fd->flags & FLASHROM_EVERY_OTHER_BYTE) { + addr >>= 1; + other_byte_mult = 2; + } + + oldstate = fd->state; + +#if FLASH_LOG > 1 + write_log(_T("flash write %08x %02x (%d) PC=%08x\n"), addr, v, fd->state, m68k_getpc()); +#endif + + addr &= fd->mask; + addr2 = addr & 0xffff; + + if (fd->state >= 7 && fd->state < 7 + 64) { + if (!(fd->flags & FLASHROM_PARALLEL_EEPROM)) { + fd->state = 100; + } else { + fd->state++; + if (fd->state >= 7 + 64) + fd->state = 100; + } + if (addr >= fd->allocsize) + return false; + if (fd->rom[addr * other_byte_mult] != v) + fd->modified = 1; + fd->rom[addr * other_byte_mult] = v; + gui_flicker_led (LED_MD, 0, 2); + return true; + } + + if (v == 0xf0) { + fd->state = 0; + return false; + } + + // unlock + if (addr2 == 0x5555 && fd->state <= 2 && v == 0xaa) + fd->state = 1; + if (addr2 == 0x2aaa && fd->state == 1 && v == 0x55) + fd->state = 2; + + // autoselect + if (addr2 == 0x5555 && fd->state == 2 && v == 0x90) + fd->state = 3; + + // program + if (addr2 == 0x5555 && fd->state == 2 && v == 0xa0) + fd->state = 7; + + // chip/sector erase + if (addr2 == 0x5555 && fd->state == 2 && v == 0x80) + fd->state = 4; + if (addr2 == 0x5555 && fd->state == 4 && v == 0xaa) + fd->state = 5; + if (addr2 == 0x2aaa && fd->state == 5 && v == 0x55) + fd->state = 6; + if (addr2 == 0x5555 && fd->state == 6 && v == 0x10) { + for (int i = 0; i < fd->allocsize; i++) { + fd->rom[i * other_byte_mult] = 0xff; + } + fd->state = 200; + fd->modified = 1; +#if FLASH_LOG + write_log(_T("flash chip erased\n"), addr); +#endif + gui_flicker_led (LED_MD, 0, 2); + return true; + } else if (fd->state == 6 && v == 0x30) { + int saddr = addr & ~(fd->sectorsize - 1); + if (saddr < fd->allocsize) { + for (int i = 0; i < fd->sectorsize; i++) { + fd->rom[(saddr + i) * other_byte_mult] = 0xff; + } + } + fd->state = 200; + fd->modified = 1; +#if FLASH_LOG + write_log(_T("flash sector %d erased (%08x)\n"), saddr / fd->sectorsize, addr); +#endif + gui_flicker_led (LED_MD, 0, 2); + return true; + } + + if (fd->state == oldstate) + fd->state = 0; + return false; +} + +uae_u32 flash_read(void *fdv, uaecptr addr) +{ + struct flashrom_data *fd = (struct flashrom_data*)fdv; + uae_u8 v = 0xff; + int other_byte_mult = 1; +#if FLASH_LOG > 1 + uaecptr oaddr = addr; +#endif + + if (!fd) + return 0; + + if (fd->flags & FLASHROM_EVERY_OTHER_BYTE) { + addr >>= 1; + other_byte_mult = 2; + } + + addr &= fd->mask; + if (fd->state == 3) { + uae_u8 a = addr & 0xff; + if (a == 0) + v = fd->mfgcode; + if (a == 1) + v = fd->devicecode; + if (a == 2) + v = 0x00; + gui_flicker_led (LED_MD, 0, 1); + } else if (fd->state >= 200) { + v = 0; + if (fd->state & 1) + v ^= 0x40; + fd->state++; + if (fd->state >= 210) + fd->state = 0; + v |= 0x08; + } else if (fd->state > 7) { + v = (fd->rom[addr * other_byte_mult] & 0x80) ^ 0x80; + if (fd->state & 1) + v ^= 0x40; + fd->state++; + if (fd->state >= 110) + fd->state = 0; + } else { + fd->state = 0; + if (addr >= fd->allocsize) + v = 0xff; + else + v = fd->rom[addr * other_byte_mult]; + } +#if FLASH_LOG > 1 + write_log(_T("flash read %08x = %02X (%d) PC=%08x\n"), oaddr, v, fd->state, m68k_getpc()); +#endif + + return v; +} diff --git a/src/gayle.cpp b/src/gayle.cpp index ecc12132..a751816d 100644 --- a/src/gayle.cpp +++ b/src/gayle.cpp @@ -23,6 +23,8 @@ #include "savestate.h" #include "uae.h" #include "threaddep/thread.h" +#include "blkdev.h" +#include "scsi.h" #include "ide.h" #include "autoconf.h" #include "rommgr.h" @@ -147,12 +149,20 @@ static int pcmcia_readonly; static int pcmcia_type; static uae_u8 pcmcia_configuration[20]; static int pcmcia_configured; +static int pcmcia_delayed_insert, pcmcia_delayed_insert_count; +static int external_card_int; static int gayle_id_cnt; static uae_u8 gayle_irq, gayle_int, gayle_cs, gayle_cs_mask, gayle_cfg; static int ide_splitter; -static struct ide_thread_state gayle_its; +static struct ide_thread_state gayle_its, pcmcia_its; + +static bool ne2000_pcmcia_irq; + +static int dataflyer_state; +static int dataflyer_disable_irq; +static uae_u8 dataflyer_byte; static void gayle_reset(int hardreset); static void gayle_map_pcmcia(void); @@ -179,6 +189,10 @@ static uae_u8 checkgayleideirq (void) int i; bool irq = false; + if (dataflyer_disable_irq) { + gayle_irq &= ~GAYLE_IRQ_IDE; + return 0; + } for (i = 0; i < 2; i++) { if (idedrive[i]) { if (!(idedrive[i]->regs.ide_devcon & 2) && (idedrive[i]->irq || (idedrive[i + 2] && idedrive[i + 2]->irq))) @@ -193,6 +207,11 @@ static uae_u8 checkgayleideirq (void) return irq ? GAYLE_IRQ_IDE : 0; } +bool isideint(void) +{ + return checkgayleideirq() != 0; +} + static void rethink_gayle (void) { int lev2 = 0; @@ -480,11 +499,113 @@ addrbank gayle_bank = { ABFLAG_IO, S_READ, S_WRITE }; +void gayle_dataflyer_enable(bool enable) +{ + if (!enable) { + dataflyer_state = 0; + dataflyer_disable_irq = 0; + return; + } + dataflyer_state = 1; +} + +static bool isdataflyerscsiplus(uaecptr addr, uae_u32 *v, int size) +{ + if (!dataflyer_state) + return false; + uaecptr addrmask = addr & 0xffff; + if (addrmask >= GAYLE_IRQ_4000 && addrmask <= GAYLE_IRQ_4000 + 1 && currprefs.cs_ide == IDE_A4000) + return false; + uaecptr addrbase = (addr & ~0xff) & ~0x1020; + int reg = ((addr & 0xffff) & ~0x2020) >> 2; + if (reg >= IDE_SECONDARY) { + reg &= ~IDE_SECONDARY; + if (reg >= 6) // normal IDE registers + return false; + if (size < 0) { + switch (reg) + { + case 0: // 53C80 fake dma port + soft_scsi_put(addrbase | 8, 1, *v); + break; + case 3: + dataflyer_byte = *v; + break; + } + } else { + switch (reg) + { + case 0: // 53C80 fake dma port + *v = soft_scsi_get(addrbase | 8, 1); + break; + case 3: + *v = 0; + if (ide_irq_check(idedrive[0], false)) + *v = dataflyer_byte; + break; + case 4: // select SCSI + dataflyer_disable_irq = 1; + dataflyer_state |= 2; + break; + case 5: // select IDE + dataflyer_disable_irq = 1; + dataflyer_state &= ~2; + break; + } + } +#if 0 + if (size < 0) + write_log(_T("SECONDARY BASE PUT(%d) %08x %08x PC=%08x\n"), -size, addr, *v, M68K_GETPC); + else + write_log(_T("SECONDARY BASE GET(%d) %08x PC=%08x\n"), size, addr, M68K_GETPC); +#endif + return true; + } + if (!(dataflyer_state & 2)) + return false; + if (size < 0) + soft_scsi_put(addrbase | reg, -size, *v); + else + *v = soft_scsi_get(addrbase | reg, size); + return true; +} + +//static bool isa4000t (uaecptr *paddr) +//{ +// if (!is_a4000t_scsi()) +// return false; +// uaecptr addr = *paddr; +// if ((addr & 0xffff) >= (GAYLE_BASE_4000 & 0xffff)) +// return false; +// addr &= 0xff; +// *paddr = addr; +// return true; +//} + static uae_u32 REGPARAM2 gayle_lget (uaecptr addr) { struct ide_hdf *ide = NULL; int ide_reg; uae_u32 v; +#ifdef NCR + if (is_a4000t_scsi() && (addr & 0xffff) == 0x3000) + return 0xffffffff; // NCR DIP BANK + if (isdataflyerscsiplus(addr, &v, 4)) { + return v; + } + if (isa4000t (&addr)) { + if (addr >= NCR_ALT_OFFSET) { + addr &= NCR_MASK; + v = (ncr710_io_bget_a4000t(addr + 3) << 0) | (ncr710_io_bget_a4000t(addr + 2) << 8) | + (ncr710_io_bget_a4000t(addr + 1) << 16) | (ncr710_io_bget_a4000t(addr + 0) << 24); + } else if (addr >= NCR_OFFSET) { + addr &= NCR_MASK; + v = (ncr710_io_bget_a4000t(addr + 3) << 0) | (ncr710_io_bget_a4000t(addr + 2) << 8) | + (ncr710_io_bget_a4000t(addr + 1) << 16) | (ncr710_io_bget_a4000t(addr + 0) << 24); + } + return v; + } +#endif ide_reg = get_gayle_ide_reg (addr, &ide); if (ide_reg == IDE_DATA) { v = ide_get_data (ide) << 16; @@ -500,6 +621,20 @@ static uae_u32 REGPARAM2 gayle_wget (uaecptr addr) struct ide_hdf *ide = NULL; int ide_reg; uae_u32 v; +#ifdef NCR + if (is_a4000t_scsi() && (addr & (0xffff - 1)) == 0x3000) + return 0xffff; // NCR DIP BANK + if (isdataflyerscsiplus(addr, &v, 2)) { + return v; + } + if (isa4000t(&addr)) { + if (addr >= NCR_OFFSET) { + addr &= NCR_MASK; + v = (ncr710_io_bget_a4000t(addr) << 8) | ncr710_io_bget_a4000t(addr + 1); + } + return v; + } +#endif ide_reg = get_gayle_ide_reg (addr, &ide); if (ide_reg == IDE_DATA) { v = ide_get_data (ide); @@ -512,6 +647,20 @@ static uae_u32 REGPARAM2 gayle_wget (uaecptr addr) static uae_u32 REGPARAM2 gayle_bget (uaecptr addr) { uae_u32 v; +#ifdef NCR + if (is_a4000t_scsi() && (addr & (0xffff - 3)) == 0x3000) + return 0xff; // NCR DIP BANK + if (isdataflyerscsiplus(addr, &v, 1)) { + return v; + } + if (isa4000t(&addr)) { + if (addr >= NCR_OFFSET) { + addr &= NCR_MASK; + return ncr710_io_bget_a4000t(addr); + } + return 0; + } +#endif v = gayle_read (addr); return v; } @@ -520,6 +669,25 @@ static void REGPARAM2 gayle_lput (uaecptr addr, uae_u32 value) { struct ide_hdf *ide = NULL; int ide_reg; + if (isdataflyerscsiplus(addr, &value, -4)) { + return; + } + //if (isa4000t(&addr)) { + // if (addr >= NCR_ALT_OFFSET) { + // addr &= NCR_MASK; + // ncr710_io_bput_a4000t(addr + 3, value >> 0); + // ncr710_io_bput_a4000t(addr + 2, value >> 8); + // ncr710_io_bput_a4000t(addr + 1, value >> 16); + // ncr710_io_bput_a4000t(addr + 0, value >> 24); + // } else if (addr >= NCR_OFFSET) { + // addr &= NCR_MASK; + // ncr710_io_bput_a4000t(addr + 3, value >> 0); + // ncr710_io_bput_a4000t(addr + 2, value >> 8); + // ncr710_io_bput_a4000t(addr + 1, value >> 16); + // ncr710_io_bput_a4000t(addr + 0, value >> 24); + // } + // return; + //} ide_reg = get_gayle_ide_reg (addr, &ide); if (ide_reg == IDE_DATA) { ide_put_data (ide, value >> 16); @@ -533,6 +701,19 @@ static void REGPARAM2 gayle_wput (uaecptr addr, uae_u32 value) { struct ide_hdf *ide = NULL; int ide_reg; +#ifdef NCR + if (isdataflyerscsiplus(addr, &value, -2)) { + return; + } + if (isa4000t(&addr)) { + if (addr >= NCR_OFFSET) { + addr &= NCR_MASK; + ncr710_io_bput_a4000t(addr, value >> 8); + ncr710_io_bput_a4000t(addr + 1, value); + } + return; + } +#endif ide_reg = get_gayle_ide_reg (addr, &ide); if (ide_reg == IDE_DATA) { ide_put_data (ide, value); @@ -544,6 +725,18 @@ static void REGPARAM2 gayle_wput (uaecptr addr, uae_u32 value) static void REGPARAM2 gayle_bput (uaecptr addr, uae_u32 value) { +#ifdef NCR + if (isdataflyerscsiplus(addr, &value, -1)) { + return; + } + if (isa4000t(&addr)) { + if (addr >= NCR_OFFSET) { + addr &= NCR_MASK; + ncr710_io_bput_a4000t(addr, value); + } + return; + } +#endif gayle_write (addr, value); } diff --git a/src/ide.cpp b/src/ide.cpp index 3ca7dffd..8cb4ac13 100644 --- a/src/ide.cpp +++ b/src/ide.cpp @@ -252,6 +252,36 @@ static bool ide_interrupt_do (struct ide_hdf *ide) return true; } +bool ide_drq_check(struct ide_hdf* idep) +{ + for (int i = 0; idep && i < 2; i++) { + struct ide_hdf* ide = i == 0 ? idep : idep->pair; + if (ide) { + if (ide->regs.ide_status & IDE_STATUS_DRQ) + return true; + } + } + return false; +} + +bool ide_irq_check(struct ide_hdf* idep, bool edge_triggered) +{ + for (int i = 0; idep && i < 2; i++) { + struct ide_hdf* ide = i == 0 ? idep : idep->pair; + if (ide->irq) { + if (edge_triggered) { + if (ide->irq_new) { + ide->irq_new = false; + return true; + } + continue; + } + return true; + } + } + return false; +} + bool ide_interrupt_hsync(struct ide_hdf *idep) { bool irq = false; diff --git a/src/scsi.cpp b/src/scsi.cpp index 8e8413b3..57b06705 100644 --- a/src/scsi.cpp +++ b/src/scsi.cpp @@ -562,23 +562,23 @@ struct scsi_data *scsi_alloc_cd(int id, int unitnum, bool atapi, int uae_unitnum return sd; } -struct scsi_data *scsi_alloc_tape(int id, const TCHAR *tape_directory, bool readonly, int uae_unitnum) -{ - struct scsi_data_tape *tape; - tape = tape_alloc (id, tape_directory, readonly); - if (!tape) - return NULL; - struct scsi_data *sd = xcalloc (struct scsi_data, 1); - sd->id = id; - sd->nativescsiunit = -1; - sd->cd_emu_unit = -1; - sd->blocksize = tape->blocksize; - sd->tape = tape; - sd->device_type = UAEDEV_TAPE; - sd->uae_unitnum = uae_unitnum; - allocscsibuf(sd); - return sd; -} +//struct scsi_data *scsi_alloc_tape(int id, const TCHAR *tape_directory, bool readonly, int uae_unitnum) +//{ +// struct scsi_data_tape *tape; +// tape = tape_alloc (id, tape_directory, readonly); +// if (!tape) +// return NULL; +// struct scsi_data *sd = xcalloc (struct scsi_data, 1); +// sd->id = id; +// sd->nativescsiunit = -1; +// sd->cd_emu_unit = -1; +// sd->blocksize = tape->blocksize; +// sd->tape = tape; +// sd->device_type = UAEDEV_TAPE; +// sd->uae_unitnum = uae_unitnum; +// allocscsibuf(sd); +// return sd; +//} struct scsi_data *scsi_alloc_native(int id, int nativeunit) { @@ -708,8 +708,8 @@ int add_scsi_device(struct scsi_data **sd, int ch, struct uaedev_config_info *ci { if (ci->type == UAEDEV_CD) return add_scsi_cd(sd, ch, ci->device_emu_unit); - else if (ci->type == UAEDEV_TAPE) - return add_scsi_tape(sd, ch, ci->rootdir, ci->readonly); + //else if (ci->type == UAEDEV_TAPE) + // return add_scsi_tape(sd, ch, ci->rootdir, ci->readonly); else if (ci->type == UAEDEV_HDF) return add_scsi_hd(sd, ch, NULL, ci); return 0; @@ -1415,23 +1415,23 @@ uae_u8 apollo_scsi_bget(uaecptr addr, uae_u32 config) return v; } -void apollo_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc); +//void apollo_add_ide_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc); -void apollo_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) -{ - if (ch < 0) { - generic_soft_scsi_add(-1, ci, rc, NONCR_APOLLO, -1, -1, ROMTYPE_APOLLO); - // make sure IDE side is also initialized - struct uaedev_config_info ci2 = { 0 }; - apollo_add_ide_unit(-1, &ci2, rc); - } else { - if (ci->controller_type < HD_CONTROLLER_TYPE_SCSI_FIRST) { - apollo_add_ide_unit(ch, ci, rc); - } else { - generic_soft_scsi_add(ch, ci, rc, NONCR_APOLLO, -1, -1, ROMTYPE_APOLLO); - } - } -} +//void apollo_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) +//{ +// if (ch < 0) { +// generic_soft_scsi_add(-1, ci, rc, NONCR_APOLLO, -1, -1, ROMTYPE_APOLLO); +// // make sure IDE side is also initialized +// struct uaedev_config_info ci2 = { 0 }; +// apollo_add_ide_unit(-1, &ci2, rc); +// } else { +// if (ci->controller_type < HD_CONTROLLER_TYPE_SCSI_FIRST) { +// apollo_add_ide_unit(ch, ci, rc); +// } else { +// generic_soft_scsi_add(ch, ci, rc, NONCR_APOLLO, -1, -1, ROMTYPE_APOLLO); +// } +// } +//} uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg); void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v);