X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fqla2xxx%2Fqla_sup.c;h=5196a746d6b2f59d97dbab0ae3a901db2ceb018a;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=b1ccdee8d592a46b04c26a405530fd78852f3689;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index b1ccdee8d..5196a746d 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -17,27 +17,15 @@ * ******************************************************************************/ -#include "qla_os.h" #include "qla_def.h" +#include +#include + static uint16_t qla2x00_nvram_request(scsi_qla_host_t *, uint32_t); static void qla2x00_nv_deselect(scsi_qla_host_t *); static void qla2x00_nv_write(scsi_qla_host_t *, uint16_t); -uint8_t qla2x00_read_flash_byte(scsi_qla_host_t *, uint32_t); -static void qla2x00_write_flash_byte(scsi_qla_host_t *, uint32_t, uint8_t); -static uint8_t qla2x00_poll_flash(scsi_qla_host_t *ha, - uint32_t addr, uint8_t poll_data, uint8_t mid); -static uint8_t qla2x00_program_flash_address(scsi_qla_host_t *ha, - uint32_t addr, uint8_t data, uint8_t mid); -static uint8_t qla2x00_erase_flash_sector(scsi_qla_host_t *ha, - uint32_t addr, uint32_t sec_mask, uint8_t mid); - -uint8_t qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha); -uint16_t qla2x00_get_flash_version(scsi_qla_host_t *); -uint16_t qla2x00_get_flash_image(scsi_qla_host_t *ha, uint8_t *image); -uint16_t qla2x00_set_flash_image(scsi_qla_host_t *ha, uint8_t *image); - /* * NVRAM support routines @@ -279,435 +267,3 @@ qla2x00_nv_write(scsi_qla_host_t *ha, uint16_t data) RD_REG_WORD(®->nvram); /* PCI Posting. */ } -/* - * Flash support routines - */ - -/** - * qla2x00_flash_enable() - Setup flash for reading and writing. - * @ha: HA context - */ -void -qla2x00_flash_enable(scsi_qla_host_t *ha) -{ - uint16_t data; - device_reg_t *reg = ha->iobase; - - data = RD_REG_WORD(®->ctrl_status); - data |= CSR_FLASH_ENABLE; - WRT_REG_WORD(®->ctrl_status, data); - RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ -} - -/** - * qla2x00_flash_disable() - Disable flash and allow RISC to run. - * @ha: HA context - */ -void -qla2x00_flash_disable(scsi_qla_host_t *ha) -{ - uint16_t data; - device_reg_t *reg = ha->iobase; - - data = RD_REG_WORD(®->ctrl_status); - data &= ~(CSR_FLASH_ENABLE); - WRT_REG_WORD(®->ctrl_status, data); - RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ -} - -/** - * qla2x00_read_flash_byte() - Reads a byte from flash - * @ha: HA context - * @addr: Address in flash to read - * - * A word is read from the chip, but, only the lower byte is valid. - * - * Returns the byte read from flash @addr. - */ -uint8_t -qla2x00_read_flash_byte(scsi_qla_host_t *ha, uint32_t addr) -{ - uint16_t data; - uint16_t bank_select; - device_reg_t *reg = ha->iobase; - - /* Setup bit 16 of flash address. */ - bank_select = RD_REG_WORD(®->ctrl_status); - if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) { - bank_select |= CSR_FLASH_64K_BANK; - WRT_REG_WORD(®->ctrl_status, bank_select); - RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ - } else if (((addr & BIT_16) == 0) && - (bank_select & CSR_FLASH_64K_BANK)) { - bank_select &= ~(CSR_FLASH_64K_BANK); - WRT_REG_WORD(®->ctrl_status, bank_select); - RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ - } - - /* The ISP2312 v2 chip cannot access the FLASH registers via MMIO. */ - if (IS_QLA2312(ha) && ha->product_id[3] == 0x2 && ha->pio_address) { - uint16_t data2; - - reg = (device_reg_t *)ha->pio_address; - outw((uint16_t)addr, (unsigned long)(®->flash_address)); - do { - data = inw((unsigned long)(®->flash_data)); - barrier(); - cpu_relax(); - data2 = inw((unsigned long)(®->flash_data)); - } while (data != data2); - } else { - WRT_REG_WORD(®->flash_address, (uint16_t)addr); - data = qla2x00_debounce_register(®->flash_data); - } - - return ((uint8_t)data); -} - -/** - * qla2x00_write_flash_byte() - Write a byte to flash - * @ha: HA context - * @addr: Address in flash to write - * @data: Data to write - */ -static void -qla2x00_write_flash_byte(scsi_qla_host_t *ha, uint32_t addr, uint8_t data) -{ - uint16_t bank_select; - device_reg_t *reg = ha->iobase; - - /* Setup bit 16 of flash address. */ - bank_select = RD_REG_WORD(®->ctrl_status); - if ((addr & BIT_16) && ((bank_select & CSR_FLASH_64K_BANK) == 0)) { - bank_select |= CSR_FLASH_64K_BANK; - WRT_REG_WORD(®->ctrl_status, bank_select); - RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ - } else if (((addr & BIT_16) == 0) && - (bank_select & CSR_FLASH_64K_BANK)) { - bank_select &= ~(CSR_FLASH_64K_BANK); - WRT_REG_WORD(®->ctrl_status, bank_select); - RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ - } - - /* The ISP2312 v2 chip cannot access the FLASH registers via MMIO. */ - if (IS_QLA2312(ha) && ha->product_id[3] == 0x2 && ha->pio_address) { - reg = (device_reg_t *)ha->pio_address; - outw((uint16_t)addr, (unsigned long)(®->flash_address)); - outw((uint16_t)data, (unsigned long)(®->flash_data)); - } else { - WRT_REG_WORD(®->flash_address, (uint16_t)addr); - RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ - WRT_REG_WORD(®->flash_data, (uint16_t)data); - RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ - } -} - -/** - * qla2x00_poll_flash() - Polls flash for completion. - * @ha: HA context - * @addr: Address in flash to poll - * @poll_data: Data to be polled - * @mid: Flash manufacturer ID - * - * This function polls the device until bit 7 of what is read matches data - * bit 7 or until data bit 5 becomes a 1. If that hapens, the flash ROM timed - * out (a fatal error). The flash book recommeds reading bit 7 again after - * reading bit 5 as a 1. - * - * Returns 0 on success, else non-zero. - */ -static uint8_t -qla2x00_poll_flash(scsi_qla_host_t *ha, - uint32_t addr, uint8_t poll_data, uint8_t mid) -{ - uint8_t status; - uint8_t flash_data; - uint32_t cnt; - int failed_pass; - - status = 1; - failed_pass = 1; - - /* Wait for 30 seconds for command to finish. */ - poll_data &= BIT_7; - for (cnt = 3000000; cnt; cnt--) { - flash_data = qla2x00_read_flash_byte(ha, addr); - if ((flash_data & BIT_7) == poll_data) { - status = 0; - break; - } - - if (mid != 0x40 && mid != 0xda) { - if (flash_data & BIT_5) - failed_pass--; - if (failed_pass < 0) - break; - } - udelay(10); - barrier(); - } - return (status); -} - -/** - * qla2x00_program_flash_address() - Programs a flash address - * @ha: HA context - * @addr: Address in flash to program - * @data: Data to be written in flash - * @mid: Flash manufacturer ID - * - * Returns 0 on success, else non-zero. - */ -static uint8_t -qla2x00_program_flash_address(scsi_qla_host_t *ha, - uint32_t addr, uint8_t data, uint8_t mid) -{ - /* Write Program Command Sequence */ - qla2x00_write_flash_byte(ha, 0x5555, 0xaa); - qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); - qla2x00_write_flash_byte(ha, 0x5555, 0xa0); - qla2x00_write_flash_byte(ha, addr, data); - - /* Wait for write to complete. */ - return (qla2x00_poll_flash(ha, addr, data, mid)); -} - -/** - * qla2x00_erase_flash_sector() - Erase a flash sector. - * @ha: HA context - * @addr: Flash sector to erase - * @sec_mask: Sector address mask - * @mid: Flash manufacturer ID - * - * Returns 0 on success, else non-zero. - */ -static uint8_t -qla2x00_erase_flash_sector(scsi_qla_host_t *ha, - uint32_t addr, uint32_t sec_mask, uint8_t mid) -{ - /* Individual Sector Erase Command Sequence */ - qla2x00_write_flash_byte(ha, 0x5555, 0xaa); - qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); - qla2x00_write_flash_byte(ha, 0x5555, 0x80); - qla2x00_write_flash_byte(ha, 0x5555, 0xaa); - qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); - - if (mid == 0xda) - qla2x00_write_flash_byte(ha, addr & sec_mask, 0x10); - else - qla2x00_write_flash_byte(ha, addr & sec_mask, 0x30); - - udelay(150); - - /* Wait for erase to complete. */ - return (qla2x00_poll_flash(ha, addr, 0x80, mid)); -} - -/** - * qla2x00_get_flash_manufacturer() - Read manufacturer ID from flash chip. - * @ha: HA context - * - * Returns the manufacturer's ID read from the flash chip. - */ -uint8_t -qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha) -{ - uint8_t manuf_id; - - qla2x00_write_flash_byte(ha, 0x5555, 0xaa); - qla2x00_write_flash_byte(ha, 0x2aaa, 0x55); - qla2x00_write_flash_byte(ha, 0x5555, 0x90); - manuf_id = qla2x00_read_flash_byte(ha, 0x0001); - - return (manuf_id); -} - -/** - * qla2x00_get_flash_version() - Read version information from flash. - * @ha: HA context - * - * Returns QLA_SUCCESS on successful retrieval of flash version. - */ -uint16_t -qla2x00_get_flash_version(scsi_qla_host_t *ha) -{ - uint16_t ret = QLA_SUCCESS; - uint32_t loop_cnt = 1; /* this is for error exit only */ - uint32_t pcir_adr; - - /* The ISP2312 v2 chip cannot access the FLASH registers via MMIO. */ - if (IS_QLA2312(ha) && ha->product_id[3] == 0x2 && !ha->pio_address) - ret = QLA_FUNCTION_FAILED; - - qla2x00_flash_enable(ha); - do { /* Loop once to provide quick error exit */ - /* Match signature */ - if (!(qla2x00_read_flash_byte(ha, 0) == 0x55 && - qla2x00_read_flash_byte(ha, 1) == 0xaa)) { - /* No signature */ - DEBUG2(printk("scsi(%ld): No matching FLASH " - "signature.\n", ha->host_no)); - ret = QLA_FUNCTION_FAILED; - break; - } - - pcir_adr = qla2x00_read_flash_byte(ha, 0x18) & 0xff; - - /* validate signature of PCI data structure */ - if ((qla2x00_read_flash_byte(ha, pcir_adr)) == 'P' && - (qla2x00_read_flash_byte(ha, pcir_adr + 1)) == 'C' && - (qla2x00_read_flash_byte(ha, pcir_adr + 2)) == 'I' && - (qla2x00_read_flash_byte(ha, pcir_adr + 3)) == 'R') { - - /* Read version */ - ha->optrom_minor = - qla2x00_read_flash_byte(ha, pcir_adr + 0x12); - ha->optrom_major = - qla2x00_read_flash_byte(ha, pcir_adr + 0x13); - DEBUG3(printk("%s(): got %d.%d.\n", - __func__, ha->optrom_major, ha->optrom_minor)); - } else { - /* error */ - DEBUG2(printk("%s(): PCI data struct not found. " - "pcir_adr=%x.\n", - __func__, pcir_adr)); - ret = QLA_FUNCTION_FAILED; - break; - } - - } while (--loop_cnt); - qla2x00_flash_disable(ha); - - return (ret); -} - -/** - * qla2x00_get_flash_image() - Read image from flash chip. - * @ha: HA context - * @image: Buffer to receive flash image - * - * Returns 0 on success, else non-zero. - */ -uint16_t -qla2x00_get_flash_image(scsi_qla_host_t *ha, uint8_t *image) -{ - uint32_t addr; - uint32_t midpoint; - uint8_t *data; - device_reg_t *reg = ha->iobase; - - midpoint = FLASH_IMAGE_SIZE / 2; - - qla2x00_flash_enable(ha); - WRT_REG_WORD(®->nvram, 0); - RD_REG_WORD(®->nvram); /* PCI Posting. */ - for (addr = 0, data = image; addr < FLASH_IMAGE_SIZE; addr++, data++) { - if (addr == midpoint) - WRT_REG_WORD(®->nvram, NVR_SELECT); - - *data = qla2x00_read_flash_byte(ha, addr); - } - qla2x00_flash_disable(ha); - - return (0); -} - -/** - * qla2x00_set_flash_image() - Write image to flash chip. - * @ha: HA context - * @image: Source image to write to flash - * - * Returns 0 on success, else non-zero. - */ -uint16_t -qla2x00_set_flash_image(scsi_qla_host_t *ha, uint8_t *image) -{ - uint16_t status; - uint32_t addr; - uint32_t midpoint; - uint32_t sec_mask; - uint32_t rest_addr; - uint8_t mid; - uint8_t sec_number; - uint8_t data; - device_reg_t *reg = ha->iobase; - - status = 0; - sec_number = 0; - - /* Reset ISP chip. */ - WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); - RD_REG_WORD(®->ctrl_status); /* PCI Posting. */ - - qla2x00_flash_enable(ha); - do { /* Loop once to provide quick error exit */ - /* Structure of flash memory based on manufacturer */ - mid = qla2x00_get_flash_manufacturer(ha); - if (mid == 0x6d) { - // Am29LV001 part - rest_addr = 0x1fff; - sec_mask = 0x1e000; - } else if (mid == 0x40) { - // Mostel v29c51001 part - rest_addr = 0x1ff; - sec_mask = 0x1fe00; - } else if (mid == 0xbf) { - // SST39sf10 part - rest_addr = 0xfff; - sec_mask = 0x1f000; - } else if (mid == 0xda) { - // Winbond W29EE011 part - rest_addr = 0x7f; - sec_mask = 0x1ff80; - addr = 0; - if (qla2x00_erase_flash_sector(ha, addr, sec_mask, - mid)) { - status = 1; - break; - } - } else { - // Am29F010 part - rest_addr = 0x3fff; - sec_mask = 0x1c000; - } - - midpoint = FLASH_IMAGE_SIZE / 2; - for (addr = 0; addr < FLASH_IMAGE_SIZE; addr++) { - data = *image++; - /* Are we at the beginning of a sector? */ - if (!(addr & rest_addr)) { - if (addr == midpoint) - WRT_REG_WORD(®->nvram, NVR_SELECT); - - /* Then erase it */ - if (qla2x00_erase_flash_sector(ha, addr, - sec_mask, mid)) { - status = 1; - break; - } - - sec_number++; - } - if (mid == 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, - mid)) { - status = 1; - break; - } - } - } while (0); - - qla2x00_flash_disable(ha); - - return (status); -}