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 static u32_t
io_inl(u16_t
);
30 static void io_outl(u16_t
, u32_t
);
31 static void do_conf(const message
*);
32 static void do_get_stat_s(message
*);
33 static void do_interrupt(const dpeth_t
*);
34 static void do_reply(dpeth_t
*);
35 static void do_vread_s(const message
*, int);
36 static void do_watchdog(void *);
38 static void de_update_conf(dpeth_t
*);
39 static int de_probe(dpeth_t
*, int skip
);
40 static void de_conf_addr(dpeth_t
*);
41 static void de_first_init(dpeth_t
*);
42 static void de_reset(const dpeth_t
*);
43 static void de_hw_conf(const dpeth_t
*);
44 static void de_start(const dpeth_t
*);
45 static void de_setup_frame(const dpeth_t
*);
46 static u16_t
de_read_rom(const dpeth_t
*, u8_t
, u8_t
);
47 static int de_calc_iov_size(iovec_dat_s_t
*);
48 static void de_next_iov(iovec_dat_s_t
*);
49 static void do_vwrite_s(const message
*, int);
50 static void de_get_userdata_s(int, cp_grant_id_t
, 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 static dpeth_t de_state
;
64 static int de_instance
;
66 /* SEF functions and variables. */
67 static void sef_local_startup(void);
68 static int sef_cb_init_fresh(int type
, sef_init_info_t
*info
);
70 /*===========================================================================*
72 *===========================================================================*/
73 int main(int argc
, char *argv
[])
80 /* SEF local startup. */
81 env_setargs(argc
, argv
);
86 if ((r
= netdriver_receive(ANY
, &m
, &ipc_status
)) != OK
)
87 panic("netdriver_receive failed: %d", r
);
89 if(is_ipc_notify(ipc_status
)) {
90 switch(_ENDPOINT_P(m
.m_source
)) {
97 if (dep
->de_mode
== DEM_ENABLED
) {
99 if (dep
->de_flags
& (DEF_ACK_SEND
| DEF_ACK_RECV
))
101 sys_irqenable(&dep
->de_hook
);
105 printf("ignoring notify from %d\n", m
.m_source
);
113 case DL_WRITEV_S
: do_vwrite_s(&m
, FALSE
); break;
114 case DL_READV_S
: do_vread_s(&m
, FALSE
); break;
115 case DL_CONF
: do_conf(&m
); break;
116 case DL_GETSTAT_S
: do_get_stat_s(&m
); break;
119 printf("message 0x%lx; %d from %d\n",
120 m
.m_type
, m
.m_type
-DL_RQ_BASE
, m
.m_source
);
121 panic("illegal message: %d", m
.m_type
);
126 /*===========================================================================*
127 * sef_local_startup *
128 *===========================================================================*/
129 static void sef_local_startup()
131 /* Register init callbacks. */
132 sef_setcb_init_fresh(sef_cb_init_fresh
);
133 sef_setcb_init_lu(sef_cb_init_fresh
);
134 sef_setcb_init_restart(sef_cb_init_fresh
);
136 /* Register live update callbacks. */
137 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready
);
138 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree
);
140 /* Register signal callbacks. */
141 sef_setcb_signal_handler(sef_cb_signal_handler_term
);
143 /* Let SEF perform startup. */
147 /*===========================================================================*
148 * sef_cb_init_fresh *
149 *===========================================================================*/
150 static int sef_cb_init_fresh(int type
, sef_init_info_t
*UNUSED(info
))
152 /* Initialize the DEC 21140A driver. */
157 (void) env_parse("instance", "d", 0, &v
, 0, 255);
158 de_instance
= (int) v
;
160 /* Request function key for debug dumps */
162 bit_set(sfkeys
, DE_FKEY
);
163 if ((fkey_map(&fkeys
, &sfkeys
)) != OK
)
164 printf("%s: error using Shift+F%d key(%d)\n", str_DevName
, DE_FKEY
, errno
);
166 /* Announce we are up! */
167 netdriver_announce();
172 static void do_get_stat_s(message
* mp
)
179 if ((rc
= sys_safecopyto(mp
->m_source
, mp
->DL_GRANT
, 0UL,
180 (vir_bytes
)&dep
->de_stat
,
181 sizeof(dep
->de_stat
))) != OK
)
182 panic(str_CopyErrMsg
, rc
);
184 mp
->m_type
= DL_STAT_REPLY
;
185 rc
= send(mp
->m_source
, mp
);
187 panic(str_StatErrMsg
, rc
);
191 static void do_conf(const message
* mp
)
199 strncpy(dep
->de_name
, str_DevName
, strlen(str_DevName
));
200 dep
->de_name
[strlen(dep
->de_name
)-1] = '0' + de_instance
;
202 if (dep
->de_mode
== DEM_DISABLED
) {
205 if (dep
->de_mode
== DEM_ENABLED
&& !de_probe(dep
, de_instance
)) {
206 printf("%s: warning no ethernet card found at 0x%04X\n",
207 dep
->de_name
, dep
->de_base_port
);
208 dep
->de_mode
= DEM_DISABLED
;
214 /* 'de_mode' may change if probe routines fail, test again */
215 switch (dep
->de_mode
) {
218 r
= ENXIO
; /* Device is OFF or hardware probe failed */
222 if (dep
->de_flags
== DEF_EMPTY
) {
224 dep
->de_flags
|= DEF_ENABLED
;
231 /* TODO CHECK PROMISC AND MULTI */
232 dep
->de_flags
&= NOT(DEF_PROMISC
| DEF_MULTI
| DEF_BROAD
);
233 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
234 dep
->de_flags
|= DEF_PROMISC
| DEF_MULTI
| DEF_BROAD
;
235 if (mp
->DL_MODE
& DL_MULTI_REQ
) dep
->de_flags
|= DEF_MULTI
;
236 if (mp
->DL_MODE
& DL_BROAD_REQ
) dep
->de_flags
|= DEF_BROAD
;
240 DEBUG(printf("%s running in sink mode\n", str_DevName
));
241 memset(dep
->de_address
.ea_addr
, 0, sizeof(ether_addr_t
));
248 reply_mess
.m_type
= DL_CONF_REPLY
;
249 reply_mess
.DL_STAT
= r
;
251 *(ether_addr_t
*) reply_mess
.DL_HWADDR
= dep
->de_address
;
254 if (send(mp
->m_source
, &reply_mess
) != OK
)
255 panic(str_SendErrMsg
, mp
->m_source
);
260 static void do_reply(dpeth_t
* dep
)
263 int r
, flags
= DL_NOFLAGS
;
265 if (dep
->de_flags
& DEF_ACK_SEND
) flags
|= DL_PACK_SEND
;
266 if (dep
->de_flags
& DEF_ACK_RECV
) flags
|= DL_PACK_RECV
;
268 reply
.m_type
= DL_TASK_REPLY
;
269 reply
.DL_FLAGS
= flags
;
270 reply
.DL_COUNT
= dep
->de_read_s
;
272 r
= send(dep
->de_client
, &reply
);
275 panic(str_SendErrMsg
, r
);
278 dep
->de_flags
&= NOT(DEF_ACK_SEND
| DEF_ACK_RECV
);
282 static void do_watchdog(void *UNUSED(message
))
284 /* nothing here yet */
288 static 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 r
= pci_next_dev(&devind
, &vid
, &did
);
308 dep
->de_base_port
= pci_attr_r32(devind
, PCI_BAR
) & 0xffffffe0;
309 dep
->de_irq
= pci_attr_r8(devind
, PCI_ILR
);
311 if (dep
->de_base_port
< DE_MIN_BASE_ADDR
)
312 panic("de_probe: base address invalid: %d", dep
->de_base_port
);
314 DEBUG(printf("%s: using I/O address 0x%lx, IRQ %d\n",
315 dep
->de_name
, (unsigned long)dep
->de_base_port
,
318 dep
->de_type
= pci_attr_r8(devind
, PCI_REV
);
320 /* device validation. We support only the DEC21140A */
321 if(dep
->de_type
!= DEC_21140A
){
322 dep
->de_type
= DE_TYPE_UNKNOWN
;
323 printf("%s: unsupported device\n", str_DevName
);
329 DEBUG(printf("Reading SROM...\n"));
331 for(i
=0;i
<(1<<SROM_BITWIDTH
)-1;i
++){
332 temp16
= de_read_rom(dep
, i
, SROM_BITWIDTH
);
333 dep
->srom
[i
*2] = temp16
& 0xFF;
334 dep
->srom
[i
*2+1] = temp16
>> 8;
337 /* TODO: validate SROM content */
338 /* acquire MAC addr */
339 DEBUG(printf("Using MAC addr= "));
341 dep
->de_address
.ea_addr
[i
] = dep
->srom
[i
+DE_SROM_EA_OFFSET
];
342 DEBUG(printf("%02X%c",dep
->de_address
.ea_addr
[i
],i
!=5?'-':'\n'));
344 DEBUG(printf("probe success\n"));
348 static u16_t
de_read_rom(const dpeth_t
*dep
, u8_t addr
, u8_t nbAddrBits
){
352 u32_t csr2
= 0; /* csr2 is used to hold constant values that are
353 setup in the init phase, it makes this a little
354 more readable, the following macro is also just
355 to clear up the code a little.*/
357 #define EMIT do { io_outl(CSR_ADDR(dep, CSR9), csr | csr2); io_outl(CSR_ADDR(dep, CSR1), 0);} while(0)
362 csr
= CSR9_SR
| CSR9_RD
; EMIT
;
364 csr2
= CSR9_SR
| CSR9_RD
;
369 csr
= CSR9_SRC
; EMIT
;
374 csr
= CSR9_DI
| CSR9_SRC
; EMIT
;
376 csr
= CSR9_DI
| CSR9_SRC
; EMIT
;
379 csr
= CSR9_SRC
; EMIT
;
383 for(i
=nbAddrBits
;i
!=0;i
--){
384 csr
= (addr
&(1<<(i
-1))) != 0 ? CSR9_DI
: 0; EMIT
;
385 csr
^= CSR9_SRC
; EMIT
;
386 csr
^= CSR9_SRC
; EMIT
;
393 csr
= CSR9_SRC
; EMIT
;
394 retVal
|= (io_inl(CSR_ADDR(dep
, CSR9
)) & CSR9_DO
) == 0 ? 0 : 1;
405 static void de_update_conf(dpeth_t
* dep
)
407 static char dpc_fmt
[] = "x:d:x";
411 strlcpy(ec_key
, "DEETH0", sizeof(ec_key
));
412 ec_key
[5] += de_instance
;
414 dep
->de_mode
= DEM_ENABLED
;
415 switch (env_parse(ec_key
, dpc_fmt
, 0, &val
, 0x000L
, 0x3FFL
)) {
416 case EP_OFF
: dep
->de_mode
= DEM_DISABLED
; break;
417 case EP_ON
: dep
->de_mode
= DEM_SINK
; break;
419 dep
->de_base_port
= 0;
424 static void do_vread_s(const message
* mp
, int from_int
)
431 de_loc_descr_t
*descr
= NULL
;
432 iovec_dat_s_t
*iovp
= NULL
;
436 dep
->de_client
= mp
->m_source
;
438 if (dep
->de_mode
== DEM_ENABLED
) {
440 descr
= &dep
->descr
[DESCR_RECV
][dep
->cur_descr
[DESCR_RECV
]];
442 /* check if packet is in the current descr and only there */
443 if( !( !(descr
->descr
->des
[DES0
] & DES0_OWN
) &&
444 (descr
->descr
->des
[DES0
] & DES0_FS
) &&
445 (descr
->descr
->des
[DES0
] & DES0_LS
) ))
449 /*TODO: multi-descr msgs...*/
450 /* We only support packets contained in a single descriptor.
451 Setting the descriptor buffer size to less then
452 ETH_MAX_PACK_SIZE will result in multi-descriptor
453 packets that we won't be able to handle
455 assert(!(descr
->descr
->des
[DES0
]&DES0_OWN
));
456 assert(descr
->descr
->des
[DES0
]&DES0_FS
);
457 assert(descr
->descr
->des
[DES0
]&DES0_LS
);
459 /* Check for abnormal messages. We assert here
460 because this driver is for a virtualized
461 envrionment where we will not get bad packets
463 assert(!(descr
->descr
->des
[DES0
]&DES0_ES
));
464 assert(!(descr
->descr
->des
[DES0
]&DES0_RE
));
467 /* Setup the iovec entry to allow copying into
470 dep
->de_read_iovec
.iod_proc_nr
= mp
->m_source
;
471 de_get_userdata_s(mp
->m_source
, (cp_grant_id_t
) mp
->DL_GRANT
, 0,
472 mp
->DL_COUNT
, dep
->de_read_iovec
.iod_iovec
);
473 dep
->de_read_iovec
.iod_iovec_s
= mp
->DL_COUNT
;
474 dep
->de_read_iovec
.iod_grant
= (cp_grant_id_t
) mp
->DL_GRANT
;
475 dep
->de_read_iovec
.iod_iovec_offset
= 0;
476 size
= de_calc_iov_size(&dep
->de_read_iovec
);
477 if (size
< ETH_MAX_PACK_SIZE
)
478 panic(str_SizeErrMsg
, size
);
480 /* Copy buffer to user area and clear ownage */
481 size
= (descr
->descr
->des
[DES0
]&DES0_FL
)>>DES0_FL_SHIFT
;
483 /*TODO: Complain to MS */
484 /*HACK: VPC2007 returns packet of invalid size. Ethernet standard
485 specify 46 bytes as the minimum for valid payload. However, this is
486 artificial in so far as for certain packet types, notably ARP, less
487 then 46 bytes are needed to contain the full information. In a non
488 virtualized environment the 46 bytes rule is enforced in order to give
489 guarantee in the collison detection scheme. Of course, this being a
490 driver for a VPC2007, we won't have collisions and I can only suppose
491 MS decided to cut packet size to true minimum, regardless of the
492 46 bytes payload standard. Note that this seems to not happen in
493 bridged mode. Note also, that the card does not return runt or
494 incomplete frames to us, so this hack is safe
497 bzero(&descr
->buf1
[size
], 60-size
);
502 iovp
= &dep
->de_read_iovec
;
503 buffer
= descr
->buf1
;
504 dep
->bytes_rx
+= size
;
505 dep
->de_stat
.ets_packetR
++;
506 dep
->de_read_s
= size
;
509 bytes
= iovp
->iod_iovec
[ix
].iov_size
; /* Size of buffer */
513 r
= sys_safecopyto(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
, 0,
514 (vir_bytes
)buffer
, bytes
);
516 panic(str_CopyErrMsg
, r
);
519 if (++ix
>= IOVEC_NR
) { /* Next buffer of IO vector */
523 } while ((size
-= bytes
) > 0);
525 descr
->descr
->des
[DES0
]=DES0_OWN
;
526 dep
->cur_descr
[DESCR_RECV
]++;
527 if(dep
->cur_descr
[DESCR_RECV
] >= DE_NB_RECV_DESCR
)
528 dep
->cur_descr
[DESCR_RECV
] = 0;
530 DEBUG(printf("Read returned size = %d\n", size
));
532 /* Reply information */
533 dep
->de_flags
|= DEF_ACK_RECV
;
534 dep
->de_flags
&= NOT(DEF_READING
);
544 assert(dep
->de_flags
& DEF_READING
);
548 assert(!(dep
->de_flags
& DEF_READING
));
549 dep
->rx_return_msg
= *mp
;
550 dep
->de_flags
|= DEF_READING
;
555 static void de_conf_addr(dpeth_t
* dep
)
557 static char ea_fmt
[] = "x:x:x:x:x:x";
562 strlcpy(ea_key
, "DEETH0_EA", sizeof(ea_key
));
563 ea_key
[5] += de_instance
;
565 for (ix
= 0; ix
< SA_ADDR_LEN
; ix
++) {
566 val
= dep
->de_address
.ea_addr
[ix
];
567 if (env_parse(ea_key
, ea_fmt
, ix
, &val
, 0x00L
, 0xFFL
) != EP_SET
)
569 dep
->de_address
.ea_addr
[ix
] = val
;
572 if (ix
!= 0 && ix
!= SA_ADDR_LEN
)
573 env_parse(ea_key
, "?", 0, &val
, 0L, 0L);
577 static void de_first_init(dpeth_t
*dep
)
580 vir_bytes descr_vir
= (vir_bytes
)dep
->sendrecv_descr_buf
;
581 vir_bytes buffer_vir
= (vir_bytes
)dep
->sendrecv_buf
;
582 de_loc_descr_t
*loc_descr
;
587 loc_descr
= &dep
->descr
[i
][0];
588 for(j
=0; j
< (i
==DESCR_RECV
? DE_NB_RECV_DESCR
: DE_NB_SEND_DESCR
); j
++){
590 /* assign buffer space for descriptor */
591 loc_descr
->descr
= (void*)descr_vir
;
592 descr_vir
+= sizeof(de_descr_t
);
594 /* assign space for buffer */
595 loc_descr
->buf1
= (u8_t
*)buffer_vir
;
596 buffer_vir
+= (i
==DESCR_RECV
? DE_RECV_BUF_SIZE
: DE_SEND_BUF_SIZE
);
602 /* Now that we have buffer space and descriptors, we need to
603 obtain their physical address to pass to the hardware
606 loc_descr
= &dep
->descr
[i
][0];
607 temp
= (i
==DESCR_RECV
? DE_RECV_BUF_SIZE
: DE_SEND_BUF_SIZE
);
608 for(j
=0; j
< (i
==DESCR_RECV
? DE_NB_RECV_DESCR
: DE_NB_SEND_DESCR
); j
++){
609 /* translate buffers physical address */
610 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)loc_descr
->buf1
, temp
,
611 &(loc_descr
->descr
->des
[DES_BUF1
]));
612 if(r
!= OK
) panic("umap failed: %d", r
);
613 loc_descr
->descr
->des
[DES_BUF2
] = 0;
614 memset(&loc_descr
->descr
->des
[DES0
],0,sizeof(u32_t
));
615 loc_descr
->descr
->des
[DES1
] = temp
;
616 if(j
==( (i
==DESCR_RECV
?DE_NB_RECV_DESCR
:DE_NB_SEND_DESCR
)-1))
617 loc_descr
->descr
->des
[DES1
] |= DES1_ER
;
619 loc_descr
->descr
->des
[DES0
] |= DES0_OWN
;
624 /* record physical location of two first descriptor */
625 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)dep
->descr
[DESCR_RECV
][0].descr
,
626 sizeof(de_descr_t
), &dep
->sendrecv_descr_phys_addr
[DESCR_RECV
]);
627 if(r
!= OK
) panic(str_UmapErrMsg
, r
);
629 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)dep
->descr
[DESCR_TRAN
][0].descr
,
630 sizeof(de_descr_t
), &dep
->sendrecv_descr_phys_addr
[DESCR_TRAN
]);
631 if(r
!= OK
) panic(str_UmapErrMsg
, r
);
633 DEBUG(printf("Descr: head tran=[%08X] head recv=[%08X]\n",
634 dep
->sendrecv_descr_phys_addr
[DESCR_TRAN
],
635 dep
->sendrecv_descr_phys_addr
[DESCR_RECV
]));
637 /* check alignment just to be extra safe */
639 loc_descr
= &dep
->descr
[i
][0];
640 for(j
=0;j
< (i
==DESCR_RECV
?DE_NB_RECV_DESCR
:DE_NB_SEND_DESCR
);j
++){
641 r
= sys_umap(SELF
, VM_D
, (vir_bytes
)&(loc_descr
->descr
),
642 sizeof(de_descr_t
), &temp
);
644 panic(str_UmapErrMsg
, r
);
646 if( ((loc_descr
->descr
->des
[DES_BUF1
] & 0x3) != 0) ||
647 ((loc_descr
->descr
->des
[DES_BUF2
] & 0x3) != 0) ||
649 panic(str_AlignErrMsg
, temp
);
655 /* Init default values */
656 dep
->cur_descr
[DESCR_TRAN
]=1;
657 dep
->cur_descr
[DESCR_RECV
]=0;
661 /* Set the interrupt handler policy. Request interrupts not to be reenabled
662 * automatically. Return the IRQ line number when an interrupt occurs.
664 dep
->de_hook
= dep
->de_irq
;
665 sys_irqsetpolicy(dep
->de_irq
, 0, &dep
->de_hook
);
666 sys_irqenable(&dep
->de_hook
);
669 static void do_interrupt(const dpeth_t
*dep
){
671 val
= io_inl(CSR_ADDR(dep
, CSR5
));
674 panic("Abnormal Int CSR5=: %d", val
);
677 if( (dep
->de_flags
& DEF_READING
) && (val
& CSR5_RI
) ){
678 do_vread_s(&dep
->rx_return_msg
, TRUE
);
681 if( (dep
->de_flags
& DEF_SENDING
) && (val
& CSR5_TI
) ){
682 do_vwrite_s(&dep
->tx_return_msg
, TRUE
);
685 /* ack and reset interrupts */
686 io_outl(CSR_ADDR(dep
, CSR5
), 0xFFFFFFFF);
690 static void de_reset(const dpeth_t
*dep
){
691 io_outl(CSR_ADDR(dep
, CSR0
), CSR0_SWR
);
694 static void de_hw_conf(const dpeth_t
*dep
){
697 /* CSR0 - global host bus prop */
698 val
= CSR0_BAR
| CSR0_CAL_8
;
699 io_outl(CSR_ADDR(dep
, CSR0
), val
);
701 /* CSR3 - Receive list BAR */
702 val
= dep
->sendrecv_descr_phys_addr
[DESCR_RECV
];
703 io_outl(CSR_ADDR(dep
, CSR3
), val
);
705 /* CSR4 - Transmit list BAR */
706 val
= dep
->sendrecv_descr_phys_addr
[DESCR_TRAN
];
707 io_outl(CSR_ADDR(dep
, CSR4
), val
);
709 /* CSR7 - interrupt mask */
710 val
= CSR7_TI
| CSR7_RI
| CSR7_AI
;
711 io_outl(CSR_ADDR(dep
, CSR7
), val
);
713 /* CSR6 - operating mode register */
714 val
= CSR6_MBO
| CSR6_PS
| CSR6_FD
| CSR6_HBD
|
715 CSR6_PCS
| CSR6_SCR
| CSR6_TR_00
;
716 io_outl(CSR_ADDR(dep
, CSR6
), val
);
719 static void de_start(const dpeth_t
*dep
){
721 val
= io_inl(CSR_ADDR(dep
, CSR6
)) | CSR6_ST
| CSR6_SR
;
722 io_outl(CSR_ADDR(dep
, CSR6
), val
);
725 static void de_setup_frame(const dpeth_t
*dep
){
729 /* this is not perfect... we assume pass all multicast and only
730 filter non-multicast frames */
731 dep
->descr
[DESCR_TRAN
][0].buf1
[0] = 0xFF;
732 dep
->descr
[DESCR_TRAN
][0].buf1
[1] = 0xFF;
733 dep
->descr
[DESCR_TRAN
][0].buf1
[4] = 0xFF;
734 dep
->descr
[DESCR_TRAN
][0].buf1
[5] = 0xFF;
735 dep
->descr
[DESCR_TRAN
][0].buf1
[8] = 0xFF;
736 dep
->descr
[DESCR_TRAN
][0].buf1
[9] = 0xFF;
738 memset(&(dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
]), 0, 12);
739 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+0] = dep
->de_address
.ea_addr
[0];
740 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+1] = dep
->de_address
.ea_addr
[1];
741 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+4] = dep
->de_address
.ea_addr
[2];
742 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+5] = dep
->de_address
.ea_addr
[3];
743 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+8] = dep
->de_address
.ea_addr
[4];
744 dep
->descr
[DESCR_TRAN
][0].buf1
[12*i
+9] = dep
->de_address
.ea_addr
[5];
747 dep
->descr
[DESCR_TRAN
][0].descr
->des
[DES0
] = DES0_OWN
;
748 dep
->descr
[DESCR_TRAN
][0].descr
->des
[DES1
] = DES1_SET
|
749 DE_SETUP_FRAME_SIZE
| DES1_IC
;
751 /* start transmit process to process setup frame */
752 val
= io_inl(CSR_ADDR(dep
, CSR6
)) | CSR6_ST
;
753 io_outl(CSR_ADDR(dep
, CSR6
), val
);
754 io_outl(CSR_ADDR(dep
, CSR1
), 0xFFFFFFFF);
759 static int de_calc_iov_size(iovec_dat_s_t
* iovp
){
764 size
+= iovp
->iod_iovec
[ix
].iov_size
;
765 if (++ix
>= IOVEC_NR
) {
769 } while (ix
< iovp
->iod_iovec_s
);
773 static void de_get_userdata_s(int user_proc
, cp_grant_id_t grant
,
774 vir_bytes offset
, int count
, void *loc_addr
){
778 len
= (count
> IOVEC_NR
? IOVEC_NR
: count
) * sizeof(iovec_t
);
779 rc
= sys_safecopyfrom(user_proc
, grant
, 0, (vir_bytes
)loc_addr
, len
);
781 panic(str_CopyErrMsg
, rc
);
785 static void de_next_iov(iovec_dat_s_t
* iovp
){
787 iovp
->iod_iovec_s
-= IOVEC_NR
;
788 iovp
->iod_iovec_offset
+= IOVEC_NR
* sizeof(iovec_t
);
789 de_get_userdata_s(iovp
->iod_proc_nr
, iovp
->iod_grant
, iovp
->iod_iovec_offset
,
790 iovp
->iod_iovec_s
, iovp
->iod_iovec
);
794 static void do_vwrite_s(const message
* mp
, int from_int
){
795 static u8_t setupDone
= 0;
796 int size
, r
, bytes
, ix
, totalsize
;
798 iovec_dat_s_t
*iovp
= NULL
;
799 de_loc_descr_t
*descr
= NULL
;
804 dep
->de_client
= mp
->m_source
;
806 if (dep
->de_mode
== DEM_ENABLED
) {
808 if (!from_int
&& (dep
->de_flags
& DEF_SENDING
))
809 panic(str_BusyErrMsg
);
811 descr
= &dep
->descr
[DESCR_TRAN
][dep
->cur_descr
[DESCR_TRAN
]];
813 if(( descr
->descr
->des
[DES0
] & DES0_OWN
)!=0)
816 if(!setupDone
&& (dep
->cur_descr
[DESCR_TRAN
] == 0) ){
817 dep
->descr
[DESCR_TRAN
][0].descr
->des
[DES0
] = 0;
821 buffer
= descr
->buf1
;
822 iovp
= &dep
->de_write_iovec
;
823 iovp
->iod_proc_nr
= mp
->m_source
;
824 de_get_userdata_s(mp
->m_source
, mp
->DL_GRANT
, 0,
825 mp
->DL_COUNT
, iovp
->iod_iovec
);
826 iovp
->iod_iovec_s
= mp
->DL_COUNT
;
827 iovp
->iod_grant
= (cp_grant_id_t
) mp
->DL_GRANT
;
828 iovp
->iod_iovec_offset
= 0;
829 totalsize
= size
= de_calc_iov_size(iovp
);
830 if (size
< ETH_MIN_PACK_SIZE
|| size
> ETH_MAX_PACK_SIZE
)
831 panic(str_SizeErrMsg
, size
);
833 dep
->bytes_tx
+= size
;
834 dep
->de_stat
.ets_packetT
++;
838 bytes
= iovp
->iod_iovec
[ix
].iov_size
;
842 r
= sys_safecopyfrom(iovp
->iod_proc_nr
, iovp
->iod_iovec
[ix
].iov_grant
,
843 0, (vir_bytes
)buffer
, bytes
);
845 panic(str_CopyErrMsg
, r
);
848 if (++ix
>= IOVEC_NR
) {
852 } while ((size
-= bytes
) > 0);
854 descr
->descr
->des
[DES1
] = (descr
->descr
->des
[DES1
]&DES1_ER
) |
855 DES1_FS
| DES1_LS
| DES1_IC
| totalsize
;
856 descr
->descr
->des
[DES0
] = DES0_OWN
;
858 dep
->cur_descr
[DESCR_TRAN
]++;
859 if(dep
->cur_descr
[DESCR_TRAN
] >= DE_NB_SEND_DESCR
)
860 dep
->cur_descr
[DESCR_TRAN
] = 0;
862 io_outl(CSR_ADDR(dep
, CSR1
), 0xFFFFFFFF);
865 dep
->de_flags
|= DEF_ACK_SEND
;
867 dep
->de_flags
&= NOT(DEF_SENDING
);
875 panic("should not happen: %d", 0);
877 dep
->de_stat
.ets_transDef
++;
878 dep
->de_flags
|= DEF_SENDING
;
879 dep
->de_stat
.ets_transDef
++;
880 dep
->tx_return_msg
= *mp
;
884 static void warning(const char *type
, int err
){
885 printf("Warning: %s sys_%s failed (%d)\n", str_DevName
, type
, err
);
889 static u32_t
io_inl(u16_t port
){
892 if ((rc
= sys_inl(port
, &value
)) != OK
) warning("inl", rc
);
896 static void io_outl(u16_t port
, u32_t value
){
898 if ((rc
= sys_outl(port
, value
)) != OK
) warning("outl", rc
);