1 #include <geekos/ne2k.h>
2 #include <geekos/debug.h>
4 #include <geekos/irq.h>
5 #include <geekos/malloc.h>
6 #include <geekos/string.h>
9 #define TX_START_BUFF 0x40
10 #define RX_START_BUFF 0x4c
11 #define RX_END_BUFF 0x80
13 static uint_t next = (RX_START_BUFF << 8);
14 static uint_t received = 0;
15 static uint_t send_done = 1;
17 struct NE2K_REGS* regs;
20 int (*packet_received)(struct NE2K_Packet_Info *info, uchar_t *packet);
24 static void Dump_Registers()
27 PrintBoth("Dumping NIC registers for page %x...\n", (In_Byte(NE2K_CR) & 0xc0) >> 6);
29 for(i = 0; i <= 0x0f; i += 0x01) {
30 data = In_Byte(NE2K_BASE_ADDR+i);
31 PrintBoth("\t%x: %x\n", NE2K_BASE_ADDR + i, data);
36 static int NE2K_Transmit(struct NE2K_REGS *regs)
41 struct _CR * cr = (struct _CR*)&(regs->cr);
42 uint_t packet_size = 80;
44 cr->stp = 0x0; //toggle start on
46 Out_Byte(NE2K_CR, regs->cr);
48 // Read-before-write bug fix?
49 Out_Byte(NE2K_RBCR0, 0x42);
50 Out_Byte(NE2K_RBCR1, 0x00);
51 Out_Byte(NE2K_RSAR0, 0x42);
52 Out_Byte(NE2K_RSAR1, 0x00);
54 cr->rd = 0x01; // set remote DMA to 'remote read'
55 Out_Byte(NE2K_CR, regs->cr);
57 regs->isr = 0x40; // clear and set Remote DMA high
58 Out_Byte(NE2K_ISR, regs->isr);
60 Out_Byte(NE2K_RBCR0, packet_size);
61 Out_Byte(NE2K_RBCR1, 0x00);
63 Out_Byte(NE2K_TBCR0, packet_size);
64 Out_Byte(NE2K_TBCR1, 0x00);
66 Out_Byte(NE2K_RSAR0, 0x00);
67 Out_Byte(NE2K_RSAR1, 0x40);
70 Out_Byte(NE2K_CR, regs->cr);
72 /* Begin pushing the packet into the dataport (located at 0x10 from the base address) */
73 /* Destination address = 52:54:00:12:34:56 */
74 Out_Word(NE2K_CR+0x10, 0x5452);
75 Out_Word(NE2K_CR+0x10, 0x1200);
76 Out_Word(NE2K_CR+0x10, 0x5634);
78 /* Source address = 52:54:00:12:34:58 */
79 Out_Word(NE2K_CR+0x10, 0x5452);
80 Out_Word(NE2K_CR+0x10, 0x1200);
81 Out_Word(NE2K_CR+0x10, 0x5834);
83 /* Type length and data; currently random data */
86 for(i = 1; i <= packet_size/2-12; i++, n+=2) {
87 //Out_Word(NE2K_CR+0x10, 0x0f0b);
88 Out_Word(NE2K_CR+0x10, (n<<8) | (n+1));
92 //Out_Byte(NE2K_ISR, regs->isr); /* Do we need this here? */
97 static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
100 PrintBoth("NIC Interrupt Occured!\n");
101 uchar_t isr_content = In_Byte(NE2K_ISR);
103 PrintBoth("Contents of ISR: %x\n", isr_content);
105 if(isr_content & 0x01) /* A packet has been received. */
108 Out_Byte(NE2K_CR, 0x4a); /* Page 1 */
109 current = In_Byte(NE2K_CURR);
110 Out_Byte(NE2K_CR, 0x0a); /* Page 0 */
113 /* When CURR equals BNRY, all packets in the receive ring buffer have been read, and
114 the packet received bit in the interrupt status register can be cleared. */
115 if(current == In_Byte(NE2K_BNRY))
116 Out_Byte(NE2K_ISR, 0x01);
120 if(isr_content & 0x02) /* A packet has been successfully transmitted. */
123 Out_Byte(NE2K_ISR, 0x02);
126 //Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts. */
129 int Init_Ne2k(int (*rcvd_fn)(struct NE2K_Packet_Info *info, uchar_t *packet))
131 callbacks.packet_received = rcvd_fn;
133 PrintBoth("Initializing network card...\n");
134 Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f)); /* Reset */
136 regs = Malloc(sizeof(struct NE2K_REGS));
137 struct _CR * cr = (struct _CR *)&(regs->cr);
138 struct _RCR * rcr = (struct _RCR*)&(regs->rcr);
139 struct _IMR * imr = (struct _IMR *)&(regs->imr);
142 regs->dcr = 0x49; /* Word-wide DMA transfer. */
143 regs->isr = 0xff; /* Clear all interrupts. */
144 regs->rcr = 0x20; /* Accept packets shorter than 64 bytes. */
145 regs->tcr = 0x02; /* Internal loopback mode. */
147 Out_Byte(NE2K_CR, regs->cr);
148 Out_Byte(NE2K_DCR, regs->dcr);
149 Out_Byte(NE2K_ISR, regs->isr);
150 Out_Byte(NE2K_RCR, regs->rcr);
151 Out_Byte(NE2K_TCR, regs->tcr);
152 Out_Byte(NE2K_IMR, regs->imr);
154 /* Remote byte count registers. */
155 Out_Byte(NE2K_RBCR0, 0x00);
156 Out_Byte(NE2K_RBCR1, 0x00);
157 /* Remote start address registers. */
158 Out_Byte(NE2K_RSAR0, 0x00);
159 Out_Byte(NE2K_RSAR1, 0x00);
161 Out_Byte(NE2K_TPSR, TX_START_BUFF); /* Transmit page start register */
162 Out_Byte(NE2K_PSTART, RX_START_BUFF); /* Page start register */
163 Out_Byte(NE2K_PSTOP, RX_END_BUFF); /* Page stop register */
164 Out_Byte(NE2K_BNRY, RX_START_BUFF); /* Boundary register */
166 cr->ps = 0x01; /* Switch to reg page 1. */
167 Out_Byte(NE2K_CR, regs->cr);
168 /* Current page register: points to first free page that can be used for packet reception. */
169 Out_Byte(NE2K_CURR, RX_START_BUFF);
170 cr->ps = 0x00; /* Switch to page 0 */
172 Out_Byte(NE2K_CR, regs->cr);
173 Out_Byte(NE2K_ISR, regs->isr);
175 /* Interrupt mask register: setting a bit to 1 enables the
176 corresponding interrupt in ISR. */
183 Out_Byte(NE2K_IMR, regs->imr);
185 cr->ps = 0x01; /* Switch to reg page 1 */
186 Out_Byte(NE2K_CR, regs->cr);
188 /* Set the physical address of the card to 52:54:00:12:34:58 */
189 Out_Byte(NE2K_CR+0x01, 0x52);
190 Out_Byte(NE2K_CR+0x02, 0x54);
191 Out_Byte(NE2K_CR+0x03, 0x00);
192 Out_Byte(NE2K_CR+0x04, 0x12);
193 Out_Byte(NE2K_CR+0x05, 0x34);
194 Out_Byte(NE2K_CR+0x06, 0x58);
196 /* Set the multicast address register to all 1s; accepts all multicast packets */
198 for(i = 0x08; i <= 0x0f; i++) {
199 Out_Byte(NE2K_CR+i, 0xff);
202 regs->cr = 0x21; //set CR to start value
203 Out_Byte(NE2K_CR, regs->cr);
206 Out_Byte(NE2K_TCR, regs->tcr);
212 rcr->pro = 0x1; /* Promiscuous mode: accept all packets. */
214 Out_Byte(NE2K_RCR, regs->rcr);
216 cr->sta = 0x1; // toggle start bit
218 Out_Byte(NE2K_CR, regs->cr);
224 Out_Byte(NE2K_CR, regs->cr);
228 Out_Byte(NE2K_CR, regs->cr);
232 Out_Byte(NE2K_CR, regs->cr);
235 Install_IRQ(NE2K_IRQ, NE2K_Interrupt_Handler);
236 Enable_IRQ(NE2K_IRQ);
238 for(i = 0; i < 0; i++)
241 PrintBoth("Transmitting a packet\n");
245 uchar_t src_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x58 };
246 uchar_t dest_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 };
249 uchar_t *data = Malloc(size);
250 data = "This is a 64-byte string that will be used to test transmission.";
252 for(i = 0; i < 0; i++) {
253 NE2K_Send(regs, src_addr, dest_addr, 0x01, data, size);
256 //Free(data); // Why does this crash?
261 /* Assumes src and dest are arrays of 6 characters. */
262 int NE2K_Send(uchar_t *packet, uint_t size)
264 struct _CR * cr = (struct _CR*)&(regs->cr);
265 regs->cr = 0x21; /* Turn off remote DMA, stop command */
266 cr->stp = 0x0; /* toggle start on */
268 Out_Byte(NE2K_CR, regs->cr);
270 // Read-before-write bug fix?
271 Out_Byte(NE2K_RBCR0, 0x42);
272 Out_Byte(NE2K_RBCR1, 0x00);
273 Out_Byte(NE2K_RSAR0, 0x42);
274 Out_Byte(NE2K_RSAR1, 0x00);
276 cr->rd = 0x01; /* set remote DMA to 'remote read' */
277 Out_Byte(NE2K_CR, regs->cr);
279 regs->isr = 0x40; /* clear 'remote DMA complete' interrupt */
280 Out_Byte(NE2K_ISR, regs->isr);
282 /* Set remote byte count registers */
283 Out_Byte(NE2K_RBCR0, size & 0xff);
284 Out_Byte(NE2K_RBCR1, (size >> 8) & 0xff);
286 /* Set transmit byte count registers. */
287 Out_Byte(NE2K_TBCR0, size & 0xff);
288 Out_Byte(NE2K_TBCR1, (size >> 8) & 0xff);
290 /* Set remote start address registers to the first page of the transmit ring buffer. */
291 Out_Byte(NE2K_RSAR0, 0x00);
292 Out_Byte(NE2K_RSAR1, TX_START_BUFF);
294 cr->rd = 0x02; /* Set remote DMA to 'remote write' */
295 Out_Byte(NE2K_CR, regs->cr);
297 /* Push the packet data to into the dataport */
299 for(i = 0; i < size; i += 2) {
300 Out_Word(NE2K_CR + 0x10, (*(packet + i + 1) << 8) | *(packet + i));
303 cr->txp = 0x1; /* Start transmission */
304 Out_Byte(NE2K_CR, regs->cr);
310 /* Assumes src and dest are arrays of 6 characters. */
311 int NE2K_Send2(uchar_t src[], uchar_t dest[], uint_t type, uchar_t *data, uint_t size)
313 struct _CR * cr = (struct _CR*)&(regs->cr);
314 uint_t packet_size = size + 16;
315 regs->cr = 0x21; /* Turn off remote DMA, stop command */
316 cr->stp = 0x0; /* toggle start on */
318 Out_Byte(NE2K_CR, regs->cr);
320 // Read-before-write bug fix?
321 Out_Byte(NE2K_RBCR0, 0x42);
322 Out_Byte(NE2K_RBCR1, 0x00);
323 Out_Byte(NE2K_RSAR0, 0x42);
324 Out_Byte(NE2K_RSAR1, 0x00);
326 cr->rd = 0x01; /* set remote DMA to 'remote read' */
327 Out_Byte(NE2K_CR, regs->cr);
329 regs->isr = 0x40; /* clear 'remote DMA complete' interrupt */
330 Out_Byte(NE2K_ISR, regs->isr);
332 /* Set remote byte count registers */
333 Out_Byte(NE2K_RBCR0, packet_size & 0xff);
334 Out_Byte(NE2K_RBCR1, (packet_size >> 8) & 0xff);
336 /* Set transmit byte count registers. */
337 Out_Byte(NE2K_TBCR0, packet_size & 0xff);
338 Out_Byte(NE2K_TBCR1, (packet_size >> 8) & 0xff);
340 /* Set remote start address registers to the first page of the transmit ring buffer. */
341 Out_Byte(NE2K_RSAR0, 0x00);
342 Out_Byte(NE2K_RSAR1, TX_START_BUFF);
344 cr->rd = 0x02; /* Set remote DMA to 'remote write' */
345 Out_Byte(NE2K_CR, regs->cr);
347 /* Begin pushing the packet into the dataport (located at 0x10 from the base address). */
348 /* Destination Address */
349 Out_Word(NE2K_CR + 0x10, (dest[1] << 8) | dest[0]);
350 Out_Word(NE2K_CR + 0x10, (dest[3] << 8) | dest[2]);
351 Out_Word(NE2K_CR + 0x10, (dest[5] << 8) | dest[4]);
354 Out_Word(NE2K_CR + 0x10, (src[1] << 8) | src[0]);
355 Out_Word(NE2K_CR + 0x10, (src[3] << 8) | src[2]);
356 Out_Word(NE2K_CR + 0x10, (src[5] << 8) | src[4]);
359 Out_Word(NE2K_CR + 0x10, packet_size);
363 for(i = 0; i < size; i += 2) {
364 Out_Word(NE2K_CR + 0x10, (*(data + i + 1) << 8) | *(data + i));
367 cr->txp = 0x1; /* Start transmission */
368 Out_Byte(NE2K_CR, regs->cr);
376 PrintBoth("Packet Received\n");
378 Out_Byte(NE2K_CR, 0x22);
379 /* Set RSAR to the start address of the received packet. */
380 Out_Byte(NE2K_RSAR0, next & 0xff);
381 Out_Byte(NE2K_RSAR1, next >> 8);
382 Out_Byte(NE2K_CR, 0x0a);
385 * A four byte header is added to the beginning of each received packet by the NIC.
386 * The first byte is the location of the next packet in the ring buffer.
387 * The second byte is the receive status code.
388 * The third and fourth bytes are the size of the packet.
393 data = In_Word(NE2K_CR + 0x10);
396 PrintBoth("\nPacket data:\n\t");
397 PrintBoth("%x ", data);
400 /* Get the location of the next packet */
401 next = data & 0xff00;
403 /* Retrieve the packet size from the header, and store it in RBCR. */
404 uint_t packet_size = In_Word(NE2K_CR + 0x10) - 4;
405 uchar_t *packet = Malloc(packet_size);
406 Out_Byte(NE2K_RBCR0, packet_size & 0xff);
407 Out_Byte(NE2K_RBCR1, (packet_size>>8) & 0xff);
410 PrintBoth("packetsize = %x\n\t", packet_size);
413 /* Copy the received packet over from the ring buffer. */
414 for(i = 0; i < packet_size; i+=2) {
415 data = In_Word(NE2K_CR + 0x10);
416 *(packet + i) = data & 0x00ff;
417 *(packet + i + 1) = (data & 0xff00) >> 8;
419 PrintBoth("BNRY = %x\n", In_Byte(NE2K_BNRY));
420 Out_Byte(NE2K_CR, 0x4a);
421 PrintBoth("CURR = %x\n", In_Byte(NE2K_CURR));
422 Out_Byte(NE2K_CR, 0x0a);
426 //Out_Byte(NE2K_RBCR0, (In_Byte(NE2K_RBCR0))-2);
427 //Out_Byte(NE2K_RSAR0, (In_Byte(NE2K_RSAR0))+2);
429 PrintBoth("\n%d packets have been received", ++received);
432 Out_Byte(NE2K_ISR, 0x40); /* Clear the remote DMA complete interrupt. */
434 /* The BNRY register stores the location of the first packet that hasn't been read yet */
435 Out_Byte(NE2K_BNRY, next >> 8);
437 struct NE2K_Packet_Info *info = Malloc(sizeof(struct NE2K_Packet_Info));
438 info->size = packet_size;
440 memcpy(info->dest, packet, 6);
441 memcpy(info->src, packet + 6, 6);
442 callbacks.packet_received(info, packet);