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
|
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
|