source: drsdaq/VME/struck/sis1100/V2.02/dev/pci/sis1100_eeprom.c@ 23

Last change on this file since 23 was 22, checked in by ogrimm, 16 years ago
First commit of drsdaq program
File size: 7.1 KB
Line 
1/* $ZEL: sis1100_eeprom.c,v 1.2 2004/05/27 23:10:19 wuestner Exp $ */
2
3/*
4 * Copyright (c) 2003-2004
5 * Peter Wuestner. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include "sis1100_sc.h"
30
31#if !defined(__NetBSD__) && ! defined(__linux__)
32#error Invalid or Unknown Operating System
33#endif
34
35/*
36Procedures in this file are used to read and write the serial EEPROM
37(FAIRCHILD NM93CS66) which holds values for PLX-Initialisation.
38
39!!Modification of the EEPROM content can render the SIS1100 unusable!!
40*/
41
42#define EEP_L16 0x80 // length of 16 bit words (2048 Bit)
43#define EEP_L8 (2*EEP_L16) // length of bytes
44
45#define EEP_C 0x01 // Clock
46#define EEP_S 0x02 // Select
47#define EEP_D 0x04 // Data Out
48#define EEP_Q 0x08 // Data In
49#define EEP_P 0x10 // EEPROM Present
50#define EEP_ALEN 8 // Address Field
51
52#define EEPROM (ofs(struct plx9045reg, CNTRL)+3)
53
54static void
55clock_eeprom(struct sis1100_softc* sc)
56{
57 u_int32_t tmp;
58 u_int i;
59
60 for (i=0; i < 2; i++) {
61 tmp=_plxreadreg_1(sc, EEPROM);
62 _plxwritereg_1(sc, EEPROM, tmp|=EEP_C);
63 }
64 for (i=0; i < 2; i++) {
65 tmp=_plxreadreg_1(sc, EEPROM);
66 _plxwritereg_1(sc, EEPROM, tmp & ~EEP_C);
67 }
68}
69
70static void
71deselect_eeprom(struct sis1100_softc* sc)
72{
73 u_int32_t tmp;
74 u_int i;
75
76 for (i=0; i < 5; i++) {
77 tmp=_plxreadreg_1(sc, EEPROM);
78 _plxwritereg_1(sc, EEPROM, tmp & 0xF0);
79 }
80 clock_eeprom(sc);
81}
82
83static void
84setup_eeprom(struct sis1100_softc* sc,
85 int len, /* # of bits */
86 u_int32_t val /* bit pattern */
87 )
88{
89 u_int32_t epv; /* base value */
90 u_int32_t mx;
91
92 mx=1L <<(len-1);
93 deselect_eeprom(sc);
94 epv =(_plxreadreg_1(sc, EEPROM) & 0xF0) |EEP_S; /* select */
95 _plxwritereg_1(sc, EEPROM, epv);
96 clock_eeprom(sc);
97
98 do {
99 if (!(val & mx)) {
100 /* reset D(ata), reset C(lock) */
101 _plxwritereg_1(sc, EEPROM, epv);
102 } else {
103 /* set D(ata), reset C(lock) */
104 _plxwritereg_1(sc, EEPROM, epv|EEP_D);
105 }
106
107 clock_eeprom(sc);
108
109 mx >>=1;
110 } while (mx);
111}
112
113static void
114setup_eeprom1(struct sis1100_softc* sc, u_int8_t command, u_int8_t address)
115{
116 u_int32_t val;
117
118 val=(1<<2|command)<<EEP_ALEN|address;
119 setup_eeprom(sc, EEP_ALEN+3, val);
120}
121
122static void
123setup_eeprom2(struct sis1100_softc* sc, u_int8_t command, u_int8_t address,
124 u_int16_t data)
125{
126 u_int32_t val;
127
128 val=((1<<2|command)<<EEP_ALEN|address)<<16|data;
129 setup_eeprom(sc, EEP_ALEN+19, val);
130}
131
132static u_int16_t
133read_eeprom_word(struct sis1100_softc* sc, u_int8_t addr)
134{
135 u_int32_t tmp;
136 u_int16_t mx;
137 int i;
138
139 setup_eeprom1(sc, 6, addr);
140
141 /* select, float the EEDO pin for read */
142 tmp=_plxreadreg_1(sc, EEPROM);
143 _plxwritereg_1(sc, EEPROM, tmp|EEP_D|EEP_S);
144
145 tmp=_plxreadreg_1(sc, EEPROM); /* dummy bit */
146
147 for (i=0, mx=0; i<16; i++) {
148 clock_eeprom(sc);
149 mx <<=1;
150 tmp=_plxreadreg_1(sc, EEPROM);
151 if ((tmp & EEP_Q) != 0) mx |=1;
152
153 }
154
155 deselect_eeprom(sc);
156 return mx;
157}
158
159int
160sis1100_read_eeprom(struct sis1100_softc* sc,
161 u_int8_t num, u_int8_t addr, u_int16_t* data)
162{
163 u_int32_t tmp;
164 u_int16_t mx;
165 int i, n, res=0;
166
167 setup_eeprom1(sc, 6, addr);
168
169 /* select, float the EEDO pin for read */
170 tmp=_plxreadreg_1(sc, EEPROM);
171 _plxwritereg_1(sc, EEPROM, tmp|EEP_D|EEP_S);
172
173 tmp=_plxreadreg_1(sc, EEPROM); /* dummy bit */
174 if (tmp & EEP_Q) {
175 deselect_eeprom(sc);
176 pINFO(sc, "read_eeprom 0x%x: select error", addr);
177 return EIO;
178 }
179
180 for (n=0; n<num; n++) {
181 for (i=0, mx=0; i<16; i++) {
182 clock_eeprom(sc);
183 mx <<=1;
184 tmp=_plxreadreg_1(sc, EEPROM);
185 if ((tmp & EEP_Q) != 0) mx |=1;
186
187 }
188#ifdef __NetBSD__
189 res=susword(data, mx)?EFAULT:0;
190#elif __linux__
191 res=-put_user(mx, data);
192#endif
193 if (res) break;
194 data++;
195 }
196
197 deselect_eeprom(sc);
198 return res;
199}
200
201int
202sis1100_write_eeprom(struct sis1100_softc* sc,
203 u_int8_t num, u_int8_t addr, u_int16_t* data)
204{
205 u_int32_t tmp;
206 u_int16_t mx, omx;
207 int n, res=0;
208
209 /* enable write */
210 setup_eeprom1(sc, 0, 0xc0);
211 deselect_eeprom(sc);
212
213 for (n=0; n<num; n++) {
214#ifdef __NetBSD__
215 {
216 int x=fusword(data);
217 res=(x==-1)?EFAULT:0;
218 mx=x;
219 }
220#elif __linux__
221 res=-get_user(mx, data);
222#endif
223 if (res) break;
224
225 omx=read_eeprom_word(sc, addr);
226 if (omx!=mx) {
227 int i=10000;
228
229 setup_eeprom2(sc, 1, addr, mx);
230 deselect_eeprom(sc);
231
232 /* select, float the EEDO pin for read */
233 for (i=0; i<4; i++) {
234 tmp=_plxreadreg_1(sc, EEPROM);
235 _plxwritereg_1(sc, EEPROM, tmp|EEP_D|EEP_S);
236 }
237
238 do {
239 tmp=_plxreadreg_1(sc, EEPROM);
240 } while (--i && !(tmp & EEP_Q));
241 /*pINFO(sc, "write_eeprom: i=%d", i);*/
242 if (!(tmp & EEP_Q)) {
243 pINFO(sc, "write_eeprom: timeout");
244 }
245 deselect_eeprom(sc);
246 }
247 data++; addr++;
248 }
249
250 /* disable write */
251 setup_eeprom1(sc, 0, 0);
252 deselect_eeprom(sc);
253
254 return res;
255}
Note: See TracBrowser for help on using the repository browser.