diff options
Diffstat (limited to 'drivers/atm/ambassador.c')
| -rw-r--r-- | drivers/atm/ambassador.c | 140 |
1 files changed, 57 insertions, 83 deletions
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 6adb72a2f876..703364b52170 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c | |||
| @@ -34,6 +34,8 @@ | |||
| 34 | #include <linux/poison.h> | 34 | #include <linux/poison.h> |
| 35 | #include <linux/bitrev.h> | 35 | #include <linux/bitrev.h> |
| 36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
| 37 | #include <linux/firmware.h> | ||
| 38 | #include <linux/ihex.h> | ||
| 37 | 39 | ||
| 38 | #include <asm/atomic.h> | 40 | #include <asm/atomic.h> |
| 39 | #include <asm/io.h> | 41 | #include <asm/io.h> |
| @@ -290,29 +292,6 @@ static inline void __init show_version (void) { | |||
| 290 | 292 | ||
| 291 | */ | 293 | */ |
| 292 | 294 | ||
| 293 | /********** microcode **********/ | ||
| 294 | |||
| 295 | #ifdef AMB_NEW_MICROCODE | ||
| 296 | #define UCODE(x) UCODE2(atmsar12.x) | ||
| 297 | #else | ||
| 298 | #define UCODE(x) UCODE2(atmsar11.x) | ||
| 299 | #endif | ||
| 300 | #define UCODE2(x) #x | ||
| 301 | |||
| 302 | static u32 __devinitdata ucode_start = | ||
| 303 | #include UCODE(start) | ||
| 304 | ; | ||
| 305 | |||
| 306 | static region __devinitdata ucode_regions[] = { | ||
| 307 | #include UCODE(regions) | ||
| 308 | { 0, 0 } | ||
| 309 | }; | ||
| 310 | |||
| 311 | static u32 __devinitdata ucode_data[] = { | ||
| 312 | #include UCODE(data) | ||
| 313 | 0xdeadbeef | ||
| 314 | }; | ||
| 315 | |||
| 316 | static void do_housekeeping (unsigned long arg); | 295 | static void do_housekeeping (unsigned long arg); |
| 317 | /********** globals **********/ | 296 | /********** globals **********/ |
| 318 | 297 | ||
| @@ -1841,45 +1820,34 @@ static int __devinit get_loader_version (loader_block * lb, | |||
| 1841 | 1820 | ||
| 1842 | /* loader: write memory data blocks */ | 1821 | /* loader: write memory data blocks */ |
| 1843 | 1822 | ||
| 1844 | static int __devinit loader_write (loader_block * lb, | 1823 | static int __devinit loader_write (loader_block* lb, |
| 1845 | const amb_dev * dev, const u32 * data, | 1824 | const amb_dev *dev, |
| 1846 | u32 address, unsigned int count) { | 1825 | const struct ihex_binrec *rec) { |
| 1847 | unsigned int i; | ||
| 1848 | transfer_block * tb = &lb->payload.transfer; | 1826 | transfer_block * tb = &lb->payload.transfer; |
| 1849 | 1827 | ||
| 1850 | PRINTD (DBG_FLOW|DBG_LOAD, "loader_write"); | 1828 | PRINTD (DBG_FLOW|DBG_LOAD, "loader_write"); |
| 1851 | 1829 | ||
| 1852 | if (count > MAX_TRANSFER_DATA) | 1830 | tb->address = rec->addr; |
| 1853 | return -EINVAL; | 1831 | tb->count = cpu_to_be32(be16_to_cpu(rec->len) / 4); |
| 1854 | tb->address = cpu_to_be32 (address); | 1832 | memcpy(tb->data, rec->data, be16_to_cpu(rec->len)); |
| 1855 | tb->count = cpu_to_be32 (count); | ||
| 1856 | for (i = 0; i < count; ++i) | ||
| 1857 | tb->data[i] = cpu_to_be32 (data[i]); | ||
| 1858 | return do_loader_command (lb, dev, write_adapter_memory); | 1833 | return do_loader_command (lb, dev, write_adapter_memory); |
| 1859 | } | 1834 | } |
| 1860 | 1835 | ||
| 1861 | /* loader: verify memory data blocks */ | 1836 | /* loader: verify memory data blocks */ |
| 1862 | 1837 | ||
| 1863 | static int __devinit loader_verify (loader_block * lb, | 1838 | static int __devinit loader_verify (loader_block * lb, |
| 1864 | const amb_dev * dev, const u32 * data, | 1839 | const amb_dev *dev, |
| 1865 | u32 address, unsigned int count) { | 1840 | const struct ihex_binrec *rec) { |
| 1866 | unsigned int i; | ||
| 1867 | transfer_block * tb = &lb->payload.transfer; | 1841 | transfer_block * tb = &lb->payload.transfer; |
| 1868 | int res; | 1842 | int res; |
| 1869 | 1843 | ||
| 1870 | PRINTD (DBG_FLOW|DBG_LOAD, "loader_verify"); | 1844 | PRINTD (DBG_FLOW|DBG_LOAD, "loader_verify"); |
| 1871 | 1845 | ||
| 1872 | if (count > MAX_TRANSFER_DATA) | 1846 | tb->address = rec->addr; |
| 1873 | return -EINVAL; | 1847 | tb->count = cpu_to_be32(be16_to_cpu(rec->len) / 4); |
| 1874 | tb->address = cpu_to_be32 (address); | ||
| 1875 | tb->count = cpu_to_be32 (count); | ||
| 1876 | res = do_loader_command (lb, dev, read_adapter_memory); | 1848 | res = do_loader_command (lb, dev, read_adapter_memory); |
| 1877 | if (!res) | 1849 | if (!res && memcmp(tb->data, rec->data, be16_to_cpu(rec->len))) |
| 1878 | for (i = 0; i < count; ++i) | 1850 | res = -EINVAL; |
| 1879 | if (tb->data[i] != cpu_to_be32 (data[i])) { | ||
| 1880 | res = -EINVAL; | ||
| 1881 | break; | ||
| 1882 | } | ||
| 1883 | return res; | 1851 | return res; |
| 1884 | } | 1852 | } |
| 1885 | 1853 | ||
| @@ -1962,47 +1930,53 @@ static int amb_reset (amb_dev * dev, int diags) { | |||
| 1962 | /********** transfer and start the microcode **********/ | 1930 | /********** transfer and start the microcode **********/ |
| 1963 | 1931 | ||
| 1964 | static int __devinit ucode_init (loader_block * lb, amb_dev * dev) { | 1932 | static int __devinit ucode_init (loader_block * lb, amb_dev * dev) { |
| 1965 | unsigned int i = 0; | 1933 | const struct firmware *fw; |
| 1966 | unsigned int total = 0; | 1934 | unsigned long start_address; |
| 1967 | const u32 * pointer = ucode_data; | 1935 | const struct ihex_binrec *rec; |
| 1968 | u32 address; | ||
| 1969 | unsigned int count; | ||
| 1970 | int res; | 1936 | int res; |
| 1971 | 1937 | ||
| 1938 | res = request_ihex_firmware(&fw, "atmsar11.fw", &dev->pci_dev->dev); | ||
| 1939 | if (res) { | ||
| 1940 | PRINTK (KERN_ERR, "Cannot load microcode data"); | ||
| 1941 | return res; | ||
| 1942 | } | ||
| 1943 | |||
| 1944 | /* First record contains just the start address */ | ||
| 1945 | rec = (const struct ihex_binrec *)fw->data; | ||
| 1946 | if (be16_to_cpu(rec->len) != sizeof(__be32) || be32_to_cpu(rec->addr)) { | ||
| 1947 | PRINTK (KERN_ERR, "Bad microcode data (no start record)"); | ||
| 1948 | return -EINVAL; | ||
| 1949 | } | ||
| 1950 | start_address = be32_to_cpup((__be32 *)rec->data); | ||
| 1951 | |||
| 1952 | rec = ihex_next_binrec(rec); | ||
| 1953 | |||
| 1972 | PRINTD (DBG_FLOW|DBG_LOAD, "ucode_init"); | 1954 | PRINTD (DBG_FLOW|DBG_LOAD, "ucode_init"); |
| 1973 | 1955 | ||
| 1974 | while (address = ucode_regions[i].start, | 1956 | while (rec) { |
| 1975 | count = ucode_regions[i].count) { | 1957 | PRINTD (DBG_LOAD, "starting region (%x, %u)", be32_to_cpu(rec->addr), |
| 1976 | PRINTD (DBG_LOAD, "starting region (%x, %u)", address, count); | 1958 | be16_to_cpu(rec->len)); |
| 1977 | while (count) { | 1959 | if (be16_to_cpu(rec->len) > 4 * MAX_TRANSFER_DATA) { |
| 1978 | unsigned int words; | 1960 | PRINTK (KERN_ERR, "Bad microcode data (record too long)"); |
| 1979 | if (count <= MAX_TRANSFER_DATA) | 1961 | return -EINVAL; |
| 1980 | words = count; | ||
| 1981 | else | ||
| 1982 | words = MAX_TRANSFER_DATA; | ||
| 1983 | total += words; | ||
| 1984 | res = loader_write (lb, dev, pointer, address, words); | ||
| 1985 | if (res) | ||
| 1986 | return res; | ||
| 1987 | res = loader_verify (lb, dev, pointer, address, words); | ||
| 1988 | if (res) | ||
| 1989 | return res; | ||
| 1990 | count -= words; | ||
| 1991 | address += sizeof(u32) * words; | ||
| 1992 | pointer += words; | ||
| 1993 | } | 1962 | } |
| 1994 | i += 1; | 1963 | if (be16_to_cpu(rec->len) & 3) { |
| 1995 | } | 1964 | PRINTK (KERN_ERR, "Bad microcode data (odd number of bytes)"); |
| 1996 | if (*pointer == ATM_POISON) { | 1965 | return -EINVAL; |
| 1997 | return loader_start (lb, dev, ucode_start); | 1966 | } |
| 1998 | } else { | 1967 | res = loader_write(lb, dev, rec); |
| 1999 | // cast needed as there is no %? for pointer differnces | 1968 | if (res) |
| 2000 | PRINTD (DBG_LOAD|DBG_ERR, | 1969 | break; |
| 2001 | "offset=%li, *pointer=%x, address=%x, total=%u", | 1970 | |
| 2002 | (long) (pointer - ucode_data), *pointer, address, total); | 1971 | res = loader_verify(lb, dev, rec); |
| 2003 | PRINTK (KERN_ERR, "incorrect microcode data"); | 1972 | if (res) |
| 2004 | return -ENOMEM; | 1973 | break; |
| 2005 | } | 1974 | } |
| 1975 | release_firmware(fw); | ||
| 1976 | if (!res) | ||
| 1977 | res = loader_start(lb, dev, start_address); | ||
| 1978 | |||
| 1979 | return res; | ||
| 2006 | } | 1980 | } |
| 2007 | 1981 | ||
| 2008 | /********** give adapter parameters **********/ | 1982 | /********** give adapter parameters **********/ |
