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.


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