diff --git a/.gitattributes b/.gitattributes index f6275b779c5..915c4a4108e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -799,8 +799,8 @@ src/emu/machine/i8214.c svneol=native#text/plain src/emu/machine/i8214.h svneol=native#text/plain src/emu/machine/i8243.c svneol=native#text/plain src/emu/machine/i8243.h svneol=native#text/plain -src/emu/machine/i8255a.c svneol=native#text/plain -src/emu/machine/i8255a.h svneol=native#text/plain +src/emu/machine/i8255.c svneol=native#text/plain +src/emu/machine/i8255.h svneol=native#text/plain src/emu/machine/i8355.c svneol=native#text/plain src/emu/machine/i8355.h svneol=native#text/plain src/emu/machine/idectrl.c svneol=native#text/plain diff --git a/src/emu/emu.mak b/src/emu/emu.mak index 8910c24718f..c4803e44f75 100644 --- a/src/emu/emu.mak +++ b/src/emu/emu.mak @@ -175,7 +175,7 @@ EMUMACHINEOBJS = \ $(EMUMACHINE)/i8212.o \ $(EMUMACHINE)/i8214.o \ $(EMUMACHINE)/i8243.o \ - $(EMUMACHINE)/i8255a.o \ + $(EMUMACHINE)/i8255.o \ $(EMUMACHINE)/i8355.o \ $(EMUMACHINE)/idectrl.o \ $(EMUMACHINE)/ins8154.o \ diff --git a/src/emu/machine/i8255.c b/src/emu/machine/i8255.c new file mode 100644 index 00000000000..176567d21fa --- /dev/null +++ b/src/emu/machine/i8255.c @@ -0,0 +1,1053 @@ +/********************************************************************** + + Intel 8255(A) Programmable Peripheral Interface emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +**********************************************************************/ + +#include "i8255.h" +#include "machine/devhelpr.h" + + + +//************************************************************************** +// MACROS / CONSTANTS +//************************************************************************** + +#define LOG 0 + + +enum +{ + PORT_A = 0, + PORT_B, + PORT_C, + CONTROL +}; + + +enum +{ + GROUP_A = 0, + GROUP_B +}; + + +enum +{ + MODE_0 = 0, + MODE_1, + MODE_2 +}; + + +enum +{ + MODE_OUTPUT = 0, + MODE_INPUT, +}; + + +#define I8255A_CONTROL_PORT_C_LOWER_INPUT 0x01 +#define I8255A_CONTROL_PORT_B_INPUT 0x02 +#define I8255A_CONTROL_GROUP_B_MODE_1 0x04 +#define I8255A_CONTROL_PORT_C_UPPER_INPUT 0x08 +#define I8255A_CONTROL_PORT_A_INPUT 0x10 +#define I8255A_CONTROL_GROUP_A_MODE_MASK 0x60 +#define I8255A_CONTROL_MODE_SET 0x80 + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +const device_type I8255 = i8255_device_config::static_alloc_device_config; +const device_type I8255A = i8255_device_config::static_alloc_device_config; + + + +//************************************************************************** +// DEVICE CONFIGURATION +//************************************************************************** + +GENERIC_DEVICE_CONFIG_SETUP(i8255, "I8255") + + +//------------------------------------------------- +// device_config_complete - perform any +// operations now that the configuration is +// complete +//------------------------------------------------- + +void i8255_device_config::device_config_complete() +{ + // inherit a copy of the static data + const i8255_interface *intf = reinterpret_cast(static_config()); + if (intf != NULL) + *static_cast(this) = *intf; + + // or initialize to defaults if none provided + else + { + memset(&m_in_pa_func, 0, sizeof(m_in_pa_func)); + memset(&m_out_pa_func, 0, sizeof(m_out_pa_func)); + memset(&m_in_pb_func, 0, sizeof(m_in_pb_func)); + memset(&m_out_pb_func, 0, sizeof(m_out_pb_func)); + memset(&m_in_pc_func, 0, sizeof(m_in_pc_func)); + memset(&m_out_pc_func, 0, sizeof(m_out_pc_func)); + } +} + + + +//************************************************************************** +// INLINE HELPERS +//************************************************************************** + +//------------------------------------------------- +// check_interrupt - +//------------------------------------------------- + +inline void i8255_device::check_interrupt(int port) +{ + switch (group_mode(port)) + { + case MODE_1: + switch (port_mode(port)) + { + case MODE_INPUT: + if (m_inte[port] && m_ibf[port]) + { + if (LOG) logerror("I8255 Port %c INTR: 1\n", 'A' + port); + + m_intr[port] = 1; + } + break; + + case MODE_OUTPUT: + if (m_inte[port] && m_obf[port]) + { + if (LOG) logerror("I8255 Port %c INTR: 1\n", 'A' + port); + + m_intr[port] = 1; + } + break; + } + break; + + case MODE_2: + if ((m_inte1 && m_obf[port]) || (m_inte2 && m_ibf[port])) + { + if (LOG) logerror("I8255 Port %c INTR: 1\n", 'A' + port); + + m_intr[port] = 1; + } + break; + } + + output_pc(); +} + + +//------------------------------------------------- +// set_ibf - +//------------------------------------------------- + +inline void i8255_device::set_ibf(int port, int state) +{ + if (LOG) logerror("I8255 Port %c IBF: %u\n", 'A' + port, state); + + m_ibf[port] = state; + + check_interrupt(port); +} + + +//------------------------------------------------- +// set_obf - +//------------------------------------------------- + +inline void i8255_device::set_obf(int port, int state) +{ + if (LOG) logerror("I8255 Port %c OBF: %u\n", 'A' + port, state); + + m_obf[port] = state; + + check_interrupt(port); +} + + +//------------------------------------------------- +// set_inte - +//------------------------------------------------- + +inline void i8255_device::set_inte(int port, int state) +{ + if (LOG) logerror("I8255 Port %c INTE: %u\n", 'A' + port, state); + + m_inte[port] = state; + + check_interrupt(port); +} + + +//------------------------------------------------- +// set_inte1 - +//------------------------------------------------- + +inline void i8255_device::set_inte1(int state) +{ + if (LOG) logerror("I8255 Port A INTE1: %u\n", state); + + m_inte1 = state; + + check_interrupt(PORT_A); +} + + +//------------------------------------------------- +// set_inte2 - +//------------------------------------------------- + +inline void i8255_device::set_inte2(int state) +{ + if (LOG) logerror("I8255 Port A INTE2: %u\n", state); + + m_inte2 = state; + + check_interrupt(PORT_A); +} + + +//------------------------------------------------- +// set_intr - +//------------------------------------------------- + +inline void i8255_device::set_intr(int port, int state) +{ + if (LOG) logerror("I8255 Port %c INTR: %u\n", 'A' + port, state); + + m_intr[port] = state; + + output_pc(); +} + + +//------------------------------------------------- +// group_mode - +//------------------------------------------------- + +inline int i8255_device::group_mode(int group) +{ + int mode = 0; + + switch (group) + { + case GROUP_A: + switch ((m_control & I8255A_CONTROL_GROUP_A_MODE_MASK) >> 5) + { + case 0: mode = MODE_0; break; + case 1: mode = MODE_1; break; + case 2: case 3: mode = MODE_2; break; + } + break; + + case GROUP_B: + mode = m_control & I8255A_CONTROL_GROUP_B_MODE_1 ? MODE_1 : MODE_0; + break; + } + + return mode; +} + + +//------------------------------------------------- +// port_mode - +//------------------------------------------------- + +inline int i8255_device::port_mode(int port) +{ + int mode = 0; + + switch (port) + { + case PORT_A: mode = m_control & I8255A_CONTROL_PORT_A_INPUT ? MODE_INPUT : MODE_OUTPUT; break; + case PORT_B: mode = m_control & I8255A_CONTROL_PORT_B_INPUT ? MODE_INPUT : MODE_OUTPUT; break; + } + + return mode; +} + + +//------------------------------------------------- +// port_c_lower_mode - +//------------------------------------------------- + +inline int i8255_device::port_c_lower_mode() +{ + return m_control & I8255A_CONTROL_PORT_C_LOWER_INPUT ? MODE_INPUT : MODE_OUTPUT; +} + + +//------------------------------------------------- +// port_c_upper_mode - +//------------------------------------------------- + +inline int i8255_device::port_c_upper_mode() +{ + return m_control & I8255A_CONTROL_PORT_C_UPPER_INPUT ? MODE_INPUT : MODE_OUTPUT; +} + + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// i8255_device - constructor +//------------------------------------------------- + +i8255_device::i8255_device(running_machine &_machine, const i8255_device_config &config) + : device_t(_machine, config), + m_config(config) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void i8255_device::device_start() +{ + // resolve callbacks + devcb_resolve_read8(&m_in_port_func[PORT_A], &m_config.m_in_pa_func, this); + devcb_resolve_write8(&m_out_port_func[PORT_A], &m_config.m_out_pa_func, this); + devcb_resolve_read8(&m_in_port_func[PORT_B], &m_config.m_in_pb_func, this); + devcb_resolve_write8(&m_out_port_func[PORT_B], &m_config.m_out_pb_func, this); + devcb_resolve_read8(&m_in_port_func[PORT_C], &m_config.m_in_pc_func, this); + devcb_resolve_write8(&m_out_port_func[PORT_C], &m_config.m_out_pc_func, this); + + // register for state saving + save_item(NAME(m_control)); + save_item(NAME(m_output)); + save_item(NAME(m_input)); + save_item(NAME(m_ibf)); + save_item(NAME(m_obf)); + save_item(NAME(m_inte)); + save_item(NAME(m_inte1)); + save_item(NAME(m_inte2)); + save_item(NAME(m_intr)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void i8255_device::device_reset() +{ + set_mode(0x9b); +} + + +//------------------------------------------------- +// read_mode0 - +//------------------------------------------------- + +UINT8 i8255_device::read_mode0(int port) +{ + UINT8 data = 0; + + if (port_mode(port) == MODE_OUTPUT) + { + // read data from output latch + data = m_output[port]; + } + else + { + // read data from port + data = devcb_call_read8(&m_in_port_func[port], 0); + } + + return data; +} + + +//------------------------------------------------- +// read_mode1 - +//------------------------------------------------- + +UINT8 i8255_device::read_mode1(int port) +{ + UINT8 data = 0; + + if (port_mode(port) == MODE_OUTPUT) + { + // read data from output latch + data = m_output[port]; + } + else + { + // read data from input latch + data = m_input[port]; + + // clear input buffer full flag + set_ibf(port, 0); + + // clear interrupt + set_intr(port, 0); + + // clear input latch + m_input[port] = 0; + } + + return data; +} + + +//------------------------------------------------- +// read_mode2 - +//------------------------------------------------- + +UINT8 i8255_device::read_mode2() +{ + UINT8 data = 0; + + // read data from input latch + data = m_input[PORT_A]; + + // clear input buffer full flag + set_ibf(PORT_A, 0); + + // clear interrupt + set_intr(PORT_A, 0); + + // clear input latch + m_input[PORT_A] = 0; + + return data; +} + + +//------------------------------------------------- +// read_pc - +//------------------------------------------------- + +UINT8 i8255_device::read_pc() +{ + UINT8 data = 0; + UINT8 mask = 0; + + // PC upper + switch (group_mode(GROUP_A)) + { + case MODE_0: + if (port_c_upper_mode() == MODE_OUTPUT) + { + // read data from output latch + data |= m_output[PORT_C] & 0xf0; + } + else + { + // read data from port + mask |= 0xf0; + } + break; + + case MODE_1: + data |= m_intr[PORT_A] ? 0x08 : 0x00; + + if (port_mode(PORT_A) == MODE_OUTPUT) + { + data |= m_obf[PORT_A] ? 0x80 : 0x00; + data |= m_inte[PORT_A] ? 0x40 : 0x00; + mask |= 0x30; + } + else + { + data |= m_ibf[PORT_A] ? 0x20 : 0x00; + data |= m_inte[PORT_A] ? 0x10 : 0x00; + mask |= 0xc0; + } + break; + + case MODE_2: + data |= m_intr[PORT_A] ? 0x08 : 0x00; + data |= m_inte2 ? 0x10 : 0x00; + data |= m_ibf[PORT_A] ? 0x20 : 0x00; + data |= m_inte1 ? 0x40 : 0x00; + data |= m_obf[PORT_A] ? 0x80 : 0x00; + break; + } + + // PC lower + switch (group_mode(GROUP_B)) + { + case MODE_0: + if (port_c_lower_mode() == MODE_OUTPUT) + { + // read data from output latch + data |= m_output[PORT_C] & 0x0f; + } + else + { + // read data from port + mask |= 0x0f; + } + break; + + case MODE_1: + data |= m_inte[PORT_B] ? 0x04 : 0x00; + data |= m_intr[PORT_B] ? 0x01 : 0x00; + + if (port_mode(PORT_B) == MODE_OUTPUT) + { + data |= m_obf[PORT_B] ? 0x02 : 0x00; + } + else + { + data |= m_ibf[PORT_B] ? 0x02 : 0x00; + } + } + + if (mask) + { + // read data from port + data |= devcb_call_read8(&m_in_port_func[PORT_C], 0) & mask; + } + + return data; +} + + +//------------------------------------------------- +// write_mode0 - +//------------------------------------------------- + +void i8255_device::write_mode0(int port, UINT8 data) +{ + if (port_mode(port) == MODE_OUTPUT) + { + // latch output data + m_output[port] = data; + + // write data to port + devcb_call_write8(&m_out_port_func[port], 0, data); + } +} + + +//------------------------------------------------- +// write_mode1 - +//------------------------------------------------- + +void i8255_device::write_mode1(int port, UINT8 data) +{ + if (port_mode(port) == MODE_OUTPUT) + { + // latch output data + m_output[port] = data; + + // write data to port + devcb_call_write8(&m_out_port_func[port], 0, data); + + // set output buffer full flag + set_obf(port, 0); + + // clear interrupt + set_intr(port, 0); + } +} + + +//------------------------------------------------- +// write_mode2 - +//------------------------------------------------- + +void i8255_device::write_mode2(UINT8 data) +{ + // latch output data + m_output[PORT_A] = data; + + // write data to port + devcb_call_write8(&m_out_port_func[PORT_A], 0, data); + + // set output buffer full flag + set_obf(PORT_A, 0); + + // clear interrupt + set_intr(PORT_A, 0); +} + + +//------------------------------------------------- +// write_pc - +//------------------------------------------------- + +void i8255_device::write_pc(UINT8 data) +{ + int changed = 0; + + if (group_mode(GROUP_A) == MODE_0) + { + // PC upper + if (port_c_upper_mode() == MODE_OUTPUT) + { + m_output[PORT_C] = (data & 0xf0) | (m_output[PORT_C] & 0x0f); + changed = 1; + } + + // PC lower + if (port_c_lower_mode() == MODE_OUTPUT) + { + m_output[PORT_C] = (m_output[PORT_C] & 0xf0) | (data & 0x0f); + changed = 1; + } + } + + if (changed) + { + output_pc(); + } +} + + +//------------------------------------------------- +// output_pc - +//------------------------------------------------- + +void i8255_device::output_pc() +{ + UINT8 data = 0; + UINT8 mask = 0; + + // PC upper + switch (group_mode(GROUP_A)) + { + case MODE_0: + if (port_c_upper_mode() == MODE_OUTPUT) + { + mask |= 0xf0; + } + else + { + // TTL inputs float high + data |= 0xf0; + } + break; + + case MODE_1: + data |= m_intr[PORT_A] ? 0x08 : 0x00; + + if (port_mode(PORT_A) == MODE_OUTPUT) + { + data |= m_obf[PORT_A] ? 0x80 : 0x00; + mask |= 0x30; + } + else + { + data |= m_ibf[PORT_A] ? 0x20 : 0x00; + mask |= 0xc0; + } + break; + + case MODE_2: + data |= m_intr[PORT_A] ? 0x08 : 0x00; + data |= m_ibf[PORT_A] ? 0x20 : 0x00; + data |= m_obf[PORT_A] ? 0x80 : 0x00; + break; + } + + // PC lower + switch (group_mode(GROUP_B)) + { + case MODE_0: + if (port_c_lower_mode() == MODE_OUTPUT) + { + mask |= 0x0f; + } + else + { + // TTL inputs float high + data |= 0x0f; + } + break; + + case MODE_1: + data |= m_intr[PORT_B] ? 0x01 : 0x00; + + if (port_mode(PORT_B) == MODE_OUTPUT) + { + data |= m_obf[PORT_B] ? 0x02 : 0x00; + } + else + { + data |= m_ibf[PORT_B] ? 0x02 : 0x00; + } + } + + data |= m_output[PORT_C] & mask; + + devcb_call_write8(&m_out_port_func[PORT_C], 0, data); +} + + +//------------------------------------------------- +// set_mode - +//------------------------------------------------- + +void i8255_device::set_mode(UINT8 data) +{ + m_control = data; + + // group A + m_output[PORT_A] = 0; + m_input[PORT_A] = 0; + m_ibf[PORT_A] = 0; + m_obf[PORT_A] = 1; + m_inte[PORT_A] = 0; + m_inte1 = 0; + m_inte2 = 0; + + if (port_mode(PORT_A) == MODE_OUTPUT) + { + devcb_call_write8(&m_out_port_func[PORT_A], 0, m_output[PORT_A]); + } + else + { + // TTL inputs float high + devcb_call_write8(&m_out_port_func[PORT_A], 0, 0xff); + } + + if (LOG) logerror("I8255 '%s' Group A Mode: %u\n", tag(), group_mode(GROUP_A)); + if (LOG) logerror("I8255 '%s' Port A Mode: %s\n", tag(), (port_mode(PORT_A) == MODE_OUTPUT) ? "output" : "input"); + if (LOG) logerror("I8255 '%s' Port C Upper Mode: %s\n", tag(), (port_c_upper_mode() == MODE_OUTPUT) ? "output" : "input"); + if (LOG) logerror("I8255 '%s' Group B Mode: %u\n", tag(), group_mode(GROUP_B)); + if (LOG) logerror("I8255 '%s' Port B Mode: %s\n", tag(), (port_mode(PORT_B) == MODE_OUTPUT) ? "output" : "input"); + if (LOG) logerror("I8255 '%s' Port C Lower Mode: %s\n", tag(), (port_c_lower_mode() == MODE_OUTPUT) ? "output" : "input"); + + // group B + m_output[PORT_B] = 0; + m_input[PORT_B] = 0; + m_ibf[PORT_B] = 0; + m_obf[PORT_B] = 1; + m_inte[PORT_B] = 0; + + if (port_mode(PORT_B) == MODE_OUTPUT) + { + devcb_call_write8(&m_out_port_func[PORT_B], 0, m_output[PORT_B]); + } + else + { + // TTL inputs float high + devcb_call_write8(&m_out_port_func[PORT_B], 0, 0xff); + } + + m_output[PORT_C] = 0; + m_input[PORT_C] = 0; + + output_pc(); +} + + +//------------------------------------------------- +// set_pc_bit - +//------------------------------------------------- + +void i8255_device::set_pc_bit(int bit, int state) +{ + // set output latch bit + m_output[PORT_C] &= ~(1 << bit); + m_output[PORT_C] |= state << bit; + + switch (group_mode(GROUP_A)) + { + case MODE_1: + if (port_mode(PORT_A) == MODE_OUTPUT) + { + switch (bit) + { + case 3: set_intr(PORT_A, state); break; + case 6: set_inte(PORT_A, state); break; + case 7: set_obf(PORT_A, state); break; + } + } + else + { + switch (bit) + { + case 3: set_intr(PORT_A, state); break; + case 4: set_inte(PORT_A, state); break; + case 5: set_ibf(PORT_A, state); break; + } + } + break; + + case MODE_2: + switch (bit) + { + case 3: set_intr(PORT_A, state); break; + case 4: set_inte2(state); break; + case 5: set_ibf(PORT_A, state); break; + case 6: set_inte1(state); break; + case 7: set_obf(PORT_A, state); break; + } + break; + } + + if (group_mode(GROUP_B) == MODE_1) + { + switch (bit) + { + case 0: set_intr(PORT_B, state); break; + case 1: + if (port_mode(PORT_B) == MODE_OUTPUT) + set_obf(PORT_B, state); + else + set_ibf(PORT_B, state); + break; + case 2: set_inte(PORT_B, state); break; + } + } + + output_pc(); +} + + +//------------------------------------------------- +// read - +//------------------------------------------------- + +READ8_MEMBER( i8255_device::read ) +{ + UINT8 data = 0; + + switch (offset & 0x03) + { + case PORT_A: + switch (group_mode(GROUP_A)) + { + case MODE_0: data = read_mode0(PORT_A); break; + case MODE_1: data = read_mode1(PORT_A); break; + case MODE_2: data = read_mode2(); break; + } + if (LOG) logerror("I8255 '%s' Port A Read: %02x\n", tag(), data); + break; + + case PORT_B: + switch (group_mode(GROUP_B)) + { + case MODE_0: data = read_mode0(PORT_B); break; + case MODE_1: data = read_mode1(PORT_B); break; + } + if (LOG) logerror("I8255 '%s' Port B Read: %02x\n", tag(), data); + break; + + case PORT_C: + data = read_pc(); + //if (LOG) logerror("I8255 '%s' Port C Read: %02x\n", tag(), data); + break; + + case CONTROL: + data = m_control; + if (LOG) logerror("I8255 '%s' Mode Control Word Read: %02x\n", tag(), data); + break; + } + + return data; +} + + +//------------------------------------------------- +// write - +//------------------------------------------------- + +WRITE8_MEMBER( i8255_device::write ) +{ + switch (offset & 0x03) + { + case PORT_A: + if (LOG) logerror("I8255 '%s' Port A Write: %02x\n", tag(), data); + + switch (group_mode(GROUP_A)) + { + case MODE_0: write_mode0(PORT_A, data); break; + case MODE_1: write_mode1(PORT_A, data); break; + case MODE_2: write_mode2(data); break; + } + break; + + case PORT_B: + if (LOG) logerror("I8255 '%s' Port B Write: %02x\n", tag(), data); + + switch (group_mode(GROUP_B)) + { + case MODE_0: write_mode0(PORT_B, data); break; + case MODE_1: write_mode1(PORT_B, data); break; + } + break; + + case PORT_C: + if (LOG) logerror("I8255 '%s' Port C Write: %02x\n", tag(), data); + + write_pc(data); + break; + + case CONTROL: + if (data & I8255A_CONTROL_MODE_SET) + { + if (LOG) logerror("I8255 '%s' Mode Control Word: %02x\n", tag(), data); + + set_mode(data); + } + else + { + int bit = (data >> 1) & 0x07; + int state = BIT(data, 0); + + if (LOG) logerror("I8255 '%s' %s Bit %u\n", tag(), state ? "Set" : "Reset", bit); + + set_pc_bit(bit, state); + } + break; + } +} + + +//------------------------------------------------- +// pa_r - +//------------------------------------------------- + +READ8_MEMBER( i8255_device::pa_r ) +{ + return pa_r(); +} + + +//------------------------------------------------- +// pb_r - port A read +//------------------------------------------------- + +UINT8 i8255_device::pa_r() +{ + UINT8 data = 0xff; + + if (port_mode(PORT_A) == MODE_OUTPUT) + { + data = m_output[PORT_A]; + } + + return data; +} + + +//------------------------------------------------- +// pb_r - +//------------------------------------------------- + +READ8_MEMBER( i8255_device::pb_r ) +{ + return pb_r(); +} + + +//------------------------------------------------- +// pb_r - port B read +//------------------------------------------------- + +UINT8 i8255_device::pb_r() +{ + UINT8 data = 0xff; + + if (port_mode(PORT_B) == MODE_OUTPUT) + { + data = m_output[PORT_B]; + } + + return data; +} + + +//------------------------------------------------- +// pc2_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( i8255_device::pc2_w ) +{ + if (group_mode(GROUP_B) == 1) + { + if (port_mode(PORT_B) == MODE_OUTPUT) + { + // port B acknowledge + if (!m_obf[PORT_B] && !state) + { + if (LOG) logerror("I8255 '%s' Port B Acknowledge\n", tag()); + + // clear output buffer flag + set_obf(PORT_B, 1); + } + } + else + { + // port B strobe + if (!m_ibf[PORT_B] && !state) + { + if (LOG) logerror("I8255 '%s' Port B Strobe\n", tag()); + + // read port into latch + m_input[PORT_B] = devcb_call_read8(&m_in_port_func[PORT_B], 0); + + // set input buffer flag + set_ibf(PORT_B, 1); + } + } + } +} + + +//------------------------------------------------- +// pc4_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( i8255_device::pc4_w ) +{ + if ((group_mode(GROUP_A) == 2) || ((group_mode(GROUP_A) == 1) && (port_mode(PORT_A) == MODE_INPUT))) + { + // port A strobe + if (!m_ibf[PORT_A] && !state) + { + if (LOG) logerror("I8255 '%s' Port A Strobe\n", tag()); + + // read port into latch + m_input[PORT_A] = devcb_call_read8(&m_in_port_func[PORT_A], 0); + + // set input buffer flag + set_ibf(PORT_A, 1); + } + } +} + + +//------------------------------------------------- +// pc6_w - +//------------------------------------------------- + +WRITE_LINE_MEMBER( i8255_device::pc6_w ) +{ + if ((group_mode(GROUP_A) == 2) || ((group_mode(GROUP_A) == 1) && (port_mode(PORT_A) == MODE_OUTPUT))) + { + // port A acknowledge + if (!m_obf[PORT_A] && !state) + { + if (LOG) logerror("I8255 '%s' Port A Acknowledge\n", tag()); + + // clear output buffer flag + set_obf(PORT_A, 1); + } + } +} diff --git a/src/emu/machine/i8255.h b/src/emu/machine/i8255.h new file mode 100644 index 00000000000..2d0d242dbdf --- /dev/null +++ b/src/emu/machine/i8255.h @@ -0,0 +1,179 @@ +/********************************************************************** + + Intel 8255(A) Programmable Peripheral Interface emulation + + Copyright MESS Team. + Visit http://mamedev.org for licensing and usage restrictions. + +********************************************************************** + _____ _____ + PA3 1 |* \_/ | 40 PA4 + PA2 2 | | 39 PA5 + PA1 3 | | 38 PA6 + PA0 4 | | 37 PA7 + _RD 5 | | 36 WR + _CS 6 | | 35 RESET + GND 7 | | 34 D0 + A1 8 | | 33 D1 + A0 9 | | 32 D2 + PC7 10 | 8255 | 31 D3 + PC6 11 | 8255A | 30 D4 + PC5 12 | | 29 D5 + PC4 13 | | 28 D6 + PC0 14 | | 27 D7 + PC1 15 | | 26 Vcc + PC2 16 | | 25 PB7 + PC3 17 | | 24 PB6 + PB0 18 | | 23 PB5 + PB1 19 | | 22 PB4 + PB2 20 |_____________| 21 PB3 + +**********************************************************************/ + +#pragma once + +#ifndef __I8255__ +#define __I8255__ + +#include "emu.h" + + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_I8255_ADD(_tag, _intrf) \ + MCFG_DEVICE_ADD(_tag, I8255, 0) \ + MCFG_DEVICE_CONFIG(_intrf) + + +#define MCFG_I8255A_ADD(_tag, _intrf) \ + MCFG_DEVICE_ADD(_tag, I8255A, 0) \ + MCFG_DEVICE_CONFIG(_intrf) + + +#define I8255_INTERFACE(name) \ + const i8255_interface (name) = + + +#define I8255A_INTERFACE(name) \ + const i8255_interface (name) = + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> i8255_interface + +struct i8255_interface +{ + devcb_read8 m_in_pa_func; + devcb_write8 m_out_pa_func; + devcb_read8 m_in_pb_func; + devcb_write8 m_out_pb_func; + devcb_read8 m_in_pc_func; + devcb_write8 m_out_pc_func; +}; + + +// ======================> i8255_device_config + +class i8255_device_config : public device_config, + public i8255_interface +{ + friend class i8255_device; + + // construction/destruction + i8255_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); + +public: + // allocators + static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock); + virtual device_t *alloc_device(running_machine &machine) const; + +protected: + // device_config overrides + virtual void device_config_complete(); +}; + + +// ======================> i8255_device + +class i8255_device : public device_t +{ + friend class i8255_device_config; + + // construction/destruction + i8255_device(running_machine &_machine, const i8255_device_config &_config); + +public: + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); + + DECLARE_READ8_MEMBER( pa_r ); + UINT8 pa_r(); + + DECLARE_READ8_MEMBER( pb_r ); + UINT8 pb_r(); + + DECLARE_WRITE_LINE_MEMBER( pc2_w ); + DECLARE_WRITE_LINE_MEMBER( pc4_w ); + DECLARE_WRITE_LINE_MEMBER( pc6_w ); + +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + +private: + inline void check_interrupt(int port); + inline void set_ibf(int port, int state); + inline void set_obf(int port, int state); + inline void set_inte(int port, int state); + inline void set_inte1(int state); + inline void set_inte2(int state); + inline void set_intr(int port, int state); + inline int group_mode(int group); + inline int port_mode(int port); + inline int port_c_lower_mode(); + inline int port_c_upper_mode(); + + UINT8 read_mode0(int port); + UINT8 read_mode1(int port); + UINT8 read_mode2(); + UINT8 read_pc(); + void write_mode0(int port, UINT8 data); + void write_mode1(int port, UINT8 data); + void write_mode2(UINT8 data); + void write_pc(UINT8 data); + void output_pc(); + void set_mode(UINT8 data); + void set_pc_bit(int bit, int state); + + devcb_resolved_read8 m_in_port_func[3]; + devcb_resolved_write8 m_out_port_func[3]; + + UINT8 m_control; // mode control word + UINT8 m_output[3]; // output latch + UINT8 m_input[3]; // input latch + + int m_ibf[2]; // input buffer full flag + int m_obf[2]; // output buffer full flag, negative logic + int m_inte[2]; // interrupt enable + int m_inte1; // interrupt enable + int m_inte2; // interrupt enable + int m_intr[2]; // interrupt + + const i8255_device_config &m_config; +}; + + +// device type definition +extern const device_type I8255; +extern const device_type I8255A; + + + +#endif diff --git a/src/emu/machine/i8255a.c b/src/emu/machine/i8255a.c deleted file mode 100644 index cdf4b91c2c0..00000000000 --- a/src/emu/machine/i8255a.c +++ /dev/null @@ -1,909 +0,0 @@ -/********************************************************************** - - Intel 8255A Programmable Peripheral Interface emulation - - Copyright MESS Team. - Visit http://mamedev.org for licensing and usage restrictions. - -**********************************************************************/ - -#include "emu.h" -#include "i8255a.h" - -/*************************************************************************** - PARAMETERS -***************************************************************************/ - -#define LOG 0 - -enum -{ - PORT_A = 0, - PORT_B, - PORT_C, - CONTROL -}; - -enum -{ - GROUP_A = 0, - GROUP_B -}; - -enum -{ - MODE_0 = 0, - MODE_1, - MODE_2 -}; - -enum -{ - MODE_OUTPUT = 0, - MODE_INPUT, -}; - -#define I8255A_CONTROL_PORT_C_LOWER_INPUT 0x01 -#define I8255A_CONTROL_PORT_B_INPUT 0x02 -#define I8255A_CONTROL_GROUP_B_MODE_1 0x04 -#define I8255A_CONTROL_PORT_C_UPPER_INPUT 0x08 -#define I8255A_CONTROL_PORT_A_INPUT 0x10 -#define I8255A_CONTROL_GROUP_A_MODE_MASK 0x60 -#define I8255A_CONTROL_MODE_SET 0x80 - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -typedef struct _i8255a_t i8255a_t; -struct _i8255a_t -{ - devcb_resolved_read8 in_port_func[3]; - devcb_resolved_write8 out_port_func[3]; - - UINT8 control; /* mode control word */ - UINT8 output[3]; /* output latch */ - UINT8 input[3]; /* input latch */ - - int ibf[2]; /* input buffer full flag */ - int obf[2]; /* output buffer full flag, negative logic */ - int inte[2]; /* interrupt enable */ - int inte1; /* interrupt enable */ - int inte2; /* interrupt enable */ - int intr[2]; /* interrupt */ -}; - -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ - -INLINE i8255a_t *get_safe_token(device_t *device) -{ - assert(device != NULL); - - return (i8255a_t *)downcast(device)->token(); -} - -INLINE const i8255a_interface *get_interface(device_t *device) -{ - assert(device != NULL); - assert((device->type() == I8255A)); - return (const i8255a_interface *) device->baseconfig().static_config(); -} - -INLINE int group_mode(i8255a_t *i8255a, int group) -{ - int mode = 0; - - switch (group) - { - case GROUP_A: - switch ((i8255a->control & I8255A_CONTROL_GROUP_A_MODE_MASK) >> 5) - { - case 0: mode = MODE_0; break; - case 1: mode = MODE_1; break; - case 2: case 3: mode = MODE_2; break; - } - break; - - case GROUP_B: - mode = i8255a->control & I8255A_CONTROL_GROUP_B_MODE_1 ? MODE_1 : MODE_0; - break; - } - - return mode; -} - -INLINE int port_mode(i8255a_t *i8255a, int port) -{ - int mode = 0; - - switch (port) - { - case PORT_A: mode = i8255a->control & I8255A_CONTROL_PORT_A_INPUT ? MODE_INPUT : MODE_OUTPUT; break; - case PORT_B: mode = i8255a->control & I8255A_CONTROL_PORT_B_INPUT ? MODE_INPUT : MODE_OUTPUT; break; - } - - return mode; -} - -INLINE int port_c_lower_mode(i8255a_t *i8255a) -{ - return i8255a->control & I8255A_CONTROL_PORT_C_LOWER_INPUT ? MODE_INPUT : MODE_OUTPUT; -} - -INLINE int port_c_upper_mode(i8255a_t *i8255a) -{ - return i8255a->control & I8255A_CONTROL_PORT_C_UPPER_INPUT ? MODE_INPUT : MODE_OUTPUT; -} - -/*************************************************************************** - IMPLEMENTATION -***************************************************************************/ - -static void output_pc(i8255a_t *i8255a) -{ - UINT8 data = 0; - UINT8 mask = 0; - - /* PC upper */ - switch (group_mode(i8255a, GROUP_A)) - { - case MODE_0: - if (port_c_upper_mode(i8255a) == MODE_OUTPUT) - { - mask |= 0xf0; - } - else - { - /* TTL inputs float high */ - data |= 0xf0; - } - break; - - case MODE_1: - data |= i8255a->intr[PORT_A] ? 0x08 : 0x00; - - if (port_mode(i8255a, PORT_A) == MODE_OUTPUT) - { - data |= i8255a->obf[PORT_A] ? 0x80 : 0x00; - mask |= 0x30; - } - else - { - data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00; - mask |= 0xc0; - } - break; - - case MODE_2: - data |= i8255a->intr[PORT_A] ? 0x08 : 0x00; - data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00; - data |= i8255a->obf[PORT_A] ? 0x80 : 0x00; - break; - } - - /* PC lower */ - switch (group_mode(i8255a, GROUP_B)) - { - case MODE_0: - if (port_c_lower_mode(i8255a) == MODE_OUTPUT) - { - mask |= 0x0f; - } - else - { - /* TTL inputs float high */ - data |= 0x0f; - } - break; - - case MODE_1: - data |= i8255a->intr[PORT_B] ? 0x01 : 0x00; - - if (port_mode(i8255a, PORT_B) == MODE_OUTPUT) - { - data |= i8255a->obf[PORT_B] ? 0x02 : 0x00; - } - else - { - data |= i8255a->ibf[PORT_B] ? 0x02 : 0x00; - } - } - - data |= i8255a->output[PORT_C] & mask; - - devcb_call_write8(&i8255a->out_port_func[PORT_C], 0, data); -} - -static void check_interrupt(i8255a_t *i8255a, int port) -{ - switch (group_mode(i8255a, port)) - { - case MODE_1: - switch (port_mode(i8255a, port)) - { - case MODE_INPUT: - if (i8255a->inte[port] && i8255a->ibf[port]) - { - if (LOG) logerror("8255A Port %c INTR: 1\n", 'A' + port); - - i8255a->intr[port] = 1; - } - break; - - case MODE_OUTPUT: - if (i8255a->inte[port] && i8255a->obf[port]) - { - if (LOG) logerror("8255A Port %c INTR: 1\n", 'A' + port); - - i8255a->intr[port] = 1; - } - break; - } - break; - - case MODE_2: - if ((i8255a->inte1 && i8255a->obf[port]) || (i8255a->inte2 && i8255a->ibf[port])) - { - if (LOG) logerror("8255A Port %c INTR: 1\n", 'A' + port); - - i8255a->intr[port] = 1; - } - break; - } - - output_pc(i8255a); -} - -static void set_ibf(i8255a_t *i8255a, int port, int state) -{ - if (LOG) logerror("8255A Port %c IBF: %u\n", 'A' + port, state); - - i8255a->ibf[port] = state; - - check_interrupt(i8255a, port); -} - -static void set_obf(i8255a_t *i8255a, int port, int state) -{ - if (LOG) logerror("8255A Port %c OBF: %u\n", 'A' + port, state); - - i8255a->obf[port] = state; - - check_interrupt(i8255a, port); -} - -static void set_inte(i8255a_t *i8255a, int port, int state) -{ - if (LOG) logerror("8255A Port %c INTE: %u\n", 'A' + port, state); - - i8255a->inte[port] = state; - - check_interrupt(i8255a, port); -} - -static void set_inte1(i8255a_t *i8255a, int state) -{ - if (LOG) logerror("8255A Port A INTE1: %u\n", state); - - i8255a->inte1 = state; - - check_interrupt(i8255a, PORT_A); -} - -static void set_inte2(i8255a_t *i8255a, int state) -{ - if (LOG) logerror("8255A Port A INTE2: %u\n", state); - - i8255a->inte2 = state; - - check_interrupt(i8255a, PORT_A); -} - -static void set_intr(i8255a_t *i8255a, int port, int state) -{ - if (LOG) logerror("8255A Port %c INTR: %u\n", 'A' + port, state); - - i8255a->intr[port] = state; - - output_pc(i8255a); -} - -static UINT8 read_mode0(i8255a_t *i8255a, int port) -{ - UINT8 data = 0; - - if (port_mode(i8255a, port) == MODE_OUTPUT) - { - /* read data from output latch */ - data = i8255a->output[port]; - } - else - { - /* read data from port */ - data = devcb_call_read8(&i8255a->in_port_func[port], 0); - } - - return data; -} - -static UINT8 read_mode1(i8255a_t *i8255a, int port) -{ - UINT8 data = 0; - - if (port_mode(i8255a, port) == MODE_OUTPUT) - { - /* read data from output latch */ - data = i8255a->output[port]; - } - else - { - /* read data from input latch */ - data = i8255a->input[port]; - - /* clear input buffer full flag */ - set_ibf(i8255a, port, 0); - - /* clear interrupt */ - set_intr(i8255a, port, 0); - - /* clear input latch */ - i8255a->input[port] = 0; - } - - return data; -} - -static UINT8 read_mode2(i8255a_t *i8255a) -{ - UINT8 data = 0; - - /* read data from input latch */ - data = i8255a->input[PORT_A]; - - /* clear input buffer full flag */ - set_ibf(i8255a, PORT_A, 0); - - /* clear interrupt */ - set_intr(i8255a, PORT_A, 0); - - /* clear input latch */ - i8255a->input[PORT_A] = 0; - - return data; -} - -static UINT8 read_pc(i8255a_t *i8255a) -{ - UINT8 data = 0; - UINT8 mask = 0; - - /* PC upper */ - switch (group_mode(i8255a, GROUP_A)) - { - case MODE_0: - if (port_c_upper_mode(i8255a) == MODE_OUTPUT) - { - /* read data from output latch */ - data |= i8255a->output[PORT_C] & 0xf0; - } - else - { - /* read data from port */ - mask |= 0xf0; - } - break; - - case MODE_1: - data |= i8255a->intr[PORT_A] ? 0x08 : 0x00; - - if (port_mode(i8255a, PORT_A) == MODE_OUTPUT) - { - data |= i8255a->obf[PORT_A] ? 0x80 : 0x00; - data |= i8255a->inte[PORT_A] ? 0x40 : 0x00; - mask |= 0x30; - } - else - { - data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00; - data |= i8255a->inte[PORT_A] ? 0x10 : 0x00; - mask |= 0xc0; - } - break; - - case MODE_2: - data |= i8255a->intr[PORT_A] ? 0x08 : 0x00; - data |= i8255a->inte2 ? 0x10 : 0x00; - data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00; - data |= i8255a->inte1 ? 0x40 : 0x00; - data |= i8255a->obf[PORT_A] ? 0x80 : 0x00; - break; - } - - /* PC lower */ - switch (group_mode(i8255a, GROUP_B)) - { - case MODE_0: - if (port_c_lower_mode(i8255a) == MODE_OUTPUT) - { - /* read data from output latch */ - data |= i8255a->output[PORT_C] & 0x0f; - } - else - { - /* read data from port */ - mask |= 0x0f; - } - break; - - case MODE_1: - data |= i8255a->inte[PORT_B] ? 0x04 : 0x00; - data |= i8255a->intr[PORT_B] ? 0x01 : 0x00; - - if (port_mode(i8255a, PORT_B) == MODE_OUTPUT) - { - data |= i8255a->obf[PORT_B] ? 0x02 : 0x00; - } - else - { - data |= i8255a->ibf[PORT_B] ? 0x02 : 0x00; - } - } - - if (mask) - { - /* read data from port */ - data |= devcb_call_read8(&i8255a->in_port_func[PORT_C], 0) & mask; - } - - return data; -} - -READ8_DEVICE_HANDLER( i8255a_r ) -{ - i8255a_t *i8255a = get_safe_token(device); - - UINT8 data = 0; - - switch (offset & 0x03) - { - case PORT_A: - switch (group_mode(i8255a, GROUP_A)) - { - case MODE_0: data = read_mode0(i8255a, PORT_A); break; - case MODE_1: data = read_mode1(i8255a, PORT_A); break; - case MODE_2: data = read_mode2(i8255a); break; - } - if (LOG) logerror("8255A '%s' Port A Read: %02x\n", device->tag(), data); - break; - - case PORT_B: - switch (group_mode(i8255a, GROUP_B)) - { - case MODE_0: data = read_mode0(i8255a, PORT_B); break; - case MODE_1: data = read_mode1(i8255a, PORT_B); break; - } - if (LOG) logerror("8255A '%s' Port B Read: %02x\n", device->tag(), data); - break; - - case PORT_C: - data = read_pc(i8255a); - //if (LOG) logerror("8255A '%s' Port C Read: %02x\n", device->tag(), data); - break; - - case CONTROL: - data = i8255a->control; - if (LOG) logerror("8255A '%s' Mode Control Word Read: %02x\n", device->tag(), data); - break; - } - - return data; -} - -static void write_mode0(i8255a_t *i8255a, int port, UINT8 data) -{ - if (port_mode(i8255a, port) == MODE_OUTPUT) - { - /* latch output data */ - i8255a->output[port] = data; - - /* write data to port */ - devcb_call_write8(&i8255a->out_port_func[port], 0, data); - } -} - -static void write_mode1(i8255a_t *i8255a, int port, UINT8 data) -{ - if (port_mode(i8255a, port) == MODE_OUTPUT) - { - /* latch output data */ - i8255a->output[port] = data; - - /* write data to port */ - devcb_call_write8(&i8255a->out_port_func[port], 0, data); - - /* set output buffer full flag */ - set_obf(i8255a, port, 0); - - /* clear interrupt */ - set_intr(i8255a, port, 0); - } -} - -static void write_mode2(i8255a_t *i8255a, UINT8 data) -{ - /* latch output data */ - i8255a->output[PORT_A] = data; - - /* write data to port */ - devcb_call_write8(&i8255a->out_port_func[PORT_A], 0, data); - - /* set output buffer full flag */ - set_obf(i8255a, PORT_A, 0); - - /* clear interrupt */ - set_intr(i8255a, PORT_A, 0); -} - -static void write_pc(i8255a_t *i8255a, UINT8 data) -{ - int changed = 0; - - if (group_mode(i8255a, GROUP_A) == MODE_0) - { - /* PC upper */ - if (port_c_upper_mode(i8255a) == MODE_OUTPUT) - { - i8255a->output[PORT_C] = (data & 0xf0) | (i8255a->output[PORT_C] & 0x0f); - changed = 1; - } - - /* PC lower */ - if (port_c_lower_mode(i8255a) == MODE_OUTPUT) - { - i8255a->output[PORT_C] = (i8255a->output[PORT_C] & 0xf0) | (data & 0x0f); - changed = 1; - } - } - - if (changed) - { - output_pc(i8255a); - } -} - -static void set_mode(device_t *device, UINT8 data) -{ - i8255a_t *i8255a = get_safe_token(device); - - i8255a->control = data; - - /* group A */ - i8255a->output[PORT_A] = 0; - i8255a->input[PORT_A] = 0; - i8255a->ibf[PORT_A] = 0; - i8255a->obf[PORT_A] = 1; - i8255a->inte[PORT_A] = 0; - i8255a->inte1 = 0; - i8255a->inte2 = 0; - - if (port_mode(i8255a, PORT_A) == MODE_OUTPUT) - { - devcb_call_write8(&i8255a->out_port_func[PORT_A], 0, i8255a->output[PORT_A]); - } - else - { - /* TTL inputs float high */ - devcb_call_write8(&i8255a->out_port_func[PORT_A], 0, 0xff); - } - - if (LOG) logerror("8255A '%s' Group A Mode: %u\n", device->tag(), group_mode(i8255a, GROUP_A)); - if (LOG) logerror("8255A '%s' Port A Mode: %s\n", device->tag(), (port_mode(i8255a, PORT_A) == MODE_OUTPUT) ? "output" : "input"); - if (LOG) logerror("8255A '%s' Port C Upper Mode: %s\n", device->tag(), (port_c_upper_mode(i8255a) == MODE_OUTPUT) ? "output" : "input"); - if (LOG) logerror("8255A '%s' Group B Mode: %u\n", device->tag(), group_mode(i8255a, GROUP_B)); - if (LOG) logerror("8255A '%s' Port B Mode: %s\n", device->tag(), (port_mode(i8255a, PORT_B) == MODE_OUTPUT) ? "output" : "input"); - if (LOG) logerror("8255A '%s' Port C Lower Mode: %s\n", device->tag(), (port_c_lower_mode(i8255a) == MODE_OUTPUT) ? "output" : "input"); - - /* group B */ - i8255a->output[PORT_B] = 0; - i8255a->input[PORT_B] = 0; - i8255a->ibf[PORT_B] = 0; - i8255a->obf[PORT_B] = 1; - i8255a->inte[PORT_B] = 0; - - if (port_mode(i8255a, PORT_B) == MODE_OUTPUT) - { - devcb_call_write8(&i8255a->out_port_func[PORT_B], 0, i8255a->output[PORT_B]); - } - else - { - /* TTL inputs float high */ - devcb_call_write8(&i8255a->out_port_func[PORT_B], 0, 0xff); - } - - i8255a->output[PORT_C] = 0; - i8255a->input[PORT_C] = 0; - - output_pc(i8255a); -} - -static void set_pc_bit(device_t *device, int bit, int state) -{ - i8255a_t *i8255a = get_safe_token(device); - - /* set output latch bit */ - i8255a->output[PORT_C] &= ~(1 << bit); - i8255a->output[PORT_C] |= state << bit; - - switch (group_mode(i8255a, GROUP_A)) - { - case MODE_1: - if (port_mode(i8255a, PORT_A) == MODE_OUTPUT) - { - switch (bit) - { - case 3: set_intr(i8255a, PORT_A, state); break; - case 6: set_inte(i8255a, PORT_A, state); break; - case 7: set_obf(i8255a, PORT_A, state); break; - } - } - else - { - switch (bit) - { - case 3: set_intr(i8255a, PORT_A, state); break; - case 4: set_inte(i8255a, PORT_A, state); break; - case 5: set_ibf(i8255a, PORT_A, state); break; - } - } - break; - - case MODE_2: - switch (bit) - { - case 3: set_intr(i8255a, PORT_A, state); break; - case 4: set_inte2(i8255a, state); break; - case 5: set_ibf(i8255a, PORT_A, state); break; - case 6: set_inte1(i8255a, state); break; - case 7: set_obf(i8255a, PORT_A, state); break; - } - break; - } - - if (group_mode(i8255a, GROUP_B) == MODE_1) - { - switch (bit) - { - case 0: set_intr(i8255a, PORT_B, state); break; - case 1: - if (port_mode(i8255a, PORT_B) == MODE_OUTPUT) - set_obf(i8255a, PORT_B, state); - else - set_ibf(i8255a, PORT_B, state); - break; - case 2: set_inte(i8255a, PORT_B, state); break; - } - } - - output_pc(i8255a); -} - -WRITE8_DEVICE_HANDLER( i8255a_w ) -{ - i8255a_t *i8255a = get_safe_token(device); - - switch (offset & 0x03) - { - case PORT_A: - if (LOG) logerror("8255A '%s' Port A Write: %02x\n", device->tag(), data); - - switch (group_mode(i8255a, GROUP_A)) - { - case MODE_0: write_mode0(i8255a, PORT_A, data); break; - case MODE_1: write_mode1(i8255a, PORT_A, data); break; - case MODE_2: write_mode2(i8255a, data); break; - } - break; - - case PORT_B: - if (LOG) logerror("8255A '%s' Port B Write: %02x\n", device->tag(), data); - - switch (group_mode(i8255a, GROUP_B)) - { - case MODE_0: write_mode0(i8255a, PORT_B, data); break; - case MODE_1: write_mode1(i8255a, PORT_B, data); break; - } - break; - - case PORT_C: - if (LOG) logerror("8255A '%s' Port C Write: %02x\n", device->tag(), data); - - write_pc(i8255a, data); - break; - - case CONTROL: - if (data & I8255A_CONTROL_MODE_SET) - { - if (LOG) logerror("8255A '%s' Mode Control Word: %02x\n", device->tag(), data); - - set_mode(device, data); - } - else - { - int bit = (data >> 1) & 0x07; - int state = BIT(data, 0); - - if (LOG) logerror("8255A '%s' %s Bit %u\n", device->tag(), state ? "Set" : "Reset", bit); - - set_pc_bit(device, bit, state); - } - break; - } -} - -READ8_DEVICE_HANDLER( i8255a_pa_r ) -{ - i8255a_t *i8255a = get_safe_token(device); - - UINT8 data = 0xff; - - if (port_mode(i8255a, PORT_A) == MODE_OUTPUT) - { - data = i8255a->output[PORT_A]; - } - - return data; -} - -READ8_DEVICE_HANDLER( i8255a_pb_r ) -{ - i8255a_t *i8255a = get_safe_token(device); - - UINT8 data = 0xff; - - if (port_mode(i8255a, PORT_B) == MODE_OUTPUT) - { - data = i8255a->output[PORT_B]; - } - - return data; -} - -WRITE_LINE_DEVICE_HANDLER( i8255a_pc2_w ) -{ - i8255a_t *i8255a = get_safe_token(device); - - if (group_mode(i8255a, GROUP_B) == 1) - { - if (port_mode(i8255a, PORT_B) == MODE_OUTPUT) - { - /* port B acknowledge */ - if (!i8255a->obf[PORT_B] && !state) - { - if (LOG) logerror("8255A '%s' Port B Acknowledge\n", device->tag()); - - /* clear output buffer flag */ - set_obf(i8255a, PORT_B, 1); - } - } - else - { - /* port B strobe */ - if (!i8255a->ibf[PORT_B] && !state) - { - if (LOG) logerror("8255A '%s' Port B Strobe\n", device->tag()); - - /* read port into latch */ - i8255a->input[PORT_B] = devcb_call_read8(&i8255a->in_port_func[PORT_B], 0); - - /* set input buffer flag */ - set_ibf(i8255a, PORT_B, 1); - } - } - } -} - -WRITE_LINE_DEVICE_HANDLER( i8255a_pc4_w ) -{ - i8255a_t *i8255a = get_safe_token(device); - - if ((group_mode(i8255a, GROUP_A) == 2) || ((group_mode(i8255a, GROUP_A) == 1) && (port_mode(i8255a, PORT_A) == MODE_INPUT))) - { - /* port A strobe */ - if (!i8255a->ibf[PORT_A] && !state) - { - if (LOG) logerror("8255A '%s' Port A Strobe\n", device->tag()); - - /* read port into latch */ - i8255a->input[PORT_A] = devcb_call_read8(&i8255a->in_port_func[PORT_A], 0); - - /* set input buffer flag */ - set_ibf(i8255a, PORT_A, 1); - } - } -} - -WRITE_LINE_DEVICE_HANDLER( i8255a_pc6_w ) -{ - i8255a_t *i8255a = get_safe_token(device); - - if ((group_mode(i8255a, GROUP_A) == 2) || ((group_mode(i8255a, GROUP_A) == 1) && (port_mode(i8255a, PORT_A) == MODE_OUTPUT))) - { - /* port A acknowledge */ - if (!i8255a->obf[PORT_A] && !state) - { - if (LOG) logerror("8255A '%s' Port A Acknowledge\n", device->tag()); - - /* clear output buffer flag */ - set_obf(i8255a, PORT_A, 1); - } - } -} - -/*------------------------------------------------- - DEVICE_START( i8255a ) --------------------------------------------------*/ - -static DEVICE_START( i8255a ) -{ - i8255a_t *i8255a = get_safe_token(device); - const i8255a_interface *intf = get_interface(device); - - /* resolve callbacks */ - devcb_resolve_read8(&i8255a->in_port_func[PORT_A], &intf->in_pa_func, device); - devcb_resolve_read8(&i8255a->in_port_func[PORT_B], &intf->in_pb_func, device); - devcb_resolve_read8(&i8255a->in_port_func[PORT_C], &intf->in_pc_func, device); - devcb_resolve_write8(&i8255a->out_port_func[PORT_A], &intf->out_pa_func, device); - devcb_resolve_write8(&i8255a->out_port_func[PORT_B], &intf->out_pb_func, device); - devcb_resolve_write8(&i8255a->out_port_func[PORT_C], &intf->out_pc_func, device); - - /* register for state saving */ - device->save_item(NAME(i8255a->control)); - device->save_item(NAME(i8255a->output)); - device->save_item(NAME(i8255a->input)); - device->save_item(NAME(i8255a->ibf)); - device->save_item(NAME(i8255a->obf)); - device->save_item(NAME(i8255a->inte)); - device->save_item(NAME(i8255a->inte1)); - device->save_item(NAME(i8255a->inte2)); - device->save_item(NAME(i8255a->intr)); -} - -/*------------------------------------------------- - DEVICE_RESET( i8255a ) --------------------------------------------------*/ - -static DEVICE_RESET( i8255a ) -{ - i8255a_w(device, CONTROL, 0x9b); -} - -/*------------------------------------------------- - DEVICE_GET_INFO( i8255a ) --------------------------------------------------*/ - -DEVICE_GET_INFO( i8255a ) -{ - switch (state) - { - /* --- the following bits of info are returned as 64-bit signed integers --- */ - case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(i8255a_t); break; - case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break; - - /* --- the following bits of info are returned as pointers to data or functions --- */ - case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(i8255a); break; - case DEVINFO_FCT_STOP: /* Nothing */ break; - case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(i8255a); break; - - /* --- the following bits of info are returned as NULL-terminated strings --- */ - case DEVINFO_STR_NAME: strcpy(info->s, "Intel 8255A"); break; - case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 8080"); 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; - } -} - - -DEFINE_LEGACY_DEVICE(I8255A, i8255a); diff --git a/src/emu/machine/i8255a.h b/src/emu/machine/i8255a.h deleted file mode 100644 index fcdcb54f012..00000000000 --- a/src/emu/machine/i8255a.h +++ /dev/null @@ -1,84 +0,0 @@ -/********************************************************************** - - Intel 8255A Programmable Peripheral Interface emulation - - Copyright MESS Team. - Visit http://mamedev.org for licensing and usage restrictions. - -********************************************************************** - _____ _____ - PA3 1 |* \_/ | 40 PA4 - PA2 2 | | 39 PA5 - PA1 3 | | 38 PA6 - PA0 4 | | 37 PA7 - _RD 5 | | 36 WR - _CS 6 | | 35 RESET - GND 7 | | 34 D0 - A1 8 | | 33 D1 - A0 9 | | 32 D2 - PC7 10 | 8255A | 31 D3 - PC6 11 | | 30 D4 - PC5 12 | | 29 D5 - PC4 13 | | 28 D6 - PC0 14 | | 27 D7 - PC1 15 | | 26 Vcc - PC2 16 | | 25 PB7 - PC3 17 | | 24 PB6 - PB0 18 | | 23 PB5 - PB1 19 | | 22 PB4 - PB2 20 |_____________| 21 PB3 - -**********************************************************************/ - -#ifndef __I8255A__ -#define __I8255A__ - -#include "devlegcy.h" - -/*************************************************************************** - MACROS / CONSTANTS -***************************************************************************/ - -DECLARE_LEGACY_DEVICE(I8255A, i8255a); - -#define MCFG_I8255A_ADD(_tag, _intrf) \ - MCFG_DEVICE_ADD(_tag, I8255A, 0) \ - MCFG_DEVICE_CONFIG(_intrf) - -#define I8255A_INTERFACE(name) \ - const i8255a_interface (name)= - -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -typedef struct _i8255a_interface i8255a_interface; -struct _i8255a_interface -{ - devcb_read8 in_pa_func; - devcb_read8 in_pb_func; - devcb_read8 in_pc_func; - - devcb_write8 out_pa_func; - devcb_write8 out_pb_func; - devcb_write8 out_pc_func; -}; - -/*************************************************************************** - PROTOTYPES -***************************************************************************/ - -/* register access */ -READ8_DEVICE_HANDLER( i8255a_r ); -WRITE8_DEVICE_HANDLER( i8255a_w ); - -/* port access */ -READ8_DEVICE_HANDLER( i8255a_pa_r ); -READ8_DEVICE_HANDLER( i8255a_pb_r ); - -/* handshaking signals */ -WRITE_LINE_DEVICE_HANDLER( i8255a_pc2_w ); -WRITE_LINE_DEVICE_HANDLER( i8255a_pc4_w ); -WRITE_LINE_DEVICE_HANDLER( i8255a_pc6_w ); - -#endif