ins8154: Updated to use devcb calls, cleaned up

This commit is contained in:
Dirk Best 2010-02-22 11:35:38 +00:00
parent b7927daaff
commit 4c15a5dfd7
2 changed files with 182 additions and 148 deletions

View File

@ -1,22 +1,23 @@
/*****************************************************************************
*
* machine/ins8154.h
*
* INS8154 N-Channel 128-by-8 Bit RAM Input/Output (RAM I/O)
*
* Written by Dirk Best, January 2008
*
* TODO: Strobed modes
*
****************************************************************************/
/***************************************************************************
National Semiconductor INS8154
N-Channel 128-by-8 Bit RAM Input/Output (RAM I/O)
TODO: Strobed modes
***************************************************************************/
#include "emu.h"
#include "ins8154.h"
#define VERBOSE 1
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
/***************************************************************************
CONSTANTS
***************************************************************************/
#define VERBOSE 1
/* Mode Definition Register */
enum
@ -27,11 +28,22 @@ enum
MDR_STROBED_OUTPUT_3STATE = 0xe0
};
typedef struct _ins8154_t ins8154_t;
struct _ins8154_t
{
const ins8154_interface *intf; /* Pointer to our interface */
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct _ins8154_state ins8154_state;
struct _ins8154_state
{
/* i/o lines */
devcb_resolved_read8 in_a_func;
devcb_resolved_write8 out_a_func;
devcb_resolved_read8 in_b_func;
devcb_resolved_write8 out_b_func;
devcb_resolved_write_line out_irq_func;
/* registers */
UINT8 in_a; /* Input Latch Port A */
UINT8 in_b; /* Input Latch Port B */
UINT8 out_a; /* Output Latch Port A */
@ -42,79 +54,62 @@ struct _ins8154_t
};
static DEVICE_START( ins8154 )
/*****************************************************************************
INLINE FUNCTIONS
*****************************************************************************/
INLINE ins8154_state *get_safe_token(running_device *device)
{
ins8154_t *ins8154 = (ins8154_t *)device->token;
assert(device != NULL);
assert(device->token != NULL);
assert(device->type == INS8154);
/* validate arguments */
assert(device->tag != NULL);
/* assign interface */
ins8154->intf = (const ins8154_interface*)device->baseconfig().static_config;
/* register for state saving */
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->in_a);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->in_b);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->out_a);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->out_b);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->mdr);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->odra);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->odrb);
return (ins8154_state *)device->token;
}
static DEVICE_RESET( ins8154 )
{
ins8154_t *ins8154 = (ins8154_t *)device->token;
ins8154->in_a = 0;
ins8154->in_b = 0;
ins8154->out_a = 0;
ins8154->out_b = 0;
ins8154->mdr = 0;
ins8154->odra = 0;
ins8154->odrb = 0;
}
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
READ8_DEVICE_HANDLER( ins8154_r )
{
ins8154_t *i = (ins8154_t *)device->token;
ins8154_state *ins8154 = get_safe_token(device);
UINT8 val = 0xff;
if (offset > 0x24)
{
logerror("INS8154 (%08x): Read from unknown offset %02x!\n",
cpu_get_pc( device->machine->firstcpu ), offset);
if (VERBOSE)
logerror("%s: INS8154 '%s' Read from invalid offset %02x!\n", cpuexec_describe_context(device->machine), device->tag.cstr(), offset);
return 0xff;
}
switch (offset)
{
case 0x20:
if (i->intf->in_a_func)
val = i->intf->in_a_func(device, 0);
i->in_a = val;
if (ins8154->in_a_func.read != NULL)
val = devcb_call_read8(&ins8154->in_a_func, 0);
ins8154->in_a = val;
break;
case 0x21:
if (i->intf->in_b_func)
val = i->intf->in_b_func(device, 0);
i->in_b = val;
if (ins8154->in_b_func.read != NULL)
val = devcb_call_read8(&ins8154->in_b_func, 0);
ins8154->in_b = val;
break;
default:
if (offset < 0x08)
{
if (i->intf->in_a_func)
val = (i->intf->in_a_func(device, 0) << (8 - offset)) & 0x80;
i->in_a = val;
if (ins8154->in_a_func.read != NULL)
val = (devcb_call_read8(&ins8154->in_a_func, 0) << (8 - offset)) & 0x80;
ins8154->in_a = val;
}
else
{
if (i->intf->in_a_func)
val = (i->intf->in_a_func(device, 0) << (8 - (offset >> 4))) & 0x80;
i->in_b = val;
if (ins8154->in_b_func.read != NULL)
val = (devcb_call_read8(&ins8154->in_b_func, 0) << (8 - (offset >> 4))) & 0x80;
ins8154->in_b = val;
}
break;
}
@ -124,48 +119,34 @@ READ8_DEVICE_HANDLER( ins8154_r )
WRITE8_DEVICE_HANDLER( ins8154_porta_w )
{
ins8154_t *i = (ins8154_t *)device->token;
ins8154_state *ins8154 = get_safe_token(device);
i->out_a = data;
ins8154->out_a = data;
/* Test if any pins are set as outputs */
if (i->odra)
{
if (i->intf->out_a_func)
i->intf->out_a_func(device, 0, (data & i->odra) | (i->odra ^ 0xff));
else
logerror("INS8154 (%08x): Write to port A but no write handler defined!\n",
cpu_get_pc( device->machine->firstcpu ) );
}
if (ins8154->odra)
devcb_call_write8(&ins8154->out_a_func, 0, (data & ins8154->odra) | (ins8154->odra ^ 0xff));
}
WRITE8_DEVICE_HANDLER( ins8154_portb_w )
{
ins8154_t *i = (ins8154_t *)device->token;
ins8154_state *ins8154 = get_safe_token(device);
i->out_b = data;
ins8154->out_b = data;
/* Test if any pins are set as outputs */
if (i->odrb)
{
if (i->intf->out_b_func)
i->intf->out_b_func(device, 0, (data & i->odrb) | (i->odrb ^ 0xff));
else
logerror("INS8154 (%08x): Write to port B but no write handler defined!\n",
cpu_get_pc( device->machine->firstcpu ) );
}
if (ins8154->odrb)
devcb_call_write8(&ins8154->out_b_func, 0, (data & ins8154->odrb) | (ins8154->odrb ^ 0xff));
}
WRITE8_DEVICE_HANDLER( ins8154_w )
{
ins8154_t *i = (ins8154_t *)device->token;
ins8154_state *ins8154 = get_safe_token(device);
if (offset > 0x24)
{
logerror("INS8154 (%04x): Write %02x to invalid offset %02x!\n",
cpu_get_pc( device->machine->firstcpu ), data, offset);
if (VERBOSE)
logerror("%s: INS8154 '%s' Write %02x to invalid offset %02x!\n", cpuexec_describe_context(device->machine), device->tag.cstr(), data, offset);
return;
}
@ -180,21 +161,24 @@ WRITE8_DEVICE_HANDLER( ins8154_w )
break;
case 0x22:
LOG(("INS8154 (%04x): ODR for port A set to %02x\n",
cpu_get_pc( device->machine->firstcpu ), data));
i->odra = data;
if (VERBOSE)
logerror("%s: INS8154 '%s' ODRA set to %02x\n", cpuexec_describe_context(device->machine), device->tag.cstr(), data);
ins8154->odra = data;
break;
case 0x23:
LOG(("INS8154 (%04x): ODR for port B set to %02x\n",
cpu_get_pc( device->machine->firstcpu ), data));
i->odrb = data;
if (VERBOSE)
logerror("%s: INS8154 '%s' ODRB set to %02x\n", cpuexec_describe_context(device->machine), device->tag.cstr(), data);
ins8154->odrb = data;
break;
case 0x24:
LOG(("INS8154 (%04x): MDR set to %02x\n",
cpu_get_pc( device->machine->firstcpu ), data));
i->mdr = data;
if (VERBOSE)
logerror("%s: INS8154 '%s' MDR set to %02x\n", cpuexec_describe_context(device->machine), device->tag.cstr(), data);
ins8154->mdr = data;
break;
default:
@ -203,11 +187,11 @@ WRITE8_DEVICE_HANDLER( ins8154_w )
/* Set bit */
if (offset < 0x08)
{
ins8154_porta_w(device, 0, i->out_a |= offset & 0x07);
ins8154_porta_w(device, 0, ins8154->out_a |= offset & 0x07);
}
else
{
ins8154_portb_w(device, 0, i->out_b |= (offset >> 4) & 0x07);
ins8154_portb_w(device, 0, ins8154->out_b |= (offset >> 4) & 0x07);
}
}
else
@ -215,11 +199,11 @@ WRITE8_DEVICE_HANDLER( ins8154_w )
/* Clear bit */
if (offset < 0x08)
{
ins8154_porta_w(device, 0, i->out_a & ~(offset & 0x07));
ins8154_porta_w(device, 0, ins8154->out_a & ~(offset & 0x07));
}
else
{
ins8154_portb_w(device, 0, i->out_b & ~((offset >> 4) & 0x07));
ins8154_portb_w(device, 0, ins8154->out_b & ~((offset >> 4) & 0x07));
}
}
@ -228,25 +212,59 @@ WRITE8_DEVICE_HANDLER( ins8154_w )
}
DEVICE_GET_INFO( ins8154 )
/*****************************************************************************
DEVICE INTERFACE
*****************************************************************************/
static DEVICE_START( ins8154 )
{
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
case DEVINFO_INT_CLASS: info->i = DEVICE_CLASS_PERIPHERAL; break;
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(ins8154_t); break;
ins8154_state *ins8154 = get_safe_token(device);
const ins8154_interface *intf = (const ins8154_interface *)device->baseconfig().static_config;
/* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(ins8154); break;
case DEVINFO_FCT_STOP: /* Nothing */ break;
case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(ins8154); break;
/* validate some basic stuff */
assert(intf != NULL);
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "National Semiconductor INS8154"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "INS8154"); 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;
}
/* resolve callbacks */
devcb_resolve_read8(&ins8154->in_a_func, &intf->in_a_func, device);
devcb_resolve_write8(&ins8154->out_a_func, &intf->out_a_func, device);
devcb_resolve_read8(&ins8154->in_b_func, &intf->in_b_func, device);
devcb_resolve_write8(&ins8154->out_b_func, &intf->out_b_func, device);
devcb_resolve_write_line(&ins8154->out_irq_func, &intf->out_irq_func, device);
/* register for state saving */
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->in_a);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->in_b);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->out_a);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->out_b);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->mdr);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->odra);
state_save_register_item(device->machine, "ins8154", device->tag, 0, ins8154->odrb);
}
static DEVICE_RESET( ins8154 )
{
ins8154_state *ins8154 = get_safe_token(device);
ins8154->in_a = 0;
ins8154->in_b = 0;
ins8154->out_a = 0;
ins8154->out_b = 0;
ins8154->mdr = 0;
ins8154->odra = 0;
ins8154->odrb = 0;
}
/***************************************************************************
DEVICE GETINFO
***************************************************************************/
static const char DEVTEMPLATE_SOURCE[] = __FILE__;
#define DEVTEMPLATE_ID(p,s) p##ins8154##s
#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET
#define DEVTEMPLATE_NAME "INS8154"
#define DEVTEMPLATE_FAMILY "INS8154"
#define DEVTEMPLATE_VERSION "1.1"
#define DEVTEMPLATE_CREDITS "Copyright MESS Team"
#include "devtempl.h"

View File

@ -1,60 +1,76 @@
/*****************************************************************************
*
* machine/ins8154.h
*
* INS8154 N-Channel 128-by-8 Bit RAM Input/Output (RAM I/O)
*
****************************************************************************/
#ifndef INS8154_H_
#define INS8154_H_
/***************************************************************************
MACROS
National Semiconductor INS8154
N-Channel 128-by-8 Bit RAM Input/Output (RAM I/O)
_____ _____
PB6 1 |* \_/ | 40 VCC
PB5 2 | | 39 PB7
PB4 3 | | 38 NWDS
PB3 4 | | 37 NRDS
PB2 5 | | 36 NRST
PB1 6 | | 35 _CS0
PB0 7 | | 34 CS1
DB7 8 | | 33 M/_IO
DB6 9 | | 32 AD6
DB5 10 | INS8154 | 31 AD5
DB4 11 | | 30 AD4
DB3 12 | | 29 AD3
DB2 13 | | 28 AD2
DB1 14 | | 27 AD1
DB0 15 | | 26 AD0
PA7 16 | | 25 INTR
PA6 17 | | 24 PA0
PA5 18 | | 23 PA1
PA4 19 | | 22 PA2
GND 20 |_____________| 21 PA3
***************************************************************************/
#define INS8154 DEVICE_GET_INFO_NAME(ins8154)
#ifndef __INS8154_H__
#define __INS8154_H__
#include "devcb.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef void (*ins8154_irq_func)(running_device *device, int state);
#define INS8154_IRQ(name) void name(running_device *device, int state )
/******************* Interface **********************************************/
typedef struct _ins8154_interface ins8154_interface;
struct _ins8154_interface
{
read8_device_func in_a_func;
read8_device_func in_b_func;
write8_device_func out_a_func;
write8_device_func out_b_func;
ins8154_irq_func irq_func;
devcb_read8 in_a_func;
devcb_write8 out_a_func;
devcb_read8 in_b_func;
devcb_write8 out_b_func;
devcb_write_line out_irq_func;
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
DEVICE_GET_INFO( ins8154 );
/******************* Standard 8-bit CPU interfaces, D0-D7 *******************/
READ8_DEVICE_HANDLER( ins8154_r );
WRITE8_DEVICE_HANDLER( ins8154_w );
/******************* 8-bit A/B port interfaces ******************************/
WRITE8_DEVICE_HANDLER( ins8154_porta_w );
WRITE8_DEVICE_HANDLER( ins8154_portb_w );
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/
#define INS8154 DEVICE_GET_INFO_NAME(ins8154)
#define MDRV_INS8154_ADD(_tag, _intrf) \
MDRV_DEVICE_ADD(_tag, INS8154, 0) \
MDRV_DEVICE_CONFIG(_intrf)
#endif /* INS8154_H_ */
#endif /* __INS8154_H__ */