xref: /freebsd/sys/dev/firewire/fwdev.c (revision 233b1b978b878820081527d727b509834caf2a7a)
117821895SHidetoshi Shimokawa /*
217821895SHidetoshi Shimokawa  * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
317821895SHidetoshi Shimokawa  * All rights reserved.
417821895SHidetoshi Shimokawa  *
517821895SHidetoshi Shimokawa  * Redistribution and use in source and binary forms, with or without
617821895SHidetoshi Shimokawa  * modification, are permitted provided that the following conditions
717821895SHidetoshi Shimokawa  * are met:
817821895SHidetoshi Shimokawa  * 1. Redistributions of source code must retain the above copyright
917821895SHidetoshi Shimokawa  *    notice, this list of conditions and the following disclaimer.
1017821895SHidetoshi Shimokawa  * 2. Redistributions in binary form must reproduce the above copyright
1117821895SHidetoshi Shimokawa  *    notice, this list of conditions and the following disclaimer in the
1217821895SHidetoshi Shimokawa  *    documentation and/or other materials provided with the distribution.
1317821895SHidetoshi Shimokawa  * 3. All advertising materials mentioning features or use of this software
1417821895SHidetoshi Shimokawa  *    must display the acknowledgement as bellow:
1517821895SHidetoshi Shimokawa  *
1617821895SHidetoshi Shimokawa  *    This product includes software developed by K. Kobayashi and H. Shimokawa
1717821895SHidetoshi Shimokawa  *
1817821895SHidetoshi Shimokawa  * 4. The name of the author may not be used to endorse or promote products
1917821895SHidetoshi Shimokawa  *    derived from this software without specific prior written permission.
2017821895SHidetoshi Shimokawa  *
2117821895SHidetoshi Shimokawa  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2217821895SHidetoshi Shimokawa  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2317821895SHidetoshi Shimokawa  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2417821895SHidetoshi Shimokawa  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2517821895SHidetoshi Shimokawa  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2617821895SHidetoshi Shimokawa  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2717821895SHidetoshi Shimokawa  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2817821895SHidetoshi Shimokawa  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2917821895SHidetoshi Shimokawa  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
3017821895SHidetoshi Shimokawa  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3117821895SHidetoshi Shimokawa  * POSSIBILITY OF SUCH DAMAGE.
3217821895SHidetoshi Shimokawa  *
3317821895SHidetoshi Shimokawa  * $FreeBSD$
3417821895SHidetoshi Shimokawa  *
3517821895SHidetoshi Shimokawa  */
3617821895SHidetoshi Shimokawa 
3717821895SHidetoshi Shimokawa #include <sys/param.h>
3817821895SHidetoshi Shimokawa #include <sys/systm.h>
3917821895SHidetoshi Shimokawa #include <sys/types.h>
4017821895SHidetoshi Shimokawa #include <sys/mbuf.h>
4117821895SHidetoshi Shimokawa 
4217821895SHidetoshi Shimokawa #include <sys/kernel.h>
4317821895SHidetoshi Shimokawa #include <sys/malloc.h>
4417821895SHidetoshi Shimokawa #include <sys/conf.h>
4517821895SHidetoshi Shimokawa #include <sys/uio.h>
4617821895SHidetoshi Shimokawa #include <sys/poll.h>
4717821895SHidetoshi Shimokawa 
4817821895SHidetoshi Shimokawa #include <sys/bus.h>
4917821895SHidetoshi Shimokawa 
5017821895SHidetoshi Shimokawa #include <sys/ioccom.h>
5117821895SHidetoshi Shimokawa 
5217821895SHidetoshi Shimokawa #include <dev/firewire/firewire.h>
5317821895SHidetoshi Shimokawa #include <dev/firewire/firewirereg.h>
5417821895SHidetoshi Shimokawa #include <dev/firewire/fwmem.h>
556d6f7f28SHidetoshi Shimokawa #include <dev/firewire/iec68113.h>
5617821895SHidetoshi Shimokawa 
5717821895SHidetoshi Shimokawa #define CDEV_MAJOR 127
5817821895SHidetoshi Shimokawa #define	FWNODE_INVAL 0xffff
5917821895SHidetoshi Shimokawa 
6017821895SHidetoshi Shimokawa static	d_open_t	fw_open;
6117821895SHidetoshi Shimokawa static	d_close_t	fw_close;
6217821895SHidetoshi Shimokawa static	d_ioctl_t	fw_ioctl;
6317821895SHidetoshi Shimokawa static	d_poll_t	fw_poll;
6417821895SHidetoshi Shimokawa static	d_read_t	fw_read;	/* for Isochronous packet */
6517821895SHidetoshi Shimokawa static	d_write_t	fw_write;
6617821895SHidetoshi Shimokawa static	d_mmap_t	fw_mmap;
6717821895SHidetoshi Shimokawa 
6817821895SHidetoshi Shimokawa struct cdevsw firewire_cdevsw =
6917821895SHidetoshi Shimokawa {
7017821895SHidetoshi Shimokawa 	fw_open, fw_close, fw_read, fw_write, fw_ioctl,
7117821895SHidetoshi Shimokawa 	fw_poll, fw_mmap, nostrategy, "fw", CDEV_MAJOR, nodump, nopsize, D_MEM
7217821895SHidetoshi Shimokawa };
7317821895SHidetoshi Shimokawa 
7417821895SHidetoshi Shimokawa static int
7517821895SHidetoshi Shimokawa fw_open (dev_t dev, int flags, int fmt, fw_proc *td)
7617821895SHidetoshi Shimokawa {
7717821895SHidetoshi Shimokawa 	struct firewire_softc *sc;
7817821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
7917821895SHidetoshi Shimokawa 	int sub = DEV2DMACH(dev);
8017821895SHidetoshi Shimokawa 
8117821895SHidetoshi Shimokawa 	int err = 0;
8217821895SHidetoshi Shimokawa 
8317821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
8417821895SHidetoshi Shimokawa 		return fwmem_open(dev, flags, fmt, td);
8517821895SHidetoshi Shimokawa 
8617821895SHidetoshi Shimokawa 	sc = devclass_get_softc(firewire_devclass, unit);
8717821895SHidetoshi Shimokawa 	if(sc->fc->ir[sub]->flag & FWXFERQ_OPEN){
8817821895SHidetoshi Shimokawa 		err = EBUSY;
8917821895SHidetoshi Shimokawa 		return err;
9017821895SHidetoshi Shimokawa 	}
9117821895SHidetoshi Shimokawa 	if(sc->fc->it[sub]->flag & FWXFERQ_OPEN){
9217821895SHidetoshi Shimokawa 		err = EBUSY;
9317821895SHidetoshi Shimokawa 		return err;
9417821895SHidetoshi Shimokawa 	}
9517821895SHidetoshi Shimokawa 	if(sc->fc->ir[sub]->flag & FWXFERQ_MODEMASK){
9617821895SHidetoshi Shimokawa 		err = EBUSY;
9717821895SHidetoshi Shimokawa 		return err;
9817821895SHidetoshi Shimokawa 	}
9917821895SHidetoshi Shimokawa /* Default is per packet mode */
10017821895SHidetoshi Shimokawa 	sc->fc->ir[sub]->flag |= FWXFERQ_OPEN;
10117821895SHidetoshi Shimokawa 	sc->fc->it[sub]->flag |= FWXFERQ_OPEN;
10217821895SHidetoshi Shimokawa 	sc->fc->ir[sub]->flag |= FWXFERQ_PACKET;
10317821895SHidetoshi Shimokawa 	return err;
10417821895SHidetoshi Shimokawa }
10517821895SHidetoshi Shimokawa 
10617821895SHidetoshi Shimokawa static int
10717821895SHidetoshi Shimokawa fw_close (dev_t dev, int flags, int fmt, fw_proc *td)
10817821895SHidetoshi Shimokawa {
10917821895SHidetoshi Shimokawa 	struct firewire_softc *sc;
11017821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
11117821895SHidetoshi Shimokawa 	int sub = DEV2DMACH(dev);
11217821895SHidetoshi Shimokawa 	struct fw_xfer *xfer;
11317821895SHidetoshi Shimokawa 	struct fw_bind *fwb;
11417821895SHidetoshi Shimokawa 	int err = 0;
11517821895SHidetoshi Shimokawa 
11617821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
11717821895SHidetoshi Shimokawa 		return fwmem_close(dev, flags, fmt, td);
11817821895SHidetoshi Shimokawa 
11917821895SHidetoshi Shimokawa 	sc = devclass_get_softc(firewire_devclass, unit);
12017821895SHidetoshi Shimokawa 	if(!(sc->fc->ir[sub]->flag & FWXFERQ_OPEN)){
12117821895SHidetoshi Shimokawa 		err = EINVAL;
12217821895SHidetoshi Shimokawa 		return err;
12317821895SHidetoshi Shimokawa 	}
12417821895SHidetoshi Shimokawa 	sc->fc->ir[sub]->flag &= ~FWXFERQ_OPEN;
12517821895SHidetoshi Shimokawa 	if(!(sc->fc->it[sub]->flag & FWXFERQ_OPEN)){
12617821895SHidetoshi Shimokawa 		err = EINVAL;
12717821895SHidetoshi Shimokawa 		return err;
12817821895SHidetoshi Shimokawa 	}
12917821895SHidetoshi Shimokawa 	sc->fc->it[sub]->flag &= ~FWXFERQ_OPEN;
13017821895SHidetoshi Shimokawa 
13117821895SHidetoshi Shimokawa 	if(sc->fc->ir[sub]->flag & FWXFERQ_RUNNING){
13217821895SHidetoshi Shimokawa 		sc->fc->irx_disable(sc->fc, sub);
13317821895SHidetoshi Shimokawa 	}
13417821895SHidetoshi Shimokawa 	if(sc->fc->it[sub]->flag & FWXFERQ_RUNNING){
13517821895SHidetoshi Shimokawa 		sc->fc->it[sub]->flag &= ~FWXFERQ_RUNNING;
13617821895SHidetoshi Shimokawa 		sc->fc->itx_disable(sc->fc, sub);
13717821895SHidetoshi Shimokawa 	}
1389190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV
13917821895SHidetoshi Shimokawa 	if(sc->fc->it[sub]->flag & FWXFERQ_DV){
1409190691bSHidetoshi Shimokawa 		struct fw_dvbuf *dvbuf;
1419190691bSHidetoshi Shimokawa 
14217821895SHidetoshi Shimokawa 		if((dvbuf = sc->fc->it[sub]->dvproc) != NULL){
1435166f1dfSHidetoshi Shimokawa 			free(dvbuf->buf, M_FW);
14417821895SHidetoshi Shimokawa 			sc->fc->it[sub]->dvproc = NULL;
14517821895SHidetoshi Shimokawa 		}
14617821895SHidetoshi Shimokawa 		if((dvbuf = sc->fc->it[sub]->dvdma) != NULL){
1475166f1dfSHidetoshi Shimokawa 			free(dvbuf->buf, M_FW);
14817821895SHidetoshi Shimokawa 			sc->fc->it[sub]->dvdma = NULL;
14917821895SHidetoshi Shimokawa 		}
15017821895SHidetoshi Shimokawa 		while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvvalid)) != NULL){
15117821895SHidetoshi Shimokawa 			STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvvalid, link);
1525166f1dfSHidetoshi Shimokawa 			free(dvbuf->buf, M_FW);
15317821895SHidetoshi Shimokawa 		}
15417821895SHidetoshi Shimokawa 		while((dvbuf = STAILQ_FIRST(&sc->fc->it[sub]->dvfree)) != NULL){
15517821895SHidetoshi Shimokawa 			STAILQ_REMOVE_HEAD(&sc->fc->it[sub]->dvfree, link);
1565166f1dfSHidetoshi Shimokawa 			free(dvbuf->buf, M_FW);
15717821895SHidetoshi Shimokawa 		}
1585166f1dfSHidetoshi Shimokawa 		free(sc->fc->it[sub]->dvbuf, M_FW);
15917821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvbuf = NULL;
16017821895SHidetoshi Shimokawa 	}
1619190691bSHidetoshi Shimokawa #endif
16217821895SHidetoshi Shimokawa 	if(sc->fc->ir[sub]->flag & FWXFERQ_EXTBUF){
1635166f1dfSHidetoshi Shimokawa 		free(sc->fc->ir[sub]->buf, M_FW);
16417821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->buf = NULL;
1655166f1dfSHidetoshi Shimokawa 		free(sc->fc->ir[sub]->bulkxfer, M_FW);
16617821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->bulkxfer = NULL;
16717821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->flag &= ~FWXFERQ_EXTBUF;
168e2ad5d6eSHidetoshi Shimokawa 		sc->fc->ir[sub]->psize = PAGE_SIZE;
16917821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->maxq = FWMAXQUEUE;
17017821895SHidetoshi Shimokawa 	}
17117821895SHidetoshi Shimokawa 	if(sc->fc->it[sub]->flag & FWXFERQ_EXTBUF){
1725166f1dfSHidetoshi Shimokawa 		free(sc->fc->it[sub]->buf, M_FW);
17317821895SHidetoshi Shimokawa 		sc->fc->it[sub]->buf = NULL;
1745166f1dfSHidetoshi Shimokawa 		free(sc->fc->it[sub]->bulkxfer, M_FW);
17517821895SHidetoshi Shimokawa 		sc->fc->it[sub]->bulkxfer = NULL;
1765a7ba74dSHidetoshi Shimokawa #ifdef FWXFERQ_DV
17717821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvbuf = NULL;
1785a7ba74dSHidetoshi Shimokawa #endif
17917821895SHidetoshi Shimokawa 		sc->fc->it[sub]->flag &= ~FWXFERQ_EXTBUF;
180e2ad5d6eSHidetoshi Shimokawa 		sc->fc->it[sub]->psize = 0;
18117821895SHidetoshi Shimokawa 		sc->fc->it[sub]->maxq = FWMAXQUEUE;
18217821895SHidetoshi Shimokawa 	}
18317821895SHidetoshi Shimokawa 	for(xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q);
18417821895SHidetoshi Shimokawa 		xfer != NULL; xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q)){
18517821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->queued--;
18617821895SHidetoshi Shimokawa 		STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->q, link);
18717821895SHidetoshi Shimokawa 
18817821895SHidetoshi Shimokawa 		xfer->resp = 0;
18917821895SHidetoshi Shimokawa 		switch(xfer->act_type){
19017821895SHidetoshi Shimokawa 		case FWACT_XFER:
19117821895SHidetoshi Shimokawa 			fw_xfer_done(xfer);
19217821895SHidetoshi Shimokawa 			break;
19317821895SHidetoshi Shimokawa 		default:
19417821895SHidetoshi Shimokawa 			break;
19517821895SHidetoshi Shimokawa 		}
19617821895SHidetoshi Shimokawa 		fw_xfer_free(xfer);
19717821895SHidetoshi Shimokawa 	}
19817821895SHidetoshi Shimokawa 	for(fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds); fwb != NULL;
19917821895SHidetoshi Shimokawa 		fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds)){
20017821895SHidetoshi Shimokawa 		STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist);
20117821895SHidetoshi Shimokawa 		STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->binds, chlist);
2025166f1dfSHidetoshi Shimokawa 		free(fwb, M_FW);
20317821895SHidetoshi Shimokawa 	}
20417821895SHidetoshi Shimokawa 	sc->fc->ir[sub]->flag &= ~FWXFERQ_MODEMASK;
20517821895SHidetoshi Shimokawa 	sc->fc->it[sub]->flag &= ~FWXFERQ_MODEMASK;
20617821895SHidetoshi Shimokawa 	return err;
20717821895SHidetoshi Shimokawa }
20817821895SHidetoshi Shimokawa 
20917821895SHidetoshi Shimokawa /*
21017821895SHidetoshi Shimokawa  * read request.
21117821895SHidetoshi Shimokawa  */
21217821895SHidetoshi Shimokawa static int
21317821895SHidetoshi Shimokawa fw_read (dev_t dev, struct uio *uio, int ioflag)
21417821895SHidetoshi Shimokawa {
21517821895SHidetoshi Shimokawa 	struct firewire_softc *sc;
21617821895SHidetoshi Shimokawa 	struct fw_xferq *ir;
21717821895SHidetoshi Shimokawa 	struct fw_xfer *xfer;
21817821895SHidetoshi Shimokawa 	int err = 0, s, slept = 0;
21917821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
22017821895SHidetoshi Shimokawa 	int sub = DEV2DMACH(dev);
22117821895SHidetoshi Shimokawa 	struct fw_pkt *fp;
22217821895SHidetoshi Shimokawa 
22317821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
22417821895SHidetoshi Shimokawa 		return fwmem_read(dev, uio, ioflag);
22517821895SHidetoshi Shimokawa 
22617821895SHidetoshi Shimokawa 	sc = devclass_get_softc(firewire_devclass, unit);
22717821895SHidetoshi Shimokawa 
22817821895SHidetoshi Shimokawa 	ir = sc->fc->ir[sub];
22917821895SHidetoshi Shimokawa 
23017821895SHidetoshi Shimokawa 	if (ir->flag & FWXFERQ_PACKET) {
23117821895SHidetoshi Shimokawa 		ir->stproc = NULL;
23217821895SHidetoshi Shimokawa 	}
23317821895SHidetoshi Shimokawa readloop:
23417821895SHidetoshi Shimokawa 	xfer = STAILQ_FIRST(&ir->q);
235c3e9e255SHidetoshi Shimokawa 	if ((ir->flag & FWXFERQ_PACKET) == 0 && ir->stproc == NULL) {
236c3e9e255SHidetoshi Shimokawa 		/* iso bulkxfer */
23717821895SHidetoshi Shimokawa 		ir->stproc = STAILQ_FIRST(&ir->stvalid);
23817821895SHidetoshi Shimokawa 		if (ir->stproc != NULL) {
23917821895SHidetoshi Shimokawa 			s = splfw();
24017821895SHidetoshi Shimokawa 			STAILQ_REMOVE_HEAD(&ir->stvalid, link);
24117821895SHidetoshi Shimokawa 			splx(s);
24217821895SHidetoshi Shimokawa 			ir->queued = 0;
24317821895SHidetoshi Shimokawa 		}
24417821895SHidetoshi Shimokawa 	}
24517821895SHidetoshi Shimokawa 	if (xfer == NULL && ir->stproc == NULL) {
246c3e9e255SHidetoshi Shimokawa 		/* no data avaliable */
24717821895SHidetoshi Shimokawa 		if (slept == 0) {
24817821895SHidetoshi Shimokawa 			slept = 1;
249c3e9e255SHidetoshi Shimokawa 			if ((ir->flag & FWXFERQ_RUNNING) == 0
25017821895SHidetoshi Shimokawa 					&& (ir->flag & FWXFERQ_PACKET)) {
25117821895SHidetoshi Shimokawa 				err = sc->fc->irx_enable(sc->fc, sub);
252c3e9e255SHidetoshi Shimokawa 				if (err)
25317821895SHidetoshi Shimokawa 					return err;
25417821895SHidetoshi Shimokawa 			}
25517821895SHidetoshi Shimokawa 			ir->flag |= FWXFERQ_WAKEUP;
25617821895SHidetoshi Shimokawa 			err = tsleep((caddr_t)ir, FWPRI, "fw_read", hz);
25717821895SHidetoshi Shimokawa 			ir->flag &= ~FWXFERQ_WAKEUP;
258c3e9e255SHidetoshi Shimokawa 			if (err == 0)
25917821895SHidetoshi Shimokawa 				goto readloop;
260c3e9e255SHidetoshi Shimokawa 		} else if (slept == 1)
26117821895SHidetoshi Shimokawa 			err = EIO;
26217821895SHidetoshi Shimokawa 		return err;
26317821895SHidetoshi Shimokawa 	} else if(xfer != NULL) {
264c3e9e255SHidetoshi Shimokawa 		/* per packet mode */
26517821895SHidetoshi Shimokawa 		s = splfw();
26617821895SHidetoshi Shimokawa 		ir->queued --;
26717821895SHidetoshi Shimokawa 		STAILQ_REMOVE_HEAD(&ir->q, link);
26817821895SHidetoshi Shimokawa 		splx(s);
26917821895SHidetoshi Shimokawa 		fp = (struct fw_pkt *)(xfer->recv.buf + xfer->recv.off);
27017821895SHidetoshi Shimokawa 		if(sc->fc->irx_post != NULL)
27117821895SHidetoshi Shimokawa 			sc->fc->irx_post(sc->fc, fp->mode.ld);
27217821895SHidetoshi Shimokawa 		err = uiomove(xfer->recv.buf + xfer->recv.off, xfer->recv.len, uio);
27317821895SHidetoshi Shimokawa 		fw_xfer_free( xfer);
27417821895SHidetoshi Shimokawa 	} else if(ir->stproc != NULL) {
275c3e9e255SHidetoshi Shimokawa 		/* iso bulkxfer */
27617821895SHidetoshi Shimokawa 		fp = (struct fw_pkt *)(ir->stproc->buf + ir->queued * ir->psize);
27717821895SHidetoshi Shimokawa 		if(sc->fc->irx_post != NULL)
27817821895SHidetoshi Shimokawa 			sc->fc->irx_post(sc->fc, fp->mode.ld);
27917821895SHidetoshi Shimokawa 		if(ntohs(fp->mode.stream.len) == 0){
28017821895SHidetoshi Shimokawa 			err = EIO;
28117821895SHidetoshi Shimokawa 			return err;
28217821895SHidetoshi Shimokawa 		}
283c3e9e255SHidetoshi Shimokawa 		err = uiomove((caddr_t)fp,
284c3e9e255SHidetoshi Shimokawa 			ntohs(fp->mode.stream.len) + sizeof(u_int32_t), uio);
285c3e9e255SHidetoshi Shimokawa #if 0
28617821895SHidetoshi Shimokawa 		fp->mode.stream.len = 0;
287c3e9e255SHidetoshi Shimokawa #endif
28817821895SHidetoshi Shimokawa 		ir->queued ++;
28917821895SHidetoshi Shimokawa 		if(ir->queued >= ir->bnpacket){
29017821895SHidetoshi Shimokawa 			s = splfw();
29117821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link);
29217821895SHidetoshi Shimokawa 			splx(s);
2935a7ba74dSHidetoshi Shimokawa 			sc->fc->irx_enable(sc->fc, sub);
29417821895SHidetoshi Shimokawa 			ir->stproc = NULL;
29517821895SHidetoshi Shimokawa 		}
296c3e9e255SHidetoshi Shimokawa 		if (uio->uio_resid >= ir->psize) {
297c3e9e255SHidetoshi Shimokawa 			slept = -1;
298c3e9e255SHidetoshi Shimokawa 			goto readloop;
299c3e9e255SHidetoshi Shimokawa 		}
30017821895SHidetoshi Shimokawa 	}
30117821895SHidetoshi Shimokawa 	return err;
30217821895SHidetoshi Shimokawa }
30317821895SHidetoshi Shimokawa 
30417821895SHidetoshi Shimokawa static int
30517821895SHidetoshi Shimokawa fw_write (dev_t dev, struct uio *uio, int ioflag)
30617821895SHidetoshi Shimokawa {
30717821895SHidetoshi Shimokawa 	int err = 0;
30817821895SHidetoshi Shimokawa 	struct firewire_softc *sc;
30917821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
31017821895SHidetoshi Shimokawa 	int sub = DEV2DMACH(dev);
31117821895SHidetoshi Shimokawa 	int s, slept = 0;
31217821895SHidetoshi Shimokawa 	struct fw_pkt *fp;
31317821895SHidetoshi Shimokawa 	struct fw_xfer *xfer;
31417821895SHidetoshi Shimokawa 	struct fw_xferq *xferq;
31517821895SHidetoshi Shimokawa 	struct firewire_comm *fc;
31617821895SHidetoshi Shimokawa 	struct fw_xferq *it;
31717821895SHidetoshi Shimokawa 
31817821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
31917821895SHidetoshi Shimokawa 		return fwmem_write(dev, uio, ioflag);
32017821895SHidetoshi Shimokawa 
32117821895SHidetoshi Shimokawa 	sc = devclass_get_softc(firewire_devclass, unit);
32217821895SHidetoshi Shimokawa 	fc = sc->fc;
32317821895SHidetoshi Shimokawa 	it = sc->fc->it[sub];
32417821895SHidetoshi Shimokawa 
32517821895SHidetoshi Shimokawa 	fp = (struct fw_pkt *)uio->uio_iov->iov_base;
32617821895SHidetoshi Shimokawa 	switch(fp->mode.common.tcode){
32717821895SHidetoshi Shimokawa 	case FWTCODE_RREQQ:
32817821895SHidetoshi Shimokawa 	case FWTCODE_RREQB:
32917821895SHidetoshi Shimokawa 	case FWTCODE_LREQ:
33017821895SHidetoshi Shimokawa 		err = EINVAL;
33117821895SHidetoshi Shimokawa 		return err;
33217821895SHidetoshi Shimokawa 	case FWTCODE_WREQQ:
33317821895SHidetoshi Shimokawa 	case FWTCODE_WREQB:
33417821895SHidetoshi Shimokawa 		xferq = fc->atq;
33517821895SHidetoshi Shimokawa 		break;
33617821895SHidetoshi Shimokawa 	case FWTCODE_STREAM:
33717821895SHidetoshi Shimokawa 		if(it->flag & FWXFERQ_PACKET){
33817821895SHidetoshi Shimokawa 			xferq = fc->atq;
33917821895SHidetoshi Shimokawa 		}else{
34017821895SHidetoshi Shimokawa 			xferq = NULL;
34117821895SHidetoshi Shimokawa 		}
34217821895SHidetoshi Shimokawa 		break;
34317821895SHidetoshi Shimokawa 	case FWTCODE_WRES:
34417821895SHidetoshi Shimokawa 	case FWTCODE_RRESQ:
34517821895SHidetoshi Shimokawa 	case FWTCODE_RRESB:
34617821895SHidetoshi Shimokawa 	case FWTCODE_LRES:
34717821895SHidetoshi Shimokawa 		xferq = fc->ats;
34817821895SHidetoshi Shimokawa 		break;
34917821895SHidetoshi Shimokawa 	default:
35017821895SHidetoshi Shimokawa 		err = EINVAL;
35117821895SHidetoshi Shimokawa 		return err;
35217821895SHidetoshi Shimokawa 	}
35317821895SHidetoshi Shimokawa 	/* Discard unsent buffered stream packet, when sending Asyrequrst */
35417821895SHidetoshi Shimokawa 	if(xferq != NULL && it->stproc != NULL){
35517821895SHidetoshi Shimokawa 		s = splfw();
35617821895SHidetoshi Shimokawa 		STAILQ_INSERT_TAIL(&it->stfree, it->stproc, link);
35717821895SHidetoshi Shimokawa 		splx(s);
35817821895SHidetoshi Shimokawa 		it->stproc = NULL;
35917821895SHidetoshi Shimokawa 	}
3609190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV
36117821895SHidetoshi Shimokawa 	if(xferq == NULL && !(it->flag & FWXFERQ_DV)){
3629190691bSHidetoshi Shimokawa #else
3639190691bSHidetoshi Shimokawa 	if (xferq == NULL) {
3649190691bSHidetoshi Shimokawa #endif
36517821895SHidetoshi Shimokawa isoloop:
36617821895SHidetoshi Shimokawa 		if (it->stproc == NULL) {
36717821895SHidetoshi Shimokawa 			it->stproc = STAILQ_FIRST(&it->stfree);
36817821895SHidetoshi Shimokawa 			if (it->stproc != NULL) {
36917821895SHidetoshi Shimokawa 				s = splfw();
37017821895SHidetoshi Shimokawa 				STAILQ_REMOVE_HEAD(&it->stfree, link);
37117821895SHidetoshi Shimokawa 				splx(s);
37217821895SHidetoshi Shimokawa 				it->queued = 0;
37317821895SHidetoshi Shimokawa 			} else if (slept == 0) {
37417821895SHidetoshi Shimokawa 				slept = 1;
37517821895SHidetoshi Shimokawa 				err = sc->fc->itx_enable(sc->fc, sub);
376c3e9e255SHidetoshi Shimokawa 				if (err)
37717821895SHidetoshi Shimokawa 					return err;
378c3e9e255SHidetoshi Shimokawa 				err = tsleep((caddr_t)it, FWPRI,
379c3e9e255SHidetoshi Shimokawa 							"fw_write", hz);
380c3e9e255SHidetoshi Shimokawa 				if (err)
38117821895SHidetoshi Shimokawa 					return err;
38217821895SHidetoshi Shimokawa 				goto isoloop;
38317821895SHidetoshi Shimokawa 			} else {
38417821895SHidetoshi Shimokawa 				err = EIO;
38517821895SHidetoshi Shimokawa 				return err;
38617821895SHidetoshi Shimokawa 			}
38717821895SHidetoshi Shimokawa 		}
388c3e9e255SHidetoshi Shimokawa 		fp = (struct fw_pkt *)
389c3e9e255SHidetoshi Shimokawa 			(it->stproc->buf + it->queued * it->psize);
390c3e9e255SHidetoshi Shimokawa 		err = uiomove((caddr_t)fp, sizeof(struct fw_isohdr), uio);
391c3e9e255SHidetoshi Shimokawa 		err = uiomove((caddr_t)fp->mode.stream.payload,
392c3e9e255SHidetoshi Shimokawa 					ntohs(fp->mode.stream.len), uio);
39317821895SHidetoshi Shimokawa 		it->queued ++;
394c3e9e255SHidetoshi Shimokawa 		if (it->queued >= it->bnpacket) {
39517821895SHidetoshi Shimokawa 			s = splfw();
39617821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link);
39717821895SHidetoshi Shimokawa 			splx(s);
39817821895SHidetoshi Shimokawa 			it->stproc = NULL;
39917821895SHidetoshi Shimokawa 			err = sc->fc->itx_enable(sc->fc, sub);
40017821895SHidetoshi Shimokawa 		}
401c3e9e255SHidetoshi Shimokawa 		if (uio->uio_resid >= sizeof(struct fw_isohdr)) {
402c3e9e255SHidetoshi Shimokawa 			slept = 0;
403c3e9e255SHidetoshi Shimokawa 			goto isoloop;
404c3e9e255SHidetoshi Shimokawa 		}
40517821895SHidetoshi Shimokawa 		return err;
4069190691bSHidetoshi Shimokawa 	}
4079190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV
4089190691bSHidetoshi Shimokawa 	if(xferq == NULL && it->flag & FWXFERQ_DV){
40917821895SHidetoshi Shimokawa dvloop:
41017821895SHidetoshi Shimokawa 		if(it->dvproc == NULL){
41117821895SHidetoshi Shimokawa 			it->dvproc = STAILQ_FIRST(&it->dvfree);
41217821895SHidetoshi Shimokawa 			if(it->dvproc != NULL){
41317821895SHidetoshi Shimokawa 				s = splfw();
41417821895SHidetoshi Shimokawa 				STAILQ_REMOVE_HEAD(&it->dvfree, link);
41517821895SHidetoshi Shimokawa 				splx(s);
41617821895SHidetoshi Shimokawa 				it->dvptr = 0;
41717821895SHidetoshi Shimokawa 			}else if(slept == 0){
41817821895SHidetoshi Shimokawa 				slept = 1;
41917821895SHidetoshi Shimokawa 				err = sc->fc->itx_enable(sc->fc, sub);
42017821895SHidetoshi Shimokawa 				if(err){
42117821895SHidetoshi Shimokawa 					return err;
42217821895SHidetoshi Shimokawa 				}
42317821895SHidetoshi Shimokawa 				err = tsleep((caddr_t)it, FWPRI, "fw_write", hz);
42417821895SHidetoshi Shimokawa 				if(err){
42517821895SHidetoshi Shimokawa 					return err;
42617821895SHidetoshi Shimokawa 				}
42717821895SHidetoshi Shimokawa 				goto dvloop;
42817821895SHidetoshi Shimokawa 			}else{
42917821895SHidetoshi Shimokawa 				err = EIO;
43017821895SHidetoshi Shimokawa 				return err;
43117821895SHidetoshi Shimokawa 			}
43217821895SHidetoshi Shimokawa 		}
4330aaa9a23SHidetoshi Shimokawa #if 0 /* What's this for? (it->dvptr? overwritten by the following uiomove)*/
43417821895SHidetoshi Shimokawa 		fp = (struct fw_pkt *)(it->dvproc->buf + it->queued * it->psize);
43517821895SHidetoshi Shimokawa 		fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t));
4360aaa9a23SHidetoshi Shimokawa #endif
43717821895SHidetoshi Shimokawa 		err = uiomove(it->dvproc->buf + it->dvptr,
43817821895SHidetoshi Shimokawa 							uio->uio_resid, uio);
43917821895SHidetoshi Shimokawa 		it->dvptr += it->psize;
44017821895SHidetoshi Shimokawa 		if(err){
44117821895SHidetoshi Shimokawa 			return err;
44217821895SHidetoshi Shimokawa 		}
44317821895SHidetoshi Shimokawa 		if(it->dvptr >= it->psize * it->dvpacket){
44417821895SHidetoshi Shimokawa 			s = splfw();
44517821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&it->dvvalid, it->dvproc, link);
44617821895SHidetoshi Shimokawa 			splx(s);
44717821895SHidetoshi Shimokawa 			it->dvproc = NULL;
44817821895SHidetoshi Shimokawa 			err = fw_tbuf_update(sc->fc, sub, 0);
44917821895SHidetoshi Shimokawa 			if(err){
45017821895SHidetoshi Shimokawa 				return err;
45117821895SHidetoshi Shimokawa 			}
45217821895SHidetoshi Shimokawa 			err = sc->fc->itx_enable(sc->fc, sub);
45317821895SHidetoshi Shimokawa 		}
45417821895SHidetoshi Shimokawa 		return err;
45517821895SHidetoshi Shimokawa 	}
4569190691bSHidetoshi Shimokawa #endif
45717821895SHidetoshi Shimokawa 	if(xferq != NULL){
45848249fe0SHidetoshi Shimokawa 		xfer = fw_xfer_alloc(M_FWXFER);
45917821895SHidetoshi Shimokawa 		if(xfer == NULL){
46017821895SHidetoshi Shimokawa 			err = ENOMEM;
46117821895SHidetoshi Shimokawa 			return err;
46217821895SHidetoshi Shimokawa 		}
4635166f1dfSHidetoshi Shimokawa 		xfer->send.buf = malloc(uio->uio_resid, M_FW, M_NOWAIT);
46417821895SHidetoshi Shimokawa 		if(xfer->send.buf == NULL){
46517821895SHidetoshi Shimokawa 			fw_xfer_free( xfer);
46617821895SHidetoshi Shimokawa 			err = ENOBUFS;
46717821895SHidetoshi Shimokawa 			return err;
46817821895SHidetoshi Shimokawa 		}
46917821895SHidetoshi Shimokawa 		xfer->dst = ntohs(fp->mode.hdr.dst);
47017821895SHidetoshi Shimokawa #if 0
47117821895SHidetoshi Shimokawa 		switch(fp->mode.common.tcode){
47217821895SHidetoshi Shimokawa 		case FWTCODE_WREQQ:
47317821895SHidetoshi Shimokawa 		case FWTCODE_WREQB:
47417821895SHidetoshi Shimokawa 			if((tl = fw_get_tlabel(fc, xfer)) == -1 ){
47517821895SHidetoshi Shimokawa 				fw_xfer_free( xfer);
47617821895SHidetoshi Shimokawa 				err = EAGAIN;
47717821895SHidetoshi Shimokawa 				return err;
47817821895SHidetoshi Shimokawa 			}
47917821895SHidetoshi Shimokawa 			fp->mode.hdr.tlrt = tl << 2;
48017821895SHidetoshi Shimokawa 		default:
48117821895SHidetoshi Shimokawa 			break;
48217821895SHidetoshi Shimokawa 		}
48317821895SHidetoshi Shimokawa 
48417821895SHidetoshi Shimokawa 		xfer->tl = fp->mode.hdr.tlrt >> 2;
48517821895SHidetoshi Shimokawa 		xfer->tcode = fp->mode.common.tcode;
48617821895SHidetoshi Shimokawa 		xfer->fc = fc;
48717821895SHidetoshi Shimokawa 		xfer->q = xferq;
48817821895SHidetoshi Shimokawa 		xfer->act_type = FWACT_XFER;
48917821895SHidetoshi Shimokawa 		xfer->retry_req = fw_asybusy;
49017821895SHidetoshi Shimokawa #endif
49117821895SHidetoshi Shimokawa 		xfer->send.len = uio->uio_resid;
49217821895SHidetoshi Shimokawa 		xfer->send.off = 0;
49317821895SHidetoshi Shimokawa 		xfer->spd = 0;/* XXX: how to setup it */
49417821895SHidetoshi Shimokawa 		xfer->act.hand = fw_asy_callback;
49517821895SHidetoshi Shimokawa 
49617821895SHidetoshi Shimokawa 		err = uiomove(xfer->send.buf, uio->uio_resid, uio);
49717821895SHidetoshi Shimokawa 		if(err){
49817821895SHidetoshi Shimokawa 			fw_xfer_free( xfer);
49917821895SHidetoshi Shimokawa 			return err;
50017821895SHidetoshi Shimokawa 		}
50117821895SHidetoshi Shimokawa #if 0
50217821895SHidetoshi Shimokawa 		fw_asystart(xfer);
50317821895SHidetoshi Shimokawa #else
50417821895SHidetoshi Shimokawa 		fw_asyreq(fc, -1, xfer);
50517821895SHidetoshi Shimokawa #endif
50617821895SHidetoshi Shimokawa 		err = tsleep((caddr_t)xfer, FWPRI, "fw_write", hz);
50717821895SHidetoshi Shimokawa 		if(xfer->resp == EBUSY)
50817821895SHidetoshi Shimokawa 			return EBUSY;
50917821895SHidetoshi Shimokawa 		fw_xfer_free( xfer);
51017821895SHidetoshi Shimokawa 		return err;
51117821895SHidetoshi Shimokawa 	}
51217821895SHidetoshi Shimokawa 	return EINVAL;
51317821895SHidetoshi Shimokawa }
51417821895SHidetoshi Shimokawa 
51517821895SHidetoshi Shimokawa /*
51617821895SHidetoshi Shimokawa  * ioctl support.
51717821895SHidetoshi Shimokawa  */
51817821895SHidetoshi Shimokawa int
51917821895SHidetoshi Shimokawa fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
52017821895SHidetoshi Shimokawa {
52117821895SHidetoshi Shimokawa 	struct firewire_softc *sc;
52217821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
52317821895SHidetoshi Shimokawa 	int sub = DEV2DMACH(dev);
52417821895SHidetoshi Shimokawa 	int i, len, err = 0;
52517821895SHidetoshi Shimokawa 	struct fw_device *fwdev;
52617821895SHidetoshi Shimokawa 	struct fw_bind *fwb;
52717821895SHidetoshi Shimokawa 	struct fw_xferq *ir, *it;
52817821895SHidetoshi Shimokawa 	struct fw_xfer *xfer;
52917821895SHidetoshi Shimokawa 	struct fw_pkt *fp;
530c547b896SHidetoshi Shimokawa 	struct fw_devinfo *devinfo;
53117821895SHidetoshi Shimokawa 
53217821895SHidetoshi Shimokawa 	struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data;
53317821895SHidetoshi Shimokawa 	struct fw_asyreq *asyreq = (struct fw_asyreq *)data;
53417821895SHidetoshi Shimokawa 	struct fw_isochreq *ichreq = (struct fw_isochreq *)data;
53517821895SHidetoshi Shimokawa 	struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data;
53617821895SHidetoshi Shimokawa 	struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data;
53717821895SHidetoshi Shimokawa 	struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data;
53817821895SHidetoshi Shimokawa 
53917821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
54017821895SHidetoshi Shimokawa 		return fwmem_ioctl(dev, cmd, data, flag, td);
54117821895SHidetoshi Shimokawa 
54217821895SHidetoshi Shimokawa 	sc = devclass_get_softc(firewire_devclass, unit);
54317821895SHidetoshi Shimokawa 	if (!data)
54417821895SHidetoshi Shimokawa 		return(EINVAL);
54517821895SHidetoshi Shimokawa 
54617821895SHidetoshi Shimokawa 	switch (cmd) {
54717821895SHidetoshi Shimokawa 	case FW_STSTREAM:
54817821895SHidetoshi Shimokawa 		sc->fc->it[sub]->flag &= ~0xff;
54917821895SHidetoshi Shimokawa 		sc->fc->it[sub]->flag |= (0x3f & ichreq->ch);
55017821895SHidetoshi Shimokawa 		sc->fc->it[sub]->flag |= ((0x3 & ichreq->tag) << 6);
55117821895SHidetoshi Shimokawa 		err = 0;
55217821895SHidetoshi Shimokawa 		break;
55317821895SHidetoshi Shimokawa 	case FW_GTSTREAM:
55417821895SHidetoshi Shimokawa 		ichreq->ch = sc->fc->it[sub]->flag & 0x3f;
55517821895SHidetoshi Shimokawa 		ichreq->tag =(sc->fc->it[sub]->flag) >> 2 & 0x3;
55617821895SHidetoshi Shimokawa 		err = 0;
55717821895SHidetoshi Shimokawa 		break;
55817821895SHidetoshi Shimokawa 	case FW_SRSTREAM:
55917821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->flag &= ~0xff;
56017821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->flag |= (0x3f & ichreq->ch);
56117821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->flag |= ((0x3 & ichreq->tag) << 6);
56217821895SHidetoshi Shimokawa 		err = sc->fc->irx_enable(sc->fc, sub);
56317821895SHidetoshi Shimokawa 		break;
56417821895SHidetoshi Shimokawa 	case FW_GRSTREAM:
56517821895SHidetoshi Shimokawa 		ichreq->ch = sc->fc->ir[sub]->flag & 0x3f;
56617821895SHidetoshi Shimokawa 		ichreq->tag =(sc->fc->ir[sub]->flag) >> 2 & 0x3;
56717821895SHidetoshi Shimokawa 		err = 0;
56817821895SHidetoshi Shimokawa 		break;
5699190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV
57017821895SHidetoshi Shimokawa 	case FW_SSTDV:
57117821895SHidetoshi Shimokawa 		ibufreq = (struct fw_isobufreq *)
5725166f1dfSHidetoshi Shimokawa 			malloc(sizeof(struct fw_isobufreq), M_FW, M_NOWAIT);
57317821895SHidetoshi Shimokawa 		if(ibufreq == NULL){
57417821895SHidetoshi Shimokawa 			err = ENOMEM;
57517821895SHidetoshi Shimokawa 			break;
57617821895SHidetoshi Shimokawa 		}
5776d6f7f28SHidetoshi Shimokawa #if DV_PAL
5786d6f7f28SHidetoshi Shimokawa #define FWDVPACKET 300
5796d6f7f28SHidetoshi Shimokawa #else
5806d6f7f28SHidetoshi Shimokawa #define FWDVPACKET 250
5816d6f7f28SHidetoshi Shimokawa #endif
58217821895SHidetoshi Shimokawa #define FWDVPMAX 512
58317821895SHidetoshi Shimokawa 		ibufreq->rx.nchunk = 8;
58417821895SHidetoshi Shimokawa 		ibufreq->rx.npacket = 50;
58517821895SHidetoshi Shimokawa 		ibufreq->rx.psize = FWDVPMAX;
58617821895SHidetoshi Shimokawa 
58717821895SHidetoshi Shimokawa 		ibufreq->tx.nchunk = 5;
5886d6f7f28SHidetoshi Shimokawa 		ibufreq->tx.npacket = FWDVPACKET + 30;	/* > 320 or 267 */
58917821895SHidetoshi Shimokawa 		ibufreq->tx.psize = FWDVPMAX;
59017821895SHidetoshi Shimokawa 
59117821895SHidetoshi Shimokawa 		err = fw_ioctl(dev, FW_SSTBUF, (caddr_t)ibufreq, flag, td);
59217821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvpacket = FWDVPACKET;
5935166f1dfSHidetoshi Shimokawa 		free(ibufreq, M_FW);
59417821895SHidetoshi Shimokawa /* reserve a buffer space */
59517821895SHidetoshi Shimokawa #define NDVCHUNK 8
59617821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvproc = NULL;
59717821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvdma = NULL;
59817821895SHidetoshi Shimokawa 		sc->fc->it[sub]->flag |= FWXFERQ_DV;
5990aaa9a23SHidetoshi Shimokawa 		/* XXX check malloc failure */
60017821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvbuf
6015166f1dfSHidetoshi Shimokawa 			= (struct fw_dvbuf *)malloc(sizeof(struct fw_dvbuf) * NDVCHUNK, M_FW, M_NOWAIT);
60217821895SHidetoshi Shimokawa 		STAILQ_INIT(&sc->fc->it[sub]->dvvalid);
60317821895SHidetoshi Shimokawa 		STAILQ_INIT(&sc->fc->it[sub]->dvfree);
60417821895SHidetoshi Shimokawa 		for( i = 0 ; i < NDVCHUNK ; i++){
6050aaa9a23SHidetoshi Shimokawa 			/* XXX check malloc failure */
60617821895SHidetoshi Shimokawa 			sc->fc->it[sub]->dvbuf[i].buf
6075166f1dfSHidetoshi Shimokawa 				= malloc(FWDVPMAX * sc->fc->it[sub]->dvpacket, M_FW, M_NOWAIT);
60817821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&sc->fc->it[sub]->dvfree,
60917821895SHidetoshi Shimokawa 					&sc->fc->it[sub]->dvbuf[i], link);
61017821895SHidetoshi Shimokawa 		}
61117821895SHidetoshi Shimokawa 		break;
6129190691bSHidetoshi Shimokawa #endif
61317821895SHidetoshi Shimokawa 	case FW_SSTBUF:
61417821895SHidetoshi Shimokawa 		ir = sc->fc->ir[sub];
61517821895SHidetoshi Shimokawa 		it = sc->fc->it[sub];
61617821895SHidetoshi Shimokawa 
61717821895SHidetoshi Shimokawa 		if(ir->flag & FWXFERQ_RUNNING || it->flag & FWXFERQ_RUNNING){
61817821895SHidetoshi Shimokawa 			return(EBUSY);
61917821895SHidetoshi Shimokawa 		}
62017821895SHidetoshi Shimokawa 		if((ir->flag & FWXFERQ_EXTBUF) || (it->flag & FWXFERQ_EXTBUF)){
62117821895SHidetoshi Shimokawa 			return(EBUSY);
62217821895SHidetoshi Shimokawa 		}
62317821895SHidetoshi Shimokawa 		if((ibufreq->rx.nchunk *
62417821895SHidetoshi Shimokawa 			ibufreq->rx.psize * ibufreq->rx.npacket) +
62517821895SHidetoshi Shimokawa 		   (ibufreq->tx.nchunk *
62617821895SHidetoshi Shimokawa 			ibufreq->tx.psize * ibufreq->tx.npacket) <= 0){
62717821895SHidetoshi Shimokawa 				return(EINVAL);
62817821895SHidetoshi Shimokawa 		}
62917821895SHidetoshi Shimokawa 		if(ibufreq->rx.nchunk > FWSTMAXCHUNK ||
63017821895SHidetoshi Shimokawa 				ibufreq->tx.nchunk > FWSTMAXCHUNK){
63117821895SHidetoshi Shimokawa 			return(EINVAL);
63217821895SHidetoshi Shimokawa 		}
63317821895SHidetoshi Shimokawa 		ir->bulkxfer
634beb19fc5SHidetoshi Shimokawa 			= (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->rx.nchunk, M_FW, 0);
63517821895SHidetoshi Shimokawa 		if(ir->bulkxfer == NULL){
63617821895SHidetoshi Shimokawa 			return(ENOMEM);
63717821895SHidetoshi Shimokawa 		}
63817821895SHidetoshi Shimokawa 		it->bulkxfer
639beb19fc5SHidetoshi Shimokawa 			= (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->tx.nchunk, M_FW, 0);
64017821895SHidetoshi Shimokawa 		if(it->bulkxfer == NULL){
64117821895SHidetoshi Shimokawa 			return(ENOMEM);
64217821895SHidetoshi Shimokawa 		}
64317821895SHidetoshi Shimokawa 		ir->buf = malloc(
64417821895SHidetoshi Shimokawa 			ibufreq->rx.nchunk * ibufreq->rx.npacket
6457643dc18SHidetoshi Shimokawa 			/* XXX psize must be 2^n and less or
6467643dc18SHidetoshi Shimokawa 						equal to PAGE_SIZE */
64717821895SHidetoshi Shimokawa 			* ((ibufreq->rx.psize + 3) &~3),
648beb19fc5SHidetoshi Shimokawa 			M_FW, 0);
64917821895SHidetoshi Shimokawa 		if(ir->buf == NULL){
6505166f1dfSHidetoshi Shimokawa 			free(ir->bulkxfer, M_FW);
6515166f1dfSHidetoshi Shimokawa 			free(it->bulkxfer, M_FW);
65217821895SHidetoshi Shimokawa 			ir->bulkxfer = NULL;
65317821895SHidetoshi Shimokawa 			it->bulkxfer = NULL;
65417821895SHidetoshi Shimokawa 			it->buf = NULL;
65517821895SHidetoshi Shimokawa 			return(ENOMEM);
65617821895SHidetoshi Shimokawa 		}
65717821895SHidetoshi Shimokawa 		it->buf = malloc(
65817821895SHidetoshi Shimokawa 			ibufreq->tx.nchunk * ibufreq->tx.npacket
6597643dc18SHidetoshi Shimokawa 			/* XXX psize must be 2^n and less or
6607643dc18SHidetoshi Shimokawa 						equal to PAGE_SIZE */
66117821895SHidetoshi Shimokawa 			* ((ibufreq->tx.psize + 3) &~3),
662beb19fc5SHidetoshi Shimokawa 			M_FW, 0);
66317821895SHidetoshi Shimokawa 		if(it->buf == NULL){
6645166f1dfSHidetoshi Shimokawa 			free(ir->bulkxfer, M_FW);
6655166f1dfSHidetoshi Shimokawa 			free(it->bulkxfer, M_FW);
6665166f1dfSHidetoshi Shimokawa 			free(ir->buf, M_FW);
66717821895SHidetoshi Shimokawa 			ir->bulkxfer = NULL;
66817821895SHidetoshi Shimokawa 			it->bulkxfer = NULL;
66917821895SHidetoshi Shimokawa 			it->buf = NULL;
67017821895SHidetoshi Shimokawa 			return(ENOMEM);
67117821895SHidetoshi Shimokawa 		}
67217821895SHidetoshi Shimokawa 
67317821895SHidetoshi Shimokawa 		ir->bnchunk = ibufreq->rx.nchunk;
67417821895SHidetoshi Shimokawa 		ir->bnpacket = ibufreq->rx.npacket;
67517821895SHidetoshi Shimokawa 		ir->psize = (ibufreq->rx.psize + 3) & ~3;
67617821895SHidetoshi Shimokawa 		ir->queued = 0;
67717821895SHidetoshi Shimokawa 
67817821895SHidetoshi Shimokawa 		it->bnchunk = ibufreq->tx.nchunk;
67917821895SHidetoshi Shimokawa 		it->bnpacket = ibufreq->tx.npacket;
68017821895SHidetoshi Shimokawa 		it->psize = (ibufreq->tx.psize + 3) & ~3;
6815a7ba74dSHidetoshi Shimokawa 		it->queued = 0;
6825a7ba74dSHidetoshi Shimokawa 
6835a7ba74dSHidetoshi Shimokawa #ifdef FWXFERQ_DV
68417821895SHidetoshi Shimokawa 		it->dvdbc = 0;
68517821895SHidetoshi Shimokawa 		it->dvdiff = 0;
68617821895SHidetoshi Shimokawa 		it->dvsync = 0;
6870aaa9a23SHidetoshi Shimokawa 		it->dvoffset = 0;
6885a7ba74dSHidetoshi Shimokawa #endif
68917821895SHidetoshi Shimokawa 
69017821895SHidetoshi Shimokawa 		STAILQ_INIT(&ir->stvalid);
69117821895SHidetoshi Shimokawa 		STAILQ_INIT(&ir->stfree);
6925a7ba74dSHidetoshi Shimokawa 		STAILQ_INIT(&ir->stdma);
69317821895SHidetoshi Shimokawa 		ir->stproc = NULL;
69417821895SHidetoshi Shimokawa 
69517821895SHidetoshi Shimokawa 		STAILQ_INIT(&it->stvalid);
69617821895SHidetoshi Shimokawa 		STAILQ_INIT(&it->stfree);
6975a7ba74dSHidetoshi Shimokawa 		STAILQ_INIT(&it->stdma);
69817821895SHidetoshi Shimokawa 		it->stproc = NULL;
69917821895SHidetoshi Shimokawa 
70017821895SHidetoshi Shimokawa 		for(i = 0 ; i < sc->fc->ir[sub]->bnchunk; i++){
70117821895SHidetoshi Shimokawa 			ir->bulkxfer[i].buf =
70217821895SHidetoshi Shimokawa 				ir->buf +
70317821895SHidetoshi Shimokawa 				i * sc->fc->ir[sub]->bnpacket *
70417821895SHidetoshi Shimokawa 			  	sc->fc->ir[sub]->psize;
70517821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&ir->stfree,
70617821895SHidetoshi Shimokawa 					&ir->bulkxfer[i], link);
70717821895SHidetoshi Shimokawa 			ir->bulkxfer[i].npacket = ir->bnpacket;
70817821895SHidetoshi Shimokawa 		}
70917821895SHidetoshi Shimokawa 		for(i = 0 ; i < sc->fc->it[sub]->bnchunk; i++){
71017821895SHidetoshi Shimokawa 			it->bulkxfer[i].buf =
71117821895SHidetoshi Shimokawa 				it->buf +
71217821895SHidetoshi Shimokawa 				i * sc->fc->it[sub]->bnpacket *
71317821895SHidetoshi Shimokawa 			  	sc->fc->it[sub]->psize;
71417821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&it->stfree,
71517821895SHidetoshi Shimokawa 					&it->bulkxfer[i], link);
71617821895SHidetoshi Shimokawa 			it->bulkxfer[i].npacket = it->bnpacket;
71717821895SHidetoshi Shimokawa 		}
71817821895SHidetoshi Shimokawa 		ir->flag &= ~FWXFERQ_MODEMASK;
71917821895SHidetoshi Shimokawa 		ir->flag |= FWXFERQ_STREAM;
72017821895SHidetoshi Shimokawa 		ir->flag |= FWXFERQ_EXTBUF;
72117821895SHidetoshi Shimokawa 
72217821895SHidetoshi Shimokawa 		it->flag &= ~FWXFERQ_MODEMASK;
72317821895SHidetoshi Shimokawa 		it->flag |= FWXFERQ_STREAM;
72417821895SHidetoshi Shimokawa 		it->flag |= FWXFERQ_EXTBUF;
72517821895SHidetoshi Shimokawa 		err = 0;
72617821895SHidetoshi Shimokawa 		break;
72717821895SHidetoshi Shimokawa 	case FW_GSTBUF:
72817821895SHidetoshi Shimokawa 		ibufreq->rx.nchunk = sc->fc->ir[sub]->bnchunk;
72917821895SHidetoshi Shimokawa 		ibufreq->rx.npacket = sc->fc->ir[sub]->bnpacket;
73017821895SHidetoshi Shimokawa 		ibufreq->rx.psize = sc->fc->ir[sub]->psize;
73117821895SHidetoshi Shimokawa 
73217821895SHidetoshi Shimokawa 		ibufreq->tx.nchunk = sc->fc->it[sub]->bnchunk;
73317821895SHidetoshi Shimokawa 		ibufreq->tx.npacket = sc->fc->it[sub]->bnpacket;
73417821895SHidetoshi Shimokawa 		ibufreq->tx.psize = sc->fc->it[sub]->psize;
73517821895SHidetoshi Shimokawa 		break;
73617821895SHidetoshi Shimokawa 	case FW_ASYREQ:
73748249fe0SHidetoshi Shimokawa 		xfer = fw_xfer_alloc(M_FWXFER);
73817821895SHidetoshi Shimokawa 		if(xfer == NULL){
73917821895SHidetoshi Shimokawa 			err = ENOMEM;
74017821895SHidetoshi Shimokawa 			return err;
74117821895SHidetoshi Shimokawa 		}
74217821895SHidetoshi Shimokawa 		fp = &asyreq->pkt;
74317821895SHidetoshi Shimokawa 		switch (asyreq->req.type) {
74417821895SHidetoshi Shimokawa 		case FWASREQNODE:
74517821895SHidetoshi Shimokawa 			xfer->dst = ntohs(fp->mode.hdr.dst);
74617821895SHidetoshi Shimokawa 			break;
74717821895SHidetoshi Shimokawa 		case FWASREQEUI:
748958c7749SHidetoshi Shimokawa 			fwdev = fw_noderesolve_eui64(sc->fc,
749233b1b97SHidetoshi Shimokawa 						&asyreq->req.dst.eui);
75017821895SHidetoshi Shimokawa 			if (fwdev == NULL) {
75117faeefcSHidetoshi Shimokawa 				device_printf(sc->fc->bdev,
75217faeefcSHidetoshi Shimokawa 					"cannot find node\n");
75317821895SHidetoshi Shimokawa 				err = EINVAL;
75417821895SHidetoshi Shimokawa 				goto error;
75517821895SHidetoshi Shimokawa 			}
75617821895SHidetoshi Shimokawa 			xfer->dst = fwdev->dst;
75717821895SHidetoshi Shimokawa 			fp->mode.hdr.dst = htons(FWLOCALBUS | xfer->dst);
75817821895SHidetoshi Shimokawa 			break;
75917821895SHidetoshi Shimokawa 		case FWASRESTL:
76017821895SHidetoshi Shimokawa 			/* XXX what's this? */
76117821895SHidetoshi Shimokawa 			break;
76217821895SHidetoshi Shimokawa 		case FWASREQSTREAM:
76317821895SHidetoshi Shimokawa 			/* nothing to do */
76417821895SHidetoshi Shimokawa 			break;
76517821895SHidetoshi Shimokawa 		}
76617821895SHidetoshi Shimokawa 		xfer->spd = asyreq->req.sped;
76717821895SHidetoshi Shimokawa 		xfer->send.len = asyreq->req.len;
7685166f1dfSHidetoshi Shimokawa 		xfer->send.buf = malloc(xfer->send.len, M_FW, M_NOWAIT);
76917821895SHidetoshi Shimokawa 		if(xfer->send.buf == NULL){
77017821895SHidetoshi Shimokawa 			return ENOMEM;
77117821895SHidetoshi Shimokawa 		}
77217821895SHidetoshi Shimokawa 		xfer->send.off = 0;
77317821895SHidetoshi Shimokawa 		bcopy(fp, xfer->send.buf, xfer->send.len);
77417821895SHidetoshi Shimokawa 		xfer->act.hand = fw_asy_callback;
77517821895SHidetoshi Shimokawa 		err = fw_asyreq(sc->fc, sub, xfer);
77617821895SHidetoshi Shimokawa 		if(err){
77717821895SHidetoshi Shimokawa 			fw_xfer_free( xfer);
77817821895SHidetoshi Shimokawa 			return err;
77917821895SHidetoshi Shimokawa 		}
78017821895SHidetoshi Shimokawa 		err = tsleep((caddr_t)xfer, FWPRI, "asyreq", hz);
78117821895SHidetoshi Shimokawa 		if(err == 0){
78217821895SHidetoshi Shimokawa 			if(asyreq->req.len >= xfer->recv.len){
78317821895SHidetoshi Shimokawa 				asyreq->req.len = xfer->recv.len;
78417821895SHidetoshi Shimokawa 			}else{
78517821895SHidetoshi Shimokawa 				err = EINVAL;
78617821895SHidetoshi Shimokawa 			}
78717821895SHidetoshi Shimokawa 			bcopy(xfer->recv.buf + xfer->recv.off, fp, asyreq->req.len);
78817821895SHidetoshi Shimokawa 		}
78917821895SHidetoshi Shimokawa error:
79017821895SHidetoshi Shimokawa 		fw_xfer_free( xfer);
79117821895SHidetoshi Shimokawa 		break;
79217821895SHidetoshi Shimokawa 	case FW_IBUSRST:
79317821895SHidetoshi Shimokawa 		sc->fc->ibr(sc->fc);
79417821895SHidetoshi Shimokawa 		break;
79517821895SHidetoshi Shimokawa 	case FW_CBINDADDR:
79617821895SHidetoshi Shimokawa 		fwb = fw_bindlookup(sc->fc,
79717821895SHidetoshi Shimokawa 				bindreq->start.hi, bindreq->start.lo);
79817821895SHidetoshi Shimokawa 		if(fwb == NULL){
79917821895SHidetoshi Shimokawa 			err = EINVAL;
80017821895SHidetoshi Shimokawa 			break;
80117821895SHidetoshi Shimokawa 		}
80217821895SHidetoshi Shimokawa 		STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist);
80317821895SHidetoshi Shimokawa 		STAILQ_REMOVE(&sc->fc->ir[sub]->binds, fwb, fw_bind, chlist);
8045166f1dfSHidetoshi Shimokawa 		free(fwb, M_FW);
80517821895SHidetoshi Shimokawa 		break;
80617821895SHidetoshi Shimokawa 	case FW_SBINDADDR:
80717821895SHidetoshi Shimokawa 		if(bindreq->len <= 0 ){
80817821895SHidetoshi Shimokawa 			err = EINVAL;
80917821895SHidetoshi Shimokawa 			break;
81017821895SHidetoshi Shimokawa 		}
81117821895SHidetoshi Shimokawa 		if(bindreq->start.hi > 0xffff ){
81217821895SHidetoshi Shimokawa 			err = EINVAL;
81317821895SHidetoshi Shimokawa 			break;
81417821895SHidetoshi Shimokawa 		}
8155166f1dfSHidetoshi Shimokawa 		fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_FW, M_NOWAIT);
81617821895SHidetoshi Shimokawa 		if(fwb == NULL){
81717821895SHidetoshi Shimokawa 			err = ENOMEM;
81817821895SHidetoshi Shimokawa 			break;
81917821895SHidetoshi Shimokawa 		}
82017821895SHidetoshi Shimokawa 		fwb->start_hi = bindreq->start.hi;
82117821895SHidetoshi Shimokawa 		fwb->start_lo = bindreq->start.lo;
82217821895SHidetoshi Shimokawa 		fwb->addrlen = bindreq->len;
82317821895SHidetoshi Shimokawa 
82448249fe0SHidetoshi Shimokawa 		xfer = fw_xfer_alloc(M_FWXFER);
82517821895SHidetoshi Shimokawa 		if(xfer == NULL){
82617821895SHidetoshi Shimokawa 			err = ENOMEM;
82717821895SHidetoshi Shimokawa 			return err;
82817821895SHidetoshi Shimokawa 		}
82917821895SHidetoshi Shimokawa 		xfer->act_type = FWACT_CH;
83017821895SHidetoshi Shimokawa 		xfer->sub = sub;
83117821895SHidetoshi Shimokawa 		xfer->fc = sc->fc;
83217821895SHidetoshi Shimokawa 
83317821895SHidetoshi Shimokawa 		fwb->xfer = xfer;
83417821895SHidetoshi Shimokawa 		err = fw_bindadd(sc->fc, fwb);
83517821895SHidetoshi Shimokawa 		break;
83617821895SHidetoshi Shimokawa 	case FW_GDEVLST:
837c547b896SHidetoshi Shimokawa 		i = len = 1;
838c547b896SHidetoshi Shimokawa 		/* myself */
839c547b896SHidetoshi Shimokawa 		devinfo = &fwdevlst->dev[0];
840c547b896SHidetoshi Shimokawa 		devinfo->dst = sc->fc->nodeid;
841c547b896SHidetoshi Shimokawa 		devinfo->status = 0;	/* XXX */
842c547b896SHidetoshi Shimokawa 		devinfo->eui.hi = sc->fc->eui.hi;
843c547b896SHidetoshi Shimokawa 		devinfo->eui.lo = sc->fc->eui.lo;
8440981f5f0SHidetoshi Shimokawa 		STAILQ_FOREACH(fwdev, &sc->fc->devices, link) {
845c547b896SHidetoshi Shimokawa 			if(len < FW_MAX_DEVLST){
846c547b896SHidetoshi Shimokawa 				devinfo = &fwdevlst->dev[len++];
847c547b896SHidetoshi Shimokawa 				devinfo->dst = fwdev->dst;
848c547b896SHidetoshi Shimokawa 				devinfo->status =
849c547b896SHidetoshi Shimokawa 					(fwdev->status == FWDEVINVAL)?0:1;
850c547b896SHidetoshi Shimokawa 				devinfo->eui.hi = fwdev->eui.hi;
851c547b896SHidetoshi Shimokawa 				devinfo->eui.lo = fwdev->eui.lo;
85217821895SHidetoshi Shimokawa 			}
85317821895SHidetoshi Shimokawa 			i++;
85417821895SHidetoshi Shimokawa 		}
85517821895SHidetoshi Shimokawa 		fwdevlst->n = i;
856c547b896SHidetoshi Shimokawa 		fwdevlst->info_len = len;
85717821895SHidetoshi Shimokawa 		break;
85817821895SHidetoshi Shimokawa 	case FW_GTPMAP:
85917821895SHidetoshi Shimokawa 		bcopy(sc->fc->topology_map, data,
86017821895SHidetoshi Shimokawa 				(sc->fc->topology_map->crc_len + 1) * 4);
86117821895SHidetoshi Shimokawa 		break;
86217821895SHidetoshi Shimokawa 	case FW_GCROM:
8630981f5f0SHidetoshi Shimokawa 		STAILQ_FOREACH(fwdev, &sc->fc->devices, link)
8640981f5f0SHidetoshi Shimokawa 			if (FW_EUI64_EQUAL(fwdev->eui, crom_buf->eui))
86517821895SHidetoshi Shimokawa 				break;
86617821895SHidetoshi Shimokawa 		if (fwdev == NULL) {
86717821895SHidetoshi Shimokawa 			err = FWNODE_INVAL;
86817821895SHidetoshi Shimokawa 			break;
86917821895SHidetoshi Shimokawa 		}
87017821895SHidetoshi Shimokawa #if 0
87117821895SHidetoshi Shimokawa 		if (fwdev->csrrom[0] >> 24 == 1)
87217821895SHidetoshi Shimokawa 			len = 4;
87317821895SHidetoshi Shimokawa 		else
87417821895SHidetoshi Shimokawa 			len = (1 + ((fwdev->csrrom[0] >> 16) & 0xff)) * 4;
87517821895SHidetoshi Shimokawa #else
87617821895SHidetoshi Shimokawa 		if (fwdev->rommax < CSRROMOFF)
87717821895SHidetoshi Shimokawa 			len = 0;
87817821895SHidetoshi Shimokawa 		else
87917821895SHidetoshi Shimokawa 			len = fwdev->rommax - CSRROMOFF + 4;
88017821895SHidetoshi Shimokawa #endif
88117821895SHidetoshi Shimokawa 		if (crom_buf->len < len)
88217821895SHidetoshi Shimokawa 			len = crom_buf->len;
88317821895SHidetoshi Shimokawa 		else
88417821895SHidetoshi Shimokawa 			crom_buf->len = len;
88517821895SHidetoshi Shimokawa 		err = copyout(&fwdev->csrrom[0], crom_buf->ptr, len);
88617821895SHidetoshi Shimokawa 		break;
88717821895SHidetoshi Shimokawa 	default:
88817821895SHidetoshi Shimokawa 		sc->fc->ioctl (dev, cmd, data, flag, td);
88917821895SHidetoshi Shimokawa 		break;
89017821895SHidetoshi Shimokawa 	}
89117821895SHidetoshi Shimokawa 	return err;
89217821895SHidetoshi Shimokawa }
89317821895SHidetoshi Shimokawa int
89417821895SHidetoshi Shimokawa fw_poll(dev_t dev, int events, fw_proc *td)
89517821895SHidetoshi Shimokawa {
89617821895SHidetoshi Shimokawa 	int revents;
89717821895SHidetoshi Shimokawa 	int tmp;
89817821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
89917821895SHidetoshi Shimokawa 	int sub = DEV2DMACH(dev);
90017821895SHidetoshi Shimokawa 	struct firewire_softc *sc;
90117821895SHidetoshi Shimokawa 
90217821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
90317821895SHidetoshi Shimokawa 		return fwmem_poll(dev, events, td);
90417821895SHidetoshi Shimokawa 
90517821895SHidetoshi Shimokawa 	sc = devclass_get_softc(firewire_devclass, unit);
90617821895SHidetoshi Shimokawa 	revents = 0;
90717821895SHidetoshi Shimokawa 	tmp = POLLIN | POLLRDNORM;
90817821895SHidetoshi Shimokawa 	if (events & tmp) {
90917821895SHidetoshi Shimokawa 		if (STAILQ_FIRST(&sc->fc->ir[sub]->q) != NULL)
91017821895SHidetoshi Shimokawa 			revents |= tmp;
91117821895SHidetoshi Shimokawa 		else
91217821895SHidetoshi Shimokawa 			selrecord(td, &sc->fc->ir[sub]->rsel);
91317821895SHidetoshi Shimokawa 	}
91417821895SHidetoshi Shimokawa 	tmp = POLLOUT | POLLWRNORM;
91517821895SHidetoshi Shimokawa 	if (events & tmp) {
91617821895SHidetoshi Shimokawa 		/* XXX should be fixed */
91717821895SHidetoshi Shimokawa 		revents |= tmp;
91817821895SHidetoshi Shimokawa 	}
91917821895SHidetoshi Shimokawa 
92017821895SHidetoshi Shimokawa 	return revents;
92117821895SHidetoshi Shimokawa }
92217821895SHidetoshi Shimokawa 
92317821895SHidetoshi Shimokawa static int
92417821895SHidetoshi Shimokawa fw_mmap (dev_t dev, vm_offset_t offset, int nproto)
92517821895SHidetoshi Shimokawa {
92617821895SHidetoshi Shimokawa 	struct firewire_softc *fc;
92717821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
92817821895SHidetoshi Shimokawa 
92917821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
93017821895SHidetoshi Shimokawa 		return fwmem_mmap(dev, offset, nproto);
93117821895SHidetoshi Shimokawa 
93217821895SHidetoshi Shimokawa 	fc = devclass_get_softc(firewire_devclass, unit);
93317821895SHidetoshi Shimokawa 
93417821895SHidetoshi Shimokawa 	return EINVAL;
93517821895SHidetoshi Shimokawa }
936