/* 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/net_plip.h> lpt_port_t lpt_ports[3]; static const struct { const char *internal_name; const lpt_device_t *device; } lpt_devices[] = { {"none", NULL}, {"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}, {"plip", &lpt_plip_device}, {"dongle_savquest", &lpt_hasp_savquest_device}, {"", NULL} }; char * lpt_device_get_name(int id) { if (strlen((char *) lpt_devices[id].internal_name) == 0) return NULL; if (!lpt_devices[id].device) return "None"; return (char *) lpt_devices[id].device->name; } char * lpt_device_get_internal_name(int id) { if (strlen((char *) lpt_devices[id].internal_name) == 0) return NULL; return (char *) lpt_devices[id].internal_name; } int lpt_device_get_from_internal_name(char *s) { int c = 0; while (strlen((char *) 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) { int i = 0; for (i = 0; i < 3; i++) { lpt_ports[i].dt = (lpt_device_t *) lpt_devices[lpt_ports[i].device].device; if (lpt_ports[i].dt) lpt_ports[i].priv = lpt_ports[i].dt->init(&lpt_ports[i]); } } void lpt_devices_close(void) { int i = 0; lpt_port_t *dev; for (i = 0; i < 3; i++) { dev = &lpt_ports[i]; if (dev->dt) 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; } } 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; } return ret; } void lpt_irq(void *priv, int raise) { 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) { int i; uint16_t default_ports[3] = { 0x378, 0x278, 0x3bc }; uint8_t default_irqs[3] = { 7, 5, 7 }; for (i = 0; i < 3; i++) { lpt_ports[i].addr = 0xffff; lpt_ports[i].irq = 0xff; lpt_ports[i].enable_irq = 0x10; if (lpt_ports[i].enabled) { lpt_port_init(i, default_ports[i]); lpt_port_irq(i, default_irqs[i]); } } } void lpt_port_init(int i, uint16_t port) { if (lpt_ports[i].enabled) { if (lpt_ports[i].addr != 0xffff) io_removehandler(lpt_ports[i].addr, 0x0003, lpt_read, NULL, NULL, lpt_write, NULL, NULL, &lpt_ports[i]); if (port != 0xffff) 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]); }