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.


5beb96798d8df310df9924ef20050b2eb1116485
[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 static uint_t received = 0;
8
9 struct _CR {  //COMMAND REG
10         uint_t stp: 1;  //STOP- software reset
11         uint_t sta: 1;  //START- activates NIC
12         uint_t txp: 1;  //TRANSMIT- set to send
13         uint_t rd:  3;  //REMOTE DMA
14         uint_t ps:  2;  //PAGE SELECT
15 };
16
17 struct _ISR{  //INTERRUPT STATUS REG
18         uint_t prx: 1;  //PACKET RECIEVED
19         uint_t ptx: 1;  //PACKET TRANSMITTED
20         uint_t rxe: 1;  //TRANSMIT ERROR
21         uint_t txe: 1;  //RECEIVE ERROR
22         uint_t ovw: 1;  //OVERWRITE WARNING
23         uint_t cnt: 1;  //COUNTER OVERFLOW
24         uint_t rdc: 1;  //REMOTE DMA COMPLETE
25         uint_t rst: 1;  //RESET STATUS
26 };
27
28 struct _IMR {  //INTERRUPT MASK REG
29         uint_t prxe: 1;  //PACKET RX INTRPT
30         uint_t ptxe: 1;  //PACKET TX INTRPT
31         uint_t rxee: 1;  //RX ERROR INTRPT
32         uint_t txee: 1;  //TX ERROR INTRPt
33         uint_t ovwe: 1;  //OVERWRITE WARNING INTRPT
34         uint_t cnte: 1;  //COUNTER OVERFLOW INTRPT
35         uint_t rdce: 1;  //DMA COMLETE INTRPT
36         uint_t rsvd: 1;
37 };
38
39 struct _DCR {  //DATA CONFIG REGISTER
40         uint_t wts: 1;  //WORD TRANSFER SELECT
41         uint_t bos: 1;  //BYTE ORDER SELECT
42         uint_t las: 1;  //LONG ADDR SELECT
43         uint_t ls:  1;  //LOOPBACK SELECT
44         uint_t arm: 1;  //AUTO-INITIALIZE REMOTE
45         uint_t ft:  2;  //FIFO THRESH SELECT
46 };
47
48 struct _TCR {  //TX CONFIG REGISTER
49         uint_t crc:  1;  //INHIBIT CRC
50         uint_t lb:   2;  //ENCODED LOOPBACK
51         uint_t atd:  1;  //AUTO TRANSMIT
52         uint_t ofst: 1;  //COLLISION OFFSET ENABLE
53         uint_t rsvd: 3;
54 };
55
56 struct _TSR {
57         uint_t ptx:  1;  //PACKET TX
58         uint_t rsvd: 1;
59         uint_t col:  1;  //TX COLLIDED
60         uint_t abt:  1;  //TX ABORTED
61         uint_t crs:  1;  //CARRIER SENSE LOST
62         uint_t fu:   1;  //FIFO UNDERRUN
63         uint_t cdh:  1;  //CD HEARTBEAT
64         uint_t owc:  1;  //OUT OF WINDOW COLLISION
65 };
66
67 struct _RCR {  //RECEIVE CONFIGURATION REGISTER
68         uint_t sep:  1;  //SAVE ERRORED PACKETS
69         uint_t ar:   1;  //ACCEPT RUNT PACKETS
70         uint_t ab:   1;  //ACCEPT BROADCAST
71         uint_t am:   1;  //ACCEPT MULTICAST
72         uint_t pro:  1;  //PROMISCUOUS PHYSICAL
73         uint_t mon:  1;  //MONITOR MODE
74         uint_t rsvd: 2;
75 };  
76
77 struct _RSR {  //RECEIVE STATUS REG
78         uint_t prx: 1;  //PACKET RX INTACT
79         uint_t crc: 1;  //CRC ERROR
80         uint_t fae: 1;  //FRAME ALIGNMENT ERROR
81         uint_t fo:  1;  //FIFO OVERRUN
82         uint_t mpa: 1;  //MISSED PACKET
83         uint_t phy: 1;  //PHYSICAL/MULTICAST ADDR
84         uint_t dis: 1;  //RX DISABLED
85         uint_t dfr: 1;  //DEFERRING
86 };
87
88
89 static void Dump_Registers()
90 {
91   uint_t data;
92
93   PrintBoth("Dumping NIC registers for page %x...\n", (In_Byte(NE2K_CR) & 0xc0) >> 6);
94   uint_t i = 0;
95   for(i = 0; i <= 0x0f; i += 0x01) {
96     data = In_Byte(NE2K_BASE_ADDR+i);
97     PrintBoth("\t%x: %x\n", NE2K_BASE_ADDR + i, data);
98   }
99 }
100
101 static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
102 {
103   Begin_IRQ(state);
104   PrintBoth("NIC Interrupt Occured!\n");
105   uint_t isr_content = In_Byte(NE2K_ISR);
106   PrintBoth("Contents of ISR: %x\n", isr_content);
107   if(In_Byte(NE2K_ISR) & 0x01)
108     NE2K_Receive();
109
110   Out_Byte(NE2K_ISR, 0xff);
111   End_IRQ(state);
112 }
113
114
115 int Init_Ne2k()
116 {
117
118 uint_t CR_START_VAL = 0x21;
119 static const uint_t DCR_START_VAL = 0x49;
120 static const uint_t ISR_START_VAL = 0xff;
121 static const uint_t RCR_START_VAL = 0x20;
122 static const uint_t TCR_START_VAL = 0x02;
123 //static const uint_t IMR_START_VAL = 0x00;
124 PrintBoth("location Startval first = %x\n", &CR_START_VAL);
125
126   PrintBoth("Initializing network card...\n");
127
128   struct NE2K_REGS* regs = Malloc(sizeof(struct NE2K_REGS));
129
130   regs->cr = (struct _CR*)&CR_START_VAL;
131   regs->dcr = (struct _DCR*)&DCR_START_VAL;
132   regs->isr = (struct _ISR*)&ISR_START_VAL;
133   regs->rcr = (struct _RCR*)&RCR_START_VAL;
134   regs->tcr = (struct _TCR*)&TCR_START_VAL;
135
136   Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
137   Out_Byte(NE2K_DCR, *(uint_t *)regs->dcr);
138   Out_Byte(NE2K_ISR, *(uint_t *)regs->isr);
139   Out_Byte(NE2K_RCR, *(uint_t *)regs->rcr);
140   Out_Byte(NE2K_TCR, *(uint_t *)regs->tcr);
141   Out_Byte(NE2K_IMR, *(uint_t *)regs->imr);
142   Out_Byte(NE2K_RBCR0, 0x00);
143   Out_Byte(NE2K_RBCR1, 0x00);
144   Out_Byte(NE2K_RSAR0, 0x00);
145   Out_Byte(NE2K_RSAR1, 0x00);
146
147   Out_Byte(NE2K_TPSR, 0x40);      // Set TPSR
148   Out_Byte(NE2K_PSTART, 0x42);    // Set PSTART
149   Out_Byte(NE2K_BNRY, 0x59);      // Set BNRY
150   Out_Byte(NE2K_PSTOP, 0x60);     // Set PSTOP
151
152   Out_Byte(NE2K_ISR, *(uint_t *)regs->isr);
153
154   regs->imr->prxe = 0x1;
155   regs->imr->ptxe = 0x1;
156   regs->imr->rxee = 0x1;
157   regs->imr->txee = 0x1;
158   regs->imr->ovwe = 0x1;
159   regs->imr->cnte = 0x1;
160   Out_Byte(NE2K_IMR, *(uint_t *)regs->imr);
161
162   regs->cr->ps = 0x01;  //switch to reg page 1
163   Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
164
165 PrintBoth("Startval 2= %x\n", CR_START_VAL);
166
167 PrintBoth("regs locat = %x\n", (uint_t *)regs->cr);
168 PrintBoth("regs = %x\n", *(uint_t *)regs->cr);
169
170   /* Set the physical address of the card to 52:54:00:12:34:58 */
171   Out_Byte(NE2K_CR+0x01, 0x52);
172   Out_Byte(NE2K_CR+0x02, 0x54);
173   Out_Byte(NE2K_CR+0x03, 0x00);
174   Out_Byte(NE2K_CR+0x04, 0x12);
175   Out_Byte(NE2K_CR+0x05, 0x34);
176   Out_Byte(NE2K_CR+0x06, 0x58);
177
178   uint_t i;
179   for(i = 0x08; i <= 0x0f; i++) {
180     Out_Byte(NE2K_CR+i, 0xff);
181   }
182
183   *(uint_t *)regs->cr = 0x21;  //set CR to start value
184   Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
185
186 PrintBoth("startval 3 = %x\n", CR_START_VAL); 
187 PrintBoth("location Startval 2 = %x\n", &CR_START_VAL);
188 PrintBoth("regs = %x\n", (uint_t *)regs->cr);
189
190   regs->tcr = 0x00;
191   Out_Byte(NE2K_TCR, *(uint_t *)regs->tcr);
192
193   regs->rcr->sep = 0x1;
194   regs->rcr->ar = 0x1;
195   regs->rcr->ab = 0x1;
196   regs->rcr->am = 0x1;
197   regs->rcr->pro = 0x1; //promiscuous mode, accept all packets
198   regs->rcr->mon = 0x0;
199   Out_Byte(NE2K_RCR, *(uint_t *)regs->rcr);
200
201   regs->cr->sta = 0x1;  //toggle start bit
202   regs->cr->stp = 0x0;
203   Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
204   
205   Dump_Registers();
206
207   Out_Byte(NE2K_CR, (*(uint_t *)regs->cr & 0x3f) | NE2K_PAGE1);
208   Dump_Registers();
209
210   Out_Byte(NE2K_CR, (*(uint_t *)regs->cr & 0x3f) | NE2K_PAGE2);
211   Dump_Registers();
212
213   // Reset?
214   Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f));
215
216   Install_IRQ(NE2K_IRQ, NE2K_Interrupt_Handler);
217   Enable_IRQ(NE2K_IRQ);
218
219   for(i = 0; i < 4; i++)
220   {
221     NE2K_Transmit(regs);
222     PrintBoth("Transmitting a packet\n");
223   }
224
225   return 0;
226 }
227 int NE2K_Transmit(struct NE2K_REGS *regs)
228 {
229   uint_t packet_size = 80;
230   *(uint_t *)regs->cr = 0x21;
231   regs->cr->stp = 0x0;  //toggle start on
232   regs->cr->sta = 0x1;
233   Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
234   
235   // Read-before-write bug fix?
236   Out_Byte(NE2K_RBCR0, 0x42);
237   Out_Byte(NE2K_RBCR1, 0x00);
238   Out_Byte(NE2K_RSAR0, 0x42);
239   Out_Byte(NE2K_RSAR1, 0x00);
240
241   regs->cr->rd = 0x01;  //set remote DMA to 'remote read'
242   Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
243
244   *(uint_t*)regs->isr = 0x40;  //clear and set Remote DMA high
245   Out_Byte(NE2K_ISR, *(uint_t *)regs->isr);
246   
247   Out_Byte(NE2K_RBCR0, packet_size);
248   Out_Byte(NE2K_RBCR1, 0x00);
249
250   Out_Byte(NE2K_TBCR0, packet_size);
251   Out_Byte(NE2K_TBCR1, 0x00);
252
253   Out_Byte(NE2K_RSAR0, 0x00);
254   Out_Byte(NE2K_RSAR1, 0x40);
255
256   *(uint_t*)regs->cr = 0x16;
257   Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
258   
259   /* Begin pushing the packet into the dataport (located at 0x10 from the base address) */
260   /* Destination address = 52:54:00:12:34:56 */
261   Out_Word(NE2K_CR+0x10, 0x5452);
262   Out_Word(NE2K_CR+0x10, 0x1200);
263   Out_Word(NE2K_CR+0x10, 0x5634);
264
265   /* Source address = 52:54:00:12:34:58 */
266   Out_Word(NE2K_CR+0x10, 0x5452);
267   Out_Word(NE2K_CR+0x10, 0x1200);
268   Out_Word(NE2K_CR+0x10, 0x5834);
269
270   /* Type length and data; currently random data */
271   uint_t i;
272   uint_t n = 0;
273   for(i = 1; i <= packet_size/2-12; i++, n+=2) {
274     //Out_Word(NE2K_CR+0x10, 0x0f0b);
275     Out_Word(NE2K_CR+0x10, (n<<8) | (n+1));
276   }
277
278   Out_Byte(NE2K_ISR, 0x40);
279
280   return 0;
281 }
282
283 int NE2K_Receive()
284 {
285   PrintBoth("Packet Received\n");
286
287   uint_t packet_size = 80;
288
289   Out_Byte(NE2K_CR, 0x22);
290   Out_Byte(NE2K_RBCR0, packet_size);
291   Out_Byte(NE2K_RBCR1, 0x00);
292 //  Out_Byte(NE2K_RSAR0, 0x42);
293     Out_Byte(NE2K_RSAR0, 0x4c);
294   Out_Byte(NE2K_RSAR1, 0x00);
295   Out_Byte(NE2K_CR, 0x0a);
296
297   uint_t i;
298   uint_t data;
299   PrintBoth("\nPacket data:\n\t");
300
301   for(i = 0; i < packet_size; i+=2) {
302     data = In_Word(NE2K_CR + 0x10);
303     PrintBoth("%x ", data);
304     if(!(i%10))
305       PrintBoth("\n\t");
306   }
307
308   PrintBoth("\n%d packets have been received", ++received);
309   PrintBoth("\n\n");
310
311   Out_Byte(NE2K_ISR, 0x40);
312
313   return 0;
314 }
315
316
317 //int NE2K_Ringbuff_Overflow(){
318         
319