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