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>
21 #include <net/gen/ether.h>
22 #include <net/gen/eth_io.h>
25 #include "dec21140A.h"
28 _PROTOTYPE( PRIVATE u32_t io_inl
, (u16_t
); );
29 _PROTOTYPE( PRIVATE
void io_outl
, (u16_t
, u32_t
); );
30 _PROTOTYPE( PRIVATE
void do_conf
, (message
*); );
31 _PROTOTYPE( PRIVATE
void do_get_name
, (message
*); );
32 _PROTOTYPE( PRIVATE
void do_get_stat_s
, (message
*); );
33 _PROTOTYPE( PRIVATE
void do_interrupt
, (dpeth_t
*); );
34 _PROTOTYPE( PRIVATE
void do_reply
, (dpeth_t
*, int, int); );
35 _PROTOTYPE( PRIVATE
void do_vread_s
, (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
*); );
40 _PROTOTYPE( PRIVATE
void de_conf_addr
, (dpeth_t
*); );
41 _PROTOTYPE( PRIVATE
void de_first_init
, (dpeth_t
*); );
42 _PROTOTYPE( PRIVATE
void de_reset
, (dpeth_t
*); );
43 _PROTOTYPE( PRIVATE
void de_hw_conf
, (dpeth_t
*); );
44 _PROTOTYPE( PRIVATE
void de_start
, (dpeth_t
*); );
45 _PROTOTYPE( PRIVATE
void de_setup_frame
, (dpeth_t
*); );
46 _PROTOTYPE( PRIVATE u16_t de_read_rom
, (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
, (message
*, int); );
50 _PROTOTYPE( PRIVATE
void de_get_userdata_s
, (int, cp_grant_id_t
,
51 vir_bytes
, int, void *); );
54 static char str_CopyErrMsg
[] = "unable to read/write user data";
55 static char str_PortErrMsg
[] = "illegal port";
56 static char str_SendErrMsg
[] = "send failed";
57 static char str_SizeErrMsg
[] = "illegal packet size";
58 static char str_UmapErrMsg
[] = "Unable to sys_umap";
59 static char str_BusyErrMsg
[] = "Send/Recv failed: busy";
60 static char str_StatErrMsg
[] = "Unable to send stats";
61 static char str_AlignErrMsg
[] = "Bad align of buffer/descriptor";
62 static char str_DevName
[] = "dec21140A:eth#?";
64 PRIVATE dpeth_t de_table
[DE_PORT_NR
];
65 PRIVATE
const char *progname
;
67 int sef_cb_init(int type
, sef_init_info_t
*info
)
72 /* Request function key for debug dumps */
73 fkeys
= sfkeys
= 0; bit_set(sfkeys
, DE_FKEY
);
74 if ((fkey_map(&fkeys
, &sfkeys
)) != OK
)
75 printf("%s: error using Shift+F%d key(%d)\n", str_DevName
, DE_FKEY
, errno
);
77 /* Try to notify inet that we are present (again) */
78 r
= ds_retrieve_label_num("inet", &tasknr
);
82 printf("%s unable to notify inet: %d\n", str_DevName
, r
);
87 /*===========================================================================*
89 *===========================================================================*/
90 int main(int argc
, char *argv
[])
96 (progname
=strrchr(argv
[0],'/')) ? progname
++ : (progname
=argv
[0]);
98 env_setargs(argc
, argv
);
100 sef_setcb_init_fresh(sef_cb_init
);
101 sef_setcb_init_restart(sef_cb_init
);
106 if ((r
= sef_receive(ANY
, &m
)) != OK
)
107 panic("minix msg sef_receive failed: %d", r
);
109 if(is_notify(m
.m_type
)) {
110 switch(_ENDPOINT_P(m
.m_source
)) {
119 for (dep
= de_table
; dep
< &de_table
[DE_PORT_NR
]; dep
+= 1) {
120 if (dep
->de_mode
== DEM_ENABLED
) {
122 if (dep
->de_flags
& (DEF_ACK_SEND
| DEF_ACK_RECV
))
123 do_reply(dep
, OK
, TRUE
);
124 sys_irqenable(&dep
->de_hook
);
132 printf("ignoring notify from %d\n", m
.m_source
);
140 case DL_WRITEV_S
: do_vwrite_s(&m
, FALSE
); break;
141 case DL_READV_S
: do_vread_s(&m
, FALSE
); break;
142 case DL_CONF
: do_conf(&m
); break;
143 case DL_GETSTAT_S
: do_get_stat_s(&m
); break;
144 case DL_GETNAME
: do_get_name(&m
); break;
145 case DL_STOP
: /* nothing */ break;
148 printf("message 0x%lx; %d from %d\n",
149 m
.m_type
, m
.m_type
-DL_RQ_BASE
, m
.m_source
);
150 panic("illegal message: %d", m
.m_type
);
155 PRIVATE
void do_get_stat_s(message
* mp
)
161 if (port
< 0 || port
>= DE_PORT_NR
)
162 panic(str_PortErrMsg
, port
);
164 dep
= &de_table
[port
];
165 dep
->de_client
= mp
->DL_PROC
;
167 if ((rc
= sys_safecopyto(mp
->DL_PROC
, mp
->DL_GRANT
, 0,
168 (vir_bytes
)&dep
->de_stat
,
169 (vir_bytes
) sizeof(dep
->de_stat
), 0)) != OK
)
170 panic(str_CopyErrMsg
, rc
);
172 mp
->m_type
= DL_STAT_REPLY
;
175 rc
= send(mp
->m_source
, mp
);
177 panic(str_StatErrMsg
, rc
);
181 PRIVATE
void do_conf(message
* mp
)
188 if (port
>= 0 && port
< DE_PORT_NR
) {
190 dep
= &de_table
[port
];
191 strncpy(dep
->de_name
, str_DevName
, strlen(str_DevName
));
192 dep
->de_name
[strlen(dep
->de_name
)-1] = '0' + port
;
194 if (dep
->de_mode
== DEM_DISABLED
) {
197 if (dep
->de_mode
== DEM_ENABLED
&& !de_probe(dep
)) {
198 printf("%s: warning no ethernet card found at 0x%04X\n",
199 dep
->de_name
, dep
->de_base_port
);
200 dep
->de_mode
= DEM_DISABLED
;
204 /* 'de_mode' may change if probe routines fail, test again */
205 switch (dep
->de_mode
) {
208 port
= ENXIO
; /* Device is OFF or hardware probe failed */
212 if (dep
->de_flags
== DEF_EMPTY
) {
214 dep
->de_flags
|= DEF_ENABLED
;
221 /* TODO CHECK PROMISC AND MULTI */
222 dep
->de_flags
&= NOT(DEF_PROMISC
| DEF_MULTI
| DEF_BROAD
);
223 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
224 dep
->de_flags
|= DEF_PROMISC
| DEF_MULTI
| DEF_BROAD
;
225 if (mp
->DL_MODE
& DL_MULTI_REQ
) dep
->de_flags
|= DEF_MULTI
;
226 if (mp
->DL_MODE
& DL_BROAD_REQ
) dep
->de_flags
|= DEF_BROAD
;
227 dep
->de_client
= mp
->m_source
;
231 DEBUG(printf("%s running in sink mode\n", str_DevName
));
232 memset(dep
->de_address
.ea_addr
, 0, sizeof(ether_addr_t
));
238 } else /* Port number is out of range */
241 reply_mess
.m_type
= DL_CONF_REPLY
;
242 reply_mess
.m3_i1
= port
;
243 reply_mess
.m3_i2
= DE_PORT_NR
;
244 *(ether_addr_t
*) reply_mess
.m3_ca1
= dep
->de_address
;
246 if (send(mp
->m_source
, &reply_mess
) != OK
)
247 panic(str_SendErrMsg
, mp
->m_source
);
253 PRIVATE
void do_get_name(mp
)
257 strncpy(mp
->DL_NAME
, progname
, sizeof(mp
->DL_NAME
));
258 mp
->DL_NAME
[sizeof(mp
->DL_NAME
)-1]= '\0';
259 mp
->m_type
= DL_NAME_REPLY
;
260 r
= send(mp
->m_source
, mp
);
262 panic("do_getname: send failed: %d", r
);
265 PRIVATE
void do_reply(dpeth_t
* dep
, int err
, int may_block
)
270 if (dep
->de_flags
& DEF_ACK_SEND
) status
|= DL_PACK_SEND
;
271 if (dep
->de_flags
& DEF_ACK_RECV
) status
|= DL_PACK_RECV
;
273 reply
.m_type
= DL_TASK_REPLY
;
274 reply
.DL_PORT
= dep
- de_table
;
275 reply
.DL_PROC
= dep
->de_client
;
276 reply
.DL_STAT
= status
| ((u32_t
) err
<< 16);
277 reply
.DL_COUNT
= dep
->de_read_s
;
280 status
= send(dep
->de_client
, &reply
);
282 if(status
== ELOCKED
&& may_block
){
283 /*printf("Warning: Dec21041 send lock prevented\n\n");*/
288 panic(str_SendErrMsg
, status
);
291 dep
->de_flags
&= NOT(DEF_ACK_SEND
| DEF_ACK_RECV
);
295 PRIVATE
void do_watchdog(void *message
)
297 /* nothing here yet */
301 PRIVATE
int de_probe(dpeth_t
*dep
){
303 u16_t vid
, did
, temp16
;
305 DEBUG(printf("PROBING..."));
307 r
= pci_first_dev(&devind
, &vid
, &did
);
313 if ( DEC21140A_VID
== vid
&&
314 DEC21140A_DID
== did
)
317 r
= pci_next_dev(&devind
, &vid
, &did
);
324 dep
->de_base_port
= pci_attr_r32(devind
, PCI_BAR
) & 0xffffffe0;
325 dep
->de_irq
= pci_attr_r8(devind
, PCI_ILR
);
327 if (dep
->de_base_port
< DE_MIN_BASE_ADDR
)
328 panic("de_probe: base address invalid: %d", dep
->de_base_port
);
330 DEBUG(printf("%s: using I/O address 0x%lx, IRQ %d\n",
331 dep
->de_name
, (unsigned long)dep
->de_base_port
,
334 dep
->de_type
= pci_attr_r8(devind
, PCI_REV
);
336 /* device validation. We support only the DEC21140A */
337 if(dep
->de_type
!= DEC_21140A
){
338 dep
->de_type
= DE_TYPE_UNKNOWN
;
339 printf("%s: unsupported device\n", str_DevName
);
345 DEBUG(printf("Reading SROM...\n"));
347 for(i
=0;i
<(1<<SROM_BITWIDTH
)-1;i
++){
348 temp16
= de_read_rom(dep
, i
, SROM_BITWIDTH
);
349 dep
->srom
[i
*2] = temp16
& 0xFF;
350 dep
->srom
[i
*2+1] = temp16
>> 8;
353 /* TODO: validate SROM content */
354 /* acquire MAC addr */
355 DEBUG(printf("Using MAC addr= "));
357 dep
->de_address
.ea_addr
[i
] = dep
->srom
[i
+DE_SROM_EA_OFFSET
];
358 DEBUG(printf("%02X%c",dep
->de_address
.ea_addr
[i
],i
!=5?'-':'\n'));
360 DEBUG(printf("probe success\n"));
364 PRIVATE u16_t
de_read_rom(dpeth_t
*dep
, u8_t addr
, u8_t nbAddrBits
){
368 u32_t csr2
= 0; /* csr2 is used to hold constant values that are
369 setup in the init phase, it makes this a little
370 more readable, the following macro is also just
371 to clear up the code a little.*/
373 #define EMIT do { io_outl(CSR_ADDR(dep, CSR9), csr | csr2); io_outl(CSR_ADDR(dep, CSR1), 0);} while(0)
378 csr
= CSR9_SR
| CSR9_RD
; EMIT
;
380 csr2
= CSR9_SR
| CSR9_RD
;
385 csr
= CSR9_SRC
; EMIT
;
390 csr
= CSR9_DI
| CSR9_SRC
; EMIT
;
392 csr
= CSR9_DI
| CSR9_SRC
; EMIT
;
395 csr
= CSR9_SRC
; EMIT
;
399 for(i
=nbAddrBits
;i
!=0;i
--){
400 csr
= (addr
&(1<<(i
-1))) != 0 ? CSR9_DI
: 0; EMIT
;
401 csr
^= CSR9_SRC
; EMIT
;
402 csr
^= CSR9_SRC
; EMIT
;
409 csr
= CSR9_SRC
; EMIT
;
410 retVal
|= (io_inl(CSR_ADDR(dep
, CSR9
)) & CSR9_DO
) == 0 ? 0 : 1;
421 static void de_update_conf(dpeth_t
* dep
)
423 static char dpc_fmt
[] = "x:d:x";
426 dep
->de_mode
= DEM_ENABLED
;
427 switch (env_parse("DEETH0", dpc_fmt
, 0, &val
, 0x000L
, 0x3FFL
)) {
428 case EP_OFF
: dep
->de_mode
= DEM_DISABLED
; break;
429 case EP_ON
: dep
->de_mode
= DEM_SINK
; break;
431 dep
->de_base_port
= 0;
436 PRIVATE
void do_vread_s(message
* mp
, int from_int
)
440 int r
, bytes
, ix
= 0;
442 de_loc_descr_t
*descr
= NULL
;
443 iovec_dat_s_t
*iovp
= NULL
;
445 if (mp
->DL_PORT
< 0 || mp
->DL_PORT
>= DE_PORT_NR
)
446 panic(str_PortErrMsg
, mp
->DL_PORT
);
448 dep
= &de_table
[mp
->DL_PORT
];
449 dep
->de_client
= mp
->DL_PROC
;
451 if (dep
->de_mode
== DEM_ENABLED
) {
453 descr
= &dep
->descr
[DESCR_RECV
][dep
->cur_descr
[DESCR_RECV
]];
455 /* check if packet is in the current descr and only there */
456 if( !( !(descr
->descr
->des
[DES0
] & DES0_OWN
) &&
457 (descr
->descr
->des
[DES0
] & DES0_FS
) &&
458 (descr
->descr
->des
[DES0
] & DES0_LS
) ))
462 /*TODO: multi-descr msgs...*/
463 /* We only support packets contained in a single descriptor.
464 Setting the descriptor buffer size to less then
465 ETH_MAX_PACK_SIZE will result in multi-descriptor
466 packets that we won't be able to handle
468 assert(!(descr
->descr
->des
[DES0
]&DES0_OWN
));
469 assert(descr
->descr
->des
[DES0
]&DES0_FS
);
470 assert(descr
->descr
->des
[DES0
]&DES0_LS
);
472 /* Check for abnormal messages. We assert here
473 because this driver is for a virtualized
474 envrionment where we will not get bad packets
476 assert(!(descr
->descr
->des
[DES0
]&DES0_ES
));
477 assert(!(descr
->descr
->des
[DES0
]&DES0_RE
));
480 /* Setup the iovec entry to allow copying into
483 dep
->de_read_iovec
.iod_proc_nr
= mp
->DL_PROC
;
484 de_get_userdata_s(mp
->DL_PROC
, (cp_grant_id_t
) mp
->DL_GRANT
, 0,
485 mp
->DL_COUNT
, dep
->de_read_iovec
.iod_iovec
);
486 dep
->de_read_iovec
.iod_iovec_s
= mp
->DL_COUNT
;
487 dep
->de_read_iovec
.iod_grant
= (cp_grant_id_t
) mp
->DL_GRANT
;
488 dep
->de_read_iovec
.iod_iovec_offset
= 0;
489 size
= de_calc_iov_size(&dep
->de_read_iovec
);
490 if (size
< ETH_MAX_PACK_SIZE
)
491 panic(str_SizeErrMsg
, size
);
493 /* Copy buffer to user area and clear ownage */
494 size
= (descr
->descr
->des
[DES0
]&DES0_FL
)>>DES0_FL_SHIFT
;
496 /*TODO: Complain to MS */
497 /*HACK: VPC2007 returns packet of invalid size. Ethernet standard
498 specify 46 bytes as the minimum for valid payload. However, this is
499 artificial in so far as for certain packet types, notably ARP, less
500 then 46 bytes are needed to contain the full information. In a non
501 virtualized environment the 46 bytes rule is enforced in order to give
502 guarantee in the collison detection scheme. Of course, this being a
503 driver for a VPC2007, we won't have collisions and I can only suppose
504 MS decided to cut packet size to true minimum, regardless of the
505 46 bytes payload standard. Note that this seems to not happen in
506 bridged mode. Note also, that the card does not return runt or
507 incomplete frames to us, so this hack is safe
510 bzero(&descr
->buf1
[size
], 60-size
);
515 iovp
= &dep
->de_read_iovec
;
516 buffer
= descr
->buf1
;
517 dep
->bytes_rx
+= size
;
518 dep
->de_stat
.ets_packetR
++;
519 dep
->de_read_s
= size
;
522 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of buffer */
526 r
= sys_safecopyto(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
, 0,
527 (vir_bytes
)buffer
, bytes
, D
);
529 panic(str_CopyErrMsg
, r
);
532 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
536 } while ((size
-= bytes
) > 0);
538 descr
->descr
->des
[DES0
]=DES0_OWN
;
539 dep
->cur_descr
[DESCR_RECV
]++;
540 if(dep
->cur_descr
[DESCR_RECV
] >= DE_NB_RECV_DESCR
)
541 dep
->cur_descr
[DESCR_RECV
] = 0;
543 DEBUG(printf("Read returned size = %d\n", size
));
545 /* Reply information */
546 dep
->de_flags
|= DEF_ACK_RECV
;
547 dep
->de_flags
&= NOT(DEF_READING
);
551 do_reply(dep
, OK
, FALSE
);
557 assert(dep
->de_flags
& DEF_READING
);
561 assert(!(dep
->de_flags
& DEF_READING
));
562 dep
->rx_return_msg
= *mp
;
563 dep
->de_flags
|= DEF_READING
;
564 do_reply(dep
, OK
, FALSE
);
568 PRIVATE
void de_conf_addr(dpeth_t
* dep
)
570 static char ea_fmt
[] = "x:x:x:x:x:x";
575 /* TODO: should be configurable... */
576 strcpy(ea_key
, "DEETH0");
577 strcat(ea_key
, "_EA");
579 for (ix
= 0; ix
< SA_ADDR_LEN
; ix
++) {
580 val
= dep
->de_address
.ea_addr
[ix
];
581 if (env_parse(ea_key
, ea_fmt
, ix
, &val
, 0x00L
, 0xFFL
) != EP_SET
)
583 dep
->de_address
.ea_addr
[ix
] = val
;
586 if (ix
!= 0 && ix
!= SA_ADDR_LEN
)
587 env_parse(ea_key
, "?", 0, &val
, 0L, 0L);
591 PRIVATE
void de_first_init(dpeth_t
*dep
)
594 vir_bytes descr_vir
= dep
->sendrecv_descr_buf
;
595 vir_bytes buffer_vir
= dep
->sendrecv_buf
;
596 de_descr_t
*phys_descr
;
597 de_loc_descr_t
*loc_descr
;
602 loc_descr
= &dep
->descr
[i
][0];
603 for(j
=0; j
< (i
==DESCR_RECV
? DE_NB_RECV_DESCR
: DE_NB_SEND_DESCR
); j
++){
605 /* assign buffer space for descriptor */
606 loc_descr
->descr
= descr_vir
;
607 descr_vir
+= sizeof(de_descr_t
);
609 /* assign space for buffer */
610 loc_descr
->buf1
= buffer_vir
;
611 buffer_vir
+= (i
==DESCR_RECV
? DE_RECV_BUF_SIZE
: DE_SEND_BUF_SIZE
);
617 /* Now that we have buffer space and descriptors, we need to
618 obtain their physical address to pass to the hardware
621 loc_descr
= &dep
->descr
[i
][0];
622 temp
= (i
==DESCR_RECV
? DE_RECV_BUF_SIZE
: DE_SEND_BUF_SIZE
);
623 for(j
=0; j
< (i
==DESCR_RECV
? DE_NB_RECV_DESCR
: DE_NB_SEND_DESCR
); j
++){
624 /* translate buffers physical address */
625 r
= sys_umap(SELF
, VM_D
, loc_descr
->buf1
, temp
,
626 &(loc_descr
->descr
->des
[DES_BUF1
]));
627 if(r
!= OK
) panic("umap failed: %d", r
);
628 loc_descr
->descr
->des
[DES_BUF2
] = 0;
629 memset(&loc_descr
->descr
->des
[DES0
],0,sizeof(u32_t
));
630 loc_descr
->descr
->des
[DES1
] = temp
;
631 if(j
==( (i
==DESCR_RECV
?DE_NB_RECV_DESCR
:DE_NB_SEND_DESCR
)-1))
632 loc_descr
->descr
->des
[DES1
] |= DES1_ER
;
634 loc_descr
->descr
->des
[DES0
] |= DES0_OWN
;
639 /* record physical location of two first descriptor */
640 r
= sys_umap(SELF
, VM_D
, dep
->descr
[DESCR_RECV
][0].descr
,
641 sizeof(de_descr_t
), &dep
->sendrecv_descr_phys_addr
[DESCR_RECV
]);
642 if(r
!= OK
) panic(str_UmapErrMsg
, r
);
644 r
= sys_umap(SELF
, VM_D
, dep
->descr
[DESCR_TRAN
][0].descr
,
645 sizeof(de_descr_t
), &dep
->sendrecv_descr_phys_addr
[DESCR_TRAN
]);
646 if(r
!= OK
) panic(str_UmapErrMsg
, r
);
648 DEBUG(printf("Descr: head tran=[%08X] head recv=[%08X]\n",
649 dep
->sendrecv_descr_phys_addr
[DESCR_TRAN
],
650 dep
->sendrecv_descr_phys_addr
[DESCR_RECV
]));
652 /* check alignment just to be extra safe */
654 loc_descr
= &dep
->descr
[i
][0];
655 for(j
=0;j
< (i
==DESCR_RECV
?DE_NB_RECV_DESCR
:DE_NB_SEND_DESCR
);j
++){
656 r
= sys_umap(SELF
, VM_D
, &(loc_descr
->descr
), sizeof(de_descr_t
),
659 panic(str_UmapErrMsg
, r
);
661 if( ((loc_descr
->descr
->des
[DES_BUF1
] & 0x3) != 0) ||
662 ((loc_descr
->descr
->des
[DES_BUF2
] & 0x3) != 0) ||
664 panic(str_AlignErrMsg
, temp
);
670 /* Init default values */
671 dep
->cur_descr
[DESCR_TRAN
]=1;
672 dep
->cur_descr
[DESCR_RECV
]=0;
676 /* Set the interrupt handler policy. Request interrupts not to be reenabled
677 * automatically. Return the IRQ line number when an interrupt occurs.
679 dep
->de_hook
= dep
->de_irq
;
680 sys_irqsetpolicy(dep
->de_irq
, 0, &dep
->de_hook
);
681 sys_irqenable(&dep
->de_hook
);
684 PRIVATE
void do_interrupt(dpeth_t
*dep
){
686 val
= io_inl(CSR_ADDR(dep
, CSR5
));
689 panic("Abnormal Int CSR5=: %d", val
);
692 if( (dep
->de_flags
& DEF_READING
) && (val
& CSR5_RI
) ){
693 do_vread_s(&dep
->rx_return_msg
, TRUE
);
696 if( (dep
->de_flags
& DEF_SENDING
) && (val
& CSR5_TI
) ){
697 do_vwrite_s(&dep
->tx_return_msg
, TRUE
);
700 /* ack and reset interrupts */
701 io_outl(CSR_ADDR(dep
, CSR5
), 0xFFFFFFFF);
705 PRIVATE
void de_reset(dpeth_t
*dep
){
706 io_outl(CSR_ADDR(dep
, CSR0
), CSR0_SWR
);
709 PRIVATE
void de_hw_conf(dpeth_t
*dep
){
712 /* CSR0 - global host bus prop */
713 val
= CSR0_BAR
| CSR0_CAL_8
;
714 io_outl(CSR_ADDR(dep
, CSR0
), val
);
716 /* CSR3 - Receive list BAR */
717 val
= dep
->sendrecv_descr_phys_addr
[DESCR_RECV
];
718 io_outl(CSR_ADDR(dep
, CSR3
), val
);
720 /* CSR4 - Transmit list BAR */
721 val
= dep
->sendrecv_descr_phys_addr
[DESCR_TRAN
];
722 io_outl(CSR_ADDR(dep
, CSR4
), val
);
724 /* CSR7 - interrupt mask */
725 val
= CSR7_TI
| CSR7_RI
| CSR7_AI
;
726 io_outl(CSR_ADDR(dep
, CSR7
), val
);
728 /* CSR6 - operating mode register */
729 val
= CSR6_MBO
| CSR6_PS
| CSR6_FD
| CSR6_HBD
|
730 CSR6_PCS
| CSR6_SCR
| CSR6_TR_00
;
731 io_outl(CSR_ADDR(dep
, CSR6
), val
);
734 PRIVATE
void de_start(dpeth_t
*dep
){
736 val
= io_inl(CSR_ADDR(dep
, CSR6
)) | CSR6_ST
| CSR6_SR
;
737 io_outl(CSR_ADDR(dep
, CSR6
), val
);
740 PRIVATE
void de_setup_frame(dpeth_t
*dep
){
744 /* this is not perfect... we assume pass all multicast and only
745 filter non-multicast frames */
746 dep
->descr
[DESCR_TRAN
][0].buf1
[0] = 0xFF;
747 dep
->descr
[DESCR_TRAN
][0].buf1
[1] = 0xFF;
748 dep
->descr
[DESCR_TRAN
][0].buf1
[4] = 0xFF;
749 dep
->descr
[DESCR_TRAN
][0].buf1
[5] = 0xFF;
750 dep
->descr
[DESCR_TRAN
][0].buf1
[8] = 0xFF;
751 dep
->descr
[DESCR_TRAN
][0].buf1
[9] = 0xFF;
753 memset(&(dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
]), 0, 12);
754 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+0] = dep
->de_address
.ea_addr
[0];
755 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+1] = dep
->de_address
.ea_addr
[1];
756 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+4] = dep
->de_address
.ea_addr
[2];
757 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+5] = dep
->de_address
.ea_addr
[3];
758 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+8] = dep
->de_address
.ea_addr
[4];
759 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+9] = dep
->de_address
.ea_addr
[5];
762 dep
->descr
[DESCR_TRAN
][0].descr
->des
[DES0
] = DES0_OWN
;
763 dep
->descr
[DESCR_TRAN
][0].descr
->des
[DES1
] = DES1_SET
|
764 DE_SETUP_FRAME_SIZE
| DES1_IC
;
766 /* start transmit process to process setup frame */
767 val
= io_inl(CSR_ADDR(dep
, CSR6
)) | CSR6_ST
;
768 io_outl(CSR_ADDR(dep
, CSR6
), val
);
769 io_outl(CSR_ADDR(dep
, CSR1
), 0xFFFFFFFF);
774 PRIVATE
int de_calc_iov_size(iovec_dat_s_t
* iovp
){
779 size
+= iovp
->iod_iovec
[ix
].iov_size
;
780 if (++ix
>= IOVEC_NR
) {
784 } while (ix
< iovp
->iod_iovec_s
);
788 PRIVATE
void de_get_userdata_s(int user_proc
, cp_grant_id_t grant
,
789 vir_bytes offset
, int count
, void *loc_addr
){
793 len
= (count
> IOVEC_NR
? IOVEC_NR
: count
) * sizeof(iovec_t
);
794 rc
= sys_safecopyfrom(user_proc
, grant
, 0, (vir_bytes
)loc_addr
, len
, D
);
796 panic(str_CopyErrMsg
, rc
);
800 PRIVATE
void de_next_iov(iovec_dat_s_t
* iovp
){
802 iovp
->iod_iovec_s
-= IOVEC_NR
;
803 iovp
->iod_iovec_offset
+= IOVEC_NR
* sizeof(iovec_t
);
804 de_get_userdata_s(iovp
->iod_proc_nr
, iovp
->iod_grant
, iovp
->iod_iovec_offset
,
805 iovp
->iod_iovec_s
, iovp
->iod_iovec
);
809 PRIVATE
void do_vwrite_s(message
* mp
, int from_int
){
810 static u8_t setupDone
= 0;
811 int size
, r
, bytes
, ix
, totalsize
;
813 iovec_dat_s_t
*iovp
= NULL
;
814 de_loc_descr_t
*descr
= NULL
;
817 if( mp
->DL_PORT
< 0 || mp
->DL_PORT
>= DE_PORT_NR
)
818 panic(str_PortErrMsg
, mp
->DL_PORT
);
820 dep
= &de_table
[mp
->DL_PORT
];
821 dep
->de_client
= mp
->DL_PROC
;
823 if (dep
->de_mode
== DEM_ENABLED
) {
825 if (!from_int
&& (dep
->de_flags
& DEF_SENDING
))
826 panic(str_BusyErrMsg
);
828 descr
= &dep
->descr
[DESCR_TRAN
][dep
->cur_descr
[DESCR_TRAN
]];
830 if(( descr
->descr
->des
[DES0
] & DES0_OWN
)!=0)
833 if(!setupDone
&& (dep
->cur_descr
[DESCR_TRAN
] == 0) ){
834 dep
->descr
[DESCR_TRAN
][0].descr
->des
[DES0
] = 0;
838 buffer
= descr
->buf1
;
839 iovp
= &dep
->de_write_iovec
;
840 iovp
->iod_proc_nr
= mp
->DL_PROC
;
841 de_get_userdata_s(mp
->DL_PROC
, mp
->DL_GRANT
, 0,
842 mp
->DL_COUNT
, iovp
->iod_iovec
);
843 iovp
->iod_iovec_s
= mp
->DL_COUNT
;
844 iovp
->iod_grant
= (cp_grant_id_t
) mp
->DL_GRANT
;
845 iovp
->iod_iovec_offset
= 0;
846 totalsize
= size
= de_calc_iov_size(iovp
);
847 if (size
< ETH_MIN_PACK_SIZE
|| size
> ETH_MAX_PACK_SIZE
)
848 panic(str_SizeErrMsg
, size
);
850 dep
->bytes_tx
+= size
;
851 dep
->de_stat
.ets_packetT
++;
855 bytes
= iovp
->iod_iovec
[ix
].iov_size
;
859 r
= sys_safecopyfrom(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
,
860 0, (vir_bytes
)buffer
, bytes
, D
);
862 panic(str_CopyErrMsg
, r
);
865 if (++ix
>= IOVEC_NR
) {
869 } while ((size
-= bytes
) > 0);
871 descr
->descr
->des
[DES1
] = (descr
->descr
->des
[DES1
]&DES1_ER
) |
872 DES1_FS
| DES1_LS
| DES1_IC
| totalsize
;
873 descr
->descr
->des
[DES0
] = DES0_OWN
;
875 dep
->cur_descr
[DESCR_TRAN
]++;
876 if(dep
->cur_descr
[DESCR_TRAN
] >= DE_NB_SEND_DESCR
)
877 dep
->cur_descr
[DESCR_TRAN
] = 0;
879 io_outl(CSR_ADDR(dep
, CSR1
), 0xFFFFFFFF);
882 dep
->de_flags
|= DEF_ACK_SEND
;
884 dep
->de_flags
&= NOT(DEF_SENDING
);
887 do_reply(dep
, OK
, FALSE
);
892 panic("should not happen: %d", 0);
894 dep
->de_stat
.ets_transDef
++;
895 dep
->de_flags
|= DEF_SENDING
;
896 dep
->de_stat
.ets_transDef
++;
897 dep
->tx_return_msg
= *mp
;
898 do_reply(dep
, OK
, FALSE
);
901 PRIVATE
void warning(const char *type
, int err
){
902 printf("Warning: %s sys_%s failed (%d)\n", str_DevName
, type
, err
);
906 PRIVATE u32_t
io_inl(u16_t port
){
909 if ((rc
= sys_inl(port
, &value
)) != OK
) warning("inl", rc
);
913 PRIVATE
void io_outl(u16_t port
, u32_t value
){
915 if ((rc
= sys_outl(port
, value
)) != OK
) warning("outl", rc
);