trunk/src/emu/machine/dp8390.c
| r29498 | r29499 | |
| 7 | 7 | const device_type DP8390D = &device_creator<dp8390d_device>; |
| 8 | 8 | const device_type RTL8019A = &device_creator<rtl8019a_device>; |
| 9 | 9 | |
| 10 | | void dp8390_device::device_config_complete() { |
| 11 | | const dp8390_interface *intf = reinterpret_cast<const dp8390_interface *>(static_config()); |
| 12 | | if(intf != NULL) |
| 13 | | *static_cast<dp8390_interface *>(this) = *intf; |
| 14 | | else { |
| 15 | | memset(&irq_cb, 0, sizeof(irq_cb)); |
| 16 | | memset(&breq_cb, 0, sizeof(breq_cb)); |
| 17 | | memset(&mem_read_cb, 0, sizeof(mem_read_cb)); |
| 18 | | memset(&mem_write_cb, 0, sizeof(mem_write_cb)); |
| 19 | | } |
| 20 | | } |
| 21 | | |
| 22 | 10 | dp8390d_device::dp8390d_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 23 | 11 | : dp8390_device(mconfig, DP8390D, "DP8390D", tag, owner, clock, 10.0f, "dp8390d", __FILE__) { |
| 24 | 12 | m_type = TYPE_DP8390D; |
| r29498 | r29499 | |
| 31 | 19 | |
| 32 | 20 | dp8390_device::dp8390_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, float bandwidth, const char *shortname, const char *source) |
| 33 | 21 | : device_t(mconfig, type, name, tag, owner, clock, shortname, source), |
| 34 | | device_network_interface(mconfig, *this, bandwidth) { |
| 22 | device_network_interface(mconfig, *this, bandwidth), |
| 23 | m_irq_cb(*this), |
| 24 | m_breq_cb(*this), |
| 25 | m_mem_read_cb(*this), |
| 26 | m_mem_write_cb(*this) |
| 27 | { |
| 35 | 28 | } |
| 36 | 29 | |
| 37 | 30 | void dp8390_device::device_start() { |
| 38 | | irq_func.resolve(irq_cb, *this); |
| 39 | | breq_func.resolve(breq_cb, *this); |
| 40 | | mem_read.resolve(mem_read_cb, *this); |
| 41 | | mem_write.resolve(mem_write_cb, *this); |
| 31 | m_irq_cb.resolve_safe(); |
| 32 | m_breq_cb.resolve_safe(); |
| 33 | m_mem_read_cb.resolve_safe(0); |
| 34 | m_mem_write_cb.resolve_safe(); |
| 42 | 35 | } |
| 43 | 36 | |
| 44 | 37 | void dp8390_device::stop() { |
| 45 | 38 | m_regs.isr = 0x80; // is this right? |
| 46 | 39 | m_regs.cr |= 1; |
| 47 | | irq_func(CLEAR_LINE); |
| 40 | m_irq_cb(CLEAR_LINE); |
| 48 | 41 | m_reset = 1; |
| 49 | 42 | } |
| 50 | 43 | |
| r29498 | r29499 | |
| 56 | 49 | memset(&m_8019regs, 0, sizeof(m_8019regs)); |
| 57 | 50 | m_8019regs.config1 = 0x80; |
| 58 | 51 | m_8019regs.config3 = 0x01; |
| 59 | | irq_func(CLEAR_LINE); |
| 52 | m_irq_cb(CLEAR_LINE); |
| 60 | 53 | |
| 61 | 54 | m_reset = 1; |
| 62 | 55 | } |
| r29498 | r29499 | |
| 83 | 76 | } |
| 84 | 77 | |
| 85 | 78 | buf.resize(m_regs.tbcr); |
| 86 | | for(i = 0; i < m_regs.tbcr; i++) buf[i] = mem_read(high16 + (m_regs.tpsr << 8) + i); |
| 79 | for(i = 0; i < m_regs.tbcr; i++) buf[i] = m_mem_read_cb(high16 + (m_regs.tpsr << 8) + i); |
| 87 | 80 | |
| 88 | 81 | if(send(buf, m_regs.tbcr)) { |
| 89 | 82 | m_regs.tsr = 1; |
| r29498 | r29499 | |
| 139 | 132 | len &= 0xffff; |
| 140 | 133 | |
| 141 | 134 | for(i = 0; i < len; i++) { |
| 142 | | mem_write(high16 + offset, buf[i]); |
| 135 | m_mem_write_cb(high16 + offset, buf[i]); |
| 143 | 136 | offset++; |
| 144 | 137 | if(!(offset & 0xff)) { |
| 145 | 138 | if((offset >> 8) == m_regs.pstop) offset = m_regs.pstart << 8; |
| r29498 | r29499 | |
| 149 | 142 | if(len < 60) { |
| 150 | 143 | // this can't pass to the next page |
| 151 | 144 | for(; i < 60; i++) { |
| 152 | | mem_write(high16 + offset, 0); |
| 145 | m_mem_write_cb(high16 + offset, 0); |
| 153 | 146 | offset++; |
| 154 | 147 | } |
| 155 | 148 | len = 60; |
| r29498 | r29499 | |
| 160 | 153 | m_regs.curr = (offset >> 8) + ((offset & 0xff)?1:0); |
| 161 | 154 | if(m_regs.curr == m_regs.pstop) m_regs.curr = m_regs.pstart; |
| 162 | 155 | len += 4; |
| 163 | | mem_write(start, m_regs.rsr); |
| 164 | | mem_write(start+1, m_regs.curr); |
| 165 | | mem_write(start+2, len & 0xff); |
| 166 | | mem_write(start+3, len >> 8); |
| 156 | m_mem_write_cb((offs_t)start, m_regs.rsr); |
| 157 | m_mem_write_cb((offs_t)start+1, m_regs.curr); |
| 158 | m_mem_write_cb((offs_t)start+2, len & 0xff); |
| 159 | m_mem_write_cb((offs_t)start+3, len >> 8); |
| 167 | 160 | check_irq(); |
| 168 | 161 | } |
| 169 | 162 | |
| r29498 | r29499 | |
| 185 | 178 | UINT32 high16 = (m_regs.dcr & 4)?m_regs.rsar<<16:0; |
| 186 | 179 | if(m_regs.dcr & 1) { |
| 187 | 180 | m_regs.crda &= ~1; |
| 188 | | data = mem_read(high16 + m_regs.crda++); |
| 189 | | data |= mem_read(high16 + m_regs.crda++) << 8; |
| 181 | data = m_mem_read_cb(high16 + m_regs.crda++); |
| 182 | data |= m_mem_read_cb(high16 + m_regs.crda++) << 8; |
| 190 | 183 | m_regs.rbcr -= (m_regs.rbcr < 2)?m_regs.rbcr:2; |
| 191 | 184 | check_dma_complete(); |
| 192 | 185 | return DP8390_BYTE_ORDER(data); |
| 193 | 186 | } else { |
| 194 | 187 | m_regs.rbcr -= (m_regs.rbcr)?1:0; |
| 195 | | data = mem_read(high16 + m_regs.crda++); |
| 188 | data = m_mem_read_cb(high16 + m_regs.crda++); |
| 196 | 189 | check_dma_complete(); |
| 197 | 190 | return data; |
| 198 | 191 | } |
| r29498 | r29499 | |
| 355 | 348 | if(m_regs.dcr & 1) { |
| 356 | 349 | data = DP8390_BYTE_ORDER(data); |
| 357 | 350 | m_regs.crda &= ~1; |
| 358 | | mem_write(high16 + m_regs.crda++, data & 0xff); |
| 359 | | mem_write(high16 + m_regs.crda++, data >> 8); |
| 351 | m_mem_write_cb(high16 + m_regs.crda++, data & 0xff); |
| 352 | m_mem_write_cb(high16 + m_regs.crda++, data >> 8); |
| 360 | 353 | m_regs.rbcr -= (m_regs.rbcr < 2)?m_regs.rbcr:2; |
| 361 | 354 | check_dma_complete(); |
| 362 | 355 | } else { |
| 363 | 356 | data &= 0xff; |
| 364 | | mem_write(high16 + m_regs.crda++, data); |
| 357 | m_mem_write_cb(high16 + m_regs.crda++, data); |
| 365 | 358 | m_regs.rbcr -= (m_regs.rbcr)?1:0; |
| 366 | 359 | check_dma_complete(); |
| 367 | 360 | } |
trunk/src/emu/machine/dp8390.h
| r29498 | r29499 | |
| 3 | 3 | |
| 4 | 4 | #include "emu.h" |
| 5 | 5 | |
| 6 | | struct dp8390_interface |
| 7 | | { |
| 8 | | devcb_write_line irq_cb; |
| 9 | | devcb_write_line breq_cb; |
| 10 | | devcb_read8 mem_read_cb; |
| 11 | | devcb_write8 mem_write_cb; |
| 12 | | }; |
| 13 | 6 | |
| 14 | 7 | // device stuff |
| 15 | | #define MCFG_DP8390D_ADD(_tag, _intrf) \ |
| 16 | | MCFG_DEVICE_ADD(_tag, DP8390D, 0) \ |
| 17 | | MCFG_DEVICE_CONFIG(_intrf) |
| 18 | 8 | |
| 19 | | #define MCFG_RTL8019A_ADD(_tag, _intrf) \ |
| 20 | | MCFG_DEVICE_ADD(_tag, RTL8019A, 0) \ |
| 21 | | MCFG_DEVICE_CONFIG(_intrf) |
| 9 | #define MCFG_DP8390D_IRQ_CB(_devcb) \ |
| 10 | devcb = &dp8390d_device::set_irq_callback(*device, DEVCB2_##_devcb); |
| 22 | 11 | |
| 12 | #define MCFG_DP8390D_BREQ_CB(_devcb) \ |
| 13 | devcb = &dp8390d_device::set_breq_callback(*device, DEVCB2_##_devcb); |
| 14 | |
| 15 | #define MCFG_DP8390D_MEM_READ_CB(_devcb) \ |
| 16 | devcb = &dp8390d_device::set_mem_read_callback(*device, DEVCB2_##_devcb); |
| 17 | |
| 18 | #define MCFG_DP8390D_MEM_WRITE_CB(_devcb) \ |
| 19 | devcb = &dp8390d_device::set_mem_write_callback(*device, DEVCB2_##_devcb); |
| 20 | |
| 21 | #define MCFG_RTL8019A_IRQ_CB(_devcb) \ |
| 22 | devcb = &rtl8019a_device::set_irq_callback(*device, DEVCB2_##_devcb); |
| 23 | |
| 24 | #define MCFG_RTL8019A_BREQ_CB(_devcb) \ |
| 25 | devcb = &rtl8019a_device::set_breq_callback(*device, DEVCB2_##_devcb); |
| 26 | |
| 27 | #define MCFG_RTL8019A_MEM_READ_CB(_devcb) \ |
| 28 | devcb = &rtl8019a_device::set_mem_read_callback(*device, DEVCB2_##_devcb); |
| 29 | |
| 30 | #define MCFG_RTL8019A_MEM_WRITE_CB(_devcb) \ |
| 31 | devcb = &rtl8019a_device::set_mem_write_callback(*device, DEVCB2_##_devcb); |
| 32 | |
| 33 | |
| 23 | 34 | class dp8390_device : public device_t, |
| 24 | | public device_network_interface, |
| 25 | | public dp8390_interface |
| 35 | public device_network_interface |
| 26 | 36 | { |
| 27 | 37 | public: |
| 28 | 38 | // construction/destruction |
| 29 | 39 | dp8390_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, float bandwidth, const char *shortname, const char *source); |
| 40 | |
| 41 | template<class _Object> static devcb2_base &set_irq_callback(device_t &device, _Object object) { return downcast<dp8390_device &>(device).m_irq_cb.set_callback(object); } |
| 42 | template<class _Object> static devcb2_base &set_breq_callback(device_t &device, _Object object) { return downcast<dp8390_device &>(device).m_breq_cb.set_callback(object); } |
| 43 | template<class _Object> static devcb2_base &set_mem_read_callback(device_t &device, _Object object) { return downcast<dp8390_device &>(device).m_mem_read_cb.set_callback(object); } |
| 44 | template<class _Object> static devcb2_base &set_mem_write_callback(device_t &device, _Object object) { return downcast<dp8390_device &>(device).m_mem_write_cb.set_callback(object); } |
| 30 | 45 | |
| 31 | 46 | DECLARE_WRITE16_MEMBER( dp8390_w ); |
| 32 | 47 | DECLARE_READ16_MEMBER( dp8390_r ); |
| r29498 | r29499 | |
| 38 | 53 | // device-level overrides |
| 39 | 54 | virtual void device_start(); |
| 40 | 55 | virtual void device_reset(); |
| 41 | | virtual void device_config_complete(); |
| 56 | |
| 42 | 57 | int m_type; |
| 43 | 58 | |
| 44 | 59 | enum { |
| r29498 | r29499 | |
| 47 | 62 | }; |
| 48 | 63 | |
| 49 | 64 | private: |
| 50 | | devcb_resolved_write_line irq_func; |
| 51 | | devcb_resolved_write_line breq_func; |
| 52 | | devcb_resolved_read8 mem_read; |
| 53 | | devcb_resolved_write8 mem_write; |
| 65 | devcb2_write_line m_irq_cb; |
| 66 | devcb2_write_line m_breq_cb; |
| 67 | devcb2_read8 m_mem_read_cb; |
| 68 | devcb2_write8 m_mem_write_cb; |
| 54 | 69 | |
| 55 | 70 | void set_cr(UINT8 newcr); |
| 56 | 71 | void check_dma_complete(); |
| 57 | 72 | void do_tx(); |
| 58 | 73 | bool mcast_ck(const UINT8 *buf, int len); |
| 59 | | void check_irq() { irq_func((m_regs.imr & m_regs.isr & 0x7f)?ASSERT_LINE:CLEAR_LINE); } |
| 74 | void check_irq() { m_irq_cb((m_regs.imr & m_regs.isr & 0x7f)?ASSERT_LINE:CLEAR_LINE); } |
| 60 | 75 | void recv_overflow(); |
| 61 | 76 | void stop(); |
| 62 | 77 | void recv(UINT8 *buf, int len); |
trunk/src/emu/bus/x68k/x68k_neptunex.c
| r29498 | r29499 | |
| 13 | 13 | |
| 14 | 14 | const device_type X68K_NEPTUNEX = &device_creator<x68k_neptune_device>; |
| 15 | 15 | |
| 16 | | static const dp8390_interface neptune_dp8390_interface = { |
| 17 | | DEVCB_DEVICE_LINE_MEMBER(DEVICE_SELF_OWNER, x68k_neptune_device, x68k_neptune_irq_w), |
| 18 | | DEVCB_NULL, |
| 19 | | DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, x68k_neptune_device, x68k_neptune_mem_read), |
| 20 | | DEVCB_DEVICE_MEMBER(DEVICE_SELF_OWNER, x68k_neptune_device, x68k_neptune_mem_write) |
| 21 | | }; |
| 22 | | |
| 23 | | |
| 24 | 16 | // device machine config |
| 25 | 17 | static MACHINE_CONFIG_FRAGMENT( x68k_neptunex ) |
| 26 | | MCFG_DP8390D_ADD("dp8390d", neptune_dp8390_interface) |
| 18 | MCFG_DEVICE_ADD("dp8390d", DP8390D, 0) |
| 19 | MCFG_DP8390D_IRQ_CB(WRITELINE(x68k_neptune_device, x68k_neptune_irq_w)) |
| 20 | MCFG_DP8390D_MEM_READ_CB(READ8(x68k_neptune_device, x68k_neptune_mem_read)) |
| 21 | MCFG_DP8390D_MEM_WRITE_CB(WRITE8(x68k_neptune_device, x68k_neptune_mem_write)) |
| 27 | 22 | MACHINE_CONFIG_END |
| 28 | 23 | |
| 29 | 24 | machine_config_constructor x68k_neptune_device::device_mconfig_additions() const |
| r29498 | r29499 | |
| 85 | 80 | m_dp8390->dp8390_reset(CLEAR_LINE); |
| 86 | 81 | return 0; |
| 87 | 82 | default: |
| 88 | | logerror("ne2000: invalid register read %02X\n", offset); |
| 83 | logerror("x68k_neptune: invalid register read %02X\n", offset); |
| 89 | 84 | } |
| 90 | 85 | return 0; |
| 91 | 86 | } |
| r29498 | r29499 | |
| 118 | 113 | m_dp8390->dp8390_reset(ASSERT_LINE); |
| 119 | 114 | return; |
| 120 | 115 | default: |
| 121 | | logerror("ne2000: invalid register write %02X\n", offset); |
| 116 | logerror("x68k_neptune: invalid register write %02X\n", offset); |
| 122 | 117 | } |
| 123 | 118 | return; |
| 124 | 119 | } |
| r29498 | r29499 | |
| 128 | 123 | if(offset < 32) return m_prom[offset>>1]; |
| 129 | 124 | if((offset < (16*1024)) || (offset >= (32*1024))) |
| 130 | 125 | { |
| 131 | | logerror("ne2000: invalid memory read %04X\n", offset); |
| 126 | logerror("x68k_neptune: invalid memory read %04X\n", offset); |
| 132 | 127 | return 0xff; |
| 133 | 128 | } |
| 134 | 129 | return m_board_ram[offset - (16*1024)]; |
| r29498 | r29499 | |
| 138 | 133 | { |
| 139 | 134 | if((offset < (16*1024)) || (offset >= (32*1024))) |
| 140 | 135 | { |
| 141 | | logerror("ne2000: invalid memory write %04X\n", offset); |
| 136 | logerror("x68k_neptune: invalid memory write %04X\n", offset); |
| 142 | 137 | return; |
| 143 | 138 | } |
| 144 | 139 | m_board_ram[offset - (16*1024)] = data; |