if_fwip.c revision 150789
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 150789 2005-10-01 18:56:19Z glebius $ 37130407Sdfr */ 38130407Sdfr 39130407Sdfr#include "opt_inet.h" 40130407Sdfr 41130407Sdfr#include <sys/param.h> 42130407Sdfr#include <sys/kernel.h> 43130407Sdfr#include <sys/malloc.h> 44130407Sdfr#include <sys/mbuf.h> 45130407Sdfr#include <sys/socket.h> 46130407Sdfr#include <sys/sockio.h> 47130407Sdfr#include <sys/sysctl.h> 48130407Sdfr#include <sys/systm.h> 49130407Sdfr#include <sys/taskqueue.h> 50130407Sdfr#include <sys/module.h> 51130407Sdfr#include <sys/bus.h> 52130407Sdfr#include <machine/bus.h> 53130407Sdfr 54130407Sdfr#include <net/bpf.h> 55130407Sdfr#include <net/if.h> 56130407Sdfr#include <net/firewire.h> 57130407Sdfr#include <net/if_arp.h> 58147256Sbrooks#include <net/if_types.h> 59130407Sdfr#ifdef __DragonFly__ 60130407Sdfr#include <bus/firewire/firewire.h> 61130407Sdfr#include <bus/firewire/firewirereg.h> 62130407Sdfr#include "if_fwipvar.h" 63130407Sdfr#else 64130407Sdfr#include <dev/firewire/firewire.h> 65130407Sdfr#include <dev/firewire/firewirereg.h> 66130411Sdfr#include <dev/firewire/iec13213.h> 67130407Sdfr#include <dev/firewire/if_fwipvar.h> 68130407Sdfr#endif 69130407Sdfr 70130407Sdfr/* 71130407Sdfr * We really need a mechanism for allocating regions in the FIFO 72130407Sdfr * address space. We pick a address in the OHCI controller's 'middle' 73130407Sdfr * address space. This means that the controller will automatically 74130407Sdfr * send responses for us, which is fine since we don't have any 75130407Sdfr * important information to put in the response anyway. 76130407Sdfr */ 77130407Sdfr#define INET_FIFO 0xfffe00000000LL 78130407Sdfr 79130407Sdfr#define FWIPDEBUG if (fwipdebug) if_printf 80130407Sdfr#define TX_MAX_QUEUE (FWMAXQUEUE - 1) 81130407Sdfr 82130407Sdfr/* network interface */ 83130407Sdfrstatic void fwip_start (struct ifnet *); 84130407Sdfrstatic int fwip_ioctl (struct ifnet *, u_long, caddr_t); 85130407Sdfrstatic void fwip_init (void *); 86130407Sdfr 87130407Sdfrstatic void fwip_post_busreset (void *); 88130407Sdfrstatic void fwip_output_callback (struct fw_xfer *); 89130407Sdfrstatic void fwip_async_output (struct fwip_softc *, struct ifnet *); 90130407Sdfrstatic void fwip_start_send (void *, int); 91130407Sdfrstatic void fwip_stream_input (struct fw_xferq *); 92130407Sdfrstatic void fwip_unicast_input(struct fw_xfer *); 93130407Sdfr 94130407Sdfrstatic int fwipdebug = 0; 95132445Sdfrstatic int broadcast_channel = 0xc0 | 0x1f; /* tag | channel(XXX) */ 96130407Sdfrstatic int tx_speed = 2; 97130407Sdfrstatic int rx_queue_len = FWMAXQUEUE; 98130407Sdfr 99130407SdfrMALLOC_DEFINE(M_FWIP, "if_fwip", "IP over FireWire interface"); 100130407SdfrSYSCTL_INT(_debug, OID_AUTO, if_fwip_debug, CTLFLAG_RW, &fwipdebug, 0, ""); 101130407SdfrSYSCTL_DECL(_hw_firewire); 102130407SdfrSYSCTL_NODE(_hw_firewire, OID_AUTO, fwip, CTLFLAG_RD, 0, 103130407Sdfr "Firewire ip subsystem"); 104130407SdfrSYSCTL_INT(_hw_firewire_fwip, OID_AUTO, rx_queue_len, CTLFLAG_RW, &rx_queue_len, 105130407Sdfr 0, "Length of the receive queue"); 106130407Sdfr 107130407SdfrTUNABLE_INT("hw.firewire.fwip.rx_queue_len", &rx_queue_len); 108130407Sdfr 109130407Sdfr#ifdef DEVICE_POLLING 110130407Sdfrstatic poll_handler_t fwip_poll; 111130407Sdfr 112130407Sdfrstatic void 113130407Sdfrfwip_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 114130407Sdfr{ 115130407Sdfr struct fwip_softc *fwip; 116130407Sdfr struct firewire_comm *fc; 117130407Sdfr 118150789Sglebius if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 119150789Sglebius return; 120150789Sglebius 121130407Sdfr fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; 122130407Sdfr fc = fwip->fd.fc; 123130407Sdfr fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count); 124130407Sdfr} 125150789Sglebius#endif /* DEVICE_POLLING */ 126150789Sglebius 127130407Sdfrstatic void 128130407Sdfrfwip_identify(driver_t *driver, device_t parent) 129130407Sdfr{ 130130407Sdfr BUS_ADD_CHILD(parent, 0, "fwip", device_get_unit(parent)); 131130407Sdfr} 132130407Sdfr 133130407Sdfrstatic int 134130407Sdfrfwip_probe(device_t dev) 135130407Sdfr{ 136130407Sdfr device_t pa; 137130407Sdfr 138130407Sdfr pa = device_get_parent(dev); 139130407Sdfr if(device_get_unit(dev) != device_get_unit(pa)){ 140130407Sdfr return(ENXIO); 141130407Sdfr } 142130407Sdfr 143130407Sdfr device_set_desc(dev, "IP over FireWire"); 144130407Sdfr return (0); 145130407Sdfr} 146130407Sdfr 147130407Sdfrstatic int 148130407Sdfrfwip_attach(device_t dev) 149130407Sdfr{ 150130407Sdfr struct fwip_softc *fwip; 151130407Sdfr struct ifnet *ifp; 152130407Sdfr int unit, s; 153130407Sdfr struct fw_hwaddr *hwaddr; 154130407Sdfr 155130407Sdfr fwip = ((struct fwip_softc *)device_get_softc(dev)); 156130407Sdfr unit = device_get_unit(dev); 157147256Sbrooks ifp = fwip->fw_softc.fwip_ifp = if_alloc(IFT_IEEE1394); 158147256Sbrooks if (ifp == NULL) 159147256Sbrooks return (ENOSPC); 160130407Sdfr 161130407Sdfr /* XXX */ 162130407Sdfr fwip->dma_ch = -1; 163130407Sdfr 164130407Sdfr fwip->fd.fc = device_get_ivars(dev); 165130407Sdfr if (tx_speed < 0) 166130407Sdfr tx_speed = fwip->fd.fc->speed; 167130407Sdfr 168130407Sdfr fwip->fd.dev = dev; 169130407Sdfr fwip->fd.post_explore = NULL; 170130407Sdfr fwip->fd.post_busreset = fwip_post_busreset; 171130407Sdfr fwip->fw_softc.fwip = fwip; 172130407Sdfr TASK_INIT(&fwip->start_send, 0, fwip_start_send, fwip); 173130407Sdfr 174130407Sdfr /* 175130407Sdfr * Encode our hardware the way that arp likes it. 176130407Sdfr */ 177147256Sbrooks hwaddr = &IFP2FWC(fwip->fw_softc.fwip_ifp)->fc_hwaddr; 178130407Sdfr hwaddr->sender_unique_ID_hi = htonl(fwip->fd.fc->eui.hi); 179130407Sdfr hwaddr->sender_unique_ID_lo = htonl(fwip->fd.fc->eui.lo); 180130407Sdfr hwaddr->sender_max_rec = fwip->fd.fc->maxrec; 181130407Sdfr hwaddr->sspd = fwip->fd.fc->speed; 182130407Sdfr hwaddr->sender_unicast_FIFO_hi = htons((uint16_t)(INET_FIFO >> 32)); 183130407Sdfr hwaddr->sender_unicast_FIFO_lo = htonl((uint32_t)INET_FIFO); 184130407Sdfr 185130407Sdfr /* fill the rest and attach interface */ 186130407Sdfr ifp->if_softc = &fwip->fw_softc; 187130407Sdfr 188130407Sdfr#if __FreeBSD_version >= 501113 || defined(__DragonFly__) 189130407Sdfr if_initname(ifp, device_get_name(dev), unit); 190130407Sdfr#else 191130407Sdfr ifp->if_unit = unit; 192130407Sdfr ifp->if_name = "fwip"; 193130407Sdfr#endif 194130407Sdfr ifp->if_init = fwip_init; 195130407Sdfr ifp->if_start = fwip_start; 196130407Sdfr ifp->if_ioctl = fwip_ioctl; 197133686Srwatson ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST| 198133686Srwatson IFF_NEEDSGIANT); 199130407Sdfr ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE; 200150789Sglebius#ifdef DEVICE_POLLING 201150789Sglebius ifp->if_capabilities |= IFCAP_POLLING; 202150789Sglebius#endif 203130407Sdfr 204130407Sdfr s = splimp(); 205130407Sdfr firewire_ifattach(ifp, hwaddr); 206130407Sdfr splx(s); 207130407Sdfr 208130407Sdfr FWIPDEBUG(ifp, "interface created\n"); 209130407Sdfr return 0; 210130407Sdfr} 211130407Sdfr 212130407Sdfrstatic void 213130407Sdfrfwip_stop(struct fwip_softc *fwip) 214130407Sdfr{ 215130407Sdfr struct firewire_comm *fc; 216130407Sdfr struct fw_xferq *xferq; 217147256Sbrooks struct ifnet *ifp = fwip->fw_softc.fwip_ifp; 218130407Sdfr struct fw_xfer *xfer, *next; 219130407Sdfr int i; 220130407Sdfr 221130407Sdfr fc = fwip->fd.fc; 222130407Sdfr 223130407Sdfr if (fwip->dma_ch >= 0) { 224130407Sdfr xferq = fc->ir[fwip->dma_ch]; 225130407Sdfr 226130407Sdfr if (xferq->flag & FWXFERQ_RUNNING) 227130407Sdfr fc->irx_disable(fc, fwip->dma_ch); 228130407Sdfr xferq->flag &= 229130407Sdfr ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM | 230130407Sdfr FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK); 231130407Sdfr xferq->hand = NULL; 232130407Sdfr 233130407Sdfr for (i = 0; i < xferq->bnchunk; i ++) 234130407Sdfr m_freem(xferq->bulkxfer[i].mbuf); 235130407Sdfr free(xferq->bulkxfer, M_FWIP); 236130407Sdfr 237130407Sdfr fw_bindremove(fc, &fwip->fwb); 238130407Sdfr for (xfer = STAILQ_FIRST(&fwip->fwb.xferlist); xfer != NULL; 239130407Sdfr xfer = next) { 240130407Sdfr next = STAILQ_NEXT(xfer, link); 241130407Sdfr fw_xfer_free(xfer); 242130407Sdfr } 243130407Sdfr 244130407Sdfr for (xfer = STAILQ_FIRST(&fwip->xferlist); xfer != NULL; 245130407Sdfr xfer = next) { 246130407Sdfr next = STAILQ_NEXT(xfer, link); 247130407Sdfr fw_xfer_free(xfer); 248130407Sdfr } 249130407Sdfr STAILQ_INIT(&fwip->xferlist); 250130407Sdfr 251130407Sdfr xferq->bulkxfer = NULL; 252130407Sdfr fwip->dma_ch = -1; 253130407Sdfr } 254130407Sdfr 255148887Srwatson#if defined(__FreeBSD__) 256148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 257148887Srwatson#else 258130407Sdfr ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 259148887Srwatson#endif 260130407Sdfr} 261130407Sdfr 262130407Sdfrstatic int 263130407Sdfrfwip_detach(device_t dev) 264130407Sdfr{ 265130407Sdfr struct fwip_softc *fwip; 266150789Sglebius struct ifnet *ifp; 267130407Sdfr int s; 268130407Sdfr 269130407Sdfr fwip = (struct fwip_softc *)device_get_softc(dev); 270150789Sglebius ifp = fwip->fw_softc.fwip_ifp; 271150789Sglebius 272150789Sglebius#ifdef DEVICE_POLLING 273150789Sglebius if (ifp->if_capenable & IFCAP_POLLING) 274150789Sglebius ether_poll_deregister(ifp); 275150789Sglebius#endif 276150789Sglebius 277130407Sdfr s = splimp(); 278130407Sdfr 279130407Sdfr fwip_stop(fwip); 280150789Sglebius firewire_ifdetach(ifp); 281150789Sglebius if_free(ifp); 282130407Sdfr 283130407Sdfr splx(s); 284130407Sdfr return 0; 285130407Sdfr} 286130407Sdfr 287130407Sdfrstatic void 288130407Sdfrfwip_init(void *arg) 289130407Sdfr{ 290130407Sdfr struct fwip_softc *fwip = ((struct fwip_eth_softc *)arg)->fwip; 291130407Sdfr struct firewire_comm *fc; 292147256Sbrooks struct ifnet *ifp = fwip->fw_softc.fwip_ifp; 293130407Sdfr struct fw_xferq *xferq; 294130407Sdfr struct fw_xfer *xfer; 295130407Sdfr struct mbuf *m; 296130407Sdfr int i; 297130407Sdfr 298130407Sdfr FWIPDEBUG(ifp, "initializing\n"); 299130407Sdfr 300130407Sdfr fc = fwip->fd.fc; 301130407Sdfr#define START 0 302130407Sdfr if (fwip->dma_ch < 0) { 303130407Sdfr for (i = START; i < fc->nisodma; i ++) { 304130407Sdfr xferq = fc->ir[i]; 305130407Sdfr if ((xferq->flag & FWXFERQ_OPEN) == 0) 306130407Sdfr goto found; 307130407Sdfr } 308130407Sdfr printf("no free dma channel\n"); 309130407Sdfr return; 310130407Sdfrfound: 311130407Sdfr fwip->dma_ch = i; 312130407Sdfr /* allocate DMA channel and init packet mode */ 313130407Sdfr xferq->flag |= FWXFERQ_OPEN | FWXFERQ_EXTBUF | 314130407Sdfr FWXFERQ_HANDLER | FWXFERQ_STREAM; 315130407Sdfr xferq->flag &= ~0xff; 316130407Sdfr xferq->flag |= broadcast_channel & 0xff; 317130407Sdfr /* register fwip_input handler */ 318130407Sdfr xferq->sc = (caddr_t) fwip; 319130407Sdfr xferq->hand = fwip_stream_input; 320130407Sdfr xferq->bnchunk = rx_queue_len; 321130407Sdfr xferq->bnpacket = 1; 322130407Sdfr xferq->psize = MCLBYTES; 323130407Sdfr xferq->queued = 0; 324130407Sdfr xferq->buf = NULL; 325130407Sdfr xferq->bulkxfer = (struct fw_bulkxfer *) malloc( 326130407Sdfr sizeof(struct fw_bulkxfer) * xferq->bnchunk, 327130407Sdfr M_FWIP, M_WAITOK); 328130407Sdfr if (xferq->bulkxfer == NULL) { 329130407Sdfr printf("if_fwip: malloc failed\n"); 330130407Sdfr return; 331130407Sdfr } 332130407Sdfr STAILQ_INIT(&xferq->stvalid); 333130407Sdfr STAILQ_INIT(&xferq->stfree); 334130407Sdfr STAILQ_INIT(&xferq->stdma); 335130407Sdfr xferq->stproc = NULL; 336130407Sdfr for (i = 0; i < xferq->bnchunk; i ++) { 337130407Sdfr m = 338130407Sdfr#if defined(__DragonFly__) || __FreeBSD_version < 500000 339130407Sdfr m_getcl(M_WAIT, MT_DATA, M_PKTHDR); 340130407Sdfr#else 341130407Sdfr m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR); 342130407Sdfr#endif 343130407Sdfr xferq->bulkxfer[i].mbuf = m; 344130407Sdfr if (m != NULL) { 345130407Sdfr m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 346130407Sdfr STAILQ_INSERT_TAIL(&xferq->stfree, 347130407Sdfr &xferq->bulkxfer[i], link); 348130407Sdfr } else 349130407Sdfr printf("fwip_as_input: m_getcl failed\n"); 350130407Sdfr } 351130407Sdfr 352130407Sdfr fwip->fwb.start = INET_FIFO; 353130407Sdfr fwip->fwb.end = INET_FIFO + 16384; /* S3200 packet size */ 354130407Sdfr fwip->fwb.act_type = FWACT_XFER; 355130407Sdfr 356130407Sdfr /* pre-allocate xfer */ 357130407Sdfr STAILQ_INIT(&fwip->fwb.xferlist); 358130407Sdfr for (i = 0; i < rx_queue_len; i ++) { 359130407Sdfr xfer = fw_xfer_alloc(M_FWIP); 360130407Sdfr if (xfer == NULL) 361130407Sdfr break; 362130407Sdfr m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR); 363130407Sdfr xfer->recv.payload = mtod(m, uint32_t *); 364130407Sdfr xfer->recv.pay_len = MCLBYTES; 365130407Sdfr xfer->act.hand = fwip_unicast_input; 366130407Sdfr xfer->fc = fc; 367130407Sdfr xfer->sc = (caddr_t)fwip; 368130407Sdfr xfer->mbuf = m; 369130407Sdfr STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link); 370130407Sdfr } 371130407Sdfr fw_bindadd(fc, &fwip->fwb); 372130407Sdfr 373130407Sdfr STAILQ_INIT(&fwip->xferlist); 374130407Sdfr for (i = 0; i < TX_MAX_QUEUE; i++) { 375130407Sdfr xfer = fw_xfer_alloc(M_FWIP); 376130407Sdfr if (xfer == NULL) 377130407Sdfr break; 378130407Sdfr xfer->send.spd = tx_speed; 379130407Sdfr xfer->fc = fwip->fd.fc; 380130407Sdfr xfer->retry_req = fw_asybusy; 381130407Sdfr xfer->sc = (caddr_t)fwip; 382130407Sdfr xfer->act.hand = fwip_output_callback; 383130407Sdfr STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); 384130407Sdfr } 385130407Sdfr } else 386130407Sdfr xferq = fc->ir[fwip->dma_ch]; 387130407Sdfr 388130407Sdfr fwip->last_dest.hi = 0; 389130407Sdfr fwip->last_dest.lo = 0; 390130407Sdfr 391130407Sdfr /* start dma */ 392130407Sdfr if ((xferq->flag & FWXFERQ_RUNNING) == 0) 393130407Sdfr fc->irx_enable(fc, fwip->dma_ch); 394130407Sdfr 395148887Srwatson#if defined(__FreeBSD__) 396148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 397148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 398148887Srwatson#else 399130407Sdfr ifp->if_flags |= IFF_RUNNING; 400130407Sdfr ifp->if_flags &= ~IFF_OACTIVE; 401148887Srwatson#endif 402130407Sdfr 403130407Sdfr#if 0 404130407Sdfr /* attempt to start output */ 405130407Sdfr fwip_start(ifp); 406130407Sdfr#endif 407130407Sdfr} 408130407Sdfr 409130407Sdfrstatic int 410130407Sdfrfwip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 411130407Sdfr{ 412130407Sdfr struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; 413130407Sdfr int s, error; 414130407Sdfr 415130407Sdfr switch (cmd) { 416130407Sdfr case SIOCSIFFLAGS: 417130407Sdfr s = splimp(); 418130407Sdfr if (ifp->if_flags & IFF_UP) { 419148887Srwatson#if defined(__FreeBSD__) 420148887Srwatson if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 421148887Srwatson#else 422130407Sdfr if (!(ifp->if_flags & IFF_RUNNING)) 423148887Srwatson#endif 424130407Sdfr fwip_init(&fwip->fw_softc); 425130407Sdfr } else { 426148887Srwatson#if defined(__FreeBSD__) 427148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) 428148887Srwatson#else 429130407Sdfr if (ifp->if_flags & IFF_RUNNING) 430148887Srwatson#endif 431130407Sdfr fwip_stop(fwip); 432130407Sdfr } 433130407Sdfr splx(s); 434130407Sdfr break; 435130407Sdfr case SIOCADDMULTI: 436130407Sdfr case SIOCDELMULTI: 437130407Sdfr break; 438150789Sglebius case SIOCSIFCAP: 439150789Sglebius#ifdef DEVICE_POLLING 440150789Sglebius { 441150789Sglebius struct ifreq *ifr = (struct ifreq *) data; 442150789Sglebius struct firewire_comm *fc = fc = fwip->fd.fc; 443130407Sdfr 444150789Sglebius if (ifr->ifr_reqcap & IFCAP_POLLING && 445150789Sglebius !(ifp->if_capenable & IFCAP_POLLING)) { 446150789Sglebius error = ether_poll_register(fwip_poll, ifp); 447150789Sglebius if (error) 448150789Sglebius return(error); 449150789Sglebius /* Disable interrupts */ 450150789Sglebius fc->set_intr(fc, 0); 451150789Sglebius ifp->if_capenable |= IFCAP_POLLING; 452150789Sglebius return (error); 453150789Sglebius 454150789Sglebius } 455150789Sglebius if (!(ifr->ifr_reqcap & IFCAP_POLLING) && 456150789Sglebius ifp->if_capenable & IFCAP_POLLING) { 457150789Sglebius error = ether_poll_deregister(ifp); 458150789Sglebius /* Enable interrupts. */ 459150789Sglebius fc->set_intr(fc, 1); 460150789Sglebius ifp->if_capenable &= ~IFCAP_POLLING; 461150789Sglebius return (error); 462150789Sglebius } 463150789Sglebius } 464150789Sglebius#endif /* DEVICE_POLLING */ 465150789Sglebius break; 466130407Sdfr#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 467130407Sdfr default: 468130407Sdfr#else 469130407Sdfr case SIOCSIFADDR: 470130407Sdfr case SIOCGIFADDR: 471130407Sdfr case SIOCSIFMTU: 472130407Sdfr#endif 473130407Sdfr s = splimp(); 474130407Sdfr error = firewire_ioctl(ifp, cmd, data); 475130407Sdfr splx(s); 476130407Sdfr return (error); 477130407Sdfr#if defined(__DragonFly__) || __FreeBSD_version < 500000 478130407Sdfr default: 479130407Sdfr return (EINVAL); 480130407Sdfr#endif 481130407Sdfr } 482130407Sdfr 483130407Sdfr return (0); 484130407Sdfr} 485130407Sdfr 486130407Sdfrstatic void 487130407Sdfrfwip_post_busreset(void *arg) 488130407Sdfr{ 489130407Sdfr struct fwip_softc *fwip = arg; 490130411Sdfr struct crom_src *src; 491130411Sdfr struct crom_chunk *root; 492130407Sdfr 493130411Sdfr src = fwip->fd.fc->crom_src; 494130411Sdfr root = fwip->fd.fc->crom_root; 495130411Sdfr 496130411Sdfr /* RFC2734 IPv4 over IEEE1394 */ 497130411Sdfr bzero(&fwip->unit4, sizeof(struct crom_chunk)); 498130411Sdfr crom_add_chunk(src, root, &fwip->unit4, CROM_UDIR); 499130411Sdfr crom_add_entry(&fwip->unit4, CSRKEY_SPEC, CSRVAL_IETF); 500130411Sdfr crom_add_simple_text(src, &fwip->unit4, &fwip->spec4, "IANA"); 501130411Sdfr crom_add_entry(&fwip->unit4, CSRKEY_VER, 1); 502130411Sdfr crom_add_simple_text(src, &fwip->unit4, &fwip->ver4, "IPv4"); 503130411Sdfr 504130411Sdfr /* RFC3146 IPv6 over IEEE1394 */ 505130411Sdfr bzero(&fwip->unit6, sizeof(struct crom_chunk)); 506130411Sdfr crom_add_chunk(src, root, &fwip->unit6, CROM_UDIR); 507130411Sdfr crom_add_entry(&fwip->unit6, CSRKEY_SPEC, CSRVAL_IETF); 508130411Sdfr crom_add_simple_text(src, &fwip->unit6, &fwip->spec6, "IANA"); 509130411Sdfr crom_add_entry(&fwip->unit6, CSRKEY_VER, 2); 510130411Sdfr crom_add_simple_text(src, &fwip->unit6, &fwip->ver6, "IPv6"); 511130411Sdfr 512130407Sdfr fwip->last_dest.hi = 0; 513130407Sdfr fwip->last_dest.lo = 0; 514147256Sbrooks firewire_busreset(fwip->fw_softc.fwip_ifp); 515130407Sdfr} 516130407Sdfr 517130407Sdfrstatic void 518130407Sdfrfwip_output_callback(struct fw_xfer *xfer) 519130407Sdfr{ 520130407Sdfr struct fwip_softc *fwip; 521130407Sdfr struct ifnet *ifp; 522130407Sdfr int s; 523130407Sdfr 524130407Sdfr GIANT_REQUIRED; 525130407Sdfr 526130407Sdfr fwip = (struct fwip_softc *)xfer->sc; 527147256Sbrooks ifp = fwip->fw_softc.fwip_ifp; 528130407Sdfr /* XXX error check */ 529130407Sdfr FWIPDEBUG(ifp, "resp = %d\n", xfer->resp); 530130407Sdfr if (xfer->resp != 0) 531130407Sdfr ifp->if_oerrors ++; 532130407Sdfr 533130407Sdfr m_freem(xfer->mbuf); 534130407Sdfr fw_xfer_unload(xfer); 535130407Sdfr 536130407Sdfr s = splimp(); 537130407Sdfr STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); 538130407Sdfr splx(s); 539130407Sdfr 540130407Sdfr /* for queue full */ 541130407Sdfr if (ifp->if_snd.ifq_head != NULL) 542130407Sdfr fwip_start(ifp); 543130407Sdfr} 544130407Sdfr 545130407Sdfrstatic void 546130407Sdfrfwip_start(struct ifnet *ifp) 547130407Sdfr{ 548130407Sdfr struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; 549130407Sdfr int s; 550130407Sdfr 551130407Sdfr GIANT_REQUIRED; 552130407Sdfr 553130407Sdfr FWIPDEBUG(ifp, "starting\n"); 554130407Sdfr 555130407Sdfr if (fwip->dma_ch < 0) { 556130407Sdfr struct mbuf *m = NULL; 557130407Sdfr 558130407Sdfr FWIPDEBUG(ifp, "not ready\n"); 559130407Sdfr 560130407Sdfr s = splimp(); 561130407Sdfr do { 562130407Sdfr IF_DEQUEUE(&ifp->if_snd, m); 563130407Sdfr if (m != NULL) 564130407Sdfr m_freem(m); 565130407Sdfr ifp->if_oerrors ++; 566130407Sdfr } while (m != NULL); 567130407Sdfr splx(s); 568130407Sdfr 569130407Sdfr return; 570130407Sdfr } 571130407Sdfr 572130407Sdfr s = splimp(); 573148887Srwatson#if defined(__FreeBSD__) 574148887Srwatson ifp->if_drv_flags |= IFF_DRV_OACTIVE; 575148887Srwatson#else 576130407Sdfr ifp->if_flags |= IFF_OACTIVE; 577148887Srwatson#endif 578130407Sdfr 579130407Sdfr if (ifp->if_snd.ifq_len != 0) 580130407Sdfr fwip_async_output(fwip, ifp); 581130407Sdfr 582148887Srwatson#if defined(__FreeBSD__) 583148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 584148887Srwatson#else 585130407Sdfr ifp->if_flags &= ~IFF_OACTIVE; 586148887Srwatson#endif 587130407Sdfr splx(s); 588130407Sdfr} 589130407Sdfr 590130407Sdfr/* Async. stream output */ 591130407Sdfrstatic void 592130407Sdfrfwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) 593130407Sdfr{ 594130407Sdfr struct firewire_comm *fc = fwip->fd.fc; 595130407Sdfr struct mbuf *m; 596130407Sdfr struct m_tag *mtag; 597130407Sdfr struct fw_hwaddr *destfw; 598130407Sdfr struct fw_xfer *xfer; 599130407Sdfr struct fw_xferq *xferq; 600130407Sdfr struct fw_pkt *fp; 601130407Sdfr uint16_t nodeid; 602130460Sdfr int error; 603130407Sdfr int i = 0; 604130407Sdfr 605130407Sdfr GIANT_REQUIRED; 606130407Sdfr 607130407Sdfr xfer = NULL; 608130407Sdfr xferq = fwip->fd.fc->atq; 609130407Sdfr while (xferq->queued < xferq->maxq - 1) { 610130407Sdfr xfer = STAILQ_FIRST(&fwip->xferlist); 611130407Sdfr if (xfer == NULL) { 612130407Sdfr printf("if_fwip: lack of xfer\n"); 613130407Sdfr return; 614130407Sdfr } 615130407Sdfr IF_DEQUEUE(&ifp->if_snd, m); 616130407Sdfr if (m == NULL) 617130407Sdfr break; 618130407Sdfr 619130407Sdfr /* 620130407Sdfr * Dig out the link-level address which 621130407Sdfr * firewire_output got via arp or neighbour 622130407Sdfr * discovery. If we don't have a link-level address, 623130407Sdfr * just stick the thing on the broadcast channel. 624130407Sdfr */ 625130407Sdfr mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 0); 626130407Sdfr if (mtag == NULL) 627130407Sdfr destfw = 0; 628130407Sdfr else 629130407Sdfr destfw = (struct fw_hwaddr *) (mtag + 1); 630130407Sdfr 631130407Sdfr STAILQ_REMOVE_HEAD(&fwip->xferlist, link); 632130407Sdfr 633130407Sdfr /* 634130407Sdfr * We don't do any bpf stuff here - the generic code 635130407Sdfr * in firewire_output gives the packet to bpf before 636130407Sdfr * it adds the link-level encapsulation. 637130407Sdfr */ 638130407Sdfr 639130407Sdfr /* 640130407Sdfr * Put the mbuf in the xfer early in case we hit an 641130407Sdfr * error case below - fwip_output_callback will free 642130407Sdfr * the mbuf. 643130407Sdfr */ 644130407Sdfr xfer->mbuf = m; 645130407Sdfr 646130407Sdfr /* 647130407Sdfr * We use the arp result (if any) to add a suitable firewire 648130407Sdfr * packet header before handing off to the bus. 649130407Sdfr */ 650130407Sdfr fp = &xfer->send.hdr; 651130407Sdfr nodeid = FWLOCALBUS | fc->nodeid; 652130407Sdfr if ((m->m_flags & M_BCAST) || !destfw) { 653130407Sdfr /* 654130407Sdfr * Broadcast packets are sent as GASP packets with 655130407Sdfr * specifier ID 0x00005e, version 1 on the broadcast 656130407Sdfr * channel. To be conservative, we send at the 657130407Sdfr * slowest possible speed. 658130407Sdfr */ 659130407Sdfr uint32_t *p; 660130407Sdfr 661130407Sdfr M_PREPEND(m, 2*sizeof(uint32_t), M_DONTWAIT); 662130407Sdfr p = mtod(m, uint32_t *); 663130407Sdfr fp->mode.stream.len = m->m_pkthdr.len; 664130407Sdfr fp->mode.stream.chtag = broadcast_channel; 665130407Sdfr fp->mode.stream.tcode = FWTCODE_STREAM; 666130407Sdfr fp->mode.stream.sy = 0; 667130407Sdfr xfer->send.spd = 0; 668130407Sdfr p[0] = htonl(nodeid << 16); 669130407Sdfr p[1] = htonl((0x5e << 24) | 1); 670130407Sdfr } else { 671130407Sdfr /* 672130407Sdfr * Unicast packets are sent as block writes to the 673130407Sdfr * target's unicast fifo address. If we can't 674130407Sdfr * find the node address, we just give up. We 675130407Sdfr * could broadcast it but that might overflow 676130407Sdfr * the packet size limitations due to the 677130407Sdfr * extra GASP header. Note: the hardware 678130407Sdfr * address is stored in network byte order to 679130407Sdfr * make life easier for ARP. 680130407Sdfr */ 681130407Sdfr struct fw_device *fd; 682130407Sdfr struct fw_eui64 eui; 683130407Sdfr 684130407Sdfr eui.hi = ntohl(destfw->sender_unique_ID_hi); 685130407Sdfr eui.lo = ntohl(destfw->sender_unique_ID_lo); 686130407Sdfr if (fwip->last_dest.hi != eui.hi || 687130407Sdfr fwip->last_dest.lo != eui.lo) { 688130407Sdfr fd = fw_noderesolve_eui64(fc, &eui); 689130407Sdfr if (!fd) { 690130407Sdfr /* error */ 691130407Sdfr ifp->if_oerrors ++; 692130407Sdfr /* XXX set error code */ 693130407Sdfr fwip_output_callback(xfer); 694130407Sdfr continue; 695130407Sdfr 696130407Sdfr } 697130407Sdfr fwip->last_hdr.mode.wreqb.dst = FWLOCALBUS | fd->dst; 698130407Sdfr fwip->last_hdr.mode.wreqb.tlrt = 0; 699130407Sdfr fwip->last_hdr.mode.wreqb.tcode = FWTCODE_WREQB; 700130407Sdfr fwip->last_hdr.mode.wreqb.pri = 0; 701130407Sdfr fwip->last_hdr.mode.wreqb.src = nodeid; 702130407Sdfr fwip->last_hdr.mode.wreqb.dest_hi = 703130407Sdfr ntohs(destfw->sender_unicast_FIFO_hi); 704130407Sdfr fwip->last_hdr.mode.wreqb.dest_lo = 705130407Sdfr ntohl(destfw->sender_unicast_FIFO_lo); 706130407Sdfr fwip->last_hdr.mode.wreqb.extcode = 0; 707130407Sdfr fwip->last_dest = eui; 708130407Sdfr } 709130407Sdfr 710130407Sdfr fp->mode.wreqb = fwip->last_hdr.mode.wreqb; 711130407Sdfr fp->mode.wreqb.len = m->m_pkthdr.len; 712130407Sdfr xfer->send.spd = min(destfw->sspd, fc->speed); 713130407Sdfr } 714130407Sdfr 715130407Sdfr xfer->send.pay_len = m->m_pkthdr.len; 716130407Sdfr 717130460Sdfr error = fw_asyreq(fc, -1, xfer); 718130460Sdfr if (error == EAGAIN) { 719130460Sdfr /* 720130460Sdfr * We ran out of tlabels - requeue the packet 721130460Sdfr * for later transmission. 722130460Sdfr */ 723130460Sdfr xfer->mbuf = 0; 724130460Sdfr STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); 725130460Sdfr IF_PREPEND(&ifp->if_snd, m); 726130460Sdfr break; 727130460Sdfr } 728130460Sdfr if (error) { 729130407Sdfr /* error */ 730130407Sdfr ifp->if_oerrors ++; 731130407Sdfr /* XXX set error code */ 732130407Sdfr fwip_output_callback(xfer); 733130407Sdfr continue; 734130407Sdfr } else { 735130407Sdfr ifp->if_opackets ++; 736130407Sdfr i++; 737130407Sdfr } 738130407Sdfr } 739130407Sdfr#if 0 740130407Sdfr if (i > 1) 741130407Sdfr printf("%d queued\n", i); 742130407Sdfr#endif 743130407Sdfr if (i > 0) { 744130407Sdfr#if 1 745130407Sdfr xferq->start(fc); 746130407Sdfr#else 747130407Sdfr taskqueue_enqueue(taskqueue_swi_giant, &fwip->start_send); 748130407Sdfr#endif 749130407Sdfr } 750130407Sdfr} 751130407Sdfr 752130407Sdfrstatic void 753130407Sdfrfwip_start_send (void *arg, int count) 754130407Sdfr{ 755130407Sdfr struct fwip_softc *fwip = arg; 756130407Sdfr 757130407Sdfr GIANT_REQUIRED; 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 GIANT_REQUIRED; 775130407Sdfr 776130407Sdfr fwip = (struct fwip_softc *)xferq->sc; 777147256Sbrooks ifp = fwip->fw_softc.fwip_ifp; 778150789Sglebius 779130407Sdfr while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) { 780130407Sdfr STAILQ_REMOVE_HEAD(&xferq->stvalid, link); 781130407Sdfr fp = mtod(sxfer->mbuf, struct fw_pkt *); 782130407Sdfr if (fwip->fd.fc->irx_post != NULL) 783130407Sdfr fwip->fd.fc->irx_post(fwip->fd.fc, fp->mode.ld); 784130407Sdfr m = sxfer->mbuf; 785130407Sdfr 786130407Sdfr /* insert new rbuf */ 787130407Sdfr sxfer->mbuf = m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 788130407Sdfr if (m0 != NULL) { 789130407Sdfr m0->m_len = m0->m_pkthdr.len = m0->m_ext.ext_size; 790130407Sdfr STAILQ_INSERT_TAIL(&xferq->stfree, sxfer, link); 791130407Sdfr } else 792130407Sdfr printf("fwip_as_input: m_getcl failed\n"); 793130407Sdfr 794130407Sdfr /* 795130407Sdfr * We must have a GASP header - leave the 796130407Sdfr * encapsulation sanity checks to the generic 797130407Sdfr * code. Remeber that we also have the firewire async 798130407Sdfr * stream header even though that isn't accounted for 799130407Sdfr * in mode.stream.len. 800130407Sdfr */ 801130407Sdfr if (sxfer->resp != 0 || fp->mode.stream.len < 802130407Sdfr 2*sizeof(uint32_t)) { 803130407Sdfr m_freem(m); 804130407Sdfr ifp->if_ierrors ++; 805130407Sdfr continue; 806130407Sdfr } 807130407Sdfr m->m_len = m->m_pkthdr.len = fp->mode.stream.len 808130407Sdfr + sizeof(fp->mode.stream); 809130407Sdfr 810130407Sdfr /* 811130407Sdfr * If we received the packet on the broadcast channel, 812130407Sdfr * mark it as broadcast, otherwise we assume it must 813130407Sdfr * be multicast. 814130407Sdfr */ 815130407Sdfr if (fp->mode.stream.chtag == broadcast_channel) 816130407Sdfr m->m_flags |= M_BCAST; 817130407Sdfr else 818130407Sdfr m->m_flags |= M_MCAST; 819130407Sdfr 820130407Sdfr /* 821130407Sdfr * Make sure we recognise the GASP specifier and 822130407Sdfr * version. 823130407Sdfr */ 824130407Sdfr p = mtod(m, uint32_t *); 825130407Sdfr if ((((ntohl(p[1]) & 0xffff) << 8) | ntohl(p[2]) >> 24) != 0x00005e 826130407Sdfr || (ntohl(p[2]) & 0xffffff) != 1) { 827130407Sdfr FWIPDEBUG(ifp, "Unrecognised GASP header %#08x %#08x\n", 828130407Sdfr ntohl(p[1]), ntohl(p[2])); 829130407Sdfr m_freem(m); 830130407Sdfr ifp->if_ierrors ++; 831130407Sdfr continue; 832130407Sdfr } 833130407Sdfr 834130407Sdfr /* 835130407Sdfr * Record the sender ID for possible BPF usage. 836130407Sdfr */ 837130407Sdfr src = ntohl(p[1]) >> 16; 838130407Sdfr if (ifp->if_bpf) { 839130407Sdfr mtag = m_tag_alloc(MTAG_FIREWIRE, 840130407Sdfr MTAG_FIREWIRE_SENDER_EUID, 841130407Sdfr 2*sizeof(uint32_t), M_NOWAIT); 842130407Sdfr if (mtag) { 843130407Sdfr /* bpf wants it in network byte order */ 844130407Sdfr struct fw_device *fd; 845130407Sdfr uint32_t *p = (uint32_t *) (mtag + 1); 846130407Sdfr fd = fw_noderesolve_nodeid(fwip->fd.fc, 847130407Sdfr src & 0x3f); 848130407Sdfr if (fd) { 849130407Sdfr p[0] = htonl(fd->eui.hi); 850130407Sdfr p[1] = htonl(fd->eui.lo); 851130407Sdfr } else { 852130407Sdfr p[0] = 0; 853130407Sdfr p[1] = 0; 854130407Sdfr } 855130407Sdfr m_tag_prepend(m, mtag); 856130407Sdfr } 857130407Sdfr } 858130407Sdfr 859130407Sdfr /* 860130407Sdfr * Trim off the GASP header 861130407Sdfr */ 862130407Sdfr m_adj(m, 3*sizeof(uint32_t)); 863130407Sdfr m->m_pkthdr.rcvif = ifp; 864130407Sdfr firewire_input(ifp, m, src); 865130407Sdfr ifp->if_ipackets ++; 866130407Sdfr } 867130407Sdfr if (STAILQ_FIRST(&xferq->stfree) != NULL) 868130407Sdfr fwip->fd.fc->irx_enable(fwip->fd.fc, fwip->dma_ch); 869130407Sdfr} 870130407Sdfr 871130407Sdfrstatic __inline void 872130407Sdfrfwip_unicast_input_recycle(struct fwip_softc *fwip, struct fw_xfer *xfer) 873130407Sdfr{ 874130407Sdfr struct mbuf *m; 875130407Sdfr 876130407Sdfr GIANT_REQUIRED; 877130407Sdfr 878130407Sdfr /* 879130407Sdfr * We have finished with a unicast xfer. Allocate a new 880130407Sdfr * cluster and stick it on the back of the input queue. 881130407Sdfr */ 882130407Sdfr m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR); 883130407Sdfr xfer->mbuf = m; 884130407Sdfr xfer->recv.payload = mtod(m, uint32_t *); 885130407Sdfr xfer->recv.pay_len = MCLBYTES; 886130407Sdfr xfer->mbuf = m; 887130407Sdfr STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link); 888130407Sdfr} 889130407Sdfr 890130407Sdfrstatic void 891130407Sdfrfwip_unicast_input(struct fw_xfer *xfer) 892130407Sdfr{ 893130407Sdfr uint64_t address; 894130407Sdfr struct mbuf *m; 895130407Sdfr struct m_tag *mtag; 896130407Sdfr struct ifnet *ifp; 897130407Sdfr struct fwip_softc *fwip; 898130407Sdfr struct fw_pkt *fp; 899130407Sdfr //struct fw_pkt *sfp; 900130407Sdfr int rtcode; 901130407Sdfr 902130407Sdfr GIANT_REQUIRED; 903130407Sdfr 904130407Sdfr fwip = (struct fwip_softc *)xfer->sc; 905147256Sbrooks ifp = fwip->fw_softc.fwip_ifp; 906130407Sdfr m = xfer->mbuf; 907130407Sdfr xfer->mbuf = 0; 908130407Sdfr fp = &xfer->recv.hdr; 909130407Sdfr 910130407Sdfr /* 911130407Sdfr * Check the fifo address - we only accept addresses of 912130407Sdfr * exactly INET_FIFO. 913130407Sdfr */ 914130407Sdfr address = ((uint64_t)fp->mode.wreqb.dest_hi << 32) 915130407Sdfr | fp->mode.wreqb.dest_lo; 916130407Sdfr if (fp->mode.wreqb.tcode != FWTCODE_WREQB) { 917130407Sdfr rtcode = FWRCODE_ER_TYPE; 918130407Sdfr } else if (address != INET_FIFO) { 919130407Sdfr rtcode = FWRCODE_ER_ADDR; 920130407Sdfr } else { 921130407Sdfr rtcode = FWRCODE_COMPLETE; 922130407Sdfr } 923130407Sdfr 924130407Sdfr /* 925130407Sdfr * Pick up a new mbuf and stick it on the back of the receive 926130407Sdfr * queue. 927130407Sdfr */ 928130407Sdfr fwip_unicast_input_recycle(fwip, xfer); 929130407Sdfr 930130407Sdfr /* 931130407Sdfr * If we've already rejected the packet, give up now. 932130407Sdfr */ 933130407Sdfr if (rtcode != FWRCODE_COMPLETE) { 934130407Sdfr m_freem(m); 935130407Sdfr ifp->if_ierrors ++; 936130407Sdfr return; 937130407Sdfr } 938130407Sdfr 939130407Sdfr if (ifp->if_bpf) { 940130407Sdfr /* 941130407Sdfr * Record the sender ID for possible BPF usage. 942130407Sdfr */ 943130407Sdfr mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID, 944130407Sdfr 2*sizeof(uint32_t), M_NOWAIT); 945130407Sdfr if (mtag) { 946130407Sdfr /* bpf wants it in network byte order */ 947130407Sdfr struct fw_device *fd; 948130407Sdfr uint32_t *p = (uint32_t *) (mtag + 1); 949130407Sdfr fd = fw_noderesolve_nodeid(fwip->fd.fc, 950130407Sdfr fp->mode.wreqb.src & 0x3f); 951130407Sdfr if (fd) { 952130407Sdfr p[0] = htonl(fd->eui.hi); 953130407Sdfr p[1] = htonl(fd->eui.lo); 954130407Sdfr } else { 955130407Sdfr p[0] = 0; 956130407Sdfr p[1] = 0; 957130407Sdfr } 958130407Sdfr m_tag_prepend(m, mtag); 959130407Sdfr } 960130407Sdfr } 961130407Sdfr 962130407Sdfr /* 963130407Sdfr * Hand off to the generic encapsulation code. We don't use 964130407Sdfr * ifp->if_input so that we can pass the source nodeid as an 965130407Sdfr * argument to facilitate link-level fragment reassembly. 966130407Sdfr */ 967130407Sdfr m->m_len = m->m_pkthdr.len = fp->mode.wreqb.len; 968130407Sdfr m->m_pkthdr.rcvif = ifp; 969130407Sdfr firewire_input(ifp, m, fp->mode.wreqb.src); 970130407Sdfr ifp->if_ipackets ++; 971130407Sdfr} 972130407Sdfr 973130407Sdfrstatic devclass_t fwip_devclass; 974130407Sdfr 975130407Sdfrstatic device_method_t fwip_methods[] = { 976130407Sdfr /* device interface */ 977130407Sdfr DEVMETHOD(device_identify, fwip_identify), 978130407Sdfr DEVMETHOD(device_probe, fwip_probe), 979130407Sdfr DEVMETHOD(device_attach, fwip_attach), 980130407Sdfr DEVMETHOD(device_detach, fwip_detach), 981130407Sdfr { 0, 0 } 982130407Sdfr}; 983130407Sdfr 984130407Sdfrstatic driver_t fwip_driver = { 985130407Sdfr "fwip", 986130407Sdfr fwip_methods, 987130407Sdfr sizeof(struct fwip_softc), 988130407Sdfr}; 989130407Sdfr 990130407Sdfr 991130407Sdfr#ifdef __DragonFly__ 992130407SdfrDECLARE_DUMMY_MODULE(fwip); 993130407Sdfr#endif 994130407SdfrDRIVER_MODULE(fwip, firewire, fwip_driver, fwip_devclass, 0, 0); 995130407SdfrMODULE_VERSION(fwip, 1); 996130407SdfrMODULE_DEPEND(fwip, firewire, 1, 1, 1); 997