explicitly mask byte i/o values to bytes.
[minix3.git] / drivers / lance / lance.c
blob9b31a326cf985a367d432842021a3cc4f1152649
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_PORT DL_PROC DL_COUNT DL_MODE DL_ADDR DL_GRANT
10 * |------------+----------+---------+----------+---------+---------+---------|
11 * | HARDINT | | | | | | |
12 * |------------|----------|---------|----------|---------|---------|---------|
13 * | DL_WRITE | port nr | proc nr | count | mode | address | |
14 * |------------|----------|---------|----------|---------|---------|---------|
15 * | DL_WRITEV | port nr | proc nr | count | mode | address | |
16 * |------------|----------|---------|----------|---------|---------|---------|
17 * | DL_WRITEV_S| port nr | proc nr | count | mode | | grant |
18 * |------------|----------|---------|----------|---------|---------|---------|
19 * | DL_READ | port nr | proc nr | count | | address | |
20 * |------------|----------|---------|----------|---------|---------|---------|
21 * | DL_READV | port nr | proc nr | count | | address | |
22 * |------------|----------|---------|----------|---------|---------|---------|
23 * | DL_READV_S | port nr | proc nr | count | | | grant |
24 * |------------|----------|---------|----------|---------|---------|---------|
25 * | DL_CONF | port nr | proc nr | | mode | address | |
26 * |------------|----------|---------|----------|---------|---------|---------|
27 * | DL_GETSTAT | port nr | proc nr | | | address | |
28 * |------------|----------|---------|----------|---------|---------|---------|
29 * |DL_GETSTAT_S| port nr | proc nr | | | | grant |
30 * |------------|----------|---------|----------|---------|---------|---------|
31 * | DL_STOP | port_nr | | | | | |
32 * |------------|----------|---------|----------|---------|---------|---------|
34 * The messages sent are:
36 * m-type DL_POR T DL_PROC DL_COUNT DL_STAT DL_CLCK
37 * |------------|----------|---------|----------|---------|---------|
38 * |DL_TASK_REPL| port nr | proc nr | rd-count | err|stat| clock |
39 * |------------|----------|---------|----------|---------|---------|
41 * m_type m3_i1 m3_i2 m3_ca1
42 * |------------+---------+-----------+---------------|
43 * |DL_CONF_REPL| port nr | last port | ethernet addr |
44 * |------------|---------|-----------|---------------|
46 * Created: Jul 27, 2002 by Kazuya Kodama <kazuya@nii.ac.jp>
47 * Adapted for Minix 3: Sep 05, 2005 by Joren l'Ami <jwlami@cs.vu.nl>
50 #define VERBOSE 0
52 #include "../drivers.h"
54 #include <minix/keymap.h>
55 #include <net/hton.h>
56 #include <net/gen/ether.h>
57 #include <net/gen/eth_io.h>
58 #include <assert.h>
60 #include <minix/syslib.h>
61 #include <ibm/pci.h>
63 #include "lance.h"
64 /*#include "proc.h"*/
66 #include <sys/ioc_memory.h>
68 /* new I/O functions in Minix 3 */
69 #define out_byte( x, y ) sys_outb( x, y )
70 #define out_word( x, y ) sys_outw( x, y )
72 static U8_t in_byte(U16_t port)
74 unsigned long value;
75 int s;
76 if ((s=sys_inb(port, &value)) != OK)
77 printf( "lance: warning, sys_inb failed: %d\n", s );
78 return (U8_t) value;
81 static U16_t in_word( U16_t port)
83 unsigned long value;
84 int s;
85 if ((s=sys_inw(port, &value)) != OK)
86 printf( "lance: warning, sys_inw failed: %d\n", s );
87 return (U16_t) value;
90 #define in_byte( x ) inb( x )
91 #define in_word( x ) inw( x )
94 static ether_card_t ec_table[EC_PORT_NR_MAX];
95 static int eth_tasknr= ANY;
96 static u16_t eth_ign_proto;
98 /* Configuration */
99 typedef struct ec_conf
101 port_t ec_port;
102 int ec_irq;
103 phys_bytes ec_mem;
104 char *ec_envvar;
105 } ec_conf_t;
107 /* We hardly use these. Just "LANCE0=on/off" "LANCE1=on/off" mean. */
108 ec_conf_t ec_conf[]= /* Card addresses */
110 /* I/O port, IRQ, Buffer address, Env. var, Buf selector. */
111 { 0x1000, 9, 0x00000, "LANCE0" },
112 { 0xD000, 15, 0x00000, "LANCE1" },
115 /* Actually, we use PCI-BIOS info. */
116 PRIVATE struct pcitab
118 u16_t vid;
119 u16_t did;
120 int checkclass;
121 } pcitab[]=
123 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, 0 }, /* AMD LANCE */
125 { 0x0000, 0x0000, 0 }
128 struct pci_device pci_dev_list[] = {
129 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
130 "AMD Lance/PCI", 0, 0, 0, 0, 0, 0},
131 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE,
132 "AMD Lance/PCI", 0, 0, 0, 0, 0, 0},
133 {0, 0, NULL, 0, 0, 0, 0, 0, 0}
137 /* General */
138 _PROTOTYPE( static void do_init, (message *mp) );
139 _PROTOTYPE( static void ec_init, (ether_card_t *ec) );
140 _PROTOTYPE( static void ec_confaddr, (ether_card_t *ec) );
141 _PROTOTYPE( static void ec_reinit, (ether_card_t *ec) );
142 _PROTOTYPE( static void ec_check_ints, (ether_card_t *ec) );
143 _PROTOTYPE( static void conf_hw, (ether_card_t *ec) );
144 /*_PROTOTYPE( static int ec_handler, (irq_hook_t *hook) );*/
145 _PROTOTYPE( static void update_conf, (ether_card_t *ec, ec_conf_t *ecp) );
146 _PROTOTYPE( static void mess_reply, (message *req, message *reply) );
147 _PROTOTYPE( static void do_int, (ether_card_t *ec) );
148 _PROTOTYPE( static void reply,
149 (ether_card_t *ec, int err, int may_block) );
150 _PROTOTYPE( static void ec_reset, (ether_card_t *ec) );
151 _PROTOTYPE( static void ec_send, (ether_card_t *ec) );
152 _PROTOTYPE( static void ec_recv, (ether_card_t *ec) );
153 _PROTOTYPE( static void do_vwrite_s,
154 (message *mp, int from_int) );
155 _PROTOTYPE( static void do_vread_s, (message *mp) );
156 _PROTOTYPE( static void get_userdata_s,
157 (int user_proc, cp_grant_id_t grant, vir_bytes offset,
158 vir_bytes count, void *loc_addr) );
159 _PROTOTYPE( static void ec_user2nic,
160 (ether_card_t *dep, iovec_dat_t *iovp,
161 vir_bytes offset, int nic_addr,
162 vir_bytes count) );
163 _PROTOTYPE( static void ec_nic2user,
164 (ether_card_t *ec, int nic_addr,
165 iovec_dat_t *iovp, vir_bytes offset,
166 vir_bytes count) );
167 _PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp) );
168 _PROTOTYPE( static void ec_next_iovec, (iovec_dat_t *iovp) );
169 _PROTOTYPE( static void do_getstat_s, (message *mp) );
170 _PROTOTYPE( static void put_userdata_s,
171 (int user_proc, cp_grant_id_t grant,
172 void *loc_addr, vir_bytes count) );
173 _PROTOTYPE( static void do_stop, (message *mp) );
174 _PROTOTYPE( static void do_getname, (message *mp) );
176 _PROTOTYPE( static void lance_dump, (void) );
177 _PROTOTYPE( static void lance_stop, (void) );
178 _PROTOTYPE( static void getAddressing, (int devind, ether_card_t *ec) );
180 /* probe+init LANCE cards */
181 _PROTOTYPE( static int lance_probe, (ether_card_t *ec) );
182 _PROTOTYPE( static void lance_init_card, (ether_card_t *ec) );
184 /* --- LANCE --- */
185 /* General */
186 #define Address unsigned long
189 /* Minix 3 */
190 #define virt_to_bus(x) (vir2phys((unsigned long)x))
191 unsigned long vir2phys( unsigned long x )
193 int r;
194 unsigned long value;
196 if ( (r=sys_umap( SELF, D, x, 4, &value )) != OK )
197 panic( "lance", "sys_umap failed", r );
199 return value;
202 /* DMA limitations */
203 #define DMA_ADDR_MASK 0xFFFFFF /* mask to verify DMA address is 24-bit */
205 #define CORRECT_DMA_MEM() ( (virt_to_bus(lance + sizeof(lance)) & ~DMA_ADDR_MASK) == 0 )
207 #define ETH_FRAME_LEN 1518
209 #define LANCE_MUST_PAD 0x00000001
210 #define LANCE_ENABLE_AUTOSELECT 0x00000002
211 #define LANCE_SELECT_PHONELINE 0x00000004
212 #define LANCE_MUST_UNRESET 0x00000008
214 static const struct lance_chip_type
216 int id_number;
217 const char *name;
218 int flags;
219 } chip_table[] = {
220 {0x0000, "LANCE 7990", /* Ancient lance chip. */
221 LANCE_MUST_PAD + LANCE_MUST_UNRESET},
222 {0x0003, "PCnet/ISA 79C960", /* 79C960 PCnet/ISA. */
223 LANCE_ENABLE_AUTOSELECT},
224 {0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */
225 LANCE_ENABLE_AUTOSELECT},
226 {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */
227 LANCE_ENABLE_AUTOSELECT},
228 {0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */
229 LANCE_ENABLE_AUTOSELECT},
230 {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */
231 LANCE_ENABLE_AUTOSELECT},
232 {0x2625, "PCnet-FAST III 79C973",/* 79C973 PCInet-FAST III. */
233 LANCE_ENABLE_AUTOSELECT},
234 {0x2626, "PCnet/HomePNA 79C978",
235 LANCE_ENABLE_AUTOSELECT|LANCE_SELECT_PHONELINE},
236 {0x0, "PCnet (unknown)",
237 LANCE_ENABLE_AUTOSELECT},
240 /* ############## for LANCE device ############## */
241 #define LANCE_ETH_ADDR 0x0
242 #define LANCE_DATA 0x10
243 #define LANCE_ADDR 0x12
244 #define LANCE_RESET 0x14
245 #define LANCE_BUS_IF 0x16
246 #define LANCE_TOTAL_SIZE 0x18
248 /* Use 2^4=16 {Rx,Tx} buffers */
249 #define LANCE_LOG_RX_BUFFERS 4
250 #define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
251 #define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
252 #define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
254 #define LANCE_LOG_TX_BUFFERS 4
255 #define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
256 #define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
257 #define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
259 /* for lance_interface */
260 struct lance_init_block
262 unsigned short mode;
263 unsigned char phys_addr[6];
264 unsigned long filter[2];
265 Address rx_ring;
266 Address tx_ring;
269 struct lance_rx_head
271 union {
272 Address base;
273 unsigned char addr[4];
274 } u;
275 short buf_length; /* 2s complement */
276 short msg_length;
279 struct lance_tx_head
281 union {
282 Address base;
283 unsigned char addr[4];
284 } u;
285 short buf_length; /* 2s complement */
286 short misc;
289 struct lance_interface
291 struct lance_init_block init_block;
292 struct lance_rx_head rx_ring[RX_RING_SIZE];
293 struct lance_tx_head tx_ring[TX_RING_SIZE];
294 unsigned char rbuf[RX_RING_SIZE][ETH_FRAME_LEN];
295 unsigned char tbuf[TX_RING_SIZE][ETH_FRAME_LEN];
298 /* =============== global variables =============== */
299 static struct lance_interface *lp;
300 static char lance[sizeof(struct lance_interface)+8];
301 static int rx_slot_nr = 0; /* Rx-slot number */
302 static int tx_slot_nr = 0; /* Tx-slot number */
303 static int cur_tx_slot_nr = 0; /* Tx-slot number */
304 static char isstored[TX_RING_SIZE]; /* Tx-slot in-use */
305 static char *progname;
308 /*===========================================================================*
309 * lance_task *
310 *===========================================================================*/
311 void main( int argc, char **argv )
313 message m;
314 int i,irq,r, tasknr;
315 ether_card_t *ec;
316 long v;
317 int fkeys, sfkeys;
318 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
320 env_setargs( argc, argv );
322 fkeys = sfkeys = 0; bit_set( sfkeys, 7 );
324 #if 0
325 if ( (r = fkey_map(&fkeys, &sfkeys)) != OK )
326 printf( "Error registering key\n" );
327 #endif
329 if((eth_tasknr=getprocnr()) < 0)
330 panic("lance","couldn't get own proc nr", i);
332 v= 0;
333 (void) env_parse("ETH_IGN_PROTO", "x", 0, &v, 0x0000L, 0xFFFFL);
334 eth_ign_proto= htons((u16_t) v);
336 /* Try to notify inet that we are present (again) */
337 r = _pm_findproc("inet", &tasknr);
338 if (r == OK)
339 notify(tasknr);
341 while (TRUE)
343 for (i=0;i<EC_PORT_NR_MAX;++i)
345 ec= &ec_table[i];
346 if (ec->ec_irq != 0)
347 sys_irqenable(&ec->ec_hook);
350 if ((r= receive(ANY, &m)) != OK)
351 panic( "lance", "receive failed", r);
353 for (i=0;i<EC_PORT_NR_MAX;++i)
355 ec= &ec_table[i];
356 if (ec->ec_irq != 0)
357 sys_irqdisable(&ec->ec_hook);
360 /*printf( "." );*/
362 switch (m.m_type){
363 case DEV_PING: notify(m.m_source); continue;
364 case DL_WRITEV_S: do_vwrite_s(&m, FALSE); break;
365 case DL_READV_S: do_vread_s(&m); break;
366 case DL_CONF: do_init(&m); break;
367 case DL_GETSTAT_S: do_getstat_s(&m); break;
368 case DL_STOP: do_stop(&m); break;
369 case DL_GETNAME: do_getname(&m); break;
370 case FKEY_PRESSED: lance_dump(); break;
371 /*case HARD_STOP: lance_stop(); break;*/
372 case SYS_SIG:
374 sigset_t set = m.NOTIFY_ARG;
375 if ( sigismember( &set, SIGKSTOP ) )
376 lance_stop();
378 break;
379 case HARD_INT:
380 for (i=0;i<EC_PORT_NR_MAX;++i)
382 ec= &ec_table[i];
383 if (ec->mode != EC_ENABLED)
384 continue;
387 printf( "#.\n" );
390 irq=ec->ec_irq;
391 /*if (ec->ec_int_pending)*/
393 ec->ec_int_pending = 0;
394 ec_check_ints(ec);
395 do_int(ec);
398 break;
399 case PROC_EVENT:
400 break;
401 default:
402 panic( "lance", "illegal message", m.m_type);
407 /*===========================================================================*
408 * lance_dump *
409 *===========================================================================*/
410 static void lance_dump()
412 ether_card_t *ec;
413 int i, isr;
414 unsigned short ioaddr;
416 printf("\n");
417 for (i= 0, ec = &ec_table[0]; i<EC_PORT_NR_MAX; i++, ec++)
419 if (ec->mode == EC_DISABLED)
420 printf("lance port %d is disabled\n", i);
421 else if (ec->mode == EC_SINK)
422 printf("lance port %d is in sink mode\n", i);
424 if (ec->mode != EC_ENABLED)
425 continue;
427 printf("lance statistics of port %d:\n", i);
429 printf("recvErr :%8ld\t", ec->eth_stat.ets_recvErr);
430 printf("sendErr :%8ld\t", ec->eth_stat.ets_sendErr);
431 printf("OVW :%8ld\n", ec->eth_stat.ets_OVW);
433 printf("CRCerr :%8ld\t", ec->eth_stat.ets_CRCerr);
434 printf("frameAll :%8ld\t", ec->eth_stat.ets_frameAll);
435 printf("missedP :%8ld\n", ec->eth_stat.ets_missedP);
437 printf("packetR :%8ld\t", ec->eth_stat.ets_packetR);
438 printf("packetT :%8ld\t", ec->eth_stat.ets_packetT);
439 printf("transDef :%8ld\n", ec->eth_stat.ets_transDef);
441 printf("collision :%8ld\t", ec->eth_stat.ets_collision);
442 printf("transAb :%8ld\t", ec->eth_stat.ets_transAb);
443 printf("carrSense :%8ld\n", ec->eth_stat.ets_carrSense);
445 printf("fifoUnder :%8ld\t", ec->eth_stat.ets_fifoUnder);
446 printf("fifoOver :%8ld\t", ec->eth_stat.ets_fifoOver);
447 printf("CDheartbeat:%8ld\n", ec->eth_stat.ets_CDheartbeat);
449 printf("OWC :%8ld\t", ec->eth_stat.ets_OWC);
451 ioaddr = ec->ec_port;
452 out_word(ioaddr+LANCE_ADDR, 0x00);
453 isr=in_word(ioaddr+LANCE_DATA);
454 printf("isr = 0x%x + 0x%x, flags = 0x%x\n", isr,
455 in_word(ioaddr+LANCE_DATA), ec->flags);
457 printf("irq = %d\tioadr = %d\n", ec->ec_irq, ec->ec_port);
461 /*===========================================================================*
462 * lance_stop *
463 *===========================================================================*/
464 static void lance_stop()
466 message mess;
467 int i;
469 for (i= 0; i<EC_PORT_NR_MAX; i++)
471 if (ec_table[i].mode != EC_ENABLED)
472 continue;
473 mess.m_type= DL_STOP;
474 mess.DL_PORT= i;
475 do_stop(&mess);
478 /*printf("LANCE driver stopped.\n");*/
480 sys_exit( 0 );
484 /*===========================================================================*
485 * do_init *
486 *===========================================================================*/
487 static void do_init(mp)
488 message *mp;
490 int port;
491 ether_card_t *ec;
492 message reply_mess;
494 pci_init();
496 port = mp->DL_PORT;
497 if (port < 0 || port >= EC_PORT_NR_MAX)
499 reply_mess.m_type= DL_CONF_REPLY;
500 reply_mess.m3_i1= ENXIO;
501 mess_reply(mp, &reply_mess);
502 return;
504 ec= &ec_table[port];
505 strcpy(ec->port_name, "eth_card#0");
506 ec->port_name[9] += port;
507 if (ec->mode == EC_DISABLED)
509 /* This is the default, try to (re)locate the device. */
510 /* only try to enable if memory is correct for DMA */
511 if ( CORRECT_DMA_MEM() )
513 conf_hw(ec);
515 else
517 report( "LANCE", "DMA denied because address out of range", NO_NUM );
520 if (ec->mode == EC_DISABLED)
522 /* Probe failed, or the device is configured off. */
523 reply_mess.m_type= DL_CONF_REPLY;
524 reply_mess.m3_i1= ENXIO;
525 mess_reply(mp, &reply_mess);
526 return;
528 if (ec->mode == EC_ENABLED)
529 ec_init(ec);
532 if (ec->mode == EC_SINK)
534 ec->mac_address.ea_addr[0] =
535 ec->mac_address.ea_addr[1] =
536 ec->mac_address.ea_addr[2] =
537 ec->mac_address.ea_addr[3] =
538 ec->mac_address.ea_addr[4] =
539 ec->mac_address.ea_addr[5] = 0;
540 ec_confaddr(ec);
541 reply_mess.m_type = DL_CONF_REPLY;
542 reply_mess.m3_i1 = mp->DL_PORT;
543 reply_mess.m3_i2 = EC_PORT_NR_MAX;
544 *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
545 mess_reply(mp, &reply_mess);
546 return;
548 assert(ec->mode == EC_ENABLED);
549 assert(ec->flags & ECF_ENABLED);
551 ec->flags &= ~(ECF_PROMISC | ECF_MULTI | ECF_BROAD);
553 if (mp->DL_MODE & DL_PROMISC_REQ)
554 ec->flags |= ECF_PROMISC | ECF_MULTI | ECF_BROAD;
555 if (mp->DL_MODE & DL_MULTI_REQ)
556 ec->flags |= ECF_MULTI;
557 if (mp->DL_MODE & DL_BROAD_REQ)
558 ec->flags |= ECF_BROAD;
560 ec->client = mp->m_source;
561 ec_reinit(ec);
563 reply_mess.m_type = DL_CONF_REPLY;
564 reply_mess.m3_i1 = mp->DL_PORT;
565 reply_mess.m3_i2 = EC_PORT_NR_MAX;
566 *(ether_addr_t *) reply_mess.m3_ca1 = ec->mac_address;
568 mess_reply(mp, &reply_mess);
572 /*===========================================================================*
573 * do_int *
574 *===========================================================================*/
575 static void do_int(ec)
576 ether_card_t *ec;
578 if (ec->flags & (ECF_PACK_SEND | ECF_PACK_RECV))
579 reply(ec, OK, TRUE);
582 #if 0
583 /*===========================================================================*
584 * ec_handler *
585 *===========================================================================*/
586 static int ec_handler(hook)
587 irq_hook_t *hook;
589 /* LANCE interrupt, send message and reenable interrupts. */
590 #if 0
591 printf(">> ec_handler(): \n");
592 #endif
594 structof(ether_card_t, ec_hook, hook)->ec_int_pending= 1;
596 notify(eth_tasknr);
598 return 0;
600 #endif
602 /*===========================================================================*
603 * conf_hw *
604 *===========================================================================*/
605 static void conf_hw(ec)
606 ether_card_t *ec;
608 static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 /* ,... */ };
610 int ifnr;
611 ec_conf_t *ecp;
613 ec->mode= EC_DISABLED; /* Superfluous */
614 ifnr= ec-ec_table;
616 ecp= &ec_conf[ifnr];
617 update_conf(ec, ecp);
618 if (ec->mode != EC_ENABLED)
619 return;
621 if (!lance_probe(ec))
623 printf("%s: No ethernet card found on PCI-BIOS info.\n",
624 ec->port_name);
625 ec->mode= EC_DISABLED;
626 return;
629 /* Allocate a memory segment, programmed I/O should set the
630 * memory segment (linmem) to zero.
632 if (ec->ec_linmem != 0)
634 assert( 0 );
635 /*phys2seg(&ec->ec_memseg, &ec->ec_memoff, ec->ec_linmem);*/
638 /* XXX */ if (ec->ec_linmem == 0) ec->ec_linmem= 0xFFFF0000;
640 ec->flags = ECF_EMPTY;
641 ec->eth_stat = empty_stat;
645 /*===========================================================================*
646 * update_conf *
647 *===========================================================================*/
648 static void update_conf(ec, ecp)
649 ether_card_t *ec;
650 ec_conf_t *ecp;
652 long v;
653 static char ec_fmt[] = "x:d:x:x";
655 /* Get the default settings and modify them from the environment. */
656 ec->mode= EC_SINK;
657 v= ecp->ec_port;
658 switch (env_parse(ecp->ec_envvar, ec_fmt, 0, &v, 0x0000L, 0xFFFFL)) {
659 case EP_OFF:
660 ec->mode= EC_DISABLED;
661 break;
662 case EP_ON:
663 case EP_SET:
664 ec->mode= EC_ENABLED; /* Might become disabled if
665 * all probes fail */
666 break;
669 ec->ec_port= v;
671 v= ecp->ec_irq | DEI_DEFAULT;
672 (void) env_parse(ecp->ec_envvar, ec_fmt, 1, &v, 0L,
673 (long) NR_IRQ_VECTORS - 1);
674 ec->ec_irq= v;
676 v= ecp->ec_mem;
677 (void) env_parse(ecp->ec_envvar, ec_fmt, 2, &v, 0L, 0xFFFFFL);
678 ec->ec_linmem= v;
680 v= 0;
681 (void) env_parse(ecp->ec_envvar, ec_fmt, 3, &v, 0x2000L, 0x8000L);
682 ec->ec_ramsize= v;
686 /*===========================================================================*
687 * ec_init *
688 *===========================================================================*/
689 static void ec_init(ec)
690 ether_card_t *ec;
692 int i, r;
694 /* General initialization */
695 ec->flags = ECF_EMPTY;
696 /*disable_irq(ec->ec_irq);*/
697 lance_init_card(ec); /* Get mac_address, etc ...*/
699 ec_confaddr(ec);
701 #if VERBOSE
702 printf("%s: Ethernet address ", ec->port_name);
703 for (i= 0; i < 6; i++)
704 printf("%x%c", ec->mac_address.ea_addr[i],
705 i < 5 ? ':' : '\n');
706 #endif
708 /* Finish the initialization */
709 ec->flags |= ECF_ENABLED;
711 /* Set the interrupt handler */
712 /*put_irq_handler(&ec->ec_hook, ec->ec_irq, ec_handler);*/
713 ec->ec_hook = ec->ec_irq;
714 if ((r=sys_irqsetpolicy(ec->ec_irq, 0, &ec->ec_hook)) != OK)
715 printf("lance: error, couldn't set IRQ policy: %d\n", r);
717 /* enable_irq(ec->ec_irq); */
719 /* enter_kdebug(">> ec_init():"); */
721 return;
725 /*===========================================================================*
726 * reply *
727 *===========================================================================*/
728 static void reply(ec, err, may_block)
729 ether_card_t *ec;
730 int err;
731 int may_block;
733 message reply;
734 int status,r;
735 clock_t now;
737 status = 0;
738 if (ec->flags & ECF_PACK_SEND)
739 status |= DL_PACK_SEND;
740 if (ec->flags & ECF_PACK_RECV)
741 status |= DL_PACK_RECV;
743 reply.m_type = DL_TASK_REPLY;
744 reply.DL_PORT = ec - ec_table;
745 reply.DL_PROC = ec->client;
746 reply.DL_STAT = status | ((u32_t) err << 16);
747 reply.DL_COUNT = ec->read_s;
748 #if 1
749 if ((r=getuptime(&now)) != OK)
750 panic("lance", "getuptime() failed:", r);
751 reply.DL_CLCK = now;
752 #else
753 reply.DL_CLCK = 0;
754 #endif
756 r = send(ec->client, &reply);
757 #if 1
758 if (r == ELOCKED && may_block)
760 /* enter_kdebug(">> lance_task: ELOCKED!"); */
761 return;
763 #endif
764 if (r < 0)
765 panic( "lance", "send failed:", r);
767 ec->read_s = 0;
768 ec->flags &= ~(ECF_PACK_SEND | ECF_PACK_RECV);
772 /*===========================================================================*
773 * mess_reply *
774 *===========================================================================*/
775 static void mess_reply(req, reply_mess)
776 message *req;
777 message *reply_mess;
779 if (send(req->m_source, reply_mess) != OK)
780 panic( "lance", "unable to mess_reply", NO_NUM);
784 /*===========================================================================*
785 * ec_confaddr *
786 *===========================================================================*/
787 static void ec_confaddr(ec)
788 ether_card_t *ec;
790 int i;
791 char eakey[16];
792 static char eafmt[]= "x:x:x:x:x:x";
793 long v;
795 /* User defined ethernet address? */
796 strcpy(eakey, ec_conf[ec-ec_table].ec_envvar);
797 strcat(eakey, "_EA");
799 for (i= 0; i < 6; i++)
801 v= ec->mac_address.ea_addr[i];
802 if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
803 break;
804 ec->mac_address.ea_addr[i]= v;
807 if (i != 0 && i != 6)
809 /* It's all or nothing; force a panic. */
810 (void) env_parse(eakey, "?", 0, &v, 0L, 0L);
815 /*===========================================================================*
816 * ec_reinit *
817 *===========================================================================*/
818 static void ec_reinit(ec)
819 ether_card_t *ec;
821 int i;
822 unsigned short ioaddr = ec->ec_port;
824 out_word(ioaddr+LANCE_ADDR, 0x0);
825 (void)in_word(ioaddr+LANCE_ADDR);
826 out_word(ioaddr+LANCE_DATA, 0x4); /* stop */
828 /* purge Tx-ring */
829 tx_slot_nr = cur_tx_slot_nr = 0;
830 for (i=0; i<TX_RING_SIZE; i++) {
831 lp->tx_ring[i].u.base = 0;
832 isstored[i]=0;
835 /* re-init Rx-ring */
836 rx_slot_nr = 0;
837 for (i=0; i<RX_RING_SIZE; i++)
839 lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
840 lp->rx_ring[i].u.addr[3] |= 0x80;
843 /* Set 'Receive Mode' */
844 if (ec->flags & ECF_PROMISC)
846 out_word(ioaddr+LANCE_ADDR, 0xf);
847 out_word(ioaddr+LANCE_DATA, 0x8000);
849 else
851 if (ec->flags & (ECF_BROAD | ECF_MULTI))
853 out_word(ioaddr+LANCE_ADDR, 0xf);
854 out_word(ioaddr+LANCE_DATA, 0x0000);
856 else
858 out_word(ioaddr+LANCE_ADDR, 0xf);
859 out_word(ioaddr+LANCE_DATA, 0x4000);
863 out_word(ioaddr+LANCE_ADDR, 0x0);
864 (void)in_word(ioaddr+LANCE_ADDR);
865 out_word(ioaddr+LANCE_DATA, 0x142); /* start && enable interrupt */
867 return;
870 /*===========================================================================*
871 * ec_check_ints *
872 *===========================================================================*/
873 static void ec_check_ints(ec)
874 ether_card_t *ec;
876 int must_restart=0;
877 int check,status;
878 int isr=0x0000;
879 unsigned short ioaddr = ec->ec_port;
881 if (!(ec->flags & ECF_ENABLED))
882 panic( "lance", "got premature interrupt", NO_NUM);
884 for (;;)
886 #if 0
887 printf("ETH: Reading ISR...");
888 #endif
889 out_word(ioaddr+LANCE_ADDR, 0x00);
890 isr=in_word(ioaddr+LANCE_DATA);
891 if (isr & 0x8600)
892 out_word( ioaddr+LANCE_DATA, isr & ~0x004f);
893 out_word(ioaddr+LANCE_DATA, 0x7940);
894 #if 0
895 printf("ISR=0x%x...",in_word(ioaddr+LANCE_DATA));
896 #endif
897 #define ISR_WINT 0x0200
898 #define ISR_RINT 0x0400
899 #define ISR_RERR 0x1000
900 #define ISR_WERR 0x4000
901 #define ISR_ERR 0x8000
902 #define ISR_RST 0x0000
904 if ((isr & (ISR_WINT|ISR_RINT|ISR_RERR|ISR_WERR|ISR_ERR)) == 0x0000)
906 #if 0
907 printf("OK\n");
908 #endif
909 break;
912 if (isr & ISR_RERR)
914 #if 0
915 printf("RERR\n");
916 #endif
917 ec->eth_stat.ets_recvErr++;
919 if ((isr & ISR_WERR) || (isr & ISR_WINT))
921 if (isr & ISR_WERR)
923 #if 0
924 printf("WERR\n");
925 #endif
926 ec->eth_stat.ets_sendErr++;
928 if (isr & ISR_WINT)
930 #if 0
931 printf("WINT\n");
932 #endif
933 /* status check: restart if needed. */
934 status = lp->tx_ring[cur_tx_slot_nr].u.base;
936 /* ??? */
937 if (status & 0x40000000)
939 status = lp->tx_ring[cur_tx_slot_nr].misc;
940 ec->eth_stat.ets_sendErr++;
941 if (status & 0x0400)
942 ec->eth_stat.ets_transAb++;
943 if (status & 0x0800)
944 ec->eth_stat.ets_carrSense++;
945 if (status & 0x1000)
946 ec->eth_stat.ets_OWC++;
947 if (status & 0x4000)
949 ec->eth_stat.ets_fifoUnder++;
950 must_restart=1;
953 else
955 if (status & 0x18000000)
956 ec->eth_stat.ets_collision++;
957 ec->eth_stat.ets_packetT++;
960 /* transmit a packet on the next slot if it exists. */
961 check = 0;
962 if (isstored[cur_tx_slot_nr]==1)
964 /* free the tx-slot just transmitted */
965 isstored[cur_tx_slot_nr]=0;
966 cur_tx_slot_nr = (++cur_tx_slot_nr) & TX_RING_MOD_MASK;
968 /* next tx-slot is ready? */
969 if (isstored[cur_tx_slot_nr]==1)
970 check=1;
971 else
972 check=0;
974 else
976 panic( "lance", "got premature WINT...", NO_NUM);
978 if (check==1)
980 lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;
981 out_word(ioaddr+LANCE_ADDR, 0x0000);
982 out_word(ioaddr+LANCE_DATA, 0x0048);
984 else
985 if (check==-1)
986 continue;
987 /* we set a buffered message in the slot if it exists. */
988 /* and transmit it, if needed. */
989 if (ec->flags & ECF_SEND_AVAIL)
990 ec_send(ec);
992 if (isr & ISR_RINT)
994 #if 0
995 printf("RINT\n");
996 #endif
997 ec_recv(ec);
1000 if (isr & ISR_RST)
1002 ec->flags = ECF_STOPPED;
1003 break;
1006 /* ??? cf. lance driver on linux */
1007 if (must_restart == 1)
1009 #if 0
1010 printf("ETH: restarting...\n");
1011 #endif
1012 out_word(ioaddr+LANCE_ADDR, 0x0);
1013 (void)in_word(ioaddr+LANCE_ADDR);
1014 out_word(ioaddr+LANCE_DATA, 0x4); /* stop */
1015 out_word(ioaddr+LANCE_DATA, 0x2); /* start */
1019 if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))
1021 #if 0
1022 printf("ETH: resetting...\n");
1023 #endif
1024 ec_reset(ec);
1028 /*===========================================================================*
1029 * ec_reset *
1030 *===========================================================================*/
1031 static void ec_reset(ec)
1032 ether_card_t *ec;
1034 /* Stop/start the chip, and clear all RX,TX-slots */
1035 unsigned short ioaddr = ec->ec_port;
1036 int i;
1038 out_word(ioaddr+LANCE_ADDR, 0x0);
1039 (void)in_word(ioaddr+LANCE_ADDR);
1040 out_word(ioaddr+LANCE_DATA, 0x4); /* stop */
1041 out_word(ioaddr+LANCE_DATA, 0x2); /* start */
1043 /* purge Tx-ring */
1044 tx_slot_nr = cur_tx_slot_nr = 0;
1045 for (i=0; i<TX_RING_SIZE; i++) {
1046 lp->tx_ring[i].u.base = 0;
1047 isstored[i]=0;
1050 /* re-init Rx-ring */
1051 rx_slot_nr = 0;
1052 for (i=0; i<RX_RING_SIZE; i++)
1054 lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
1055 lp->rx_ring[i].u.addr[3] |= 0x80;
1058 /* store a buffered message on the slot if exists */
1059 ec_send(ec);
1060 ec->flags &= ~ECF_STOPPED;
1063 /*===========================================================================*
1064 * ec_send *
1065 *===========================================================================*/
1066 static void ec_send(ec)
1067 ether_card_t *ec;
1069 /* from ec_check_ints() or ec_reset(). */
1070 /* this function proccesses the buffered message. (slot/transmit) */
1071 if (!(ec->flags & ECF_SEND_AVAIL))
1072 return;
1074 ec->flags &= ~ECF_SEND_AVAIL;
1075 switch(ec->sendmsg.m_type)
1077 case DL_WRITEV_S: do_vwrite_s(&ec->sendmsg, TRUE); break;
1078 default:
1079 panic( "lance", "wrong type:", ec->sendmsg.m_type);
1080 break;
1084 /*===========================================================================*
1085 * do_vread_s *
1086 *===========================================================================*/
1087 static void do_vread_s(mp)
1088 message *mp;
1090 int port, count, size;
1091 ether_card_t *ec;
1093 port = mp->DL_PORT;
1094 count = mp->DL_COUNT;
1095 ec= &ec_table[port];
1096 ec->client= mp->DL_PROC;
1098 get_userdata_s(mp->DL_PROC, (vir_bytes) mp->DL_GRANT, 0,
1099 (count > IOVEC_NR ? IOVEC_NR : count) *
1100 sizeof(iovec_s_t), ec->read_iovec.iod_iovec);
1101 ec->read_iovec.iod_iovec_s = count;
1102 ec->read_iovec.iod_proc_nr = mp->DL_PROC;
1103 ec->read_iovec.iod_grant = (vir_bytes) mp->DL_GRANT;
1104 ec->read_iovec.iod_iovec_offset = 0;
1106 ec->tmp_iovec = ec->read_iovec;
1107 size= calc_iovec_size(&ec->tmp_iovec);
1109 ec->flags |= ECF_READING;
1111 ec_recv(ec);
1113 if ((ec->flags & (ECF_READING|ECF_STOPPED)) == (ECF_READING|ECF_STOPPED))
1114 ec_reset(ec);
1115 reply(ec, OK, FALSE);
1118 /*===========================================================================*
1119 * ec_recv *
1120 *===========================================================================*/
1121 static void ec_recv(ec)
1122 ether_card_t *ec;
1124 vir_bytes length;
1125 int packet_processed;
1126 int status;
1127 unsigned short ioaddr = ec->ec_port;
1129 if ((ec->flags & ECF_READING)==0)
1130 return;
1131 if (!(ec->flags & ECF_ENABLED))
1132 return;
1134 /* we check all the received slots until find a properly received packet */
1135 packet_processed = FALSE;
1136 while (!packet_processed)
1138 status = lp->rx_ring[rx_slot_nr].u.base >> 24;
1139 if ( (status & 0x80) == 0x00 )
1141 status = lp->rx_ring[rx_slot_nr].u.base >> 24;
1143 /* ??? */
1144 if (status != 0x03)
1146 if (status & 0x01)
1147 ec->eth_stat.ets_recvErr++;
1148 if (status & 0x04)
1149 ec->eth_stat.ets_fifoOver++;
1150 if (status & 0x08)
1151 ec->eth_stat.ets_CRCerr++;
1152 if (status & 0x10)
1153 ec->eth_stat.ets_OVW++;
1154 if (status & 0x20)
1155 ec->eth_stat.ets_frameAll++;
1156 length = 0;
1158 else
1160 ec->eth_stat.ets_packetR++;
1161 length = lp->rx_ring[rx_slot_nr].msg_length;
1163 if (length > 0)
1165 ec_nic2user(ec, (int)(lp->rbuf[rx_slot_nr]),
1166 &ec->read_iovec, 0, length);
1168 ec->read_s = length;
1169 ec->flags |= ECF_PACK_RECV;
1170 ec->flags &= ~ECF_READING;
1171 packet_processed = TRUE;
1173 /* set up this slot again, and we move to the next slot */
1174 lp->rx_ring[rx_slot_nr].buf_length = -ETH_FRAME_LEN;
1175 lp->rx_ring[rx_slot_nr].u.addr[3] |= 0x80;
1177 out_word(ioaddr+LANCE_ADDR, 0x00);
1178 out_word(ioaddr+LANCE_DATA, 0x7940);
1180 rx_slot_nr = (++rx_slot_nr) & RX_RING_MOD_MASK;
1182 else
1183 break;
1187 /*===========================================================================*
1188 * do_vwrite_s *
1189 *===========================================================================*/
1190 static void do_vwrite_s(mp, from_int)
1191 message *mp;
1192 int from_int;
1194 int port, count, check;
1195 ether_card_t *ec;
1196 unsigned short ioaddr;
1198 port = mp->DL_PORT;
1199 count = mp->DL_COUNT;
1200 ec = &ec_table[port];
1201 ec->client= mp->DL_PROC;
1203 if (isstored[tx_slot_nr]==1)
1205 /* all slots are used, so this message is buffered */
1206 ec->sendmsg= *mp;
1207 ec->flags |= ECF_SEND_AVAIL;
1208 reply(ec, OK, FALSE);
1209 return;
1212 /* convert the message to write_iovec */
1213 get_userdata_s(mp->DL_PROC, mp->DL_GRANT, 0,
1214 (count > IOVEC_NR ? IOVEC_NR : count) *
1215 sizeof(iovec_s_t), ec->write_iovec.iod_iovec);
1217 ec->write_iovec.iod_iovec_s = count;
1218 ec->write_iovec.iod_proc_nr = mp->DL_PROC;
1219 ec->write_iovec.iod_grant = mp->DL_GRANT;
1220 ec->write_iovec.iod_iovec_offset = 0;
1222 ec->tmp_iovec = ec->write_iovec;
1223 ec->write_s = calc_iovec_size(&ec->tmp_iovec);
1225 /* copy write_iovec to the slot on DMA address */
1226 ec_user2nic(ec, &ec->write_iovec, 0,
1227 (int)(lp->tbuf[tx_slot_nr]), ec->write_s);
1228 /* set-up for transmitting, and transmit it if needed. */
1229 lp->tx_ring[tx_slot_nr].buf_length = -ec->write_s;
1230 lp->tx_ring[tx_slot_nr].misc = 0x0;
1231 lp->tx_ring[tx_slot_nr].u.base
1232 = virt_to_bus(lp->tbuf[tx_slot_nr]) & 0xffffff;
1233 isstored[tx_slot_nr]=1;
1234 if (cur_tx_slot_nr == tx_slot_nr)
1235 check=1;
1236 else
1237 check=0;
1238 tx_slot_nr = (++tx_slot_nr) & TX_RING_MOD_MASK;
1240 if (check == 1)
1242 ioaddr = ec->ec_port;
1243 lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;
1244 out_word(ioaddr+LANCE_ADDR, 0x0000);
1245 out_word(ioaddr+LANCE_DATA, 0x0048);
1248 ec->flags |= ECF_PACK_SEND;
1250 /* reply by calling do_int() if this function is called from interrupt. */
1251 if (from_int)
1252 return;
1253 reply(ec, OK, FALSE);
1257 /*===========================================================================*
1258 * get_userdata_s *
1259 *===========================================================================*/
1260 static void get_userdata_s(user_proc, grant, offset, count, loc_addr)
1261 int user_proc;
1262 cp_grant_id_t grant;
1263 vir_bytes offset;
1264 vir_bytes count;
1265 void *loc_addr;
1267 int cps;
1268 cps = sys_safecopyfrom(user_proc, grant, offset,
1269 (vir_bytes)loc_addr, count, D);
1270 if (cps != OK)
1271 panic(__FILE__,
1272 "get_userdata_s: sys_safecopyfrom failed: %d\n", cps);
1275 /*===========================================================================*
1276 * ec_user2nic *
1277 *===========================================================================*/
1278 static void ec_user2nic(ec, iovp, offset, nic_addr, count)
1279 ether_card_t *ec;
1280 iovec_dat_t *iovp;
1281 vir_bytes offset;
1282 int nic_addr;
1283 vir_bytes count;
1285 int bytes, i, r;
1287 i= 0;
1288 while (count > 0)
1290 if (i >= IOVEC_NR)
1292 ec_next_iovec(iovp);
1293 i= 0;
1294 continue;
1296 if (offset >= iovp->iod_iovec[i].iov_size)
1298 offset -= iovp->iod_iovec[i].iov_size;
1299 i++;
1300 continue;
1302 bytes = iovp->iod_iovec[i].iov_size - offset;
1303 if (bytes > count)
1304 bytes = count;
1306 if ( (r=sys_safecopyfrom(iovp->iod_proc_nr,
1307 iovp->iod_iovec[i].iov_grant, offset,
1308 nic_addr, bytes, D )) != OK )
1309 panic( __FILE__, "ec_user2nic: sys_safecopyfrom failed", r );
1311 count -= bytes;
1312 nic_addr += bytes;
1313 offset += bytes;
1317 /*===========================================================================*
1318 * ec_nic2user *
1319 *===========================================================================*/
1320 static void ec_nic2user(ec, nic_addr, iovp, offset, count)
1321 ether_card_t *ec;
1322 int nic_addr;
1323 iovec_dat_t *iovp;
1324 vir_bytes offset;
1325 vir_bytes count;
1327 int bytes, i, r;
1329 i= 0;
1330 while (count > 0)
1332 if (i >= IOVEC_NR)
1334 ec_next_iovec(iovp);
1335 i= 0;
1336 continue;
1338 if (offset >= iovp->iod_iovec[i].iov_size)
1340 offset -= iovp->iod_iovec[i].iov_size;
1341 i++;
1342 continue;
1344 bytes = iovp->iod_iovec[i].iov_size - offset;
1345 if (bytes > count)
1346 bytes = count;
1347 if ( (r=sys_safecopyto( iovp->iod_proc_nr, iovp->iod_iovec[i].iov_grant,
1348 offset, nic_addr, bytes, D )) != OK )
1349 panic( __FILE__, "ec_nic2user: sys_safecopyto failed: ", r );
1351 count -= bytes;
1352 nic_addr += bytes;
1353 offset += bytes;
1358 /*===========================================================================*
1359 * calc_iovec_size *
1360 *===========================================================================*/
1361 static int calc_iovec_size(iovp)
1362 iovec_dat_t *iovp;
1364 int size,i;
1366 size = i = 0;
1368 while (i < iovp->iod_iovec_s)
1370 if (i >= IOVEC_NR)
1372 ec_next_iovec(iovp);
1373 i= 0;
1374 continue;
1376 size += iovp->iod_iovec[i].iov_size;
1377 i++;
1380 return size;
1383 /*===========================================================================*
1384 * ec_next_iovec *
1385 *===========================================================================*/
1386 static void ec_next_iovec(iovp)
1387 iovec_dat_t *iovp;
1389 iovp->iod_iovec_s -= IOVEC_NR;
1390 iovp->iod_iovec_offset += IOVEC_NR * sizeof(iovec_s_t);
1392 get_userdata_s(iovp->iod_proc_nr, iovp->iod_grant,
1393 iovp->iod_iovec_offset,
1394 (iovp->iod_iovec_s > IOVEC_NR ?
1395 IOVEC_NR : iovp->iod_iovec_s) * sizeof(iovec_s_t),
1396 iovp->iod_iovec);
1400 /*===========================================================================*
1401 * do_getstat_s *
1402 *===========================================================================*/
1403 static void do_getstat_s(mp)
1404 message *mp;
1406 int port;
1407 ether_card_t *ec;
1409 port = mp->DL_PORT;
1410 if (port < 0 || port >= EC_PORT_NR_MAX)
1411 panic( "lance", "illegal port", port);
1413 ec= &ec_table[port];
1414 ec->client= mp->DL_PROC;
1416 put_userdata_s(mp->DL_PROC, mp->DL_GRANT,
1417 &ec->eth_stat, sizeof(ec->eth_stat));
1418 reply(ec, OK, FALSE);
1421 /*===========================================================================*
1422 * put_userdata_s *
1423 *===========================================================================*/
1424 static void put_userdata_s(user_proc, grant, loc_addr, count)
1425 int user_proc;
1426 cp_grant_id_t grant;
1427 void *loc_addr;
1428 vir_bytes count;
1430 int cps;
1431 cps = sys_safecopyto(user_proc, grant, 0,
1432 (vir_bytes) loc_addr, count, D);
1433 if (cps != OK)
1434 panic(__FILE__,
1435 "put_userdata_s: sys_safecopyto failed: %d\n", cps);
1438 /*===========================================================================*
1439 * do_stop *
1440 *===========================================================================*/
1441 static void do_stop(mp)
1442 message *mp;
1444 int port;
1445 ether_card_t *ec;
1446 unsigned short ioaddr;
1448 port = mp->DL_PORT;
1449 if (port < 0 || port >= EC_PORT_NR_MAX)
1450 panic( "lance", "illegal port", port);
1451 ec = &ec_table[port];
1453 if (!(ec->flags & ECF_ENABLED))
1454 return;
1456 ioaddr = ec->ec_port;
1458 out_word(ioaddr+LANCE_ADDR, 0x0);
1459 (void)in_word(ioaddr+LANCE_ADDR);
1460 out_word(ioaddr+LANCE_DATA, 0x4); /* stop */
1461 out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* reset */
1463 ec->flags = ECF_EMPTY;
1466 static void getAddressing(devind, ec)
1467 int devind;
1468 ether_card_t *ec;
1470 unsigned int membase, ioaddr;
1471 int reg, irq;
1473 for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4)
1475 ioaddr = pci_attr_r32(devind, reg);
1477 if ((ioaddr & PCI_BASE_ADDRESS_IO_MASK) == 0
1478 || (ioaddr & PCI_BASE_ADDRESS_SPACE_IO) == 0)
1479 continue;
1480 /* Strip the I/O address out of the returned value */
1481 ioaddr &= PCI_BASE_ADDRESS_IO_MASK;
1482 /* Get the memory base address */
1483 membase = pci_attr_r32(devind, PCI_BASE_ADDRESS_1);
1484 /* KK: Get the IRQ number */
1485 irq = pci_attr_r8(devind, PCI_INTERRUPT_PIN);
1486 if (irq)
1487 irq = pci_attr_r8(devind, PCI_INTERRUPT_LINE);
1488 /* Get the ROM base address */
1489 /*pci_attr_r32(devind, PCI_ROM_ADDRESS, &romaddr);
1490 romaddr >>= 10;*/
1491 /* Take the first one or the one that matches in boot ROM address */
1492 /*if (pci_ioaddr == 0
1493 || romaddr == ((unsigned long) rom.rom_segment << 4)) {*/
1494 ec->ec_linmem = membase;
1495 ec->ec_port = ioaddr;
1496 ec->ec_irq = irq;
1497 /*}*/
1501 /*===========================================================================*
1502 * lance_probe *
1503 *===========================================================================*/
1504 static int lance_probe(ec)
1505 ether_card_t *ec;
1507 unsigned short pci_cmd, attached = 0;
1508 unsigned short ioaddr;
1509 int lance_version, chip_version;
1510 int devind, just_one, i, r;
1512 u16_t vid, did;
1513 u32_t bar;
1514 u8_t ilr;
1515 char *dname;
1517 if ((ec->ec_pcibus | ec->ec_pcidev | ec->ec_pcifunc) != 0)
1519 /* Look for specific PCI device */
1520 r= pci_find_dev(ec->ec_pcibus, ec->ec_pcidev,
1521 ec->ec_pcifunc, &devind);
1522 if (r == 0)
1524 printf("%s: no PCI found at %d.%d.%d\n",
1525 ec->port_name, ec->ec_pcibus,
1526 ec->ec_pcidev, ec->ec_pcifunc);
1527 return 0;
1529 pci_ids(devind, &vid, &did);
1530 just_one= TRUE;
1532 else
1534 r= pci_first_dev(&devind, &vid, &did);
1535 if (r == 0)
1536 return 0;
1537 just_one= FALSE;
1540 for(;;)
1542 for (i= 0; pcitab[i].vid != 0; i++)
1544 if (pcitab[i].vid != vid)
1545 continue;
1546 if (pcitab[i].did != did)
1547 continue;
1548 if (pcitab[i].checkclass)
1550 panic("lance",
1551 "class check not implemented", NO_NUM);
1553 break;
1555 if (pcitab[i].vid != 0)
1556 break;
1558 if (just_one)
1560 printf(
1561 "%s: wrong PCI device (%04x/%04x) found at %d.%d.%d\n",
1562 ec->port_name, vid, did,
1563 ec->ec_pcibus,
1564 ec->ec_pcidev, ec->ec_pcifunc);
1565 return 0;
1568 r= pci_next_dev(&devind, &vid, &did);
1569 if (!r)
1570 return 0;
1573 dname= pci_dev_name(vid, did);
1574 if (!dname)
1575 dname= "unknown device";
1578 printf("%s: ", ec->port_name);
1579 printf("%s ", dname);
1580 printf("(%x/", vid);
1581 printf("%x) ", did);
1582 printf("at %s\n", pci_slot_name(devind));
1584 pci_reserve(devind);
1586 /* for (i = 0; pci_dev_list[i].vendor != 0; i++) {
1587 if (pci_dev_list[i].suffix == 1)
1589 ec->ec_port = pci_dev_list[i].ioaddr;
1590 ec->ec_irq = pci_dev_list[i].irq;
1591 ec->ec_linmem = pci_dev_list[i].membase;
1592 ec->ec_bus = pci_dev_list[i].bus;
1593 ec->ec_dev = pci_dev_list[i].devfn;
1594 ec->ec_fnc =
1595 pci_dev_list[i].suffix = -1;
1596 attached = 1;
1597 break;
1600 if (attached == 0)
1601 return 0;
1603 getAddressing(devind, ec);
1605 /* ===== Bus Master ? ===== */
1606 /*pcibios_read_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, &pci_cmd);*/
1607 pci_cmd = pci_attr_r32(devind, PCI_CR);
1608 if (!(pci_cmd & PCI_COMMAND_MASTER)) {
1609 pci_cmd |= PCI_COMMAND_MASTER;
1610 /*pcibios_write_config_word(ec->ec_bus, ec->ec_devfn, PCI_COMMAND, pci_cmd);*/
1611 pci_attr_w32(devind, PCI_CR, pci_cmd);
1614 /* ===== Probe Details ===== */
1615 ioaddr = ec->ec_port;
1617 out_word(ioaddr+LANCE_RESET, in_word(ioaddr+LANCE_RESET)); /* Reset */
1618 out_word(ioaddr+LANCE_ADDR, 0x0); /* Sw to win 0 */
1619 if (in_word(ioaddr+LANCE_DATA) != 0x4)
1621 ec->mode=EC_DISABLED;
1623 /* Probe Chip Version */
1624 out_word(ioaddr+LANCE_ADDR, 88); /* Get the version of the chip */
1625 if (in_word(ioaddr+LANCE_ADDR) != 88)
1626 lance_version = 0;
1627 else
1629 chip_version = in_word(ioaddr+LANCE_DATA);
1630 out_word(ioaddr+LANCE_ADDR, 89);
1631 chip_version |= in_word(ioaddr+LANCE_DATA) << 16;
1632 if ((chip_version & 0xfff) != 0x3)
1634 ec->mode=EC_DISABLED;
1636 chip_version = (chip_version >> 12) & 0xffff;
1637 for (lance_version = 1; chip_table[lance_version].id_number != 0;
1638 ++lance_version)
1639 if (chip_table[lance_version].id_number == chip_version)
1640 break;
1643 #if 0
1644 printf("%s: %s at %X:%d\n",
1645 ec->port_name, chip_table[lance_version].name,
1646 ec->ec_port, ec->ec_irq);
1647 #endif
1649 return lance_version;
1652 /*===========================================================================*
1653 * do_getname *
1654 *===========================================================================*/
1655 static void do_getname(mp)
1656 message *mp;
1658 int r;
1660 strncpy(mp->DL_NAME, progname, sizeof(mp->DL_NAME));
1661 mp->DL_NAME[sizeof(mp->DL_NAME)-1]= '\0';
1662 mp->m_type= DL_NAME_REPLY;
1663 r= send(mp->m_source, mp);
1664 if (r != OK)
1665 panic("LANCE", "do_getname: send failed", r);
1668 /*===========================================================================*
1669 * lance_init_card *
1670 *===========================================================================*/
1671 static void lance_init_card(ec)
1672 ether_card_t *ec;
1674 int i;
1675 Address l;
1676 unsigned short ioaddr = ec->ec_port;
1678 /* ============= setup init_block(cf. lance_probe1) ================ */
1679 /* make sure data structure is 8-byte aligned */
1680 l = ((Address)lance + 7) & ~7;
1681 lp = (struct lance_interface *)l;
1682 lp->init_block.mode = 0x3; /* disable Rx and Tx */
1683 lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0;
1684 /* using multiple Rx/Tx buffer */
1685 lp->init_block.rx_ring
1686 = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
1687 lp->init_block.tx_ring
1688 = (virt_to_bus(&lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
1690 l = virt_to_bus(&lp->init_block);
1691 out_word(ioaddr+LANCE_ADDR, 0x1);
1692 (void)in_word(ioaddr+LANCE_ADDR);
1693 out_word(ioaddr+LANCE_DATA, (unsigned short)l);
1694 out_word(ioaddr+LANCE_ADDR, 0x2);
1695 (void)in_word(ioaddr+LANCE_ADDR);
1696 out_word(ioaddr+LANCE_DATA, (unsigned short)(l >> 16));
1697 out_word(ioaddr+LANCE_ADDR, 0x4);
1698 (void)in_word(ioaddr+LANCE_ADDR);
1699 out_word(ioaddr+LANCE_DATA, 0x915);
1700 out_word(ioaddr+LANCE_ADDR, 0x0);
1701 (void)in_word(ioaddr+LANCE_ADDR);
1703 /* ============= Get MAC address (cf. lance_probe1) ================ */
1704 for (i = 0; i < 6; ++i)
1705 ec->mac_address.ea_addr[i]=in_byte(ioaddr+LANCE_ETH_ADDR+i);
1707 /* ============ (re)start init_block(cf. lance_reset) =============== */
1708 /* Reset the LANCE */
1709 (void)in_word(ioaddr+LANCE_RESET);
1711 /* ----- Re-initialize the LANCE ----- */
1712 /* Set station address */
1713 for (i = 0; i < 6; ++i)
1714 lp->init_block.phys_addr[i] = ec->mac_address.ea_addr[i];
1715 /* Preset the receive ring headers */
1716 for (i=0; i<RX_RING_SIZE; i++) {
1717 lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
1718 /* OWN */
1719 lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff;
1720 /* we set the top byte as the very last thing */
1721 lp->rx_ring[i].u.addr[3] = 0x80;
1723 /* Preset the transmitting ring headers */
1724 for (i=0; i<TX_RING_SIZE; i++) {
1725 lp->tx_ring[i].u.base = 0;
1726 isstored[i] = 0;
1728 lp->init_block.mode = 0x0; /* enable Rx and Tx */
1730 l = (Address)virt_to_bus(&lp->init_block);
1731 out_word(ioaddr+LANCE_ADDR, 0x1);
1732 (void)in_word(ioaddr+LANCE_ADDR);
1733 out_word(ioaddr+LANCE_DATA, (short)l);
1734 out_word(ioaddr+LANCE_ADDR, 0x2);
1735 (void)in_word(ioaddr+LANCE_ADDR);
1736 out_word(ioaddr+LANCE_DATA, (short)(l >> 16));
1737 out_word(ioaddr+LANCE_ADDR, 0x4);
1738 (void)in_word(ioaddr+LANCE_ADDR);
1739 out_word(ioaddr+LANCE_DATA, 0x915);
1740 out_word(ioaddr+LANCE_ADDR, 0x0);
1741 (void)in_word(ioaddr+LANCE_ADDR);
1743 /* ----- start when init done. ----- */
1744 out_word(ioaddr+LANCE_DATA, 0x4); /* stop */
1745 out_word(ioaddr+LANCE_DATA, 0x1); /* init */
1746 for (i = 10000; i > 0; --i)
1747 if (in_word(ioaddr+LANCE_DATA) & 0x100)
1748 break;
1750 /* Set 'Multicast Table' */
1751 for (i=0;i<4;++i)
1753 out_word(ioaddr+LANCE_ADDR, 0x8 + i);
1754 out_word(ioaddr+LANCE_DATA, 0xffff);
1757 /* Set 'Receive Mode' */
1758 if (ec->flags & ECF_PROMISC)
1760 out_word(ioaddr+LANCE_ADDR, 0xf);
1761 out_word(ioaddr+LANCE_DATA, 0x8000);
1763 else
1765 if (ec->flags & (ECF_BROAD | ECF_MULTI))
1767 out_word(ioaddr+LANCE_ADDR, 0xf);
1768 out_word(ioaddr+LANCE_DATA, 0x0000);
1770 else
1772 out_word(ioaddr+LANCE_ADDR, 0xf);
1773 out_word(ioaddr+LANCE_DATA, 0x4000);
1777 out_word(ioaddr+LANCE_ADDR, 0x0);
1778 (void)in_word(ioaddr+LANCE_ADDR);
1779 out_word(ioaddr+LANCE_DATA, 0x142); /* start && enable interrupt */
1781 return;