1 1.59 riastrad /* $NetBSD: if_mc.c,v 1.59 2024/06/29 12:11:10 riastradh Exp $ */ 2 1.2 briggs 3 1.1 briggs /*- 4 1.23 wiz * Copyright (c) 1997 David Huang <khym (at) azeotrope.org> 5 1.1 briggs * All rights reserved. 6 1.1 briggs * 7 1.1 briggs * Portions of this code are based on code by Denton Gentry <denny1 (at) home.com>, 8 1.1 briggs * Charles M. Hannum, Yanagisawa Takeshi <yanagisw (at) aa.ap.titech.ac.jp>, and 9 1.1 briggs * Jason R. Thorpe. 10 1.1 briggs * 11 1.1 briggs * Redistribution and use in source and binary forms, with or without 12 1.1 briggs * modification, are permitted provided that the following conditions 13 1.1 briggs * are met: 14 1.1 briggs * 1. Redistributions of source code must retain the above copyright 15 1.1 briggs * notice, this list of conditions and the following disclaimer. 16 1.1 briggs * 2. The name of the author may not be used to endorse or promote products 17 1.1 briggs * derived from this software without specific prior written permission 18 1.1 briggs * 19 1.1 briggs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 1.1 briggs * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 1.1 briggs * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 1.1 briggs * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 1.1 briggs * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 1.1 briggs * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 1.1 briggs * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 1.1 briggs * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 1.1 briggs * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 1.1 briggs * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 1.1 briggs * 30 1.1 briggs */ 31 1.1 briggs 32 1.1 briggs /* 33 1.1 briggs * Driver for the AMD Am79C940 (MACE) ethernet chip, used for onboard 34 1.1 briggs * ethernet on the Centris/Quadra 660av and Quadra 840av. 35 1.1 briggs */ 36 1.22 lukem 37 1.22 lukem #include <sys/cdefs.h> 38 1.59 riastrad __KERNEL_RCSID(0, "$NetBSD: if_mc.c,v 1.59 2024/06/29 12:11:10 riastradh Exp $"); 39 1.1 briggs 40 1.7 jonathan #include "opt_ddb.h" 41 1.7 jonathan #include "opt_inet.h" 42 1.7 jonathan 43 1.1 briggs #include <sys/param.h> 44 1.1 briggs #include <sys/systm.h> 45 1.1 briggs #include <sys/mbuf.h> 46 1.1 briggs #include <sys/buf.h> 47 1.1 briggs #include <sys/protosw.h> 48 1.1 briggs #include <sys/socket.h> 49 1.1 briggs #include <sys/syslog.h> 50 1.1 briggs #include <sys/ioctl.h> 51 1.1 briggs #include <sys/errno.h> 52 1.1 briggs #include <sys/device.h> 53 1.1 briggs 54 1.57 rin #include <sys/rndsource.h> 55 1.57 rin 56 1.20 thorpej #include <uvm/uvm_extern.h> 57 1.20 thorpej 58 1.1 briggs #include <net/if.h> 59 1.1 briggs #include <net/if_dl.h> 60 1.1 briggs #include <net/if_ether.h> 61 1.46 msaitoh #include <net/bpf.h> 62 1.1 briggs 63 1.1 briggs #ifdef INET 64 1.1 briggs #include <netinet/in.h> 65 1.1 briggs #include <netinet/if_inarp.h> 66 1.1 briggs #include <netinet/in_systm.h> 67 1.1 briggs #include <netinet/in_var.h> 68 1.1 briggs #include <netinet/ip.h> 69 1.1 briggs #endif 70 1.1 briggs 71 1.1 briggs #include <machine/bus.h> 72 1.1 briggs #include <mac68k/dev/if_mcreg.h> 73 1.1 briggs #include <mac68k/dev/if_mcvar.h> 74 1.1 briggs 75 1.25 chs hide void mcwatchdog(struct ifnet *); 76 1.25 chs hide int mcinit(struct mc_softc *); 77 1.25 chs hide int mcstop(struct mc_softc *); 78 1.30 christos hide int mcioctl(struct ifnet *, u_long, void *); 79 1.25 chs hide void mcstart(struct ifnet *); 80 1.25 chs hide void mcreset(struct mc_softc *); 81 1.25 chs 82 1.25 chs integrate u_int maceput(struct mc_softc *, struct mbuf *); 83 1.25 chs integrate void mc_tint(struct mc_softc *); 84 1.30 christos integrate void mace_read(struct mc_softc *, void *, int); 85 1.30 christos integrate struct mbuf *mace_get(struct mc_softc *, void *, int); 86 1.50 msaitoh static void mace_calcladrf(struct ethercom *, uint8_t *); 87 1.50 msaitoh static inline uint16_t ether_cmp(void *, void *); 88 1.1 briggs 89 1.1 briggs 90 1.1 briggs /* 91 1.1 briggs * Compare two Ether/802 addresses for equality, inlined and 92 1.36 cegger * unrolled for speed. Use this like memcmp(). 93 1.1 briggs * 94 1.1 briggs * XXX: Add <machine/inlines.h> for stuff like this? 95 1.1 briggs * XXX: or maybe add it to libkern.h instead? 96 1.1 briggs * 97 1.1 briggs * "I'd love to have an inline assembler version of this." 98 1.1 briggs * XXX: Who wanted that? mycroft? I wrote one, but this 99 1.1 briggs * version in C is as good as hand-coded assembly. -gwr 100 1.1 briggs * 101 1.1 briggs * Please do NOT tweak this without looking at the actual 102 1.1 briggs * assembly code generated before and after your tweaks! 103 1.1 briggs */ 104 1.50 msaitoh static inline uint16_t 105 1.25 chs ether_cmp(void *one, void *two) 106 1.1 briggs { 107 1.50 msaitoh uint16_t *a = (u_short *) one; 108 1.50 msaitoh uint16_t *b = (u_short *) two; 109 1.50 msaitoh uint16_t diff; 110 1.1 briggs 111 1.1 briggs #ifdef m68k 112 1.1 briggs /* 113 1.1 briggs * The post-increment-pointer form produces the best 114 1.1 briggs * machine code for m68k. This was carefully tuned 115 1.1 briggs * so it compiles to just 8 short (2-byte) op-codes! 116 1.1 briggs */ 117 1.1 briggs diff = *a++ - *b++; 118 1.1 briggs diff |= *a++ - *b++; 119 1.1 briggs diff |= *a++ - *b++; 120 1.1 briggs #else 121 1.1 briggs /* 122 1.52 msaitoh * Most modern CPUs do better with a single expression. 123 1.1 briggs * Note that short-cut evaluation is NOT helpful here, 124 1.1 briggs * because it just makes the code longer, not faster! 125 1.1 briggs */ 126 1.1 briggs diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]); 127 1.1 briggs #endif 128 1.1 briggs 129 1.50 msaitoh return diff; 130 1.1 briggs } 131 1.1 briggs 132 1.1 briggs #define ETHER_CMP ether_cmp 133 1.1 briggs 134 1.1 briggs /* 135 1.1 briggs * Interface exists: make available by filling in network interface 136 1.1 briggs * record. System will initialize the interface when it is ready 137 1.1 briggs * to accept packets. 138 1.1 briggs */ 139 1.1 briggs int 140 1.50 msaitoh mcsetup(struct mc_softc *sc, uint8_t *lladdr) 141 1.1 briggs { 142 1.1 briggs struct ifnet *ifp = &sc->sc_if; 143 1.1 briggs 144 1.1 briggs /* reset the chip and disable all interrupts */ 145 1.1 briggs NIC_PUT(sc, MACE_BIUCC, SWRST); 146 1.1 briggs DELAY(100); 147 1.1 briggs NIC_PUT(sc, MACE_IMR, ~0); 148 1.1 briggs 149 1.25 chs memcpy(sc->sc_enaddr, lladdr, ETHER_ADDR_LEN); 150 1.1 briggs printf(": address %s\n", ether_sprintf(lladdr)); 151 1.1 briggs 152 1.39 chs memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); 153 1.1 briggs ifp->if_softc = sc; 154 1.1 briggs ifp->if_ioctl = mcioctl; 155 1.1 briggs ifp->if_start = mcstart; 156 1.49 msaitoh ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 157 1.1 briggs ifp->if_watchdog = mcwatchdog; 158 1.1 briggs 159 1.1 briggs if_attach(ifp); 160 1.45 nonaka if_deferred_start_init(ifp, NULL); 161 1.1 briggs ether_ifattach(ifp, lladdr); 162 1.1 briggs 163 1.57 rin rnd_attach_source(&sc->rnd_source, ifp->if_xname, RND_TYPE_NET, 164 1.57 rin RND_FLAG_DEFAULT); 165 1.57 rin 166 1.50 msaitoh return 0; 167 1.1 briggs } 168 1.1 briggs 169 1.1 briggs hide int 170 1.30 christos mcioctl(struct ifnet *ifp, u_long cmd, void *data) 171 1.1 briggs { 172 1.1 briggs struct mc_softc *sc = ifp->if_softc; 173 1.1 briggs struct ifaddr *ifa; 174 1.1 briggs 175 1.1 briggs int s = splnet(), err = 0; 176 1.1 briggs 177 1.1 briggs switch (cmd) { 178 1.1 briggs 179 1.35 dyoung case SIOCINITIFADDR: 180 1.1 briggs ifa = (struct ifaddr *)data; 181 1.1 briggs ifp->if_flags |= IFF_UP; 182 1.35 dyoung mcinit(sc); 183 1.1 briggs switch (ifa->ifa_addr->sa_family) { 184 1.1 briggs #ifdef INET 185 1.1 briggs case AF_INET: 186 1.1 briggs arp_ifinit(ifp, ifa); 187 1.1 briggs break; 188 1.1 briggs #endif 189 1.1 briggs default: 190 1.1 briggs break; 191 1.1 briggs } 192 1.1 briggs break; 193 1.1 briggs 194 1.1 briggs case SIOCSIFFLAGS: 195 1.35 dyoung if ((err = ifioctl_common(ifp, cmd, data)) != 0) 196 1.35 dyoung break; 197 1.35 dyoung /* XXX see the comment in ed_ioctl() about code re-use */ 198 1.1 briggs if ((ifp->if_flags & IFF_UP) == 0 && 199 1.1 briggs (ifp->if_flags & IFF_RUNNING) != 0) { 200 1.1 briggs /* 201 1.1 briggs * If interface is marked down and it is running, 202 1.1 briggs * then stop it. 203 1.1 briggs */ 204 1.1 briggs mcstop(sc); 205 1.1 briggs ifp->if_flags &= ~IFF_RUNNING; 206 1.1 briggs } else if ((ifp->if_flags & IFF_UP) != 0 && 207 1.1 briggs (ifp->if_flags & IFF_RUNNING) == 0) { 208 1.1 briggs /* 209 1.1 briggs * If interface is marked up and it is stopped, 210 1.1 briggs * then start it. 211 1.1 briggs */ 212 1.1 briggs (void)mcinit(sc); 213 1.1 briggs } else { 214 1.1 briggs /* 215 1.1 briggs * reset the interface to pick up any other changes 216 1.1 briggs * in flags 217 1.1 briggs */ 218 1.1 briggs mcreset(sc); 219 1.1 briggs mcstart(ifp); 220 1.1 briggs } 221 1.1 briggs break; 222 1.1 briggs 223 1.1 briggs case SIOCADDMULTI: 224 1.1 briggs case SIOCDELMULTI: 225 1.32 dyoung if ((err = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 226 1.1 briggs /* 227 1.1 briggs * Multicast list has changed; set the hardware 228 1.1 briggs * filter accordingly. But remember UP flag! 229 1.1 briggs */ 230 1.24 thorpej if (ifp->if_flags & IFF_RUNNING) 231 1.24 thorpej mcreset(sc); 232 1.1 briggs err = 0; 233 1.1 briggs } 234 1.1 briggs break; 235 1.1 briggs default: 236 1.35 dyoung err = ether_ioctl(ifp, cmd, data); 237 1.1 briggs } 238 1.1 briggs splx(s); 239 1.50 msaitoh return err; 240 1.1 briggs } 241 1.1 briggs 242 1.1 briggs /* 243 1.1 briggs * Encapsulate a packet of type family for the local net. 244 1.1 briggs */ 245 1.1 briggs hide void 246 1.25 chs mcstart(struct ifnet *ifp) 247 1.1 briggs { 248 1.1 briggs struct mc_softc *sc = ifp->if_softc; 249 1.25 chs struct mbuf *m; 250 1.1 briggs 251 1.58 thorpej if ((ifp->if_flags & IFF_RUNNING) == 0) 252 1.1 briggs return; 253 1.1 briggs 254 1.58 thorpej while (!sc->sc_txbusy) { 255 1.1 briggs IF_DEQUEUE(&ifp->if_snd, m); 256 1.1 briggs if (m == 0) 257 1.1 briggs return; 258 1.1 briggs 259 1.1 briggs /* 260 1.1 briggs * If bpf is listening on this interface, let it 261 1.1 briggs * see the packet before we commit it to the wire. 262 1.1 briggs */ 263 1.47 msaitoh bpf_mtap(ifp, m, BPF_D_OUT); 264 1.1 briggs 265 1.1 briggs /* 266 1.1 briggs * Copy the mbuf chain into the transmit buffer. 267 1.1 briggs */ 268 1.58 thorpej sc->sc_txbusy = true; 269 1.1 briggs maceput(sc, m); 270 1.1 briggs 271 1.53 thorpej if_statinc(ifp, if_opackets); /* # of pkts */ 272 1.1 briggs } 273 1.1 briggs } 274 1.1 briggs 275 1.1 briggs /* 276 1.1 briggs * reset and restart the MACE. Called in case of fatal 277 1.1 briggs * hardware/software errors. 278 1.1 briggs */ 279 1.1 briggs hide void 280 1.25 chs mcreset(struct mc_softc *sc) 281 1.1 briggs { 282 1.1 briggs mcstop(sc); 283 1.1 briggs mcinit(sc); 284 1.1 briggs } 285 1.1 briggs 286 1.1 briggs hide int 287 1.25 chs mcinit(struct mc_softc *sc) 288 1.1 briggs { 289 1.1 briggs int s; 290 1.50 msaitoh uint8_t maccc, ladrf[8]; 291 1.1 briggs 292 1.1 briggs if (sc->sc_if.if_flags & IFF_RUNNING) 293 1.1 briggs /* already running */ 294 1.50 msaitoh return 0; 295 1.1 briggs 296 1.1 briggs s = splnet(); 297 1.1 briggs 298 1.1 briggs NIC_PUT(sc, MACE_BIUCC, sc->sc_biucc); 299 1.1 briggs NIC_PUT(sc, MACE_FIFOCC, sc->sc_fifocc); 300 1.1 briggs NIC_PUT(sc, MACE_IMR, ~0); /* disable all interrupts */ 301 1.1 briggs NIC_PUT(sc, MACE_PLSCC, sc->sc_plscc); 302 1.1 briggs 303 1.1 briggs NIC_PUT(sc, MACE_UTR, RTRD); /* disable reserved test registers */ 304 1.1 briggs 305 1.1 briggs /* set MAC address */ 306 1.1 briggs NIC_PUT(sc, MACE_IAC, ADDRCHG); 307 1.1 briggs while (NIC_GET(sc, MACE_IAC) & ADDRCHG) 308 1.1 briggs ; 309 1.1 briggs NIC_PUT(sc, MACE_IAC, PHYADDR); 310 1.1 briggs bus_space_write_multi_1(sc->sc_regt, sc->sc_regh, MACE_REG(MACE_PADR), 311 1.1 briggs sc->sc_enaddr, ETHER_ADDR_LEN); 312 1.1 briggs 313 1.1 briggs /* set logical address filter */ 314 1.1 briggs mace_calcladrf(&sc->sc_ethercom, ladrf); 315 1.1 briggs 316 1.1 briggs NIC_PUT(sc, MACE_IAC, ADDRCHG); 317 1.1 briggs while (NIC_GET(sc, MACE_IAC) & ADDRCHG) 318 1.1 briggs ; 319 1.1 briggs NIC_PUT(sc, MACE_IAC, LOGADDR); 320 1.1 briggs bus_space_write_multi_1(sc->sc_regt, sc->sc_regh, MACE_REG(MACE_LADRF), 321 1.1 briggs ladrf, 8); 322 1.1 briggs 323 1.1 briggs NIC_PUT(sc, MACE_XMTFC, APADXMT); 324 1.1 briggs /* 325 1.1 briggs * No need to autostrip padding on receive... Ethernet frames 326 1.1 briggs * don't have a length field, unlike 802.3 frames, so the MACE 327 1.1 briggs * can't figure out the length of the packet anyways. 328 1.1 briggs */ 329 1.1 briggs NIC_PUT(sc, MACE_RCVFC, 0); 330 1.1 briggs 331 1.1 briggs maccc = ENXMT | ENRCV; 332 1.1 briggs if (sc->sc_if.if_flags & IFF_PROMISC) 333 1.1 briggs maccc |= PROM; 334 1.1 briggs 335 1.1 briggs NIC_PUT(sc, MACE_MACCC, maccc); 336 1.1 briggs 337 1.1 briggs if (sc->sc_bus_init) 338 1.1 briggs (*sc->sc_bus_init)(sc); 339 1.1 briggs 340 1.1 briggs /* 341 1.1 briggs * Enable all interrupts except receive, since we use the DMA 342 1.1 briggs * completion interrupt for that. 343 1.1 briggs */ 344 1.1 briggs NIC_PUT(sc, MACE_IMR, RCVINTM); 345 1.1 briggs 346 1.1 briggs /* flag interface as "running" */ 347 1.1 briggs sc->sc_if.if_flags |= IFF_RUNNING; 348 1.58 thorpej sc->sc_txbusy = false; 349 1.1 briggs 350 1.1 briggs splx(s); 351 1.50 msaitoh return 0; 352 1.1 briggs } 353 1.1 briggs 354 1.1 briggs /* 355 1.1 briggs * close down an interface and free its buffers 356 1.1 briggs * Called on final close of device, or if mcinit() fails 357 1.1 briggs * part way through. 358 1.1 briggs */ 359 1.1 briggs hide int 360 1.25 chs mcstop(struct mc_softc *sc) 361 1.1 briggs { 362 1.25 chs int s; 363 1.50 msaitoh 364 1.25 chs s = splnet(); 365 1.1 briggs 366 1.1 briggs NIC_PUT(sc, MACE_BIUCC, SWRST); 367 1.1 briggs DELAY(100); 368 1.1 briggs 369 1.1 briggs sc->sc_if.if_timer = 0; 370 1.21 bjh21 sc->sc_if.if_flags &= ~IFF_RUNNING; 371 1.1 briggs 372 1.1 briggs splx(s); 373 1.50 msaitoh return 0; 374 1.1 briggs } 375 1.1 briggs 376 1.1 briggs /* 377 1.1 briggs * Called if any Tx packets remain unsent after 5 seconds, 378 1.1 briggs * In all cases we just reset the chip, and any retransmission 379 1.1 briggs * will be handled by higher level protocol timeouts. 380 1.1 briggs */ 381 1.1 briggs hide void 382 1.25 chs mcwatchdog(struct ifnet *ifp) 383 1.1 briggs { 384 1.1 briggs struct mc_softc *sc = ifp->if_softc; 385 1.1 briggs 386 1.1 briggs printf("mcwatchdog: resetting chip\n"); 387 1.1 briggs mcreset(sc); 388 1.1 briggs } 389 1.1 briggs 390 1.1 briggs /* 391 1.1 briggs * stuff packet into MACE (at splnet) 392 1.1 briggs */ 393 1.1 briggs integrate u_int 394 1.25 chs maceput(struct mc_softc *sc, struct mbuf *m) 395 1.1 briggs { 396 1.1 briggs struct mbuf *n; 397 1.1 briggs u_int len, totlen = 0; 398 1.1 briggs u_char *buff; 399 1.1 briggs 400 1.31 he buff = (u_char*)sc->sc_txbuf + (sc->sc_txset == 0 ? 0 : 0x800); 401 1.1 briggs 402 1.1 briggs for (; m; m = n) { 403 1.1 briggs u_char *data = mtod(m, u_char *); 404 1.1 briggs len = m->m_len; 405 1.1 briggs totlen += len; 406 1.25 chs memcpy(buff, data, len); 407 1.1 briggs buff += len; 408 1.43 christos n = m_free(m); 409 1.1 briggs } 410 1.1 briggs 411 1.20 thorpej if (totlen > PAGE_SIZE) 412 1.39 chs panic("%s: maceput: packet overflow", device_xname(sc->sc_dev)); 413 1.1 briggs 414 1.1 briggs #if 0 415 1.1 briggs if (totlen < ETHERMIN + sizeof(struct ether_header)) { 416 1.1 briggs int pad = ETHERMIN + sizeof(struct ether_header) - totlen; 417 1.25 chs memset(sc->sc_txbuf + totlen, 0, pad); 418 1.1 briggs totlen = ETHERMIN + sizeof(struct ether_header); 419 1.1 briggs } 420 1.1 briggs #endif 421 1.1 briggs 422 1.1 briggs (*sc->sc_putpacket)(sc, totlen); 423 1.1 briggs 424 1.1 briggs sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */ 425 1.50 msaitoh return totlen; 426 1.1 briggs } 427 1.1 briggs 428 1.1 briggs void 429 1.25 chs mcintr(void *arg) 430 1.1 briggs { 431 1.1 briggs struct mc_softc *sc = arg; 432 1.50 msaitoh uint8_t ir; 433 1.1 briggs 434 1.1 briggs ir = NIC_GET(sc, MACE_IR) & ~NIC_GET(sc, MACE_IMR); 435 1.1 briggs if (ir & JAB) { 436 1.1 briggs #ifdef MCDEBUG 437 1.39 chs printf("%s: jabber error\n", device_xname(sc->sc_dev)); 438 1.1 briggs #endif 439 1.53 thorpej if_statinc(&sc->sc_if, if_oerrors); 440 1.1 briggs } 441 1.1 briggs 442 1.1 briggs if (ir & BABL) { 443 1.1 briggs #ifdef MCDEBUG 444 1.39 chs printf("%s: babble\n", device_xname(sc->sc_dev)); 445 1.1 briggs #endif 446 1.53 thorpej if_statinc(&sc->sc_if, if_oerrors); 447 1.1 briggs } 448 1.1 briggs 449 1.1 briggs if (ir & CERR) { 450 1.14 scottr #ifdef MCDEBUG 451 1.39 chs printf("%s: collision error\n", device_xname(sc->sc_dev)); 452 1.14 scottr #endif 453 1.53 thorpej if_statinc(&sc->sc_if, if_collisions); 454 1.1 briggs } 455 1.1 briggs 456 1.1 briggs /* 457 1.1 briggs * Pretend we have carrier; if we don't this will be cleared 458 1.1 briggs * shortly. 459 1.1 briggs */ 460 1.56 roy const int ocarrier = sc->sc_havecarrier; 461 1.1 briggs sc->sc_havecarrier = 1; 462 1.1 briggs 463 1.1 briggs if (ir & XMTINT) 464 1.1 briggs mc_tint(sc); 465 1.1 briggs 466 1.1 briggs if (ir & RCVINT) 467 1.1 briggs mc_rint(sc); 468 1.56 roy 469 1.56 roy if (sc->sc_havecarrier != ocarrier) 470 1.56 roy if_link_state_change(&sc->sc_if, 471 1.56 roy sc->sc_havecarrier ? LINK_STATE_UP : LINK_STATE_DOWN); 472 1.1 briggs } 473 1.1 briggs 474 1.1 briggs integrate void 475 1.25 chs mc_tint(struct mc_softc *sc) 476 1.1 briggs { 477 1.50 msaitoh uint8_t /* xmtrc,*/ xmtfs; 478 1.1 briggs 479 1.40 martin /* xmtrc = */ NIC_GET(sc, MACE_XMTRC); 480 1.1 briggs xmtfs = NIC_GET(sc, MACE_XMTFS); 481 1.1 briggs 482 1.1 briggs if ((xmtfs & XMTSV) == 0) 483 1.1 briggs return; 484 1.1 briggs 485 1.1 briggs if (xmtfs & UFLO) { 486 1.39 chs printf("%s: underflow\n", device_xname(sc->sc_dev)); 487 1.1 briggs mcreset(sc); 488 1.1 briggs return; 489 1.1 briggs } 490 1.1 briggs 491 1.53 thorpej net_stat_ref_t nsr = IF_STAT_GETREF(&sc->sc_if); 492 1.53 thorpej 493 1.1 briggs if (xmtfs & LCOL) { 494 1.39 chs printf("%s: late collision\n", device_xname(sc->sc_dev)); 495 1.59 riastrad if_statinc_ref(&sc->sc_if, nsr, if_oerrors); 496 1.59 riastrad if_statinc_ref(&sc->sc_if, nsr, if_collisions); 497 1.1 briggs } 498 1.1 briggs 499 1.1 briggs if (xmtfs & MORE) 500 1.1 briggs /* Real number is unknown. */ 501 1.59 riastrad if_statadd_ref(&sc->sc_if, nsr, if_collisions, 2); 502 1.1 briggs else if (xmtfs & ONE) 503 1.59 riastrad if_statinc_ref(&sc->sc_if, nsr, if_collisions); 504 1.1 briggs else if (xmtfs & RTRY) { 505 1.39 chs printf("%s: excessive collisions\n", device_xname(sc->sc_dev)); 506 1.59 riastrad if_statadd_ref(&sc->sc_if, nsr, if_collisions, 16); 507 1.59 riastrad if_statinc_ref(&sc->sc_if, nsr, if_oerrors); 508 1.1 briggs } 509 1.1 briggs 510 1.1 briggs if (xmtfs & LCAR) { 511 1.1 briggs sc->sc_havecarrier = 0; 512 1.39 chs printf("%s: lost carrier\n", device_xname(sc->sc_dev)); 513 1.59 riastrad if_statinc_ref(&sc->sc_if, nsr, if_oerrors); 514 1.1 briggs } 515 1.1 briggs 516 1.53 thorpej IF_STAT_PUTREF(&sc->sc_if); 517 1.53 thorpej 518 1.58 thorpej sc->sc_txbusy = false; 519 1.1 briggs sc->sc_if.if_timer = 0; 520 1.45 nonaka if_schedule_deferred_start(&sc->sc_if); 521 1.57 rin 522 1.57 rin rnd_add_uint32(&sc->rnd_source, xmtfs); 523 1.1 briggs } 524 1.1 briggs 525 1.5 scottr void 526 1.25 chs mc_rint(struct mc_softc *sc) 527 1.1 briggs { 528 1.1 briggs #define rxf sc->sc_rxframe 529 1.1 briggs u_int len; 530 1.1 briggs 531 1.1 briggs len = (rxf.rx_rcvcnt | ((rxf.rx_rcvsts & 0xf) << 8)) - 4; 532 1.1 briggs 533 1.1 briggs #ifdef MCDEBUG 534 1.1 briggs if (rxf.rx_rcvsts & 0xf0) 535 1.1 briggs printf("%s: rcvcnt %02x rcvsts %02x rntpc 0x%02x rcvcc 0x%02x\n", 536 1.39 chs device_xname(sc->sc_dev), rxf.rx_rcvcnt, rxf.rx_rcvsts, 537 1.1 briggs rxf.rx_rntpc, rxf.rx_rcvcc); 538 1.1 briggs #endif 539 1.1 briggs 540 1.1 briggs if (rxf.rx_rcvsts & OFLO) { 541 1.39 chs printf("%s: receive FIFO overflow\n", device_xname(sc->sc_dev)); 542 1.53 thorpej if_statinc(&sc->sc_if, if_ierrors); 543 1.1 briggs return; 544 1.1 briggs } 545 1.1 briggs 546 1.1 briggs if (rxf.rx_rcvsts & CLSN) 547 1.53 thorpej if_statinc(&sc->sc_if, if_collisions); 548 1.1 briggs 549 1.1 briggs if (rxf.rx_rcvsts & FRAM) { 550 1.1 briggs #ifdef MCDEBUG 551 1.39 chs printf("%s: framing error\n", device_xname(sc->sc_dev)); 552 1.1 briggs #endif 553 1.53 thorpej if_statinc(&sc->sc_if, if_ierrors); 554 1.1 briggs return; 555 1.1 briggs } 556 1.1 briggs 557 1.1 briggs if (rxf.rx_rcvsts & FCS) { 558 1.1 briggs #ifdef MCDEBUG 559 1.39 chs printf("%s: frame control checksum error\n", device_xname(sc->sc_dev)); 560 1.1 briggs #endif 561 1.53 thorpej if_statinc(&sc->sc_if, if_ierrors); 562 1.1 briggs return; 563 1.1 briggs } 564 1.1 briggs 565 1.1 briggs mace_read(sc, rxf.rx_frame, len); 566 1.57 rin 567 1.57 rin rnd_add_uint32(&sc->rnd_source, rxf.rx_rcvsts); 568 1.1 briggs #undef rxf 569 1.1 briggs } 570 1.1 briggs 571 1.1 briggs integrate void 572 1.30 christos mace_read(struct mc_softc *sc, void *pkt, int len) 573 1.1 briggs { 574 1.1 briggs struct ifnet *ifp = &sc->sc_if; 575 1.1 briggs struct mbuf *m; 576 1.1 briggs 577 1.1 briggs if (len <= sizeof(struct ether_header) || 578 1.1 briggs len > ETHERMTU + sizeof(struct ether_header)) { 579 1.1 briggs #ifdef MCDEBUG 580 1.1 briggs printf("%s: invalid packet size %d; dropping\n", 581 1.39 chs device_xname(sc->sc_dev), len); 582 1.1 briggs #endif 583 1.53 thorpej if_statinc(ifp, if_ierrors); 584 1.1 briggs return; 585 1.1 briggs } 586 1.1 briggs 587 1.1 briggs m = mace_get(sc, pkt, len); 588 1.1 briggs if (m == NULL) { 589 1.53 thorpej if_statinc(ifp, if_ierrors); 590 1.1 briggs return; 591 1.1 briggs } 592 1.1 briggs 593 1.13 thorpej /* Pass the packet up. */ 594 1.41 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 595 1.1 briggs } 596 1.1 briggs 597 1.1 briggs /* 598 1.1 briggs * Pull data off an interface. 599 1.1 briggs * Len is length of data, with local net header stripped. 600 1.1 briggs * We copy the data into mbufs. When full cluster sized units are present 601 1.1 briggs * we copy into clusters. 602 1.1 briggs */ 603 1.1 briggs integrate struct mbuf * 604 1.30 christos mace_get(struct mc_softc *sc, void *pkt, int totlen) 605 1.1 briggs { 606 1.25 chs struct mbuf *m; 607 1.1 briggs struct mbuf *top, **mp; 608 1.1 briggs int len; 609 1.1 briggs 610 1.1 briggs MGETHDR(m, M_DONTWAIT, MT_DATA); 611 1.1 briggs if (m == 0) 612 1.50 msaitoh return 0; 613 1.42 ozaki m_set_rcvif(m, &sc->sc_if); 614 1.1 briggs m->m_pkthdr.len = totlen; 615 1.1 briggs len = MHLEN; 616 1.1 briggs top = 0; 617 1.1 briggs mp = ⊤ 618 1.1 briggs 619 1.1 briggs while (totlen > 0) { 620 1.1 briggs if (top) { 621 1.1 briggs MGET(m, M_DONTWAIT, MT_DATA); 622 1.1 briggs if (m == 0) { 623 1.1 briggs m_freem(top); 624 1.1 briggs return 0; 625 1.1 briggs } 626 1.1 briggs len = MLEN; 627 1.1 briggs } 628 1.1 briggs if (totlen >= MINCLSIZE) { 629 1.1 briggs MCLGET(m, M_DONTWAIT); 630 1.1 briggs if ((m->m_flags & M_EXT) == 0) { 631 1.1 briggs m_free(m); 632 1.1 briggs m_freem(top); 633 1.1 briggs return 0; 634 1.1 briggs } 635 1.1 briggs len = MCLBYTES; 636 1.1 briggs } 637 1.48 riastrad m->m_len = len = uimin(totlen, len); 638 1.30 christos memcpy(mtod(m, void *), pkt, len); 639 1.31 he pkt = (char*)pkt + len; 640 1.1 briggs totlen -= len; 641 1.1 briggs *mp = m; 642 1.1 briggs mp = &m->m_next; 643 1.1 briggs } 644 1.1 briggs 645 1.50 msaitoh return top; 646 1.1 briggs } 647 1.1 briggs 648 1.1 briggs /* 649 1.1 briggs * Go through the list of multicast addresses and calculate the logical 650 1.1 briggs * address filter. 651 1.1 briggs */ 652 1.1 briggs void 653 1.50 msaitoh mace_calcladrf(struct ethercom *ec, uint8_t *af) 654 1.1 briggs { 655 1.50 msaitoh struct ifnet *ifp = &ec->ec_if; 656 1.1 briggs struct ether_multi *enm; 657 1.25 chs u_char *cp; 658 1.50 msaitoh uint32_t crc; 659 1.50 msaitoh static const uint32_t crctab[] = { 660 1.6 mycroft 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 661 1.6 mycroft 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 662 1.6 mycroft 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 663 1.6 mycroft 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 664 1.6 mycroft }; 665 1.25 chs int len; 666 1.1 briggs struct ether_multistep step; 667 1.1 briggs 668 1.1 briggs /* 669 1.1 briggs * Set up multicast address filter by passing all multicast addresses 670 1.1 briggs * through a crc generator, and then using the high order 6 bits as an 671 1.1 briggs * index into the 64 bit logical address filter. The high order bit 672 1.1 briggs * selects the word, while the rest of the bits select the bit within 673 1.1 briggs * the word. 674 1.1 briggs */ 675 1.1 briggs 676 1.50 msaitoh *((uint32_t *)af) = *((uint32_t *)af + 1) = 0; 677 1.51 msaitoh ETHER_LOCK(ec); 678 1.50 msaitoh ETHER_FIRST_MULTI(step, ec, enm); 679 1.1 briggs while (enm != NULL) { 680 1.1 briggs if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) { 681 1.1 briggs /* 682 1.1 briggs * We must listen to a range of multicast addresses. 683 1.1 briggs * For now, just accept all multicasts, rather than 684 1.1 briggs * trying to set only those filter bits needed to match 685 1.1 briggs * the range. (At this time, the only use of address 686 1.1 briggs * ranges is for IP multicast routing, for which the 687 1.1 briggs * range is big enough to require all bits set.) 688 1.1 briggs */ 689 1.51 msaitoh ETHER_UNLOCK(ec); 690 1.1 briggs goto allmulti; 691 1.1 briggs } 692 1.1 briggs 693 1.1 briggs cp = enm->enm_addrlo; 694 1.1 briggs crc = 0xffffffff; 695 1.1 briggs for (len = sizeof(enm->enm_addrlo); --len >= 0;) { 696 1.6 mycroft crc ^= *cp++; 697 1.6 mycroft crc = (crc >> 4) ^ crctab[crc & 0xf]; 698 1.6 mycroft crc = (crc >> 4) ^ crctab[crc & 0xf]; 699 1.1 briggs } 700 1.1 briggs /* Just want the 6 most significant bits. */ 701 1.1 briggs crc >>= 26; 702 1.1 briggs 703 1.1 briggs /* Set the corresponding bit in the filter. */ 704 1.1 briggs af[crc >> 3] |= 1 << (crc & 7); 705 1.1 briggs 706 1.1 briggs ETHER_NEXT_MULTI(step, enm); 707 1.1 briggs } 708 1.51 msaitoh ETHER_UNLOCK(ec); 709 1.1 briggs ifp->if_flags &= ~IFF_ALLMULTI; 710 1.1 briggs return; 711 1.1 briggs 712 1.1 briggs allmulti: 713 1.1 briggs ifp->if_flags |= IFF_ALLMULTI; 714 1.50 msaitoh *((uint32_t *)af) = *((uint32_t *)af + 1) = 0xffffffff; 715 1.1 briggs } 716 1.1 briggs 717 1.1 briggs static u_char bbr4[] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}; 718 1.1 briggs #define bbr(v) ((bbr4[(v)&0xf] << 4) | bbr4[((v)>>4) & 0xf]) 719 1.1 briggs 720 1.1 briggs u_char 721 1.25 chs mc_get_enaddr(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, 722 1.25 chs u_char *dst) 723 1.1 briggs { 724 1.1 briggs int i; 725 1.1 briggs u_char b, csum; 726 1.1 briggs 727 1.1 briggs /* 728 1.1 briggs * The XOR of the 8 bytes of the ROM must be 0xff for it to be 729 1.1 briggs * valid 730 1.1 briggs */ 731 1.1 briggs for (i = 0, csum = 0; i < 8; i++) { 732 1.1 briggs b = bus_space_read_1(t, h, o+16*i); 733 1.1 briggs if (i < ETHER_ADDR_LEN) 734 1.1 briggs dst[i] = bbr(b); 735 1.1 briggs csum ^= b; 736 1.1 briggs } 737 1.1 briggs 738 1.1 briggs return csum; 739 1.1 briggs } 740