ke_counter.c revision da91b2692e0939b307f9047192d2b9fe07793e7a
12f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann/*
22f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    comedi/drivers/ke_counter.c
32f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    Comedi driver for Kolter-Electronic PCI Counter 1 Card
42f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
52f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    COMEDI - Linux Control and Measurement Device Interface
62f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
72f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
82f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    This program is free software; you can redistribute it and/or modify
92f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    it under the terms of the GNU General Public License as published by
102f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    the Free Software Foundation; either version 2 of the License, or
112f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    (at your option) any later version.
122f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
132f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    This program is distributed in the hope that it will be useful,
142f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    but WITHOUT ANY WARRANTY; without even the implied warranty of
152f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
162f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    GNU General Public License for more details.
172f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
182f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    You should have received a copy of the GNU General Public License
192f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    along with this program; if not, write to the Free Software
202f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
212f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
222f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann*/
232f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann/*
242f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael HillmannDriver: ke_counter
252f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael HillmannDescription: Driver for Kolter Electronic Counter Card
262f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael HillmannDevices: [Kolter Electronic] PCI Counter Card (ke_counter)
272f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael HillmannAuthor: Michael Hillmann
282f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael HillmannUpdated: Mon, 14 Apr 2008 15:42:42 +0100
292f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael HillmannStatus: tested
302f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
312f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael HillmannConfiguration Options:
322f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann  [0] - PCI bus of device (optional)
332f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann  [1] - PCI slot of device (optional)
342f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann  If bus/slot is not specified, the first supported
352f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann  PCI device found will be used.
362f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
372f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael HillmannThis driver is a simple driver to read the counter values from
382f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael HillmannKolter Electronic PCI Counter Card.
392f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann*/
402f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
412f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann#include "../comedidev.h"
422f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
432f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann#include "comedi_pci.h"
442f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
452f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann#define CNT_DRIVER_NAME         "ke_counter"
462f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann#define PCI_VENDOR_ID_KOLTER    0x1001
472f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann#define CNT_CARD_DEVICE_ID      0x0014
482f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
492f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann/*-- function prototypes ----------------------------------------------------*/
502f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
51da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it);
52da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cnt_detach(struct comedi_device *dev);
532f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
542f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmannstatic DEFINE_PCI_DEVICE_TABLE(cnt_pci_table) = {
552f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	{PCI_VENDOR_ID_KOLTER, CNT_CARD_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
562f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		0},
572f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	{0}
582f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann};
592f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
602f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael HillmannMODULE_DEVICE_TABLE(pci, cnt_pci_table);
612f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
622f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann/*-- board specification structure ------------------------------------------*/
632f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
649beff277bb14a844b5cb437fcdca9db7534ee44aBill Pembertonstruct cnt_board_struct {
659beff277bb14a844b5cb437fcdca9db7534ee44aBill Pemberton
662f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	const char *name;
672f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	int device_id;
682f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	int cnt_channel_nbr;
692f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	int cnt_bits;
709beff277bb14a844b5cb437fcdca9db7534ee44aBill Pemberton};
719beff277bb14a844b5cb437fcdca9db7534ee44aBill Pemberton
722f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
739beff277bb14a844b5cb437fcdca9db7534ee44aBill Pembertonstatic const struct cnt_board_struct cnt_boards[] = {
742f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	{
752f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	      name:	CNT_DRIVER_NAME,
762f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	      device_id:CNT_CARD_DEVICE_ID,
772f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	      cnt_channel_nbr:3,
782f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann      cnt_bits:24}
792f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann};
802f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
819beff277bb14a844b5cb437fcdca9db7534ee44aBill Pemberton#define cnt_board_nbr (sizeof(cnt_boards)/sizeof(struct cnt_board_struct))
822f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
832f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann/*-- device private structure -----------------------------------------------*/
842f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
852e2269f90f2bb4e9438849f0690daba5cba29fc5Bill Pembertonstruct cnt_device_private {
862e2269f90f2bb4e9438849f0690daba5cba29fc5Bill Pemberton
872f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	struct pci_dev *pcidev;
882e2269f90f2bb4e9438849f0690daba5cba29fc5Bill Pemberton};
892e2269f90f2bb4e9438849f0690daba5cba29fc5Bill Pemberton
902f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
912e2269f90f2bb4e9438849f0690daba5cba29fc5Bill Pemberton#define devpriv ((struct cnt_device_private *)dev->private)
922f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
93139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver cnt_driver = {
942f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann      driver_name:CNT_DRIVER_NAME,
952f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann      module:THIS_MODULE,
962f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann      attach:cnt_attach,
972f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann      detach:cnt_detach,
982f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann};
992f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1002f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael HillmannCOMEDI_PCI_INITCLEANUP(cnt_driver, cnt_pci_table);
1012f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1022f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann/*-- counter write ----------------------------------------------------------*/
1032f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1042f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann/* This should be used only for resetting the counters; maybe it is better
1052f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann   to make a special command 'reset'. */
106da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cnt_winsn(struct comedi_device *dev,
107da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
1082f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann{
1092f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	int chan = CR_CHAN(insn->chanspec);
1102f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1112f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	outb((unsigned char)((data[0] >> 24) & 0xff),
1122f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		dev->iobase + chan * 0x20 + 0x10);
1132f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	outb((unsigned char)((data[0] >> 16) & 0xff),
1142f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		dev->iobase + chan * 0x20 + 0x0c);
1152f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	outb((unsigned char)((data[0] >> 8) & 0xff),
1162f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		dev->iobase + chan * 0x20 + 0x08);
1172f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	outb((unsigned char)((data[0] >> 0) & 0xff),
1182f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		dev->iobase + chan * 0x20 + 0x04);
1192f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1202f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	/* return the number of samples written */
1212f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	return 1;
1222f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann}
1232f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1242f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann/*-- counter read -----------------------------------------------------------*/
1252f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
126da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cnt_rinsn(struct comedi_device *dev,
127da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
1282f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann{
1292f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	unsigned char a0, a1, a2, a3, a4;
1302f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	int chan = CR_CHAN(insn->chanspec);
1312f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	int result;
1322f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1332f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	a0 = inb(dev->iobase + chan * 0x20);
1342f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	a1 = inb(dev->iobase + chan * 0x20 + 0x04);
1352f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	a2 = inb(dev->iobase + chan * 0x20 + 0x08);
1362f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	a3 = inb(dev->iobase + chan * 0x20 + 0x0c);
1372f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	a4 = inb(dev->iobase + chan * 0x20 + 0x10);
1382f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1392f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	result = (a1 + (a2 * 256) + (a3 * 65536));
1402f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	if (a4 > 0)
1412f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		result = result - s->maxdata;
1422f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
143790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	*data = (unsigned int) result;
1442f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1452f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	/* return the number of samples read */
1462f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	return 1;
1472f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann}
1482f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1492f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann/*-- attach -----------------------------------------------------------------*/
1502f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
151da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cnt_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1522f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann{
15334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice;
1542f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	struct pci_dev *pci_device;
1559beff277bb14a844b5cb437fcdca9db7534ee44aBill Pemberton	struct cnt_board_struct *board;
1562f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	unsigned long io_base;
1572f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	int error, i;
1582f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1592f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	/* allocate device private structure */
1602e2269f90f2bb4e9438849f0690daba5cba29fc5Bill Pemberton	if ((error = alloc_private(dev, sizeof(struct cnt_device_private))) < 0) {
1612f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		return error;
1622f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	}
1632f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1642f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	/* Probe the device to determine what device in the series it is. */
1652f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
1662f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		pci_device != NULL;
1672f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		pci_device =
1682f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) {
1692f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		if (pci_device->vendor == PCI_VENDOR_ID_KOLTER) {
1702f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann			for (i = 0; i < cnt_board_nbr; i++) {
1712f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann				if (cnt_boards[i].device_id ==
1722f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann					pci_device->device) {
1732f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann					/* was a particular bus/slot requested? */
1742f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann					if ((it->options[0] != 0)
1752f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann						|| (it->options[1] != 0)) {
1762f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann						/* are we on the wrong bus/slot? */
1772f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann						if (pci_device->bus->number !=
1782f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann							it->options[0]
1792f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann							|| PCI_SLOT(pci_device->
1802f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann								devfn) !=
1812f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann							it->options[1]) {
1822f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann							continue;
1832f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann						}
1842f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann					}
1852f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1862f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann					dev->board_ptr = cnt_boards + i;
1879beff277bb14a844b5cb437fcdca9db7534ee44aBill Pemberton					board = (struct cnt_board_struct *) dev->
1882f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann						board_ptr;
1892f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann					goto found;
1902f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann				}
1912f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann			}
1922f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		}
1932f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	}
1942f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	printk("comedi%d: no supported board found! (req. bus/slot: %d/%d)\n",
1952f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		dev->minor, it->options[0], it->options[1]);
1962f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	return -EIO;
1972f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
1982f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann      found:
1992f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	printk("comedi%d: found %s at PCI bus %d, slot %d\n", dev->minor,
2002f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		board->name, pci_device->bus->number,
2012f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		PCI_SLOT(pci_device->devfn));
2022f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	devpriv->pcidev = pci_device;
2032f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	dev->board_name = board->name;
2042f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
2052f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	/* enable PCI device and request regions */
2062f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	if ((error = comedi_pci_enable(pci_device, CNT_DRIVER_NAME)) < 0) {
2072f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		printk("comedi%d: failed to enable PCI device and request regions!\n", dev->minor);
2082f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		return error;
2092f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	}
2102f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
2112f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	/* read register base address [PCI_BASE_ADDRESS #0] */
2122f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	io_base = pci_resource_start(pci_device, 0);
2132f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	dev->iobase = io_base;
2142f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
2152f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	/* allocate the subdevice structures */
2162f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	if ((error = alloc_subdevices(dev, 1)) < 0) {
2172f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		return error;
2182f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	}
2192f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
2202f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	subdevice = dev->subdevices + 0;
2212f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	dev->read_subdev = subdevice;
2222f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
2232f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	subdevice->type = COMEDI_SUBD_COUNTER;
2242f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	subdevice->subdev_flags = SDF_READABLE /* | SDF_COMMON */ ;
2252f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	subdevice->n_chan = board->cnt_channel_nbr;
2262f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	subdevice->maxdata = (1 << board->cnt_bits) - 1;
2272f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	subdevice->insn_read = cnt_rinsn;
2282f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	subdevice->insn_write = cnt_winsn;
2292f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
2302696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  select 20MHz clock */
2312f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	outb(3, dev->iobase + 248);
2322f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
2332696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton	/*  reset all counters */
2342f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	outb(0, dev->iobase);
2352f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	outb(0, dev->iobase + 0x20);
2362f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	outb(0, dev->iobase + 0x40);
2372f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
2382f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	printk("comedi%d: " CNT_DRIVER_NAME " attached.\n", dev->minor);
2392f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	return 0;
2402f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann}
2412f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
2422f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann/*-- detach -----------------------------------------------------------------*/
2432f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann
244da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cnt_detach(struct comedi_device *dev)
2452f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann{
2462f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	if (devpriv && devpriv->pcidev) {
2472f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		if (dev->iobase) {
2482f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann			comedi_pci_disable(devpriv->pcidev);
2492f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		}
2502f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann		pci_dev_put(devpriv->pcidev);
2512f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	}
2522f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	printk("comedi%d: " CNT_DRIVER_NAME " remove\n", dev->minor);
2532f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann	return 0;
2542f82613d3a7ef447be4ce656f757fc1ea101a4f1Michael Hillmann}
255