addi_eeprom.c revision 25417922694e60f04cd4dc8448ada9236f18c532
1/**
2@verbatim
3
4Copyright (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
14This 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
16This 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
18You 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
20You 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
62struct str_Functionality {
63	unsigned char b_Type;
64	unsigned short w_Address;
65};
66
67struct str_MainHeader {
68	unsigned short w_HeaderSize;
69	unsigned char b_Nfunctions;
70	struct str_Functionality s_Functions[7];
71};
72
73struct str_DigitalInputHeader {
74	unsigned short w_Nchannel;
75	unsigned char b_Interruptible;
76	unsigned short w_NinterruptLogic;
77};
78
79struct str_DigitalOutputHeader {
80
81	unsigned short w_Nchannel;
82};
83
84
85/* used for timer as well as watchdog */
86
87struct 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
96struct str_TimerMainHeader {
97
98
99	unsigned short w_Ntimer;
100	struct str_TimerDetails s_TimerDetails[4];	/*   supports 4 timers */
101};
102
103
104struct str_AnalogOutputHeader {
105	unsigned short w_Nchannel;
106	unsigned char b_Resolution;
107};
108
109struct 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
122int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
123	char *pc_PCIChipInformation, struct comedi_device *dev);
124
125int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
126	char *pc_PCIChipInformation, unsigned short w_Address,
127	struct str_DigitalInputHeader *s_Header);
128
129int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
130	char *pc_PCIChipInformation, unsigned short w_Address,
131	struct str_DigitalOutputHeader *s_Header);
132
133int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
134	char *pc_PCIChipInformation, unsigned short w_Address,
135	struct str_TimerMainHeader *s_Header);
136
137int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
138	char *pc_PCIChipInformation, unsigned short w_Address,
139	struct str_AnalogOutputHeader *s_Header);
140
141int 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		/******************************************/
148unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
149	unsigned short w_EepromStartAddress);
150void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
151void v_EepromClock76(unsigned int dw_Address, unsigned int dw_RegisterValue);
152void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
153void v_EepromSendCommand76(unsigned int dw_Address, unsigned int dw_EepromCommand,
154	unsigned char b_DataLengthInBits);
155void 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
178unsigned 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
383void 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
448void 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
519void 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
654void 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
805int 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			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*/
940int 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*/
985int 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*/
1016int 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
1082int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
1083	char *pc_PCIChipInformation, unsigned short w_Address,
1084	struct 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 */
1120int 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}
1157