Deleted Added
full compact
ql_misc.c (250661) ql_misc.c (254976)
1/*
2 * Copyright (c) 2013-2014 Qlogic Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27/*
28 * File : ql_misc.c
29 * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
30 */
31
32#include <sys/cdefs.h>
1/*
2 * Copyright (c) 2013-2014 Qlogic Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27/*
28 * File : ql_misc.c
29 * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/dev/qlxgbe/ql_misc.c 250661 2013-05-15 17:03:09Z davidcs $");
33__FBSDID("$FreeBSD: head/sys/dev/qlxgbe/ql_misc.c 254976 2013-08-27 21:29:21Z davidcs $");
34
35#include "ql_os.h"
36#include "ql_hw.h"
37#include "ql_def.h"
38#include "ql_inline.h"
39#include "ql_glbl.h"
40#include "ql_dbg.h"
41#include "ql_tmplt.h"
42
43#define QL_FDT_OFFSET 0x3F0000
44#define Q8_FLASH_SECTOR_SIZE 0x10000
45
46static int qla_ld_fw_init(qla_host_t *ha);
47
48/*
49 * structure encapsulating the value to read/write to offchip memory
50 */
51typedef struct _offchip_mem_val {
52 uint32_t data_lo;
53 uint32_t data_hi;
54 uint32_t data_ulo;
55 uint32_t data_uhi;
56} offchip_mem_val_t;
57
58/*
59 * Name: ql_rdwr_indreg32
60 * Function: Read/Write an Indirect Register
61 */
62int
63ql_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd)
64{
65 uint32_t wnd_reg;
66 uint32_t count = 100;
67
68 wnd_reg = (Q8_CRB_WINDOW_PF0 | (ha->pci_func << 2));
69
70 WRITE_REG32(ha, wnd_reg, addr);
71
72 while (count--) {
73 if (READ_REG32(ha, wnd_reg) == addr)
74 break;
75 qla_mdelay(__func__, 1);
76 }
77 if (!count || QL_ERR_INJECT(ha, INJCT_RDWR_INDREG_FAILURE)) {
78 device_printf(ha->pci_dev, "%s: [0x%08x, 0x%08x, %d] failed\n",
79 __func__, addr, *val, rd);
80 ha->qla_initiate_recovery = 1;
81 return -1;
82 }
83
84 if (rd) {
85 *val = READ_REG32(ha, Q8_WILD_CARD);
86 } else {
87 WRITE_REG32(ha, Q8_WILD_CARD, *val);
88 }
89
90 return 0;
91}
92
93/*
94 * Name: ql_rdwr_offchip_mem
95 * Function: Read/Write OffChip Memory
96 */
97int
98ql_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, q80_offchip_mem_val_t *val,
99 uint32_t rd)
100{
101 uint32_t count = 100;
102 uint32_t data, step = 0;
103
104
105 if (QL_ERR_INJECT(ha, INJCT_RDWR_OFFCHIPMEM_FAILURE))
106 goto exit_ql_rdwr_offchip_mem;
107
108 data = (uint32_t)addr;
109 if (ql_rdwr_indreg32(ha, Q8_MS_ADDR_LO, &data, 0)) {
110 step = 1;
111 goto exit_ql_rdwr_offchip_mem;
112 }
113
114 data = (uint32_t)(addr >> 32);
115 if (ql_rdwr_indreg32(ha, Q8_MS_ADDR_HI, &data, 0)) {
116 step = 2;
117 goto exit_ql_rdwr_offchip_mem;
118 }
119
120 data = BIT_1;
121 if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
122 step = 3;
123 goto exit_ql_rdwr_offchip_mem;
124 }
125
126 if (!rd) {
127 data = val->data_lo;
128 if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_0_31, &data, 0)) {
129 step = 4;
130 goto exit_ql_rdwr_offchip_mem;
131 }
132
133 data = val->data_hi;
134 if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_32_63, &data, 0)) {
135 step = 5;
136 goto exit_ql_rdwr_offchip_mem;
137 }
138
139 data = val->data_ulo;
140 if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_64_95, &data, 0)) {
141 step = 6;
142 goto exit_ql_rdwr_offchip_mem;
143 }
144
145 data = val->data_uhi;
146 if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_96_127, &data, 0)) {
147 step = 7;
148 goto exit_ql_rdwr_offchip_mem;
149 }
150
151 data = (BIT_2|BIT_1|BIT_0);
152 if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
153 step = 7;
154 goto exit_ql_rdwr_offchip_mem;
155 }
156 } else {
157 data = (BIT_1|BIT_0);
158 if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
159 step = 8;
160 goto exit_ql_rdwr_offchip_mem;
161 }
162 }
163
164 while (count--) {
165 if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 1)) {
166 step = 9;
167 goto exit_ql_rdwr_offchip_mem;
168 }
169
170 if (!(data & BIT_3)) {
171 if (rd) {
172 if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_0_31,
173 &data, 1)) {
174 step = 10;
175 goto exit_ql_rdwr_offchip_mem;
176 }
177 val->data_lo = data;
178
179 if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_32_63,
180 &data, 1)) {
181 step = 11;
182 goto exit_ql_rdwr_offchip_mem;
183 }
184 val->data_hi = data;
185
186 if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_64_95,
187 &data, 1)) {
188 step = 12;
189 goto exit_ql_rdwr_offchip_mem;
190 }
191 val->data_ulo = data;
192
193 if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_96_127,
194 &data, 1)) {
195 step = 13;
196 goto exit_ql_rdwr_offchip_mem;
197 }
198 val->data_uhi = data;
199 }
200 return 0;
201 } else
202 qla_mdelay(__func__, 1);
203 }
204
205exit_ql_rdwr_offchip_mem:
206
207 device_printf(ha->pci_dev,
208 "%s: [0x%08x 0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x]"
209 " [%d] [%d] failed\n", __func__, (uint32_t)(addr >> 32),
210 (uint32_t)(addr), val->data_lo, val->data_hi, val->data_ulo,
211 val->data_uhi, rd, step);
212
213 ha->qla_initiate_recovery = 1;
214
215 return (-1);
216}
217
218/*
219 * Name: ql_rd_flash32
220 * Function: Read Flash Memory
221 */
222int
223ql_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
224{
225 uint32_t data32;
226
227 if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID, 0xABCDABCD)) {
228 device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
229 __func__);
230 return (-1);
231 }
232
233 data32 = addr;
234 if (ql_rdwr_indreg32(ha, Q8_FLASH_DIRECT_WINDOW, &data32, 0)) {
235 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
236 device_printf(ha->pci_dev,
237 "%s: Q8_FLASH_DIRECT_WINDOW[0x%08x] failed\n",
238 __func__, data32);
239 return (-1);
240 }
241
242 data32 = Q8_FLASH_DIRECT_DATA | (addr & 0xFFFF);
243 if (ql_rdwr_indreg32(ha, data32, data, 1)) {
244 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
245 device_printf(ha->pci_dev,
246 "%s: data32:data [0x%08x] failed\n",
247 __func__, data32);
248 return (-1);
249 }
250
251 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
252 return 0;
253}
254
255static int
256qla_get_fdt(qla_host_t *ha)
257{
258 uint32_t data32;
259 int count;
260 qla_hw_t *hw;
261
262 hw = &ha->hw;
263
264 for (count = 0; count < sizeof(qla_flash_desc_table_t); count+=4) {
265 if (ql_rd_flash32(ha, QL_FDT_OFFSET + count,
266 (uint32_t *)&hw->fdt + (count >> 2))) {
267 device_printf(ha->pci_dev,
268 "%s: Read QL_FDT_OFFSET + %d failed\n",
269 __func__, count);
270 return (-1);
271 }
272 }
273
274 if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
275 Q8_FDT_LOCK_MAGIC_ID)) {
276 device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
277 __func__);
278 return (-1);
279 }
280
281 data32 = Q8_FDT_FLASH_ADDR_VAL;
282 if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
283 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
284 device_printf(ha->pci_dev,
285 "%s: Write to Q8_FLASH_ADDRESS failed\n",
286 __func__);
287 return (-1);
288 }
289
290 data32 = Q8_FDT_FLASH_CTRL_VAL;
291 if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
292 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
293 device_printf(ha->pci_dev,
294 "%s: Write to Q8_FLASH_CONTROL failed\n",
295 __func__);
296 return (-1);
297 }
298
299 count = 0;
300
301 do {
302 if (count < 1000) {
303 QLA_USEC_DELAY(10);
304 count += 10;
305 } else {
306 qla_mdelay(__func__, 1);
307 count += 1000;
308 }
309
310 data32 = 0;
311
312 if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
313 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
314 device_printf(ha->pci_dev,
315 "%s: Read Q8_FLASH_STATUS failed\n",
316 __func__);
317 return (-1);
318 }
319
320 data32 &= 0x6;
321
322 } while ((count < 10000) && (data32 != 0x6));
323
34
35#include "ql_os.h"
36#include "ql_hw.h"
37#include "ql_def.h"
38#include "ql_inline.h"
39#include "ql_glbl.h"
40#include "ql_dbg.h"
41#include "ql_tmplt.h"
42
43#define QL_FDT_OFFSET 0x3F0000
44#define Q8_FLASH_SECTOR_SIZE 0x10000
45
46static int qla_ld_fw_init(qla_host_t *ha);
47
48/*
49 * structure encapsulating the value to read/write to offchip memory
50 */
51typedef struct _offchip_mem_val {
52 uint32_t data_lo;
53 uint32_t data_hi;
54 uint32_t data_ulo;
55 uint32_t data_uhi;
56} offchip_mem_val_t;
57
58/*
59 * Name: ql_rdwr_indreg32
60 * Function: Read/Write an Indirect Register
61 */
62int
63ql_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd)
64{
65 uint32_t wnd_reg;
66 uint32_t count = 100;
67
68 wnd_reg = (Q8_CRB_WINDOW_PF0 | (ha->pci_func << 2));
69
70 WRITE_REG32(ha, wnd_reg, addr);
71
72 while (count--) {
73 if (READ_REG32(ha, wnd_reg) == addr)
74 break;
75 qla_mdelay(__func__, 1);
76 }
77 if (!count || QL_ERR_INJECT(ha, INJCT_RDWR_INDREG_FAILURE)) {
78 device_printf(ha->pci_dev, "%s: [0x%08x, 0x%08x, %d] failed\n",
79 __func__, addr, *val, rd);
80 ha->qla_initiate_recovery = 1;
81 return -1;
82 }
83
84 if (rd) {
85 *val = READ_REG32(ha, Q8_WILD_CARD);
86 } else {
87 WRITE_REG32(ha, Q8_WILD_CARD, *val);
88 }
89
90 return 0;
91}
92
93/*
94 * Name: ql_rdwr_offchip_mem
95 * Function: Read/Write OffChip Memory
96 */
97int
98ql_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, q80_offchip_mem_val_t *val,
99 uint32_t rd)
100{
101 uint32_t count = 100;
102 uint32_t data, step = 0;
103
104
105 if (QL_ERR_INJECT(ha, INJCT_RDWR_OFFCHIPMEM_FAILURE))
106 goto exit_ql_rdwr_offchip_mem;
107
108 data = (uint32_t)addr;
109 if (ql_rdwr_indreg32(ha, Q8_MS_ADDR_LO, &data, 0)) {
110 step = 1;
111 goto exit_ql_rdwr_offchip_mem;
112 }
113
114 data = (uint32_t)(addr >> 32);
115 if (ql_rdwr_indreg32(ha, Q8_MS_ADDR_HI, &data, 0)) {
116 step = 2;
117 goto exit_ql_rdwr_offchip_mem;
118 }
119
120 data = BIT_1;
121 if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
122 step = 3;
123 goto exit_ql_rdwr_offchip_mem;
124 }
125
126 if (!rd) {
127 data = val->data_lo;
128 if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_0_31, &data, 0)) {
129 step = 4;
130 goto exit_ql_rdwr_offchip_mem;
131 }
132
133 data = val->data_hi;
134 if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_32_63, &data, 0)) {
135 step = 5;
136 goto exit_ql_rdwr_offchip_mem;
137 }
138
139 data = val->data_ulo;
140 if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_64_95, &data, 0)) {
141 step = 6;
142 goto exit_ql_rdwr_offchip_mem;
143 }
144
145 data = val->data_uhi;
146 if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_96_127, &data, 0)) {
147 step = 7;
148 goto exit_ql_rdwr_offchip_mem;
149 }
150
151 data = (BIT_2|BIT_1|BIT_0);
152 if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
153 step = 7;
154 goto exit_ql_rdwr_offchip_mem;
155 }
156 } else {
157 data = (BIT_1|BIT_0);
158 if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
159 step = 8;
160 goto exit_ql_rdwr_offchip_mem;
161 }
162 }
163
164 while (count--) {
165 if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 1)) {
166 step = 9;
167 goto exit_ql_rdwr_offchip_mem;
168 }
169
170 if (!(data & BIT_3)) {
171 if (rd) {
172 if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_0_31,
173 &data, 1)) {
174 step = 10;
175 goto exit_ql_rdwr_offchip_mem;
176 }
177 val->data_lo = data;
178
179 if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_32_63,
180 &data, 1)) {
181 step = 11;
182 goto exit_ql_rdwr_offchip_mem;
183 }
184 val->data_hi = data;
185
186 if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_64_95,
187 &data, 1)) {
188 step = 12;
189 goto exit_ql_rdwr_offchip_mem;
190 }
191 val->data_ulo = data;
192
193 if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_96_127,
194 &data, 1)) {
195 step = 13;
196 goto exit_ql_rdwr_offchip_mem;
197 }
198 val->data_uhi = data;
199 }
200 return 0;
201 } else
202 qla_mdelay(__func__, 1);
203 }
204
205exit_ql_rdwr_offchip_mem:
206
207 device_printf(ha->pci_dev,
208 "%s: [0x%08x 0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x]"
209 " [%d] [%d] failed\n", __func__, (uint32_t)(addr >> 32),
210 (uint32_t)(addr), val->data_lo, val->data_hi, val->data_ulo,
211 val->data_uhi, rd, step);
212
213 ha->qla_initiate_recovery = 1;
214
215 return (-1);
216}
217
218/*
219 * Name: ql_rd_flash32
220 * Function: Read Flash Memory
221 */
222int
223ql_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
224{
225 uint32_t data32;
226
227 if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID, 0xABCDABCD)) {
228 device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
229 __func__);
230 return (-1);
231 }
232
233 data32 = addr;
234 if (ql_rdwr_indreg32(ha, Q8_FLASH_DIRECT_WINDOW, &data32, 0)) {
235 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
236 device_printf(ha->pci_dev,
237 "%s: Q8_FLASH_DIRECT_WINDOW[0x%08x] failed\n",
238 __func__, data32);
239 return (-1);
240 }
241
242 data32 = Q8_FLASH_DIRECT_DATA | (addr & 0xFFFF);
243 if (ql_rdwr_indreg32(ha, data32, data, 1)) {
244 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
245 device_printf(ha->pci_dev,
246 "%s: data32:data [0x%08x] failed\n",
247 __func__, data32);
248 return (-1);
249 }
250
251 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
252 return 0;
253}
254
255static int
256qla_get_fdt(qla_host_t *ha)
257{
258 uint32_t data32;
259 int count;
260 qla_hw_t *hw;
261
262 hw = &ha->hw;
263
264 for (count = 0; count < sizeof(qla_flash_desc_table_t); count+=4) {
265 if (ql_rd_flash32(ha, QL_FDT_OFFSET + count,
266 (uint32_t *)&hw->fdt + (count >> 2))) {
267 device_printf(ha->pci_dev,
268 "%s: Read QL_FDT_OFFSET + %d failed\n",
269 __func__, count);
270 return (-1);
271 }
272 }
273
274 if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
275 Q8_FDT_LOCK_MAGIC_ID)) {
276 device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
277 __func__);
278 return (-1);
279 }
280
281 data32 = Q8_FDT_FLASH_ADDR_VAL;
282 if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
283 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
284 device_printf(ha->pci_dev,
285 "%s: Write to Q8_FLASH_ADDRESS failed\n",
286 __func__);
287 return (-1);
288 }
289
290 data32 = Q8_FDT_FLASH_CTRL_VAL;
291 if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
292 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
293 device_printf(ha->pci_dev,
294 "%s: Write to Q8_FLASH_CONTROL failed\n",
295 __func__);
296 return (-1);
297 }
298
299 count = 0;
300
301 do {
302 if (count < 1000) {
303 QLA_USEC_DELAY(10);
304 count += 10;
305 } else {
306 qla_mdelay(__func__, 1);
307 count += 1000;
308 }
309
310 data32 = 0;
311
312 if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
313 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
314 device_printf(ha->pci_dev,
315 "%s: Read Q8_FLASH_STATUS failed\n",
316 __func__);
317 return (-1);
318 }
319
320 data32 &= 0x6;
321
322 } while ((count < 10000) && (data32 != 0x6));
323
324 if (count == 0 && data32 != 0x6) {
324 if (data32 != 0x6) {
325 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
326 device_printf(ha->pci_dev,
327 "%s: Poll Q8_FLASH_STATUS failed\n",
328 __func__);
329 return (-1);
330 }
331
332 if (ql_rdwr_indreg32(ha, Q8_FLASH_RD_DATA, &data32, 1)) {
333 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
334 device_printf(ha->pci_dev,
335 "%s: Read Q8_FLASH_RD_DATA failed\n",
336 __func__);
337 return (-1);
338 }
339
340 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
341
342 data32 &= Q8_FDT_MASK_VAL;
343 if (hw->fdt.flash_manuf == data32)
344 return (0);
345 else
346 return (-1);
347}
348
349static int
350qla_flash_write_enable(qla_host_t *ha, int enable)
351{
352 uint32_t data32;
353 int count = 0;
354
355 data32 = Q8_WR_ENABLE_FL_ADDR | ha->hw.fdt.write_statusreg_cmd;
356 if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
357 device_printf(ha->pci_dev,
358 "%s: Write to Q8_FLASH_ADDRESS failed\n",
359 __func__);
360 return (-1);
361 }
362
363 if (enable)
364 data32 = ha->hw.fdt.write_enable_bits;
365 else
366 data32 = ha->hw.fdt.write_disable_bits;
367
368 if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, &data32, 0)) {
369 device_printf(ha->pci_dev,
370 "%s: Write to Q8_FLASH_WR_DATA failed\n",
371 __func__);
372 return (-1);
373 }
374
375 data32 = Q8_WR_ENABLE_FL_CTRL;
376 if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
377 device_printf(ha->pci_dev,
378 "%s: Write to Q8_FLASH_CONTROL failed\n",
379 __func__);
380 return (-1);
381 }
382
383 do {
384 if (count < 1000) {
385 QLA_USEC_DELAY(10);
386 count += 10;
387 } else {
388 qla_mdelay(__func__, 1);
389 count += 1000;
390 }
391
392 data32 = 0;
393 if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
394 device_printf(ha->pci_dev,
395 "%s: Read Q8_FLASH_STATUS failed\n",
396 __func__);
397 return (-1);
398 }
399
400 data32 &= 0x6;
401
402 } while ((count < 10000) && (data32 != 0x6));
403
325 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
326 device_printf(ha->pci_dev,
327 "%s: Poll Q8_FLASH_STATUS failed\n",
328 __func__);
329 return (-1);
330 }
331
332 if (ql_rdwr_indreg32(ha, Q8_FLASH_RD_DATA, &data32, 1)) {
333 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
334 device_printf(ha->pci_dev,
335 "%s: Read Q8_FLASH_RD_DATA failed\n",
336 __func__);
337 return (-1);
338 }
339
340 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
341
342 data32 &= Q8_FDT_MASK_VAL;
343 if (hw->fdt.flash_manuf == data32)
344 return (0);
345 else
346 return (-1);
347}
348
349static int
350qla_flash_write_enable(qla_host_t *ha, int enable)
351{
352 uint32_t data32;
353 int count = 0;
354
355 data32 = Q8_WR_ENABLE_FL_ADDR | ha->hw.fdt.write_statusreg_cmd;
356 if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
357 device_printf(ha->pci_dev,
358 "%s: Write to Q8_FLASH_ADDRESS failed\n",
359 __func__);
360 return (-1);
361 }
362
363 if (enable)
364 data32 = ha->hw.fdt.write_enable_bits;
365 else
366 data32 = ha->hw.fdt.write_disable_bits;
367
368 if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, &data32, 0)) {
369 device_printf(ha->pci_dev,
370 "%s: Write to Q8_FLASH_WR_DATA failed\n",
371 __func__);
372 return (-1);
373 }
374
375 data32 = Q8_WR_ENABLE_FL_CTRL;
376 if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
377 device_printf(ha->pci_dev,
378 "%s: Write to Q8_FLASH_CONTROL failed\n",
379 __func__);
380 return (-1);
381 }
382
383 do {
384 if (count < 1000) {
385 QLA_USEC_DELAY(10);
386 count += 10;
387 } else {
388 qla_mdelay(__func__, 1);
389 count += 1000;
390 }
391
392 data32 = 0;
393 if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
394 device_printf(ha->pci_dev,
395 "%s: Read Q8_FLASH_STATUS failed\n",
396 __func__);
397 return (-1);
398 }
399
400 data32 &= 0x6;
401
402 } while ((count < 10000) && (data32 != 0x6));
403
404 if (count == 0 && data32 != 0x6) {
404 if (data32 != 0x6) {
405 device_printf(ha->pci_dev,
406 "%s: Poll Q8_FLASH_STATUS failed\n",
407 __func__);
408 return (-1);
409 }
410
411 return 0;
412}
413
414static int
415qla_erase_flash_sector(qla_host_t *ha, uint32_t start)
416{
417 uint32_t data32;
418 int count = 0;
419
420 do {
421 qla_mdelay(__func__, 1);
422
423 data32 = 0;
424 if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
425 device_printf(ha->pci_dev,
426 "%s: Read Q8_FLASH_STATUS failed\n",
427 __func__);
428 return (-1);
429 }
430
431 data32 &= 0x6;
432
433 } while (((count++) < 1000) && (data32 != 0x6));
434
405 device_printf(ha->pci_dev,
406 "%s: Poll Q8_FLASH_STATUS failed\n",
407 __func__);
408 return (-1);
409 }
410
411 return 0;
412}
413
414static int
415qla_erase_flash_sector(qla_host_t *ha, uint32_t start)
416{
417 uint32_t data32;
418 int count = 0;
419
420 do {
421 qla_mdelay(__func__, 1);
422
423 data32 = 0;
424 if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
425 device_printf(ha->pci_dev,
426 "%s: Read Q8_FLASH_STATUS failed\n",
427 __func__);
428 return (-1);
429 }
430
431 data32 &= 0x6;
432
433 } while (((count++) < 1000) && (data32 != 0x6));
434
435 if (count == 0 && data32 != 0x6) {
435 if (data32 != 0x6) {
436 device_printf(ha->pci_dev,
437 "%s: Poll Q8_FLASH_STATUS failed\n",
438 __func__);
439 return (-1);
440 }
441
442 data32 = (start >> 16) & 0xFF;
443 if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, &data32, 0)) {
444 device_printf(ha->pci_dev,
445 "%s: Write to Q8_FLASH_WR_DATA failed\n",
446 __func__);
447 return (-1);
448 }
449
450 data32 = Q8_ERASE_FL_ADDR_MASK | ha->hw.fdt.erase_cmd;
451 if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
452 device_printf(ha->pci_dev,
453 "%s: Write to Q8_FLASH_ADDRESS failed\n",
454 __func__);
455 return (-1);
456 }
457
458 data32 = Q8_ERASE_FL_CTRL_MASK;
459 if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
460 device_printf(ha->pci_dev,
461 "%s: Write to Q8_FLASH_CONTROL failed\n",
462 __func__);
463 return (-1);
464 }
465
466 count = 0;
467 do {
468 qla_mdelay(__func__, 1);
469
470 data32 = 0;
471 if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
472 device_printf(ha->pci_dev,
473 "%s: Read Q8_FLASH_STATUS failed\n",
474 __func__);
475 return (-1);
476 }
477
478 data32 &= 0x6;
479
480 } while (((count++) < 1000) && (data32 != 0x6));
481
436 device_printf(ha->pci_dev,
437 "%s: Poll Q8_FLASH_STATUS failed\n",
438 __func__);
439 return (-1);
440 }
441
442 data32 = (start >> 16) & 0xFF;
443 if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, &data32, 0)) {
444 device_printf(ha->pci_dev,
445 "%s: Write to Q8_FLASH_WR_DATA failed\n",
446 __func__);
447 return (-1);
448 }
449
450 data32 = Q8_ERASE_FL_ADDR_MASK | ha->hw.fdt.erase_cmd;
451 if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
452 device_printf(ha->pci_dev,
453 "%s: Write to Q8_FLASH_ADDRESS failed\n",
454 __func__);
455 return (-1);
456 }
457
458 data32 = Q8_ERASE_FL_CTRL_MASK;
459 if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
460 device_printf(ha->pci_dev,
461 "%s: Write to Q8_FLASH_CONTROL failed\n",
462 __func__);
463 return (-1);
464 }
465
466 count = 0;
467 do {
468 qla_mdelay(__func__, 1);
469
470 data32 = 0;
471 if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
472 device_printf(ha->pci_dev,
473 "%s: Read Q8_FLASH_STATUS failed\n",
474 __func__);
475 return (-1);
476 }
477
478 data32 &= 0x6;
479
480 } while (((count++) < 1000) && (data32 != 0x6));
481
482 if (count == 0 && data32 != 0x6) {
482 if (data32 != 0x6) {
483 device_printf(ha->pci_dev,
484 "%s: Poll Q8_FLASH_STATUS failed\n",
485 __func__);
486 return (-1);
487 }
488
489 return 0;
490}
491
492int
493ql_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size)
494{
495 int rval = 0;
496 uint32_t start;
497
498 if (off & (Q8_FLASH_SECTOR_SIZE -1))
499 return (-1);
500
501 if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
502 Q8_ERASE_LOCK_MAGIC_ID)) {
503 device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
504 __func__);
505 return (-1);
506 }
507
508 if (qla_flash_write_enable(ha, 1) != 0) {
509 rval = -1;
510 goto ql_erase_flash_exit;
511 }
512
513 for (start = off; start < (off + size); start = start +
514 Q8_FLASH_SECTOR_SIZE) {
515 if (qla_erase_flash_sector(ha, start)) {
516 rval = -1;
517 break;
518 }
519 }
520
521 rval = qla_flash_write_enable(ha, 0);
522
523ql_erase_flash_exit:
524 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
525 return (rval);
526}
527
528static int
529qla_wr_flash32(qla_host_t *ha, uint32_t off, uint32_t *data)
530{
531 uint32_t data32;
532 int count = 0;
533
534 data32 = Q8_WR_FL_ADDR_MASK | (off >> 2);
535 if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
536 device_printf(ha->pci_dev,
537 "%s: Write to Q8_FLASH_ADDRESS failed\n",
538 __func__);
539 return (-1);
540 }
541
542 if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, data, 0)) {
543 device_printf(ha->pci_dev,
544 "%s: Write to Q8_FLASH_WR_DATA failed\n",
545 __func__);
546 return (-1);
547 }
548
549 data32 = Q8_WR_FL_CTRL_MASK;
550 if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
551 device_printf(ha->pci_dev,
552 "%s: Write to Q8_FLASH_CONTROL failed\n",
553 __func__);
554 return (-1);
555 }
556
557 do {
558 if (count < 1000) {
559 QLA_USEC_DELAY(10);
560 count += 10;
561 } else {
562 qla_mdelay(__func__, 1);
563 count += 1000;
564 }
565
566 data32 = 0;
567 if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
568 device_printf(ha->pci_dev,
569 "%s: Read Q8_FLASH_STATUS failed\n",
570 __func__);
571 return (-1);
572 }
573
574 data32 &= 0x6;
575
576 } while ((count < 10000) && (data32 != 0x6));
577
483 device_printf(ha->pci_dev,
484 "%s: Poll Q8_FLASH_STATUS failed\n",
485 __func__);
486 return (-1);
487 }
488
489 return 0;
490}
491
492int
493ql_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size)
494{
495 int rval = 0;
496 uint32_t start;
497
498 if (off & (Q8_FLASH_SECTOR_SIZE -1))
499 return (-1);
500
501 if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
502 Q8_ERASE_LOCK_MAGIC_ID)) {
503 device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
504 __func__);
505 return (-1);
506 }
507
508 if (qla_flash_write_enable(ha, 1) != 0) {
509 rval = -1;
510 goto ql_erase_flash_exit;
511 }
512
513 for (start = off; start < (off + size); start = start +
514 Q8_FLASH_SECTOR_SIZE) {
515 if (qla_erase_flash_sector(ha, start)) {
516 rval = -1;
517 break;
518 }
519 }
520
521 rval = qla_flash_write_enable(ha, 0);
522
523ql_erase_flash_exit:
524 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
525 return (rval);
526}
527
528static int
529qla_wr_flash32(qla_host_t *ha, uint32_t off, uint32_t *data)
530{
531 uint32_t data32;
532 int count = 0;
533
534 data32 = Q8_WR_FL_ADDR_MASK | (off >> 2);
535 if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
536 device_printf(ha->pci_dev,
537 "%s: Write to Q8_FLASH_ADDRESS failed\n",
538 __func__);
539 return (-1);
540 }
541
542 if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, data, 0)) {
543 device_printf(ha->pci_dev,
544 "%s: Write to Q8_FLASH_WR_DATA failed\n",
545 __func__);
546 return (-1);
547 }
548
549 data32 = Q8_WR_FL_CTRL_MASK;
550 if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
551 device_printf(ha->pci_dev,
552 "%s: Write to Q8_FLASH_CONTROL failed\n",
553 __func__);
554 return (-1);
555 }
556
557 do {
558 if (count < 1000) {
559 QLA_USEC_DELAY(10);
560 count += 10;
561 } else {
562 qla_mdelay(__func__, 1);
563 count += 1000;
564 }
565
566 data32 = 0;
567 if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
568 device_printf(ha->pci_dev,
569 "%s: Read Q8_FLASH_STATUS failed\n",
570 __func__);
571 return (-1);
572 }
573
574 data32 &= 0x6;
575
576 } while ((count < 10000) && (data32 != 0x6));
577
578 if (count == 0 && data32 != 0x6) {
578 if (data32 != 0x6) {
579 device_printf(ha->pci_dev,
580 "%s: Poll Q8_FLASH_STATUS failed\n",
581 __func__);
582 return (-1);
583 }
584
585 return 0;
586}
587
588static int
589qla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size,
590 void *data)
591{
592 int rval = 0;
593 uint32_t start;
594 uint32_t *data32 = data;
595
596 if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
597 Q8_WR_FL_LOCK_MAGIC_ID)) {
598 device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
599 __func__);
600 rval = -1;
601 goto qla_flash_write_data_exit;
602 }
603
604 if ((qla_flash_write_enable(ha, 1) != 0)) {
605 device_printf(ha->pci_dev, "%s: failed\n",
606 __func__);
607 rval = -1;
608 goto qla_flash_write_data_unlock_exit;
609 }
610
611 for (start = off; start < (off + size); start = start + 4) {
612 if (*data32 != 0xFFFFFFFF) {
613 if (qla_wr_flash32(ha, start, data32)) {
614 rval = -1;
615 break;
616 }
617 }
618 data32++;
619 }
620
621 rval = qla_flash_write_enable(ha, 0);
622
623qla_flash_write_data_unlock_exit:
624 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
625
626qla_flash_write_data_exit:
627 return (rval);
628}
629
630int
631ql_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf)
632{
633 int rval = 0;
634 void *data;
635
636 if (size == 0)
637 return 0;
638
639 size = size << 2;
640
641 if (buf == NULL)
642 return -1;
643
644 if ((data = malloc(size, M_QLA83XXBUF, M_NOWAIT)) == NULL) {
645 device_printf(ha->pci_dev, "%s: malloc failed \n", __func__);
646 rval = -1;
647 goto ql_wr_flash_buffer_exit;
648 }
649
650 if ((rval = copyin(buf, data, size))) {
651 device_printf(ha->pci_dev, "%s copyin failed\n", __func__);
652 goto ql_wr_flash_buffer_free_exit;
653 }
654
655 rval = qla_flash_write_data(ha, off, size, data);
656
657ql_wr_flash_buffer_free_exit:
658 free(data, M_QLA83XXBUF);
659
660ql_wr_flash_buffer_exit:
661 return (rval);
662}
663
664/*
665 * Name: qla_load_fw_from_flash
666 * Function: Reads the Bootloader from Flash and Loads into Offchip Memory
667 */
668static void
669qla_load_fw_from_flash(qla_host_t *ha)
670{
671 uint32_t flash_off = 0x10000;
672 uint64_t mem_off;
673 uint32_t count, mem_size;
674 q80_offchip_mem_val_t val;
675
676 mem_off = (uint64_t)(READ_REG32(ha, Q8_BOOTLD_ADDR));
677 mem_size = READ_REG32(ha, Q8_BOOTLD_SIZE);
678
679 device_printf(ha->pci_dev, "%s: [0x%08x][0x%08x]\n",
680 __func__, (uint32_t)mem_off, mem_size);
681
682 /* only bootloader needs to be loaded into memory */
683 for (count = 0; count < mem_size ; ) {
684 ql_rd_flash32(ha, flash_off, &val.data_lo);
685 count = count + 4;
686 flash_off = flash_off + 4;
687
688 ql_rd_flash32(ha, flash_off, &val.data_hi);
689 count = count + 4;
690 flash_off = flash_off + 4;
691
692 ql_rd_flash32(ha, flash_off, &val.data_ulo);
693 count = count + 4;
694 flash_off = flash_off + 4;
695
696 ql_rd_flash32(ha, flash_off, &val.data_uhi);
697 count = count + 4;
698 flash_off = flash_off + 4;
699
700 ql_rdwr_offchip_mem(ha, mem_off, &val, 0);
701
702 mem_off = mem_off + 16;
703 }
704
705 return;
706}
707
708/*
709 * Name: qla_init_from_flash
710 * Function: Performs Initialization which consists of the following sequence
711 * - reset
712 * - CRB Init
713 * - Peg Init
714 * - Read the Bootloader from Flash and Load into Offchip Memory
715 * - Kick start the bootloader which loads the rest of the firmware
716 * and performs the remaining steps in the initialization process.
717 */
718static int
719qla_init_from_flash(qla_host_t *ha)
720{
721 uint32_t delay = 300;
722 uint32_t data;
723
724 qla_ld_fw_init(ha);
725
726 do {
727 data = READ_REG32(ha, Q8_CMDPEG_STATE);
728
729 QL_DPRINT2(ha,
730 (ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
731 __func__, ha->pci_func, data));
732 if (data == 0xFF01) {
733 QL_DPRINT2(ha, (ha->pci_dev,
734 "%s: func[%d] init complete\n",
735 __func__, ha->pci_func));
736 return(0);
737 }
738 qla_mdelay(__func__, 100);
739 } while (delay--);
740
741 return (-1);
742}
743
744/*
745 * Name: ql_init_hw
746 * Function: Initializes P3+ hardware.
747 */
748int
749ql_init_hw(qla_host_t *ha)
750{
751 device_t dev;
752 int ret = 0;
753 uint32_t val, delay = 300;
754
755 dev = ha->pci_dev;
756
757 QL_DPRINT1(ha, (dev, "%s: enter\n", __func__));
758
759 if (ha->pci_func & 0x1) {
760
761 while ((ha->pci_func & 0x1) && delay--) {
762
763 val = READ_REG32(ha, Q8_CMDPEG_STATE);
764
765 if (val == 0xFF01) {
766 QL_DPRINT2(ha, (dev,
767 "%s: func = %d init complete\n",
768 __func__, ha->pci_func));
769 qla_mdelay(__func__, 100);
770 goto qla_init_exit;
771 }
772 qla_mdelay(__func__, 100);
773 }
774 return (-1);
775 }
776
777
778 val = READ_REG32(ha, Q8_CMDPEG_STATE);
779 if (!cold || (val != 0xFF01)) {
780 ret = qla_init_from_flash(ha);
781 qla_mdelay(__func__, 100);
782 }
783
784qla_init_exit:
785 ha->fw_ver_major = READ_REG32(ha, Q8_FW_VER_MAJOR);
786 ha->fw_ver_minor = READ_REG32(ha, Q8_FW_VER_MINOR);
787 ha->fw_ver_sub = READ_REG32(ha, Q8_FW_VER_SUB);
788
789 if (qla_get_fdt(ha) != 0) {
790 device_printf(dev, "%s: qla_get_fdt failed\n", __func__);
791 } else {
792 ha->hw.flags.fdt_valid = 1;
793 }
794
795 return (ret);
796}
797
798void
799ql_read_mac_addr(qla_host_t *ha)
800{
801 uint8_t *macp;
802 uint32_t mac_lo;
803 uint32_t mac_hi;
804 uint32_t flash_off;
805
806 flash_off = Q8_BOARD_CONFIG_OFFSET + Q8_BOARD_CONFIG_MAC0_LO +
807 (ha->pci_func << 3);
808 ql_rd_flash32(ha, flash_off, &mac_lo);
809
810 flash_off += 4;
811 ql_rd_flash32(ha, flash_off, &mac_hi);
812
813 macp = (uint8_t *)&mac_lo;
814 ha->hw.mac_addr[5] = macp[0];
815 ha->hw.mac_addr[4] = macp[1];
816 ha->hw.mac_addr[3] = macp[2];
817 ha->hw.mac_addr[2] = macp[3];
818
819 macp = (uint8_t *)&mac_hi;
820 ha->hw.mac_addr[1] = macp[0];
821 ha->hw.mac_addr[0] = macp[1];
822
823 //device_printf(ha->pci_dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
824 // __func__, ha->hw.mac_addr[0], ha->hw.mac_addr[1],
825 // ha->hw.mac_addr[2], ha->hw.mac_addr[3],
826 // ha->hw.mac_addr[4], ha->hw.mac_addr[5]);
827
828 return;
829}
830
831/*
832 * Stop/Start/Initialization Handling
833 */
834
835static uint16_t
836qla_tmplt_16bit_checksum(qla_host_t *ha, uint16_t *buf, uint32_t size)
837{
838 uint32_t sum = 0;
839 uint32_t count = size >> 1; /* size in 16 bit words */
840
841 while (count-- > 0)
842 sum += *buf++;
843
844 while (sum >> 16)
845 sum = (sum & 0xFFFF) + (sum >> 16);
846
847 return (~sum);
848}
849
850static int
851qla_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
852{
853 q8_wrl_e_t *wr_l;
854 int i;
855
856 wr_l = (q8_wrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
857
858 for (i = 0; i < ce_hdr->opcount; i++, wr_l++) {
859
860 if (ql_rdwr_indreg32(ha, wr_l->addr, &wr_l->value, 0)) {
861 device_printf(ha->pci_dev,
862 "%s: [0x%08x 0x%08x] error\n", __func__,
863 wr_l->addr, wr_l->value);
864 return -1;
865 }
866 if (ce_hdr->delay_to) {
867 DELAY(ce_hdr->delay_to);
868 }
869 }
870 return 0;
871}
872
873static int
874qla_rd_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
875{
876 q8_rdwrl_e_t *rd_wr_l;
877 uint32_t data;
878 int i;
879
880 rd_wr_l = (q8_rdwrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
881
882 for (i = 0; i < ce_hdr->opcount; i++, rd_wr_l++) {
883
884 if (ql_rdwr_indreg32(ha, rd_wr_l->rd_addr, &data, 1)) {
885 device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
886 __func__, rd_wr_l->rd_addr);
887
888 return -1;
889 }
890
891 if (ql_rdwr_indreg32(ha, rd_wr_l->wr_addr, &data, 0)) {
892 device_printf(ha->pci_dev,
893 "%s: [0x%08x 0x%08x] error\n", __func__,
894 rd_wr_l->wr_addr, data);
895 return -1;
896 }
897 if (ce_hdr->delay_to) {
898 DELAY(ce_hdr->delay_to);
899 }
900 }
901 return 0;
902}
903
904static int
905qla_poll_reg(qla_host_t *ha, uint32_t addr, uint32_t ms_to, uint32_t tmask,
906 uint32_t tvalue)
907{
908 uint32_t data;
909
910 while (ms_to) {
911
912 if (ql_rdwr_indreg32(ha, addr, &data, 1)) {
913 device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
914 __func__, addr);
915 return -1;
916 }
917
918 if ((data & tmask) != tvalue) {
919 ms_to--;
920 } else
921 break;
922
923 qla_mdelay(__func__, 1);
924 }
925 return ((ms_to ? 0: -1));
926}
927
928static int
929qla_poll_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
930{
931 int i;
932 q8_poll_hdr_t *phdr;
933 q8_poll_e_t *pe;
934 uint32_t data;
935
936 phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
937 pe = (q8_poll_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
938
939 for (i = 0; i < ce_hdr->opcount; i++, pe++) {
940 if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
941 device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
942 __func__, pe->addr);
943 return -1;
944 }
945
946 if (ce_hdr->delay_to) {
947 if ((data & phdr->tmask) == phdr->tvalue)
948 break;
949 if (qla_poll_reg(ha, pe->addr, ce_hdr->delay_to,
950 phdr->tmask, phdr->tvalue)) {
951
952 if (ql_rdwr_indreg32(ha, pe->to_addr, &data,
953 1)) {
954 device_printf(ha->pci_dev,
955 "%s: [0x%08x] error\n",
956 __func__, pe->to_addr);
957 return -1;
958 }
959
960 if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
961 device_printf(ha->pci_dev,
962 "%s: [0x%08x] error\n",
963 __func__, pe->addr);
964 return -1;
965 }
966 }
967 }
968 }
969 return 0;
970}
971
972static int
973qla_poll_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
974{
975 int i;
976 q8_poll_hdr_t *phdr;
977 q8_poll_wr_e_t *wr_e;
978
979 phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
980 wr_e = (q8_poll_wr_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
981
982 for (i = 0; i < ce_hdr->opcount; i++, wr_e++) {
983
984 if (ql_rdwr_indreg32(ha, wr_e->dr_addr, &wr_e->dr_value, 0)) {
985 device_printf(ha->pci_dev,
986 "%s: [0x%08x 0x%08x] error\n", __func__,
987 wr_e->dr_addr, wr_e->dr_value);
988 return -1;
989 }
990 if (ql_rdwr_indreg32(ha, wr_e->ar_addr, &wr_e->ar_value, 0)) {
991 device_printf(ha->pci_dev,
992 "%s: [0x%08x 0x%08x] error\n", __func__,
993 wr_e->ar_addr, wr_e->ar_value);
994 return -1;
995 }
996 if (ce_hdr->delay_to) {
997 if (qla_poll_reg(ha, wr_e->ar_addr, ce_hdr->delay_to,
998 phdr->tmask, phdr->tvalue))
999 device_printf(ha->pci_dev, "%s: "
1000 "[ar_addr, ar_value, delay, tmask,"
1001 "tvalue] [0x%08x 0x%08x 0x%08x 0x%08x"
1002 " 0x%08x]\n",
1003 __func__, wr_e->ar_addr, wr_e->ar_value,
1004 ce_hdr->delay_to, phdr->tmask,
1005 phdr->tvalue);
1006 }
1007 }
1008 return 0;
1009}
1010
1011static int
1012qla_poll_read_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1013{
1014 int i;
1015 q8_poll_hdr_t *phdr;
1016 q8_poll_rd_e_t *rd_e;
1017 uint32_t value;
1018
1019 phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
1020 rd_e = (q8_poll_rd_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
1021
1022 for (i = 0; i < ce_hdr->opcount; i++, rd_e++) {
1023 if (ql_rdwr_indreg32(ha, rd_e->ar_addr, &rd_e->ar_value, 0)) {
1024 device_printf(ha->pci_dev,
1025 "%s: [0x%08x 0x%08x] error\n", __func__,
1026 rd_e->ar_addr, rd_e->ar_value);
1027 return -1;
1028 }
1029
1030 if (ce_hdr->delay_to) {
1031 if (qla_poll_reg(ha, rd_e->ar_addr, ce_hdr->delay_to,
1032 phdr->tmask, phdr->tvalue)) {
1033 return (-1);
1034 } else {
1035 if (ql_rdwr_indreg32(ha, rd_e->dr_addr,
1036 &value, 1)) {
1037 device_printf(ha->pci_dev,
1038 "%s: [0x%08x] error\n",
1039 __func__, rd_e->ar_addr);
1040 return -1;
1041 }
1042
1043 ha->hw.rst_seq[ha->hw.rst_seq_idx++] = value;
1044 if (ha->hw.rst_seq_idx == Q8_MAX_RESET_SEQ_IDX)
1045 ha->hw.rst_seq_idx = 1;
1046 }
1047 }
1048 }
1049 return 0;
1050}
1051
1052static int
1053qla_rdmwr(qla_host_t *ha, uint32_t raddr, uint32_t waddr, q8_rdmwr_hdr_t *hdr)
1054{
1055 uint32_t value;
1056
1057 if (hdr->index_a >= Q8_MAX_RESET_SEQ_IDX) {
1058 device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1059 hdr->index_a);
1060 return -1;
1061 }
1062
1063 if (hdr->index_a) {
1064 value = ha->hw.rst_seq[hdr->index_a];
1065 } else {
1066 if (ql_rdwr_indreg32(ha, raddr, &value, 1)) {
1067 device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
1068 __func__, raddr);
1069 return -1;
1070 }
1071 }
1072
1073 value &= hdr->and_value;
1074 value <<= hdr->shl;
1075 value >>= hdr->shr;
1076 value |= hdr->or_value;
1077 value ^= hdr->xor_value;
1078
1079 if (ql_rdwr_indreg32(ha, waddr, &value, 0)) {
1080 device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1081 raddr);
1082 return -1;
1083 }
1084 return 0;
1085}
1086
1087static int
1088qla_read_modify_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1089{
1090 int i;
1091 q8_rdmwr_hdr_t *rdmwr_hdr;
1092 q8_rdmwr_e_t *rdmwr_e;
1093
1094 rdmwr_hdr = (q8_rdmwr_hdr_t *)((uint8_t *)ce_hdr +
1095 sizeof (q8_ce_hdr_t));
1096 rdmwr_e = (q8_rdmwr_e_t *)((uint8_t *)rdmwr_hdr +
1097 sizeof(q8_rdmwr_hdr_t));
1098
1099 for (i = 0; i < ce_hdr->opcount; i++, rdmwr_e++) {
1100
1101 if (qla_rdmwr(ha, rdmwr_e->rd_addr, rdmwr_e->wr_addr,
1102 rdmwr_hdr)) {
1103 return -1;
1104 }
1105 if (ce_hdr->delay_to) {
1106 DELAY(ce_hdr->delay_to);
1107 }
1108 }
1109 return 0;
1110}
1111
1112static int
1113qla_tmplt_execute(qla_host_t *ha, uint8_t *buf, int start_idx, int *end_idx,
1114 uint32_t nentries)
1115{
1116 int i, ret = 0, proc_end = 0;
1117 q8_ce_hdr_t *ce_hdr;
1118
1119 for (i = start_idx; ((i < nentries) && (!proc_end)); i++) {
1120 ce_hdr = (q8_ce_hdr_t *)buf;
1121 ret = 0;
1122
1123 switch (ce_hdr->opcode) {
1124 case Q8_CE_OPCODE_NOP:
1125 break;
1126
1127 case Q8_CE_OPCODE_WRITE_LIST:
1128 ret = qla_wr_list(ha, ce_hdr);
1129 //printf("qla_wr_list %d\n", ret);
1130 break;
1131
1132 case Q8_CE_OPCODE_READ_WRITE_LIST:
1133 ret = qla_rd_wr_list(ha, ce_hdr);
1134 //printf("qla_rd_wr_list %d\n", ret);
1135 break;
1136
1137 case Q8_CE_OPCODE_POLL_LIST:
1138 ret = qla_poll_list(ha, ce_hdr);
1139 //printf("qla_poll_list %d\n", ret);
1140 break;
1141
1142 case Q8_CE_OPCODE_POLL_WRITE_LIST:
1143 ret = qla_poll_write_list(ha, ce_hdr);
1144 //printf("qla_poll_write_list %d\n", ret);
1145 break;
1146
1147 case Q8_CE_OPCODE_POLL_RD_LIST:
1148 ret = qla_poll_read_list(ha, ce_hdr);
1149 //printf("qla_poll_read_list %d\n", ret);
1150 break;
1151
1152 case Q8_CE_OPCODE_READ_MODIFY_WRITE:
1153 ret = qla_read_modify_write_list(ha, ce_hdr);
1154 //printf("qla_read_modify_write_list %d\n", ret);
1155 break;
1156
1157 case Q8_CE_OPCODE_SEQ_PAUSE:
1158 if (ce_hdr->delay_to) {
1159 qla_mdelay(__func__, ce_hdr->delay_to);
1160 }
1161 break;
1162
1163 case Q8_CE_OPCODE_SEQ_END:
1164 proc_end = 1;
1165 break;
1166
1167 case Q8_CE_OPCODE_TMPLT_END:
1168 *end_idx = i;
1169 return 0;
1170 }
1171
1172 if (ret)
1173 break;
1174
1175 buf += ce_hdr->size;
1176 }
1177 *end_idx = i;
1178
1179 return (ret);
1180}
1181
1182
1183static int
1184qla_ld_fw_init(qla_host_t *ha)
1185{
1186 uint8_t *buf;
1187 uint32_t index = 0, end_idx;
1188 q8_tmplt_hdr_t *hdr;
1189
1190 bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1191
1192 hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1193
1194 if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1195 (uint32_t)hdr->size)) {
1196 device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1197 __func__);
1198 return -1;
1199 }
1200
1201
1202 buf = ql83xx_resetseq + hdr->stop_seq_off;
1203
1204// device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1205 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1206 device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1207 return -1;
1208 }
1209
1210 index = end_idx;
1211
1212 buf = ql83xx_resetseq + hdr->init_seq_off;
1213
1214// device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1215 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1216 device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1217 return -1;
1218 }
1219
1220 qla_load_fw_from_flash(ha);
1221 WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
1222
1223 index = end_idx;
1224 buf = ql83xx_resetseq + hdr->start_seq_off;
1225
1226// device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1227 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1228 device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1229 return -1;
1230 }
1231
1232 return 0;
1233}
1234
1235int
1236ql_stop_sequence(qla_host_t *ha)
1237{
1238 uint8_t *buf;
1239 uint32_t index = 0, end_idx;
1240 q8_tmplt_hdr_t *hdr;
1241
1242 bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1243
1244 hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1245
1246 if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1247 (uint32_t)hdr->size)) {
1248 device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1249 __func__);
1250 return (-1);
1251 }
1252
1253 buf = ql83xx_resetseq + hdr->stop_seq_off;
1254
1255 device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1256 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1257 device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1258 return (-1);
1259 }
1260
1261 return end_idx;
1262}
1263
1264int
1265ql_start_sequence(qla_host_t *ha, uint16_t index)
1266{
1267 uint8_t *buf;
1268 uint32_t end_idx;
1269 q8_tmplt_hdr_t *hdr;
1270
1271 bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1272
1273 hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1274
1275 if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1276 (uint32_t)hdr->size)) {
1277 device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1278 __func__);
1279 return (-1);
1280 }
1281
1282 buf = ql83xx_resetseq + hdr->init_seq_off;
1283
1284 device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1285 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1286 device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1287 return (-1);
1288 }
1289
1290 qla_load_fw_from_flash(ha);
1291 WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
1292
1293 index = end_idx;
1294 buf = ql83xx_resetseq + hdr->start_seq_off;
1295
1296 device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1297 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1298 device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1299 return -1;
1300 }
1301
1302 return (0);
1303}
1304
579 device_printf(ha->pci_dev,
580 "%s: Poll Q8_FLASH_STATUS failed\n",
581 __func__);
582 return (-1);
583 }
584
585 return 0;
586}
587
588static int
589qla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size,
590 void *data)
591{
592 int rval = 0;
593 uint32_t start;
594 uint32_t *data32 = data;
595
596 if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
597 Q8_WR_FL_LOCK_MAGIC_ID)) {
598 device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
599 __func__);
600 rval = -1;
601 goto qla_flash_write_data_exit;
602 }
603
604 if ((qla_flash_write_enable(ha, 1) != 0)) {
605 device_printf(ha->pci_dev, "%s: failed\n",
606 __func__);
607 rval = -1;
608 goto qla_flash_write_data_unlock_exit;
609 }
610
611 for (start = off; start < (off + size); start = start + 4) {
612 if (*data32 != 0xFFFFFFFF) {
613 if (qla_wr_flash32(ha, start, data32)) {
614 rval = -1;
615 break;
616 }
617 }
618 data32++;
619 }
620
621 rval = qla_flash_write_enable(ha, 0);
622
623qla_flash_write_data_unlock_exit:
624 qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
625
626qla_flash_write_data_exit:
627 return (rval);
628}
629
630int
631ql_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf)
632{
633 int rval = 0;
634 void *data;
635
636 if (size == 0)
637 return 0;
638
639 size = size << 2;
640
641 if (buf == NULL)
642 return -1;
643
644 if ((data = malloc(size, M_QLA83XXBUF, M_NOWAIT)) == NULL) {
645 device_printf(ha->pci_dev, "%s: malloc failed \n", __func__);
646 rval = -1;
647 goto ql_wr_flash_buffer_exit;
648 }
649
650 if ((rval = copyin(buf, data, size))) {
651 device_printf(ha->pci_dev, "%s copyin failed\n", __func__);
652 goto ql_wr_flash_buffer_free_exit;
653 }
654
655 rval = qla_flash_write_data(ha, off, size, data);
656
657ql_wr_flash_buffer_free_exit:
658 free(data, M_QLA83XXBUF);
659
660ql_wr_flash_buffer_exit:
661 return (rval);
662}
663
664/*
665 * Name: qla_load_fw_from_flash
666 * Function: Reads the Bootloader from Flash and Loads into Offchip Memory
667 */
668static void
669qla_load_fw_from_flash(qla_host_t *ha)
670{
671 uint32_t flash_off = 0x10000;
672 uint64_t mem_off;
673 uint32_t count, mem_size;
674 q80_offchip_mem_val_t val;
675
676 mem_off = (uint64_t)(READ_REG32(ha, Q8_BOOTLD_ADDR));
677 mem_size = READ_REG32(ha, Q8_BOOTLD_SIZE);
678
679 device_printf(ha->pci_dev, "%s: [0x%08x][0x%08x]\n",
680 __func__, (uint32_t)mem_off, mem_size);
681
682 /* only bootloader needs to be loaded into memory */
683 for (count = 0; count < mem_size ; ) {
684 ql_rd_flash32(ha, flash_off, &val.data_lo);
685 count = count + 4;
686 flash_off = flash_off + 4;
687
688 ql_rd_flash32(ha, flash_off, &val.data_hi);
689 count = count + 4;
690 flash_off = flash_off + 4;
691
692 ql_rd_flash32(ha, flash_off, &val.data_ulo);
693 count = count + 4;
694 flash_off = flash_off + 4;
695
696 ql_rd_flash32(ha, flash_off, &val.data_uhi);
697 count = count + 4;
698 flash_off = flash_off + 4;
699
700 ql_rdwr_offchip_mem(ha, mem_off, &val, 0);
701
702 mem_off = mem_off + 16;
703 }
704
705 return;
706}
707
708/*
709 * Name: qla_init_from_flash
710 * Function: Performs Initialization which consists of the following sequence
711 * - reset
712 * - CRB Init
713 * - Peg Init
714 * - Read the Bootloader from Flash and Load into Offchip Memory
715 * - Kick start the bootloader which loads the rest of the firmware
716 * and performs the remaining steps in the initialization process.
717 */
718static int
719qla_init_from_flash(qla_host_t *ha)
720{
721 uint32_t delay = 300;
722 uint32_t data;
723
724 qla_ld_fw_init(ha);
725
726 do {
727 data = READ_REG32(ha, Q8_CMDPEG_STATE);
728
729 QL_DPRINT2(ha,
730 (ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
731 __func__, ha->pci_func, data));
732 if (data == 0xFF01) {
733 QL_DPRINT2(ha, (ha->pci_dev,
734 "%s: func[%d] init complete\n",
735 __func__, ha->pci_func));
736 return(0);
737 }
738 qla_mdelay(__func__, 100);
739 } while (delay--);
740
741 return (-1);
742}
743
744/*
745 * Name: ql_init_hw
746 * Function: Initializes P3+ hardware.
747 */
748int
749ql_init_hw(qla_host_t *ha)
750{
751 device_t dev;
752 int ret = 0;
753 uint32_t val, delay = 300;
754
755 dev = ha->pci_dev;
756
757 QL_DPRINT1(ha, (dev, "%s: enter\n", __func__));
758
759 if (ha->pci_func & 0x1) {
760
761 while ((ha->pci_func & 0x1) && delay--) {
762
763 val = READ_REG32(ha, Q8_CMDPEG_STATE);
764
765 if (val == 0xFF01) {
766 QL_DPRINT2(ha, (dev,
767 "%s: func = %d init complete\n",
768 __func__, ha->pci_func));
769 qla_mdelay(__func__, 100);
770 goto qla_init_exit;
771 }
772 qla_mdelay(__func__, 100);
773 }
774 return (-1);
775 }
776
777
778 val = READ_REG32(ha, Q8_CMDPEG_STATE);
779 if (!cold || (val != 0xFF01)) {
780 ret = qla_init_from_flash(ha);
781 qla_mdelay(__func__, 100);
782 }
783
784qla_init_exit:
785 ha->fw_ver_major = READ_REG32(ha, Q8_FW_VER_MAJOR);
786 ha->fw_ver_minor = READ_REG32(ha, Q8_FW_VER_MINOR);
787 ha->fw_ver_sub = READ_REG32(ha, Q8_FW_VER_SUB);
788
789 if (qla_get_fdt(ha) != 0) {
790 device_printf(dev, "%s: qla_get_fdt failed\n", __func__);
791 } else {
792 ha->hw.flags.fdt_valid = 1;
793 }
794
795 return (ret);
796}
797
798void
799ql_read_mac_addr(qla_host_t *ha)
800{
801 uint8_t *macp;
802 uint32_t mac_lo;
803 uint32_t mac_hi;
804 uint32_t flash_off;
805
806 flash_off = Q8_BOARD_CONFIG_OFFSET + Q8_BOARD_CONFIG_MAC0_LO +
807 (ha->pci_func << 3);
808 ql_rd_flash32(ha, flash_off, &mac_lo);
809
810 flash_off += 4;
811 ql_rd_flash32(ha, flash_off, &mac_hi);
812
813 macp = (uint8_t *)&mac_lo;
814 ha->hw.mac_addr[5] = macp[0];
815 ha->hw.mac_addr[4] = macp[1];
816 ha->hw.mac_addr[3] = macp[2];
817 ha->hw.mac_addr[2] = macp[3];
818
819 macp = (uint8_t *)&mac_hi;
820 ha->hw.mac_addr[1] = macp[0];
821 ha->hw.mac_addr[0] = macp[1];
822
823 //device_printf(ha->pci_dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
824 // __func__, ha->hw.mac_addr[0], ha->hw.mac_addr[1],
825 // ha->hw.mac_addr[2], ha->hw.mac_addr[3],
826 // ha->hw.mac_addr[4], ha->hw.mac_addr[5]);
827
828 return;
829}
830
831/*
832 * Stop/Start/Initialization Handling
833 */
834
835static uint16_t
836qla_tmplt_16bit_checksum(qla_host_t *ha, uint16_t *buf, uint32_t size)
837{
838 uint32_t sum = 0;
839 uint32_t count = size >> 1; /* size in 16 bit words */
840
841 while (count-- > 0)
842 sum += *buf++;
843
844 while (sum >> 16)
845 sum = (sum & 0xFFFF) + (sum >> 16);
846
847 return (~sum);
848}
849
850static int
851qla_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
852{
853 q8_wrl_e_t *wr_l;
854 int i;
855
856 wr_l = (q8_wrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
857
858 for (i = 0; i < ce_hdr->opcount; i++, wr_l++) {
859
860 if (ql_rdwr_indreg32(ha, wr_l->addr, &wr_l->value, 0)) {
861 device_printf(ha->pci_dev,
862 "%s: [0x%08x 0x%08x] error\n", __func__,
863 wr_l->addr, wr_l->value);
864 return -1;
865 }
866 if (ce_hdr->delay_to) {
867 DELAY(ce_hdr->delay_to);
868 }
869 }
870 return 0;
871}
872
873static int
874qla_rd_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
875{
876 q8_rdwrl_e_t *rd_wr_l;
877 uint32_t data;
878 int i;
879
880 rd_wr_l = (q8_rdwrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
881
882 for (i = 0; i < ce_hdr->opcount; i++, rd_wr_l++) {
883
884 if (ql_rdwr_indreg32(ha, rd_wr_l->rd_addr, &data, 1)) {
885 device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
886 __func__, rd_wr_l->rd_addr);
887
888 return -1;
889 }
890
891 if (ql_rdwr_indreg32(ha, rd_wr_l->wr_addr, &data, 0)) {
892 device_printf(ha->pci_dev,
893 "%s: [0x%08x 0x%08x] error\n", __func__,
894 rd_wr_l->wr_addr, data);
895 return -1;
896 }
897 if (ce_hdr->delay_to) {
898 DELAY(ce_hdr->delay_to);
899 }
900 }
901 return 0;
902}
903
904static int
905qla_poll_reg(qla_host_t *ha, uint32_t addr, uint32_t ms_to, uint32_t tmask,
906 uint32_t tvalue)
907{
908 uint32_t data;
909
910 while (ms_to) {
911
912 if (ql_rdwr_indreg32(ha, addr, &data, 1)) {
913 device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
914 __func__, addr);
915 return -1;
916 }
917
918 if ((data & tmask) != tvalue) {
919 ms_to--;
920 } else
921 break;
922
923 qla_mdelay(__func__, 1);
924 }
925 return ((ms_to ? 0: -1));
926}
927
928static int
929qla_poll_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
930{
931 int i;
932 q8_poll_hdr_t *phdr;
933 q8_poll_e_t *pe;
934 uint32_t data;
935
936 phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
937 pe = (q8_poll_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
938
939 for (i = 0; i < ce_hdr->opcount; i++, pe++) {
940 if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
941 device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
942 __func__, pe->addr);
943 return -1;
944 }
945
946 if (ce_hdr->delay_to) {
947 if ((data & phdr->tmask) == phdr->tvalue)
948 break;
949 if (qla_poll_reg(ha, pe->addr, ce_hdr->delay_to,
950 phdr->tmask, phdr->tvalue)) {
951
952 if (ql_rdwr_indreg32(ha, pe->to_addr, &data,
953 1)) {
954 device_printf(ha->pci_dev,
955 "%s: [0x%08x] error\n",
956 __func__, pe->to_addr);
957 return -1;
958 }
959
960 if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
961 device_printf(ha->pci_dev,
962 "%s: [0x%08x] error\n",
963 __func__, pe->addr);
964 return -1;
965 }
966 }
967 }
968 }
969 return 0;
970}
971
972static int
973qla_poll_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
974{
975 int i;
976 q8_poll_hdr_t *phdr;
977 q8_poll_wr_e_t *wr_e;
978
979 phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
980 wr_e = (q8_poll_wr_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
981
982 for (i = 0; i < ce_hdr->opcount; i++, wr_e++) {
983
984 if (ql_rdwr_indreg32(ha, wr_e->dr_addr, &wr_e->dr_value, 0)) {
985 device_printf(ha->pci_dev,
986 "%s: [0x%08x 0x%08x] error\n", __func__,
987 wr_e->dr_addr, wr_e->dr_value);
988 return -1;
989 }
990 if (ql_rdwr_indreg32(ha, wr_e->ar_addr, &wr_e->ar_value, 0)) {
991 device_printf(ha->pci_dev,
992 "%s: [0x%08x 0x%08x] error\n", __func__,
993 wr_e->ar_addr, wr_e->ar_value);
994 return -1;
995 }
996 if (ce_hdr->delay_to) {
997 if (qla_poll_reg(ha, wr_e->ar_addr, ce_hdr->delay_to,
998 phdr->tmask, phdr->tvalue))
999 device_printf(ha->pci_dev, "%s: "
1000 "[ar_addr, ar_value, delay, tmask,"
1001 "tvalue] [0x%08x 0x%08x 0x%08x 0x%08x"
1002 " 0x%08x]\n",
1003 __func__, wr_e->ar_addr, wr_e->ar_value,
1004 ce_hdr->delay_to, phdr->tmask,
1005 phdr->tvalue);
1006 }
1007 }
1008 return 0;
1009}
1010
1011static int
1012qla_poll_read_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1013{
1014 int i;
1015 q8_poll_hdr_t *phdr;
1016 q8_poll_rd_e_t *rd_e;
1017 uint32_t value;
1018
1019 phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
1020 rd_e = (q8_poll_rd_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
1021
1022 for (i = 0; i < ce_hdr->opcount; i++, rd_e++) {
1023 if (ql_rdwr_indreg32(ha, rd_e->ar_addr, &rd_e->ar_value, 0)) {
1024 device_printf(ha->pci_dev,
1025 "%s: [0x%08x 0x%08x] error\n", __func__,
1026 rd_e->ar_addr, rd_e->ar_value);
1027 return -1;
1028 }
1029
1030 if (ce_hdr->delay_to) {
1031 if (qla_poll_reg(ha, rd_e->ar_addr, ce_hdr->delay_to,
1032 phdr->tmask, phdr->tvalue)) {
1033 return (-1);
1034 } else {
1035 if (ql_rdwr_indreg32(ha, rd_e->dr_addr,
1036 &value, 1)) {
1037 device_printf(ha->pci_dev,
1038 "%s: [0x%08x] error\n",
1039 __func__, rd_e->ar_addr);
1040 return -1;
1041 }
1042
1043 ha->hw.rst_seq[ha->hw.rst_seq_idx++] = value;
1044 if (ha->hw.rst_seq_idx == Q8_MAX_RESET_SEQ_IDX)
1045 ha->hw.rst_seq_idx = 1;
1046 }
1047 }
1048 }
1049 return 0;
1050}
1051
1052static int
1053qla_rdmwr(qla_host_t *ha, uint32_t raddr, uint32_t waddr, q8_rdmwr_hdr_t *hdr)
1054{
1055 uint32_t value;
1056
1057 if (hdr->index_a >= Q8_MAX_RESET_SEQ_IDX) {
1058 device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1059 hdr->index_a);
1060 return -1;
1061 }
1062
1063 if (hdr->index_a) {
1064 value = ha->hw.rst_seq[hdr->index_a];
1065 } else {
1066 if (ql_rdwr_indreg32(ha, raddr, &value, 1)) {
1067 device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
1068 __func__, raddr);
1069 return -1;
1070 }
1071 }
1072
1073 value &= hdr->and_value;
1074 value <<= hdr->shl;
1075 value >>= hdr->shr;
1076 value |= hdr->or_value;
1077 value ^= hdr->xor_value;
1078
1079 if (ql_rdwr_indreg32(ha, waddr, &value, 0)) {
1080 device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1081 raddr);
1082 return -1;
1083 }
1084 return 0;
1085}
1086
1087static int
1088qla_read_modify_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1089{
1090 int i;
1091 q8_rdmwr_hdr_t *rdmwr_hdr;
1092 q8_rdmwr_e_t *rdmwr_e;
1093
1094 rdmwr_hdr = (q8_rdmwr_hdr_t *)((uint8_t *)ce_hdr +
1095 sizeof (q8_ce_hdr_t));
1096 rdmwr_e = (q8_rdmwr_e_t *)((uint8_t *)rdmwr_hdr +
1097 sizeof(q8_rdmwr_hdr_t));
1098
1099 for (i = 0; i < ce_hdr->opcount; i++, rdmwr_e++) {
1100
1101 if (qla_rdmwr(ha, rdmwr_e->rd_addr, rdmwr_e->wr_addr,
1102 rdmwr_hdr)) {
1103 return -1;
1104 }
1105 if (ce_hdr->delay_to) {
1106 DELAY(ce_hdr->delay_to);
1107 }
1108 }
1109 return 0;
1110}
1111
1112static int
1113qla_tmplt_execute(qla_host_t *ha, uint8_t *buf, int start_idx, int *end_idx,
1114 uint32_t nentries)
1115{
1116 int i, ret = 0, proc_end = 0;
1117 q8_ce_hdr_t *ce_hdr;
1118
1119 for (i = start_idx; ((i < nentries) && (!proc_end)); i++) {
1120 ce_hdr = (q8_ce_hdr_t *)buf;
1121 ret = 0;
1122
1123 switch (ce_hdr->opcode) {
1124 case Q8_CE_OPCODE_NOP:
1125 break;
1126
1127 case Q8_CE_OPCODE_WRITE_LIST:
1128 ret = qla_wr_list(ha, ce_hdr);
1129 //printf("qla_wr_list %d\n", ret);
1130 break;
1131
1132 case Q8_CE_OPCODE_READ_WRITE_LIST:
1133 ret = qla_rd_wr_list(ha, ce_hdr);
1134 //printf("qla_rd_wr_list %d\n", ret);
1135 break;
1136
1137 case Q8_CE_OPCODE_POLL_LIST:
1138 ret = qla_poll_list(ha, ce_hdr);
1139 //printf("qla_poll_list %d\n", ret);
1140 break;
1141
1142 case Q8_CE_OPCODE_POLL_WRITE_LIST:
1143 ret = qla_poll_write_list(ha, ce_hdr);
1144 //printf("qla_poll_write_list %d\n", ret);
1145 break;
1146
1147 case Q8_CE_OPCODE_POLL_RD_LIST:
1148 ret = qla_poll_read_list(ha, ce_hdr);
1149 //printf("qla_poll_read_list %d\n", ret);
1150 break;
1151
1152 case Q8_CE_OPCODE_READ_MODIFY_WRITE:
1153 ret = qla_read_modify_write_list(ha, ce_hdr);
1154 //printf("qla_read_modify_write_list %d\n", ret);
1155 break;
1156
1157 case Q8_CE_OPCODE_SEQ_PAUSE:
1158 if (ce_hdr->delay_to) {
1159 qla_mdelay(__func__, ce_hdr->delay_to);
1160 }
1161 break;
1162
1163 case Q8_CE_OPCODE_SEQ_END:
1164 proc_end = 1;
1165 break;
1166
1167 case Q8_CE_OPCODE_TMPLT_END:
1168 *end_idx = i;
1169 return 0;
1170 }
1171
1172 if (ret)
1173 break;
1174
1175 buf += ce_hdr->size;
1176 }
1177 *end_idx = i;
1178
1179 return (ret);
1180}
1181
1182
1183static int
1184qla_ld_fw_init(qla_host_t *ha)
1185{
1186 uint8_t *buf;
1187 uint32_t index = 0, end_idx;
1188 q8_tmplt_hdr_t *hdr;
1189
1190 bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1191
1192 hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1193
1194 if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1195 (uint32_t)hdr->size)) {
1196 device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1197 __func__);
1198 return -1;
1199 }
1200
1201
1202 buf = ql83xx_resetseq + hdr->stop_seq_off;
1203
1204// device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1205 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1206 device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1207 return -1;
1208 }
1209
1210 index = end_idx;
1211
1212 buf = ql83xx_resetseq + hdr->init_seq_off;
1213
1214// device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1215 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1216 device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1217 return -1;
1218 }
1219
1220 qla_load_fw_from_flash(ha);
1221 WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
1222
1223 index = end_idx;
1224 buf = ql83xx_resetseq + hdr->start_seq_off;
1225
1226// device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1227 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1228 device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1229 return -1;
1230 }
1231
1232 return 0;
1233}
1234
1235int
1236ql_stop_sequence(qla_host_t *ha)
1237{
1238 uint8_t *buf;
1239 uint32_t index = 0, end_idx;
1240 q8_tmplt_hdr_t *hdr;
1241
1242 bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1243
1244 hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1245
1246 if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1247 (uint32_t)hdr->size)) {
1248 device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1249 __func__);
1250 return (-1);
1251 }
1252
1253 buf = ql83xx_resetseq + hdr->stop_seq_off;
1254
1255 device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1256 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1257 device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1258 return (-1);
1259 }
1260
1261 return end_idx;
1262}
1263
1264int
1265ql_start_sequence(qla_host_t *ha, uint16_t index)
1266{
1267 uint8_t *buf;
1268 uint32_t end_idx;
1269 q8_tmplt_hdr_t *hdr;
1270
1271 bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1272
1273 hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1274
1275 if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1276 (uint32_t)hdr->size)) {
1277 device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1278 __func__);
1279 return (-1);
1280 }
1281
1282 buf = ql83xx_resetseq + hdr->init_seq_off;
1283
1284 device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1285 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1286 device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1287 return (-1);
1288 }
1289
1290 qla_load_fw_from_flash(ha);
1291 WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
1292
1293 index = end_idx;
1294 buf = ql83xx_resetseq + hdr->start_seq_off;
1295
1296 device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1297 if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1298 device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1299 return -1;
1300 }
1301
1302 return (0);
1303}
1304