1/** 2@verbatim 3 4Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. 5 6 ADDI-DATA GmbH 7 Dieselstrasse 3 8 D-77833 Ottersweier 9 Tel: +19(0)7223/9493-0 10 Fax: +49(0)7223/9493-92 11 http://www.addi-data.com 12 info@addi-data.com 13 14This program is free software; you can redistribute it and/or modify it under 15the terms of the GNU General Public License as published by the Free Software 16Foundation; either version 2 of the License, or (at your option) any later 17version. 18 19This program is distributed in the hope that it will be useful, but WITHOUT ANY 20WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 21PARTICULAR PURPOSE. See the GNU General Public License for more details. 22 23@endverbatim 24*/ 25/* 26 27 +-----------------------------------------------------------------------+ 28 | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier | 29 +-----------------------------------------------------------------------+ 30 | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | 31 | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | 32 +-----------------------------------------------------------------------+ 33 | Project : ADDI DATA | Compiler : GCC | 34 | Modulname : addi_common.c | Version : 2.96 | 35 +-------------------------------+---------------------------------------+ 36 | Author : | Date : | 37 +-----------------------------------------------------------------------+ 38 | Description : ADDI COMMON Main Module | 39 +-----------------------------------------------------------------------+ 40*/ 41 42static int i_ADDIDATA_InsnReadEeprom(struct comedi_device *dev, 43 struct comedi_subdevice *s, 44 struct comedi_insn *insn, 45 unsigned int *data) 46{ 47 const struct addi_board *this_board = dev->board_ptr; 48 struct addi_private *devpriv = dev->private; 49 unsigned short w_Address = CR_CHAN(insn->chanspec); 50 unsigned short w_Data; 51 52 w_Data = addi_eeprom_readw(devpriv->i_IobaseAmcc, 53 this_board->pc_EepromChip, 2 * w_Address); 54 data[0] = w_Data; 55 56 return insn->n; 57} 58 59static irqreturn_t v_ADDI_Interrupt(int irq, void *d) 60{ 61 struct comedi_device *dev = d; 62 const struct addi_board *this_board = dev->board_ptr; 63 64 this_board->interrupt(irq, d); 65 return IRQ_RETVAL(1); 66} 67 68static int i_ADDI_Reset(struct comedi_device *dev) 69{ 70 const struct addi_board *this_board = dev->board_ptr; 71 72 this_board->reset(dev); 73 return 0; 74} 75 76static int addi_auto_attach(struct comedi_device *dev, 77 unsigned long context_unused) 78{ 79 struct pci_dev *pcidev = comedi_to_pci_dev(dev); 80 const struct addi_board *this_board = dev->board_ptr; 81 struct addi_private *devpriv; 82 struct comedi_subdevice *s; 83 int ret, n_subdevices; 84 unsigned int dw_Dummy; 85 86 dev->board_name = this_board->pc_DriverName; 87 88 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); 89 if (!devpriv) 90 return -ENOMEM; 91 92 ret = comedi_pci_enable(dev); 93 if (ret) 94 return ret; 95 96 if (this_board->i_IorangeBase1) 97 dev->iobase = pci_resource_start(pcidev, 1); 98 else 99 dev->iobase = pci_resource_start(pcidev, 0); 100 101 devpriv->iobase = dev->iobase; 102 devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0); 103 devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2); 104 devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3); 105 106 /* Initialize parameters that can be overridden in EEPROM */ 107 devpriv->s_EeParameters.i_NbrAiChannel = this_board->i_NbrAiChannel; 108 devpriv->s_EeParameters.i_NbrAoChannel = this_board->i_NbrAoChannel; 109 devpriv->s_EeParameters.i_AiMaxdata = this_board->i_AiMaxdata; 110 devpriv->s_EeParameters.i_AoMaxdata = this_board->i_AoMaxdata; 111 devpriv->s_EeParameters.i_NbrDiChannel = this_board->i_NbrDiChannel; 112 devpriv->s_EeParameters.i_NbrDoChannel = this_board->i_NbrDoChannel; 113 devpriv->s_EeParameters.i_DoMaxdata = this_board->i_DoMaxdata; 114 devpriv->s_EeParameters.i_Timer = this_board->i_Timer; 115 devpriv->s_EeParameters.ui_MinAcquisitiontimeNs = 116 this_board->ui_MinAcquisitiontimeNs; 117 devpriv->s_EeParameters.ui_MinDelaytimeNs = 118 this_board->ui_MinDelaytimeNs; 119 120 /* ## */ 121 122 if (pcidev->irq > 0) { 123 ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED, 124 dev->board_name, dev); 125 if (ret == 0) 126 dev->irq = pcidev->irq; 127 } 128 129 /* Read eepeom and fill addi_board Structure */ 130 131 if (this_board->i_PCIEeprom) { 132 if (!(strcmp(this_board->pc_EepromChip, "S5920"))) { 133 /* Set 3 wait stait */ 134 if (!(strcmp(dev->board_name, "apci035"))) 135 outl(0x80808082, devpriv->i_IobaseAmcc + 0x60); 136 else 137 outl(0x83838383, devpriv->i_IobaseAmcc + 0x60); 138 139 /* Enable the interrupt for the controller */ 140 dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38); 141 outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38); 142 } 143 addi_eeprom_read_info(dev, pci_resource_start(pcidev, 0)); 144 } 145 146 n_subdevices = 7; 147 ret = comedi_alloc_subdevices(dev, n_subdevices); 148 if (ret) 149 return ret; 150 151 /* Allocate and Initialise AI Subdevice Structures */ 152 s = &dev->subdevices[0]; 153 if ((devpriv->s_EeParameters.i_NbrAiChannel) 154 || (this_board->i_NbrAiChannelDiff)) { 155 dev->read_subdev = s; 156 s->type = COMEDI_SUBD_AI; 157 s->subdev_flags = 158 SDF_READABLE | SDF_COMMON | SDF_GROUND 159 | SDF_DIFF; 160 if (devpriv->s_EeParameters.i_NbrAiChannel) 161 s->n_chan = devpriv->s_EeParameters.i_NbrAiChannel; 162 else 163 s->n_chan = this_board->i_NbrAiChannelDiff; 164 s->maxdata = devpriv->s_EeParameters.i_AiMaxdata; 165 s->len_chanlist = this_board->i_AiChannelList; 166 s->range_table = this_board->pr_AiRangelist; 167 168 s->insn_config = this_board->ai_config; 169 s->insn_read = this_board->ai_read; 170 s->insn_write = this_board->ai_write; 171 s->insn_bits = this_board->ai_bits; 172 s->do_cmdtest = this_board->ai_cmdtest; 173 s->do_cmd = this_board->ai_cmd; 174 s->cancel = this_board->ai_cancel; 175 176 } else { 177 s->type = COMEDI_SUBD_UNUSED; 178 } 179 180 /* Allocate and Initialise AO Subdevice Structures */ 181 s = &dev->subdevices[1]; 182 if (devpriv->s_EeParameters.i_NbrAoChannel) { 183 s->type = COMEDI_SUBD_AO; 184 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; 185 s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel; 186 s->maxdata = devpriv->s_EeParameters.i_AoMaxdata; 187 s->len_chanlist = 188 devpriv->s_EeParameters.i_NbrAoChannel; 189 s->insn_write = this_board->ao_write; 190 } else { 191 s->type = COMEDI_SUBD_UNUSED; 192 } 193 /* Allocate and Initialise DI Subdevice Structures */ 194 s = &dev->subdevices[2]; 195 if (devpriv->s_EeParameters.i_NbrDiChannel) { 196 s->type = COMEDI_SUBD_DI; 197 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; 198 s->n_chan = devpriv->s_EeParameters.i_NbrDiChannel; 199 s->maxdata = 1; 200 s->len_chanlist = 201 devpriv->s_EeParameters.i_NbrDiChannel; 202 s->range_table = &range_digital; 203 s->insn_config = this_board->di_config; 204 s->insn_read = this_board->di_read; 205 s->insn_write = this_board->di_write; 206 s->insn_bits = this_board->di_bits; 207 } else { 208 s->type = COMEDI_SUBD_UNUSED; 209 } 210 /* Allocate and Initialise DO Subdevice Structures */ 211 s = &dev->subdevices[3]; 212 if (devpriv->s_EeParameters.i_NbrDoChannel) { 213 s->type = COMEDI_SUBD_DO; 214 s->subdev_flags = 215 SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; 216 s->n_chan = devpriv->s_EeParameters.i_NbrDoChannel; 217 s->maxdata = devpriv->s_EeParameters.i_DoMaxdata; 218 s->len_chanlist = 219 devpriv->s_EeParameters.i_NbrDoChannel; 220 s->range_table = &range_digital; 221 222 /* insn_config - for digital output memory */ 223 s->insn_config = this_board->do_config; 224 s->insn_write = this_board->do_write; 225 s->insn_bits = this_board->do_bits; 226 s->insn_read = this_board->do_read; 227 } else { 228 s->type = COMEDI_SUBD_UNUSED; 229 } 230 231 /* Allocate and Initialise Timer Subdevice Structures */ 232 s = &dev->subdevices[4]; 233 if (devpriv->s_EeParameters.i_Timer) { 234 s->type = COMEDI_SUBD_TIMER; 235 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; 236 s->n_chan = 1; 237 s->maxdata = 0; 238 s->len_chanlist = 1; 239 s->range_table = &range_digital; 240 241 s->insn_write = this_board->timer_write; 242 s->insn_read = this_board->timer_read; 243 s->insn_config = this_board->timer_config; 244 s->insn_bits = this_board->timer_bits; 245 } else { 246 s->type = COMEDI_SUBD_UNUSED; 247 } 248 249 /* Allocate and Initialise TTL */ 250 s = &dev->subdevices[5]; 251 s->type = COMEDI_SUBD_UNUSED; 252 253 /* EEPROM */ 254 s = &dev->subdevices[6]; 255 if (this_board->i_PCIEeprom) { 256 s->type = COMEDI_SUBD_MEMORY; 257 s->subdev_flags = SDF_READABLE | SDF_INTERNAL; 258 s->n_chan = 256; 259 s->maxdata = 0xffff; 260 s->insn_read = i_ADDIDATA_InsnReadEeprom; 261 } else { 262 s->type = COMEDI_SUBD_UNUSED; 263 } 264 265 i_ADDI_Reset(dev); 266 return 0; 267} 268 269static void i_ADDI_Detach(struct comedi_device *dev) 270{ 271 if (dev->iobase) 272 i_ADDI_Reset(dev); 273 comedi_pci_detach(dev); 274} 275