MFp4: Fix broken userland API for async packets.
- Introduce fw_xferlist_add/remove(). - Introduce fw_read/write_async(). - Remove unused FWACT_CH. MFC after: 1 week
This commit is contained in:
parent
3cb8dc7cd5
commit
0892f4c5ec
@ -716,9 +716,6 @@ void fw_init(struct firewire_comm *fc)
|
||||
|
||||
STAILQ_INIT(&fc->it[i]->q);
|
||||
STAILQ_INIT(&fc->ir[i]->q);
|
||||
|
||||
STAILQ_INIT(&fc->it[i]->binds);
|
||||
STAILQ_INIT(&fc->ir[i]->binds);
|
||||
}
|
||||
|
||||
fc->arq->maxq = FWMAXQUEUE;
|
||||
@ -811,7 +808,7 @@ fw_bindlookup(struct firewire_comm *fc, uint16_t dest_hi, uint32_t dest_lo)
|
||||
|
||||
addr = ((u_int64_t)dest_hi << 32) | dest_lo;
|
||||
STAILQ_FOREACH(tfw, &fc->binds, fclist)
|
||||
if (tfw->act_type != FWACT_NULL && BIND_CMP(addr, tfw) == 0)
|
||||
if (BIND_CMP(addr, tfw) == 0)
|
||||
return(tfw);
|
||||
return(NULL);
|
||||
}
|
||||
@ -836,20 +833,15 @@ fw_bindadd(struct firewire_comm *fc, struct fw_bind *fwb)
|
||||
}
|
||||
if (prev == NULL) {
|
||||
STAILQ_INSERT_HEAD(&fc->binds, fwb, fclist);
|
||||
goto out;
|
||||
return (0);
|
||||
}
|
||||
if (prev->end < fwb->start) {
|
||||
STAILQ_INSERT_AFTER(&fc->binds, prev, fwb, fclist);
|
||||
goto out;
|
||||
return (0);
|
||||
}
|
||||
|
||||
printf("%s: bind failed\n", __func__);
|
||||
return (EBUSY);
|
||||
|
||||
out:
|
||||
if (fwb->act_type == FWACT_CH)
|
||||
STAILQ_INSERT_HEAD(&fc->ir[fwb->sub]->binds, fwb, chlist);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -888,6 +880,40 @@ fw_bindremove(struct firewire_comm *fc, struct fw_bind *fwb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fw_xferlist_add(struct fw_xferlist *q, struct malloc_type *type,
|
||||
int slen, int rlen, int n,
|
||||
struct firewire_comm *fc, void *sc, void (*hand)(struct fw_xfer *))
|
||||
{
|
||||
int i, s;
|
||||
struct fw_xfer *xfer;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
xfer = fw_xfer_alloc_buf(type, slen, rlen);
|
||||
if (xfer == NULL)
|
||||
return (n);
|
||||
xfer->fc = fc;
|
||||
xfer->sc = sc;
|
||||
xfer->hand = hand;
|
||||
s = splfw();
|
||||
STAILQ_INSERT_TAIL(q, xfer, link);
|
||||
splx(s);
|
||||
}
|
||||
return (n);
|
||||
}
|
||||
|
||||
void
|
||||
fw_xferlist_remove(struct fw_xferlist *q)
|
||||
{
|
||||
struct fw_xfer *xfer, *next;
|
||||
|
||||
for (xfer = STAILQ_FIRST(q); xfer != NULL; xfer = next) {
|
||||
next = STAILQ_NEXT(xfer, link);
|
||||
fw_xfer_free_buf(xfer);
|
||||
}
|
||||
STAILQ_INIT(q);
|
||||
}
|
||||
|
||||
/*
|
||||
* To free transaction label.
|
||||
*/
|
||||
@ -1760,7 +1786,7 @@ fw_rcv(struct fw_rcv_buf *rb)
|
||||
{
|
||||
struct fw_pkt *fp, *resfp;
|
||||
struct fw_bind *bind;
|
||||
int tcode, s;
|
||||
int tcode;
|
||||
int i, len, oldstate;
|
||||
#if 0
|
||||
{
|
||||
@ -1888,50 +1914,15 @@ fw_rcv(struct fw_rcv_buf *rb)
|
||||
len = 0;
|
||||
for (i = 0; i < rb->nvec; i ++)
|
||||
len += rb->vec[i].iov_len;
|
||||
switch(bind->act_type){
|
||||
case FWACT_XFER:
|
||||
/* splfw()?? */
|
||||
rb->xfer = STAILQ_FIRST(&bind->xferlist);
|
||||
if (rb->xfer == NULL) {
|
||||
printf("Discard a packet for this bind.\n");
|
||||
goto err;
|
||||
}
|
||||
STAILQ_REMOVE_HEAD(&bind->xferlist, link);
|
||||
fw_rcv_copy(rb);
|
||||
rb->xfer->hand(rb->xfer);
|
||||
return;
|
||||
break;
|
||||
case FWACT_CH:
|
||||
if(rb->fc->ir[bind->sub]->queued >=
|
||||
rb->fc->ir[bind->sub]->maxq){
|
||||
device_printf(rb->fc->bdev,
|
||||
"Discard a packet %x %d\n",
|
||||
bind->sub,
|
||||
rb->fc->ir[bind->sub]->queued);
|
||||
goto err;
|
||||
}
|
||||
rb->xfer = STAILQ_FIRST(&bind->xferlist);
|
||||
if (rb->xfer == NULL) {
|
||||
printf("Discard packet for this bind\n");
|
||||
goto err;
|
||||
}
|
||||
STAILQ_REMOVE_HEAD(&bind->xferlist, link);
|
||||
fw_rcv_copy(rb);
|
||||
s = splfw();
|
||||
rb->fc->ir[bind->sub]->queued++;
|
||||
STAILQ_INSERT_TAIL(&rb->fc->ir[bind->sub]->q,
|
||||
rb->xfer, link);
|
||||
splx(s);
|
||||
|
||||
wakeup((caddr_t)rb->fc->ir[bind->sub]);
|
||||
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
rb->xfer = STAILQ_FIRST(&bind->xferlist);
|
||||
if (rb->xfer == NULL) {
|
||||
printf("Discard a packet for this bind.\n");
|
||||
goto err;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
STAILQ_REMOVE_HEAD(&bind->xferlist, link);
|
||||
fw_rcv_copy(rb);
|
||||
rb->xfer->hand(rb->xfer);
|
||||
return;
|
||||
#if 0 /* shouldn't happen ?? or for GASP */
|
||||
case FWTCODE_STREAM:
|
||||
{
|
||||
|
@ -50,6 +50,8 @@ typedef struct proc fw_proc;
|
||||
|
||||
#define splfw splimp
|
||||
|
||||
STAILQ_HEAD(fw_xferlist, fw_xfer);
|
||||
|
||||
struct fw_device{
|
||||
uint16_t dst;
|
||||
struct fw_eui64 eui;
|
||||
@ -134,7 +136,7 @@ struct firewire_comm{
|
||||
struct fw_eui64 eui;
|
||||
struct fw_xferq
|
||||
*arq, *atq, *ars, *ats, *it[FW_MAX_DMACH],*ir[FW_MAX_DMACH];
|
||||
STAILQ_HEAD(, fw_xfer) tlabels[0x40];
|
||||
struct fw_xferlist tlabels[0x40];
|
||||
STAILQ_HEAD(, fw_bind) binds;
|
||||
STAILQ_HEAD(, fw_device) devices;
|
||||
u_int sid_cnt;
|
||||
@ -190,11 +192,10 @@ struct fw_xferq {
|
||||
#define FWXFERQ_WAKEUP (1 << 17)
|
||||
void (*start) (struct firewire_comm*);
|
||||
int dmach;
|
||||
STAILQ_HEAD(, fw_xfer) q;
|
||||
struct fw_xferlist q;
|
||||
u_int queued;
|
||||
u_int maxq;
|
||||
u_int psize;
|
||||
STAILQ_HEAD(, fw_bind) binds;
|
||||
struct fwdma_alloc_multi *buf;
|
||||
u_int bnchunk;
|
||||
u_int bnpacket;
|
||||
@ -220,14 +221,10 @@ struct fw_bulkxfer{
|
||||
struct fw_bind{
|
||||
u_int64_t start;
|
||||
u_int64_t end;
|
||||
STAILQ_HEAD(, fw_xfer) xferlist;
|
||||
struct fw_xferlist xferlist;
|
||||
STAILQ_ENTRY(fw_bind) fclist;
|
||||
STAILQ_ENTRY(fw_bind) chlist;
|
||||
#define FWACT_NULL 0
|
||||
#define FWACT_XFER 2
|
||||
#define FWACT_CH 3
|
||||
uint8_t act_type;
|
||||
uint8_t sub;
|
||||
void *sc;
|
||||
};
|
||||
|
||||
struct fw_xfer{
|
||||
@ -278,6 +275,9 @@ int fw_tbuf_update (struct firewire_comm *, int, int);
|
||||
int fw_rbuf_update (struct firewire_comm *, int, int);
|
||||
int fw_bindadd (struct firewire_comm *, struct fw_bind *);
|
||||
int fw_bindremove (struct firewire_comm *, struct fw_bind *);
|
||||
int fw_xferlist_add (struct fw_xferlist *, struct malloc_type *, int, int, int,
|
||||
struct firewire_comm *, void *, void (*)(struct fw_xfer *));
|
||||
void fw_xferlist_remove (struct fw_xferlist *);
|
||||
int fw_asyreq (struct firewire_comm *, int, struct fw_xfer*);
|
||||
void fw_busreset (struct firewire_comm *, uint32_t);
|
||||
uint16_t fw_crc16 (uint32_t *, uint32_t);
|
||||
|
@ -108,9 +108,12 @@ struct cdevsw firewire_cdevsw = {
|
||||
};
|
||||
|
||||
struct fw_drv1 {
|
||||
struct firewire_comm *fc;
|
||||
struct fw_xferq *ir;
|
||||
struct fw_xferq *it;
|
||||
struct fw_isobufreq bufreq;
|
||||
STAILQ_HEAD(, fw_bind) binds;
|
||||
STAILQ_HEAD(, fw_xfer) rq;
|
||||
};
|
||||
|
||||
static int
|
||||
@ -181,6 +184,9 @@ static int
|
||||
fw_open (struct cdev *dev, int flags, int fmt, fw_proc *td)
|
||||
{
|
||||
int err = 0;
|
||||
int unit = DEV2UNIT(dev);
|
||||
struct fw_drv1 *d;
|
||||
struct firewire_softc *sc;
|
||||
|
||||
if (DEV_FWMEM(dev))
|
||||
return fwmem_open(dev, flags, fmt, td);
|
||||
@ -200,6 +206,14 @@ fw_open (struct cdev *dev, int flags, int fmt, fw_proc *td)
|
||||
#endif
|
||||
|
||||
dev->si_drv1 = malloc(sizeof(struct fw_drv1), M_FW, M_WAITOK | M_ZERO);
|
||||
if (dev->si_drv1 == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
d = (struct fw_drv1 *)dev->si_drv1;
|
||||
sc = devclass_get_softc(firewire_devclass, unit);
|
||||
d->fc = sc->fc;
|
||||
STAILQ_INIT(&d->binds);
|
||||
STAILQ_INIT(&d->rq);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -207,10 +221,8 @@ fw_open (struct cdev *dev, int flags, int fmt, fw_proc *td)
|
||||
static int
|
||||
fw_close (struct cdev *dev, int flags, int fmt, fw_proc *td)
|
||||
{
|
||||
struct firewire_softc *sc;
|
||||
struct firewire_comm *fc;
|
||||
struct fw_drv1 *d;
|
||||
int unit = DEV2UNIT(dev);
|
||||
struct fw_xfer *xfer;
|
||||
struct fw_bind *fwb;
|
||||
int err = 0;
|
||||
@ -218,10 +230,17 @@ fw_close (struct cdev *dev, int flags, int fmt, fw_proc *td)
|
||||
if (DEV_FWMEM(dev))
|
||||
return fwmem_close(dev, flags, fmt, td);
|
||||
|
||||
sc = devclass_get_softc(firewire_devclass, unit);
|
||||
fc = sc->fc;
|
||||
d = (struct fw_drv1 *)dev->si_drv1;
|
||||
fc = d->fc;
|
||||
|
||||
/* remove binding */
|
||||
for (fwb = STAILQ_FIRST(&d->binds); fwb != NULL;
|
||||
fwb = STAILQ_FIRST(&d->binds)) {
|
||||
fw_bindremove(fc, fwb);
|
||||
STAILQ_REMOVE_HEAD(&d->binds, chlist);
|
||||
fw_xferlist_remove(&fwb->xferlist);
|
||||
free(fwb, M_FW);
|
||||
}
|
||||
if (d->ir != NULL) {
|
||||
struct fw_xferq *ir = d->ir;
|
||||
|
||||
@ -242,13 +261,6 @@ fw_close (struct cdev *dev, int flags, int fmt, fw_proc *td)
|
||||
xfer->resp = 0;
|
||||
fw_xfer_done(xfer);
|
||||
}
|
||||
/* remove binding */
|
||||
for (fwb = STAILQ_FIRST(&ir->binds); fwb != NULL;
|
||||
fwb = STAILQ_FIRST(&ir->binds)) {
|
||||
STAILQ_REMOVE(&fc->binds, fwb, fw_bind, fclist);
|
||||
STAILQ_REMOVE_HEAD(&ir->binds, chlist);
|
||||
free(fwb, M_FW);
|
||||
}
|
||||
ir->flag &= ~(FWXFERQ_OPEN |
|
||||
FWXFERQ_MODEMASK | FWXFERQ_CHTAGMASK);
|
||||
d->ir = NULL;
|
||||
@ -275,30 +287,71 @@ fw_close (struct cdev *dev, int flags, int fmt, fw_proc *td)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
fw_read_async(struct fw_drv1 *d, struct uio *uio, int ioflag)
|
||||
{
|
||||
int err = 0, s;
|
||||
struct fw_xfer *xfer;
|
||||
struct fw_bind *fwb;
|
||||
struct fw_pkt *fp;
|
||||
struct tcode_info *tinfo;
|
||||
|
||||
while ((xfer = STAILQ_FIRST(&d->rq)) == NULL && err == 0)
|
||||
err = tsleep(&d->rq, FWPRI, "fwra", 0);
|
||||
|
||||
if (err != 0)
|
||||
return (err);
|
||||
|
||||
s = splfw();
|
||||
STAILQ_REMOVE_HEAD(&d->rq, link);
|
||||
splx(s);
|
||||
fp = &xfer->recv.hdr;
|
||||
#if 0 /* for GASP ?? */
|
||||
if (fc->irx_post != NULL)
|
||||
fc->irx_post(fc, fp->mode.ld);
|
||||
#endif
|
||||
tinfo = &xfer->fc->tcode[fp->mode.hdr.tcode];
|
||||
err = uiomove((void *)fp, tinfo->hdr_len, uio);
|
||||
if (err)
|
||||
goto out;
|
||||
err = uiomove((void *)xfer->recv.payload, xfer->recv.pay_len, uio);
|
||||
|
||||
out:
|
||||
/* recycle this xfer */
|
||||
fwb = (struct fw_bind *)xfer->sc;
|
||||
fw_xfer_unload(xfer);
|
||||
xfer->recv.pay_len = PAGE_SIZE;
|
||||
STAILQ_INSERT_TAIL(&fwb->xferlist, xfer, link);
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* read request.
|
||||
*/
|
||||
static int
|
||||
fw_read (struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct firewire_softc *sc;
|
||||
struct fw_drv1 *d;
|
||||
struct fw_xferq *ir;
|
||||
struct fw_xfer *xfer;
|
||||
struct firewire_comm *fc;
|
||||
int err = 0, s, slept = 0;
|
||||
int unit = DEV2UNIT(dev);
|
||||
struct fw_pkt *fp;
|
||||
|
||||
if (DEV_FWMEM(dev))
|
||||
return physio(dev, uio, ioflag);
|
||||
|
||||
sc = devclass_get_softc(firewire_devclass, unit);
|
||||
|
||||
ir = ((struct fw_drv1 *)dev->si_drv1)->ir;
|
||||
if (ir == NULL || ir->buf == NULL)
|
||||
d = (struct fw_drv1 *)dev->si_drv1;
|
||||
fc = d->fc;
|
||||
ir = d->ir;
|
||||
|
||||
if (ir == NULL)
|
||||
return (fw_read_async(d, uio, ioflag));
|
||||
|
||||
if (ir->buf == NULL)
|
||||
return (EIO);
|
||||
|
||||
readloop:
|
||||
xfer = STAILQ_FIRST(&ir->q);
|
||||
if (ir->stproc == NULL) {
|
||||
/* iso bulkxfer */
|
||||
ir->stproc = STAILQ_FIRST(&ir->stvalid);
|
||||
@ -309,7 +362,7 @@ fw_read (struct cdev *dev, struct uio *uio, int ioflag)
|
||||
ir->queued = 0;
|
||||
}
|
||||
}
|
||||
if (xfer == NULL && ir->stproc == NULL) {
|
||||
if (ir->stproc == NULL) {
|
||||
/* no data avaliable */
|
||||
if (slept == 0) {
|
||||
slept = 1;
|
||||
@ -321,27 +374,12 @@ fw_read (struct cdev *dev, struct uio *uio, int ioflag)
|
||||
} else if (slept == 1)
|
||||
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 = &xfer->recv.hdr;
|
||||
if (sc->fc->irx_post != NULL)
|
||||
sc->fc->irx_post(sc->fc, fp->mode.ld);
|
||||
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 */
|
||||
fp = (struct fw_pkt *)fwdma_v_addr(ir->buf,
|
||||
ir->stproc->poffset + ir->queued);
|
||||
if(sc->fc->irx_post != NULL)
|
||||
sc->fc->irx_post(sc->fc, fp->mode.ld);
|
||||
if(fc->irx_post != NULL)
|
||||
fc->irx_post(fc, fp->mode.ld);
|
||||
if(fp->mode.stream.len == 0){
|
||||
err = EIO;
|
||||
return err;
|
||||
@ -353,7 +391,7 @@ fw_read (struct cdev *dev, struct uio *uio, int ioflag)
|
||||
s = splfw();
|
||||
STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link);
|
||||
splx(s);
|
||||
sc->fc->irx_enable(sc->fc, ir->dmach);
|
||||
fc->irx_enable(fc, ir->dmach);
|
||||
ir->stproc = NULL;
|
||||
}
|
||||
if (uio->uio_resid >= ir->psize) {
|
||||
@ -364,13 +402,66 @@ fw_read (struct cdev *dev, struct uio *uio, int ioflag)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
fw_write_async(struct fw_drv1 *d, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct fw_xfer *xfer;
|
||||
struct fw_pkt pkt;
|
||||
struct tcode_info *tinfo;
|
||||
int err;
|
||||
|
||||
bzero(&pkt, sizeof(struct fw_pkt));
|
||||
if ((err = uiomove((caddr_t)&pkt, sizeof(uint32_t), uio)))
|
||||
return (err);
|
||||
tinfo = &d->fc->tcode[pkt.mode.hdr.tcode];
|
||||
if ((err = uiomove((caddr_t)&pkt + sizeof(uint32_t),
|
||||
tinfo->hdr_len - sizeof(uint32_t), uio)))
|
||||
return (err);
|
||||
|
||||
if ((xfer = fw_xfer_alloc_buf(M_FWXFER, uio->uio_resid,
|
||||
PAGE_SIZE/*XXX*/)) == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
bcopy(&pkt, &xfer->send.hdr, sizeof(struct fw_pkt));
|
||||
xfer->send.pay_len = uio->uio_resid;
|
||||
if (uio->uio_resid > 0) {
|
||||
if ((err = uiomove((caddr_t)&xfer->send.payload[0],
|
||||
uio->uio_resid, uio)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
xfer->fc = d->fc;
|
||||
xfer->sc = NULL;
|
||||
xfer->hand = fw_asy_callback;
|
||||
xfer->send.spd = 2 /* XXX */;
|
||||
|
||||
if ((err = fw_asyreq(xfer->fc, -1, xfer)))
|
||||
goto out;
|
||||
|
||||
if ((err = tsleep(xfer, FWPRI, "fwwa", 0)))
|
||||
goto out;
|
||||
|
||||
if (xfer->resp != 0) {
|
||||
err = xfer->resp;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (xfer->state == FWXF_RCVD) {
|
||||
STAILQ_INSERT_TAIL(&d->rq, xfer, link);
|
||||
return (0);
|
||||
}
|
||||
|
||||
out:
|
||||
fw_xfer_free(xfer);
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
fw_write (struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
int err = 0;
|
||||
struct firewire_softc *sc;
|
||||
int unit = DEV2UNIT(dev);
|
||||
int s, slept = 0;
|
||||
struct fw_drv1 *d;
|
||||
struct fw_pkt *fp;
|
||||
struct firewire_comm *fc;
|
||||
struct fw_xferq *it;
|
||||
@ -378,10 +469,14 @@ fw_write (struct cdev *dev, struct uio *uio, int ioflag)
|
||||
if (DEV_FWMEM(dev))
|
||||
return physio(dev, uio, ioflag);
|
||||
|
||||
sc = devclass_get_softc(firewire_devclass, unit);
|
||||
fc = sc->fc;
|
||||
it = ((struct fw_drv1 *)dev->si_drv1)->it;
|
||||
if (it == NULL || it->buf == NULL)
|
||||
d = (struct fw_drv1 *)dev->si_drv1;
|
||||
fc = d->fc;
|
||||
it = d->it;
|
||||
|
||||
if (it == NULL)
|
||||
return (fw_write_async(d, uio, ioflag));
|
||||
|
||||
if (it->buf == NULL)
|
||||
return (EIO);
|
||||
isoloop:
|
||||
if (it->stproc == NULL) {
|
||||
@ -393,7 +488,7 @@ fw_write (struct cdev *dev, struct uio *uio, int ioflag)
|
||||
it->queued = 0;
|
||||
} else if (slept == 0) {
|
||||
slept = 1;
|
||||
err = sc->fc->itx_enable(sc->fc, it->dmach);
|
||||
err = fc->itx_enable(fc, it->dmach);
|
||||
if (err)
|
||||
return err;
|
||||
err = tsleep(it, FWPRI, "fw_write", hz);
|
||||
@ -416,7 +511,7 @@ fw_write (struct cdev *dev, struct uio *uio, int ioflag)
|
||||
STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link);
|
||||
splx(s);
|
||||
it->stproc = NULL;
|
||||
err = sc->fc->itx_enable(sc->fc, it->dmach);
|
||||
err = fc->itx_enable(fc, it->dmach);
|
||||
}
|
||||
if (uio->uio_resid >= sizeof(struct fw_isohdr)) {
|
||||
slept = 0;
|
||||
@ -424,17 +519,28 @@ fw_write (struct cdev *dev, struct uio *uio, int ioflag)
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
fw_hand(struct fw_xfer *xfer)
|
||||
{
|
||||
struct fw_bind *fwb;
|
||||
struct fw_drv1 *d;
|
||||
|
||||
fwb = (struct fw_bind *)xfer->sc;
|
||||
d = (struct fw_drv1 *)fwb->sc;
|
||||
STAILQ_INSERT_TAIL(&d->rq, xfer, link);
|
||||
wakeup(&d->rq);
|
||||
}
|
||||
|
||||
/*
|
||||
* ioctl support.
|
||||
*/
|
||||
int
|
||||
fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
{
|
||||
struct firewire_softc *sc;
|
||||
struct firewire_comm *fc;
|
||||
struct fw_drv1 *d;
|
||||
int unit = DEV2UNIT(dev);
|
||||
int s, i, len, err = 0;
|
||||
int i, len, err = 0;
|
||||
struct fw_device *fwdev;
|
||||
struct fw_bind *fwb;
|
||||
struct fw_xferq *ir, *it;
|
||||
@ -456,9 +562,8 @@ fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
if (!data)
|
||||
return(EINVAL);
|
||||
|
||||
sc = devclass_get_softc(firewire_devclass, unit);
|
||||
fc = sc->fc;
|
||||
d = (struct fw_drv1 *)dev->si_drv1;
|
||||
fc = d->fc;
|
||||
ir = d->ir;
|
||||
it = d->it;
|
||||
|
||||
@ -543,7 +648,7 @@ fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
int pay_len = 0;
|
||||
|
||||
fp = &asyreq->pkt;
|
||||
tinfo = &sc->fc->tcode[fp->mode.hdr.tcode];
|
||||
tinfo = &fc->tcode[fp->mode.hdr.tcode];
|
||||
|
||||
if ((tinfo->flag & FWTI_BLOCK_ASY) != 0)
|
||||
pay_len = MAX(0, asyreq->req.len - tinfo->hdr_len);
|
||||
@ -556,10 +661,10 @@ fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
case FWASREQNODE:
|
||||
break;
|
||||
case FWASREQEUI:
|
||||
fwdev = fw_noderesolve_eui64(sc->fc,
|
||||
fwdev = fw_noderesolve_eui64(fc,
|
||||
&asyreq->req.dst.eui);
|
||||
if (fwdev == NULL) {
|
||||
device_printf(sc->fc->bdev,
|
||||
device_printf(fc->bdev,
|
||||
"cannot find node\n");
|
||||
err = EINVAL;
|
||||
goto out;
|
||||
@ -581,7 +686,7 @@ fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
xfer->send.spd = asyreq->req.sped;
|
||||
xfer->hand = fw_asy_callback;
|
||||
|
||||
if ((err = fw_asyreq(sc->fc, -1, xfer)) != 0)
|
||||
if ((err = fw_asyreq(fc, -1, xfer)) != 0)
|
||||
goto out;
|
||||
if ((err = tsleep(xfer, FWPRI, "asyreq", hz)) != 0)
|
||||
goto out;
|
||||
@ -593,7 +698,7 @@ fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
goto out;
|
||||
|
||||
/* copy response */
|
||||
tinfo = &sc->fc->tcode[xfer->recv.hdr.mode.hdr.tcode];
|
||||
tinfo = &fc->tcode[xfer->recv.hdr.mode.hdr.tcode];
|
||||
if (xfer->recv.hdr.mode.hdr.tcode == FWTCODE_RRESB ||
|
||||
xfer->recv.hdr.mode.hdr.tcode == FWTCODE_LRES) {
|
||||
pay_len = xfer->recv.pay_len;
|
||||
@ -614,17 +719,18 @@ fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
break;
|
||||
}
|
||||
case FW_IBUSRST:
|
||||
sc->fc->ibr(sc->fc);
|
||||
fc->ibr(fc);
|
||||
break;
|
||||
case FW_CBINDADDR:
|
||||
fwb = fw_bindlookup(sc->fc,
|
||||
fwb = fw_bindlookup(fc,
|
||||
bindreq->start.hi, bindreq->start.lo);
|
||||
if(fwb == NULL){
|
||||
err = EINVAL;
|
||||
break;
|
||||
}
|
||||
STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist);
|
||||
STAILQ_REMOVE(&ir->binds, fwb, fw_bind, chlist);
|
||||
fw_bindremove(fc, fwb);
|
||||
STAILQ_REMOVE(&d->binds, fwb, fw_bind, chlist);
|
||||
fw_xferlist_remove(&fwb->xferlist);
|
||||
free(fwb, M_FW);
|
||||
break;
|
||||
case FW_SBINDADDR:
|
||||
@ -644,34 +750,26 @@ fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
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){
|
||||
free(fwb, M_FW);
|
||||
return (ENOMEM);
|
||||
}
|
||||
xfer->fc = sc->fc;
|
||||
|
||||
s = splfw();
|
||||
/* XXX broken. need multiple xfer */
|
||||
fwb->sc = (void *)d;
|
||||
STAILQ_INIT(&fwb->xferlist);
|
||||
STAILQ_INSERT_TAIL(&fwb->xferlist, xfer, link);
|
||||
splx(s);
|
||||
err = fw_bindadd(sc->fc, fwb);
|
||||
err = fw_bindadd(fc, fwb);
|
||||
if (err == 0) {
|
||||
fw_xferlist_add(&fwb->xferlist, M_FWXFER,
|
||||
/* XXX */
|
||||
PAGE_SIZE, PAGE_SIZE, 5,
|
||||
fc, (void *)fwb, fw_hand);
|
||||
STAILQ_INSERT_TAIL(&d->binds, fwb, chlist);
|
||||
}
|
||||
break;
|
||||
case FW_GDEVLST:
|
||||
i = len = 1;
|
||||
/* myself */
|
||||
devinfo = &fwdevlst->dev[0];
|
||||
devinfo->dst = sc->fc->nodeid;
|
||||
devinfo->dst = fc->nodeid;
|
||||
devinfo->status = 0; /* XXX */
|
||||
devinfo->eui.hi = sc->fc->eui.hi;
|
||||
devinfo->eui.lo = sc->fc->eui.lo;
|
||||
STAILQ_FOREACH(fwdev, &sc->fc->devices, link) {
|
||||
devinfo->eui.hi = fc->eui.hi;
|
||||
devinfo->eui.lo = fc->eui.lo;
|
||||
STAILQ_FOREACH(fwdev, &fc->devices, link) {
|
||||
if(len < FW_MAX_DEVLST){
|
||||
devinfo = &fwdevlst->dev[len++];
|
||||
devinfo->dst = fwdev->dst;
|
||||
@ -686,15 +784,15 @@ fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
fwdevlst->info_len = len;
|
||||
break;
|
||||
case FW_GTPMAP:
|
||||
bcopy(sc->fc->topology_map, data,
|
||||
(sc->fc->topology_map->crc_len + 1) * 4);
|
||||
bcopy(fc->topology_map, data,
|
||||
(fc->topology_map->crc_len + 1) * 4);
|
||||
break;
|
||||
case FW_GCROM:
|
||||
STAILQ_FOREACH(fwdev, &sc->fc->devices, link)
|
||||
STAILQ_FOREACH(fwdev, &fc->devices, link)
|
||||
if (FW_EUI64_EQUAL(fwdev->eui, crom_buf->eui))
|
||||
break;
|
||||
if (fwdev == NULL) {
|
||||
if (!FW_EUI64_EQUAL(sc->fc->eui, crom_buf->eui)) {
|
||||
if (!FW_EUI64_EQUAL(fc->eui, crom_buf->eui)) {
|
||||
err = FWNODE_INVAL;
|
||||
break;
|
||||
}
|
||||
@ -703,7 +801,7 @@ fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
len = CROMSIZE;
|
||||
for (i = 0; i < CROMSIZE/4; i++)
|
||||
((uint32_t *)ptr)[i]
|
||||
= ntohl(sc->fc->config_rom[i]);
|
||||
= ntohl(fc->config_rom[i]);
|
||||
} else {
|
||||
/* found */
|
||||
ptr = (void *)&fwdev->csrrom[0];
|
||||
@ -722,7 +820,7 @@ fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
free(ptr, M_FW);
|
||||
break;
|
||||
default:
|
||||
sc->fc->ioctl (dev, cmd, data, flag, td);
|
||||
fc->ioctl (dev, cmd, data, flag, td);
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
@ -730,16 +828,13 @@ fw_ioctl (struct cdev *dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
|
||||
int
|
||||
fw_poll(struct cdev *dev, int events, fw_proc *td)
|
||||
{
|
||||
struct firewire_softc *sc;
|
||||
struct fw_xferq *ir;
|
||||
int revents;
|
||||
int tmp;
|
||||
int unit = DEV2UNIT(dev);
|
||||
|
||||
if (DEV_FWMEM(dev))
|
||||
return fwmem_poll(dev, events, td);
|
||||
|
||||
sc = devclass_get_softc(firewire_devclass, unit);
|
||||
ir = ((struct fw_drv1 *)dev->si_drv1)->ir;
|
||||
revents = 0;
|
||||
tmp = POLLIN | POLLRDNORM;
|
||||
@ -765,8 +860,6 @@ fw_mmap (struct cdev *dev, vm_offset_t offset, int nproto)
|
||||
fw_mmap (struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nproto)
|
||||
#endif
|
||||
{
|
||||
struct firewire_softc *sc;
|
||||
int unit = DEV2UNIT(dev);
|
||||
|
||||
if (DEV_FWMEM(dev))
|
||||
#if defined(__DragonFly__) || __FreeBSD_version < 500102
|
||||
@ -775,8 +868,6 @@ fw_mmap (struct cdev *dev, vm_offset_t offset, vm_paddr_t *paddr, int nproto)
|
||||
return fwmem_mmap(dev, offset, paddr, nproto);
|
||||
#endif
|
||||
|
||||
sc = devclass_get_softc(firewire_devclass, unit);
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
|
@ -354,7 +354,6 @@ fwip_init(void *arg)
|
||||
|
||||
fwip->fwb.start = INET_FIFO;
|
||||
fwip->fwb.end = INET_FIFO + 16384; /* S3200 packet size */
|
||||
fwip->fwb.act_type = FWACT_XFER;
|
||||
|
||||
/* pre-allocate xfer */
|
||||
STAILQ_INIT(&fwip->fwb.xferlist);
|
||||
|
@ -1910,7 +1910,6 @@ sbp_attach(device_t dev)
|
||||
{
|
||||
struct sbp_softc *sbp;
|
||||
struct cam_devq *devq;
|
||||
struct fw_xfer *xfer;
|
||||
int i, s, error;
|
||||
|
||||
if (DFLTPHYS > SBP_MAXPHYS)
|
||||
@ -1987,20 +1986,11 @@ END_DEBUG
|
||||
/* We reserve 16 bit space (4 bytes X 64 targets X 256 luns) */
|
||||
sbp->fwb.start = ((u_int64_t)SBP_BIND_HI << 32) | SBP_DEV2ADDR(0, 0);
|
||||
sbp->fwb.end = sbp->fwb.start + 0xffff;
|
||||
sbp->fwb.act_type = FWACT_XFER;
|
||||
/* pre-allocate xfer */
|
||||
STAILQ_INIT(&sbp->fwb.xferlist);
|
||||
for (i = 0; i < SBP_NUM_OCB/2; i ++) {
|
||||
xfer = fw_xfer_alloc_buf(M_SBP,
|
||||
/* send */0,
|
||||
/* recv */SBP_RECV_LEN);
|
||||
xfer->hand = sbp_recv;
|
||||
#if NEED_RESPONSE
|
||||
xfer->fc = sbp->fd.fc;
|
||||
#endif
|
||||
xfer->sc = (caddr_t)sbp;
|
||||
STAILQ_INSERT_TAIL(&sbp->fwb.xferlist, xfer, link);
|
||||
}
|
||||
fw_xferlist_add(&sbp->fwb.xferlist, M_SBP,
|
||||
/*send*/ 0, /*recv*/ SBP_RECV_LEN, SBP_NUM_OCB/2,
|
||||
sbp->fd.fc, (void *)sbp, sbp_recv);
|
||||
fw_bindadd(sbp->fd.fc, &sbp->fwb);
|
||||
|
||||
sbp->fd.post_busreset = sbp_post_busreset;
|
||||
@ -2102,7 +2092,6 @@ sbp_detach(device_t dev)
|
||||
{
|
||||
struct sbp_softc *sbp = ((struct sbp_softc *)device_get_softc(dev));
|
||||
struct firewire_comm *fc = sbp->fd.fc;
|
||||
struct fw_xfer *xfer, *next;
|
||||
int i;
|
||||
|
||||
SBP_DEBUG(0)
|
||||
@ -2124,13 +2113,8 @@ END_DEBUG
|
||||
for (i = 0 ; i < SBP_NUM_TARGETS ; i ++)
|
||||
sbp_free_target(&sbp->targets[i]);
|
||||
|
||||
for (xfer = STAILQ_FIRST(&sbp->fwb.xferlist);
|
||||
xfer != NULL; xfer = next) {
|
||||
next = STAILQ_NEXT(xfer, link);
|
||||
fw_xfer_free_buf(xfer);
|
||||
}
|
||||
STAILQ_INIT(&sbp->fwb.xferlist);
|
||||
fw_bindremove(fc, &sbp->fwb);
|
||||
fw_xferlist_remove(&sbp->fwb.xferlist);
|
||||
|
||||
bus_dma_tag_destroy(sbp->dmat);
|
||||
|
||||
|
@ -1610,8 +1610,6 @@ sbp_targ_attach(device_t dev)
|
||||
{
|
||||
struct sbp_targ_softc *sc;
|
||||
struct cam_devq *devq;
|
||||
struct fw_xfer *xfer;
|
||||
int i;
|
||||
|
||||
sc = (struct sbp_targ_softc *) device_get_softc(dev);
|
||||
bzero((void *)sc, sizeof(struct sbp_targ_softc));
|
||||
@ -1644,19 +1642,12 @@ sbp_targ_attach(device_t dev)
|
||||
|
||||
sc->fwb.start = SBP_TARG_BIND_START;
|
||||
sc->fwb.end = SBP_TARG_BIND_END;
|
||||
sc->fwb.act_type = FWACT_XFER;
|
||||
|
||||
/* pre-allocate xfer */
|
||||
STAILQ_INIT(&sc->fwb.xferlist);
|
||||
for (i = 0; i < MAX_LUN /* XXX */; i ++) {
|
||||
xfer = fw_xfer_alloc_buf(M_SBP_TARG,
|
||||
/* send */ 0,
|
||||
/* recv */ SBP_TARG_RECV_LEN);
|
||||
xfer->hand = sbp_targ_recv;
|
||||
xfer->fc = sc->fd.fc;
|
||||
xfer->sc = (caddr_t)sc;
|
||||
STAILQ_INSERT_TAIL(&sc->fwb.xferlist, xfer, link);
|
||||
}
|
||||
fw_xferlist_add(&sc->fwb.xferlist, M_SBP_TARG,
|
||||
/*send*/ 0, /*recv*/ SBP_TARG_RECV_LEN, MAX_LUN /* XXX */,
|
||||
sc->fd.fc, (void *)sc, sbp_targ_recv);
|
||||
fw_bindadd(sc->fd.fc, &sc->fwb);
|
||||
return 0;
|
||||
|
||||
@ -1670,7 +1661,6 @@ sbp_targ_detach(device_t dev)
|
||||
{
|
||||
struct sbp_targ_softc *sc;
|
||||
struct sbp_targ_lstate *lstate;
|
||||
struct fw_xfer *xfer, *next;
|
||||
int i;
|
||||
|
||||
sc = (struct sbp_targ_softc *)device_get_softc(dev);
|
||||
@ -1692,13 +1682,8 @@ sbp_targ_detach(device_t dev)
|
||||
free(sc->black_hole, M_SBP_TARG);
|
||||
}
|
||||
|
||||
for (xfer = STAILQ_FIRST(&sc->fwb.xferlist);
|
||||
xfer != NULL; xfer = next) {
|
||||
next = STAILQ_NEXT(xfer, link);
|
||||
fw_xfer_free_buf(xfer);
|
||||
}
|
||||
STAILQ_INIT(&sc->fwb.xferlist);
|
||||
fw_bindremove(sc->fd.fc, &sc->fwb);
|
||||
fw_xferlist_remove(&sc->fwb.xferlist);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user