From 34cee6c5ddd5aa73a80b3d2f5544ff9f11bff3df Mon Sep 17 00:00:00 2001 From: David Schleef Date: Tue, 10 Jul 2001 21:02:20 +0000 Subject: [PATCH] So long, you served well. --- comedi/drivers/das08-old.c | 405 ------------ comedi/drivers/das08jr-old.c | 329 ---------- comedi/drivers/das16-old.c | 1191 ---------------------------------- comedi/drivers/das1600-old.c | 497 -------------- 4 files changed, 2422 deletions(-) delete mode 100644 comedi/drivers/das08-old.c delete mode 100644 comedi/drivers/das08jr-old.c delete mode 100644 comedi/drivers/das16-old.c delete mode 100644 comedi/drivers/das1600-old.c diff --git a/comedi/drivers/das08-old.c b/comedi/drivers/das08-old.c deleted file mode 100644 index 9acb10e4..00000000 --- a/comedi/drivers/das08-old.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - - DAS-08 adapter - - hack by David Schleef - - mostly borrowed from Warren J. Jasper - - should be compatible with boards from Keithley Metrabyte and - Computer Boards. - - * Copyright (C) 1998 Warren Jasper, David Schleef - * All rights reserved. - * - * This software may be freely copied, modified, and redistributed - * provided that this copyright notice is preserved on all copies. - * - * You may not distribute this software, in whole or in part, as part of - * any commercial product without the express consent of the authors. - * - * There is no warranty or other guarantee of fitness of this software - * for any purpose. It is provided solely "as is". - - -*/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include <8255.h> - -/* general debugging messages */ -#define DEBUG - -/* specific debugging messages */ -#undef DAVE1 -#undef DAVE2 -#undef DAVE3 - -/* - on the non-AO board, the DA registers don't exist - and the 8255 registers move up by 4 - it also doesn't use the GAIN_REG -*/ - - -#define DAS08_SIZE 0x10 - -#define LSB_AND_CHNLS 0 /* A/D Data & Channel Register */ -#define MSB_DATA_BYTE 1 -#define STATUS_REG 2 /* Channel Mux Scan Limits Register */ -#define GAIN_REG 3 /* Programmable Gain Register */ -#define COUNTER_0_DATA 4 /* Counter 0 Register */ -#define COUNTER_1_DATA 5 /* Counter 1 Register */ -#define COUNTER_2_DATA 6 /* Counter 2 Register */ -#define COUNTER_CONTROL 7 /* Conter Control Register */ -#define DA_CHAN0_LSB 8 /* DAC 0 Low Byte */ -#define DA_CHAN0_MSB 9 /* DAC 0 High Byte */ -#define DA_CHAN1_LSB 10 /* DAC 1 Low Byte */ -#define DA_CHAN1_MSB 11 /* DAC 1 High Byte */ -#define DIO_PORTA 12 /* Port A 8 bit I/O of 8255 */ -#define DIO_PORTB 13 /* Port B 8 bit I/O of 8255 */ -#define DIO_PORTC 14 /* Port C 4+4 bit of 8255 */ -#define DIO_CNTRL_REG 15 /* Mode and Direction Control Reg. */ - -/* - - info provided by Carsten Zerbst about das08: - agrees with pdf file from www.computerboards.com - -port, read, write -0 A/D Bits 3-0(LSB) Start 8 bit A/D conversion -1 A/D Bits 11-4(MSB) Start 12 bit A/D conversion -2 EOC,IP1-IP3,IRQ,MUX Address OP1-OP4, INTE & MUX address -3 not used not used -4 Read counter 0 Load Counter 0 -5 Read counter 1 Load Counter 1 -6 Read counter 2 Load Counter 2 -7 not used Counter control -8 Port A input 8255 Port A Output -9 Port B input Port A output -10 Port C Input Port A Output -11 None. No read Back on 8255 Configure 8255 - - -pgh model: gains .5,1,5,10,50,100,500,1000, unipolar and bipolar -pgl model: gains .5,1.2,4,8, unipolar and bipolar - -pgh bipolar ranges: +/- 10, +/-5, etc. -pgh unipolar ranges: 0 to { x,10,x,1,x,0.1,x,0.01 } - (what does x mean?) - -pgl bipolar ranges: +/- { 10,5,2.5,1.25,0.625 } -pgl unipolar ranges: 0 to { N/A, 10, 5, 2.5, 1.25 } - - -das08jr info: - -4 DAC0 lsb -5 DAC0 msb -6 DAC1 lsb -7 DAC1 msb - - - -*/ - - - -/************************************************************************* -* STATUS_REG base_reg+2 Status Register * -**************************************************************************/ - -/* Read */ -#define MUX0 0x01 /* Current multiplexor channel */ -#define MUX1 0x02 /* Current multiplexor channel */ -#define MUX2 0x04 /* Current multiplexor channel */ -#define IRQ 0x08 /* 1 = positive edge detected */ -#define IP1 0x10 /* digial input line IP1 */ -#define IP2 0x20 /* digial input line IP2 */ -#define IP3 0x40 /* digial input line IP3 */ -#define EOC 0x80 /* 1=A/D busy, 0=not busy */ - -/* Write */ -#define INTE 0x08 /* 1=enable interrupts, 0=disable */ -#define OP1 0x10 /* digital output line OP1 */ -#define OP2 0x20 /* digital output line OP2 */ -#define OP3 0x40 /* digital output line OP3 */ -#define OP4 0x80 /* digital output line OP4 */ - -/************************************************************************* -* Constants for dealing with the 8254 counters * -**************************************************************************/ - -#define MODE0 0x0 -#define MODE1 0x2 -#define MODE2 0x4 -#define MODE3 0x6 -#define MODE4 0x8 -#define MODE5 0xa - -#define C0 0x00 -#define C1 0x40 -#define C2 0x80 - -#define _LATCH 0x00 /* LATCH gets caught up with timex.h */ -#define LSBONLY 0x10 -#define MSBONLY 0x20 -#define LSBFIRST 0x30 - -#define S0 0x00 -#define S1 0x02 - -typedef struct{ - int boardtype; - int dio; - int aip[16]; -}das08_private; -#define devpriv ((das08_private *)dev->private) - -struct boardtype_struct{ - char name[20]; - int ai_chans; - int ao_chans; -}; -static struct boardtype_struct boardtypes[]={ - {"das08",8,0}, - {"das08-aol",8,0}, - {"das08-pgh",8,0}, - {"das08-pgl",8,0} -}; -#define this_board (boardtypes[devpriv->boardtype]) -#define n_boardtypes (sizeof(boardtypes)/sizeof(boardtypes[0])) - -static int das08_attach(comedi_device *dev,comedi_devconfig *it); -static int das08_detach(comedi_device *dev); -comedi_driver driver_das08={ - driver_name: "das08", - module: THIS_MODULE, - attach: das08_attach, - detach: das08_detach, - board_name: boardtypes, - num_names: n_boardtypes, - offset: sizeof(struct boardtype_struct), -}; - - - -static int das08_ai(comedi_device *dev,comedi_subdevice *s,comedi_trig *it) -{ - int i,lsb,msb; - int chan; - - chan=CR_CHAN(it->chanlist[0]); - -#ifndef DAVE1 - /* possibly clears A/D queue */ - inb(dev->iobase+LSB_AND_CHNLS); - inb(dev->iobase+MSB_DATA_BYTE); -#endif - - /* set multiplexer */ - devpriv->dio &= ~0xf; - devpriv->dio |= chan; - outb_p(devpriv->dio,dev->iobase+STATUS_REG); - - /* XXX do we have to wait for MUX to settle? how long? */ - - /* how to set gain? */ - - /* trigger conversion */ -#ifndef DAVE3 - outb_p(0,dev->iobase+LSB_AND_CHNLS); -#else - outb_p(0,dev->iobase+MSB_DATA_BYTE); -#endif -#ifdef DAVE2 - /* wait for conversion to take place */ - udelay(25); - - msb=inb(dev->iobase+MSB_DATA_BYTE); - lsb=inb(dev->iobase+LSB_AND_CHNLS); - it->data[0]=(lsb >> 4) | (msb << 4); - return 1; -#else - for(i=0;i<200;i++){ - if(!(inb_p(dev->iobase+STATUS_REG) & EOC)){ - msb=inb(dev->iobase+MSB_DATA_BYTE); - lsb=inb(dev->iobase+LSB_AND_CHNLS); - it->data[0]=(lsb >> 4) | (msb << 4); - return 1; - } - udelay(5); - } -#ifdef DEBUG - rt_printk("das08: ai timeout\n"); -#endif - return -ETIME; -#endif -} - - -static int das08_ao(comedi_device *dev,comedi_subdevice *s,comedi_trig *it) -{ - int lsb,msb; - - lsb=it->data[0]&0xff; - msb=(it->data[0]>>8)&0xf; - if(CR_CHAN(it->chanlist[0])==0){ - outb(lsb,dev->iobase+DA_CHAN0_LSB); - outb(msb,dev->iobase+DA_CHAN0_MSB); - }else{ - outb(lsb,dev->iobase+DA_CHAN1_LSB); - outb(msb,dev->iobase+DA_CHAN1_MSB); - } - return 1; -} - -static int das08_do(comedi_device *dev,comedi_subdevice *s,comedi_trig *it) -{ - do_pack(&s->state,it); - - devpriv->dio &= ~0xf0; - devpriv->dio |= s->state << 4; - outb_p(devpriv->dio,dev->iobase+STATUS_REG); - - return it->n_chan; -} - -static int das08_di(comedi_device *dev,comedi_subdevice *s,comedi_trig *it) -{ - unsigned int bits; - - bits=(inb(dev->iobase+STATUS_REG)>>4)&0x7; - - return di_unpack(bits,it); -} - -static int das08_attach(comedi_device *dev,comedi_devconfig *it) -{ - int i; - comedi_subdevice *s; - int ret; - - dev->iobase=it->options[0]; - printk("comedi%d: das08: 0x%04x",dev->minor,dev->iobase); - if(check_region(dev->iobase,DAS08_SIZE)<0){ - printk(" I/O port conflict\n"); - return -EIO; - } - dev->board_name="das08"; - dev->iosize=DAS08_SIZE; - dev->irq=0; - -#ifdef DEBUG - printk("\nboard fingerprint:\n"); - for(i=0;iiobase+i)); - } -#endif - dev->n_subdevices=5; - if((ret=alloc_subdevices(dev))<0) - return ret; - if((ret=alloc_private(dev,sizeof(das08_private)))<0) - return ret; - - request_region(dev->iobase,DAS08_SIZE,"das08"); - - devpriv->boardtype=0; - - s=dev->subdevices+0; - /* ai */ - s->type=COMEDI_SUBD_AI; - s->subdev_flags=SDF_READABLE; - s->n_chan=8; - s->maxdata=0xfff; - s->range_table=&range_unknown; /* XXX */ - s->trig[0]=das08_ai; - - s=dev->subdevices+1; - /* ao */ - if(this_board.ao_chans>0){ - s->type=COMEDI_SUBD_AO; - s->subdev_flags=SDF_WRITEABLE; - s->n_chan=2; - s->maxdata=0xfff; - s->range_table=&range_unknown; /* XXX */ - }else{ - s->type=COMEDI_SUBD_UNUSED; - } - s->trig[0]=das08_ao; - - s=dev->subdevices+2; - subdev_8255_init(dev,s,NULL,(void *)(dev->iobase+DIO_PORTA)); - - s=dev->subdevices+3; - /* ai */ - s->type=COMEDI_SUBD_DI; - s->subdev_flags=SDF_READABLE; - s->n_chan=3; - s->maxdata=1; - s->range_table=&range_digital; - s->trig[0]=das08_di; - - s=dev->subdevices+4; - /* ai */ - s->type=COMEDI_SUBD_DO; - s->subdev_flags=SDF_WRITEABLE; - s->n_chan=4; - s->maxdata=1; - s->range_table=&range_digital; - s->trig[0]=das08_do; - - devpriv->dio=0; - - - if(this_board.ao_chans>0){ - /* zero AO */ - outb(0,dev->iobase+DA_CHAN0_LSB); - outb(0,dev->iobase+DA_CHAN0_MSB); - outb(0,dev->iobase+DA_CHAN1_LSB); - outb(0,dev->iobase+DA_CHAN1_MSB); - } - - outb_p(0,dev->iobase+STATUS_REG); - -#if 0 - outb_p(0,dev->iobase+DIO_PORTA); - outb_p(0,dev->iobase+DIO_PORTB); - outb_p(0,dev->iobase+DIO_PORTC); -#endif - - printk("\n"); - - return 0; -} - -static int das08_detach(comedi_device *dev) -{ - printk("comedi%d: das08: remove\n",dev->minor); - - release_region(dev->iobase,dev->iosize); - - return 0; -} - -#ifdef MODULE -int init_module(void) -{ - comedi_driver_register(&driver_das08); - - return 0; -} - -void cleanup_module(void) -{ - comedi_driver_unregister(&driver_das08); -} -#endif diff --git a/comedi/drivers/das08jr-old.c b/comedi/drivers/das08jr-old.c deleted file mode 100644 index fd6bc188..00000000 --- a/comedi/drivers/das08jr-old.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - The comedi version of this driver was modified from the - original by ds. - - * das08jr - * ======= - * - * Linux device driver for Computer Boards CIO-DAS08/Jr-AO board. - * - * This board has 8 analog input lines and 2 analog output lines. Additionally - * there are 8 digital outputs. - * These lines are mapped onto minor 0 (digital output), 1 - 8 for analog - * input, and 1 + 2 for analog output. - * - * Copyright (C) 1998 Jochen Küpper - * - * $Id$ - */ - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -/* delay for A/D- and D/A-conversions [us] */ -#define DAS08JR_DELAY ( 30 ) - - -/* Module Name */ -#define DAS08JR_NAME "das08jr" - - - - -/* driver version */ -#if 0 -static const char das08jr_version[] = "PCI-DAS08Jr-AO driver ($Id$)"; -#endif - - - - - -/* Port Offsets */ -#define DAS08JR_SIZE ( 8 ) /* number of ports */ -#define DAS08JR_ANALOG_IN_LSB ( 0 ) /* read */ -#define DAS08JR_ANALOG_IN_MSB ( 1 ) /* read */ -#define DAS08JR_START ( 1 ) -#define DAS08JR_STATUS ( 2 ) /* read */ -#define DAS08JR_MUX ( 2 ) -#define DAS08JR_CONTROL ( 2 ) -#define DAS08JR_DIGITAL_IN ( 3 ) /* read */ -#define DAS08JR_DIGITAL_OUT ( 3 ) -#define DAS08JR_ANALOG_OUT_LSB0 ( 4 ) -#define DAS08JR_ANALOG_OUT_MSB0 ( 5 ) -#define DAS08JR_ANALOG_OUT_LSB1 ( 6 ) -#define DAS08JR_ANALOG_OUT_MSB1 ( 7 ) - - - -/* number of available lines */ -#define DAS08JR_ANALOG_INPUTS ( 8 ) -#define DAS08JR_ANALOG_OUTPUTS ( 2 ) -#define DAS08JR_DIGITAL_LINES ( 1 ) -#define DAS08JR_MAX_LINE ( 8 ) /* we have nine lines starting at zero */ - - -static int das08jr_attach(comedi_device *dev,comedi_devconfig *it); -static int das08jr_detach(comedi_device *dev); -comedi_driver driver_das08jr={ - driver_name: "das08jr", - module: THIS_MODULE, - attach: das08jr_attach, - detach: das08jr_detach, -}; - - -typedef struct{ - int last_do; -}das08jr_priv; -#define devpriv ((das08jr_priv *)dev->private) - -static void release_resources(comedi_device *dev); - - - -/** - * Read digital lines - * - * @author Jochen Küpper - * @version $Id$ - */ -static int das08jr_di(comedi_device * dev,comedi_subdevice *s, comedi_trig * it) -{ - int chan; - int data; - int i; - - data = inb(dev->iobase + DAS08JR_DIGITAL_IN); - - for(i=0;in_chan;i++){ - chan=CR_CHAN(it->chanlist[i]); - it->data[i]=(data>>chan)&1; - } - - return i; -} - - - -/** - * write digital lines - * - * @author Jochen Küpper - * @version $Id$ - */ -static int das08jr_do(comedi_device * dev,comedi_subdevice *s, comedi_trig * it) -{ - int data; - int chan; - int mask; - int i; - - data=devpriv->last_do; - for(i=0;in_chan;i++){ - chan=CR_CHAN(it->chanlist[i]); - mask=1<data[i]) - data|=mask; - } - devpriv->last_do=data; - - outb(data, dev->iobase + DAS08JR_DIGITAL_OUT); - - return i; -} - - - -/** - * Read from analog line - * - * @author Jochen Küpper - * @version $Id$ - */ -static int das08jr_ai(comedi_device * dev, comedi_subdevice *s, comedi_trig * it) -{ - unsigned char lsb, msb; - - /* we alway read one short value */ - - /* start daq */ - - /* XXX do something here to trigger it */ - - /* busy waiting for board to finish */ - udelay( DAS08JR_DELAY ); - - /* read data and put it into user space */ - - lsb = inb(DAS08JR_ANALOG_IN_LSB); - msb = inb(DAS08JR_ANALOG_IN_MSB); - - it->data[0] = (((int) msb) << 4) + (lsb >> 4); - - return 1; -} - - -/*------------------------------*/ - -/** - * Write to writeable analog line. - * - * We do not need to check wether this really is an writeable line, since open - * cares about that an we only get called on lines 1 or 2. - * - * We simply put one value to the output ports, start D/A conversion, and return. - * - * @return On success the number of written bytes ( always 2 ), - * a negative error code otherwise. - * - * @author Jochen Küpper - * @version $Id$ - */ -static int das08jr_ao(comedi_device * dev, comedi_subdevice *s, comedi_trig * it) -{ - unsigned short val = it->data[0]; - int chan=CR_CHAN(it->chanlist[0]); - - if (chan){ - outb((unsigned char) val >> 4, DAS08JR_ANALOG_OUT_MSB1); - outb((unsigned char) val << 4, DAS08JR_ANALOG_OUT_LSB1); - } else { - outb((unsigned char) val >> 4, DAS08JR_ANALOG_OUT_MSB0); - outb((unsigned char) val << 4, DAS08JR_ANALOG_OUT_LSB0); - } - - /* what does this do? */ - outb(0xff, DAS08JR_START); - - return 1; -} - - - - -/** - * Register ports, - * - * @author Jochen Küpper - * @version $Id$ - */ -static int das08jr_attach(comedi_device * dev, comedi_devconfig * it) -{ - int result = 0; - int io; - comedi_subdevice *s; - - printk("comedi%d: das08jr: ", dev->minor); - - io = it->options[0]; -#if 0 - if (0 == io) { - /* should autoprobe here */ - io = DAS08JR_PORT; - } -#endif - if ((result = check_region(io, DAS08JR_SIZE)) < 0) { - printk("Cannot register port memory at %x.\n", io); - return result; - } - request_region(io, DAS08JR_SIZE, DAS08JR_NAME); - - dev->board_name = DAS08JR_NAME; - dev->iobase = io; - - printk("Copyright (C) 1998 Jochen K\"upper.\n"); - - dev->n_subdevices = 3; - if((result=alloc_subdevices(dev))<0) - return result; - if((result=alloc_private(dev,sizeof(das08jr_priv)))<0) - return result; - - s = dev->subdevices + 0; - /* ai subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 8; - s->maxdata = 0xfff; - s->range_table = &range_unknown; - s->trig[0] = das08jr_ai; - - s = dev->subdevices + 1; - /* ao subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITEABLE; - s->n_chan = 2; - s->maxdata = 0xfff; - s->range_table = &range_unknown; - s->trig[0] = das08jr_ao; - - s = dev->subdevices + 2; - /* di subdevice */ - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->trig[0] = das08jr_di; - - s = dev->subdevices + 3; - /* do subdevice */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITEABLE; - s->n_chan = 8; - s->maxdata = 1; - s->range_table = &range_digital; - s->trig[0] = das08jr_do; - - return 0; -} - - -static void release_resources(comedi_device *dev) -{ - if (dev->iobase) - release_region(dev->iobase, DAS08JR_SIZE); -} - -/** - * @author Jochen Küpper - * @version $Id$ - */ -static int das08jr_detach(comedi_device *dev) -{ - printk("comedi%d: das08jr: remove\n", dev->minor); - - release_resources(dev); - - return 0; -} - -#ifdef MODULE -int init_module(void) -{ - comedi_driver_register(&driver_das08jr); - - return 0; -} - -void cleanup_module(void) -{ - comedi_driver_unregister(&driver_das08jr); -} -#endif diff --git a/comedi/drivers/das16-old.c b/comedi/drivers/das16-old.c deleted file mode 100644 index be34fd81..00000000 --- a/comedi/drivers/das16-old.c +++ /dev/null @@ -1,1191 +0,0 @@ -/* - * Copyright (C) 1995,1996 Sam Moore, Warren Jasper - * 1999 David Schleef - * All rights reserved. - * - * This software may be freely copied, modified, and redistributed - * provided that this copyright notice is preserved on all copies. - * - * There is no warranty or other guarantee of fitness of this software - * for any purpose. It is provided solely "as is". - * - */ -/* - * The comedi version of this driver was modified from the original - * by David Schleef. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEBUG - -/* - * Note: Interrupts, when enabled, are generated differently depending - * upon the mode of the board: - * Compatibility mode: Interrupts generated every A/D conversion - * from either pacer clock or soft trigger. - * Enhanced mode: Interrupts generated when FIFO half full - * or when Total_Count = 0. - */ - -/* DT Connection is not supported */ - -#define DT_CONNECT FALSE - - -#define AD_CHANNELS 16 /* 16 Single Ended or 8 Diff. */ -#define DIO_CHANNEL 16 /* dio minor channel number */ - -#define PORT_SIZE 0x14 /* uses 20 bytes of registers */ - - -#define LSB_AND_CHNLS 0 /* A/D Data & Channel Register */ -#define MSB_DATA_BYTE 1 -#define MUX_SCAN_LIMITS 2 /* Channel Mux Scan Limits Register */ -#define DIO_REG 3 /* 4 Bit Digital I/O Register */ -#define STATUS_REG 8 /* Status Register */ -#define CNTRL_REG 9 /* DMA, Interrupt & Trigger Control */ -#define PACER_CLOCK_REG 10 /* Pacer Clock Control Register */ -#define MISC_REG 11 /* Analog Input Range Reg., ETC */ - -#define COUNTERA_0_DATA 12 /* Pacer Clock A Counter 0 Register */ -#define COUNTERA_1_DATA 13 /* Pacer Clock A Counter 1 Register */ -#define COUNTERA_2_DATA 14 /* Pacer Clock A Counter 2 Register */ -#define COUNTERA_CONTROL 15 /* Pacer Clock A Control Register */ - -#define COUNTERB_0_DATA 16 /* Pacer Clock B Counter 0 Register */ -#define COUNTERB_1_DATA 17 /* Pacer Clock B Counter 1 Register */ -#define COUNTERB_2_DATA 18 /* Pacer Clock B Counter 2 Register */ -#define COUNTERB_CONTROL 19 /* Pacer Clock B Control Register */ - - -/************************************************************************* -* STATUS_REG base_reg+8 Status Register * -**************************************************************************/ -#define ADSR_INT 0x10 /* INT=1 External pulse received, INT=0 waiting */ -#define ADSR_MUX 0x20 /* MUX=1 16 Single Ended, MUX=0 8 Differential */ -#define ADSR_UB 0x40 /* U/B=1 Unipolar mode, U/B=0 Bipolar mode */ -#define ADSR_EOC 0x80 /* EOC=1, A/D is busy, EOC=0 free */ - -/************************************************************************* -* CNTRL_REG base_reg+9 DMA, Interrupt & Trigger Control * -**************************************************************************/ -#define CNTL_TS0 0x1 /* TS0=0 External Trigger, TS0=1 Pacer Clock */ -#define CNTL_TS1 0x2 /* TS1=0 Software triggered A/D only */ -#define CNTL_DMA 0x4 /* DMA Disabled = 0, DMA Enabled = 1 */ -#define CNTL_INTE 0x80 /* Interrupts Disabled = 0, Enabled = 1 */ - -/************************************************************************* -* MISC_REG base_reg+11 Range, and Exteded Features * -**************************************************************************/ - -#define ENHANCED_BIT (0x10) /* Enhanced Mode Enabled = 1, Disabled = 0 */ -#define MISC_OVERRUN (0x20) /* No overrun = 0, FIFP buffer full = 1 */ -#define MISC_PRETRIG (0x40) /* Pretrigger Enabled = 1, Disable = 0 */ -#define MISC_DT (0x80) /* DT-Connect Enable = 1, Disable = 0 */ - -/************************************************************************* -* Constants for dealing with the 8254 counters * -**************************************************************************/ - -#define MODE0 0x0 -#define MODE1 0x2 -#define MODE2 0x4 -#define MODE3 0x6 -#define MODE4 0x8 -#define MODE5 0xa - -#define C0 0x00 -#define C1 0x40 -#define C2 0x80 - -//#define LATCH 0x00 -#define LSBONLY 0x10 -#define MSBONLY 0x20 -#define LSBFIRST 0x30 - -#define S0 0x00 -#define S1 0x02 - -#define PACKETSIZE 512 -#define MAX_COUNT 16384 -/* Interrupt context data. Controls interrupt service handler */ - -typedef struct{ - unsigned int ir; /* shifted bits for board 0-7, 10->0, 11->1 */ - unsigned int misc_reg; -} das16_private ; -#define devpriv ((das16_private *)dev->private) - -/* Values kept for each channel. */ - -#if 0 -typedef struct CHANNEL_REC { - int open; /* Is channel device open() */ - int adc_dio_pretrig; /* TRUE = write dio before sampling */ - LONG count; /* Number of samples requested */ - BYTE dio_value; /* DIO value to be written before sampling */ - BYTE mode; /* 0 = Soft Trigger */ - /* 2 = External Trigger */ - /* 4 = Pacer Clock */ - /* 6 = Pacer Clock External Trig Enable */ - BYTE gain; /* Voltage range */ - BYTE lowChan; /* Starting Channel of MUX scan limit */ - BYTE hiChan; /* Ending Channel of MUX scan limit */ -} ChanRec; - -#endif - - - - - - -#if 0 -static WORD base_reg = PORT_MIN; /* base register address */ -static int WordsToRead; /* number of conversions until done */ -static ChanRec *CurrChan = NULL; /* pointer to Chan[minor] */ -static int MajorNumber = DEFAULT_MAJOR_DEV; /* Major number compiled in */ -static ChanRec Chan[DIO_CHANNEL + 1]; /* Channel specific information */ -static BoardRec BoardData; /* Board specific information */ -static WORD KernBuff[MAX_COUNT]; /* Kernel buffer where samples are */ - /* saved before write to user space */ - /* structure for timer data */ -static WORD *KernBuffPtr; /* pointer to kernbuf */ -struct wait_queue *adc0_wait; /* wait semaphore */ -struct timer_list TimerList = -{NULL, NULL, 0, 0, adc0_TimerHandler}; -#endif - -int irq_list[]={ -1, -1, 2, 3, 4, 5, 6, 7, -1, -1, 0, 1, -1, -1, -1, -1 }; - -static int compatibility_read(comedi_device *dev,comedi_trig *it); -static void release_resources(comedi_device *dev); - -static int das16_attach(comedi_device *dev,comedi_devconfig *it); -static int das16_detach(comedi_device *dev); -comedi_driver driver_das16={ - driver_name: "das16", - module: THIS_MODULE, - attach: das16_attach, - detach: das16_detach, -}; - - -/* - interrupt routine - - */ - -static void das16_interrupt(int irq,void *d,struct pt_regs *regs) -{ - -} - - -/* - AD subsystem - - */ - -static void set_gain(comedi_device * dev, int gain) -{ - devpriv->misc_reg &= 0xf0; - devpriv->misc_reg |= (gain << 4); - outb_p(devpriv->misc_reg, dev->iobase + MISC_REG); -} - -static int set_channel_mux(comedi_device * dev, int first_chan, int last_chan) -{ - int channel; - - channel = (last_chan << 4) | first_chan; - outb_p(channel, dev->iobase + MUX_SCAN_LIMITS); - - while ((inb_p(dev->iobase + MISC_REG) & MISC_OVERRUN)) - /* spin */; - - return 0; -} - -static int das16_ai_mode0(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) -{ - int bReg; - - /* Put in Compatibility Mode here just to be safe */ - bReg = inb(dev->iobase + MISC_REG); - outb(bReg & ~ENHANCED_BIT, dev->iobase + MISC_REG); - - /* Set modes for this channel */ - set_gain(dev, CR_RANGE(it->chanlist[0])); - - set_channel_mux(dev, CR_CHAN(it->chanlist[0]), CR_CHAN(it->chanlist[0])); - - compatibility_read(dev,it); - - return 1; -} - - -/* - DIO subsystem - - */ - -static int das16_dio(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) -{ - int data; - - data = inb(dev->iobase + DIO_REG); - - return di_unpack(data, it); -} - -/* - AO subsystem - - */ - -/*************************************************************************** - * - * Loads driver. Called when "insmod adc.o" is invoked on the command line. - * The board is set to IRQ, - * - ***************************************************************************/ - -static int das16_attach(comedi_device *dev,comedi_devconfig *it) -{ - comedi_subdevice *s; - int iobase,irq; - int ret=0; - int chan; - - iobase=it->options[0]; - if (check_region(iobase, PORT_SIZE) != 0) { /* in use */ - printk("comedi%d: das16: Can't allocate region port address 0x%x\n", - dev->minor,iobase); - return -EIO; - } - request_region(iobase, PORT_SIZE, "das16"); - dev->iobase=iobase; - dev->board_name="das16"; - -#if 0 - /* we don't really want to search for boards... */ - /* Look to see if ADC is installed */ - for (base_reg = PORT_MIN; base_reg <= PORT_MAX; base_reg += PORT_STEP) { - if (check_region(base_reg, PORT_SIZE) == 0) { /* not in use */ - request_region(base_reg, PORT_SIZE, "adc"); - if (adc_find(base_reg)) { /* found the board */ - BoardData.base = base_reg; - break; - } else { - release_region(base_reg, PORT_SIZE); - } - } - } - - if (base_reg > PORT_MAX) { - printk("%s: No boards found from address %#x to %#x.\n", - ADAPTER_ID, PORT_MIN, PORT_MAX); - if (unregister_chrdev(MajorNumber, "adc") != 0) { - printk("%s: unregister_chrdev() failed.\n", ADAPTER_ID); - } - return -ENODEV; - } -#endif - - /* Register interrupt handler. */ - - irq=it->options[1]; - - if(irq<0 || irq>=16 || irq_list[irq]<0){ - return -EINVAL; - } - if (comedi_request_irq(irq, das16_interrupt, 0, "das16", dev) == 0) { - return -EIO; - } - dev->irq=irq; - -#if 0 - printk("%s: address=%#x IRQ=%d.", ADAPTER_ID, BoardData.base, BoardData.irq); - printk(" 4/27/95 wjasper@tx.ncsu.edu sam@tx.ncsu.edu\n"); -#endif - - if((ret=alloc_private(dev,sizeof(das16_private)))<0) - return ret; - - dev->n_subdevices=3; - - if((ret=alloc_subdevices(dev))<0) - return ret; - - s=dev->subdevices; - - if (inb(dev->iobase+STATUS_REG) & ADSR_MUX) { - chan = 16; - } else { - chan = 8; - } - /* ai subdevice */ - s->type=COMEDI_SUBD_AI; - s->n_chan=8; - s->trig[0]=das16_ai_mode0; - s->maxdata=0xfff; - - s++; - /* ao subdevice */ - s->type=COMEDI_SUBD_AO; - s->n_chan=2; -#if 0 - s->trig[0]=das16_ao; -#endif - s->maxdata=0xfff; - - s++; - /* dio subdevice */ - s->type=COMEDI_SUBD_DIO; - s->n_chan=8; - s->trig[0]=das16_dio; - s->maxdata=1; - - - /* Set interrupt level on board 2-7, 10->0 and 11->1 */ - devpriv->ir = irq_list[irq] << 4; - - /* ... clearing INTE bit in control reg */ - outb(devpriv->ir, dev->iobase+CNTRL_REG); - - outb(0x0, dev->iobase+MISC_REG); /* Put in compatibility mode */ - - printk("\n"); - - return 0; -} - - -#if 0 -/*************************************************************************** - * - * Test memory locations for exsistance of adc board. - * - ***************************************************************************/ -static int adc_find(WORD base_reg) -{ - -/* - To test if there is a DAS 16/330 board do the following: - 1. write MUX_SCAN_LIMITS register. - 2. read MUX_SCAN_LIMITS register. If fail return FALSE. - 3. read STATUS_REG (bits 0-3). If fail return FALSE. - */ - - BYTE bReg = 0x0; - - bReg = 0xa3; /* set mux from channel 3 to channel 10 */ - outb_p(bReg, MUX_SCAN_LIMITS); /* write to register */ - if (inb_p(MUX_SCAN_LIMITS) != 0xa3) - return FALSE; /* not a 16/330 board */ - if ((inb_p(STATUS_REG) & 0xf) != 0x3) - return FALSE; /* not a 16/330 board */ - bReg = 0xd2; /* set mux from channel 2 to channel 13 */ - outb_p(bReg, MUX_SCAN_LIMITS); /* write to register */ - if (inb_p(MUX_SCAN_LIMITS) != 0xd2) - return FALSE; /* not a 16/330 board */ - if ((inb_p(STATUS_REG) & 0xf) != 0x2) - return FALSE; /* not a 16/330 board */ - return TRUE; /* found it! */ -} -#endif - -/*************************************************************************** - * - * Remove driver. Called when "rmmod adc" is run on the command line. - * - ***************************************************************************/ - -static void release_resources(comedi_device *dev) -{ - if(dev->irq){ - free_irq(dev->irq,dev); - } - - if(dev->iobase) - release_region(dev->iobase, PORT_SIZE); - -} - -static int das16_detach(comedi_device *dev) -{ - release_resources(dev); - - return 0; -} - -#ifdef MODULE -int init_module(void) -{ - comedi_driver_register(&driver_das16); - - return 0; -} - -void cleanup_module(void) -{ - comedi_driver_unregister(&driver_das16); -} -#endif - -#if 0 -static int adc_open(struct inode *iNode, struct file *filePtr) -{ - int minor = MINOR(iNode->i_rdev); - - MOD_INC_USE_COUNT; - - /* - check if device is already open: only one process may read from a - port at a time. There is still the possibility of two processes - reading from two different channels messing things up. However, - the overhead to check for this may not be worth it. - */ - - if (Chan[minor].open == TRUE) { - return -EBUSY; - } - Chan[minor].open = TRUE; /* The device is open */ - Chan[minor].gain = BP_10_00V; /* +/- 10V */ - Chan[minor].mode = filePtr->f_flags; /* set trigger mode */ - Chan[minor].lowChan = minor; /* set MUX scan limits to current channel */ - Chan[minor].hiChan = minor; - - if (Chan[minor].mode == ADC_PACER_EXTERN_TRIG) { - BoardData.pacerReg = 0x1; - } else { - BoardData.pacerReg = 0x0; - } - - outb_p(0x00, STATUS_REG); /* Clear INT bit */ - outb_p(0x0, MISC_REG); /* Put in compatibility mode */ - -#ifdef DEBUG - printk("%s: open(): minor %d mode %d.\n", ADAPTER_ID, minor, Chan[minor].mode); -#endif - return 0; -} -#endif - - - -#if 0 -static int adc_read(struct inode *iNode, struct file *filePtr, char *buf, int count) -{ - int stat; - BYTE bReg; - int minor = MINOR(iNode->i_rdev); - register int i; - - /* Read */ - - switch (Chan[minor].mode) { - - case ADC_SOFT_TRIGGER: -#ifdef DEBUG - printk("adc_read(): Entering ADC_SOFT_TRIGGER mode.\n"); -#endif - if (CompatibilityRead(KernBuff, &Chan[minor])) { - printk("adc_read: SoftTrigRead() failed.\n"); - BoardData.busy = FALSE; - return (-1); - } - break; - - case ADC_EXTERNAL_TRIGGER: -#ifdef DEBUG - printk("adc_read(): Entering ADC_EXTERNAL_TRIGGER mode.\n"); -#endif - if (Chan[minor].count == 1) { /* use compatibility mode */ - if (CompatibilityRead(KernBuff, &Chan[minor])) { - printk("adc_read: CompatibilityRead() failed with ADC_EXTERNAL_TRIGGER.\n"); - BoardData.busy = FALSE; - return (-1); - } - } else { - StopPacer(); /* disable pacer if in pacer mode */ - if (EnhancedRead(KernBuff, &Chan[minor])) { - printk("adc_read: ExternalRead() failed with ADC_EXTERNAL_TRIGGER.\n"); - BoardData.busy = FALSE; - return (-1); - } - } - break; - - case ADC_PACER_CLOCK: -#ifdef DEBUG - printk("adc_read(): Entering ADC_PACER_CLOCK mode.\n"); -#endif - if (Chan[minor].count == 1) { /* use compatibility mode */ - if (CompatibilityRead(KernBuff, &Chan[minor])) { - printk("adc_read: CompatibilityRead() failed with pacer.\n"); - BoardData.busy = FALSE; - return (-1); - } - } else { - StopPacer(); /* disable pacer if in pacer mode */ - outb_p(0x1, PACER_CLOCK_REG); /*IP0 controls counter gate */ - if (EnhancedRead(KernBuff, &Chan[minor])) { - printk("adc_read: EnchancedRead() failed.\n"); - BoardData.busy = FALSE; - return (-1); - } - } - break; - - case ADC_PACER_EXTERN_TRIG: -#ifdef DEBUG - printk("adc_read(): Entering ADC_PACER_EXTERN_TRIG mode.\n"); -#endif - StopPacer(); /* disable pacer if in pacer mode */ - outb_p(0x1, PACER_CLOCK_REG); /*IP0 controls counter gate */ - if (EnhancedRead(KernBuff, &Chan[minor])) { - printk("adc_read: EnchancedRead() with external tigger failed.\n"); - BoardData.busy = FALSE; - return (-1); - } - break; - } - - /* Check that data can be written to file. */ - - if ((stat = verify_area(VERIFY_WRITE, buf, sizeof(WORD) * Chan[minor].count)) != 0) { - printk("adc_read: Failed VERIFY_WRITE.\n"); - BoardData.busy = FALSE; - return -1; - } - /* Write data to user space */ - - for (i = 0; i < Chan[minor].count; i++) { - KernBuff[i] >>= 4; - } - - if (Chan[minor].count == 1) { - put_fs_word(*KernBuff, (WORD *) buf); - } else { - memcpy_tofs(buf, KernBuff, Chan[minor].count * sizeof(WORD)); - } - - BoardData.busy = FALSE; - return (Chan[minor].count); /* return number of samples read */ -} -#endif - - - - -#if 0 -static int dio_write(struct inode *iNode, struct file *filePtr, char *buf, int count) -{ - int minor = MINOR(iNode->i_rdev); - BYTE value; - - if (minor != DIO_CHANNEL) { - printk("dio_write: bad minor number = %d\n", minor); - return -1; - } - cli(); - value = get_fs_byte(buf) & 0xf; - outb_p(value, DIO_REG); - sti(); -#ifdef DEBUG - printk("DIO set to %#x\n", value & 0xf); -#endif - return 1; -} -#endif - - -#if 0 -static int adc_ioctl(struct inode *iNode, struct file *filePtr, unsigned int cmd, LONG arg) -{ - int minor = MINOR(iNode->i_rdev); - - switch (cmd) { - case ADC_SET_GAINS: - Chan[minor].gain = (BYTE) arg; - break; - case ADC_GET_GAINS: - put_fs_long((long) Chan[minor].gain, (long *) arg); - break; - case ADC_SET_PACER_FREQ: - if (BoardData.freq > MAX_FREQ && Chan[minor].mode == ADC_PACER_CLOCK) { - printk("ioctl: BoardData.freq = %ld out of range.\n", BoardData.freq); - return -1; - } else { - BoardData.freq = (LONG) arg; - SetPacerFreq(&BoardData); - LoadPacer(&BoardData); /* load the board frequency now */ - outb_p(BoardData.pacerReg, PACER_CLOCK_REG); - } - break; - case ADC_GET_PACER_FREQ: - put_fs_long(BoardData.freq, (long *) arg); - break; - case ADC_STOP_PACER: - StopPacer(); - break; - case CTR0: - if (arg == 1) { - BoardData.pacerReg |= 0x2; - } else { - BoardData.pacerReg &= ~(0x2); - } - outb_p(BoardData.pacerReg, PACER_CLOCK_REG); - break; - case COUNTER0: - LoadCounter0((LONG) arg); - break; - case ADC_DIO_PRESET: - if (arg == -1) { - Chan[minor].adc_dio_pretrig = FALSE; - } else { - Chan[minor].adc_dio_pretrig = TRUE; - Chan[minor].dio_value = (BYTE) (arg & 0xf); - } - -#ifdef DEBUG - printk("ioctl(ADC_DIO_PRESET): value = %#x\n", Chan[minor].dio_value); -#endif - - break; - case ADC_GET_STATUS: - /* return status register */ - put_fs_long(inb_p(STATUS_REG), (long *) arg); - break; - case SET_MUX_LOW: - Chan[minor].lowChan = (BYTE) arg; - break; - case SET_MUX_HIGH: - Chan[minor].hiChan = (BYTE) arg; - break; - case GET_MUX_SCAN_LIMITS: - put_fs_long(inb_p(MUX_SCAN_LIMITS), (long *) arg); - break; - default: - return (-EINVAL); - break; - } - return 0; -} -#endif - -/*************************************************************************** - * - * Block copy of data samples from data register to kernel memory. - * - ***************************************************************************/ - -#if 0 -inline char * - RegCopy(char *dest, const int reg, int n) -{ - __asm__ __volatile__( - "cld\n\t" - "rep\n\t" - "insw" - : - :"D"(dest), "d"(reg), "c"(n) - :"di", "dx", "cx"); - return dest; -} -#endif - -/*************************************************************************** - * - * Alarm handler to handle situations where an interrupt is missed. - * - ***************************************************************************/ - -#if 0 -static void adc0_TimerHandler(LONG unused) -{ - /* - we should only be here if an interrupt occured while - we were reading half the FIFO - */ - -#ifdef DEBUG - printk("TimerHandler: WordsToRead = %d\n", WordsToRead); -#endif - - cli(); - outb_p(0x30, COUNTERB_CONTROL); /* Set TOTALBAR to 1 */ - RegCopy((char *) KernBuffPtr, base_reg, WordsToRead); - WordsToRead -= WordsToRead; - del_timer(&TimerList); - wake_up_interruptible(&adc0_wait); -} -#endif - -/*************************************************************************** - * - * Interrupt handler used to service enhanced mode(interrupt) read(). - * - ***************************************************************************/ - -#if 0 -static void adc0_ReadInterrupt(int irq) -{ - WORD msb, lsb; - -#ifdef DEBUG - printk("Entering adc0_ReadInterrupt(). mode = %d\n", CurrChan->mode); -#endif - - cli(); - switch (CurrChan->mode) { - - case ADC_SOFT_TRIGGER: - /* Bang! Bang! Method: Force conversion, Conversion forces interrupt */ - lsb = (WORD) inb(base_reg); /* Sample: ADC -> kernel buffer */ - msb = (WORD) inb(MSB_DATA_BYTE); - *KernBuffPtr++ = (msb << 8) | lsb; - WordsToRead--; /* One sample at a time */ - if (!WordsToRead) { - wake_up_interruptible(&adc0_wait); - } else { - outb_p(0x00, STATUS_REG); /* Clear INT bit, allow Interrupt */ - outb_p(0x1, base_reg); /* Force conversion */ - sti(); - } - break; - - case ADC_PACER_CLOCK: - case ADC_EXTERNAL_TRIGGER: - if (CurrChan->count == 1) { - lsb = (WORD) inb(base_reg); /* Sample: ADC -> kernel buffer */ - msb = (WORD) inb(MSB_DATA_BYTE); - *KernBuffPtr++ = (msb << 8) | lsb; - wake_up_interruptible(&adc0_wait); - break; - } - case ADC_PACER_EXTERN_TRIG: - if (WordsToRead > PACKETSIZE) { - RegCopy((char *) KernBuffPtr, base_reg, PACKETSIZE); - WordsToRead -= PACKETSIZE; - KernBuffPtr += PACKETSIZE; - if (WordsToRead < PACKETSIZE) { - TimerList.expires = WordsToRead * 100 / BoardData.freq + 2; - add_timer(&TimerList); - } - outb_p(0x00, STATUS_REG); /* Clear INT bit, allow Interrupt */ - sti(); - } else { - outb_p(0x30, COUNTERB_CONTROL); /* Set TOTALBAR to 1 */ - RegCopy((char *) KernBuffPtr, base_reg, WordsToRead); - del_timer(&TimerList); - WordsToRead -= WordsToRead; - wake_up_interruptible(&adc0_wait); - return; - } - break; - default: - break; - } -} -#endif - -/*************************************************************************** - * - * Handles software/pacer triggered read(). - * - * Bang! Bang! Method: - * - * o Runs in Compatibility Mode - * o Force interrupt by forcing conversion. - * o Get one sample at a time and put it in the kernel buffer(kernBuff). - * o Get chan->count samples - * - ***************************************************************************/ - -static int compatibility_read(comedi_device *dev,comedi_trig *it) -{ - int bReg; - -#ifdef DEBUG - printk("Entering CompatibilityRead().\n"); -#endif - - /* Set interrupt level on board, disable interrupts, and pacer */ - - outb(devpriv->ir, dev->iobase + CNTRL_REG); /* & clear INTE bit in control reg */ - - bReg = inb(dev->iobase+MISC_REG); /* put in compatibility mode */ - outb(bReg & ~ENHANCED_BIT, MISC_REG); - - bReg = inb(dev->iobase + MUX_SCAN_LIMITS); /* Read/Write clears FIFO */ - outb(bReg, dev->iobase + MUX_SCAN_LIMITS); - -#if 0 - /* Prepare global data for parameterless interrupt handler */ - - CurrChan = chan; /* pass chanel number to global */ - KernBuffPtr = KernBuff; /* same with KernBuff */ - WordsToRead = chan->count; - - bReg = inb(CNTRL_REG); /* Turns on ADC interrupts */ - - switch (chan->mode) { - - case ADC_SOFT_TRIGGER: - outb(bReg | CNTL_INTE, CNTRL_REG); - outb(0x00, STATUS_REG); /* Clears INT bit, allow Int. */ - outb(0x1, base_reg); /* Force first conversion */ - break; - - case ADC_EXTERNAL_TRIGGER: - outb(bReg | CNTL_INTE | 0x2, CNTRL_REG); - outb(0x00, STATUS_REG); /* Clears INT bit, allow Int. */ - break; - - case ADC_PACER_CLOCK: - outb(bReg | CNTL_INTE | 0x3, CNTRL_REG); - outb(0x00, STATUS_REG); /* Clears INT bit, allow Int. */ - break; - } - -#endif - outb(devpriv->ir, dev->iobase+CNTRL_REG); /* & clear INTE bit in control reg */ - - return 0; -} - - -/**************************************************************************** - * Set Pacer Clock Frequency - * - * Description: - * Set the counters so that the pacer clock runs at the - * desired frequency. The frequency is generated by dividing - * down a 10 MHz clock, so all frequencies can not be generated. - * This routine calculated the divisor to generate a frequency - * as near as possible to the requested one. It then calculates - * the real frequency and returns it . - ****************************************************************************/ - -#if 0 -static int SetPacerFreq(BoardRec * board) -{ - short unsigned ctr1, ctr2; - LONG product, error; - - /* divide 10Mhz by frequency */ - product = 10000000.0 / board->freq + 0.5; - - /* Now the job is to find two 16 bit numbers, that when multiplied - together are approximately equal to product. Start by setting - one of them, ctr1 to 2 (minimum settable value) and increment until - the error is minimized and ctr2 is less than 32768. - - NOTE: In Mode 2, a value of 1 is illegal! Therefore, crt1 and crt2 - can never be 1. - - */ - - ctr1 = product / 32768; - if (ctr1 < 2) - ctr1 = 2; - ctr2 = product / ctr1; - error = abs(product - (long) ctr2 * (long) ctr1); - - while (error && ctr1 < 32768 && ctr2 > 1) { - ctr1++; - ctr2 = product / ctr1; - error = abs(product - (long) ctr2 * (long) ctr1); - } - - /* the frequency is prime, add 1 to it */ - if (error) { - product++; - ctr1 = product / 32768; - if (ctr1 < 2) - ctr1 = 2; - ctr2 = product / ctr1; - error = abs(product - (long) ctr2 * (long) ctr1); - - while (error && ctr1 < 32768 && ctr2 > 1) { - ctr1++; - ctr2 = product / ctr1; - error = abs(product - (long) ctr2 * (long) ctr1); - } - } - /* we can't have ctr2 equal to 1, or system hangs */ - if (ctr2 == 1) { - ctr2++; - ctr1 /= 2; - } - board->ctr1 = ctr1; - board->ctr2 = ctr2; - board->freq = 10000000.0 / ((long) ctr1 * (long) ctr2) + 0.5; - -#ifdef DEBUG - printk("SetPacerFreq: Pacer Register set to %#x\n", BoardData.pacerReg); -#endif - - return 0; -} -#endif - -#if 0 -/*************************************************************************** - * - * Load two part frequency to pacer counter chip. - * - ***************************************************************************/ - -static void load_pacer(comedi_device *dev,int timer) -{ - unsigned int mask; - unsigned int ctr1,ctr2; - - /* Write the values of ctr1 and ctr2 into counter A1 and A2 */ - - ctr1=timer&0xffff; - ctr2=(timer>>16)&0xffff; - - mask = C2 | MODE2 | LSBFIRST; - outb(mask, dev->iobase+COUNTERA_CONTROL); - - outb(ctr2 & 0xff , dev->iobase + COUNTERA_2_DATA); - outb(ctr2 >> 8, dev->iobase + COUNTERA_2_DATA); - - mask = C1 | MODE2 | LSBFIRST; - outb(mask, dev->iobase+COUNTERA_CONTROL); - - outb(ctr1 & 0xff, dev->iobase + COUNTERA_1_DATA); - outb(ctr1 >> 8, dev->iobase + COUNTERA_1_DATA); - -} - -/*************************************************************************** - * - * Load value into Counter 0 XXXX Mode MSB LSB - * Byte 3 Byte 2 Byte 1 Byte 0 - * - ***************************************************************************/ - -static void load_counter(comedi_device *dev,int mode,int value) -{ - unsigned int mask; - - /* Write the value into Counter 0 Mode 2 */ - - /* the mode is in the thrid byte */ - mask = (0xff & mode) | C0 | LSBFIRST; - outb(mask, dev->iobase + COUNTERA_CONTROL); - -#if 0 - if (mode & 0xff00) /* load control word only */ - return; -#endif - outb(value & 0xff, dev->iobase+COUNTERA_0_DATA); - outb((value>>8)&0xff, dev->iobase+COUNTERA_0_DATA); -} - - -/*************************************************************************** - * - * Turn off pacer timer chip. - * - ***************************************************************************/ - -static void stop_pacer(comedi_device *dev) -{ - unsigned int mask; - - mask = C2 | MODE2 | LSBFIRST; - outb(mask, dev->iobase + COUNTERA_CONTROL); - mask = C1 | MODE2 | LSBFIRST; - outb(mask, dev->iobase + COUNTERA_CONTROL); -} -#endif - -/*************************************************************************** - * - * Handles - * o pacer/counter triggered read() with software start. - * o pacer/counter triggered read() with external start. - * o external triggered read(). - * - * Pacer Method: - * - * o Runs in CIO-DAS 16/330 Enhanced Mode - * o Pacer counter controls frequency of sample conversions - * o Total counter controls number of samples taken - * o Interrupts occur every 512(PACKETSIZE) samples and at last sample - * o Get chan->count samples - * o Samples are saved in kernel buffer(kernBuff) in readInterrupt() - * - ***************************************************************************/ - -#if 0 -static int EnhancedRead(WORD * kernBuff, ChanRec * chan) -{ - BYTE bReg = 0x0; - WORD wReg = 0x0; - -#ifdef DEBUG - printk("Entering EnchacedRead().\n"); -#endif - - cli(); - - /* Set interrupt level on board, disable interrupts, and pacer */ - - outb_p(BoardData.ir, CNTRL_REG); /* & clear INTE bit in control reg */ - - /* - There is some confusion exactly what is going on, but if bit 5 in reg+11 - is equal to 1, the FIFO is over run and we can not write to reg+2, - or what I call MUX_SCAN_LIMITS. So I will try to clear bit 5 - and keep reading until the FIFO is not full. This should not - happen, but Robert Wilhelm (robert@haegar.physiol.med.tu-muenchen.de) - claims that it is. - */ - - /* clear Overrun status bit (bit 5 in reg+11) */ - bReg = (BYTE) inb_p(MISC_REG) & (~MISC_OVERRUN); - outb_p(bReg, MISC_REG); - - do { - bReg = (BYTE) inb_p(MUX_SCAN_LIMITS); /* Read/Write clears FIFO */ - outb_p(bReg, MUX_SCAN_LIMITS); - } - while (((BYTE) inb_p(MISC_REG) & MISC_OVERRUN)); - - bReg = chan->gain | ENHANCED_BIT; /* Set gain and enhanced mode */ - outb(bReg, MISC_REG); - bReg = (BYTE) inb_p(MISC_REG); /* check to make sure we are in */ - if (!(bReg & ENHANCED_BIT)) { /* enhanced mode */ - return (NO_ENHANCED_MODE); - } - do { - bReg = (BYTE) inb_p(MUX_SCAN_LIMITS); /* Read/Write clears FIFO */ - outb_p(bReg, MUX_SCAN_LIMITS); - } - while (((BYTE) inb_p(MISC_REG) & MISC_OVERRUN)); - - if (DT_CONNECT) { - bReg = (BYTE) inb_p(MISC_REG); - bReg |= MISC_DT; - outb_p(bReg, MISC_REG); - } - /* load the Total Counter for the DAS 16/330 */ - - bReg = C0 + MODE0 + LSBFIRST; /* CounterB -> mode 0, DON'T load it */ - outb_p(bReg, COUNTERB_CONTROL); /* Sets output HIGH? */ - - bReg = (BYTE) inb_p(CNTRL_REG); /* S1=0 and S0=0 from above */ - if (chan->mode == ADC_PACER_CLOCK || chan->mode == ADC_PACER_EXTERN_TRIG) { - bReg |= (0x3); /* Set S1=1 and S0=1 Internal Pacer */ - } else { - bReg |= (0x2); /* Set S1=1 and S0=0 External Pacer (A/D Triggering) */ - } - outb_p(bReg, CNTRL_REG); - - wReg = (WORD) (chan->count >> 16); /* get upper word of count */ - if (chan->count & 0xffff) - wReg++; /* increment if lower count is ! zero */ - - bReg = C0 + MODE0 + LSBFIRST; /* Counter -> mode 0, DON'T load it */ - outb_p(bReg, COUNTERB_CONTROL); /* Sets output HIGH? */ - bReg = (BYTE) (wReg & 0xff); /* load the upper word */ - outb_p(bReg, COUNTERB_0_DATA); - bReg = (BYTE) (wReg >> 8); - outb_p(bReg, COUNTERB_0_DATA); - - /* Set the trigger counters. Counter 0 is changed to counter 1 */ - - bReg = C1 + MODE2 + LSBFIRST; /* Ensure clock starts low */ - outb_p(bReg, COUNTERB_CONTROL); - - bReg = C1 + MODE0 + LSBFIRST; /* Make C0 clock high */ - outb_p(bReg, COUNTERB_CONTROL); - - bReg = C1 + MODE2 + LSBFIRST; /* Make C0 clock low */ - outb_p(bReg, COUNTERB_CONTROL); /* complete 1st clock cycle */ - - wReg = (WORD) (chan->count & 0xffff); - - if (wReg == 1) { - wReg++; /* wReg can not be 1 */ - bReg = (BYTE) (wReg & 0xff); /* load the lower word */ - outb_p(bReg, COUNTERB_1_DATA); - bReg = (BYTE) (wReg >> 8); - outb_p(bReg, COUNTERB_1_DATA); - outb_p(0x1, base_reg); /* Force conversion to get count = 1 */ - } else { - bReg = (BYTE) (wReg & 0xff); /* load the lower word */ - outb_p(bReg, COUNTERB_1_DATA); - bReg = (BYTE) (wReg >> 8); - outb_p(bReg, COUNTERB_1_DATA); - } - outb_p(0x1, base_reg); /* Force a conversion */ - outw_p(0x0, COUNTERB_1_DATA); /* rollover mode ?? */ - - if (chan->mode == ADC_PACER_CLOCK || chan->mode == ADC_PACER_EXTERN_TRIG) { - LoadPacer(&BoardData); /* Establish sample frequency */ - } - do { - bReg = (BYTE) inb_p(MUX_SCAN_LIMITS); /* Read/Write clears FIFO */ - outb_p(bReg, MUX_SCAN_LIMITS); - } - while (((BYTE) inb_p(MISC_REG) & MISC_OVERRUN)); - - outb_p(0x00, STATUS_REG); /* Clear INT bit, allow Interrupt */ - - /* Prepare global data for parameterless interrupt handler */ - - CurrChan = chan; /* pass chanel number to global */ - KernBuffPtr = KernBuff; /* same with KernBuff */ - WordsToRead = chan->count; - - bReg = (BYTE) inb_p(CNTRL_REG); /* Enable interrupts */ - bReg |= CNTL_INTE; - outb_p(bReg, CNTRL_REG); - - if (chan->mode == ADC_PACER_CLOCK || chan->mode == ADC_PACER_EXTERN_TRIG) { - outb_p(BoardData.pacerReg, PACER_CLOCK_REG); /* Start pacer begins sampling. */ - } - if (chan->adc_dio_pretrig) { - /* enable interrupts before setting dio bits */ - sti(); - outb_p(chan->dio_value, DIO_REG); - } - interruptible_sleep_on(&adc0_wait); /* Block in wait state */ - - /* turn off interrupts, and trigger control. Leave pacer clock on if enabled */ - outb_p(0x0, CNTRL_REG); - - if (WordsToRead != 0) { - printk("Timing error in EnchacedRead: WordsToRead = %d\n", WordsToRead); - return -1; - } - outb_p(0x00, STATUS_REG); /* Clear INT bit */ - return 0; -} -#endif diff --git a/comedi/drivers/das1600-old.c b/comedi/drivers/das1600-old.c deleted file mode 100644 index 59131571..00000000 --- a/comedi/drivers/das1600-old.c +++ /dev/null @@ -1,497 +0,0 @@ -/* - module/das1600.c - hardware driver for Keithley Metrabyte DAS16, DAS1600 and compatibles - - COMEDI - Linux Control and Measurement Device Interface - Copyright (C) 1999 Anders Blomdell - - 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. - - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include <8255.h> - - -#define DAS1600_BASE_SIZE 16 -#define DAS1600_DIO_SIZE 8 - -#define DAS1600_ADC_Low 0x000 // ADC-Low register -#define DAS1600_ADC_High 0x001 // ADC-High register -#define DAS1600_Channel_Mux 0x002 // Channel MUX register -#define DAS1600_Digital_4_Bit 0x003 // 4-bit digital in/out -#define DAS1600_DA0_Low 0x004 // DA0-Low register -#define DAS1600_DA0_High 0x005 // DA0-High register -#define DAS1600_DA1_Low 0x006 // DA1-Low register -#define DAS1600_DA1_High 0x007 // DA1-High register -#define DAS1600_Status 0x008 // Status register -#define DAS1600_Control 0x009 // DMA, interrupt and trigger control -#define DAS1600_Pacer_Control 0x00a // Pacer clock control -#define DAS1600_Gain_Control 0x00b // Gain control -#define DAS1600_Counter_0 0x00c // 8254 counter 0 data -#define DAS1600_Counter_1 0x00d // 8254 counter 1 data -#define DAS1600_Counter_2 0x00e // 8254 counter 2 data -#define DAS1600_Counter_Control 0x00f // 8254 counter control -#define DAS1600_Port_A 0x400 // 8255 port A -#define DAS1600_Port_B 0x401 // 8255 port B -#define DAS1600_Port_C 0x402 // 8255 port C -#define DAS1600_Control_8255 0x403 // 8255 control -#define DAS1600_Convert_Disable 0x404 // Disable AD conversion -#define DAS1600_Mode_Enable 0x405 // Enable DAS1600 mode -#define DAS1600_Burst_Enable 0x406 // Enable burst mode -#define DAS1600_Burst_Status 0x407 // Burst mode status - -/* Some (or all?) K. M. das16/1600 boards have a bug, apparently due to the - * sample/hold amplifier being slower than the a/d converter. This causes rapid - * succesive a/d conversions on different channels to return wrong values. - * Sampling each channel twice and discarding the first reading seems to get - * around this. Define SLOW_SH_BUG to use this work-around. - * - * It is also reported to be helpful to ground any ai channels that are not in - * use. - * - * Thanks to Anders Blomdell for pointing this out.*/ - -#define SLOW_SH_BUG - -/* Old, 1980's vintage K. M. das16 and das16F cards do not have software - * adjustable input gains. Defining NO_SOFT_RANGE will prevent the driver from - * attmpting to set the gain. - */ - -/*#define NO_SOFT_RANGE*/ - -static void das1600_release_resources(comedi_device * dev); - -static comedi_lrange range_das1601_ai_10_bipolar = { 4, { - RANGE( -10, 10 ), - RANGE( -1, 1 ), - RANGE( -0.1, 0.1 ), - RANGE( -0.01, 0.01 ) -}}; -static comedi_lrange range_das1601_ai_10_unipolar = { 4, { - RANGE( 0, 10 ), - RANGE( 0, 1 ), - RANGE( 0, 0.1 ), - RANGE( 0, 0.01 ) -}}; -static comedi_lrange range_das1602_ai_10_bipolar = { 4, { - RANGE( -10, 10 ), - RANGE( -5, 5 ), - RANGE( -2.5, 2.5 ), - RANGE( -1.25, 1.25 ) -}}; -static comedi_lrange range_das1602_ai_10_unipolar = { 4, { - RANGE( 0, 10 ), - RANGE( 0, 5 ), - RANGE( 0, 2.5 ), - RANGE( 0, 1.25 ) -}}; -static comedi_lrange range_das1600_ao_extern_bipolar = { 1, { - RANGE_ext( -1, 1 ) -}}; -static comedi_lrange range_das1600_ao_extern_unipolar = { 1, { - RANGE_ext( -1, 1 ) -}}; -static comedi_lrange _range_bipolar10 = { 1, { - RANGE( -10, 10 ) -}}; -static comedi_lrange _range_bipolar5 = { 1, { - RANGE( -5, 5 ) -}}; -static comedi_lrange _range_unipolar10 = { 1, { - RANGE( 0, 10 ) -}}; -static comedi_lrange _range_unipolar5 = { 1, { - RANGE( 0, 5 ) -}}; - -typedef struct{ - char *name; - int ai_bits; - comedi_lrange *bip_range; - comedi_lrange *unip_range; -}boardtype; -static boardtype boardtypes[]={ - { "das1601/12", 12, - bip_range: &range_das1601_ai_10_bipolar, - unip_range: &range_das1601_ai_10_unipolar, - }, - { "das1602/12", 12, - bip_range: &range_das1602_ai_10_bipolar, - unip_range: &range_das1602_ai_10_unipolar, - }, - { "das1602/16", 16, - bip_range: &range_das1602_ai_10_bipolar, - unip_range: &range_das1602_ai_10_unipolar, - }, -}; -#define n_boardtypes sizeof(boardtypes)/sizeof(boardtype) -#define this_board ((boardtype *)dev->board_ptr) - -static int das1600_attach(comedi_device *dev,comedi_devconfig *it); -static int das1600_detach(comedi_device *dev); -comedi_driver driver_das1600={ - driver_name: "das1600", - module: THIS_MODULE, - attach: das1600_attach, - detach: das1600_detach, - board_name: boardtypes, - num_names: n_boardtypes, - offset: sizeof(boardtype), -}; - - -typedef struct { - int dma; - int crystal; - enum { - adc_diff, adc_singleended - } adc_mux; - enum { - adc_bipolar10, adc_unipolar10 - } adc_range; - enum { - dac_bipolar10, dac_bipolar5, dac_bipolaruser, - dac_unipolar10, dac_unipolar5, dac_unipolaruser, - } dac_range[2]; - comedi_lrange *range_type_list[2]; -} das1600_private; - -#define devpriv ((das1600_private *)dev->private) - -static comedi_lrange *range_types[] = -{ - &_range_bipolar10, - &_range_bipolar5, - &range_das1600_ao_extern_bipolar, - &_range_unipolar10, - &_range_unipolar5, - &range_das1600_ao_extern_unipolar -}; - -#define DAS1600_TIMEOUT 100 - - -static int das1600_ai(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) -{ - int i; - -#ifdef SLOW_SH_BUG - int j; -#endif - - for(i=0 ; i < it->n_chan ; i++) { - int t, gain, hi, lo, chan; - - if (it->mode != 0) - return -EINVAL; - -#ifndef NO_SOFT_RANGE - gain = CR_RANGE(it->chanlist[i]); - outb(gain, dev->iobase + DAS1600_Gain_Control); -#endif - - chan = CR_CHAN(it->chanlist[i]); - -#ifdef SLOW_SH_BUG - - for (j=0 ; j < 2 ; j++) { - outb(chan + (chan << 4), dev->iobase + DAS1600_Channel_Mux); - outb(0, dev->iobase + DAS1600_ADC_Low); - for (t = 0; t < DAS1600_TIMEOUT; t++) { - if ((inb(dev->iobase + DAS1600_Status) & 0x80) == 0) { - break; - } - } - lo = inb(dev->iobase + DAS1600_ADC_Low); - hi = inb(dev->iobase + DAS1600_ADC_High); - } - -#else - - outb(chan + (chan << 4), dev->iobase + DAS1600_Channel_Mux); - outb(0, dev->iobase + DAS1600_ADC_Low); - for (t = 0; t < DAS1600_TIMEOUT; t++) { - if ((inb(dev->iobase + DAS1600_Status) & 0x80) == 0) { - break; - } - } - lo = inb(dev->iobase + DAS1600_ADC_Low); - hi = inb(dev->iobase + DAS1600_ADC_High); - -#endif - - if (t == DAS1600_TIMEOUT) { - rt_printk("das1600: timeout\n"); - } - - if(this_board->ai_bits==12){ - it->data[i] = (hi << 4) | (lo >> 4); - }else{ - it->data[i] = (hi << 8) | lo; - } - } - return i; -} - - -static int das1600_ao(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) -{ - int i; - for(i=0 ; i < it->n_chan ; i++) { - int chan; - int data; - - chan = CR_CHAN(it->chanlist[i]); - data = it->data[i]; - - outb((data & 0x00f) << 4, dev->iobase + ((chan) ? DAS1600_DA1_Low : DAS1600_DA0_Low)); - outb((data & 0xff0) >> 4, dev->iobase + ((chan) ? DAS1600_DA1_High : DAS1600_DA0_High)); - } - return i; -} - -#if 1 - -static int das1600_di(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) -{ - unsigned int bits; - - bits = inb(dev->iobase + DAS1600_Digital_4_Bit); - - di_unpack(bits,it); - - return it->n_chan; -} - -static int das1600_do(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) -{ - do_pack(&s->state,it); - - /* the outputs are inverted... dumb... (Is this really true? can't - find it in my docs...) */ - outb(s->state ^ 0xff, dev->iobase + DAS1600_Digital_4_Bit); - - return it->n_chan; -} - -#else - -static int das1600_di(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) -{ - int data; - int chan; - int i; - - data= inb(dev->iobase + DAS1600_DI); - for(i=0;in_chan;i++){ - chan=CR_CHAN(it->chanlist[i]); - it->data[i]=(i>>chan)&1; - } - - return i; -} - -static int das1600_do(comedi_device * dev, comedi_subdevice * s, comedi_trig * it) -{ - int data; - int chan; - int mask; - int i; - - data=devpriv->last_do; - - for(i=0;in_chan;i++){ - chan=CR_CHAN(it->chanlist[i]); - mask=1<data[i]) - data |=mask; - } - devpriv->last_do=data; - - /* why are outputs inverted? dumb... */ - outb(data ^ 0xff, dev->iobase + DAS1600_DO); - - return i; -} - -#endif - - -/* - options[0] Board base address - options[1] IRQ - options[2] DMA level select configuration - 0 == no DMA - 1 == DMA level 1 - 3 == DMA level 3 - options[3] Crystal select configuration - 0 == 10 MHz - 1 == 1 MHz - 10 == 10 MHz - options[4] Input configuration - 0 == differential - 1 == single-ended - options[5] Analog input range configuration - 0 == bipolar 10V (-10V -- +10V) - 1 == unipolar 10V (0V -- +10V) - options[6] Analog output 0 range configuration - 0 == bipolar 10V (-10V -- +10V) - 1 == bipolar 5V (-5V -- +5V) - 2 == bipolar user supplied (-xV -- +xV) - 3 == unipolar 10V (0V -- +10V) - 4 == unipolar 5V (0V -- +5V) - 5 == unipolar user supplied (0V -- +xV) - options[7] Analog output 1 range configuration - 0 == bipolar 10V (-10V -- +10V) - 1 == bipolar 5V (-5V -- +5V) - 2 == bipolar user supplied (-xV -- +xV) - 3 == unipolar 10V (0V -- +10V) - 4 == unipolar 5V (0V -- +5V) - 5 == unipolar user supplied (0V -- +xV) - */ - -static int das1600_attach(comedi_device * dev, comedi_devconfig * it) -{ - int result = 1; - comedi_subdevice *s; - - dev->iobase = it->options[0]; - - printk("comedi%d: das1600: 0x%04x ", dev->minor, dev->iobase); - if (check_region(dev->iobase, DAS1600_BASE_SIZE) < 0 || - check_region(dev->iobase + 0x400, DAS1600_DIO_SIZE) < 0) { - printk("I/O port conflict\n"); - return -EIO; - } - request_region(dev->iobase, DAS1600_BASE_SIZE, "das1600"); - request_region(dev->iobase + 0x400, DAS1600_DIO_SIZE, "das1600"); - - dev->board_name=*(char **)dev->board_ptr; - - dev->n_subdevices=5; - - if((result=alloc_private(dev,sizeof(das1600_private)))<0) - return result; - if((result=alloc_subdevices(dev))<0) - return result; - - devpriv->dma = it->options[2]; - devpriv->crystal = it->options[3]; - devpriv->adc_mux = (it->options[4] == 1) ? adc_singleended : adc_diff; - devpriv->adc_range = it->options[5]; - devpriv->dac_range[0] = it->options[6]; - devpriv->dac_range[1] = it->options[7]; - - s = dev->subdevices + 0; - /* ai subdevice */ - s->type = COMEDI_SUBD_AI; - s->subdev_flags = SDF_READABLE|SDF_RT; - s->n_chan = (devpriv->adc_mux == adc_singleended) ? 16 : 8; - s->maxdata = (1<ai_bits)-1; - s->trig[0] = das1600_ai; - switch (devpriv->adc_range) { - case adc_bipolar10: - s->range_table = this_board->bip_range; - break; - case adc_unipolar10: - s->range_table = this_board->unip_range; - break; - } - - s++; - /* ao subdevice */ - s->type = COMEDI_SUBD_AO; - s->subdev_flags = SDF_WRITEABLE|SDF_RT; - s->n_chan = 2; - s->maxdata = 0xfff; - s->trig[0] = das1600_ao; - s->range_table_list = devpriv->range_type_list; - devpriv->range_type_list[0] = range_types[devpriv->dac_range[0]]; - devpriv->range_type_list[1] = range_types[devpriv->dac_range[1]]; - - s++; - /* di subdevice */ - s->type = COMEDI_SUBD_DI; - s->subdev_flags = SDF_READABLE|SDF_RT; - s->trig[0] = das1600_di; - s->n_chan = 4; - s->maxdata = 1; - s->range_table = &range_digital; - - s++; - /* do subdevice */ - s->type = COMEDI_SUBD_DO; - s->subdev_flags = SDF_WRITEABLE|SDF_RT; - s->trig[0] = das1600_do; - s->n_chan = 4; - s->maxdata = 1; - s->range_table = &range_digital; - - s++; - /* 8255 subdevice */ - subdev_8255_init(dev,s,NULL,(void *)(dev->iobase+DAS1600_Port_A)); - - printk("\n"); - return 0; -} - -static void das1600_release_resources(comedi_device * dev) -{ - if (dev->iobase) { - release_region(dev->iobase, DAS1600_BASE_SIZE); - release_region(dev->iobase + 0x400, DAS1600_DIO_SIZE); - } - if (dev->irq) { - free_irq(dev->irq, dev); - } -} - -static int das1600_detach(comedi_device * dev) -{ - printk("comedi%d: das1600: remove\n", dev->minor); - - das1600_release_resources(dev); - - return 0; -} - -#ifdef MODULE -int init_module(void) -{ - comedi_driver_register(&driver_das1600); - - return 0; -} - -void cleanup_module(void) -{ - comedi_driver_unregister(&driver_das1600); -} -#endif -- 2.26.2