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>
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>
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
, (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 *); );
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 /*===========================================================================*
73 *===========================================================================*/
74 int main(int argc
, char *argv
[])
81 /* SEF local startup. */
82 env_setargs(argc
, argv
);
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
)) {
98 if (dep
->de_mode
== DEM_ENABLED
) {
100 if (dep
->de_flags
& (DEF_ACK_SEND
| DEF_ACK_RECV
))
102 sys_irqenable(&dep
->de_hook
);
106 printf("ignoring notify from %d\n", m
.m_source
);
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;
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. */
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. */
158 (void) env_parse("instance", "d", 0, &v
, 0, 255);
159 de_instance
= (int) v
;
161 /* Request function key for debug dumps */
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();
173 PRIVATE
void do_get_stat_s(message
* mp
)
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
);
188 panic(str_StatErrMsg
, rc
);
192 PRIVATE
void do_conf(const message
* mp
)
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
) {
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
;
215 /* 'de_mode' may change if probe routines fail, test again */
216 switch (dep
->de_mode
) {
219 r
= ENXIO
; /* Device is OFF or hardware probe failed */
223 if (dep
->de_flags
== DEF_EMPTY
) {
225 dep
->de_flags
|= DEF_ENABLED
;
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
;
241 DEBUG(printf("%s running in sink mode\n", str_DevName
));
242 memset(dep
->de_address
.ea_addr
, 0, sizeof(ether_addr_t
));
249 reply_mess
.m_type
= DL_CONF_REPLY
;
250 reply_mess
.DL_STAT
= r
;
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
);
261 PRIVATE
void do_reply(dpeth_t
* dep
)
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
);
276 panic(str_SendErrMsg
, r
);
279 dep
->de_flags
&= NOT(DEF_ACK_SEND
| DEF_ACK_RECV
);
283 PRIVATE
void do_watchdog(void *UNUSED(message
))
285 /* nothing here yet */
289 PRIVATE
int de_probe(dpeth_t
*dep
, int skip
){
291 u16_t vid
, did
, temp16
;
293 DEBUG(printf("PROBING..."));
295 r
= pci_first_dev(&devind
, &vid
, &did
);
301 if ( DEC21140A_VID
== vid
&&
302 DEC21140A_DID
== did
)
309 r
= pci_next_dev(&devind
, &vid
, &did
);
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
,
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
);
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= "));
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"));
356 PRIVATE u16_t
de_read_rom(const dpeth_t
*dep
, u8_t addr
, u8_t nbAddrBits
){
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)
370 csr
= CSR9_SR
| CSR9_RD
; EMIT
;
372 csr2
= CSR9_SR
| CSR9_RD
;
377 csr
= CSR9_SRC
; EMIT
;
382 csr
= CSR9_DI
| CSR9_SRC
; EMIT
;
384 csr
= CSR9_DI
| CSR9_SRC
; EMIT
;
387 csr
= CSR9_SRC
; EMIT
;
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
;
401 csr
= CSR9_SRC
; EMIT
;
402 retVal
|= (io_inl(CSR_ADDR(dep
, CSR9
)) & CSR9_DO
) == 0 ? 0 : 1;
413 static void de_update_conf(dpeth_t
* dep
)
415 static char dpc_fmt
[] = "x:d:x";
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;
432 PRIVATE
void do_vread_s(const message
* mp
, int from_int
)
439 de_loc_descr_t
*descr
= NULL
;
440 iovec_dat_s_t
*iovp
= NULL
;
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
) ))
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
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
505 bzero(&descr
->buf1
[size
], 60-size
);
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
;
517 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of buffer */
521 r
= sys_safecopyto(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
, 0,
522 (vir_bytes
)buffer
, bytes
, D
);
524 panic(str_CopyErrMsg
, r
);
527 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
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
);
552 assert(dep
->de_flags
& DEF_READING
);
556 assert(!(dep
->de_flags
& DEF_READING
));
557 dep
->rx_return_msg
= *mp
;
558 dep
->de_flags
|= DEF_READING
;
563 PRIVATE
void de_conf_addr(dpeth_t
* dep
)
565 static char ea_fmt
[] = "x:x:x:x:x:x";
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
)
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);
585 PRIVATE
void de_first_init(dpeth_t
*dep
)
588 vir_bytes descr_vir
= dep
->sendrecv_descr_buf
;
589 vir_bytes buffer_vir
= dep
->sendrecv_buf
;
590 de_loc_descr_t
*loc_descr
;
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
);
610 /* Now that we have buffer space and descriptors, we need to
611 obtain their physical address to pass to the hardware
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
;
627 loc_descr
->descr
->des
[DES0
] |= DES0_OWN
;
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 */
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
),
652 panic(str_UmapErrMsg
, r
);
654 if( ((loc_descr
->descr
->des
[DES_BUF1
] & 0x3) != 0) ||
655 ((loc_descr
->descr
->des
[DES_BUF2
] & 0x3) != 0) ||
657 panic(str_AlignErrMsg
, temp
);
663 /* Init default values */
664 dep
->cur_descr
[DESCR_TRAN
]=1;
665 dep
->cur_descr
[DESCR_RECV
]=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
){
679 val
= io_inl(CSR_ADDR(dep
, CSR5
));
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);
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
){
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
){
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
){
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;
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);
767 PRIVATE
int de_calc_iov_size(iovec_dat_s_t
* iovp
){
772 size
+= iovp
->iod_iovec
[ix
].iov_size
;
773 if (++ix
>= IOVEC_NR
) {
777 } while (ix
< iovp
->iod_iovec_s
);
781 PRIVATE
void de_get_userdata_s(int user_proc
, cp_grant_id_t grant
,
782 vir_bytes offset
, int count
, void *loc_addr
){
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
);
789 panic(str_CopyErrMsg
, rc
);
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
);
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
;
806 iovec_dat_s_t
*iovp
= NULL
;
807 de_loc_descr_t
*descr
= NULL
;
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)
824 if(!setupDone
&& (dep
->cur_descr
[DESCR_TRAN
] == 0) ){
825 dep
->descr
[DESCR_TRAN
][0].descr
->des
[DES0
] = 0;
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
++;
846 bytes
= iovp
->iod_iovec
[ix
].iov_size
;
850 r
= sys_safecopyfrom(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
,
851 0, (vir_bytes
)buffer
, bytes
, D
);
853 panic(str_CopyErrMsg
, r
);
856 if (++ix
>= IOVEC_NR
) {
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
;
875 dep
->de_flags
&= NOT(DEF_SENDING
);
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
;
892 PRIVATE
void warning(const char *type
, int err
){
893 printf("Warning: %s sys_%s failed (%d)\n", str_DevName
, type
, err
);
897 PRIVATE u32_t
io_inl(u16_t port
){
900 if ((rc
= sys_inl(port
, &value
)) != OK
) warning("inl", rc
);
904 PRIVATE
void io_outl(u16_t port
, u32_t value
){
906 if ((rc
= sys_outl(port
, value
)) != OK
) warning("outl", rc
);