xref: /minix/minix/drivers/net/lance/lance.c (revision bb9622b5)
1 /*
2  * lance.c
3  *
4  * This file contains a ethernet device driver for AMD LANCE based ethernet
5  * cards.
6  *
7  * Created: Jul 27, 2002 by Kazuya Kodama <kazuya@nii.ac.jp>
8  * Adapted for Minix 3: Sep 05, 2005 by Joren l'Ami <jwlami@cs.vu.nl>
9  */
10 
11 #define VERBOSE 0 /* Verbose debugging output */
12 #define LANCE_FKEY 0 /* Use function key to dump Lance stats */
13 
14 #include <minix/drivers.h>
15 #include <minix/netdriver.h>
16 
17 #include <assert.h>
18 
19 #include <minix/syslib.h>
20 #include <minix/endpoint.h>
21 #include <machine/pci.h>
22 #include <minix/ds.h>
23 
24 #include "lance.h"
25 
26 static int do_init(unsigned int instance, netdriver_addr_t *addr,
27 	uint32_t *caps, unsigned int *ticks);
28 static void ec_confaddr(netdriver_addr_t *addr, unsigned int instance);
29 static void ec_reinit(ether_card_t *ec);
30 static void do_intr(unsigned int mask);
31 static void do_set_mode(unsigned int mode, const netdriver_addr_t *mcast_list,
32 	unsigned int mcast_count);
33 static int do_send(struct netdriver_data *data, size_t size);
34 static ssize_t do_recv(struct netdriver_data *data, size_t max);
35 static void do_stop(void);
36 static void lance_dump(void);
37 static void do_other(const message *m_ptr, int ipc_status);
38 static void get_addressing(int devind, ether_card_t *ec);
39 static int lance_probe(ether_card_t *ec, unsigned int skip);
40 static void lance_init_hw(ether_card_t *ec, netdriver_addr_t *addr,
41 	unsigned int instance);
42 
43 /* Accesses Lance Control and Status Registers */
44 static u8_t in_byte(port_t port);
45 static u16_t in_word(port_t port);
46 static void out_word(port_t port, u16_t value);
47 static u16_t read_csr(port_t ioaddr, u16_t csrno);
48 static void write_csr(port_t ioaddr, u16_t csrno, u16_t value);
49 
50 static ether_card_t ec_state;
51 
52 /* --- LANCE --- */
53 /* General */
54 typedef uint32_t Address;
55 
56 #define ETH_FRAME_LEN           1518
57 
58 #define LANCE_MUST_PAD          0x00000001
59 #define LANCE_ENABLE_AUTOSELECT 0x00000002
60 #define LANCE_SELECT_PHONELINE  0x00000004
61 #define LANCE_MUST_UNRESET      0x00000008
62 
63 static const struct lance_chip_type
64 {
65    int        id_number;
66    const char *name;
67    int        flags;
68 } chip_table[] = {
69    {0x0000, "LANCE 7990",           /* Ancient lance chip.  */
70     LANCE_MUST_PAD + LANCE_MUST_UNRESET},
71    {0x0003, "PCnet/ISA 79C960",     /* 79C960 PCnet/ISA.  */
72     LANCE_ENABLE_AUTOSELECT},
73    {0x2260, "PCnet/ISA+ 79C961",    /* 79C961 PCnet/ISA+, Plug-n-Play.  */
74     LANCE_ENABLE_AUTOSELECT},
75    {0x2420, "PCnet/PCI 79C970",     /* 79C970 or 79C974 PCnet-SCSI, PCI. */
76     LANCE_ENABLE_AUTOSELECT},
77    {0x2430, "PCnet32",              /* 79C965 PCnet for VL bus. */
78     LANCE_ENABLE_AUTOSELECT},
79    {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */
80     LANCE_ENABLE_AUTOSELECT},
81    {0x2625, "PCnet-FAST III 79C973",/* 79C973 PCInet-FAST III. */
82     LANCE_ENABLE_AUTOSELECT},
83    {0x2626, "PCnet/HomePNA 79C978",
84     LANCE_ENABLE_AUTOSELECT|LANCE_SELECT_PHONELINE},
85    {0x0, "PCnet (unknown)",
86     LANCE_ENABLE_AUTOSELECT},
87 };
88 
89 /* ############## for LANCE device ############## */
90 #define LANCE_ETH_ADDR          0x0
91 #define LANCE_DATA              0x10
92 #define LANCE_ADDR              0x12
93 #define LANCE_RESET             0x14
94 #define LANCE_BUS_IF            0x16
95 #define LANCE_TOTAL_SIZE        0x18
96 
97 /* Use 2^4=16 {Rx,Tx} buffers */
98 #define LANCE_LOG_RX_BUFFERS    4
99 #define RX_RING_SIZE            (1 << (LANCE_LOG_RX_BUFFERS))
100 #define RX_RING_MOD_MASK        (RX_RING_SIZE - 1)
101 #define RX_RING_LEN_BITS        ((LANCE_LOG_RX_BUFFERS) << 29)
102 
103 #define LANCE_LOG_TX_BUFFERS    4
104 #define TX_RING_SIZE            (1 << (LANCE_LOG_TX_BUFFERS))
105 #define TX_RING_MOD_MASK        (TX_RING_SIZE - 1)
106 #define TX_RING_LEN_BITS        ((LANCE_LOG_TX_BUFFERS) << 29)
107 
108 /* for lance_interface */
109 struct lance_init_block
110 {
111    unsigned short  mode;
112    unsigned char   phys_addr[6];
113    unsigned long   filter[2];
114    Address         rx_ring;
115    Address         tx_ring;
116 };
117 
118 struct lance_rx_head
119 {
120    union {
121       Address         base;
122       unsigned char   addr[4];
123    } u;
124    short           buf_length;     /* 2s complement */
125    short           msg_length;
126 };
127 
128 struct lance_tx_head
129 {
130    union {
131       Address         base;
132       unsigned char   addr[4];
133    } u;
134    short           buf_length;     /* 2s complement */
135    short           misc;
136 };
137 
138 struct lance_interface
139 {
140    struct lance_init_block init_block;
141    struct lance_rx_head    rx_ring[RX_RING_SIZE];
142    struct lance_tx_head    tx_ring[TX_RING_SIZE];
143    unsigned char           rbuf[RX_RING_SIZE][ETH_FRAME_LEN];
144    unsigned char           tbuf[TX_RING_SIZE][ETH_FRAME_LEN];
145 };
146 
147 /* =============== global variables =============== */
148 /* AKA the stuff that really should have been in ether_card_t */
149 static struct lance_interface  *lp;
150 #define LANCE_BUF_SIZE (sizeof(struct lance_interface))
151 static char *lance_buf = NULL;
152 static int rx_slot_nr = 0;          /* Rx-slot number */
153 static int tx_slot_nr = 0;          /* Tx-slot number */
154 static int cur_tx_slot_nr = 0;      /* Tx-slot number */
155 static phys_bytes tx_ring_base[TX_RING_SIZE]; /* Tx-slot physical address */
156 static char isstored[TX_RING_SIZE]; /* Tx-slot in-use */
157 
158 static const struct netdriver lance_table = {
159 	.ndr_name	= "le",
160 	.ndr_init	= do_init,
161 	.ndr_stop	= do_stop,
162 	.ndr_set_mode	= do_set_mode,
163 	.ndr_recv	= do_recv,
164 	.ndr_send	= do_send,
165 	.ndr_intr	= do_intr,
166 	.ndr_other	= do_other,
167 };
168 
169 /*===========================================================================*
170  *                              main                                         *
171  *===========================================================================*/
172 int main(int argc, char **argv)
173 {
174 
175    env_setargs(argc, argv);
176 
177    netdriver_task(&lance_table);
178 
179    return 0;
180 }
181 
182 /*===========================================================================*
183  *                              lance_dump                                   *
184  *===========================================================================*/
185 static void lance_dump()
186 {
187    ether_card_t *ec;
188    int isr, csr;
189    unsigned short ioaddr;
190 
191    printf("\n");
192    ec = &ec_state;
193 
194    printf("lance driver %s:\n", netdriver_name());
195 
196    ioaddr = ec->ec_port;
197    isr = read_csr(ioaddr, LANCE_CSR0);
198    printf("isr = 0x%x, mode = 0x%x\n", isr, ec->ec_mode);
199 
200    printf("irq = %d\tioadr = 0x%x\n", ec->ec_irq, ec->ec_port);
201 
202    csr = read_csr(ioaddr, LANCE_CSR0);
203    printf("CSR0: 0x%x\n", csr);
204    csr = read_csr(ioaddr, LANCE_CSR3);
205    printf("CSR3: 0x%x\n", csr);
206    csr = read_csr(ioaddr, LANCE_CSR4);
207    printf("CSR4: 0x%x\n", csr);
208    csr = read_csr(ioaddr, LANCE_CSR5);
209    printf("CSR5: 0x%x\n", csr);
210    csr = read_csr(ioaddr, LANCE_CSR15);
211    printf("CSR15: 0x%x\n", csr);
212 }
213 
214 /*===========================================================================*
215  *                              do_other                                     *
216  *===========================================================================*/
217 static void do_other(const message *m_ptr, int ipc_status)
218 {
219 
220    if (is_ipc_notify(ipc_status) && m_ptr->m_source == TTY_PROC_NR)
221       lance_dump();
222 }
223 
224 /*===========================================================================*
225  *                              ec_confaddr                                  *
226  *===========================================================================*/
227 static void ec_confaddr(netdriver_addr_t *addr, unsigned int instance)
228 {
229    int i;
230    char eakey[16];
231    static char eafmt[]= "x:x:x:x:x:x";
232    long v;
233 
234    /* User defined ethernet address? */
235    strlcpy(eakey, "LANCE0_EA", sizeof(eakey));
236    eakey[5] += instance;
237 
238    for (i = 0; i < 6; i++)
239    {
240       v= addr->na_addr[i];
241       if (env_parse(eakey, eafmt, i, &v, 0x00L, 0xFFL) != EP_SET)
242          break;
243       addr->na_addr[i]= v;
244    }
245 
246    if (i != 0 && i != 6)
247    {
248       /* It's all or nothing; force a panic. */
249       panic("invalid ethernet address supplied");
250    }
251 }
252 
253 /*===========================================================================*
254  *		                do_init                                      *
255  *===========================================================================*/
256 static int do_init(unsigned int instance, netdriver_addr_t *addr,
257 	uint32_t *caps, unsigned int *ticks __unused)
258 {
259 /* Initialize the lance driver. */
260    ether_card_t *ec;
261 #if VERBOSE
262    int i;
263 #endif
264 #if LANCE_FKEY
265    int r, fkeys, sfkeys;
266 #endif
267 
268 #if LANCE_FKEY
269    fkeys = sfkeys = 0;
270    bit_set( sfkeys, 7 );
271    if ( (r = fkey_map(&fkeys, &sfkeys)) != OK )
272       printf("Warning: lance couldn't observe Shift+F7 key: %d\n",r);
273 #endif
274 
275    /* Initialize the driver state. */
276    ec= &ec_state;
277    memset(ec, 0, sizeof(*ec));
278 
279    /* See if there is a matching card. */
280    if (!lance_probe(ec, instance))
281       return ENXIO;
282 
283    /* Initialize the hardware. */
284    lance_init_hw(ec, addr, instance);
285 
286 #if VERBOSE
287    printf("%s: Ethernet address ", netdriver_name());
288    for (i= 0; i < 6; i++)
289       printf("%x%c", addr->na_addr[i], i < 5 ? ':' : '\n');
290 #endif
291 
292    *caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
293    return OK;
294 }
295 
296 /*===========================================================================*
297  *                              ec_reinit                                    *
298  *===========================================================================*/
299 static void ec_reinit(ether_card_t *ec)
300 {
301    spin_t spin;
302    int i;
303    unsigned short ioaddr = ec->ec_port;
304 
305    /* stop */
306    write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
307    /* init */
308    write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_INIT);
309    /* poll for IDON */
310    SPIN_FOR(&spin, 1000) {
311       if (read_csr(ioaddr, LANCE_CSR0) & LANCE_CSR0_IDON)
312          break;
313    }
314 
315    /* Set 'Multicast Table' */
316    for (i=0;i<4;++i)
317    {
318       write_csr(ioaddr, LANCE_CSR8 + i, 0xffff);
319    }
320 
321    /* Set 'Receive Mode' */
322    if (ec->ec_mode & NDEV_MODE_PROMISC)
323    {
324       write_csr(ioaddr, LANCE_CSR15, LANCE_CSR15_PROM);
325    }
326    else
327    {
328       if (ec->ec_mode &
329           (NDEV_MODE_BCAST | NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
330       {
331          write_csr(ioaddr, LANCE_CSR15, 0x0000);
332       }
333       else
334       {
335          write_csr(ioaddr, LANCE_CSR15, LANCE_CSR15_DRCVBC);
336       }
337    }
338 
339    /* purge Tx-ring */
340    tx_slot_nr = cur_tx_slot_nr = 0;
341    for (i=0; i<TX_RING_SIZE; i++)
342    {
343       lp->tx_ring[i].u.base = 0;
344       isstored[i]=0;
345    }
346    cur_tx_slot_nr = tx_slot_nr;
347 
348    /* re-init Rx-ring */
349    rx_slot_nr = 0;
350    for (i=0; i<RX_RING_SIZE; i++)
351    {
352       lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
353       lp->rx_ring[i].u.addr[3] |= 0x80;
354    }
355 
356    /* start && enable interrupt */
357    write_csr(ioaddr, LANCE_CSR0,
358              LANCE_CSR0_IDON|LANCE_CSR0_IENA|LANCE_CSR0_STRT);
359 
360    return;
361 }
362 
363 /*===========================================================================*
364  *                              do_set_mode                                    *
365  *===========================================================================*/
366 static void do_set_mode(unsigned int mode,
367 	const netdriver_addr_t *mcast_list __unused,
368 	unsigned int mcast_count __unused)
369 {
370    ether_card_t *ec;
371 
372    ec = &ec_state;
373 
374    ec->ec_mode = mode;
375 
376    ec_reinit(ec);
377 }
378 
379 /*===========================================================================*
380  *                              do_intr                                      *
381  *===========================================================================*/
382 static void do_intr(unsigned int __unused mask)
383 {
384    ether_card_t *ec;
385    int must_restart = 0;
386    int r, check, status;
387    int isr = 0x0000;
388    unsigned short ioaddr;
389 
390    ec = &ec_state;
391    ioaddr = ec->ec_port;
392 
393    for (;;)
394    {
395 #if VERBOSE
396       printf("ETH: Reading ISR...");
397 #endif
398       isr = read_csr(ioaddr, LANCE_CSR0);
399       if (isr & (LANCE_CSR0_ERR|LANCE_CSR0_RINT|LANCE_CSR0_TINT)) {
400          write_csr(ioaddr, LANCE_CSR0,
401                    isr & ~(LANCE_CSR0_IENA|LANCE_CSR0_TDMD|LANCE_CSR0_STOP
402                            |LANCE_CSR0_STRT|LANCE_CSR0_INIT) );
403       }
404       write_csr(ioaddr, LANCE_CSR0,
405                 LANCE_CSR0_BABL|LANCE_CSR0_CERR|LANCE_CSR0_MISS|LANCE_CSR0_MERR
406                 |LANCE_CSR0_IDON|LANCE_CSR0_IENA);
407 
408       if ((isr & (LANCE_CSR0_TINT|LANCE_CSR0_RINT|LANCE_CSR0_MISS
409                   |LANCE_CSR0_BABL|LANCE_CSR0_ERR)) == 0x0000)
410       {
411 #if VERBOSE
412          printf("OK\n");
413 #endif
414          break;
415       }
416 
417       if (isr & LANCE_CSR0_MISS)
418       {
419 #if VERBOSE
420          printf("RX Missed Frame\n");
421 #endif
422          netdriver_stat_ierror(1);
423       }
424       if ((isr & LANCE_CSR0_BABL) || (isr & LANCE_CSR0_TINT))
425       {
426          if (isr & LANCE_CSR0_BABL)
427          {
428 #if VERBOSE
429             printf("TX Timeout\n");
430 #endif
431             netdriver_stat_oerror(1);
432          }
433          if (isr & LANCE_CSR0_TINT)
434          {
435 #if VERBOSE
436             printf("TX INT\n");
437 #endif
438             /* status check: restart if needed. */
439             status = lp->tx_ring[cur_tx_slot_nr].u.base;
440 
441             /* did an error (UFLO, LCOL, LCAR, RTRY) occur? */
442             if (status & 0x40000000)
443             {
444                status = lp->tx_ring[cur_tx_slot_nr].misc;
445                netdriver_stat_oerror(1);
446                if (status & 0x4000) /* UFLO */
447                {
448                   must_restart=1;
449                }
450             }
451             else
452             {
453                if (status & 0x18000000)
454                   netdriver_stat_coll(1);
455             }
456          }
457          /* transmit a packet on the next slot if it exists. */
458          check = 0;
459          if (isstored[cur_tx_slot_nr]==1)
460          {
461             /* free the tx-slot just transmitted */
462             isstored[cur_tx_slot_nr]=0;
463             cur_tx_slot_nr = (cur_tx_slot_nr + 1) & TX_RING_MOD_MASK;
464 
465             /* next tx-slot is ready? */
466             if (isstored[cur_tx_slot_nr]==1)
467                check=1;
468             else
469                check=0;
470          }
471          else
472          {
473             panic("got premature TX INT..");
474          }
475          if (check==1)
476          {
477             lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;
478             write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_IENA|LANCE_CSR0_TDMD);
479          }
480          /* we set a buffered message in the slot if it exists. */
481          /* and transmit it, if needed. */
482          if (!must_restart)
483             netdriver_send();
484       }
485       if (isr & LANCE_CSR0_RINT)
486       {
487 #if VERBOSE
488          printf("RX INT\n");
489 #endif
490          netdriver_recv();
491       }
492 
493       if (must_restart == 1)
494       {
495 #if VERBOSE
496          printf("ETH: restarting...\n");
497 #endif
498 
499          ec_reinit(ec);
500 
501 	 /* store a buffered message on the slot if it exists */
502 	 netdriver_send();
503       }
504    }
505 
506    /* reenable interrupts */
507    if ((r = sys_irqenable(&ec->ec_hook)) != OK)
508       panic("couldn't enable interrupt: %d", r);
509 }
510 
511 /*===========================================================================*
512  *                              do_recv                                      *
513  *===========================================================================*/
514 static ssize_t do_recv(struct netdriver_data *data, size_t max)
515 {
516    ether_card_t *ec;
517    vir_bytes length;
518    int packet_processed;
519    int status;
520    unsigned short ioaddr;
521 
522    ec = &ec_state;
523    ioaddr = ec->ec_port;
524 
525    /* we check all the received slots until find a properly received packet */
526    packet_processed = FALSE;
527    while (!packet_processed)
528    {
529       status = lp->rx_ring[rx_slot_nr].u.base >> 24;
530 
531       /* is the slot marked as ready? */
532       if ( (status & 0x80) != 0x00 )
533          return SUSPEND; /* no */
534 
535       /* did an error occur? */
536       if (status != 0x03)
537       {
538          if (status & 0x01)
539             netdriver_stat_ierror(1);
540          length = 0;
541       }
542       else
543       {
544          length = lp->rx_ring[rx_slot_nr].msg_length;
545       }
546 
547       /* do we now have a valid packet? */
548       if (length > 0)
549       {
550 	 if (length > max)
551 	    length = max;
552          netdriver_copyout(data, 0, lp->rbuf[rx_slot_nr], length);
553          packet_processed = TRUE;
554       }
555 
556       /* set up this slot again, and we move to the next slot */
557       lp->rx_ring[rx_slot_nr].buf_length = -ETH_FRAME_LEN;
558       lp->rx_ring[rx_slot_nr].u.addr[3] |= 0x80;
559 
560       write_csr(ioaddr, LANCE_CSR0,
561                 LANCE_CSR0_BABL|LANCE_CSR0_CERR|LANCE_CSR0_MISS
562                 |LANCE_CSR0_MERR|LANCE_CSR0_IDON|LANCE_CSR0_IENA);
563 
564       rx_slot_nr = (rx_slot_nr + 1) & RX_RING_MOD_MASK;
565    }
566 
567    /* return the length of the packet we have received */
568    return length;
569 }
570 
571 /*===========================================================================*
572  *                              do_send                                      *
573  *===========================================================================*/
574 static int do_send(struct netdriver_data *data, size_t size)
575 {
576    int check;
577    ether_card_t *ec;
578    unsigned short ioaddr;
579 
580    ec = &ec_state;
581 
582    /* if all slots are used, this request must be deferred */
583    if (isstored[tx_slot_nr]==1)
584       return SUSPEND;
585 
586    /* copy the packet to the slot on DMA address */
587    netdriver_copyin(data, 0, lp->tbuf[tx_slot_nr], size);
588 
589    /* set-up for transmitting, and transmit it if needed. */
590    lp->tx_ring[tx_slot_nr].buf_length = -size;
591    lp->tx_ring[tx_slot_nr].misc = 0x0;
592    lp->tx_ring[tx_slot_nr].u.base = tx_ring_base[tx_slot_nr];
593    isstored[tx_slot_nr]=1;
594    if (cur_tx_slot_nr == tx_slot_nr)
595       check=1;
596    else
597       check=0;
598    tx_slot_nr = (tx_slot_nr + 1) & TX_RING_MOD_MASK;
599 
600    if (check == 1)
601    {
602       ioaddr = ec->ec_port;
603       lp->tx_ring[cur_tx_slot_nr].u.addr[3] = 0x83;
604       write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_IENA|LANCE_CSR0_TDMD);
605    }
606 
607    return OK;
608 }
609 
610 /*===========================================================================*
611  *                              do_stop                                      *
612  *===========================================================================*/
613 static void do_stop(void)
614 {
615    ether_card_t *ec;
616    unsigned short ioaddr;
617 
618    ec = &ec_state;
619 
620    ioaddr = ec->ec_port;
621 
622    /* stop */
623    write_csr(ioaddr, LANCE_CSR0, LANCE_CSR0_STOP);
624 
625    /* Reset */
626    in_word(ioaddr+LANCE_RESET);
627 }
628 
629 /*===========================================================================*
630  *                              get_addressing                               *
631  *===========================================================================*/
632 static void get_addressing(int devind, ether_card_t *ec)
633 {
634    unsigned int ioaddr;
635    int reg, irq;
636 
637    for (reg = PCI_BAR; reg <= PCI_BAR_6; reg += 4)
638    {
639       ioaddr = pci_attr_r32(devind, reg);
640 
641       if ((ioaddr & PCI_BAR_IO_MASK) == 0 || (ioaddr & PCI_BAR_IO) == 0)
642          continue;
643       /* Strip the I/O address out of the returned value */
644       ioaddr &= PCI_BAR_IO_MASK;
645       ec->ec_port = ioaddr;
646    }
647 
648    /* KK: Get the IRQ number */
649    irq = pci_attr_r8(devind, PCI_IPR);
650    if (irq)
651       irq = pci_attr_r8(devind, PCI_ILR);
652    ec->ec_irq = irq;
653 }
654 
655 /*===========================================================================*
656  *                              lance_probe                                  *
657  *===========================================================================*/
658 static int lance_probe(ether_card_t *ec, unsigned int skip)
659 {
660    unsigned short    pci_cmd;
661    unsigned short    ioaddr;
662    int               lance_version, chip_version;
663    int devind, r;
664    u16_t vid, did;
665 
666    pci_init();
667 
668    r= pci_first_dev(&devind, &vid, &did);
669    if (r == 0)
670       return 0;
671 
672    while (skip--)
673    {
674       r= pci_next_dev(&devind, &vid, &did);
675       if (!r)
676          return 0;
677    }
678 
679    pci_reserve(devind);
680 
681    get_addressing(devind, ec);
682 
683    /* ===== Bus Master ? ===== */
684    pci_cmd = pci_attr_r32(devind, PCI_CR);
685    if (!(pci_cmd & PCI_CR_MAST_EN)) {
686       pci_cmd |= PCI_CR_MAST_EN;
687       pci_attr_w32(devind, PCI_CR, pci_cmd);
688    }
689 
690    /* ===== Probe Details ===== */
691    ioaddr = ec->ec_port;
692 
693    /* Reset */
694    in_word(ioaddr+LANCE_RESET);
695 
696    if (read_csr(ioaddr, LANCE_CSR0) != LANCE_CSR0_STOP)
697    {
698       return 0;
699    }
700 
701    /* Probe Chip Version */
702    out_word(ioaddr+LANCE_ADDR, 88);     /* Get the version of the chip */
703    if (in_word(ioaddr+LANCE_ADDR) != 88)
704       lance_version = 0;
705    else
706    {
707       chip_version = read_csr(ioaddr, LANCE_CSR88);
708       chip_version |= read_csr(ioaddr, LANCE_CSR89) << 16;
709 
710       if ((chip_version & 0xfff) != 0x3)
711       {
712 	 return 0;
713       }
714       chip_version = (chip_version >> 12) & 0xffff;
715       for (lance_version = 1; chip_table[lance_version].id_number != 0;
716            ++lance_version)
717          if (chip_table[lance_version].id_number == chip_version)
718             break;
719    }
720 
721 #if VERBOSE
722    printf("%s: %s at %X:%d\n",
723           netdriver_name(), chip_table[lance_version].name,
724           ec->ec_port, ec->ec_irq);
725 #endif
726 
727    return lance_version;
728 }
729 
730 /*===========================================================================*
731  *                              virt_to_bus                                  *
732  *===========================================================================*/
733 static phys_bytes virt_to_bus(void *ptr)
734 {
735    phys_bytes value;
736    int r;
737 
738    if ((r = sys_umap(SELF, VM_D, (vir_bytes)ptr, 4, &value)) != OK)
739       panic("sys_umap failed: %d", r);
740 
741    return value;
742 }
743 
744 /*===========================================================================*
745  *                              lance_init_hw                                *
746  *===========================================================================*/
747 static void lance_init_hw(ether_card_t *ec, netdriver_addr_t *addr,
748 	unsigned int instance)
749 {
750    phys_bytes lance_buf_phys;
751    int i, r;
752    Address l;
753    unsigned short ioaddr = ec->ec_port;
754 
755    /* ============= setup init_block(cf. lance_probe1) ================ */
756    /* make sure data structure is 8-byte aligned and below 16MB (for DMA) */
757 
758    /* Allocate memory */
759    if ((lance_buf = alloc_contig(LANCE_BUF_SIZE, AC_ALIGN4K|AC_LOWER16M,
760      &lance_buf_phys)) == NULL)
761       panic("alloc_contig failed: %d", LANCE_BUF_SIZE);
762 
763    l = (vir_bytes)lance_buf;
764    lp = (struct lance_interface *)l;
765 
766    /* disable Tx and Rx */
767    lp->init_block.mode = LANCE_CSR15_DTX|LANCE_CSR15_DRX;
768    lp->init_block.filter[0] = lp->init_block.filter[1] = 0x0;
769    /* using multiple Rx/Tx buffer */
770    lp->init_block.rx_ring
771       = (virt_to_bus(&lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS;
772    lp->init_block.tx_ring
773       = (virt_to_bus(&lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS;
774 
775    l = virt_to_bus(&lp->init_block);
776    write_csr(ioaddr, LANCE_CSR1, (unsigned short)l);
777    write_csr(ioaddr, LANCE_CSR2, (unsigned short)(l >> 16));
778    write_csr(ioaddr, LANCE_CSR4,
779              LANCE_CSR4_APAD_XMT|LANCE_CSR4_MFCOM|LANCE_CSR4_RCVCCOM
780              |LANCE_CSR4_TXSTRTM|LANCE_CSR4_JABM);
781 
782    /* ============= Get MAC address (cf. lance_probe1) ================ */
783    for (i = 0; i < 6; ++i)
784       addr->na_addr[i]=in_byte(ioaddr+LANCE_ETH_ADDR+i);
785 
786    /* Allow the user to override the hardware address. */
787    ec_confaddr(addr, instance);
788 
789    /* ============ (re)start init_block(cf. lance_reset) =============== */
790    /* Reset the LANCE */
791    (void)in_word(ioaddr+LANCE_RESET);
792 
793    /* ----- Re-initialize the LANCE ----- */
794    /* Set station address */
795    for (i = 0; i < 6; ++i)
796       lp->init_block.phys_addr[i] = addr->na_addr[i];
797    /* Preset the receive ring headers */
798    for (i=0; i<RX_RING_SIZE; i++)
799    {
800       lp->rx_ring[i].buf_length = -ETH_FRAME_LEN;
801       /* OWN */
802       lp->rx_ring[i].u.base = virt_to_bus(lp->rbuf[i]) & 0xffffff;
803       /* we set the top byte as the very last thing */
804       lp->rx_ring[i].u.addr[3] = 0x80;
805    }
806    /* Preset the transmitting ring headers */
807    for (i=0; i<TX_RING_SIZE; i++)
808    {
809       lp->tx_ring[i].u.base = 0;
810       tx_ring_base[i] = virt_to_bus(lp->tbuf[i]) & 0xffffff;
811       isstored[i] = 0;
812    }
813    /* enable Rx and Tx */
814    lp->init_block.mode = 0x0;
815 
816    l = (Address)virt_to_bus(&lp->init_block);
817    write_csr(ioaddr, LANCE_CSR1, (short)l);
818    write_csr(ioaddr, LANCE_CSR2, (short)(l >> 16));
819    write_csr(ioaddr, LANCE_CSR4,
820              LANCE_CSR4_APAD_XMT|LANCE_CSR4_MFCOM|LANCE_CSR4_RCVCCOM
821              |LANCE_CSR4_TXSTRTM|LANCE_CSR4_JABM);
822 
823    /* ----- start when init done. ----- */
824    ec_reinit(ec);
825 
826    /* Set the interrupt handler */
827    ec->ec_hook = ec->ec_irq;
828    if ((r=sys_irqsetpolicy(ec->ec_irq, 0, &ec->ec_hook)) != OK)
829       panic("couldn't set IRQ policy: %d", r);
830    if ((r = sys_irqenable(&ec->ec_hook)) != OK)
831       panic("couldn't enable interrupt: %d", r);
832 
833    /* start && enable interrupt */
834    write_csr(ioaddr, LANCE_CSR0,
835              LANCE_CSR0_IDON|LANCE_CSR0_IENA|LANCE_CSR0_STRT);
836 }
837 
838 /*===========================================================================*
839  *                              in_byte                                      *
840  *===========================================================================*/
841 static u8_t in_byte(port_t port)
842 {
843 	int r;
844 	u32_t value;
845 
846 	r= sys_inb(port, &value);
847 	if (r != OK)
848 		panic("sys_inb failed: %d", r);
849 	return value;
850 }
851 
852 /*===========================================================================*
853  *                              in_word                                      *
854  *===========================================================================*/
855 static u16_t in_word(port_t port)
856 {
857 	int r;
858 	u32_t value;
859 
860 	r= sys_inw(port, &value);
861 	if (r != OK)
862 		panic("sys_inw failed: %d", r);
863 	return value;
864 }
865 
866 
867 /*===========================================================================*
868  *                              out_word                                     *
869  *===========================================================================*/
870 static void out_word(port_t port, u16_t value)
871 {
872 	int r;
873 
874 	r= sys_outw(port, value);
875 	if (r != OK)
876 		panic("sys_outw failed: %d", r);
877 }
878 
879 /*===========================================================================*
880  *                              read_csr                                     *
881  *===========================================================================*/
882 static u16_t read_csr(port_t ioaddr, u16_t csrno)
883 {
884    out_word(ioaddr+LANCE_ADDR, csrno);
885    return in_word(ioaddr+LANCE_DATA);
886 }
887 
888 /*===========================================================================*
889  *                              write_csr                                    *
890  *===========================================================================*/
891 static void write_csr(port_t ioaddr, u16_t csrno, u16_t value)
892 {
893    out_word(ioaddr+LANCE_ADDR, csrno);
894    out_word(ioaddr+LANCE_DATA, value);
895 }
896