if_fwip.c revision 170374
1139749Simp/*- 2130407Sdfr * Copyright (c) 2004 3130407Sdfr * Doug Rabson 4130407Sdfr * Copyright (c) 2002-2003 5130407Sdfr * Hidetoshi Shimokawa. All rights reserved. 6130407Sdfr * 7130407Sdfr * Redistribution and use in source and binary forms, with or without 8130407Sdfr * modification, are permitted provided that the following conditions 9130407Sdfr * are met: 10130407Sdfr * 1. Redistributions of source code must retain the above copyright 11130407Sdfr * notice, this list of conditions and the following disclaimer. 12130407Sdfr * 2. Redistributions in binary form must reproduce the above copyright 13130407Sdfr * notice, this list of conditions and the following disclaimer in the 14130407Sdfr * documentation and/or other materials provided with the distribution. 15130407Sdfr * 3. All advertising materials mentioning features or use of this software 16130407Sdfr * must display the following acknowledgement: 17130407Sdfr * 18130407Sdfr * This product includes software developed by Hidetoshi Shimokawa. 19130407Sdfr * 20130407Sdfr * 4. Neither the name of the author nor the names of its contributors 21130407Sdfr * may be used to endorse or promote products derived from this software 22130407Sdfr * without specific prior written permission. 23130407Sdfr * 24130407Sdfr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25130407Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26130407Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27130407Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28130407Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29130407Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30130407Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31130407Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32130407Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33130407Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34130407Sdfr * SUCH DAMAGE. 35130407Sdfr * 36130407Sdfr * $FreeBSD: head/sys/dev/firewire/if_fwip.c 170374 2007-06-06 14:31:36Z simokawa $ 37130407Sdfr */ 38130407Sdfr 39150968Sglebius#ifdef HAVE_KERNEL_OPTION_HEADERS 40150968Sglebius#include "opt_device_polling.h" 41130407Sdfr#include "opt_inet.h" 42150968Sglebius#endif 43130407Sdfr 44130407Sdfr#include <sys/param.h> 45130407Sdfr#include <sys/kernel.h> 46130407Sdfr#include <sys/malloc.h> 47130407Sdfr#include <sys/mbuf.h> 48130407Sdfr#include <sys/socket.h> 49130407Sdfr#include <sys/sockio.h> 50130407Sdfr#include <sys/sysctl.h> 51130407Sdfr#include <sys/systm.h> 52130407Sdfr#include <sys/taskqueue.h> 53130407Sdfr#include <sys/module.h> 54130407Sdfr#include <sys/bus.h> 55130407Sdfr#include <machine/bus.h> 56130407Sdfr 57130407Sdfr#include <net/bpf.h> 58130407Sdfr#include <net/if.h> 59130407Sdfr#include <net/firewire.h> 60130407Sdfr#include <net/if_arp.h> 61147256Sbrooks#include <net/if_types.h> 62130407Sdfr#ifdef __DragonFly__ 63130407Sdfr#include <bus/firewire/firewire.h> 64130407Sdfr#include <bus/firewire/firewirereg.h> 65130407Sdfr#include "if_fwipvar.h" 66130407Sdfr#else 67130407Sdfr#include <dev/firewire/firewire.h> 68130407Sdfr#include <dev/firewire/firewirereg.h> 69130411Sdfr#include <dev/firewire/iec13213.h> 70130407Sdfr#include <dev/firewire/if_fwipvar.h> 71130407Sdfr#endif 72130407Sdfr 73130407Sdfr/* 74130407Sdfr * We really need a mechanism for allocating regions in the FIFO 75130407Sdfr * address space. We pick a address in the OHCI controller's 'middle' 76130407Sdfr * address space. This means that the controller will automatically 77130407Sdfr * send responses for us, which is fine since we don't have any 78130407Sdfr * important information to put in the response anyway. 79130407Sdfr */ 80130407Sdfr#define INET_FIFO 0xfffe00000000LL 81130407Sdfr 82130407Sdfr#define FWIPDEBUG if (fwipdebug) if_printf 83130407Sdfr#define TX_MAX_QUEUE (FWMAXQUEUE - 1) 84130407Sdfr 85130407Sdfr/* network interface */ 86130407Sdfrstatic void fwip_start (struct ifnet *); 87130407Sdfrstatic int fwip_ioctl (struct ifnet *, u_long, caddr_t); 88130407Sdfrstatic void fwip_init (void *); 89130407Sdfr 90130407Sdfrstatic void fwip_post_busreset (void *); 91130407Sdfrstatic void fwip_output_callback (struct fw_xfer *); 92130407Sdfrstatic void fwip_async_output (struct fwip_softc *, struct ifnet *); 93130407Sdfrstatic void fwip_start_send (void *, int); 94130407Sdfrstatic void fwip_stream_input (struct fw_xferq *); 95130407Sdfrstatic void fwip_unicast_input(struct fw_xfer *); 96130407Sdfr 97130407Sdfrstatic int fwipdebug = 0; 98132445Sdfrstatic int broadcast_channel = 0xc0 | 0x1f; /* tag | channel(XXX) */ 99130407Sdfrstatic int tx_speed = 2; 100130407Sdfrstatic int rx_queue_len = FWMAXQUEUE; 101130407Sdfr 102130407SdfrMALLOC_DEFINE(M_FWIP, "if_fwip", "IP over FireWire interface"); 103130407SdfrSYSCTL_INT(_debug, OID_AUTO, if_fwip_debug, CTLFLAG_RW, &fwipdebug, 0, ""); 104130407SdfrSYSCTL_DECL(_hw_firewire); 105130407SdfrSYSCTL_NODE(_hw_firewire, OID_AUTO, fwip, CTLFLAG_RD, 0, 106130407Sdfr "Firewire ip subsystem"); 107130407SdfrSYSCTL_INT(_hw_firewire_fwip, OID_AUTO, rx_queue_len, CTLFLAG_RW, &rx_queue_len, 108130407Sdfr 0, "Length of the receive queue"); 109130407Sdfr 110130407SdfrTUNABLE_INT("hw.firewire.fwip.rx_queue_len", &rx_queue_len); 111130407Sdfr 112130407Sdfr#ifdef DEVICE_POLLING 113130407Sdfrstatic poll_handler_t fwip_poll; 114130407Sdfr 115130407Sdfrstatic void 116130407Sdfrfwip_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 117130407Sdfr{ 118130407Sdfr struct fwip_softc *fwip; 119130407Sdfr struct firewire_comm *fc; 120130407Sdfr 121150789Sglebius if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 122150789Sglebius return; 123150789Sglebius 124130407Sdfr fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; 125130407Sdfr fc = fwip->fd.fc; 126130407Sdfr fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count); 127130407Sdfr} 128150789Sglebius#endif /* DEVICE_POLLING */ 129150789Sglebius 130130407Sdfrstatic void 131130407Sdfrfwip_identify(driver_t *driver, device_t parent) 132130407Sdfr{ 133130407Sdfr BUS_ADD_CHILD(parent, 0, "fwip", device_get_unit(parent)); 134130407Sdfr} 135130407Sdfr 136130407Sdfrstatic int 137130407Sdfrfwip_probe(device_t dev) 138130407Sdfr{ 139130407Sdfr device_t pa; 140130407Sdfr 141130407Sdfr pa = device_get_parent(dev); 142130407Sdfr if(device_get_unit(dev) != device_get_unit(pa)){ 143130407Sdfr return(ENXIO); 144130407Sdfr } 145130407Sdfr 146130407Sdfr device_set_desc(dev, "IP over FireWire"); 147130407Sdfr return (0); 148130407Sdfr} 149130407Sdfr 150130407Sdfrstatic int 151130407Sdfrfwip_attach(device_t dev) 152130407Sdfr{ 153130407Sdfr struct fwip_softc *fwip; 154130407Sdfr struct ifnet *ifp; 155130407Sdfr int unit, s; 156130407Sdfr struct fw_hwaddr *hwaddr; 157130407Sdfr 158130407Sdfr fwip = ((struct fwip_softc *)device_get_softc(dev)); 159130407Sdfr unit = device_get_unit(dev); 160147256Sbrooks ifp = fwip->fw_softc.fwip_ifp = if_alloc(IFT_IEEE1394); 161147256Sbrooks if (ifp == NULL) 162147256Sbrooks return (ENOSPC); 163130407Sdfr 164170374Ssimokawa mtx_init(&fwip->mtx, "fwip", NULL, MTX_DEF); 165130407Sdfr /* XXX */ 166130407Sdfr fwip->dma_ch = -1; 167130407Sdfr 168130407Sdfr fwip->fd.fc = device_get_ivars(dev); 169130407Sdfr if (tx_speed < 0) 170130407Sdfr tx_speed = fwip->fd.fc->speed; 171130407Sdfr 172130407Sdfr fwip->fd.dev = dev; 173130407Sdfr fwip->fd.post_explore = NULL; 174130407Sdfr fwip->fd.post_busreset = fwip_post_busreset; 175130407Sdfr fwip->fw_softc.fwip = fwip; 176130407Sdfr TASK_INIT(&fwip->start_send, 0, fwip_start_send, fwip); 177130407Sdfr 178130407Sdfr /* 179130407Sdfr * Encode our hardware the way that arp likes it. 180130407Sdfr */ 181147256Sbrooks hwaddr = &IFP2FWC(fwip->fw_softc.fwip_ifp)->fc_hwaddr; 182130407Sdfr hwaddr->sender_unique_ID_hi = htonl(fwip->fd.fc->eui.hi); 183130407Sdfr hwaddr->sender_unique_ID_lo = htonl(fwip->fd.fc->eui.lo); 184130407Sdfr hwaddr->sender_max_rec = fwip->fd.fc->maxrec; 185130407Sdfr hwaddr->sspd = fwip->fd.fc->speed; 186130407Sdfr hwaddr->sender_unicast_FIFO_hi = htons((uint16_t)(INET_FIFO >> 32)); 187130407Sdfr hwaddr->sender_unicast_FIFO_lo = htonl((uint32_t)INET_FIFO); 188130407Sdfr 189130407Sdfr /* fill the rest and attach interface */ 190130407Sdfr ifp->if_softc = &fwip->fw_softc; 191130407Sdfr 192130407Sdfr#if __FreeBSD_version >= 501113 || defined(__DragonFly__) 193130407Sdfr if_initname(ifp, device_get_name(dev), unit); 194130407Sdfr#else 195130407Sdfr ifp->if_unit = unit; 196130407Sdfr ifp->if_name = "fwip"; 197130407Sdfr#endif 198130407Sdfr ifp->if_init = fwip_init; 199130407Sdfr ifp->if_start = fwip_start; 200130407Sdfr ifp->if_ioctl = fwip_ioctl; 201170374Ssimokawa ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); 202130407Sdfr ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE; 203150789Sglebius#ifdef DEVICE_POLLING 204150789Sglebius ifp->if_capabilities |= IFCAP_POLLING; 205150789Sglebius#endif 206130407Sdfr 207130407Sdfr s = splimp(); 208130407Sdfr firewire_ifattach(ifp, hwaddr); 209130407Sdfr splx(s); 210130407Sdfr 211130407Sdfr FWIPDEBUG(ifp, "interface created\n"); 212130407Sdfr return 0; 213130407Sdfr} 214130407Sdfr 215130407Sdfrstatic void 216130407Sdfrfwip_stop(struct fwip_softc *fwip) 217130407Sdfr{ 218130407Sdfr struct firewire_comm *fc; 219130407Sdfr struct fw_xferq *xferq; 220147256Sbrooks struct ifnet *ifp = fwip->fw_softc.fwip_ifp; 221130407Sdfr struct fw_xfer *xfer, *next; 222130407Sdfr int i; 223130407Sdfr 224130407Sdfr fc = fwip->fd.fc; 225130407Sdfr 226130407Sdfr if (fwip->dma_ch >= 0) { 227130407Sdfr xferq = fc->ir[fwip->dma_ch]; 228130407Sdfr 229130407Sdfr if (xferq->flag & FWXFERQ_RUNNING) 230130407Sdfr fc->irx_disable(fc, fwip->dma_ch); 231130407Sdfr xferq->flag &= 232130407Sdfr ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM | 233130407Sdfr FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK); 234130407Sdfr xferq->hand = NULL; 235130407Sdfr 236130407Sdfr for (i = 0; i < xferq->bnchunk; i ++) 237130407Sdfr m_freem(xferq->bulkxfer[i].mbuf); 238130407Sdfr free(xferq->bulkxfer, M_FWIP); 239130407Sdfr 240130407Sdfr fw_bindremove(fc, &fwip->fwb); 241130407Sdfr for (xfer = STAILQ_FIRST(&fwip->fwb.xferlist); xfer != NULL; 242130407Sdfr xfer = next) { 243130407Sdfr next = STAILQ_NEXT(xfer, link); 244130407Sdfr fw_xfer_free(xfer); 245130407Sdfr } 246130407Sdfr 247130407Sdfr for (xfer = STAILQ_FIRST(&fwip->xferlist); xfer != NULL; 248130407Sdfr xfer = next) { 249130407Sdfr next = STAILQ_NEXT(xfer, link); 250130407Sdfr fw_xfer_free(xfer); 251130407Sdfr } 252130407Sdfr STAILQ_INIT(&fwip->xferlist); 253130407Sdfr 254130407Sdfr xferq->bulkxfer = NULL; 255130407Sdfr fwip->dma_ch = -1; 256130407Sdfr } 257130407Sdfr 258148887Srwatson#if defined(__FreeBSD__) 259148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 260148887Srwatson#else 261130407Sdfr ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 262148887Srwatson#endif 263130407Sdfr} 264130407Sdfr 265130407Sdfrstatic int 266130407Sdfrfwip_detach(device_t dev) 267130407Sdfr{ 268130407Sdfr struct fwip_softc *fwip; 269150789Sglebius struct ifnet *ifp; 270130407Sdfr int s; 271130407Sdfr 272130407Sdfr fwip = (struct fwip_softc *)device_get_softc(dev); 273150789Sglebius ifp = fwip->fw_softc.fwip_ifp; 274150789Sglebius 275150789Sglebius#ifdef DEVICE_POLLING 276150789Sglebius if (ifp->if_capenable & IFCAP_POLLING) 277150789Sglebius ether_poll_deregister(ifp); 278150789Sglebius#endif 279150789Sglebius 280130407Sdfr s = splimp(); 281130407Sdfr 282130407Sdfr fwip_stop(fwip); 283150789Sglebius firewire_ifdetach(ifp); 284150789Sglebius if_free(ifp); 285170374Ssimokawa mtx_destroy(&fwip->mtx); 286130407Sdfr 287130407Sdfr splx(s); 288130407Sdfr return 0; 289130407Sdfr} 290130407Sdfr 291130407Sdfrstatic void 292130407Sdfrfwip_init(void *arg) 293130407Sdfr{ 294130407Sdfr struct fwip_softc *fwip = ((struct fwip_eth_softc *)arg)->fwip; 295130407Sdfr struct firewire_comm *fc; 296147256Sbrooks struct ifnet *ifp = fwip->fw_softc.fwip_ifp; 297130407Sdfr struct fw_xferq *xferq; 298130407Sdfr struct fw_xfer *xfer; 299130407Sdfr struct mbuf *m; 300130407Sdfr int i; 301130407Sdfr 302130407Sdfr FWIPDEBUG(ifp, "initializing\n"); 303130407Sdfr 304130407Sdfr fc = fwip->fd.fc; 305130407Sdfr#define START 0 306130407Sdfr if (fwip->dma_ch < 0) { 307170374Ssimokawa fwip->dma_ch = fw_open_isodma(fc, /* tx */0); 308170374Ssimokawa if (fwip->dma_ch < 0) 309170374Ssimokawa return; 310170374Ssimokawa xferq = fc->ir[fwip->dma_ch]; 311170374Ssimokawa xferq->flag |= FWXFERQ_EXTBUF | 312130407Sdfr FWXFERQ_HANDLER | FWXFERQ_STREAM; 313130407Sdfr xferq->flag &= ~0xff; 314130407Sdfr xferq->flag |= broadcast_channel & 0xff; 315130407Sdfr /* register fwip_input handler */ 316130407Sdfr xferq->sc = (caddr_t) fwip; 317130407Sdfr xferq->hand = fwip_stream_input; 318130407Sdfr xferq->bnchunk = rx_queue_len; 319130407Sdfr xferq->bnpacket = 1; 320130407Sdfr xferq->psize = MCLBYTES; 321130407Sdfr xferq->queued = 0; 322130407Sdfr xferq->buf = NULL; 323130407Sdfr xferq->bulkxfer = (struct fw_bulkxfer *) malloc( 324130407Sdfr sizeof(struct fw_bulkxfer) * xferq->bnchunk, 325130407Sdfr M_FWIP, M_WAITOK); 326130407Sdfr if (xferq->bulkxfer == NULL) { 327130407Sdfr printf("if_fwip: malloc failed\n"); 328130407Sdfr return; 329130407Sdfr } 330130407Sdfr STAILQ_INIT(&xferq->stvalid); 331130407Sdfr STAILQ_INIT(&xferq->stfree); 332130407Sdfr STAILQ_INIT(&xferq->stdma); 333130407Sdfr xferq->stproc = NULL; 334130407Sdfr for (i = 0; i < xferq->bnchunk; i ++) { 335130407Sdfr m = 336130407Sdfr#if defined(__DragonFly__) || __FreeBSD_version < 500000 337130407Sdfr m_getcl(M_WAIT, MT_DATA, M_PKTHDR); 338130407Sdfr#else 339130407Sdfr m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR); 340130407Sdfr#endif 341130407Sdfr xferq->bulkxfer[i].mbuf = m; 342130407Sdfr if (m != NULL) { 343130407Sdfr m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 344130407Sdfr STAILQ_INSERT_TAIL(&xferq->stfree, 345130407Sdfr &xferq->bulkxfer[i], link); 346130407Sdfr } else 347130407Sdfr printf("fwip_as_input: m_getcl failed\n"); 348130407Sdfr } 349130407Sdfr 350130407Sdfr fwip->fwb.start = INET_FIFO; 351130407Sdfr fwip->fwb.end = INET_FIFO + 16384; /* S3200 packet size */ 352130407Sdfr 353130407Sdfr /* pre-allocate xfer */ 354130407Sdfr STAILQ_INIT(&fwip->fwb.xferlist); 355130407Sdfr for (i = 0; i < rx_queue_len; i ++) { 356130407Sdfr xfer = fw_xfer_alloc(M_FWIP); 357130407Sdfr if (xfer == NULL) 358130407Sdfr break; 359130407Sdfr m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR); 360130407Sdfr xfer->recv.payload = mtod(m, uint32_t *); 361130407Sdfr xfer->recv.pay_len = MCLBYTES; 362167632Ssimokawa xfer->hand = fwip_unicast_input; 363130407Sdfr xfer->fc = fc; 364130407Sdfr xfer->sc = (caddr_t)fwip; 365130407Sdfr xfer->mbuf = m; 366130407Sdfr STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link); 367130407Sdfr } 368130407Sdfr fw_bindadd(fc, &fwip->fwb); 369130407Sdfr 370130407Sdfr STAILQ_INIT(&fwip->xferlist); 371130407Sdfr for (i = 0; i < TX_MAX_QUEUE; i++) { 372130407Sdfr xfer = fw_xfer_alloc(M_FWIP); 373130407Sdfr if (xfer == NULL) 374130407Sdfr break; 375130407Sdfr xfer->send.spd = tx_speed; 376130407Sdfr xfer->fc = fwip->fd.fc; 377130407Sdfr xfer->sc = (caddr_t)fwip; 378167632Ssimokawa xfer->hand = fwip_output_callback; 379130407Sdfr STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); 380130407Sdfr } 381130407Sdfr } else 382130407Sdfr xferq = fc->ir[fwip->dma_ch]; 383130407Sdfr 384130407Sdfr fwip->last_dest.hi = 0; 385130407Sdfr fwip->last_dest.lo = 0; 386130407Sdfr 387130407Sdfr /* start dma */ 388130407Sdfr if ((xferq->flag & FWXFERQ_RUNNING) == 0) 389130407Sdfr fc->irx_enable(fc, fwip->dma_ch); 390130407Sdfr 391148887Srwatson#if defined(__FreeBSD__) 392148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 393148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 394148887Srwatson#else 395130407Sdfr ifp->if_flags |= IFF_RUNNING; 396130407Sdfr ifp->if_flags &= ~IFF_OACTIVE; 397148887Srwatson#endif 398130407Sdfr 399130407Sdfr#if 0 400130407Sdfr /* attempt to start output */ 401130407Sdfr fwip_start(ifp); 402130407Sdfr#endif 403130407Sdfr} 404130407Sdfr 405130407Sdfrstatic int 406130407Sdfrfwip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 407130407Sdfr{ 408130407Sdfr struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; 409130407Sdfr int s, error; 410130407Sdfr 411130407Sdfr switch (cmd) { 412130407Sdfr case SIOCSIFFLAGS: 413130407Sdfr s = splimp(); 414130407Sdfr if (ifp->if_flags & IFF_UP) { 415148887Srwatson#if defined(__FreeBSD__) 416148887Srwatson if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 417148887Srwatson#else 418130407Sdfr if (!(ifp->if_flags & IFF_RUNNING)) 419148887Srwatson#endif 420130407Sdfr fwip_init(&fwip->fw_softc); 421130407Sdfr } else { 422148887Srwatson#if defined(__FreeBSD__) 423148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) 424148887Srwatson#else 425130407Sdfr if (ifp->if_flags & IFF_RUNNING) 426148887Srwatson#endif 427130407Sdfr fwip_stop(fwip); 428130407Sdfr } 429130407Sdfr splx(s); 430130407Sdfr break; 431130407Sdfr case SIOCADDMULTI: 432130407Sdfr case SIOCDELMULTI: 433130407Sdfr break; 434150789Sglebius case SIOCSIFCAP: 435150789Sglebius#ifdef DEVICE_POLLING 436150789Sglebius { 437150789Sglebius struct ifreq *ifr = (struct ifreq *) data; 438150789Sglebius struct firewire_comm *fc = fc = fwip->fd.fc; 439130407Sdfr 440150789Sglebius if (ifr->ifr_reqcap & IFCAP_POLLING && 441150789Sglebius !(ifp->if_capenable & IFCAP_POLLING)) { 442150789Sglebius error = ether_poll_register(fwip_poll, ifp); 443150789Sglebius if (error) 444150789Sglebius return(error); 445150789Sglebius /* Disable interrupts */ 446150789Sglebius fc->set_intr(fc, 0); 447150789Sglebius ifp->if_capenable |= IFCAP_POLLING; 448150789Sglebius return (error); 449150789Sglebius 450150789Sglebius } 451150789Sglebius if (!(ifr->ifr_reqcap & IFCAP_POLLING) && 452150789Sglebius ifp->if_capenable & IFCAP_POLLING) { 453150789Sglebius error = ether_poll_deregister(ifp); 454150789Sglebius /* Enable interrupts. */ 455150789Sglebius fc->set_intr(fc, 1); 456150789Sglebius ifp->if_capenable &= ~IFCAP_POLLING; 457150789Sglebius return (error); 458150789Sglebius } 459150789Sglebius } 460150789Sglebius#endif /* DEVICE_POLLING */ 461150789Sglebius break; 462130407Sdfr#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 463130407Sdfr default: 464130407Sdfr#else 465130407Sdfr case SIOCSIFADDR: 466130407Sdfr case SIOCGIFADDR: 467130407Sdfr case SIOCSIFMTU: 468130407Sdfr#endif 469130407Sdfr s = splimp(); 470130407Sdfr error = firewire_ioctl(ifp, cmd, data); 471130407Sdfr splx(s); 472130407Sdfr return (error); 473130407Sdfr#if defined(__DragonFly__) || __FreeBSD_version < 500000 474130407Sdfr default: 475130407Sdfr return (EINVAL); 476130407Sdfr#endif 477130407Sdfr } 478130407Sdfr 479130407Sdfr return (0); 480130407Sdfr} 481130407Sdfr 482130407Sdfrstatic void 483130407Sdfrfwip_post_busreset(void *arg) 484130407Sdfr{ 485130407Sdfr struct fwip_softc *fwip = arg; 486130411Sdfr struct crom_src *src; 487130411Sdfr struct crom_chunk *root; 488130407Sdfr 489130411Sdfr src = fwip->fd.fc->crom_src; 490130411Sdfr root = fwip->fd.fc->crom_root; 491130411Sdfr 492130411Sdfr /* RFC2734 IPv4 over IEEE1394 */ 493130411Sdfr bzero(&fwip->unit4, sizeof(struct crom_chunk)); 494130411Sdfr crom_add_chunk(src, root, &fwip->unit4, CROM_UDIR); 495130411Sdfr crom_add_entry(&fwip->unit4, CSRKEY_SPEC, CSRVAL_IETF); 496130411Sdfr crom_add_simple_text(src, &fwip->unit4, &fwip->spec4, "IANA"); 497130411Sdfr crom_add_entry(&fwip->unit4, CSRKEY_VER, 1); 498130411Sdfr crom_add_simple_text(src, &fwip->unit4, &fwip->ver4, "IPv4"); 499130411Sdfr 500130411Sdfr /* RFC3146 IPv6 over IEEE1394 */ 501130411Sdfr bzero(&fwip->unit6, sizeof(struct crom_chunk)); 502130411Sdfr crom_add_chunk(src, root, &fwip->unit6, CROM_UDIR); 503130411Sdfr crom_add_entry(&fwip->unit6, CSRKEY_SPEC, CSRVAL_IETF); 504130411Sdfr crom_add_simple_text(src, &fwip->unit6, &fwip->spec6, "IANA"); 505130411Sdfr crom_add_entry(&fwip->unit6, CSRKEY_VER, 2); 506130411Sdfr crom_add_simple_text(src, &fwip->unit6, &fwip->ver6, "IPv6"); 507130411Sdfr 508130407Sdfr fwip->last_dest.hi = 0; 509130407Sdfr fwip->last_dest.lo = 0; 510147256Sbrooks firewire_busreset(fwip->fw_softc.fwip_ifp); 511130407Sdfr} 512130407Sdfr 513130407Sdfrstatic void 514130407Sdfrfwip_output_callback(struct fw_xfer *xfer) 515130407Sdfr{ 516130407Sdfr struct fwip_softc *fwip; 517130407Sdfr struct ifnet *ifp; 518130407Sdfr int s; 519130407Sdfr 520130407Sdfr fwip = (struct fwip_softc *)xfer->sc; 521147256Sbrooks ifp = fwip->fw_softc.fwip_ifp; 522130407Sdfr /* XXX error check */ 523130407Sdfr FWIPDEBUG(ifp, "resp = %d\n", xfer->resp); 524130407Sdfr if (xfer->resp != 0) 525130407Sdfr ifp->if_oerrors ++; 526130407Sdfr 527130407Sdfr m_freem(xfer->mbuf); 528130407Sdfr fw_xfer_unload(xfer); 529130407Sdfr 530130407Sdfr s = splimp(); 531170374Ssimokawa FWIP_LOCK(fwip); 532130407Sdfr STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); 533170374Ssimokawa FWIP_UNLOCK(fwip); 534130407Sdfr splx(s); 535130407Sdfr 536130407Sdfr /* for queue full */ 537170374Ssimokawa if (ifp->if_snd.ifq_head != NULL) { 538130407Sdfr fwip_start(ifp); 539170374Ssimokawa } 540130407Sdfr} 541130407Sdfr 542130407Sdfrstatic void 543130407Sdfrfwip_start(struct ifnet *ifp) 544130407Sdfr{ 545130407Sdfr struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; 546130407Sdfr int s; 547130407Sdfr 548130407Sdfr FWIPDEBUG(ifp, "starting\n"); 549130407Sdfr 550130407Sdfr if (fwip->dma_ch < 0) { 551130407Sdfr struct mbuf *m = NULL; 552130407Sdfr 553130407Sdfr FWIPDEBUG(ifp, "not ready\n"); 554130407Sdfr 555130407Sdfr s = splimp(); 556130407Sdfr do { 557130407Sdfr IF_DEQUEUE(&ifp->if_snd, m); 558130407Sdfr if (m != NULL) 559130407Sdfr m_freem(m); 560130407Sdfr ifp->if_oerrors ++; 561130407Sdfr } while (m != NULL); 562130407Sdfr splx(s); 563130407Sdfr 564130407Sdfr return; 565130407Sdfr } 566130407Sdfr 567130407Sdfr s = splimp(); 568148887Srwatson#if defined(__FreeBSD__) 569148887Srwatson ifp->if_drv_flags |= IFF_DRV_OACTIVE; 570148887Srwatson#else 571130407Sdfr ifp->if_flags |= IFF_OACTIVE; 572148887Srwatson#endif 573130407Sdfr 574130407Sdfr if (ifp->if_snd.ifq_len != 0) 575130407Sdfr fwip_async_output(fwip, ifp); 576130407Sdfr 577148887Srwatson#if defined(__FreeBSD__) 578148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 579148887Srwatson#else 580130407Sdfr ifp->if_flags &= ~IFF_OACTIVE; 581148887Srwatson#endif 582130407Sdfr splx(s); 583130407Sdfr} 584130407Sdfr 585130407Sdfr/* Async. stream output */ 586130407Sdfrstatic void 587130407Sdfrfwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) 588130407Sdfr{ 589130407Sdfr struct firewire_comm *fc = fwip->fd.fc; 590130407Sdfr struct mbuf *m; 591130407Sdfr struct m_tag *mtag; 592130407Sdfr struct fw_hwaddr *destfw; 593130407Sdfr struct fw_xfer *xfer; 594130407Sdfr struct fw_xferq *xferq; 595130407Sdfr struct fw_pkt *fp; 596130407Sdfr uint16_t nodeid; 597130460Sdfr int error; 598130407Sdfr int i = 0; 599130407Sdfr 600130407Sdfr xfer = NULL; 601170374Ssimokawa xferq = fc->atq; 602170374Ssimokawa while ((xferq->queued < xferq->maxq - 1) && 603170374Ssimokawa (ifp->if_snd.ifq_head != NULL)) { 604170374Ssimokawa FWIP_LOCK(fwip); 605130407Sdfr xfer = STAILQ_FIRST(&fwip->xferlist); 606130407Sdfr if (xfer == NULL) { 607170374Ssimokawa FWIP_UNLOCK(fwip); 608170374Ssimokawa#if 0 609130407Sdfr printf("if_fwip: lack of xfer\n"); 610170374Ssimokawa#endif 611170374Ssimokawa break; 612130407Sdfr } 613170374Ssimokawa STAILQ_REMOVE_HEAD(&fwip->xferlist, link); 614170374Ssimokawa FWIP_UNLOCK(fwip); 615170374Ssimokawa 616130407Sdfr IF_DEQUEUE(&ifp->if_snd, m); 617170374Ssimokawa if (m == NULL) { 618170374Ssimokawa FWIP_LOCK(fwip); 619170374Ssimokawa STAILQ_INSERT_HEAD(&fwip->xferlist, xfer, link); 620170374Ssimokawa FWIP_UNLOCK(fwip); 621130407Sdfr break; 622170374Ssimokawa } 623130407Sdfr 624130407Sdfr /* 625130407Sdfr * Dig out the link-level address which 626130407Sdfr * firewire_output got via arp or neighbour 627130407Sdfr * discovery. If we don't have a link-level address, 628130407Sdfr * just stick the thing on the broadcast channel. 629130407Sdfr */ 630130407Sdfr mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 0); 631130407Sdfr if (mtag == NULL) 632130407Sdfr destfw = 0; 633130407Sdfr else 634130407Sdfr destfw = (struct fw_hwaddr *) (mtag + 1); 635130407Sdfr 636130407Sdfr 637130407Sdfr /* 638130407Sdfr * We don't do any bpf stuff here - the generic code 639130407Sdfr * in firewire_output gives the packet to bpf before 640130407Sdfr * it adds the link-level encapsulation. 641130407Sdfr */ 642130407Sdfr 643130407Sdfr /* 644130407Sdfr * Put the mbuf in the xfer early in case we hit an 645130407Sdfr * error case below - fwip_output_callback will free 646130407Sdfr * the mbuf. 647130407Sdfr */ 648130407Sdfr xfer->mbuf = m; 649130407Sdfr 650130407Sdfr /* 651130407Sdfr * We use the arp result (if any) to add a suitable firewire 652130407Sdfr * packet header before handing off to the bus. 653130407Sdfr */ 654130407Sdfr fp = &xfer->send.hdr; 655130407Sdfr nodeid = FWLOCALBUS | fc->nodeid; 656130407Sdfr if ((m->m_flags & M_BCAST) || !destfw) { 657130407Sdfr /* 658130407Sdfr * Broadcast packets are sent as GASP packets with 659130407Sdfr * specifier ID 0x00005e, version 1 on the broadcast 660130407Sdfr * channel. To be conservative, we send at the 661130407Sdfr * slowest possible speed. 662130407Sdfr */ 663130407Sdfr uint32_t *p; 664130407Sdfr 665130407Sdfr M_PREPEND(m, 2*sizeof(uint32_t), M_DONTWAIT); 666130407Sdfr p = mtod(m, uint32_t *); 667130407Sdfr fp->mode.stream.len = m->m_pkthdr.len; 668130407Sdfr fp->mode.stream.chtag = broadcast_channel; 669130407Sdfr fp->mode.stream.tcode = FWTCODE_STREAM; 670130407Sdfr fp->mode.stream.sy = 0; 671130407Sdfr xfer->send.spd = 0; 672130407Sdfr p[0] = htonl(nodeid << 16); 673130407Sdfr p[1] = htonl((0x5e << 24) | 1); 674130407Sdfr } else { 675130407Sdfr /* 676130407Sdfr * Unicast packets are sent as block writes to the 677130407Sdfr * target's unicast fifo address. If we can't 678130407Sdfr * find the node address, we just give up. We 679130407Sdfr * could broadcast it but that might overflow 680130407Sdfr * the packet size limitations due to the 681130407Sdfr * extra GASP header. Note: the hardware 682130407Sdfr * address is stored in network byte order to 683130407Sdfr * make life easier for ARP. 684130407Sdfr */ 685130407Sdfr struct fw_device *fd; 686130407Sdfr struct fw_eui64 eui; 687130407Sdfr 688130407Sdfr eui.hi = ntohl(destfw->sender_unique_ID_hi); 689130407Sdfr eui.lo = ntohl(destfw->sender_unique_ID_lo); 690130407Sdfr if (fwip->last_dest.hi != eui.hi || 691130407Sdfr fwip->last_dest.lo != eui.lo) { 692130407Sdfr fd = fw_noderesolve_eui64(fc, &eui); 693130407Sdfr if (!fd) { 694130407Sdfr /* error */ 695130407Sdfr ifp->if_oerrors ++; 696130407Sdfr /* XXX set error code */ 697130407Sdfr fwip_output_callback(xfer); 698130407Sdfr continue; 699130407Sdfr 700130407Sdfr } 701130407Sdfr fwip->last_hdr.mode.wreqb.dst = FWLOCALBUS | fd->dst; 702130407Sdfr fwip->last_hdr.mode.wreqb.tlrt = 0; 703130407Sdfr fwip->last_hdr.mode.wreqb.tcode = FWTCODE_WREQB; 704130407Sdfr fwip->last_hdr.mode.wreqb.pri = 0; 705130407Sdfr fwip->last_hdr.mode.wreqb.src = nodeid; 706130407Sdfr fwip->last_hdr.mode.wreqb.dest_hi = 707130407Sdfr ntohs(destfw->sender_unicast_FIFO_hi); 708130407Sdfr fwip->last_hdr.mode.wreqb.dest_lo = 709130407Sdfr ntohl(destfw->sender_unicast_FIFO_lo); 710130407Sdfr fwip->last_hdr.mode.wreqb.extcode = 0; 711130407Sdfr fwip->last_dest = eui; 712130407Sdfr } 713130407Sdfr 714130407Sdfr fp->mode.wreqb = fwip->last_hdr.mode.wreqb; 715130407Sdfr fp->mode.wreqb.len = m->m_pkthdr.len; 716130407Sdfr xfer->send.spd = min(destfw->sspd, fc->speed); 717130407Sdfr } 718130407Sdfr 719130407Sdfr xfer->send.pay_len = m->m_pkthdr.len; 720130407Sdfr 721130460Sdfr error = fw_asyreq(fc, -1, xfer); 722130460Sdfr if (error == EAGAIN) { 723130460Sdfr /* 724130460Sdfr * We ran out of tlabels - requeue the packet 725130460Sdfr * for later transmission. 726130460Sdfr */ 727130460Sdfr xfer->mbuf = 0; 728170374Ssimokawa FWIP_LOCK(fwip); 729130460Sdfr STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); 730170374Ssimokawa FWIP_UNLOCK(fwip); 731130460Sdfr IF_PREPEND(&ifp->if_snd, m); 732130460Sdfr break; 733130460Sdfr } 734130460Sdfr if (error) { 735130407Sdfr /* error */ 736130407Sdfr ifp->if_oerrors ++; 737130407Sdfr /* XXX set error code */ 738130407Sdfr fwip_output_callback(xfer); 739130407Sdfr continue; 740130407Sdfr } else { 741130407Sdfr ifp->if_opackets ++; 742130407Sdfr i++; 743130407Sdfr } 744130407Sdfr } 745130407Sdfr#if 0 746130407Sdfr if (i > 1) 747130407Sdfr printf("%d queued\n", i); 748130407Sdfr#endif 749170374Ssimokawa if (i > 0) 750130407Sdfr xferq->start(fc); 751130407Sdfr} 752130407Sdfr 753130407Sdfrstatic void 754130407Sdfrfwip_start_send (void *arg, int count) 755130407Sdfr{ 756130407Sdfr struct fwip_softc *fwip = arg; 757130407Sdfr 758130407Sdfr fwip->fd.fc->atq->start(fwip->fd.fc); 759130407Sdfr} 760130407Sdfr 761130407Sdfr/* Async. stream output */ 762130407Sdfrstatic void 763130407Sdfrfwip_stream_input(struct fw_xferq *xferq) 764130407Sdfr{ 765130407Sdfr struct mbuf *m, *m0; 766130407Sdfr struct m_tag *mtag; 767130407Sdfr struct ifnet *ifp; 768130407Sdfr struct fwip_softc *fwip; 769130407Sdfr struct fw_bulkxfer *sxfer; 770130407Sdfr struct fw_pkt *fp; 771130407Sdfr uint16_t src; 772130407Sdfr uint32_t *p; 773130407Sdfr 774130407Sdfr 775130407Sdfr fwip = (struct fwip_softc *)xferq->sc; 776147256Sbrooks ifp = fwip->fw_softc.fwip_ifp; 777150789Sglebius 778130407Sdfr while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) { 779130407Sdfr STAILQ_REMOVE_HEAD(&xferq->stvalid, link); 780130407Sdfr fp = mtod(sxfer->mbuf, struct fw_pkt *); 781130407Sdfr if (fwip->fd.fc->irx_post != NULL) 782130407Sdfr fwip->fd.fc->irx_post(fwip->fd.fc, fp->mode.ld); 783130407Sdfr m = sxfer->mbuf; 784130407Sdfr 785130407Sdfr /* insert new rbuf */ 786130407Sdfr sxfer->mbuf = m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 787130407Sdfr if (m0 != NULL) { 788130407Sdfr m0->m_len = m0->m_pkthdr.len = m0->m_ext.ext_size; 789130407Sdfr STAILQ_INSERT_TAIL(&xferq->stfree, sxfer, link); 790130407Sdfr } else 791130407Sdfr printf("fwip_as_input: m_getcl failed\n"); 792130407Sdfr 793130407Sdfr /* 794130407Sdfr * We must have a GASP header - leave the 795130407Sdfr * encapsulation sanity checks to the generic 796130407Sdfr * code. Remeber that we also have the firewire async 797130407Sdfr * stream header even though that isn't accounted for 798130407Sdfr * in mode.stream.len. 799130407Sdfr */ 800130407Sdfr if (sxfer->resp != 0 || fp->mode.stream.len < 801130407Sdfr 2*sizeof(uint32_t)) { 802130407Sdfr m_freem(m); 803130407Sdfr ifp->if_ierrors ++; 804130407Sdfr continue; 805130407Sdfr } 806130407Sdfr m->m_len = m->m_pkthdr.len = fp->mode.stream.len 807130407Sdfr + sizeof(fp->mode.stream); 808130407Sdfr 809130407Sdfr /* 810130407Sdfr * If we received the packet on the broadcast channel, 811130407Sdfr * mark it as broadcast, otherwise we assume it must 812130407Sdfr * be multicast. 813130407Sdfr */ 814130407Sdfr if (fp->mode.stream.chtag == broadcast_channel) 815130407Sdfr m->m_flags |= M_BCAST; 816130407Sdfr else 817130407Sdfr m->m_flags |= M_MCAST; 818130407Sdfr 819130407Sdfr /* 820130407Sdfr * Make sure we recognise the GASP specifier and 821130407Sdfr * version. 822130407Sdfr */ 823130407Sdfr p = mtod(m, uint32_t *); 824130407Sdfr if ((((ntohl(p[1]) & 0xffff) << 8) | ntohl(p[2]) >> 24) != 0x00005e 825130407Sdfr || (ntohl(p[2]) & 0xffffff) != 1) { 826130407Sdfr FWIPDEBUG(ifp, "Unrecognised GASP header %#08x %#08x\n", 827130407Sdfr ntohl(p[1]), ntohl(p[2])); 828130407Sdfr m_freem(m); 829130407Sdfr ifp->if_ierrors ++; 830130407Sdfr continue; 831130407Sdfr } 832130407Sdfr 833130407Sdfr /* 834130407Sdfr * Record the sender ID for possible BPF usage. 835130407Sdfr */ 836130407Sdfr src = ntohl(p[1]) >> 16; 837165632Sjhb if (bpf_peers_present(ifp->if_bpf)) { 838130407Sdfr mtag = m_tag_alloc(MTAG_FIREWIRE, 839130407Sdfr MTAG_FIREWIRE_SENDER_EUID, 840130407Sdfr 2*sizeof(uint32_t), M_NOWAIT); 841130407Sdfr if (mtag) { 842130407Sdfr /* bpf wants it in network byte order */ 843130407Sdfr struct fw_device *fd; 844130407Sdfr uint32_t *p = (uint32_t *) (mtag + 1); 845130407Sdfr fd = fw_noderesolve_nodeid(fwip->fd.fc, 846130407Sdfr src & 0x3f); 847130407Sdfr if (fd) { 848130407Sdfr p[0] = htonl(fd->eui.hi); 849130407Sdfr p[1] = htonl(fd->eui.lo); 850130407Sdfr } else { 851130407Sdfr p[0] = 0; 852130407Sdfr p[1] = 0; 853130407Sdfr } 854130407Sdfr m_tag_prepend(m, mtag); 855130407Sdfr } 856130407Sdfr } 857130407Sdfr 858130407Sdfr /* 859130407Sdfr * Trim off the GASP header 860130407Sdfr */ 861130407Sdfr m_adj(m, 3*sizeof(uint32_t)); 862130407Sdfr m->m_pkthdr.rcvif = ifp; 863130407Sdfr firewire_input(ifp, m, src); 864130407Sdfr ifp->if_ipackets ++; 865130407Sdfr } 866130407Sdfr if (STAILQ_FIRST(&xferq->stfree) != NULL) 867130407Sdfr fwip->fd.fc->irx_enable(fwip->fd.fc, fwip->dma_ch); 868130407Sdfr} 869130407Sdfr 870130407Sdfrstatic __inline void 871130407Sdfrfwip_unicast_input_recycle(struct fwip_softc *fwip, struct fw_xfer *xfer) 872130407Sdfr{ 873130407Sdfr struct mbuf *m; 874130407Sdfr 875130407Sdfr /* 876130407Sdfr * We have finished with a unicast xfer. Allocate a new 877130407Sdfr * cluster and stick it on the back of the input queue. 878130407Sdfr */ 879130407Sdfr m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR); 880130407Sdfr xfer->mbuf = m; 881130407Sdfr xfer->recv.payload = mtod(m, uint32_t *); 882130407Sdfr xfer->recv.pay_len = MCLBYTES; 883130407Sdfr xfer->mbuf = m; 884130407Sdfr STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link); 885130407Sdfr} 886130407Sdfr 887130407Sdfrstatic void 888130407Sdfrfwip_unicast_input(struct fw_xfer *xfer) 889130407Sdfr{ 890130407Sdfr uint64_t address; 891130407Sdfr struct mbuf *m; 892130407Sdfr struct m_tag *mtag; 893130407Sdfr struct ifnet *ifp; 894130407Sdfr struct fwip_softc *fwip; 895130407Sdfr struct fw_pkt *fp; 896130407Sdfr //struct fw_pkt *sfp; 897130407Sdfr int rtcode; 898130407Sdfr 899130407Sdfr fwip = (struct fwip_softc *)xfer->sc; 900147256Sbrooks ifp = fwip->fw_softc.fwip_ifp; 901130407Sdfr m = xfer->mbuf; 902130407Sdfr xfer->mbuf = 0; 903130407Sdfr fp = &xfer->recv.hdr; 904130407Sdfr 905130407Sdfr /* 906130407Sdfr * Check the fifo address - we only accept addresses of 907130407Sdfr * exactly INET_FIFO. 908130407Sdfr */ 909130407Sdfr address = ((uint64_t)fp->mode.wreqb.dest_hi << 32) 910130407Sdfr | fp->mode.wreqb.dest_lo; 911130407Sdfr if (fp->mode.wreqb.tcode != FWTCODE_WREQB) { 912130407Sdfr rtcode = FWRCODE_ER_TYPE; 913130407Sdfr } else if (address != INET_FIFO) { 914130407Sdfr rtcode = FWRCODE_ER_ADDR; 915130407Sdfr } else { 916130407Sdfr rtcode = FWRCODE_COMPLETE; 917130407Sdfr } 918130407Sdfr 919130407Sdfr /* 920130407Sdfr * Pick up a new mbuf and stick it on the back of the receive 921130407Sdfr * queue. 922130407Sdfr */ 923130407Sdfr fwip_unicast_input_recycle(fwip, xfer); 924130407Sdfr 925130407Sdfr /* 926130407Sdfr * If we've already rejected the packet, give up now. 927130407Sdfr */ 928130407Sdfr if (rtcode != FWRCODE_COMPLETE) { 929130407Sdfr m_freem(m); 930130407Sdfr ifp->if_ierrors ++; 931130407Sdfr return; 932130407Sdfr } 933130407Sdfr 934165632Sjhb if (bpf_peers_present(ifp->if_bpf)) { 935130407Sdfr /* 936130407Sdfr * Record the sender ID for possible BPF usage. 937130407Sdfr */ 938130407Sdfr mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID, 939130407Sdfr 2*sizeof(uint32_t), M_NOWAIT); 940130407Sdfr if (mtag) { 941130407Sdfr /* bpf wants it in network byte order */ 942130407Sdfr struct fw_device *fd; 943130407Sdfr uint32_t *p = (uint32_t *) (mtag + 1); 944130407Sdfr fd = fw_noderesolve_nodeid(fwip->fd.fc, 945130407Sdfr fp->mode.wreqb.src & 0x3f); 946130407Sdfr if (fd) { 947130407Sdfr p[0] = htonl(fd->eui.hi); 948130407Sdfr p[1] = htonl(fd->eui.lo); 949130407Sdfr } else { 950130407Sdfr p[0] = 0; 951130407Sdfr p[1] = 0; 952130407Sdfr } 953130407Sdfr m_tag_prepend(m, mtag); 954130407Sdfr } 955130407Sdfr } 956130407Sdfr 957130407Sdfr /* 958130407Sdfr * Hand off to the generic encapsulation code. We don't use 959130407Sdfr * ifp->if_input so that we can pass the source nodeid as an 960130407Sdfr * argument to facilitate link-level fragment reassembly. 961130407Sdfr */ 962130407Sdfr m->m_len = m->m_pkthdr.len = fp->mode.wreqb.len; 963130407Sdfr m->m_pkthdr.rcvif = ifp; 964130407Sdfr firewire_input(ifp, m, fp->mode.wreqb.src); 965130407Sdfr ifp->if_ipackets ++; 966130407Sdfr} 967130407Sdfr 968130407Sdfrstatic devclass_t fwip_devclass; 969130407Sdfr 970130407Sdfrstatic device_method_t fwip_methods[] = { 971130407Sdfr /* device interface */ 972130407Sdfr DEVMETHOD(device_identify, fwip_identify), 973130407Sdfr DEVMETHOD(device_probe, fwip_probe), 974130407Sdfr DEVMETHOD(device_attach, fwip_attach), 975130407Sdfr DEVMETHOD(device_detach, fwip_detach), 976130407Sdfr { 0, 0 } 977130407Sdfr}; 978130407Sdfr 979130407Sdfrstatic driver_t fwip_driver = { 980130407Sdfr "fwip", 981130407Sdfr fwip_methods, 982130407Sdfr sizeof(struct fwip_softc), 983130407Sdfr}; 984130407Sdfr 985130407Sdfr 986130407Sdfr#ifdef __DragonFly__ 987130407SdfrDECLARE_DUMMY_MODULE(fwip); 988130407Sdfr#endif 989130407SdfrDRIVER_MODULE(fwip, firewire, fwip_driver, fwip_devclass, 0, 0); 990130407SdfrMODULE_VERSION(fwip, 1); 991130407SdfrMODULE_DEPEND(fwip, firewire, 1, 1, 1); 992