pccard: Remove cmx(4) driver

The only attachment of cmx was pccard, so remove the driver in
anticipation of PC Card support removal.

Relnotes: Yes
This commit is contained in:
Warner Losh 2021-01-07 15:15:09 -07:00
parent 31cafce9fd
commit 0d3a424a89
11 changed files with 3 additions and 1135 deletions

View file

@ -36,6 +36,9 @@
# xargs -n1 | sort | uniq -d;
# done
# 20210108: retire cmx driver
OLD_FILES+=usr/share/man/man4/cmw.4.gz
# 20210107: retire a.out support
OLD_DIRS+=usr/lib/aout
OLD_DIRS+=usr/lib/compat/aout

View file

@ -111,7 +111,6 @@ MAN= aac.4 \
${_chvgpio.4} \
ciss.4 \
cloudabi.4 \
cmx.4 \
${_coretemp.4} \
cp2112.4 \
${_cpuctl.4} \

View file

@ -1,126 +0,0 @@
.\"
.\" Copyright (c) 2006-2007 Daniel Roethlisberger <daniel@roe.ch>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice unmodified, this list of conditions, and the following
.\" disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd July 7, 2007
.Dt CMX 4
.Os
.Sh NAME
.Nm cmx
.Nd Omnikey CardMan 4040 smartcard reader device driver
.Sh SYNOPSIS
.Cd device cmx
.Sh DEPRECATION NOTICE
This driver is scheduled for removal prior to the release of
.Fx 13.0
.Sh DESCRIPTION
The
.Nm
driver provides support for the PCCARD based
.Em Omnikey CardMan 4040
smartcard reader.
The driver provides a character device special file based
.Em Chip/Smart Card Interface Devices (CCID)
interface.
The driver implements what the vendor calls the
.Em Synchronous API
onto the smartcard reader device.
.Pp
Reading and writing is synchronous, meaning that a call to
.Xr write 2
directly corresponds to a complete CCID command sent to the
device, while the following
.Xr read 2
will return the complete answer from the reader.
There is no support for partial reads or writes.
There is no upper limit on
CCID request or response sizes, but the complete CCID request
must be sent to the driver in
.Xr write 2
and the complete CCID response must fit into the buffer
supplied to
.Xr read 2 .
.Pp
Non-blocking I/O,
.Xr select 2
and
.Xr poll 2
are supported and work as expected.
An open file descriptor
will always be ready for writing, but only ready for reading
if the device indicates that it has data available.
.Sh FILES
.Bl -tag -width /usr/ports/security/openct -compact
.It Pa /dev/cmx\fBn\fP
Character device special file.
.It Pa /usr/ports/security/openct
OpenCT, a userspace smartcard daemon containing a
.Em CCID
driver which directly supports
.Nm
devices.
.\".It Pa /usr/ports/devel/pcsc-lite
.\"PC/SC-Lite, a userspace smartcard daemon.
.\".It Pa /usr/ports/devel/libccid
.\"libccid, a generic
.\".Em CCID
.\"driver for use by PC/SC-Lite to interface to
.\".Nm
.\"devices.
.El
.Sh COMPATIBILITY
Userland smartcard code written for the vendor's Linux drivers
should work with the
.Nm
driver without modification.
.Sh SEE ALSO
.Xr pccard 4
.Sh HISTORY
The
.Nm cmx
driver first appeared in
.Fx 7.1 .
.Sh AUTHORS
.An -nosplit
The
.Nm
driver was written by
.An Daniel Roethlisberger Aq Mt daniel@roe.ch ,
originally based on the Linux driver v1.1.0 by
.An Omnikey GmbH Lk www.omnikey.com .
Early testing and bug fixes by
.An Marcin Cieslak Aq Mt saper@system.pl .
.Sh BUGS
.An -nosplit
The way the
.Nm
driver talks to the CardMan 4040 is a bit rough.
Due to the complete lack of hardware documentation other than vendor drivers
for other operating systems, the gory details of the device's
I/O registers are not understood very well.
There may be error conditions which can only be solved by physically
reinserting the reader.

View file

@ -2185,13 +2185,6 @@ options SND_FEEDER_RATE_HP
options SND_PCM_64
options SND_OLDSTEREO
#
# Miscellaneous hardware:
#
# cmx: OmniKey CardMan 4040 pccard smartcard reader
device cmx
#
# PC Card/PCMCIA and Cardbus
#

View file

@ -1418,8 +1418,6 @@ dev/cfi/cfi_dev.c optional cfi
dev/cfi/cfi_disk.c optional cfid
dev/chromebook_platform/chromebook_platform.c optional chromebook_platform
dev/ciss/ciss.c optional ciss
dev/cmx/cmx.c optional cmx
dev/cmx/cmx_pccard.c optional cmx pccard
dev/cpufreq/ichss.c optional cpufreq pci
dev/cxgb/cxgb_main.c optional cxgb pci \
compile-with "${NORMAL_C} -I$S/dev/cxgb"

View file

@ -1,702 +0,0 @@
/*-
* Copyright (c) 2006-2007 Daniel Roethlisberger <daniel@roe.ch>
* Copyright (c) 2000-2004 OMNIKEY GmbH (www.omnikey.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* OMNIKEY CardMan 4040 a.k.a. CardMan eXtended (cmx) driver.
* This is a PCMCIA based smartcard reader which seems to work
* like an I/O port mapped USB CCID smartcard device.
*
* I/O originally based on Linux driver version 1.1.0 by OMNIKEY.
* Dual GPL/BSD. Almost all of the code has been rewritten.
* $Omnikey: cm4040_cs.c,v 1.7 2004/10/04 09:08:50 jp Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
#include <sys/kernel.h>
#include <sys/mutex.h>
#include <sys/sockio.h>
#include <sys/mbuf.h>
#include <sys/poll.h>
#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/uio.h>
#include <sys/selinfo.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <dev/cmx/cmxvar.h>
#include <dev/cmx/cmxreg.h>
#ifdef CMX_DEBUG
#define DEBUG_printf(dev, fmt, args...) \
device_printf(dev, "%s: " fmt, __FUNCTION__, ##args)
#else
#define DEBUG_printf(dev, fmt, args...)
#endif
#define SPIN_COUNT 1000
#define WAIT_TICKS (hz/100)
#define POLL_TICKS (hz/10)
/* possibly bogus */
#define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*hz)
#define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*hz)
#define CCID_DRIVER_MINIMUM_TIMEOUT (3*hz)
#ifdef CMX_DEBUG
static char BSRBITS[] = "\020"
"\01BULK_OUT_FULL" /* 0x01 */
"\02BULK_IN_FULL" /* 0x02 */
"\03(0x04)"; /* 0x04 */
#ifdef CMX_INTR
static char SCRBITS[] = "\020"
"\01POWER_DOWN" /* 0x01 */
"\02PULSE_INTERRUPT" /* 0x02 */
"\03HOST_TO_READER_DONE" /* 0x04 */
"\04READER_TO_HOST_DONE" /* 0x08 */
"\05ACK_NOTIFY" /* 0x10 */
"\06EN_NOTIFY" /* 0x20 */
"\07ABORT" /* 0x40 */
"\10HOST_TO_READER_START"; /* 0x80 */
#endif /* CMX_INTR */
static char POLLBITS[] = "\020"
"\01POLLIN" /* 0x0001 */
"\02POLLPRI" /* 0x0002 */
"\03POLLOUT" /* 0x0004 */
"\04POLLERR" /* 0x0008 */
"\05POLLHUP" /* 0x0010 */
"\06POLLINVAL" /* 0x0020 */
"\07POLLRDNORM" /* 0x0040 */
"\10POLLRDBAND" /* 0x0080 */
"\11POLLWRBAND"; /* 0x0100 */
static char MODEBITS[] = "\020"
"\01READ" /* 0x0001 */
"\02WRITE" /* 0x0002 */
"\03NONBLOCK" /* 0x0004 */
"\04APPEND" /* 0x0008 */
"\05SHLOCK" /* 0x0010 */
"\06EXLOCK" /* 0x0020 */
"\07ASYNC" /* 0x0040 */
"\10FSYNC" /* 0x0080 */
"\11NOFOLLOW" /* 0x0100 */
"\12CREAT" /* 0x0200 */
"\13TRUNK" /* 0x0400 */
"\14EXCL" /* 0x0800 */
"\15(0x1000)" /* 0x1000 */
"\16(0x2000)" /* 0x2000 */
"\17HASLOCK" /* 0x4000 */
"\20NOCTTY" /* 0x8000 */
"\21DIRECT"; /* 0x00010000 */
#endif /* CMX_DEBUG */
devclass_t cmx_devclass;
static d_open_t cmx_open;
static d_close_t cmx_close;
static d_read_t cmx_read;
static d_write_t cmx_write;
static d_poll_t cmx_poll;
#ifdef CMX_INTR
static void cmx_intr(void *arg);
#endif
static struct cdevsw cmx_cdevsw = {
.d_version = D_VERSION,
.d_open = cmx_open,
.d_close = cmx_close,
.d_read = cmx_read,
.d_write = cmx_write,
.d_poll = cmx_poll,
.d_name = "cmx",
};
/*
* Initialize the softc structure. Must be called from
* the bus specific device allocation routine.
*/
void
cmx_init_softc(device_t dev)
{
struct cmx_softc *sc = device_get_softc(dev);
sc->dev = dev;
sc->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
}
/*
* Allocate driver resources. Must be called from the
* bus specific device allocation routine. Caller must
* ensure to call cmx_release_resources to free the
* resources when detaching.
* Return zero if successful, and ENOMEM if the resources
* could not be allocated.
*/
int
cmx_alloc_resources(device_t dev)
{
struct cmx_softc *sc = device_get_softc(dev);
#ifdef CMX_INTR
int rv;
#endif
sc->ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
&sc->ioport_rid, RF_ACTIVE);
if (!sc->ioport) {
device_printf(dev, "failed to allocate io port\n");
return ENOMEM;
}
sc->bst = rman_get_bustag(sc->ioport);
sc->bsh = rman_get_bushandle(sc->ioport);
#ifdef CMX_INTR
sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
&sc->irq_rid, RF_ACTIVE);
if (!sc->irq) {
device_printf(dev, "failed to allocate irq\n");
return ENOMEM;
}
if ((rv = bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY,
cmx_intr, sc, &sc->ih)) != 0) {
device_printf(dev, "failed to set up irq\n");
return ENOMEM;
}
#endif
mtx_init(&sc->mtx, device_get_nameunit(dev),
"cmx softc lock",
MTX_DEF | MTX_RECURSE);
callout_init_mtx(&sc->ch, &sc->mtx, 0);
return 0;
}
/*
* Release the resources allocated by cmx_allocate_resources.
*/
void
cmx_release_resources(device_t dev)
{
struct cmx_softc *sc = device_get_softc(dev);
mtx_destroy(&sc->mtx);
#ifdef CMX_INTR
if (sc->ih) {
bus_teardown_intr(dev, sc->irq, sc->ih);
sc->ih = NULL;
}
if (sc->irq) {
bus_release_resource(dev, SYS_RES_IRQ,
sc->irq_rid, sc->irq);
sc->irq = NULL;
}
#endif
if (sc->ioport) {
bus_deactivate_resource(dev, SYS_RES_IOPORT,
sc->ioport_rid, sc->ioport);
bus_release_resource(dev, SYS_RES_IOPORT,
sc->ioport_rid, sc->ioport);
sc->ioport = NULL;
}
return;
}
/*
* Bus independent device attachment routine. Creates the
* character device node.
*/
int
cmx_attach(device_t dev)
{
struct cmx_softc *sc = device_get_softc(dev);
if (!sc || sc->dying)
return ENXIO;
sc->cdev = make_dev(&cmx_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
"cmx%d", device_get_unit(dev));
if (!sc->cdev) {
device_printf(dev, "failed to create character device\n");
return ENOMEM;
}
sc->cdev->si_drv1 = sc;
return 0;
}
/*
* Bus independent device detachment routine. Makes sure all
* allocated resources are freed, callouts disabled and waiting
* processes unblocked.
*/
int
cmx_detach(device_t dev)
{
struct cmx_softc *sc = device_get_softc(dev);
DEBUG_printf(dev, "called\n");
sc->dying = 1;
CMX_LOCK(sc);
if (sc->polling) {
DEBUG_printf(sc->dev, "disabling polling\n");
callout_stop(&sc->ch);
sc->polling = 0;
CMX_UNLOCK(sc);
callout_drain(&sc->ch);
selwakeuppri(&sc->sel, PZERO);
} else {
CMX_UNLOCK(sc);
}
wakeup(sc);
destroy_dev(sc->cdev);
DEBUG_printf(dev, "releasing resources\n");
cmx_release_resources(dev);
return 0;
}
/*
* Wait for buffer status register events. If test is non-zero,
* wait until flags are set, otherwise wait until flags are unset.
* Will spin SPIN_COUNT times, then sleep until timeout is reached.
* Returns zero if event happened, EIO if the timeout was reached,
* and ENXIO if the device was detached in the meantime. When that
* happens, the caller must quit immediately, since a detach is
* in progress.
*/
static inline int
cmx_wait_BSR(struct cmx_softc *sc, uint8_t flags, int test)
{
int rv;
for (int i = 0; i < SPIN_COUNT; i++) {
if (cmx_test_BSR(sc, flags, test))
return 0;
}
for (int i = 0; i * WAIT_TICKS < sc->timeout; i++) {
if (cmx_test_BSR(sc, flags, test))
return 0;
rv = tsleep(sc, PWAIT|PCATCH, "cmx", WAIT_TICKS);
/*
* Currently, the only reason for waking up with
* rv == 0 is when we are detaching, in which
* case sc->dying is always 1.
*/
if (sc->dying)
return ENXIO;
if (rv != EAGAIN)
return rv;
}
/* timeout */
return EIO;
}
/*
* Set the sync control register to val. Before and after writing
* to the SCR, we wait for the BSR to not signal BULK_OUT_FULL.
* Returns zero if successful, or whatever errors cmx_wait_BSR can
* return. ENXIO signals that the device has been detached in the
* meantime, and that we should leave the kernel immediately.
*/
static inline int
cmx_sync_write_SCR(struct cmx_softc *sc, uint8_t val)
{
int rv = 0;
if ((rv = cmx_wait_BSR(sc, BSR_BULK_OUT_FULL, 0)) != 0) {
return rv;
}
cmx_write_SCR(sc, val);
if ((rv = cmx_wait_BSR(sc, BSR_BULK_OUT_FULL, 0)) != 0) {
return rv;
}
return 0;
}
/*
* Returns a suitable timeout value based on the given command byte.
* Some commands appear to need longer timeout values than others.
*/
static inline unsigned long
cmx_timeout_by_cmd(uint8_t cmd)
{
switch (cmd) {
case CMD_PC_TO_RDR_XFRBLOCK:
case CMD_PC_TO_RDR_SECURE:
case CMD_PC_TO_RDR_TEST_SECURE:
case CMD_PC_TO_RDR_OK_SECURE:
return CCID_DRIVER_BULK_DEFAULT_TIMEOUT;
case CMD_PC_TO_RDR_ICCPOWERON:
return CCID_DRIVER_ASYNC_POWERUP_TIMEOUT;
case CMD_PC_TO_RDR_GETSLOTSTATUS:
case CMD_PC_TO_RDR_ICCPOWEROFF:
case CMD_PC_TO_RDR_GETPARAMETERS:
case CMD_PC_TO_RDR_RESETPARAMETERS:
case CMD_PC_TO_RDR_SETPARAMETERS:
case CMD_PC_TO_RDR_ESCAPE:
case CMD_PC_TO_RDR_ICCCLOCK:
default:
return CCID_DRIVER_MINIMUM_TIMEOUT;
}
}
/*
* Periodical callout routine, polling the reader for data
* availability. If the reader signals data ready for reading,
* wakes up the processes which are waiting in select()/poll().
* Otherwise, reschedules itself with a delay of POLL_TICKS.
*/
static void
cmx_tick(void *xsc)
{
struct cmx_softc *sc = xsc;
uint8_t bsr;
CMX_LOCK(sc);
if (sc->polling && !sc->dying) {
bsr = cmx_read_BSR(sc);
DEBUG_printf(sc->dev, "BSR=%b\n", bsr, BSRBITS);
if (cmx_test(bsr, BSR_BULK_IN_FULL, 1)) {
sc->polling = 0;
selwakeuppri(&sc->sel, PZERO);
} else {
callout_reset(&sc->ch, POLL_TICKS, cmx_tick, sc);
}
}
CMX_UNLOCK(sc);
}
/*
* Open the character device. Only a single process may open the
* device at a time.
*/
static int
cmx_open(struct cdev *cdev, int flags, int fmt, struct thread *td)
{
struct cmx_softc *sc = cdev->si_drv1;
if (sc == NULL || sc->dying)
return ENXIO;
CMX_LOCK(sc);
if (sc->open) {
CMX_UNLOCK(sc);
return EBUSY;
}
sc->open = 1;
CMX_UNLOCK(sc);
DEBUG_printf(sc->dev, "open (flags=%b thread=%p)\n",
flags, MODEBITS, td);
return 0;
}
/*
* Close the character device.
*/
static int
cmx_close(struct cdev *cdev, int flags, int fmt, struct thread *td)
{
struct cmx_softc *sc = cdev->si_drv1;
if (sc == NULL || sc->dying)
return ENXIO;
CMX_LOCK(sc);
if (!sc->open) {
CMX_UNLOCK(sc);
return EINVAL;
}
if (sc->polling) {
DEBUG_printf(sc->dev, "disabling polling\n");
callout_stop(&sc->ch);
sc->polling = 0;
CMX_UNLOCK(sc);
callout_drain(&sc->ch);
selwakeuppri(&sc->sel, PZERO);
CMX_LOCK(sc);
}
sc->open = 0;
CMX_UNLOCK(sc);
DEBUG_printf(sc->dev, "close (flags=%b thread=%p)\n",
flags, MODEBITS, td);
return 0;
}
/*
* Read from the character device.
* Returns zero if successful, ENXIO if dying, EINVAL if an attempt
* was made to read less than CMX_MIN_RDLEN bytes or less than the
* device has available, or any of the errors that cmx_sync_write_SCR
* can return. Partial reads are not supported.
*/
static int
cmx_read(struct cdev *cdev, struct uio *uio, int flag)
{
struct cmx_softc *sc = cdev->si_drv1;
unsigned long bytes_left;
uint8_t uc;
int rv, amnt, offset;
if (sc == NULL || sc->dying)
return ENXIO;
DEBUG_printf(sc->dev, "called (len=%d flag=%b)\n",
uio->uio_resid, flag, MODEBITS);
CMX_LOCK(sc);
if (sc->polling) {
DEBUG_printf(sc->dev, "disabling polling\n");
callout_stop(&sc->ch);
sc->polling = 0;
CMX_UNLOCK(sc);
callout_drain(&sc->ch);
selwakeuppri(&sc->sel, PZERO);
} else {
CMX_UNLOCK(sc);
}
if (uio->uio_resid == 0) {
return 0;
}
if (uio->uio_resid < CMX_MIN_RDLEN) {
return EINVAL;
}
if (flag & O_NONBLOCK) {
if (cmx_test_BSR(sc, BSR_BULK_IN_FULL, 0)) {
return EAGAIN;
}
}
for (int i = 0; i < 5; i++) {
if ((rv = cmx_wait_BSR(sc, BSR_BULK_IN_FULL, 1)) != 0) {
return rv;
}
sc->buf[i] = cmx_read_DTR(sc);
DEBUG_printf(sc->dev, "buf[%02x]=%02x\n", i, sc->buf[i]);
}
bytes_left = CMX_MIN_RDLEN +
(0x000000FF&((char)sc->buf[1])) +
(0x0000FF00&((char)sc->buf[2] << 8)) +
(0x00FF0000&((char)sc->buf[3] << 16)) +
(0xFF000000&((char)sc->buf[4] << 24));
DEBUG_printf(sc->dev, "msgsz=%lu\n", bytes_left);
if (uio->uio_resid < bytes_left) {
return EINVAL;
}
offset = 5; /* prefetched header */
while (bytes_left > 0) {
amnt = MIN(bytes_left, sizeof(sc->buf));
for (int i = offset; i < amnt; i++) {
if ((rv = cmx_wait_BSR(sc, BSR_BULK_IN_FULL, 1))!=0) {
return rv;
}
sc->buf[i] = cmx_read_DTR(sc);
DEBUG_printf(sc->dev, "buf[%02x]=%02x\n",
i, sc->buf[i]);
}
if ((rv = uiomove(sc->buf, amnt, uio)) != 0) {
DEBUG_printf(sc->dev, "uiomove failed (%d)\n", rv);
return rv;
}
if (offset)
offset = 0;
bytes_left -= amnt;
}
if ((rv = cmx_wait_BSR(sc, BSR_BULK_IN_FULL, 1)) != 0) {
return rv;
}
if ((rv = cmx_sync_write_SCR(sc, SCR_READER_TO_HOST_DONE)) != 0) {
return rv;
}
uc = cmx_read_DTR(sc);
DEBUG_printf(sc->dev, "success (DTR=%02x)\n", uc);
return 0;
}
/*
* Write to the character device.
* Returns zero if successful, NXIO if dying, EINVAL if less data
* written than CMX_MIN_WRLEN, or any of the errors that cmx_sync_SCR
* can return.
*/
static int
cmx_write(struct cdev *cdev, struct uio *uio, int flag)
{
struct cmx_softc *sc = cdev->si_drv1;
int rv, amnt;
if (sc == NULL || sc->dying)
return ENXIO;
DEBUG_printf(sc->dev, "called (len=%d flag=%b)\n",
uio->uio_resid, flag, MODEBITS);
if (uio->uio_resid == 0) {
return 0;
}
if (uio->uio_resid < CMX_MIN_WRLEN) {
return EINVAL;
}
if ((rv = cmx_sync_write_SCR(sc, SCR_HOST_TO_READER_START)) != 0) {
return rv;
}
sc->timeout = 0;
while (uio->uio_resid > 0) {
amnt = MIN(uio->uio_resid, sizeof(sc->buf));
if ((rv = uiomove(sc->buf, amnt, uio)) != 0) {
DEBUG_printf(sc->dev, "uiomove failed (%d)\n", rv);
/* wildly guessed attempt to notify device */
sc->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
cmx_sync_write_SCR(sc, SCR_HOST_TO_READER_DONE);
return rv;
}
if (sc->timeout == 0) {
sc->timeout = cmx_timeout_by_cmd(sc->buf[0]);
DEBUG_printf(sc->dev, "cmd=%02x timeout=%lu\n",
sc->buf[0], sc->timeout);
}
for (int i = 0; i < amnt; i++) {
if ((rv = cmx_wait_BSR(sc, BSR_BULK_OUT_FULL, 0))!=0) {
return rv;
}
cmx_write_DTR(sc, sc->buf[i]);
DEBUG_printf(sc->dev, "buf[%02x]=%02x\n",
i, sc->buf[i]);
}
}
if ((rv = cmx_sync_write_SCR(sc, SCR_HOST_TO_READER_DONE)) != 0) {
return rv;
}
DEBUG_printf(sc->dev, "success\n");
return 0;
}
/*
* Poll handler. Writing is always possible, reading is only possible
* if BSR_BULK_IN_FULL is set. Will start the cmx_tick callout and
* set sc->polling.
*/
static int
cmx_poll(struct cdev *cdev, int events, struct thread *td)
{
struct cmx_softc *sc = cdev->si_drv1;
int revents = 0;
uint8_t bsr = 0;
if (sc == NULL || sc->dying)
return ENXIO;
bsr = cmx_read_BSR(sc);
DEBUG_printf(sc->dev, "called (events=%b BSR=%b)\n",
events, POLLBITS, bsr, BSRBITS);
revents = events & (POLLOUT | POLLWRNORM);
if (events & (POLLIN | POLLRDNORM)) {
if (cmx_test(bsr, BSR_BULK_IN_FULL, 1)) {
revents |= events & (POLLIN | POLLRDNORM);
} else {
selrecord(td, &sc->sel);
CMX_LOCK(sc);
if (!sc->polling) {
DEBUG_printf(sc->dev, "enabling polling\n");
sc->polling = 1;
callout_reset(&sc->ch, POLL_TICKS,
cmx_tick, sc);
} else {
DEBUG_printf(sc->dev, "already polling\n");
}
CMX_UNLOCK(sc);
}
}
DEBUG_printf(sc->dev, "success (revents=%b)\n", revents, POLLBITS);
return revents;
}
#ifdef CMX_INTR
/*
* Interrupt handler. Currently has no function except to
* print register status (if debugging is also enabled).
*/
static void
cmx_intr(void *arg)
{
struct cmx_softc *sc = (struct cmx_softc *)arg;
if (sc == NULL || sc->dying)
return;
DEBUG_printf(sc->dev, "received interrupt (SCR=%b BSR=%b)\n",
cmx_read_SCR(sc), SCRBITS,
cmx_read_BSR(sc), BSRBITS);
return;
}
#endif

View file

@ -1,116 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006-2007 Daniel Roethlisberger <daniel@roe.ch>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice unmodified, this list of conditions, and the following
* disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/selinfo.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
#include <dev/cmx/cmxvar.h>
#include <dev/pccard/pccardvar.h>
#include <dev/pccard/pccard_cis.h>
#include "pccarddevs.h"
static const struct pccard_product cmx_pccard_products[] = {
PCMCIA_CARD(OMNIKEY, CM4040),
{ NULL }
};
/*
* Probe for the card.
*/
static int
cmx_pccard_probe(device_t dev)
{
const struct pccard_product *pp;
if ((pp = pccard_product_lookup(dev, cmx_pccard_products,
sizeof(cmx_pccard_products[0]), NULL)) != NULL) {
if (pp->pp_name != NULL)
device_set_desc(dev, pp->pp_name);
return 0;
}
return EIO;
}
/*
* Attach to the pccard, and call bus independent attach and
* resource allocation routines.
*/
static int
cmx_pccard_attach(device_t dev)
{
int rv = 0;
cmx_init_softc(dev);
if ((rv = cmx_alloc_resources(dev)) != 0) {
device_printf(dev, "cmx_alloc_resources() failed!\n");
cmx_release_resources(dev);
return rv;
}
if ((rv = cmx_attach(dev)) != 0) {
device_printf(dev, "cmx_attach() failed!\n");
cmx_release_resources(dev);
return rv;
}
gone_in_dev(dev, 13, "pccard removed");
return 0;
}
static device_method_t cmx_pccard_methods[] = {
DEVMETHOD(device_probe, cmx_pccard_probe),
DEVMETHOD(device_attach, cmx_pccard_attach),
DEVMETHOD(device_detach, cmx_detach),
{ 0, 0 }
};
static driver_t cmx_pccard_driver = {
"cmx",
cmx_pccard_methods,
sizeof(struct cmx_softc),
};
DRIVER_MODULE(cmx, pccard, cmx_pccard_driver, cmx_devclass, 0, 0);
PCCARD_PNP_INFO(cmx_pccard_products);

View file

@ -1,68 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006-2007 Daniel Roethlisberger <daniel@roe.ch>
* Copyright (c) 2000-2004 OMNIKEY GmbH (www.omnikey.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/* I/O port registers */
#define REG_OFFSET_DTR 0 /* data transfer register */
#define REG_OFFSET_BSR 1 /* buffer status register */
#define REG_OFFSET_SCR 2 /* sync control register */
/* buffer status register flags */
#define BSR_BULK_OUT_FULL 0x01
#define BSR_BULK_IN_FULL 0x02
/* sync control register flags */
#define SCR_POWER_DOWN 0x01
#define SCR_PULSE_INTERRUPT 0x02
#define SCR_HOST_TO_READER_DONE 0x04
#define SCR_READER_TO_HOST_DONE 0x08
#define SCR_ACK_NOTIFY 0x10
#define SCR_EN_NOTIFY 0x20
#define SCR_ABORT 0x40
#define SCR_HOST_TO_READER_START 0x80
/* CCID commands */
#define CMD_PC_TO_RDR_SETPARAMETERS 0x61
#define CMD_PC_TO_RDR_ICCPOWERON 0x62
#define CMD_PC_TO_RDR_ICCPOWEROFF 0x63
#define CMD_PC_TO_RDR_GETSLOTSTATUS 0x65
#define CMD_PC_TO_RDR_SECURE 0x69
#define CMD_PC_TO_RDR_ESCAPE 0x6B
#define CMD_PC_TO_RDR_GETPARAMETERS 0x6C
#define CMD_PC_TO_RDR_RESETPARAMETERS 0x6D
#define CMD_PC_TO_RDR_ICCCLOCK 0x6E
#define CMD_PC_TO_RDR_XFRBLOCK 0x6F
#define CMD_PC_TO_RDR_TEST_SECURE 0x74
#define CMD_PC_TO_RDR_OK_SECURE 0x89
#define CMD_RDR_TO_PC_DATABLOCK 0x80
#define CMD_RDR_TO_PC_SLOTSTATUS 0x81
#define CMD_RDR_TO_PC_PARAMETERS 0x82
#define CMD_RDR_TO_PC_ESCAPE 0x83
#define CMD_RDR_TO_PC_OK_SECURE 0x89

View file

@ -1,101 +0,0 @@
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 2006-2007 Daniel Roethlisberger <daniel@roe.ch>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/*#define CMX_DEBUG*/
/*#define CMX_INTR*/
#define CMX_MIN_RDLEN 10 /* min read length */
#define CMX_MIN_WRLEN 5 /* min write length */
#define CMX_BUFSZ 512 /* I/O block size */
struct cmx_softc {
device_t dev; /* pccard device */
struct cdev *cdev; /* character device */
struct resource *ioport; /* io port resource descriptor */
int ioport_rid; /* io port resource identification */
bus_space_tag_t bst; /* bus space tag */
bus_space_handle_t bsh; /* bus space handle */
#ifdef CMX_INTR
struct resource* irq; /* irq resource descriptor */
int irq_rid; /* irq resource identification */
void *ih; /* intr handle */
#endif
struct mtx mtx; /* per-unit lock */
struct callout ch; /* callout handle */
struct selinfo sel; /* select/poll queue handle */
int open; /* is chardev open? */
int polling; /* are we polling? */
int dying; /* are we detaching? */
unsigned long timeout; /* response timeout */
uint8_t buf[CMX_BUFSZ]; /* read/write buffer */
};
extern devclass_t cmx_devclass;
void cmx_init_softc(device_t);
int cmx_alloc_resources(device_t);
void cmx_release_resources(device_t);
int cmx_attach(device_t);
int cmx_detach(device_t);
#define CMX_READ_1(sc, off) \
(bus_space_read_1((sc)->bst, (sc)->bsh, off))
#define CMX_WRITE_1(sc, off, val) \
(bus_space_write_1((sc)->bst, (sc)->bsh, off, val))
#define cmx_read_BSR(sc) \
CMX_READ_1(sc, REG_OFFSET_BSR)
#define cmx_write_BSR(sc, val) \
CMX_WRITE_1(sc, REG_OFFSET_BSR, val)
#define cmx_read_SCR(sc) \
CMX_READ_1(sc, REG_OFFSET_SCR)
#define cmx_write_SCR(sc, val) \
CMX_WRITE_1(sc, REG_OFFSET_SCR, val)
#define cmx_read_DTR(sc) \
CMX_READ_1(sc, REG_OFFSET_DTR)
#define cmx_write_DTR(sc, val) \
CMX_WRITE_1(sc, REG_OFFSET_DTR, val)
#define cmx_test(byte, flags, test) \
(((byte) & (flags)) == ((test) ? (flags) : 0))
#define cmx_test_BSR(sc, flags, test) \
cmx_test(cmx_read_BSR(sc), flags, test)
#define CMX_LOCK(sc) mtx_lock(&(sc)->mtx)
#define CMX_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
#define CMX_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, (what))

View file

@ -91,7 +91,6 @@ SUBDIR= \
cloudabi \
${_cloudabi32} \
${_cloudabi64} \
${_cmx} \
${_coretemp} \
${_cp} \
${_cpsw} \
@ -668,7 +667,6 @@ _bytgpio= bytgpio
_chvgpio= chvgpio
_ciss= ciss
_chromebook_platform= chromebook_platform
_cmx= cmx
_coretemp= coretemp
.if ${MK_SOURCELESS_HOST} != "no" && empty(KCSAN_ENABLED)
_hpt27xx= hpt27xx

View file

@ -1,10 +0,0 @@
# $FreeBSD$
#
.PATH: ${SRCTOP}/sys/dev/cmx
KMOD= cmx
SRCS= cmx.c cmxvar.h cmxreg.h \
cmx_pccard.c \
pccarddevs.h device_if.h bus_if.h card_if.h
.include <bsd.kmod.mk>