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.


Version that automatically checks RX packet size. Still receives multiple instances...
[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
7 #define DEBUG 1
8 #define RX_START_BUFF 0x4c
9
10 static uint_t received = 0;
11 static uint_t send_done = 1;
12 uint_t next = (RX_START_BUFF<<8);
13
14 static void Dump_Registers()
15 {
16   uint_t data;
17   PrintBoth("Dumping NIC registers for page %x...\n", (In_Byte(NE2K_CR) & 0xc0) >> 6);
18   uint_t i = 0;
19   for(i = 0; i <= 0x0f; i += 0x01) {
20     data = In_Byte(NE2K_BASE_ADDR+i);
21     PrintBoth("\t%x: %x\n", NE2K_BASE_ADDR + i, data);
22   }
23 }
24
25 static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
26 {
27   Begin_IRQ(state);
28   PrintBoth("NIC Interrupt Occured!\n");
29   uchar_t isr_content = In_Byte(NE2K_ISR);
30  // Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts */
31
32   PrintBoth("Contents of ISR: %x\n", isr_content);
33   if(isr_content & 0x01)
34     {
35         NE2K_Receive();
36         Out_Byte(NE2K_ISR, 0x01);
37 }
38
39   End_IRQ(state);
40   if(isr_content & 0x02)
41     send_done = 1;  
42
43 }
44
45 int Init_Ne2k()
46 {
47   PrintBoth("Initializing network card...\n");
48   Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f));  /* Reset? */
49
50   struct NE2K_REGS* regs = Malloc(sizeof(struct NE2K_REGS));
51   struct _CR * cr = (struct _CR *)&(regs->cr);
52   struct _RCR * rcr = (struct _RCR*)&(regs->rcr);
53   struct _IMR * imr = (struct _IMR *)&(regs->imr);
54
55   regs->cr = 0x21;
56   regs->dcr = 0x49;
57   regs->isr = 0xff;
58   regs->rcr = 0x20;
59   regs->tcr = 0x02;
60
61   Out_Byte(NE2K_CR, regs->cr);
62   Out_Byte(NE2K_DCR, regs->dcr);
63   Out_Byte(NE2K_ISR, regs->isr);
64   Out_Byte(NE2K_RCR, regs->rcr);
65   Out_Byte(NE2K_TCR, regs->tcr);
66   Out_Byte(NE2K_IMR, regs->imr);
67
68   Out_Byte(NE2K_RBCR0, 0x00);
69   Out_Byte(NE2K_RBCR1, 0x00);
70   Out_Byte(NE2K_RSAR0, 0x00);
71   Out_Byte(NE2K_RSAR1, 0x00);
72
73   Out_Byte(NE2K_TPSR, 0x40);      // Set TPSR
74   Out_Byte(NE2K_PSTART, RX_START_BUFF);    // Set PSTART
75   Out_Byte(NE2K_BNRY, 0x59);      // Set BNRY
76   Out_Byte(NE2K_PSTOP, 0x80);     // Set PSTOP
77
78   cr->ps = 0x01;  //switch to reg page 1
79   Out_Byte(NE2K_CR, regs->cr);
80   Out_Byte(NE2K_CURR, RX_START_BUFF);
81   cr->ps = 0x00;
82
83   Out_Byte(NE2K_CR, regs->cr);
84   Out_Byte(NE2K_BNRY, RX_START_BUFF);
85
86   Out_Byte(NE2K_ISR, regs->isr);
87
88   imr->prxe = 0x1;
89   imr->ptxe = 0x1;
90   imr->rxee = 0x1;
91   imr->txee = 0x1;
92   imr->ovwe = 0x1;
93   imr->cnte = 0x1;
94   Out_Byte(NE2K_IMR, regs->imr);
95
96   cr->ps = 0x01;  //switch to reg page 1
97   Out_Byte(NE2K_CR, regs->cr);
98
99   /* Set the physical address of the card to 52:54:00:12:34:58 */
100   Out_Byte(NE2K_CR+0x01, 0x52);
101   Out_Byte(NE2K_CR+0x02, 0x54);
102   Out_Byte(NE2K_CR+0x03, 0x00);
103   Out_Byte(NE2K_CR+0x04, 0x12);
104   Out_Byte(NE2K_CR+0x05, 0x34);
105   Out_Byte(NE2K_CR+0x06, 0x58);
106
107   /* Accept all multicast packets */
108   uint_t i;
109   for(i = 0x08; i <= 0x0f; i++) {
110     Out_Byte(NE2K_CR+i, 0xff);
111   }
112
113   regs->cr = 0x21;  //set CR to start value
114   Out_Byte(NE2K_CR, regs->cr);
115
116   regs->tcr = 0x00;
117   Out_Byte(NE2K_TCR, regs->tcr);
118
119   rcr->sep = 0x1;
120   rcr->ar = 0x1;
121   rcr->ab = 0x1;
122   rcr->am = 0x1;
123   rcr->pro = 0x1; // promiscuous mode, accept all packets
124   rcr->mon = 0x0;
125   Out_Byte(NE2K_RCR, regs->rcr);
126
127   cr->sta = 0x1;  // toggle start bit
128   cr->stp = 0x0;
129   Out_Byte(NE2K_CR, regs->cr);
130   
131   Dump_Registers();
132
133   cr->ps = NE2K_PAGE1;
134   Out_Byte(NE2K_CR, regs->cr);
135   Dump_Registers();
136
137   cr->ps = NE2K_PAGE2;  
138   Out_Byte(NE2K_CR, regs->cr);
139   Dump_Registers();
140
141   cr->ps = NE2K_PAGE0;
142   Out_Byte(NE2K_CR, regs->cr);
143
144   // Reset?
145 //  Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f));
146
147   Install_IRQ(NE2K_IRQ, NE2K_Interrupt_Handler);
148   Enable_IRQ(NE2K_IRQ);
149 /*
150   for(i = 0; i < 1; i++)
151   {
152     NE2K_Transmit(regs);
153     PrintBoth("Transmitting a packet\n");
154   }
155 */  
156   return 0;
157 }
158
159 int NE2K_Transmit(struct NE2K_REGS *regs)
160 {
161   while(!send_done);
162   send_done = 0;
163
164   struct _CR * cr = (struct _CR*)&(regs->cr);
165   uint_t packet_size = 80;
166   regs->cr = 0x21;
167   cr->stp = 0x0;  //toggle start on
168   cr->sta = 0x1;
169   Out_Byte(NE2K_CR, regs->cr);
170   
171   // Read-before-write bug fix?
172   Out_Byte(NE2K_RBCR0, 0x42);
173   Out_Byte(NE2K_RBCR1, 0x00);
174   Out_Byte(NE2K_RSAR0, 0x42);
175   Out_Byte(NE2K_RSAR1, 0x00);
176
177   cr->rd = 0x01;  // set remote DMA to 'remote read'
178   Out_Byte(NE2K_CR, regs->cr);
179
180   regs->isr = 0x40;  // clear and set Remote DMA high
181   Out_Byte(NE2K_ISR, regs->isr);
182   
183   Out_Byte(NE2K_RBCR0, packet_size);
184   Out_Byte(NE2K_RBCR1, 0x00);
185
186   Out_Byte(NE2K_TBCR0, packet_size);
187   Out_Byte(NE2K_TBCR1, 0x00);
188
189   Out_Byte(NE2K_RSAR0, 0x00);
190   Out_Byte(NE2K_RSAR1, 0x40);
191
192   regs->cr = 0x16;
193   Out_Byte(NE2K_CR, regs->cr);
194
195   /* Begin pushing the packet into the dataport (located at 0x10 from the base address) */
196   /* Destination address = 52:54:00:12:34:56 */
197   Out_Word(NE2K_CR+0x10, 0x5452);
198   Out_Word(NE2K_CR+0x10, 0x1200);
199   Out_Word(NE2K_CR+0x10, 0x5634);
200
201   /* Source address = 52:54:00:12:34:58 */
202   Out_Word(NE2K_CR+0x10, 0x5452);
203   Out_Word(NE2K_CR+0x10, 0x1200);
204   Out_Word(NE2K_CR+0x10, 0x5834);
205
206   /* Type length and data; currently random data */
207   uint_t i;
208   uint_t n = 0;
209   for(i = 1; i <= packet_size/2-12; i++, n+=2) {
210     //Out_Word(NE2K_CR+0x10, 0x0f0b);
211     Out_Word(NE2K_CR+0x10, (n<<8) | (n+1));
212   }
213
214   //regs->isr = 0x40;
215   //Out_Byte(NE2K_ISR, regs->isr); /* Do we need this here? */
216
217   return 0;
218 }
219
220 int NE2K_Receive()
221 {
222   PrintBoth("Packet Received\n");
223
224 //  uint_t packet_size = 80;
225
226   Out_Byte(NE2K_CR, 0x22);
227
228   Out_Byte(NE2K_RBCR1, 0x00); 
229 //  Out_Byte(NE2K_RBCR0, 0x60);
230   
231 //  Out_Byte(NE2K_RSAR0, 0x42);
232   Out_Byte(NE2K_RSAR1, next >> 8);
233   Out_Byte(NE2K_RSAR0, next & 0xff);
234   Out_Byte(NE2K_CR, 0x0a);
235
236   uint_t i;
237   uint_t data;
238   PrintBoth("\nPacket data:\n\t");
239
240   data = In_Word(NE2K_CR + 0x10);
241   PrintBoth("%x ", data);
242
243   /* The first byte is the page number where the next packet in the ring buffer is stored */
244   next = data & 0xff00;
245
246   uint_t packet_size =  In_Word(NE2K_CR + 0x10) - 4;
247   Out_Byte(NE2K_RBCR0, packet_size & 0xff);
248   Out_Byte(NE2K_RBCR1, (packet_size>>8) & 0xff);
249
250 #if DEBUG
251         PrintBoth("packetsize = %x\n\t", packet_size);
252 #endif
253
254   for(i = 2; i < packet_size; i+=2) {
255     data = In_Word(NE2K_CR + 0x10);
256     PrintBoth("%x ", data);
257     
258 #if 0
259     PrintBoth("BNRY = %x\n", In_Byte(NE2K_BNRY));
260     Out_Byte(NE2K_CR, 0x4a);
261     PrintBoth("CURR = %x\n", In_Byte(NE2K_CURR));  
262     Out_Byte(NE2K_CR, 0x0a);
263 #endif
264
265     if(!(i%10))
266       PrintBoth("\n\t");
267   }
268
269 //Out_Byte(NE2K_RBCR0, (In_Byte(NE2K_RBCR0))-2);
270 //Out_Byte(NE2K_RSAR0, (In_Byte(NE2K_RSAR0))+2);
271
272   PrintBoth("\n%d packets have been received", ++received);
273   PrintBoth("\n\n");
274
275   Out_Byte(NE2K_ISR, 0x40);
276
277   /* The BNRY register stores the location of the first packet that hasn't been read yet */
278   Out_Byte(NE2K_BNRY, next >> 8);
279
280   return 0;
281 }
282