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