1eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf/* 2c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * ii_pci20kc.c 3c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Driver for Intelligent Instruments PCI-20001C carrier board and modules. 4eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf * 5c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Copyright (C) 2000 Markus Kempf <kempf@matsci.uni-sb.de> 6c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * with suggestions from David Schleef 16.06.2000 7c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten */ 8c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten 9c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten/* 10c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Driver: ii_pci20kc 11c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Description: Intelligent Instruments PCI-20001C carrier board 12c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Devices: (Intelligent Instrumentation) PCI-20001C [ii_pci20kc] 13c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Author: Markus Kempf <kempf@matsci.uni-sb.de> 14c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Status: works 15eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf * 16c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Supports the PCI-20001C-1a and PCI-20001C-2a carrier boards. The 17c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * -2a version has 32 on-board DIO channels. Three add-on modules 18c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * can be added to the carrier board for additional functionality. 19eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf * 20c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Supported add-on modules: 21c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * PCI-20006M-1 1 channel, 16-bit analog output module 22c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * PCI-20006M-2 2 channel, 16-bit analog output module 23c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * PCI-20341M-1A 4 channel, 16-bit analog input module 24eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf * 25c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * Options: 26c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * 0 Board base address 27c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten * 1 IRQ (not-used) 28eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf */ 29eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 30ce157f8032bbd46d9427034c335b0afd751da25dH Hartley Sweeten#include <linux/module.h> 31eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf#include "../comedidev.h" 32eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 339abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten/* 349abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten * Register I/O map 359abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten */ 3627fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott#define II20K_SIZE 0x400 37f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten#define II20K_MOD_OFFSET 0x100 389abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_REG 0x00 399abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_MOD1_EMPTY (1 << 7) 409abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_MOD2_EMPTY (1 << 6) 419abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_MOD3_EMPTY (1 << 5) 429abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_MASK 0x1f 439abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_PCI20001C_1A 0x1b /* no on-board DIO */ 449abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_ID_PCI20001C_2A 0x1d /* on-board DIO */ 459abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_MOD_STATUS_REG 0x40 469abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_MOD_STATUS_IRQ_MOD1 (1 << 7) 479abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_MOD_STATUS_IRQ_MOD2 (1 << 6) 489abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_MOD_STATUS_IRQ_MOD3 (1 << 5) 499abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIO0_REG 0x80 509abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIO1_REG 0x81 519abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIR_ENA_REG 0x82 529abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIR_DIO3_OUT (1 << 7) 539abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIR_DIO2_OUT (1 << 6) 549abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_BUF_DISAB_DIO3 (1 << 5) 559abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_BUF_DISAB_DIO2 (1 << 4) 569abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIR_DIO1_OUT (1 << 3) 579abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIR_DIO0_OUT (1 << 2) 589abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_BUF_DISAB_DIO1 (1 << 1) 599abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_BUF_DISAB_DIO0 (1 << 0) 609abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL01_REG 0x83 619abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL01_SET (1 << 7) 629abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL01_DIO0_IN (1 << 4) 639abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL01_DIO1_IN (1 << 1) 649abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIO2_REG 0xc0 659abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_DIO3_REG 0xc1 669abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL23_REG 0xc3 679abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL23_SET (1 << 7) 689abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL23_DIO2_IN (1 << 4) 699abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten#define II20K_CTRL23_DIO3_IN (1 << 1) 709abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten 7187a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_ID_PCI20006M_1 0xe2 /* 1 AO channels */ 7287a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_ID_PCI20006M_2 0xe3 /* 2 AO channels */ 7387a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_AO_STRB_REG(x) (0x0b + ((x) * 0x08)) 7487a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_AO_LSB_REG(x) (0x0d + ((x) * 0x08)) 7587a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_AO_MSB_REG(x) (0x0e + ((x) * 0x08)) 7687a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten#define II20K_AO_STRB_BOTH_REG 0x1b 7787a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten 78c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten#define II20K_ID_PCI20341M_1 0x77 /* 4 AI channels */ 793aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_CMD_REG 0x01 803aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_CMD_BUSY (1 << 7) 813aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_CMD_HW_ENA (1 << 1) 823aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_CMD_EXT_START (1 << 0) 833aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_LSB_REG 0x02 843aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_MSB_REG 0x03 853aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_PACER_RESET_REG 0x04 863aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_16BIT_DATA_REG 0x06 873aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CONF_REG 0x10 883aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CONF_ENA (1 << 2) 893aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_OPT_REG 0x11 903aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_OPT_TRIG_ENA (1 << 5) 913aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_OPT_TRIG_INV (1 << 4) 923aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_OPT_TIMEBASE(x) (((x) & 0x3) << 1) 933aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_OPT_BURST_MODE (1 << 0) 943aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_REG 0x12 953aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_INT (1 << 7) 963aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_TRIG (1 << 6) 973aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_TRIG_ENA (1 << 5) 983aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_PACER_ERR (1 << 2) 993aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_DATA_ERR (1 << 1) 1003aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_STATUS_SET_TIME_ERR (1 << 0) 1013aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_LAST_CHAN_ADDR_REG 0x13 1023aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CUR_ADDR_REG 0x14 1033aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_SET_TIME_REG 0x15 1043aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_DELAY_LSB_REG 0x16 1053aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_DELAY_MSB_REG 0x17 1063aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHAN_ADV_REG 0x18 1073aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHAN_RESET_REG 0x19 1083aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_START_TRIG_REG 0x1a 1093aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_COUNT_RESET_REG 0x1b 1103aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_REG 0x80 1113aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_ONBOARD_ONLY (1 << 5) 1123aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_GAIN(x) (((x) & 0x3) << 3) 1133aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_MUX_ENA (1 << 2) 1143aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_CHAN(x) (((x) & 0x3) << 0) 1153aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten#define II20K_AI_CHANLIST_LEN 0x80 116eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 11787a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten/* the AO range is set by jumpers on the 20006M module */ 11887a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweetenstatic const struct comedi_lrange ii20k_ao_ranges = { 11987a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten 3, { 12087a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten BIP_RANGE(5), /* Chan 0 - W1/W3 in Chan 1 - W2/W4 in */ 12187a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten UNI_RANGE(10), /* Chan 0 - W1/W3 out Chan 1 - W2/W4 in */ 12287a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten BIP_RANGE(10) /* Chan 0 - W1/W3 in Chan 1 - W2/W4 out */ 12387a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten } 12487a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten}; 1253366244718f5c95b25cc96318cf448dafa1dcd00H Hartley Sweeten 1263aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweetenstatic const struct comedi_lrange ii20k_ai_ranges = { 1273aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 4, { 1283aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten BIP_RANGE(5), /* gain 1 */ 1293aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten BIP_RANGE(0.5), /* gain 10 */ 1303aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten BIP_RANGE(0.05), /* gain 100 */ 1313aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten BIP_RANGE(0.025) /* gain 200 */ 1323aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten }, 1333366244718f5c95b25cc96318cf448dafa1dcd00H Hartley Sweeten}; 1343366244718f5c95b25cc96318cf448dafa1dcd00H Hartley Sweeten 13557b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweetenstatic void __iomem *ii20k_module_iobase(struct comedi_device *dev, 13657b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten struct comedi_subdevice *s) 13757b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten{ 138d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten return dev->mmio + (s->index + 1) * II20K_MOD_OFFSET; 13957b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten} 14057b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten 141f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweetenstatic int ii20k_ao_insn_write(struct comedi_device *dev, 1420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 143f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten struct comedi_insn *insn, 144f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten unsigned int *data) 145eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf{ 14657b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten void __iomem *iobase = ii20k_module_iobase(dev, s); 14787a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten unsigned int chan = CR_CHAN(insn->chanspec); 14887a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten int i; 149eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 15087a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten for (i = 0; i < insn->n; i++) { 1511fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten unsigned int val = data[i]; 15287a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten 1531fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten s->readback[chan] = val; 154c3c17d2eadce4e497a88783a625e07acb31f1dfbH Hartley Sweeten 15587a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten /* munge data */ 15687a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten val += ((s->maxdata + 1) >> 1); 15787a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten val &= s->maxdata; 15887a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten 15987a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten writeb(val & 0xff, iobase + II20K_AO_LSB_REG(chan)); 16087a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten writeb((val >> 8) & 0xff, iobase + II20K_AO_MSB_REG(chan)); 16187a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten writeb(0x00, iobase + II20K_AO_STRB_REG(chan)); 162eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf } 163eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 16487a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten return insn->n; 165eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf} 166eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 16783b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweetenstatic int ii20k_ai_eoc(struct comedi_device *dev, 16883b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten struct comedi_subdevice *s, 16983b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten struct comedi_insn *insn, 17083b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten unsigned long context) 1713aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten{ 1723aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten void __iomem *iobase = ii20k_module_iobase(dev, s); 1733aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten unsigned char status; 1743aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 17583b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten status = readb(iobase + II20K_AI_STATUS_REG); 17683b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten if ((status & II20K_AI_STATUS_INT) == 0) 17783b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten return 0; 17883b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten return -EBUSY; 1793aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten} 1803aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 1813aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweetenstatic void ii20k_ai_setup(struct comedi_device *dev, 1823aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten struct comedi_subdevice *s, 1833aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten unsigned int chanspec) 1843aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten{ 1853aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten void __iomem *iobase = ii20k_module_iobase(dev, s); 1863aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten unsigned int chan = CR_CHAN(chanspec); 1873aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten unsigned int range = CR_RANGE(chanspec); 1883aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten unsigned char val; 1893aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 1903aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten /* initialize module */ 1913aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten writeb(II20K_AI_CONF_ENA, iobase + II20K_AI_CONF_REG); 1923aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 1933aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten /* software conversion */ 1943aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten writeb(0, iobase + II20K_AI_STATUS_CMD_REG); 1953aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 1963aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten /* set the time base for the settling time counter based on the gain */ 1973aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten val = (range < 3) ? II20K_AI_OPT_TIMEBASE(0) : II20K_AI_OPT_TIMEBASE(2); 1983aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten writeb(val, iobase + II20K_AI_OPT_REG); 1993aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 2003aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten /* set the settling time counter based on the gain */ 2013aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten val = (range < 2) ? 0x58 : (range < 3) ? 0x93 : 0x99; 2023aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten writeb(val, iobase + II20K_AI_SET_TIME_REG); 2033aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 2043aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten /* set number of input channels */ 2053aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten writeb(1, iobase + II20K_AI_LAST_CHAN_ADDR_REG); 2063aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 2073aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten /* set the channel list byte */ 2083aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten val = II20K_AI_CHANLIST_ONBOARD_ONLY | 2093aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten II20K_AI_CHANLIST_MUX_ENA | 2103aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten II20K_AI_CHANLIST_GAIN(range) | 2113aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten II20K_AI_CHANLIST_CHAN(chan); 2123aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten writeb(val, iobase + II20K_AI_CHANLIST_REG); 2133aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 2143aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten /* reset settling time counter and trigger delay counter */ 2153aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten writeb(0, iobase + II20K_AI_COUNT_RESET_REG); 2163aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 2173aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten /* reset channel scanner */ 2183aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten writeb(0, iobase + II20K_AI_CHAN_RESET_REG); 2193aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten} 2203aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 221f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweetenstatic int ii20k_ai_insn_read(struct comedi_device *dev, 2220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral struct comedi_subdevice *s, 223f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten struct comedi_insn *insn, 224f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten unsigned int *data) 225eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf{ 22657b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten void __iomem *iobase = ii20k_module_iobase(dev, s); 2273aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten int ret; 2283aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten int i; 2293555a4c35e59c0217983f5df0cfe39a9fa65c2dfXenofon Foukas 2303aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten ii20k_ai_setup(dev, s, insn->chanspec); 2313555a4c35e59c0217983f5df0cfe39a9fa65c2dfXenofon Foukas 2323aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten for (i = 0; i < insn->n; i++) { 2333aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten unsigned int val; 234eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 2353aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten /* generate a software start convert signal */ 2363aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten readb(iobase + II20K_AI_PACER_RESET_REG); 237eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 23883b4d991253dd764cfcb46fb10ef73bbff913e47H Hartley Sweeten ret = comedi_timeout(dev, s, insn, ii20k_ai_eoc, 0); 2393aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten if (ret) 2403aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten return ret; 241eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 2423aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten val = readb(iobase + II20K_AI_LSB_REG); 2433aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten val |= (readb(iobase + II20K_AI_MSB_REG) << 8); 244eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 2453aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten /* munge two's complement data */ 2463aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten val += ((s->maxdata + 1) >> 1); 2473aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten val &= s->maxdata; 2483aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 2493aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten data[i] = val; 2503aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten } 2513aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten 2523aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten return insn->n; 253842525c6c1efa0bfefb7fb96838ef6ec588ce95eH Hartley Sweeten} 254842525c6c1efa0bfefb7fb96838ef6ec588ce95eH Hartley Sweeten 2559abeb196a740bd52401a24108df27e20576da036H Hartley Sweetenstatic void ii20k_dio_config(struct comedi_device *dev, 2569abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten struct comedi_subdevice *s) 257eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf{ 2589abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten unsigned char ctrl01 = 0; 2599abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten unsigned char ctrl23 = 0; 2609abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten unsigned char dir_ena = 0; 261eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 2629abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* port 0 - channels 0-7 */ 263eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf if (s->io_bits & 0x000000ff) { 2649abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* output port */ 2659abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ctrl01 &= ~II20K_CTRL01_DIO0_IN; 2669abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena &= ~II20K_BUF_DISAB_DIO0; 2679abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena |= II20K_DIR_DIO0_OUT; 268eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf } else { 2699abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* input port */ 2709abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ctrl01 |= II20K_CTRL01_DIO0_IN; 2719abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena &= ~II20K_DIR_DIO0_OUT; 272eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf } 2739abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten 2749abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* port 1 - channels 8-15 */ 275eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf if (s->io_bits & 0x0000ff00) { 2769abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* output port */ 2779abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ctrl01 &= ~II20K_CTRL01_DIO1_IN; 2789abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena &= ~II20K_BUF_DISAB_DIO1; 2799abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena |= II20K_DIR_DIO1_OUT; 280eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf } else { 2819abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* input port */ 2829abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ctrl01 |= II20K_CTRL01_DIO1_IN; 2839abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena &= ~II20K_DIR_DIO1_OUT; 284eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf } 2859abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten 2869abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* port 2 - channels 16-23 */ 287eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf if (s->io_bits & 0x00ff0000) { 2889abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* output port */ 2899abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ctrl23 &= ~II20K_CTRL23_DIO2_IN; 2909abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena &= ~II20K_BUF_DISAB_DIO2; 2919abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena |= II20K_DIR_DIO2_OUT; 292eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf } else { 2939abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* input port */ 2949abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ctrl23 |= II20K_CTRL23_DIO2_IN; 2959abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena &= ~II20K_DIR_DIO2_OUT; 296eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf } 2979abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten 2989abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* port 3 - channels 24-31 */ 299eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf if (s->io_bits & 0xff000000) { 3009abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* output port */ 3019abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ctrl23 &= ~II20K_CTRL23_DIO3_IN; 3029abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena &= ~II20K_BUF_DISAB_DIO3; 3039abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena |= II20K_DIR_DIO3_OUT; 304eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf } else { 3059abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* input port */ 3069abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ctrl23 |= II20K_CTRL23_DIO3_IN; 3079abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten dir_ena &= ~II20K_DIR_DIO3_OUT; 308eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf } 3099abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten 3109abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ctrl23 |= II20K_CTRL01_SET; 3119abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ctrl23 |= II20K_CTRL23_SET; 3129abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten 3139abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* order is important */ 314d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten writeb(ctrl01, dev->mmio + II20K_CTRL01_REG); 315d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten writeb(ctrl23, dev->mmio + II20K_CTRL23_REG); 316d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten writeb(dir_ena, dev->mmio + II20K_DIR_ENA_REG); 317eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf} 318eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 3199abeb196a740bd52401a24108df27e20576da036H Hartley Sweetenstatic int ii20k_dio_insn_config(struct comedi_device *dev, 3209abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten struct comedi_subdevice *s, 3219abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten struct comedi_insn *insn, 3229abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten unsigned int *data) 323eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf{ 3245dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten unsigned int chan = CR_CHAN(insn->chanspec); 3255dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten unsigned int mask; 3265dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten int ret; 3275dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten 3285dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten if (chan < 8) 3295dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten mask = 0x000000ff; 3305dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten else if (chan < 16) 3315dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten mask = 0x0000ff00; 3325dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten else if (chan < 24) 3335dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten mask = 0x00ff0000; 33463d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten else 3355dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten mask = 0xff000000; 3365dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten 3375dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten ret = comedi_dio_insn_config(dev, s, insn, data, mask); 3385dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten if (ret) 3395dacadcca3176e2b1f8db662e503c080484d71faH Hartley Sweeten return ret; 34063d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten 3419abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ii20k_dio_config(dev, s); 3429abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten 3439abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten return insn->n; 344eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf} 345eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 3469abeb196a740bd52401a24108df27e20576da036H Hartley Sweetenstatic int ii20k_dio_insn_bits(struct comedi_device *dev, 3479abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten struct comedi_subdevice *s, 3489abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten struct comedi_insn *insn, 3499abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten unsigned int *data) 350eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf{ 3519b13bc1d4ab0c5abc1b29d4fa95a41bf02238d2aH Hartley Sweeten unsigned int mask; 3529abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten 3539b13bc1d4ab0c5abc1b29d4fa95a41bf02238d2aH Hartley Sweeten mask = comedi_dio_update_state(s, data); 3549abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten if (mask) { 3559abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten if (mask & 0x000000ff) 3569abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten writeb((s->state >> 0) & 0xff, 357d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten dev->mmio + II20K_DIO0_REG); 3589abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten if (mask & 0x0000ff00) 3599abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten writeb((s->state >> 8) & 0xff, 360d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten dev->mmio + II20K_DIO1_REG); 3619abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten if (mask & 0x00ff0000) 3629abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten writeb((s->state >> 16) & 0xff, 363d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten dev->mmio + II20K_DIO2_REG); 3649abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten if (mask & 0xff000000) 3659abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten writeb((s->state >> 24) & 0xff, 366d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten dev->mmio + II20K_DIO3_REG); 3679abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten } 368eb3a3c1b7c92a129f43541c6ceb0e277fc61e354Markus Kempf 369d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten data[1] = readb(dev->mmio + II20K_DIO0_REG); 370d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten data[1] |= readb(dev->mmio + II20K_DIO1_REG) << 8; 371d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten data[1] |= readb(dev->mmio + II20K_DIO2_REG) << 16; 372d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten data[1] |= readb(dev->mmio + II20K_DIO3_REG) << 24; 37363d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten 37463d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten return insn->n; 37563d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten} 37663d6e8ff0d25256d57453959c4d192b950a417ceH Hartley Sweeten 377f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweetenstatic int ii20k_init_module(struct comedi_device *dev, 3783aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten struct comedi_subdevice *s) 379f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten{ 38057b2161f021c26f56574edfaaaa9503f877fc1a2H Hartley Sweeten void __iomem *iobase = ii20k_module_iobase(dev, s); 381f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten unsigned char id; 3821fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten int ret; 383f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten 384f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten id = readb(iobase + II20K_ID_REG); 385f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten switch (id) { 38687a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten case II20K_ID_PCI20006M_1: 38787a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten case II20K_ID_PCI20006M_2: 388f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten /* Analog Output subdevice */ 389f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->type = COMEDI_SUBD_AO; 390f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->subdev_flags = SDF_WRITABLE; 39187a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten s->n_chan = (id == II20K_ID_PCI20006M_2) ? 2 : 1; 392f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->maxdata = 0xffff; 39387a61614e3cd841cb6d73878b46d8e858418e536H Hartley Sweeten s->range_table = &ii20k_ao_ranges; 394f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->insn_write = ii20k_ao_insn_write; 3951fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten s->insn_read = comedi_readback_insn_read; 3961fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten 3971fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten ret = comedi_alloc_subdev_readback(s); 3981fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten if (ret) 3991fd142ce3d23ea5168b2c0eebca5c9fbdce632efH Hartley Sweeten return ret; 400f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten break; 401c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten case II20K_ID_PCI20341M_1: 402f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten /* Analog Input subdevice */ 403f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->type = COMEDI_SUBD_AI; 4043aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten s->subdev_flags = SDF_READABLE | SDF_DIFF; 405f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->n_chan = 4; 406f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->maxdata = 0xffff; 4073aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten s->range_table = &ii20k_ai_ranges; 408f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->insn_read = ii20k_ai_insn_read; 409f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten break; 410f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten default: 411f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->type = COMEDI_SUBD_UNUSED; 412f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten break; 413f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten } 414f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten 415f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten return 0; 416f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten} 417f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten 418c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweetenstatic int ii20k_attach(struct comedi_device *dev, 419c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten struct comedi_devconfig *it) 4200f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten{ 4219abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten struct comedi_subdevice *s; 42227fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott unsigned int membase; 4239abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten unsigned char id; 4249abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten bool has_dio; 4259abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten int ret; 4260f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten 42727fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott membase = it->options[0]; 42827fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott if (!membase || (membase & ~(0x100000 - II20K_SIZE))) { 42927fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott dev_warn(dev->class_dev, 43027fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott "%s: invalid memory address specified\n", 43127fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott dev->board_name); 43227fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott return -EINVAL; 43327fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott } 43427fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott 43527fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott if (!request_mem_region(membase, II20K_SIZE, dev->board_name)) { 43627fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott dev_warn(dev->class_dev, "%s: I/O mem conflict (%#x,%u)\n", 43727fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott dev->board_name, membase, II20K_SIZE); 43827fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott return -EIO; 43927fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott } 44027fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott dev->iobase = membase; /* actually, a memory address */ 44127fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott 44227fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott dev->mmio = ioremap(membase, II20K_SIZE); 44327fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott if (!dev->mmio) 44427fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott return -ENOMEM; 4450f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten 446d6e497b92f4296db79577a05d399ba20a58b719bH Hartley Sweeten id = readb(dev->mmio + II20K_ID_REG); 4479abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten switch (id & II20K_ID_MASK) { 4489abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten case II20K_ID_PCI20001C_1A: 44927a2234edd4a5c8b0ebdaaa3f6a5f00183f3154fChristian Engelmayer has_dio = false; 4509abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten break; 4519abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten case II20K_ID_PCI20001C_2A: 4529abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten has_dio = true; 4539abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten break; 4549abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten default: 4559abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten return -ENODEV; 4560f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten } 4570f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten 4589abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ret = comedi_alloc_subdevices(dev, 4); 4599abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten if (ret) 4609abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten return ret; 4619abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten 462f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s = &dev->subdevices[0]; 463f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten if (id & II20K_ID_MOD1_EMPTY) { 464f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->type = COMEDI_SUBD_UNUSED; 465f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten } else { 4663aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten ret = ii20k_init_module(dev, s); 467f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten if (ret) 468f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten return ret; 469f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten } 470f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten 471f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s = &dev->subdevices[1]; 472f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten if (id & II20K_ID_MOD2_EMPTY) { 473f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->type = COMEDI_SUBD_UNUSED; 474f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten } else { 4753aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten ret = ii20k_init_module(dev, s); 476f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten if (ret) 477f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten return ret; 478f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten } 479f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten 480f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s = &dev->subdevices[2]; 481f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten if (id & II20K_ID_MOD3_EMPTY) { 482f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten s->type = COMEDI_SUBD_UNUSED; 483f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten } else { 4843aa5e81177bd8bf235d2b506659a3ecd05d67634H Hartley Sweeten ret = ii20k_init_module(dev, s); 485f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten if (ret) 486f0e32df3d21f048ee35c07e523e918015845d95fH Hartley Sweeten return ret; 4870f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten } 4880f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten 4899abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* Digital I/O subdevice */ 4909abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten s = &dev->subdevices[3]; 4919abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten if (has_dio) { 4929abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten s->type = COMEDI_SUBD_DIO; 4939abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 4949abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten s->n_chan = 32; 4959abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten s->maxdata = 1; 4969abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten s->range_table = &range_digital; 4979abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten s->insn_bits = ii20k_dio_insn_bits; 4989abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten s->insn_config = ii20k_dio_insn_config; 4999abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten 5009abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten /* default all channels to input */ 5019abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten ii20k_dio_config(dev, s); 5029abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten } else { 5039abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten s->type = COMEDI_SUBD_UNUSED; 5049abeb196a740bd52401a24108df27e20576da036H Hartley Sweeten } 5050f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten 506c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten return 0; 5070f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten} 5080f8409dc057935900a53d4781bcbb77149348267H Hartley Sweeten 50927fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbottstatic void ii20k_detach(struct comedi_device *dev) 51027fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott{ 51127fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott if (dev->mmio) 51227fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott iounmap(dev->mmio); 51327fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott if (dev->iobase) /* actually, a memory address */ 51427fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott release_mem_region(dev->iobase, II20K_SIZE); 51527fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott} 51627fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott 517c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweetenstatic struct comedi_driver ii20k_driver = { 5182396472f2aed86884a446109c5b51a3702028339H Hartley Sweeten .driver_name = "ii_pci20kc", 5192396472f2aed86884a446109c5b51a3702028339H Hartley Sweeten .module = THIS_MODULE, 520c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweeten .attach = ii20k_attach, 52127fc26f99e63bcbe42176f08eaf590bff81a2e1cIan Abbott .detach = ii20k_detach, 5222396472f2aed86884a446109c5b51a3702028339H Hartley Sweeten}; 523c325f9a9edf24dfc13145b5fce792aec577fe381H Hartley Sweetenmodule_comedi_driver(ii20k_driver); 52490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas 52590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org"); 52690f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver"); 52790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL"); 528