{
udi_init_context_t init_context;
- struct
- {
+ udi_cb_t *active_cb;
+
+ udi_intr_attach_cb_t *intr_attach_cb;
+
+ struct {
udi_index_t pio_index;
+ udi_index_t n_intr_event_cb;
+
+ udi_index_t rx_chan_index;
} init;
- udi_pio_handle_t pio_handles[1];
+ udi_pio_handle_t pio_handles[4];
+ udi_channel_t interrupt_channel;
+ udi_channel_t rx_channel;
+ udi_channel_t tx_channel;
+
udi_ubit8_t macaddr[6];
} ne2k_rdata_t;
extern udi_channel_event_ind_op_t ne2k_bus_dev_channel_event_ind;
extern udi_bus_bind_ack_op_t ne2k_bus_dev_bus_bind_ack;
extern udi_pio_map_call_t ne2k_bus_dev_bind__pio_map;
+extern udi_channel_spawn_call_t ne2k_bus_dev_bind__intr_chanel;
+extern udi_cb_alloc_call_t ne2k_bus_dev_bind__intr_attach;
extern udi_bus_unbind_ack_op_t ne2k_bus_dev_bus_unbind_ack;
extern udi_intr_attach_ack_op_t ne2k_bus_dev_intr_attach_ack;
+extern udi_cb_alloc_call_t ne2k_bus_dev_bind__intr_event_cb;
+extern udi_pio_trans_call_t ne2k_bus_dev_bind__card_reset;
extern udi_intr_detach_ack_op_t ne2k_bus_dev_intr_detach_ack;
extern udi_channel_event_ind_op_t ne2k_nd_ctrl_channel_event_ind;
extern udi_nd_bind_req_op_t ne2k_nd_ctrl_bind_req;
+extern udi_channel_spawn_call_t ne2k_nd_ctrl_bind__tx_chan_ok;
+extern udi_channel_spawn_call_t ne2k_nd_ctrl_bind__rx_chan_ok;
extern udi_nd_unbind_req_op_t ne2k_nd_ctrl_unbind_req;
extern udi_nd_enable_req_op_t ne2k_nd_ctrl_enable_req;
extern udi_nd_disable_req_op_t ne2k_nd_ctrl_disable_req;
extern udi_channel_event_ind_op_t ne2k_nd_rx_channel_event_ind;
extern udi_nd_rx_rdy_op_t ne2k_nd_rx_rx_rdy;
+extern udi_channel_event_ind_op_t ne2k_bus_irq_channel_event_ind;
+extern udi_intr_event_ind_op_t ne2k_bus_irq_intr_event_ind;
+
+extern void ne2k_intr__rx_ok(udi_cb_t *gcb);
+
#endif
#include <udi_nic.h>
#include "ne2000_common.h"
-#define NE2K_META_BUS 1
-#define NE2K_META_NIC 2
+enum {
+ NE2K_META_BUS = 1,
+ NE2K_META_NIC,
+};
+enum {
+ NE2K_OPS_DEV = 1,
+ NE2K_OPS_CTRL,
+ NE2K_OPS_TX,
+ NE2K_OPS_RX,
+ NE2K_OPS_IRQ,
+};
+enum {
+ NE2K_CB_INTR = 1,
+ NE2K_CB_INTR_EVENT,
+};
+
+#define NE2K_NUM_INTR_EVENT_CBS 4
// === GLOBALS ===
#define PIO_op_RI(op, reg, sz, val) {UDI_PIO_##op+UDI_PIO_DIRECT+UDI_PIO_##reg, UDI_PIO_##sz##BYTE, val}
#define PIO_OUT_RI1(reg, ofs) PIO_op_RI(OUT, reg, 1, ofs)
#define PIO_IN_RI1(reg, ofs) PIO_op_RI(IN, reg, 1, ofs)
// --- Programmed IO ---
-/// Ne2000 reset operation (reads MAC address too)
-udi_pio_trans_t ne2k_pio_reset[] = {
- // - Reset card
- PIO_IN_RI1(R0, NE2K_REG_RESET),
- PIO_OUT_RI1(R0, NE2K_REG_RESET),
- // While ISR bit 7 is unset, spin
- {UDI_PIO_LABEL, 0, 1},
- PIO_IN_RI1(R0, NE2K_REG_ISR),
- {UDI_PIO_AND_IMM+UDI_PIO_R0, UDI_PIO_1BYTE, 0x80},
- {UDI_PIO_CSKIP+UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_NZ},
- {UDI_PIO_BRANCH, 0, 1},
- // ISR = 0x80 [Clear reset]
- PIO_OUT_RI1(R0, NE2K_REG_ISR),
- // - Init pass 1
- // CMD = 0x40|0x21 [Page1, NoDMA, Stop]
- PIO_MOV_RI1(R0, 0x40|0x21),
- PIO_OUT_RI1(R0, NE2K_REG_CMD),
- // CURR = First RX page
- PIO_MOV_RI1(R0, NE2K_RX_FIRST_PG),
- PIO_OUT_RI1(R0, NE2K_REG_CURR),
- // CMD = 0x21 [Page0, NoDMA, Stop]
- PIO_MOV_RI1(R0, 0x21),
- PIO_OUT_RI1(R0, NE2K_REG_CMD),
- // DCR = ? [WORD, ...]
- PIO_MOV_RI1(R0, 0x49),
- PIO_OUT_RI1(R0, NE2K_REG_DCR),
- // IMR = 0 [Disable all]
- PIO_MOV_RI1(R0, 0x00),
- PIO_OUT_RI1(R0, NE2K_REG_IMR),
- // ISR = 0xFF [ACK all]
- PIO_MOV_RI1(R0, 0xFF),
- PIO_OUT_RI1(R0, NE2K_REG_ISR),
- // RCR = 0x20 [Monitor]
- PIO_MOV_RI1(R0, 0x20),
- PIO_OUT_RI1(R0, NE2K_REG_RCR),
- // TCR = 0x02 [TX Off, Loopback]
- PIO_MOV_RI1(R0, 0x02),
- PIO_OUT_RI1(R0, NE2K_REG_TCR),
- // - Read MAC address from EEPROM (24 bytes from 0)
- PIO_MOV_RI1(R0, 0),
- PIO_MOV_RI1(R1, 0),
- PIO_OUT_RI1(R0, NE2K_REG_RSAR0),
- PIO_OUT_RI1(R1, NE2K_REG_RSAR1),
- PIO_MOV_RI1(R0, 6*4),
- PIO_MOV_RI1(R1, 0),
- PIO_OUT_RI1(R0, NE2K_REG_RBCR0),
- PIO_OUT_RI1(R1, NE2K_REG_RBCR1),
- // CMD = 0x0A [Start remote DMA]
- PIO_MOV_RI1(R0, 0x0A),
- PIO_OUT_RI1(R0, NE2K_REG_CMD),
- // Read MAC address
- PIO_MOV_RI1(R0, 0), // - Buffer offset (incremented by 1 each iteration)
- PIO_MOV_RI1(R1, NE2K_REG_MEM), // - Reg offset (no increment)
- PIO_MOV_RI1(R2, 6), // - Six iterations
- {UDI_PIO_REP_IN_IND, UDI_PIO_1BYTE,
- UDI_PIO_REP_ARGS(UDI_PIO_BUF, UDI_PIO_R0, 1, UDI_PIO_R1, 0, UDI_PIO_R2)},
- // - Setup
- // PSTART = First RX page [Receive area start]
- PIO_MOV_RI1(R0, NE2K_RX_FIRST_PG),
- PIO_OUT_RI1(R0, NE2K_REG_PSTART),
- // BNRY = Last RX page - 1 [???]
- PIO_MOV_RI1(R0, NE2K_RX_LAST_PG-1),
- PIO_OUT_RI1(R0, NE2K_REG_BNRY),
- // PSTOP = Last RX page [???]
- PIO_MOV_RI1(R0, NE2K_RX_LAST_PG),
- PIO_OUT_RI1(R0, NE2K_REG_PSTOP),
- // > Clear all interrupt and set mask
- // ISR = 0xFF [ACK all]
- PIO_MOV_RI1(R0, 0xFF),
- PIO_OUT_RI1(R0, NE2K_REG_ISR),
- // IMR = 0x3F []
- PIO_MOV_RI1(R0, 0x3F),
- PIO_OUT_RI1(R0, NE2K_REG_IMR),
- // CMD = 0x22 [NoDMA, Start]
- PIO_MOV_RI1(R0, 0x22),
- PIO_OUT_RI1(R0, NE2K_REG_CMD),
- // RCR = 0x0F [Wrap, Promisc]
- PIO_MOV_RI1(R0, 0x0F),
- PIO_OUT_RI1(R0, NE2K_REG_RCR),
- // TCR = 0x00 [Normal]
- PIO_MOV_RI1(R0, 0x00),
- PIO_OUT_RI1(R0, NE2K_REG_TCR),
- // TPSR = 0x40 [TX Start]
- PIO_MOV_RI1(R0, 0x40),
- PIO_OUT_RI1(R0, NE2K_REG_TPSR),
- // End
- {UDI_PIO_END_IMM, UDI_PIO_2BYTE, 0}
-};
-struct {
- udi_pio_trans_t *trans_list;
- udi_ubit16_t list_length;
- udi_ubit16_t pio_attributes;
-} ne2k_pio_ops[] = {
- {ne2k_pio_reset, ARRAY_SIZEOF(ne2k_pio_reset), 0}
-};
-const int NE2K_NUM_PIO_OPS = ARRAY_SIZEOF(ne2k_pio_ops);
+#include "ne2000_pio.h"
// === CODE ===
// --- Management
rdata->macaddr[0], rdata->macaddr[1], rdata->macaddr[2],
rdata->macaddr[3], rdata->macaddr[4], rdata->macaddr[5] );
attr_list ++;
- udi_enumerate_ack(cb, UDI_ENUMERATE_OK, 2);
+ udi_enumerate_ack(cb, UDI_ENUMERATE_OK, NE2K_OPS_CTRL);
break;
case UDI_ENUMERATE_NEXT:
udi_enumerate_ack(cb, UDI_ENUMERATE_DONE, 0);
{
udi_cb_t *gcb = UDI_GCB(cb);
ne2k_rdata_t *rdata = gcb->context;
+ rdata->active_cb = gcb;
// Set up PIO handles
rdata->init.pio_index = -1;
ne2k_pio_ops[rdata->init.pio_index].list_length,
UDI_PIO_LITTLE_ENDIAN, 0, 0
);
+ return ;
}
- else
- {
- // Next!
- }
+
+ // Next: Bind interrupt
+ udi_channel_spawn(ne2k_bus_dev_bind__intr_chanel, gcb, gcb->channel,
+ 0, NE2K_OPS_IRQ, rdata);
+}
+void ne2k_bus_dev_bind__intr_chanel(udi_cb_t *gcb, udi_channel_t new_channel)
+{
+ ne2k_rdata_t *rdata = gcb->context;
+
+ rdata->interrupt_channel = new_channel;
+
+ udi_cb_alloc(ne2k_bus_dev_bind__intr_attach, gcb, NE2K_CB_INTR, gcb->channel);
+}
+void ne2k_bus_dev_bind__intr_attach(udi_cb_t *gcb, udi_cb_t *new_cb)
+{
+ ne2k_rdata_t *rdata = gcb->context;
+ udi_intr_attach_cb_t *intr_cb = UDI_MCB(new_cb, udi_intr_attach_cb_t);
+ intr_cb->interrupt_idx = 0;
+ intr_cb->min_event_pend = 2;
+ intr_cb->preprocessing_handle = rdata->pio_handles[NE2K_PIO_IRQACK];
+ udi_intr_attach_req(intr_cb);
+ // continued in ne2k_bus_dev_intr_attach_ack
}
void ne2k_bus_dev_bus_unbind_ack(udi_bus_bind_cb_t *cb)
{
}
void ne2k_bus_dev_intr_attach_ack(udi_intr_attach_cb_t *intr_attach_cb, udi_status_t status)
{
+ udi_cb_t *gcb = UDI_GCB(intr_attach_cb);
+ ne2k_rdata_t *rdata = gcb->context;
+ // continuing from ne2k_bus_dev_bind__intr_attach
+ if( status != UDI_OK ) {
+ // TODO: Error
+ udi_cb_free( UDI_GCB(intr_attach_cb) );
+ return ;
+ }
+
+ rdata->intr_attach_cb = intr_attach_cb;
+
+ rdata->init.n_intr_event_cb = 0;
+ udi_cb_alloc(ne2k_bus_dev_bind__intr_event_cb, gcb, NE2K_CB_INTR_EVENT, rdata->interrupt_channel);
+ // V V V V
+}
+void ne2k_bus_dev_bind__intr_event_cb(udi_cb_t *gcb, udi_cb_t *new_cb)
+{
+ ne2k_rdata_t *rdata = gcb->context;
+
+ udi_intr_event_cb_t *intr_event_cb = UDI_MCB(new_cb, udi_intr_event_cb_t);
+ udi_intr_event_rdy(intr_event_cb);
+ rdata->init.n_intr_event_cb ++;
+
+ if( rdata->init.n_intr_event_cb < NE2K_NUM_INTR_EVENT_CBS )
+ {
+ udi_cb_alloc(ne2k_bus_dev_bind__intr_event_cb, gcb,
+ NE2K_CB_INTR_EVENT, rdata->interrupt_channel);
+ // A A A A
+ return ;
+ }
+
+ udi_pio_trans(ne2k_bus_dev_bind__card_reset, gcb,
+ rdata->pio_handles[NE2K_PIO_RESET], 0, NULL, &rdata->macaddr);
+ // V V V V
+}
+
+void ne2k_bus_dev_bind__card_reset(udi_cb_t *gcb, udi_buf_t *new_buf, udi_status_t status, udi_ubit16_t result)
+{
+ ne2k_rdata_t *rdata = gcb->context;
+ // Done! (Finally)
+ udi_channel_event_complete( UDI_MCB(rdata->active_cb, udi_channel_event_cb_t), UDI_OK );
+ // = = = =
}
void ne2k_bus_dev_intr_detach_ack(udi_intr_detach_cb_t *intr_detach_cb)
{
}
void ne2k_nd_ctrl_bind_req(udi_nic_bind_cb_t *cb, udi_index_t tx_chan_index, udi_index_t rx_chan_index)
{
+ udi_cb_t *gcb = UDI_GCB(cb);
+ ne2k_rdata_t *rdata = gcb->context;
+ rdata->init.rx_chan_index = rx_chan_index;
+ udi_channel_spawn(ne2k_nd_ctrl_bind__tx_chan_ok, gcb, gcb->channel, tx_chan_index, NE2K_OPS_TX, rdata);
+ // V V V V
+}
+void ne2k_nd_ctrl_bind__tx_chan_ok(udi_cb_t *gcb, udi_channel_t new_channel)
+{
+ ne2k_rdata_t *rdata = gcb->context;
+ rdata->tx_channel = new_channel;
+ udi_channel_spawn(ne2k_nd_ctrl_bind__rx_chan_ok, gcb, gcb->channel,
+ rdata->init.rx_chan_index, NE2K_OPS_RX, rdata);
+ // V V V V
+}
+void ne2k_nd_ctrl_bind__rx_chan_ok(udi_cb_t *cb, udi_channel_t new_channel)
+{
+ ne2k_rdata_t *rdata = cb->context;
+ rdata->rx_channel = new_channel;
+ udi_nsr_bind_ack( UDI_MCB(cb, udi_nic_bind_cb_t), UDI_OK );
+ // = = = =
}
void ne2k_nd_ctrl_unbind_req(udi_nic_cb_t *cb)
{
}
void ne2k_nd_ctrl_enable_req(udi_nic_cb_t *cb)
{
+ // Enable
}
void ne2k_nd_ctrl_disable_req(udi_nic_cb_t *cb)
{
void ne2k_nd_ctrl_info_req(udi_nic_info_cb_t *cb, udi_boolean_t reset_statistics)
{
}
+// --- IRQ
+void ne2k_bus_irq_channel_event_ind(udi_channel_event_cb_t *cb)
+{
+}
+void ne2k_bus_irq_intr_event_ind(udi_intr_event_cb_t *cb, udi_ubit8_t flags)
+{
+ if( cb->intr_result & 0x01 )
+ {
+ ne2k_intr__rx_ok( UDI_GCB(cb) );
+ }
+ udi_intr_event_rdy(cb);
+}
// === Definition structures ===
udi_mgmt_ops_t ne2k_mgmt_ops = {
ne2k_nd_rx_rx_rdy
};
udi_ubit8_t ne2k_nd_rx_ops_flags[2] = {0};
+udi_intr_handler_ops_t ne2k_bus_irq_ops = {
+ ne2k_bus_irq_channel_event_ind,
+ ne2k_bus_irq_intr_event_ind
+};
+udi_ubit8_t ne2k_bus_irq_ops_flags[2] = {0};
+
udi_primary_init_t ne2k_pri_init = {
.mgmt_ops = &ne2k_mgmt_ops,
.mgmt_op_flags = ne2k_mgmt_op_flags,
};
udi_ops_init_t ne2k_ops_list[] = {
{
- 1, NE2K_META_BUS, UDI_BUS_DEVICE_OPS_NUM,
+ NE2K_OPS_DEV, NE2K_META_BUS, UDI_BUS_DEVICE_OPS_NUM,
0,
(udi_ops_vector_t*)&ne2k_bus_dev_ops,
ne2k_bus_dev_ops_flags
},
{
- 2, NE2K_META_NIC, UDI_ND_CTRL_OPS_NUM,
+ NE2K_OPS_CTRL, NE2K_META_NIC, UDI_ND_CTRL_OPS_NUM,
0,
(udi_ops_vector_t*)&ne2k_nd_ctrl_ops,
ne2k_nd_ctrl_ops_flags
},
{
- 3, NE2K_META_NIC, UDI_ND_TX_OPS_NUM,
+ NE2K_OPS_TX, NE2K_META_NIC, UDI_ND_TX_OPS_NUM,
0,
(udi_ops_vector_t*)&ne2k_nd_tx_ops,
ne2k_nd_tx_ops_flags
},
{
- 4, NE2K_META_NIC, UDI_ND_RX_OPS_NUM,
+ NE2K_OPS_RX, NE2K_META_NIC, UDI_ND_RX_OPS_NUM,
0,
(udi_ops_vector_t*)&ne2k_nd_rx_ops,
ne2k_nd_rx_ops_flags
},
+ {
+ NE2K_OPS_IRQ, NE2K_META_BUS, UDI_BUS_INTR_HANDLER_OPS_NUM,
+ 0,
+ (udi_ops_vector_t*)&ne2k_bus_irq_ops,
+ ne2k_bus_irq_ops_flags
+ },
{0}
};
const udi_init_t udi_init_info = {
--- /dev/null
+//
+// Ne2000 reset operation (reads MAC address too)
+//
+udi_pio_trans_t ne2k_pio_reset[] = {
+ // - Reset card
+ PIO_IN_RI1(R0, NE2K_REG_RESET),
+ PIO_OUT_RI1(R0, NE2K_REG_RESET),
+ // While ISR bit 7 is unset, spin
+ {UDI_PIO_LABEL, 0, 1},
+ PIO_IN_RI1(R0, NE2K_REG_ISR),
+ {UDI_PIO_AND_IMM+UDI_PIO_R0, UDI_PIO_1BYTE, 0x80},
+ {UDI_PIO_CSKIP+UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_NZ},
+ {UDI_PIO_BRANCH, 0, 1},
+ // ISR = 0x80 [Clear reset]
+ PIO_OUT_RI1(R0, NE2K_REG_ISR),
+ // - Init pass 1
+ // CMD = 0x40|0x21 [Page1, NoDMA, Stop]
+ PIO_MOV_RI1(R0, 0x40|0x21),
+ PIO_OUT_RI1(R0, NE2K_REG_CMD),
+ // CURR = First RX page
+ PIO_MOV_RI1(R0, NE2K_RX_FIRST_PG),
+ PIO_OUT_RI1(R0, NE2K_REG_CURR),
+ // CMD = 0x21 [Page0, NoDMA, Stop]
+ PIO_MOV_RI1(R0, 0x21),
+ PIO_OUT_RI1(R0, NE2K_REG_CMD),
+ // DCR = ? [WORD, ...]
+ PIO_MOV_RI1(R0, 0x49),
+ PIO_OUT_RI1(R0, NE2K_REG_DCR),
+ // IMR = 0 [Disable all]
+ PIO_MOV_RI1(R0, 0x00),
+ PIO_OUT_RI1(R0, NE2K_REG_IMR),
+ // ISR = 0xFF [ACK all]
+ PIO_MOV_RI1(R0, 0xFF),
+ PIO_OUT_RI1(R0, NE2K_REG_ISR),
+ // RCR = 0x20 [Monitor]
+ PIO_MOV_RI1(R0, 0x20),
+ PIO_OUT_RI1(R0, NE2K_REG_RCR),
+ // TCR = 0x02 [TX Off, Loopback]
+ PIO_MOV_RI1(R0, 0x02),
+ PIO_OUT_RI1(R0, NE2K_REG_TCR),
+ // - Read MAC address from EEPROM (24 bytes from 0)
+ PIO_MOV_RI1(R0, 0),
+ PIO_MOV_RI1(R1, 0),
+ PIO_OUT_RI1(R0, NE2K_REG_RSAR0),
+ PIO_OUT_RI1(R1, NE2K_REG_RSAR1),
+ PIO_MOV_RI1(R0, 6*4),
+ PIO_MOV_RI1(R1, 0),
+ PIO_OUT_RI1(R0, NE2K_REG_RBCR0),
+ PIO_OUT_RI1(R1, NE2K_REG_RBCR1),
+ // CMD = 0x0A [Start remote DMA]
+ PIO_MOV_RI1(R0, 0x0A),
+ PIO_OUT_RI1(R0, NE2K_REG_CMD),
+ // Read MAC address
+ PIO_MOV_RI1(R0, 0), // - Buffer offset (incremented by 1 each iteration)
+ PIO_MOV_RI1(R1, NE2K_REG_MEM), // - Reg offset (no increment)
+ PIO_MOV_RI1(R2, 6), // - Six iterations
+ {UDI_PIO_REP_IN_IND, UDI_PIO_1BYTE,
+ UDI_PIO_REP_ARGS(UDI_PIO_MEM, UDI_PIO_R0, 1, UDI_PIO_R1, 0, UDI_PIO_R2)},
+ // End
+ {UDI_PIO_END_IMM, UDI_PIO_2BYTE, 0}
+};
+//
+// Enable the card
+//
+udi_pio_trans_t ne2k_pio_enable[] = {
+ // - Setup
+ // PSTART = First RX page [Receive area start]
+ PIO_MOV_RI1(R0, NE2K_RX_FIRST_PG),
+ PIO_OUT_RI1(R0, NE2K_REG_PSTART),
+ // BNRY = Last RX page - 1 [???]
+ PIO_MOV_RI1(R0, NE2K_RX_LAST_PG-1),
+ PIO_OUT_RI1(R0, NE2K_REG_BNRY),
+ // PSTOP = Last RX page [???]
+ PIO_MOV_RI1(R0, NE2K_RX_LAST_PG),
+ PIO_OUT_RI1(R0, NE2K_REG_PSTOP),
+ // CMD = 0x22 [NoDMA, Start]
+ PIO_MOV_RI1(R0, 0x22),
+ PIO_OUT_RI1(R0, NE2K_REG_CMD),
+ // RCR = 0x0F [Wrap, Promisc]
+ PIO_MOV_RI1(R0, 0x0F),
+ PIO_OUT_RI1(R0, NE2K_REG_RCR),
+ // TCR = 0x00 [Normal]
+ PIO_MOV_RI1(R0, 0x00),
+ PIO_OUT_RI1(R0, NE2K_REG_TCR),
+ // TPSR = 0x40 [TX Start]
+ PIO_MOV_RI1(R0, 0x40),
+ PIO_OUT_RI1(R0, NE2K_REG_TPSR),
+ // End
+ {UDI_PIO_END_IMM, UDI_PIO_2BYTE, 0}
+};
+//
+// Read a packet
+// - Expects an output buffer
+//
+udi_pio_trans_t ne2k_pio_rx[] = {
+ // Get current page into R7
+ PIO_MOV_RI1(R0, 0),
+ {UDI_PIO_LOAD|UDI_PIO_MEM|UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_R7},
+ // Read header into regs, then data into buffer
+ // - CMD = 0x22
+ PIO_MOV_RI1(R0, 0x22), PIO_OUT_RI1(R0, NE2K_REG_CMD),
+ // - Clear RDMA flag
+ PIO_MOV_RI1(R0, 0x40), PIO_OUT_RI1(R0, NE2K_REG_ISR),
+ // - Set up transaction for 1 page from CurRX
+ PIO_MOV_RI1(R0, 1),
+ PIO_MOV_RI1(R1, 0),
+ PIO_OUT_RI1(R7, NE2K_REG_RSAR0), // Current RX page
+ PIO_OUT_RI1(R1, NE2K_REG_RSAR1),
+ PIO_OUT_RI1(R0, NE2K_REG_RBCR0),
+ PIO_OUT_RI1(R1, NE2K_REG_RBCR1),
+ // - Start read
+ PIO_MOV_RI1(R0, 0x0A), PIO_OUT_RI1(R0, NE2K_REG_CMD),
+ {UDI_PIO_DELAY, 0, 0},
+ // > Header to registers
+ {UDI_PIO_IN|UDI_PIO_DIRECT|UDI_PIO_R6, UDI_PIO_2BYTE, NE2K_REG_MEM}, // Status,NextPacketPage
+ {UDI_PIO_IN|UDI_PIO_DIRECT|UDI_PIO_R5, UDI_PIO_2BYTE, NE2K_REG_MEM}, // Length (bytes)
+ // > Data to buffer (126 words)
+ PIO_MOV_RI1(R4, 0), // - Buffer offset (incremented by 1 each iteration)
+ PIO_MOV_RI1(R1, NE2K_REG_MEM), // - Reg offset (no increment)
+ PIO_MOV_RI1(R2, 256/2-2), // - Six iterations
+ {UDI_PIO_REP_IN_IND, UDI_PIO_2BYTE,
+ UDI_PIO_REP_ARGS(UDI_PIO_BUF, UDI_PIO_R4, 2, UDI_PIO_R1, 0, UDI_PIO_R2)},
+ // - Subtract 256-4 from length, if <=0 we've grabbed the entire packet
+ {UDI_PIO_SUB|UDI_PIO_R5, UDI_PIO_2BYTE, 256-4},
+ {UDI_PIO_LABEL, 0, 2},
+ {UDI_PIO_CSKIP|UDI_PIO_R5, UDI_PIO_2BYTE, UDI_PIO_NZ},
+ {UDI_PIO_BRANCH, 0, 1}, // 1: End if ==0
+ {UDI_PIO_CSKIP|UDI_PIO_R5, UDI_PIO_2BYTE, UDI_PIO_NNEG},
+ {UDI_PIO_BRANCH, 0, 1}, // 1: End if <0
+ // - Read pages until all of packet RXd
+ {UDI_PIO_ADD|UDI_PIO_DIRECT|UDI_PIO_R7, UDI_PIO_1BYTE, 1},
+ {UDI_PIO_STORE|UDI_PIO_DIRECT|UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_R7},
+ {UDI_PIO_SUB|UDI_PIO_R0, UDI_PIO_1BYTE, NE2K_RX_LAST_PG+1},
+ {UDI_PIO_CSKIP|UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_NZ}, // if R7-RX_LAST == 0
+ {UDI_PIO_LOAD_IMM|UDI_PIO_R7, UDI_PIO_1BYTE, NE2K_RX_FIRST_PG}, // R7 = RX_FIRST
+ // > Transaction start
+ PIO_MOV_RI1(R0, 1),
+ PIO_MOV_RI1(R1, 0),
+ PIO_OUT_RI1(R7, NE2K_REG_RSAR0), // Current RX page
+ PIO_OUT_RI1(R1, NE2K_REG_RSAR1),
+ PIO_OUT_RI1(R0, NE2K_REG_RBCR0),
+ PIO_OUT_RI1(R1, NE2K_REG_RBCR1),
+ PIO_MOV_RI1(R0, 0x0A), PIO_OUT_RI1(R0, NE2K_REG_CMD),
+ {UDI_PIO_DELAY, 0, 0},
+ // > Data to buffer (128 words)
+ // buffer offset maintained in R4
+ PIO_MOV_RI1(R1, NE2K_REG_MEM), // - Reg offset (no increment)
+ PIO_MOV_RI1(R2, 256/2), // - Six iterations
+ {UDI_PIO_REP_IN_IND, UDI_PIO_2BYTE,
+ UDI_PIO_REP_ARGS(UDI_PIO_BUF, UDI_PIO_R4, 2, UDI_PIO_R1, 0, UDI_PIO_R2)},
+ // - Jump to length check
+ {UDI_PIO_SUB|UDI_PIO_R5, UDI_PIO_2BYTE, 256},
+ {UDI_PIO_BRANCH, 0, 2}, // 2: Check against length
+
+ // Cleanup
+ {UDI_PIO_LABEL, 0, 1},
+ // - Update next RX page, return status
+ {UDI_PIO_OUT|UDI_PIO_DIRECT|UDI_PIO_R7, UDI_PIO_1BYTE, NE2K_REG_BNRY},
+ {UDI_PIO_STORE|UDI_PIO_DIRECT|UDI_PIO_R7, UDI_PIO_2BYTE, UDI_PIO_R6}, // Status,Next
+ {UDI_PIO_SHIFT_RIGHT|UDI_PIO_DIRECT|UDI_PIO_R7, UDI_PIO_2BYTE, 8}, // Next
+ PIO_MOV_RI1(R0, 0),
+ {UDI_PIO_STORE|UDI_PIO_MEM|UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_R7}, // Store to mem[0]
+
+ {UDI_PIO_END, UDI_PIO_1BYTE, UDI_PIO_R6} // Status
+};
+//
+//
+//
+udi_pio_trans_t ne2k_pio_irqack[] = {
+ // 0: Enable interrupts
+ // IMR = 0x3F []
+ PIO_MOV_RI1(R0, 0x3F),
+ PIO_OUT_RI1(R0, NE2K_REG_IMR),
+ // ISR = 0xFF [ACK all]
+ PIO_MOV_RI1(R0, 0xFF),
+ PIO_OUT_RI1(R0, NE2K_REG_ISR),
+ {UDI_PIO_END_IMM, UDI_PIO_2BYTE, 0},
+ // 1: Normal
+ {UDI_PIO_LABEL, 0, 1},
+ PIO_IN_RI1(R0, NE2K_REG_ISR),
+ PIO_OUT_RI1(R0, NE2K_REG_ISR),
+ {UDI_PIO_CSKIP|UDI_PIO_R0, UDI_PIO_1BYTE, UDI_PIO_Z}, // if R0!=0
+ {UDI_PIO_END, UDI_PIO_2BYTE, UDI_PIO_R0},
+ // - No IRQ, quiet quit
+ PIO_MOV_RI1(R0, UDI_INTR_NO_EVENT),
+ PIO_MOV_RI1(R1, 0), // scratch offset
+ {UDI_PIO_STORE|UDI_PIO_SCRATCH|UDI_PIO_R1, UDI_PIO_1BYTE, UDI_PIO_R0},
+ {UDI_PIO_END_IMM, UDI_PIO_2BYTE, 0},
+ // 2: Overrun
+ {UDI_PIO_LABEL, 0, 2},
+ // 3: Overrun irqs
+ {UDI_PIO_LABEL, 0, 3},
+ {UDI_PIO_END_IMM, UDI_PIO_2BYTE, 0},
+};
+
+struct {
+ udi_pio_trans_t *trans_list;
+ udi_ubit16_t list_length;
+ udi_ubit16_t pio_attributes;
+} ne2k_pio_ops[] = {
+ {ne2k_pio_reset, ARRAY_SIZEOF(ne2k_pio_reset), 0},
+ {ne2k_pio_enable, ARRAY_SIZEOF(ne2k_pio_enable), 0},
+ {ne2k_pio_rx, ARRAY_SIZEOF(ne2k_pio_rx), 0},
+ {ne2k_pio_irqack, ARRAY_SIZEOF(ne2k_pio_irqack), 0},
+};
+const int NE2K_NUM_PIO_OPS = ARRAY_SIZEOF(ne2k_pio_ops);
+enum {
+ NE2K_PIO_RESET,
+ NE2K_PIO_ENABLE,
+ NE2K_PIO_RX,
+ NE2K_PIO_IRQACK,
+};
+/*
+ * UDI Ne2000 NIC Driver
+ * By John Hodge (thePowersGang)
+ *
+ * ne2000_rx.c
+ * - Receive Code
+ */
+#include <udi.h>
+#include <udi_nic.h>
+#include "ne2000_common.h"
+
+// === CODE ===
+void ne2k_intr__rx_ok(udi_cb_t *gcb)
+{
+
+}
+
# Source-only udiprops
source_files ne2000_core.c ne2000_rx.c ne2000_tx.c
-compile_options