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.


*** empty log message ***
[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 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 'remote DMA complete' interrupt */
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   /* Set remote start address registers to the first page of the transmit ring buffer. */
292   Out_Byte(NE2K_RSAR0, 0x00);
293   Out_Byte(NE2K_RSAR1, TX_START_BUFF);
294
295   cr->rd = 0x02; /* Set remote DMA to 'remote write' */
296   Out_Byte(NE2K_CR, regs->cr);
297
298   /* Begin pushing the packet into the dataport (located at 0x10 from the base address). */
299   /* Destination Address */
300   Out_Word(NE2K_CR + 0x10, (dest[1] << 8) | dest[0]);
301   Out_Word(NE2K_CR + 0x10, (dest[3] << 8) | dest[2]);
302   Out_Word(NE2K_CR + 0x10, (dest[5] << 8) | dest[4]);
303
304   /* Source Address */
305   Out_Word(NE2K_CR + 0x10, (src[1] << 8) | src[0]);
306   Out_Word(NE2K_CR + 0x10, (src[3] << 8) | src[2]);
307   Out_Word(NE2K_CR + 0x10, (src[5] << 8) | src[4]);
308
309   /* Type */
310   Out_Word(NE2K_CR + 0x10, packet_size);
311
312   /* Packet data */
313   uint_t i;
314   for(i = 0; i < size; i += 2) {
315     Out_Word(NE2K_CR + 0x10, (*(data + i + 1) << 8) | *(data + i));
316   }
317
318   cr->txp = 0x1; /* Start transmission */
319   Out_Byte(NE2K_CR, regs->cr);
320
321   return 0;
322 }
323
324 int NE2K_Receive()
325 {
326   PrintBoth("Packet Received\n");
327
328   Out_Byte(NE2K_CR, 0x22);
329   /* Set RSAR to the start address of the received packet. */
330   Out_Byte(NE2K_RSAR0, next & 0xff);
331   Out_Byte(NE2K_RSAR1, next >> 8);
332   Out_Byte(NE2K_CR, 0x0a);
333
334   /* 
335    * A four byte header is added to the beginning of each received packet by the NIC.
336    * The first byte is the location of the next packet in the ring buffer.
337    * The second byte is the receive status code.
338    * The third and fourth bytes are the size of the packet.
339    */
340
341   uint_t i;
342   uint_t data;
343   data = In_Word(NE2K_CR + 0x10);
344
345 #if DEBUG
346   PrintBoth("\nPacket data:\n\t");
347   PrintBoth("%x ", data);
348 #endif
349
350   /* Get the location of the next packet */
351   next = data & 0xff00;
352
353   /* Retrieve the packet size from the header, and store it in RBCR. */
354   uint_t packet_size =  In_Word(NE2K_CR + 0x10) - 4;
355   uchar_t *packet = Malloc(packet_size);
356   Out_Byte(NE2K_RBCR0, packet_size & 0xff);
357   Out_Byte(NE2K_RBCR1, (packet_size>>8) & 0xff);
358
359 #if DEBUG
360         PrintBoth("packetsize = %x\n\t", packet_size);
361 #endif
362
363   /* Copy the received packet over from the ring buffer. */
364   for(i = 0; i < packet_size; i+=2) {
365     data = In_Word(NE2K_CR + 0x10);
366     *(packet + i) = data & 0x00ff;
367     *(packet + i + 1) = (data & 0xff00) >> 8;
368 #if 0
369     PrintBoth("BNRY = %x\n", In_Byte(NE2K_BNRY));
370     Out_Byte(NE2K_CR, 0x4a);
371     PrintBoth("CURR = %x\n", In_Byte(NE2K_CURR));  
372     Out_Byte(NE2K_CR, 0x0a);
373 #endif
374   }
375
376 //Out_Byte(NE2K_RBCR0, (In_Byte(NE2K_RBCR0))-2);
377 //Out_Byte(NE2K_RSAR0, (In_Byte(NE2K_RSAR0))+2);
378
379   PrintBoth("\n%d packets have been received", ++received);
380   PrintBoth("\n\n");
381
382   Out_Byte(NE2K_ISR, 0x40); /* Clear the remote DMA complete interrupt. */
383
384   /* The BNRY register stores the location of the first packet that hasn't been read yet */
385   Out_Byte(NE2K_BNRY, next >> 8);
386
387   struct NE2K_Packet_Info *info = Malloc(sizeof(struct NE2K_Packet_Info));
388   info->size = packet_size;
389   info->status = 0;
390   memcpy(info->dest, packet, 6);
391   memcpy(info->src, packet + 6, 6);
392   callbacks.packet_received(info, packet);
393
394   return 0;
395 }
396
397
398
399