1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Comedi driver for NI PCMCIA MIO E series cards 4 * 5 * COMEDI - Linux Control and Measurement Device Interface 6 * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> 7 */ 8 9 /* 10 * Driver: ni_mio_cs 11 * Description: National Instruments DAQCard E series 12 * Author: ds 13 * Status: works 14 * Devices: [National Instruments] DAQCard-AI-16XE-50 (ni_mio_cs), 15 * DAQCard-AI-16E-4, DAQCard-6062E, DAQCard-6024E, DAQCard-6036E 16 * Updated: Thu Oct 23 19:43:17 CDT 2003 17 * 18 * See the notes in the ni_atmio.o driver. 19 */ 20 21 /* 22 * The real guts of the driver is in ni_mio_common.c, which is 23 * included by all the E series drivers. 24 * 25 * References for specifications: 26 * 341080a.pdf DAQCard E Series Register Level Programmer Manual 27 */ 28 29 #include <linux/module.h> 30 #include <linux/delay.h> 31 #include <linux/comedi/comedi_pcmcia.h> 32 #include <linux/comedi/comedi_8255.h> 33 34 #include "ni_stc.h" 35 36 /* 37 * AT specific setup 38 */ 39 40 static const struct ni_board_struct ni_boards[] = { 41 { 42 .name = "DAQCard-ai-16xe-50", 43 .device_id = 0x010d, 44 .n_adchan = 16, 45 .ai_maxdata = 0xffff, 46 .ai_fifo_depth = 1024, 47 .gainlkup = ai_gain_8, 48 .ai_speed = 5000, 49 .caldac = { dac8800, dac8043 }, 50 }, { 51 .name = "DAQCard-ai-16e-4", 52 .device_id = 0x010c, 53 .n_adchan = 16, 54 .ai_maxdata = 0x0fff, 55 .ai_fifo_depth = 1024, 56 .gainlkup = ai_gain_16, 57 .ai_speed = 4000, 58 .caldac = { mb88341 }, /* verified */ 59 }, { 60 .name = "DAQCard-6062E", 61 .device_id = 0x02c4, 62 .n_adchan = 16, 63 .ai_maxdata = 0x0fff, 64 .ai_fifo_depth = 8192, 65 .gainlkup = ai_gain_16, 66 .ai_speed = 2000, 67 .n_aochan = 2, 68 .ao_maxdata = 0x0fff, 69 .ao_fifo_depth = 2048, 70 .ao_range_table = &range_bipolar10, 71 .ao_speed = 1176, 72 .caldac = { ad8804_debug }, /* verified */ 73 }, { 74 /* specs incorrect! */ 75 .name = "DAQCard-6024E", 76 .device_id = 0x075e, 77 .n_adchan = 16, 78 .ai_maxdata = 0x0fff, 79 .ai_fifo_depth = 1024, 80 .gainlkup = ai_gain_4, 81 .ai_speed = 5000, 82 .n_aochan = 2, 83 .ao_maxdata = 0x0fff, 84 .ao_range_table = &range_bipolar10, 85 .ao_speed = 1000000, 86 .caldac = { ad8804_debug }, 87 }, { 88 /* specs incorrect! */ 89 .name = "DAQCard-6036E", 90 .device_id = 0x0245, 91 .n_adchan = 16, 92 .ai_maxdata = 0xffff, 93 .ai_fifo_depth = 1024, 94 .alwaysdither = 1, 95 .gainlkup = ai_gain_4, 96 .ai_speed = 5000, 97 .n_aochan = 2, 98 .ao_maxdata = 0xffff, 99 .ao_range_table = &range_bipolar10, 100 .ao_speed = 1000000, 101 .caldac = { ad8804_debug }, 102 }, 103 #if 0 104 { 105 .name = "DAQCard-6715", 106 .device_id = 0x0000, /* unknown */ 107 .n_aochan = 8, 108 .ao_maxdata = 0x0fff, 109 .ao_671x = 8192, 110 .caldac = { mb88341, mb88341 }, 111 }, 112 #endif 113 }; 114 115 #include "ni_mio_common.c" 116 117 static const void *ni_getboardtype(struct comedi_device *dev, 118 struct pcmcia_device *link) 119 { 120 static const struct ni_board_struct *board; 121 int i; 122 123 for (i = 0; i < ARRAY_SIZE(ni_boards); i++) { 124 board = &ni_boards[i]; 125 if (board->device_id == link->card_id) 126 return board; 127 } 128 return NULL; 129 } 130 131 static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data) 132 { 133 int base, ret; 134 135 p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; 136 p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; 137 138 for (base = 0x000; base < 0x400; base += 0x20) { 139 p_dev->resource[0]->start = base; 140 ret = pcmcia_request_io(p_dev); 141 if (!ret) 142 return 0; 143 } 144 return -ENODEV; 145 } 146 147 static int mio_cs_auto_attach(struct comedi_device *dev, 148 unsigned long context) 149 { 150 struct pcmcia_device *link = comedi_to_pcmcia_dev(dev); 151 static const struct ni_board_struct *board; 152 int ret; 153 154 board = ni_getboardtype(dev, link); 155 if (!board) 156 return -ENODEV; 157 dev->board_ptr = board; 158 dev->board_name = board->name; 159 160 link->config_flags |= CONF_AUTO_SET_IO | CONF_ENABLE_IRQ; 161 ret = comedi_pcmcia_enable(dev, mio_pcmcia_config_loop); 162 if (ret) 163 return ret; 164 dev->iobase = link->resource[0]->start; 165 166 link->priv = dev; 167 ret = pcmcia_request_irq(link, ni_E_interrupt); 168 if (ret) 169 return ret; 170 dev->irq = link->irq; 171 172 ret = ni_alloc_private(dev); 173 if (ret) 174 return ret; 175 176 return ni_E_init(dev, 0, 1); 177 } 178 179 static void mio_cs_detach(struct comedi_device *dev) 180 { 181 mio_common_detach(dev); 182 comedi_pcmcia_disable(dev); 183 } 184 185 static struct comedi_driver driver_ni_mio_cs = { 186 .driver_name = "ni_mio_cs", 187 .module = THIS_MODULE, 188 .auto_attach = mio_cs_auto_attach, 189 .detach = mio_cs_detach, 190 }; 191 192 static int cs_attach(struct pcmcia_device *link) 193 { 194 return comedi_pcmcia_auto_config(link, &driver_ni_mio_cs); 195 } 196 197 static const struct pcmcia_device_id ni_mio_cs_ids[] = { 198 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010d), /* DAQCard-ai-16xe-50 */ 199 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010c), /* DAQCard-ai-16e-4 */ 200 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x02c4), /* DAQCard-6062E */ 201 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x075e), /* DAQCard-6024E */ 202 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0245), /* DAQCard-6036E */ 203 PCMCIA_DEVICE_NULL 204 }; 205 MODULE_DEVICE_TABLE(pcmcia, ni_mio_cs_ids); 206 207 static struct pcmcia_driver ni_mio_cs_driver = { 208 .name = "ni_mio_cs", 209 .owner = THIS_MODULE, 210 .id_table = ni_mio_cs_ids, 211 .probe = cs_attach, 212 .remove = comedi_pcmcia_auto_unconfig, 213 }; 214 module_comedi_pcmcia_driver(driver_ni_mio_cs, ni_mio_cs_driver); 215 216 MODULE_DESCRIPTION("Comedi driver for National Instruments DAQCard E series"); 217 MODULE_AUTHOR("David A. Schleef <ds@schleef.org>"); 218 MODULE_LICENSE("GPL"); 219