xref: /freebsd/sys/dev/firewire/fwdev.c (revision c547b896f5bb72011400ccb2cb9a321b20b06596)
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){
14317821895SHidetoshi Shimokawa 			free(dvbuf->buf, M_DEVBUF);
14417821895SHidetoshi Shimokawa 			sc->fc->it[sub]->dvproc = NULL;
14517821895SHidetoshi Shimokawa 		}
14617821895SHidetoshi Shimokawa 		if((dvbuf = sc->fc->it[sub]->dvdma) != NULL){
14717821895SHidetoshi Shimokawa 			free(dvbuf->buf, M_DEVBUF);
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);
15217821895SHidetoshi Shimokawa 			free(dvbuf->buf, M_DEVBUF);
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);
15617821895SHidetoshi Shimokawa 			free(dvbuf->buf, M_DEVBUF);
15717821895SHidetoshi Shimokawa 		}
15817821895SHidetoshi Shimokawa 		free(sc->fc->it[sub]->dvbuf, M_DEVBUF);
15917821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvbuf = NULL;
16017821895SHidetoshi Shimokawa 	}
1619190691bSHidetoshi Shimokawa #endif
16217821895SHidetoshi Shimokawa 	if(sc->fc->ir[sub]->flag & FWXFERQ_EXTBUF){
16317821895SHidetoshi Shimokawa 		free(sc->fc->ir[sub]->buf, M_DEVBUF);
16417821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->buf = NULL;
16517821895SHidetoshi Shimokawa 		free(sc->fc->ir[sub]->bulkxfer, M_DEVBUF);
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){
17217821895SHidetoshi Shimokawa 		free(sc->fc->it[sub]->buf, M_DEVBUF);
17317821895SHidetoshi Shimokawa 		sc->fc->it[sub]->buf = NULL;
17417821895SHidetoshi Shimokawa 		free(sc->fc->it[sub]->bulkxfer, M_DEVBUF);
17517821895SHidetoshi Shimokawa 		sc->fc->it[sub]->bulkxfer = NULL;
17617821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvbuf = NULL;
17717821895SHidetoshi Shimokawa 		sc->fc->it[sub]->flag &= ~FWXFERQ_EXTBUF;
178e2ad5d6eSHidetoshi Shimokawa 		sc->fc->it[sub]->psize = 0;
17917821895SHidetoshi Shimokawa 		sc->fc->it[sub]->maxq = FWMAXQUEUE;
18017821895SHidetoshi Shimokawa 	}
18117821895SHidetoshi Shimokawa 	for(xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q);
18217821895SHidetoshi Shimokawa 		xfer != NULL; xfer = STAILQ_FIRST(&sc->fc->ir[sub]->q)){
18317821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->queued--;
18417821895SHidetoshi Shimokawa 		STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->q, link);
18517821895SHidetoshi Shimokawa 
18617821895SHidetoshi Shimokawa 		xfer->resp = 0;
18717821895SHidetoshi Shimokawa 		switch(xfer->act_type){
18817821895SHidetoshi Shimokawa 		case FWACT_XFER:
18917821895SHidetoshi Shimokawa 			fw_xfer_done(xfer);
19017821895SHidetoshi Shimokawa 			break;
19117821895SHidetoshi Shimokawa 		default:
19217821895SHidetoshi Shimokawa 			break;
19317821895SHidetoshi Shimokawa 		}
19417821895SHidetoshi Shimokawa 		fw_xfer_free(xfer);
19517821895SHidetoshi Shimokawa 	}
19617821895SHidetoshi Shimokawa 	for(fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds); fwb != NULL;
19717821895SHidetoshi Shimokawa 		fwb = STAILQ_FIRST(&sc->fc->ir[sub]->binds)){
19817821895SHidetoshi Shimokawa 		STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist);
19917821895SHidetoshi Shimokawa 		STAILQ_REMOVE_HEAD(&sc->fc->ir[sub]->binds, chlist);
20017821895SHidetoshi Shimokawa 		free(fwb, M_DEVBUF);
20117821895SHidetoshi Shimokawa 	}
20217821895SHidetoshi Shimokawa 	sc->fc->ir[sub]->flag &= ~FWXFERQ_MODEMASK;
20317821895SHidetoshi Shimokawa 	sc->fc->it[sub]->flag &= ~FWXFERQ_MODEMASK;
20417821895SHidetoshi Shimokawa 	return err;
20517821895SHidetoshi Shimokawa }
20617821895SHidetoshi Shimokawa 
20717821895SHidetoshi Shimokawa /*
20817821895SHidetoshi Shimokawa  * read request.
20917821895SHidetoshi Shimokawa  */
21017821895SHidetoshi Shimokawa static int
21117821895SHidetoshi Shimokawa fw_read (dev_t dev, struct uio *uio, int ioflag)
21217821895SHidetoshi Shimokawa {
21317821895SHidetoshi Shimokawa 	struct firewire_softc *sc;
21417821895SHidetoshi Shimokawa 	struct fw_xferq *ir;
21517821895SHidetoshi Shimokawa 	struct fw_xfer *xfer;
21617821895SHidetoshi Shimokawa 	int err = 0, s, slept = 0;
21717821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
21817821895SHidetoshi Shimokawa 	int sub = DEV2DMACH(dev);
21917821895SHidetoshi Shimokawa 	struct fw_pkt *fp;
22017821895SHidetoshi Shimokawa 
22117821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
22217821895SHidetoshi Shimokawa 		return fwmem_read(dev, uio, ioflag);
22317821895SHidetoshi Shimokawa 
22417821895SHidetoshi Shimokawa 	sc = devclass_get_softc(firewire_devclass, unit);
22517821895SHidetoshi Shimokawa 
22617821895SHidetoshi Shimokawa 	ir = sc->fc->ir[sub];
22717821895SHidetoshi Shimokawa 
22817821895SHidetoshi Shimokawa 	if(ir->flag & FWXFERQ_PACKET){
22917821895SHidetoshi Shimokawa 		ir->stproc = NULL;
23017821895SHidetoshi Shimokawa 	}
23117821895SHidetoshi Shimokawa readloop:
23217821895SHidetoshi Shimokawa 	xfer = STAILQ_FIRST(&ir->q);
23317821895SHidetoshi Shimokawa 	if(!(ir->flag & FWXFERQ_PACKET) && ir->stproc == NULL){
23417821895SHidetoshi Shimokawa 		ir->stproc = STAILQ_FIRST(&ir->stvalid);
23517821895SHidetoshi Shimokawa 		if(ir->stproc != NULL){
23617821895SHidetoshi Shimokawa 			s = splfw();
23717821895SHidetoshi Shimokawa 			STAILQ_REMOVE_HEAD(&ir->stvalid, link);
23817821895SHidetoshi Shimokawa 			splx(s);
23917821895SHidetoshi Shimokawa 			ir->queued = 0;
24017821895SHidetoshi Shimokawa 		}
24117821895SHidetoshi Shimokawa 	}
24217821895SHidetoshi Shimokawa 
24317821895SHidetoshi Shimokawa 	if(xfer == NULL && ir->stproc == NULL){
24417821895SHidetoshi Shimokawa 		if(slept == 0){
24517821895SHidetoshi Shimokawa 			slept = 1;
24617821895SHidetoshi Shimokawa 			if(!(ir->flag & FWXFERQ_RUNNING)
24717821895SHidetoshi Shimokawa 				&& (ir->flag & FWXFERQ_PACKET)){
24817821895SHidetoshi Shimokawa 				err = sc->fc->irx_enable(sc->fc, sub);
24917821895SHidetoshi Shimokawa 			}
25017821895SHidetoshi Shimokawa 			if(err){
25117821895SHidetoshi Shimokawa 				return err;
25217821895SHidetoshi Shimokawa 			}
25317821895SHidetoshi Shimokawa 			ir->flag |= FWXFERQ_WAKEUP;
25417821895SHidetoshi Shimokawa 			err = tsleep((caddr_t)ir, FWPRI, "fw_read", hz);
25517821895SHidetoshi Shimokawa 			if(err){
25617821895SHidetoshi Shimokawa 				ir->flag &= ~FWXFERQ_WAKEUP;
25717821895SHidetoshi Shimokawa 				return err;
25817821895SHidetoshi Shimokawa 			}
25917821895SHidetoshi Shimokawa 			goto readloop;
26017821895SHidetoshi Shimokawa 		}else{
26117821895SHidetoshi Shimokawa 			err = EIO;
26217821895SHidetoshi Shimokawa 			return err;
26317821895SHidetoshi Shimokawa 		}
26417821895SHidetoshi Shimokawa 	}else if(xfer != NULL){
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){
27517821895SHidetoshi Shimokawa 		fp = (struct fw_pkt *)(ir->stproc->buf + ir->queued * ir->psize);
27617821895SHidetoshi Shimokawa 		if(sc->fc->irx_post != NULL)
27717821895SHidetoshi Shimokawa 			sc->fc->irx_post(sc->fc, fp->mode.ld);
27817821895SHidetoshi Shimokawa 		if(ntohs(fp->mode.stream.len) == 0){
27917821895SHidetoshi Shimokawa 			err = EIO;
28017821895SHidetoshi Shimokawa 			return err;
28117821895SHidetoshi Shimokawa 		}
28217821895SHidetoshi Shimokawa 		err = uiomove((caddr_t)fp, ntohs(fp->mode.stream.len) + sizeof(u_int32_t), uio);
28317821895SHidetoshi Shimokawa 		fp->mode.stream.len = 0;
28417821895SHidetoshi Shimokawa 		ir->queued ++;
28517821895SHidetoshi Shimokawa 		if(ir->queued >= ir->bnpacket){
28617821895SHidetoshi Shimokawa 			s = splfw();
28717821895SHidetoshi Shimokawa 			ir->stproc->flag = 0;
28817821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&ir->stfree, ir->stproc, link);
28917821895SHidetoshi Shimokawa 			splx(s);
29017821895SHidetoshi Shimokawa 			ir->stproc = NULL;
29117821895SHidetoshi Shimokawa 		}
29217821895SHidetoshi Shimokawa 	}
29317821895SHidetoshi Shimokawa #if 0
29417821895SHidetoshi Shimokawa 	if(STAILQ_FIRST(&ir->q) == NULL &&
29517821895SHidetoshi Shimokawa 		(ir->flag & FWXFERQ_RUNNING) && (ir->flag & FWXFERQ_PACKET)){
29617821895SHidetoshi Shimokawa 		err = sc->fc->irx_enable(sc->fc, sub);
29717821895SHidetoshi Shimokawa 	}
29817821895SHidetoshi Shimokawa #endif
29917821895SHidetoshi Shimokawa #if 0
30017821895SHidetoshi Shimokawa 	if(STAILQ_FIRST(&ir->stvalid) == NULL &&
30117821895SHidetoshi Shimokawa 		(ir->flag & FWXFERQ_RUNNING) && !(ir->flag & FWXFERQ_PACKET)){
30217821895SHidetoshi Shimokawa 		err = sc->fc->irx_enable(sc->fc, sub);
30317821895SHidetoshi Shimokawa 	}
30417821895SHidetoshi Shimokawa #endif
30517821895SHidetoshi Shimokawa 	return err;
30617821895SHidetoshi Shimokawa }
30717821895SHidetoshi Shimokawa 
30817821895SHidetoshi Shimokawa static int
30917821895SHidetoshi Shimokawa fw_write (dev_t dev, struct uio *uio, int ioflag)
31017821895SHidetoshi Shimokawa {
31117821895SHidetoshi Shimokawa 	int err = 0;
31217821895SHidetoshi Shimokawa 	struct firewire_softc *sc;
31317821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
31417821895SHidetoshi Shimokawa 	int sub = DEV2DMACH(dev);
31517821895SHidetoshi Shimokawa 	int s, slept = 0;
31617821895SHidetoshi Shimokawa 	struct fw_pkt *fp;
31717821895SHidetoshi Shimokawa 	struct fw_xfer *xfer;
31817821895SHidetoshi Shimokawa 	struct fw_xferq *xferq;
31917821895SHidetoshi Shimokawa 	struct firewire_comm *fc;
32017821895SHidetoshi Shimokawa 	struct fw_xferq *it;
32117821895SHidetoshi Shimokawa 
32217821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
32317821895SHidetoshi Shimokawa 		return fwmem_write(dev, uio, ioflag);
32417821895SHidetoshi Shimokawa 
32517821895SHidetoshi Shimokawa 	sc = devclass_get_softc(firewire_devclass, unit);
32617821895SHidetoshi Shimokawa 	fc = sc->fc;
32717821895SHidetoshi Shimokawa 	it = sc->fc->it[sub];
32817821895SHidetoshi Shimokawa 
32917821895SHidetoshi Shimokawa 	fp = (struct fw_pkt *)uio->uio_iov->iov_base;
33017821895SHidetoshi Shimokawa 	switch(fp->mode.common.tcode){
33117821895SHidetoshi Shimokawa 	case FWTCODE_RREQQ:
33217821895SHidetoshi Shimokawa 	case FWTCODE_RREQB:
33317821895SHidetoshi Shimokawa 	case FWTCODE_LREQ:
33417821895SHidetoshi Shimokawa 		err = EINVAL;
33517821895SHidetoshi Shimokawa 		return err;
33617821895SHidetoshi Shimokawa 	case FWTCODE_WREQQ:
33717821895SHidetoshi Shimokawa 	case FWTCODE_WREQB:
33817821895SHidetoshi Shimokawa 		xferq = fc->atq;
33917821895SHidetoshi Shimokawa 		break;
34017821895SHidetoshi Shimokawa 	case FWTCODE_STREAM:
34117821895SHidetoshi Shimokawa 		if(it->flag & FWXFERQ_PACKET){
34217821895SHidetoshi Shimokawa 			xferq = fc->atq;
34317821895SHidetoshi Shimokawa 		}else{
34417821895SHidetoshi Shimokawa 			xferq = NULL;
34517821895SHidetoshi Shimokawa 		}
34617821895SHidetoshi Shimokawa 		break;
34717821895SHidetoshi Shimokawa 	case FWTCODE_WRES:
34817821895SHidetoshi Shimokawa 	case FWTCODE_RRESQ:
34917821895SHidetoshi Shimokawa 	case FWTCODE_RRESB:
35017821895SHidetoshi Shimokawa 	case FWTCODE_LRES:
35117821895SHidetoshi Shimokawa 		xferq = fc->ats;
35217821895SHidetoshi Shimokawa 		break;
35317821895SHidetoshi Shimokawa 	default:
35417821895SHidetoshi Shimokawa 		err = EINVAL;
35517821895SHidetoshi Shimokawa 		return err;
35617821895SHidetoshi Shimokawa 	}
35717821895SHidetoshi Shimokawa 	/* Discard unsent buffered stream packet, when sending Asyrequrst */
35817821895SHidetoshi Shimokawa 	if(xferq != NULL && it->stproc != NULL){
35917821895SHidetoshi Shimokawa 		s = splfw();
36017821895SHidetoshi Shimokawa 		it->stproc->flag = 0;
36117821895SHidetoshi Shimokawa 		STAILQ_INSERT_TAIL(&it->stfree, it->stproc, link);
36217821895SHidetoshi Shimokawa 		splx(s);
36317821895SHidetoshi Shimokawa 		it->stproc = NULL;
36417821895SHidetoshi Shimokawa 	}
3659190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV
36617821895SHidetoshi Shimokawa 	if(xferq == NULL && !(it->flag & FWXFERQ_DV)){
3679190691bSHidetoshi Shimokawa #else
3689190691bSHidetoshi Shimokawa 	if (xferq == NULL) {
3699190691bSHidetoshi Shimokawa #endif
37017821895SHidetoshi Shimokawa isoloop:
37117821895SHidetoshi Shimokawa 		if(it->stproc == NULL){
37217821895SHidetoshi Shimokawa 			it->stproc = STAILQ_FIRST(&it->stfree);
37317821895SHidetoshi Shimokawa 			if(it->stproc != NULL){
37417821895SHidetoshi Shimokawa 				s = splfw();
37517821895SHidetoshi Shimokawa 				STAILQ_REMOVE_HEAD(&it->stfree, link);
37617821895SHidetoshi Shimokawa 				splx(s);
37717821895SHidetoshi Shimokawa 				it->queued = 0;
37817821895SHidetoshi Shimokawa 			}else if(slept == 0){
37917821895SHidetoshi Shimokawa 				slept = 1;
38017821895SHidetoshi Shimokawa 				err = sc->fc->itx_enable(sc->fc, sub);
38117821895SHidetoshi Shimokawa 				if(err){
38217821895SHidetoshi Shimokawa 					return err;
38317821895SHidetoshi Shimokawa 				}
38417821895SHidetoshi Shimokawa 				err = tsleep((caddr_t)it, FWPRI, "fw_write", hz);
38517821895SHidetoshi Shimokawa 				if(err){
38617821895SHidetoshi Shimokawa 					return err;
38717821895SHidetoshi Shimokawa 				}
38817821895SHidetoshi Shimokawa 				goto isoloop;
38917821895SHidetoshi Shimokawa 			}else{
39017821895SHidetoshi Shimokawa 				err = EIO;
39117821895SHidetoshi Shimokawa 				return err;
39217821895SHidetoshi Shimokawa 			}
39317821895SHidetoshi Shimokawa 		}
3940aaa9a23SHidetoshi Shimokawa #if 0 /* What's this for? (overwritten by the following uiomove)*/
39517821895SHidetoshi Shimokawa 		fp = (struct fw_pkt *)(it->stproc->buf + it->queued * it->psize);
39617821895SHidetoshi Shimokawa 		fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t));
3970aaa9a23SHidetoshi Shimokawa #endif
39817821895SHidetoshi Shimokawa 		err = uiomove(it->stproc->buf + it->queued * it->psize,
39917821895SHidetoshi Shimokawa 							uio->uio_resid, uio);
40017821895SHidetoshi Shimokawa 		it->queued ++;
40117821895SHidetoshi Shimokawa 		if(it->queued >= it->btpacket){
40217821895SHidetoshi Shimokawa 			s = splfw();
40317821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&it->stvalid, it->stproc, link);
40417821895SHidetoshi Shimokawa 			splx(s);
40517821895SHidetoshi Shimokawa 			it->stproc = NULL;
40617821895SHidetoshi Shimokawa 			fw_tbuf_update(sc->fc, sub, 0);
40717821895SHidetoshi Shimokawa 			err = sc->fc->itx_enable(sc->fc, sub);
40817821895SHidetoshi Shimokawa 		}
40917821895SHidetoshi Shimokawa 		return err;
4109190691bSHidetoshi Shimokawa 	}
4119190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV
4129190691bSHidetoshi Shimokawa 	if(xferq == NULL && it->flag & FWXFERQ_DV){
41317821895SHidetoshi Shimokawa dvloop:
41417821895SHidetoshi Shimokawa 		if(it->dvproc == NULL){
41517821895SHidetoshi Shimokawa 			it->dvproc = STAILQ_FIRST(&it->dvfree);
41617821895SHidetoshi Shimokawa 			if(it->dvproc != NULL){
41717821895SHidetoshi Shimokawa 				s = splfw();
41817821895SHidetoshi Shimokawa 				STAILQ_REMOVE_HEAD(&it->dvfree, link);
41917821895SHidetoshi Shimokawa 				splx(s);
42017821895SHidetoshi Shimokawa 				it->dvptr = 0;
42117821895SHidetoshi Shimokawa 			}else if(slept == 0){
42217821895SHidetoshi Shimokawa 				slept = 1;
42317821895SHidetoshi Shimokawa 				err = sc->fc->itx_enable(sc->fc, sub);
42417821895SHidetoshi Shimokawa 				if(err){
42517821895SHidetoshi Shimokawa 					return err;
42617821895SHidetoshi Shimokawa 				}
42717821895SHidetoshi Shimokawa 				err = tsleep((caddr_t)it, FWPRI, "fw_write", hz);
42817821895SHidetoshi Shimokawa 				if(err){
42917821895SHidetoshi Shimokawa 					return err;
43017821895SHidetoshi Shimokawa 				}
43117821895SHidetoshi Shimokawa 				goto dvloop;
43217821895SHidetoshi Shimokawa 			}else{
43317821895SHidetoshi Shimokawa 				err = EIO;
43417821895SHidetoshi Shimokawa 				return err;
43517821895SHidetoshi Shimokawa 			}
43617821895SHidetoshi Shimokawa 		}
4370aaa9a23SHidetoshi Shimokawa #if 0 /* What's this for? (it->dvptr? overwritten by the following uiomove)*/
43817821895SHidetoshi Shimokawa 		fp = (struct fw_pkt *)(it->dvproc->buf + it->queued * it->psize);
43917821895SHidetoshi Shimokawa 		fp->mode.stream.len = htons(uio->uio_resid - sizeof(u_int32_t));
4400aaa9a23SHidetoshi Shimokawa #endif
44117821895SHidetoshi Shimokawa 		err = uiomove(it->dvproc->buf + it->dvptr,
44217821895SHidetoshi Shimokawa 							uio->uio_resid, uio);
44317821895SHidetoshi Shimokawa 		it->dvptr += it->psize;
44417821895SHidetoshi Shimokawa 		if(err){
44517821895SHidetoshi Shimokawa 			return err;
44617821895SHidetoshi Shimokawa 		}
44717821895SHidetoshi Shimokawa 		if(it->dvptr >= it->psize * it->dvpacket){
44817821895SHidetoshi Shimokawa 			s = splfw();
44917821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&it->dvvalid, it->dvproc, link);
45017821895SHidetoshi Shimokawa 			splx(s);
45117821895SHidetoshi Shimokawa 			it->dvproc = NULL;
45217821895SHidetoshi Shimokawa 			err = fw_tbuf_update(sc->fc, sub, 0);
45317821895SHidetoshi Shimokawa 			if(err){
45417821895SHidetoshi Shimokawa 				return err;
45517821895SHidetoshi Shimokawa 			}
45617821895SHidetoshi Shimokawa 			err = sc->fc->itx_enable(sc->fc, sub);
45717821895SHidetoshi Shimokawa 		}
45817821895SHidetoshi Shimokawa 		return err;
45917821895SHidetoshi Shimokawa 	}
4609190691bSHidetoshi Shimokawa #endif
46117821895SHidetoshi Shimokawa 	if(xferq != NULL){
46217821895SHidetoshi Shimokawa 		xfer = fw_xfer_alloc();
46317821895SHidetoshi Shimokawa 		if(xfer == NULL){
46417821895SHidetoshi Shimokawa 			err = ENOMEM;
46517821895SHidetoshi Shimokawa 			return err;
46617821895SHidetoshi Shimokawa 		}
46717821895SHidetoshi Shimokawa 		xfer->send.buf = malloc(uio->uio_resid, M_DEVBUF, M_NOWAIT);
46817821895SHidetoshi Shimokawa 		if(xfer->send.buf == NULL){
46917821895SHidetoshi Shimokawa 			fw_xfer_free( xfer);
47017821895SHidetoshi Shimokawa 			err = ENOBUFS;
47117821895SHidetoshi Shimokawa 			return err;
47217821895SHidetoshi Shimokawa 		}
47317821895SHidetoshi Shimokawa 		xfer->dst = ntohs(fp->mode.hdr.dst);
47417821895SHidetoshi Shimokawa #if 0
47517821895SHidetoshi Shimokawa 		switch(fp->mode.common.tcode){
47617821895SHidetoshi Shimokawa 		case FWTCODE_WREQQ:
47717821895SHidetoshi Shimokawa 		case FWTCODE_WREQB:
47817821895SHidetoshi Shimokawa 			if((tl = fw_get_tlabel(fc, xfer)) == -1 ){
47917821895SHidetoshi Shimokawa 				fw_xfer_free( xfer);
48017821895SHidetoshi Shimokawa 				err = EAGAIN;
48117821895SHidetoshi Shimokawa 				return err;
48217821895SHidetoshi Shimokawa 			}
48317821895SHidetoshi Shimokawa 			fp->mode.hdr.tlrt = tl << 2;
48417821895SHidetoshi Shimokawa 		default:
48517821895SHidetoshi Shimokawa 			break;
48617821895SHidetoshi Shimokawa 		}
48717821895SHidetoshi Shimokawa 
48817821895SHidetoshi Shimokawa 		xfer->tl = fp->mode.hdr.tlrt >> 2;
48917821895SHidetoshi Shimokawa 		xfer->tcode = fp->mode.common.tcode;
49017821895SHidetoshi Shimokawa 		xfer->fc = fc;
49117821895SHidetoshi Shimokawa 		xfer->q = xferq;
49217821895SHidetoshi Shimokawa 		xfer->act_type = FWACT_XFER;
49317821895SHidetoshi Shimokawa 		xfer->retry_req = fw_asybusy;
49417821895SHidetoshi Shimokawa #endif
49517821895SHidetoshi Shimokawa 		xfer->send.len = uio->uio_resid;
49617821895SHidetoshi Shimokawa 		xfer->send.off = 0;
49717821895SHidetoshi Shimokawa 		xfer->spd = 0;/* XXX: how to setup it */
49817821895SHidetoshi Shimokawa 		xfer->act.hand = fw_asy_callback;
49917821895SHidetoshi Shimokawa 
50017821895SHidetoshi Shimokawa 		err = uiomove(xfer->send.buf, uio->uio_resid, uio);
50117821895SHidetoshi Shimokawa 		if(err){
50217821895SHidetoshi Shimokawa 			fw_xfer_free( xfer);
50317821895SHidetoshi Shimokawa 			return err;
50417821895SHidetoshi Shimokawa 		}
50517821895SHidetoshi Shimokawa #if 0
50617821895SHidetoshi Shimokawa 		fw_asystart(xfer);
50717821895SHidetoshi Shimokawa #else
50817821895SHidetoshi Shimokawa 		fw_asyreq(fc, -1, xfer);
50917821895SHidetoshi Shimokawa #endif
51017821895SHidetoshi Shimokawa 		err = tsleep((caddr_t)xfer, FWPRI, "fw_write", hz);
51117821895SHidetoshi Shimokawa 		if(xfer->resp == EBUSY)
51217821895SHidetoshi Shimokawa 			return EBUSY;
51317821895SHidetoshi Shimokawa 		fw_xfer_free( xfer);
51417821895SHidetoshi Shimokawa 		return err;
51517821895SHidetoshi Shimokawa 	}
51617821895SHidetoshi Shimokawa 	return EINVAL;
51717821895SHidetoshi Shimokawa }
51817821895SHidetoshi Shimokawa 
51917821895SHidetoshi Shimokawa /*
52017821895SHidetoshi Shimokawa  * ioctl support.
52117821895SHidetoshi Shimokawa  */
52217821895SHidetoshi Shimokawa int
52317821895SHidetoshi Shimokawa fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
52417821895SHidetoshi Shimokawa {
52517821895SHidetoshi Shimokawa 	struct firewire_softc *sc;
52617821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
52717821895SHidetoshi Shimokawa 	int sub = DEV2DMACH(dev);
52817821895SHidetoshi Shimokawa 	int i, len, err = 0;
52917821895SHidetoshi Shimokawa 	struct fw_device *fwdev;
53017821895SHidetoshi Shimokawa 	struct fw_bind *fwb;
53117821895SHidetoshi Shimokawa 	struct fw_xferq *ir, *it;
53217821895SHidetoshi Shimokawa 	struct fw_xfer *xfer;
53317821895SHidetoshi Shimokawa 	struct fw_pkt *fp;
534c547b896SHidetoshi Shimokawa 	struct fw_devinfo *devinfo;
53517821895SHidetoshi Shimokawa 
53617821895SHidetoshi Shimokawa 	struct fw_devlstreq *fwdevlst = (struct fw_devlstreq *)data;
53717821895SHidetoshi Shimokawa 	struct fw_asyreq *asyreq = (struct fw_asyreq *)data;
53817821895SHidetoshi Shimokawa 	struct fw_isochreq *ichreq = (struct fw_isochreq *)data;
53917821895SHidetoshi Shimokawa 	struct fw_isobufreq *ibufreq = (struct fw_isobufreq *)data;
54017821895SHidetoshi Shimokawa 	struct fw_asybindreq *bindreq = (struct fw_asybindreq *)data;
54117821895SHidetoshi Shimokawa 	struct fw_crom_buf *crom_buf = (struct fw_crom_buf *)data;
54217821895SHidetoshi Shimokawa 
54317821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
54417821895SHidetoshi Shimokawa 		return fwmem_ioctl(dev, cmd, data, flag, td);
54517821895SHidetoshi Shimokawa 
54617821895SHidetoshi Shimokawa 	sc = devclass_get_softc(firewire_devclass, unit);
54717821895SHidetoshi Shimokawa 	if (!data)
54817821895SHidetoshi Shimokawa 		return(EINVAL);
54917821895SHidetoshi Shimokawa 
55017821895SHidetoshi Shimokawa 	switch (cmd) {
55117821895SHidetoshi Shimokawa 	case FW_STSTREAM:
55217821895SHidetoshi Shimokawa 		sc->fc->it[sub]->flag &= ~0xff;
55317821895SHidetoshi Shimokawa 		sc->fc->it[sub]->flag |= (0x3f & ichreq->ch);
55417821895SHidetoshi Shimokawa 		sc->fc->it[sub]->flag |= ((0x3 & ichreq->tag) << 6);
55517821895SHidetoshi Shimokawa 		err = 0;
55617821895SHidetoshi Shimokawa 		break;
55717821895SHidetoshi Shimokawa 	case FW_GTSTREAM:
55817821895SHidetoshi Shimokawa 		ichreq->ch = sc->fc->it[sub]->flag & 0x3f;
55917821895SHidetoshi Shimokawa 		ichreq->tag =(sc->fc->it[sub]->flag) >> 2 & 0x3;
56017821895SHidetoshi Shimokawa 		err = 0;
56117821895SHidetoshi Shimokawa 		break;
56217821895SHidetoshi Shimokawa 	case FW_SRSTREAM:
56317821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->flag &= ~0xff;
56417821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->flag |= (0x3f & ichreq->ch);
56517821895SHidetoshi Shimokawa 		sc->fc->ir[sub]->flag |= ((0x3 & ichreq->tag) << 6);
56617821895SHidetoshi Shimokawa 		err = sc->fc->irx_enable(sc->fc, sub);
56717821895SHidetoshi Shimokawa 		break;
56817821895SHidetoshi Shimokawa 	case FW_GRSTREAM:
56917821895SHidetoshi Shimokawa 		ichreq->ch = sc->fc->ir[sub]->flag & 0x3f;
57017821895SHidetoshi Shimokawa 		ichreq->tag =(sc->fc->ir[sub]->flag) >> 2 & 0x3;
57117821895SHidetoshi Shimokawa 		err = 0;
57217821895SHidetoshi Shimokawa 		break;
5739190691bSHidetoshi Shimokawa #ifdef FWXFERQ_DV
57417821895SHidetoshi Shimokawa 	case FW_SSTDV:
57517821895SHidetoshi Shimokawa 		ibufreq = (struct fw_isobufreq *)
57617821895SHidetoshi Shimokawa 			malloc(sizeof(struct fw_isobufreq), M_DEVBUF, M_NOWAIT);
57717821895SHidetoshi Shimokawa 		if(ibufreq == NULL){
57817821895SHidetoshi Shimokawa 			err = ENOMEM;
57917821895SHidetoshi Shimokawa 			break;
58017821895SHidetoshi Shimokawa 		}
5816d6f7f28SHidetoshi Shimokawa #if DV_PAL
5826d6f7f28SHidetoshi Shimokawa #define FWDVPACKET 300
5836d6f7f28SHidetoshi Shimokawa #else
5846d6f7f28SHidetoshi Shimokawa #define FWDVPACKET 250
5856d6f7f28SHidetoshi Shimokawa #endif
58617821895SHidetoshi Shimokawa #define FWDVPMAX 512
58717821895SHidetoshi Shimokawa 		ibufreq->rx.nchunk = 8;
58817821895SHidetoshi Shimokawa 		ibufreq->rx.npacket = 50;
58917821895SHidetoshi Shimokawa 		ibufreq->rx.psize = FWDVPMAX;
59017821895SHidetoshi Shimokawa 
59117821895SHidetoshi Shimokawa 		ibufreq->tx.nchunk = 5;
5926d6f7f28SHidetoshi Shimokawa 		ibufreq->tx.npacket = FWDVPACKET + 30;	/* > 320 or 267 */
59317821895SHidetoshi Shimokawa 		ibufreq->tx.psize = FWDVPMAX;
59417821895SHidetoshi Shimokawa 
59517821895SHidetoshi Shimokawa 		err = fw_ioctl(dev, FW_SSTBUF, (caddr_t)ibufreq, flag, td);
59617821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvpacket = FWDVPACKET;
59717821895SHidetoshi Shimokawa 		free(ibufreq, M_DEVBUF);
59817821895SHidetoshi Shimokawa /* reserve a buffer space */
59917821895SHidetoshi Shimokawa #define NDVCHUNK 8
60017821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvproc = NULL;
60117821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvdma = NULL;
60217821895SHidetoshi Shimokawa 		sc->fc->it[sub]->flag |= FWXFERQ_DV;
6030aaa9a23SHidetoshi Shimokawa 		/* XXX check malloc failure */
60417821895SHidetoshi Shimokawa 		sc->fc->it[sub]->dvbuf
605ae8c82bbSHidetoshi Shimokawa 			= (struct fw_dvbuf *)malloc(sizeof(struct fw_dvbuf) * NDVCHUNK, M_DEVBUF, M_NOWAIT);
60617821895SHidetoshi Shimokawa 		STAILQ_INIT(&sc->fc->it[sub]->dvvalid);
60717821895SHidetoshi Shimokawa 		STAILQ_INIT(&sc->fc->it[sub]->dvfree);
60817821895SHidetoshi Shimokawa 		for( i = 0 ; i < NDVCHUNK ; i++){
6090aaa9a23SHidetoshi Shimokawa 			/* XXX check malloc failure */
61017821895SHidetoshi Shimokawa 			sc->fc->it[sub]->dvbuf[i].buf
611ae8c82bbSHidetoshi Shimokawa 				= malloc(FWDVPMAX * sc->fc->it[sub]->dvpacket, M_DEVBUF, M_NOWAIT);
61217821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&sc->fc->it[sub]->dvfree,
61317821895SHidetoshi Shimokawa 					&sc->fc->it[sub]->dvbuf[i], link);
61417821895SHidetoshi Shimokawa 		}
61517821895SHidetoshi Shimokawa 		break;
6169190691bSHidetoshi Shimokawa #endif
61717821895SHidetoshi Shimokawa 	case FW_SSTBUF:
61817821895SHidetoshi Shimokawa 		ir = sc->fc->ir[sub];
61917821895SHidetoshi Shimokawa 		it = sc->fc->it[sub];
62017821895SHidetoshi Shimokawa 
62117821895SHidetoshi Shimokawa 		if(ir->flag & FWXFERQ_RUNNING || it->flag & FWXFERQ_RUNNING){
62217821895SHidetoshi Shimokawa 			return(EBUSY);
62317821895SHidetoshi Shimokawa 		}
62417821895SHidetoshi Shimokawa 		if((ir->flag & FWXFERQ_EXTBUF) || (it->flag & FWXFERQ_EXTBUF)){
62517821895SHidetoshi Shimokawa 			return(EBUSY);
62617821895SHidetoshi Shimokawa 		}
62717821895SHidetoshi Shimokawa 		if((ibufreq->rx.nchunk *
62817821895SHidetoshi Shimokawa 			ibufreq->rx.psize * ibufreq->rx.npacket) +
62917821895SHidetoshi Shimokawa 		   (ibufreq->tx.nchunk *
63017821895SHidetoshi Shimokawa 			ibufreq->tx.psize * ibufreq->tx.npacket) <= 0){
63117821895SHidetoshi Shimokawa 				return(EINVAL);
63217821895SHidetoshi Shimokawa 		}
63317821895SHidetoshi Shimokawa 		if(ibufreq->rx.nchunk > FWSTMAXCHUNK ||
63417821895SHidetoshi Shimokawa 				ibufreq->tx.nchunk > FWSTMAXCHUNK){
63517821895SHidetoshi Shimokawa 			return(EINVAL);
63617821895SHidetoshi Shimokawa 		}
63717821895SHidetoshi Shimokawa 		ir->bulkxfer
638ae8c82bbSHidetoshi Shimokawa 			= (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->rx.nchunk, M_DEVBUF, M_NOWAIT);
63917821895SHidetoshi Shimokawa 		if(ir->bulkxfer == NULL){
64017821895SHidetoshi Shimokawa 			return(ENOMEM);
64117821895SHidetoshi Shimokawa 		}
64217821895SHidetoshi Shimokawa 		it->bulkxfer
643ae8c82bbSHidetoshi Shimokawa 			= (struct fw_bulkxfer *)malloc(sizeof(struct fw_bulkxfer) * ibufreq->tx.nchunk, M_DEVBUF, M_NOWAIT);
64417821895SHidetoshi Shimokawa 		if(it->bulkxfer == NULL){
64517821895SHidetoshi Shimokawa 			return(ENOMEM);
64617821895SHidetoshi Shimokawa 		}
64717821895SHidetoshi Shimokawa 		ir->buf = malloc(
64817821895SHidetoshi Shimokawa 			ibufreq->rx.nchunk * ibufreq->rx.npacket
6497643dc18SHidetoshi Shimokawa 			/* XXX psize must be 2^n and less or
6507643dc18SHidetoshi Shimokawa 						equal to PAGE_SIZE */
65117821895SHidetoshi Shimokawa 			* ((ibufreq->rx.psize + 3) &~3),
652ae8c82bbSHidetoshi Shimokawa 			M_DEVBUF, M_NOWAIT);
65317821895SHidetoshi Shimokawa 		if(ir->buf == NULL){
65417821895SHidetoshi Shimokawa 			free(ir->bulkxfer, M_DEVBUF);
65517821895SHidetoshi Shimokawa 			free(it->bulkxfer, M_DEVBUF);
65617821895SHidetoshi Shimokawa 			ir->bulkxfer = NULL;
65717821895SHidetoshi Shimokawa 			it->bulkxfer = NULL;
65817821895SHidetoshi Shimokawa 			it->buf = NULL;
65917821895SHidetoshi Shimokawa 			return(ENOMEM);
66017821895SHidetoshi Shimokawa 		}
66117821895SHidetoshi Shimokawa 		it->buf = malloc(
66217821895SHidetoshi Shimokawa 			ibufreq->tx.nchunk * ibufreq->tx.npacket
6637643dc18SHidetoshi Shimokawa 			/* XXX psize must be 2^n and less or
6647643dc18SHidetoshi Shimokawa 						equal to PAGE_SIZE */
66517821895SHidetoshi Shimokawa 			* ((ibufreq->tx.psize + 3) &~3),
666ae8c82bbSHidetoshi Shimokawa 			M_DEVBUF, M_NOWAIT);
66717821895SHidetoshi Shimokawa 		if(it->buf == NULL){
66817821895SHidetoshi Shimokawa 			free(ir->bulkxfer, M_DEVBUF);
66917821895SHidetoshi Shimokawa 			free(it->bulkxfer, M_DEVBUF);
67017821895SHidetoshi Shimokawa 			free(ir->buf, M_DEVBUF);
67117821895SHidetoshi Shimokawa 			ir->bulkxfer = NULL;
67217821895SHidetoshi Shimokawa 			it->bulkxfer = NULL;
67317821895SHidetoshi Shimokawa 			it->buf = NULL;
67417821895SHidetoshi Shimokawa 			return(ENOMEM);
67517821895SHidetoshi Shimokawa 		}
67617821895SHidetoshi Shimokawa 
67717821895SHidetoshi Shimokawa 		ir->bnchunk = ibufreq->rx.nchunk;
67817821895SHidetoshi Shimokawa 		ir->bnpacket = ibufreq->rx.npacket;
67917821895SHidetoshi Shimokawa 		ir->btpacket = ibufreq->rx.npacket;
68017821895SHidetoshi Shimokawa 		ir->psize = (ibufreq->rx.psize + 3) & ~3;
68117821895SHidetoshi Shimokawa 		ir->queued = 0;
68217821895SHidetoshi Shimokawa 
68317821895SHidetoshi Shimokawa 		it->bnchunk = ibufreq->tx.nchunk;
68417821895SHidetoshi Shimokawa 		it->bnpacket = ibufreq->tx.npacket;
68517821895SHidetoshi Shimokawa 		it->btpacket = ibufreq->tx.npacket;
68617821895SHidetoshi Shimokawa 		it->psize = (ibufreq->tx.psize + 3) & ~3;
68717821895SHidetoshi Shimokawa 		ir->queued = 0;
68817821895SHidetoshi Shimokawa 		it->dvdbc = 0;
68917821895SHidetoshi Shimokawa 		it->dvdiff = 0;
69017821895SHidetoshi Shimokawa 		it->dvsync = 0;
6910aaa9a23SHidetoshi Shimokawa 		it->dvoffset = 0;
69217821895SHidetoshi Shimokawa 
69317821895SHidetoshi Shimokawa 		STAILQ_INIT(&ir->stvalid);
69417821895SHidetoshi Shimokawa 		STAILQ_INIT(&ir->stfree);
69517821895SHidetoshi Shimokawa 		ir->stdma = NULL;
69617821895SHidetoshi Shimokawa 		ir->stdma2 = NULL;
69717821895SHidetoshi Shimokawa 		ir->stproc = NULL;
69817821895SHidetoshi Shimokawa 
69917821895SHidetoshi Shimokawa 		STAILQ_INIT(&it->stvalid);
70017821895SHidetoshi Shimokawa 		STAILQ_INIT(&it->stfree);
70117821895SHidetoshi Shimokawa 		it->stdma = NULL;
70217821895SHidetoshi Shimokawa 		it->stdma2 = NULL;
70317821895SHidetoshi Shimokawa 		it->stproc = NULL;
70417821895SHidetoshi Shimokawa 
70517821895SHidetoshi Shimokawa 		for(i = 0 ; i < sc->fc->ir[sub]->bnchunk; i++){
70617821895SHidetoshi Shimokawa 			ir->bulkxfer[i].buf =
70717821895SHidetoshi Shimokawa 				ir->buf +
70817821895SHidetoshi Shimokawa 				i * sc->fc->ir[sub]->bnpacket *
70917821895SHidetoshi Shimokawa 			  	sc->fc->ir[sub]->psize;
71017821895SHidetoshi Shimokawa 			ir->bulkxfer[i].flag = 0;
71117821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&ir->stfree,
71217821895SHidetoshi Shimokawa 					&ir->bulkxfer[i], link);
71317821895SHidetoshi Shimokawa 			ir->bulkxfer[i].npacket = ir->bnpacket;
71417821895SHidetoshi Shimokawa 		}
71517821895SHidetoshi Shimokawa 		for(i = 0 ; i < sc->fc->it[sub]->bnchunk; i++){
71617821895SHidetoshi Shimokawa 			it->bulkxfer[i].buf =
71717821895SHidetoshi Shimokawa 				it->buf +
71817821895SHidetoshi Shimokawa 				i * sc->fc->it[sub]->bnpacket *
71917821895SHidetoshi Shimokawa 			  	sc->fc->it[sub]->psize;
72017821895SHidetoshi Shimokawa 			it->bulkxfer[i].flag = 0;
72117821895SHidetoshi Shimokawa 			STAILQ_INSERT_TAIL(&it->stfree,
72217821895SHidetoshi Shimokawa 					&it->bulkxfer[i], link);
72317821895SHidetoshi Shimokawa 			it->bulkxfer[i].npacket = it->bnpacket;
72417821895SHidetoshi Shimokawa 		}
72517821895SHidetoshi Shimokawa 		ir->flag &= ~FWXFERQ_MODEMASK;
72617821895SHidetoshi Shimokawa 		ir->flag |= FWXFERQ_STREAM;
72717821895SHidetoshi Shimokawa 		ir->flag |= FWXFERQ_EXTBUF;
72817821895SHidetoshi Shimokawa 
72917821895SHidetoshi Shimokawa 		it->flag &= ~FWXFERQ_MODEMASK;
73017821895SHidetoshi Shimokawa 		it->flag |= FWXFERQ_STREAM;
73117821895SHidetoshi Shimokawa 		it->flag |= FWXFERQ_EXTBUF;
73217821895SHidetoshi Shimokawa 		err = 0;
73317821895SHidetoshi Shimokawa 		break;
73417821895SHidetoshi Shimokawa 	case FW_GSTBUF:
73517821895SHidetoshi Shimokawa 		ibufreq->rx.nchunk = sc->fc->ir[sub]->bnchunk;
73617821895SHidetoshi Shimokawa 		ibufreq->rx.npacket = sc->fc->ir[sub]->bnpacket;
73717821895SHidetoshi Shimokawa 		ibufreq->rx.psize = sc->fc->ir[sub]->psize;
73817821895SHidetoshi Shimokawa 
73917821895SHidetoshi Shimokawa 		ibufreq->tx.nchunk = sc->fc->it[sub]->bnchunk;
74017821895SHidetoshi Shimokawa 		ibufreq->tx.npacket = sc->fc->it[sub]->bnpacket;
74117821895SHidetoshi Shimokawa 		ibufreq->tx.psize = sc->fc->it[sub]->psize;
74217821895SHidetoshi Shimokawa 		break;
74317821895SHidetoshi Shimokawa 	case FW_ASYREQ:
74417821895SHidetoshi Shimokawa 		xfer = fw_xfer_alloc();
74517821895SHidetoshi Shimokawa 		if(xfer == NULL){
74617821895SHidetoshi Shimokawa 			err = ENOMEM;
74717821895SHidetoshi Shimokawa 			return err;
74817821895SHidetoshi Shimokawa 		}
74917821895SHidetoshi Shimokawa 		fp = &asyreq->pkt;
75017821895SHidetoshi Shimokawa 		switch (asyreq->req.type) {
75117821895SHidetoshi Shimokawa 		case FWASREQNODE:
75217821895SHidetoshi Shimokawa 			xfer->dst = ntohs(fp->mode.hdr.dst);
75317821895SHidetoshi Shimokawa 			break;
75417821895SHidetoshi Shimokawa 		case FWASREQEUI:
75517821895SHidetoshi Shimokawa 			fwdev = fw_noderesolve(sc->fc, asyreq->req.dst.eui);
75617821895SHidetoshi Shimokawa 			if (fwdev == NULL) {
75717faeefcSHidetoshi Shimokawa 				device_printf(sc->fc->bdev,
75817faeefcSHidetoshi Shimokawa 					"cannot find node\n");
75917821895SHidetoshi Shimokawa 				err = EINVAL;
76017821895SHidetoshi Shimokawa 				goto error;
76117821895SHidetoshi Shimokawa 			}
76217821895SHidetoshi Shimokawa 			xfer->dst = fwdev->dst;
76317821895SHidetoshi Shimokawa 			fp->mode.hdr.dst = htons(FWLOCALBUS | xfer->dst);
76417821895SHidetoshi Shimokawa 			break;
76517821895SHidetoshi Shimokawa 		case FWASRESTL:
76617821895SHidetoshi Shimokawa 			/* XXX what's this? */
76717821895SHidetoshi Shimokawa 			break;
76817821895SHidetoshi Shimokawa 		case FWASREQSTREAM:
76917821895SHidetoshi Shimokawa 			/* nothing to do */
77017821895SHidetoshi Shimokawa 			break;
77117821895SHidetoshi Shimokawa 		}
77217821895SHidetoshi Shimokawa 		xfer->spd = asyreq->req.sped;
77317821895SHidetoshi Shimokawa 		xfer->send.len = asyreq->req.len;
77417821895SHidetoshi Shimokawa 		xfer->send.buf = malloc(xfer->send.len, M_DEVBUF, M_NOWAIT);
77517821895SHidetoshi Shimokawa 		if(xfer->send.buf == NULL){
77617821895SHidetoshi Shimokawa 			return ENOMEM;
77717821895SHidetoshi Shimokawa 		}
77817821895SHidetoshi Shimokawa 		xfer->send.off = 0;
77917821895SHidetoshi Shimokawa 		bcopy(fp, xfer->send.buf, xfer->send.len);
78017821895SHidetoshi Shimokawa 		xfer->act.hand = fw_asy_callback;
78117821895SHidetoshi Shimokawa 		err = fw_asyreq(sc->fc, sub, xfer);
78217821895SHidetoshi Shimokawa 		if(err){
78317821895SHidetoshi Shimokawa 			fw_xfer_free( xfer);
78417821895SHidetoshi Shimokawa 			return err;
78517821895SHidetoshi Shimokawa 		}
78617821895SHidetoshi Shimokawa 		err = tsleep((caddr_t)xfer, FWPRI, "asyreq", hz);
78717821895SHidetoshi Shimokawa 		if(err == 0){
78817821895SHidetoshi Shimokawa 			if(asyreq->req.len >= xfer->recv.len){
78917821895SHidetoshi Shimokawa 				asyreq->req.len = xfer->recv.len;
79017821895SHidetoshi Shimokawa 			}else{
79117821895SHidetoshi Shimokawa 				err = EINVAL;
79217821895SHidetoshi Shimokawa 			}
79317821895SHidetoshi Shimokawa 			bcopy(xfer->recv.buf + xfer->recv.off, fp, asyreq->req.len);
79417821895SHidetoshi Shimokawa 		}
79517821895SHidetoshi Shimokawa error:
79617821895SHidetoshi Shimokawa 		fw_xfer_free( xfer);
79717821895SHidetoshi Shimokawa 		break;
79817821895SHidetoshi Shimokawa 	case FW_IBUSRST:
79917821895SHidetoshi Shimokawa 		sc->fc->ibr(sc->fc);
80017821895SHidetoshi Shimokawa 		break;
80117821895SHidetoshi Shimokawa 	case FW_CBINDADDR:
80217821895SHidetoshi Shimokawa 		fwb = fw_bindlookup(sc->fc,
80317821895SHidetoshi Shimokawa 				bindreq->start.hi, bindreq->start.lo);
80417821895SHidetoshi Shimokawa 		if(fwb == NULL){
80517821895SHidetoshi Shimokawa 			err = EINVAL;
80617821895SHidetoshi Shimokawa 			break;
80717821895SHidetoshi Shimokawa 		}
80817821895SHidetoshi Shimokawa 		STAILQ_REMOVE(&sc->fc->binds, fwb, fw_bind, fclist);
80917821895SHidetoshi Shimokawa 		STAILQ_REMOVE(&sc->fc->ir[sub]->binds, fwb, fw_bind, chlist);
81017821895SHidetoshi Shimokawa 		free(fwb, M_DEVBUF);
81117821895SHidetoshi Shimokawa 		break;
81217821895SHidetoshi Shimokawa 	case FW_SBINDADDR:
81317821895SHidetoshi Shimokawa 		if(bindreq->len <= 0 ){
81417821895SHidetoshi Shimokawa 			err = EINVAL;
81517821895SHidetoshi Shimokawa 			break;
81617821895SHidetoshi Shimokawa 		}
81717821895SHidetoshi Shimokawa 		if(bindreq->start.hi > 0xffff ){
81817821895SHidetoshi Shimokawa 			err = EINVAL;
81917821895SHidetoshi Shimokawa 			break;
82017821895SHidetoshi Shimokawa 		}
821ae8c82bbSHidetoshi Shimokawa 		fwb = (struct fw_bind *)malloc(sizeof (struct fw_bind), M_DEVBUF, M_NOWAIT);
82217821895SHidetoshi Shimokawa 		if(fwb == NULL){
82317821895SHidetoshi Shimokawa 			err = ENOMEM;
82417821895SHidetoshi Shimokawa 			break;
82517821895SHidetoshi Shimokawa 		}
82617821895SHidetoshi Shimokawa 		fwb->start_hi = bindreq->start.hi;
82717821895SHidetoshi Shimokawa 		fwb->start_lo = bindreq->start.lo;
82817821895SHidetoshi Shimokawa 		fwb->addrlen = bindreq->len;
82917821895SHidetoshi Shimokawa 
83017821895SHidetoshi Shimokawa 		xfer = fw_xfer_alloc();
83117821895SHidetoshi Shimokawa 		if(xfer == NULL){
83217821895SHidetoshi Shimokawa 			err = ENOMEM;
83317821895SHidetoshi Shimokawa 			return err;
83417821895SHidetoshi Shimokawa 		}
83517821895SHidetoshi Shimokawa 		xfer->act_type = FWACT_CH;
83617821895SHidetoshi Shimokawa 		xfer->sub = sub;
83717821895SHidetoshi Shimokawa 		xfer->fc = sc->fc;
83817821895SHidetoshi Shimokawa 
83917821895SHidetoshi Shimokawa 		fwb->xfer = xfer;
84017821895SHidetoshi Shimokawa 		err = fw_bindadd(sc->fc, fwb);
84117821895SHidetoshi Shimokawa 		break;
84217821895SHidetoshi Shimokawa 	case FW_GDEVLST:
843c547b896SHidetoshi Shimokawa 		i = len = 1;
844c547b896SHidetoshi Shimokawa 		/* myself */
845c547b896SHidetoshi Shimokawa 		devinfo = &fwdevlst->dev[0];
846c547b896SHidetoshi Shimokawa 		devinfo->dst = sc->fc->nodeid;
847c547b896SHidetoshi Shimokawa 		devinfo->status = 0;	/* XXX */
848c547b896SHidetoshi Shimokawa 		devinfo->eui.hi = sc->fc->eui.hi;
849c547b896SHidetoshi Shimokawa 		devinfo->eui.lo = sc->fc->eui.lo;
85017821895SHidetoshi Shimokawa 		for (fwdev = TAILQ_FIRST(&sc->fc->devices); fwdev != NULL;
85117821895SHidetoshi Shimokawa 			fwdev = TAILQ_NEXT(fwdev, link)) {
852c547b896SHidetoshi Shimokawa 			if(len < FW_MAX_DEVLST){
853c547b896SHidetoshi Shimokawa 				devinfo = &fwdevlst->dev[len++];
854c547b896SHidetoshi Shimokawa 				devinfo->dst = fwdev->dst;
855c547b896SHidetoshi Shimokawa 				devinfo->status =
856c547b896SHidetoshi Shimokawa 					(fwdev->status == FWDEVINVAL)?0:1;
857c547b896SHidetoshi Shimokawa 				devinfo->eui.hi = fwdev->eui.hi;
858c547b896SHidetoshi Shimokawa 				devinfo->eui.lo = fwdev->eui.lo;
85917821895SHidetoshi Shimokawa 			}
86017821895SHidetoshi Shimokawa 			i++;
86117821895SHidetoshi Shimokawa 		}
86217821895SHidetoshi Shimokawa 		fwdevlst->n = i;
863c547b896SHidetoshi Shimokawa 		fwdevlst->info_len = len;
86417821895SHidetoshi Shimokawa 		break;
86517821895SHidetoshi Shimokawa 	case FW_GTPMAP:
86617821895SHidetoshi Shimokawa 		bcopy(sc->fc->topology_map, data,
86717821895SHidetoshi Shimokawa 				(sc->fc->topology_map->crc_len + 1) * 4);
86817821895SHidetoshi Shimokawa 		break;
86917821895SHidetoshi Shimokawa 	case FW_GCROM:
87017821895SHidetoshi Shimokawa 		for (fwdev = TAILQ_FIRST(&sc->fc->devices); fwdev != NULL;
87117821895SHidetoshi Shimokawa 			fwdev = TAILQ_NEXT(fwdev, link)) {
87217821895SHidetoshi Shimokawa 			if (fwdev->eui.hi == crom_buf->eui.hi &&
87317821895SHidetoshi Shimokawa 					fwdev->eui.lo == crom_buf->eui.lo)
87417821895SHidetoshi Shimokawa 				break;
87517821895SHidetoshi Shimokawa 		}
87617821895SHidetoshi Shimokawa 		if (fwdev == NULL) {
87717821895SHidetoshi Shimokawa 			err = FWNODE_INVAL;
87817821895SHidetoshi Shimokawa 			break;
87917821895SHidetoshi Shimokawa 		}
88017821895SHidetoshi Shimokawa #if 0
88117821895SHidetoshi Shimokawa 		if (fwdev->csrrom[0] >> 24 == 1)
88217821895SHidetoshi Shimokawa 			len = 4;
88317821895SHidetoshi Shimokawa 		else
88417821895SHidetoshi Shimokawa 			len = (1 + ((fwdev->csrrom[0] >> 16) & 0xff)) * 4;
88517821895SHidetoshi Shimokawa #else
88617821895SHidetoshi Shimokawa 		if (fwdev->rommax < CSRROMOFF)
88717821895SHidetoshi Shimokawa 			len = 0;
88817821895SHidetoshi Shimokawa 		else
88917821895SHidetoshi Shimokawa 			len = fwdev->rommax - CSRROMOFF + 4;
89017821895SHidetoshi Shimokawa #endif
89117821895SHidetoshi Shimokawa 		if (crom_buf->len < len)
89217821895SHidetoshi Shimokawa 			len = crom_buf->len;
89317821895SHidetoshi Shimokawa 		else
89417821895SHidetoshi Shimokawa 			crom_buf->len = len;
89517821895SHidetoshi Shimokawa 		err = copyout(&fwdev->csrrom[0], crom_buf->ptr, len);
89617821895SHidetoshi Shimokawa 		break;
89717821895SHidetoshi Shimokawa 	default:
89817821895SHidetoshi Shimokawa 		sc->fc->ioctl (dev, cmd, data, flag, td);
89917821895SHidetoshi Shimokawa 		break;
90017821895SHidetoshi Shimokawa 	}
90117821895SHidetoshi Shimokawa 	return err;
90217821895SHidetoshi Shimokawa }
90317821895SHidetoshi Shimokawa int
90417821895SHidetoshi Shimokawa fw_poll(dev_t dev, int events, fw_proc *td)
90517821895SHidetoshi Shimokawa {
90617821895SHidetoshi Shimokawa 	int revents;
90717821895SHidetoshi Shimokawa 	int tmp;
90817821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
90917821895SHidetoshi Shimokawa 	int sub = DEV2DMACH(dev);
91017821895SHidetoshi Shimokawa 	struct firewire_softc *sc;
91117821895SHidetoshi Shimokawa 
91217821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
91317821895SHidetoshi Shimokawa 		return fwmem_poll(dev, events, td);
91417821895SHidetoshi Shimokawa 
91517821895SHidetoshi Shimokawa 	sc = devclass_get_softc(firewire_devclass, unit);
91617821895SHidetoshi Shimokawa 	revents = 0;
91717821895SHidetoshi Shimokawa 	tmp = POLLIN | POLLRDNORM;
91817821895SHidetoshi Shimokawa 	if (events & tmp) {
91917821895SHidetoshi Shimokawa 		if (STAILQ_FIRST(&sc->fc->ir[sub]->q) != NULL)
92017821895SHidetoshi Shimokawa 			revents |= tmp;
92117821895SHidetoshi Shimokawa 		else
92217821895SHidetoshi Shimokawa 			selrecord(td, &sc->fc->ir[sub]->rsel);
92317821895SHidetoshi Shimokawa 	}
92417821895SHidetoshi Shimokawa 	tmp = POLLOUT | POLLWRNORM;
92517821895SHidetoshi Shimokawa 	if (events & tmp) {
92617821895SHidetoshi Shimokawa 		/* XXX should be fixed */
92717821895SHidetoshi Shimokawa 		revents |= tmp;
92817821895SHidetoshi Shimokawa 	}
92917821895SHidetoshi Shimokawa 
93017821895SHidetoshi Shimokawa 	return revents;
93117821895SHidetoshi Shimokawa }
93217821895SHidetoshi Shimokawa 
93317821895SHidetoshi Shimokawa static int
93417821895SHidetoshi Shimokawa fw_mmap (dev_t dev, vm_offset_t offset, int nproto)
93517821895SHidetoshi Shimokawa {
93617821895SHidetoshi Shimokawa 	struct firewire_softc *fc;
93717821895SHidetoshi Shimokawa 	int unit = DEV2UNIT(dev);
93817821895SHidetoshi Shimokawa 
93917821895SHidetoshi Shimokawa 	if (DEV_FWMEM(dev))
94017821895SHidetoshi Shimokawa 		return fwmem_mmap(dev, offset, nproto);
94117821895SHidetoshi Shimokawa 
94217821895SHidetoshi Shimokawa 	fc = devclass_get_softc(firewire_devclass, unit);
94317821895SHidetoshi Shimokawa 
94417821895SHidetoshi Shimokawa 	return EINVAL;
94517821895SHidetoshi Shimokawa }
946