1fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 2fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef comedi/drivers/skel.c 3fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef Skeleton code for a Comedi driver 4fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 5fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef COMEDI - Linux Control and Measurement Device Interface 6fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef Copyright (C) 2000 David A. Schleef <ds@schleef.org> 7fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 8fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef This program is free software; you can redistribute it and/or modify 9fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef it under the terms of the GNU General Public License as published by 10fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef the Free Software Foundation; either version 2 of the License, or 11fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef (at your option) any later version. 12fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 13fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef This program is distributed in the hope that it will be useful, 14fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef but WITHOUT ANY WARRANTY; without even the implied warranty of 15fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef GNU General Public License for more details. 17fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 18fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef You should have received a copy of the GNU General Public License 19fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef along with this program; if not, write to the Free Software 20fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 22fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef*/ 23fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 24fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid SchleefDriver: skel 25fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid SchleefDescription: Skeleton driver, an example for driver writers 26fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid SchleefDevices: 27fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid SchleefAuthor: ds 28fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid SchleefUpdated: Mon, 18 Mar 2002 15:34:01 -0800 29fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid SchleefStatus: works 30fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 31fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid SchleefThis driver is a documented example on how Comedi drivers are 32fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleefwritten. 33fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 34fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid SchleefConfiguration Options: 35fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef none 36fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef*/ 37fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 38fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 39fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * The previous block comment is used to automatically generate 40fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * documentation in Comedi and Comedilib. The fields: 41fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * 429a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * Driver: the name of the driver 439a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * Description: a short phrase describing the driver. Don't list boards. 449a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * Devices: a full list of the boards that attempt to be supported by 459a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * the driver. Format is "(manufacturer) board name [comedi name]", 469a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * where comedi_name is the name that is used to configure the board. 479a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * See the comment near board_name: in the struct comedi_driver structure 489a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * below. If (manufacturer) or [comedi name] is missing, the previous 499a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * value is used. 509a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * Author: you 519a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * Updated: date when the _documentation_ was last updated. Use 'date -R' 529a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * to get a value for this. 539a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * Status: a one-word description of the status. Valid values are: 549a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * works - driver works correctly on most boards supported, and 559a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * passes comedi_test. 569a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * unknown - unknown. Usually put there by ds. 579a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * experimental - may not work in any particular release. Author 589a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * probably wants assistance testing it. 599a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * bitrotten - driver has not been update in a long time, probably 609a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * doesn't work, and probably is missing support for significant 619a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * Comedi interface features. 629a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * untested - author probably wrote it "blind", and is believed to 639a390f38b6a84d5a11c89a116363db3fe587598bIan Abbott * work, but no confirmation. 64fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * 65fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * These headers should be followed by a blank line, and any comments 66fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * you wish to say about the driver. The comment area is the place 67fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * to put any known bugs, limitations, unsupported features, supported 68fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * command triggers, whether or not commands are supported on particular 69fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * subdevices, etc. 70fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * 71fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * Somewhere in the comment should be information about configuration 72fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * options that are used with comedi_config. 73fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 74fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 75fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef#include "../comedidev.h" 76fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 77fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef#include <linux/pci.h> /* for PCI devices */ 78fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 79fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* Imaginary registers for the imaginary board */ 80fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 81fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef#define SKEL_SIZE 0 82fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 83fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef#define SKEL_START_AI_CONV 0 84fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef#define SKEL_AI_READ 0 85fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 86fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 87fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * Board descriptions for two imaginary boards. Describing the 88fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * boards in this way is optional, and completely driver-dependent. 89fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * Some drivers use arrays such as this, other do not. 90fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 91c1dd2fa6a12bfba92d3522fa43173480f52dbaedBill Pembertonstruct skel_board { 92fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef const char *name; 93fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int ai_chans; 94fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int ai_bits; 95fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int have_dio; 96c1dd2fa6a12bfba92d3522fa43173480f52dbaedBill Pemberton}; 97c1dd2fa6a12bfba92d3522fa43173480f52dbaedBill Pemberton 98c1dd2fa6a12bfba92d3522fa43173480f52dbaedBill Pembertonstatic const struct skel_board skel_boards[] = { 99fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef { 1000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "skel-100", 1010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_chans = 16, 1020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_bits = 12, 1030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .have_dio = 1, 1040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 105fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef { 1060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .name = "skel-200", 1070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_chans = 8, 1080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .ai_bits = 16, 1090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral .have_dio = 0, 1100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral }, 111fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef}; 112fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 113fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* This is used by modprobe to translate PCI IDs to drivers. Should 114fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * only be used for PCI and ISA-PnP devices */ 115fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded 116fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * upstream. */ 117fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef#define PCI_VENDOR_ID_SKEL 0xdafe 118fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleefstatic DEFINE_PCI_DEVICE_TABLE(skel_pci_table) = { 1197af6fb13cada6dfa8144d7c316c60bd7f8bd1ba9Javier Martinez Canillas { PCI_DEVICE(PCI_VENDOR_ID_SKEL, 0x0100) }, 1207af6fb13cada6dfa8144d7c316c60bd7f8bd1ba9Javier Martinez Canillas { PCI_DEVICE(PCI_VENDOR_ID_SKEL, 0x0200) }, 1217af6fb13cada6dfa8144d7c316c60bd7f8bd1ba9Javier Martinez Canillas { 0 } 122fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef}; 123fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 124fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid SchleefMODULE_DEVICE_TABLE(pci, skel_pci_table); 125fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 126fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 127fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * Useful for shorthand access to the particular board structure 128fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 129c1dd2fa6a12bfba92d3522fa43173480f52dbaedBill Pemberton#define thisboard ((const struct skel_board *)dev->board_ptr) 130fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 131fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* this structure is for data unique to this hardware driver. If 132fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef several hardware drivers keep similar information in this structure, 133588063a10f4e21cd3a2cc693c0c1ebb846ac4ce5Ellwyn Cole feel free to suggest moving the variable to the struct comedi_device struct. 134588063a10f4e21cd3a2cc693c0c1ebb846ac4ce5Ellwyn Cole */ 135404d108d8f5968f47ba72417a3532f213e020914Bill Pembertonstruct skel_private { 136404d108d8f5968f47ba72417a3532f213e020914Bill Pemberton 137fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int data; 138fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 139fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* would be useful for a PCI device */ 140fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef struct pci_dev *pci_dev; 141fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 142fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* Used for AO readback */ 143790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton unsigned int ao_readback[2]; 144404d108d8f5968f47ba72417a3532f213e020914Bill Pemberton}; 145404d108d8f5968f47ba72417a3532f213e020914Bill Pemberton 146fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 147fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * most drivers define the following macro to make it easy to 148fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * access the private structure. 149fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 150404d108d8f5968f47ba72417a3532f213e020914Bill Pemberton#define devpriv ((struct skel_private *)dev->private) 151fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 152fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 153139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pemberton * The struct comedi_driver structure tells the Comedi core module 154fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * which functions to call to configure/deconfigure (attach/detach) 155fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * the board, and also about the kernel module that contains 156fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * the device code. 157fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 158da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it); 159da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int skel_detach(struct comedi_device *dev); 160139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_skel = { 16168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .driver_name = "dummy", 16268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .module = THIS_MODULE, 16368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .attach = skel_attach, 16468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .detach = skel_detach, 165fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* It is not necessary to implement the following members if you are 166fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * writing a driver for a ISA PnP or PCI card */ 167fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* Most drivers will support multiple types of boards by 168fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * having an array of board structures. These were defined 169fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * in skel_boards[] above. Note that the element 'name' 170fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * was first in the structure -- Comedi uses this fact to 171fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * extract the name of the board without knowing any details 172fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * about the structure except for its length. 173fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * When a device is attached (by comedi_config), the name 174fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * of the device is given to Comedi, and Comedi tries to 175fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * match it by going through the list of board names. If 176fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * there is a match, the address of the pointer is put 177fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * into dev->board_ptr and driver->attach() is called. 178fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * 179fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * Note that these are not necessary if you can determine 180fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * the type of board in software. ISA PnP, PCI, and PCMCIA 181fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * devices are such boards. 182fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 18368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .board_name = &skel_boards[0].name, 18468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton .offset = sizeof(struct skel_board), 1858629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton .num_names = ARRAY_SIZE(skel_boards), 186fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef}; 187fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 188da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 1890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 190da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int skel_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 1910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 192da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int skel_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 1930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 1940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int skel_dio_insn_bits(struct comedi_device *dev, 1950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 1970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int skel_dio_insn_config(struct comedi_device *dev, 1980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 1990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data); 2000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int skel_ai_cmdtest(struct comedi_device *dev, 2010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, struct comedi_cmd *cmd); 202fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleefstatic int skel_ns_to_timer(unsigned int *ns, int round); 203fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 204fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 205fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * Attach is called by the Comedi core to configure the driver 206fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * for a particular board. If you specified a board_name array 207fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * in the driver structure, dev->board_ptr contains that 208fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * address. 209fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 210da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int skel_attach(struct comedi_device *dev, struct comedi_devconfig *it) 211fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef{ 21234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton struct comedi_subdevice *s; 213fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 214588063a10f4e21cd3a2cc693c0c1ebb846ac4ce5Ellwyn Cole pr_info("comedi%d: skel: ", dev->minor); 215fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 216fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 217fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * If you can probe the device to determine what device in a series 218fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * it is, this is the place to do it. Otherwise, dev->board_ptr 219fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * should already be initialized. 220fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 22197070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton /* dev->board_ptr = skel_probe(dev, it); */ 222fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 223fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 224fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * Initialize dev->board_name. Note that we can use the "thisboard" 225fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * macro now, since we just initialized it in the last line. 226fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 227fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef dev->board_name = thisboard->name; 228fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 229fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 230fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * Allocate the private structure area. alloc_private() is a 231fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * convenient macro defined in comedidev.h. 232fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 233404d108d8f5968f47ba72417a3532f213e020914Bill Pemberton if (alloc_private(dev, sizeof(struct skel_private)) < 0) 234fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return -ENOMEM; 235fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 236fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 237fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * Allocate the subdevice structures. alloc_subdevice() is a 238fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * convenient macro defined in comedidev.h. 239fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 240fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (alloc_subdevices(dev, 3) < 0) 241fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return -ENOMEM; 242fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 243fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s = dev->subdevices + 0; 24497070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton /* dev->read_subdev=s; */ 245fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* analog input subdevice */ 246fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->type = COMEDI_SUBD_AI; 247fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* we support single-ended (ground) and differential */ 248fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; 249fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->n_chan = thisboard->ai_chans; 250fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->maxdata = (1 << thisboard->ai_bits) - 1; 251fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->range_table = &range_bipolar10; 252fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->len_chanlist = 16; /* This is the maximum chanlist length that 253fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef the board can handle */ 254fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->insn_read = skel_ai_rinsn; 25597070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton/* 25697070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton* s->subdev_flags |= SDF_CMD_READ; 25797070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton* s->do_cmd = skel_ai_cmd; 25897070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton*/ 259fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->do_cmdtest = skel_ai_cmdtest; 260fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 261fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s = dev->subdevices + 1; 262fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* analog output subdevice */ 263fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->type = COMEDI_SUBD_AO; 264fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->subdev_flags = SDF_WRITABLE; 265fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->n_chan = 1; 266fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->maxdata = 0xffff; 267fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->range_table = &range_bipolar5; 268fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->insn_write = skel_ao_winsn; 269fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->insn_read = skel_ao_rinsn; 270fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 271fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s = dev->subdevices + 2; 272fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* digital i/o subdevice */ 273fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (thisboard->have_dio) { 274fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->type = COMEDI_SUBD_DIO; 275fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 276fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->n_chan = 16; 277fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->maxdata = 1; 278fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->range_table = &range_digital; 279fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->insn_bits = skel_dio_insn_bits; 280fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->insn_config = skel_dio_insn_config; 281fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } else { 282fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->type = COMEDI_SUBD_UNUSED; 283fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 284fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 285588063a10f4e21cd3a2cc693c0c1ebb846ac4ce5Ellwyn Cole pr_info("attached\n"); 286fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 287fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return 0; 288fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef} 289fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 290fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 291fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * _detach is called to deconfigure a device. It should deallocate 292fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * resources. 293fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * This function is also called when _attach() fails, so it should be 294fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * careful not to release resources that were not necessarily 295fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * allocated by _attach(). dev->private and dev->subdevices are 296fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * deallocated automatically by the core. 297fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 298da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int skel_detach(struct comedi_device *dev) 299fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef{ 300588063a10f4e21cd3a2cc693c0c1ebb846ac4ce5Ellwyn Cole pr_info("comedi%d: skel: remove\n", dev->minor); 301fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 302fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return 0; 303fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef} 304fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 305fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* 306fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * "instructions" read/write data in "one-shot" or "software-triggered" 307fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * mode. 308fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 309da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int skel_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 3100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 311fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef{ 312fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int n, i; 313fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef unsigned int d; 314fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef unsigned int status; 315fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 316fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* a typical programming sequence */ 317fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 318fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* write channel to multiplexer */ 31997070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton /* outw(chan,dev->iobase + SKEL_MUX); */ 320fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 321fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* don't wait for mux to settle */ 322fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 323fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* convert n samples */ 324fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef for (n = 0; n < insn->n; n++) { 325fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* trigger conversion */ 32697070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton /* outw(0,dev->iobase + SKEL_CONVERT); */ 327fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 328fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef#define TIMEOUT 100 329fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* wait for conversion to end */ 330fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef for (i = 0; i < TIMEOUT; i++) { 331fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef status = 1; 33297070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton /* status = inb(dev->iobase + SKEL_STATUS); */ 333fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (status) 334fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef break; 335fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 336fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (i == TIMEOUT) { 3375f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman /* printk() should be used instead of printk() 338fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * whenever the code can be called from real-time. */ 339588063a10f4e21cd3a2cc693c0c1ebb846ac4ce5Ellwyn Cole pr_info("timeout\n"); 340fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return -ETIMEDOUT; 341fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 342fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 343fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* read data */ 34497070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton /* d = inw(dev->iobase + SKEL_AI_DATA); */ 345fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef d = 0; 346fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 347fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* mangle the data as necessary */ 348fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef d ^= 1 << (thisboard->ai_bits - 1); 349fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 350fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef data[n] = d; 351fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 352fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 353fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* return the number of samples read/written */ 354fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return n; 355fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef} 356fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 3570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int skel_ai_cmdtest(struct comedi_device *dev, 3580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, struct comedi_cmd *cmd) 359fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef{ 360fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int err = 0; 361fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int tmp; 362fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 363fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* cmdtest tests a particular command to see if it is valid. 364fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * Using the cmdtest ioctl, a user can create a valid cmd 365fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * and then have it executes by the cmd ioctl. 366fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * 367fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * cmdtest returns 1,2,3,4 or 0, depending on which tests 368fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * the command passes. */ 369fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 370fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* step 1: make sure trigger sources are trivially valid */ 371fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 372fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef tmp = cmd->start_src; 373fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->start_src &= TRIG_NOW; 374fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (!cmd->start_src || tmp != cmd->start_src) 375fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 376fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 377fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef tmp = cmd->scan_begin_src; 378fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT; 379fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 380fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 381fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 382fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef tmp = cmd->convert_src; 383fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->convert_src &= TRIG_TIMER | TRIG_EXT; 384fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (!cmd->convert_src || tmp != cmd->convert_src) 385fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 386fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 387fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef tmp = cmd->scan_end_src; 388fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->scan_end_src &= TRIG_COUNT; 389fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 390fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 391fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 392fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef tmp = cmd->stop_src; 393fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 394fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (!cmd->stop_src || tmp != cmd->stop_src) 395fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 396fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 397fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (err) 398fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return 1; 399fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 400588063a10f4e21cd3a2cc693c0c1ebb846ac4ce5Ellwyn Cole /* step 2: make sure trigger sources are unique and mutually compatible 401588063a10f4e21cd3a2cc693c0c1ebb846ac4ce5Ellwyn Cole */ 402fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 403828684f9a6e096f9150bad523c43b75d74b9baddDirk Hohndel /* note that mutual compatibility is not an issue here */ 404fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->scan_begin_src != TRIG_TIMER && 4050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->scan_begin_src != TRIG_EXT) 406fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 407fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) 408fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 409fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) 410fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 411fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 412fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (err) 413fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return 2; 414fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 415fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* step 3: make sure arguments are trivially compatible */ 416fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 417fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->start_arg != 0) { 418fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->start_arg = 0; 419fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 420fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 421fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef#define MAX_SPEED 10000 /* in nanoseconds */ 422fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef#define MIN_SPEED 1000000000 /* in nanoseconds */ 423fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 424fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->scan_begin_src == TRIG_TIMER) { 425fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->scan_begin_arg < MAX_SPEED) { 426fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->scan_begin_arg = MAX_SPEED; 427fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 428fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 429fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->scan_begin_arg > MIN_SPEED) { 430fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->scan_begin_arg = MIN_SPEED; 431fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 432fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 433fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } else { 434fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* external trigger */ 435fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* should be level/edge, hi/lo specification here */ 436fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* should specify multiple external triggers */ 437fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->scan_begin_arg > 9) { 438fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->scan_begin_arg = 9; 439fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 440fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 441fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 442fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->convert_src == TRIG_TIMER) { 443fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->convert_arg < MAX_SPEED) { 444fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->convert_arg = MAX_SPEED; 445fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 446fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 447fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->convert_arg > MIN_SPEED) { 448fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->convert_arg = MIN_SPEED; 449fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 450fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 451fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } else { 452fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* external trigger */ 453fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* see above */ 454fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->convert_arg > 9) { 455fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->convert_arg = 9; 456fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 457fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 458fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 459fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 460fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->scan_end_arg != cmd->chanlist_len) { 461fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->scan_end_arg = cmd->chanlist_len; 462fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 463fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 464fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->stop_src == TRIG_COUNT) { 465fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->stop_arg > 0x00ffffff) { 466fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->stop_arg = 0x00ffffff; 467fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 468fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 469fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } else { 470fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* TRIG_NONE */ 471fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->stop_arg != 0) { 472fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->stop_arg = 0; 473fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 474fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 475fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 476fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 477fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (err) 478fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return 3; 479fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 480fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* step 4: fix up any arguments */ 481fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 482fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->scan_begin_src == TRIG_TIMER) { 483fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef tmp = cmd->scan_begin_arg; 484fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef skel_ns_to_timer(&cmd->scan_begin_arg, 4850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->flags & TRIG_ROUND_MASK); 486fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (tmp != cmd->scan_begin_arg) 487fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 488fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 489fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->convert_src == TRIG_TIMER) { 490fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef tmp = cmd->convert_arg; 491fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef skel_ns_to_timer(&cmd->convert_arg, 4920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->flags & TRIG_ROUND_MASK); 493fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (tmp != cmd->convert_arg) 494fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 495fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (cmd->scan_begin_src == TRIG_TIMER && 4960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->scan_begin_arg < 4970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->convert_arg * cmd->scan_end_arg) { 498fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef cmd->scan_begin_arg = 4990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral cmd->convert_arg * cmd->scan_end_arg; 500fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef err++; 501fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 502fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 503fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 504fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (err) 505fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return 4; 506fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 507fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return 0; 508fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef} 509fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 510fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* This function doesn't require a particular form, this is just 511fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * what happens to be used in some of the drivers. It should 512fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * convert ns nanoseconds to a counter value suitable for programming 513fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * the device. Also, it should adjust ns so that it cooresponds to 514fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * the actual time that the device will use. */ 515fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleefstatic int skel_ns_to_timer(unsigned int *ns, int round) 516fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef{ 517fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* trivial timer */ 518fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* if your timing is done through two cascaded timers, the 519fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * i8253_cascade_ns_to_timer() function in 8253.h can be 520fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * very helpful. There are also i8254_load() and i8254_mm_load() 521fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * which can be used to load values into the ubiquitous 8254 counters 522fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef */ 523fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 524fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return *ns; 525fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef} 526fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 527da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int skel_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 5280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 529fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef{ 530fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int i; 531fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int chan = CR_CHAN(insn->chanspec); 532fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 533588063a10f4e21cd3a2cc693c0c1ebb846ac4ce5Ellwyn Cole pr_info("skel_ao_winsn\n"); 534fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* Writing a list of values to an AO channel is probably not 535fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * very useful, but that's how the interface is defined. */ 536fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef for (i = 0; i < insn->n; i++) { 537fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* a typical programming sequence */ 53897070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton /* outw(data[i],dev->iobase + SKEL_DA0 + chan); */ 539fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef devpriv->ao_readback[chan] = data[i]; 540fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 541fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 542fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* return the number of samples read/written */ 543fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return i; 544fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef} 545fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 546fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* AO subdevices should have a read insn as well as a write insn. 547fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * Usually this means copying a value stored in devpriv. */ 548da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int skel_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 5490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 550fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef{ 551fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int i; 552fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int chan = CR_CHAN(insn->chanspec); 553fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 554fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef for (i = 0; i < insn->n; i++) 555fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef data[i] = devpriv->ao_readback[chan]; 556fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 557fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return i; 558fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef} 559fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 560fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef/* DIO devices are slightly special. Although it is possible to 561fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * implement the insn_read/insn_write interface, it is much more 562fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * useful to applications if you implement the insn_bits interface. 563fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * This allows packed reading/writing of the DIO channels. The 564fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * comedi core can convert between insn_bits and insn_read/write */ 5650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int skel_dio_insn_bits(struct comedi_device *dev, 5660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 5670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 568fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef{ 569fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (insn->n != 2) 570fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return -EINVAL; 571fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 572fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* The insn data is a mask in data[0] and the new data 573fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * in data[1], each channel cooresponding to a bit. */ 574fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef if (data[0]) { 575fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->state &= ~data[0]; 576fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->state |= data[0] & data[1]; 577fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* Write out the new digital output lines */ 57897070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton /* outw(s->state,dev->iobase + SKEL_DIO); */ 579fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 580fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 581fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* on return, data[1] contains the value of the digital 582fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * input and output lines. */ 58397070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton /* data[1]=inw(dev->iobase + SKEL_DIO); */ 584fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* or we could just return the software copy of the output values if 585fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * it was a purely digital output subdevice */ 58697070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton /* data[1]=s->state; */ 587fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 588fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return 2; 589fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef} 590fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 5910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int skel_dio_insn_config(struct comedi_device *dev, 5920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 5930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_insn *insn, unsigned int *data) 594fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef{ 595fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef int chan = CR_CHAN(insn->chanspec); 596fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 597fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef /* The input or output configuration of each digital line is 598fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * configured by a special insn_config instruction. chanspec 599fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * contains the channel to be changed, and data[0] contains the 600fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef * value COMEDI_INPUT or COMEDI_OUTPUT. */ 601fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef switch (data[0]) { 602fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef case INSN_CONFIG_DIO_OUTPUT: 603fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->io_bits |= 1 << chan; 604fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef break; 605fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef case INSN_CONFIG_DIO_INPUT: 606fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef s->io_bits &= ~(1 << chan); 607fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef break; 608fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef case INSN_CONFIG_DIO_QUERY: 609fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef data[1] = 6100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; 611fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return insn->n; 612fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef break; 613fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef default: 614fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return -EINVAL; 615fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef break; 616fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef } 61797070b32a886d53b7343bcb28ed38d906fa95f50Bill Pemberton /* outw(s->io_bits,dev->iobase + SKEL_DIO_CONFIG); */ 618fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 619fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef return insn->n; 620fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef} 621fc6a12e5076255c7d0160a6e3749b89c7e4b5bebDavid Schleef 622727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas#ifdef CONFIG_COMEDI_PCI 623727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit driver_skel_pci_probe(struct pci_dev *dev, 624727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas const struct pci_device_id *ent) 625727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 626727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas return comedi_pci_auto_config(dev, driver_skel.driver_name); 627727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 628727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 629727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit driver_skel_pci_remove(struct pci_dev *dev) 630727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 631727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas comedi_pci_auto_unconfig(dev); 632727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 633727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 634727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver driver_skel_pci_driver = { 635727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas .id_table = skel_pci_table, 636727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas .probe = &driver_skel_pci_probe, 637727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas .remove = __devexit_p(&driver_skel_pci_remove) 638727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}; 639727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 640727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init driver_skel_init_module(void) 641727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 642727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas int retval; 643727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 644727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas retval = comedi_driver_register(&driver_skel); 645727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas if (retval < 0) 646727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas return retval; 647727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 648727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas driver_skel_pci_driver.name = (char *)driver_skel.driver_name; 649727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas return pci_register_driver(&driver_skel_pci_driver); 650727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 651727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 652727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit driver_skel_cleanup_module(void) 653727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{ 654727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas pci_unregister_driver(&driver_skel_pci_driver); 655727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas comedi_driver_unregister(&driver_skel); 656727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas} 657727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas 658727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(driver_skel_init_module); 659727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(driver_skel_cleanup_module); 660727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas#else 6617114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_skel_init_module(void) 6627114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 6637114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas return comedi_driver_register(&driver_skel); 6647114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 6657114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 6667114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_skel_cleanup_module(void) 6677114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{ 6687114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas comedi_driver_unregister(&driver_skel); 6697114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas} 6707114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas 6717114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_skel_init_module); 6727114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_skel_cleanup_module); 673727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas#endif 67490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 67590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 67690f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 67790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 678