diff --git a/src/sio/sio_fdc37m60x.c b/src/sio/sio_fdc37m60x.c index ca0111405..b98801ff2 100644 --- a/src/sio/sio_fdc37m60x.c +++ b/src/sio/sio_fdc37m60x.c @@ -31,24 +31,27 @@ #include <86box/fdc.h> #include <86box/sio.h> -#define SIO_INDEX_PORT dev->sio_index_port -#define INDEX dev->index +#define SIO_INDEX_PORT dev->sio_index_port +#define INDEX dev->index /* Current Logical Device Number */ -#define CURRENT_LOGICAL_DEVICE dev->regs[0x07] +#define CURRENT_LOGICAL_DEVICE dev->regs[0x07] /* Global Device Configuration */ -#define ENABLED dev->device_regs[CURRENT_LOGICAL_DEVICE][0x30] -#define BASE_ADDRESS ((dev->device_regs[CURRENT_LOGICAL_DEVICE][0x60] << 8) | (dev->device_regs[CURRENT_LOGICAL_DEVICE][0x61])) -#define IRQ dev->device_regs[CURRENT_LOGICAL_DEVICE][0x70] -#define DMA dev->device_regs[CURRENT_LOGICAL_DEVICE][0x74] +#define ENABLED(ld) dev->device_regs[ld][0x30] +#define BASE_ADDRESS(ld) ((dev->device_regs[ld][0x60] << 8) | \ + (dev->device_regs[ld][0x61])) +#define IRQ(ld) dev->device_regs[ld][0x70] +#define DMA(ld) dev->device_regs[ld][0x74] /* Miscellaneous Chip Functionality */ -#define SOFT_RESET (val & 0x01) -#define POWER_CONTROL dev->regs[0x22] +#define SOFT_RESET (val & 0x01) +#define POWER_CONTROL dev->regs[0x22] + #ifdef ENABLE_FDC37M60X_LOG int fdc37m60x_do_log = ENABLE_FDC37M60X_LOG; + static void fdc37m60x_log(const char *fmt, ...) { @@ -65,196 +68,217 @@ fdc37m60x_log(const char *fmt, ...) #define fdc37m60x_log(fmt, ...) #endif + typedef struct { - uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function; - uint16_t sio_index_port; + uint8_t index, regs[256], device_regs[10][256], cfg_lock, ide_function; + uint16_t sio_index_port; - fdc_t *fdc_controller; - serial_t *uart[2]; + fdc_t * fdc; + serial_t * uart[2]; } fdc37m60x_t; -void fdc37m60x_fdc_handler(fdc37m60x_t *dev); -void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev); -void fdc37m60x_lpt_handler(fdc37m60x_t *dev); -void fdc37m60x_logical_device_handler(fdc37m60x_t *dev); -static void fdc37m60x_reset(void *priv); + +static void fdc37m60x_fdc_handler(fdc37m60x_t *dev); +static void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev); +static void fdc37m60x_lpt_handler(fdc37m60x_t *dev); +static void fdc37m60x_logical_device_handler(fdc37m60x_t *dev); +static void fdc37m60x_reset(void *priv); + static void fdc37m60x_write(uint16_t addr, uint8_t val, void *priv) { fdc37m60x_t *dev = (fdc37m60x_t *)priv; - switch (addr) - { - case 0x3f0: - case 0x370: - INDEX = val; + if (addr & 1) { + if (!dev->cfg_lock) { + switch (INDEX) { + /* Global Configuration */ + case 0x02: + dev->regs[INDEX] = val; + if (SOFT_RESET) + fdc37m60x_reset(dev); + break; - /* Enter/Escape Configuration Mode */ - if (val == 0x55) - dev->cfg_lock = 0; - else if (val == 0xaa) - dev->cfg_lock = 1; - break; + case 0x07: + CURRENT_LOGICAL_DEVICE = val; + break; - case 0x3f1: - case 0x371: - if (!dev->cfg_lock) - { - switch (INDEX) - { - /* Global Configuration */ - case 0x02: - dev->regs[INDEX] = val; - if (SOFT_RESET) - fdc37m60x_reset(dev); - break; + case 0x22: + POWER_CONTROL = val & 0x3f; + break; - case 0x07: - CURRENT_LOGICAL_DEVICE = (val & 0x0f); - break; + case 0x23: + dev->regs[INDEX] = val & 0x3f; + break; - case 0x22: - POWER_CONTROL = val & 0x3f; - break; + case 0x24: + dev->regs[INDEX] = val & 0x4e; + break; - case 0x23: - dev->regs[INDEX] = val & 0x3f; - break; + case 0x2b: case 0x2c: case 0x2d: case 0x2e: + case 0x2f: + dev->regs[INDEX] = val; + break; - case 0x24: - dev->regs[INDEX] = val & 0xce; - break; - - /* Device Configuration */ - case 0x30: - case 0x60: - case 0x61: - case 0x70: - case 0x74: - if(CURRENT_LOGICAL_DEVICE <= 0x81) /* Avoid Overflow */ - dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] = (INDEX == 0x30) ? (val & 1) : val; - fdc37m60x_logical_device_handler(dev); - break; - } + /* Device Configuration */ + case 0x30: + case 0x60: case 0x61: + case 0x70: + case 0x74: + case 0xf0: case 0xf1: case 0xf2: case 0xf3: + case 0xf4: case 0xf5: case 0xf6: case 0xf7: + if (CURRENT_LOGICAL_DEVICE <= 0x81) /* Avoid Overflow */ + dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] = (INDEX == 0x30) ? (val & 1) : val; + fdc37m60x_logical_device_handler(dev); + break; + } } - break; + } else { + /* Enter/Escape Configuration Mode */ + if (val == 0x55) + dev->cfg_lock = 0; + else if (!dev->cfg_lock && (val == 0xaa)) + dev->cfg_lock = 1; + else if (!dev->cfg_lock) + INDEX = val; } } + static uint8_t fdc37m60x_read(uint16_t addr, void *priv) { fdc37m60x_t *dev = (fdc37m60x_t *)priv; + uint8_t ret = 0xff; - return (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX]; + if (addr & 1) + ret = (INDEX >= 0x30) ? dev->device_regs[CURRENT_LOGICAL_DEVICE][INDEX] : dev->regs[INDEX]; + + return ret; } -void fdc37m60x_fdc_handler(fdc37m60x_t *dev) + +static void +fdc37m60x_fdc_handler(fdc37m60x_t *dev) { - fdc_remove(dev->fdc_controller); - if(ENABLED || (POWER_CONTROL & 0x01)) + fdc_remove(dev->fdc); + + if (ENABLED(0) || (POWER_CONTROL & 0x01)) { - fdc_set_base(dev->fdc_controller, BASE_ADDRESS); - fdc_set_irq(dev->fdc_controller, IRQ & 0xf); - fdc_set_dma_ch(dev->fdc_controller, DMA & 0x07); - fdc37m60x_log("SMC60x-FDC: BASE %04x IRQ %d DMA %d\n", BASE_ADDRESS, IRQ & 0xf, DMA & 0x07); + fdc_set_base(dev->fdc, BASE_ADDRESS(0)); + fdc_set_irq(dev->fdc, IRQ(0) & 0xf); + fdc_set_dma_ch(dev->fdc, DMA(0) & 0x07); + fdc37m60x_log("SMC60x-FDC: BASE %04x IRQ %d DMA %d\n", BASE_ADDRESS(0), IRQ(0) & 0xf, DMA(0) & 0x07); } + + fdc_update_enh_mode(dev->fdc, dev->device_regs[0][0xf0] & 0x01); + + fdc_update_densel_force(dev->fdc, (dev->device_regs[0][0xf1] & 0xc) >> 2); + + fdc_update_rwc(dev->fdc, 3, (dev->device_regs[0][0xf2] & 0xc0) >> 6); + fdc_update_rwc(dev->fdc, 2, (dev->device_regs[0][0xf2] & 0x30) >> 4); + fdc_update_rwc(dev->fdc, 1, (dev->device_regs[0][0xf2] & 0x0c) >> 2); + fdc_update_rwc(dev->fdc, 0, (dev->device_regs[0][0xf2] & 0x03)); + + fdc_update_drvrate(dev->fdc, 0, (dev->device_regs[0][0xf4] & 0x18) >> 3); + fdc_update_drvrate(dev->fdc, 1, (dev->device_regs[0][0xf5] & 0x18) >> 3); + fdc_update_drvrate(dev->fdc, 2, (dev->device_regs[0][0xf6] & 0x18) >> 3); + fdc_update_drvrate(dev->fdc, 3, (dev->device_regs[0][0xf7] & 0x18) >> 3); } -void fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev) + +static void +fdc37m60x_uart_handler(uint8_t num, fdc37m60x_t *dev) { serial_remove(dev->uart[num & 1]); - if(!(num & 1) ? (ENABLED || (POWER_CONTROL & 0x10)) : (ENABLED || (POWER_CONTROL & 0x20))) + + if (ENABLED(4 + (num & 1)) || (POWER_CONTROL & (1 << (4 + (num & 1))))) { - serial_setup(dev->uart[num & 1], BASE_ADDRESS, IRQ & 0xf); - fdc37m60x_log("SMC60x-UART%d: BASE %04x IRQ %d\n", num & 1, BASE_ADDRESS, IRQ & 0xf); + serial_setup(dev->uart[num & 1], BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf); + fdc37m60x_log("SMC60x-UART%d: BASE %04x IRQ %d\n", num & 1, BASE_ADDRESS(4 + (num & 1)), IRQ(4 + (num & 1)) & 0xf); } } + void fdc37m60x_lpt_handler(fdc37m60x_t *dev) { lpt1_remove(); - if(ENABLED || (POWER_CONTROL & 0x80)) - { - lpt1_init(BASE_ADDRESS); - lpt1_irq(IRQ & 0xf); - fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS, IRQ & 0xf); + + if (ENABLED(3) || (POWER_CONTROL & 0x08)) { + lpt1_init(BASE_ADDRESS(3)); + lpt1_irq(IRQ(3) & 0xf); + fdc37m60x_log("SMC60x-LPT: BASE %04x IRQ %d\n", BASE_ADDRESS(3), IRQ(3) & 0xf); } } + void fdc37m60x_logical_device_handler(fdc37m60x_t *dev) { -/* -Register 07h: -Device 0: FDC -Device 3: LPT -Device 4: UART1 -Device 5: UART2 -*/ - switch (CURRENT_LOGICAL_DEVICE) - { - case 0x00: - fdc37m60x_fdc_handler(dev); - break; + /* Register 07h: + Device 0: FDC + Device 3: LPT + Device 4: UART1 + Device 5: UART2 + */ - case 0x03: - fdc37m60x_lpt_handler(dev); - break; + switch (CURRENT_LOGICAL_DEVICE) { + case 0x00: + fdc37m60x_fdc_handler(dev); + break; - case 0x04: - fdc37m60x_uart_handler(0, dev); - break; + case 0x03: + fdc37m60x_lpt_handler(dev); + break; - case 0x05: - fdc37m60x_uart_handler(1, dev); - break; + case 0x04: + fdc37m60x_uart_handler(0, dev); + break; + + case 0x05: + fdc37m60x_uart_handler(1, dev); + break; } } + static void fdc37m60x_reset(void *priv) { - fdc37m60x_t *dev = (fdc37m60x_t *)priv; + fdc37m60x_t *dev = (fdc37m60x_t *) priv; + uint8_t i; - CURRENT_LOGICAL_DEVICE = 0x00; - dev->regs[0x22] = 0x00; + memset(dev->regs, 0, sizeof(dev->regs)); + for (i = 0; i < 10; i++) + memset(dev->device_regs[i], 0, sizeof(dev->device_regs[i])); + + dev->regs[0x20] = 0x47; + dev->regs[0x24] = 0x04; dev->regs[0x26] = SIO_INDEX_PORT & 0xf; dev->regs[0x27] = (SIO_INDEX_PORT >> 4) & 0xf; /* FDC Registers */ - dev->device_regs[0][0x30] = 0x00; dev->device_regs[0][0x60] = 0x03; /* Base Address */ dev->device_regs[0][0x61] = 0xf0; - dev->device_regs[0][0x70] = 0x06; dev->device_regs[0][0x74] = 0x02; + dev->device_regs[0][0xf0] = 0x0e; + dev->device_regs[0][0xf2] = 0xff; /* LPT Port */ - dev->device_regs[3][0x30] = 0x00; - dev->device_regs[3][0x60] = 0x00; /* Base Address */ - dev->device_regs[3][0x61] = 0x00; - - dev->device_regs[3][0x64] = 0x04; + dev->device_regs[3][0x74] = 0x04; + dev->device_regs[3][0xf0] = 0x3c; /* UART1 */ - dev->device_regs[4][0x30] = 0x00; - dev->device_regs[4][0x60] = 0x00; /* Base Address */ - dev->device_regs[4][0x61] = 0x00; - - dev->device_regs[4][0x70] = 0x00; - - /* UART2 */ - dev->device_regs[5][0x30] = 0x00; - dev->device_regs[5][0x60] = 0x00; /* Base Address */ - dev->device_regs[5][0x61] = 0x00; - - dev->device_regs[5][0x70] = 0x00; + dev->device_regs[4][0x74] = 0x04; + dev->device_regs[4][0xf1] = 0x02; + dev->device_regs[4][0xf2] = 0x03; /* AUX */ - dev->device_regs[8][0x30] = 0x00; + dev->device_regs[8][0xc0] = 0x06; + dev->device_regs[8][0xc1] = 0x03; fdc37m60x_fdc_handler(dev); fdc37m60x_uart_handler(0, dev); @@ -262,6 +286,7 @@ fdc37m60x_reset(void *priv) fdc37m60x_lpt_handler(dev); } + static void fdc37m60x_close(void *priv) { @@ -270,6 +295,7 @@ fdc37m60x_close(void *priv) free(dev); } + static void * fdc37m60x_init(const device_t *info) { @@ -277,25 +303,18 @@ fdc37m60x_init(const device_t *info) memset(dev, 0, sizeof(fdc37m60x_t)); SIO_INDEX_PORT = info->local; - dev->regs[0x20] = 0x47; - dev->regs[0x24] = 0x04; - dev->device_regs[0][0xf0] = 0x0e; - dev->device_regs[0][0xf2] = 0xff; - dev->device_regs[3][0xf0] = 0x3c; - dev->device_regs[4][0xf1] = 0x02; - dev->device_regs[4][0xf2] = 0x03; - dev->device_regs[8][0xc0] = 0x06; - dev->device_regs[8][0xc1] = 0x03; - - dev->fdc_controller = device_add(&fdc_at_smc_device); + dev->fdc = device_add(&fdc_at_smc_device); dev->uart[0] = device_add_inst(&ns16550_device, 1); dev->uart[1] = device_add_inst(&ns16550_device, 2); io_sethandler(SIO_INDEX_PORT, 0x0002, fdc37m60x_read, NULL, NULL, fdc37m60x_write, NULL, NULL, dev); + fdc37m60x_reset(dev); + return dev; } + const device_t fdc37m60x_device = { "SMSC FDC37M60X", 0, @@ -303,10 +322,11 @@ const device_t fdc37m60x_device = { fdc37m60x_init, fdc37m60x_close, NULL, - {NULL}, + { NULL }, NULL, NULL, - NULL}; + NULL +}; const device_t fdc37m60x_370_device = { "SMSC FDC37M60X with 10K Pull Up Resistor", @@ -315,7 +335,8 @@ const device_t fdc37m60x_370_device = { fdc37m60x_init, fdc37m60x_close, NULL, - {NULL}, + { NULL }, NULL, NULL, - NULL}; + NULL +};