1 /* $NetBSD: fwiso.c,v 1.3 2003/07/14 15:47:13 lukem Exp $ */
2
3 /*-
4 * Copyright (c) 2001 and 2002
5 * HAYAKAWA Koichi. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: fwiso.c,v 1.3 2003/07/14 15:47:13 lukem Exp $");
33
34 #include "fwiso.h"
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/conf.h>
40 #include <sys/ioctl.h>
41 #include <sys/fcntl.h>
42 #include <sys/uio.h>
43 #include <sys/device.h>
44 #include <sys/errno.h>
45 #include <sys/signalvar.h>
46 #include <sys/vnode.h>
47 #include <sys/mbuf.h>
48 #include <sys/poll.h>
49 #include <sys/select.h>
50
51 #include <dev/ieee1394/fwiso_ioctl.h>
52 #include <dev/ieee1394/ieee1394reg.h>
53 #include <dev/ieee1394/ieee1394var.h>
54 #include <dev/ieee1394/fwisovar.h>
55
56 #ifdef DEBUG
57 #define DPRINTF(x) printf x
58 #else
59 #define DPRINTF(x)
60 #endif
61
62 #define UNIT(dev) minor(dev)&0xff
63 #define IOCTL(dev) minor(dev)&0x0100
64 #define DVDEV(dev) minor(dev)&0x0200
65 #define MPEG2DEV(dev) minor(dev)&0x0300
66
67 /*
68 * device number rule
69 *
70 * Lower 8-bit of minor number represents fwiso pseudo device.
71 * Higher bits represents types of the device.
72 *
73 * 0x0000: raw fwiso device
74 * 0x0100: for ioctl (can't read/write)
75 * 0x0200: standard DV type
76 * 0x0300: MPEG2 TS
77 */
78
79
80 /*
81 * The movement of data.
82 *
83 * Isochronous data acquired by device is copied in reservoir
84 * buffer by fwisohandler. fwisohandler is a callback function,
85 * called in the device drover of an IEEE 1394 host device. The
86 * copied data in reservoir is deriverd to userland by fwisoread.
87 * So, at least data copy will happen twice.
88 */
89
90
91 struct fwiso_pktdata {
92 u_int8_t *pkt_base; /* Base address: NEVER change */
93 size_t pkt_len; /* Length of the data in the buffer */
94 size_t pkt_buflen; /* Length of the buffer: NEVER change */
95 };
96
97 struct fwiso_pkts {
98 struct fwiso_pktdata *fp_iov; /* packet data vector: NEVER change */
99 struct fwiso_pktdata *fp_iov_last; /* end packet data vector: NEVER change */
100 /*
101 * Set members below volatile because they will be changed by
102 * both intr handler and read routine.
103 */
104 volatile struct fwiso_pktdata *fp_iov_start; /* pkt data vector */
105 struct fwiso_pktdata *fp_iov_end; /* pkt data vector */
106 volatile int fp_iovcnt; /* vector length */
107 };
108
109 #define FWISO_DEVNAMESIZ 12
110 struct fwiso_data {
111 char fd_devname[FWISO_DEVNAMESIZ];
112 struct ieee1394_softc *fd_dev;
113
114 int fd_status; /* status: share with interrupt hendler */
115 int fd_overflow;
116
117 struct uio *fd_uio; /* for interrupt handler */
118
119 struct fwiso_pkts fd_rsv_pkts; /* temporary buffer for packets */
120 u_int8_t *fd_rsv_buf;
121 int fd_rsv_size;
122
123 /*
124 * Should those data (fd_mode, fd_channel, fd_tag) be dedicatd
125 * for read and write, or be shared with read and write?
126 */
127 int fd_mode;
128 int fd_channel; /* ISO channel (0 - 63) */
129 int fd_tag; /* IEEE1394_ISO_TAG0, _TAG1, _TAG2 */
130 int fd_threshold;
131
132 u_int32_t fd_cycletimer;
133
134 ieee1394_ir_tag_t fd_irtag; /* tag for isochronous reception */
135
136 ieee1394_it_tag_t fd_ittag; /* tag for isochronous transmission */
137 struct ieee1394_it_datalist *fd_itlist;
138 int fd_it_serial; /* serial number of data block (not packet) */
139 int fd_it_frame; /* frame number */
140 int fd_it_dv_insert_empty;
141 int fd_it_dv_insert_fraction;
142 int fd_it_dv_insert_fractional;
143
144 int fd_flags;
145 #define FWISO_OPEN 0x01
146 #define FWISO_SETHANDLER 0x02
147 #define FWISO_IR_SLEEPING 0x04
148 #define FWISO_WRITE 0x08
149 #define FWISO_NONBLOCK 0x10
150
151 size_t fd_uioprev; /* previous uio value: XXX really needed? */
152 };
153
154
155 struct fwiso_data fwiso_data_str[NFWISO];
156
157 static int fwiso_min_space[FWISO_MODE_MAX] = {1, 480, 488, 1};
158 static int fwiso_head_offset[FWISO_MODE_MAX] = {0, 8, 0, 0};
159 #define FWISO_MAX_INTERFACE 10
160 /* I hope all the elements of fwiso_interface is initialised as NULL */
161 static struct ieee1394_softc *fwiso_interface[FWISO_MAX_INTERFACE] = {NULL};
162
163 static struct evcnt fwiso_drop_ev = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "fwiso", "dropframe");
164 static struct evcnt fwiso_frame_ev = EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "fwiso", "frame");
165
166 void fwisoattach(int);
167
168 static struct ieee1394_softc *fwiso_lookup_if(const char *);
169 int fwisowrite_dv(struct fwiso_data *, struct uio *, int);
170 static int fwiso_set_handler(struct fwiso_data *);
171
172 dev_type_open(fwisoopen);
173 dev_type_close(fwisoclose);
174 dev_type_read(fwisoread);
175 dev_type_write(fwisowrite);
176 dev_type_ioctl(fwisoioctl);
177 dev_type_poll(fwisopoll);
178
179 const struct cdevsw fwiso_cdevsw = {
180 fwisoopen, fwisoclose, fwisoread, fwisowrite, fwisoioctl,
181 nostop, notty, fwisopoll, nommap,
182 };
183
184
185 /* XXX: only for experimental */
186 extern int fwohci_set_isotx(struct ieee1394_softc *);
187 struct fwohci_it_ctx;
188 extern int fwohci_it_ctx_clear(ieee1394_it_tag_t);
189 extern u_int16_t fwohci_it_cycletimer(ieee1394_it_tag_t);
190 extern ieee1394_it_tag_t fwohci_it_set(struct ieee1394_softc *, int, int);
191 extern int fwohci_it_ctx_writedata(ieee1394_it_tag_t, int,
192 struct ieee1394_it_datalist *, int);
193
194
195
196 /* ARGSUSED */
197 void
198 fwisoattach(int n)
199 {
200 int i;
201
202 memset(fwiso_data_str, 0, sizeof(fwiso_data_str));
203
204 for (i = 0; i < NFWISO; ++i) {
205 snprintf(fwiso_data_str[i].fd_devname, 10, "fwiso%d", i);
206 fwiso_data_str[i].fd_channel = -1;
207 fwiso_data_str[i].fd_mode = -1;
208 fwiso_data_str[i].fd_threshold = 0;
209 fwiso_data_str[i].fd_tag = 0;
210 fwiso_data_str[i].fd_uioprev = 0;
211 }
212
213 evcnt_attach_static(&fwiso_drop_ev);
214 evcnt_attach_static(&fwiso_frame_ev);
215 }
216
217
218
219
220 /*
221 * int fwisoread(dev_t dev, struct uio *uio, int ioflag)
222 *
223 * Read routine
224 *
225 * Algorithm:
226 *
227 * if interrupt handler is not set
228 * register interrupt handler
229 * prepare reserve buffer;
230 * if some data exists in reserve buffer
231 * copy data in uio
232 * if uio is full
233 * return
234 * set uio in interrupt handler
235 * sleep until interrupt handler wait me
236 * set reserve buffer
237 * return
238 */
239 int
240 fwisoread(dev_t dev, struct uio *uio, int ioflag)
241 {
242 struct fwiso_data *fd;
243 int unit;
244 int status = 0;
245 int s;
246
247 int minspace;
248 int headoffs;
249 volatile struct fwiso_pktdata *pkt;
250 struct fwiso_pktdata *pkt_last;
251 struct ieee1394_softc *isc;
252 size_t resid;
253
254 int i;
255
256 unit = UNIT(dev);
257
258 if (unit >= NFWISO) {
259 return ENXIO;
260 }
261
262 if (IOCTL(dev)) {
263 DPRINTF(("fwiso%d cannot read\n", unit));
264 return ENXIO;
265 }
266
267 fd = &fwiso_data_str[unit];
268
269 if ((fd->fd_flags & FWISO_OPEN) == 0) {
270 return EBUSY;
271 }
272
273 isc = fd->fd_dev;
274
275 if ((fd->fd_flags & FWISO_SETHANDLER) == 0) {
276 int rv;
277
278 if ((rv = fwiso_set_handler(fd)) != 0) {
279 return rv;
280 }
281 }
282
283 minspace = fwiso_min_space[fd->fd_mode];
284 headoffs = fwiso_head_offset[fd->fd_mode];
285
286 /* This is constant */
287 pkt_last = fd->fd_rsv_pkts.fp_iov_last;
288 /* Only fwiso writes. Others read only */
289 pkt = fd->fd_rsv_pkts.fp_iov_start;
290
291 s = splbio();
292
293 i = 0;
294 resid = uio->uio_resid;
295 DPRINTF(("%s: now reading\n", isc->sc1394_dev.dv_xname));
296 while ((status = (*isc->sc1394_ir_read)((struct device *)isc,
297 fd->fd_irtag, uio, headoffs, 0)) == EAGAIN
298 || (status == 0 && uio->uio_resid == resid)) {
299 if (fd->fd_flags & FWISO_NONBLOCK) {
300 break;
301 }
302 if (isc->sc1394_ir_wait == NULL) {
303 if (++i > 20) {
304 status = EIO;
305 break;
306 }
307 delay(100);
308 } else {
309 status = (*isc->sc1394_ir_wait)((struct device *)isc,
310 fd->fd_irtag, (void *)fd, fd->fd_devname);
311 if (status != 0) {
312 break;
313 }
314 }
315 }
316
317 splx(s);
318
319 return status;
320 }
321
322
323
324
325
326 /*
327 * int fwisowrite(dev_t dev, struct uio *uio, int ioflag)
328 *
329 * Write routine
330 */
331 int
332 fwisowrite(dev_t dev, struct uio *uio, int ioflag)
333 {
334 struct fwiso_data *fd;
335 int unit;
336 int rv = ENODEV;
337
338 unit = UNIT(dev);
339
340 if (unit >= NFWISO) {
341 return ENXIO;
342 }
343
344 if (IOCTL(dev)) {
345 DPRINTF(("fwiso%d cannot read\n", unit));
346 return ENXIO;
347 }
348
349 fd = &fwiso_data_str[unit];
350
351 if ((fd->fd_flags & FWISO_OPEN) == 0) {
352 return EBUSY;
353 }
354
355 if (fd->fd_ittag == NULL) {
356 /* XXX */
357 if (fd->fd_channel < 0) {
358 fd->fd_channel = 63;
359 }
360 if (fd->fd_tag <= 0) {
361 fd->fd_tag = IEEE1394_ISO_TAG1;
362 }
363 fd->fd_ittag = fwohci_it_set(fd->fd_dev, fd->fd_channel,
364 fd->fd_tag);
365 if (fd->fd_ittag == NULL) {
366 return EBUSY;
367 }
368 fd->fd_flags |= FWISO_WRITE;
369 printf("fwiso%d: it_set returns %p\n", unit, fd->fd_ittag);
370
371 fd->fd_it_dv_insert_fractional = 16000;
372 fd->fd_it_dv_insert_fraction = 1015;
373 fd->fd_it_dv_insert_empty = 0;
374
375 #define ITLISTSIZE sizeof(struct ieee1394_it_datalist)*100
376 if ((fd->fd_itlist = malloc(ITLISTSIZE, M_DEVBUF,
377 M_WAITOK|M_ZERO)) == NULL) {
378 /* */
379 printf("fwiso%d: cannot get memory for it_list\n",
380 unit);
381 return EBUSY;
382 }
383
384 /* XXX */
385 fd->fd_cycletimer = fwohci_it_cycletimer(fd->fd_ittag);
386 printf("cycletimer %x %d %d\n", fd->fd_cycletimer,
387 fd->fd_cycletimer >> 13, fd->fd_cycletimer&0x1fff);
388 }
389 #if 1
390 switch(fd->fd_mode) {
391 case FWISO_MODE_DV:
392 rv = fwisowrite_dv(fd, uio, 480);
393 break;
394 case FWISO_MODE_DV_RAW:
395 break;
396 case FWISO_MODE_RAW:
397 break;
398 }
399
400 #endif
401
402 return rv;
403 }
404
405
406
407
408 int
409 fwisowrite_dv(struct fwiso_data *fd, struct uio *uio, int size)
410 {
411 int rv;
412 struct ieee1394_it_datalist *itlist;
413 struct ieee1394_it_datalist *loopend;
414 struct iovec *iov = uio->uio_iov;
415 int nodeid;
416 const struct iovec *iov_end = iov + uio->uio_iovcnt;
417 int iov_offs; /* offset in iov */
418 int ndata;
419 int writesize = 0;
420 int res = 0;
421 int serialno;
422 int i;
423 int s;
424
425 DPRINTF(("fwisowrite_dv(%p %p %d), resid %d iovcnt %d\n",
426 fd, uio, size, uio->uio_resid, uio->uio_iovcnt));
427
428 iov_offs = 0;
429 itlist = fd->fd_itlist;
430
431 if (uio->uio_resid < size) {
432 /* Only get rid of small data */
433 uio->uio_offset += uio->uio_resid;
434 uio->uio_resid = 0;
435 return res;
436 }
437
438 nodeid = 0;
439
440 s = splbio();
441
442 while (uio->uio_resid >= size) {
443 if (uio->uio_resid > 90*size) {
444 loopend = fd->fd_itlist + 90;
445 DPRINTF(("loop 90\n"));
446 } else {
447 loopend = fd->fd_itlist + uio->uio_resid/size;
448 DPRINTF(("loop %d %p\n", uio->uio_resid/size, loopend));
449 }
450
451 serialno = fd->fd_it_serial;
452
453 /* make data list */
454 for (itlist = fd->fd_itlist; itlist < loopend; ++itlist) {
455 int psize = size;
456
457 /* first data is CIP header */
458 itlist->it_cmd[0] = IEEE1394_IT_CMD_IMMED | 8;
459 itlist->it_u[0].id_data[0]
460 = IEEE1394_CIP_SET(SID, nodeid)
461 | IEEE1394_CIP_SET(DBS, size)
462 | IEEE1394_CIP_SET(DBC, serialno);
463 ++serialno;
464
465 itlist->it_u[0].id_data[1]
466 = IEEE1394_CIP_FMT_DV
467 | IEEE1394_CIP_SET(FDF_SYT, 0xffff);
468
469 for (i = 1; i < IEEE1394_IT_CMD_NUM; ++i) {
470
471 if (psize == 0) {
472 itlist->it_cmd[i]
473 = IEEE1394_IT_CMD_NOP;
474 continue;
475 }
476
477 itlist->it_u[i].id_addr
478 = (u_int8_t *)iov->iov_base + iov_offs;
479
480 if (iov->iov_len - iov_offs >= psize) {
481 itlist->it_cmd[i]
482 = IEEE1394_IT_CMD_PTR | psize;
483 iov_offs += psize;
484 psize = 0;
485 } else {
486 itlist->it_cmd[i]
487 = IEEE1394_IT_CMD_PTR | (iov->iov_len - iov_offs);
488 psize -= iov->iov_len - iov_offs;
489 iov_offs = 0;
490 if (++iov == iov_end) {
491 printf("ERROR iov %d\n",
492 iov - uio->uio_iov);
493 res = EFAULT;
494 goto error_1;
495 }
496 }
497 }
498 }
499 ndata = itlist - fd->fd_itlist;
500 DPRINTF(("calling fwohci_it_ctx_writedata(%p %d %p 0)\n",
501 fd->fd_ittag, ndata, fd->fd_itlist));
502 rv = fwohci_it_ctx_writedata(fd->fd_ittag, ndata,
503 fd->fd_itlist, 0);
504
505 writesize = rv * size;
506 /* XXX: decrement for empty packet */
507
508 uio->uio_resid -= writesize;
509 uio->uio_offset += writesize;
510 fd->fd_it_serial += rv;
511 itlist += rv;
512
513 if (rv == 0) {
514 if (fd->fd_uioprev == uio->uio_resid) {
515 #if 0
516 printf("umm, I cannot write any more (%d)\n",
517 fd->fd_it_serial);
518 res = EFAULT;
519 goto error_1;
520 #endif
521 }
522 }
523 fd->fd_uioprev = uio->uio_resid;
524
525 if (rv < ndata) {
526 /* reach at the end of DMA buffer */
527 break;
528 }
529 }
530
531 error_1:
532
533 splx(s);
534
535 return res;
536 }
537
538
539
540 int
541 fwisoopen(dev_t dev, int flags, int fmt, struct proc *p)
542 {
543 struct fwiso_data *fd;
544 int unit = UNIT(dev);
545
546 if (unit >= NFWISO) {
547 return ENXIO;
548 }
549
550 if (IOCTL(dev)) {
551 return 0;
552 }
553
554 fd = &fwiso_data_str[unit];
555
556 if (fd->fd_flags &= FWISO_OPEN) {
557 return EBUSY;
558 }
559
560 fd->fd_flags = FWISO_OPEN;
561 if (flags & O_NONBLOCK) {
562 fd->fd_flags |= FWISO_NONBLOCK;
563 }
564
565 fd->fd_rsv_size = 0;
566 fd->fd_uio = NULL;
567 fd->fd_mode = FWISO_MODE_RAW;
568
569 if (DVDEV(dev)) {
570 fd->fd_mode = FWISO_MODE_DV;
571 fd->fd_channel = 63;
572 fd->fd_tag = IEEE1394_ISO_TAG1;
573 }
574
575 if (fd->fd_dev == NULL) {
576 int i;
577
578 for (i = 0; i < FWISO_MAX_INTERFACE; ++i) {
579 if (fwiso_interface[i] != NULL) {
580 fd->fd_dev = fwiso_interface[i];
581 printf("%s: using %s\n", fd->fd_devname,
582 fwiso_interface[i]->sc1394_dev.dv_xname);
583 break;
584 }
585 }
586 }
587
588 fd->fd_overflow = 0;
589
590 return 0;
591 }
592
593
594
595
596
597 int
598 fwisoclose(dev_t dev, int flags, int fmt, struct proc *p)
599 {
600 struct fwiso_data *fd;
601 int unit = UNIT(dev);
602
603 if (unit >= NFWISO) {
604 return ENXIO;
605 }
606
607 fd = &fwiso_data_str[unit];
608
609 fd->fd_flags &= ~FWISO_OPEN;
610
611 /* remove interrupt handler */
612 if (fd->fd_flags & FWISO_SETHANDLER) {
613 int s = splbio();
614 /* remove handler */
615 (*fd->fd_dev->sc1394_ir_close)((struct device *)fd->fd_dev,
616 fd->fd_irtag);
617
618 fd->fd_flags &= ~FWISO_SETHANDLER;
619 splx(s);
620 }
621
622 /* When this is opened for write, cleanup it_tag */
623 if (fd->fd_flags & FWISO_WRITE) {
624 fwohci_it_ctx_clear(fd->fd_ittag);
625 fd->fd_ittag = NULL;
626 }
627
628 if (fd->fd_overflow > 0) {
629 printf("%s: %d frame dropped\n", fd->fd_devname, fd->fd_overflow);
630 }
631
632 fd->fd_flags = 0;
633 fd->fd_overflow = 0;
634 /* keep mode and interface */
635
636 return 0;
637 }
638
639
640
641 int
642 fwisoioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct proc *p)
643 {
644 int unit = UNIT(dev);
645 struct fwiso_data *fd;
646 int error = 0;
647
648 if (unit >= NFWISO) {
649 return ENXIO;
650 }
651
652 fd = &fwiso_data_str[unit];
653
654 if (!data) {
655 return EINVAL;
656 }
657
658 switch(cmd) {
659
660 case FWISOSETIF:
661 {
662 const struct fwiso_if *fi = (struct fwiso_if *)data;
663
664 if ((fd->fd_dev = fwiso_lookup_if(fi->fi_name)) == NULL) {
665 error = EINVAL;
666 }
667 break;
668 }
669 case FWISOGETIF:
670 {
671 struct fwiso_if *fi = (struct fwiso_if *)data;
672
673 if (fd->fd_dev != NULL) {
674 memcpy(fi->fi_name, fd->fd_dev->sc1394_dev.dv_xname,
675 FWISO_IFNAMESIZ);
676 } else {
677 memcpy(fi->fi_name, "---", 3);
678 }
679 break;
680 }
681 case FWISOSETMODE:
682 {
683 const int mode = *(int *)data;
684
685 if (mode >= 0 && mode < FWISO_MODE_MAX) {
686 fd->fd_mode = mode;
687 } else {
688 error = EINVAL;
689 }
690 break;
691 }
692 case FWISOGETMODE:
693 *((int *)data) = fd->fd_mode;
694 break;
695 case FWISOSETCHANNEL:
696 {
697 const int channel = *(int *)data;
698
699 if (channel >= 0 && channel < 64) {
700 fd->fd_channel = channel;
701 } else if (channel == FWISO_CHANNEL_ANY) {
702 fd->fd_channel = IEEE1394_ISO_CHANNEL_ANY;
703 } else {
704 error = EINVAL;
705 }
706 break;
707 }
708 case FWISOGETCHANNEL:
709 *((int *)data) = fd->fd_channel;
710 break;
711 case FWISOSETTAG:
712 {
713 const int tag = *(int *)data;
714
715 #define FWISO_TAG_MAX (FWISO_TAG0 | FWISO_TAG1 | FWISO_TAG2 | FWISO_TAG3)
716
717 if (tag >= FWISO_TAG0 || tag <= FWISO_TAG_MAX) {
718 /* valid tag */
719 fd->fd_tag = tag;
720 } else {
721 error = EINVAL;
722 }
723 }
724 case FWISOGETTAG:
725 *((int *)data) = fd->fd_tag;
726 break;
727 default:
728 error = EINVAL;
729 break;
730 }
731
732 return error;
733 }
734
735
736
737
738 int
739 fwisopoll(dev_t dev, int events, struct proc *p)
740 {
741 int unit = UNIT(dev);
742 struct fwiso_data *fd;
743 int s;
744 int revents;
745 int (*ir_select)(struct device *, ieee1394_ir_tag_t, struct proc *);
746
747 if (unit >= NFWISO) {
748 return ENXIO;
749 }
750
751 fd = &fwiso_data_str[unit];
752
753 if ((ir_select = fd->fd_dev->sc1394_ir_select) == NULL) {
754 return events;
755 }
756
757 s = splbio();
758 /*
759 * right now, only select for read is supported.
760 */
761 revents = events & (POLLOUT | POLLWRNORM);
762
763 if (events & (POLLIN | POLLRDNORM)) {
764 if ((fd->fd_flags & FWISO_SETHANDLER) == 0) {
765 int errcode;
766
767 if ((errcode = fwiso_set_handler(fd)) != 0) {
768 splx(s);
769 return errcode;
770 }
771 }
772
773 if ((*ir_select)((struct device *)fd->fd_dev,
774 fd->fd_irtag, p) > 0) {
775 revents |= events & (POLLIN | POLLRDNORM);
776 }
777 #if 0
778 if (fd->fd_rsv_pkts.fp_iovcnt > 0) {
779 revents |= events & (POLLIN | POLLRDNORM);
780 } else {
781 selrecord(p, &fd->fd_sel);
782 }
783 #endif
784 }
785
786 splx(s);
787 return revents;
788 }
789
790
791
792 int
793 fwiso_register_if(struct ieee1394_softc *interface)
794 {
795 int i;
796
797 for (i = 0; i < FWISO_MAX_INTERFACE; ++i) {
798 if (fwiso_interface[i] == NULL) {
799 fwiso_interface[i] = interface;
800 break;
801 }
802 }
803
804 if (i == FWISO_MAX_INTERFACE) {
805 printf("fwiso: too many interfaces %s\n",
806 interface->sc1394_dev.dv_xname);
807 return 1;
808 }
809
810 return 0;
811 }
812
813
814
815
816 static struct ieee1394_softc *
817 fwiso_lookup_if(const char *ifname)
818 {
819 int i;
820
821 for (i = 0; i < FWISO_MAX_INTERFACE; ++i) {
822 if (!strncmp(fwiso_interface[i]->sc1394_dev.dv_xname,
823 ifname, FWISO_IFNAMESIZ)) {
824 return fwiso_interface[i];
825 }
826 }
827
828 return NULL;
829 }
830
831
832
833
834 /*
835 * static int fwiso_set_handler(struct fwiso_data *fd)
836 *
837 * This function set interrupt handler for isochronous data read.
838 */
839 static int
840 fwiso_set_handler(struct fwiso_data *fd)
841 {
842 int bufsize;
843 int s;
844 struct ieee1394_softc *isc = fd->fd_dev;
845 int flags = 0;
846
847 if (isc == NULL || isc->sc1394_ir_open == NULL) {
848 return ENXIO;
849 }
850 switch (fd->fd_mode) {
851 case FWISO_MODE_DV:
852 if (fd->fd_threshold == 0) {
853 fd->fd_threshold = 30;
854 }
855 fd->fd_rsv_size = 1024; /* buffer for 256 ms DV data */
856 bufsize = 488;
857 flags |= IEEE1394_IR_TRIGGER_CIP_SYNC;
858 break;
859 case FWISO_MODE_DV_RAW:
860 fd->fd_rsv_size = 128; /* buffer for 16 ms DV data */
861 bufsize = 488;
862 flags |= IEEE1394_IR_SHORTDELAY;
863 break;
864 case FWISO_MODE_RAW:
865 fd->fd_rsv_size = 64;
866 bufsize = 4000;
867 flags |= IEEE1394_IR_NEEDHEADER | IEEE1394_IR_SHORTDELAY;
868 break;
869 case FWISO_MODE_MPEG2TS:
870 fd->fd_rsv_size = 64;
871 bufsize = 512;
872 break;
873 }
874
875 s = splbio();
876
877 /* set interrupt handler */
878 fd->fd_irtag = (*isc->sc1394_ir_open)((struct device *)isc,
879 fd->fd_channel, fd->fd_tag, fd->fd_rsv_size, bufsize, flags);
880 if (fd->fd_irtag == NULL) {
881 splx(s);
882 return ENXIO;
883 }
884 fd->fd_flags |= FWISO_SETHANDLER;
885
886 splx(s);
887
888 return 0;
889 }
Cache object: 1bb4d4b5191b4d98f26f3142bd8df5be
|