aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2005-07-06 13:31:07 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2005-07-14 10:56:54 -0400
commit459c537807bd72cce7b007fb218bb5a658a6c3c1 (patch)
tree18a05e5f8fb73651219860f7056c6f73a885d623 /drivers/scsi/qla2xxx
parent1c7c63574ff3e568ca374e9f05e30b8d7d64273e (diff)
[SCSI] qla2xxx: Add ISP24xx flash-manipulation routines.
Add ISP24xx flash-manipulation routines. Add read/write flash manipulation routines for the ISP24xx. Update sysfs NVRAM objects to use generalized accessor functions. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c59
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h11
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c538
4 files changed, 531 insertions, 79 deletions
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 30c381c3abcc..9361f4255e62 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -118,23 +118,15 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf, loff_t off,
118{ 118{
119 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 119 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
120 struct device, kobj))); 120 struct device, kobj)));
121 uint16_t *witer;
122 unsigned long flags; 121 unsigned long flags;
123 uint16_t cnt;
124 122
125 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != sizeof(nvram_t)) 123 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
126 return 0; 124 return 0;
127 125
128 /* Read NVRAM. */ 126 /* Read NVRAM. */
129 spin_lock_irqsave(&ha->hardware_lock, flags); 127 spin_lock_irqsave(&ha->hardware_lock, flags);
130 qla2x00_lock_nvram_access(ha); 128 ha->isp_ops.read_nvram(ha, (uint8_t *)buf, ha->nvram_base,
131 witer = (uint16_t *)buf; 129 ha->nvram_size);
132 for (cnt = 0; cnt < count / 2; cnt++) {
133 *witer = cpu_to_le16(qla2x00_get_nvram_word(ha,
134 cnt+ha->nvram_base));
135 witer++;
136 }
137 qla2x00_unlock_nvram_access(ha);
138 spin_unlock_irqrestore(&ha->hardware_lock, flags); 130 spin_unlock_irqrestore(&ha->hardware_lock, flags);
139 131
140 return (count); 132 return (count);
@@ -146,34 +138,38 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf, loff_t off,
146{ 138{
147 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, 139 struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
148 struct device, kobj))); 140 struct device, kobj)));
149 uint8_t *iter;
150 uint16_t *witer;
151 unsigned long flags; 141 unsigned long flags;
152 uint16_t cnt; 142 uint16_t cnt;
153 uint8_t chksum;
154 143
155 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != sizeof(nvram_t)) 144 if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
156 return 0; 145 return 0;
157 146
158 /* Checksum NVRAM. */ 147 /* Checksum NVRAM. */
159 iter = (uint8_t *)buf; 148 if (IS_QLA24XX(ha) || IS_QLA25XX(ha)) {
160 chksum = 0; 149 uint32_t *iter;
161 for (cnt = 0; cnt < count - 1; cnt++) 150 uint32_t chksum;
162 chksum += *iter++; 151
163 chksum = ~chksum + 1; 152 iter = (uint32_t *)buf;
164 *iter = chksum; 153 chksum = 0;
154 for (cnt = 0; cnt < ((count >> 2) - 1); cnt++)
155 chksum += le32_to_cpu(*iter++);
156 chksum = ~chksum + 1;
157 *iter = cpu_to_le32(chksum);
158 } else {
159 uint8_t *iter;
160 uint8_t chksum;
161
162 iter = (uint8_t *)buf;
163 chksum = 0;
164 for (cnt = 0; cnt < count - 1; cnt++)
165 chksum += *iter++;
166 chksum = ~chksum + 1;
167 *iter = chksum;
168 }
165 169
166 /* Write NVRAM. */ 170 /* Write NVRAM. */
167 spin_lock_irqsave(&ha->hardware_lock, flags); 171 spin_lock_irqsave(&ha->hardware_lock, flags);
168 qla2x00_lock_nvram_access(ha); 172 ha->isp_ops.write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count);
169 qla2x00_release_nvram_protection(ha);
170 witer = (uint16_t *)buf;
171 for (cnt = 0; cnt < count / 2; cnt++) {
172 qla2x00_write_nvram_word(ha, cnt+ha->nvram_base,
173 cpu_to_le16(*witer));
174 witer++;
175 }
176 qla2x00_unlock_nvram_access(ha);
177 spin_unlock_irqrestore(&ha->hardware_lock, flags); 173 spin_unlock_irqrestore(&ha->hardware_lock, flags);
178 174
179 return (count); 175 return (count);
@@ -185,7 +181,7 @@ static struct bin_attribute sysfs_nvram_attr = {
185 .mode = S_IRUSR | S_IWUSR, 181 .mode = S_IRUSR | S_IWUSR,
186 .owner = THIS_MODULE, 182 .owner = THIS_MODULE,
187 }, 183 },
188 .size = sizeof(nvram_t), 184 .size = 0,
189 .read = qla2x00_sysfs_read_nvram, 185 .read = qla2x00_sysfs_read_nvram,
190 .write = qla2x00_sysfs_write_nvram, 186 .write = qla2x00_sysfs_write_nvram,
191}; 187};
@@ -196,6 +192,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha)
196 struct Scsi_Host *host = ha->host; 192 struct Scsi_Host *host = ha->host;
197 193
198 sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); 194 sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr);
195 sysfs_nvram_attr.size = ha->nvram_size;
199 sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); 196 sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr);
200} 197}
201 198
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 574446c0892a..0dd732486e24 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -220,6 +220,17 @@ extern void qla2x00_unlock_nvram_access(scsi_qla_host_t *);
220extern void qla2x00_release_nvram_protection(scsi_qla_host_t *); 220extern void qla2x00_release_nvram_protection(scsi_qla_host_t *);
221extern uint16_t qla2x00_get_nvram_word(scsi_qla_host_t *, uint32_t); 221extern uint16_t qla2x00_get_nvram_word(scsi_qla_host_t *, uint32_t);
222extern void qla2x00_write_nvram_word(scsi_qla_host_t *, uint32_t, uint16_t); 222extern void qla2x00_write_nvram_word(scsi_qla_host_t *, uint32_t, uint16_t);
223extern uint32_t *qla24xx_read_flash_data(scsi_qla_host_t *, uint32_t *,
224 uint32_t, uint32_t);
225extern uint8_t *qla2x00_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
226 uint32_t);
227extern uint8_t *qla24xx_read_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
228 uint32_t);
229extern int qla2x00_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
230 uint32_t);
231extern int qla24xx_write_nvram_data(scsi_qla_host_t *, uint8_t *, uint32_t,
232 uint32_t);
233
223/* 234/*
224 * Global Function Prototypes in qla_dbg.c source file. 235 * Global Function Prototypes in qla_dbg.c source file.
225 */ 236 */
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index a325b66ea41c..9e6d05119253 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1187,6 +1187,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
1187 ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32; 1187 ha->isp_ops.calc_req_entries = qla2x00_calc_iocbs_32;
1188 ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32; 1188 ha->isp_ops.build_iocbs = qla2x00_build_scsi_iocbs_32;
1189 ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb; 1189 ha->isp_ops.prep_ms_iocb = qla2x00_prep_ms_iocb;
1190 ha->isp_ops.read_nvram = qla2x00_read_nvram_data;
1191 ha->isp_ops.write_nvram = qla2x00_write_nvram_data;
1190 ha->isp_ops.fw_dump = qla2100_fw_dump; 1192 ha->isp_ops.fw_dump = qla2100_fw_dump;
1191 ha->isp_ops.ascii_fw_dump = qla2100_ascii_fw_dump; 1193 ha->isp_ops.ascii_fw_dump = qla2100_ascii_fw_dump;
1192 if (IS_QLA2100(ha)) { 1194 if (IS_QLA2100(ha)) {
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index cf2a6bc444d2..c95ef2bb089a 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -79,54 +79,6 @@ qla2x00_unlock_nvram_access(scsi_qla_host_t *ha)
79} 79}
80 80
81/** 81/**
82 * qla2x00_release_nvram_protection() -
83 * @ha: HA context
84 */
85void
86qla2x00_release_nvram_protection(scsi_qla_host_t *ha)
87{
88 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
89 uint32_t word;
90
91 /* Release NVRAM write protection. */
92 if (IS_QLA2322(ha) || IS_QLA6322(ha)) {
93 /* Write enable. */
94 qla2x00_nv_write(ha, NVR_DATA_OUT);
95 qla2x00_nv_write(ha, 0);
96 qla2x00_nv_write(ha, 0);
97 for (word = 0; word < 8; word++)
98 qla2x00_nv_write(ha, NVR_DATA_OUT);
99
100 qla2x00_nv_deselect(ha);
101
102 /* Enable protection register. */
103 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
104 qla2x00_nv_write(ha, NVR_PR_ENABLE);
105 qla2x00_nv_write(ha, NVR_PR_ENABLE);
106 for (word = 0; word < 8; word++)
107 qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
108
109 qla2x00_nv_deselect(ha);
110
111 /* Clear protection register (ffff is cleared). */
112 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
113 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
114 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
115 for (word = 0; word < 8; word++)
116 qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
117
118 qla2x00_nv_deselect(ha);
119
120 /* Wait for NVRAM to become ready. */
121 WRT_REG_WORD(&reg->nvram, NVR_SELECT);
122 do {
123 NVRAM_DELAY();
124 word = RD_REG_WORD(&reg->nvram);
125 } while ((word & NVR_DATA_IN) == 0);
126 }
127}
128
129/**
130 * qla2x00_get_nvram_word() - Calculates word position in NVRAM and calls the 82 * qla2x00_get_nvram_word() - Calculates word position in NVRAM and calls the
131 * request routine to get the word from NVRAM. 83 * request routine to get the word from NVRAM.
132 * @ha: HA context 84 * @ha: HA context
@@ -202,6 +154,64 @@ qla2x00_write_nvram_word(scsi_qla_host_t *ha, uint32_t addr, uint16_t data)
202 qla2x00_nv_deselect(ha); 154 qla2x00_nv_deselect(ha);
203} 155}
204 156
157static int
158qla2x00_write_nvram_word_tmo(scsi_qla_host_t *ha, uint32_t addr, uint16_t data,
159 uint32_t tmo)
160{
161 int ret, count;
162 uint16_t word;
163 uint32_t nv_cmd;
164 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
165
166 ret = QLA_SUCCESS;
167
168 qla2x00_nv_write(ha, NVR_DATA_OUT);
169 qla2x00_nv_write(ha, 0);
170 qla2x00_nv_write(ha, 0);
171
172 for (word = 0; word < 8; word++)
173 qla2x00_nv_write(ha, NVR_DATA_OUT);
174
175 qla2x00_nv_deselect(ha);
176
177 /* Write data */
178 nv_cmd = (addr << 16) | NV_WRITE_OP;
179 nv_cmd |= data;
180 nv_cmd <<= 5;
181 for (count = 0; count < 27; count++) {
182 if (nv_cmd & BIT_31)
183 qla2x00_nv_write(ha, NVR_DATA_OUT);
184 else
185 qla2x00_nv_write(ha, 0);
186
187 nv_cmd <<= 1;
188 }
189
190 qla2x00_nv_deselect(ha);
191
192 /* Wait for NVRAM to become ready */
193 WRT_REG_WORD(&reg->nvram, NVR_SELECT);
194 do {
195 NVRAM_DELAY();
196 word = RD_REG_WORD(&reg->nvram);
197 if (!--tmo) {
198 ret = QLA_FUNCTION_FAILED;
199 break;
200 }
201 } while ((word & NVR_DATA_IN) == 0);
202
203 qla2x00_nv_deselect(ha);
204
205 /* Disable writes */
206 qla2x00_nv_write(ha, NVR_DATA_OUT);
207 for (count = 0; count < 10; count++)
208 qla2x00_nv_write(ha, 0);
209
210 qla2x00_nv_deselect(ha);
211
212 return ret;
213}
214
205/** 215/**
206 * qla2x00_nvram_request() - Sends read command to NVRAM and gets data from 216 * qla2x00_nvram_request() - Sends read command to NVRAM and gets data from
207 * NVRAM. 217 * NVRAM.
@@ -292,3 +302,435 @@ qla2x00_nv_write(scsi_qla_host_t *ha, uint16_t data)
292 NVRAM_DELAY(); 302 NVRAM_DELAY();
293} 303}
294 304
305/**
306 * qla2x00_clear_nvram_protection() -
307 * @ha: HA context
308 */
309static int
310qla2x00_clear_nvram_protection(scsi_qla_host_t *ha)
311{
312 int ret, stat;
313 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
314 uint32_t word;
315 uint16_t wprot, wprot_old;
316
317 /* Clear NVRAM write protection. */
318 ret = QLA_FUNCTION_FAILED;
319 wprot_old = cpu_to_le16(qla2x00_get_nvram_word(ha, 0));
320 stat = qla2x00_write_nvram_word_tmo(ha, 0,
321 __constant_cpu_to_le16(0x1234), 100000);
322 wprot = cpu_to_le16(qla2x00_get_nvram_word(ha, 0));
323 if (stat != QLA_SUCCESS || wprot != __constant_cpu_to_le16(0x1234)) {
324 /* Write enable. */
325 qla2x00_nv_write(ha, NVR_DATA_OUT);
326 qla2x00_nv_write(ha, 0);
327 qla2x00_nv_write(ha, 0);
328 for (word = 0; word < 8; word++)
329 qla2x00_nv_write(ha, NVR_DATA_OUT);
330
331 qla2x00_nv_deselect(ha);
332
333 /* Enable protection register. */
334 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
335 qla2x00_nv_write(ha, NVR_PR_ENABLE);
336 qla2x00_nv_write(ha, NVR_PR_ENABLE);
337 for (word = 0; word < 8; word++)
338 qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
339
340 qla2x00_nv_deselect(ha);
341
342 /* Clear protection register (ffff is cleared). */
343 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
344 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
345 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
346 for (word = 0; word < 8; word++)
347 qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
348
349 qla2x00_nv_deselect(ha);
350
351 /* Wait for NVRAM to become ready. */
352 WRT_REG_WORD(&reg->nvram, NVR_SELECT);
353 do {
354 NVRAM_DELAY();
355 word = RD_REG_WORD(&reg->nvram);
356 } while ((word & NVR_DATA_IN) == 0);
357
358 ret = QLA_SUCCESS;
359 } else
360 qla2x00_write_nvram_word(ha, 0, wprot_old);
361
362 return ret;
363}
364
365static void
366qla2x00_set_nvram_protection(scsi_qla_host_t *ha, int stat)
367{
368 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
369 uint32_t word;
370
371 if (stat != QLA_SUCCESS)
372 return;
373
374 /* Set NVRAM write protection. */
375 /* Write enable. */
376 qla2x00_nv_write(ha, NVR_DATA_OUT);
377 qla2x00_nv_write(ha, 0);
378 qla2x00_nv_write(ha, 0);
379 for (word = 0; word < 8; word++)
380 qla2x00_nv_write(ha, NVR_DATA_OUT);
381
382 qla2x00_nv_deselect(ha);
383
384 /* Enable protection register. */
385 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
386 qla2x00_nv_write(ha, NVR_PR_ENABLE);
387 qla2x00_nv_write(ha, NVR_PR_ENABLE);
388 for (word = 0; word < 8; word++)
389 qla2x00_nv_write(ha, NVR_DATA_OUT | NVR_PR_ENABLE);
390
391 qla2x00_nv_deselect(ha);
392
393 /* Enable protection register. */
394 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
395 qla2x00_nv_write(ha, NVR_PR_ENABLE);
396 qla2x00_nv_write(ha, NVR_PR_ENABLE | NVR_DATA_OUT);
397 for (word = 0; word < 8; word++)
398 qla2x00_nv_write(ha, NVR_PR_ENABLE);
399
400 qla2x00_nv_deselect(ha);
401
402 /* Wait for NVRAM to become ready. */
403 WRT_REG_WORD(&reg->nvram, NVR_SELECT);
404 do {
405 NVRAM_DELAY();
406 word = RD_REG_WORD(&reg->nvram);
407 } while ((word & NVR_DATA_IN) == 0);
408}
409
410
411/*****************************************************************************/
412/* Flash Manipulation Routines */
413/*****************************************************************************/
414
415static inline uint32_t
416flash_conf_to_access_addr(uint32_t faddr)
417{
418 return FARX_ACCESS_FLASH_CONF | faddr;
419}
420
421static inline uint32_t
422flash_data_to_access_addr(uint32_t faddr)
423{
424 return FARX_ACCESS_FLASH_DATA | faddr;
425}
426
427static inline uint32_t
428nvram_conf_to_access_addr(uint32_t naddr)
429{
430 return FARX_ACCESS_NVRAM_CONF | naddr;
431}
432
433static inline uint32_t
434nvram_data_to_access_addr(uint32_t naddr)
435{
436 return FARX_ACCESS_NVRAM_DATA | naddr;
437}
438
439uint32_t
440qla24xx_read_flash_dword(scsi_qla_host_t *ha, uint32_t addr)
441{
442 int rval;
443 uint32_t cnt, data;
444 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
445
446 WRT_REG_DWORD(&reg->flash_addr, addr & ~FARX_DATA_FLAG);
447 /* Wait for READ cycle to complete. */
448 rval = QLA_SUCCESS;
449 for (cnt = 3000;
450 (RD_REG_DWORD(&reg->flash_addr) & FARX_DATA_FLAG) == 0 &&
451 rval == QLA_SUCCESS; cnt--) {
452 if (cnt)
453 udelay(10);
454 else
455 rval = QLA_FUNCTION_TIMEOUT;
456 }
457
458 /* TODO: What happens if we time out? */
459 data = 0xDEADDEAD;
460 if (rval == QLA_SUCCESS)
461 data = RD_REG_DWORD(&reg->flash_data);
462
463 return data;
464}
465
466uint32_t *
467qla24xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
468 uint32_t dwords)
469{
470 uint32_t i;
471 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
472
473 /* Pause RISC. */
474 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
475 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
476
477 /* Dword reads to flash. */
478 for (i = 0; i < dwords; i++, faddr++)
479 dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
480 flash_data_to_access_addr(faddr)));
481
482 /* Release RISC pause. */
483 WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
484 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
485
486 return dwptr;
487}
488
489int
490qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data)
491{
492 int rval;
493 uint32_t cnt;
494 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
495
496 WRT_REG_DWORD(&reg->flash_data, data);
497 RD_REG_DWORD(&reg->flash_data); /* PCI Posting. */
498 WRT_REG_DWORD(&reg->flash_addr, addr | FARX_DATA_FLAG);
499 /* Wait for Write cycle to complete. */
500 rval = QLA_SUCCESS;
501 for (cnt = 500000; (RD_REG_DWORD(&reg->flash_addr) & FARX_DATA_FLAG) &&
502 rval == QLA_SUCCESS; cnt--) {
503 if (cnt)
504 udelay(10);
505 else
506 rval = QLA_FUNCTION_TIMEOUT;
507 }
508 return rval;
509}
510
511void
512qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
513 uint8_t *flash_id)
514{
515 uint32_t ids;
516
517 ids = qla24xx_read_flash_dword(ha, flash_data_to_access_addr(0xd03ab));
518 *man_id = LSB(ids);
519 *flash_id = MSB(ids);
520}
521
522int
523qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
524 uint32_t dwords)
525{
526 int ret;
527 uint32_t liter;
528 uint32_t sec_mask, rest_addr, conf_addr;
529 uint32_t fdata;
530 uint8_t man_id, flash_id;
531 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
532
533 ret = QLA_SUCCESS;
534
535 /* Pause RISC. */
536 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
537 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
538
539 qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id);
540 DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__,
541 ha->host_no, man_id, flash_id));
542
543 conf_addr = flash_conf_to_access_addr(0x03d8);
544 switch (man_id) {
545 case 0xbf: // STT flash
546 rest_addr = 0x1fff;
547 sec_mask = 0x3e000;
548 if (flash_id == 0x80)
549 conf_addr = flash_conf_to_access_addr(0x0352);
550 break;
551 case 0x13: // ST M25P80
552 rest_addr = 0x3fff;
553 sec_mask = 0x3c000;
554 break;
555 default:
556 // Default to 64 kb sector size
557 rest_addr = 0x3fff;
558 sec_mask = 0x3c000;
559 break;
560 }
561
562 /* Enable flash write. */
563 WRT_REG_DWORD(&reg->ctrl_status,
564 RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
565 RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
566
567 /* Disable flash write-protection. */
568 qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0);
569
570 do { /* Loop once to provide quick error exit. */
571 for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
572 /* Are we at the beginning of a sector? */
573 if ((faddr & rest_addr) == 0) {
574 fdata = (faddr & sec_mask) << 2;
575 ret = qla24xx_write_flash_dword(ha, conf_addr,
576 (fdata & 0xff00) |((fdata << 16) &
577 0xff0000) | ((fdata >> 16) & 0xff));
578 if (ret != QLA_SUCCESS) {
579 DEBUG9(printk("%s(%ld) Unable to flash "
580 "sector: address=%x.\n", __func__,
581 ha->host_no, faddr));
582 break;
583 }
584 }
585 ret = qla24xx_write_flash_dword(ha,
586 flash_data_to_access_addr(faddr),
587 cpu_to_le32(*dwptr));
588 if (ret != QLA_SUCCESS) {
589 DEBUG9(printk("%s(%ld) Unable to program flash "
590 "address=%x data=%x.\n", __func__,
591 ha->host_no, faddr, *dwptr));
592 break;
593 }
594 }
595 } while (0);
596
597 /* Disable flash write. */
598 WRT_REG_DWORD(&reg->ctrl_status,
599 RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
600 RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
601
602 /* Release RISC pause. */
603 WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
604 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
605
606 return ret;
607}
608
609uint8_t *
610qla2x00_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
611 uint32_t bytes)
612{
613 uint32_t i;
614 uint16_t *wptr;
615
616 /* Word reads to NVRAM via registers. */
617 wptr = (uint16_t *)buf;
618 qla2x00_lock_nvram_access(ha);
619 for (i = 0; i < bytes >> 1; i++, naddr++)
620 wptr[i] = cpu_to_le16(qla2x00_get_nvram_word(ha,
621 naddr));
622 qla2x00_unlock_nvram_access(ha);
623
624 return buf;
625}
626
627uint8_t *
628qla24xx_read_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
629 uint32_t bytes)
630{
631 uint32_t i;
632 uint32_t *dwptr;
633 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
634
635 /* Pause RISC. */
636 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
637 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
638
639 /* Dword reads to flash. */
640 dwptr = (uint32_t *)buf;
641 for (i = 0; i < bytes >> 2; i++, naddr++)
642 dwptr[i] = cpu_to_le32(qla24xx_read_flash_dword(ha,
643 nvram_data_to_access_addr(naddr)));
644
645 /* Release RISC pause. */
646 WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
647 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
648
649 return buf;
650}
651
652int
653qla2x00_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
654 uint32_t bytes)
655{
656 int ret, stat;
657 uint32_t i;
658 uint16_t *wptr;
659
660 ret = QLA_SUCCESS;
661
662 qla2x00_lock_nvram_access(ha);
663
664 /* Disable NVRAM write-protection. */
665 stat = qla2x00_clear_nvram_protection(ha);
666
667 wptr = (uint16_t *)buf;
668 for (i = 0; i < bytes >> 1; i++, naddr++) {
669 qla2x00_write_nvram_word(ha, naddr,
670 cpu_to_le16(*wptr));
671 wptr++;
672 }
673
674 /* Enable NVRAM write-protection. */
675 qla2x00_set_nvram_protection(ha, stat);
676
677 qla2x00_unlock_nvram_access(ha);
678
679 return ret;
680}
681
682int
683qla24xx_write_nvram_data(scsi_qla_host_t *ha, uint8_t *buf, uint32_t naddr,
684 uint32_t bytes)
685{
686 int ret;
687 uint32_t i;
688 uint32_t *dwptr;
689 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
690
691 ret = QLA_SUCCESS;
692
693 /* Pause RISC. */
694 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
695 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
696
697 /* Enable flash write. */
698 WRT_REG_DWORD(&reg->ctrl_status,
699 RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
700 RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
701
702 /* Disable NVRAM write-protection. */
703 qla24xx_write_flash_dword(ha, nvram_conf_to_access_addr(0x101),
704 0);
705 qla24xx_write_flash_dword(ha, nvram_conf_to_access_addr(0x101),
706 0);
707
708 /* Dword writes to flash. */
709 dwptr = (uint32_t *)buf;
710 for (i = 0; i < bytes >> 2; i++, naddr++, dwptr++) {
711 ret = qla24xx_write_flash_dword(ha,
712 nvram_data_to_access_addr(naddr),
713 cpu_to_le32(*dwptr));
714 if (ret != QLA_SUCCESS) {
715 DEBUG9(printk("%s(%ld) Unable to program "
716 "nvram address=%x data=%x.\n", __func__,
717 ha->host_no, naddr, *dwptr));
718 break;
719 }
720 }
721
722 /* Enable NVRAM write-protection. */
723 qla24xx_write_flash_dword(ha, nvram_conf_to_access_addr(0x101),
724 0x8c);
725
726 /* Disable flash write. */
727 WRT_REG_DWORD(&reg->ctrl_status,
728 RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
729 RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
730
731 /* Release RISC pause. */
732 WRT_REG_DWORD(&reg->hccr, HCCRX_REL_RISC_PAUSE);
733 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
734
735 return ret;
736}