1 1.91 andvar /* $NetBSD: i82586.c,v 1.91 2024/02/09 22:08:34 andvar Exp $ */ 2 1.1 pk 3 1.1 pk /*- 4 1.9 pk * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 1.9 pk * All rights reserved. 6 1.9 pk * 7 1.9 pk * This code is derived from software contributed to The NetBSD Foundation 8 1.17 mycroft * by Paul Kranenburg and Charles M. Hannum. 9 1.9 pk * 10 1.9 pk * Redistribution and use in source and binary forms, with or without 11 1.9 pk * modification, are permitted provided that the following conditions 12 1.9 pk * are met: 13 1.9 pk * 1. Redistributions of source code must retain the above copyright 14 1.9 pk * notice, this list of conditions and the following disclaimer. 15 1.9 pk * 2. Redistributions in binary form must reproduce the above copyright 16 1.9 pk * notice, this list of conditions and the following disclaimer in the 17 1.9 pk * documentation and/or other materials provided with the distribution. 18 1.9 pk * 19 1.9 pk * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.9 pk * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.9 pk * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.9 pk * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.9 pk * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.9 pk * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.9 pk * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.9 pk * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.9 pk * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.9 pk * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.9 pk * POSSIBILITY OF SUCH DAMAGE. 30 1.9 pk */ 31 1.9 pk 32 1.9 pk /*- 33 1.1 pk * Copyright (c) 1997 Paul Kranenburg. 34 1.1 pk * Copyright (c) 1992, 1993, University of Vermont and State 35 1.1 pk * Agricultural College. 36 1.1 pk * Copyright (c) 1992, 1993, Garrett A. Wollman. 37 1.1 pk * 38 1.1 pk * Portions: 39 1.1 pk * Copyright (c) 1994, 1995, Rafal K. Boni 40 1.1 pk * Copyright (c) 1990, 1991, William F. Jolitz 41 1.1 pk * Copyright (c) 1990, The Regents of the University of California 42 1.1 pk * 43 1.1 pk * All rights reserved. 44 1.1 pk * 45 1.1 pk * Redistribution and use in source and binary forms, with or without 46 1.1 pk * modification, are permitted provided that the following conditions 47 1.1 pk * are met: 48 1.1 pk * 1. Redistributions of source code must retain the above copyright 49 1.1 pk * notice, this list of conditions and the following disclaimer. 50 1.1 pk * 2. Redistributions in binary form must reproduce the above copyright 51 1.1 pk * notice, this list of conditions and the following disclaimer in the 52 1.1 pk * documentation and/or other materials provided with the distribution. 53 1.1 pk * 3. All advertising materials mentioning features or use of this software 54 1.1 pk * must display the following acknowledgement: 55 1.18 mycroft * This product includes software developed by the University of Vermont 56 1.18 mycroft * and State Agricultural College and Garrett A. Wollman, by William F. 57 1.18 mycroft * Jolitz, and by the University of California, Berkeley, Lawrence 58 1.18 mycroft * Berkeley Laboratory, and its contributors. 59 1.1 pk * 4. Neither the names of the Universities nor the names of the authors 60 1.1 pk * may be used to endorse or promote products derived from this software 61 1.1 pk * without specific prior written permission. 62 1.1 pk * 63 1.1 pk * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 64 1.1 pk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 65 1.1 pk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 66 1.1 pk * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR AUTHORS BE LIABLE 67 1.1 pk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 68 1.1 pk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 69 1.1 pk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 70 1.1 pk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 71 1.1 pk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 72 1.1 pk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 73 1.1 pk * SUCH DAMAGE. 74 1.1 pk */ 75 1.1 pk 76 1.1 pk /* 77 1.1 pk * Intel 82586 Ethernet chip 78 1.1 pk * Register, bit, and structure definitions. 79 1.1 pk * 80 1.1 pk * Original StarLAN driver written by Garrett Wollman with reference to the 81 1.1 pk * Clarkson Packet Driver code for this chip written by Russ Nelson and others. 82 1.1 pk * 83 1.1 pk * BPF support code taken from hpdev/if_le.c, supplied with tcpdump. 84 1.1 pk * 85 1.1 pk * 3C507 support is loosely based on code donated to NetBSD by Rafal Boni. 86 1.1 pk * 87 1.1 pk * Majorly cleaned up and 3C507 code merged by Charles Hannum. 88 1.1 pk * 89 1.1 pk * Converted to SUN ie driver by Charles D. Cranor, 90 1.1 pk * October 1994, January 1995. 91 1.1 pk * This sun version based on i386 version 1.30. 92 1.1 pk */ 93 1.1 pk 94 1.1 pk /* 95 1.1 pk * The i82586 is a very painful chip, found in sun3's, sun-4/100's 96 1.1 pk * sun-4/200's, and VME based suns. The byte order is all wrong for a 97 1.1 pk * SUN, making life difficult. Programming this chip is mostly the same, 98 1.1 pk * but certain details differ from system to system. This driver is 99 1.90 andvar * written so that different "ie" interfaces can be controlled by the same 100 1.1 pk * driver. 101 1.1 pk */ 102 1.1 pk 103 1.1 pk /* 104 1.1 pk Mode of operation: 105 1.1 pk 106 1.1 pk We run the 82586 in a standard Ethernet mode. We keep NFRAMES 107 1.1 pk received frame descriptors around for the receiver to use, and 108 1.1 pk NRXBUF associated receive buffer descriptors, both in a circular 109 1.1 pk list. Whenever a frame is received, we rotate both lists as 110 1.1 pk necessary. (The 586 treats both lists as a simple queue.) We also 111 1.1 pk keep a transmit command around so that packets can be sent off 112 1.1 pk quickly. 113 1.1 pk 114 1.1 pk We configure the adapter in AL-LOC = 1 mode, which means that the 115 1.1 pk Ethernet/802.3 MAC header is placed at the beginning of the receive 116 1.1 pk buffer rather than being split off into various fields in the RFD. 117 1.1 pk This also means that we must include this header in the transmit 118 1.1 pk buffer as well. 119 1.1 pk 120 1.1 pk By convention, all transmit commands, and only transmit commands, 121 1.1 pk shall have the I (IE_CMD_INTR) bit set in the command. This way, 122 1.9 pk when an interrupt arrives at i82586_intr(), it is immediately possible 123 1.1 pk to tell what precisely caused it. ANY OTHER command-sending 124 1.1 pk routines should run at splnet(), and should post an acknowledgement 125 1.1 pk to every interrupt they generate. 126 1.1 pk 127 1.6 pk To save the expense of shipping a command to 82586 every time we 128 1.6 pk want to send a frame, we use a linked list of commands consisting 129 1.6 pk of alternate XMIT and NOP commands. The links of these elements 130 1.6 pk are manipulated (in iexmit()) such that the NOP command loops back 131 1.6 pk to itself whenever the following XMIT command is not yet ready to 132 1.6 pk go. Whenever an XMIT is ready, the preceding NOP link is pointed 133 1.6 pk at it, while its own link field points to the following NOP command. 134 1.6 pk Thus, a single transmit command sets off an interlocked traversal 135 1.6 pk of the xmit command chain, with the host processor in control of 136 1.6 pk the synchronization. 137 1.1 pk */ 138 1.1 pk 139 1.41 lukem #include <sys/cdefs.h> 140 1.91 andvar __KERNEL_RCSID(0, "$NetBSD: i82586.c,v 1.91 2024/02/09 22:08:34 andvar Exp $"); 141 1.41 lukem 142 1.40 lukem 143 1.1 pk #include <sys/param.h> 144 1.1 pk #include <sys/systm.h> 145 1.1 pk #include <sys/mbuf.h> 146 1.1 pk #include <sys/socket.h> 147 1.1 pk #include <sys/ioctl.h> 148 1.1 pk #include <sys/errno.h> 149 1.1 pk #include <sys/syslog.h> 150 1.1 pk #include <sys/device.h> 151 1.81 msaitoh #include <sys/bus.h> 152 1.1 pk 153 1.1 pk #include <net/if.h> 154 1.7 pk #include <net/if_dl.h> 155 1.1 pk #include <net/if_types.h> 156 1.7 pk #include <net/if_media.h> 157 1.1 pk #include <net/if_ether.h> 158 1.1 pk #include <net/bpf.h> 159 1.1 pk 160 1.1 pk #include <dev/ic/i82586reg.h> 161 1.1 pk #include <dev/ic/i82586var.h> 162 1.1 pk 163 1.81 msaitoh void i82586_reset(struct ie_softc *, int); 164 1.81 msaitoh void i82586_watchdog(struct ifnet *); 165 1.81 msaitoh int i82586_init(struct ifnet *); 166 1.81 msaitoh int i82586_ioctl(struct ifnet *, u_long, void *); 167 1.81 msaitoh void i82586_start(struct ifnet *); 168 1.81 msaitoh void i82586_stop(struct ifnet *, int); 169 1.50 perry 170 1.50 perry 171 1.81 msaitoh int i82586_rint(struct ie_softc *, int); 172 1.81 msaitoh int i82586_tint(struct ie_softc *, int); 173 1.50 perry 174 1.81 msaitoh int i82586_mediachange(struct ifnet *); 175 1.81 msaitoh void i82586_mediastatus(struct ifnet *, struct ifmediareq *); 176 1.50 perry 177 1.81 msaitoh static int ie_readframe(struct ie_softc *, int); 178 1.50 perry static struct mbuf *ieget(struct ie_softc *, int, int); 179 1.50 perry static int i82586_get_rbd_list(struct ie_softc *, 180 1.81 msaitoh uint16_t *, uint16_t *, int *); 181 1.50 perry static void i82586_release_rbd_list(struct ie_softc *, 182 1.81 msaitoh uint16_t, uint16_t); 183 1.50 perry static int i82586_drop_frames(struct ie_softc *); 184 1.50 perry static int i82586_chk_rx_ring(struct ie_softc *); 185 1.50 perry 186 1.81 msaitoh static inline void ie_ack(struct ie_softc *, u_int); 187 1.81 msaitoh static inline void iexmit(struct ie_softc *); 188 1.81 msaitoh static void i82586_start_transceiver(struct ie_softc *); 189 1.50 perry 190 1.50 perry static void i82586_count_errors(struct ie_softc *); 191 1.50 perry static void i82586_rx_errors(struct ie_softc *, int, int); 192 1.81 msaitoh static void i82586_setup_bufs(struct ie_softc *); 193 1.50 perry static void setup_simple_command(struct ie_softc *, int, int); 194 1.81 msaitoh static int ie_cfg_setup(struct ie_softc *, int, int, int); 195 1.50 perry static int ie_ia_setup(struct ie_softc *, int); 196 1.81 msaitoh static void ie_run_tdr(struct ie_softc *, int); 197 1.81 msaitoh static int ie_mc_setup(struct ie_softc *, int); 198 1.81 msaitoh static void ie_mc_reset(struct ie_softc *); 199 1.81 msaitoh static int i82586_start_cmd(struct ie_softc *, int, int, int, int); 200 1.50 perry static int i82586_cmd_wait(struct ie_softc *); 201 1.7 pk 202 1.25 pk #if I82586_DEBUG 203 1.83 msaitoh void print_rbd(struct ie_softc *, int); 204 1.7 pk #endif 205 1.1 pk 206 1.45 bouyer static char* padbuf = NULL; 207 1.1 pk 208 1.1 pk /* 209 1.9 pk * Front-ends call this function to attach to the MI driver. 210 1.9 pk * 211 1.9 pk * The front-end has responsibility for managing the ICP and ISCP 212 1.9 pk * structures. Both of these are opaque to us. Also, the front-end 213 1.9 pk * chooses a location for the SCB which is expected to be addressable 214 1.9 pk * (through `sc->scb') as an offset against the shared-memory bus handle. 215 1.9 pk * 216 1.9 pk * The following MD interface function must be setup by the front-end 217 1.9 pk * before calling here: 218 1.9 pk * 219 1.9 pk * hwreset - board dependent reset 220 1.9 pk * hwinit - board dependent initialization 221 1.9 pk * chan_attn - channel attention 222 1.9 pk * intrhook - board dependent interrupt processing 223 1.9 pk * memcopyin - shared memory copy: board to KVA 224 1.9 pk * memcopyout - shared memory copy: KVA to board 225 1.11 kleink * ie_bus_read16 - read a sixteen-bit i82586 pointer 226 1.9 pk * ie_bus_write16 - write a sixteen-bit i82586 pointer 227 1.11 kleink * ie_bus_write24 - write a twenty-four-bit i82586 pointer 228 1.9 pk * 229 1.1 pk */ 230 1.1 pk void 231 1.81 msaitoh i82586_attach(struct ie_softc *sc, const char *name, uint8_t *etheraddr, 232 1.73 msaitoh int *media, int nmedia, int defmedia) 233 1.1 pk { 234 1.7 pk int i; 235 1.1 pk struct ifnet *ifp = &sc->sc_ethercom.ec_if; 236 1.1 pk 237 1.69 tsutsui strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 238 1.1 pk ifp->if_softc = sc; 239 1.7 pk ifp->if_start = i82586_start; 240 1.7 pk ifp->if_ioctl = i82586_ioctl; 241 1.29 bjh21 ifp->if_init = i82586_init; 242 1.29 bjh21 ifp->if_stop = i82586_stop; 243 1.7 pk ifp->if_watchdog = i82586_watchdog; 244 1.80 msaitoh ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 245 1.33 thorpej IFQ_SET_READY(&ifp->if_snd); 246 1.1 pk 247 1.81 msaitoh /* Initialize media goo. */ 248 1.85 msaitoh sc->sc_ethercom.ec_ifmedia = &sc->sc_media; 249 1.81 msaitoh ifmedia_init(&sc->sc_media, 0, i82586_mediachange, i82586_mediastatus); 250 1.81 msaitoh if (media != NULL) { 251 1.81 msaitoh for (i = 0; i < nmedia; i++) 252 1.81 msaitoh ifmedia_add(&sc->sc_media, media[i], 0, NULL); 253 1.81 msaitoh ifmedia_set(&sc->sc_media, defmedia); 254 1.81 msaitoh } else { 255 1.81 msaitoh ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_MANUAL, 0, NULL); 256 1.81 msaitoh ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_MANUAL); 257 1.81 msaitoh } 258 1.7 pk 259 1.45 bouyer if (padbuf == NULL) { 260 1.45 bouyer padbuf = malloc(ETHER_MIN_LEN - ETHER_CRC_LEN, M_DEVBUF, 261 1.87 chs M_ZERO | M_WAITOK); 262 1.45 bouyer } 263 1.45 bouyer 264 1.1 pk /* Attach the interface. */ 265 1.1 pk if_attach(ifp); 266 1.76 ozaki if_deferred_start_init(ifp, NULL); 267 1.1 pk ether_ifattach(ifp, etheraddr); 268 1.1 pk 269 1.74 msaitoh aprint_normal(" address %s, type %s\n", ether_sprintf(etheraddr),name); 270 1.1 pk } 271 1.1 pk 272 1.1 pk 273 1.1 pk /* 274 1.9 pk * Device timeout/watchdog routine. 275 1.9 pk * Entered if the device neglects to generate an interrupt after a 276 1.9 pk * transmit has been started on it. 277 1.1 pk */ 278 1.1 pk void 279 1.65 dsl i82586_watchdog(struct ifnet *ifp) 280 1.1 pk { 281 1.1 pk struct ie_softc *sc = ifp->if_softc; 282 1.1 pk 283 1.69 tsutsui log(LOG_ERR, "%s: device timeout\n", device_xname(sc->sc_dev)); 284 1.88 thorpej if_statinc(ifp, if_oerrors); 285 1.1 pk 286 1.7 pk i82586_reset(sc, 1); 287 1.1 pk } 288 1.1 pk 289 1.9 pk static int 290 1.65 dsl i82586_cmd_wait(struct ie_softc *sc) 291 1.9 pk { 292 1.9 pk /* spin on i82586 command acknowledge; wait at most 0.9 (!) seconds */ 293 1.9 pk int i, off; 294 1.81 msaitoh uint16_t cmd; 295 1.9 pk 296 1.9 pk for (i = 0; i < 900000; i++) { 297 1.9 pk /* Read the command word */ 298 1.9 pk off = IE_SCB_CMD(sc->scb); 299 1.34 bjh21 300 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); 301 1.34 bjh21 if ((cmd = sc->ie_bus_read16(sc, off)) == 0) 302 1.9 pk return (0); 303 1.9 pk delay(1); 304 1.9 pk } 305 1.9 pk 306 1.34 bjh21 off = IE_SCB_STATUS(sc->scb); 307 1.34 bjh21 printf("i82586_cmd_wait: timo(%ssync): scb status: 0x%x, cmd: 0x%x\n", 308 1.51 perry sc->async_cmd_inprogress?"a":"", 309 1.34 bjh21 sc->ie_bus_read16(sc, off), cmd); 310 1.34 bjh21 311 1.9 pk return (1); /* Timeout */ 312 1.9 pk } 313 1.9 pk 314 1.1 pk /* 315 1.9 pk * Send a command to the controller and wait for it to either complete 316 1.9 pk * or be accepted, depending on the command. If the command pointer 317 1.9 pk * is null, then pretend that the command is not an action command. 318 1.9 pk * If the command pointer is not null, and the command is an action 319 1.9 pk * command, wait for one of the MASK bits to turn on in the command's 320 1.9 pk * status field. 321 1.9 pk * If ASYNC is set, we just call the chip's attention and return. 322 1.9 pk * We may have to wait for the command's acceptance later though. 323 1.1 pk */ 324 1.9 pk static int 325 1.73 msaitoh i82586_start_cmd(struct ie_softc *sc, int cmd, int iecmdbuf, int mask, 326 1.73 msaitoh int async) 327 1.9 pk { 328 1.9 pk int i; 329 1.9 pk int off; 330 1.9 pk 331 1.10 pk if (sc->async_cmd_inprogress != 0) { 332 1.9 pk /* 333 1.9 pk * If previous command was issued asynchronously, wait 334 1.9 pk * for it now. 335 1.9 pk */ 336 1.9 pk if (i82586_cmd_wait(sc) != 0) 337 1.9 pk return (1); 338 1.10 pk sc->async_cmd_inprogress = 0; 339 1.9 pk } 340 1.9 pk 341 1.9 pk off = IE_SCB_CMD(sc->scb); 342 1.34 bjh21 sc->ie_bus_write16(sc, off, cmd); 343 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE); 344 1.36 jdolecek (sc->chan_attn)(sc, CARD_RESET); 345 1.9 pk 346 1.9 pk if (async != 0) { 347 1.10 pk sc->async_cmd_inprogress = 1; 348 1.9 pk return (0); 349 1.9 pk } 350 1.9 pk 351 1.9 pk if (IE_ACTION_COMMAND(cmd) && iecmdbuf) { 352 1.9 pk int status; 353 1.9 pk /* 354 1.9 pk * Now spin-lock waiting for status. This is not a very nice 355 1.9 pk * thing to do, and can kill performance pretty well... 356 1.9 pk * According to the packet driver, the minimum timeout 357 1.9 pk * should be .369 seconds. 358 1.9 pk */ 359 1.9 pk for (i = 0; i < 369000; i++) { 360 1.9 pk /* Read the command status */ 361 1.9 pk off = IE_CMD_COMMON_STATUS(iecmdbuf); 362 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); 363 1.34 bjh21 status = sc->ie_bus_read16(sc, off); 364 1.9 pk if (status & mask) 365 1.9 pk return (0); 366 1.9 pk delay(1); 367 1.9 pk } 368 1.9 pk 369 1.9 pk } else { 370 1.9 pk /* 371 1.9 pk * Otherwise, just wait for the command to be accepted. 372 1.9 pk */ 373 1.9 pk return (i82586_cmd_wait(sc)); 374 1.9 pk } 375 1.9 pk 376 1.9 pk /* Timeout */ 377 1.9 pk return (1); 378 1.9 pk } 379 1.9 pk 380 1.9 pk /* 381 1.9 pk * Interrupt Acknowledge. 382 1.9 pk */ 383 1.55 perry static inline void 384 1.66 dsl ie_ack(struct ie_softc *sc, u_int mask) 385 1.66 dsl /* mask: in native byte-order */ 386 1.1 pk { 387 1.10 pk u_int status; 388 1.1 pk 389 1.34 bjh21 IE_BUS_BARRIER(sc, 0, 0, BUS_SPACE_BARRIER_READ); 390 1.34 bjh21 status = sc->ie_bus_read16(sc, IE_SCB_STATUS(sc->scb)); 391 1.10 pk i82586_start_cmd(sc, status & mask, 0, 0, 0); 392 1.27 bjh21 if (sc->intrhook) 393 1.27 bjh21 sc->intrhook(sc, INTR_ACK); 394 1.1 pk } 395 1.1 pk 396 1.9 pk /* 397 1.9 pk * Transfer accumulated chip error counters to IF. 398 1.9 pk */ 399 1.54 perry static inline void 400 1.65 dsl i82586_count_errors(struct ie_softc *sc) 401 1.9 pk { 402 1.9 pk int scb = sc->scb; 403 1.9 pk 404 1.88 thorpej if_statadd(&sc->sc_ethercom.ec_if, if_ierrors, 405 1.9 pk sc->ie_bus_read16(sc, IE_SCB_ERRCRC(scb)) + 406 1.9 pk sc->ie_bus_read16(sc, IE_SCB_ERRALN(scb)) + 407 1.9 pk sc->ie_bus_read16(sc, IE_SCB_ERRRES(scb)) + 408 1.88 thorpej sc->ie_bus_read16(sc, IE_SCB_ERROVR(scb))); 409 1.3 pk 410 1.9 pk /* Clear error counters */ 411 1.9 pk sc->ie_bus_write16(sc, IE_SCB_ERRCRC(scb), 0); 412 1.9 pk sc->ie_bus_write16(sc, IE_SCB_ERRALN(scb), 0); 413 1.9 pk sc->ie_bus_write16(sc, IE_SCB_ERRRES(scb), 0); 414 1.9 pk sc->ie_bus_write16(sc, IE_SCB_ERROVR(scb), 0); 415 1.9 pk } 416 1.9 pk 417 1.9 pk static void 418 1.65 dsl i82586_rx_errors(struct ie_softc *sc, int fn, int status) 419 1.9 pk { 420 1.9 pk char bits[128]; 421 1.64 christos snprintb(bits, sizeof(bits), IE_FD_STATUSBITS, status); 422 1.64 christos log(LOG_ERR, "%s: rx error (frame# %d): %s\n", 423 1.69 tsutsui device_xname(sc->sc_dev), fn, bits); 424 1.9 pk } 425 1.9 pk 426 1.9 pk /* 427 1.9 pk * i82586 interrupt entry point. 428 1.9 pk */ 429 1.9 pk int 430 1.65 dsl i82586_intr(void *v) 431 1.1 pk { 432 1.9 pk struct ie_softc *sc = v; 433 1.9 pk u_int status; 434 1.9 pk int off; 435 1.9 pk 436 1.81 msaitoh /* 437 1.81 msaitoh * Implementation dependent interrupt handling. 438 1.81 msaitoh */ 439 1.9 pk if (sc->intrhook) 440 1.9 pk (sc->intrhook)(sc, INTR_ENTER); 441 1.9 pk 442 1.9 pk off = IE_SCB_STATUS(sc->scb); 443 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); 444 1.9 pk status = sc->ie_bus_read16(sc, off) & IE_ST_WHENCE; 445 1.9 pk 446 1.9 pk if ((status & IE_ST_WHENCE) == 0) { 447 1.9 pk if (sc->intrhook) 448 1.9 pk (sc->intrhook)(sc, INTR_EXIT); 449 1.9 pk 450 1.9 pk return (0); 451 1.9 pk } 452 1.9 pk 453 1.9 pk loop: 454 1.9 pk /* Ack interrupts FIRST in case we receive more during the ISR. */ 455 1.9 pk #if 0 456 1.9 pk ie_ack(sc, status & IE_ST_WHENCE); 457 1.9 pk #endif 458 1.9 pk i82586_start_cmd(sc, status & IE_ST_WHENCE, 0, 0, 1); 459 1.9 pk 460 1.9 pk if (status & (IE_ST_FR | IE_ST_RNR)) 461 1.9 pk if (i82586_rint(sc, status) != 0) 462 1.9 pk goto reset; 463 1.9 pk 464 1.9 pk if (status & IE_ST_CX) 465 1.9 pk if (i82586_tint(sc, status) != 0) 466 1.9 pk goto reset; 467 1.9 pk 468 1.25 pk #if I82586_DEBUG 469 1.9 pk if ((status & IE_ST_CNA) && (sc->sc_debug & IED_CNA)) 470 1.73 msaitoh printf("%s: cna; status=0x%x\n", device_xname(sc->sc_dev), 471 1.73 msaitoh status); 472 1.9 pk #endif 473 1.9 pk if (sc->intrhook) 474 1.9 pk (sc->intrhook)(sc, INTR_LOOP); 475 1.9 pk 476 1.9 pk /* 477 1.9 pk * Interrupt ACK was posted asynchronously; wait for 478 1.9 pk * completion here before reading SCB status again. 479 1.51 perry * 480 1.34 bjh21 * If ACK fails, try to reset the chip, in hopes that 481 1.34 bjh21 * it helps. 482 1.9 pk */ 483 1.34 bjh21 if (i82586_cmd_wait(sc) != 0) 484 1.34 bjh21 goto reset; 485 1.9 pk 486 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); 487 1.9 pk status = sc->ie_bus_read16(sc, off); 488 1.9 pk if ((status & IE_ST_WHENCE) != 0) 489 1.9 pk goto loop; 490 1.9 pk 491 1.10 pk out: 492 1.9 pk if (sc->intrhook) 493 1.9 pk (sc->intrhook)(sc, INTR_EXIT); 494 1.9 pk return (1); 495 1.9 pk 496 1.9 pk reset: 497 1.9 pk i82586_cmd_wait(sc); 498 1.9 pk i82586_reset(sc, 1); 499 1.10 pk goto out; 500 1.10 pk 501 1.9 pk } 502 1.9 pk 503 1.9 pk /* 504 1.9 pk * Process a received-frame interrupt. 505 1.9 pk */ 506 1.9 pk int 507 1.65 dsl i82586_rint(struct ie_softc *sc, int scbstatus) 508 1.9 pk { 509 1.9 pk static int timesthru = 1024; 510 1.9 pk int i, status, off; 511 1.9 pk 512 1.25 pk #if I82586_DEBUG 513 1.9 pk if (sc->sc_debug & IED_RINT) 514 1.9 pk printf("%s: rint: status 0x%x\n", 515 1.69 tsutsui device_xname(sc->sc_dev), scbstatus); 516 1.9 pk #endif 517 1.9 pk 518 1.9 pk for (;;) { 519 1.9 pk int drop = 0; 520 1.9 pk 521 1.9 pk i = sc->rfhead; 522 1.9 pk off = IE_RFRAME_STATUS(sc->rframes, i); 523 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); 524 1.9 pk status = sc->ie_bus_read16(sc, off); 525 1.1 pk 526 1.25 pk #if I82586_DEBUG 527 1.9 pk if (sc->sc_debug & IED_RINT) 528 1.9 pk printf("%s: rint: frame(%d) status 0x%x\n", 529 1.69 tsutsui device_xname(sc->sc_dev), i, status); 530 1.1 pk #endif 531 1.9 pk if ((status & IE_FD_COMPLETE) == 0) { 532 1.9 pk if ((status & IE_FD_OK) != 0) { 533 1.10 pk printf("%s: rint: weird: ", 534 1.69 tsutsui device_xname(sc->sc_dev)); 535 1.9 pk i82586_rx_errors(sc, i, status); 536 1.9 pk break; 537 1.9 pk } 538 1.9 pk if (--timesthru == 0) { 539 1.9 pk /* Account the accumulated errors */ 540 1.9 pk i82586_count_errors(sc); 541 1.9 pk timesthru = 1024; 542 1.9 pk } 543 1.9 pk break; 544 1.9 pk } else if ((status & IE_FD_OK) == 0) { 545 1.9 pk /* 546 1.9 pk * If the chip is configured to automatically 547 1.9 pk * discard bad frames, the only reason we can 548 1.9 pk * get here is an "out-of-resource" condition. 549 1.9 pk */ 550 1.9 pk i82586_rx_errors(sc, i, status); 551 1.9 pk drop = 1; 552 1.1 pk } 553 1.1 pk 554 1.25 pk #if I82586_DEBUG 555 1.9 pk if ((status & IE_FD_BUSY) != 0) 556 1.9 pk printf("%s: rint: frame(%d) busy; status=0x%x\n", 557 1.69 tsutsui device_xname(sc->sc_dev), i, status); 558 1.9 pk #endif 559 1.9 pk 560 1.9 pk 561 1.9 pk /* 562 1.9 pk * Advance the RFD list, since we're done with 563 1.9 pk * this descriptor. 564 1.9 pk */ 565 1.9 pk 566 1.9 pk /* Clear frame status */ 567 1.9 pk sc->ie_bus_write16(sc, off, 0); 568 1.1 pk 569 1.9 pk /* Put fence at this frame (the head) */ 570 1.9 pk off = IE_RFRAME_LAST(sc->rframes, i); 571 1.81 msaitoh sc->ie_bus_write16(sc, off, IE_FD_EOL | IE_FD_SUSP); 572 1.9 pk 573 1.9 pk /* and clear RBD field */ 574 1.9 pk off = IE_RFRAME_BUFDESC(sc->rframes, i); 575 1.9 pk sc->ie_bus_write16(sc, off, 0xffff); 576 1.9 pk 577 1.9 pk /* Remove fence from current tail */ 578 1.9 pk off = IE_RFRAME_LAST(sc->rframes, sc->rftail); 579 1.9 pk sc->ie_bus_write16(sc, off, 0); 580 1.9 pk 581 1.9 pk if (++sc->rftail == sc->nframes) 582 1.9 pk sc->rftail = 0; 583 1.9 pk if (++sc->rfhead == sc->nframes) 584 1.9 pk sc->rfhead = 0; 585 1.9 pk 586 1.9 pk /* Pull the frame off the board */ 587 1.9 pk if (drop) { 588 1.9 pk i82586_drop_frames(sc); 589 1.10 pk if ((status & IE_FD_RNR) != 0) 590 1.9 pk sc->rnr_expect = 1; 591 1.88 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_ierrors); 592 1.9 pk } else if (ie_readframe(sc, i) != 0) 593 1.9 pk return (1); 594 1.9 pk } 595 1.9 pk 596 1.10 pk if ((scbstatus & IE_ST_RNR) != 0) { 597 1.10 pk 598 1.10 pk /* 599 1.10 pk * Receiver went "Not Ready". We try to figure out 600 1.10 pk * whether this was an expected event based on past 601 1.10 pk * frame status values. 602 1.10 pk */ 603 1.9 pk 604 1.10 pk if ((scbstatus & IE_RUS_SUSPEND) != 0) { 605 1.10 pk /* 606 1.10 pk * We use the "suspend on last frame" flag. 607 1.10 pk * Send a RU RESUME command in response, since 608 1.10 pk * we should have dealt with all completed frames 609 1.10 pk * by now. 610 1.10 pk */ 611 1.10 pk printf("RINT: SUSPENDED; scbstatus=0x%x\n", 612 1.10 pk scbstatus); 613 1.9 pk if (i82586_start_cmd(sc, IE_RUC_RESUME, 0, 0, 0) == 0) 614 1.9 pk return (0); 615 1.73 msaitoh aprint_error_dev(sc->sc_dev, 616 1.73 msaitoh "RU RESUME command timed out\n"); 617 1.10 pk return (1); /* Ask for a reset */ 618 1.1 pk } 619 1.10 pk 620 1.10 pk if (sc->rnr_expect != 0) { 621 1.10 pk /* 622 1.10 pk * The RNR condition was announced in the previously 623 1.10 pk * completed frame. Assume the receive ring is Ok, 624 1.10 pk * so restart the receiver without further delay. 625 1.10 pk */ 626 1.9 pk i82586_start_transceiver(sc); 627 1.9 pk sc->rnr_expect = 0; 628 1.9 pk return (0); 629 1.10 pk 630 1.10 pk } else if ((scbstatus & IE_RUS_NOSPACE) != 0) { 631 1.10 pk /* 632 1.10 pk * We saw no previous IF_FD_RNR flag. 633 1.10 pk * We check our ring invariants and, if ok, 634 1.10 pk * just restart the receiver at the current 635 1.10 pk * point in the ring. 636 1.10 pk */ 637 1.10 pk if (i82586_chk_rx_ring(sc) != 0) 638 1.10 pk return (1); 639 1.10 pk 640 1.10 pk i82586_start_transceiver(sc); 641 1.88 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_ierrors); 642 1.10 pk return (0); 643 1.9 pk } else 644 1.9 pk printf("%s: receiver not ready; scbstatus=0x%x\n", 645 1.69 tsutsui device_xname(sc->sc_dev), scbstatus); 646 1.10 pk 647 1.88 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_ierrors); 648 1.10 pk return (1); /* Ask for a reset */ 649 1.9 pk } 650 1.10 pk 651 1.9 pk return (0); 652 1.1 pk } 653 1.1 pk 654 1.1 pk /* 655 1.9 pk * Process a command-complete interrupt. These are only generated by the 656 1.10 pk * transmission of frames. This routine is deceptively simple, since most 657 1.10 pk * of the real work is done by i82586_start(). 658 1.1 pk */ 659 1.9 pk int 660 1.65 dsl i82586_tint(struct ie_softc *sc, int scbstatus) 661 1.1 pk { 662 1.9 pk struct ifnet *ifp = &sc->sc_ethercom.ec_if; 663 1.9 pk int status; 664 1.6 pk 665 1.9 pk ifp->if_timer = 0; 666 1.1 pk 667 1.25 pk #if I82586_DEBUG 668 1.9 pk if (sc->xmit_busy <= 0) { 669 1.9 pk printf("i82586_tint: WEIRD: xmit_busy=%d, xctail=%d, xchead=%d\n", 670 1.9 pk sc->xmit_busy, sc->xctail, sc->xchead); 671 1.10 pk return (0); 672 1.9 pk } 673 1.1 pk #endif 674 1.1 pk 675 1.9 pk status = sc->ie_bus_read16(sc, IE_CMD_XMIT_STATUS(sc->xmit_cmds, 676 1.9 pk sc->xctail)); 677 1.6 pk 678 1.25 pk #if I82586_DEBUG 679 1.9 pk if (sc->sc_debug & IED_TINT) 680 1.9 pk printf("%s: tint: SCB status 0x%x; xmit status 0x%x\n", 681 1.69 tsutsui device_xname(sc->sc_dev), scbstatus, status); 682 1.9 pk #endif 683 1.6 pk 684 1.9 pk if ((status & IE_STAT_COMPL) == 0 || (status & IE_STAT_BUSY)) { 685 1.9 pk printf("i82586_tint: command still busy; status=0x%x; tail=%d\n", 686 1.9 pk status, sc->xctail); 687 1.9 pk printf("iestatus = 0x%x\n", scbstatus); 688 1.9 pk } 689 1.9 pk 690 1.9 pk if (status & IE_STAT_OK) { 691 1.88 thorpej if_statadd2(ifp, if_opackets, 1, 692 1.88 thorpej if_collisions, status & IE_XS_MAXCOLL); 693 1.9 pk } else { 694 1.88 thorpej if_statinc(ifp, if_oerrors); 695 1.9 pk /* 696 1.9 pk * Check SQE and DEFERRED? 697 1.9 pk * What if more than one bit is set? 698 1.9 pk */ 699 1.9 pk if (status & IE_STAT_ABORT) 700 1.69 tsutsui aprint_error_dev(sc->sc_dev, "send aborted\n"); 701 1.9 pk else if (status & IE_XS_NOCARRIER) 702 1.69 tsutsui aprint_error_dev(sc->sc_dev, "no carrier\n"); 703 1.9 pk else if (status & IE_XS_LOSTCTS) 704 1.69 tsutsui aprint_error_dev(sc->sc_dev, "lost CTS\n"); 705 1.9 pk else if (status & IE_XS_UNDERRUN) 706 1.69 tsutsui aprint_error_dev(sc->sc_dev, "DMA underrun\n"); 707 1.9 pk else if (status & IE_XS_EXCMAX) { 708 1.69 tsutsui aprint_error_dev(sc->sc_dev, "too many collisions\n"); 709 1.88 thorpej if_statadd(&sc->sc_ethercom.ec_if, if_collisions, 16); 710 1.9 pk } 711 1.9 pk } 712 1.9 pk 713 1.9 pk /* 714 1.9 pk * If multicast addresses were added or deleted while transmitting, 715 1.9 pk * ie_mc_reset() set the want_mcsetup flag indicating that we 716 1.9 pk * should do it. 717 1.9 pk */ 718 1.9 pk if (sc->want_mcsetup) { 719 1.9 pk ie_mc_setup(sc, IE_XBUF_ADDR(sc, sc->xctail)); 720 1.9 pk sc->want_mcsetup = 0; 721 1.9 pk } 722 1.9 pk 723 1.9 pk /* Done with the buffer. */ 724 1.9 pk sc->xmit_busy--; 725 1.9 pk sc->xctail = (sc->xctail + 1) % NTXBUF; 726 1.9 pk 727 1.9 pk /* Start the next packet, if any, transmitting. */ 728 1.9 pk if (sc->xmit_busy > 0) 729 1.9 pk iexmit(sc); 730 1.9 pk 731 1.76 ozaki if_schedule_deferred_start(ifp); 732 1.9 pk return (0); 733 1.9 pk } 734 1.9 pk 735 1.9 pk /* 736 1.9 pk * Get a range of receive buffer descriptors that represent one packet. 737 1.9 pk */ 738 1.9 pk static int 739 1.81 msaitoh i82586_get_rbd_list(struct ie_softc *sc, uint16_t *start, uint16_t *end, 740 1.73 msaitoh int *pktlen) 741 1.9 pk { 742 1.9 pk int off, rbbase = sc->rbds; 743 1.9 pk int rbindex, count = 0; 744 1.9 pk int plen = 0; 745 1.9 pk int rbdstatus; 746 1.9 pk 747 1.9 pk *start = rbindex = sc->rbhead; 748 1.9 pk 749 1.9 pk do { 750 1.9 pk off = IE_RBD_STATUS(rbbase, rbindex); 751 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); 752 1.9 pk rbdstatus = sc->ie_bus_read16(sc, off); 753 1.9 pk if ((rbdstatus & IE_RBD_USED) == 0) { 754 1.9 pk /* 755 1.9 pk * This means we are somehow out of sync. So, we 756 1.9 pk * reset the adapter. 757 1.9 pk */ 758 1.25 pk #if I82586_DEBUG 759 1.9 pk print_rbd(sc, rbindex); 760 1.9 pk #endif 761 1.9 pk log(LOG_ERR, 762 1.9 pk "%s: receive descriptors out of sync at %d\n", 763 1.69 tsutsui device_xname(sc->sc_dev), rbindex); 764 1.9 pk return (0); 765 1.9 pk } 766 1.9 pk plen += (rbdstatus & IE_RBD_CNTMASK); 767 1.9 pk 768 1.9 pk if (++rbindex == sc->nrxbuf) 769 1.9 pk rbindex = 0; 770 1.9 pk 771 1.9 pk ++count; 772 1.9 pk } while ((rbdstatus & IE_RBD_LAST) == 0); 773 1.9 pk *end = rbindex; 774 1.9 pk *pktlen = plen; 775 1.9 pk return (count); 776 1.9 pk } 777 1.6 pk 778 1.6 pk 779 1.9 pk /* 780 1.9 pk * Release a range of receive buffer descriptors after we've copied the packet. 781 1.9 pk */ 782 1.9 pk static void 783 1.81 msaitoh i82586_release_rbd_list(struct ie_softc *sc, uint16_t start, uint16_t end) 784 1.9 pk { 785 1.9 pk int off, rbbase = sc->rbds; 786 1.9 pk int rbindex = start; 787 1.6 pk 788 1.9 pk do { 789 1.9 pk /* Clear buffer status */ 790 1.9 pk off = IE_RBD_STATUS(rbbase, rbindex); 791 1.9 pk sc->ie_bus_write16(sc, off, 0); 792 1.9 pk if (++rbindex == sc->nrxbuf) 793 1.9 pk rbindex = 0; 794 1.9 pk } while (rbindex != end); 795 1.9 pk 796 1.9 pk /* Mark EOL at new tail */ 797 1.9 pk rbindex = ((rbindex == 0) ? sc->nrxbuf : rbindex) - 1; 798 1.9 pk off = IE_RBD_BUFLEN(rbbase, rbindex); 799 1.81 msaitoh sc->ie_bus_write16(sc, off, IE_RBUF_SIZE | IE_RBD_EOL); 800 1.9 pk 801 1.9 pk /* Remove EOL from current tail */ 802 1.9 pk off = IE_RBD_BUFLEN(rbbase, sc->rbtail); 803 1.9 pk sc->ie_bus_write16(sc, off, IE_RBUF_SIZE); 804 1.9 pk 805 1.9 pk /* New head & tail pointer */ 806 1.9 pk /* hmm, why have both? head is always (tail + 1) % NRXBUF */ 807 1.9 pk sc->rbhead = end; 808 1.9 pk sc->rbtail = rbindex; 809 1.9 pk } 810 1.6 pk 811 1.10 pk /* 812 1.10 pk * Drop the packet at the head of the RX buffer ring. 813 1.10 pk * Called if the frame descriptor reports an error on this packet. 814 1.10 pk * Returns 1 if the buffer descriptor ring appears to be corrupt; 815 1.10 pk * and 0 otherwise. 816 1.10 pk */ 817 1.9 pk static int 818 1.65 dsl i82586_drop_frames(struct ie_softc *sc) 819 1.9 pk { 820 1.81 msaitoh uint16_t bstart, bend; 821 1.9 pk int pktlen; 822 1.1 pk 823 1.9 pk if (i82586_get_rbd_list(sc, &bstart, &bend, &pktlen) == 0) 824 1.9 pk return (1); 825 1.9 pk i82586_release_rbd_list(sc, bstart, bend); 826 1.9 pk return (0); 827 1.1 pk } 828 1.1 pk 829 1.1 pk /* 830 1.10 pk * Check the RX frame & buffer descriptor lists for our invariants, 831 1.10 pk * i.e.: EOL bit set iff. it is pointed at by the r*tail pointer. 832 1.10 pk * 833 1.10 pk * Called when the receive unit has stopped unexpectedly. 834 1.10 pk * Returns 1 if an inconsistency is detected; 0 otherwise. 835 1.10 pk * 836 1.10 pk * The Receive Unit is expected to be NOT RUNNING. 837 1.10 pk */ 838 1.10 pk static int 839 1.65 dsl i82586_chk_rx_ring(struct ie_softc *sc) 840 1.10 pk { 841 1.10 pk int n, off, val; 842 1.10 pk 843 1.10 pk for (n = 0; n < sc->nrxbuf; n++) { 844 1.10 pk off = IE_RBD_BUFLEN(sc->rbds, n); 845 1.10 pk val = sc->ie_bus_read16(sc, off); 846 1.10 pk if ((n == sc->rbtail) ^ ((val & IE_RBD_EOL) != 0)) { 847 1.10 pk /* `rbtail' and EOL flag out of sync */ 848 1.10 pk log(LOG_ERR, 849 1.10 pk "%s: rx buffer descriptors out of sync at %d\n", 850 1.69 tsutsui device_xname(sc->sc_dev), n); 851 1.10 pk return (1); 852 1.10 pk } 853 1.10 pk 854 1.10 pk /* Take the opportunity to clear the status fields here ? */ 855 1.10 pk } 856 1.10 pk 857 1.10 pk for (n = 0; n < sc->nframes; n++) { 858 1.10 pk off = IE_RFRAME_LAST(sc->rframes, n); 859 1.10 pk val = sc->ie_bus_read16(sc, off); 860 1.81 msaitoh if ((n == sc->rftail) ^ ((val & (IE_FD_EOL | IE_FD_SUSP)) 861 1.81 msaitoh != 0)) { 862 1.10 pk /* `rftail' and EOL flag out of sync */ 863 1.10 pk log(LOG_ERR, 864 1.10 pk "%s: rx frame list out of sync at %d\n", 865 1.69 tsutsui device_xname(sc->sc_dev), n); 866 1.10 pk return (1); 867 1.10 pk } 868 1.10 pk } 869 1.10 pk 870 1.10 pk return (0); 871 1.10 pk } 872 1.10 pk 873 1.10 pk /* 874 1.1 pk * Read data off the interface, and turn it into an mbuf chain. 875 1.1 pk * 876 1.1 pk * This code is DRAMATICALLY different from the previous version; this 877 1.1 pk * version tries to allocate the entire mbuf chain up front, given the 878 1.1 pk * length of the data available. This enables us to allocate mbuf 879 1.1 pk * clusters in many situations where before we would have had a long 880 1.1 pk * chain of partially-full mbufs. This should help to speed up the 881 1.1 pk * operation considerably. (Provided that it works, of course.) 882 1.1 pk */ 883 1.54 perry static inline struct mbuf * 884 1.65 dsl ieget(struct ie_softc *sc, int head, int totlen) 885 1.1 pk { 886 1.19 mycroft struct mbuf *m, *m0, *newm; 887 1.9 pk int len, resid; 888 1.3 pk int thisrboff, thismboff; 889 1.21 thorpej struct ether_header eh; 890 1.1 pk 891 1.1 pk /* 892 1.1 pk * Snarf the Ethernet header. 893 1.1 pk */ 894 1.21 thorpej (sc->memcopyin)(sc, &eh, IE_RBUF_ADDR(sc, head), 895 1.21 thorpej sizeof(struct ether_header)); 896 1.1 pk 897 1.21 thorpej resid = totlen; 898 1.1 pk 899 1.19 mycroft MGETHDR(m0, M_DONTWAIT, MT_DATA); 900 1.19 mycroft if (m0 == 0) 901 1.10 pk return (0); 902 1.72 ozaki m_set_rcvif(m0, &sc->sc_ethercom.ec_if); 903 1.19 mycroft m0->m_pkthdr.len = totlen; 904 1.3 pk len = MHLEN; 905 1.19 mycroft m = m0; 906 1.1 pk 907 1.1 pk /* 908 1.1 pk * This loop goes through and allocates mbufs for all the data we will 909 1.1 pk * be copying in. It does not actually do the copying yet. 910 1.1 pk */ 911 1.3 pk while (totlen > 0) { 912 1.3 pk if (totlen >= MINCLSIZE) { 913 1.1 pk MCLGET(m, M_DONTWAIT); 914 1.19 mycroft if ((m->m_flags & M_EXT) == 0) 915 1.19 mycroft goto bad; 916 1.3 pk len = MCLBYTES; 917 1.22 pk } 918 1.22 pk 919 1.22 pk if (m == m0) { 920 1.58 christos char *newdata = (char *) 921 1.22 pk ALIGN(m->m_data + sizeof(struct ether_header)) - 922 1.22 pk sizeof(struct ether_header); 923 1.22 pk len -= newdata - m->m_data; 924 1.22 pk m->m_data = newdata; 925 1.1 pk } 926 1.19 mycroft 927 1.79 riastrad m->m_len = len = uimin(totlen, len); 928 1.19 mycroft 929 1.3 pk totlen -= len; 930 1.19 mycroft if (totlen > 0) { 931 1.19 mycroft MGET(newm, M_DONTWAIT, MT_DATA); 932 1.19 mycroft if (newm == 0) 933 1.19 mycroft goto bad; 934 1.19 mycroft len = MLEN; 935 1.19 mycroft m = m->m_next = newm; 936 1.19 mycroft } 937 1.3 pk } 938 1.1 pk 939 1.19 mycroft m = m0; 940 1.1 pk thismboff = 0; 941 1.1 pk 942 1.1 pk /* 943 1.21 thorpej * Copy the Ethernet header into the mbuf chain. 944 1.21 thorpej */ 945 1.58 christos memcpy(mtod(m, void *), &eh, sizeof(struct ether_header)); 946 1.21 thorpej thismboff = sizeof(struct ether_header); 947 1.21 thorpej thisrboff = sizeof(struct ether_header); 948 1.21 thorpej resid -= sizeof(struct ether_header); 949 1.21 thorpej 950 1.21 thorpej /* 951 1.1 pk * Now we take the mbuf chain (hopefully only one mbuf most of the 952 1.9 pk * time) and stuff the data into it. There are no possible failures 953 1.9 pk * at or after this point. 954 1.1 pk */ 955 1.3 pk while (resid > 0) { 956 1.9 pk int thisrblen = IE_RBUF_SIZE - thisrboff, 957 1.3 pk thismblen = m->m_len - thismboff; 958 1.79 riastrad len = uimin(thisrblen, thismblen); 959 1.3 pk 960 1.58 christos (sc->memcopyin)(sc, mtod(m, char *) + thismboff, 961 1.82 msaitoh IE_RBUF_ADDR(sc, head) + thisrboff, 962 1.9 pk (u_int)len); 963 1.3 pk resid -= len; 964 1.1 pk 965 1.3 pk if (len == thismblen) { 966 1.1 pk m = m->m_next; 967 1.3 pk thismboff = 0; 968 1.3 pk } else 969 1.3 pk thismboff += len; 970 1.3 pk 971 1.3 pk if (len == thisrblen) { 972 1.9 pk if (++head == sc->nrxbuf) 973 1.9 pk head = 0; 974 1.3 pk thisrboff = 0; 975 1.3 pk } else 976 1.3 pk thisrboff += len; 977 1.1 pk } 978 1.1 pk 979 1.1 pk /* 980 1.9 pk * Unless something changed strangely while we were doing the copy, 981 1.9 pk * we have now copied everything in from the shared memory. 982 1.1 pk * This means that we are done. 983 1.1 pk */ 984 1.19 mycroft return (m0); 985 1.19 mycroft 986 1.19 mycroft bad: 987 1.19 mycroft m_freem(m0); 988 1.19 mycroft return (0); 989 1.1 pk } 990 1.1 pk 991 1.1 pk /* 992 1.1 pk * Read frame NUM from unit UNIT (pre-cached as IE). 993 1.1 pk * 994 1.1 pk * This routine reads the RFD at NUM, and copies in the buffers from the list 995 1.9 pk * of RBD, then rotates the RBD list so that the receiver doesn't start 996 1.9 pk * complaining. Trailers are DROPPED---there's no point in wasting time 997 1.9 pk * on confusing code to deal with them. Hopefully, this machine will 998 1.9 pk * never ARP for trailers anyway. 999 1.1 pk */ 1000 1.9 pk static int 1001 1.56 christos ie_readframe( 1002 1.56 christos struct ie_softc *sc, 1003 1.57 christos int num) /* frame number to read */ 1004 1.1 pk { 1005 1.9 pk struct mbuf *m; 1006 1.81 msaitoh uint16_t bstart, bend; 1007 1.9 pk int pktlen; 1008 1.1 pk 1009 1.9 pk if (i82586_get_rbd_list(sc, &bstart, &bend, &pktlen) == 0) { 1010 1.88 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_ierrors); 1011 1.9 pk return (1); 1012 1.9 pk } 1013 1.1 pk 1014 1.29 bjh21 m = ieget(sc, bstart, pktlen); 1015 1.9 pk i82586_release_rbd_list(sc, bstart, bend); 1016 1.9 pk 1017 1.3 pk if (m == 0) { 1018 1.88 thorpej if_statinc(&sc->sc_ethercom.ec_if, if_ierrors); 1019 1.9 pk return (0); 1020 1.1 pk } 1021 1.1 pk 1022 1.25 pk #if I82586_DEBUG 1023 1.21 thorpej if (sc->sc_debug & IED_READFRAME) { 1024 1.21 thorpej struct ether_header *eh = mtod(m, struct ether_header *); 1025 1.21 thorpej 1026 1.9 pk printf("%s: frame from ether %s type 0x%x len %d\n", 1027 1.69 tsutsui device_xname(sc->sc_dev), 1028 1.21 thorpej ether_sprintf(eh->ether_shost), 1029 1.27 bjh21 (u_int)ntohs(eh->ether_type), 1030 1.9 pk pktlen); 1031 1.21 thorpej } 1032 1.1 pk #endif 1033 1.1 pk 1034 1.1 pk /* 1035 1.1 pk * Finally pass this packet up to higher layers. 1036 1.1 pk */ 1037 1.71 ozaki if_percpuq_enqueue((&sc->sc_ethercom.ec_if)->if_percpuq, m); 1038 1.9 pk return (0); 1039 1.1 pk } 1040 1.1 pk 1041 1.9 pk 1042 1.9 pk /* 1043 1.9 pk * Setup all necessary artifacts for an XMIT command, and then pass the XMIT 1044 1.9 pk * command to the chip to be executed. 1045 1.9 pk */ 1046 1.55 perry static inline void 1047 1.65 dsl iexmit(struct ie_softc *sc) 1048 1.1 pk { 1049 1.9 pk int off; 1050 1.9 pk int cur, prev; 1051 1.9 pk 1052 1.9 pk cur = sc->xctail; 1053 1.1 pk 1054 1.25 pk #if I82586_DEBUG 1055 1.9 pk if (sc->sc_debug & IED_XMIT) 1056 1.69 tsutsui printf("%s: xmit buffer %d\n", device_xname(sc->sc_dev), cur); 1057 1.1 pk #endif 1058 1.9 pk 1059 1.9 pk /* 1060 1.9 pk * Setup the transmit command. 1061 1.9 pk */ 1062 1.9 pk sc->ie_bus_write16(sc, IE_CMD_XMIT_DESC(sc->xmit_cmds, cur), 1063 1.9 pk IE_XBD_ADDR(sc->xbds, cur)); 1064 1.9 pk 1065 1.9 pk sc->ie_bus_write16(sc, IE_CMD_XMIT_STATUS(sc->xmit_cmds, cur), 0); 1066 1.9 pk 1067 1.9 pk if (sc->do_xmitnopchain) { 1068 1.9 pk /* 1069 1.9 pk * Gate this XMIT command to the following NOP 1070 1.9 pk */ 1071 1.9 pk sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds, cur), 1072 1.9 pk IE_CMD_NOP_ADDR(sc->nop_cmds, cur)); 1073 1.9 pk sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur), 1074 1.9 pk IE_CMD_XMIT | IE_CMD_INTR); 1075 1.9 pk 1076 1.9 pk /* 1077 1.9 pk * Loopback at following NOP 1078 1.9 pk */ 1079 1.9 pk sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, cur), 0); 1080 1.9 pk sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, cur), 1081 1.9 pk IE_CMD_NOP_ADDR(sc->nop_cmds, cur)); 1082 1.9 pk 1083 1.9 pk /* 1084 1.9 pk * Gate preceding NOP to this XMIT command 1085 1.9 pk */ 1086 1.9 pk prev = (cur + NTXBUF - 1) % NTXBUF; 1087 1.73 msaitoh sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, prev), 1088 1.73 msaitoh 0); 1089 1.9 pk sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, prev), 1090 1.9 pk IE_CMD_XMIT_ADDR(sc->xmit_cmds, cur)); 1091 1.9 pk 1092 1.9 pk off = IE_SCB_STATUS(sc->scb); 1093 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); 1094 1.9 pk if ((sc->ie_bus_read16(sc, off) & IE_CUS_ACTIVE) == 0) { 1095 1.9 pk printf("iexmit: CU not active\n"); 1096 1.9 pk i82586_start_transceiver(sc); 1097 1.1 pk } 1098 1.9 pk } else { 1099 1.82 msaitoh sc->ie_bus_write16(sc, IE_CMD_XMIT_LINK(sc->xmit_cmds, cur), 1100 1.9 pk 0xffff); 1101 1.9 pk 1102 1.9 pk sc->ie_bus_write16(sc, IE_CMD_XMIT_CMD(sc->xmit_cmds, cur), 1103 1.81 msaitoh IE_CMD_XMIT | IE_CMD_INTR | IE_CMD_LAST); 1104 1.1 pk 1105 1.9 pk off = IE_SCB_CMDLST(sc->scb); 1106 1.73 msaitoh sc->ie_bus_write16(sc, off, IE_CMD_XMIT_ADDR(sc->xmit_cmds, 1107 1.73 msaitoh cur)); 1108 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); 1109 1.1 pk 1110 1.9 pk if (i82586_start_cmd(sc, IE_CUC_START, 0, 0, 1)) 1111 1.73 msaitoh aprint_error_dev(sc->sc_dev, 1112 1.73 msaitoh "iexmit: start xmit command timed out\n"); 1113 1.9 pk } 1114 1.9 pk 1115 1.9 pk sc->sc_ethercom.ec_if.if_timer = 5; 1116 1.1 pk } 1117 1.1 pk 1118 1.1 pk 1119 1.1 pk /* 1120 1.1 pk * Start transmission on an interface. 1121 1.1 pk */ 1122 1.1 pk void 1123 1.65 dsl i82586_start(struct ifnet *ifp) 1124 1.1 pk { 1125 1.1 pk struct ie_softc *sc = ifp->if_softc; 1126 1.1 pk struct mbuf *m0, *m; 1127 1.9 pk int buffer, head, xbase; 1128 1.9 pk u_short len; 1129 1.9 pk int s; 1130 1.1 pk 1131 1.89 thorpej if ((ifp->if_flags & IFF_RUNNING) != IFF_RUNNING) 1132 1.1 pk return; 1133 1.1 pk 1134 1.89 thorpej while (sc->xmit_busy < NTXBUF) { 1135 1.9 pk head = sc->xchead; 1136 1.9 pk xbase = sc->xbds; 1137 1.9 pk 1138 1.33 thorpej IFQ_DEQUEUE(&ifp->if_snd, m0); 1139 1.3 pk if (m0 == 0) 1140 1.1 pk break; 1141 1.1 pk 1142 1.3 pk /* We need to use m->m_pkthdr.len, so require the header */ 1143 1.3 pk if ((m0->m_flags & M_PKTHDR) == 0) 1144 1.7 pk panic("i82586_start: no header mbuf"); 1145 1.3 pk 1146 1.3 pk /* Tap off here if there is a BPF listener. */ 1147 1.78 msaitoh bpf_mtap(ifp, m0, BPF_D_OUT); 1148 1.3 pk 1149 1.25 pk #if I82586_DEBUG 1150 1.3 pk if (sc->sc_debug & IED_ENQ) 1151 1.69 tsutsui printf("%s: fill buffer %d\n", device_xname(sc->sc_dev), 1152 1.3 pk sc->xchead); 1153 1.3 pk #endif 1154 1.3 pk 1155 1.3 pk if (m0->m_pkthdr.len > IE_TBUF_SIZE) 1156 1.69 tsutsui printf("%s: tbuf overflow\n", device_xname(sc->sc_dev)); 1157 1.3 pk 1158 1.9 pk buffer = IE_XBUF_ADDR(sc, head); 1159 1.3 pk for (m = m0; m != 0; m = m->m_next) { 1160 1.58 christos (sc->memcopyout)(sc, mtod(m,void *), buffer, m->m_len); 1161 1.1 pk buffer += m->m_len; 1162 1.1 pk } 1163 1.46 bouyer len = m0->m_pkthdr.len; 1164 1.46 bouyer if (len < ETHER_MIN_LEN - ETHER_CRC_LEN) { 1165 1.45 bouyer (sc->memcopyout)(sc, padbuf, buffer, 1166 1.46 bouyer ETHER_MIN_LEN - ETHER_CRC_LEN - len); 1167 1.46 bouyer buffer += ETHER_MIN_LEN -ETHER_CRC_LEN - len; 1168 1.46 bouyer len = ETHER_MIN_LEN - ETHER_CRC_LEN; 1169 1.45 bouyer } 1170 1.1 pk m_freem(m0); 1171 1.3 pk 1172 1.9 pk /* 1173 1.9 pk * Setup the transmit buffer descriptor here, while we 1174 1.9 pk * know the packet's length. 1175 1.9 pk */ 1176 1.9 pk sc->ie_bus_write16(sc, IE_XBD_FLAGS(xbase, head), 1177 1.9 pk len | IE_TBD_EOL); 1178 1.9 pk sc->ie_bus_write16(sc, IE_XBD_NEXT(xbase, head), 0xffff); 1179 1.9 pk sc->ie_bus_write24(sc, IE_XBD_BUF(xbase, head), 1180 1.9 pk IE_XBUF_ADDR(sc, head)); 1181 1.9 pk 1182 1.9 pk if (++head == NTXBUF) 1183 1.9 pk head = 0; 1184 1.9 pk sc->xchead = head; 1185 1.6 pk 1186 1.6 pk s = splnet(); 1187 1.3 pk /* Start the first packet transmitting. */ 1188 1.3 pk if (sc->xmit_busy == 0) 1189 1.3 pk iexmit(sc); 1190 1.3 pk 1191 1.3 pk sc->xmit_busy++; 1192 1.6 pk splx(s); 1193 1.3 pk } 1194 1.1 pk } 1195 1.1 pk 1196 1.1 pk /* 1197 1.9 pk * Probe IE's ram setup [ Move all this into MD front-end!? ] 1198 1.9 pk * Use only if SCP and ISCP represent offsets into shared ram space. 1199 1.1 pk */ 1200 1.1 pk int 1201 1.65 dsl i82586_proberam(struct ie_softc *sc) 1202 1.1 pk { 1203 1.10 pk int result, off; 1204 1.1 pk 1205 1.9 pk /* Put in 16-bit mode */ 1206 1.10 pk off = IE_SCP_BUS_USE(sc->scp); 1207 1.42 fredette sc->ie_bus_write16(sc, off, IE_SYSBUS_16BIT); 1208 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE); 1209 1.10 pk 1210 1.10 pk /* Set the ISCP `busy' bit */ 1211 1.10 pk off = IE_ISCP_BUSY(sc->iscp); 1212 1.34 bjh21 sc->ie_bus_write16(sc, off, 1); 1213 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_WRITE); 1214 1.1 pk 1215 1.1 pk if (sc->hwreset) 1216 1.7 pk (sc->hwreset)(sc, CHIP_PROBE); 1217 1.1 pk 1218 1.36 jdolecek (sc->chan_attn) (sc, CHIP_PROBE); 1219 1.1 pk 1220 1.1 pk delay(100); /* wait a while... */ 1221 1.1 pk 1222 1.10 pk /* Read back the ISCP `busy' bit; it should be clear by now */ 1223 1.10 pk off = IE_ISCP_BUSY(sc->iscp); 1224 1.34 bjh21 IE_BUS_BARRIER(sc, off, 2, BUS_SPACE_BARRIER_READ); 1225 1.34 bjh21 result = sc->ie_bus_read16(sc, off) == 0; 1226 1.9 pk 1227 1.10 pk /* Acknowledge any interrupts we may have caused. */ 1228 1.1 pk ie_ack(sc, IE_ST_WHENCE); 1229 1.10 pk 1230 1.10 pk return (result); 1231 1.1 pk } 1232 1.1 pk 1233 1.1 pk void 1234 1.65 dsl i82586_reset(struct ie_softc *sc, int hard) 1235 1.1 pk { 1236 1.1 pk int s = splnet(); 1237 1.1 pk 1238 1.10 pk if (hard) 1239 1.69 tsutsui printf("%s: reset\n", device_xname(sc->sc_dev)); 1240 1.1 pk 1241 1.7 pk sc->sc_ethercom.ec_if.if_timer = 0; 1242 1.1 pk 1243 1.1 pk /* 1244 1.1 pk * Stop i82586 dead in its tracks. 1245 1.1 pk */ 1246 1.9 pk if (i82586_start_cmd(sc, IE_RUC_ABORT | IE_CUC_ABORT, 0, 0, 0)) 1247 1.69 tsutsui aprint_error_dev(sc->sc_dev, "abort commands timed out\n"); 1248 1.1 pk 1249 1.9 pk /* 1250 1.7 pk * This can really slow down the i82586_reset() on some cards, but it's 1251 1.9 pk * necessary to unwedge other ones (eg, the Sun VME ones) from certain 1252 1.7 pk * lockups. 1253 1.7 pk */ 1254 1.10 pk if (hard && sc->hwreset) 1255 1.7 pk (sc->hwreset)(sc, CARD_RESET); 1256 1.6 pk 1257 1.10 pk delay(100); 1258 1.5 pk ie_ack(sc, IE_ST_WHENCE); 1259 1.6 pk 1260 1.9 pk if ((sc->sc_ethercom.ec_if.if_flags & IFF_UP) != 0) { 1261 1.9 pk int retries=0; /* XXX - find out why init sometimes fails */ 1262 1.9 pk while (retries++ < 2) 1263 1.31 scw if (i82586_init(&sc->sc_ethercom.ec_if) == 0) 1264 1.9 pk break; 1265 1.9 pk } 1266 1.1 pk 1267 1.1 pk splx(s); 1268 1.1 pk } 1269 1.1 pk 1270 1.9 pk 1271 1.9 pk static void 1272 1.65 dsl setup_simple_command(struct ie_softc *sc, int cmd, int cmdbuf) 1273 1.1 pk { 1274 1.9 pk /* Setup a simple command */ 1275 1.9 pk sc->ie_bus_write16(sc, IE_CMD_COMMON_STATUS(cmdbuf), 0); 1276 1.9 pk sc->ie_bus_write16(sc, IE_CMD_COMMON_CMD(cmdbuf), cmd | IE_CMD_LAST); 1277 1.9 pk sc->ie_bus_write16(sc, IE_CMD_COMMON_LINK(cmdbuf), 0xffff); 1278 1.1 pk 1279 1.9 pk /* Assign the command buffer to the SCB command list */ 1280 1.9 pk sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb), cmdbuf); 1281 1.1 pk } 1282 1.1 pk 1283 1.1 pk /* 1284 1.1 pk * Run the time-domain reflectometer. 1285 1.1 pk */ 1286 1.1 pk static void 1287 1.65 dsl ie_run_tdr(struct ie_softc *sc, int cmd) 1288 1.1 pk { 1289 1.1 pk int result; 1290 1.1 pk 1291 1.9 pk setup_simple_command(sc, IE_CMD_TDR, cmd); 1292 1.34 bjh21 sc->ie_bus_write16(sc, IE_CMD_TDR_TIME(cmd), 0); 1293 1.1 pk 1294 1.9 pk if (i82586_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0) || 1295 1.9 pk (sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd)) & IE_STAT_OK) == 0) 1296 1.1 pk result = 0x10000; /* XXX */ 1297 1.1 pk else 1298 1.9 pk result = sc->ie_bus_read16(sc, IE_CMD_TDR_TIME(cmd)); 1299 1.1 pk 1300 1.9 pk /* Squash any pending interrupts */ 1301 1.1 pk ie_ack(sc, IE_ST_WHENCE); 1302 1.1 pk 1303 1.1 pk if (result & IE_TDR_SUCCESS) 1304 1.1 pk return; 1305 1.1 pk 1306 1.1 pk if (result & 0x10000) 1307 1.69 tsutsui aprint_error_dev(sc->sc_dev, "TDR command failed\n"); 1308 1.1 pk else if (result & IE_TDR_XCVR) 1309 1.69 tsutsui aprint_error_dev(sc->sc_dev, "transceiver problem\n"); 1310 1.1 pk else if (result & IE_TDR_OPEN) 1311 1.73 msaitoh aprint_error_dev(sc->sc_dev, "TDR detected incorrect " 1312 1.73 msaitoh "termination %d clocks away\n", result & IE_TDR_TIME); 1313 1.1 pk else if (result & IE_TDR_SHORT) 1314 1.73 msaitoh aprint_error_dev(sc->sc_dev, "TDR detected a short circuit " 1315 1.73 msaitoh "%d clocks away\n", result & IE_TDR_TIME); 1316 1.1 pk else 1317 1.73 msaitoh aprint_error_dev(sc->sc_dev, 1318 1.73 msaitoh "TDR returned unknown status 0x%x\n", result); 1319 1.1 pk } 1320 1.1 pk 1321 1.1 pk 1322 1.1 pk /* 1323 1.9 pk * i82586_setup_bufs: set up the buffers 1324 1.1 pk * 1325 1.9 pk * We have a block of KVA at sc->buf_area which is of size sc->buf_area_sz. 1326 1.91 andvar * this is to be used for the buffers. The chip indexes its control data 1327 1.1 pk * structures with 16 bit offsets, and it indexes actual buffers with 1328 1.9 pk * 24 bit addresses. So we should allocate control buffers first so that 1329 1.1 pk * we don't overflow the 16 bit offset field. The number of transmit 1330 1.1 pk * buffers is fixed at compile time. 1331 1.1 pk * 1332 1.1 pk */ 1333 1.1 pk static void 1334 1.65 dsl i82586_setup_bufs(struct ie_softc *sc) 1335 1.1 pk { 1336 1.9 pk int ptr = sc->buf_area; /* memory pool */ 1337 1.81 msaitoh int n, r; 1338 1.1 pk 1339 1.1 pk /* 1340 1.1 pk * step 0: zero memory and figure out how many recv buffers and 1341 1.3 pk * frames we can have. 1342 1.1 pk */ 1343 1.9 pk ptr = (ptr + 3) & ~3; /* set alignment and stick with it */ 1344 1.9 pk 1345 1.9 pk 1346 1.9 pk /* 1347 1.9 pk * step 1: lay out data structures in the shared-memory area 1348 1.9 pk */ 1349 1.9 pk 1350 1.9 pk /* The no-op commands; used if "nop-chaining" is in effect */ 1351 1.9 pk sc->nop_cmds = ptr; 1352 1.9 pk ptr += NTXBUF * IE_CMD_NOP_SZ; 1353 1.9 pk 1354 1.9 pk /* The transmit commands */ 1355 1.9 pk sc->xmit_cmds = ptr; 1356 1.9 pk ptr += NTXBUF * IE_CMD_XMIT_SZ; 1357 1.1 pk 1358 1.9 pk /* The transmit buffers descriptors */ 1359 1.9 pk sc->xbds = ptr; 1360 1.9 pk ptr += NTXBUF * IE_XBD_SZ; 1361 1.1 pk 1362 1.9 pk /* The transmit buffers */ 1363 1.9 pk sc->xbufs = ptr; 1364 1.9 pk ptr += NTXBUF * IE_TBUF_SIZE; 1365 1.1 pk 1366 1.9 pk ptr = (ptr + 3) & ~3; /* re-align.. just in case */ 1367 1.1 pk 1368 1.9 pk /* Compute free space for RECV stuff */ 1369 1.9 pk n = sc->buf_area_sz - (ptr - sc->buf_area); 1370 1.9 pk 1371 1.9 pk /* Compute size of one RECV frame */ 1372 1.9 pk r = IE_RFRAME_SZ + ((IE_RBD_SZ + IE_RBUF_SIZE) * B_PER_F); 1373 1.1 pk 1374 1.1 pk sc->nframes = n / r; 1375 1.9 pk 1376 1.1 pk if (sc->nframes <= 0) 1377 1.44 provos panic("ie: bogus buffer calc"); 1378 1.1 pk 1379 1.1 pk sc->nrxbuf = sc->nframes * B_PER_F; 1380 1.1 pk 1381 1.48 wiz /* The receive frame descriptors */ 1382 1.9 pk sc->rframes = ptr; 1383 1.9 pk ptr += sc->nframes * IE_RFRAME_SZ; 1384 1.9 pk 1385 1.9 pk /* The receive buffer descriptors */ 1386 1.9 pk sc->rbds = ptr; 1387 1.9 pk ptr += sc->nrxbuf * IE_RBD_SZ; 1388 1.9 pk 1389 1.9 pk /* The receive buffers */ 1390 1.9 pk sc->rbufs = ptr; 1391 1.9 pk ptr += sc->nrxbuf * IE_RBUF_SIZE; 1392 1.9 pk 1393 1.25 pk #if I82586_DEBUG 1394 1.73 msaitoh printf("%s: %d frames %d bufs\n", device_xname(sc->sc_dev), 1395 1.73 msaitoh sc->nframes, sc->nrxbuf); 1396 1.1 pk #endif 1397 1.1 pk 1398 1.1 pk /* 1399 1.9 pk * step 2: link together the recv frames and set EOL on last one 1400 1.1 pk */ 1401 1.9 pk for (n = 0; n < sc->nframes; n++) { 1402 1.9 pk int m = (n == sc->nframes - 1) ? 0 : n + 1; 1403 1.9 pk 1404 1.9 pk /* Clear status */ 1405 1.82 msaitoh sc->ie_bus_write16(sc, IE_RFRAME_STATUS(sc->rframes, n), 0); 1406 1.9 pk 1407 1.9 pk /* RBD link = NULL */ 1408 1.82 msaitoh sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes, n), 1409 1.9 pk 0xffff); 1410 1.9 pk 1411 1.9 pk /* Make a circular list */ 1412 1.82 msaitoh sc->ie_bus_write16(sc, IE_RFRAME_NEXT(sc->rframes, n), 1413 1.82 msaitoh IE_RFRAME_ADDR(sc->rframes, m)); 1414 1.1 pk 1415 1.9 pk /* Mark last as EOL */ 1416 1.82 msaitoh sc->ie_bus_write16(sc, IE_RFRAME_LAST(sc->rframes, n), 1417 1.81 msaitoh ((m==0)? (IE_FD_EOL | IE_FD_SUSP) : 0)); 1418 1.1 pk } 1419 1.1 pk 1420 1.1 pk /* 1421 1.9 pk * step 3: link the RBDs and set EOL on last one 1422 1.1 pk */ 1423 1.9 pk for (n = 0; n < sc->nrxbuf; n++) { 1424 1.9 pk int m = (n == sc->nrxbuf - 1) ? 0 : n + 1; 1425 1.9 pk 1426 1.9 pk /* Clear status */ 1427 1.82 msaitoh sc->ie_bus_write16(sc, IE_RBD_STATUS(sc->rbds, n), 0); 1428 1.9 pk 1429 1.9 pk /* Make a circular list */ 1430 1.82 msaitoh sc->ie_bus_write16(sc, IE_RBD_NEXT(sc->rbds, n), 1431 1.82 msaitoh IE_RBD_ADDR(sc->rbds, m)); 1432 1.9 pk 1433 1.9 pk /* Link to data buffers */ 1434 1.9 pk sc->ie_bus_write24(sc, IE_RBD_BUFADDR(sc->rbds, n), 1435 1.9 pk IE_RBUF_ADDR(sc, n)); 1436 1.82 msaitoh sc->ie_bus_write16(sc, IE_RBD_BUFLEN(sc->rbds, n), 1437 1.9 pk IE_RBUF_SIZE | ((m==0)?IE_RBD_EOL:0)); 1438 1.1 pk } 1439 1.1 pk 1440 1.1 pk /* 1441 1.9 pk * step 4: all xmit no-op commands loopback onto themselves 1442 1.6 pk */ 1443 1.6 pk for (n = 0; n < NTXBUF; n++) { 1444 1.34 bjh21 sc->ie_bus_write16(sc, IE_CMD_NOP_STATUS(sc->nop_cmds, n), 0); 1445 1.6 pk 1446 1.34 bjh21 sc->ie_bus_write16(sc, IE_CMD_NOP_CMD(sc->nop_cmds, n), 1447 1.9 pk IE_CMD_NOP); 1448 1.1 pk 1449 1.34 bjh21 sc->ie_bus_write16(sc, IE_CMD_NOP_LINK(sc->nop_cmds, n), 1450 1.9 pk IE_CMD_NOP_ADDR(sc->nop_cmds, n)); 1451 1.1 pk } 1452 1.1 pk 1453 1.1 pk 1454 1.1 pk /* 1455 1.9 pk * step 6: set the head and tail pointers on receive to keep track of 1456 1.9 pk * the order in which RFDs and RBDs are used. 1457 1.1 pk */ 1458 1.1 pk 1459 1.1 pk /* Pointers to last packet sent and next available transmit buffer. */ 1460 1.1 pk sc->xchead = sc->xctail = 0; 1461 1.1 pk 1462 1.1 pk /* Clear transmit-busy flag and set number of free transmit buffers. */ 1463 1.1 pk sc->xmit_busy = 0; 1464 1.1 pk 1465 1.1 pk /* 1466 1.9 pk * Pointers to first and last receive frame. 1467 1.9 pk * The RFD pointed to by rftail is the only one that has EOL set. 1468 1.1 pk */ 1469 1.1 pk sc->rfhead = 0; 1470 1.1 pk sc->rftail = sc->nframes - 1; 1471 1.9 pk 1472 1.9 pk /* 1473 1.9 pk * Pointers to first and last receive descriptor buffer. 1474 1.9 pk * The RBD pointed to by rbtail is the only one that has EOL set. 1475 1.9 pk */ 1476 1.1 pk sc->rbhead = 0; 1477 1.1 pk sc->rbtail = sc->nrxbuf - 1; 1478 1.1 pk 1479 1.9 pk /* link in recv frames * and buffer into the scb. */ 1480 1.25 pk #if I82586_DEBUG 1481 1.9 pk printf("%s: reserved %d bytes\n", 1482 1.69 tsutsui device_xname(sc->sc_dev), ptr - sc->buf_area); 1483 1.1 pk #endif 1484 1.1 pk } 1485 1.1 pk 1486 1.9 pk static int 1487 1.66 dsl ie_cfg_setup(struct ie_softc *sc, int cmd, int promiscuous, int manchester) 1488 1.9 pk { 1489 1.9 pk int cmdresult, status; 1490 1.81 msaitoh uint8_t buf[IE_CMD_CFG_SZ]; /* XXX malloc? */ 1491 1.9 pk 1492 1.81 msaitoh *IE_CMD_CFG_CNT(buf) = 0x0c; 1493 1.81 msaitoh *IE_CMD_CFG_FIFO(buf) = 8; 1494 1.81 msaitoh *IE_CMD_CFG_SAVEBAD(buf) = 0x40; 1495 1.27 bjh21 *IE_CMD_CFG_ADDRLEN(buf) = 0x2e; 1496 1.27 bjh21 *IE_CMD_CFG_PRIORITY(buf) = 0; 1497 1.81 msaitoh *IE_CMD_CFG_IFS(buf) = 0x60; 1498 1.27 bjh21 *IE_CMD_CFG_SLOT_LOW(buf) = 0; 1499 1.27 bjh21 *IE_CMD_CFG_SLOT_HIGH(buf) = 0xf2; 1500 1.70 mrg *IE_CMD_CFG_PROMISC(buf) = (!!promiscuous) | manchester << 2; 1501 1.81 msaitoh *IE_CMD_CFG_CRSCDT(buf) = 0; 1502 1.81 msaitoh *IE_CMD_CFG_MINLEN(buf) = 64; 1503 1.81 msaitoh *IE_CMD_CFG_JUNK(buf) = 0xff; 1504 1.27 bjh21 sc->memcopyout(sc, buf, cmd, IE_CMD_CFG_SZ); 1505 1.9 pk setup_simple_command(sc, IE_CMD_CONFIG, cmd); 1506 1.34 bjh21 IE_BUS_BARRIER(sc, cmd, IE_CMD_CFG_SZ, BUS_SPACE_BARRIER_WRITE); 1507 1.9 pk 1508 1.9 pk cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0); 1509 1.9 pk status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd)); 1510 1.9 pk if (cmdresult != 0) { 1511 1.73 msaitoh aprint_error_dev(sc->sc_dev, 1512 1.73 msaitoh "configure command timed out; status %x\n", status); 1513 1.9 pk return (0); 1514 1.9 pk } 1515 1.9 pk if ((status & IE_STAT_OK) == 0) { 1516 1.73 msaitoh aprint_error_dev(sc->sc_dev, 1517 1.73 msaitoh "configure command failed; status %x\n", status); 1518 1.9 pk return (0); 1519 1.9 pk } 1520 1.10 pk 1521 1.10 pk /* Squash any pending interrupts */ 1522 1.10 pk ie_ack(sc, IE_ST_WHENCE); 1523 1.9 pk return (1); 1524 1.9 pk } 1525 1.9 pk 1526 1.9 pk static int 1527 1.65 dsl ie_ia_setup(struct ie_softc *sc, int cmdbuf) 1528 1.9 pk { 1529 1.9 pk int cmdresult, status; 1530 1.9 pk struct ifnet *ifp = &sc->sc_ethercom.ec_if; 1531 1.9 pk 1532 1.9 pk setup_simple_command(sc, IE_CMD_IASETUP, cmdbuf); 1533 1.9 pk 1534 1.59 dyoung (sc->memcopyout)(sc, CLLADDR(ifp->if_sadl), 1535 1.9 pk IE_CMD_IAS_EADDR(cmdbuf), ETHER_ADDR_LEN); 1536 1.9 pk 1537 1.9 pk cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 0); 1538 1.9 pk status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf)); 1539 1.9 pk if (cmdresult != 0) { 1540 1.73 msaitoh aprint_error_dev(sc->sc_dev, 1541 1.73 msaitoh "individual address command timed out; status %x\n", 1542 1.73 msaitoh status); 1543 1.9 pk return (0); 1544 1.9 pk } 1545 1.9 pk if ((status & IE_STAT_OK) == 0) { 1546 1.73 msaitoh aprint_error_dev(sc->sc_dev, 1547 1.73 msaitoh "individual address command failed; status %x\n", status); 1548 1.9 pk return (0); 1549 1.9 pk } 1550 1.10 pk 1551 1.10 pk /* Squash any pending interrupts */ 1552 1.10 pk ie_ack(sc, IE_ST_WHENCE); 1553 1.9 pk return (1); 1554 1.9 pk } 1555 1.9 pk 1556 1.1 pk /* 1557 1.1 pk * Run the multicast setup command. 1558 1.1 pk * Called at splnet(). 1559 1.1 pk */ 1560 1.1 pk static int 1561 1.65 dsl ie_mc_setup(struct ie_softc *sc, int cmdbuf) 1562 1.1 pk { 1563 1.9 pk int cmdresult, status; 1564 1.1 pk 1565 1.9 pk if (sc->mcast_count == 0) 1566 1.9 pk return (1); 1567 1.1 pk 1568 1.9 pk setup_simple_command(sc, IE_CMD_MCAST, cmdbuf); 1569 1.1 pk 1570 1.58 christos (sc->memcopyout)(sc, (void *)sc->mcast_addrs, 1571 1.9 pk IE_CMD_MCAST_MADDR(cmdbuf), 1572 1.9 pk sc->mcast_count * ETHER_ADDR_LEN); 1573 1.9 pk 1574 1.9 pk sc->ie_bus_write16(sc, IE_CMD_MCAST_BYTES(cmdbuf), 1575 1.9 pk sc->mcast_count * ETHER_ADDR_LEN); 1576 1.9 pk 1577 1.9 pk /* Start the command */ 1578 1.73 msaitoh cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmdbuf, IE_STAT_COMPL, 1579 1.73 msaitoh 0); 1580 1.9 pk status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmdbuf)); 1581 1.9 pk if (cmdresult != 0) { 1582 1.73 msaitoh aprint_error_dev(sc->sc_dev, 1583 1.73 msaitoh "multicast setup command timed out; status %x\n", status); 1584 1.9 pk return (0); 1585 1.9 pk } 1586 1.9 pk if ((status & IE_STAT_OK) == 0) { 1587 1.73 msaitoh aprint_error_dev(sc->sc_dev, 1588 1.73 msaitoh "multicast setup command failed; status %x\n", status); 1589 1.9 pk return (0); 1590 1.1 pk } 1591 1.6 pk 1592 1.10 pk /* Squash any pending interrupts */ 1593 1.10 pk ie_ack(sc, IE_ST_WHENCE); 1594 1.9 pk return (1); 1595 1.1 pk } 1596 1.1 pk 1597 1.1 pk /* 1598 1.1 pk * This routine takes the environment generated by check_ie_present() and adds 1599 1.1 pk * to it all the other structures we need to operate the adapter. This 1600 1.1 pk * includes executing the CONFIGURE, IA-SETUP, and MC-SETUP commands, starting 1601 1.1 pk * the receiver unit, and clearing interrupts. 1602 1.1 pk * 1603 1.1 pk * THIS ROUTINE MUST BE CALLED AT splnet() OR HIGHER. 1604 1.1 pk */ 1605 1.1 pk int 1606 1.65 dsl i82586_init(struct ifnet *ifp) 1607 1.1 pk { 1608 1.29 bjh21 struct ie_softc *sc = ifp->if_softc; 1609 1.9 pk int cmd; 1610 1.9 pk 1611 1.10 pk sc->async_cmd_inprogress = 0; 1612 1.1 pk 1613 1.9 pk cmd = sc->buf_area; 1614 1.1 pk 1615 1.1 pk /* 1616 1.1 pk * Send the configure command first. 1617 1.1 pk */ 1618 1.9 pk if (ie_cfg_setup(sc, cmd, sc->promisc, 0) == 0) 1619 1.37 bjh21 return EIO; 1620 1.1 pk 1621 1.9 pk /* 1622 1.9 pk * Send the Individual Address Setup command. 1623 1.9 pk */ 1624 1.9 pk if (ie_ia_setup(sc, cmd) == 0) 1625 1.37 bjh21 return EIO; 1626 1.1 pk 1627 1.1 pk /* 1628 1.9 pk * Run the time-domain reflectometer. 1629 1.1 pk */ 1630 1.9 pk ie_run_tdr(sc, cmd); 1631 1.1 pk 1632 1.1 pk /* 1633 1.9 pk * Set the multi-cast filter, if any 1634 1.1 pk */ 1635 1.9 pk if (ie_mc_setup(sc, cmd) == 0) 1636 1.37 bjh21 return EIO; 1637 1.1 pk 1638 1.1 pk /* 1639 1.1 pk * Acknowledge any interrupts we have generated thus far. 1640 1.1 pk */ 1641 1.1 pk ie_ack(sc, IE_ST_WHENCE); 1642 1.1 pk 1643 1.1 pk /* 1644 1.1 pk * Set up the transmit and recv buffers. 1645 1.1 pk */ 1646 1.9 pk i82586_setup_bufs(sc); 1647 1.1 pk 1648 1.6 pk if (sc->hwinit) 1649 1.6 pk (sc->hwinit)(sc); 1650 1.6 pk 1651 1.3 pk ifp->if_flags |= IFF_RUNNING; 1652 1.1 pk 1653 1.6 pk if (NTXBUF < 2) 1654 1.7 pk sc->do_xmitnopchain = 0; 1655 1.6 pk 1656 1.6 pk i82586_start_transceiver(sc); 1657 1.31 scw return (0); 1658 1.6 pk } 1659 1.6 pk 1660 1.9 pk /* 1661 1.9 pk * Start the RU and possibly the CU unit 1662 1.9 pk */ 1663 1.6 pk static void 1664 1.65 dsl i82586_start_transceiver(struct ie_softc *sc) 1665 1.6 pk { 1666 1.9 pk 1667 1.9 pk /* 1668 1.9 pk * Start RU at current position in frame & RBD lists. 1669 1.9 pk */ 1670 1.82 msaitoh sc->ie_bus_write16(sc, IE_RFRAME_BUFDESC(sc->rframes, sc->rfhead), 1671 1.9 pk IE_RBD_ADDR(sc->rbds, sc->rbhead)); 1672 1.9 pk 1673 1.9 pk sc->ie_bus_write16(sc, IE_SCB_RCVLST(sc->scb), 1674 1.82 msaitoh IE_RFRAME_ADDR(sc->rframes, sc->rfhead)); 1675 1.1 pk 1676 1.7 pk if (sc->do_xmitnopchain) { 1677 1.6 pk /* Stop transmit command chain */ 1678 1.81 msaitoh if (i82586_start_cmd(sc, IE_CUC_SUSPEND | IE_RUC_SUSPEND, 1679 1.81 msaitoh 0, 0, 0)) 1680 1.73 msaitoh aprint_error_dev(sc->sc_dev, 1681 1.73 msaitoh "CU/RU stop command timed out\n"); 1682 1.1 pk 1683 1.6 pk /* Start the receiver & transmitter chain */ 1684 1.9 pk /* sc->scb->ie_command_list = 1685 1.9 pk IEADDR(sc->nop_cmds[(sc->xctail+NTXBUF-1) % NTXBUF]);*/ 1686 1.9 pk sc->ie_bus_write16(sc, IE_SCB_CMDLST(sc->scb), 1687 1.9 pk IE_CMD_NOP_ADDR( 1688 1.9 pk sc->nop_cmds, 1689 1.9 pk (sc->xctail + NTXBUF - 1) % NTXBUF)); 1690 1.9 pk 1691 1.81 msaitoh if (i82586_start_cmd(sc, IE_CUC_START | IE_RUC_START, 0, 0, 0)) 1692 1.73 msaitoh aprint_error_dev(sc->sc_dev, 1693 1.73 msaitoh "CU/RU command timed out\n"); 1694 1.6 pk } else { 1695 1.9 pk if (i82586_start_cmd(sc, IE_RUC_START, 0, 0, 0)) 1696 1.69 tsutsui aprint_error_dev(sc->sc_dev, "RU command timed out\n"); 1697 1.6 pk } 1698 1.1 pk } 1699 1.1 pk 1700 1.29 bjh21 void 1701 1.74 msaitoh i82586_stop(struct ifnet *ifp, int disable) 1702 1.1 pk { 1703 1.29 bjh21 struct ie_softc *sc = ifp->if_softc; 1704 1.1 pk 1705 1.9 pk if (i82586_start_cmd(sc, IE_RUC_SUSPEND | IE_CUC_SUSPEND, 0, 0, 0)) 1706 1.73 msaitoh aprint_error_dev(sc->sc_dev, 1707 1.73 msaitoh "iestop: disable commands timed out\n"); 1708 1.1 pk } 1709 1.1 pk 1710 1.1 pk int 1711 1.63 dyoung i82586_ioctl(struct ifnet *ifp, unsigned long cmd, void *data) 1712 1.1 pk { 1713 1.1 pk struct ie_softc *sc = ifp->if_softc; 1714 1.1 pk int s, error = 0; 1715 1.1 pk 1716 1.1 pk s = splnet(); 1717 1.82 msaitoh switch (cmd) { 1718 1.29 bjh21 default: 1719 1.29 bjh21 error = ether_ioctl(ifp, cmd, data); 1720 1.1 pk if (error == ENETRESET) { 1721 1.1 pk /* 1722 1.1 pk * Multicast list has changed; set the hardware filter 1723 1.1 pk * accordingly. 1724 1.1 pk */ 1725 1.49 thorpej if (ifp->if_flags & IFF_RUNNING) 1726 1.49 thorpej ie_mc_reset(sc); 1727 1.1 pk error = 0; 1728 1.1 pk } 1729 1.1 pk break; 1730 1.1 pk } 1731 1.29 bjh21 #if I82586_DEBUG 1732 1.29 bjh21 if (cmd == SIOCSIFFLAGS) 1733 1.29 bjh21 sc->sc_debug = (ifp->if_flags & IFF_DEBUG) ? IED_ALL : 0; 1734 1.29 bjh21 #endif 1735 1.1 pk splx(s); 1736 1.10 pk return (error); 1737 1.1 pk } 1738 1.1 pk 1739 1.1 pk static void 1740 1.65 dsl ie_mc_reset(struct ie_softc *sc) 1741 1.1 pk { 1742 1.82 msaitoh struct ethercom *ec = &sc->sc_ethercom; 1743 1.1 pk struct ether_multi *enm; 1744 1.1 pk struct ether_multistep step; 1745 1.9 pk int size; 1746 1.1 pk 1747 1.1 pk /* 1748 1.1 pk * Step through the list of addresses. 1749 1.1 pk */ 1750 1.9 pk again: 1751 1.9 pk size = 0; 1752 1.1 pk sc->mcast_count = 0; 1753 1.84 msaitoh ETHER_LOCK(ec); 1754 1.82 msaitoh ETHER_FIRST_MULTI(step, ec, enm); 1755 1.1 pk while (enm) { 1756 1.9 pk size += 6; 1757 1.9 pk if (sc->mcast_count >= IE_MAXMCAST || 1758 1.38 thorpej memcmp(enm->enm_addrlo, enm->enm_addrhi, 6) != 0) { 1759 1.82 msaitoh ec->ec_if.if_flags |= IFF_ALLMULTI; 1760 1.82 msaitoh i82586_ioctl(&ec->ec_if, SIOCSIFFLAGS, NULL); 1761 1.84 msaitoh ETHER_UNLOCK(ec); 1762 1.9 pk return; 1763 1.1 pk } 1764 1.9 pk ETHER_NEXT_MULTI(step, enm); 1765 1.9 pk } 1766 1.84 msaitoh ETHER_UNLOCK(ec); 1767 1.9 pk 1768 1.9 pk if (size > sc->mcast_addrs_size) { 1769 1.9 pk /* Need to allocate more space */ 1770 1.9 pk if (sc->mcast_addrs_size) 1771 1.43 thorpej free(sc->mcast_addrs, M_IFMADDR); 1772 1.9 pk sc->mcast_addrs = (char *) 1773 1.43 thorpej malloc(size, M_IFMADDR, M_WAITOK); 1774 1.9 pk sc->mcast_addrs_size = size; 1775 1.9 pk } 1776 1.9 pk 1777 1.9 pk /* 1778 1.9 pk * We've got the space; now copy the addresses 1779 1.9 pk */ 1780 1.84 msaitoh ETHER_LOCK(ec); 1781 1.84 msaitoh ETHER_FIRST_MULTI(step, ec, enm); 1782 1.9 pk while (enm) { 1783 1.84 msaitoh if (sc->mcast_count >= IE_MAXMCAST) { 1784 1.84 msaitoh ETHER_UNLOCK(ec); 1785 1.9 pk goto again; /* Just in case */ 1786 1.84 msaitoh } 1787 1.1 pk 1788 1.39 thorpej memcpy(&sc->mcast_addrs[sc->mcast_count], enm->enm_addrlo, 6); 1789 1.1 pk sc->mcast_count++; 1790 1.1 pk ETHER_NEXT_MULTI(step, enm); 1791 1.1 pk } 1792 1.84 msaitoh ETHER_UNLOCK(ec); 1793 1.1 pk sc->want_mcsetup = 1; 1794 1.1 pk } 1795 1.1 pk 1796 1.7 pk /* 1797 1.7 pk * Media change callback. 1798 1.7 pk */ 1799 1.7 pk int 1800 1.65 dsl i82586_mediachange(struct ifnet *ifp) 1801 1.7 pk { 1802 1.81 msaitoh struct ie_softc *sc = ifp->if_softc; 1803 1.7 pk 1804 1.81 msaitoh if (sc->sc_mediachange) 1805 1.81 msaitoh return ((*sc->sc_mediachange)(sc)); 1806 1.81 msaitoh return (0); 1807 1.7 pk } 1808 1.7 pk 1809 1.7 pk /* 1810 1.7 pk * Media status callback. 1811 1.7 pk */ 1812 1.7 pk void 1813 1.65 dsl i82586_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 1814 1.9 pk { 1815 1.81 msaitoh struct ie_softc *sc = ifp->if_softc; 1816 1.7 pk 1817 1.81 msaitoh if (sc->sc_mediastatus) 1818 1.81 msaitoh (*sc->sc_mediastatus)(sc, ifmr); 1819 1.7 pk } 1820 1.7 pk 1821 1.25 pk #if I82586_DEBUG 1822 1.1 pk void 1823 1.65 dsl print_rbd(struct ie_softc *sc, int n) 1824 1.1 pk { 1825 1.1 pk 1826 1.81 msaitoh printf("RBD at %08x:\n status %04x, next %04x, buffer %lx\n" 1827 1.82 msaitoh "length/EOL %04x\n", IE_RBD_ADDR(sc->rbds, n), 1828 1.82 msaitoh sc->ie_bus_read16(sc, IE_RBD_STATUS(sc->rbds, n)), 1829 1.82 msaitoh sc->ie_bus_read16(sc, IE_RBD_NEXT(sc->rbds, n)), 1830 1.9 pk (u_long)0,/*bus_space_read_4(sc->bt, sc->bh, IE_RBD_BUFADDR(sc->rbds,n)),-* XXX */ 1831 1.82 msaitoh sc->ie_bus_read16(sc, IE_RBD_BUFLEN(sc->rbds, n))); 1832 1.1 pk } 1833 1.1 pk #endif 1834