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.


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