17f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 27f62d87d6876445d460c110054b6d38561cdff45Calin Culianu comedi/drivers/cb_pcimdda.c 37f62d87d6876445d460c110054b6d38561cdff45Calin Culianu Computer Boards PCIM-DDA06-16 Comedi driver 47f62d87d6876445d460c110054b6d38561cdff45Calin Culianu Author: Calin Culianu <calin@ajvar.org> 57f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 67f62d87d6876445d460c110054b6d38561cdff45Calin Culianu COMEDI - Linux Control and Measurement Device Interface 77f62d87d6876445d460c110054b6d38561cdff45Calin Culianu Copyright (C) 2000 David A. Schleef <ds@schleef.org> 87f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 97f62d87d6876445d460c110054b6d38561cdff45Calin Culianu This program is free software; you can redistribute it and/or modify 107f62d87d6876445d460c110054b6d38561cdff45Calin Culianu it under the terms of the GNU General Public License as published by 117f62d87d6876445d460c110054b6d38561cdff45Calin Culianu the Free Software Foundation; either version 2 of the License, or 127f62d87d6876445d460c110054b6d38561cdff45Calin Culianu (at your option) any later version. 137f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 147f62d87d6876445d460c110054b6d38561cdff45Calin Culianu This program is distributed in the hope that it will be useful, 157f62d87d6876445d460c110054b6d38561cdff45Calin Culianu but WITHOUT ANY WARRANTY; without even the implied warranty of 167f62d87d6876445d460c110054b6d38561cdff45Calin Culianu MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 177f62d87d6876445d460c110054b6d38561cdff45Calin Culianu GNU General Public License for more details. 187f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 197f62d87d6876445d460c110054b6d38561cdff45Calin Culianu You should have received a copy of the GNU General Public License 207f62d87d6876445d460c110054b6d38561cdff45Calin Culianu along with this program; if not, write to the Free Software 217f62d87d6876445d460c110054b6d38561cdff45Calin Culianu Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 227f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 237f62d87d6876445d460c110054b6d38561cdff45Calin Culianu*/ 247f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 257f62d87d6876445d460c110054b6d38561cdff45Calin CulianuDriver: cb_pcimdda 267f62d87d6876445d460c110054b6d38561cdff45Calin CulianuDescription: Measurement Computing PCIM-DDA06-16 277f62d87d6876445d460c110054b6d38561cdff45Calin CulianuDevices: [Measurement Computing] PCIM-DDA06-16 (cb_pcimdda) 287f62d87d6876445d460c110054b6d38561cdff45Calin CulianuAuthor: Calin Culianu <calin@ajvar.org> 297f62d87d6876445d460c110054b6d38561cdff45Calin CulianuUpdated: Mon, 14 Apr 2008 15:15:51 +0100 307f62d87d6876445d460c110054b6d38561cdff45Calin CulianuStatus: works 317f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 327f62d87d6876445d460c110054b6d38561cdff45Calin CulianuAll features of the PCIM-DDA06-16 board are supported. This board 337f62d87d6876445d460c110054b6d38561cdff45Calin Culianuhas 6 16-bit AO channels, and the usual 8255 DIO setup. (24 channels, 347f62d87d6876445d460c110054b6d38561cdff45Calin Culianuconfigurable in banks of 8 and 4, etc.). This board does not support commands. 357f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 367f62d87d6876445d460c110054b6d38561cdff45Calin CulianuThe board has a peculiar way of specifying AO gain/range settings -- You have 377f62d87d6876445d460c110054b6d38561cdff45Calin Culianu1 jumper bank on the card, which either makes all 6 AO channels either 387f62d87d6876445d460c110054b6d38561cdff45Calin Culianu5 Volt unipolar, 5V bipolar, 10 Volt unipolar or 10V bipolar. 397f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 407f62d87d6876445d460c110054b6d38561cdff45Calin CulianuSince there is absolutely _no_ way to tell in software how this jumper is set 417f62d87d6876445d460c110054b6d38561cdff45Calin Culianu(well, at least according to the rather thin spec. from Measurement Computing 427f62d87d6876445d460c110054b6d38561cdff45Calin Culianu that comes with the board), the driver assumes the jumper is at its factory 437f62d87d6876445d460c110054b6d38561cdff45Calin Culianudefault setting of +/-5V. 447f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 457f62d87d6876445d460c110054b6d38561cdff45Calin CulianuAlso of note is the fact that this board features another jumper, whose 467f62d87d6876445d460c110054b6d38561cdff45Calin Culianustate is also completely invisible to software. It toggles two possible AO 477f62d87d6876445d460c110054b6d38561cdff45Calin Culianuoutput modes on the board: 487f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 497f62d87d6876445d460c110054b6d38561cdff45Calin Culianu - Update Mode: Writing to an AO channel instantaneously updates the actual 507f62d87d6876445d460c110054b6d38561cdff45Calin Culianu signal output by the DAC on the board (this is the factory default). 517f62d87d6876445d460c110054b6d38561cdff45Calin Culianu - Simultaneous XFER Mode: Writing to an AO channel has no effect until 527f62d87d6876445d460c110054b6d38561cdff45Calin Culianu you read from any one of the AO channels. This is useful for loading 537f62d87d6876445d460c110054b6d38561cdff45Calin Culianu all 6 AO values, and then reading from any one of the AO channels on the 547f62d87d6876445d460c110054b6d38561cdff45Calin Culianu device to instantly update all 6 AO values in unison. Useful for some 557f62d87d6876445d460c110054b6d38561cdff45Calin Culianu control apps, I would assume? If your jumper is in this setting, then you 567f62d87d6876445d460c110054b6d38561cdff45Calin Culianu need to issue your comedi_data_write()s to load all the values you want, 577f62d87d6876445d460c110054b6d38561cdff45Calin Culianu then issue one comedi_data_read() on any channel on the AO subdevice 587f62d87d6876445d460c110054b6d38561cdff45Calin Culianu to initiate the simultaneous XFER. 597f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 607f62d87d6876445d460c110054b6d38561cdff45Calin CulianuConfiguration Options: 617f62d87d6876445d460c110054b6d38561cdff45Calin Culianu [0] PCI bus (optional) 627f62d87d6876445d460c110054b6d38561cdff45Calin Culianu [1] PCI slot (optional) 637f62d87d6876445d460c110054b6d38561cdff45Calin Culianu [2] analog output range jumper setting 647f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 0 == +/- 5 V 657f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 1 == +/- 10 V 667f62d87d6876445d460c110054b6d38561cdff45Calin Culianu*/ 677f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 687f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 697f62d87d6876445d460c110054b6d38561cdff45Calin Culianu This is a driver for the Computer Boards PCIM-DDA06-16 Analog Output 707f62d87d6876445d460c110054b6d38561cdff45Calin Culianu card. This board has a unique register layout and as such probably 717f62d87d6876445d460c110054b6d38561cdff45Calin Culianu deserves its own driver file. 727f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 737f62d87d6876445d460c110054b6d38561cdff45Calin Culianu It is theoretically possible to integrate this board into the cb_pcidda 747f62d87d6876445d460c110054b6d38561cdff45Calin Culianu file, but since that isn't my code, I didn't want to significantly 757f62d87d6876445d460c110054b6d38561cdff45Calin Culianu modify that file to support this board (I thought it impolite to do so). 767f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 777f62d87d6876445d460c110054b6d38561cdff45Calin Culianu At any rate, if you feel ambitious, please feel free to take 787f62d87d6876445d460c110054b6d38561cdff45Calin Culianu the code out of this file and combine it with a more unified driver 797f62d87d6876445d460c110054b6d38561cdff45Calin Culianu file. 807f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 817f62d87d6876445d460c110054b6d38561cdff45Calin Culianu I would like to thank Timothy Curry <Timothy.Curry@rdec.redstone.army.mil> 827f62d87d6876445d460c110054b6d38561cdff45Calin Culianu for lending me a board so that I could write this driver. 837f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 847f62d87d6876445d460c110054b6d38561cdff45Calin Culianu -Calin Culianu <calin@ajvar.org> 857f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 867f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 877f62d87d6876445d460c110054b6d38561cdff45Calin Culianu#include "../comedidev.h" 887f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 897f62d87d6876445d460c110054b6d38561cdff45Calin Culianu#include "comedi_pci.h" 907f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 917f62d87d6876445d460c110054b6d38561cdff45Calin Culianu#include "8255.h" 927f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 937f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* device ids of the cards we support -- currently only 1 card supported */ 94558587e2d96a4f5439a609509e4ea88f7536203bGreg Kroah-Hartman#define PCI_VENDOR_ID_COMPUTERBOARDS 0x1307 95558587e2d96a4f5439a609509e4ea88f7536203bGreg Kroah-Hartman#define PCI_ID_PCIM_DDA06_16 0x0053 967f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 977f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 987f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * This is straight from skel.c -- I did this in case this source file 997f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * will someday support more than 1 board... 1007f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 101324da11efaea562c8270834ac03c7c3df03aa79bBill Pembertonstruct board_struct { 1027f62d87d6876445d460c110054b6d38561cdff45Calin Culianu const char *name; 1037f62d87d6876445d460c110054b6d38561cdff45Calin Culianu unsigned short device_id; 1047f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int ao_chans; 1057f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int ao_bits; 1067f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int dio_chans; 1077f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int dio_method; 10841912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya /* how many bytes into the BADR are the DIO ports */ 10941912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya int dio_offset; 1107f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int regs_badrindex; /* IO Region for the control, analog output, 1117f62d87d6876445d460c110054b6d38561cdff45Calin Culianu and DIO registers */ 1127f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int reg_sz; /* number of bytes of registers in io region */ 113324da11efaea562c8270834ac03c7c3df03aa79bBill Pemberton}; 1147f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 1157f62d87d6876445d460c110054b6d38561cdff45Calin Culianuenum DIO_METHODS { 1167f62d87d6876445d460c110054b6d38561cdff45Calin Culianu DIO_NONE = 0, 1177f62d87d6876445d460c110054b6d38561cdff45Calin Culianu DIO_8255, 1187f62d87d6876445d460c110054b6d38561cdff45Calin Culianu DIO_INTERNAL /* unimplemented */ 1197f62d87d6876445d460c110054b6d38561cdff45Calin Culianu}; 1207f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 121324da11efaea562c8270834ac03c7c3df03aa79bBill Pembertonstatic const struct board_struct boards[] = { 1227f62d87d6876445d460c110054b6d38561cdff45Calin Culianu { 1230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "cb_pcimdda06-16", 1240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .device_id = PCI_ID_PCIM_DDA06_16, 1250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ao_chans = 6, 1260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ao_bits = 16, 1270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .dio_chans = 24, 1280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .dio_method = DIO_8255, 1290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .dio_offset = 12, 1300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .regs_badrindex = 3, 1310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .reg_sz = 16, 1320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral } 1337f62d87d6876445d460c110054b6d38561cdff45Calin Culianu}; 1347f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 1357f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 1367f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * Useful for shorthand access to the particular board structure 1377f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 138324da11efaea562c8270834ac03c7c3df03aa79bBill Pemberton#define thisboard ((const struct board_struct *)dev->board_ptr) 1397f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 1407f62d87d6876445d460c110054b6d38561cdff45Calin Culianu#define REG_SZ (thisboard->reg_sz) 1417f62d87d6876445d460c110054b6d38561cdff45Calin Culianu#define REGS_BADRINDEX (thisboard->regs_badrindex) 1427f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 1437f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* This is used by modprobe to translate PCI IDs to drivers. Should 1447f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * only be used for PCI and ISA-PnP devices */ 1457f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded 1467f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * upstream. */ 1477f62d87d6876445d460c110054b6d38561cdff45Calin Culianustatic DEFINE_PCI_DEVICE_TABLE(pci_table) = { 14871d4c80db1e042baae6c5a2ca1bbfc16c89bd2b5Peter Huewe { PCI_DEVICE(PCI_VENDOR_ID_COMPUTERBOARDS, PCI_ID_PCIM_DDA06_16) }, 14971d4c80db1e042baae6c5a2ca1bbfc16c89bd2b5Peter Huewe {0} 1507f62d87d6876445d460c110054b6d38561cdff45Calin Culianu}; 1517f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 1527f62d87d6876445d460c110054b6d38561cdff45Calin CulianuMODULE_DEVICE_TABLE(pci, pci_table); 1537f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 15441912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya/* 15541912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya * this structure is for data unique to this hardware driver. If 15641912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya * several hardware drivers keep similar information in this structure, 15741912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya * feel free to suggest moving the variable to the struct comedi_device 15841912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya * struct. 15941912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya */ 1600ff297c4ebf5f7119e928d74a9d952158d329acaBill Pembertonstruct board_private_struct { 1617f62d87d6876445d460c110054b6d38561cdff45Calin Culianu unsigned long registers; /* set by probe */ 1627f62d87d6876445d460c110054b6d38561cdff45Calin Culianu unsigned long dio_registers; 1637f62d87d6876445d460c110054b6d38561cdff45Calin Culianu char attached_to_8255; /* boolean */ 1647f62d87d6876445d460c110054b6d38561cdff45Calin Culianu char attached_successfully; /* boolean */ 1657f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* would be useful for a PCI device */ 1667f62d87d6876445d460c110054b6d38561cdff45Calin Culianu struct pci_dev *pci_dev; 1677f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 1687f62d87d6876445d460c110054b6d38561cdff45Calin Culianu#define MAX_AO_READBACK_CHANNELS 6 1697f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* Used for AO readback */ 170790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton unsigned int ao_readback[MAX_AO_READBACK_CHANNELS]; 1717f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 1720ff297c4ebf5f7119e928d74a9d952158d329acaBill Pemberton}; 1737f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 1747f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 1757f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * most drivers define the following macro to make it easy to 1767f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * access the private structure. 1777f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 1780ff297c4ebf5f7119e928d74a9d952158d329acaBill Pemberton#define devpriv ((struct board_private_struct *)dev->private) 1797f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 1807f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 181139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pemberton * The struct comedi_driver structure tells the Comedi core module 1827f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * which functions to call to configure/deconfigure (attach/detach) 1837f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * the board, and also about the kernel module that contains 1847f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * the device code. 1857f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 186da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int attach(struct comedi_device *dev, struct comedi_devconfig *it); 187da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int detach(struct comedi_device *dev); 188139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver cb_pcimdda_driver = { 18968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "cb_pcimdda", 19068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 19168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = attach, 19268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = detach, 1937f62d87d6876445d460c110054b6d38561cdff45Calin Culianu}; 1947f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 1957f62d87d6876445d460c110054b6d38561cdff45Calin CulianuMODULE_AUTHOR("Calin A. Culianu <calin@rtlab.org>"); 1967f62d87d6876445d460c110054b6d38561cdff45Calin CulianuMODULE_DESCRIPTION("Comedi low-level driver for the Computerboards PCIM-DDA " 1970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral "series. Currently only supports PCIM-DDA06-16 (which " 1980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral "also happens to be the only board in this series. :) ) "); 1997f62d87d6876445d460c110054b6d38561cdff45Calin CulianuMODULE_LICENSE("GPL"); 200727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit cb_pcimdda_driver_pci_probe(struct pci_dev *dev, 201727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas const struct pci_device_id 202727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas *ent) 203727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 204727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas return comedi_pci_auto_config(dev, cb_pcimdda_driver.driver_name); 205727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 206727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 207727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit cb_pcimdda_driver_pci_remove(struct pci_dev *dev) 208727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 209727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas comedi_pci_auto_unconfig(dev); 210727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 211727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 212727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver cb_pcimdda_driver_pci_driver = { 213727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas .id_table = pci_table, 214727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas .probe = &cb_pcimdda_driver_pci_probe, 215727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas .remove = __devexit_p(&cb_pcimdda_driver_pci_remove) 216727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}; 217727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 218727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init cb_pcimdda_driver_init_module(void) 219727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 220727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas int retval; 221727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 222727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas retval = comedi_driver_register(&cb_pcimdda_driver); 223727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas if (retval < 0) 224727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas return retval; 225727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 226727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas cb_pcimdda_driver_pci_driver.name = 227727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas (char *)cb_pcimdda_driver.driver_name; 228727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas return pci_register_driver(&cb_pcimdda_driver_pci_driver); 229727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 230727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 231727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit cb_pcimdda_driver_cleanup_module(void) 232727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 233727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas pci_unregister_driver(&cb_pcimdda_driver_pci_driver); 234727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas comedi_driver_unregister(&cb_pcimdda_driver); 235727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 236727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 237727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(cb_pcimdda_driver_init_module); 238727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(cb_pcimdda_driver_cleanup_module); 2397f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 240da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 2410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 242da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 2430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 2447f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 2457f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/*--------------------------------------------------------------------------- 2467f62d87d6876445d460c110054b6d38561cdff45Calin Culianu HELPER FUNCTION DECLARATIONS 2477f62d87d6876445d460c110054b6d38561cdff45Calin Culianu-----------------------------------------------------------------------------*/ 2487f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 2497f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* returns a maxdata value for a given n_bits */ 250790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pembertonstatic inline unsigned int figure_out_maxdata(int bits) 2517f62d87d6876445d460c110054b6d38561cdff45Calin Culianu{ 2520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral return ((unsigned int)1 << bits) - 1; 2537f62d87d6876445d460c110054b6d38561cdff45Calin Culianu} 2547f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 2557f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 2567f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * Probes for a supported device. 2577f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * 2587f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * Prerequisite: private be allocated already inside dev 2597f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * 2607f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * If the device is found, it returns 0 and has the following side effects: 2617f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * 2627f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * o assigns a struct pci_dev * to dev->private->pci_dev 2637f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * o assigns a struct board * to dev->board_ptr 2647f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * o sets dev->private->registers 2657f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * o sets dev->private->dio_registers 2667f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * 2677f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * Otherwise, returns a -errno on error 2687f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 269da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int probe(struct comedi_device *dev, const struct comedi_devconfig *it); 2707f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 2717f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/*--------------------------------------------------------------------------- 2727f62d87d6876445d460c110054b6d38561cdff45Calin Culianu FUNCTION DEFINITIONS 2737f62d87d6876445d460c110054b6d38561cdff45Calin Culianu-----------------------------------------------------------------------------*/ 2747f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 2757f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 2767f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * Attach is called by the Comedi core to configure the driver 2777f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * for a particular board. If you specified a board_name array 2787f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * in the driver structure, dev->board_ptr contains that 2797f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * address. 2807f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 281da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int attach(struct comedi_device *dev, struct comedi_devconfig *it) 2827f62d87d6876445d460c110054b6d38561cdff45Calin Culianu{ 28334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 2847f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int err; 2857f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 2867f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 2877f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * Allocate the private structure area. alloc_private() is a 2887f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * convenient macro defined in comedidev.h. 2897f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * if this function fails (returns negative) then the private area is 2907f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * kfree'd by comedi 2917f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 2920ff297c4ebf5f7119e928d74a9d952158d329acaBill Pemberton if (alloc_private(dev, sizeof(struct board_private_struct)) < 0) 2937f62d87d6876445d460c110054b6d38561cdff45Calin Culianu return -ENOMEM; 2947f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 2957f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 2967f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * If you can probe the device to determine what device in a series 2977f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * it is, this is the place to do it. Otherwise, dev->board_ptr 2987f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * should already be initialized. 2997f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 300c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton err = probe(dev, it); 301c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton if (err) 3027f62d87d6876445d460c110054b6d38561cdff45Calin Culianu return err; 3037f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3047f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* Output some info */ 3057f62d87d6876445d460c110054b6d38561cdff45Calin Culianu printk("comedi%d: %s: ", dev->minor, thisboard->name); 3067f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3077f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 3087f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * Initialize dev->board_name. Note that we can use the "thisboard" 3097f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * macro now, since we just initialized it in the last line. 3107f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 3117f62d87d6876445d460c110054b6d38561cdff45Calin Culianu dev->board_name = thisboard->name; 3127f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3137f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 3147f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * Allocate the subdevice structures. alloc_subdevice() is a 3157f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * convenient macro defined in comedidev.h. 3167f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 3177f62d87d6876445d460c110054b6d38561cdff45Calin Culianu if (alloc_subdevices(dev, 2) < 0) 3187f62d87d6876445d460c110054b6d38561cdff45Calin Culianu return -ENOMEM; 3197f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3207f62d87d6876445d460c110054b6d38561cdff45Calin Culianu s = dev->subdevices + 0; 3217f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3227f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* analog output subdevice */ 3237f62d87d6876445d460c110054b6d38561cdff45Calin Culianu s->type = COMEDI_SUBD_AO; 3247f62d87d6876445d460c110054b6d38561cdff45Calin Culianu s->subdev_flags = SDF_WRITABLE | SDF_READABLE; 3257f62d87d6876445d460c110054b6d38561cdff45Calin Culianu s->n_chan = thisboard->ao_chans; 3267f62d87d6876445d460c110054b6d38561cdff45Calin Culianu s->maxdata = figure_out_maxdata(thisboard->ao_bits); 3277f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* this is hard-coded here */ 328f1c54e82726fe51a55a18d15dc9377b8fd568ca2Andrea Gelmini if (it->options[2]) 3297f62d87d6876445d460c110054b6d38561cdff45Calin Culianu s->range_table = &range_bipolar10; 330f1c54e82726fe51a55a18d15dc9377b8fd568ca2Andrea Gelmini else 3317f62d87d6876445d460c110054b6d38561cdff45Calin Culianu s->range_table = &range_bipolar5; 3327f62d87d6876445d460c110054b6d38561cdff45Calin Culianu s->insn_write = &ao_winsn; 3337f62d87d6876445d460c110054b6d38561cdff45Calin Culianu s->insn_read = &ao_rinsn; 3347f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3357f62d87d6876445d460c110054b6d38561cdff45Calin Culianu s = dev->subdevices + 1; 3367f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* digital i/o subdevice */ 3377f62d87d6876445d460c110054b6d38561cdff45Calin Culianu if (thisboard->dio_chans) { 3387f62d87d6876445d460c110054b6d38561cdff45Calin Culianu switch (thisboard->dio_method) { 3397f62d87d6876445d460c110054b6d38561cdff45Calin Culianu case DIO_8255: 34041912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya /* 34141912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya * this is a straight 8255, so register us with 34241912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya * the 8255 driver 34341912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya */ 3447f62d87d6876445d460c110054b6d38561cdff45Calin Culianu subdev_8255_init(dev, s, NULL, devpriv->dio_registers); 3457f62d87d6876445d460c110054b6d38561cdff45Calin Culianu devpriv->attached_to_8255 = 1; 3467f62d87d6876445d460c110054b6d38561cdff45Calin Culianu break; 3477f62d87d6876445d460c110054b6d38561cdff45Calin Culianu case DIO_INTERNAL: 3487f62d87d6876445d460c110054b6d38561cdff45Calin Culianu default: 3497f62d87d6876445d460c110054b6d38561cdff45Calin Culianu printk("DIO_INTERNAL not implemented yet!\n"); 3507f62d87d6876445d460c110054b6d38561cdff45Calin Culianu return -ENXIO; 3517f62d87d6876445d460c110054b6d38561cdff45Calin Culianu break; 3527f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 3537f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } else { 3547f62d87d6876445d460c110054b6d38561cdff45Calin Culianu s->type = COMEDI_SUBD_UNUSED; 3557f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 3567f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3577f62d87d6876445d460c110054b6d38561cdff45Calin Culianu devpriv->attached_successfully = 1; 3587f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3597f62d87d6876445d460c110054b6d38561cdff45Calin Culianu printk("attached\n"); 3607f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3617f62d87d6876445d460c110054b6d38561cdff45Calin Culianu return 1; 3627f62d87d6876445d460c110054b6d38561cdff45Calin Culianu} 3637f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3647f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 3657f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * _detach is called to deconfigure a device. It should deallocate 3667f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * resources. 3677f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * This function is also called when _attach() fails, so it should be 3687f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * careful not to release resources that were not necessarily 3697f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * allocated by _attach(). dev->private and dev->subdevices are 3707f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * deallocated automatically by the core. 3717f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 372da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int detach(struct comedi_device *dev) 3737f62d87d6876445d460c110054b6d38561cdff45Calin Culianu{ 3747f62d87d6876445d460c110054b6d38561cdff45Calin Culianu if (devpriv) { 3757f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3767f62d87d6876445d460c110054b6d38561cdff45Calin Culianu if (dev->subdevices && devpriv->attached_to_8255) { 3777f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* de-register us from the 8255 driver */ 3787f62d87d6876445d460c110054b6d38561cdff45Calin Culianu subdev_8255_cleanup(dev, dev->subdevices + 2); 3797f62d87d6876445d460c110054b6d38561cdff45Calin Culianu devpriv->attached_to_8255 = 0; 3807f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 3817f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3827f62d87d6876445d460c110054b6d38561cdff45Calin Culianu if (devpriv->pci_dev) { 383f1c54e82726fe51a55a18d15dc9377b8fd568ca2Andrea Gelmini if (devpriv->registers) 3847f62d87d6876445d460c110054b6d38561cdff45Calin Culianu comedi_pci_disable(devpriv->pci_dev); 3857f62d87d6876445d460c110054b6d38561cdff45Calin Culianu pci_dev_put(devpriv->pci_dev); 3867f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 3877f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3887f62d87d6876445d460c110054b6d38561cdff45Calin Culianu if (devpriv->attached_successfully && thisboard) 3897f62d87d6876445d460c110054b6d38561cdff45Calin Culianu printk("comedi%d: %s: detached\n", dev->minor, 3900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral thisboard->name); 3917f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3927f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 3937f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 3947f62d87d6876445d460c110054b6d38561cdff45Calin Culianu return 0; 3957f62d87d6876445d460c110054b6d38561cdff45Calin Culianu} 3967f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 397da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 3980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 3997f62d87d6876445d460c110054b6d38561cdff45Calin Culianu{ 4007f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int i; 4017f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int chan = CR_CHAN(insn->chanspec); 4027f62d87d6876445d460c110054b6d38561cdff45Calin Culianu unsigned long offset = devpriv->registers + chan * 2; 4037f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 4047f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* Writing a list of values to an AO channel is probably not 4057f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * very useful, but that's how the interface is defined. */ 4067f62d87d6876445d460c110054b6d38561cdff45Calin Culianu for (i = 0; i < insn->n; i++) { 4077f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* first, load the low byte */ 4087f62d87d6876445d460c110054b6d38561cdff45Calin Culianu outb((char)(data[i] & 0x00ff), offset); 4097f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* next, write the high byte -- only after this is written is 4107f62d87d6876445d460c110054b6d38561cdff45Calin Culianu the channel voltage updated in the DAC, unless 4117f62d87d6876445d460c110054b6d38561cdff45Calin Culianu we're in simultaneous xfer mode (jumper on card) 4127f62d87d6876445d460c110054b6d38561cdff45Calin Culianu then a rinsn is necessary to actually update the DAC -- 4137f62d87d6876445d460c110054b6d38561cdff45Calin Culianu see ao_rinsn() below... */ 4147f62d87d6876445d460c110054b6d38561cdff45Calin Culianu outb((char)(data[i] >> 8 & 0x00ff), offset + 1); 4157f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 4167f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* for testing only.. the actual rinsn SHOULD do an inw! 4177f62d87d6876445d460c110054b6d38561cdff45Calin Culianu (see the stuff about simultaneous XFER mode on this board) */ 4187f62d87d6876445d460c110054b6d38561cdff45Calin Culianu devpriv->ao_readback[chan] = data[i]; 4197f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 4207f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 4217f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* return the number of samples read/written */ 4227f62d87d6876445d460c110054b6d38561cdff45Calin Culianu return i; 4237f62d87d6876445d460c110054b6d38561cdff45Calin Culianu} 4247f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 4257f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* AO subdevices should have a read insn as well as a write insn. 4267f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 4277f62d87d6876445d460c110054b6d38561cdff45Calin Culianu Usually this means copying a value stored in devpriv->ao_readback. 4287f62d87d6876445d460c110054b6d38561cdff45Calin Culianu However, since this board has this jumper setting called "Simultaneous 4297f62d87d6876445d460c110054b6d38561cdff45Calin Culianu Xfer mode" (off by default), we will support it. Simultaneaous xfer 4307f62d87d6876445d460c110054b6d38561cdff45Calin Culianu mode is accomplished by loading ALL the values you want for AO in all the 4317f62d87d6876445d460c110054b6d38561cdff45Calin Culianu channels, then READing off one of the AO registers to initiate the 4327f62d87d6876445d460c110054b6d38561cdff45Calin Culianu instantaneous simultaneous update of all DAC outputs, which makes 4337f62d87d6876445d460c110054b6d38561cdff45Calin Culianu all AO channels update simultaneously. This is useful for some control 4347f62d87d6876445d460c110054b6d38561cdff45Calin Culianu applications, I would imagine. 4357f62d87d6876445d460c110054b6d38561cdff45Calin Culianu*/ 436da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 4370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 4387f62d87d6876445d460c110054b6d38561cdff45Calin Culianu{ 4397f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int i; 4407f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int chan = CR_CHAN(insn->chanspec); 4417f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 4427f62d87d6876445d460c110054b6d38561cdff45Calin Culianu for (i = 0; i < insn->n; i++) { 4437f62d87d6876445d460c110054b6d38561cdff45Calin Culianu inw(devpriv->registers + chan * 2); 44441912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya /* 44541912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya * should I set data[i] to the result of the actual read 44641912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya * on the register or the cached unsigned int in 44741912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya * devpriv->ao_readback[]? 44841912a3f231e97efa154f4662608c024238ffe5eRavishankar karkala Mallikarjunayya */ 4497f62d87d6876445d460c110054b6d38561cdff45Calin Culianu data[i] = devpriv->ao_readback[chan]; 4507f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 4517f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 4527f62d87d6876445d460c110054b6d38561cdff45Calin Culianu return i; 4537f62d87d6876445d460c110054b6d38561cdff45Calin Culianu} 4547f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 4557f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/*--------------------------------------------------------------------------- 4567f62d87d6876445d460c110054b6d38561cdff45Calin Culianu HELPER FUNCTION DEFINITIONS 4577f62d87d6876445d460c110054b6d38561cdff45Calin Culianu-----------------------------------------------------------------------------*/ 4587f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 4597f62d87d6876445d460c110054b6d38561cdff45Calin Culianu/* 4607f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * Probes for a supported device. 4617f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * 4627f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * Prerequisite: private be allocated already inside dev 4637f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * 4647f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * If the device is found, it returns 0 and has the following side effects: 4657f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * 4667f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * o assigns a struct pci_dev * to dev->private->pci_dev 4677f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * o assigns a struct board * to dev->board_ptr 4687f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * o sets dev->private->registers 4697f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * o sets dev->private->dio_registers 4707f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * 4717f62d87d6876445d460c110054b6d38561cdff45Calin Culianu * Otherwise, returns a -errno on error 4727f62d87d6876445d460c110054b6d38561cdff45Calin Culianu */ 473da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int probe(struct comedi_device *dev, const struct comedi_devconfig *it) 4747f62d87d6876445d460c110054b6d38561cdff45Calin Culianu{ 47520fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy struct pci_dev *pcidev = NULL; 4767f62d87d6876445d460c110054b6d38561cdff45Calin Culianu int index; 4777f62d87d6876445d460c110054b6d38561cdff45Calin Culianu unsigned long registers; 4787f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 47920fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy for_each_pci_dev(pcidev) { 4802696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* is it not a computer boards card? */ 4817f62d87d6876445d460c110054b6d38561cdff45Calin Culianu if (pcidev->vendor != PCI_VENDOR_ID_COMPUTERBOARDS) 4827f62d87d6876445d460c110054b6d38561cdff45Calin Culianu continue; 4832696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* loop through cards supported by this driver */ 4848629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton for (index = 0; index < ARRAY_SIZE(boards); index++) { 4857f62d87d6876445d460c110054b6d38561cdff45Calin Culianu if (boards[index].device_id != pcidev->device) 4867f62d87d6876445d460c110054b6d38561cdff45Calin Culianu continue; 4872696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* was a particular bus/slot requested? */ 4887f62d87d6876445d460c110054b6d38561cdff45Calin Culianu if (it->options[0] || it->options[1]) { 4892696fb57e6af653dd8b4df41b16754579f42fc78Bill Pemberton /* are we on the wrong bus/slot? */ 4907f62d87d6876445d460c110054b6d38561cdff45Calin Culianu if (pcidev->bus->number != it->options[0] || 4910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral PCI_SLOT(pcidev->devfn) != it->options[1]) { 4927f62d87d6876445d460c110054b6d38561cdff45Calin Culianu continue; 4937f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 4947f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 4957f62d87d6876445d460c110054b6d38561cdff45Calin Culianu /* found ! */ 4967f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 4977f62d87d6876445d460c110054b6d38561cdff45Calin Culianu devpriv->pci_dev = pcidev; 4987f62d87d6876445d460c110054b6d38561cdff45Calin Culianu dev->board_ptr = boards + index; 4997f62d87d6876445d460c110054b6d38561cdff45Calin Culianu if (comedi_pci_enable(pcidev, thisboard->name)) { 5000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral printk 5010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral ("cb_pcimdda: Failed to enable PCI device and request regions\n"); 5027f62d87d6876445d460c110054b6d38561cdff45Calin Culianu return -EIO; 5037f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 5047f62d87d6876445d460c110054b6d38561cdff45Calin Culianu registers = 5050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral pci_resource_start(devpriv->pci_dev, 5060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral REGS_BADRINDEX); 5077f62d87d6876445d460c110054b6d38561cdff45Calin Culianu devpriv->registers = registers; 5087f62d87d6876445d460c110054b6d38561cdff45Calin Culianu devpriv->dio_registers 5090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral = devpriv->registers + thisboard->dio_offset; 5107f62d87d6876445d460c110054b6d38561cdff45Calin Culianu return 0; 5117f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 5127f62d87d6876445d460c110054b6d38561cdff45Calin Culianu } 5137f62d87d6876445d460c110054b6d38561cdff45Calin Culianu 5147f62d87d6876445d460c110054b6d38561cdff45Calin Culianu printk("cb_pcimdda: No supported ComputerBoards/MeasurementComputing " 5150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral "card found at the requested position\n"); 5167f62d87d6876445d460c110054b6d38561cdff45Calin Culianu return -ENODEV; 5177f62d87d6876445d460c110054b6d38561cdff45Calin Culianu} 518