1 /* $NetBSD: if_ef.c,v 1.29 2009/05/12 08:44:19 cegger Exp $ */
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: if_ef.c,v 1.29 2009/05/12 08:44:19 cegger Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
38 #include <sys/errno.h>
39 #include <sys/device.h>
40 #include <sys/protosw.h>
41 #include <sys/socket.h>
44 #include <net/if_dl.h>
45 #include <net/if_types.h>
46 #include <net/if_media.h>
47 #include <net/if_ether.h>
53 #include <dev/isa/isareg.h>
54 #include <dev/isa/isavar.h>
56 #include <dev/ic/i82586reg.h>
57 #include <dev/ic/i82586var.h>
58 #include <dev/isa/if_efreg.h>
59 #include <dev/isa/elink.h>
62 #define DPRINTF(x) printf x
68 struct ie_softc sc_ie
;
70 bus_space_tag_t sc_regt
; /* space tag for registers */
71 bus_space_handle_t sc_regh
; /* space handle for registers */
73 void* sc_ih
; /* interrupt handle */
75 u_int8_t card_rev
; /* hardware revision */
76 u_int8_t card_type
; /* card model -- AUI/BNC or TP */
83 #define NEF_MEDIA (sizeof(ef_media) / sizeof(ef_media[0]))
88 #define NEFTP_MEDIA (sizeof(eftp_media) / sizeof(eftp_media[0]))
90 /* Routines required by the MI i82586 driver API */
91 static void ef_reset(struct ie_softc
*, int);
92 static void ef_hwinit(struct ie_softc
*);
93 static void ef_atten(struct ie_softc
*, int);
94 static int ef_intrhook(struct ie_softc
*, int);
96 static void ef_copyin(struct ie_softc
*, void *, int, size_t);
97 static void ef_copyout(struct ie_softc
*, const void *, int, size_t);
99 static u_int16_t
ef_read_16(struct ie_softc
*, int);
100 static void ef_write_16(struct ie_softc
*, int, u_int16_t
);
101 static void ef_write_24(struct ie_softc
*, int, int);
103 static void ef_mediastatus(struct ie_softc
*, struct ifmediareq
*);
106 static int ef_port_check(bus_space_tag_t
, bus_space_handle_t
);
108 int ef_match(device_t
, cfdata_t
, void *);
109 void ef_attach(device_t
, device_t
, void *);
112 * This keeps track of which ISAs have been through an ie probe sequence.
113 * A simple static variable isn't enough, since it's conceivable that
114 * a system might have more than one ISA bus.
116 * The "isa_bus" member is a pointer to the parent ISA bus device struct
117 * which will unique per ISA bus.
120 #define MAXCARDS_PER_ISABUS 8 /* if you have more than 8, you lose */
123 LIST_ENTRY(ef_isabus
) isa_link
;
134 } isa_cards
[MAXCARDS_PER_ISABUS
];
137 static LIST_HEAD(, ef_isabus
) ef_isa_buses
;
138 static int ef_isa_buses_inited
;
142 struct ef_isabus
*bus
,
150 DPRINTF(("Adding 3c507 at 0x%x, IRQ %d, Mem 0x%lx/%ld\n",
151 (u_int
) iobase
, irq
, (u_long
) maddr
, msiz
));
153 for (idx
= 0; idx
< MAXCARDS_PER_ISABUS
; idx
++) {
154 if (bus
->isa_cards
[idx
].available
== 0) {
155 bus
->isa_cards
[idx
].iobase
= iobase
;
156 bus
->isa_cards
[idx
].maddr
= maddr
;
157 bus
->isa_cards
[idx
].msize
= msiz
;
158 bus
->isa_cards
[idx
].irq
= irq
;
159 bus
->isa_cards
[idx
].available
= 1;
166 * 3C507 support routines
169 ef_reset(struct ie_softc
*sc
, int why
)
171 struct ef_softc
* esc
= (struct ef_softc
*) sc
;
175 /* reset to chip to see if it responds */
176 bus_space_write_1(esc
->sc_regt
, esc
->sc_regh
,
177 EF_CTRL
, EF_CTRL_RESET
);
179 bus_space_write_1(esc
->sc_regt
, esc
->sc_regh
,
180 EF_CTRL
, EF_CTRL_NORMAL
);
186 * this takes around 10sec, and we can get
187 * by quite well w/out it...
194 ef_atten(struct ie_softc
*sc
, int why
)
196 struct ef_softc
* esc
= (struct ef_softc
*) sc
;
197 bus_space_write_1(esc
->sc_regt
, esc
->sc_regh
, EF_ATTN
, 1);
201 ef_hwinit(struct ie_softc
*sc
)
203 struct ef_softc
* esc
= (struct ef_softc
*) sc
;
204 bus_space_write_1(esc
->sc_regt
, esc
->sc_regh
, EF_ICTRL
, 1);
208 ef_intrhook(struct ie_softc
*sc
, int where
)
211 struct ef_softc
* esc
= (struct ef_softc
*) sc
;
215 /* entering ISR: disable, ack card interrupts */
216 cr
= bus_space_read_1(esc
->sc_regt
, esc
->sc_regh
, EF_CTRL
);
217 bus_space_write_1(esc
->sc_regt
, esc
->sc_regh
, EF_CTRL
,
219 bus_space_write_1(esc
->sc_regt
, esc
->sc_regh
, EF_ICTRL
, 1);
223 /* exiting ISR: re-enable card interrupts */
224 cr
= bus_space_read_1(esc
->sc_regt
, esc
->sc_regh
, EF_CTRL
);
225 bus_space_write_1(esc
->sc_regt
, esc
->sc_regh
, EF_CTRL
,
230 /* looping in ISR: ack new interrupts */
231 bus_space_write_1(esc
->sc_regt
, esc
->sc_regh
, EF_ICTRL
, 1);
239 ef_read_16 (struct ie_softc
*sc
, int offset
)
241 bus_space_barrier(sc
->bt
, sc
->bh
, offset
, 2, BUS_SPACE_BARRIER_READ
);
242 return bus_space_read_2(sc
->bt
, sc
->bh
, offset
);
246 ef_copyin (struct ie_softc
*sc
, void *dst
, int offset
, size_t size
)
249 u_int8_t
* bptr
= dst
;
251 bus_space_barrier(sc
->bt
, sc
->bh
, offset
, size
,
252 BUS_SPACE_BARRIER_READ
);
255 *bptr
= bus_space_read_1(sc
->bt
, sc
->bh
, offset
);
256 offset
++; bptr
++; size
--;
260 bus_space_read_region_2(sc
->bt
, sc
->bh
, offset
, (u_int16_t
*) bptr
,
266 *bptr
= bus_space_read_1(sc
->bt
, sc
->bh
, offset
);
271 ef_copyout (struct ie_softc
*sc
, const void *src
, int offset
, size_t size
)
275 int ooffset
= offset
;
276 const u_int8_t
* bptr
= src
;
279 bus_space_write_1(sc
->bt
, sc
->bh
, offset
, *bptr
);
280 offset
++; bptr
++; size
--;
284 bus_space_write_region_2(sc
->bt
, sc
->bh
, offset
,
285 (const u_int16_t
*)bptr
, size
>> 1);
289 bus_space_write_1(sc
->bt
, sc
->bh
, offset
, *bptr
);
292 bus_space_barrier(sc
->bt
, sc
->bh
, ooffset
, osize
,
293 BUS_SPACE_BARRIER_WRITE
);
297 ef_write_16 (struct ie_softc
*sc
, int offset
, u_int16_t value
)
299 bus_space_write_2(sc
->bt
, sc
->bh
, offset
, value
);
300 bus_space_barrier(sc
->bt
, sc
->bh
, offset
, 2, BUS_SPACE_BARRIER_WRITE
);
304 ef_write_24 (struct ie_softc
*sc
, int offset
, int addr
)
306 bus_space_write_4(sc
->bt
, sc
->bh
, offset
, addr
+
307 (u_long
) sc
->sc_maddr
- (u_long
) sc
->sc_iobase
);
308 bus_space_barrier(sc
->bt
, sc
->bh
, offset
, 4, BUS_SPACE_BARRIER_WRITE
);
312 ef_mediastatus(struct ie_softc
*sc
, struct ifmediareq
*ifmr
)
314 struct ifmedia
*ifm
= &sc
->sc_media
;
317 * The currently selected media is always the active media.
319 ifmr
->ifm_active
= ifm
->ifm_cur
->ifm_media
;
323 ef_match(device_t parent
, cfdata_t cf
, void *aux
)
325 struct isa_attach_args
* const ia
= aux
;
328 struct ef_isabus
*bus
;
330 bus_space_handle_t ioh
;
331 bus_space_tag_t iot
= ia
->ia_iot
;
333 if (ISA_DIRECT_CONFIG(ia
))
336 if (ef_isa_buses_inited
== 0) {
337 LIST_INIT(&ef_isa_buses
);
338 ef_isa_buses_inited
= 1;
342 * Probe this bus if we haven't done so already.
344 for (bus
= ef_isa_buses
.lh_first
; bus
!= NULL
;
345 bus
= bus
->isa_link
.le_next
) {
346 if (bus
->isa_bus
== parent
)
354 * Mark this bus so we don't probe it again.
356 bus
= (struct ef_isabus
*)
357 malloc(sizeof(struct ef_isabus
), M_DEVBUF
, M_NOWAIT
);
359 panic("ef_isa_probe: can't allocate state storage for %s",
360 device_xname(parent
));
362 bus
->bus_state
= 0; /* nothing done yet */
363 bus
->isa_bus
= parent
;
365 LIST_INSERT_HEAD(&ef_isa_buses
, bus
, isa_link
);
367 if (bus_space_map(iot
, ELINK_ID_PORT
, 1, 0, &ioh
)) {
368 DPRINTF(("3c507 probe: can't map Etherlink ID port\n"));
373 * Reset and put card in CONFIG state without
376 elink_reset(iot
, ioh
, device_unit(parent
));
377 elink_idseq(iot
, ioh
, ELINK_507_POLY
);
378 elink_idseq(iot
, ioh
, ELINK_507_POLY
);
379 bus_space_write_1(iot
, ioh
, 0, 0xff);
381 /* Unmap the ID port */
382 bus_space_unmap(iot
, ioh
, 1);
384 bus
->bus_state
++; /* cards now in CONFIG state */
386 for (iobase
= EF_IOBASE_LOW
; iobase
<= EF_IOBASE_HIGH
;
387 iobase
+= EF_IOSIZE
) {
389 * Map the 507's port-space for the probe sequence.
391 if (bus_space_map(iot
, iobase
, EF_IOSIZE
,
395 /* Now look for the 3Com magic bytes */
397 if (ef_port_check(iot
, ioh
)) {
402 bus_space_handle_t memh
;
404 irq
= bus_space_read_1(iot
, ioh
, EF_IRQ
) &
407 v
= bus_space_read_1(iot
, ioh
, EF_MADDR
);
408 maddr
= EF_MADDR_BASE
+
409 ((v
& EF_MADDR_MASK
) << EF_MADDR_SHIFT
);
410 msiz1
= ((v
& EF_MSIZE_MASK
) + 1) *
413 if (bus_space_map(ia
->ia_memt
, maddr
,
414 msiz1
, 0, &memh
) == 0) {
415 ef_card_add(bus
, iobase
, maddr
,
417 bus_space_unmap(ia
->ia_memt
,
421 bus_space_unmap(iot
, ioh
, EF_IOSIZE
);
427 if (ia
->ia_niomem
< 1)
432 for (idx
= 0; idx
< MAXCARDS_PER_ISABUS
; idx
++) {
433 if (bus
->isa_cards
[idx
].available
!= 1)
436 if (ia
->ia_io
[0].ir_addr
!= ISA_UNKNOWN_PORT
&&
437 ia
->ia_io
[0].ir_addr
!= bus
->isa_cards
[idx
].iobase
)
440 if (ia
->ia_iomem
[0].ir_addr
!= ISA_UNKNOWN_IOMEM
&&
441 ia
->ia_iomem
[0].ir_addr
!= bus
->isa_cards
[idx
].maddr
)
444 if (ia
->ia_irq
[0].ir_irq
!= ISA_UNKNOWN_IRQ
&&
445 ia
->ia_irq
[0].ir_irq
!= bus
->isa_cards
[idx
].irq
)
451 if (idx
== MAXCARDS_PER_ISABUS
)
454 bus
->isa_cards
[idx
].available
++;
457 ia
->ia_io
[0].ir_addr
= bus
->isa_cards
[idx
].iobase
;
458 ia
->ia_io
[0].ir_size
= EF_IOSIZE
;
461 ia
->ia_iomem
[0].ir_addr
= bus
->isa_cards
[idx
].maddr
;
462 ia
->ia_iomem
[0].ir_size
= bus
->isa_cards
[idx
].msize
;
465 ia
->ia_irq
[0].ir_irq
= bus
->isa_cards
[idx
].irq
;
473 ef_attach(device_t parent
, device_t self
, void *aux
)
475 struct ef_softc
*esc
= (void *)self
;
476 struct ie_softc
*sc
= &esc
->sc_ie
;
477 struct isa_attach_args
*ia
= aux
;
478 bus_space_tag_t iot
= ia
->ia_iot
;
482 struct ef_isabus
*bus
;
483 u_int8_t partno
[EF_TYPE_LEN
];
484 bus_space_handle_t ioh
, memh
;
485 u_int8_t ethaddr
[ETHER_ADDR_LEN
];
487 sc
->hwinit
= ef_hwinit
;
488 sc
->hwreset
= ef_reset
;
489 sc
->chan_attn
= ef_atten
;
490 sc
->intrhook
= ef_intrhook
;
492 sc
->ie_bus_barrier
= NULL
;
494 sc
->memcopyin
= ef_copyin
;
495 sc
->memcopyout
= ef_copyout
;
496 sc
->ie_bus_read16
= ef_read_16
;
497 sc
->ie_bus_write16
= ef_write_16
;
498 sc
->ie_bus_write24
= ef_write_24
;
503 * NOP chains don't give any advantage on this card, in fact they
504 * seem to slow it down some. As the doctor says, "if it hurts,
507 sc
->do_xmitnopchain
= 0;
509 sc
->sc_mediachange
= NULL
;
510 sc
->sc_mediastatus
= ef_mediastatus
;
512 /* Find the cards parent bus */
513 for (bus
= ef_isa_buses
.lh_first
; bus
!= NULL
;
514 bus
= bus
->isa_link
.le_next
) {
516 if (bus
->isa_bus
== parent
)
521 panic("%s: Can't find parent bus!", device_xname(&sc
->sc_dev
));
524 /* If the bus hasn't been transitioned to the RUN state, do so now */
525 if (bus
->bus_state
== 1) {
526 if (bus_space_map(iot
, ELINK_ID_PORT
, 1, 0, &ioh
) != 0) {
527 DPRINTF(("\n%s: Can't map Elink ID port!\n",
528 device_xname(&sc
->sc_dev
)));
532 bus_space_write_1(ia
->ia_iot
, ioh
, 0, 0x00);
533 elink_idseq(ia
->ia_iot
, ioh
, ELINK_507_POLY
);
534 bus_space_write_1(ia
->ia_iot
, ioh
, 0, 0x00);
535 bus_space_unmap(ia
->ia_iot
, ioh
, 1);
541 if (bus_space_map(ia
->ia_iot
, ia
->ia_io
[0].ir_addr
,
542 ia
->ia_io
[0].ir_size
, 0, &ioh
) != 0) {
544 DPRINTF(("\n%s: can't map i/o space 0x%x-0x%x\n",
545 device_xname(&sc
->sc_dev
), ia
->ia_io
[0].ir_addr
,
546 ia
->ia_io
[0].ir_addr
+ ia
->ia_io
[0].ir_size
- 1));
550 esc
->sc_regt
= ia
->ia_iot
;
553 if (bus_space_map(ia
->ia_memt
, ia
->ia_iomem
[0].ir_addr
,
554 ia
->ia_iomem
[0].ir_size
, 0, &memh
) != 0) {
556 DPRINTF(("\n%s: can't map iomem space 0x%x-0x%x\n",
557 device_xname(&sc
->sc_dev
), ia
->ia_maddr
,
558 ia
->ia_maddr
+ ia
->ia_msize
- 1));
559 bus_space_unmap(ia
->ia_iot
, ioh
, ia
->ia_io
[0].ir_size
);
563 sc
->bt
= ia
->ia_memt
;
566 sc
->sc_msize
= ia
->ia_iomem
[0].ir_size
;
567 sc
->sc_maddr
= (void *)memh
;
568 sc
->sc_iobase
= (char *)sc
->sc_maddr
+ sc
->sc_msize
- (1 << 24);
570 /* set up pointers to important on-card control structures */
572 sc
->scb
= IE_ISCP_SZ
;
573 sc
->scp
= sc
->sc_msize
+ IE_SCP_ADDR
- (1 << 24);
575 sc
->buf_area
= sc
->scb
+ IE_SCB_SZ
;
576 sc
->buf_area_sz
= sc
->sc_msize
- IE_ISCP_SZ
- IE_SCB_SZ
- IE_SCP_SZ
;
578 /* zero card memory */
579 bus_space_set_region_1(sc
->bt
, sc
->bh
, 0, 0, sc
->sc_msize
);
581 /* set card to 16-bit bus mode */
582 bus_space_write_1(sc
->bt
, sc
->bh
, IE_SCP_BUS_USE((u_long
)sc
->scp
),
585 /* set up pointers to key structures */
586 ef_write_24(sc
, IE_SCP_ISCP((u_long
)sc
->scp
), (u_long
) sc
->iscp
);
587 ef_write_16(sc
, IE_ISCP_SCB((u_long
)sc
->iscp
), (u_long
) sc
->scb
);
588 ef_write_24(sc
, IE_ISCP_BASE((u_long
)sc
->iscp
), (u_long
) sc
->iscp
);
590 /* flush setup of pointers, check if chip answers */
591 bus_space_barrier(sc
->bt
, sc
->bh
, 0, sc
->sc_msize
,
592 BUS_SPACE_BARRIER_WRITE
);
593 if (!i82586_proberam(sc
)) {
594 DPRINTF(("\n%s: can't talk to i82586!\n",
595 device_xname(&sc
->sc_dev
)));
596 bus_space_unmap(ia
->ia_iot
, ioh
, ia
->ia_io
[0].ir_size
);
597 bus_space_unmap(ia
->ia_memt
, memh
, ia
->ia_iomem
[0].ir_size
);
601 /* set bank 2 for card part number and revision */
602 bus_space_write_1(esc
->sc_regt
, esc
->sc_regh
, EF_CTRL
,
603 EF_CTRL_NRST
| EF_CTRL_BNK2
);
605 /* card revision is encoded in BCD */
606 i
= bus_space_read_1(esc
->sc_regt
, esc
->sc_regh
, EF_REV
);
607 esc
->card_rev
= 10 * (i
/ 16) + (i
% 16);
609 for (i
= 0; i
< EF_TYPE_LEN
; i
++)
610 partno
[i
] = bus_space_read_1(esc
->sc_regt
, esc
->sc_regh
,
613 /* use part number to guess if card is TP or AUI/BNC model */
614 esc
->card_type
= EF_IS_TP(partno
) ? EF_CARD_TP
: EF_CARD_BNC
;
616 /* set bank 0 for ethernet address */
617 bus_space_write_1(esc
->sc_regt
, esc
->sc_regh
,
618 EF_CTRL
, EF_CTRL_NORMAL
);
620 for (i
= 0; i
< EF_ADDR_LEN
; i
++)
621 ethaddr
[i
] = bus_space_read_1(esc
->sc_regt
, esc
->sc_regh
,
624 snprintf(vers
, sizeof(vers
), "%s, rev. %d",
625 (esc
->card_type
== EF_CARD_TP
) ? "3C507-TP" : "3C507",
628 if (esc
->card_type
== EF_CARD_TP
)
629 i82586_attach(sc
, vers
, ethaddr
, eftp_media
, NEFTP_MEDIA
,
632 u_int8_t media
= bus_space_read_1(esc
->sc_regt
, esc
->sc_regh
,
634 media
= (media
& EF_MEDIA_MASK
) >> EF_MEDIA_SHIFT
;
636 i82586_attach(sc
, vers
, ethaddr
, ef_media
, NEF_MEDIA
,
640 /* Clear the interrupt latch just in case. */
641 bus_space_write_1(esc
->sc_regt
, esc
->sc_regh
, EF_ICTRL
, 1);
643 esc
->sc_ih
= isa_intr_establish(ia
->ia_ic
, ia
->ia_irq
[0].ir_irq
,
644 IST_EDGE
, IPL_NET
, i82586_intr
, sc
);
645 if (esc
->sc_ih
== NULL
) {
646 DPRINTF(("\n%s: can't establish interrupt\n",
647 device_xname(&sc
->sc_dev
)));
652 ef_port_check(bus_space_tag_t iot
, bus_space_handle_t ioh
)
656 const u_char
* signature
= EF_SIGNATURE
;
658 for (i
= 0; i
< strlen(signature
); i
++) {
659 ch
= bus_space_read_1(iot
, ioh
, i
);
660 if (ch
!= signature
[i
])
664 /* If card is mapped in high memory (above 15Meg), we can't use it */
665 ch
= bus_space_read_1(iot
, ioh
, EF_MADDR
);
666 if (ch
& EF_MADDR_HIGH
)
667 return 0; /* XXX: maybe we should panic?? */
672 CFATTACH_DECL(ef
, sizeof(struct ef_softc
),
673 ef_match
, ef_attach
, NULL
, NULL
);