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.


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