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.


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