1 1.29 rin /* $NetBSD: if_xe.c,v 1.29 2024/07/05 04:31:49 rin Exp $ */ 2 1.1 dbj /* 3 1.1 dbj * Copyright (c) 1998 Darrin B. Jewell 4 1.1 dbj * All rights reserved. 5 1.1 dbj * 6 1.1 dbj * Redistribution and use in source and binary forms, with or without 7 1.1 dbj * modification, are permitted provided that the following conditions 8 1.1 dbj * are met: 9 1.1 dbj * 1. Redistributions of source code must retain the above copyright 10 1.1 dbj * notice, this list of conditions and the following disclaimer. 11 1.1 dbj * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 dbj * notice, this list of conditions and the following disclaimer in the 13 1.1 dbj * documentation and/or other materials provided with the distribution. 14 1.1 dbj * 15 1.1 dbj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 1.1 dbj * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 1.1 dbj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 1.1 dbj * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 1.1 dbj * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 1.1 dbj * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 1.1 dbj * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 1.1 dbj * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 1.1 dbj * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 1.1 dbj * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 1.1 dbj */ 26 1.14 lukem 27 1.14 lukem #include <sys/cdefs.h> 28 1.29 rin __KERNEL_RCSID(0, "$NetBSD: if_xe.c,v 1.29 2024/07/05 04:31:49 rin Exp $"); 29 1.1 dbj 30 1.2 jonathan #include "opt_inet.h" 31 1.1 dbj 32 1.1 dbj #include <sys/param.h> 33 1.1 dbj #include <sys/systm.h> 34 1.1 dbj #include <sys/mbuf.h> 35 1.1 dbj #include <sys/syslog.h> 36 1.1 dbj #include <sys/socket.h> 37 1.1 dbj #include <sys/device.h> 38 1.27 thorpej #include <sys/kmem.h> 39 1.1 dbj 40 1.1 dbj #include <net/if.h> 41 1.1 dbj #include <net/if_ether.h> 42 1.1 dbj #include <net/if_media.h> 43 1.1 dbj 44 1.1 dbj #ifdef INET 45 1.1 dbj #include <netinet/in.h> 46 1.1 dbj #include <netinet/if_inarp.h> 47 1.1 dbj #endif 48 1.1 dbj 49 1.1 dbj #include <machine/autoconf.h> 50 1.1 dbj #include <machine/cpu.h> 51 1.1 dbj #include <machine/intr.h> 52 1.1 dbj #include <machine/bus.h> 53 1.1 dbj 54 1.1 dbj #include <next68k/next68k/isr.h> 55 1.1 dbj 56 1.1 dbj #include <next68k/dev/mb8795reg.h> 57 1.1 dbj #include <next68k/dev/mb8795var.h> 58 1.1 dbj 59 1.7 mycroft #include <next68k/dev/bmapreg.h> 60 1.7 mycroft #include <next68k/dev/intiovar.h> 61 1.1 dbj #include <next68k/dev/nextdmareg.h> 62 1.1 dbj #include <next68k/dev/nextdmavar.h> 63 1.1 dbj 64 1.1 dbj #include <next68k/dev/if_xevar.h> 65 1.7 mycroft #include <next68k/dev/if_xereg.h> 66 1.7 mycroft 67 1.7 mycroft #ifdef DEBUG 68 1.7 mycroft #define XE_DEBUG 69 1.7 mycroft #endif 70 1.1 dbj 71 1.7 mycroft #ifdef XE_DEBUG 72 1.7 mycroft int xe_debug = 0; 73 1.7 mycroft #define DPRINTF(x) if (xe_debug) printf x; 74 1.7 mycroft #else 75 1.7 mycroft #define DPRINTF(x) 76 1.7 mycroft #endif 77 1.7 mycroft #define PRINTF(x) printf x; 78 1.7 mycroft 79 1.7 mycroft extern int turbo; 80 1.1 dbj 81 1.22 chs int xe_match(device_t, cfdata_t, void *); 82 1.22 chs void xe_attach(device_t, device_t, void *); 83 1.16 chs int xe_tint(void *); 84 1.16 chs int xe_rint(void *); 85 1.16 chs 86 1.25 msaitoh struct mbuf *xe_dma_rxmap_load(struct mb8795_softc *, bus_dmamap_t); 87 1.16 chs 88 1.16 chs bus_dmamap_t xe_dma_rx_continue(void *); 89 1.25 msaitoh void xe_dma_rx_completed(bus_dmamap_t, void *); 90 1.16 chs bus_dmamap_t xe_dma_tx_continue(void *); 91 1.25 msaitoh void xe_dma_tx_completed(bus_dmamap_t, void *); 92 1.25 msaitoh void xe_dma_rx_shutdown(void *); 93 1.25 msaitoh void xe_dma_tx_shutdown(void *); 94 1.7 mycroft 95 1.25 msaitoh static void findchannel_defer(device_t); 96 1.7 mycroft 97 1.22 chs CFATTACH_DECL_NEW(xe, sizeof(struct xe_softc), 98 1.11 thorpej xe_match, xe_attach, NULL, NULL); 99 1.1 dbj 100 1.7 mycroft static int xe_dma_medias[] = { 101 1.25 msaitoh IFM_ETHER | IFM_AUTO, 102 1.25 msaitoh IFM_ETHER | IFM_10_T, 103 1.25 msaitoh IFM_ETHER | IFM_10_2, 104 1.6 christos }; 105 1.25 msaitoh static int nxe_dma_medias = __arraycount(xe_dma_medias); 106 1.7 mycroft 107 1.7 mycroft static int attached = 0; 108 1.7 mycroft 109 1.7 mycroft /* 110 1.7 mycroft * Functions and the switch for the MI code. 111 1.7 mycroft */ 112 1.16 chs u_char xe_read_reg(struct mb8795_softc *, int); 113 1.16 chs void xe_write_reg(struct mb8795_softc *, int, u_char); 114 1.16 chs void xe_dma_reset(struct mb8795_softc *); 115 1.16 chs void xe_dma_rx_setup(struct mb8795_softc *); 116 1.16 chs void xe_dma_rx_go(struct mb8795_softc *); 117 1.16 chs struct mbuf * xe_dma_rx_mbuf(struct mb8795_softc *); 118 1.16 chs void xe_dma_tx_setup(struct mb8795_softc *); 119 1.16 chs void xe_dma_tx_go(struct mb8795_softc *); 120 1.16 chs int xe_dma_tx_mbuf(struct mb8795_softc *, struct mbuf *); 121 1.16 chs int xe_dma_tx_isactive(struct mb8795_softc *); 122 1.7 mycroft 123 1.7 mycroft struct mb8795_glue xe_glue = { 124 1.7 mycroft xe_read_reg, 125 1.7 mycroft xe_write_reg, 126 1.7 mycroft xe_dma_reset, 127 1.7 mycroft xe_dma_rx_setup, 128 1.7 mycroft xe_dma_rx_go, 129 1.7 mycroft xe_dma_rx_mbuf, 130 1.7 mycroft xe_dma_tx_setup, 131 1.7 mycroft xe_dma_tx_go, 132 1.7 mycroft xe_dma_tx_mbuf, 133 1.7 mycroft xe_dma_tx_isactive, 134 1.7 mycroft }; 135 1.6 christos 136 1.1 dbj int 137 1.22 chs xe_match(device_t parent, cfdata_t match, void *aux) 138 1.1 dbj { 139 1.7 mycroft struct intio_attach_args *ia = (struct intio_attach_args *)aux; 140 1.7 mycroft 141 1.7 mycroft if (attached) 142 1.25 msaitoh return 0; 143 1.7 mycroft 144 1.7 mycroft ia->ia_addr = (void *)NEXT_P_ENET; 145 1.7 mycroft 146 1.25 msaitoh return 1; 147 1.7 mycroft } 148 1.7 mycroft 149 1.7 mycroft static void 150 1.22 chs findchannel_defer(device_t self) 151 1.7 mycroft { 152 1.22 chs struct xe_softc *xsc = device_private(self); 153 1.7 mycroft struct mb8795_softc *sc = &xsc->sc_mb8795; 154 1.7 mycroft int i, error; 155 1.7 mycroft 156 1.7 mycroft if (!xsc->sc_txdma) { 157 1.7 mycroft xsc->sc_txdma = nextdma_findchannel ("enetx"); 158 1.7 mycroft if (xsc->sc_txdma == NULL) 159 1.22 chs panic("%s: can't find enetx DMA channel", 160 1.22 chs device_xname(sc->sc_dev)); 161 1.7 mycroft } 162 1.7 mycroft if (!xsc->sc_rxdma) { 163 1.7 mycroft xsc->sc_rxdma = nextdma_findchannel ("enetr"); 164 1.7 mycroft if (xsc->sc_rxdma == NULL) 165 1.13 wiz panic ("%s: can't find enetr DMA channel", 166 1.22 chs device_xname(sc->sc_dev)); 167 1.7 mycroft } 168 1.22 chs aprint_normal_dev(sc->sc_dev, "using DMA channels %s %s\n", 169 1.22 chs device_xname(xsc->sc_txdma->sc_dev), 170 1.22 chs device_xname(xsc->sc_rxdma->sc_dev)); 171 1.7 mycroft 172 1.7 mycroft nextdma_setconf (xsc->sc_rxdma, continue_cb, xe_dma_rx_continue); 173 1.7 mycroft nextdma_setconf (xsc->sc_rxdma, completed_cb, xe_dma_rx_completed); 174 1.7 mycroft nextdma_setconf (xsc->sc_rxdma, shutdown_cb, xe_dma_rx_shutdown); 175 1.7 mycroft nextdma_setconf (xsc->sc_rxdma, cb_arg, sc); 176 1.7 mycroft 177 1.7 mycroft nextdma_setconf (xsc->sc_txdma, continue_cb, xe_dma_tx_continue); 178 1.7 mycroft nextdma_setconf (xsc->sc_txdma, completed_cb, xe_dma_tx_completed); 179 1.7 mycroft nextdma_setconf (xsc->sc_txdma, shutdown_cb, xe_dma_tx_shutdown); 180 1.7 mycroft nextdma_setconf (xsc->sc_txdma, cb_arg, sc); 181 1.7 mycroft 182 1.13 wiz /* Initialize the DMA maps */ 183 1.7 mycroft error = bus_dmamap_create(xsc->sc_txdma->sc_dmat, MCLBYTES, 184 1.25 msaitoh (MCLBYTES/MSIZE), MCLBYTES, 0, BUS_DMA_ALLOCNOW, 185 1.25 msaitoh &xsc->sc_tx_dmamap); 186 1.7 mycroft if (error) { 187 1.25 msaitoh aprint_error_dev(sc->sc_dev, 188 1.25 msaitoh "can't create tx DMA map, error = %d", error); 189 1.7 mycroft } 190 1.7 mycroft 191 1.7 mycroft for(i = 0; i < MB8795_NRXBUFS; i++) { 192 1.7 mycroft error = bus_dmamap_create(xsc->sc_rxdma->sc_dmat, MCLBYTES, 193 1.25 msaitoh (MCLBYTES/MSIZE), MCLBYTES, 0, BUS_DMA_ALLOCNOW, 194 1.25 msaitoh &xsc->sc_rx_dmamap[i]); 195 1.7 mycroft if (error) { 196 1.8 provos panic("%s: can't create rx DMA map, error = %d", 197 1.22 chs device_xname(sc->sc_dev), error); 198 1.7 mycroft } 199 1.7 mycroft xsc->sc_rx_mb_head[i] = NULL; 200 1.7 mycroft } 201 1.7 mycroft xsc->sc_rx_loaded_idx = 0; 202 1.7 mycroft xsc->sc_rx_completed_idx = 0; 203 1.7 mycroft xsc->sc_rx_handled_idx = 0; 204 1.7 mycroft 205 1.28 tsutsui /* 206 1.28 tsutsui * @@@ more next hacks 207 1.7 mycroft * the 2000 covers at least a 1500 mtu + headers 208 1.7 mycroft * + DMA_BEGINALIGNMENT+ DMA_ENDALIGNMENT 209 1.7 mycroft */ 210 1.27 thorpej xsc->sc_txbuf = kmem_alloc(2000, KM_SLEEP); 211 1.7 mycroft xsc->sc_tx_mb_head = NULL; 212 1.7 mycroft xsc->sc_tx_loaded = 0; 213 1.28 tsutsui 214 1.7 mycroft mb8795_config(sc, xe_dma_medias, nxe_dma_medias, xe_dma_medias[0]); 215 1.28 tsutsui 216 1.7 mycroft isrlink_autovec(xe_tint, sc, NEXT_I_IPL(NEXT_I_ENETX), 1, NULL); 217 1.7 mycroft INTR_ENABLE(NEXT_I_ENETX); 218 1.7 mycroft isrlink_autovec(xe_rint, sc, NEXT_I_IPL(NEXT_I_ENETR), 1, NULL); 219 1.7 mycroft INTR_ENABLE(NEXT_I_ENETR); 220 1.1 dbj } 221 1.1 dbj 222 1.1 dbj void 223 1.22 chs xe_attach(device_t parent, device_t self, void *aux) 224 1.1 dbj { 225 1.7 mycroft struct intio_attach_args *ia = (struct intio_attach_args *)aux; 226 1.22 chs struct xe_softc *xsc = device_private(self); 227 1.7 mycroft struct mb8795_softc *sc = &xsc->sc_mb8795; 228 1.7 mycroft 229 1.22 chs sc->sc_dev = self; 230 1.22 chs DPRINTF(("%s: xe_attach()\n", device_xname(self))); 231 1.7 mycroft 232 1.7 mycroft { 233 1.25 msaitoh /* kludge from machdep.c:next68k_bootargs() */ 234 1.25 msaitoh extern u_char rom_enetaddr[6]; 235 1.7 mycroft int i; 236 1.25 msaitoh 237 1.25 msaitoh for (i = 0; i < 6; i++) 238 1.7 mycroft sc->sc_enaddr[i] = rom_enetaddr[i]; 239 1.7 mycroft } 240 1.7 mycroft 241 1.7 mycroft printf("\n%s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", 242 1.22 chs device_xname(self), 243 1.7 mycroft sc->sc_enaddr[0],sc->sc_enaddr[1],sc->sc_enaddr[2], 244 1.7 mycroft sc->sc_enaddr[3],sc->sc_enaddr[4],sc->sc_enaddr[5]); 245 1.7 mycroft 246 1.7 mycroft xsc->sc_bst = ia->ia_bst; 247 1.7 mycroft if (bus_space_map(xsc->sc_bst, NEXT_P_ENET, 248 1.7 mycroft XE_DEVICE_SIZE, 0, &xsc->sc_bsh)) { 249 1.8 provos panic("\n%s: can't map mb8795 registers", 250 1.22 chs device_xname(self)); 251 1.7 mycroft } 252 1.1 dbj 253 1.7 mycroft sc->sc_bmap_bst = ia->ia_bst; 254 1.7 mycroft if (bus_space_map(sc->sc_bmap_bst, NEXT_P_BMAP, 255 1.25 msaitoh BMAP_SIZE, 0, &sc->sc_bmap_bsh)) 256 1.25 msaitoh panic("\n%s: can't map bmap registers", device_xname(self)); 257 1.1 dbj 258 1.25 msaitoh /* Set up glue for MI code. */ 259 1.7 mycroft sc->sc_glue = &xe_glue; 260 1.1 dbj 261 1.22 chs xsc->sc_txdma = nextdma_findchannel("enetx"); 262 1.22 chs xsc->sc_rxdma = nextdma_findchannel("enetr"); 263 1.25 msaitoh if (xsc->sc_rxdma && xsc->sc_txdma) 264 1.22 chs findchannel_defer(self); 265 1.25 msaitoh else 266 1.22 chs config_defer(self, findchannel_defer); 267 1.1 dbj 268 1.7 mycroft attached = 1; 269 1.1 dbj } 270 1.1 dbj 271 1.1 dbj int 272 1.16 chs xe_tint(void *arg) 273 1.1 dbj { 274 1.7 mycroft if (!INTR_OCCURRED(NEXT_I_ENETX)) 275 1.7 mycroft return 0; 276 1.7 mycroft mb8795_tint((struct mb8795_softc *)arg); 277 1.25 msaitoh return 1; 278 1.1 dbj } 279 1.1 dbj 280 1.1 dbj int 281 1.16 chs xe_rint(void *arg) 282 1.7 mycroft { 283 1.7 mycroft if (!INTR_OCCURRED(NEXT_I_ENETR)) 284 1.25 msaitoh return 0; 285 1.7 mycroft mb8795_rint((struct mb8795_softc *)arg); 286 1.25 msaitoh return 1; 287 1.7 mycroft } 288 1.7 mycroft 289 1.7 mycroft /* 290 1.7 mycroft * Glue functions. 291 1.7 mycroft */ 292 1.7 mycroft 293 1.7 mycroft u_char 294 1.16 chs xe_read_reg(struct mb8795_softc *sc, int reg) 295 1.7 mycroft { 296 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 297 1.7 mycroft 298 1.25 msaitoh return bus_space_read_1(xsc->sc_bst, xsc->sc_bsh, reg); 299 1.7 mycroft } 300 1.7 mycroft 301 1.7 mycroft void 302 1.16 chs xe_write_reg(struct mb8795_softc *sc, int reg, u_char val) 303 1.7 mycroft { 304 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 305 1.7 mycroft 306 1.7 mycroft bus_space_write_1(xsc->sc_bst, xsc->sc_bsh, reg, val); 307 1.7 mycroft } 308 1.7 mycroft 309 1.7 mycroft void 310 1.16 chs xe_dma_reset(struct mb8795_softc *sc) 311 1.7 mycroft { 312 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 313 1.7 mycroft int i; 314 1.7 mycroft 315 1.13 wiz DPRINTF(("xe DMA reset\n")); 316 1.28 tsutsui 317 1.7 mycroft nextdma_reset(xsc->sc_rxdma); 318 1.7 mycroft nextdma_reset(xsc->sc_txdma); 319 1.7 mycroft 320 1.7 mycroft if (xsc->sc_tx_loaded) { 321 1.7 mycroft bus_dmamap_sync(xsc->sc_txdma->sc_dmat, xsc->sc_tx_dmamap, 322 1.25 msaitoh 0, xsc->sc_tx_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); 323 1.7 mycroft bus_dmamap_unload(xsc->sc_txdma->sc_dmat, xsc->sc_tx_dmamap); 324 1.7 mycroft xsc->sc_tx_loaded = 0; 325 1.7 mycroft } 326 1.29 rin m_freem(xsc->sc_tx_mb_head); 327 1.29 rin xsc->sc_tx_mb_head = NULL; 328 1.7 mycroft 329 1.7 mycroft for(i = 0; i < MB8795_NRXBUFS; i++) { 330 1.7 mycroft if (xsc->sc_rx_mb_head[i]) { 331 1.25 msaitoh bus_dmamap_unload(xsc->sc_rxdma->sc_dmat, 332 1.25 msaitoh xsc->sc_rx_dmamap[i]); 333 1.7 mycroft m_freem(xsc->sc_rx_mb_head[i]); 334 1.7 mycroft xsc->sc_rx_mb_head[i] = NULL; 335 1.7 mycroft } 336 1.7 mycroft } 337 1.7 mycroft } 338 1.7 mycroft 339 1.7 mycroft void 340 1.16 chs xe_dma_rx_setup(struct mb8795_softc *sc) 341 1.7 mycroft { 342 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 343 1.7 mycroft int i; 344 1.7 mycroft 345 1.13 wiz DPRINTF(("xe DMA rx setup\n")); 346 1.7 mycroft 347 1.25 msaitoh for(i = 0; i < MB8795_NRXBUFS; i++) 348 1.28 tsutsui xsc->sc_rx_mb_head[i] = 349 1.7 mycroft xe_dma_rxmap_load(sc, xsc->sc_rx_dmamap[i]); 350 1.25 msaitoh 351 1.7 mycroft xsc->sc_rx_loaded_idx = 0; 352 1.7 mycroft xsc->sc_rx_completed_idx = 0; 353 1.7 mycroft xsc->sc_rx_handled_idx = 0; 354 1.7 mycroft 355 1.7 mycroft nextdma_init(xsc->sc_rxdma); 356 1.7 mycroft } 357 1.7 mycroft 358 1.7 mycroft void 359 1.16 chs xe_dma_rx_go(struct mb8795_softc *sc) 360 1.7 mycroft { 361 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 362 1.7 mycroft 363 1.13 wiz DPRINTF(("xe DMA rx go\n")); 364 1.7 mycroft 365 1.7 mycroft nextdma_start(xsc->sc_rxdma, DMACSR_SETREAD); 366 1.7 mycroft } 367 1.7 mycroft 368 1.7 mycroft struct mbuf * 369 1.16 chs xe_dma_rx_mbuf(struct mb8795_softc *sc) 370 1.7 mycroft { 371 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 372 1.7 mycroft bus_dmamap_t map; 373 1.7 mycroft struct mbuf *m; 374 1.7 mycroft 375 1.7 mycroft m = NULL; 376 1.7 mycroft if (xsc->sc_rx_handled_idx != xsc->sc_rx_completed_idx) { 377 1.7 mycroft xsc->sc_rx_handled_idx++; 378 1.7 mycroft xsc->sc_rx_handled_idx %= MB8795_NRXBUFS; 379 1.7 mycroft 380 1.7 mycroft map = xsc->sc_rx_dmamap[xsc->sc_rx_handled_idx]; 381 1.7 mycroft m = xsc->sc_rx_mb_head[xsc->sc_rx_handled_idx]; 382 1.28 tsutsui 383 1.7 mycroft m->m_len = map->dm_xfer_len; 384 1.7 mycroft 385 1.7 mycroft bus_dmamap_sync(xsc->sc_rxdma->sc_dmat, map, 386 1.7 mycroft 0, map->dm_mapsize, BUS_DMASYNC_POSTREAD); 387 1.28 tsutsui 388 1.7 mycroft bus_dmamap_unload(xsc->sc_rxdma->sc_dmat, map); 389 1.28 tsutsui 390 1.7 mycroft /* Install a fresh mbuf for next packet */ 391 1.28 tsutsui 392 1.28 tsutsui xsc->sc_rx_mb_head[xsc->sc_rx_handled_idx] = 393 1.7 mycroft xe_dma_rxmap_load(sc,map); 394 1.7 mycroft 395 1.7 mycroft /* Punt runt packets 396 1.13 wiz * DMA restarts create 0 length packets for example 397 1.7 mycroft */ 398 1.7 mycroft if (m->m_len < ETHER_MIN_LEN) { 399 1.7 mycroft m_freem(m); 400 1.7 mycroft m = NULL; 401 1.7 mycroft } 402 1.7 mycroft } 403 1.25 msaitoh return m; 404 1.7 mycroft } 405 1.7 mycroft 406 1.7 mycroft void 407 1.16 chs xe_dma_tx_setup(struct mb8795_softc *sc) 408 1.7 mycroft { 409 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 410 1.7 mycroft 411 1.13 wiz DPRINTF(("xe DMA tx setup\n")); 412 1.7 mycroft 413 1.7 mycroft nextdma_init(xsc->sc_txdma); 414 1.7 mycroft } 415 1.7 mycroft 416 1.7 mycroft void 417 1.16 chs xe_dma_tx_go(struct mb8795_softc *sc) 418 1.7 mycroft { 419 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 420 1.7 mycroft 421 1.13 wiz DPRINTF(("xe DMA tx go\n")); 422 1.7 mycroft 423 1.7 mycroft nextdma_start(xsc->sc_txdma, DMACSR_SETWRITE); 424 1.7 mycroft } 425 1.7 mycroft 426 1.7 mycroft int 427 1.16 chs xe_dma_tx_mbuf(struct mb8795_softc *sc, struct mbuf *m) 428 1.7 mycroft { 429 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 430 1.7 mycroft int error; 431 1.7 mycroft 432 1.7 mycroft xsc->sc_tx_mb_head = m; 433 1.7 mycroft 434 1.7 mycroft /* The following is a next specific hack that should 435 1.7 mycroft * probably be moved out of MI code. 436 1.7 mycroft * This macro assumes it can move forward as needed 437 1.7 mycroft * in the buffer. Perhaps it should zero the extra buffer. 438 1.7 mycroft */ 439 1.7 mycroft #define REALIGN_DMABUF(s,l) \ 440 1.7 mycroft { (s) = ((u_char *)(((unsigned)(s)+DMA_BEGINALIGNMENT-1) \ 441 1.7 mycroft &~(DMA_BEGINALIGNMENT-1))); \ 442 1.7 mycroft (l) = ((u_char *)(((unsigned)((s)+(l))+DMA_ENDALIGNMENT-1) \ 443 1.7 mycroft &~(DMA_ENDALIGNMENT-1)))-(s);} 444 1.7 mycroft 445 1.7 mycroft #if 0 446 1.7 mycroft error = bus_dmamap_load_mbuf(xsc->sc_txdma->sc_dmat, 447 1.25 msaitoh xsc->sc_tx_dmamap, xsc->sc_tx_mb_head, BUS_DMA_NOWAIT); 448 1.7 mycroft #else 449 1.7 mycroft { 450 1.7 mycroft u_char *buf = xsc->sc_txbuf; 451 1.7 mycroft int buflen = 0; 452 1.7 mycroft 453 1.7 mycroft buflen = m->m_pkthdr.len; 454 1.7 mycroft 455 1.7 mycroft { 456 1.7 mycroft u_char *p = buf; 457 1.7 mycroft for (m=xsc->sc_tx_mb_head; m; m = m->m_next) { 458 1.7 mycroft if (m->m_len == 0) continue; 459 1.19 cegger memcpy(p, mtod(m, u_char *), m->m_len); 460 1.7 mycroft p += m->m_len; 461 1.12 bouyer } 462 1.12 bouyer /* Fix runt packets */ 463 1.12 bouyer if (buflen < ETHER_MIN_LEN - ETHER_CRC_LEN) { 464 1.12 bouyer memset(p, 0, 465 1.12 bouyer ETHER_MIN_LEN - ETHER_CRC_LEN - buflen); 466 1.12 bouyer buflen = ETHER_MIN_LEN - ETHER_CRC_LEN; 467 1.7 mycroft } 468 1.7 mycroft } 469 1.28 tsutsui 470 1.25 msaitoh error = bus_dmamap_load(xsc->sc_txdma->sc_dmat, 471 1.25 msaitoh xsc->sc_tx_dmamap, buf, buflen, NULL, BUS_DMA_NOWAIT); 472 1.7 mycroft } 473 1.7 mycroft #endif 474 1.7 mycroft if (error) { 475 1.25 msaitoh aprint_error_dev(sc->sc_dev, 476 1.25 msaitoh "can't load mbuf chain, error = %d\n", error); 477 1.7 mycroft m_freem(xsc->sc_tx_mb_head); 478 1.7 mycroft xsc->sc_tx_mb_head = NULL; 479 1.25 msaitoh return error; 480 1.7 mycroft } 481 1.7 mycroft 482 1.7 mycroft #ifdef DIAGNOSTIC 483 1.7 mycroft if (xsc->sc_tx_loaded != 0) { 484 1.22 chs panic("%s: xsc->sc_tx_loaded is %d", device_xname(sc->sc_dev), 485 1.7 mycroft xsc->sc_tx_loaded); 486 1.7 mycroft } 487 1.7 mycroft #endif 488 1.7 mycroft 489 1.7 mycroft bus_dmamap_sync(xsc->sc_txdma->sc_dmat, xsc->sc_tx_dmamap, 0, 490 1.7 mycroft xsc->sc_tx_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE); 491 1.7 mycroft 492 1.25 msaitoh return 0; 493 1.7 mycroft } 494 1.7 mycroft 495 1.7 mycroft int 496 1.16 chs xe_dma_tx_isactive(struct mb8795_softc *sc) 497 1.7 mycroft { 498 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 499 1.7 mycroft 500 1.7 mycroft return (xsc->sc_tx_loaded != 0); 501 1.7 mycroft } 502 1.7 mycroft 503 1.7 mycroft /****************************************************************/ 504 1.7 mycroft 505 1.28 tsutsui void 506 1.16 chs xe_dma_tx_completed(bus_dmamap_t map, void *arg) 507 1.7 mycroft { 508 1.15 perseant #if defined (XE_DEBUG) || defined (DIAGNOSTIC) 509 1.7 mycroft struct mb8795_softc *sc = arg; 510 1.15 perseant #endif 511 1.15 perseant #ifdef DIAGNOSTIC 512 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 513 1.15 perseant #endif 514 1.7 mycroft 515 1.22 chs DPRINTF(("%s: xe_dma_tx_completed()\n", device_xname(sc->sc_dev))); 516 1.7 mycroft 517 1.7 mycroft #ifdef DIAGNOSTIC 518 1.25 msaitoh if (!xsc->sc_tx_loaded) 519 1.25 msaitoh panic("%s: tx completed never loaded", 520 1.25 msaitoh device_xname(sc->sc_dev)); 521 1.25 msaitoh 522 1.25 msaitoh if (map != xsc->sc_tx_dmamap) 523 1.25 msaitoh panic("%s: unexpected tx completed map", 524 1.25 msaitoh device_xname(sc->sc_dev)); 525 1.7 mycroft 526 1.7 mycroft #endif 527 1.7 mycroft } 528 1.7 mycroft 529 1.28 tsutsui void 530 1.16 chs xe_dma_tx_shutdown(void *arg) 531 1.1 dbj { 532 1.7 mycroft struct mb8795_softc *sc = arg; 533 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 534 1.7 mycroft struct ifnet *ifp = &sc->sc_ethercom.ec_if; 535 1.7 mycroft 536 1.22 chs DPRINTF(("%s: xe_dma_tx_shutdown()\n", device_xname(sc->sc_dev))); 537 1.7 mycroft 538 1.7 mycroft #ifdef DIAGNOSTIC 539 1.25 msaitoh if (!xsc->sc_tx_loaded) 540 1.25 msaitoh panic("%s: tx shutdown never loaded", 541 1.25 msaitoh device_xname(sc->sc_dev)); 542 1.7 mycroft #endif 543 1.7 mycroft 544 1.7 mycroft if (turbo) 545 1.7 mycroft MB_WRITE_REG(sc, MB8795_TXMODE, MB8795_TXMODE_TURBO1); 546 1.7 mycroft if (xsc->sc_tx_loaded) { 547 1.7 mycroft bus_dmamap_sync(xsc->sc_txdma->sc_dmat, xsc->sc_tx_dmamap, 548 1.25 msaitoh 0, xsc->sc_tx_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE); 549 1.7 mycroft bus_dmamap_unload(xsc->sc_txdma->sc_dmat, xsc->sc_tx_dmamap); 550 1.7 mycroft m_freem(xsc->sc_tx_mb_head); 551 1.7 mycroft xsc->sc_tx_mb_head = NULL; 552 1.28 tsutsui 553 1.7 mycroft xsc->sc_tx_loaded--; 554 1.7 mycroft } 555 1.7 mycroft 556 1.7 mycroft #ifdef DIAGNOSTIC 557 1.25 msaitoh if (xsc->sc_tx_loaded != 0) 558 1.22 chs panic("%s: sc->sc_tx_loaded is %d", device_xname(sc->sc_dev), 559 1.7 mycroft xsc->sc_tx_loaded); 560 1.7 mycroft #endif 561 1.7 mycroft 562 1.7 mycroft ifp->if_timer = 0; 563 1.7 mycroft 564 1.7 mycroft #if 1 565 1.7 mycroft if ((ifp->if_flags & IFF_RUNNING) && !IF_IS_EMPTY(&sc->sc_tx_snd)) { 566 1.16 chs void mb8795_start_dma(struct mb8795_softc *); /* XXXX */ 567 1.7 mycroft mb8795_start_dma(sc); 568 1.7 mycroft } 569 1.7 mycroft #endif 570 1.7 mycroft 571 1.7 mycroft #if 0 572 1.7 mycroft /* Enable ready interrupt */ 573 1.28 tsutsui MB_WRITE_REG(sc, MB8795_TXMASK, 574 1.7 mycroft MB_READ_REG(sc, MB8795_TXMASK) 575 1.7 mycroft | MB8795_TXMASK_TXRXIE/* READYIE */); 576 1.7 mycroft #endif 577 1.7 mycroft } 578 1.7 mycroft 579 1.7 mycroft 580 1.28 tsutsui void 581 1.16 chs xe_dma_rx_completed(bus_dmamap_t map, void *arg) 582 1.7 mycroft { 583 1.7 mycroft struct mb8795_softc *sc = arg; 584 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 585 1.7 mycroft struct ifnet *ifp = &sc->sc_ethercom.ec_if; 586 1.7 mycroft 587 1.7 mycroft if (ifp->if_flags & IFF_RUNNING) { 588 1.7 mycroft xsc->sc_rx_completed_idx++; 589 1.7 mycroft xsc->sc_rx_completed_idx %= MB8795_NRXBUFS; 590 1.28 tsutsui 591 1.25 msaitoh DPRINTF(("%s: xe_dma_rx_completed(), " 592 1.25 msaitoh "sc->sc_rx_completed_idx = %d\n", 593 1.22 chs device_xname(sc->sc_dev), xsc->sc_rx_completed_idx)); 594 1.28 tsutsui 595 1.7 mycroft #if (defined(DIAGNOSTIC)) 596 1.25 msaitoh if (map != xsc->sc_rx_dmamap[xsc->sc_rx_completed_idx]) 597 1.8 provos panic("%s: Unexpected rx dmamap completed", 598 1.22 chs device_xname(sc->sc_dev)); 599 1.7 mycroft #endif 600 1.7 mycroft } 601 1.7 mycroft #ifdef DIAGNOSTIC 602 1.7 mycroft else 603 1.25 msaitoh DPRINTF(("%s: Unexpected rx dmamap completed while if not " 604 1.25 msaitoh "running\n", device_xname(sc->sc_dev))); 605 1.7 mycroft #endif 606 1.7 mycroft } 607 1.7 mycroft 608 1.28 tsutsui void 609 1.16 chs xe_dma_rx_shutdown(void *arg) 610 1.7 mycroft { 611 1.7 mycroft struct mb8795_softc *sc = arg; 612 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 613 1.7 mycroft struct ifnet *ifp = &sc->sc_ethercom.ec_if; 614 1.7 mycroft 615 1.7 mycroft if (ifp->if_flags & IFF_RUNNING) { 616 1.7 mycroft DPRINTF(("%s: xe_dma_rx_shutdown(), restarting.\n", 617 1.22 chs device_xname(sc->sc_dev))); 618 1.28 tsutsui 619 1.7 mycroft nextdma_start(xsc->sc_rxdma, DMACSR_SETREAD); 620 1.7 mycroft if (turbo) 621 1.25 msaitoh MB_WRITE_REG(sc, MB8795_RXMODE, 622 1.25 msaitoh MB8795_RXMODE_TEST | MB8795_RXMODE_MULTICAST); 623 1.7 mycroft } 624 1.7 mycroft #ifdef DIAGNOSTIC 625 1.7 mycroft else 626 1.25 msaitoh DPRINTF(("%s: Unexpected rx DMA shutdown while if not " 627 1.25 msaitoh "running\n", device_xname(sc->sc_dev))); 628 1.7 mycroft #endif 629 1.7 mycroft } 630 1.7 mycroft 631 1.7 mycroft /* 632 1.7 mycroft * load a dmamap with a freshly allocated mbuf 633 1.7 mycroft */ 634 1.7 mycroft struct mbuf * 635 1.16 chs xe_dma_rxmap_load(struct mb8795_softc *sc, bus_dmamap_t map) 636 1.7 mycroft { 637 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 638 1.7 mycroft struct ifnet *ifp = &sc->sc_ethercom.ec_if; 639 1.7 mycroft struct mbuf *m; 640 1.7 mycroft int error; 641 1.7 mycroft 642 1.7 mycroft MGETHDR(m, M_DONTWAIT, MT_DATA); 643 1.7 mycroft if (m) { 644 1.7 mycroft MCLGET(m, M_DONTWAIT); 645 1.7 mycroft if ((m->m_flags & M_EXT) == 0) { 646 1.7 mycroft m_freem(m); 647 1.7 mycroft m = NULL; 648 1.25 msaitoh } else 649 1.7 mycroft m->m_len = MCLBYTES; 650 1.7 mycroft } 651 1.7 mycroft if (!m) { 652 1.25 msaitoh /* 653 1.25 msaitoh * @@@ Handle this gracefully by reusing a scratch buffer 654 1.7 mycroft * or something. 655 1.7 mycroft */ 656 1.8 provos panic("Unable to get memory for incoming ethernet"); 657 1.7 mycroft } 658 1.7 mycroft 659 1.25 msaitoh /* 660 1.25 msaitoh * Align buffer, @@@ next specific. 661 1.28 tsutsui * perhaps should be using M_ALIGN here instead? 662 1.7 mycroft * First we give us a little room to align with. 663 1.7 mycroft */ 664 1.7 mycroft { 665 1.7 mycroft u_char *buf = m->m_data; 666 1.7 mycroft int buflen = m->m_len; 667 1.7 mycroft buflen -= DMA_ENDALIGNMENT+DMA_BEGINALIGNMENT; 668 1.7 mycroft REALIGN_DMABUF(buf, buflen); 669 1.7 mycroft m->m_data = buf; 670 1.7 mycroft m->m_len = buflen; 671 1.7 mycroft } 672 1.7 mycroft 673 1.24 ozaki m_set_rcvif(m, ifp); 674 1.7 mycroft m->m_pkthdr.len = m->m_len; 675 1.7 mycroft 676 1.7 mycroft error = bus_dmamap_load_mbuf(xsc->sc_rxdma->sc_dmat, 677 1.7 mycroft map, m, BUS_DMA_NOWAIT); 678 1.7 mycroft 679 1.7 mycroft bus_dmamap_sync(xsc->sc_rxdma->sc_dmat, map, 0, 680 1.7 mycroft map->dm_mapsize, BUS_DMASYNC_PREREAD); 681 1.28 tsutsui 682 1.7 mycroft if (error) { 683 1.7 mycroft DPRINTF(("DEBUG: m->m_data = %p, m->m_len = %d\n", 684 1.7 mycroft m->m_data, m->m_len)); 685 1.7 mycroft DPRINTF(("DEBUG: MCLBYTES = %d, map->_dm_size = %ld\n", 686 1.7 mycroft MCLBYTES, map->_dm_size)); 687 1.7 mycroft 688 1.8 provos panic("%s: can't load rx mbuf chain, error = %d", 689 1.22 chs device_xname(sc->sc_dev), error); 690 1.7 mycroft m_freem(m); 691 1.7 mycroft m = NULL; 692 1.7 mycroft } 693 1.7 mycroft 694 1.25 msaitoh return m; 695 1.7 mycroft } 696 1.7 mycroft 697 1.28 tsutsui bus_dmamap_t 698 1.16 chs xe_dma_rx_continue(void *arg) 699 1.7 mycroft { 700 1.7 mycroft struct mb8795_softc *sc = arg; 701 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 702 1.7 mycroft struct ifnet *ifp = &sc->sc_ethercom.ec_if; 703 1.7 mycroft bus_dmamap_t map = NULL; 704 1.7 mycroft 705 1.7 mycroft if (ifp->if_flags & IFF_RUNNING) { 706 1.25 msaitoh if (((xsc->sc_rx_loaded_idx+1)%MB8795_NRXBUFS) 707 1.25 msaitoh == xsc->sc_rx_handled_idx) { 708 1.25 msaitoh /* Make space for one packet by dropping one */ 709 1.7 mycroft struct mbuf *m; 710 1.7 mycroft m = xe_dma_rx_mbuf (sc); 711 1.7 mycroft if (m) 712 1.7 mycroft m_freem(m); 713 1.7 mycroft #if (defined(DIAGNOSTIC)) 714 1.25 msaitoh DPRINTF(("%s: out of receive DMA buffers\n", 715 1.25 msaitoh device_xname(sc->sc_dev))); 716 1.7 mycroft #endif 717 1.7 mycroft } 718 1.7 mycroft xsc->sc_rx_loaded_idx++; 719 1.7 mycroft xsc->sc_rx_loaded_idx %= MB8795_NRXBUFS; 720 1.7 mycroft map = xsc->sc_rx_dmamap[xsc->sc_rx_loaded_idx]; 721 1.28 tsutsui 722 1.25 msaitoh DPRINTF(("%s: xe_dma_rx_continue() xsc->sc_rx_loaded_idx " 723 1.25 msaitoh "= %d\n", device_xname(sc->sc_dev), 724 1.25 msaitoh xsc->sc_rx_loaded_idx)); 725 1.7 mycroft } 726 1.7 mycroft #ifdef DIAGNOSTIC 727 1.7 mycroft else 728 1.13 wiz panic("%s: Unexpected rx DMA continue while if not running", 729 1.22 chs device_xname(sc->sc_dev)); 730 1.7 mycroft #endif 731 1.28 tsutsui 732 1.25 msaitoh return map; 733 1.7 mycroft } 734 1.7 mycroft 735 1.28 tsutsui bus_dmamap_t 736 1.16 chs xe_dma_tx_continue(void *arg) 737 1.7 mycroft { 738 1.7 mycroft struct mb8795_softc *sc = arg; 739 1.7 mycroft struct xe_softc *xsc = (struct xe_softc *)sc; 740 1.7 mycroft bus_dmamap_t map; 741 1.7 mycroft 742 1.22 chs DPRINTF(("%s: xe_dma_tx_continue()\n", device_xname(sc->sc_dev))); 743 1.7 mycroft 744 1.25 msaitoh if (xsc->sc_tx_loaded) 745 1.7 mycroft map = NULL; 746 1.25 msaitoh else { 747 1.7 mycroft map = xsc->sc_tx_dmamap; 748 1.7 mycroft xsc->sc_tx_loaded++; 749 1.7 mycroft } 750 1.7 mycroft 751 1.7 mycroft #ifdef DIAGNOSTIC 752 1.25 msaitoh if (xsc->sc_tx_loaded != 1) 753 1.22 chs panic("%s: sc->sc_tx_loaded is %d", device_xname(sc->sc_dev), 754 1.7 mycroft xsc->sc_tx_loaded); 755 1.7 mycroft #endif 756 1.7 mycroft 757 1.25 msaitoh return map; 758 1.1 dbj } 759