Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


fixed a ton of compile errors
[palacios.git] / palacios / src / geekos / ne2k.c
1 #include <geekos/ne2k.h>
2 #include <geekos/debug.h>
3 #include <geekos/io.h>
4 #include <geekos/irq.h>
5 #include <geekos/malloc.h>
6 #include <geekos/string.h>
7 #include <uip/uip.h>
8 #include <uip/uip_arp.h>
9
10 #define DEBUG 1
11 #define TX_START_BUFF   0x40
12 #define RX_START_BUFF   0x4c
13 #define RX_END_BUFF     0x80
14
15 static uint_t next = (RX_START_BUFF << 8);
16 static uint_t received = 0;
17 static uint_t send_done = 1;
18
19 struct NE2K_REGS* regs;
20
21 struct callback {
22   int (*packet_received)(struct NE2K_Packet_Info *info, uchar_t *packet);
23 } callbacks;
24
25 #if DEBUG
26 static void Dump_Registers()
27 {
28   uint_t data;
29   PrintBoth("Dumping NIC registers for page %x...\n", (In_Byte(NE2K_CR) & 0xc0) >> 6);
30   uint_t i = 0;
31   for(i = 0; i <= 0x0f; i += 0x01) {
32     data = In_Byte(NE2K_BASE_ADDR+i);
33     PrintBoth("\t%x: %x\n", NE2K_BASE_ADDR + i, data);
34   }
35 }
36 #endif
37
38 static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
39 {
40
41   Begin_IRQ(state);
42   PrintBoth("NIC Interrupt Occured!\n");
43   uchar_t isr_content = In_Byte(NE2K_ISR);
44
45   PrintBoth("Contents of ISR: %x\n", isr_content);
46
47   if(isr_content & 0x01) /* A packet has been received. */
48   {
49         uchar_t current;
50         Out_Byte(NE2K_CR, 0x4a);        /* Page 1 */
51         current = In_Byte(NE2K_CURR);
52         Out_Byte(NE2K_CR, 0x0a);        /* Page 0 */
53         NE2K_Receive();
54
55         /* When CURR equals BNRY, all packets in the receive ring buffer have been read, and
56            the packet received bit in the interrupt status register can be cleared. */
57         if(current == In_Byte(NE2K_BNRY))
58           Out_Byte(NE2K_ISR, 0x01);
59   }
60
61   End_IRQ(state);
62   if(isr_content & 0x02) /* A packet has been successfully transmitted. */
63   {
64     send_done = 1;  
65     Out_Byte(NE2K_ISR, 0x02);
66   }
67
68   //Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts. */
69 }
70
71 int Init_Ne2k(int (*rcvd_fn)(struct NE2K_Packet_Info *info, uchar_t *packet))
72 {
73   callbacks.packet_received = rcvd_fn;
74
75   PrintBoth("Initializing network card...\n");
76   Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f));  /* Reset */
77
78   regs = Malloc(sizeof(struct NE2K_REGS));
79   struct _CR * cr = (struct _CR *)&(regs->cr);
80   struct _RCR * rcr = (struct _RCR*)&(regs->rcr);
81   struct _IMR * imr = (struct _IMR *)&(regs->imr);
82
83   regs->cr = 0x21;
84   regs->dcr = 0x49; /* Word-wide DMA transfer. */
85   regs->isr = 0xff; /* Clear all interrupts. */
86   regs->rcr = 0x20; /* Accept packets shorter than 64 bytes. */
87   regs->tcr = 0x02; /* Internal loopback mode. */
88
89   Out_Byte(NE2K_CR, regs->cr);
90   Out_Byte(NE2K_DCR, regs->dcr);
91   Out_Byte(NE2K_ISR, regs->isr);
92   Out_Byte(NE2K_RCR, regs->rcr);
93   Out_Byte(NE2K_TCR, regs->tcr);
94   Out_Byte(NE2K_IMR, regs->imr);
95
96   /* Remote byte count registers. */
97   Out_Byte(NE2K_RBCR0, 0x00);
98   Out_Byte(NE2K_RBCR1, 0x00);
99   /* Remote start address registers. */
100   Out_Byte(NE2K_RSAR0, 0x00);
101   Out_Byte(NE2K_RSAR1, 0x00);
102
103   Out_Byte(NE2K_TPSR, TX_START_BUFF);           /* Transmit page start register */
104   Out_Byte(NE2K_PSTART, RX_START_BUFF);         /* Page start register */
105   Out_Byte(NE2K_PSTOP, RX_END_BUFF);                    /* Page stop register */
106   Out_Byte(NE2K_BNRY, RX_START_BUFF);           /* Boundary register */ 
107
108   cr->ps = 0x01; /* Switch to reg page 1. */
109   Out_Byte(NE2K_CR, regs->cr);
110   /* Current page register: points to first free page that can be used for packet reception. */
111   Out_Byte(NE2K_CURR, RX_START_BUFF);
112   cr->ps = 0x00; /* Switch to page 0 */
113
114   Out_Byte(NE2K_CR, regs->cr);
115   Out_Byte(NE2K_ISR, regs->isr);
116
117   /* Interrupt mask register: setting a bit to 1 enables the
118      corresponding interrupt in ISR. */
119   imr->prxe = 0x1;
120   imr->ptxe = 0x1;
121   imr->rxee = 0x1;
122   imr->txee = 0x1;
123   imr->ovwe = 0x1;
124   imr->cnte = 0x1;
125   Out_Byte(NE2K_IMR, regs->imr);
126
127   cr->ps = 0x01;  /* Switch to reg page 1 */
128   Out_Byte(NE2K_CR, regs->cr);
129
130   /* Set the physical address of the card to 52:54:00:12:34:58 */
131   Out_Byte(NE2K_CR+0x01, 0x52);
132   Out_Byte(NE2K_CR+0x02, 0x54);
133   Out_Byte(NE2K_CR+0x03, 0x00);
134   Out_Byte(NE2K_CR+0x04, 0x12);
135   Out_Byte(NE2K_CR+0x05, 0x34);
136   Out_Byte(NE2K_CR+0x06, 0x58);
137
138   /* Set the multicast address register to all 1s; accepts all multicast packets */
139   uint_t i;
140   for(i = 0x08; i <= 0x0f; i++) {
141     Out_Byte(NE2K_CR+i, 0xff);
142   }
143
144   regs->cr = 0x21;  //set CR to start value
145   Out_Byte(NE2K_CR, regs->cr);
146
147   regs->tcr = 0x00;
148   Out_Byte(NE2K_TCR, regs->tcr);
149
150   rcr->sep = 0x1;
151   rcr->ar = 0x1;
152   rcr->ab = 0x1;
153   rcr->am = 0x1;
154   rcr->pro = 0x1; /* Promiscuous mode: accept all packets. */
155   rcr->mon = 0x0;
156   Out_Byte(NE2K_RCR, regs->rcr);
157
158   cr->sta = 0x1;  // toggle start bit
159   cr->stp = 0x0;
160   Out_Byte(NE2K_CR, regs->cr);
161
162 #if DEBUG
163   Dump_Registers();
164
165   cr->ps = 0x01;
166   Out_Byte(NE2K_CR, regs->cr);
167   Dump_Registers();
168
169   cr->ps = 0x02;
170   Out_Byte(NE2K_CR, regs->cr);
171   Dump_Registers();
172
173   cr->ps = 0x00;
174   Out_Byte(NE2K_CR, regs->cr);
175 #endif
176
177   Install_IRQ(NE2K_IRQ, NE2K_Interrupt_Handler);
178   Enable_IRQ(NE2K_IRQ);
179 #if 0
180   for(i = 0; i < 0; i++)
181   {
182     NE2K_Transmit(regs);
183     PrintBoth("Transmitting a packet\n");
184   }
185 #endif
186 /*
187   uchar_t src_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x58 };
188   uchar_t dest_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 };
189
190   uint_t size = 64;
191   uchar_t *data = Malloc(size);
192   data = "This is a 64-byte string that will be used to test transmission.";
193
194   for(i = 0; i < 0; i++) {
195     NE2K_Send(regs, src_addr, dest_addr, 0x01, data, size);
196   }
197 */
198   //Free(data);  // Why does this crash?
199
200   return 0;
201 }
202
203 /* 
204  * This function is called when there is data in uip_buf that's ready to be sent.
205  * uip_arp_out() is used to translate the destination IP address to a MAC address.
206  * If the corresponding MAC address isn't in the cache, the packet is replaced with
207  * an ARP packet, which is sent out instead.  The original packet will need to be
208  * retransmitted at some point in the future.
209  */
210 int NE2K_Transmit(uint_t size)
211 {
212   uip_arp_out();
213   uchar_t *data;
214   data = Malloc(size);
215
216   /* Based on example code from the uIP documentation... */
217   if(size <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
218     memcpy(data, &uip_buf[0], size);
219   } else {
220     memcpy(data, &uip_buf[0], UIP_LLH_LEN + UIP_TCPIP_HLEN);
221     memcpy(data + UIP_LLH_LEN + UIP_TCPIP_HLEN, uip_appdata, size - UIP_TCPIP_HLEN - UIP_LLH_LEN);
222   }
223
224   /* Manually copy in the source MAC address for now. */
225   uchar_t src_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x58 };
226   memcpy(data + 6, src_addr, 6);
227   if(*(data+12) != 0x08 || *(data+13) != 0x06)
228   {
229     /* This is not an ARP packet. Fill in te size of the packet manually. */
230     *(data+12) = size & 0xff;
231     *(data+13) = (size >> 8) & 0xff;
232   }
233
234   NE2K_Send_Packet(data, size);
235   Free(data);
236   return 0;
237 }
238
239 int NE2K_Send_Packet(uchar_t *packet, uint_t size)
240 {
241   struct _CR * cr = (struct _CR*)&(regs->cr);
242   regs->cr = 0x21; /* Turn off remote DMA, stop command */
243   cr->stp = 0x0;  /* toggle start on */
244   cr->sta = 0x1;
245   Out_Byte(NE2K_CR, regs->cr);
246   
247   // Read-before-write bug fix?
248   Out_Byte(NE2K_RBCR0, 0x42);
249   Out_Byte(NE2K_RBCR1, 0x00);
250   Out_Byte(NE2K_RSAR0, 0x42);
251   Out_Byte(NE2K_RSAR1, 0x00);
252
253   cr->rd = 0x01;  /* set remote DMA to 'remote read' */
254   Out_Byte(NE2K_CR, regs->cr);
255
256   regs->isr = 0x40;  /* clear 'remote DMA complete' interrupt */
257   Out_Byte(NE2K_ISR, regs->isr);
258   
259   /* Set remote byte count registers */
260   Out_Byte(NE2K_RBCR0, size & 0xff);
261   Out_Byte(NE2K_RBCR1, (size >> 8) & 0xff);
262
263   /* Set transmit byte count registers. */
264   Out_Byte(NE2K_TBCR0, size & 0xff);
265   Out_Byte(NE2K_TBCR1, (size >> 8) & 0xff);
266
267   /* Set remote start address registers to the first page of the transmit ring buffer. */
268   Out_Byte(NE2K_RSAR0, 0x00);
269   Out_Byte(NE2K_RSAR1, TX_START_BUFF);
270
271   cr->rd = 0x02; /* Set remote DMA to 'remote write' */
272   Out_Byte(NE2K_CR, regs->cr);
273
274   /* Push the packet data to into the dataport */
275   uint_t i;
276   for(i = 0; i < size; i += 2) {
277     Out_Word(NE2K_CR + 0x10, (*(packet + i + 1) << 8) | *(packet + i));
278   }
279
280   cr->txp = 0x1; /* Start transmission */
281   Out_Byte(NE2K_CR, regs->cr);
282
283   return 0;
284 }
285
286 #if 1
287 /* Assumes src and dest are arrays of 6 characters. */
288 int NE2K_Send(uchar_t src[], uchar_t dest[], uint_t type, uchar_t *data, uint_t size)
289 {
290   struct _CR * cr = (struct _CR*)&(regs->cr);
291   uint_t packet_size = size + 16;
292   regs->cr = 0x21; /* Turn off remote DMA, stop command */
293   cr->stp = 0x0;  /* toggle start on */
294   cr->sta = 0x1;
295   Out_Byte(NE2K_CR, regs->cr);
296   
297   // Read-before-write bug fix?
298   Out_Byte(NE2K_RBCR0, 0x42);
299   Out_Byte(NE2K_RBCR1, 0x00);
300   Out_Byte(NE2K_RSAR0, 0x42);
301   Out_Byte(NE2K_RSAR1, 0x00);
302
303   cr->rd = 0x01;  /* set remote DMA to 'remote read' */
304   Out_Byte(NE2K_CR, regs->cr);
305
306   regs->isr = 0x40;  /* clear 'remote DMA complete' interrupt */
307   Out_Byte(NE2K_ISR, regs->isr);
308   
309   /* Set remote byte count registers */
310   Out_Byte(NE2K_RBCR0, packet_size & 0xff);
311   Out_Byte(NE2K_RBCR1, (packet_size >> 8) & 0xff);
312
313   /* Set transmit byte count registers. */
314   Out_Byte(NE2K_TBCR0, packet_size & 0xff);
315   Out_Byte(NE2K_TBCR1, (packet_size >> 8) & 0xff);
316
317   /* Set remote start address registers to the first page of the transmit ring buffer. */
318   Out_Byte(NE2K_RSAR0, 0x00);
319   Out_Byte(NE2K_RSAR1, TX_START_BUFF);
320
321   cr->rd = 0x02; /* Set remote DMA to 'remote write' */
322   Out_Byte(NE2K_CR, regs->cr);
323
324   /* Begin pushing the packet into the dataport (located at 0x10 from the base address). */
325   /* Destination Address */
326   Out_Word(NE2K_CR + 0x10, (dest[1] << 8) | dest[0]);
327   Out_Word(NE2K_CR + 0x10, (dest[3] << 8) | dest[2]);
328   Out_Word(NE2K_CR + 0x10, (dest[5] << 8) | dest[4]);
329
330   /* Source Address */
331   Out_Word(NE2K_CR + 0x10, (src[1] << 8) | src[0]);
332   Out_Word(NE2K_CR + 0x10, (src[3] << 8) | src[2]);
333   Out_Word(NE2K_CR + 0x10, (src[5] << 8) | src[4]);
334
335   /* Type */
336   Out_Word(NE2K_CR + 0x10, packet_size);
337
338   /* Packet data */
339   uint_t i;
340   for(i = 0; i < size; i += 2) {
341     Out_Word(NE2K_CR + 0x10, (*(data + i + 1) << 8) | *(data + i));
342   }
343
344   cr->txp = 0x1; /* Start transmission */
345   Out_Byte(NE2K_CR, regs->cr);
346
347   return 0;
348 }
349 #endif
350
351 int NE2K_Receive()
352 {
353   PrintBoth("Packet Received\n");
354
355   Out_Byte(NE2K_CR, 0x22);
356   /* Set RSAR to the start address of the received packet. */
357   Out_Byte(NE2K_RSAR0, next & 0xff);
358   Out_Byte(NE2K_RSAR1, next >> 8);
359   Out_Byte(NE2K_CR, 0x0a);
360
361   /* 
362    * A four byte header is added to the beginning of each received packet by the NIC.
363    * The first byte is the location of the next packet in the ring buffer.
364    * The second byte is the receive status code.
365    * The third and fourth bytes are the size of the packet.
366    */
367
368   uint_t i;
369   uint_t data;
370   data = In_Word(NE2K_CR + 0x10);
371
372 #if DEBUG
373   PrintBoth("\nPacket data:\n\t");
374   PrintBoth("%x ", data);
375 #endif
376
377   /* Get the location of the next packet */
378   next = data & 0xff00;
379
380   /* Retrieve the packet size from the header, and store it in RBCR. */
381   uint_t packet_size =  In_Word(NE2K_CR + 0x10) - 4;
382   uchar_t *packet = Malloc(packet_size);
383   Out_Byte(NE2K_RBCR0, packet_size & 0xff);
384   Out_Byte(NE2K_RBCR1, (packet_size>>8) & 0xff);
385
386 #if DEBUG
387         PrintBoth("packetsize = %x\n\t", packet_size);
388 #endif
389
390   /* Copy the received packet over from the ring buffer. */
391   for(i = 0; i < packet_size; i+=2) {
392     data = In_Word(NE2K_CR + 0x10);
393     *(packet + i) = data & 0x00ff;
394     *(packet + i + 1) = (data & 0xff00) >> 8;
395 #if 0
396     PrintBoth("BNRY = %x\n", In_Byte(NE2K_BNRY));
397     Out_Byte(NE2K_CR, 0x4a);
398     PrintBoth("CURR = %x\n", In_Byte(NE2K_CURR));  
399     Out_Byte(NE2K_CR, 0x0a);
400 #endif
401   }
402
403 //Out_Byte(NE2K_RBCR0, (In_Byte(NE2K_RBCR0))-2);
404 //Out_Byte(NE2K_RSAR0, (In_Byte(NE2K_RSAR0))+2);
405
406   PrintBoth("\n%d packets have been received", ++received);
407   PrintBoth("\n\n");
408
409   Out_Byte(NE2K_ISR, 0x40); /* Clear the remote DMA complete interrupt. */
410
411   /* The BNRY register stores the location of the first packet that hasn't been read yet */
412   Out_Byte(NE2K_BNRY, next >> 8);
413
414   struct NE2K_Packet_Info *info = Malloc(sizeof(struct NE2K_Packet_Info));
415   info->size = packet_size;
416   info->status = 0;
417   memcpy(info->dest, packet, 6);
418   memcpy(info->src, packet + 6, 6);
419   callbacks.packet_received(info, packet);
420
421   return 0;
422 }
423
424
425
426