diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt index 29fc0b9b4..999b83aeb 100644 --- a/src/device/CMakeLists.txt +++ b/src/device/CMakeLists.txt @@ -41,7 +41,7 @@ add_library(dev OBJECT keyboard.c keyboard_at.c keyboard_xt.c - ../lpt.c + lpt.c mouse.c mouse_bus.c mouse_microtouch_touchscreen.c diff --git a/src/device/hasp.c b/src/device/hasp.c index 3834af4cd..53228c2a0 100644 --- a/src/device/hasp.c +++ b/src/device/hasp.c @@ -27,6 +27,7 @@ #include #define HAVE_STDARG_H #include <86box/86box.h> +#include <86box/timer.h> #include <86box/lpt.h> #include <86box/device.h> @@ -334,13 +335,16 @@ hasp_close(void *priv) } const lpt_device_t lpt_hasp_savquest_device = { - .name = "Protection Dongle for Savage Quest", - .internal_name = "dongle_savquest", - .init = hasp_init_savquest, - .close = hasp_close, - .write_data = hasp_write_data, - .write_ctrl = NULL, - .read_data = NULL, - .read_status = hasp_read_status, - .read_ctrl = NULL + .name = "Protection Dongle for Savage Quest", + .internal_name = "dongle_savquest", + .init = hasp_init_savquest, + .close = hasp_close, + .write_data = hasp_write_data, + .write_ctrl = NULL, + .autofeed = NULL, + .strobe = NULL, + .read_status = hasp_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; diff --git a/src/device/lpt.c b/src/device/lpt.c new file mode 100644 index 000000000..179dc9a2d --- /dev/null +++ b/src/device/lpt.c @@ -0,0 +1,837 @@ +/* Copyright holders: Sarah Walker + see COPYING for more details +*/ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/fifo.h> +#include <86box/timer.h> +#include <86box/dma.h> +#include <86box/lpt.h> +#include <86box/pic.h> +#include <86box/sound.h> +#include <86box/prt_devs.h> +#include <86box/thread.h> +#include <86box/device.h> +#include <86box/machine.h> +#include <86box/network.h> + +lpt_port_t lpt_ports[PARALLEL_MAX]; + +const lpt_device_t lpt_none_device = { + .name = "None", + .internal_name = "none", + .init = NULL, + .close = NULL, + .write_data = NULL, + .write_ctrl = NULL, + .read_status = NULL, + .read_ctrl = NULL +}; + +static const struct { + const char *internal_name; + const lpt_device_t *device; +} lpt_devices[] = { + // clang-format off + {"none", &lpt_none_device }, + {"dss", &dss_device }, + {"lpt_dac", &lpt_dac_device }, + {"lpt_dac_stereo", &lpt_dac_stereo_device }, + {"text_prt", &lpt_prt_text_device }, + {"dot_matrix", &lpt_prt_escp_device }, + {"postscript", &lpt_prt_ps_device }, + {"pcl", &lpt_prt_pcl_device }, + {"plip", &lpt_plip_device }, + {"dongle_savquest", &lpt_hasp_savquest_device }, + {"", NULL } + // clang-format on +}; + +#ifdef ENABLE_LPT_LOG +int lpt_do_log = ENABLE_LPT_LOG; + +static void +lpt_log(const char *fmt, ...) +{ + va_list ap; + + if (lpt_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define lpt_log(fmt, ...) +#endif + +const char * +lpt_device_get_name(const int id) +{ + if (strlen(lpt_devices[id].internal_name) == 0) + return NULL; + if (lpt_devices[id].device == NULL) + return "None"; + return lpt_devices[id].device->name; +} + +const char * +lpt_device_get_internal_name(const int id) +{ + if (strlen(lpt_devices[id].internal_name) == 0) + return NULL; + return lpt_devices[id].internal_name; +} + +int +lpt_device_get_from_internal_name(const char *s) +{ + int c = 0; + + while (strlen(lpt_devices[c].internal_name) != 0) { + if (strcmp(lpt_devices[c].internal_name, s) == 0) + return c; + c++; + } + + return 0; +} + +void +lpt_devices_init(void) +{ + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + lpt_ports[i].dt = (lpt_device_t *) lpt_devices[lpt_ports[i].device].device; + + if (lpt_ports[i].dt && lpt_ports[i].dt->init) + lpt_ports[i].priv = lpt_ports[i].dt->init(&lpt_ports[i]); + } +} + +void +lpt_devices_close(void) +{ + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + lpt_port_t *dev = &lpt_ports[i]; + + if (lpt_ports[i].dt && lpt_ports[i].dt->close) + dev->dt->close(dev->priv); + + dev->dt = NULL; + } +} + +static uint8_t +lpt_get_ctrl_raw(const lpt_port_t *dev) +{ + uint8_t ret; + + if (dev->dt && dev->dt->read_ctrl && dev->priv) + ret = (dev->dt->read_ctrl(dev->priv) & 0xef) | dev->enable_irq; + else + ret = 0xc0 | dev->ctrl | dev->enable_irq; + + return ret & 0xdf; +} + +static uint8_t +lpt_is_epp(const lpt_port_t *dev) +{ + return (dev->epp || ((dev->ecp) && ((dev->ecr & 0xe0) == 0x80))); +} + +static uint8_t +lpt_get_ctrl(const lpt_port_t *dev) +{ + uint8_t ret = lpt_get_ctrl_raw(dev); + + if (!dev->ecp && !dev->epp) + ret |= 0x20; + + return ret; +} + +static void +lpt_write_fifo(lpt_port_t *dev, const uint8_t val, const uint8_t tag) +{ + if (!fifo_get_full(dev->fifo)) { + fifo_write_evt_tagged(tag, val, dev->fifo); + + if (!timer_is_enabled(&dev->fifo_out_timer)) + timer_set_delay_u64(&dev->fifo_out_timer, (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + } +} + +static void +lpt_ecp_update_irq(lpt_port_t *dev) +{ + if (!(dev->ecr & 0x04) && ((dev->fifo_stat | dev->dma_stat) & 0x04)) + picintlevel(1 << dev->irq, &dev->irq_state); + else + picintclevel(1 << dev->irq, &dev->irq_state); +} + +static void +lpt_autofeed(lpt_port_t *dev, const uint8_t val) +{ + if (dev->dt && dev->dt->autofeed && dev->priv) + dev->dt->autofeed(val, dev->priv); + + dev->autofeed = val; +} + +static void +lpt_strobe(lpt_port_t *dev, const uint8_t val) +{ + if (dev->dt && dev->dt->strobe && dev->priv) + dev->dt->strobe(dev->strobe, val, dev->priv); + + dev->strobe = val; +} + +static void +lpt_fifo_out_callback(void *priv) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + + switch (dev->state) { + default: + break; + + case LPT_STATE_READ_DMA: + ; + int ret = 0xff; + + if (dev->dma == 0xff) + ret = DMA_NODATA; + else + ret = dma_channel_read(dev->dma); + + lpt_log("DMA %02X: %08X\n", dev->dma, ret); + + if (ret != DMA_NODATA) { + fifo_write_evt_tagged(0x01, (uint8_t) (ret & 0xff), dev->fifo); + + if (ret & DMA_OVER) + /* Internal flag to indicate we have finished the DMA reads. */ + dev->dma_stat = 0x08; + } + + timer_advance_u64(&dev->fifo_out_timer, + (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + + if (dev->dma_stat || fifo_get_full(dev->fifo)) + dev->state = LPT_STATE_WRITE_FIFO; + break; + + case LPT_STATE_WRITE_FIFO: + if (!fifo_get_empty(dev->fifo)) { + uint8_t tag = 0x00; + const uint8_t val = fifo_read_evt_tagged(&tag, dev->fifo); + + lpt_log("FIFO: %02X, TAG = %02X\n", val, tag); + + /* We do not currently support sending commands. */ + if (tag == 0x01) { + if (dev->dt && dev->dt->write_data && dev->priv) + dev->dt->write_data(val, dev->priv); + + lpt_strobe(dev, 1); + lpt_strobe(dev, 0); + } + } + + if (dev->ecr & 0x08) { + if (fifo_get_empty(dev->fifo)) { + if (dev->dma_stat) { + /* Now actually set the external flag. */ + dev->dma_stat = 0x04; + dev->state = LPT_STATE_IDLE; + lpt_ecp_update_irq(dev); + lpt_autofeed(dev, 0); + } else { + dev->state = LPT_STATE_READ_DMA; + + timer_advance_u64(&dev->fifo_out_timer, + (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + } + } else + timer_advance_u64(&dev->fifo_out_timer, + (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + } else if (!fifo_get_empty(dev->fifo)) + timer_advance_u64(&dev->fifo_out_timer, + (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + else + lpt_autofeed(dev, 0); + break; + } +} + +void +lpt_write(const uint16_t port, const uint8_t val, void *priv) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + uint16_t mask = 0x0407; + + lpt_log("[W] %04X = %02X\n", port, val); + + /* This is needed so the parallel port at 3BC works. */ + if (dev->addr & 0x0004) + mask = 0x0403; + + switch (port & mask) { + case 0x0000: + if (dev->ecp) { + if ((dev->ecr & 0xe0) == 0x60) + /* AFIFO */ + lpt_write_fifo(dev, val, 0x00); + else if (!(dev->ecr & 0xc0) && (!(dev->ecr & 0x20) || !(lpt_get_ctrl_raw(dev) & 0x20)) && + dev->dt && dev->dt->write_data && dev->priv) + /* DATAR */ + dev->dt->write_data(val, dev->priv); + dev->dat = val; + } else { + /* DTR */ + if ((!dev->ext || !(lpt_get_ctrl_raw(dev) & 0x20)) && dev->dt && + dev->dt->write_data && dev->priv) + dev->dt->write_data(val, dev->priv); + dev->dat = val; + } + break; + + case 0x0001: + break; + + case 0x0002: + if (dev->dt && dev->dt->write_ctrl && dev->priv) { + if (dev->ecp) + dev->dt->write_ctrl((val & 0xfc) | dev->autofeed | dev->strobe, dev->priv); + else + dev->dt->write_ctrl(val, dev->priv); + } + dev->ctrl = val; + dev->enable_irq = val & 0x10; + if (!(val & 0x10) && (dev->irq != 0xff)) + picintc(1 << dev->irq); + dev->irq_state = 0; + break; + + case 0x0003: + if (lpt_is_epp(dev)) { + if (dev->dt && dev->dt->epp_write_data && dev->priv) + dev->dt->epp_write_data(1, val, dev->priv); + } + break; + + case 0x0004 ... 0x0007: + if (lpt_is_epp(dev)) { + if (dev->dt && dev->dt->epp_write_data && dev->priv) + dev->dt->epp_write_data(0, val, dev->priv); + } + break; + + case 0x0400: case 0x0404: + switch (dev->ecr >> 5) { + default: + break; + case 2: + lpt_write_fifo(dev, val, 0x01); + break; + case 3: + if (!(lpt_get_ctrl_raw(dev) & 0x20)) + lpt_write_fifo(dev, val, 0x01); + break; + case 6: + /* TFIFO */ + if (!fifo_get_full(dev->fifo)) + fifo_write_evt(val, dev->fifo); + break; + } + break; + + case 0x0402: case 0x0406: + if (!(val & 0x0c)) + lpt_autofeed(dev, 0x00); + else + lpt_autofeed(dev, 0x02); + + if ((dev->ecr & 0x04) && !(val & 0x04)) { + dev->dma_stat = 0x00; + fifo_reset(dev->fifo); + if (val & 0x08) { + dev->state = LPT_STATE_READ_DMA; + dev->fifo_stat = 0x00; + if (!timer_is_enabled(&dev->fifo_out_timer)) + timer_set_delay_u64(&dev->fifo_out_timer, (uint64_t) ((1000000.0 / 2500000.0) * (double) TIMER_USEC)); + } else { + dev->state = LPT_STATE_WRITE_FIFO; + if (lpt_get_ctrl_raw(dev) & 0x20) + dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x04 : 0x00; + else + dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x00 : 0x04; + } + } else if ((val & 0x04) && !(dev->ecr & 0x04)) { + if (timer_is_enabled(&dev->fifo_out_timer)) + timer_disable(&dev->fifo_out_timer); + + dev->state = LPT_STATE_IDLE; + } + dev->ecr = val; + lpt_ecp_update_irq(dev); + break; + + default: + break; + } +} + +static void +lpt_fifo_d_ready_evt(void *priv) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + + if (!(dev->ecr & 0x08)) { + if (lpt_get_ctrl_raw(dev) & 0x20) + dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x04 : 0x00; + else + dev->fifo_stat = fifo_get_ready(dev->fifo) ? 0x00 : 0x04; + } + + lpt_ecp_update_irq(dev); +} + +void +lpt_write_to_fifo(void *priv, const uint8_t val) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + + if (dev->ecp) { + if (((dev->ecr & 0xe0) == 0x20) && (lpt_get_ctrl_raw(dev) & 0x20)) + dev->dat = val; + else if (((dev->ecr & 0xe0) == 0x60) && (lpt_get_ctrl_raw(dev) & 0x20) && + !fifo_get_full(dev->fifo)) + fifo_write_evt_tagged(0x01, val, dev->fifo); + + if (((dev->ecr & 0x0c) == 0x08) && (dev->dma != 0xff)) { + const int ret = dma_channel_write(dev->dma, val); + + if (ret & DMA_OVER) + dev->dma_stat |= 0x04; + } + } else { + if (dev->ext && (lpt_get_ctrl_raw(dev) & 0x20)) + dev->dat = val; + } +} + +void +lpt_write_to_dat(void *priv, const uint8_t val) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + + dev->dat = val; +} + +static uint8_t +lpt_read_fifo(const lpt_port_t *dev) +{ + uint8_t ret = 0xff; + + if (!fifo_get_empty(dev->fifo)) + ret = fifo_read(dev->fifo); + + return ret; +} + +uint8_t +lpt_read_status(const int port) +{ + lpt_port_t *dev = &lpt_ports[port]; + uint8_t low_bits = 0x07; + uint8_t ret; + + if (dev->ext) { + low_bits = 0x03 | (dev->irq_state ? 0x00 : 0x04); + if (dev->irq != 0xff) + picintclevel(1 << dev->irq, &dev->irq_state); + dev->irq_state = 0; + } + if (dev->epp || dev->ecp) { + low_bits = lpt_is_epp(dev) ? 0x02 : 0x03; + if (lpt_get_ctrl_raw(dev) & 0x10) + low_bits |= (dev->irq_state ? 0x00 : 0x04); + else + low_bits |= 0x04; + } + + if (dev->dt && dev->dt->read_status && dev->priv) + ret = (dev->dt->read_status(dev->priv) & 0xf8) | low_bits; + else + ret = 0xd8 | low_bits; + + return ret; +} + +uint8_t +lpt_read(const uint16_t port, void *priv) +{ + const lpt_port_t *dev = (lpt_port_t *) priv; + uint16_t mask = 0x0407; + uint8_t ret = 0xff; + + /* This is needed so the parallel port at 3BC works. */ + if (dev->addr & 0x0004) + mask = 0x0403; + + switch (port & mask) { + case 0x0000: + if (dev->ecp) { + if (!(dev->ecr & 0xc0)) + ret = dev->dat; + } else { + /* DTR */ + ret = dev->dat; + } + break; + + case 0x0001: + ret = lpt_read_status(dev->id); + break; + + case 0x0002: + ret = lpt_get_ctrl(dev); + if (dev->ecp) + ret = (ret & 0xfc) | (dev->ctrl & 0x03); + break; + + case 0x0003: + if (lpt_is_epp(dev)) { + if (dev->dt && dev->dt->epp_request_read && dev->priv) + dev->dt->epp_request_read(1, dev->priv); + ret = dev->dat; + } + break; + + case 0x0004 ... 0x0007: + if (lpt_is_epp(dev)) { + if (dev->dt && dev->dt->epp_request_read && dev->priv) + dev->dt->epp_request_read(0, dev->priv); + ret = dev->dat; + } + break; + + case 0x0400: case 0x0404: + switch (dev->ecr >> 5) { + default: + break; + case 3: + if (lpt_get_ctrl_raw(dev) & 0x20) + ret = lpt_read_fifo(dev); + break; + case 6: + /* TFIFO */ + if (!fifo_get_empty(dev->fifo)) + ret = fifo_read_evt(dev->fifo); + break; + case 7: + /* CNFGA */ + ret = 0x14; + break; + } + break; + + case 0x0401: case 0x0405: + if ((dev->ecr & 0xe0) == 0xe0) { + /* CNFGB */ + ret = 0x08; + ret |= (dev->irq_state ? 0x40 : 0x00); + ret |= ((dev->irq == 0x05) ? 0x30 : 0x00); + if ((dev->dma >= 1) && (dev->dma <= 3)) + ret |= dev->dma; + } + break; + + case 0x0402: case 0x0406: + ret = dev->ecr | dev->fifo_stat | (dev->dma_stat & 0x04); + ret |= (fifo_get_full(dev->fifo) ? 0x02 : 0x00); + ret |= (fifo_get_empty(dev->fifo) ? 0x01 : 0x00); + break; + + default: + break; + } + + lpt_log("[R] %04X = %02X\n", port, ret); + + return ret; +} + +uint8_t +lpt_read_port(const int port, const uint16_t reg) +{ + lpt_port_t *dev = &(lpt_ports[port]); + + return lpt_read(reg, dev); +} + +void +lpt_irq(void *priv, const int raise) +{ + lpt_port_t *dev = (lpt_port_t *) priv; + + if (dev->enable_irq) { + if (dev->irq != 0xff) { + if (dev->ext) { + if (raise) + picintlevel(1 << dev->irq, &dev->irq_state); + else + picintclevel(1 << dev->irq, &dev->irq_state); + } else { + if (raise) + picint(1 << dev->irq); + else + picintc(1 << dev->irq); + } + } + + if (!dev->ext || (dev->irq == 0xff)) + dev->irq_state = raise; + } else { + if (dev->irq != 0xff) { + if (dev->ext) + picintclevel(1 << dev->irq, &dev->irq_state); + else + picintc(1 << dev->irq); + } + + dev->irq_state = 0; + } +} + +void +lpt_set_ext(const int port, const uint8_t ext) +{ + if (lpt_ports[port].enabled) + lpt_ports[port].ext = ext; +} + +void +lpt_set_ecp(const int port, const uint8_t ecp) +{ + if (lpt_ports[port].enabled) { + const uint16_t addr = lpt_ports[port].addr; + lpt_port_setup(port, 0xfff); + lpt_ports[port].ecp = ecp; + lpt_port_setup(port, addr); + } +} + +void +lpt_set_epp(const int port, const uint8_t epp) +{ + if (lpt_ports[port].enabled) { + const uint16_t addr = lpt_ports[port].addr; + lpt_port_setup(port, 0xfff); + lpt_ports[port].epp = epp; + lpt_port_setup(port, addr); + } +} + +void +lpt_set_lv2(const int port, const uint8_t lv2) +{ + if (lpt_ports[port].enabled) { + const uint16_t addr = lpt_ports[port].addr; + lpt_port_setup(port, 0xfff); + lpt_ports[port].lv2 = lv2; + lpt_port_setup(port, addr); + } +} + +void +lpt_close(void) +{ + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + if (lpt_ports[i].enabled) { + fifo_close(lpt_ports[i].fifo); + lpt_ports[i].fifo = NULL; + + timer_disable(&lpt_ports[i].fifo_out_timer); + } + } +} + +void +lpt_port_zero(lpt_port_t *dev) +{ + lpt_port_t temp = { 0 }; + + temp.irq = dev->irq; + temp.id = dev->id; + temp.device = dev->device; + temp.dt = dev->dt; + temp.priv = dev->priv; + temp.enabled = dev->enabled; + temp.fifo = dev->fifo; + temp.fifo_out_timer = dev->fifo_out_timer; + + if (dev->enabled) + lpt_port_remove(dev->id); + + memset(dev, 0x00, sizeof(lpt_port_t)); + + dev->addr = 0xffff; + dev->irq = temp.irq; + dev->id = temp.id; + dev->device = temp.device; + dev->dt = temp.dt; + dev->priv = temp.priv; + dev->enabled = temp.enabled; + dev->fifo = temp.fifo; + dev->fifo_out_timer = temp.fifo_out_timer; + + if (machine_has_bus(machine, MACHINE_BUS_MCA)) + dev->ext = 1; +} + +void +lpt_reset(void) +{ + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + if (lpt_ports[i].enabled) + if (timer_is_enabled(&lpt_ports[i].fifo_out_timer)) + timer_disable(&lpt_ports[i].fifo_out_timer); + + lpt_port_zero(&(lpt_ports[i])); + + if (lpt_ports[i].enabled) { + if (lpt_ports[i].irq_state) { + if (lpt_ports[i].irq == 0xff) + lpt_ports[i].irq_state = 0x00; + else { + picintclevel(lpt_ports[i].irq, &lpt_ports[i].irq_state); + picintc(lpt_ports[i].irq); + } + } + + lpt_ports[i].enable_irq = 0x00; + lpt_ports[i].ext = !!(machine_has_bus(machine, MACHINE_BUS_MCA)); + lpt_ports[i].epp = 0; + lpt_ports[i].ecp = 0; + lpt_ports[i].ecr = 0x15; + lpt_ports[i].dat = 0xff; + lpt_ports[i].fifo_stat = 0x00; + lpt_ports[i].dma_stat = 0x00; + } + } +} + +void +lpt_init(void) +{ + const uint16_t default_ports[PARALLEL_MAX] = { LPT1_ADDR, LPT2_ADDR, LPT_MDA_ADDR, LPT4_ADDR }; + const uint8_t default_irqs[PARALLEL_MAX] = { LPT1_IRQ, LPT2_IRQ, LPT_MDA_IRQ, LPT4_IRQ }; + + for (uint8_t i = 0; i < PARALLEL_MAX; i++) { + lpt_ports[i].id = i; + lpt_ports[i].dt = NULL; + lpt_ports[i].priv = NULL; + lpt_ports[i].fifo = NULL; + memset(&lpt_ports[i].fifo_out_timer, 0x00, sizeof(pc_timer_t)); + + lpt_port_zero(&(lpt_ports[i])); + + lpt_ports[i].addr = 0xffff; + lpt_ports[i].irq = 0xff; + lpt_ports[i].dma = 0xff; + lpt_ports[i].enable_irq = 0x00; + lpt_ports[i].ext = 0; + lpt_ports[i].epp = 0; + lpt_ports[i].ecp = 0; + lpt_ports[i].ecr = 0x15; + + if (lpt_ports[i].enabled) { + lpt_port_setup(i, default_ports[i]); + lpt_port_irq(i, default_irqs[i]); + + lpt_ports[i].fifo = fifo16_init(); + + fifo_set_trigger_len(lpt_ports[i].fifo, 8); + + fifo_set_d_ready_evt(lpt_ports[i].fifo, lpt_fifo_d_ready_evt); + fifo_set_priv(lpt_ports[i].fifo, &lpt_ports[i]); + + timer_add(&lpt_ports[i].fifo_out_timer, lpt_fifo_out_callback, &lpt_ports[i], 0); + } + } +} + +void +lpt_port_setup(const int i, const uint16_t port) +{ + if (lpt_ports[i].enabled) { + if (lpt_ports[i].addr != 0xffff) { + io_removehandler(lpt_ports[i].addr, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + io_removehandler(lpt_ports[i].addr + 0x0400, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + } + if (port != 0xffff) { + lpt_log("Set handler: %04X-%04X\n", port, port + 0x0003); + io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + if (lpt_ports[i].epp) + io_sethandler(lpt_ports[i].addr + 0x0003, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + if (lpt_ports[i].ecp || lpt_ports[i].lv2) { + io_sethandler(port + 0x0400, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + if (lpt_ports[i].epp) + io_sethandler(lpt_ports[i].addr + 0x0403, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + } + } + lpt_ports[i].addr = port; + } else + lpt_ports[i].addr = 0xffff; +} + +void +lpt_port_irq(const int i, const uint8_t irq) +{ + if (lpt_ports[i].enabled) + lpt_ports[i].irq = irq; + else + lpt_ports[i].irq = 0xff; + + lpt_log("Port %i IRQ = %02X\n", i, irq); +} + +void +lpt_port_dma(const int i, const uint8_t dma) +{ + if (lpt_ports[i].enabled) + lpt_ports[i].dma = dma; + else + lpt_ports[i].dma = 0xff; + + lpt_log("Port %i DMA = %02X\n", i, dma); +} + +void +lpt_port_remove(const int i) +{ + if (lpt_ports[i].enabled && (lpt_ports[i].addr != 0xffff)) { + io_removehandler(lpt_ports[i].addr, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + io_removehandler(lpt_ports[i].addr + 0x0400, 0x0007, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); + + lpt_ports[i].addr = 0xffff; + } +} + +void +lpt1_remove_ams(void) +{ + if (lpt_ports[0].enabled) + io_removehandler(lpt_ports[0].addr + 1, 0x0002, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[0]); +} diff --git a/src/include/86box/lpt.h b/src/include/86box/lpt.h index 674d6340f..c13d70291 100644 --- a/src/include/86box/lpt.h +++ b/src/include/86box/lpt.h @@ -25,14 +25,24 @@ typedef struct lpt_device_t { void (*close)(void *priv); void (*write_data)(uint8_t val, void *priv); void (*write_ctrl)(uint8_t val, void *priv); - uint8_t (*read_data)(void *priv); + void (*autofeed)(uint8_t val,void *priv); + void (*strobe)(uint8_t old, uint8_t val,void *priv); uint8_t (*read_status)(void *priv); uint8_t (*read_ctrl)(void *priv); + void (*epp_write_data)(uint8_t is_addr, uint8_t val, void *priv); + void (*epp_request_read)(uint8_t is_addr, void *priv); } lpt_device_t; +extern void lpt_set_ext(int port, uint8_t ext); +extern void lpt_set_ecp(int port, uint8_t ecp); +extern void lpt_set_epp(int port, uint8_t epp); +extern void lpt_set_lv2(int port, uint8_t lv2); +extern void lpt_reset(void); +extern void lpt_close(void); extern void lpt_init(void); extern void lpt_port_setup(int i, uint16_t port); extern void lpt_port_irq(int i, uint8_t irq); +extern void lpt_port_dma(int i, uint8_t dma); extern void lpt_port_remove(int i); extern void lpt1_remove_ams(void); @@ -68,31 +78,62 @@ void lpt_devices_close(void); typedef struct lpt_port_t { uint8_t enabled; uint8_t irq; + uint8_t irq_state; + uint8_t dma; uint8_t dat; uint8_t ctrl; + uint8_t ext; + uint8_t epp; + uint8_t ecp; + uint8_t ecr; + uint8_t in_dat; + uint8_t fifo_stat; + uint8_t dma_stat; + uint8_t state; + uint8_t autofeed; + uint8_t strobe; + uint8_t lv2; + uint8_t pad[7]; uint16_t addr; - uint16_t pad0; + uint16_t id; + uint16_t pad0[2]; int device; int enable_irq; lpt_device_t *dt; +#ifdef FIFO_H + fifo16_t *fifo; +#else + void *fifo; +#endif void *priv; + + pc_timer_t fifo_out_timer; } lpt_port_t; +typedef enum { + LPT_STATE_IDLE = 0, + LPT_STATE_READ_DMA, + LPT_STATE_WRITE_FIFO +} lpt_state_t; + extern lpt_port_t lpt_ports[PARALLEL_MAX]; -extern void lpt_write(uint16_t port, uint8_t val, void *priv); -extern uint8_t lpt_read(uint16_t port, void *priv); +extern void lpt_write(uint16_t port, uint8_t val, void *priv); -extern uint8_t lpt_read_port(int port, uint16_t reg); +extern void lpt_write_to_fifo(void *priv, uint8_t val); -extern uint8_t lpt_read_status(int port); -extern void lpt_irq(void *priv, int raise); +extern uint8_t lpt_read(uint16_t port, void *priv); + +extern uint8_t lpt_read_port(int port, uint16_t reg); + +extern uint8_t lpt_read_status(int port); +extern void lpt_irq(void *priv, int raise); + +extern int lpt_device_get_from_internal_name(const char *s); extern const char *lpt_device_get_name(int id); extern const char *lpt_device_get_internal_name(int id); -extern int lpt_device_get_from_internal_name(char *s); - extern const lpt_device_t lpt_dac_device; extern const lpt_device_t lpt_dac_stereo_device; diff --git a/src/lpt.c b/src/lpt.c deleted file mode 100644 index 072f4a34c..000000000 --- a/src/lpt.c +++ /dev/null @@ -1,264 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#include -#include -#include -#include -#include <86box/86box.h> -#include <86box/io.h> -#include <86box/lpt.h> -#include <86box/pic.h> -#include <86box/sound.h> -#include <86box/prt_devs.h> -#include <86box/thread.h> -#include <86box/timer.h> -#include <86box/device.h> -#include <86box/network.h> - -lpt_port_t lpt_ports[PARALLEL_MAX]; - -const lpt_device_t lpt_none_device = { - .name = "None", - .internal_name = "none", - .init = NULL, - .close = NULL, - .write_data = NULL, - .write_ctrl = NULL, - .read_data = NULL, - .read_status = NULL, - .read_ctrl = NULL -}; - -static const struct { - const char *internal_name; - const lpt_device_t *device; -} lpt_devices[] = { - // clang-format off - {"none", &lpt_none_device }, - {"dss", &dss_device }, - {"lpt_dac", &lpt_dac_device }, - {"lpt_dac_stereo", &lpt_dac_stereo_device }, - {"text_prt", &lpt_prt_text_device }, - {"dot_matrix", &lpt_prt_escp_device }, - {"postscript", &lpt_prt_ps_device }, -#ifdef USE_PCL - {"pcl", &lpt_prt_pcl_device }, -#endif - {"plip", &lpt_plip_device }, - {"dongle_savquest", &lpt_hasp_savquest_device }, - {"", NULL } - // clang-format on -}; - -const char * -lpt_device_get_name(int id) -{ - if (strlen(lpt_devices[id].internal_name) == 0) - return NULL; - if (!lpt_devices[id].device) - return "None"; - return lpt_devices[id].device->name; -} - -const char * -lpt_device_get_internal_name(int id) -{ - if (strlen(lpt_devices[id].internal_name) == 0) - return NULL; - return lpt_devices[id].internal_name; -} - -int -lpt_device_get_from_internal_name(char *s) -{ - int c = 0; - - while (strlen(lpt_devices[c].internal_name) != 0) { - if (strcmp(lpt_devices[c].internal_name, s) == 0) - return c; - c++; - } - - return 0; -} - -void -lpt_devices_init(void) -{ - for (uint8_t i = 0; i < PARALLEL_MAX; i++) { - lpt_ports[i].dt = (lpt_device_t *) lpt_devices[lpt_ports[i].device].device; - - if (lpt_ports[i].dt && lpt_ports[i].dt->init) - lpt_ports[i].priv = lpt_ports[i].dt->init(&lpt_ports[i]); - } -} - -void -lpt_devices_close(void) -{ - lpt_port_t *dev; - - for (uint8_t i = 0; i < PARALLEL_MAX; i++) { - dev = &lpt_ports[i]; - - if (lpt_ports[i].dt && lpt_ports[i].dt->close) - dev->dt->close(dev->priv); - - dev->dt = NULL; - } -} - -void -lpt_write(uint16_t port, uint8_t val, void *priv) -{ - lpt_port_t *dev = (lpt_port_t *) priv; - - switch (port & 3) { - case 0: - if (dev->dt && dev->dt->write_data && dev->priv) - dev->dt->write_data(val, dev->priv); - dev->dat = val; - break; - - case 1: - break; - - case 2: - if (dev->dt && dev->dt->write_ctrl && dev->priv) - dev->dt->write_ctrl(val, dev->priv); - dev->ctrl = val; - dev->enable_irq = val & 0x10; - break; - - default: - break; - } -} - -uint8_t -lpt_read(uint16_t port, void *priv) -{ - uint8_t ret = 0xff; - lpt_port_t *dev = (lpt_port_t *) priv; - - switch (port & 3) { - case 0: - if (dev->dt && dev->dt->read_data && dev->priv) - ret = dev->dt->read_data(dev->priv); - else - ret = dev->dat; - break; - - case 1: - if (dev->dt && dev->dt->read_status && dev->priv) - ret = dev->dt->read_status(dev->priv) | 0x07; - else - ret = 0xdf; - break; - - case 2: - if (dev->dt && dev->dt->read_ctrl && dev->priv) - ret = (dev->dt->read_ctrl(dev->priv) & 0xef) | dev->enable_irq; - else - ret = 0xe0 | dev->ctrl | dev->enable_irq; - break; - - default: - break; - } - - return ret; -} - -uint8_t -lpt_read_port(int port, uint16_t reg) -{ - lpt_port_t *dev = &(lpt_ports[port]); - uint8_t ret = lpt_read(reg, dev); - - return ret; -} - -uint8_t -lpt_read_status(int port) -{ - lpt_port_t *dev = &(lpt_ports[port]); - uint8_t ret = 0xff; - - if (dev->dt && dev->dt->read_status && dev->priv) - ret = dev->dt->read_status(dev->priv) | 0x07; - else - ret = 0xdf; - - return ret; -} - -void -lpt_irq(void *priv, int raise) -{ - const lpt_port_t *dev = (lpt_port_t *) priv; - - if (dev->enable_irq && (dev->irq != 0xff)) { - if (raise) - picint(1 << dev->irq); - else - picintc(1 << dev->irq); - } -} - -void -lpt_init(void) -{ - uint16_t default_ports[PARALLEL_MAX] = { LPT1_ADDR, LPT2_ADDR, LPT_MDA_ADDR, LPT4_ADDR }; - uint8_t default_irqs[PARALLEL_MAX] = { LPT1_IRQ, LPT2_IRQ, LPT_MDA_IRQ, LPT4_IRQ }; - - for (uint8_t i = 0; i < PARALLEL_MAX; i++) { - lpt_ports[i].addr = 0xffff; - lpt_ports[i].irq = 0xff; - lpt_ports[i].enable_irq = 0x10; - - if (lpt_ports[i].enabled) { - lpt_port_setup(i, default_ports[i]); - lpt_port_irq(i, default_irqs[i]); - } - } -} - -void -lpt_port_setup(int i, uint16_t port) -{ - if (lpt_ports[i].enabled) { - if ((lpt_ports[i].addr != 0xffff) && (lpt_ports[i].addr != 0x0000)) - io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); - if ((port != 0xffff) && (port != 0x0000)) - io_sethandler(port, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); - lpt_ports[i].addr = port; - } else - lpt_ports[i].addr = 0xffff; -} - -void -lpt_port_irq(int i, uint8_t irq) -{ - if (lpt_ports[i].enabled) - lpt_ports[i].irq = irq; - else - lpt_ports[i].irq = 0xff; -} - -void -lpt_port_remove(int i) -{ - if (lpt_ports[i].enabled && (lpt_ports[i].addr != 0xffff)) { - io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); - lpt_ports[i].addr = 0xffff; - } -} - -void -lpt1_remove_ams(void) -{ - if (lpt_ports[0].enabled) - io_removehandler(lpt_ports[0].addr + 1, 0x0002, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[0]); -} diff --git a/src/network/net_plip.c b/src/network/net_plip.c index 8c46213c6..ac8ab2850 100644 --- a/src/network/net_plip.c +++ b/src/network/net_plip.c @@ -488,15 +488,18 @@ plip_close(void *priv) } const lpt_device_t lpt_plip_device = { - .name = "Parallel Line Internet Protocol", - .internal_name = "plip", - .init = plip_lpt_init, - .close = plip_close, - .write_data = plip_write_data, - .write_ctrl = plip_write_ctrl, - .read_data = NULL, - .read_status = plip_read_status, - .read_ctrl = NULL + .name = "Parallel Line Internet Protocol", + .internal_name = "plip", + .init = plip_lpt_init, + .close = plip_close, + .write_data = plip_write_data, + .write_ctrl = plip_write_ctrl, + .autofeed = NULL, + .strobe = NULL, + .read_status = plip_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; const device_t plip_device = { diff --git a/src/printer/prt_escp.c b/src/printer/prt_escp.c index f238341c5..41c81e696 100644 --- a/src/printer/prt_escp.c +++ b/src/printer/prt_escp.c @@ -1881,6 +1881,39 @@ write_data(uint8_t val, void *priv) dev->data = val; } +static void +autofeed(uint8_t val, void *priv) +{ + escp_t *dev = (escp_t *) priv; + + if (dev == NULL) + return; + + dev->autofeed = ((val & 0x02) > 0); +} + +static void +strobe(uint8_t old, uint8_t val, void *priv) +{ + escp_t *dev = (escp_t *) priv; + + if (dev == NULL) + return; + + /* Data is strobed to the parallel printer on the falling edge of the + strobe bit. */ + if (!(val & 0x01) && (old & 0x01)) { + /* Process incoming character. */ + handle_char(dev, dev->data); + + /* ACK it, will be read on next READ STATUS. */ + dev->ack = 1; + timer_set_delay_u64(&dev->pulse_timer, ISACONST); + + timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); + } +} + static void write_ctrl(uint8_t val, void *priv) { @@ -1919,14 +1952,6 @@ write_ctrl(uint8_t val, void *priv) dev->autofeed = ((val & 0x02) > 0); } -static uint8_t -read_data(void *priv) -{ - const escp_t *dev = (escp_t *) priv; - - return dev->data; -} - static uint8_t read_ctrl(void *priv) { @@ -2058,13 +2083,16 @@ escp_close(void *priv) } const lpt_device_t lpt_prt_escp_device = { - .name = "Generic ESC/P Dot-Matrix Printer", - .internal_name = "dot_matrix", - .init = escp_init, - .close = escp_close, - .write_data = write_data, - .write_ctrl = write_ctrl, - .read_data = read_data, - .read_status = read_status, - .read_ctrl = read_ctrl + .name = "Generic ESC/P Dot-Matrix", + .internal_name = "dot_matrix", + .init = escp_init, + .close = escp_close, + .write_data = write_data, + .write_ctrl = write_ctrl, + .autofeed = autofeed, + .strobe = strobe, + .read_status = read_status, + .read_ctrl = read_ctrl, + .epp_write_data = NULL, + .epp_request_read = NULL }; diff --git a/src/printer/prt_ps.c b/src/printer/prt_ps.c index 1298018ee..904ff34ad 100644 --- a/src/printer/prt_ps.c +++ b/src/printer/prt_ps.c @@ -319,6 +319,35 @@ process_data(ps_t *dev) dev->buffer[dev->buffer_pos] = 0; } +static void +ps_autofeed(uint8_t val, void *priv) +{ + ps_t *dev = (ps_t *) priv; + + if (dev == NULL) + return; + + dev->autofeed = val & 0x02 ? true : false; +} + +static void +ps_strobe(uint8_t old, uint8_t val, void *priv) +{ + ps_t *dev = (ps_t *) priv; + + if (dev == NULL) + return; + + if (!(val & 0x01) && (old & 0x01)) { + process_data(dev); + + dev->ack = true; + + timer_set_delay_u64(&dev->pulse_timer, ISACONST); + timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); + } +} + static void ps_write_ctrl(uint8_t val, void *priv) { @@ -479,27 +508,33 @@ ps_close(void *priv) } const lpt_device_t lpt_prt_ps_device = { - .name = "Generic PostScript Printer", - .internal_name = "postscript", - .init = ps_init, - .close = ps_close, - .write_data = ps_write_data, - .write_ctrl = ps_write_ctrl, - .read_data = NULL, - .read_status = ps_read_status, - .read_ctrl = NULL + .name = "Generic PostScript Printer", + .internal_name = "postscript", + .init = ps_init, + .close = ps_close, + .write_data = ps_write_data, + .write_ctrl = ps_write_ctrl, + .autofeed = ps_autofeed, + .strobe = ps_strobe, + .read_status = ps_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; #ifdef USE_PCL const lpt_device_t lpt_prt_pcl_device = { - .name = "Generic PCL5e Printer", - .internal_name = "pcl", - .init = pcl_init, - .close = ps_close, - .write_data = ps_write_data, - .write_ctrl = ps_write_ctrl, - .read_data = NULL, - .read_status = ps_read_status, - .read_ctrl = NULL + .name = "Generic PCL5e Printer", + .internal_name = "pcl", + .init = pcl_init, + .close = ps_close, + .write_data = ps_write_data, + .write_ctrl = ps_write_ctrl, + .autofeed = ps_autofeed, + .strobe = ps_strobe, + .read_status = ps_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; #endif diff --git a/src/printer/prt_text.c b/src/printer/prt_text.c index e04ef9680..7604d023e 100644 --- a/src/printer/prt_text.c +++ b/src/printer/prt_text.c @@ -367,6 +367,38 @@ write_data(uint8_t val, void *priv) dev->data = val; } +static void +autofeed(uint8_t val, void *priv) +{ + prnt_t *dev = (prnt_t *) priv; + + if (dev == NULL) + return; + + /* set autofeed value */ + dev->autofeed = val & 0x02 ? 1 : 0; +} + +static void +strobe(uint8_t old, uint8_t val, void *priv) +{ + prnt_t *dev = (prnt_t *) priv; + + if (dev == NULL) + return; + + if (!(val & 0x01) && (old & 0x01)) { /* STROBE */ + /* Process incoming character. */ + handle_char(dev); + + /* ACK it, will be read on next READ STATUS. */ + dev->ack = 1; + + timer_set_delay_u64(&dev->pulse_timer, ISACONST); + timer_set_delay_u64(&dev->timeout_timer, 5000000 * TIMER_USEC); + } +} + static void write_ctrl(uint8_t val, void *priv) { @@ -465,13 +497,16 @@ prnt_close(void *priv) } const lpt_device_t lpt_prt_text_device = { - .name = "Generic Text Printer", - .internal_name = "text_prt", - .init = prnt_init, - .close = prnt_close, - .write_data = write_data, - .write_ctrl = write_ctrl, - .read_data = NULL, - .read_status = read_status, - .read_ctrl = NULL + .name = "Generic Text Printer", + .internal_name = "text_prt", + .init = prnt_init, + .close = prnt_close, + .write_data = write_data, + .write_ctrl = write_ctrl, + .autofeed = autofeed, + .strobe = strobe, + .read_status = read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; diff --git a/src/sio/sio_ali5123.c b/src/sio/sio_ali5123.c index 398d00839..436e425d2 100644 --- a/src/sio/sio_ali5123.c +++ b/src/sio/sio_ali5123.c @@ -85,11 +85,18 @@ ali5123_lpt_handler(ali5123_t *dev) uint8_t global_enable = !(dev->regs[0x22] & (1 << 3)); uint8_t local_enable = !!dev->ld_regs[3][0x30]; uint8_t lpt_irq = dev->ld_regs[3][0x70]; + uint8_t lpt_dma = dev->ld_regs[3][0x74]; if (lpt_irq > 15) lpt_irq = 0xff; + if (lpt_dma == 4) + lpt_dma = 0xff; + lpt1_remove(); + lpt_set_epp(0, !!(dev->ld_regs[3][0xf0] & 0x01)); + lpt_set_ecp(0, !!(dev->ld_regs[3][0xf0] & 0x02)); + lpt_set_ext(0, !(dev->ld_regs[3][0xf0] & 0x04) || !!(dev->ld_regs[3][0xf1] & 0x80)); if (global_enable && local_enable) { ld_port = make_port(dev, 3) & 0xFFFC; if ((ld_port >= 0x0100) && (ld_port <= 0x0FFC)) @@ -247,7 +254,7 @@ ali5123_write(uint16_t port, uint8_t val, void *priv) dev->regs[dev->cur_reg] = val; } else { valxor = val ^ dev->ld_regs[cur_ld][dev->cur_reg]; - if (((dev->cur_reg & 0xf0) == 0x70) && (cur_ld < 4)) + if (((dev->cur_reg & 0xf0) == 0x70) && (cur_ld < 4) && (cur_ld != 3)) return; /* Block writes to some logical devices. */ if (cur_ld > 0x0c) @@ -357,6 +364,9 @@ ali5123_write(uint16_t port, uint8_t val, void *priv) case 0x60: case 0x61: case 0x70: + case 0x74: + case 0xf0: + case 0xf1: if ((dev->cur_reg == 0x30) && (val & 0x01)) dev->regs[0x22] &= ~0x08; if (valxor) diff --git a/src/sio/sio_pc87306.c b/src/sio/sio_pc87306.c index 41d69b0cc..e42c48ab4 100644 --- a/src/sio/sio_pc87306.c +++ b/src/sio/sio_pc87306.c @@ -121,6 +121,10 @@ lpt1_handler(pc87306_t *dev) uint16_t lptba; uint16_t lpt_port = LPT1_ADDR; uint8_t lpt_irq = LPT2_IRQ; + uint8_t lpt_dma = ((dev->regs[0x18] & 0x06) >> 1); + + if (lpt_dma == 0x00) + lpt_dma = 0xff; temp = dev->regs[0x01] & 3; lptba = ((uint16_t) dev->regs[0x19]) << 2; @@ -157,6 +161,13 @@ lpt1_handler(pc87306_t *dev) lpt1_setup(lpt_port); lpt1_irq(lpt_irq); + + lpt_port_dma(0, lpt_dma); + + lpt_set_ext(0, !!(dev->regs[0x02] & 0x80)); + + lpt_set_epp(0, !!(dev->regs[0x04] & 0x01)); + lpt_set_ecp(0, !!(dev->regs[0x04] & 0x04)); } static void @@ -169,7 +180,7 @@ serial_handler(pc87306_t *dev, int uart) uint8_t pnp_shift; uint8_t irq; - temp = (dev->regs[1] >> (2 << uart)) & 3; + temp = (dev->regs[0x01] >> (2 << uart)) & 3; fer_shift = 2 << uart; /* 2 for UART 1, 4 for UART 2 */ pnp_shift = 2 + (uart << 2); /* 2 for UART 1, 6 for UART 2 */ @@ -188,7 +199,7 @@ serial_handler(pc87306_t *dev, int uart) serial_setup(dev->uart[uart], COM2_ADDR, irq); break; case 2: - switch ((dev->regs[1] >> 6) & 3) { + switch ((dev->regs[0x01] >> 6) & 3) { case 0: serial_setup(dev->uart[uart], COM3_ADDR, irq); break; @@ -207,7 +218,7 @@ serial_handler(pc87306_t *dev, int uart) } break; case 3: - switch ((dev->regs[1] >> 6) & 3) { + switch ((dev->regs[0x01] >> 6) & 3) { case 0: serial_setup(dev->uart[uart], COM4_ADDR, irq); break; @@ -264,41 +275,41 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) switch (dev->cur_reg) { case 0x00: - if (valxor & 1) { + if (valxor & 0x01) { lpt1_remove(); - if ((val & 1) && !(dev->regs[2] & 1)) + if ((val & 1) && !(dev->regs[0x02] & 1)) lpt1_handler(dev); } - if (valxor & 2) { - serial_remove(dev->uart[0]); - if ((val & 2) && !(dev->regs[2] & 1)) + if (valxor & 0x02) { + serial_remove(dev->uart[0x00]); + if ((val & 2) && !(dev->regs[0x02] & 1)) serial_handler(dev, 0); } - if (valxor & 4) { - serial_remove(dev->uart[1]); - if ((val & 4) && !(dev->regs[2] & 1)) + if (valxor & 0x04) { + serial_remove(dev->uart[0x01]); + if ((val & 4) && !(dev->regs[0x02] & 1)) serial_handler(dev, 1); } if (valxor & 0x28) { fdc_remove(dev->fdc); - if ((val & 8) && !(dev->regs[2] & 1)) + if ((val & 8) && !(dev->regs[0x02] & 1)) fdc_set_base(dev->fdc, (val & 0x20) ? FDC_SECONDARY_ADDR : FDC_PRIMARY_ADDR); } break; case 0x01: - if (valxor & 3) { + if (valxor & 0x03) { lpt1_remove(); - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) lpt1_handler(dev); } if (valxor & 0xcc) { - serial_remove(dev->uart[0]); - if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) + serial_remove(dev->uart[0x00]); + if ((dev->regs[0x00] & 2) && !(dev->regs[0x02] & 1)) serial_handler(dev, 0); } if (valxor & 0xf0) { - serial_remove(dev->uart[1]); - if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) + serial_remove(dev->uart[0x01]); + if ((dev->regs[0x00] & 4) && !(dev->regs[0x02] & 1)) serial_handler(dev, 1); } break; @@ -327,6 +338,11 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) } break; case 0x04: + if (valxor & (0x05)) { + lpt1_remove(); + if ((dev->regs[0x00] & 0x01) && !(dev->regs[0x02] & 0x01)) + lpt1_handler(dev); + } if (valxor & 0x80) nvr_lock_set(0x00, 256, !!(val & 0x80), dev->nvr); break; @@ -352,10 +368,17 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) if (valxor & 0x30) pc87306_gpio_handler(dev); break; + case 0x18: + if (valxor & (0x06)) { + lpt1_remove(); + if ((dev->regs[0x00] & 0x01) && !(dev->regs[0x02] & 0x01)) + lpt1_handler(dev); + } + break; case 0x19: if (valxor) { lpt1_remove(); - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) lpt1_handler(dev); } break; @@ -364,18 +387,18 @@ pc87306_write(uint16_t port, uint8_t val, void *priv) lpt1_remove(); if (!(val & 0x40)) dev->regs[0x19] = 0xEF; - if ((dev->regs[0] & 1) && !(dev->regs[2] & 1)) + if ((dev->regs[0x00] & 1) && !(dev->regs[0x02] & 1)) lpt1_handler(dev); } break; case 0x1c: if (valxor) { - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); + serial_remove(dev->uart[0x00]); + serial_remove(dev->uart[0x01]); - if ((dev->regs[0] & 2) && !(dev->regs[2] & 1)) + if ((dev->regs[0x00] & 2) && !(dev->regs[0x02] & 1)) serial_handler(dev, 0); - if ((dev->regs[0] & 4) && !(dev->regs[2] & 1)) + if ((dev->regs[0x00] & 4) && !(dev->regs[0x02] & 1)) serial_handler(dev, 1); } break; @@ -432,8 +455,8 @@ pc87306_reset_common(void *priv) */ lpt1_remove(); lpt1_handler(dev); - serial_remove(dev->uart[0]); - serial_remove(dev->uart[1]); + serial_remove(dev->uart[0x00]); + serial_remove(dev->uart[0x01]); serial_handler(dev, 0); serial_handler(dev, 1); fdc_reset(dev->fdc); @@ -471,8 +494,8 @@ pc87306_init(UNUSED(const device_t *info)) dev->fdc = device_add(&fdc_at_nsc_device); - dev->uart[0] = device_add_inst(&ns16550_device, 1); - dev->uart[1] = device_add_inst(&ns16550_device, 2); + dev->uart[0x00] = device_add_inst(&ns16550_device, 1); + dev->uart[0x01] = device_add_inst(&ns16550_device, 2); dev->nvr = device_add(&at_mb_nvr_device); diff --git a/src/sound/snd_lpt_dac.c b/src/sound/snd_lpt_dac.c index 0462818a0..13a430c91 100644 --- a/src/sound/snd_lpt_dac.c +++ b/src/sound/snd_lpt_dac.c @@ -50,6 +50,14 @@ dac_write_data(uint8_t val, void *priv) dac_update(lpt_dac); } +static void +dac_strobe(uint8_t old, uint8_t val, void *priv) +{ + lpt_dac_t *lpt_dac = (lpt_dac_t *) priv; + + lpt_dac->channel = val; +} + static void dac_write_ctrl(uint8_t val, void *priv) { @@ -109,25 +117,31 @@ dac_close(void *priv) } const lpt_device_t lpt_dac_device = { - .name = "LPT DAC / Covox Speech Thing", - .internal_name = "lpt_dac", - .init = dac_init, - .close = dac_close, - .write_data = dac_write_data, - .write_ctrl = dac_write_ctrl, - .read_data = NULL, - .read_status = dac_read_status, - .read_ctrl = NULL + .name = "LPT DAC / Covox Speech Thing", + .internal_name = "lpt_dac", + .init = dac_init, + .close = dac_close, + .write_data = dac_write_data, + .write_ctrl = dac_write_ctrl, + .autofeed = NULL, + .strobe = dac_strobe, + .read_status = dac_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; const lpt_device_t lpt_dac_stereo_device = { - .name = "Stereo LPT DAC", - .internal_name = "lpt_dac_stereo", - .init = dac_stereo_init, - .close = dac_close, - .write_data = dac_write_data, - .write_ctrl = dac_write_ctrl, - .read_data = NULL, - .read_status = dac_read_status, - .read_ctrl = NULL + .name = "Stereo LPT DAC", + .internal_name = "lpt_dac_stereo", + .init = dac_stereo_init, + .close = dac_close, + .write_data = dac_write_data, + .write_ctrl = dac_write_ctrl, + .autofeed = NULL, + .strobe = dac_strobe, + .read_status = dac_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL }; diff --git a/src/sound/snd_lpt_dss.c b/src/sound/snd_lpt_dss.c index 875230518..b609e3add 100644 --- a/src/sound/snd_lpt_dss.c +++ b/src/sound/snd_lpt_dss.c @@ -133,13 +133,16 @@ dss_close(void *priv) } const lpt_device_t dss_device = { - .name = "Disney Sound Source", - .internal_name = "dss", - .init = dss_init, - .close = dss_close, - .write_data = dss_write_data, - .write_ctrl = dss_write_ctrl, - .read_data = NULL, - .read_status = dss_read_status, - .read_ctrl = NULL + .name = "Disney Sound Source", + .internal_name = "dss", + .init = dss_init, + .close = dss_close, + .write_data = dss_write_data, + .autofeed = NULL, + .strobe = NULL, + .write_ctrl = dss_write_ctrl, + .read_status = dss_read_status, + .read_ctrl = NULL, + .epp_write_data = NULL, + .epp_request_read = NULL };