Merge branch 'for-2.6.31' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[pandora-kernel.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 shoud 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 typedef struct {
105         unsigned short w_Nchannel;
106         unsigned char b_Resolution;
107 } str_AnalogOutputHeader;
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         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 adress 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         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                         this_board->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                         this_board->i_NbrDoChannel =
860                                 s_DigitalOutputHeader.w_Nchannel;
861                         ui_Temp = 0xffffffff;
862                         this_board->i_DoMaxdata =
863                                 ui_Temp >> (32 - this_board->i_NbrDoChannel);
864                         break;
865
866                 case EEPROM_ANALOGINPUT:
867                         i_EepromReadAnlogInputHeader(w_PCIBoardEepromAddress,
868                                 pc_PCIChipInformation,
869                                 s_MainHeader.s_Functions[i].w_Address,
870                                 &s_AnalogInputHeader);
871                         if (!(strcmp(this_board->pc_DriverName, "apci3200")))
872                                 this_board->i_NbrAiChannel =
873                                         s_AnalogInputHeader.w_Nchannel * 4;
874                         else
875                                 this_board->i_NbrAiChannel =
876                                         s_AnalogInputHeader.w_Nchannel;
877                         this_board->i_Dma = s_AnalogInputHeader.b_HasDma;
878                         this_board->ui_MinAcquisitiontimeNs =
879                                 (unsigned int) s_AnalogInputHeader.w_MinConvertTiming *
880                                 1000;
881                         this_board->ui_MinDelaytimeNs =
882                                 (unsigned int) s_AnalogInputHeader.w_MinDelayTiming *
883                                 1000;
884                         ui_Temp = 0xffff;
885                         this_board->i_AiMaxdata =
886                                 ui_Temp >> (16 -
887                                 s_AnalogInputHeader.b_Resolution);
888                         break;
889
890                 case EEPROM_ANALOGOUTPUT:
891                         i_EepromReadAnlogOutputHeader(w_PCIBoardEepromAddress,
892                                 pc_PCIChipInformation,
893                                 s_MainHeader.s_Functions[i].w_Address,
894                                 &s_AnalogOutputHeader);
895                         this_board->i_NbrAoChannel =
896                                 s_AnalogOutputHeader.w_Nchannel;
897                         ui_Temp = 0xffff;
898                         this_board->i_AoMaxdata =
899                                 ui_Temp >> (16 -
900                                 s_AnalogOutputHeader.b_Resolution);
901                         break;
902
903                 case EEPROM_TIMER:
904                         this_board->i_Timer = 1;        /* Timer subdevice present */
905                         break;
906
907                 case EEPROM_WATCHDOG:
908                         this_board->i_Timer = 1;        /* Timer subdevice present */
909                         break;
910
911                 case EEPROM_TIMER_WATCHDOG_COUNTER:
912                         this_board->i_Timer = 1;        /* Timer subdevice present */
913                 }
914         }
915
916         return 0;
917 }
918
919 /*
920 +----------------------------------------------------------------------------+
921 | Function Name  : int i_EepromReadDigitalInputHeader(unsigned short                                     |
922 |                       w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
923 |                       unsigned short w_Address,struct str_DigitalInputHeader *s_Header)                |
924 |                                                                                                                                        |
925 +----------------------------------------------------------------------------+
926 | Task              : Read Digital Input Header                              |
927 +----------------------------------------------------------------------------+
928 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
929 |                                                                                                                                        |
930 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
931 |                                                                                                                                        |
932 |                        struct str_DigitalInputHeader *s_Header: Digita Input Header   |
933 |                                                                                                  Pointer                       |
934 +----------------------------------------------------------------------------+
935 | Output Parameters : -                                                      |
936 +----------------------------------------------------------------------------+
937 | Return Value      : 0                                                                              |
938 +----------------------------------------------------------------------------+
939 */
940 int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
941         char *pc_PCIChipInformation, unsigned short w_Address,
942         struct str_DigitalInputHeader *s_Header)
943 {
944         unsigned short w_Temp;
945
946         /*  read nbr of channels */
947         s_Header->w_Nchannel =
948                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
949                 0x100 + w_Address + 6);
950
951         /*  interruptible or not */
952         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
953                 pc_PCIChipInformation, 0x100 + w_Address + 8);
954         s_Header->b_Interruptible = (unsigned char) (w_Temp >> 7) & 0x01;
955
956 /* How many interruptible logic */
957         s_Header->w_NinterruptLogic =
958                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
959                 0x100 + w_Address + 10);
960
961         return 0;
962 }
963
964 /*
965 +----------------------------------------------------------------------------+
966 | Function Name  : int i_EepromReadDigitalOutputHeader(unsigned short                            |
967 |                       w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
968 |                       unsigned short w_Address,struct str_DigitalOutputHeader *s_Header)           |
969 |                                                                                                                                        |
970 +----------------------------------------------------------------------------+
971 | Task              : Read Digital Output Header                             |
972 +----------------------------------------------------------------------------+
973 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
974 |                                                                                                                                        |
975 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
976 |                                                                                                                                        |
977 |                        struct str_DigitalOutputHeader *s_Header: Digital Output Header|
978 |                                                                                          Pointer                               |
979 +----------------------------------------------------------------------------+
980 | Output Parameters : -                                                      |
981 +----------------------------------------------------------------------------+
982 | Return Value      : 0                                                                              |
983 +----------------------------------------------------------------------------+
984 */
985 int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
986         char *pc_PCIChipInformation, unsigned short w_Address,
987         struct str_DigitalOutputHeader *s_Header)
988 {
989 /* Read Nbr channels */
990         s_Header->w_Nchannel =
991                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
992                 0x100 + w_Address + 6);
993         return 0;
994 }
995
996 /*
997 +----------------------------------------------------------------------------+
998 | Function Name  : int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress, |
999 |                       char *pc_PCIChipInformation,WORD w_Address,                              |
1000 |                       struct str_TimerMainHeader *s_Header)                                                    |
1001 +----------------------------------------------------------------------------+
1002 | Task              : Read Timer or Watchdog Header                          |
1003 +----------------------------------------------------------------------------+
1004 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
1005 |                                                                                                                                        |
1006 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
1007 |                                                                                                                                        |
1008 |                        struct str_TimerMainHeader *s_Header: Timer Header                      |
1009 |                                                                                          Pointer                               |
1010 +----------------------------------------------------------------------------+
1011 | Output Parameters : -                                                      |
1012 +----------------------------------------------------------------------------+
1013 | Return Value      : 0                                                                              |
1014 +----------------------------------------------------------------------------+
1015 */
1016 int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
1017         char *pc_PCIChipInformation, unsigned short w_Address,
1018         struct str_TimerMainHeader *s_Header)
1019 {
1020
1021         unsigned short i, w_Size = 0, w_Temp;
1022
1023 /* Read No of Timer */
1024         s_Header->w_Ntimer =
1025                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
1026                 0x100 + w_Address + 6);
1027 /* Read header size */
1028
1029         for (i = 0; i < s_Header->w_Ntimer; i++) {
1030                 s_Header->s_TimerDetails[i].w_HeaderSize =
1031                         w_EepromReadWord(w_PCIBoardEepromAddress,
1032                         pc_PCIChipInformation,
1033                         0x100 + w_Address + 8 + w_Size + 0);
1034                 w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1035                         pc_PCIChipInformation,
1036                         0x100 + w_Address + 8 + w_Size + 2);
1037
1038                 /* Read Resolution */
1039                 s_Header->s_TimerDetails[i].b_Resolution =
1040                         (unsigned char) (w_Temp >> 10) & 0x3F;
1041
1042                 /* Read Mode */
1043                 s_Header->s_TimerDetails[i].b_Mode =
1044                         (unsigned char) (w_Temp >> 4) & 0x3F;
1045
1046                 w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1047                         pc_PCIChipInformation,
1048                         0x100 + w_Address + 8 + w_Size + 4);
1049
1050                 /* Read MinTiming */
1051                 s_Header->s_TimerDetails[i].w_MinTiming = (w_Temp >> 6) & 0x3FF;
1052
1053                 /* Read Timebase */
1054                 s_Header->s_TimerDetails[i].b_TimeBase = (unsigned char) (w_Temp) & 0x3F;
1055                 w_Size += s_Header->s_TimerDetails[i].w_HeaderSize;
1056         }
1057
1058         return 0;
1059 }
1060
1061 /*
1062 +----------------------------------------------------------------------------+
1063 | Function Name  : int i_EepromReadAnlogOutputHeader(unsigned short                                      |
1064 |                       w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
1065 |                       unsigned short w_Address,str_AnalogOutputHeader *s_Header)         |
1066 +----------------------------------------------------------------------------+
1067 | Task              : Read Nalog Output  Header                              |
1068 +----------------------------------------------------------------------------+
1069 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
1070 |                                                                                                                                        |
1071 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
1072 |                                                                                                                                        |
1073 |                        str_AnalogOutputHeader *s_Header:Anlog Output Header    |
1074 |                                                                                          Pointer                               |
1075 +----------------------------------------------------------------------------+
1076 | Output Parameters : -                                                      |
1077 +----------------------------------------------------------------------------+
1078 | Return Value      : 0                                                                              |
1079 +----------------------------------------------------------------------------+
1080 */
1081
1082 int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
1083         char *pc_PCIChipInformation, unsigned short w_Address,
1084         str_AnalogOutputHeader *s_Header)
1085 {
1086         unsigned short w_Temp;
1087         /*  No of channels for 1st hard component */
1088         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1089                 pc_PCIChipInformation, 0x100 + w_Address + 10);
1090         s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
1091         /*  Resolution for 1st hard component */
1092         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1093                 pc_PCIChipInformation, 0x100 + w_Address + 16);
1094         s_Header->b_Resolution = (unsigned char) (w_Temp >> 8) & 0xFF;
1095         return 0;
1096 }
1097
1098 /*
1099 +----------------------------------------------------------------------------+
1100 | Function Name  : int i_EepromReadAnlogInputHeader(unsigned short                                       |
1101 |                       w_PCIBoardEepromAddress,char *pc_PCIChipInformation,     |
1102 |                       unsigned short w_Address,struct str_AnalogInputHeader *s_Header)          |
1103 +----------------------------------------------------------------------------+
1104 | Task              : Read Nalog Output  Header                              |
1105 +----------------------------------------------------------------------------+
1106 | Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
1107 |                                                                                                                                        |
1108 |                     char *pc_PCIChipInformation  : PCI Chip Type.          |
1109 |                                                                                                                                        |
1110 |                        struct str_AnalogInputHeader *s_Header:Anlog Input Header      |
1111 |                                                                                          Pointer                               |
1112 +----------------------------------------------------------------------------+
1113 | Output Parameters : -                                                      |
1114 +----------------------------------------------------------------------------+
1115 | Return Value      : 0                                                                              |
1116 +----------------------------------------------------------------------------+
1117 */
1118
1119 /* Reads only for ONE  hardware component */
1120 int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
1121         char *pc_PCIChipInformation, unsigned short w_Address,
1122         struct str_AnalogInputHeader *s_Header)
1123 {
1124         unsigned short w_Temp, w_Offset;
1125         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1126                 pc_PCIChipInformation, 0x100 + w_Address + 10);
1127         s_Header->w_Nchannel = (w_Temp >> 4) & 0x03FF;
1128         s_Header->w_MinConvertTiming =
1129                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
1130                 0x100 + w_Address + 16);
1131         s_Header->w_MinDelayTiming =
1132                 w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation,
1133                 0x100 + w_Address + 30);
1134         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1135                 pc_PCIChipInformation, 0x100 + w_Address + 20);
1136         s_Header->b_HasDma = (w_Temp >> 13) & 0x01;     /*  whether dma present or not */
1137
1138         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress, pc_PCIChipInformation, 0x100 + w_Address + 72);      /*  reading Y */
1139         w_Temp = w_Temp & 0x00FF;
1140         if (w_Temp)             /* Y>0 */
1141         {
1142                 w_Offset = 74 + (2 * w_Temp) + (10 * (1 + (w_Temp / 16)));      /*  offset of first analog input single header */
1143                 w_Offset = w_Offset + 2;        /*  resolution */
1144         } else                  /* Y=0 */
1145         {
1146                 w_Offset = 74;
1147                 w_Offset = w_Offset + 2;        /*  resolution */
1148         }
1149
1150 /* read Resolution */
1151         w_Temp = w_EepromReadWord(w_PCIBoardEepromAddress,
1152                 pc_PCIChipInformation, 0x100 + w_Address + w_Offset);
1153         s_Header->b_Resolution = w_Temp & 0x001F;       /*  last 5 bits */
1154
1155         return 0;
1156 }