summaryrefslogtreecommitdiffstatshomepage
path: root/src/mess/machine/pc_lpt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mess/machine/pc_lpt.c')
-rw-r--r--src/mess/machine/pc_lpt.c342
1 files changed, 342 insertions, 0 deletions
diff --git a/src/mess/machine/pc_lpt.c b/src/mess/machine/pc_lpt.c
new file mode 100644
index 00000000000..2f227f3f8d0
--- /dev/null
+++ b/src/mess/machine/pc_lpt.c
@@ -0,0 +1,342 @@
+/***************************************************************************
+
+ IBM-PC printer interface
+
+***************************************************************************/
+
+#include "emu.h"
+#include "pc_lpt.h"
+#include "machine/ctronics.h"
+#include "cntr_covox.h"
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static WRITE_LINE_DEVICE_HANDLER( pc_lpt_ack_w );
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _pc_lpt_state pc_lpt_state;
+struct _pc_lpt_state
+{
+ centronics_device *centronics;
+
+ devcb_resolved_write_line out_irq_func;
+
+ UINT8 data;
+
+ int ack;
+
+ /* control latch */
+ int strobe;
+ int autofd;
+ int init;
+ int select;
+ int irq_enabled;
+};
+
+
+/***************************************************************************
+ CENTRONICS INTERFACE
+***************************************************************************/
+
+static const centronics_interface pc_centronics_config =
+{
+ DEVCB_LINE(pc_lpt_ack_w),
+ DEVCB_NULL,
+ DEVCB_NULL
+};
+
+static SLOT_INTERFACE_START(pc_centronics)
+ SLOT_INTERFACE("printer", CENTRONICS_PRINTER)
+ SLOT_INTERFACE("covox", CENTRONICS_COVOX)
+ SLOT_INTERFACE("covox_stereo", CENTRONICS_COVOX_STEREO)
+SLOT_INTERFACE_END
+
+static MACHINE_CONFIG_FRAGMENT( pc_lpt )
+ MCFG_CENTRONICS_ADD("centronics", pc_centronics_config, pc_centronics, "printer", NULL)
+MACHINE_CONFIG_END
+
+
+/*****************************************************************************
+ INLINE FUNCTIONS
+*****************************************************************************/
+
+INLINE pc_lpt_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == PC_LPT);
+
+ return (pc_lpt_state *)downcast<legacy_device_base *>(device)->token();
+}
+
+
+/***************************************************************************
+ DEVICE INTERFACE
+***************************************************************************/
+
+static DEVICE_START( pc_lpt )
+{
+ pc_lpt_state *lpt = get_safe_token(device);
+ const pc_lpt_interface *intf = (const pc_lpt_interface *)device->static_config();
+ /* validate some basic stuff */
+ assert(device->static_config() != NULL);
+
+ /* get centronics device */
+ lpt->centronics = device->subdevice<centronics_device>("centronics");
+ assert(lpt->centronics != NULL);
+
+ /* resolve callbacks */
+ lpt->out_irq_func.resolve(intf->out_irq_func, *device);
+
+ /* register for state saving */
+ device->save_item(NAME(lpt->ack));
+ device->save_item(NAME(lpt->strobe));
+ device->save_item(NAME(lpt->autofd));
+ device->save_item(NAME(lpt->init));
+ device->save_item(NAME(lpt->select));
+ device->save_item(NAME(lpt->irq_enabled));
+}
+
+static DEVICE_RESET( pc_lpt )
+{
+ pc_lpt_state *lpt = get_safe_token(device);
+
+ lpt->strobe = TRUE;
+ lpt->autofd = TRUE;
+ lpt->init = FALSE;
+ lpt->select = TRUE;
+ lpt->irq_enabled = FALSE;
+ lpt->data = 0xff;
+}
+
+DEVICE_GET_INFO( pc_lpt )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(pc_lpt_state); break;
+ case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers --- */
+ case DEVINFO_PTR_MACHINE_CONFIG: info->machine_config = MACHINE_CONFIG_NAME(pc_lpt); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(pc_lpt); break;
+ case DEVINFO_FCT_STOP: /* Nothing */ break;
+ case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(pc_lpt); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "PC-LPT"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Parallel port"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright MESS Team"); break;
+ }
+}
+
+
+/***************************************************************************
+ IMPLEMENTATION
+***************************************************************************/
+
+static WRITE_LINE_DEVICE_HANDLER( pc_lpt_ack_w )
+{
+ pc_lpt_state *lpt = get_safe_token(device->owner());
+
+ if (lpt->irq_enabled && lpt->ack == TRUE && state == FALSE)
+ {
+ /* pulse irq when going from high to low */
+ lpt->out_irq_func(TRUE);
+ lpt->out_irq_func(FALSE);
+ }
+
+ lpt->ack = state;
+}
+
+
+READ8_DEVICE_HANDLER( pc_lpt_data_r )
+{
+ pc_lpt_state *lpt = get_safe_token(device);
+ // pull up mechanism for input lines, zeros are provided by pheripherial
+ return lpt->data & ~lpt->centronics->read(*device->machine().memory().first_space(), 0);
+}
+
+
+WRITE8_DEVICE_HANDLER( pc_lpt_data_w )
+{
+ pc_lpt_state *lpt = get_safe_token(device);
+ lpt->data = data;
+ lpt->centronics->write(*device->machine().memory().first_space(), 0, data);
+}
+
+
+READ8_DEVICE_HANDLER( pc_lpt_status_r )
+{
+ pc_lpt_state *lpt = get_safe_token(device);
+ UINT8 result = 0;
+
+ result |= lpt->centronics->fault_r() << 3;
+ result |= lpt->centronics->vcc_r() << 4; /* SELECT is connected to VCC */
+ result |= !lpt->centronics->pe_r() << 5;
+ result |= lpt->centronics->ack_r() << 6;
+ result |= !lpt->centronics->busy_r() << 7;
+
+ return result;
+}
+
+
+READ8_DEVICE_HANDLER( pc_lpt_control_r )
+{
+ pc_lpt_state *lpt = get_safe_token(device);
+ UINT8 result = 0;
+
+ /* return latch state */
+ result |= lpt->strobe << 0;
+ result |= lpt->autofd << 1;
+ result |= lpt->init << 2;
+ result |= lpt->select << 3;
+ result |= lpt->irq_enabled << 4;
+
+ return result;
+}
+
+
+WRITE8_DEVICE_HANDLER( pc_lpt_control_w )
+{
+ pc_lpt_state *lpt = get_safe_token(device);
+
+// logerror("pc_lpt_control_w: 0x%02x\n", data);
+
+ /* save to latch */
+ lpt->strobe = BIT(data, 0);
+ lpt->autofd = BIT(data, 1);
+ lpt->init = BIT(data, 2);
+ lpt->select = BIT(data, 3);
+ lpt->irq_enabled = BIT(data, 4);
+
+ /* output to centronics */
+ lpt->centronics->strobe_w(lpt->strobe);
+ lpt->centronics->autofeed_w(lpt->autofd);
+ lpt->centronics->init_prime_w(lpt->init);
+}
+
+
+READ8_DEVICE_HANDLER( pc_lpt_r )
+{
+ switch (offset)
+ {
+ case 0: return pc_lpt_data_r(device, 0);
+ case 1: return pc_lpt_status_r(device, 0);
+ case 2: return pc_lpt_control_r(device, 0);
+ }
+
+ /* if we reach this its an error */
+ logerror("PC-LPT %s: Read from invalid offset %x\n", device->tag(), offset);
+
+ return 0xff;
+}
+
+
+WRITE8_DEVICE_HANDLER( pc_lpt_w )
+{
+ switch (offset)
+ {
+ case 0: pc_lpt_data_w(device, 0, data); break;
+ case 1: break;
+ case 2: pc_lpt_control_w(device, 0, data); break;
+ }
+}
+
+DEFINE_LEGACY_DEVICE(PC_LPT, pc_lpt);
+
+static WRITE_LINE_DEVICE_HANDLER(pc_cpu_line)
+{
+ isa8_lpt_device *lpt = downcast<isa8_lpt_device *>(device->owner());
+ if (lpt->is_primary())
+ lpt->m_isa->irq7_w(state);
+ else
+ lpt->m_isa->irq5_w(state);
+}
+static const pc_lpt_interface pc_lpt_config =
+{
+ DEVCB_LINE(pc_cpu_line)
+};
+
+static MACHINE_CONFIG_FRAGMENT( lpt_config )
+ MCFG_PC_LPT_ADD("lpt", pc_lpt_config)
+MACHINE_CONFIG_END
+
+static INPUT_PORTS_START( lpt_dsw )
+ PORT_START("DSW")
+ PORT_DIPNAME( 0x01, 0x00, "Base address")
+ PORT_DIPSETTING( 0x00, "0x378" )
+ PORT_DIPSETTING( 0x01, "0x278" )
+INPUT_PORTS_END
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type ISA8_LPT = &device_creator<isa8_lpt_device>;
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor isa8_lpt_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( lpt_config );
+}
+
+//-------------------------------------------------
+// input_ports - device-specific input ports
+//-------------------------------------------------
+
+ioport_constructor isa8_lpt_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME( lpt_dsw );
+}
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// isa8_lpt_device - constructor
+//-------------------------------------------------
+
+isa8_lpt_device::isa8_lpt_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, ISA8_LPT, "Printer Adapter", tag, owner, clock),
+ device_isa8_card_interface(mconfig, *this)
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void isa8_lpt_device::device_start()
+{
+ set_isa_device();
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void isa8_lpt_device::device_reset()
+{
+ m_is_primary = (ioport("DSW")->read() & 1) ? false : true;
+ if (m_is_primary) {
+ m_isa->install_device(subdevice("lpt"), 0x0378, 0x037b, 0, 0, FUNC(pc_lpt_r), FUNC(pc_lpt_w) );
+ } else {
+ m_isa->install_device(subdevice("lpt"), 0x0278, 0x027b, 0, 0, FUNC(pc_lpt_r), FUNC(pc_lpt_w) );
+ }
+}