blob: b52fa8977d91cbc16bff9524cf2f23dc181d3010 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Andrew Vasquezfa90c542005-10-27 11:10:08 -07002 * QLogic Fibre Channel HBA Driver
3 * Copyright (c) 2003-2005 QLogic Corporation
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Andrew Vasquezfa90c542005-10-27 11:10:08 -07005 * See LICENSE.qla2xxx for copyright and licensing details.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
7#include "qla_def.h"
8
9#include <linux/delay.h>
10
Andrew Vasqueza7a167b2006-06-23 16:10:29 -070011static inline void
12qla2xxx_prep_dump(scsi_qla_host_t *ha, struct qla2xxx_fw_dump *fw_dump)
13{
14 fw_dump->fw_major_version = htonl(ha->fw_major_version);
15 fw_dump->fw_minor_version = htonl(ha->fw_minor_version);
16 fw_dump->fw_subminor_version = htonl(ha->fw_subminor_version);
17 fw_dump->fw_attributes = htonl(ha->fw_attributes);
18
19 fw_dump->vendor = htonl(ha->pdev->vendor);
20 fw_dump->device = htonl(ha->pdev->device);
21 fw_dump->subsystem_vendor = htonl(ha->pdev->subsystem_vendor);
22 fw_dump->subsystem_device = htonl(ha->pdev->subsystem_device);
23}
24
25static inline void *
26qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr)
27{
28 /* Request queue. */
29 memcpy(ptr, ha->request_ring, ha->request_q_length *
30 sizeof(request_t));
31
32 /* Response queue. */
33 ptr += ha->request_q_length * sizeof(request_t);
34 memcpy(ptr, ha->response_ring, ha->response_q_length *
35 sizeof(response_t));
36
37 return ptr + (ha->response_q_length * sizeof(response_t));
38}
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070040static int
Andrew Vasquezc81d04c2007-07-26 11:41:13 -070041qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram,
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -070042 uint32_t cram_size, uint32_t *ext_mem, void **nxt)
43{
44 int rval;
45 uint32_t cnt, stat, timer, risc_address, ext_mem_cnt;
46 uint16_t mb[4];
47 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
48
49 rval = QLA_SUCCESS;
50 risc_address = ext_mem_cnt = 0;
51 memset(mb, 0, sizeof(mb));
52
53 /* Code RAM. */
54 risc_address = 0x20000;
55 WRT_REG_WORD(&reg->mailbox0, MBC_READ_RAM_EXTENDED);
56 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
57
58 for (cnt = 0; cnt < cram_size / 4 && rval == QLA_SUCCESS;
59 cnt++, risc_address++) {
60 WRT_REG_WORD(&reg->mailbox1, LSW(risc_address));
61 WRT_REG_WORD(&reg->mailbox8, MSW(risc_address));
62 RD_REG_WORD(&reg->mailbox8);
63 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
64
65 for (timer = 6000000; timer; timer--) {
66 /* Check for pending interrupts. */
67 stat = RD_REG_DWORD(&reg->host_status);
68 if (stat & HSRX_RISC_INT) {
69 stat &= 0xff;
70
71 if (stat == 0x1 || stat == 0x2 ||
72 stat == 0x10 || stat == 0x11) {
73 set_bit(MBX_INTERRUPT,
74 &ha->mbx_cmd_flags);
75
76 mb[0] = RD_REG_WORD(&reg->mailbox0);
77 mb[2] = RD_REG_WORD(&reg->mailbox2);
78 mb[3] = RD_REG_WORD(&reg->mailbox3);
79
80 WRT_REG_DWORD(&reg->hccr,
81 HCCRX_CLR_RISC_INT);
82 RD_REG_DWORD(&reg->hccr);
83 break;
84 }
85
86 /* Clear this intr; it wasn't a mailbox intr */
87 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
88 RD_REG_DWORD(&reg->hccr);
89 }
90 udelay(5);
91 }
92
93 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
94 rval = mb[0] & MBS_MASK;
95 code_ram[cnt] = htonl((mb[3] << 16) | mb[2]);
96 } else {
97 rval = QLA_FUNCTION_FAILED;
98 }
99 }
100
101 if (rval == QLA_SUCCESS) {
102 /* External Memory. */
103 risc_address = 0x100000;
104 ext_mem_cnt = ha->fw_memory_size - 0x100000 + 1;
105 WRT_REG_WORD(&reg->mailbox0, MBC_READ_RAM_EXTENDED);
106 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
107 }
108 for (cnt = 0; cnt < ext_mem_cnt && rval == QLA_SUCCESS;
109 cnt++, risc_address++) {
110 WRT_REG_WORD(&reg->mailbox1, LSW(risc_address));
111 WRT_REG_WORD(&reg->mailbox8, MSW(risc_address));
112 RD_REG_WORD(&reg->mailbox8);
113 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
114
115 for (timer = 6000000; timer; timer--) {
116 /* Check for pending interrupts. */
117 stat = RD_REG_DWORD(&reg->host_status);
118 if (stat & HSRX_RISC_INT) {
119 stat &= 0xff;
120
121 if (stat == 0x1 || stat == 0x2 ||
122 stat == 0x10 || stat == 0x11) {
123 set_bit(MBX_INTERRUPT,
124 &ha->mbx_cmd_flags);
125
126 mb[0] = RD_REG_WORD(&reg->mailbox0);
127 mb[2] = RD_REG_WORD(&reg->mailbox2);
128 mb[3] = RD_REG_WORD(&reg->mailbox3);
129
130 WRT_REG_DWORD(&reg->hccr,
131 HCCRX_CLR_RISC_INT);
132 RD_REG_DWORD(&reg->hccr);
133 break;
134 }
135
136 /* Clear this intr; it wasn't a mailbox intr */
137 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
138 RD_REG_DWORD(&reg->hccr);
139 }
140 udelay(5);
141 }
142
143 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
144 rval = mb[0] & MBS_MASK;
145 ext_mem[cnt] = htonl((mb[3] << 16) | mb[2]);
146 } else {
147 rval = QLA_FUNCTION_FAILED;
148 }
149 }
150
151 *nxt = rval == QLA_SUCCESS ? &ext_mem[cnt]: NULL;
152 return rval;
153}
154
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700155static uint32_t *
156qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase,
157 uint32_t count, uint32_t *buf)
158{
159 uint32_t __iomem *dmp_reg;
160
161 WRT_REG_DWORD(&reg->iobase_addr, iobase);
162 dmp_reg = &reg->iobase_window;
163 while (count--)
164 *buf++ = htonl(RD_REG_DWORD(dmp_reg++));
165
166 return buf;
167}
168
169static inline int
170qla24xx_pause_risc(struct device_reg_24xx __iomem *reg)
171{
172 int rval = QLA_SUCCESS;
173 uint32_t cnt;
174
175 if ((RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0) {
176 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_RESET |
177 HCCRX_CLR_HOST_INT);
178 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
179 WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
180 for (cnt = 30000;
181 (RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0 &&
182 rval == QLA_SUCCESS; cnt--) {
183 if (cnt)
184 udelay(100);
185 else
186 rval = QLA_FUNCTION_TIMEOUT;
187 }
188 }
189
190 return rval;
191}
192
193static int
194qla24xx_soft_reset(scsi_qla_host_t *ha)
195{
196 int rval = QLA_SUCCESS;
197 uint32_t cnt;
198 uint16_t mb0, wd;
199 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
200
201 /* Reset RISC. */
202 WRT_REG_DWORD(&reg->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
203 for (cnt = 0; cnt < 30000; cnt++) {
204 if ((RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
205 break;
206
207 udelay(10);
208 }
209
210 WRT_REG_DWORD(&reg->ctrl_status,
211 CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
212 pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
213
214 udelay(100);
215 /* Wait for firmware to complete NVRAM accesses. */
216 mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
217 for (cnt = 10000 ; cnt && mb0; cnt--) {
218 udelay(5);
219 mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
220 barrier();
221 }
222
223 /* Wait for soft-reset to complete. */
224 for (cnt = 0; cnt < 30000; cnt++) {
225 if ((RD_REG_DWORD(&reg->ctrl_status) &
226 CSRX_ISP_SOFT_RESET) == 0)
227 break;
228
229 udelay(10);
230 }
231 WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_RESET);
232 RD_REG_DWORD(&reg->hccr); /* PCI Posting. */
233
234 for (cnt = 30000; RD_REG_WORD(&reg->mailbox0) != 0 &&
235 rval == QLA_SUCCESS; cnt--) {
236 if (cnt)
237 udelay(100);
238 else
239 rval = QLA_FUNCTION_TIMEOUT;
240 }
241
242 return rval;
243}
244
245static inline void
246qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count,
247 uint16_t *buf)
248{
249 uint16_t __iomem *dmp_reg = &reg->u.isp2300.fb_cmd;
250
251 while (count--)
252 *buf++ = htons(RD_REG_WORD(dmp_reg++));
253}
254
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255/**
256 * qla2300_fw_dump() - Dumps binary data from the 2300 firmware.
257 * @ha: HA context
258 * @hardware_locked: Called with the hardware_lock
259 */
260void
261qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
262{
263 int rval;
264 uint32_t cnt, timer;
265 uint32_t risc_address;
266 uint16_t mb0, mb2;
267
268 uint32_t stat;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700269 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 uint16_t __iomem *dmp_reg;
271 unsigned long flags;
272 struct qla2300_fw_dump *fw;
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700273 uint32_t data_ram_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
275 risc_address = data_ram_cnt = 0;
276 mb0 = mb2 = 0;
277 flags = 0;
278
279 if (!hardware_locked)
280 spin_lock_irqsave(&ha->hardware_lock, flags);
281
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700282 if (!ha->fw_dump) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 qla_printk(KERN_WARNING, ha,
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700284 "No buffer available for dump!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 goto qla2300_fw_dump_failed;
286 }
287
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700288 if (ha->fw_dumped) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 qla_printk(KERN_WARNING, ha,
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700290 "Firmware has been previously dumped (%p) -- ignoring "
291 "request...\n", ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 goto qla2300_fw_dump_failed;
293 }
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700294 fw = &ha->fw_dump->isp.isp23;
295 qla2xxx_prep_dump(ha, ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
297 rval = QLA_SUCCESS;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700298 fw->hccr = htons(RD_REG_WORD(&reg->hccr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 /* Pause RISC. */
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700301 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302 if (IS_QLA2300(ha)) {
303 for (cnt = 30000;
304 (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
305 rval == QLA_SUCCESS; cnt--) {
306 if (cnt)
307 udelay(100);
308 else
309 rval = QLA_FUNCTION_TIMEOUT;
310 }
311 } else {
312 RD_REG_WORD(&reg->hccr); /* PCI Posting. */
313 udelay(10);
314 }
315
316 if (rval == QLA_SUCCESS) {
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700317 dmp_reg = &reg->flash_address;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700318 for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700319 fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700321 dmp_reg = &reg->u.isp2300.req_q_in;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700322 for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700323 fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700325 dmp_reg = &reg->u.isp2300.mailbox0;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700326 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700327 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328
329 WRT_REG_WORD(&reg->ctrl_status, 0x40);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700330 qla2xxx_read_window(reg, 32, fw->resp_dma_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331
332 WRT_REG_WORD(&reg->ctrl_status, 0x50);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700333 qla2xxx_read_window(reg, 48, fw->dma_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334
335 WRT_REG_WORD(&reg->ctrl_status, 0x00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700336 dmp_reg = &reg->risc_hw;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700337 for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700338 fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700340 WRT_REG_WORD(&reg->pcr, 0x2000);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700341 qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700343 WRT_REG_WORD(&reg->pcr, 0x2200);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700344 qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700346 WRT_REG_WORD(&reg->pcr, 0x2400);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700347 qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700349 WRT_REG_WORD(&reg->pcr, 0x2600);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700350 qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700352 WRT_REG_WORD(&reg->pcr, 0x2800);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700353 qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700355 WRT_REG_WORD(&reg->pcr, 0x2A00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700356 qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700358 WRT_REG_WORD(&reg->pcr, 0x2C00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700359 qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700361 WRT_REG_WORD(&reg->pcr, 0x2E00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700362 qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700364 WRT_REG_WORD(&reg->ctrl_status, 0x10);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700365 qla2xxx_read_window(reg, 64, fw->frame_buf_hdw_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700367 WRT_REG_WORD(&reg->ctrl_status, 0x20);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700368 qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700370 WRT_REG_WORD(&reg->ctrl_status, 0x30);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700371 qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
373 /* Reset RISC. */
374 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
375 for (cnt = 0; cnt < 30000; cnt++) {
376 if ((RD_REG_WORD(&reg->ctrl_status) &
377 CSR_ISP_SOFT_RESET) == 0)
378 break;
379
380 udelay(10);
381 }
382 }
383
384 if (!IS_QLA2300(ha)) {
385 for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 &&
386 rval == QLA_SUCCESS; cnt--) {
387 if (cnt)
388 udelay(100);
389 else
390 rval = QLA_FUNCTION_TIMEOUT;
391 }
392 }
393
394 if (rval == QLA_SUCCESS) {
395 /* Get RISC SRAM. */
396 risc_address = 0x800;
397 WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD);
398 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
399 }
400 for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS;
401 cnt++, risc_address++) {
402 WRT_MAILBOX_REG(ha, reg, 1, (uint16_t)risc_address);
403 WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
404
405 for (timer = 6000000; timer; timer--) {
406 /* Check for pending interrupts. */
407 stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
408 if (stat & HSR_RISC_INT) {
409 stat &= 0xff;
410
411 if (stat == 0x1 || stat == 0x2) {
412 set_bit(MBX_INTERRUPT,
413 &ha->mbx_cmd_flags);
414
415 mb0 = RD_MAILBOX_REG(ha, reg, 0);
416 mb2 = RD_MAILBOX_REG(ha, reg, 2);
417
418 /* Release mailbox registers. */
419 WRT_REG_WORD(&reg->semaphore, 0);
420 WRT_REG_WORD(&reg->hccr,
421 HCCR_CLR_RISC_INT);
422 RD_REG_WORD(&reg->hccr);
423 break;
424 } else if (stat == 0x10 || stat == 0x11) {
425 set_bit(MBX_INTERRUPT,
426 &ha->mbx_cmd_flags);
427
428 mb0 = RD_MAILBOX_REG(ha, reg, 0);
429 mb2 = RD_MAILBOX_REG(ha, reg, 2);
430
431 WRT_REG_WORD(&reg->hccr,
432 HCCR_CLR_RISC_INT);
433 RD_REG_WORD(&reg->hccr);
434 break;
435 }
436
437 /* clear this intr; it wasn't a mailbox intr */
438 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
439 RD_REG_WORD(&reg->hccr);
440 }
441 udelay(5);
442 }
443
444 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
445 rval = mb0 & MBS_MASK;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700446 fw->risc_ram[cnt] = htons(mb2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 } else {
448 rval = QLA_FUNCTION_FAILED;
449 }
450 }
451
452 if (rval == QLA_SUCCESS) {
453 /* Get stack SRAM. */
454 risc_address = 0x10000;
455 WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_EXTENDED);
456 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
457 }
458 for (cnt = 0; cnt < sizeof(fw->stack_ram) / 2 && rval == QLA_SUCCESS;
459 cnt++, risc_address++) {
460 WRT_MAILBOX_REG(ha, reg, 1, LSW(risc_address));
461 WRT_MAILBOX_REG(ha, reg, 8, MSW(risc_address));
462 WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
463
464 for (timer = 6000000; timer; timer--) {
465 /* Check for pending interrupts. */
466 stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
467 if (stat & HSR_RISC_INT) {
468 stat &= 0xff;
469
470 if (stat == 0x1 || stat == 0x2) {
471 set_bit(MBX_INTERRUPT,
472 &ha->mbx_cmd_flags);
473
474 mb0 = RD_MAILBOX_REG(ha, reg, 0);
475 mb2 = RD_MAILBOX_REG(ha, reg, 2);
476
477 /* Release mailbox registers. */
478 WRT_REG_WORD(&reg->semaphore, 0);
479 WRT_REG_WORD(&reg->hccr,
480 HCCR_CLR_RISC_INT);
481 RD_REG_WORD(&reg->hccr);
482 break;
483 } else if (stat == 0x10 || stat == 0x11) {
484 set_bit(MBX_INTERRUPT,
485 &ha->mbx_cmd_flags);
486
487 mb0 = RD_MAILBOX_REG(ha, reg, 0);
488 mb2 = RD_MAILBOX_REG(ha, reg, 2);
489
490 WRT_REG_WORD(&reg->hccr,
491 HCCR_CLR_RISC_INT);
492 RD_REG_WORD(&reg->hccr);
493 break;
494 }
495
496 /* clear this intr; it wasn't a mailbox intr */
497 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
498 RD_REG_WORD(&reg->hccr);
499 }
500 udelay(5);
501 }
502
503 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
504 rval = mb0 & MBS_MASK;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700505 fw->stack_ram[cnt] = htons(mb2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 } else {
507 rval = QLA_FUNCTION_FAILED;
508 }
509 }
510
511 if (rval == QLA_SUCCESS) {
512 /* Get data SRAM. */
513 risc_address = 0x11000;
514 data_ram_cnt = ha->fw_memory_size - risc_address + 1;
515 WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_EXTENDED);
516 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
517 }
518 for (cnt = 0; cnt < data_ram_cnt && rval == QLA_SUCCESS;
519 cnt++, risc_address++) {
520 WRT_MAILBOX_REG(ha, reg, 1, LSW(risc_address));
521 WRT_MAILBOX_REG(ha, reg, 8, MSW(risc_address));
522 WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
523
524 for (timer = 6000000; timer; timer--) {
525 /* Check for pending interrupts. */
526 stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
527 if (stat & HSR_RISC_INT) {
528 stat &= 0xff;
529
530 if (stat == 0x1 || stat == 0x2) {
531 set_bit(MBX_INTERRUPT,
532 &ha->mbx_cmd_flags);
533
534 mb0 = RD_MAILBOX_REG(ha, reg, 0);
535 mb2 = RD_MAILBOX_REG(ha, reg, 2);
536
537 /* Release mailbox registers. */
538 WRT_REG_WORD(&reg->semaphore, 0);
539 WRT_REG_WORD(&reg->hccr,
540 HCCR_CLR_RISC_INT);
541 RD_REG_WORD(&reg->hccr);
542 break;
543 } else if (stat == 0x10 || stat == 0x11) {
544 set_bit(MBX_INTERRUPT,
545 &ha->mbx_cmd_flags);
546
547 mb0 = RD_MAILBOX_REG(ha, reg, 0);
548 mb2 = RD_MAILBOX_REG(ha, reg, 2);
549
550 WRT_REG_WORD(&reg->hccr,
551 HCCR_CLR_RISC_INT);
552 RD_REG_WORD(&reg->hccr);
553 break;
554 }
555
556 /* clear this intr; it wasn't a mailbox intr */
557 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
558 RD_REG_WORD(&reg->hccr);
559 }
560 udelay(5);
561 }
562
563 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
564 rval = mb0 & MBS_MASK;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700565 fw->data_ram[cnt] = htons(mb2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 } else {
567 rval = QLA_FUNCTION_FAILED;
568 }
569 }
570
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700571 if (rval == QLA_SUCCESS)
572 qla2xxx_copy_queues(ha, &fw->data_ram[cnt]);
573
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 if (rval != QLA_SUCCESS) {
575 qla_printk(KERN_WARNING, ha,
576 "Failed to dump firmware (%x)!!!\n", rval);
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700577 ha->fw_dumped = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 } else {
580 qla_printk(KERN_INFO, ha,
581 "Firmware dump saved to temp buffer (%ld/%p).\n",
582 ha->host_no, ha->fw_dump);
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700583 ha->fw_dumped = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 }
585
586qla2300_fw_dump_failed:
587 if (!hardware_locked)
588 spin_unlock_irqrestore(&ha->hardware_lock, flags);
589}
590
591/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 * qla2100_fw_dump() - Dumps binary data from the 2100/2200 firmware.
593 * @ha: HA context
594 * @hardware_locked: Called with the hardware_lock
595 */
596void
597qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
598{
599 int rval;
600 uint32_t cnt, timer;
601 uint16_t risc_address;
602 uint16_t mb0, mb2;
Andrew Vasquez3d716442005-07-06 10:30:26 -0700603 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 uint16_t __iomem *dmp_reg;
605 unsigned long flags;
606 struct qla2100_fw_dump *fw;
607
608 risc_address = 0;
609 mb0 = mb2 = 0;
610 flags = 0;
611
612 if (!hardware_locked)
613 spin_lock_irqsave(&ha->hardware_lock, flags);
614
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700615 if (!ha->fw_dump) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 qla_printk(KERN_WARNING, ha,
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700617 "No buffer available for dump!!!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 goto qla2100_fw_dump_failed;
619 }
620
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700621 if (ha->fw_dumped) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622 qla_printk(KERN_WARNING, ha,
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700623 "Firmware has been previously dumped (%p) -- ignoring "
624 "request...\n", ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 goto qla2100_fw_dump_failed;
626 }
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700627 fw = &ha->fw_dump->isp.isp21;
628 qla2xxx_prep_dump(ha, ha->fw_dump);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
630 rval = QLA_SUCCESS;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700631 fw->hccr = htons(RD_REG_WORD(&reg->hccr));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
633 /* Pause RISC. */
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700634 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 for (cnt = 30000; (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
636 rval == QLA_SUCCESS; cnt--) {
637 if (cnt)
638 udelay(100);
639 else
640 rval = QLA_FUNCTION_TIMEOUT;
641 }
642 if (rval == QLA_SUCCESS) {
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700643 dmp_reg = &reg->flash_address;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700644 for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700645 fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700647 dmp_reg = &reg->u.isp2100.mailbox0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648 for (cnt = 0; cnt < ha->mbx_count; cnt++) {
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700649 if (cnt == 8)
650 dmp_reg = &reg->u_end.isp2200.mailbox8;
651
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700652 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 }
654
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700655 dmp_reg = &reg->u.isp2100.unused_2[0];
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700656 for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700657 fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
659 WRT_REG_WORD(&reg->ctrl_status, 0x00);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700660 dmp_reg = &reg->risc_hw;
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700661 for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700662 fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700664 WRT_REG_WORD(&reg->pcr, 0x2000);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700665 qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700667 WRT_REG_WORD(&reg->pcr, 0x2100);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700668 qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700670 WRT_REG_WORD(&reg->pcr, 0x2200);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700671 qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700673 WRT_REG_WORD(&reg->pcr, 0x2300);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700674 qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700676 WRT_REG_WORD(&reg->pcr, 0x2400);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700677 qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700679 WRT_REG_WORD(&reg->pcr, 0x2500);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700680 qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700682 WRT_REG_WORD(&reg->pcr, 0x2600);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700683 qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700685 WRT_REG_WORD(&reg->pcr, 0x2700);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700686 qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700688 WRT_REG_WORD(&reg->ctrl_status, 0x10);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700689 qla2xxx_read_window(reg, 16, fw->frame_buf_hdw_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700691 WRT_REG_WORD(&reg->ctrl_status, 0x20);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700692 qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700694 WRT_REG_WORD(&reg->ctrl_status, 0x30);
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700695 qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
697 /* Reset the ISP. */
698 WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
699 }
700
701 for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 &&
702 rval == QLA_SUCCESS; cnt--) {
703 if (cnt)
704 udelay(100);
705 else
706 rval = QLA_FUNCTION_TIMEOUT;
707 }
708
709 /* Pause RISC. */
710 if (rval == QLA_SUCCESS && (IS_QLA2200(ha) || (IS_QLA2100(ha) &&
711 (RD_REG_WORD(&reg->mctr) & (BIT_1 | BIT_0)) != 0))) {
712
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -0700713 WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 for (cnt = 30000;
715 (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
716 rval == QLA_SUCCESS; cnt--) {
717 if (cnt)
718 udelay(100);
719 else
720 rval = QLA_FUNCTION_TIMEOUT;
721 }
722 if (rval == QLA_SUCCESS) {
723 /* Set memory configuration and timing. */
724 if (IS_QLA2100(ha))
725 WRT_REG_WORD(&reg->mctr, 0xf1);
726 else
727 WRT_REG_WORD(&reg->mctr, 0xf2);
728 RD_REG_WORD(&reg->mctr); /* PCI Posting. */
729
730 /* Release RISC. */
731 WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
732 }
733 }
734
735 if (rval == QLA_SUCCESS) {
736 /* Get RISC SRAM. */
737 risc_address = 0x1000;
738 WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD);
739 clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
740 }
741 for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS;
742 cnt++, risc_address++) {
743 WRT_MAILBOX_REG(ha, reg, 1, risc_address);
744 WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
745
746 for (timer = 6000000; timer != 0; timer--) {
747 /* Check for pending interrupts. */
748 if (RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) {
749 if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
750 set_bit(MBX_INTERRUPT,
751 &ha->mbx_cmd_flags);
752
753 mb0 = RD_MAILBOX_REG(ha, reg, 0);
754 mb2 = RD_MAILBOX_REG(ha, reg, 2);
755
756 WRT_REG_WORD(&reg->semaphore, 0);
757 WRT_REG_WORD(&reg->hccr,
758 HCCR_CLR_RISC_INT);
759 RD_REG_WORD(&reg->hccr);
760 break;
761 }
762 WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
763 RD_REG_WORD(&reg->hccr);
764 }
765 udelay(5);
766 }
767
768 if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
769 rval = mb0 & MBS_MASK;
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700770 fw->risc_ram[cnt] = htons(mb2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 } else {
772 rval = QLA_FUNCTION_FAILED;
773 }
774 }
775
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700776 if (rval == QLA_SUCCESS)
777 qla2xxx_copy_queues(ha, &fw->risc_ram[cnt]);
778
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 if (rval != QLA_SUCCESS) {
780 qla_printk(KERN_WARNING, ha,
781 "Failed to dump firmware (%x)!!!\n", rval);
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700782 ha->fw_dumped = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 } else {
785 qla_printk(KERN_INFO, ha,
786 "Firmware dump saved to temp buffer (%ld/%p).\n",
787 ha->host_no, ha->fw_dump);
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700788 ha->fw_dumped = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 }
790
791qla2100_fw_dump_failed:
792 if (!hardware_locked)
793 spin_unlock_irqrestore(&ha->hardware_lock, flags);
794}
795
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700796void
797qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
798{
799 int rval;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700800 uint32_t cnt;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700801 uint32_t risc_address;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700802
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700803 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
804 uint32_t __iomem *dmp_reg;
805 uint32_t *iter_reg;
806 uint16_t __iomem *mbx_reg;
807 unsigned long flags;
808 struct qla24xx_fw_dump *fw;
809 uint32_t ext_mem_cnt;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -0700810 void *nxt;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700811
812 risc_address = ext_mem_cnt = 0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700813 flags = 0;
814
815 if (!hardware_locked)
816 spin_lock_irqsave(&ha->hardware_lock, flags);
817
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700818 if (!ha->fw_dump) {
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700819 qla_printk(KERN_WARNING, ha,
820 "No buffer available for dump!!!\n");
821 goto qla24xx_fw_dump_failed;
822 }
823
824 if (ha->fw_dumped) {
825 qla_printk(KERN_WARNING, ha,
826 "Firmware has been previously dumped (%p) -- ignoring "
Andrew Vasquezd4e3e042006-05-17 15:09:50 -0700827 "request...\n", ha->fw_dump);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700828 goto qla24xx_fw_dump_failed;
829 }
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700830 fw = &ha->fw_dump->isp.isp24;
831 qla2xxx_prep_dump(ha, ha->fw_dump);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700832
Andrew Vasqueza7a167b2006-06-23 16:10:29 -0700833 fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700834
835 /* Pause RISC. */
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700836 rval = qla24xx_pause_risc(reg);
837 if (rval != QLA_SUCCESS)
838 goto qla24xx_fw_dump_failed_0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700839
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700840 /* Host interface registers. */
841 dmp_reg = &reg->flash_addr;
842 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
843 fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700844
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700845 /* Disable interrupts. */
846 WRT_REG_DWORD(&reg->ictrl, 0);
847 RD_REG_DWORD(&reg->ictrl);
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800848
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700849 /* Shadow registers. */
850 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
851 RD_REG_DWORD(&reg->iobase_addr);
852 WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
853 fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800854
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700855 WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
856 fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800857
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700858 WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
859 fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800860
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700861 WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
862 fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800863
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700864 WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
865 fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800866
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700867 WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
868 fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800869
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700870 WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
871 fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
andrew.vasquez@qlogic.com210d5352006-01-13 17:05:21 -0800872
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700873 /* Mailbox registers. */
874 mbx_reg = &reg->mailbox0;
875 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
876 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700877
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700878 /* Transfer sequence registers. */
879 iter_reg = fw->xseq_gp_reg;
880 iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
881 iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
882 iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
883 iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
884 iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
885 iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
886 iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
887 qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700888
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700889 qla24xx_read_window(reg, 0xBFE0, 16, fw->xseq_0_reg);
890 qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700891
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700892 /* Receive sequence registers. */
893 iter_reg = fw->rseq_gp_reg;
894 iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
895 iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
896 iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
897 iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
898 iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
899 iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
900 iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
901 qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700902
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700903 qla24xx_read_window(reg, 0xFFD0, 16, fw->rseq_0_reg);
904 qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
905 qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700906
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700907 /* Command DMA registers. */
908 qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700909
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700910 /* Queues. */
911 iter_reg = fw->req0_dma_reg;
912 iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
913 dmp_reg = &reg->iobase_q;
914 for (cnt = 0; cnt < 7; cnt++)
915 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700916
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700917 iter_reg = fw->resp0_dma_reg;
918 iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
919 dmp_reg = &reg->iobase_q;
920 for (cnt = 0; cnt < 7; cnt++)
921 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700922
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700923 iter_reg = fw->req1_dma_reg;
924 iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
925 dmp_reg = &reg->iobase_q;
926 for (cnt = 0; cnt < 7; cnt++)
927 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700928
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700929 /* Transmit DMA registers. */
930 iter_reg = fw->xmt0_dma_reg;
931 iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
932 qla24xx_read_window(reg, 0x7610, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700933
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700934 iter_reg = fw->xmt1_dma_reg;
935 iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
936 qla24xx_read_window(reg, 0x7630, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700937
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700938 iter_reg = fw->xmt2_dma_reg;
939 iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
940 qla24xx_read_window(reg, 0x7650, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700941
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700942 iter_reg = fw->xmt3_dma_reg;
943 iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
944 qla24xx_read_window(reg, 0x7670, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700945
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700946 iter_reg = fw->xmt4_dma_reg;
947 iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
948 qla24xx_read_window(reg, 0x7690, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700949
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700950 qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700951
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700952 /* Receive DMA registers. */
953 iter_reg = fw->rcvt0_data_dma_reg;
954 iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
955 qla24xx_read_window(reg, 0x7710, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700956
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700957 iter_reg = fw->rcvt1_data_dma_reg;
958 iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
959 qla24xx_read_window(reg, 0x7730, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700960
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700961 /* RISC registers. */
962 iter_reg = fw->risc_gp_reg;
963 iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
964 iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
965 iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
966 iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
967 iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
968 iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
969 iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
970 qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700971
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700972 /* Local memory controller registers. */
973 iter_reg = fw->lmc_reg;
974 iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
975 iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
976 iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
977 iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
978 iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
979 iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
980 qla24xx_read_window(reg, 0x3060, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700981
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700982 /* Fibre Protocol Module registers. */
983 iter_reg = fw->fpm_hdw_reg;
984 iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
985 iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
986 iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
987 iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
988 iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
989 iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
990 iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
991 iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
992 iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
993 iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
994 iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
995 qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -0700996
Andrew Vasquezc81d04c2007-07-26 11:41:13 -0700997 /* Frame Buffer registers. */
998 iter_reg = fw->fb_hdw_reg;
999 iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
1000 iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
1001 iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
1002 iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
1003 iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
1004 iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
1005 iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
1006 iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
1007 iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
1008 iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
1009 qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001010
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001011 rval = qla24xx_soft_reset(ha);
1012 if (rval != QLA_SUCCESS)
1013 goto qla24xx_fw_dump_failed_0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001014
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001015 rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
1016 fw->ext_mem, &nxt);
1017 if (rval != QLA_SUCCESS)
1018 goto qla24xx_fw_dump_failed_0;
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001019
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001020 nxt = qla2xxx_copy_queues(ha, nxt);
1021 if (ha->eft)
1022 memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001023
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001024qla24xx_fw_dump_failed_0:
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001025 if (rval != QLA_SUCCESS) {
1026 qla_printk(KERN_WARNING, ha,
1027 "Failed to dump firmware (%x)!!!\n", rval);
1028 ha->fw_dumped = 0;
1029
1030 } else {
1031 qla_printk(KERN_INFO, ha,
1032 "Firmware dump saved to temp buffer (%ld/%p).\n",
Andrew Vasquezd4e3e042006-05-17 15:09:50 -07001033 ha->host_no, ha->fw_dump);
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001034 ha->fw_dumped = 1;
1035 }
1036
1037qla24xx_fw_dump_failed:
1038 if (!hardware_locked)
1039 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1040}
1041
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001042void
1043qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked)
1044{
1045 int rval;
1046 uint32_t cnt;
1047 uint32_t risc_address;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001048
1049 struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
1050 uint32_t __iomem *dmp_reg;
1051 uint32_t *iter_reg;
1052 uint16_t __iomem *mbx_reg;
1053 unsigned long flags;
1054 struct qla25xx_fw_dump *fw;
1055 uint32_t ext_mem_cnt;
1056 void *nxt;
1057
1058 risc_address = ext_mem_cnt = 0;
1059 flags = 0;
1060
1061 if (!hardware_locked)
1062 spin_lock_irqsave(&ha->hardware_lock, flags);
1063
1064 if (!ha->fw_dump) {
1065 qla_printk(KERN_WARNING, ha,
1066 "No buffer available for dump!!!\n");
1067 goto qla25xx_fw_dump_failed;
1068 }
1069
1070 if (ha->fw_dumped) {
1071 qla_printk(KERN_WARNING, ha,
1072 "Firmware has been previously dumped (%p) -- ignoring "
1073 "request...\n", ha->fw_dump);
1074 goto qla25xx_fw_dump_failed;
1075 }
1076 fw = &ha->fw_dump->isp.isp25;
1077 qla2xxx_prep_dump(ha, ha->fw_dump);
1078
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001079 fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
1080
1081 /* Pause RISC. */
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001082 rval = qla24xx_pause_risc(reg);
1083 if (rval != QLA_SUCCESS)
1084 goto qla25xx_fw_dump_failed_0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001085
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001086 /* Host interface registers. */
1087 dmp_reg = &reg->flash_addr;
1088 for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
1089 fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001090
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001091 /* Disable interrupts. */
1092 WRT_REG_DWORD(&reg->ictrl, 0);
1093 RD_REG_DWORD(&reg->ictrl);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001094
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001095 /* Shadow registers. */
1096 WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
1097 RD_REG_DWORD(&reg->iobase_addr);
1098 WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
1099 fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001100
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001101 WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
1102 fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001103
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001104 WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
1105 fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001106
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001107 WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
1108 fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001109
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001110 WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
1111 fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001112
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001113 WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
1114 fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001115
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001116 WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
1117 fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001118
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001119 WRT_REG_DWORD(&reg->iobase_select, 0xB0700000);
1120 fw->shadow_reg[7] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001121
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001122 WRT_REG_DWORD(&reg->iobase_select, 0xB0800000);
1123 fw->shadow_reg[8] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001124
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001125 WRT_REG_DWORD(&reg->iobase_select, 0xB0900000);
1126 fw->shadow_reg[9] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001127
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001128 WRT_REG_DWORD(&reg->iobase_select, 0xB0A00000);
1129 fw->shadow_reg[10] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001130
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001131 /* RISC I/O register. */
1132 WRT_REG_DWORD(&reg->iobase_addr, 0x0010);
1133 fw->risc_io_reg = htonl(RD_REG_DWORD(&reg->iobase_window));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001134
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001135 /* Mailbox registers. */
1136 mbx_reg = &reg->mailbox0;
1137 for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
1138 fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001139
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001140 /* Transfer sequence registers. */
1141 iter_reg = fw->xseq_gp_reg;
1142 iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
1143 iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
1144 iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
1145 iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
1146 iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
1147 iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
1148 iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
1149 qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001150
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001151 iter_reg = fw->xseq_0_reg;
1152 iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg);
1153 iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg);
1154 qla24xx_read_window(reg, 0xBFE0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001155
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001156 qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001157
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001158 /* Receive sequence registers. */
1159 iter_reg = fw->rseq_gp_reg;
1160 iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
1161 iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
1162 iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
1163 iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
1164 iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
1165 iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
1166 iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
1167 qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001168
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001169 iter_reg = fw->rseq_0_reg;
1170 iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg);
1171 qla24xx_read_window(reg, 0xFFD0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001172
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001173 qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
1174 qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001175
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001176 /* Auxiliary sequence registers. */
1177 iter_reg = fw->aseq_gp_reg;
1178 iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg);
1179 iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg);
1180 iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg);
1181 iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg);
1182 iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg);
1183 iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg);
1184 iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg);
1185 qla24xx_read_window(reg, 0xB070, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001186
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001187 iter_reg = fw->aseq_0_reg;
1188 iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg);
1189 qla24xx_read_window(reg, 0xB0D0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001190
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001191 qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg);
1192 qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001193
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001194 /* Command DMA registers. */
1195 qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001196
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001197 /* Queues. */
1198 iter_reg = fw->req0_dma_reg;
1199 iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
1200 dmp_reg = &reg->iobase_q;
1201 for (cnt = 0; cnt < 7; cnt++)
1202 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001203
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001204 iter_reg = fw->resp0_dma_reg;
1205 iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
1206 dmp_reg = &reg->iobase_q;
1207 for (cnt = 0; cnt < 7; cnt++)
1208 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001209
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001210 iter_reg = fw->req1_dma_reg;
1211 iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
1212 dmp_reg = &reg->iobase_q;
1213 for (cnt = 0; cnt < 7; cnt++)
1214 *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001215
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001216 /* Transmit DMA registers. */
1217 iter_reg = fw->xmt0_dma_reg;
1218 iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
1219 qla24xx_read_window(reg, 0x7610, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001220
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001221 iter_reg = fw->xmt1_dma_reg;
1222 iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
1223 qla24xx_read_window(reg, 0x7630, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001224
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001225 iter_reg = fw->xmt2_dma_reg;
1226 iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
1227 qla24xx_read_window(reg, 0x7650, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001228
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001229 iter_reg = fw->xmt3_dma_reg;
1230 iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
1231 qla24xx_read_window(reg, 0x7670, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001232
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001233 iter_reg = fw->xmt4_dma_reg;
1234 iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
1235 qla24xx_read_window(reg, 0x7690, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001236
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001237 qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001238
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001239 /* Receive DMA registers. */
1240 iter_reg = fw->rcvt0_data_dma_reg;
1241 iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
1242 qla24xx_read_window(reg, 0x7710, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001243
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001244 iter_reg = fw->rcvt1_data_dma_reg;
1245 iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
1246 qla24xx_read_window(reg, 0x7730, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001247
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001248 /* RISC registers. */
1249 iter_reg = fw->risc_gp_reg;
1250 iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
1251 iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
1252 iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
1253 iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
1254 iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
1255 iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
1256 iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
1257 qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001258
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001259 /* Local memory controller registers. */
1260 iter_reg = fw->lmc_reg;
1261 iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
1262 iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
1263 iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
1264 iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
1265 iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
1266 iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
1267 iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg);
1268 qla24xx_read_window(reg, 0x3070, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001269
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001270 /* Fibre Protocol Module registers. */
1271 iter_reg = fw->fpm_hdw_reg;
1272 iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
1273 iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
1274 iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
1275 iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
1276 iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
1277 iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
1278 iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
1279 iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
1280 iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
1281 iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
1282 iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
1283 qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001284
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001285 /* Frame Buffer registers. */
1286 iter_reg = fw->fb_hdw_reg;
1287 iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
1288 iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
1289 iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
1290 iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
1291 iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
1292 iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
1293 iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
1294 iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
1295 iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
1296 iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
1297 iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
1298 qla24xx_read_window(reg, 0x6F00, 16, iter_reg);
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001299
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001300 rval = qla24xx_soft_reset(ha);
1301 if (rval != QLA_SUCCESS)
1302 goto qla25xx_fw_dump_failed_0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001303
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001304 rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
1305 fw->ext_mem, &nxt);
1306 if (rval != QLA_SUCCESS)
1307 goto qla25xx_fw_dump_failed_0;
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001308
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001309 nxt = qla2xxx_copy_queues(ha, nxt);
1310 if (ha->eft)
1311 memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001312
Andrew Vasquezc81d04c2007-07-26 11:41:13 -07001313qla25xx_fw_dump_failed_0:
Andrew Vasquezc3a2f0d2007-07-19 20:37:34 -07001314 if (rval != QLA_SUCCESS) {
1315 qla_printk(KERN_WARNING, ha,
1316 "Failed to dump firmware (%x)!!!\n", rval);
1317 ha->fw_dumped = 0;
1318
1319 } else {
1320 qla_printk(KERN_INFO, ha,
1321 "Firmware dump saved to temp buffer (%ld/%p).\n",
1322 ha->host_no, ha->fw_dump);
1323 ha->fw_dumped = 1;
1324 }
1325
1326qla25xx_fw_dump_failed:
1327 if (!hardware_locked)
1328 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1329}
1330
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331/****************************************************************************/
1332/* Driver Debug Functions. */
1333/****************************************************************************/
1334
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001335void
1336qla2x00_dump_regs(scsi_qla_host_t *ha)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337{
Andrew Vasquez6afd9762007-08-12 18:22:56 -07001338 int i;
Andrew Vasquez3d716442005-07-06 10:30:26 -07001339 struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
Andrew Vasquez6afd9762007-08-12 18:22:56 -07001340 struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
1341 uint16_t __iomem *mbx_reg;
1342
1343 mbx_reg = IS_FWI2_CAPABLE(ha) ? &reg24->mailbox0:
1344 MAILBOX_REG(ha, reg, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
1346 printk("Mailbox registers:\n");
Andrew Vasquez6afd9762007-08-12 18:22:56 -07001347 for (i = 0; i < 6; i++)
1348 printk("scsi(%ld): mbox %d 0x%04x \n", ha->host_no, i,
1349 RD_REG_WORD(mbx_reg++));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350}
1351
1352
1353void
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001354qla2x00_dump_buffer(uint8_t * b, uint32_t size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355{
1356 uint32_t cnt;
1357 uint8_t c;
1358
1359 printk(" 0 1 2 3 4 5 6 7 8 9 "
1360 "Ah Bh Ch Dh Eh Fh\n");
1361 printk("----------------------------------------"
1362 "----------------------\n");
1363
1364 for (cnt = 0; cnt < size;) {
1365 c = *b++;
1366 printk("%02x",(uint32_t) c);
1367 cnt++;
1368 if (!(cnt % 16))
1369 printk("\n");
1370 else
1371 printk(" ");
1372 }
1373 if (cnt % 16)
1374 printk("\n");
1375}
1376
1377/**************************************************************************
1378 * qla2x00_print_scsi_cmd
1379 * Dumps out info about the scsi cmd and srb.
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001380 * Input
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 * cmd : struct scsi_cmnd
1382 **************************************************************************/
1383void
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001384qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385{
1386 int i;
1387 struct scsi_qla_host *ha;
1388 srb_t *sp;
1389
1390 ha = (struct scsi_qla_host *)cmd->device->host->hostdata;
1391
1392 sp = (srb_t *) cmd->SCp.ptr;
1393 printk("SCSI Command @=0x%p, Handle=0x%p\n", cmd, cmd->host_scribble);
1394 printk(" chan=0x%02x, target=0x%02x, lun=0x%02x, cmd_len=0x%02x\n",
1395 cmd->device->channel, cmd->device->id, cmd->device->lun,
1396 cmd->cmd_len);
1397 printk(" CDB: ");
1398 for (i = 0; i < cmd->cmd_len; i++) {
1399 printk("0x%02x ", cmd->cmnd[i]);
1400 }
c6295cd2005-04-03 14:59:11 -05001401 printk("\n seg_cnt=%d, allowed=%d, retries=%d\n",
FUJITA Tomonori385d70b2007-05-26 01:55:38 +09001402 scsi_sg_count(cmd), cmd->allowed, cmd->retries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 printk(" request buffer=0x%p, request buffer len=0x%x\n",
FUJITA Tomonori385d70b2007-05-26 01:55:38 +09001404 scsi_sglist(cmd), scsi_bufflen(cmd));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 printk(" tag=%d, transfersize=0x%x\n",
1406 cmd->tag, cmd->transfersize);
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001407 printk(" serial_number=%lx, SP=%p\n", cmd->serial_number, sp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 printk(" data direction=%d\n", cmd->sc_data_direction);
1409
1410 if (!sp)
1411 return;
1412
1413 printk(" sp flags=0x%x\n", sp->flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414}
1415
Andrew Vasquez6d9b61e2005-07-06 10:30:36 -07001416void
1417qla2x00_dump_pkt(void *pkt)
1418{
1419 uint32_t i;
1420 uint8_t *data = (uint8_t *) pkt;
1421
1422 for (i = 0; i < 64; i++) {
1423 if (!(i % 4))
1424 printk("\n%02x: ", i);
1425
1426 printk("%02x ", data[i]);
1427 }
1428 printk("\n");
1429}
1430
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431#if defined(QL_DEBUG_ROUTINES)
1432/*
1433 * qla2x00_formatted_dump_buffer
1434 * Prints string plus buffer.
1435 *
1436 * Input:
1437 * string = Null terminated string (no newline at end).
1438 * buffer = buffer address.
1439 * wd_size = word size 8, 16, 32 or 64 bits
1440 * count = number of words.
1441 */
1442void
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -07001443qla2x00_formatted_dump_buffer(char *string, uint8_t * buffer,
1444 uint8_t wd_size, uint32_t count)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445{
1446 uint32_t cnt;
1447 uint16_t *buf16;
1448 uint32_t *buf32;
1449
1450 if (strcmp(string, "") != 0)
1451 printk("%s\n",string);
1452
1453 switch (wd_size) {
1454 case 8:
1455 printk(" 0 1 2 3 4 5 6 7 "
1456 "8 9 Ah Bh Ch Dh Eh Fh\n");
1457 printk("-----------------------------------------"
1458 "-------------------------------------\n");
1459
1460 for (cnt = 1; cnt <= count; cnt++, buffer++) {
1461 printk("%02x",*buffer);
1462 if (cnt % 16 == 0)
1463 printk("\n");
1464 else
1465 printk(" ");
1466 }
1467 if (cnt % 16 != 0)
1468 printk("\n");
1469 break;
1470 case 16:
1471 printk(" 0 2 4 6 8 Ah "
1472 " Ch Eh\n");
1473 printk("-----------------------------------------"
1474 "-------------\n");
1475
1476 buf16 = (uint16_t *) buffer;
1477 for (cnt = 1; cnt <= count; cnt++, buf16++) {
1478 printk("%4x",*buf16);
1479
1480 if (cnt % 8 == 0)
1481 printk("\n");
1482 else if (*buf16 < 10)
1483 printk(" ");
1484 else
1485 printk(" ");
1486 }
1487 if (cnt % 8 != 0)
1488 printk("\n");
1489 break;
1490 case 32:
1491 printk(" 0 4 8 Ch\n");
1492 printk("------------------------------------------\n");
1493
1494 buf32 = (uint32_t *) buffer;
1495 for (cnt = 1; cnt <= count; cnt++, buf32++) {
1496 printk("%8x", *buf32);
1497
1498 if (cnt % 4 == 0)
1499 printk("\n");
1500 else if (*buf32 < 10)
1501 printk(" ");
1502 else
1503 printk(" ");
1504 }
1505 if (cnt % 4 != 0)
1506 printk("\n");
1507 break;
1508 default:
1509 break;
1510 }
1511}
1512#endif