Staging: comedi: add c6xdigio driver
Driver for Mechatronic Systems Inc. C6x_DIGIO DSP daughter card Written by Dan Block, email address unknown Cc: David Schleef <ds@schleef.org> Cc: Ian Abbott <abbotti@mev.co.uk> Cc: Frank Mori Hess <fmhess@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
9a21297d79
commit
2c89e159cd
1 changed files with 517 additions and 0 deletions
517
drivers/staging/comedi/drivers/c6xdigio.c
Normal file
517
drivers/staging/comedi/drivers/c6xdigio.c
Normal file
|
@ -0,0 +1,517 @@
|
|||
/*
|
||||
comedi/drivers/c6xdigio.c
|
||||
|
||||
Hardware driver for Mechatronic Systems Inc. C6x_DIGIO DSP daughter card.
|
||||
(http://robot0.ge.uiuc.edu/~spong/mecha/)
|
||||
|
||||
COMEDI - Linux Control and Measurement Device Interface
|
||||
Copyright (C) 1999 Dan Block
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
/*
|
||||
Driver: c6xdigio
|
||||
Description: Mechatronic Systems Inc. C6x_DIGIO DSP daughter card
|
||||
Author: Dan Block
|
||||
Status: unknown
|
||||
Devices: [Mechatronic Systems Inc.] C6x_DIGIO DSP daughter card (c6xdigio)
|
||||
Updated: Sun Nov 20 20:18:34 EST 2005
|
||||
|
||||
This driver will not work with a 2.4 kernel.
|
||||
http://robot0.ge.uiuc.edu/~spong/mecha/
|
||||
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/timex.h>
|
||||
#include <linux/timer.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/pnp.h>
|
||||
|
||||
#include "../comedidev.h"
|
||||
|
||||
static u8 ReadByteFromHwPort(unsigned long addr)
|
||||
{
|
||||
u8 result = inb(addr);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void WriteByteToHwPort(unsigned long addr, u8 val)
|
||||
{
|
||||
outb_p(val, addr);
|
||||
}
|
||||
|
||||
#define C6XDIGIO_SIZE 3
|
||||
|
||||
/*
|
||||
* port offsets
|
||||
*/
|
||||
#define C6XDIGIO_PARALLEL_DATA 0
|
||||
#define C6XDIGIO_PARALLEL_STATUS 1
|
||||
#define C6XDIGIO_PARALLEL_CONTROL 2
|
||||
struct pwmbitstype {
|
||||
unsigned sb0:2;
|
||||
unsigned sb1:2;
|
||||
unsigned sb2:2;
|
||||
unsigned sb3:2;
|
||||
unsigned sb4:2;
|
||||
};
|
||||
union pwmcmdtype {
|
||||
unsigned cmd; // assuming here that int is 32bit
|
||||
struct pwmbitstype bits;
|
||||
};
|
||||
struct encbitstype {
|
||||
unsigned sb0:3;
|
||||
unsigned sb1:3;
|
||||
unsigned sb2:3;
|
||||
unsigned sb3:3;
|
||||
unsigned sb4:3;
|
||||
unsigned sb5:3;
|
||||
unsigned sb6:3;
|
||||
unsigned sb7:3;
|
||||
};
|
||||
union encvaluetype {
|
||||
unsigned value;
|
||||
struct encbitstype bits;
|
||||
};
|
||||
|
||||
#define C6XDIGIO_TIME_OUT 20
|
||||
|
||||
static int c6xdigio_attach(comedi_device * dev, comedi_devconfig * it);
|
||||
static int c6xdigio_detach(comedi_device * dev);
|
||||
comedi_driver driver_c6xdigio = {
|
||||
driver_name:"c6xdigio",
|
||||
module:THIS_MODULE,
|
||||
attach:c6xdigio_attach,
|
||||
detach:c6xdigio_detach,
|
||||
};
|
||||
|
||||
static void C6X_pwmInit(unsigned long baseAddr)
|
||||
{
|
||||
int timeout = 0;
|
||||
|
||||
//printk("Inside C6X_pwmInit\n");
|
||||
|
||||
WriteByteToHwPort(baseAddr, 0x70);
|
||||
while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0)
|
||||
&& (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
timeout++;
|
||||
}
|
||||
|
||||
WriteByteToHwPort(baseAddr, 0x74);
|
||||
timeout = 0;
|
||||
while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80)
|
||||
&& (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
timeout++;
|
||||
}
|
||||
|
||||
WriteByteToHwPort(baseAddr, 0x70);
|
||||
timeout = 0;
|
||||
while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x0)
|
||||
&& (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
timeout++;
|
||||
}
|
||||
|
||||
WriteByteToHwPort(baseAddr, 0x0);
|
||||
timeout = 0;
|
||||
while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80)
|
||||
&& (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
timeout++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void C6X_pwmOutput(unsigned long baseAddr, unsigned channel, int value)
|
||||
{
|
||||
unsigned ppcmd;
|
||||
union pwmcmdtype pwm;
|
||||
int timeout = 0;
|
||||
unsigned tmp;
|
||||
|
||||
//printk("Inside C6X_pwmOutput\n");
|
||||
|
||||
pwm.cmd = value;
|
||||
if (pwm.cmd > 498)
|
||||
pwm.cmd = 498;
|
||||
if (pwm.cmd < 2)
|
||||
pwm.cmd = 2;
|
||||
|
||||
if (channel == 0) {
|
||||
ppcmd = 0x28;
|
||||
} else { // if channel == 1
|
||||
ppcmd = 0x30;
|
||||
} /* endif */
|
||||
|
||||
WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb0);
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb1 + 0x4);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb2);
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb3 + 0x4);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
WriteByteToHwPort(baseAddr, ppcmd + pwm.bits.sb4);
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
WriteByteToHwPort(baseAddr, 0x0);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int C6X_encInput(unsigned long baseAddr, unsigned channel)
|
||||
{
|
||||
unsigned ppcmd;
|
||||
union encvaluetype enc;
|
||||
int timeout = 0;
|
||||
int tmp;
|
||||
|
||||
//printk("Inside C6X_encInput\n");
|
||||
|
||||
enc.value = 0;
|
||||
if (channel == 0) {
|
||||
ppcmd = 0x48;
|
||||
} else {
|
||||
ppcmd = 0x50;
|
||||
}
|
||||
WriteByteToHwPort(baseAddr, ppcmd);
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
enc.bits.sb0 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7);
|
||||
WriteByteToHwPort(baseAddr, ppcmd + 0x4);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
enc.bits.sb1 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7);
|
||||
WriteByteToHwPort(baseAddr, ppcmd);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
enc.bits.sb2 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7);
|
||||
WriteByteToHwPort(baseAddr, ppcmd + 0x4);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
enc.bits.sb3 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7);
|
||||
WriteByteToHwPort(baseAddr, ppcmd);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
enc.bits.sb4 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7);
|
||||
WriteByteToHwPort(baseAddr, ppcmd + 0x4);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
enc.bits.sb5 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7);
|
||||
WriteByteToHwPort(baseAddr, ppcmd);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0x0) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
enc.bits.sb6 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7);
|
||||
WriteByteToHwPort(baseAddr, ppcmd + 0x4);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
enc.bits.sb7 = ((ReadByteFromHwPort(baseAddr + 1) >> 3) & 0x7);
|
||||
WriteByteToHwPort(baseAddr, ppcmd);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0x0) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
WriteByteToHwPort(baseAddr, 0x0);
|
||||
timeout = 0;
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
while (((tmp & 0x80) == 0x80) && (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
tmp = ReadByteFromHwPort(baseAddr + 1);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
return (enc.value ^ 0x800000);
|
||||
}
|
||||
|
||||
static void C6X_encResetAll(unsigned long baseAddr)
|
||||
{
|
||||
unsigned timeout = 0;
|
||||
|
||||
//printk("Inside C6X_encResetAll\n");
|
||||
|
||||
WriteByteToHwPort(baseAddr, 0x68);
|
||||
while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0)
|
||||
&& (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
timeout++;
|
||||
}
|
||||
WriteByteToHwPort(baseAddr, 0x6C);
|
||||
timeout = 0;
|
||||
while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80)
|
||||
&& (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
timeout++;
|
||||
}
|
||||
WriteByteToHwPort(baseAddr, 0x68);
|
||||
timeout = 0;
|
||||
while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x0)
|
||||
&& (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
timeout++;
|
||||
}
|
||||
WriteByteToHwPort(baseAddr, 0x0);
|
||||
timeout = 0;
|
||||
while (((ReadByteFromHwPort(baseAddr + 1) & 0x80) == 0x80)
|
||||
&& (timeout < C6XDIGIO_TIME_OUT)) {
|
||||
timeout++;
|
||||
}
|
||||
}
|
||||
|
||||
static int c6xdigio_pwmo_insn_read(comedi_device * dev,
|
||||
comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
|
||||
{
|
||||
printk("c6xdigio_pwmo_insn_read %x\n", insn->n);
|
||||
return insn->n;
|
||||
}
|
||||
|
||||
static int c6xdigio_pwmo_insn_write(comedi_device * dev,
|
||||
comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
|
||||
{
|
||||
int i;
|
||||
int chan = CR_CHAN(insn->chanspec);
|
||||
|
||||
// printk("c6xdigio_pwmo_insn_write %x\n", insn->n);
|
||||
for (i = 0; i < insn->n; i++) {
|
||||
C6X_pwmOutput(dev->iobase, chan, data[i]);
|
||||
/* devpriv->ao_readback[chan] = data[i]; */
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
//static int c6xdigio_ei_init_insn_read(comedi_device *dev,
|
||||
// comedi_subdevice *s,
|
||||
// comedi_insn *insn,
|
||||
// lsampl_t *data)
|
||||
//{
|
||||
// printk("c6xdigio_ei_init_insn_read %x\n", insn->n);
|
||||
// return insn->n;
|
||||
//}
|
||||
|
||||
//static int c6xdigio_ei_init_insn_write(comedi_device *dev,
|
||||
// comedi_subdevice *s,
|
||||
// comedi_insn *insn,
|
||||
// lsampl_t *data)
|
||||
//{
|
||||
// int i;
|
||||
// int chan = CR_CHAN(insn->chanspec);
|
||||
//
|
||||
// C6X_encResetAll( dev->iobase );
|
||||
//
|
||||
// return insn->n;
|
||||
//}
|
||||
|
||||
static int c6xdigio_ei_insn_read(comedi_device * dev,
|
||||
comedi_subdevice * s, comedi_insn * insn, lsampl_t * data)
|
||||
{
|
||||
// printk("c6xdigio_ei__insn_read %x\n", insn->n);
|
||||
int n;
|
||||
int chan = CR_CHAN(insn->chanspec);
|
||||
|
||||
for (n = 0; n < insn->n; n++) {
|
||||
data[n] = (C6X_encInput(dev->iobase, chan) & 0xffffff);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void board_init(comedi_device * dev)
|
||||
{
|
||||
|
||||
//printk("Inside board_init\n");
|
||||
|
||||
C6X_pwmInit(dev->iobase);
|
||||
C6X_encResetAll(dev->iobase);
|
||||
|
||||
}
|
||||
|
||||
//static void board_halt(comedi_device *dev) {
|
||||
// C6X_pwmInit(dev->iobase);
|
||||
//}
|
||||
|
||||
/*
|
||||
options[0] - I/O port
|
||||
options[1] - irq
|
||||
options[2] - number of encoder chips installed
|
||||
*/
|
||||
|
||||
static const struct pnp_device_id c6xdigio_pnp_tbl[] = {
|
||||
/* Standard LPT Printer Port */
|
||||
{.id = "PNP0400",.driver_data = 0},
|
||||
/* ECP Printer Port */
|
||||
{.id = "PNP0401",.driver_data = 0},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct pnp_driver c6xdigio_pnp_driver = {
|
||||
.name = "c6xdigio",
|
||||
.id_table = c6xdigio_pnp_tbl,
|
||||
};
|
||||
|
||||
static int c6xdigio_attach(comedi_device * dev, comedi_devconfig * it)
|
||||
{
|
||||
int result = 0;
|
||||
unsigned long iobase;
|
||||
unsigned int irq;
|
||||
comedi_subdevice *s;
|
||||
|
||||
iobase = it->options[0];
|
||||
printk("comedi%d: c6xdigio: 0x%04lx\n", dev->minor, iobase);
|
||||
if (!request_region(iobase, C6XDIGIO_SIZE, "c6xdigio")) {
|
||||
printk("comedi%d: I/O port conflict\n", dev->minor);
|
||||
return -EIO;
|
||||
}
|
||||
dev->iobase = iobase;
|
||||
dev->board_name = "c6xdigio";
|
||||
|
||||
result = alloc_subdevices(dev, 2); // 3 with encoder_init write
|
||||
if (result < 0)
|
||||
return result;
|
||||
|
||||
// Make sure that PnP ports gets activated
|
||||
pnp_register_driver(&c6xdigio_pnp_driver);
|
||||
|
||||
irq = it->options[1];
|
||||
if (irq > 0) {
|
||||
printk("comedi%d: irq = %u ignored\n", dev->minor, irq);
|
||||
} else if (irq == 0) {
|
||||
printk("comedi%d: no irq\n", dev->minor);
|
||||
}
|
||||
|
||||
s = dev->subdevices + 0;
|
||||
/* pwm output subdevice */
|
||||
s->type = COMEDI_SUBD_AO; // Not sure what to put here
|
||||
s->subdev_flags = SDF_WRITEABLE;
|
||||
s->n_chan = 2;
|
||||
/* s->trig[0] = c6xdigio_pwmo; */
|
||||
s->insn_read = c6xdigio_pwmo_insn_read;
|
||||
s->insn_write = c6xdigio_pwmo_insn_write;
|
||||
s->maxdata = 500;
|
||||
s->range_table = &range_bipolar10; // A suitable lie
|
||||
|
||||
s = dev->subdevices + 1;
|
||||
/* encoder (counter) subdevice */
|
||||
s->type = COMEDI_SUBD_COUNTER;
|
||||
s->subdev_flags = SDF_READABLE | SDF_LSAMPL;
|
||||
s->n_chan = 2;
|
||||
/* s->trig[0] = c6xdigio_ei; */
|
||||
s->insn_read = c6xdigio_ei_insn_read;
|
||||
s->maxdata = 0xffffff;
|
||||
s->range_table = &range_unknown;
|
||||
|
||||
// s = dev->subdevices + 2;
|
||||
// /* pwm output subdevice */
|
||||
// s->type = COMEDI_SUBD_COUNTER; // Not sure what to put here
|
||||
// s->subdev_flags = SDF_WRITEABLE;
|
||||
// s->n_chan = 1;
|
||||
// /* s->trig[0] = c6xdigio_ei_init; */
|
||||
// s->insn_read = c6xdigio_ei_init_insn_read;
|
||||
// s->insn_write = c6xdigio_ei_init_insn_write;
|
||||
// s->maxdata = 0xFFFF; // Really just a don't care
|
||||
// s->range_table = &range_unknown; // Not sure what to put here
|
||||
|
||||
// I will call this init anyway but more than likely the DSP board will not be connect
|
||||
// when device driver is loaded.
|
||||
board_init(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int c6xdigio_detach(comedi_device * dev)
|
||||
{
|
||||
// board_halt(dev); // may not need this
|
||||
|
||||
printk("comedi%d: c6xdigio: remove\n", dev->minor);
|
||||
|
||||
if (dev->iobase) {
|
||||
release_region(dev->iobase, C6XDIGIO_SIZE);
|
||||
}
|
||||
if (dev->irq) {
|
||||
free_irq(dev->irq, dev);
|
||||
} // Not using IRQ so I am not sure if I need this
|
||||
pnp_unregister_driver(&c6xdigio_pnp_driver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
COMEDI_INITCLEANUP(driver_c6xdigio);
|
Loading…
Reference in a new issue