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 "../drivers.h"
16 #include <minix/syslib.h>
17 #include <minix/endpoint.h>
18 #include <minix/com.h>
19 #include <minix/sef.h>
22 #include <net/gen/ether.h>
23 #include <net/gen/eth_io.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
, (message
*); );
32 _PROTOTYPE( PRIVATE
void do_fkey
, (message
*); );
33 _PROTOTYPE( PRIVATE
void do_get_name
, (message
*); );
34 _PROTOTYPE( PRIVATE
void do_get_stat_s
, (message
*); );
35 _PROTOTYPE( PRIVATE
void do_interrupt
, (dpeth_t
*); );
36 _PROTOTYPE( PRIVATE
void do_reply
, (dpeth_t
*, int, int); );
37 _PROTOTYPE( PRIVATE
void do_vread_s
, (message
*, int); );
38 _PROTOTYPE( PRIVATE
void do_watchdog
, (void *); );
40 _PROTOTYPE( PRIVATE
void de_update_conf
, (dpeth_t
*); );
41 _PROTOTYPE( PRIVATE
int de_probe
, (dpeth_t
*); );
42 _PROTOTYPE( PRIVATE
void de_conf_addr
, (dpeth_t
*); );
43 _PROTOTYPE( PRIVATE
void de_first_init
, (dpeth_t
*); );
44 _PROTOTYPE( PRIVATE
void de_reset
, (dpeth_t
*); );
45 _PROTOTYPE( PRIVATE
void de_hw_conf
, (dpeth_t
*); );
46 _PROTOTYPE( PRIVATE
void de_start
, (dpeth_t
*); );
47 _PROTOTYPE( PRIVATE
void de_setup_frame
, (dpeth_t
*); );
48 _PROTOTYPE( PRIVATE u16_t de_read_rom
, (dpeth_t
*, u8_t
, u8_t
); );
49 _PROTOTYPE( PRIVATE
int de_calc_iov_size
, (iovec_dat_s_t
*); );
50 _PROTOTYPE( PRIVATE
void de_next_iov
, (iovec_dat_s_t
*); );
51 _PROTOTYPE( PRIVATE
void do_vwrite_s
, (message
*, int); );
52 _PROTOTYPE( PRIVATE
void de_get_userdata_s
, (int, cp_grant_id_t
,
53 vir_bytes
, int, void *); );
56 static char str_CopyErrMsg
[] = "unable to read/write user data";
57 static char str_PortErrMsg
[] = "illegal port";
58 static char str_RecvErrMsg
[] = "receive failed";
59 static char str_SendErrMsg
[] = "send failed";
60 static char str_SizeErrMsg
[] = "illegal packet size";
61 static char str_TypeErrMsg
[] = "illegal message type";
62 static char str_UmapErrMsg
[] = "Unable to sys_umap";
63 static char str_BusyErrMsg
[] = "Send/Recv failed: busy";
64 static char str_StatErrMsg
[] = "Unable to send stats";
65 static char str_AlignErrMsg
[] = "Bad align of buffer/descriptor";
66 static char str_DevName
[] = "dec21140A:eth#?";
69 static dpeth_t de_table
[DE_PORT_NR
];
70 static char *progname
;
72 int sef_cb_init(int type
, sef_init_info_t
*info
)
77 /* Request function key for debug dumps */
78 fkeys
= sfkeys
= 0; bit_set(sfkeys
, DE_FKEY
);
79 if ((fkey_map(&fkeys
, &sfkeys
)) != OK
)
80 printf("%s: error using Shift+F%d key(%d)\n", str_DevName
, DE_FKEY
, errno
);
82 /* Try to notify inet that we are present (again) */
83 r
= ds_retrieve_label_num("inet", &tasknr
);
87 printf("%s unable to notify inet: %d\n", str_DevName
, r
);
90 /*===========================================================================*
92 *===========================================================================*/
93 int main(int argc
, char *argv
[])
99 (progname
=strrchr(argv
[0],'/')) ? progname
++ : (progname
=argv
[0]);
101 env_setargs(argc
, argv
);
103 sef_setcb_init_fresh(sef_cb_init
);
104 sef_setcb_init_restart(sef_cb_init
);
109 if ((r
= sef_receive(ANY
, &m
)) != OK
)
110 panic(str_DevName
, "minix msg sef_receive failed", r
);
112 if(is_notify(m
.m_type
)) {
113 switch(_ENDPOINT_P(m
.m_source
)) {
122 for (dep
= de_table
; dep
< &de_table
[DE_PORT_NR
]; dep
+= 1) {
123 if (dep
->de_mode
== DEM_ENABLED
) {
125 if (dep
->de_flags
& (DEF_ACK_SEND
| DEF_ACK_RECV
))
126 do_reply(dep
, OK
, TRUE
);
127 sys_irqenable(&dep
->de_hook
);
135 printf("ignoring notify from %d\n", m
.m_source
);
143 case DL_WRITEV_S
: do_vwrite_s(&m
, FALSE
); break;
144 case DL_READV_S
: do_vread_s(&m
, FALSE
); break;
145 case DL_CONF
: do_conf(&m
); break;
146 case DL_GETSTAT_S
: do_get_stat_s(&m
); break;
147 case DL_GETNAME
: do_get_name(&m
); break;
148 case DL_STOP
: /* nothing */ break;
151 printf("message 0x%lx; %d from %d\n",
152 m
.m_type
, m
.m_type
-DL_RQ_BASE
, m
.m_source
);
153 panic(str_DevName
, "illegal message", m
.m_type
);
158 PRIVATE
void do_get_stat_s(message
* mp
)
164 if (port
< 0 || port
>= DE_PORT_NR
)
165 panic(str_DevName
, str_PortErrMsg
, port
);
167 dep
= &de_table
[port
];
168 dep
->de_client
= mp
->DL_PROC
;
170 if ((rc
= sys_safecopyto(mp
->DL_PROC
, mp
->DL_GRANT
, 0,
171 (vir_bytes
)&dep
->de_stat
,
172 (vir_bytes
) sizeof(dep
->de_stat
), 0)) != OK
)
173 panic(str_DevName
, str_CopyErrMsg
, rc
);
175 mp
->m_type
= DL_STAT_REPLY
;
178 rc
= send(mp
->m_source
, mp
);
180 panic(str_DevName
, str_StatErrMsg
, rc
);
184 PRIVATE
void do_conf(message
* mp
)
191 if (port
>= 0 && port
< DE_PORT_NR
) {
193 dep
= &de_table
[port
];
194 strncpy(dep
->de_name
, str_DevName
, strlen(str_DevName
));
195 dep
->de_name
[strlen(dep
->de_name
)-1] = '0' + port
;
197 if (dep
->de_mode
== DEM_DISABLED
) {
200 if (dep
->de_mode
== DEM_ENABLED
&& !de_probe(dep
)) {
201 printf("%s: warning no ethernet card found at 0x%04X\n",
202 dep
->de_name
, dep
->de_base_port
);
203 dep
->de_mode
= DEM_DISABLED
;
207 /* 'de_mode' may change if probe routines fail, test again */
208 switch (dep
->de_mode
) {
211 port
= ENXIO
; /* Device is OFF or hardware probe failed */
215 if (dep
->de_flags
== DEF_EMPTY
) {
217 dep
->de_flags
|= DEF_ENABLED
;
224 /* TODO CHECK PROMISC AND MULTI */
225 dep
->de_flags
&= NOT(DEF_PROMISC
| DEF_MULTI
| DEF_BROAD
);
226 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
227 dep
->de_flags
|= DEF_PROMISC
| DEF_MULTI
| DEF_BROAD
;
228 if (mp
->DL_MODE
& DL_MULTI_REQ
) dep
->de_flags
|= DEF_MULTI
;
229 if (mp
->DL_MODE
& DL_BROAD_REQ
) dep
->de_flags
|= DEF_BROAD
;
230 dep
->de_client
= mp
->m_source
;
234 DEBUG(printf("%s running in sink mode\n", str_DevName
));
235 memset(dep
->de_address
.ea_addr
, 0, sizeof(ether_addr_t
));
241 } else /* Port number is out of range */
244 reply_mess
.m_type
= DL_CONF_REPLY
;
245 reply_mess
.m3_i1
= port
;
246 reply_mess
.m3_i2
= DE_PORT_NR
;
247 *(ether_addr_t
*) reply_mess
.m3_ca1
= dep
->de_address
;
249 if (send(mp
->m_source
, &reply_mess
) != OK
)
250 panic(str_DevName
, str_SendErrMsg
, mp
->m_source
);
256 PRIVATE
void do_get_name(mp
)
260 strncpy(mp
->DL_NAME
, progname
, sizeof(mp
->DL_NAME
));
261 mp
->DL_NAME
[sizeof(mp
->DL_NAME
)-1]= '\0';
262 mp
->m_type
= DL_NAME_REPLY
;
263 r
= send(mp
->m_source
, mp
);
265 panic(str_DevName
, "do_getname: send failed", r
);
268 PRIVATE
void do_reply(dpeth_t
* dep
, int err
, int may_block
)
273 if (dep
->de_flags
& DEF_ACK_SEND
) status
|= DL_PACK_SEND
;
274 if (dep
->de_flags
& DEF_ACK_RECV
) status
|= DL_PACK_RECV
;
276 reply
.m_type
= DL_TASK_REPLY
;
277 reply
.DL_PORT
= dep
- de_table
;
278 reply
.DL_PROC
= dep
->de_client
;
279 reply
.DL_STAT
= status
| ((u32_t
) err
<< 16);
280 reply
.DL_COUNT
= dep
->de_read_s
;
283 status
= send(dep
->de_client
, &reply
);
285 if(status
== ELOCKED
&& may_block
){
286 /*printf("Warning: Dec21041 send lock prevented\n\n");*/
291 panic(dep
->de_name
, str_SendErrMsg
, status
);
294 dep
->de_flags
&= NOT(DEF_ACK_SEND
| DEF_ACK_RECV
);
298 PRIVATE
void do_watchdog(void *message
)
300 /* nothing here yet */
304 PRIVATE
int de_probe(dpeth_t
*dep
){
306 u16_t vid
, did
, temp16
;
308 DEBUG(printf("PROBING..."));
310 r
= pci_first_dev(&devind
, &vid
, &did
);
316 if ( DEC21140A_VID
== vid
&&
317 DEC21140A_DID
== did
)
320 r
= pci_next_dev(&devind
, &vid
, &did
);
327 dep
->de_base_port
= pci_attr_r32(devind
, PCI_BAR
) & 0xffffffe0;
328 dep
->de_irq
= pci_attr_r8(devind
, PCI_ILR
);
330 if (dep
->de_base_port
< DE_MIN_BASE_ADDR
)
331 panic(str_DevName
,"de_probe: base address invalid ", dep
->de_base_port
);
333 DEBUG(printf("%s: using I/O address 0x%lx, IRQ %d\n",
334 dep
->de_name
, (unsigned long)dep
->de_base_port
,
337 dep
->de_type
= pci_attr_r8(devind
, PCI_REV
);
339 /* device validation. We support only the DEC21140A */
340 if(dep
->de_type
!= DEC_21140A
){
341 dep
->de_type
= DE_TYPE_UNKNOWN
;
342 printf("%s: unsupported device\n", str_DevName
);
348 DEBUG(printf("Reading SROM...\n"));
350 for(i
=0;i
<(1<<SROM_BITWIDTH
)-1;i
++){
351 temp16
= de_read_rom(dep
, i
, SROM_BITWIDTH
);
352 dep
->srom
[i
*2] = temp16
& 0xFF;
353 dep
->srom
[i
*2+1] = temp16
>> 8;
356 /* TODO: validate SROM content */
357 /* acquire MAC addr */
358 DEBUG(printf("Using MAC addr= "));
360 dep
->de_address
.ea_addr
[i
] = dep
->srom
[i
+DE_SROM_EA_OFFSET
];
361 DEBUG(printf("%02X%c",dep
->de_address
.ea_addr
[i
],i
!=5?'-':'\n'));
363 DEBUG(printf("probe success\n"));
367 PRIVATE u16_t
de_read_rom(dpeth_t
*dep
, u8_t addr
, u8_t nbAddrBits
){
371 u32_t csr2
= 0; /* csr2 is used to hold constant values that are
372 setup in the init phase, it makes this a little
373 more readable, the following macro is also just
374 to clear up the code a little.*/
376 #define EMIT do { io_outl(CSR_ADDR(dep, CSR9), csr | csr2); io_outl(CSR_ADDR(dep, CSR1), 0);} while(0)
381 csr
= CSR9_SR
| CSR9_RD
; EMIT
;
383 csr2
= CSR9_SR
| CSR9_RD
;
388 csr
= CSR9_SRC
; EMIT
;
393 csr
= CSR9_DI
| CSR9_SRC
; EMIT
;
395 csr
= CSR9_DI
| CSR9_SRC
; EMIT
;
398 csr
= CSR9_SRC
; EMIT
;
402 for(i
=nbAddrBits
;i
!=0;i
--){
403 csr
= (addr
&(1<<(i
-1))) != 0 ? CSR9_DI
: 0; EMIT
;
404 csr
^= CSR9_SRC
; EMIT
;
405 csr
^= CSR9_SRC
; EMIT
;
412 csr
= CSR9_SRC
; EMIT
;
413 retVal
|= (io_inl(CSR_ADDR(dep
, CSR9
)) & CSR9_DO
) == 0 ? 0 : 1;
424 static void de_update_conf(dpeth_t
* dep
)
426 static char dpc_fmt
[] = "x:d:x";
429 dep
->de_mode
= DEM_ENABLED
;
430 switch (env_parse("DEETH0", dpc_fmt
, 0, &val
, 0x000L
, 0x3FFL
)) {
431 case EP_OFF
: dep
->de_mode
= DEM_DISABLED
; break;
432 case EP_ON
: dep
->de_mode
= DEM_SINK
; break;
434 dep
->de_base_port
= 0;
439 PRIVATE
void do_vread_s(message
* mp
, int from_int
)
443 int r
, bytes
, ix
= 0;
445 de_loc_descr_t
*descr
= NULL
;
446 iovec_dat_s_t
*iovp
= NULL
;
448 if (mp
->DL_PORT
< 0 || mp
->DL_PORT
>= DE_PORT_NR
)
449 panic(dep
->de_name
, str_PortErrMsg
, mp
->DL_PORT
);
451 dep
= &de_table
[mp
->DL_PORT
];
452 dep
->de_client
= mp
->DL_PROC
;
454 if (dep
->de_mode
== DEM_ENABLED
) {
456 descr
= &dep
->descr
[DESCR_RECV
][dep
->cur_descr
[DESCR_RECV
]];
458 /* check if packet is in the current descr and only there */
459 if( !( !(descr
->descr
->des
[DES0
] & DES0_OWN
) &&
460 (descr
->descr
->des
[DES0
] & DES0_FS
) &&
461 (descr
->descr
->des
[DES0
] & DES0_LS
) ))
465 /*TODO: multi-descr msgs...*/
466 /* We only support packets contained in a single descriptor.
467 Setting the descriptor buffer size to less then
468 ETH_MAX_PACK_SIZE will result in multi-descriptor
469 packets that we won't be able to handle
471 assert(!(descr
->descr
->des
[DES0
]&DES0_OWN
));
472 assert(descr
->descr
->des
[DES0
]&DES0_FS
);
473 assert(descr
->descr
->des
[DES0
]&DES0_LS
);
475 /* Check for abnormal messages. We assert here
476 because this driver is for a virtualized
477 envrionment where we will not get bad packets
479 assert(!(descr
->descr
->des
[DES0
]&DES0_ES
));
480 assert(!(descr
->descr
->des
[DES0
]&DES0_RE
));
483 /* Setup the iovec entry to allow copying into
486 dep
->de_read_iovec
.iod_proc_nr
= mp
->DL_PROC
;
487 de_get_userdata_s(mp
->DL_PROC
, (vir_bytes
) mp
->DL_GRANT
, 0,
488 mp
->DL_COUNT
, dep
->de_read_iovec
.iod_iovec
);
489 dep
->de_read_iovec
.iod_iovec_s
= mp
->DL_COUNT
;
490 dep
->de_read_iovec
.iod_grant
= (vir_bytes
) mp
->DL_GRANT
;
491 dep
->de_read_iovec
.iod_iovec_offset
= 0;
492 size
= de_calc_iov_size(&dep
->de_read_iovec
);
493 if (size
< ETH_MAX_PACK_SIZE
)
494 panic(str_DevName
, str_SizeErrMsg
, size
);
496 /* Copy buffer to user area and clear ownage */
497 size
= (descr
->descr
->des
[DES0
]&DES0_FL
)>>DES0_FL_SHIFT
;
499 /*TODO: Complain to MS */
500 /*HACK: VPC2007 returns packet of invalid size. Ethernet standard
501 specify 46 bytes as the minimum for valid payload. However, this is
502 artificial in so far as for certain packet types, notably ARP, less
503 then 46 bytes are needed to contain the full information. In a non
504 virtualized environment the 46 bytes rule is enforced in order to give
505 guarantee in the collison detection scheme. Of course, this being a
506 driver for a VPC2007, we won't have collisions and I can only suppose
507 MS decided to cut packet size to true minimum, regardless of the
508 46 bytes payload standard. Note that this seems to not happen in
509 bridged mode. Note also, that the card does not return runt or
510 incomplete frames to us, so this hack is safe
513 bzero(&descr
->buf1
[size
], 60-size
);
518 iovp
= &dep
->de_read_iovec
;
519 buffer
= descr
->buf1
;
520 dep
->bytes_rx
+= size
;
521 dep
->de_stat
.ets_packetR
++;
522 dep
->de_read_s
= size
;
525 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of buffer */
529 r
= sys_safecopyto(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
, 0,
530 (vir_bytes
)buffer
, bytes
, D
);
532 panic(str_DevName
, str_CopyErrMsg
, r
);
535 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
539 } while ((size
-= bytes
) > 0);
541 descr
->descr
->des
[DES0
]=DES0_OWN
;
542 dep
->cur_descr
[DESCR_RECV
]++;
543 if(dep
->cur_descr
[DESCR_RECV
] >= DE_NB_RECV_DESCR
)
544 dep
->cur_descr
[DESCR_RECV
] = 0;
546 DEBUG(printf("Read returned size = %d\n", size
));
548 /* Reply information */
549 dep
->de_flags
|= DEF_ACK_RECV
;
550 dep
->de_flags
&= NOT(DEF_READING
);
554 do_reply(dep
, OK
, FALSE
);
560 assert(dep
->de_flags
& DEF_READING
);
564 assert(!(dep
->de_flags
& DEF_READING
));
565 dep
->rx_return_msg
= *mp
;
566 dep
->de_flags
|= DEF_READING
;
567 do_reply(dep
, OK
, FALSE
);
571 PRIVATE
void de_conf_addr(dpeth_t
* dep
)
573 static char ea_fmt
[] = "x:x:x:x:x:x";
578 /* TODO: should be configurable... */
579 strcpy(ea_key
, "DEETH0");
580 strcat(ea_key
, "_EA");
582 for (ix
= 0; ix
< SA_ADDR_LEN
; ix
++) {
583 val
= dep
->de_address
.ea_addr
[ix
];
584 if (env_parse(ea_key
, ea_fmt
, ix
, &val
, 0x00L
, 0xFFL
) != EP_SET
)
586 dep
->de_address
.ea_addr
[ix
] = val
;
589 if (ix
!= 0 && ix
!= SA_ADDR_LEN
)
590 env_parse(ea_key
, "?", 0, &val
, 0L, 0L);
594 PRIVATE
void do_fkey(message
*mp
)
600 for (port
= 0, dep
= de_table
; port
< DE_PORT_NR
; port
+= 1, dep
+= 1) {
601 if (dep
->de_mode
== DEM_DISABLED
) continue;
602 printf("%s status:\n", dep
->de_name
);
605 printf("%02X%c",dep
->de_address
.ea_addr
[i
], i
!=5?':':'\n');
606 printf("Tx packets: %-16d Tx kb: %d.%02d\n", dep
->de_stat
.ets_packetT
,
608 (int)(((dep
->bytes_tx
%1024)/1024.0)*100));
609 printf("Rx packets: %-16d Rx kb: %d.%02d\n", dep
->de_stat
.ets_packetR
,
611 (int)(((dep
->bytes_rx
%1024)/1024.0)*100));
612 printf("Rx errors: %-16d Tx errors: %d\n",
613 dep
->de_stat
.ets_recvErr
,
614 dep
->de_stat
.ets_sendErr
);
619 PRIVATE
void de_first_init(dpeth_t
*dep
){
621 vir_bytes descr_vir
= dep
->sendrecv_descr_buf
;
622 vir_bytes buffer_vir
= dep
->sendrecv_buf
;
623 de_descr_t
*phys_descr
;
624 de_loc_descr_t
*loc_descr
;
629 loc_descr
= &dep
->descr
[i
][0];
630 for(j
=0; j
< (i
==DESCR_RECV
? DE_NB_RECV_DESCR
: DE_NB_SEND_DESCR
); j
++){
632 /* assign buffer space for descriptor */
633 loc_descr
->descr
= descr_vir
;
634 descr_vir
+= sizeof(de_descr_t
);
636 /* assign space for buffer */
637 loc_descr
->buf1
= buffer_vir
;
638 buffer_vir
+= (i
==DESCR_RECV
? DE_RECV_BUF_SIZE
: DE_SEND_BUF_SIZE
);
644 /* Now that we have buffer space and descriptors, we need to
645 obtain their physical address to pass to the hardware
648 loc_descr
= &dep
->descr
[i
][0];
649 temp
= (i
==DESCR_RECV
? DE_RECV_BUF_SIZE
: DE_SEND_BUF_SIZE
);
650 for(j
=0; j
< (i
==DESCR_RECV
? DE_NB_RECV_DESCR
: DE_NB_SEND_DESCR
); j
++){
651 /* translate buffers physical address */
652 r
= sys_umap(SELF
, VM_D
, loc_descr
->buf1
, temp
,
653 &(loc_descr
->descr
->des
[DES_BUF1
]));
654 if(r
!= OK
) panic(dep
->de_name
, "umap failed", r
);
655 loc_descr
->descr
->des
[DES_BUF2
] = 0;
656 memset(&loc_descr
->descr
->des
[DES0
],0,sizeof(u32_t
));
657 loc_descr
->descr
->des
[DES1
] = temp
;
658 if(j
==( (i
==DESCR_RECV
?DE_NB_RECV_DESCR
:DE_NB_SEND_DESCR
)-1))
659 loc_descr
->descr
->des
[DES1
] |= DES1_ER
;
661 loc_descr
->descr
->des
[DES0
] |= DES0_OWN
;
666 /* record physical location of two first descriptor */
667 r
= sys_umap(SELF
, VM_D
, dep
->descr
[DESCR_RECV
][0].descr
,
668 sizeof(de_descr_t
), &dep
->sendrecv_descr_phys_addr
[DESCR_RECV
]);
669 if(r
!= OK
) panic(str_DevName
, str_UmapErrMsg
, r
);
671 r
= sys_umap(SELF
, VM_D
, dep
->descr
[DESCR_TRAN
][0].descr
,
672 sizeof(de_descr_t
), &dep
->sendrecv_descr_phys_addr
[DESCR_TRAN
]);
673 if(r
!= OK
) panic(str_DevName
, str_UmapErrMsg
, r
);
675 DEBUG(printf("Descr: head tran=[%08X] head recv=[%08X]\n",
676 dep
->sendrecv_descr_phys_addr
[DESCR_TRAN
],
677 dep
->sendrecv_descr_phys_addr
[DESCR_RECV
]));
679 /* check alignment just to be extra safe */
681 loc_descr
= &dep
->descr
[i
][0];
682 for(j
=0;j
< (i
==DESCR_RECV
?DE_NB_RECV_DESCR
:DE_NB_SEND_DESCR
);j
++){
683 r
= sys_umap(SELF
, VM_D
, &(loc_descr
->descr
), sizeof(de_descr_t
),
686 panic(str_DevName
, str_UmapErrMsg
, r
);
688 if( ((loc_descr
->descr
->des
[DES_BUF1
] & 0x3) != 0) ||
689 ((loc_descr
->descr
->des
[DES_BUF2
] & 0x3) != 0) ||
691 panic(str_DevName
, str_AlignErrMsg
, temp
);
697 /* Init default values */
698 dep
->cur_descr
[DESCR_TRAN
]=1;
699 dep
->cur_descr
[DESCR_RECV
]=0;
703 /* Set the interrupt handler policy. Request interrupts not to be reenabled
704 * automatically. Return the IRQ line number when an interrupt occurs.
706 dep
->de_hook
= dep
->de_irq
;
707 sys_irqsetpolicy(dep
->de_irq
, 0, &dep
->de_hook
);
708 sys_irqenable(&dep
->de_hook
);
711 PRIVATE
void do_interrupt(dpeth_t
*dep
){
713 val
= io_inl(CSR_ADDR(dep
, CSR5
));
716 panic(dep
->de_name
, "Abnormal Int CSR5=", val
);
719 if( (dep
->de_flags
& DEF_READING
) && (val
& CSR5_RI
) ){
720 do_vread_s(&dep
->rx_return_msg
, TRUE
);
723 if( (dep
->de_flags
& DEF_SENDING
) && (val
& CSR5_TI
) ){
724 do_vwrite_s(&dep
->tx_return_msg
, TRUE
);
727 /* ack and reset interrupts */
728 io_outl(CSR_ADDR(dep
, CSR5
), 0xFFFFFFFF);
732 PRIVATE
void de_reset(dpeth_t
*dep
){
733 io_outl(CSR_ADDR(dep
, CSR0
), CSR0_SWR
);
734 micro_delay(1000000);
737 PRIVATE
void de_hw_conf(dpeth_t
*dep
){
740 /* CSR0 - global host bus prop */
741 val
= CSR0_BAR
| CSR0_CAL_8
;
742 io_outl(CSR_ADDR(dep
, CSR0
), val
);
744 /* CSR3 - Receive list BAR */
745 val
= dep
->sendrecv_descr_phys_addr
[DESCR_RECV
];
746 io_outl(CSR_ADDR(dep
, CSR3
), val
);
748 /* CSR4 - Transmit list BAR */
749 val
= dep
->sendrecv_descr_phys_addr
[DESCR_TRAN
];
750 io_outl(CSR_ADDR(dep
, CSR4
), val
);
752 /* CSR7 - interrupt mask */
753 val
= CSR7_TI
| CSR7_RI
| CSR7_AI
;
754 io_outl(CSR_ADDR(dep
, CSR7
), val
);
756 /* CSR6 - operating mode register */
757 val
= CSR6_MBO
| CSR6_PS
| CSR6_FD
| CSR6_HBD
|
758 CSR6_PCS
| CSR6_SCR
| CSR6_TR_00
;
759 io_outl(CSR_ADDR(dep
, CSR6
), val
);
762 PRIVATE
void de_start(dpeth_t
*dep
){
764 val
= io_inl(CSR_ADDR(dep
, CSR6
)) | CSR6_ST
| CSR6_SR
;
765 io_outl(CSR_ADDR(dep
, CSR6
), val
);
768 PRIVATE
void de_setup_frame(dpeth_t
*dep
){
772 /* this is not perfect... we assume pass all multicast and only
773 filter non-multicast frames */
774 dep
->descr
[DESCR_TRAN
][0].buf1
[0] = 0xFF;
775 dep
->descr
[DESCR_TRAN
][0].buf1
[1] = 0xFF;
776 dep
->descr
[DESCR_TRAN
][0].buf1
[4] = 0xFF;
777 dep
->descr
[DESCR_TRAN
][0].buf1
[5] = 0xFF;
778 dep
->descr
[DESCR_TRAN
][0].buf1
[8] = 0xFF;
779 dep
->descr
[DESCR_TRAN
][0].buf1
[9] = 0xFF;
781 memset(&(dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
]), 0, 12);
782 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+0] = dep
->de_address
.ea_addr
[0];
783 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+1] = dep
->de_address
.ea_addr
[1];
784 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+4] = dep
->de_address
.ea_addr
[2];
785 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+5] = dep
->de_address
.ea_addr
[3];
786 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+8] = dep
->de_address
.ea_addr
[4];
787 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+9] = dep
->de_address
.ea_addr
[5];
790 dep
->descr
[DESCR_TRAN
][0].descr
->des
[DES0
] = DES0_OWN
;
791 dep
->descr
[DESCR_TRAN
][0].descr
->des
[DES1
] = DES1_SET
|
792 DE_SETUP_FRAME_SIZE
| DES1_IC
;
794 /* start transmit process to process setup frame */
795 val
= io_inl(CSR_ADDR(dep
, CSR6
)) | CSR6_ST
;
796 io_outl(CSR_ADDR(dep
, CSR6
), val
);
797 io_outl(CSR_ADDR(dep
, CSR1
), 0xFFFFFFFF);
802 PRIVATE
int de_calc_iov_size(iovec_dat_s_t
* iovp
){
807 size
+= iovp
->iod_iovec
[ix
].iov_size
;
808 if (++ix
>= IOVEC_NR
) {
812 } while (ix
< iovp
->iod_iovec_s
);
816 PRIVATE
void de_get_userdata_s(int user_proc
, cp_grant_id_t grant
,
817 vir_bytes offset
, int count
, void *loc_addr
){
821 len
= (count
> IOVEC_NR
? IOVEC_NR
: count
) * sizeof(iovec_t
);
822 rc
= sys_safecopyfrom(user_proc
, grant
, 0, (vir_bytes
)loc_addr
, len
, D
);
824 panic(str_DevName
, str_CopyErrMsg
, rc
);
828 PRIVATE
void de_next_iov(iovec_dat_s_t
* iovp
){
830 iovp
->iod_iovec_s
-= IOVEC_NR
;
831 iovp
->iod_iovec_offset
+= IOVEC_NR
* sizeof(iovec_t
);
832 de_get_userdata_s(iovp
->iod_proc_nr
, iovp
->iod_grant
, iovp
->iod_iovec_offset
,
833 iovp
->iod_iovec_s
, iovp
->iod_iovec
);
837 PRIVATE
void do_vwrite_s(message
* mp
, int from_int
){
838 static u8_t setupDone
= 0;
839 int size
, r
, bytes
, ix
, totalsize
;
841 iovec_dat_s_t
*iovp
= NULL
;
842 de_loc_descr_t
*descr
= NULL
;
845 if( mp
->DL_PORT
< 0 || mp
->DL_PORT
>= DE_PORT_NR
)
846 panic(str_DevName
, str_PortErrMsg
, mp
->DL_PORT
);
848 dep
= &de_table
[mp
->DL_PORT
];
849 dep
->de_client
= mp
->DL_PROC
;
851 if (dep
->de_mode
== DEM_ENABLED
) {
853 if (!from_int
&& (dep
->de_flags
& DEF_SENDING
))
854 panic(str_DevName
, str_BusyErrMsg
, NO_NUM
);
856 descr
= &dep
->descr
[DESCR_TRAN
][dep
->cur_descr
[DESCR_TRAN
]];
858 if(( descr
->descr
->des
[DES0
] & DES0_OWN
)!=0)
861 if(!setupDone
&& (dep
->cur_descr
[DESCR_TRAN
] == 0) ){
862 dep
->descr
[DESCR_TRAN
][0].descr
->des
[DES0
] = 0;
866 buffer
= descr
->buf1
;
867 iovp
= &dep
->de_write_iovec
;
868 iovp
->iod_proc_nr
= mp
->DL_PROC
;
869 de_get_userdata_s(mp
->DL_PROC
, mp
->DL_GRANT
, 0,
870 mp
->DL_COUNT
, iovp
->iod_iovec
);
871 iovp
->iod_iovec_s
= mp
->DL_COUNT
;
872 iovp
->iod_grant
= (vir_bytes
) mp
->DL_GRANT
;
873 iovp
->iod_iovec_offset
= 0;
874 totalsize
= size
= de_calc_iov_size(iovp
);
875 if (size
< ETH_MIN_PACK_SIZE
|| size
> ETH_MAX_PACK_SIZE
)
876 panic(str_DevName
, str_SizeErrMsg
, size
);
878 dep
->bytes_tx
+= size
;
879 dep
->de_stat
.ets_packetT
++;
883 bytes
= iovp
->iod_iovec
[ix
].iov_size
;
887 r
= sys_safecopyfrom(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
,
888 0, (vir_bytes
)buffer
, bytes
, D
);
890 panic(str_DevName
, str_CopyErrMsg
, r
);
893 if (++ix
>= IOVEC_NR
) {
897 } while ((size
-= bytes
) > 0);
899 descr
->descr
->des
[DES1
] = (descr
->descr
->des
[DES1
]&DES1_ER
) |
900 DES1_FS
| DES1_LS
| DES1_IC
| totalsize
;
901 descr
->descr
->des
[DES0
] = DES0_OWN
;
903 dep
->cur_descr
[DESCR_TRAN
]++;
904 if(dep
->cur_descr
[DESCR_TRAN
] >= DE_NB_SEND_DESCR
)
905 dep
->cur_descr
[DESCR_TRAN
] = 0;
907 io_outl(CSR_ADDR(dep
, CSR1
), 0xFFFFFFFF);
910 dep
->de_flags
|= DEF_ACK_SEND
;
912 dep
->de_flags
&= NOT(DEF_SENDING
);
915 do_reply(dep
, OK
, FALSE
);
920 panic(str_DevName
, "should not happen", 0);
922 dep
->de_stat
.ets_transDef
++;
923 dep
->de_flags
|= DEF_SENDING
;
924 dep
->de_stat
.ets_transDef
++;
925 dep
->tx_return_msg
= *mp
;
926 do_reply(dep
, OK
, FALSE
);
929 PRIVATE
void warning(const char *type
, int err
){
930 printf("Warning: %s sys_%s failed (%d)\n", str_DevName
, type
, err
);
934 PRIVATE u32_t
io_inl(u16_t port
){
937 if ((rc
= sys_inl(port
, &value
)) != OK
) warning("inl", rc
);
941 PRIVATE
void io_outl(u16_t port
, u32_t value
){
943 if ((rc
= sys_outl(port
, value
)) != OK
) warning("outl", rc
);