mirror of
https://github.com/holub/mame
synced 2025-04-24 09:20:02 +03:00
Modernized smc91c9x device. (nw)
This commit is contained in:
parent
217d078f9b
commit
4b33db6dc4
@ -13,7 +13,6 @@
|
||||
|
||||
#include "emu.h"
|
||||
#include "smc91c9x.h"
|
||||
#include "devlegcy.h"
|
||||
|
||||
|
||||
|
||||
@ -30,9 +29,6 @@
|
||||
CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
#define ETHER_BUFFER_SIZE (2048)
|
||||
#define ETHER_RX_BUFFERS (4)
|
||||
|
||||
/* Ethernet registers - bank 0 */
|
||||
#define EREG_TCR (0*8 + 0)
|
||||
#define EREG_EPH_STATUS (0*8 + 1)
|
||||
@ -104,62 +100,118 @@ static const char *const ethernet_regname[64] =
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
DEVICE INTERFACE
|
||||
***************************************************************************/
|
||||
|
||||
struct smc91c9x_state
|
||||
smc91c9x_device::smc91c9x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
|
||||
: device_t(mconfig, type, name, tag, owner, clock, shortname, source)
|
||||
{
|
||||
device_t *device;
|
||||
smc91c9x_irq_func irq_handler;
|
||||
}
|
||||
|
||||
/* raw register data and masks */
|
||||
UINT16 reg[64];
|
||||
UINT16 regmask[64];
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
/* IRQ information */
|
||||
UINT8 irq_state;
|
||||
|
||||
/* allocate information */
|
||||
UINT8 alloc_count;
|
||||
|
||||
/* transmit/receive FIFOs */
|
||||
UINT8 fifo_count;
|
||||
UINT8 rx[ETHER_BUFFER_SIZE * ETHER_RX_BUFFERS];
|
||||
UINT8 tx[ETHER_BUFFER_SIZE];
|
||||
|
||||
/* counters */
|
||||
UINT32 sent;
|
||||
UINT32 recd;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
|
||||
static void update_ethernet_irq(smc91c9x_state *smc);
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
INLINE FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
get_safe_token - makes sure that the passed
|
||||
in device is, in fact, an IDE controller
|
||||
-------------------------------------------------*/
|
||||
|
||||
INLINE smc91c9x_state *get_safe_token(device_t *device)
|
||||
void smc91c9x_device::device_config_complete()
|
||||
{
|
||||
assert(device != NULL);
|
||||
assert(device->type() == SMC91C94 || device->type() == SMC91C96);
|
||||
// inherit a copy of the static data
|
||||
const smc91c9x_interface *intf = reinterpret_cast<const smc91c9x_interface *>(static_config());
|
||||
if (intf != NULL)
|
||||
*static_cast<smc91c9x_interface *>(this) = *intf;
|
||||
|
||||
return (smc91c9x_state *)downcast<smc91c9x_device *>(device)->token();
|
||||
// or initialize to defaults if none provided
|
||||
else
|
||||
{
|
||||
memset(&m_interrupt, 0, sizeof(m_interrupt));
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void smc91c9x_device::device_start()
|
||||
{
|
||||
m_irq_handler = m_interrupt;
|
||||
|
||||
/* register ide states */
|
||||
save_item(NAME(m_reg));
|
||||
save_item(NAME(m_regmask));
|
||||
save_item(NAME(m_irq_state));
|
||||
save_item(NAME(m_alloc_count));
|
||||
save_item(NAME(m_fifo_count));
|
||||
save_item(NAME(m_rx));
|
||||
save_item(NAME(m_tx));
|
||||
save_item(NAME(m_sent));
|
||||
save_item(NAME(m_recd));
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void smc91c9x_device::device_reset()
|
||||
{
|
||||
memset(m_reg, 0, sizeof(m_reg));
|
||||
memset(m_regmask, 0, sizeof(m_regmask));
|
||||
m_irq_state = 0;
|
||||
m_alloc_count = 0;
|
||||
m_fifo_count = 0;
|
||||
m_sent = 0;
|
||||
m_recd = 0;
|
||||
|
||||
m_reg[EREG_TCR] = 0x0000; m_regmask[EREG_TCR] = 0x3d87;
|
||||
m_reg[EREG_EPH_STATUS] = 0x0000; m_regmask[EREG_EPH_STATUS] = 0x0000;
|
||||
m_reg[EREG_RCR] = 0x0000; m_regmask[EREG_RCR] = 0xc307;
|
||||
m_reg[EREG_COUNTER] = 0x0000; m_regmask[EREG_COUNTER] = 0x0000;
|
||||
m_reg[EREG_MIR] = 0x1212; m_regmask[EREG_MIR] = 0x0000;
|
||||
m_reg[EREG_MCR] = 0x3300; m_regmask[EREG_MCR] = 0x00ff;
|
||||
m_reg[EREG_BANK] = 0x3300; m_regmask[EREG_BANK] = 0x0007;
|
||||
|
||||
m_reg[EREG_CONFIG] = 0x0030; m_regmask[EREG_CONFIG] = 0x17c6;
|
||||
m_reg[EREG_BASE] = 0x1866; m_regmask[EREG_BASE] = 0xfffe;
|
||||
m_reg[EREG_IA0_1] = 0x0000; m_regmask[EREG_IA0_1] = 0xffff;
|
||||
m_reg[EREG_IA2_3] = 0x0000; m_regmask[EREG_IA2_3] = 0xffff;
|
||||
m_reg[EREG_IA4_5] = 0x0000; m_regmask[EREG_IA4_5] = 0xffff;
|
||||
m_reg[EREG_GENERAL_PURP] = 0x0000; m_regmask[EREG_GENERAL_PURP] = 0xffff;
|
||||
m_reg[EREG_CONTROL] = 0x0100; m_regmask[EREG_CONTROL] = 0x68e7;
|
||||
|
||||
m_reg[EREG_MMU_COMMAND] = 0x0000; m_regmask[EREG_MMU_COMMAND] = 0x00e7;
|
||||
m_reg[EREG_PNR_ARR] = 0x8000; m_regmask[EREG_PNR_ARR] = 0x00ff;
|
||||
m_reg[EREG_FIFO_PORTS] = 0x8080; m_regmask[EREG_FIFO_PORTS] = 0x0000;
|
||||
m_reg[EREG_POINTER] = 0x0000; m_regmask[EREG_POINTER] = 0xf7ff;
|
||||
m_reg[EREG_DATA_0] = 0x0000; m_regmask[EREG_DATA_0] = 0xffff;
|
||||
m_reg[EREG_DATA_1] = 0x0000; m_regmask[EREG_DATA_1] = 0xffff;
|
||||
m_reg[EREG_INTERRUPT] = 0x0004; m_regmask[EREG_INTERRUPT] = 0x7f00;
|
||||
|
||||
m_reg[EREG_MT0_1] = 0x0000; m_regmask[EREG_MT0_1] = 0xffff;
|
||||
m_reg[EREG_MT2_3] = 0x0000; m_regmask[EREG_MT2_3] = 0xffff;
|
||||
m_reg[EREG_MT4_5] = 0x0000; m_regmask[EREG_MT4_5] = 0xffff;
|
||||
m_reg[EREG_MT6_7] = 0x0000; m_regmask[EREG_MT6_7] = 0xffff;
|
||||
m_reg[EREG_MGMT] = 0x3030; m_regmask[EREG_MGMT] = 0x0f0f;
|
||||
m_reg[EREG_REVISION] = 0x3340; m_regmask[EREG_REVISION] = 0x0000;
|
||||
m_reg[EREG_ERCV] = 0x331f; m_regmask[EREG_ERCV] = 0x009f;
|
||||
|
||||
update_ethernet_irq();
|
||||
}
|
||||
|
||||
|
||||
const device_type SMC91C94 = &device_creator<smc91c94_device>;
|
||||
|
||||
smc91c94_device::smc91c94_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: smc91c9x_device(mconfig, SMC91C94, "SMC91C94", tag, owner, clock, "smc91c94", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const device_type SMC91C96 = &device_creator<smc91c96_device>;
|
||||
|
||||
smc91c96_device::smc91c96_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: smc91c9x_device(mconfig, SMC91C96, "SMC91C96", tag, owner, clock, "smc91c96", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
INTERNAL HELPERS
|
||||
@ -169,15 +221,15 @@ INLINE smc91c9x_state *get_safe_token(device_t *device)
|
||||
update_ethernet_irq - update the IRQ state
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void update_ethernet_irq(smc91c9x_state *smc)
|
||||
void smc91c9x_device::update_ethernet_irq()
|
||||
{
|
||||
UINT8 mask = smc->reg[EREG_INTERRUPT] >> 8;
|
||||
UINT8 state = smc->reg[EREG_INTERRUPT] & 0xff;
|
||||
UINT8 mask = m_reg[EREG_INTERRUPT] >> 8;
|
||||
UINT8 state = m_reg[EREG_INTERRUPT] & 0xff;
|
||||
|
||||
/* update the IRQ state */
|
||||
smc->irq_state = ((mask & state) != 0);
|
||||
if (smc->irq_handler != NULL)
|
||||
(*smc->irq_handler)(smc->device, smc->irq_state ? ASSERT_LINE : CLEAR_LINE);
|
||||
m_irq_state = ((mask & state) != 0);
|
||||
if (m_irq_handler != NULL)
|
||||
(*m_irq_handler)(this, m_irq_state ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
|
||||
@ -185,10 +237,10 @@ static void update_ethernet_irq(smc91c9x_state *smc)
|
||||
update_stats - draw statistics
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void update_stats(smc91c9x_state *smc)
|
||||
void smc91c9x_device::update_stats()
|
||||
{
|
||||
if (DISPLAY_STATS)
|
||||
popmessage("Sent:%d Rec'd:%d", smc->sent, smc->recd);
|
||||
popmessage("Sent:%d Rec'd:%d", m_sent, m_recd);
|
||||
}
|
||||
|
||||
|
||||
@ -196,31 +248,31 @@ static void update_stats(smc91c9x_state *smc)
|
||||
finish_enqueue - complete an enqueued packet
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void finish_enqueue(smc91c9x_state *smc, int param)
|
||||
void smc91c9x_device::finish_enqueue(int param)
|
||||
{
|
||||
int is_broadcast = (smc->tx[4] == 0xff && smc->tx[5] == 0xff && smc->tx[6] == 0xff &&
|
||||
smc->tx[7] == 0xff && smc->tx[8] == 0xff && smc->tx[9] == 0xff);
|
||||
int is_broadcast = (m_tx[4] == 0xff && m_tx[5] == 0xff && m_tx[6] == 0xff &&
|
||||
m_tx[7] == 0xff && m_tx[8] == 0xff && m_tx[9] == 0xff);
|
||||
|
||||
/* update the EPH register and stuff it in the first transmit word */
|
||||
smc->reg[EREG_EPH_STATUS] = 0x0001;
|
||||
m_reg[EREG_EPH_STATUS] = 0x0001;
|
||||
if (is_broadcast)
|
||||
smc->reg[EREG_EPH_STATUS] |= 0x0040;
|
||||
smc->tx[0] = smc->reg[EREG_EPH_STATUS];
|
||||
smc->tx[1] = smc->reg[EREG_EPH_STATUS] >> 8;
|
||||
m_reg[EREG_EPH_STATUS] |= 0x0040;
|
||||
m_tx[0] = m_reg[EREG_EPH_STATUS];
|
||||
m_tx[1] = m_reg[EREG_EPH_STATUS] >> 8;
|
||||
|
||||
/* signal a transmit interrupt and mark the transmit buffer empty */
|
||||
smc->reg[EREG_INTERRUPT] |= EINT_TX;
|
||||
smc->reg[EREG_INTERRUPT] |= EINT_TX_EMPTY;
|
||||
smc->reg[EREG_FIFO_PORTS] |= 0x0080;
|
||||
smc->sent++;
|
||||
update_stats(smc);
|
||||
m_reg[EREG_INTERRUPT] |= EINT_TX;
|
||||
m_reg[EREG_INTERRUPT] |= EINT_TX_EMPTY;
|
||||
m_reg[EREG_FIFO_PORTS] |= 0x0080;
|
||||
m_sent++;
|
||||
update_stats();
|
||||
|
||||
/* loopback? */
|
||||
if (smc->reg[EREG_TCR] & 0x2002)
|
||||
if (smc->fifo_count < ETHER_RX_BUFFERS)
|
||||
if (m_reg[EREG_TCR] & 0x2002)
|
||||
if (m_fifo_count < ETHER_RX_BUFFERS)
|
||||
{
|
||||
int buffer_len = ((smc->tx[3] << 8) | smc->tx[2]) & 0x7ff;
|
||||
UINT8 *packet = &smc->rx[smc->fifo_count++ * ETHER_BUFFER_SIZE];
|
||||
int buffer_len = ((m_tx[3] << 8) | m_tx[2]) & 0x7ff;
|
||||
UINT8 *packet = &m_rx[m_fifo_count++ * ETHER_BUFFER_SIZE];
|
||||
int packet_len;
|
||||
|
||||
/* compute the packet length */
|
||||
@ -233,16 +285,16 @@ static void finish_enqueue(smc91c9x_state *smc, int param)
|
||||
packet[1] = 0x0000;
|
||||
packet[2] = buffer_len;
|
||||
packet[3] = buffer_len >> 8;
|
||||
memcpy(&packet[4], &smc->tx[4], 6);
|
||||
memcpy(&packet[10], &smc->tx[10], 6);
|
||||
memcpy(&packet[16], &smc->tx[16], buffer_len - 16);
|
||||
memcpy(&packet[4], &m_tx[4], 6);
|
||||
memcpy(&packet[10], &m_tx[10], 6);
|
||||
memcpy(&packet[16], &m_tx[16], buffer_len - 16);
|
||||
|
||||
/* set the broadcast flag */
|
||||
if (is_broadcast)
|
||||
packet[1] |= 0x40;
|
||||
|
||||
/* pad? */
|
||||
if (smc->reg[EREG_TCR & 0x0080])
|
||||
if (m_reg[EREG_TCR & 0x0080])
|
||||
if (packet_len < 64)
|
||||
{
|
||||
memset(&packet[buffer_len], 0, 64+6 - buffer_len);
|
||||
@ -253,10 +305,10 @@ static void finish_enqueue(smc91c9x_state *smc, int param)
|
||||
}
|
||||
|
||||
/* signal a receive */
|
||||
smc->reg[EREG_INTERRUPT] |= EINT_RCV;
|
||||
smc->reg[EREG_FIFO_PORTS] &= ~0x8000;
|
||||
m_reg[EREG_INTERRUPT] |= EINT_RCV;
|
||||
m_reg[EREG_FIFO_PORTS] &= ~0x8000;
|
||||
}
|
||||
update_ethernet_irq(smc);
|
||||
update_ethernet_irq();
|
||||
}
|
||||
|
||||
|
||||
@ -264,7 +316,7 @@ static void finish_enqueue(smc91c9x_state *smc, int param)
|
||||
process_command - handle MMU commands
|
||||
-------------------------------------------------*/
|
||||
|
||||
static void process_command(smc91c9x_state *smc, UINT16 data)
|
||||
void smc91c9x_device::process_command(UINT16 data)
|
||||
{
|
||||
switch ((data >> 5) & 7)
|
||||
{
|
||||
@ -276,10 +328,10 @@ static void process_command(smc91c9x_state *smc, UINT16 data)
|
||||
case ECMD_ALLOCATE:
|
||||
if (LOG_ETHERNET)
|
||||
logerror(" ALLOCATE MEMORY FOR TX (%d)\n", (data & 7));
|
||||
smc->reg[EREG_PNR_ARR] &= ~0xff00;
|
||||
smc->reg[EREG_PNR_ARR] |= smc->alloc_count++ << 8;
|
||||
smc->reg[EREG_INTERRUPT] |= 0x0008;
|
||||
update_ethernet_irq(smc);
|
||||
m_reg[EREG_PNR_ARR] &= ~0xff00;
|
||||
m_reg[EREG_PNR_ARR] |= m_alloc_count++ << 8;
|
||||
m_reg[EREG_INTERRUPT] |= 0x0008;
|
||||
update_ethernet_irq();
|
||||
break;
|
||||
|
||||
case ECMD_RESET_MMU:
|
||||
@ -295,20 +347,20 @@ static void process_command(smc91c9x_state *smc, UINT16 data)
|
||||
case ECMD_REMOVE_RELEASE:
|
||||
if (LOG_ETHERNET)
|
||||
logerror(" REMOVE AND RELEASE FRAME FROM RX FIFO\n");
|
||||
smc->reg[EREG_INTERRUPT] &= ~EINT_RCV;
|
||||
if (smc->fifo_count > 0)
|
||||
smc->fifo_count--;
|
||||
if (smc->fifo_count > 0)
|
||||
m_reg[EREG_INTERRUPT] &= ~EINT_RCV;
|
||||
if (m_fifo_count > 0)
|
||||
m_fifo_count--;
|
||||
if (m_fifo_count > 0)
|
||||
{
|
||||
memmove(&smc->rx[0], &smc->rx[ETHER_BUFFER_SIZE], smc->fifo_count * ETHER_BUFFER_SIZE);
|
||||
smc->reg[EREG_INTERRUPT] |= EINT_RCV;
|
||||
smc->reg[EREG_FIFO_PORTS] &= ~0x8000;
|
||||
memmove(&m_rx[0], &m_rx[ETHER_BUFFER_SIZE], m_fifo_count * ETHER_BUFFER_SIZE);
|
||||
m_reg[EREG_INTERRUPT] |= EINT_RCV;
|
||||
m_reg[EREG_FIFO_PORTS] &= ~0x8000;
|
||||
}
|
||||
else
|
||||
smc->reg[EREG_FIFO_PORTS] |= 0x8000;
|
||||
update_ethernet_irq(smc);
|
||||
smc->recd++;
|
||||
update_stats(smc);
|
||||
m_reg[EREG_FIFO_PORTS] |= 0x8000;
|
||||
update_ethernet_irq();
|
||||
m_recd++;
|
||||
update_stats();
|
||||
break;
|
||||
|
||||
case ECMD_RELEASE_PACKET:
|
||||
@ -319,7 +371,7 @@ static void process_command(smc91c9x_state *smc, UINT16 data)
|
||||
case ECMD_ENQUEUE_PACKET:
|
||||
if (LOG_ETHERNET)
|
||||
logerror(" ENQUEUE TX PACKET\n");
|
||||
finish_enqueue(smc, 0);
|
||||
finish_enqueue(0);
|
||||
break;
|
||||
|
||||
case ECMD_RESET_FIFOS:
|
||||
@ -327,7 +379,7 @@ static void process_command(smc91c9x_state *smc, UINT16 data)
|
||||
logerror(" RESET TX FIFOS\n");
|
||||
break;
|
||||
}
|
||||
smc->reg[EREG_MMU_COMMAND] &= ~0x0001;
|
||||
m_reg[EREG_MMU_COMMAND] &= ~0x0001;
|
||||
}
|
||||
|
||||
|
||||
@ -340,43 +392,42 @@ static void process_command(smc91c9x_state *smc, UINT16 data)
|
||||
smc91c9x_r - handle a read from the device
|
||||
-------------------------------------------------*/
|
||||
|
||||
READ16_DEVICE_HANDLER( smc91c9x_r )
|
||||
READ16_MEMBER( smc91c9x_device::read )
|
||||
{
|
||||
smc91c9x_state *smc = get_safe_token(device);
|
||||
UINT32 result = ~0;
|
||||
|
||||
/* determine the effective register */
|
||||
offset %= 8;
|
||||
if (offset != EREG_BANK)
|
||||
offset += 8 * (smc->reg[EREG_BANK] & 7);
|
||||
result = smc->reg[offset];
|
||||
offset += 8 * (m_reg[EREG_BANK] & 7);
|
||||
result = m_reg[offset];
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case EREG_PNR_ARR:
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
smc->reg[EREG_INTERRUPT] &= ~0x0008;
|
||||
update_ethernet_irq(smc);
|
||||
m_reg[EREG_INTERRUPT] &= ~0x0008;
|
||||
update_ethernet_irq();
|
||||
}
|
||||
break;
|
||||
|
||||
case EREG_DATA_0: /* data register */
|
||||
case EREG_DATA_1: /* data register */
|
||||
{
|
||||
UINT8 *buffer = (smc->reg[EREG_POINTER] & 0x8000) ? smc->rx : smc->tx;
|
||||
int addr = smc->reg[EREG_POINTER] & 0x7ff;
|
||||
UINT8 *buffer = (m_reg[EREG_POINTER] & 0x8000) ? m_rx : m_tx;
|
||||
int addr = m_reg[EREG_POINTER] & 0x7ff;
|
||||
result = buffer[addr++];
|
||||
if (ACCESSING_BITS_8_15)
|
||||
result |= buffer[addr++] << 8;
|
||||
if (smc->reg[EREG_POINTER] & 0x4000)
|
||||
smc->reg[EREG_POINTER] = (smc->reg[EREG_POINTER] & ~0x7ff) | (addr & 0x7ff);
|
||||
if (m_reg[EREG_POINTER] & 0x4000)
|
||||
m_reg[EREG_POINTER] = (m_reg[EREG_POINTER] & ~0x7ff) | (addr & 0x7ff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (LOG_ETHERNET && offset != EREG_BANK)
|
||||
logerror("%s:smc91c9x_r(%s) = %04X & %04X\n", device->machine().describe_context(), ethernet_regname[offset], result, mem_mask);
|
||||
logerror("%s:smc91c9x_r(%s) = %04X & %04X\n", machine().describe_context(), ethernet_regname[offset], result, mem_mask);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -385,23 +436,22 @@ READ16_DEVICE_HANDLER( smc91c9x_r )
|
||||
smc91c9x_w - handle a write to the device
|
||||
-------------------------------------------------*/
|
||||
|
||||
WRITE16_DEVICE_HANDLER( smc91c9x_w )
|
||||
WRITE16_MEMBER( smc91c9x_device::write )
|
||||
{
|
||||
smc91c9x_state *smc = get_safe_token(device);
|
||||
// UINT16 olddata;
|
||||
// UINT16 olddata;
|
||||
|
||||
/* determine the effective register */
|
||||
offset %= 8;
|
||||
if (offset != EREG_BANK)
|
||||
offset += 8 * (smc->reg[EREG_BANK] & 7);
|
||||
offset += 8 * (m_reg[EREG_BANK] & 7);
|
||||
|
||||
/* update the data generically */
|
||||
// olddata = smc->reg[offset];
|
||||
mem_mask &= smc->regmask[offset];
|
||||
COMBINE_DATA(&smc->reg[offset]);
|
||||
// olddata = m_reg[offset];
|
||||
mem_mask &= m_regmask[offset];
|
||||
COMBINE_DATA(&m_reg[offset]);
|
||||
|
||||
if (LOG_ETHERNET && offset != 7)
|
||||
logerror("%s:smc91c9x_w(%s) = %04X & %04X\n", device->machine().describe_context(), ethernet_regname[offset], data, mem_mask);
|
||||
logerror("%s:smc91c9x_w(%s) = %04X & %04X\n", machine().describe_context(), ethernet_regname[offset], data, mem_mask);
|
||||
|
||||
/* handle it */
|
||||
switch (offset)
|
||||
@ -424,7 +474,7 @@ WRITE16_DEVICE_HANDLER( smc91c9x_w )
|
||||
case EREG_RCR: /* receive control register */
|
||||
if (LOG_ETHERNET)
|
||||
{
|
||||
if (data & 0x8000) device->reset();
|
||||
if (data & 0x8000) reset();
|
||||
if (data & 0x8000) logerror(" SOFT RST\n");
|
||||
if (data & 0x4000) logerror(" FILT_CAR\n");
|
||||
if (data & 0x0200) logerror(" STRIP CRC\n");
|
||||
@ -474,162 +524,25 @@ WRITE16_DEVICE_HANDLER( smc91c9x_w )
|
||||
break;
|
||||
|
||||
case EREG_MMU_COMMAND: /* command register */
|
||||
process_command(smc, data);
|
||||
process_command(data);
|
||||
break;
|
||||
|
||||
case EREG_DATA_0: /* data register */
|
||||
case EREG_DATA_1: /* data register */
|
||||
{
|
||||
UINT8 *buffer = (smc->reg[EREG_POINTER] & 0x8000) ? smc->rx : smc->tx;
|
||||
int addr = smc->reg[EREG_POINTER] & 0x7ff;
|
||||
UINT8 *buffer = (m_reg[EREG_POINTER] & 0x8000) ? m_rx : m_tx;
|
||||
int addr = m_reg[EREG_POINTER] & 0x7ff;
|
||||
buffer[addr++] = data;
|
||||
if (ACCESSING_BITS_8_15)
|
||||
buffer[addr++] = data >> 8;
|
||||
if (smc->reg[EREG_POINTER] & 0x4000)
|
||||
smc->reg[EREG_POINTER] = (smc->reg[EREG_POINTER] & ~0x7ff) | (addr & 0x7ff);
|
||||
if (m_reg[EREG_POINTER] & 0x4000)
|
||||
m_reg[EREG_POINTER] = (m_reg[EREG_POINTER] & ~0x7ff) | (addr & 0x7ff);
|
||||
break;
|
||||
}
|
||||
|
||||
case EREG_INTERRUPT:
|
||||
smc->reg[EREG_INTERRUPT] &= ~(data & 0x56);
|
||||
update_ethernet_irq(smc);
|
||||
m_reg[EREG_INTERRUPT] &= ~(data & 0x56);
|
||||
update_ethernet_irq();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
DEVICE INTERFACE
|
||||
***************************************************************************/
|
||||
|
||||
/*-------------------------------------------------
|
||||
device start callback
|
||||
-------------------------------------------------*/
|
||||
|
||||
static DEVICE_START( smc91c9x )
|
||||
{
|
||||
const smc91c9x_config *config = (const smc91c9x_config *)device->static_config();
|
||||
smc91c9x_state *smc = get_safe_token(device);
|
||||
|
||||
/* validate some basic stuff */
|
||||
assert(device != NULL);
|
||||
|
||||
/* store a pointer back to the device */
|
||||
smc->device = device;
|
||||
smc->irq_handler = config->interrupt;
|
||||
|
||||
/* register ide states */
|
||||
device->save_item(NAME(smc->reg));
|
||||
device->save_item(NAME(smc->regmask));
|
||||
device->save_item(NAME(smc->irq_state));
|
||||
device->save_item(NAME(smc->alloc_count));
|
||||
device->save_item(NAME(smc->fifo_count));
|
||||
device->save_item(NAME(smc->rx));
|
||||
device->save_item(NAME(smc->tx));
|
||||
device->save_item(NAME(smc->sent));
|
||||
device->save_item(NAME(smc->recd));
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
device reset callback
|
||||
-------------------------------------------------*/
|
||||
|
||||
static DEVICE_RESET( smc91c9x )
|
||||
{
|
||||
smc91c9x_state *smc = get_safe_token(device);
|
||||
|
||||
memset(smc->reg, 0, sizeof(smc->reg));
|
||||
memset(smc->regmask, 0, sizeof(smc->regmask));
|
||||
smc->irq_state = 0;
|
||||
smc->alloc_count = 0;
|
||||
smc->fifo_count = 0;
|
||||
smc->sent = 0;
|
||||
smc->recd = 0;
|
||||
|
||||
smc->reg[EREG_TCR] = 0x0000; smc->regmask[EREG_TCR] = 0x3d87;
|
||||
smc->reg[EREG_EPH_STATUS] = 0x0000; smc->regmask[EREG_EPH_STATUS] = 0x0000;
|
||||
smc->reg[EREG_RCR] = 0x0000; smc->regmask[EREG_RCR] = 0xc307;
|
||||
smc->reg[EREG_COUNTER] = 0x0000; smc->regmask[EREG_COUNTER] = 0x0000;
|
||||
smc->reg[EREG_MIR] = 0x1212; smc->regmask[EREG_MIR] = 0x0000;
|
||||
smc->reg[EREG_MCR] = 0x3300; smc->regmask[EREG_MCR] = 0x00ff;
|
||||
smc->reg[EREG_BANK] = 0x3300; smc->regmask[EREG_BANK] = 0x0007;
|
||||
|
||||
smc->reg[EREG_CONFIG] = 0x0030; smc->regmask[EREG_CONFIG] = 0x17c6;
|
||||
smc->reg[EREG_BASE] = 0x1866; smc->regmask[EREG_BASE] = 0xfffe;
|
||||
smc->reg[EREG_IA0_1] = 0x0000; smc->regmask[EREG_IA0_1] = 0xffff;
|
||||
smc->reg[EREG_IA2_3] = 0x0000; smc->regmask[EREG_IA2_3] = 0xffff;
|
||||
smc->reg[EREG_IA4_5] = 0x0000; smc->regmask[EREG_IA4_5] = 0xffff;
|
||||
smc->reg[EREG_GENERAL_PURP] = 0x0000; smc->regmask[EREG_GENERAL_PURP] = 0xffff;
|
||||
smc->reg[EREG_CONTROL] = 0x0100; smc->regmask[EREG_CONTROL] = 0x68e7;
|
||||
|
||||
smc->reg[EREG_MMU_COMMAND] = 0x0000; smc->regmask[EREG_MMU_COMMAND] = 0x00e7;
|
||||
smc->reg[EREG_PNR_ARR] = 0x8000; smc->regmask[EREG_PNR_ARR] = 0x00ff;
|
||||
smc->reg[EREG_FIFO_PORTS] = 0x8080; smc->regmask[EREG_FIFO_PORTS] = 0x0000;
|
||||
smc->reg[EREG_POINTER] = 0x0000; smc->regmask[EREG_POINTER] = 0xf7ff;
|
||||
smc->reg[EREG_DATA_0] = 0x0000; smc->regmask[EREG_DATA_0] = 0xffff;
|
||||
smc->reg[EREG_DATA_1] = 0x0000; smc->regmask[EREG_DATA_1] = 0xffff;
|
||||
smc->reg[EREG_INTERRUPT] = 0x0004; smc->regmask[EREG_INTERRUPT] = 0x7f00;
|
||||
|
||||
smc->reg[EREG_MT0_1] = 0x0000; smc->regmask[EREG_MT0_1] = 0xffff;
|
||||
smc->reg[EREG_MT2_3] = 0x0000; smc->regmask[EREG_MT2_3] = 0xffff;
|
||||
smc->reg[EREG_MT4_5] = 0x0000; smc->regmask[EREG_MT4_5] = 0xffff;
|
||||
smc->reg[EREG_MT6_7] = 0x0000; smc->regmask[EREG_MT6_7] = 0xffff;
|
||||
smc->reg[EREG_MGMT] = 0x3030; smc->regmask[EREG_MGMT] = 0x0f0f;
|
||||
smc->reg[EREG_REVISION] = 0x3340; smc->regmask[EREG_REVISION] = 0x0000;
|
||||
smc->reg[EREG_ERCV] = 0x331f; smc->regmask[EREG_ERCV] = 0x009f;
|
||||
|
||||
update_ethernet_irq(smc);
|
||||
}
|
||||
|
||||
|
||||
smc91c9x_device::smc91c9x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
|
||||
: device_t(mconfig, type, name, tag, owner, clock, shortname, source)
|
||||
{
|
||||
m_token = global_alloc_clear(smc91c9x_state);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void smc91c9x_device::device_config_complete()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void smc91c9x_device::device_start()
|
||||
{
|
||||
DEVICE_START_NAME( smc91c9x )(this);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_reset - device-specific reset
|
||||
//-------------------------------------------------
|
||||
|
||||
void smc91c9x_device::device_reset()
|
||||
{
|
||||
DEVICE_RESET_NAME( smc91c9x )(this);
|
||||
}
|
||||
|
||||
|
||||
const device_type SMC91C94 = &device_creator<smc91c94_device>;
|
||||
|
||||
smc91c94_device::smc91c94_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: smc91c9x_device(mconfig, SMC91C94, "SMC91C94", tag, owner, clock, "smc91c94", __FILE__)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const device_type SMC91C96 = &device_creator<smc91c96_device>;
|
||||
|
||||
smc91c96_device::smc91c96_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: smc91c9x_device(mconfig, SMC91C96, "SMC91C96", tag, owner, clock, "smc91c96", __FILE__)
|
||||
{
|
||||
}
|
||||
|
@ -9,7 +9,8 @@
|
||||
#ifndef __SMC91C9X__
|
||||
#define __SMC91C9X__
|
||||
|
||||
|
||||
#define ETHER_BUFFER_SIZE (2048)
|
||||
#define ETHER_RX_BUFFERS (4)
|
||||
|
||||
/***************************************************************************
|
||||
TYPE DEFINITIONS
|
||||
@ -18,52 +19,56 @@
|
||||
typedef void (*smc91c9x_irq_func)(device_t *device, int state);
|
||||
|
||||
|
||||
struct smc91c9x_config
|
||||
struct smc91c9x_interface
|
||||
{
|
||||
smc91c9x_irq_func interrupt;
|
||||
smc91c9x_irq_func m_interrupt;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
DEVICE CONFIGURATION MACROS
|
||||
***************************************************************************/
|
||||
|
||||
#define MCFG_SMC91C94_ADD(_tag, _config) \
|
||||
MCFG_DEVICE_ADD(_tag, SMC91C94, 0) \
|
||||
MCFG_DEVICE_CONFIG(_config)
|
||||
|
||||
#define MCFG_SMC91C96_ADD(_tag, _config) \
|
||||
MCFG_DEVICE_ADD(_tag, SMC91C96, 0) \
|
||||
MCFG_DEVICE_CONFIG(_config)
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
FUNCTION PROTOTYPES
|
||||
***************************************************************************/
|
||||
|
||||
DECLARE_READ16_DEVICE_HANDLER( smc91c9x_r );
|
||||
DECLARE_WRITE16_DEVICE_HANDLER( smc91c9x_w );
|
||||
|
||||
|
||||
/* ----- device interface ----- */
|
||||
class smc91c9x_device : public device_t
|
||||
class smc91c9x_device : public device_t,
|
||||
public smc91c9x_interface
|
||||
{
|
||||
public:
|
||||
smc91c9x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
|
||||
~smc91c9x_device() { global_free(m_token); }
|
||||
~smc91c9x_device() {}
|
||||
|
||||
// access to legacy token
|
||||
void *token() const { assert(m_token != NULL); return m_token; }
|
||||
DECLARE_READ16_MEMBER( read );
|
||||
DECLARE_WRITE16_MEMBER( write );
|
||||
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
private:
|
||||
// internal state
|
||||
void *m_token;
|
||||
smc91c9x_irq_func m_irq_handler;
|
||||
|
||||
/* raw register data and masks */
|
||||
UINT16 m_reg[64];
|
||||
UINT16 m_regmask[64];
|
||||
|
||||
/* IRQ information */
|
||||
UINT8 m_irq_state;
|
||||
|
||||
/* allocate information */
|
||||
UINT8 m_alloc_count;
|
||||
|
||||
/* transmit/receive FIFOs */
|
||||
UINT8 m_fifo_count;
|
||||
UINT8 m_rx[ETHER_BUFFER_SIZE * ETHER_RX_BUFFERS];
|
||||
UINT8 m_tx[ETHER_BUFFER_SIZE];
|
||||
|
||||
/* counters */
|
||||
UINT32 m_sent;
|
||||
UINT32 m_recd;
|
||||
|
||||
void update_ethernet_irq();
|
||||
void update_stats();
|
||||
void finish_enqueue(int param);
|
||||
void process_command(UINT16 data);
|
||||
};
|
||||
|
||||
|
||||
@ -83,5 +88,17 @@ public:
|
||||
|
||||
extern const device_type SMC91C96;
|
||||
|
||||
/***************************************************************************
|
||||
DEVICE CONFIGURATION MACROS
|
||||
***************************************************************************/
|
||||
|
||||
#define MCFG_SMC91C94_ADD(_tag, _config) \
|
||||
MCFG_DEVICE_ADD(_tag, SMC91C94, 0) \
|
||||
MCFG_DEVICE_CONFIG(_config)
|
||||
|
||||
#define MCFG_SMC91C96_ADD(_tag, _config) \
|
||||
MCFG_DEVICE_ADD(_tag, SMC91C96, 0) \
|
||||
MCFG_DEVICE_CONFIG(_config)
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -430,7 +430,8 @@ public:
|
||||
m_asic_reset(*this, "asic_reset"),
|
||||
m_rombase(*this, "rombase"),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_ide(*this, "ide")
|
||||
m_ide(*this, "ide"),
|
||||
m_ethernet(*this, "ethernet")
|
||||
{
|
||||
}
|
||||
|
||||
@ -440,6 +441,9 @@ public:
|
||||
required_shared_ptr<UINT32> m_interrupt_config;
|
||||
required_shared_ptr<UINT32> m_asic_reset;
|
||||
required_shared_ptr<UINT32> m_rombase;
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<bus_master_ide_controller_device> m_ide;
|
||||
optional_device<smc91c94_device> m_ethernet;
|
||||
galileo_data m_galileo;
|
||||
widget_data m_widget;
|
||||
device_t *m_voodoo;
|
||||
@ -517,8 +521,6 @@ public:
|
||||
void widget_reset();
|
||||
void update_widget_irq();
|
||||
void init_common(int ioasic, int serialnum, int yearoffs, int config);
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<bus_master_ide_controller_device> m_ide;
|
||||
};
|
||||
|
||||
/*************************************
|
||||
@ -1518,21 +1520,19 @@ WRITE32_MEMBER(seattle_state::carnevil_gun_w)
|
||||
|
||||
READ32_MEMBER(seattle_state::ethernet_r)
|
||||
{
|
||||
device_t *device = machine().device("ethernet");
|
||||
if (!(offset & 8))
|
||||
return smc91c9x_r(device, space, offset & 7, mem_mask & 0xffff);
|
||||
return m_ethernet->read(space, offset & 7, mem_mask & 0xffff);
|
||||
else
|
||||
return smc91c9x_r(device, space, offset & 7, mem_mask & 0x00ff);
|
||||
return m_ethernet->read(space, offset & 7, mem_mask & 0x00ff);
|
||||
}
|
||||
|
||||
|
||||
WRITE32_MEMBER(seattle_state::ethernet_w)
|
||||
{
|
||||
device_t *device = machine().device("ethernet");
|
||||
if (!(offset & 8))
|
||||
smc91c9x_w(device, space, offset & 7, data & 0xffff, mem_mask | 0xffff);
|
||||
m_ethernet->write(space, offset & 7, data & 0xffff, mem_mask | 0xffff);
|
||||
else
|
||||
smc91c9x_w(device, space, offset & 7, data & 0x00ff, mem_mask | 0x00ff);
|
||||
m_ethernet->write(space, offset & 7, data & 0x00ff, mem_mask | 0x00ff);
|
||||
}
|
||||
|
||||
|
||||
@ -1565,7 +1565,6 @@ void seattle_state::update_widget_irq()
|
||||
|
||||
READ32_MEMBER(seattle_state::widget_r)
|
||||
{
|
||||
device_t *device = machine().device("ethernet");
|
||||
UINT32 result = ~0;
|
||||
|
||||
switch (offset)
|
||||
@ -1584,7 +1583,7 @@ READ32_MEMBER(seattle_state::widget_r)
|
||||
break;
|
||||
|
||||
case WREG_ETHER_DATA:
|
||||
result = smc91c9x_r(device, space, m_widget.ethernet_addr & 7, mem_mask & 0xffff);
|
||||
result = m_ethernet->read(space, m_widget.ethernet_addr & 7, mem_mask & 0xffff);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1596,7 +1595,6 @@ READ32_MEMBER(seattle_state::widget_r)
|
||||
|
||||
WRITE32_MEMBER(seattle_state::widget_w)
|
||||
{
|
||||
device_t *device = machine().device("ethernet");
|
||||
if (LOG_WIDGET)
|
||||
logerror("Widget write (%02X) = %08X & %08X\n", offset*4, data, mem_mask);
|
||||
|
||||
@ -1616,7 +1614,7 @@ WRITE32_MEMBER(seattle_state::widget_w)
|
||||
break;
|
||||
|
||||
case WREG_ETHER_DATA:
|
||||
smc91c9x_w(device, space, m_widget.ethernet_addr & 7, data & 0xffff, mem_mask & 0xffff);
|
||||
m_ethernet->write(space, m_widget.ethernet_addr & 7, data & 0xffff, mem_mask & 0xffff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2569,7 +2567,7 @@ static MACHINE_CONFIG_DERIVED( seattle150, seattle_common )
|
||||
MCFG_CPU_PROGRAM_MAP(seattle_map)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
static const smc91c9x_config ethernet_intf =
|
||||
static const smc91c9x_interface ethernet_intf =
|
||||
{
|
||||
ethernet_interrupt
|
||||
};
|
||||
|
@ -1500,21 +1500,25 @@ static WRITE32_DEVICE_HANDLER( ide_bus_master32_w )
|
||||
|
||||
static READ32_DEVICE_HANDLER( ethernet_r )
|
||||
{
|
||||
smc91c94_device *ethernet = space.machine().device<smc91c94_device>("ethernet");
|
||||
|
||||
UINT32 result = 0;
|
||||
if (ACCESSING_BITS_0_15)
|
||||
result |= smc91c9x_r(device, space, offset * 2 + 0, mem_mask);
|
||||
result |= ethernet->read(space, offset * 2 + 0, mem_mask);
|
||||
if (ACCESSING_BITS_16_31)
|
||||
result |= smc91c9x_r(device, space, offset * 2 + 1, mem_mask >> 16) << 16;
|
||||
result |= ethernet->read(space, offset * 2 + 1, mem_mask >> 16) << 16;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static WRITE32_DEVICE_HANDLER( ethernet_w )
|
||||
{
|
||||
smc91c94_device *ethernet = space.machine().device<smc91c94_device>("ethernet");
|
||||
|
||||
if (ACCESSING_BITS_0_15)
|
||||
smc91c9x_w(device, space, offset * 2 + 0, data, mem_mask);
|
||||
ethernet->write(space, offset * 2 + 0, data, mem_mask);
|
||||
if (ACCESSING_BITS_16_31)
|
||||
smc91c9x_w(device, space, offset * 2 + 1, data >> 16, mem_mask >> 16);
|
||||
ethernet->write(space, offset * 2 + 1, data >> 16, mem_mask >> 16);
|
||||
}
|
||||
|
||||
|
||||
@ -2232,7 +2236,7 @@ static const mips3_config r5000_config =
|
||||
SYSTEM_CLOCK /* system clock rate */
|
||||
};
|
||||
|
||||
static const smc91c9x_config ethernet_intf =
|
||||
static const smc91c9x_interface ethernet_intf =
|
||||
{
|
||||
ethernet_interrupt
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user