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