new libunwind, updated to netbsd b1f513eedd
[minix3.git] / drivers / lance / lance.c
blobcf86f9d9e92c91570b02f13b52f524377f066159
1 /*
2 * lance.c
4 * This file contains a ethernet device driver for AMD LANCE based ethernet
5 * cards.
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 * |---------------|----------|---------|
29 * m_type
30 * |---------------|
31 * | DL_STAT_REPLY |
32 * |---------------|
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>
49 #include <net/hton.h>
50 #include <net/gen/ether.h>
51 #include <net/gen/eth_io.h>
52 #include <assert.h>
54 #include <minix/syslib.h>
55 #include <minix/endpoint.h>
56 #include <machine/pci.h>
57 #include <minix/ds.h>
59 #include "lance.h"
61 static ether_card_t ec_state;
62 static int ec_instance;
64 /* Configuration */
65 typedef struct ec_conf
67 port_t ec_port;
68 int ec_irq;
69 phys_bytes ec_mem;
70 } ec_conf_t;
72 /* We hardly use these. Just "LANCE0=on/off" "LANCE1=on/off" mean. */
73 #define EC_CONF_NR 3
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, },
82 /* General */
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);
121 /* --- LANCE --- */
122 /* General */
123 typedef unsigned long Address;
125 #define virt_to_bus(x) (vir2phys((unsigned long)x))
126 unsigned long vir2phys( unsigned long x )
128 int r;
129 unsigned long value;
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);
136 return value;
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
153 int id_number;
154 const char *name;
155 int flags;
156 } chip_table[] = {
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
199 unsigned short mode;
200 unsigned char phys_addr[6];
201 unsigned long filter[2];
202 Address rx_ring;
203 Address tx_ring;
206 struct lance_rx_head
208 union {
209 Address base;
210 unsigned char addr[4];
211 } u;
212 short buf_length; /* 2s complement */
213 short msg_length;
216 struct lance_tx_head
218 union {
219 Address base;
220 unsigned char addr[4];
221 } u;
222 short buf_length; /* 2s complement */
223 short misc;
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 /*===========================================================================*
253 * main *
254 *===========================================================================*/
255 int main( int argc, char **argv )
257 message m;
258 int ipc_status;
259 int r;
260 ether_card_t *ec;
262 /* SEF local startup. */
263 env_setargs(argc, argv);
264 sef_local_startup();
266 ec= &ec_state;
268 while (TRUE)
270 if (ec->ec_irq != 0)
271 sys_irqenable(&ec->ec_hook);
273 if ((r= netdriver_receive(ANY, &m, &ipc_status)) != OK)
274 panic("netdriver_receive failed: %d", r);
276 if (ec->ec_irq != 0)
277 sys_irqdisable(&ec->ec_hook);
279 if (is_ipc_notify(ipc_status)) {
280 switch(_ENDPOINT_P(m.m_source)) {
281 case TTY_PROC_NR:
282 lance_dump();
283 break;
284 case HARDWARE:
285 if (ec->mode == EC_ENABLED)
287 ec->ec_int_pending = 0;
288 ec_check_ints(ec);
289 do_int(ec);
291 break;
292 default:
293 panic("illegal notify source: %d", m.m_source);
296 /* get next message */
297 continue;
300 switch (m.m_type)
302 case DL_WRITEV_S:
303 do_vwrite_s(&m, FALSE);
304 break;
305 case DL_READV_S:
306 do_vread_s(&m);
307 break;
308 case DL_CONF:
309 do_init(&m);
310 break;
311 case DL_GETSTAT_S:
312 do_getstat_s(&m);
313 break;
314 default:
315 panic("illegal message: %d", m.m_type);
319 return 0;
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. */
340 sef_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. */
349 long v;
350 #if LANCE_FKEY
351 int r, fkeys, sfkeys;
352 #endif
354 #if LANCE_FKEY
355 fkeys = sfkeys = 0;
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);
359 #endif
361 v = 0;
362 (void) env_parse("instance", "d", 0, &v, 0, 255);
363 ec_instance = (int) v;
365 /* Announce we are up! */
366 netdriver_announce();
368 return OK;
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);
383 #if VERBOSE
384 printf("LANCE driver stopped.\n");
385 #endif
387 exit(0);
390 /*===========================================================================*
391 * lance_dump *
392 *===========================================================================*/
393 static void lance_dump()
395 ether_card_t *ec;
396 int isr, csr;
397 unsigned short ioaddr;
399 printf("\n");
400 ec = &ec_state;
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)
407 return;
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,
436 ec->flags);
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 /*===========================================================================*
453 * do_init *
454 *===========================================================================*/
455 static void do_init(mp)
456 message *mp;
458 ether_card_t *ec;
459 message reply_mess;
461 pci_init();
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);
467 ec= &ec_state;
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() )
477 conf_hw(ec);
479 else
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);
490 return;
492 if (ec->mode == EC_ENABLED)
493 ec_init(ec);
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;
504 ec_confaddr(ec);
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);
510 return;
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;
524 ec_reinit(ec);
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 /*===========================================================================*
536 * do_int *
537 *===========================================================================*/
538 static void do_int(ec)
539 ether_card_t *ec;
541 if (ec->flags & (ECF_PACK_SEND | ECF_PACK_RECV))
542 reply(ec);
546 /*===========================================================================*
547 * conf_hw *
548 *===========================================================================*/
549 static void conf_hw(ec)
550 ether_card_t *ec;
552 static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ };
554 int confnr;
555 ec_conf_t *ecp;
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)
565 return;
567 if (!lance_probe(ec, ec_instance))
569 printf("%s: No ethernet card found on PCI-BIOS info.\n",
570 ec->port_name);
571 ec->mode= EC_DISABLED;
572 return;
575 /* XXX */ if (ec->ec_linmem == 0) ec->ec_linmem= 0xFFFF0000;
577 ec->flags = ECF_EMPTY;
578 ec->eth_stat = empty_stat;
582 /*===========================================================================*
583 * update_conf *
584 *===========================================================================*/
585 static void update_conf(ec, ecp)
586 ether_card_t *ec;
587 ec_conf_t *ecp;
589 long v;
590 char eckey[16];
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;
596 ec->mode= EC_SINK;
597 v= ecp->ec_port;
598 switch (env_parse(eckey, ec_fmt, 0, &v, 0x0000L, 0xFFFFL))
600 case EP_OFF:
601 ec->mode= EC_DISABLED;
602 break;
603 case EP_ON:
604 case EP_SET:
605 default:
606 ec->mode= EC_ENABLED; /* Might become disabled if
607 * all probes fail */
608 break;
611 ec->ec_port= v;
613 v= ecp->ec_irq | DEI_DEFAULT;
614 (void) env_parse(eckey, ec_fmt, 1, &v, 0L, (long) NR_IRQ_VECTORS - 1);
615 ec->ec_irq= v;
617 v= ecp->ec_mem;
618 (void) env_parse(eckey, ec_fmt, 2, &v, 0L, 0xFFFFFL);
619 ec->ec_linmem= v;
621 v= 0;
622 (void) env_parse(eckey, ec_fmt, 3, &v, 0x2000L, 0x8000L);
623 ec->ec_ramsize= v;
627 /*===========================================================================*
628 * ec_init *
629 *===========================================================================*/
630 static void ec_init(ec)
631 ether_card_t *ec;
633 int r;
634 #if VERBOSE
635 int i;
636 #endif
638 /* General initialization */
639 ec->flags = ECF_EMPTY;
640 lance_init_card(ec); /* Get mac_address, etc ...*/
642 ec_confaddr(ec);
644 #if VERBOSE
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],
648 i < 5 ? ':' : '\n');
649 #endif
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);
659 return;
663 /*===========================================================================*
664 * reply *
665 *===========================================================================*/
666 static void reply(ec)
667 ether_card_t *ec;
669 message reply;
670 int flags,r;
672 flags = DL_NOFLAGS;
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);
683 if (r < 0)
684 panic("ipc_send failed: %d", r);
686 ec->read_s = 0;
687 ec->flags &= ~(ECF_PACK_SEND | ECF_PACK_RECV);
691 /*===========================================================================*
692 * mess_reply *
693 *===========================================================================*/
694 static void mess_reply(req, reply_mess)
695 message *req;
696 message *reply_mess;
698 if (ipc_send(req->m_source, reply_mess) != OK)
699 panic("unable to mess_reply");
703 /*===========================================================================*
704 * ec_confaddr *
705 *===========================================================================*/
706 static void ec_confaddr(ec)
707 ether_card_t *ec;
709 int i;
710 char eakey[16];
711 static char eafmt[]= "x:x:x:x:x:x";
712 long v;
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)
722 break;
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 /*===========================================================================*
735 * ec_reinit *
736 *===========================================================================*/
737 static void ec_reinit(ec)
738 ether_card_t *ec;
740 int i;
741 unsigned short ioaddr = ec->ec_port;
743 /* stop */
744 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
746 /* purge Tx-ring */
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;
751 isstored[i]=0;
754 /* re-init Rx-ring */
755 rx_slot_nr = 0;
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);
767 else
769 if (ec->flags & (ECF_BROAD | ECF_MULTI))
771 write_csr(ioaddr, LANCE_CSR15, 0x0000);
773 else
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);
783 return;
786 /*===========================================================================*
787 * ec_check_ints *
788 *===========================================================================*/
789 static void ec_check_ints(ec)
790 ether_card_t *ec;
792 int must_restart = 0;
793 int check,status;
794 int isr = 0x0000;
795 unsigned short ioaddr = ec->ec_port;
797 if (!(ec->flags & ECF_ENABLED))
798 panic("got premature interrupt");
800 for (;;)
802 #if VERBOSE
803 printf("ETH: Reading ISR...");
804 #endif
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)
820 #if VERBOSE
821 printf("OK\n");
822 #endif
823 break;
826 if (isr & LANCE_CSR0_MISS)
828 #if VERBOSE
829 printf("RX Missed Frame\n");
830 #endif
831 ec->eth_stat.ets_recvErr++;
833 if ((isr & LANCE_CSR0_BABL) || (isr & LANCE_CSR0_TINT))
835 if (isr & LANCE_CSR0_BABL)
837 #if VERBOSE
838 printf("TX Timeout\n");
839 #endif
840 ec->eth_stat.ets_sendErr++;
842 if (isr & LANCE_CSR0_TINT)
844 #if VERBOSE
845 printf("TX INT\n");
846 #endif
847 /* status check: restart if needed. */
848 status = lp->tx_ring[cur_tx_slot_nr].u.base;
850 /* ??? */
851 if (status & 0x40000000)
853 status = lp->tx_ring[cur_tx_slot_nr].misc;
854 ec->eth_stat.ets_sendErr++;
855 if (status & 0x0400)
856 ec->eth_stat.ets_transAb++;
857 if (status & 0x0800)
858 ec->eth_stat.ets_carrSense++;
859 if (status & 0x1000)
860 ec->eth_stat.ets_OWC++;
861 if (status & 0x4000)
863 ec->eth_stat.ets_fifoUnder++;
864 must_restart=1;
867 else
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. */
875 check = 0;
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)
884 check=1;
885 else
886 check=0;
888 else
890 panic("got premature TX INT..");
892 if (check==1)
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)
900 ec_send(ec);
902 if (isr & LANCE_CSR0_RINT)
904 #if VERBOSE
905 printf("RX INT\n");
906 #endif
907 ec_recv(ec);
910 if (isr & ISR_RST)
912 ec->flags = ECF_STOPPED;
913 #if VERBOSE
914 printf("ISR_RST\n");
915 #endif
916 break;
919 /* ??? cf. lance driver on linux */
920 if (must_restart == 1)
922 #if VERBOSE
923 printf("ETH: restarting...\n");
924 #endif
925 /* stop */
926 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
927 /* start */
928 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STRT);
932 if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))
934 #if VERBOSE
935 printf("ETH: resetting...\n");
936 #endif
937 ec_reset(ec);
941 /*===========================================================================*
942 * ec_reset *
943 *===========================================================================*/
944 static void ec_reset(ec)
945 ether_card_t *ec;
947 /* Stop/start the chip, and clear all RX,TX-slots */
948 unsigned short ioaddr = ec->ec_port;
949 int i;
951 /* stop */
952 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
953 /* start */
954 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STRT);
956 /* purge Tx-ring */
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;
961 isstored[i]=0;
964 /* re-init Rx-ring */
965 rx_slot_nr = 0;
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 */
973 ec_send(ec);
974 ec->flags &= ~ECF_STOPPED;
977 /*===========================================================================*
978 * ec_send *
979 *===========================================================================*/
980 static void ec_send(ec)
981 ether_card_t *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))
986 return;
988 ec->flags &= ~ECF_SEND_AVAIL;
989 switch(ec->sendmsg.m_type)
991 case DL_WRITEV_S: do_vwrite_s(&ec->sendmsg, TRUE); break;
992 default:
993 panic("wrong type: %d", ec->sendmsg.m_type);
994 break;
998 /*===========================================================================*
999 * do_vread_s *
1000 *===========================================================================*/
1001 static void do_vread_s(const message *mp)
1003 int count, r;
1004 ether_card_t *ec;
1006 ec= &ec_state;
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) *
1014 sizeof(iovec_s_t));
1015 if (r != OK)
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;
1026 ec_recv(ec);
1028 if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))
1029 ec_reset(ec);
1030 reply(ec);
1033 /*===========================================================================*
1034 * ec_recv *
1035 *===========================================================================*/
1036 static void ec_recv(ec)
1037 ether_card_t *ec;
1039 vir_bytes length;
1040 int packet_processed;
1041 int status;
1042 unsigned short ioaddr = ec->ec_port;
1044 if ((ec->flags & ECF_READING)==0)
1045 return;
1046 if (!(ec->flags & ECF_ENABLED))
1047 return;
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;
1058 /* ??? */
1059 if (status != 0x03)
1061 if (status & 0x01)
1062 ec->eth_stat.ets_recvErr++;
1063 if (status & 0x04)
1064 ec->eth_stat.ets_fifoOver++;
1065 if (status & 0x08)
1066 ec->eth_stat.ets_CRCerr++;
1067 if (status & 0x10)
1068 ec->eth_stat.ets_OVW++;
1069 if (status & 0x20)
1070 ec->eth_stat.ets_frameAll++;
1071 length = 0;
1073 else
1075 ec->eth_stat.ets_packetR++;
1076 length = lp->rx_ring[rx_slot_nr].msg_length;
1078 if (length > 0)
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;
1098 else
1099 break;
1103 /*===========================================================================*
1104 * do_vwrite_s *
1105 *===========================================================================*/
1106 static void do_vwrite_s(mp, from_int)
1107 message *mp;
1108 int from_int;
1110 int count, check, r;
1111 ether_card_t *ec;
1112 unsigned short ioaddr;
1114 ec = &ec_state;
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 */
1122 ec->sendmsg= *mp;
1123 ec->flags |= ECF_SEND_AVAIL;
1124 reply(ec);
1125 return;
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) *
1132 sizeof(iovec_s_t));
1133 if (r != OK)
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)
1153 check=1;
1154 else
1155 check=0;
1156 tx_slot_nr = (tx_slot_nr + 1) & TX_RING_MOD_MASK;
1158 if (check == 1)
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. */
1168 if (from_int)
1169 return;
1170 reply(ec);
1174 /*===========================================================================*
1175 * ec_user2nic *
1176 *===========================================================================*/
1177 static void ec_user2nic(ec, iovp, offset, nic_addr, count)
1178 ether_card_t *ec;
1179 iovec_dat_t *iovp;
1180 vir_bytes offset;
1181 int nic_addr;
1182 vir_bytes count;
1184 int bytes, i, r;
1186 i= 0;
1187 while (count > 0)
1189 if (i >= IOVEC_NR)
1191 ec_next_iovec(iovp);
1192 i= 0;
1193 continue;
1195 if (offset >= iovp->iod_iovec[i].iov_size)
1197 offset -= iovp->iod_iovec[i].iov_size;
1198 i++;
1199 continue;
1201 bytes = iovp->iod_iovec[i].iov_size - offset;
1202 if (bytes > count)
1203 bytes = count;
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);
1210 count -= bytes;
1211 nic_addr += bytes;
1212 offset += bytes;
1216 /*===========================================================================*
1217 * ec_nic2user *
1218 *===========================================================================*/
1219 static void ec_nic2user(ec, nic_addr, iovp, offset, count)
1220 ether_card_t *ec;
1221 int nic_addr;
1222 iovec_dat_t *iovp;
1223 vir_bytes offset;
1224 vir_bytes count;
1226 int bytes, i, r;
1228 i= 0;
1229 while (count > 0)
1231 if (i >= IOVEC_NR)
1233 ec_next_iovec(iovp);
1234 i= 0;
1235 continue;
1237 if (offset >= iovp->iod_iovec[i].iov_size)
1239 offset -= iovp->iod_iovec[i].iov_size;
1240 i++;
1241 continue;
1243 bytes = iovp->iod_iovec[i].iov_size - offset;
1244 if (bytes > count)
1245 bytes = count;
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);
1250 count -= bytes;
1251 nic_addr += bytes;
1252 offset += bytes;
1257 /*===========================================================================*
1258 * calc_iovec_size *
1259 *===========================================================================*/
1260 static int calc_iovec_size(iovec_dat_t *iovp)
1262 int size,i;
1264 size = i = 0;
1266 while (i < iovp->iod_iovec_s)
1268 if (i >= IOVEC_NR)
1270 ec_next_iovec(iovp);
1271 i= 0;
1272 continue;
1274 size += iovp->iod_iovec[i].iov_size;
1275 i++;
1278 return size;
1281 /*===========================================================================*
1282 * ec_next_iovec *
1283 *===========================================================================*/
1284 static void ec_next_iovec(iovp)
1285 iovec_dat_t *iovp;
1287 int r;
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) *
1297 sizeof(iovec_s_t));
1298 if (r != OK)
1299 panic("ec_next_iovec: sys_safecopyfrom failed: %d", r);
1303 /*===========================================================================*
1304 * do_getstat_s *
1305 *===========================================================================*/
1306 static void do_getstat_s(mp)
1307 message *mp;
1309 int r;
1310 ether_card_t *ec;
1312 ec= &ec_state;
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));
1317 if (r != OK)
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);
1322 if (r != OK)
1323 panic("do_getstat_s: send failed: %d", r);
1326 /*===========================================================================*
1327 * lance_stop *
1328 *===========================================================================*/
1329 static void lance_stop(ec)
1330 ether_card_t *ec;
1332 unsigned short ioaddr;
1334 if (!(ec->flags & ECF_ENABLED))
1335 return;
1337 ioaddr = ec->ec_port;
1339 /* stop */
1340 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
1342 /* Reset */
1343 in_word(ioaddr+LANCE_RESET);
1345 ec->flags = ECF_EMPTY;
1348 /*===========================================================================*
1349 * getAddressing *
1350 *===========================================================================*/
1351 static void getAddressing(devind, ec)
1352 int devind;
1353 ether_card_t *ec;
1355 unsigned int membase, ioaddr;
1356 int reg, irq;
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)
1363 continue;
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);
1370 if (irq)
1371 irq = pci_attr_r8(devind, PCI_ILR);
1373 ec->ec_linmem = membase;
1374 ec->ec_port = ioaddr;
1375 ec->ec_irq = irq;
1379 /*===========================================================================*
1380 * lance_probe *
1381 *===========================================================================*/
1382 static int lance_probe(ec, skip)
1383 ether_card_t *ec;
1384 int skip;
1386 unsigned short pci_cmd;
1387 unsigned short ioaddr;
1388 int lance_version, chip_version;
1389 int devind, r;
1390 u16_t vid, did;
1392 r= pci_first_dev(&devind, &vid, &did);
1393 if (r == 0)
1394 return 0;
1396 while (skip--)
1398 r= pci_next_dev(&devind, &vid, &did);
1399 if (!r)
1400 return 0;
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;
1418 /* Reset */
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)
1429 lance_version = 0;
1430 else
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;
1441 ++lance_version)
1442 if (chip_table[lance_version].id_number == chip_version)
1443 break;
1446 #if VERBOSE
1447 printf("%s: %s at %X:%d\n",
1448 ec->port_name, chip_table[lance_version].name,
1449 ec->ec_port, ec->ec_irq);
1450 #endif
1452 return lance_version;
1455 /*===========================================================================*
1456 * lance_init_card *
1457 *===========================================================================*/
1458 static void lance_init_card(ec)
1459 ether_card_t *ec;
1461 int i;
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;
1502 /* OWN */
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;
1511 isstored[i] = 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. ----- */
1524 /* stop */
1525 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
1526 /* init */
1527 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_INIT);
1528 /* poll for IDON */
1529 for (i = 10000; i > 0; --i)
1530 if (read_csr(ioaddr, LANCE_CSR0) & LANCE_CSR0_IDON)
1531 break;
1533 /* Set 'Multicast Table' */
1534 for (i=0;i<4;++i)
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);
1544 else
1546 if (ec->flags & (ECF_BROAD | ECF_MULTI))
1548 write_csr(ioaddr, LANCE_CSR15, 0x0000);
1550 else
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);
1560 return;
1563 /*===========================================================================*
1564 * in_byte *
1565 *===========================================================================*/
1566 static u8_t in_byte(port_t port)
1568 int r;
1569 u32_t value;
1571 r= sys_inb(port, &value);
1572 if (r != OK)
1573 panic("sys_inb failed: %d", r);
1574 return value;
1577 /*===========================================================================*
1578 * in_word *
1579 *===========================================================================*/
1580 static u16_t in_word(port_t port)
1582 int r;
1583 u32_t value;
1585 r= sys_inw(port, &value);
1586 if (r != OK)
1587 panic("sys_inw failed: %d", r);
1588 return value;
1592 /*===========================================================================*
1593 * out_word *
1594 *===========================================================================*/
1595 static void out_word(port_t port, u16_t value)
1597 int r;
1599 r= sys_outw(port, value);
1600 if (r != OK)
1601 panic("sys_outw failed: %d", r);
1604 /*===========================================================================*
1605 * read_csr *
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 /*===========================================================================*
1614 * write_csr *
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);