if_fwip.c revision 130407
1/* 2 * Copyright (c) 2004 3 * Doug Rabson 4 * Copyright (c) 2002-2003 5 * Hidetoshi Shimokawa. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * 18 * This product includes software developed by Hidetoshi Shimokawa. 19 * 20 * 4. Neither the name of the author nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * $FreeBSD: head/sys/dev/firewire/if_fwip.c 130407 2004-06-13 10:54:36Z dfr $ 37 */ 38 39#include "opt_inet.h" 40 41#include <sys/param.h> 42#include <sys/kernel.h> 43#include <sys/malloc.h> 44#include <sys/mbuf.h> 45#include <sys/socket.h> 46#include <sys/sockio.h> 47#include <sys/sysctl.h> 48#include <sys/systm.h> 49#include <sys/taskqueue.h> 50#include <sys/module.h> 51#include <sys/bus.h> 52#include <machine/bus.h> 53 54#include <net/bpf.h> 55#include <net/if.h> 56#include <net/firewire.h> 57#include <net/if_arp.h> 58#ifdef __DragonFly__ 59#include <bus/firewire/firewire.h> 60#include <bus/firewire/firewirereg.h> 61#include "if_fwipvar.h" 62#else 63#include <dev/firewire/firewire.h> 64#include <dev/firewire/firewirereg.h> 65#include <dev/firewire/if_fwipvar.h> 66#endif 67 68/* 69 * We really need a mechanism for allocating regions in the FIFO 70 * address space. We pick a address in the OHCI controller's 'middle' 71 * address space. This means that the controller will automatically 72 * send responses for us, which is fine since we don't have any 73 * important information to put in the response anyway. 74 */ 75#define INET_FIFO 0xfffe00000000LL 76 77#define FWIPDEBUG if (fwipdebug) if_printf 78#define TX_MAX_QUEUE (FWMAXQUEUE - 1) 79 80/* network interface */ 81static void fwip_start (struct ifnet *); 82static int fwip_ioctl (struct ifnet *, u_long, caddr_t); 83static void fwip_init (void *); 84 85static void fwip_post_busreset (void *); 86static void fwip_output_callback (struct fw_xfer *); 87static void fwip_async_output (struct fwip_softc *, struct ifnet *); 88static void fwip_start_send (void *, int); 89static void fwip_stream_input (struct fw_xferq *); 90static void fwip_unicast_input(struct fw_xfer *); 91 92static int fwipdebug = 0; 93static int broadcast_channel = 31; /* XXX */ 94static int tx_speed = 2; 95static int rx_queue_len = FWMAXQUEUE; 96 97MALLOC_DEFINE(M_FWIP, "if_fwip", "IP over FireWire interface"); 98SYSCTL_INT(_debug, OID_AUTO, if_fwip_debug, CTLFLAG_RW, &fwipdebug, 0, ""); 99SYSCTL_DECL(_hw_firewire); 100SYSCTL_NODE(_hw_firewire, OID_AUTO, fwip, CTLFLAG_RD, 0, 101 "Firewire ip subsystem"); 102SYSCTL_INT(_hw_firewire_fwip, OID_AUTO, rx_queue_len, CTLFLAG_RW, &rx_queue_len, 103 0, "Length of the receive queue"); 104 105TUNABLE_INT("hw.firewire.fwip.rx_queue_len", &rx_queue_len); 106 107#ifdef DEVICE_POLLING 108#define FWIP_POLL_REGISTER(func, fwip, ifp) \ 109 if (ether_poll_register(func, ifp)) { \ 110 struct firewire_comm *fc = (fwip)->fd.fc; \ 111 fc->set_intr(fc, 0); \ 112 } 113 114#define FWIP_POLL_DEREGISTER(fwip, ifp) \ 115 do { \ 116 struct firewire_comm *fc = (fwip)->fd.fc; \ 117 ether_poll_deregister(ifp); \ 118 fc->set_intr(fc, 1); \ 119 } while(0) \ 120 121static poll_handler_t fwip_poll; 122 123static void 124fwip_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 125{ 126 struct fwip_softc *fwip; 127 struct firewire_comm *fc; 128 129 fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; 130 fc = fwip->fd.fc; 131 if (cmd == POLL_DEREGISTER) { 132 /* enable interrupts */ 133 fc->set_intr(fc, 1); 134 return; 135 } 136 fc->poll(fc, (cmd == POLL_AND_CHECK_STATUS)?0:1, count); 137} 138#else 139#define FWIP_POLL_REGISTER(func, fwip, ifp) 140#define FWIP_POLL_DEREGISTER(fwip, ifp) 141#endif 142static void 143fwip_identify(driver_t *driver, device_t parent) 144{ 145 BUS_ADD_CHILD(parent, 0, "fwip", device_get_unit(parent)); 146} 147 148static int 149fwip_probe(device_t dev) 150{ 151 device_t pa; 152 153 pa = device_get_parent(dev); 154 if(device_get_unit(dev) != device_get_unit(pa)){ 155 return(ENXIO); 156 } 157 158 device_set_desc(dev, "IP over FireWire"); 159 return (0); 160} 161 162static int 163fwip_attach(device_t dev) 164{ 165 struct fwip_softc *fwip; 166 struct ifnet *ifp; 167 int unit, s; 168 struct fw_hwaddr *hwaddr; 169 170 fwip = ((struct fwip_softc *)device_get_softc(dev)); 171 unit = device_get_unit(dev); 172 173 bzero(fwip, sizeof(struct fwip_softc)); 174 /* XXX */ 175 fwip->dma_ch = -1; 176 177 fwip->fd.fc = device_get_ivars(dev); 178 if (tx_speed < 0) 179 tx_speed = fwip->fd.fc->speed; 180 181 fwip->fd.dev = dev; 182 fwip->fd.post_explore = NULL; 183 fwip->fd.post_busreset = fwip_post_busreset; 184 fwip->fw_softc.fwip = fwip; 185 TASK_INIT(&fwip->start_send, 0, fwip_start_send, fwip); 186 187 /* 188 * Encode our hardware the way that arp likes it. 189 */ 190 hwaddr = &fwip->fw_softc.fwcom.fc_hwaddr; 191 hwaddr->sender_unique_ID_hi = htonl(fwip->fd.fc->eui.hi); 192 hwaddr->sender_unique_ID_lo = htonl(fwip->fd.fc->eui.lo); 193 hwaddr->sender_max_rec = fwip->fd.fc->maxrec; 194 hwaddr->sspd = fwip->fd.fc->speed; 195 hwaddr->sender_unicast_FIFO_hi = htons((uint16_t)(INET_FIFO >> 32)); 196 hwaddr->sender_unicast_FIFO_lo = htonl((uint32_t)INET_FIFO); 197 198 /* fill the rest and attach interface */ 199 ifp = &fwip->fwip_if; 200 ifp->if_softc = &fwip->fw_softc; 201 202#if __FreeBSD_version >= 501113 || defined(__DragonFly__) 203 if_initname(ifp, device_get_name(dev), unit); 204#else 205 ifp->if_unit = unit; 206 ifp->if_name = "fwip"; 207#endif 208 ifp->if_init = fwip_init; 209 ifp->if_start = fwip_start; 210 ifp->if_ioctl = fwip_ioctl; 211 ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); 212 ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE; 213 214 s = splimp(); 215 firewire_ifattach(ifp, hwaddr); 216 splx(s); 217 218 FWIPDEBUG(ifp, "interface created\n"); 219 return 0; 220} 221 222static void 223fwip_stop(struct fwip_softc *fwip) 224{ 225 struct firewire_comm *fc; 226 struct fw_xferq *xferq; 227 struct ifnet *ifp = &fwip->fwip_if; 228 struct fw_xfer *xfer, *next; 229 int i; 230 231 fc = fwip->fd.fc; 232 233 FWIP_POLL_DEREGISTER(fwip, ifp); 234 235 if (fwip->dma_ch >= 0) { 236 xferq = fc->ir[fwip->dma_ch]; 237 238 if (xferq->flag & FWXFERQ_RUNNING) 239 fc->irx_disable(fc, fwip->dma_ch); 240 xferq->flag &= 241 ~(FWXFERQ_MODEMASK | FWXFERQ_OPEN | FWXFERQ_STREAM | 242 FWXFERQ_EXTBUF | FWXFERQ_HANDLER | FWXFERQ_CHTAGMASK); 243 xferq->hand = NULL; 244 245 for (i = 0; i < xferq->bnchunk; i ++) 246 m_freem(xferq->bulkxfer[i].mbuf); 247 free(xferq->bulkxfer, M_FWIP); 248 249 fw_bindremove(fc, &fwip->fwb); 250 for (xfer = STAILQ_FIRST(&fwip->fwb.xferlist); xfer != NULL; 251 xfer = next) { 252 next = STAILQ_NEXT(xfer, link); 253 fw_xfer_free(xfer); 254 } 255 256 for (xfer = STAILQ_FIRST(&fwip->xferlist); xfer != NULL; 257 xfer = next) { 258 next = STAILQ_NEXT(xfer, link); 259 fw_xfer_free(xfer); 260 } 261 STAILQ_INIT(&fwip->xferlist); 262 263 xferq->bulkxfer = NULL; 264 fwip->dma_ch = -1; 265 } 266 267 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 268} 269 270static int 271fwip_detach(device_t dev) 272{ 273 struct fwip_softc *fwip; 274 int s; 275 276 fwip = (struct fwip_softc *)device_get_softc(dev); 277 s = splimp(); 278 279 fwip_stop(fwip); 280 firewire_ifdetach(&fwip->fwip_if); 281 282 splx(s); 283 return 0; 284} 285 286static void 287fwip_init(void *arg) 288{ 289 struct fwip_softc *fwip = ((struct fwip_eth_softc *)arg)->fwip; 290 struct firewire_comm *fc; 291 struct ifnet *ifp = &fwip->fwip_if; 292 struct fw_xferq *xferq; 293 struct fw_xfer *xfer; 294 struct mbuf *m; 295 int i; 296 297 FWIPDEBUG(ifp, "initializing\n"); 298 299 fc = fwip->fd.fc; 300#define START 0 301 if (fwip->dma_ch < 0) { 302 for (i = START; i < fc->nisodma; i ++) { 303 xferq = fc->ir[i]; 304 if ((xferq->flag & FWXFERQ_OPEN) == 0) 305 goto found; 306 } 307 printf("no free dma channel\n"); 308 return; 309found: 310 fwip->dma_ch = i; 311 /* allocate DMA channel and init packet mode */ 312 xferq->flag |= FWXFERQ_OPEN | FWXFERQ_EXTBUF | 313 FWXFERQ_HANDLER | FWXFERQ_STREAM; 314 xferq->flag &= ~0xff; 315 xferq->flag |= broadcast_channel & 0xff; 316 /* register fwip_input handler */ 317 xferq->sc = (caddr_t) fwip; 318 xferq->hand = fwip_stream_input; 319 xferq->bnchunk = rx_queue_len; 320 xferq->bnpacket = 1; 321 xferq->psize = MCLBYTES; 322 xferq->queued = 0; 323 xferq->buf = NULL; 324 xferq->bulkxfer = (struct fw_bulkxfer *) malloc( 325 sizeof(struct fw_bulkxfer) * xferq->bnchunk, 326 M_FWIP, M_WAITOK); 327 if (xferq->bulkxfer == NULL) { 328 printf("if_fwip: malloc failed\n"); 329 return; 330 } 331 STAILQ_INIT(&xferq->stvalid); 332 STAILQ_INIT(&xferq->stfree); 333 STAILQ_INIT(&xferq->stdma); 334 xferq->stproc = NULL; 335 for (i = 0; i < xferq->bnchunk; i ++) { 336 m = 337#if defined(__DragonFly__) || __FreeBSD_version < 500000 338 m_getcl(M_WAIT, MT_DATA, M_PKTHDR); 339#else 340 m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR); 341#endif 342 xferq->bulkxfer[i].mbuf = m; 343 if (m != NULL) { 344 m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 345 STAILQ_INSERT_TAIL(&xferq->stfree, 346 &xferq->bulkxfer[i], link); 347 } else 348 printf("fwip_as_input: m_getcl failed\n"); 349 } 350 351 fwip->fwb.start = INET_FIFO; 352 fwip->fwb.end = INET_FIFO + 16384; /* S3200 packet size */ 353 fwip->fwb.act_type = FWACT_XFER; 354 355 /* pre-allocate xfer */ 356 STAILQ_INIT(&fwip->fwb.xferlist); 357 for (i = 0; i < rx_queue_len; i ++) { 358 xfer = fw_xfer_alloc(M_FWIP); 359 if (xfer == NULL) 360 break; 361 m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR); 362 xfer->recv.payload = mtod(m, uint32_t *); 363 xfer->recv.pay_len = MCLBYTES; 364 xfer->act.hand = fwip_unicast_input; 365 xfer->fc = fc; 366 xfer->sc = (caddr_t)fwip; 367 xfer->mbuf = m; 368 STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link); 369 } 370 fw_bindadd(fc, &fwip->fwb); 371 372 STAILQ_INIT(&fwip->xferlist); 373 for (i = 0; i < TX_MAX_QUEUE; i++) { 374 xfer = fw_xfer_alloc(M_FWIP); 375 if (xfer == NULL) 376 break; 377 xfer->send.spd = tx_speed; 378 xfer->fc = fwip->fd.fc; 379 xfer->retry_req = fw_asybusy; 380 xfer->sc = (caddr_t)fwip; 381 xfer->act.hand = fwip_output_callback; 382 STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); 383 } 384 } else 385 xferq = fc->ir[fwip->dma_ch]; 386 387 fwip->last_dest.hi = 0; 388 fwip->last_dest.lo = 0; 389 390 /* start dma */ 391 if ((xferq->flag & FWXFERQ_RUNNING) == 0) 392 fc->irx_enable(fc, fwip->dma_ch); 393 394 ifp->if_flags |= IFF_RUNNING; 395 ifp->if_flags &= ~IFF_OACTIVE; 396 397 FWIP_POLL_REGISTER(fwip_poll, fwip, ifp); 398#if 0 399 /* attempt to start output */ 400 fwip_start(ifp); 401#endif 402} 403 404static int 405fwip_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 406{ 407 struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; 408 int s, error; 409 410 switch (cmd) { 411 case SIOCSIFFLAGS: 412 s = splimp(); 413 if (ifp->if_flags & IFF_UP) { 414 if (!(ifp->if_flags & IFF_RUNNING)) 415 fwip_init(&fwip->fw_softc); 416 } else { 417 if (ifp->if_flags & IFF_RUNNING) 418 fwip_stop(fwip); 419 } 420 splx(s); 421 break; 422 case SIOCADDMULTI: 423 case SIOCDELMULTI: 424 break; 425 426#if defined(__FreeBSD__) && __FreeBSD_version >= 500000 427 default: 428#else 429 case SIOCSIFADDR: 430 case SIOCGIFADDR: 431 case SIOCSIFMTU: 432#endif 433 s = splimp(); 434 error = firewire_ioctl(ifp, cmd, data); 435 splx(s); 436 return (error); 437#if defined(__DragonFly__) || __FreeBSD_version < 500000 438 default: 439 return (EINVAL); 440#endif 441 } 442 443 return (0); 444} 445 446static void 447fwip_post_busreset(void *arg) 448{ 449 struct fwip_softc *fwip = arg; 450 451 fwip->last_dest.hi = 0; 452 fwip->last_dest.lo = 0; 453 firewire_busreset(&fwip->fwip_if); 454} 455 456static void 457fwip_output_callback(struct fw_xfer *xfer) 458{ 459 struct fwip_softc *fwip; 460 struct ifnet *ifp; 461 int s; 462 463 GIANT_REQUIRED; 464 465 fwip = (struct fwip_softc *)xfer->sc; 466 ifp = &fwip->fwip_if; 467 /* XXX error check */ 468 FWIPDEBUG(ifp, "resp = %d\n", xfer->resp); 469 if (xfer->resp != 0) 470 ifp->if_oerrors ++; 471 472 m_freem(xfer->mbuf); 473 fw_xfer_unload(xfer); 474 475 s = splimp(); 476 STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link); 477 splx(s); 478 479 /* for queue full */ 480 if (ifp->if_snd.ifq_head != NULL) 481 fwip_start(ifp); 482} 483 484static void 485fwip_start(struct ifnet *ifp) 486{ 487 struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip; 488 int s; 489 490 GIANT_REQUIRED; 491 492 FWIPDEBUG(ifp, "starting\n"); 493 494 if (fwip->dma_ch < 0) { 495 struct mbuf *m = NULL; 496 497 FWIPDEBUG(ifp, "not ready\n"); 498 499 s = splimp(); 500 do { 501 IF_DEQUEUE(&ifp->if_snd, m); 502 if (m != NULL) 503 m_freem(m); 504 ifp->if_oerrors ++; 505 } while (m != NULL); 506 splx(s); 507 508 return; 509 } 510 511 s = splimp(); 512 ifp->if_flags |= IFF_OACTIVE; 513 514 if (ifp->if_snd.ifq_len != 0) 515 fwip_async_output(fwip, ifp); 516 517 ifp->if_flags &= ~IFF_OACTIVE; 518 splx(s); 519} 520 521/* Async. stream output */ 522static void 523fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp) 524{ 525 struct firewire_comm *fc = fwip->fd.fc; 526 struct mbuf *m; 527 struct m_tag *mtag; 528 struct fw_hwaddr *destfw; 529 struct fw_xfer *xfer; 530 struct fw_xferq *xferq; 531 struct fw_pkt *fp; 532 uint16_t nodeid; 533 int i = 0; 534 535 GIANT_REQUIRED; 536 537 xfer = NULL; 538 xferq = fwip->fd.fc->atq; 539 while (xferq->queued < xferq->maxq - 1) { 540 xfer = STAILQ_FIRST(&fwip->xferlist); 541 if (xfer == NULL) { 542 printf("if_fwip: lack of xfer\n"); 543 return; 544 } 545 IF_DEQUEUE(&ifp->if_snd, m); 546 if (m == NULL) 547 break; 548 549 /* 550 * Dig out the link-level address which 551 * firewire_output got via arp or neighbour 552 * discovery. If we don't have a link-level address, 553 * just stick the thing on the broadcast channel. 554 */ 555 mtag = m_tag_locate(m, MTAG_FIREWIRE, MTAG_FIREWIRE_HWADDR, 0); 556 if (mtag == NULL) 557 destfw = 0; 558 else 559 destfw = (struct fw_hwaddr *) (mtag + 1); 560 561 STAILQ_REMOVE_HEAD(&fwip->xferlist, link); 562 563 /* 564 * We don't do any bpf stuff here - the generic code 565 * in firewire_output gives the packet to bpf before 566 * it adds the link-level encapsulation. 567 */ 568 569 /* 570 * Put the mbuf in the xfer early in case we hit an 571 * error case below - fwip_output_callback will free 572 * the mbuf. 573 */ 574 xfer->mbuf = m; 575 576 /* 577 * We use the arp result (if any) to add a suitable firewire 578 * packet header before handing off to the bus. 579 */ 580 fp = &xfer->send.hdr; 581 nodeid = FWLOCALBUS | fc->nodeid; 582 if ((m->m_flags & M_BCAST) || !destfw) { 583 /* 584 * Broadcast packets are sent as GASP packets with 585 * specifier ID 0x00005e, version 1 on the broadcast 586 * channel. To be conservative, we send at the 587 * slowest possible speed. 588 */ 589 uint32_t *p; 590 591 M_PREPEND(m, 2*sizeof(uint32_t), M_DONTWAIT); 592 p = mtod(m, uint32_t *); 593 fp->mode.stream.len = m->m_pkthdr.len; 594 fp->mode.stream.chtag = broadcast_channel; 595 fp->mode.stream.tcode = FWTCODE_STREAM; 596 fp->mode.stream.sy = 0; 597 xfer->send.spd = 0; 598 p[0] = htonl(nodeid << 16); 599 p[1] = htonl((0x5e << 24) | 1); 600 } else { 601 /* 602 * Unicast packets are sent as block writes to the 603 * target's unicast fifo address. If we can't 604 * find the node address, we just give up. We 605 * could broadcast it but that might overflow 606 * the packet size limitations due to the 607 * extra GASP header. Note: the hardware 608 * address is stored in network byte order to 609 * make life easier for ARP. 610 */ 611 struct fw_device *fd; 612 struct fw_eui64 eui; 613 614 eui.hi = ntohl(destfw->sender_unique_ID_hi); 615 eui.lo = ntohl(destfw->sender_unique_ID_lo); 616 if (fwip->last_dest.hi != eui.hi || 617 fwip->last_dest.lo != eui.lo) { 618 fd = fw_noderesolve_eui64(fc, &eui); 619 if (!fd) { 620 /* error */ 621 ifp->if_oerrors ++; 622 /* XXX set error code */ 623 fwip_output_callback(xfer); 624 continue; 625 626 } 627 fwip->last_hdr.mode.wreqb.dst = FWLOCALBUS | fd->dst; 628 fwip->last_hdr.mode.wreqb.tlrt = 0; 629 fwip->last_hdr.mode.wreqb.tcode = FWTCODE_WREQB; 630 fwip->last_hdr.mode.wreqb.pri = 0; 631 fwip->last_hdr.mode.wreqb.src = nodeid; 632 fwip->last_hdr.mode.wreqb.dest_hi = 633 ntohs(destfw->sender_unicast_FIFO_hi); 634 fwip->last_hdr.mode.wreqb.dest_lo = 635 ntohl(destfw->sender_unicast_FIFO_lo); 636 fwip->last_hdr.mode.wreqb.extcode = 0; 637 fwip->last_dest = eui; 638 } 639 640 fp->mode.wreqb = fwip->last_hdr.mode.wreqb; 641 fp->mode.wreqb.len = m->m_pkthdr.len; 642 xfer->send.spd = min(destfw->sspd, fc->speed); 643 } 644 645 xfer->send.pay_len = m->m_pkthdr.len; 646 647 if (fw_asyreq(fc, -1, xfer) != 0) { 648 /* error */ 649 ifp->if_oerrors ++; 650 /* XXX set error code */ 651 fwip_output_callback(xfer); 652 continue; 653 } else { 654 ifp->if_opackets ++; 655 i++; 656 } 657 } 658#if 0 659 if (i > 1) 660 printf("%d queued\n", i); 661#endif 662 if (i > 0) { 663#if 1 664 xferq->start(fc); 665#else 666 taskqueue_enqueue(taskqueue_swi_giant, &fwip->start_send); 667#endif 668 } 669} 670 671static void 672fwip_start_send (void *arg, int count) 673{ 674 struct fwip_softc *fwip = arg; 675 676 GIANT_REQUIRED; 677 fwip->fd.fc->atq->start(fwip->fd.fc); 678} 679 680/* Async. stream output */ 681static void 682fwip_stream_input(struct fw_xferq *xferq) 683{ 684 struct mbuf *m, *m0; 685 struct m_tag *mtag; 686 struct ifnet *ifp; 687 struct fwip_softc *fwip; 688 struct fw_bulkxfer *sxfer; 689 struct fw_pkt *fp; 690 uint16_t src; 691 uint32_t *p; 692 693 GIANT_REQUIRED; 694 695 fwip = (struct fwip_softc *)xferq->sc; 696 ifp = &fwip->fwip_if; 697#if 0 698 FWIP_POLL_REGISTER(fwip_poll, fwip, ifp); 699#endif 700 while ((sxfer = STAILQ_FIRST(&xferq->stvalid)) != NULL) { 701 STAILQ_REMOVE_HEAD(&xferq->stvalid, link); 702 fp = mtod(sxfer->mbuf, struct fw_pkt *); 703 if (fwip->fd.fc->irx_post != NULL) 704 fwip->fd.fc->irx_post(fwip->fd.fc, fp->mode.ld); 705 m = sxfer->mbuf; 706 707 /* insert new rbuf */ 708 sxfer->mbuf = m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 709 if (m0 != NULL) { 710 m0->m_len = m0->m_pkthdr.len = m0->m_ext.ext_size; 711 STAILQ_INSERT_TAIL(&xferq->stfree, sxfer, link); 712 } else 713 printf("fwip_as_input: m_getcl failed\n"); 714 715 /* 716 * We must have a GASP header - leave the 717 * encapsulation sanity checks to the generic 718 * code. Remeber that we also have the firewire async 719 * stream header even though that isn't accounted for 720 * in mode.stream.len. 721 */ 722 if (sxfer->resp != 0 || fp->mode.stream.len < 723 2*sizeof(uint32_t)) { 724 m_freem(m); 725 ifp->if_ierrors ++; 726 continue; 727 } 728 m->m_len = m->m_pkthdr.len = fp->mode.stream.len 729 + sizeof(fp->mode.stream); 730 731 /* 732 * If we received the packet on the broadcast channel, 733 * mark it as broadcast, otherwise we assume it must 734 * be multicast. 735 */ 736 if (fp->mode.stream.chtag == broadcast_channel) 737 m->m_flags |= M_BCAST; 738 else 739 m->m_flags |= M_MCAST; 740 741 /* 742 * Make sure we recognise the GASP specifier and 743 * version. 744 */ 745 p = mtod(m, uint32_t *); 746 if ((((ntohl(p[1]) & 0xffff) << 8) | ntohl(p[2]) >> 24) != 0x00005e 747 || (ntohl(p[2]) & 0xffffff) != 1) { 748 FWIPDEBUG(ifp, "Unrecognised GASP header %#08x %#08x\n", 749 ntohl(p[1]), ntohl(p[2])); 750 m_freem(m); 751 ifp->if_ierrors ++; 752 continue; 753 } 754 755 /* 756 * Record the sender ID for possible BPF usage. 757 */ 758 src = ntohl(p[1]) >> 16; 759 if (ifp->if_bpf) { 760 mtag = m_tag_alloc(MTAG_FIREWIRE, 761 MTAG_FIREWIRE_SENDER_EUID, 762 2*sizeof(uint32_t), M_NOWAIT); 763 if (mtag) { 764 /* bpf wants it in network byte order */ 765 struct fw_device *fd; 766 uint32_t *p = (uint32_t *) (mtag + 1); 767 fd = fw_noderesolve_nodeid(fwip->fd.fc, 768 src & 0x3f); 769 if (fd) { 770 p[0] = htonl(fd->eui.hi); 771 p[1] = htonl(fd->eui.lo); 772 } else { 773 p[0] = 0; 774 p[1] = 0; 775 } 776 m_tag_prepend(m, mtag); 777 } 778 } 779 780 /* 781 * Trim off the GASP header 782 */ 783 m_adj(m, 3*sizeof(uint32_t)); 784 m->m_pkthdr.rcvif = ifp; 785 firewire_input(ifp, m, src); 786 ifp->if_ipackets ++; 787 } 788 if (STAILQ_FIRST(&xferq->stfree) != NULL) 789 fwip->fd.fc->irx_enable(fwip->fd.fc, fwip->dma_ch); 790} 791 792static __inline void 793fwip_unicast_input_recycle(struct fwip_softc *fwip, struct fw_xfer *xfer) 794{ 795 struct mbuf *m; 796 797 GIANT_REQUIRED; 798 799 /* 800 * We have finished with a unicast xfer. Allocate a new 801 * cluster and stick it on the back of the input queue. 802 */ 803 m = m_getcl(M_TRYWAIT, MT_DATA, M_PKTHDR); 804 xfer->mbuf = m; 805 xfer->recv.payload = mtod(m, uint32_t *); 806 xfer->recv.pay_len = MCLBYTES; 807 xfer->mbuf = m; 808 STAILQ_INSERT_TAIL(&fwip->fwb.xferlist, xfer, link); 809} 810 811static void 812fwip_unicast_input(struct fw_xfer *xfer) 813{ 814 uint64_t address; 815 struct mbuf *m; 816 struct m_tag *mtag; 817 struct ifnet *ifp; 818 struct fwip_softc *fwip; 819 struct fw_pkt *fp; 820 //struct fw_pkt *sfp; 821 int rtcode; 822 823 GIANT_REQUIRED; 824 825 fwip = (struct fwip_softc *)xfer->sc; 826 ifp = &fwip->fwip_if; 827 m = xfer->mbuf; 828 xfer->mbuf = 0; 829 fp = &xfer->recv.hdr; 830 831 /* 832 * Check the fifo address - we only accept addresses of 833 * exactly INET_FIFO. 834 */ 835 address = ((uint64_t)fp->mode.wreqb.dest_hi << 32) 836 | fp->mode.wreqb.dest_lo; 837 if (fp->mode.wreqb.tcode != FWTCODE_WREQB) { 838 rtcode = FWRCODE_ER_TYPE; 839 } else if (address != INET_FIFO) { 840 rtcode = FWRCODE_ER_ADDR; 841 } else { 842 rtcode = FWRCODE_COMPLETE; 843 } 844 845 /* 846 * Pick up a new mbuf and stick it on the back of the receive 847 * queue. 848 */ 849 fwip_unicast_input_recycle(fwip, xfer); 850 851 /* 852 * If we've already rejected the packet, give up now. 853 */ 854 if (rtcode != FWRCODE_COMPLETE) { 855 m_freem(m); 856 ifp->if_ierrors ++; 857 return; 858 } 859 860 if (ifp->if_bpf) { 861 /* 862 * Record the sender ID for possible BPF usage. 863 */ 864 mtag = m_tag_alloc(MTAG_FIREWIRE, MTAG_FIREWIRE_SENDER_EUID, 865 2*sizeof(uint32_t), M_NOWAIT); 866 if (mtag) { 867 /* bpf wants it in network byte order */ 868 struct fw_device *fd; 869 uint32_t *p = (uint32_t *) (mtag + 1); 870 fd = fw_noderesolve_nodeid(fwip->fd.fc, 871 fp->mode.wreqb.src & 0x3f); 872 if (fd) { 873 p[0] = htonl(fd->eui.hi); 874 p[1] = htonl(fd->eui.lo); 875 } else { 876 p[0] = 0; 877 p[1] = 0; 878 } 879 m_tag_prepend(m, mtag); 880 } 881 } 882 883 /* 884 * Hand off to the generic encapsulation code. We don't use 885 * ifp->if_input so that we can pass the source nodeid as an 886 * argument to facilitate link-level fragment reassembly. 887 */ 888 m->m_len = m->m_pkthdr.len = fp->mode.wreqb.len; 889 m->m_pkthdr.rcvif = ifp; 890 firewire_input(ifp, m, fp->mode.wreqb.src); 891 ifp->if_ipackets ++; 892} 893 894static devclass_t fwip_devclass; 895 896static device_method_t fwip_methods[] = { 897 /* device interface */ 898 DEVMETHOD(device_identify, fwip_identify), 899 DEVMETHOD(device_probe, fwip_probe), 900 DEVMETHOD(device_attach, fwip_attach), 901 DEVMETHOD(device_detach, fwip_detach), 902 { 0, 0 } 903}; 904 905static driver_t fwip_driver = { 906 "fwip", 907 fwip_methods, 908 sizeof(struct fwip_softc), 909}; 910 911 912#ifdef __DragonFly__ 913DECLARE_DUMMY_MODULE(fwip); 914#endif 915DRIVER_MODULE(fwip, firewire, fwip_driver, fwip_devclass, 0, 0); 916MODULE_VERSION(fwip, 1); 917MODULE_DEPEND(fwip, firewire, 1, 1, 1); 918