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 the bug that caused the first packet sent to always be malformed.
[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 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 src[], uchar_t dest[], uint_t type, uchar_t *data, uint_t size)
263 {
264   struct _CR * cr = (struct _CR*)&(regs->cr);
265   uint_t packet_size = size + 16;
266   regs->cr = 0x21; /* Turn off remote DMA, stop command */
267   cr->stp = 0x0;  //toggle start on
268   cr->sta = 0x1;
269   Out_Byte(NE2K_CR, regs->cr);
270   
271   // Read-before-write bug fix?
272   Out_Byte(NE2K_RBCR0, 0x42);
273   Out_Byte(NE2K_RBCR1, 0x00);
274   Out_Byte(NE2K_RSAR0, 0x42);
275   Out_Byte(NE2K_RSAR1, 0x00);
276
277   cr->rd = 0x01;  // set remote DMA to 'remote read'
278   Out_Byte(NE2K_CR, regs->cr);
279
280   regs->isr = 0x40;  // clear and set Remote DMA high
281   Out_Byte(NE2K_ISR, regs->isr);
282   
283   /* Set remote byte count registers */
284   Out_Byte(NE2K_RBCR0, packet_size & 0xff);
285   Out_Byte(NE2K_RBCR1, (packet_size >> 8) & 0xff);
286
287   /* Set transmit byte count registers. */
288   Out_Byte(NE2K_TBCR0, packet_size & 0xff);
289   Out_Byte(NE2K_TBCR1, (packet_size >> 8) & 0xff);
290
291   Out_Byte(NE2K_RSAR0, 0x00);
292   Out_Byte(NE2K_RSAR1, TX_START_BUFF);
293
294   cr->rd = 0x02; /* Set remote DMA to write */
295   Out_Byte(NE2K_CR, regs->cr);
296
297   /* Destination Address */
298   Out_Word(NE2K_CR + 0x10, (dest[1] << 8) | dest[0]);
299   Out_Word(NE2K_CR + 0x10, (dest[3] << 8) | dest[2]);
300   Out_Word(NE2K_CR + 0x10, (dest[5] << 8) | dest[4]);
301
302   /* Source Address */
303   Out_Word(NE2K_CR + 0x10, (src[1] << 8) | src[0]);
304   Out_Word(NE2K_CR + 0x10, (src[3] << 8) | src[2]);
305   Out_Word(NE2K_CR + 0x10, (src[5] << 8) | src[4]);
306
307   /* Type */
308   Out_Word(NE2K_CR + 0x10, packet_size);
309
310   uint_t i;
311   for(i = 0; i < size; i += 2) {
312     Out_Word(NE2K_CR + 0x10, (*(data + i + 1) << 8) | *(data + i));
313   }
314
315   cr->txp = 0x1; /* Start transmission */
316   Out_Byte(NE2K_CR, regs->cr);
317
318   return 0;
319 }
320
321 int NE2K_Receive()
322 {
323   PrintBoth("Packet Received\n");
324
325   Out_Byte(NE2K_CR, 0x22);
326   /* Set RSAR to the start address of the received packet. */
327   Out_Byte(NE2K_RSAR0, next & 0xff);
328   Out_Byte(NE2K_RSAR1, next >> 8);
329   Out_Byte(NE2K_CR, 0x0a);
330
331   /* 
332    * A four byte header is added to the beginning of each received packet by the NIC.
333    * The first byte is the location of the next packet in the ring buffer.
334    * The second byte is the receive status code.
335    * The third and fourth bytes are the size of the packet.
336    */
337
338   uint_t i;
339   uint_t data;
340   PrintBoth("\nPacket data:\n\t");
341
342   data = In_Word(NE2K_CR + 0x10);
343   PrintBoth("%x ", data);
344
345   /* Get the location of the next packet */
346   next = data & 0xff00;
347
348   /* Retrieve the packet size from the header, and store it in RBCR. */
349   uint_t packet_size =  In_Word(NE2K_CR + 0x10) - 4;
350   uchar_t *packet = Malloc(packet_size);
351   Out_Byte(NE2K_RBCR0, packet_size & 0xff);
352   Out_Byte(NE2K_RBCR1, (packet_size>>8) & 0xff);
353
354 #if DEBUG
355         PrintBoth("packetsize = %x\n\t", packet_size);
356 #endif
357
358   /* Copy the received packet over from the ring buffer. */
359   for(i = 0; i < packet_size; i+=2) {
360     data = In_Word(NE2K_CR + 0x10);
361     *(packet + i) = data & 0x00ff;
362     *(packet + i + 1) = (data & 0xff00) >> 8;
363 #if 0
364     PrintBoth("BNRY = %x\n", In_Byte(NE2K_BNRY));
365     Out_Byte(NE2K_CR, 0x4a);
366     PrintBoth("CURR = %x\n", In_Byte(NE2K_CURR));  
367     Out_Byte(NE2K_CR, 0x0a);
368 #endif
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