]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/qlxgb/qla_misc.c
Update to ELF Tool Chain r3668
[FreeBSD/FreeBSD.git] / sys / dev / qlxgb / qla_misc.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2011-2013 Qlogic Corporation
5  * All rights reserved.
6  *
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions
9  *  are met:
10  *
11  *  1. Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *  2. Redistributions in binary form must reproduce the above copyright
14  *     notice, this list of conditions and the following disclaimer in the
15  *     documentation and/or other materials provided with the distribution.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  *  POSSIBILITY OF SUCH DAMAGE.
28  */
29 /*
30  * File : qla_misc.c
31  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
32  */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include "qla_os.h"
38 #include "qla_reg.h"
39 #include "qla_hw.h"
40 #include "qla_def.h"
41 #include "qla_reg.h"
42 #include "qla_inline.h"
43 #include "qla_glbl.h"
44 #include "qla_dbg.h"
45
46 /*
47  * structure encapsulating the value to read/write to offchip memory
48  */
49 typedef struct _offchip_mem_val {
50         uint32_t data_lo;
51         uint32_t data_hi;
52         uint32_t data_ulo;
53         uint32_t data_uhi;
54 } offchip_mem_val_t;
55
56 #define Q8_ADDR_UNDEFINED               0xFFFFFFFF
57
58 /*
59  * The index to this table is Bits 20-27 of the indirect register address
60  */ 
61 static uint32_t indirect_to_base_map[] =
62         {
63                 Q8_ADDR_UNDEFINED,      /* 0x00 */
64                 0x77300000,             /* 0x01 */
65                 0x29500000,             /* 0x02 */
66                 0x2A500000,             /* 0x03 */
67                 Q8_ADDR_UNDEFINED,      /* 0x04 */
68                 0x0D000000,             /* 0x05 */
69                 0x1B100000,             /* 0x06 */
70                 0x0E600000,             /* 0x07 */
71                 0x0E000000,             /* 0x08 */
72                 0x0E100000,             /* 0x09 */
73                 0x0E200000,             /* 0x0A */
74                 0x0E300000,             /* 0x0B */
75                 0x42000000,             /* 0x0C */
76                 0x41700000,             /* 0x0D */
77                 0x42100000,             /* 0x0E */
78                 0x34B00000,             /* 0x0F */
79                 0x40500000,             /* 0x10 */
80                 0x34000000,             /* 0x11 */
81                 0x34100000,             /* 0x12 */
82                 0x34200000,             /* 0x13 */
83                 0x34300000,             /* 0x14 */
84                 0x34500000,             /* 0x15 */
85                 0x34400000,             /* 0x16 */
86                 0x3C000000,             /* 0x17 */
87                 0x3C100000,             /* 0x18 */
88                 0x3C200000,             /* 0x19 */
89                 0x3C300000,             /* 0x1A */
90                 Q8_ADDR_UNDEFINED,      /* 0x1B */
91                 0x3C400000,             /* 0x1C */
92                 0x41000000,             /* 0x1D */
93                 Q8_ADDR_UNDEFINED,      /* 0x1E */
94                 0x0D100000,             /* 0x1F */
95                 Q8_ADDR_UNDEFINED,      /* 0x20 */
96                 0x77300000,             /* 0x21 */
97                 0x41600000,             /* 0x22 */
98                 Q8_ADDR_UNDEFINED,      /* 0x23 */
99                 Q8_ADDR_UNDEFINED,      /* 0x24 */
100                 Q8_ADDR_UNDEFINED,      /* 0x25 */
101                 Q8_ADDR_UNDEFINED,      /* 0x26 */
102                 Q8_ADDR_UNDEFINED,      /* 0x27 */
103                 0x41700000,             /* 0x28 */
104                 Q8_ADDR_UNDEFINED,      /* 0x29 */
105                 0x08900000,             /* 0x2A */
106                 0x70A00000,             /* 0x2B */
107                 0x70B00000,             /* 0x2C */
108                 0x70C00000,             /* 0x2D */
109                 0x08D00000,             /* 0x2E */
110                 0x08E00000,             /* 0x2F */
111                 0x70F00000,             /* 0x30 */
112                 0x40500000,             /* 0x31 */
113                 0x42000000,             /* 0x32 */
114                 0x42100000,             /* 0x33 */
115                 Q8_ADDR_UNDEFINED,      /* 0x34 */
116                 0x08800000,             /* 0x35 */
117                 0x09100000,             /* 0x36 */
118                 0x71200000,             /* 0x37 */
119                 0x40600000,             /* 0x38 */
120                 Q8_ADDR_UNDEFINED,      /* 0x39 */
121                 0x71800000,             /* 0x3A */
122                 0x19900000,             /* 0x3B */
123                 0x1A900000,             /* 0x3C */
124                 Q8_ADDR_UNDEFINED,      /* 0x3D */
125                 0x34600000,             /* 0x3E */
126                 Q8_ADDR_UNDEFINED,      /* 0x3F */
127         };
128
129 /*
130  * Address Translation Table for CRB to offsets from PCI BAR0
131  */
132 typedef struct _crb_to_pci {
133         uint32_t crb_addr;
134         uint32_t pci_addr;
135 } crb_to_pci_t;
136
137 static crb_to_pci_t crbinit_to_pciaddr[] = {
138         {(0x088 << 20), (0x035 << 20)},
139         {(0x089 << 20), (0x02A << 20)},
140         {(0x08D << 20), (0x02E << 20)},
141         {(0x08E << 20), (0x02F << 20)},
142         {(0x0C6 << 20), (0x023 << 20)},
143         {(0x0C7 << 20), (0x024 << 20)},
144         {(0x0C8 << 20), (0x025 << 20)},
145         {(0x0D0 << 20), (0x005 << 20)},
146         {(0x0D1 << 20), (0x01F << 20)},
147         {(0x0E0 << 20), (0x008 << 20)},
148         {(0x0E1 << 20), (0x009 << 20)},
149         {(0x0E2 << 20), (0x00A << 20)},
150         {(0x0E3 << 20), (0x00B << 20)},
151         {(0x0E6 << 20), (0x007 << 20)},
152         {(0x199 << 20), (0x03B << 20)},
153         {(0x1B1 << 20), (0x006 << 20)},
154         {(0x295 << 20), (0x002 << 20)},
155         {(0x29A << 20), (0x000 << 20)},
156         {(0x2A5 << 20), (0x003 << 20)},
157         {(0x340 << 20), (0x011 << 20)},
158         {(0x341 << 20), (0x012 << 20)},
159         {(0x342 << 20), (0x013 << 20)},
160         {(0x343 << 20), (0x014 << 20)},
161         {(0x344 << 20), (0x016 << 20)},
162         {(0x345 << 20), (0x015 << 20)},
163         {(0x3C0 << 20), (0x017 << 20)},
164         {(0x3C1 << 20), (0x018 << 20)},
165         {(0x3C2 << 20), (0x019 << 20)},
166         {(0x3C3 << 20), (0x01A << 20)},
167         {(0x3C4 << 20), (0x01C << 20)},
168         {(0x3C5 << 20), (0x01B << 20)},
169         {(0x405 << 20), (0x031 << 20)},
170         {(0x406 << 20), (0x038 << 20)},
171         {(0x410 << 20), (0x01D << 20)},
172         {(0x416 << 20), (0x022 << 20)},
173         {(0x417 << 20), (0x028 << 20)},
174         {(0x420 << 20), (0x032 << 20)},
175         {(0x421 << 20), (0x033 << 20)},
176         {(0x700 << 20), (0x00C << 20)},
177         {(0x701 << 20), (0x00D << 20)},
178         {(0x702 << 20), (0x00E << 20)},
179         {(0x703 << 20), (0x00F << 20)},
180         {(0x704 << 20), (0x010 << 20)},
181         {(0x70A << 20), (0x02B << 20)},
182         {(0x70B << 20), (0x02C << 20)},
183         {(0x70C << 20), (0x02D << 20)},
184         {(0x70F << 20), (0x030 << 20)},
185         {(0x718 << 20), (0x03A << 20)},
186         {(0x758 << 20), (0x026 << 20)},
187         {(0x759 << 20), (0x027 << 20)},
188         {(0x773 << 20), (0x001 << 20)}
189 };
190  
191 #define Q8_INVALID_ADDRESS      (-1)
192 #define Q8_ADDR_MASK            (0xFFF << 20)
193
194 typedef struct _addr_val {
195         uint32_t addr;
196         uint32_t value;
197         uint32_t pci_addr;
198         uint32_t ind_addr;
199 } addr_val_t;
200
201 /*
202  * Name: qla_rdwr_indreg32
203  * Function: Read/Write an Indirect Register
204  */
205 int
206 qla_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd)
207 {
208         uint32_t offset;
209         int count = 100;
210
211         offset = (addr & 0xFFF00000) >> 20;
212
213         if (offset > 0x3F) {
214                 device_printf(ha->pci_dev, "%s: invalid addr 0x%08x\n",
215                         __func__, addr);
216                 return -1;
217         }
218
219         offset = indirect_to_base_map[offset];
220         if (offset == Q8_ADDR_UNDEFINED) {
221                 device_printf(ha->pci_dev, "%s: undefined map 0x%08x\n",
222                         __func__, addr);
223                 return -1;
224         }
225
226         offset = offset | (addr & 0x000F0000);
227
228         if (qla_sem_lock(ha, Q8_SEM7_LOCK, 0, 0)) {
229                 device_printf(ha->pci_dev, "%s: SEM7_LOCK failed\n", __func__);
230                 return (-1);
231         }
232
233         WRITE_OFFSET32(ha, Q8_CRB_WINDOW_2M, offset);
234
235         while (offset != (READ_OFFSET32(ha, Q8_CRB_WINDOW_2M))) {
236                 count--;
237                 if (!count) {
238                         qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
239                         return -1;
240                 }
241
242                 qla_mdelay(__func__, 1);
243         }
244
245         if (rd) {
246                 *val = READ_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000));
247         } else {
248                 WRITE_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000), *val);
249         } 
250
251         qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
252         return 0;
253 }
254
255 /*
256  * Name: qla_rdwr_offchip_mem
257  * Function: Read/Write OffChip Memory
258  */
259 static int
260 qla_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, offchip_mem_val_t *val,
261         uint32_t rd)
262 {
263         uint32_t count = 100;
264         uint32_t data;
265
266         WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_LO, (uint32_t)addr);
267         WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_HI, (uint32_t)(addr >> 32));
268
269         if (!rd) {
270                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_LO, val->data_lo);
271                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_HI, val->data_hi);
272                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_ULO, val->data_ulo);
273                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_UHI, val->data_uhi);
274                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x07); /* Write */
275         } else {
276                 WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x03); /* Read */
277         }
278
279         while (count--) {
280                 data = READ_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL);
281                 if (!(data & BIT_3)) {
282                         if (rd) {
283                                 val->data_lo = READ_OFFSET32(ha, \
284                                                 Q8_MIU_TEST_AGT_RDDATA_LO);
285                                 val->data_hi = READ_OFFSET32(ha, \
286                                                 Q8_MIU_TEST_AGT_RDDATA_HI);
287                                 val->data_ulo = READ_OFFSET32(ha, \
288                                                 Q8_MIU_TEST_AGT_RDDATA_ULO);
289                                 val->data_uhi = READ_OFFSET32(ha, \
290                                                 Q8_MIU_TEST_AGT_RDDATA_UHI);
291                         }
292                         return 0;
293                 } else 
294                         qla_mdelay(__func__, 1);
295         }
296         
297         device_printf(ha->pci_dev, "%s: failed[0x%08x]\n", __func__, data);
298         return (-1);
299 }
300
301 /*
302  * Name: qla_rd_flash32
303  * Function: Read Flash Memory
304  */
305 int
306 qla_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
307 {
308         uint32_t val;
309         uint32_t count = 100;
310
311         if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
312                 device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
313                 return (-1);
314         }
315         WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
316
317         val = addr;
318         qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
319         val = 0;
320         qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
321         val = 3;
322         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
323
324         QLA_USEC_DELAY(100);
325
326         val = ROM_OPCODE_FAST_RD;
327         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
328
329         while (!((val = READ_OFFSET32(ha, Q8_ROM_STATUS)) & BIT_1)) {
330                 count--;
331                 if (!count) {
332                         qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
333                         return -1;
334                 }
335         }
336
337         val = 0;
338         qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
339         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
340
341         QLA_USEC_DELAY(100);
342
343         qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, data, 1);
344
345         qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
346         return 0;
347 }
348
349 static int
350 qla_p3p_sem_lock2(qla_host_t *ha)
351 {
352         if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
353                 device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
354                 return (-1);
355         }
356         WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
357         return (0);
358 }
359
360 /*
361  * Name: qla_int_to_pci_addr_map
362  * Function: Convert's Internal(CRB) Address to Indirect Address
363  */
364 static uint32_t
365 qla_int_to_pci_addr_map(qla_host_t *ha, uint32_t int_addr)
366 {
367         uint32_t crb_to_pci_table_size, i;
368         uint32_t addr;
369
370         crb_to_pci_table_size = sizeof(crbinit_to_pciaddr)/sizeof(crb_to_pci_t);
371         addr = int_addr & Q8_ADDR_MASK;
372
373         for (i = 0; i < crb_to_pci_table_size; i++) {
374                 if (crbinit_to_pciaddr[i].crb_addr == addr) {
375                         addr = (int_addr & ~Q8_ADDR_MASK) |
376                                         crbinit_to_pciaddr[i].pci_addr;
377                         return (addr);
378                 }
379         }
380         return (Q8_INVALID_ADDRESS);
381 }
382
383 /*
384  * Name: qla_filter_pci_addr
385  * Function: Filter's out Indirect Addresses which are not writeable
386  */
387 static uint32_t
388 qla_filter_pci_addr(qla_host_t *ha, uint32_t addr)
389 {
390         if ((addr == Q8_INVALID_ADDRESS) ||
391                 (addr == 0x00112040) ||
392                 (addr == 0x00112048) ||
393                 ((addr & 0xFFFF0FFF) == 0x001100C4) ||
394                 ((addr & 0xFFFF0FFF) == 0x001100C8) ||
395                 ((addr & 0x0FF00000) == 0x00200000) ||
396                 (addr == 0x022021FC) ||
397                 (addr == 0x0330001C) ||
398                 (addr == 0x03300024) ||
399                 (addr == 0x033000A8) ||
400                 (addr == 0x033000C8) ||
401                 (addr == 0x033000BC) ||
402                 ((addr & 0x0FF00000) == 0x03A00000) ||
403                 (addr == 0x03B0001C))
404                 return (Q8_INVALID_ADDRESS);
405         else
406                 return (addr); 
407 }
408
409 /*
410  * Name: qla_crb_init
411  * Function: CRB Initialization - first step in the initialization after reset
412  *      Essentially reads the address/value pairs from address = 0x00 and
413  *      writes the value into address in the addr/value pair.
414  */
415 static int
416 qla_crb_init(qla_host_t *ha)
417 {
418         uint32_t val = 0, sig = 0;
419         uint32_t offset, count, i;
420         addr_val_t *addr_val_map, *avmap;
421
422         qla_rd_flash32(ha, 0, &sig);
423         QL_DPRINT2((ha->pci_dev, "%s: val[0] = 0x%08x\n", __func__, sig));
424
425         qla_rd_flash32(ha, 4, &val);
426         QL_DPRINT2((ha->pci_dev, "%s: val[4] = 0x%08x\n", __func__, val));
427
428         count = val >> 16;
429         offset = val & 0xFFFF;
430         offset = offset << 2;
431
432         QL_DPRINT2((ha->pci_dev, "%s: [sig,val]=[0x%08x, 0x%08x] %d pairs\n",
433                 __func__, sig, val, count));
434
435         addr_val_map = avmap = malloc((sizeof(addr_val_t) * count),
436                                         M_QLA8XXXBUF, M_NOWAIT);
437
438         if (addr_val_map == NULL) {
439                 device_printf(ha->pci_dev, "%s: malloc failed\n", __func__);
440                 return (-1);
441         }
442         memset(avmap, 0, (sizeof(addr_val_t) * count));
443
444         count = count << 1;
445         for (i = 0; i < count; ) {
446                 qla_rd_flash32(ha, (offset + (i * 4)), &avmap->value);
447                 i++;
448                 qla_rd_flash32(ha, (offset + (i * 4)), &avmap->addr);
449                 i++;
450
451                 avmap->pci_addr = qla_int_to_pci_addr_map(ha, avmap->addr);
452                 avmap->ind_addr = qla_filter_pci_addr(ha, avmap->pci_addr);
453
454                 QL_DPRINT2((ha->pci_dev,
455                         "%s: [0x%02x][0x%08x:0x%08x:0x%08x] 0x%08x\n",
456                         __func__, (i >> 1), avmap->addr, avmap->pci_addr,
457                         avmap->ind_addr, avmap->value));
458
459                 if (avmap->ind_addr != Q8_INVALID_ADDRESS) {
460                         qla_rdwr_indreg32(ha, avmap->ind_addr, &avmap->value,0);
461                         qla_mdelay(__func__, 1);
462                 }
463                 avmap++;
464         }
465
466         free (addr_val_map, M_QLA8XXXBUF);
467         return (0);
468 }
469
470 /*
471  * Name: qla_init_peg_regs
472  * Function: Protocol Engine Register Initialization
473  */
474 static void
475 qla_init_peg_regs(qla_host_t *ha)
476 {
477         WRITE_OFFSET32(ha, Q8_PEG_D_RESET1, 0x001E);
478         WRITE_OFFSET32(ha, Q8_PEG_D_RESET2, 0x0008);
479         WRITE_OFFSET32(ha, Q8_PEG_I_RESET, 0x0008);
480         WRITE_OFFSET32(ha, Q8_PEG_0_CLR1, 0x0000);
481         WRITE_OFFSET32(ha, Q8_PEG_0_CLR2, 0x0000);
482         WRITE_OFFSET32(ha, Q8_PEG_1_CLR1, 0x0000);
483         WRITE_OFFSET32(ha, Q8_PEG_1_CLR2, 0x0000);
484         WRITE_OFFSET32(ha, Q8_PEG_2_CLR1, 0x0000);
485         WRITE_OFFSET32(ha, Q8_PEG_2_CLR2, 0x0000);
486         WRITE_OFFSET32(ha, Q8_PEG_3_CLR1, 0x0000);
487         WRITE_OFFSET32(ha, Q8_PEG_3_CLR2, 0x0000);
488         WRITE_OFFSET32(ha, Q8_PEG_4_CLR1, 0x0000);
489         WRITE_OFFSET32(ha, Q8_PEG_4_CLR2, 0x0000);
490 }
491
492 /*
493  * Name: qla_load_fw_from_flash
494  * Function: Reads the Bootloader from Flash and Loads into Offchip Memory
495  */
496 static void
497 qla_load_fw_from_flash(qla_host_t *ha)
498 {
499         uint64_t mem_off        = 0x10000;
500         uint32_t flash_off      = 0x10000;
501         uint32_t count;
502         offchip_mem_val_t val;
503
504
505         /* only bootloader needs to be loaded into memory */
506         for (count = 0; count < 0x20000 ; ) {
507                 qla_rd_flash32(ha, flash_off, &val.data_lo);
508                 count = count + 4;
509                 flash_off = flash_off + 4;
510
511                 qla_rd_flash32(ha, flash_off, &val.data_hi);
512                 count = count + 4;
513                 flash_off = flash_off + 4;
514
515                 qla_rd_flash32(ha, flash_off, &val.data_ulo);
516                 count = count + 4;
517                 flash_off = flash_off + 4;
518
519                 qla_rd_flash32(ha, flash_off, &val.data_uhi);
520                 count = count + 4;
521                 flash_off = flash_off + 4;
522
523                 qla_rdwr_offchip_mem(ha, mem_off, &val, 0);
524
525                 mem_off = mem_off + 16;
526         }
527         return;
528 }
529
530 /*
531  * Name: qla_init_from_flash
532  * Function: Performs Initialization which consists of the following sequence
533  *      - reset
534  *      - CRB Init
535  *      - Peg Init
536  *      - Read the Bootloader from Flash and Load into Offchip Memory
537  *      - Kick start the bootloader which loads the rest of the firmware
538  *              and performs the remaining steps in the initialization process.
539  */
540 static int
541 qla_init_from_flash(qla_host_t *ha)
542 {
543         uint32_t delay = 300;
544         uint32_t data;
545
546         qla_hw_reset(ha);
547         qla_mdelay(__func__, 100);
548
549         qla_crb_init(ha);
550         qla_mdelay(__func__, 10);
551
552         qla_init_peg_regs(ha);
553         qla_mdelay(__func__, 10);
554
555         qla_load_fw_from_flash(ha);
556         
557         WRITE_OFFSET32(ha, Q8_CMDPEG_STATE, 0x00000000);
558         WRITE_OFFSET32(ha, Q8_PEG_0_RESET, 0x00001020);
559         WRITE_OFFSET32(ha, Q8_ASIC_RESET, 0x0080001E);
560         qla_mdelay(__func__, 100);
561
562         do {
563                 data = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
564
565                 QL_DPRINT2((ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
566                                 __func__, ha->pci_func, data));
567                 if (data == CMDPEG_PHAN_INIT_COMPLETE) {
568                         QL_DPRINT2((ha->pci_dev,
569                                 "%s: func[%d] init complete\n",
570                                 __func__, ha->pci_func));
571                         return(0);
572                 }
573                 qla_mdelay(__func__, 100);
574         } while (delay--);
575
576         device_printf(ha->pci_dev,
577                 "%s: func[%d] Q8_PEG_HALT_STATUS1[0x%08x] STATUS2[0x%08x]"
578                 " HEARTBEAT[0x%08x] RCVPEG_STATE[0x%08x]"
579                 " CMDPEG_STATE[0x%08x]\n",
580                 __func__, ha->pci_func,
581                 (READ_OFFSET32(ha, Q8_PEG_HALT_STATUS1)),
582                 (READ_OFFSET32(ha, Q8_PEG_HALT_STATUS2)),
583                 (READ_OFFSET32(ha, Q8_FIRMWARE_HEARTBEAT)),
584                 (READ_OFFSET32(ha, Q8_RCVPEG_STATE)), data);
585         
586         return (-1);
587 }
588
589 /*
590  * Name: qla_init_hw
591  * Function: Initializes P3+ hardware.
592  */
593 int
594 qla_init_hw(qla_host_t *ha)
595 {
596         device_t dev;
597         int ret = 0;
598         uint32_t val, delay = 300;
599
600         dev = ha->pci_dev;
601
602         QL_DPRINT1((dev, "%s: enter\n", __func__));
603
604         qla_mdelay(__func__, 100);
605
606         if (ha->pci_func & 0x1) {
607                 while ((ha->pci_func & 0x1) && delay--) {
608                         val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
609
610                         if (val == CMDPEG_PHAN_INIT_COMPLETE) {
611                                 QL_DPRINT2((dev,
612                                         "%s: func = %d init complete\n",
613                                         __func__, ha->pci_func));
614                                 qla_mdelay(__func__, 100);
615                                 goto qla_init_exit;
616                         }
617                         qla_mdelay(__func__, 100);
618                 }
619                 return (-1);
620         }
621
622         val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
623
624         if (val != CMDPEG_PHAN_INIT_COMPLETE) {
625                 ret = qla_init_from_flash(ha);
626                 qla_mdelay(__func__, 100);
627         } else {
628                 ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
629                 ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
630                 ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
631
632                 if (qla_rd_flash32(ha, 0x100004, &val) == 0) {
633
634                         if (((val & 0xFF) != ha->fw_ver_major) ||
635                                 (((val >> 8) & 0xFF) != ha->fw_ver_minor) ||
636                                 (((val >> 16) & 0xFF) != ha->fw_ver_sub)) {
637
638                                 ret = qla_init_from_flash(ha);
639                                 qla_mdelay(__func__, 100);
640                         }
641                 }
642         }
643
644 qla_init_exit:
645         ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
646         ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
647         ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
648         ha->fw_ver_build = READ_OFFSET32(ha, Q8_FW_VER_BUILD);
649
650         return (ret);
651 }
652
653 static int
654 qla_wait_for_flash_busy(qla_host_t *ha)
655 {
656         uint32_t count = 100;
657         uint32_t val;
658
659         QLA_USEC_DELAY(100);
660
661         while (count--) {
662                 val = READ_OFFSET32(ha, Q8_ROM_STATUS);
663
664                 if (val & BIT_1)
665                         return 0;
666                 qla_mdelay(__func__, 1);
667         }
668         return -1;
669 }
670
671 static int
672 qla_flash_write_enable(qla_host_t *ha)
673 {
674         uint32_t val, rval;
675
676         val = 0;
677         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
678
679         val = ROM_OPCODE_WR_ENABLE;
680         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
681
682         rval = qla_wait_for_flash_busy(ha);
683
684         if (rval)
685                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
686
687         return (rval);
688 }
689
690 static int
691 qla_flash_unprotect(qla_host_t *ha)
692 {
693         uint32_t val, rval;
694
695         if (qla_flash_write_enable(ha) != 0) 
696                 return(-1);
697
698         val = 0;
699         qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
700
701         val = ROM_OPCODE_WR_STATUS_REG;
702         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
703         
704         rval = qla_wait_for_flash_busy(ha);
705
706         if (rval) {
707                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
708                 return rval;
709         }
710
711         if (qla_flash_write_enable(ha) != 0) 
712                 return(-1);
713
714         val = 0;
715         qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
716
717         val = ROM_OPCODE_WR_STATUS_REG;
718         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
719         
720         rval = qla_wait_for_flash_busy(ha);
721
722         if (rval)
723                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
724
725         return rval;
726 }
727
728 static int
729 qla_flash_protect(qla_host_t *ha)
730 {
731         uint32_t val, rval;
732
733         if (qla_flash_write_enable(ha) != 0) 
734                 return(-1);
735
736         val = 0x9C;
737         qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
738
739         val = ROM_OPCODE_WR_STATUS_REG;
740         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
741         
742         rval = qla_wait_for_flash_busy(ha);
743
744         if (rval)
745                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
746
747         return rval;
748 }
749
750 static uint32_t
751 qla_flash_get_status(qla_host_t *ha)
752 {
753         uint32_t count = 1000;
754         uint32_t val, rval;
755
756         while (count--) {
757                 val = 0;
758                 qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
759                         
760                 val = ROM_OPCODE_RD_STATUS_REG;
761                 qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
762         
763                 rval = qla_wait_for_flash_busy(ha);
764
765                 if (rval == 0) {
766                         qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
767
768                         if ((val & BIT_0) == 0)
769                                 return (val);
770                 }
771                 qla_mdelay(__func__, 1);
772         }
773         return -1;
774 }
775
776 static int
777 qla_wait_for_flash_unprotect(qla_host_t *ha)
778 {
779         uint32_t delay = 1000;
780
781         while (delay--) {
782
783                 if (qla_flash_get_status(ha) == 0)
784                         return 0;
785
786                 qla_mdelay(__func__, 1);
787         }
788
789         return -1;
790 }
791
792 static int
793 qla_wait_for_flash_protect(qla_host_t *ha)
794 {
795         uint32_t delay = 1000;
796
797         while (delay--) {
798
799                 if (qla_flash_get_status(ha) == 0x9C)
800                         return 0;
801
802                 qla_mdelay(__func__, 1);
803         }
804
805         return -1;
806 }
807
808 static int
809 qla_erase_flash_sector(qla_host_t *ha, uint32_t start)
810 {
811         uint32_t val;
812         int rval;
813
814         if (qla_flash_write_enable(ha) != 0) 
815                 return(-1);
816
817         val = start;
818         qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
819
820         val = 3;
821         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
822
823         val = ROM_OPCODE_SECTOR_ERASE;
824         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
825
826         rval = qla_wait_for_flash_busy(ha);
827
828         if (rval)
829                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
830         return rval;
831 }
832
833 #define Q8_FLASH_SECTOR_SIZE 0x10000
834 int
835 qla_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size)
836 {
837         int rval = 0;
838         uint32_t start;
839
840         if (off & (Q8_FLASH_SECTOR_SIZE -1))
841                 return -1;
842
843         if ((rval = qla_p3p_sem_lock2(ha)))
844                 goto qla_erase_flash_exit;
845
846         if ((rval = qla_flash_unprotect(ha)))
847                 goto qla_erase_flash_unlock_exit;
848
849         if ((rval = qla_wait_for_flash_unprotect(ha)))
850                 goto qla_erase_flash_unlock_exit;
851
852         for (start = off; start < (off + size); start = start + 0x10000) {
853                 if (qla_erase_flash_sector(ha, start)) {
854                         rval = -1;
855                         break;
856                 }
857         }
858
859         rval = qla_flash_protect(ha);
860
861 qla_erase_flash_unlock_exit:
862         qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
863
864 qla_erase_flash_exit:
865         return (rval);
866 }
867
868 static int
869 qla_flash_write32(qla_host_t *ha, uint32_t off, uint32_t data)
870 {
871         uint32_t val;
872         int rval = 0;
873
874         val = data;
875         qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
876
877         val = off;
878         qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
879
880         val = 3;
881         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
882
883         val = ROM_OPCODE_PROG_PAGE;
884         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
885
886         rval = qla_wait_for_flash_busy(ha);
887
888         if (rval)
889                 device_printf(ha->pci_dev, "%s: failed \n", __func__);
890
891         return rval;
892 }
893
894 static int
895 qla_flash_wait_for_write_complete(qla_host_t *ha)
896 {
897         uint32_t val, count = 1000;
898         int rval = 0;
899
900         while (count--) {
901
902                 val = 0;
903                 qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
904
905                 val = ROM_OPCODE_RD_STATUS_REG;
906                 qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
907
908                 
909                 rval = qla_wait_for_flash_busy(ha);
910
911                 if (rval == 0) {
912                         qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
913
914                         if ((val & BIT_0) == 0)
915                                 return (0);
916                 }
917                 qla_mdelay(__func__, 1);
918         }
919         return -1;
920 }
921
922 static int
923 qla_flash_write(qla_host_t *ha, uint32_t off, uint32_t data)
924 {
925         if (qla_flash_write_enable(ha) != 0) 
926                 return(-1);
927
928         if (qla_flash_write32(ha, off, data) != 0)
929                 return -1;
930
931         if (qla_flash_wait_for_write_complete(ha))
932                 return -1;
933
934         return 0;
935 }
936
937
938 static int
939 qla_flash_write_pattern(qla_host_t *ha, uint32_t off, uint32_t size,
940         uint32_t pattern)
941 {
942         int rval = 0;
943         uint32_t start;
944
945
946         if ((rval = qla_p3p_sem_lock2(ha)))
947                 goto qla_wr_pattern_exit;
948
949         if ((rval = qla_flash_unprotect(ha)))
950                 goto qla_wr_pattern_unlock_exit;
951
952         if ((rval = qla_wait_for_flash_unprotect(ha)))
953                 goto qla_wr_pattern_unlock_exit;
954
955         for (start = off; start < (off + size); start = start + 4) {
956                 if (qla_flash_write(ha, start, pattern)) {
957                         rval = -1;
958                         break;
959                 }
960         }
961
962         rval = qla_flash_protect(ha);
963
964         if (rval == 0)
965                 rval = qla_wait_for_flash_protect(ha);
966
967 qla_wr_pattern_unlock_exit:
968         qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
969
970 qla_wr_pattern_exit:
971         return (rval);
972 }
973
974 static int
975 qla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size,
976         void *data)
977 {
978         int rval = 0;
979         uint32_t start;
980         uint32_t *data32 = data;
981
982
983         if ((rval = qla_p3p_sem_lock2(ha)))
984                 goto qla_wr_pattern_exit;
985
986         if ((rval = qla_flash_unprotect(ha)))
987                 goto qla_wr_pattern_unlock_exit;
988
989         if ((rval = qla_wait_for_flash_unprotect(ha)))
990                 goto qla_wr_pattern_unlock_exit;
991
992         for (start = off; start < (off + size); start = start + 4) {
993                 
994                 if (*data32 != 0xFFFFFFFF) {
995                         if (qla_flash_write(ha, start, *data32)) {
996                                 rval = -1;
997                                 break;
998                         }
999                 }
1000                 data32++;
1001         }
1002
1003         rval = qla_flash_protect(ha);
1004
1005         if (rval == 0)
1006                 rval = qla_wait_for_flash_protect(ha);
1007
1008 qla_wr_pattern_unlock_exit:
1009         qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
1010
1011 qla_wr_pattern_exit:
1012         return (rval);
1013 }
1014  
1015 int
1016 qla_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf,
1017         uint32_t pattern)
1018 {
1019         int rval = 0;
1020         void *data;
1021
1022
1023         if (size == 0)
1024                 return 0;
1025
1026         size = size << 2;
1027
1028         if (buf == NULL) {
1029                 rval = qla_flash_write_pattern(ha, off, size, pattern);
1030                 return (rval);
1031         }
1032
1033         if ((data = malloc(size, M_QLA8XXXBUF, M_NOWAIT)) == NULL) {
1034                 device_printf(ha->pci_dev, "%s: malloc failed \n", __func__);
1035                 rval = -1;
1036                 goto qla_wr_flash_buffer_exit;
1037         }
1038
1039         if ((rval = copyin(buf, data, size))) {
1040                 device_printf(ha->pci_dev, "%s copyin failed\n", __func__);
1041                 goto qla_wr_flash_buffer_free_exit;
1042         }
1043
1044         rval = qla_flash_write_data(ha, off, size, data);
1045
1046 qla_wr_flash_buffer_free_exit:
1047         free(data, M_QLA8XXXBUF);
1048
1049 qla_wr_flash_buffer_exit:
1050         return (rval);
1051 }
1052