From f9d591b7bcdd842365ffbaff0a8dac78ac1c1b5d Mon Sep 17 00:00:00 2001 From: Fabio Priuli Date: Tue, 4 Jun 2013 10:17:53 +0000 Subject: [PATCH] (MESS) modernized uPD71071 DMA device. [Fabio Priuli] --- src/mess/drivers/fmtowns.c | 18 +- src/mess/drivers/pc88va.c | 8 +- src/mess/includes/fmtowns.h | 6 +- src/mess/machine/upd71071.c | 429 ++++++++++++++++-------------------- src/mess/machine/upd71071.h | 68 ++++-- 5 files changed, 251 insertions(+), 278 deletions(-) diff --git a/src/mess/drivers/fmtowns.c b/src/mess/drivers/fmtowns.c index 45b21a22e3d..c4571b4f109 100644 --- a/src/mess/drivers/fmtowns.c +++ b/src/mess/drivers/fmtowns.c @@ -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"); diff --git a/src/mess/drivers/pc88va.c b/src/mess/drivers/pc88va.c index 6a2f8a71001..f1ebd9c5f74 100644 --- a/src/mess/drivers/pc88va.c +++ b/src/mess/drivers/pc88va.c @@ -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("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) diff --git a/src/mess/includes/fmtowns.h b/src/mess/includes/fmtowns.h index ab643b0c8f9..ac356b8b1a3 100644 --- a/src/mess/includes/fmtowns.h +++ b/src/mess/includes/fmtowns.h @@ -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 m_pic_master; required_device m_pic_slave; required_device m_pit; + required_device m_dma_1; + required_device m_dma_2; required_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; diff --git a/src/mess/machine/upd71071.c b/src/mess/machine/upd71071.c index 9b6228f588b..8e0c15788bc 100644 --- a/src/mess/machine/upd71071.c +++ b/src/mess/machine/upd71071.c @@ -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; -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(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(static_config()); + if (intf != NULL) + *static_cast(this) = *intf; + + // or initialize to defaults if none provided + else + { + } +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void upd71071_device::device_start() +{ + m_cpu = machine().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(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; } } diff --git a/src/mess/machine/upd71071.h b/src/mess/machine/upd71071.h index 9a815d8819e..a3ff24f6248 100644 --- a/src/mess/machine/upd71071.h +++ b/src/mess/machine/upd71071.h @@ -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_*/