kernel: fix sanity check
[minix.git] / drivers / lance / lance.c
blob5a9729d5ecbb847fc11b731f355c2412817abfd8
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.DL_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.DL_STAT = OK;
507 *(ether_addr_t *) reply_mess.DL_HWADDR = ec->mac_address;
508 mess_reply(mp, &reply_mess);
509 return;
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;
523 ec_reinit(ec);
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 /*===========================================================================*
534 * do_int *
535 *===========================================================================*/
536 static void do_int(ec)
537 ether_card_t *ec;
539 if (ec->flags & (ECF_PACK_SEND | ECF_PACK_RECV))
540 reply(ec);
544 /*===========================================================================*
545 * conf_hw *
546 *===========================================================================*/
547 static void conf_hw(ec)
548 ether_card_t *ec;
550 static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ };
552 int confnr;
553 ec_conf_t *ecp;
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)
563 return;
565 if (!lance_probe(ec, ec_instance))
567 printf("%s: No ethernet card found on PCI-BIOS info.\n",
568 ec->port_name);
569 ec->mode= EC_DISABLED;
570 return;
573 /* XXX */ if (ec->ec_linmem == 0) ec->ec_linmem= 0xFFFF0000;
575 ec->flags = ECF_EMPTY;
576 ec->eth_stat = empty_stat;
580 /*===========================================================================*
581 * update_conf *
582 *===========================================================================*/
583 static void update_conf(ec, ecp)
584 ether_card_t *ec;
585 ec_conf_t *ecp;
587 long v;
588 char eckey[16];
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;
594 ec->mode= EC_SINK;
595 v= ecp->ec_port;
596 switch (env_parse(eckey, ec_fmt, 0, &v, 0x0000L, 0xFFFFL))
598 case EP_OFF:
599 ec->mode= EC_DISABLED;
600 break;
601 case EP_ON:
602 case EP_SET:
603 default:
604 ec->mode= EC_ENABLED; /* Might become disabled if
605 * all probes fail */
606 break;
609 ec->ec_port= v;
611 v= ecp->ec_irq | DEI_DEFAULT;
612 (void) env_parse(eckey, ec_fmt, 1, &v, 0L, (long) NR_IRQ_VECTORS - 1);
613 ec->ec_irq= v;
615 v= ecp->ec_mem;
616 (void) env_parse(eckey, ec_fmt, 2, &v, 0L, 0xFFFFFL);
617 ec->ec_linmem= v;
619 v= 0;
620 (void) env_parse(eckey, ec_fmt, 3, &v, 0x2000L, 0x8000L);
621 ec->ec_ramsize= v;
625 /*===========================================================================*
626 * ec_init *
627 *===========================================================================*/
628 static void ec_init(ec)
629 ether_card_t *ec;
631 int r;
632 #if VERBOSE
633 int i;
634 #endif
636 /* General initialization */
637 ec->flags = ECF_EMPTY;
638 lance_init_card(ec); /* Get mac_address, etc ...*/
640 ec_confaddr(ec);
642 #if VERBOSE
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],
646 i < 5 ? ':' : '\n');
647 #endif
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);
657 return;
661 /*===========================================================================*
662 * reply *
663 *===========================================================================*/
664 static void reply(ec)
665 ether_card_t *ec;
667 message reply;
668 int flags,r;
670 flags = DL_NOFLAGS;
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);
681 if (r < 0)
682 panic("send failed: %d", r);
684 ec->read_s = 0;
685 ec->flags &= ~(ECF_PACK_SEND | ECF_PACK_RECV);
689 /*===========================================================================*
690 * mess_reply *
691 *===========================================================================*/
692 static void mess_reply(req, reply_mess)
693 message *req;
694 message *reply_mess;
696 if (send(req->m_source, reply_mess) != OK)
697 panic("unable to mess_reply");
701 /*===========================================================================*
702 * ec_confaddr *
703 *===========================================================================*/
704 static void ec_confaddr(ec)
705 ether_card_t *ec;
707 int i;
708 char eakey[16];
709 static char eafmt[]= "x:x:x:x:x:x";
710 long v;
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)
720 break;
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 /*===========================================================================*
733 * ec_reinit *
734 *===========================================================================*/
735 static void ec_reinit(ec)
736 ether_card_t *ec;
738 int i;
739 unsigned short ioaddr = ec->ec_port;
741 /* stop */
742 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
744 /* purge Tx-ring */
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;
749 isstored[i]=0;
752 /* re-init Rx-ring */
753 rx_slot_nr = 0;
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);
765 else
767 if (ec->flags & (ECF_BROAD | ECF_MULTI))
769 write_csr(ioaddr, LANCE_CSR15, 0x0000);
771 else
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);
781 return;
784 /*===========================================================================*
785 * ec_check_ints *
786 *===========================================================================*/
787 static void ec_check_ints(ec)
788 ether_card_t *ec;
790 int must_restart = 0;
791 int check,status;
792 int isr = 0x0000;
793 unsigned short ioaddr = ec->ec_port;
795 if (!(ec->flags & ECF_ENABLED))
796 panic("got premature interrupt");
798 for (;;)
800 #if VERBOSE
801 printf("ETH: Reading ISR...");
802 #endif
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)
818 #if VERBOSE
819 printf("OK\n");
820 #endif
821 break;
824 if (isr & LANCE_CSR0_MISS)
826 #if VERBOSE
827 printf("RX Missed Frame\n");
828 #endif
829 ec->eth_stat.ets_recvErr++;
831 if ((isr & LANCE_CSR0_BABL) || (isr & LANCE_CSR0_TINT))
833 if (isr & LANCE_CSR0_BABL)
835 #if VERBOSE
836 printf("TX Timeout\n");
837 #endif
838 ec->eth_stat.ets_sendErr++;
840 if (isr & LANCE_CSR0_TINT)
842 #if VERBOSE
843 printf("TX INT\n");
844 #endif
845 /* status check: restart if needed. */
846 status = lp->tx_ring[cur_tx_slot_nr].u.base;
848 /* ??? */
849 if (status & 0x40000000)
851 status = lp->tx_ring[cur_tx_slot_nr].misc;
852 ec->eth_stat.ets_sendErr++;
853 if (status & 0x0400)
854 ec->eth_stat.ets_transAb++;
855 if (status & 0x0800)
856 ec->eth_stat.ets_carrSense++;
857 if (status & 0x1000)
858 ec->eth_stat.ets_OWC++;
859 if (status & 0x4000)
861 ec->eth_stat.ets_fifoUnder++;
862 must_restart=1;
865 else
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. */
873 check = 0;
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)
882 check=1;
883 else
884 check=0;
886 else
888 panic("got premature TX INT..");
890 if (check==1)
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)
898 ec_send(ec);
900 if (isr & LANCE_CSR0_RINT)
902 #if VERBOSE
903 printf("RX INT\n");
904 #endif
905 ec_recv(ec);
908 if (isr & ISR_RST)
910 ec->flags = ECF_STOPPED;
911 #if VERBOSE
912 printf("ISR_RST\n");
913 #endif
914 break;
917 /* ??? cf. lance driver on linux */
918 if (must_restart == 1)
920 #if VERBOSE
921 printf("ETH: restarting...\n");
922 #endif
923 /* stop */
924 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
925 /* start */
926 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STRT);
930 if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))
932 #if VERBOSE
933 printf("ETH: resetting...\n");
934 #endif
935 ec_reset(ec);
939 /*===========================================================================*
940 * ec_reset *
941 *===========================================================================*/
942 static void ec_reset(ec)
943 ether_card_t *ec;
945 /* Stop/start the chip, and clear all RX,TX-slots */
946 unsigned short ioaddr = ec->ec_port;
947 int i;
949 /* stop */
950 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
951 /* start */
952 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STRT);
954 /* purge Tx-ring */
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;
959 isstored[i]=0;
962 /* re-init Rx-ring */
963 rx_slot_nr = 0;
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 */
971 ec_send(ec);
972 ec->flags &= ~ECF_STOPPED;
975 /*===========================================================================*
976 * ec_send *
977 *===========================================================================*/
978 static void ec_send(ec)
979 ether_card_t *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))
984 return;
986 ec->flags &= ~ECF_SEND_AVAIL;
987 switch(ec->sendmsg.m_type)
989 case DL_WRITEV_S: do_vwrite_s(&ec->sendmsg, TRUE); break;
990 default:
991 panic("wrong type: %d", ec->sendmsg.m_type);
992 break;
996 /*===========================================================================*
997 * do_vread_s *
998 *===========================================================================*/
999 static void do_vread_s(const message *mp)
1001 int count, r;
1002 ether_card_t *ec;
1004 ec= &ec_state;
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) *
1012 sizeof(iovec_s_t));
1013 if (r != OK)
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;
1024 ec_recv(ec);
1026 if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))
1027 ec_reset(ec);
1028 reply(ec);
1031 /*===========================================================================*
1032 * ec_recv *
1033 *===========================================================================*/
1034 static void ec_recv(ec)
1035 ether_card_t *ec;
1037 vir_bytes length;
1038 int packet_processed;
1039 int status;
1040 unsigned short ioaddr = ec->ec_port;
1042 if ((ec->flags & ECF_READING)==0)
1043 return;
1044 if (!(ec->flags & ECF_ENABLED))
1045 return;
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;
1056 /* ??? */
1057 if (status != 0x03)
1059 if (status & 0x01)
1060 ec->eth_stat.ets_recvErr++;
1061 if (status & 0x04)
1062 ec->eth_stat.ets_fifoOver++;
1063 if (status & 0x08)
1064 ec->eth_stat.ets_CRCerr++;
1065 if (status & 0x10)
1066 ec->eth_stat.ets_OVW++;
1067 if (status & 0x20)
1068 ec->eth_stat.ets_frameAll++;
1069 length = 0;
1071 else
1073 ec->eth_stat.ets_packetR++;
1074 length = lp->rx_ring[rx_slot_nr].msg_length;
1076 if (length > 0)
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;
1096 else
1097 break;
1101 /*===========================================================================*
1102 * do_vwrite_s *
1103 *===========================================================================*/
1104 static void do_vwrite_s(mp, from_int)
1105 message *mp;
1106 int from_int;
1108 int count, check, r;
1109 ether_card_t *ec;
1110 unsigned short ioaddr;
1112 ec = &ec_state;
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 */
1120 ec->sendmsg= *mp;
1121 ec->flags |= ECF_SEND_AVAIL;
1122 reply(ec);
1123 return;
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) *
1130 sizeof(iovec_s_t));
1131 if (r != OK)
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)
1151 check=1;
1152 else
1153 check=0;
1154 tx_slot_nr = (tx_slot_nr + 1) & TX_RING_MOD_MASK;
1156 if (check == 1)
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. */
1166 if (from_int)
1167 return;
1168 reply(ec);
1172 /*===========================================================================*
1173 * ec_user2nic *
1174 *===========================================================================*/
1175 static void ec_user2nic(ec, iovp, offset, nic_addr, count)
1176 ether_card_t *ec;
1177 iovec_dat_t *iovp;
1178 vir_bytes offset;
1179 int nic_addr;
1180 vir_bytes count;
1182 int bytes, i, r;
1184 i= 0;
1185 while (count > 0)
1187 if (i >= IOVEC_NR)
1189 ec_next_iovec(iovp);
1190 i= 0;
1191 continue;
1193 if (offset >= iovp->iod_iovec[i].iov_size)
1195 offset -= iovp->iod_iovec[i].iov_size;
1196 i++;
1197 continue;
1199 bytes = iovp->iod_iovec[i].iov_size - offset;
1200 if (bytes > count)
1201 bytes = count;
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);
1208 count -= bytes;
1209 nic_addr += bytes;
1210 offset += bytes;
1214 /*===========================================================================*
1215 * ec_nic2user *
1216 *===========================================================================*/
1217 static void ec_nic2user(ec, nic_addr, iovp, offset, count)
1218 ether_card_t *ec;
1219 int nic_addr;
1220 iovec_dat_t *iovp;
1221 vir_bytes offset;
1222 vir_bytes count;
1224 int bytes, i, r;
1226 i= 0;
1227 while (count > 0)
1229 if (i >= IOVEC_NR)
1231 ec_next_iovec(iovp);
1232 i= 0;
1233 continue;
1235 if (offset >= iovp->iod_iovec[i].iov_size)
1237 offset -= iovp->iod_iovec[i].iov_size;
1238 i++;
1239 continue;
1241 bytes = iovp->iod_iovec[i].iov_size - offset;
1242 if (bytes > count)
1243 bytes = count;
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);
1248 count -= bytes;
1249 nic_addr += bytes;
1250 offset += bytes;
1255 /*===========================================================================*
1256 * calc_iovec_size *
1257 *===========================================================================*/
1258 static int calc_iovec_size(iovec_dat_t *iovp)
1260 int size,i;
1262 size = i = 0;
1264 while (i < iovp->iod_iovec_s)
1266 if (i >= IOVEC_NR)
1268 ec_next_iovec(iovp);
1269 i= 0;
1270 continue;
1272 size += iovp->iod_iovec[i].iov_size;
1273 i++;
1276 return size;
1279 /*===========================================================================*
1280 * ec_next_iovec *
1281 *===========================================================================*/
1282 static void ec_next_iovec(iovp)
1283 iovec_dat_t *iovp;
1285 int r;
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) *
1295 sizeof(iovec_s_t));
1296 if (r != OK)
1297 panic("ec_next_iovec: sys_safecopyfrom failed: %d", r);
1301 /*===========================================================================*
1302 * do_getstat_s *
1303 *===========================================================================*/
1304 static void do_getstat_s(mp)
1305 message *mp;
1307 int r;
1308 ether_card_t *ec;
1310 ec= &ec_state;
1312 r = sys_safecopyto(mp->m_source, mp->DL_GRANT, 0,
1313 (vir_bytes)&ec->eth_stat, sizeof(ec->eth_stat));
1315 if (r != OK)
1316 panic("do_getstat_s: sys_safecopyto failed: %d", r);
1318 mp->m_type= DL_STAT_REPLY;
1319 r= send(mp->m_source, mp);
1320 if (r != OK)
1321 panic("do_getstat_s: send failed: %d", r);
1324 /*===========================================================================*
1325 * lance_stop *
1326 *===========================================================================*/
1327 static void lance_stop(ec)
1328 ether_card_t *ec;
1330 unsigned short ioaddr;
1332 if (!(ec->flags & ECF_ENABLED))
1333 return;
1335 ioaddr = ec->ec_port;
1337 /* stop */
1338 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
1340 /* Reset */
1341 in_word(ioaddr+LANCE_RESET);
1343 ec->flags = ECF_EMPTY;
1346 /*===========================================================================*
1347 * getAddressing *
1348 *===========================================================================*/
1349 static void getAddressing(devind, ec)
1350 int devind;
1351 ether_card_t *ec;
1353 unsigned int membase, ioaddr;
1354 int reg, irq;
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)
1361 continue;
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);
1368 if (irq)
1369 irq = pci_attr_r8(devind, PCI_ILR);
1371 ec->ec_linmem = membase;
1372 ec->ec_port = ioaddr;
1373 ec->ec_irq = irq;
1377 /*===========================================================================*
1378 * lance_probe *
1379 *===========================================================================*/
1380 static int lance_probe(ec, skip)
1381 ether_card_t *ec;
1382 int skip;
1384 unsigned short pci_cmd;
1385 unsigned short ioaddr;
1386 int lance_version, chip_version;
1387 int devind, r;
1388 u16_t vid, did;
1390 r= pci_first_dev(&devind, &vid, &did);
1391 if (r == 0)
1392 return 0;
1394 while (skip--)
1396 r= pci_next_dev(&devind, &vid, &did);
1397 if (!r)
1398 return 0;
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;
1416 /* Reset */
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)
1427 lance_version = 0;
1428 else
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;
1439 ++lance_version)
1440 if (chip_table[lance_version].id_number == chip_version)
1441 break;
1444 #if VERBOSE
1445 printf("%s: %s at %X:%d\n",
1446 ec->port_name, chip_table[lance_version].name,
1447 ec->ec_port, ec->ec_irq);
1448 #endif
1450 return lance_version;
1453 /*===========================================================================*
1454 * lance_init_card *
1455 *===========================================================================*/
1456 static void lance_init_card(ec)
1457 ether_card_t *ec;
1459 int i;
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;
1500 /* OWN */
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;
1509 isstored[i] = 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. ----- */
1522 /* stop */
1523 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
1524 /* init */
1525 write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_INIT);
1526 /* poll for IDON */
1527 for (i = 10000; i > 0; --i)
1528 if (read_csr(ioaddr, LANCE_CSR0) & LANCE_CSR0_IDON)
1529 break;
1531 /* Set 'Multicast Table' */
1532 for (i=0;i<4;++i)
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);
1542 else
1544 if (ec->flags & (ECF_BROAD | ECF_MULTI))
1546 write_csr(ioaddr, LANCE_CSR15, 0x0000);
1548 else
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);
1558 return;
1561 /*===========================================================================*
1562 * in_byte *
1563 *===========================================================================*/
1564 static u8_t in_byte(port_t port)
1566 int r;
1567 u32_t value;
1569 r= sys_inb(port, &value);
1570 if (r != OK)
1571 panic("sys_inb failed: %d", r);
1572 return value;
1575 /*===========================================================================*
1576 * in_word *
1577 *===========================================================================*/
1578 static u16_t in_word(port_t port)
1580 int r;
1581 u32_t value;
1583 r= sys_inw(port, &value);
1584 if (r != OK)
1585 panic("sys_inw failed: %d", r);
1586 return value;
1590 /*===========================================================================*
1591 * out_word *
1592 *===========================================================================*/
1593 static void out_word(port_t port, u16_t value)
1595 int r;
1597 r= sys_outw(port, value);
1598 if (r != OK)
1599 panic("sys_outw failed: %d", r);
1602 /*===========================================================================*
1603 * read_csr *
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 /*===========================================================================*
1612 * write_csr *
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);