static int labpc_pci_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct labpc_boardinfo *board = NULL; struct labpc_private *devpriv; int ret; if (context < ARRAY_SIZE(labpc_pci_boards)) board = &labpc_pci_boards[context]; if (!board) return -ENODEV; dev->board_ptr = board; dev->board_name = board->name; ret = comedi_pci_enable(dev); if (ret) return ret; ret = labpc_pci_mite_init(pcidev); if (ret) return ret; dev->mmio = pci_ioremap_bar(pcidev, 1); if (!dev->mmio) return -ENOMEM; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; return labpc_common_attach(dev, pcidev->irq, IRQF_SHARED); }
/* * This function does some special set-up for the PCIe boards * PCIe215, PCIe236, PCIe296. */ static int dio200_pcie_board_setup(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); void __iomem *brbase; /* * The board uses Altera Cyclone IV with PCI-Express hard IP. * The FPGA configuration has the PCI-Express Avalon-MM Bridge * Control registers in PCI BAR 0, offset 0, and the length of * these registers is 0x4000. * * We need to write 0x80 to the "Avalon-MM to PCI-Express Interrupt * Enable" register at offset 0x50 to allow generation of PCIe * interrupts when RXmlrq_i is asserted in the SOPC Builder system. */ if (pci_resource_len(pcidev, 0) < 0x4000) { dev_err(dev->class_dev, "error! bad PCI region!\n"); return -EINVAL; } brbase = pci_ioremap_bar(pcidev, 0); if (!brbase) { dev_err(dev->class_dev, "error! failed to map registers!\n"); return -ENOMEM; } writel(0x80, brbase + 0x50); iounmap(brbase); /* Enable "enhanced" features of board. */ amplc_dio200_set_enhance(dev, 1); return 0; }
static int pci236_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pci_dev = comedi_to_pci_dev(dev); struct pc236_private *devpriv; unsigned long iobase; int ret; dev_info(dev->class_dev, "amplc_pci236: attach pci %s\n", pci_name(pci_dev)); devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; dev->board_ptr = &pc236_pci_board; dev->board_name = pc236_pci_board.name; ret = comedi_pci_enable(dev); if (ret) return ret; devpriv->lcr_iobase = pci_resource_start(pci_dev, 1); iobase = pci_resource_start(pci_dev, 2); return amplc_pc236_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED); }
static int pci263_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pci_dev = comedi_to_pci_dev(dev); struct comedi_subdevice *s; int ret; ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pci_dev, 2); ret = comedi_alloc_subdevices(dev, 1); if (ret) return ret; s = &dev->subdevices[0]; /* digital output subdevice */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = pci263_do_insn_bits; /* read initial relay state */ s->state = inb(dev->iobase) | (inb(dev->iobase + 1) << 8); return 0; }
static int apci1032_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct apci1032_private *devpriv; struct comedi_subdevice *s; int ret; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; ret = comedi_pci_enable(dev); if (ret) return ret; devpriv->amcc_iobase = pci_resource_start(pcidev, 0); dev->iobase = pci_resource_start(pcidev, 1); apci1032_reset(dev); if (pcidev->irq > 0) { ret = request_irq(pcidev->irq, apci1032_interrupt, IRQF_SHARED, dev->board_name, dev); if (ret == 0) dev->irq = pcidev->irq; } ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; /* Allocate and Initialise DI Subdevice Structures */ s = &dev->subdevices[0]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 32; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = apci1032_di_insn_bits; /* Change-Of-State (COS) interrupt subdevice */ s = &dev->subdevices[1]; if (dev->irq) { dev->read_subdev = s; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_CMD_READ; s->n_chan = 1; s->maxdata = 1; s->range_table = &range_digital; s->insn_config = apci1032_cos_insn_config; s->insn_bits = apci1032_cos_insn_bits; s->len_chanlist = 1; s->do_cmdtest = apci1032_cos_cmdtest; s->do_cmd = apci1032_cos_cmd; s->cancel = apci1032_cos_cancel; } else { s->type = COMEDI_SUBD_UNUSED; } return 0; }
static int labpc_pci_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct labpc_boardinfo *board = NULL; struct labpc_private *devpriv; int ret; if (context < ARRAY_SIZE(labpc_pci_boards)) board = &labpc_pci_boards[context]; if (!board) return -ENODEV; dev->board_ptr = board; dev->board_name = board->name; ret = comedi_pci_enable(dev); if (ret) return ret; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; devpriv->mite = mite_alloc(pcidev); if (!devpriv->mite) return -ENOMEM; ret = mite_setup(devpriv->mite); if (ret < 0) return ret; dev->iobase = (unsigned long)devpriv->mite->daq_io_addr; return labpc_common_attach(dev, mite_irq(devpriv->mite), IRQF_SHARED); }
static int pci6208_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct comedi_subdevice *s; unsigned int val; int ret; ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 2); ret = comedi_alloc_subdevices(dev, 3); if (ret) return ret; s = &dev->subdevices[0]; /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 16; /* Only 8 usable on PCI-6208 */ s->maxdata = 0xffff; s->range_table = &range_bipolar10; s->insn_write = pci6208_ao_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; s = &dev->subdevices[1]; /* digital input subdevice */ s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 4; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = pci6208_di_insn_bits; s = &dev->subdevices[2]; /* digital output subdevice */ s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 4; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = pci6208_do_insn_bits; /* * Get the read back signals from the digital outputs * and save it as the initial state for the subdevice. */ val = inw(dev->iobase + PCI6208_DIO); val = (val & PCI6208_DIO_DO_MASK) >> PCI6208_DIO_DO_SHIFT; s->state = val; return 0; }
static int dio200_pci_auto_attach(struct comedi_device *dev, unsigned long context_model) { struct pci_dev *pci_dev = comedi_to_pci_dev(dev); const struct dio200_board *thisboard = NULL; struct dio200_private *devpriv; unsigned int bar; int ret; if (context_model < ARRAY_SIZE(dio200_pci_boards)) thisboard = &dio200_pci_boards[context_model]; if (!thisboard) return -EINVAL; dev->board_ptr = thisboard; dev->board_name = thisboard->name; dev_info(dev->class_dev, "%s: attach pci %s (%s)\n", dev->driver->driver_name, pci_name(pci_dev), dev->board_name); devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; ret = comedi_pci_enable(dev); if (ret) return ret; bar = thisboard->mainbar; if (pci_resource_len(pci_dev, bar) < thisboard->mainsize) { dev_err(dev->class_dev, "error! PCI region size too small!\n"); return -EINVAL; } if (pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) { devpriv->io.u.membase = pci_ioremap_bar(pci_dev, bar); if (!devpriv->io.u.membase) { dev_err(dev->class_dev, "error! cannot remap registers\n"); return -ENOMEM; } devpriv->io.regtype = mmio_regtype; } else { devpriv->io.u.iobase = pci_resource_start(pci_dev, bar); devpriv->io.regtype = io_regtype; } switch (context_model) { case pcie215_model: case pcie236_model: case pcie296_model: ret = dio200_pcie_board_setup(dev); if (ret < 0) return ret; break; default: break; } return amplc_dio200_common_attach(dev, pci_dev->irq, IRQF_SHARED); }
static void contec_detach(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); if (pcidev) { if (dev->iobase) comedi_pci_disable(pcidev); } }
/** * comedi_pci_disable() - Release the regions and disable the PCI device * @dev: COMEDI device. * * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a * a &struct device embedded in a &struct pci_dev. If the earlier call * to comedi_pci_enable() was successful, release the PCI device's regions * and disable it. Reset @dev->ioenabled back to %false. */ void comedi_pci_disable(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); if (pcidev && dev->ioenabled) { pci_release_regions(pcidev); pci_disable_device(pcidev); } dev->ioenabled = false; }
/** * comedi_pci_detach() - A generic "detach" handler for PCI COMEDI drivers * @dev: COMEDI device. * * COMEDI drivers for PCI devices that need no special clean-up of private data * and have no ioremapped regions other than that pointed to by @dev->mmio may * use this function as its "detach" handler called by the COMEDI core when a * COMEDI device is being detached from the low-level driver. It may be also * called from a more specific "detach" handler that does additional clean-up. * * Free the IRQ if @dev->irq is non-zero, iounmap @dev->mmio if it is * non-%NULL, and call comedi_pci_disable() to release the PCI device's regions * and disable it. */ void comedi_pci_detach(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); if (!pcidev || !dev->ioenabled) return; if (dev->irq) { free_irq(dev->irq, dev); dev->irq = 0; } if (dev->mmio) { iounmap(dev->mmio); dev->mmio = NULL; } comedi_pci_disable(dev); }
static int pci1720_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct comedi_subdevice *s; int ret; ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 2); ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; /* Analog Output subdevice */ s = &dev->subdevices[0]; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 4; s->maxdata = 0x0fff; s->range_table = &pci1720_ao_range; s->insn_write = pci1720_ao_insn_write; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; /* Digital Input subdevice (BoardID SW1) */ s = &dev->subdevices[1]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 4; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = pci1720_di_insn_bits; /* disable synchronized output, channels update when written */ outb(0, dev->iobase + PCI1720_SYNC_CTRL_REG); return 0; }
static int dio200_pci_auto_attach(struct comedi_device *dev, unsigned long context_model) { struct pci_dev *pci_dev = comedi_to_pci_dev(dev); const struct dio200_board *board = NULL; unsigned int bar; int ret; if (context_model < ARRAY_SIZE(dio200_pci_boards)) board = &dio200_pci_boards[context_model]; if (!board) return -EINVAL; dev->board_ptr = board; dev->board_name = board->name; dev_info(dev->class_dev, "%s: attach pci %s (%s)\n", dev->driver->driver_name, pci_name(pci_dev), dev->board_name); ret = comedi_pci_enable(dev); if (ret) return ret; bar = board->mainbar; if (pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) { dev->mmio = pci_ioremap_bar(pci_dev, bar); if (!dev->mmio) { dev_err(dev->class_dev, "error! cannot remap registers\n"); return -ENOMEM; } } else { dev->iobase = pci_resource_start(pci_dev, bar); } if (board->is_pcie) { ret = dio200_pcie_board_setup(dev); if (ret < 0) return ret; } return amplc_dio200_common_attach(dev, pci_dev->irq, IRQF_SHARED); }
/** * comedi_pci_enable() - Enable the PCI device and request the regions * @dev: COMEDI device. * * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a * a &struct device embedded in a &struct pci_dev. Enable the PCI device * and request its regions. Set @dev->ioenabled to %true if successful, * otherwise undo what was done. * * Calls to comedi_pci_enable() and comedi_pci_disable() cannot be nested. * * Return: * 0 on success, * -%ENODEV if @dev->hw_dev is %NULL, * -%EBUSY if regions busy, * or some negative error number if failed to enable PCI device. * */ int comedi_pci_enable(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); int rc; if (!pcidev) return -ENODEV; rc = pci_enable_device(pcidev); if (rc < 0) return rc; rc = pci_request_regions(pcidev, dev->board_name); if (rc < 0) pci_disable_device(pcidev); else dev->ioenabled = true; return rc; }
static int das08_pci_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pdev = comedi_to_pci_dev(dev); struct das08_private_struct *devpriv; int ret; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; /* The das08 driver needs the board_ptr */ dev->board_ptr = &das08_pci_boards[0]; ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pdev, 2); return das08_common_attach(dev, dev->iobase); }
static int ke_counter_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct comedi_subdevice *s; int ret; ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 0); ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; s = &dev->subdevices[0]; s->type = COMEDI_SUBD_COUNTER; s->subdev_flags = SDF_READABLE; s->n_chan = 3; s->maxdata = 0x01ffffff; s->range_table = &range_unknown; s->insn_read = ke_counter_insn_read; s->insn_write = ke_counter_insn_write; s->insn_config = ke_counter_insn_config; s = &dev->subdevices[1]; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 3; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = ke_counter_do_insn_bits; outb(KE_OSC_SEL_20MHZ, dev->iobase + KE_OSC_SEL_REG); ke_counter_reset(dev); return 0; }
static int contec_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct comedi_subdevice *s; int ret; dev->board_name = dev->driver->driver_name; ret = comedi_pci_enable(pcidev, dev->board_name); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 0); ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; s = &dev->subdevices[0]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = contec_di_insn_bits; s = &dev->subdevices[1]; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; s->insn_bits = contec_do_insn_bits; dev_info(dev->class_dev, "%s attached\n", dev->board_name); return 0; }
static int cb_pcimdda_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct comedi_subdevice *s; int ret; ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 3); ret = comedi_alloc_subdevices(dev, 2); if (ret) return ret; s = &dev->subdevices[0]; /* analog output subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE | SDF_READABLE; s->n_chan = 6; s->maxdata = 0xffff; s->range_table = &range_bipolar5; s->insn_write = cb_pcimdda_ao_insn_write; s->insn_read = cb_pcimdda_ao_insn_read; ret = comedi_alloc_subdev_readback(s); if (ret) return ret; s = &dev->subdevices[1]; /* digital i/o subdevice */ ret = subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG); if (ret) return ret; return 0; }
static int pci_8255_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct pci_8255_boardinfo *board = NULL; struct pci_8255_private *devpriv; struct comedi_subdevice *s; bool is_mmio; int ret; int i; if (context < ARRAY_SIZE(pci_8255_boards)) board = &pci_8255_boards[context]; if (!board) return -ENODEV; dev->board_ptr = board; dev->board_name = board->name; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; ret = comedi_pci_enable(dev); if (ret) return ret; if (board->has_mite) { ret = pci_8255_mite_init(pcidev); if (ret) return ret; } is_mmio = (pci_resource_flags(pcidev, board->dio_badr) & IORESOURCE_MEM) != 0; if (is_mmio) { devpriv->mmio_base = pci_ioremap_bar(pcidev, board->dio_badr); if (!devpriv->mmio_base) return -ENOMEM; } else { dev->iobase = pci_resource_start(pcidev, board->dio_badr); } /* * One, two, or four subdevices are setup by this driver depending * on the number of channels provided by the board. Each subdevice * has 24 channels supported by the 8255 module. */ ret = comedi_alloc_subdevices(dev, board->n_8255); if (ret) return ret; for (i = 0; i < board->n_8255; i++) { unsigned long iobase; s = &dev->subdevices[i]; if (is_mmio) { iobase = (unsigned long)(devpriv->mmio_base + (i * 4)); ret = subdev_8255_init(dev, s, pci_8255_mmio, iobase); } else { iobase = dev->iobase + (i * 4); ret = subdev_8255_init(dev, s, NULL, iobase); } if (ret) return ret; } return 0; }
static int apci1500_auto_attach(struct comedi_device *dev, unsigned long context) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct apci1500_private *devpriv; struct comedi_subdevice *s; int ret; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 1); devpriv->iobase = dev->iobase; devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0); devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2); devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3); if (pcidev->irq > 0) { ret = request_irq(pcidev->irq, apci1500_interrupt, IRQF_SHARED, dev->board_name, dev); if (ret == 0) dev->irq = pcidev->irq; } ret = comedi_alloc_subdevices(dev, 3); if (ret) return ret; /* Allocate and Initialise DI Subdevice Structures */ s = &dev->subdevices[0]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; s->insn_config = apci1500_di_config; s->insn_read = apci1500_di_read; s->insn_write = apci1500_di_write; s->insn_bits = apci1500_di_insn_bits; /* Allocate and Initialise DO Subdevice Structures */ s = &dev->subdevices[1]; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_READABLE | SDF_WRITABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; s->insn_config = apci1500_do_config; s->insn_write = apci1500_do_write; s->insn_bits = apci1500_do_bits; /* Allocate and Initialise Timer Subdevice Structures */ s = &dev->subdevices[2]; s->type = COMEDI_SUBD_TIMER; s->subdev_flags = SDF_WRITABLE; s->n_chan = 1; s->maxdata = 0; s->len_chanlist = 1; s->range_table = &range_digital; s->insn_write = apci1500_timer_write; s->insn_read = apci1500_timer_read; s->insn_config = apci1500_timer_config; s->insn_bits = apci1500_timer_bits; apci1500_reset(dev); return 0; }
static int addi_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); const struct addi_board *this_board = dev->board_ptr; struct addi_private *devpriv; struct comedi_subdevice *s; int ret, n_subdevices; unsigned int dw_Dummy; dev->board_name = this_board->pc_DriverName; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; ret = comedi_pci_enable(dev); if (ret) return ret; if (this_board->i_IorangeBase1) dev->iobase = pci_resource_start(pcidev, 1); else dev->iobase = pci_resource_start(pcidev, 0); devpriv->iobase = dev->iobase; devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0); devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2); devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3); /* Initialize parameters that can be overridden in EEPROM */ devpriv->s_EeParameters.i_NbrAiChannel = this_board->i_NbrAiChannel; devpriv->s_EeParameters.i_NbrAoChannel = this_board->i_NbrAoChannel; devpriv->s_EeParameters.i_AiMaxdata = this_board->i_AiMaxdata; devpriv->s_EeParameters.i_AoMaxdata = this_board->i_AoMaxdata; devpriv->s_EeParameters.i_NbrDiChannel = this_board->i_NbrDiChannel; devpriv->s_EeParameters.i_NbrDoChannel = this_board->i_NbrDoChannel; devpriv->s_EeParameters.i_DoMaxdata = this_board->i_DoMaxdata; devpriv->s_EeParameters.i_Timer = this_board->i_Timer; devpriv->s_EeParameters.ui_MinAcquisitiontimeNs = this_board->ui_MinAcquisitiontimeNs; devpriv->s_EeParameters.ui_MinDelaytimeNs = this_board->ui_MinDelaytimeNs; /* ## */ if (pcidev->irq > 0) { ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED, dev->board_name, dev); if (ret == 0) dev->irq = pcidev->irq; } /* Read eepeom and fill addi_board Structure */ if (this_board->i_PCIEeprom) { if (!(strcmp(this_board->pc_EepromChip, "S5920"))) { /* Set 3 wait stait */ if (!(strcmp(dev->board_name, "apci035"))) outl(0x80808082, devpriv->i_IobaseAmcc + 0x60); else outl(0x83838383, devpriv->i_IobaseAmcc + 0x60); /* Enable the interrupt for the controller */ dw_Dummy = inl(devpriv->i_IobaseAmcc + 0x38); outl(dw_Dummy | 0x2000, devpriv->i_IobaseAmcc + 0x38); } addi_eeprom_read_info(dev, pci_resource_start(pcidev, 0)); } n_subdevices = 7; ret = comedi_alloc_subdevices(dev, n_subdevices); if (ret) return ret; /* Allocate and Initialise AI Subdevice Structures */ s = &dev->subdevices[0]; if ((devpriv->s_EeParameters.i_NbrAiChannel) || (this_board->i_NbrAiChannelDiff)) { dev->read_subdev = s; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF; if (devpriv->s_EeParameters.i_NbrAiChannel) s->n_chan = devpriv->s_EeParameters.i_NbrAiChannel; else s->n_chan = this_board->i_NbrAiChannelDiff; s->maxdata = devpriv->s_EeParameters.i_AiMaxdata; s->len_chanlist = this_board->i_AiChannelList; s->range_table = this_board->pr_AiRangelist; s->insn_config = this_board->ai_config; s->insn_read = this_board->ai_read; s->insn_write = this_board->ai_write; s->insn_bits = this_board->ai_bits; s->do_cmdtest = this_board->ai_cmdtest; s->do_cmd = this_board->ai_cmd; s->cancel = this_board->ai_cancel; } else { s->type = COMEDI_SUBD_UNUSED; } /* Allocate and Initialise AO Subdevice Structures */ s = &dev->subdevices[1]; if (devpriv->s_EeParameters.i_NbrAoChannel) { s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel; s->maxdata = devpriv->s_EeParameters.i_AoMaxdata; s->len_chanlist = devpriv->s_EeParameters.i_NbrAoChannel; s->insn_write = this_board->ao_write; } else { s->type = COMEDI_SUBD_UNUSED; } /* Allocate and Initialise DI Subdevice Structures */ s = &dev->subdevices[2]; if (devpriv->s_EeParameters.i_NbrDiChannel) { s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON; s->n_chan = devpriv->s_EeParameters.i_NbrDiChannel; s->maxdata = 1; s->len_chanlist = devpriv->s_EeParameters.i_NbrDiChannel; s->range_table = &range_digital; s->insn_config = this_board->di_config; s->insn_read = this_board->di_read; s->insn_write = this_board->di_write; s->insn_bits = this_board->di_bits; } else { s->type = COMEDI_SUBD_UNUSED; } /* Allocate and Initialise DO Subdevice Structures */ s = &dev->subdevices[3]; if (devpriv->s_EeParameters.i_NbrDoChannel) { s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; s->n_chan = devpriv->s_EeParameters.i_NbrDoChannel; s->maxdata = devpriv->s_EeParameters.i_DoMaxdata; s->len_chanlist = devpriv->s_EeParameters.i_NbrDoChannel; s->range_table = &range_digital; /* insn_config - for digital output memory */ s->insn_config = this_board->do_config; s->insn_write = this_board->do_write; s->insn_bits = this_board->do_bits; s->insn_read = this_board->do_read; } else { s->type = COMEDI_SUBD_UNUSED; } /* Allocate and Initialise Timer Subdevice Structures */ s = &dev->subdevices[4]; if (devpriv->s_EeParameters.i_Timer) { s->type = COMEDI_SUBD_TIMER; s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON; s->n_chan = 1; s->maxdata = 0; s->len_chanlist = 1; s->range_table = &range_digital; s->insn_write = this_board->timer_write; s->insn_read = this_board->timer_read; s->insn_config = this_board->timer_config; s->insn_bits = this_board->timer_bits; } else { s->type = COMEDI_SUBD_UNUSED; } /* Allocate and Initialise TTL */ s = &dev->subdevices[5]; s->type = COMEDI_SUBD_UNUSED; /* EEPROM */ s = &dev->subdevices[6]; if (this_board->i_PCIEeprom) { s->type = COMEDI_SUBD_MEMORY; s->subdev_flags = SDF_READABLE | SDF_INTERNAL; s->n_chan = 256; s->maxdata = 0xffff; s->insn_read = i_ADDIDATA_InsnReadEeprom; } else { s->type = COMEDI_SUBD_UNUSED; } i_ADDI_Reset(dev); return 0; }
static int dyna_pci10xx_auto_attach(struct comedi_device *dev, unsigned long context_unused) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct dyna_pci10xx_private *devpriv; struct comedi_subdevice *s; int ret; devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); if (!devpriv) return -ENOMEM; ret = comedi_pci_enable(dev); if (ret) return ret; dev->iobase = pci_resource_start(pcidev, 2); devpriv->BADR3 = pci_resource_start(pcidev, 3); mutex_init(&devpriv->mutex); ret = comedi_alloc_subdevices(dev, 4); if (ret) return ret; /* analog input */ s = &dev->subdevices[0]; s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF; s->n_chan = 16; s->maxdata = 0x0FFF; s->range_table = &range_pci1050_ai; s->len_chanlist = 16; s->insn_read = dyna_pci10xx_insn_read_ai; /* analog output */ s = &dev->subdevices[1]; s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 16; s->maxdata = 0x0FFF; s->range_table = &range_unipolar10; s->len_chanlist = 16; s->insn_write = dyna_pci10xx_insn_write_ao; /* digital input */ s = &dev->subdevices[2]; s->type = COMEDI_SUBD_DI; s->subdev_flags = SDF_READABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; s->len_chanlist = 16; s->insn_bits = dyna_pci10xx_di_insn_bits; /* digital output */ s = &dev->subdevices[3]; s->type = COMEDI_SUBD_DO; s->subdev_flags = SDF_WRITABLE; s->n_chan = 16; s->maxdata = 1; s->range_table = &range_digital; s->len_chanlist = 16; s->state = 0; s->insn_bits = dyna_pci10xx_do_insn_bits; return 0; }