1 1.66 thorpej /* $NetBSD: seeq8005.c,v 1.66 2020/01/30 04:56:11 thorpej Exp $ */ 2 1.1 bjh21 3 1.1 bjh21 /* 4 1.27 bjh21 * Copyright (c) 2000, 2001 Ben Harris 5 1.11 bjh21 * Copyright (c) 1995-1998 Mark Brinicombe 6 1.1 bjh21 * All rights reserved. 7 1.1 bjh21 * 8 1.1 bjh21 * Redistribution and use in source and binary forms, with or without 9 1.1 bjh21 * modification, are permitted provided that the following conditions 10 1.1 bjh21 * are met: 11 1.1 bjh21 * 1. Redistributions of source code must retain the above copyright 12 1.1 bjh21 * notice, this list of conditions and the following disclaimer. 13 1.1 bjh21 * 2. Redistributions in binary form must reproduce the above copyright 14 1.1 bjh21 * notice, this list of conditions and the following disclaimer in the 15 1.1 bjh21 * documentation and/or other materials provided with the distribution. 16 1.1 bjh21 * 3. All advertising materials mentioning features or use of this software 17 1.1 bjh21 * must display the following acknowledgement: 18 1.11 bjh21 * This product includes software developed by Mark Brinicombe 19 1.11 bjh21 * for the NetBSD Project. 20 1.1 bjh21 * 4. The name of the company nor the name of the author may be used to 21 1.1 bjh21 * endorse or promote products derived from this software without specific 22 1.1 bjh21 * prior written permission. 23 1.1 bjh21 * 24 1.1 bjh21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 25 1.1 bjh21 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 26 1.1 bjh21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 27 1.1 bjh21 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 28 1.1 bjh21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 1.1 bjh21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 1.1 bjh21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 1.1 bjh21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 1.1 bjh21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 1.1 bjh21 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 1.1 bjh21 * SUCH DAMAGE. 35 1.1 bjh21 */ 36 1.1 bjh21 /* 37 1.2 bjh21 * seeq8005.c - SEEQ 8005 device driver 38 1.2 bjh21 */ 39 1.2 bjh21 /* 40 1.24 bjh21 * This driver currently supports the following chips: 41 1.2 bjh21 * SEEQ 8005 Advanced Ethernet Data Link Controller 42 1.20 bjh21 * SEEQ 80C04 Ethernet Data Link Controller 43 1.20 bjh21 * SEEQ 80C04A AutoDUPLEX CMOS Ethernet Data Link Controller 44 1.2 bjh21 */ 45 1.2 bjh21 /* 46 1.11 bjh21 * More information on the 8004 and 8005 AEDLC controllers can be found in 47 1.11 bjh21 * the SEEQ Technology Inc 1992 Data Comm Devices data book. 48 1.11 bjh21 * 49 1.11 bjh21 * This data book may no longer be available as these are rather old chips 50 1.11 bjh21 * (1991 - 1993) 51 1.11 bjh21 */ 52 1.11 bjh21 /* 53 1.2 bjh21 * This driver is based on the arm32 ea(4) driver, hence the names of many 54 1.2 bjh21 * of the functions. 55 1.1 bjh21 */ 56 1.1 bjh21 /* 57 1.1 bjh21 * Bugs/possible improvements: 58 1.1 bjh21 * - Does not currently support DMA 59 1.1 bjh21 * - Does not transmit multiple packets in one go 60 1.1 bjh21 * - Does not support 8-bit busses 61 1.1 bjh21 */ 62 1.1 bjh21 63 1.31 lukem #include <sys/cdefs.h> 64 1.66 thorpej __KERNEL_RCSID(0, "$NetBSD: seeq8005.c,v 1.66 2020/01/30 04:56:11 thorpej Exp $"); 65 1.31 lukem 66 1.1 bjh21 #include <sys/param.h> 67 1.1 bjh21 #include <sys/systm.h> 68 1.1 bjh21 #include <sys/endian.h> 69 1.1 bjh21 #include <sys/errno.h> 70 1.1 bjh21 #include <sys/ioctl.h> 71 1.1 bjh21 #include <sys/mbuf.h> 72 1.1 bjh21 #include <sys/socket.h> 73 1.1 bjh21 #include <sys/syslog.h> 74 1.1 bjh21 #include <sys/device.h> 75 1.1 bjh21 76 1.1 bjh21 #include <net/if.h> 77 1.1 bjh21 #include <net/if_dl.h> 78 1.1 bjh21 #include <net/if_types.h> 79 1.1 bjh21 #include <net/if_ether.h> 80 1.11 bjh21 #include <net/if_media.h> 81 1.1 bjh21 #include <net/bpf.h> 82 1.1 bjh21 83 1.53 riastrad #include <sys/rndsource.h> 84 1.30 bjh21 85 1.42 ad #include <sys/bus.h> 86 1.42 ad #include <sys/intr.h> 87 1.1 bjh21 88 1.1 bjh21 #include <dev/ic/seeq8005reg.h> 89 1.1 bjh21 #include <dev/ic/seeq8005var.h> 90 1.1 bjh21 91 1.10 bjh21 /*#define SEEQ_DEBUG*/ 92 1.1 bjh21 93 1.1 bjh21 /* for debugging convenience */ 94 1.16 bjh21 #ifdef SEEQ8005_DEBUG 95 1.11 bjh21 #define SEEQ_DEBUG_MISC 1 96 1.11 bjh21 #define SEEQ_DEBUG_TX 2 97 1.11 bjh21 #define SEEQ_DEBUG_RX 4 98 1.11 bjh21 #define SEEQ_DEBUG_PKT 8 99 1.11 bjh21 #define SEEQ_DEBUG_TXINT 16 100 1.11 bjh21 #define SEEQ_DEBUG_RXINT 32 101 1.16 bjh21 int seeq8005_debug = 0; 102 1.16 bjh21 #define DPRINTF(f, x) { if (seeq8005_debug & (f)) printf x; } 103 1.1 bjh21 #else 104 1.11 bjh21 #define DPRINTF(f, x) 105 1.1 bjh21 #endif 106 1.11 bjh21 107 1.51 skrll #ifndef EA_TX_BUFFER_SIZE 108 1.51 skrll #define EA_TX_BUFFER_SIZE 0x800 /* (> ETHER_MAX_LEN) */ 109 1.51 skrll #endif 110 1.51 skrll #ifndef EA_TX_BUFFER_COUNT 111 1.51 skrll #define EA_TX_BUFFER_COUNT 1 /* (> 0) */ 112 1.51 skrll #endif 113 1.1 bjh21 114 1.24 bjh21 #define SEEQ_READ16(sc, iot, ioh, reg) \ 115 1.24 bjh21 ((sc)->sc_flags & SF_8BIT ? \ 116 1.24 bjh21 (bus_space_read_1((iot), (ioh), (reg)) | \ 117 1.24 bjh21 (bus_space_read_1((iot), (ioh), (reg) + 1) << 8)) : \ 118 1.24 bjh21 (bus_space_read_2((iot), (ioh), (reg)))) 119 1.24 bjh21 120 1.24 bjh21 #define SEEQ_WRITE16(sc, iot, ioh, reg, val) do { \ 121 1.24 bjh21 if ((sc)->sc_flags & SF_8BIT) { \ 122 1.24 bjh21 bus_space_write_1((iot), (ioh), (reg), (val) & 0xff); \ 123 1.24 bjh21 bus_space_write_1((iot), (ioh), (reg) + 1, (val) >> 8); \ 124 1.24 bjh21 } else \ 125 1.24 bjh21 bus_space_write_2((iot), (ioh), (reg), (val)); \ 126 1.24 bjh21 } while (/*CONSTCOND*/0) 127 1.24 bjh21 128 1.1 bjh21 /* 129 1.1 bjh21 * prototypes 130 1.1 bjh21 */ 131 1.1 bjh21 132 1.5 bjh21 static int ea_init(struct ifnet *); 133 1.39 christos static int ea_ioctl(struct ifnet *, u_long, void *); 134 1.1 bjh21 static void ea_start(struct ifnet *); 135 1.1 bjh21 static void ea_watchdog(struct ifnet *); 136 1.1 bjh21 static void ea_chipreset(struct seeq8005_softc *); 137 1.1 bjh21 static void ea_ramtest(struct seeq8005_softc *); 138 1.1 bjh21 static int ea_stoptx(struct seeq8005_softc *); 139 1.1 bjh21 static int ea_stoprx(struct seeq8005_softc *); 140 1.5 bjh21 static void ea_stop(struct ifnet *, int); 141 1.1 bjh21 static void ea_await_fifo_empty(struct seeq8005_softc *); 142 1.1 bjh21 static void ea_await_fifo_full(struct seeq8005_softc *); 143 1.11 bjh21 static void ea_writebuf(struct seeq8005_softc *, u_char *, int, size_t); 144 1.11 bjh21 static void ea_readbuf(struct seeq8005_softc *, u_char *, int, size_t); 145 1.3 bjh21 static void ea_select_buffer(struct seeq8005_softc *, int); 146 1.62 msaitoh static void ea_set_address(struct seeq8005_softc *, int, const uint8_t *); 147 1.11 bjh21 static void ea_read(struct seeq8005_softc *, int, int); 148 1.11 bjh21 static struct mbuf *ea_get(struct seeq8005_softc *, int, int, struct ifnet *); 149 1.20 bjh21 static void ea_txint(struct seeq8005_softc *); 150 1.20 bjh21 static void ea_rxint(struct seeq8005_softc *); 151 1.49 skrll static void ea_txpacket(struct seeq8005_softc *); 152 1.12 bjh21 static int ea_writembuf(struct seeq8005_softc *, struct mbuf *, int); 153 1.5 bjh21 static void ea_mc_reset(struct seeq8005_softc *); 154 1.11 bjh21 static void ea_mc_reset_8004(struct seeq8005_softc *); 155 1.11 bjh21 static void ea_mc_reset_8005(struct seeq8005_softc *); 156 1.11 bjh21 static int ea_mediachange(struct ifnet *); 157 1.11 bjh21 static void ea_mediastatus(struct ifnet *, struct ifmediareq *); 158 1.1 bjh21 159 1.47 martin static u_char* padbuf = NULL; 160 1.35 bouyer 161 1.1 bjh21 162 1.1 bjh21 /* 163 1.1 bjh21 * Attach chip. 164 1.1 bjh21 */ 165 1.1 bjh21 166 1.1 bjh21 void 167 1.62 msaitoh seeq8005_attach(struct seeq8005_softc *sc, const uint8_t *myaddr, int *media, 168 1.11 bjh21 int nmedia, int defmedia) 169 1.1 bjh21 { 170 1.62 msaitoh device_t dev = sc->sc_dev; 171 1.1 bjh21 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 172 1.24 bjh21 bus_space_tag_t iot = sc->sc_iot; 173 1.24 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 174 1.2 bjh21 u_int id; 175 1.2 bjh21 176 1.11 bjh21 KASSERT(myaddr != NULL); 177 1.2 bjh21 printf(" address %s", ether_sprintf(myaddr)); 178 1.2 bjh21 179 1.3 bjh21 /* Stop the board. */ 180 1.3 bjh21 181 1.3 bjh21 ea_chipreset(sc); 182 1.3 bjh21 183 1.24 bjh21 /* Work out data bus width. */ 184 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_PTR, 0x1234); 185 1.25 bjh21 if (SEEQ_READ16(sc, iot, ioh, SEEQ_RX_PTR) != 0x1234) { 186 1.24 bjh21 /* Try 8-bit mode */ 187 1.24 bjh21 sc->sc_flags |= SF_8BIT; 188 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_PTR, 0x1234); 189 1.25 bjh21 if (SEEQ_READ16(sc, iot, ioh, SEEQ_RX_PTR) != 0x1234) { 190 1.43 cegger aprint_normal("\n"); 191 1.62 msaitoh aprint_error_dev(dev, 192 1.62 msaitoh "Cannot determine data bus width\n"); 193 1.24 bjh21 return; 194 1.24 bjh21 } 195 1.24 bjh21 } 196 1.24 bjh21 197 1.24 bjh21 printf(", %d-bit", sc->sc_flags & SF_8BIT ? 8 : 16); 198 1.24 bjh21 199 1.2 bjh21 /* Get the product ID */ 200 1.37 perry 201 1.10 bjh21 ea_select_buffer(sc, SEEQ_BUFCODE_PRODUCTID); 202 1.24 bjh21 id = SEEQ_READ16(sc, sc->sc_iot, sc->sc_ioh, SEEQ_BUFWIN); 203 1.2 bjh21 204 1.11 bjh21 switch (id & SEEQ_PRODUCTID_MASK) { 205 1.11 bjh21 case SEEQ_PRODUCTID_8004: 206 1.11 bjh21 sc->sc_variant = SEEQ_8004; 207 1.20 bjh21 switch (id & SEEQ_PRODUCTID_REV_MASK) { 208 1.20 bjh21 case SEEQ_PRODUCTID_REV_80C04: 209 1.20 bjh21 printf(", SEEQ 80C04\n"); 210 1.20 bjh21 break; 211 1.20 bjh21 case SEEQ_PRODUCTID_REV_80C04A: 212 1.20 bjh21 printf(", SEEQ 80C04A\n"); 213 1.20 bjh21 break; 214 1.20 bjh21 default: 215 1.20 bjh21 /* Unknown SEEQ 8004 variants */ 216 1.20 bjh21 printf(", SEEQ 8004 rev %x\n", 217 1.20 bjh21 id & SEEQ_PRODUCTID_REV_MASK); 218 1.20 bjh21 break; 219 1.20 bjh21 } 220 1.11 bjh21 break; 221 1.11 bjh21 default: /* XXX */ 222 1.11 bjh21 sc->sc_variant = SEEQ_8005; 223 1.20 bjh21 printf(", SEEQ 8005\n"); 224 1.11 bjh21 break; 225 1.11 bjh21 } 226 1.11 bjh21 227 1.11 bjh21 /* Both the 8004 and 8005 are designed for 64K Buffer memory */ 228 1.11 bjh21 sc->sc_buffersize = SEEQ_MAX_BUFFER_SIZE; 229 1.11 bjh21 230 1.11 bjh21 /* 231 1.11 bjh21 * Set up tx and rx buffers. 232 1.11 bjh21 * 233 1.51 skrll * We set aside EA_TX_BUFFER_SIZE * EA_TX_BUFFER_COUNT for TX 234 1.11 bjh21 * buffers and the rest for RX buffers 235 1.11 bjh21 */ 236 1.51 skrll sc->sc_tx_bufs = EA_TX_BUFFER_COUNT; 237 1.51 skrll sc->sc_tx_bufsize = sc->sc_tx_bufs * EA_TX_BUFFER_SIZE; 238 1.11 bjh21 sc->sc_rx_bufsize = sc->sc_buffersize - sc->sc_tx_bufsize; 239 1.11 bjh21 sc->sc_enabled = 0; 240 1.11 bjh21 241 1.11 bjh21 /* Test the RAM */ 242 1.11 bjh21 ea_ramtest(sc); 243 1.11 bjh21 244 1.11 bjh21 printf("%s: %dKB packet memory, txbuf=%dKB (%d buffers), rxbuf=%dKB", 245 1.62 msaitoh device_xname(dev), sc->sc_buffersize >> 10, 246 1.37 perry sc->sc_tx_bufsize >> 10, sc->sc_tx_bufs, sc->sc_rx_bufsize >> 10); 247 1.1 bjh21 248 1.35 bouyer if (padbuf == NULL) { 249 1.35 bouyer padbuf = malloc(ETHER_MIN_LEN - ETHER_CRC_LEN, M_DEVBUF, 250 1.65 chs M_ZERO | M_WAITOK); 251 1.35 bouyer } 252 1.35 bouyer 253 1.1 bjh21 /* Initialise ifnet structure. */ 254 1.1 bjh21 255 1.62 msaitoh strlcpy(ifp->if_xname, device_xname(dev), IFNAMSIZ); 256 1.1 bjh21 ifp->if_softc = sc; 257 1.1 bjh21 ifp->if_start = ea_start; 258 1.1 bjh21 ifp->if_ioctl = ea_ioctl; 259 1.5 bjh21 ifp->if_init = ea_init; 260 1.5 bjh21 ifp->if_stop = ea_stop; 261 1.1 bjh21 ifp->if_watchdog = ea_watchdog; 262 1.61 msaitoh ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST; 263 1.11 bjh21 if (sc->sc_variant == SEEQ_8004) 264 1.11 bjh21 ifp->if_flags |= IFF_SIMPLEX; 265 1.7 thorpej IFQ_SET_READY(&ifp->if_snd); 266 1.1 bjh21 267 1.11 bjh21 /* Initialize media goo. */ 268 1.11 bjh21 ifmedia_init(&sc->sc_media, 0, ea_mediachange, ea_mediastatus); 269 1.11 bjh21 if (media != NULL) { 270 1.11 bjh21 int i; 271 1.11 bjh21 272 1.11 bjh21 for (i = 0; i < nmedia; i++) 273 1.11 bjh21 ifmedia_add(&sc->sc_media, media[i], 0, NULL); 274 1.11 bjh21 ifmedia_set(&sc->sc_media, defmedia); 275 1.11 bjh21 } else { 276 1.62 msaitoh ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL); 277 1.62 msaitoh ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL); 278 1.11 bjh21 } 279 1.11 bjh21 280 1.27 bjh21 /* We can support 802.1Q VLAN-sized frames. */ 281 1.27 bjh21 sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; 282 1.27 bjh21 283 1.1 bjh21 /* Now we can attach the interface. */ 284 1.1 bjh21 285 1.1 bjh21 if_attach(ifp); 286 1.1 bjh21 ether_ifattach(ifp, myaddr); 287 1.1 bjh21 288 1.11 bjh21 printf("\n"); 289 1.30 bjh21 290 1.30 bjh21 /* After \n because it can print a line of its own. */ 291 1.62 msaitoh rnd_attach_source(&sc->rnd_source, device_xname(dev), 292 1.52 tls RND_TYPE_NET, RND_FLAG_DEFAULT); 293 1.11 bjh21 } 294 1.11 bjh21 295 1.11 bjh21 /* 296 1.11 bjh21 * Media change callback. 297 1.11 bjh21 */ 298 1.11 bjh21 static int 299 1.11 bjh21 ea_mediachange(struct ifnet *ifp) 300 1.11 bjh21 { 301 1.11 bjh21 struct seeq8005_softc *sc = ifp->if_softc; 302 1.8 bjh21 303 1.11 bjh21 if (sc->sc_mediachange) 304 1.62 msaitoh return (*sc->sc_mediachange)(sc); 305 1.62 msaitoh return EINVAL; 306 1.1 bjh21 } 307 1.1 bjh21 308 1.11 bjh21 /* 309 1.11 bjh21 * Media status callback. 310 1.11 bjh21 */ 311 1.11 bjh21 static void 312 1.11 bjh21 ea_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 313 1.11 bjh21 { 314 1.11 bjh21 struct seeq8005_softc *sc = ifp->if_softc; 315 1.11 bjh21 316 1.11 bjh21 if (sc->sc_enabled == 0) { 317 1.11 bjh21 ifmr->ifm_active = IFM_ETHER | IFM_NONE; 318 1.11 bjh21 ifmr->ifm_status = 0; 319 1.11 bjh21 return; 320 1.11 bjh21 } 321 1.11 bjh21 322 1.11 bjh21 if (sc->sc_mediastatus) 323 1.11 bjh21 (*sc->sc_mediastatus)(sc, ifmr); 324 1.11 bjh21 } 325 1.1 bjh21 326 1.1 bjh21 /* 327 1.1 bjh21 * Test the RAM on the ethernet card. 328 1.1 bjh21 */ 329 1.1 bjh21 330 1.1 bjh21 void 331 1.1 bjh21 ea_ramtest(struct seeq8005_softc *sc) 332 1.1 bjh21 { 333 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 334 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 335 1.1 bjh21 int loop; 336 1.1 bjh21 u_int sum = 0; 337 1.1 bjh21 338 1.1 bjh21 /* 339 1.1 bjh21 * Test the buffer memory on the board. 340 1.1 bjh21 * Write simple pattens to it and read them back. 341 1.1 bjh21 */ 342 1.1 bjh21 343 1.1 bjh21 /* Set up the whole buffer RAM for writing */ 344 1.1 bjh21 345 1.10 bjh21 ea_select_buffer(sc, SEEQ_BUFCODE_TX_EAP); 346 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, (SEEQ_MAX_BUFFER_SIZE >> 8) - 1); 347 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_TX_PTR, 0x0000); 348 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_PTR, SEEQ_MAX_BUFFER_SIZE - 2); 349 1.1 bjh21 350 1.62 msaitoh #define SEEQ_RAMTEST_LOOP(value) \ 351 1.3 bjh21 do { \ 352 1.3 bjh21 /* Set the write start address and write a pattern */ \ 353 1.3 bjh21 ea_writebuf(sc, NULL, 0x0000, 0); \ 354 1.10 bjh21 for (loop = 0; loop < SEEQ_MAX_BUFFER_SIZE; loop += 2) \ 355 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, (value)); \ 356 1.3 bjh21 \ 357 1.3 bjh21 /* Set the read start address and verify the pattern */ \ 358 1.3 bjh21 ea_readbuf(sc, NULL, 0x0000, 0); \ 359 1.10 bjh21 for (loop = 0; loop < SEEQ_MAX_BUFFER_SIZE; loop += 2) \ 360 1.62 msaitoh if (SEEQ_READ16(sc, iot, ioh, SEEQ_BUFWIN) != (value)) \ 361 1.3 bjh21 ++sum; \ 362 1.3 bjh21 } while (/*CONSTCOND*/0) 363 1.3 bjh21 364 1.10 bjh21 SEEQ_RAMTEST_LOOP(loop); 365 1.10 bjh21 SEEQ_RAMTEST_LOOP(loop ^ (SEEQ_MAX_BUFFER_SIZE - 1)); 366 1.10 bjh21 SEEQ_RAMTEST_LOOP(0xaa55); 367 1.10 bjh21 SEEQ_RAMTEST_LOOP(0x55aa); 368 1.1 bjh21 369 1.1 bjh21 /* Report */ 370 1.1 bjh21 371 1.2 bjh21 if (sum > 0) 372 1.62 msaitoh aprint_error_dev(sc->sc_dev, 373 1.62 msaitoh "buffer RAM failed self test, %d faults\n", sum); 374 1.1 bjh21 } 375 1.1 bjh21 376 1.1 bjh21 377 1.1 bjh21 /* 378 1.1 bjh21 * Stop the tx interface. 379 1.1 bjh21 * 380 1.1 bjh21 * Returns 0 if the tx was already stopped or 1 if it was active 381 1.1 bjh21 */ 382 1.1 bjh21 383 1.1 bjh21 static int 384 1.1 bjh21 ea_stoptx(struct seeq8005_softc *sc) 385 1.1 bjh21 { 386 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 387 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 388 1.1 bjh21 int timeout; 389 1.1 bjh21 int status; 390 1.1 bjh21 391 1.16 bjh21 DPRINTF(SEEQ_DEBUG_TX, ("ea_stoptx()\n")); 392 1.11 bjh21 393 1.11 bjh21 sc->sc_enabled = 0; 394 1.1 bjh21 395 1.24 bjh21 status = SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS); 396 1.10 bjh21 if (!(status & SEEQ_STATUS_TX_ON)) 397 1.1 bjh21 return 0; 398 1.1 bjh21 399 1.1 bjh21 /* Stop any tx and wait for confirmation */ 400 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 401 1.62 msaitoh sc->sc_command | SEEQ_CMD_TX_OFF); 402 1.1 bjh21 403 1.1 bjh21 timeout = 20000; 404 1.1 bjh21 do { 405 1.24 bjh21 status = SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS); 406 1.11 bjh21 delay(1); 407 1.10 bjh21 } while ((status & SEEQ_STATUS_TX_ON) && --timeout > 0); 408 1.63 msaitoh if (timeout == 0) 409 1.11 bjh21 log(LOG_ERR, "%s: timeout waiting for tx termination\n", 410 1.50 skrll device_xname(sc->sc_dev)); 411 1.1 bjh21 412 1.1 bjh21 /* Clear any pending tx interrupt */ 413 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 414 1.10 bjh21 sc->sc_command | SEEQ_CMD_TX_INTACK); 415 1.1 bjh21 return 1; 416 1.1 bjh21 } 417 1.1 bjh21 418 1.1 bjh21 419 1.1 bjh21 /* 420 1.1 bjh21 * Stop the rx interface. 421 1.1 bjh21 * 422 1.1 bjh21 * Returns 0 if the tx was already stopped or 1 if it was active 423 1.1 bjh21 */ 424 1.1 bjh21 425 1.1 bjh21 static int 426 1.1 bjh21 ea_stoprx(struct seeq8005_softc *sc) 427 1.1 bjh21 { 428 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 429 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 430 1.1 bjh21 int timeout; 431 1.1 bjh21 int status; 432 1.1 bjh21 433 1.16 bjh21 DPRINTF(SEEQ_DEBUG_RX, ("ea_stoprx()\n")); 434 1.1 bjh21 435 1.24 bjh21 status = SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS); 436 1.10 bjh21 if (!(status & SEEQ_STATUS_RX_ON)) 437 1.1 bjh21 return 0; 438 1.1 bjh21 439 1.1 bjh21 /* Stop any rx and wait for confirmation */ 440 1.1 bjh21 441 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 442 1.10 bjh21 sc->sc_command | SEEQ_CMD_RX_OFF); 443 1.1 bjh21 444 1.1 bjh21 timeout = 20000; 445 1.1 bjh21 do { 446 1.24 bjh21 status = SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS); 447 1.51 skrll delay(1); 448 1.10 bjh21 } while ((status & SEEQ_STATUS_RX_ON) && --timeout > 0); 449 1.1 bjh21 if (timeout == 0) 450 1.11 bjh21 log(LOG_ERR, "%s: timeout waiting for rx termination\n", 451 1.50 skrll device_xname(sc->sc_dev)); 452 1.1 bjh21 453 1.1 bjh21 /* Clear any pending rx interrupt */ 454 1.1 bjh21 455 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 456 1.10 bjh21 sc->sc_command | SEEQ_CMD_RX_INTACK); 457 1.1 bjh21 return 1; 458 1.1 bjh21 } 459 1.1 bjh21 460 1.1 bjh21 461 1.1 bjh21 /* 462 1.1 bjh21 * Stop interface. 463 1.1 bjh21 * Stop all IO and shut the interface down 464 1.1 bjh21 */ 465 1.1 bjh21 466 1.34 bjh21 /* ARGSUSED */ 467 1.1 bjh21 static void 468 1.5 bjh21 ea_stop(struct ifnet *ifp, int disable) 469 1.1 bjh21 { 470 1.5 bjh21 struct seeq8005_softc *sc = ifp->if_softc; 471 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 472 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 473 1.37 perry 474 1.16 bjh21 DPRINTF(SEEQ_DEBUG_MISC, ("ea_stop()\n")); 475 1.1 bjh21 476 1.1 bjh21 /* Stop all IO */ 477 1.1 bjh21 ea_stoptx(sc); 478 1.1 bjh21 ea_stoprx(sc); 479 1.1 bjh21 480 1.1 bjh21 /* Disable rx and tx interrupts */ 481 1.48 christos sc->sc_command &= ~(SEEQ_CMD_RX_INTEN | SEEQ_CMD_TX_INTEN); 482 1.1 bjh21 483 1.1 bjh21 /* Clear any pending interrupts */ 484 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 485 1.62 msaitoh sc->sc_command | SEEQ_CMD_RX_INTACK | SEEQ_CMD_TX_INTACK | 486 1.62 msaitoh SEEQ_CMD_DMA_INTACK | SEEQ_CMD_BW_INTACK); 487 1.11 bjh21 488 1.11 bjh21 if (sc->sc_variant == SEEQ_8004) { 489 1.11 bjh21 /* Put the chip to sleep */ 490 1.11 bjh21 ea_select_buffer(sc, SEEQ_BUFCODE_CONFIG3); 491 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, 492 1.11 bjh21 sc->sc_config3 | SEEQ_CFG3_SLEEP); 493 1.11 bjh21 } 494 1.1 bjh21 495 1.1 bjh21 /* Cancel any watchdog timer */ 496 1.48 christos sc->sc_ethercom.ec_if.if_timer = 0; 497 1.1 bjh21 } 498 1.1 bjh21 499 1.1 bjh21 500 1.1 bjh21 /* 501 1.1 bjh21 * Reset the chip 502 1.1 bjh21 * Following this the software registers are reset 503 1.1 bjh21 */ 504 1.1 bjh21 505 1.1 bjh21 static void 506 1.1 bjh21 ea_chipreset(struct seeq8005_softc *sc) 507 1.1 bjh21 { 508 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 509 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 510 1.1 bjh21 511 1.16 bjh21 DPRINTF(SEEQ_DEBUG_MISC, ("ea_chipreset()\n")); 512 1.1 bjh21 513 1.1 bjh21 /* Reset the controller. Min of 4us delay here */ 514 1.1 bjh21 515 1.24 bjh21 /* 516 1.24 bjh21 * This can be called before we know whether the chip is in 8- or 517 1.24 bjh21 * 16-bit mode, so we do a reset in both modes. The 16-bit reset is 518 1.24 bjh21 * harmless in 8-bit mode, so we do that second. 519 1.24 bjh21 */ 520 1.24 bjh21 521 1.24 bjh21 /* In 16-bit mode, this will munge the PreamSelect bit. */ 522 1.24 bjh21 bus_space_write_1(iot, ioh, SEEQ_CONFIG2 + 1, SEEQ_CFG2_RESET >> 8); 523 1.24 bjh21 delay(4); 524 1.24 bjh21 /* In 8-bit mode, this will zero the bottom half of config reg 2. */ 525 1.10 bjh21 bus_space_write_2(iot, ioh, SEEQ_CONFIG2, SEEQ_CFG2_RESET); 526 1.3 bjh21 delay(4); 527 1.1 bjh21 528 1.1 bjh21 sc->sc_command = 0; 529 1.1 bjh21 sc->sc_config1 = 0; 530 1.1 bjh21 sc->sc_config2 = 0; 531 1.11 bjh21 sc->sc_config3 = 0; 532 1.1 bjh21 } 533 1.1 bjh21 534 1.1 bjh21 535 1.1 bjh21 /* 536 1.1 bjh21 * If the DMA FIFO's in write mode, wait for it to empty. Needed when 537 1.1 bjh21 * switching the FIFO from write to read. We also use it when changing 538 1.1 bjh21 * the address for writes. 539 1.1 bjh21 */ 540 1.1 bjh21 static void 541 1.1 bjh21 ea_await_fifo_empty(struct seeq8005_softc *sc) 542 1.1 bjh21 { 543 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 544 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 545 1.1 bjh21 int timeout; 546 1.37 perry 547 1.1 bjh21 timeout = 20000; 548 1.24 bjh21 if ((SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS) & 549 1.10 bjh21 SEEQ_STATUS_FIFO_DIR) != 0) 550 1.1 bjh21 return; /* FIFO is reading anyway. */ 551 1.18 bjh21 while (--timeout > 0) 552 1.24 bjh21 if (SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS) & 553 1.18 bjh21 SEEQ_STATUS_FIFO_EMPTY) 554 1.18 bjh21 return; 555 1.64 msaitoh log(LOG_ERR, "%s: DMA FIFO failed to empty\n", 556 1.64 msaitoh device_xname(sc->sc_dev)); 557 1.1 bjh21 } 558 1.1 bjh21 559 1.1 bjh21 /* 560 1.1 bjh21 * Wait for the DMA FIFO to fill before reading from it. 561 1.1 bjh21 */ 562 1.1 bjh21 static void 563 1.1 bjh21 ea_await_fifo_full(struct seeq8005_softc *sc) 564 1.1 bjh21 { 565 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 566 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 567 1.1 bjh21 int timeout; 568 1.1 bjh21 569 1.1 bjh21 timeout = 20000; 570 1.18 bjh21 while (--timeout > 0) 571 1.24 bjh21 if (SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS) & 572 1.18 bjh21 SEEQ_STATUS_FIFO_FULL) 573 1.18 bjh21 return; 574 1.50 skrll log(LOG_ERR, "%s: DMA FIFO failed to fill\n", device_xname(sc->sc_dev)); 575 1.1 bjh21 } 576 1.1 bjh21 577 1.1 bjh21 /* 578 1.1 bjh21 * write to the buffer memory on the interface 579 1.1 bjh21 * 580 1.1 bjh21 * The buffer address is set to ADDR. 581 1.1 bjh21 * If len != 0 then data is copied from the address starting at buf 582 1.1 bjh21 * to the interface buffer. 583 1.62 msaitoh * BUF must be usable as a uint16_t *. 584 1.1 bjh21 * If LEN is odd, it must be safe to overwrite one extra byte. 585 1.1 bjh21 */ 586 1.1 bjh21 587 1.1 bjh21 static void 588 1.11 bjh21 ea_writebuf(struct seeq8005_softc *sc, u_char *buf, int addr, size_t len) 589 1.1 bjh21 { 590 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 591 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 592 1.1 bjh21 593 1.16 bjh21 DPRINTF(SEEQ_DEBUG_MISC, ("writebuf: st=%04x\n", 594 1.24 bjh21 SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS))); 595 1.1 bjh21 596 1.1 bjh21 #ifdef DIAGNOSTIC 597 1.62 msaitoh if (__predict_false(!ALIGNED_POINTER(buf, uint16_t))) 598 1.50 skrll panic("%s: unaligned writebuf", device_xname(sc->sc_dev)); 599 1.10 bjh21 if (__predict_false(addr >= SEEQ_MAX_BUFFER_SIZE)) 600 1.50 skrll panic("%s: writebuf out of range", device_xname(sc->sc_dev)); 601 1.14 bjh21 #endif 602 1.1 bjh21 603 1.11 bjh21 if (addr != -1) { 604 1.11 bjh21 ea_await_fifo_empty(sc); 605 1.1 bjh21 606 1.11 bjh21 ea_select_buffer(sc, SEEQ_BUFCODE_LOCAL_MEM); 607 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 608 1.11 bjh21 sc->sc_command | SEEQ_CMD_FIFO_WRITE); 609 1.51 skrll 610 1.51 skrll ea_await_fifo_empty(sc); 611 1.51 skrll 612 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_DMA_ADDR, addr); 613 1.11 bjh21 } 614 1.1 bjh21 615 1.24 bjh21 if (len > 0) { 616 1.24 bjh21 if (sc->sc_flags & SF_8BIT) 617 1.24 bjh21 bus_space_write_multi_1(iot, ioh, SEEQ_BUFWIN, 618 1.62 msaitoh (uint8_t *)buf, len); 619 1.24 bjh21 else 620 1.24 bjh21 bus_space_write_multi_2(iot, ioh, SEEQ_BUFWIN, 621 1.34 bjh21 /* LINTED: alignment checked above */ 622 1.62 msaitoh (uint16_t *)buf, len / 2); 623 1.24 bjh21 } 624 1.33 bjh21 if (!(sc->sc_flags & SF_8BIT) && len % 2) { 625 1.33 bjh21 /* Write the last byte */ 626 1.33 bjh21 bus_space_write_2(iot, ioh, SEEQ_BUFWIN, buf[len - 1]); 627 1.33 bjh21 } 628 1.1 bjh21 /* Leave FIFO to empty in the background */ 629 1.1 bjh21 } 630 1.1 bjh21 631 1.1 bjh21 632 1.1 bjh21 /* 633 1.1 bjh21 * read from the buffer memory on the interface 634 1.1 bjh21 * 635 1.1 bjh21 * The buffer address is set to ADDR. 636 1.1 bjh21 * If len != 0 then data is copied from the interface buffer to the 637 1.1 bjh21 * address starting at buf. 638 1.62 msaitoh * BUF must be usable as a uint16_t *. 639 1.1 bjh21 * If LEN is odd, it must be safe to overwrite one extra byte. 640 1.1 bjh21 */ 641 1.1 bjh21 642 1.1 bjh21 static void 643 1.11 bjh21 ea_readbuf(struct seeq8005_softc *sc, u_char *buf, int addr, size_t len) 644 1.1 bjh21 { 645 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 646 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 647 1.19 bjh21 int runup; 648 1.1 bjh21 649 1.16 bjh21 DPRINTF(SEEQ_DEBUG_MISC, ("readbuf: st=%04x addr=%04x len=%d\n", 650 1.24 bjh21 SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS), addr, len)); 651 1.1 bjh21 652 1.1 bjh21 #ifdef DIAGNOSTIC 653 1.62 msaitoh if (__predict_false(!ALIGNED_POINTER(buf, uint16_t))) 654 1.50 skrll panic("%s: unaligned readbuf", device_xname(sc->sc_dev)); 655 1.14 bjh21 if (__predict_false(addr >= SEEQ_MAX_BUFFER_SIZE)) 656 1.50 skrll panic("%s: readbuf out of range", device_xname(sc->sc_dev)); 657 1.1 bjh21 #endif 658 1.1 bjh21 659 1.11 bjh21 if (addr != -1) { 660 1.19 bjh21 /* 661 1.19 bjh21 * SEEQ 80C04 bug: 662 1.19 bjh21 * Starting reading from certain addresses seems to cause 663 1.19 bjh21 * us to get bogus results, so we avoid them. 664 1.19 bjh21 */ 665 1.19 bjh21 runup = 0; 666 1.19 bjh21 if (sc->sc_variant == SEEQ_8004 && 667 1.19 bjh21 ((addr & 0x00ff) == 0x00ea || 668 1.19 bjh21 (addr & 0x00ff) == 0x00ee || 669 1.19 bjh21 (addr & 0x00ff) == 0x00f0)) 670 1.19 bjh21 runup = (addr & 0x00ff) - 0x00e8; 671 1.19 bjh21 672 1.11 bjh21 ea_await_fifo_empty(sc); 673 1.1 bjh21 674 1.11 bjh21 ea_select_buffer(sc, SEEQ_BUFCODE_LOCAL_MEM); 675 1.21 bjh21 676 1.21 bjh21 /* 677 1.21 bjh21 * 80C04 bug workaround. I found this in the old arm32 "eb" 678 1.21 bjh21 * driver. I've no idea what it does, but it seems to stop 679 1.21 bjh21 * the chip mangling data so often. 680 1.21 bjh21 */ 681 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 682 1.21 bjh21 sc->sc_command | SEEQ_CMD_FIFO_WRITE); 683 1.21 bjh21 ea_await_fifo_empty(sc); 684 1.21 bjh21 685 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_DMA_ADDR, addr - runup); 686 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 687 1.11 bjh21 sc->sc_command | SEEQ_CMD_FIFO_READ); 688 1.1 bjh21 689 1.11 bjh21 ea_await_fifo_full(sc); 690 1.19 bjh21 while (runup > 0) { 691 1.34 bjh21 /* LINTED: Reading a volatile _does_ have an effect */ 692 1.24 bjh21 (void)SEEQ_READ16(sc, iot, ioh, SEEQ_BUFWIN); 693 1.19 bjh21 runup -= 2; 694 1.19 bjh21 } 695 1.11 bjh21 } 696 1.1 bjh21 697 1.24 bjh21 if (len > 0) { 698 1.24 bjh21 if (sc->sc_flags & SF_8BIT) 699 1.24 bjh21 bus_space_read_multi_1(iot, ioh, SEEQ_BUFWIN, 700 1.62 msaitoh (uint8_t *)buf, len); 701 1.24 bjh21 else 702 1.24 bjh21 bus_space_read_multi_2(iot, ioh, SEEQ_BUFWIN, 703 1.34 bjh21 /* LINTED: pointer alignment checked above */ 704 1.62 msaitoh (uint16_t *)buf, len / 2); 705 1.33 bjh21 } 706 1.33 bjh21 if (!(sc->sc_flags & SF_8BIT) && len % 2) { 707 1.33 bjh21 /* Read the last byte */ 708 1.33 bjh21 buf[len - 1] = bus_space_read_2(iot, ioh, SEEQ_BUFWIN); 709 1.24 bjh21 } 710 1.1 bjh21 } 711 1.1 bjh21 712 1.3 bjh21 static void 713 1.3 bjh21 ea_select_buffer(struct seeq8005_softc *sc, int bufcode) 714 1.3 bjh21 { 715 1.3 bjh21 716 1.24 bjh21 SEEQ_WRITE16(sc, sc->sc_iot, sc->sc_ioh, SEEQ_CONFIG1, 717 1.3 bjh21 sc->sc_config1 | bufcode); 718 1.3 bjh21 } 719 1.1 bjh21 720 1.5 bjh21 /* Must be called at splnet */ 721 1.5 bjh21 static void 722 1.62 msaitoh ea_set_address(struct seeq8005_softc *sc, int which, const uint8_t *ea) 723 1.5 bjh21 { 724 1.5 bjh21 int i; 725 1.5 bjh21 726 1.10 bjh21 ea_select_buffer(sc, SEEQ_BUFCODE_STATION_ADDR0 + which); 727 1.5 bjh21 for (i = 0; i < ETHER_ADDR_LEN; ++i) 728 1.62 msaitoh SEEQ_WRITE16(sc, sc->sc_iot, sc->sc_ioh, SEEQ_BUFWIN, ea[i]); 729 1.5 bjh21 } 730 1.5 bjh21 731 1.1 bjh21 /* 732 1.1 bjh21 * Initialize interface. 733 1.1 bjh21 * 734 1.1 bjh21 * This should leave the interface in a state for packet reception and 735 1.1 bjh21 * transmission. 736 1.1 bjh21 */ 737 1.1 bjh21 738 1.1 bjh21 static int 739 1.5 bjh21 ea_init(struct ifnet *ifp) 740 1.1 bjh21 { 741 1.5 bjh21 struct seeq8005_softc *sc = ifp->if_softc; 742 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 743 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 744 1.5 bjh21 int s; 745 1.1 bjh21 746 1.16 bjh21 DPRINTF(SEEQ_DEBUG_MISC, ("ea_init()\n")); 747 1.1 bjh21 748 1.1 bjh21 s = splnet(); 749 1.1 bjh21 750 1.1 bjh21 /* First, reset the board. */ 751 1.1 bjh21 752 1.3 bjh21 ea_chipreset(sc); 753 1.3 bjh21 754 1.3 bjh21 /* Set up defaults for the registers */ 755 1.3 bjh21 756 1.11 bjh21 sc->sc_command = 0; 757 1.11 bjh21 sc->sc_config1 = 0; 758 1.3 bjh21 #if BYTE_ORDER == BIG_ENDIAN 759 1.11 bjh21 sc->sc_config2 = SEEQ_CFG2_BYTESWAP; 760 1.3 bjh21 #else 761 1.3 bjh21 sc->sc_config2 = 0; 762 1.3 bjh21 #endif 763 1.11 bjh21 sc->sc_config3 = 0; 764 1.1 bjh21 765 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, sc->sc_command); 766 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG1, sc->sc_config1); 767 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2); 768 1.11 bjh21 if (sc->sc_variant == SEEQ_8004) { 769 1.11 bjh21 ea_select_buffer(sc, SEEQ_BUFCODE_CONFIG3); 770 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, sc->sc_config3); 771 1.11 bjh21 } 772 1.11 bjh21 773 1.11 bjh21 /* Write the station address - the receiver must be off */ 774 1.62 msaitoh ea_set_address(sc, 0, (const uint8_t *)CLLADDR(ifp->if_sadl)); 775 1.3 bjh21 776 1.3 bjh21 /* Split board memory into Rx and Tx. */ 777 1.10 bjh21 ea_select_buffer(sc, SEEQ_BUFCODE_TX_EAP); 778 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, (sc->sc_tx_bufsize>> 8) - 1); 779 1.3 bjh21 780 1.27 bjh21 if (sc->sc_variant == SEEQ_8004) { 781 1.27 bjh21 /* Make the interface IFF_SIMPLEX. */ 782 1.11 bjh21 sc->sc_config2 |= SEEQ_CFG2_RX_TX_DISABLE; 783 1.27 bjh21 /* Enable reception of long packets (for vlan(4)). */ 784 1.27 bjh21 sc->sc_config2 |= SEEQ_CFG2_PASS_LONGSHORT; 785 1.27 bjh21 } 786 1.1 bjh21 787 1.1 bjh21 /* Configure rx. */ 788 1.13 bjh21 ea_mc_reset(sc); 789 1.1 bjh21 if (ifp->if_flags & IFF_PROMISC) 790 1.10 bjh21 sc->sc_config1 = SEEQ_CFG1_PROMISCUOUS; 791 1.13 bjh21 else if ((ifp->if_flags & IFF_ALLMULTI) || sc->sc_variant == SEEQ_8004) 792 1.10 bjh21 sc->sc_config1 = SEEQ_CFG1_MULTICAST; 793 1.1 bjh21 else 794 1.10 bjh21 sc->sc_config1 = SEEQ_CFG1_BROADCAST; 795 1.10 bjh21 sc->sc_config1 |= SEEQ_CFG1_STATION_ADDR0; 796 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG1, sc->sc_config1); 797 1.3 bjh21 798 1.3 bjh21 /* Setup the Rx pointers */ 799 1.11 bjh21 sc->sc_rx_ptr = sc->sc_tx_bufsize; 800 1.3 bjh21 801 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_PTR, sc->sc_rx_ptr); 802 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_END, sc->sc_rx_ptr >> 8); 803 1.3 bjh21 804 1.3 bjh21 805 1.3 bjh21 /* Place a NULL header at the beginning of the receive area */ 806 1.3 bjh21 ea_writebuf(sc, NULL, sc->sc_rx_ptr, 0); 807 1.37 perry 808 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, 0x0000); 809 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, 0x0000); 810 1.1 bjh21 811 1.3 bjh21 812 1.1 bjh21 /* Configure TX. */ 813 1.16 bjh21 DPRINTF(SEEQ_DEBUG_MISC, ("Configuring tx...\n")); 814 1.1 bjh21 815 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_TX_PTR, 0x0000); 816 1.1 bjh21 817 1.10 bjh21 sc->sc_config2 |= SEEQ_CFG2_OUTPUT; 818 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2); 819 1.1 bjh21 820 1.11 bjh21 /* Reset tx buffer pointers */ 821 1.11 bjh21 sc->sc_tx_cur = 0; 822 1.11 bjh21 sc->sc_tx_used = 0; 823 1.11 bjh21 sc->sc_tx_next = 0; 824 1.1 bjh21 825 1.1 bjh21 /* Place a NULL header at the beginning of the transmit area */ 826 1.1 bjh21 ea_writebuf(sc, NULL, 0x0000, 0); 827 1.37 perry 828 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, 0x0000); 829 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_BUFWIN, 0x0000); 830 1.1 bjh21 831 1.10 bjh21 sc->sc_command |= SEEQ_CMD_TX_INTEN; 832 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, sc->sc_command); 833 1.1 bjh21 834 1.11 bjh21 /* Turn on Rx */ 835 1.11 bjh21 sc->sc_command |= SEEQ_CMD_RX_INTEN; 836 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 837 1.11 bjh21 sc->sc_command | SEEQ_CMD_RX_ON); 838 1.11 bjh21 839 1.49 skrll /* TX_ON gets set by ea_txpacket when there's something to transmit. */ 840 1.1 bjh21 841 1.1 bjh21 842 1.1 bjh21 /* Set flags appropriately. */ 843 1.1 bjh21 ifp->if_flags |= IFF_RUNNING; 844 1.1 bjh21 ifp->if_flags &= ~IFF_OACTIVE; 845 1.11 bjh21 sc->sc_enabled = 1; 846 1.1 bjh21 847 1.1 bjh21 /* And start output. */ 848 1.1 bjh21 ea_start(ifp); 849 1.1 bjh21 850 1.1 bjh21 splx(s); 851 1.1 bjh21 return 0; 852 1.1 bjh21 } 853 1.1 bjh21 854 1.1 bjh21 /* 855 1.1 bjh21 * Start output on interface. Get datagrams from the queue and output them, 856 1.1 bjh21 * giving the receiver a chance between datagrams. Call only from splnet or 857 1.1 bjh21 * interrupt level! 858 1.1 bjh21 */ 859 1.1 bjh21 860 1.1 bjh21 static void 861 1.1 bjh21 ea_start(struct ifnet *ifp) 862 1.1 bjh21 { 863 1.1 bjh21 struct seeq8005_softc *sc = ifp->if_softc; 864 1.1 bjh21 int s; 865 1.1 bjh21 866 1.1 bjh21 s = splnet(); 867 1.16 bjh21 DPRINTF(SEEQ_DEBUG_TX, ("ea_start()...\n")); 868 1.1 bjh21 869 1.14 bjh21 /* 870 1.14 bjh21 * Don't do anything if output is active. seeq8005intr() will call 871 1.49 skrll * us (actually ea_txpacket()) back when the card's ready for more 872 1.14 bjh21 * frames. 873 1.14 bjh21 */ 874 1.54 christos if (ifp->if_flags & IFF_OACTIVE) { 875 1.54 christos splx(s); 876 1.1 bjh21 return; 877 1.54 christos } 878 1.1 bjh21 879 1.1 bjh21 /* Mark interface as output active */ 880 1.37 perry 881 1.1 bjh21 ifp->if_flags |= IFF_OACTIVE; 882 1.1 bjh21 883 1.1 bjh21 /* tx packets */ 884 1.1 bjh21 885 1.49 skrll ea_txpacket(sc); 886 1.1 bjh21 splx(s); 887 1.1 bjh21 } 888 1.1 bjh21 889 1.1 bjh21 890 1.1 bjh21 /* 891 1.1 bjh21 * Transfer a packet to the interface buffer and start transmission 892 1.1 bjh21 * 893 1.1 bjh21 * Called at splnet() 894 1.1 bjh21 */ 895 1.37 perry 896 1.48 christos static void 897 1.49 skrll ea_txpacket(struct seeq8005_softc *sc) 898 1.1 bjh21 { 899 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 900 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 901 1.12 bjh21 struct mbuf *m0; 902 1.1 bjh21 struct ifnet *ifp; 903 1.1 bjh21 904 1.1 bjh21 ifp = &sc->sc_ethercom.ec_if; 905 1.1 bjh21 906 1.1 bjh21 /* Dequeue the next packet. */ 907 1.7 thorpej IFQ_DEQUEUE(&ifp->if_snd, m0); 908 1.1 bjh21 909 1.1 bjh21 /* If there's nothing to send, return. */ 910 1.51 skrll if (m0 == NULL) { 911 1.1 bjh21 ifp->if_flags &= ~IFF_OACTIVE; 912 1.10 bjh21 sc->sc_config2 |= SEEQ_CFG2_OUTPUT; 913 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2); 914 1.16 bjh21 DPRINTF(SEEQ_DEBUG_TX, ("tx finished\n")); 915 1.1 bjh21 return; 916 1.1 bjh21 } 917 1.1 bjh21 918 1.1 bjh21 /* Give the packet to the bpf, if any. */ 919 1.59 msaitoh bpf_mtap(ifp, m0, BPF_D_OUT); 920 1.1 bjh21 921 1.16 bjh21 DPRINTF(SEEQ_DEBUG_TX, ("Tx new packet\n")); 922 1.1 bjh21 923 1.10 bjh21 sc->sc_config2 &= ~SEEQ_CFG2_OUTPUT; 924 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2); 925 1.1 bjh21 926 1.12 bjh21 ea_writembuf(sc, m0, 0x0000); 927 1.12 bjh21 m_freem(m0); 928 1.12 bjh21 929 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_TX_PTR, 0x0000); 930 1.12 bjh21 931 1.12 bjh21 /* Now transmit the datagram. */ 932 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 933 1.12 bjh21 sc->sc_command | SEEQ_CMD_TX_ON); 934 1.15 bjh21 935 1.15 bjh21 /* Make sure we notice if the chip goes silent on us. */ 936 1.15 bjh21 ifp->if_timer = 5; 937 1.15 bjh21 938 1.16 bjh21 DPRINTF(SEEQ_DEBUG_TX, 939 1.24 bjh21 ("st=%04x\n", SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS))); 940 1.16 bjh21 DPRINTF(SEEQ_DEBUG_TX, ("tx: queued\n")); 941 1.12 bjh21 } 942 1.12 bjh21 943 1.12 bjh21 /* 944 1.12 bjh21 * Copy a packet from an mbuf to the transmit buffer on the card. 945 1.12 bjh21 * 946 1.12 bjh21 * Puts a valid Tx header at the start of the packet, and a null header at 947 1.12 bjh21 * the end. 948 1.12 bjh21 */ 949 1.12 bjh21 static int 950 1.12 bjh21 ea_writembuf(struct seeq8005_softc *sc, struct mbuf *m0, int bufstart) 951 1.12 bjh21 { 952 1.12 bjh21 struct mbuf *m; 953 1.12 bjh21 int len, nextpacket; 954 1.62 msaitoh uint8_t hdr[4]; 955 1.12 bjh21 956 1.1 bjh21 /* 957 1.12 bjh21 * Copy the datagram to the packet buffer. 958 1.1 bjh21 */ 959 1.1 bjh21 len = 0; 960 1.1 bjh21 for (m = m0; m; m = m->m_next) { 961 1.1 bjh21 if (m->m_len == 0) 962 1.1 bjh21 continue; 963 1.34 bjh21 ea_writebuf(sc, mtod(m, u_char *), bufstart + 4 + len, 964 1.22 bjh21 m->m_len); 965 1.1 bjh21 len += m->m_len; 966 1.1 bjh21 } 967 1.1 bjh21 968 1.35 bouyer if (len < ETHER_MIN_LEN) { 969 1.35 bouyer ea_writebuf(sc, padbuf, bufstart + 4 + len, 970 1.35 bouyer ETHER_MIN_LEN - len); 971 1.35 bouyer len = ETHER_MIN_LEN; 972 1.35 bouyer } 973 1.1 bjh21 974 1.1 bjh21 /* Follow it with a NULL packet header */ 975 1.22 bjh21 memset(hdr, 0, 4); 976 1.22 bjh21 ea_writebuf(sc, hdr, bufstart + 4 + len, 4); 977 1.1 bjh21 978 1.12 bjh21 /* Ok we now have a packet len bytes long in our packet buffer */ 979 1.16 bjh21 DPRINTF(SEEQ_DEBUG_TX, ("ea_writembuf: length=%d\n", len)); 980 1.1 bjh21 981 1.1 bjh21 /* Write the packet header */ 982 1.51 skrll nextpacket = bufstart + len + 4; 983 1.1 bjh21 hdr[0] = (nextpacket >> 8) & 0xff; 984 1.1 bjh21 hdr[1] = nextpacket & 0xff; 985 1.10 bjh21 hdr[2] = SEEQ_PKTCMD_TX | SEEQ_PKTCMD_DATA_FOLLOWS | 986 1.10 bjh21 SEEQ_TXCMD_XMIT_SUCCESS_INT | SEEQ_TXCMD_COLLISION_INT; 987 1.48 christos hdr[3] = 0; /* Status byte -- will be updated by hardware. */ 988 1.51 skrll ea_writebuf(sc, hdr, bufstart, 4); 989 1.1 bjh21 990 1.12 bjh21 return len; 991 1.1 bjh21 } 992 1.1 bjh21 993 1.1 bjh21 /* 994 1.1 bjh21 * Ethernet controller interrupt. 995 1.1 bjh21 */ 996 1.1 bjh21 997 1.1 bjh21 int 998 1.1 bjh21 seeq8005intr(void *arg) 999 1.1 bjh21 { 1000 1.1 bjh21 struct seeq8005_softc *sc = arg; 1001 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 1002 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 1003 1.11 bjh21 int status, handled; 1004 1.1 bjh21 1005 1.1 bjh21 handled = 0; 1006 1.1 bjh21 1007 1.1 bjh21 /* Get the controller status */ 1008 1.24 bjh21 status = SEEQ_READ16(sc, iot, ioh, SEEQ_STATUS); 1009 1.1 bjh21 1010 1.1 bjh21 /* Tx interrupt ? */ 1011 1.10 bjh21 if (status & SEEQ_STATUS_TX_INT) { 1012 1.1 bjh21 handled = 1; 1013 1.1 bjh21 1014 1.1 bjh21 /* Acknowledge the interrupt */ 1015 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 1016 1.10 bjh21 sc->sc_command | SEEQ_CMD_TX_INTACK); 1017 1.1 bjh21 1018 1.20 bjh21 ea_txint(sc); 1019 1.1 bjh21 } 1020 1.1 bjh21 1021 1.1 bjh21 1022 1.1 bjh21 /* Rx interrupt ? */ 1023 1.10 bjh21 if (status & SEEQ_STATUS_RX_INT) { 1024 1.1 bjh21 handled = 1; 1025 1.1 bjh21 1026 1.1 bjh21 /* Acknowledge the interrupt */ 1027 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 1028 1.10 bjh21 sc->sc_command | SEEQ_CMD_RX_INTACK); 1029 1.1 bjh21 1030 1.1 bjh21 /* Processes the received packets */ 1031 1.20 bjh21 ea_rxint(sc); 1032 1.20 bjh21 } 1033 1.1 bjh21 1034 1.30 bjh21 if (handled) 1035 1.30 bjh21 rnd_add_uint32(&sc->rnd_source, status); 1036 1.46 tls 1037 1.20 bjh21 return handled; 1038 1.20 bjh21 } 1039 1.1 bjh21 1040 1.20 bjh21 static void 1041 1.20 bjh21 ea_txint(struct seeq8005_softc *sc) 1042 1.20 bjh21 { 1043 1.20 bjh21 struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1044 1.20 bjh21 bus_space_tag_t iot = sc->sc_iot; 1045 1.20 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 1046 1.62 msaitoh uint8_t txhdr[4]; 1047 1.20 bjh21 u_int txstatus; 1048 1.20 bjh21 1049 1.20 bjh21 ea_readbuf(sc, txhdr, 0x0000, 4); 1050 1.20 bjh21 1051 1.20 bjh21 DPRINTF(SEEQ_DEBUG_TX, ("txstatus=%02x %02x %02x %02x\n", 1052 1.20 bjh21 txhdr[0], txhdr[1], txhdr[2], txhdr[3])); 1053 1.20 bjh21 txstatus = txhdr[3]; 1054 1.20 bjh21 1055 1.20 bjh21 /* 1056 1.20 bjh21 * If SEEQ_TXSTAT_COLLISION is set then we received at least 1057 1.20 bjh21 * one collision. On the 8004 we can find out exactly how many 1058 1.20 bjh21 * collisions occurred. 1059 1.20 bjh21 * 1060 1.20 bjh21 * The SEEQ_PKTSTAT_DONE will be set if the transmission has 1061 1.20 bjh21 * completed. 1062 1.20 bjh21 * 1063 1.20 bjh21 * If SEEQ_TXSTAT_COLLISION16 is set then 16 collisions 1064 1.20 bjh21 * occurred and the packet transmission was aborted. 1065 1.20 bjh21 * This situation is untested as present. 1066 1.20 bjh21 * 1067 1.27 bjh21 * The SEEQ_TXSTAT_BABBLE is untested as it should only be set 1068 1.27 bjh21 * when we deliberately transmit oversized packets (e.g. for 1069 1.27 bjh21 * 802.1Q). 1070 1.20 bjh21 */ 1071 1.20 bjh21 if (txstatus & SEEQ_TXSTAT_COLLISION) { 1072 1.20 bjh21 switch (sc->sc_variant) { 1073 1.20 bjh21 case SEEQ_8004: { 1074 1.20 bjh21 int colls; 1075 1.20 bjh21 1076 1.20 bjh21 /* 1077 1.20 bjh21 * The 8004 contains a 4 bit collision count 1078 1.20 bjh21 * in the status register. 1079 1.20 bjh21 */ 1080 1.66 thorpej #if 0 1081 1.20 bjh21 /* This appears to be broken on 80C04.AE */ 1082 1.66 thorpej if_statadd(ifp, if_collisions, 1083 1.20 bjh21 (txstatus >> SEEQ_TXSTAT_COLLISIONS_SHIFT) 1084 1.66 thorpej & SEEQ_TXSTAT_COLLISION_MASK; 1085 1.66 thorpej #endif 1086 1.37 perry 1087 1.20 bjh21 /* Use the TX Collision register */ 1088 1.20 bjh21 ea_select_buffer(sc, SEEQ_BUFCODE_TX_COLLS); 1089 1.20 bjh21 colls = bus_space_read_1(iot, ioh, SEEQ_BUFWIN); 1090 1.66 thorpej if_statadd(ifp, if_collisions, colls); 1091 1.20 bjh21 break; 1092 1.1 bjh21 } 1093 1.20 bjh21 case SEEQ_8005: 1094 1.20 bjh21 /* We known there was at least 1 collision */ 1095 1.66 thorpej if_statinc(ifp, if_collisions); 1096 1.20 bjh21 break; 1097 1.20 bjh21 } 1098 1.20 bjh21 } else if (txstatus & SEEQ_TXSTAT_COLLISION16) { 1099 1.20 bjh21 printf("seeq_intr: col16 %x\n", txstatus); 1100 1.66 thorpej if_statadd2(ifp, if_collisions, 16, if_oerrors, 1); 1101 1.1 bjh21 } 1102 1.1 bjh21 1103 1.20 bjh21 /* Have we completed transmission on the packet ? */ 1104 1.20 bjh21 if (txstatus & SEEQ_PKTSTAT_DONE) { 1105 1.20 bjh21 /* Clear watchdog timer. */ 1106 1.20 bjh21 ifp->if_timer = 0; 1107 1.20 bjh21 ifp->if_flags &= ~IFF_OACTIVE; 1108 1.20 bjh21 1109 1.20 bjh21 /* Update stats */ 1110 1.66 thorpej if_statinc(ifp, if_opackets); 1111 1.20 bjh21 1112 1.20 bjh21 /* Tx next packet */ 1113 1.20 bjh21 1114 1.49 skrll ea_txpacket(sc); 1115 1.20 bjh21 } 1116 1.1 bjh21 } 1117 1.1 bjh21 1118 1.48 christos static void 1119 1.20 bjh21 ea_rxint(struct seeq8005_softc *sc) 1120 1.1 bjh21 { 1121 1.1 bjh21 bus_space_tag_t iot = sc->sc_iot; 1122 1.1 bjh21 bus_space_handle_t ioh = sc->sc_ioh; 1123 1.1 bjh21 u_int addr; 1124 1.1 bjh21 int len; 1125 1.1 bjh21 int ctrl; 1126 1.1 bjh21 int ptr; 1127 1.1 bjh21 int status; 1128 1.62 msaitoh uint8_t rxhdr[4]; 1129 1.1 bjh21 struct ifnet *ifp; 1130 1.1 bjh21 1131 1.1 bjh21 ifp = &sc->sc_ethercom.ec_if; 1132 1.1 bjh21 1133 1.1 bjh21 1134 1.1 bjh21 /* We start from the last rx pointer position */ 1135 1.1 bjh21 addr = sc->sc_rx_ptr; 1136 1.10 bjh21 sc->sc_config2 &= ~SEEQ_CFG2_OUTPUT; 1137 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2); 1138 1.1 bjh21 1139 1.1 bjh21 do { 1140 1.1 bjh21 /* Read rx header */ 1141 1.1 bjh21 ea_readbuf(sc, rxhdr, addr, 4); 1142 1.37 perry 1143 1.1 bjh21 /* Split the packet header */ 1144 1.1 bjh21 ptr = (rxhdr[0] << 8) | rxhdr[1]; 1145 1.1 bjh21 ctrl = rxhdr[2]; 1146 1.1 bjh21 status = rxhdr[3]; 1147 1.1 bjh21 1148 1.16 bjh21 DPRINTF(SEEQ_DEBUG_RX, 1149 1.16 bjh21 ("addr=%04x ptr=%04x ctrl=%02x status=%02x\n", 1150 1.16 bjh21 addr, ptr, ctrl, status)); 1151 1.1 bjh21 1152 1.1 bjh21 /* Zero packet ptr ? then must be null header so exit */ 1153 1.1 bjh21 if (ptr == 0) break; 1154 1.1 bjh21 1155 1.15 bjh21 /* Sanity-check the next-packet pointer and flags. */ 1156 1.15 bjh21 if (__predict_false(ptr < sc->sc_tx_bufsize || 1157 1.15 bjh21 (ctrl & SEEQ_PKTCMD_TX))) { 1158 1.66 thorpej if_statinc(ifp, if_ierrors); 1159 1.15 bjh21 log(LOG_ERR, 1160 1.15 bjh21 "%s: Rx chain corrupt at %04x (ptr = %04x)\n", 1161 1.50 skrll device_xname(sc->sc_dev), addr, ptr); 1162 1.15 bjh21 ea_init(ifp); 1163 1.15 bjh21 return; 1164 1.15 bjh21 } 1165 1.1 bjh21 1166 1.1 bjh21 /* Get packet length */ 1167 1.48 christos len = (ptr - addr) - 4; 1168 1.1 bjh21 1169 1.1 bjh21 if (len < 0) 1170 1.11 bjh21 len += sc->sc_rx_bufsize; 1171 1.16 bjh21 DPRINTF(SEEQ_DEBUG_RX, ("len=%04x\n", len)); 1172 1.1 bjh21 1173 1.1 bjh21 /* Has the packet rx completed ? if not then exit */ 1174 1.10 bjh21 if ((status & SEEQ_PKTSTAT_DONE) == 0) 1175 1.1 bjh21 break; 1176 1.1 bjh21 1177 1.1 bjh21 /* 1178 1.1 bjh21 * Did we have any errors? then note error and go to 1179 1.1 bjh21 * next packet 1180 1.1 bjh21 */ 1181 1.27 bjh21 if (__predict_false(status & 1182 1.27 bjh21 (SEEQ_RXSTAT_CRC_ERROR | SEEQ_RXSTAT_DRIBBLE_ERROR | 1183 1.27 bjh21 SEEQ_RXSTAT_SHORT_FRAME))) { 1184 1.66 thorpej if_statinc(ifp, if_ierrors); 1185 1.1 bjh21 log(LOG_WARNING, 1186 1.17 bjh21 "%s: rx packet error at %04x (err=%02x)\n", 1187 1.50 skrll device_xname(sc->sc_dev), addr, status & 0x0f); 1188 1.19 bjh21 /* XXX shouldn't need to reset if it's genuine. */ 1189 1.19 bjh21 ea_init(ifp); 1190 1.19 bjh21 return; 1191 1.1 bjh21 } 1192 1.1 bjh21 /* 1193 1.27 bjh21 * Is the packet too big? We allow slightly oversize packets 1194 1.27 bjh21 * for vlan(4) and tcpdump purposes, but the rest of the world 1195 1.27 bjh21 * wants incoming packets in a single mbuf cluster. 1196 1.1 bjh21 */ 1197 1.27 bjh21 if (__predict_false(len > MCLBYTES)) { 1198 1.66 thorpej if_statinc(ifp, if_ierrors); 1199 1.17 bjh21 log(LOG_ERR, 1200 1.17 bjh21 "%s: rx packet size error at %04x (len=%d)\n", 1201 1.50 skrll device_xname(sc->sc_dev), addr, len); 1202 1.5 bjh21 ea_init(ifp); 1203 1.1 bjh21 return; 1204 1.1 bjh21 } 1205 1.1 bjh21 1206 1.1 bjh21 /* Pass data up to upper levels. */ 1207 1.11 bjh21 ea_read(sc, addr + 4, len); 1208 1.1 bjh21 1209 1.1 bjh21 addr = ptr; 1210 1.1 bjh21 } while (len != 0); 1211 1.1 bjh21 1212 1.10 bjh21 sc->sc_config2 |= SEEQ_CFG2_OUTPUT; 1213 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_CONFIG2, sc->sc_config2); 1214 1.1 bjh21 1215 1.16 bjh21 DPRINTF(SEEQ_DEBUG_RX, ("new rx ptr=%04x\n", addr)); 1216 1.1 bjh21 1217 1.1 bjh21 /* Store new rx pointer */ 1218 1.1 bjh21 sc->sc_rx_ptr = addr; 1219 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_RX_END, sc->sc_rx_ptr >> 8); 1220 1.1 bjh21 1221 1.1 bjh21 /* Make sure the receiver is on */ 1222 1.24 bjh21 SEEQ_WRITE16(sc, iot, ioh, SEEQ_COMMAND, 1223 1.10 bjh21 sc->sc_command | SEEQ_CMD_RX_ON); 1224 1.1 bjh21 } 1225 1.1 bjh21 1226 1.1 bjh21 1227 1.1 bjh21 /* 1228 1.1 bjh21 * Pass a packet up to the higher levels. 1229 1.1 bjh21 */ 1230 1.1 bjh21 1231 1.1 bjh21 static void 1232 1.11 bjh21 ea_read(struct seeq8005_softc *sc, int addr, int len) 1233 1.1 bjh21 { 1234 1.1 bjh21 struct mbuf *m; 1235 1.1 bjh21 struct ifnet *ifp; 1236 1.1 bjh21 1237 1.1 bjh21 ifp = &sc->sc_ethercom.ec_if; 1238 1.1 bjh21 1239 1.1 bjh21 /* Pull packet off interface. */ 1240 1.11 bjh21 m = ea_get(sc, addr, len, ifp); 1241 1.48 christos if (m == NULL) 1242 1.1 bjh21 return; 1243 1.1 bjh21 1244 1.55 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 1245 1.1 bjh21 } 1246 1.1 bjh21 1247 1.1 bjh21 /* 1248 1.1 bjh21 * Pull read data off a interface. Len is length of data, with local net 1249 1.1 bjh21 * header stripped. We copy the data into mbufs. When full cluster sized 1250 1.1 bjh21 * units are present we copy into clusters. 1251 1.1 bjh21 */ 1252 1.1 bjh21 1253 1.1 bjh21 struct mbuf * 1254 1.11 bjh21 ea_get(struct seeq8005_softc *sc, int addr, int totlen, struct ifnet *ifp) 1255 1.1 bjh21 { 1256 1.63 msaitoh struct mbuf *top, **mp, *m; 1257 1.63 msaitoh int len; 1258 1.63 msaitoh u_int cp, epkt; 1259 1.63 msaitoh 1260 1.63 msaitoh cp = addr; 1261 1.63 msaitoh epkt = cp + totlen; 1262 1.63 msaitoh 1263 1.63 msaitoh MGETHDR(m, M_DONTWAIT, MT_DATA); 1264 1.63 msaitoh if (m == NULL) 1265 1.63 msaitoh return NULL; 1266 1.63 msaitoh m_set_rcvif(m, ifp); 1267 1.63 msaitoh m->m_pkthdr.len = totlen; 1268 1.63 msaitoh m->m_len = MHLEN; 1269 1.63 msaitoh top = NULL; 1270 1.63 msaitoh mp = ⊤ 1271 1.63 msaitoh 1272 1.63 msaitoh while (totlen > 0) { 1273 1.63 msaitoh if (top) { 1274 1.63 msaitoh MGET(m, M_DONTWAIT, MT_DATA); 1275 1.63 msaitoh if (m == NULL) { 1276 1.63 msaitoh m_freem(top); 1277 1.63 msaitoh return NULL; 1278 1.63 msaitoh } 1279 1.63 msaitoh m->m_len = MLEN; 1280 1.63 msaitoh } 1281 1.63 msaitoh len = uimin(totlen, epkt - cp); 1282 1.63 msaitoh if (len >= MINCLSIZE) { 1283 1.63 msaitoh MCLGET(m, M_DONTWAIT); 1284 1.63 msaitoh if (m->m_flags & M_EXT) 1285 1.63 msaitoh m->m_len = len = uimin(len, MCLBYTES); 1286 1.63 msaitoh else 1287 1.63 msaitoh len = m->m_len; 1288 1.63 msaitoh } else { 1289 1.63 msaitoh /* 1290 1.63 msaitoh * Place initial small packet/header at end of mbuf. 1291 1.63 msaitoh */ 1292 1.63 msaitoh if (len < m->m_len) { 1293 1.63 msaitoh if (top == NULL && len + max_linkhdr <= m->m_len) 1294 1.63 msaitoh m->m_data += max_linkhdr; 1295 1.63 msaitoh m->m_len = len; 1296 1.63 msaitoh } else 1297 1.63 msaitoh len = m->m_len; 1298 1.63 msaitoh } 1299 1.48 christos if (top == NULL) { 1300 1.1 bjh21 /* Make sure the payload is aligned */ 1301 1.40 he char *newdata = (char *) 1302 1.62 msaitoh ALIGN((char*)m->m_data + 1303 1.40 he sizeof(struct ether_header)) - 1304 1.1 bjh21 sizeof(struct ether_header); 1305 1.1 bjh21 len -= newdata - m->m_data; 1306 1.1 bjh21 m->m_len = len; 1307 1.1 bjh21 m->m_data = newdata; 1308 1.1 bjh21 } 1309 1.63 msaitoh ea_readbuf(sc, mtod(m, u_char *), 1310 1.11 bjh21 cp < SEEQ_MAX_BUFFER_SIZE ? cp : cp - sc->sc_rx_bufsize, 1311 1.11 bjh21 len); 1312 1.63 msaitoh cp += len; 1313 1.63 msaitoh *mp = m; 1314 1.63 msaitoh mp = &m->m_next; 1315 1.63 msaitoh totlen -= len; 1316 1.63 msaitoh if (cp == epkt) 1317 1.63 msaitoh cp = addr; 1318 1.63 msaitoh } 1319 1.1 bjh21 1320 1.63 msaitoh return top; 1321 1.1 bjh21 } 1322 1.1 bjh21 1323 1.1 bjh21 /* 1324 1.3 bjh21 * Process an ioctl request. Mostly boilerplate. 1325 1.1 bjh21 */ 1326 1.1 bjh21 static int 1327 1.39 christos ea_ioctl(struct ifnet *ifp, u_long cmd, void *data) 1328 1.1 bjh21 { 1329 1.1 bjh21 struct seeq8005_softc *sc = ifp->if_softc; 1330 1.1 bjh21 int s, error = 0; 1331 1.1 bjh21 1332 1.1 bjh21 s = splnet(); 1333 1.1 bjh21 switch (cmd) { 1334 1.1 bjh21 1335 1.5 bjh21 default: 1336 1.5 bjh21 error = ether_ioctl(ifp, cmd, data); 1337 1.5 bjh21 if (error == ENETRESET) { 1338 1.1 bjh21 /* 1339 1.5 bjh21 * Multicast list has changed; set the hardware filter 1340 1.5 bjh21 * accordingly. 1341 1.1 bjh21 */ 1342 1.36 thorpej if (ifp->if_flags & IFF_RUNNING) 1343 1.36 thorpej ea_mc_reset(sc); 1344 1.5 bjh21 error = 0; 1345 1.1 bjh21 } 1346 1.1 bjh21 break; 1347 1.1 bjh21 } 1348 1.1 bjh21 1349 1.1 bjh21 splx(s); 1350 1.1 bjh21 return error; 1351 1.1 bjh21 } 1352 1.1 bjh21 1353 1.5 bjh21 /* Must be called at splnet() */ 1354 1.11 bjh21 1355 1.5 bjh21 static void 1356 1.5 bjh21 ea_mc_reset(struct seeq8005_softc *sc) 1357 1.5 bjh21 { 1358 1.11 bjh21 1359 1.11 bjh21 switch (sc->sc_variant) { 1360 1.11 bjh21 case SEEQ_8004: 1361 1.11 bjh21 ea_mc_reset_8004(sc); 1362 1.11 bjh21 return; 1363 1.11 bjh21 case SEEQ_8005: 1364 1.11 bjh21 ea_mc_reset_8005(sc); 1365 1.11 bjh21 return; 1366 1.11 bjh21 } 1367 1.11 bjh21 } 1368 1.11 bjh21 1369 1.11 bjh21 static void 1370 1.11 bjh21 ea_mc_reset_8004(struct seeq8005_softc *sc) 1371 1.11 bjh21 { 1372 1.11 bjh21 struct ethercom *ec = &sc->sc_ethercom; 1373 1.11 bjh21 struct ifnet *ifp = &ec->ec_if; 1374 1.11 bjh21 struct ether_multi *enm; 1375 1.63 msaitoh uint32_t crc; 1376 1.63 msaitoh int i; 1377 1.63 msaitoh struct ether_multistep step; 1378 1.63 msaitoh uint8_t af[8]; 1379 1.11 bjh21 1380 1.11 bjh21 /* 1381 1.11 bjh21 * Set up multicast address filter by passing all multicast addresses 1382 1.11 bjh21 * through a crc generator, and then using bits 2 - 7 as an index 1383 1.11 bjh21 * into the 64 bit logical address filter. The high order bits 1384 1.11 bjh21 * selects the word, while the rest of the bits select the bit within 1385 1.11 bjh21 * the word. 1386 1.11 bjh21 */ 1387 1.11 bjh21 1388 1.11 bjh21 if (ifp->if_flags & IFF_PROMISC) { 1389 1.11 bjh21 ifp->if_flags |= IFF_ALLMULTI; 1390 1.11 bjh21 for (i = 0; i < 8; i++) 1391 1.11 bjh21 af[i] = 0xff; 1392 1.11 bjh21 return; 1393 1.11 bjh21 } 1394 1.11 bjh21 for (i = 0; i < 8; i++) 1395 1.11 bjh21 af[i] = 0; 1396 1.64 msaitoh 1397 1.64 msaitoh ETHER_LOCK(ec); 1398 1.11 bjh21 ETHER_FIRST_MULTI(step, ec, enm); 1399 1.11 bjh21 while (enm != NULL) { 1400 1.28 thorpej if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 1401 1.11 bjh21 sizeof(enm->enm_addrlo)) != 0) { 1402 1.11 bjh21 /* 1403 1.11 bjh21 * We must listen to a range of multicast addresses. 1404 1.11 bjh21 * For now, just accept all multicasts, rather than 1405 1.11 bjh21 * trying to set only those filter bits needed to match 1406 1.11 bjh21 * the range. (At this time, the only use of address 1407 1.11 bjh21 * ranges is for IP multicast routing, for which the 1408 1.11 bjh21 * range is big enough to require all bits set.) 1409 1.11 bjh21 */ 1410 1.11 bjh21 ifp->if_flags |= IFF_ALLMULTI; 1411 1.11 bjh21 for (i = 0; i < 8; i++) 1412 1.11 bjh21 af[i] = 0xff; 1413 1.13 bjh21 break; 1414 1.11 bjh21 } 1415 1.26 bjh21 1416 1.26 bjh21 crc = ether_crc32_be(enm->enm_addrlo, sizeof(enm->enm_addrlo)); 1417 1.26 bjh21 1418 1.11 bjh21 /* Just want the 6 most significant bits. */ 1419 1.11 bjh21 crc = (crc >> 2) & 0x3f; 1420 1.11 bjh21 1421 1.11 bjh21 /* Turn on the corresponding bit in the filter. */ 1422 1.11 bjh21 af[crc >> 3] |= 1 << (crc & 0x7); 1423 1.11 bjh21 1424 1.11 bjh21 ETHER_NEXT_MULTI(step, enm); 1425 1.11 bjh21 } 1426 1.64 msaitoh ETHER_UNLOCK(ec); 1427 1.11 bjh21 ifp->if_flags &= ~IFF_ALLMULTI; 1428 1.11 bjh21 1429 1.11 bjh21 ea_select_buffer(sc, SEEQ_BUFCODE_MULTICAST); 1430 1.11 bjh21 for (i = 0; i < 8; ++i) 1431 1.11 bjh21 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 1432 1.11 bjh21 SEEQ_BUFWIN, af[i]); 1433 1.11 bjh21 } 1434 1.11 bjh21 1435 1.11 bjh21 static void 1436 1.11 bjh21 ea_mc_reset_8005(struct seeq8005_softc *sc) 1437 1.11 bjh21 { 1438 1.62 msaitoh struct ethercom *ec = &sc->sc_ethercom; 1439 1.5 bjh21 struct ether_multi *enm; 1440 1.5 bjh21 struct ether_multistep step; 1441 1.5 bjh21 int naddr, maxaddrs; 1442 1.5 bjh21 1443 1.5 bjh21 naddr = 0; 1444 1.11 bjh21 maxaddrs = 5; 1445 1.64 msaitoh ETHER_LOCK(ec); 1446 1.62 msaitoh ETHER_FIRST_MULTI(step, ec, enm); 1447 1.5 bjh21 while (enm != NULL) { 1448 1.5 bjh21 /* Have we got space? */ 1449 1.5 bjh21 if (naddr >= maxaddrs || 1450 1.28 thorpej memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { 1451 1.62 msaitoh ec->ec_if.if_flags |= IFF_ALLMULTI; 1452 1.64 msaitoh ETHER_UNLOCK(ec); 1453 1.62 msaitoh ea_ioctl(&ec->ec_if, SIOCSIFFLAGS, NULL); 1454 1.5 bjh21 return; 1455 1.5 bjh21 } 1456 1.11 bjh21 ea_set_address(sc, 1 + naddr, enm->enm_addrlo); 1457 1.11 bjh21 sc->sc_config1 |= SEEQ_CFG1_STATION_ADDR1 << naddr; 1458 1.5 bjh21 naddr++; 1459 1.5 bjh21 ETHER_NEXT_MULTI(step, enm); 1460 1.5 bjh21 } 1461 1.64 msaitoh ETHER_UNLOCK(ec); 1462 1.64 msaitoh 1463 1.5 bjh21 for (; naddr < maxaddrs; naddr++) 1464 1.11 bjh21 sc->sc_config1 &= ~(SEEQ_CFG1_STATION_ADDR1 << naddr); 1465 1.24 bjh21 SEEQ_WRITE16(sc, sc->sc_iot, sc->sc_ioh, SEEQ_CONFIG1, 1466 1.5 bjh21 sc->sc_config1); 1467 1.5 bjh21 } 1468 1.5 bjh21 1469 1.1 bjh21 /* 1470 1.1 bjh21 * Device timeout routine. 1471 1.1 bjh21 */ 1472 1.1 bjh21 1473 1.1 bjh21 static void 1474 1.1 bjh21 ea_watchdog(struct ifnet *ifp) 1475 1.1 bjh21 { 1476 1.1 bjh21 struct seeq8005_softc *sc = ifp->if_softc; 1477 1.1 bjh21 1478 1.15 bjh21 log(LOG_ERR, "%s: lost Tx interrupt (status = 0x%04x)\n", 1479 1.50 skrll device_xname(sc->sc_dev), 1480 1.24 bjh21 SEEQ_READ16(sc, sc->sc_iot, sc->sc_ioh, SEEQ_STATUS)); 1481 1.66 thorpej if_statinc(ifp, if_oerrors); 1482 1.1 bjh21 1483 1.1 bjh21 /* Kick the interface */ 1484 1.1 bjh21 1485 1.5 bjh21 ea_init(ifp); 1486 1.1 bjh21 1487 1.1 bjh21 ifp->if_timer = 0; 1488 1.1 bjh21 } 1489 1.1 bjh21 1490 1.48 christos /* End of seeq8005.c */ 1491