xref: /minix/minix/drivers/net/dec21140A/dec21140A.c (revision 9f988b79)
1 /*
2  * dec21041.c
3  *
4  * This file contains an ethernet device driver for DEC  21140A
5  * fast ethernet controllers as emulated by VirtualPC 2007. It is not
6  * intended to support the real card, as much more error checking
7  * and testing would be needed. It supports both bridged and NAT mode.
8  *
9  * Created:	Mar 2008 by Nicolas Tittley <first.last@ google's mail>
10  */
11 
12 #include <minix/drivers.h>
13 #include <minix/netdriver.h>
14 
15 #include <machine/pci.h>
16 #include <assert.h>
17 
18 #include "dec21140A.h"
19 
20 static u32_t io_inl(u16_t);
21 static void io_outl(u16_t, u32_t);
22 
23 static int do_init(unsigned int, ether_addr_t *);
24 static void do_stop(void);
25 static int do_send(struct netdriver_data *, size_t);
26 static ssize_t do_recv(struct netdriver_data *, size_t);
27 static void do_stat(eth_stat_t *);
28 static void do_intr(unsigned int);
29 
30 static int de_probe(dpeth_t *, unsigned int skip);
31 static void de_conf_addr(dpeth_t *, ether_addr_t *);
32 static void de_init_buf(dpeth_t *);
33 static void de_reset(const dpeth_t *);
34 static void de_hw_conf(const dpeth_t *);
35 static void de_start(const dpeth_t *);
36 static void de_setup_frame(const dpeth_t *, const ether_addr_t *);
37 static u16_t de_read_rom(const dpeth_t *, u8_t, u8_t);
38 
39 static dpeth_t de_state;
40 static int de_instance;
41 
42 static const struct netdriver de_table = {
43 	.ndr_init	= do_init,
44 	.ndr_stop	= do_stop,
45 	.ndr_recv	= do_recv,
46 	.ndr_send	= do_send,
47 	.ndr_stat	= do_stat,
48 	.ndr_intr	= do_intr
49 };
50 
51 int main(int argc, char *argv[])
52 {
53   env_setargs(argc, argv);
54 
55   netdriver_task(&de_table);
56 
57   return 0;
58 }
59 
60 static void de_init_hw(dpeth_t *dep, ether_addr_t *addr)
61 {
62   de_reset(dep);
63   de_conf_addr(dep, addr);
64   de_init_buf(dep);
65 
66   /* Set the interrupt handler policy. Request interrupts not to be reenabled
67    * automatically. Return the IRQ line number when an interrupt occurs.
68    */
69   dep->de_hook = dep->de_irq;
70   sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
71   sys_irqenable(&dep->de_hook);
72 
73   de_reset(dep);
74   de_hw_conf(dep);
75   de_setup_frame(dep, addr);
76   de_start(dep);
77 }
78 
79 static int do_init(unsigned int instance, ether_addr_t *addr)
80 {
81 /* Initialize the DEC 21140A driver. */
82   dpeth_t *dep;
83 
84   dep = &de_state;
85   memset(dep, 0, sizeof(*dep));
86 
87   strlcpy(dep->de_name, "dec21140A:?", sizeof(dep->de_name));
88   dep->de_name[strlen(dep->de_name)-1] = '0' + instance;
89 
90   de_instance = instance;
91 
92   if (!de_probe(dep, instance))
93     return ENXIO;
94 
95   de_init_hw(dep, addr);
96 
97   return OK;
98 }
99 
100 static void do_stat(eth_stat_t *stat)
101 {
102   memcpy(stat, &de_state.de_stat, sizeof(*stat));
103 }
104 
105 static int de_probe(dpeth_t *dep, unsigned int skip)
106 {
107   int r, devind;
108   u16_t vid, did;
109 
110   DEBUG(printf("PROBING..."));
111 
112   pci_init();
113 
114   r= pci_first_dev(&devind, &vid, &did);
115   if (r == 0)
116     return FALSE;
117 
118   while (skip--)
119     {
120       r= pci_next_dev(&devind, &vid, &did);
121       if (!r)
122 	return FALSE;
123     }
124 
125   pci_reserve(devind);
126 
127   dep->de_base_port = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
128   dep->de_irq = pci_attr_r8(devind, PCI_ILR);
129 
130   if (dep->de_base_port < DE_MIN_BASE_ADDR)
131     panic("de_probe: base address invalid: %d", dep->de_base_port);
132 
133   DEBUG(printf("%s: using I/O address 0x%lx, IRQ %d\n",
134 	       dep->de_name, (unsigned long)dep->de_base_port,
135 	       dep->de_irq));
136 
137   dep->de_type = pci_attr_r8(devind, PCI_REV);
138 
139   /* device validation. We support only the DEC21140A */
140   if(dep->de_type != DEC_21140A){
141     printf("%s: unsupported card type %x\n", dep->de_name, dep->de_type);
142     return FALSE;
143   }
144 
145   return TRUE;
146 }
147 
148 static u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits)
149 {
150   u16_t retVal = 0;
151   int i;
152   u32_t csr = 0;
153   u32_t csr2 = 0; /* csr2 is used to hold constant values that are
154 		     setup in the init phase, it makes this a little
155 		     more readable, the following macro is also just
156 		     to clear up the code a little.*/
157 
158 #define EMIT \
159   do { \
160     io_outl(CSR_ADDR(dep, CSR9), csr | csr2); \
161     io_outl(CSR_ADDR(dep, CSR1), 0); \
162   } while(0)
163 
164   /* init */
165   csr = 0;                 EMIT;
166   csr = CSR9_SR;           EMIT;
167   csr = CSR9_SR | CSR9_RD; EMIT;
168 
169   csr2 = CSR9_SR | CSR9_RD;
170   csr = 0;                 EMIT;
171   csr2 |= CSR9_CS;
172 
173   csr = 0;                 EMIT;
174   csr = CSR9_SRC;          EMIT;
175   csr = 0;                 EMIT;
176 
177   /* cmd 110 - Read */
178   csr = CSR9_DI;            EMIT;
179   csr = CSR9_DI | CSR9_SRC; EMIT;
180   csr = CSR9_DI;            EMIT;
181   csr = CSR9_DI | CSR9_SRC; EMIT;
182   csr = CSR9_DI;            EMIT;
183   csr = 0;                  EMIT;
184   csr = CSR9_SRC;           EMIT;
185   csr = 0;                  EMIT;
186 
187   /* addr to read */
188   for(i=nbAddrBits;i!=0;i--){
189     csr = (addr&(1<<(i-1))) != 0 ? CSR9_DI : 0;  EMIT;
190     csr ^= CSR9_SRC; EMIT;
191     csr ^= CSR9_SRC; EMIT;
192   }
193 
194   /* actual read */
195   retVal=0;
196   for(i=0;i<16;i++){
197     retVal <<= 1;
198     csr = CSR9_SRC; EMIT;
199     retVal |= (io_inl(CSR_ADDR(dep, CSR9)) & CSR9_DO) == 0 ? 0 : 1;
200     csr = 0; EMIT;
201   }
202 
203   /* clean up */
204   csr = 0;                 EMIT;
205 
206 #undef EMIT
207   return retVal;
208 }
209 
210 static ssize_t do_recv(struct netdriver_data *data, size_t max)
211 {
212   u32_t size;
213   dpeth_t *dep;
214   de_loc_descr_t *descr;
215 
216   dep = &de_state;
217 
218   descr = &dep->descr[DESCR_RECV][dep->cur_descr[DESCR_RECV]];
219 
220   /* check if packet is in the current descr and only there */
221   if ((descr->descr->des[DES0] & DES0_OWN) ||
222       !(descr->descr->des[DES0] & DES0_FS) ||
223       !(descr->descr->des[DES0] & DES0_LS))
224     return SUSPEND;
225 
226   /*TODO: multi-descr msgs...*/
227   /* We only support packets contained in a single descriptor.
228      Setting the descriptor buffer size to less then
229      ETH_MAX_PACK_SIZE will result in multi-descriptor
230      packets that we won't be able to handle
231   */
232 
233   /* Check for abnormal messages. We assert here
234      because this driver is for a virtualized
235      envrionment where we will not get bad packets
236   */
237   assert(!(descr->descr->des[DES0]&DES0_ES));
238   assert(!(descr->descr->des[DES0]&DES0_RE));
239 
240   /* Copy buffer to user area and clear ownage */
241   size = (descr->descr->des[DES0]&DES0_FL)>>DES0_FL_SHIFT;
242 
243   /* HACK: VPC2007 sends short-sized packets, pad to minimum ethernet length */
244   if(size<60){
245     memset(&descr->buf1[size], 0, 60-size);
246     size=60;
247   }
248 
249   /* Truncate large packets */
250   if (size > max)
251     size = max;
252 
253   netdriver_copyout(data, 0, descr->buf1, size);
254 
255   dep->de_stat.ets_packetR++;
256 
257   descr->descr->des[DES0]=DES0_OWN;
258   dep->cur_descr[DESCR_RECV]++;
259   if(dep->cur_descr[DESCR_RECV] >= DE_NB_RECV_DESCR)
260     dep->cur_descr[DESCR_RECV] = 0;
261 
262   DEBUG(printf("Read returned size = %d\n", size));
263 
264   return size;
265 }
266 
267 static void de_conf_addr(dpeth_t *dep, ether_addr_t *addr)
268 {
269   u16_t temp16;
270   int i;
271 
272   DEBUG(printf("Reading SROM...\n"));
273 
274   for(i=0;i<(1<<SROM_BITWIDTH)-1;i++){
275     temp16 = de_read_rom(dep, i, SROM_BITWIDTH);
276     dep->srom[i*2] = temp16 & 0xFF;
277     dep->srom[i*2+1] = temp16 >> 8;
278   }
279 
280   /* TODO: validate SROM content */
281   /* acquire MAC addr */
282   DEBUG(printf("Using MAC addr= "));
283   for(i=0;i<6;i++){
284     addr->ea_addr[i] = dep->srom[i+DE_SROM_EA_OFFSET];
285     DEBUG(printf("%02X%c", addr->ea_addr[i],i!=5?'-':'\n'));
286   }
287   DEBUG(printf("probe success\n"));
288 }
289 
290 static void de_init_buf(dpeth_t *dep)
291 {
292   int i,j,r;
293   vir_bytes descr_vir = (vir_bytes)dep->sendrecv_descr_buf;
294   vir_bytes buffer_vir = (vir_bytes)dep->sendrecv_buf;
295   de_loc_descr_t *loc_descr;
296   phys_bytes temp;
297 
298   for(i=0;i<2;i++){
299     loc_descr = &dep->descr[i][0];
300     for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){
301 
302       /* assign buffer space for descriptor */
303       loc_descr->descr = (void*)descr_vir;
304       descr_vir += sizeof(de_descr_t);
305 
306       /* assign space for buffer */
307       loc_descr->buf1 = (u8_t*)buffer_vir;
308       buffer_vir += (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE);
309       loc_descr->buf2 = 0;
310       loc_descr++;
311     }
312   }
313 
314   /* Now that we have buffer space and descriptors, we need to
315      obtain their physical address to pass to the hardware
316   */
317   for(i=0;i<2;i++){
318     loc_descr = &dep->descr[i][0];
319     temp = (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE);
320     for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){
321       /* translate buffers physical address */
322       r = sys_umap(SELF, VM_D, (vir_bytes)loc_descr->buf1, temp,
323 		   (phys_bytes *) &(loc_descr->descr->des[DES_BUF1]));
324       if(r != OK) panic("umap failed: %d", r);
325       loc_descr->descr->des[DES_BUF2] = 0;
326       memset(&loc_descr->descr->des[DES0],0,sizeof(u32_t));
327       loc_descr->descr->des[DES1] = temp;
328       if(j==( (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR)-1))
329 	loc_descr->descr->des[DES1] |= DES1_ER;
330       if(i==DESCR_RECV)
331 	loc_descr->descr->des[DES0] |= DES0_OWN;
332       loc_descr++;
333     }
334   }
335 
336   /* record physical location of two first descriptor */
337   r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_RECV][0].descr,
338 	       sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_RECV]);
339   if(r != OK) panic("sys_umap failed: %d", r);
340 
341   r = sys_umap(SELF, VM_D, (vir_bytes)dep->descr[DESCR_TRAN][0].descr,
342 	       sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_TRAN]);
343   if(r != OK) panic("sys_umap failed: %d", r);
344 
345   DEBUG(printf("Descr: head tran=[%08X] head recv=[%08X]\n",
346 	       dep->sendrecv_descr_phys_addr[DESCR_TRAN],
347 	       dep->sendrecv_descr_phys_addr[DESCR_RECV]));
348 
349   /* check alignment just to be extra safe */
350   for(i=0;i<2;i++){
351     loc_descr = &dep->descr[i][0];
352     for(j=0;j< (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR);j++){
353       r = sys_umap(SELF, VM_D, (vir_bytes)&(loc_descr->descr),
354 			sizeof(de_descr_t), &temp);
355       if(r != OK) panic("sys_umap failed: %d", r);
356 
357       if( ((loc_descr->descr->des[DES_BUF1] & 0x3) != 0) ||
358 	  ((loc_descr->descr->des[DES_BUF2] & 0x3) != 0) ||
359 	  ((temp&0x3)!=0) )
360 	panic("alignment error: 0x%lx", temp);
361 
362       loc_descr++;
363     }
364   }
365 
366   /* Init default values */
367   dep->cur_descr[DESCR_TRAN]=1;
368   dep->cur_descr[DESCR_RECV]=0;
369 }
370 
371 static void do_intr(unsigned int __unused mask)
372 {
373   dpeth_t *dep;
374   u32_t val;
375 
376   dep = &de_state;
377 
378   val = io_inl(CSR_ADDR(dep, CSR5));
379 
380   if(val & CSR5_AIS){
381     panic("Abnormal Int CSR5=: %d", val);
382   }
383 
384   if (val & CSR5_RI)
385     netdriver_recv();
386 
387   if (val & CSR5_TI)
388     netdriver_send();
389 
390   /* ack and reset interrupts */
391   io_outl(CSR_ADDR(dep, CSR5), 0xFFFFFFFF);
392 
393   sys_irqenable(&dep->de_hook);
394 }
395 
396 static void de_reset(const dpeth_t *dep)
397 {
398   io_outl(CSR_ADDR(dep, CSR0), CSR0_SWR);
399 }
400 
401 static void do_stop(void)
402 {
403   de_reset(&de_state);
404 }
405 
406 static void de_hw_conf(const dpeth_t *dep)
407 {
408   u32_t val;
409 
410   /* CSR0 - global host bus prop */
411   val = CSR0_BAR | CSR0_CAL_8;
412   io_outl(CSR_ADDR(dep, CSR0), val);
413 
414   /* CSR3 - Receive list BAR */
415   val = dep->sendrecv_descr_phys_addr[DESCR_RECV];
416   io_outl(CSR_ADDR(dep, CSR3), val);
417 
418   /* CSR4 - Transmit list BAR */
419   val = dep->sendrecv_descr_phys_addr[DESCR_TRAN];
420   io_outl(CSR_ADDR(dep, CSR4), val);
421 
422   /* CSR7 - interrupt mask */
423   val = CSR7_TI | CSR7_RI | CSR7_AI;
424   io_outl(CSR_ADDR(dep, CSR7), val);
425 
426   /* CSR6 - operating mode register */
427   val = CSR6_MBO | CSR6_PS | CSR6_FD | CSR6_HBD |
428     CSR6_PCS | CSR6_SCR | CSR6_TR_00;
429   io_outl(CSR_ADDR(dep, CSR6), val);
430 }
431 
432 static void de_start(const dpeth_t *dep)
433 {
434   u32_t val;
435   val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST | CSR6_SR;
436   io_outl(CSR_ADDR(dep, CSR6), val);
437 }
438 
439 static void de_setup_frame(const dpeth_t *dep, const ether_addr_t *addr)
440 {
441   int i;
442   u32_t val;
443 
444   /* this is not perfect... we assume pass all multicast and only
445      filter non-multicast frames */
446   dep->descr[DESCR_TRAN][0].buf1[0] = 0xFF;
447   dep->descr[DESCR_TRAN][0].buf1[1] = 0xFF;
448   dep->descr[DESCR_TRAN][0].buf1[4] = 0xFF;
449   dep->descr[DESCR_TRAN][0].buf1[5] = 0xFF;
450   dep->descr[DESCR_TRAN][0].buf1[8] = 0xFF;
451   dep->descr[DESCR_TRAN][0].buf1[9] = 0xFF;
452   for(i=1;i<16;i++){
453     memset(&(dep->descr[DESCR_TRAN][0].buf1[12*i]), 0, 12);
454     dep->descr[DESCR_TRAN][0].buf1[12*i+0] = addr->ea_addr[0];
455     dep->descr[DESCR_TRAN][0].buf1[12*i+1] = addr->ea_addr[1];
456     dep->descr[DESCR_TRAN][0].buf1[12*i+4] = addr->ea_addr[2];
457     dep->descr[DESCR_TRAN][0].buf1[12*i+5] = addr->ea_addr[3];
458     dep->descr[DESCR_TRAN][0].buf1[12*i+8] = addr->ea_addr[4];
459     dep->descr[DESCR_TRAN][0].buf1[12*i+9] = addr->ea_addr[5];
460   }
461 
462   dep->descr[DESCR_TRAN][0].descr->des[DES0] = DES0_OWN;
463   dep->descr[DESCR_TRAN][0].descr->des[DES1] = DES1_SET |
464     DE_SETUP_FRAME_SIZE | DES1_IC;
465 
466   /* start transmit process to process setup frame */
467   val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST;
468   io_outl(CSR_ADDR(dep, CSR6), val);
469   io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF);
470 }
471 
472 static int do_send(struct netdriver_data *data, size_t size)
473 {
474   static int setup_done = 0;
475   dpeth_t *dep;
476   de_loc_descr_t *descr = NULL;
477 
478   dep = &de_state;
479 
480   descr = &dep->descr[DESCR_TRAN][dep->cur_descr[DESCR_TRAN]];
481 
482   if(( descr->descr->des[DES0] & DES0_OWN)!=0)
483     return SUSPEND;
484 
485   if(!setup_done && (dep->cur_descr[DESCR_TRAN] == 0) ){
486     dep->descr[DESCR_TRAN][0].descr->des[DES0] = 0;
487     setup_done=1;
488   }
489 
490   netdriver_copyin(data, 0, descr->buf1, size);
491 
492   descr->descr->des[DES1] = (descr->descr->des[DES1]&DES1_ER) |
493     DES1_FS | DES1_LS | DES1_IC | size;
494   descr->descr->des[DES0] = DES0_OWN;
495 
496   dep->cur_descr[DESCR_TRAN]++;
497   if(dep->cur_descr[DESCR_TRAN] >= DE_NB_SEND_DESCR)
498     dep->cur_descr[DESCR_TRAN] = 0;
499 
500   io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF);
501 
502   dep->de_stat.ets_packetT++;
503 
504   return OK;
505 }
506 
507 static u32_t io_inl(u16_t port)
508 {
509   u32_t value;
510   int rc;
511   if ((rc = sys_inl(port, &value)) != OK)
512     panic("sys_inl failed: %d", rc);
513   return value;
514 }
515 
516 static void io_outl(u16_t port, u32_t value)
517 {
518   int rc;
519   if ((rc = sys_outl(port, value)) != OK)
520     panic("sys_outl failed: %d", rc);
521 }
522