#include <geekos/io.h>
#include <geekos/irq.h>
#include <geekos/malloc.h>
+#include <geekos/string.h>
+#include <uip/uip.h>
+#include <uip/uip_arp.h>
+#define DEBUG 1
+#define TX_START_BUFF 0x40
+#define RX_START_BUFF 0x4c
+#define RX_END_BUFF 0x80
+
+static uint_t next = (RX_START_BUFF << 8);
static uint_t received = 0;
+static uint_t send_done = 1;
-struct _CR { //COMMAND REG
- uint_t stp: 1; //STOP- software reset
- uint_t sta: 1; //START- activates NIC
- uint_t txp: 1; //TRANSMIT- set to send
- uint_t rd: 3; //REMOTE DMA
- uint_t ps: 2; //PAGE SELECT
-};
-
-struct _ISR{ //INTERRUPT STATUS REG
- uint_t prx: 1; //PACKET RECIEVED
- uint_t ptx: 1; //PACKET TRANSMITTED
- uint_t rxe: 1; //TRANSMIT ERROR
- uint_t txe: 1; //RECEIVE ERROR
- uint_t ovw: 1; //OVERWRITE WARNING
- uint_t cnt: 1; //COUNTER OVERFLOW
- uint_t rdc: 1; //REMOTE DMA COMPLETE
- uint_t rst: 1; //RESET STATUS
-};
-
-struct _IMR { //INTERRUPT MASK REG
- uint_t prxe: 1; //PACKET RX INTRPT
- uint_t ptxe: 1; //PACKET TX INTRPT
- uint_t rxee: 1; //RX ERROR INTRPT
- uint_t txee: 1; //TX ERROR INTRPt
- uint_t ovwe: 1; //OVERWRITE WARNING INTRPT
- uint_t cnte: 1; //COUNTER OVERFLOW INTRPT
- uint_t rdce: 1; //DMA COMLETE INTRPT
- uint_t rsvd: 1;
-};
-
-struct _DCR { //DATA CONFIG REGISTER
- uint_t wts: 1; //WORD TRANSFER SELECT
- uint_t bos: 1; //BYTE ORDER SELECT
- uint_t las: 1; //LONG ADDR SELECT
- uint_t ls: 1; //LOOPBACK SELECT
- uint_t arm: 1; //AUTO-INITIALIZE REMOTE
- uint_t ft: 2; //FIFO THRESH SELECT
-};
-
-struct _TCR { //TX CONFIG REGISTER
- uint_t crc: 1; //INHIBIT CRC
- uint_t lb: 2; //ENCODED LOOPBACK
- uint_t atd: 1; //AUTO TRANSMIT
- uint_t ofst: 1; //COLLISION OFFSET ENABLE
- uint_t rsvd: 3;
-};
-
-struct _TSR {
- uint_t ptx: 1; //PACKET TX
- uint_t rsvd: 1;
- uint_t col: 1; //TX COLLIDED
- uint_t abt: 1; //TX ABORTED
- uint_t crs: 1; //CARRIER SENSE LOST
- uint_t fu: 1; //FIFO UNDERRUN
- uint_t cdh: 1; //CD HEARTBEAT
- uint_t owc: 1; //OUT OF WINDOW COLLISION
-};
-
-struct _RCR { //RECEIVE CONFIGURATION REGISTER
- uint_t sep: 1; //SAVE ERRORED PACKETS
- uint_t ar: 1; //ACCEPT RUNT PACKETS
- uint_t ab: 1; //ACCEPT BROADCAST
- uint_t am: 1; //ACCEPT MULTICAST
- uint_t pro: 1; //PROMISCUOUS PHYSICAL
- uint_t mon: 1; //MONITOR MODE
- uint_t rsvd: 2;
-};
-
-struct _RSR { //RECEIVE STATUS REG
- uint_t prx: 1; //PACKET RX INTACT
- uint_t crc: 1; //CRC ERROR
- uint_t fae: 1; //FRAME ALIGNMENT ERROR
- uint_t fo: 1; //FIFO OVERRUN
- uint_t mpa: 1; //MISSED PACKET
- uint_t phy: 1; //PHYSICAL/MULTICAST ADDR
- uint_t dis: 1; //RX DISABLED
- uint_t dfr: 1; //DEFERRING
-};
+struct NE2K_REGS* regs;
+struct callback {
+ int (*packet_received)(struct NE2K_Packet_Info *info, uchar_t *packet);
+} callbacks;
+#if DEBUG
static void Dump_Registers()
{
uint_t data;
-
PrintBoth("Dumping NIC registers for page %x...\n", (In_Byte(NE2K_CR) & 0xc0) >> 6);
uint_t i = 0;
for(i = 0; i <= 0x0f; i += 0x01) {
PrintBoth("\t%x: %x\n", NE2K_BASE_ADDR + i, data);
}
}
+#endif
static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
{
+
Begin_IRQ(state);
PrintBoth("NIC Interrupt Occured!\n");
- uint_t isr_content = In_Byte(NE2K_ISR);
+ uchar_t isr_content = In_Byte(NE2K_ISR);
+
PrintBoth("Contents of ISR: %x\n", isr_content);
- if(In_Byte(NE2K_ISR) & 0x01)
- NE2K_Receive();
- Out_Byte(NE2K_ISR, 0xff);
+ if(isr_content & 0x01) /* A packet has been received. */
+ {
+ uchar_t current;
+ Out_Byte(NE2K_CR, 0x4a); /* Page 1 */
+ current = In_Byte(NE2K_CURR);
+ Out_Byte(NE2K_CR, 0x0a); /* Page 0 */
+ NE2K_Receive();
+
+ /* When CURR equals BNRY, all packets in the receive ring buffer have been read, and
+ the packet received bit in the interrupt status register can be cleared. */
+ if(current == In_Byte(NE2K_BNRY))
+ Out_Byte(NE2K_ISR, 0x01);
+ }
+
End_IRQ(state);
-}
+ if(isr_content & 0x02) /* A packet has been successfully transmitted. */
+ {
+ send_done = 1;
+ Out_Byte(NE2K_ISR, 0x02);
+ }
+ //Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts. */
+}
-int Init_Ne2k()
+int Init_Ne2k(int (*rcvd_fn)(struct NE2K_Packet_Info *info, uchar_t *packet))
{
-
-uint_t CR_START_VAL = 0x21;
-static const uint_t DCR_START_VAL = 0x49;
-static const uint_t ISR_START_VAL = 0xff;
-static const uint_t RCR_START_VAL = 0x20;
-static const uint_t TCR_START_VAL = 0x02;
-//static const uint_t IMR_START_VAL = 0x00;
-PrintBoth("location Startval first = %x\n", &CR_START_VAL);
+ callbacks.packet_received = rcvd_fn;
PrintBoth("Initializing network card...\n");
-
- struct NE2K_REGS* regs = Malloc(sizeof(struct NE2K_REGS));
-
- regs->cr = (struct _CR*)&CR_START_VAL;
- regs->dcr = (struct _DCR*)&DCR_START_VAL;
- regs->isr = (struct _ISR*)&ISR_START_VAL;
- regs->rcr = (struct _RCR*)&RCR_START_VAL;
- regs->tcr = (struct _TCR*)&TCR_START_VAL;
-
- Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
- Out_Byte(NE2K_DCR, *(uint_t *)regs->dcr);
- Out_Byte(NE2K_ISR, *(uint_t *)regs->isr);
- Out_Byte(NE2K_RCR, *(uint_t *)regs->rcr);
- Out_Byte(NE2K_TCR, *(uint_t *)regs->tcr);
- Out_Byte(NE2K_IMR, *(uint_t *)regs->imr);
+ Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f)); /* Reset */
+
+ regs = Malloc(sizeof(struct NE2K_REGS));
+ struct _CR * cr = (struct _CR *)&(regs->cr);
+ struct _RCR * rcr = (struct _RCR*)&(regs->rcr);
+ struct _IMR * imr = (struct _IMR *)&(regs->imr);
+
+ regs->cr = 0x21;
+ regs->dcr = 0x49; /* Word-wide DMA transfer. */
+ regs->isr = 0xff; /* Clear all interrupts. */
+ regs->rcr = 0x20; /* Accept packets shorter than 64 bytes. */
+ regs->tcr = 0x02; /* Internal loopback mode. */
+
+ Out_Byte(NE2K_CR, regs->cr);
+ Out_Byte(NE2K_DCR, regs->dcr);
+ Out_Byte(NE2K_ISR, regs->isr);
+ Out_Byte(NE2K_RCR, regs->rcr);
+ Out_Byte(NE2K_TCR, regs->tcr);
+ Out_Byte(NE2K_IMR, regs->imr);
+
+ /* Remote byte count registers. */
Out_Byte(NE2K_RBCR0, 0x00);
Out_Byte(NE2K_RBCR1, 0x00);
+ /* Remote start address registers. */
Out_Byte(NE2K_RSAR0, 0x00);
Out_Byte(NE2K_RSAR1, 0x00);
- Out_Byte(NE2K_TPSR, 0x40); // Set TPSR
- Out_Byte(NE2K_PSTART, 0x42); // Set PSTART
- Out_Byte(NE2K_BNRY, 0x59); // Set BNRY
- Out_Byte(NE2K_PSTOP, 0x60); // Set PSTOP
-
- Out_Byte(NE2K_ISR, *(uint_t *)regs->isr);
-
- regs->imr->prxe = 0x1;
- regs->imr->ptxe = 0x1;
- regs->imr->rxee = 0x1;
- regs->imr->txee = 0x1;
- regs->imr->ovwe = 0x1;
- regs->imr->cnte = 0x1;
- Out_Byte(NE2K_IMR, *(uint_t *)regs->imr);
-
- regs->cr->ps = 0x01; //switch to reg page 1
- Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
-
-PrintBoth("Startval 2= %x\n", CR_START_VAL);
-
-PrintBoth("regs locat = %x\n", (uint_t *)regs->cr);
-PrintBoth("regs = %x\n", *(uint_t *)regs->cr);
+ Out_Byte(NE2K_TPSR, TX_START_BUFF); /* Transmit page start register */
+ Out_Byte(NE2K_PSTART, RX_START_BUFF); /* Page start register */
+ Out_Byte(NE2K_PSTOP, RX_END_BUFF); /* Page stop register */
+ Out_Byte(NE2K_BNRY, RX_START_BUFF); /* Boundary register */
+
+ cr->ps = 0x01; /* Switch to reg page 1. */
+ Out_Byte(NE2K_CR, regs->cr);
+ /* Current page register: points to first free page that can be used for packet reception. */
+ Out_Byte(NE2K_CURR, RX_START_BUFF);
+ cr->ps = 0x00; /* Switch to page 0 */
+
+ Out_Byte(NE2K_CR, regs->cr);
+ Out_Byte(NE2K_ISR, regs->isr);
+
+ /* Interrupt mask register: setting a bit to 1 enables the
+ corresponding interrupt in ISR. */
+ imr->prxe = 0x1;
+ imr->ptxe = 0x1;
+ imr->rxee = 0x1;
+ imr->txee = 0x1;
+ imr->ovwe = 0x1;
+ imr->cnte = 0x1;
+ Out_Byte(NE2K_IMR, regs->imr);
+
+ cr->ps = 0x01; /* Switch to reg page 1 */
+ Out_Byte(NE2K_CR, regs->cr);
/* Set the physical address of the card to 52:54:00:12:34:58 */
Out_Byte(NE2K_CR+0x01, 0x52);
Out_Byte(NE2K_CR+0x05, 0x34);
Out_Byte(NE2K_CR+0x06, 0x58);
+ /* Set the multicast address register to all 1s; accepts all multicast packets */
uint_t i;
for(i = 0x08; i <= 0x0f; i++) {
Out_Byte(NE2K_CR+i, 0xff);
}
- *(uint_t *)regs->cr = 0x21; //set CR to start value
- Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
-
-PrintBoth("startval 3 = %x\n", CR_START_VAL);
-PrintBoth("location Startval 2 = %x\n", &CR_START_VAL);
-PrintBoth("regs = %x\n", (uint_t *)regs->cr);
+ regs->cr = 0x21; //set CR to start value
+ Out_Byte(NE2K_CR, regs->cr);
regs->tcr = 0x00;
- Out_Byte(NE2K_TCR, *(uint_t *)regs->tcr);
-
- regs->rcr->sep = 0x1;
- regs->rcr->ar = 0x1;
- regs->rcr->ab = 0x1;
- regs->rcr->am = 0x1;
- regs->rcr->pro = 0x1; //promiscuous mode, accept all packets
- regs->rcr->mon = 0x0;
- Out_Byte(NE2K_RCR, *(uint_t *)regs->rcr);
-
- regs->cr->sta = 0x1; //toggle start bit
- regs->cr->stp = 0x0;
- Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
-
+ Out_Byte(NE2K_TCR, regs->tcr);
+
+ rcr->sep = 0x1;
+ rcr->ar = 0x1;
+ rcr->ab = 0x1;
+ rcr->am = 0x1;
+ rcr->pro = 0x1; /* Promiscuous mode: accept all packets. */
+ rcr->mon = 0x0;
+ Out_Byte(NE2K_RCR, regs->rcr);
+
+ cr->sta = 0x1; // toggle start bit
+ cr->stp = 0x0;
+ Out_Byte(NE2K_CR, regs->cr);
+
+#if DEBUG
Dump_Registers();
- Out_Byte(NE2K_CR, (*(uint_t *)regs->cr & 0x3f) | NE2K_PAGE1);
+ cr->ps = 0x01;
+ Out_Byte(NE2K_CR, regs->cr);
Dump_Registers();
- Out_Byte(NE2K_CR, (*(uint_t *)regs->cr & 0x3f) | NE2K_PAGE2);
+ cr->ps = 0x02;
+ Out_Byte(NE2K_CR, regs->cr);
Dump_Registers();
- // Reset?
- Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f));
+ cr->ps = 0x00;
+ Out_Byte(NE2K_CR, regs->cr);
+#endif
Install_IRQ(NE2K_IRQ, NE2K_Interrupt_Handler);
Enable_IRQ(NE2K_IRQ);
-
- for(i = 0; i < 4; i++)
+#if 0
+ for(i = 0; i < 0; i++)
{
NE2K_Transmit(regs);
PrintBoth("Transmitting a packet\n");
}
+#endif
+/*
+ uchar_t src_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x58 };
+ uchar_t dest_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 };
+
+ uint_t size = 64;
+ uchar_t *data = Malloc(size);
+ data = "This is a 64-byte string that will be used to test transmission.";
+
+ for(i = 0; i < 0; i++) {
+ NE2K_Send(regs, src_addr, dest_addr, 0x01, data, size);
+ }
+*/
+ //Free(data); // Why does this crash?
return 0;
}
-int NE2K_Transmit(struct NE2K_REGS *regs)
+
+/*
+ * This function is called when there is data in uip_buf that's ready to be sent.
+ * uip_arp_out() is used to translate the destination IP address to a MAC address.
+ * If the corresponding MAC address isn't in the cache, the packet is replaced with
+ * an ARP packet, which is sent out instead. The original packet will need to be
+ * retransmitted at some point in the future.
+ */
+int NE2K_Transmit(uint_t size)
+{
+ uip_arp_out();
+ uchar_t *data;
+ data = Malloc(size);
+
+ /* Based on example code from the uIP documentation... */
+ if(size <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
+ memcpy(data, &uip_buf[0], size);
+ } else {
+ memcpy(data, &uip_buf[0], UIP_LLH_LEN + UIP_TCPIP_HLEN);
+ memcpy(data + UIP_LLH_LEN + UIP_TCPIP_HLEN, uip_appdata, size - UIP_TCPIP_HLEN - UIP_LLH_LEN);
+ }
+
+ /* Manually copy in the source MAC address for now. */
+ uchar_t src_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x58 };
+ memcpy(data + 6, src_addr, 6);
+ if(*(data+12) != 0x08 || *(data+13) != 0x06)
+ {
+ /* This is not an ARP packet. Fill in te size of the packet manually. */
+ *(data+12) = size & 0xff;
+ *(data+13) = (size >> 8) & 0xff;
+ }
+
+ NE2K_Send_Packet(data, size);
+ Free(data);
+ return 0;
+}
+
+int NE2K_Send_Packet(uchar_t *packet, uint_t size)
{
- uint_t packet_size = 80;
- *(uint_t *)regs->cr = 0x21;
- regs->cr->stp = 0x0; //toggle start on
- regs->cr->sta = 0x1;
- Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
+ struct _CR * cr = (struct _CR*)&(regs->cr);
+ regs->cr = 0x21; /* Turn off remote DMA, stop command */
+ cr->stp = 0x0; /* toggle start on */
+ cr->sta = 0x1;
+ Out_Byte(NE2K_CR, regs->cr);
// Read-before-write bug fix?
Out_Byte(NE2K_RBCR0, 0x42);
Out_Byte(NE2K_RSAR0, 0x42);
Out_Byte(NE2K_RSAR1, 0x00);
- regs->cr->rd = 0x01; //set remote DMA to 'remote read'
- Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
+ cr->rd = 0x01; /* set remote DMA to 'remote read' */
+ Out_Byte(NE2K_CR, regs->cr);
- *(uint_t*)regs->isr = 0x40; //clear and set Remote DMA high
- Out_Byte(NE2K_ISR, *(uint_t *)regs->isr);
+ regs->isr = 0x40; /* clear 'remote DMA complete' interrupt */
+ Out_Byte(NE2K_ISR, regs->isr);
- Out_Byte(NE2K_RBCR0, packet_size);
- Out_Byte(NE2K_RBCR1, 0x00);
+ /* Set remote byte count registers */
+ Out_Byte(NE2K_RBCR0, size & 0xff);
+ Out_Byte(NE2K_RBCR1, (size >> 8) & 0xff);
- Out_Byte(NE2K_TBCR0, packet_size);
- Out_Byte(NE2K_TBCR1, 0x00);
+ /* Set transmit byte count registers. */
+ Out_Byte(NE2K_TBCR0, size & 0xff);
+ Out_Byte(NE2K_TBCR1, (size >> 8) & 0xff);
+ /* Set remote start address registers to the first page of the transmit ring buffer. */
Out_Byte(NE2K_RSAR0, 0x00);
- Out_Byte(NE2K_RSAR1, 0x40);
+ Out_Byte(NE2K_RSAR1, TX_START_BUFF);
+
+ cr->rd = 0x02; /* Set remote DMA to 'remote write' */
+ Out_Byte(NE2K_CR, regs->cr);
+
+ /* Push the packet data to into the dataport */
+ uint_t i;
+ for(i = 0; i < size; i += 2) {
+ Out_Word(NE2K_CR + 0x10, (*(packet + i + 1) << 8) | *(packet + i));
+ }
- *(uint_t*)regs->cr = 0x16;
- Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
+ cr->txp = 0x1; /* Start transmission */
+ Out_Byte(NE2K_CR, regs->cr);
+
+ return 0;
+}
+
+#if 1
+/* Assumes src and dest are arrays of 6 characters. */
+int NE2K_Send(uchar_t src[], uchar_t dest[], uint_t type, uchar_t *data, uint_t size)
+{
+ struct _CR * cr = (struct _CR*)&(regs->cr);
+ uint_t packet_size = size + 16;
+ regs->cr = 0x21; /* Turn off remote DMA, stop command */
+ cr->stp = 0x0; /* toggle start on */
+ cr->sta = 0x1;
+ Out_Byte(NE2K_CR, regs->cr);
- /* Begin pushing the packet into the dataport (located at 0x10 from the base address) */
- /* Destination address = 52:54:00:12:34:56 */
- Out_Word(NE2K_CR+0x10, 0x5452);
- Out_Word(NE2K_CR+0x10, 0x1200);
- Out_Word(NE2K_CR+0x10, 0x5634);
-
- /* Source address = 52:54:00:12:34:58 */
- Out_Word(NE2K_CR+0x10, 0x5452);
- Out_Word(NE2K_CR+0x10, 0x1200);
- Out_Word(NE2K_CR+0x10, 0x5834);
-
- /* Type length and data; currently random data */
+ // Read-before-write bug fix?
+ Out_Byte(NE2K_RBCR0, 0x42);
+ Out_Byte(NE2K_RBCR1, 0x00);
+ Out_Byte(NE2K_RSAR0, 0x42);
+ Out_Byte(NE2K_RSAR1, 0x00);
+
+ cr->rd = 0x01; /* set remote DMA to 'remote read' */
+ Out_Byte(NE2K_CR, regs->cr);
+
+ regs->isr = 0x40; /* clear 'remote DMA complete' interrupt */
+ Out_Byte(NE2K_ISR, regs->isr);
+
+ /* Set remote byte count registers */
+ Out_Byte(NE2K_RBCR0, packet_size & 0xff);
+ Out_Byte(NE2K_RBCR1, (packet_size >> 8) & 0xff);
+
+ /* Set transmit byte count registers. */
+ Out_Byte(NE2K_TBCR0, packet_size & 0xff);
+ Out_Byte(NE2K_TBCR1, (packet_size >> 8) & 0xff);
+
+ /* Set remote start address registers to the first page of the transmit ring buffer. */
+ Out_Byte(NE2K_RSAR0, 0x00);
+ Out_Byte(NE2K_RSAR1, TX_START_BUFF);
+
+ cr->rd = 0x02; /* Set remote DMA to 'remote write' */
+ Out_Byte(NE2K_CR, regs->cr);
+
+ /* Begin pushing the packet into the dataport (located at 0x10 from the base address). */
+ /* Destination Address */
+ Out_Word(NE2K_CR + 0x10, (dest[1] << 8) | dest[0]);
+ Out_Word(NE2K_CR + 0x10, (dest[3] << 8) | dest[2]);
+ Out_Word(NE2K_CR + 0x10, (dest[5] << 8) | dest[4]);
+
+ /* Source Address */
+ Out_Word(NE2K_CR + 0x10, (src[1] << 8) | src[0]);
+ Out_Word(NE2K_CR + 0x10, (src[3] << 8) | src[2]);
+ Out_Word(NE2K_CR + 0x10, (src[5] << 8) | src[4]);
+
+ /* Type */
+ Out_Word(NE2K_CR + 0x10, packet_size);
+
+ /* Packet data */
uint_t i;
- uint_t n = 0;
- for(i = 1; i <= packet_size/2-12; i++, n+=2) {
- //Out_Word(NE2K_CR+0x10, 0x0f0b);
- Out_Word(NE2K_CR+0x10, (n<<8) | (n+1));
+ for(i = 0; i < size; i += 2) {
+ Out_Word(NE2K_CR + 0x10, (*(data + i + 1) << 8) | *(data + i));
}
- Out_Byte(NE2K_ISR, 0x40);
+ cr->txp = 0x1; /* Start transmission */
+ Out_Byte(NE2K_CR, regs->cr);
return 0;
}
+#endif
int NE2K_Receive()
{
PrintBoth("Packet Received\n");
- uint_t packet_size = 80;
-
Out_Byte(NE2K_CR, 0x22);
- Out_Byte(NE2K_RBCR0, packet_size);
- Out_Byte(NE2K_RBCR1, 0x00);
-// Out_Byte(NE2K_RSAR0, 0x42);
- Out_Byte(NE2K_RSAR0, 0x4c);
- Out_Byte(NE2K_RSAR1, 0x00);
+ /* Set RSAR to the start address of the received packet. */
+ Out_Byte(NE2K_RSAR0, next & 0xff);
+ Out_Byte(NE2K_RSAR1, next >> 8);
Out_Byte(NE2K_CR, 0x0a);
+ /*
+ * A four byte header is added to the beginning of each received packet by the NIC.
+ * The first byte is the location of the next packet in the ring buffer.
+ * The second byte is the receive status code.
+ * The third and fourth bytes are the size of the packet.
+ */
+
uint_t i;
uint_t data;
+ data = In_Word(NE2K_CR + 0x10);
+
+#if DEBUG
PrintBoth("\nPacket data:\n\t");
+ PrintBoth("%x ", data);
+#endif
+
+ /* Get the location of the next packet */
+ next = data & 0xff00;
+
+ /* Retrieve the packet size from the header, and store it in RBCR. */
+ uint_t packet_size = In_Word(NE2K_CR + 0x10) - 4;
+ uchar_t *packet = Malloc(packet_size);
+ Out_Byte(NE2K_RBCR0, packet_size & 0xff);
+ Out_Byte(NE2K_RBCR1, (packet_size>>8) & 0xff);
+
+#if DEBUG
+ PrintBoth("packetsize = %x\n\t", packet_size);
+#endif
+ /* Copy the received packet over from the ring buffer. */
for(i = 0; i < packet_size; i+=2) {
data = In_Word(NE2K_CR + 0x10);
- PrintBoth("%x ", data);
- if(!(i%10))
- PrintBoth("\n\t");
+ *(packet + i) = data & 0x00ff;
+ *(packet + i + 1) = (data & 0xff00) >> 8;
+#if 0
+ PrintBoth("BNRY = %x\n", In_Byte(NE2K_BNRY));
+ Out_Byte(NE2K_CR, 0x4a);
+ PrintBoth("CURR = %x\n", In_Byte(NE2K_CURR));
+ Out_Byte(NE2K_CR, 0x0a);
+#endif
}
+//Out_Byte(NE2K_RBCR0, (In_Byte(NE2K_RBCR0))-2);
+//Out_Byte(NE2K_RSAR0, (In_Byte(NE2K_RSAR0))+2);
+
PrintBoth("\n%d packets have been received", ++received);
PrintBoth("\n\n");
- Out_Byte(NE2K_ISR, 0x40);
+ Out_Byte(NE2K_ISR, 0x40); /* Clear the remote DMA complete interrupt. */
+
+ /* The BNRY register stores the location of the first packet that hasn't been read yet */
+ Out_Byte(NE2K_BNRY, next >> 8);
+
+ struct NE2K_Packet_Info *info = Malloc(sizeof(struct NE2K_Packet_Info));
+ info->size = packet_size;
+ info->status = 0;
+ memcpy(info->dest, packet, 6);
+ memcpy(info->src, packet + 6, 6);
+ callbacks.packet_received(info, packet);
return 0;
}
-//int NE2K_Ringbuff_Overflow(){
-
+