addi_eeprom.c revision 117102b0f6e0a9ab3ea4fa9fd89b7eb4a8888fb9
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 PDWORD				unsigned int  *
55
56#ifndef DWORD
57#define	DWORD				unsigned int
58#endif
59
60#define EEPROM_DIGITALINPUT 			0
61#define EEPROM_DIGITALOUTPUT			1
62#define EEPROM_ANALOGINPUT				2
63#define EEPROM_ANALOGOUTPUT				3
64#define EEPROM_TIMER					4
65#define EEPROM_WATCHDOG					5
66#define EEPROM_TIMER_WATCHDOG_COUNTER	10
67
68struct str_Functionality {
69	unsigned char b_Type;
70	unsigned short w_Address;
71};
72
73typedef struct {
74	unsigned short w_HeaderSize;
75	unsigned char b_Nfunctions;
76	struct str_Functionality s_Functions[7];
77} str_MainHeader;
78
79typedef struct {
80	unsigned short w_Nchannel;
81	unsigned char b_Interruptible;
82	unsigned short w_NinterruptLogic;
83} str_DigitalInputHeader;
84
85typedef struct {
86	unsigned short w_Nchannel;
87} str_DigitalOutputHeader;
88
89// used for timer as well as watchdog
90
91typedef struct {
92	unsigned short w_HeaderSize;
93	unsigned char b_Resolution;
94	unsigned char b_Mode;		// in case of Watchdog it is functionality
95	unsigned short w_MinTiming;
96	unsigned char b_TimeBase;
97} str_TimerDetails;
98typedef struct {
99
100	unsigned short w_Ntimer;
101	str_TimerDetails s_TimerDetails[4];	//  supports 4 timers
102} str_TimerMainHeader;
103
104typedef struct {
105	unsigned short w_Nchannel;
106	unsigned char b_Resolution;
107} str_AnalogOutputHeader;
108
109typedef struct {
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} str_AnalogInputHeader;
116
117		/*****************************************/
118		/*            Read Header Functions              */
119		/*****************************************/
120
121int i_EepromReadMainHeader(unsigned short w_PCIBoardEepromAddress,
122	char *pc_PCIChipInformation, struct comedi_device *dev);
123
124int i_EepromReadDigitalInputHeader(unsigned short w_PCIBoardEepromAddress,
125	char *pc_PCIChipInformation, unsigned short w_Address,
126	str_DigitalInputHeader * s_Header);
127
128int i_EepromReadDigitalOutputHeader(unsigned short w_PCIBoardEepromAddress,
129	char *pc_PCIChipInformation, unsigned short w_Address,
130	str_DigitalOutputHeader * s_Header);
131
132int i_EepromReadTimerHeader(unsigned short w_PCIBoardEepromAddress,
133	char *pc_PCIChipInformation, unsigned short w_Address,
134	str_TimerMainHeader * s_Header);
135
136int i_EepromReadAnlogOutputHeader(unsigned short w_PCIBoardEepromAddress,
137	char *pc_PCIChipInformation, unsigned short w_Address,
138	str_AnalogOutputHeader * s_Header);
139
140int i_EepromReadAnlogInputHeader(unsigned short w_PCIBoardEepromAddress,
141	char *pc_PCIChipInformation, unsigned short w_Address,
142	str_AnalogInputHeader * s_Header);
143
144		/******************************************/
145		/*      Eeprom Specific Functions                         */
146		/******************************************/
147unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
148	unsigned short w_EepromStartAddress);
149void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
150void v_EepromClock76(DWORD dw_Address, DWORD dw_RegisterValue);
151void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress);
152void v_EepromSendCommand76(DWORD dw_Address, DWORD dw_EepromCommand,
153	unsigned char b_DataLengthInBits);
154void v_EepromCs76Read(DWORD dw_Address, unsigned short w_offset, unsigned short * pw_Value);
155
156/*
157+----------------------------------------------------------------------------+
158| Function   Name   : unsigned short w_EepromReadWord                                  |
159|				(unsigned short	w_PCIBoardEepromAddress,             		 |
160|				 char *	pc_PCIChipInformation,               		 |
161|				 unsigned short   w_EepromStartAddress)                		 |
162+----------------------------------------------------------------------------+
163| Task              : Read from eepromn a word                               |
164+----------------------------------------------------------------------------+
165| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom address      |
166|																	 |
167|		      char *pc_PCIChipInformation  : PCI Chip Type.          |
168|																	 |
169|		      unsigned short w_EepromStartAddress    : Selected eeprom address |
170+----------------------------------------------------------------------------+
171| Output Parameters : -                                                      |
172+----------------------------------------------------------------------------+
173| Return Value      : Read word value from eeprom                            |
174+----------------------------------------------------------------------------+
175*/
176
177unsigned short w_EepromReadWord(unsigned short w_PCIBoardEepromAddress, char *pc_PCIChipInformation,
178	unsigned short w_EepromStartAddress)
179{
180
181	unsigned char b_Counter = 0;
182
183	unsigned char b_ReadByte = 0;
184
185	unsigned char b_ReadLowByte = 0;
186
187	unsigned char b_ReadHighByte = 0;
188
189	unsigned char b_SelectedAddressLow = 0;
190
191	unsigned char b_SelectedAddressHigh = 0;
192
193	unsigned short w_ReadWord = 0;
194
195	/**************************/
196
197	/* Test the PCI chip type */
198
199	/**************************/
200
201	if ((!strcmp(pc_PCIChipInformation, "S5920")) ||
202		(!strcmp(pc_PCIChipInformation, "S5933")))
203	{
204
205		for (b_Counter = 0; b_Counter < 2; b_Counter++)
206		{
207
208			b_SelectedAddressLow = (w_EepromStartAddress + b_Counter) % 256;	//Read the low 8 bit part
209
210			b_SelectedAddressHigh = (w_EepromStartAddress + b_Counter) / 256;	//Read the high 8 bit part
211
212	      /************************************/
213
214			/* Select the load low address mode */
215
216	      /************************************/
217
218			outb(NVCMD_LOAD_LOW, w_PCIBoardEepromAddress + 0x3F);
219
220	      /****************/
221
222			/* Wait on busy */
223
224	      /****************/
225
226			v_EepromWaitBusy(w_PCIBoardEepromAddress);
227
228	      /************************/
229
230			/* Load the low address */
231
232	      /************************/
233
234			outb(b_SelectedAddressLow,
235				w_PCIBoardEepromAddress + 0x3E);
236
237	      /****************/
238
239			/* Wait on busy */
240
241	      /****************/
242
243			v_EepromWaitBusy(w_PCIBoardEepromAddress);
244
245	      /*************************************/
246
247			/* Select the load high address mode */
248
249	      /*************************************/
250
251			outb(NVCMD_LOAD_HIGH, w_PCIBoardEepromAddress + 0x3F);
252
253	      /****************/
254
255			/* Wait on busy */
256
257	      /****************/
258
259			v_EepromWaitBusy(w_PCIBoardEepromAddress);
260
261	      /*************************/
262
263			/* Load the high address */
264
265	      /*************************/
266
267			outb(b_SelectedAddressHigh,
268				w_PCIBoardEepromAddress + 0x3E);
269
270	      /****************/
271
272			/* Wait on busy */
273
274	      /****************/
275
276			v_EepromWaitBusy(w_PCIBoardEepromAddress);
277
278	      /************************/
279
280			/* Select the READ mode */
281
282	      /************************/
283
284			outb(NVCMD_BEGIN_READ, w_PCIBoardEepromAddress + 0x3F);
285
286	      /****************/
287
288			/* Wait on busy */
289
290	      /****************/
291
292			v_EepromWaitBusy(w_PCIBoardEepromAddress);
293
294	      /*****************************/
295
296			/* Read data into the EEPROM */
297
298	      /*****************************/
299
300			b_ReadByte = inb(w_PCIBoardEepromAddress + 0x3E);
301
302	      /****************/
303
304			/* Wait on busy */
305
306	      /****************/
307
308			v_EepromWaitBusy(w_PCIBoardEepromAddress);
309
310	      /*********************************/
311
312			/* Select the upper address part */
313
314	      /*********************************/
315
316			if (b_Counter == 0)
317			{
318
319				b_ReadLowByte = b_ReadByte;
320
321			}	// if(b_Counter==0)
322
323			else
324			{
325
326				b_ReadHighByte = b_ReadByte;
327
328			}	// if(b_Counter==0)
329
330		}		// for (b_Counter=0; b_Counter<2; b_Counter++)
331
332		w_ReadWord = (b_ReadLowByte | (((unsigned short) b_ReadHighByte) * 256));
333
334	}			// end of if ((!strcmp(pc_PCIChipInformation, "S5920")) || (!strcmp(pc_PCIChipInformation, "S5933")))
335
336	if (!strcmp(pc_PCIChipInformation, "93C76"))
337	{
338
339	   /*************************************/
340
341		/* Read 16 bit from the EEPROM 93C76 */
342
343	   /*************************************/
344
345		v_EepromCs76Read(w_PCIBoardEepromAddress, w_EepromStartAddress,
346			&w_ReadWord);
347
348	}
349
350	return (w_ReadWord);
351
352}
353
354/*
355
356+----------------------------------------------------------------------------+
357
358| Function   Name   : void v_EepromWaitBusy                                  |
359
360|			(unsigned short	w_PCIBoardEepromAddress)                    	 |
361
362+----------------------------------------------------------------------------+
363
364| Task              : Wait the busy flag from PCI controller                 |
365
366+----------------------------------------------------------------------------+
367
368| Input Parameters  : unsigned short w_PCIBoardEepromAddress : PCI eeprom base address |
369
370+----------------------------------------------------------------------------+
371
372| Output Parameters : -                                                      |
373
374+----------------------------------------------------------------------------+
375
376| Return Value      : -                                                      |
377
378+----------------------------------------------------------------------------+
379
380*/
381
382void v_EepromWaitBusy(unsigned short w_PCIBoardEepromAddress)
383{
384
385	unsigned char b_EepromBusy = 0;
386
387	do
388	{
389
390	   /*************/
391
392		/* IMPORTANT */
393
394	   /*************/
395
396	   /************************************************************************/
397
398		/* An error has been written in the AMCC 5933 book at the page B-13 */
399
400		/* Ex: if you read a byte and look for the busy statusEEPROM=0x80 and   */
401
402		/*      the operator register is AMCC_OP_REG_MCSR+3 */
403
404		/*      unsigned short read  EEPROM=0x8000 andAMCC_OP_REG_MCSR+2                  */
405
406		/*      DWORD read  EEPROM=0x80000000 and AMCC_OP_REG_MCSR */
407
408	   /************************************************************************/
409
410		b_EepromBusy = inb(w_PCIBoardEepromAddress + 0x3F);
411		b_EepromBusy = b_EepromBusy & 0x80;
412
413	}
414	while (b_EepromBusy == 0x80);
415
416}
417
418/*
419
420+---------------------------------------------------------------------------------+
421
422| Function   Name   : void v_EepromClock76(DWORD dw_Address,                      |
423
424|					   DWORD dw_RegisterValue)                 			  |
425
426+---------------------------------------------------------------------------------+
427
428| Task              : This function sends the clocking sequence to the EEPROM.    |
429
430+---------------------------------------------------------------------------------+
431
432| Input Parameters  : DWORD dw_Address : PCI eeprom base address                  |
433
434|		      DWORD 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(DWORD dw_Address, DWORD 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(DWORD dw_Address,                |
490
491|					   DWORD   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  : DWORD dw_Address : PCI eeprom base address                  |
502
503|		      DWORD 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(DWORD dw_Address, DWORD dw_EepromCommand,
520	unsigned char b_DataLengthInBits)
521{
522
523	char c_BitPos = 0;
524
525	DWORD 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(DWORD 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  : DWORD dw_Address : PCI eeprom base address                  |
637
638|		      unsigned short    w_offset : Offset of the adress to read             |
639
640|		      unsigned short *   pw_Value : PCI eeprom 16 bit read value.            |
641
642+---------------------------------------------------------------------------------+
643
644| Output Parameters : -                                                           |
645
646+---------------------------------------------------------------------------------+
647
648| Return Value      : -                                                           |
649
650+---------------------------------------------------------------------------------+
651
652*/
653
654void v_EepromCs76Read(DWORD dw_Address, unsigned short w_offset, unsigned short * pw_Value)
655{
656
657        char c_BitPos = 0;
658
659	DWORD dw_RegisterValue = 0;
660
661	DWORD 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	str_MainHeader s_MainHeader;
811	str_DigitalInputHeader s_DigitalInputHeader;
812	str_DigitalOutputHeader s_DigitalOutputHeader;
813	//str_TimerMainHeader     s_TimerMainHeader,s_WatchdogMainHeader;
814	str_AnalogOutputHeader s_AnalogOutputHeader;
815	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,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|			 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	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,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|			 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	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|			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|			 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	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	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,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|			 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	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