1 1.56 rin /* $NetBSD: if_sn.c,v 1.56 2024/07/05 04:31:49 rin Exp $ */ 2 1.1 tsubai 3 1.1 tsubai /* 4 1.1 tsubai * National Semiconductor DP8393X SONIC Driver 5 1.1 tsubai * Copyright (c) 1991 Algorithmics Ltd (http://www.algor.co.uk) 6 1.1 tsubai * You may use, copy, and modify this program so long as you retain the 7 1.1 tsubai * copyright line. 8 1.1 tsubai * 9 1.1 tsubai * This driver has been substantially modified since Algorithmics donated 10 1.1 tsubai * it. 11 1.1 tsubai * 12 1.1 tsubai * Denton Gentry <denny1 (at) home.com> 13 1.1 tsubai * and also 14 1.1 tsubai * Yanagisawa Takeshi <yanagisw (at) aa.ap.titech.ac.jp> 15 1.1 tsubai * did the work to get this running on the Macintosh. 16 1.1 tsubai */ 17 1.14 lukem 18 1.14 lukem #include <sys/cdefs.h> 19 1.56 rin __KERNEL_RCSID(0, "$NetBSD: if_sn.c,v 1.56 2024/07/05 04:31:49 rin Exp $"); 20 1.1 tsubai 21 1.1 tsubai #include "opt_inet.h" 22 1.1 tsubai 23 1.1 tsubai #include <sys/param.h> 24 1.1 tsubai #include <sys/systm.h> 25 1.1 tsubai #include <sys/mbuf.h> 26 1.1 tsubai #include <sys/buf.h> 27 1.1 tsubai #include <sys/protosw.h> 28 1.1 tsubai #include <sys/socket.h> 29 1.1 tsubai #include <sys/syslog.h> 30 1.1 tsubai #include <sys/ioctl.h> 31 1.1 tsubai #include <sys/errno.h> 32 1.1 tsubai #include <sys/device.h> 33 1.1 tsubai 34 1.1 tsubai #include <net/if.h> 35 1.1 tsubai #include <net/if_dl.h> 36 1.1 tsubai #include <net/if_ether.h> 37 1.40 msaitoh #include <net/bpf.h> 38 1.1 tsubai 39 1.1 tsubai #ifdef INET 40 1.1 tsubai #include <netinet/in.h> 41 1.1 tsubai #include <netinet/in_systm.h> 42 1.1 tsubai #include <netinet/in_var.h> 43 1.1 tsubai #include <netinet/ip.h> 44 1.1 tsubai #include <netinet/if_inarp.h> 45 1.1 tsubai #endif 46 1.1 tsubai 47 1.4 mrg #include <uvm/uvm_extern.h> 48 1.1 tsubai 49 1.1 tsubai #include <machine/cpu.h> 50 1.24 tsutsui #include <newsmips/apbus/apbusvar.h> 51 1.1 tsubai #include <newsmips/apbus/if_snreg.h> 52 1.1 tsubai #include <newsmips/apbus/if_snvar.h> 53 1.1 tsubai 54 1.55 andvar /* #define SNDEBUG */ 55 1.1 tsubai 56 1.55 andvar #ifdef SNDEBUG 57 1.1 tsubai # define DPRINTF printf 58 1.1 tsubai #else 59 1.1 tsubai # define DPRINTF while (0) printf 60 1.1 tsubai #endif 61 1.1 tsubai 62 1.16 tsutsui static void snwatchdog(struct ifnet *); 63 1.16 tsutsui static int sninit(struct sn_softc *sc); 64 1.16 tsutsui static int snstop(struct sn_softc *sc); 65 1.22 christos static int snioctl(struct ifnet *ifp, u_long cmd, void *data); 66 1.16 tsutsui static void snstart(struct ifnet *ifp); 67 1.16 tsutsui static void snreset(struct sn_softc *sc); 68 1.16 tsutsui 69 1.16 tsutsui static void caminitialise(struct sn_softc *); 70 1.29 he static void camentry(struct sn_softc *, int, const u_char *ea); 71 1.16 tsutsui static void camprogram(struct sn_softc *); 72 1.16 tsutsui static void initialise_tda(struct sn_softc *); 73 1.16 tsutsui static void initialise_rda(struct sn_softc *); 74 1.16 tsutsui static void initialise_rra(struct sn_softc *); 75 1.1 tsubai #ifdef SNDEBUG 76 1.16 tsutsui static void camdump(struct sn_softc *sc); 77 1.1 tsubai #endif 78 1.1 tsubai 79 1.16 tsutsui static void sonictxint(struct sn_softc *); 80 1.16 tsutsui static void sonicrxint(struct sn_softc *); 81 1.1 tsubai 82 1.19 perry static inline u_int sonicput(struct sn_softc *sc, struct mbuf *m0, 83 1.16 tsutsui int mtd_next); 84 1.22 christos static inline int sonic_read(struct sn_softc *, void *, int); 85 1.22 christos static inline struct mbuf *sonic_get(struct sn_softc *, void *, int); 86 1.1 tsubai 87 1.1 tsubai /* 88 1.1 tsubai * SONIC buffers need to be aligned 16 or 32 bit aligned. 89 1.1 tsubai * These macros calculate and verify alignment. 90 1.1 tsubai */ 91 1.21 he #define SOALIGN(m, array) (m ? (roundup((int)array, 4)) : \ 92 1.21 he (roundup((int)array, 2))) 93 1.1 tsubai 94 1.1 tsubai #define LOWER(x) ((unsigned)(x) & 0xffff) 95 1.1 tsubai #define UPPER(x) ((unsigned)(x) >> 16) 96 1.1 tsubai 97 1.1 tsubai /* 98 1.1 tsubai * Interface exists: make available by filling in network interface 99 1.1 tsubai * record. System will initialize the interface when it is ready 100 1.1 tsubai * to accept packets. 101 1.1 tsubai */ 102 1.1 tsubai int 103 1.16 tsutsui snsetup(struct sn_softc *sc, uint8_t *lladdr) 104 1.1 tsubai { 105 1.1 tsubai struct ifnet *ifp = &sc->sc_if; 106 1.30 tsutsui uint8_t *p; 107 1.30 tsutsui uint8_t *pp; 108 1.1 tsubai int i; 109 1.1 tsubai 110 1.43 tsutsui if (sc->memory == NULL) { 111 1.30 tsutsui aprint_error_dev(sc->sc_dev, 112 1.30 tsutsui "memory allocation for descriptors failed\n"); 113 1.16 tsutsui return 1; 114 1.1 tsubai } 115 1.1 tsubai 116 1.1 tsubai /* 117 1.1 tsubai * Put the pup in reset mode (sninit() will fix it later), 118 1.1 tsubai * stop the timer, disable all interrupts and clear any interrupts. 119 1.1 tsubai */ 120 1.1 tsubai NIC_PUT(sc, SNR_CR, CR_STP); 121 1.1 tsubai wbflush(); 122 1.1 tsubai NIC_PUT(sc, SNR_CR, CR_RST); 123 1.1 tsubai wbflush(); 124 1.1 tsubai NIC_PUT(sc, SNR_IMR, 0); 125 1.1 tsubai wbflush(); 126 1.1 tsubai NIC_PUT(sc, SNR_ISR, ISR_ALL); 127 1.1 tsubai wbflush(); 128 1.1 tsubai 129 1.1 tsubai /* 130 1.1 tsubai * because the SONIC is basically 16bit device it 'concatenates' 131 1.1 tsubai * a higher buffer address to a 16 bit offset--this will cause wrap 132 1.1 tsubai * around problems near the end of 64k !! 133 1.1 tsubai */ 134 1.43 tsutsui p = sc->memory; 135 1.30 tsutsui pp = (uint8_t *)roundup((int)p, PAGE_SIZE); 136 1.1 tsubai p = pp; 137 1.1 tsubai 138 1.1 tsubai for (i = 0; i < NRRA; i++) { 139 1.1 tsubai sc->p_rra[i] = (void *)p; 140 1.43 tsutsui sc->v_rra[i] = SONIC_GETDMA(sc, p); 141 1.1 tsubai p += RXRSRC_SIZE(sc); 142 1.1 tsubai } 143 1.43 tsutsui sc->v_rea = SONIC_GETDMA(sc, p); 144 1.1 tsubai 145 1.30 tsutsui p = (uint8_t *)SOALIGN(sc, p); 146 1.1 tsubai 147 1.1 tsubai sc->p_cda = (void *)(p); 148 1.43 tsutsui sc->v_cda = SONIC_GETDMA(sc, p); 149 1.1 tsubai p += CDA_SIZE(sc); 150 1.1 tsubai 151 1.30 tsutsui p = (uint8_t *)SOALIGN(sc, p); 152 1.1 tsubai 153 1.1 tsubai for (i = 0; i < NTDA; i++) { 154 1.1 tsubai struct mtd *mtdp = &sc->mtda[i]; 155 1.1 tsubai mtdp->mtd_txp = (void *)p; 156 1.43 tsutsui mtdp->mtd_vtxp = SONIC_GETDMA(sc, p); 157 1.1 tsubai p += TXP_SIZE(sc); 158 1.1 tsubai } 159 1.1 tsubai 160 1.30 tsutsui p = (uint8_t *)SOALIGN(sc, p); 161 1.1 tsubai 162 1.12 thorpej if ((p - pp) > PAGE_SIZE) { 163 1.30 tsutsui aprint_error_dev(sc->sc_dev, "sizeof RRA (%ld) + CDA (%ld) +" 164 1.12 thorpej "TDA (%ld) > PAGE_SIZE (%d). Punt!\n", 165 1.1 tsubai (ulong)sc->p_cda - (ulong)sc->p_rra[0], 166 1.1 tsubai (ulong)sc->mtda[0].mtd_txp - (ulong)sc->p_cda, 167 1.1 tsubai (ulong)p - (ulong)sc->mtda[0].mtd_txp, 168 1.12 thorpej PAGE_SIZE); 169 1.16 tsutsui return 1; 170 1.1 tsubai } 171 1.1 tsubai 172 1.12 thorpej p = pp + PAGE_SIZE; 173 1.1 tsubai pp = p; 174 1.1 tsubai 175 1.12 thorpej sc->sc_nrda = PAGE_SIZE / RXPKT_SIZE(sc); 176 1.22 christos sc->p_rda = (void *)p; 177 1.43 tsutsui sc->v_rda = SONIC_GETDMA(sc, p); 178 1.1 tsubai 179 1.12 thorpej p = pp + PAGE_SIZE; 180 1.1 tsubai 181 1.1 tsubai for (i = 0; i < NRBA; i++) { 182 1.43 tsutsui sc->rbuf[i] = SONIC_BUFFER(sc, p); 183 1.12 thorpej p += PAGE_SIZE; 184 1.1 tsubai } 185 1.1 tsubai 186 1.1 tsubai pp = p; 187 1.1 tsubai for (i = 0; i < NTDA; i++) { 188 1.1 tsubai struct mtd *mtdp = &sc->mtda[i]; 189 1.1 tsubai 190 1.43 tsutsui mtdp->mtd_buf = SONIC_BUFFER(sc, p); 191 1.43 tsutsui mtdp->mtd_vbuf = SONIC_GETDMA(sc, p); 192 1.1 tsubai p += TXBSIZE; 193 1.1 tsubai } 194 1.1 tsubai 195 1.1 tsubai #ifdef SNDEBUG 196 1.1 tsubai camdump(sc); 197 1.1 tsubai #endif 198 1.30 tsutsui aprint_normal_dev(sc->sc_dev, "Ethernet address %s\n", 199 1.30 tsutsui ether_sprintf(lladdr)); 200 1.1 tsubai 201 1.1 tsubai #ifdef SNDEBUG 202 1.30 tsutsui aprint_debug_dev(sc->sc_dev, "buffers: rra=%p cda=%p rda=%p tda=%p\n", 203 1.53 andvar sc->p_rra[0], sc->p_cda, 204 1.1 tsubai sc->p_rda, sc->mtda[0].mtd_txp); 205 1.1 tsubai #endif 206 1.1 tsubai 207 1.30 tsutsui strcpy(ifp->if_xname, device_xname(sc->sc_dev)); 208 1.1 tsubai ifp->if_softc = sc; 209 1.1 tsubai ifp->if_ioctl = snioctl; 210 1.1 tsubai ifp->if_start = snstart; 211 1.44 msaitoh ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 212 1.1 tsubai ifp->if_watchdog = snwatchdog; 213 1.1 tsubai if_attach(ifp); 214 1.38 nonaka if_deferred_start_init(ifp, NULL); 215 1.1 tsubai ether_ifattach(ifp, lladdr); 216 1.1 tsubai 217 1.16 tsutsui return 0; 218 1.1 tsubai } 219 1.1 tsubai 220 1.1 tsubai static int 221 1.22 christos snioctl(struct ifnet *ifp, u_long cmd, void *data) 222 1.1 tsubai { 223 1.1 tsubai struct ifaddr *ifa; 224 1.1 tsubai struct sn_softc *sc = ifp->if_softc; 225 1.1 tsubai int s = splnet(), err = 0; 226 1.46 msaitoh u_short temp; 227 1.1 tsubai 228 1.1 tsubai switch (cmd) { 229 1.1 tsubai 230 1.31 dyoung case SIOCINITIFADDR: 231 1.1 tsubai ifa = (struct ifaddr *)data; 232 1.1 tsubai ifp->if_flags |= IFF_UP; 233 1.31 dyoung (void)sninit(sc); 234 1.1 tsubai switch (ifa->ifa_addr->sa_family) { 235 1.1 tsubai #ifdef INET 236 1.1 tsubai case AF_INET: 237 1.1 tsubai arp_ifinit(ifp, ifa); 238 1.1 tsubai break; 239 1.1 tsubai #endif 240 1.1 tsubai default: 241 1.1 tsubai break; 242 1.1 tsubai } 243 1.1 tsubai break; 244 1.1 tsubai 245 1.1 tsubai case SIOCSIFFLAGS: 246 1.31 dyoung if ((err = ifioctl_common(ifp, cmd, data)) != 0) 247 1.31 dyoung break; 248 1.1 tsubai if ((ifp->if_flags & IFF_UP) == 0 && 249 1.1 tsubai (ifp->if_flags & IFF_RUNNING) != 0) { 250 1.1 tsubai /* 251 1.1 tsubai * If interface is marked down and it is running, 252 1.1 tsubai * then stop it. 253 1.1 tsubai */ 254 1.1 tsubai snstop(sc); 255 1.1 tsubai ifp->if_flags &= ~IFF_RUNNING; 256 1.1 tsubai } else if ((ifp->if_flags & IFF_UP) != 0 && 257 1.1 tsubai (ifp->if_flags & IFF_RUNNING) == 0) { 258 1.1 tsubai /* 259 1.1 tsubai * If interface is marked up and it is stopped, 260 1.1 tsubai * then start it. 261 1.1 tsubai */ 262 1.1 tsubai (void)sninit(sc); 263 1.1 tsubai } else { 264 1.1 tsubai /* 265 1.1 tsubai * reset the interface to pick up any other changes 266 1.1 tsubai * in flags 267 1.1 tsubai */ 268 1.1 tsubai temp = ifp->if_flags & IFF_UP; 269 1.1 tsubai snreset(sc); 270 1.1 tsubai ifp->if_flags |= temp; 271 1.1 tsubai snstart(ifp); 272 1.1 tsubai } 273 1.1 tsubai break; 274 1.1 tsubai 275 1.1 tsubai case SIOCADDMULTI: 276 1.1 tsubai case SIOCDELMULTI: 277 1.25 dyoung if ((err = ether_ioctl(ifp, cmd, data)) == ENETRESET) { 278 1.1 tsubai /* 279 1.1 tsubai * Multicast list has changed; set the hardware 280 1.1 tsubai * filter accordingly. But remember UP flag! 281 1.1 tsubai */ 282 1.15 thorpej if (ifp->if_flags & IFF_RUNNING) { 283 1.15 thorpej temp = ifp->if_flags & IFF_UP; 284 1.15 thorpej snreset(sc); 285 1.15 thorpej ifp->if_flags |= temp; 286 1.15 thorpej } 287 1.1 tsubai err = 0; 288 1.1 tsubai } 289 1.1 tsubai break; 290 1.1 tsubai default: 291 1.31 dyoung err = ether_ioctl(ifp, cmd, data); 292 1.31 dyoung break; 293 1.1 tsubai } 294 1.1 tsubai splx(s); 295 1.16 tsutsui return err; 296 1.1 tsubai } 297 1.1 tsubai 298 1.1 tsubai /* 299 1.1 tsubai * Encapsulate a packet of type family for the local net. 300 1.1 tsubai */ 301 1.1 tsubai static void 302 1.16 tsutsui snstart(struct ifnet *ifp) 303 1.1 tsubai { 304 1.1 tsubai struct sn_softc *sc = ifp->if_softc; 305 1.1 tsubai struct mbuf *m; 306 1.1 tsubai int mtd_next; 307 1.1 tsubai 308 1.51 thorpej if ((ifp->if_flags & IFF_RUNNING) == 0) 309 1.1 tsubai return; 310 1.1 tsubai 311 1.1 tsubai outloop: 312 1.1 tsubai /* Check for room in the xmit buffer. */ 313 1.1 tsubai if ((mtd_next = (sc->mtd_free + 1)) == NTDA) 314 1.1 tsubai mtd_next = 0; 315 1.1 tsubai 316 1.1 tsubai if (mtd_next == sc->mtd_hw) { 317 1.1 tsubai return; 318 1.1 tsubai } 319 1.1 tsubai 320 1.50 thorpej IF_POLL(&ifp->if_snd, m); 321 1.1 tsubai if (m == 0) 322 1.1 tsubai return; 323 1.1 tsubai 324 1.1 tsubai /* We need the header for m_pkthdr.len. */ 325 1.51 thorpej KASSERT(m->m_flags & M_PKTHDR); 326 1.1 tsubai 327 1.1 tsubai /* 328 1.1 tsubai * If bpf is listening on this interface, let it 329 1.1 tsubai * see the packet before we commit it to the wire. 330 1.1 tsubai */ 331 1.41 msaitoh bpf_mtap(ifp, m, BPF_D_OUT); 332 1.1 tsubai 333 1.1 tsubai /* 334 1.1 tsubai * If there is nothing in the o/p queue, and there is room in 335 1.50 thorpej * the Tx ring, then send the packet directly. Otherwise it 336 1.50 thorpej * stays on the queue. 337 1.1 tsubai */ 338 1.1 tsubai if ((sonicput(sc, m, mtd_next)) == 0) { 339 1.1 tsubai return; 340 1.1 tsubai } 341 1.50 thorpej IF_DEQUEUE(&ifp->if_snd, m); 342 1.1 tsubai 343 1.1 tsubai sc->mtd_prev = sc->mtd_free; 344 1.1 tsubai sc->mtd_free = mtd_next; 345 1.1 tsubai 346 1.47 skrll if_statinc(ifp, if_opackets); /* # of pkts */ 347 1.1 tsubai 348 1.1 tsubai /* Jump back for possibly more punishment. */ 349 1.1 tsubai goto outloop; 350 1.1 tsubai } 351 1.1 tsubai 352 1.1 tsubai /* 353 1.1 tsubai * reset and restart the SONIC. Called in case of fatal 354 1.1 tsubai * hardware/software errors. 355 1.1 tsubai */ 356 1.1 tsubai static void 357 1.16 tsutsui snreset(struct sn_softc *sc) 358 1.1 tsubai { 359 1.16 tsutsui 360 1.1 tsubai snstop(sc); 361 1.1 tsubai sninit(sc); 362 1.1 tsubai } 363 1.1 tsubai 364 1.48 skrll static int 365 1.16 tsutsui sninit(struct sn_softc *sc) 366 1.1 tsubai { 367 1.1 tsubai u_long s_rcr; 368 1.1 tsubai int s; 369 1.1 tsubai 370 1.1 tsubai if (sc->sc_if.if_flags & IFF_RUNNING) 371 1.1 tsubai /* already running */ 372 1.16 tsutsui return 0; 373 1.1 tsubai 374 1.1 tsubai s = splnet(); 375 1.1 tsubai 376 1.8 wiz NIC_PUT(sc, SNR_CR, CR_RST); /* DCR only accessible in reset mode! */ 377 1.1 tsubai 378 1.1 tsubai /* config it */ 379 1.1 tsubai NIC_PUT(sc, SNR_DCR, (sc->snr_dcr | 380 1.1 tsubai (sc->bitmode ? DCR_DW32 : DCR_DW16))); 381 1.1 tsubai NIC_PUT(sc, SNR_DCR2, sc->snr_dcr2); 382 1.1 tsubai 383 1.1 tsubai s_rcr = RCR_BRD | RCR_LBNONE; 384 1.1 tsubai if (sc->sc_if.if_flags & IFF_PROMISC) 385 1.1 tsubai s_rcr |= RCR_PRO; 386 1.1 tsubai if (sc->sc_if.if_flags & IFF_ALLMULTI) 387 1.1 tsubai s_rcr |= RCR_AMC; 388 1.1 tsubai NIC_PUT(sc, SNR_RCR, s_rcr); 389 1.1 tsubai 390 1.1 tsubai #if 0 391 1.1 tsubai NIC_PUT(sc, SNR_IMR, (IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN)); 392 1.1 tsubai #else 393 1.1 tsubai NIC_PUT(sc, SNR_IMR, IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN | 394 1.1 tsubai IMR_BREN | IMR_HBLEN | IMR_RDEEN | IMR_RBEEN | 395 1.1 tsubai IMR_RBAEEN | IMR_RFOEN); 396 1.1 tsubai #endif 397 1.1 tsubai 398 1.1 tsubai /* clear pending interrupts */ 399 1.1 tsubai NIC_PUT(sc, SNR_ISR, ISR_ALL); 400 1.1 tsubai 401 1.1 tsubai /* clear tally counters */ 402 1.1 tsubai NIC_PUT(sc, SNR_CRCT, -1); 403 1.1 tsubai NIC_PUT(sc, SNR_FAET, -1); 404 1.1 tsubai NIC_PUT(sc, SNR_MPT, -1); 405 1.1 tsubai 406 1.1 tsubai initialise_tda(sc); 407 1.1 tsubai initialise_rda(sc); 408 1.1 tsubai initialise_rra(sc); 409 1.1 tsubai 410 1.1 tsubai sn_md_init(sc); /* MD initialization */ 411 1.1 tsubai 412 1.1 tsubai /* enable the chip */ 413 1.1 tsubai NIC_PUT(sc, SNR_CR, 0); 414 1.1 tsubai wbflush(); 415 1.1 tsubai 416 1.1 tsubai /* program the CAM */ 417 1.1 tsubai camprogram(sc); 418 1.1 tsubai 419 1.1 tsubai /* get it to read resource descriptors */ 420 1.1 tsubai NIC_PUT(sc, SNR_CR, CR_RRRA); 421 1.1 tsubai wbflush(); 422 1.1 tsubai while ((NIC_GET(sc, SNR_CR)) & CR_RRRA) 423 1.1 tsubai continue; 424 1.1 tsubai 425 1.1 tsubai /* enable rx */ 426 1.1 tsubai NIC_PUT(sc, SNR_CR, CR_RXEN); 427 1.1 tsubai wbflush(); 428 1.1 tsubai 429 1.1 tsubai /* flag interface as "running" */ 430 1.1 tsubai sc->sc_if.if_flags |= IFF_RUNNING; 431 1.1 tsubai 432 1.1 tsubai splx(s); 433 1.16 tsutsui return 0; 434 1.1 tsubai } 435 1.1 tsubai 436 1.1 tsubai /* 437 1.1 tsubai * close down an interface and free its buffers 438 1.1 tsubai * Called on final close of device, or if sninit() fails 439 1.1 tsubai * part way through. 440 1.1 tsubai */ 441 1.48 skrll static int 442 1.16 tsutsui snstop(struct sn_softc *sc) 443 1.1 tsubai { 444 1.1 tsubai struct mtd *mtd; 445 1.1 tsubai int s = splnet(); 446 1.1 tsubai 447 1.1 tsubai /* stick chip in reset */ 448 1.1 tsubai NIC_PUT(sc, SNR_CR, CR_RST); 449 1.1 tsubai wbflush(); 450 1.1 tsubai 451 1.1 tsubai /* free all receive buffers (currently static so nothing to do) */ 452 1.1 tsubai 453 1.1 tsubai /* free all pending transmit mbufs */ 454 1.1 tsubai while (sc->mtd_hw != sc->mtd_free) { 455 1.1 tsubai mtd = &sc->mtda[sc->mtd_hw]; 456 1.56 rin m_freem(mtd->mtd_mbuf); 457 1.1 tsubai if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0; 458 1.1 tsubai } 459 1.1 tsubai 460 1.1 tsubai sc->sc_if.if_timer = 0; 461 1.1 tsubai sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_UP); 462 1.1 tsubai 463 1.1 tsubai splx(s); 464 1.16 tsutsui return 0; 465 1.1 tsubai } 466 1.1 tsubai 467 1.1 tsubai /* 468 1.1 tsubai * Called if any Tx packets remain unsent after 5 seconds, 469 1.1 tsubai * In all cases we just reset the chip, and any retransmission 470 1.1 tsubai * will be handled by higher level protocol timeouts. 471 1.1 tsubai */ 472 1.1 tsubai static void 473 1.16 tsutsui snwatchdog(struct ifnet *ifp) 474 1.1 tsubai { 475 1.1 tsubai struct sn_softc *sc = ifp->if_softc; 476 1.1 tsubai struct mtd *mtd; 477 1.46 msaitoh u_short temp; 478 1.1 tsubai 479 1.1 tsubai if (sc->mtd_hw != sc->mtd_free) { 480 1.1 tsubai /* something still pending for transmit */ 481 1.1 tsubai mtd = &sc->mtda[sc->mtd_hw]; 482 1.1 tsubai if (SRO(sc->bitmode, mtd->mtd_txp, TXP_STATUS) == 0) 483 1.1 tsubai log(LOG_ERR, "%s: Tx - timeout\n", 484 1.30 tsutsui device_xname(sc->sc_dev)); 485 1.1 tsubai else 486 1.1 tsubai log(LOG_ERR, "%s: Tx - lost interrupt\n", 487 1.30 tsutsui device_xname(sc->sc_dev)); 488 1.1 tsubai temp = ifp->if_flags & IFF_UP; 489 1.1 tsubai snreset(sc); 490 1.1 tsubai ifp->if_flags |= temp; 491 1.1 tsubai } 492 1.1 tsubai } 493 1.1 tsubai 494 1.1 tsubai /* 495 1.1 tsubai * stuff packet into sonic (at splnet) 496 1.1 tsubai */ 497 1.19 perry static inline u_int 498 1.16 tsutsui sonicput(struct sn_softc *sc, struct mbuf *m0, int mtd_next) 499 1.1 tsubai { 500 1.1 tsubai struct mtd *mtdp; 501 1.1 tsubai struct mbuf *m; 502 1.1 tsubai u_char *buff; 503 1.1 tsubai void *txp; 504 1.1 tsubai u_int len = 0; 505 1.1 tsubai u_int totlen = 0; 506 1.1 tsubai 507 1.1 tsubai #ifdef whyonearthwouldyoudothis 508 1.1 tsubai if (NIC_GET(sc, SNR_CR) & CR_TXP) 509 1.16 tsutsui return 0; 510 1.1 tsubai #endif 511 1.1 tsubai 512 1.1 tsubai /* grab the replacement mtd */ 513 1.1 tsubai mtdp = &sc->mtda[sc->mtd_free]; 514 1.1 tsubai 515 1.1 tsubai buff = mtdp->mtd_buf; 516 1.13 tsutsui 517 1.1 tsubai /* this packet goes to mtdnext fill in the TDA */ 518 1.1 tsubai mtdp->mtd_mbuf = m0; 519 1.1 tsubai txp = mtdp->mtd_txp; 520 1.1 tsubai 521 1.1 tsubai /* Write to the config word. Every (NTDA/2)+1 packets we set an intr */ 522 1.1 tsubai if (sc->mtd_pint == 0) { 523 1.1 tsubai sc->mtd_pint = NTDA/2; 524 1.1 tsubai SWO(sc->bitmode, txp, TXP_CONFIG, TCR_PINT); 525 1.1 tsubai } else { 526 1.1 tsubai sc->mtd_pint--; 527 1.1 tsubai SWO(sc->bitmode, txp, TXP_CONFIG, 0); 528 1.1 tsubai } 529 1.1 tsubai 530 1.1 tsubai for (m = m0; m; m = m->m_next) { 531 1.1 tsubai u_char *data = mtod(m, u_char *); 532 1.1 tsubai len = m->m_len; 533 1.1 tsubai totlen += len; 534 1.16 tsutsui memcpy(buff, data, len); 535 1.1 tsubai buff += len; 536 1.1 tsubai } 537 1.1 tsubai if (totlen >= TXBSIZE) { 538 1.30 tsutsui panic("%s: sonicput: packet overflow", 539 1.30 tsutsui device_xname(sc->sc_dev)); 540 1.1 tsubai } 541 1.1 tsubai 542 1.1 tsubai SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRLO, 543 1.1 tsubai LOWER(mtdp->mtd_vbuf)); 544 1.1 tsubai SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRHI, 545 1.1 tsubai UPPER(mtdp->mtd_vbuf)); 546 1.1 tsubai 547 1.1 tsubai if (totlen < ETHERMIN + ETHER_HDR_LEN) { 548 1.1 tsubai int pad = ETHERMIN + ETHER_HDR_LEN - totlen; 549 1.23 he memset((char *)mtdp->mtd_buf + totlen, 0, pad); 550 1.1 tsubai totlen = ETHERMIN + ETHER_HDR_LEN; 551 1.1 tsubai } 552 1.1 tsubai 553 1.1 tsubai SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FSIZE, 554 1.1 tsubai totlen); 555 1.1 tsubai SWO(sc->bitmode, txp, TXP_FRAGCNT, 1); 556 1.1 tsubai SWO(sc->bitmode, txp, TXP_PKTSIZE, totlen); 557 1.1 tsubai 558 1.1 tsubai /* link onto the next mtd that will be used */ 559 1.1 tsubai SWO(sc->bitmode, txp, TXP_FRAGOFF + (1 * TXP_FRAGSIZE) + TXP_FPTRLO, 560 1.1 tsubai LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL); 561 1.1 tsubai 562 1.1 tsubai /* 563 1.1 tsubai * The previous txp.tlink currently contains a pointer to 564 1.1 tsubai * our txp | EOL. Want to clear the EOL, so write our 565 1.1 tsubai * pointer to the previous txp. 566 1.1 tsubai */ 567 1.1 tsubai SWO(sc->bitmode, sc->mtda[sc->mtd_prev].mtd_txp, sc->mtd_tlinko, 568 1.1 tsubai LOWER(mtdp->mtd_vtxp)); 569 1.1 tsubai 570 1.1 tsubai /* make sure chip is running */ 571 1.1 tsubai wbflush(); 572 1.1 tsubai NIC_PUT(sc, SNR_CR, CR_TXP); 573 1.1 tsubai wbflush(); 574 1.1 tsubai sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */ 575 1.1 tsubai 576 1.16 tsutsui return totlen; 577 1.1 tsubai } 578 1.1 tsubai 579 1.1 tsubai /* 580 1.1 tsubai * These are called from sonicioctl() when /etc/ifconfig is run to set 581 1.1 tsubai * the address or switch the i/f on. 582 1.1 tsubai */ 583 1.1 tsubai /* 584 1.1 tsubai * CAM support 585 1.1 tsubai */ 586 1.48 skrll static void 587 1.16 tsutsui caminitialise(struct sn_softc *sc) 588 1.1 tsubai { 589 1.1 tsubai void *p_cda = sc->p_cda; 590 1.1 tsubai int i; 591 1.1 tsubai int camoffset; 592 1.1 tsubai 593 1.1 tsubai for (i = 0; i < MAXCAM; i++) { 594 1.1 tsubai camoffset = i * CDA_CAMDESC; 595 1.1 tsubai SWO(bitmode, p_cda, (camoffset + CDA_CAMEP), i); 596 1.1 tsubai SWO(bitmode, p_cda, (camoffset + CDA_CAMAP2), 0); 597 1.1 tsubai SWO(bitmode, p_cda, (camoffset + CDA_CAMAP1), 0); 598 1.1 tsubai SWO(bitmode, p_cda, (camoffset + CDA_CAMAP0), 0); 599 1.1 tsubai } 600 1.1 tsubai SWO(bitmode, p_cda, CDA_ENABLE, 0); 601 1.1 tsubai } 602 1.1 tsubai 603 1.48 skrll static void 604 1.29 he camentry(struct sn_softc *sc, int entry, const u_char *ea) 605 1.1 tsubai { 606 1.1 tsubai void *p_cda = sc->p_cda; 607 1.1 tsubai int camoffset = entry * CDA_CAMDESC; 608 1.1 tsubai 609 1.1 tsubai SWO(bitmode, p_cda, camoffset + CDA_CAMEP, entry); 610 1.1 tsubai SWO(bitmode, p_cda, camoffset + CDA_CAMAP2, (ea[5] << 8) | ea[4]); 611 1.1 tsubai SWO(bitmode, p_cda, camoffset + CDA_CAMAP1, (ea[3] << 8) | ea[2]); 612 1.1 tsubai SWO(bitmode, p_cda, camoffset + CDA_CAMAP0, (ea[1] << 8) | ea[0]); 613 1.48 skrll SWO(bitmode, p_cda, CDA_ENABLE, 614 1.1 tsubai (SRO(bitmode, p_cda, CDA_ENABLE) | (1 << entry))); 615 1.1 tsubai } 616 1.1 tsubai 617 1.48 skrll static void 618 1.16 tsutsui camprogram(struct sn_softc *sc) 619 1.1 tsubai { 620 1.45 msaitoh struct ethercom *ec = &sc->sc_ethercom; 621 1.1 tsubai struct ether_multistep step; 622 1.1 tsubai struct ether_multi *enm; 623 1.1 tsubai struct ifnet *ifp; 624 1.1 tsubai int timeout; 625 1.1 tsubai int mcount = 0; 626 1.1 tsubai 627 1.1 tsubai caminitialise(sc); 628 1.1 tsubai 629 1.1 tsubai ifp = &sc->sc_if; 630 1.1 tsubai 631 1.1 tsubai /* Always load our own address first. */ 632 1.29 he camentry(sc, mcount, CLLADDR(ifp->if_sadl)); 633 1.1 tsubai mcount++; 634 1.1 tsubai 635 1.1 tsubai /* Assume we won't need allmulti bit. */ 636 1.1 tsubai ifp->if_flags &= ~IFF_ALLMULTI; 637 1.1 tsubai 638 1.1 tsubai /* Loop through multicast addresses */ 639 1.45 msaitoh ETHER_LOCK(ec); 640 1.45 msaitoh ETHER_FIRST_MULTI(step, ec, enm); 641 1.1 tsubai while (enm != NULL) { 642 1.1 tsubai if (mcount == MAXCAM) { 643 1.1 tsubai ifp->if_flags |= IFF_ALLMULTI; 644 1.1 tsubai break; 645 1.1 tsubai } 646 1.1 tsubai 647 1.16 tsutsui if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 648 1.1 tsubai sizeof(enm->enm_addrlo)) != 0) { 649 1.1 tsubai /* 650 1.1 tsubai * SONIC's CAM is programmed with specific 651 1.1 tsubai * addresses. It has no way to specify a range. 652 1.1 tsubai * (Well, thats not exactly true. If the 653 1.1 tsubai * range is small one could program each addr 654 1.9 wiz * within the range as a separate CAM entry) 655 1.1 tsubai */ 656 1.1 tsubai ifp->if_flags |= IFF_ALLMULTI; 657 1.1 tsubai break; 658 1.1 tsubai } 659 1.1 tsubai 660 1.1 tsubai /* program the CAM with the specified entry */ 661 1.1 tsubai camentry(sc, mcount, enm->enm_addrlo); 662 1.1 tsubai mcount++; 663 1.1 tsubai 664 1.1 tsubai ETHER_NEXT_MULTI(step, enm); 665 1.1 tsubai } 666 1.45 msaitoh ETHER_UNLOCK(ec); 667 1.1 tsubai 668 1.1 tsubai NIC_PUT(sc, SNR_CDP, LOWER(sc->v_cda)); 669 1.1 tsubai NIC_PUT(sc, SNR_CDC, MAXCAM); 670 1.1 tsubai NIC_PUT(sc, SNR_CR, CR_LCAM); 671 1.1 tsubai wbflush(); 672 1.1 tsubai 673 1.1 tsubai timeout = 10000; 674 1.1 tsubai while ((NIC_GET(sc, SNR_CR) & CR_LCAM) && timeout--) 675 1.3 tsubai delay(10); 676 1.1 tsubai if (timeout == 0) { 677 1.1 tsubai /* XXX */ 678 1.30 tsutsui panic("%s: CAM initialisation failed", 679 1.30 tsutsui device_xname(sc->sc_dev)); 680 1.1 tsubai } 681 1.1 tsubai timeout = 10000; 682 1.1 tsubai while (((NIC_GET(sc, SNR_ISR) & ISR_LCD) == 0) && timeout--) 683 1.3 tsubai delay(10); 684 1.1 tsubai 685 1.1 tsubai if (NIC_GET(sc, SNR_ISR) & ISR_LCD) 686 1.1 tsubai NIC_PUT(sc, SNR_ISR, ISR_LCD); 687 1.1 tsubai else 688 1.1 tsubai printf("%s: CAM initialisation without interrupt\n", 689 1.30 tsutsui device_xname(sc->sc_dev)); 690 1.1 tsubai } 691 1.1 tsubai 692 1.1 tsubai #ifdef SNDEBUG 693 1.48 skrll static void 694 1.16 tsutsui camdump(struct sn_softc *sc) 695 1.1 tsubai { 696 1.1 tsubai int i; 697 1.1 tsubai 698 1.1 tsubai printf("CAM entries:\n"); 699 1.1 tsubai NIC_PUT(sc, SNR_CR, CR_RST); 700 1.1 tsubai wbflush(); 701 1.1 tsubai 702 1.1 tsubai for (i = 0; i < 16; i++) { 703 1.1 tsubai ushort ap2, ap1, ap0; 704 1.1 tsubai NIC_PUT(sc, SNR_CEP, i); 705 1.1 tsubai wbflush(); 706 1.1 tsubai ap2 = NIC_GET(sc, SNR_CAP2); 707 1.1 tsubai ap1 = NIC_GET(sc, SNR_CAP1); 708 1.1 tsubai ap0 = NIC_GET(sc, SNR_CAP0); 709 1.1 tsubai printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0); 710 1.1 tsubai } 711 1.1 tsubai printf("CAM enable 0x%x\n", NIC_GET(sc, SNR_CEP)); 712 1.1 tsubai 713 1.1 tsubai NIC_PUT(sc, SNR_CR, 0); 714 1.1 tsubai wbflush(); 715 1.1 tsubai } 716 1.1 tsubai #endif 717 1.1 tsubai 718 1.48 skrll static void 719 1.16 tsutsui initialise_tda(struct sn_softc *sc) 720 1.1 tsubai { 721 1.1 tsubai struct mtd *mtd; 722 1.1 tsubai int i; 723 1.1 tsubai 724 1.1 tsubai for (i = 0; i < NTDA; i++) { 725 1.1 tsubai mtd = &sc->mtda[i]; 726 1.1 tsubai mtd->mtd_mbuf = 0; 727 1.1 tsubai } 728 1.1 tsubai 729 1.1 tsubai sc->mtd_hw = 0; 730 1.1 tsubai sc->mtd_prev = NTDA - 1; 731 1.1 tsubai sc->mtd_free = 0; 732 1.1 tsubai sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO; 733 1.1 tsubai sc->mtd_pint = NTDA/2; 734 1.1 tsubai 735 1.1 tsubai NIC_PUT(sc, SNR_UTDA, UPPER(sc->mtda[0].mtd_vtxp)); 736 1.1 tsubai NIC_PUT(sc, SNR_CTDA, LOWER(sc->mtda[0].mtd_vtxp)); 737 1.43 tsutsui wbflush(); 738 1.1 tsubai } 739 1.1 tsubai 740 1.1 tsubai static void 741 1.16 tsutsui initialise_rda(struct sn_softc *sc) 742 1.1 tsubai { 743 1.1 tsubai int i; 744 1.23 he char *p_rda = 0; 745 1.16 tsutsui uint32_t v_rda = 0; 746 1.1 tsubai 747 1.1 tsubai /* link the RDA's together into a circular list */ 748 1.1 tsubai for (i = 0; i < (sc->sc_nrda - 1); i++) { 749 1.23 he p_rda = (char *)sc->p_rda + (i * RXPKT_SIZE(sc)); 750 1.1 tsubai v_rda = sc->v_rda + ((i+1) * RXPKT_SIZE(sc)); 751 1.1 tsubai SWO(bitmode, p_rda, RXPKT_RLINK, LOWER(v_rda)); 752 1.1 tsubai SWO(bitmode, p_rda, RXPKT_INUSE, 1); 753 1.1 tsubai } 754 1.23 he p_rda = (char *)sc->p_rda + ((sc->sc_nrda - 1) * RXPKT_SIZE(sc)); 755 1.1 tsubai SWO(bitmode, p_rda, RXPKT_RLINK, LOWER(sc->v_rda) | EOL); 756 1.1 tsubai SWO(bitmode, p_rda, RXPKT_INUSE, 1); 757 1.1 tsubai 758 1.1 tsubai /* mark end of receive descriptor list */ 759 1.1 tsubai sc->sc_rdamark = sc->sc_nrda - 1; 760 1.1 tsubai 761 1.1 tsubai sc->sc_rxmark = 0; 762 1.1 tsubai 763 1.1 tsubai NIC_PUT(sc, SNR_URDA, UPPER(sc->v_rda)); 764 1.1 tsubai NIC_PUT(sc, SNR_CRDA, LOWER(sc->v_rda)); 765 1.1 tsubai wbflush(); 766 1.1 tsubai } 767 1.1 tsubai 768 1.1 tsubai static void 769 1.16 tsutsui initialise_rra(struct sn_softc *sc) 770 1.1 tsubai { 771 1.1 tsubai int i; 772 1.1 tsubai u_int v; 773 1.1 tsubai int bitmode = sc->bitmode; 774 1.1 tsubai 775 1.1 tsubai if (bitmode) 776 1.1 tsubai NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 2); 777 1.1 tsubai else 778 1.1 tsubai NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 1); 779 1.1 tsubai 780 1.1 tsubai NIC_PUT(sc, SNR_URRA, UPPER(sc->v_rra[0])); 781 1.1 tsubai NIC_PUT(sc, SNR_RSA, LOWER(sc->v_rra[0])); 782 1.1 tsubai /* rea must point just past the end of the rra space */ 783 1.1 tsubai NIC_PUT(sc, SNR_REA, LOWER(sc->v_rea)); 784 1.1 tsubai NIC_PUT(sc, SNR_RRP, LOWER(sc->v_rra[0])); 785 1.1 tsubai NIC_PUT(sc, SNR_RSC, 0); 786 1.1 tsubai 787 1.1 tsubai /* fill up SOME of the rra with buffers */ 788 1.1 tsubai for (i = 0; i < NRBA; i++) { 789 1.43 tsutsui v = SONIC_GETDMA(sc, sc->rbuf[i]); 790 1.1 tsubai SWO(bitmode, sc->p_rra[i], RXRSRC_PTRHI, UPPER(v)); 791 1.1 tsubai SWO(bitmode, sc->p_rra[i], RXRSRC_PTRLO, LOWER(v)); 792 1.12 thorpej SWO(bitmode, sc->p_rra[i], RXRSRC_WCHI, UPPER(PAGE_SIZE/2)); 793 1.12 thorpej SWO(bitmode, sc->p_rra[i], RXRSRC_WCLO, LOWER(PAGE_SIZE/2)); 794 1.1 tsubai } 795 1.1 tsubai sc->sc_rramark = NRBA; 796 1.1 tsubai NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[sc->sc_rramark])); 797 1.1 tsubai wbflush(); 798 1.1 tsubai } 799 1.1 tsubai 800 1.6 onoe int 801 1.16 tsutsui snintr(void *arg) 802 1.1 tsubai { 803 1.1 tsubai struct sn_softc *sc = (struct sn_softc *)arg; 804 1.6 onoe int handled = 0; 805 1.1 tsubai int isr; 806 1.1 tsubai 807 1.1 tsubai while ((isr = (NIC_GET(sc, SNR_ISR) & ISR_ALL)) != 0) { 808 1.1 tsubai /* scrub the interrupts that we are going to service */ 809 1.1 tsubai NIC_PUT(sc, SNR_ISR, isr); 810 1.6 onoe handled = 1; 811 1.1 tsubai wbflush(); 812 1.1 tsubai 813 1.1 tsubai if (isr & (ISR_BR | ISR_LCD | ISR_TC)) 814 1.1 tsubai printf("%s: unexpected interrupt status 0x%x\n", 815 1.30 tsutsui device_xname(sc->sc_dev), isr); 816 1.1 tsubai 817 1.1 tsubai if (isr & (ISR_TXDN | ISR_TXER | ISR_PINT)) 818 1.1 tsubai sonictxint(sc); 819 1.1 tsubai 820 1.1 tsubai if (isr & ISR_PKTRX) 821 1.1 tsubai sonicrxint(sc); 822 1.1 tsubai 823 1.1 tsubai if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) { 824 1.1 tsubai if (isr & ISR_HBL) 825 1.1 tsubai /* 826 1.1 tsubai * The repeater is not providing a heartbeat. 827 1.1 tsubai * In itself this isn't harmful, lots of the 828 1.1 tsubai * cheap repeater hubs don't supply a heartbeat. 829 1.1 tsubai * So ignore the lack of heartbeat. Its only 830 1.1 tsubai * if we can't detect a carrier that we have a 831 1.1 tsubai * problem. 832 1.1 tsubai */ 833 1.1 tsubai ; 834 1.1 tsubai if (isr & ISR_RDE) 835 1.1 tsubai printf("%s: receive descriptors exhausted\n", 836 1.30 tsutsui device_xname(sc->sc_dev)); 837 1.1 tsubai if (isr & ISR_RBE) 838 1.1 tsubai printf("%s: receive buffers exhausted\n", 839 1.30 tsutsui device_xname(sc->sc_dev)); 840 1.1 tsubai if (isr & ISR_RBAE) 841 1.1 tsubai printf("%s: receive buffer area exhausted\n", 842 1.30 tsutsui device_xname(sc->sc_dev)); 843 1.1 tsubai if (isr & ISR_RFO) 844 1.1 tsubai printf("%s: receive FIFO overrun\n", 845 1.30 tsutsui device_xname(sc->sc_dev)); 846 1.1 tsubai } 847 1.1 tsubai if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) { 848 1.1 tsubai #ifdef notdef 849 1.1 tsubai if (isr & ISR_CRC) 850 1.1 tsubai sc->sc_crctally++; 851 1.1 tsubai if (isr & ISR_FAE) 852 1.1 tsubai sc->sc_faetally++; 853 1.1 tsubai if (isr & ISR_MP) 854 1.1 tsubai sc->sc_mptally++; 855 1.1 tsubai #endif 856 1.1 tsubai } 857 1.38 nonaka if_schedule_deferred_start(&sc->sc_if); 858 1.1 tsubai } 859 1.6 onoe return handled; 860 1.1 tsubai } 861 1.1 tsubai 862 1.1 tsubai /* 863 1.1 tsubai * Transmit interrupt routine 864 1.1 tsubai */ 865 1.48 skrll static void 866 1.16 tsutsui sonictxint(struct sn_softc *sc) 867 1.1 tsubai { 868 1.1 tsubai struct mtd *mtd; 869 1.1 tsubai void *txp; 870 1.1 tsubai unsigned short txp_status; 871 1.1 tsubai int mtd_hw; 872 1.1 tsubai struct ifnet *ifp = &sc->sc_if; 873 1.1 tsubai 874 1.1 tsubai mtd_hw = sc->mtd_hw; 875 1.1 tsubai 876 1.1 tsubai if (mtd_hw == sc->mtd_free) 877 1.1 tsubai return; 878 1.1 tsubai 879 1.1 tsubai while (mtd_hw != sc->mtd_free) { 880 1.1 tsubai mtd = &sc->mtda[mtd_hw]; 881 1.1 tsubai 882 1.1 tsubai txp = mtd->mtd_txp; 883 1.1 tsubai 884 1.1 tsubai if (SRO(sc->bitmode, txp, TXP_STATUS) == 0) { 885 1.1 tsubai break; /* it hasn't really gone yet */ 886 1.1 tsubai } 887 1.1 tsubai 888 1.1 tsubai #ifdef SNDEBUG 889 1.1 tsubai { 890 1.1 tsubai struct ether_header *eh; 891 1.1 tsubai 892 1.1 tsubai eh = (struct ether_header *) mtd->mtd_buf; 893 1.1 tsubai printf("%s: xmit status=0x%x len=%d type=0x%x from %s", 894 1.30 tsutsui device_xname(sc->sc_dev), 895 1.1 tsubai SRO(sc->bitmode, txp, TXP_STATUS), 896 1.1 tsubai SRO(sc->bitmode, txp, TXP_PKTSIZE), 897 1.1 tsubai htons(eh->ether_type), 898 1.1 tsubai ether_sprintf(eh->ether_shost)); 899 1.1 tsubai printf(" (to %s)\n", ether_sprintf(eh->ether_dhost)); 900 1.1 tsubai } 901 1.1 tsubai #endif /* SNDEBUG */ 902 1.1 tsubai 903 1.56 rin m_freem(mtd->mtd_mbuf); 904 1.56 rin mtd->mtd_mbuf = NULL; 905 1.1 tsubai if (++mtd_hw == NTDA) mtd_hw = 0; 906 1.1 tsubai 907 1.1 tsubai txp_status = SRO(sc->bitmode, txp, TXP_STATUS); 908 1.1 tsubai 909 1.47 skrll if_statadd(ifp, if_collisions, (txp_status & TCR_EXC) ? 16 : 910 1.47 skrll ((txp_status & TCR_NC) >> 12)); 911 1.1 tsubai 912 1.1 tsubai if ((txp_status & TCR_PTX) == 0) { 913 1.47 skrll if_statinc(ifp, if_oerrors); 914 1.1 tsubai printf("%s: Tx packet status=0x%x\n", 915 1.30 tsutsui device_xname(sc->sc_dev), txp_status); 916 1.13 tsutsui 917 1.1 tsubai /* XXX - DG This looks bogus */ 918 1.1 tsubai if (mtd_hw != sc->mtd_free) { 919 1.1 tsubai printf("resubmitting remaining packets\n"); 920 1.1 tsubai mtd = &sc->mtda[mtd_hw]; 921 1.1 tsubai NIC_PUT(sc, SNR_CTDA, LOWER(mtd->mtd_vtxp)); 922 1.1 tsubai NIC_PUT(sc, SNR_CR, CR_TXP); 923 1.1 tsubai wbflush(); 924 1.1 tsubai break; 925 1.1 tsubai } 926 1.1 tsubai } 927 1.1 tsubai } 928 1.1 tsubai 929 1.1 tsubai sc->mtd_hw = mtd_hw; 930 1.1 tsubai return; 931 1.1 tsubai } 932 1.1 tsubai 933 1.1 tsubai /* 934 1.1 tsubai * Receive interrupt routine 935 1.1 tsubai */ 936 1.48 skrll static void 937 1.16 tsutsui sonicrxint(struct sn_softc *sc) 938 1.1 tsubai { 939 1.22 christos void * rda; 940 1.1 tsubai int orra; 941 1.1 tsubai int len; 942 1.1 tsubai int rramark; 943 1.1 tsubai int rdamark; 944 1.16 tsutsui uint16_t rxpkt_ptr; 945 1.1 tsubai 946 1.23 he rda = (char *)sc->p_rda + (sc->sc_rxmark * RXPKT_SIZE(sc)); 947 1.1 tsubai 948 1.1 tsubai while (SRO(bitmode, rda, RXPKT_INUSE) == 0) { 949 1.1 tsubai u_int status = SRO(bitmode, rda, RXPKT_STATUS); 950 1.1 tsubai 951 1.1 tsubai orra = RBASEQ(SRO(bitmode, rda, RXPKT_SEQNO)) & RRAMASK; 952 1.1 tsubai rxpkt_ptr = SRO(bitmode, rda, RXPKT_PTRLO); 953 1.1 tsubai len = SRO(bitmode, rda, RXPKT_BYTEC) - FCSSIZE; 954 1.1 tsubai if (status & RCR_PRX) { 955 1.22 christos void *pkt = 956 1.23 he (char *)sc->rbuf[orra & RBAMASK] + 957 1.23 he (rxpkt_ptr & PGOFSET); 958 1.37 ozaki if (sonic_read(sc, pkt, len) == 0) 959 1.49 martin if_statinc(&sc->sc_if, if_ierrors); 960 1.1 tsubai } else 961 1.49 martin if_statinc(&sc->sc_if, if_ierrors); 962 1.1 tsubai 963 1.1 tsubai /* 964 1.1 tsubai * give receive buffer area back to chip. 965 1.1 tsubai * 966 1.1 tsubai * If this was the last packet in the RRA, give the RRA to 967 1.1 tsubai * the chip again. 968 1.1 tsubai * If sonic read didnt copy it out then we would have to 969 1.1 tsubai * wait !! 970 1.1 tsubai * (dont bother add it back in again straight away) 971 1.1 tsubai * 972 1.1 tsubai * Really, we're doing p_rra[rramark] = p_rra[orra] but 973 1.1 tsubai * we have to use the macros because SONIC might be in 974 1.1 tsubai * 16 or 32 bit mode. 975 1.1 tsubai */ 976 1.1 tsubai if (status & RCR_LPKT) { 977 1.1 tsubai void *tmp1, *tmp2; 978 1.1 tsubai 979 1.1 tsubai rramark = sc->sc_rramark; 980 1.1 tsubai tmp1 = sc->p_rra[rramark]; 981 1.1 tsubai tmp2 = sc->p_rra[orra]; 982 1.1 tsubai SWO(bitmode, tmp1, RXRSRC_PTRLO, 983 1.16 tsutsui SRO(bitmode, tmp2, RXRSRC_PTRLO)); 984 1.1 tsubai SWO(bitmode, tmp1, RXRSRC_PTRHI, 985 1.16 tsutsui SRO(bitmode, tmp2, RXRSRC_PTRHI)); 986 1.1 tsubai SWO(bitmode, tmp1, RXRSRC_WCLO, 987 1.16 tsutsui SRO(bitmode, tmp2, RXRSRC_WCLO)); 988 1.1 tsubai SWO(bitmode, tmp1, RXRSRC_WCHI, 989 1.16 tsutsui SRO(bitmode, tmp2, RXRSRC_WCHI)); 990 1.1 tsubai 991 1.1 tsubai /* zap old rra for fun */ 992 1.1 tsubai SWO(bitmode, tmp2, RXRSRC_WCHI, 0); 993 1.1 tsubai SWO(bitmode, tmp2, RXRSRC_WCLO, 0); 994 1.1 tsubai 995 1.1 tsubai sc->sc_rramark = (++rramark) & RRAMASK; 996 1.1 tsubai NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[rramark])); 997 1.1 tsubai wbflush(); 998 1.1 tsubai } 999 1.1 tsubai 1000 1.1 tsubai /* 1001 1.1 tsubai * give receive descriptor back to chip simple 1002 1.1 tsubai * list is circular 1003 1.1 tsubai */ 1004 1.1 tsubai rdamark = sc->sc_rdamark; 1005 1.1 tsubai SWO(bitmode, rda, RXPKT_INUSE, 1); 1006 1.1 tsubai SWO(bitmode, rda, RXPKT_RLINK, 1007 1.16 tsutsui SRO(bitmode, rda, RXPKT_RLINK) | EOL); 1008 1.23 he SWO(bitmode, ((char *)sc->p_rda + (rdamark * RXPKT_SIZE(sc))), 1009 1.16 tsutsui RXPKT_RLINK, 1010 1.23 he SRO(bitmode, ((char *)sc->p_rda + 1011 1.23 he (rdamark * RXPKT_SIZE(sc))), 1012 1.16 tsutsui RXPKT_RLINK) & ~EOL); 1013 1.1 tsubai sc->sc_rdamark = sc->sc_rxmark; 1014 1.1 tsubai 1015 1.1 tsubai if (++sc->sc_rxmark >= sc->sc_nrda) 1016 1.1 tsubai sc->sc_rxmark = 0; 1017 1.23 he rda = (char *)sc->p_rda + (sc->sc_rxmark * RXPKT_SIZE(sc)); 1018 1.1 tsubai } 1019 1.1 tsubai } 1020 1.1 tsubai 1021 1.1 tsubai /* 1022 1.1 tsubai * sonic_read -- pull packet off interface and forward to 1023 1.1 tsubai * appropriate protocol handler 1024 1.1 tsubai */ 1025 1.48 skrll static inline int 1026 1.22 christos sonic_read(struct sn_softc *sc, void *pkt, int len) 1027 1.1 tsubai { 1028 1.1 tsubai struct ifnet *ifp = &sc->sc_if; 1029 1.1 tsubai struct mbuf *m; 1030 1.1 tsubai 1031 1.1 tsubai if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN) || 1032 1.1 tsubai len > (ETHER_MAX_LEN - ETHER_CRC_LEN)) { 1033 1.1 tsubai printf("%s: invalid packet length %d bytes\n", 1034 1.30 tsutsui device_xname(sc->sc_dev), len); 1035 1.16 tsutsui return 0; 1036 1.1 tsubai } 1037 1.1 tsubai 1038 1.53 andvar #ifdef SNDEBUG 1039 1.53 andvar { 1040 1.53 andvar struct ether_header eh_s, *eh = &eh_s; 1041 1.53 andvar memcpy(eh, pkt, sizeof(*eh)); 1042 1.53 andvar CTASSERT(sizeof(*eh) <= ETHER_MIN_LEN); 1043 1.53 andvar printf("%s: rcvd %p len=%d type=0x%x from %s", 1044 1.53 andvar device_xname(sc->sc_dev), eh, len, htons(eh->ether_type), 1045 1.53 andvar ether_sprintf(eh->ether_shost)); 1046 1.53 andvar printf(" (to %s)\n", ether_sprintf(eh->ether_dhost)); 1047 1.53 andvar } 1048 1.53 andvar #endif /* SNDEBUG */ 1049 1.53 andvar 1050 1.10 thorpej m = sonic_get(sc, pkt, len); 1051 1.10 thorpej if (m == NULL) 1052 1.16 tsutsui return 0; 1053 1.35 ozaki if_percpuq_enqueue(ifp->if_percpuq, m); 1054 1.16 tsutsui return 1; 1055 1.1 tsubai } 1056 1.1 tsubai 1057 1.1 tsubai /* 1058 1.1 tsubai * munge the received packet into an mbuf chain 1059 1.1 tsubai */ 1060 1.19 perry static inline struct mbuf * 1061 1.22 christos sonic_get(struct sn_softc *sc, void *pkt, int datalen) 1062 1.1 tsubai { 1063 1.1 tsubai struct mbuf *m, *top, **mp; 1064 1.1 tsubai int len; 1065 1.1 tsubai 1066 1.1 tsubai MGETHDR(m, M_DONTWAIT, MT_DATA); 1067 1.1 tsubai if (m == 0) 1068 1.16 tsutsui return 0; 1069 1.36 ozaki m_set_rcvif(m, &sc->sc_if); 1070 1.1 tsubai m->m_pkthdr.len = datalen; 1071 1.1 tsubai len = MHLEN; 1072 1.1 tsubai top = 0; 1073 1.1 tsubai mp = ⊤ 1074 1.1 tsubai 1075 1.1 tsubai while (datalen > 0) { 1076 1.1 tsubai if (top) { 1077 1.1 tsubai MGET(m, M_DONTWAIT, MT_DATA); 1078 1.1 tsubai if (m == 0) { 1079 1.1 tsubai m_freem(top); 1080 1.16 tsutsui return 0; 1081 1.1 tsubai } 1082 1.1 tsubai len = MLEN; 1083 1.1 tsubai } 1084 1.1 tsubai if (datalen >= MINCLSIZE) { 1085 1.1 tsubai MCLGET(m, M_DONTWAIT); 1086 1.1 tsubai if ((m->m_flags & M_EXT) == 0) { 1087 1.39 riastrad if (top) 1088 1.39 riastrad m_freem(top); 1089 1.39 riastrad else 1090 1.39 riastrad m_freem(m); 1091 1.16 tsutsui return 0; 1092 1.1 tsubai } 1093 1.1 tsubai len = MCLBYTES; 1094 1.1 tsubai } 1095 1.1 tsubai 1096 1.1 tsubai if (mp == &top) { 1097 1.23 he char *newdata = (char *) 1098 1.48 skrll ALIGN((char *)m->m_data + 1099 1.23 he sizeof(struct ether_header)) - 1100 1.1 tsubai sizeof(struct ether_header); 1101 1.48 skrll len -= newdata - m->m_data; 1102 1.1 tsubai m->m_data = newdata; 1103 1.1 tsubai } 1104 1.1 tsubai 1105 1.42 riastrad m->m_len = len = uimin(datalen, len); 1106 1.1 tsubai 1107 1.22 christos memcpy(mtod(m, void *), pkt, (unsigned) len); 1108 1.23 he pkt = (char *)pkt + len; 1109 1.1 tsubai datalen -= len; 1110 1.1 tsubai *mp = m; 1111 1.1 tsubai mp = &m->m_next; 1112 1.1 tsubai } 1113 1.1 tsubai 1114 1.16 tsutsui return top; 1115 1.1 tsubai } 1116