d3c0903f7bb369313c85e5f1af23731ef9cb760e
[akaros.git] / kern / src / rl8168.c
1 #ifdef __DEPUTY__
2 #pragma nodeputy
3 #endif
4
5 #include <arch/mmu.h>
6 #include <arch/x86.h>
7 #include <arch/smp.h>
8 #include <arch/apic.h>
9
10 #include <ros/memlayout.h>
11
12 #include <atomic.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <rl8168.h>
16 #include <trap.h>
17 #include <kmalloc.h>
18
19 #include <pmap.h>
20
21 /* RealTek 8168d (8111d) NIC Driver
22  *
23  * Written by Paul Pearce.
24  *
25  * This is a really rough "driver". Really, its not a driver, just a kernel hack to give
26  * the kernel a way to receive and send packets. The basis of the init code is the OSDEV
27  * page on the 8169 chipset, which is a varient of this chipset (most 8169 drivers work 
28  * on the 8168d). http://wiki.osdev.org/RTL8169
29  * 
30  * Basic ideas (although no direct code) were gleamed from the OpenBSD re(4) driver,
31  * which can be found in sys/dev/ic/re.c. sys/dev/ic/rtl81x9reg.h is needed to make
32  * sense of the constants used in re.c.
33  *
34  * This is an ongoing work in progress. Main thing is we need a kernel interface for PCI
35  * devices and network devices, that we can hook into, instead of providing arbitary functions
36  * 
37  * TODO: Remove hacky syscall hack stuff (once we get a real stack).
38  * TODO: Jumbo frame support
39  * TODO: Use high priority transmit ring for syscall stuff.
40  * TODO: Discuss panic conditions.
41  * TODO: Shutdown cleanup kfrees()
42  * TODO: Use onboard timer interrupt to check for packets, instead of writing a bit each time we have a packet.
43  * TODO: CONCURRENCY!
44  */
45
46
47
48 struct Descriptor
49 {
50     unsigned int command,  /* command/status dword */
51                  vlan,     /* currently unused */
52                  low_buf,  /* low 32-bits of physical buffer address */
53                  high_buf; /* high 32-bits of physical buffer address */
54 };
55
56
57 uint32_t io_base_addr = 0;
58 uint32_t irq = 0;
59 char device_mac[6];
60
61 struct Descriptor *rx_des_kva;
62 struct Descriptor *rx_des_pa;
63
64 struct Descriptor *tx_des_kva;
65 struct Descriptor *tx_des_pa;
66
67 uint32_t rx_des_cur = 0;
68 uint32_t tx_des_cur = 0;
69
70 uint8_t eth_up = 0;
71
72 // Hacky stuff for syscall hack. Go away.
73 int packet_waiting;
74 int packet_buffer_size;
75 char* packet_buffer;
76 char* packet_buffer_orig;
77 int packet_buffer_pos = 0;
78 // End hacky stuff
79
80 void init_nic() {
81         
82         if (scan_pci() < 0) return;
83         read_mac();
84         setup_descriptors();
85         configure_nic();
86         setup_interrupts();
87         eth_up = 1;
88         
89         //Trigger sw based nic interrupt
90         //outb(io_base_addr + 0x38, 0x1);
91         //udelay(3000000);
92         
93         return;
94 }
95
96
97 int scan_pci() {
98         
99         uint32_t address;
100         uint32_t lbus = 0;
101         uint32_t ldev = 0;
102         uint32_t lfunc = 0; // We only look at function 0 for now.
103         uint32_t lreg = 0; 
104         uint32_t result  = 0;
105  
106         cprintf("Searching for RealTek 8168 Network device......");
107
108         for (int i = 0; i < PCI_MAX_BUS; i++)
109                 for (int j = 0; j < PCI_MAX_DEV; j++) {
110
111                 lbus = i;
112                 ldev = j;
113                 lreg = 0; // PCI REGISTER 0
114
115                 address = MK_CONFIG_ADDR(lbus, ldev, lfunc, lreg); 
116
117                 // Probe current bus/dev
118                 outl(PCI_CONFIG_ADDR, address);
119                 result = inl(PCI_CONFIG_DATA);
120         
121                 uint16_t dev_id = result >> PCI_DEVICE_OFFSET;
122                 uint16_t ven_id = result & PCI_VENDOR_MASK;
123
124                 // Vender DNE
125                 if (ven_id == INVALID_VENDOR_ID) 
126                         continue;
127
128                 // Ignore non RealTek 8168 Devices
129                 if (ven_id != REALTEK_VENDOR_ID || dev_id != REALTEK_DEV_ID)
130                         continue;
131                 cprintf(" found on BUS %x DEV %x\n", i, j);
132
133                 // Find the IRQ
134                 address = MK_CONFIG_ADDR(lbus, ldev, lfunc, PCI_IRQ_REG);
135                 outl(PCI_CONFIG_ADDR, address);
136                 irq = inl(PCI_CONFIG_DATA) & PCI_IRQ_MASK;
137                 nic_debug("-->IRQ: %u\n", irq);
138
139                 // Loop over the BARs
140                 for (int k = 0; k <= 5; k++) {
141                         lreg = 4 + k;
142                         address = MK_CONFIG_ADDR(lbus, ldev, lfunc, lreg << 2); 
143                 outl(PCI_CONFIG_ADDR, address);
144                 result = inl(PCI_CONFIG_DATA);
145                                         
146                         if (result == 0) // (0 denotes no valid data)
147                                 continue;
148
149                         // Read the bottom bit of the BAR. 
150                         if (result & PCI_BAR_IO_MASK) {
151                                 result = result & PCI_IO_MASK;
152                                 nic_debug("-->BAR%u: %s --> %x\n", k, "IO", result);
153                         } else {
154                                 result = result & PCI_MEM_MASK;
155                                 nic_debug("-->BAR%u: %s --> %x\n", k, "MEM", result);
156                         }
157                         
158                         // TODO Switch to memory mapped instead of IO?
159                         if (k == 0) // BAR0 denotes the IO Addr for the device
160                                 io_base_addr = result;                                          
161                 }
162                 
163                 nic_debug("-->hwrev: %x\n", inl(io_base_addr + RL_HWREV_REG) & RL_HWREV_MASK);
164                 
165                 return 0;
166         }
167         cprintf(" not found. No device configured.\n");
168         
169         return -1;
170 }
171
172 void read_mac() {
173         
174         for (int i = 0; i < 6; i++)
175            device_mac[i] = inb(io_base_addr + RL_MAC_OFFSET + i); 
176         
177         nic_debug("-->DEVICE MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 0xFF & device_mac[0], 0xFF & device_mac[1], 
178                                                                     0xFF & device_mac[2], 0xFF & device_mac[3], 
179                                                                 0xFF & device_mac[4], 0xFF & device_mac[5]);
180         return;
181 }
182
183 /*
184 void setup_descriptors() {
185         
186         nic_debug("-->Setting up tx/rx descriptors.\n");
187         
188         page_t *rx_des_page = NULL, *tx_des_page = NULL;
189                         
190         if (page_alloc(&rx_des_page) < 0) panic("Can't allocate page for RX Ring");
191         
192         if (page_alloc(&tx_des_page) < 0) panic("Can't allocate page for TX Ring");
193         
194         if (page2pa(tx_des_page) == 0x1000)
195                 if (page_alloc(&tx_des_page) < 0) panic("Can't allocate page for TX Ring");
196         
197         // extra page_alloc needed because of the strange page_alloc thing
198         if (page_alloc(&tx_des_page) < 0) panic("Can't allocate page for TX Ring");
199         
200         rx_des_kva = page2kva(rx_des_page);
201         tx_des_kva = page2kva(tx_des_page);
202         
203         rx_des_pa = page2pa(rx_des_page);
204         tx_des_pa = page2pa(tx_des_page);
205
206         cprintf("rx_des_page: %x\n", rx_des_pa);
207         cprintf("tx_des_page: %x\n", tx_des_pa);
208         
209     for (int i = 0; i < num_of_rx_descriptors; i++) 
210                 set_rx_descriptor(i);
211                 
212         for (int i = 0; i < num_of_tx_descriptors; i++) 
213                 set_tx_descriptor(i);
214 }
215 */
216
217 void setup_descriptors() {
218         
219         nic_debug("-->Setting up tx/rx descriptors.\n");
220                         
221         // Allocate room for the buffers. Include an extra ALIGN space.
222         // Buffers need to be on 256 byte boundries.
223         // Note: Buffers are alligned by kmalloc automatically to powers of 2 less than the size requested
224         // We request more than 256, thus they are aligned on 256 byte boundries
225         rx_des_kva = kmalloc(NUM_RX_DESCRIPTORS * sizeof(struct Descriptor), 0);
226         tx_des_kva = kmalloc(NUM_TX_DESCRIPTORS * sizeof(struct Descriptor), 0);
227         
228         if (rx_des_kva == NULL) panic("Can't allocate page for RX Ring");
229         if (tx_des_kva == NULL) panic("Can't allocate page for TX Ring");
230         
231         rx_des_pa = (struct Descriptor *)PADDR(rx_des_kva);
232         tx_des_pa = (struct Descriptor *)PADDR(tx_des_kva);
233         
234     for (int i = 0; i < NUM_RX_DESCRIPTORS; i++) 
235                 set_rx_descriptor(i, TRUE); // Allocate memory for the descriptor
236                 
237         for (int i = 0; i < NUM_TX_DESCRIPTORS; i++) 
238                 set_tx_descriptor(i);
239                 
240         return;
241 }
242
243
244 void set_rx_descriptor(uint32_t des_num, uint8_t reset_buffer) {
245         
246         // Set the OWN bit on all descriptors. Also set the buffer size.
247         rx_des_kva[des_num].command = (DES_OWN_MASK | (RL_RX_MAX_BUFFER_SIZE & DES_RX_SIZE_MASK));
248         
249         if (des_num == (NUM_RX_DESCRIPTORS - 1)) 
250                 rx_des_kva[des_num].command = rx_des_kva[des_num].command | DES_EOR_MASK;
251         
252         if (reset_buffer) {
253                 // Must be aligned on 8 byte boundries. Taken care of by kmalloc.
254                 char *rx_buffer = kmalloc(RL_RX_MAX_BUFFER_SIZE, 0);
255         
256                 if (rx_buffer == NULL) panic ("Can't allocate page for RX Buffer");
257
258                 rx_des_kva[des_num].low_buf = PADDR(rx_buffer);
259                 //.high_buf used if we do 64bit.
260         }
261         
262         return;
263 }
264
265 void set_tx_descriptor(uint32_t des_num) {
266         
267         // Clear the command bits.
268         tx_des_kva[des_num].command = 0;
269         
270         // Set EOR bit on last descriptor
271         if (des_num == (NUM_TX_DESCRIPTORS - 1))
272                 tx_des_kva[des_num].command = DES_EOR_MASK;     
273                 
274         char *tx_buffer = kmalloc(RL_TX_MAX_BUFFER_SIZE, 0);
275
276         if (tx_buffer == NULL) panic ("Can't allocate page for TX Buffer");
277
278         tx_des_kva[des_num].low_buf = PADDR(tx_buffer);
279         //.high_buf used if we do 64bit.
280                 
281         return;
282 }
283
284 void configure_nic() {
285         
286         // TODO: Weigh resetting the nic. Not really needed. Remove?
287         // TODO Check ordering of what we set.
288         // TODO Remove C+ register setting?
289         
290         nic_debug("-->Configuring Device.\n");
291         reset_nic();
292
293         // Magic to handle the C+ register. Completely undocumented, ripped from the BSE RE driver.
294         outl(io_base_addr + RL_CP_CTRL_REG, RL_CP_MAGIC_MASK);
295
296         // Unlock EPPROM CTRL REG
297         outb(io_base_addr + RL_EP_CTRL_REG, RL_EP_CTRL_UL_MASK);        
298         
299         // Set max RX Packet Size
300     outw(io_base_addr + RL_RX_MXPKT_REG, RL_RX_MAX_SIZE);       
301                 
302         // Set max TX Packet Size
303     outb(io_base_addr + RL_TX_MXPKT_REG, RL_TX_MAX_SIZE);                       
304
305         // Set TX Des Ring Start Addr
306     outl(io_base_addr + RL_TX_DES_REG, (unsigned long)tx_des_pa); 
307         
308         // Set RX Des Ring Start Addr
309     outl(io_base_addr + RL_RX_DES_REG, (unsigned long)rx_des_pa);       
310
311         // Configure TX
312         outl(io_base_addr + RL_TX_CFG_REG, RL_TX_CFG_MASK); 
313         
314         // Configure RX
315         outl(io_base_addr + RL_TX_CFG_REG, RL_RX_CFG_MASK);                     
316
317         // Enable RX and TX in the CTRL Reg
318         outb(io_base_addr + RL_CTRL_REG, RL_CTRL_RXTX_MASK);                    
319
320         // Lock the EPPROM Ctrl REG
321     outl(io_base_addr + RL_EP_CTRL_REG, RL_EP_CTRL_L_MASK);             
322         
323         return;
324 }
325
326 void reset_nic() {
327         
328         nic_debug("-->Resetting device..... ");
329         outb(io_base_addr + RL_CTRL_REG, RL_CTRL_RESET_MASK);
330         
331         // Wait for NIC to answer "done resetting" before continuing on
332         while (inb(io_base_addr + RL_CTRL_REG) & RL_CTRL_RESET_MASK);
333         nic_debug(" done.\n");
334         
335         return;
336 }
337
338 void setup_interrupts() {
339         
340         extern handler_t interrupt_handlers[];
341         
342         nic_debug("-->Setting interrupts.\n");
343         
344         // Enable NIC interrupts
345         outw(io_base_addr + RL_IM_REG, RL_INTERRUPT_MASK);
346         
347         //Clear the current interrupts.
348         outw(io_base_addr + RL_IS_REG, RL_INTRRUPT_CLEAR);
349         
350         // Kernel based interrupt stuff
351         register_interrupt_handler(interrupt_handlers, KERNEL_IRQ_OFFSET + irq, nic_interrupt_handler, 0);
352         pic_unmask_irq(irq);
353         unmask_lapic_lvt(LAPIC_LVT_LINT0);
354         enable_irq();
355         
356         return;
357 }
358
359 // We need to evaluate this routine in terms of concurrency.
360 // We also need to figure out whats up with different core interrupts
361 void nic_interrupt_handler(trapframe_t *tf, void* data) {
362         
363         nic_interrupt_debug("\nNic interrupt on core %u!\n", lapic_get_id());
364                 
365         // Read the offending interrupt(s)
366         uint16_t interrupt_status = inw(io_base_addr + RL_IS_REG);
367
368         // We can have multiple interrupts fire at once. I've personally seen this.
369         // This means we need to handle this as a series of independent if's
370         if (interrupt_status & RL_INT_ROK) {
371                 nic_interrupt_debug("-->RX OK\n");
372                 nic_handle_rx_packet();
373         }       
374         
375         if (interrupt_status & RL_INT_RERR) {
376                 nic_interrupt_debug("-->RX ERR\n");
377         }
378         
379         if (interrupt_status & RL_INT_TOK) {
380                 nic_interrupt_debug("-->TX OK\n");
381         }
382         
383         if (interrupt_status & RL_INT_TERR) {
384                 nic_interrupt_debug("-->TX ERR\n");
385         }
386         
387         if (interrupt_status & RL_INT_RDU) {
388                 nic_interrupt_debug("-->RX Descriptor Unavailable\n");
389         }
390         
391         if (interrupt_status & RL_INT_LINKCHG) {
392                 nic_interrupt_debug("-->Link Status Changed\n");
393         }
394         
395         if (interrupt_status & RL_INT_FOVW) {
396                 nic_interrupt_debug("-->RX Fifo Overflow\n");
397         }
398         
399         if (interrupt_status & RL_INT_TDU) {
400                 nic_interrupt_debug("-->TX Descriptor Unavailable\n");
401         }
402         
403         if (interrupt_status & RL_INT_SWINT) {
404                 nic_interrupt_debug("-->Software Generated Interrupt\n");
405         }
406         
407         if (interrupt_status & RL_INT_TIMEOUT) {
408                 nic_interrupt_debug("-->Timer Expired\n");
409         }
410         
411         if (interrupt_status & RL_INT_SERR) {
412                 nic_interrupt_debug("-->PCI Bus System Error\n");
413         }
414         
415         nic_interrupt_debug("\n");
416                 
417         // Clear interrupts     
418         outw(io_base_addr + RL_IS_REG, RL_INTRRUPT_CLEAR);
419         
420         return;
421 }
422
423 // TODO: Does a packet too large get dropped or just set the error bits in the descriptor? Find out.
424 void nic_handle_rx_packet() {
425         
426         uint32_t current_command = rx_des_kva[rx_des_cur].command;
427         uint16_t packet_size;
428                 
429         nic_frame_debug("-->RX Des: %u\n", rx_des_cur);
430         
431         // Make sure we are processing from the start of a packet segment
432         if (!(current_command & DES_FS_MASK)) {
433                 nic_frame_debug("-->ERR: Current RX descriptor not marked with FS mask. Panic!");
434                 panic("RX Descriptor Ring FS out of sync");
435         }
436         
437         // NOTE: We are currently configured that the max packet size is large enough to fit inside 1 descriptor buffer,
438         // So we should never be in a situation where a packet spans multiple descriptors.
439         // When we change this, this should operate in a loop until the LS mask is found
440         // Loop would begin here.
441         
442         uint32_t rx_des_loop_cur = rx_des_cur;
443         uint32_t frame_size = 0;
444         uint32_t fragment_size = 0;
445         uint32_t num_frags = 0;
446         
447         char *rx_buffer = kmalloc(MAX_FRAME_SIZE, 0);
448         
449         if (rx_buffer == NULL) panic ("Can't allocate page for incoming packet.");
450         
451         do {
452                 current_command =  rx_des_kva[rx_des_loop_cur].command;
453                 fragment_size = rx_des_kva[rx_des_loop_cur].command & DES_RX_SIZE_MASK;
454                 
455                 // If we've looped through the entire ring and not found a terminating packet, bad nic state.
456                 // Panic or clear all descriptors? This is a nic hardware error. 
457                 if (num_frags && (rx_des_loop_cur == rx_des_cur)) {
458                         //for (int i = 0; i < NUM_RX_DESCRIPTORS; i++) 
459                         //      set_rx_descriptor(i, FALSE); // Dont reallocate memory for the descriptor
460                         // rx_des_cur = 0;
461                         // return;
462                         nic_frame_debug("-->ERR: No ending segment found in RX buffer.\n");
463                         panic("RX Descriptor Ring out of sync.");
464                 }
465                 
466                 num_frags++;
467                 
468                 
469                 // Make sure we own the current packet. Kernel ownership is denoted by a 0. Nic by a 1.
470                 if (current_command & DES_OWN_MASK) {
471                         nic_frame_debug("-->ERR: Current RX descriptor not owned by kernel. Panic!");
472                         panic("RX Descriptor Ring OWN out of sync");
473                 }
474                 
475                 // Make sure if we are at the end of the buffer, the des is marked as end
476                 if ((rx_des_loop_cur == (NUM_RX_DESCRIPTORS - 1)) && !(current_command & DES_EOR_MASK)) {
477                         nic_frame_debug("-->ERR: Last RX descriptor not marked with EOR mask. Panic!\n");
478                         panic("RX Descriptor Ring EOR Missing");
479                 }
480                 
481                 // We set a max frame size and the nic violated that. 
482                 // Panic or clear all desriptors?
483                 if ((frame_size + fragment_size) > MAX_FRAME_SIZE) {
484                         //for (int i = 0; i < NUM_RX_DESCRIPTORS; i++) 
485                         //      set_rx_descriptor(i, FALSE); // Dont reallocate memory for the descriptor
486                         // rx_des_cur = 0;
487                         // return;
488                         nic_frame_debug("-->ERR: Nic sent %u byte packet. Max is %u\n", frame_size, MAX_FRAME_SIZE);
489                         panic("NIC Sent packets larger than configured.");
490                 }
491                 
492                 // Move the fragment data into the buffer
493                 memcpy(rx_buffer + frame_size, KADDR(rx_des_kva[rx_des_loop_cur].low_buf), fragment_size);
494                 
495                 // Reset the descriptor. No reuse buffer.
496                 set_rx_descriptor(rx_des_loop_cur, FALSE);
497                 
498                 // Note: We mask out fragment sizes at 0x3FFFF. There can be at most 1024 of them.
499                 // This can not overflow the uint32_t we allocated for frame size, so
500                 // we dont need to worry about mallocing too little then overflowing when we read.
501                 frame_size = frame_size + fragment_size;
502                 
503                 // Advance to the next descriptor
504                 rx_des_loop_cur = (rx_des_loop_cur + 1) % NUM_RX_DESCRIPTORS;
505                 
506         } while (!(current_command & DES_LS_MASK));
507         
508         // Hack for UDP syscall hack. 
509         // This is a quick hack to let us deal with where to put packets coming in. This is not concurrency friendly
510         // In the event that we get 2 incoming frames for our syscall test (shouldnt happen)
511         // We cant process more until another packet comes in. This is ugly, but this code goes away as soon as we integrate a real stack.
512         // This keys off the source port, fix it for dest port. 
513         // Also this may access packet regions that are wrong. If someone addresses empty packet for our interface
514         // and the bits that happened to be in memory before are the right port, this will trigger. this is bad
515         // but since syscalls are a hack for only 1 machine connected, we dont care for now.
516         
517         if ((current_command & DES_PAM_MASK) && (*((uint16_t*)(rx_buffer + 36)) == 0x9bad)) {
518                 
519                 if (packet_waiting) return;
520
521                 packet_buffer = rx_buffer + PACKET_HEADER_SIZE;
522                 
523                 // So ugly I want to cry
524                 packet_buffer_size = *((uint16_t*)(rx_buffer + 38)); 
525                 packet_buffer_size = (((uint16_t)packet_buffer_size & 0xff00) >> 8) |  (((uint16_t)packet_buffer_size & 0x00ff) << 8);          
526                 packet_buffer_size = packet_buffer_size - 8;
527
528                 packet_buffer_orig = rx_buffer;
529                 packet_buffer_pos = 0;
530                 
531                 packet_waiting = 1;
532                 
533                 process_frame(rx_buffer, frame_size, current_command);
534                 
535                 rx_des_cur = rx_des_loop_cur;
536                 
537                 return;
538         }
539         
540         // END HACKY STUFF
541         
542         // Chew on the frame data. Command bits should be the same for all frags.
543         process_frame(rx_buffer, frame_size, current_command);
544
545         rx_des_cur = rx_des_loop_cur;
546         
547         kfree(rx_buffer);
548         
549         return;
550 }
551
552 // This is really more of a debug level function. Will probably go away once we get a stack going.
553 void process_frame(char *frame_buffer, uint32_t frame_size, uint32_t command) {
554                 
555         nic_frame_debug("-->Command: %x\n", command);
556         nic_frame_debug("-->Size: %u\n", frame_size);
557         
558         if (frame_buffer == NULL)
559                 return;
560         
561         // This is hacky. Once we know what our stack will look like, change this.
562         // Once remove check for 0 size.
563         if (frame_size < MINIMUM_PACKET_SIZE) {
564                 nic_frame_debug("-->Packet too small. Discarding.\n");
565                 return;
566         }
567         
568         char dest_mac[6];
569         char source_mac[6];
570         char eth_type[2];
571         
572         for (int i = 0; i < 6; i++) {
573                 dest_mac[i] = frame_buffer[i];
574         }
575         
576         for (int i = 0; i < 6; i++) {
577                 source_mac[i] = frame_buffer[i+6];
578         }
579         
580         eth_type[0] = frame_buffer[12];
581         eth_type[1] = frame_buffer[13];
582         
583         if (command & DES_MAR_MASK) {
584                 nic_frame_debug("-->Multicast Packet.\n");
585         }
586         
587         if (command & DES_PAM_MASK) {
588                 nic_frame_debug("-->Physical Address Matched.\n");
589         }
590         
591         if (command & DES_BAR_MASK) {
592                 nic_frame_debug("-->Broadcast Packet.\n");
593         }
594         
595         // Note: DEST comes before SRC in the ethernet frame, but that 
596         
597         nic_frame_debug("-->DEST   MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 0xFF & dest_mac[0], 0xFF & dest_mac[1],       
598                                                                            0xFF & dest_mac[2], 0xFF & dest_mac[3],      
599                                                                        0xFF & dest_mac[4], 0xFF & dest_mac[5]);
600         
601         nic_frame_debug("-->SOURCE MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 0xFF & source_mac[0], 0xFF & source_mac[1],   
602                                                                            0xFF & source_mac[2], 0xFF & source_mac[3],  
603                                                                        0xFF & source_mac[4], 0xFF & source_mac[5]);
604
605         nic_frame_debug("-->ETHR MODE: %02x%02x\n", 0xFF & eth_type[0], 0xFF & eth_type[1]);
606                 
607         return;
608 }
609
610 // Main routine to send a frame. Just sends it and goes.
611 // Card supports sending across multiple fragments.
612 // Would we want to write a function that takes a larger packet and generates fragments?
613 // This seems like the stacks responsibility. Leave this for now. may in future
614 // Remove the max size cap and generate multiple packets.
615 int send_frame(const char *data, size_t len) {
616
617         if (data == NULL)
618                 return -1;
619         if (len == 0)
620                 return 0;
621
622         if (tx_des_kva[tx_des_cur].command & DES_OWN_MASK) {
623                 nic_frame_debug("-->TX Ring Buffer Full!\n");
624                 return -1;
625         }
626         
627         if (len > MAX_FRAME_SIZE) {
628                 nic_frame_debug("-->Frame Too Large!\n");
629                 return -1;
630         }
631         
632         memcpy(KADDR(tx_des_kva[tx_des_cur].low_buf), data, len);
633
634         tx_des_kva[tx_des_cur].command = tx_des_kva[tx_des_cur].command | len | DES_OWN_MASK | DES_FS_MASK | DES_LS_MASK;
635
636         // For this revision of the NIC, the checksum bits get set in the vlan field not the command field.
637         // THIS IS A HACK: Need to reach inside the frame we are sending and detect if its of type ip/udp/tcp and set right flag
638         // For now, for the syscall hack, force ip checksum on. (we dont care about udp checksum).
639         // Add an argument to function to specify packet type?
640         tx_des_kva[tx_des_cur].vlan = DES_TX_IP_CHK_MASK;
641         
642         tx_des_cur = (tx_des_cur + 1) % NUM_TX_DESCRIPTORS;
643         
644         //nic_frame_debug("-->Sent packet.\n");
645         
646         outb(io_base_addr + RL_TX_CTRL_REG, RL_TX_SEND_MASK);
647         
648         return len;
649 }
650
651 // This function is a complete hack for syscalls until we get a stack.
652 // the day I delete this monstrosity of code I will be a happy man --Paul
653 const char *packet_wrap(const char* data, size_t len) {
654         
655         #define htons(A) ((((uint16_t)(A) & 0xff00) >> 8) | \
656                             (((uint16_t)(A) & 0x00ff) << 8))
657         #define htonl(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \
658                             (((uint32_t)(A) & 0x00ff0000) >> 8)  | \
659                             (((uint32_t)(A) & 0x0000ff00) << 8)  | \
660                             (((uint32_t)(A) & 0x000000ff) << 24))
661
662         #define ntohs  htons
663         #define ntohl  htohl
664
665         if ((len == 0) || (data == NULL))
666                 return NULL;
667         
668         struct ETH_Header
669         {
670                 char dest_mac[6];
671                 char source_mac[6];
672                 uint16_t eth_type;
673         };
674
675         
676         struct IP_Header
677         {
678                 uint32_t ip_opts0;
679                 uint32_t ip_opts1;
680                 uint32_t ip_opts2;
681                 uint32_t source_ip;
682                 uint32_t dest_ip;
683         };
684         
685         struct UDP_Header
686         {
687                 uint16_t source_port;
688                 uint16_t dest_port;
689                 uint16_t length;
690                 uint16_t checksum;
691         };      
692         
693         // Hard coded to paul's laptop's mac
694         char dest_mac_address[6] = {0x00, 0x23, 0x32, 0xd5, 0xae, 0x82};
695         
696         uint32_t source_ip = 0xC0A8000A; // 192.168.0.10
697         uint32_t dest_ip   = 0xC0A8000B; // 192.168.0.11
698  
699         
700         if (len > MAX_PACKET_DATA) {
701                 nic_frame_debug("Bad packet size for packet wrapping");
702                 return NULL;
703         }
704         
705         char* wrap_buffer = kmalloc(MAX_PACKET_SIZE, 0);
706         
707         if (wrap_buffer == NULL) {
708                 nic_frame_debug("Can't allocate page for packet wrapping");
709                 return NULL;
710         }
711         
712         struct ETH_Header *eth_header = (struct ETH_Header*) wrap_buffer;
713         struct IP_Header *ip_header = (struct IP_Header*) (wrap_buffer + sizeof(struct ETH_Header));
714         struct UDP_Header *udp_header = (struct UDP_Header*) (wrap_buffer + sizeof(struct ETH_Header) + sizeof(struct IP_Header));
715         
716         // Setup eth data
717         for (int i = 0; i < 6; i++) 
718                 eth_header->dest_mac[i] = dest_mac_address[i];
719                 
720         for (int i = 0; i < 6; i++) 
721                 eth_header->source_mac[i] = device_mac[i];
722                 
723         eth_header->eth_type = htons(0x0800);
724         
725         // Setup IP data
726         ip_header->ip_opts0 = htonl((4<<28) | (5 << 24) | (len + 28));
727         ip_header->ip_opts1 = 0;
728         ip_header->ip_opts2 = 0x00110a;
729         ip_header->source_ip = htonl(source_ip);
730         ip_header->dest_ip = htonl(dest_ip);
731         
732         // Setup UDP Data
733         udp_header->source_port = htons(44443);
734         udp_header->dest_port = htons(44444);
735         udp_header->length = htons(8 + len);
736         udp_header->checksum = 0;
737         
738         memcpy (wrap_buffer + PACKET_HEADER_SIZE, data, len);
739         
740         return wrap_buffer;     
741 }