From e302ab780a35c896834163a4618385d6a3ec28c6 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Mon, 16 Mar 2020 17:13:24 +0700 Subject: indy_indigo2: networking * hook up edlc ethernet device * implement ethernet dma --- src/mame/drivers/indy_indigo2.cpp | 15 +- src/mame/machine/hpc3.cpp | 350 ++++++++++++++++++++++++++------------ src/mame/machine/hpc3.h | 117 +++++++++---- 3 files changed, 328 insertions(+), 154 deletions(-) diff --git a/src/mame/drivers/indy_indigo2.cpp b/src/mame/drivers/indy_indigo2.cpp index bf6da2eedac..fe9ba3d88c3 100644 --- a/src/mame/drivers/indy_indigo2.cpp +++ b/src/mame/drivers/indy_indigo2.cpp @@ -137,7 +137,7 @@ protected: required_shared_ptr m_mainram; required_device m_mem_ctrl; required_device m_scsi_ctrl; - required_device m_edlc; + required_device m_edlc; required_device m_eeprom; required_device m_hal2; required_device m_hpc3; @@ -357,13 +357,6 @@ void ip24_state::ip24_base(machine_config &config) m_hpc3->set_addrmap(hpc3_device::AS_PIO0, &ip24_state::pio0_map); m_hpc3->set_addrmap(hpc3_device::AS_PIO1, &ip24_state::pio1_map); m_hpc3->set_addrmap(hpc3_device::AS_PIO2, &ip24_state::pio2_map); - m_hpc3->enet_rd_cb().set(m_edlc, FUNC(seeq8003_device::read)); - m_hpc3->enet_wr_cb().set(m_edlc, FUNC(seeq8003_device::write)); - m_hpc3->enet_rxrd_cb().set(m_edlc, FUNC(seeq8003_device::fifo_r)); - m_hpc3->enet_txwr_cb().set(m_edlc, FUNC(seeq8003_device::fifo_w)); - m_hpc3->enet_d8_rd_cb().set(m_edlc, FUNC(seeq8003_device::rxeof_r)); - m_hpc3->enet_d8_wr_cb().set(m_edlc, FUNC(seeq8003_device::txeof_w)); - m_hpc3->enet_reset_cb().set(m_edlc, FUNC(seeq8003_device::reset_w)); m_hpc3->enet_intr_out_cb().set(m_ioc2, FUNC(ioc2_device::enet_int_w)); m_hpc3->hd_rd_cb<0>().set(m_scsi_ctrl, FUNC(wd33c93b_device::indir_r)); m_hpc3->hd_wr_cb<0>().set(m_scsi_ctrl, FUNC(wd33c93b_device::indir_w)); @@ -379,12 +372,10 @@ void ip24_state::ip24_base(machine_config &config) //m_hpc3->eeprom_pre_cb().set(m_eeprom, FUNC(eeprom_serial_93cxx_device::pre_write)); m_hpc3->dma_complete_int_cb().set(m_ioc2, FUNC(ioc2_device::hpc_dma_done_w)); - SEEQ8003(config, m_edlc); + SEEQ80C03(config, m_edlc); m_edlc->out_int_cb().set(m_hpc3, FUNC(hpc3_device::enet_intr_in_w)); m_edlc->out_rxrdy_cb().set(m_hpc3, FUNC(hpc3_device::enet_rxrdy_w)); - m_edlc->out_txrdy_cb().set(m_hpc3, FUNC(hpc3_device::enet_txrdy_w)); - //m_edlc->out_rxdc_cb().set(m_hpc3, FUNC(hpc3_device::enet_rxdc_w)); - //m_edlc->out_txret_cb().set(m_hpc3, FUNC(hpc3_device::enet_txret_w)); + m_hpc3->set_enet(m_edlc); SGI_HAL2(config, m_hal2); EEPROM_93C56_16BIT(config, m_eeprom); diff --git a/src/mame/machine/hpc3.cpp b/src/mame/machine/hpc3.cpp index cd88932d6e3..aabe5da6908 100644 --- a/src/mame/machine/hpc3.cpp +++ b/src/mame/machine/hpc3.cpp @@ -40,14 +40,7 @@ hpc3_device::hpc3_device(const machine_config &mconfig, const char *tag, device_ {"PIO channel 9", ENDIANNESS_LITTLE, 16, 8, -1}} , m_gio64_space(*this, finder_base::DUMMY_TAG, -1) , m_hal2(*this, finder_base::DUMMY_TAG) - , m_enet_rd_cb(*this) - , m_enet_wr_cb(*this) - , m_enet_rxrd_cb(*this) - , m_enet_txwr_cb(*this) - , m_enet_d8_rd_cb(*this) - , m_enet_d8_wr_cb(*this) - , m_enet_reset_cb(*this) - , m_enet_loopback_cb(*this) + , m_enet(*this, finder_base::DUMMY_TAG) , m_enet_intr_out_cb(*this) , m_hd_rd_cb(*this) , m_hd_wr_cb(*this) @@ -83,14 +76,6 @@ device_memory_interface::space_config_vector hpc3_device::memory_space_config() void hpc3_device::device_resolve_objects() { - m_enet_rd_cb.resolve(); - m_enet_wr_cb.resolve_safe(); - m_enet_rxrd_cb.resolve_safe(0); - m_enet_txwr_cb.resolve_safe(); - m_enet_d8_rd_cb.resolve_safe(0); - m_enet_d8_wr_cb.resolve_safe(); - m_enet_reset_cb.resolve_safe(); - m_enet_loopback_cb.resolve_safe(); m_enet_intr_out_cb.resolve_safe(); m_hd_rd_cb.resolve_all(); m_hd_wr_cb.resolve_all(); @@ -132,19 +117,28 @@ void hpc3_device::device_start() save_item(NAME(m_scsi_dma[i].m_active), i); } - for (uint32_t i = 0; i < 2; i++) - { - save_item(NAME(m_enet_dma[i].m_cbp), i); - save_item(NAME(m_enet_dma[i].m_nbdp), i); - save_item(NAME(m_enet_dma[i].m_bc), i); - save_item(NAME(m_enet_dma[i].m_ctrl), i); - save_item(NAME(m_enet_dma[i].m_gio_fifo_ptr), i); - save_item(NAME(m_enet_dma[i].m_dev_fifo_ptr), i); - } - save_item(NAME(m_enet_reset)); + save_item(NAME(m_enet_rx_cbp)); + save_item(NAME(m_enet_rx_nbdp)); + save_item(NAME(m_enet_rx_bc)); + save_item(NAME(m_enet_rx_ctrl)); + save_item(NAME(m_enet_rx_gio)); + save_item(NAME(m_enet_rx_dev)); + + save_item(NAME(m_enet_misc)); save_item(NAME(m_enet_dmacfg)); save_item(NAME(m_enet_piocfg)); + save_item(NAME(m_enet_tx_cbp)); + save_item(NAME(m_enet_tx_nbdp)); + save_item(NAME(m_enet_tx_bc)); + save_item(NAME(m_enet_tx_ctrl)); + save_item(NAME(m_enet_tx_gio)); + save_item(NAME(m_enet_tx_dev)); + + save_item(NAME(m_enet_rx_cbdp)); + save_item(NAME(m_enet_tx_cpfbdp)); + save_item(NAME(m_enet_tx_ppfbdp)); + for (uint32_t i = 0; i < 8; i++) { save_item(NAME(m_pbus_dma[i].m_active), i); @@ -171,6 +165,8 @@ void hpc3_device::device_start() save_pointer(NAME(m_scsi_fifo[1]), 96); save_pointer(NAME(m_enet_fifo[ENET_RECV]), 32); save_pointer(NAME(m_enet_fifo[ENET_XMIT]), 40); + + m_enet_tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hpc3_device::enet_transmit), this)); } void hpc3_device::device_reset() @@ -178,14 +174,6 @@ void hpc3_device::device_reset() m_cpu_aux_ctrl = 0; memset(m_scsi_dma, 0, sizeof(scsi_dma_t) * 2); - memset(m_enet_dma, 0, sizeof(enet_dma_t) * 2); - m_enet_dmacfg = 0; - m_enet_piocfg = 0; - - m_enet_dma[ENET_RECV].m_cbp = 0x80000000; - m_enet_dma[ENET_XMIT].m_cbp = 0x80000000; - m_enet_dma[ENET_RECV].m_nbdp = 0x80000000; - m_enet_dma[ENET_XMIT].m_nbdp = 0x80000000; for (uint32_t i = 0; i < 8; i++) { @@ -204,6 +192,8 @@ void hpc3_device::device_reset() m_intstat = 0; m_dma_complete_int_cb(0); + + m_enet_misc = MISC_RESET; } void hpc3_device::map(address_map &map) @@ -221,7 +211,7 @@ void hpc3_device::map(address_map &map) map(0x0003000c, 0x0003000f).r(FUNC(hpc3_device::intstat_r)); map(0x00040000, 0x00047fff).rw(FUNC(hpc3_device::hd_r<0>), FUNC(hpc3_device::hd_w<0>)); map(0x00048000, 0x0004ffff).rw(FUNC(hpc3_device::hd_r<1>), FUNC(hpc3_device::hd_w<1>)); - map(0x00054000, 0x000544ff).rw(FUNC(hpc3_device::enet_r), FUNC(hpc3_device::enet_w)); + map(0x00054000, 0x000544ff).m(m_enet, FUNC(seeq80c03_device::map)).umask64(0x000000ff000000ff); map(0x00058000, 0x0005bfff).rw(FUNC(hpc3_device::pio_data_r), FUNC(hpc3_device::pio_data_w)); map(0x0005c000, 0x0005cfff).rw(FUNC(hpc3_device::dma_config_r), FUNC(hpc3_device::dma_config_w)); map(0x0005d000, 0x0005dfff).rw(FUNC(hpc3_device::pio_config_r), FUNC(hpc3_device::pio_config_w)); @@ -298,29 +288,6 @@ void hpc3_device::do_pbus_dma(uint32_t channel) } } -READ32_MEMBER(hpc3_device::enet_r) -{ - switch (offset) - { - case 0x000/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3: enet_r: Read MAC Address bytes 0-3, 0x80675309 & %08x\n", machine().describe_context(), mem_mask); - return 0x80675309; - default: - LOGMASKED(LOG_ETHERNET, "%s: HPC3: enet_r: Read Unknown Register %08x & %08x\n", machine().describe_context(), 0x1fbd4000 + (offset << 2), mem_mask); - return 0; - } -} - -WRITE32_MEMBER(hpc3_device::enet_w) -{ - switch (offset) - { - default: - LOGMASKED(LOG_ETHERNET, "%s: HPC3: enet_w: Write Unknown Register %08x = %08x & %08x\n", machine().describe_context(), 0x1fbd4000 + (offset << 2), data, mem_mask); - break; - } -} - READ32_MEMBER(hpc3_device::hd_enet_r) { switch (offset) @@ -395,26 +362,26 @@ READ32_MEMBER(hpc3_device::hd_enet_r) return m_scsi_dma[channel].m_piocfg; } case 0x4000/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Current Buffer Pointer Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_RECV].m_cbp); - return m_enet_dma[ENET_RECV].m_cbp; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Current Buffer Pointer Read: %08x\n", machine().describe_context(), m_enet_rx_cbp); + return m_enet_rx_cbp; case 0x4004/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Next Buffer Desc Pointer Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_RECV].m_nbdp); - return m_enet_dma[ENET_RECV].m_nbdp; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Next Buffer Desc Pointer Read: %08x\n", machine().describe_context(), m_enet_rx_nbdp); + return m_enet_rx_nbdp; case 0x5000/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Buffer Count Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_RECV].m_bc); - return m_enet_dma[ENET_RECV].m_bc; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Buffer Count Read: %08x\n", machine().describe_context(), m_enet_rx_bc); + return m_enet_rx_bc; case 0x5004/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver DMA Control Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_RECV].m_ctrl); - return m_enet_dma[ENET_RECV].m_ctrl; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver DMA Control Read: %08x\n", machine().describe_context(), m_enet_rx_ctrl); + return m_enet_rx_ctrl; case 0x5008/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver GIO FIFO Pointer Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_RECV].m_gio_fifo_ptr); - return m_enet_dma[ENET_RECV].m_gio_fifo_ptr; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver GIO FIFO Pointer Read: %08x\n", machine().describe_context(), m_enet_rx_gio); + return m_enet_rx_gio; case 0x500c/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Device FIFO Pointer Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_RECV].m_dev_fifo_ptr); - return m_enet_dma[ENET_RECV].m_dev_fifo_ptr; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Device FIFO Pointer Read: %08x\n", machine().describe_context(), m_enet_rx_dev); + return m_enet_rx_dev; case 0x5014/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Reset Register Read: %08x\n", machine().describe_context(), m_enet_reset); - return m_enet_reset; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Reset Register Read: %08x\n", machine().describe_context(), m_enet_misc); + return m_enet_misc; case 0x5018/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet DMA Config Read: %08x\n", machine().describe_context(), m_enet_dmacfg); return m_enet_dmacfg; @@ -422,23 +389,32 @@ READ32_MEMBER(hpc3_device::hd_enet_r) LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet PIO Config Read: %08x\n", machine().describe_context(), m_enet_piocfg); return m_enet_piocfg; case 0x6000/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Current Buffer Pointer Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_XMIT].m_cbp); - return m_enet_dma[ENET_XMIT].m_cbp; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Current Buffer Pointer Read: %08x\n", machine().describe_context(), m_enet_tx_cbp); + return m_enet_tx_cbp; case 0x6004/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Next Buffer Desc Pointer Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_XMIT].m_nbdp); - return m_enet_dma[ENET_XMIT].m_nbdp; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Next Buffer Desc Pointer Read: %08x\n", machine().describe_context(), m_enet_tx_nbdp); + return m_enet_tx_nbdp; case 0x7000/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Buffer Count Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_XMIT].m_bc); - return m_enet_dma[ENET_XMIT].m_bc; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Buffer Count Read: %08x\n", machine().describe_context(), m_enet_tx_bc); + return m_enet_tx_bc; case 0x7004/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter DMA Control Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_XMIT].m_ctrl); - return m_enet_dma[ENET_XMIT].m_ctrl; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter DMA Control Read: %08x\n", machine().describe_context(), m_enet_tx_ctrl); + return m_enet_tx_ctrl; case 0x7008/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter GIO FIFO Pointer Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_XMIT].m_gio_fifo_ptr); - return m_enet_dma[ENET_XMIT].m_gio_fifo_ptr; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter GIO FIFO Pointer Read: %08x\n", machine().describe_context(), m_enet_tx_gio); + return m_enet_tx_gio; case 0x700c/4: - LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Device FIFO Pointer Read: %08x\n", machine().describe_context(), m_enet_dma[ENET_XMIT].m_dev_fifo_ptr); - return m_enet_dma[ENET_XMIT].m_dev_fifo_ptr; + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Device FIFO Pointer Read: %08x\n", machine().describe_context(), m_enet_tx_dev); + return m_enet_tx_dev; + case 0x8000/4: + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Current Buffer Descriptor Pointer Read: %08x\n", machine().describe_context(), m_enet_rx_cbdp); + return m_enet_rx_cbdp; + case 0xa000/4: + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Current/Previous First Buffer Descriptor Pointer Read: %08x\n", machine().describe_context(), m_enet_tx_cpfbdp); + return m_enet_tx_cpfbdp; + case 0xa004/4: + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Previous/Previous First Buffer Descriptor Pointer Read: %08x\n", machine().describe_context(), m_enet_tx_ppfbdp); + return m_enet_tx_ppfbdp; default: LOGMASKED(LOG_UNKNOWN, "%s: Unknown HPC3 ENET/HDx Read: %08x & %08x\n", machine().describe_context(), 0x1fb90000 + (offset << 2), mem_mask); return 0; @@ -463,6 +439,7 @@ WRITE32_MEMBER(hpc3_device::hd_enet_w) const uint32_t channel = (offset & 0x2000/4) ? 1 : 0; LOGMASKED(LOG_SCSI, "%s: HPC3 SCSI%d Buffer Count Write: %08x\n", machine().describe_context(), channel, data); m_scsi_dma[channel].m_bc = data; + break; } case 0x1004/4: case 0x3004/4: @@ -516,18 +493,21 @@ WRITE32_MEMBER(hpc3_device::hd_enet_w) } case 0x4000/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Current Buffer Pointer Write: %08x\n", machine().describe_context(), data); - m_enet_dma[ENET_RECV].m_cbp = data; + m_enet_rx_cbp = data; break; case 0x4004/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Next Buffer Desc Pointer Write: %08x\n", machine().describe_context(), data); - m_enet_dma[ENET_RECV].m_nbdp = data; + m_enet_rx_nbdp = data; break; case 0x5000/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Buffer Count Write (ignored): %08x\n", machine().describe_context(), data); break; case 0x5004/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver DMA Control Write: %08x\n", machine().describe_context(), data); - m_enet_dma[ENET_RECV].m_ctrl = data; + if (m_enet_rx_ctrl & RXC_CAM) + m_enet_rx_ctrl = (m_enet_rx_ctrl & (RXC_LC | RXC_ST)) | (data & ~(RXC_CA | RXC_LC | RXC_ST)); + else + m_enet_rx_ctrl = (m_enet_rx_ctrl & (RXC_LC | RXC_ST)) | (data & ~((RXC_LC | RXC_ST))); break; case 0x5008/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver GIO FIFO Pointer Write (ignored): %08x\n", machine().describe_context(), data); @@ -537,7 +517,7 @@ WRITE32_MEMBER(hpc3_device::hd_enet_w) break; case 0x5014/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Reset Register Write: %08x\n", machine().describe_context(), data); - m_enet_reset = data; + enet_misc_w(data); break; case 0x5018/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet DMA Config Write: %08x\n", machine().describe_context(), data); @@ -552,14 +532,20 @@ WRITE32_MEMBER(hpc3_device::hd_enet_w) break; case 0x6004/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Next Buffer Desc Pointer Write: %08x\n", machine().describe_context(), data); - m_enet_dma[ENET_XMIT].m_nbdp = data; + m_enet_tx_nbdp = data; break; case 0x7000/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Buffer Count Write (ignored): %08x\n", machine().describe_context(), data); break; case 0x7004/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter DMA Control Write: %08x\n", machine().describe_context(), data); - m_enet_dma[ENET_XMIT].m_ctrl = data; + if (m_enet_tx_ctrl & RXC_CAM) + m_enet_tx_ctrl = (m_enet_tx_ctrl & (TXC_LC | TXC_ST)) | (data & ~(TXC_CA | TXC_LC | TXC_ST)); + else + m_enet_tx_ctrl = (m_enet_tx_ctrl & (TXC_LC | TXC_ST)) | (data & ~((TXC_LC | TXC_ST))); + + if ((m_enet_tx_ctrl & TXC_CA) && !m_enet_tx_timer->enabled()) + m_enet_tx_timer->adjust(attotime::zero); break; case 0x7008/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter GIO FIFO Pointer Write (ignored): %08x\n", machine().describe_context(), data); @@ -567,35 +553,115 @@ WRITE32_MEMBER(hpc3_device::hd_enet_w) case 0x700c/4: LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Device FIFO Pointer Write (ignored): %08x\n", machine().describe_context(), data); break; + case 0x8000/4: + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Receiver Current Buffer Descriptor Pointer Write: %08x\n", machine().describe_context(), data); + m_enet_rx_cbdp = data; + break; + case 0xa000/4: + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Current/Previous Buffer Descriptor Pointer Write: %08x\n", machine().describe_context(), data); + m_enet_tx_cpfbdp = data; + break; + case 0xa004/4: + LOGMASKED(LOG_ETHERNET, "%s: HPC3 Ethernet Transmitter Previous/Previous Buffer Descriptor Pointer Write: %08x\n", machine().describe_context(), data); + m_enet_tx_ppfbdp = data; + break; + default: LOGMASKED(LOG_UNKNOWN, "%s: Unknown HPC3 ENET/HDx write: %08x = %08x & %08x\n", machine().describe_context(), 0x1fb90000 + (offset << 2), data, mem_mask); break; } } -WRITE_LINE_MEMBER(hpc3_device::enet_txrdy_w) +void hpc3_device::enet_rxrdy_w(int state) { - // TODO -} + // check receive dma enabled + if (state && (m_enet_rx_ctrl & RXC_CA)) + { + // next descriptor becomes current + m_enet_rx_cbdp = m_enet_rx_nbdp; -WRITE_LINE_MEMBER(hpc3_device::enet_rxrdy_w) -{ - // TODO -} + // fetch the current descriptor + m_enet_rx_cbp = m_gio64_space->read_dword(m_enet_rx_cbdp + 0); + m_enet_rx_bc = m_gio64_space->read_dword(m_enet_rx_cbdp + 4); + m_enet_rx_nbdp = m_gio64_space->read_dword(m_enet_rx_cbdp + 8); -WRITE_LINE_MEMBER(hpc3_device::enet_rxdc_w) -{ - // TODO -} + LOGMASKED(LOG_ETHERNET, "enet rx dma chain 0x%08x cbp 0x%08x bc 0x%08x nbdp 0x%08x\n", + m_enet_rx_cbdp, m_enet_rx_cbp, m_enet_rx_bc, m_enet_rx_nbdp); -WRITE_LINE_MEMBER(hpc3_device::enet_txret_w) -{ - // TODO + // skip buffer alignment bytes + if (enet_rx_bc_dec(2)) + m_enet_rx_cbp += 2; + + // transfer data from edlc fifo to memory + while (!m_enet->rxeof_r()) + if (enet_rx_bc_dec()) + m_gio64_space->write_byte(m_enet_rx_cbp++, m_enet->fifo_r()); + } } -WRITE_LINE_MEMBER(hpc3_device::enet_intr_in_w) +void hpc3_device::enet_intr_in_w(int state) { - // TODO + if (state) + { + bool interrupt = false; + + // copy edlc status registers + m_enet_rx_ctrl &= ~RXC_ST; + m_enet_rx_ctrl |= m_enet->read(6) & RXC_ST; + m_enet_tx_ctrl &= ~TXC_ST; + m_enet_tx_ctrl |= m_enet->read(7) & TXC_ST; + + LOGMASKED(LOG_ETHERNET, "rx status 0x%02x tx status 0x%02x\n", + u8(m_enet_rx_ctrl), u8(m_enet_tx_ctrl)); + + // tx interrupt + if (!(m_enet_tx_ctrl & TXC_ST_O)) + { + // write txd and clear byte count + if (m_enet_tx_ctrl & TXC_ST_S) + m_gio64_space->write_word(m_enet_tx_cpfbdp + 6, BC_TXD); + + // interrupt host if xie or error + if ((m_enet_tx_bc & BC_XIE) || (m_enet_tx_ctrl & (TXC_ST_U | TXC_ST_C | TXC_ST_R))) + { + // stop dma + // FIXME: do we always stop dma, or only on errors? + m_enet_tx_ctrl &= ~TXC_CA; + + interrupt = true; + } + + // transmit next packet + if (m_enet_tx_ctrl & TXC_CA) + m_enet_tx_timer->adjust(attotime::zero); + } + + // rx interrupt + if (!(m_enet_rx_ctrl & RXC_ST_O)) + { + // transfer the status byte + if (enet_rx_bc_dec()) + m_gio64_space->write_byte(m_enet_rx_cbp++, u8(m_enet_rx_ctrl)); + + // store the remaining buffer length + m_gio64_space->write_word(m_enet_rx_cbdp + 6, u16(m_enet_rx_bc & BC_BC)); + + // check for edlc overflow, receive buffer overflow or end of descriptor chain + if ((m_enet_rx_ctrl & (RXC_ST_V | RXC_RBO)) || (m_enet_rx_bc & BC_EOX)) + { + m_enet_rx_ctrl &= ~RXC_CA; + interrupt = true; + } + else if (m_enet_rx_bc & BC_XIE) + interrupt = true; + } + + if (interrupt && !BIT(m_enet_misc, 1)) + { + m_enet_misc |= MISC_INT; + m_enet_intr_out_cb(interrupt); + } + } } template @@ -1042,3 +1108,75 @@ void hpc3_device::eeprom_w(uint32_t data) m_eeprom_cs_cb(BIT(data, 1)); m_eeprom_clk_cb(BIT(data, 2)); } + +void hpc3_device::enet_transmit(void *ptr, int param) +{ + // save the first transmit buffer descriptor pointer + // TODO: not sure how cpfbdp and ppfbdp work, perhaps round-robin? + m_enet_tx_cpfbdp = m_enet_tx_nbdp; + + bool done = false; + while (!done) + { + // fetch the current descriptor + m_enet_tx_cbp = m_gio64_space->read_dword(m_enet_tx_nbdp + 0); + m_enet_tx_bc = m_gio64_space->read_dword(m_enet_tx_nbdp + 4); + m_enet_tx_nbdp = m_gio64_space->read_dword(m_enet_tx_nbdp + 8); + + LOGMASKED(LOG_ETHERNET, "enet tx dma chain 0x%08x cbp 0x%08x bc 0x%08x nbdp 0x%08x\n", + m_enet_tx_cpfbdp, m_enet_tx_cbp, m_enet_tx_bc, m_enet_tx_nbdp); + + // TODO: write inter-packet gap from first descriptor to seeq + //if (BIT(m_enet_dmacfg, 12)) + // m_enet->write(2, u8(m_enet_tx_bc >> 16)); + + // transfer data from memory to edlc fifo + unsigned const count = m_enet_tx_bc & BC_BC; + for (unsigned i = 0; i < count; i++) + m_enet->fifo_w(m_gio64_space->read_byte(m_enet_tx_cbp + i)); + + // check for end of packet + if (m_enet_tx_bc & BC_EOXP) + { + m_enet->txeof_w(1); + done = true; + } + + // check for end of chain + if (m_enet_tx_bc & BC_EOX) + { + // stop dma + m_enet_tx_ctrl &= ~TXC_CA; + done = true; + } + } +} + +void hpc3_device::enet_misc_w(u32 data) +{ + // channel reset + m_enet->reset_w(!(data & MISC_RESET)); + // TODO: reset ethernet dma state + + // clear channel interrupt + if (data & MISC_INT) + m_enet_intr_out_cb(0); + + // TODO: loopback + + m_enet_misc = data & ~MISC_INT; +} + +bool hpc3_device::enet_rx_bc_dec(unsigned const count) +{ + if ((m_enet_rx_bc & BC_BC) >= count) + { + m_enet_rx_bc = (m_enet_rx_bc & ~BC_BC) | (((m_enet_rx_bc & BC_BC) - count) & BC_BC); + + return true; + } + + // receive buffer overflow + m_enet_rx_ctrl |= RXC_RBO; + return false; +} diff --git a/src/mame/machine/hpc3.h b/src/mame/machine/hpc3.h index aa59275eb9d..3630cbf9058 100644 --- a/src/mame/machine/hpc3.h +++ b/src/mame/machine/hpc3.h @@ -12,6 +12,7 @@ #pragma once #include "machine/hal2.h" +#include "machine/edlc.h" class hpc3_device : public device_t, public device_memory_interface { @@ -41,15 +42,8 @@ public: template void set_gio64_space(T &&tag, int spacenum) { m_gio64_space.set_tag(std::forward(tag), spacenum); } template void set_hal2_tag(T &&tag) { m_hal2.set_tag(std::forward(tag)); } + template void set_enet(T &&tag) { m_enet.set_tag(std::forward(tag)); } - auto enet_rd_cb() { return m_enet_rd_cb.bind(); } - auto enet_wr_cb() { return m_enet_wr_cb.bind(); } - auto enet_rxrd_cb() { return m_enet_rxrd_cb.bind(); } - auto enet_txwr_cb() { return m_enet_txwr_cb.bind(); } - auto enet_d8_rd_cb() { return m_enet_d8_rd_cb.bind(); } - auto enet_d8_wr_cb() { return m_enet_d8_wr_cb.bind(); } - auto enet_reset_cb() { return m_enet_reset_cb.bind(); } - auto enet_loopback_cb() { return m_enet_loopback_cb.bind(); } auto enet_intr_out_cb() { return m_enet_intr_out_cb.bind(); } template auto hd_rd_cb() { return m_hd_rd_cb[N].bind(); } template auto hd_wr_cb() { return m_hd_wr_cb[N].bind(); } @@ -67,11 +61,8 @@ public: void map(address_map &map); - DECLARE_WRITE_LINE_MEMBER(enet_txrdy_w); - DECLARE_WRITE_LINE_MEMBER(enet_rxrdy_w); - DECLARE_WRITE_LINE_MEMBER(enet_rxdc_w); - DECLARE_WRITE_LINE_MEMBER(enet_txret_w); - DECLARE_WRITE_LINE_MEMBER(enet_intr_in_w); + void enet_rxrdy_w(int state); + void enet_intr_in_w(int state); DECLARE_WRITE_LINE_MEMBER(scsi0_drq); DECLARE_WRITE_LINE_MEMBER(scsi1_drq); @@ -128,6 +119,10 @@ protected: void scsi_drq(bool state, int channel); //void scsi_dma(int channel); + void enet_transmit(void *ptr = nullptr, int param = 0); + void enet_misc_w(u32 data); + bool enet_rx_bc_dec(unsigned const count = 1); + static const device_timer_id TIMER_PBUS_DMA = 0; struct pbus_dma_t @@ -187,15 +182,8 @@ protected: required_address_space m_gio64_space; address_space *m_pio_space[10]; required_device m_hal2; + required_device m_enet; - devcb_read8 m_enet_rd_cb; - devcb_write8 m_enet_wr_cb; - devcb_read8 m_enet_rxrd_cb; - devcb_write8 m_enet_txwr_cb; - devcb_read_line m_enet_d8_rd_cb; - devcb_write_line m_enet_d8_wr_cb; - devcb_write_line m_enet_reset_cb; - devcb_write_line m_enet_loopback_cb; devcb_write_line m_enet_intr_out_cb; devcb_read8::array<2> m_hd_rd_cb; devcb_write8::array<2> m_hd_wr_cb; @@ -230,21 +218,6 @@ protected: bool m_active; }; - struct enet_dma_t - { - uint32_t m_cbp; - uint32_t m_nbdp; - uint32_t m_bc; - uint32_t m_ctrl; - uint32_t m_gio_fifo_ptr; - uint32_t m_dev_fifo_ptr; - }; - - enet_dma_t m_enet_dma[2]; - uint32_t m_enet_reset; - uint32_t m_enet_dmacfg; - uint32_t m_enet_piocfg; - scsi_dma_t m_scsi_dma[2]; pbus_dma_t m_pbus_dma[8]; uint32_t m_pio_config[10]; @@ -252,6 +225,78 @@ protected: std::unique_ptr m_pbus_fifo; std::unique_ptr m_scsi_fifo[2]; std::unique_ptr m_enet_fifo[2]; + +private: + emu_timer *m_enet_tx_timer; + + enum enet_dma_rx_ctrl : u32 + { + RXC_ST = 0x0000'00bf, // edlc receive status + RXC_LC = 0x0000'0040, // late receive collision + RXC_LE = 0x0000'0100, // receive little endian + RXC_CA = 0x0000'0200, // receive channel active + RXC_CAM = 0x0000'0400, // receive channel active mask + RXC_RBO = 0x0000'0800, // receive buffer overflow + + // individual receive status bits + RXC_ST_V = 0x0000'0001, // received frame with overflow error + RXC_ST_C = 0x0000'0002, // received frame with crc error + RXC_ST_D = 0x0000'0004, // received frame with dribble error + RXC_ST_S = 0x0000'0008, // received short frame + RXC_ST_E = 0x0000'0010, // received end of frame + RXC_ST_G = 0x0000'0020, // received good frame + RXC_ST_O = 0x0000'0080, // old/new status + }; + enum enet_dma_tx_ctrl : u32 + { + TXC_ST = 0x0000'00ef, // edlc transmit status + TXC_LC = 0x0000'0010, // late transmit collision + TXC_LE = 0x0000'0100, // transmit little endian + TXC_CA = 0x0000'0200, // transmit channel active + TXC_CAM = 0x0000'0400, // transmit channel active mask + + // individual transmit status bits + TXC_ST_U = 0x0000'0001, // transmit underflow + TXC_ST_C = 0x0000'0002, // transmit collision + TXC_ST_R = 0x0000'0004, // 16 transmission attempts + TXC_ST_S = 0x0000'0008, // transmission successful + TXC_ST_O = 0x0000'0080, // old/new status + }; + enum enet_dma_bc : u32 + { + BC_BC = 0x0000'3fff, // byte count + BC_TXD = 0x0000'8000, // transmit done + BC_IPG = 0x00ff'0000, // inter-packet gap + BC_XIE = 0x2000'0000, // transmit interrupt enable + BC_EOXP = 0x4000'0000, // end of packet + BC_EOX = 0x8000'0000, // end of descriptor chain + }; + enum enet_enet_misc : u32 + { + MISC_RESET = 0x0000'0001, // channel reset + MISC_INT = 0x0000'0002, // interrupt + MISC_LOOPBACK = 0x0000'0004, // loopback + }; + + // ethernet registers + u32 m_enet_rx_cbp; // current receive buffer pointer + u32 m_enet_rx_nbdp; // next receive buffer descriptor pointer + u32 m_enet_rx_bc; // receive byte count + u32 m_enet_rx_ctrl; // receive status + u32 m_enet_rx_gio; // receive gio fifo pointer + u32 m_enet_rx_dev; // receive device fifo pointer + u32 m_enet_misc; // reset, clear interrupt, loopback + u32 m_enet_piocfg; // pio configuration + u32 m_enet_dmacfg; // dma configuration + u32 m_enet_tx_cbp; // current transmit buffer pointer + u32 m_enet_tx_nbdp; // next transmit buffer descriptor pointer + u32 m_enet_tx_bc; // transmit byte count + u32 m_enet_tx_ctrl; // transmit status + u32 m_enet_tx_gio; // transmit gio fifo pointer + u32 m_enet_tx_dev; // transmit device fifo pointer + u32 m_enet_rx_cbdp; // current receive buffer descriptor pointer + u32 m_enet_tx_cpfbdp; // current/previous first transmit buffer descriptor pointer + u32 m_enet_tx_ppfbdp; // previous/previous? first transmit buffer descriptor pointer }; DECLARE_DEVICE_TYPE(SGI_HPC3, hpc3_device) -- cgit v1.2.3