diff options
author | simokawa <simokawa@FreeBSD.org> | 2003-10-02 04:06:56 +0000 |
---|---|---|
committer | simokawa <simokawa@FreeBSD.org> | 2003-10-02 04:06:56 +0000 |
commit | db5d831317931b7bb1d2ea7b34c895d5de9e931e (patch) | |
tree | 7f27d60f89b5c06e7ea329138d86ab46f08532d4 /sys/dev/firewire/fwdev.c | |
parent | 1c522512fd8b855dc3d6dbd26fed59bda6e9f0e4 (diff) | |
download | FreeBSD-src-db5d831317931b7bb1d2ea7b34c895d5de9e931e.zip FreeBSD-src-db5d831317931b7bb1d2ea7b34c895d5de9e931e.tar.gz |
MFp4: Change struct fw_xfer to reduce memory copy in fwmem_*() functions.
And many changes.
* all
- Major change of struct fw_xfer.
o {send,recv}.buf is splitted into hdr and payload.
o Remove unnecessary fields.
o spd is moved under send and recv.
- Remove unnecessary 'volatile' keyword.
- Add definition of rtcode and extcode.
* firewire.c
- Ignore FWDEVINVAL devices in fw_noderesolve_nodeid().
- Check the existance of the bind before call STAILQ_REMOVE().
- Fix bug in the fw_bindadd().
- Change element of struct fw_bind for simplicity.
- Check rtcode of response packet.
- Reduce split transaction timeout to 200 msec.
(100msec is the default value in the spec.)
- Set watchdog timer cycle to 10 Hz.
- Set xfer->tv just before calling fw_get_tlabel().
* fwohci.c
- Simplifies fwohci_get_plen().
* sbp.c
- Fix byte order of multibyte scsi_status informations.
- Split sbp.c and sbp.h.
- Unit number is not necessary for FIFO¤ address.
- Reduce LOGIN_DELAY and SCAN_DELAY to 1 sec.
- Add some constants defineded in SBP-2 spec.
* fwmem.c
- Introduce fwmem_strategy() and reduce memory copy.
Diffstat (limited to 'sys/dev/firewire/fwdev.c')
-rw-r--r-- | sys/dev/firewire/fwdev.c | 86 |
1 files changed, 65 insertions, 21 deletions
diff --git a/sys/dev/firewire/fwdev.c b/sys/dev/firewire/fwdev.c index 545f1cd..29af3b2 100644 --- a/sys/dev/firewire/fwdev.c +++ b/sys/dev/firewire/fwdev.c @@ -39,6 +39,11 @@ #include <sys/systm.h> #include <sys/types.h> #include <sys/mbuf.h> +#if __FreeBSD_version < 500000 +#include <sys/buf.h> +#else +#include <sys/bio.h> +#endif #include <sys/kernel.h> #include <sys/malloc.h> @@ -67,6 +72,7 @@ static d_poll_t fw_poll; static d_read_t fw_read; /* for Isochronous packet */ static d_write_t fw_write; static d_mmap_t fw_mmap; +static d_strategy_t fw_strategy; struct cdevsw firewire_cdevsw = { @@ -78,12 +84,13 @@ struct cdevsw firewire_cdevsw = .d_ioctl = fw_ioctl, .d_poll = fw_poll, .d_mmap = fw_mmap, + .d_strategy = fw_strategy, .d_name = "fw", .d_maj = CDEV_MAJOR, .d_flags = D_MEM #else fw_open, fw_close, fw_read, fw_write, fw_ioctl, - fw_poll, fw_mmap, nostrategy, "fw", CDEV_MAJOR, + fw_poll, fw_mmap, fw_strategy, "fw", CDEV_MAJOR, nodump, nopsize, D_MEM, -1 #endif }; @@ -270,7 +277,7 @@ fw_read (dev_t dev, struct uio *uio, int ioflag) struct fw_pkt *fp; if (DEV_FWMEM(dev)) - return fwmem_read(dev, uio, ioflag); + return physio(dev, uio, ioflag); sc = devclass_get_softc(firewire_devclass, unit); @@ -303,16 +310,19 @@ readloop: err = EIO; return err; } else if(xfer != NULL) { +#if 0 /* XXX broken */ /* per packet mode or FWACT_CH bind?*/ s = splfw(); ir->queued --; STAILQ_REMOVE_HEAD(&ir->q, link); splx(s); - fp = (struct fw_pkt *)xfer->recv.buf; - if(sc->fc->irx_post != NULL) + fp = &xfer->recv.hdr; + if (sc->fc->irx_post != NULL) sc->fc->irx_post(sc->fc, fp->mode.ld); - err = uiomove(xfer->recv.buf, xfer->recv.len, uio); + err = uiomove((void *)fp, 1 /* XXX header size */, uio); + /* XXX copy payload too */ /* XXX we should recycle this xfer */ +#endif fw_xfer_free( xfer); } else if(ir->stproc != NULL) { /* iso bulkxfer */ @@ -354,7 +364,7 @@ fw_write (dev_t dev, struct uio *uio, int ioflag) struct fw_xferq *it; if (DEV_FWMEM(dev)) - return fwmem_write(dev, uio, ioflag); + return physio(dev, uio, ioflag); sc = devclass_get_softc(firewire_devclass, unit); fc = sc->fc; @@ -520,8 +530,11 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) } break; case FW_ASYREQ: + { + struct tcode_info *tinfo; + xfer = fw_xfer_alloc_buf(M_FWXFER, asyreq->req.len, - PAGE_SIZE /* XXX */); + PAGE_SIZE/*XXX*/); if(xfer == NULL){ err = ENOMEM; return err; @@ -529,7 +542,6 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) fp = &asyreq->pkt; switch (asyreq->req.type) { case FWASREQNODE: - xfer->dst = fp->mode.hdr.dst; break; case FWASREQEUI: fwdev = fw_noderesolve_eui64(sc->fc, @@ -540,8 +552,7 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) err = EINVAL; goto error; } - xfer->dst = FWLOCALBUS | fwdev->dst; - fp->mode.hdr.dst = xfer->dst; + fp->mode.hdr.dst = FWLOCALBUS | fwdev->dst; break; case FWASRESTL: /* XXX what's this? */ @@ -550,26 +561,41 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) /* nothing to do */ break; } - xfer->spd = asyreq->req.sped; - bcopy(fp, xfer->send.buf, xfer->send.len); + xfer->send.spd = asyreq->req.sped; + tinfo = &sc->fc->tcode[fp->mode.hdr.tcode]; + bcopy(fp, (void *)&xfer->send.hdr, tinfo->hdr_len); + if ((tinfo->flag & FWTI_BLOCK_ASY) != 0) + bcopy((char *)fp + tinfo->hdr_len, + (void *)&xfer->send.payload, + asyreq->req.len - tinfo->hdr_len); xfer->act.hand = fw_asy_callback; err = fw_asyreq(sc->fc, -1, xfer); if(err){ - fw_xfer_free( xfer); + fw_xfer_free_buf(xfer); return err; } err = tsleep(xfer, FWPRI, "asyreq", hz); - if(err == 0){ - if(asyreq->req.len >= xfer->recv.len){ - asyreq->req.len = xfer->recv.len; + if (err == 0) { + if (xfer->resp != 0) { + err = EIO; + goto error; + } + tinfo = &sc->fc->tcode[xfer->recv.hdr.mode.hdr.tcode]; + if (asyreq->req.len >= xfer->recv.pay_len + + tinfo->hdr_len) { + asyreq->req.len = xfer->recv.pay_len; }else{ err = EINVAL; } - bcopy(xfer->recv.buf, fp, asyreq->req.len); + bcopy(&xfer->recv.hdr, fp, tinfo->hdr_len); + bcopy(xfer->recv.payload, + (char *)fp + tinfo->hdr_len, + asyreq->req.len - tinfo->hdr_len); } error: - fw_xfer_free( xfer); + fw_xfer_free_buf(xfer); break; + } case FW_IBUSRST: sc->fc->ibr(sc->fc); break; @@ -598,13 +624,14 @@ error: err = ENOMEM; break; } - fwb->start_hi = bindreq->start.hi; - fwb->start_lo = bindreq->start.lo; - fwb->addrlen = bindreq->len; + fwb->start = ((u_int64_t)bindreq->start.hi << 32) | + bindreq->start.lo; + fwb->end = fwb->start + bindreq->len; /* XXX */ fwb->sub = ir->dmach; fwb->act_type = FWACT_CH; + /* XXX alloc buf */ xfer = fw_xfer_alloc(M_FWXFER); if(xfer == NULL){ err = ENOMEM; @@ -736,6 +763,23 @@ fw_mmap (dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nproto) return EINVAL; } +static void +fw_strategy(struct bio *bp) +{ + dev_t dev; + + dev = bp->bio_dev; + if (DEV_FWMEM(dev)) { + fwmem_strategy(bp); + return; + } + + bp->bio_error = EOPNOTSUPP; + bp->bio_flags |= BIO_ERROR; + bp->bio_resid = bp->bio_bcount; + biodone(bp); +} + int fwdev_makedev(struct firewire_softc *sc) { |