diff options
Diffstat (limited to 'drivers/staging/comedi/drivers/addi-data/addi_eeprom.c')
-rw-r--r-- | drivers/staging/comedi/drivers/addi-data/addi_eeprom.c | 1367 |
1 files changed, 285 insertions, 1082 deletions
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c index 3a9339b92610..5124ac9f1818 100644 --- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c +++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c @@ -1,1162 +1,365 @@ -/** -@verbatim - -Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. - - ADDI-DATA GmbH - Dieselstrasse 3 - D-77833 Ottersweier - Tel: +19(0)7223/9493-0 - Fax: +49(0)7223/9493-92 - http://www.addi-data.com - info@addi-data.com - -This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -You should also find the complete GPL in the COPYING file accompanying this source code. - -@endverbatim -*/ /* - - +-----------------------------------------------------------------------+ - | (C) ADDI-DATA GmbH Dieselstrasse 3 D-77833 Ottersweier | - +-----------------------------------------------------------------------+ - | Tel : +49 (0) 7223/9493-0 | email : info@addi-data.com | - | Fax : +49 (0) 7223/9493-92 | Internet : http://www.addi-data.com | - +-----------------------------------------------------------------------+ - | Project : ADDI DATA | Compiler : GCC | - | Modulname : addi_eeprom.c | Version : 2.96 | - +-------------------------------+---------------------------------------+ - | Project manager: Eric Stolz | Date : 02/12/2002 | - +-----------------------------------------------------------------------+ - | Description : ADDI EEPROM Module | - +-----------------------------------------------------------------------+ - | UPDATE'S | - +-----------------------------------------------------------------------+ - | Date | Author | Description of updates | - +----------+-----------+------------------------------------------------+ - | | | | - | | | | - +----------+-----------+------------------------------------------------+ -*/ - -#define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */ -#define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */ -#define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */ -#define EE76_CMD_LEN 13 /* bits in instructions */ -#define EE_READ 0x0180 /* 01 1000 0000 read instruction */ - -#define EEPROM_DIGITALINPUT 0 -#define EEPROM_DIGITALOUTPUT 1 -#define EEPROM_ANALOGINPUT 2 -#define EEPROM_ANALOGOUTPUT 3 -#define EEPROM_TIMER 4 -#define EEPROM_WATCHDOG 5 + * addi_eeprom.c - ADDI EEPROM Module + * Copyright (C) 2004,2005 ADDI-DATA GmbH for the source code of this module. + * Project manager: Eric Stolz + * + * ADDI-DATA GmbH + * Dieselstrasse 3 + * D-77833 Ottersweier + * Tel: +19(0)7223/9493-0 + * Fax: +49(0)7223/9493-92 + * http://www.addi-data.com + * info@addi-data.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * You should also find the complete GPL in the COPYING file accompanying + * this source code. + */ + +#define NVRAM_USER_DATA_START 0x100 + +#define NVCMD_BEGIN_READ (0x7 << 5) /* nvRam begin read command */ +#define NVCMD_LOAD_LOW (0x4 << 5) /* nvRam load low command */ +#define NVCMD_LOAD_HIGH (0x5 << 5) /* nvRam load high command */ + +#define EE93C76_CLK_BIT (1 << 0) +#define EE93C76_CS_BIT (1 << 1) +#define EE93C76_DOUT_BIT (1 << 2) +#define EE93C76_DIN_BIT (1 << 3) +#define EE93C76_READ_CMD (0x0180 << 4) +#define EE93C76_CMD_LEN 13 + +#define EEPROM_DIGITALINPUT 0 +#define EEPROM_DIGITALOUTPUT 1 +#define EEPROM_ANALOGINPUT 2 +#define EEPROM_ANALOGOUTPUT 3 +#define EEPROM_TIMER 4 +#define EEPROM_WATCHDOG 5 #define EEPROM_TIMER_WATCHDOG_COUNTER 10 -struct str_Functionality { - unsigned char b_Type; - unsigned short w_Address; -}; - -struct str_MainHeader { - unsigned short w_HeaderSize; - unsigned char b_Nfunctions; - struct str_Functionality s_Functions[7]; -}; - -struct str_DigitalInputHeader { - unsigned short w_Nchannel; - unsigned char b_Interruptible; - unsigned short w_NinterruptLogic; -}; - -struct str_DigitalOutputHeader { - - unsigned short w_Nchannel; -}; - - -/* used for timer as well as watchdog */ - -struct str_TimerDetails { - - unsigned short w_HeaderSize; - unsigned char b_Resolution; - unsigned char b_Mode; /* in case of Watchdog it is functionality */ - unsigned short w_MinTiming; - unsigned char b_TimeBase; -}; - -struct str_TimerMainHeader { - - - unsigned short w_Ntimer; - struct str_TimerDetails s_TimerDetails[4]; /* supports 4 timers */ -}; - - -struct str_AnalogOutputHeader { - unsigned short w_Nchannel; - unsigned char b_Resolution; -}; - -struct str_AnalogInputHeader { - unsigned short w_Nchannel; - unsigned short w_MinConvertTiming; - unsigned short w_MinDelayTiming; - unsigned char b_HasDma; - unsigned char b_Resolution; -}; - - - /*****************************************/ - /* Read Header Functions */ - /*****************************************/ - -int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, struct comedi_device *dev); - -int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, unsigned short w_Address, - struct str_DigitalInputHeader *s_Header); - -int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, unsigned short w_Address, - struct str_DigitalOutputHeader *s_Header); - -int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, unsigned short w_Address, - struct str_TimerMainHeader *s_Header); - -int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, unsigned short w_Address, - struct str_AnalogOutputHeader *s_Header); - -int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, unsigned short w_Address, - struct str_AnalogInputHeader *s_Header); - - /******************************************/ - /* Eeprom Specific Functions */ - /******************************************/ -unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation, - unsigned short w_EepromStartAddress); -void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress); -void v_EepromClock76(unsigned int dw_Address, unsigned int dw_RegisterValue); -void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress); -void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromCommand, - unsigned char b_DataLengthInBits); -void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short *pw_Value); - -/* -+----------------------------------------------------------------------------+ -| Function Name : unsigned short w_EepromReadWord | -| (unsigned short w_PCIBoardEepromAddress, | -| char * pc_PCIChipInformation, | -| unsigned short w_EepromStartAddress) | -+----------------------------------------------------------------------------+ -| Task : Read from eepromn a word | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned short w_PCIBoardEepromAddress : PCI eeprom address | -| | -| char *pc_PCIChipInformation : PCI Chip Type. | -| | -| unsigned short w_EepromStartAddress : Selected eeprom address | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : Read word value from eeprom | -+----------------------------------------------------------------------------+ -*/ - -unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation, - unsigned short w_EepromStartAddress) +static void addi_eeprom_clk_93c76(unsigned long iobase, unsigned int val) { - - unsigned char b_Counter = 0; - - unsigned char b_ReadByte = 0; - - unsigned char b_ReadLowByte = 0; - - unsigned char b_ReadHighByte = 0; - - unsigned char b_SelectedAddressLow = 0; - - unsigned char b_SelectedAddressHigh = 0; - - unsigned short w_ReadWord = 0; - - /**************************/ - - /* Test the PCI chip type */ - - /**************************/ - - if ((!strcmp(pc_PCIChipInformation, "S5920")) || - (!strcmp(pc_PCIChipInformation, "S5933"))) - { - - for (b_Counter = 0; b_Counter < 2; b_Counter++) - { - - b_SelectedAddressLow = (w_EepromStartAddress + b_Counter) % 256; /* Read the low 8 bit part */ - - b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256; /* Read the high 8 bit part */ - - /************************************/ - - /* Select the load low address mode */ - - /************************************/ - - outb(NVCMD_LOAD_LOW, w_PCIBoardEepromAddress + 0x3F); - - /****************/ - - /* Wait on busy */ - - /****************/ - - v_EepromWaitBusy(w_PCIBoardEepromAddress); - - /************************/ - - /* Load the low address */ - - /************************/ - - outb(b_SelectedAddressLow, - w_PCIBoardEepromAddress + 0x3E); - - /****************/ - - /* Wait on busy */ - - /****************/ - - v_EepromWaitBusy(w_PCIBoardEepromAddress); - - /*************************************/ - - /* Select the load high address mode */ - - /*************************************/ - - outb(NVCMD_LOAD_HIGH, w_PCIBoardEepromAddress + 0x3F); - - /****************/ - - /* Wait on busy */ - - /****************/ - - v_EepromWaitBusy(w_PCIBoardEepromAddress); - - /*************************/ - - /* Load the high address */ - - /*************************/ - - outb(b_SelectedAddressHigh, - w_PCIBoardEepromAddress + 0x3E); - - /****************/ - - /* Wait on busy */ - - /****************/ - - v_EepromWaitBusy(w_PCIBoardEepromAddress); - - /************************/ - - /* Select the READ mode */ - - /************************/ - - outb(NVCMD_BEGIN_READ, w_PCIBoardEepromAddress + 0x3F); - - /****************/ - - /* Wait on busy */ - - /****************/ - - v_EepromWaitBusy(w_PCIBoardEepromAddress); - - /*****************************/ - - /* Read data into the EEPROM */ - - /*****************************/ - - b_ReadByte = inb(w_PCIBoardEepromAddress + 0x3E); - - /****************/ - - /* Wait on busy */ - - /****************/ - - v_EepromWaitBusy(w_PCIBoardEepromAddress); - - /*********************************/ - - /* Select the upper address part */ - - /*********************************/ - - if (b_Counter == 0) - { - - b_ReadLowByte = b_ReadByte; - - } /* if(b_Counter==0) */ - - else - { - - b_ReadHighByte = b_ReadByte; - - } /* if(b_Counter==0) */ - - } /* for (b_Counter=0; b_Counter<2; b_Counter++) */ - - w_ReadWord = (b_ReadLowByte | (((unsigned short) b_ReadHighByte) * 256)); - - } /* end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933"))) */ - - if (!strcmp(pc_PCIChipInformation, "93C76")) - { - - /*************************************/ - - /* Read 16 bit from the EEPROM 93C76 */ - - /*************************************/ - - v_EepromCs76Read(w_PCIBoardEepromAddress, w_EepromStartAddress, - &w_ReadWord); - - } - - return w_ReadWord; - -} - -/* - -+----------------------------------------------------------------------------+ - -| Function Name : void v_EepromWaitBusy | - -| (unsigned short w_PCIBoardEepromAddress) | - -+----------------------------------------------------------------------------+ - -| Task : Wait the busy flag from PCI controller | - -+----------------------------------------------------------------------------+ - -| Input Parameters : unsigned short w_PCIBoardEepromAddress : PCI eeprom base address | - -+----------------------------------------------------------------------------+ - -| Output Parameters : - | - -+----------------------------------------------------------------------------+ - -| Return Value : - | - -+----------------------------------------------------------------------------+ - -*/ - -void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress) -{ - - unsigned char b_EepromBusy = 0; - - do - { - - /*************/ - - /* IMPORTANT */ - - /*************/ - - /************************************************************************/ - - /* An error has been written in the AMCC 5933 book at the page B-13 */ - - /* Ex: if you read a byte and look for the busy statusEEPROM=0x80 and */ - - /* the operator register is AMCC_OP_REG_MCSR+3 */ - - /* unsigned short read EEPROM=0x8000 andAMCC_OP_REG_MCSR+2 */ - - /* unsigned int read EEPROM=0x80000000 and AMCC_OP_REG_MCSR */ - - /************************************************************************/ - - b_EepromBusy = inb(w_PCIBoardEepromAddress + 0x3F); - b_EepromBusy = b_EepromBusy & 0x80; - - } while (b_EepromBusy == 0x80); - -} - -/* - -+---------------------------------------------------------------------------------+ - -| Function Name : void v_EepromClock76(unsigned int dw_Address, | - -| unsigned int dw_RegisterValue) | - -+---------------------------------------------------------------------------------+ - -| Task : This function sends the clocking sequence to the EEPROM. | - -+---------------------------------------------------------------------------------+ - -| Input Parameters : unsigned int dw_Address : PCI eeprom base address | - -| unsigned int dw_RegisterValue : PCI eeprom register value to write.| - -+---------------------------------------------------------------------------------+ - -| Output Parameters : - | - -+---------------------------------------------------------------------------------+ - -| Return Value : - | - -+---------------------------------------------------------------------------------+ - -*/ - -void v_EepromClock76(unsigned int dw_Address, unsigned int dw_RegisterValue) -{ - - /************************/ - - /* Set EEPROM clock Low */ - - /************************/ - - outl(dw_RegisterValue & 0x6, dw_Address); - - /***************/ - - /* Wait 0.1 ms */ - - /***************/ - + outl(val & ~EE93C76_CLK_BIT, iobase); udelay(100); - /*************************/ - - /* Set EEPROM clock High */ - - /*************************/ - - outl(dw_RegisterValue | 0x1, dw_Address); - - /***************/ - - /* Wait 0.1 ms */ - - /***************/ - + outl(val | EE93C76_CLK_BIT, iobase); udelay(100); - } -/* - -+---------------------------------------------------------------------------------+ - -| Function Name : void v_EepromSendCommand76(unsigned int dw_Address, | - -| unsigned int dw_EepromCommand, | - -| unsigned char b_DataLengthInBits) | - -+---------------------------------------------------------------------------------+ - -| Task : This function sends a Command to the EEPROM 93C76. | - -+---------------------------------------------------------------------------------+ - -| Input Parameters : unsigned int dw_Address : PCI eeprom base address | - -| unsigned int dw_EepromCommand : PCI eeprom command to write. | - -| unsigned char b_DataLengthInBits : PCI eeprom command data length. | - -+---------------------------------------------------------------------------------+ - -| Output Parameters : - | - -+---------------------------------------------------------------------------------+ - -| Return Value : - | - -+---------------------------------------------------------------------------------+ - -*/ - -void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromCommand, - unsigned char b_DataLengthInBits) +static unsigned int addi_eeprom_cmd_93c76(unsigned long iobase, + unsigned int cmd, + unsigned char len) { - - char c_BitPos = 0; - - unsigned int dw_RegisterValue = 0; - - /*****************************/ - - /* Enable EEPROM Chip Select */ - - /*****************************/ - - dw_RegisterValue = 0x2; - - /********************************************************************/ + unsigned int val = EE93C76_CS_BIT; + int i; /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */ - - /********************************************************************/ - - outl(dw_RegisterValue, dw_Address); - - /***************/ - - /* Wait 0.1 ms */ - - /***************/ - + outl(val, iobase); udelay(100); - /*******************************************/ - /* Send EEPROM command - one bit at a time */ - - /*******************************************/ - - for (c_BitPos = (b_DataLengthInBits - 1); c_BitPos >= 0; c_BitPos--) - { - - /**********************************/ - - /* Check if current bit is 0 or 1 */ - - /**********************************/ - - if (dw_EepromCommand & (1 << c_BitPos)) - { - - /***********/ - - /* Write 1 */ - - /***********/ - - dw_RegisterValue = dw_RegisterValue | 0x4; - - } - + for (i = (len - 1); i >= 0; i--) { + if (cmd & (1 << i)) + val |= EE93C76_DOUT_BIT; else - { - - /***********/ - - /* Write 0 */ - - /***********/ - - dw_RegisterValue = dw_RegisterValue & 0x3; - - } - - /*********************/ + val &= ~EE93C76_DOUT_BIT; /* Write the command */ - - /*********************/ - - outl(dw_RegisterValue, dw_Address); - - /***************/ - - /* Wait 0.1 ms */ - - /***************/ - + outl(val, iobase); udelay(100); - /****************************/ - - /* Trigger the EEPROM clock */ - - /****************************/ - - v_EepromClock76(dw_Address, dw_RegisterValue); - + addi_eeprom_clk_93c76(iobase, val); } - + return val; } -/* - -+---------------------------------------------------------------------------------+ - -| Function Name : void v_EepromCs76Read(unsigned int dw_Address, | - -| unsigned short w_offset, | - -| unsigned short * pw_Value) | - -+---------------------------------------------------------------------------------+ - -| Task : This function read a value from the EEPROM 93C76. | - -+---------------------------------------------------------------------------------+ - -| Input Parameters : unsigned int dw_Address : PCI eeprom base address | - -| unsigned short w_offset : Offset of the address to read | - -| unsigned short * pw_Value : PCI eeprom 16 bit read value. | - -+---------------------------------------------------------------------------------+ - -| Output Parameters : - | - -+---------------------------------------------------------------------------------+ - -| Return Value : - | - -+---------------------------------------------------------------------------------+ - -*/ - -void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short *pw_Value) +static unsigned short addi_eeprom_readw_93c76(unsigned long iobase, + unsigned short addr) { - - char c_BitPos = 0; - - unsigned int dw_RegisterValue = 0; - - unsigned int dw_RegisterValueRead = 0; - - /*************************************************/ + unsigned short val = 0; + unsigned int cmd; + unsigned int tmp; + int i; /* Send EEPROM read command and offset to EEPROM */ - - /*************************************************/ - - v_EepromSendCommand76(dw_Address, (EE_READ << 4) | (w_offset / 2), - EE76_CMD_LEN); - - /*******************************/ - - /* Get the last register value */ - - /*******************************/ - - dw_RegisterValue = (((w_offset / 2) & 0x1) << 2) | 0x2; - - /*****************************/ - - /* Set the 16-bit value of 0 */ - - /*****************************/ - - *pw_Value = 0; - - /************************/ + cmd = EE93C76_READ_CMD | (addr / 2); + cmd = addi_eeprom_cmd_93c76(iobase, cmd, EE93C76_CMD_LEN); /* Get the 16-bit value */ + for (i = 0; i < 16; i++) { + addi_eeprom_clk_93c76(iobase, cmd); - /************************/ - - for (c_BitPos = 0; c_BitPos < 16; c_BitPos++) - { - - /****************************/ - - /* Trigger the EEPROM clock */ - - /****************************/ - - v_EepromClock76(dw_Address, dw_RegisterValue); - - /**********************/ - - /* Get the result bit */ - - /**********************/ - - dw_RegisterValueRead = inl(dw_Address); - - /***************/ - - /* Wait 0.1 ms */ - - /***************/ - + tmp = inl(iobase); udelay(100); - /***************************************/ - - /* Get bit value and shift into result */ - - /***************************************/ - - if (dw_RegisterValueRead & 0x8) - { - - /**********/ + val <<= 1; + if (tmp & EE93C76_DIN_BIT) + val |= 0x1; + } - /* Read 1 */ + /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */ + outl(0, iobase); + udelay(100); - /**********/ + return val; +} - *pw_Value = (*pw_Value << 1) | 0x1; +static void addi_eeprom_nvram_wait(unsigned long iobase) +{ + unsigned char val; - } + do { + val = inb(iobase + AMCC_OP_REG_MCSR_NVCMD); + } while (val & 0x80); +} +static unsigned short addi_eeprom_readw_nvram(unsigned long iobase, + unsigned short addr) +{ + unsigned short val = 0; + unsigned char tmp; + unsigned char i; + + for (i = 0; i < 2; i++) { + /* Load the low 8 bit address */ + outb(NVCMD_LOAD_LOW, iobase + AMCC_OP_REG_MCSR_NVCMD); + addi_eeprom_nvram_wait(iobase); + outb((addr + i) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA); + addi_eeprom_nvram_wait(iobase); + + /* Load the high 8 bit address */ + outb(NVCMD_LOAD_HIGH, iobase + AMCC_OP_REG_MCSR_NVCMD); + addi_eeprom_nvram_wait(iobase); + outb(((addr + i) >> 8) & 0xff, + iobase + AMCC_OP_REG_MCSR_NVDATA); + addi_eeprom_nvram_wait(iobase); + + /* Read the eeprom data byte */ + outb(NVCMD_BEGIN_READ, iobase + AMCC_OP_REG_MCSR_NVCMD); + addi_eeprom_nvram_wait(iobase); + tmp = inb(iobase + AMCC_OP_REG_MCSR_NVDATA); + addi_eeprom_nvram_wait(iobase); + + if (i == 0) + val |= tmp; else - { - - /**********/ - - /* Read 0 */ + val |= (tmp << 8); + } - /**********/ + return val; +} - *pw_Value = (*pw_Value << 1); +static unsigned short addi_eeprom_readw(unsigned long iobase, + char *type, + unsigned short addr) +{ + unsigned short val = 0; - } + /* Add the offset to the start of the user data */ + addr += NVRAM_USER_DATA_START; - } + if (!strcmp(type, "S5920") || !strcmp(type, "S5933")) + val = addi_eeprom_readw_nvram(iobase, addr); - /*************************/ + if (!strcmp(type, "93C76")) + val = addi_eeprom_readw_93c76(iobase, addr); - /* Clear all EEPROM bits */ + return val; +} - /*************************/ +static void addi_eeprom_read_di_info(struct comedi_device *dev, + unsigned long iobase, + unsigned short addr) +{ + const struct addi_board *this_board = comedi_board(dev); + struct addi_private *devpriv = dev->private; + char *type = this_board->pc_EepromChip; + unsigned short tmp; - dw_RegisterValue = 0x0; + /* Number of channels */ + tmp = addi_eeprom_readw(iobase, type, addr + 6); + devpriv->s_EeParameters.i_NbrDiChannel = tmp; - /********************************************************************/ + /* Interruptible or not */ + tmp = addi_eeprom_readw(iobase, type, addr + 8); + tmp = (tmp >> 7) & 0x01; - /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */ + /* How many interruptible logic */ + tmp = addi_eeprom_readw(iobase, type, addr + 10); +} - /********************************************************************/ +static void addi_eeprom_read_do_info(struct comedi_device *dev, + unsigned long iobase, + unsigned short addr) +{ + const struct addi_board *this_board = comedi_board(dev); + struct addi_private *devpriv = dev->private; + char *type = this_board->pc_EepromChip; + unsigned short tmp; - outl(dw_RegisterValue, dw_Address); + /* Number of channels */ + tmp = addi_eeprom_readw(iobase, type, addr + 6); + devpriv->s_EeParameters.i_NbrDoChannel = tmp; - /***************/ + devpriv->s_EeParameters.i_DoMaxdata = 0xffffffff >> (32 - tmp); +} - /* Wait 0.1 ms */ +static void addi_eeprom_read_timer_info(struct comedi_device *dev, + unsigned long iobase, + unsigned short addr) +{ + struct addi_private *devpriv = dev->private; +#if 0 + const struct addi_board *this_board = comedi_board(dev); + char *type = this_board->pc_EepromChip; + unsigned short offset = 0; + unsigned short ntimers; + unsigned short tmp; + int i; + + /* Number of Timers */ + ntimers = addi_eeprom_readw(iobase, type, addr + 6); + + /* Read header size */ + for (i = 0; i < ntimers; i++) { + unsigned short size; + unsigned short res; + unsigned short mode; + unsigned short min_timing; + unsigned short timebase; + + size = addi_eeprom_readw(iobase, type, addr + 8 + offset + 0); + + /* Resolution / Mode */ + tmp = addi_eeprom_readw(iobase, type, addr + 8 + offset + 2); + res = (tmp >> 10) & 0x3f; + mode = (tmp >> 4) & 0x3f; + + /* MinTiming / Timebase */ + tmp = addi_eeprom_readw(iobase, type, addr + 8 + offset + 4); + min_timing = (tmp >> 6) & 0x3ff; + Timebase = tmp & 0x3f; + + offset += size; + } +#endif + /* Timer subdevice present */ + devpriv->s_EeParameters.i_Timer = 1; +} - /***************/ +static void addi_eeprom_read_ao_info(struct comedi_device *dev, + unsigned long iobase, + unsigned short addr) +{ + const struct addi_board *this_board = comedi_board(dev); + struct addi_private *devpriv = dev->private; + char *type = this_board->pc_EepromChip; + unsigned short tmp; + + /* No of channels for 1st hard component */ + tmp = addi_eeprom_readw(iobase, type, addr + 10); + devpriv->s_EeParameters.i_NbrAoChannel = (tmp >> 4) & 0x3ff; + + /* Resolution for 1st hard component */ + tmp = addi_eeprom_readw(iobase, type, addr + 16); + tmp = (tmp >> 8) & 0xff; + devpriv->s_EeParameters.i_AoMaxdata = 0xfff >> (16 - tmp); +} - udelay(100); +static void addi_eeprom_read_ai_info(struct comedi_device *dev, + unsigned long iobase, + unsigned short addr) +{ + const struct addi_board *this_board = comedi_board(dev); + struct addi_private *devpriv = dev->private; + char *type = this_board->pc_EepromChip; + unsigned short offset; + unsigned short tmp; + + /* No of channels for 1st hard component */ + tmp = addi_eeprom_readw(iobase, type, addr + 10); + devpriv->s_EeParameters.i_NbrAiChannel = (tmp >> 4) & 0x3ff; + if (!strcmp(this_board->pc_DriverName, "apci3200")) + devpriv->s_EeParameters.i_NbrAiChannel *= 4; + + tmp = addi_eeprom_readw(iobase, type, addr + 16); + devpriv->s_EeParameters.ui_MinAcquisitiontimeNs = tmp * 1000; + + tmp = addi_eeprom_readw(iobase, type, addr + 30); + devpriv->s_EeParameters.ui_MinDelaytimeNs = tmp * 1000; + + tmp = addi_eeprom_readw(iobase, type, addr + 20); + devpriv->s_EeParameters.i_Dma = (tmp >> 13) & 0x01; + + tmp = addi_eeprom_readw(iobase, type, addr + 72) & 0xff; + if (tmp) { /* > 0 */ + /* offset of first analog input single header */ + offset = 74 + (2 * tmp) + (10 * (1 + (tmp / 16))); + } else { /* = 0 */ + offset = 74; + } + /* Resolution */ + tmp = addi_eeprom_readw(iobase, type, addr + offset + 2) & 0x1f; + devpriv->s_EeParameters.i_AiMaxdata = 0xffff >> (16 - tmp); } - /******************************************/ - /* EEPROM HEADER READ FUNCTIONS */ - /******************************************/ - -/* -+----------------------------------------------------------------------------+ -| Function Name : int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress, | -| char * pc_PCIChipInformation,struct comedi_device *dev) | -+----------------------------------------------------------------------------+ -| Task : Read from eeprom Main Header | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned short w_PCIBoardEepromAddress : PCI eeprom address | -| | -| char *pc_PCIChipInformation : PCI Chip Type. | -| | -| struct comedi_device *dev : comedi device structure | -| pointer | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0 | -+----------------------------------------------------------------------------+ -*/ - -int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, struct comedi_device *dev) +static void addi_eeprom_read_info(struct comedi_device *dev, + unsigned long iobase) { - unsigned short w_Temp, i, w_Count = 0; - unsigned int ui_Temp; - struct str_MainHeader s_MainHeader; - struct str_DigitalInputHeader s_DigitalInputHeader; - struct str_DigitalOutputHeader s_DigitalOutputHeader; - /* struct str_TimerMainHeader s_TimerMainHeader,s_WatchdogMainHeader; */ - struct str_AnalogOutputHeader s_AnalogOutputHeader; - struct str_AnalogInputHeader s_AnalogInputHeader; - - /* Read size */ - s_MainHeader.w_HeaderSize = - w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, - 0x100 + 8); - - /* Read nbr of functionality */ - w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, 0x100 + 10); - s_MainHeader.b_Nfunctions = (unsigned char) w_Temp & 0x00FF; + const struct addi_board *this_board = comedi_board(dev); + char *type = this_board->pc_EepromChip; + unsigned short size; + unsigned char nfuncs; + int i; + + size = addi_eeprom_readw(iobase, type, 8); + nfuncs = addi_eeprom_readw(iobase, type, 10) & 0xff; /* Read functionality details */ - for (i = 0; i < s_MainHeader.b_Nfunctions; i++) { - /* Read Type */ - w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, 0x100 + 12 + w_Count); - s_MainHeader.s_Functions[i].b_Type = (unsigned char) w_Temp & 0x3F; - w_Count = w_Count + 2; - /* Read Address */ - s_MainHeader.s_Functions[i].w_Address = - w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, 0x100 + 12 + w_Count); - w_Count = w_Count + 2; - } + for (i = 0; i < nfuncs; i++) { + unsigned short offset = i * 4; + unsigned short addr; + unsigned char func; - /* Display main header info */ - for (i = 0; i < s_MainHeader.b_Nfunctions; i++) { + func = addi_eeprom_readw(iobase, type, 12 + offset) & 0x3f; + addr = addi_eeprom_readw(iobase, type, 14 + offset); - switch (s_MainHeader.s_Functions[i].b_Type) { + switch (func) { case EEPROM_DIGITALINPUT: - i_EepromReadDigitalInputHeader(w_PCIBoardEepromAddress, - pc_PCIChipInformation, - s_MainHeader.s_Functions[i].w_Address, - &s_DigitalInputHeader); - devpriv->s_EeParameters.i_NbrDiChannel = - s_DigitalInputHeader.w_Nchannel; + addi_eeprom_read_di_info(dev, iobase, addr); break; case EEPROM_DIGITALOUTPUT: - i_EepromReadDigitalOutputHeader(w_PCIBoardEepromAddress, - pc_PCIChipInformation, - s_MainHeader.s_Functions[i].w_Address, - &s_DigitalOutputHeader); - devpriv->s_EeParameters.i_NbrDoChannel = - s_DigitalOutputHeader.w_Nchannel; - ui_Temp = 0xffffffff; - devpriv->s_EeParameters.i_DoMaxdata = - ui_Temp >> (32 - - devpriv->s_EeParameters.i_NbrDoChannel); + addi_eeprom_read_do_info(dev, iobase, addr); break; case EEPROM_ANALOGINPUT: - i_EepromReadAnlogInputHeader(w_PCIBoardEepromAddress, - pc_PCIChipInformation, - s_MainHeader.s_Functions[i].w_Address, - &s_AnalogInputHeader); - if (!(strcmp(this_board->pc_DriverName, "apci3200"))) - devpriv->s_EeParameters.i_NbrAiChannel = - s_AnalogInputHeader.w_Nchannel * 4; - else - devpriv->s_EeParameters.i_NbrAiChannel = - s_AnalogInputHeader.w_Nchannel; - devpriv->s_EeParameters.i_Dma = - s_AnalogInputHeader.b_HasDma; - devpriv->s_EeParameters.ui_MinAcquisitiontimeNs = - (unsigned int) s_AnalogInputHeader.w_MinConvertTiming * - 1000; - devpriv->s_EeParameters.ui_MinDelaytimeNs = - (unsigned int) s_AnalogInputHeader.w_MinDelayTiming * - 1000; - ui_Temp = 0xffff; - devpriv->s_EeParameters.i_AiMaxdata = - ui_Temp >> (16 - - s_AnalogInputHeader.b_Resolution); + addi_eeprom_read_ai_info(dev, iobase, addr); break; case EEPROM_ANALOGOUTPUT: - i_EepromReadAnlogOutputHeader(w_PCIBoardEepromAddress, - pc_PCIChipInformation, - s_MainHeader.s_Functions[i].w_Address, - &s_AnalogOutputHeader); - devpriv->s_EeParameters.i_NbrAoChannel = - s_AnalogOutputHeader.w_Nchannel; - ui_Temp = 0xffff; - devpriv->s_EeParameters.i_AoMaxdata = - ui_Temp >> (16 - - s_AnalogOutputHeader.b_Resolution); + addi_eeprom_read_ao_info(dev, iobase, addr); break; case EEPROM_TIMER: - /* Timer subdevice present */ - devpriv->s_EeParameters.i_Timer = 1; - break; - case EEPROM_WATCHDOG: - /* Timer subdevice present */ - devpriv->s_EeParameters.i_Timer = 1; - break; - case EEPROM_TIMER_WATCHDOG_COUNTER: - /* Timer subdevice present */ - devpriv->s_EeParameters.i_Timer = 1; + addi_eeprom_read_timer_info(dev, iobase, addr); break; } } - - return 0; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : int i_EepromReadDigitalInputHeader(unsigned short | -| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, | -| unsigned short w_Address,struct str_DigitalInputHeader *s_Header) | -| | -+----------------------------------------------------------------------------+ -| Task : Read Digital Input Header | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned short w_PCIBoardEepromAddress : PCI eeprom address | -| | -| char *pc_PCIChipInformation : PCI Chip Type. | -| | -| struct str_DigitalInputHeader *s_Header: Digita Input Header | -| Pointer | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0 | -+----------------------------------------------------------------------------+ -*/ -int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, unsigned short w_Address, - struct str_DigitalInputHeader *s_Header) -{ - unsigned short w_Temp; - - /* read nbr of channels */ - s_Header->w_Nchannel = - w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, - 0x100 + w_Address + 6); - - /* interruptible or not */ - w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, 0x100 + w_Address + 8); - s_Header->b_Interruptible = (unsigned char) (w_Temp >> 7) & 0x01; - -/* How many interruptible logic */ - s_Header->w_NinterruptLogic = - w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, - 0x100 + w_Address + 10); - - return 0; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : int i_EepromReadDigitalOutputHeader(unsigned short | -| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, | -| unsigned short w_Address,struct str_DigitalOutputHeader *s_Header) | -| | -+----------------------------------------------------------------------------+ -| Task : Read Digital Output Header | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned short w_PCIBoardEepromAddress : PCI eeprom address | -| | -| char *pc_PCIChipInformation : PCI Chip Type. | -| | -| struct str_DigitalOutputHeader *s_Header: Digital Output Header| -| Pointer | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0 | -+----------------------------------------------------------------------------+ -*/ -int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, unsigned short w_Address, - struct str_DigitalOutputHeader *s_Header) -{ -/* Read Nbr channels */ - s_Header->w_Nchannel = - w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, - 0x100 + w_Address + 6); - return 0; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, | -| char *pc_PCIChipInformation,WORD w_Address, | -| struct str_TimerMainHeader *s_Header) | -+----------------------------------------------------------------------------+ -| Task : Read Timer or Watchdog Header | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned short w_PCIBoardEepromAddress : PCI eeprom address | -| | -| char *pc_PCIChipInformation : PCI Chip Type. | -| | -| struct str_TimerMainHeader *s_Header: Timer Header | -| Pointer | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0 | -+----------------------------------------------------------------------------+ -*/ -int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, unsigned short w_Address, - struct str_TimerMainHeader *s_Header) -{ - - unsigned short i, w_Size = 0, w_Temp; - -/* Read No of Timer */ - s_Header->w_Ntimer = - w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, - 0x100 + w_Address + 6); -/* Read header size */ - - for (i = 0; i < s_Header->w_Ntimer; i++) { - s_Header->s_TimerDetails[i].w_HeaderSize = - w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, - 0x100 + w_Address + 8 + w_Size + 0); - w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, - 0x100 + w_Address + 8 + w_Size + 2); - - /* Read Resolution */ - s_Header->s_TimerDetails[i].b_Resolution = - (unsigned char) (w_Temp >> 10) & 0x3F; - - /* Read Mode */ - s_Header->s_TimerDetails[i].b_Mode = - (unsigned char) (w_Temp >> 4) & 0x3F; - - w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, - 0x100 + w_Address + 8 + w_Size + 4); - - /* Read MinTiming */ - s_Header->s_TimerDetails[i].w_MinTiming = (w_Temp >> 6) & 0x3FF; - - /* Read Timebase */ - s_Header->s_TimerDetails[i].b_TimeBase = (unsigned char) (w_Temp) & 0x3F; - w_Size += s_Header->s_TimerDetails[i].w_HeaderSize; - } - - return 0; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : int i_EepromReadAnlogOutputHeader(unsigned short | -| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, | -| unsigned short w_Address,str_AnalogOutputHeader *s_Header) | -+----------------------------------------------------------------------------+ -| Task : Read Nalog Output Header | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned short w_PCIBoardEepromAddress : PCI eeprom address | -| | -| char *pc_PCIChipInformation : PCI Chip Type. | -| | -| str_AnalogOutputHeader *s_Header:Anlog Output Header | -| Pointer | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0 | -+----------------------------------------------------------------------------+ -*/ - -int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, unsigned short w_Address, - struct str_AnalogOutputHeader *s_Header) -{ - unsigned short w_Temp; - /* No of channels for 1st hard component */ - w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, 0x100 + w_Address + 10); - s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF; - /* Resolution for 1st hard component */ - w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, 0x100 + w_Address + 16); - s_Header->b_Resolution = (unsigned char) (w_Temp >> 8) & 0xFF; - return 0; -} - -/* -+----------------------------------------------------------------------------+ -| Function Name : int i_EepromReadAnlogInputHeader(unsigned short | -| w_PCIBoardEepromAddress,char *pc_PCIChipInformation, | -| unsigned short w_Address,struct str_AnalogInputHeader *s_Header) | -+----------------------------------------------------------------------------+ -| Task : Read Nalog Output Header | -+----------------------------------------------------------------------------+ -| Input Parameters : unsigned short w_PCIBoardEepromAddress : PCI eeprom address | -| | -| char *pc_PCIChipInformation : PCI Chip Type. | -| | -| struct str_AnalogInputHeader *s_Header:Anlog Input Header | -| Pointer | -+----------------------------------------------------------------------------+ -| Output Parameters : - | -+----------------------------------------------------------------------------+ -| Return Value : 0 | -+----------------------------------------------------------------------------+ -*/ - -/* Reads only for ONE hardware component */ -int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress, - char *pc_PCIChipInformation, unsigned short w_Address, - struct str_AnalogInputHeader *s_Header) -{ - unsigned short w_Temp, w_Offset; - w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, 0x100 + w_Address + 10); - s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF; - s_Header->w_MinConvertTiming = - w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, - 0x100 + w_Address + 16); - s_Header->w_MinDelayTiming = - w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, - 0x100 + w_Address + 30); - w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, 0x100 + w_Address + 20); - s_Header->b_HasDma = (w_Temp >> 13) & 0x01; /* whether dma present or not */ - - w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, 0x100 + w_Address + 72); /* reading Y */ - w_Temp = w_Temp & 0x00FF; - if (w_Temp) /* Y>0 */ - { - w_Offset = 74 + (2 * w_Temp) + (10 * (1 + (w_Temp / 16))); /* offset of first analog input single header */ - w_Offset = w_Offset + 2; /* resolution */ - } else /* Y=0 */ - { - w_Offset = 74; - w_Offset = w_Offset + 2; /* resolution */ - } - -/* read Resolution */ - w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, - pc_PCIChipInformation, 0x100 + w_Address + w_Offset); - s_Header->b_Resolution = w_Temp & 0x001F; /* last 5 bits */ - - return 0; } |