comedi/drivers/ni_6514.c
driver for National Instruments PCI-6514
+ Copyright (C) 2006 Jon Grierson <jd@renko.co.uk>
+ Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net>
+
COMEDI - Linux Control and Measurement Device Interface
Copyright (C) 1999,2002,2003 David A. Schleef <ds@schleef.org>
/*
Driver: ni_65xx.o
Description: National Instruments 65xx static dio boards
-Author: Jon Grierson <jd@renko.co.uk>
+Author: Jon Grierson <jd@renko.co.uk>, Frank Mori Hess <fmhess@users.sourceforge.net>
Status: testing
Devices: [National Instruments] PCI-6514 (ni_65xx), PXI-6514, PXI-6509
Updated: Mon, 17 Jul 2006 16:40:10 +0100
Based on the PCI-6527 driver by ds.
-Should be easily modified for 6509, 651x, 6520, 6521 and 6528
+Should be easily modified for 6509, 651x, 6520, 6521 and 6528 if you
+send in the pci device id of your board.
*/
*/
+#define _GNU_SOURCE
#define DEBUG 1
#define DEBUG_FLAGS
-
#include <linux/comedidev.h>
#include "mite.h"
#define NI6514_DIO_SIZE 4096
#define NI6514_MITE_SIZE 4096
+#define NI_65XX_MAX_NUM_PORTS 12
+static const unsigned ni_65xx_channels_per_port = 8;
+static const unsigned ni_65xx_port_offset = 0x10;
-#define Port_Register(x) (0x40+(x))
+static inline unsigned Port_Data(unsigned port)
+{
+ return 0x40 + port * ni_65xx_port_offset;
+}
+static inline unsigned Port_Select(unsigned port)
+{
+ return 0x41 + port * ni_65xx_port_offset;
+}
+static inline unsigned Rising_Edge_Detection_Enable(unsigned port)
+{
+ return 0x42 + port * ni_65xx_port_offset;
+}
+static inline unsigned Falling_Edge_Detection_Enable(unsigned port)
+{
+ return 0x43 + port * ni_65xx_port_offset;
+}
+static inline unsigned Filter_Enable(unsigned port)
+{
+ return 0x44 + port * ni_65xx_port_offset;
+}
#define ID_Register 0x00
#define Clear_Register 0x01
#define ClrOverflow 0x04
#define Filter_Interval 0x08
-#define Filter_Enable(x) (0x44+(x))
#define Change_Status 0x02
#define MasterInterruptStatus 0x04
#define OverflowIntEnable 0x02
#define EdgeIntEnable 0x01
-#define Rising_Edge_Detection_Enable(x) (0x42+(x))
-#define Falling_Edge_Detection_Enable(x) (0x43+(x))
-
-
-
-static int ni6514_attach(comedi_device *dev,comedi_devconfig *it);
-static int ni6514_detach(comedi_device *dev);
-static comedi_driver driver_ni6514={
+static int ni_65xx_attach(comedi_device *dev,comedi_devconfig *it);
+static int ni_65xx_detach(comedi_device *dev);
+static comedi_driver driver_ni_65xx={
driver_name: "ni_65xx",
module: THIS_MODULE,
- attach: ni6514_attach,
- detach: ni6514_detach,
+ attach: ni_65xx_attach,
+ detach: ni_65xx_detach,
};
-COMEDI_INITCLEANUP(driver_ni6514);
+COMEDI_INITCLEANUP(driver_ni_65xx);
typedef struct{
int dev_id;
- char *name;
-}ni6514_board;
-static ni6514_board ni6514_boards[] = {
+ const char *name;
+ unsigned num_dio_ports;
+ unsigned num_di_ports;
+ unsigned num_do_ports;
+ unsigned invert_outputs : 1;
+}ni_65xx_board;
+static ni_65xx_board ni_65xx_boards[] = {
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6509",
+ num_dio_ports: 12
+ },
{
dev_id: 0x1710,
name: "pxi-6509",
+ num_dio_ports: 12
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6510",
+ num_di_ports: 4
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6511",
+ num_di_ports: 8
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pxi-6511",
+ num_di_ports: 8
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6512",
+ num_do_ports: 8
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pxi-6512",
+ num_do_ports: 8
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6513",
+ num_do_ports: 8
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pxi-6513",
+ num_do_ports: 8
},
{
dev_id: 0x7088,
name: "pci-6514",
+ num_di_ports: 4,
+ num_do_ports: 4,
+ invert_outputs: 1
},
{
dev_id: 0x70CD,
name: "pxi-6514",
+ num_di_ports: 4,
+ num_do_ports: 4,
+ invert_outputs: 1
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6515",
+ num_di_ports: 4,
+ num_do_ports: 4,
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pxi-6515",
+ num_di_ports: 4,
+ num_do_ports: 4,
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6516",
+ num_do_ports: 4,
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6517",
+ num_do_ports: 4,
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6518",
+ num_di_ports: 2,
+ num_do_ports: 2,
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6519",
+ num_di_ports: 2,
+ num_do_ports: 2,
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6520",
+ num_di_ports: 1,
+ num_do_ports: 1,
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6521",
+ num_di_ports: 1,
+ num_do_ports: 1,
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pxi-6521",
+ num_di_ports: 1,
+ num_do_ports: 1,
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pci-6528",
+ num_di_ports: 3,
+ num_do_ports: 3,
+ },
+ {
+ dev_id: 0x0, //XXX
+ name: "pxi-6528",
+ num_di_ports: 3,
+ num_do_ports: 3,
},
};
-#define n_ni6514_boards (sizeof(ni6514_boards)/sizeof(ni6514_boards[0]))
-#define this_board ((ni6514_board *)dev->board_ptr)
+#define n_ni_65xx_boards (sizeof(ni_65xx_boards)/sizeof(ni_65xx_boards[0]))
+static inline const ni_65xx_board* board(comedi_device *dev)
+{
+ return dev->board_ptr;
+}
+static inline unsigned ni_65xx_port_by_channel(unsigned channel)
+{
+ return channel / ni_65xx_channels_per_port;
+}
+static inline unsigned ni_65xx_total_num_ports(const ni_65xx_board *board)
+{
+ return board->num_dio_ports + board->num_di_ports + board->num_do_ports;
+}
-static struct pci_device_id ni6514_pci_table[] __devinitdata = {
+static struct pci_device_id ni_65xx_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_NATINST, 0x1710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_NATINST, 0x7088, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ PCI_VENDOR_ID_NATINST, 0x70CD, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0 }
};
-MODULE_DEVICE_TABLE(pci, ni6514_pci_table);
+MODULE_DEVICE_TABLE(pci, ni_65xx_pci_table);
typedef struct{
struct mite_struct *mite;
unsigned int filter_interval;
- unsigned int filter_enable;
-}ni6514_private;
-#define devpriv ((ni6514_private *)dev->private)
-
-static int ni6514_find_device(comedi_device *dev,int bus,int slot);
-
-
-static int ni6514_di_insn_config(comedi_device *dev,comedi_subdevice *s,
- comedi_insn *insn,lsampl_t *data)
+ unsigned short filter_enable[NI_65XX_MAX_NUM_PORTS];
+ unsigned short output_bits[NI_65XX_MAX_NUM_PORTS];
+ unsigned short dio_direction[NI_65XX_MAX_NUM_PORTS];
+}ni_65xx_private;
+static inline ni_65xx_private* private(comedi_device *dev)
{
- int chan = CR_CHAN(insn->chanspec);
- unsigned int interval;
-
- if(insn->n!=2)return -EINVAL;
+ return dev->private;
+}
- if(data[0] != INSN_CONFIG_FILTER)return -EINVAL;
+typedef struct
+{
+ unsigned base_port;
+}ni_65xx_subdevice_private;
+static inline ni_65xx_subdevice_private* sprivate(comedi_subdevice *subdev)
+{
+ return subdev->private;
+}
+static ni_65xx_subdevice_private* ni_65xx_alloc_subdevice_private(void)
+{
+ ni_65xx_subdevice_private *subdev_private = kmalloc(sizeof(ni_65xx_subdevice_private), GFP_KERNEL);
+ if(subdev_private == NULL) return NULL;
+ memset(subdev_private, 0, sizeof(ni_65xx_subdevice_private));
+ return subdev_private;
+}
- if(data[1]){
- interval = (data[1]+100)/200;
- data[1] = interval*200;
+static int ni_65xx_find_device(comedi_device *dev,int bus,int slot);
- if(interval!=devpriv->filter_interval){
- writeb(interval&0x000fffff, devpriv->mite->daq_io_addr + Filter_Interval); /* FIXME 32 bit reg - mask possibly wrong??? */
+static int ni_65xx_config_filter(comedi_device *dev, comedi_subdevice *s,
+ comedi_insn *insn, lsampl_t *data)
+{
+ const unsigned chan = CR_CHAN(insn->chanspec);
+ const unsigned port = sprivate(s)->base_port + ni_65xx_port_by_channel(chan);
- devpriv->filter_interval = interval;
+ if(insn->n != 2)return -EINVAL;
+ if(data[0] != INSN_CONFIG_FILTER) return -EINVAL;
+ if(data[1])
+ {
+ static const unsigned filter_resolution_ns = 200;
+ static const unsigned max_filter_interval = 0xfffff;
+ unsigned interval = (data[1] + (filter_resolution_ns / 2)) / filter_resolution_ns;
+ if(interval > max_filter_interval) interval = max_filter_interval;
+ data[1] = interval * filter_resolution_ns;
+
+ if(interval != private(dev)->filter_interval)
+ {
+ writeb(interval, private(dev)->mite->daq_io_addr + Filter_Interval);
+ private(dev)->filter_interval = interval;
}
- devpriv->filter_enable |= 1<<chan;
+ private(dev)->filter_enable[port] |= 1 << (chan % ni_65xx_channels_per_port);
}else{
- devpriv->filter_enable &= ~(1<<chan);
+ private(dev)->filter_enable[port] &= ~(1 << (chan % ni_65xx_channels_per_port));
}
- writeb(devpriv->filter_enable, devpriv->mite->daq_io_addr + Filter_Enable(0));
- writeb(devpriv->filter_enable>>8, devpriv->mite->daq_io_addr + Filter_Enable(0x10));
- writeb(devpriv->filter_enable>>16, devpriv->mite->daq_io_addr + Filter_Enable(0x20));
- writeb(devpriv->filter_enable>>24, devpriv->mite->daq_io_addr + Filter_Enable(0x30));
+ writeb(private(dev)->filter_enable[port], private(dev)->mite->daq_io_addr + Filter_Enable(port));
return 2;
}
-static int ni6514_di_insn_bits(comedi_device *dev,comedi_subdevice *s,
+static int ni_65xx_dio_insn_config(comedi_device *dev,comedi_subdevice *s,
comedi_insn *insn,lsampl_t *data)
{
- if(insn->n!=2)return -EINVAL;
-
- data[1] = readb(devpriv->mite->daq_io_addr+Port_Register(0));
- data[1] |= readb(devpriv->mite->daq_io_addr+Port_Register(0x10))<<8;
- data[1] |= readb(devpriv->mite->daq_io_addr+Port_Register(0x20))<<16;
- data[1] |= readb(devpriv->mite->daq_io_addr+Port_Register(0x30))<<24;
-
- return 2;
+ if(insn->n < 1) return -EINVAL;
+ unsigned port = sprivate(s)->base_port + ni_65xx_port_by_channel(CR_CHAN(insn->chanspec));
+ switch(data[0])
+ {
+ case INSN_CONFIG_FILTER:
+ return ni_65xx_config_filter(dev, s, insn, data);
+ break;
+ case INSN_CONFIG_DIO_OUTPUT:
+ if(s->type != COMEDI_SUBD_DIO) return -EINVAL;
+ private(dev)->dio_direction[port] = COMEDI_OUTPUT;
+ writeb(1, private(dev)->mite->daq_io_addr + Port_Select(port));
+ return 1;
+ break;
+ case INSN_CONFIG_DIO_INPUT:
+ if(s->type != COMEDI_SUBD_DIO) return -EINVAL;
+ private(dev)->dio_direction[port] = COMEDI_INPUT;
+ writeb(0, private(dev)->mite->daq_io_addr + Port_Select(port));
+ return 1;
+ break;
+ case INSN_CONFIG_DIO_QUERY:
+ if(s->type != COMEDI_SUBD_DIO) return -EINVAL;
+ data[1] = private(dev)->dio_direction[port];
+ return insn->n;
+ break;
+ default:
+ break;
+ }
+ return -EINVAL;
}
-static int ni6514_do_insn_bits(comedi_device *dev,comedi_subdevice *s,
+static int ni_65xx_dio_insn_bits(comedi_device *dev,comedi_subdevice *s,
comedi_insn *insn,lsampl_t *data)
{
- if(insn->n!=2)return -EINVAL;
- if(data[0]){
- s->state &= ~data[0];
- s->state |= (data[0]&data[1]);
-
- /* The open relay state on the board cooresponds to 1,
- * but in Comedi, it is represented by 0. */
- if(data[0]&0x000000ff){
- writeb((s->state^0xff),devpriv->mite->daq_io_addr+Port_Register(0x40));
- }
- if(data[0]&0x0000ff00){
- writeb((s->state>>8)^0xff,devpriv->mite->daq_io_addr+Port_Register(0x50));
- }
- if(data[0]&0x00ff0000){
- writeb((s->state>>16)^0xff,devpriv->mite->daq_io_addr+Port_Register(0x60));
- }
- if(data[0]&0xff000000){
- writeb((s->state>>24)^0xff,devpriv->mite->daq_io_addr+Port_Register(0x70));
+ const unsigned elements_per_bitfield = 2;
+ if(insn->n % elements_per_bitfield) return -EINVAL;
+ const unsigned num_bitfields = insn->n / elements_per_bitfield;
+ unsigned i;
+ for(i = 0; i < num_bitfields; ++i)
+ {
+ const unsigned ports_per_bitfield = 4;
+ const unsigned array_offset = i * elements_per_bitfield;
+ data[array_offset + 1] = 0;
+ unsigned j;
+ for(j = 0; j < ports_per_bitfield; ++j)
+ {
+ const unsigned port = sprivate(s)->base_port + i * ports_per_bitfield + j;
+ if(port >= ni_65xx_total_num_ports(board(dev))) break;
+ const unsigned port_mask = (data[array_offset] >> (j * 8)) & 0xff;
+ if(port_mask)
+ {
+ private(dev)->output_bits[port] &= ~port_mask;
+ private(dev)->output_bits[port] |= (data[array_offset + 1] >> (j * 8)) & port_mask;
+ unsigned bits = private(dev)->output_bits[port];
+ if(board(dev)->invert_outputs) bits = ~bits;
+ writeb(bits, private(dev)->mite->daq_io_addr + Port_Data(port));
+ }
+ data[array_offset + 1] |= readb(private(dev)->mite->daq_io_addr + Port_Data(port));
}
}
- data[1] = s->state;
-
- return 2;
+ return insn->n;
}
-static irqreturn_t ni6514_interrupt(int irq, void *d, struct pt_regs *regs)
+static irqreturn_t ni_65xx_interrupt(int irq, void *d, struct pt_regs *regs)
{
comedi_device *dev = d;
comedi_subdevice *s = dev->subdevices + 2;
unsigned int status;
- status = readb(devpriv->mite->daq_io_addr + Change_Status);
+ status = readb(private(dev)->mite->daq_io_addr + Change_Status);
if((status & MasterInterruptStatus) == 0) return IRQ_NONE;
if((status & EdgeStatus) == 0) return IRQ_NONE;
- writeb(ClrEdge | ClrOverflow, devpriv->mite->daq_io_addr + Clear_Register);
+ writeb(ClrEdge | ClrOverflow, private(dev)->mite->daq_io_addr + Clear_Register);
comedi_buf_put(s->async, 0);
s->async->events |= COMEDI_CB_EOS;
return IRQ_HANDLED;
}
-static int ni6514_intr_cmdtest(comedi_device *dev,comedi_subdevice *s,
+static int ni_65xx_intr_cmdtest(comedi_device *dev,comedi_subdevice *s,
comedi_cmd *cmd)
{
int err=0;
return 0;
}
-static int ni6514_intr_cmd(comedi_device *dev,comedi_subdevice *s)
+static int ni_65xx_intr_cmd(comedi_device *dev,comedi_subdevice *s)
{
//comedi_cmd *cmd = &s->async->cmd;
- writeb(ClrEdge|ClrOverflow, devpriv->mite->daq_io_addr + Clear_Register);
+ writeb(ClrEdge|ClrOverflow, private(dev)->mite->daq_io_addr + Clear_Register);
writeb(FallingEdgeIntEnable|RisingEdgeIntEnable|
MasterInterruptEnable|EdgeIntEnable,
- devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+ private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
return 0;
}
-static int ni6514_intr_cancel(comedi_device *dev,comedi_subdevice *s)
+static int ni_65xx_intr_cancel(comedi_device *dev,comedi_subdevice *s)
{
- writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+ writeb(0x00, private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
return 0;
}
-static int ni6514_intr_insn_bits(comedi_device *dev, comedi_subdevice *s,
+static int ni_65xx_intr_insn_bits(comedi_device *dev, comedi_subdevice *s,
comedi_insn *insn, lsampl_t *data)
{
if(insn->n < 1)return -EINVAL;
return 2;
}
-static int ni6514_intr_insn_config(comedi_device *dev, comedi_subdevice *s,
+static int ni_65xx_intr_insn_config(comedi_device *dev, comedi_subdevice *s,
comedi_insn *insn, lsampl_t *data)
{
if(insn->n < 1)return -EINVAL;
if(data[0] != INSN_CONFIG_CHANGE_NOTIFY)return -EINVAL;
- writeb(data[1], devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(0));
- writeb(data[1]>>8, devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(0x10));
- writeb(data[1]>>16, devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(0x20));
- writeb(data[1]>>24, devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(0x30));
+ writeb(data[1], private(dev)->mite->daq_io_addr + Rising_Edge_Detection_Enable(0));
+ writeb(data[1]>>8, private(dev)->mite->daq_io_addr + Rising_Edge_Detection_Enable(0x10));
+ writeb(data[1]>>16, private(dev)->mite->daq_io_addr + Rising_Edge_Detection_Enable(0x20));
+ writeb(data[1]>>24, private(dev)->mite->daq_io_addr + Rising_Edge_Detection_Enable(0x30));
- writeb(data[2], devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(0));
- writeb(data[2]>>8, devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(0x10));
- writeb(data[2]>>16, devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(0x20));
- writeb(data[2]>>24, devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(0x30));
+ writeb(data[2], private(dev)->mite->daq_io_addr + Falling_Edge_Detection_Enable(0));
+ writeb(data[2]>>8, private(dev)->mite->daq_io_addr + Falling_Edge_Detection_Enable(0x10));
+ writeb(data[2]>>16, private(dev)->mite->daq_io_addr + Falling_Edge_Detection_Enable(0x20));
+ writeb(data[2]>>24, private(dev)->mite->daq_io_addr + Falling_Edge_Detection_Enable(0x30));
return 2;
}
-static int ni6514_attach(comedi_device *dev,comedi_devconfig *it)
+static int ni_65xx_attach(comedi_device *dev,comedi_devconfig *it)
{
comedi_subdevice *s;
int ret;
- printk("comedi%d: ni6514:",dev->minor);
+ printk("comedi%d: ni_65xx:",dev->minor);
- if((ret=alloc_private(dev,sizeof(ni6514_private)))<0)
+ if((ret=alloc_private(dev,sizeof(ni_65xx_private)))<0)
return ret;
- ret=ni6514_find_device(dev,it->options[0],it->options[1]);
+ ret=ni_65xx_find_device(dev,it->options[0],it->options[1]);
if(ret<0)return ret;
- ret = mite_setup(devpriv->mite);
+ ret = mite_setup(private(dev)->mite);
if(ret < 0)
{
printk("error setting up mite\n");
return ret;
}
- dev->board_name=this_board->name;
- dev->irq=mite_irq(devpriv->mite);
+ dev->board_name = board(dev)->name;
+ dev->irq = mite_irq(private(dev)->mite);
printk(" %s",dev->board_name);
- printk(" ID=0x%02x", readb(devpriv->mite->daq_io_addr + ID_Register));
+ printk(" ID=0x%02x", readb(private(dev)->mite->daq_io_addr + ID_Register));
- if((ret=alloc_subdevices(dev,3))<0)
+ if((ret=alloc_subdevices(dev, 4)) < 0)
return ret;
- s=dev->subdevices+0;
- s->type=COMEDI_SUBD_DI;
- s->subdev_flags=SDF_READABLE;
- s->n_chan=32;
- s->range_table=&range_digital;
- s->maxdata=1;
- s->insn_config = ni6514_di_insn_config;
- s->insn_bits = ni6514_di_insn_bits;
-
- s=dev->subdevices+1;
- s->type=COMEDI_SUBD_DO;
- s->subdev_flags=SDF_READABLE|SDF_WRITABLE;
- s->n_chan=32;
- s->range_table=&range_digital;
- s->maxdata=1;
- s->insn_bits = ni6514_do_insn_bits;
+ s = dev->subdevices + 0;
+ if(board(dev)->num_di_ports)
+ {
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE;
+ s->n_chan = board(dev)->num_di_ports * ni_65xx_channels_per_port;
+ s->range_table = &range_digital;
+ s->maxdata = 1;
+ s->insn_config = ni_65xx_dio_insn_config;
+ s->insn_bits = ni_65xx_dio_insn_bits;
+ s->private = ni_65xx_alloc_subdevice_private();
+ if(s->private == NULL) return -ENOMEM;
+ sprivate(s)->base_port = 0;
+ }else
+ {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ s=dev->subdevices + 1;
+ if(board(dev)->num_do_ports)
+ {
+ s->type = COMEDI_SUBD_DO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = board(dev)->num_di_ports * ni_65xx_channels_per_port;
+ s->range_table = &range_digital;
+ s->maxdata = 1;
+ s->insn_bits = ni_65xx_dio_insn_bits;
+ s->private = ni_65xx_alloc_subdevice_private();
+ if(s->private == NULL) return -ENOMEM;
+ sprivate(s)->base_port = board(dev)->num_di_ports;
+ }else
+ {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
s=dev->subdevices + 2;
+ if(board(dev)->num_dio_ports)
+ {
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = board(dev)->num_dio_ports * ni_65xx_channels_per_port;
+ s->range_table=&range_digital;
+ s->maxdata=1;
+ s->insn_config = ni_65xx_dio_insn_config;
+ s->insn_bits = ni_65xx_dio_insn_bits;
+ s->private = ni_65xx_alloc_subdevice_private();
+ if(s->private == NULL) return -ENOMEM;
+ sprivate(s)->base_port = 0;
+ }else
+ {
+ s->type = COMEDI_SUBD_UNUSED;
+ }
+
+ s=dev->subdevices + 3;
dev->read_subdev = s;
s->type=COMEDI_SUBD_DI;
s->subdev_flags=SDF_READABLE;
s->n_chan=1;
s->range_table=&range_unknown;
s->maxdata=1;
- s->do_cmdtest = ni6514_intr_cmdtest;
- s->do_cmd = ni6514_intr_cmd;
- s->cancel = ni6514_intr_cancel;
- s->insn_bits = ni6514_intr_insn_bits;
- s->insn_config = ni6514_intr_insn_config;
-
- writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(0));
- writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(0x10));
- writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(0x20));
- writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(0x30));
-
- writeb(0x00,devpriv->mite->daq_io_addr+Port_Register(0x40));
- writeb(0x00,devpriv->mite->daq_io_addr+Port_Register(0x50));
- writeb(0x00,devpriv->mite->daq_io_addr+Port_Register(0x60));
- writeb(0x00,devpriv->mite->daq_io_addr+Port_Register(0x70));
-
+ s->do_cmdtest = ni_65xx_intr_cmdtest;
+ s->do_cmd = ni_65xx_intr_cmd;
+ s->cancel = ni_65xx_intr_cancel;
+ s->insn_bits = ni_65xx_intr_insn_bits;
+ s->insn_config = ni_65xx_intr_insn_config;
+
+ unsigned i;
+ for(i = 0; i < ni_65xx_total_num_ports(board(dev)); ++i)
+ {
+ writeb(0x00, private(dev)->mite->daq_io_addr + Filter_Enable(i));
+ writeb(0x00,private(dev)->mite->daq_io_addr + Port_Data(i));
+ }
writeb(ClrEdge|ClrOverflow,
- devpriv->mite->daq_io_addr + Clear_Register);
- writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+ private(dev)->mite->daq_io_addr + Clear_Register);
+ writeb(0x00, private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
/* Set filter interval to 0 (32bit reg) */
- writeb(0x00000000, devpriv->mite->daq_io_addr + Filter_Interval);
+ writeb(0x00000000, private(dev)->mite->daq_io_addr + Filter_Interval);
- ret=comedi_request_irq(dev->irq,ni6514_interrupt,SA_SHIRQ,"ni6514",dev);
+ ret=comedi_request_irq(dev->irq,ni_65xx_interrupt,SA_SHIRQ,"ni_65xx",dev);
if(ret<0){
dev->irq=0;
printk(" irq not available");
return 0;
}
-static int ni6514_detach(comedi_device *dev)
+static int ni_65xx_detach(comedi_device *dev)
{
- if(devpriv && devpriv->mite && devpriv->mite->daq_io_addr){
- writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
+ if(private(dev) && private(dev)->mite && private(dev)->mite->daq_io_addr){
+ writeb(0x00, private(dev)->mite->daq_io_addr + Master_Interrupt_Control);
}
if(dev->irq){
comedi_free_irq(dev->irq,dev);
}
- if(devpriv && devpriv->mite){
- mite_unsetup(devpriv->mite);
+ if(private(dev))
+ {
+ unsigned i;
+ for(i = 0; i < dev->n_subdevices; ++i)
+ {
+ if(dev->subdevices[i].private)
+ {
+ kfree(dev->subdevices[i].private);
+ dev->subdevices[i].private = NULL;
+ }
+ }
+ if(private(dev)->mite){
+ mite_unsetup(private(dev)->mite);
+ }
}
-
return 0;
}
-static int ni6514_find_device(comedi_device *dev,int bus,int slot)
+static int ni_65xx_find_device(comedi_device *dev,int bus,int slot)
{
struct mite_struct *mite;
int i;
slot!=PCI_SLOT(mite->pcidev->devfn))
continue;
}
- for(i=0;i<n_ni6514_boards;i++){
- if(mite_device_id(mite)==ni6514_boards[i].dev_id){
- dev->board_ptr = ni6514_boards + i;
- devpriv->mite=mite;
+ for(i=0;i<n_ni_65xx_boards;i++){
+ if(mite_device_id(mite)==ni_65xx_boards[i].dev_id){
+ dev->board_ptr = ni_65xx_boards + i;
+ private(dev)->mite=mite;
return 0;
}
}