1 #include <geekos/ne2k.h>
2 #include <geekos/debug.h>
4 #include <geekos/irq.h>
5 #include <geekos/malloc.h>
8 #define TX_START_BUFF 0x40
9 #define RX_START_BUFF 0x4c
12 uint_t next = (RX_START_BUFF << 8);
13 static uint_t received = 0;
14 static uint_t send_done = 1;
16 static void Dump_Registers()
19 PrintBoth("Dumping NIC registers for page %x...\n", (In_Byte(NE2K_CR) & 0xc0) >> 6);
21 for(i = 0; i <= 0x0f; i += 0x01) {
22 data = In_Byte(NE2K_BASE_ADDR+i);
23 PrintBoth("\t%x: %x\n", NE2K_BASE_ADDR + i, data);
27 static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
30 PrintBoth("NIC Interrupt Occured!\n");
31 uchar_t isr_content = In_Byte(NE2K_ISR);
32 // Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts */
34 PrintBoth("Contents of ISR: %x\n", isr_content);
36 if(isr_content & 0x01) /* A packet has been received. */
40 Out_Byte(NE2K_CR, 0x4a);
41 current = In_Byte(NE2K_CURR);
42 Out_Byte(NE2K_CR, 0x0a);
44 Out_Byte(NE2K_ISR, 0x01);
45 /* If BNRY and CURR aren't equal, more than one packet has been received. */
46 }while (current > In_Byte(NE2K_BNRY));
50 if(isr_content & 0x02) /* A packet has been successfully transmitted. */
53 Out_Byte(NE2K_ISR, 0x02);
55 Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts. */
60 PrintBoth("Initializing network card...\n");
61 Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f)); /* Reset? */
63 struct NE2K_REGS* regs = Malloc(sizeof(struct NE2K_REGS));
64 struct _CR * cr = (struct _CR *)&(regs->cr);
65 struct _RCR * rcr = (struct _RCR*)&(regs->rcr);
66 struct _IMR * imr = (struct _IMR *)&(regs->imr);
69 regs->dcr = 0x49; /* Word-wide DMA transfer. */
70 regs->isr = 0xff; /* Clear all interrupts. */
71 regs->rcr = 0x20; /* Accept packets shorter than 64 bytes. */
72 regs->tcr = 0x02; /* Internal loopback mode. */
74 Out_Byte(NE2K_CR, regs->cr);
75 Out_Byte(NE2K_DCR, regs->dcr);
76 Out_Byte(NE2K_ISR, regs->isr);
77 Out_Byte(NE2K_RCR, regs->rcr);
78 Out_Byte(NE2K_TCR, regs->tcr);
79 Out_Byte(NE2K_IMR, regs->imr);
81 /* Remote byte count registers. */
82 Out_Byte(NE2K_RBCR0, 0x00);
83 Out_Byte(NE2K_RBCR1, 0x00);
84 /* Remote start address registers. */
85 Out_Byte(NE2K_RSAR0, 0x00);
86 Out_Byte(NE2K_RSAR1, 0x00);
88 Out_Byte(NE2K_TPSR, TX_START_BUFF); /* Transmit page start register */
89 Out_Byte(NE2K_PSTART, RX_START_BUFF); /* Page start register */
90 // Out_Byte(NE2K_BNRY, 0x59); /* Boundary register */
91 Out_Byte(NE2K_PSTOP, 0x80); /* Page stop register */
93 cr->ps = 0x01; /* Switch to reg page 1. */
94 Out_Byte(NE2K_CR, regs->cr);
95 /* Current page register: points to first free page that can be used for packet reception. */
96 Out_Byte(NE2K_CURR, RX_START_BUFF);
97 cr->ps = 0x00; /* Switch to page 0 */
99 Out_Byte(NE2K_CR, regs->cr);
100 Out_Byte(NE2K_BNRY, RX_START_BUFF);
102 Out_Byte(NE2K_ISR, regs->isr);
104 /* Interrupt mask register: setting a bit to 1 enables the
105 corresponding interrupt in ISR. */
112 Out_Byte(NE2K_IMR, regs->imr);
114 cr->ps = 0x01; /* Switch to reg page 1 */
115 Out_Byte(NE2K_CR, regs->cr);
117 /* Set the physical address of the card to 52:54:00:12:34:58 */
118 Out_Byte(NE2K_CR+0x01, 0x52);
119 Out_Byte(NE2K_CR+0x02, 0x54);
120 Out_Byte(NE2K_CR+0x03, 0x00);
121 Out_Byte(NE2K_CR+0x04, 0x12);
122 Out_Byte(NE2K_CR+0x05, 0x34);
123 Out_Byte(NE2K_CR+0x06, 0x58);
125 /* Set the multicast address registr to all 1s; accepts all multicast packets */
127 for(i = 0x08; i <= 0x0f; i++) {
128 Out_Byte(NE2K_CR+i, 0xff);
131 regs->cr = 0x21; //set CR to start value
132 Out_Byte(NE2K_CR, regs->cr);
135 Out_Byte(NE2K_TCR, regs->tcr);
141 rcr->pro = 0x1; /* Promiscuous mode: accept all packets. */
143 Out_Byte(NE2K_RCR, regs->rcr);
145 cr->sta = 0x1; // toggle start bit
147 Out_Byte(NE2K_CR, regs->cr);
152 Out_Byte(NE2K_CR, regs->cr);
156 Out_Byte(NE2K_CR, regs->cr);
160 Out_Byte(NE2K_CR, regs->cr);
163 // Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f));
165 Install_IRQ(NE2K_IRQ, NE2K_Interrupt_Handler);
166 Enable_IRQ(NE2K_IRQ);
168 for(i = 0; i < 2; i++)
171 PrintBoth("Transmitting a packet\n");
175 uchar_t src_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x58 };
176 uchar_t dest_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 };
179 uchar_t *data = Malloc(size);
180 data = "This is a 64-byte string that will be used to test transmission.";
182 for(i = 0; i < 4; i++) {
183 NE2K_Send(regs, src_addr, dest_addr, 0x01, data, size);
191 /* Assumes src and dest are arrays of 6 characters. */
192 int NE2K_Send(struct NE2K_REGS *regs, uchar_t src[], uchar_t dest[], uint_t type, uchar_t *data, uint_t size)
194 struct _CR * cr = (struct _CR*)&(regs->cr);
195 uint_t packet_size = size + 16;
197 cr->stp = 0x0; //toggle start on
199 Out_Byte(NE2K_CR, regs->cr);
201 // Read-before-write bug fix?
202 Out_Byte(NE2K_RBCR0, 0x42);
203 Out_Byte(NE2K_RBCR1, 0x00);
204 Out_Byte(NE2K_RSAR0, 0x42);
205 Out_Byte(NE2K_RSAR1, 0x00);
207 cr->rd = 0x01; // set remote DMA to 'remote read'
208 Out_Byte(NE2K_CR, regs->cr);
210 regs->isr = 0x40; // clear and set Remote DMA high
211 Out_Byte(NE2K_ISR, regs->isr);
213 /* Set remote byte count registers */
214 Out_Byte(NE2K_RBCR0, packet_size & 0xff);
215 Out_Byte(NE2K_RBCR1, (packet_size >> 8) & 0xff);
217 /* Set transmit byte count registers. */
218 Out_Byte(NE2K_TBCR0, packet_size & 0xff);
219 Out_Byte(NE2K_TBCR1, (packet_size >> 8) & 0xff);
221 Out_Byte(NE2K_RSAR0, 0x00);
222 Out_Byte(NE2K_RSAR1, TX_START_BUFF);
225 Out_Byte(NE2K_CR, regs->cr);
227 /* Destination Address */
228 Out_Word(NE2K_CR + 0x10, (dest[1] << 8) | dest[0]);
229 Out_Word(NE2K_CR + 0x10, (dest[3] << 8) | dest[2]);
230 Out_Word(NE2K_CR + 0x10, (dest[5] << 8) | dest[4]);
233 Out_Word(NE2K_CR + 0x10, (src[1] << 8) | src[0]);
234 Out_Word(NE2K_CR + 0x10, (src[3] << 8) | src[2]);
235 Out_Word(NE2K_CR + 0x10, (src[5] << 8) | src[4]);
238 Out_Word(NE2K_CR + 0x10, packet_size);
241 for(i = 0; i < size; i += 2) {
242 Out_Word(NE2K_CR + 0x10, (*(data + i + 1) << 8) | *(data + i));
248 int NE2K_Transmit(struct NE2K_REGS *regs)
253 struct _CR * cr = (struct _CR*)&(regs->cr);
254 uint_t packet_size = 80;
256 cr->stp = 0x0; //toggle start on
258 Out_Byte(NE2K_CR, regs->cr);
260 // Read-before-write bug fix?
261 Out_Byte(NE2K_RBCR0, 0x42);
262 Out_Byte(NE2K_RBCR1, 0x00);
263 Out_Byte(NE2K_RSAR0, 0x42);
264 Out_Byte(NE2K_RSAR1, 0x00);
266 cr->rd = 0x01; // set remote DMA to 'remote read'
267 Out_Byte(NE2K_CR, regs->cr);
269 regs->isr = 0x40; // clear and set Remote DMA high
270 Out_Byte(NE2K_ISR, regs->isr);
272 Out_Byte(NE2K_RBCR0, packet_size);
273 Out_Byte(NE2K_RBCR1, 0x00);
275 Out_Byte(NE2K_TBCR0, packet_size);
276 Out_Byte(NE2K_TBCR1, 0x00);
278 Out_Byte(NE2K_RSAR0, 0x00);
279 Out_Byte(NE2K_RSAR1, 0x40);
282 Out_Byte(NE2K_CR, regs->cr);
284 /* Begin pushing the packet into the dataport (located at 0x10 from the base address) */
285 /* Destination address = 52:54:00:12:34:56 */
286 Out_Word(NE2K_CR+0x10, 0x5452);
287 Out_Word(NE2K_CR+0x10, 0x1200);
288 Out_Word(NE2K_CR+0x10, 0x5634);
290 /* Source address = 52:54:00:12:34:58 */
291 Out_Word(NE2K_CR+0x10, 0x5452);
292 Out_Word(NE2K_CR+0x10, 0x1200);
293 Out_Word(NE2K_CR+0x10, 0x5834);
295 /* Type length and data; currently random data */
298 for(i = 1; i <= packet_size/2-12; i++, n+=2) {
299 //Out_Word(NE2K_CR+0x10, 0x0f0b);
300 Out_Word(NE2K_CR+0x10, (n<<8) | (n+1));
304 //Out_Byte(NE2K_ISR, regs->isr); /* Do we need this here? */
311 PrintBoth("Packet Received\n");
313 Out_Byte(NE2K_CR, 0x22);
315 Out_Byte(NE2K_RBCR1, 0x00);
316 // Out_Byte(NE2K_RBCR0, 0x60);
318 // Out_Byte(NE2K_RSAR0, 0x42);
319 Out_Byte(NE2K_RSAR1, next >> 8);
320 Out_Byte(NE2K_RSAR0, next & 0xff);
321 Out_Byte(NE2K_CR, 0x0a);
324 * A four byte header is added to the beginning of each received packet.
325 * The first byte is the location of the next packet in the ring buffer.
326 * The second byte is the receive status code.
327 * The third and fourth bytes are the size of the packet.
332 PrintBoth("\nPacket data:\n\t");
334 data = In_Word(NE2K_CR + 0x10);
335 PrintBoth("%x ", data);
337 /* Get the location of the next packet */
338 next = data & 0xff00;
340 uint_t packet_size = In_Word(NE2K_CR + 0x10) - 4;
341 Out_Byte(NE2K_RBCR0, packet_size & 0xff);
342 Out_Byte(NE2K_RBCR1, (packet_size>>8) & 0xff);
345 PrintBoth("packetsize = %x\n\t", packet_size);
348 /* Copy the received packet over from the ring buffer. */
349 for(i = 0; i < packet_size; i+=2) {
350 data = In_Word(NE2K_CR + 0x10);
351 PrintBoth("%x ", data);
354 PrintBoth("BNRY = %x\n", In_Byte(NE2K_BNRY));
355 Out_Byte(NE2K_CR, 0x4a);
356 PrintBoth("CURR = %x\n", In_Byte(NE2K_CURR));
357 Out_Byte(NE2K_CR, 0x0a);
364 //Out_Byte(NE2K_RBCR0, (In_Byte(NE2K_RBCR0))-2);
365 //Out_Byte(NE2K_RSAR0, (In_Byte(NE2K_RSAR0))+2);
367 PrintBoth("\n%d packets have been received", ++received);
370 Out_Byte(NE2K_ISR, 0x40);
372 /* The BNRY register stores the location of the first packet that hasn't been read yet */
373 Out_Byte(NE2K_BNRY, next >> 8);