1 /* $NetBSD: fwdev.c,v 1.16 2009/03/18 17:06:49 cegger Exp $ */
3 * Copyright (c) 2003 Hidetoshi Shimokawa
4 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the acknowledgement as bellow:
18 * This product includes software developed by K. Kobayashi and H. Shimokawa
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
35 * $FreeBSD: src/sys/dev/firewire/fwdev.c,v 1.52 2007/06/06 14:31:36 simokawa Exp $
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: fwdev.c,v 1.16 2009/03/18 17:06:49 cegger Exp $");
42 #if defined(__FreeBSD__)
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/types.h>
47 #if defined(__DragonFly__) || __FreeBSD_version < 500000
53 #include <sys/kernel.h>
54 #include <sys/malloc.h>
59 #include <sys/ctype.h>
62 #include <sys/ioccom.h>
67 #include "firewirereg.h"
72 #include <dev/firewire/fw_port.h>
73 #include <dev/firewire/firewire.h>
74 #include <dev/firewire/firewirereg.h>
75 #include <dev/firewire/fwdma.h>
76 #include <dev/firewire/fwmem.h>
77 #include <dev/firewire/iec68113.h>
79 #elif defined(__NetBSD__)
80 #include <sys/param.h>
81 #include <sys/device.h>
82 #include <sys/errno.h>
85 #include <sys/kernel.h>
86 #include <sys/malloc.h>
93 #include <dev/ieee1394/fw_port.h>
94 #include <dev/ieee1394/firewire.h>
95 #include <dev/ieee1394/firewirereg.h>
96 #include <dev/ieee1394/fwdma.h>
97 #include <dev/ieee1394/fwmem.h>
98 #include <dev/ieee1394/iec68113.h>
101 #define FWNODE_INVAL 0xffff
103 #if defined(__FreeBSD__)
104 static d_open_t fw_open
;
105 static d_close_t fw_close
;
106 static d_ioctl_t fw_ioctl
;
107 static d_poll_t fw_poll
;
108 static d_read_t fw_read
; /* for Isochronous packet */
109 static d_write_t fw_write
;
110 static d_mmap_t fw_mmap
;
111 static d_strategy_t fw_strategy
;
113 struct cdevsw firewire_cdevsw
= {
115 #define CDEV_MAJOR 127
116 "fw", CDEV_MAJOR
, D_MEM
, NULL
, 0,
117 fw_open
, fw_close
, fw_read
, fw_write
, fw_ioctl
,
118 fw_poll
, fw_mmap
, fw_strategy
, nodump
, nopsize
,
119 #elif __FreeBSD_version >= 500104
120 .d_version
= D_VERSION
,
128 .d_strategy
= fw_strategy
,
132 #define CDEV_MAJOR 127
133 fw_open
, fw_close
, fw_read
, fw_write
, fw_ioctl
,
134 fw_poll
, fw_mmap
, fw_strategy
, "fw", CDEV_MAJOR
,
135 nodump
, nopsize
, D_MEM
, -1
138 #elif defined(__NetBSD__)
139 dev_type_open(fw_open
);
140 dev_type_close(fw_close
);
141 dev_type_read(fw_read
);
142 dev_type_write(fw_write
);
143 dev_type_ioctl(fw_ioctl
);
144 dev_type_poll(fw_poll
);
145 dev_type_mmap(fw_mmap
);
146 dev_type_strategy(fw_strategy
);
148 const struct bdevsw fw_bdevsw
= {
149 fw_open
, fw_close
, fw_strategy
, fw_ioctl
, nodump
, nosize
, D_OTHER
,
152 const struct cdevsw fw_cdevsw
= {
153 fw_open
, fw_close
, fw_read
, fw_write
, fw_ioctl
,
154 nostop
, notty
, fw_poll
, fw_mmap
, nokqfilter
, D_OTHER
,
159 struct firewire_comm
*fc
;
162 struct fw_isobufreq bufreq
;
163 STAILQ_HEAD(, fw_bind
) binds
;
164 STAILQ_HEAD(, fw_xfer
) rq
;
168 fwdev_allocbuf(struct firewire_comm
*fc
, struct fw_xferq
*q
,
169 struct fw_bufspec
*b
)
173 if (q
->flag
& (FWXFERQ_RUNNING
| FWXFERQ_EXTBUF
))
176 q
->bulkxfer
= (struct fw_bulkxfer
*) malloc(
177 sizeof(struct fw_bulkxfer
) * b
->nchunk
,
179 if (q
->bulkxfer
== NULL
)
182 b
->psize
= roundup2(b
->psize
, sizeof(uint32_t));
183 q
->buf
= fwdma_malloc_multiseg(fc
, sizeof(uint32_t),
184 b
->psize
, b
->nchunk
* b
->npacket
, BUS_DMA_WAITOK
);
186 if (q
->buf
== NULL
) {
187 free(q
->bulkxfer
, M_FW
);
191 q
->bnchunk
= b
->nchunk
;
192 q
->bnpacket
= b
->npacket
;
193 q
->psize
= (b
->psize
+ 3) & ~3;
196 STAILQ_INIT(&q
->stvalid
);
197 STAILQ_INIT(&q
->stfree
);
198 STAILQ_INIT(&q
->stdma
);
201 for(i
= 0 ; i
< q
->bnchunk
; i
++){
202 q
->bulkxfer
[i
].poffset
= i
* q
->bnpacket
;
203 q
->bulkxfer
[i
].mbuf
= NULL
;
204 STAILQ_INSERT_TAIL(&q
->stfree
, &q
->bulkxfer
[i
], link
);
207 q
->flag
&= ~FWXFERQ_MODEMASK
;
208 q
->flag
|= FWXFERQ_STREAM
;
209 q
->flag
|= FWXFERQ_EXTBUF
;
215 fwdev_freebuf(struct fw_xferq
*q
)
217 if (q
->flag
& FWXFERQ_EXTBUF
) {
219 fwdma_free_multiseg(q
->buf
);
221 free(q
->bulkxfer
, M_FW
);
223 q
->flag
&= ~FWXFERQ_EXTBUF
;
225 q
->maxq
= FWMAXQUEUE
;
240 if (dev
->si_drv1
!= NULL
) {
244 /* set dummy value for allocation */
245 dev
->si_drv1
= (void *)-1;
248 dev
->si_drv1
= malloc(sizeof(struct fw_drv1
), M_FW
, M_WAITOK
| M_ZERO
);
249 if (dev
->si_drv1
== NULL
)
252 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
253 if ((dev
->si_flags
& SI_NAMED
) == 0) {
254 int unit
= DEV2UNIT(dev
);
255 int sub
= DEV2SUB(dev
);
257 make_dev(&firewire_cdevsw
, minor(dev
),
258 UID_ROOT
, GID_OPERATOR
, 0660,
259 "fw%d.%d", unit
, sub
);
263 d
= (struct fw_drv1
*)dev
->si_drv1
;
265 STAILQ_INIT(&d
->binds
);
273 struct firewire_comm
*fc
;
275 struct fw_xfer
*xfer
;
282 d
= (struct fw_drv1
*)dev
->si_drv1
;
286 for (fwb
= STAILQ_FIRST(&d
->binds
); fwb
!= NULL
;
287 fwb
= STAILQ_FIRST(&d
->binds
)) {
288 fw_bindremove(fc
, fwb
);
289 STAILQ_REMOVE_HEAD(&d
->binds
, chlist
);
290 fw_xferlist_remove(&fwb
->xferlist
);
294 struct fw_xferq
*ir
= d
->ir
;
296 if ((ir
->flag
& FWXFERQ_OPEN
) == 0)
298 if (ir
->flag
& FWXFERQ_RUNNING
) {
299 ir
->flag
&= ~FWXFERQ_RUNNING
;
300 fc
->irx_disable(fc
, ir
->dmach
);
304 /* drain receiving buffer */
305 for (xfer
= STAILQ_FIRST(&ir
->q
);
306 xfer
!= NULL
; xfer
= STAILQ_FIRST(&ir
->q
)) {
308 STAILQ_REMOVE_HEAD(&ir
->q
, link
);
313 ir
->flag
&= ~(FWXFERQ_OPEN
|
314 FWXFERQ_MODEMASK
| FWXFERQ_CHTAGMASK
);
319 struct fw_xferq
*it
= d
->it
;
321 if ((it
->flag
& FWXFERQ_OPEN
) == 0)
323 if (it
->flag
& FWXFERQ_RUNNING
) {
324 it
->flag
&= ~FWXFERQ_RUNNING
;
325 fc
->itx_disable(fc
, it
->dmach
);
329 it
->flag
&= ~(FWXFERQ_OPEN
|
330 FWXFERQ_MODEMASK
| FWXFERQ_CHTAGMASK
);
333 free(dev
->si_drv1
, M_FW
);
340 fw_read_async(struct fw_drv1
*d
, struct uio
*uio
, int ioflag
)
343 struct fw_xfer
*xfer
;
346 const struct tcode_info
*tinfo
;
349 while ((xfer
= STAILQ_FIRST(&d
->rq
)) == NULL
&& err
== 0)
350 err
= fw_msleep(&d
->rq
, FW_GMTX(d
->fc
), FWPRI
, "fwra", 0);
358 STAILQ_REMOVE_HEAD(&d
->rq
, link
);
359 FW_GUNLOCK(xfer
->fc
);
361 fp
= &xfer
->recv
.hdr
;
362 #if 0 /* for GASP ?? */
363 if (fc
->irx_post
!= NULL
)
364 fc
->irx_post(fc
, fp
->mode
.ld
);
366 tinfo
= &xfer
->fc
->tcode
[fp
->mode
.hdr
.tcode
];
367 err
= uiomove((void *)fp
, tinfo
->hdr_len
, uio
);
370 err
= uiomove((void *)xfer
->recv
.payload
, xfer
->recv
.pay_len
, uio
);
373 /* recycle this xfer */
374 fwb
= (struct fw_bind
*)xfer
->sc
;
375 fw_xfer_unload(xfer
);
376 xfer
->recv
.pay_len
= PAGE_SIZE
;
378 STAILQ_INSERT_TAIL(&fwb
->xferlist
, xfer
, link
);
379 FW_GUNLOCK(xfer
->fc
);
391 struct firewire_comm
*fc
;
392 int err
= 0, s
, slept
= 0;
397 d
= (struct fw_drv1
*)dev
->si_drv1
;
402 return (fw_read_async(d
, uio
, ioflag
));
409 if (ir
->stproc
== NULL
) {
411 ir
->stproc
= STAILQ_FIRST(&ir
->stvalid
);
412 if (ir
->stproc
!= NULL
) {
414 STAILQ_REMOVE_HEAD(&ir
->stvalid
, link
);
419 if (ir
->stproc
== NULL
) {
420 /* no data avaliable */
423 ir
->flag
|= FWXFERQ_WAKEUP
;
424 err
= fw_msleep(ir
, FW_GMTX(fc
), FWPRI
, "fw_read", hz
);
425 ir
->flag
&= ~FWXFERQ_WAKEUP
;
428 } else if (slept
== 1)
432 } else if(ir
->stproc
!= NULL
) {
435 fp
= (struct fw_pkt
*)fwdma_v_addr(ir
->buf
,
436 ir
->stproc
->poffset
+ ir
->queued
);
437 if(fc
->irx_post
!= NULL
)
438 fc
->irx_post(fc
, fp
->mode
.ld
);
439 if(fp
->mode
.stream
.len
== 0){
443 err
= uiomove((void *)fp
,
444 fp
->mode
.stream
.len
+ sizeof(uint32_t), uio
);
446 if(ir
->queued
>= ir
->bnpacket
){
448 STAILQ_INSERT_TAIL(&ir
->stfree
, ir
->stproc
, link
);
450 fc
->irx_enable(fc
, ir
->dmach
);
453 if (uio
->uio_resid
>= ir
->psize
) {
463 fw_write_async(struct fw_drv1
*d
, struct uio
*uio
, int ioflag
)
465 struct fw_xfer
*xfer
;
467 const struct tcode_info
*tinfo
;
470 memset(&pkt
, 0, sizeof(struct fw_pkt
));
471 if ((err
= uiomove((void *)&pkt
, sizeof(uint32_t), uio
)))
473 tinfo
= &d
->fc
->tcode
[pkt
.mode
.hdr
.tcode
];
474 if ((err
= uiomove((char *)&pkt
+ sizeof(uint32_t),
475 tinfo
->hdr_len
- sizeof(uint32_t), uio
)))
478 if ((xfer
= fw_xfer_alloc_buf(M_FWXFER
, uio
->uio_resid
,
479 PAGE_SIZE
/*XXX*/)) == NULL
)
482 memcpy(&xfer
->send
.hdr
, &pkt
, sizeof(struct fw_pkt
));
483 xfer
->send
.pay_len
= uio
->uio_resid
;
484 if (uio
->uio_resid
> 0) {
485 if ((err
= uiomove((void *)&xfer
->send
.payload
[0],
486 uio
->uio_resid
, uio
)))
492 xfer
->hand
= fw_xferwake
;
493 xfer
->send
.spd
= 2 /* XXX */;
495 if ((err
= fw_asyreq(xfer
->fc
, -1, xfer
)))
498 if ((err
= fw_xferwait(xfer
)))
501 if (xfer
->resp
!= 0) {
506 if (xfer
->flag
== FWXF_RCVD
) {
508 STAILQ_INSERT_TAIL(&d
->rq
, xfer
, link
);
509 FW_GUNLOCK(xfer
->fc
);
525 struct firewire_comm
*fc
;
529 d
= (struct fw_drv1
*)dev
->si_drv1
;
534 return (fw_write_async(d
, uio
, ioflag
));
541 if (it
->stproc
== NULL
) {
542 it
->stproc
= STAILQ_FIRST(&it
->stfree
);
543 if (it
->stproc
!= NULL
) {
545 STAILQ_REMOVE_HEAD(&it
->stfree
, link
);
548 } else if (slept
== 0) {
550 #if 0 /* XXX to avoid lock recursion */
551 err
= fc
->itx_enable(fc
, it
->dmach
);
555 err
= fw_msleep(it
, FW_GMTX(fc
), FWPRI
, "fw_write", hz
);
565 fp
= (struct fw_pkt
*)fwdma_v_addr(it
->buf
,
566 it
->stproc
->poffset
+ it
->queued
);
567 err
= uiomove((void *)fp
, sizeof(struct fw_isohdr
), uio
);
568 err
= uiomove((void *)fp
->mode
.stream
.payload
,
569 fp
->mode
.stream
.len
, uio
);
571 if (it
->queued
>= it
->bnpacket
) {
573 STAILQ_INSERT_TAIL(&it
->stvalid
, it
->stproc
, link
);
576 err
= fc
->itx_enable(fc
, it
->dmach
);
578 if (uio
->uio_resid
>= sizeof(struct fw_isohdr
)) {
591 fw_hand(struct fw_xfer
*xfer
)
596 fwb
= (struct fw_bind
*)xfer
->sc
;
597 d
= (struct fw_drv1
*)fwb
->sc
;
599 STAILQ_INSERT_TAIL(&d
->rq
, xfer
, link
);
600 FW_GUNLOCK(xfer
->fc
);
610 struct firewire_comm
*fc
;
613 struct fw_device
*fwdev
;
615 struct fw_xferq
*ir
, *it
;
616 struct fw_xfer
*xfer
;
618 struct fw_devinfo
*devinfo
;
621 struct fw_devlstreq
*fwdevlst
= (struct fw_devlstreq
*)data
;
622 struct fw_asyreq
*asyreq
= (struct fw_asyreq
*)data
;
623 struct fw_isochreq
*ichreq
= (struct fw_isochreq
*)data
;
624 struct fw_isobufreq
*ibufreq
= (struct fw_isobufreq
*)data
;
625 struct fw_asybindreq
*bindreq
= (struct fw_asybindreq
*)data
;
626 struct fw_crom_buf
*crom_buf
= (struct fw_crom_buf
*)data
;
633 d
= (struct fw_drv1
*)dev
->si_drv1
;
641 i
= fw_open_isodma(fc
, /* tx */1);
647 err
= fwdev_allocbuf(fc
, it
, &d
->bufreq
.tx
);
649 it
->flag
&= ~FWXFERQ_OPEN
;
654 it
->flag
|= (0x3f & ichreq
->ch
);
655 it
->flag
|= ((0x3 & ichreq
->tag
) << 6);
660 ichreq
->ch
= it
->flag
& 0x3f;
661 ichreq
->tag
= it
->flag
>> 2 & 0x3;
667 i
= fw_open_isodma(fc
, /* tx */0);
673 err
= fwdev_allocbuf(fc
, ir
, &d
->bufreq
.rx
);
675 ir
->flag
&= ~FWXFERQ_OPEN
;
680 ir
->flag
|= (0x3f & ichreq
->ch
);
681 ir
->flag
|= ((0x3 & ichreq
->tag
) << 6);
683 err
= fc
->irx_enable(fc
, ir
->dmach
);
687 ichreq
->ch
= ir
->flag
& 0x3f;
688 ichreq
->tag
= ir
->flag
>> 2 & 0x3;
693 memcpy(&d
->bufreq
, ibufreq
, sizeof(d
->bufreq
));
696 memset(&ibufreq
->rx
, 0, sizeof(ibufreq
->rx
));
698 ibufreq
->rx
.nchunk
= ir
->bnchunk
;
699 ibufreq
->rx
.npacket
= ir
->bnpacket
;
700 ibufreq
->rx
.psize
= ir
->psize
;
702 memset(&ibufreq
->tx
, 0, sizeof(ibufreq
->tx
));
704 ibufreq
->tx
.nchunk
= it
->bnchunk
;
705 ibufreq
->tx
.npacket
= it
->bnpacket
;
706 ibufreq
->tx
.psize
= it
->psize
;
711 const struct tcode_info
*tinfo
;
715 tinfo
= &fc
->tcode
[fp
->mode
.hdr
.tcode
];
717 if ((tinfo
->flag
& FWTI_BLOCK_ASY
) != 0)
718 pay_len
= MAX(0, asyreq
->req
.len
- tinfo
->hdr_len
);
720 xfer
= fw_xfer_alloc_buf(M_FWXFER
, pay_len
, PAGE_SIZE
/*XXX*/);
724 switch (asyreq
->req
.type
) {
728 fwdev
= fw_noderesolve_eui64(fc
,
729 &asyreq
->req
.dst
.eui
);
731 fw_printf(fc
->bdev
, "cannot find node\n");
735 fp
->mode
.hdr
.dst
= FWLOCALBUS
| fwdev
->dst
;
738 /* XXX what's this? */
745 memcpy((void *)&xfer
->send
.hdr
, fp
, tinfo
->hdr_len
);
747 bcopy((char *)fp
+ tinfo
->hdr_len
,
748 (void *)xfer
->send
.payload
, pay_len
);
749 xfer
->send
.spd
= asyreq
->req
.sped
;
750 xfer
->hand
= fw_xferwake
;
752 if ((err
= fw_asyreq(fc
, -1, xfer
)) != 0)
754 if ((err
= fw_xferwait(xfer
)) != 0)
756 if (xfer
->resp
!= 0) {
760 if ((tinfo
->flag
& FWTI_TLABEL
) == 0)
764 tinfo
= &fc
->tcode
[xfer
->recv
.hdr
.mode
.hdr
.tcode
];
765 if (xfer
->recv
.hdr
.mode
.hdr
.tcode
== FWTCODE_RRESB
||
766 xfer
->recv
.hdr
.mode
.hdr
.tcode
== FWTCODE_LRES
) {
767 pay_len
= xfer
->recv
.pay_len
;
768 if (asyreq
->req
.len
>= xfer
->recv
.pay_len
+ tinfo
->hdr_len
) {
769 asyreq
->req
.len
= xfer
->recv
.pay_len
+
778 memcpy(fp
, &xfer
->recv
.hdr
, tinfo
->hdr_len
);
779 memcpy((char *)fp
+ tinfo
->hdr_len
, xfer
->recv
.payload
, pay_len
);
781 fw_xfer_free_buf(xfer
);
788 fwb
= fw_bindlookup(fc
,
789 bindreq
->start
.hi
, bindreq
->start
.lo
);
794 fw_bindremove(fc
, fwb
);
795 STAILQ_REMOVE(&d
->binds
, fwb
, fw_bind
, chlist
);
796 fw_xferlist_remove(&fwb
->xferlist
);
800 if(bindreq
->len
<= 0 ){
804 if(bindreq
->start
.hi
> 0xffff ){
808 fwb
= (struct fw_bind
*)malloc(sizeof (struct fw_bind
), M_FW
, M_WAITOK
);
813 fwb
->start
= ((u_int64_t
)bindreq
->start
.hi
<< 32) |
815 fwb
->end
= fwb
->start
+ bindreq
->len
;
817 STAILQ_INIT(&fwb
->xferlist
);
818 err
= fw_bindadd(fc
, fwb
);
820 fw_xferlist_add(&fwb
->xferlist
, M_FWXFER
,
822 PAGE_SIZE
, PAGE_SIZE
, 5,
823 fc
, (void *)fwb
, fw_hand
);
824 STAILQ_INSERT_TAIL(&d
->binds
, fwb
, chlist
);
830 devinfo
= &fwdevlst
->dev
[0];
831 devinfo
->dst
= fc
->nodeid
;
832 devinfo
->status
= 0; /* XXX */
833 devinfo
->eui
.hi
= fc
->eui
.hi
;
834 devinfo
->eui
.lo
= fc
->eui
.lo
;
835 STAILQ_FOREACH(fwdev
, &fc
->devices
, link
) {
836 if(len
< FW_MAX_DEVLST
){
837 devinfo
= &fwdevlst
->dev
[len
++];
838 devinfo
->dst
= fwdev
->dst
;
840 (fwdev
->status
== FWDEVINVAL
)?0:1;
841 devinfo
->eui
.hi
= fwdev
->eui
.hi
;
842 devinfo
->eui
.lo
= fwdev
->eui
.lo
;
847 fwdevlst
->info_len
= len
;
850 memcpy(data
, fc
->topology_map
,
851 (fc
->topology_map
->crc_len
+ 1) * 4);
854 STAILQ_FOREACH(fwdev
, &fc
->devices
, link
)
855 if (FW_EUI64_EQUAL(fwdev
->eui
, crom_buf
->eui
))
858 if (!FW_EUI64_EQUAL(fc
->eui
, crom_buf
->eui
)) {
863 ptr
= malloc(CROMSIZE
, M_FW
, M_WAITOK
);
865 for (i
= 0; i
< CROMSIZE
/4; i
++)
867 = ntohl(fc
->config_rom
[i
]);
870 ptr
= (void *)&fwdev
->csrrom
[0];
871 if (fwdev
->rommax
< CSRROMOFF
)
874 len
= fwdev
->rommax
- CSRROMOFF
+ 4;
876 if (crom_buf
->len
< len
)
880 err
= copyout(ptr
, crom_buf
->ptr
, len
);
886 FWDEV_IOCTL_REDIRECT
;
901 ir
= ((struct fw_drv1
*)dev
->si_drv1
)->ir
;
903 tmp
= POLLIN
| POLLRDNORM
;
905 if (STAILQ_FIRST(&ir
->q
) != NULL
)
908 selrecord(td
, &ir
->rsel
);
910 tmp
= POLLOUT
| POLLWRNORM
;
912 /* XXX should be fixed */
929 fw_strategy(struct bio
*bp
)
933 FWDEV_STRATEGY_START
;
935 bp
->bio_error
= EOPNOTSUPP
;
936 bp
->bio_resid
= bp
->bio_bcount
;
940 #if defined(__FreeBSD__)
942 fwdev_makedev(struct firewire_softc
*sc
)
946 #if defined(__DragonFly__)
949 unit
= fw_get_unit(sc
->fc
->bdev
);
950 cdevsw_add(&firewire_cdevsw
, FW_UNITMASK
, FW_UNIT(unit
));
951 #elif __FreeBSD_version < 500000
952 cdevsw_add(&firewire_cdevsw
);
957 unit
= fw_get_unit(sc
->fc
->bdev
);
958 sc
->dev
= make_dev(&firewire_cdevsw
, MAKEMINOR(0, unit
, 0),
959 UID_ROOT
, GID_OPERATOR
, 0660,
961 d
= make_dev(&firewire_cdevsw
,
962 MAKEMINOR(FWMEM_FLAG
, unit
, 0),
963 UID_ROOT
, GID_OPERATOR
, 0660,
964 "fwmem%d.%d", unit
, 0);
965 dev_depends(sc
->dev
, d
);
966 make_dev_alias(sc
->dev
, "fw%d", unit
);
967 make_dev_alias(d
, "fwmem%d", unit
);
974 fwdev_destroydev(struct firewire_softc
*sc
)
978 #if defined(__DragonFly__)
981 unit
= fw_get_unit(sc
->fc
->bdev
);
982 cdevsw_remove(&firewire_cdevsw
, FW_UNITMASK
, FW_UNIT(unit
));
983 #elif __FreeBSD_version < 500000
984 cdevsw_remove(&firewire_cdevsw
);
986 destroy_dev(sc
->dev
);
991 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
994 fwdev_clone(void *arg
, struct ucred
*cred
, char *name
, int namelen
,
997 struct firewire_softc
*sc
;
998 char *devnames
[NDEVTYPE
] = {"fw", "fwmem"};
1000 int devflag
[NDEVTYPE
] = {0, FWMEM_FLAG
};
1001 int i
, unit
= 0, sub
= 0;
1006 for (i
= 0; i
< NDEVTYPE
; i
++)
1007 if (dev_stdclone(name
, &subp
, devnames
[i
], &unit
) == 2)
1013 if (subp
== NULL
|| *subp
++ != '.')
1017 while (isdigit(*subp
)) {
1019 sub
+= *subp
++ - '0';
1024 sc
= devclass_get_softc(firewire_devclass
, unit
);
1027 *dev
= make_dev(&firewire_cdevsw
, MAKEMINOR(devflag
[i
], unit
, sub
),
1028 UID_ROOT
, GID_OPERATOR
, 0660,
1029 "%s%d.%d", devnames
[i
], unit
, sub
);
1031 (*dev
)->si_flags
|= SI_CHEAPCLONE
;
1032 dev_depends(sc
->dev
, *dev
);