Initial commit
[kernel/linux-3.0.git] / drivers / staging / comedi / drivers / addi-data / addi_eeprom.c
1 /**
2 @verbatim
3
4 Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
5
6         ADDI-DATA GmbH
7         Dieselstrasse 3
8         D-77833 Ottersweier
9         Tel: +19(0)7223/9493-0
10         Fax: +49(0)7223/9493-92
11         http://www.addi-data.com
12         info@addi-data.com
13
14 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.
15
16 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.
17
18 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
19
20 You should also find the complete GPL in the COPYING file accompanying this source code.
21
22 @endverbatim
23 */
24 /*
25
26   +-----------------------------------------------------------------------+
27   | (C) ADDI-DATA GmbH          Dieselstrasse 3      D-77833 Ottersweier  |
28   +-----------------------------------------------------------------------+
29   | Tel : +49 (0) 7223/9493-0     | email    : info@addi-data.com         |
30   | Fax : +49 (0) 7223/9493-92    | Internet : http://www.addi-data.com   |
31   +-----------------------------------------------------------------------+
32   | Project   : ADDI DATA         | Compiler : GCC                                    |
33   | Modulname : addi_eeprom.c     | Version  : 2.96                       |
34   +-------------------------------+---------------------------------------+
35   | Project manager: Eric Stolz   | Date     :  02/12/2002                |
36   +-----------------------------------------------------------------------+
37   | Description : ADDI EEPROM  Module                                     |
38   +-----------------------------------------------------------------------+
39   |                             UPDATE'S                                  |
40   +-----------------------------------------------------------------------+
41   |   Date   |   Author  |          Description of updates                |
42   +----------+-----------+------------------------------------------------+
43   |          |           |                                                |
44   |          |           |                                                |
45   +----------+-----------+------------------------------------------------+
46 */
47
48 #define NVCMD_BEGIN_READ        (0x7 << 5)      /*  nvRam begin read command */
49 #define NVCMD_LOAD_LOW          (0x4 << 5)      /*  nvRam load low command */
50 #define NVCMD_LOAD_HIGH         (0x5 << 5)      /*  nvRam load high command */
51 #define EE76_CMD_LEN            13      /*  bits in instructions */
52 #define EE_READ                 0x0180  /*  01 1000 0000 read instruction */
53
54 #define EEPROM_DIGITALINPUT                     0
55 #define EEPROM_DIGITALOUTPUT                    1
56 #define EEPROM_ANALOGINPUT                              2
57 #define EEPROM_ANALOGOUTPUT                             3
58 #define EEPROM_TIMER                                    4
59 #define EEPROM_WATCHDOG                                 5
60 #define EEPROM_TIMER_WATCHDOG_COUNTER   10
61
62 struct str_Functionality {
63         unsigned char b_Type;
64         unsigned short w_Address;
65 };
66
67 struct str_MainHeader {
68         unsigned short w_HeaderSize;
69         unsigned char b_Nfunctions;
70         struct str_Functionality s_Functions[7];
71 };
72
73 struct str_DigitalInputHeader {
74         unsigned short w_Nchannel;
75         unsigned char b_Interruptible;
76         unsigned short w_NinterruptLogic;
77 };
78
79 struct str_DigitalOutputHeader {
80
81         unsigned short w_Nchannel;
82 };
83
84
85 /* used for timer as well as watchdog */
86
87 struct str_TimerDetails {
88
89         unsigned short w_HeaderSize;
90         unsigned char b_Resolution;
91         unsigned char b_Mode;           /*  in case of Watchdog it is functionality */
92         unsigned short w_MinTiming;
93         unsigned char b_TimeBase;
94 };
95
96 struct str_TimerMainHeader {
97
98
99         unsigned short w_Ntimer;
100         struct str_TimerDetails s_TimerDetails[4];      /*   supports 4 timers */
101 };
102
103
104 struct str_AnalogOutputHeader {
105         unsigned short w_Nchannel;
106         unsigned char b_Resolution;
107 };
108
109 struct str_AnalogInputHeader {
110         unsigned short w_Nchannel;
111         unsigned short w_MinConvertTiming;
112         unsigned short w_MinDelayTiming;
113         unsigned char b_HasDma;
114         unsigned char b_Resolution;
115 };
116
117
118                 /*****************************************/
119                 /*            Read Header Functions              */
120                 /*****************************************/
121
122 int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
123         char *pc_PCIChipInformation, struct comedi_device *dev);
124
125 int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
126         char *pc_PCIChipInformation, unsigned short w_Address,
127         struct str_DigitalInputHeader *s_Header);
128
129 int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
130         char *pc_PCIChipInformation, unsigned short w_Address,
131         struct str_DigitalOutputHeader *s_Header);
132
133 int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
134         char *pc_PCIChipInformation, unsigned short w_Address,
135         struct str_TimerMainHeader *s_Header);
136
137 int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
138         char *pc_PCIChipInformation, unsigned short w_Address,
139         struct str_AnalogOutputHeader *s_Header);
140
141 int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
142         char *pc_PCIChipInformation, unsigned short w_Address,
143         struct str_AnalogInputHeader *s_Header);
144
145                 /******************************************/
146                 /*      Eeprom Specific Functions                         */
147                 /******************************************/
148 unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
149         unsigned short w_EepromStartAddress);
150 void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
151 void v_EepromClock76(unsigned int dw_Address, unsigned int dw_RegisterValue);
152 void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
153 void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromCommand,
154         unsigned char b_DataLengthInBits);
155 void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short *pw_Value);
156
157 /*
158 +----------------------------------------------------------------------------+
159 | Function   Name   : unsigned short w_EepromReadWord                                  |
160 |                               (unsigned short w_PCIBoardEepromAddress,                         |
161 |                                char * pc_PCIChipInformation,                           |
162 |                                unsigned short   w_EepromStartAddress)                          |
163 +----------------------------------------------------------------------------+
164 | Task              : Read from eepromn a word                               |
165 +----------------------------------------------------------------------------+
166 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
167 |                                                                                                                                        |
168 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
169 |                                                                                                                                        |
170 |                     unsigned short w_EepromStartAddress    : Selected eeprom address |
171 +----------------------------------------------------------------------------+
172 | Output Parameters : -                                                      |
173 +----------------------------------------------------------------------------+
174 | Return Value      : Read word value from eeprom                            |
175 +----------------------------------------------------------------------------+
176 */
177
178 unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
179         unsigned short w_EepromStartAddress)
180 {
181
182         unsigned char b_Counter = 0;
183
184         unsigned char b_ReadByte = 0;
185
186         unsigned char b_ReadLowByte = 0;
187
188         unsigned char b_ReadHighByte = 0;
189
190         unsigned char b_SelectedAddressLow = 0;
191
192         unsigned char b_SelectedAddressHigh = 0;
193
194         unsigned short w_ReadWord = 0;
195
196         /**************************/
197
198         /* Test the PCI chip type */
199
200         /**************************/
201
202         if ((!strcmp(pc_PCIChipInformation, "S5920")) ||
203                 (!strcmp(pc_PCIChipInformation, "S5933")))
204         {
205
206                 for (b_Counter = 0; b_Counter < 2; b_Counter++)
207                 {
208
209                         b_SelectedAddressLow = (w_EepromStartAddress + b_Counter) % 256;        /* Read the low 8 bit part */
210
211                         b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256;       /* Read the high 8 bit part */
212
213               /************************************/
214
215                         /* Select the load low address mode */
216
217               /************************************/
218
219                         outb(NVCMD_LOAD_LOW, w_PCIBoardEepromAddress + 0x3F);
220
221               /****************/
222
223                         /* Wait on busy */
224
225               /****************/
226
227                         v_EepromWaitBusy(w_PCIBoardEepromAddress);
228
229               /************************/
230
231                         /* Load the low address */
232
233               /************************/
234
235                         outb(b_SelectedAddressLow,
236                                 w_PCIBoardEepromAddress + 0x3E);
237
238               /****************/
239
240                         /* Wait on busy */
241
242               /****************/
243
244                         v_EepromWaitBusy(w_PCIBoardEepromAddress);
245
246               /*************************************/
247
248                         /* Select the load high address mode */
249
250               /*************************************/
251
252                         outb(NVCMD_LOAD_HIGH, w_PCIBoardEepromAddress + 0x3F);
253
254               /****************/
255
256                         /* Wait on busy */
257
258               /****************/
259
260                         v_EepromWaitBusy(w_PCIBoardEepromAddress);
261
262               /*************************/
263
264                         /* Load the high address */
265
266               /*************************/
267
268                         outb(b_SelectedAddressHigh,
269                                 w_PCIBoardEepromAddress + 0x3E);
270
271               /****************/
272
273                         /* Wait on busy */
274
275               /****************/
276
277                         v_EepromWaitBusy(w_PCIBoardEepromAddress);
278
279               /************************/
280
281                         /* Select the READ mode */
282
283               /************************/
284
285                         outb(NVCMD_BEGIN_READ, w_PCIBoardEepromAddress + 0x3F);
286
287               /****************/
288
289                         /* Wait on busy */
290
291               /****************/
292
293                         v_EepromWaitBusy(w_PCIBoardEepromAddress);
294
295               /*****************************/
296
297                         /* Read data into the EEPROM */
298
299               /*****************************/
300
301                         b_ReadByte = inb(w_PCIBoardEepromAddress + 0x3E);
302
303               /****************/
304
305                         /* Wait on busy */
306
307               /****************/
308
309                         v_EepromWaitBusy(w_PCIBoardEepromAddress);
310
311               /*********************************/
312
313                         /* Select the upper address part */
314
315               /*********************************/
316
317                         if (b_Counter == 0)
318                         {
319
320                                 b_ReadLowByte = b_ReadByte;
321
322                         }       /*  if(b_Counter==0) */
323
324                         else
325                         {
326
327                                 b_ReadHighByte = b_ReadByte;
328
329                         }       /*  if(b_Counter==0) */
330
331                 }               /*  for (b_Counter=0; b_Counter<2; b_Counter++) */
332
333                 w_ReadWord = (b_ReadLowByte | (((unsigned short) b_ReadHighByte) * 256));
334
335         }                       /*  end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933"))) */
336
337         if (!strcmp(pc_PCIChipInformation, "93C76"))
338         {
339
340            /*************************************/
341
342                 /* Read 16 bit from the EEPROM 93C76 */
343
344            /*************************************/
345
346                 v_EepromCs76Read(w_PCIBoardEepromAddress, w_EepromStartAddress,
347                         &w_ReadWord);
348
349         }
350
351         return w_ReadWord;
352
353 }
354
355 /*
356
357 +----------------------------------------------------------------------------+
358
359 | Function   Name   : void v_EepromWaitBusy                                  |
360
361 |                       (unsigned short w_PCIBoardEepromAddress)                         |
362
363 +----------------------------------------------------------------------------+
364
365 | Task              : Wait the busy flag from PCI controller                 |
366
367 +----------------------------------------------------------------------------+
368
369 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom base address |
370
371 +----------------------------------------------------------------------------+
372
373 | Output Parameters : -                                                      |
374
375 +----------------------------------------------------------------------------+
376
377 | Return Value      : -                                                      |
378
379 +----------------------------------------------------------------------------+
380
381 */
382
383 void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress)
384 {
385
386         unsigned char b_EepromBusy = 0;
387
388         do
389         {
390
391            /*************/
392
393                 /* IMPORTANT */
394
395            /*************/
396
397            /************************************************************************/
398
399                 /* An error has been written in the AMCC 5933 book at the page B-13 */
400
401                 /* Ex: if you read a byte and look for the busy statusEEPROM=0x80 and   */
402
403                 /*      the operator register is AMCC_OP_REG_MCSR+3 */
404
405                 /*      unsigned short read  EEPROM=0x8000 andAMCC_OP_REG_MCSR+2                  */
406
407                 /*      unsigned int read  EEPROM=0x80000000 and AMCC_OP_REG_MCSR */
408
409            /************************************************************************/
410
411                 b_EepromBusy = inb(w_PCIBoardEepromAddress + 0x3F);
412                 b_EepromBusy = b_EepromBusy & 0x80;
413
414         } while (b_EepromBusy == 0x80);
415
416 }
417
418 /*
419
420 +---------------------------------------------------------------------------------+
421
422 | Function   Name   : void v_EepromClock76(unsigned int dw_Address,                      |
423
424 |                                          unsigned int dw_RegisterValue)                                         |
425
426 +---------------------------------------------------------------------------------+
427
428 | Task              : This function sends the clocking sequence to the EEPROM.    |
429
430 +---------------------------------------------------------------------------------+
431
432 | Input Parameters  : unsigned int dw_Address : PCI eeprom base address                  |
433
434 |                     unsigned int dw_RegisterValue : PCI eeprom register value to write.|
435
436 +---------------------------------------------------------------------------------+
437
438 | Output Parameters : -                                                           |
439
440 +---------------------------------------------------------------------------------+
441
442 | Return Value      : -                                                           |
443
444 +---------------------------------------------------------------------------------+
445
446 */
447
448 void v_EepromClock76(unsigned int dw_Address, unsigned int dw_RegisterValue)
449 {
450
451    /************************/
452
453         /* Set EEPROM clock Low */
454
455    /************************/
456
457         outl(dw_RegisterValue & 0x6, dw_Address);
458
459    /***************/
460
461         /* Wait 0.1 ms */
462
463    /***************/
464
465         udelay(100);
466
467    /*************************/
468
469         /* Set EEPROM clock High */
470
471    /*************************/
472
473         outl(dw_RegisterValue | 0x1, dw_Address);
474
475    /***************/
476
477         /* Wait 0.1 ms */
478
479    /***************/
480
481         udelay(100);
482
483 }
484
485 /*
486
487 +---------------------------------------------------------------------------------+
488
489 | Function   Name   : void v_EepromSendCommand76(unsigned int dw_Address,                |
490
491 |                                          unsigned int   dw_EepromCommand,                               |
492
493 |                                          unsigned char    b_DataLengthInBits)                        |
494
495 +---------------------------------------------------------------------------------+
496
497 | Task              : This function sends a Command to the EEPROM 93C76.          |
498
499 +---------------------------------------------------------------------------------+
500
501 | Input Parameters  : unsigned int dw_Address : PCI eeprom base address                  |
502
503 |                     unsigned int dw_EepromCommand : PCI eeprom command to write.       |
504
505 |                     unsigned char  b_DataLengthInBits : PCI eeprom command data length.  |
506
507 +---------------------------------------------------------------------------------+
508
509 | Output Parameters : -                                                           |
510
511 +---------------------------------------------------------------------------------+
512
513 | Return Value      : -                                                           |
514
515 +---------------------------------------------------------------------------------+
516
517 */
518
519 void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromCommand,
520         unsigned char b_DataLengthInBits)
521 {
522
523         char c_BitPos = 0;
524
525         unsigned int dw_RegisterValue = 0;
526
527    /*****************************/
528
529         /* Enable EEPROM Chip Select */
530
531    /*****************************/
532
533         dw_RegisterValue = 0x2;
534
535    /********************************************************************/
536
537         /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
538
539    /********************************************************************/
540
541         outl(dw_RegisterValue, dw_Address);
542
543    /***************/
544
545         /* Wait 0.1 ms */
546
547    /***************/
548
549         udelay(100);
550
551    /*******************************************/
552
553         /* Send EEPROM command - one bit at a time */
554
555    /*******************************************/
556
557         for (c_BitPos = (b_DataLengthInBits - 1); c_BitPos >= 0; c_BitPos--)
558         {
559
560       /**********************************/
561
562                 /* Check if current bit is 0 or 1 */
563
564       /**********************************/
565
566                 if (dw_EepromCommand & (1 << c_BitPos))
567                 {
568
569          /***********/
570
571                         /* Write 1 */
572
573          /***********/
574
575                         dw_RegisterValue = dw_RegisterValue | 0x4;
576
577                 }
578
579                 else
580                 {
581
582          /***********/
583
584                         /* Write 0 */
585
586          /***********/
587
588                         dw_RegisterValue = dw_RegisterValue & 0x3;
589
590                 }
591
592       /*********************/
593
594                 /* Write the command */
595
596       /*********************/
597
598                 outl(dw_RegisterValue, dw_Address);
599
600       /***************/
601
602                 /* Wait 0.1 ms */
603
604       /***************/
605
606                 udelay(100);
607
608       /****************************/
609
610                 /* Trigger the EEPROM clock */
611
612       /****************************/
613
614                 v_EepromClock76(dw_Address, dw_RegisterValue);
615
616         }
617
618 }
619
620 /*
621
622 +---------------------------------------------------------------------------------+
623
624 | Function   Name   : void v_EepromCs76Read(unsigned int dw_Address,                     |
625
626 |                                          unsigned short    w_offset,                                            |
627
628 |                                          unsigned short *   pw_Value)                                           |
629
630 +---------------------------------------------------------------------------------+
631
632 | Task              : This function read a value from the EEPROM 93C76.           |
633
634 +---------------------------------------------------------------------------------+
635
636 | Input Parameters  : unsigned int dw_Address : PCI eeprom base address                  |
637
638 |                     unsigned short    w_offset : Offset of the address to read             |
639
640 |                     unsigned short *   pw_Value : PCI eeprom 16 bit read value.            |
641
642 +---------------------------------------------------------------------------------+
643
644 | Output Parameters : -                                                           |
645
646 +---------------------------------------------------------------------------------+
647
648 | Return Value      : -                                                           |
649
650 +---------------------------------------------------------------------------------+
651
652 */
653
654 void v_EepromCs76Read(unsigned int dw_Address, unsigned short w_offset, unsigned short *pw_Value)
655 {
656
657         char c_BitPos = 0;
658
659         unsigned int dw_RegisterValue = 0;
660
661         unsigned int dw_RegisterValueRead = 0;
662
663    /*************************************************/
664
665         /* Send EEPROM read command and offset to EEPROM */
666
667    /*************************************************/
668
669         v_EepromSendCommand76(dw_Address, (EE_READ << 4) | (w_offset / 2),
670                 EE76_CMD_LEN);
671
672    /*******************************/
673
674         /* Get the last register value */
675
676    /*******************************/
677
678         dw_RegisterValue = (((w_offset / 2) & 0x1) << 2) | 0x2;
679
680    /*****************************/
681
682         /* Set the 16-bit value of 0 */
683
684    /*****************************/
685
686         *pw_Value = 0;
687
688    /************************/
689
690         /* Get the 16-bit value */
691
692    /************************/
693
694         for (c_BitPos = 0; c_BitPos < 16; c_BitPos++)
695         {
696
697       /****************************/
698
699                 /* Trigger the EEPROM clock */
700
701       /****************************/
702
703                 v_EepromClock76(dw_Address, dw_RegisterValue);
704
705       /**********************/
706
707                 /* Get the result bit */
708
709       /**********************/
710
711                 dw_RegisterValueRead = inl(dw_Address);
712
713       /***************/
714
715                 /* Wait 0.1 ms */
716
717       /***************/
718
719                 udelay(100);
720
721       /***************************************/
722
723                 /* Get bit value and shift into result */
724
725       /***************************************/
726
727                 if (dw_RegisterValueRead & 0x8)
728                 {
729
730          /**********/
731
732                         /* Read 1 */
733
734          /**********/
735
736                         *pw_Value = (*pw_Value << 1) | 0x1;
737
738                 }
739
740                 else
741                 {
742
743          /**********/
744
745                         /* Read 0 */
746
747          /**********/
748
749                         *pw_Value = (*pw_Value << 1);
750
751                 }
752
753         }
754
755    /*************************/
756
757         /* Clear all EEPROM bits */
758
759    /*************************/
760
761         dw_RegisterValue = 0x0;
762
763    /********************************************************************/
764
765         /* Toggle EEPROM's Chip select to get it out of Shift Register Mode */
766
767    /********************************************************************/
768
769         outl(dw_RegisterValue, dw_Address);
770
771    /***************/
772
773         /* Wait 0.1 ms */
774
775    /***************/
776
777         udelay(100);
778
779 }
780
781         /******************************************/
782         /*      EEPROM HEADER READ FUNCTIONS      */
783         /******************************************/
784
785 /*
786 +----------------------------------------------------------------------------+
787 | Function Name  : int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,  |
788 |                               char *  pc_PCIChipInformation,struct comedi_device *dev)    |
789 +----------------------------------------------------------------------------+
790 | Task              : Read from eeprom Main Header                           |
791 +----------------------------------------------------------------------------+
792 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
793 |                                                                                                                                        |
794 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
795 |                                                                                                                                        |
796 |                         struct comedi_device *dev                : comedi device structure |
797 |                                                                                        pointer                                 |
798 +----------------------------------------------------------------------------+
799 | Output Parameters : -                                                      |
800 +----------------------------------------------------------------------------+
801 | Return Value      : 0                                                                              |
802 +----------------------------------------------------------------------------+
803 */
804
805 int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
806         char *pc_PCIChipInformation, struct comedi_device *dev)
807 {
808         unsigned short w_Temp, i, w_Count = 0;
809         unsigned int ui_Temp;
810         struct str_MainHeader s_MainHeader;
811         struct str_DigitalInputHeader s_DigitalInputHeader;
812         struct str_DigitalOutputHeader s_DigitalOutputHeader;
813         /* struct str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader; */
814         struct str_AnalogOutputHeader s_AnalogOutputHeader;
815         struct str_AnalogInputHeader s_AnalogInputHeader;
816
817         /* Read size */
818         s_MainHeader.w_HeaderSize =
819                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
820                 0x100 + 8);
821
822         /* Read nbr of functionality */
823         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
824                 pc_PCIChipInformation, 0x100 + 10);
825         s_MainHeader.b_Nfunctions = (unsigned char) w_Temp & 0x00FF;
826
827         /* Read functionality details */
828         for (i = 0; i < s_MainHeader.b_Nfunctions; i++) {
829                 /* Read Type */
830                 w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
831                         pc_PCIChipInformation, 0x100 + 12 + w_Count);
832                 s_MainHeader.s_Functions[i].b_Type = (unsigned char) w_Temp & 0x3F;
833                 w_Count = w_Count + 2;
834                 /* Read Address */
835                 s_MainHeader.s_Functions[i].w_Address =
836                         w_EepromReadWord(w_PCIBoardEepromAddress,
837                         pc_PCIChipInformation, 0x100 + 12 + w_Count);
838                 w_Count = w_Count + 2;
839         }
840
841         /* Display main header info */
842         for (i = 0; i < s_MainHeader.b_Nfunctions; i++) {
843
844                 switch (s_MainHeader.s_Functions[i].b_Type) {
845                 case EEPROM_DIGITALINPUT:
846                         i_EepromReadDigitalInputHeader(w_PCIBoardEepromAddress,
847                                 pc_PCIChipInformation,
848                                 s_MainHeader.s_Functions[i].w_Address,
849                                 &s_DigitalInputHeader);
850                         devpriv->s_EeParameters.i_NbrDiChannel =
851                                 s_DigitalInputHeader.w_Nchannel;
852                         break;
853
854                 case EEPROM_DIGITALOUTPUT:
855                         i_EepromReadDigitalOutputHeader(w_PCIBoardEepromAddress,
856                                 pc_PCIChipInformation,
857                                 s_MainHeader.s_Functions[i].w_Address,
858                                 &s_DigitalOutputHeader);
859                         devpriv->s_EeParameters.i_NbrDoChannel =
860                                 s_DigitalOutputHeader.w_Nchannel;
861                         ui_Temp = 0xffffffff;
862                         devpriv->s_EeParameters.i_DoMaxdata =
863                                 ui_Temp >> (32 -
864                                         devpriv->s_EeParameters.i_NbrDoChannel);
865                         break;
866
867                 case EEPROM_ANALOGINPUT:
868                         i_EepromReadAnlogInputHeader(w_PCIBoardEepromAddress,
869                                 pc_PCIChipInformation,
870                                 s_MainHeader.s_Functions[i].w_Address,
871                                 &s_AnalogInputHeader);
872                         if (!(strcmp(this_board->pc_DriverName, "apci3200")))
873                                 devpriv->s_EeParameters.i_NbrAiChannel =
874                                         s_AnalogInputHeader.w_Nchannel * 4;
875                         else
876                                 devpriv->s_EeParameters.i_NbrAiChannel =
877                                         s_AnalogInputHeader.w_Nchannel;
878                         devpriv->s_EeParameters.i_Dma =
879                                 s_AnalogInputHeader.b_HasDma;
880                         devpriv->s_EeParameters.ui_MinAcquisitiontimeNs =
881                                 (unsigned int) s_AnalogInputHeader.w_MinConvertTiming *
882                                 1000;
883                         devpriv->s_EeParameters.ui_MinDelaytimeNs =
884                                 (unsigned int) s_AnalogInputHeader.w_MinDelayTiming *
885                                 1000;
886                         ui_Temp = 0xffff;
887                         devpriv->s_EeParameters.i_AiMaxdata =
888                                 ui_Temp >> (16 -
889                                 s_AnalogInputHeader.b_Resolution);
890                         break;
891
892                 case EEPROM_ANALOGOUTPUT:
893                         i_EepromReadAnlogOutputHeader(w_PCIBoardEepromAddress,
894                                 pc_PCIChipInformation,
895                                 s_MainHeader.s_Functions[i].w_Address,
896                                 &s_AnalogOutputHeader);
897                         devpriv->s_EeParameters.i_NbrAoChannel =
898                                 s_AnalogOutputHeader.w_Nchannel;
899                         ui_Temp = 0xffff;
900                         devpriv->s_EeParameters.i_AoMaxdata =
901                                 ui_Temp >> (16 -
902                                 s_AnalogOutputHeader.b_Resolution);
903                         break;
904
905                 case EEPROM_TIMER:
906                         /* Timer subdevice present */
907                         devpriv->s_EeParameters.i_Timer = 1;
908                         break;
909
910                 case EEPROM_WATCHDOG:
911                         /* Timer subdevice present */
912                         devpriv->s_EeParameters.i_Timer = 1;
913                         break;
914
915                 case EEPROM_TIMER_WATCHDOG_COUNTER:
916                         /* Timer subdevice present */
917                         devpriv->s_EeParameters.i_Timer = 1;
918                         break;
919                 }
920         }
921
922         return 0;
923 }
924
925 /*
926 +----------------------------------------------------------------------------+
927 | Function Name  : int i_EepromReadDigitalInputHeader(unsigned short                                     |
928 |                       w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
929 |                       unsigned short w_Address,struct str_DigitalInputHeader *s_Header)                |
930 |                                                                                                                                        |
931 +----------------------------------------------------------------------------+
932 | Task              : Read Digital Input Header                              |
933 +----------------------------------------------------------------------------+
934 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
935 |                                                                                                                                        |
936 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
937 |                                                                                                                                        |
938 |                        struct str_DigitalInputHeader *s_Header: Digita Input Header   |
939 |                                                                                                  Pointer                       |
940 +----------------------------------------------------------------------------+
941 | Output Parameters : -                                                      |
942 +----------------------------------------------------------------------------+
943 | Return Value      : 0                                                                              |
944 +----------------------------------------------------------------------------+
945 */
946 int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
947         char *pc_PCIChipInformation, unsigned short w_Address,
948         struct str_DigitalInputHeader *s_Header)
949 {
950         unsigned short w_Temp;
951
952         /*  read nbr of channels */
953         s_Header->w_Nchannel =
954                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
955                 0x100 + w_Address + 6);
956
957         /*  interruptible or not */
958         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
959                 pc_PCIChipInformation, 0x100 + w_Address + 8);
960         s_Header->b_Interruptible = (unsigned char) (w_Temp >> 7) & 0x01;
961
962 /* How many interruptible logic */
963         s_Header->w_NinterruptLogic =
964                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
965                 0x100 + w_Address + 10);
966
967         return 0;
968 }
969
970 /*
971 +----------------------------------------------------------------------------+
972 | Function Name  : int i_EepromReadDigitalOutputHeader(unsigned short                            |
973 |                       w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
974 |                       unsigned short w_Address,struct str_DigitalOutputHeader *s_Header)           |
975 |                                                                                                                                        |
976 +----------------------------------------------------------------------------+
977 | Task              : Read Digital Output Header                             |
978 +----------------------------------------------------------------------------+
979 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
980 |                                                                                                                                        |
981 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
982 |                                                                                                                                        |
983 |                        struct str_DigitalOutputHeader *s_Header: Digital Output Header|
984 |                                                                                          Pointer                               |
985 +----------------------------------------------------------------------------+
986 | Output Parameters : -                                                      |
987 +----------------------------------------------------------------------------+
988 | Return Value      : 0                                                                              |
989 +----------------------------------------------------------------------------+
990 */
991 int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
992         char *pc_PCIChipInformation, unsigned short w_Address,
993         struct str_DigitalOutputHeader *s_Header)
994 {
995 /* Read Nbr channels */
996         s_Header->w_Nchannel =
997                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
998                 0x100 + w_Address + 6);
999         return 0;
1000 }
1001
1002 /*
1003 +----------------------------------------------------------------------------+
1004 | Function Name  : int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, |
1005 |                       char *pc_PCIChipInformation,WORD w_Address,                              |
1006 |                       struct str_TimerMainHeader *s_Header)                                                    |
1007 +----------------------------------------------------------------------------+
1008 | Task              : Read Timer or Watchdog Header                          |
1009 +----------------------------------------------------------------------------+
1010 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
1011 |                                                                                                                                        |
1012 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
1013 |                                                                                                                                        |
1014 |                        struct str_TimerMainHeader *s_Header: Timer Header                      |
1015 |                                                                                          Pointer                               |
1016 +----------------------------------------------------------------------------+
1017 | Output Parameters : -                                                      |
1018 +----------------------------------------------------------------------------+
1019 | Return Value      : 0                                                                              |
1020 +----------------------------------------------------------------------------+
1021 */
1022 int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
1023         char *pc_PCIChipInformation, unsigned short w_Address,
1024         struct str_TimerMainHeader *s_Header)
1025 {
1026
1027         unsigned short i, w_Size = 0, w_Temp;
1028
1029 /* Read No of Timer */
1030         s_Header->w_Ntimer =
1031                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
1032                 0x100 + w_Address + 6);
1033 /* Read header size */
1034
1035         for (i = 0; i < s_Header->w_Ntimer; i++) {
1036                 s_Header->s_TimerDetails[i].w_HeaderSize =
1037                         w_EepromReadWord(w_PCIBoardEepromAddress,
1038                         pc_PCIChipInformation,
1039                         0x100 + w_Address + 8 + w_Size + 0);
1040                 w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1041                         pc_PCIChipInformation,
1042                         0x100 + w_Address + 8 + w_Size + 2);
1043
1044                 /* Read Resolution */
1045                 s_Header->s_TimerDetails[i].b_Resolution =
1046                         (unsigned char) (w_Temp >> 10) & 0x3F;
1047
1048                 /* Read Mode */
1049                 s_Header->s_TimerDetails[i].b_Mode =
1050                         (unsigned char) (w_Temp >> 4) & 0x3F;
1051
1052                 w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1053                         pc_PCIChipInformation,
1054                         0x100 + w_Address + 8 + w_Size + 4);
1055
1056                 /* Read MinTiming */
1057                 s_Header->s_TimerDetails[i].w_MinTiming = (w_Temp >> 6) & 0x3FF;
1058
1059                 /* Read Timebase */
1060                 s_Header->s_TimerDetails[i].b_TimeBase = (unsigned char) (w_Temp) & 0x3F;
1061                 w_Size += s_Header->s_TimerDetails[i].w_HeaderSize;
1062         }
1063
1064         return 0;
1065 }
1066
1067 /*
1068 +----------------------------------------------------------------------------+
1069 | Function Name  : int i_EepromReadAnlogOutputHeader(unsigned short                                      |
1070 |                       w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
1071 |                       unsigned short w_Address,str_AnalogOutputHeader *s_Header)         |
1072 +----------------------------------------------------------------------------+
1073 | Task              : Read Nalog Output  Header                              |
1074 +----------------------------------------------------------------------------+
1075 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
1076 |                                                                                                                                        |
1077 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
1078 |                                                                                                                                        |
1079 |                        str_AnalogOutputHeader *s_Header:Anlog Output Header    |
1080 |                                                                                          Pointer                               |
1081 +----------------------------------------------------------------------------+
1082 | Output Parameters : -                                                      |
1083 +----------------------------------------------------------------------------+
1084 | Return Value      : 0                                                                              |
1085 +----------------------------------------------------------------------------+
1086 */
1087
1088 int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
1089         char *pc_PCIChipInformation, unsigned short w_Address,
1090         struct str_AnalogOutputHeader *s_Header)
1091 {
1092         unsigned short w_Temp;
1093         /*  No of channels for 1st hard component */
1094         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1095                 pc_PCIChipInformation, 0x100 + w_Address + 10);
1096         s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
1097         /*  Resolution for 1st hard component */
1098         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1099                 pc_PCIChipInformation, 0x100 + w_Address + 16);
1100         s_Header->b_Resolution = (unsigned char) (w_Temp >> 8) & 0xFF;
1101         return 0;
1102 }
1103
1104 /*
1105 +----------------------------------------------------------------------------+
1106 | Function Name  : int i_EepromReadAnlogInputHeader(unsigned short                                       |
1107 |                       w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
1108 |                       unsigned short w_Address,struct str_AnalogInputHeader *s_Header)          |
1109 +----------------------------------------------------------------------------+
1110 | Task              : Read Nalog Output  Header                              |
1111 +----------------------------------------------------------------------------+
1112 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
1113 |                                                                                                                                        |
1114 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
1115 |                                                                                                                                        |
1116 |                        struct str_AnalogInputHeader *s_Header:Anlog Input Header      |
1117 |                                                                                          Pointer                               |
1118 +----------------------------------------------------------------------------+
1119 | Output Parameters : -                                                      |
1120 +----------------------------------------------------------------------------+
1121 | Return Value      : 0                                                                              |
1122 +----------------------------------------------------------------------------+
1123 */
1124
1125 /* Reads only for ONE  hardware component */
1126 int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
1127         char *pc_PCIChipInformation, unsigned short w_Address,
1128         struct str_AnalogInputHeader *s_Header)
1129 {
1130         unsigned short w_Temp, w_Offset;
1131         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1132                 pc_PCIChipInformation, 0x100 + w_Address + 10);
1133         s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
1134         s_Header->w_MinConvertTiming =
1135                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
1136                 0x100 + w_Address + 16);
1137         s_Header->w_MinDelayTiming =
1138                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
1139                 0x100 + w_Address + 30);
1140         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1141                 pc_PCIChipInformation, 0x100 + w_Address + 20);
1142         s_Header->b_HasDma = (w_Temp >> 13) & 0x01;     /*  whether dma present or not */
1143
1144         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, 0x100 + w_Address + 72);      /*  reading Y */
1145         w_Temp = w_Temp & 0x00FF;
1146         if (w_Temp)             /* Y>0 */
1147         {
1148                 w_Offset = 74 + (2 * w_Temp) + (10 * (1 + (w_Temp / 16)));      /*  offset of first analog input single header */
1149                 w_Offset = w_Offset + 2;        /*  resolution */
1150         } else                  /* Y=0 */
1151         {
1152                 w_Offset = 74;
1153                 w_Offset = w_Offset + 2;        /*  resolution */
1154         }
1155
1156 /* read Resolution */
1157         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1158                 pc_PCIChipInformation, 0x100 + w_Address + w_Offset);
1159         s_Header->b_Resolution = w_Temp & 0x001F;       /*  last 5 bits */
1160
1161         return 0;
1162 }