qla_sup.c
来自「linux 内核源代码」· C语言 代码 · 共 2,224 行 · 第 1/4 页
C
2,224 行
break; } else if (flash_id == 0x3e) { /* * Am29LV008b part - 64kb sector size with * 32kb,8kb,8kb,16kb sector at memory address * h0xf0000. */ rest_addr = 0xffff; sec_mask = 0x10000; break; } else if (flash_id == 0x20 || flash_id == 0x6e) { /* * Am29LV010 part or AM29f010 - 16kb sector * size. */ rest_addr = 0x3fff; sec_mask = 0x1c000; break; } else if (flash_id == 0x6d) { /* Am29LV001 part - 8kb sector size. */ rest_addr = 0x1fff; sec_mask = 0x1e000; break; } default: /* Default to 16 kb sector size. */ rest_addr = 0x3fff; sec_mask = 0x1c000; break; }update_flash: if (IS_QLA2322(ha) || IS_QLA6322(ha)) { if (qla2x00_erase_flash(ha, man_id, flash_id)) { rval = QLA_FUNCTION_FAILED; break; } } for (addr = offset, liter = 0; liter < length; liter++, addr++) { data = buf[liter]; /* Are we at the beginning of a sector? */ if ((addr & rest_addr) == 0) { if (IS_QLA2322(ha) || IS_QLA6322(ha)) { if (addr >= 0x10000UL) { if (((addr >> 12) & 0xf0) && ((man_id == 0x01 && flash_id == 0x3e) || (man_id == 0x20 && flash_id == 0xd2))) { sec_number++; if (sec_number == 1) { rest_addr = 0x7fff; sec_mask = 0x18000; } else if ( sec_number == 2 || sec_number == 3) { rest_addr = 0x1fff; sec_mask = 0x1e000; } else if ( sec_number == 4) { rest_addr = 0x3fff; sec_mask = 0x1c000; } } } } else if (addr == ha->optrom_size / 2) { WRT_REG_WORD(®->nvram, NVR_SELECT); RD_REG_WORD(®->nvram); } if (flash_id == 0xda && man_id == 0xc1) { qla2x00_write_flash_byte(ha, 0x5555, 0xaa); qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); qla2x00_write_flash_byte(ha, 0x5555, 0xa0); } else if (!IS_QLA2322(ha) && !IS_QLA6322(ha)) { /* Then erase it */ if (qla2x00_erase_flash_sector(ha, addr, sec_mask, man_id, flash_id)) { rval = QLA_FUNCTION_FAILED; break; } if (man_id == 0x01 && flash_id == 0x6d) sec_number++; } } if (man_id == 0x01 && flash_id == 0x6d) { if (sec_number == 1 && addr == (rest_addr - 1)) { rest_addr = 0x0fff; sec_mask = 0x1f000; } else if (sec_number == 3 && (addr & 0x7ffe)) { rest_addr = 0x3fff; sec_mask = 0x1c000; } } if (qla2x00_program_flash_address(ha, addr, data, man_id, flash_id)) { rval = QLA_FUNCTION_FAILED; break; } cond_resched(); } } while (0); qla2x00_flash_disable(ha); /* Resume HBA. */ qla2x00_resume_hba(ha); return rval;}uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, uint32_t offset, uint32_t length){ /* Suspend HBA. */ scsi_block_requests(ha->host); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with read. */ qla24xx_read_flash_data(ha, (uint32_t *)buf, offset >> 2, length >> 2); /* Resume HBA. */ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); scsi_unblock_requests(ha->host); return buf;}intqla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, uint32_t offset, uint32_t length){ int rval; /* Suspend HBA. */ scsi_block_requests(ha->host); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with write. */ rval = qla24xx_write_flash_data(ha, (uint32_t *)buf, offset >> 2, length >> 2); /* Resume HBA -- RISC reset needed. */ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); qla2xxx_wake_dpc(ha); qla2x00_wait_for_hba_online(ha); scsi_unblock_requests(ha->host); return rval;}uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, uint32_t offset, uint32_t length){ int rval; dma_addr_t optrom_dma; void *optrom; uint8_t *pbuf; uint32_t faddr, left, burst; if (offset & 0xfff) goto slow_read; if (length < OPTROM_BURST_SIZE) goto slow_read; optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, &optrom_dma, GFP_KERNEL); if (!optrom) { qla_printk(KERN_DEBUG, ha, "Unable to allocate memory for optrom burst read " "(%x KB).\n", OPTROM_BURST_SIZE / 1024); goto slow_read; } pbuf = buf; faddr = offset >> 2; left = length >> 2; burst = OPTROM_BURST_DWORDS; while (left != 0) { if (burst > left) burst = left; rval = qla2x00_dump_ram(ha, optrom_dma, flash_data_to_access_addr(faddr), burst); if (rval) { qla_printk(KERN_WARNING, ha, "Unable to burst-read optrom segment " "(%x/%x/%llx).\n", rval, flash_data_to_access_addr(faddr), (unsigned long long)optrom_dma); qla_printk(KERN_WARNING, ha, "Reverting to slow-read.\n"); dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, optrom, optrom_dma); goto slow_read; } memcpy(pbuf, optrom, burst * 4); left -= burst; faddr += burst; pbuf += burst * 4; } dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, optrom, optrom_dma); return buf;slow_read: return qla24xx_read_optrom_data(ha, buf, offset, length);}/** * qla2x00_get_fcode_version() - Determine an FCODE image's version. * @ha: HA context * @pcids: Pointer to the FCODE PCI data structure * * The process of retrieving the FCODE version information is at best * described as interesting. * * Within the first 100h bytes of the image an ASCII string is present * which contains several pieces of information including the FCODE * version. Unfortunately it seems the only reliable way to retrieve * the version is by scanning for another sentinel within the string, * the FCODE build date: * * ... 2.00.02 10/17/02 ... * * Returns QLA_SUCCESS on successful retrieval of version. */static voidqla2x00_get_fcode_version(scsi_qla_host_t *ha, uint32_t pcids){ int ret = QLA_FUNCTION_FAILED; uint32_t istart, iend, iter, vend; uint8_t do_next, rbyte, *vbyte; memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); /* Skip the PCI data structure. */ istart = pcids + ((qla2x00_read_flash_byte(ha, pcids + 0x0B) << 8) | qla2x00_read_flash_byte(ha, pcids + 0x0A)); iend = istart + 0x100; do { /* Scan for the sentinel date string...eeewww. */ do_next = 0; iter = istart; while ((iter < iend) && !do_next) { iter++; if (qla2x00_read_flash_byte(ha, iter) == '/') { if (qla2x00_read_flash_byte(ha, iter + 2) == '/') do_next++; else if (qla2x00_read_flash_byte(ha, iter + 3) == '/') do_next++; } } if (!do_next) break; /* Backtrack to previous ' ' (space). */ do_next = 0; while ((iter > istart) && !do_next) { iter--; if (qla2x00_read_flash_byte(ha, iter) == ' ') do_next++; } if (!do_next) break; /* * Mark end of version tag, and find previous ' ' (space) or * string length (recent FCODE images -- major hack ahead!!!). */ vend = iter - 1; do_next = 0; while ((iter > istart) && !do_next) { iter--; rbyte = qla2x00_read_flash_byte(ha, iter); if (rbyte == ' ' || rbyte == 0xd || rbyte == 0x10) do_next++; } if (!do_next) break; /* Mark beginning of version tag, and copy data. */ iter++; if ((vend - iter) && ((vend - iter) < sizeof(ha->fcode_revision))) { vbyte = ha->fcode_revision; while (iter <= vend) { *vbyte++ = qla2x00_read_flash_byte(ha, iter); iter++; } ret = QLA_SUCCESS; } } while (0); if (ret != QLA_SUCCESS) memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision));}intqla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf){ int ret = QLA_SUCCESS; uint8_t code_type, last_image; uint32_t pcihdr, pcids; uint8_t *dbyte; uint16_t *dcode; if (!ha->pio_address || !mbuf) return QLA_FUNCTION_FAILED; memset(ha->bios_revision, 0, sizeof(ha->bios_revision)); memset(ha->efi_revision, 0, sizeof(ha->efi_revision)); memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); qla2x00_flash_enable(ha); /* Begin with first PCI expansion ROM header. */ pcihdr = 0; last_image = 1; do { /* Verify PCI expansion ROM header. */ if (qla2x00_read_flash_byte(ha, pcihdr) != 0x55 || qla2x00_read_flash_byte(ha, pcihdr + 0x01) != 0xaa) { /* No signature */ DEBUG2(printk("scsi(%ld): No matching ROM " "signature.\n", ha->host_no)); ret = QLA_FUNCTION_FAILED; break; } /* Locate PCI data structure. */ pcids = pcihdr + ((qla2x00_read_flash_byte(ha, pcihdr + 0x19) << 8) | qla2x00_read_flash_byte(ha, pcihdr + 0x18)); /* Validate signature of PCI data structure. */ if (qla2x00_read_flash_byte(ha, pcids) != 'P' || qla2x00_read_flash_byte(ha, pcids + 0x1) != 'C' || qla2x00_read_flash_byte(ha, pcids + 0x2) != 'I' || qla2x00_read_flash_byte(ha, pcids + 0x3) != 'R') { /* Incorrect header. */ DEBUG2(printk("%s(): PCI data struct not found " "pcir_adr=%x.\n", __func__, pcids)); ret = QLA_FUNCTION_FAILED; break; } /* Read version */ code_type = qla2x00_read_flash_byte(ha, pcids + 0x14); switch (code_type) { case ROM_CODE_TYPE_BIOS: /* Intel x86, PC-AT compatible. */ ha->bios_revision[0] = qla2x00_read_flash_byte(ha, pcids + 0x12); ha->bios_revision[1] = qla2x00_read_flash_byte(ha, pcids + 0x13); DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__, ha->bios_revision[1], ha->bios_revision[0])); break; case ROM_CODE_TYPE_FCODE: /* Open Firmware standard for PCI (FCode). */ /* Eeeewww... */ qla2x00_get_fcode_version(ha, pcids); break; case ROM_CODE_TYPE_EFI: /* Extensible Firmware Interface (EFI). */ ha->efi_revision[0] = qla2x00_read_flash_byte(ha, pcids + 0x12); ha->efi_revision[1] = qla2x00_read_flash_byte(ha, pcids + 0x13); DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__, ha->efi_revision[1], ha->efi_revision[0])); break; default: DEBUG2(printk("%s(): Unrecognized code type %x at " "pcids %x.\n", __func__, code_type, pcids)); break; } last_image = qla2x00_read_flash_byte(ha, pcids + 0x15) & BIT_7; /* Locate next PCI expansion ROM. */ pcihdr += ((qla2x00_read_flash_byte(ha, pcids + 0x11) << 8) | qla2x00_read_flash_byte(ha, pcids + 0x10)) * 512; } while (!last_image); if (IS_QLA2322(ha)) { /* Read firmware image information. */ memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); dbyte = mbuf; memset(dbyte, 0, 8); dcode = (uint16_t *)dbyte; qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10, 8); DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", __func__, ha->host_no)); DEBUG3(qla2x00_dump_buffer((uint8_t *)dbyte, 8)); if ((dcode[0] == 0xffff && dcode[1] == 0xffff && dcode[2] == 0xffff && dcode[3] == 0xffff) || (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && dcode[3] == 0)) { DEBUG2(printk("%s(): Unrecognized fw revision at " "%x.\n", __func__, FA_RISC_CODE_ADDR * 4)); } else { /* values are in big endian */ ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; ha->fw_revision[1] = dbyte[2] << 16 | dbyte[3]; ha->fw_revision[2] = dbyte[4] << 16 | dbyte[5]; } } qla2x00_flash_disable(ha); return ret;}intqla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf){ int ret = QLA_SUCCESS; uint32_t pcihdr, pcids; uint32_t *dcode; uint8_t *bcode; uint8_t code_type, last_image; int i; if (!mbuf) return QLA_FUNCTION_FAILED; memset(ha->bios_revision, 0, sizeof(ha->bios_revision)); memset(ha->efi_revision, 0, sizeof(ha->efi_revision)); memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); dcode = mbuf; /* Begin with first PCI expansion ROM header. */ pcihdr = 0; last_image = 1; do { /* Verify PCI expansion ROM header. */ qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20); bcode = mbuf + (pcihdr % 4); if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) { /* No signature */ DEBUG2(printk("scsi(%ld): No matching ROM " "signature.\n", ha->host_no)); ret = QLA_FUNCTION_FAILED; break; } /* Locate PCI data structure. */ pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20); bcode = mbuf + (pcihdr % 4); /* Validate signature of PCI data structure. */ if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || bcode[0x2] != 'I' || bcode[0x3] != 'R') { /* Incorrect header. */ DEBUG2(printk("%s(): PCI data struct not found " "pcir_adr=%x.\n", __func__, pcids)); ret = QLA_FUNCTION_FAILED; break; } /* Read version */ code_type = bcode[0x14]; switch (code_type) { case ROM_CODE_TYPE_BIOS: /* Intel x86, PC-AT compatible. */ ha->bios_revision[0] = bcode[0x12]; ha->bios_revision[1] = bcode[0x13]; DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__, ha->bios_revision[1], ha->bios_revision[0])); break; case ROM_CODE_TYPE_FCODE: /* Open Firmware standard for PCI (FCode). */ ha->fcode_revision[0] = bcode[0x12]; ha->fcode_revision[1] = bcode[0x13]; DEBUG3(printk("%s(): read FCODE %d.%d.\n", __func__, ha->fcode_revision[1], ha->fcode_revision[0])); break; case ROM_CODE_TYPE_EFI: /* Extensible Firmware Interface (EFI). */ ha->efi_revision[0] = bcode[0x12]; ha->efi_revision[1] = bcode[0x13]; DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__, ha->efi_revision[1], ha->efi_revision[0])); break; default: DEBUG2(printk("%s(): Unrecognized code type %x at " "pcids %x.\n", __func__, code_type, pcids)); break; } last_image = bcode[0x15] & BIT_7; /* Locate next PCI expansion ROM. */ pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512; } while (!last_image); /* Read firmware image information. */ memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); dcode = mbuf; qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4); for (i = 0; i < 4; i++) dcode[i] = be32_to_cpu(dcode[i]); if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && dcode[3] == 0)) { DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", __func__, FA_RISC_CODE_ADDR)); } else { ha->fw_revision[0] = dcode[0]; ha->fw_revision[1] = dcode[1]; ha->fw_revision[2] = dcode[2]; ha->fw_revision[3] = dcode[3]; } return ret;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?