diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 14:44:25 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 14:44:25 -0500 |
commit | 5f0b1437e0708772b6fecae5900c01c3b5f9b512 (patch) | |
tree | bcd923e305345178bc162ed8560d56a3af197224 /drivers/scsi/qla2xxx/qla_sup.c | |
parent | 574009c1a895aeeb85eaab29c235d75852b09eb8 (diff) | |
parent | 81b7bbd1932a04869d4c8635a75222dfc6089f96 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (97 commits)
[SCSI] zfcp: removed wrong comment
[SCSI] zfcp: use of uninitialized variable
[SCSI] zfcp: Invalid locking order
[SCSI] aic79xx: use dma_get_required_mask()
[SCSI] aic79xx: fix bracket mismatch in unused macro
[SCSI] BusLogic: Replace 'boolean' by 'bool'
[SCSI] advansys: clean up warnings
[SCSI] 53c7xx: brackets fix in uncompiled code
[SCSI] nsp_cs: remove old scsi code
[SCSI] aic79xx: make ahd_match_scb() static
[SCSI] DAC960: kmalloc->kzalloc/Casting cleanups
[SCSI] scsi_kmap_atomic_sg(): check that local irqs are disabled
[SCSI] Buslogic: local_irq_disable() is redundant after local_irq_save()
[SCSI] aic94xx: update for v28 firmware
[SCSI] scsi_error: Fix lost EH commands
[SCSI] aic94xx: Add default bus reset handler
[SCSI] aic94xx: Remove TMF result code munging
[SCSI] libsas: Add an LU reset mechanism to the error handler
[SCSI] libsas: Don't BUG when connecting two expanders via wide port
[SCSI] st: fix Tape dies if wrong block size used, bug 7919
...
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_sup.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_sup.c | 348 |
1 files changed, 347 insertions, 1 deletions
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 15390ad87456..ff1dd4175a7f 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -611,7 +611,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, | |||
611 | flash_conf_to_access_addr(0x0339), | 611 | flash_conf_to_access_addr(0x0339), |
612 | (fdata & 0xff00) | ((fdata << 16) & | 612 | (fdata & 0xff00) | ((fdata << 16) & |
613 | 0xff0000) | ((fdata >> 16) & 0xff)); | 613 | 0xff0000) | ((fdata >> 16) & 0xff)); |
614 | fdata = (faddr & sec_mask) << 2; | ||
615 | ret = qla24xx_write_flash_dword(ha, conf_addr, | 614 | ret = qla24xx_write_flash_dword(ha, conf_addr, |
616 | (fdata & 0xff00) |((fdata << 16) & | 615 | (fdata & 0xff00) |((fdata << 16) & |
617 | 0xff0000) | ((fdata >> 16) & 0xff)); | 616 | 0xff0000) | ((fdata >> 16) & 0xff)); |
@@ -1383,6 +1382,29 @@ qla2x00_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id, | |||
1383 | qla2x00_write_flash_byte(ha, 0x5555, 0xf0); | 1382 | qla2x00_write_flash_byte(ha, 0x5555, 0xf0); |
1384 | } | 1383 | } |
1385 | 1384 | ||
1385 | static void | ||
1386 | qla2x00_read_flash_data(scsi_qla_host_t *ha, uint8_t *tmp_buf, uint32_t saddr, | ||
1387 | uint32_t length) | ||
1388 | { | ||
1389 | struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; | ||
1390 | uint32_t midpoint, ilength; | ||
1391 | uint8_t data; | ||
1392 | |||
1393 | midpoint = length / 2; | ||
1394 | |||
1395 | WRT_REG_WORD(®->nvram, 0); | ||
1396 | RD_REG_WORD(®->nvram); | ||
1397 | for (ilength = 0; ilength < length; saddr++, ilength++, tmp_buf++) { | ||
1398 | if (ilength == midpoint) { | ||
1399 | WRT_REG_WORD(®->nvram, NVR_SELECT); | ||
1400 | RD_REG_WORD(®->nvram); | ||
1401 | } | ||
1402 | data = qla2x00_read_flash_byte(ha, saddr); | ||
1403 | if (saddr % 100) | ||
1404 | udelay(10); | ||
1405 | *tmp_buf = data; | ||
1406 | } | ||
1407 | } | ||
1386 | 1408 | ||
1387 | static inline void | 1409 | static inline void |
1388 | qla2x00_suspend_hba(struct scsi_qla_host *ha) | 1410 | qla2x00_suspend_hba(struct scsi_qla_host *ha) |
@@ -1722,3 +1744,327 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, | |||
1722 | 1744 | ||
1723 | return rval; | 1745 | return rval; |
1724 | } | 1746 | } |
1747 | |||
1748 | /** | ||
1749 | * qla2x00_get_fcode_version() - Determine an FCODE image's version. | ||
1750 | * @ha: HA context | ||
1751 | * @pcids: Pointer to the FCODE PCI data structure | ||
1752 | * | ||
1753 | * The process of retrieving the FCODE version information is at best | ||
1754 | * described as interesting. | ||
1755 | * | ||
1756 | * Within the first 100h bytes of the image an ASCII string is present | ||
1757 | * which contains several pieces of information including the FCODE | ||
1758 | * version. Unfortunately it seems the only reliable way to retrieve | ||
1759 | * the version is by scanning for another sentinel within the string, | ||
1760 | * the FCODE build date: | ||
1761 | * | ||
1762 | * ... 2.00.02 10/17/02 ... | ||
1763 | * | ||
1764 | * Returns QLA_SUCCESS on successful retrieval of version. | ||
1765 | */ | ||
1766 | static void | ||
1767 | qla2x00_get_fcode_version(scsi_qla_host_t *ha, uint32_t pcids) | ||
1768 | { | ||
1769 | int ret = QLA_FUNCTION_FAILED; | ||
1770 | uint32_t istart, iend, iter, vend; | ||
1771 | uint8_t do_next, rbyte, *vbyte; | ||
1772 | |||
1773 | memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); | ||
1774 | |||
1775 | /* Skip the PCI data structure. */ | ||
1776 | istart = pcids + | ||
1777 | ((qla2x00_read_flash_byte(ha, pcids + 0x0B) << 8) | | ||
1778 | qla2x00_read_flash_byte(ha, pcids + 0x0A)); | ||
1779 | iend = istart + 0x100; | ||
1780 | do { | ||
1781 | /* Scan for the sentinel date string...eeewww. */ | ||
1782 | do_next = 0; | ||
1783 | iter = istart; | ||
1784 | while ((iter < iend) && !do_next) { | ||
1785 | iter++; | ||
1786 | if (qla2x00_read_flash_byte(ha, iter) == '/') { | ||
1787 | if (qla2x00_read_flash_byte(ha, iter + 2) == | ||
1788 | '/') | ||
1789 | do_next++; | ||
1790 | else if (qla2x00_read_flash_byte(ha, | ||
1791 | iter + 3) == '/') | ||
1792 | do_next++; | ||
1793 | } | ||
1794 | } | ||
1795 | if (!do_next) | ||
1796 | break; | ||
1797 | |||
1798 | /* Backtrack to previous ' ' (space). */ | ||
1799 | do_next = 0; | ||
1800 | while ((iter > istart) && !do_next) { | ||
1801 | iter--; | ||
1802 | if (qla2x00_read_flash_byte(ha, iter) == ' ') | ||
1803 | do_next++; | ||
1804 | } | ||
1805 | if (!do_next) | ||
1806 | break; | ||
1807 | |||
1808 | /* | ||
1809 | * Mark end of version tag, and find previous ' ' (space) or | ||
1810 | * string length (recent FCODE images -- major hack ahead!!!). | ||
1811 | */ | ||
1812 | vend = iter - 1; | ||
1813 | do_next = 0; | ||
1814 | while ((iter > istart) && !do_next) { | ||
1815 | iter--; | ||
1816 | rbyte = qla2x00_read_flash_byte(ha, iter); | ||
1817 | if (rbyte == ' ' || rbyte == 0xd || rbyte == 0x10) | ||
1818 | do_next++; | ||
1819 | } | ||
1820 | if (!do_next) | ||
1821 | break; | ||
1822 | |||
1823 | /* Mark beginning of version tag, and copy data. */ | ||
1824 | iter++; | ||
1825 | if ((vend - iter) && | ||
1826 | ((vend - iter) < sizeof(ha->fcode_revision))) { | ||
1827 | vbyte = ha->fcode_revision; | ||
1828 | while (iter <= vend) { | ||
1829 | *vbyte++ = qla2x00_read_flash_byte(ha, iter); | ||
1830 | iter++; | ||
1831 | } | ||
1832 | ret = QLA_SUCCESS; | ||
1833 | } | ||
1834 | } while (0); | ||
1835 | |||
1836 | if (ret != QLA_SUCCESS) | ||
1837 | memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); | ||
1838 | } | ||
1839 | |||
1840 | int | ||
1841 | qla2x00_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | ||
1842 | { | ||
1843 | int ret = QLA_SUCCESS; | ||
1844 | uint8_t code_type, last_image; | ||
1845 | uint32_t pcihdr, pcids; | ||
1846 | uint8_t *dbyte; | ||
1847 | uint16_t *dcode; | ||
1848 | |||
1849 | if (!ha->pio_address || !mbuf) | ||
1850 | return QLA_FUNCTION_FAILED; | ||
1851 | |||
1852 | memset(ha->bios_revision, 0, sizeof(ha->bios_revision)); | ||
1853 | memset(ha->efi_revision, 0, sizeof(ha->efi_revision)); | ||
1854 | memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); | ||
1855 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); | ||
1856 | |||
1857 | qla2x00_flash_enable(ha); | ||
1858 | |||
1859 | /* Begin with first PCI expansion ROM header. */ | ||
1860 | pcihdr = 0; | ||
1861 | last_image = 1; | ||
1862 | do { | ||
1863 | /* Verify PCI expansion ROM header. */ | ||
1864 | if (qla2x00_read_flash_byte(ha, pcihdr) != 0x55 || | ||
1865 | qla2x00_read_flash_byte(ha, pcihdr + 0x01) != 0xaa) { | ||
1866 | /* No signature */ | ||
1867 | DEBUG2(printk("scsi(%ld): No matching ROM " | ||
1868 | "signature.\n", ha->host_no)); | ||
1869 | ret = QLA_FUNCTION_FAILED; | ||
1870 | break; | ||
1871 | } | ||
1872 | |||
1873 | /* Locate PCI data structure. */ | ||
1874 | pcids = pcihdr + | ||
1875 | ((qla2x00_read_flash_byte(ha, pcihdr + 0x19) << 8) | | ||
1876 | qla2x00_read_flash_byte(ha, pcihdr + 0x18)); | ||
1877 | |||
1878 | /* Validate signature of PCI data structure. */ | ||
1879 | if (qla2x00_read_flash_byte(ha, pcids) != 'P' || | ||
1880 | qla2x00_read_flash_byte(ha, pcids + 0x1) != 'C' || | ||
1881 | qla2x00_read_flash_byte(ha, pcids + 0x2) != 'I' || | ||
1882 | qla2x00_read_flash_byte(ha, pcids + 0x3) != 'R') { | ||
1883 | /* Incorrect header. */ | ||
1884 | DEBUG2(printk("%s(): PCI data struct not found " | ||
1885 | "pcir_adr=%x.\n", __func__, pcids)); | ||
1886 | ret = QLA_FUNCTION_FAILED; | ||
1887 | break; | ||
1888 | } | ||
1889 | |||
1890 | /* Read version */ | ||
1891 | code_type = qla2x00_read_flash_byte(ha, pcids + 0x14); | ||
1892 | switch (code_type) { | ||
1893 | case ROM_CODE_TYPE_BIOS: | ||
1894 | /* Intel x86, PC-AT compatible. */ | ||
1895 | ha->bios_revision[0] = | ||
1896 | qla2x00_read_flash_byte(ha, pcids + 0x12); | ||
1897 | ha->bios_revision[1] = | ||
1898 | qla2x00_read_flash_byte(ha, pcids + 0x13); | ||
1899 | DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__, | ||
1900 | ha->bios_revision[1], ha->bios_revision[0])); | ||
1901 | break; | ||
1902 | case ROM_CODE_TYPE_FCODE: | ||
1903 | /* Open Firmware standard for PCI (FCode). */ | ||
1904 | /* Eeeewww... */ | ||
1905 | qla2x00_get_fcode_version(ha, pcids); | ||
1906 | break; | ||
1907 | case ROM_CODE_TYPE_EFI: | ||
1908 | /* Extensible Firmware Interface (EFI). */ | ||
1909 | ha->efi_revision[0] = | ||
1910 | qla2x00_read_flash_byte(ha, pcids + 0x12); | ||
1911 | ha->efi_revision[1] = | ||
1912 | qla2x00_read_flash_byte(ha, pcids + 0x13); | ||
1913 | DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__, | ||
1914 | ha->efi_revision[1], ha->efi_revision[0])); | ||
1915 | break; | ||
1916 | default: | ||
1917 | DEBUG2(printk("%s(): Unrecognized code type %x at " | ||
1918 | "pcids %x.\n", __func__, code_type, pcids)); | ||
1919 | break; | ||
1920 | } | ||
1921 | |||
1922 | last_image = qla2x00_read_flash_byte(ha, pcids + 0x15) & BIT_7; | ||
1923 | |||
1924 | /* Locate next PCI expansion ROM. */ | ||
1925 | pcihdr += ((qla2x00_read_flash_byte(ha, pcids + 0x11) << 8) | | ||
1926 | qla2x00_read_flash_byte(ha, pcids + 0x10)) * 512; | ||
1927 | } while (!last_image); | ||
1928 | |||
1929 | if (IS_QLA2322(ha)) { | ||
1930 | /* Read firmware image information. */ | ||
1931 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); | ||
1932 | dbyte = mbuf; | ||
1933 | memset(dbyte, 0, 8); | ||
1934 | dcode = (uint16_t *)dbyte; | ||
1935 | |||
1936 | qla2x00_read_flash_data(ha, dbyte, FA_RISC_CODE_ADDR * 4 + 10, | ||
1937 | 8); | ||
1938 | DEBUG3(printk("%s(%ld): dumping fw ver from flash:\n", | ||
1939 | __func__, ha->host_no)); | ||
1940 | DEBUG3(qla2x00_dump_buffer((uint8_t *)dbyte, 8)); | ||
1941 | |||
1942 | if ((dcode[0] == 0xffff && dcode[1] == 0xffff && | ||
1943 | dcode[2] == 0xffff && dcode[3] == 0xffff) || | ||
1944 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | ||
1945 | dcode[3] == 0)) { | ||
1946 | DEBUG2(printk("%s(): Unrecognized fw revision at " | ||
1947 | "%x.\n", __func__, FA_RISC_CODE_ADDR * 4)); | ||
1948 | } else { | ||
1949 | /* values are in big endian */ | ||
1950 | ha->fw_revision[0] = dbyte[0] << 16 | dbyte[1]; | ||
1951 | ha->fw_revision[1] = dbyte[2] << 16 | dbyte[3]; | ||
1952 | ha->fw_revision[2] = dbyte[4] << 16 | dbyte[5]; | ||
1953 | } | ||
1954 | } | ||
1955 | |||
1956 | qla2x00_flash_disable(ha); | ||
1957 | |||
1958 | return ret; | ||
1959 | } | ||
1960 | |||
1961 | int | ||
1962 | qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf) | ||
1963 | { | ||
1964 | int ret = QLA_SUCCESS; | ||
1965 | uint32_t pcihdr, pcids; | ||
1966 | uint32_t *dcode; | ||
1967 | uint8_t *bcode; | ||
1968 | uint8_t code_type, last_image; | ||
1969 | int i; | ||
1970 | |||
1971 | if (!mbuf) | ||
1972 | return QLA_FUNCTION_FAILED; | ||
1973 | |||
1974 | memset(ha->bios_revision, 0, sizeof(ha->bios_revision)); | ||
1975 | memset(ha->efi_revision, 0, sizeof(ha->efi_revision)); | ||
1976 | memset(ha->fcode_revision, 0, sizeof(ha->fcode_revision)); | ||
1977 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); | ||
1978 | |||
1979 | dcode = mbuf; | ||
1980 | |||
1981 | /* Begin with first PCI expansion ROM header. */ | ||
1982 | pcihdr = 0; | ||
1983 | last_image = 1; | ||
1984 | do { | ||
1985 | /* Verify PCI expansion ROM header. */ | ||
1986 | qla24xx_read_flash_data(ha, dcode, pcihdr >> 2, 0x20); | ||
1987 | bcode = mbuf + (pcihdr % 4); | ||
1988 | if (bcode[0x0] != 0x55 || bcode[0x1] != 0xaa) { | ||
1989 | /* No signature */ | ||
1990 | DEBUG2(printk("scsi(%ld): No matching ROM " | ||
1991 | "signature.\n", ha->host_no)); | ||
1992 | ret = QLA_FUNCTION_FAILED; | ||
1993 | break; | ||
1994 | } | ||
1995 | |||
1996 | /* Locate PCI data structure. */ | ||
1997 | pcids = pcihdr + ((bcode[0x19] << 8) | bcode[0x18]); | ||
1998 | |||
1999 | qla24xx_read_flash_data(ha, dcode, pcids >> 2, 0x20); | ||
2000 | bcode = mbuf + (pcihdr % 4); | ||
2001 | |||
2002 | /* Validate signature of PCI data structure. */ | ||
2003 | if (bcode[0x0] != 'P' || bcode[0x1] != 'C' || | ||
2004 | bcode[0x2] != 'I' || bcode[0x3] != 'R') { | ||
2005 | /* Incorrect header. */ | ||
2006 | DEBUG2(printk("%s(): PCI data struct not found " | ||
2007 | "pcir_adr=%x.\n", __func__, pcids)); | ||
2008 | ret = QLA_FUNCTION_FAILED; | ||
2009 | break; | ||
2010 | } | ||
2011 | |||
2012 | /* Read version */ | ||
2013 | code_type = bcode[0x14]; | ||
2014 | switch (code_type) { | ||
2015 | case ROM_CODE_TYPE_BIOS: | ||
2016 | /* Intel x86, PC-AT compatible. */ | ||
2017 | ha->bios_revision[0] = bcode[0x12]; | ||
2018 | ha->bios_revision[1] = bcode[0x13]; | ||
2019 | DEBUG3(printk("%s(): read BIOS %d.%d.\n", __func__, | ||
2020 | ha->bios_revision[1], ha->bios_revision[0])); | ||
2021 | break; | ||
2022 | case ROM_CODE_TYPE_FCODE: | ||
2023 | /* Open Firmware standard for PCI (FCode). */ | ||
2024 | ha->fcode_revision[0] = bcode[0x12]; | ||
2025 | ha->fcode_revision[1] = bcode[0x13]; | ||
2026 | DEBUG3(printk("%s(): read FCODE %d.%d.\n", __func__, | ||
2027 | ha->fcode_revision[1], ha->fcode_revision[0])); | ||
2028 | break; | ||
2029 | case ROM_CODE_TYPE_EFI: | ||
2030 | /* Extensible Firmware Interface (EFI). */ | ||
2031 | ha->efi_revision[0] = bcode[0x12]; | ||
2032 | ha->efi_revision[1] = bcode[0x13]; | ||
2033 | DEBUG3(printk("%s(): read EFI %d.%d.\n", __func__, | ||
2034 | ha->efi_revision[1], ha->efi_revision[0])); | ||
2035 | break; | ||
2036 | default: | ||
2037 | DEBUG2(printk("%s(): Unrecognized code type %x at " | ||
2038 | "pcids %x.\n", __func__, code_type, pcids)); | ||
2039 | break; | ||
2040 | } | ||
2041 | |||
2042 | last_image = bcode[0x15] & BIT_7; | ||
2043 | |||
2044 | /* Locate next PCI expansion ROM. */ | ||
2045 | pcihdr += ((bcode[0x11] << 8) | bcode[0x10]) * 512; | ||
2046 | } while (!last_image); | ||
2047 | |||
2048 | /* Read firmware image information. */ | ||
2049 | memset(ha->fw_revision, 0, sizeof(ha->fw_revision)); | ||
2050 | dcode = mbuf; | ||
2051 | |||
2052 | qla24xx_read_flash_data(ha, dcode, FA_RISC_CODE_ADDR + 4, 4); | ||
2053 | for (i = 0; i < 4; i++) | ||
2054 | dcode[i] = be32_to_cpu(dcode[i]); | ||
2055 | |||
2056 | if ((dcode[0] == 0xffffffff && dcode[1] == 0xffffffff && | ||
2057 | dcode[2] == 0xffffffff && dcode[3] == 0xffffffff) || | ||
2058 | (dcode[0] == 0 && dcode[1] == 0 && dcode[2] == 0 && | ||
2059 | dcode[3] == 0)) { | ||
2060 | DEBUG2(printk("%s(): Unrecognized fw version at %x.\n", | ||
2061 | __func__, FA_RISC_CODE_ADDR)); | ||
2062 | } else { | ||
2063 | ha->fw_revision[0] = dcode[0]; | ||
2064 | ha->fw_revision[1] = dcode[1]; | ||
2065 | ha->fw_revision[2] = dcode[2]; | ||
2066 | ha->fw_revision[3] = dcode[3]; | ||
2067 | } | ||
2068 | |||
2069 | return ret; | ||
2070 | } | ||