4 * This file contains a ethernet device driver for AMD LANCE based ethernet
7 * The valid messages and their parameters are:
9 * m_type DL_COUNT DL_MODE DL_GRANT
10 * |--------------+----------+---------+---------|
11 * | DL_WRITEV_S | count | | grant |
12 * |--------------|----------|---------|---------|
13 * | DL_READV_S | count | | grant |
14 * |--------------|----------|---------|---------|
15 * | DL_CONF | | mode | |
16 * |--------------|----------|---------|---------|
17 * | DL_GETSTAT_S | | | grant |
18 * |--------------|----------|---------|---------|
19 * | hardware int | | | |
20 * |--------------|----------|---------|---------|
22 * The messages sent are:
24 * m_type DL_COUNT DL_FLAGS
25 * |---------------+----------+---------|
26 * | DL_TASK_REPLY | rd-count | flags |
27 * |---------------|----------|---------|
34 * m_type DL_STAT DL_ADDR
35 * |---------------+---------+---------------|
36 * | DL_CONF_REPLY | code | ethernet addr |
37 * |---------------|---------|---------------|
39 * Created: Jul 27, 2002 by Kazuya Kodama <kazuya@nii.ac.jp>
40 * Adapted for Minix 3: Sep 05, 2005 by Joren l'Ami <jwlami@cs.vu.nl>
43 #define VERBOSE 0 /* Verbose debugging output */
44 #define LANCE_FKEY 0 /* Use function key to dump Lance stats */
46 #include <minix/drivers.h>
47 #include <minix/netdriver.h>
50 #include <net/gen/ether.h>
51 #include <net/gen/eth_io.h>
54 #include <minix/syslib.h>
55 #include <minix/endpoint.h>
56 #include <machine/pci.h>
61 static ether_card_t ec_state
;
62 static int ec_instance
;
65 typedef struct ec_conf
72 /* We hardly use these. Just "LANCE0=on/off" "LANCE1=on/off" mean. */
74 ec_conf_t ec_conf
[EC_CONF_NR
]= /* Card addresses */
76 /* I/O port, IRQ, Buffer address. */
77 { 0x1000, 9, 0x00000, },
78 { 0xD000, 15, 0x00000, },
79 { 0x0000, 0, 0x00000, },
83 static void do_init(message
*mp
);
84 static void ec_init(ether_card_t
*ec
);
85 static void ec_confaddr(ether_card_t
*ec
);
86 static void ec_reinit(ether_card_t
*ec
);
87 static void ec_check_ints(ether_card_t
*ec
);
88 static void conf_hw(ether_card_t
*ec
);
89 static void update_conf(ether_card_t
*ec
, ec_conf_t
*ecp
);
90 static void mess_reply(message
*req
, message
*reply
);
91 static void do_int(ether_card_t
*ec
);
92 static void reply(ether_card_t
*ec
);
93 static void ec_reset(ether_card_t
*ec
);
94 static void ec_send(ether_card_t
*ec
);
95 static void ec_recv(ether_card_t
*ec
);
96 static void do_vwrite_s(message
*mp
, int from_int
);
97 static void do_vread_s(const message
*mp
);
98 static void ec_user2nic(ether_card_t
*dep
, iovec_dat_t
*iovp
, vir_bytes
99 offset
, int nic_addr
, vir_bytes count
);
100 static void ec_nic2user(ether_card_t
*ec
, int nic_addr
, iovec_dat_t
101 *iovp
, vir_bytes offset
, vir_bytes count
);
102 static int calc_iovec_size(iovec_dat_t
*iovp
);
103 static void ec_next_iovec(iovec_dat_t
*iovp
);
104 static void do_getstat_s(message
*mp
);
105 static void lance_stop(ether_card_t
*ec
);
107 static void lance_dump(void);
108 static void getAddressing(int devind
, ether_card_t
*ec
);
110 /* probe+init LANCE cards */
111 static int lance_probe(ether_card_t
*ec
, int skip
);
112 static void lance_init_card(ether_card_t
*ec
);
114 /* Accesses Lance Control and Status Registers */
115 static u8_t
in_byte(port_t port
);
116 static u16_t
in_word(port_t port
);
117 static void out_word(port_t port
, u16_t value
);
118 static u16_t
read_csr(port_t ioaddr
, u16_t csrno
);
119 static void write_csr(port_t ioaddr
, u16_t csrno
, u16_t value
);
123 typedef unsigned long Address
;
125 #define virt_to_bus(x) (vir2phys((unsigned long)x))
126 unsigned long vir2phys( unsigned long x
)
131 if ( (r
=sys_umap( SELF
, VM_D
, x
, 4, &value
)) != OK
) {
132 printf("lance: umap of 0x%lx failed\n",x
);
133 panic("sys_umap failed: %d", r
);
139 /* DMA limitations */
140 #define DMA_ADDR_MASK 0xFFFFFF /* mask to verify DMA address is 24-bit */
142 #define CORRECT_DMA_MEM() ( (virt_to_bus(lance_buf + sizeof(struct lance_interface)) & ~DMA_ADDR_MASK) == 0 )
144 #define ETH_FRAME_LEN 1518
146 #define LANCE_MUST_PAD 0x00000001
147 #define LANCE_ENABLE_AUTOSELECT 0x00000002
148 #define LANCE_SELECT_PHONELINE 0x00000004
149 #define LANCE_MUST_UNRESET 0x00000008
151 static const struct lance_chip_type
157 {0x0000, "LANCE 7990", /* Ancient lance chip. */
158 LANCE_MUST_PAD
+ LANCE_MUST_UNRESET
},
159 {0x0003, "PCnet/ISA 79C960", /* 79C960 PCnet/ISA. */
160 LANCE_ENABLE_AUTOSELECT
},
161 {0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */
162 LANCE_ENABLE_AUTOSELECT
},
163 {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */
164 LANCE_ENABLE_AUTOSELECT
},
165 {0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */
166 LANCE_ENABLE_AUTOSELECT
},
167 {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */
168 LANCE_ENABLE_AUTOSELECT
},
169 {0x2625, "PCnet-FAST III 79C973",/* 79C973 PCInet-FAST III. */
170 LANCE_ENABLE_AUTOSELECT
},
171 {0x2626, "PCnet/HomePNA 79C978",
172 LANCE_ENABLE_AUTOSELECT
|LANCE_SELECT_PHONELINE
},
173 {0x0, "PCnet (unknown)",
174 LANCE_ENABLE_AUTOSELECT
},
177 /* ############## for LANCE device ############## */
178 #define LANCE_ETH_ADDR 0x0
179 #define LANCE_DATA 0x10
180 #define LANCE_ADDR 0x12
181 #define LANCE_RESET 0x14
182 #define LANCE_BUS_IF 0x16
183 #define LANCE_TOTAL_SIZE 0x18
185 /* Use 2^4=16 {Rx,Tx} buffers */
186 #define LANCE_LOG_RX_BUFFERS 4
187 #define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
188 #define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
189 #define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
191 #define LANCE_LOG_TX_BUFFERS 4
192 #define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
193 #define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
194 #define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
196 /* for lance_interface */
197 struct lance_init_block
200 unsigned char phys_addr
[6];
201 unsigned long filter
[2];
210 unsigned char addr
[4];
212 short buf_length
; /* 2s complement */
220 unsigned char addr
[4];
222 short buf_length
; /* 2s complement */
226 struct lance_interface
228 struct lance_init_block init_block
;
229 struct lance_rx_head rx_ring
[RX_RING_SIZE
];
230 struct lance_tx_head tx_ring
[TX_RING_SIZE
];
231 unsigned char rbuf
[RX_RING_SIZE
][ETH_FRAME_LEN
];
232 unsigned char tbuf
[TX_RING_SIZE
][ETH_FRAME_LEN
];
235 /* =============== global variables =============== */
236 /* AKA the stuff that really should have been in ether_card_t */
237 static struct lance_interface
*lp
;
238 #define LANCE_BUF_SIZE (sizeof(struct lance_interface))
239 static char *lance_buf
= NULL
;
240 static int rx_slot_nr
= 0; /* Rx-slot number */
241 static int tx_slot_nr
= 0; /* Tx-slot number */
242 static int cur_tx_slot_nr
= 0; /* Tx-slot number */
243 static char isstored
[TX_RING_SIZE
]; /* Tx-slot in-use */
245 phys_bytes lance_buf_phys
;
247 /* SEF functions and variables. */
248 static void sef_local_startup(void);
249 static int sef_cb_init_fresh(int type
, sef_init_info_t
*info
);
250 static void sef_cb_signal_handler(int signo
);
252 /*===========================================================================*
254 *===========================================================================*/
255 int main( int argc
, char **argv
)
262 /* SEF local startup. */
263 env_setargs(argc
, argv
);
271 sys_irqenable(&ec
->ec_hook
);
273 if ((r
= netdriver_receive(ANY
, &m
, &ipc_status
)) != OK
)
274 panic("netdriver_receive failed: %d", r
);
277 sys_irqdisable(&ec
->ec_hook
);
279 if (is_ipc_notify(ipc_status
)) {
280 switch(_ENDPOINT_P(m
.m_source
)) {
285 if (ec
->mode
== EC_ENABLED
)
287 ec
->ec_int_pending
= 0;
293 panic("illegal notify source: %d", m
.m_source
);
296 /* get next message */
303 do_vwrite_s(&m
, FALSE
);
315 panic("illegal message: %d", m
.m_type
);
322 /*===========================================================================*
323 * sef_local_startup *
324 *===========================================================================*/
325 static void sef_local_startup()
327 /* Register init callbacks. */
328 sef_setcb_init_fresh(sef_cb_init_fresh
);
329 sef_setcb_init_lu(sef_cb_init_fresh
);
330 sef_setcb_init_restart(sef_cb_init_fresh
);
332 /* Register live update callbacks. */
333 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready
);
334 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_workfree
);
336 /* Register signal callbacks. */
337 sef_setcb_signal_handler(sef_cb_signal_handler
);
339 /* Let SEF perform startup. */
343 /*===========================================================================*
344 * sef_cb_init_fresh *
345 *===========================================================================*/
346 static int sef_cb_init_fresh(int type
, sef_init_info_t
*UNUSED(info
))
348 /* Initialize the lance driver. */
351 int r
, fkeys
, sfkeys
;
356 bit_set( sfkeys
, 7 );
357 if ( (r
= fkey_map(&fkeys
, &sfkeys
)) != OK
)
358 printf("Warning: lance couldn't observe Shift+F7 key: %d\n",r
);
362 (void) env_parse("instance", "d", 0, &v
, 0, 255);
363 ec_instance
= (int) v
;
365 /* Announce we are up! */
366 netdriver_announce();
371 /*===========================================================================*
372 * sef_cb_signal_handler *
373 *===========================================================================*/
374 static void sef_cb_signal_handler(int signo
)
377 /* Only check for termination signal, ignore anything else. */
378 if (signo
!= SIGTERM
) return;
380 if (ec_state
.mode
== EC_ENABLED
)
381 lance_stop(&ec_state
);
384 printf("LANCE driver stopped.\n");
390 /*===========================================================================*
392 *===========================================================================*/
393 static void lance_dump()
397 unsigned short ioaddr
;
401 if (ec
->mode
== EC_DISABLED
)
402 printf("lance instance %d is disabled\n", ec_instance
);
403 else if (ec
->mode
== EC_SINK
)
404 printf("lance instance %d is in sink mode\n", ec_instance
);
406 if (ec
->mode
!= EC_ENABLED
)
409 printf("lance statistics of instance %d:\n", ec_instance
);
411 printf("recvErr :%8ld\t", ec
->eth_stat
.ets_recvErr
);
412 printf("sendErr :%8ld\t", ec
->eth_stat
.ets_sendErr
);
413 printf("OVW :%8ld\n", ec
->eth_stat
.ets_OVW
);
415 printf("CRCerr :%8ld\t", ec
->eth_stat
.ets_CRCerr
);
416 printf("frameAll :%8ld\t", ec
->eth_stat
.ets_frameAll
);
417 printf("missedP :%8ld\n", ec
->eth_stat
.ets_missedP
);
419 printf("packetR :%8ld\t", ec
->eth_stat
.ets_packetR
);
420 printf("packetT :%8ld\t", ec
->eth_stat
.ets_packetT
);
421 printf("transDef :%8ld\n", ec
->eth_stat
.ets_transDef
);
423 printf("collision :%8ld\t", ec
->eth_stat
.ets_collision
);
424 printf("transAb :%8ld\t", ec
->eth_stat
.ets_transAb
);
425 printf("carrSense :%8ld\n", ec
->eth_stat
.ets_carrSense
);
427 printf("fifoUnder :%8ld\t", ec
->eth_stat
.ets_fifoUnder
);
428 printf("fifoOver :%8ld\t", ec
->eth_stat
.ets_fifoOver
);
429 printf("CDheartbeat:%8ld\n", ec
->eth_stat
.ets_CDheartbeat
);
431 printf("OWC :%8ld\t", ec
->eth_stat
.ets_OWC
);
433 ioaddr
= ec
->ec_port
;
434 isr
= read_csr(ioaddr
, LANCE_CSR0
);
435 printf("isr = 0x%x, flags = 0x%x\n", isr
,
438 printf("irq = %d\tioadr = 0x%x\n", ec
->ec_irq
, ec
->ec_port
);
440 csr
= read_csr(ioaddr
, LANCE_CSR0
);
441 printf("CSR0: 0x%x\n", csr
);
442 csr
= read_csr(ioaddr
, LANCE_CSR3
);
443 printf("CSR3: 0x%x\n", csr
);
444 csr
= read_csr(ioaddr
, LANCE_CSR4
);
445 printf("CSR4: 0x%x\n", csr
);
446 csr
= read_csr(ioaddr
, LANCE_CSR5
);
447 printf("CSR5: 0x%x\n", csr
);
448 csr
= read_csr(ioaddr
, LANCE_CSR15
);
449 printf("CSR15: 0x%x\n", csr
);
452 /*===========================================================================*
454 *===========================================================================*/
455 static void do_init(mp
)
463 if(!lance_buf
&& !(lance_buf
= alloc_contig(LANCE_BUF_SIZE
, AC_ALIGN4K
|AC_LOWER16M
, &lance_buf_phys
))) {
464 panic("alloc_contig failed: %d", LANCE_BUF_SIZE
);
468 strlcpy(ec
->port_name
, "lance#0", sizeof(ec
->port_name
));
469 ec
->port_name
[6] += ec_instance
;
471 if (ec
->mode
== EC_DISABLED
)
473 /* This is the default, try to (re)locate the device. */
474 /* only try to enable if memory is correct for DMA */
475 if ( CORRECT_DMA_MEM() )
481 printf("LANCE: DMA denied because address out of range\n" );
484 if (ec
->mode
== EC_DISABLED
)
486 /* Probe failed, or the device is configured off. */
487 reply_mess
.m_type
= DL_CONF_REPLY
;
488 reply_mess
.m_netdrv_net_dl_conf
.stat
= ENXIO
;
489 mess_reply(mp
, &reply_mess
);
492 if (ec
->mode
== EC_ENABLED
)
496 if (ec
->mode
== EC_SINK
)
498 ec
->mac_address
.ea_addr
[0] =
499 ec
->mac_address
.ea_addr
[1] =
500 ec
->mac_address
.ea_addr
[2] =
501 ec
->mac_address
.ea_addr
[3] =
502 ec
->mac_address
.ea_addr
[4] =
503 ec
->mac_address
.ea_addr
[5] = 0;
505 reply_mess
.m_type
= DL_CONF_REPLY
;
506 reply_mess
.m_netdrv_net_dl_conf
.stat
= OK
;
507 memcpy(reply_mess
.m_netdrv_net_dl_conf
.hw_addr
, ec
->mac_address
.ea_addr
,
508 sizeof(reply_mess
.m_netdrv_net_dl_conf
.hw_addr
));
509 mess_reply(mp
, &reply_mess
);
512 assert(ec
->mode
== EC_ENABLED
);
513 assert(ec
->flags
& ECF_ENABLED
);
515 ec
->flags
&= ~(ECF_PROMISC
| ECF_MULTI
| ECF_BROAD
);
517 if (mp
->m_net_netdrv_dl_conf
.mode
& DL_PROMISC_REQ
)
518 ec
->flags
|= ECF_PROMISC
| ECF_MULTI
| ECF_BROAD
;
519 if (mp
->m_net_netdrv_dl_conf
.mode
& DL_MULTI_REQ
)
520 ec
->flags
|= ECF_MULTI
;
521 if (mp
->m_net_netdrv_dl_conf
.mode
& DL_BROAD_REQ
)
522 ec
->flags
|= ECF_BROAD
;
526 reply_mess
.m_type
= DL_CONF_REPLY
;
527 reply_mess
.m_netdrv_net_dl_conf
.stat
= OK
;
528 memcpy(reply_mess
.m_netdrv_net_dl_conf
.hw_addr
, ec
->mac_address
.ea_addr
,
529 sizeof(reply_mess
.m_netdrv_net_dl_conf
.hw_addr
));
531 mess_reply(mp
, &reply_mess
);
535 /*===========================================================================*
537 *===========================================================================*/
538 static void do_int(ec
)
541 if (ec
->flags
& (ECF_PACK_SEND
| ECF_PACK_RECV
))
546 /*===========================================================================*
548 *===========================================================================*/
549 static void conf_hw(ec
)
552 static eth_stat_t empty_stat
= {0, 0, 0, 0, 0, 0 /* ,... */ };
557 ec
->mode
= EC_DISABLED
; /* Superfluous */
559 /* Pick a default configuration. This hardly matters anymore. */
560 confnr
= MIN(ec_instance
, EC_CONF_NR
-1);
562 ecp
= &ec_conf
[confnr
];
563 update_conf(ec
, ecp
);
564 if (ec
->mode
!= EC_ENABLED
)
567 if (!lance_probe(ec
, ec_instance
))
569 printf("%s: No ethernet card found on PCI-BIOS info.\n",
571 ec
->mode
= EC_DISABLED
;
575 /* XXX */ if (ec
->ec_linmem
== 0) ec
->ec_linmem
= 0xFFFF0000;
577 ec
->flags
= ECF_EMPTY
;
578 ec
->eth_stat
= empty_stat
;
582 /*===========================================================================*
584 *===========================================================================*/
585 static void update_conf(ec
, ecp
)
591 static char ec_fmt
[] = "x:d:x:x";
593 /* Get the default settings and modify them from the environment. */
594 strlcpy(eckey
, "LANCE0", sizeof(eckey
));
595 eckey
[5] += ec_instance
;
598 switch (env_parse(eckey
, ec_fmt
, 0, &v
, 0x0000L
, 0xFFFFL
))
601 ec
->mode
= EC_DISABLED
;
606 ec
->mode
= EC_ENABLED
; /* Might become disabled if
613 v
= ecp
->ec_irq
| DEI_DEFAULT
;
614 (void) env_parse(eckey
, ec_fmt
, 1, &v
, 0L, (long) NR_IRQ_VECTORS
- 1);
618 (void) env_parse(eckey
, ec_fmt
, 2, &v
, 0L, 0xFFFFFL
);
622 (void) env_parse(eckey
, ec_fmt
, 3, &v
, 0x2000L
, 0x8000L
);
627 /*===========================================================================*
629 *===========================================================================*/
630 static void ec_init(ec
)
638 /* General initialization */
639 ec
->flags
= ECF_EMPTY
;
640 lance_init_card(ec
); /* Get mac_address, etc ...*/
645 printf("%s: Ethernet address ", ec
->port_name
);
646 for (i
= 0; i
< 6; i
++)
647 printf("%x%c", ec
->mac_address
.ea_addr
[i
],
651 /* Finish the initialization */
652 ec
->flags
|= ECF_ENABLED
;
654 /* Set the interrupt handler */
655 ec
->ec_hook
= ec
->ec_irq
;
656 if ((r
=sys_irqsetpolicy(ec
->ec_irq
, 0, &ec
->ec_hook
)) != OK
)
657 printf("lance: error, couldn't set IRQ policy: %d\n", r
);
663 /*===========================================================================*
665 *===========================================================================*/
666 static void reply(ec
)
673 if (ec
->flags
& ECF_PACK_SEND
)
674 flags
|= DL_PACK_SEND
;
675 if (ec
->flags
& ECF_PACK_RECV
)
676 flags
|= DL_PACK_RECV
;
678 reply
.m_type
= DL_TASK_REPLY
;
679 reply
.m_netdrv_net_dl_task
.flags
= flags
;
680 reply
.m_netdrv_net_dl_task
.count
= ec
->read_s
;
682 r
= ipc_send(ec
->client
, &reply
);
684 panic("ipc_send failed: %d", r
);
687 ec
->flags
&= ~(ECF_PACK_SEND
| ECF_PACK_RECV
);
691 /*===========================================================================*
693 *===========================================================================*/
694 static void mess_reply(req
, reply_mess
)
698 if (ipc_send(req
->m_source
, reply_mess
) != OK
)
699 panic("unable to mess_reply");
703 /*===========================================================================*
705 *===========================================================================*/
706 static void ec_confaddr(ec
)
711 static char eafmt
[]= "x:x:x:x:x:x";
714 /* User defined ethernet address? */
715 strlcpy(eakey
, "LANCE0_EA", sizeof(eakey
));
716 eakey
[5] += ec_instance
;
718 for (i
= 0; i
< 6; i
++)
720 v
= ec
->mac_address
.ea_addr
[i
];
721 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
723 ec
->mac_address
.ea_addr
[i
]= v
;
726 if (i
!= 0 && i
!= 6)
728 /* It's all or nothing; force a panic. */
729 (void) env_parse(eakey
, "?", 0, &v
, 0L, 0L);
734 /*===========================================================================*
736 *===========================================================================*/
737 static void ec_reinit(ec
)
741 unsigned short ioaddr
= ec
->ec_port
;
744 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
747 tx_slot_nr
= cur_tx_slot_nr
= 0;
748 for (i
=0; i
<TX_RING_SIZE
; i
++)
750 lp
->tx_ring
[i
].u
.base
= 0;
754 /* re-init Rx-ring */
756 for (i
=0; i
<RX_RING_SIZE
; i
++)
758 lp
->rx_ring
[i
].buf_length
= -ETH_FRAME_LEN
;
759 lp
->rx_ring
[i
].u
.addr
[3] |= 0x80;
762 /* Set 'Receive Mode' */
763 if (ec
->flags
& ECF_PROMISC
)
765 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_PROM
);
769 if (ec
->flags
& (ECF_BROAD
| ECF_MULTI
))
771 write_csr(ioaddr
, LANCE_CSR15
, 0x0000);
775 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_DRCVBC
);
779 /* start && enable interrupt */
780 write_csr(ioaddr
, LANCE_CSR0
,
781 LANCE_CSR0_IDON
|LANCE_CSR0_IENA
|LANCE_CSR0_STRT
);
786 /*===========================================================================*
788 *===========================================================================*/
789 static void ec_check_ints(ec
)
792 int must_restart
= 0;
795 unsigned short ioaddr
= ec
->ec_port
;
797 if (!(ec
->flags
& ECF_ENABLED
))
798 panic("got premature interrupt");
803 printf("ETH: Reading ISR...");
805 isr
= read_csr(ioaddr
, LANCE_CSR0
);
806 if (isr
& (LANCE_CSR0_ERR
|LANCE_CSR0_RINT
|LANCE_CSR0_TINT
)) {
807 write_csr(ioaddr
, LANCE_CSR0
,
808 isr
& ~(LANCE_CSR0_IENA
|LANCE_CSR0_TDMD
|LANCE_CSR0_STOP
809 |LANCE_CSR0_STRT
|LANCE_CSR0_INIT
) );
811 write_csr(ioaddr
, LANCE_CSR0
,
812 LANCE_CSR0_BABL
|LANCE_CSR0_CERR
|LANCE_CSR0_MISS
|LANCE_CSR0_MERR
813 |LANCE_CSR0_IDON
|LANCE_CSR0_IENA
);
815 #define ISR_RST 0x0000
817 if ((isr
& (LANCE_CSR0_TINT
|LANCE_CSR0_RINT
|LANCE_CSR0_MISS
818 |LANCE_CSR0_BABL
|LANCE_CSR0_ERR
)) == 0x0000)
826 if (isr
& LANCE_CSR0_MISS
)
829 printf("RX Missed Frame\n");
831 ec
->eth_stat
.ets_recvErr
++;
833 if ((isr
& LANCE_CSR0_BABL
) || (isr
& LANCE_CSR0_TINT
))
835 if (isr
& LANCE_CSR0_BABL
)
838 printf("TX Timeout\n");
840 ec
->eth_stat
.ets_sendErr
++;
842 if (isr
& LANCE_CSR0_TINT
)
847 /* status check: restart if needed. */
848 status
= lp
->tx_ring
[cur_tx_slot_nr
].u
.base
;
851 if (status
& 0x40000000)
853 status
= lp
->tx_ring
[cur_tx_slot_nr
].misc
;
854 ec
->eth_stat
.ets_sendErr
++;
856 ec
->eth_stat
.ets_transAb
++;
858 ec
->eth_stat
.ets_carrSense
++;
860 ec
->eth_stat
.ets_OWC
++;
863 ec
->eth_stat
.ets_fifoUnder
++;
869 if (status
& 0x18000000)
870 ec
->eth_stat
.ets_collision
++;
871 ec
->eth_stat
.ets_packetT
++;
874 /* transmit a packet on the next slot if it exists. */
876 if (isstored
[cur_tx_slot_nr
]==1)
878 /* free the tx-slot just transmitted */
879 isstored
[cur_tx_slot_nr
]=0;
880 cur_tx_slot_nr
= (cur_tx_slot_nr
+ 1) & TX_RING_MOD_MASK
;
882 /* next tx-slot is ready? */
883 if (isstored
[cur_tx_slot_nr
]==1)
890 panic("got premature TX INT..");
894 lp
->tx_ring
[cur_tx_slot_nr
].u
.addr
[3] = 0x83;
895 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_IENA
|LANCE_CSR0_TDMD
);
897 /* we set a buffered message in the slot if it exists. */
898 /* and transmit it, if needed. */
899 if (ec
->flags
& ECF_SEND_AVAIL
)
902 if (isr
& LANCE_CSR0_RINT
)
912 ec
->flags
= ECF_STOPPED
;
919 /* ??? cf. lance driver on linux */
920 if (must_restart
== 1)
923 printf("ETH: restarting...\n");
926 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
928 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STRT
);
932 if ((ec
->flags
& (ECF_READING
|ECF_STOPPED
)) == (ECF_READING
|ECF_STOPPED
))
935 printf("ETH: resetting...\n");
941 /*===========================================================================*
943 *===========================================================================*/
944 static void ec_reset(ec
)
947 /* Stop/start the chip, and clear all RX,TX-slots */
948 unsigned short ioaddr
= ec
->ec_port
;
952 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
954 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STRT
);
957 tx_slot_nr
= cur_tx_slot_nr
= 0;
958 for (i
=0; i
<TX_RING_SIZE
; i
++)
960 lp
->tx_ring
[i
].u
.base
= 0;
964 /* re-init Rx-ring */
966 for (i
=0; i
<RX_RING_SIZE
; i
++)
968 lp
->rx_ring
[i
].buf_length
= -ETH_FRAME_LEN
;
969 lp
->rx_ring
[i
].u
.addr
[3] |= 0x80;
972 /* store a buffered message on the slot if exists */
974 ec
->flags
&= ~ECF_STOPPED
;
977 /*===========================================================================*
979 *===========================================================================*/
980 static void ec_send(ec
)
983 /* from ec_check_ints() or ec_reset(). */
984 /* this function proccesses the buffered message. (slot/transmit) */
985 if (!(ec
->flags
& ECF_SEND_AVAIL
))
988 ec
->flags
&= ~ECF_SEND_AVAIL
;
989 switch(ec
->sendmsg
.m_type
)
991 case DL_WRITEV_S
: do_vwrite_s(&ec
->sendmsg
, TRUE
); break;
993 panic("wrong type: %d", ec
->sendmsg
.m_type
);
998 /*===========================================================================*
1000 *===========================================================================*/
1001 static void do_vread_s(const message
*mp
)
1008 ec
->client
= mp
->m_source
;
1009 count
= mp
->m_net_netdrv_dl_readv_s
.count
;
1011 r
= sys_safecopyfrom(mp
->m_source
, mp
->m_net_netdrv_dl_readv_s
.grant
, 0,
1012 (vir_bytes
)ec
->read_iovec
.iod_iovec
,
1013 (count
> IOVEC_NR
? IOVEC_NR
: count
) *
1016 panic("do_vread_s: sys_safecopyfrom failed: %d", r
);
1017 ec
->read_iovec
.iod_iovec_s
= count
;
1018 ec
->read_iovec
.iod_proc_nr
= mp
->m_source
;
1019 ec
->read_iovec
.iod_grant
= mp
->m_net_netdrv_dl_readv_s
.grant
;
1020 ec
->read_iovec
.iod_iovec_offset
= 0;
1022 ec
->tmp_iovec
= ec
->read_iovec
;
1024 ec
->flags
|= ECF_READING
;
1028 if ((ec
->flags
& (ECF_READING
|ECF_STOPPED
)) == (ECF_READING
|ECF_STOPPED
))
1033 /*===========================================================================*
1035 *===========================================================================*/
1036 static void ec_recv(ec
)
1040 int packet_processed
;
1042 unsigned short ioaddr
= ec
->ec_port
;
1044 if ((ec
->flags
& ECF_READING
)==0)
1046 if (!(ec
->flags
& ECF_ENABLED
))
1049 /* we check all the received slots until find a properly received packet */
1050 packet_processed
= FALSE
;
1051 while (!packet_processed
)
1053 status
= lp
->rx_ring
[rx_slot_nr
].u
.base
>> 24;
1054 if ( (status
& 0x80) == 0x00 )
1056 status
= lp
->rx_ring
[rx_slot_nr
].u
.base
>> 24;
1062 ec
->eth_stat
.ets_recvErr
++;
1064 ec
->eth_stat
.ets_fifoOver
++;
1066 ec
->eth_stat
.ets_CRCerr
++;
1068 ec
->eth_stat
.ets_OVW
++;
1070 ec
->eth_stat
.ets_frameAll
++;
1075 ec
->eth_stat
.ets_packetR
++;
1076 length
= lp
->rx_ring
[rx_slot_nr
].msg_length
;
1080 ec_nic2user(ec
, (int)(lp
->rbuf
[rx_slot_nr
]),
1081 &ec
->read_iovec
, 0, length
);
1083 ec
->read_s
= length
;
1084 ec
->flags
|= ECF_PACK_RECV
;
1085 ec
->flags
&= ~ECF_READING
;
1086 packet_processed
= TRUE
;
1088 /* set up this slot again, and we move to the next slot */
1089 lp
->rx_ring
[rx_slot_nr
].buf_length
= -ETH_FRAME_LEN
;
1090 lp
->rx_ring
[rx_slot_nr
].u
.addr
[3] |= 0x80;
1092 write_csr(ioaddr
, LANCE_CSR0
,
1093 LANCE_CSR0_BABL
|LANCE_CSR0_CERR
|LANCE_CSR0_MISS
1094 |LANCE_CSR0_MERR
|LANCE_CSR0_IDON
|LANCE_CSR0_IENA
);
1096 rx_slot_nr
= (rx_slot_nr
+ 1) & RX_RING_MOD_MASK
;
1103 /*===========================================================================*
1105 *===========================================================================*/
1106 static void do_vwrite_s(mp
, from_int
)
1110 int count
, check
, r
;
1112 unsigned short ioaddr
;
1116 ec
->client
= mp
->m_source
;
1117 count
= mp
->m_net_netdrv_dl_writev_s
.count
;
1119 if (isstored
[tx_slot_nr
]==1)
1121 /* all slots are used, so this message is buffered */
1123 ec
->flags
|= ECF_SEND_AVAIL
;
1128 /* convert the message to write_iovec */
1129 r
= sys_safecopyfrom(mp
->m_source
, mp
->m_net_netdrv_dl_writev_s
.grant
, 0,
1130 (vir_bytes
)ec
->write_iovec
.iod_iovec
,
1131 (count
> IOVEC_NR
? IOVEC_NR
: count
) *
1134 panic("do_vwrite_s: sys_safecopyfrom failed: %d", r
);
1135 ec
->write_iovec
.iod_iovec_s
= count
;
1136 ec
->write_iovec
.iod_proc_nr
= mp
->m_source
;
1137 ec
->write_iovec
.iod_grant
= mp
->m_net_netdrv_dl_writev_s
.grant
;
1138 ec
->write_iovec
.iod_iovec_offset
= 0;
1140 ec
->tmp_iovec
= ec
->write_iovec
;
1141 ec
->write_s
= calc_iovec_size(&ec
->tmp_iovec
);
1143 /* copy write_iovec to the slot on DMA address */
1144 ec_user2nic(ec
, &ec
->write_iovec
, 0,
1145 (int)(lp
->tbuf
[tx_slot_nr
]), ec
->write_s
);
1146 /* set-up for transmitting, and transmit it if needed. */
1147 lp
->tx_ring
[tx_slot_nr
].buf_length
= -ec
->write_s
;
1148 lp
->tx_ring
[tx_slot_nr
].misc
= 0x0;
1149 lp
->tx_ring
[tx_slot_nr
].u
.base
1150 = virt_to_bus(lp
->tbuf
[tx_slot_nr
]) & 0xffffff;
1151 isstored
[tx_slot_nr
]=1;
1152 if (cur_tx_slot_nr
== tx_slot_nr
)
1156 tx_slot_nr
= (tx_slot_nr
+ 1) & TX_RING_MOD_MASK
;
1160 ioaddr
= ec
->ec_port
;
1161 lp
->tx_ring
[cur_tx_slot_nr
].u
.addr
[3] = 0x83;
1162 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_IENA
|LANCE_CSR0_TDMD
);
1165 ec
->flags
|= ECF_PACK_SEND
;
1167 /* reply by calling do_int() if this function is called from interrupt. */
1174 /*===========================================================================*
1176 *===========================================================================*/
1177 static void ec_user2nic(ec
, iovp
, offset
, nic_addr
, count
)
1191 ec_next_iovec(iovp
);
1195 if (offset
>= iovp
->iod_iovec
[i
].iov_size
)
1197 offset
-= iovp
->iod_iovec
[i
].iov_size
;
1201 bytes
= iovp
->iod_iovec
[i
].iov_size
- offset
;
1205 if ( (r
=sys_safecopyfrom(iovp
->iod_proc_nr
,
1206 iovp
->iod_iovec
[i
].iov_grant
, offset
,
1207 nic_addr
, bytes
)) != OK
)
1208 panic("ec_user2nic: sys_safecopyfrom failed: %d", r
);
1216 /*===========================================================================*
1218 *===========================================================================*/
1219 static void ec_nic2user(ec
, nic_addr
, iovp
, offset
, count
)
1233 ec_next_iovec(iovp
);
1237 if (offset
>= iovp
->iod_iovec
[i
].iov_size
)
1239 offset
-= iovp
->iod_iovec
[i
].iov_size
;
1243 bytes
= iovp
->iod_iovec
[i
].iov_size
- offset
;
1246 if ( (r
=sys_safecopyto( iovp
->iod_proc_nr
, iovp
->iod_iovec
[i
].iov_grant
,
1247 offset
, nic_addr
, bytes
)) != OK
)
1248 panic("ec_nic2user: sys_safecopyto failed: %d", r
);
1257 /*===========================================================================*
1259 *===========================================================================*/
1260 static int calc_iovec_size(iovec_dat_t
*iovp
)
1266 while (i
< iovp
->iod_iovec_s
)
1270 ec_next_iovec(iovp
);
1274 size
+= iovp
->iod_iovec
[i
].iov_size
;
1281 /*===========================================================================*
1283 *===========================================================================*/
1284 static void ec_next_iovec(iovp
)
1289 iovp
->iod_iovec_s
-= IOVEC_NR
;
1290 iovp
->iod_iovec_offset
+= IOVEC_NR
* sizeof(iovec_s_t
);
1292 r
= sys_safecopyfrom(iovp
->iod_proc_nr
, iovp
->iod_grant
,
1293 iovp
->iod_iovec_offset
,
1294 (vir_bytes
)iovp
->iod_iovec
,
1295 (iovp
->iod_iovec_s
> IOVEC_NR
?
1296 IOVEC_NR
: iovp
->iod_iovec_s
) *
1299 panic("ec_next_iovec: sys_safecopyfrom failed: %d", r
);
1303 /*===========================================================================*
1305 *===========================================================================*/
1306 static void do_getstat_s(mp
)
1314 r
= sys_safecopyto(mp
->m_source
, mp
->m_net_netdrv_dl_getstat_s
.grant
, 0,
1315 (vir_bytes
)&ec
->eth_stat
, sizeof(ec
->eth_stat
));
1318 panic("do_getstat_s: sys_safecopyto failed: %d", r
);
1320 mp
->m_type
= DL_STAT_REPLY
;
1321 r
= ipc_send(mp
->m_source
, mp
);
1323 panic("do_getstat_s: send failed: %d", r
);
1326 /*===========================================================================*
1328 *===========================================================================*/
1329 static void lance_stop(ec
)
1332 unsigned short ioaddr
;
1334 if (!(ec
->flags
& ECF_ENABLED
))
1337 ioaddr
= ec
->ec_port
;
1340 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
1343 in_word(ioaddr
+LANCE_RESET
);
1345 ec
->flags
= ECF_EMPTY
;
1348 /*===========================================================================*
1350 *===========================================================================*/
1351 static void getAddressing(devind
, ec
)
1355 unsigned int membase
, ioaddr
;
1358 for (reg
= PCI_BAR
; reg
<= PCI_BAR_6
; reg
+= 4)
1360 ioaddr
= pci_attr_r32(devind
, reg
);
1362 if ((ioaddr
& PCI_BAR_IO_MASK
) == 0 || (ioaddr
& PCI_BAR_IO
) == 0)
1364 /* Strip the I/O address out of the returned value */
1365 ioaddr
&= PCI_BAR_IO_MASK
;
1366 /* Get the memory base address */
1367 membase
= pci_attr_r32(devind
, PCI_BAR_2
);
1368 /* KK: Get the IRQ number */
1369 irq
= pci_attr_r8(devind
, PCI_IPR
);
1371 irq
= pci_attr_r8(devind
, PCI_ILR
);
1373 ec
->ec_linmem
= membase
;
1374 ec
->ec_port
= ioaddr
;
1379 /*===========================================================================*
1381 *===========================================================================*/
1382 static int lance_probe(ec
, skip
)
1386 unsigned short pci_cmd
;
1387 unsigned short ioaddr
;
1388 int lance_version
, chip_version
;
1392 r
= pci_first_dev(&devind
, &vid
, &did
);
1398 r
= pci_next_dev(&devind
, &vid
, &did
);
1403 pci_reserve(devind
);
1405 getAddressing(devind
, ec
);
1408 /* ===== Bus Master ? ===== */
1409 pci_cmd
= pci_attr_r32(devind
, PCI_CR
);
1410 if (!(pci_cmd
& PCI_CR_MAST_EN
)) {
1411 pci_cmd
|= PCI_CR_MAST_EN
;
1412 pci_attr_w32(devind
, PCI_CR
, pci_cmd
);
1415 /* ===== Probe Details ===== */
1416 ioaddr
= ec
->ec_port
;
1419 in_word(ioaddr
+LANCE_RESET
);
1421 if (read_csr(ioaddr
, LANCE_CSR0
) != LANCE_CSR0_STOP
)
1423 ec
->mode
=EC_DISABLED
;
1426 /* Probe Chip Version */
1427 out_word(ioaddr
+LANCE_ADDR
, 88); /* Get the version of the chip */
1428 if (in_word(ioaddr
+LANCE_ADDR
) != 88)
1432 chip_version
= read_csr(ioaddr
, LANCE_CSR88
);
1433 chip_version
|= read_csr(ioaddr
, LANCE_CSR89
) << 16;
1435 if ((chip_version
& 0xfff) != 0x3)
1437 ec
->mode
=EC_DISABLED
;
1439 chip_version
= (chip_version
>> 12) & 0xffff;
1440 for (lance_version
= 1; chip_table
[lance_version
].id_number
!= 0;
1442 if (chip_table
[lance_version
].id_number
== chip_version
)
1447 printf("%s: %s at %X:%d\n",
1448 ec
->port_name
, chip_table
[lance_version
].name
,
1449 ec
->ec_port
, ec
->ec_irq
);
1452 return lance_version
;
1455 /*===========================================================================*
1457 *===========================================================================*/
1458 static void lance_init_card(ec
)
1462 Address l
= (vir_bytes
)lance_buf
;
1463 unsigned short ioaddr
= ec
->ec_port
;
1465 /* ============= setup init_block(cf. lance_probe1) ================ */
1466 /* make sure data structure is 8-byte aligned and below 16MB (for DMA) */
1468 lp
= (struct lance_interface
*)l
;
1470 /* disable Tx and Rx */
1471 lp
->init_block
.mode
= LANCE_CSR15_DTX
|LANCE_CSR15_DRX
;
1472 lp
->init_block
.filter
[0] = lp
->init_block
.filter
[1] = 0x0;
1473 /* using multiple Rx/Tx buffer */
1474 lp
->init_block
.rx_ring
1475 = (virt_to_bus(&lp
->rx_ring
) & 0xffffff) | RX_RING_LEN_BITS
;
1476 lp
->init_block
.tx_ring
1477 = (virt_to_bus(&lp
->tx_ring
) & 0xffffff) | TX_RING_LEN_BITS
;
1479 l
= virt_to_bus(&lp
->init_block
);
1480 write_csr(ioaddr
, LANCE_CSR1
, (unsigned short)l
);
1481 write_csr(ioaddr
, LANCE_CSR2
, (unsigned short)(l
>> 16));
1482 write_csr(ioaddr
, LANCE_CSR4
,
1483 LANCE_CSR4_APAD_XMT
|LANCE_CSR4_MFCOM
|LANCE_CSR4_RCVCCOM
1484 |LANCE_CSR4_TXSTRTM
|LANCE_CSR4_JABM
);
1486 /* ============= Get MAC address (cf. lance_probe1) ================ */
1487 for (i
= 0; i
< 6; ++i
)
1488 ec
->mac_address
.ea_addr
[i
]=in_byte(ioaddr
+LANCE_ETH_ADDR
+i
);
1490 /* ============ (re)start init_block(cf. lance_reset) =============== */
1491 /* Reset the LANCE */
1492 (void)in_word(ioaddr
+LANCE_RESET
);
1494 /* ----- Re-initialize the LANCE ----- */
1495 /* Set station address */
1496 for (i
= 0; i
< 6; ++i
)
1497 lp
->init_block
.phys_addr
[i
] = ec
->mac_address
.ea_addr
[i
];
1498 /* Preset the receive ring headers */
1499 for (i
=0; i
<RX_RING_SIZE
; i
++)
1501 lp
->rx_ring
[i
].buf_length
= -ETH_FRAME_LEN
;
1503 lp
->rx_ring
[i
].u
.base
= virt_to_bus(lp
->rbuf
[i
]) & 0xffffff;
1504 /* we set the top byte as the very last thing */
1505 lp
->rx_ring
[i
].u
.addr
[3] = 0x80;
1507 /* Preset the transmitting ring headers */
1508 for (i
=0; i
<TX_RING_SIZE
; i
++)
1510 lp
->tx_ring
[i
].u
.base
= 0;
1513 /* enable Rx and Tx */
1514 lp
->init_block
.mode
= 0x0;
1516 l
= (Address
)virt_to_bus(&lp
->init_block
);
1517 write_csr(ioaddr
, LANCE_CSR1
, (short)l
);
1518 write_csr(ioaddr
, LANCE_CSR2
, (short)(l
>> 16));
1519 write_csr(ioaddr
, LANCE_CSR4
,
1520 LANCE_CSR4_APAD_XMT
|LANCE_CSR4_MFCOM
|LANCE_CSR4_RCVCCOM
1521 |LANCE_CSR4_TXSTRTM
|LANCE_CSR4_JABM
);
1523 /* ----- start when init done. ----- */
1525 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
1527 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_INIT
);
1529 for (i
= 10000; i
> 0; --i
)
1530 if (read_csr(ioaddr
, LANCE_CSR0
) & LANCE_CSR0_IDON
)
1533 /* Set 'Multicast Table' */
1536 write_csr(ioaddr
, LANCE_CSR8
+ i
, 0xffff);
1539 /* Set 'Receive Mode' */
1540 if (ec
->flags
& ECF_PROMISC
)
1542 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_PROM
);
1546 if (ec
->flags
& (ECF_BROAD
| ECF_MULTI
))
1548 write_csr(ioaddr
, LANCE_CSR15
, 0x0000);
1552 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_DRCVBC
);
1556 /* start && enable interrupt */
1557 write_csr(ioaddr
, LANCE_CSR0
,
1558 LANCE_CSR0_IDON
|LANCE_CSR0_IENA
|LANCE_CSR0_STRT
);
1563 /*===========================================================================*
1565 *===========================================================================*/
1566 static u8_t
in_byte(port_t port
)
1571 r
= sys_inb(port
, &value
);
1573 panic("sys_inb failed: %d", r
);
1577 /*===========================================================================*
1579 *===========================================================================*/
1580 static u16_t
in_word(port_t port
)
1585 r
= sys_inw(port
, &value
);
1587 panic("sys_inw failed: %d", r
);
1592 /*===========================================================================*
1594 *===========================================================================*/
1595 static void out_word(port_t port
, u16_t value
)
1599 r
= sys_outw(port
, value
);
1601 panic("sys_outw failed: %d", r
);
1604 /*===========================================================================*
1606 *===========================================================================*/
1607 static u16_t
read_csr(port_t ioaddr
, u16_t csrno
)
1609 out_word(ioaddr
+LANCE_ADDR
, csrno
);
1610 return in_word(ioaddr
+LANCE_DATA
);
1613 /*===========================================================================*
1615 *===========================================================================*/
1616 static void write_csr(port_t ioaddr
, u16_t csrno
, u16_t value
)
1618 out_word(ioaddr
+LANCE_ADDR
, csrno
);
1619 out_word(ioaddr
+LANCE_DATA
, value
);