use oxpcie only if enabled to avoid baud bottleneck of uart.
[minix.git] / drivers / dec21140A / dec21140A.c
blobd16aa8b48faecbabba189ef64c2e33662050903d
1 /*
2 * dec21041.c
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.
9 * Created: Mar 2008 by Nicolas Tittley <first.last@ google's mail>
12 #include <minix/drivers.h>
13 #include <minix/netdriver.h>
15 #include <assert.h>
16 #include <machine/pci.h>
17 #include <minix/syslib.h>
18 #include <minix/endpoint.h>
19 #include <minix/com.h>
20 #include <minix/sef.h>
21 #include <minix/ds.h>
22 #include <net/gen/ether.h>
23 #include <net/gen/eth_io.h>
24 #include <stdlib.h>
26 #include "dec21140A.h"
29 _PROTOTYPE( PRIVATE u32_t io_inl, (u16_t); );
30 _PROTOTYPE( PRIVATE void io_outl, (u16_t, u32_t); );
31 _PROTOTYPE( PRIVATE void do_conf, (const message *); );
32 _PROTOTYPE( PRIVATE void do_get_stat_s, (message *); );
33 _PROTOTYPE( PRIVATE void do_interrupt, (const dpeth_t *); );
34 _PROTOTYPE( PRIVATE void do_reply, (dpeth_t *); );
35 _PROTOTYPE( PRIVATE void do_vread_s, (const message *, int); );
36 _PROTOTYPE( PRIVATE void do_watchdog, (void *); );
38 _PROTOTYPE( PRIVATE void de_update_conf, (dpeth_t *); );
39 _PROTOTYPE( PRIVATE int de_probe, (dpeth_t *, int skip); );
40 _PROTOTYPE( PRIVATE void de_conf_addr, (dpeth_t *); );
41 _PROTOTYPE( PRIVATE void de_first_init, (dpeth_t *); );
42 _PROTOTYPE( PRIVATE void de_reset, (const dpeth_t *); );
43 _PROTOTYPE( PRIVATE void de_hw_conf, (const dpeth_t *); );
44 _PROTOTYPE( PRIVATE void de_start, (const dpeth_t *); );
45 _PROTOTYPE( PRIVATE void de_setup_frame, (const dpeth_t *); );
46 _PROTOTYPE( PRIVATE u16_t de_read_rom, (const dpeth_t *, u8_t, u8_t); );
47 _PROTOTYPE( PRIVATE int de_calc_iov_size, (iovec_dat_s_t *); );
48 _PROTOTYPE( PRIVATE void de_next_iov, (iovec_dat_s_t *); );
49 _PROTOTYPE( PRIVATE void do_vwrite_s, (const message *, int); );
50 _PROTOTYPE( PRIVATE void de_get_userdata_s, (int, cp_grant_id_t,
51 vir_bytes, int, void *); );
53 /* Error messages */
54 static char str_CopyErrMsg[] = "unable to read/write user data";
55 static char str_SendErrMsg[] = "send failed";
56 static char str_SizeErrMsg[] = "illegal packet size";
57 static char str_UmapErrMsg[] = "Unable to sys_umap";
58 static char str_BusyErrMsg[] = "Send/Recv failed: busy";
59 static char str_StatErrMsg[] = "Unable to send stats";
60 static char str_AlignErrMsg[] = "Bad align of buffer/descriptor";
61 static char str_DevName[] = "dec21140A:eth#?";
63 PRIVATE dpeth_t de_state;
64 PRIVATE int de_instance;
66 /* SEF functions and variables. */
67 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
68 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
69 EXTERN char **env_argv;
71 /*===========================================================================*
72 * main *
73 *===========================================================================*/
74 int main(int argc, char *argv[])
76 dpeth_t *dep;
77 message m;
78 int ipc_status;
79 int r;
81 /* SEF local startup. */
82 env_setargs(argc, argv);
83 sef_local_startup();
85 while (TRUE)
87 if ((r= netdriver_receive(ANY, &m, &ipc_status)) != OK)
88 panic("netdriver_receive failed: %d", r);
90 if(is_ipc_notify(ipc_status)) {
91 switch(_ENDPOINT_P(m.m_source)) {
92 case CLOCK:
93 do_watchdog(&m);
94 break;
96 case HARDWARE:
97 dep = &de_state;
98 if (dep->de_mode == DEM_ENABLED) {
99 do_interrupt(dep);
100 if (dep->de_flags & (DEF_ACK_SEND | DEF_ACK_RECV))
101 do_reply(dep);
102 sys_irqenable(&dep->de_hook);
104 break;
105 default:
106 printf("ignoring notify from %d\n", m.m_source);
107 break;
109 continue;
112 switch (m.m_type)
114 case DL_WRITEV_S: do_vwrite_s(&m, FALSE); break;
115 case DL_READV_S: do_vread_s(&m, FALSE); break;
116 case DL_CONF: do_conf(&m); break;
117 case DL_GETSTAT_S: do_get_stat_s(&m); break;
119 default:
120 printf("message 0x%lx; %d from %d\n",
121 m.m_type, m.m_type-DL_RQ_BASE, m.m_source);
122 panic("illegal message: %d", m.m_type);
127 /*===========================================================================*
128 * sef_local_startup *
129 *===========================================================================*/
130 PRIVATE void sef_local_startup()
132 /* Register init callbacks. */
133 sef_setcb_init_fresh(sef_cb_init_fresh);
134 sef_setcb_init_lu(sef_cb_init_fresh);
135 sef_setcb_init_restart(sef_cb_init_fresh);
137 /* Register live update callbacks. */
138 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready);
139 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree);
141 /* Register signal callbacks. */
142 sef_setcb_signal_handler(sef_cb_signal_handler_term);
144 /* Let SEF perform startup. */
145 sef_startup();
148 /*===========================================================================*
149 * sef_cb_init_fresh *
150 *===========================================================================*/
151 PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *UNUSED(info))
153 /* Initialize the DEC 21140A driver. */
154 int fkeys, sfkeys;
155 long v;
157 v = 0;
158 (void) env_parse("instance", "d", 0, &v, 0, 255);
159 de_instance = (int) v;
161 /* Request function key for debug dumps */
162 fkeys = sfkeys = 0;
163 bit_set(sfkeys, DE_FKEY);
164 if ((fkey_map(&fkeys, &sfkeys)) != OK)
165 printf("%s: error using Shift+F%d key(%d)\n", str_DevName, DE_FKEY, errno);
167 /* Announce we are up! */
168 netdriver_announce();
170 return OK;
173 PRIVATE void do_get_stat_s(message * mp)
175 int rc;
176 dpeth_t *dep;
178 dep = &de_state;
180 if ((rc = sys_safecopyto(mp->DL_ENDPT, mp->DL_GRANT, 0UL,
181 (vir_bytes)&dep->de_stat,
182 sizeof(dep->de_stat), 0)) != OK)
183 panic(str_CopyErrMsg, rc);
185 mp->m_type = DL_STAT_REPLY;
186 rc = send(mp->m_source, mp);
187 if( rc != OK )
188 panic(str_StatErrMsg, rc);
189 return;
192 PRIVATE void do_conf(const message * mp)
194 int r;
195 dpeth_t *dep;
196 message reply_mess;
198 dep = &de_state;
200 strncpy(dep->de_name, str_DevName, strlen(str_DevName));
201 dep->de_name[strlen(dep->de_name)-1] = '0' + de_instance;
203 if (dep->de_mode == DEM_DISABLED) {
204 de_update_conf(dep);
205 pci_init();
206 if (dep->de_mode == DEM_ENABLED && !de_probe(dep, de_instance)) {
207 printf("%s: warning no ethernet card found at 0x%04X\n",
208 dep->de_name, dep->de_base_port);
209 dep->de_mode = DEM_DISABLED;
213 r = OK;
215 /* 'de_mode' may change if probe routines fail, test again */
216 switch (dep->de_mode) {
218 case DEM_DISABLED:
219 r = ENXIO; /* Device is OFF or hardware probe failed */
220 break;
222 case DEM_ENABLED:
223 if (dep->de_flags == DEF_EMPTY) {
224 de_first_init(dep);
225 dep->de_flags |= DEF_ENABLED;
226 de_reset(dep);
227 de_hw_conf(dep);
228 de_setup_frame(dep);
229 de_start(dep);
232 /* TODO CHECK PROMISC AND MULTI */
233 dep->de_flags &= NOT(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
234 if (mp->DL_MODE & DL_PROMISC_REQ)
235 dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
236 if (mp->DL_MODE & DL_MULTI_REQ) dep->de_flags |= DEF_MULTI;
237 if (mp->DL_MODE & DL_BROAD_REQ) dep->de_flags |= DEF_BROAD;
238 break;
240 case DEM_SINK:
241 DEBUG(printf("%s running in sink mode\n", str_DevName));
242 memset(dep->de_address.ea_addr, 0, sizeof(ether_addr_t));
243 de_conf_addr(dep);
244 break;
246 default: break;
249 reply_mess.m_type = DL_CONF_REPLY;
250 reply_mess.DL_STAT = r;
251 if(r == OK){
252 *(ether_addr_t *) reply_mess.DL_HWADDR = dep->de_address;
255 if (send(mp->m_source, &reply_mess) != OK)
256 panic(str_SendErrMsg, mp->m_source);
258 return;
261 PRIVATE void do_reply(dpeth_t * dep)
263 message reply;
264 int r, flags = DL_NOFLAGS;
266 if (dep->de_flags & DEF_ACK_SEND) flags |= DL_PACK_SEND;
267 if (dep->de_flags & DEF_ACK_RECV) flags |= DL_PACK_RECV;
269 reply.m_type = DL_TASK_REPLY;
270 reply.DL_STAT = flags;
271 reply.DL_COUNT = dep->de_read_s;
273 r = send(dep->de_client, &reply);
275 if(r < 0)
276 panic(str_SendErrMsg, r);
278 dep->de_read_s = 0;
279 dep->de_flags &= NOT(DEF_ACK_SEND | DEF_ACK_RECV);
280 return;
283 PRIVATE void do_watchdog(void *UNUSED(message))
285 /* nothing here yet */
286 return;
289 PRIVATE int de_probe(dpeth_t *dep, int skip){
290 int i, r, devind;
291 u16_t vid, did, temp16;
293 DEBUG(printf("PROBING..."));
295 r= pci_first_dev(&devind, &vid, &did);
296 if (r == 0)
297 return FALSE;
299 for(;;)
301 if ( DEC21140A_VID == vid &&
302 DEC21140A_DID == did)
304 if (!skip)
305 break;
306 skip--;
309 r= pci_next_dev(&devind, &vid, &did);
310 if (!r)
311 return FALSE;
314 pci_reserve(devind);
316 dep->de_base_port = pci_attr_r32(devind, PCI_BAR) & 0xffffffe0;
317 dep->de_irq = pci_attr_r8(devind, PCI_ILR);
319 if (dep->de_base_port < DE_MIN_BASE_ADDR)
320 panic("de_probe: base address invalid: %d", dep->de_base_port);
322 DEBUG(printf("%s: using I/O address 0x%lx, IRQ %d\n",
323 dep->de_name, (unsigned long)dep->de_base_port,
324 dep->de_irq));
326 dep->de_type = pci_attr_r8(devind, PCI_REV);
328 /* device validation. We support only the DEC21140A */
329 if(dep->de_type != DEC_21140A){
330 dep->de_type = DE_TYPE_UNKNOWN;
331 printf("%s: unsupported device\n", str_DevName);
332 return FALSE;
335 de_reset(dep);
337 DEBUG(printf("Reading SROM...\n"));
339 for(i=0;i<(1<<SROM_BITWIDTH)-1;i++){
340 temp16 = de_read_rom(dep, i, SROM_BITWIDTH);
341 dep->srom[i*2] = temp16 & 0xFF;
342 dep->srom[i*2+1] = temp16 >> 8;
345 /* TODO: validate SROM content */
346 /* acquire MAC addr */
347 DEBUG(printf("Using MAC addr= "));
348 for(i=0;i<6;i++){
349 dep->de_address.ea_addr[i] = dep->srom[i+DE_SROM_EA_OFFSET];
350 DEBUG(printf("%02X%c",dep->de_address.ea_addr[i],i!=5?'-':'\n'));
352 DEBUG(printf("probe success\n"));
353 return TRUE;
356 PRIVATE u16_t de_read_rom(const dpeth_t *dep, u8_t addr, u8_t nbAddrBits){
357 u16_t retVal = 0;
358 int i;
359 u32_t csr = 0;
360 u32_t csr2 = 0; /* csr2 is used to hold constant values that are
361 setup in the init phase, it makes this a little
362 more readable, the following macro is also just
363 to clear up the code a little.*/
365 #define EMIT do { io_outl(CSR_ADDR(dep, CSR9), csr | csr2); io_outl(CSR_ADDR(dep, CSR1), 0);} while(0)
367 /* init */
368 csr = 0; EMIT;
369 csr = CSR9_SR; EMIT;
370 csr = CSR9_SR | CSR9_RD; EMIT;
372 csr2 = CSR9_SR | CSR9_RD;
373 csr = 0; EMIT;
374 csr2 |= CSR9_CS;
376 csr = 0; EMIT;
377 csr = CSR9_SRC; EMIT;
378 csr = 0; EMIT;
380 /* cmd 110 - Read */
381 csr = CSR9_DI; EMIT;
382 csr = CSR9_DI | CSR9_SRC; EMIT;
383 csr = CSR9_DI; EMIT;
384 csr = CSR9_DI | CSR9_SRC; EMIT;
385 csr = CSR9_DI; EMIT;
386 csr = 0; EMIT;
387 csr = CSR9_SRC; EMIT;
388 csr = 0; EMIT;
390 /* addr to read */
391 for(i=nbAddrBits;i!=0;i--){
392 csr = (addr&(1<<(i-1))) != 0 ? CSR9_DI : 0; EMIT;
393 csr ^= CSR9_SRC; EMIT;
394 csr ^= CSR9_SRC; EMIT;
397 /* actual read */
398 retVal=0;
399 for(i=0;i<16;i++){
400 retVal <<= 1;
401 csr = CSR9_SRC; EMIT;
402 retVal |= (io_inl(CSR_ADDR(dep, CSR9)) & CSR9_DO) == 0 ? 0 : 1;
403 csr = 0; EMIT;
406 /* clean up */
407 csr = 0; EMIT;
409 #undef EMIT
410 return retVal;
413 static void de_update_conf(dpeth_t * dep)
415 static char dpc_fmt[] = "x:d:x";
416 char ec_key[16];
417 long val;
419 strcpy(ec_key, "DEETH0");
420 ec_key[5] += de_instance;
422 dep->de_mode = DEM_ENABLED;
423 switch (env_parse(ec_key, dpc_fmt, 0, &val, 0x000L, 0x3FFL)) {
424 case EP_OFF: dep->de_mode = DEM_DISABLED; break;
425 case EP_ON: dep->de_mode = DEM_SINK; break;
427 dep->de_base_port = 0;
429 return;
432 PRIVATE void do_vread_s(const message * mp, int from_int)
434 char *buffer;
435 u32_t size;
436 int r, ix = 0;
437 vir_bytes bytes;
438 dpeth_t *dep = NULL;
439 de_loc_descr_t *descr = NULL;
440 iovec_dat_s_t *iovp = NULL;
442 dep = &de_state;
444 dep->de_client = mp->m_source;
446 if (dep->de_mode == DEM_ENABLED) {
448 descr = &dep->descr[DESCR_RECV][dep->cur_descr[DESCR_RECV]];
450 /* check if packet is in the current descr and only there */
451 if( !( !(descr->descr->des[DES0] & DES0_OWN) &&
452 (descr->descr->des[DES0] & DES0_FS) &&
453 (descr->descr->des[DES0] & DES0_LS) ))
454 goto suspend;
457 /*TODO: multi-descr msgs...*/
458 /* We only support packets contained in a single descriptor.
459 Setting the descriptor buffer size to less then
460 ETH_MAX_PACK_SIZE will result in multi-descriptor
461 packets that we won't be able to handle
463 assert(!(descr->descr->des[DES0]&DES0_OWN));
464 assert(descr->descr->des[DES0]&DES0_FS);
465 assert(descr->descr->des[DES0]&DES0_LS);
467 /* Check for abnormal messages. We assert here
468 because this driver is for a virtualized
469 envrionment where we will not get bad packets
471 assert(!(descr->descr->des[DES0]&DES0_ES));
472 assert(!(descr->descr->des[DES0]&DES0_RE));
475 /* Setup the iovec entry to allow copying into
476 client layer
478 dep->de_read_iovec.iod_proc_nr = mp->DL_ENDPT;
479 de_get_userdata_s(mp->DL_ENDPT, (cp_grant_id_t) mp->DL_GRANT, 0,
480 mp->DL_COUNT, dep->de_read_iovec.iod_iovec);
481 dep->de_read_iovec.iod_iovec_s = mp->DL_COUNT;
482 dep->de_read_iovec.iod_grant = (cp_grant_id_t) mp->DL_GRANT;
483 dep->de_read_iovec.iod_iovec_offset = 0;
484 size = de_calc_iov_size(&dep->de_read_iovec);
485 if (size < ETH_MAX_PACK_SIZE)
486 panic(str_SizeErrMsg, size);
488 /* Copy buffer to user area and clear ownage */
489 size = (descr->descr->des[DES0]&DES0_FL)>>DES0_FL_SHIFT;
491 /*TODO: Complain to MS */
492 /*HACK: VPC2007 returns packet of invalid size. Ethernet standard
493 specify 46 bytes as the minimum for valid payload. However, this is
494 artificial in so far as for certain packet types, notably ARP, less
495 then 46 bytes are needed to contain the full information. In a non
496 virtualized environment the 46 bytes rule is enforced in order to give
497 guarantee in the collison detection scheme. Of course, this being a
498 driver for a VPC2007, we won't have collisions and I can only suppose
499 MS decided to cut packet size to true minimum, regardless of the
500 46 bytes payload standard. Note that this seems to not happen in
501 bridged mode. Note also, that the card does not return runt or
502 incomplete frames to us, so this hack is safe
504 if(size<60){
505 bzero(&descr->buf1[size], 60-size);
506 size=60;
508 /* End ugly hack */
510 iovp = &dep->de_read_iovec;
511 buffer = descr->buf1;
512 dep->bytes_rx += size;
513 dep->de_stat.ets_packetR++;
514 dep->de_read_s = size;
516 do {
517 bytes = iovp->iod_iovec[ix].iov_size; /* Size of buffer */
518 if (bytes >= size)
519 bytes = size;
521 r= sys_safecopyto(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0,
522 (vir_bytes)buffer, bytes, D);
523 if (r != OK)
524 panic(str_CopyErrMsg, r);
525 buffer += bytes;
527 if (++ix >= IOVEC_NR) { /* Next buffer of IO vector */
528 de_next_iov(iovp);
529 ix = 0;
531 } while ((size -= bytes) > 0);
533 descr->descr->des[DES0]=DES0_OWN;
534 dep->cur_descr[DESCR_RECV]++;
535 if(dep->cur_descr[DESCR_RECV] >= DE_NB_RECV_DESCR)
536 dep->cur_descr[DESCR_RECV] = 0;
538 DEBUG(printf("Read returned size = %d\n", size));
540 /* Reply information */
541 dep->de_flags |= DEF_ACK_RECV;
542 dep->de_flags &= NOT(DEF_READING);
545 if(!from_int){
546 do_reply(dep);
548 return;
550 suspend:
551 if(from_int){
552 assert(dep->de_flags & DEF_READING);
553 return;
556 assert(!(dep->de_flags & DEF_READING));
557 dep->rx_return_msg = *mp;
558 dep->de_flags |= DEF_READING;
559 do_reply(dep);
560 return;
563 PRIVATE void de_conf_addr(dpeth_t * dep)
565 static char ea_fmt[] = "x:x:x:x:x:x";
566 char ea_key[16];
567 int ix;
568 long val;
570 strcpy(ea_key, "DEETH0_EA");
571 ea_key[5] += de_instance;
573 for (ix = 0; ix < SA_ADDR_LEN; ix++) {
574 val = dep->de_address.ea_addr[ix];
575 if (env_parse(ea_key, ea_fmt, ix, &val, 0x00L, 0xFFL) != EP_SET)
576 break;
577 dep->de_address.ea_addr[ix] = val;
580 if (ix != 0 && ix != SA_ADDR_LEN)
581 env_parse(ea_key, "?", 0, &val, 0L, 0L);
582 return;
585 PRIVATE void de_first_init(dpeth_t *dep)
587 int i,j,r;
588 vir_bytes descr_vir = dep->sendrecv_descr_buf;
589 vir_bytes buffer_vir = dep->sendrecv_buf;
590 de_loc_descr_t *loc_descr;
591 u32_t temp;
594 for(i=0;i<2;i++){
595 loc_descr = &dep->descr[i][0];
596 for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){
598 /* assign buffer space for descriptor */
599 loc_descr->descr = descr_vir;
600 descr_vir += sizeof(de_descr_t);
602 /* assign space for buffer */
603 loc_descr->buf1 = buffer_vir;
604 buffer_vir += (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE);
605 loc_descr->buf2 = 0;
606 loc_descr++;
610 /* Now that we have buffer space and descriptors, we need to
611 obtain their physical address to pass to the hardware
613 for(i=0;i<2;i++){
614 loc_descr = &dep->descr[i][0];
615 temp = (i==DESCR_RECV ? DE_RECV_BUF_SIZE : DE_SEND_BUF_SIZE);
616 for(j=0; j < (i==DESCR_RECV ? DE_NB_RECV_DESCR : DE_NB_SEND_DESCR); j++){
617 /* translate buffers physical address */
618 r = sys_umap(SELF, VM_D, loc_descr->buf1, temp,
619 &(loc_descr->descr->des[DES_BUF1]));
620 if(r != OK) panic("umap failed: %d", r);
621 loc_descr->descr->des[DES_BUF2] = 0;
622 memset(&loc_descr->descr->des[DES0],0,sizeof(u32_t));
623 loc_descr->descr->des[DES1] = temp;
624 if(j==( (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR)-1))
625 loc_descr->descr->des[DES1] |= DES1_ER;
626 if(i==DESCR_RECV)
627 loc_descr->descr->des[DES0] |= DES0_OWN;
628 loc_descr++;
632 /* record physical location of two first descriptor */
633 r = sys_umap(SELF, VM_D, dep->descr[DESCR_RECV][0].descr,
634 sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_RECV]);
635 if(r != OK) panic(str_UmapErrMsg, r);
637 r = sys_umap(SELF, VM_D, dep->descr[DESCR_TRAN][0].descr,
638 sizeof(de_descr_t), &dep->sendrecv_descr_phys_addr[DESCR_TRAN]);
639 if(r != OK) panic(str_UmapErrMsg, r);
641 DEBUG(printf("Descr: head tran=[%08X] head recv=[%08X]\n",
642 dep->sendrecv_descr_phys_addr[DESCR_TRAN],
643 dep->sendrecv_descr_phys_addr[DESCR_RECV]));
645 /* check alignment just to be extra safe */
646 for(i=0;i<2;i++){
647 loc_descr = &dep->descr[i][0];
648 for(j=0;j< (i==DESCR_RECV?DE_NB_RECV_DESCR:DE_NB_SEND_DESCR);j++){
649 r = sys_umap(SELF, VM_D, &(loc_descr->descr), sizeof(de_descr_t),
650 &temp);
651 if(r != OK)
652 panic(str_UmapErrMsg, r);
654 if( ((loc_descr->descr->des[DES_BUF1] & 0x3) != 0) ||
655 ((loc_descr->descr->des[DES_BUF2] & 0x3) != 0) ||
656 ((temp&0x3)!=0) )
657 panic(str_AlignErrMsg, temp);
659 loc_descr++;
663 /* Init default values */
664 dep->cur_descr[DESCR_TRAN]=1;
665 dep->cur_descr[DESCR_RECV]=0;
666 dep->bytes_rx = 0;
667 dep->bytes_tx = 0;
669 /* Set the interrupt handler policy. Request interrupts not to be reenabled
670 * automatically. Return the IRQ line number when an interrupt occurs.
672 dep->de_hook = dep->de_irq;
673 sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
674 sys_irqenable(&dep->de_hook);
677 PRIVATE void do_interrupt(const dpeth_t *dep){
678 u32_t val;
679 val = io_inl(CSR_ADDR(dep, CSR5));
681 if(val & CSR5_AIS){
682 panic("Abnormal Int CSR5=: %d", val);
685 if( (dep->de_flags & DEF_READING) && (val & CSR5_RI) ){
686 do_vread_s(&dep->rx_return_msg, TRUE);
689 if( (dep->de_flags & DEF_SENDING) && (val & CSR5_TI) ){
690 do_vwrite_s(&dep->tx_return_msg, TRUE);
693 /* ack and reset interrupts */
694 io_outl(CSR_ADDR(dep, CSR5), 0xFFFFFFFF);
695 return;
698 PRIVATE void de_reset(const dpeth_t *dep){
699 io_outl(CSR_ADDR(dep, CSR0), CSR0_SWR);
702 PRIVATE void de_hw_conf(const dpeth_t *dep){
703 u32_t val;
705 /* CSR0 - global host bus prop */
706 val = CSR0_BAR | CSR0_CAL_8;
707 io_outl(CSR_ADDR(dep, CSR0), val);
709 /* CSR3 - Receive list BAR */
710 val = dep->sendrecv_descr_phys_addr[DESCR_RECV];
711 io_outl(CSR_ADDR(dep, CSR3), val);
713 /* CSR4 - Transmit list BAR */
714 val = dep->sendrecv_descr_phys_addr[DESCR_TRAN];
715 io_outl(CSR_ADDR(dep, CSR4), val);
717 /* CSR7 - interrupt mask */
718 val = CSR7_TI | CSR7_RI | CSR7_AI;
719 io_outl(CSR_ADDR(dep, CSR7), val);
721 /* CSR6 - operating mode register */
722 val = CSR6_MBO | CSR6_PS | CSR6_FD | CSR6_HBD |
723 CSR6_PCS | CSR6_SCR | CSR6_TR_00;
724 io_outl(CSR_ADDR(dep, CSR6), val);
727 PRIVATE void de_start(const dpeth_t *dep){
728 u32_t val;
729 val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST | CSR6_SR;
730 io_outl(CSR_ADDR(dep, CSR6), val);
733 PRIVATE void de_setup_frame(const dpeth_t *dep){
734 int i;
735 u32_t val;
737 /* this is not perfect... we assume pass all multicast and only
738 filter non-multicast frames */
739 dep->descr[DESCR_TRAN][0].buf1[0] = 0xFF;
740 dep->descr[DESCR_TRAN][0].buf1[1] = 0xFF;
741 dep->descr[DESCR_TRAN][0].buf1[4] = 0xFF;
742 dep->descr[DESCR_TRAN][0].buf1[5] = 0xFF;
743 dep->descr[DESCR_TRAN][0].buf1[8] = 0xFF;
744 dep->descr[DESCR_TRAN][0].buf1[9] = 0xFF;
745 for(i=1;i<16;i++){
746 memset(&(dep->descr[DESCR_TRAN][0].buf1[12*i]), 0, 12);
747 dep->descr[DESCR_TRAN][0].buf1[12*i+0] = dep->de_address.ea_addr[0];
748 dep->descr[DESCR_TRAN][0].buf1[12*i+1] = dep->de_address.ea_addr[1];
749 dep->descr[DESCR_TRAN][0].buf1[12*i+4] = dep->de_address.ea_addr[2];
750 dep->descr[DESCR_TRAN][0].buf1[12*i+5] = dep->de_address.ea_addr[3];
751 dep->descr[DESCR_TRAN][0].buf1[12*i+8] = dep->de_address.ea_addr[4];
752 dep->descr[DESCR_TRAN][0].buf1[12*i+9] = dep->de_address.ea_addr[5];
755 dep->descr[DESCR_TRAN][0].descr->des[DES0] = DES0_OWN;
756 dep->descr[DESCR_TRAN][0].descr->des[DES1] = DES1_SET |
757 DE_SETUP_FRAME_SIZE | DES1_IC;
759 /* start transmit process to process setup frame */
760 val = io_inl(CSR_ADDR(dep, CSR6)) | CSR6_ST;
761 io_outl(CSR_ADDR(dep, CSR6), val);
762 io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF);
764 return;
767 PRIVATE int de_calc_iov_size(iovec_dat_s_t * iovp){
768 int size, ix;
769 size = ix = 0;
772 size += iovp->iod_iovec[ix].iov_size;
773 if (++ix >= IOVEC_NR) {
774 de_next_iov(iovp);
775 ix = 0;
777 } while (ix < iovp->iod_iovec_s);
778 return size;
781 PRIVATE void de_get_userdata_s(int user_proc, cp_grant_id_t grant,
782 vir_bytes offset, int count, void *loc_addr){
783 int rc;
784 vir_bytes len;
786 len = (count > IOVEC_NR ? IOVEC_NR : count) * sizeof(iovec_t);
787 rc = sys_safecopyfrom(user_proc, grant, 0, (vir_bytes)loc_addr, len, D);
788 if (rc != OK)
789 panic(str_CopyErrMsg, rc);
790 return;
793 PRIVATE void de_next_iov(iovec_dat_s_t * iovp){
795 iovp->iod_iovec_s -= IOVEC_NR;
796 iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_t);
797 de_get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant, iovp->iod_iovec_offset,
798 iovp->iod_iovec_s, iovp->iod_iovec);
799 return;
802 PRIVATE void do_vwrite_s(const message * mp, int from_int){
803 static u8_t setupDone = 0;
804 int size, r, bytes, ix, totalsize;
805 dpeth_t *dep;
806 iovec_dat_s_t *iovp = NULL;
807 de_loc_descr_t *descr = NULL;
808 char *buffer = NULL;
810 dep = &de_state;
812 dep->de_client = mp->m_source;
814 if (dep->de_mode == DEM_ENABLED) {
816 if (!from_int && (dep->de_flags & DEF_SENDING))
817 panic(str_BusyErrMsg);
819 descr = &dep->descr[DESCR_TRAN][dep->cur_descr[DESCR_TRAN]];
821 if(( descr->descr->des[DES0] & DES0_OWN)!=0)
822 goto suspend;
824 if(!setupDone && (dep->cur_descr[DESCR_TRAN] == 0) ){
825 dep->descr[DESCR_TRAN][0].descr->des[DES0] = 0;
826 setupDone=1;
829 buffer = descr->buf1;
830 iovp = &dep->de_write_iovec;
831 iovp->iod_proc_nr = mp->DL_ENDPT;
832 de_get_userdata_s(mp->DL_ENDPT, mp->DL_GRANT, 0,
833 mp->DL_COUNT, iovp->iod_iovec);
834 iovp->iod_iovec_s = mp->DL_COUNT;
835 iovp->iod_grant = (cp_grant_id_t) mp->DL_GRANT;
836 iovp->iod_iovec_offset = 0;
837 totalsize = size = de_calc_iov_size(iovp);
838 if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE)
839 panic(str_SizeErrMsg, size);
841 dep->bytes_tx += size;
842 dep->de_stat.ets_packetT++;
844 ix=0;
845 do {
846 bytes = iovp->iod_iovec[ix].iov_size;
847 if (bytes >= size)
848 bytes = size;
850 r= sys_safecopyfrom(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant,
851 0, (vir_bytes)buffer, bytes, D);
852 if (r != OK)
853 panic(str_CopyErrMsg, r);
854 buffer += bytes;
856 if (++ix >= IOVEC_NR) {
857 de_next_iov(iovp);
858 ix = 0;
860 } while ((size -= bytes) > 0);
862 descr->descr->des[DES1] = (descr->descr->des[DES1]&DES1_ER) |
863 DES1_FS | DES1_LS | DES1_IC | totalsize;
864 descr->descr->des[DES0] = DES0_OWN;
866 dep->cur_descr[DESCR_TRAN]++;
867 if(dep->cur_descr[DESCR_TRAN] >= DE_NB_SEND_DESCR)
868 dep->cur_descr[DESCR_TRAN] = 0;
870 io_outl(CSR_ADDR(dep, CSR1), 0xFFFFFFFF);
873 dep->de_flags |= DEF_ACK_SEND;
874 if(from_int){
875 dep->de_flags &= NOT(DEF_SENDING);
876 return;
878 do_reply(dep);
879 return;
881 suspend:
882 if(from_int)
883 panic("should not happen: %d", 0);
885 dep->de_stat.ets_transDef++;
886 dep->de_flags |= DEF_SENDING;
887 dep->de_stat.ets_transDef++;
888 dep->tx_return_msg = *mp;
889 do_reply(dep);
892 PRIVATE void warning(const char *type, int err){
893 printf("Warning: %s sys_%s failed (%d)\n", str_DevName, type, err);
894 return;
897 PRIVATE u32_t io_inl(u16_t port){
898 u32_t value;
899 int rc;
900 if ((rc = sys_inl(port, &value)) != OK) warning("inl", rc);
901 return value;
904 PRIVATE void io_outl(u16_t port, u32_t value){
905 int rc;
906 if ((rc = sys_outl(port, value)) != OK) warning("outl", rc);
907 return;