1176868Srink/*-
2176868Srink * Copyright (c) 2006-2007 Daniel Roethlisberger <daniel@roe.ch>
3176868Srink * Copyright (c) 2000-2004 OMNIKEY GmbH (www.omnikey.com)
4176868Srink * All rights reserved.
5176868Srink *
6176868Srink * Redistribution and use in source and binary forms, with or without
7176868Srink * modification, are permitted provided that the following conditions
8176868Srink * are met:
9176868Srink * 1. Redistributions of source code must retain the above copyright
10176868Srink *    notice unmodified, this list of conditions, and the following
11176868Srink *    disclaimer.
12176868Srink * 2. Redistributions in binary form must reproduce the above copyright
13176868Srink *    notice, this list of conditions and the following disclaimer in the
14176868Srink *    documentation and/or other materials provided with the distribution.
15176868Srink *
16176868Srink * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17176868Srink * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18176868Srink * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19176868Srink * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20176868Srink * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21176868Srink * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22176868Srink * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23176868Srink * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24176868Srink * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25176868Srink * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26176868Srink * SUCH DAMAGE.
27176868Srink */
28176868Srink
29176868Srink#include <sys/cdefs.h>
30176868Srink__FBSDID("$FreeBSD: releng/10.2/sys/dev/cmx/cmx.c 176868 2008-03-06 08:09:45Z rink $");
31176868Srink
32176868Srink/*
33176868Srink * OMNIKEY CardMan 4040 a.k.a. CardMan eXtended (cmx) driver.
34176868Srink * This is a PCMCIA based smartcard reader which seems to work
35176868Srink * like an I/O port mapped USB CCID smartcard device.
36176868Srink *
37176868Srink * I/O originally based on Linux driver version 1.1.0 by OMNIKEY.
38176868Srink * Dual GPL/BSD.  Almost all of the code has been rewritten.
39176868Srink * $Omnikey: cm4040_cs.c,v 1.7 2004/10/04 09:08:50 jp Exp $
40176868Srink */
41176868Srink
42176868Srink#include <sys/param.h>
43176868Srink#include <sys/systm.h>
44176868Srink#include <sys/kernel.h>
45176868Srink#include <sys/sockio.h>
46176868Srink#include <sys/mbuf.h>
47176868Srink#include <sys/poll.h>
48176868Srink#include <sys/conf.h>
49176868Srink#include <sys/fcntl.h>
50176868Srink#include <sys/uio.h>
51176868Srink#include <sys/selinfo.h>
52176868Srink
53176868Srink#include <sys/module.h>
54176868Srink#include <sys/bus.h>
55176868Srink
56176868Srink#include <machine/bus.h>
57176868Srink#include <machine/resource.h>
58176868Srink#include <sys/rman.h>
59176868Srink
60176868Srink#include <dev/cmx/cmxvar.h>
61176868Srink#include <dev/cmx/cmxreg.h>
62176868Srink
63176868Srink#ifdef CMX_DEBUG
64176868Srink#define	DEBUG_printf(dev, fmt, args...) \
65176868Srink	device_printf(dev, "%s: " fmt, __FUNCTION__, ##args)
66176868Srink#else
67176868Srink#define	DEBUG_printf(dev, fmt, args...)
68176868Srink#endif
69176868Srink
70176868Srink#define	SPIN_COUNT				1000
71176868Srink#define	WAIT_TICKS				(hz/100)
72176868Srink#define	POLL_TICKS				(hz/10)
73176868Srink
74176868Srink/* possibly bogus */
75176868Srink#define	CCID_DRIVER_BULK_DEFAULT_TIMEOUT	(150*hz)
76176868Srink#define	CCID_DRIVER_ASYNC_POWERUP_TIMEOUT	(35*hz)
77176868Srink#define	CCID_DRIVER_MINIMUM_TIMEOUT		(3*hz)
78176868Srink
79176868Srink#ifdef CMX_DEBUG
80176868Srinkstatic char	BSRBITS[] = "\020"
81176868Srink	"\01BULK_OUT_FULL"		/* 0x01 */
82176868Srink	"\02BULK_IN_FULL"		/* 0x02 */
83176868Srink	"\03(0x04)";			/* 0x04 */
84176868Srink#ifdef CMX_INTR
85176868Srinkstatic char	SCRBITS[] = "\020"
86176868Srink	"\01POWER_DOWN"			/* 0x01 */
87176868Srink	"\02PULSE_INTERRUPT"		/* 0x02 */
88176868Srink	"\03HOST_TO_READER_DONE"	/* 0x04 */
89176868Srink	"\04READER_TO_HOST_DONE"	/* 0x08 */
90176868Srink	"\05ACK_NOTIFY"			/* 0x10 */
91176868Srink	"\06EN_NOTIFY"			/* 0x20 */
92176868Srink	"\07ABORT"			/* 0x40 */
93176868Srink	"\10HOST_TO_READER_START";	/* 0x80 */
94176868Srink#endif /* CMX_INTR */
95176868Srinkstatic char	POLLBITS[] = "\020"
96176868Srink	"\01POLLIN"			/* 0x0001 */
97176868Srink	"\02POLLPRI"			/* 0x0002 */
98176868Srink	"\03POLLOUT"			/* 0x0004 */
99176868Srink	"\04POLLERR"			/* 0x0008 */
100176868Srink	"\05POLLHUP"			/* 0x0010 */
101176868Srink	"\06POLLINVAL"			/* 0x0020 */
102176868Srink	"\07POLLRDNORM"			/* 0x0040 */
103176868Srink	"\10POLLRDBAND"			/* 0x0080 */
104176868Srink	"\11POLLWRBAND";		/* 0x0100 */
105176868Srinkstatic char	MODEBITS[] = "\020"
106176868Srink	"\01READ"			/* 0x0001 */
107176868Srink	"\02WRITE"			/* 0x0002 */
108176868Srink	"\03NONBLOCK"			/* 0x0004 */
109176868Srink	"\04APPEND"			/* 0x0008 */
110176868Srink	"\05SHLOCK"			/* 0x0010 */
111176868Srink	"\06EXLOCK"			/* 0x0020 */
112176868Srink	"\07ASYNC"			/* 0x0040 */
113176868Srink	"\10FSYNC"			/* 0x0080 */
114176868Srink	"\11NOFOLLOW"			/* 0x0100 */
115176868Srink	"\12CREAT"			/* 0x0200 */
116176868Srink	"\13TRUNK"			/* 0x0400 */
117176868Srink	"\14EXCL"			/* 0x0800 */
118176868Srink	"\15(0x1000)"			/* 0x1000 */
119176868Srink	"\16(0x2000)"			/* 0x2000 */
120176868Srink	"\17HASLOCK"			/* 0x4000 */
121176868Srink	"\20NOCTTY"			/* 0x8000 */
122176868Srink	"\21DIRECT";			/* 0x00010000 */
123176868Srink#endif /* CMX_DEBUG */
124176868Srink
125176868Srinkdevclass_t cmx_devclass;
126176868Srink
127176868Srinkstatic d_open_t		cmx_open;
128176868Srinkstatic d_close_t	cmx_close;
129176868Srinkstatic d_read_t		cmx_read;
130176868Srinkstatic d_write_t	cmx_write;
131176868Srinkstatic d_poll_t		cmx_poll;
132176868Srink#ifdef CMX_INTR
133176868Srinkstatic void		cmx_intr(void *arg);
134176868Srink#endif
135176868Srink
136176868Srinkstatic struct cdevsw cmx_cdevsw = {
137176868Srink	.d_version =	D_VERSION,
138176868Srink	.d_open =	cmx_open,
139176868Srink	.d_close =	cmx_close,
140176868Srink	.d_read =	cmx_read,
141176868Srink	.d_write =	cmx_write,
142176868Srink	.d_poll =	cmx_poll,
143176868Srink	.d_name =	"cmx",
144176868Srink};
145176868Srink
146176868Srink/*
147176868Srink * Initialize the softc structure.  Must be called from
148176868Srink * the bus specific device allocation routine.
149176868Srink */
150176868Srinkvoid
151176868Srinkcmx_init_softc(device_t dev)
152176868Srink{
153176868Srink	struct cmx_softc *sc = device_get_softc(dev);
154176868Srink	sc->dev = dev;
155176868Srink	sc->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
156176868Srink}
157176868Srink
158176868Srink/*
159176868Srink * Allocate driver resources.  Must be called from the
160176868Srink * bus specific device allocation routine.  Caller must
161176868Srink * ensure to call cmx_release_resources to free the
162176868Srink * resources when detaching.
163176868Srink * Return zero if successful, and ENOMEM if the resources
164176868Srink * could not be allocated.
165176868Srink */
166176868Srinkint
167176868Srinkcmx_alloc_resources(device_t dev)
168176868Srink{
169176868Srink	struct cmx_softc *sc = device_get_softc(dev);
170176868Srink#ifdef CMX_INTR
171176868Srink	int rv;
172176868Srink#endif
173176868Srink
174176868Srink	sc->ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
175176868Srink			&sc->ioport_rid, RF_ACTIVE);
176176868Srink	if (!sc->ioport) {
177176868Srink		device_printf(dev, "failed to allocate io port\n");
178176868Srink		return ENOMEM;
179176868Srink	}
180176868Srink	sc->bst = rman_get_bustag(sc->ioport);
181176868Srink	sc->bsh = rman_get_bushandle(sc->ioport);
182176868Srink
183176868Srink#ifdef CMX_INTR
184176868Srink	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
185176868Srink			&sc->irq_rid, RF_ACTIVE);
186176868Srink	if (!sc->irq) {
187176868Srink		device_printf(dev, "failed to allocate irq\n");
188176868Srink		return ENOMEM;
189176868Srink	}
190176868Srink	if ((rv = bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY,
191176868Srink			cmx_intr, sc, &sc->ih)) != 0) {
192176868Srink		device_printf(dev, "failed to set up irq\n");
193176868Srink		return ENOMEM;
194176868Srink	}
195176868Srink#endif
196176868Srink
197176868Srink	mtx_init(&sc->mtx, device_get_nameunit(dev),
198176868Srink			"cmx softc lock",
199176868Srink			MTX_DEF | MTX_RECURSE);
200176868Srink	callout_init_mtx(&sc->ch, &sc->mtx, 0);
201176868Srink
202176868Srink	return 0;
203176868Srink}
204176868Srink
205176868Srink/*
206176868Srink * Release the resources allocated by cmx_allocate_resources.
207176868Srink */
208176868Srinkvoid
209176868Srinkcmx_release_resources(device_t dev)
210176868Srink{
211176868Srink	struct cmx_softc *sc = device_get_softc(dev);
212176868Srink
213176868Srink	mtx_destroy(&sc->mtx);
214176868Srink
215176868Srink#ifdef CMX_INTR
216176868Srink	if (sc->ih) {
217176868Srink		bus_teardown_intr(dev, sc->irq, sc->ih);
218176868Srink		sc->ih = NULL;
219176868Srink	}
220176868Srink	if (sc->irq) {
221176868Srink		bus_release_resource(dev, SYS_RES_IRQ,
222176868Srink				sc->irq_rid, sc->irq);
223176868Srink		sc->irq = NULL;
224176868Srink	}
225176868Srink#endif
226176868Srink
227176868Srink	if (sc->ioport) {
228176868Srink		bus_deactivate_resource(dev, SYS_RES_IOPORT,
229176868Srink				sc->ioport_rid, sc->ioport);
230176868Srink		bus_release_resource(dev, SYS_RES_IOPORT,
231176868Srink				sc->ioport_rid, sc->ioport);
232176868Srink		sc->ioport = NULL;
233176868Srink	}
234176868Srink	return;
235176868Srink}
236176868Srink
237176868Srink/*
238176868Srink * Bus independant device attachment routine.  Creates the
239176868Srink * character device node.
240176868Srink */
241176868Srinkint
242176868Srinkcmx_attach(device_t dev)
243176868Srink{
244176868Srink	struct cmx_softc *sc = device_get_softc(dev);
245176868Srink
246176868Srink	if (!sc || sc->dying)
247176868Srink		return ENXIO;
248176868Srink
249176868Srink	sc->cdev = make_dev(&cmx_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
250176868Srink	                    "cmx%d", device_get_unit(dev));
251176868Srink	if (!sc->cdev) {
252176868Srink		device_printf(dev, "failed to create character device\n");
253176868Srink		return ENOMEM;
254176868Srink	}
255176868Srink	sc->cdev->si_drv1 = sc;
256176868Srink
257176868Srink	return 0;
258176868Srink}
259176868Srink
260176868Srink/*
261176868Srink * Bus independant device detachment routine.  Makes sure all
262176868Srink * allocated resources are freed, callouts disabled and waiting
263176868Srink * processes unblocked.
264176868Srink */
265176868Srinkint
266176868Srinkcmx_detach(device_t dev)
267176868Srink{
268176868Srink	struct cmx_softc *sc = device_get_softc(dev);
269176868Srink
270176868Srink	DEBUG_printf(dev, "called\n");
271176868Srink
272176868Srink	sc->dying = 1;
273176868Srink
274176868Srink	CMX_LOCK(sc);
275176868Srink	if (sc->polling) {
276176868Srink		DEBUG_printf(sc->dev, "disabling polling\n");
277176868Srink		callout_stop(&sc->ch);
278176868Srink		sc->polling = 0;
279176868Srink		CMX_UNLOCK(sc);
280176868Srink		callout_drain(&sc->ch);
281176868Srink		selwakeuppri(&sc->sel, PZERO);
282176868Srink	} else {
283176868Srink		CMX_UNLOCK(sc);
284176868Srink	}
285176868Srink
286176868Srink	wakeup(sc);
287176868Srink	destroy_dev(sc->cdev);
288176868Srink
289176868Srink	DEBUG_printf(dev, "releasing resources\n");
290176868Srink	cmx_release_resources(dev);
291176868Srink	return 0;
292176868Srink}
293176868Srink
294176868Srink/*
295176868Srink * Wait for buffer status register events.  If test is non-zero,
296176868Srink * wait until flags are set, otherwise wait until flags are unset.
297176868Srink * Will spin SPIN_COUNT times, then sleep until timeout is reached.
298176868Srink * Returns zero if event happened, EIO if the timeout was reached,
299176868Srink * and ENXIO if the device was detached in the meantime.  When that
300176868Srink * happens, the caller must quit immediately, since a detach is
301176868Srink * in progress.
302176868Srink */
303176868Srinkstatic inline int
304176868Srinkcmx_wait_BSR(struct cmx_softc *sc, uint8_t flags, int test)
305176868Srink{
306176868Srink	int rv;
307176868Srink
308176868Srink	for (int i = 0; i < SPIN_COUNT; i++) {
309176868Srink		if (cmx_test_BSR(sc, flags, test))
310176868Srink			return 0;
311176868Srink	}
312176868Srink
313176868Srink	for (int i = 0; i * WAIT_TICKS < sc->timeout; i++) {
314176868Srink		if (cmx_test_BSR(sc, flags, test))
315176868Srink			return 0;
316176868Srink		rv = tsleep(sc, PWAIT|PCATCH, "cmx", WAIT_TICKS);
317176868Srink		/*
318176868Srink		 * Currently, the only reason for waking up with
319176868Srink		 * rv == 0 is when we are detaching, in which
320176868Srink		 * case sc->dying is always 1.
321176868Srink		 */
322176868Srink		if (sc->dying)
323176868Srink			return ENXIO;
324176868Srink		if (rv != EAGAIN)
325176868Srink			return rv;
326176868Srink	}
327176868Srink
328176868Srink	/* timeout */
329176868Srink	return EIO;
330176868Srink}
331176868Srink
332176868Srink/*
333176868Srink * Set the sync control register to val.  Before and after writing
334176868Srink * to the SCR, we wait for the BSR to not signal BULK_OUT_FULL.
335176868Srink * Returns zero if successful, or whatever errors cmx_wait_BSR can
336176868Srink * return.  ENXIO signals that the device has been detached in the
337176868Srink * meantime, and that we should leave the kernel immediately.
338176868Srink */
339176868Srinkstatic inline int
340176868Srinkcmx_sync_write_SCR(struct cmx_softc *sc, uint8_t val)
341176868Srink{
342176868Srink	int rv = 0;
343176868Srink
344176868Srink	if ((rv = cmx_wait_BSR(sc, BSR_BULK_OUT_FULL, 0)) != 0) {
345176868Srink		return rv;
346176868Srink	}
347176868Srink
348176868Srink	cmx_write_SCR(sc, val);
349176868Srink
350176868Srink	if ((rv = cmx_wait_BSR(sc, BSR_BULK_OUT_FULL, 0)) != 0) {
351176868Srink		return rv;
352176868Srink	}
353176868Srink
354176868Srink	return 0;
355176868Srink}
356176868Srink
357176868Srink/*
358176868Srink * Returns a suitable timeout value based on the given command byte.
359176868Srink * Some commands appear to need longer timeout values than others.
360176868Srink */
361176868Srinkstatic inline unsigned long
362176868Srinkcmx_timeout_by_cmd(uint8_t cmd)
363176868Srink{
364176868Srink	switch (cmd) {
365176868Srink	case CMD_PC_TO_RDR_XFRBLOCK:
366176868Srink	case CMD_PC_TO_RDR_SECURE:
367176868Srink	case CMD_PC_TO_RDR_TEST_SECURE:
368176868Srink	case CMD_PC_TO_RDR_OK_SECURE:
369176868Srink		return CCID_DRIVER_BULK_DEFAULT_TIMEOUT;
370176868Srink
371176868Srink	case CMD_PC_TO_RDR_ICCPOWERON:
372176868Srink		return CCID_DRIVER_ASYNC_POWERUP_TIMEOUT;
373176868Srink
374176868Srink	case CMD_PC_TO_RDR_GETSLOTSTATUS:
375176868Srink	case CMD_PC_TO_RDR_ICCPOWEROFF:
376176868Srink	case CMD_PC_TO_RDR_GETPARAMETERS:
377176868Srink	case CMD_PC_TO_RDR_RESETPARAMETERS:
378176868Srink	case CMD_PC_TO_RDR_SETPARAMETERS:
379176868Srink	case CMD_PC_TO_RDR_ESCAPE:
380176868Srink	case CMD_PC_TO_RDR_ICCCLOCK:
381176868Srink	default:
382176868Srink		return CCID_DRIVER_MINIMUM_TIMEOUT;
383176868Srink	}
384176868Srink}
385176868Srink
386176868Srink/*
387176868Srink * Periodical callout routine, polling the reader for data
388176868Srink * availability.  If the reader signals data ready for reading,
389176868Srink * wakes up the processes which are waiting in select()/poll().
390176868Srink * Otherwise, reschedules itself with a delay of POLL_TICKS.
391176868Srink */
392176868Srinkstatic void
393176868Srinkcmx_tick(void *xsc)
394176868Srink{
395176868Srink	struct cmx_softc *sc = xsc;
396176868Srink	uint8_t bsr;
397176868Srink
398176868Srink	CMX_LOCK(sc);
399176868Srink	if (sc->polling && !sc->dying) {
400176868Srink		bsr = cmx_read_BSR(sc);
401176868Srink		DEBUG_printf(sc->dev, "BSR=%b\n", bsr, BSRBITS);
402176868Srink		if (cmx_test(bsr, BSR_BULK_IN_FULL, 1)) {
403176868Srink			sc->polling = 0;
404176868Srink			selwakeuppri(&sc->sel, PZERO);
405176868Srink		} else {
406176868Srink			callout_reset(&sc->ch, POLL_TICKS, cmx_tick, sc);
407176868Srink		}
408176868Srink	}
409176868Srink	CMX_UNLOCK(sc);
410176868Srink}
411176868Srink
412176868Srink/*
413176868Srink * Open the character device.  Only a single process may open the
414176868Srink * device at a time.
415176868Srink */
416176868Srinkstatic int
417176868Srinkcmx_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
418176868Srink{
419176868Srink	struct cmx_softc *sc = cdev->si_drv1;
420176868Srink
421176868Srink	if (sc == NULL || sc->dying)
422176868Srink		return ENXIO;
423176868Srink
424176868Srink	CMX_LOCK(sc);
425176868Srink	if (sc->open) {
426176868Srink		CMX_UNLOCK(sc);
427176868Srink		return EBUSY;
428176868Srink	}
429176868Srink	sc->open = 1;
430176868Srink	CMX_UNLOCK(sc);
431176868Srink
432176868Srink	DEBUG_printf(sc->dev, "open (flags=%b thread=%p)\n",
433176868Srink			flags, MODEBITS, td);
434176868Srink	return 0;
435176868Srink}
436176868Srink
437176868Srink/*
438176868Srink * Close the character device.
439176868Srink */
440176868Srinkstatic int
441176868Srinkcmx_close(struct cdev *cdev, int flags, int fmt, struct thread *td)
442176868Srink{
443176868Srink	struct cmx_softc *sc = cdev->si_drv1;
444176868Srink
445176868Srink	if (sc == NULL || sc->dying)
446176868Srink		return ENXIO;
447176868Srink
448176868Srink	CMX_LOCK(sc);
449176868Srink	if (!sc->open) {
450176868Srink		CMX_UNLOCK(sc);
451176868Srink		return EINVAL;
452176868Srink	}
453176868Srink	if (sc->polling) {
454176868Srink		DEBUG_printf(sc->dev, "disabling polling\n");
455176868Srink		callout_stop(&sc->ch);
456176868Srink		sc->polling = 0;
457176868Srink		CMX_UNLOCK(sc);
458176868Srink		callout_drain(&sc->ch);
459176868Srink		selwakeuppri(&sc->sel, PZERO);
460176868Srink		CMX_LOCK(sc);
461176868Srink	}
462176868Srink	sc->open = 0;
463176868Srink	CMX_UNLOCK(sc);
464176868Srink
465176868Srink	DEBUG_printf(sc->dev, "close (flags=%b thread=%p)\n",
466176868Srink			flags, MODEBITS, td);
467176868Srink	return 0;
468176868Srink}
469176868Srink
470176868Srink/*
471176868Srink * Read from the character device.
472176868Srink * Returns zero if successful, ENXIO if dying, EINVAL if an attempt
473176868Srink * was made to read less than CMX_MIN_RDLEN bytes or less than the
474176868Srink * device has available, or any of the errors that cmx_sync_write_SCR
475176868Srink * can return.  Partial reads are not supported.
476176868Srink */
477176868Srinkstatic int
478176868Srinkcmx_read(struct cdev *cdev, struct uio *uio, int flag)
479176868Srink{
480176868Srink	struct cmx_softc *sc = cdev->si_drv1;
481176868Srink	unsigned long bytes_left;
482176868Srink	uint8_t uc;
483176868Srink	int rv, amnt, offset;
484176868Srink
485176868Srink	if (sc == NULL || sc->dying)
486176868Srink		return ENXIO;
487176868Srink
488176868Srink	DEBUG_printf(sc->dev, "called (len=%d flag=%b)\n",
489176868Srink		uio->uio_resid, flag, MODEBITS);
490176868Srink
491176868Srink	CMX_LOCK(sc);
492176868Srink	if (sc->polling) {
493176868Srink		DEBUG_printf(sc->dev, "disabling polling\n");
494176868Srink		callout_stop(&sc->ch);
495176868Srink		sc->polling = 0;
496176868Srink		CMX_UNLOCK(sc);
497176868Srink		callout_drain(&sc->ch);
498176868Srink		selwakeuppri(&sc->sel, PZERO);
499176868Srink	} else {
500176868Srink		CMX_UNLOCK(sc);
501176868Srink	}
502176868Srink
503176868Srink	if (uio->uio_resid == 0) {
504176868Srink		return 0;
505176868Srink	}
506176868Srink
507176868Srink	if (uio->uio_resid < CMX_MIN_RDLEN) {
508176868Srink		return EINVAL;
509176868Srink	}
510176868Srink
511176868Srink	if (flag & O_NONBLOCK) {
512176868Srink		if (cmx_test_BSR(sc, BSR_BULK_IN_FULL, 0)) {
513176868Srink			return EAGAIN;
514176868Srink		}
515176868Srink	}
516176868Srink
517176868Srink	for (int i = 0; i < 5; i++) {
518176868Srink		if ((rv = cmx_wait_BSR(sc, BSR_BULK_IN_FULL, 1)) != 0) {
519176868Srink			return rv;
520176868Srink		}
521176868Srink		sc->buf[i] = cmx_read_DTR(sc);
522176868Srink		DEBUG_printf(sc->dev, "buf[%02x]=%02x\n", i, sc->buf[i]);
523176868Srink	}
524176868Srink
525176868Srink	bytes_left = CMX_MIN_RDLEN +
526176868Srink	                (0x000000FF&((char)sc->buf[1])) +
527176868Srink	                (0x0000FF00&((char)sc->buf[2] << 8)) +
528176868Srink	                (0x00FF0000&((char)sc->buf[3] << 16)) +
529176868Srink	                (0xFF000000&((char)sc->buf[4] << 24));
530176868Srink	DEBUG_printf(sc->dev, "msgsz=%lu\n", bytes_left);
531176868Srink
532176868Srink	if (uio->uio_resid < bytes_left) {
533176868Srink		return EINVAL;
534176868Srink	}
535176868Srink
536176868Srink	offset = 5; /* prefetched header */
537176868Srink	while (bytes_left > 0) {
538176868Srink		amnt = MIN(bytes_left, sizeof(sc->buf));
539176868Srink
540176868Srink		for (int i = offset; i < amnt; i++) {
541176868Srink			if ((rv = cmx_wait_BSR(sc, BSR_BULK_IN_FULL, 1))!=0) {
542176868Srink				return rv;
543176868Srink			}
544176868Srink			sc->buf[i] = cmx_read_DTR(sc);
545176868Srink			DEBUG_printf(sc->dev, "buf[%02x]=%02x\n",
546176868Srink					i, sc->buf[i]);
547176868Srink		}
548176868Srink
549176868Srink		if ((rv = uiomove(sc->buf, amnt, uio)) != 0) {
550176868Srink			DEBUG_printf(sc->dev, "uiomove failed (%d)\n", rv);
551176868Srink			return rv;
552176868Srink		}
553176868Srink
554176868Srink		if (offset)
555176868Srink			offset = 0;
556176868Srink		bytes_left -= amnt;
557176868Srink	}
558176868Srink
559176868Srink	if ((rv = cmx_wait_BSR(sc, BSR_BULK_IN_FULL, 1)) != 0) {
560176868Srink		return rv;
561176868Srink	}
562176868Srink
563176868Srink	if ((rv = cmx_sync_write_SCR(sc, SCR_READER_TO_HOST_DONE)) != 0) {
564176868Srink		return rv;
565176868Srink	}
566176868Srink
567176868Srink	uc = cmx_read_DTR(sc);
568176868Srink	DEBUG_printf(sc->dev, "success (DTR=%02x)\n", uc);
569176868Srink	return 0;
570176868Srink}
571176868Srink
572176868Srink/*
573176868Srink * Write to the character device.
574176868Srink * Returns zero if successful, NXIO if dying, EINVAL if less data
575176868Srink * written than CMX_MIN_WRLEN, or any of the errors that cmx_sync_SCR
576176868Srink * can return.
577176868Srink */
578176868Srinkstatic int
579176868Srinkcmx_write(struct cdev *cdev, struct uio *uio, int flag)
580176868Srink{
581176868Srink	struct cmx_softc *sc = cdev->si_drv1;
582176868Srink	int rv, amnt;
583176868Srink
584176868Srink	if (sc == NULL || sc->dying)
585176868Srink		return ENXIO;
586176868Srink
587176868Srink	DEBUG_printf(sc->dev, "called (len=%d flag=%b)\n",
588176868Srink			uio->uio_resid, flag, MODEBITS);
589176868Srink
590176868Srink	if (uio->uio_resid == 0) {
591176868Srink		return 0;
592176868Srink	}
593176868Srink
594176868Srink	if (uio->uio_resid < CMX_MIN_WRLEN) {
595176868Srink		return EINVAL;
596176868Srink	}
597176868Srink
598176868Srink	if ((rv = cmx_sync_write_SCR(sc, SCR_HOST_TO_READER_START)) != 0) {
599176868Srink		return rv;
600176868Srink	}
601176868Srink
602176868Srink	sc->timeout = 0;
603176868Srink	while (uio->uio_resid > 0) {
604176868Srink		amnt = MIN(uio->uio_resid, sizeof(sc->buf));
605176868Srink
606176868Srink		if ((rv = uiomove(sc->buf, amnt, uio)) != 0) {
607176868Srink			DEBUG_printf(sc->dev, "uiomove failed (%d)\n", rv);
608176868Srink			/* wildly guessed attempt to notify device */
609176868Srink			sc->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
610176868Srink			cmx_sync_write_SCR(sc, SCR_HOST_TO_READER_DONE);
611176868Srink			return rv;
612176868Srink		}
613176868Srink
614176868Srink		if (sc->timeout == 0) {
615176868Srink			sc->timeout = cmx_timeout_by_cmd(sc->buf[0]);
616176868Srink			DEBUG_printf(sc->dev, "cmd=%02x timeout=%lu\n",
617176868Srink					sc->buf[0], sc->timeout);
618176868Srink		}
619176868Srink
620176868Srink		for (int i = 0; i < amnt; i++) {
621176868Srink			if ((rv = cmx_wait_BSR(sc, BSR_BULK_OUT_FULL, 0))!=0) {
622176868Srink				return rv;
623176868Srink			}
624176868Srink			cmx_write_DTR(sc, sc->buf[i]);
625176868Srink			DEBUG_printf(sc->dev, "buf[%02x]=%02x\n",
626176868Srink					i, sc->buf[i]);
627176868Srink		}
628176868Srink	}
629176868Srink
630176868Srink	if ((rv = cmx_sync_write_SCR(sc, SCR_HOST_TO_READER_DONE)) != 0) {
631176868Srink		return rv;
632176868Srink	}
633176868Srink
634176868Srink	DEBUG_printf(sc->dev, "success\n");
635176868Srink	return 0;
636176868Srink}
637176868Srink
638176868Srink/*
639176868Srink * Poll handler.  Writing is always possible, reading is only possible
640176868Srink * if BSR_BULK_IN_FULL is set.  Will start the cmx_tick callout and
641176868Srink * set sc->polling.
642176868Srink */
643176868Srinkstatic int
644176868Srinkcmx_poll(struct cdev *cdev, int events, struct thread *td)
645176868Srink{
646176868Srink	struct cmx_softc *sc = cdev->si_drv1;
647176868Srink	int revents = 0;
648176868Srink	uint8_t bsr = 0;
649176868Srink
650176868Srink	if (sc == NULL || sc->dying)
651176868Srink		return ENXIO;
652176868Srink
653176868Srink	bsr = cmx_read_BSR(sc);
654176868Srink	DEBUG_printf(sc->dev, "called (events=%b BSR=%b)\n",
655176868Srink			events, POLLBITS, bsr, BSRBITS);
656176868Srink
657176868Srink	revents = events & (POLLOUT | POLLWRNORM);
658176868Srink	if (events & (POLLIN | POLLRDNORM)) {
659176868Srink		if (cmx_test(bsr, BSR_BULK_IN_FULL, 1)) {
660176868Srink			revents |= events & (POLLIN | POLLRDNORM);
661176868Srink		} else {
662176868Srink			selrecord(td, &sc->sel);
663176868Srink			CMX_LOCK(sc);
664176868Srink			if (!sc->polling) {
665176868Srink				DEBUG_printf(sc->dev, "enabling polling\n");
666176868Srink				sc->polling = 1;
667176868Srink				callout_reset(&sc->ch, POLL_TICKS,
668176868Srink						cmx_tick, sc);
669176868Srink			} else {
670176868Srink				DEBUG_printf(sc->dev, "already polling\n");
671176868Srink			}
672176868Srink			CMX_UNLOCK(sc);
673176868Srink		}
674176868Srink	}
675176868Srink
676176868Srink	DEBUG_printf(sc->dev, "success (revents=%b)\n", revents, POLLBITS);
677176868Srink
678176868Srink	return revents;
679176868Srink}
680176868Srink
681176868Srink#ifdef CMX_INTR
682176868Srink/*
683176868Srink * Interrupt handler.  Currently has no function except to
684176868Srink * print register status (if debugging is also enabled).
685176868Srink */
686176868Srinkstatic void
687176868Srinkcmx_intr(void *arg)
688176868Srink{
689176868Srink	struct cmx_softc *sc = (struct cmx_softc *)arg;
690176868Srink
691176868Srink	if (sc == NULL || sc->dying)
692176868Srink		return;
693176868Srink
694176868Srink	DEBUG_printf(sc->dev, "received interrupt (SCR=%b BSR=%b)\n",
695176868Srink			cmx_read_SCR(sc), SCRBITS,
696176868Srink			cmx_read_BSR(sc), BSRBITS);
697176868Srink
698176868Srink	return;
699176868Srink}
700176868Srink#endif
701176868Srink
702