Add a driver for Omnikey CardMan 4040 smartcard reader - cmx(4).
[dragonfly.git] / sys / dev / misc / cmx / cmx.c
CommitLineData
c4bf625e
HT
1/*-
2 * Copyright (c) 2006-2007 Daniel Roethlisberger <daniel@roe.ch>
3 * Copyright (c) 2000-2004 OMNIKEY GmbH (www.omnikey.com)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
11 * 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 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 *
28 * $FreeBSD: src/sys/dev/cmx/cmx.c,v 1.1 2008/03/06 08:09:45 rink Exp $
29 * $DragonFly: src/sys/dev/misc/cmx/cmx.c,v 1.1 2008/04/23 08:57:10 hasso Exp $
30 */
31
32/*
33 * OMNIKEY CardMan 4040 a.k.a. CardMan eXtended (cmx) driver.
34 * This is a PCMCIA based smartcard reader which seems to work
35 * like an I/O port mapped USB CCID smartcard device.
36 *
37 * I/O originally based on Linux driver version 1.1.0 by OMNIKEY.
38 * Dual GPL/BSD. Almost all of the code has been rewritten.
39 * $Omnikey: cm4040_cs.c,v 1.7 2004/10/04 09:08:50 jp Exp $
40 */
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/kernel.h>
45#include <sys/sockio.h>
46#include <sys/mbuf.h>
47#include <sys/poll.h>
48#include <sys/conf.h>
49#include <sys/fcntl.h>
50#include <sys/uio.h>
51#include <sys/selinfo.h>
52#include <sys/types.h>
53#include <sys/lock.h>
54#include <sys/device.h>
55#include <sys/thread2.h>
56
57#include <sys/module.h>
58#include <sys/bus.h>
59#include <sys/resource.h>
60#include <sys/rman.h>
61
62#include "cmxvar.h"
63#include "cmxreg.h"
64
65#ifdef CMX_DEBUG
66#define DEBUG_printf(dev, fmt, args...) \
67 device_printf(dev, "%s: " fmt, __FUNCTION__, ##args)
68#else
69#define DEBUG_printf(dev, fmt, args...)
70#endif
71
72#define SPIN_COUNT 1000
73#define WAIT_TICKS (hz/100)
74#define POLL_TICKS (hz/10)
75
76/* possibly bogus */
77#define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*hz)
78#define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*hz)
79#define CCID_DRIVER_MINIMUM_TIMEOUT (3*hz)
80
81#ifdef CMX_DEBUG
82static char BSRBITS[] = "\020"
83 "\01BULK_OUT_FULL" /* 0x01 */
84 "\02BULK_IN_FULL" /* 0x02 */
85 "\03(0x04)"; /* 0x04 */
86#ifdef CMX_INTR
87static char SCRBITS[] = "\020"
88 "\01POWER_DOWN" /* 0x01 */
89 "\02PULSE_INTERRUPT" /* 0x02 */
90 "\03HOST_TO_READER_DONE" /* 0x04 */
91 "\04READER_TO_HOST_DONE" /* 0x08 */
92 "\05ACK_NOTIFY" /* 0x10 */
93 "\06EN_NOTIFY" /* 0x20 */
94 "\07ABORT" /* 0x40 */
95 "\10HOST_TO_READER_START"; /* 0x80 */
96#endif /* CMX_INTR */
97static char POLLBITS[] = "\020"
98 "\01POLLIN" /* 0x0001 */
99 "\02POLLPRI" /* 0x0002 */
100 "\03POLLOUT" /* 0x0004 */
101 "\04POLLERR" /* 0x0008 */
102 "\05POLLHUP" /* 0x0010 */
103 "\06POLLINVAL" /* 0x0020 */
104 "\07POLLRDNORM" /* 0x0040 */
105 "\10POLLRDBAND" /* 0x0080 */
106 "\11POLLWRBAND"; /* 0x0100 */
107static char MODEBITS[] = "\020"
108 "\01READ" /* 0x0001 */
109 "\02WRITE" /* 0x0002 */
110 "\03NONBLOCK" /* 0x0004 */
111 "\04APPEND" /* 0x0008 */
112 "\05SHLOCK" /* 0x0010 */
113 "\06EXLOCK" /* 0x0020 */
114 "\07ASYNC" /* 0x0040 */
115 "\10FSYNC" /* 0x0080 */
116 "\11NOFOLLOW" /* 0x0100 */
117 "\12CREAT" /* 0x0200 */
118 "\13TRUNK" /* 0x0400 */
119 "\14EXCL" /* 0x0800 */
120 "\15(0x1000)" /* 0x1000 */
121 "\16(0x2000)" /* 0x2000 */
122 "\17HASLOCK" /* 0x4000 */
123 "\20NOCTTY" /* 0x8000 */
124 "\21DIRECT"; /* 0x00010000 */
125#endif /* CMX_DEBUG */
126
127devclass_t cmx_devclass;
128
129static d_open_t cmx_open;
130static d_close_t cmx_close;
131static d_read_t cmx_read;
132static d_write_t cmx_write;
133static d_poll_t cmx_poll;
134#ifdef CMX_INTR
135static void cmx_intr(void *arg);
136#endif
137
138#define CDEV_MAJOR 185
139static struct dev_ops cmx_ops = {
140 { "cmx", CDEV_MAJOR, 0 },
141 .d_open = cmx_open,
142 .d_close = cmx_close,
143 .d_read = cmx_read,
144 .d_write = cmx_write,
145 .d_poll = cmx_poll,
146};
147
148/*
149 * Initialize the softc structure. Must be called from
150 * the bus specific device allocation routine.
151 */
152void
153cmx_init_softc(device_t dev)
154{
155 struct cmx_softc *sc = device_get_softc(dev);
156 sc->dev = dev;
157 sc->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
158}
159
160/*
161 * Allocate driver resources. Must be called from the
162 * bus specific device allocation routine. Caller must
163 * ensure to call cmx_release_resources to free the
164 * resources when detaching.
165 * Return zero if successful, and ENOMEM if the resources
166 * could not be allocated.
167 */
168int
169cmx_alloc_resources(device_t dev)
170{
171 struct cmx_softc *sc = device_get_softc(dev);
172#ifdef CMX_INTR
173 int rv;
174#endif
175
176 sc->ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
177 &sc->ioport_rid, RF_ACTIVE);
178 if (!sc->ioport) {
179 device_printf(dev, "failed to allocate io port\n");
180 return ENOMEM;
181 }
182 sc->bst = rman_get_bustag(sc->ioport);
183 sc->bsh = rman_get_bushandle(sc->ioport);
184
185#ifdef CMX_INTR
186 sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
187 &sc->irq_rid, RF_ACTIVE);
188 if (!sc->irq) {
189 device_printf(dev, "failed to allocate irq\n");
190 return ENOMEM;
191 }
192 if ((rv = bus_setup_intr(dev, sc->irq, 0, cmx_intr, sc,
193 &sc->ih, NULL)) != 0) {
194 device_printf(dev, "failed to set up irq\n");
195 return ENOMEM;
196 }
197#endif
198
199 lockinit(&sc->mtx, "cmx softc lock", 0, LK_CANRECURSE);
200 callout_init(&sc->ch);
201
202 return 0;
203}
204
205/*
206 * Release the resources allocated by cmx_allocate_resources.
207 */
208void
209cmx_release_resources(device_t dev)
210{
211 struct cmx_softc *sc = device_get_softc(dev);
212
213 lockuninit(&sc->mtx);
214
215#ifdef CMX_INTR
216 if (sc->ih) {
217 bus_teardown_intr(dev, sc->irq, sc->ih);
218 sc->ih = NULL;
219 }
220 if (sc->irq) {
221 bus_release_resource(dev, SYS_RES_IRQ,
222 sc->irq_rid, sc->irq);
223 sc->irq = NULL;
224 }
225#endif
226
227 if (sc->ioport) {
228 bus_deactivate_resource(dev, SYS_RES_IOPORT,
229 sc->ioport_rid, sc->ioport);
230 bus_release_resource(dev, SYS_RES_IOPORT,
231 sc->ioport_rid, sc->ioport);
232 sc->ioport = NULL;
233 }
234 return;
235}
236
237/*
238 * Bus independant device attachment routine. Creates the
239 * character device node.
240 */
241int
242cmx_attach(device_t dev)
243{
244 struct cmx_softc *sc = device_get_softc(dev);
245
246 if (!sc || sc->dying)
247 return ENXIO;
248
249 dev_ops_add(&cmx_ops, -1, device_get_unit(dev));
250 sc->cdev = make_dev(&cmx_ops, 0, UID_ROOT, GID_WHEEL, 0600,
251 "cmx%d", device_get_unit(dev));
252 if (!sc->cdev) {
253 device_printf(dev, "failed to create character device\n");
254 return ENOMEM;
255 }
256 sc->cdev->si_drv1 = sc;
257
258 return 0;
259}
260
261/*
262 * Bus independant device detachment routine. Makes sure all
263 * allocated resources are freed, callouts disabled and waiting
264 * processes unblocked.
265 */
266int
267cmx_detach(device_t dev)
268{
269 struct cmx_softc *sc = device_get_softc(dev);
270
271 DEBUG_printf(dev, "called\n");
272
273 sc->dying = 1;
274
275 CMX_LOCK(sc);
276 if (sc->polling) {
277 DEBUG_printf(sc->dev, "disabling polling\n");
278 callout_stop(&sc->ch);
279 sc->polling = 0;
280 CMX_UNLOCK(sc);
281 selwakeup(&sc->sel);
282 } else {
283 CMX_UNLOCK(sc);
284 }
285
286 wakeup(sc);
287 destroy_dev(sc->cdev);
288
289 DEBUG_printf(dev, "releasing resources\n");
290 cmx_release_resources(dev);
291 return 0;
292}
293
294/*
295 * Wait for buffer status register events. If test is non-zero,
296 * wait until flags are set, otherwise wait until flags are unset.
297 * Will spin SPIN_COUNT times, then sleep until timeout is reached.
298 * Returns zero if event happened, EIO if the timeout was reached,
299 * and ENXIO if the device was detached in the meantime. When that
300 * happens, the caller must quit immediately, since a detach is
301 * in progress.
302 */
303static inline int
304cmx_wait_BSR(struct cmx_softc *sc, uint8_t flags, int test)
305{
306 int rv;
307
308 for (int i = 0; i < SPIN_COUNT; i++) {
309 if (cmx_test_BSR(sc, flags, test))
310 return 0;
311 }
312
313 for (int i = 0; i * WAIT_TICKS < sc->timeout; i++) {
314 if (cmx_test_BSR(sc, flags, test))
315 return 0;
316 rv = tsleep(sc, PCATCH, "cmx", WAIT_TICKS);
317 /*
318 * Currently, the only reason for waking up with
319 * rv == 0 is when we are detaching, in which
320 * case sc->dying is always 1.
321 */
322 if (sc->dying)
323 return ENXIO;
324 if (rv != EAGAIN)
325 return rv;
326 }
327
328 /* timeout */
329 return EIO;
330}
331
332/*
333 * Set the sync control register to val. Before and after writing
334 * to the SCR, we wait for the BSR to not signal BULK_OUT_FULL.
335 * Returns zero if successful, or whatever errors cmx_wait_BSR can
336 * return. ENXIO signals that the device has been detached in the
337 * meantime, and that we should leave the kernel immediately.
338 */
339static inline int
340cmx_sync_write_SCR(struct cmx_softc *sc, uint8_t val)
341{
342 int rv = 0;
343
344 if ((rv = cmx_wait_BSR(sc, BSR_BULK_OUT_FULL, 0)) != 0) {
345 return rv;
346 }
347
348 cmx_write_SCR(sc, val);
349
350 if ((rv = cmx_wait_BSR(sc, BSR_BULK_OUT_FULL, 0)) != 0) {
351 return rv;
352 }
353
354 return 0;
355}
356
357/*
358 * Returns a suitable timeout value based on the given command byte.
359 * Some commands appear to need longer timeout values than others.
360 */
361static inline unsigned long
362cmx_timeout_by_cmd(uint8_t cmd)
363{
364 switch (cmd) {
365 case CMD_PC_TO_RDR_XFRBLOCK:
366 case CMD_PC_TO_RDR_SECURE:
367 case CMD_PC_TO_RDR_TEST_SECURE:
368 case CMD_PC_TO_RDR_OK_SECURE:
369 return CCID_DRIVER_BULK_DEFAULT_TIMEOUT;
370
371 case CMD_PC_TO_RDR_ICCPOWERON:
372 return CCID_DRIVER_ASYNC_POWERUP_TIMEOUT;
373
374 case CMD_PC_TO_RDR_GETSLOTSTATUS:
375 case CMD_PC_TO_RDR_ICCPOWEROFF:
376 case CMD_PC_TO_RDR_GETPARAMETERS:
377 case CMD_PC_TO_RDR_RESETPARAMETERS:
378 case CMD_PC_TO_RDR_SETPARAMETERS:
379 case CMD_PC_TO_RDR_ESCAPE:
380 case CMD_PC_TO_RDR_ICCCLOCK:
381 default:
382 return CCID_DRIVER_MINIMUM_TIMEOUT;
383 }
384}
385
386/*
387 * Periodical callout routine, polling the reader for data
388 * availability. If the reader signals data ready for reading,
389 * wakes up the processes which are waiting in select()/poll().
390 * Otherwise, reschedules itself with a delay of POLL_TICKS.
391 */
392static void
393cmx_tick(void *xsc)
394{
395 struct cmx_softc *sc = xsc;
396 uint8_t bsr;
397
398 CMX_LOCK(sc);
399 if (sc->polling && !sc->dying) {
400 bsr = cmx_read_BSR(sc);
401 DEBUG_printf(sc->dev, "BSR=%b\n", bsr, BSRBITS);
402 if (cmx_test(bsr, BSR_BULK_IN_FULL, 1)) {
403 sc->polling = 0;
404 selwakeup(&sc->sel);
405 } else {
406 callout_reset(&sc->ch, POLL_TICKS, cmx_tick, sc);
407 }
408 }
409 CMX_UNLOCK(sc);
410}
411
412/*
413 * Open the character device. Only a single process may open the
414 * device at a time.
415 */
416static int
417cmx_open(struct dev_open_args *ap)
418{
419 cdev_t dev = ap->a_head.a_dev;
420 struct cmx_softc *sc;
421
422 sc = devclass_get_softc(cmx_devclass, minor(dev));
423 if (sc == NULL || sc->dying)
424 return ENXIO;
425
426 CMX_LOCK(sc);
427 if (sc->open) {
428 CMX_UNLOCK(sc);
429 return EBUSY;
430 }
431 sc->open = 1;
432 CMX_UNLOCK(sc);
433
434 DEBUG_printf(sc->dev, "open (flags=%b thread=%p)\n",
435 ap->a_oflags, MODEBITS, curthread);
436 return 0;
437}
438
439/*
440 * Close the character device.
441 */
442static int
443cmx_close(struct dev_close_args *ap)
444{
445 cdev_t dev = ap->a_head.a_dev;
446 struct cmx_softc *sc;
447
448 sc = devclass_get_softc(cmx_devclass, minor(dev));
449 if (sc == NULL || sc->dying)
450 return ENXIO;
451
452 CMX_LOCK(sc);
453 if (!sc->open) {
454 CMX_UNLOCK(sc);
455 return EINVAL;
456 }
457 if (sc->polling) {
458 DEBUG_printf(sc->dev, "disabling polling\n");
459 callout_stop(&sc->ch);
460 sc->polling = 0;
461 CMX_UNLOCK(sc);
462 selwakeup(&sc->sel);
463 CMX_LOCK(sc);
464 }
465 sc->open = 0;
466 CMX_UNLOCK(sc);
467
468 DEBUG_printf(sc->dev, "close (flags=%b thread=%p)\n",
469 ap->a_fflag, MODEBITS, curthread);
470 return 0;
471}
472
473/*
474 * Read from the character device.
475 * Returns zero if successful, ENXIO if dying, EINVAL if an attempt
476 * was made to read less than CMX_MIN_RDLEN bytes or less than the
477 * device has available, or any of the errors that cmx_sync_write_SCR
478 * can return. Partial reads are not supported.
479 */
480static int
481cmx_read(struct dev_read_args *ap)
482{
483 cdev_t dev = ap->a_head.a_dev;
484 struct cmx_softc *sc;
485 struct uio *uio = ap->a_uio;
486 unsigned long bytes_left;
487 uint8_t uc;
488 int rv, amnt, offset;
489
490 sc = devclass_get_softc(cmx_devclass, minor(dev));
491 if (sc == NULL || sc->dying)
492 return ENXIO;
493
494 DEBUG_printf(sc->dev, "called (len=%d flag=%b)\n",
495 uio->uio_resid, ap->a_ioflag, MODEBITS);
496
497 CMX_LOCK(sc);
498 if (sc->polling) {
499 DEBUG_printf(sc->dev, "disabling polling\n");
500 callout_stop(&sc->ch);
501 sc->polling = 0;
502 CMX_UNLOCK(sc);
503 selwakeup(&sc->sel);
504 } else {
505 CMX_UNLOCK(sc);
506 }
507
508 if (uio->uio_resid == 0) {
509 return 0;
510 }
511
512 if (uio->uio_resid < CMX_MIN_RDLEN) {
513 return EINVAL;
514 }
515
516 if (ap->a_ioflag & O_NONBLOCK) {
517 if (cmx_test_BSR(sc, BSR_BULK_IN_FULL, 0)) {
518 return EAGAIN;
519 }
520 }
521
522 for (int i = 0; i < 5; i++) {
523 if ((rv = cmx_wait_BSR(sc, BSR_BULK_IN_FULL, 1)) != 0) {
524 return rv;
525 }
526 sc->buf[i] = cmx_read_DTR(sc);
527 DEBUG_printf(sc->dev, "buf[%02x]=%02x\n", i, sc->buf[i]);
528 }
529
530 bytes_left = CMX_MIN_RDLEN +
531 (0x000000FF&((char)sc->buf[1])) +
532 (0x0000FF00&((char)sc->buf[2] << 8)) +
533 (0x00FF0000&((char)sc->buf[3] << 16)) +
534 (0xFF000000&((char)sc->buf[4] << 24));
535 DEBUG_printf(sc->dev, "msgsz=%lu\n", bytes_left);
536
537 if (uio->uio_resid < bytes_left) {
538 return EINVAL;
539 }
540
541 offset = 5; /* prefetched header */
542 while (bytes_left > 0) {
543 amnt = MIN(bytes_left, sizeof(sc->buf));
544
545 for (int i = offset; i < amnt; i++) {
546 if ((rv = cmx_wait_BSR(sc, BSR_BULK_IN_FULL, 1))!=0) {
547 return rv;
548 }
549 sc->buf[i] = cmx_read_DTR(sc);
550 DEBUG_printf(sc->dev, "buf[%02x]=%02x\n",
551 i, sc->buf[i]);
552 }
553
554 if ((rv = uiomove(sc->buf, amnt, uio)) != 0) {
555 DEBUG_printf(sc->dev, "uiomove failed (%d)\n", rv);
556 return rv;
557 }
558
559 if (offset)
560 offset = 0;
561 bytes_left -= amnt;
562 }
563
564 if ((rv = cmx_wait_BSR(sc, BSR_BULK_IN_FULL, 1)) != 0) {
565 return rv;
566 }
567
568 if ((rv = cmx_sync_write_SCR(sc, SCR_READER_TO_HOST_DONE)) != 0) {
569 return rv;
570 }
571
572 uc = cmx_read_DTR(sc);
573 DEBUG_printf(sc->dev, "success (DTR=%02x)\n", uc);
574 return 0;
575}
576
577/*
578 * Write to the character device.
579 * Returns zero if successful, NXIO if dying, EINVAL if less data
580 * written than CMX_MIN_WRLEN, or any of the errors that cmx_sync_SCR
581 * can return.
582 */
583static int
584cmx_write(struct dev_write_args *ap)
585{
586 cdev_t dev = ap->a_head.a_dev;
587 struct cmx_softc *sc;
588 struct uio *uio = ap->a_uio;
589 int rv, amnt;
590
591 sc = devclass_get_softc(cmx_devclass, minor(dev));
592 if (sc == NULL || sc->dying)
593 return ENXIO;
594
595 DEBUG_printf(sc->dev, "called (len=%d flag=%b)\n",
596 uio->uio_resid, ap->a_ioflag, MODEBITS);
597
598 if (uio->uio_resid == 0) {
599 return 0;
600 }
601
602 if (uio->uio_resid < CMX_MIN_WRLEN) {
603 return EINVAL;
604 }
605
606 if ((rv = cmx_sync_write_SCR(sc, SCR_HOST_TO_READER_START)) != 0) {
607 return rv;
608 }
609
610 sc->timeout = 0;
611 while (uio->uio_resid > 0) {
612 amnt = MIN(uio->uio_resid, sizeof(sc->buf));
613
614 if ((rv = uiomove(sc->buf, amnt, uio)) != 0) {
615 DEBUG_printf(sc->dev, "uiomove failed (%d)\n", rv);
616 /* wildly guessed attempt to notify device */
617 sc->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
618 cmx_sync_write_SCR(sc, SCR_HOST_TO_READER_DONE);
619 return rv;
620 }
621
622 if (sc->timeout == 0) {
623 sc->timeout = cmx_timeout_by_cmd(sc->buf[0]);
624 DEBUG_printf(sc->dev, "cmd=%02x timeout=%lu\n",
625 sc->buf[0], sc->timeout);
626 }
627
628 for (int i = 0; i < amnt; i++) {
629 if ((rv = cmx_wait_BSR(sc, BSR_BULK_OUT_FULL, 0))!=0) {
630 return rv;
631 }
632 cmx_write_DTR(sc, sc->buf[i]);
633 DEBUG_printf(sc->dev, "buf[%02x]=%02x\n",
634 i, sc->buf[i]);
635 }
636 }
637
638 if ((rv = cmx_sync_write_SCR(sc, SCR_HOST_TO_READER_DONE)) != 0) {
639 return rv;
640 }
641
642 DEBUG_printf(sc->dev, "success\n");
643 return 0;
644}
645
646/*
647 * Poll handler. Writing is always possible, reading is only possible
648 * if BSR_BULK_IN_FULL is set. Will start the cmx_tick callout and
649 * set sc->polling.
650 */
651static int
652cmx_poll(struct dev_poll_args *ap)
653{
654 cdev_t dev = ap->a_head.a_dev;
655 struct cmx_softc *sc;
656 int revents = 0;
657 uint8_t bsr = 0;
658
659 sc = devclass_get_softc(cmx_devclass, minor(dev));
660 if (sc == NULL || sc->dying)
661 return ENXIO;
662
663 bsr = cmx_read_BSR(sc);
664 DEBUG_printf(sc->dev, "called (events=%b BSR=%b)\n",
665 ap->a_events, POLLBITS, bsr, BSRBITS);
666
667 revents = ap->a_events & (POLLOUT | POLLWRNORM);
668 if (ap->a_events & (POLLIN | POLLRDNORM)) {
669 if (cmx_test(bsr, BSR_BULK_IN_FULL, 1)) {
670 revents |= ap->a_events & (POLLIN | POLLRDNORM);
671 } else {
672 selrecord(curthread, &sc->sel);
673 CMX_LOCK(sc);
674 if (!sc->polling) {
675 DEBUG_printf(sc->dev, "enabling polling\n");
676 sc->polling = 1;
677 callout_reset(&sc->ch, POLL_TICKS,
678 cmx_tick, sc);
679 } else {
680 DEBUG_printf(sc->dev, "already polling\n");
681 }
682 CMX_UNLOCK(sc);
683 }
684 }
685
686 DEBUG_printf(sc->dev, "success (revents=%b)\n", revents, POLLBITS);
687
688 return revents;
689}
690
691#ifdef CMX_INTR
692/*
693 * Interrupt handler. Currently has no function except to
694 * print register status (if debugging is also enabled).
695 */
696static void
697cmx_intr(void *arg)
698{
699 struct cmx_softc *sc = (struct cmx_softc *)arg;
700
701 if (sc == NULL || sc->dying)
702 return;
703
704 DEBUG_printf(sc->dev, "received interrupt (SCR=%b BSR=%b)\n",
705 cmx_read_SCR(sc), SCRBITS,
706 cmx_read_BSR(sc), BSRBITS);
707
708 return;
709}
710#endif
711