1578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell/* 2578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell comedi/drivers/serial2002.c 3578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell Skeleton code for a Comedi driver 4578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 5578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell COMEDI - Linux Control and Measurement Device Interface 6578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell Copyright (C) 2002 Anders Blomdell <anders.blomdell@control.lth.se> 7578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 8578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell This program is free software; you can redistribute it and/or modify 9578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell it under the terms of the GNU General Public License as published by 10578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell the Free Software Foundation; either version 2 of the License, or 11578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell (at your option) any later version. 12578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 13578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell This program is distributed in the hope that it will be useful, 14578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell but WITHOUT ANY WARRANTY; without even the implied warranty of 15578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell GNU General Public License for more details. 17578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 18578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell You should have received a copy of the GNU General Public License 19578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell along with this program; if not, write to the Free Software 20578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 22578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell*/ 23578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 24578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell/* 25578c0183545d8fe99f8a65cfb1483360d18c1253Anders BlomdellDriver: serial2002 26578c0183545d8fe99f8a65cfb1483360d18c1253Anders BlomdellDescription: Driver for serial connected hardware 27578c0183545d8fe99f8a65cfb1483360d18c1253Anders BlomdellDevices: 28578c0183545d8fe99f8a65cfb1483360d18c1253Anders BlomdellAuthor: Anders Blomdell 29578c0183545d8fe99f8a65cfb1483360d18c1253Anders BlomdellUpdated: Fri, 7 Jun 2002 12:56:45 -0700 30578c0183545d8fe99f8a65cfb1483360d18c1253Anders BlomdellStatus: in development 31578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 32578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell*/ 33578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 34578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell#include "../comedidev.h" 35578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 36578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell#include <linux/delay.h> 37578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell#include <linux/ioport.h> 38029214841ba8a1fae48a4a108d138b302d8a1afbGreg Kroah-Hartman#include <linux/sched.h> 395a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 40578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 41b041267ea819054aa9b406efc94fe8821ea2e67bRavishankar#include <linux/termios.h> 42578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell#include <asm/ioctls.h> 43578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell#include <linux/serial.h> 44578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell#include <linux/poll.h> 45578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 46578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell/* 47578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell * Board descriptions for two imaginary boards. Describing the 48578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell * boards in this way is optional, and completely driver-dependent. 49578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell * Some drivers use arrays such as this, other do not. 50578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell */ 51ca9ed0f295a5e85861c63713406d86643e570580Bill Pembertonstruct serial2002_board { 52578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell const char *name; 53ca9ed0f295a5e85861c63713406d86643e570580Bill Pemberton}; 54578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 55ca9ed0f295a5e85861c63713406d86643e570580Bill Pembertonstatic const struct serial2002_board serial2002_boards[] = { 56578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell { 570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "serial2002"} 58578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell}; 59578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 60578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell/* 61578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell * Useful for shorthand access to the particular board structure 62578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell */ 63ca9ed0f295a5e85861c63713406d86643e570580Bill Pemberton#define thisboard ((const struct serial2002_board *)dev->board_ptr) 64578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 65b3fb588d463c575706fe80e9c30bf4b1c7702034Bill Pembertonstruct serial2002_range_table_t { 66b3fb588d463c575706fe80e9c30bf4b1c7702034Bill Pemberton 672696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* HACK... */ 68578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int length; 691f6325d629ce03501e8927480495685828561f26Bill Pemberton struct comedi_krange range; 70b3fb588d463c575706fe80e9c30bf4b1c7702034Bill Pemberton}; 71b3fb588d463c575706fe80e9c30bf4b1c7702034Bill Pemberton 72e21ffa44f55ebf7f6f7d1e60a49463ca579c056aBill Pembertonstruct serial2002_private { 73e21ffa44f55ebf7f6f7d1e60a49463ca579c056aBill Pemberton 742696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton int port; /* /dev/ttyS<port> */ 752696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton int speed; /* baudrate */ 76578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct file *tty; 77790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton unsigned int ao_readback[32]; 78578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell unsigned char digital_in_mapping[32]; 79578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell unsigned char digital_out_mapping[32]; 80578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell unsigned char analog_in_mapping[32]; 81578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell unsigned char analog_out_mapping[32]; 82578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell unsigned char encoder_in_mapping[32]; 83b3fb588d463c575706fe80e9c30bf4b1c7702034Bill Pemberton struct serial2002_range_table_t in_range[32], out_range[32]; 84e21ffa44f55ebf7f6f7d1e60a49463ca579c056aBill Pemberton}; 85e21ffa44f55ebf7f6f7d1e60a49463ca579c056aBill Pemberton 86578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell/* 87578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell * most drivers define the following macro to make it easy to 88578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell * access the private structure. 89578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell */ 90e21ffa44f55ebf7f6f7d1e60a49463ca579c056aBill Pemberton#define devpriv ((struct serial2002_private *)dev->private) 91578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_attach(struct comedi_device *dev, 930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it); 94da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int serial2002_detach(struct comedi_device *dev); 95139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstruct comedi_driver driver_serial2002 = { 9668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "serial2002", 9768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 9868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = serial2002_attach, 9968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = serial2002_detach, 10068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .board_name = &serial2002_boards[0].name, 10168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .offset = sizeof(struct serial2002_board), 1028629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton .num_names = ARRAY_SIZE(serial2002_boards), 103578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell}; 104578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 1050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_di_rinsn(struct comedi_device *dev, 1060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 1080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_do_winsn(struct comedi_device *dev, 1090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 1110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_ai_rinsn(struct comedi_device *dev, 1120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 1140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_ao_winsn(struct comedi_device *dev, 1150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 1170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_ao_rinsn(struct comedi_device *dev, 1180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 120578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 121578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdellstruct serial_data { 122578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell enum { is_invalid, is_digital, is_channel } kind; 123578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int index; 124578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell unsigned long value; 125578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell}; 126578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 127578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdellstatic long tty_ioctl(struct file *f, unsigned op, unsigned long param) 128578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 12900a1855c21ab1efc71db98b0a87ea3d0ee7b8d92Shawn Bohrer if (f->f_op->unlocked_ioctl) 130578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return f->f_op->unlocked_ioctl(f, op, param); 13100a1855c21ab1efc71db98b0a87ea3d0ee7b8d92Shawn Bohrer 132578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return -ENOSYS; 133578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 134578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 135578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdellstatic int tty_write(struct file *f, unsigned char *buf, int count) 136578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 137578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int result; 138578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell mm_segment_t oldfs; 139578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 140578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell oldfs = get_fs(); 141578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell set_fs(KERNEL_DS); 142578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell f->f_pos = 0; 143578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result = f->f_op->write(f, buf, count, &f->f_pos); 144578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell set_fs(oldfs); 145578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return result; 146578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 147578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 148578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell#if 0 149578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell/* 150578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell * On 2.6.26.3 this occaisonally gave me page faults, worked around by 151578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell * settings.c_cc[VMIN] = 0; settings.c_cc[VTIME] = 0 152578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell */ 153578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdellstatic int tty_available(struct file *f) 154578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 155578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell long result = 0; 156578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell mm_segment_t oldfs; 157578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 158578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell oldfs = get_fs(); 159578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell set_fs(KERNEL_DS); 160578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell tty_ioctl(f, FIONREAD, (unsigned long)&result); 161578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell set_fs(oldfs); 162578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return result; 163578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 164578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell#endif 165578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 166578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdellstatic int tty_read(struct file *f, int timeout) 167578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 168578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int result; 169578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 170578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result = -1; 171578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (!IS_ERR(f)) { 172578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell mm_segment_t oldfs; 173578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 174578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell oldfs = get_fs(); 175578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell set_fs(KERNEL_DS); 176578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (f->f_op->poll) { 177578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct poll_wqueues table; 178578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct timeval start, now; 179578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 180578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell do_gettimeofday(&start); 181578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell poll_initwait(&table); 182578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell while (1) { 183578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell long elapsed; 184578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int mask; 185578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 186578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell mask = f->f_op->poll(f, &table.pt); 187578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (mask & (POLLRDNORM | POLLRDBAND | POLLIN | 1880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral POLLHUP | POLLERR)) { 189578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 190578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 191578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell do_gettimeofday(&now); 192578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell elapsed = 1930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (1000000 * (now.tv_sec - start.tv_sec) + 1940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral now.tv_usec - start.tv_usec); 195b041267ea819054aa9b406efc94fe8821ea2e67bRavishankar if (elapsed > timeout) 196578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 197578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell set_current_state(TASK_INTERRUPTIBLE); 198578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell schedule_timeout(((timeout - 1990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral elapsed) * HZ) / 10000); 200578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 201578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell poll_freewait(&table); 202578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell { 2030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unsigned char ch; 204578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 2050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral f->f_pos = 0; 206b041267ea819054aa9b406efc94fe8821ea2e67bRavishankar if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) 2070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral result = ch; 208578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 209578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } else { 210578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell /* Device does not support poll, busy wait */ 211578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int retries = 0; 212578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell while (1) { 213356cdbcb838ebcc234a43ec81621a39231fdcb7aBill Pemberton unsigned char ch; 214578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 215578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell retries++; 216b041267ea819054aa9b406efc94fe8821ea2e67bRavishankar if (retries >= timeout) 217578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 218578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 219578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell f->f_pos = 0; 220578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (f->f_op->read(f, &ch, 1, &f->f_pos) == 1) { 221356cdbcb838ebcc234a43ec81621a39231fdcb7aBill Pemberton result = ch; 222578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 223578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 2245f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman udelay(100); 225578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 226578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 227578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell set_fs(oldfs); 228578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 229578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return result; 230578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 231578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 232578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdellstatic void tty_setspeed(struct file *f, int speed) 233578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 234578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell mm_segment_t oldfs; 235578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 236578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell oldfs = get_fs(); 237578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell set_fs(KERNEL_DS); 238578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell { 2392696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* Set speed */ 240578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct termios settings; 241578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 242578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell tty_ioctl(f, TCGETS, (unsigned long)&settings); 2432696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX)); */ 244578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_iflag = 0; 245578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_oflag = 0; 246578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_lflag = 0; 247578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_cflag = CLOCAL | CS8 | CREAD; 248578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_cc[VMIN] = 0; 249578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_cc[VTIME] = 0; 250578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell switch (speed) { 251578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 2400:{ 252578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_cflag |= B2400; 253578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 254578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 255578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 4800:{ 256578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_cflag |= B4800; 257578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 258578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 259578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 9600:{ 260578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_cflag |= B9600; 261578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 262578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 263578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 19200:{ 264578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_cflag |= B19200; 265578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 266578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 267578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 38400:{ 268578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_cflag |= B38400; 269578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 270578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 271578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 57600:{ 272578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_cflag |= B57600; 273578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 274578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 275578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 115200:{ 276578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_cflag |= B115200; 277578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 278578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 279578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell default:{ 280578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.c_cflag |= B9600; 281578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 282578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 283578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 284578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell tty_ioctl(f, TCSETS, (unsigned long)&settings); 2852696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton/* printk("Speed: %d\n", settings.c_cflag & (CBAUD | CBAUDEX)); */ 286578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 287578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell { 2882696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* Set low latency */ 289578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct serial_struct settings; 290578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 291578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell tty_ioctl(f, TIOCGSERIAL, (unsigned long)&settings); 292578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell settings.flags |= ASYNC_LOW_LATENCY; 293578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell tty_ioctl(f, TIOCSSERIAL, (unsigned long)&settings); 294578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 295578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 296578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell set_fs(oldfs); 297578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 298578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 299578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdellstatic void poll_digital(struct file *f, int channel) 300578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 301578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell char cmd; 302578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 303578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell cmd = 0x40 | (channel & 0x1f); 304578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell tty_write(f, &cmd, 1); 305578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 306578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 307578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdellstatic void poll_channel(struct file *f, int channel) 308578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 309578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell char cmd; 310578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 311578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell cmd = 0x60 | (channel & 0x1f); 312578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell tty_write(f, &cmd, 1); 313578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 314578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 315578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdellstatic struct serial_data serial_read(struct file *f, int timeout) 316578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 317578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct serial_data result; 318578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int length; 319578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 320578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result.kind = is_invalid; 321578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result.index = 0; 322578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result.value = 0; 323578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell length = 0; 324578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell while (1) { 325578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int data = tty_read(f, timeout); 326578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 327578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell length++; 328578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (data < 0) { 329b041267ea819054aa9b406efc94fe8821ea2e67bRavishankar printk(KERN_ERR "serial2002 error\n"); 330578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 331578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } else if (data & 0x80) { 332578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result.value = (result.value << 7) | (data & 0x7f); 333578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } else { 334578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (length == 1) { 335578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell switch ((data >> 5) & 0x03) { 336578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 0:{ 337578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result.value = 0; 338578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result.kind = is_digital; 339578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 340578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 341578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 1:{ 342578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result.value = 1; 343578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result.kind = is_digital; 344578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 345578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 346578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 347578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } else { 348578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result.value = 3490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (result.value << 2) | ((data & 0x60) >> 5); 350578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result.kind = is_channel; 351578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 352578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell result.index = data & 0x1f; 353578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 354578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 355578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 356578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return result; 357578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 358578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 359578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 360578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdellstatic void serial_write(struct file *f, struct serial_data data) 361578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 362578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (data.kind == is_digital) { 363578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell unsigned char ch = 3640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((data.value << 5) & 0x20) | (data.index & 0x1f); 365578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell tty_write(f, &ch, 1); 366578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } else { 367578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell unsigned char ch[6]; 368578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int i = 0; 369578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (data.value >= (1L << 30)) { 370578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell ch[i] = 0x80 | ((data.value >> 30) & 0x03); 371578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell i++; 372578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 373578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (data.value >= (1L << 23)) { 374578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell ch[i] = 0x80 | ((data.value >> 23) & 0x7f); 375578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell i++; 376578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 377578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (data.value >= (1L << 16)) { 378578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell ch[i] = 0x80 | ((data.value >> 16) & 0x7f); 379578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell i++; 380578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 381578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (data.value >= (1L << 9)) { 382578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell ch[i] = 0x80 | ((data.value >> 9) & 0x7f); 383578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell i++; 384578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 385578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell ch[i] = 0x80 | ((data.value >> 2) & 0x7f); 386578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell i++; 387578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell ch[i] = ((data.value << 5) & 0x60) | (data.index & 0x1f); 388578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell i++; 389578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell tty_write(f, ch, i); 390578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 391578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 392578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 3933c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbottstatic int serial_2002_open(struct comedi_device *dev) 394578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 3953c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott int result; 396578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell char port[20]; 397578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 398578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell sprintf(port, "/dev/ttyS%d", devpriv->port); 3992021937c6d8ec1212b8f4fa01e86f852c9b96368OGAWA Hirofumi devpriv->tty = filp_open(port, O_RDWR, 0); 400578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (IS_ERR(devpriv->tty)) { 4013c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott result = (int)PTR_ERR(devpriv->tty); 402b041267ea819054aa9b406efc94fe8821ea2e67bRavishankar printk(KERN_ERR "serial_2002: file open error = %d\n", result); 403578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } else { 404e2b523aab1b04e7edc092588abbafa67f560deb4Bill Pemberton struct config_t { 405e2b523aab1b04e7edc092588abbafa67f560deb4Bill Pemberton 40667a6efb1f86eb51e4b702c4e8e735ca24e3427d8Ian Abbott short int kind; 40767a6efb1f86eb51e4b702c4e8e735ca24e3427d8Ian Abbott short int bits; 408578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int min; 409578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int max; 410e2b523aab1b04e7edc092588abbafa67f560deb4Bill Pemberton }; 411e2b523aab1b04e7edc092588abbafa67f560deb4Bill Pemberton 412668f272e57e80ece987bed273096f8e3a707123cIan Abbott struct config_t *dig_in_config; 413668f272e57e80ece987bed273096f8e3a707123cIan Abbott struct config_t *dig_out_config; 414668f272e57e80ece987bed273096f8e3a707123cIan Abbott struct config_t *chan_in_config; 415668f272e57e80ece987bed273096f8e3a707123cIan Abbott struct config_t *chan_out_config; 416578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int i; 417578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 4189e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott result = 0; 419668f272e57e80ece987bed273096f8e3a707123cIan Abbott dig_in_config = kcalloc(32, sizeof(struct config_t), 420668f272e57e80ece987bed273096f8e3a707123cIan Abbott GFP_KERNEL); 421668f272e57e80ece987bed273096f8e3a707123cIan Abbott dig_out_config = kcalloc(32, sizeof(struct config_t), 422668f272e57e80ece987bed273096f8e3a707123cIan Abbott GFP_KERNEL); 423668f272e57e80ece987bed273096f8e3a707123cIan Abbott chan_in_config = kcalloc(32, sizeof(struct config_t), 424668f272e57e80ece987bed273096f8e3a707123cIan Abbott GFP_KERNEL); 425668f272e57e80ece987bed273096f8e3a707123cIan Abbott chan_out_config = kcalloc(32, sizeof(struct config_t), 426668f272e57e80ece987bed273096f8e3a707123cIan Abbott GFP_KERNEL); 427668f272e57e80ece987bed273096f8e3a707123cIan Abbott if (!dig_in_config || !dig_out_config 428668f272e57e80ece987bed273096f8e3a707123cIan Abbott || !chan_in_config || !chan_out_config) { 429668f272e57e80ece987bed273096f8e3a707123cIan Abbott result = -ENOMEM; 430668f272e57e80ece987bed273096f8e3a707123cIan Abbott goto err_alloc_configs; 431578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 432578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 433578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell tty_setspeed(devpriv->tty, devpriv->speed); 4342696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton poll_channel(devpriv->tty, 31); /* Start reading configuration */ 435578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell while (1) { 436578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct serial_data data; 437578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 438578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell data = serial_read(devpriv->tty, 1000); 439578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (data.kind != is_channel || data.index != 31 4400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral || !(data.value & 0xe0)) { 441578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 442578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } else { 443578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int command, channel, kind; 444c5da20905c8ce21a73a9b443e5d7ef0dc623cff0Ian Abbott struct config_t *cur_config = NULL; 445578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 446578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell channel = data.value & 0x1f; 447578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell kind = (data.value >> 5) & 0x7; 448578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell command = (data.value >> 8) & 0x3; 449578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell switch (kind) { 450578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 1:{ 451578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell cur_config = dig_in_config; 452578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 453578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 454578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 2:{ 455578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell cur_config = dig_out_config; 456578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 457578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 458578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 3:{ 459578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell cur_config = chan_in_config; 460578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 461578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 462578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 4:{ 463578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell cur_config = chan_out_config; 464578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 465578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 466578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 5:{ 467578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell cur_config = chan_in_config; 468578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 469578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 470578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 471578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 472578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (cur_config) { 473578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell cur_config[channel].kind = kind; 474578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell switch (command) { 475578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 0:{ 4760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cur_config[channel].bits 4770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral = 4780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (data.value >> 10) & 4790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 0x3f; 480578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 481578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 482578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 1:{ 483578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int unit, sign, min; 4840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unit = 4850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (data.value >> 10) & 4860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 0x7; 4870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral sign = 4880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (data.value >> 13) & 4890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 0x1; 4900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral min = 4910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (data.value >> 14) & 4920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 0xfffff; 493578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 494578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell switch (unit) { 495578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 0:{ 4960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral min = 4970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral min 4980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 4990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1000000; 500578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 501578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 502578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 1:{ 5030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral min = 5040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral min 5050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 5060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1000; 507578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 508578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 509578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 2:{ 5100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral min = 5110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral min 5120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 1; 513578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 514578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 515578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 516e9d1cf89ed5561adc1d36aea6d1349d12dfedd74Ravishankar if (sign) 517578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell min = -min; 5180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cur_config[channel].min 5190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral = min; 520578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 521578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 522578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 2:{ 523578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int unit, sign, max; 5240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral unit = 5250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (data.value >> 10) & 5260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 0x7; 5270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral sign = 5280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (data.value >> 13) & 5290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 0x1; 5300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral max = 5310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (data.value >> 14) & 5320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 0xfffff; 533578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 534578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell switch (unit) { 535578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 0:{ 5360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral max = 5370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral max 5380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 5390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1000000; 540578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 541578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 542578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 1:{ 5430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral max = 5440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral max 5450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 5460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral 1000; 547578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 548578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 549578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 2:{ 5500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral max = 5510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral max 5520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral * 1; 553578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 554578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 555578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 556e9d1cf89ed5561adc1d36aea6d1349d12dfedd74Ravishankar if (sign) 557578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell max = -max; 5580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cur_config[channel].max 5590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral = max; 560578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 561578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 562578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 563578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 564578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 565578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 566578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell for (i = 0; i <= 4; i++) { 5672696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* Fill in subdev data */ 568e2b523aab1b04e7edc092588abbafa67f560deb4Bill Pemberton struct config_t *c; 569c5da20905c8ce21a73a9b443e5d7ef0dc623cff0Ian Abbott unsigned char *mapping = NULL; 570c5da20905c8ce21a73a9b443e5d7ef0dc623cff0Ian Abbott struct serial2002_range_table_t *range = NULL; 571578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int kind = 0; 572578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 573578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell switch (i) { 574578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 0:{ 575578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell c = dig_in_config; 576578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell mapping = devpriv->digital_in_mapping; 577578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell kind = 1; 578578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 579578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 580578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 1:{ 581578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell c = dig_out_config; 582578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell mapping = devpriv->digital_out_mapping; 583578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell kind = 2; 584578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 585578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 586578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 2:{ 587578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell c = chan_in_config; 588578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell mapping = devpriv->analog_in_mapping; 589578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell range = devpriv->in_range; 590578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell kind = 3; 591578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 592578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 593578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 3:{ 594578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell c = chan_out_config; 595578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell mapping = devpriv->analog_out_mapping; 596578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell range = devpriv->out_range; 597578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell kind = 4; 598578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 599578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 600578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell case 4:{ 601578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell c = chan_in_config; 602578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell mapping = devpriv->encoder_in_mapping; 603578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell range = devpriv->in_range; 604578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell kind = 5; 605578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 606578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 607578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell default:{ 608c5da20905c8ce21a73a9b443e5d7ef0dc623cff0Ian Abbott c = NULL; 609578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 610578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 611578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 612578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (c) { 61334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 6140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral const struct comedi_lrange **range_table_list = 6150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral NULL; 616578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell unsigned int *maxdata_list; 617578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int j, chan; 618578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 619578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell for (chan = 0, j = 0; j < 32; j++) { 620e9d1cf89ed5561adc1d36aea6d1349d12dfedd74Ravishankar if (c[j].kind == kind) 621578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell chan++; 622578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 623578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s = &dev->subdevices[i]; 624578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->n_chan = chan; 625578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->maxdata = 0; 6269e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott kfree(s->maxdata_list); 627578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->maxdata_list = maxdata_list = 6280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral kmalloc(sizeof(unsigned int) * s->n_chan, 6290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral GFP_KERNEL); 6309e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott if (!s->maxdata_list) 6319e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott break; /* error handled below */ 6329e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott kfree(s->range_table_list); 6339e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott s->range_table = NULL; 6349e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott s->range_table_list = NULL; 635578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (range) { 636578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->range_table_list = range_table_list = 6370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral kmalloc(sizeof 6380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (struct 6390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral serial2002_range_table_t) * 6400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral s->n_chan, GFP_KERNEL); 6419e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott if (!s->range_table_list) 6429e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott break; /* err handled below */ 643578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 644578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell for (chan = 0, j = 0; j < 32; j++) { 645578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (c[j].kind == kind) { 646e9d1cf89ed5561adc1d36aea6d1349d12dfedd74Ravishankar if (mapping) 647578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell mapping[chan] = j; 648578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (range) { 649578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell range[j].length = 1; 650578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell range[j].range.min = 6510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral c[j].min; 652578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell range[j].range.max = 6530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral c[j].max; 654578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell range_table_list[chan] = 6550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (const struct 6560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral comedi_lrange *) 6570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral &range[j]; 658578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 659578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell maxdata_list[chan] = 6600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ((long long)1 << c[j].bits) 6610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral - 1; 662578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell chan++; 663578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 664578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 665578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 666578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 6679e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott if (i <= 4) { 6689e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott /* Failed to allocate maxdata_list or range_table_list 6699e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott * for a subdevice that needed it. */ 6709e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott result = -ENOMEM; 6719e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott for (i = 0; i <= 4; i++) { 6729e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott struct comedi_subdevice *s; 6739e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott 6749e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott s = &dev->subdevices[i]; 6759e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott kfree(s->maxdata_list); 6769e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott s->maxdata_list = NULL; 6779e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott kfree(s->range_table_list); 6789e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott s->range_table_list = NULL; 6799e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott } 6809e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott } 681668f272e57e80ece987bed273096f8e3a707123cIan Abbott 682668f272e57e80ece987bed273096f8e3a707123cIan Abbotterr_alloc_configs: 683668f272e57e80ece987bed273096f8e3a707123cIan Abbott kfree(dig_in_config); 684668f272e57e80ece987bed273096f8e3a707123cIan Abbott kfree(dig_out_config); 685668f272e57e80ece987bed273096f8e3a707123cIan Abbott kfree(chan_in_config); 686668f272e57e80ece987bed273096f8e3a707123cIan Abbott kfree(chan_out_config); 687668f272e57e80ece987bed273096f8e3a707123cIan Abbott 6889e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott if (result) { 6899e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott if (devpriv->tty) { 6909e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott filp_close(devpriv->tty, 0); 6919e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott devpriv->tty = NULL; 6929e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott } 6939e7f2256883c954691e5d395d471e0f125f6b30bIan Abbott } 694578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 6953c17ba0743d75f9888d905ddf9f8551c7dd36493Ian Abbott return result; 696578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 697578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 698da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void serial_2002_close(struct comedi_device *dev) 699578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 700e9d1cf89ed5561adc1d36aea6d1349d12dfedd74Ravishankar if (!IS_ERR(devpriv->tty) && (devpriv->tty != 0)) 701578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell filp_close(devpriv->tty, 0); 702578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 703578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 7040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_di_rinsn(struct comedi_device *dev, 7050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 7060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 707578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 708578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int n; 709578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int chan; 710578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 711578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell chan = devpriv->digital_in_mapping[CR_CHAN(insn->chanspec)]; 712578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell for (n = 0; n < insn->n; n++) { 713578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct serial_data read; 714578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 715578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell poll_digital(devpriv->tty, chan); 716578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell while (1) { 717578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell read = serial_read(devpriv->tty, 1000); 718e9d1cf89ed5561adc1d36aea6d1349d12dfedd74Ravishankar if (read.kind != is_digital || read.index == chan) 719578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 720578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 721578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell data[n] = read.value; 722578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 723578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return n; 724578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 725578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 7260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_do_winsn(struct comedi_device *dev, 7270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 7280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 729578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 730578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int n; 731578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int chan; 732578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 733578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell chan = devpriv->digital_out_mapping[CR_CHAN(insn->chanspec)]; 734578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell for (n = 0; n < insn->n; n++) { 735578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct serial_data write; 736578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 737578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell write.kind = is_digital; 738578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell write.index = chan; 739578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell write.value = data[n]; 740578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell serial_write(devpriv->tty, write); 741578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 742578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return n; 743578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 744578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 7450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_ai_rinsn(struct comedi_device *dev, 7460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 7470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 748578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 749578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int n; 750578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int chan; 751578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 752578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell chan = devpriv->analog_in_mapping[CR_CHAN(insn->chanspec)]; 753578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell for (n = 0; n < insn->n; n++) { 754578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct serial_data read; 755578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 756578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell poll_channel(devpriv->tty, chan); 757578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell while (1) { 758578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell read = serial_read(devpriv->tty, 1000); 759e9d1cf89ed5561adc1d36aea6d1349d12dfedd74Ravishankar if (read.kind != is_channel || read.index == chan) 760578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 761578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 762578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell data[n] = read.value; 763578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 764578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return n; 765578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 766578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 7670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_ao_winsn(struct comedi_device *dev, 7680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 7690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 770578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 771578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int n; 772578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int chan; 773578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 774578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell chan = devpriv->analog_out_mapping[CR_CHAN(insn->chanspec)]; 775578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell for (n = 0; n < insn->n; n++) { 776578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct serial_data write; 777578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 778578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell write.kind = is_channel; 779578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell write.index = chan; 780578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell write.value = data[n]; 781578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell serial_write(devpriv->tty, write); 782578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell devpriv->ao_readback[chan] = data[n]; 783578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 784578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return n; 785578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 786578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 7870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_ao_rinsn(struct comedi_device *dev, 7880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 7890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 790578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 791578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int n; 792578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int chan = CR_CHAN(insn->chanspec); 793578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 794e9d1cf89ed5561adc1d36aea6d1349d12dfedd74Ravishankar for (n = 0; n < insn->n; n++) 795578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell data[n] = devpriv->ao_readback[chan]; 796578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 797578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return n; 798578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 799578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 8000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_ei_rinsn(struct comedi_device *dev, 8010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 8020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 803578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 804578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int n; 805578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int chan; 806578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 807578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell chan = devpriv->encoder_in_mapping[CR_CHAN(insn->chanspec)]; 808578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell for (n = 0; n < insn->n; n++) { 809578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell struct serial_data read; 810578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 811578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell poll_channel(devpriv->tty, chan); 812578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell while (1) { 813578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell read = serial_read(devpriv->tty, 1000); 814e9d1cf89ed5561adc1d36aea6d1349d12dfedd74Ravishankar if (read.kind != is_channel || read.index == chan) 815578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell break; 816578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 817578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell data[n] = read.value; 818578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 819578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return n; 820578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 821578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 8220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int serial2002_attach(struct comedi_device *dev, 8230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_devconfig *it) 824578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 82534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 826578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 8273dbeb83c245bbdc906eb54821d1cd77a25f56741Ravishankar karkala Mallikarjunayya dev_dbg(dev->hw_dev, "comedi%d: attached\n", dev->minor); 828578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell dev->board_name = thisboard->name; 829e9d1cf89ed5561adc1d36aea6d1349d12dfedd74Ravishankar if (alloc_private(dev, sizeof(struct serial2002_private)) < 0) 830578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return -ENOMEM; 831578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell dev->open = serial_2002_open; 832578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell dev->close = serial_2002_close; 833578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell devpriv->port = it->options[0]; 834578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell devpriv->speed = it->options[1]; 8353dbeb83c245bbdc906eb54821d1cd77a25f56741Ravishankar karkala Mallikarjunayya dev_dbg(dev->hw_dev, "/dev/ttyS%d @ %d\n", devpriv->port, 8363dbeb83c245bbdc906eb54821d1cd77a25f56741Ravishankar karkala Mallikarjunayya devpriv->speed); 837578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 838578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell if (alloc_subdevices(dev, 5) < 0) 839578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return -ENOMEM; 840578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 841578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell /* digital input subdevice */ 842578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s = dev->subdevices + 0; 843578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->type = COMEDI_SUBD_DI; 844578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->subdev_flags = SDF_READABLE; 845578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->n_chan = 0; 846578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->maxdata = 1; 847578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->range_table = &range_digital; 848578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->insn_read = &serial2002_di_rinsn; 849578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 850578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell /* digital output subdevice */ 851578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s = dev->subdevices + 1; 852578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->type = COMEDI_SUBD_DO; 853578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->subdev_flags = SDF_WRITEABLE; 854578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->n_chan = 0; 855578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->maxdata = 1; 856578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->range_table = &range_digital; 857578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->insn_write = &serial2002_do_winsn; 858578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 859578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell /* analog input subdevice */ 860578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s = dev->subdevices + 2; 861578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->type = COMEDI_SUBD_AI; 862578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->subdev_flags = SDF_READABLE | SDF_GROUND; 863578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->n_chan = 0; 864578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->maxdata = 1; 865578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->range_table = 0; 866578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->insn_read = &serial2002_ai_rinsn; 867578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 868578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell /* analog output subdevice */ 869578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s = dev->subdevices + 3; 870578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->type = COMEDI_SUBD_AO; 871578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->subdev_flags = SDF_WRITEABLE; 872578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->n_chan = 0; 873578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->maxdata = 1; 874578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->range_table = 0; 875578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->insn_write = &serial2002_ao_winsn; 876578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->insn_read = &serial2002_ao_rinsn; 877578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 878578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell /* encoder input subdevice */ 879578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s = dev->subdevices + 4; 880578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->type = COMEDI_SUBD_COUNTER; 881578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->subdev_flags = SDF_READABLE | SDF_LSAMPL; 882578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->n_chan = 0; 883578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->maxdata = 1; 884578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->range_table = 0; 885578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s->insn_read = &serial2002_ei_rinsn; 886578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 887578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return 1; 888578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 889578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 890da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int serial2002_detach(struct comedi_device *dev) 891578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell{ 89234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 893578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell int i; 894578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 8953dbeb83c245bbdc906eb54821d1cd77a25f56741Ravishankar karkala Mallikarjunayya dev_dbg(dev->hw_dev, "comedi%d: remove\n", dev->minor); 896fa3b5d9ab0487f58b45d55a37070aa0d417f59d5Ian Abbott for (i = 0; i < 5; i++) { 897578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell s = &dev->subdevices[i]; 898e4e1f289be88a75dc8b63d50ade1f9a2e6168021Ilia Mirkin kfree(s->maxdata_list); 899e4e1f289be88a75dc8b63d50ade1f9a2e6168021Ilia Mirkin kfree(s->range_table_list); 900578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell } 901578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell return 0; 902578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell} 903578c0183545d8fe99f8a65cfb1483360d18c1253Anders Blomdell 9047114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_serial2002_init_module(void) 9057114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 9067114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas return comedi_driver_register(&driver_serial2002); 9077114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 9087114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 9097114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_serial2002_cleanup_module(void) 9107114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 9117114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas comedi_driver_unregister(&driver_serial2002); 9127114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 9137114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 9147114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_serial2002_init_module); 9157114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_serial2002_cleanup_module); 91690f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 91790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 91890f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 91990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 920