xref: /linux/drivers/scsi/qla2xxx/qla_dbg.c (revision 7b867cf76fbcc8d77867cbec6f509f71dce8a98f)
11da177e4SLinus Torvalds /*
2fa90c54fSAndrew Vasquez  * QLogic Fibre Channel HBA Driver
301e58d8eSAndrew Vasquez  * Copyright (c)  2003-2008 QLogic Corporation
41da177e4SLinus Torvalds  *
5fa90c54fSAndrew Vasquez  * See LICENSE.qla2xxx for copyright and licensing details.
61da177e4SLinus Torvalds  */
71da177e4SLinus Torvalds #include "qla_def.h"
81da177e4SLinus Torvalds 
91da177e4SLinus Torvalds #include <linux/delay.h>
101da177e4SLinus Torvalds 
11a7a167bfSAndrew Vasquez static inline void
12*7b867cf7SAnirban Chakraborty qla2xxx_prep_dump(struct qla_hw_data *ha, struct qla2xxx_fw_dump *fw_dump)
13a7a167bfSAndrew Vasquez {
14a7a167bfSAndrew Vasquez 	fw_dump->fw_major_version = htonl(ha->fw_major_version);
15a7a167bfSAndrew Vasquez 	fw_dump->fw_minor_version = htonl(ha->fw_minor_version);
16a7a167bfSAndrew Vasquez 	fw_dump->fw_subminor_version = htonl(ha->fw_subminor_version);
17a7a167bfSAndrew Vasquez 	fw_dump->fw_attributes = htonl(ha->fw_attributes);
18a7a167bfSAndrew Vasquez 
19a7a167bfSAndrew Vasquez 	fw_dump->vendor = htonl(ha->pdev->vendor);
20a7a167bfSAndrew Vasquez 	fw_dump->device = htonl(ha->pdev->device);
21a7a167bfSAndrew Vasquez 	fw_dump->subsystem_vendor = htonl(ha->pdev->subsystem_vendor);
22a7a167bfSAndrew Vasquez 	fw_dump->subsystem_device = htonl(ha->pdev->subsystem_device);
23a7a167bfSAndrew Vasquez }
24a7a167bfSAndrew Vasquez 
25a7a167bfSAndrew Vasquez static inline void *
26*7b867cf7SAnirban Chakraborty qla2xxx_copy_queues(scsi_qla_host_t *vha, void *ptr)
27a7a167bfSAndrew Vasquez {
28*7b867cf7SAnirban Chakraborty 	struct req_que *req = vha->hw->req;
29*7b867cf7SAnirban Chakraborty 	struct rsp_que *rsp = vha->hw->rsp;
30*7b867cf7SAnirban Chakraborty 
31a7a167bfSAndrew Vasquez 	/* Request queue. */
32*7b867cf7SAnirban Chakraborty 	memcpy(ptr, req->ring, req->length *
33a7a167bfSAndrew Vasquez 	    sizeof(request_t));
34a7a167bfSAndrew Vasquez 
35a7a167bfSAndrew Vasquez 	/* Response queue. */
36*7b867cf7SAnirban Chakraborty 	ptr += req->length * sizeof(request_t);
37*7b867cf7SAnirban Chakraborty 	memcpy(ptr, rsp->ring, rsp->length  *
38a7a167bfSAndrew Vasquez 	    sizeof(response_t));
39a7a167bfSAndrew Vasquez 
40*7b867cf7SAnirban Chakraborty 	return ptr + (rsp->length * sizeof(response_t));
41a7a167bfSAndrew Vasquez }
421da177e4SLinus Torvalds 
43c3a2f0dfSAndrew Vasquez static int
44*7b867cf7SAnirban Chakraborty qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint32_t *ram,
45c5722708SAndrew Vasquez     uint32_t ram_dwords, void **nxt)
46c3a2f0dfSAndrew Vasquez {
47c3a2f0dfSAndrew Vasquez 	int rval;
48c5722708SAndrew Vasquez 	uint32_t cnt, stat, timer, dwords, idx;
49c5722708SAndrew Vasquez 	uint16_t mb0;
50c3a2f0dfSAndrew Vasquez 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
51c5722708SAndrew Vasquez 	dma_addr_t dump_dma = ha->gid_list_dma;
52c5722708SAndrew Vasquez 	uint32_t *dump = (uint32_t *)ha->gid_list;
53c3a2f0dfSAndrew Vasquez 
54c3a2f0dfSAndrew Vasquez 	rval = QLA_SUCCESS;
55c5722708SAndrew Vasquez 	mb0 = 0;
56c5722708SAndrew Vasquez 
57c5722708SAndrew Vasquez 	WRT_REG_WORD(&reg->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
58c5722708SAndrew Vasquez 	clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
59c5722708SAndrew Vasquez 
60c5722708SAndrew Vasquez 	dwords = GID_LIST_SIZE / 4;
61c5722708SAndrew Vasquez 	for (cnt = 0; cnt < ram_dwords && rval == QLA_SUCCESS;
62c5722708SAndrew Vasquez 	    cnt += dwords, addr += dwords) {
63c5722708SAndrew Vasquez 		if (cnt + dwords > ram_dwords)
64c5722708SAndrew Vasquez 			dwords = ram_dwords - cnt;
65c5722708SAndrew Vasquez 
66c5722708SAndrew Vasquez 		WRT_REG_WORD(&reg->mailbox1, LSW(addr));
67c5722708SAndrew Vasquez 		WRT_REG_WORD(&reg->mailbox8, MSW(addr));
68c5722708SAndrew Vasquez 
69c5722708SAndrew Vasquez 		WRT_REG_WORD(&reg->mailbox2, MSW(dump_dma));
70c5722708SAndrew Vasquez 		WRT_REG_WORD(&reg->mailbox3, LSW(dump_dma));
71c5722708SAndrew Vasquez 		WRT_REG_WORD(&reg->mailbox6, MSW(MSD(dump_dma)));
72c5722708SAndrew Vasquez 		WRT_REG_WORD(&reg->mailbox7, LSW(MSD(dump_dma)));
73c5722708SAndrew Vasquez 
74c5722708SAndrew Vasquez 		WRT_REG_WORD(&reg->mailbox4, MSW(dwords));
75c5722708SAndrew Vasquez 		WRT_REG_WORD(&reg->mailbox5, LSW(dwords));
76c5722708SAndrew Vasquez 		WRT_REG_DWORD(&reg->hccr, HCCRX_SET_HOST_INT);
77c5722708SAndrew Vasquez 
78c5722708SAndrew Vasquez 		for (timer = 6000000; timer; timer--) {
79c5722708SAndrew Vasquez 			/* Check for pending interrupts. */
80c5722708SAndrew Vasquez 			stat = RD_REG_DWORD(&reg->host_status);
81c5722708SAndrew Vasquez 			if (stat & HSRX_RISC_INT) {
82c5722708SAndrew Vasquez 				stat &= 0xff;
83c5722708SAndrew Vasquez 
84c5722708SAndrew Vasquez 				if (stat == 0x1 || stat == 0x2 ||
85c5722708SAndrew Vasquez 				    stat == 0x10 || stat == 0x11) {
86c5722708SAndrew Vasquez 					set_bit(MBX_INTERRUPT,
87c5722708SAndrew Vasquez 					    &ha->mbx_cmd_flags);
88c5722708SAndrew Vasquez 
89c5722708SAndrew Vasquez 					mb0 = RD_REG_WORD(&reg->mailbox0);
90c5722708SAndrew Vasquez 
91c5722708SAndrew Vasquez 					WRT_REG_DWORD(&reg->hccr,
92c5722708SAndrew Vasquez 					    HCCRX_CLR_RISC_INT);
93c5722708SAndrew Vasquez 					RD_REG_DWORD(&reg->hccr);
94c5722708SAndrew Vasquez 					break;
95c5722708SAndrew Vasquez 				}
96c5722708SAndrew Vasquez 
97c5722708SAndrew Vasquez 				/* Clear this intr; it wasn't a mailbox intr */
98c5722708SAndrew Vasquez 				WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
99c5722708SAndrew Vasquez 				RD_REG_DWORD(&reg->hccr);
100c5722708SAndrew Vasquez 			}
101c5722708SAndrew Vasquez 			udelay(5);
102c5722708SAndrew Vasquez 		}
103c5722708SAndrew Vasquez 
104c5722708SAndrew Vasquez 		if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
105c5722708SAndrew Vasquez 			rval = mb0 & MBS_MASK;
106c5722708SAndrew Vasquez 			for (idx = 0; idx < dwords; idx++)
107c5722708SAndrew Vasquez 				ram[cnt + idx] = swab32(dump[idx]);
108c5722708SAndrew Vasquez 		} else {
109c5722708SAndrew Vasquez 			rval = QLA_FUNCTION_FAILED;
110c5722708SAndrew Vasquez 		}
111c5722708SAndrew Vasquez 	}
112c5722708SAndrew Vasquez 
113c5722708SAndrew Vasquez 	*nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
114c5722708SAndrew Vasquez 	return rval;
115c5722708SAndrew Vasquez }
116c5722708SAndrew Vasquez 
117c5722708SAndrew Vasquez static int
118*7b867cf7SAnirban Chakraborty qla24xx_dump_memory(struct qla_hw_data *ha, uint32_t *code_ram,
119c5722708SAndrew Vasquez     uint32_t cram_size, void **nxt)
120c5722708SAndrew Vasquez {
121c5722708SAndrew Vasquez 	int rval;
122c3a2f0dfSAndrew Vasquez 
123c3a2f0dfSAndrew Vasquez 	/* Code RAM. */
124c5722708SAndrew Vasquez 	rval = qla24xx_dump_ram(ha, 0x20000, code_ram, cram_size / 4, nxt);
125c5722708SAndrew Vasquez 	if (rval != QLA_SUCCESS)
126c3a2f0dfSAndrew Vasquez 		return rval;
127c5722708SAndrew Vasquez 
128c5722708SAndrew Vasquez 	/* External Memory. */
129c5722708SAndrew Vasquez 	return qla24xx_dump_ram(ha, 0x100000, *nxt,
130c5722708SAndrew Vasquez 	    ha->fw_memory_size - 0x100000 + 1, nxt);
131c3a2f0dfSAndrew Vasquez }
132c3a2f0dfSAndrew Vasquez 
133c81d04c9SAndrew Vasquez static uint32_t *
134c81d04c9SAndrew Vasquez qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase,
135c81d04c9SAndrew Vasquez     uint32_t count, uint32_t *buf)
136c81d04c9SAndrew Vasquez {
137c81d04c9SAndrew Vasquez 	uint32_t __iomem *dmp_reg;
138c81d04c9SAndrew Vasquez 
139c81d04c9SAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_addr, iobase);
140c81d04c9SAndrew Vasquez 	dmp_reg = &reg->iobase_window;
141c81d04c9SAndrew Vasquez 	while (count--)
142c81d04c9SAndrew Vasquez 		*buf++ = htonl(RD_REG_DWORD(dmp_reg++));
143c81d04c9SAndrew Vasquez 
144c81d04c9SAndrew Vasquez 	return buf;
145c81d04c9SAndrew Vasquez }
146c81d04c9SAndrew Vasquez 
147c81d04c9SAndrew Vasquez static inline int
148c81d04c9SAndrew Vasquez qla24xx_pause_risc(struct device_reg_24xx __iomem *reg)
149c81d04c9SAndrew Vasquez {
150c81d04c9SAndrew Vasquez 	int rval = QLA_SUCCESS;
151c81d04c9SAndrew Vasquez 	uint32_t cnt;
152c81d04c9SAndrew Vasquez 
153c3b058afSAndrew Vasquez 	if (RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE)
154c3b058afSAndrew Vasquez 		return rval;
155c3b058afSAndrew Vasquez 
156c81d04c9SAndrew Vasquez 	WRT_REG_DWORD(&reg->hccr, HCCRX_SET_RISC_PAUSE);
157c3b058afSAndrew Vasquez 	for (cnt = 30000; (RD_REG_DWORD(&reg->hccr) & HCCRX_RISC_PAUSE) == 0 &&
158c81d04c9SAndrew Vasquez 	    rval == QLA_SUCCESS; cnt--) {
159c81d04c9SAndrew Vasquez 		if (cnt)
160c81d04c9SAndrew Vasquez 			udelay(100);
161c81d04c9SAndrew Vasquez 		else
162c81d04c9SAndrew Vasquez 			rval = QLA_FUNCTION_TIMEOUT;
163c81d04c9SAndrew Vasquez 	}
164c81d04c9SAndrew Vasquez 
165c81d04c9SAndrew Vasquez 	return rval;
166c81d04c9SAndrew Vasquez }
167c81d04c9SAndrew Vasquez 
168c81d04c9SAndrew Vasquez static int
169*7b867cf7SAnirban Chakraborty qla24xx_soft_reset(struct qla_hw_data *ha)
170c81d04c9SAndrew Vasquez {
171c81d04c9SAndrew Vasquez 	int rval = QLA_SUCCESS;
172c81d04c9SAndrew Vasquez 	uint32_t cnt;
173c81d04c9SAndrew Vasquez 	uint16_t mb0, wd;
174c81d04c9SAndrew Vasquez 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
175c81d04c9SAndrew Vasquez 
176c81d04c9SAndrew Vasquez 	/* Reset RISC. */
177c81d04c9SAndrew Vasquez 	WRT_REG_DWORD(&reg->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
178c81d04c9SAndrew Vasquez 	for (cnt = 0; cnt < 30000; cnt++) {
179c81d04c9SAndrew Vasquez 		if ((RD_REG_DWORD(&reg->ctrl_status) & CSRX_DMA_ACTIVE) == 0)
180c81d04c9SAndrew Vasquez 			break;
181c81d04c9SAndrew Vasquez 
182c81d04c9SAndrew Vasquez 		udelay(10);
183c81d04c9SAndrew Vasquez 	}
184c81d04c9SAndrew Vasquez 
185c81d04c9SAndrew Vasquez 	WRT_REG_DWORD(&reg->ctrl_status,
186c81d04c9SAndrew Vasquez 	    CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES);
187c81d04c9SAndrew Vasquez 	pci_read_config_word(ha->pdev, PCI_COMMAND, &wd);
188c81d04c9SAndrew Vasquez 
189c81d04c9SAndrew Vasquez 	udelay(100);
190c81d04c9SAndrew Vasquez 	/* Wait for firmware to complete NVRAM accesses. */
191c81d04c9SAndrew Vasquez 	mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
192c81d04c9SAndrew Vasquez 	for (cnt = 10000 ; cnt && mb0; cnt--) {
193c81d04c9SAndrew Vasquez 		udelay(5);
194c81d04c9SAndrew Vasquez 		mb0 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
195c81d04c9SAndrew Vasquez 		barrier();
196c81d04c9SAndrew Vasquez 	}
197c81d04c9SAndrew Vasquez 
198c81d04c9SAndrew Vasquez 	/* Wait for soft-reset to complete. */
199c81d04c9SAndrew Vasquez 	for (cnt = 0; cnt < 30000; cnt++) {
200c81d04c9SAndrew Vasquez 		if ((RD_REG_DWORD(&reg->ctrl_status) &
201c81d04c9SAndrew Vasquez 		    CSRX_ISP_SOFT_RESET) == 0)
202c81d04c9SAndrew Vasquez 			break;
203c81d04c9SAndrew Vasquez 
204c81d04c9SAndrew Vasquez 		udelay(10);
205c81d04c9SAndrew Vasquez 	}
206c81d04c9SAndrew Vasquez 	WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_RESET);
207c81d04c9SAndrew Vasquez 	RD_REG_DWORD(&reg->hccr);             /* PCI Posting. */
208c81d04c9SAndrew Vasquez 
209c81d04c9SAndrew Vasquez 	for (cnt = 30000; RD_REG_WORD(&reg->mailbox0) != 0 &&
210c81d04c9SAndrew Vasquez 	    rval == QLA_SUCCESS; cnt--) {
211c81d04c9SAndrew Vasquez 		if (cnt)
212c81d04c9SAndrew Vasquez 			udelay(100);
213c81d04c9SAndrew Vasquez 		else
214c81d04c9SAndrew Vasquez 			rval = QLA_FUNCTION_TIMEOUT;
215c81d04c9SAndrew Vasquez 	}
216c81d04c9SAndrew Vasquez 
217c81d04c9SAndrew Vasquez 	return rval;
218c81d04c9SAndrew Vasquez }
219c81d04c9SAndrew Vasquez 
220c5722708SAndrew Vasquez static int
221*7b867cf7SAnirban Chakraborty qla2xxx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint16_t *ram,
222*7b867cf7SAnirban Chakraborty     uint16_t ram_words, void **nxt)
223c5722708SAndrew Vasquez {
224c5722708SAndrew Vasquez 	int rval;
225c5722708SAndrew Vasquez 	uint32_t cnt, stat, timer, words, idx;
226c5722708SAndrew Vasquez 	uint16_t mb0;
227c5722708SAndrew Vasquez 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
228c5722708SAndrew Vasquez 	dma_addr_t dump_dma = ha->gid_list_dma;
229c5722708SAndrew Vasquez 	uint16_t *dump = (uint16_t *)ha->gid_list;
230c5722708SAndrew Vasquez 
231c5722708SAndrew Vasquez 	rval = QLA_SUCCESS;
232c5722708SAndrew Vasquez 	mb0 = 0;
233c5722708SAndrew Vasquez 
234c5722708SAndrew Vasquez 	WRT_MAILBOX_REG(ha, reg, 0, MBC_DUMP_RISC_RAM_EXTENDED);
235c5722708SAndrew Vasquez 	clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
236c5722708SAndrew Vasquez 
237c5722708SAndrew Vasquez 	words = GID_LIST_SIZE / 2;
238c5722708SAndrew Vasquez 	for (cnt = 0; cnt < ram_words && rval == QLA_SUCCESS;
239c5722708SAndrew Vasquez 	    cnt += words, addr += words) {
240c5722708SAndrew Vasquez 		if (cnt + words > ram_words)
241c5722708SAndrew Vasquez 			words = ram_words - cnt;
242c5722708SAndrew Vasquez 
243c5722708SAndrew Vasquez 		WRT_MAILBOX_REG(ha, reg, 1, LSW(addr));
244c5722708SAndrew Vasquez 		WRT_MAILBOX_REG(ha, reg, 8, MSW(addr));
245c5722708SAndrew Vasquez 
246c5722708SAndrew Vasquez 		WRT_MAILBOX_REG(ha, reg, 2, MSW(dump_dma));
247c5722708SAndrew Vasquez 		WRT_MAILBOX_REG(ha, reg, 3, LSW(dump_dma));
248c5722708SAndrew Vasquez 		WRT_MAILBOX_REG(ha, reg, 6, MSW(MSD(dump_dma)));
249c5722708SAndrew Vasquez 		WRT_MAILBOX_REG(ha, reg, 7, LSW(MSD(dump_dma)));
250c5722708SAndrew Vasquez 
251c5722708SAndrew Vasquez 		WRT_MAILBOX_REG(ha, reg, 4, words);
252c5722708SAndrew Vasquez 		WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
253c5722708SAndrew Vasquez 
254c5722708SAndrew Vasquez 		for (timer = 6000000; timer; timer--) {
255c5722708SAndrew Vasquez 			/* Check for pending interrupts. */
256c5722708SAndrew Vasquez 			stat = RD_REG_DWORD(&reg->u.isp2300.host_status);
257c5722708SAndrew Vasquez 			if (stat & HSR_RISC_INT) {
258c5722708SAndrew Vasquez 				stat &= 0xff;
259c5722708SAndrew Vasquez 
260c5722708SAndrew Vasquez 				if (stat == 0x1 || stat == 0x2) {
261c5722708SAndrew Vasquez 					set_bit(MBX_INTERRUPT,
262c5722708SAndrew Vasquez 					    &ha->mbx_cmd_flags);
263c5722708SAndrew Vasquez 
264c5722708SAndrew Vasquez 					mb0 = RD_MAILBOX_REG(ha, reg, 0);
265c5722708SAndrew Vasquez 
266c5722708SAndrew Vasquez 					/* Release mailbox registers. */
267c5722708SAndrew Vasquez 					WRT_REG_WORD(&reg->semaphore, 0);
268c5722708SAndrew Vasquez 					WRT_REG_WORD(&reg->hccr,
269c5722708SAndrew Vasquez 					    HCCR_CLR_RISC_INT);
270c5722708SAndrew Vasquez 					RD_REG_WORD(&reg->hccr);
271c5722708SAndrew Vasquez 					break;
272c5722708SAndrew Vasquez 				} else if (stat == 0x10 || stat == 0x11) {
273c5722708SAndrew Vasquez 					set_bit(MBX_INTERRUPT,
274c5722708SAndrew Vasquez 					    &ha->mbx_cmd_flags);
275c5722708SAndrew Vasquez 
276c5722708SAndrew Vasquez 					mb0 = RD_MAILBOX_REG(ha, reg, 0);
277c5722708SAndrew Vasquez 
278c5722708SAndrew Vasquez 					WRT_REG_WORD(&reg->hccr,
279c5722708SAndrew Vasquez 					    HCCR_CLR_RISC_INT);
280c5722708SAndrew Vasquez 					RD_REG_WORD(&reg->hccr);
281c5722708SAndrew Vasquez 					break;
282c5722708SAndrew Vasquez 				}
283c5722708SAndrew Vasquez 
284c5722708SAndrew Vasquez 				/* clear this intr; it wasn't a mailbox intr */
285c5722708SAndrew Vasquez 				WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
286c5722708SAndrew Vasquez 				RD_REG_WORD(&reg->hccr);
287c5722708SAndrew Vasquez 			}
288c5722708SAndrew Vasquez 			udelay(5);
289c5722708SAndrew Vasquez 		}
290c5722708SAndrew Vasquez 
291c5722708SAndrew Vasquez 		if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
292c5722708SAndrew Vasquez 			rval = mb0 & MBS_MASK;
293c5722708SAndrew Vasquez 			for (idx = 0; idx < words; idx++)
294c5722708SAndrew Vasquez 				ram[cnt + idx] = swab16(dump[idx]);
295c5722708SAndrew Vasquez 		} else {
296c5722708SAndrew Vasquez 			rval = QLA_FUNCTION_FAILED;
297c5722708SAndrew Vasquez 		}
298c5722708SAndrew Vasquez 	}
299c5722708SAndrew Vasquez 
300c5722708SAndrew Vasquez 	*nxt = rval == QLA_SUCCESS ? &ram[cnt]: NULL;
301c5722708SAndrew Vasquez 	return rval;
302c5722708SAndrew Vasquez }
303c5722708SAndrew Vasquez 
304c81d04c9SAndrew Vasquez static inline void
305c81d04c9SAndrew Vasquez qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count,
306c81d04c9SAndrew Vasquez     uint16_t *buf)
307c81d04c9SAndrew Vasquez {
308c81d04c9SAndrew Vasquez 	uint16_t __iomem *dmp_reg = &reg->u.isp2300.fb_cmd;
309c81d04c9SAndrew Vasquez 
310c81d04c9SAndrew Vasquez 	while (count--)
311c81d04c9SAndrew Vasquez 		*buf++ = htons(RD_REG_WORD(dmp_reg++));
312c81d04c9SAndrew Vasquez }
313c81d04c9SAndrew Vasquez 
3141da177e4SLinus Torvalds /**
3151da177e4SLinus Torvalds  * qla2300_fw_dump() - Dumps binary data from the 2300 firmware.
3161da177e4SLinus Torvalds  * @ha: HA context
3171da177e4SLinus Torvalds  * @hardware_locked: Called with the hardware_lock
3181da177e4SLinus Torvalds  */
3191da177e4SLinus Torvalds void
320*7b867cf7SAnirban Chakraborty qla2300_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
3211da177e4SLinus Torvalds {
3221da177e4SLinus Torvalds 	int		rval;
323c5722708SAndrew Vasquez 	uint32_t	cnt;
324*7b867cf7SAnirban Chakraborty 	struct qla_hw_data *ha = vha->hw;
3253d71644cSAndrew Vasquez 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
3261da177e4SLinus Torvalds 	uint16_t __iomem *dmp_reg;
3271da177e4SLinus Torvalds 	unsigned long	flags;
3281da177e4SLinus Torvalds 	struct qla2300_fw_dump	*fw;
329c5722708SAndrew Vasquez 	void		*nxt;
3301da177e4SLinus Torvalds 
3311da177e4SLinus Torvalds 	flags = 0;
3321da177e4SLinus Torvalds 
3331da177e4SLinus Torvalds 	if (!hardware_locked)
3341da177e4SLinus Torvalds 		spin_lock_irqsave(&ha->hardware_lock, flags);
3351da177e4SLinus Torvalds 
336d4e3e04dSAndrew Vasquez 	if (!ha->fw_dump) {
3371da177e4SLinus Torvalds 		qla_printk(KERN_WARNING, ha,
338d4e3e04dSAndrew Vasquez 		    "No buffer available for dump!!!\n");
3391da177e4SLinus Torvalds 		goto qla2300_fw_dump_failed;
3401da177e4SLinus Torvalds 	}
3411da177e4SLinus Torvalds 
342d4e3e04dSAndrew Vasquez 	if (ha->fw_dumped) {
3431da177e4SLinus Torvalds 		qla_printk(KERN_WARNING, ha,
344d4e3e04dSAndrew Vasquez 		    "Firmware has been previously dumped (%p) -- ignoring "
345d4e3e04dSAndrew Vasquez 		    "request...\n", ha->fw_dump);
3461da177e4SLinus Torvalds 		goto qla2300_fw_dump_failed;
3471da177e4SLinus Torvalds 	}
348a7a167bfSAndrew Vasquez 	fw = &ha->fw_dump->isp.isp23;
349a7a167bfSAndrew Vasquez 	qla2xxx_prep_dump(ha, ha->fw_dump);
3501da177e4SLinus Torvalds 
3511da177e4SLinus Torvalds 	rval = QLA_SUCCESS;
352a7a167bfSAndrew Vasquez 	fw->hccr = htons(RD_REG_WORD(&reg->hccr));
3531da177e4SLinus Torvalds 
3541da177e4SLinus Torvalds 	/* Pause RISC. */
3551da177e4SLinus Torvalds 	WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
3561da177e4SLinus Torvalds 	if (IS_QLA2300(ha)) {
3571da177e4SLinus Torvalds 		for (cnt = 30000;
3581da177e4SLinus Torvalds 		    (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
3591da177e4SLinus Torvalds 			rval == QLA_SUCCESS; cnt--) {
3601da177e4SLinus Torvalds 			if (cnt)
3611da177e4SLinus Torvalds 				udelay(100);
3621da177e4SLinus Torvalds 			else
3631da177e4SLinus Torvalds 				rval = QLA_FUNCTION_TIMEOUT;
3641da177e4SLinus Torvalds 		}
3651da177e4SLinus Torvalds 	} else {
3661da177e4SLinus Torvalds 		RD_REG_WORD(&reg->hccr);		/* PCI Posting. */
3671da177e4SLinus Torvalds 		udelay(10);
3681da177e4SLinus Torvalds 	}
3691da177e4SLinus Torvalds 
3701da177e4SLinus Torvalds 	if (rval == QLA_SUCCESS) {
371c81d04c9SAndrew Vasquez 		dmp_reg = &reg->flash_address;
3721da177e4SLinus Torvalds 		for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
373a7a167bfSAndrew Vasquez 			fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
3741da177e4SLinus Torvalds 
375c81d04c9SAndrew Vasquez 		dmp_reg = &reg->u.isp2300.req_q_in;
3761da177e4SLinus Torvalds 		for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++)
377a7a167bfSAndrew Vasquez 			fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
3781da177e4SLinus Torvalds 
379c81d04c9SAndrew Vasquez 		dmp_reg = &reg->u.isp2300.mailbox0;
3801da177e4SLinus Torvalds 		for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
381a7a167bfSAndrew Vasquez 			fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
3821da177e4SLinus Torvalds 
3831da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, 0x40);
384c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 32, fw->resp_dma_reg);
3851da177e4SLinus Torvalds 
3861da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, 0x50);
387c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 48, fw->dma_reg);
3881da177e4SLinus Torvalds 
3891da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, 0x00);
390c81d04c9SAndrew Vasquez 		dmp_reg = &reg->risc_hw;
3911da177e4SLinus Torvalds 		for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
392a7a167bfSAndrew Vasquez 			fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
3931da177e4SLinus Torvalds 
3941da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2000);
395c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
3961da177e4SLinus Torvalds 
3971da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2200);
398c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
3991da177e4SLinus Torvalds 
4001da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2400);
401c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
4021da177e4SLinus Torvalds 
4031da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2600);
404c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
4051da177e4SLinus Torvalds 
4061da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2800);
407c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
4081da177e4SLinus Torvalds 
4091da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2A00);
410c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
4111da177e4SLinus Torvalds 
4121da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2C00);
413c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
4141da177e4SLinus Torvalds 
4151da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2E00);
416c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
4171da177e4SLinus Torvalds 
4181da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, 0x10);
419c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 64, fw->frame_buf_hdw_reg);
4201da177e4SLinus Torvalds 
4211da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, 0x20);
422c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, 0x30);
425c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
4261da177e4SLinus Torvalds 
4271da177e4SLinus Torvalds 		/* Reset RISC. */
4281da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
4291da177e4SLinus Torvalds 		for (cnt = 0; cnt < 30000; cnt++) {
4301da177e4SLinus Torvalds 			if ((RD_REG_WORD(&reg->ctrl_status) &
4311da177e4SLinus Torvalds 			    CSR_ISP_SOFT_RESET) == 0)
4321da177e4SLinus Torvalds 				break;
4331da177e4SLinus Torvalds 
4341da177e4SLinus Torvalds 			udelay(10);
4351da177e4SLinus Torvalds 		}
4361da177e4SLinus Torvalds 	}
4371da177e4SLinus Torvalds 
4381da177e4SLinus Torvalds 	if (!IS_QLA2300(ha)) {
4391da177e4SLinus Torvalds 		for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 &&
4401da177e4SLinus Torvalds 		    rval == QLA_SUCCESS; cnt--) {
4411da177e4SLinus Torvalds 			if (cnt)
4421da177e4SLinus Torvalds 				udelay(100);
4431da177e4SLinus Torvalds 			else
4441da177e4SLinus Torvalds 				rval = QLA_FUNCTION_TIMEOUT;
4451da177e4SLinus Torvalds 		}
4461da177e4SLinus Torvalds 	}
4471da177e4SLinus Torvalds 
4481da177e4SLinus Torvalds 	/* Get RISC SRAM. */
449c5722708SAndrew Vasquez 	if (rval == QLA_SUCCESS)
450c5722708SAndrew Vasquez 		rval = qla2xxx_dump_ram(ha, 0x800, fw->risc_ram,
451c5722708SAndrew Vasquez 		    sizeof(fw->risc_ram) / 2, &nxt);
4521da177e4SLinus Torvalds 
4531da177e4SLinus Torvalds 	/* Get stack SRAM. */
454c5722708SAndrew Vasquez 	if (rval == QLA_SUCCESS)
455c5722708SAndrew Vasquez 		rval = qla2xxx_dump_ram(ha, 0x10000, fw->stack_ram,
456c5722708SAndrew Vasquez 		    sizeof(fw->stack_ram) / 2, &nxt);
4571da177e4SLinus Torvalds 
4581da177e4SLinus Torvalds 	/* Get data SRAM. */
459c5722708SAndrew Vasquez 	if (rval == QLA_SUCCESS)
460c5722708SAndrew Vasquez 		rval = qla2xxx_dump_ram(ha, 0x11000, fw->data_ram,
461c5722708SAndrew Vasquez 		    ha->fw_memory_size - 0x11000 + 1, &nxt);
4621da177e4SLinus Torvalds 
463a7a167bfSAndrew Vasquez 	if (rval == QLA_SUCCESS)
464*7b867cf7SAnirban Chakraborty 		qla2xxx_copy_queues(vha, nxt);
465a7a167bfSAndrew Vasquez 
4661da177e4SLinus Torvalds 	if (rval != QLA_SUCCESS) {
4671da177e4SLinus Torvalds 		qla_printk(KERN_WARNING, ha,
4681da177e4SLinus Torvalds 		    "Failed to dump firmware (%x)!!!\n", rval);
469d4e3e04dSAndrew Vasquez 		ha->fw_dumped = 0;
4701da177e4SLinus Torvalds 
4711da177e4SLinus Torvalds 	} else {
4721da177e4SLinus Torvalds 		qla_printk(KERN_INFO, ha,
4731da177e4SLinus Torvalds 		    "Firmware dump saved to temp buffer (%ld/%p).\n",
474*7b867cf7SAnirban Chakraborty 		    vha->host_no, ha->fw_dump);
475d4e3e04dSAndrew Vasquez 		ha->fw_dumped = 1;
4761da177e4SLinus Torvalds 	}
4771da177e4SLinus Torvalds 
4781da177e4SLinus Torvalds qla2300_fw_dump_failed:
4791da177e4SLinus Torvalds 	if (!hardware_locked)
4801da177e4SLinus Torvalds 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
4811da177e4SLinus Torvalds }
4821da177e4SLinus Torvalds 
4831da177e4SLinus Torvalds /**
4841da177e4SLinus Torvalds  * qla2100_fw_dump() - Dumps binary data from the 2100/2200 firmware.
4851da177e4SLinus Torvalds  * @ha: HA context
4861da177e4SLinus Torvalds  * @hardware_locked: Called with the hardware_lock
4871da177e4SLinus Torvalds  */
4881da177e4SLinus Torvalds void
489*7b867cf7SAnirban Chakraborty qla2100_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
4901da177e4SLinus Torvalds {
4911da177e4SLinus Torvalds 	int		rval;
4921da177e4SLinus Torvalds 	uint32_t	cnt, timer;
4931da177e4SLinus Torvalds 	uint16_t	risc_address;
4941da177e4SLinus Torvalds 	uint16_t	mb0, mb2;
495*7b867cf7SAnirban Chakraborty 	struct qla_hw_data *ha = vha->hw;
4963d71644cSAndrew Vasquez 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
4971da177e4SLinus Torvalds 	uint16_t __iomem *dmp_reg;
4981da177e4SLinus Torvalds 	unsigned long	flags;
4991da177e4SLinus Torvalds 	struct qla2100_fw_dump	*fw;
5001da177e4SLinus Torvalds 
5011da177e4SLinus Torvalds 	risc_address = 0;
5021da177e4SLinus Torvalds 	mb0 = mb2 = 0;
5031da177e4SLinus Torvalds 	flags = 0;
5041da177e4SLinus Torvalds 
5051da177e4SLinus Torvalds 	if (!hardware_locked)
5061da177e4SLinus Torvalds 		spin_lock_irqsave(&ha->hardware_lock, flags);
5071da177e4SLinus Torvalds 
508d4e3e04dSAndrew Vasquez 	if (!ha->fw_dump) {
5091da177e4SLinus Torvalds 		qla_printk(KERN_WARNING, ha,
510d4e3e04dSAndrew Vasquez 		    "No buffer available for dump!!!\n");
5111da177e4SLinus Torvalds 		goto qla2100_fw_dump_failed;
5121da177e4SLinus Torvalds 	}
5131da177e4SLinus Torvalds 
514d4e3e04dSAndrew Vasquez 	if (ha->fw_dumped) {
5151da177e4SLinus Torvalds 		qla_printk(KERN_WARNING, ha,
516d4e3e04dSAndrew Vasquez 		    "Firmware has been previously dumped (%p) -- ignoring "
517d4e3e04dSAndrew Vasquez 		    "request...\n", ha->fw_dump);
5181da177e4SLinus Torvalds 		goto qla2100_fw_dump_failed;
5191da177e4SLinus Torvalds 	}
520a7a167bfSAndrew Vasquez 	fw = &ha->fw_dump->isp.isp21;
521a7a167bfSAndrew Vasquez 	qla2xxx_prep_dump(ha, ha->fw_dump);
5221da177e4SLinus Torvalds 
5231da177e4SLinus Torvalds 	rval = QLA_SUCCESS;
524a7a167bfSAndrew Vasquez 	fw->hccr = htons(RD_REG_WORD(&reg->hccr));
5251da177e4SLinus Torvalds 
5261da177e4SLinus Torvalds 	/* Pause RISC. */
5271da177e4SLinus Torvalds 	WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
5281da177e4SLinus Torvalds 	for (cnt = 30000; (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
5291da177e4SLinus Torvalds 	    rval == QLA_SUCCESS; cnt--) {
5301da177e4SLinus Torvalds 		if (cnt)
5311da177e4SLinus Torvalds 			udelay(100);
5321da177e4SLinus Torvalds 		else
5331da177e4SLinus Torvalds 			rval = QLA_FUNCTION_TIMEOUT;
5341da177e4SLinus Torvalds 	}
5351da177e4SLinus Torvalds 	if (rval == QLA_SUCCESS) {
536c81d04c9SAndrew Vasquez 		dmp_reg = &reg->flash_address;
5371da177e4SLinus Torvalds 		for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++)
538a7a167bfSAndrew Vasquez 			fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
5391da177e4SLinus Torvalds 
540c81d04c9SAndrew Vasquez 		dmp_reg = &reg->u.isp2100.mailbox0;
5411da177e4SLinus Torvalds 		for (cnt = 0; cnt < ha->mbx_count; cnt++) {
542c81d04c9SAndrew Vasquez 			if (cnt == 8)
543c81d04c9SAndrew Vasquez 				dmp_reg = &reg->u_end.isp2200.mailbox8;
544c81d04c9SAndrew Vasquez 
545a7a167bfSAndrew Vasquez 			fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
5461da177e4SLinus Torvalds 		}
5471da177e4SLinus Torvalds 
548c81d04c9SAndrew Vasquez 		dmp_reg = &reg->u.isp2100.unused_2[0];
5491da177e4SLinus Torvalds 		for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++)
550a7a167bfSAndrew Vasquez 			fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
5511da177e4SLinus Torvalds 
5521da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, 0x00);
553c81d04c9SAndrew Vasquez 		dmp_reg = &reg->risc_hw;
5541da177e4SLinus Torvalds 		for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++)
555a7a167bfSAndrew Vasquez 			fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++));
5561da177e4SLinus Torvalds 
5571da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2000);
558c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp0_reg);
5591da177e4SLinus Torvalds 
5601da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2100);
561c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp1_reg);
5621da177e4SLinus Torvalds 
5631da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2200);
564c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp2_reg);
5651da177e4SLinus Torvalds 
5661da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2300);
567c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp3_reg);
5681da177e4SLinus Torvalds 
5691da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2400);
570c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp4_reg);
5711da177e4SLinus Torvalds 
5721da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2500);
573c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp5_reg);
5741da177e4SLinus Torvalds 
5751da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2600);
576c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp6_reg);
5771da177e4SLinus Torvalds 
5781da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->pcr, 0x2700);
579c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->risc_gp7_reg);
5801da177e4SLinus Torvalds 
5811da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, 0x10);
582c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 16, fw->frame_buf_hdw_reg);
5831da177e4SLinus Torvalds 
5841da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, 0x20);
585c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 64, fw->fpm_b0_reg);
5861da177e4SLinus Torvalds 
5871da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, 0x30);
588c81d04c9SAndrew Vasquez 		qla2xxx_read_window(reg, 64, fw->fpm_b1_reg);
5891da177e4SLinus Torvalds 
5901da177e4SLinus Torvalds 		/* Reset the ISP. */
5911da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->ctrl_status, CSR_ISP_SOFT_RESET);
5921da177e4SLinus Torvalds 	}
5931da177e4SLinus Torvalds 
5941da177e4SLinus Torvalds 	for (cnt = 30000; RD_MAILBOX_REG(ha, reg, 0) != 0 &&
5951da177e4SLinus Torvalds 	    rval == QLA_SUCCESS; cnt--) {
5961da177e4SLinus Torvalds 		if (cnt)
5971da177e4SLinus Torvalds 			udelay(100);
5981da177e4SLinus Torvalds 		else
5991da177e4SLinus Torvalds 			rval = QLA_FUNCTION_TIMEOUT;
6001da177e4SLinus Torvalds 	}
6011da177e4SLinus Torvalds 
6021da177e4SLinus Torvalds 	/* Pause RISC. */
6031da177e4SLinus Torvalds 	if (rval == QLA_SUCCESS && (IS_QLA2200(ha) || (IS_QLA2100(ha) &&
6041da177e4SLinus Torvalds 	    (RD_REG_WORD(&reg->mctr) & (BIT_1 | BIT_0)) != 0))) {
6051da177e4SLinus Torvalds 
6061da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->hccr, HCCR_PAUSE_RISC);
6071da177e4SLinus Torvalds 		for (cnt = 30000;
6081da177e4SLinus Torvalds 		    (RD_REG_WORD(&reg->hccr) & HCCR_RISC_PAUSE) == 0 &&
6091da177e4SLinus Torvalds 		    rval == QLA_SUCCESS; cnt--) {
6101da177e4SLinus Torvalds 			if (cnt)
6111da177e4SLinus Torvalds 				udelay(100);
6121da177e4SLinus Torvalds 			else
6131da177e4SLinus Torvalds 				rval = QLA_FUNCTION_TIMEOUT;
6141da177e4SLinus Torvalds 		}
6151da177e4SLinus Torvalds 		if (rval == QLA_SUCCESS) {
6161da177e4SLinus Torvalds 			/* Set memory configuration and timing. */
6171da177e4SLinus Torvalds 			if (IS_QLA2100(ha))
6181da177e4SLinus Torvalds 				WRT_REG_WORD(&reg->mctr, 0xf1);
6191da177e4SLinus Torvalds 			else
6201da177e4SLinus Torvalds 				WRT_REG_WORD(&reg->mctr, 0xf2);
6211da177e4SLinus Torvalds 			RD_REG_WORD(&reg->mctr);	/* PCI Posting. */
6221da177e4SLinus Torvalds 
6231da177e4SLinus Torvalds 			/* Release RISC. */
6241da177e4SLinus Torvalds 			WRT_REG_WORD(&reg->hccr, HCCR_RELEASE_RISC);
6251da177e4SLinus Torvalds 		}
6261da177e4SLinus Torvalds 	}
6271da177e4SLinus Torvalds 
6281da177e4SLinus Torvalds 	if (rval == QLA_SUCCESS) {
6291da177e4SLinus Torvalds 		/* Get RISC SRAM. */
6301da177e4SLinus Torvalds 		risc_address = 0x1000;
6311da177e4SLinus Torvalds  		WRT_MAILBOX_REG(ha, reg, 0, MBC_READ_RAM_WORD);
6321da177e4SLinus Torvalds 		clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
6331da177e4SLinus Torvalds 	}
6341da177e4SLinus Torvalds 	for (cnt = 0; cnt < sizeof(fw->risc_ram) / 2 && rval == QLA_SUCCESS;
6351da177e4SLinus Torvalds 	    cnt++, risc_address++) {
6361da177e4SLinus Torvalds  		WRT_MAILBOX_REG(ha, reg, 1, risc_address);
6371da177e4SLinus Torvalds 		WRT_REG_WORD(&reg->hccr, HCCR_SET_HOST_INT);
6381da177e4SLinus Torvalds 
6391da177e4SLinus Torvalds 		for (timer = 6000000; timer != 0; timer--) {
6401da177e4SLinus Torvalds 			/* Check for pending interrupts. */
6411da177e4SLinus Torvalds 			if (RD_REG_WORD(&reg->istatus) & ISR_RISC_INT) {
6421da177e4SLinus Torvalds 				if (RD_REG_WORD(&reg->semaphore) & BIT_0) {
6431da177e4SLinus Torvalds 					set_bit(MBX_INTERRUPT,
6441da177e4SLinus Torvalds 					    &ha->mbx_cmd_flags);
6451da177e4SLinus Torvalds 
6461da177e4SLinus Torvalds 					mb0 = RD_MAILBOX_REG(ha, reg, 0);
6471da177e4SLinus Torvalds 					mb2 = RD_MAILBOX_REG(ha, reg, 2);
6481da177e4SLinus Torvalds 
6491da177e4SLinus Torvalds 					WRT_REG_WORD(&reg->semaphore, 0);
6501da177e4SLinus Torvalds 					WRT_REG_WORD(&reg->hccr,
6511da177e4SLinus Torvalds 					    HCCR_CLR_RISC_INT);
6521da177e4SLinus Torvalds 					RD_REG_WORD(&reg->hccr);
6531da177e4SLinus Torvalds 					break;
6541da177e4SLinus Torvalds 				}
6551da177e4SLinus Torvalds 				WRT_REG_WORD(&reg->hccr, HCCR_CLR_RISC_INT);
6561da177e4SLinus Torvalds 				RD_REG_WORD(&reg->hccr);
6571da177e4SLinus Torvalds 			}
6581da177e4SLinus Torvalds 			udelay(5);
6591da177e4SLinus Torvalds 		}
6601da177e4SLinus Torvalds 
6611da177e4SLinus Torvalds 		if (test_and_clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags)) {
6621da177e4SLinus Torvalds 			rval = mb0 & MBS_MASK;
663a7a167bfSAndrew Vasquez 			fw->risc_ram[cnt] = htons(mb2);
6641da177e4SLinus Torvalds 		} else {
6651da177e4SLinus Torvalds 			rval = QLA_FUNCTION_FAILED;
6661da177e4SLinus Torvalds 		}
6671da177e4SLinus Torvalds 	}
6681da177e4SLinus Torvalds 
669a7a167bfSAndrew Vasquez 	if (rval == QLA_SUCCESS)
670*7b867cf7SAnirban Chakraborty 		qla2xxx_copy_queues(vha, &fw->risc_ram[cnt]);
671a7a167bfSAndrew Vasquez 
6721da177e4SLinus Torvalds 	if (rval != QLA_SUCCESS) {
6731da177e4SLinus Torvalds 		qla_printk(KERN_WARNING, ha,
6741da177e4SLinus Torvalds 		    "Failed to dump firmware (%x)!!!\n", rval);
675d4e3e04dSAndrew Vasquez 		ha->fw_dumped = 0;
6761da177e4SLinus Torvalds 
6771da177e4SLinus Torvalds 	} else {
6781da177e4SLinus Torvalds 		qla_printk(KERN_INFO, ha,
6791da177e4SLinus Torvalds 		    "Firmware dump saved to temp buffer (%ld/%p).\n",
680*7b867cf7SAnirban Chakraborty 		    vha->host_no, ha->fw_dump);
681d4e3e04dSAndrew Vasquez 		ha->fw_dumped = 1;
6821da177e4SLinus Torvalds 	}
6831da177e4SLinus Torvalds 
6841da177e4SLinus Torvalds qla2100_fw_dump_failed:
6851da177e4SLinus Torvalds 	if (!hardware_locked)
6861da177e4SLinus Torvalds 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
6871da177e4SLinus Torvalds }
6881da177e4SLinus Torvalds 
6896d9b61edSAndrew Vasquez void
690*7b867cf7SAnirban Chakraborty qla24xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
6916d9b61edSAndrew Vasquez {
6926d9b61edSAndrew Vasquez 	int		rval;
693c3a2f0dfSAndrew Vasquez 	uint32_t	cnt;
6946d9b61edSAndrew Vasquez 	uint32_t	risc_address;
695*7b867cf7SAnirban Chakraborty 	struct qla_hw_data *ha = vha->hw;
6966d9b61edSAndrew Vasquez 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
6976d9b61edSAndrew Vasquez 	uint32_t __iomem *dmp_reg;
6986d9b61edSAndrew Vasquez 	uint32_t	*iter_reg;
6996d9b61edSAndrew Vasquez 	uint16_t __iomem *mbx_reg;
7006d9b61edSAndrew Vasquez 	unsigned long	flags;
7016d9b61edSAndrew Vasquez 	struct qla24xx_fw_dump *fw;
7026d9b61edSAndrew Vasquez 	uint32_t	ext_mem_cnt;
703c3a2f0dfSAndrew Vasquez 	void		*nxt;
7046d9b61edSAndrew Vasquez 
7056d9b61edSAndrew Vasquez 	risc_address = ext_mem_cnt = 0;
7066d9b61edSAndrew Vasquez 	flags = 0;
7076d9b61edSAndrew Vasquez 
7086d9b61edSAndrew Vasquez 	if (!hardware_locked)
7096d9b61edSAndrew Vasquez 		spin_lock_irqsave(&ha->hardware_lock, flags);
7106d9b61edSAndrew Vasquez 
711d4e3e04dSAndrew Vasquez 	if (!ha->fw_dump) {
7126d9b61edSAndrew Vasquez 		qla_printk(KERN_WARNING, ha,
7136d9b61edSAndrew Vasquez 		    "No buffer available for dump!!!\n");
7146d9b61edSAndrew Vasquez 		goto qla24xx_fw_dump_failed;
7156d9b61edSAndrew Vasquez 	}
7166d9b61edSAndrew Vasquez 
7176d9b61edSAndrew Vasquez 	if (ha->fw_dumped) {
7186d9b61edSAndrew Vasquez 		qla_printk(KERN_WARNING, ha,
7196d9b61edSAndrew Vasquez 		    "Firmware has been previously dumped (%p) -- ignoring "
720d4e3e04dSAndrew Vasquez 		    "request...\n", ha->fw_dump);
7216d9b61edSAndrew Vasquez 		goto qla24xx_fw_dump_failed;
7226d9b61edSAndrew Vasquez 	}
723a7a167bfSAndrew Vasquez 	fw = &ha->fw_dump->isp.isp24;
724a7a167bfSAndrew Vasquez 	qla2xxx_prep_dump(ha, ha->fw_dump);
7256d9b61edSAndrew Vasquez 
726a7a167bfSAndrew Vasquez 	fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
7276d9b61edSAndrew Vasquez 
7286d9b61edSAndrew Vasquez 	/* Pause RISC. */
729c81d04c9SAndrew Vasquez 	rval = qla24xx_pause_risc(reg);
730c81d04c9SAndrew Vasquez 	if (rval != QLA_SUCCESS)
731c81d04c9SAndrew Vasquez 		goto qla24xx_fw_dump_failed_0;
7326d9b61edSAndrew Vasquez 
7336d9b61edSAndrew Vasquez 	/* Host interface registers. */
734c81d04c9SAndrew Vasquez 	dmp_reg = &reg->flash_addr;
7356d9b61edSAndrew Vasquez 	for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
736a7a167bfSAndrew Vasquez 		fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
7376d9b61edSAndrew Vasquez 
738210d5350Sandrew.vasquez@qlogic.com 	/* Disable interrupts. */
739210d5350Sandrew.vasquez@qlogic.com 	WRT_REG_DWORD(&reg->ictrl, 0);
740210d5350Sandrew.vasquez@qlogic.com 	RD_REG_DWORD(&reg->ictrl);
741210d5350Sandrew.vasquez@qlogic.com 
742210d5350Sandrew.vasquez@qlogic.com 	/* Shadow registers. */
743210d5350Sandrew.vasquez@qlogic.com 	WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
744210d5350Sandrew.vasquez@qlogic.com 	RD_REG_DWORD(&reg->iobase_addr);
745c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
746c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
747210d5350Sandrew.vasquez@qlogic.com 
748c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
749c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
750210d5350Sandrew.vasquez@qlogic.com 
751c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
752c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
753210d5350Sandrew.vasquez@qlogic.com 
754c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
755c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
756210d5350Sandrew.vasquez@qlogic.com 
757c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
758c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
759210d5350Sandrew.vasquez@qlogic.com 
760c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
761c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
762210d5350Sandrew.vasquez@qlogic.com 
763c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
764c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
765210d5350Sandrew.vasquez@qlogic.com 
7666d9b61edSAndrew Vasquez 	/* Mailbox registers. */
767c3a2f0dfSAndrew Vasquez 	mbx_reg = &reg->mailbox0;
7686d9b61edSAndrew Vasquez 	for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
769a7a167bfSAndrew Vasquez 		fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
7706d9b61edSAndrew Vasquez 
7716d9b61edSAndrew Vasquez 	/* Transfer sequence registers. */
7726d9b61edSAndrew Vasquez 	iter_reg = fw->xseq_gp_reg;
773c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
774c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
775c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
776c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
777c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
778c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
779c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
780c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
7816d9b61edSAndrew Vasquez 
782c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xBFE0, 16, fw->xseq_0_reg);
783c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
7846d9b61edSAndrew Vasquez 
7856d9b61edSAndrew Vasquez 	/* Receive sequence registers. */
7866d9b61edSAndrew Vasquez 	iter_reg = fw->rseq_gp_reg;
787c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
788c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
789c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
790c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
791c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
792c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
793c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
794c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
7956d9b61edSAndrew Vasquez 
796c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xFFD0, 16, fw->rseq_0_reg);
797c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
798c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
7996d9b61edSAndrew Vasquez 
8006d9b61edSAndrew Vasquez 	/* Command DMA registers. */
801c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
8026d9b61edSAndrew Vasquez 
8036d9b61edSAndrew Vasquez 	/* Queues. */
8046d9b61edSAndrew Vasquez 	iter_reg = fw->req0_dma_reg;
805c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
806c3a2f0dfSAndrew Vasquez 	dmp_reg = &reg->iobase_q;
8076d9b61edSAndrew Vasquez 	for (cnt = 0; cnt < 7; cnt++)
808a7a167bfSAndrew Vasquez 		*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
8096d9b61edSAndrew Vasquez 
8106d9b61edSAndrew Vasquez 	iter_reg = fw->resp0_dma_reg;
811c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
812c3a2f0dfSAndrew Vasquez 	dmp_reg = &reg->iobase_q;
8136d9b61edSAndrew Vasquez 	for (cnt = 0; cnt < 7; cnt++)
814a7a167bfSAndrew Vasquez 		*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
8156d9b61edSAndrew Vasquez 
8166d9b61edSAndrew Vasquez 	iter_reg = fw->req1_dma_reg;
817c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
818c3a2f0dfSAndrew Vasquez 	dmp_reg = &reg->iobase_q;
8196d9b61edSAndrew Vasquez 	for (cnt = 0; cnt < 7; cnt++)
820a7a167bfSAndrew Vasquez 		*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
8216d9b61edSAndrew Vasquez 
8226d9b61edSAndrew Vasquez 	/* Transmit DMA registers. */
8236d9b61edSAndrew Vasquez 	iter_reg = fw->xmt0_dma_reg;
824c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
825c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7610, 16, iter_reg);
8266d9b61edSAndrew Vasquez 
8276d9b61edSAndrew Vasquez 	iter_reg = fw->xmt1_dma_reg;
828c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
829c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7630, 16, iter_reg);
8306d9b61edSAndrew Vasquez 
8316d9b61edSAndrew Vasquez 	iter_reg = fw->xmt2_dma_reg;
832c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
833c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7650, 16, iter_reg);
8346d9b61edSAndrew Vasquez 
8356d9b61edSAndrew Vasquez 	iter_reg = fw->xmt3_dma_reg;
836c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
837c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7670, 16, iter_reg);
8386d9b61edSAndrew Vasquez 
8396d9b61edSAndrew Vasquez 	iter_reg = fw->xmt4_dma_reg;
840c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
841c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7690, 16, iter_reg);
8426d9b61edSAndrew Vasquez 
843c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
8446d9b61edSAndrew Vasquez 
8456d9b61edSAndrew Vasquez 	/* Receive DMA registers. */
8466d9b61edSAndrew Vasquez 	iter_reg = fw->rcvt0_data_dma_reg;
847c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
848c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7710, 16, iter_reg);
8496d9b61edSAndrew Vasquez 
8506d9b61edSAndrew Vasquez 	iter_reg = fw->rcvt1_data_dma_reg;
851c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
852c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7730, 16, iter_reg);
8536d9b61edSAndrew Vasquez 
8546d9b61edSAndrew Vasquez 	/* RISC registers. */
8556d9b61edSAndrew Vasquez 	iter_reg = fw->risc_gp_reg;
856c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
857c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
858c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
859c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
860c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
861c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
862c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
863c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
8646d9b61edSAndrew Vasquez 
8656d9b61edSAndrew Vasquez 	/* Local memory controller registers. */
8666d9b61edSAndrew Vasquez 	iter_reg = fw->lmc_reg;
867c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
868c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
869c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
870c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
871c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
872c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
873c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x3060, 16, iter_reg);
8746d9b61edSAndrew Vasquez 
8756d9b61edSAndrew Vasquez 	/* Fibre Protocol Module registers. */
8766d9b61edSAndrew Vasquez 	iter_reg = fw->fpm_hdw_reg;
877c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
878c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
879c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
880c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
881c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
882c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
883c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
884c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
885c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
886c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
887c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
888c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
8896d9b61edSAndrew Vasquez 
8906d9b61edSAndrew Vasquez 	/* Frame Buffer registers. */
8916d9b61edSAndrew Vasquez 	iter_reg = fw->fb_hdw_reg;
892c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
893c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
894c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
895c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
896c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
897c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
898c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
899c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
900c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
901c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
902c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
9036d9b61edSAndrew Vasquez 
904c81d04c9SAndrew Vasquez 	rval = qla24xx_soft_reset(ha);
905c81d04c9SAndrew Vasquez 	if (rval != QLA_SUCCESS)
906c81d04c9SAndrew Vasquez 		goto qla24xx_fw_dump_failed_0;
9076d9b61edSAndrew Vasquez 
908c81d04c9SAndrew Vasquez 	rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
909c5722708SAndrew Vasquez 	    &nxt);
910c81d04c9SAndrew Vasquez 	if (rval != QLA_SUCCESS)
911c81d04c9SAndrew Vasquez 		goto qla24xx_fw_dump_failed_0;
9126d9b61edSAndrew Vasquez 
913*7b867cf7SAnirban Chakraborty 	nxt = qla2xxx_copy_queues(vha, nxt);
914a7a167bfSAndrew Vasquez 	if (ha->eft)
915c3a2f0dfSAndrew Vasquez 		memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
916a7a167bfSAndrew Vasquez 
917c81d04c9SAndrew Vasquez qla24xx_fw_dump_failed_0:
9186d9b61edSAndrew Vasquez 	if (rval != QLA_SUCCESS) {
9196d9b61edSAndrew Vasquez 		qla_printk(KERN_WARNING, ha,
9206d9b61edSAndrew Vasquez 		    "Failed to dump firmware (%x)!!!\n", rval);
9216d9b61edSAndrew Vasquez 		ha->fw_dumped = 0;
9226d9b61edSAndrew Vasquez 
9236d9b61edSAndrew Vasquez 	} else {
9246d9b61edSAndrew Vasquez 		qla_printk(KERN_INFO, ha,
9256d9b61edSAndrew Vasquez 		    "Firmware dump saved to temp buffer (%ld/%p).\n",
926*7b867cf7SAnirban Chakraborty 		    vha->host_no, ha->fw_dump);
9276d9b61edSAndrew Vasquez 		ha->fw_dumped = 1;
9286d9b61edSAndrew Vasquez 	}
9296d9b61edSAndrew Vasquez 
9306d9b61edSAndrew Vasquez qla24xx_fw_dump_failed:
9316d9b61edSAndrew Vasquez 	if (!hardware_locked)
9326d9b61edSAndrew Vasquez 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
9336d9b61edSAndrew Vasquez }
9346d9b61edSAndrew Vasquez 
935c3a2f0dfSAndrew Vasquez void
936*7b867cf7SAnirban Chakraborty qla25xx_fw_dump(scsi_qla_host_t *vha, int hardware_locked)
937c3a2f0dfSAndrew Vasquez {
938c3a2f0dfSAndrew Vasquez 	int		rval;
939c3a2f0dfSAndrew Vasquez 	uint32_t	cnt;
940c3a2f0dfSAndrew Vasquez 	uint32_t	risc_address;
941*7b867cf7SAnirban Chakraborty 	struct qla_hw_data *ha = vha->hw;
942c3a2f0dfSAndrew Vasquez 	struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
943c3a2f0dfSAndrew Vasquez 	uint32_t __iomem *dmp_reg;
944c3a2f0dfSAndrew Vasquez 	uint32_t	*iter_reg;
945c3a2f0dfSAndrew Vasquez 	uint16_t __iomem *mbx_reg;
946c3a2f0dfSAndrew Vasquez 	unsigned long	flags;
947c3a2f0dfSAndrew Vasquez 	struct qla25xx_fw_dump *fw;
948c3a2f0dfSAndrew Vasquez 	uint32_t	ext_mem_cnt;
949c3a2f0dfSAndrew Vasquez 	void		*nxt;
950df613b96SAndrew Vasquez 	struct qla2xxx_fce_chain *fcec;
951c3a2f0dfSAndrew Vasquez 
952c3a2f0dfSAndrew Vasquez 	risc_address = ext_mem_cnt = 0;
953c3a2f0dfSAndrew Vasquez 	flags = 0;
954c3a2f0dfSAndrew Vasquez 
955c3a2f0dfSAndrew Vasquez 	if (!hardware_locked)
956c3a2f0dfSAndrew Vasquez 		spin_lock_irqsave(&ha->hardware_lock, flags);
957c3a2f0dfSAndrew Vasquez 
958c3a2f0dfSAndrew Vasquez 	if (!ha->fw_dump) {
959c3a2f0dfSAndrew Vasquez 		qla_printk(KERN_WARNING, ha,
960c3a2f0dfSAndrew Vasquez 		    "No buffer available for dump!!!\n");
961c3a2f0dfSAndrew Vasquez 		goto qla25xx_fw_dump_failed;
962c3a2f0dfSAndrew Vasquez 	}
963c3a2f0dfSAndrew Vasquez 
964c3a2f0dfSAndrew Vasquez 	if (ha->fw_dumped) {
965c3a2f0dfSAndrew Vasquez 		qla_printk(KERN_WARNING, ha,
966c3a2f0dfSAndrew Vasquez 		    "Firmware has been previously dumped (%p) -- ignoring "
967c3a2f0dfSAndrew Vasquez 		    "request...\n", ha->fw_dump);
968c3a2f0dfSAndrew Vasquez 		goto qla25xx_fw_dump_failed;
969c3a2f0dfSAndrew Vasquez 	}
970c3a2f0dfSAndrew Vasquez 	fw = &ha->fw_dump->isp.isp25;
971c3a2f0dfSAndrew Vasquez 	qla2xxx_prep_dump(ha, ha->fw_dump);
972b5836927SAndrew Vasquez 	ha->fw_dump->version = __constant_htonl(2);
973c3a2f0dfSAndrew Vasquez 
974c3a2f0dfSAndrew Vasquez 	fw->host_status = htonl(RD_REG_DWORD(&reg->host_status));
975c3a2f0dfSAndrew Vasquez 
976c3a2f0dfSAndrew Vasquez 	/* Pause RISC. */
977c81d04c9SAndrew Vasquez 	rval = qla24xx_pause_risc(reg);
978c81d04c9SAndrew Vasquez 	if (rval != QLA_SUCCESS)
979c81d04c9SAndrew Vasquez 		goto qla25xx_fw_dump_failed_0;
980c3a2f0dfSAndrew Vasquez 
981b5836927SAndrew Vasquez 	/* Host/Risc registers. */
982b5836927SAndrew Vasquez 	iter_reg = fw->host_risc_reg;
983b5836927SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg);
984b5836927SAndrew Vasquez 	qla24xx_read_window(reg, 0x7010, 16, iter_reg);
985b5836927SAndrew Vasquez 
986b5836927SAndrew Vasquez 	/* PCIe registers. */
987b5836927SAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_addr, 0x7C00);
988b5836927SAndrew Vasquez 	RD_REG_DWORD(&reg->iobase_addr);
989b5836927SAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_window, 0x01);
990b5836927SAndrew Vasquez 	dmp_reg = &reg->iobase_c4;
991b5836927SAndrew Vasquez 	fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++));
992b5836927SAndrew Vasquez 	fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++));
993b5836927SAndrew Vasquez 	fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg));
994b5836927SAndrew Vasquez 	fw->pcie_regs[3] = htonl(RD_REG_DWORD(&reg->iobase_window));
995b5836927SAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_window, 0x00);
996b5836927SAndrew Vasquez 	RD_REG_DWORD(&reg->iobase_window);
997b5836927SAndrew Vasquez 
998c3a2f0dfSAndrew Vasquez 	/* Host interface registers. */
999c81d04c9SAndrew Vasquez 	dmp_reg = &reg->flash_addr;
1000c3a2f0dfSAndrew Vasquez 	for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++)
1001c3a2f0dfSAndrew Vasquez 		fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++));
1002c3a2f0dfSAndrew Vasquez 
1003c3a2f0dfSAndrew Vasquez 	/* Disable interrupts. */
1004c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->ictrl, 0);
1005c3a2f0dfSAndrew Vasquez 	RD_REG_DWORD(&reg->ictrl);
1006c3a2f0dfSAndrew Vasquez 
1007c3a2f0dfSAndrew Vasquez 	/* Shadow registers. */
1008c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_addr, 0x0F70);
1009c3a2f0dfSAndrew Vasquez 	RD_REG_DWORD(&reg->iobase_addr);
1010c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0000000);
1011c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[0] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1012c3a2f0dfSAndrew Vasquez 
1013c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0100000);
1014c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[1] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1015c3a2f0dfSAndrew Vasquez 
1016c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0200000);
1017c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[2] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1018c3a2f0dfSAndrew Vasquez 
1019c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0300000);
1020c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[3] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1021c3a2f0dfSAndrew Vasquez 
1022c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0400000);
1023c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[4] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1024c3a2f0dfSAndrew Vasquez 
1025c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0500000);
1026c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[5] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1027c3a2f0dfSAndrew Vasquez 
1028c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0600000);
1029c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[6] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1030c3a2f0dfSAndrew Vasquez 
1031c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0700000);
1032c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[7] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1033c3a2f0dfSAndrew Vasquez 
1034c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0800000);
1035c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[8] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1036c3a2f0dfSAndrew Vasquez 
1037c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0900000);
1038c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[9] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1039c3a2f0dfSAndrew Vasquez 
1040c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_select, 0xB0A00000);
1041c3a2f0dfSAndrew Vasquez 	fw->shadow_reg[10] = htonl(RD_REG_DWORD(&reg->iobase_sdata));
1042c3a2f0dfSAndrew Vasquez 
1043c3a2f0dfSAndrew Vasquez 	/* RISC I/O register. */
1044c3a2f0dfSAndrew Vasquez 	WRT_REG_DWORD(&reg->iobase_addr, 0x0010);
1045c3a2f0dfSAndrew Vasquez 	fw->risc_io_reg = htonl(RD_REG_DWORD(&reg->iobase_window));
1046c3a2f0dfSAndrew Vasquez 
1047c3a2f0dfSAndrew Vasquez 	/* Mailbox registers. */
1048c3a2f0dfSAndrew Vasquez 	mbx_reg = &reg->mailbox0;
1049c3a2f0dfSAndrew Vasquez 	for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++)
1050c3a2f0dfSAndrew Vasquez 		fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++));
1051c3a2f0dfSAndrew Vasquez 
1052c3a2f0dfSAndrew Vasquez 	/* Transfer sequence registers. */
1053c3a2f0dfSAndrew Vasquez 	iter_reg = fw->xseq_gp_reg;
1054c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg);
1055c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg);
1056c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg);
1057c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg);
1058c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg);
1059c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg);
1060c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg);
1061c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xBF70, 16, iter_reg);
1062c3a2f0dfSAndrew Vasquez 
1063c3a2f0dfSAndrew Vasquez 	iter_reg = fw->xseq_0_reg;
1064c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg);
1065c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg);
1066c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xBFE0, 16, iter_reg);
1067c3a2f0dfSAndrew Vasquez 
1068c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg);
1069c3a2f0dfSAndrew Vasquez 
1070c3a2f0dfSAndrew Vasquez 	/* Receive sequence registers. */
1071c3a2f0dfSAndrew Vasquez 	iter_reg = fw->rseq_gp_reg;
1072c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg);
1073c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg);
1074c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg);
1075c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg);
1076c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg);
1077c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg);
1078c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg);
1079c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xFF70, 16, iter_reg);
1080c3a2f0dfSAndrew Vasquez 
1081c3a2f0dfSAndrew Vasquez 	iter_reg = fw->rseq_0_reg;
1082c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg);
1083c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xFFD0, 16, iter_reg);
1084c3a2f0dfSAndrew Vasquez 
1085c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg);
1086c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg);
1087c3a2f0dfSAndrew Vasquez 
1088c3a2f0dfSAndrew Vasquez 	/* Auxiliary sequence registers. */
1089c3a2f0dfSAndrew Vasquez 	iter_reg = fw->aseq_gp_reg;
1090c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg);
1091c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg);
1092c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg);
1093c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg);
1094c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg);
1095c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg);
1096c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg);
1097c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xB070, 16, iter_reg);
1098c3a2f0dfSAndrew Vasquez 
1099c3a2f0dfSAndrew Vasquez 	iter_reg = fw->aseq_0_reg;
1100c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg);
1101c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xB0D0, 16, iter_reg);
1102c3a2f0dfSAndrew Vasquez 
1103c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg);
1104c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg);
1105c3a2f0dfSAndrew Vasquez 
1106c3a2f0dfSAndrew Vasquez 	/* Command DMA registers. */
1107c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg);
1108c3a2f0dfSAndrew Vasquez 
1109c3a2f0dfSAndrew Vasquez 	/* Queues. */
1110c3a2f0dfSAndrew Vasquez 	iter_reg = fw->req0_dma_reg;
1111c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg);
1112c3a2f0dfSAndrew Vasquez 	dmp_reg = &reg->iobase_q;
1113c3a2f0dfSAndrew Vasquez 	for (cnt = 0; cnt < 7; cnt++)
1114c3a2f0dfSAndrew Vasquez 		*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1115c3a2f0dfSAndrew Vasquez 
1116c3a2f0dfSAndrew Vasquez 	iter_reg = fw->resp0_dma_reg;
1117c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg);
1118c3a2f0dfSAndrew Vasquez 	dmp_reg = &reg->iobase_q;
1119c3a2f0dfSAndrew Vasquez 	for (cnt = 0; cnt < 7; cnt++)
1120c3a2f0dfSAndrew Vasquez 		*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1121c3a2f0dfSAndrew Vasquez 
1122c3a2f0dfSAndrew Vasquez 	iter_reg = fw->req1_dma_reg;
1123c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg);
1124c3a2f0dfSAndrew Vasquez 	dmp_reg = &reg->iobase_q;
1125c3a2f0dfSAndrew Vasquez 	for (cnt = 0; cnt < 7; cnt++)
1126c3a2f0dfSAndrew Vasquez 		*iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++));
1127c3a2f0dfSAndrew Vasquez 
1128c3a2f0dfSAndrew Vasquez 	/* Transmit DMA registers. */
1129c3a2f0dfSAndrew Vasquez 	iter_reg = fw->xmt0_dma_reg;
1130c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg);
1131c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7610, 16, iter_reg);
1132c3a2f0dfSAndrew Vasquez 
1133c3a2f0dfSAndrew Vasquez 	iter_reg = fw->xmt1_dma_reg;
1134c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg);
1135c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7630, 16, iter_reg);
1136c3a2f0dfSAndrew Vasquez 
1137c3a2f0dfSAndrew Vasquez 	iter_reg = fw->xmt2_dma_reg;
1138c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg);
1139c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7650, 16, iter_reg);
1140c3a2f0dfSAndrew Vasquez 
1141c3a2f0dfSAndrew Vasquez 	iter_reg = fw->xmt3_dma_reg;
1142c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg);
1143c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7670, 16, iter_reg);
1144c3a2f0dfSAndrew Vasquez 
1145c3a2f0dfSAndrew Vasquez 	iter_reg = fw->xmt4_dma_reg;
1146c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg);
1147c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7690, 16, iter_reg);
1148c3a2f0dfSAndrew Vasquez 
1149c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg);
1150c3a2f0dfSAndrew Vasquez 
1151c3a2f0dfSAndrew Vasquez 	/* Receive DMA registers. */
1152c3a2f0dfSAndrew Vasquez 	iter_reg = fw->rcvt0_data_dma_reg;
1153c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg);
1154c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7710, 16, iter_reg);
1155c3a2f0dfSAndrew Vasquez 
1156c3a2f0dfSAndrew Vasquez 	iter_reg = fw->rcvt1_data_dma_reg;
1157c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg);
1158c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x7730, 16, iter_reg);
1159c3a2f0dfSAndrew Vasquez 
1160c3a2f0dfSAndrew Vasquez 	/* RISC registers. */
1161c3a2f0dfSAndrew Vasquez 	iter_reg = fw->risc_gp_reg;
1162c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg);
1163c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg);
1164c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg);
1165c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg);
1166c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg);
1167c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg);
1168c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg);
1169c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x0F70, 16, iter_reg);
1170c3a2f0dfSAndrew Vasquez 
1171c3a2f0dfSAndrew Vasquez 	/* Local memory controller registers. */
1172c3a2f0dfSAndrew Vasquez 	iter_reg = fw->lmc_reg;
1173c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg);
1174c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg);
1175c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg);
1176c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg);
1177c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg);
1178c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg);
1179c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg);
1180c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x3070, 16, iter_reg);
1181c3a2f0dfSAndrew Vasquez 
1182c3a2f0dfSAndrew Vasquez 	/* Fibre Protocol Module registers. */
1183c3a2f0dfSAndrew Vasquez 	iter_reg = fw->fpm_hdw_reg;
1184c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg);
1185c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg);
1186c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg);
1187c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg);
1188c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg);
1189c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg);
1190c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg);
1191c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg);
1192c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg);
1193c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg);
1194c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg);
1195c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x40B0, 16, iter_reg);
1196c3a2f0dfSAndrew Vasquez 
1197c3a2f0dfSAndrew Vasquez 	/* Frame Buffer registers. */
1198c3a2f0dfSAndrew Vasquez 	iter_reg = fw->fb_hdw_reg;
1199c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg);
1200c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg);
1201c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg);
1202c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg);
1203c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg);
1204c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg);
1205c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg);
1206c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg);
1207c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg);
1208c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg);
1209c81d04c9SAndrew Vasquez 	iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg);
1210c81d04c9SAndrew Vasquez 	qla24xx_read_window(reg, 0x6F00, 16, iter_reg);
1211c3a2f0dfSAndrew Vasquez 
1212c81d04c9SAndrew Vasquez 	rval = qla24xx_soft_reset(ha);
1213c81d04c9SAndrew Vasquez 	if (rval != QLA_SUCCESS)
1214c81d04c9SAndrew Vasquez 		goto qla25xx_fw_dump_failed_0;
1215c3a2f0dfSAndrew Vasquez 
1216c81d04c9SAndrew Vasquez 	rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram),
1217c5722708SAndrew Vasquez 	    &nxt);
1218c81d04c9SAndrew Vasquez 	if (rval != QLA_SUCCESS)
1219c81d04c9SAndrew Vasquez 		goto qla25xx_fw_dump_failed_0;
1220c3a2f0dfSAndrew Vasquez 
1221df613b96SAndrew Vasquez 	/* Fibre Channel Trace Buffer. */
1222*7b867cf7SAnirban Chakraborty 	nxt = qla2xxx_copy_queues(vha, nxt);
1223c3a2f0dfSAndrew Vasquez 	if (ha->eft)
1224c3a2f0dfSAndrew Vasquez 		memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size));
1225c3a2f0dfSAndrew Vasquez 
1226df613b96SAndrew Vasquez 	/* Fibre Channel Event Buffer. */
1227df613b96SAndrew Vasquez 	if (!ha->fce)
1228df613b96SAndrew Vasquez 		goto qla25xx_fw_dump_failed_0;
1229df613b96SAndrew Vasquez 
1230df613b96SAndrew Vasquez 	ha->fw_dump->version |= __constant_htonl(DUMP_CHAIN_VARIANT);
1231df613b96SAndrew Vasquez 
1232df613b96SAndrew Vasquez 	fcec = nxt + ntohl(ha->fw_dump->eft_size);
1233df613b96SAndrew Vasquez 	fcec->type = __constant_htonl(DUMP_CHAIN_FCE | DUMP_CHAIN_LAST);
1234df613b96SAndrew Vasquez 	fcec->chain_size = htonl(sizeof(struct qla2xxx_fce_chain) +
1235df613b96SAndrew Vasquez 	    fce_calc_size(ha->fce_bufs));
1236df613b96SAndrew Vasquez 	fcec->size = htonl(fce_calc_size(ha->fce_bufs));
1237df613b96SAndrew Vasquez 	fcec->addr_l = htonl(LSD(ha->fce_dma));
1238df613b96SAndrew Vasquez 	fcec->addr_h = htonl(MSD(ha->fce_dma));
1239df613b96SAndrew Vasquez 
1240df613b96SAndrew Vasquez 	iter_reg = fcec->eregs;
1241df613b96SAndrew Vasquez 	for (cnt = 0; cnt < 8; cnt++)
1242df613b96SAndrew Vasquez 		*iter_reg++ = htonl(ha->fce_mb[cnt]);
1243df613b96SAndrew Vasquez 
1244df613b96SAndrew Vasquez 	memcpy(iter_reg, ha->fce, ntohl(fcec->size));
1245df613b96SAndrew Vasquez 
1246c81d04c9SAndrew Vasquez qla25xx_fw_dump_failed_0:
1247c3a2f0dfSAndrew Vasquez 	if (rval != QLA_SUCCESS) {
1248c3a2f0dfSAndrew Vasquez 		qla_printk(KERN_WARNING, ha,
1249c3a2f0dfSAndrew Vasquez 		    "Failed to dump firmware (%x)!!!\n", rval);
1250c3a2f0dfSAndrew Vasquez 		ha->fw_dumped = 0;
1251c3a2f0dfSAndrew Vasquez 
1252c3a2f0dfSAndrew Vasquez 	} else {
1253c3a2f0dfSAndrew Vasquez 		qla_printk(KERN_INFO, ha,
1254c3a2f0dfSAndrew Vasquez 		    "Firmware dump saved to temp buffer (%ld/%p).\n",
1255*7b867cf7SAnirban Chakraborty 		    vha->host_no, ha->fw_dump);
1256c3a2f0dfSAndrew Vasquez 		ha->fw_dumped = 1;
1257c3a2f0dfSAndrew Vasquez 	}
1258c3a2f0dfSAndrew Vasquez 
1259c3a2f0dfSAndrew Vasquez qla25xx_fw_dump_failed:
1260c3a2f0dfSAndrew Vasquez 	if (!hardware_locked)
1261c3a2f0dfSAndrew Vasquez 		spin_unlock_irqrestore(&ha->hardware_lock, flags);
1262c3a2f0dfSAndrew Vasquez }
1263c3a2f0dfSAndrew Vasquez 
12641da177e4SLinus Torvalds /****************************************************************************/
12651da177e4SLinus Torvalds /*                         Driver Debug Functions.                          */
12661da177e4SLinus Torvalds /****************************************************************************/
12671da177e4SLinus Torvalds 
12681da177e4SLinus Torvalds void
1269*7b867cf7SAnirban Chakraborty qla2x00_dump_regs(scsi_qla_host_t *vha)
12701da177e4SLinus Torvalds {
12716afd9763SAndrew Vasquez 	int i;
1272*7b867cf7SAnirban Chakraborty 	struct qla_hw_data *ha = vha->hw;
12733d71644cSAndrew Vasquez 	struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
12746afd9763SAndrew Vasquez 	struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24;
12756afd9763SAndrew Vasquez 	uint16_t __iomem *mbx_reg;
12766afd9763SAndrew Vasquez 
12776afd9763SAndrew Vasquez 	mbx_reg = IS_FWI2_CAPABLE(ha) ? &reg24->mailbox0:
12786afd9763SAndrew Vasquez 	    MAILBOX_REG(ha, reg, 0);
12791da177e4SLinus Torvalds 
12801da177e4SLinus Torvalds 	printk("Mailbox registers:\n");
12816afd9763SAndrew Vasquez 	for (i = 0; i < 6; i++)
1282*7b867cf7SAnirban Chakraborty 		printk("scsi(%ld): mbox %d 0x%04x \n", vha->host_no, i,
12836afd9763SAndrew Vasquez 		    RD_REG_WORD(mbx_reg++));
12841da177e4SLinus Torvalds }
12851da177e4SLinus Torvalds 
12861da177e4SLinus Torvalds 
12871da177e4SLinus Torvalds void
12881da177e4SLinus Torvalds qla2x00_dump_buffer(uint8_t * b, uint32_t size)
12891da177e4SLinus Torvalds {
12901da177e4SLinus Torvalds 	uint32_t cnt;
12911da177e4SLinus Torvalds 	uint8_t c;
12921da177e4SLinus Torvalds 
12931da177e4SLinus Torvalds 	printk(" 0   1   2   3   4   5   6   7   8   9  "
12941da177e4SLinus Torvalds 	    "Ah  Bh  Ch  Dh  Eh  Fh\n");
12951da177e4SLinus Torvalds 	printk("----------------------------------------"
12961da177e4SLinus Torvalds 	    "----------------------\n");
12971da177e4SLinus Torvalds 
12981da177e4SLinus Torvalds 	for (cnt = 0; cnt < size;) {
12991da177e4SLinus Torvalds 		c = *b++;
13001da177e4SLinus Torvalds 		printk("%02x",(uint32_t) c);
13011da177e4SLinus Torvalds 		cnt++;
13021da177e4SLinus Torvalds 		if (!(cnt % 16))
13031da177e4SLinus Torvalds 			printk("\n");
13041da177e4SLinus Torvalds 		else
13051da177e4SLinus Torvalds 			printk("  ");
13061da177e4SLinus Torvalds 	}
13071da177e4SLinus Torvalds 	if (cnt % 16)
13081da177e4SLinus Torvalds 		printk("\n");
13091da177e4SLinus Torvalds }
1310