phyp_llan.c revision 256778
1256778Snwhitehorn/*- 2256778Snwhitehorn * Copyright 2013 Nathan Whitehorn 3256778Snwhitehorn * All rights reserved. 4256778Snwhitehorn * 5256778Snwhitehorn * Redistribution and use in source and binary forms, with or without 6256778Snwhitehorn * modification, are permitted provided that the following conditions 7256778Snwhitehorn * are met: 8256778Snwhitehorn * 1. Redistributions of source code must retain the above copyright 9256778Snwhitehorn * notice, this list of conditions and the following disclaimer. 10256778Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 11256778Snwhitehorn * notice, this list of conditions and the following disclaimer in the 12256778Snwhitehorn * documentation and/or other materials provided with the distribution. 13256778Snwhitehorn * 14256778Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15256778Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16256778Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17256778Snwhitehorn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18256778Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19256778Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20256778Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21256778Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22256778Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23256778Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24256778Snwhitehorn * SUCH DAMAGE. 25256778Snwhitehorn */ 26256778Snwhitehorn 27256778Snwhitehorn#include <sys/cdefs.h> 28256778Snwhitehorn__FBSDID("$FreeBSD: head/sys/powerpc/pseries/phyp_llan.c 256778 2013-10-20 01:31:09Z nwhitehorn $"); 29256778Snwhitehorn 30256778Snwhitehorn#include <sys/param.h> 31256778Snwhitehorn#include <sys/systm.h> 32256778Snwhitehorn#include <sys/sockio.h> 33256778Snwhitehorn#include <sys/endian.h> 34256778Snwhitehorn#include <sys/mbuf.h> 35256778Snwhitehorn#include <sys/module.h> 36256778Snwhitehorn#include <sys/malloc.h> 37256778Snwhitehorn#include <sys/kernel.h> 38256778Snwhitehorn#include <sys/socket.h> 39256778Snwhitehorn 40256778Snwhitehorn#include <net/bpf.h> 41256778Snwhitehorn#include <net/if.h> 42256778Snwhitehorn#include <net/if_arp.h> 43256778Snwhitehorn#include <net/ethernet.h> 44256778Snwhitehorn#include <net/if_dl.h> 45256778Snwhitehorn#include <net/if_media.h> 46256778Snwhitehorn#include <net/if_types.h> 47256778Snwhitehorn#include <net/if_vlan_var.h> 48256778Snwhitehorn 49256778Snwhitehorn#include <dev/ofw/openfirm.h> 50256778Snwhitehorn#include <dev/ofw/ofw_bus.h> 51256778Snwhitehorn#include <dev/ofw/ofw_bus_subr.h> 52256778Snwhitehorn#include <machine/bus.h> 53256778Snwhitehorn#include <machine/resource.h> 54256778Snwhitehorn#include <sys/bus.h> 55256778Snwhitehorn#include <sys/rman.h> 56256778Snwhitehorn 57256778Snwhitehorn#include <powerpc/pseries/phyp-hvcall.h> 58256778Snwhitehorn 59256778Snwhitehorn#define LLAN_MAX_RX_PACKETS 100 60256778Snwhitehorn#define LLAN_MAX_TX_PACKETS 100 61256778Snwhitehorn#define LLAN_RX_BUF_LEN 8*PAGE_SIZE 62256778Snwhitehorn 63256778Snwhitehornstruct llan_xfer { 64256778Snwhitehorn struct mbuf *rx_mbuf; 65256778Snwhitehorn bus_dmamap_t rx_dmamap; 66256778Snwhitehorn uint64_t rx_bufdesc; 67256778Snwhitehorn}; 68256778Snwhitehorn 69256778Snwhitehornstruct llan_receive_queue_entry { /* PAPR page 539 */ 70256778Snwhitehorn uint8_t control; 71256778Snwhitehorn uint8_t reserved; 72256778Snwhitehorn uint16_t offset; 73256778Snwhitehorn uint32_t length; 74256778Snwhitehorn uint64_t handle; 75256778Snwhitehorn} __packed; 76256778Snwhitehorn 77256778Snwhitehornstruct llan_softc { 78256778Snwhitehorn device_t dev; 79256778Snwhitehorn struct mtx io_lock; 80256778Snwhitehorn 81256778Snwhitehorn cell_t unit; 82256778Snwhitehorn uint8_t mac_address[8]; 83256778Snwhitehorn 84256778Snwhitehorn int irqid; 85256778Snwhitehorn struct resource *irq; 86256778Snwhitehorn void *irq_cookie; 87256778Snwhitehorn 88256778Snwhitehorn bus_dma_tag_t rx_dma_tag; 89256778Snwhitehorn bus_dma_tag_t rxbuf_dma_tag; 90256778Snwhitehorn bus_dma_tag_t tx_dma_tag; 91256778Snwhitehorn 92256778Snwhitehorn bus_dmamap_t tx_dma_map; 93256778Snwhitehorn 94256778Snwhitehorn struct llan_receive_queue_entry *rx_buf; 95256778Snwhitehorn int rx_dma_slot; 96256778Snwhitehorn int rx_valid_val; 97256778Snwhitehorn bus_dmamap_t rx_buf_map; 98256778Snwhitehorn bus_addr_t rx_buf_phys; 99256778Snwhitehorn bus_size_t rx_buf_len; 100256778Snwhitehorn bus_addr_t input_buf_phys; 101256778Snwhitehorn bus_addr_t filter_buf_phys; 102256778Snwhitehorn struct llan_xfer rx_xfer[LLAN_MAX_RX_PACKETS]; 103256778Snwhitehorn 104256778Snwhitehorn struct ifnet *ifp; 105256778Snwhitehorn}; 106256778Snwhitehorn 107256778Snwhitehornstatic int llan_probe(device_t); 108256778Snwhitehornstatic int llan_attach(device_t); 109256778Snwhitehornstatic void llan_intr(void *xsc); 110256778Snwhitehornstatic void llan_init(void *xsc); 111256778Snwhitehornstatic void llan_start(struct ifnet *ifp); 112256778Snwhitehornstatic int llan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 113256778Snwhitehornstatic void llan_rx_load_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, 114256778Snwhitehorn int err); 115256778Snwhitehornstatic int llan_add_rxbuf(struct llan_softc *sc, struct llan_xfer *rx); 116256778Snwhitehorn 117256778Snwhitehornstatic devclass_t llan_devclass; 118256778Snwhitehornstatic device_method_t llan_methods[] = { 119256778Snwhitehorn DEVMETHOD(device_probe, llan_probe), 120256778Snwhitehorn DEVMETHOD(device_attach, llan_attach), 121256778Snwhitehorn 122256778Snwhitehorn DEVMETHOD_END 123256778Snwhitehorn}; 124256778Snwhitehornstatic driver_t llan_driver = { 125256778Snwhitehorn "llan", 126256778Snwhitehorn llan_methods, 127256778Snwhitehorn sizeof(struct llan_softc) 128256778Snwhitehorn}; 129256778SnwhitehornDRIVER_MODULE(llan, vdevice, llan_driver, llan_devclass, 0, 0); 130256778Snwhitehorn 131256778Snwhitehornstatic int 132256778Snwhitehornllan_probe(device_t dev) 133256778Snwhitehorn{ 134256778Snwhitehorn if (!ofw_bus_is_compatible(dev,"IBM,l-lan")) 135256778Snwhitehorn return (ENXIO); 136256778Snwhitehorn 137256778Snwhitehorn device_set_desc(dev, "POWER Hypervisor Virtual Ethernet"); 138256778Snwhitehorn return (0); 139256778Snwhitehorn} 140256778Snwhitehorn 141256778Snwhitehornstatic int 142256778Snwhitehornllan_attach(device_t dev) 143256778Snwhitehorn{ 144256778Snwhitehorn struct llan_softc *sc; 145256778Snwhitehorn phandle_t node; 146256778Snwhitehorn int error, i; 147256778Snwhitehorn 148256778Snwhitehorn sc = device_get_softc(dev); 149256778Snwhitehorn sc->dev = dev; 150256778Snwhitehorn 151256778Snwhitehorn /* Get firmware properties */ 152256778Snwhitehorn node = ofw_bus_get_node(dev); 153256778Snwhitehorn OF_getprop(node, "local-mac-address", sc->mac_address, 154256778Snwhitehorn sizeof(sc->mac_address)); 155256778Snwhitehorn OF_getprop(node, "reg", &sc->unit, sizeof(sc->unit)); 156256778Snwhitehorn 157256778Snwhitehorn mtx_init(&sc->io_lock, "llan", NULL, MTX_DEF); 158256778Snwhitehorn 159256778Snwhitehorn /* Setup interrupt */ 160256778Snwhitehorn sc->irqid = 0; 161256778Snwhitehorn sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqid, 162256778Snwhitehorn RF_ACTIVE); 163256778Snwhitehorn 164256778Snwhitehorn if (!sc->irq) { 165256778Snwhitehorn device_printf(dev, "Could not allocate IRQ\n"); 166256778Snwhitehorn mtx_destroy(&sc->io_lock); 167256778Snwhitehorn return (ENXIO); 168256778Snwhitehorn } 169256778Snwhitehorn 170256778Snwhitehorn bus_setup_intr(dev, sc->irq, INTR_TYPE_MISC | INTR_MPSAFE | 171256778Snwhitehorn INTR_ENTROPY, NULL, llan_intr, sc, &sc->irq_cookie); 172256778Snwhitehorn 173256778Snwhitehorn /* Setup DMA */ 174256778Snwhitehorn error = bus_dma_tag_create(bus_get_dma_tag(dev), 16, 0, 175256778Snwhitehorn BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 176256778Snwhitehorn LLAN_RX_BUF_LEN, 1, BUS_SPACE_MAXSIZE_32BIT, 177256778Snwhitehorn 0, NULL, NULL, &sc->rx_dma_tag); 178256778Snwhitehorn error = bus_dma_tag_create(bus_get_dma_tag(dev), 4, 0, 179256778Snwhitehorn BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 180256778Snwhitehorn BUS_SPACE_MAXSIZE, 1, BUS_SPACE_MAXSIZE_32BIT, 181256778Snwhitehorn 0, NULL, NULL, &sc->rxbuf_dma_tag); 182256778Snwhitehorn error = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0, 183256778Snwhitehorn BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 184256778Snwhitehorn BUS_SPACE_MAXSIZE, 6, BUS_SPACE_MAXSIZE_32BIT, 0, 185256778Snwhitehorn busdma_lock_mutex, &sc->io_lock, &sc->tx_dma_tag); 186256778Snwhitehorn 187256778Snwhitehorn error = bus_dmamem_alloc(sc->rx_dma_tag, (void **)&sc->rx_buf, 188256778Snwhitehorn BUS_DMA_WAITOK | BUS_DMA_ZERO, &sc->rx_buf_map); 189256778Snwhitehorn error = bus_dmamap_load(sc->rx_dma_tag, sc->rx_buf_map, sc->rx_buf, 190256778Snwhitehorn LLAN_RX_BUF_LEN, llan_rx_load_cb, sc, 0); 191256778Snwhitehorn 192256778Snwhitehorn /* TX DMA maps */ 193256778Snwhitehorn bus_dmamap_create(sc->tx_dma_tag, 0, &sc->tx_dma_map); 194256778Snwhitehorn 195256778Snwhitehorn /* RX DMA */ 196256778Snwhitehorn for (i = 0; i < LLAN_MAX_RX_PACKETS; i++) { 197256778Snwhitehorn error = bus_dmamap_create(sc->rxbuf_dma_tag, 0, 198256778Snwhitehorn &sc->rx_xfer[i].rx_dmamap); 199256778Snwhitehorn sc->rx_xfer[i].rx_mbuf = NULL; 200256778Snwhitehorn } 201256778Snwhitehorn 202256778Snwhitehorn /* Attach to network stack */ 203256778Snwhitehorn sc->ifp = if_alloc(IFT_ETHER); 204256778Snwhitehorn sc->ifp->if_softc = sc; 205256778Snwhitehorn 206256778Snwhitehorn if_initname(sc->ifp, device_get_name(dev), device_get_unit(dev)); 207256778Snwhitehorn sc->ifp->if_mtu = ETHERMTU; /* XXX max-frame-size from OF? */ 208256778Snwhitehorn sc->ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 209256778Snwhitehorn sc->ifp->if_hwassist = 0; /* XXX: ibm,illan-options */ 210256778Snwhitehorn sc->ifp->if_capabilities = 0; 211256778Snwhitehorn sc->ifp->if_capenable = 0; 212256778Snwhitehorn sc->ifp->if_start = llan_start; 213256778Snwhitehorn sc->ifp->if_ioctl = llan_ioctl; 214256778Snwhitehorn sc->ifp->if_init = llan_init; 215256778Snwhitehorn 216256778Snwhitehorn IFQ_SET_MAXLEN(&sc->ifp->if_snd, LLAN_MAX_TX_PACKETS); 217256778Snwhitehorn sc->ifp->if_snd.ifq_drv_maxlen = LLAN_MAX_TX_PACKETS; 218256778Snwhitehorn IFQ_SET_READY(&sc->ifp->if_snd); 219256778Snwhitehorn 220256778Snwhitehorn ether_ifattach(sc->ifp, &sc->mac_address[2]); 221256778Snwhitehorn 222256778Snwhitehorn return (0); 223256778Snwhitehorn} 224256778Snwhitehorn 225256778Snwhitehornstatic void 226256778Snwhitehornllan_rx_load_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int err) 227256778Snwhitehorn{ 228256778Snwhitehorn struct llan_softc *sc = xsc; 229256778Snwhitehorn 230256778Snwhitehorn sc->rx_buf_phys = segs[0].ds_addr; 231256778Snwhitehorn sc->rx_buf_len = segs[0].ds_len - 2*PAGE_SIZE; 232256778Snwhitehorn sc->input_buf_phys = segs[0].ds_addr + segs[0].ds_len - PAGE_SIZE; 233256778Snwhitehorn sc->filter_buf_phys = segs[0].ds_addr + segs[0].ds_len - 2*PAGE_SIZE; 234256778Snwhitehorn} 235256778Snwhitehorn 236256778Snwhitehornstatic void 237256778Snwhitehornllan_init(void *xsc) 238256778Snwhitehorn{ 239256778Snwhitehorn struct llan_softc *sc = xsc; 240256778Snwhitehorn uint64_t rx_buf_desc; 241256778Snwhitehorn uint64_t macaddr; 242256778Snwhitehorn int err, i; 243256778Snwhitehorn 244256778Snwhitehorn mtx_lock(&sc->io_lock); 245256778Snwhitehorn 246256778Snwhitehorn phyp_hcall(H_FREE_LOGICAL_LAN, sc->unit); 247256778Snwhitehorn 248256778Snwhitehorn /* Create buffers (page 539) */ 249256778Snwhitehorn sc->rx_dma_slot = 0; 250256778Snwhitehorn sc->rx_valid_val = 1; 251256778Snwhitehorn 252256778Snwhitehorn rx_buf_desc = (1UL << 63); /* valid */ 253256778Snwhitehorn rx_buf_desc |= (sc->rx_buf_len << 32); 254256778Snwhitehorn rx_buf_desc |= sc->rx_buf_phys; 255256778Snwhitehorn memcpy(&macaddr, sc->mac_address, 8); 256256778Snwhitehorn err = phyp_hcall(H_REGISTER_LOGICAL_LAN, sc->unit, sc->input_buf_phys, 257256778Snwhitehorn rx_buf_desc, sc->filter_buf_phys, macaddr); 258256778Snwhitehorn 259256778Snwhitehorn for (i = 0; i < LLAN_MAX_RX_PACKETS; i++) 260256778Snwhitehorn llan_add_rxbuf(sc, &sc->rx_xfer[i]); 261256778Snwhitehorn 262256778Snwhitehorn phyp_hcall(H_VIO_SIGNAL, sc->unit, 1); /* Enable interrupts */ 263256778Snwhitehorn 264256778Snwhitehorn /* Tell stack we're up */ 265256778Snwhitehorn sc->ifp->if_drv_flags |= IFF_DRV_RUNNING; 266256778Snwhitehorn sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 267256778Snwhitehorn 268256778Snwhitehorn mtx_unlock(&sc->io_lock); 269256778Snwhitehorn} 270256778Snwhitehorn 271256778Snwhitehornstatic int 272256778Snwhitehornllan_add_rxbuf(struct llan_softc *sc, struct llan_xfer *rx) 273256778Snwhitehorn{ 274256778Snwhitehorn struct mbuf *m; 275256778Snwhitehorn bus_dma_segment_t segs[1]; 276256778Snwhitehorn int error, nsegs; 277256778Snwhitehorn 278256778Snwhitehorn mtx_assert(&sc->io_lock, MA_OWNED); 279256778Snwhitehorn 280256778Snwhitehorn m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 281256778Snwhitehorn if (m == NULL) 282256778Snwhitehorn return (ENOBUFS); 283256778Snwhitehorn 284256778Snwhitehorn m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 285256778Snwhitehorn if (rx->rx_mbuf != NULL) { 286256778Snwhitehorn bus_dmamap_sync(sc->rxbuf_dma_tag, rx->rx_dmamap, 287256778Snwhitehorn BUS_DMASYNC_POSTREAD); 288256778Snwhitehorn bus_dmamap_unload(sc->rxbuf_dma_tag, rx->rx_dmamap); 289256778Snwhitehorn } 290256778Snwhitehorn 291256778Snwhitehorn /* Save pointer to buffer structure */ 292256778Snwhitehorn m_copyback(m, 0, 8, (void *)&rx); 293256778Snwhitehorn 294256778Snwhitehorn error = bus_dmamap_load_mbuf_sg(sc->rxbuf_dma_tag, rx->rx_dmamap, m, 295256778Snwhitehorn segs, &nsegs, BUS_DMA_NOWAIT); 296256778Snwhitehorn if (error != 0) { 297256778Snwhitehorn device_printf(sc->dev, 298256778Snwhitehorn "cannot load RX DMA map %p, error = %d\n", rx, error); 299256778Snwhitehorn m_freem(m); 300256778Snwhitehorn return (error); 301256778Snwhitehorn } 302256778Snwhitehorn 303256778Snwhitehorn /* If nsegs is wrong then the stack is corrupt. */ 304256778Snwhitehorn KASSERT(nsegs == 1, 305256778Snwhitehorn ("%s: too many DMA segments (%d)", __func__, nsegs)); 306256778Snwhitehorn rx->rx_mbuf = m; 307256778Snwhitehorn 308256778Snwhitehorn bus_dmamap_sync(sc->rxbuf_dma_tag, rx->rx_dmamap, BUS_DMASYNC_PREREAD); 309256778Snwhitehorn 310256778Snwhitehorn rx->rx_bufdesc = (1UL << 63); /* valid */ 311256778Snwhitehorn rx->rx_bufdesc |= (((uint64_t)segs[0].ds_len) << 32); 312256778Snwhitehorn rx->rx_bufdesc |= segs[0].ds_addr; 313256778Snwhitehorn error = phyp_hcall(H_ADD_LOGICAL_LAN_BUFFER, sc->unit, rx->rx_bufdesc); 314256778Snwhitehorn if (error != 0) { 315256778Snwhitehorn m_freem(m); 316256778Snwhitehorn rx->rx_mbuf = NULL; 317256778Snwhitehorn return (ENOBUFS); 318256778Snwhitehorn } 319256778Snwhitehorn 320256778Snwhitehorn return (0); 321256778Snwhitehorn} 322256778Snwhitehorn 323256778Snwhitehornstatic void 324256778Snwhitehornllan_intr(void *xsc) 325256778Snwhitehorn{ 326256778Snwhitehorn struct llan_softc *sc = xsc; 327256778Snwhitehorn struct llan_xfer *rx; 328256778Snwhitehorn struct mbuf *m; 329256778Snwhitehorn 330256778Snwhitehorn mtx_lock(&sc->io_lock); 331256778Snwhitehorn phyp_hcall(H_VIO_SIGNAL, sc->unit, 0); 332256778Snwhitehorn 333256778Snwhitehorn while ((sc->rx_buf[sc->rx_dma_slot].control >> 7) == sc->rx_valid_val) { 334256778Snwhitehorn rx = (struct llan_xfer *)sc->rx_buf[sc->rx_dma_slot].handle; 335256778Snwhitehorn m = rx->rx_mbuf; 336256778Snwhitehorn m_adj(m, sc->rx_buf[sc->rx_dma_slot].offset - 8); 337256778Snwhitehorn m->m_len = sc->rx_buf[sc->rx_dma_slot].length; 338256778Snwhitehorn 339256778Snwhitehorn /* llan_add_rxbuf does DMA sync and unload as well as requeue */ 340256778Snwhitehorn if (llan_add_rxbuf(sc, rx) != 0) { 341256778Snwhitehorn sc->ifp->if_ierrors++; 342256778Snwhitehorn phyp_hcall(H_ADD_LOGICAL_LAN_BUFFER, sc->unit, 343256778Snwhitehorn rx->rx_bufdesc); 344256778Snwhitehorn continue; 345256778Snwhitehorn } 346256778Snwhitehorn 347256778Snwhitehorn sc->ifp->if_ipackets++; 348256778Snwhitehorn m_adj(m, sc->rx_buf[sc->rx_dma_slot].offset); 349256778Snwhitehorn m->m_len = sc->rx_buf[sc->rx_dma_slot].length; 350256778Snwhitehorn m->m_pkthdr.rcvif = sc->ifp; 351256778Snwhitehorn m->m_pkthdr.len = m->m_len; 352256778Snwhitehorn sc->rx_dma_slot++; 353256778Snwhitehorn 354256778Snwhitehorn if (sc->rx_dma_slot >= sc->rx_buf_len/sizeof(sc->rx_buf[0])) { 355256778Snwhitehorn sc->rx_dma_slot = 0; 356256778Snwhitehorn sc->rx_valid_val = !sc->rx_valid_val; 357256778Snwhitehorn } 358256778Snwhitehorn 359256778Snwhitehorn mtx_unlock(&sc->io_lock); 360256778Snwhitehorn (*sc->ifp->if_input)(sc->ifp, m); 361256778Snwhitehorn mtx_lock(&sc->io_lock); 362256778Snwhitehorn } 363256778Snwhitehorn 364256778Snwhitehorn phyp_hcall(H_VIO_SIGNAL, sc->unit, 1); 365256778Snwhitehorn mtx_unlock(&sc->io_lock); 366256778Snwhitehorn} 367256778Snwhitehorn 368256778Snwhitehornstatic void 369256778Snwhitehornllan_send_packet(void *xsc, bus_dma_segment_t *segs, int nsegs, 370256778Snwhitehorn bus_size_t mapsize, int error) 371256778Snwhitehorn{ 372256778Snwhitehorn struct llan_softc *sc = xsc; 373256778Snwhitehorn uint64_t bufdescs[6]; 374256778Snwhitehorn int i; 375256778Snwhitehorn 376256778Snwhitehorn bzero(bufdescs, sizeof(bufdescs)); 377256778Snwhitehorn 378256778Snwhitehorn for (i = 0; i < nsegs; i++) { 379256778Snwhitehorn bufdescs[i] = (1UL << 63); /* valid */ 380256778Snwhitehorn bufdescs[i] |= (((uint64_t)segs[i].ds_len) << 32); 381256778Snwhitehorn bufdescs[i] |= segs[i].ds_addr; 382256778Snwhitehorn } 383256778Snwhitehorn 384256778Snwhitehorn error = phyp_hcall(H_SEND_LOGICAL_LAN, sc->unit, bufdescs[0], 385256778Snwhitehorn bufdescs[1], bufdescs[2], bufdescs[3], bufdescs[4], bufdescs[5], 0); 386256778Snwhitehorn#if 0 387256778Snwhitehorn if (error) 388256778Snwhitehorn sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 389256778Snwhitehorn 390256778Snwhitehorn /* XXX: handle H_BUSY? */ 391256778Snwhitehorn /* H_SEND_LOGICAL_LAN returning 0 implies completion of the send op */ 392256778Snwhitehorn#endif 393256778Snwhitehorn} 394256778Snwhitehorn 395256778Snwhitehornstatic void 396256778Snwhitehornllan_start_locked(struct ifnet *ifp) 397256778Snwhitehorn{ 398256778Snwhitehorn struct llan_softc *sc = ifp->if_softc; 399256778Snwhitehorn bus_addr_t first; 400256778Snwhitehorn int nsegs; 401256778Snwhitehorn struct mbuf *mb_head, *m; 402256778Snwhitehorn 403256778Snwhitehorn mtx_assert(&sc->io_lock, MA_OWNED); 404256778Snwhitehorn first = 0; 405256778Snwhitehorn 406256778Snwhitehorn if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 407256778Snwhitehorn IFF_DRV_RUNNING) 408256778Snwhitehorn return; 409256778Snwhitehorn 410256778Snwhitehorn while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) { 411256778Snwhitehorn IFQ_DRV_DEQUEUE(&ifp->if_snd, mb_head); 412256778Snwhitehorn 413256778Snwhitehorn if (mb_head == NULL) 414256778Snwhitehorn break; 415256778Snwhitehorn 416256778Snwhitehorn BPF_MTAP(ifp, mb_head); 417256778Snwhitehorn 418256778Snwhitehorn for (m = mb_head, nsegs = 0; m != NULL; m = m->m_next) 419256778Snwhitehorn nsegs++; 420256778Snwhitehorn if (nsegs > 6) { 421256778Snwhitehorn m = m_collapse(mb_head, M_NOWAIT, 6); 422256778Snwhitehorn if (m == NULL) { 423256778Snwhitehorn m_freem(mb_head); 424256778Snwhitehorn continue; 425256778Snwhitehorn } 426256778Snwhitehorn } 427256778Snwhitehorn 428256778Snwhitehorn bus_dmamap_load_mbuf(sc->tx_dma_tag, sc->tx_dma_map, //xfer->dmamap, 429256778Snwhitehorn mb_head, llan_send_packet, sc, 0); 430256778Snwhitehorn bus_dmamap_unload(sc->tx_dma_tag, sc->tx_dma_map); // XXX 431256778Snwhitehorn m_freem(mb_head); 432256778Snwhitehorn } 433256778Snwhitehorn} 434256778Snwhitehorn 435256778Snwhitehornstatic void 436256778Snwhitehornllan_start(struct ifnet *ifp) 437256778Snwhitehorn{ 438256778Snwhitehorn struct llan_softc *sc = ifp->if_softc; 439256778Snwhitehorn 440256778Snwhitehorn mtx_lock(&sc->io_lock); 441256778Snwhitehorn llan_start_locked(ifp); 442256778Snwhitehorn mtx_unlock(&sc->io_lock); 443256778Snwhitehorn} 444256778Snwhitehorn 445256778Snwhitehornstatic int 446256778Snwhitehornllan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 447256778Snwhitehorn{ 448256778Snwhitehorn int err; 449256778Snwhitehorn 450256778Snwhitehorn err = ether_ioctl(ifp, cmd, data); 451256778Snwhitehorn 452256778Snwhitehorn return (err); 453256778Snwhitehorn} 454256778Snwhitehorn 455