adl_pci6208.c revision c1b31c44a38e2b5153193680e4bee4856b3307e1
18b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/*
28b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    comedi/drivers/adl_pci6208.c
38b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
48b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    Hardware driver for ADLink 6208 series cards:
58b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	card	     | voltage output    | current output
68b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	-------------+-------------------+---------------
78b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	PCI-6208V    |  8 channels       | -
88b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	PCI-6216V    | 16 channels       | -
98b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	PCI-6208A    |  8 channels       | 8 channels
108b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
118b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    COMEDI - Linux Control and Measurement Device Interface
128b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
138b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
148b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    This program is free software; you can redistribute it and/or modify
158b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    it under the terms of the GNU General Public License as published by
168b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    the Free Software Foundation; either version 2 of the License, or
178b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    (at your option) any later version.
188b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
198b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    This program is distributed in the hope that it will be useful,
208b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    but WITHOUT ANY WARRANTY; without even the implied warranty of
218b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
228b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    GNU General Public License for more details.
238b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
248b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    You should have received a copy of the GNU General Public License
258b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    along with this program; if not, write to the Free Software
268b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
278b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow*/
288b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/*
298b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowDriver: adl_pci6208
308b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowDescription: ADLink PCI-6208A
318b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowDevices: [ADLink] PCI-6208A (adl_pci6208)
328b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowAuthor: nsyeow <nsyeow@pd.jaring.my>
338b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowUpdated: Fri, 30 Jan 2004 14:44:27 +0800
348b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowStatus: untested
358b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
368b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowConfiguration Options:
378b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow  none
388b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
398b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowReferences:
408b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	- ni_660x.c
418b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	- adl_pci9111.c		copied the entire pci setup section
428b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	- adl_pci9118.c
438b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow*/
448b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/*
458b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * These headers should be followed by a blank line, and any comments
468b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * you wish to say about the driver.  The comment area is the place
478b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * to put any known bugs, limitations, unsupported features, supported
488b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * command triggers, whether or not commands are supported on particular
498b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * subdevices, etc.
508b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow *
518b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * Somewhere in the comment should be information about configuration
528b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * options that are used with comedi_config.
538b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow */
548b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow#include "../comedidev.h"
558b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow#include "comedi_pci.h"
568b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
578b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow#define PCI6208_DRIVER_NAME 	"adl_pci6208"
588b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
598b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/* Board descriptions */
60c1b31c44a38e2b5153193680e4bee4856b3307e1Bill Pembertonstruct pci6208_board {
618b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	const char *name;
628b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	unsigned short dev_id;	/* `lspci` will show you this */
638b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	int ao_chans;
648b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//int ao_bits;
65c1b31c44a38e2b5153193680e4bee4856b3307e1Bill Pemberton};
66c1b31c44a38e2b5153193680e4bee4856b3307e1Bill Pemberton
67c1b31c44a38e2b5153193680e4bee4856b3307e1Bill Pembertonstatic const struct pci6208_board pci6208_boards[] = {
688b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	/*{
698b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	   name :  "pci6208v",
708b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	   dev_id       :  0x6208,      //not sure
718b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	   ao_chans:  8
728b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	   //,  ao_bits :  16
738b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	   },
748b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	   {
758b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	   name :  "pci6216v",
768b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	   dev_id       :  0x6208,      //not sure
778b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	   ao_chans:  16
788b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	   //,  ao_bits :  16
798b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	   }, */
808b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	{
818b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	      name:	"pci6208a",
828b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	      dev_id:	0x6208,
838b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	      ao_chans:8
848b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow			//,     ao_bits :  16
858b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		}
868b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow};
878b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
888b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/* This is used by modprobe to translate PCI IDs to drivers.  Should
898b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * only be used for PCI and ISA-PnP devices */
908b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowstatic DEFINE_PCI_DEVICE_TABLE(pci6208_pci_table) = {
918b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//{ PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
928b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//{ PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
938b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	{PCI_VENDOR_ID_ADLINK, 0x6208, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
948b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	{0}
958b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow};
968b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
978b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowMODULE_DEVICE_TABLE(pci, pci6208_pci_table);
988b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
998b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/* Will be initialized in pci6208_find device(). */
100c1b31c44a38e2b5153193680e4bee4856b3307e1Bill Pemberton#define thisboard ((const struct pci6208_board *)dev->board_ptr)
1018b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1028b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowtypedef struct {
1038b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	int data;
1048b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	struct pci_dev *pci_dev;	/* for a PCI device */
105790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int ao_readback[2];	/* Used for AO readback */
1068b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow} pci6208_private;
1078b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1088b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow#define devpriv ((pci6208_private *)dev->private)
1098b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1100707bb04be89b18ee83b5a997e36cc585f0b988dBill Pembertonstatic int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig * it);
11171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int pci6208_detach(struct comedi_device * dev);
1128b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1138b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow#define pci6208_board_nbr \
114c1b31c44a38e2b5153193680e4bee4856b3307e1Bill Pemberton	(sizeof(pci6208_boards) / sizeof(struct pci6208_board))
1158b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
116139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_pci6208 = {
1178b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow      driver_name:PCI6208_DRIVER_NAME,
1188b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow      module:THIS_MODULE,
1198b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow      attach:pci6208_attach,
1208b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow      detach:pci6208_detach,
1218b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow};
1228b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1238b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowCOMEDI_PCI_INITCLEANUP(driver_pci6208, pci6208_pci_table);
1248b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
12571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int pci6208_find_device(struct comedi_device * dev, int bus, int slot);
1268b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowstatic int
1278b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowpci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
1288b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	int dev_minor);
1298b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1308b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/*read/write functions*/
13134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
13290035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
13334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
13490035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
13534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton//static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s,
13690035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton//      struct comedi_insn *insn,unsigned int *data);
13734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton//static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s,
13890035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton//      struct comedi_insn *insn,unsigned int *data);
1398b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1408b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/*
1418b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * Attach is called by the Comedi core to configure the driver
1428b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * for a particular board.  If you specified a board_name array
1438b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * in the driver structure, dev->board_ptr contains that
1448b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * address.
1458b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow */
1460707bb04be89b18ee83b5a997e36cc585f0b988dBill Pembertonstatic int pci6208_attach(struct comedi_device * dev, struct comedi_devconfig * it)
1478b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow{
14834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
1498b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	int retval;
1508b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	unsigned long io_base;
1518b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1528b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	printk("comedi%d: pci6208: ", dev->minor);
1538b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1548b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	retval = alloc_private(dev, sizeof(pci6208_private));
1558b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	if (retval < 0)
1568b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		return retval;
1578b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1588b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	retval = pci6208_find_device(dev, it->options[0], it->options[1]);
1598b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	if (retval < 0)
1608b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		return retval;
1618b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1628b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	retval = pci6208_pci_setup(devpriv->pci_dev, &io_base, dev->minor);
1638b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	if (retval < 0)
1648b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		return retval;
1658b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1668b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	dev->iobase = io_base;
1678b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	dev->board_name = thisboard->name;
1688b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1698b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/*
1708b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * Allocate the subdevice structures.  alloc_subdevice() is a
1718b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * convenient macro defined in comedidev.h.
1728b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow */
1738b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	if (alloc_subdevices(dev, 2) < 0)
1748b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		return -ENOMEM;
1758b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1768b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	s = dev->subdevices + 0;
1778b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	/* analog output subdevice */
1788b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	s->type = COMEDI_SUBD_AO;
1798b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	s->subdev_flags = SDF_WRITABLE;	//anything else to add here??
1808b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	s->n_chan = thisboard->ao_chans;
1818b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	s->maxdata = 0xffff;	//16-bit DAC
1828b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	s->range_table = &range_bipolar10;	//this needs to be checked.
1838b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	s->insn_write = pci6208_ao_winsn;
1848b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	s->insn_read = pci6208_ao_rinsn;
1858b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1868b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//s=dev->subdevices+1;
1878b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	/* digital i/o subdevice */
1888b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//s->type=COMEDI_SUBD_DIO;
1898b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//s->subdev_flags=SDF_READABLE|SDF_WRITABLE;
1908b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//s->n_chan=16;
1918b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//s->maxdata=1;
1928b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//s->range_table=&range_digital;
1938b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//s->insn_bits = pci6208_dio_insn_bits;
1948b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//s->insn_config = pci6208_dio_insn_config;
1958b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1968b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	printk("attached\n");
1978b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
1988b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	return 1;
1998b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow}
2008b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2018b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/*
2028b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * _detach is called to deconfigure a device.  It should deallocate
2038b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * resources.
2048b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * This function is also called when _attach() fails, so it should be
2058b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * careful not to release resources that were not necessarily
2068b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * allocated by _attach().  dev->private and dev->subdevices are
2078b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * deallocated automatically by the core.
2088b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow */
20971b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int pci6208_detach(struct comedi_device * dev)
2108b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow{
2118b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	printk("comedi%d: pci6208: remove\n", dev->minor);
2128b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2138b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	if (devpriv && devpriv->pci_dev) {
2148b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		if (dev->iobase) {
2158b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow			comedi_pci_disable(devpriv->pci_dev);
2168b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		}
2178b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		pci_dev_put(devpriv->pci_dev);
2188b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	}
2198b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2208b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	return 0;
2218b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow}
2228b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
22334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int pci6208_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
22490035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
2258b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow{
2268b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	int i = 0, Data_Read;
2278b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	unsigned short chan = CR_CHAN(insn->chanspec);
2288b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	unsigned long invert = 1 << (16 - 1);
2298b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	unsigned long out_value;
2308b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	/* Writing a list of values to an AO channel is probably not
2318b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	 * very useful, but that's how the interface is defined. */
2328b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	for (i = 0; i < insn->n; i++) {
2338b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		out_value = data[i] ^ invert;
2348b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		/* a typical programming sequence */
2358b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		do {
2368b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow			Data_Read = (inw(dev->iobase) & 1);
2378b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		} while (Data_Read);
2388b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		outw(out_value, dev->iobase + (0x02 * chan));
2398b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		devpriv->ao_readback[chan] = out_value;
2408b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	}
2418b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2428b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	/* return the number of samples read/written */
2438b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	return i;
2448b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow}
2458b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2468b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/* AO subdevices should have a read insn as well as a write insn.
2478b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * Usually this means copying a value stored in devpriv. */
24834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int pci6208_ao_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
24990035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
2508b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow{
2518b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	int i;
2528b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	int chan = CR_CHAN(insn->chanspec);
2538b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2548b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	for (i = 0; i < insn->n; i++)
2558b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		data[i] = devpriv->ao_readback[chan];
2568b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2578b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	return i;
2588b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow}
2598b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2608b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow/* DIO devices are slightly special.  Although it is possible to
2618b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * implement the insn_read/insn_write interface, it is much more
2628b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * useful to applications if you implement the insn_bits interface.
2638b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * This allows packed reading/writing of the DIO channels.  The
2648b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow * comedi core can convert between insn_bits and insn_read/write */
26534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton//static int pci6208_dio_insn_bits(struct comedi_device *dev,struct comedi_subdevice *s,
26690035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton//      struct comedi_insn *insn,unsigned int *data)
2678b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//{
2688b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//      if(insn->n!=2)return -EINVAL;
2698b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2708b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	/* The insn data is a mask in data[0] and the new data
2718b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	 * in data[1], each channel cooresponding to a bit. */
2728b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//      if(data[0]){
2738b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//              s->state &= ~data[0];
2748b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//              s->state |= data[0]&data[1];
2758b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		/* Write out the new digital output lines */
2768b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		//outw(s->state,dev->iobase + SKEL_DIO);
2778b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//      }
2788b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2798b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	/* on return, data[1] contains the value of the digital
2808b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	 * input and output lines. */
2818b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//data[1]=inw(dev->iobase + SKEL_DIO);
2828b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	/* or we could just return the software copy of the output values if
2838b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	 * it was a purely digital output subdevice */
2848b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//data[1]=s->state;
2858b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2868b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//      return 2;
2878b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//}
2888b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
28934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton//static int pci6208_dio_insn_config(struct comedi_device *dev,struct comedi_subdevice *s,
29090035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton//      struct comedi_insn *insn,unsigned int *data)
2918b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//{
2928b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//      int chan=CR_CHAN(insn->chanspec);
2938b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2948b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	/* The input or output configuration of each digital line is
2958b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	 * configured by a special insn_config instruction.  chanspec
2968b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	 * contains the channel to be changed, and data[0] contains the
2978b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	 * value COMEDI_INPUT or COMEDI_OUTPUT. */
2988b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
2998b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//      if(data[0]==COMEDI_OUTPUT){
3008b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//              s->io_bits |= 1<<chan;
3018b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//      }else{
3028b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//              s->io_bits &= ~(1<<chan);
3038b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//      }
3048b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//outw(s->io_bits,dev->iobase + SKEL_DIO_CONFIG);
3058b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3068b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//      return 1;
3078b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow//}
3088b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
30971b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int pci6208_find_device(struct comedi_device * dev, int bus, int slot)
3108b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow{
3118b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	struct pci_dev *pci_dev;
3128b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	int i;
3138b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3148b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	for (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
3158b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		pci_dev != NULL;
3168b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
3178b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		if (pci_dev->vendor == PCI_VENDOR_ID_ADLINK) {
3188b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow			for (i = 0; i < pci6208_board_nbr; i++) {
3198b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow				if (pci6208_boards[i].dev_id == pci_dev->device) {
3208b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow					// was a particular bus/slot requested?
3218b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow					if ((bus != 0) || (slot != 0)) {
3228b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow						// are we on the wrong bus/slot?
3238b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow						if (pci_dev->bus->number
3248b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow							!= bus ||
3258b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow							PCI_SLOT(pci_dev->devfn)
3268b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow							!= slot) {
3278b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow							continue;
3288b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow						}
3298b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow					}
3308b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow					dev->board_ptr = pci6208_boards + i;
3318b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow					goto found;
3328b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow				}
3338b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow			}
3348b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		}
3358b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	}
3368b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3378b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
3388b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		dev->minor, bus, slot);
3398b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	return -EIO;
3408b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3418b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow      found:
3428b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	printk("comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n",
3438b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		dev->minor,
3448b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		pci6208_boards[i].name,
3458b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		pci_dev->bus->number,
3468b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		PCI_SLOT(pci_dev->devfn),
3478b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		PCI_FUNC(pci_dev->devfn), pci_dev->irq);
3488b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3498b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	// TODO: Warn about non-tested boards.
3508b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//switch(board->device_id)
3518b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//{
3528b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//};
3538b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3548b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	devpriv->pci_dev = pci_dev;
3558b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3568b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	return 0;
3578b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow}
3588b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3598b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowstatic int
3608b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeowpci6208_pci_setup(struct pci_dev *pci_dev, unsigned long *io_base_ptr,
3618b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	int dev_minor)
3628b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow{
3638b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
3648b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3658b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	// Enable PCI device and request regions
3668b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	if (comedi_pci_enable(pci_dev, PCI6208_DRIVER_NAME) < 0) {
3678b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		printk("comedi%d: Failed to enable PCI device and request regions\n", dev_minor);
3688b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		return -EIO;
3698b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	}
3708b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	// Read local configuration register base address [PCI_BASE_ADDRESS #1].
3718b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	lcr_io_base = pci_resource_start(pci_dev, 1);
3728b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	lcr_io_range = pci_resource_len(pci_dev, 1);
3738b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3748b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	printk("comedi%d: local config registers at address 0x%4lx [0x%4lx]\n",
3758b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		dev_minor, lcr_io_base, lcr_io_range);
3768b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3778b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	// Read PCI6208 register base address [PCI_BASE_ADDRESS #2].
3788b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	io_base = pci_resource_start(pci_dev, 2);
3798b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	io_range = pci_resource_end(pci_dev, 2) - io_base + 1;
3808b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3818b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	printk("comedi%d: 6208 registers at address 0x%4lx [0x%4lx]\n",
3828b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow		dev_minor, io_base, io_range);
3838b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3848b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	*io_base_ptr = io_base;
3858b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//devpriv->io_range = io_range;
3868b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//devpriv->is_valid=0;
3878b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//devpriv->lcr_io_base=lcr_io_base;
3888b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	//devpriv->lcr_io_range=lcr_io_range;
3898b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow
3908b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow	return 0;
3918b93f9034efbf2874d8809a9b8233e596bcbd5b1nsyeow}
392