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