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