1098ca2bdSWarner Losh /*- 2df57947fSPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause 3df57947fSPedro F. Giffuni * 4b8b33234SDoug Rabson * Copyright (c) 2004 5b8b33234SDoug Rabson * Doug Rabson 6b8b33234SDoug Rabson * Copyright (c) 2002-2003 7b8b33234SDoug Rabson * Hidetoshi Shimokawa. All rights reserved. 8b8b33234SDoug Rabson * 9b8b33234SDoug Rabson * Redistribution and use in source and binary forms, with or without 10b8b33234SDoug Rabson * modification, are permitted provided that the following conditions 11b8b33234SDoug Rabson * are met: 12b8b33234SDoug Rabson * 1. Redistributions of source code must retain the above copyright 13b8b33234SDoug Rabson * notice, this list of conditions and the following disclaimer. 14b8b33234SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 15b8b33234SDoug Rabson * notice, this list of conditions and the following disclaimer in the 16b8b33234SDoug Rabson * documentation and/or other materials provided with the distribution. 17b8b33234SDoug Rabson * 3. All advertising materials mentioning features or use of this software 18b8b33234SDoug Rabson * must display the following acknowledgement: 19b8b33234SDoug Rabson * 20b8b33234SDoug Rabson * This product includes software developed by Hidetoshi Shimokawa. 21b8b33234SDoug Rabson * 22b8b33234SDoug Rabson * 4. Neither the name of the author nor the names of its contributors 23b8b33234SDoug Rabson * may be used to endorse or promote products derived from this software 24b8b33234SDoug Rabson * without specific prior written permission. 25b8b33234SDoug Rabson * 26b8b33234SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27b8b33234SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28b8b33234SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29b8b33234SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30b8b33234SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31b8b33234SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32b8b33234SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33b8b33234SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34b8b33234SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35b8b33234SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36b8b33234SDoug Rabson * SUCH DAMAGE. 37b8b33234SDoug Rabson * 38b8b33234SDoug Rabson */ 39b8b33234SDoug Rabson 40f0796cd2SGleb Smirnoff #ifdef HAVE_KERNEL_OPTION_HEADERS 41f0796cd2SGleb Smirnoff #include "opt_device_polling.h" 42b8b33234SDoug Rabson #include "opt_inet.h" 43f0796cd2SGleb Smirnoff #endif 44b8b33234SDoug Rabson 45b8b33234SDoug Rabson #include <sys/param.h> 46b8b33234SDoug Rabson #include <sys/kernel.h> 47b8b33234SDoug Rabson #include <sys/malloc.h> 48b8b33234SDoug Rabson #include <sys/mbuf.h> 49b8b33234SDoug Rabson #include <sys/socket.h> 50b8b33234SDoug Rabson #include <sys/sockio.h> 51b8b33234SDoug Rabson #include <sys/sysctl.h> 52b8b33234SDoug Rabson #include <sys/systm.h> 53b8b33234SDoug Rabson #include <sys/taskqueue.h> 54b8b33234SDoug Rabson #include <sys/module.h> 55b8b33234SDoug Rabson #include <sys/bus.h> 56b8b33234SDoug Rabson #include <machine/bus.h> 57b8b33234SDoug Rabson 58b8b33234SDoug Rabson #include <net/bpf.h> 59b8b33234SDoug Rabson #include <net/if.h> 6076039bc8SGleb Smirnoff #include <net/if_var.h> 61b8b33234SDoug Rabson #include <net/firewire.h> 62b8b33234SDoug Rabson #include <net/if_arp.h> 63fc74a9f9SBrooks Davis #include <net/if_types.h> 64b8b33234SDoug Rabson #include <dev/firewire/firewire.h> 65b8b33234SDoug Rabson #include <dev/firewire/firewirereg.h> 6604fa3b29SDoug Rabson #include <dev/firewire/iec13213.h> 67b8b33234SDoug Rabson #include <dev/firewire/if_fwipvar.h> 68b8b33234SDoug Rabson 69b8b33234SDoug Rabson /* 70b8b33234SDoug Rabson * We really need a mechanism for allocating regions in the FIFO 71b8b33234SDoug Rabson * address space. We pick a address in the OHCI controller's 'middle' 72b8b33234SDoug Rabson * address space. This means that the controller will automatically 73b8b33234SDoug Rabson * send responses for us, which is fine since we don't have any 74b8b33234SDoug Rabson * important information to put in the response anyway. 75b8b33234SDoug Rabson */ 76b8b33234SDoug Rabson #define INET_FIFO 0xfffe00000000LL 77b8b33234SDoug Rabson 78b8b33234SDoug Rabson #define FWIPDEBUG if (fwipdebug) if_printf 79b8b33234SDoug Rabson #define TX_MAX_QUEUE (FWMAXQUEUE - 1) 80b8b33234SDoug Rabson 81b8b33234SDoug Rabson /* network interface */ 8261c05f13SJustin Hibbits static void fwip_start (if_t); 8361c05f13SJustin Hibbits static int fwip_ioctl (if_t, u_long, caddr_t); 84b8b33234SDoug Rabson static void fwip_init (void *); 85b8b33234SDoug Rabson 86b8b33234SDoug Rabson static void fwip_post_busreset (void *); 87b8b33234SDoug Rabson static void fwip_output_callback (struct fw_xfer *); 8861c05f13SJustin Hibbits static void fwip_async_output (struct fwip_softc *, if_t); 89b8b33234SDoug Rabson static void fwip_start_send (void *, int); 90b8b33234SDoug Rabson static void fwip_stream_input (struct fw_xferq *); 91b8b33234SDoug Rabson static void fwip_unicast_input(struct fw_xfer *); 92b8b33234SDoug Rabson 93b8b33234SDoug Rabson static int fwipdebug = 0; 942f8e2ebbSDoug Rabson static int broadcast_channel = 0xc0 | 0x1f; /* tag | channel(XXX) */ 95b8b33234SDoug Rabson static int tx_speed = 2; 96b8b33234SDoug Rabson static int rx_queue_len = FWMAXQUEUE; 97b8b33234SDoug Rabson 98d745c852SEd Schouten static MALLOC_DEFINE(M_FWIP, "if_fwip", "IP over FireWire interface"); 99b8b33234SDoug Rabson SYSCTL_INT(_debug, OID_AUTO, if_fwip_debug, CTLFLAG_RW, &fwipdebug, 0, ""); 100b8b33234SDoug Rabson SYSCTL_DECL(_hw_firewire); 1017029da5cSPawel Biernacki static SYSCTL_NODE(_hw_firewire, OID_AUTO, fwip, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 102b8b33234SDoug Rabson "Firewire ip subsystem"); 103af3b2549SHans Petter Selasky SYSCTL_INT(_hw_firewire_fwip, OID_AUTO, rx_queue_len, CTLFLAG_RWTUN, &rx_queue_len, 104b8b33234SDoug Rabson 0, "Length of the receive queue"); 105b8b33234SDoug Rabson 106b8b33234SDoug Rabson #ifdef DEVICE_POLLING 107b8b33234SDoug Rabson static poll_handler_t fwip_poll; 108b8b33234SDoug Rabson 1091abcdbd1SAttilio Rao static int 11061c05f13SJustin Hibbits fwip_poll(if_t ifp, enum poll_cmd cmd, int count) 111b8b33234SDoug Rabson { 112b8b33234SDoug Rabson struct fwip_softc *fwip; 113b8b33234SDoug Rabson struct firewire_comm *fc; 114b8b33234SDoug Rabson 11561c05f13SJustin Hibbits if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) 1161abcdbd1SAttilio Rao return (0); 11740929967SGleb Smirnoff 11861c05f13SJustin Hibbits fwip = ((struct fwip_eth_softc *)if_getsoftc(ifp))->fwip; 119b8b33234SDoug Rabson fc = fwip->fd.fc; 120b8b33234SDoug Rabson fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count); 1211abcdbd1SAttilio Rao return (0); 122b8b33234SDoug Rabson } 12340929967SGleb Smirnoff #endif /* DEVICE_POLLING */ 12440929967SGleb Smirnoff 125b8b33234SDoug Rabson static void 126b8b33234SDoug Rabson fwip_identify(driver_t *driver, device_t parent) 127b8b33234SDoug Rabson { 128b8b33234SDoug Rabson BUS_ADD_CHILD(parent, 0, "fwip", device_get_unit(parent)); 129b8b33234SDoug Rabson } 130b8b33234SDoug Rabson 131b8b33234SDoug Rabson static int 132b8b33234SDoug Rabson fwip_probe(device_t dev) 133b8b33234SDoug Rabson { 134b8b33234SDoug Rabson device_t pa; 135b8b33234SDoug Rabson 136b8b33234SDoug Rabson pa = device_get_parent(dev); 137b8b33234SDoug Rabson if (device_get_unit(dev) != device_get_unit(pa)) { 138b8b33234SDoug Rabson return (ENXIO); 139b8b33234SDoug Rabson } 140b8b33234SDoug Rabson 141b8b33234SDoug Rabson device_set_desc(dev, "IP over FireWire"); 142b8b33234SDoug Rabson return (0); 143b8b33234SDoug Rabson } 144b8b33234SDoug Rabson 145b8b33234SDoug Rabson static int 146b8b33234SDoug Rabson fwip_attach(device_t dev) 147b8b33234SDoug Rabson { 148b8b33234SDoug Rabson struct fwip_softc *fwip; 14961c05f13SJustin Hibbits if_t ifp; 150b8b33234SDoug Rabson int unit, s; 151b8b33234SDoug Rabson struct fw_hwaddr *hwaddr; 152b8b33234SDoug Rabson 153b8b33234SDoug Rabson fwip = ((struct fwip_softc *)device_get_softc(dev)); 154b8b33234SDoug Rabson unit = device_get_unit(dev); 155fc74a9f9SBrooks Davis ifp = fwip->fw_softc.fwip_ifp = if_alloc(IFT_IEEE1394); 156b8b33234SDoug Rabson 1579950b741SHidetoshi Shimokawa mtx_init(&fwip->mtx, "fwip", NULL, MTX_DEF); 158b8b33234SDoug Rabson /* XXX */ 159b8b33234SDoug Rabson fwip->dma_ch = -1; 160b8b33234SDoug Rabson 161b8b33234SDoug Rabson fwip->fd.fc = device_get_ivars(dev); 162b8b33234SDoug Rabson if (tx_speed < 0) 163b8b33234SDoug Rabson tx_speed = fwip->fd.fc->speed; 164b8b33234SDoug Rabson 165b8b33234SDoug Rabson fwip->fd.dev = dev; 166b8b33234SDoug Rabson fwip->fd.post_explore = NULL; 167b8b33234SDoug Rabson fwip->fd.post_busreset = fwip_post_busreset; 168b8b33234SDoug Rabson fwip->fw_softc.fwip = fwip; 169b8b33234SDoug Rabson TASK_INIT(&fwip->start_send, 0, fwip_start_send, fwip); 170b8b33234SDoug Rabson 171b8b33234SDoug Rabson /* 172b8b33234SDoug Rabson * Encode our hardware the way that arp likes it. 173b8b33234SDoug Rabson */ 174fc74a9f9SBrooks Davis hwaddr = &IFP2FWC(fwip->fw_softc.fwip_ifp)->fc_hwaddr; 175b8b33234SDoug Rabson hwaddr->sender_unique_ID_hi = htonl(fwip->fd.fc->eui.hi); 176b8b33234SDoug Rabson hwaddr->sender_unique_ID_lo = htonl(fwip->fd.fc->eui.lo); 177b8b33234SDoug Rabson hwaddr->sender_max_rec = fwip->fd.fc->maxrec; 178b8b33234SDoug Rabson hwaddr->sspd = fwip->fd.fc->speed; 179b8b33234SDoug Rabson hwaddr->sender_unicast_FIFO_hi = htons((uint16_t)(INET_FIFO >> 32)); 180b8b33234SDoug Rabson hwaddr->sender_unicast_FIFO_lo = htonl((uint32_t)INET_FIFO); 181b8b33234SDoug Rabson 182b8b33234SDoug Rabson /* fill the rest and attach interface */ 18361c05f13SJustin Hibbits if_setsoftc(ifp, &fwip->fw_softc); 184b8b33234SDoug Rabson 185b8b33234SDoug Rabson if_initname(ifp, device_get_name(dev), unit); 18661c05f13SJustin Hibbits if_setinitfn(ifp, fwip_init); 18761c05f13SJustin Hibbits if_setstartfn(ifp, fwip_start); 18861c05f13SJustin Hibbits if_setioctlfn(ifp, fwip_ioctl); 18961c05f13SJustin Hibbits if_setflags(ifp, (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST)); 19061c05f13SJustin Hibbits if_setsendqlen(ifp, TX_MAX_QUEUE); 19140929967SGleb Smirnoff #ifdef DEVICE_POLLING 19261c05f13SJustin Hibbits if_setcapabilitiesbit(ifp, IFCAP_POLLING, 0); 19340929967SGleb Smirnoff #endif 194b8b33234SDoug Rabson 195b8b33234SDoug Rabson s = splimp(); 196b8b33234SDoug Rabson firewire_ifattach(ifp, hwaddr); 197b8b33234SDoug Rabson splx(s); 198b8b33234SDoug Rabson 199b8b33234SDoug Rabson FWIPDEBUG(ifp, "interface created\n"); 200aa386085SZhenlei Huang return (0); 201b8b33234SDoug Rabson } 202b8b33234SDoug Rabson 203b8b33234SDoug Rabson static void 204b8b33234SDoug Rabson fwip_stop(struct fwip_softc *fwip) 205b8b33234SDoug Rabson { 206b8b33234SDoug Rabson struct firewire_comm *fc; 207b8b33234SDoug Rabson struct fw_xferq *xferq; 20861c05f13SJustin Hibbits if_t ifp = fwip->fw_softc.fwip_ifp; 209b8b33234SDoug Rabson struct fw_xfer *xfer, *next; 210b8b33234SDoug Rabson int i; 211b8b33234SDoug Rabson 212b8b33234SDoug Rabson fc = fwip->fd.fc; 213b8b33234SDoug Rabson 214b8b33234SDoug Rabson if (fwip->dma_ch >= 0) { 215b8b33234SDoug Rabson xferq = fc->ir[fwip->dma_ch]; 216b8b33234SDoug Rabson 217b8b33234SDoug Rabson if (xferq->flag & FWXFERQ_RUNNING) 218b8b33234SDoug Rabson fc->irx_disable(fc, fwip->dma_ch); 219b8b33234SDoug Rabson xferq->flag &= 220b8b33234SDoug Rabson ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM | 221b8b33234SDoug Rabson FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK); 222b8b33234SDoug Rabson xferq->hand = NULL; 223b8b33234SDoug Rabson 224b8b33234SDoug Rabson for (i = 0; i < xferq->bnchunk; i++) 225b8b33234SDoug Rabson m_freem(xferq->bulkxfer[i].mbuf); 226b8b33234SDoug Rabson free(xferq->bulkxfer, M_FWIP); 227b8b33234SDoug Rabson 228b8b33234SDoug Rabson fw_bindremove(fc, &fwip->fwb); 229b8b33234SDoug Rabson for (xfer = STAILQ_FIRST(&fwip->fwb.xferlist); xfer != NULL; 230b8b33234SDoug Rabson xfer = next) { 231b8b33234SDoug Rabson next = STAILQ_NEXT(xfer, link); 232b8b33234SDoug Rabson fw_xfer_free(xfer); 233b8b33234SDoug Rabson } 234b8b33234SDoug Rabson 235b8b33234SDoug Rabson for (xfer = STAILQ_FIRST(&fwip->xferlist); xfer != NULL; 236b8b33234SDoug Rabson xfer = next) { 237b8b33234SDoug Rabson next = STAILQ_NEXT(xfer, link); 238b8b33234SDoug Rabson fw_xfer_free(xfer); 239b8b33234SDoug Rabson } 240b8b33234SDoug Rabson STAILQ_INIT(&fwip->xferlist); 241b8b33234SDoug Rabson 242b8b33234SDoug Rabson xferq->bulkxfer = NULL; 243b8b33234SDoug Rabson fwip->dma_ch = -1; 244b8b33234SDoug Rabson } 245b8b33234SDoug Rabson 24661c05f13SJustin Hibbits if_setdrvflagbits(ifp, 0, (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)); 247b8b33234SDoug Rabson } 248b8b33234SDoug Rabson 249b8b33234SDoug Rabson static int 250b8b33234SDoug Rabson fwip_detach(device_t dev) 251b8b33234SDoug Rabson { 252b8b33234SDoug Rabson struct fwip_softc *fwip; 25361c05f13SJustin Hibbits if_t ifp; 254b8b33234SDoug Rabson int s; 255b8b33234SDoug Rabson 256b8b33234SDoug Rabson fwip = (struct fwip_softc *)device_get_softc(dev); 25740929967SGleb Smirnoff ifp = fwip->fw_softc.fwip_ifp; 25840929967SGleb Smirnoff 25940929967SGleb Smirnoff #ifdef DEVICE_POLLING 26061c05f13SJustin Hibbits if (if_getcapenable(ifp) & IFCAP_POLLING) 26140929967SGleb Smirnoff ether_poll_deregister(ifp); 26240929967SGleb Smirnoff #endif 26340929967SGleb Smirnoff 264b8b33234SDoug Rabson s = splimp(); 265b8b33234SDoug Rabson 266b8b33234SDoug Rabson fwip_stop(fwip); 26740929967SGleb Smirnoff firewire_ifdetach(ifp); 26840929967SGleb Smirnoff if_free(ifp); 2699950b741SHidetoshi Shimokawa mtx_destroy(&fwip->mtx); 270b8b33234SDoug Rabson 271b8b33234SDoug Rabson splx(s); 272b8b33234SDoug Rabson return 0; 273b8b33234SDoug Rabson } 274b8b33234SDoug Rabson 275b8b33234SDoug Rabson static void 276b8b33234SDoug Rabson fwip_init(void *arg) 277b8b33234SDoug Rabson { 278b8b33234SDoug Rabson struct fwip_softc *fwip = ((struct fwip_eth_softc *)arg)->fwip; 279b8b33234SDoug Rabson struct firewire_comm *fc; 28061c05f13SJustin Hibbits if_t ifp = fwip->fw_softc.fwip_ifp; 281b8b33234SDoug Rabson struct fw_xferq *xferq; 282b8b33234SDoug Rabson struct fw_xfer *xfer; 283b8b33234SDoug Rabson struct mbuf *m; 284b8b33234SDoug Rabson int i; 285b8b33234SDoug Rabson 286b8b33234SDoug Rabson FWIPDEBUG(ifp, "initializing\n"); 287b8b33234SDoug Rabson 288b8b33234SDoug Rabson fc = fwip->fd.fc; 289b8b33234SDoug Rabson #define START 0 290b8b33234SDoug Rabson if (fwip->dma_ch < 0) { 2919950b741SHidetoshi Shimokawa fwip->dma_ch = fw_open_isodma(fc, /* tx */0); 2929950b741SHidetoshi Shimokawa if (fwip->dma_ch < 0) 293b8b33234SDoug Rabson return; 2949950b741SHidetoshi Shimokawa xferq = fc->ir[fwip->dma_ch]; 2959950b741SHidetoshi Shimokawa xferq->flag |= FWXFERQ_EXTBUF | 296b8b33234SDoug Rabson FWXFERQ_HANDLER | FWXFERQ_STREAM; 297b8b33234SDoug Rabson xferq->flag &= ~0xff; 298b8b33234SDoug Rabson xferq->flag |= broadcast_channel & 0xff; 299b8b33234SDoug Rabson /* register fwip_input handler */ 300b8b33234SDoug Rabson xferq->sc = (caddr_t) fwip; 301b8b33234SDoug Rabson xferq->hand = fwip_stream_input; 302b8b33234SDoug Rabson xferq->bnchunk = rx_queue_len; 303b8b33234SDoug Rabson xferq->bnpacket = 1; 304b8b33234SDoug Rabson xferq->psize = MCLBYTES; 305b8b33234SDoug Rabson xferq->queued = 0; 306b8b33234SDoug Rabson xferq->buf = NULL; 307*4d47c7caSZhenlei Huang xferq->bulkxfer = malloc( 308b8b33234SDoug Rabson sizeof(struct fw_bulkxfer) * xferq->bnchunk, 309b8b33234SDoug Rabson M_FWIP, M_WAITOK); 310b8b33234SDoug Rabson STAILQ_INIT(&xferq->stvalid); 311b8b33234SDoug Rabson STAILQ_INIT(&xferq->stfree); 312b8b33234SDoug Rabson STAILQ_INIT(&xferq->stdma); 313b8b33234SDoug Rabson xferq->stproc = NULL; 314b8b33234SDoug Rabson for (i = 0; i < xferq->bnchunk; i++) { 315c6499eccSGleb Smirnoff m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR); 316b8b33234SDoug Rabson xferq->bulkxfer[i].mbuf = m; 317b8b33234SDoug Rabson m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 318b8b33234SDoug Rabson STAILQ_INSERT_TAIL(&xferq->stfree, 319b8b33234SDoug Rabson &xferq->bulkxfer[i], link); 320b8b33234SDoug Rabson } 321b8b33234SDoug Rabson 322b8b33234SDoug Rabson fwip->fwb.start = INET_FIFO; 323b8b33234SDoug Rabson fwip->fwb.end = INET_FIFO + 16384; /* S3200 packet size */ 324b8b33234SDoug Rabson 325b8b33234SDoug Rabson /* pre-allocate xfer */ 326b8b33234SDoug Rabson STAILQ_INIT(&fwip->fwb.xferlist); 327b8b33234SDoug Rabson for (i = 0; i < rx_queue_len; i++) { 328b8b33234SDoug Rabson xfer = fw_xfer_alloc(M_FWIP); 329b8b33234SDoug Rabson if (xfer == NULL) 330b8b33234SDoug Rabson break; 331c6499eccSGleb Smirnoff m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR); 332b8b33234SDoug Rabson xfer->recv.payload = mtod(m, uint32_t *); 333b8b33234SDoug Rabson xfer->recv.pay_len = MCLBYTES; 334801167a8SHidetoshi Shimokawa xfer->hand = fwip_unicast_input; 335b8b33234SDoug Rabson xfer->fc = fc; 336b8b33234SDoug Rabson xfer->sc = (caddr_t)fwip; 337b8b33234SDoug Rabson xfer->mbuf = m; 338b8b33234SDoug Rabson STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link); 339b8b33234SDoug Rabson } 340b8b33234SDoug Rabson fw_bindadd(fc, &fwip->fwb); 341b8b33234SDoug Rabson 342b8b33234SDoug Rabson STAILQ_INIT(&fwip->xferlist); 343b8b33234SDoug Rabson for (i = 0; i < TX_MAX_QUEUE; i++) { 344b8b33234SDoug Rabson xfer = fw_xfer_alloc(M_FWIP); 345b8b33234SDoug Rabson if (xfer == NULL) 346b8b33234SDoug Rabson break; 347b8b33234SDoug Rabson xfer->send.spd = tx_speed; 348b8b33234SDoug Rabson xfer->fc = fwip->fd.fc; 349b8b33234SDoug Rabson xfer->sc = (caddr_t)fwip; 350801167a8SHidetoshi Shimokawa xfer->hand = fwip_output_callback; 351b8b33234SDoug Rabson STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); 352b8b33234SDoug Rabson } 353b8b33234SDoug Rabson } else 354b8b33234SDoug Rabson xferq = fc->ir[fwip->dma_ch]; 355b8b33234SDoug Rabson 356b8b33234SDoug Rabson fwip->last_dest.hi = 0; 357b8b33234SDoug Rabson fwip->last_dest.lo = 0; 358b8b33234SDoug Rabson 359b8b33234SDoug Rabson /* start dma */ 360b8b33234SDoug Rabson if ((xferq->flag & FWXFERQ_RUNNING) == 0) 361b8b33234SDoug Rabson fc->irx_enable(fc, fwip->dma_ch); 362b8b33234SDoug Rabson 36361c05f13SJustin Hibbits if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); 36461c05f13SJustin Hibbits if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 365b8b33234SDoug Rabson 366b8b33234SDoug Rabson #if 0 367b8b33234SDoug Rabson /* attempt to start output */ 368b8b33234SDoug Rabson fwip_start(ifp); 369b8b33234SDoug Rabson #endif 370b8b33234SDoug Rabson } 371b8b33234SDoug Rabson 372b8b33234SDoug Rabson static int 37361c05f13SJustin Hibbits fwip_ioctl(if_t ifp, u_long cmd, caddr_t data) 374b8b33234SDoug Rabson { 37561c05f13SJustin Hibbits struct fwip_softc *fwip = ((struct fwip_eth_softc *)if_getsoftc(ifp))->fwip; 376b8b33234SDoug Rabson int s, error; 377b8b33234SDoug Rabson 378b8b33234SDoug Rabson switch (cmd) { 379b8b33234SDoug Rabson case SIOCSIFFLAGS: 380b8b33234SDoug Rabson s = splimp(); 38161c05f13SJustin Hibbits if (if_getflags(ifp) & IFF_UP) { 38261c05f13SJustin Hibbits if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) 383b8b33234SDoug Rabson fwip_init(&fwip->fw_softc); 384b8b33234SDoug Rabson } else { 38561c05f13SJustin Hibbits if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) 386b8b33234SDoug Rabson fwip_stop(fwip); 387b8b33234SDoug Rabson } 388b8b33234SDoug Rabson splx(s); 389b8b33234SDoug Rabson break; 390b8b33234SDoug Rabson case SIOCADDMULTI: 391b8b33234SDoug Rabson case SIOCDELMULTI: 392b8b33234SDoug Rabson break; 39340929967SGleb Smirnoff case SIOCSIFCAP: 39440929967SGleb Smirnoff #ifdef DEVICE_POLLING 39540929967SGleb Smirnoff { 39640929967SGleb Smirnoff struct ifreq *ifr = (struct ifreq *) data; 3970a5eaa9dSMax Khon struct firewire_comm *fc = fwip->fd.fc; 398b8b33234SDoug Rabson 39940929967SGleb Smirnoff if (ifr->ifr_reqcap & IFCAP_POLLING && 40061c05f13SJustin Hibbits !(if_getcapenable(ifp) & IFCAP_POLLING)) { 40140929967SGleb Smirnoff error = ether_poll_register(fwip_poll, ifp); 40240929967SGleb Smirnoff if (error) 40340929967SGleb Smirnoff return (error); 40440929967SGleb Smirnoff /* Disable interrupts */ 40540929967SGleb Smirnoff fc->set_intr(fc, 0); 40661c05f13SJustin Hibbits if_setcapenablebit(ifp, IFCAP_POLLING, 0); 40740929967SGleb Smirnoff return (error); 40840929967SGleb Smirnoff } 40940929967SGleb Smirnoff if (!(ifr->ifr_reqcap & IFCAP_POLLING) && 41061c05f13SJustin Hibbits if_getcapenable(ifp) & IFCAP_POLLING) { 41140929967SGleb Smirnoff error = ether_poll_deregister(ifp); 41240929967SGleb Smirnoff /* Enable interrupts. */ 41340929967SGleb Smirnoff fc->set_intr(fc, 1); 41461c05f13SJustin Hibbits if_setcapenablebit(ifp, 0, IFCAP_POLLING); 41540929967SGleb Smirnoff return (error); 41640929967SGleb Smirnoff } 41740929967SGleb Smirnoff } 41840929967SGleb Smirnoff #endif /* DEVICE_POLLING */ 41940929967SGleb Smirnoff break; 420b8b33234SDoug Rabson default: 421b8b33234SDoug Rabson s = splimp(); 422b8b33234SDoug Rabson error = firewire_ioctl(ifp, cmd, data); 423b8b33234SDoug Rabson splx(s); 424b8b33234SDoug Rabson return (error); 425b8b33234SDoug Rabson } 426b8b33234SDoug Rabson 427b8b33234SDoug Rabson return (0); 428b8b33234SDoug Rabson } 429b8b33234SDoug Rabson 430b8b33234SDoug Rabson static void 431b8b33234SDoug Rabson fwip_post_busreset(void *arg) 432b8b33234SDoug Rabson { 433b8b33234SDoug Rabson struct fwip_softc *fwip = arg; 43404fa3b29SDoug Rabson struct crom_src *src; 43504fa3b29SDoug Rabson struct crom_chunk *root; 43604fa3b29SDoug Rabson 43704fa3b29SDoug Rabson src = fwip->fd.fc->crom_src; 43804fa3b29SDoug Rabson root = fwip->fd.fc->crom_root; 43904fa3b29SDoug Rabson 44004fa3b29SDoug Rabson /* RFC2734 IPv4 over IEEE1394 */ 44104fa3b29SDoug Rabson bzero(&fwip->unit4, sizeof(struct crom_chunk)); 44204fa3b29SDoug Rabson crom_add_chunk(src, root, &fwip->unit4, CROM_UDIR); 44304fa3b29SDoug Rabson crom_add_entry(&fwip->unit4, CSRKEY_SPEC, CSRVAL_IETF); 44404fa3b29SDoug Rabson crom_add_simple_text(src, &fwip->unit4, &fwip->spec4, "IANA"); 44504fa3b29SDoug Rabson crom_add_entry(&fwip->unit4, CSRKEY_VER, 1); 44604fa3b29SDoug Rabson crom_add_simple_text(src, &fwip->unit4, &fwip->ver4, "IPv4"); 44704fa3b29SDoug Rabson 44804fa3b29SDoug Rabson /* RFC3146 IPv6 over IEEE1394 */ 44904fa3b29SDoug Rabson bzero(&fwip->unit6, sizeof(struct crom_chunk)); 45004fa3b29SDoug Rabson crom_add_chunk(src, root, &fwip->unit6, CROM_UDIR); 45104fa3b29SDoug Rabson crom_add_entry(&fwip->unit6, CSRKEY_SPEC, CSRVAL_IETF); 45204fa3b29SDoug Rabson crom_add_simple_text(src, &fwip->unit6, &fwip->spec6, "IANA"); 45304fa3b29SDoug Rabson crom_add_entry(&fwip->unit6, CSRKEY_VER, 2); 45404fa3b29SDoug Rabson crom_add_simple_text(src, &fwip->unit6, &fwip->ver6, "IPv6"); 455b8b33234SDoug Rabson 456b8b33234SDoug Rabson fwip->last_dest.hi = 0; 457b8b33234SDoug Rabson fwip->last_dest.lo = 0; 458fc74a9f9SBrooks Davis firewire_busreset(fwip->fw_softc.fwip_ifp); 459b8b33234SDoug Rabson } 460b8b33234SDoug Rabson 461b8b33234SDoug Rabson static void 462b8b33234SDoug Rabson fwip_output_callback(struct fw_xfer *xfer) 463b8b33234SDoug Rabson { 464b8b33234SDoug Rabson struct fwip_softc *fwip; 46561c05f13SJustin Hibbits if_t ifp; 466b8b33234SDoug Rabson int s; 467b8b33234SDoug Rabson 468b8b33234SDoug Rabson fwip = (struct fwip_softc *)xfer->sc; 469fc74a9f9SBrooks Davis ifp = fwip->fw_softc.fwip_ifp; 470b8b33234SDoug Rabson /* XXX error check */ 471b8b33234SDoug Rabson FWIPDEBUG(ifp, "resp = %d\n", xfer->resp); 472b8b33234SDoug Rabson if (xfer->resp != 0) 473c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 474b8b33234SDoug Rabson m_freem(xfer->mbuf); 475b8b33234SDoug Rabson fw_xfer_unload(xfer); 476b8b33234SDoug Rabson 477b8b33234SDoug Rabson s = splimp(); 4789950b741SHidetoshi Shimokawa FWIP_LOCK(fwip); 479b8b33234SDoug Rabson STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); 4809950b741SHidetoshi Shimokawa FWIP_UNLOCK(fwip); 481b8b33234SDoug Rabson splx(s); 482b8b33234SDoug Rabson 483b8b33234SDoug Rabson /* for queue full */ 48461c05f13SJustin Hibbits if (!if_sendq_empty(ifp)) { 485b8b33234SDoug Rabson fwip_start(ifp); 486b8b33234SDoug Rabson } 4879950b741SHidetoshi Shimokawa } 488b8b33234SDoug Rabson 489b8b33234SDoug Rabson static void 49061c05f13SJustin Hibbits fwip_start(if_t ifp) 491b8b33234SDoug Rabson { 49261c05f13SJustin Hibbits struct fwip_softc *fwip = ((struct fwip_eth_softc *)if_getsoftc(ifp))->fwip; 493b8b33234SDoug Rabson int s; 494b8b33234SDoug Rabson 495b8b33234SDoug Rabson FWIPDEBUG(ifp, "starting\n"); 496b8b33234SDoug Rabson 497b8b33234SDoug Rabson if (fwip->dma_ch < 0) { 498b8b33234SDoug Rabson struct mbuf *m = NULL; 499b8b33234SDoug Rabson 500b8b33234SDoug Rabson FWIPDEBUG(ifp, "not ready\n"); 501b8b33234SDoug Rabson 502b8b33234SDoug Rabson s = splimp(); 503b8b33234SDoug Rabson do { 50461c05f13SJustin Hibbits m = if_dequeue(ifp); 505b8b33234SDoug Rabson if (m != NULL) 506b8b33234SDoug Rabson m_freem(m); 507c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 508b8b33234SDoug Rabson } while (m != NULL); 509b8b33234SDoug Rabson splx(s); 510b8b33234SDoug Rabson 511b8b33234SDoug Rabson return; 512b8b33234SDoug Rabson } 513b8b33234SDoug Rabson 514b8b33234SDoug Rabson s = splimp(); 51561c05f13SJustin Hibbits if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); 516b8b33234SDoug Rabson 51761c05f13SJustin Hibbits if (!if_sendq_empty(ifp)) 518b8b33234SDoug Rabson fwip_async_output(fwip, ifp); 519b8b33234SDoug Rabson 52061c05f13SJustin Hibbits if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 521b8b33234SDoug Rabson splx(s); 522b8b33234SDoug Rabson } 523b8b33234SDoug Rabson 524b8b33234SDoug Rabson /* Async. stream output */ 525b8b33234SDoug Rabson static void 52661c05f13SJustin Hibbits fwip_async_output(struct fwip_softc *fwip, if_t ifp) 527b8b33234SDoug Rabson { 528b8b33234SDoug Rabson struct firewire_comm *fc = fwip->fd.fc; 529b8b33234SDoug Rabson struct mbuf *m; 530b8b33234SDoug Rabson struct m_tag *mtag; 531b8b33234SDoug Rabson struct fw_hwaddr *destfw; 532b8b33234SDoug Rabson struct fw_xfer *xfer; 533b8b33234SDoug Rabson struct fw_xferq *xferq; 534b8b33234SDoug Rabson struct fw_pkt *fp; 535b8b33234SDoug Rabson uint16_t nodeid; 536ee2f2cccSDoug Rabson int error; 537b8b33234SDoug Rabson int i = 0; 538b8b33234SDoug Rabson 539b8b33234SDoug Rabson xfer = NULL; 5409950b741SHidetoshi Shimokawa xferq = fc->atq; 5419950b741SHidetoshi Shimokawa while ((xferq->queued < xferq->maxq - 1) && 54261c05f13SJustin Hibbits !if_sendq_empty(ifp)) { 5439950b741SHidetoshi Shimokawa FWIP_LOCK(fwip); 544b8b33234SDoug Rabson xfer = STAILQ_FIRST(&fwip->xferlist); 545b8b33234SDoug Rabson if (xfer == NULL) { 5469950b741SHidetoshi Shimokawa FWIP_UNLOCK(fwip); 5479950b741SHidetoshi Shimokawa #if 0 548b8b33234SDoug Rabson printf("if_fwip: lack of xfer\n"); 5499950b741SHidetoshi Shimokawa #endif 550b8b33234SDoug Rabson break; 5519950b741SHidetoshi Shimokawa } 5529950b741SHidetoshi Shimokawa STAILQ_REMOVE_HEAD(&fwip->xferlist, link); 5539950b741SHidetoshi Shimokawa FWIP_UNLOCK(fwip); 5549950b741SHidetoshi Shimokawa 55561c05f13SJustin Hibbits m = if_dequeue(ifp); 5569950b741SHidetoshi Shimokawa if (m == NULL) { 5579950b741SHidetoshi Shimokawa FWIP_LOCK(fwip); 5589950b741SHidetoshi Shimokawa STAILQ_INSERT_HEAD(&fwip->xferlist, xfer, link); 5599950b741SHidetoshi Shimokawa FWIP_UNLOCK(fwip); 5609950b741SHidetoshi Shimokawa break; 5619950b741SHidetoshi Shimokawa } 562b8b33234SDoug Rabson 563b8b33234SDoug Rabson /* 564b8b33234SDoug Rabson * Dig out the link-level address which 565b8b33234SDoug Rabson * firewire_output got via arp or neighbour 566b8b33234SDoug Rabson * discovery. If we don't have a link-level address, 567b8b33234SDoug Rabson * just stick the thing on the broadcast channel. 568b8b33234SDoug Rabson */ 569b8b33234SDoug Rabson mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 0); 570b8b33234SDoug Rabson if (mtag == NULL) 5714d24901aSPedro F. Giffuni destfw = NULL; 572b8b33234SDoug Rabson else 573b8b33234SDoug Rabson destfw = (struct fw_hwaddr *) (mtag + 1); 574b8b33234SDoug Rabson 575b8b33234SDoug Rabson 576b8b33234SDoug Rabson /* 577b8b33234SDoug Rabson * We don't do any bpf stuff here - the generic code 578b8b33234SDoug Rabson * in firewire_output gives the packet to bpf before 579b8b33234SDoug Rabson * it adds the link-level encapsulation. 580b8b33234SDoug Rabson */ 581b8b33234SDoug Rabson 582b8b33234SDoug Rabson /* 583b8b33234SDoug Rabson * Put the mbuf in the xfer early in case we hit an 584b8b33234SDoug Rabson * error case below - fwip_output_callback will free 585b8b33234SDoug Rabson * the mbuf. 586b8b33234SDoug Rabson */ 587b8b33234SDoug Rabson xfer->mbuf = m; 588b8b33234SDoug Rabson 589b8b33234SDoug Rabson /* 590b8b33234SDoug Rabson * We use the arp result (if any) to add a suitable firewire 591b8b33234SDoug Rabson * packet header before handing off to the bus. 592b8b33234SDoug Rabson */ 593b8b33234SDoug Rabson fp = &xfer->send.hdr; 594b8b33234SDoug Rabson nodeid = FWLOCALBUS | fc->nodeid; 595b8b33234SDoug Rabson if ((m->m_flags & M_BCAST) || !destfw) { 596b8b33234SDoug Rabson /* 597b8b33234SDoug Rabson * Broadcast packets are sent as GASP packets with 598b8b33234SDoug Rabson * specifier ID 0x00005e, version 1 on the broadcast 599b8b33234SDoug Rabson * channel. To be conservative, we send at the 600b8b33234SDoug Rabson * slowest possible speed. 601b8b33234SDoug Rabson */ 602b8b33234SDoug Rabson uint32_t *p; 603b8b33234SDoug Rabson 604c6499eccSGleb Smirnoff M_PREPEND(m, 2*sizeof(uint32_t), M_NOWAIT); 605b8b33234SDoug Rabson p = mtod(m, uint32_t *); 606b8b33234SDoug Rabson fp->mode.stream.len = m->m_pkthdr.len; 607b8b33234SDoug Rabson fp->mode.stream.chtag = broadcast_channel; 608b8b33234SDoug Rabson fp->mode.stream.tcode = FWTCODE_STREAM; 609b8b33234SDoug Rabson fp->mode.stream.sy = 0; 610b8b33234SDoug Rabson xfer->send.spd = 0; 611b8b33234SDoug Rabson p[0] = htonl(nodeid << 16); 612b8b33234SDoug Rabson p[1] = htonl((0x5e << 24) | 1); 613b8b33234SDoug Rabson } else { 614b8b33234SDoug Rabson /* 615b8b33234SDoug Rabson * Unicast packets are sent as block writes to the 616b8b33234SDoug Rabson * target's unicast fifo address. If we can't 617b8b33234SDoug Rabson * find the node address, we just give up. We 618b8b33234SDoug Rabson * could broadcast it but that might overflow 619b8b33234SDoug Rabson * the packet size limitations due to the 620b8b33234SDoug Rabson * extra GASP header. Note: the hardware 621b8b33234SDoug Rabson * address is stored in network byte order to 622b8b33234SDoug Rabson * make life easier for ARP. 623b8b33234SDoug Rabson */ 624b8b33234SDoug Rabson struct fw_device *fd; 625b8b33234SDoug Rabson struct fw_eui64 eui; 626b8b33234SDoug Rabson 627b8b33234SDoug Rabson eui.hi = ntohl(destfw->sender_unique_ID_hi); 628b8b33234SDoug Rabson eui.lo = ntohl(destfw->sender_unique_ID_lo); 629b8b33234SDoug Rabson if (fwip->last_dest.hi != eui.hi || 630b8b33234SDoug Rabson fwip->last_dest.lo != eui.lo) { 631b8b33234SDoug Rabson fd = fw_noderesolve_eui64(fc, &eui); 632b8b33234SDoug Rabson if (!fd) { 633b8b33234SDoug Rabson /* error */ 634c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 635b8b33234SDoug Rabson /* XXX set error code */ 636b8b33234SDoug Rabson fwip_output_callback(xfer); 637b8b33234SDoug Rabson continue; 638b8b33234SDoug Rabson 639b8b33234SDoug Rabson } 640b8b33234SDoug Rabson fwip->last_hdr.mode.wreqb.dst = FWLOCALBUS | fd->dst; 641b8b33234SDoug Rabson fwip->last_hdr.mode.wreqb.tlrt = 0; 642b8b33234SDoug Rabson fwip->last_hdr.mode.wreqb.tcode = FWTCODE_WREQB; 643b8b33234SDoug Rabson fwip->last_hdr.mode.wreqb.pri = 0; 644b8b33234SDoug Rabson fwip->last_hdr.mode.wreqb.src = nodeid; 645b8b33234SDoug Rabson fwip->last_hdr.mode.wreqb.dest_hi = 646b8b33234SDoug Rabson ntohs(destfw->sender_unicast_FIFO_hi); 647b8b33234SDoug Rabson fwip->last_hdr.mode.wreqb.dest_lo = 648b8b33234SDoug Rabson ntohl(destfw->sender_unicast_FIFO_lo); 649b8b33234SDoug Rabson fwip->last_hdr.mode.wreqb.extcode = 0; 650b8b33234SDoug Rabson fwip->last_dest = eui; 651b8b33234SDoug Rabson } 652b8b33234SDoug Rabson 653b8b33234SDoug Rabson fp->mode.wreqb = fwip->last_hdr.mode.wreqb; 654b8b33234SDoug Rabson fp->mode.wreqb.len = m->m_pkthdr.len; 655b8b33234SDoug Rabson xfer->send.spd = min(destfw->sspd, fc->speed); 656b8b33234SDoug Rabson } 657b8b33234SDoug Rabson 658b8b33234SDoug Rabson xfer->send.pay_len = m->m_pkthdr.len; 659b8b33234SDoug Rabson 660ee2f2cccSDoug Rabson error = fw_asyreq(fc, -1, xfer); 661ee2f2cccSDoug Rabson if (error == EAGAIN) { 662ee2f2cccSDoug Rabson /* 663ee2f2cccSDoug Rabson * We ran out of tlabels - requeue the packet 664ee2f2cccSDoug Rabson * for later transmission. 665ee2f2cccSDoug Rabson */ 666ee2f2cccSDoug Rabson xfer->mbuf = 0; 6679950b741SHidetoshi Shimokawa FWIP_LOCK(fwip); 668ee2f2cccSDoug Rabson STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); 6699950b741SHidetoshi Shimokawa FWIP_UNLOCK(fwip); 67061c05f13SJustin Hibbits if_sendq_prepend(ifp, m); 671ee2f2cccSDoug Rabson break; 672ee2f2cccSDoug Rabson } 673ee2f2cccSDoug Rabson if (error) { 674b8b33234SDoug Rabson /* error */ 675c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 676b8b33234SDoug Rabson /* XXX set error code */ 677b8b33234SDoug Rabson fwip_output_callback(xfer); 678b8b33234SDoug Rabson continue; 679b8b33234SDoug Rabson } else { 680c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 681b8b33234SDoug Rabson i++; 682b8b33234SDoug Rabson } 683b8b33234SDoug Rabson } 684b8b33234SDoug Rabson #if 0 685b8b33234SDoug Rabson if (i > 1) 686b8b33234SDoug Rabson printf("%d queued\n", i); 687b8b33234SDoug Rabson #endif 6889950b741SHidetoshi Shimokawa if (i > 0) 689b8b33234SDoug Rabson xferq->start(fc); 690b8b33234SDoug Rabson } 691b8b33234SDoug Rabson 692b8b33234SDoug Rabson static void 693b8b33234SDoug Rabson fwip_start_send (void *arg, int count) 694b8b33234SDoug Rabson { 695b8b33234SDoug Rabson struct fwip_softc *fwip = arg; 696b8b33234SDoug Rabson 697b8b33234SDoug Rabson fwip->fd.fc->atq->start(fwip->fd.fc); 698b8b33234SDoug Rabson } 699b8b33234SDoug Rabson 700b8b33234SDoug Rabson /* Async. stream output */ 701b8b33234SDoug Rabson static void 702b8b33234SDoug Rabson fwip_stream_input(struct fw_xferq *xferq) 703b8b33234SDoug Rabson { 704b8a6e03fSGleb Smirnoff struct epoch_tracker et; 705b8b33234SDoug Rabson struct mbuf *m, *m0; 706b8b33234SDoug Rabson struct m_tag *mtag; 70761c05f13SJustin Hibbits if_t ifp; 708b8b33234SDoug Rabson struct fwip_softc *fwip; 709b8b33234SDoug Rabson struct fw_bulkxfer *sxfer; 710b8b33234SDoug Rabson struct fw_pkt *fp; 711b8b33234SDoug Rabson uint16_t src; 712b8b33234SDoug Rabson uint32_t *p; 713b8b33234SDoug Rabson 714b8b33234SDoug Rabson fwip = (struct fwip_softc *)xferq->sc; 715fc74a9f9SBrooks Davis ifp = fwip->fw_softc.fwip_ifp; 71640929967SGleb Smirnoff 717b8a6e03fSGleb Smirnoff NET_EPOCH_ENTER(et); 718b8b33234SDoug Rabson while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) { 719b8b33234SDoug Rabson STAILQ_REMOVE_HEAD(&xferq->stvalid, link); 720b8b33234SDoug Rabson fp = mtod(sxfer->mbuf, struct fw_pkt *); 721b8b33234SDoug Rabson if (fwip->fd.fc->irx_post != NULL) 722b8b33234SDoug Rabson fwip->fd.fc->irx_post(fwip->fd.fc, fp->mode.ld); 723b8b33234SDoug Rabson m = sxfer->mbuf; 724b8b33234SDoug Rabson 725b8b33234SDoug Rabson /* insert new rbuf */ 726c6499eccSGleb Smirnoff sxfer->mbuf = m0 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 727b8b33234SDoug Rabson if (m0 != NULL) { 728b8b33234SDoug Rabson m0->m_len = m0->m_pkthdr.len = m0->m_ext.ext_size; 729b8b33234SDoug Rabson STAILQ_INSERT_TAIL(&xferq->stfree, sxfer, link); 730b8b33234SDoug Rabson } else 731b8b33234SDoug Rabson printf("fwip_as_input: m_getcl failed\n"); 732b8b33234SDoug Rabson 733b8b33234SDoug Rabson /* 734b8b33234SDoug Rabson * We must have a GASP header - leave the 735b8b33234SDoug Rabson * encapsulation sanity checks to the generic 736453130d9SPedro F. Giffuni * code. Remember that we also have the firewire async 737b8b33234SDoug Rabson * stream header even though that isn't accounted for 738b8b33234SDoug Rabson * in mode.stream.len. 739b8b33234SDoug Rabson */ 740b8b33234SDoug Rabson if (sxfer->resp != 0 || fp->mode.stream.len < 741b8b33234SDoug Rabson 2*sizeof(uint32_t)) { 742b8b33234SDoug Rabson m_freem(m); 743c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 744b8b33234SDoug Rabson continue; 745b8b33234SDoug Rabson } 746b8b33234SDoug Rabson m->m_len = m->m_pkthdr.len = fp->mode.stream.len 747b8b33234SDoug Rabson + sizeof(fp->mode.stream); 748b8b33234SDoug Rabson 749b8b33234SDoug Rabson /* 750b8b33234SDoug Rabson * If we received the packet on the broadcast channel, 751b8b33234SDoug Rabson * mark it as broadcast, otherwise we assume it must 752b8b33234SDoug Rabson * be multicast. 753b8b33234SDoug Rabson */ 754b8b33234SDoug Rabson if (fp->mode.stream.chtag == broadcast_channel) 755b8b33234SDoug Rabson m->m_flags |= M_BCAST; 756b8b33234SDoug Rabson else 757b8b33234SDoug Rabson m->m_flags |= M_MCAST; 758b8b33234SDoug Rabson 759b8b33234SDoug Rabson /* 760b8b33234SDoug Rabson * Make sure we recognise the GASP specifier and 761b8b33234SDoug Rabson * version. 762b8b33234SDoug Rabson */ 763b8b33234SDoug Rabson p = mtod(m, uint32_t *); 764b8b33234SDoug Rabson if ((((ntohl(p[1]) & 0xffff) << 8) | ntohl(p[2]) >> 24) != 0x00005e 765b8b33234SDoug Rabson || (ntohl(p[2]) & 0xffffff) != 1) { 766b8b33234SDoug Rabson FWIPDEBUG(ifp, "Unrecognised GASP header %#08x %#08x\n", 767b8b33234SDoug Rabson ntohl(p[1]), ntohl(p[2])); 768b8b33234SDoug Rabson m_freem(m); 769c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 770b8b33234SDoug Rabson continue; 771b8b33234SDoug Rabson } 772b8b33234SDoug Rabson 773b8b33234SDoug Rabson /* 774b8b33234SDoug Rabson * Record the sender ID for possible BPF usage. 775b8b33234SDoug Rabson */ 776b8b33234SDoug Rabson src = ntohl(p[1]) >> 16; 7778f31b879SJustin Hibbits if (bpf_peers_present_if(ifp)) { 778b8b33234SDoug Rabson mtag = m_tag_alloc(MTAG_FIREWIRE, 779b8b33234SDoug Rabson MTAG_FIREWIRE_SENDER_EUID, 780b8b33234SDoug Rabson 2*sizeof(uint32_t), M_NOWAIT); 781b8b33234SDoug Rabson if (mtag) { 782b8b33234SDoug Rabson /* bpf wants it in network byte order */ 783b8b33234SDoug Rabson struct fw_device *fd; 784b8b33234SDoug Rabson uint32_t *p = (uint32_t *) (mtag + 1); 785b8b33234SDoug Rabson fd = fw_noderesolve_nodeid(fwip->fd.fc, 786b8b33234SDoug Rabson src & 0x3f); 787b8b33234SDoug Rabson if (fd) { 788b8b33234SDoug Rabson p[0] = htonl(fd->eui.hi); 789b8b33234SDoug Rabson p[1] = htonl(fd->eui.lo); 790b8b33234SDoug Rabson } else { 791b8b33234SDoug Rabson p[0] = 0; 792b8b33234SDoug Rabson p[1] = 0; 793b8b33234SDoug Rabson } 794b8b33234SDoug Rabson m_tag_prepend(m, mtag); 795b8b33234SDoug Rabson } 796b8b33234SDoug Rabson } 797b8b33234SDoug Rabson 798b8b33234SDoug Rabson /* 799b8b33234SDoug Rabson * Trim off the GASP header 800b8b33234SDoug Rabson */ 801b8b33234SDoug Rabson m_adj(m, 3*sizeof(uint32_t)); 802b8b33234SDoug Rabson m->m_pkthdr.rcvif = ifp; 803b8b33234SDoug Rabson firewire_input(ifp, m, src); 804c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 805b8b33234SDoug Rabson } 806b8a6e03fSGleb Smirnoff NET_EPOCH_EXIT(et); 807b8b33234SDoug Rabson if (STAILQ_FIRST(&xferq->stfree) != NULL) 808b8b33234SDoug Rabson fwip->fd.fc->irx_enable(fwip->fd.fc, fwip->dma_ch); 809b8b33234SDoug Rabson } 810b8b33234SDoug Rabson 811b8b33234SDoug Rabson static __inline void 812b8b33234SDoug Rabson fwip_unicast_input_recycle(struct fwip_softc *fwip, struct fw_xfer *xfer) 813b8b33234SDoug Rabson { 814b8b33234SDoug Rabson struct mbuf *m; 815b8b33234SDoug Rabson 816b8b33234SDoug Rabson /* 817b8b33234SDoug Rabson * We have finished with a unicast xfer. Allocate a new 818b8b33234SDoug Rabson * cluster and stick it on the back of the input queue. 819b8b33234SDoug Rabson */ 820c6499eccSGleb Smirnoff m = m_getcl(M_WAITOK, MT_DATA, M_PKTHDR); 821b8b33234SDoug Rabson xfer->mbuf = m; 822b8b33234SDoug Rabson xfer->recv.payload = mtod(m, uint32_t *); 823b8b33234SDoug Rabson xfer->recv.pay_len = MCLBYTES; 824b8b33234SDoug Rabson xfer->mbuf = m; 825b8b33234SDoug Rabson STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link); 826b8b33234SDoug Rabson } 827b8b33234SDoug Rabson 828b8b33234SDoug Rabson static void 829b8b33234SDoug Rabson fwip_unicast_input(struct fw_xfer *xfer) 830b8b33234SDoug Rabson { 831b8b33234SDoug Rabson uint64_t address; 832b8b33234SDoug Rabson struct mbuf *m; 833b8b33234SDoug Rabson struct m_tag *mtag; 834bdf316e8STai-hwa Liang struct epoch_tracker et; 83561c05f13SJustin Hibbits if_t ifp; 836b8b33234SDoug Rabson struct fwip_softc *fwip; 837b8b33234SDoug Rabson struct fw_pkt *fp; 838b8b33234SDoug Rabson //struct fw_pkt *sfp; 839b8b33234SDoug Rabson int rtcode; 840b8b33234SDoug Rabson 841b8b33234SDoug Rabson fwip = (struct fwip_softc *)xfer->sc; 842fc74a9f9SBrooks Davis ifp = fwip->fw_softc.fwip_ifp; 843b8b33234SDoug Rabson m = xfer->mbuf; 844b8b33234SDoug Rabson xfer->mbuf = 0; 845b8b33234SDoug Rabson fp = &xfer->recv.hdr; 846b8b33234SDoug Rabson 847b8b33234SDoug Rabson /* 848b8b33234SDoug Rabson * Check the fifo address - we only accept addresses of 849b8b33234SDoug Rabson * exactly INET_FIFO. 850b8b33234SDoug Rabson */ 851b8b33234SDoug Rabson address = ((uint64_t)fp->mode.wreqb.dest_hi << 32) 852b8b33234SDoug Rabson | fp->mode.wreqb.dest_lo; 853b8b33234SDoug Rabson if (fp->mode.wreqb.tcode != FWTCODE_WREQB) { 854b8b33234SDoug Rabson rtcode = FWRCODE_ER_TYPE; 855b8b33234SDoug Rabson } else if (address != INET_FIFO) { 856b8b33234SDoug Rabson rtcode = FWRCODE_ER_ADDR; 857b8b33234SDoug Rabson } else { 858b8b33234SDoug Rabson rtcode = FWRCODE_COMPLETE; 859b8b33234SDoug Rabson } 860bdf316e8STai-hwa Liang NET_EPOCH_ENTER(et); 861b8b33234SDoug Rabson 862b8b33234SDoug Rabson /* 863b8b33234SDoug Rabson * Pick up a new mbuf and stick it on the back of the receive 864b8b33234SDoug Rabson * queue. 865b8b33234SDoug Rabson */ 866b8b33234SDoug Rabson fwip_unicast_input_recycle(fwip, xfer); 867b8b33234SDoug Rabson 868b8b33234SDoug Rabson /* 869b8b33234SDoug Rabson * If we've already rejected the packet, give up now. 870b8b33234SDoug Rabson */ 871b8b33234SDoug Rabson if (rtcode != FWRCODE_COMPLETE) { 872b8b33234SDoug Rabson m_freem(m); 873c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 874bdf316e8STai-hwa Liang goto done; 875b8b33234SDoug Rabson } 876b8b33234SDoug Rabson 8778f31b879SJustin Hibbits if (bpf_peers_present_if(ifp)) { 878b8b33234SDoug Rabson /* 879b8b33234SDoug Rabson * Record the sender ID for possible BPF usage. 880b8b33234SDoug Rabson */ 881b8b33234SDoug Rabson mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID, 882b8b33234SDoug Rabson 2*sizeof(uint32_t), M_NOWAIT); 883b8b33234SDoug Rabson if (mtag) { 884b8b33234SDoug Rabson /* bpf wants it in network byte order */ 885b8b33234SDoug Rabson struct fw_device *fd; 886b8b33234SDoug Rabson uint32_t *p = (uint32_t *) (mtag + 1); 887b8b33234SDoug Rabson fd = fw_noderesolve_nodeid(fwip->fd.fc, 888b8b33234SDoug Rabson fp->mode.wreqb.src & 0x3f); 889b8b33234SDoug Rabson if (fd) { 890b8b33234SDoug Rabson p[0] = htonl(fd->eui.hi); 891b8b33234SDoug Rabson p[1] = htonl(fd->eui.lo); 892b8b33234SDoug Rabson } else { 893b8b33234SDoug Rabson p[0] = 0; 894b8b33234SDoug Rabson p[1] = 0; 895b8b33234SDoug Rabson } 896b8b33234SDoug Rabson m_tag_prepend(m, mtag); 897b8b33234SDoug Rabson } 898b8b33234SDoug Rabson } 899b8b33234SDoug Rabson 900b8b33234SDoug Rabson /* 901b8b33234SDoug Rabson * Hand off to the generic encapsulation code. We don't use 902b8b33234SDoug Rabson * ifp->if_input so that we can pass the source nodeid as an 903b8b33234SDoug Rabson * argument to facilitate link-level fragment reassembly. 904b8b33234SDoug Rabson */ 905b8b33234SDoug Rabson m->m_len = m->m_pkthdr.len = fp->mode.wreqb.len; 906b8b33234SDoug Rabson m->m_pkthdr.rcvif = ifp; 907b8b33234SDoug Rabson firewire_input(ifp, m, fp->mode.wreqb.src); 908c8dfaf38SGleb Smirnoff if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 909bdf316e8STai-hwa Liang done: 910bdf316e8STai-hwa Liang NET_EPOCH_EXIT(et); 911b8b33234SDoug Rabson } 912b8b33234SDoug Rabson 913b8b33234SDoug Rabson static device_method_t fwip_methods[] = { 914b8b33234SDoug Rabson /* device interface */ 915b8b33234SDoug Rabson DEVMETHOD(device_identify, fwip_identify), 916b8b33234SDoug Rabson DEVMETHOD(device_probe, fwip_probe), 917b8b33234SDoug Rabson DEVMETHOD(device_attach, fwip_attach), 918b8b33234SDoug Rabson DEVMETHOD(device_detach, fwip_detach), 919b8b33234SDoug Rabson { 0, 0 } 920b8b33234SDoug Rabson }; 921b8b33234SDoug Rabson 922b8b33234SDoug Rabson static driver_t fwip_driver = { 923b8b33234SDoug Rabson "fwip", 924b8b33234SDoug Rabson fwip_methods, 925b8b33234SDoug Rabson sizeof(struct fwip_softc), 926b8b33234SDoug Rabson }; 927b8b33234SDoug Rabson 928b8b33234SDoug Rabson 9298984411bSJohn Baldwin DRIVER_MODULE(fwip, firewire, fwip_driver, 0, 0); 930b8b33234SDoug Rabson MODULE_VERSION(fwip, 1); 931b8b33234SDoug Rabson MODULE_DEPEND(fwip, firewire, 1, 1, 1); 932