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
.DL_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
.DL_STAT
= OK
;
507 *(ether_addr_t
*) reply_mess
.DL_HWADDR
= ec
->mac_address
;
508 mess_reply(mp
, &reply_mess
);
511 assert(ec
->mode
== EC_ENABLED
);
512 assert(ec
->flags
& ECF_ENABLED
);
514 ec
->flags
&= ~(ECF_PROMISC
| ECF_MULTI
| ECF_BROAD
);
516 if (mp
->DL_MODE
& DL_PROMISC_REQ
)
517 ec
->flags
|= ECF_PROMISC
| ECF_MULTI
| ECF_BROAD
;
518 if (mp
->DL_MODE
& DL_MULTI_REQ
)
519 ec
->flags
|= ECF_MULTI
;
520 if (mp
->DL_MODE
& DL_BROAD_REQ
)
521 ec
->flags
|= ECF_BROAD
;
525 reply_mess
.m_type
= DL_CONF_REPLY
;
526 reply_mess
.DL_STAT
= OK
;
527 *(ether_addr_t
*) reply_mess
.DL_HWADDR
= ec
->mac_address
;
529 mess_reply(mp
, &reply_mess
);
533 /*===========================================================================*
535 *===========================================================================*/
536 static void do_int(ec
)
539 if (ec
->flags
& (ECF_PACK_SEND
| ECF_PACK_RECV
))
544 /*===========================================================================*
546 *===========================================================================*/
547 static void conf_hw(ec
)
550 static eth_stat_t empty_stat
= {0, 0, 0, 0, 0, 0 /* ,... */ };
555 ec
->mode
= EC_DISABLED
; /* Superfluous */
557 /* Pick a default configuration. This hardly matters anymore. */
558 confnr
= MIN(ec_instance
, EC_CONF_NR
-1);
560 ecp
= &ec_conf
[confnr
];
561 update_conf(ec
, ecp
);
562 if (ec
->mode
!= EC_ENABLED
)
565 if (!lance_probe(ec
, ec_instance
))
567 printf("%s: No ethernet card found on PCI-BIOS info.\n",
569 ec
->mode
= EC_DISABLED
;
573 /* XXX */ if (ec
->ec_linmem
== 0) ec
->ec_linmem
= 0xFFFF0000;
575 ec
->flags
= ECF_EMPTY
;
576 ec
->eth_stat
= empty_stat
;
580 /*===========================================================================*
582 *===========================================================================*/
583 static void update_conf(ec
, ecp
)
589 static char ec_fmt
[] = "x:d:x:x";
591 /* Get the default settings and modify them from the environment. */
592 strlcpy(eckey
, "LANCE0", sizeof(eckey
));
593 eckey
[5] += ec_instance
;
596 switch (env_parse(eckey
, ec_fmt
, 0, &v
, 0x0000L
, 0xFFFFL
))
599 ec
->mode
= EC_DISABLED
;
604 ec
->mode
= EC_ENABLED
; /* Might become disabled if
611 v
= ecp
->ec_irq
| DEI_DEFAULT
;
612 (void) env_parse(eckey
, ec_fmt
, 1, &v
, 0L, (long) NR_IRQ_VECTORS
- 1);
616 (void) env_parse(eckey
, ec_fmt
, 2, &v
, 0L, 0xFFFFFL
);
620 (void) env_parse(eckey
, ec_fmt
, 3, &v
, 0x2000L
, 0x8000L
);
625 /*===========================================================================*
627 *===========================================================================*/
628 static void ec_init(ec
)
636 /* General initialization */
637 ec
->flags
= ECF_EMPTY
;
638 lance_init_card(ec
); /* Get mac_address, etc ...*/
643 printf("%s: Ethernet address ", ec
->port_name
);
644 for (i
= 0; i
< 6; i
++)
645 printf("%x%c", ec
->mac_address
.ea_addr
[i
],
649 /* Finish the initialization */
650 ec
->flags
|= ECF_ENABLED
;
652 /* Set the interrupt handler */
653 ec
->ec_hook
= ec
->ec_irq
;
654 if ((r
=sys_irqsetpolicy(ec
->ec_irq
, 0, &ec
->ec_hook
)) != OK
)
655 printf("lance: error, couldn't set IRQ policy: %d\n", r
);
661 /*===========================================================================*
663 *===========================================================================*/
664 static void reply(ec
)
671 if (ec
->flags
& ECF_PACK_SEND
)
672 flags
|= DL_PACK_SEND
;
673 if (ec
->flags
& ECF_PACK_RECV
)
674 flags
|= DL_PACK_RECV
;
676 reply
.m_type
= DL_TASK_REPLY
;
677 reply
.DL_FLAGS
= flags
;
678 reply
.DL_COUNT
= ec
->read_s
;
680 r
= send(ec
->client
, &reply
);
682 panic("send failed: %d", r
);
685 ec
->flags
&= ~(ECF_PACK_SEND
| ECF_PACK_RECV
);
689 /*===========================================================================*
691 *===========================================================================*/
692 static void mess_reply(req
, reply_mess
)
696 if (send(req
->m_source
, reply_mess
) != OK
)
697 panic("unable to mess_reply");
701 /*===========================================================================*
703 *===========================================================================*/
704 static void ec_confaddr(ec
)
709 static char eafmt
[]= "x:x:x:x:x:x";
712 /* User defined ethernet address? */
713 strlcpy(eakey
, "LANCE0_EA", sizeof(eakey
));
714 eakey
[5] += ec_instance
;
716 for (i
= 0; i
< 6; i
++)
718 v
= ec
->mac_address
.ea_addr
[i
];
719 if (env_parse(eakey
, eafmt
, i
, &v
, 0x00L
, 0xFFL
) != EP_SET
)
721 ec
->mac_address
.ea_addr
[i
]= v
;
724 if (i
!= 0 && i
!= 6)
726 /* It's all or nothing; force a panic. */
727 (void) env_parse(eakey
, "?", 0, &v
, 0L, 0L);
732 /*===========================================================================*
734 *===========================================================================*/
735 static void ec_reinit(ec
)
739 unsigned short ioaddr
= ec
->ec_port
;
742 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
745 tx_slot_nr
= cur_tx_slot_nr
= 0;
746 for (i
=0; i
<TX_RING_SIZE
; i
++)
748 lp
->tx_ring
[i
].u
.base
= 0;
752 /* re-init Rx-ring */
754 for (i
=0; i
<RX_RING_SIZE
; i
++)
756 lp
->rx_ring
[i
].buf_length
= -ETH_FRAME_LEN
;
757 lp
->rx_ring
[i
].u
.addr
[3] |= 0x80;
760 /* Set 'Receive Mode' */
761 if (ec
->flags
& ECF_PROMISC
)
763 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_PROM
);
767 if (ec
->flags
& (ECF_BROAD
| ECF_MULTI
))
769 write_csr(ioaddr
, LANCE_CSR15
, 0x0000);
773 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_DRCVBC
);
777 /* start && enable interrupt */
778 write_csr(ioaddr
, LANCE_CSR0
,
779 LANCE_CSR0_IDON
|LANCE_CSR0_IENA
|LANCE_CSR0_STRT
);
784 /*===========================================================================*
786 *===========================================================================*/
787 static void ec_check_ints(ec
)
790 int must_restart
= 0;
793 unsigned short ioaddr
= ec
->ec_port
;
795 if (!(ec
->flags
& ECF_ENABLED
))
796 panic("got premature interrupt");
801 printf("ETH: Reading ISR...");
803 isr
= read_csr(ioaddr
, LANCE_CSR0
);
804 if (isr
& (LANCE_CSR0_ERR
|LANCE_CSR0_RINT
|LANCE_CSR0_TINT
)) {
805 write_csr(ioaddr
, LANCE_CSR0
,
806 isr
& ~(LANCE_CSR0_IENA
|LANCE_CSR0_TDMD
|LANCE_CSR0_STOP
807 |LANCE_CSR0_STRT
|LANCE_CSR0_INIT
) );
809 write_csr(ioaddr
, LANCE_CSR0
,
810 LANCE_CSR0_BABL
|LANCE_CSR0_CERR
|LANCE_CSR0_MISS
|LANCE_CSR0_MERR
811 |LANCE_CSR0_IDON
|LANCE_CSR0_IENA
);
813 #define ISR_RST 0x0000
815 if ((isr
& (LANCE_CSR0_TINT
|LANCE_CSR0_RINT
|LANCE_CSR0_MISS
816 |LANCE_CSR0_BABL
|LANCE_CSR0_ERR
)) == 0x0000)
824 if (isr
& LANCE_CSR0_MISS
)
827 printf("RX Missed Frame\n");
829 ec
->eth_stat
.ets_recvErr
++;
831 if ((isr
& LANCE_CSR0_BABL
) || (isr
& LANCE_CSR0_TINT
))
833 if (isr
& LANCE_CSR0_BABL
)
836 printf("TX Timeout\n");
838 ec
->eth_stat
.ets_sendErr
++;
840 if (isr
& LANCE_CSR0_TINT
)
845 /* status check: restart if needed. */
846 status
= lp
->tx_ring
[cur_tx_slot_nr
].u
.base
;
849 if (status
& 0x40000000)
851 status
= lp
->tx_ring
[cur_tx_slot_nr
].misc
;
852 ec
->eth_stat
.ets_sendErr
++;
854 ec
->eth_stat
.ets_transAb
++;
856 ec
->eth_stat
.ets_carrSense
++;
858 ec
->eth_stat
.ets_OWC
++;
861 ec
->eth_stat
.ets_fifoUnder
++;
867 if (status
& 0x18000000)
868 ec
->eth_stat
.ets_collision
++;
869 ec
->eth_stat
.ets_packetT
++;
872 /* transmit a packet on the next slot if it exists. */
874 if (isstored
[cur_tx_slot_nr
]==1)
876 /* free the tx-slot just transmitted */
877 isstored
[cur_tx_slot_nr
]=0;
878 cur_tx_slot_nr
= (cur_tx_slot_nr
+ 1) & TX_RING_MOD_MASK
;
880 /* next tx-slot is ready? */
881 if (isstored
[cur_tx_slot_nr
]==1)
888 panic("got premature TX INT..");
892 lp
->tx_ring
[cur_tx_slot_nr
].u
.addr
[3] = 0x83;
893 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_IENA
|LANCE_CSR0_TDMD
);
895 /* we set a buffered message in the slot if it exists. */
896 /* and transmit it, if needed. */
897 if (ec
->flags
& ECF_SEND_AVAIL
)
900 if (isr
& LANCE_CSR0_RINT
)
910 ec
->flags
= ECF_STOPPED
;
917 /* ??? cf. lance driver on linux */
918 if (must_restart
== 1)
921 printf("ETH: restarting...\n");
924 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
926 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STRT
);
930 if ((ec
->flags
& (ECF_READING
|ECF_STOPPED
)) == (ECF_READING
|ECF_STOPPED
))
933 printf("ETH: resetting...\n");
939 /*===========================================================================*
941 *===========================================================================*/
942 static void ec_reset(ec
)
945 /* Stop/start the chip, and clear all RX,TX-slots */
946 unsigned short ioaddr
= ec
->ec_port
;
950 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
952 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STRT
);
955 tx_slot_nr
= cur_tx_slot_nr
= 0;
956 for (i
=0; i
<TX_RING_SIZE
; i
++)
958 lp
->tx_ring
[i
].u
.base
= 0;
962 /* re-init Rx-ring */
964 for (i
=0; i
<RX_RING_SIZE
; i
++)
966 lp
->rx_ring
[i
].buf_length
= -ETH_FRAME_LEN
;
967 lp
->rx_ring
[i
].u
.addr
[3] |= 0x80;
970 /* store a buffered message on the slot if exists */
972 ec
->flags
&= ~ECF_STOPPED
;
975 /*===========================================================================*
977 *===========================================================================*/
978 static void ec_send(ec
)
981 /* from ec_check_ints() or ec_reset(). */
982 /* this function proccesses the buffered message. (slot/transmit) */
983 if (!(ec
->flags
& ECF_SEND_AVAIL
))
986 ec
->flags
&= ~ECF_SEND_AVAIL
;
987 switch(ec
->sendmsg
.m_type
)
989 case DL_WRITEV_S
: do_vwrite_s(&ec
->sendmsg
, TRUE
); break;
991 panic("wrong type: %d", ec
->sendmsg
.m_type
);
996 /*===========================================================================*
998 *===========================================================================*/
999 static void do_vread_s(const message
*mp
)
1006 ec
->client
= mp
->m_source
;
1007 count
= mp
->DL_COUNT
;
1009 r
= sys_safecopyfrom(mp
->m_source
, mp
->DL_GRANT
, 0,
1010 (vir_bytes
)ec
->read_iovec
.iod_iovec
,
1011 (count
> IOVEC_NR
? IOVEC_NR
: count
) *
1014 panic("do_vread_s: sys_safecopyfrom failed: %d", r
);
1015 ec
->read_iovec
.iod_iovec_s
= count
;
1016 ec
->read_iovec
.iod_proc_nr
= mp
->m_source
;
1017 ec
->read_iovec
.iod_grant
= (cp_grant_id_t
) mp
->DL_GRANT
;
1018 ec
->read_iovec
.iod_iovec_offset
= 0;
1020 ec
->tmp_iovec
= ec
->read_iovec
;
1022 ec
->flags
|= ECF_READING
;
1026 if ((ec
->flags
& (ECF_READING
|ECF_STOPPED
)) == (ECF_READING
|ECF_STOPPED
))
1031 /*===========================================================================*
1033 *===========================================================================*/
1034 static void ec_recv(ec
)
1038 int packet_processed
;
1040 unsigned short ioaddr
= ec
->ec_port
;
1042 if ((ec
->flags
& ECF_READING
)==0)
1044 if (!(ec
->flags
& ECF_ENABLED
))
1047 /* we check all the received slots until find a properly received packet */
1048 packet_processed
= FALSE
;
1049 while (!packet_processed
)
1051 status
= lp
->rx_ring
[rx_slot_nr
].u
.base
>> 24;
1052 if ( (status
& 0x80) == 0x00 )
1054 status
= lp
->rx_ring
[rx_slot_nr
].u
.base
>> 24;
1060 ec
->eth_stat
.ets_recvErr
++;
1062 ec
->eth_stat
.ets_fifoOver
++;
1064 ec
->eth_stat
.ets_CRCerr
++;
1066 ec
->eth_stat
.ets_OVW
++;
1068 ec
->eth_stat
.ets_frameAll
++;
1073 ec
->eth_stat
.ets_packetR
++;
1074 length
= lp
->rx_ring
[rx_slot_nr
].msg_length
;
1078 ec_nic2user(ec
, (int)(lp
->rbuf
[rx_slot_nr
]),
1079 &ec
->read_iovec
, 0, length
);
1081 ec
->read_s
= length
;
1082 ec
->flags
|= ECF_PACK_RECV
;
1083 ec
->flags
&= ~ECF_READING
;
1084 packet_processed
= TRUE
;
1086 /* set up this slot again, and we move to the next slot */
1087 lp
->rx_ring
[rx_slot_nr
].buf_length
= -ETH_FRAME_LEN
;
1088 lp
->rx_ring
[rx_slot_nr
].u
.addr
[3] |= 0x80;
1090 write_csr(ioaddr
, LANCE_CSR0
,
1091 LANCE_CSR0_BABL
|LANCE_CSR0_CERR
|LANCE_CSR0_MISS
1092 |LANCE_CSR0_MERR
|LANCE_CSR0_IDON
|LANCE_CSR0_IENA
);
1094 rx_slot_nr
= (rx_slot_nr
+ 1) & RX_RING_MOD_MASK
;
1101 /*===========================================================================*
1103 *===========================================================================*/
1104 static void do_vwrite_s(mp
, from_int
)
1108 int count
, check
, r
;
1110 unsigned short ioaddr
;
1114 ec
->client
= mp
->m_source
;
1115 count
= mp
->DL_COUNT
;
1117 if (isstored
[tx_slot_nr
]==1)
1119 /* all slots are used, so this message is buffered */
1121 ec
->flags
|= ECF_SEND_AVAIL
;
1126 /* convert the message to write_iovec */
1127 r
= sys_safecopyfrom(mp
->m_source
, mp
->DL_GRANT
, 0,
1128 (vir_bytes
)ec
->write_iovec
.iod_iovec
,
1129 (count
> IOVEC_NR
? IOVEC_NR
: count
) *
1132 panic("do_vwrite_s: sys_safecopyfrom failed: %d", r
);
1133 ec
->write_iovec
.iod_iovec_s
= count
;
1134 ec
->write_iovec
.iod_proc_nr
= mp
->m_source
;
1135 ec
->write_iovec
.iod_grant
= mp
->DL_GRANT
;
1136 ec
->write_iovec
.iod_iovec_offset
= 0;
1138 ec
->tmp_iovec
= ec
->write_iovec
;
1139 ec
->write_s
= calc_iovec_size(&ec
->tmp_iovec
);
1141 /* copy write_iovec to the slot on DMA address */
1142 ec_user2nic(ec
, &ec
->write_iovec
, 0,
1143 (int)(lp
->tbuf
[tx_slot_nr
]), ec
->write_s
);
1144 /* set-up for transmitting, and transmit it if needed. */
1145 lp
->tx_ring
[tx_slot_nr
].buf_length
= -ec
->write_s
;
1146 lp
->tx_ring
[tx_slot_nr
].misc
= 0x0;
1147 lp
->tx_ring
[tx_slot_nr
].u
.base
1148 = virt_to_bus(lp
->tbuf
[tx_slot_nr
]) & 0xffffff;
1149 isstored
[tx_slot_nr
]=1;
1150 if (cur_tx_slot_nr
== tx_slot_nr
)
1154 tx_slot_nr
= (tx_slot_nr
+ 1) & TX_RING_MOD_MASK
;
1158 ioaddr
= ec
->ec_port
;
1159 lp
->tx_ring
[cur_tx_slot_nr
].u
.addr
[3] = 0x83;
1160 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_IENA
|LANCE_CSR0_TDMD
);
1163 ec
->flags
|= ECF_PACK_SEND
;
1165 /* reply by calling do_int() if this function is called from interrupt. */
1172 /*===========================================================================*
1174 *===========================================================================*/
1175 static void ec_user2nic(ec
, iovp
, offset
, nic_addr
, count
)
1189 ec_next_iovec(iovp
);
1193 if (offset
>= iovp
->iod_iovec
[i
].iov_size
)
1195 offset
-= iovp
->iod_iovec
[i
].iov_size
;
1199 bytes
= iovp
->iod_iovec
[i
].iov_size
- offset
;
1203 if ( (r
=sys_safecopyfrom(iovp
->iod_proc_nr
,
1204 iovp
->iod_iovec
[i
].iov_grant
, offset
,
1205 nic_addr
, bytes
)) != OK
)
1206 panic("ec_user2nic: sys_safecopyfrom failed: %d", r
);
1214 /*===========================================================================*
1216 *===========================================================================*/
1217 static void ec_nic2user(ec
, nic_addr
, iovp
, offset
, count
)
1231 ec_next_iovec(iovp
);
1235 if (offset
>= iovp
->iod_iovec
[i
].iov_size
)
1237 offset
-= iovp
->iod_iovec
[i
].iov_size
;
1241 bytes
= iovp
->iod_iovec
[i
].iov_size
- offset
;
1244 if ( (r
=sys_safecopyto( iovp
->iod_proc_nr
, iovp
->iod_iovec
[i
].iov_grant
,
1245 offset
, nic_addr
, bytes
)) != OK
)
1246 panic("ec_nic2user: sys_safecopyto failed: %d", r
);
1255 /*===========================================================================*
1257 *===========================================================================*/
1258 static int calc_iovec_size(iovec_dat_t
*iovp
)
1264 while (i
< iovp
->iod_iovec_s
)
1268 ec_next_iovec(iovp
);
1272 size
+= iovp
->iod_iovec
[i
].iov_size
;
1279 /*===========================================================================*
1281 *===========================================================================*/
1282 static void ec_next_iovec(iovp
)
1287 iovp
->iod_iovec_s
-= IOVEC_NR
;
1288 iovp
->iod_iovec_offset
+= IOVEC_NR
* sizeof(iovec_s_t
);
1290 r
= sys_safecopyfrom(iovp
->iod_proc_nr
, iovp
->iod_grant
,
1291 iovp
->iod_iovec_offset
,
1292 (vir_bytes
)iovp
->iod_iovec
,
1293 (iovp
->iod_iovec_s
> IOVEC_NR
?
1294 IOVEC_NR
: iovp
->iod_iovec_s
) *
1297 panic("ec_next_iovec: sys_safecopyfrom failed: %d", r
);
1301 /*===========================================================================*
1303 *===========================================================================*/
1304 static void do_getstat_s(mp
)
1312 r
= sys_safecopyto(mp
->m_source
, mp
->DL_GRANT
, 0,
1313 (vir_bytes
)&ec
->eth_stat
, sizeof(ec
->eth_stat
));
1316 panic("do_getstat_s: sys_safecopyto failed: %d", r
);
1318 mp
->m_type
= DL_STAT_REPLY
;
1319 r
= send(mp
->m_source
, mp
);
1321 panic("do_getstat_s: send failed: %d", r
);
1324 /*===========================================================================*
1326 *===========================================================================*/
1327 static void lance_stop(ec
)
1330 unsigned short ioaddr
;
1332 if (!(ec
->flags
& ECF_ENABLED
))
1335 ioaddr
= ec
->ec_port
;
1338 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
1341 in_word(ioaddr
+LANCE_RESET
);
1343 ec
->flags
= ECF_EMPTY
;
1346 /*===========================================================================*
1348 *===========================================================================*/
1349 static void getAddressing(devind
, ec
)
1353 unsigned int membase
, ioaddr
;
1356 for (reg
= PCI_BAR
; reg
<= PCI_BAR_6
; reg
+= 4)
1358 ioaddr
= pci_attr_r32(devind
, reg
);
1360 if ((ioaddr
& PCI_BAR_IO_MASK
) == 0 || (ioaddr
& PCI_BAR_IO
) == 0)
1362 /* Strip the I/O address out of the returned value */
1363 ioaddr
&= PCI_BAR_IO_MASK
;
1364 /* Get the memory base address */
1365 membase
= pci_attr_r32(devind
, PCI_BAR_2
);
1366 /* KK: Get the IRQ number */
1367 irq
= pci_attr_r8(devind
, PCI_IPR
);
1369 irq
= pci_attr_r8(devind
, PCI_ILR
);
1371 ec
->ec_linmem
= membase
;
1372 ec
->ec_port
= ioaddr
;
1377 /*===========================================================================*
1379 *===========================================================================*/
1380 static int lance_probe(ec
, skip
)
1384 unsigned short pci_cmd
;
1385 unsigned short ioaddr
;
1386 int lance_version
, chip_version
;
1390 r
= pci_first_dev(&devind
, &vid
, &did
);
1396 r
= pci_next_dev(&devind
, &vid
, &did
);
1401 pci_reserve(devind
);
1403 getAddressing(devind
, ec
);
1406 /* ===== Bus Master ? ===== */
1407 pci_cmd
= pci_attr_r32(devind
, PCI_CR
);
1408 if (!(pci_cmd
& PCI_CR_MAST_EN
)) {
1409 pci_cmd
|= PCI_CR_MAST_EN
;
1410 pci_attr_w32(devind
, PCI_CR
, pci_cmd
);
1413 /* ===== Probe Details ===== */
1414 ioaddr
= ec
->ec_port
;
1417 in_word(ioaddr
+LANCE_RESET
);
1419 if (read_csr(ioaddr
, LANCE_CSR0
) != LANCE_CSR0_STOP
)
1421 ec
->mode
=EC_DISABLED
;
1424 /* Probe Chip Version */
1425 out_word(ioaddr
+LANCE_ADDR
, 88); /* Get the version of the chip */
1426 if (in_word(ioaddr
+LANCE_ADDR
) != 88)
1430 chip_version
= read_csr(ioaddr
, LANCE_CSR88
);
1431 chip_version
|= read_csr(ioaddr
, LANCE_CSR89
) << 16;
1433 if ((chip_version
& 0xfff) != 0x3)
1435 ec
->mode
=EC_DISABLED
;
1437 chip_version
= (chip_version
>> 12) & 0xffff;
1438 for (lance_version
= 1; chip_table
[lance_version
].id_number
!= 0;
1440 if (chip_table
[lance_version
].id_number
== chip_version
)
1445 printf("%s: %s at %X:%d\n",
1446 ec
->port_name
, chip_table
[lance_version
].name
,
1447 ec
->ec_port
, ec
->ec_irq
);
1450 return lance_version
;
1453 /*===========================================================================*
1455 *===========================================================================*/
1456 static void lance_init_card(ec
)
1460 Address l
= (vir_bytes
)lance_buf
;
1461 unsigned short ioaddr
= ec
->ec_port
;
1463 /* ============= setup init_block(cf. lance_probe1) ================ */
1464 /* make sure data structure is 8-byte aligned and below 16MB (for DMA) */
1466 lp
= (struct lance_interface
*)l
;
1468 /* disable Tx and Rx */
1469 lp
->init_block
.mode
= LANCE_CSR15_DTX
|LANCE_CSR15_DRX
;
1470 lp
->init_block
.filter
[0] = lp
->init_block
.filter
[1] = 0x0;
1471 /* using multiple Rx/Tx buffer */
1472 lp
->init_block
.rx_ring
1473 = (virt_to_bus(&lp
->rx_ring
) & 0xffffff) | RX_RING_LEN_BITS
;
1474 lp
->init_block
.tx_ring
1475 = (virt_to_bus(&lp
->tx_ring
) & 0xffffff) | TX_RING_LEN_BITS
;
1477 l
= virt_to_bus(&lp
->init_block
);
1478 write_csr(ioaddr
, LANCE_CSR1
, (unsigned short)l
);
1479 write_csr(ioaddr
, LANCE_CSR2
, (unsigned short)(l
>> 16));
1480 write_csr(ioaddr
, LANCE_CSR4
,
1481 LANCE_CSR4_APAD_XMT
|LANCE_CSR4_MFCOM
|LANCE_CSR4_RCVCCOM
1482 |LANCE_CSR4_TXSTRTM
|LANCE_CSR4_JABM
);
1484 /* ============= Get MAC address (cf. lance_probe1) ================ */
1485 for (i
= 0; i
< 6; ++i
)
1486 ec
->mac_address
.ea_addr
[i
]=in_byte(ioaddr
+LANCE_ETH_ADDR
+i
);
1488 /* ============ (re)start init_block(cf. lance_reset) =============== */
1489 /* Reset the LANCE */
1490 (void)in_word(ioaddr
+LANCE_RESET
);
1492 /* ----- Re-initialize the LANCE ----- */
1493 /* Set station address */
1494 for (i
= 0; i
< 6; ++i
)
1495 lp
->init_block
.phys_addr
[i
] = ec
->mac_address
.ea_addr
[i
];
1496 /* Preset the receive ring headers */
1497 for (i
=0; i
<RX_RING_SIZE
; i
++)
1499 lp
->rx_ring
[i
].buf_length
= -ETH_FRAME_LEN
;
1501 lp
->rx_ring
[i
].u
.base
= virt_to_bus(lp
->rbuf
[i
]) & 0xffffff;
1502 /* we set the top byte as the very last thing */
1503 lp
->rx_ring
[i
].u
.addr
[3] = 0x80;
1505 /* Preset the transmitting ring headers */
1506 for (i
=0; i
<TX_RING_SIZE
; i
++)
1508 lp
->tx_ring
[i
].u
.base
= 0;
1511 /* enable Rx and Tx */
1512 lp
->init_block
.mode
= 0x0;
1514 l
= (Address
)virt_to_bus(&lp
->init_block
);
1515 write_csr(ioaddr
, LANCE_CSR1
, (short)l
);
1516 write_csr(ioaddr
, LANCE_CSR2
, (short)(l
>> 16));
1517 write_csr(ioaddr
, LANCE_CSR4
,
1518 LANCE_CSR4_APAD_XMT
|LANCE_CSR4_MFCOM
|LANCE_CSR4_RCVCCOM
1519 |LANCE_CSR4_TXSTRTM
|LANCE_CSR4_JABM
);
1521 /* ----- start when init done. ----- */
1523 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_STOP
);
1525 write_csr(ioaddr
, LANCE_CSR0
, LANCE_CSR0_INIT
);
1527 for (i
= 10000; i
> 0; --i
)
1528 if (read_csr(ioaddr
, LANCE_CSR0
) & LANCE_CSR0_IDON
)
1531 /* Set 'Multicast Table' */
1534 write_csr(ioaddr
, LANCE_CSR8
+ i
, 0xffff);
1537 /* Set 'Receive Mode' */
1538 if (ec
->flags
& ECF_PROMISC
)
1540 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_PROM
);
1544 if (ec
->flags
& (ECF_BROAD
| ECF_MULTI
))
1546 write_csr(ioaddr
, LANCE_CSR15
, 0x0000);
1550 write_csr(ioaddr
, LANCE_CSR15
, LANCE_CSR15_DRCVBC
);
1554 /* start && enable interrupt */
1555 write_csr(ioaddr
, LANCE_CSR0
,
1556 LANCE_CSR0_IDON
|LANCE_CSR0_IENA
|LANCE_CSR0_STRT
);
1561 /*===========================================================================*
1563 *===========================================================================*/
1564 static u8_t
in_byte(port_t port
)
1569 r
= sys_inb(port
, &value
);
1571 panic("sys_inb failed: %d", r
);
1575 /*===========================================================================*
1577 *===========================================================================*/
1578 static u16_t
in_word(port_t port
)
1583 r
= sys_inw(port
, &value
);
1585 panic("sys_inw failed: %d", r
);
1590 /*===========================================================================*
1592 *===========================================================================*/
1593 static void out_word(port_t port
, u16_t value
)
1597 r
= sys_outw(port
, value
);
1599 panic("sys_outw failed: %d", r
);
1602 /*===========================================================================*
1604 *===========================================================================*/
1605 static u16_t
read_csr(port_t ioaddr
, u16_t csrno
)
1607 out_word(ioaddr
+LANCE_ADDR
, csrno
);
1608 return in_word(ioaddr
+LANCE_DATA
);
1611 /*===========================================================================*
1613 *===========================================================================*/
1614 static void write_csr(port_t ioaddr
, u16_t csrno
, u16_t value
)
1616 out_word(ioaddr
+LANCE_ADDR
, csrno
);
1617 out_word(ioaddr
+LANCE_DATA
, value
);