1 /* $NetBSD: if_iy.c,v 1.85 2009/05/12 08:44:19 cegger Exp $ */
3 /* #define IYMEMDEBUG */
6 * Copyright (c) 1996,2001 The NetBSD Foundation, Inc.
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Ignatios Souvatzis.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
37 * - Intel EtherExpress Pro/10.
38 * - possibly other boards using the i82595 chip and no special tweaks.
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: if_iy.c,v 1.85 2009/05/12 08:44:19 cegger Exp $");
48 #include <sys/param.h>
49 #include <sys/systm.h>
52 #include <sys/protosw.h>
53 #include <sys/socket.h>
54 #include <sys/ioctl.h>
55 #include <sys/errno.h>
56 #include <sys/syslog.h>
57 #include <sys/device.h>
58 #include <sys/endian.h>
64 #include <net/if_types.h>
65 #include <net/if_dl.h>
67 #include <net/if_ether.h>
71 #include <net/bpfdesc.h>
75 #include <netinet/in.h>
76 #include <netinet/in_systm.h>
77 #include <netinet/in_var.h>
78 #include <netinet/ip.h>
79 #include <netinet/if_inarp.h>
83 #if defined(SIOCSIFMEDIA)
84 #include <net/if_media.h>
91 #include <dev/isa/isareg.h>
92 #include <dev/isa/isavar.h>
93 #include <dev/ic/i82595reg.h>
95 /* XXX why isn't this centralized? */
96 #ifndef __BUS_SPACE_HAS_STREAM_METHODS
97 #define bus_space_write_stream_2 bus_space_write_2
98 #define bus_space_write_multi_stream_2 bus_space_write_multi_2
99 #define bus_space_read_stream_2 bus_space_read_2
100 #define bus_space_read_multi_stream_2 bus_space_read_multi_2
101 #endif /* __BUS_SPACE_HAS_STREAM_METHODS */
104 * Ethernet status, per interface.
107 struct device sc_dev
;
110 bus_space_tag_t sc_iot
;
111 bus_space_handle_t sc_ioh
;
113 struct ethercom sc_ethercom
;
115 struct ifmedia iy_ifmedia
;
124 int sram
, tx_size
, rx_size
;
126 int tx_start
, tx_end
, tx_last
;
135 rndsource_element_t rnd_source
;
139 void iywatchdog(struct ifnet
*);
140 int iyioctl(struct ifnet
*, u_long
, void *);
142 void iyinit(struct iy_softc
*);
143 void iystop(struct iy_softc
*);
144 void iystart(struct ifnet
*);
146 void iy_intr_rx(struct iy_softc
*);
147 void iy_intr_tx(struct iy_softc
*);
149 void iyreset(struct iy_softc
*);
150 void iy_readframe(struct iy_softc
*, int);
151 void iy_drop_packet_buffer(struct iy_softc
*);
152 void iy_find_mem_size(struct iy_softc
*);
153 void iyrint(struct iy_softc
*);
154 void iytint(struct iy_softc
*);
155 void iyxmit(struct iy_softc
*);
156 static void iy_mc_setup(struct iy_softc
*);
157 static void iy_mc_reset(struct iy_softc
*);
158 void iyget(struct iy_softc
*, bus_space_tag_t
, bus_space_handle_t
, int);
159 void iyprobemem(struct iy_softc
*);
160 static inline void eepromwritebit(bus_space_tag_t
, bus_space_handle_t
, int);
161 static inline int eepromreadbit(bus_space_tag_t
, bus_space_handle_t
);
164 void print_rbd(volatile struct iy_recv_buf_desc
*);
170 int iy_mediachange(struct ifnet
*);
171 void iy_mediastatus(struct ifnet
*, struct ifmediareq
*);
173 int iyprobe(device_t
, cfdata_t
, void *);
174 void iyattach(device_t
, device_t
, void *);
176 static u_int16_t
eepromread(bus_space_tag_t
, bus_space_handle_t
, int);
178 static int eepromreadall(bus_space_tag_t
, bus_space_handle_t
, u_int16_t
*,
181 CFATTACH_DECL(iy
, sizeof(struct iy_softc
),
182 iyprobe
, iyattach
, NULL
, NULL
);
184 static u_int8_t eepro_irqmap
[] = EEPP_INTMAP
;
185 static u_int8_t eepro_revirqmap
[] = EEPP_RINTMAP
;
188 iyprobe(device_t parent
, cfdata_t match
, void *aux
)
190 struct isa_attach_args
*ia
= aux
;
193 bus_space_handle_t ioh
;
202 if (ISA_DIRECT_CONFIG(ia
))
207 if (ia
->ia_io
[0].ir_addr
== ISA_UNKNOWN_PORT
)
210 if (bus_space_map(iot
, ia
->ia_io
[0].ir_addr
, 16, 0, &ioh
))
213 /* try to find the round robin sig: */
215 c
= bus_space_read_1(iot
, ioh
, ID_REG
);
216 if ((c
& ID_REG_MASK
) != ID_REG_SIG
)
219 d
= bus_space_read_1(iot
, ioh
, ID_REG
);
220 if ((d
& ID_REG_MASK
) != ID_REG_SIG
)
223 if (((d
-c
) & R_ROBIN_BITS
) != 0x40)
226 d
= bus_space_read_1(iot
, ioh
, ID_REG
);
227 if ((d
& ID_REG_MASK
) != ID_REG_SIG
)
230 if (((d
-c
) & R_ROBIN_BITS
) != 0x80)
233 d
= bus_space_read_1(iot
, ioh
, ID_REG
);
234 if ((d
& ID_REG_MASK
) != ID_REG_SIG
)
237 if (((d
-c
) & R_ROBIN_BITS
) != 0xC0)
240 d
= bus_space_read_1(iot
, ioh
, ID_REG
);
241 if ((d
& ID_REG_MASK
) != ID_REG_SIG
)
244 if (((d
-c
) & R_ROBIN_BITS
) != 0x00)
248 printf("iyprobe verified working ID reg.\n");
251 if (eepromreadall(iot
, ioh
, eaddr
, 8))
254 if (ia
->ia_irq
[0].ir_irq
== ISA_UNKNOWN_IRQ
)
255 irq
= eepro_irqmap
[eaddr
[EEPPW1
] & EEPP_Int
];
257 irq
= ia
->ia_irq
[0].ir_irq
;
259 if (irq
>= sizeof(eepro_revirqmap
))
262 if (eepro_revirqmap
[irq
] == 0xff)
265 /* now lets reset the chip */
267 bus_space_write_1(iot
, ioh
, COMMAND_REG
, RESET_CMD
);
271 ia
->ia_io
[0].ir_size
= 16;
274 ia
->ia_irq
[0].ir_irq
= irq
;
279 bus_space_unmap(iot
, ioh
, 16);
280 return 1; /* found */
282 bus_space_unmap(iot
, ioh
, 16);
287 iyattach(device_t parent
, device_t self
, void *aux
)
289 struct iy_softc
*sc
= (void *)self
;
290 struct isa_attach_args
*ia
= aux
;
291 struct ifnet
*ifp
= &sc
->sc_ethercom
.ec_if
;
293 bus_space_handle_t ioh
;
296 u_int8_t myaddr
[ETHER_ADDR_LEN
];
301 if (bus_space_map(iot
, ia
->ia_io
[0].ir_addr
, 16, 0, &ioh
)) {
302 printf(": can't map i/o space\n");
309 sc
->mappedirq
= eepro_revirqmap
[ia
->ia_irq
[0].ir_irq
];
311 /* now let's reset the chip */
313 bus_space_write_1(iot
, ioh
, COMMAND_REG
, RESET_CMD
);
318 strlcpy(ifp
->if_xname
, device_xname(&sc
->sc_dev
), IFNAMSIZ
);
320 ifp
->if_start
= iystart
;
321 ifp
->if_flags
= IFF_BROADCAST
| IFF_SIMPLEX
| IFF_NOTRAILERS
324 sc
->doing_mc_setup
= 0;
326 ifp
->if_ioctl
= iyioctl
;
327 ifp
->if_watchdog
= iywatchdog
;
329 IFQ_SET_READY(&ifp
->if_snd
);
331 (void)eepromreadall(iot
, ioh
, eaddr
, 8);
332 sc
->hard_vers
= eaddr
[EEPW6
] & EEPP_BoardRev
;
335 if ((eaddr
[EEPPEther0
] !=
336 eepromread(iot
, ioh
, EEPPEther0a
)) &&
337 (eaddr
[EEPPEther1
] !=
338 eepromread(iot
, ioh
, EEPPEther1a
)) &&
339 (eaddr
[EEPPEther2
] !=
340 eepromread(iot
, ioh
, EEPPEther2a
)))
342 printf("EEPROM Ethernet address differs from copy\n");
345 myaddr
[1] = eaddr
[EEPPEther0
] & 0xFF;
346 myaddr
[0] = eaddr
[EEPPEther0
] >> 8;
347 myaddr
[3] = eaddr
[EEPPEther1
] & 0xFF;
348 myaddr
[2] = eaddr
[EEPPEther1
] >> 8;
349 myaddr
[5] = eaddr
[EEPPEther2
] & 0xFF;
350 myaddr
[4] = eaddr
[EEPPEther2
] >> 8;
352 ifmedia_init(&sc
->iy_ifmedia
, 0, iy_mediachange
, iy_mediastatus
);
353 ifmedia_add(&sc
->iy_ifmedia
, IFM_ETHER
| IFM_10_2
, 0, NULL
);
354 ifmedia_add(&sc
->iy_ifmedia
, IFM_ETHER
| IFM_10_5
, 0, NULL
);
355 ifmedia_add(&sc
->iy_ifmedia
, IFM_ETHER
| IFM_10_T
, 0, NULL
);
356 ifmedia_add(&sc
->iy_ifmedia
, IFM_ETHER
| IFM_AUTO
, 0, NULL
);
357 ifmedia_set(&sc
->iy_ifmedia
, IFM_ETHER
| IFM_AUTO
);
358 /* Attach the interface. */
360 ether_ifattach(ifp
, myaddr
);
361 printf(": address %s, rev. %d, %d kB\n",
362 ether_sprintf(myaddr
),
363 sc
->hard_vers
, sc
->sram
/1024);
365 eirq
= eepro_irqmap
[eaddr
[EEPPW1
] & EEPP_Int
];
366 if (eirq
!= ia
->ia_irq
[0].ir_irq
)
367 printf("%s: EEPROM irq setting %d ignored\n",
368 device_xname(&sc
->sc_dev
), eirq
);
370 sc
->sc_ih
= isa_intr_establish(ia
->ia_ic
, ia
->ia_irq
[0].ir_irq
,
371 IST_EDGE
, IPL_NET
, iyintr
, sc
);
374 rnd_attach_source(&sc
->rnd_source
, device_xname(&sc
->sc_dev
),
378 temp
= bus_space_read_1(iot
, ioh
, INT_NO_REG
);
379 bus_space_write_1(iot
, ioh
, INT_NO_REG
, (temp
& 0xf8) | sc
->mappedirq
);
383 iystop(struct iy_softc
*sc
)
386 bus_space_handle_t ioh
;
394 bus_space_write_1(iot
, ioh
, COMMAND_REG
, RCV_DISABLE_CMD
);
396 bus_space_write_1(iot
, ioh
, INT_MASK_REG
, ALL_INTS
);
397 bus_space_write_1(iot
, ioh
, STATUS_REG
, ALL_INTS
);
399 bus_space_write_1(iot
, ioh
, COMMAND_REG
, RESET_CMD
);
402 printf("%s: dumping tx chain (st 0x%x end 0x%x last 0x%x)\n",
403 device_xname(&sc
->sc_dev
), sc
->tx_start
, sc
->tx_end
, sc
->tx_last
);
410 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, p
);
412 v
= le16toh(bus_space_read_stream_2(iot
, ioh
, MEM_PORT_REG
));
413 snprintb(sbuf
, sizeof(sbuf
), "\020\006Ab\010Dn", v
);
414 printf("0x%04x: %s ", p
, sbuf
);
416 v
= le16toh(bus_space_read_stream_2(iot
, ioh
, MEM_PORT_REG
));
417 snprintb(sbuf
, sizeof(sbuf
),
418 "\020\6MAX_COL\7HRT_BEAT\010TX_DEF\011UND_RUN"
419 "\012JERR\013LST_CRS\014LTCOL\016TX_OK\020COLL", v
);
420 printf("0x%s", sbuf
);
422 p
= le16toh(bus_space_read_stream_2(iot
, ioh
, MEM_PORT_REG
));
423 printf(" 0x%04x", p
);
425 v
= le16toh(bus_space_read_stream_2(iot
, ioh
, MEM_PORT_REG
));
426 snprintb(sbuf
, sizeof(sbuf
), "\020\020Ch", v
);
427 printf(" 0x%s\n", sbuf
);
429 } while (v
& 0x8000);
431 sc
->tx_start
= sc
->tx_end
= sc
->rx_size
;
433 sc
->sc_ethercom
.ec_if
.if_flags
&= ~(IFF_RUNNING
|IFF_OACTIVE
);
437 iyreset(struct iy_softc
*sc
)
447 iyinit(struct iy_softc
*sc
)
453 bus_space_handle_t ioh
;
458 ifp
= &sc
->sc_ethercom
.ec_if
;
460 printf("ifp is %p\n", ifp
);
463 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(2));
465 temp
= bus_space_read_1(iot
, ioh
, EEPROM_REG
);
467 bus_space_write_1(iot
, ioh
, EEPROM_REG
, temp
& ~0x10);
469 for (i
=0; i
<6; ++i
) {
470 bus_space_write_1(iot
, ioh
, I_ADD(i
), CLLADDR(ifp
->if_sadl
)[i
]);
473 temp
= bus_space_read_1(iot
, ioh
, REG1
);
474 bus_space_write_1(iot
, ioh
, REG1
,
475 temp
| /* XMT_CHAIN_INT | XMT_CHAIN_ERRSTOP | */ RCV_DISCARD_BAD
);
477 if (ifp
->if_flags
& (IFF_PROMISC
|IFF_ALLMULTI
)) {
482 bus_space_write_1(iot
, ioh
, RECV_MODES_REG
, temp
);
488 snprintb(sbuf
, sizeof(sbuf
),
489 "\020\1PRMSC\2NOBRDST\3SEECRC\4LENGTH\5NOSaIns\6MultiIA",
492 printf("%s: RECV_MODES set to %s\n", device_xname(&sc
->sc_dev
), sbuf
);
496 temp
= bus_space_read_1(iot
, ioh
, MEDIA_SELECT
);
497 bus_space_write_1(iot
, ioh
, MEDIA_SELECT
, temp
);
498 /* XXX END OF VOODOO */
501 delay(500000); /* for the hardware to test for the connector */
503 temp
= bus_space_read_1(iot
, ioh
, MEDIA_SELECT
);
508 snprintb(sbuf
, sizeof(sbuf
),
509 "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC",
511 printf("%s: media select was 0x%s ", device_xname(&sc
->sc_dev
), sbuf
);
514 temp
= (temp
& TEST_MODE_MASK
);
516 switch(IFM_SUBTYPE(sc
->iy_ifmedia
.ifm_media
)) {
518 temp
&= ~ (BNC_BIT
| TPE_BIT
);
522 temp
= (temp
& ~TPE_BIT
) | BNC_BIT
;
526 temp
= (temp
& ~BNC_BIT
) | TPE_BIT
;
530 /* nothing; leave as it is */
532 switch (temp
& (BNC_BIT
| TPE_BIT
)) {
534 sc
->iy_media
= IFM_ETHER
| IFM_10_2
;
537 sc
->iy_media
= IFM_ETHER
| IFM_10_T
;
540 sc
->iy_media
= IFM_ETHER
| IFM_10_5
;
543 bus_space_write_1(iot
, ioh
, MEDIA_SELECT
, temp
);
548 snprintb(sbuf
, sizeof(sbuf
),
549 "\020\1LnkInDis\2PolCor\3TPE\4JabberDis\5NoAport\6BNC",
551 printf("changed to 0x%s\n", sbuf
);
555 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(0));
556 bus_space_write_1(iot
, ioh
, INT_MASK_REG
, ALL_INTS
);
557 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(1));
559 temp
= bus_space_read_1(iot
, ioh
, INT_NO_REG
);
560 bus_space_write_1(iot
, ioh
, INT_NO_REG
, (temp
& 0xf8) | sc
->mappedirq
);
566 snprintb(sbuf
, sizeof(sbuf
),
567 "\020\4bad_irq\010flash/boot present", temp
);
569 printf("%s: int no was %s\n", device_xname(&sc
->sc_dev
), sbuf
);
571 temp
= bus_space_read_1(iot
, ioh
, INT_NO_REG
);
572 snprintb(sbuf
, sizeof(sbuf
),
573 "\020\4bad_irq\010flash/boot present", temp
);
574 printf("%s: int no now %s\n", device_xname(&sc
->sc_dev
), sbuf
);
578 bus_space_write_1(iot
, ioh
, RCV_LOWER_LIMIT_REG
, 0);
579 bus_space_write_1(iot
, ioh
, RCV_UPPER_LIMIT_REG
, (sc
->rx_size
-2) >>8);
580 bus_space_write_1(iot
, ioh
, XMT_LOWER_LIMIT_REG
, sc
->rx_size
>>8);
581 bus_space_write_1(iot
, ioh
, XMT_UPPER_LIMIT_REG
, (sc
->sram
- 2) >>8);
583 temp
= bus_space_read_1(iot
, ioh
, REG1
);
588 snprintb(sbuf
, sizeof(sbuf
), "\020\2WORD_WIDTH\010INT_ENABLE",
591 printf("%s: HW access is %s\n", device_xname(&sc
->sc_dev
), sbuf
);
594 bus_space_write_1(iot
, ioh
, REG1
, temp
| INT_ENABLE
); /* XXX what about WORD_WIDTH? */
600 temp
= bus_space_read_1(iot
, ioh
, REG1
);
601 snprintb(sbuf
, sizeof(sbuf
), "\020\2WORD_WIDTH\010INT_ENABLE",
603 printf("%s: HW access is %s\n", device_xname(&sc
->sc_dev
), sbuf
);
607 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(0));
609 bus_space_write_1(iot
, ioh
, INT_MASK_REG
, ALL_INTS
& ~(RX_BIT
|TX_BIT
));
610 bus_space_write_1(iot
, ioh
, STATUS_REG
, ALL_INTS
); /* clear ints */
612 bus_space_write_1(iot
, ioh
, RCV_COPY_THRESHOLD
, 0);
614 bus_space_write_2(iot
, ioh
, RCV_START_LOW
, 0);
615 bus_space_write_2(iot
, ioh
, RCV_STOP_LOW
, sc
->rx_size
- 2);
618 bus_space_write_1(iot
, ioh
, 0, SEL_RESET_CMD
);
621 bus_space_write_2(iot
, ioh
, XMT_ADDR_REG
, sc
->rx_size
);
623 sc
->tx_start
= sc
->tx_end
= sc
->rx_size
;
626 bus_space_write_1(iot
, ioh
, 0, RCV_ENABLE_CMD
);
628 ifp
->if_flags
|= IFF_RUNNING
;
629 ifp
->if_flags
&= ~IFF_OACTIVE
;
633 iystart(struct ifnet
*ifp
)
639 u_int len
, pad
, last
, end
;
640 u_int llen
, residual
;
644 u_int16_t resval
, stat
;
646 bus_space_handle_t ioh
;
649 printf("iystart called\n");
653 if ((ifp
->if_flags
& (IFF_RUNNING
| IFF_OACTIVE
)) != IFF_RUNNING
)
662 IFQ_POLL(&ifp
->if_snd
, m0
);
666 printf("%s: trying to write another packet to the hardware\n",
667 device_xname(&sc
->sc_dev
));
670 /* We need to use m->m_pkthdr.len, so require the header */
671 if ((m0
->m_flags
& M_PKTHDR
) == 0)
672 panic("iystart: no header mbuf");
674 len
= m0
->m_pkthdr
.len
;
678 printf("%s: length is %d.\n", device_xname(&sc
->sc_dev
), len
);
680 if (len
< (ETHER_MIN_LEN
- ETHER_CRC_LEN
)) {
681 pad
= ETHER_MIN_LEN
- ETHER_CRC_LEN
- len
;
684 if (len
+ pad
> ETHER_MAX_LEN
) {
685 /* packet is obviously too large: toss it */
687 IFQ_DEQUEUE(&ifp
->if_snd
, m0
);
694 bpf_mtap(ifp
->if_bpf
, m0
);
697 avail
= sc
->tx_start
- sc
->tx_end
;
699 avail
+= sc
->tx_size
;
702 printf("%s: avail is %d.\n", device_xname(&sc
->sc_dev
), avail
);
705 * we MUST RUN at splnet here ---
706 * XXX todo: or even turn off the boards ints ??? hm...
709 /* See if there is room to put another packet in the buffer. */
711 if ((len
+pad
+2*I595_XMT_HDRLEN
) > avail
) {
713 printf("%s: len = %d, avail = %d, setting OACTIVE\n",
714 device_xname(&sc
->sc_dev
), len
, avail
);
716 /* mark interface as full ... */
717 ifp
->if_flags
|= IFF_OACTIVE
;
719 /* and wait for any transmission result */
720 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(2));
722 temp
= bus_space_read_1(iot
, ioh
, REG1
);
723 bus_space_write_1(iot
, ioh
, REG1
,
724 temp
& ~XMT_CHAIN_INT
);
726 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(0));
731 /* we know it fits in the hardware now, so dequeue it */
732 IFQ_DEQUEUE(&ifp
->if_snd
, m0
);
735 end
= last
+ pad
+ len
+ I595_XMT_HDRLEN
;
737 if (end
>= sc
->sram
) {
738 if ((sc
->sram
- last
) <= I595_XMT_HDRLEN
) {
739 /* keep header in one piece */
741 end
= last
+ pad
+ len
+ I595_XMT_HDRLEN
;
746 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, last
);
747 bus_space_write_stream_2(iot
, ioh
, MEM_PORT_REG
,
750 bus_space_write_2(iot
, ioh
, MEM_PORT_REG
, 0);
751 bus_space_write_2(iot
, ioh
, MEM_PORT_REG
, 0);
753 bus_space_write_stream_2(iot
, ioh
, MEM_PORT_REG
,
756 residual
= resval
= 0;
758 while ((m
= m0
)!=0) {
759 data
= mtod(m
, void *);
763 printf("%s: merging residual with next mbuf.\n",
764 device_xname(&sc
->sc_dev
));
766 resval
|= *data
<< 8;
767 bus_space_write_stream_2(iot
, ioh
,
768 MEM_PORT_REG
, resval
);
773 * XXX ALIGNMENT LOSSAGE HERE.
776 bus_space_write_multi_stream_2(iot
, ioh
,
777 MEM_PORT_REG
, (u_int16_t
*) data
,
781 resval
= *(data
+ llen
- 1);
783 printf("%s: got odd mbuf to send.\n",
784 device_xname(&sc
->sc_dev
));
792 bus_space_write_stream_2(iot
, ioh
, MEM_PORT_REG
,
797 bus_space_write_stream_2(iot
, ioh
, MEM_PORT_REG
, 0);
800 printf("%s: new last = 0x%x, end = 0x%x.\n",
801 device_xname(&sc
->sc_dev
), last
, end
);
802 printf("%s: old start = 0x%x, end = 0x%x, last = 0x%x\n",
803 device_xname(&sc
->sc_dev
), sc
->tx_start
, sc
->tx_end
, sc
->tx_last
);
806 if (sc
->tx_start
!= sc
->tx_end
) {
807 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
,
808 sc
->tx_last
+ XMT_COUNT
);
811 * XXX We keep stat in le order, to potentially save
814 stat
= bus_space_read_stream_2(iot
, ioh
, MEM_PORT_REG
);
816 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
,
817 sc
->tx_last
+ XMT_CHAIN
);
819 bus_space_write_stream_2(iot
, ioh
, MEM_PORT_REG
,
822 bus_space_write_stream_2(iot
, ioh
, MEM_PORT_REG
,
823 stat
| htole16(CHAIN
));
825 printf("%s: setting 0x%x to 0x%x\n",
826 device_xname(&sc
->sc_dev
), sc
->tx_last
+ XMT_COUNT
,
827 le16toh(stat
) | CHAIN
);
830 stat
= bus_space_read_2(iot
, ioh
, MEM_PORT_REG
); /* dummy read */
832 /* XXX todo: enable ints here if disabled */
836 if (sc
->tx_start
== sc
->tx_end
) {
837 bus_space_write_2(iot
, ioh
, XMT_ADDR_REG
, last
);
838 bus_space_write_1(iot
, ioh
, 0, XMT_CMD
);
841 printf("%s: writing 0x%x to XAR and giving XCMD\n",
842 device_xname(&sc
->sc_dev
), last
);
845 bus_space_write_1(iot
, ioh
, 0, RESUME_XMT_CMD
);
847 printf("%s: giving RESUME_XCMD\n",
848 device_xname(&sc
->sc_dev
));
854 /* and wait only for end of transmission chain */
855 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(2));
857 temp
= bus_space_read_1(iot
, ioh
, REG1
);
858 bus_space_write_1(iot
, ioh
, REG1
, temp
| XMT_CHAIN_INT
);
860 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(0));
865 eepromwritebit(bus_space_tag_t iot
, bus_space_handle_t ioh
, int what
)
867 bus_space_write_1(iot
, ioh
, EEPROM_REG
, what
);
869 bus_space_write_1(iot
, ioh
, EEPROM_REG
, what
|EESK
);
871 bus_space_write_1(iot
, ioh
, EEPROM_REG
, what
);
876 eepromreadbit(bus_space_tag_t iot
, bus_space_handle_t ioh
)
880 bus_space_write_1(iot
, ioh
, EEPROM_REG
, EECS
|EESK
);
882 b
= bus_space_read_1(iot
, ioh
, EEPROM_REG
);
883 bus_space_write_1(iot
, ioh
, EEPROM_REG
, EECS
);
886 return ((b
& EEDO
) != 0);
890 eepromread(bus_space_tag_t iot
, bus_space_handle_t ioh
, int offset
)
894 volatile u_int16_t readval
;
896 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(2));
898 bus_space_write_1(iot
, ioh
, EEPROM_REG
, EECS
); /* XXXX??? */
901 eepromwritebit(iot
, ioh
, EECS
|EEDI
);
902 eepromwritebit(iot
, ioh
, EECS
|EEDI
);
903 eepromwritebit(iot
, ioh
, EECS
);
905 for (j
=5; j
>=0; --j
) {
907 eepromwritebit(iot
, ioh
, EECS
|EEDI
);
909 eepromwritebit(iot
, ioh
, EECS
);
912 for (readval
=0, i
=0; i
<16; ++i
) {
914 readval
|= eepromreadbit(iot
, ioh
);
917 bus_space_write_1(iot
, ioh
, EEPROM_REG
, 0|EESK
);
919 bus_space_write_1(iot
, ioh
, EEPROM_REG
, 0);
921 bus_space_write_1(iot
, ioh
, COMMAND_REG
, BANK_SEL(0));
927 * Device timeout/watchdog routine. Entered if the device neglects to generate
928 * an interrupt after a transmit has been started on it.
931 iywatchdog(struct ifnet
*ifp
)
933 struct iy_softc
*sc
= ifp
->if_softc
;
935 log(LOG_ERR
, "%s: device timeout\n", device_xname(&sc
->sc_dev
));
936 ++sc
->sc_ethercom
.ec_if
.if_oerrors
;
941 * What to do upon receipt of an interrupt.
949 bus_space_handle_t ioh
;
957 ifp
= &sc
->sc_ethercom
.ec_if
;
959 status
= bus_space_read_1(iot
, ioh
, STATUS_REG
);
961 if (status
& ALL_INTS
) {
964 snprintb(sbuf
, sizeof(sbuf
), "\020\1RX_STP\2RX\3TX\4EXEC",
966 printf("%s: got interrupt %s", device_xname(&sc
->sc_dev
), sbuf
);
968 if (status
& EXEC_INT
) {
969 snprintb(sbuf
, sizeof(sbuf
),
970 "\020\6ABORT", bus_space_read_1(iot
, ioh
, 0));
971 printf(" event %s\n", sbuf
);
976 if ((status
& (RX_INT
| TX_INT
)) == 0)
979 if (status
& RX_INT
) {
981 bus_space_write_1(iot
, ioh
, STATUS_REG
, RX_INT
);
983 if (status
& TX_INT
) {
984 /* Tell feeders we may be able to accept more data... */
985 ifp
->if_flags
&= ~IFF_OACTIVE
;
986 /* and get more data. */
988 bus_space_write_1(iot
, ioh
, STATUS_REG
, TX_INT
);
992 rnd_add_uint32(&sc
->rnd_source
, status
);
999 iyget(struct iy_softc
*sc
, bus_space_tag_t iot
, bus_space_handle_t ioh
, int rxlen
)
1001 struct mbuf
*m
, *top
, **mp
;
1005 ifp
= &sc
->sc_ethercom
.ec_if
;
1007 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
1010 m
->m_pkthdr
.rcvif
= ifp
;
1011 m
->m_pkthdr
.len
= rxlen
;
1018 MGET(m
, M_DONTWAIT
, MT_DATA
);
1025 if (rxlen
>= MINCLSIZE
) {
1026 MCLGET(m
, M_DONTWAIT
);
1027 if ((m
->m_flags
& M_EXT
) == 0) {
1034 len
= min(rxlen
, len
);
1036 * XXX ALIGNMENT LOSSAGE HERE.
1041 bus_space_read_multi_stream_2(iot
, ioh
, MEM_PORT_REG
,
1042 mtod(m
, u_int16_t
*), len
/2);
1045 printf("%s: received odd mbuf\n", device_xname(&sc
->sc_dev
));
1047 *(mtod(m
, char *)) = bus_space_read_stream_2(iot
, ioh
,
1059 /* XXX receive the top here */
1065 bpf_mtap(ifp
->if_bpf
, top
);
1067 (*ifp
->if_input
)(ifp
, top
);
1076 iy_intr_rx(struct iy_softc
*sc
)
1078 bus_space_tag_t iot
;
1079 bus_space_handle_t ioh
;
1081 u_int rxadrs
, rxevnt
, rxstatus
, rxnext
, rxlen
;
1086 rxadrs
= sc
->rx_start
;
1087 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, rxadrs
);
1088 rxevnt
= le16toh(bus_space_read_stream_2(iot
, ioh
, MEM_PORT_REG
));
1091 while (rxevnt
== RCV_DONE
) {
1092 rxstatus
= le16toh(bus_space_read_stream_2(iot
, ioh
,
1094 rxnext
= le16toh(bus_space_read_stream_2(iot
, ioh
,
1096 rxlen
= le16toh(bus_space_read_stream_2(iot
, ioh
,
1102 snprintb(sbuf
, sizeof(sbuf
),
1103 "\020\1RCLD\2IA_MCH\010SHORT\011OVRN\013ALGERR"
1104 "\014CRCERR\015LENERR\016RCVOK\020TYP", rxstatus
);
1106 printf("%s: pck at 0x%04x stat %s next 0x%x len 0x%x\n",
1107 device_xname(&sc
->sc_dev
), rxadrs
, sbuf
, rxnext
, rxlen
);
1110 iyget(sc
, iot
, ioh
, rxlen
);
1112 /* move stop address */
1113 bus_space_write_2(iot
, ioh
, RCV_STOP_LOW
,
1114 rxnext
== 0 ? sc
->rx_size
- 2 : rxnext
- 2);
1116 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, rxnext
);
1118 rxevnt
= le16toh(bus_space_read_stream_2(iot
, ioh
,
1121 sc
->rx_start
= rxnext
;
1125 iy_intr_tx(struct iy_softc
*sc
)
1127 bus_space_tag_t iot
;
1128 bus_space_handle_t ioh
;
1130 u_int txstatus
, txstat2
, txlen
, txnext
;
1132 ifp
= &sc
->sc_ethercom
.ec_if
;
1136 while (sc
->tx_start
!= sc
->tx_end
) {
1137 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, sc
->tx_start
);
1138 txstatus
= le16toh(bus_space_read_stream_2(iot
, ioh
,
1141 if ((txstatus
& (TX_DONE
|CMD_MASK
)) != (TX_DONE
|XMT_CMD
))
1144 txstat2
= le16toh(bus_space_read_stream_2(iot
, ioh
,
1146 txnext
= le16toh(bus_space_read_stream_2(iot
, ioh
,
1148 txlen
= le16toh(bus_space_read_stream_2(iot
, ioh
,
1154 snprintb(sbuf
, sizeof(sbuf
),
1155 "\020\6MAX_COL\7HRT_BEAT\010TX_DEF"
1156 "\011UND_RUN\012JERR\013LST_CRS"
1157 "\014LTCOL\016TX_OK\020COLL", txstat2
);
1159 printf("txstat 0x%x stat2 0x%s next 0x%x len 0x%x\n",
1160 txstatus
, sbuf
, txnext
, txlen
);
1164 sc
->tx_start
= txnext
;
1166 sc
->tx_start
= sc
->tx_end
;
1167 ifp
->if_flags
&= ~IFF_OACTIVE
;
1169 if (txstat2
& 0x0020)
1170 ifp
->if_collisions
+= 16;
1172 ifp
->if_collisions
+= txstat2
& 0x000f;
1174 if ((txstat2
& 0x2000) == 0)
1180 iyioctl(struct ifnet
*ifp
, u_long cmd
, void *data
)
1182 struct iy_softc
*sc
;
1188 ifa
= (struct ifaddr
*)data
;
1189 ifr
= (struct ifreq
*)data
;
1192 printf("iyioctl called with ifp %p (%s) cmd 0x%lx data %p\n",
1193 ifp
, ifp
->if_xname
, cmd
, data
);
1200 case SIOCINITIFADDR
:
1201 ifp
->if_flags
|= IFF_UP
;
1204 switch (ifa
->ifa_addr
->sa_family
) {
1207 arp_ifinit(ifp
, ifa
);
1216 if ((error
= ifioctl_common(ifp
, cmd
, data
)) != 0)
1218 sc
->promisc
= ifp
->if_flags
& (IFF_PROMISC
| IFF_ALLMULTI
);
1219 /* XXX re-use ether_ioctl() */
1220 switch (ifp
->if_flags
& (IFF_UP
|IFF_RUNNING
)) {
1223 * If interface is marked down and it is running, then
1227 ifp
->if_flags
&= ~IFF_RUNNING
;
1231 * If interface is marked up and it is stopped, then
1238 * Reset the interface to pick up changes in any other
1239 * flags that affect hardware registers.
1246 if (ifp
->if_flags
& IFF_DEBUG
)
1247 sc
->sc_debug
= IFY_ALL
;
1255 if ((error
= ether_ioctl(ifp
, cmd
, data
)) == ENETRESET
) {
1257 * Multicast list has changed; set the hardware filter
1260 if (ifp
->if_flags
& IFF_RUNNING
) {
1261 /* XXX can't make it work otherwise */
1271 error
= ifmedia_ioctl(ifp
, ifr
, &sc
->iy_ifmedia
, cmd
);
1274 error
= ether_ioctl(ifp
, cmd
, data
);
1281 iy_mediachange(struct ifnet
*ifp
)
1283 struct iy_softc
*sc
= ifp
->if_softc
;
1285 if (IFM_TYPE(sc
->iy_ifmedia
.ifm_media
) != IFM_ETHER
)
1287 switch(IFM_SUBTYPE(sc
->iy_ifmedia
.ifm_media
)) {
1301 iy_mediastatus(struct ifnet
*ifp
, struct ifmediareq
*ifmr
)
1303 struct iy_softc
*sc
= ifp
->if_softc
;
1305 ifmr
->ifm_active
= sc
->iy_media
;
1306 ifmr
->ifm_status
= IFM_AVALID
| IFM_ACTIVE
;
1311 iy_mc_setup(struct iy_softc
*sc
)
1313 struct ether_multi
*enm
;
1314 struct ether_multistep step
;
1315 struct ethercom
*ecp
;
1317 bus_space_tag_t iot
;
1318 bus_space_handle_t ioh
;
1319 int avail
, last
/*, end*/ , len
;
1321 volatile u_int16_t dum
;
1325 ecp
= &sc
->sc_ethercom
;
1331 len
= 6 * ecp
->ec_multicnt
;
1333 avail
= sc
->tx_start
- sc
->tx_end
;
1335 avail
+= sc
->tx_size
;
1336 if (ifp
->if_flags
& IFF_DEBUG
)
1337 printf("%s: iy_mc_setup called, %d addresses, "
1338 "%d/%d bytes needed/avail\n", ifp
->if_xname
,
1339 ecp
->ec_multicnt
, len
+ I595_XMT_HDRLEN
, avail
);
1343 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(2));
1344 bus_space_write_1(iot
, ioh
, RECV_MODES_REG
, MATCH_BRDCST
);
1346 temp
= bus_space_read_1(iot
, ioh
, MEDIA_SELECT
);
1347 bus_space_write_1(iot
, ioh
, MEDIA_SELECT
, temp
);
1348 /* XXX END OF VOODOO */
1349 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(0));
1350 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, last
);
1351 bus_space_write_stream_2(iot
, ioh
, MEM_PORT_REG
, htole16(MC_SETUP_CMD
));
1352 bus_space_write_2(iot
, ioh
, MEM_PORT_REG
, 0);
1353 bus_space_write_2(iot
, ioh
, MEM_PORT_REG
, 0);
1354 bus_space_write_stream_2(iot
, ioh
, MEM_PORT_REG
, htole16(len
));
1356 ETHER_FIRST_MULTI(step
, ecp
, enm
);
1359 * XXX ALIGNMENT LOSSAGE HERE?
1361 bus_space_write_multi_stream_2(iot
, ioh
, MEM_PORT_REG
,
1362 (u_int16_t
*) enm
->enm_addrlo
, 3);
1364 ETHER_NEXT_MULTI(step
, enm
);
1366 dum
= bus_space_read_2(iot
, ioh
, MEM_PORT_REG
); /* dummy read */
1367 bus_space_write_2(iot
, ioh
, XMT_ADDR_REG
, last
);
1368 bus_space_write_1(iot
, ioh
, 0, MC_SETUP_CMD
);
1371 sc
->tx_start
= sc
->rx_size
;
1372 sc
->tx_end
= sc
->rx_size
+ I595_XMT_HDRLEN
+ len
;
1374 for (timeout
=0; timeout
<100; timeout
++) {
1376 if ((bus_space_read_1(iot
, ioh
, STATUS_REG
) & EXEC_INT
) == 0)
1379 temp
= bus_space_read_1(iot
, ioh
, 0);
1380 bus_space_write_1(iot
, ioh
, STATUS_REG
, EXEC_INT
);
1383 aprint_error_dev(&sc
->sc_dev
, "mc setup failed, %d usec\n",
1385 } else if (((temp
& 0x0f) == 0x03) &&
1386 (ifp
->if_flags
& IFF_DEBUG
)) {
1387 printf("%s: mc setup done, %d usec\n",
1388 device_xname(&sc
->sc_dev
), timeout
* 2);
1393 sc
->tx_start
= sc
->tx_end
;
1394 ifp
->if_flags
&= ~IFF_OACTIVE
;
1399 iy_mc_reset(struct iy_softc
*sc
)
1401 struct ether_multi
*enm
;
1402 struct ether_multistep step
;
1403 struct ethercom
*ecp
;
1405 bus_space_tag_t iot
;
1406 bus_space_handle_t ioh
;
1409 ecp
= &sc
->sc_ethercom
;
1415 if (ecp
->ec_multicnt
> 63) {
1416 ifp
->if_flags
|= IFF_ALLMULTI
;
1418 } else if (ecp
->ec_multicnt
> 0) {
1420 * Step through the list of addresses.
1422 ETHER_FIRST_MULTI(step
, ecp
, enm
);
1424 if (memcmp(enm
->enm_addrlo
, enm
->enm_addrhi
, 6) != 0) {
1425 ifp
->if_flags
|= IFF_ALLMULTI
;
1428 ETHER_NEXT_MULTI(step
, enm
);
1430 /* OK, we really need to do it now: */
1432 if ((ifp
->if_flags
& (IFF_RUNNING
| IFF_OACTIVE
))
1434 ifp
->if_flags
|= IFF_OACTIVE
;
1435 sc
->want_mc_setup
= 1;
1441 ifp
->if_flags
&= ~IFF_ALLMULTI
;
1445 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(2));
1446 if (ifp
->if_flags
& (IFF_PROMISC
|IFF_ALLMULTI
)) {
1449 temp
= MATCH_BRDCST
;
1451 bus_space_write_1(iot
, ioh
, RECV_MODES_REG
, temp
);
1453 temp
= bus_space_read_1(iot
, ioh
, MEDIA_SELECT
);
1454 bus_space_write_1(iot
, ioh
, MEDIA_SELECT
, temp
);
1455 /* XXX END OF VOODOO */
1457 /* XXX TBD: setup hardware for all multicasts */
1458 bus_space_write_1(iot
, ioh
, 0, BANK_SEL(0));
1464 print_rbd(volatile struct ie_recv_buf_desc
*rbd
)
1466 printf("RBD at %08lx:\nactual %04x, next %04x, buffer %08x\n"
1467 "length %04x, mbz %04x\n", (u_long
)rbd
, rbd
->ie_rbd_actual
,
1468 rbd
->ie_rbd_next
, rbd
->ie_rbd_buffer
, rbd
->ie_rbd_length
,
1474 iyprobemem(struct iy_softc
*sc
)
1476 bus_space_tag_t iot
;
1477 bus_space_handle_t ioh
;
1483 bus_space_write_1(iot
, ioh
, COMMAND_REG
, BANK_SEL(0));
1485 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, 4096-2);
1486 bus_space_write_2(iot
, ioh
, MEM_PORT_REG
, 0);
1488 for (testing
=65536; testing
>= 4096; testing
>>= 1) {
1489 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, testing
-2);
1490 bus_space_write_2(iot
, ioh
, MEM_PORT_REG
, 0xdead);
1491 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, testing
-2);
1492 if (bus_space_read_2(iot
, ioh
, MEM_PORT_REG
) != 0xdead) {
1494 printf("%s: Didn't keep 0xdead at 0x%x\n",
1495 device_xname(&sc
->sc_dev
), testing
-2);
1500 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, testing
-2);
1501 bus_space_write_2(iot
, ioh
, MEM_PORT_REG
, 0xbeef);
1502 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, testing
-2);
1503 if (bus_space_read_2(iot
, ioh
, MEM_PORT_REG
) != 0xbeef) {
1505 printf("%s: Didn't keep 0xbeef at 0x%x\n",
1506 device_xname(&sc
->sc_dev
), testing
-2);
1511 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, 0);
1512 bus_space_write_2(iot
, ioh
, MEM_PORT_REG
, 0);
1513 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, testing
>> 1);
1514 bus_space_write_2(iot
, ioh
, MEM_PORT_REG
, testing
>> 1);
1515 bus_space_write_2(iot
, ioh
, HOST_ADDR_REG
, 0);
1516 if (bus_space_read_2(iot
, ioh
, MEM_PORT_REG
) == (testing
>> 1)) {
1518 printf("%s: 0x%x alias of 0x0\n",
1519 device_xname(&sc
->sc_dev
), testing
>> 1);
1531 /* 4 NFS packets + overhead RX, 2 NFS + overhead TX */
1532 sc
->rx_size
= 44*1024;
1536 /* 2 NFS packets + overhead RX, 1 NFS + overhead TX */
1537 sc
->rx_size
= 22*1024;
1541 /* 1 NFS packet + overhead RX, 4 big packets TX */
1542 sc
->rx_size
= 10*1024;
1545 sc
->rx_size
= testing
/2;
1548 sc
->tx_size
= testing
- sc
->rx_size
;
1552 eepromreadall(bus_space_tag_t iot
, bus_space_handle_t ioh
, u_int16_t
*wordp
, int maxi
)
1555 u_int16_t checksum
, tmp
;
1559 for (i
=0; i
<EEPP_LENGTH
; ++i
) {
1560 tmp
= eepromread(iot
, ioh
, i
);
1566 if (checksum
!= EEPP_CHKSUM
) {
1568 printf("wrong EEPROM checksum 0x%x should be 0x%x\n",
1569 checksum
, EEPP_CHKSUM
);