1 /**********************************************************************
2 * Reading the NVRAM on the Interphase 5526 PCI Fibre Channel Card.
3 * All contents in this file : courtesy Interphase Corporation.
4 * Special thanks to Kevin Quick, kquick@iphase.com.
5 **********************************************************************/
7 #define FF_MAGIC 0x4646
8 #define DB_MAGIC 0x4442
9 #define DL_MAGIC 0x444d
16 * Switches and defines for header files.
18 * The following defines are used to turn on and off
19 * various options in the header files. Primarily useful
24 static const unsigned short novram_default
[4] = {
32 * a list of the commands that can be sent to the NOVRAM
35 #define NR_EXTEND 0x100
36 #define NR_WRITE 0x140
38 #define NR_ERASE 0x1c0
46 * Defines for the pins on the NOVRAM
49 #define BIT(x) (1 << (x))
52 #define NVDI BIT(NVDI_B)
56 #define NV_MANUAL BIT(28)
64 #define KeStallExecutionProcessor(x) {volatile int d, p;\
65 for (d=0; d<x; d++) for (p=0; p<10; p++);\
69 /***********************
71 * This define ands the value and the current config register and puts
72 * the result in the config register
74 ***********************/
76 #define CFG_AND(val) { volatile int t; \
77 t = readl(fi->n_r.ptr_novram_hw_control_reg); \
79 writel(t, fi->n_r.ptr_novram_hw_control_reg); \
82 /***********************
84 * This define ors the value and the current config register and puts
85 * the result in the config register
87 ***********************/
89 #define CFG_OR(val) { volatile int t; \
90 t = readl(fi->n_r.ptr_novram_hw_control_reg); \
92 writel(t, fi->n_r.ptr_novram_hw_control_reg); \
95 /***********************
97 * Send a command to the NOVRAM, the command is in cmd.
99 * clear CE and SK. Then assert CE.
100 * Clock each of the command bits out in the correct order with SK
101 * exit with CE still asserted
103 ***********************/
105 #define NVRAM_CMD(cmd) { int i; \
107 CFG_AND(~(NVCE|NVSK)); \
109 for (i=0; i<CMD_LEN; i++) { \
110 NVRAM_CLKOUT((c & (1 << (CMD_LEN - 1))) ? 1 : 0);\
113 /***********************
115 * clear the CE, this must be used after each command is complete
117 ***********************/
119 #define NVRAM_CLR_CE CFG_AND(~NVCE)
121 /***********************
123 * clock the data bit in bitval out to the NOVRAM. The bitval must be
124 * a 1 or 0, or the clockout operation is undefined
126 ***********************/
128 #define NVRAM_CLKOUT(bitval) {\
130 CFG_OR((bitval) << NVDI_B); \
131 KeStallExecutionProcessor(5);\
133 KeStallExecutionProcessor(5);\
137 /***********************
139 * clock the data bit in and return a 1 or 0, depending on the value
140 * that was received from the NOVRAM
142 ***********************/
144 #define NVRAM_CLKIN(val) {\
146 KeStallExecutionProcessor(5);\
148 KeStallExecutionProcessor(5);\
149 val = (readl(fi->n_r.ptr_novram_hw_status_reg) & NVDO) ? 1 : 0; \
154 * Function Prototypes
158 static int iph5526_nr_get(struct fc_info
*fi
, int addr
);
159 static void iph5526_nr_do_init(struct fc_info
*fi
);
160 static void iph5526_nr_checksum(struct fc_info
*fi
);
163 /*******************************************************************
165 * Local routine: iph5526_nr_do_init
166 * Purpose: initialize novram server
169 * iph5526_nr_do_init reads the novram into the temporary holding place.
170 * A checksum is done on the area and the Magic Cookies are checked.
171 * If any of them are bad, the NOVRAM is initialized with the
172 * default values and a warning message is displayed.
174 *******************************************************************/
176 static void iph5526_nr_do_init(struct fc_info
*fi
)
179 unsigned short chksum
= 0;
182 for (i
=0; i
<IPH5526_NOVRAM_SIZE
; i
++) {
183 fi
->n_r
.data
[i
] = iph5526_nr_get(fi
, i
);
184 chksum
+= fi
->n_r
.data
[i
];
190 if (fi
->n_r
.data
[IPH5526_NOVRAM_SIZE
- 4] != FF_MAGIC
)
192 if (fi
->n_r
.data
[IPH5526_NOVRAM_SIZE
- 3] != DB_MAGIC
)
194 if (fi
->n_r
.data
[IPH5526_NOVRAM_SIZE
- 2] != DL_MAGIC
)
198 for (i
=0; i
<IPH5526_NOVRAM_SIZE
; i
++) {
199 if (i
< (IPH5526_NOVRAM_SIZE
- 4)) {
200 fi
->n_r
.data
[i
] = 0xffff;
202 fi
->n_r
.data
[i
] = novram_default
[i
- (IPH5526_NOVRAM_SIZE
- 4)];
205 iph5526_nr_checksum(fi
);
210 /*******************************************************************
212 * Local routine: iph5526_nr_get
213 * Purpose: read a single word of NOVRAM
216 * read the 16 bits that make up a word addr of the novram.
217 * The 16 bits of data that are read are returned as the return value
219 *******************************************************************/
221 static int iph5526_nr_get(struct fc_info
*fi
, int addr
)
230 * read the first bit that was clocked with the falling edge of the
231 * the last command data clock
234 NVRAM_CMD(NR_READ
+ addr
);
237 * Now read the rest of the bits, the next bit read is D1, then D2,
242 for (i
=0; i
<16; i
++) {
258 /*******************************************************************
260 * Local routine: iph5526_nr_checksum
261 * Purpose: calculate novram checksum on fi->n_r.data
264 * calculate a checksum for the novram on the image that is
265 * currently in fi->n_r.data
267 *******************************************************************/
269 static void iph5526_nr_checksum(struct fc_info
*fi
)
272 unsigned short chksum
= 0;
274 for (i
=0; i
<(IPH5526_NOVRAM_SIZE
- 1); i
++)
275 chksum
+= fi
->n_r
.data
[i
];
277 fi
->n_r
.data
[i
] = -chksum
;