diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/daqboard2000.c')
-rw-r--r-- | drivers/staging/comedi/drivers/daqboard2000.c | 467 |
1 files changed, 203 insertions, 264 deletions
diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c index ef28385c1482..d13c8c5822bf 100644 --- a/drivers/staging/comedi/drivers/daqboard2000.c +++ b/drivers/staging/comedi/drivers/daqboard2000.c @@ -31,16 +31,10 @@ Devices: [IOTech] DAQBoard/2000 (daqboard2000) Much of the functionality of this driver was determined from reading the source code for the Windows driver. -The FPGA on the board requires initialization code, which can -be loaded by comedi_config using the -i -option. The initialization code is available from http://www.comedi.org -in the comedi_nonfree_firmware tarball. - -Configuration options: - [0] - PCI bus of device (optional) - [1] - PCI slot of device (optional) - If bus/slot is not specified, the first supported - PCI device found will be used. +The FPGA on the board requires fimware, which is available from +http://www.comedi.org in the comedi_nonfree_firmware tarball. + +Configuration options: not applicable, uses PCI auto config */ /* This card was obviously never intended to leave the Windows world, @@ -117,17 +111,17 @@ Configuration options: #include <linux/delay.h> #include <linux/interrupt.h> +#include <linux/firmware.h> #include "8255.h" +#define DAQBOARD2000_FIRMWARE "daqboard2000_firmware.bin" + #define PCI_VENDOR_ID_IOTECH 0x1616 #define DAQBOARD2000_SUBSYSTEM_IDS2 0x0002 /* Daqboard/2000 - 2 Dacs */ #define DAQBOARD2000_SUBSYSTEM_IDS4 0x0004 /* Daqboard/2000 - 4 Dacs */ -#define DAQBOARD2000_DAQ_SIZE 0x1002 -#define DAQBOARD2000_PLX_SIZE 0x100 - /* Initialization bits for the Serial EEPROM Control Register */ #define DAQBOARD2000_SECRProgPinHi 0x8001767e #define DAQBOARD2000_SECRProgPinLo 0x8000767e @@ -143,85 +137,56 @@ Configuration options: #define DAQBOARD2000_CPLD_INIT 0x0002 #define DAQBOARD2000_CPLD_DONE 0x0004 -/* Available ranges */ -static const struct comedi_lrange range_daqboard2000_ai = { 13, { - RANGE(-10, 10), - RANGE(-5, 5), - RANGE(-2.5, - 2.5), - RANGE(-1.25, - 1.25), - RANGE(-0.625, - 0.625), - RANGE(-0.3125, - 0.3125), - RANGE(-0.156, - 0.156), - RANGE(0, 10), - RANGE(0, 5), - RANGE(0, 2.5), - RANGE(0, 1.25), - RANGE(0, - 0.625), - RANGE(0, - 0.3125) - } -}; - -static const struct comedi_lrange range_daqboard2000_ao = { 1, { - RANGE(-10, 10) - } +static const struct comedi_lrange range_daqboard2000_ai = { + 13, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25), + BIP_RANGE(0.625), + BIP_RANGE(0.3125), + BIP_RANGE(0.156), + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25), + UNI_RANGE(0.625), + UNI_RANGE(0.3125) + } }; -struct daqboard2000_hw { - volatile u16 acqControl; /* 0x00 */ - volatile u16 acqScanListFIFO; /* 0x02 */ - volatile u32 acqPacerClockDivLow; /* 0x04 */ - - volatile u16 acqScanCounter; /* 0x08 */ - volatile u16 acqPacerClockDivHigh; /* 0x0a */ - volatile u16 acqTriggerCount; /* 0x0c */ - volatile u16 fill2; /* 0x0e */ - volatile u16 acqResultsFIFO; /* 0x10 */ - volatile u16 fill3; /* 0x12 */ - volatile u16 acqResultsShadow; /* 0x14 */ - volatile u16 fill4; /* 0x16 */ - volatile u16 acqAdcResult; /* 0x18 */ - volatile u16 fill5; /* 0x1a */ - volatile u16 dacScanCounter; /* 0x1c */ - volatile u16 fill6; /* 0x1e */ - - volatile u16 dacControl; /* 0x20 */ - volatile u16 fill7; /* 0x22 */ - volatile s16 dacFIFO; /* 0x24 */ - volatile u16 fill8[2]; /* 0x26 */ - volatile u16 dacPacerClockDiv; /* 0x2a */ - volatile u16 refDacs; /* 0x2c */ - volatile u16 fill9; /* 0x2e */ - - volatile u16 dioControl; /* 0x30 */ - volatile s16 dioP3hsioData; /* 0x32 */ - volatile u16 dioP3Control; /* 0x34 */ - volatile u16 calEepromControl; /* 0x36 */ - volatile s16 dacSetting[4]; /* 0x38 */ - volatile s16 dioP2ExpansionIO8Bit[32]; /* 0x40 */ - - volatile u16 ctrTmrControl; /* 0x80 */ - volatile u16 fill10[3]; /* 0x82 */ - volatile s16 ctrInput[4]; /* 0x88 */ - volatile u16 fill11[8]; /* 0x90 */ - volatile u16 timerDivisor[2]; /* 0xa0 */ - volatile u16 fill12[6]; /* 0xa4 */ - - volatile u16 dmaControl; /* 0xb0 */ - volatile u16 trigControl; /* 0xb2 */ - volatile u16 fill13[2]; /* 0xb4 */ - volatile u16 calEeprom; /* 0xb8 */ - volatile u16 acqDigitalMark; /* 0xba */ - volatile u16 trigDacs; /* 0xbc */ - volatile u16 fill14; /* 0xbe */ - volatile s16 dioP2ExpansionIO16Bit[32]; /* 0xc0 */ -}; +/* + * Register Memory Map + */ +#define acqControl 0x00 /* u16 */ +#define acqScanListFIFO 0x02 /* u16 */ +#define acqPacerClockDivLow 0x04 /* u32 */ +#define acqScanCounter 0x08 /* u16 */ +#define acqPacerClockDivHigh 0x0a /* u16 */ +#define acqTriggerCount 0x0c /* u16 */ +#define acqResultsFIFO 0x10 /* u16 */ +#define acqResultsShadow 0x14 /* u16 */ +#define acqAdcResult 0x18 /* u16 */ +#define dacScanCounter 0x1c /* u16 */ +#define dacControl 0x20 /* u16 */ +#define dacFIFO 0x24 /* s16 */ +#define dacPacerClockDiv 0x2a /* u16 */ +#define refDacs 0x2c /* u16 */ +#define dioControl 0x30 /* u16 */ +#define dioP3hsioData 0x32 /* s16 */ +#define dioP3Control 0x34 /* u16 */ +#define calEepromControl 0x36 /* u16 */ +#define dacSetting(x) (0x38 + (x)*2) /* s16 */ +#define dioP2ExpansionIO8Bit 0x40 /* s16 */ +#define ctrTmrControl 0x80 /* u16 */ +#define ctrInput(x) (0x88 + (x)*2) /* s16 */ +#define timerDivisor(x) (0xa0 + (x)*2) /* u16 */ +#define dmaControl 0xb0 /* u16 */ +#define trigControl 0xb2 /* u16 */ +#define calEeprom 0xb8 /* u16 */ +#define acqDigitalMark 0xba /* u16 */ +#define trigDacs 0xbc /* u16 */ +#define dioP2ExpansionIO16Bit(x) (0xc0 + (x)*2) /* s16 */ /* Scan Sequencer programming */ #define DAQBOARD2000_SeqStartScanList 0x0011 @@ -311,27 +276,23 @@ static const struct daq200_boardtype boardtypes[] = { {"ids4", DAQBOARD2000_SUBSYSTEM_IDS4}, }; -#define this_board ((const struct daq200_boardtype *)dev->board_ptr) - struct daqboard2000_private { enum { card_daqboard_2000 } card; - void *daq; + void __iomem *daq; void __iomem *plx; unsigned int ao_readback[2]; }; -#define devpriv ((struct daqboard2000_private *)dev->private) - static void writeAcqScanListEntry(struct comedi_device *dev, u16 entry) { - struct daqboard2000_hw *fpga = devpriv->daq; + struct daqboard2000_private *devpriv = dev->private; -/* udelay(4); */ - fpga->acqScanListFIFO = entry & 0x00ff; -/* udelay(4); */ - fpga->acqScanListFIFO = (entry >> 8) & 0x00ff; + /* udelay(4); */ + writew(entry & 0x00ff, devpriv->daq + acqScanListFIFO); + /* udelay(4); */ + writew((entry >> 8) & 0x00ff, devpriv->daq + acqScanListFIFO); } static void setup_sampling(struct comedi_device *dev, int chan, int gain) @@ -372,7 +333,6 @@ static void setup_sampling(struct comedi_device *dev, int chan, int gain) /* These should be read from EEPROM */ word2 |= 0x0800; word3 |= 0xc000; -/* printk("%d %4.4x %4.4x %4.4x %4.4x\n", chan, word0, word1, word2, word3);*/ writeAcqScanListEntry(dev, word0); writeAcqScanListEntry(dev, word1); writeAcqScanListEntry(dev, word2); @@ -384,21 +344,22 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int i; - struct daqboard2000_hw *fpga = devpriv->daq; + struct daqboard2000_private *devpriv = dev->private; + unsigned int val; int gain, chan, timeout; + int i; - fpga->acqControl = - DAQBOARD2000_AcqResetScanListFifo | - DAQBOARD2000_AcqResetResultsFifo | DAQBOARD2000_AcqResetConfigPipe; + writew(DAQBOARD2000_AcqResetScanListFifo | + DAQBOARD2000_AcqResetResultsFifo | + DAQBOARD2000_AcqResetConfigPipe, devpriv->daq + acqControl); /* * If pacer clock is not set to some high value (> 10 us), we * risk multiple samples to be put into the result FIFO. */ /* 1 second, should be long enough */ - fpga->acqPacerClockDivLow = 1000000; - fpga->acqPacerClockDivHigh = 0; + writel(1000000, devpriv->daq + acqPacerClockDivLow); + writew(0, devpriv->daq + acqPacerClockDivHigh); gain = CR_RANGE(insn->chanspec); chan = CR_CHAN(insn->chanspec); @@ -410,28 +371,30 @@ static int daqboard2000_ai_insn_read(struct comedi_device *dev, for (i = 0; i < insn->n; i++) { setup_sampling(dev, chan, gain); /* Enable reading from the scanlist FIFO */ - fpga->acqControl = DAQBOARD2000_SeqStartScanList; + writew(DAQBOARD2000_SeqStartScanList, + devpriv->daq + acqControl); for (timeout = 0; timeout < 20; timeout++) { - if (fpga->acqControl & DAQBOARD2000_AcqConfigPipeFull) + val = readw(devpriv->daq + acqControl); + if (val & DAQBOARD2000_AcqConfigPipeFull) break; /* udelay(2); */ } - fpga->acqControl = DAQBOARD2000_AdcPacerEnable; + writew(DAQBOARD2000_AdcPacerEnable, devpriv->daq + acqControl); for (timeout = 0; timeout < 20; timeout++) { - if (fpga->acqControl & DAQBOARD2000_AcqLogicScanning) + val = readw(devpriv->daq + acqControl); + if (val & DAQBOARD2000_AcqLogicScanning) break; /* udelay(2); */ } for (timeout = 0; timeout < 20; timeout++) { - if (fpga->acqControl & - DAQBOARD2000_AcqResultsFIFOHasValidData) { + val = readw(devpriv->daq + acqControl); + if (val & DAQBOARD2000_AcqResultsFIFOHasValidData) break; - } /* udelay(2); */ } - data[i] = fpga->acqResultsFIFO; - fpga->acqControl = DAQBOARD2000_AdcPacerDisable; - fpga->acqControl = DAQBOARD2000_SeqStopScanList; + data[i] = readw(devpriv->daq + acqResultsFIFO); + writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl); + writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl); } return i; @@ -442,8 +405,9 @@ static int daqboard2000_ao_insn_read(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int i; + struct daqboard2000_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); + int i; for (i = 0; i < insn->n; i++) data[i] = devpriv->ao_readback[chan]; @@ -456,28 +420,39 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { - int i; + struct daqboard2000_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); - struct daqboard2000_hw *fpga = devpriv->daq; + unsigned int val; int timeout; + int i; for (i = 0; i < insn->n; i++) { +#if 0 /* - * OK, since it works OK without enabling the DAC's, let's keep - * it as simple as possible... + * OK, since it works OK without enabling the DAC's, + * let's keep it as simple as possible... */ - /* fpga->dacControl = (chan + 2) * 0x0010 | 0x0001; udelay(1000); */ - fpga->dacSetting[chan] = data[i]; + writew((chan + 2) * 0x0010 | 0x0001, + devpriv->daq + dacControl); + udelay(1000); +#endif + writew(data[i], devpriv->daq + dacSetting(chan)); for (timeout = 0; timeout < 20; timeout++) { - if ((fpga->dacControl & ((chan + 1) * 0x0010)) == 0) + val = readw(devpriv->daq + dacControl); + if ((val & ((chan + 1) * 0x0010)) == 0) break; /* udelay(2); */ } devpriv->ao_readback[chan] = data[i]; +#if 0 /* - * Since we never enabled the DAC's, we don't need to disable it... - * fpga->dacControl = (chan + 2) * 0x0010 | 0x0000; udelay(1000); + * Since we never enabled the DAC's, we don't need + * to disable it... */ + writew((chan + 2) * 0x0010 | 0x0000, + devpriv->daq + dacControl); + udelay(1000); +#endif } return i; @@ -485,7 +460,8 @@ static int daqboard2000_ao_insn_write(struct comedi_device *dev, static void daqboard2000_resetLocalBus(struct comedi_device *dev) { - dev_dbg(dev->class_dev, "daqboard2000_resetLocalBus\n"); + struct daqboard2000_private *devpriv = dev->private; + writel(DAQBOARD2000_SECRLocalBusHi, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRLocalBusLo, devpriv->plx + 0x6c); @@ -494,7 +470,8 @@ static void daqboard2000_resetLocalBus(struct comedi_device *dev) static void daqboard2000_reloadPLX(struct comedi_device *dev) { - dev_dbg(dev->class_dev, "daqboard2000_reloadPLX\n"); + struct daqboard2000_private *devpriv = dev->private; + writel(DAQBOARD2000_SECRReloadLo, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRReloadHi, devpriv->plx + 0x6c); @@ -505,7 +482,8 @@ static void daqboard2000_reloadPLX(struct comedi_device *dev) static void daqboard2000_pulseProgPin(struct comedi_device *dev) { - dev_dbg(dev->class_dev, "daqboard2000_pulseProgPin 1\n"); + struct daqboard2000_private *devpriv = dev->private; + writel(DAQBOARD2000_SECRProgPinHi, devpriv->plx + 0x6c); udelay(10000); writel(DAQBOARD2000_SECRProgPinLo, devpriv->plx + 0x6c); @@ -514,6 +492,7 @@ static void daqboard2000_pulseProgPin(struct comedi_device *dev) static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask) { + struct daqboard2000_private *devpriv = dev->private; int result = 0; int i; int cpld; @@ -533,6 +512,7 @@ static int daqboard2000_pollCPLD(struct comedi_device *dev, int mask) static int daqboard2000_writeCPLD(struct comedi_device *dev, int data) { + struct daqboard2000_private *devpriv = dev->private; int result = 0; udelay(10); @@ -545,41 +525,29 @@ static int daqboard2000_writeCPLD(struct comedi_device *dev, int data) } static int initialize_daqboard2000(struct comedi_device *dev, - unsigned char *cpld_array, int len) + const u8 *cpld_array, size_t len) { + struct daqboard2000_private *devpriv = dev->private; int result = -EIO; /* Read the serial EEPROM control register */ int secr; int retry; - int i; + size_t i; /* Check to make sure the serial eeprom is present on the board */ secr = readl(devpriv->plx + 0x6c); - if (!(secr & DAQBOARD2000_EEPROM_PRESENT)) { -#ifdef DEBUG_EEPROM - dev_dbg(dev->class_dev, "no serial eeprom\n"); -#endif + if (!(secr & DAQBOARD2000_EEPROM_PRESENT)) return -EIO; - } for (retry = 0; retry < 3; retry++) { -#ifdef DEBUG_EEPROM - dev_dbg(dev->class_dev, "Programming EEPROM try %x\n", retry); -#endif - daqboard2000_resetLocalBus(dev); daqboard2000_reloadPLX(dev); daqboard2000_pulseProgPin(dev); if (daqboard2000_pollCPLD(dev, DAQBOARD2000_CPLD_INIT)) { for (i = 0; i < len; i++) { - if (cpld_array[i] == 0xff - && cpld_array[i + 1] == 0x20) { -#ifdef DEBUG_EEPROM - dev_dbg(dev->class_dev, - "Preamble found at %d\n", i); -#endif + if (cpld_array[i] == 0xff && + cpld_array[i + 1] == 0x20) break; - } } for (; i < len; i += 2) { int data = @@ -588,9 +556,6 @@ static int initialize_daqboard2000(struct comedi_device *dev, break; } if (i >= len) { -#ifdef DEBUG_EEPROM - dev_dbg(dev->class_dev, "Programmed\n"); -#endif daqboard2000_resetLocalBus(dev); daqboard2000_reloadPLX(dev); result = 0; @@ -601,28 +566,45 @@ static int initialize_daqboard2000(struct comedi_device *dev, return result; } +static int daqboard2000_upload_firmware(struct comedi_device *dev) +{ + struct pci_dev *pcidev = comedi_to_pci_dev(dev); + const struct firmware *fw; + int ret; + + ret = request_firmware(&fw, DAQBOARD2000_FIRMWARE, &pcidev->dev); + if (ret) + return ret; + + ret = initialize_daqboard2000(dev, fw->data, fw->size); + release_firmware(fw); + + return ret; +} + static void daqboard2000_adcStopDmaTransfer(struct comedi_device *dev) { -/* printk("Implement: daqboard2000_adcStopDmaTransfer\n");*/ } static void daqboard2000_adcDisarm(struct comedi_device *dev) { - struct daqboard2000_hw *fpga = devpriv->daq; + struct daqboard2000_private *devpriv = dev->private; /* Disable hardware triggers */ udelay(2); - fpga->trigControl = DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable; + writew(DAQBOARD2000_TrigAnalog | DAQBOARD2000_TrigDisable, + devpriv->daq + trigControl); udelay(2); - fpga->trigControl = DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable; + writew(DAQBOARD2000_TrigTTL | DAQBOARD2000_TrigDisable, + devpriv->daq + trigControl); /* Stop the scan list FIFO from loading the configuration pipe */ udelay(2); - fpga->acqControl = DAQBOARD2000_SeqStopScanList; + writew(DAQBOARD2000_SeqStopScanList, devpriv->daq + acqControl); /* Stop the pacer clock */ udelay(2); - fpga->acqControl = DAQBOARD2000_AdcPacerDisable; + writew(DAQBOARD2000_AdcPacerDisable, devpriv->daq + acqControl); /* Stop the input dma (abort channel 1) */ daqboard2000_adcStopDmaTransfer(dev); @@ -630,41 +612,39 @@ static void daqboard2000_adcDisarm(struct comedi_device *dev) static void daqboard2000_activateReferenceDacs(struct comedi_device *dev) { - struct daqboard2000_hw *fpga = devpriv->daq; + struct daqboard2000_private *devpriv = dev->private; + unsigned int val; int timeout; /* Set the + reference dac value in the FPGA */ - fpga->refDacs = 0x80 | DAQBOARD2000_PosRefDacSelect; + writew(0x80 | DAQBOARD2000_PosRefDacSelect, devpriv->daq + refDacs); for (timeout = 0; timeout < 20; timeout++) { - if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) + val = readw(devpriv->daq + dacControl); + if ((val & DAQBOARD2000_RefBusy) == 0) break; udelay(2); } -/* printk("DAQBOARD2000_PosRefDacSelect %d\n", timeout);*/ /* Set the - reference dac value in the FPGA */ - fpga->refDacs = 0x80 | DAQBOARD2000_NegRefDacSelect; + writew(0x80 | DAQBOARD2000_NegRefDacSelect, devpriv->daq + refDacs); for (timeout = 0; timeout < 20; timeout++) { - if ((fpga->dacControl & DAQBOARD2000_RefBusy) == 0) + val = readw(devpriv->daq + dacControl); + if ((val & DAQBOARD2000_RefBusy) == 0) break; udelay(2); } -/* printk("DAQBOARD2000_NegRefDacSelect %d\n", timeout);*/ } static void daqboard2000_initializeCtrs(struct comedi_device *dev) { -/* printk("Implement: daqboard2000_initializeCtrs\n");*/ } static void daqboard2000_initializeTmrs(struct comedi_device *dev) { -/* printk("Implement: daqboard2000_initializeTmrs\n");*/ } static void daqboard2000_dacDisarm(struct comedi_device *dev) { -/* printk("Implement: daqboard2000_dacDisarm\n");*/ } static void daqboard2000_initializeAdc(struct comedi_device *dev) @@ -680,89 +660,66 @@ static void daqboard2000_initializeDac(struct comedi_device *dev) daqboard2000_dacDisarm(dev); } -/* -The test command, REMOVE!!: - -rmmod daqboard2000 ; rmmod comedi; make install ; modprobe daqboard2000; /usr/sbin/comedi_config /dev/comedi0 daqboard/2000 ; tail -40 /var/log/messages -*/ - static int daqboard2000_8255_cb(int dir, int port, int data, unsigned long ioaddr) { - int result = 0; + void __iomem *mmio_base = (void __iomem *)ioaddr; + if (dir) { - writew(data, ((void *)ioaddr) + port * 2); - result = 0; + writew(data, mmio_base + port * 2); + return 0; } else { - result = readw(((void *)ioaddr) + port * 2); + return readw(mmio_base + port * 2); } -/* - printk("daqboard2000_8255_cb %x %d %d %2.2x -> %2.2x\n", - arg, dir, port, data, result); -*/ - return result; } -static struct pci_dev *daqboard2000_find_pci_dev(struct comedi_device *dev, - struct comedi_devconfig *it) +static const void *daqboard2000_find_boardinfo(struct comedi_device *dev, + struct pci_dev *pcidev) { - struct pci_dev *pcidev = NULL; - int bus = it->options[0]; - int slot = it->options[1]; + const struct daq200_boardtype *board; int i; - for_each_pci_dev(pcidev) { - if (bus || slot) { - if (bus != pcidev->bus->number || - slot != PCI_SLOT(pcidev->devfn)) - continue; - } - if (pcidev->vendor != PCI_VENDOR_ID_IOTECH || - pcidev->device != 0x0409) - continue; - - for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { - if (boardtypes[i].id != pcidev->subsystem_device) - continue; - dev->board_ptr = boardtypes + i; - return pcidev; - } + if (pcidev->subsystem_device != PCI_VENDOR_ID_IOTECH) + return NULL; + + for (i = 0; i < ARRAY_SIZE(boardtypes); i++) { + board = &boardtypes[i]; + if (pcidev->subsystem_device == board->id) + return board; } - dev_err(dev->class_dev, - "No supported board found! (req. bus %d, slot %d)\n", - bus, slot); return NULL; } -static int daqboard2000_attach(struct comedi_device *dev, - struct comedi_devconfig *it) +static int daqboard2000_attach_pci(struct comedi_device *dev, + struct pci_dev *pcidev) { - struct pci_dev *pcidev; + const struct daq200_boardtype *board; + struct daqboard2000_private *devpriv; struct comedi_subdevice *s; - void *aux_data; - unsigned int aux_len; int result; - result = alloc_private(dev, sizeof(struct daqboard2000_private)); + comedi_set_hw_dev(dev, &pcidev->dev); + + board = daqboard2000_find_boardinfo(dev, pcidev); + if (!board) + return -ENODEV; + dev->board_ptr = board; + dev->board_name = board->name; + + result = alloc_private(dev, sizeof(*devpriv)); if (result < 0) return -ENOMEM; + devpriv = dev->private; - pcidev = daqboard2000_find_pci_dev(dev, it); - if (!pcidev) - return -EIO; - comedi_set_hw_dev(dev, &pcidev->dev); - - result = comedi_pci_enable(pcidev, "daqboard2000"); - if (result < 0) { - dev_err(dev->class_dev, - "failed to enable PCI device and request regions\n"); - return -EIO; - } - dev->iobase = pci_resource_start(pcidev, 2); + result = comedi_pci_enable(pcidev, dev->driver->driver_name); + if (result < 0) + return result; + dev->iobase = 1; /* the "detach" needs this */ - devpriv->plx = - ioremap(pci_resource_start(pcidev, 0), DAQBOARD2000_PLX_SIZE); - devpriv->daq = ioremap(dev->iobase, DAQBOARD2000_DAQ_SIZE); + devpriv->plx = ioremap(pci_resource_start(pcidev, 0), + pci_resource_len(pcidev, 0)); + devpriv->daq = ioremap(pci_resource_start(pcidev, 2), + pci_resource_len(pcidev, 2)); if (!devpriv->plx || !devpriv->daq) return -ENOMEM; @@ -772,38 +729,14 @@ static int daqboard2000_attach(struct comedi_device *dev, readl(devpriv->plx + 0x6c); - /* - u8 interrupt; - Windows code does restore interrupts, but since we don't use them... - pci_read_config_byte(pcidev, PCI_INTERRUPT_LINE, &interrupt); - printk("Interrupt before is: %x\n", interrupt); - */ - - aux_data = comedi_aux_data(it->options, 0); - aux_len = it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]; - - if (aux_data && aux_len) { - result = initialize_daqboard2000(dev, aux_data, aux_len); - } else { - dev_dbg(dev->class_dev, - "no FPGA initialization code, aborting\n"); - result = -EIO; - } + result = daqboard2000_upload_firmware(dev); if (result < 0) - goto out; + return result; + daqboard2000_initializeAdc(dev); daqboard2000_initializeDac(dev); - /* - Windows code does restore interrupts, but since we don't use them... - pci_read_config_byte(pcidev, PCI_INTERRUPT_LINE, &interrupt); - printk("Interrupt after is: %x\n", interrupt); - */ - - dev->iobase = (unsigned long)devpriv->daq; - - dev->board_name = this_board->name; - s = dev->subdevices + 0; + s = &dev->subdevices[0]; /* ai subdevice */ s->type = COMEDI_SUBD_AI; s->subdev_flags = SDF_READABLE | SDF_GROUND; @@ -812,7 +745,7 @@ static int daqboard2000_attach(struct comedi_device *dev, s->insn_read = daqboard2000_ai_insn_read; s->range_table = &range_daqboard2000_ai; - s = dev->subdevices + 1; + s = &dev->subdevices[1]; /* ao subdevice */ s->type = COMEDI_SUBD_AO; s->subdev_flags = SDF_WRITABLE; @@ -820,22 +753,27 @@ static int daqboard2000_attach(struct comedi_device *dev, s->maxdata = 0xffff; s->insn_read = daqboard2000_ao_insn_read; s->insn_write = daqboard2000_ao_insn_write; - s->range_table = &range_daqboard2000_ao; + s->range_table = &range_bipolar10; - s = dev->subdevices + 2; + s = &dev->subdevices[2]; result = subdev_8255_init(dev, s, daqboard2000_8255_cb, - (unsigned long)(dev->iobase + 0x40)); + (unsigned long)(devpriv->daq + dioP2ExpansionIO8Bit)); + if (result) + return result; -out: - return result; + dev_info(dev->class_dev, "%s: %s attached\n", + dev->driver->driver_name, dev->board_name); + + return 0; } static void daqboard2000_detach(struct comedi_device *dev) { struct pci_dev *pcidev = comedi_to_pci_dev(dev); + struct daqboard2000_private *devpriv = dev->private; if (dev->subdevices) - subdev_8255_cleanup(dev, dev->subdevices + 2); + subdev_8255_cleanup(dev, &dev->subdevices[2]); if (dev->irq) free_irq(dev->irq, dev); if (devpriv) { @@ -854,7 +792,7 @@ static void daqboard2000_detach(struct comedi_device *dev) static struct comedi_driver daqboard2000_driver = { .driver_name = "daqboard2000", .module = THIS_MODULE, - .attach = daqboard2000_attach, + .attach_pci = daqboard2000_attach_pci, .detach = daqboard2000_detach, }; @@ -886,3 +824,4 @@ module_comedi_pci_driver(daqboard2000_driver, daqboard2000_pci_driver); MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_LICENSE("GPL"); +MODULE_FIRMWARE(DAQBOARD2000_FIRMWARE); |