diff options
Diffstat (limited to 'drivers/char/isicom.c')
-rw-r--r-- | drivers/char/isicom.c | 447 |
1 files changed, 239 insertions, 208 deletions
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 49f88c9006cb..9ef8ab301768 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -107,7 +107,6 @@ | |||
107 | * Omit those entries for boards you don't have installed. | 107 | * Omit those entries for boards you don't have installed. |
108 | * | 108 | * |
109 | * TODO | 109 | * TODO |
110 | * Hotplug | ||
111 | * Merge testing | 110 | * Merge testing |
112 | * 64-bit verification | 111 | * 64-bit verification |
113 | */ | 112 | */ |
@@ -146,20 +145,30 @@ | |||
146 | #define isicom_paranoia_check(a, b, c) 0 | 145 | #define isicom_paranoia_check(a, b, c) 0 |
147 | #endif | 146 | #endif |
148 | 147 | ||
148 | static int isicom_probe(struct pci_dev *, const struct pci_device_id *); | ||
149 | static void __devexit isicom_remove(struct pci_dev *); | ||
150 | |||
149 | static struct pci_device_id isicom_pci_tbl[] = { | 151 | static struct pci_device_id isicom_pci_tbl[] = { |
150 | { VENDOR_ID, 0x2028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 152 | { PCI_DEVICE(VENDOR_ID, 0x2028) }, |
151 | { VENDOR_ID, 0x2051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 153 | { PCI_DEVICE(VENDOR_ID, 0x2051) }, |
152 | { VENDOR_ID, 0x2052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 154 | { PCI_DEVICE(VENDOR_ID, 0x2052) }, |
153 | { VENDOR_ID, 0x2053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 155 | { PCI_DEVICE(VENDOR_ID, 0x2053) }, |
154 | { VENDOR_ID, 0x2054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 156 | { PCI_DEVICE(VENDOR_ID, 0x2054) }, |
155 | { VENDOR_ID, 0x2055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 157 | { PCI_DEVICE(VENDOR_ID, 0x2055) }, |
156 | { VENDOR_ID, 0x2056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 158 | { PCI_DEVICE(VENDOR_ID, 0x2056) }, |
157 | { VENDOR_ID, 0x2057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 159 | { PCI_DEVICE(VENDOR_ID, 0x2057) }, |
158 | { VENDOR_ID, 0x2058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 160 | { PCI_DEVICE(VENDOR_ID, 0x2058) }, |
159 | { 0 } | 161 | { 0 } |
160 | }; | 162 | }; |
161 | MODULE_DEVICE_TABLE(pci, isicom_pci_tbl); | 163 | MODULE_DEVICE_TABLE(pci, isicom_pci_tbl); |
162 | 164 | ||
165 | static struct pci_driver isicom_driver = { | ||
166 | .name = "isicom", | ||
167 | .id_table = isicom_pci_tbl, | ||
168 | .probe = isicom_probe, | ||
169 | .remove = __devexit_p(isicom_remove) | ||
170 | }; | ||
171 | |||
163 | static int prev_card = 3; /* start servicing isi_card[0] */ | 172 | static int prev_card = 3; /* start servicing isi_card[0] */ |
164 | static struct tty_driver *isicom_normal; | 173 | static struct tty_driver *isicom_normal; |
165 | 174 | ||
@@ -171,8 +180,6 @@ static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned int c | |||
171 | static void isicom_tx(unsigned long _data); | 180 | static void isicom_tx(unsigned long _data); |
172 | static void isicom_start(struct tty_struct *tty); | 181 | static void isicom_start(struct tty_struct *tty); |
173 | 182 | ||
174 | static unsigned char *tmp_buf; | ||
175 | |||
176 | /* baud index mappings from linux defns to isi */ | 183 | /* baud index mappings from linux defns to isi */ |
177 | 184 | ||
178 | static signed char linuxb_to_isib[] = { | 185 | static signed char linuxb_to_isib[] = { |
@@ -1365,7 +1372,7 @@ static int isicom_write(struct tty_struct *tty, const unsigned char *buf, | |||
1365 | if (isicom_paranoia_check(port, tty->name, "isicom_write")) | 1372 | if (isicom_paranoia_check(port, tty->name, "isicom_write")) |
1366 | return 0; | 1373 | return 0; |
1367 | 1374 | ||
1368 | if (!tty || !port->xmit_buf || !tmp_buf) | 1375 | if (!tty || !port->xmit_buf) |
1369 | return 0; | 1376 | return 0; |
1370 | 1377 | ||
1371 | spin_lock_irqsave(&card->card_lock, flags); | 1378 | spin_lock_irqsave(&card->card_lock, flags); |
@@ -1731,32 +1738,39 @@ static void isicom_flush_buffer(struct tty_struct *tty) | |||
1731 | tty_wakeup(tty); | 1738 | tty_wakeup(tty); |
1732 | } | 1739 | } |
1733 | 1740 | ||
1741 | /* | ||
1742 | * Driver init and deinit functions | ||
1743 | */ | ||
1734 | 1744 | ||
1735 | static int __devinit register_ioregion(void) | 1745 | static int __devinit isicom_register_ioregion(struct pci_dev *pdev, |
1746 | const unsigned int index) | ||
1736 | { | 1747 | { |
1737 | int count, done=0; | 1748 | struct isi_board *board = pci_get_drvdata(pdev); |
1738 | for (count=0; count < BOARD_COUNT; count++ ) { | 1749 | |
1739 | if (isi_card[count].base) | 1750 | if (!board->base) |
1740 | if (!request_region(isi_card[count].base,16,ISICOM_NAME)) { | 1751 | return -EINVAL; |
1741 | printk(KERN_DEBUG "ISICOM: I/O Region 0x%lx-0x%lx is busy. Card%d will be disabled.\n", | 1752 | |
1742 | isi_card[count].base,isi_card[count].base+15,count+1); | 1753 | if (!request_region(board->base, 16, ISICOM_NAME)) { |
1743 | isi_card[count].base=0; | 1754 | dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d " |
1744 | done++; | 1755 | "will be disabled.\n", board->base, board->base + 15, |
1745 | } | 1756 | index + 1); |
1746 | } | 1757 | return -EBUSY; |
1747 | return done; | 1758 | } |
1759 | |||
1760 | return 0; | ||
1748 | } | 1761 | } |
1749 | 1762 | ||
1750 | static void unregister_ioregion(void) | 1763 | static void isicom_unregister_ioregion(struct pci_dev *pdev) |
1751 | { | 1764 | { |
1752 | int count; | 1765 | struct isi_board *board = pci_get_drvdata(pdev); |
1753 | for (count=0; count < BOARD_COUNT; count++ ) | 1766 | |
1754 | if (isi_card[count].base) { | 1767 | if (!board->base) |
1755 | release_region(isi_card[count].base,16); | 1768 | return; |
1756 | #ifdef ISICOM_DEBUG | 1769 | |
1757 | printk(KERN_DEBUG "ISICOM: I/O Region 0x%lx-0x%lx released for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1); | 1770 | release_region(board->base, 16); |
1758 | #endif | 1771 | dev_dbg(&pdev->dev, "I/O Region 0x%lx-0x%lx released.\n", |
1759 | } | 1772 | board->base, board->base + 15); |
1773 | board->base = 0; | ||
1760 | } | 1774 | } |
1761 | 1775 | ||
1762 | static struct tty_operations isicom_ops = { | 1776 | static struct tty_operations isicom_ops = { |
@@ -1820,207 +1834,223 @@ static void isicom_unregister_tty_driver(void) | |||
1820 | put_tty_driver(isicom_normal); | 1834 | put_tty_driver(isicom_normal); |
1821 | } | 1835 | } |
1822 | 1836 | ||
1823 | static int __devinit register_isr(void) | 1837 | static int __devinit isicom_register_isr(struct pci_dev *pdev, |
1838 | const unsigned int index) | ||
1824 | { | 1839 | { |
1825 | int count, done=0; | 1840 | struct isi_board *board = pci_get_drvdata(pdev); |
1826 | unsigned long irqflags; | 1841 | unsigned long irqflags = SA_INTERRUPT; |
1827 | 1842 | int retval = -EINVAL; | |
1828 | for (count=0; count < BOARD_COUNT; count++ ) { | ||
1829 | if (isi_card[count].base) { | ||
1830 | irqflags = (isi_card[count].isa == YES) ? | ||
1831 | SA_INTERRUPT : | ||
1832 | (SA_INTERRUPT | SA_SHIRQ); | ||
1833 | |||
1834 | if (request_irq(isi_card[count].irq, | ||
1835 | isicom_interrupt, | ||
1836 | irqflags, | ||
1837 | ISICOM_NAME, &isi_card[count])) { | ||
1838 | |||
1839 | printk(KERN_WARNING "ISICOM: Could not" | ||
1840 | " install handler at Irq %d." | ||
1841 | " Card%d will be disabled.\n", | ||
1842 | isi_card[count].irq, count+1); | ||
1843 | |||
1844 | release_region(isi_card[count].base,16); | ||
1845 | isi_card[count].base=0; | ||
1846 | } | ||
1847 | else | ||
1848 | done++; | ||
1849 | } | ||
1850 | } | ||
1851 | return done; | ||
1852 | } | ||
1853 | 1843 | ||
1854 | static void __exit unregister_isr(void) | 1844 | if (!board->base) |
1855 | { | 1845 | goto end; |
1856 | int count; | ||
1857 | 1846 | ||
1858 | for (count=0; count < BOARD_COUNT; count++ ) { | 1847 | if (board->isa == NO) |
1859 | if (isi_card[count].base) | 1848 | irqflags |= SA_SHIRQ; |
1860 | free_irq(isi_card[count].irq, &isi_card[count]); | 1849 | |
1861 | } | 1850 | retval = request_irq(board->irq, isicom_interrupt, irqflags, |
1851 | ISICOM_NAME, board); | ||
1852 | if (retval < 0) | ||
1853 | dev_warn(&pdev->dev, "Could not install handler at Irq %d. " | ||
1854 | "Card%d will be disabled.\n", board->irq, index + 1); | ||
1855 | else | ||
1856 | retval = 0; | ||
1857 | end: | ||
1858 | return retval; | ||
1862 | } | 1859 | } |
1863 | 1860 | ||
1864 | static int __devinit isicom_init(void) | 1861 | static int __devinit reset_card(struct pci_dev *pdev, |
1862 | const unsigned int card, unsigned int *signature) | ||
1865 | { | 1863 | { |
1866 | int card, channel, base; | 1864 | struct isi_board *board = pci_get_drvdata(pdev); |
1867 | struct isi_port *port; | 1865 | unsigned long base = board->base; |
1868 | unsigned long page; | 1866 | unsigned int portcount = 0; |
1867 | int retval = 0; | ||
1869 | 1868 | ||
1870 | if (!tmp_buf) { | 1869 | dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1, |
1871 | page = get_zeroed_page(GFP_KERNEL); | 1870 | base); |
1872 | if (!page) { | ||
1873 | #ifdef ISICOM_DEBUG | ||
1874 | printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.\n"); | ||
1875 | #else | ||
1876 | printk(KERN_ERR "ISICOM: Not enough memory...\n"); | ||
1877 | #endif | ||
1878 | return 0; | ||
1879 | } | ||
1880 | tmp_buf = (unsigned char *) page; | ||
1881 | } | ||
1882 | 1871 | ||
1883 | if (!register_ioregion()) | 1872 | inw(base + 0x8); |
1884 | { | ||
1885 | printk(KERN_ERR "ISICOM: All required I/O space found busy.\n"); | ||
1886 | free_page((unsigned long)tmp_buf); | ||
1887 | return 0; | ||
1888 | } | ||
1889 | if (isicom_register_tty_driver()) | ||
1890 | { | ||
1891 | unregister_ioregion(); | ||
1892 | free_page((unsigned long)tmp_buf); | ||
1893 | return 0; | ||
1894 | } | ||
1895 | if (!register_isr()) | ||
1896 | { | ||
1897 | isicom_unregister_tty_driver(); | ||
1898 | /* ioports already uregistered in register_isr */ | ||
1899 | free_page((unsigned long)tmp_buf); | ||
1900 | return 0; | ||
1901 | } | ||
1902 | 1873 | ||
1903 | memset(isi_ports, 0, sizeof(isi_ports)); | 1874 | mdelay(10); |
1904 | for (card = 0; card < BOARD_COUNT; card++) { | 1875 | |
1905 | port = &isi_ports[card * 16]; | 1876 | outw(0, base + 0x8); /* Reset */ |
1906 | isi_card[card].ports = port; | 1877 | |
1907 | spin_lock_init(&isi_card[card].card_lock); | 1878 | msleep(3000); |
1908 | base = isi_card[card].base; | 1879 | |
1909 | for (channel = 0; channel < 16; channel++, port++) { | 1880 | *signature = inw(base + 0x4) & 0xff; |
1910 | port->magic = ISICOM_MAGIC; | 1881 | |
1911 | port->card = &isi_card[card]; | 1882 | if (board->isa == YES) { |
1912 | port->channel = channel; | 1883 | if (!(inw(base + 0xe) & 0x1) || (inw(base + 0x2))) { |
1913 | port->close_delay = 50 * HZ/100; | 1884 | dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n", |
1914 | port->closing_wait = 3000 * HZ/100; | 1885 | inw(base + 0x2), inw(base + 0xe)); |
1915 | INIT_WORK(&port->hangup_tq, do_isicom_hangup, port); | 1886 | dev_err(&pdev->dev, "ISILoad:ISA Card%d reset failure " |
1916 | INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port); | 1887 | "(Possible bad I/O Port Address 0x%lx).\n", |
1917 | port->status = 0; | 1888 | card + 1, base); |
1918 | init_waitqueue_head(&port->open_wait); | 1889 | retval = -EIO; |
1919 | init_waitqueue_head(&port->close_wait); | 1890 | goto end; |
1920 | /* . . . */ | ||
1921 | } | 1891 | } |
1892 | } else { | ||
1893 | portcount = inw(base + 0x2); | ||
1894 | if (!(inw(base + 0xe) & 0x1) || ((portcount != 0) && | ||
1895 | (portcount != 4) && (portcount != 8))) { | ||
1896 | dev_dbg(&pdev->dev, "base+0x2=0x%lx, base+0xe=0x%lx\n", | ||
1897 | inw(base + 0x2), inw(base + 0xe)); | ||
1898 | dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure " | ||
1899 | "(Possible bad I/O Port Address 0x%lx).\n", | ||
1900 | card + 1, base); | ||
1901 | retval = -EIO; | ||
1902 | goto end; | ||
1903 | } | ||
1904 | } | ||
1905 | |||
1906 | switch (*signature) { | ||
1907 | case 0xa5: | ||
1908 | case 0xbb: | ||
1909 | case 0xdd: | ||
1910 | board->port_count = (board->isa == NO && portcount == 4) ? 4 : | ||
1911 | 8; | ||
1912 | board->shift_count = 12; | ||
1913 | break; | ||
1914 | case 0xcc: | ||
1915 | board->port_count = 16; | ||
1916 | board->shift_count = 11; | ||
1917 | break; | ||
1918 | default: | ||
1919 | dev_warn(&pdev->dev, "ISILoad:Card%d reset failure (Possible " | ||
1920 | "bad I/O Port Address 0x%lx).\n", card + 1, base); | ||
1921 | dev_dbg(&pdev->dev, "Sig=0x%lx\n", signature); | ||
1922 | retval = -EIO; | ||
1922 | } | 1923 | } |
1924 | dev_info(&pdev->dev, "-Done\n"); | ||
1923 | 1925 | ||
1924 | return 1; | 1926 | end: |
1927 | return retval; | ||
1925 | } | 1928 | } |
1926 | 1929 | ||
1927 | /* | 1930 | /* |
1928 | * Insmod can set static symbols so keep these static | 1931 | * Insmod can set static symbols so keep these static |
1929 | */ | 1932 | */ |
1930 | |||
1931 | static int io[4]; | 1933 | static int io[4]; |
1932 | static int irq[4]; | 1934 | static int irq[4]; |
1935 | static int card; | ||
1936 | |||
1937 | static int __devinit isicom_probe(struct pci_dev *pdev, | ||
1938 | const struct pci_device_id *ent) | ||
1939 | { | ||
1940 | unsigned int ioaddr, signature, index; | ||
1941 | int retval = -EPERM; | ||
1942 | u8 pciirq; | ||
1943 | struct isi_board *board = NULL; | ||
1944 | |||
1945 | if (card >= BOARD_COUNT) | ||
1946 | goto err; | ||
1947 | |||
1948 | ioaddr = pci_resource_start(pdev, 3); | ||
1949 | /* i.e at offset 0x1c in the PCI configuration register space. */ | ||
1950 | pciirq = pdev->irq; | ||
1951 | dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device); | ||
1952 | |||
1953 | /* allot the first empty slot in the array */ | ||
1954 | for (index = 0; index < BOARD_COUNT; index++) | ||
1955 | if (isi_card[index].base == 0) { | ||
1956 | board = &isi_card[index]; | ||
1957 | break; | ||
1958 | } | ||
1959 | |||
1960 | board->base = ioaddr; | ||
1961 | board->irq = pciirq; | ||
1962 | board->isa = NO; | ||
1963 | card++; | ||
1964 | |||
1965 | pci_set_drvdata(pdev, board); | ||
1966 | |||
1967 | retval = isicom_register_ioregion(pdev, index); | ||
1968 | if (retval < 0) | ||
1969 | goto err; | ||
1970 | |||
1971 | retval = isicom_register_isr(pdev, index); | ||
1972 | if (retval < 0) | ||
1973 | goto errunrr; | ||
1974 | |||
1975 | retval = reset_card(pdev, index, &signature); | ||
1976 | if (retval < 0) | ||
1977 | goto errunri; | ||
1978 | |||
1979 | return 0; | ||
1980 | |||
1981 | errunri: | ||
1982 | free_irq(board->irq, board); | ||
1983 | errunrr: | ||
1984 | isicom_unregister_ioregion(pdev); | ||
1985 | err: | ||
1986 | board->base = 0; | ||
1987 | return retval; | ||
1988 | } | ||
1989 | |||
1990 | static void __devexit isicom_remove(struct pci_dev *pdev) | ||
1991 | { | ||
1992 | struct isi_board *board = pci_get_drvdata(pdev); | ||
1993 | |||
1994 | free_irq(board->irq, board); | ||
1995 | isicom_unregister_ioregion(pdev); | ||
1996 | } | ||
1933 | 1997 | ||
1934 | static int __devinit isicom_setup(void) | 1998 | static int __devinit isicom_setup(void) |
1935 | { | 1999 | { |
1936 | struct pci_dev *dev = NULL; | 2000 | int retval, idx, channel; |
1937 | int retval, card, idx, count; | 2001 | struct isi_port *port; |
1938 | unsigned char pciirq; | ||
1939 | unsigned int ioaddr; | ||
1940 | 2002 | ||
1941 | card = 0; | 2003 | card = 0; |
1942 | for (idx=0; idx < BOARD_COUNT; idx++) { | 2004 | memset(isi_ports, 0, sizeof(isi_ports)); |
1943 | if (io[idx]) { | ||
1944 | isi_card[idx].base=io[idx]; | ||
1945 | isi_card[idx].irq=irq[idx]; | ||
1946 | isi_card[idx].isa=YES; | ||
1947 | card++; | ||
1948 | } | ||
1949 | else { | ||
1950 | isi_card[idx].base = 0; | ||
1951 | isi_card[idx].irq = 0; | ||
1952 | } | ||
1953 | } | ||
1954 | |||
1955 | for (idx=0 ;idx < card; idx++) { | ||
1956 | if (!((isi_card[idx].irq==2)||(isi_card[idx].irq==3)|| | ||
1957 | (isi_card[idx].irq==4)||(isi_card[idx].irq==5)|| | ||
1958 | (isi_card[idx].irq==7)||(isi_card[idx].irq==10)|| | ||
1959 | (isi_card[idx].irq==11)||(isi_card[idx].irq==12)|| | ||
1960 | (isi_card[idx].irq==15))) { | ||
1961 | |||
1962 | if (isi_card[idx].base) { | ||
1963 | printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n", | ||
1964 | isi_card[idx].irq, idx+1); | ||
1965 | isi_card[idx].base=0; | ||
1966 | card--; | ||
1967 | } | ||
1968 | } | ||
1969 | } | ||
1970 | 2005 | ||
1971 | if (card < BOARD_COUNT) { | 2006 | for(idx = 0; idx < BOARD_COUNT; idx++) { |
1972 | for (idx=0; idx < DEVID_COUNT; idx++) { | 2007 | port = &isi_ports[idx * 16]; |
1973 | dev = NULL; | 2008 | isi_card[idx].ports = port; |
1974 | for (;;){ | 2009 | spin_lock_init(&isi_card[idx].card_lock); |
1975 | if (!(dev = pci_find_device(VENDOR_ID, isicom_pci_tbl[idx].device, dev))) | 2010 | for (channel = 0; channel < 16; channel++, port++) { |
1976 | break; | 2011 | port->magic = ISICOM_MAGIC; |
1977 | if (card >= BOARD_COUNT) | 2012 | port->card = &isi_card[idx]; |
1978 | break; | 2013 | port->channel = channel; |
2014 | port->close_delay = 50 * HZ/100; | ||
2015 | port->closing_wait = 3000 * HZ/100; | ||
2016 | INIT_WORK(&port->hangup_tq, do_isicom_hangup, port); | ||
2017 | INIT_WORK(&port->bh_tqueue, isicom_bottomhalf, port); | ||
2018 | port->status = 0; | ||
2019 | init_waitqueue_head(&port->open_wait); | ||
2020 | init_waitqueue_head(&port->close_wait); | ||
2021 | /* . . . */ | ||
2022 | } | ||
2023 | isi_card[idx].base = 0; | ||
2024 | isi_card[idx].irq = 0; | ||
1979 | 2025 | ||
1980 | if (pci_enable_device(dev)) | 2026 | if (!io[idx]) |
1981 | break; | 2027 | continue; |
1982 | 2028 | ||
1983 | /* found a PCI ISI card! */ | 2029 | if (irq[idx] == 2 || irq[idx] == 3 || irq[idx] == 4 || |
1984 | ioaddr = pci_resource_start (dev, 3); | 2030 | irq[idx] == 5 || irq[idx] == 7 || |
1985 | /* i.e at offset 0x1c in the | 2031 | irq[idx] == 10 || irq[idx] == 11 || |
1986 | * PCI configuration register | 2032 | irq[idx] == 12 || irq[idx] == 15) { |
1987 | * space. | 2033 | printk(KERN_ERR "ISICOM: ISA not supported yet.\n"); |
1988 | */ | 2034 | retval = -EINVAL; |
1989 | pciirq = dev->irq; | 2035 | goto error; |
1990 | printk(KERN_INFO "ISI PCI Card(Device ID 0x%x)\n", isicom_pci_tbl[idx].device); | 2036 | } else |
1991 | /* | 2037 | printk(KERN_ERR "ISICOM: Irq %d unsupported. " |
1992 | * allot the first empty slot in the array | 2038 | "Disabling Card%d...\n", irq[idx], idx + 1); |
1993 | */ | ||
1994 | for (count=0; count < BOARD_COUNT; count++) { | ||
1995 | if (isi_card[count].base == 0) { | ||
1996 | isi_card[count].base = ioaddr; | ||
1997 | isi_card[count].irq = pciirq; | ||
1998 | isi_card[count].isa = NO; | ||
1999 | card++; | ||
2000 | break; | ||
2001 | } | ||
2002 | } | ||
2003 | } | ||
2004 | if (card >= BOARD_COUNT) break; | ||
2005 | } | ||
2006 | } | 2039 | } |
2007 | 2040 | ||
2008 | if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) { | 2041 | retval = isicom_register_tty_driver(); |
2009 | printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n"); | 2042 | if (retval < 0) |
2010 | return -EIO; | 2043 | goto error; |
2011 | } | ||
2012 | 2044 | ||
2013 | retval = misc_register(&isiloader_device); | 2045 | retval = pci_register_driver(&isicom_driver); |
2014 | if (retval < 0) { | 2046 | if (retval < 0) { |
2015 | printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.\n"); | 2047 | printk(KERN_ERR "ISICOM: Unable to register pci driver.\n"); |
2016 | return retval; | 2048 | goto errtty; |
2017 | } | 2049 | } |
2018 | 2050 | ||
2019 | if (!isicom_init()) { | 2051 | retval = misc_register(&isiloader_device); |
2020 | if (misc_deregister(&isiloader_device)) | 2052 | if (retval < 0) |
2021 | printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n"); | 2053 | goto errpci; |
2022 | return -EIO; | ||
2023 | } | ||
2024 | 2054 | ||
2025 | init_timer(&tx); | 2055 | init_timer(&tx); |
2026 | tx.expires = jiffies + 1; | 2056 | tx.expires = jiffies + 1; |
@@ -2030,6 +2060,12 @@ static int __devinit isicom_setup(void) | |||
2030 | add_timer(&tx); | 2060 | add_timer(&tx); |
2031 | 2061 | ||
2032 | return 0; | 2062 | return 0; |
2063 | errpci: | ||
2064 | pci_unregister_driver(&isicom_driver); | ||
2065 | errtty: | ||
2066 | isicom_unregister_tty_driver(); | ||
2067 | error: | ||
2068 | return retval; | ||
2033 | } | 2069 | } |
2034 | 2070 | ||
2035 | static void __exit isicom_exit(void) | 2071 | static void __exit isicom_exit(void) |
@@ -2041,13 +2077,8 @@ static void __exit isicom_exit(void) | |||
2041 | while (re_schedule != 2 && index++ < 100) | 2077 | while (re_schedule != 2 && index++ < 100) |
2042 | msleep(10); | 2078 | msleep(10); |
2043 | 2079 | ||
2044 | unregister_isr(); | 2080 | pci_unregister_driver(&isicom_driver); |
2045 | isicom_unregister_tty_driver(); | 2081 | isicom_unregister_tty_driver(); |
2046 | unregister_ioregion(); | ||
2047 | if (tmp_buf) | ||
2048 | free_page((unsigned long)tmp_buf); | ||
2049 | if (misc_deregister(&isiloader_device)) | ||
2050 | printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n"); | ||
2051 | } | 2082 | } |
2052 | 2083 | ||
2053 | module_init(isicom_setup); | 2084 | module_init(isicom_setup); |