1178173Simp/*- 2178173Simp * Copyright (C) 2007 3178173Simp * Oleksandr Tymoshenko <gonzo@freebsd.org>. All rights reserved. 4178173Simp * 5178173Simp * Redistribution and use in source and binary forms, with or without 6178173Simp * modification, are permitted provided that the following conditions 7178173Simp * are met: 8178173Simp * 1. Redistributions of source code must retain the above copyright 9178173Simp * notice, this list of conditions and the following disclaimer. 10178173Simp * 2. Redistributions in binary form must reproduce the above copyright 11178173Simp * notice, this list of conditions and the following disclaimer in the 12178173Simp * documentation and/or other materials provided with the distribution. 13178173Simp * 14178173Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15178173Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16178173Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17178173Simp * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 18178173Simp * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19178173Simp * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20178173Simp * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21178173Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22178173Simp * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23178173Simp * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24178173Simp * THE POSSIBILITY OF SUCH DAMAGE. 25178173Simp * 26178173Simp * $Id: $ 27178173Simp * 28178173Simp */ 29178173Simp 30178173Simp#include <sys/cdefs.h> 31178173Simp__FBSDID("$FreeBSD$"); 32178173Simp 33178173Simp/* 34178173Simp * RC32434 Ethernet interface driver 35178173Simp */ 36178173Simp#include <sys/param.h> 37178173Simp#include <sys/endian.h> 38178173Simp#include <sys/systm.h> 39178173Simp#include <sys/sockio.h> 40178173Simp#include <sys/mbuf.h> 41178173Simp#include <sys/malloc.h> 42178173Simp#include <sys/kernel.h> 43257420Smarkj#include <sys/lock.h> 44178173Simp#include <sys/module.h> 45257420Smarkj#include <sys/mutex.h> 46178173Simp#include <sys/socket.h> 47178173Simp#include <sys/taskqueue.h> 48178173Simp 49178173Simp#include <net/if.h> 50178173Simp#include <net/if_arp.h> 51178173Simp#include <net/ethernet.h> 52178173Simp#include <net/if_dl.h> 53178173Simp#include <net/if_media.h> 54178173Simp#include <net/if_types.h> 55257420Smarkj#include <net/if_var.h> 56178173Simp 57178173Simp#include <net/bpf.h> 58178173Simp 59178173Simp#include <machine/bus.h> 60178173Simp#include <machine/resource.h> 61178173Simp#include <sys/bus.h> 62178173Simp#include <sys/rman.h> 63178173Simp 64178173Simp#include <dev/mii/mii.h> 65178173Simp#include <dev/mii/miivar.h> 66178173Simp 67178173Simp#include <dev/pci/pcireg.h> 68178173Simp#include <dev/pci/pcivar.h> 69178173Simp 70178173SimpMODULE_DEPEND(kr, ether, 1, 1, 1); 71178173SimpMODULE_DEPEND(kr, miibus, 1, 1, 1); 72178173Simp 73178173Simp#include "miibus_if.h" 74178173Simp 75182901Sgonzo#include <mips/idt/if_krreg.h> 76178173Simp 77178173Simp#define KR_DEBUG 78178173Simp 79178173Simpstatic int kr_attach(device_t); 80178173Simpstatic int kr_detach(device_t); 81178173Simpstatic int kr_ifmedia_upd(struct ifnet *); 82178173Simpstatic void kr_ifmedia_sts(struct ifnet *, struct ifmediareq *); 83178173Simpstatic int kr_ioctl(struct ifnet *, u_long, caddr_t); 84178173Simpstatic void kr_init(void *); 85178173Simpstatic void kr_init_locked(struct kr_softc *); 86178173Simpstatic void kr_link_task(void *, int); 87178173Simpstatic int kr_miibus_readreg(device_t, int, int); 88178173Simpstatic void kr_miibus_statchg(device_t); 89178173Simpstatic int kr_miibus_writereg(device_t, int, int, int); 90178173Simpstatic int kr_probe(device_t); 91178173Simpstatic void kr_reset(struct kr_softc *); 92178173Simpstatic int kr_resume(device_t); 93178173Simpstatic int kr_rx_ring_init(struct kr_softc *); 94178173Simpstatic int kr_tx_ring_init(struct kr_softc *); 95194342Sbzstatic int kr_shutdown(device_t); 96178173Simpstatic void kr_start(struct ifnet *); 97178173Simpstatic void kr_start_locked(struct ifnet *); 98178173Simpstatic void kr_stop(struct kr_softc *); 99178173Simpstatic int kr_suspend(device_t); 100178173Simp 101178173Simpstatic void kr_rx(struct kr_softc *); 102178173Simpstatic void kr_tx(struct kr_softc *); 103178173Simpstatic void kr_rx_intr(void *); 104178173Simpstatic void kr_tx_intr(void *); 105178173Simpstatic void kr_rx_und_intr(void *); 106178173Simpstatic void kr_tx_ovr_intr(void *); 107178173Simpstatic void kr_tick(void *); 108178173Simp 109178173Simpstatic void kr_dmamap_cb(void *, bus_dma_segment_t *, int, int); 110178173Simpstatic int kr_dma_alloc(struct kr_softc *); 111178173Simpstatic void kr_dma_free(struct kr_softc *); 112178173Simpstatic int kr_newbuf(struct kr_softc *, int); 113178173Simpstatic __inline void kr_fixup_rx(struct mbuf *); 114178173Simp 115178173Simpstatic device_method_t kr_methods[] = { 116178173Simp /* Device interface */ 117178173Simp DEVMETHOD(device_probe, kr_probe), 118178173Simp DEVMETHOD(device_attach, kr_attach), 119178173Simp DEVMETHOD(device_detach, kr_detach), 120178173Simp DEVMETHOD(device_suspend, kr_suspend), 121178173Simp DEVMETHOD(device_resume, kr_resume), 122178173Simp DEVMETHOD(device_shutdown, kr_shutdown), 123178173Simp 124178173Simp /* MII interface */ 125178173Simp DEVMETHOD(miibus_readreg, kr_miibus_readreg), 126178173Simp DEVMETHOD(miibus_writereg, kr_miibus_writereg), 127178173Simp DEVMETHOD(miibus_statchg, kr_miibus_statchg), 128178173Simp 129227843Smarius DEVMETHOD_END 130178173Simp}; 131178173Simp 132178173Simpstatic driver_t kr_driver = { 133178173Simp "kr", 134178173Simp kr_methods, 135178173Simp sizeof(struct kr_softc) 136178173Simp}; 137178173Simp 138178173Simpstatic devclass_t kr_devclass; 139178173Simp 140178173SimpDRIVER_MODULE(kr, obio, kr_driver, kr_devclass, 0, 0); 141178173SimpDRIVER_MODULE(miibus, kr, miibus_driver, miibus_devclass, 0, 0); 142178173Simp 143178173Simpstatic int 144178173Simpkr_probe(device_t dev) 145178173Simp{ 146178173Simp 147178173Simp device_set_desc(dev, "RC32434 Ethernet interface"); 148178173Simp return (0); 149178173Simp} 150178173Simp 151178173Simpstatic int 152178173Simpkr_attach(device_t dev) 153178173Simp{ 154178173Simp uint8_t eaddr[ETHER_ADDR_LEN]; 155178173Simp struct ifnet *ifp; 156178173Simp struct kr_softc *sc; 157178173Simp int error = 0, rid; 158178173Simp int unit; 159178173Simp 160178173Simp sc = device_get_softc(dev); 161178173Simp unit = device_get_unit(dev); 162178173Simp sc->kr_dev = dev; 163178173Simp 164178173Simp mtx_init(&sc->kr_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 165178173Simp MTX_DEF); 166178173Simp callout_init_mtx(&sc->kr_stat_callout, &sc->kr_mtx, 0); 167178173Simp TASK_INIT(&sc->kr_link_task, 0, kr_link_task, sc); 168178173Simp pci_enable_busmaster(dev); 169178173Simp 170178173Simp /* Map control/status registers. */ 171178173Simp sc->kr_rid = 0; 172178173Simp sc->kr_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->kr_rid, 173178173Simp RF_ACTIVE); 174178173Simp 175178173Simp if (sc->kr_res == NULL) { 176178173Simp device_printf(dev, "couldn't map memory\n"); 177178173Simp error = ENXIO; 178178173Simp goto fail; 179178173Simp } 180178173Simp 181178173Simp sc->kr_btag = rman_get_bustag(sc->kr_res); 182178173Simp sc->kr_bhandle = rman_get_bushandle(sc->kr_res); 183178173Simp 184178173Simp /* Allocate interrupts */ 185178173Simp rid = 0; 186178173Simp sc->kr_rx_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, KR_RX_IRQ, 187178173Simp KR_RX_IRQ, 1, RF_SHAREABLE | RF_ACTIVE); 188178173Simp 189178173Simp if (sc->kr_rx_irq == NULL) { 190178173Simp device_printf(dev, "couldn't map rx interrupt\n"); 191178173Simp error = ENXIO; 192178173Simp goto fail; 193178173Simp } 194178173Simp 195178173Simp rid = 0; 196178173Simp sc->kr_tx_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, KR_TX_IRQ, 197178173Simp KR_TX_IRQ, 1, RF_SHAREABLE | RF_ACTIVE); 198178173Simp 199178173Simp if (sc->kr_tx_irq == NULL) { 200178173Simp device_printf(dev, "couldn't map tx interrupt\n"); 201178173Simp error = ENXIO; 202178173Simp goto fail; 203178173Simp } 204178173Simp 205178173Simp rid = 0; 206178173Simp sc->kr_rx_und_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 207178173Simp KR_RX_UND_IRQ, KR_RX_UND_IRQ, 1, RF_SHAREABLE | RF_ACTIVE); 208178173Simp 209178173Simp if (sc->kr_rx_und_irq == NULL) { 210178173Simp device_printf(dev, "couldn't map rx underrun interrupt\n"); 211178173Simp error = ENXIO; 212178173Simp goto fail; 213178173Simp } 214178173Simp 215178173Simp rid = 0; 216178173Simp sc->kr_tx_ovr_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 217178173Simp KR_TX_OVR_IRQ, KR_TX_OVR_IRQ, 1, RF_SHAREABLE | RF_ACTIVE); 218178173Simp 219178173Simp if (sc->kr_tx_ovr_irq == NULL) { 220178173Simp device_printf(dev, "couldn't map tx overrun interrupt\n"); 221178173Simp error = ENXIO; 222178173Simp goto fail; 223178173Simp } 224178173Simp 225178173Simp /* Allocate ifnet structure. */ 226178173Simp ifp = sc->kr_ifp = if_alloc(IFT_ETHER); 227178173Simp 228178173Simp if (ifp == NULL) { 229178173Simp device_printf(dev, "couldn't allocate ifnet structure\n"); 230178173Simp error = ENOSPC; 231178173Simp goto fail; 232178173Simp } 233178173Simp ifp->if_softc = sc; 234178173Simp if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 235178173Simp ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 236178173Simp ifp->if_ioctl = kr_ioctl; 237178173Simp ifp->if_start = kr_start; 238178173Simp ifp->if_init = kr_init; 239178173Simp 240178173Simp /* XXX: add real size */ 241178173Simp IFQ_SET_MAXLEN(&ifp->if_snd, 9); 242178173Simp ifp->if_snd.ifq_maxlen = 9; 243178173Simp IFQ_SET_READY(&ifp->if_snd); 244178173Simp 245178173Simp ifp->if_capenable = ifp->if_capabilities; 246178173Simp 247178173Simp eaddr[0] = 0x00; 248178173Simp eaddr[1] = 0x0C; 249178173Simp eaddr[2] = 0x42; 250178173Simp eaddr[3] = 0x09; 251178173Simp eaddr[4] = 0x5E; 252178173Simp eaddr[5] = 0x6B; 253178173Simp 254178173Simp if (kr_dma_alloc(sc) != 0) { 255178173Simp error = ENXIO; 256178173Simp goto fail; 257178173Simp } 258178173Simp 259178173Simp /* TODO: calculate prescale */ 260178173Simp CSR_WRITE_4(sc, KR_ETHMCP, (165000000 / (1250000 + 1)) & ~1); 261178173Simp 262178173Simp CSR_WRITE_4(sc, KR_MIIMCFG, KR_MIIMCFG_R); 263178173Simp DELAY(1000); 264178173Simp CSR_WRITE_4(sc, KR_MIIMCFG, 0); 265178173Simp 266178173Simp /* Do MII setup. */ 267213894Smarius error = mii_attach(dev, &sc->kr_miibus, ifp, kr_ifmedia_upd, 268213894Smarius kr_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0); 269213894Smarius if (error != 0) { 270213894Smarius device_printf(dev, "attaching PHYs failed\n"); 271178173Simp goto fail; 272178173Simp } 273178173Simp 274178173Simp /* Call MI attach routine. */ 275178173Simp ether_ifattach(ifp, eaddr); 276178173Simp 277178173Simp /* Hook interrupt last to avoid having to lock softc */ 278178173Simp error = bus_setup_intr(dev, sc->kr_rx_irq, INTR_TYPE_NET | INTR_MPSAFE, 279178173Simp NULL, kr_rx_intr, sc, &sc->kr_rx_intrhand); 280178173Simp 281178173Simp if (error) { 282178173Simp device_printf(dev, "couldn't set up rx irq\n"); 283178173Simp ether_ifdetach(ifp); 284178173Simp goto fail; 285178173Simp } 286178173Simp 287178173Simp error = bus_setup_intr(dev, sc->kr_tx_irq, INTR_TYPE_NET | INTR_MPSAFE, 288178173Simp NULL, kr_tx_intr, sc, &sc->kr_tx_intrhand); 289178173Simp 290178173Simp if (error) { 291178173Simp device_printf(dev, "couldn't set up tx irq\n"); 292178173Simp ether_ifdetach(ifp); 293178173Simp goto fail; 294178173Simp } 295178173Simp 296178173Simp error = bus_setup_intr(dev, sc->kr_rx_und_irq, 297178173Simp INTR_TYPE_NET | INTR_MPSAFE, NULL, kr_rx_und_intr, sc, 298178173Simp &sc->kr_rx_und_intrhand); 299178173Simp 300178173Simp if (error) { 301178173Simp device_printf(dev, "couldn't set up rx underrun irq\n"); 302178173Simp ether_ifdetach(ifp); 303178173Simp goto fail; 304178173Simp } 305178173Simp 306178173Simp error = bus_setup_intr(dev, sc->kr_tx_ovr_irq, 307178173Simp INTR_TYPE_NET | INTR_MPSAFE, NULL, kr_tx_ovr_intr, sc, 308178173Simp &sc->kr_tx_ovr_intrhand); 309178173Simp 310178173Simp if (error) { 311178173Simp device_printf(dev, "couldn't set up tx overrun irq\n"); 312178173Simp ether_ifdetach(ifp); 313178173Simp goto fail; 314178173Simp } 315178173Simp 316178173Simpfail: 317178173Simp if (error) 318178173Simp kr_detach(dev); 319178173Simp 320178173Simp return (error); 321178173Simp} 322178173Simp 323178173Simpstatic int 324178173Simpkr_detach(device_t dev) 325178173Simp{ 326178173Simp struct kr_softc *sc = device_get_softc(dev); 327178173Simp struct ifnet *ifp = sc->kr_ifp; 328178173Simp 329178173Simp KASSERT(mtx_initialized(&sc->kr_mtx), ("vr mutex not initialized")); 330178173Simp 331178173Simp /* These should only be active if attach succeeded */ 332178173Simp if (device_is_attached(dev)) { 333178173Simp KR_LOCK(sc); 334178173Simp sc->kr_detach = 1; 335178173Simp kr_stop(sc); 336178173Simp KR_UNLOCK(sc); 337178173Simp taskqueue_drain(taskqueue_swi, &sc->kr_link_task); 338178173Simp ether_ifdetach(ifp); 339178173Simp } 340178173Simp if (sc->kr_miibus) 341178173Simp device_delete_child(dev, sc->kr_miibus); 342178173Simp bus_generic_detach(dev); 343178173Simp 344178173Simp if (sc->kr_rx_intrhand) 345178173Simp bus_teardown_intr(dev, sc->kr_rx_irq, sc->kr_rx_intrhand); 346178173Simp if (sc->kr_rx_irq) 347178173Simp bus_release_resource(dev, SYS_RES_IRQ, 0, sc->kr_rx_irq); 348178173Simp if (sc->kr_tx_intrhand) 349178173Simp bus_teardown_intr(dev, sc->kr_tx_irq, sc->kr_tx_intrhand); 350178173Simp if (sc->kr_tx_irq) 351178173Simp bus_release_resource(dev, SYS_RES_IRQ, 0, sc->kr_tx_irq); 352178173Simp if (sc->kr_rx_und_intrhand) 353178173Simp bus_teardown_intr(dev, sc->kr_rx_und_irq, 354178173Simp sc->kr_rx_und_intrhand); 355178173Simp if (sc->kr_rx_und_irq) 356178173Simp bus_release_resource(dev, SYS_RES_IRQ, 0, sc->kr_rx_und_irq); 357178173Simp if (sc->kr_tx_ovr_intrhand) 358178173Simp bus_teardown_intr(dev, sc->kr_tx_ovr_irq, 359178173Simp sc->kr_tx_ovr_intrhand); 360178173Simp if (sc->kr_tx_ovr_irq) 361178173Simp bus_release_resource(dev, SYS_RES_IRQ, 0, sc->kr_tx_ovr_irq); 362178173Simp 363178173Simp if (sc->kr_res) 364178173Simp bus_release_resource(dev, SYS_RES_MEMORY, sc->kr_rid, 365178173Simp sc->kr_res); 366178173Simp 367178173Simp if (ifp) 368178173Simp if_free(ifp); 369178173Simp 370178173Simp kr_dma_free(sc); 371178173Simp 372178173Simp mtx_destroy(&sc->kr_mtx); 373178173Simp 374178173Simp return (0); 375178173Simp 376178173Simp} 377178173Simp 378178173Simpstatic int 379178173Simpkr_suspend(device_t dev) 380178173Simp{ 381178173Simp 382178173Simp panic("%s", __func__); 383178173Simp return 0; 384178173Simp} 385178173Simp 386178173Simpstatic int 387178173Simpkr_resume(device_t dev) 388178173Simp{ 389178173Simp 390178173Simp panic("%s", __func__); 391178173Simp return 0; 392178173Simp} 393178173Simp 394194342Sbzstatic int 395178173Simpkr_shutdown(device_t dev) 396178173Simp{ 397178173Simp struct kr_softc *sc; 398178173Simp 399178173Simp sc = device_get_softc(dev); 400178173Simp 401178173Simp KR_LOCK(sc); 402178173Simp kr_stop(sc); 403178173Simp KR_UNLOCK(sc); 404194342Sbz 405194342Sbz return (0); 406178173Simp} 407178173Simp 408178173Simpstatic int 409178173Simpkr_miibus_readreg(device_t dev, int phy, int reg) 410178173Simp{ 411178173Simp struct kr_softc * sc = device_get_softc(dev); 412178173Simp int i, result; 413178173Simp 414178173Simp i = KR_MII_TIMEOUT; 415178173Simp while ((CSR_READ_4(sc, KR_MIIMIND) & KR_MIIMIND_BSY) && i) 416178173Simp i--; 417178173Simp 418178173Simp if (i == 0) 419178173Simp device_printf(dev, "phy mii is busy %d:%d\n", phy, reg); 420178173Simp 421178173Simp CSR_WRITE_4(sc, KR_MIIMADDR, (phy << 8) | reg); 422178173Simp 423178173Simp i = KR_MII_TIMEOUT; 424178173Simp while ((CSR_READ_4(sc, KR_MIIMIND) & KR_MIIMIND_BSY) && i) 425178173Simp i--; 426178173Simp 427178173Simp if (i == 0) 428178173Simp device_printf(dev, "phy mii is busy %d:%d\n", phy, reg); 429178173Simp 430178173Simp CSR_WRITE_4(sc, KR_MIIMCMD, KR_MIIMCMD_RD); 431178173Simp 432178173Simp i = KR_MII_TIMEOUT; 433178173Simp while ((CSR_READ_4(sc, KR_MIIMIND) & KR_MIIMIND_BSY) && i) 434178173Simp i--; 435178173Simp 436178173Simp if (i == 0) 437178173Simp device_printf(dev, "phy mii read is timed out %d:%d\n", phy, 438178173Simp reg); 439178173Simp 440178173Simp if (CSR_READ_4(sc, KR_MIIMIND) & KR_MIIMIND_NV) 441178173Simp printf("phy mii readreg failed %d:%d: data not valid\n", 442178173Simp phy, reg); 443178173Simp 444178173Simp result = CSR_READ_4(sc , KR_MIIMRDD); 445178173Simp CSR_WRITE_4(sc, KR_MIIMCMD, 0); 446178173Simp 447178173Simp return (result); 448178173Simp} 449178173Simp 450178173Simpstatic int 451178173Simpkr_miibus_writereg(device_t dev, int phy, int reg, int data) 452178173Simp{ 453178173Simp struct kr_softc * sc = device_get_softc(dev); 454178173Simp int i; 455178173Simp 456178173Simp i = KR_MII_TIMEOUT; 457178173Simp while ((CSR_READ_4(sc, KR_MIIMIND) & KR_MIIMIND_BSY) && i) 458178173Simp i--; 459178173Simp 460178173Simp if (i == 0) 461178173Simp device_printf(dev, "phy mii is busy %d:%d\n", phy, reg); 462178173Simp 463178173Simp CSR_WRITE_4(sc, KR_MIIMADDR, (phy << 8) | reg); 464178173Simp 465178173Simp i = KR_MII_TIMEOUT; 466178173Simp while ((CSR_READ_4(sc, KR_MIIMIND) & KR_MIIMIND_BSY) && i) 467178173Simp i--; 468178173Simp 469178173Simp if (i == 0) 470178173Simp device_printf(dev, "phy mii is busy %d:%d\n", phy, reg); 471178173Simp 472178173Simp CSR_WRITE_4(sc, KR_MIIMWTD, data); 473178173Simp 474178173Simp i = KR_MII_TIMEOUT; 475178173Simp while ((CSR_READ_4(sc, KR_MIIMIND) & KR_MIIMIND_BSY) && i) 476178173Simp i--; 477178173Simp 478178173Simp if (i == 0) 479178173Simp device_printf(dev, "phy mii is busy %d:%d\n", phy, reg); 480178173Simp 481178173Simp return (0); 482178173Simp} 483178173Simp 484178173Simpstatic void 485178173Simpkr_miibus_statchg(device_t dev) 486178173Simp{ 487178173Simp struct kr_softc *sc; 488178173Simp 489178173Simp sc = device_get_softc(dev); 490178173Simp taskqueue_enqueue(taskqueue_swi, &sc->kr_link_task); 491178173Simp} 492178173Simp 493178173Simpstatic void 494178173Simpkr_link_task(void *arg, int pending) 495178173Simp{ 496178173Simp struct kr_softc *sc; 497178173Simp struct mii_data *mii; 498178173Simp struct ifnet *ifp; 499178173Simp /* int lfdx, mfdx; */ 500178173Simp 501178173Simp sc = (struct kr_softc *)arg; 502178173Simp 503178173Simp KR_LOCK(sc); 504178173Simp mii = device_get_softc(sc->kr_miibus); 505178173Simp ifp = sc->kr_ifp; 506178173Simp if (mii == NULL || ifp == NULL || 507178173Simp (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 508178173Simp KR_UNLOCK(sc); 509178173Simp return; 510178173Simp } 511178173Simp 512178173Simp if (mii->mii_media_status & IFM_ACTIVE) { 513178173Simp if (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) 514178173Simp sc->kr_link_status = 1; 515178173Simp } else 516178173Simp sc->kr_link_status = 0; 517178173Simp 518178173Simp KR_UNLOCK(sc); 519178173Simp} 520178173Simp 521178173Simpstatic void 522178173Simpkr_reset(struct kr_softc *sc) 523178173Simp{ 524178173Simp int i; 525178173Simp 526178173Simp CSR_WRITE_4(sc, KR_ETHINTFC, 0); 527178173Simp 528178173Simp for (i = 0; i < KR_TIMEOUT; i++) { 529178173Simp DELAY(10); 530178173Simp if (!(CSR_READ_4(sc, KR_ETHINTFC) & ETH_INTFC_RIP)) 531178173Simp break; 532178173Simp } 533178173Simp 534178173Simp if (i == KR_TIMEOUT) 535178173Simp device_printf(sc->kr_dev, "reset time out\n"); 536178173Simp} 537178173Simp 538178173Simpstatic void 539178173Simpkr_init(void *xsc) 540178173Simp{ 541178173Simp struct kr_softc *sc = xsc; 542178173Simp 543178173Simp KR_LOCK(sc); 544178173Simp kr_init_locked(sc); 545178173Simp KR_UNLOCK(sc); 546178173Simp} 547178173Simp 548178173Simpstatic void 549178173Simpkr_init_locked(struct kr_softc *sc) 550178173Simp{ 551178173Simp struct ifnet *ifp = sc->kr_ifp; 552178173Simp struct mii_data *mii; 553178173Simp 554178173Simp KR_LOCK_ASSERT(sc); 555178173Simp 556178173Simp mii = device_get_softc(sc->kr_miibus); 557178173Simp 558178173Simp kr_stop(sc); 559178173Simp kr_reset(sc); 560178173Simp 561178173Simp CSR_WRITE_4(sc, KR_ETHINTFC, ETH_INTFC_EN); 562178173Simp 563178173Simp /* Init circular RX list. */ 564178173Simp if (kr_rx_ring_init(sc) != 0) { 565178173Simp device_printf(sc->kr_dev, 566178173Simp "initialization failed: no memory for rx buffers\n"); 567178173Simp kr_stop(sc); 568178173Simp return; 569178173Simp } 570178173Simp 571178173Simp /* Init tx descriptors. */ 572178173Simp kr_tx_ring_init(sc); 573178173Simp 574178173Simp KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_S, 0); 575178173Simp KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_NDPTR, 0); 576178173Simp KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_DPTR, 577178173Simp sc->kr_rdata.kr_rx_ring_paddr); 578178173Simp 579178173Simp 580178173Simp KR_DMA_CLEARBITS_REG(KR_DMA_RXCHAN, DMA_SM, 581178173Simp DMA_SM_H | DMA_SM_E | DMA_SM_D) ; 582178173Simp 583178173Simp KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_S, 0); 584178173Simp KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_NDPTR, 0); 585178173Simp KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_DPTR, 0); 586178173Simp KR_DMA_CLEARBITS_REG(KR_DMA_TXCHAN, DMA_SM, 587178173Simp DMA_SM_F | DMA_SM_E); 588178173Simp 589178173Simp 590178173Simp /* Accept only packets destined for THIS Ethernet device address */ 591178173Simp CSR_WRITE_4(sc, KR_ETHARC, 1); 592178173Simp 593178173Simp /* 594178173Simp * Set all Ethernet address registers to the same initial values 595178173Simp * set all four addresses to 66-88-aa-cc-dd-ee 596178173Simp */ 597178173Simp CSR_WRITE_4(sc, KR_ETHSAL0, 0x42095E6B); 598178173Simp CSR_WRITE_4(sc, KR_ETHSAH0, 0x0000000C); 599178173Simp 600178173Simp CSR_WRITE_4(sc, KR_ETHSAL1, 0x42095E6B); 601178173Simp CSR_WRITE_4(sc, KR_ETHSAH1, 0x0000000C); 602178173Simp 603178173Simp CSR_WRITE_4(sc, KR_ETHSAL2, 0x42095E6B); 604178173Simp CSR_WRITE_4(sc, KR_ETHSAH2, 0x0000000C); 605178173Simp 606178173Simp CSR_WRITE_4(sc, KR_ETHSAL3, 0x42095E6B); 607178173Simp CSR_WRITE_4(sc, KR_ETHSAH3, 0x0000000C); 608178173Simp 609178173Simp CSR_WRITE_4(sc, KR_ETHMAC2, 610178173Simp KR_ETH_MAC2_PEN | KR_ETH_MAC2_CEN | KR_ETH_MAC2_FD); 611178173Simp 612178173Simp CSR_WRITE_4(sc, KR_ETHIPGT, KR_ETHIPGT_FULL_DUPLEX); 613178173Simp CSR_WRITE_4(sc, KR_ETHIPGR, 0x12); /* minimum value */ 614178173Simp 615178173Simp CSR_WRITE_4(sc, KR_MIIMCFG, KR_MIIMCFG_R); 616178173Simp DELAY(1000); 617178173Simp CSR_WRITE_4(sc, KR_MIIMCFG, 0); 618178173Simp 619178173Simp /* TODO: calculate prescale */ 620178173Simp CSR_WRITE_4(sc, KR_ETHMCP, (165000000 / (1250000 + 1)) & ~1); 621178173Simp 622178173Simp /* FIFO Tx threshold level */ 623178173Simp CSR_WRITE_4(sc, KR_ETHFIFOTT, 0x30); 624178173Simp 625178173Simp CSR_WRITE_4(sc, KR_ETHMAC1, KR_ETH_MAC1_RE); 626178173Simp 627178173Simp sc->kr_link_status = 0; 628178173Simp mii_mediachg(mii); 629178173Simp 630178173Simp ifp->if_drv_flags |= IFF_DRV_RUNNING; 631178173Simp ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 632178173Simp 633178173Simp callout_reset(&sc->kr_stat_callout, hz, kr_tick, sc); 634178173Simp} 635178173Simp 636178173Simpstatic void 637178173Simpkr_start(struct ifnet *ifp) 638178173Simp{ 639178173Simp struct kr_softc *sc; 640178173Simp 641178173Simp sc = ifp->if_softc; 642178173Simp 643178173Simp KR_LOCK(sc); 644178173Simp kr_start_locked(ifp); 645178173Simp KR_UNLOCK(sc); 646178173Simp} 647178173Simp 648178173Simp/* 649178173Simp * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data 650178173Simp * pointers to the fragment pointers. 651178173Simp */ 652178173Simpstatic int 653178173Simpkr_encap(struct kr_softc *sc, struct mbuf **m_head) 654178173Simp{ 655178173Simp struct kr_txdesc *txd; 656178173Simp struct kr_desc *desc, *prev_desc; 657178173Simp bus_dma_segment_t txsegs[KR_MAXFRAGS]; 658178173Simp uint32_t link_addr; 659178173Simp int error, i, nsegs, prod, si, prev_prod; 660178173Simp 661178173Simp KR_LOCK_ASSERT(sc); 662178173Simp 663178173Simp prod = sc->kr_cdata.kr_tx_prod; 664178173Simp txd = &sc->kr_cdata.kr_txdesc[prod]; 665178173Simp error = bus_dmamap_load_mbuf_sg(sc->kr_cdata.kr_tx_tag, txd->tx_dmamap, 666178173Simp *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT); 667178173Simp if (error == EFBIG) { 668178173Simp panic("EFBIG"); 669178173Simp } else if (error != 0) 670178173Simp return (error); 671178173Simp if (nsegs == 0) { 672178173Simp m_freem(*m_head); 673178173Simp *m_head = NULL; 674178173Simp return (EIO); 675178173Simp } 676178173Simp 677178173Simp /* Check number of available descriptors. */ 678178173Simp if (sc->kr_cdata.kr_tx_cnt + nsegs >= (KR_TX_RING_CNT - 1)) { 679178173Simp bus_dmamap_unload(sc->kr_cdata.kr_tx_tag, txd->tx_dmamap); 680178173Simp return (ENOBUFS); 681178173Simp } 682178173Simp 683178173Simp txd->tx_m = *m_head; 684178173Simp bus_dmamap_sync(sc->kr_cdata.kr_tx_tag, txd->tx_dmamap, 685178173Simp BUS_DMASYNC_PREWRITE); 686178173Simp 687178173Simp si = prod; 688178173Simp 689178173Simp /* 690178173Simp * Make a list of descriptors for this packet. DMA controller will 691178173Simp * walk through it while kr_link is not zero. The last one should 692178173Simp * have COF flag set, to pickup next chain from NDPTR 693178173Simp */ 694178173Simp prev_prod = prod; 695178173Simp desc = prev_desc = NULL; 696178173Simp for (i = 0; i < nsegs; i++) { 697178173Simp desc = &sc->kr_rdata.kr_tx_ring[prod]; 698178173Simp desc->kr_ctl = KR_DMASIZE(txsegs[i].ds_len) | KR_CTL_IOF; 699178173Simp if (i == 0) 700178173Simp desc->kr_devcs = KR_DMATX_DEVCS_FD; 701178173Simp desc->kr_ca = txsegs[i].ds_addr; 702178173Simp desc->kr_link = 0; 703178173Simp /* link with previous descriptor */ 704178173Simp if (prev_desc) 705178173Simp prev_desc->kr_link = KR_TX_RING_ADDR(sc, prod); 706178173Simp 707178173Simp sc->kr_cdata.kr_tx_cnt++; 708178173Simp prev_desc = desc; 709178173Simp KR_INC(prod, KR_TX_RING_CNT); 710178173Simp } 711178173Simp 712178173Simp /* 713178173Simp * Set COF for last descriptor and mark last fragment with LD flag 714178173Simp */ 715178173Simp if (desc) { 716178173Simp desc->kr_ctl |= KR_CTL_COF; 717178173Simp desc->kr_devcs |= KR_DMATX_DEVCS_LD; 718178173Simp } 719178173Simp 720178173Simp /* Update producer index. */ 721178173Simp sc->kr_cdata.kr_tx_prod = prod; 722178173Simp 723178173Simp /* Sync descriptors. */ 724178173Simp bus_dmamap_sync(sc->kr_cdata.kr_tx_ring_tag, 725178173Simp sc->kr_cdata.kr_tx_ring_map, 726178173Simp BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 727178173Simp 728178173Simp /* Start transmitting */ 729178173Simp /* Check if new list is queued in NDPTR */ 730178173Simp if (KR_DMA_READ_REG(KR_DMA_TXCHAN, DMA_NDPTR) == 0) { 731178173Simp /* NDPTR is not busy - start new list */ 732178173Simp KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_NDPTR, 733178173Simp KR_TX_RING_ADDR(sc, si)); 734178173Simp } 735178173Simp else { 736178173Simp link_addr = KR_TX_RING_ADDR(sc, si); 737178173Simp /* Get previous descriptor */ 738178173Simp si = (si + KR_TX_RING_CNT - 1) % KR_TX_RING_CNT; 739178173Simp desc = &sc->kr_rdata.kr_tx_ring[si]; 740178173Simp desc->kr_link = link_addr; 741178173Simp } 742178173Simp 743178173Simp return (0); 744178173Simp} 745178173Simp 746178173Simpstatic void 747178173Simpkr_start_locked(struct ifnet *ifp) 748178173Simp{ 749178173Simp struct kr_softc *sc; 750178173Simp struct mbuf *m_head; 751178173Simp int enq; 752178173Simp 753178173Simp sc = ifp->if_softc; 754178173Simp 755178173Simp KR_LOCK_ASSERT(sc); 756178173Simp 757178173Simp if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 758178173Simp IFF_DRV_RUNNING || sc->kr_link_status == 0 ) 759178173Simp return; 760178173Simp 761178173Simp for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && 762178173Simp sc->kr_cdata.kr_tx_cnt < KR_TX_RING_CNT - 2; ) { 763178173Simp IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 764178173Simp if (m_head == NULL) 765178173Simp break; 766178173Simp /* 767178173Simp * Pack the data into the transmit ring. If we 768178173Simp * don't have room, set the OACTIVE flag and wait 769178173Simp * for the NIC to drain the ring. 770178173Simp */ 771178173Simp if (kr_encap(sc, &m_head)) { 772178173Simp if (m_head == NULL) 773178173Simp break; 774178173Simp IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 775178173Simp ifp->if_drv_flags |= IFF_DRV_OACTIVE; 776178173Simp break; 777178173Simp } 778178173Simp 779178173Simp enq++; 780178173Simp /* 781178173Simp * If there's a BPF listener, bounce a copy of this frame 782178173Simp * to him. 783178173Simp */ 784178173Simp ETHER_BPF_MTAP(ifp, m_head); 785178173Simp } 786178173Simp} 787178173Simp 788178173Simpstatic void 789178173Simpkr_stop(struct kr_softc *sc) 790178173Simp{ 791178173Simp struct ifnet *ifp; 792178173Simp 793178173Simp KR_LOCK_ASSERT(sc); 794178173Simp 795178173Simp 796178173Simp ifp = sc->kr_ifp; 797178173Simp ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 798178173Simp callout_stop(&sc->kr_stat_callout); 799178173Simp 800178173Simp /* mask out RX interrupts */ 801178173Simp KR_DMA_SETBITS_REG(KR_DMA_RXCHAN, DMA_SM, 802178173Simp DMA_SM_D | DMA_SM_H | DMA_SM_E); 803178173Simp 804178173Simp /* mask out TX interrupts */ 805178173Simp KR_DMA_SETBITS_REG(KR_DMA_TXCHAN, DMA_SM, 806178173Simp DMA_SM_F | DMA_SM_E); 807178173Simp 808178173Simp /* Abort RX DMA transactions */ 809178173Simp if (KR_DMA_READ_REG(KR_DMA_RXCHAN, DMA_C) & DMA_C_R) { 810178173Simp /* Set ABORT bit if trunsuction is in progress */ 811178173Simp KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_C, DMA_C_ABORT); 812178173Simp /* XXX: Add timeout */ 813178173Simp while ((KR_DMA_READ_REG(KR_DMA_RXCHAN, DMA_S) & DMA_S_H) == 0) 814178173Simp DELAY(10); 815178173Simp KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_S, 0); 816178173Simp } 817178173Simp KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_DPTR, 0); 818178173Simp KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_NDPTR, 0); 819178173Simp 820178173Simp /* Abort TX DMA transactions */ 821178173Simp if (KR_DMA_READ_REG(KR_DMA_TXCHAN, DMA_C) & DMA_C_R) { 822178173Simp /* Set ABORT bit if trunsuction is in progress */ 823178173Simp KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_C, DMA_C_ABORT); 824178173Simp /* XXX: Add timeout */ 825178173Simp while ((KR_DMA_READ_REG(KR_DMA_TXCHAN, DMA_S) & DMA_S_H) == 0) 826178173Simp DELAY(10); 827178173Simp KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_S, 0); 828178173Simp } 829178173Simp KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_DPTR, 0); 830178173Simp KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_NDPTR, 0); 831178173Simp 832178173Simp CSR_WRITE_4(sc, KR_ETHINTFC, 0); 833178173Simp} 834178173Simp 835178173Simp 836178173Simpstatic int 837178173Simpkr_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 838178173Simp{ 839178173Simp struct kr_softc *sc = ifp->if_softc; 840178173Simp struct ifreq *ifr = (struct ifreq *) data; 841178173Simp struct mii_data *mii; 842178173Simp int error; 843178173Simp 844178173Simp switch (command) { 845178173Simp case SIOCSIFFLAGS: 846178173Simp#if 0 847178173Simp KR_LOCK(sc); 848178173Simp if (ifp->if_flags & IFF_UP) { 849178173Simp if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 850178173Simp if ((ifp->if_flags ^ sc->kr_if_flags) & 851178173Simp (IFF_PROMISC | IFF_ALLMULTI)) 852178173Simp kr_set_filter(sc); 853178173Simp } else { 854178173Simp if (sc->kr_detach == 0) 855178173Simp kr_init_locked(sc); 856178173Simp } 857178173Simp } else { 858178173Simp if (ifp->if_drv_flags & IFF_DRV_RUNNING) 859178173Simp kr_stop(sc); 860178173Simp } 861178173Simp sc->kr_if_flags = ifp->if_flags; 862178173Simp KR_UNLOCK(sc); 863178173Simp#endif 864178173Simp error = 0; 865178173Simp break; 866178173Simp case SIOCADDMULTI: 867178173Simp case SIOCDELMULTI: 868178173Simp#if 0 869178173Simp KR_LOCK(sc); 870178173Simp kr_set_filter(sc); 871178173Simp KR_UNLOCK(sc); 872178173Simp#endif 873178173Simp error = 0; 874178173Simp break; 875178173Simp case SIOCGIFMEDIA: 876178173Simp case SIOCSIFMEDIA: 877178173Simp mii = device_get_softc(sc->kr_miibus); 878178173Simp error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); 879178173Simp break; 880178173Simp case SIOCSIFCAP: 881178173Simp error = 0; 882178173Simp#if 0 883178173Simp mask = ifr->ifr_reqcap ^ ifp->if_capenable; 884178173Simp if ((mask & IFCAP_HWCSUM) != 0) { 885178173Simp ifp->if_capenable ^= IFCAP_HWCSUM; 886178173Simp if ((IFCAP_HWCSUM & ifp->if_capenable) && 887178173Simp (IFCAP_HWCSUM & ifp->if_capabilities)) 888178173Simp ifp->if_hwassist = KR_CSUM_FEATURES; 889178173Simp else 890178173Simp ifp->if_hwassist = 0; 891178173Simp } 892178173Simp if ((mask & IFCAP_VLAN_HWTAGGING) != 0) { 893178173Simp ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 894178173Simp if (IFCAP_VLAN_HWTAGGING & ifp->if_capenable && 895178173Simp IFCAP_VLAN_HWTAGGING & ifp->if_capabilities && 896178173Simp ifp->if_drv_flags & IFF_DRV_RUNNING) { 897178173Simp KR_LOCK(sc); 898178173Simp kr_vlan_setup(sc); 899178173Simp KR_UNLOCK(sc); 900178173Simp } 901178173Simp } 902178173Simp VLAN_CAPABILITIES(ifp); 903178173Simp#endif 904178173Simp break; 905178173Simp default: 906178173Simp error = ether_ioctl(ifp, command, data); 907178173Simp break; 908178173Simp } 909178173Simp 910178173Simp return (error); 911178173Simp} 912178173Simp 913178173Simp/* 914178173Simp * Set media options. 915178173Simp */ 916178173Simpstatic int 917178173Simpkr_ifmedia_upd(struct ifnet *ifp) 918178173Simp{ 919178173Simp struct kr_softc *sc; 920178173Simp struct mii_data *mii; 921178173Simp struct mii_softc *miisc; 922178173Simp int error; 923178173Simp 924178173Simp sc = ifp->if_softc; 925178173Simp KR_LOCK(sc); 926178173Simp mii = device_get_softc(sc->kr_miibus); 927221407Smarius LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 928221407Smarius PHY_RESET(miisc); 929178173Simp error = mii_mediachg(mii); 930178173Simp KR_UNLOCK(sc); 931178173Simp 932178173Simp return (error); 933178173Simp} 934178173Simp 935178173Simp/* 936178173Simp * Report current media status. 937178173Simp */ 938178173Simpstatic void 939178173Simpkr_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 940178173Simp{ 941178173Simp struct kr_softc *sc = ifp->if_softc; 942178173Simp struct mii_data *mii; 943178173Simp 944178173Simp mii = device_get_softc(sc->kr_miibus); 945178173Simp KR_LOCK(sc); 946178173Simp mii_pollstat(mii); 947178173Simp ifmr->ifm_active = mii->mii_media_active; 948178173Simp ifmr->ifm_status = mii->mii_media_status; 949226478Syongari KR_UNLOCK(sc); 950178173Simp} 951178173Simp 952178173Simpstruct kr_dmamap_arg { 953178173Simp bus_addr_t kr_busaddr; 954178173Simp}; 955178173Simp 956178173Simpstatic void 957178173Simpkr_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 958178173Simp{ 959178173Simp struct kr_dmamap_arg *ctx; 960178173Simp 961178173Simp if (error != 0) 962178173Simp return; 963178173Simp ctx = arg; 964178173Simp ctx->kr_busaddr = segs[0].ds_addr; 965178173Simp} 966178173Simp 967178173Simpstatic int 968178173Simpkr_dma_alloc(struct kr_softc *sc) 969178173Simp{ 970178173Simp struct kr_dmamap_arg ctx; 971178173Simp struct kr_txdesc *txd; 972178173Simp struct kr_rxdesc *rxd; 973178173Simp int error, i; 974178173Simp 975178173Simp /* Create parent DMA tag. */ 976178173Simp error = bus_dma_tag_create( 977178173Simp bus_get_dma_tag(sc->kr_dev), /* parent */ 978178173Simp 1, 0, /* alignment, boundary */ 979178173Simp BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 980178173Simp BUS_SPACE_MAXADDR, /* highaddr */ 981178173Simp NULL, NULL, /* filter, filterarg */ 982178173Simp BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ 983178173Simp 0, /* nsegments */ 984178173Simp BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 985178173Simp 0, /* flags */ 986178173Simp NULL, NULL, /* lockfunc, lockarg */ 987178173Simp &sc->kr_cdata.kr_parent_tag); 988178173Simp if (error != 0) { 989178173Simp device_printf(sc->kr_dev, "failed to create parent DMA tag\n"); 990178173Simp goto fail; 991178173Simp } 992178173Simp /* Create tag for Tx ring. */ 993178173Simp error = bus_dma_tag_create( 994178173Simp sc->kr_cdata.kr_parent_tag, /* parent */ 995178173Simp KR_RING_ALIGN, 0, /* alignment, boundary */ 996178173Simp BUS_SPACE_MAXADDR, /* lowaddr */ 997178173Simp BUS_SPACE_MAXADDR, /* highaddr */ 998178173Simp NULL, NULL, /* filter, filterarg */ 999178173Simp KR_TX_RING_SIZE, /* maxsize */ 1000178173Simp 1, /* nsegments */ 1001178173Simp KR_TX_RING_SIZE, /* maxsegsize */ 1002178173Simp 0, /* flags */ 1003178173Simp NULL, NULL, /* lockfunc, lockarg */ 1004178173Simp &sc->kr_cdata.kr_tx_ring_tag); 1005178173Simp if (error != 0) { 1006178173Simp device_printf(sc->kr_dev, "failed to create Tx ring DMA tag\n"); 1007178173Simp goto fail; 1008178173Simp } 1009178173Simp 1010178173Simp /* Create tag for Rx ring. */ 1011178173Simp error = bus_dma_tag_create( 1012178173Simp sc->kr_cdata.kr_parent_tag, /* parent */ 1013178173Simp KR_RING_ALIGN, 0, /* alignment, boundary */ 1014178173Simp BUS_SPACE_MAXADDR, /* lowaddr */ 1015178173Simp BUS_SPACE_MAXADDR, /* highaddr */ 1016178173Simp NULL, NULL, /* filter, filterarg */ 1017178173Simp KR_RX_RING_SIZE, /* maxsize */ 1018178173Simp 1, /* nsegments */ 1019178173Simp KR_RX_RING_SIZE, /* maxsegsize */ 1020178173Simp 0, /* flags */ 1021178173Simp NULL, NULL, /* lockfunc, lockarg */ 1022178173Simp &sc->kr_cdata.kr_rx_ring_tag); 1023178173Simp if (error != 0) { 1024178173Simp device_printf(sc->kr_dev, "failed to create Rx ring DMA tag\n"); 1025178173Simp goto fail; 1026178173Simp } 1027178173Simp 1028178173Simp /* Create tag for Tx buffers. */ 1029178173Simp error = bus_dma_tag_create( 1030178173Simp sc->kr_cdata.kr_parent_tag, /* parent */ 1031178173Simp sizeof(uint32_t), 0, /* alignment, boundary */ 1032178173Simp BUS_SPACE_MAXADDR, /* lowaddr */ 1033178173Simp BUS_SPACE_MAXADDR, /* highaddr */ 1034178173Simp NULL, NULL, /* filter, filterarg */ 1035178173Simp MCLBYTES * KR_MAXFRAGS, /* maxsize */ 1036178173Simp KR_MAXFRAGS, /* nsegments */ 1037178173Simp MCLBYTES, /* maxsegsize */ 1038178173Simp 0, /* flags */ 1039178173Simp NULL, NULL, /* lockfunc, lockarg */ 1040178173Simp &sc->kr_cdata.kr_tx_tag); 1041178173Simp if (error != 0) { 1042178173Simp device_printf(sc->kr_dev, "failed to create Tx DMA tag\n"); 1043178173Simp goto fail; 1044178173Simp } 1045178173Simp 1046178173Simp /* Create tag for Rx buffers. */ 1047178173Simp error = bus_dma_tag_create( 1048178173Simp sc->kr_cdata.kr_parent_tag, /* parent */ 1049178173Simp KR_RX_ALIGN, 0, /* alignment, boundary */ 1050178173Simp BUS_SPACE_MAXADDR, /* lowaddr */ 1051178173Simp BUS_SPACE_MAXADDR, /* highaddr */ 1052178173Simp NULL, NULL, /* filter, filterarg */ 1053178173Simp MCLBYTES, /* maxsize */ 1054178173Simp 1, /* nsegments */ 1055178173Simp MCLBYTES, /* maxsegsize */ 1056178173Simp 0, /* flags */ 1057178173Simp NULL, NULL, /* lockfunc, lockarg */ 1058178173Simp &sc->kr_cdata.kr_rx_tag); 1059178173Simp if (error != 0) { 1060178173Simp device_printf(sc->kr_dev, "failed to create Rx DMA tag\n"); 1061178173Simp goto fail; 1062178173Simp } 1063178173Simp 1064178173Simp /* Allocate DMA'able memory and load the DMA map for Tx ring. */ 1065178173Simp error = bus_dmamem_alloc(sc->kr_cdata.kr_tx_ring_tag, 1066178173Simp (void **)&sc->kr_rdata.kr_tx_ring, BUS_DMA_WAITOK | 1067178173Simp BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->kr_cdata.kr_tx_ring_map); 1068178173Simp if (error != 0) { 1069178173Simp device_printf(sc->kr_dev, 1070178173Simp "failed to allocate DMA'able memory for Tx ring\n"); 1071178173Simp goto fail; 1072178173Simp } 1073178173Simp 1074178173Simp ctx.kr_busaddr = 0; 1075178173Simp error = bus_dmamap_load(sc->kr_cdata.kr_tx_ring_tag, 1076178173Simp sc->kr_cdata.kr_tx_ring_map, sc->kr_rdata.kr_tx_ring, 1077178173Simp KR_TX_RING_SIZE, kr_dmamap_cb, &ctx, 0); 1078178173Simp if (error != 0 || ctx.kr_busaddr == 0) { 1079178173Simp device_printf(sc->kr_dev, 1080178173Simp "failed to load DMA'able memory for Tx ring\n"); 1081178173Simp goto fail; 1082178173Simp } 1083178173Simp sc->kr_rdata.kr_tx_ring_paddr = ctx.kr_busaddr; 1084178173Simp 1085178173Simp /* Allocate DMA'able memory and load the DMA map for Rx ring. */ 1086178173Simp error = bus_dmamem_alloc(sc->kr_cdata.kr_rx_ring_tag, 1087178173Simp (void **)&sc->kr_rdata.kr_rx_ring, BUS_DMA_WAITOK | 1088178173Simp BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->kr_cdata.kr_rx_ring_map); 1089178173Simp if (error != 0) { 1090178173Simp device_printf(sc->kr_dev, 1091178173Simp "failed to allocate DMA'able memory for Rx ring\n"); 1092178173Simp goto fail; 1093178173Simp } 1094178173Simp 1095178173Simp ctx.kr_busaddr = 0; 1096178173Simp error = bus_dmamap_load(sc->kr_cdata.kr_rx_ring_tag, 1097178173Simp sc->kr_cdata.kr_rx_ring_map, sc->kr_rdata.kr_rx_ring, 1098178173Simp KR_RX_RING_SIZE, kr_dmamap_cb, &ctx, 0); 1099178173Simp if (error != 0 || ctx.kr_busaddr == 0) { 1100178173Simp device_printf(sc->kr_dev, 1101178173Simp "failed to load DMA'able memory for Rx ring\n"); 1102178173Simp goto fail; 1103178173Simp } 1104178173Simp sc->kr_rdata.kr_rx_ring_paddr = ctx.kr_busaddr; 1105178173Simp 1106178173Simp /* Create DMA maps for Tx buffers. */ 1107178173Simp for (i = 0; i < KR_TX_RING_CNT; i++) { 1108178173Simp txd = &sc->kr_cdata.kr_txdesc[i]; 1109178173Simp txd->tx_m = NULL; 1110178173Simp txd->tx_dmamap = NULL; 1111178173Simp error = bus_dmamap_create(sc->kr_cdata.kr_tx_tag, 0, 1112178173Simp &txd->tx_dmamap); 1113178173Simp if (error != 0) { 1114178173Simp device_printf(sc->kr_dev, 1115178173Simp "failed to create Tx dmamap\n"); 1116178173Simp goto fail; 1117178173Simp } 1118178173Simp } 1119178173Simp /* Create DMA maps for Rx buffers. */ 1120178173Simp if ((error = bus_dmamap_create(sc->kr_cdata.kr_rx_tag, 0, 1121178173Simp &sc->kr_cdata.kr_rx_sparemap)) != 0) { 1122178173Simp device_printf(sc->kr_dev, 1123178173Simp "failed to create spare Rx dmamap\n"); 1124178173Simp goto fail; 1125178173Simp } 1126178173Simp for (i = 0; i < KR_RX_RING_CNT; i++) { 1127178173Simp rxd = &sc->kr_cdata.kr_rxdesc[i]; 1128178173Simp rxd->rx_m = NULL; 1129178173Simp rxd->rx_dmamap = NULL; 1130178173Simp error = bus_dmamap_create(sc->kr_cdata.kr_rx_tag, 0, 1131178173Simp &rxd->rx_dmamap); 1132178173Simp if (error != 0) { 1133178173Simp device_printf(sc->kr_dev, 1134178173Simp "failed to create Rx dmamap\n"); 1135178173Simp goto fail; 1136178173Simp } 1137178173Simp } 1138178173Simp 1139178173Simpfail: 1140178173Simp return (error); 1141178173Simp} 1142178173Simp 1143178173Simpstatic void 1144178173Simpkr_dma_free(struct kr_softc *sc) 1145178173Simp{ 1146178173Simp struct kr_txdesc *txd; 1147178173Simp struct kr_rxdesc *rxd; 1148178173Simp int i; 1149178173Simp 1150178173Simp /* Tx ring. */ 1151178173Simp if (sc->kr_cdata.kr_tx_ring_tag) { 1152267363Sjhb if (sc->kr_rdata.kr_tx_ring_paddr) 1153178173Simp bus_dmamap_unload(sc->kr_cdata.kr_tx_ring_tag, 1154178173Simp sc->kr_cdata.kr_tx_ring_map); 1155267363Sjhb if (sc->kr_rdata.kr_tx_ring) 1156178173Simp bus_dmamem_free(sc->kr_cdata.kr_tx_ring_tag, 1157178173Simp sc->kr_rdata.kr_tx_ring, 1158178173Simp sc->kr_cdata.kr_tx_ring_map); 1159178173Simp sc->kr_rdata.kr_tx_ring = NULL; 1160267363Sjhb sc->kr_rdata.kr_tx_ring_paddr = 0; 1161178173Simp bus_dma_tag_destroy(sc->kr_cdata.kr_tx_ring_tag); 1162178173Simp sc->kr_cdata.kr_tx_ring_tag = NULL; 1163178173Simp } 1164178173Simp /* Rx ring. */ 1165178173Simp if (sc->kr_cdata.kr_rx_ring_tag) { 1166267363Sjhb if (sc->kr_rdata.kr_rx_ring_paddr) 1167178173Simp bus_dmamap_unload(sc->kr_cdata.kr_rx_ring_tag, 1168178173Simp sc->kr_cdata.kr_rx_ring_map); 1169267363Sjhb if (sc->kr_rdata.kr_rx_ring) 1170178173Simp bus_dmamem_free(sc->kr_cdata.kr_rx_ring_tag, 1171178173Simp sc->kr_rdata.kr_rx_ring, 1172178173Simp sc->kr_cdata.kr_rx_ring_map); 1173178173Simp sc->kr_rdata.kr_rx_ring = NULL; 1174267363Sjhb sc->kr_rdata.kr_rx_ring_paddr = 0; 1175178173Simp bus_dma_tag_destroy(sc->kr_cdata.kr_rx_ring_tag); 1176178173Simp sc->kr_cdata.kr_rx_ring_tag = NULL; 1177178173Simp } 1178178173Simp /* Tx buffers. */ 1179178173Simp if (sc->kr_cdata.kr_tx_tag) { 1180178173Simp for (i = 0; i < KR_TX_RING_CNT; i++) { 1181178173Simp txd = &sc->kr_cdata.kr_txdesc[i]; 1182178173Simp if (txd->tx_dmamap) { 1183178173Simp bus_dmamap_destroy(sc->kr_cdata.kr_tx_tag, 1184178173Simp txd->tx_dmamap); 1185178173Simp txd->tx_dmamap = NULL; 1186178173Simp } 1187178173Simp } 1188178173Simp bus_dma_tag_destroy(sc->kr_cdata.kr_tx_tag); 1189178173Simp sc->kr_cdata.kr_tx_tag = NULL; 1190178173Simp } 1191178173Simp /* Rx buffers. */ 1192178173Simp if (sc->kr_cdata.kr_rx_tag) { 1193178173Simp for (i = 0; i < KR_RX_RING_CNT; i++) { 1194178173Simp rxd = &sc->kr_cdata.kr_rxdesc[i]; 1195178173Simp if (rxd->rx_dmamap) { 1196178173Simp bus_dmamap_destroy(sc->kr_cdata.kr_rx_tag, 1197178173Simp rxd->rx_dmamap); 1198178173Simp rxd->rx_dmamap = NULL; 1199178173Simp } 1200178173Simp } 1201178173Simp if (sc->kr_cdata.kr_rx_sparemap) { 1202178173Simp bus_dmamap_destroy(sc->kr_cdata.kr_rx_tag, 1203178173Simp sc->kr_cdata.kr_rx_sparemap); 1204178173Simp sc->kr_cdata.kr_rx_sparemap = 0; 1205178173Simp } 1206178173Simp bus_dma_tag_destroy(sc->kr_cdata.kr_rx_tag); 1207178173Simp sc->kr_cdata.kr_rx_tag = NULL; 1208178173Simp } 1209178173Simp 1210178173Simp if (sc->kr_cdata.kr_parent_tag) { 1211178173Simp bus_dma_tag_destroy(sc->kr_cdata.kr_parent_tag); 1212178173Simp sc->kr_cdata.kr_parent_tag = NULL; 1213178173Simp } 1214178173Simp} 1215178173Simp 1216178173Simp/* 1217178173Simp * Initialize the transmit descriptors. 1218178173Simp */ 1219178173Simpstatic int 1220178173Simpkr_tx_ring_init(struct kr_softc *sc) 1221178173Simp{ 1222178173Simp struct kr_ring_data *rd; 1223178173Simp struct kr_txdesc *txd; 1224178173Simp bus_addr_t addr; 1225178173Simp int i; 1226178173Simp 1227178173Simp sc->kr_cdata.kr_tx_prod = 0; 1228178173Simp sc->kr_cdata.kr_tx_cons = 0; 1229178173Simp sc->kr_cdata.kr_tx_cnt = 0; 1230178173Simp sc->kr_cdata.kr_tx_pkts = 0; 1231178173Simp 1232178173Simp rd = &sc->kr_rdata; 1233178173Simp bzero(rd->kr_tx_ring, KR_TX_RING_SIZE); 1234178173Simp for (i = 0; i < KR_TX_RING_CNT; i++) { 1235178173Simp if (i == KR_TX_RING_CNT - 1) 1236178173Simp addr = KR_TX_RING_ADDR(sc, 0); 1237178173Simp else 1238178173Simp addr = KR_TX_RING_ADDR(sc, i + 1); 1239178173Simp rd->kr_tx_ring[i].kr_ctl = KR_CTL_IOF; 1240178173Simp rd->kr_tx_ring[i].kr_ca = 0; 1241178173Simp rd->kr_tx_ring[i].kr_devcs = 0; 1242178173Simp rd->kr_tx_ring[i].kr_link = 0; 1243178173Simp txd = &sc->kr_cdata.kr_txdesc[i]; 1244178173Simp txd->tx_m = NULL; 1245178173Simp } 1246178173Simp 1247178173Simp bus_dmamap_sync(sc->kr_cdata.kr_tx_ring_tag, 1248178173Simp sc->kr_cdata.kr_tx_ring_map, 1249178173Simp BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1250178173Simp 1251178173Simp return (0); 1252178173Simp} 1253178173Simp 1254178173Simp/* 1255178173Simp * Initialize the RX descriptors and allocate mbufs for them. Note that 1256178173Simp * we arrange the descriptors in a closed ring, so that the last descriptor 1257178173Simp * points back to the first. 1258178173Simp */ 1259178173Simpstatic int 1260178173Simpkr_rx_ring_init(struct kr_softc *sc) 1261178173Simp{ 1262178173Simp struct kr_ring_data *rd; 1263178173Simp struct kr_rxdesc *rxd; 1264178173Simp bus_addr_t addr; 1265178173Simp int i; 1266178173Simp 1267178173Simp sc->kr_cdata.kr_rx_cons = 0; 1268178173Simp 1269178173Simp rd = &sc->kr_rdata; 1270178173Simp bzero(rd->kr_rx_ring, KR_RX_RING_SIZE); 1271178173Simp for (i = 0; i < KR_RX_RING_CNT; i++) { 1272178173Simp rxd = &sc->kr_cdata.kr_rxdesc[i]; 1273178173Simp rxd->rx_m = NULL; 1274178173Simp rxd->desc = &rd->kr_rx_ring[i]; 1275178173Simp if (i == KR_RX_RING_CNT - 1) 1276178173Simp addr = KR_RX_RING_ADDR(sc, 0); 1277178173Simp else 1278178173Simp addr = KR_RX_RING_ADDR(sc, i + 1); 1279178173Simp rd->kr_rx_ring[i].kr_ctl = KR_CTL_IOD; 1280178173Simp if (i == KR_RX_RING_CNT - 1) 1281178173Simp rd->kr_rx_ring[i].kr_ctl |= KR_CTL_COD; 1282178173Simp rd->kr_rx_ring[i].kr_devcs = 0; 1283178173Simp rd->kr_rx_ring[i].kr_ca = 0; 1284178173Simp rd->kr_rx_ring[i].kr_link = addr; 1285178173Simp if (kr_newbuf(sc, i) != 0) 1286178173Simp return (ENOBUFS); 1287178173Simp } 1288178173Simp 1289178173Simp bus_dmamap_sync(sc->kr_cdata.kr_rx_ring_tag, 1290178173Simp sc->kr_cdata.kr_rx_ring_map, 1291178173Simp BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1292178173Simp 1293178173Simp return (0); 1294178173Simp} 1295178173Simp 1296178173Simp/* 1297178173Simp * Initialize an RX descriptor and attach an MBUF cluster. 1298178173Simp */ 1299178173Simpstatic int 1300178173Simpkr_newbuf(struct kr_softc *sc, int idx) 1301178173Simp{ 1302178173Simp struct kr_desc *desc; 1303178173Simp struct kr_rxdesc *rxd; 1304178173Simp struct mbuf *m; 1305178173Simp bus_dma_segment_t segs[1]; 1306178173Simp bus_dmamap_t map; 1307178173Simp int nsegs; 1308178173Simp 1309243882Sglebius m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 1310178173Simp if (m == NULL) 1311178173Simp return (ENOBUFS); 1312178173Simp m->m_len = m->m_pkthdr.len = MCLBYTES; 1313178173Simp m_adj(m, sizeof(uint64_t)); 1314178173Simp 1315178173Simp if (bus_dmamap_load_mbuf_sg(sc->kr_cdata.kr_rx_tag, 1316178173Simp sc->kr_cdata.kr_rx_sparemap, m, segs, &nsegs, 0) != 0) { 1317178173Simp m_freem(m); 1318178173Simp return (ENOBUFS); 1319178173Simp } 1320178173Simp KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 1321178173Simp 1322178173Simp rxd = &sc->kr_cdata.kr_rxdesc[idx]; 1323178173Simp if (rxd->rx_m != NULL) { 1324178173Simp bus_dmamap_sync(sc->kr_cdata.kr_rx_tag, rxd->rx_dmamap, 1325178173Simp BUS_DMASYNC_POSTREAD); 1326178173Simp bus_dmamap_unload(sc->kr_cdata.kr_rx_tag, rxd->rx_dmamap); 1327178173Simp } 1328178173Simp map = rxd->rx_dmamap; 1329178173Simp rxd->rx_dmamap = sc->kr_cdata.kr_rx_sparemap; 1330178173Simp sc->kr_cdata.kr_rx_sparemap = map; 1331178173Simp bus_dmamap_sync(sc->kr_cdata.kr_rx_tag, rxd->rx_dmamap, 1332178173Simp BUS_DMASYNC_PREREAD); 1333178173Simp rxd->rx_m = m; 1334178173Simp desc = rxd->desc; 1335178173Simp desc->kr_ca = segs[0].ds_addr; 1336178173Simp desc->kr_ctl |= KR_DMASIZE(segs[0].ds_len); 1337178173Simp rxd->saved_ca = desc->kr_ca ; 1338178173Simp rxd->saved_ctl = desc->kr_ctl ; 1339178173Simp 1340178173Simp return (0); 1341178173Simp} 1342178173Simp 1343178173Simpstatic __inline void 1344178173Simpkr_fixup_rx(struct mbuf *m) 1345178173Simp{ 1346178173Simp int i; 1347178173Simp uint16_t *src, *dst; 1348178173Simp 1349178173Simp src = mtod(m, uint16_t *); 1350178173Simp dst = src - 1; 1351178173Simp 1352178173Simp for (i = 0; i < (m->m_len / sizeof(uint16_t) + 1); i++) 1353178173Simp *dst++ = *src++; 1354178173Simp 1355178173Simp m->m_data -= ETHER_ALIGN; 1356178173Simp} 1357178173Simp 1358178173Simp 1359178173Simpstatic void 1360178173Simpkr_tx(struct kr_softc *sc) 1361178173Simp{ 1362178173Simp struct kr_txdesc *txd; 1363178173Simp struct kr_desc *cur_tx; 1364178173Simp struct ifnet *ifp; 1365178173Simp uint32_t ctl, devcs; 1366178173Simp int cons, prod; 1367178173Simp 1368178173Simp KR_LOCK_ASSERT(sc); 1369178173Simp 1370178173Simp cons = sc->kr_cdata.kr_tx_cons; 1371178173Simp prod = sc->kr_cdata.kr_tx_prod; 1372178173Simp if (cons == prod) 1373178173Simp return; 1374178173Simp 1375178173Simp bus_dmamap_sync(sc->kr_cdata.kr_tx_ring_tag, 1376178173Simp sc->kr_cdata.kr_tx_ring_map, 1377178173Simp BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1378178173Simp 1379178173Simp ifp = sc->kr_ifp; 1380178173Simp /* 1381178173Simp * Go through our tx list and free mbufs for those 1382178173Simp * frames that have been transmitted. 1383178173Simp */ 1384178173Simp for (; cons != prod; KR_INC(cons, KR_TX_RING_CNT)) { 1385178173Simp cur_tx = &sc->kr_rdata.kr_tx_ring[cons]; 1386178173Simp ctl = cur_tx->kr_ctl; 1387178173Simp devcs = cur_tx->kr_devcs; 1388178173Simp /* Check if descriptor has "finished" flag */ 1389178173Simp if ((ctl & KR_CTL_F) == 0) 1390178173Simp break; 1391178173Simp 1392178173Simp sc->kr_cdata.kr_tx_cnt--; 1393178173Simp ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1394178173Simp 1395178173Simp txd = &sc->kr_cdata.kr_txdesc[cons]; 1396178173Simp 1397178173Simp if (devcs & KR_DMATX_DEVCS_TOK) 1398271858Sglebius if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 1399178173Simp else { 1400271858Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 1401178173Simp /* collisions: medium busy, late collision */ 1402178173Simp if ((devcs & KR_DMATX_DEVCS_EC) || 1403178173Simp (devcs & KR_DMATX_DEVCS_LC)) 1404271858Sglebius if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); 1405178173Simp } 1406178173Simp 1407178173Simp bus_dmamap_sync(sc->kr_cdata.kr_tx_tag, txd->tx_dmamap, 1408178173Simp BUS_DMASYNC_POSTWRITE); 1409178173Simp bus_dmamap_unload(sc->kr_cdata.kr_tx_tag, txd->tx_dmamap); 1410178173Simp 1411178173Simp /* Free only if it's first descriptor in list */ 1412178173Simp if (txd->tx_m) 1413178173Simp m_freem(txd->tx_m); 1414178173Simp txd->tx_m = NULL; 1415178173Simp 1416178173Simp /* reset descriptor */ 1417178173Simp cur_tx->kr_ctl = KR_CTL_IOF; 1418178173Simp cur_tx->kr_devcs = 0; 1419178173Simp cur_tx->kr_ca = 0; 1420178173Simp cur_tx->kr_link = 0; 1421178173Simp } 1422178173Simp 1423178173Simp sc->kr_cdata.kr_tx_cons = cons; 1424178173Simp 1425178173Simp bus_dmamap_sync(sc->kr_cdata.kr_tx_ring_tag, 1426178173Simp sc->kr_cdata.kr_tx_ring_map, BUS_DMASYNC_PREWRITE); 1427178173Simp} 1428178173Simp 1429178173Simp 1430178173Simpstatic void 1431178173Simpkr_rx(struct kr_softc *sc) 1432178173Simp{ 1433178173Simp struct kr_rxdesc *rxd; 1434178173Simp struct ifnet *ifp = sc->kr_ifp; 1435178173Simp int cons, prog, packet_len, count, error; 1436178173Simp struct kr_desc *cur_rx; 1437178173Simp struct mbuf *m; 1438178173Simp 1439178173Simp KR_LOCK_ASSERT(sc); 1440178173Simp 1441178173Simp cons = sc->kr_cdata.kr_rx_cons; 1442178173Simp 1443178173Simp bus_dmamap_sync(sc->kr_cdata.kr_rx_ring_tag, 1444178173Simp sc->kr_cdata.kr_rx_ring_map, 1445178173Simp BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1446178173Simp 1447178173Simp for (prog = 0; prog < KR_RX_RING_CNT; KR_INC(cons, KR_RX_RING_CNT)) { 1448178173Simp cur_rx = &sc->kr_rdata.kr_rx_ring[cons]; 1449178173Simp rxd = &sc->kr_cdata.kr_rxdesc[cons]; 1450178173Simp m = rxd->rx_m; 1451178173Simp 1452178173Simp if ((cur_rx->kr_ctl & KR_CTL_D) == 0) 1453178173Simp break; 1454178173Simp 1455178173Simp prog++; 1456178173Simp 1457178173Simp packet_len = KR_PKTSIZE(cur_rx->kr_devcs); 1458178173Simp count = m->m_len - KR_DMASIZE(cur_rx->kr_ctl); 1459178173Simp /* Assume it's error */ 1460178173Simp error = 1; 1461178173Simp 1462178173Simp if (packet_len != count) 1463271858Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 1464178173Simp else if (count < 64) 1465271858Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 1466178173Simp else if ((cur_rx->kr_devcs & KR_DMARX_DEVCS_LD) == 0) 1467271858Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 1468178173Simp else if ((cur_rx->kr_devcs & KR_DMARX_DEVCS_ROK) != 0) { 1469178173Simp error = 0; 1470178173Simp bus_dmamap_sync(sc->kr_cdata.kr_rx_tag, rxd->rx_dmamap, 1471178173Simp BUS_DMASYNC_PREREAD); 1472178173Simp m = rxd->rx_m; 1473178173Simp kr_fixup_rx(m); 1474178173Simp m->m_pkthdr.rcvif = ifp; 1475178173Simp /* Skip 4 bytes of CRC */ 1476178173Simp m->m_pkthdr.len = m->m_len = packet_len - ETHER_CRC_LEN; 1477271858Sglebius if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 1478178173Simp 1479178173Simp KR_UNLOCK(sc); 1480178173Simp (*ifp->if_input)(ifp, m); 1481178173Simp KR_LOCK(sc); 1482178173Simp } 1483178173Simp 1484178173Simp if (error) { 1485178173Simp /* Restore CONTROL and CA values, reset DEVCS */ 1486178173Simp cur_rx->kr_ctl = rxd->saved_ctl; 1487178173Simp cur_rx->kr_ca = rxd->saved_ca; 1488178173Simp cur_rx->kr_devcs = 0; 1489178173Simp } 1490178173Simp else { 1491178173Simp /* Reinit descriptor */ 1492178173Simp cur_rx->kr_ctl = KR_CTL_IOD; 1493178173Simp if (cons == KR_RX_RING_CNT - 1) 1494178173Simp cur_rx->kr_ctl |= KR_CTL_COD; 1495178173Simp cur_rx->kr_devcs = 0; 1496178173Simp cur_rx->kr_ca = 0; 1497178173Simp if (kr_newbuf(sc, cons) != 0) { 1498178173Simp device_printf(sc->kr_dev, 1499178173Simp "Failed to allocate buffer\n"); 1500178173Simp break; 1501178173Simp } 1502178173Simp } 1503178173Simp 1504178173Simp bus_dmamap_sync(sc->kr_cdata.kr_rx_ring_tag, 1505178173Simp sc->kr_cdata.kr_rx_ring_map, 1506178173Simp BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1507178173Simp 1508178173Simp } 1509178173Simp 1510178173Simp if (prog > 0) { 1511178173Simp sc->kr_cdata.kr_rx_cons = cons; 1512178173Simp 1513178173Simp bus_dmamap_sync(sc->kr_cdata.kr_rx_ring_tag, 1514178173Simp sc->kr_cdata.kr_rx_ring_map, 1515178173Simp BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1516178173Simp } 1517178173Simp} 1518178173Simp 1519178173Simpstatic void 1520178173Simpkr_rx_intr(void *arg) 1521178173Simp{ 1522178173Simp struct kr_softc *sc = arg; 1523178173Simp uint32_t status; 1524178173Simp 1525178173Simp KR_LOCK(sc); 1526178173Simp 1527178173Simp /* mask out interrupts */ 1528178173Simp KR_DMA_SETBITS_REG(KR_DMA_RXCHAN, DMA_SM, 1529178173Simp DMA_SM_D | DMA_SM_H | DMA_SM_E); 1530178173Simp 1531178173Simp status = KR_DMA_READ_REG(KR_DMA_RXCHAN, DMA_S); 1532178173Simp if (status & (DMA_S_D | DMA_S_E | DMA_S_H)) { 1533178173Simp kr_rx(sc); 1534178173Simp 1535178173Simp if (status & DMA_S_E) 1536178173Simp device_printf(sc->kr_dev, "RX DMA error\n"); 1537178173Simp } 1538178173Simp 1539178173Simp /* Reread status */ 1540178173Simp status = KR_DMA_READ_REG(KR_DMA_RXCHAN, DMA_S); 1541178173Simp 1542178173Simp /* restart DMA RX if it has been halted */ 1543178173Simp if (status & DMA_S_H) { 1544178173Simp KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_DPTR, 1545178173Simp KR_RX_RING_ADDR(sc, sc->kr_cdata.kr_rx_cons)); 1546178173Simp } 1547178173Simp 1548178173Simp KR_DMA_WRITE_REG(KR_DMA_RXCHAN, DMA_S, ~status); 1549178173Simp 1550178173Simp /* Enable F, H, E interrupts */ 1551178173Simp KR_DMA_CLEARBITS_REG(KR_DMA_RXCHAN, DMA_SM, 1552178173Simp DMA_SM_D | DMA_SM_H | DMA_SM_E); 1553178173Simp 1554178173Simp KR_UNLOCK(sc); 1555178173Simp} 1556178173Simp 1557178173Simpstatic void 1558178173Simpkr_tx_intr(void *arg) 1559178173Simp{ 1560178173Simp struct kr_softc *sc = arg; 1561178173Simp uint32_t status; 1562178173Simp 1563178173Simp KR_LOCK(sc); 1564178173Simp 1565178173Simp /* mask out interrupts */ 1566178173Simp KR_DMA_SETBITS_REG(KR_DMA_TXCHAN, DMA_SM, 1567178173Simp DMA_SM_F | DMA_SM_E); 1568178173Simp 1569178173Simp status = KR_DMA_READ_REG(KR_DMA_TXCHAN, DMA_S); 1570178173Simp if (status & (DMA_S_F | DMA_S_E)) { 1571178173Simp kr_tx(sc); 1572178173Simp if (status & DMA_S_E) 1573178173Simp device_printf(sc->kr_dev, "DMA error\n"); 1574178173Simp } 1575178173Simp 1576178173Simp KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_S, ~status); 1577178173Simp 1578178173Simp /* Enable F, E interrupts */ 1579178173Simp KR_DMA_CLEARBITS_REG(KR_DMA_TXCHAN, DMA_SM, 1580178173Simp DMA_SM_F | DMA_SM_E); 1581178173Simp 1582178173Simp KR_UNLOCK(sc); 1583178173Simp 1584178173Simp} 1585178173Simp 1586178173Simpstatic void 1587178173Simpkr_rx_und_intr(void *arg) 1588178173Simp{ 1589178173Simp 1590178173Simp panic("interrupt: %s\n", __func__); 1591178173Simp} 1592178173Simp 1593178173Simpstatic void 1594178173Simpkr_tx_ovr_intr(void *arg) 1595178173Simp{ 1596178173Simp 1597178173Simp panic("interrupt: %s\n", __func__); 1598178173Simp} 1599178173Simp 1600178173Simpstatic void 1601178173Simpkr_tick(void *xsc) 1602178173Simp{ 1603178173Simp struct kr_softc *sc = xsc; 1604178173Simp struct mii_data *mii; 1605178173Simp 1606178173Simp KR_LOCK_ASSERT(sc); 1607178173Simp 1608178173Simp mii = device_get_softc(sc->kr_miibus); 1609178173Simp mii_tick(mii); 1610178173Simp callout_reset(&sc->kr_stat_callout, hz, kr_tick, sc); 1611178173Simp} 1612