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.


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