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.


Added callbacks to allow functios at a higher level to receive packets.
[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   }
113
114   End_IRQ(state);
115   if(isr_content & 0x02) /* A packet has been successfully transmitted. */
116   {
117     send_done = 1;  
118     Out_Byte(NE2K_ISR, 0x02);
119   }
120   Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts. */
121 }
122
123 int Init_Ne2k(int (*rcvd_fn)(struct NE2K_Packet_Info *info, uchar_t *packet))
124 {
125   callbacks.packet_received = rcvd_fn;
126
127   PrintBoth("Initializing network card...\n");
128   Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f));  /* Reset? */
129
130   struct NE2K_REGS* regs = Malloc(sizeof(struct NE2K_REGS));
131   struct _CR * cr = (struct _CR *)&(regs->cr);
132   struct _RCR * rcr = (struct _RCR*)&(regs->rcr);
133   struct _IMR * imr = (struct _IMR *)&(regs->imr);
134
135   regs->cr = 0x21;
136   regs->dcr = 0x49; /* Word-wide DMA transfer. */
137   regs->isr = 0xff; /* Clear all interrupts. */
138   regs->rcr = 0x20; /* Accept packets shorter than 64 bytes. */
139   regs->tcr = 0x02; /* Internal loopback mode. */
140
141   Out_Byte(NE2K_CR, regs->cr);
142   Out_Byte(NE2K_DCR, regs->dcr);
143   Out_Byte(NE2K_ISR, regs->isr);
144   Out_Byte(NE2K_RCR, regs->rcr);
145   Out_Byte(NE2K_TCR, regs->tcr);
146   Out_Byte(NE2K_IMR, regs->imr);
147
148   /* Remote byte count registers. */
149   Out_Byte(NE2K_RBCR0, 0x00);
150   Out_Byte(NE2K_RBCR1, 0x00);
151   /* Remote start address registers. */
152   Out_Byte(NE2K_RSAR0, 0x00);
153   Out_Byte(NE2K_RSAR1, 0x00);
154
155   Out_Byte(NE2K_TPSR, TX_START_BUFF);           /* Transmit page start register */
156   Out_Byte(NE2K_PSTART, RX_START_BUFF);         /* Page start register */
157   Out_Byte(NE2K_PSTOP, RX_END_BUFF);                    /* Page stop register */
158   Out_Byte(NE2K_BNRY, RX_START_BUFF);           /* Boundary register */ 
159
160   cr->ps = 0x01; /* Switch to reg page 1. */
161   Out_Byte(NE2K_CR, regs->cr);
162   /* Current page register: points to first free page that can be used for packet reception. */
163   Out_Byte(NE2K_CURR, RX_START_BUFF);
164   cr->ps = 0x00; /* Switch to page 0 */
165
166   Out_Byte(NE2K_CR, regs->cr);
167   Out_Byte(NE2K_ISR, regs->isr);
168
169   /* Interrupt mask register: setting a bit to 1 enables the
170      corresponding interrupt in ISR. */
171   imr->prxe = 0x1;
172   imr->ptxe = 0x1;
173   imr->rxee = 0x1;
174   imr->txee = 0x1;
175   imr->ovwe = 0x1;
176   imr->cnte = 0x1;
177   Out_Byte(NE2K_IMR, regs->imr);
178
179   cr->ps = 0x01;  /* Switch to reg page 1 */
180   Out_Byte(NE2K_CR, regs->cr);
181
182   /* Set the physical address of the card to 52:54:00:12:34:58 */
183   Out_Byte(NE2K_CR+0x01, 0x52);
184   Out_Byte(NE2K_CR+0x02, 0x54);
185   Out_Byte(NE2K_CR+0x03, 0x00);
186   Out_Byte(NE2K_CR+0x04, 0x12);
187   Out_Byte(NE2K_CR+0x05, 0x34);
188   Out_Byte(NE2K_CR+0x06, 0x58);
189
190   /* Set the multicast address register to all 1s; accepts all multicast packets */
191   uint_t i;
192   for(i = 0x08; i <= 0x0f; i++) {
193     Out_Byte(NE2K_CR+i, 0xff);
194   }
195
196   regs->cr = 0x21;  //set CR to start value
197   Out_Byte(NE2K_CR, regs->cr);
198
199   regs->tcr = 0x00;
200   Out_Byte(NE2K_TCR, regs->tcr);
201
202   rcr->sep = 0x1;
203   rcr->ar = 0x1;
204   rcr->ab = 0x1;
205   rcr->am = 0x1;
206   rcr->pro = 0x1; /* Promiscuous mode: accept all packets. */
207   rcr->mon = 0x0;
208   Out_Byte(NE2K_RCR, regs->rcr);
209
210   cr->sta = 0x1;  // toggle start bit
211   cr->stp = 0x0;
212   Out_Byte(NE2K_CR, regs->cr);
213   
214   Dump_Registers();
215
216   cr->ps = NE2K_PAGE1;
217   Out_Byte(NE2K_CR, regs->cr);
218   Dump_Registers();
219
220   cr->ps = NE2K_PAGE2;  
221   Out_Byte(NE2K_CR, regs->cr);
222   Dump_Registers();
223
224   cr->ps = NE2K_PAGE0;
225   Out_Byte(NE2K_CR, regs->cr);
226
227   Install_IRQ(NE2K_IRQ, NE2K_Interrupt_Handler);
228   Enable_IRQ(NE2K_IRQ);
229
230   for(i = 0; i < 0; i++)
231   {
232     NE2K_Transmit(regs);
233     PrintBoth("Transmitting a packet\n");
234   }
235
236   uchar_t src_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x58 };
237   uchar_t dest_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 };
238
239   uint_t size = 64;
240   uchar_t *data = Malloc(size);
241   data = "This is a 64-byte string that will be used to test transmission.";
242
243   for(i = 0; i < 0; i++) {
244     NE2K_Send(regs, src_addr, dest_addr, 0x01, data, size);
245   }
246
247   //Free(data);  // Why does this crash?
248
249   return 0;
250 }
251
252 /* Assumes src and dest are arrays of 6 characters. */
253 int NE2K_Send(struct NE2K_REGS *regs, uchar_t src[], uchar_t dest[], uint_t type, uchar_t *data, uint_t size)
254 {
255   struct _CR * cr = (struct _CR*)&(regs->cr);
256   uint_t packet_size = size + 16;
257   regs->cr = 0x21;
258   cr->stp = 0x0;  //toggle start on
259   cr->sta = 0x1;
260   Out_Byte(NE2K_CR, regs->cr);
261   
262   // Read-before-write bug fix?
263   Out_Byte(NE2K_RBCR0, 0x42);
264   Out_Byte(NE2K_RBCR1, 0x00);
265   Out_Byte(NE2K_RSAR0, 0x42);
266   Out_Byte(NE2K_RSAR1, 0x00);
267
268   cr->rd = 0x01;  // set remote DMA to 'remote read'
269   Out_Byte(NE2K_CR, regs->cr);
270
271   regs->isr = 0x40;  // clear and set Remote DMA high
272   Out_Byte(NE2K_ISR, regs->isr);
273   
274   /* Set remote byte count registers */
275   Out_Byte(NE2K_RBCR0, packet_size & 0xff);
276   Out_Byte(NE2K_RBCR1, (packet_size >> 8) & 0xff);
277
278   /* Set transmit byte count registers. */
279   Out_Byte(NE2K_TBCR0, packet_size & 0xff);
280   Out_Byte(NE2K_TBCR1, (packet_size >> 8) & 0xff);
281
282   Out_Byte(NE2K_RSAR0, 0x00);
283   Out_Byte(NE2K_RSAR1, TX_START_BUFF);
284
285   regs->cr = 0x16;
286   Out_Byte(NE2K_CR, regs->cr);
287
288   /* Destination Address */
289   Out_Word(NE2K_CR + 0x10, (dest[1] << 8) | dest[0]);
290   Out_Word(NE2K_CR + 0x10, (dest[3] << 8) | dest[2]);
291   Out_Word(NE2K_CR + 0x10, (dest[5] << 8) | dest[4]);
292
293   /* Source Address */
294   Out_Word(NE2K_CR + 0x10, (src[1] << 8) | src[0]);
295   Out_Word(NE2K_CR + 0x10, (src[3] << 8) | src[2]);
296   Out_Word(NE2K_CR + 0x10, (src[5] << 8) | src[4]);
297
298   /* Type */
299   Out_Word(NE2K_CR + 0x10, packet_size);
300
301   uint_t i;
302   for(i = 0; i < size; i += 2) {
303     Out_Word(NE2K_CR + 0x10, (*(data + i + 1) << 8) | *(data + i));
304   }
305
306   return 0;
307 }
308
309 int NE2K_Receive()
310 {
311   PrintBoth("Packet Received\n");
312
313   Out_Byte(NE2K_CR, 0x22);
314   /* Set RSAR to the start address of the received packet. */
315   Out_Byte(NE2K_RSAR0, next & 0xff);
316   Out_Byte(NE2K_RSAR1, next >> 8);
317   Out_Byte(NE2K_CR, 0x0a);
318
319   /* 
320    * A four byte header is added to the beginning of each received packet by the NIC.
321    * The first byte is the location of the next packet in the ring buffer.
322    * The second byte is the receive status code.
323    * The third and fourth bytes are the size of the packet.
324    */
325
326   uint_t i;
327   uint_t data;
328   PrintBoth("\nPacket data:\n\t");
329
330   data = In_Word(NE2K_CR + 0x10);
331   PrintBoth("%x ", data);
332
333   /* Get the location of the next packet */
334   next = data & 0xff00;
335
336   /* Retrieve the packet size from the header, and store it in RBCR. */
337   uint_t packet_size =  In_Word(NE2K_CR + 0x10) - 4;
338   uchar_t *packet = Malloc(packet_size);
339   Out_Byte(NE2K_RBCR0, packet_size & 0xff);
340   Out_Byte(NE2K_RBCR1, (packet_size>>8) & 0xff);
341
342 #if DEBUG
343         PrintBoth("packetsize = %x\n\t", packet_size);
344 #endif
345
346   /* Copy the received packet over from the ring buffer. */
347   for(i = 0; i < packet_size; i+=2) {
348     data = In_Word(NE2K_CR + 0x10);
349     //PrintBoth("%x ", data);
350     *(packet + i) = data & 0x00ff;
351     *(packet + i + 1) = (data & 0xff00) >> 8;
352 #if 0
353     PrintBoth("BNRY = %x\n", In_Byte(NE2K_BNRY));
354     Out_Byte(NE2K_CR, 0x4a);
355     PrintBoth("CURR = %x\n", In_Byte(NE2K_CURR));  
356     Out_Byte(NE2K_CR, 0x0a);
357 #endif
358
359     //if(!(i%10))
360       //PrintBoth("\n\t");
361   }
362
363 //Out_Byte(NE2K_RBCR0, (In_Byte(NE2K_RBCR0))-2);
364 //Out_Byte(NE2K_RSAR0, (In_Byte(NE2K_RSAR0))+2);
365
366   PrintBoth("\n%d packets have been received", ++received);
367   PrintBoth("\n\n");
368
369   Out_Byte(NE2K_ISR, 0x40); /* Clear the remote DMA complete interrupt. */
370
371   /* The BNRY register stores the location of the first packet that hasn't been read yet */
372   Out_Byte(NE2K_BNRY, next >> 8);
373
374   struct NE2K_Packet_Info *info = Malloc(sizeof(struct NE2K_Packet_Info));
375   info->size = packet_size;
376   info->status = 0;
377   memcpy(info->dest, packet, 6);
378   memcpy(info->src, packet + 6, 6);
379   callbacks.packet_received(info, packet);
380
381   return 0;
382 }
383
384
385
386