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