mirror of
https://github.com/holub/mame
synced 2025-04-25 17:56:43 +03:00
(MESS) modernized uPD71071 DMA device. [Fabio Priuli]
This commit is contained in:
parent
f8269256cd
commit
f9d591b7bc
@ -458,25 +458,25 @@ WRITE8_MEMBER(towns_state::towns_sys6c_w)
|
||||
READ8_MEMBER(towns_state::towns_dma1_r)
|
||||
{
|
||||
// logerror("DMA#1: read register %i\n",offset);
|
||||
return upd71071_r(m_dma_1,space, offset);
|
||||
return m_dma_1->read(space, offset);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(towns_state::towns_dma1_w)
|
||||
{
|
||||
// logerror("DMA#1: wrote 0x%02x to register %i\n",data,offset);
|
||||
upd71071_w(m_dma_1,space, offset,data);
|
||||
m_dma_1->write(space, offset, data);
|
||||
}
|
||||
|
||||
READ8_MEMBER(towns_state::towns_dma2_r)
|
||||
{
|
||||
logerror("DMA#2: read register %i\n",offset);
|
||||
return upd71071_r(m_dma_2,space, offset);
|
||||
return m_dma_2->read(space, offset);
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(towns_state::towns_dma2_w)
|
||||
{
|
||||
logerror("DMA#2: wrote 0x%02x to register %i\n",data,offset);
|
||||
upd71071_w(m_dma_2,space, offset,data);
|
||||
m_dma_2->write(space, offset, data);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -493,7 +493,7 @@ WRITE_LINE_MEMBER( towns_state::mb8877a_irq_w )
|
||||
|
||||
WRITE_LINE_MEMBER( towns_state::mb8877a_drq_w )
|
||||
{
|
||||
upd71071_dmarq(m_dma_1, state, 0);
|
||||
m_dma_1->dmarq(state, 0);
|
||||
}
|
||||
|
||||
READ8_MEMBER(towns_state::towns_floppy_r)
|
||||
@ -1394,14 +1394,14 @@ UINT8 towns_state::towns_cd_get_track()
|
||||
|
||||
TIMER_CALLBACK_MEMBER(towns_state::towns_cdrom_read_byte)
|
||||
{
|
||||
device_t* device = (device_t* )ptr;
|
||||
upd71071_device* device = (upd71071_device* )ptr;
|
||||
int masked;
|
||||
// TODO: support software transfers, for now DMA is assumed.
|
||||
|
||||
if(m_towns_cd.buffer_ptr < 0) // transfer has ended
|
||||
return;
|
||||
|
||||
masked = upd71071_dmarq(device,param,3); // CD-ROM controller uses DMA1 channel 3
|
||||
masked = device->dmarq(param, 3); // CD-ROM controller uses DMA1 channel 3
|
||||
// logerror("DMARQ: param=%i ret=%i bufferptr=%i\n",param,masked,m_towns_cd.buffer_ptr);
|
||||
if(param != 0)
|
||||
{
|
||||
@ -1993,7 +1993,7 @@ WRITE_LINE_MEMBER(towns_state::towns_scsi_irq)
|
||||
|
||||
WRITE_LINE_MEMBER(towns_state::towns_scsi_drq)
|
||||
{
|
||||
upd71071_dmarq(m_dma_1,state,1); // SCSI HDs use channel 1
|
||||
m_dma_1->dmarq(state, 1); // SCSI HDs use channel 1
|
||||
}
|
||||
|
||||
|
||||
@ -2605,8 +2605,6 @@ void marty_state::driver_start()
|
||||
void towns_state::machine_reset()
|
||||
{
|
||||
address_space &program = m_maincpu->space(AS_PROGRAM);
|
||||
m_dma_1 = machine().device("dma_1");
|
||||
m_dma_2 = machine().device("dma_2");
|
||||
m_fdc = machine().device("fdc");
|
||||
m_messram = m_ram;
|
||||
m_cdrom = machine().device<cdrom_image_device>("cdrom");
|
||||
|
@ -1141,7 +1141,7 @@ WRITE8_MEMBER(pc88va_state::pc88va_fdc_w)
|
||||
timer_set(attotime::from_msec(100), TIMER_PC88VA_FDC_TIMER);
|
||||
|
||||
if((m_fdc_ctrl_2 & 0x10) != (data & 0x10))
|
||||
upd71071_dmarq(m_dmac,1,2);
|
||||
m_dmac->dmarq(1, 2);
|
||||
|
||||
if(data & 0x80) // correct?
|
||||
machine().device<upd765a_device>("upd765")->reset();
|
||||
@ -1278,7 +1278,7 @@ static ADDRESS_MAP_START( pc88va_io_map, AS_IO, 16, pc88va_state )
|
||||
AM_RANGE(0x0156, 0x0157) AM_READ8(rom_bank_r,0x00ff) // ROM bank status
|
||||
// AM_RANGE(0x0158, 0x0159) Interruption Mode Modification
|
||||
// AM_RANGE(0x015c, 0x015f) NMI mask port (strobe port)
|
||||
AM_RANGE(0x0160, 0x016f) AM_DEVREADWRITE8_LEGACY("dmac", upd71071_r, upd71071_w,0xffff) // DMA Controller
|
||||
AM_RANGE(0x0160, 0x016f) AM_DEVREADWRITE8("dmac", upd71071_device, read, write, 0xffff) // DMA Controller
|
||||
AM_RANGE(0x0184, 0x0187) AM_DEVREADWRITE8("pic8259_slave", pic8259_device, read, write, 0x00ff)
|
||||
AM_RANGE(0x0188, 0x018b) AM_DEVREADWRITE8("pic8259_master", pic8259_device, read, write, 0x00ff) // ICU, also controls 8214 emulation
|
||||
// AM_RANGE(0x0190, 0x0191) System Port 5
|
||||
@ -1769,7 +1769,7 @@ static const struct pit8253_interface pc88va_pit8253_config =
|
||||
void pc88va_state::fdc_drq(bool state)
|
||||
{
|
||||
printf("%02x DRQ\n",state);
|
||||
upd71071_dmarq(m_dmac,state,2);
|
||||
m_dmac->dmarq(state, 2);
|
||||
}
|
||||
|
||||
void pc88va_state::fdc_irq(bool state)
|
||||
@ -1882,7 +1882,7 @@ static MACHINE_CONFIG_START( pc88va, pc88va_state )
|
||||
|
||||
MCFG_PIC8259_ADD( "pic8259_slave", DEVWRITELINE("pic8259_master", pic8259_device, ir7_w), GND, NULL )
|
||||
|
||||
MCFG_UPD71071_ADD("dmac",pc88va_dma_config)
|
||||
MCFG_UPD71071_ADD("dmac", pc88va_dma_config)
|
||||
|
||||
MCFG_UPD765A_ADD("upd765", false, true)
|
||||
MCFG_FLOPPY_DRIVE_ADD("upd765:0", pc88va_floppies, "525hd", pc88va_state::floppy_formats)
|
||||
|
@ -83,6 +83,8 @@ class towns_state : public driver_device
|
||||
m_pic_master(*this, "pic8259_master"),
|
||||
m_pic_slave(*this, "pic8259_slave"),
|
||||
m_pit(*this, "pit"),
|
||||
m_dma_1(*this, "dma_1"),
|
||||
m_dma_2(*this, "dma_2"),
|
||||
m_ram(*this, RAM_TAG),
|
||||
m_nvram(*this, "nvram"),
|
||||
m_nvram16(*this, "nvram16")
|
||||
@ -94,9 +96,9 @@ class towns_state : public driver_device
|
||||
required_device<pic8259_device> m_pic_master;
|
||||
required_device<pic8259_device> m_pic_slave;
|
||||
required_device<pit8253_device> m_pit;
|
||||
required_device<upd71071_device> m_dma_1;
|
||||
required_device<upd71071_device> m_dma_2;
|
||||
required_device<ram_device> m_ram;
|
||||
device_t* m_dma_1;
|
||||
device_t* m_dma_2;
|
||||
device_t* m_fdc;
|
||||
ram_device* m_messram;
|
||||
cdrom_image_device* m_cdrom;
|
||||
|
@ -80,154 +80,151 @@
|
||||
#include "emu.h"
|
||||
#include "machine/upd71071.h"
|
||||
|
||||
struct upd71071_reg
|
||||
{
|
||||
UINT8 initialise;
|
||||
UINT8 channel;
|
||||
UINT16 count_current[4];
|
||||
UINT16 count_base[4];
|
||||
UINT32 address_current[4];
|
||||
UINT32 address_base[4];
|
||||
UINT16 device_control;
|
||||
UINT8 mode_control[4];
|
||||
UINT8 status;
|
||||
UINT8 temp_l;
|
||||
UINT8 temp_h;
|
||||
UINT8 request;
|
||||
UINT8 mask;
|
||||
};
|
||||
|
||||
struct upd71071_t
|
||||
{
|
||||
struct upd71071_reg reg;
|
||||
int selected_channel;
|
||||
int buswidth;
|
||||
int dmarq[4];
|
||||
emu_timer* timer[4];
|
||||
int in_progress[4];
|
||||
int transfer_size[4];
|
||||
int base;
|
||||
const upd71071_intf* intf;
|
||||
devcb_resolved_write_line m_out_hreq_func;
|
||||
devcb_resolved_write_line m_out_eop_func;
|
||||
devcb_resolved_read16 m_dma_read[4];
|
||||
devcb_resolved_write16 m_dma_write[4];
|
||||
devcb_resolved_write_line m_out_dack_func[4];
|
||||
int m_hreq;
|
||||
int m_eop;
|
||||
};
|
||||
const device_type UPD71071 = &device_creator<upd71071_device>;
|
||||
|
||||
INLINE upd71071_t *get_safe_token(device_t *device)
|
||||
upd71071_device::upd71071_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, UPD71071, "NEC uPD71071", tag, owner, clock)
|
||||
{
|
||||
assert(device != NULL);
|
||||
assert(device->type() == UPD71071);
|
||||
|
||||
return (upd71071_t*)downcast<upd71071_device *>(device)->token();
|
||||
}
|
||||
|
||||
static TIMER_CALLBACK(dma_transfer_timer)
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void upd71071_device::device_config_complete()
|
||||
{
|
||||
// inherit a copy of the static data
|
||||
const upd71071_intf *intf = reinterpret_cast<const upd71071_intf *>(static_config());
|
||||
if (intf != NULL)
|
||||
*static_cast<upd71071_intf *>(this) = *intf;
|
||||
|
||||
// or initialize to defaults if none provided
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void upd71071_device::device_start()
|
||||
{
|
||||
m_cpu = machine().device<cpu_device>(cputag);
|
||||
|
||||
m_out_hreq_func.resolve(m_out_hreq_cb, *this);
|
||||
m_out_eop_func.resolve(m_out_eop_cb, *this);
|
||||
for (int x = 0; x < 4; x++)
|
||||
{
|
||||
m_timer[x] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(upd71071_device::dma_transfer_timer),this));
|
||||
m_dma_read[x].resolve(m_dma_read_cb[x], *this);
|
||||
m_dma_write[x].resolve(m_dma_write_cb[x], *this);
|
||||
m_out_dack_func[x].resolve(m_out_dack_cb[x], *this);
|
||||
}
|
||||
m_selected_channel = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
TIMER_CALLBACK_MEMBER(upd71071_device::dma_transfer_timer)
|
||||
{
|
||||
// single byte or word transfer
|
||||
device_t* device = (device_t*)ptr;
|
||||
upd71071_t* dmac = get_safe_token(device);
|
||||
address_space& space = device->machine().device(dmac->intf->cputag)->memory().space(AS_PROGRAM);
|
||||
address_space& space = m_cpu->space(AS_PROGRAM);
|
||||
int channel = param;
|
||||
UINT16 data = 0; // data to transfer
|
||||
|
||||
switch(dmac->reg.mode_control[channel] & 0x0c)
|
||||
switch (m_reg.mode_control[channel] & 0x0c)
|
||||
{
|
||||
case 0x00: // Verify
|
||||
break;
|
||||
case 0x04: // I/O -> memory
|
||||
if(!dmac->m_dma_read[channel].isnull())
|
||||
data = dmac->m_dma_read[channel](0);
|
||||
space.write_byte(dmac->reg.address_current[channel],data & 0xff);
|
||||
if(dmac->reg.mode_control[channel] & 0x20) // Address direction
|
||||
dmac->reg.address_current[channel]--;
|
||||
if (!m_dma_read[channel].isnull())
|
||||
data = m_dma_read[channel](0);
|
||||
space.write_byte(m_reg.address_current[channel], data & 0xff);
|
||||
if (m_reg.mode_control[channel] & 0x20) // Address direction
|
||||
m_reg.address_current[channel]--;
|
||||
else
|
||||
dmac->reg.address_current[channel]++;
|
||||
if(dmac->reg.count_current[channel] == 0)
|
||||
m_reg.address_current[channel]++;
|
||||
if (m_reg.count_current[channel] == 0)
|
||||
{
|
||||
if(dmac->reg.mode_control[channel] & 0x10) // auto-initialise
|
||||
if (m_reg.mode_control[channel] & 0x10) // auto-initialise
|
||||
{
|
||||
dmac->reg.address_current[channel] = dmac->reg.address_base[channel];
|
||||
dmac->reg.count_current[channel] = dmac->reg.count_base[channel];
|
||||
m_reg.address_current[channel] = m_reg.address_base[channel];
|
||||
m_reg.count_current[channel] = m_reg.count_base[channel];
|
||||
}
|
||||
// TODO: send terminal count
|
||||
set_eop(device,ASSERT_LINE);
|
||||
set_eop(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
dmac->reg.count_current[channel]--;
|
||||
m_reg.count_current[channel]--;
|
||||
break;
|
||||
case 0x08: // memory -> I/O
|
||||
data = space.read_byte(dmac->reg.address_current[channel]);
|
||||
if(!dmac->m_dma_write[channel].isnull())
|
||||
dmac->m_dma_write[channel](0,data);
|
||||
if(dmac->reg.mode_control[channel] & 0x20) // Address direction
|
||||
dmac->reg.address_current[channel]--;
|
||||
data = space.read_byte(m_reg.address_current[channel]);
|
||||
if (!m_dma_write[channel].isnull())
|
||||
m_dma_write[channel](0, data);
|
||||
if (m_reg.mode_control[channel] & 0x20) // Address direction
|
||||
m_reg.address_current[channel]--;
|
||||
else
|
||||
dmac->reg.address_current[channel]++;
|
||||
if(dmac->reg.count_current[channel] == 0)
|
||||
m_reg.address_current[channel]++;
|
||||
if (m_reg.count_current[channel] == 0)
|
||||
{
|
||||
if(dmac->reg.mode_control[channel] & 0x10) // auto-initialise
|
||||
if (m_reg.mode_control[channel] & 0x10) // auto-initialise
|
||||
{
|
||||
dmac->reg.address_current[channel] = dmac->reg.address_base[channel];
|
||||
dmac->reg.count_current[channel] = dmac->reg.count_base[channel];
|
||||
m_reg.address_current[channel] = m_reg.address_base[channel];
|
||||
m_reg.count_current[channel] = m_reg.count_base[channel];
|
||||
}
|
||||
// TODO: send terminal count
|
||||
set_eop(device,ASSERT_LINE);
|
||||
set_eop(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
dmac->reg.count_current[channel]--;
|
||||
m_reg.count_current[channel]--;
|
||||
break;
|
||||
case 0x0c: // Invalid
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void upd71071_soft_reset(device_t* device)
|
||||
void upd71071_device::soft_reset()
|
||||
{
|
||||
upd71071_t* dmac = get_safe_token(device);
|
||||
int x;
|
||||
|
||||
// Does not change base/current address, count, or buswidth
|
||||
dmac->selected_channel = 0;
|
||||
dmac->base = 0;
|
||||
for(x=0;x<4;x++)
|
||||
dmac->reg.mode_control[x] = 0;
|
||||
dmac->reg.device_control = 0;
|
||||
dmac->reg.temp_h = 0;
|
||||
dmac->reg.temp_l = 0;
|
||||
dmac->reg.mask = 0x0f; // mask all channels
|
||||
dmac->reg.status &= ~0x0f; // clears bits 0-3 only
|
||||
dmac->reg.request = 0;
|
||||
m_selected_channel = 0;
|
||||
m_base = 0;
|
||||
for (int x = 0; x < 4; x++)
|
||||
m_reg.mode_control[x] = 0;
|
||||
m_reg.device_control = 0;
|
||||
m_reg.temp_h = 0;
|
||||
m_reg.temp_l = 0;
|
||||
m_reg.mask = 0x0f; // mask all channels
|
||||
m_reg.status &= ~0x0f; // clears bits 0-3 only
|
||||
m_reg.request = 0;
|
||||
}
|
||||
|
||||
int upd71071_dmarq(device_t* device, int state,int channel)
|
||||
int upd71071_device::dmarq(int state, int channel)
|
||||
{
|
||||
upd71071_t* dmac = get_safe_token(device);
|
||||
|
||||
if(state != 0)
|
||||
if (state != 0)
|
||||
{
|
||||
if(dmac->reg.device_control & 0x0004)
|
||||
if (m_reg.device_control & 0x0004)
|
||||
return 2;
|
||||
|
||||
if(dmac->reg.mask & (1 << channel)) // is channel masked?
|
||||
if (m_reg.mask & (1 << channel)) // is channel masked?
|
||||
return 1;
|
||||
|
||||
dmac->dmarq[channel] = 1; // DMARQ line is set
|
||||
dmac->reg.status |= (0x10 << channel);
|
||||
m_dmarq[channel] = 1; // DMARQ line is set
|
||||
m_reg.status |= (0x10 << channel);
|
||||
|
||||
// start transfer
|
||||
switch(dmac->reg.mode_control[channel] & 0xc0)
|
||||
switch (m_reg.mode_control[channel] & 0xc0)
|
||||
{
|
||||
case 0x00: // Demand
|
||||
// TODO
|
||||
set_eop(device,CLEAR_LINE);
|
||||
dmac->timer[channel]->adjust(attotime::from_hz(dmac->intf->clock),channel);
|
||||
set_eop(CLEAR_LINE);
|
||||
m_timer[channel]->adjust(attotime::from_hz(m_upd_clock), channel);
|
||||
break;
|
||||
case 0x40: // Single
|
||||
dmac->timer[channel]->adjust(attotime::from_hz(dmac->intf->clock),channel);
|
||||
m_timer[channel]->adjust(attotime::from_hz(m_upd_clock), channel);
|
||||
break;
|
||||
case 0x80: // Block
|
||||
// TODO
|
||||
@ -240,249 +237,191 @@ int upd71071_dmarq(device_t* device, int state,int channel)
|
||||
}
|
||||
else
|
||||
{
|
||||
dmac->dmarq[channel] = 0; // clear DMARQ line
|
||||
dmac->reg.status &= ~(0x10 << channel);
|
||||
dmac->reg.status |= (0x01 << channel); // END or TC
|
||||
m_dmarq[channel] = 0; // clear DMARQ line
|
||||
m_reg.status &= ~(0x10 << channel);
|
||||
m_reg.status |= (0x01 << channel); // END or TC
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEVICE_START(upd71071)
|
||||
READ8_MEMBER(upd71071_device::read)
|
||||
{
|
||||
upd71071_t* dmac = get_safe_token(device);
|
||||
int x;
|
||||
|
||||
dmac->intf = (const upd71071_intf*)device->static_config();
|
||||
dmac->m_out_hreq_func.resolve(dmac->intf->m_out_hreq_cb, *device);
|
||||
dmac->m_out_eop_func.resolve(dmac->intf->m_out_eop_cb, *device);
|
||||
for(x=0;x<4;x++)
|
||||
{
|
||||
dmac->timer[x] = device->machine().scheduler().timer_alloc(FUNC(dma_transfer_timer), (void*)device);
|
||||
dmac->m_dma_read[x].resolve(dmac->intf->m_dma_read[x], *device);
|
||||
dmac->m_dma_write[x].resolve(dmac->intf->m_dma_write[x], *device);
|
||||
dmac->m_out_dack_func[x].resolve(dmac->intf->m_out_dack_cb[x], *device);
|
||||
}
|
||||
dmac->selected_channel = 0;
|
||||
}
|
||||
|
||||
static READ8_DEVICE_HANDLER(upd71071_read)
|
||||
{
|
||||
upd71071_t* dmac = get_safe_token(device);
|
||||
UINT8 ret = 0;
|
||||
|
||||
logerror("DMA: read from register %02x\n",offset);
|
||||
switch(offset)
|
||||
{
|
||||
case 0x01: // Channel
|
||||
ret = (1 << dmac->selected_channel);
|
||||
if(dmac->base != 0)
|
||||
ret = (1 << m_selected_channel);
|
||||
if (m_base != 0)
|
||||
ret |= 0x10;
|
||||
break;
|
||||
case 0x02: // Count (low)
|
||||
if(dmac->base != 0)
|
||||
ret = dmac->reg.count_base[dmac->selected_channel] & 0xff;
|
||||
if (m_base != 0)
|
||||
ret = m_reg.count_base[m_selected_channel] & 0xff;
|
||||
else
|
||||
ret = dmac->reg.count_current[dmac->selected_channel] & 0xff;
|
||||
ret = m_reg.count_current[m_selected_channel] & 0xff;
|
||||
break;
|
||||
case 0x03: // Count (high)
|
||||
if(dmac->base != 0)
|
||||
ret = (dmac->reg.count_base[dmac->selected_channel] >> 8) & 0xff;
|
||||
if (m_base != 0)
|
||||
ret = (m_reg.count_base[m_selected_channel] >> 8) & 0xff;
|
||||
else
|
||||
ret = (dmac->reg.count_current[dmac->selected_channel] >> 8) & 0xff;
|
||||
ret = (m_reg.count_current[m_selected_channel] >> 8) & 0xff;
|
||||
break;
|
||||
case 0x04: // Address (low)
|
||||
if(dmac->base != 0)
|
||||
ret = dmac->reg.address_base[dmac->selected_channel] & 0xff;
|
||||
if (m_base != 0)
|
||||
ret = m_reg.address_base[m_selected_channel] & 0xff;
|
||||
else
|
||||
ret = dmac->reg.address_current[dmac->selected_channel] & 0xff;
|
||||
ret = m_reg.address_current[m_selected_channel] & 0xff;
|
||||
break;
|
||||
case 0x05: // Address (mid)
|
||||
if(dmac->base != 0)
|
||||
ret = (dmac->reg.address_base[dmac->selected_channel] >> 8) & 0xff;
|
||||
if (m_base != 0)
|
||||
ret = (m_reg.address_base[m_selected_channel] >> 8) & 0xff;
|
||||
else
|
||||
ret = (dmac->reg.address_current[dmac->selected_channel] >> 8) & 0xff;
|
||||
ret = (m_reg.address_current[m_selected_channel] >> 8) & 0xff;
|
||||
break;
|
||||
case 0x06: // Address (high)
|
||||
if(dmac->base != 0)
|
||||
ret = (dmac->reg.address_base[dmac->selected_channel] >> 16) & 0xff;
|
||||
if (m_base != 0)
|
||||
ret = (m_reg.address_base[m_selected_channel] >> 16) & 0xff;
|
||||
else
|
||||
ret = (dmac->reg.address_current[dmac->selected_channel] >> 16) & 0xff;
|
||||
ret = (m_reg.address_current[m_selected_channel] >> 16) & 0xff;
|
||||
break;
|
||||
case 0x07: // Address (highest)
|
||||
if(dmac->base != 0)
|
||||
ret = (dmac->reg.address_base[dmac->selected_channel] >> 24) & 0xff;
|
||||
if (m_base != 0)
|
||||
ret = (m_reg.address_base[m_selected_channel] >> 24) & 0xff;
|
||||
else
|
||||
ret = (dmac->reg.address_current[dmac->selected_channel] >> 24) & 0xff;
|
||||
ret = (m_reg.address_current[m_selected_channel] >> 24) & 0xff;
|
||||
break;
|
||||
case 0x08: // Device control (low)
|
||||
ret = dmac->reg.device_control & 0xff;
|
||||
ret = m_reg.device_control & 0xff;
|
||||
break;
|
||||
case 0x09: // Device control (high)
|
||||
ret = (dmac->reg.device_control >> 8) & 0xff;
|
||||
ret = (m_reg.device_control >> 8) & 0xff;
|
||||
break;
|
||||
case 0x0a: // Mode control
|
||||
ret = dmac->reg.mode_control[dmac->selected_channel];
|
||||
ret = m_reg.mode_control[m_selected_channel];
|
||||
break;
|
||||
case 0x0b: // Status
|
||||
ret = dmac->reg.status;
|
||||
dmac->reg.status &= ~0x0f; // resets END/TC?
|
||||
ret = m_reg.status;
|
||||
m_reg.status &= ~0x0f; // resets END/TC?
|
||||
break;
|
||||
case 0x0c: // Temporary (low)
|
||||
ret = dmac->reg.temp_h;
|
||||
ret = m_reg.temp_h;
|
||||
break;
|
||||
case 0x0d: // Temporary (high)
|
||||
ret = dmac->reg.temp_l;
|
||||
ret = m_reg.temp_l;
|
||||
break;
|
||||
case 0x0e: // Request
|
||||
ret = dmac->reg.request;
|
||||
ret = m_reg.request;
|
||||
break;
|
||||
case 0x0f: // Mask
|
||||
ret = dmac->reg.mask;
|
||||
ret = m_reg.mask;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static WRITE8_DEVICE_HANDLER(upd71071_write)
|
||||
WRITE8_MEMBER(upd71071_device::write)
|
||||
{
|
||||
upd71071_t* dmac = get_safe_token(device);
|
||||
|
||||
switch(offset)
|
||||
switch (offset)
|
||||
{
|
||||
case 0x00: // Initialise
|
||||
// TODO: reset (bit 0)
|
||||
dmac->buswidth = data & 0x02;
|
||||
if(data & 0x01)
|
||||
upd71071_soft_reset(device);
|
||||
m_buswidth = data & 0x02;
|
||||
if (data & 0x01)
|
||||
soft_reset();
|
||||
logerror("DMA: Initialise [%02x]\n",data);
|
||||
break;
|
||||
case 0x01: // Channel
|
||||
dmac->selected_channel = data & 0x03;
|
||||
dmac->base = data & 0x04;
|
||||
m_selected_channel = data & 0x03;
|
||||
m_base = data & 0x04;
|
||||
logerror("DMA: Channel selected [%02x]\n",data);
|
||||
break;
|
||||
case 0x02: // Count (low)
|
||||
dmac->reg.count_base[dmac->selected_channel] =
|
||||
(dmac->reg.count_base[dmac->selected_channel] & 0xff00) | data;
|
||||
if(dmac->base == 0)
|
||||
dmac->reg.count_current[dmac->selected_channel] =
|
||||
(dmac->reg.count_current[dmac->selected_channel] & 0xff00) | data;
|
||||
logerror("DMA: Channel %i Counter set [%04x]\n",dmac->selected_channel,dmac->reg.count_base[dmac->selected_channel]);
|
||||
m_reg.count_base[m_selected_channel] =
|
||||
(m_reg.count_base[m_selected_channel] & 0xff00) | data;
|
||||
if (m_base == 0)
|
||||
m_reg.count_current[m_selected_channel] =
|
||||
(m_reg.count_current[m_selected_channel] & 0xff00) | data;
|
||||
logerror("DMA: Channel %i Counter set [%04x]\n",m_selected_channel,m_reg.count_base[m_selected_channel]);
|
||||
break;
|
||||
case 0x03: // Count (high)
|
||||
dmac->reg.count_base[dmac->selected_channel] =
|
||||
(dmac->reg.count_base[dmac->selected_channel] & 0x00ff) | (data << 8);
|
||||
if(dmac->base == 0)
|
||||
dmac->reg.count_current[dmac->selected_channel] =
|
||||
(dmac->reg.count_current[dmac->selected_channel] & 0x00ff) | (data << 8);
|
||||
logerror("DMA: Channel %i Counter set [%04x]\n",dmac->selected_channel,dmac->reg.count_base[dmac->selected_channel]);
|
||||
m_reg.count_base[m_selected_channel] =
|
||||
(m_reg.count_base[m_selected_channel] & 0x00ff) | (data << 8);
|
||||
if (m_base == 0)
|
||||
m_reg.count_current[m_selected_channel] =
|
||||
(m_reg.count_current[m_selected_channel] & 0x00ff) | (data << 8);
|
||||
logerror("DMA: Channel %i Counter set [%04x]\n",m_selected_channel,m_reg.count_base[m_selected_channel]);
|
||||
break;
|
||||
case 0x04: // Address (low)
|
||||
dmac->reg.address_base[dmac->selected_channel] =
|
||||
(dmac->reg.address_base[dmac->selected_channel] & 0xffffff00) | data;
|
||||
if(dmac->base == 0)
|
||||
dmac->reg.address_current[dmac->selected_channel] =
|
||||
(dmac->reg.address_current[dmac->selected_channel] & 0xffffff00) | data;
|
||||
logerror("DMA: Channel %i Address set [%08x]\n",dmac->selected_channel,dmac->reg.address_base[dmac->selected_channel]);
|
||||
m_reg.address_base[m_selected_channel] =
|
||||
(m_reg.address_base[m_selected_channel] & 0xffffff00) | data;
|
||||
if (m_base == 0)
|
||||
m_reg.address_current[m_selected_channel] =
|
||||
(m_reg.address_current[m_selected_channel] & 0xffffff00) | data;
|
||||
logerror("DMA: Channel %i Address set [%08x]\n",m_selected_channel,m_reg.address_base[m_selected_channel]);
|
||||
break;
|
||||
case 0x05: // Address (mid)
|
||||
dmac->reg.address_base[dmac->selected_channel] =
|
||||
(dmac->reg.address_base[dmac->selected_channel] & 0xffff00ff) | (data << 8);
|
||||
if(dmac->base == 0)
|
||||
dmac->reg.address_current[dmac->selected_channel] =
|
||||
(dmac->reg.address_current[dmac->selected_channel] & 0xffff00ff) | (data << 8);
|
||||
logerror("DMA: Channel %i Address set [%08x]\n",dmac->selected_channel,dmac->reg.address_base[dmac->selected_channel]);
|
||||
m_reg.address_base[m_selected_channel] =
|
||||
(m_reg.address_base[m_selected_channel] & 0xffff00ff) | (data << 8);
|
||||
if (m_base == 0)
|
||||
m_reg.address_current[m_selected_channel] =
|
||||
(m_reg.address_current[m_selected_channel] & 0xffff00ff) | (data << 8);
|
||||
logerror("DMA: Channel %i Address set [%08x]\n",m_selected_channel,m_reg.address_base[m_selected_channel]);
|
||||
break;
|
||||
case 0x06: // Address (high)
|
||||
dmac->reg.address_base[dmac->selected_channel] =
|
||||
(dmac->reg.address_base[dmac->selected_channel] & 0xff00ffff) | (data << 16);
|
||||
if(dmac->base == 0)
|
||||
dmac->reg.address_current[dmac->selected_channel] =
|
||||
(dmac->reg.address_current[dmac->selected_channel] & 0xff00ffff) | (data << 16);
|
||||
logerror("DMA: Channel %i Address set [%08x]\n",dmac->selected_channel,dmac->reg.address_base[dmac->selected_channel]);
|
||||
m_reg.address_base[m_selected_channel] =
|
||||
(m_reg.address_base[m_selected_channel] & 0xff00ffff) | (data << 16);
|
||||
if (m_base == 0)
|
||||
m_reg.address_current[m_selected_channel] =
|
||||
(m_reg.address_current[m_selected_channel] & 0xff00ffff) | (data << 16);
|
||||
logerror("DMA: Channel %i Address set [%08x]\n",m_selected_channel,m_reg.address_base[m_selected_channel]);
|
||||
break;
|
||||
case 0x07: // Address (highest)
|
||||
dmac->reg.address_base[dmac->selected_channel] =
|
||||
(dmac->reg.address_base[dmac->selected_channel] & 0x00ffffff) | (data << 24);
|
||||
if(dmac->base == 0)
|
||||
dmac->reg.address_current[dmac->selected_channel] =
|
||||
(dmac->reg.address_current[dmac->selected_channel] & 0x00ffffff) | (data << 24);
|
||||
logerror("DMA: Channel %i Address set [%08x]\n",dmac->selected_channel,dmac->reg.address_base[dmac->selected_channel]);
|
||||
m_reg.address_base[m_selected_channel] =
|
||||
(m_reg.address_base[m_selected_channel] & 0x00ffffff) | (data << 24);
|
||||
if (m_base == 0)
|
||||
m_reg.address_current[m_selected_channel] =
|
||||
(m_reg.address_current[m_selected_channel] & 0x00ffffff) | (data << 24);
|
||||
logerror("DMA: Channel %i Address set [%08x]\n",m_selected_channel,m_reg.address_base[m_selected_channel]);
|
||||
break;
|
||||
case 0x08: // Device control (low)
|
||||
dmac->reg.device_control = (dmac->reg.device_control & 0xff00) | data;
|
||||
logerror("DMA: Device control set [%04x]\n",dmac->reg.device_control);
|
||||
m_reg.device_control = (m_reg.device_control & 0xff00) | data;
|
||||
logerror("DMA: Device control set [%04x]\n",m_reg.device_control);
|
||||
break;
|
||||
case 0x09: // Device control (high)
|
||||
dmac->reg.device_control = (dmac->reg.device_control & 0x00ff) | (data << 8);
|
||||
logerror("DMA: Device control set [%04x]\n",dmac->reg.device_control);
|
||||
m_reg.device_control = (m_reg.device_control & 0x00ff) | (data << 8);
|
||||
logerror("DMA: Device control set [%04x]\n",m_reg.device_control);
|
||||
break;
|
||||
case 0x0a: // Mode control
|
||||
dmac->reg.mode_control[dmac->selected_channel] = data;
|
||||
logerror("DMA: Channel %i Mode control set [%02x]\n",dmac->selected_channel,dmac->reg.mode_control[dmac->selected_channel]);
|
||||
m_reg.mode_control[m_selected_channel] = data;
|
||||
logerror("DMA: Channel %i Mode control set [%02x]\n",m_selected_channel,m_reg.mode_control[m_selected_channel]);
|
||||
break;
|
||||
case 0x0e: // Request
|
||||
dmac->reg.request = data;
|
||||
m_reg.request = data;
|
||||
logerror("DMA: Request set [%02x]\n",data);
|
||||
break;
|
||||
case 0x0f: // Mask
|
||||
dmac->reg.mask = data;
|
||||
m_reg.mask = data;
|
||||
logerror("DMA: Mask set [%02x]\n",data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
READ8_DEVICE_HANDLER(upd71071_r) { return upd71071_read(device,space,offset,mem_mask); }
|
||||
WRITE8_DEVICE_HANDLER(upd71071_w) { upd71071_write(device,space,offset,data,mem_mask); }
|
||||
|
||||
const device_type UPD71071 = &device_creator<upd71071_device>;
|
||||
|
||||
upd71071_device::upd71071_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: device_t(mconfig, UPD71071, "NEC uPD71071", tag, owner, clock)
|
||||
WRITE_LINE_MEMBER(upd71071_device::set_hreq)
|
||||
{
|
||||
m_token = global_alloc_clear(upd71071_t);
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_config_complete - perform any
|
||||
// operations now that the configuration is
|
||||
// complete
|
||||
//-------------------------------------------------
|
||||
|
||||
void upd71071_device::device_config_complete()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// device_start - device-specific startup
|
||||
//-------------------------------------------------
|
||||
|
||||
void upd71071_device::device_start()
|
||||
{
|
||||
DEVICE_START_NAME( upd71071 )(this);
|
||||
}
|
||||
|
||||
|
||||
void set_hreq( device_t *device, int state)
|
||||
{
|
||||
upd71071_t* dmac = get_safe_token(device);
|
||||
|
||||
if (dmac->m_hreq != state)
|
||||
if (m_hreq != state)
|
||||
{
|
||||
dmac->m_out_hreq_func(state);
|
||||
|
||||
dmac->m_hreq = state;
|
||||
m_out_hreq_func(state);
|
||||
m_hreq = state;
|
||||
}
|
||||
}
|
||||
|
||||
void set_eop( device_t *device, int state)
|
||||
WRITE_LINE_MEMBER(upd71071_device::set_eop)
|
||||
{
|
||||
upd71071_t* dmac = get_safe_token(device);
|
||||
|
||||
if (dmac->m_eop != state)
|
||||
if (m_eop != state)
|
||||
{
|
||||
dmac->m_out_eop_func(state);
|
||||
|
||||
dmac->m_eop = state;
|
||||
m_out_eop_func(state);
|
||||
m_eop = state;
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +1,76 @@
|
||||
#ifndef UPD71071_H_
|
||||
#define UPD71071_H_
|
||||
#ifndef __UPD71071_H__
|
||||
#define __UPD71071_H__
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
struct upd71071_intf
|
||||
{
|
||||
const char* cputag;
|
||||
int clock;
|
||||
int m_upd_clock;
|
||||
devcb_write_line m_out_hreq_cb;
|
||||
devcb_write_line m_out_eop_cb;
|
||||
devcb_read16 m_dma_read[4];
|
||||
devcb_write16 m_dma_write[4];
|
||||
devcb_read16 m_dma_read_cb[4];
|
||||
devcb_write16 m_dma_write_cb[4];
|
||||
devcb_write_line m_out_dack_cb[4];
|
||||
};
|
||||
|
||||
int upd71071_dmarq(device_t* device,int state,int channel);
|
||||
struct upd71071_reg
|
||||
{
|
||||
UINT8 initialise;
|
||||
UINT8 channel;
|
||||
UINT16 count_current[4];
|
||||
UINT16 count_base[4];
|
||||
UINT32 address_current[4];
|
||||
UINT32 address_base[4];
|
||||
UINT16 device_control;
|
||||
UINT8 mode_control[4];
|
||||
UINT8 status;
|
||||
UINT8 temp_l;
|
||||
UINT8 temp_h;
|
||||
UINT8 request;
|
||||
UINT8 mask;
|
||||
};
|
||||
|
||||
class upd71071_device : public device_t
|
||||
class upd71071_device : public device_t,
|
||||
public upd71071_intf
|
||||
{
|
||||
public:
|
||||
upd71071_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
~upd71071_device() { global_free(m_token); }
|
||||
~upd71071_device() {}
|
||||
|
||||
DECLARE_READ8_MEMBER(read);
|
||||
DECLARE_WRITE8_MEMBER(write);
|
||||
DECLARE_WRITE_LINE_MEMBER(set_hreq);
|
||||
DECLARE_WRITE_LINE_MEMBER(set_eop);
|
||||
|
||||
int dmarq(int state, int channel);
|
||||
|
||||
// access to legacy token
|
||||
void *token() const { assert(m_token != NULL); return m_token; }
|
||||
protected:
|
||||
// device-level overrides
|
||||
virtual void device_config_complete();
|
||||
virtual void device_start();
|
||||
|
||||
private:
|
||||
// internal state
|
||||
void *m_token;
|
||||
void soft_reset();
|
||||
TIMER_CALLBACK_MEMBER(dma_transfer_timer);
|
||||
|
||||
struct upd71071_reg m_reg;
|
||||
int m_selected_channel;
|
||||
int m_buswidth;
|
||||
int m_dmarq[4];
|
||||
emu_timer* m_timer[4];
|
||||
int m_in_progress[4];
|
||||
int m_transfer_size[4];
|
||||
int m_base;
|
||||
devcb_resolved_write_line m_out_hreq_func;
|
||||
devcb_resolved_write_line m_out_eop_func;
|
||||
devcb_resolved_read16 m_dma_read[4];
|
||||
devcb_resolved_write16 m_dma_write[4];
|
||||
devcb_resolved_write_line m_out_dack_func[4];
|
||||
int m_hreq;
|
||||
int m_eop;
|
||||
cpu_device *m_cpu;
|
||||
};
|
||||
|
||||
extern const device_type UPD71071;
|
||||
@ -40,11 +80,5 @@ extern const device_type UPD71071;
|
||||
MCFG_DEVICE_ADD(_tag, UPD71071, 0) \
|
||||
MCFG_DEVICE_CONFIG(_config)
|
||||
|
||||
DECLARE_READ8_DEVICE_HANDLER(upd71071_r);
|
||||
DECLARE_WRITE8_DEVICE_HANDLER(upd71071_w);
|
||||
|
||||
void set_hreq( device_t *device, int state);
|
||||
void set_eop( device_t *device, int state);
|
||||
|
||||
|
||||
#endif /*UPD71071_H_*/
|
||||
|
Loading…
Reference in New Issue
Block a user