diff options
author | simokawa <simokawa@FreeBSD.org> | 2003-10-24 13:55:51 +0000 |
---|---|---|
committer | simokawa <simokawa@FreeBSD.org> | 2003-10-24 13:55:51 +0000 |
commit | ba78730b1c7ee8daedbf7e62f650bf3788a507c3 (patch) | |
tree | 1fb1f7981206cba66709ed60b75a1cf78da7c74d /sys/dev/firewire/fwdev.c | |
parent | 0d82acd1ef3aacc7539a97ccf21bdad7b1725a18 (diff) | |
download | FreeBSD-src-ba78730b1c7ee8daedbf7e62f650bf3788a507c3.zip FreeBSD-src-ba78730b1c7ee8daedbf7e62f650bf3788a507c3.tar.gz |
Fix for FW_ASYREQ.
- set send.pay_len correctly.
- copy response only if needed.
- remove unnecessary 'err = 0'.
Diffstat (limited to 'sys/dev/firewire/fwdev.c')
-rw-r--r-- | sys/dev/firewire/fwdev.c | 75 |
1 files changed, 36 insertions, 39 deletions
diff --git a/sys/dev/firewire/fwdev.c b/sys/dev/firewire/fwdev.c index 29af3b2..56ff4c5 100644 --- a/sys/dev/firewire/fwdev.c +++ b/sys/dev/firewire/fwdev.c @@ -471,13 +471,11 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) it->flag |= (0x3f & ichreq->ch); it->flag |= ((0x3 & ichreq->tag) << 6); d->it = it; - err = 0; break; case FW_GTSTREAM: if (it != NULL) { ichreq->ch = it->flag & 0x3f; ichreq->tag = it->flag >> 2 & 0x3; - err = 0; } else err = EINVAL; break; @@ -507,13 +505,11 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) if (d->ir != NULL) { ichreq->ch = ir->flag & 0x3f; ichreq->tag = ir->flag >> 2 & 0x3; - err = 0; } else err = EINVAL; break; case FW_SSTBUF: bcopy(ibufreq, &d->bufreq, sizeof(d->bufreq)); - err = 0; break; case FW_GSTBUF: bzero(&ibufreq->rx, sizeof(ibufreq->rx)); @@ -532,14 +528,18 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) case FW_ASYREQ: { struct tcode_info *tinfo; + int pay_len = 0; - xfer = fw_xfer_alloc_buf(M_FWXFER, asyreq->req.len, - PAGE_SIZE/*XXX*/); - if(xfer == NULL){ - err = ENOMEM; - return err; - } fp = &asyreq->pkt; + tinfo = &sc->fc->tcode[fp->mode.hdr.tcode]; + + if ((tinfo->flag & FWTI_BLOCK_ASY) != 0) + pay_len = MAX(0, asyreq->req.len - tinfo->hdr_len); + + xfer = fw_xfer_alloc_buf(M_FWXFER, pay_len, PAGE_SIZE/*XXX*/); + if (xfer == NULL) + return (ENOMEM); + switch (asyreq->req.type) { case FWASREQNODE: break; @@ -550,7 +550,7 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) device_printf(sc->fc->bdev, "cannot find node\n"); err = EINVAL; - goto error; + goto out; } fp->mode.hdr.dst = FWLOCALBUS | fwdev->dst; break; @@ -561,38 +561,35 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) /* nothing to do */ break; } - 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) + if (pay_len > 0) bcopy((char *)fp + tinfo->hdr_len, - (void *)&xfer->send.payload, - asyreq->req.len - tinfo->hdr_len); + (void *)&xfer->send.payload, pay_len); + xfer->send.spd = asyreq->req.sped; xfer->act.hand = fw_asy_callback; - err = fw_asyreq(sc->fc, -1, xfer); - if(err){ - fw_xfer_free_buf(xfer); - return err; - } - err = tsleep(xfer, FWPRI, "asyreq", hz); - 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.hdr, fp, tinfo->hdr_len); - bcopy(xfer->recv.payload, - (char *)fp + tinfo->hdr_len, - asyreq->req.len - tinfo->hdr_len); + + if ((err = fw_asyreq(sc->fc, -1, xfer)) != 0) + goto out; + if ((err = tsleep(xfer, FWPRI, "asyreq", hz)) != 0) + goto out; + if (xfer->resp != 0) { + err = EIO; + goto out; } -error: + if ((tinfo->flag & FWTI_TLABEL) == 0) + goto out; + + /* copy response */ + 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.hdr, fp, tinfo->hdr_len); + bcopy(xfer->recv.payload, (char *)fp + tinfo->hdr_len, + MAX(0, asyreq->req.len - tinfo->hdr_len)); +out: fw_xfer_free_buf(xfer); break; } |