From 42185da70360aff9e3b1a69437d954f14263846e Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 5 May 2000 19:22:41 +0000 Subject: [PATCH] added ni_mio_cs.c --- comedi/drivers/ni_mio_cs.c | 493 +++++++++++++++++++++++++++++++++++++ 1 file changed, 493 insertions(+) create mode 100644 comedi/drivers/ni_mio_cs.c diff --git a/comedi/drivers/ni_mio_cs.c b/comedi/drivers/ni_mio_cs.c new file mode 100644 index 00000000..c17e906a --- /dev/null +++ b/comedi/drivers/ni_mio_cs.c @@ -0,0 +1,493 @@ +/* + module/atmio-E.c + Hardware driver for NI PCMCIA MIO E series cards + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1997-2000 David A. Schleef + + 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. + +*/ + +/* + The real guts of the driver is in ni-E.c, which is included + both here and in pcimio-E.c + + + Interrupt support added by Truxton Fulton + + References for specifications: + + 321747b.pdf Register Level Programmer Manual (obsolete) + 321747c.pdf Register Level Programmer Manual (new) + DAQ-STC reference manual + + Other possibly relevant info: + + 320517c.pdf User manual (obsolete) + 320517f.pdf User manual (new) + 320889a.pdf delete + 320906c.pdf maximum signal ratings + 321066a.pdf about 16x + 321791a.pdf discontinuation of at-mio-16e-10 rev. c + 321808a.pdf about at-mio-16e-10 rev P + 321837a.pdf discontinuation of at-mio-16de-10 rev d + 321838a.pdf about at-mio-16de-10 rev N + + ISSUES: + + need to deal with external reference for DAC, and other DAC + properties in board properties + + deal with at-mio-16de-10 revision D to N changes, etc. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_COMEDI_RT +#include +#endif +#include +#include +#include <8255.h> + +#undef Status + +#include +#include +#include +#include +#include + +#undef DEBUG + +#define ATMIO 1 +#undef PCIMIO + +/* + * AT specific setup + */ + +#define NI_SIZE 0x20 + +static struct caldac_struct *type1[]={&caldac_mb88341,NULL,NULL}; +static struct caldac_struct *type2[]={&caldac_dac8800,&caldac_dac8043,NULL}; + +static ni_board ni_boards[]={ + { device_id: 44, + name: "xe-50", + n_adchan: 16, + adbits: 16, + ai_fifo_depth: 8192, + alwaysdither: 0, + gainlkup: ai_gain_16, + ai_speed: 800, + n_aochan: 2, + aobits: 12, + ao_fifo_depth: 2048, + ao_unipolar: 1, + has_8255: 0, + caldac: type1, + }, +}; + + +static int ni_irqpin[]={-1,-1,-1,0,1,2,-1,3,-1,-1,4,5,6,-1,-1,7}; + +#define interrupt_pin(a) (ni_irqpin[(a)]) + +#define IRQ_POLARITY 0 + + +/* How we access registers */ + +#define ni_writew(a,b) (outw((a),(b)+dev->iobase)) +#define ni_readw(a) (inw((a)+dev->iobase)) +#define ni_writeb(a,b) (outb((a),(b)+dev->iobase)) +#define ni_readb(a) (inb((a)+dev->iobase)) +#define ni_writeb_p(a,b) (outb_p((a),(b)+dev->iobase)) +#define ni_readb_p(a) (inb_p((a)+dev->iobase)) + + +/* + * this is how we access windowed registers + */ + +#define win_out(a,b) (ni_writew((b),Window_Address),ni_writew((a),Window_Data)) +#define win_in(b) (ni_writew((b),Window_Address),ni_readw(Window_Data)) +#define win_save() (ni_readw(Window_Address)) +#define win_restore(a) (ni_writew((a),Window_Address)) + + +typedef struct{ + int dio; + int ao0p,ao1p; + int lastchan; + int last_do; + int rt_irq; + int irqmask; + int aimode; + + unsigned short ao_mode1; + unsigned short ao_mode2; + unsigned short ao_mode3; + unsigned short ao_cmd1; + unsigned short ao_cmd2; + unsigned short ao_cmd3; + unsigned short ao_trigger_select; +}ni_private; +#define devpriv ((ni_private *)dev->private) + +static int mio_cs_attach(comedi_device *dev,comedi_devconfig *it); +static int mio_cs_detach(comedi_device *dev); +comedi_driver driver_atmio={ + driver_name: "mio-cs", + module: &__this_module, + attach: mio_cs_attach, + detach: mio_cs_detach, +}; + + +#include "ni_mio_common.c" + + +static int init_stage2(comedi_device *dev,comedi_devconfig *it); +static int ni_getboardtype(comedi_device *dev); + +/* clean up allocated resources */ +int atmio_E_free(comedi_device *dev) +{ + if(dev->iobase) + release_region(dev->iobase,NI_SIZE); + if(dev->irq){ + comedi_free_irq(dev->irq,dev); + } + + return 0; +} + +/* called when driver is removed */ +static int mio_cs_detach(comedi_device *dev) +{ + return atmio_E_free(dev); +} + +void mio_cs_config(dev_link_t *link); +static void cs_release(u_long arg); +static void cs_detach(dev_link_t *); +static int irq_mask; + +static dev_link_t *dev_list = NULL; +static dev_info_t dev_info = "ni_mio_cs"; +static int mio_cs_event(event_t event, int priority, event_callback_args_t *args); + +static void cs_error(client_handle_t handle, int func, int ret) +{ + error_info_t err = { func, ret }; + CardServices(ReportError, handle, &err); +} + +static dev_link_t *cs_attach(void) +{ + dev_link_t *link; + client_reg_t client_reg; + int ret; + + link=kmalloc(sizeof(*link),GFP_KERNEL); + if(!link)return NULL; + memset(link,0,sizeof(*link)); + + link->release.function = &cs_release; + link->release.data = (u_long)link; + + link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + link->io.NumPorts1 = 16; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; + link->irq.IRQInfo2 = irq_mask; + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + link->next = dev_list; + dev_list = link; + + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &mio_cs_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + cs_detach(link); + return NULL; + } + + return link; +} + +static void cs_release(u_long arg) +{ + dev_link_t *link=(void *)arg; + + CardServices(ReleaseConfiguration, link->handle); + CardServices(ReleaseIO, link->handle, &link->io); + CardServices(ReleaseIRQ, link->handle, &link->irq); + + link->state &= ~DEV_CONFIG; +} + +static void cs_detach(dev_link_t *link) +{ + // delete linkp + + + +} + +static int mio_cs_event(event_t event, int priority, event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + + + switch(event){ + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if(link->state & DEV_CONFIG) { + link->release.expires = jiffies+HZ/20; + link->state |= DEV_RELEASE_PENDING; + add_timer(&link->release); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + mio_cs_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* fall through */ + case CS_EVENT_RESET_PHYSICAL: + if(link->state & DEV_CONFIG) + CardServices(ReleaseConfiguration, link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* fall through */ + case CS_EVENT_CARD_RESET: + if(DEV_OK(link)) + CardServices(RequestConfiguration, link->handle, &link->conf); + break; + } + return 0; +} + +static int mio_cs_attach(comedi_device *dev,comedi_devconfig *it) +{ + if(!strcmp("ni_E",it->board_name)){ + printk("comedi: 'ni_E' deprecated. Use 'atmio-E'\n"); + }else if(!strcmp("atmio-E",it->board_name)){ + ; + }else{ + return 0; + } + + return init_stage2(dev,it); +} + + +void mio_cs_config(dev_link_t *link) +{ + client_handle_t handle = link->handle; + tuple_t tuple; + u_short buf[128]; + cisparse_t parse; + int ret; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CONFIG; + + ret=CardServices(GetFirstTuple, handle,&tuple); + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + link->state |= DEV_CONFIG; + +#if 0 + tuple.DesiredTuple = CISTPL_LONGLINK_MFC; + tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; + info->multi (first_tuple(handle, &tuple, &parse) == CS_SUCCESS); +#endif + +#if 0 + tuple.DesiredTuple = CISTPL_MANFID; + if(first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { + info->manfid = le16_to_cpu(buf[0]); + // search + } +#endif + + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + CardServices(GetTupleData, handle, &tuple); + CardServices(ParseTuple, handle, &tuple, &parse); + CardServices(RequestIO, handle, &link->io); + + CardServices(RequestIRQ, handle, &link->irq); + CardServices(RequestConfiguration, handle, &link->conf); + + printk("irq = %d\n",link->irq.AssignedIRQ); + printk("iobase = 0x%04x\n",link->io.BasePort1); + //printk("mfr = 0x%04x\n",link->io.BasePort1); + +} + +static int init_stage2(comedi_device *dev,comedi_devconfig *it) +{ + int ret; + int iobase; + int board; + int irq; + + + /* reserve our I/O region */ + + iobase=0x200; + if(it->options[0])iobase=it->options[0]; + + printk("comedi%d: ni_E: 0x%04x",dev->minor,iobase); + if(check_region(iobase,NI_SIZE)<0){ + printk(" I/O port conflict\n"); + return -EIO; + } + request_region(iobase,NI_SIZE,"ni_E"); + + dev->iobase=iobase; + dev->iosize=NI_SIZE; + + + /* board existence sanity check */ + +#ifdef DEBUG + { + int i; + + printk(" board fingerprint:"); + for(i=0;i<16;i+=2){ + printk(" %04x %02x",inw(dev->iobase+i),inb(dev->iobase+i+1)); + } + } +#endif + + /* get board type */ + + board=ni_getboardtype(dev); + if(board<0)return -EIO; + + printk(" %s",ni_boards[board].name); + dev->board_name=ni_boards[board].name; + + /* irq stuff */ + + irq=it->options[1]; + if(irq!=0){ + if(irq<0 || irq>15 || ni_irqpin[irq]==-1){ + printk(" invalid irq\n"); + return -EINVAL; + } + printk(" ( irq = %d )",irq); + if( (ret=comedi_request_irq(irq,ni_E_interrupt,NI_E_IRQ_FLAGS,"atmio-E",dev))<0 ){ + printk(" irq not available\n"); + return -EINVAL; + } + dev->irq=irq; + } + + /* allocate private area */ + + if((ret=alloc_private(dev,sizeof(ni_private)))<0) + return ret; + + dev->board=board; + + /* generic E series stuff in ni-E.c */ + + if( (ret=ni_E_init(dev,it))<0 ){ + return ret; + } + + return 0; +} + + +static int ni_getboardtype(comedi_device *dev) +{ + int device_id=ni_read_eeprom(dev,511); + int i; + + for(i=0;i