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.


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