diff options
Diffstat (limited to 'drivers/net')
91 files changed, 2751 insertions, 27508 deletions
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c index ce99845d8266..066e22b01a94 100644 --- a/drivers/net/8139cp.c +++ b/drivers/net/8139cp.c | |||
@@ -539,8 +539,7 @@ rx_status_loop: | |||
539 | unsigned buflen; | 539 | unsigned buflen; |
540 | 540 | ||
541 | skb = cp->rx_skb[rx_tail].skb; | 541 | skb = cp->rx_skb[rx_tail].skb; |
542 | if (!skb) | 542 | BUG_ON(!skb); |
543 | BUG(); | ||
544 | 543 | ||
545 | desc = &cp->rx_ring[rx_tail]; | 544 | desc = &cp->rx_ring[rx_tail]; |
546 | status = le32_to_cpu(desc->opts1); | 545 | status = le32_to_cpu(desc->opts1); |
@@ -723,8 +722,7 @@ static void cp_tx (struct cp_private *cp) | |||
723 | break; | 722 | break; |
724 | 723 | ||
725 | skb = cp->tx_skb[tx_tail].skb; | 724 | skb = cp->tx_skb[tx_tail].skb; |
726 | if (!skb) | 725 | BUG_ON(!skb); |
727 | BUG(); | ||
728 | 726 | ||
729 | pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping, | 727 | pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping, |
730 | cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE); | 728 | cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE); |
@@ -1550,8 +1548,7 @@ static void cp_get_ethtool_stats (struct net_device *dev, | |||
1550 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort); | 1548 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_abort); |
1551 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun); | 1549 | tmp_stats[i++] = le16_to_cpu(nic_stats->tx_underrun); |
1552 | tmp_stats[i++] = cp->cp_stats.rx_frags; | 1550 | tmp_stats[i++] = cp->cp_stats.rx_frags; |
1553 | if (i != CP_NUM_STATS) | 1551 | BUG_ON(i != CP_NUM_STATS); |
1554 | BUG(); | ||
1555 | 1552 | ||
1556 | pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma); | 1553 | pci_free_consistent(cp->pdev, sizeof(*nic_stats), nic_stats, dma); |
1557 | } | 1554 | } |
@@ -1856,8 +1853,7 @@ static void cp_remove_one (struct pci_dev *pdev) | |||
1856 | struct net_device *dev = pci_get_drvdata(pdev); | 1853 | struct net_device *dev = pci_get_drvdata(pdev); |
1857 | struct cp_private *cp = netdev_priv(dev); | 1854 | struct cp_private *cp = netdev_priv(dev); |
1858 | 1855 | ||
1859 | if (!dev) | 1856 | BUG_ON(!dev); |
1860 | BUG(); | ||
1861 | unregister_netdev(dev); | 1857 | unregister_netdev(dev); |
1862 | iounmap(cp->regs); | 1858 | iounmap(cp->regs); |
1863 | if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0); | 1859 | if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0); |
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 64e2caf3083d..fabc0607b0f1 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c | |||
@@ -765,8 +765,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
765 | BUGMSG(D_DURING, "in arcnet_interrupt\n"); | 765 | BUGMSG(D_DURING, "in arcnet_interrupt\n"); |
766 | 766 | ||
767 | lp = dev->priv; | 767 | lp = dev->priv; |
768 | if (!lp) | 768 | BUG_ON(!lp); |
769 | BUG(); | ||
770 | 769 | ||
771 | spin_lock(&lp->lock); | 770 | spin_lock(&lp->lock); |
772 | 771 | ||
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index 43150b2bd13f..0d45553ff75c 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c | |||
@@ -125,11 +125,11 @@ static void __init com90xx_probe(void) | |||
125 | if (!io && !irq && !shmem && !*device && com90xx_skip_probe) | 125 | if (!io && !irq && !shmem && !*device && com90xx_skip_probe) |
126 | return; | 126 | return; |
127 | 127 | ||
128 | shmems = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(unsigned long), | 128 | shmems = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(unsigned long), |
129 | GFP_KERNEL); | 129 | GFP_KERNEL); |
130 | if (!shmems) | 130 | if (!shmems) |
131 | return; | 131 | return; |
132 | iomem = kzalloc(((0x10000-0xa0000) / 0x800) * sizeof(void __iomem *), | 132 | iomem = kzalloc(((0x100000-0xa0000) / 0x800) * sizeof(void __iomem *), |
133 | GFP_KERNEL); | 133 | GFP_KERNEL); |
134 | if (!iomem) { | 134 | if (!iomem) { |
135 | kfree(shmems); | 135 | kfree(shmems); |
diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 15032f2c7817..3d306681919e 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * | 2 | * |
3 | * Copyright (C) 2002 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 2002 David S. Miller (davem@redhat.com) |
4 | * Fixed by Pekka Pietikainen (pp@ee.oulu.fi) | 4 | * Fixed by Pekka Pietikainen (pp@ee.oulu.fi) |
5 | * Copyright (C) 2006 Broadcom Corporation. | ||
5 | * | 6 | * |
6 | * Distribute under GPL. | 7 | * Distribute under GPL. |
7 | */ | 8 | */ |
@@ -28,8 +29,8 @@ | |||
28 | 29 | ||
29 | #define DRV_MODULE_NAME "b44" | 30 | #define DRV_MODULE_NAME "b44" |
30 | #define PFX DRV_MODULE_NAME ": " | 31 | #define PFX DRV_MODULE_NAME ": " |
31 | #define DRV_MODULE_VERSION "0.97" | 32 | #define DRV_MODULE_VERSION "1.00" |
32 | #define DRV_MODULE_RELDATE "Nov 30, 2005" | 33 | #define DRV_MODULE_RELDATE "Apr 7, 2006" |
33 | 34 | ||
34 | #define B44_DEF_MSG_ENABLE \ | 35 | #define B44_DEF_MSG_ENABLE \ |
35 | (NETIF_MSG_DRV | \ | 36 | (NETIF_MSG_DRV | \ |
@@ -136,7 +137,7 @@ static inline unsigned long br32(const struct b44 *bp, unsigned long reg) | |||
136 | return readl(bp->regs + reg); | 137 | return readl(bp->regs + reg); |
137 | } | 138 | } |
138 | 139 | ||
139 | static inline void bw32(const struct b44 *bp, | 140 | static inline void bw32(const struct b44 *bp, |
140 | unsigned long reg, unsigned long val) | 141 | unsigned long reg, unsigned long val) |
141 | { | 142 | { |
142 | writel(val, bp->regs + reg); | 143 | writel(val, bp->regs + reg); |
@@ -286,13 +287,13 @@ static void __b44_cam_write(struct b44 *bp, unsigned char *data, int index) | |||
286 | val |= ((u32) data[4]) << 8; | 287 | val |= ((u32) data[4]) << 8; |
287 | val |= ((u32) data[5]) << 0; | 288 | val |= ((u32) data[5]) << 0; |
288 | bw32(bp, B44_CAM_DATA_LO, val); | 289 | bw32(bp, B44_CAM_DATA_LO, val); |
289 | val = (CAM_DATA_HI_VALID | | 290 | val = (CAM_DATA_HI_VALID | |
290 | (((u32) data[0]) << 8) | | 291 | (((u32) data[0]) << 8) | |
291 | (((u32) data[1]) << 0)); | 292 | (((u32) data[1]) << 0)); |
292 | bw32(bp, B44_CAM_DATA_HI, val); | 293 | bw32(bp, B44_CAM_DATA_HI, val); |
293 | bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE | | 294 | bw32(bp, B44_CAM_CTRL, (CAM_CTRL_WRITE | |
294 | (index << CAM_CTRL_INDEX_SHIFT))); | 295 | (index << CAM_CTRL_INDEX_SHIFT))); |
295 | b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1); | 296 | b44_wait_bit(bp, B44_CAM_CTRL, CAM_CTRL_BUSY, 100, 1); |
296 | } | 297 | } |
297 | 298 | ||
298 | static inline void __b44_disable_ints(struct b44 *bp) | 299 | static inline void __b44_disable_ints(struct b44 *bp) |
@@ -410,25 +411,18 @@ static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags) | |||
410 | 411 | ||
411 | static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote) | 412 | static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote) |
412 | { | 413 | { |
413 | u32 pause_enab = bp->flags & (B44_FLAG_TX_PAUSE | | 414 | u32 pause_enab = 0; |
414 | B44_FLAG_RX_PAUSE); | ||
415 | 415 | ||
416 | if (local & ADVERTISE_PAUSE_CAP) { | 416 | /* The driver supports only rx pause by default because |
417 | if (local & ADVERTISE_PAUSE_ASYM) { | 417 | the b44 mac tx pause mechanism generates excessive |
418 | if (remote & LPA_PAUSE_CAP) | 418 | pause frames. |
419 | pause_enab |= (B44_FLAG_TX_PAUSE | | 419 | Use ethtool to turn on b44 tx pause if necessary. |
420 | B44_FLAG_RX_PAUSE); | 420 | */ |
421 | else if (remote & LPA_PAUSE_ASYM) | 421 | if ((local & ADVERTISE_PAUSE_CAP) && |
422 | pause_enab |= B44_FLAG_RX_PAUSE; | 422 | (local & ADVERTISE_PAUSE_ASYM)){ |
423 | } else { | 423 | if ((remote & LPA_PAUSE_ASYM) && |
424 | if (remote & LPA_PAUSE_CAP) | 424 | !(remote & LPA_PAUSE_CAP)) |
425 | pause_enab |= (B44_FLAG_TX_PAUSE | | 425 | pause_enab |= B44_FLAG_RX_PAUSE; |
426 | B44_FLAG_RX_PAUSE); | ||
427 | } | ||
428 | } else if (local & ADVERTISE_PAUSE_ASYM) { | ||
429 | if ((remote & LPA_PAUSE_CAP) && | ||
430 | (remote & LPA_PAUSE_ASYM)) | ||
431 | pause_enab |= B44_FLAG_TX_PAUSE; | ||
432 | } | 426 | } |
433 | 427 | ||
434 | __b44_set_flow_ctrl(bp, pause_enab); | 428 | __b44_set_flow_ctrl(bp, pause_enab); |
@@ -608,8 +602,7 @@ static void b44_tx(struct b44 *bp) | |||
608 | struct ring_info *rp = &bp->tx_buffers[cons]; | 602 | struct ring_info *rp = &bp->tx_buffers[cons]; |
609 | struct sk_buff *skb = rp->skb; | 603 | struct sk_buff *skb = rp->skb; |
610 | 604 | ||
611 | if (unlikely(skb == NULL)) | 605 | BUG_ON(skb == NULL); |
612 | BUG(); | ||
613 | 606 | ||
614 | pci_unmap_single(bp->pdev, | 607 | pci_unmap_single(bp->pdev, |
615 | pci_unmap_addr(rp, mapping), | 608 | pci_unmap_addr(rp, mapping), |
@@ -1064,7 +1057,7 @@ static int b44_change_mtu(struct net_device *dev, int new_mtu) | |||
1064 | spin_unlock_irq(&bp->lock); | 1057 | spin_unlock_irq(&bp->lock); |
1065 | 1058 | ||
1066 | b44_enable_ints(bp); | 1059 | b44_enable_ints(bp); |
1067 | 1060 | ||
1068 | return 0; | 1061 | return 0; |
1069 | } | 1062 | } |
1070 | 1063 | ||
@@ -1382,7 +1375,7 @@ static void b44_init_hw(struct b44 *bp) | |||
1382 | bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); | 1375 | bw32(bp, B44_DMARX_ADDR, bp->rx_ring_dma + bp->dma_offset); |
1383 | 1376 | ||
1384 | bw32(bp, B44_DMARX_PTR, bp->rx_pending); | 1377 | bw32(bp, B44_DMARX_PTR, bp->rx_pending); |
1385 | bp->rx_prod = bp->rx_pending; | 1378 | bp->rx_prod = bp->rx_pending; |
1386 | 1379 | ||
1387 | bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); | 1380 | bw32(bp, B44_MIB_CTRL, MIB_CTRL_CLR_ON_READ); |
1388 | 1381 | ||
@@ -1554,9 +1547,9 @@ static void __b44_set_rx_mode(struct net_device *dev) | |||
1554 | val |= RXCONFIG_ALLMULTI; | 1547 | val |= RXCONFIG_ALLMULTI; |
1555 | else | 1548 | else |
1556 | i = __b44_load_mcast(bp, dev); | 1549 | i = __b44_load_mcast(bp, dev); |
1557 | 1550 | ||
1558 | for (; i < 64; i++) { | 1551 | for (; i < 64; i++) { |
1559 | __b44_cam_write(bp, zero, i); | 1552 | __b44_cam_write(bp, zero, i); |
1560 | } | 1553 | } |
1561 | bw32(bp, B44_RXCONFIG, val); | 1554 | bw32(bp, B44_RXCONFIG, val); |
1562 | val = br32(bp, B44_CAM_CTRL); | 1555 | val = br32(bp, B44_CAM_CTRL); |
@@ -1738,7 +1731,7 @@ static int b44_set_ringparam(struct net_device *dev, | |||
1738 | spin_unlock_irq(&bp->lock); | 1731 | spin_unlock_irq(&bp->lock); |
1739 | 1732 | ||
1740 | b44_enable_ints(bp); | 1733 | b44_enable_ints(bp); |
1741 | 1734 | ||
1742 | return 0; | 1735 | return 0; |
1743 | } | 1736 | } |
1744 | 1737 | ||
@@ -1783,7 +1776,7 @@ static int b44_set_pauseparam(struct net_device *dev, | |||
1783 | spin_unlock_irq(&bp->lock); | 1776 | spin_unlock_irq(&bp->lock); |
1784 | 1777 | ||
1785 | b44_enable_ints(bp); | 1778 | b44_enable_ints(bp); |
1786 | 1779 | ||
1787 | return 0; | 1780 | return 0; |
1788 | } | 1781 | } |
1789 | 1782 | ||
@@ -1899,7 +1892,7 @@ static int __devinit b44_get_invariants(struct b44 *bp) | |||
1899 | bp->core_unit = ssb_core_unit(bp); | 1892 | bp->core_unit = ssb_core_unit(bp); |
1900 | bp->dma_offset = SB_PCI_DMA; | 1893 | bp->dma_offset = SB_PCI_DMA; |
1901 | 1894 | ||
1902 | /* XXX - really required? | 1895 | /* XXX - really required? |
1903 | bp->flags |= B44_FLAG_BUGGY_TXPTR; | 1896 | bp->flags |= B44_FLAG_BUGGY_TXPTR; |
1904 | */ | 1897 | */ |
1905 | out: | 1898 | out: |
@@ -1947,7 +1940,7 @@ static int __devinit b44_init_one(struct pci_dev *pdev, | |||
1947 | "aborting.\n"); | 1940 | "aborting.\n"); |
1948 | goto err_out_free_res; | 1941 | goto err_out_free_res; |
1949 | } | 1942 | } |
1950 | 1943 | ||
1951 | err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK); | 1944 | err = pci_set_consistent_dma_mask(pdev, (u64) B44_DMA_MASK); |
1952 | if (err) { | 1945 | if (err) { |
1953 | printk(KERN_ERR PFX "No usable DMA configuration, " | 1946 | printk(KERN_ERR PFX "No usable DMA configuration, " |
@@ -2042,9 +2035,9 @@ static int __devinit b44_init_one(struct pci_dev *pdev, | |||
2042 | 2035 | ||
2043 | pci_save_state(bp->pdev); | 2036 | pci_save_state(bp->pdev); |
2044 | 2037 | ||
2045 | /* Chip reset provides power to the b44 MAC & PCI cores, which | 2038 | /* Chip reset provides power to the b44 MAC & PCI cores, which |
2046 | * is necessary for MAC register access. | 2039 | * is necessary for MAC register access. |
2047 | */ | 2040 | */ |
2048 | b44_chip_reset(bp); | 2041 | b44_chip_reset(bp); |
2049 | 2042 | ||
2050 | printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name); | 2043 | printk(KERN_INFO "%s: Broadcom 4400 10/100BaseT Ethernet ", dev->name); |
@@ -2092,10 +2085,10 @@ static int b44_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2092 | 2085 | ||
2093 | del_timer_sync(&bp->timer); | 2086 | del_timer_sync(&bp->timer); |
2094 | 2087 | ||
2095 | spin_lock_irq(&bp->lock); | 2088 | spin_lock_irq(&bp->lock); |
2096 | 2089 | ||
2097 | b44_halt(bp); | 2090 | b44_halt(bp); |
2098 | netif_carrier_off(bp->dev); | 2091 | netif_carrier_off(bp->dev); |
2099 | netif_device_detach(bp->dev); | 2092 | netif_device_detach(bp->dev); |
2100 | b44_free_rings(bp); | 2093 | b44_free_rings(bp); |
2101 | 2094 | ||
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 2671da20a496..5ca99e26660a 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -63,7 +63,7 @@ | |||
63 | /* Time in jiffies before concluding the transmitter is hung. */ | 63 | /* Time in jiffies before concluding the transmitter is hung. */ |
64 | #define TX_TIMEOUT (5*HZ) | 64 | #define TX_TIMEOUT (5*HZ) |
65 | 65 | ||
66 | static char version[] __devinitdata = | 66 | static const char version[] __devinitdata = |
67 | "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 67 | "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; |
68 | 68 | ||
69 | MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>"); | 69 | MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>"); |
diff --git a/drivers/net/chelsio/Makefile b/drivers/net/chelsio/Makefile index 91e927827c43..54c78d94f48b 100644 --- a/drivers/net/chelsio/Makefile +++ b/drivers/net/chelsio/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_CHELSIO_T1) += cxgb.o | 5 | obj-$(CONFIG_CHELSIO_T1) += cxgb.o |
6 | 6 | ||
7 | EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/chelsio $(DEBUG_FLAGS) | 7 | EXTRA_CFLAGS += -Idrivers/net/chelsio $(DEBUG_FLAGS) |
8 | 8 | ||
9 | 9 | ||
10 | cxgb-objs := cxgb2.o espi.o pm3393.o sge.o subr.o mv88x201x.o | 10 | cxgb-objs := cxgb2.o espi.o pm3393.o sge.o subr.o mv88x201x.o |
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 30ff8ea1a402..4391bf4bf573 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c | |||
@@ -1093,8 +1093,7 @@ static int process_responses(struct adapter *adapter, int budget) | |||
1093 | if (likely(e->DataValid)) { | 1093 | if (likely(e->DataValid)) { |
1094 | struct freelQ *fl = &sge->freelQ[e->FreelistQid]; | 1094 | struct freelQ *fl = &sge->freelQ[e->FreelistQid]; |
1095 | 1095 | ||
1096 | if (unlikely(!e->Sop || !e->Eop)) | 1096 | BUG_ON(!e->Sop || !e->Eop); |
1097 | BUG(); | ||
1098 | if (unlikely(e->Offload)) | 1097 | if (unlikely(e->Offload)) |
1099 | unexpected_offload(adapter, fl); | 1098 | unexpected_offload(adapter, fl); |
1100 | else | 1099 | else |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 49cd096a3c3d..c99e87838f92 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -3308,8 +3308,7 @@ e1000_clean(struct net_device *poll_dev, int *budget) | |||
3308 | 3308 | ||
3309 | while (poll_dev != &adapter->polling_netdev[i]) { | 3309 | while (poll_dev != &adapter->polling_netdev[i]) { |
3310 | i++; | 3310 | i++; |
3311 | if (unlikely(i == adapter->num_rx_queues)) | 3311 | BUG_ON(i == adapter->num_rx_queues); |
3312 | BUG(); | ||
3313 | } | 3312 | } |
3314 | 3313 | ||
3315 | if (likely(adapter->num_tx_queues == 1)) { | 3314 | if (likely(adapter->num_tx_queues == 1)) { |
@@ -3769,6 +3768,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, | |||
3769 | ps_page->ps_page[j] = NULL; | 3768 | ps_page->ps_page[j] = NULL; |
3770 | skb->len += length; | 3769 | skb->len += length; |
3771 | skb->data_len += length; | 3770 | skb->data_len += length; |
3771 | skb->truesize += length; | ||
3772 | } | 3772 | } |
3773 | 3773 | ||
3774 | copydone: | 3774 | copydone: |
diff --git a/drivers/net/eql.c b/drivers/net/eql.c index aa1569182fd6..815436c6170f 100644 --- a/drivers/net/eql.c +++ b/drivers/net/eql.c | |||
@@ -203,8 +203,7 @@ static int eql_open(struct net_device *dev) | |||
203 | printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on " | 203 | printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on " |
204 | "your slave devices.\n", dev->name); | 204 | "your slave devices.\n", dev->name); |
205 | 205 | ||
206 | if (!list_empty(&eql->queue.all_slaves)) | 206 | BUG_ON(!list_empty(&eql->queue.all_slaves)); |
207 | BUG(); | ||
208 | 207 | ||
209 | eql->min_slaves = 1; | 208 | eql->min_slaves = 1; |
210 | eql->max_slaves = EQL_DEFAULT_MAX_SLAVES; /* 4 usually... */ | 209 | eql->max_slaves = EQL_DEFAULT_MAX_SLAVES; /* 4 usually... */ |
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 7627a75f4f7c..9788b1ef2e7d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -105,6 +105,7 @@ | |||
105 | * 0.50: 20 Jan 2006: Add 8021pq tagging support. | 105 | * 0.50: 20 Jan 2006: Add 8021pq tagging support. |
106 | * 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings. | 106 | * 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings. |
107 | * 0.52: 20 Jan 2006: Add MSI/MSIX support. | 107 | * 0.52: 20 Jan 2006: Add MSI/MSIX support. |
108 | * 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset. | ||
108 | * | 109 | * |
109 | * Known bugs: | 110 | * Known bugs: |
110 | * We suspect that on some hardware no TX done interrupts are generated. | 111 | * We suspect that on some hardware no TX done interrupts are generated. |
@@ -116,7 +117,7 @@ | |||
116 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few | 117 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few |
117 | * superfluous timer interrupts from the nic. | 118 | * superfluous timer interrupts from the nic. |
118 | */ | 119 | */ |
119 | #define FORCEDETH_VERSION "0.52" | 120 | #define FORCEDETH_VERSION "0.53" |
120 | #define DRV_NAME "forcedeth" | 121 | #define DRV_NAME "forcedeth" |
121 | 122 | ||
122 | #include <linux/module.h> | 123 | #include <linux/module.h> |
@@ -160,6 +161,7 @@ | |||
160 | #define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */ | 161 | #define DEV_HAS_VLAN 0x0020 /* device supports vlan tagging and striping */ |
161 | #define DEV_HAS_MSI 0x0040 /* device supports MSI */ | 162 | #define DEV_HAS_MSI 0x0040 /* device supports MSI */ |
162 | #define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ | 163 | #define DEV_HAS_MSI_X 0x0080 /* device supports MSI-X */ |
164 | #define DEV_HAS_POWER_CNTRL 0x0100 /* device supports power savings */ | ||
163 | 165 | ||
164 | enum { | 166 | enum { |
165 | NvRegIrqStatus = 0x000, | 167 | NvRegIrqStatus = 0x000, |
@@ -203,6 +205,8 @@ enum { | |||
203 | #define NVREG_MISC1_HD 0x02 | 205 | #define NVREG_MISC1_HD 0x02 |
204 | #define NVREG_MISC1_FORCE 0x3b0f3c | 206 | #define NVREG_MISC1_FORCE 0x3b0f3c |
205 | 207 | ||
208 | NvRegMacReset = 0x3c, | ||
209 | #define NVREG_MAC_RESET_ASSERT 0x0F3 | ||
206 | NvRegTransmitterControl = 0x084, | 210 | NvRegTransmitterControl = 0x084, |
207 | #define NVREG_XMITCTL_START 0x01 | 211 | #define NVREG_XMITCTL_START 0x01 |
208 | NvRegTransmitterStatus = 0x088, | 212 | NvRegTransmitterStatus = 0x088, |
@@ -326,6 +330,10 @@ enum { | |||
326 | NvRegMSIXMap0 = 0x3e0, | 330 | NvRegMSIXMap0 = 0x3e0, |
327 | NvRegMSIXMap1 = 0x3e4, | 331 | NvRegMSIXMap1 = 0x3e4, |
328 | NvRegMSIXIrqStatus = 0x3f0, | 332 | NvRegMSIXIrqStatus = 0x3f0, |
333 | |||
334 | NvRegPowerState2 = 0x600, | ||
335 | #define NVREG_POWERSTATE2_POWERUP_MASK 0x0F11 | ||
336 | #define NVREG_POWERSTATE2_POWERUP_REV_A3 0x0001 | ||
329 | }; | 337 | }; |
330 | 338 | ||
331 | /* Big endian: should work, but is untested */ | 339 | /* Big endian: should work, but is untested */ |
@@ -414,7 +422,8 @@ typedef union _ring_type { | |||
414 | #define NV_RX3_VLAN_TAG_MASK (0x0000FFFF) | 422 | #define NV_RX3_VLAN_TAG_MASK (0x0000FFFF) |
415 | 423 | ||
416 | /* Miscelaneous hardware related defines: */ | 424 | /* Miscelaneous hardware related defines: */ |
417 | #define NV_PCI_REGSZ 0x270 | 425 | #define NV_PCI_REGSZ_VER1 0x270 |
426 | #define NV_PCI_REGSZ_VER2 0x604 | ||
418 | 427 | ||
419 | /* various timeout delays: all in usec */ | 428 | /* various timeout delays: all in usec */ |
420 | #define NV_TXRX_RESET_DELAY 4 | 429 | #define NV_TXRX_RESET_DELAY 4 |
@@ -431,6 +440,7 @@ typedef union _ring_type { | |||
431 | #define NV_MIIBUSY_DELAY 50 | 440 | #define NV_MIIBUSY_DELAY 50 |
432 | #define NV_MIIPHY_DELAY 10 | 441 | #define NV_MIIPHY_DELAY 10 |
433 | #define NV_MIIPHY_DELAYMAX 10000 | 442 | #define NV_MIIPHY_DELAYMAX 10000 |
443 | #define NV_MAC_RESET_DELAY 64 | ||
434 | 444 | ||
435 | #define NV_WAKEUPPATTERNS 5 | 445 | #define NV_WAKEUPPATTERNS 5 |
436 | #define NV_WAKEUPMASKENTRIES 4 | 446 | #define NV_WAKEUPMASKENTRIES 4 |
@@ -552,6 +562,8 @@ struct fe_priv { | |||
552 | u32 desc_ver; | 562 | u32 desc_ver; |
553 | u32 txrxctl_bits; | 563 | u32 txrxctl_bits; |
554 | u32 vlanctl_bits; | 564 | u32 vlanctl_bits; |
565 | u32 driver_data; | ||
566 | u32 register_size; | ||
555 | 567 | ||
556 | void __iomem *base; | 568 | void __iomem *base; |
557 | 569 | ||
@@ -919,6 +931,24 @@ static void nv_txrx_reset(struct net_device *dev) | |||
919 | pci_push(base); | 931 | pci_push(base); |
920 | } | 932 | } |
921 | 933 | ||
934 | static void nv_mac_reset(struct net_device *dev) | ||
935 | { | ||
936 | struct fe_priv *np = netdev_priv(dev); | ||
937 | u8 __iomem *base = get_hwbase(dev); | ||
938 | |||
939 | dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name); | ||
940 | writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); | ||
941 | pci_push(base); | ||
942 | writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset); | ||
943 | pci_push(base); | ||
944 | udelay(NV_MAC_RESET_DELAY); | ||
945 | writel(0, base + NvRegMacReset); | ||
946 | pci_push(base); | ||
947 | udelay(NV_MAC_RESET_DELAY); | ||
948 | writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl); | ||
949 | pci_push(base); | ||
950 | } | ||
951 | |||
922 | /* | 952 | /* |
923 | * nv_get_stats: dev->get_stats function | 953 | * nv_get_stats: dev->get_stats function |
924 | * Get latest stats value from the nic. | 954 | * Get latest stats value from the nic. |
@@ -1331,7 +1361,7 @@ static void nv_tx_timeout(struct net_device *dev) | |||
1331 | dev->name, (unsigned long)np->ring_addr, | 1361 | dev->name, (unsigned long)np->ring_addr, |
1332 | np->next_tx, np->nic_tx); | 1362 | np->next_tx, np->nic_tx); |
1333 | printk(KERN_INFO "%s: Dumping tx registers\n", dev->name); | 1363 | printk(KERN_INFO "%s: Dumping tx registers\n", dev->name); |
1334 | for (i=0;i<0x400;i+= 32) { | 1364 | for (i=0;i<=np->register_size;i+= 32) { |
1335 | printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n", | 1365 | printk(KERN_INFO "%3x: %08x %08x %08x %08x %08x %08x %08x %08x\n", |
1336 | i, | 1366 | i, |
1337 | readl(base + i + 0), readl(base + i + 4), | 1367 | readl(base + i + 0), readl(base + i + 4), |
@@ -2488,11 +2518,11 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
2488 | } | 2518 | } |
2489 | 2519 | ||
2490 | #define FORCEDETH_REGS_VER 1 | 2520 | #define FORCEDETH_REGS_VER 1 |
2491 | #define FORCEDETH_REGS_SIZE 0x400 /* 256 32-bit registers */ | ||
2492 | 2521 | ||
2493 | static int nv_get_regs_len(struct net_device *dev) | 2522 | static int nv_get_regs_len(struct net_device *dev) |
2494 | { | 2523 | { |
2495 | return FORCEDETH_REGS_SIZE; | 2524 | struct fe_priv *np = netdev_priv(dev); |
2525 | return np->register_size; | ||
2496 | } | 2526 | } |
2497 | 2527 | ||
2498 | static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) | 2528 | static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf) |
@@ -2504,7 +2534,7 @@ static void nv_get_regs(struct net_device *dev, struct ethtool_regs *regs, void | |||
2504 | 2534 | ||
2505 | regs->version = FORCEDETH_REGS_VER; | 2535 | regs->version = FORCEDETH_REGS_VER; |
2506 | spin_lock_irq(&np->lock); | 2536 | spin_lock_irq(&np->lock); |
2507 | for (i=0;i<FORCEDETH_REGS_SIZE/sizeof(u32);i++) | 2537 | for (i = 0;i <= np->register_size/sizeof(u32); i++) |
2508 | rbuf[i] = readl(base + i*sizeof(u32)); | 2538 | rbuf[i] = readl(base + i*sizeof(u32)); |
2509 | spin_unlock_irq(&np->lock); | 2539 | spin_unlock_irq(&np->lock); |
2510 | } | 2540 | } |
@@ -2608,6 +2638,8 @@ static int nv_open(struct net_device *dev) | |||
2608 | dprintk(KERN_DEBUG "nv_open: begin\n"); | 2638 | dprintk(KERN_DEBUG "nv_open: begin\n"); |
2609 | 2639 | ||
2610 | /* 1) erase previous misconfiguration */ | 2640 | /* 1) erase previous misconfiguration */ |
2641 | if (np->driver_data & DEV_HAS_POWER_CNTRL) | ||
2642 | nv_mac_reset(dev); | ||
2611 | /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */ | 2643 | /* 4.1-1: stop adapter: ignored, 4.3 seems to be overkill */ |
2612 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); | 2644 | writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); |
2613 | writel(0, base + NvRegMulticastAddrB); | 2645 | writel(0, base + NvRegMulticastAddrB); |
@@ -2878,6 +2910,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2878 | unsigned long addr; | 2910 | unsigned long addr; |
2879 | u8 __iomem *base; | 2911 | u8 __iomem *base; |
2880 | int err, i; | 2912 | int err, i; |
2913 | u32 powerstate; | ||
2881 | 2914 | ||
2882 | dev = alloc_etherdev(sizeof(struct fe_priv)); | 2915 | dev = alloc_etherdev(sizeof(struct fe_priv)); |
2883 | err = -ENOMEM; | 2916 | err = -ENOMEM; |
@@ -2910,6 +2943,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2910 | if (err < 0) | 2943 | if (err < 0) |
2911 | goto out_disable; | 2944 | goto out_disable; |
2912 | 2945 | ||
2946 | if (id->driver_data & (DEV_HAS_VLAN|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL)) | ||
2947 | np->register_size = NV_PCI_REGSZ_VER2; | ||
2948 | else | ||
2949 | np->register_size = NV_PCI_REGSZ_VER1; | ||
2950 | |||
2913 | err = -EINVAL; | 2951 | err = -EINVAL; |
2914 | addr = 0; | 2952 | addr = 0; |
2915 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { | 2953 | for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { |
@@ -2918,7 +2956,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2918 | pci_resource_len(pci_dev, i), | 2956 | pci_resource_len(pci_dev, i), |
2919 | pci_resource_flags(pci_dev, i)); | 2957 | pci_resource_flags(pci_dev, i)); |
2920 | if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM && | 2958 | if (pci_resource_flags(pci_dev, i) & IORESOURCE_MEM && |
2921 | pci_resource_len(pci_dev, i) >= NV_PCI_REGSZ) { | 2959 | pci_resource_len(pci_dev, i) >= np->register_size) { |
2922 | addr = pci_resource_start(pci_dev, i); | 2960 | addr = pci_resource_start(pci_dev, i); |
2923 | break; | 2961 | break; |
2924 | } | 2962 | } |
@@ -2929,6 +2967,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2929 | goto out_relreg; | 2967 | goto out_relreg; |
2930 | } | 2968 | } |
2931 | 2969 | ||
2970 | /* copy of driver data */ | ||
2971 | np->driver_data = id->driver_data; | ||
2972 | |||
2932 | /* handle different descriptor versions */ | 2973 | /* handle different descriptor versions */ |
2933 | if (id->driver_data & DEV_HAS_HIGH_DMA) { | 2974 | if (id->driver_data & DEV_HAS_HIGH_DMA) { |
2934 | /* packet format 3: supports 40-bit addressing */ | 2975 | /* packet format 3: supports 40-bit addressing */ |
@@ -2986,7 +3027,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2986 | } | 3027 | } |
2987 | 3028 | ||
2988 | err = -ENOMEM; | 3029 | err = -ENOMEM; |
2989 | np->base = ioremap(addr, NV_PCI_REGSZ); | 3030 | np->base = ioremap(addr, np->register_size); |
2990 | if (!np->base) | 3031 | if (!np->base) |
2991 | goto out_relreg; | 3032 | goto out_relreg; |
2992 | dev->base_addr = (unsigned long)np->base; | 3033 | dev->base_addr = (unsigned long)np->base; |
@@ -3062,6 +3103,20 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
3062 | writel(0, base + NvRegWakeUpFlags); | 3103 | writel(0, base + NvRegWakeUpFlags); |
3063 | np->wolenabled = 0; | 3104 | np->wolenabled = 0; |
3064 | 3105 | ||
3106 | if (id->driver_data & DEV_HAS_POWER_CNTRL) { | ||
3107 | u8 revision_id; | ||
3108 | pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id); | ||
3109 | |||
3110 | /* take phy and nic out of low power mode */ | ||
3111 | powerstate = readl(base + NvRegPowerState2); | ||
3112 | powerstate &= ~NVREG_POWERSTATE2_POWERUP_MASK; | ||
3113 | if ((id->device == PCI_DEVICE_ID_NVIDIA_NVENET_12 || | ||
3114 | id->device == PCI_DEVICE_ID_NVIDIA_NVENET_13) && | ||
3115 | revision_id >= 0xA3) | ||
3116 | powerstate |= NVREG_POWERSTATE2_POWERUP_REV_A3; | ||
3117 | writel(powerstate, base + NvRegPowerState2); | ||
3118 | } | ||
3119 | |||
3065 | if (np->desc_ver == DESC_VER_1) { | 3120 | if (np->desc_ver == DESC_VER_1) { |
3066 | np->tx_flags = NV_TX_VALID; | 3121 | np->tx_flags = NV_TX_VALID; |
3067 | } else { | 3122 | } else { |
@@ -3223,19 +3278,19 @@ static struct pci_device_id pci_tbl[] = { | |||
3223 | }, | 3278 | }, |
3224 | { /* MCP51 Ethernet Controller */ | 3279 | { /* MCP51 Ethernet Controller */ |
3225 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12), | 3280 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_12), |
3226 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA, | 3281 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL, |
3227 | }, | 3282 | }, |
3228 | { /* MCP51 Ethernet Controller */ | 3283 | { /* MCP51 Ethernet Controller */ |
3229 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13), | 3284 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_13), |
3230 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA, | 3285 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL, |
3231 | }, | 3286 | }, |
3232 | { /* MCP55 Ethernet Controller */ | 3287 | { /* MCP55 Ethernet Controller */ |
3233 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), | 3288 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), |
3234 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X, | 3289 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL, |
3235 | }, | 3290 | }, |
3236 | { /* MCP55 Ethernet Controller */ | 3291 | { /* MCP55 Ethernet Controller */ |
3237 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), | 3292 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), |
3238 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X, | 3293 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL, |
3239 | }, | 3294 | }, |
3240 | {0,}, | 3295 | {0,}, |
3241 | }; | 3296 | }; |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 771e25d8c417..218d31764c52 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -210,7 +210,8 @@ static int gfar_probe(struct platform_device *pdev) | |||
210 | goto regs_fail; | 210 | goto regs_fail; |
211 | } | 211 | } |
212 | 212 | ||
213 | spin_lock_init(&priv->lock); | 213 | spin_lock_init(&priv->txlock); |
214 | spin_lock_init(&priv->rxlock); | ||
214 | 215 | ||
215 | platform_set_drvdata(pdev, dev); | 216 | platform_set_drvdata(pdev, dev); |
216 | 217 | ||
@@ -515,11 +516,13 @@ void stop_gfar(struct net_device *dev) | |||
515 | phy_stop(priv->phydev); | 516 | phy_stop(priv->phydev); |
516 | 517 | ||
517 | /* Lock it down */ | 518 | /* Lock it down */ |
518 | spin_lock_irqsave(&priv->lock, flags); | 519 | spin_lock_irqsave(&priv->txlock, flags); |
520 | spin_lock(&priv->rxlock); | ||
519 | 521 | ||
520 | gfar_halt(dev); | 522 | gfar_halt(dev); |
521 | 523 | ||
522 | spin_unlock_irqrestore(&priv->lock, flags); | 524 | spin_unlock(&priv->rxlock); |
525 | spin_unlock_irqrestore(&priv->txlock, flags); | ||
523 | 526 | ||
524 | /* Free the IRQs */ | 527 | /* Free the IRQs */ |
525 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { | 528 | if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { |
@@ -605,14 +608,15 @@ void gfar_start(struct net_device *dev) | |||
605 | tempval |= DMACTRL_INIT_SETTINGS; | 608 | tempval |= DMACTRL_INIT_SETTINGS; |
606 | gfar_write(&priv->regs->dmactrl, tempval); | 609 | gfar_write(&priv->regs->dmactrl, tempval); |
607 | 610 | ||
608 | /* Clear THLT, so that the DMA starts polling now */ | ||
609 | gfar_write(®s->tstat, TSTAT_CLEAR_THALT); | ||
610 | |||
611 | /* Make sure we aren't stopped */ | 611 | /* Make sure we aren't stopped */ |
612 | tempval = gfar_read(&priv->regs->dmactrl); | 612 | tempval = gfar_read(&priv->regs->dmactrl); |
613 | tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); | 613 | tempval &= ~(DMACTRL_GRS | DMACTRL_GTS); |
614 | gfar_write(&priv->regs->dmactrl, tempval); | 614 | gfar_write(&priv->regs->dmactrl, tempval); |
615 | 615 | ||
616 | /* Clear THLT/RHLT, so that the DMA starts polling now */ | ||
617 | gfar_write(®s->tstat, TSTAT_CLEAR_THALT); | ||
618 | gfar_write(®s->rstat, RSTAT_CLEAR_RHALT); | ||
619 | |||
616 | /* Unmask the interrupts we look for */ | 620 | /* Unmask the interrupts we look for */ |
617 | gfar_write(®s->imask, IMASK_DEFAULT); | 621 | gfar_write(®s->imask, IMASK_DEFAULT); |
618 | } | 622 | } |
@@ -928,12 +932,13 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
928 | struct txfcb *fcb = NULL; | 932 | struct txfcb *fcb = NULL; |
929 | struct txbd8 *txbdp; | 933 | struct txbd8 *txbdp; |
930 | u16 status; | 934 | u16 status; |
935 | unsigned long flags; | ||
931 | 936 | ||
932 | /* Update transmit stats */ | 937 | /* Update transmit stats */ |
933 | priv->stats.tx_bytes += skb->len; | 938 | priv->stats.tx_bytes += skb->len; |
934 | 939 | ||
935 | /* Lock priv now */ | 940 | /* Lock priv now */ |
936 | spin_lock_irq(&priv->lock); | 941 | spin_lock_irqsave(&priv->txlock, flags); |
937 | 942 | ||
938 | /* Point at the first free tx descriptor */ | 943 | /* Point at the first free tx descriptor */ |
939 | txbdp = priv->cur_tx; | 944 | txbdp = priv->cur_tx; |
@@ -1004,7 +1009,7 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1004 | gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); | 1009 | gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT); |
1005 | 1010 | ||
1006 | /* Unlock priv */ | 1011 | /* Unlock priv */ |
1007 | spin_unlock_irq(&priv->lock); | 1012 | spin_unlock_irqrestore(&priv->txlock, flags); |
1008 | 1013 | ||
1009 | return 0; | 1014 | return 0; |
1010 | } | 1015 | } |
@@ -1049,7 +1054,7 @@ static void gfar_vlan_rx_register(struct net_device *dev, | |||
1049 | unsigned long flags; | 1054 | unsigned long flags; |
1050 | u32 tempval; | 1055 | u32 tempval; |
1051 | 1056 | ||
1052 | spin_lock_irqsave(&priv->lock, flags); | 1057 | spin_lock_irqsave(&priv->rxlock, flags); |
1053 | 1058 | ||
1054 | priv->vlgrp = grp; | 1059 | priv->vlgrp = grp; |
1055 | 1060 | ||
@@ -1076,7 +1081,7 @@ static void gfar_vlan_rx_register(struct net_device *dev, | |||
1076 | gfar_write(&priv->regs->rctrl, tempval); | 1081 | gfar_write(&priv->regs->rctrl, tempval); |
1077 | } | 1082 | } |
1078 | 1083 | ||
1079 | spin_unlock_irqrestore(&priv->lock, flags); | 1084 | spin_unlock_irqrestore(&priv->rxlock, flags); |
1080 | } | 1085 | } |
1081 | 1086 | ||
1082 | 1087 | ||
@@ -1085,12 +1090,12 @@ static void gfar_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid) | |||
1085 | struct gfar_private *priv = netdev_priv(dev); | 1090 | struct gfar_private *priv = netdev_priv(dev); |
1086 | unsigned long flags; | 1091 | unsigned long flags; |
1087 | 1092 | ||
1088 | spin_lock_irqsave(&priv->lock, flags); | 1093 | spin_lock_irqsave(&priv->rxlock, flags); |
1089 | 1094 | ||
1090 | if (priv->vlgrp) | 1095 | if (priv->vlgrp) |
1091 | priv->vlgrp->vlan_devices[vid] = NULL; | 1096 | priv->vlgrp->vlan_devices[vid] = NULL; |
1092 | 1097 | ||
1093 | spin_unlock_irqrestore(&priv->lock, flags); | 1098 | spin_unlock_irqrestore(&priv->rxlock, flags); |
1094 | } | 1099 | } |
1095 | 1100 | ||
1096 | 1101 | ||
@@ -1179,7 +1184,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs) | |||
1179 | gfar_write(&priv->regs->ievent, IEVENT_TX_MASK); | 1184 | gfar_write(&priv->regs->ievent, IEVENT_TX_MASK); |
1180 | 1185 | ||
1181 | /* Lock priv */ | 1186 | /* Lock priv */ |
1182 | spin_lock(&priv->lock); | 1187 | spin_lock(&priv->txlock); |
1183 | bdp = priv->dirty_tx; | 1188 | bdp = priv->dirty_tx; |
1184 | while ((bdp->status & TXBD_READY) == 0) { | 1189 | while ((bdp->status & TXBD_READY) == 0) { |
1185 | /* If dirty_tx and cur_tx are the same, then either the */ | 1190 | /* If dirty_tx and cur_tx are the same, then either the */ |
@@ -1224,7 +1229,7 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id, struct pt_regs *regs) | |||
1224 | else | 1229 | else |
1225 | gfar_write(&priv->regs->txic, 0); | 1230 | gfar_write(&priv->regs->txic, 0); |
1226 | 1231 | ||
1227 | spin_unlock(&priv->lock); | 1232 | spin_unlock(&priv->txlock); |
1228 | 1233 | ||
1229 | return IRQ_HANDLED; | 1234 | return IRQ_HANDLED; |
1230 | } | 1235 | } |
@@ -1305,9 +1310,10 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) | |||
1305 | { | 1310 | { |
1306 | struct net_device *dev = (struct net_device *) dev_id; | 1311 | struct net_device *dev = (struct net_device *) dev_id; |
1307 | struct gfar_private *priv = netdev_priv(dev); | 1312 | struct gfar_private *priv = netdev_priv(dev); |
1308 | |||
1309 | #ifdef CONFIG_GFAR_NAPI | 1313 | #ifdef CONFIG_GFAR_NAPI |
1310 | u32 tempval; | 1314 | u32 tempval; |
1315 | #else | ||
1316 | unsigned long flags; | ||
1311 | #endif | 1317 | #endif |
1312 | 1318 | ||
1313 | /* Clear IEVENT, so rx interrupt isn't called again | 1319 | /* Clear IEVENT, so rx interrupt isn't called again |
@@ -1330,7 +1336,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) | |||
1330 | } | 1336 | } |
1331 | #else | 1337 | #else |
1332 | 1338 | ||
1333 | spin_lock(&priv->lock); | 1339 | spin_lock_irqsave(&priv->rxlock, flags); |
1334 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | 1340 | gfar_clean_rx_ring(dev, priv->rx_ring_size); |
1335 | 1341 | ||
1336 | /* If we are coalescing interrupts, update the timer */ | 1342 | /* If we are coalescing interrupts, update the timer */ |
@@ -1341,7 +1347,7 @@ irqreturn_t gfar_receive(int irq, void *dev_id, struct pt_regs *regs) | |||
1341 | else | 1347 | else |
1342 | gfar_write(&priv->regs->rxic, 0); | 1348 | gfar_write(&priv->regs->rxic, 0); |
1343 | 1349 | ||
1344 | spin_unlock(&priv->lock); | 1350 | spin_unlock_irqrestore(&priv->rxlock, flags); |
1345 | #endif | 1351 | #endif |
1346 | 1352 | ||
1347 | return IRQ_HANDLED; | 1353 | return IRQ_HANDLED; |
@@ -1490,13 +1496,6 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) | |||
1490 | /* Update the current rxbd pointer to be the next one */ | 1496 | /* Update the current rxbd pointer to be the next one */ |
1491 | priv->cur_rx = bdp; | 1497 | priv->cur_rx = bdp; |
1492 | 1498 | ||
1493 | /* If no packets have arrived since the | ||
1494 | * last one we processed, clear the IEVENT RX and | ||
1495 | * BSY bits so that another interrupt won't be | ||
1496 | * generated when we set IMASK */ | ||
1497 | if (bdp->status & RXBD_EMPTY) | ||
1498 | gfar_write(&priv->regs->ievent, IEVENT_RX_MASK); | ||
1499 | |||
1500 | return howmany; | 1499 | return howmany; |
1501 | } | 1500 | } |
1502 | 1501 | ||
@@ -1516,7 +1515,7 @@ static int gfar_poll(struct net_device *dev, int *budget) | |||
1516 | rx_work_limit -= howmany; | 1515 | rx_work_limit -= howmany; |
1517 | *budget -= howmany; | 1516 | *budget -= howmany; |
1518 | 1517 | ||
1519 | if (rx_work_limit >= 0) { | 1518 | if (rx_work_limit > 0) { |
1520 | netif_rx_complete(dev); | 1519 | netif_rx_complete(dev); |
1521 | 1520 | ||
1522 | /* Clear the halt bit in RSTAT */ | 1521 | /* Clear the halt bit in RSTAT */ |
@@ -1533,7 +1532,8 @@ static int gfar_poll(struct net_device *dev, int *budget) | |||
1533 | gfar_write(&priv->regs->rxic, 0); | 1532 | gfar_write(&priv->regs->rxic, 0); |
1534 | } | 1533 | } |
1535 | 1534 | ||
1536 | return (rx_work_limit < 0) ? 1 : 0; | 1535 | /* Return 1 if there's more work to do */ |
1536 | return (rx_work_limit > 0) ? 0 : 1; | ||
1537 | } | 1537 | } |
1538 | #endif | 1538 | #endif |
1539 | 1539 | ||
@@ -1629,7 +1629,7 @@ static void adjust_link(struct net_device *dev) | |||
1629 | struct phy_device *phydev = priv->phydev; | 1629 | struct phy_device *phydev = priv->phydev; |
1630 | int new_state = 0; | 1630 | int new_state = 0; |
1631 | 1631 | ||
1632 | spin_lock_irqsave(&priv->lock, flags); | 1632 | spin_lock_irqsave(&priv->txlock, flags); |
1633 | if (phydev->link) { | 1633 | if (phydev->link) { |
1634 | u32 tempval = gfar_read(®s->maccfg2); | 1634 | u32 tempval = gfar_read(®s->maccfg2); |
1635 | u32 ecntrl = gfar_read(®s->ecntrl); | 1635 | u32 ecntrl = gfar_read(®s->ecntrl); |
@@ -1694,7 +1694,7 @@ static void adjust_link(struct net_device *dev) | |||
1694 | if (new_state && netif_msg_link(priv)) | 1694 | if (new_state && netif_msg_link(priv)) |
1695 | phy_print_status(phydev); | 1695 | phy_print_status(phydev); |
1696 | 1696 | ||
1697 | spin_unlock_irqrestore(&priv->lock, flags); | 1697 | spin_unlock_irqrestore(&priv->txlock, flags); |
1698 | } | 1698 | } |
1699 | 1699 | ||
1700 | /* Update the hash table based on the current list of multicast | 1700 | /* Update the hash table based on the current list of multicast |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index d37d5401be6e..127c98cf3336 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
@@ -656,43 +656,62 @@ struct gfar { | |||
656 | * the buffer descriptor determines the actual condition. | 656 | * the buffer descriptor determines the actual condition. |
657 | */ | 657 | */ |
658 | struct gfar_private { | 658 | struct gfar_private { |
659 | /* pointers to arrays of skbuffs for tx and rx */ | 659 | /* Fields controlled by TX lock */ |
660 | spinlock_t txlock; | ||
661 | |||
662 | /* Pointer to the array of skbuffs */ | ||
660 | struct sk_buff ** tx_skbuff; | 663 | struct sk_buff ** tx_skbuff; |
661 | struct sk_buff ** rx_skbuff; | ||
662 | 664 | ||
663 | /* indices pointing to the next free sbk in skb arrays */ | 665 | /* next free skb in the array */ |
664 | u16 skb_curtx; | 666 | u16 skb_curtx; |
665 | u16 skb_currx; | ||
666 | 667 | ||
667 | /* index of the first skb which hasn't been transmitted | 668 | /* First skb in line to be transmitted */ |
668 | * yet. */ | ||
669 | u16 skb_dirtytx; | 669 | u16 skb_dirtytx; |
670 | 670 | ||
671 | /* Configuration info for the coalescing features */ | 671 | /* Configuration info for the coalescing features */ |
672 | unsigned char txcoalescing; | 672 | unsigned char txcoalescing; |
673 | unsigned short txcount; | 673 | unsigned short txcount; |
674 | unsigned short txtime; | 674 | unsigned short txtime; |
675 | |||
676 | /* Buffer descriptor pointers */ | ||
677 | struct txbd8 *tx_bd_base; /* First tx buffer descriptor */ | ||
678 | struct txbd8 *cur_tx; /* Next free ring entry */ | ||
679 | struct txbd8 *dirty_tx; /* First buffer in line | ||
680 | to be transmitted */ | ||
681 | unsigned int tx_ring_size; | ||
682 | |||
683 | /* RX Locked fields */ | ||
684 | spinlock_t rxlock; | ||
685 | |||
686 | /* skb array and index */ | ||
687 | struct sk_buff ** rx_skbuff; | ||
688 | u16 skb_currx; | ||
689 | |||
690 | /* RX Coalescing values */ | ||
675 | unsigned char rxcoalescing; | 691 | unsigned char rxcoalescing; |
676 | unsigned short rxcount; | 692 | unsigned short rxcount; |
677 | unsigned short rxtime; | 693 | unsigned short rxtime; |
678 | 694 | ||
679 | /* GFAR addresses */ | 695 | struct rxbd8 *rx_bd_base; /* First Rx buffers */ |
680 | struct rxbd8 *rx_bd_base; /* Base addresses of Rx and Tx Buffers */ | ||
681 | struct txbd8 *tx_bd_base; | ||
682 | struct rxbd8 *cur_rx; /* Next free rx ring entry */ | 696 | struct rxbd8 *cur_rx; /* Next free rx ring entry */ |
683 | struct txbd8 *cur_tx; /* Next free ring entry */ | 697 | |
684 | struct txbd8 *dirty_tx; /* The Ring entry to be freed. */ | 698 | /* RX parameters */ |
685 | struct gfar __iomem *regs; /* Pointer to the GFAR memory mapped Registers */ | 699 | unsigned int rx_ring_size; |
686 | u32 __iomem *hash_regs[16]; | ||
687 | int hash_width; | ||
688 | struct net_device_stats stats; /* linux network statistics */ | ||
689 | struct gfar_extra_stats extra_stats; | ||
690 | spinlock_t lock; | ||
691 | unsigned int rx_buffer_size; | 700 | unsigned int rx_buffer_size; |
692 | unsigned int rx_stash_size; | 701 | unsigned int rx_stash_size; |
693 | unsigned int rx_stash_index; | 702 | unsigned int rx_stash_index; |
694 | unsigned int tx_ring_size; | 703 | |
695 | unsigned int rx_ring_size; | 704 | struct vlan_group *vlgrp; |
705 | |||
706 | /* Unprotected fields */ | ||
707 | /* Pointer to the GFAR memory mapped Registers */ | ||
708 | struct gfar __iomem *regs; | ||
709 | |||
710 | /* Hash registers and their width */ | ||
711 | u32 __iomem *hash_regs[16]; | ||
712 | int hash_width; | ||
713 | |||
714 | /* global parameters */ | ||
696 | unsigned int fifo_threshold; | 715 | unsigned int fifo_threshold; |
697 | unsigned int fifo_starve; | 716 | unsigned int fifo_starve; |
698 | unsigned int fifo_starve_off; | 717 | unsigned int fifo_starve_off; |
@@ -702,13 +721,15 @@ struct gfar_private { | |||
702 | extended_hash:1, | 721 | extended_hash:1, |
703 | bd_stash_en:1; | 722 | bd_stash_en:1; |
704 | unsigned short padding; | 723 | unsigned short padding; |
705 | struct vlan_group *vlgrp; | 724 | |
706 | /* Info structure initialized by board setup code */ | ||
707 | unsigned int interruptTransmit; | 725 | unsigned int interruptTransmit; |
708 | unsigned int interruptReceive; | 726 | unsigned int interruptReceive; |
709 | unsigned int interruptError; | 727 | unsigned int interruptError; |
728 | |||
729 | /* info structure initialized by platform code */ | ||
710 | struct gianfar_platform_data *einfo; | 730 | struct gianfar_platform_data *einfo; |
711 | 731 | ||
732 | /* PHY stuff */ | ||
712 | struct phy_device *phydev; | 733 | struct phy_device *phydev; |
713 | struct mii_bus *mii_bus; | 734 | struct mii_bus *mii_bus; |
714 | int oldspeed; | 735 | int oldspeed; |
@@ -716,6 +737,10 @@ struct gfar_private { | |||
716 | int oldlink; | 737 | int oldlink; |
717 | 738 | ||
718 | uint32_t msg_enable; | 739 | uint32_t msg_enable; |
740 | |||
741 | /* Network Statistics */ | ||
742 | struct net_device_stats stats; | ||
743 | struct gfar_extra_stats extra_stats; | ||
719 | }; | 744 | }; |
720 | 745 | ||
721 | static inline u32 gfar_read(volatile unsigned __iomem *addr) | 746 | static inline u32 gfar_read(volatile unsigned __iomem *addr) |
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 5de7b2e259dc..d69698c695ef 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
@@ -455,10 +455,14 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva | |||
455 | 455 | ||
456 | /* Halt TX and RX, and process the frames which | 456 | /* Halt TX and RX, and process the frames which |
457 | * have already been received */ | 457 | * have already been received */ |
458 | spin_lock_irqsave(&priv->lock, flags); | 458 | spin_lock_irqsave(&priv->txlock, flags); |
459 | spin_lock(&priv->rxlock); | ||
460 | |||
459 | gfar_halt(dev); | 461 | gfar_halt(dev); |
460 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | 462 | gfar_clean_rx_ring(dev, priv->rx_ring_size); |
461 | spin_unlock_irqrestore(&priv->lock, flags); | 463 | |
464 | spin_unlock(&priv->rxlock); | ||
465 | spin_unlock_irqrestore(&priv->txlock, flags); | ||
462 | 466 | ||
463 | /* Now we take down the rings to rebuild them */ | 467 | /* Now we take down the rings to rebuild them */ |
464 | stop_gfar(dev); | 468 | stop_gfar(dev); |
@@ -488,10 +492,14 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) | |||
488 | 492 | ||
489 | /* Halt TX and RX, and process the frames which | 493 | /* Halt TX and RX, and process the frames which |
490 | * have already been received */ | 494 | * have already been received */ |
491 | spin_lock_irqsave(&priv->lock, flags); | 495 | spin_lock_irqsave(&priv->txlock, flags); |
496 | spin_lock(&priv->rxlock); | ||
497 | |||
492 | gfar_halt(dev); | 498 | gfar_halt(dev); |
493 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | 499 | gfar_clean_rx_ring(dev, priv->rx_ring_size); |
494 | spin_unlock_irqrestore(&priv->lock, flags); | 500 | |
501 | spin_unlock(&priv->rxlock); | ||
502 | spin_unlock_irqrestore(&priv->txlock, flags); | ||
495 | 503 | ||
496 | /* Now we take down the rings to rebuild them */ | 504 | /* Now we take down the rings to rebuild them */ |
497 | stop_gfar(dev); | 505 | stop_gfar(dev); |
@@ -523,7 +531,7 @@ static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) | |||
523 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | 531 | if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) |
524 | return -EOPNOTSUPP; | 532 | return -EOPNOTSUPP; |
525 | 533 | ||
526 | spin_lock_irqsave(&priv->lock, flags); | 534 | spin_lock_irqsave(&priv->txlock, flags); |
527 | gfar_halt(dev); | 535 | gfar_halt(dev); |
528 | 536 | ||
529 | if (data) | 537 | if (data) |
@@ -532,7 +540,7 @@ static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) | |||
532 | dev->features &= ~NETIF_F_IP_CSUM; | 540 | dev->features &= ~NETIF_F_IP_CSUM; |
533 | 541 | ||
534 | gfar_start(dev); | 542 | gfar_start(dev); |
535 | spin_unlock_irqrestore(&priv->lock, flags); | 543 | spin_unlock_irqrestore(&priv->txlock, flags); |
536 | 544 | ||
537 | return 0; | 545 | return 0; |
538 | } | 546 | } |
diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c index 51ef181b1368..a6d5c43199cb 100644 --- a/drivers/net/gianfar_sysfs.c +++ b/drivers/net/gianfar_sysfs.c | |||
@@ -82,7 +82,7 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev, | |||
82 | else | 82 | else |
83 | return count; | 83 | return count; |
84 | 84 | ||
85 | spin_lock_irqsave(&priv->lock, flags); | 85 | spin_lock_irqsave(&priv->rxlock, flags); |
86 | 86 | ||
87 | /* Set the new stashing value */ | 87 | /* Set the new stashing value */ |
88 | priv->bd_stash_en = new_setting; | 88 | priv->bd_stash_en = new_setting; |
@@ -96,7 +96,7 @@ static ssize_t gfar_set_bd_stash(struct class_device *cdev, | |||
96 | 96 | ||
97 | gfar_write(&priv->regs->attr, temp); | 97 | gfar_write(&priv->regs->attr, temp); |
98 | 98 | ||
99 | spin_unlock_irqrestore(&priv->lock, flags); | 99 | spin_unlock_irqrestore(&priv->rxlock, flags); |
100 | 100 | ||
101 | return count; | 101 | return count; |
102 | } | 102 | } |
@@ -118,7 +118,7 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev, | |||
118 | u32 temp; | 118 | u32 temp; |
119 | unsigned long flags; | 119 | unsigned long flags; |
120 | 120 | ||
121 | spin_lock_irqsave(&priv->lock, flags); | 121 | spin_lock_irqsave(&priv->rxlock, flags); |
122 | if (length > priv->rx_buffer_size) | 122 | if (length > priv->rx_buffer_size) |
123 | return count; | 123 | return count; |
124 | 124 | ||
@@ -142,7 +142,7 @@ static ssize_t gfar_set_rx_stash_size(struct class_device *cdev, | |||
142 | 142 | ||
143 | gfar_write(&priv->regs->attr, temp); | 143 | gfar_write(&priv->regs->attr, temp); |
144 | 144 | ||
145 | spin_unlock_irqrestore(&priv->lock, flags); | 145 | spin_unlock_irqrestore(&priv->rxlock, flags); |
146 | 146 | ||
147 | return count; | 147 | return count; |
148 | } | 148 | } |
@@ -166,7 +166,7 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev, | |||
166 | u32 temp; | 166 | u32 temp; |
167 | unsigned long flags; | 167 | unsigned long flags; |
168 | 168 | ||
169 | spin_lock_irqsave(&priv->lock, flags); | 169 | spin_lock_irqsave(&priv->rxlock, flags); |
170 | if (index > priv->rx_stash_size) | 170 | if (index > priv->rx_stash_size) |
171 | return count; | 171 | return count; |
172 | 172 | ||
@@ -180,7 +180,7 @@ static ssize_t gfar_set_rx_stash_index(struct class_device *cdev, | |||
180 | temp |= ATTRELI_EI(index); | 180 | temp |= ATTRELI_EI(index); |
181 | gfar_write(&priv->regs->attreli, flags); | 181 | gfar_write(&priv->regs->attreli, flags); |
182 | 182 | ||
183 | spin_unlock_irqrestore(&priv->lock, flags); | 183 | spin_unlock_irqrestore(&priv->rxlock, flags); |
184 | 184 | ||
185 | return count; | 185 | return count; |
186 | } | 186 | } |
@@ -205,7 +205,7 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev, | |||
205 | if (length > GFAR_MAX_FIFO_THRESHOLD) | 205 | if (length > GFAR_MAX_FIFO_THRESHOLD) |
206 | return count; | 206 | return count; |
207 | 207 | ||
208 | spin_lock_irqsave(&priv->lock, flags); | 208 | spin_lock_irqsave(&priv->txlock, flags); |
209 | 209 | ||
210 | priv->fifo_threshold = length; | 210 | priv->fifo_threshold = length; |
211 | 211 | ||
@@ -214,7 +214,7 @@ static ssize_t gfar_set_fifo_threshold(struct class_device *cdev, | |||
214 | temp |= length; | 214 | temp |= length; |
215 | gfar_write(&priv->regs->fifo_tx_thr, temp); | 215 | gfar_write(&priv->regs->fifo_tx_thr, temp); |
216 | 216 | ||
217 | spin_unlock_irqrestore(&priv->lock, flags); | 217 | spin_unlock_irqrestore(&priv->txlock, flags); |
218 | 218 | ||
219 | return count; | 219 | return count; |
220 | } | 220 | } |
@@ -240,7 +240,7 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev, | |||
240 | if (num > GFAR_MAX_FIFO_STARVE) | 240 | if (num > GFAR_MAX_FIFO_STARVE) |
241 | return count; | 241 | return count; |
242 | 242 | ||
243 | spin_lock_irqsave(&priv->lock, flags); | 243 | spin_lock_irqsave(&priv->txlock, flags); |
244 | 244 | ||
245 | priv->fifo_starve = num; | 245 | priv->fifo_starve = num; |
246 | 246 | ||
@@ -249,7 +249,7 @@ static ssize_t gfar_set_fifo_starve(struct class_device *cdev, | |||
249 | temp |= num; | 249 | temp |= num; |
250 | gfar_write(&priv->regs->fifo_tx_starve, temp); | 250 | gfar_write(&priv->regs->fifo_tx_starve, temp); |
251 | 251 | ||
252 | spin_unlock_irqrestore(&priv->lock, flags); | 252 | spin_unlock_irqrestore(&priv->txlock, flags); |
253 | 253 | ||
254 | return count; | 254 | return count; |
255 | } | 255 | } |
@@ -274,7 +274,7 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev, | |||
274 | if (num > GFAR_MAX_FIFO_STARVE_OFF) | 274 | if (num > GFAR_MAX_FIFO_STARVE_OFF) |
275 | return count; | 275 | return count; |
276 | 276 | ||
277 | spin_lock_irqsave(&priv->lock, flags); | 277 | spin_lock_irqsave(&priv->txlock, flags); |
278 | 278 | ||
279 | priv->fifo_starve_off = num; | 279 | priv->fifo_starve_off = num; |
280 | 280 | ||
@@ -283,7 +283,7 @@ static ssize_t gfar_set_fifo_starve_off(struct class_device *cdev, | |||
283 | temp |= num; | 283 | temp |= num; |
284 | gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); | 284 | gfar_write(&priv->regs->fifo_tx_starve_shutoff, temp); |
285 | 285 | ||
286 | spin_unlock_irqrestore(&priv->lock, flags); | 286 | spin_unlock_irqrestore(&priv->txlock, flags); |
287 | 287 | ||
288 | return count; | 288 | return count; |
289 | } | 289 | } |
diff --git a/drivers/net/hydra.h b/drivers/net/hydra.h deleted file mode 100644 index 37414146258d..000000000000 --- a/drivers/net/hydra.h +++ /dev/null | |||
@@ -1,177 +0,0 @@ | |||
1 | /* $Linux: hydra.h,v 1.0 1994/10/26 02:03:47 cgd Exp $ */ | ||
2 | |||
3 | /* | ||
4 | * Copyright (c) 1994 Timo Rossi | ||
5 | * All rights reserved. | ||
6 | * | ||
7 | * Redistribution and use in source and binary forms, with or without | ||
8 | * modification, are permitted provided that the following conditions | ||
9 | * are met: | ||
10 | * 1. Redistributions of source code must retain the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer. | ||
12 | * 2. Redistributions in binary form must reproduce the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer in the | ||
14 | * documentation and/or other materials provided with the distribution. | ||
15 | * 3. All advertising materials mentioning features or use of this software | ||
16 | * must display the following acknowledgement: | ||
17 | * This product includes software developed by Timo Rossi | ||
18 | * 4. The name of the author may not be used to endorse or promote products | ||
19 | * derived from this software without specific prior written permission | ||
20 | * | ||
21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
23 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
24 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
31 | */ | ||
32 | |||
33 | /* | ||
34 | * The Hydra Systems card uses the National Semiconductor | ||
35 | * 8390 NIC (Network Interface Controller) chip, located | ||
36 | * at card base address + 0xffe1. NIC registers are accessible | ||
37 | * only at odd byte addresses, so the register offsets must | ||
38 | * be multiplied by two. | ||
39 | * | ||
40 | * Card address PROM is located at card base + 0xffc0 (even byte addresses) | ||
41 | * | ||
42 | * RAM starts at the card base address, and is 16K or 64K. | ||
43 | * The current Amiga NetBSD hydra driver is hardwired for 16K. | ||
44 | * It seems that the RAM should be accessed as words or longwords only. | ||
45 | * | ||
46 | */ | ||
47 | |||
48 | /* adapted for Linux by Topi Kanerva 03/29/95 | ||
49 | with original author's permission */ | ||
50 | |||
51 | #define HYDRA_NIC_BASE 0xffe1 | ||
52 | |||
53 | /* Page0 registers */ | ||
54 | |||
55 | #define NIC_CR 0 /* Command register */ | ||
56 | #define NIC_PSTART (1*2) /* Page start (write) */ | ||
57 | #define NIC_PSTOP (2*2) /* Page stop (write) */ | ||
58 | #define NIC_BNDRY (3*2) /* Boundary pointer */ | ||
59 | #define NIC_TSR (4*2) /* Transmit status (read) */ | ||
60 | #define NIC_TPSR (4*2) /* Transmit page start (write) */ | ||
61 | #define NIC_NCR (5*2) /* Number of collisions, read */ | ||
62 | #define NIC_TBCR0 (5*2) /* Transmit byte count low (write) */ | ||
63 | #define NIC_FIFO (6*2) /* FIFO reg. (read) */ | ||
64 | #define NIC_TBCR1 (6*2) /* Transmit byte count high (write) */ | ||
65 | #define NIC_ISR (7*2) /* Interrupt status register */ | ||
66 | #define NIC_RBCR0 (0xa*2) /* Remote byte count low (write) */ | ||
67 | #define NIC_RBCR1 (0xb*2) /* Remote byte count high (write) */ | ||
68 | #define NIC_RSR (0xc*2) /* Receive status (read) */ | ||
69 | #define NIC_RCR (0xc*2) /* Receive config (write) */ | ||
70 | #define NIC_CNTR0 (0xd*2) /* Frame alignment error count (read) */ | ||
71 | #define NIC_TCR (0xd*2) /* Transmit config (write) */ | ||
72 | #define NIC_CNTR1 (0xe*2) /* CRC error counter (read) */ | ||
73 | #define NIC_DCR (0xe*2) /* Data config (write) */ | ||
74 | #define NIC_CNTR2 (0xf*2) /* missed packet counter (read) */ | ||
75 | #define NIC_IMR (0xf*2) /* Interrupt mask reg. (write) */ | ||
76 | |||
77 | /* Page1 registers */ | ||
78 | |||
79 | #define NIC_PAR0 (1*2) /* Physical address */ | ||
80 | #define NIC_PAR1 (2*2) | ||
81 | #define NIC_PAR2 (3*2) | ||
82 | #define NIC_PAR3 (4*2) | ||
83 | #define NIC_PAR4 (5*2) | ||
84 | #define NIC_PAR5 (6*2) | ||
85 | #define NIC_CURR (7*2) /* Current RX ring-buffer page */ | ||
86 | #define NIC_MAR0 (8*2) /* Multicast address */ | ||
87 | #define NIC_MAR1 (9*2) | ||
88 | #define NIC_MAR2 (0xa*2) | ||
89 | #define NIC_MAR3 (0xb*2) | ||
90 | #define NIC_MAR4 (0xc*2) | ||
91 | #define NIC_MAR5 (0xd*2) | ||
92 | #define NIC_MAR6 (0xe*2) | ||
93 | #define NIC_MAR7 (0xf*2) | ||
94 | |||
95 | /* Command register definitions */ | ||
96 | |||
97 | #define CR_STOP 0x01 /* Stop -- software reset command */ | ||
98 | #define CR_START 0x02 /* Start */ | ||
99 | #define CR_TXP 0x04 /* Transmit packet */ | ||
100 | |||
101 | #define CR_RD0 0x08 /* Remote DMA cmd */ | ||
102 | #define CR_RD1 0x10 | ||
103 | #define CR_RD2 0x20 | ||
104 | |||
105 | #define CR_NODMA CR_RD2 | ||
106 | |||
107 | #define CR_PS0 0x40 /* Page select */ | ||
108 | #define CR_PS1 0x80 | ||
109 | |||
110 | #define CR_PAGE0 0 | ||
111 | #define CR_PAGE1 CR_PS0 | ||
112 | #define CR_PAGE2 CR_PS1 | ||
113 | |||
114 | /* Interrupt status reg. definitions */ | ||
115 | |||
116 | #define ISR_PRX 0x01 /* Packet received without errors */ | ||
117 | #define ISR_PTX 0x02 /* Packet transmitted without errors */ | ||
118 | #define ISR_RXE 0x04 /* Receive error */ | ||
119 | #define ISR_TXE 0x08 /* Transmit error */ | ||
120 | #define ISR_OVW 0x10 /* Ring buffer overrun */ | ||
121 | #define ISR_CNT 0x20 /* Counter overflow */ | ||
122 | #define ISR_RDC 0x40 /* Remote DMA compile */ | ||
123 | #define ISR_RST 0x80 /* Reset status */ | ||
124 | |||
125 | /* Data config reg. definitions */ | ||
126 | |||
127 | #define DCR_WTS 0x01 /* Word transfer select */ | ||
128 | #define DCR_BOS 0x02 /* Byte order select */ | ||
129 | #define DCR_LAS 0x04 /* Long address select */ | ||
130 | #define DCR_LS 0x08 /* Loopback select */ | ||
131 | #define DCR_AR 0x10 /* Auto-init remote */ | ||
132 | #define DCR_FT0 0x20 /* FIFO threshold select */ | ||
133 | #define DCR_FT1 0x40 | ||
134 | |||
135 | /* Transmit config reg. definitions */ | ||
136 | |||
137 | #define TCR_CRC 0x01 /* Inhibit CRC */ | ||
138 | #define TCR_LB0 0x02 /* Loopback control */ | ||
139 | #define TCR_LB1 0x04 | ||
140 | #define TCR_ATD 0x08 /* Auto transmit disable */ | ||
141 | #define TCR_OFST 0x10 /* Collision offset enable */ | ||
142 | |||
143 | /* Transmit status reg. definitions */ | ||
144 | |||
145 | #define TSR_PTX 0x01 /* Packet transmitted */ | ||
146 | #define TSR_COL 0x04 /* Transmit collided */ | ||
147 | #define TSR_ABT 0x08 /* Transmit aborted */ | ||
148 | #define TSR_CRS 0x10 /* Carrier sense lost */ | ||
149 | #define TSR_FU 0x20 /* FIFO underrun */ | ||
150 | #define TSR_CDH 0x40 /* CD Heartbeat */ | ||
151 | #define TSR_OWC 0x80 /* Out of Window Collision */ | ||
152 | |||
153 | /* Receiver config register definitions */ | ||
154 | |||
155 | #define RCR_SEP 0x01 /* Save errored packets */ | ||
156 | #define RCR_AR 0x02 /* Accept runt packets */ | ||
157 | #define RCR_AB 0x04 /* Accept broadcast */ | ||
158 | #define RCR_AM 0x08 /* Accept multicast */ | ||
159 | #define RCR_PRO 0x10 /* Promiscuous mode */ | ||
160 | #define RCR_MON 0x20 /* Monitor mode */ | ||
161 | |||
162 | /* Receiver status register definitions */ | ||
163 | |||
164 | #define RSR_PRX 0x01 /* Packet received without error */ | ||
165 | #define RSR_CRC 0x02 /* CRC error */ | ||
166 | #define RSR_FAE 0x04 /* Frame alignment error */ | ||
167 | #define RSR_FO 0x08 /* FIFO overrun */ | ||
168 | #define RSR_MPA 0x10 /* Missed packet */ | ||
169 | #define RSR_PHY 0x20 /* Physical address */ | ||
170 | #define RSR_DIS 0x40 /* Received disabled */ | ||
171 | #define RSR_DFR 0x80 /* Deferring (jabber) */ | ||
172 | |||
173 | /* Hydra System card address PROM offset */ | ||
174 | |||
175 | #define HYDRA_ADDRPROM 0xffc0 | ||
176 | |||
177 | |||
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index ceb98fd398af..52d01027d9e7 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c | |||
@@ -235,7 +235,7 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc | |||
235 | 235 | ||
236 | lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); | 236 | lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); |
237 | 237 | ||
238 | if(lpar_rc != H_Success) { | 238 | if(lpar_rc != H_SUCCESS) { |
239 | pool->free_map[free_index] = index; | 239 | pool->free_map[free_index] = index; |
240 | pool->skbuff[index] = NULL; | 240 | pool->skbuff[index] = NULL; |
241 | pool->consumer_index--; | 241 | pool->consumer_index--; |
@@ -373,7 +373,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) | |||
373 | 373 | ||
374 | lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); | 374 | lpar_rc = h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.desc); |
375 | 375 | ||
376 | if(lpar_rc != H_Success) { | 376 | if(lpar_rc != H_SUCCESS) { |
377 | ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc); | 377 | ibmveth_debug_printk("h_add_logical_lan_buffer failed during recycle rc=%ld", lpar_rc); |
378 | ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); | 378 | ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); |
379 | } | 379 | } |
@@ -511,7 +511,7 @@ static int ibmveth_open(struct net_device *netdev) | |||
511 | adapter->filter_list_dma, | 511 | adapter->filter_list_dma, |
512 | mac_address); | 512 | mac_address); |
513 | 513 | ||
514 | if(lpar_rc != H_Success) { | 514 | if(lpar_rc != H_SUCCESS) { |
515 | ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc); | 515 | ibmveth_error_printk("h_register_logical_lan failed with %ld\n", lpar_rc); |
516 | ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n", | 516 | ibmveth_error_printk("buffer TCE:0x%lx filter TCE:0x%lx rxq desc:0x%lx MAC:0x%lx\n", |
517 | adapter->buffer_list_dma, | 517 | adapter->buffer_list_dma, |
@@ -527,7 +527,7 @@ static int ibmveth_open(struct net_device *netdev) | |||
527 | ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc); | 527 | ibmveth_error_printk("unable to request irq 0x%x, rc %d\n", netdev->irq, rc); |
528 | do { | 528 | do { |
529 | rc = h_free_logical_lan(adapter->vdev->unit_address); | 529 | rc = h_free_logical_lan(adapter->vdev->unit_address); |
530 | } while (H_isLongBusy(rc) || (rc == H_Busy)); | 530 | } while (H_IS_LONG_BUSY(rc) || (rc == H_BUSY)); |
531 | 531 | ||
532 | ibmveth_cleanup(adapter); | 532 | ibmveth_cleanup(adapter); |
533 | return rc; | 533 | return rc; |
@@ -556,9 +556,9 @@ static int ibmveth_close(struct net_device *netdev) | |||
556 | 556 | ||
557 | do { | 557 | do { |
558 | lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); | 558 | lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); |
559 | } while (H_isLongBusy(lpar_rc) || (lpar_rc == H_Busy)); | 559 | } while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY)); |
560 | 560 | ||
561 | if(lpar_rc != H_Success) | 561 | if(lpar_rc != H_SUCCESS) |
562 | { | 562 | { |
563 | ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n", | 563 | ibmveth_error_printk("h_free_logical_lan failed with %lx, continuing with close\n", |
564 | lpar_rc); | 564 | lpar_rc); |
@@ -693,9 +693,9 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
693 | desc[4].desc, | 693 | desc[4].desc, |
694 | desc[5].desc, | 694 | desc[5].desc, |
695 | correlator); | 695 | correlator); |
696 | } while ((lpar_rc == H_Busy) && (retry_count--)); | 696 | } while ((lpar_rc == H_BUSY) && (retry_count--)); |
697 | 697 | ||
698 | if(lpar_rc != H_Success && lpar_rc != H_Dropped) { | 698 | if(lpar_rc != H_SUCCESS && lpar_rc != H_DROPPED) { |
699 | int i; | 699 | int i; |
700 | ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc); | 700 | ibmveth_error_printk("tx: h_send_logical_lan failed with rc=%ld\n", lpar_rc); |
701 | for(i = 0; i < 6; i++) { | 701 | for(i = 0; i < 6; i++) { |
@@ -786,14 +786,14 @@ static int ibmveth_poll(struct net_device *netdev, int *budget) | |||
786 | /* we think we are done - reenable interrupts, then check once more to make sure we are done */ | 786 | /* we think we are done - reenable interrupts, then check once more to make sure we are done */ |
787 | lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE); | 787 | lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_ENABLE); |
788 | 788 | ||
789 | ibmveth_assert(lpar_rc == H_Success); | 789 | ibmveth_assert(lpar_rc == H_SUCCESS); |
790 | 790 | ||
791 | netif_rx_complete(netdev); | 791 | netif_rx_complete(netdev); |
792 | 792 | ||
793 | if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed)) | 793 | if(ibmveth_rxq_pending_buffer(adapter) && netif_rx_reschedule(netdev, frames_processed)) |
794 | { | 794 | { |
795 | lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); | 795 | lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); |
796 | ibmveth_assert(lpar_rc == H_Success); | 796 | ibmveth_assert(lpar_rc == H_SUCCESS); |
797 | more_work = 1; | 797 | more_work = 1; |
798 | goto restart_poll; | 798 | goto restart_poll; |
799 | } | 799 | } |
@@ -813,7 +813,7 @@ static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance, struct pt_regs | |||
813 | 813 | ||
814 | if(netif_rx_schedule_prep(netdev)) { | 814 | if(netif_rx_schedule_prep(netdev)) { |
815 | lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); | 815 | lpar_rc = h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); |
816 | ibmveth_assert(lpar_rc == H_Success); | 816 | ibmveth_assert(lpar_rc == H_SUCCESS); |
817 | __netif_rx_schedule(netdev); | 817 | __netif_rx_schedule(netdev); |
818 | } | 818 | } |
819 | return IRQ_HANDLED; | 819 | return IRQ_HANDLED; |
@@ -835,7 +835,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) | |||
835 | IbmVethMcastEnableRecv | | 835 | IbmVethMcastEnableRecv | |
836 | IbmVethMcastDisableFiltering, | 836 | IbmVethMcastDisableFiltering, |
837 | 0); | 837 | 0); |
838 | if(lpar_rc != H_Success) { | 838 | if(lpar_rc != H_SUCCESS) { |
839 | ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc); | 839 | ibmveth_error_printk("h_multicast_ctrl rc=%ld when entering promisc mode\n", lpar_rc); |
840 | } | 840 | } |
841 | } else { | 841 | } else { |
@@ -847,7 +847,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) | |||
847 | IbmVethMcastDisableFiltering | | 847 | IbmVethMcastDisableFiltering | |
848 | IbmVethMcastClearFilterTable, | 848 | IbmVethMcastClearFilterTable, |
849 | 0); | 849 | 0); |
850 | if(lpar_rc != H_Success) { | 850 | if(lpar_rc != H_SUCCESS) { |
851 | ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc); | 851 | ibmveth_error_printk("h_multicast_ctrl rc=%ld when attempting to clear filter table\n", lpar_rc); |
852 | } | 852 | } |
853 | /* add the addresses to the filter table */ | 853 | /* add the addresses to the filter table */ |
@@ -858,7 +858,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) | |||
858 | lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, | 858 | lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, |
859 | IbmVethMcastAddFilter, | 859 | IbmVethMcastAddFilter, |
860 | mcast_addr); | 860 | mcast_addr); |
861 | if(lpar_rc != H_Success) { | 861 | if(lpar_rc != H_SUCCESS) { |
862 | ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc); | 862 | ibmveth_error_printk("h_multicast_ctrl rc=%ld when adding an entry to the filter table\n", lpar_rc); |
863 | } | 863 | } |
864 | } | 864 | } |
@@ -867,7 +867,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev) | |||
867 | lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, | 867 | lpar_rc = h_multicast_ctrl(adapter->vdev->unit_address, |
868 | IbmVethMcastEnableFiltering, | 868 | IbmVethMcastEnableFiltering, |
869 | 0); | 869 | 0); |
870 | if(lpar_rc != H_Success) { | 870 | if(lpar_rc != H_SUCCESS) { |
871 | ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc); | 871 | ibmveth_error_printk("h_multicast_ctrl rc=%ld when enabling filtering\n", lpar_rc); |
872 | } | 872 | } |
873 | } | 873 | } |
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 6e2ec56cde0b..96bdb73c2283 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /***************************************************************************** | 1 | /***************************************************************************** |
2 | * | 2 | * |
3 | * Filename: irda-usb.c | 3 | * Filename: irda-usb.c |
4 | * Version: 0.9b | 4 | * Version: 0.10 |
5 | * Description: IrDA-USB Driver | 5 | * Description: IrDA-USB Driver |
6 | * Status: Experimental | 6 | * Status: Experimental |
7 | * Author: Dag Brattli <dag@brattli.net> | 7 | * Author: Dag Brattli <dag@brattli.net> |
@@ -9,6 +9,9 @@ | |||
9 | * Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at> | 9 | * Copyright (C) 2000, Roman Weissgaerber <weissg@vienna.at> |
10 | * Copyright (C) 2001, Dag Brattli <dag@brattli.net> | 10 | * Copyright (C) 2001, Dag Brattli <dag@brattli.net> |
11 | * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> | 11 | * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> |
12 | * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com> | ||
13 | * Copyright (C) 2005, Milan Beno <beno@pobox.sk> | ||
14 | * Copyright (C) 2006, Nick Fedchik <nick@fedchik.org.ua> | ||
12 | * | 15 | * |
13 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
@@ -61,6 +64,7 @@ | |||
61 | #include <linux/slab.h> | 64 | #include <linux/slab.h> |
62 | #include <linux/rtnetlink.h> | 65 | #include <linux/rtnetlink.h> |
63 | #include <linux/usb.h> | 66 | #include <linux/usb.h> |
67 | #include <linux/firmware.h> | ||
64 | 68 | ||
65 | #include "irda-usb.h" | 69 | #include "irda-usb.h" |
66 | 70 | ||
@@ -78,8 +82,12 @@ static struct usb_device_id dongles[] = { | |||
78 | { USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, | 82 | { USB_DEVICE(0x50f, 0x180), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, |
79 | /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */ | 83 | /* Extended Systems, Inc., XTNDAccess IrDA USB (ESI-9685) */ |
80 | { USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, | 84 | { USB_DEVICE(0x8e9, 0x100), .driver_info = IUC_SPEED_BUG | IUC_NO_WINDOW }, |
85 | /* SigmaTel STIR4210/4220/4116 USB IrDA (VFIR) Bridge */ | ||
86 | { USB_DEVICE(0x66f, 0x4210), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, | ||
87 | { USB_DEVICE(0x66f, 0x4220), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, | ||
88 | { USB_DEVICE(0x66f, 0x4116), .driver_info = IUC_STIR_4210 | IUC_SPEED_BUG }, | ||
81 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | | 89 | { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS | |
82 | USB_DEVICE_ID_MATCH_INT_SUBCLASS, | 90 | USB_DEVICE_ID_MATCH_INT_SUBCLASS, |
83 | .bInterfaceClass = USB_CLASS_APP_SPEC, | 91 | .bInterfaceClass = USB_CLASS_APP_SPEC, |
84 | .bInterfaceSubClass = USB_CLASS_IRDA, | 92 | .bInterfaceSubClass = USB_CLASS_IRDA, |
85 | .driver_info = IUC_DEFAULT, }, | 93 | .driver_info = IUC_DEFAULT, }, |
@@ -99,6 +107,7 @@ MODULE_DEVICE_TABLE(usb, dongles); | |||
99 | 107 | ||
100 | /*------------------------------------------------------------------*/ | 108 | /*------------------------------------------------------------------*/ |
101 | 109 | ||
110 | static void irda_usb_init_qos(struct irda_usb_cb *self) ; | ||
102 | static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf); | 111 | static struct irda_class_desc *irda_usb_find_class_desc(struct usb_interface *intf); |
103 | static void irda_usb_disconnect(struct usb_interface *intf); | 112 | static void irda_usb_disconnect(struct usb_interface *intf); |
104 | static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); | 113 | static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self); |
@@ -141,7 +150,24 @@ static void irda_usb_build_header(struct irda_usb_cb *self, | |||
141 | __u8 *header, | 150 | __u8 *header, |
142 | int force) | 151 | int force) |
143 | { | 152 | { |
144 | /* Set the negotiated link speed */ | 153 | /* Here we check if we have an STIR421x chip, |
154 | * and if either speed or xbofs (or both) needs | ||
155 | * to be changed. | ||
156 | */ | ||
157 | if (self->capability & IUC_STIR_4210 && | ||
158 | ((self->new_speed != -1) || (self->new_xbofs != -1))) { | ||
159 | |||
160 | /* With STIR421x, speed and xBOFs must be set at the same | ||
161 | * time, even if only one of them changes. | ||
162 | */ | ||
163 | if (self->new_speed == -1) | ||
164 | self->new_speed = self->speed ; | ||
165 | |||
166 | if (self->new_xbofs == -1) | ||
167 | self->new_xbofs = self->xbofs ; | ||
168 | } | ||
169 | |||
170 | /* Set the link speed */ | ||
145 | if (self->new_speed != -1) { | 171 | if (self->new_speed != -1) { |
146 | /* Hum... Ugly hack :-( | 172 | /* Hum... Ugly hack :-( |
147 | * Some device are not compliant with the spec and change | 173 | * Some device are not compliant with the spec and change |
@@ -191,7 +217,11 @@ static void irda_usb_build_header(struct irda_usb_cb *self, | |||
191 | *header = SPEED_4000000; | 217 | *header = SPEED_4000000; |
192 | self->new_xbofs = 0; | 218 | self->new_xbofs = 0; |
193 | break; | 219 | break; |
194 | } | 220 | case 16000000: |
221 | *header = SPEED_16000000; | ||
222 | self->new_xbofs = 0; | ||
223 | break; | ||
224 | } | ||
195 | } else | 225 | } else |
196 | /* No change */ | 226 | /* No change */ |
197 | *header = 0; | 227 | *header = 0; |
@@ -235,6 +265,32 @@ static void irda_usb_build_header(struct irda_usb_cb *self, | |||
235 | } | 265 | } |
236 | } | 266 | } |
237 | 267 | ||
268 | /* | ||
269 | * calculate turnaround time for SigmaTel header | ||
270 | */ | ||
271 | static __u8 get_turnaround_time(struct sk_buff *skb) | ||
272 | { | ||
273 | int turnaround_time = irda_get_mtt(skb); | ||
274 | |||
275 | if ( turnaround_time == 0 ) | ||
276 | return 0; | ||
277 | else if ( turnaround_time <= 10 ) | ||
278 | return 1; | ||
279 | else if ( turnaround_time <= 50 ) | ||
280 | return 2; | ||
281 | else if ( turnaround_time <= 100 ) | ||
282 | return 3; | ||
283 | else if ( turnaround_time <= 500 ) | ||
284 | return 4; | ||
285 | else if ( turnaround_time <= 1000 ) | ||
286 | return 5; | ||
287 | else if ( turnaround_time <= 5000 ) | ||
288 | return 6; | ||
289 | else | ||
290 | return 7; | ||
291 | } | ||
292 | |||
293 | |||
238 | /*------------------------------------------------------------------*/ | 294 | /*------------------------------------------------------------------*/ |
239 | /* | 295 | /* |
240 | * Send a command to change the speed of the dongle | 296 | * Send a command to change the speed of the dongle |
@@ -262,12 +318,18 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self) | |||
262 | /* Set the new speed and xbofs in this fake frame */ | 318 | /* Set the new speed and xbofs in this fake frame */ |
263 | irda_usb_build_header(self, frame, 1); | 319 | irda_usb_build_header(self, frame, 1); |
264 | 320 | ||
321 | if ( self->capability & IUC_STIR_4210 ) { | ||
322 | if (frame[0] == 0) return ; // do nothing if no change | ||
323 | frame[1] = 0; // other parameters don't change here | ||
324 | frame[2] = 0; | ||
325 | } | ||
326 | |||
265 | /* Submit the 0 length IrDA frame to trigger new speed settings */ | 327 | /* Submit the 0 length IrDA frame to trigger new speed settings */ |
266 | usb_fill_bulk_urb(urb, self->usbdev, | 328 | usb_fill_bulk_urb(urb, self->usbdev, |
267 | usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), | 329 | usb_sndbulkpipe(self->usbdev, self->bulk_out_ep), |
268 | frame, IRDA_USB_SPEED_MTU, | 330 | frame, IRDA_USB_SPEED_MTU, |
269 | speed_bulk_callback, self); | 331 | speed_bulk_callback, self); |
270 | urb->transfer_buffer_length = USB_IRDA_HEADER; | 332 | urb->transfer_buffer_length = self->header_length; |
271 | urb->transfer_flags = 0; | 333 | urb->transfer_flags = 0; |
272 | 334 | ||
273 | /* Irq disabled -> GFP_ATOMIC */ | 335 | /* Irq disabled -> GFP_ATOMIC */ |
@@ -383,16 +445,35 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
383 | * allocation will be done lower in skb_push(). | 445 | * allocation will be done lower in skb_push(). |
384 | * Also, we don't use directly skb_cow(), because it require | 446 | * Also, we don't use directly skb_cow(), because it require |
385 | * headroom >= 16, which force unnecessary copies - Jean II */ | 447 | * headroom >= 16, which force unnecessary copies - Jean II */ |
386 | if (skb_headroom(skb) < USB_IRDA_HEADER) { | 448 | if (skb_headroom(skb) < self->header_length) { |
387 | IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__); | 449 | IRDA_DEBUG(0, "%s(), Insuficient skb headroom.\n", __FUNCTION__); |
388 | if (skb_cow(skb, USB_IRDA_HEADER)) { | 450 | if (skb_cow(skb, self->header_length)) { |
389 | IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__); | 451 | IRDA_WARNING("%s(), failed skb_cow() !!!\n", __FUNCTION__); |
390 | goto drop; | 452 | goto drop; |
391 | } | 453 | } |
392 | } | 454 | } |
393 | 455 | ||
394 | /* Change setting for next frame */ | 456 | /* Change setting for next frame */ |
395 | irda_usb_build_header(self, skb_push(skb, USB_IRDA_HEADER), 0); | 457 | |
458 | if ( self->capability & IUC_STIR_4210 ) { | ||
459 | __u8 turnaround_time; | ||
460 | __u8* frame; | ||
461 | turnaround_time = get_turnaround_time( skb ); | ||
462 | frame= skb_push(skb, self->header_length); | ||
463 | irda_usb_build_header(self, frame, 0); | ||
464 | frame[2] = turnaround_time; | ||
465 | if ((skb->len != 0) && | ||
466 | ((skb->len % 128) == 0) && | ||
467 | ((skb->len % 512) != 0)) { | ||
468 | /* add extra byte for special SigmaTel feature */ | ||
469 | frame[1] = 1; | ||
470 | skb_put(skb, 1); | ||
471 | } else { | ||
472 | frame[1] = 0; | ||
473 | } | ||
474 | } else { | ||
475 | irda_usb_build_header(self, skb_push(skb, self->header_length), 0); | ||
476 | } | ||
396 | 477 | ||
397 | /* FIXME: Make macro out of this one */ | 478 | /* FIXME: Make macro out of this one */ |
398 | ((struct irda_skb_cb *)skb->cb)->context = self; | 479 | ((struct irda_skb_cb *)skb->cb)->context = self; |
@@ -795,7 +876,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) | |||
795 | } | 876 | } |
796 | 877 | ||
797 | /* Check for empty frames */ | 878 | /* Check for empty frames */ |
798 | if (urb->actual_length <= USB_IRDA_HEADER) { | 879 | if (urb->actual_length <= self->header_length) { |
799 | IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__); | 880 | IRDA_WARNING("%s(), empty frame!\n", __FUNCTION__); |
800 | goto done; | 881 | goto done; |
801 | } | 882 | } |
@@ -816,7 +897,11 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) | |||
816 | docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD); | 897 | docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD); |
817 | 898 | ||
818 | /* Allocate a new skb */ | 899 | /* Allocate a new skb */ |
819 | newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU); | 900 | if ( self->capability & IUC_STIR_4210 ) |
901 | newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU + USB_IRDA_SIGMATEL_HEADER); | ||
902 | else | ||
903 | newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU); | ||
904 | |||
820 | if (!newskb) { | 905 | if (!newskb) { |
821 | self->stats.rx_dropped++; | 906 | self->stats.rx_dropped++; |
822 | /* We could deliver the current skb, but this would stall | 907 | /* We could deliver the current skb, but this would stall |
@@ -845,7 +930,7 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs) | |||
845 | 930 | ||
846 | /* Set proper length on skb & remove USB-IrDA header */ | 931 | /* Set proper length on skb & remove USB-IrDA header */ |
847 | skb_put(dataskb, urb->actual_length); | 932 | skb_put(dataskb, urb->actual_length); |
848 | skb_pull(dataskb, USB_IRDA_HEADER); | 933 | skb_pull(dataskb, self->header_length); |
849 | 934 | ||
850 | /* Ask the networking layer to queue the packet for the IrDA stack */ | 935 | /* Ask the networking layer to queue the packet for the IrDA stack */ |
851 | dataskb->dev = self->netdev; | 936 | dataskb->dev = self->netdev; |
@@ -937,6 +1022,191 @@ static int irda_usb_is_receiving(struct irda_usb_cb *self) | |||
937 | return 0; /* For now */ | 1022 | return 0; /* For now */ |
938 | } | 1023 | } |
939 | 1024 | ||
1025 | |||
1026 | #define STIR421X_PATCH_PRODUCT_VERSION_STR "Product Version: " | ||
1027 | #define STIR421X_PATCH_COMPONENT_VERSION_STR "Component Version: " | ||
1028 | #define STIR421X_PATCH_DATA_TAG_STR "STMP" | ||
1029 | #define STIR421X_PATCH_FILE_VERSION_MAX_OFFSET 512 /* version info is before here */ | ||
1030 | #define STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET 512 /* patch image starts before here */ | ||
1031 | #define STIR421X_PATCH_FILE_END_OF_HEADER_TAG 0x1A /* marks end of patch file header (PC DOS text file EOF character) */ | ||
1032 | |||
1033 | /* | ||
1034 | * Known firmware patches for STIR421x dongles | ||
1035 | */ | ||
1036 | static char * stir421x_patches[] = { | ||
1037 | "42101001.sb", | ||
1038 | "42101002.sb", | ||
1039 | }; | ||
1040 | |||
1041 | static int stir421x_get_patch_version(unsigned char * patch, const unsigned long patch_len) | ||
1042 | { | ||
1043 | unsigned int version_offset; | ||
1044 | unsigned long version_major, version_minor, version_build; | ||
1045 | unsigned char * version_start; | ||
1046 | int version_found = 0; | ||
1047 | |||
1048 | for (version_offset = 0; | ||
1049 | version_offset < STIR421X_PATCH_FILE_END_OF_HEADER_TAG; | ||
1050 | version_offset++) { | ||
1051 | if (!memcmp(patch + version_offset, | ||
1052 | STIR421X_PATCH_PRODUCT_VERSION_STR, | ||
1053 | sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1)) { | ||
1054 | version_found = 1; | ||
1055 | version_start = patch + | ||
1056 | version_offset + | ||
1057 | sizeof(STIR421X_PATCH_PRODUCT_VERSION_STR) - 1; | ||
1058 | break; | ||
1059 | } | ||
1060 | } | ||
1061 | |||
1062 | /* We couldn't find a product version on this patch */ | ||
1063 | if (!version_found) | ||
1064 | return -EINVAL; | ||
1065 | |||
1066 | /* Let's check if the product version is dotted */ | ||
1067 | if (version_start[3] != '.' || | ||
1068 | version_start[7] != '.') | ||
1069 | return -EINVAL; | ||
1070 | |||
1071 | version_major = simple_strtoul(version_start, NULL, 10); | ||
1072 | version_minor = simple_strtoul(version_start + 4, NULL, 10); | ||
1073 | version_build = simple_strtoul(version_start + 8, NULL, 10); | ||
1074 | |||
1075 | IRDA_DEBUG(2, "%s(), Major: %ld Minor: %ld Build: %ld\n", | ||
1076 | __FUNCTION__, | ||
1077 | version_major, version_minor, version_build); | ||
1078 | |||
1079 | return (((version_major) << 12) + | ||
1080 | ((version_minor) << 8) + | ||
1081 | ((version_build / 10) << 4) + | ||
1082 | (version_build % 10)); | ||
1083 | |||
1084 | } | ||
1085 | |||
1086 | |||
1087 | static int stir421x_upload_patch (struct irda_usb_cb *self, | ||
1088 | unsigned char * patch, | ||
1089 | const unsigned int patch_len) | ||
1090 | { | ||
1091 | int retval = 0; | ||
1092 | int actual_len; | ||
1093 | unsigned int i = 0, download_amount = 0; | ||
1094 | unsigned char * patch_chunk; | ||
1095 | |||
1096 | IRDA_DEBUG (2, "%s(), Uploading STIR421x Patch\n", __FUNCTION__); | ||
1097 | |||
1098 | patch_chunk = kzalloc(STIR421X_MAX_PATCH_DOWNLOAD_SIZE, GFP_KERNEL); | ||
1099 | if (patch_chunk == NULL) | ||
1100 | return -ENOMEM; | ||
1101 | |||
1102 | /* break up patch into 1023-byte sections */ | ||
1103 | for (i = 0; retval >= 0 && i < patch_len; i += download_amount) { | ||
1104 | download_amount = patch_len - i; | ||
1105 | if (download_amount > STIR421X_MAX_PATCH_DOWNLOAD_SIZE) | ||
1106 | download_amount = STIR421X_MAX_PATCH_DOWNLOAD_SIZE; | ||
1107 | |||
1108 | /* download the patch section */ | ||
1109 | memcpy(patch_chunk, patch + i, download_amount); | ||
1110 | |||
1111 | retval = usb_bulk_msg (self->usbdev, | ||
1112 | usb_sndbulkpipe (self->usbdev, | ||
1113 | self->bulk_out_ep), | ||
1114 | patch_chunk, download_amount, | ||
1115 | &actual_len, msecs_to_jiffies (500)); | ||
1116 | IRDA_DEBUG (2, "%s(), Sent %u bytes\n", __FUNCTION__, | ||
1117 | actual_len); | ||
1118 | if (retval == 0) | ||
1119 | mdelay(10); | ||
1120 | } | ||
1121 | |||
1122 | kfree(patch_chunk); | ||
1123 | |||
1124 | if (i != patch_len) { | ||
1125 | IRDA_ERROR ("%s(), Pushed %d bytes (!= patch_len (%d))\n", | ||
1126 | __FUNCTION__, i, patch_len); | ||
1127 | retval = -EIO; | ||
1128 | } | ||
1129 | |||
1130 | if (retval < 0) | ||
1131 | /* todo - mark device as not ready */ | ||
1132 | IRDA_ERROR ("%s(), STIR421x patch upload failed (%d)\n", | ||
1133 | __FUNCTION__, retval); | ||
1134 | |||
1135 | return retval; | ||
1136 | } | ||
1137 | |||
1138 | |||
1139 | static int stir421x_patch_device(struct irda_usb_cb *self) | ||
1140 | { | ||
1141 | unsigned int i, patch_found = 0, data_found = 0, data_offset; | ||
1142 | int patch_version, ret = 0; | ||
1143 | const struct firmware *fw_entry; | ||
1144 | |||
1145 | for (i = 0; i < ARRAY_SIZE(stir421x_patches); i++) { | ||
1146 | if(request_firmware(&fw_entry, stir421x_patches[i], &self->usbdev->dev) != 0) { | ||
1147 | IRDA_ERROR( "%s(), Patch %s is not available\n", __FUNCTION__, stir421x_patches[i]); | ||
1148 | continue; | ||
1149 | } | ||
1150 | |||
1151 | /* We found a patch from userspace */ | ||
1152 | patch_version = stir421x_get_patch_version (fw_entry->data, fw_entry->size); | ||
1153 | |||
1154 | if (patch_version < 0) { | ||
1155 | /* Couldn't fetch a version, let's move on to the next file */ | ||
1156 | IRDA_ERROR("%s(), version parsing failed\n", __FUNCTION__); | ||
1157 | ret = patch_version; | ||
1158 | release_firmware(fw_entry); | ||
1159 | continue; | ||
1160 | } | ||
1161 | |||
1162 | if (patch_version != self->usbdev->descriptor.bcdDevice) { | ||
1163 | /* Patch version and device don't match */ | ||
1164 | IRDA_ERROR ("%s(), wrong patch version (%d <-> %d)\n", | ||
1165 | __FUNCTION__, | ||
1166 | patch_version, self->usbdev->descriptor.bcdDevice); | ||
1167 | ret = -EINVAL; | ||
1168 | release_firmware(fw_entry); | ||
1169 | continue; | ||
1170 | } | ||
1171 | |||
1172 | /* If we're here, we've found a correct patch */ | ||
1173 | patch_found = 1; | ||
1174 | break; | ||
1175 | |||
1176 | } | ||
1177 | |||
1178 | /* We couldn't find a valid firmware, let's leave */ | ||
1179 | if (!patch_found) | ||
1180 | return ret; | ||
1181 | |||
1182 | /* The actual image starts after the "STMP" keyword */ | ||
1183 | for (data_offset = 0; data_offset < STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET; data_offset++) { | ||
1184 | if (!memcmp(fw_entry->data + data_offset, | ||
1185 | STIR421X_PATCH_DATA_TAG_STR, | ||
1186 | sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))) { | ||
1187 | IRDA_DEBUG(2, "%s(), found patch data for STIR421x at offset %d\n", | ||
1188 | __FUNCTION__, data_offset); | ||
1189 | data_found = 1; | ||
1190 | break; | ||
1191 | } | ||
1192 | } | ||
1193 | |||
1194 | /* We couldn't find "STMP" from the header */ | ||
1195 | if (!data_found) | ||
1196 | return -EINVAL; | ||
1197 | |||
1198 | /* Let's upload the patch to the target */ | ||
1199 | ret = stir421x_upload_patch(self, | ||
1200 | &fw_entry->data[data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET)], | ||
1201 | fw_entry->size - (data_offset + sizeof(STIR421X_PATCH_FILE_IMAGE_MAX_OFFSET))); | ||
1202 | |||
1203 | release_firmware(fw_entry); | ||
1204 | |||
1205 | return ret; | ||
1206 | |||
1207 | } | ||
1208 | |||
1209 | |||
940 | /********************** IRDA DEVICE CALLBACKS **********************/ | 1210 | /********************** IRDA DEVICE CALLBACKS **********************/ |
941 | /* | 1211 | /* |
942 | * Main calls from the IrDA/Network subsystem. | 1212 | * Main calls from the IrDA/Network subsystem. |
@@ -972,6 +1242,11 @@ static int irda_usb_net_open(struct net_device *netdev) | |||
972 | return -1; | 1242 | return -1; |
973 | } | 1243 | } |
974 | 1244 | ||
1245 | if(self->needspatch) { | ||
1246 | IRDA_WARNING("%s(), device needs patch\n", __FUNCTION__) ; | ||
1247 | return -EIO ; | ||
1248 | } | ||
1249 | |||
975 | /* Initialise default speed and xbofs value | 1250 | /* Initialise default speed and xbofs value |
976 | * (IrLAP will change that soon) */ | 1251 | * (IrLAP will change that soon) */ |
977 | self->speed = -1; | 1252 | self->speed = -1; |
@@ -1050,7 +1325,7 @@ static int irda_usb_net_close(struct net_device *netdev) | |||
1050 | del_timer(&self->rx_defer_timer); | 1325 | del_timer(&self->rx_defer_timer); |
1051 | 1326 | ||
1052 | /* Deallocate all the Rx path buffers (URBs and skb) */ | 1327 | /* Deallocate all the Rx path buffers (URBs and skb) */ |
1053 | for (i = 0; i < IU_MAX_RX_URBS; i++) { | 1328 | for (i = 0; i < self->max_rx_urb; i++) { |
1054 | struct urb *urb = self->rx_urb[i]; | 1329 | struct urb *urb = self->rx_urb[i]; |
1055 | struct sk_buff *skb = (struct sk_buff *) urb->context; | 1330 | struct sk_buff *skb = (struct sk_buff *) urb->context; |
1056 | /* Cancel the receive command */ | 1331 | /* Cancel the receive command */ |
@@ -1426,8 +1701,22 @@ static int irda_usb_probe(struct usb_interface *intf, | |||
1426 | spin_lock_init(&self->lock); | 1701 | spin_lock_init(&self->lock); |
1427 | init_timer(&self->rx_defer_timer); | 1702 | init_timer(&self->rx_defer_timer); |
1428 | 1703 | ||
1704 | self->capability = id->driver_info; | ||
1705 | self->needspatch = ((self->capability & IUC_STIR_4210) != 0) ; | ||
1706 | |||
1429 | /* Create all of the needed urbs */ | 1707 | /* Create all of the needed urbs */ |
1430 | for (i = 0; i < IU_MAX_RX_URBS; i++) { | 1708 | if (self->capability & IUC_STIR_4210) { |
1709 | self->max_rx_urb = IU_SIGMATEL_MAX_RX_URBS; | ||
1710 | self->header_length = USB_IRDA_SIGMATEL_HEADER; | ||
1711 | } else { | ||
1712 | self->max_rx_urb = IU_MAX_RX_URBS; | ||
1713 | self->header_length = USB_IRDA_HEADER; | ||
1714 | } | ||
1715 | |||
1716 | self->rx_urb = kzalloc(self->max_rx_urb * sizeof(struct urb *), | ||
1717 | GFP_KERNEL); | ||
1718 | |||
1719 | for (i = 0; i < self->max_rx_urb; i++) { | ||
1431 | self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); | 1720 | self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); |
1432 | if (!self->rx_urb[i]) { | 1721 | if (!self->rx_urb[i]) { |
1433 | goto err_out_1; | 1722 | goto err_out_1; |
@@ -1479,17 +1768,28 @@ static int irda_usb_probe(struct usb_interface *intf, | |||
1479 | goto err_out_3; | 1768 | goto err_out_3; |
1480 | } | 1769 | } |
1481 | 1770 | ||
1771 | self->usbdev = dev; | ||
1772 | |||
1482 | /* Find IrDA class descriptor */ | 1773 | /* Find IrDA class descriptor */ |
1483 | irda_desc = irda_usb_find_class_desc(intf); | 1774 | irda_desc = irda_usb_find_class_desc(intf); |
1484 | ret = -ENODEV; | 1775 | ret = -ENODEV; |
1485 | if (irda_desc == NULL) | 1776 | if (irda_desc == NULL) |
1486 | goto err_out_3; | 1777 | goto err_out_3; |
1487 | 1778 | ||
1779 | if (self->needspatch) { | ||
1780 | ret = usb_control_msg (self->usbdev, usb_sndctrlpipe (self->usbdev, 0), | ||
1781 | 0x02, 0x40, 0, 0, 0, 0, msecs_to_jiffies(500)); | ||
1782 | if (ret < 0) { | ||
1783 | IRDA_DEBUG (0, "usb_control_msg failed %d\n", ret); | ||
1784 | goto err_out_3; | ||
1785 | } else { | ||
1786 | mdelay(10); | ||
1787 | } | ||
1788 | } | ||
1789 | |||
1488 | self->irda_desc = irda_desc; | 1790 | self->irda_desc = irda_desc; |
1489 | self->present = 1; | 1791 | self->present = 1; |
1490 | self->netopen = 0; | 1792 | self->netopen = 0; |
1491 | self->capability = id->driver_info; | ||
1492 | self->usbdev = dev; | ||
1493 | self->usbintf = intf; | 1793 | self->usbintf = intf; |
1494 | 1794 | ||
1495 | /* Allocate the buffer for speed changes */ | 1795 | /* Allocate the buffer for speed changes */ |
@@ -1508,8 +1808,32 @@ static int irda_usb_probe(struct usb_interface *intf, | |||
1508 | 1808 | ||
1509 | IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); | 1809 | IRDA_MESSAGE("IrDA: Registered device %s\n", net->name); |
1510 | usb_set_intfdata(intf, self); | 1810 | usb_set_intfdata(intf, self); |
1811 | |||
1812 | if (self->needspatch) { | ||
1813 | /* Now we fetch and upload the firmware patch */ | ||
1814 | ret = stir421x_patch_device(self); | ||
1815 | self->needspatch = (ret < 0); | ||
1816 | if (ret < 0) { | ||
1817 | printk("patch_device failed\n"); | ||
1818 | goto err_out_5; | ||
1819 | } | ||
1820 | |||
1821 | /* replace IrDA class descriptor with what patched device is now reporting */ | ||
1822 | irda_desc = irda_usb_find_class_desc (self->usbintf); | ||
1823 | if (irda_desc == NULL) { | ||
1824 | ret = -ENODEV; | ||
1825 | goto err_out_5; | ||
1826 | } | ||
1827 | if (self->irda_desc) | ||
1828 | kfree (self->irda_desc); | ||
1829 | self->irda_desc = irda_desc; | ||
1830 | irda_usb_init_qos(self); | ||
1831 | } | ||
1832 | |||
1511 | return 0; | 1833 | return 0; |
1512 | 1834 | ||
1835 | err_out_5: | ||
1836 | unregister_netdev(self->netdev); | ||
1513 | err_out_4: | 1837 | err_out_4: |
1514 | kfree(self->speed_buff); | 1838 | kfree(self->speed_buff); |
1515 | err_out_3: | 1839 | err_out_3: |
@@ -1518,7 +1842,7 @@ err_out_3: | |||
1518 | err_out_2: | 1842 | err_out_2: |
1519 | usb_free_urb(self->tx_urb); | 1843 | usb_free_urb(self->tx_urb); |
1520 | err_out_1: | 1844 | err_out_1: |
1521 | for (i = 0; i < IU_MAX_RX_URBS; i++) { | 1845 | for (i = 0; i < self->max_rx_urb; i++) { |
1522 | if (self->rx_urb[i]) | 1846 | if (self->rx_urb[i]) |
1523 | usb_free_urb(self->rx_urb[i]); | 1847 | usb_free_urb(self->rx_urb[i]); |
1524 | } | 1848 | } |
@@ -1571,7 +1895,7 @@ static void irda_usb_disconnect(struct usb_interface *intf) | |||
1571 | /*netif_device_detach(self->netdev);*/ | 1895 | /*netif_device_detach(self->netdev);*/ |
1572 | netif_stop_queue(self->netdev); | 1896 | netif_stop_queue(self->netdev); |
1573 | /* Stop all the receive URBs. Must be synchronous. */ | 1897 | /* Stop all the receive URBs. Must be synchronous. */ |
1574 | for (i = 0; i < IU_MAX_RX_URBS; i++) | 1898 | for (i = 0; i < self->max_rx_urb; i++) |
1575 | usb_kill_urb(self->rx_urb[i]); | 1899 | usb_kill_urb(self->rx_urb[i]); |
1576 | /* Cancel Tx and speed URB. | 1900 | /* Cancel Tx and speed URB. |
1577 | * Make sure it's synchronous to avoid races. */ | 1901 | * Make sure it's synchronous to avoid races. */ |
@@ -1586,8 +1910,9 @@ static void irda_usb_disconnect(struct usb_interface *intf) | |||
1586 | self->usbintf = NULL; | 1910 | self->usbintf = NULL; |
1587 | 1911 | ||
1588 | /* Clean up our urbs */ | 1912 | /* Clean up our urbs */ |
1589 | for (i = 0; i < IU_MAX_RX_URBS; i++) | 1913 | for (i = 0; i < self->max_rx_urb; i++) |
1590 | usb_free_urb(self->rx_urb[i]); | 1914 | usb_free_urb(self->rx_urb[i]); |
1915 | kfree(self->rx_urb); | ||
1591 | /* Clean up Tx and speed URB */ | 1916 | /* Clean up Tx and speed URB */ |
1592 | usb_free_urb(self->tx_urb); | 1917 | usb_free_urb(self->tx_urb); |
1593 | usb_free_urb(self->speed_urb); | 1918 | usb_free_urb(self->speed_urb); |
@@ -1648,6 +1973,6 @@ module_exit(usb_irda_cleanup); | |||
1648 | */ | 1973 | */ |
1649 | module_param(qos_mtt_bits, int, 0); | 1974 | module_param(qos_mtt_bits, int, 0); |
1650 | MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); | 1975 | MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); |
1651 | MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net> and Jean Tourrilhes <jt@hpl.hp.com>"); | 1976 | MODULE_AUTHOR("Roman Weissgaerber <weissg@vienna.at>, Dag Brattli <dag@brattli.net>, Jean Tourrilhes <jt@hpl.hp.com> and Nick Fedchik <nick@fedchik.org.ua>"); |
1652 | MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); | 1977 | MODULE_DESCRIPTION("IrDA-USB Dongle Driver"); |
1653 | MODULE_LICENSE("GPL"); | 1978 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/net/irda/irda-usb.h b/drivers/net/irda/irda-usb.h index 4026af42dd47..d833db52cebf 100644 --- a/drivers/net/irda/irda-usb.h +++ b/drivers/net/irda/irda-usb.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /***************************************************************************** | 1 | /***************************************************************************** |
2 | * | 2 | * |
3 | * Filename: irda-usb.h | 3 | * Filename: irda-usb.h |
4 | * Version: 0.9b | 4 | * Version: 0.10 |
5 | * Description: IrDA-USB Driver | 5 | * Description: IrDA-USB Driver |
6 | * Status: Experimental | 6 | * Status: Experimental |
7 | * Author: Dag Brattli <dag@brattli.net> | 7 | * Author: Dag Brattli <dag@brattli.net> |
@@ -9,6 +9,9 @@ | |||
9 | * Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at> | 9 | * Copyright (C) 2001, Roman Weissgaerber <weissg@vienna.at> |
10 | * Copyright (C) 2000, Dag Brattli <dag@brattli.net> | 10 | * Copyright (C) 2000, Dag Brattli <dag@brattli.net> |
11 | * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> | 11 | * Copyright (C) 2001, Jean Tourrilhes <jt@hpl.hp.com> |
12 | * Copyright (C) 2004, SigmaTel, Inc. <irquality@sigmatel.com> | ||
13 | * Copyright (C) 2005, Milan Beno <beno@pobox.sk> | ||
14 | * Copyright (C) 2006, Nick FEdchik <nick@fedchik.org.ua> | ||
12 | * | 15 | * |
13 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
@@ -31,6 +34,9 @@ | |||
31 | #include <net/irda/irda.h> | 34 | #include <net/irda/irda.h> |
32 | #include <net/irda/irda_device.h> /* struct irlap_cb */ | 35 | #include <net/irda/irda_device.h> /* struct irlap_cb */ |
33 | 36 | ||
37 | #define PATCH_FILE_SIZE_MAX 65536 | ||
38 | #define PATCH_FILE_SIZE_MIN 80 | ||
39 | |||
34 | #define RX_COPY_THRESHOLD 200 | 40 | #define RX_COPY_THRESHOLD 200 |
35 | #define IRDA_USB_MAX_MTU 2051 | 41 | #define IRDA_USB_MAX_MTU 2051 |
36 | #define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */ | 42 | #define IRDA_USB_SPEED_MTU 64 /* Weird, but work like this */ |
@@ -79,15 +85,16 @@ | |||
79 | /* Inbound header */ | 85 | /* Inbound header */ |
80 | #define MEDIA_BUSY 0x80 | 86 | #define MEDIA_BUSY 0x80 |
81 | 87 | ||
82 | #define SPEED_2400 0x01 | 88 | #define SPEED_2400 0x01 |
83 | #define SPEED_9600 0x02 | 89 | #define SPEED_9600 0x02 |
84 | #define SPEED_19200 0x03 | 90 | #define SPEED_19200 0x03 |
85 | #define SPEED_38400 0x04 | 91 | #define SPEED_38400 0x04 |
86 | #define SPEED_57600 0x05 | 92 | #define SPEED_57600 0x05 |
87 | #define SPEED_115200 0x06 | 93 | #define SPEED_115200 0x06 |
88 | #define SPEED_576000 0x07 | 94 | #define SPEED_576000 0x07 |
89 | #define SPEED_1152000 0x08 | 95 | #define SPEED_1152000 0x08 |
90 | #define SPEED_4000000 0x09 | 96 | #define SPEED_4000000 0x09 |
97 | #define SPEED_16000000 0x0a | ||
91 | 98 | ||
92 | /* Basic capabilities */ | 99 | /* Basic capabilities */ |
93 | #define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */ | 100 | #define IUC_DEFAULT 0x00 /* Basic device compliant with 1.0 spec */ |
@@ -100,11 +107,14 @@ | |||
100 | #define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */ | 107 | #define IUC_SMALL_PKT 0x10 /* Device doesn't behave with big Rx packets */ |
101 | #define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */ | 108 | #define IUC_MAX_WINDOW 0x20 /* Device underestimate the Rx window */ |
102 | #define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */ | 109 | #define IUC_MAX_XBOFS 0x40 /* Device need more xbofs than advertised */ |
110 | #define IUC_STIR_4210 0x80 /* SigmaTel 4210/4220/4116 VFIR */ | ||
103 | 111 | ||
104 | /* USB class definitions */ | 112 | /* USB class definitions */ |
105 | #define USB_IRDA_HEADER 0x01 | 113 | #define USB_IRDA_HEADER 0x01 |
106 | #define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */ | 114 | #define USB_CLASS_IRDA 0x02 /* USB_CLASS_APP_SPEC subclass */ |
107 | #define USB_DT_IRDA 0x21 | 115 | #define USB_DT_IRDA 0x21 |
116 | #define USB_IRDA_SIGMATEL_HEADER 0x03 | ||
117 | #define IU_SIGMATEL_MAX_RX_URBS (IU_MAX_ACTIVE_RX_URBS + USB_IRDA_SIGMATEL_HEADER) | ||
108 | 118 | ||
109 | struct irda_class_desc { | 119 | struct irda_class_desc { |
110 | __u8 bLength; | 120 | __u8 bLength; |
@@ -123,6 +133,7 @@ struct irda_class_desc { | |||
123 | * (6.2.5, USB-IrDA class spec 1.0) */ | 133 | * (6.2.5, USB-IrDA class spec 1.0) */ |
124 | 134 | ||
125 | #define IU_REQ_GET_CLASS_DESC 0x06 | 135 | #define IU_REQ_GET_CLASS_DESC 0x06 |
136 | #define STIR421X_MAX_PATCH_DOWNLOAD_SIZE 1023 | ||
126 | 137 | ||
127 | struct irda_usb_cb { | 138 | struct irda_usb_cb { |
128 | struct irda_class_desc *irda_desc; | 139 | struct irda_class_desc *irda_desc; |
@@ -136,7 +147,8 @@ struct irda_usb_cb { | |||
136 | __u16 bulk_out_mtu; /* Max Tx packet size in bytes */ | 147 | __u16 bulk_out_mtu; /* Max Tx packet size in bytes */ |
137 | __u8 bulk_int_ep; /* Interrupt Endpoint assignments */ | 148 | __u8 bulk_int_ep; /* Interrupt Endpoint assignments */ |
138 | 149 | ||
139 | struct urb *rx_urb[IU_MAX_RX_URBS]; /* URBs used to receive data frames */ | 150 | __u8 max_rx_urb; |
151 | struct urb **rx_urb; /* URBs used to receive data frames */ | ||
140 | struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */ | 152 | struct urb *idle_rx_urb; /* Pointer to idle URB in Rx path */ |
141 | struct urb *tx_urb; /* URB used to send data frames */ | 153 | struct urb *tx_urb; /* URB used to send data frames */ |
142 | struct urb *speed_urb; /* URB used to send speed commands */ | 154 | struct urb *speed_urb; /* URB used to send speed commands */ |
@@ -157,6 +169,9 @@ struct irda_usb_cb { | |||
157 | __u32 speed; /* Current speed */ | 169 | __u32 speed; /* Current speed */ |
158 | __s32 new_speed; /* speed we need to set */ | 170 | __s32 new_speed; /* speed we need to set */ |
159 | 171 | ||
172 | __u8 header_length; /* USB-IrDA frame header size */ | ||
173 | int needspatch; /* device needs firmware patch */ | ||
174 | |||
160 | struct timer_list rx_defer_timer; /* Wait for Rx error to clear */ | 175 | struct timer_list rx_defer_timer; /* Wait for Rx error to clear */ |
161 | }; | 176 | }; |
162 | 177 | ||
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index 63d38fbbd04e..f530686bd09f 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c | |||
@@ -695,8 +695,7 @@ static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) | |||
695 | /* | 695 | /* |
696 | * We must not be transmitting... | 696 | * We must not be transmitting... |
697 | */ | 697 | */ |
698 | if (si->txskb) | 698 | BUG_ON(si->txskb); |
699 | BUG(); | ||
700 | 699 | ||
701 | netif_stop_queue(dev); | 700 | netif_stop_queue(dev); |
702 | 701 | ||
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c index ec94ecdb103d..58f76cefbc83 100644 --- a/drivers/net/irda/smsc-ircc2.c +++ b/drivers/net/irda/smsc-ircc2.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * Copyright (c) 2002 Daniele Peri | 11 | * Copyright (c) 2002 Daniele Peri |
12 | * All Rights Reserved. | 12 | * All Rights Reserved. |
13 | * Copyright (c) 2002 Jean Tourrilhes | 13 | * Copyright (c) 2002 Jean Tourrilhes |
14 | * Copyright (c) 2006 Linus Walleij | ||
14 | * | 15 | * |
15 | * | 16 | * |
16 | * Based on smc-ircc.c: | 17 | * Based on smc-ircc.c: |
@@ -61,6 +62,9 @@ | |||
61 | 62 | ||
62 | #include <linux/spinlock.h> | 63 | #include <linux/spinlock.h> |
63 | #include <linux/pm.h> | 64 | #include <linux/pm.h> |
65 | #ifdef CONFIG_PCI | ||
66 | #include <linux/pci.h> | ||
67 | #endif | ||
64 | 68 | ||
65 | #include <net/irda/wrapper.h> | 69 | #include <net/irda/wrapper.h> |
66 | #include <net/irda/irda.h> | 70 | #include <net/irda/irda.h> |
@@ -100,6 +104,22 @@ MODULE_PARM_DESC(ircc_transceiver, "Transceiver type"); | |||
100 | 104 | ||
101 | /* Types */ | 105 | /* Types */ |
102 | 106 | ||
107 | #ifdef CONFIG_PCI | ||
108 | struct smsc_ircc_subsystem_configuration { | ||
109 | unsigned short vendor; /* PCI vendor ID */ | ||
110 | unsigned short device; /* PCI vendor ID */ | ||
111 | unsigned short subvendor; /* PCI subsystem vendor ID */ | ||
112 | unsigned short subdevice; /* PCI sybsystem device ID */ | ||
113 | unsigned short sir_io; /* I/O port for SIR */ | ||
114 | unsigned short fir_io; /* I/O port for FIR */ | ||
115 | unsigned char fir_irq; /* FIR IRQ */ | ||
116 | unsigned char fir_dma; /* FIR DMA */ | ||
117 | unsigned short cfg_base; /* I/O port for chip configuration */ | ||
118 | int (*preconfigure)(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); /* Preconfig function */ | ||
119 | const char *name; /* name shown as info */ | ||
120 | }; | ||
121 | #endif | ||
122 | |||
103 | struct smsc_transceiver { | 123 | struct smsc_transceiver { |
104 | char *name; | 124 | char *name; |
105 | void (*set_for_speed)(int fir_base, u32 speed); | 125 | void (*set_for_speed)(int fir_base, u32 speed); |
@@ -202,6 +222,18 @@ static int __init smsc_superio_flat(const struct smsc_chip *chips, unsigned shor | |||
202 | static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); | 222 | static int __init smsc_superio_paged(const struct smsc_chip *chips, unsigned short cfg_base, char *type); |
203 | static int __init smsc_superio_fdc(unsigned short cfg_base); | 223 | static int __init smsc_superio_fdc(unsigned short cfg_base); |
204 | static int __init smsc_superio_lpc(unsigned short cfg_base); | 224 | static int __init smsc_superio_lpc(unsigned short cfg_base); |
225 | #ifdef CONFIG_PCI | ||
226 | static int __init preconfigure_smsc_chip(struct smsc_ircc_subsystem_configuration *conf); | ||
227 | static int __init preconfigure_through_82801(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); | ||
228 | static void __init preconfigure_ali_port(struct pci_dev *dev, | ||
229 | unsigned short port); | ||
230 | static int __init preconfigure_through_ali(struct pci_dev *dev, struct smsc_ircc_subsystem_configuration *conf); | ||
231 | static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, | ||
232 | unsigned short ircc_fir, | ||
233 | unsigned short ircc_sir, | ||
234 | unsigned char ircc_dma, | ||
235 | unsigned char ircc_irq); | ||
236 | #endif | ||
205 | 237 | ||
206 | /* Transceivers specific functions */ | 238 | /* Transceivers specific functions */ |
207 | 239 | ||
@@ -353,6 +385,13 @@ static int __init smsc_ircc_init(void) | |||
353 | return ret; | 385 | return ret; |
354 | } | 386 | } |
355 | 387 | ||
388 | #ifdef CONFIG_PCI | ||
389 | if (smsc_ircc_preconfigure_subsystems(ircc_cfg, ircc_fir, ircc_sir, ircc_dma, ircc_irq) < 0) { | ||
390 | /* Ignore errors from preconfiguration */ | ||
391 | IRDA_ERROR("%s, Preconfiguration failed !\n", driver_name); | ||
392 | } | ||
393 | #endif | ||
394 | |||
356 | dev_count = 0; | 395 | dev_count = 0; |
357 | 396 | ||
358 | if (ircc_fir > 0 && ircc_sir > 0) { | 397 | if (ircc_fir > 0 && ircc_sir > 0) { |
@@ -2285,6 +2324,490 @@ static int __init smsc_superio_lpc(unsigned short cfg_base) | |||
2285 | return ret; | 2324 | return ret; |
2286 | } | 2325 | } |
2287 | 2326 | ||
2327 | /* | ||
2328 | * Look for some specific subsystem setups that need | ||
2329 | * pre-configuration not properly done by the BIOS (especially laptops) | ||
2330 | * This code is based in part on smcinit.c, tosh1800-smcinit.c | ||
2331 | * and tosh2450-smcinit.c. The table lists the device entries | ||
2332 | * for ISA bridges with an LPC (Low Pin Count) controller which | ||
2333 | * handles the communication with the SMSC device. After the LPC | ||
2334 | * controller is initialized through PCI, the SMSC device is initialized | ||
2335 | * through a dedicated port in the ISA port-mapped I/O area, this latter | ||
2336 | * area is used to configure the SMSC device with default | ||
2337 | * SIR and FIR I/O ports, DMA and IRQ. Different vendors have | ||
2338 | * used different sets of parameters and different control port | ||
2339 | * addresses making a subsystem device table necessary. | ||
2340 | */ | ||
2341 | #ifdef CONFIG_PCI | ||
2342 | #define PCIID_VENDOR_INTEL 0x8086 | ||
2343 | #define PCIID_VENDOR_ALI 0x10b9 | ||
2344 | static struct smsc_ircc_subsystem_configuration subsystem_configurations[] __devinitdata = { | ||
2345 | { | ||
2346 | .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */ | ||
2347 | .device = 0x24cc, | ||
2348 | .subvendor = 0x103c, | ||
2349 | .subdevice = 0x088c, | ||
2350 | /* Quite certain these are the same for nc8000 as for nc6000 */ | ||
2351 | .sir_io = 0x02f8, | ||
2352 | .fir_io = 0x0130, | ||
2353 | .fir_irq = 0x05, | ||
2354 | .fir_dma = 0x03, | ||
2355 | .cfg_base = 0x004e, | ||
2356 | .preconfigure = preconfigure_through_82801, | ||
2357 | .name = "HP nc8000", | ||
2358 | }, | ||
2359 | { | ||
2360 | .vendor = PCIID_VENDOR_INTEL, /* Intel 82801DBM LPC bridge */ | ||
2361 | .device = 0x24cc, | ||
2362 | .subvendor = 0x103c, | ||
2363 | .subdevice = 0x0890, | ||
2364 | .sir_io = 0x02f8, | ||
2365 | .fir_io = 0x0130, | ||
2366 | .fir_irq = 0x05, | ||
2367 | .fir_dma = 0x03, | ||
2368 | .cfg_base = 0x004e, | ||
2369 | .preconfigure = preconfigure_through_82801, | ||
2370 | .name = "HP nc6000", | ||
2371 | }, | ||
2372 | { | ||
2373 | /* Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge */ | ||
2374 | .vendor = PCIID_VENDOR_INTEL, | ||
2375 | .device = 0x24c0, | ||
2376 | .subvendor = 0x1179, | ||
2377 | .subdevice = 0xffff, /* 0xffff is "any" */ | ||
2378 | .sir_io = 0x03f8, | ||
2379 | .fir_io = 0x0130, | ||
2380 | .fir_irq = 0x07, | ||
2381 | .fir_dma = 0x01, | ||
2382 | .cfg_base = 0x002e, | ||
2383 | .preconfigure = preconfigure_through_82801, | ||
2384 | .name = "Toshiba laptop with Intel 82801DB/DBL LPC bridge", | ||
2385 | }, | ||
2386 | { | ||
2387 | .vendor = PCIID_VENDOR_INTEL, /* Intel 82801CAM ISA bridge */ | ||
2388 | .device = 0x248c, | ||
2389 | .subvendor = 0x1179, | ||
2390 | .subdevice = 0xffff, /* 0xffff is "any" */ | ||
2391 | .sir_io = 0x03f8, | ||
2392 | .fir_io = 0x0130, | ||
2393 | .fir_irq = 0x03, | ||
2394 | .fir_dma = 0x03, | ||
2395 | .cfg_base = 0x002e, | ||
2396 | .preconfigure = preconfigure_through_82801, | ||
2397 | .name = "Toshiba laptop with Intel 82801CAM ISA bridge", | ||
2398 | }, | ||
2399 | { | ||
2400 | /* 82801DBM (ICH4-M) LPC Interface Bridge */ | ||
2401 | .vendor = PCIID_VENDOR_INTEL, | ||
2402 | .device = 0x24cc, | ||
2403 | .subvendor = 0x1179, | ||
2404 | .subdevice = 0xffff, /* 0xffff is "any" */ | ||
2405 | .sir_io = 0x03f8, | ||
2406 | .fir_io = 0x0130, | ||
2407 | .fir_irq = 0x03, | ||
2408 | .fir_dma = 0x03, | ||
2409 | .cfg_base = 0x002e, | ||
2410 | .preconfigure = preconfigure_through_82801, | ||
2411 | .name = "Toshiba laptop with Intel 8281DBM LPC bridge", | ||
2412 | }, | ||
2413 | { | ||
2414 | /* ALi M1533/M1535 PCI to ISA Bridge [Aladdin IV/V/V+] */ | ||
2415 | .vendor = PCIID_VENDOR_ALI, | ||
2416 | .device = 0x1533, | ||
2417 | .subvendor = 0x1179, | ||
2418 | .subdevice = 0xffff, /* 0xffff is "any" */ | ||
2419 | .sir_io = 0x02e8, | ||
2420 | .fir_io = 0x02f8, | ||
2421 | .fir_irq = 0x07, | ||
2422 | .fir_dma = 0x03, | ||
2423 | .cfg_base = 0x002e, | ||
2424 | .preconfigure = preconfigure_through_ali, | ||
2425 | .name = "Toshiba laptop with ALi ISA bridge", | ||
2426 | }, | ||
2427 | { } // Terminator | ||
2428 | }; | ||
2429 | |||
2430 | |||
2431 | /* | ||
2432 | * This sets up the basic SMSC parameters | ||
2433 | * (FIR port, SIR port, FIR DMA, FIR IRQ) | ||
2434 | * through the chip configuration port. | ||
2435 | */ | ||
2436 | static int __init preconfigure_smsc_chip(struct | ||
2437 | smsc_ircc_subsystem_configuration | ||
2438 | *conf) | ||
2439 | { | ||
2440 | unsigned short iobase = conf->cfg_base; | ||
2441 | unsigned char tmpbyte; | ||
2442 | |||
2443 | outb(LPC47N227_CFGACCESSKEY, iobase); // enter configuration state | ||
2444 | outb(SMSCSIOFLAT_DEVICEID_REG, iobase); // set for device ID | ||
2445 | tmpbyte = inb(iobase +1); // Read device ID | ||
2446 | IRDA_DEBUG(0, | ||
2447 | "Detected Chip id: 0x%02x, setting up registers...\n", | ||
2448 | tmpbyte); | ||
2449 | |||
2450 | /* Disable UART1 and set up SIR I/O port */ | ||
2451 | outb(0x24, iobase); // select CR24 - UART1 base addr | ||
2452 | outb(0x00, iobase + 1); // disable UART1 | ||
2453 | outb(SMSCSIOFLAT_UART2BASEADDR_REG, iobase); // select CR25 - UART2 base addr | ||
2454 | outb( (conf->sir_io >> 2), iobase + 1); // bits 2-9 of 0x3f8 | ||
2455 | tmpbyte = inb(iobase + 1); | ||
2456 | if (tmpbyte != (conf->sir_io >> 2) ) { | ||
2457 | IRDA_WARNING("ERROR: could not configure SIR ioport.\n"); | ||
2458 | IRDA_WARNING("Try to supply ircc_cfg argument.\n"); | ||
2459 | return -ENXIO; | ||
2460 | } | ||
2461 | |||
2462 | /* Set up FIR IRQ channel for UART2 */ | ||
2463 | outb(SMSCSIOFLAT_UARTIRQSELECT_REG, iobase); // select CR28 - UART1,2 IRQ select | ||
2464 | tmpbyte = inb(iobase + 1); | ||
2465 | tmpbyte &= SMSCSIOFLAT_UART1IRQSELECT_MASK; // Do not touch the UART1 portion | ||
2466 | tmpbyte |= (conf->fir_irq & SMSCSIOFLAT_UART2IRQSELECT_MASK); | ||
2467 | outb(tmpbyte, iobase + 1); | ||
2468 | tmpbyte = inb(iobase + 1) & SMSCSIOFLAT_UART2IRQSELECT_MASK; | ||
2469 | if (tmpbyte != conf->fir_irq) { | ||
2470 | IRDA_WARNING("ERROR: could not configure FIR IRQ channel.\n"); | ||
2471 | return -ENXIO; | ||
2472 | } | ||
2473 | |||
2474 | /* Set up FIR I/O port */ | ||
2475 | outb(SMSCSIOFLAT_FIRBASEADDR_REG, iobase); // CR2B - SCE (FIR) base addr | ||
2476 | outb((conf->fir_io >> 3), iobase + 1); | ||
2477 | tmpbyte = inb(iobase + 1); | ||
2478 | if (tmpbyte != (conf->fir_io >> 3) ) { | ||
2479 | IRDA_WARNING("ERROR: could not configure FIR I/O port.\n"); | ||
2480 | return -ENXIO; | ||
2481 | } | ||
2482 | |||
2483 | /* Set up FIR DMA channel */ | ||
2484 | outb(SMSCSIOFLAT_FIRDMASELECT_REG, iobase); // CR2C - SCE (FIR) DMA select | ||
2485 | outb((conf->fir_dma & LPC47N227_FIRDMASELECT_MASK), iobase + 1); // DMA | ||
2486 | tmpbyte = inb(iobase + 1) & LPC47N227_FIRDMASELECT_MASK; | ||
2487 | if (tmpbyte != (conf->fir_dma & LPC47N227_FIRDMASELECT_MASK)) { | ||
2488 | IRDA_WARNING("ERROR: could not configure FIR DMA channel.\n"); | ||
2489 | return -ENXIO; | ||
2490 | } | ||
2491 | |||
2492 | outb(SMSCSIOFLAT_UARTMODE0C_REG, iobase); // CR0C - UART mode | ||
2493 | tmpbyte = inb(iobase + 1); | ||
2494 | tmpbyte &= ~SMSCSIOFLAT_UART2MODE_MASK | | ||
2495 | SMSCSIOFLAT_UART2MODE_VAL_IRDA; | ||
2496 | outb(tmpbyte, iobase + 1); // enable IrDA (HPSIR) mode, high speed | ||
2497 | |||
2498 | outb(LPC47N227_APMBOOTDRIVE_REG, iobase); // CR07 - Auto Pwr Mgt/boot drive sel | ||
2499 | tmpbyte = inb(iobase + 1); | ||
2500 | outb(tmpbyte | LPC47N227_UART2AUTOPWRDOWN_MASK, iobase + 1); // enable UART2 autopower down | ||
2501 | |||
2502 | /* This one was not part of tosh1800 */ | ||
2503 | outb(0x0a, iobase); // CR0a - ecp fifo / ir mux | ||
2504 | tmpbyte = inb(iobase + 1); | ||
2505 | outb(tmpbyte | 0x40, iobase + 1); // send active device to ir port | ||
2506 | |||
2507 | outb(LPC47N227_UART12POWER_REG, iobase); // CR02 - UART 1,2 power | ||
2508 | tmpbyte = inb(iobase + 1); | ||
2509 | outb(tmpbyte | LPC47N227_UART2POWERDOWN_MASK, iobase + 1); // UART2 power up mode, UART1 power down | ||
2510 | |||
2511 | outb(LPC47N227_FDCPOWERVALIDCONF_REG, iobase); // CR00 - FDC Power/valid config cycle | ||
2512 | tmpbyte = inb(iobase + 1); | ||
2513 | outb(tmpbyte | LPC47N227_VALID_MASK, iobase + 1); // valid config cycle done | ||
2514 | |||
2515 | outb(LPC47N227_CFGEXITKEY, iobase); // Exit configuration | ||
2516 | |||
2517 | return 0; | ||
2518 | } | ||
2519 | |||
2520 | /* 82801CAM generic registers */ | ||
2521 | #define VID 0x00 | ||
2522 | #define DID 0x02 | ||
2523 | #define PIRQ_A_D_ROUT 0x60 | ||
2524 | #define SIRQ_CNTL 0x64 | ||
2525 | #define PIRQ_E_H_ROUT 0x68 | ||
2526 | #define PCI_DMA_C 0x90 | ||
2527 | /* LPC-specific registers */ | ||
2528 | #define COM_DEC 0xe0 | ||
2529 | #define GEN1_DEC 0xe4 | ||
2530 | #define LPC_EN 0xe6 | ||
2531 | #define GEN2_DEC 0xec | ||
2532 | /* | ||
2533 | * Sets up the I/O range using the 82801CAM ISA bridge, 82801DBM LPC bridge | ||
2534 | * or Intel 82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge. | ||
2535 | * They all work the same way! | ||
2536 | */ | ||
2537 | static int __init preconfigure_through_82801(struct pci_dev *dev, | ||
2538 | struct | ||
2539 | smsc_ircc_subsystem_configuration | ||
2540 | *conf) | ||
2541 | { | ||
2542 | unsigned short tmpword; | ||
2543 | unsigned char tmpbyte; | ||
2544 | |||
2545 | IRDA_MESSAGE("Setting up Intel 82801 controller and SMSC device\n"); | ||
2546 | /* | ||
2547 | * Select the range for the COMA COM port (SIR) | ||
2548 | * Register COM_DEC: | ||
2549 | * Bit 7: reserved | ||
2550 | * Bit 6-4, COMB decode range | ||
2551 | * Bit 3: reserved | ||
2552 | * Bit 2-0, COMA decode range | ||
2553 | * | ||
2554 | * Decode ranges: | ||
2555 | * 000 = 0x3f8-0x3ff (COM1) | ||
2556 | * 001 = 0x2f8-0x2ff (COM2) | ||
2557 | * 010 = 0x220-0x227 | ||
2558 | * 011 = 0x228-0x22f | ||
2559 | * 100 = 0x238-0x23f | ||
2560 | * 101 = 0x2e8-0x2ef (COM4) | ||
2561 | * 110 = 0x338-0x33f | ||
2562 | * 111 = 0x3e8-0x3ef (COM3) | ||
2563 | */ | ||
2564 | pci_read_config_byte(dev, COM_DEC, &tmpbyte); | ||
2565 | tmpbyte &= 0xf8; /* mask COMA bits */ | ||
2566 | switch(conf->sir_io) { | ||
2567 | case 0x3f8: | ||
2568 | tmpbyte |= 0x00; | ||
2569 | break; | ||
2570 | case 0x2f8: | ||
2571 | tmpbyte |= 0x01; | ||
2572 | break; | ||
2573 | case 0x220: | ||
2574 | tmpbyte |= 0x02; | ||
2575 | break; | ||
2576 | case 0x228: | ||
2577 | tmpbyte |= 0x03; | ||
2578 | break; | ||
2579 | case 0x238: | ||
2580 | tmpbyte |= 0x04; | ||
2581 | break; | ||
2582 | case 0x2e8: | ||
2583 | tmpbyte |= 0x05; | ||
2584 | break; | ||
2585 | case 0x338: | ||
2586 | tmpbyte |= 0x06; | ||
2587 | break; | ||
2588 | case 0x3e8: | ||
2589 | tmpbyte |= 0x07; | ||
2590 | break; | ||
2591 | default: | ||
2592 | tmpbyte |= 0x01; /* COM2 default */ | ||
2593 | } | ||
2594 | IRDA_DEBUG(1, "COM_DEC (write): 0x%02x\n", tmpbyte); | ||
2595 | pci_write_config_byte(dev, COM_DEC, tmpbyte); | ||
2596 | |||
2597 | /* Enable Low Pin Count interface */ | ||
2598 | pci_read_config_word(dev, LPC_EN, &tmpword); | ||
2599 | /* These seem to be set up at all times, | ||
2600 | * just make sure it is properly set. | ||
2601 | */ | ||
2602 | switch(conf->cfg_base) { | ||
2603 | case 0x04e: | ||
2604 | tmpword |= 0x2000; | ||
2605 | break; | ||
2606 | case 0x02e: | ||
2607 | tmpword |= 0x1000; | ||
2608 | break; | ||
2609 | case 0x062: | ||
2610 | tmpword |= 0x0800; | ||
2611 | break; | ||
2612 | case 0x060: | ||
2613 | tmpword |= 0x0400; | ||
2614 | break; | ||
2615 | default: | ||
2616 | IRDA_WARNING("Uncommon I/O base address: 0x%04x\n", | ||
2617 | conf->cfg_base); | ||
2618 | break; | ||
2619 | } | ||
2620 | tmpword &= 0xfffd; /* disable LPC COMB */ | ||
2621 | tmpword |= 0x0001; /* set bit 0 : enable LPC COMA addr range (GEN2) */ | ||
2622 | IRDA_DEBUG(1, "LPC_EN (write): 0x%04x\n", tmpword); | ||
2623 | pci_write_config_word(dev, LPC_EN, tmpword); | ||
2624 | |||
2625 | /* | ||
2626 | * Configure LPC DMA channel | ||
2627 | * PCI_DMA_C bits: | ||
2628 | * Bit 15-14: DMA channel 7 select | ||
2629 | * Bit 13-12: DMA channel 6 select | ||
2630 | * Bit 11-10: DMA channel 5 select | ||
2631 | * Bit 9-8: Reserved | ||
2632 | * Bit 7-6: DMA channel 3 select | ||
2633 | * Bit 5-4: DMA channel 2 select | ||
2634 | * Bit 3-2: DMA channel 1 select | ||
2635 | * Bit 1-0: DMA channel 0 select | ||
2636 | * 00 = Reserved value | ||
2637 | * 01 = PC/PCI DMA | ||
2638 | * 10 = Reserved value | ||
2639 | * 11 = LPC I/F DMA | ||
2640 | */ | ||
2641 | pci_read_config_word(dev, PCI_DMA_C, &tmpword); | ||
2642 | switch(conf->fir_dma) { | ||
2643 | case 0x07: | ||
2644 | tmpword |= 0xc000; | ||
2645 | break; | ||
2646 | case 0x06: | ||
2647 | tmpword |= 0x3000; | ||
2648 | break; | ||
2649 | case 0x05: | ||
2650 | tmpword |= 0x0c00; | ||
2651 | break; | ||
2652 | case 0x03: | ||
2653 | tmpword |= 0x00c0; | ||
2654 | break; | ||
2655 | case 0x02: | ||
2656 | tmpword |= 0x0030; | ||
2657 | break; | ||
2658 | case 0x01: | ||
2659 | tmpword |= 0x000c; | ||
2660 | break; | ||
2661 | case 0x00: | ||
2662 | tmpword |= 0x0003; | ||
2663 | break; | ||
2664 | default: | ||
2665 | break; /* do not change settings */ | ||
2666 | } | ||
2667 | IRDA_DEBUG(1, "PCI_DMA_C (write): 0x%04x\n", tmpword); | ||
2668 | pci_write_config_word(dev, PCI_DMA_C, tmpword); | ||
2669 | |||
2670 | /* | ||
2671 | * GEN2_DEC bits: | ||
2672 | * Bit 15-4: Generic I/O range | ||
2673 | * Bit 3-1: reserved (read as 0) | ||
2674 | * Bit 0: enable GEN2 range on LPC I/F | ||
2675 | */ | ||
2676 | tmpword = conf->fir_io & 0xfff8; | ||
2677 | tmpword |= 0x0001; | ||
2678 | IRDA_DEBUG(1, "GEN2_DEC (write): 0x%04x\n", tmpword); | ||
2679 | pci_write_config_word(dev, GEN2_DEC, tmpword); | ||
2680 | |||
2681 | /* Pre-configure chip */ | ||
2682 | return preconfigure_smsc_chip(conf); | ||
2683 | } | ||
2684 | |||
2685 | /* | ||
2686 | * Pre-configure a certain port on the ALi 1533 bridge. | ||
2687 | * This is based on reverse-engineering since ALi does not | ||
2688 | * provide any data sheet for the 1533 chip. | ||
2689 | */ | ||
2690 | static void __init preconfigure_ali_port(struct pci_dev *dev, | ||
2691 | unsigned short port) | ||
2692 | { | ||
2693 | unsigned char reg; | ||
2694 | /* These bits obviously control the different ports */ | ||
2695 | unsigned char mask; | ||
2696 | unsigned char tmpbyte; | ||
2697 | |||
2698 | switch(port) { | ||
2699 | case 0x0130: | ||
2700 | case 0x0178: | ||
2701 | reg = 0xb0; | ||
2702 | mask = 0x80; | ||
2703 | break; | ||
2704 | case 0x03f8: | ||
2705 | reg = 0xb4; | ||
2706 | mask = 0x80; | ||
2707 | break; | ||
2708 | case 0x02f8: | ||
2709 | reg = 0xb4; | ||
2710 | mask = 0x30; | ||
2711 | break; | ||
2712 | case 0x02e8: | ||
2713 | reg = 0xb4; | ||
2714 | mask = 0x08; | ||
2715 | break; | ||
2716 | default: | ||
2717 | IRDA_ERROR("Failed to configure unsupported port on ALi 1533 bridge: 0x%04x\n", port); | ||
2718 | return; | ||
2719 | } | ||
2720 | |||
2721 | pci_read_config_byte(dev, reg, &tmpbyte); | ||
2722 | /* Turn on the right bits */ | ||
2723 | tmpbyte |= mask; | ||
2724 | pci_write_config_byte(dev, reg, tmpbyte); | ||
2725 | IRDA_MESSAGE("Activated ALi 1533 ISA bridge port 0x%04x.\n", port); | ||
2726 | return; | ||
2727 | } | ||
2728 | |||
2729 | static int __init preconfigure_through_ali(struct pci_dev *dev, | ||
2730 | struct | ||
2731 | smsc_ircc_subsystem_configuration | ||
2732 | *conf) | ||
2733 | { | ||
2734 | /* Configure the two ports on the ALi 1533 */ | ||
2735 | preconfigure_ali_port(dev, conf->sir_io); | ||
2736 | preconfigure_ali_port(dev, conf->fir_io); | ||
2737 | |||
2738 | /* Pre-configure chip */ | ||
2739 | return preconfigure_smsc_chip(conf); | ||
2740 | } | ||
2741 | |||
2742 | static int __init smsc_ircc_preconfigure_subsystems(unsigned short ircc_cfg, | ||
2743 | unsigned short ircc_fir, | ||
2744 | unsigned short ircc_sir, | ||
2745 | unsigned char ircc_dma, | ||
2746 | unsigned char ircc_irq) | ||
2747 | { | ||
2748 | struct pci_dev *dev = NULL; | ||
2749 | unsigned short ss_vendor = 0x0000; | ||
2750 | unsigned short ss_device = 0x0000; | ||
2751 | int ret = 0; | ||
2752 | |||
2753 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); | ||
2754 | |||
2755 | while (dev != NULL) { | ||
2756 | struct smsc_ircc_subsystem_configuration *conf; | ||
2757 | |||
2758 | /* | ||
2759 | * Cache the subsystem vendor/device: | ||
2760 | * some manufacturers fail to set this for all components, | ||
2761 | * so we save it in case there is just 0x0000 0x0000 on the | ||
2762 | * device we want to check. | ||
2763 | */ | ||
2764 | if (dev->subsystem_vendor != 0x0000U) { | ||
2765 | ss_vendor = dev->subsystem_vendor; | ||
2766 | ss_device = dev->subsystem_device; | ||
2767 | } | ||
2768 | conf = subsystem_configurations; | ||
2769 | for( ; conf->subvendor; conf++) { | ||
2770 | if(conf->vendor == dev->vendor && | ||
2771 | conf->device == dev->device && | ||
2772 | conf->subvendor == ss_vendor && | ||
2773 | /* Sometimes these are cached values */ | ||
2774 | (conf->subdevice == ss_device || | ||
2775 | conf->subdevice == 0xffff)) { | ||
2776 | struct smsc_ircc_subsystem_configuration | ||
2777 | tmpconf; | ||
2778 | |||
2779 | memcpy(&tmpconf, conf, | ||
2780 | sizeof(struct smsc_ircc_subsystem_configuration)); | ||
2781 | |||
2782 | /* | ||
2783 | * Override the default values with anything | ||
2784 | * passed in as parameter | ||
2785 | */ | ||
2786 | if (ircc_cfg != 0) | ||
2787 | tmpconf.cfg_base = ircc_cfg; | ||
2788 | if (ircc_fir != 0) | ||
2789 | tmpconf.fir_io = ircc_fir; | ||
2790 | if (ircc_sir != 0) | ||
2791 | tmpconf.sir_io = ircc_sir; | ||
2792 | if (ircc_dma != 0xff) | ||
2793 | tmpconf.fir_dma = ircc_dma; | ||
2794 | if (ircc_irq != 0xff) | ||
2795 | tmpconf.fir_irq = ircc_irq; | ||
2796 | |||
2797 | IRDA_MESSAGE("Detected unconfigured %s SMSC IrDA chip, pre-configuring device.\n", conf->name); | ||
2798 | if (conf->preconfigure) | ||
2799 | ret = conf->preconfigure(dev, &tmpconf); | ||
2800 | else | ||
2801 | ret = -ENODEV; | ||
2802 | } | ||
2803 | } | ||
2804 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); | ||
2805 | } | ||
2806 | |||
2807 | return ret; | ||
2808 | } | ||
2809 | #endif // CONFIG_PCI | ||
2810 | |||
2288 | /************************************************ | 2811 | /************************************************ |
2289 | * | 2812 | * |
2290 | * Transceivers specific functions | 2813 | * Transceivers specific functions |
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index f9f77e4f5965..cfd67d812f0d 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c | |||
@@ -357,18 +357,20 @@ ixgb_probe(struct pci_dev *pdev, | |||
357 | if((err = pci_enable_device(pdev))) | 357 | if((err = pci_enable_device(pdev))) |
358 | return err; | 358 | return err; |
359 | 359 | ||
360 | if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { | 360 | if(!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)) && |
361 | !(err = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))) { | ||
361 | pci_using_dac = 1; | 362 | pci_using_dac = 1; |
362 | } else { | 363 | } else { |
363 | if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) { | 364 | if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) || |
365 | (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) { | ||
364 | IXGB_ERR("No usable DMA configuration, aborting\n"); | 366 | IXGB_ERR("No usable DMA configuration, aborting\n"); |
365 | return err; | 367 | goto err_dma_mask; |
366 | } | 368 | } |
367 | pci_using_dac = 0; | 369 | pci_using_dac = 0; |
368 | } | 370 | } |
369 | 371 | ||
370 | if((err = pci_request_regions(pdev, ixgb_driver_name))) | 372 | if((err = pci_request_regions(pdev, ixgb_driver_name))) |
371 | return err; | 373 | goto err_request_regions; |
372 | 374 | ||
373 | pci_set_master(pdev); | 375 | pci_set_master(pdev); |
374 | 376 | ||
@@ -502,6 +504,9 @@ err_ioremap: | |||
502 | free_netdev(netdev); | 504 | free_netdev(netdev); |
503 | err_alloc_etherdev: | 505 | err_alloc_etherdev: |
504 | pci_release_regions(pdev); | 506 | pci_release_regions(pdev); |
507 | err_request_regions: | ||
508 | err_dma_mask: | ||
509 | pci_disable_device(pdev); | ||
505 | return err; | 510 | return err; |
506 | } | 511 | } |
507 | 512 | ||
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 9f2661355a4a..ea62a3e7d586 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -281,10 +281,16 @@ static void mv643xx_eth_tx_timeout_task(struct net_device *dev) | |||
281 | { | 281 | { |
282 | struct mv643xx_private *mp = netdev_priv(dev); | 282 | struct mv643xx_private *mp = netdev_priv(dev); |
283 | 283 | ||
284 | netif_device_detach(dev); | 284 | if (!netif_running(dev)) |
285 | return; | ||
286 | |||
287 | netif_stop_queue(dev); | ||
288 | |||
285 | eth_port_reset(mp->port_num); | 289 | eth_port_reset(mp->port_num); |
286 | eth_port_start(dev); | 290 | eth_port_start(dev); |
287 | netif_device_attach(dev); | 291 | |
292 | if (mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB) | ||
293 | netif_wake_queue(dev); | ||
288 | } | 294 | } |
289 | 295 | ||
290 | /** | 296 | /** |
@@ -552,9 +558,9 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, | |||
552 | #else | 558 | #else |
553 | if (eth_int_cause & ETH_INT_CAUSE_RX) | 559 | if (eth_int_cause & ETH_INT_CAUSE_RX) |
554 | mv643xx_eth_receive_queue(dev, INT_MAX); | 560 | mv643xx_eth_receive_queue(dev, INT_MAX); |
561 | #endif | ||
555 | if (eth_int_cause_ext & ETH_INT_CAUSE_TX) | 562 | if (eth_int_cause_ext & ETH_INT_CAUSE_TX) |
556 | mv643xx_eth_free_completed_tx_descs(dev); | 563 | mv643xx_eth_free_completed_tx_descs(dev); |
557 | #endif | ||
558 | 564 | ||
559 | /* | 565 | /* |
560 | * If no real interrupt occured, exit. | 566 | * If no real interrupt occured, exit. |
@@ -1186,7 +1192,12 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1186 | 1192 | ||
1187 | BUG_ON(netif_queue_stopped(dev)); | 1193 | BUG_ON(netif_queue_stopped(dev)); |
1188 | BUG_ON(skb == NULL); | 1194 | BUG_ON(skb == NULL); |
1189 | BUG_ON(mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB); | 1195 | |
1196 | if (mp->tx_ring_size - mp->tx_desc_count < MAX_DESCS_PER_SKB) { | ||
1197 | printk(KERN_ERR "%s: transmit with queue full\n", dev->name); | ||
1198 | netif_stop_queue(dev); | ||
1199 | return 1; | ||
1200 | } | ||
1190 | 1201 | ||
1191 | if (has_tiny_unaligned_frags(skb)) { | 1202 | if (has_tiny_unaligned_frags(skb)) { |
1192 | if ((skb_linearize(skb, GFP_ATOMIC) != 0)) { | 1203 | if ((skb_linearize(skb, GFP_ATOMIC) != 0)) { |
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c index 7826afbb9db9..90627756d6fa 100644 --- a/drivers/net/natsemi.c +++ b/drivers/net/natsemi.c | |||
@@ -238,7 +238,7 @@ static int full_duplex[MAX_UNITS]; | |||
238 | #define NATSEMI_RX_LIMIT 2046 /* maximum supported by hardware */ | 238 | #define NATSEMI_RX_LIMIT 2046 /* maximum supported by hardware */ |
239 | 239 | ||
240 | /* These identify the driver base version and may not be removed. */ | 240 | /* These identify the driver base version and may not be removed. */ |
241 | static char version[] __devinitdata = | 241 | static const char version[] __devinitdata = |
242 | KERN_INFO DRV_NAME " dp8381x driver, version " | 242 | KERN_INFO DRV_NAME " dp8381x driver, version " |
243 | DRV_VERSION ", " DRV_RELDATE "\n" | 243 | DRV_VERSION ", " DRV_RELDATE "\n" |
244 | KERN_INFO " originally by Donald Becker <becker@scyld.com>\n" | 244 | KERN_INFO " originally by Donald Becker <becker@scyld.com>\n" |
diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 08b218c5bfbc..93c494bcd18d 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c | |||
@@ -226,7 +226,7 @@ struct net_device * __init ne_probe(int unit) | |||
226 | netdev_boot_setup_check(dev); | 226 | netdev_boot_setup_check(dev); |
227 | 227 | ||
228 | #ifdef CONFIG_TOSHIBA_RBTX4938 | 228 | #ifdef CONFIG_TOSHIBA_RBTX4938 |
229 | dev->base_addr = 0x07f20280; | 229 | dev->base_addr = RBTX4938_RTL_8019_BASE; |
230 | dev->irq = RBTX4938_RTL_8019_IRQ; | 230 | dev->irq = RBTX4938_RTL_8019_IRQ; |
231 | #endif | 231 | #endif |
232 | err = do_ne_probe(dev); | 232 | err = do_ne_probe(dev); |
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index d11821dd86ed..ced9fdb8335c 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c | |||
@@ -645,9 +645,7 @@ static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev) | |||
645 | { | 645 | { |
646 | struct net_device *dev = pci_get_drvdata(pdev); | 646 | struct net_device *dev = pci_get_drvdata(pdev); |
647 | 647 | ||
648 | if (!dev) | 648 | BUG_ON(!dev); |
649 | BUG(); | ||
650 | |||
651 | unregister_netdev(dev); | 649 | unregister_netdev(dev); |
652 | release_region(dev->base_addr, NE_IO_EXTENT); | 650 | release_region(dev->base_addr, NE_IO_EXTENT); |
653 | free_netdev(dev); | 651 | free_netdev(dev); |
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 75b35ad760de..66e74f740261 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c | |||
@@ -87,6 +87,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len) | |||
87 | } | 87 | } |
88 | 88 | ||
89 | static struct console netconsole = { | 89 | static struct console netconsole = { |
90 | .name = "netcon", | ||
90 | .flags = CON_ENABLED | CON_PRINTBUFFER, | 91 | .flags = CON_ENABLED | CON_PRINTBUFFER, |
91 | .write = write_msg | 92 | .write = write_msg |
92 | }; | 93 | }; |
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index 8e9b1a537dee..706aed7d717f 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c | |||
@@ -568,8 +568,7 @@ static inline int ns83820_add_rx_skb(struct ns83820 *dev, struct sk_buff *skb) | |||
568 | #endif | 568 | #endif |
569 | 569 | ||
570 | sg = dev->rx_info.descs + (next_empty * DESC_SIZE); | 570 | sg = dev->rx_info.descs + (next_empty * DESC_SIZE); |
571 | if (unlikely(NULL != dev->rx_info.skbs[next_empty])) | 571 | BUG_ON(NULL != dev->rx_info.skbs[next_empty]); |
572 | BUG(); | ||
573 | dev->rx_info.skbs[next_empty] = skb; | 572 | dev->rx_info.skbs[next_empty] = skb; |
574 | 573 | ||
575 | dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC; | 574 | dev->rx_info.next_empty = (next_empty + 1) % NR_RX_DESC; |
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index ce90becb8bdf..fab93360f017 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c | |||
@@ -204,7 +204,7 @@ enum Window4 { /* Window 4: Xcvr/media bits. */ | |||
204 | #define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */ | 204 | #define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */ |
205 | 205 | ||
206 | struct el3_private { | 206 | struct el3_private { |
207 | dev_link_t link; | 207 | struct pcmcia_device *p_dev; |
208 | dev_node_t node; | 208 | dev_node_t node; |
209 | struct net_device_stats stats; | 209 | struct net_device_stats stats; |
210 | u16 advertising, partner; /* NWay media advertisement */ | 210 | u16 advertising, partner; /* NWay media advertisement */ |
@@ -225,8 +225,8 @@ static char mii_preamble_required = 0; | |||
225 | 225 | ||
226 | /* Index of functions. */ | 226 | /* Index of functions. */ |
227 | 227 | ||
228 | static void tc574_config(dev_link_t *link); | 228 | static int tc574_config(struct pcmcia_device *link); |
229 | static void tc574_release(dev_link_t *link); | 229 | static void tc574_release(struct pcmcia_device *link); |
230 | 230 | ||
231 | static void mdio_sync(kio_addr_t ioaddr, int bits); | 231 | static void mdio_sync(kio_addr_t ioaddr, int bits); |
232 | static int mdio_read(kio_addr_t ioaddr, int phy_id, int location); | 232 | static int mdio_read(kio_addr_t ioaddr, int phy_id, int location); |
@@ -256,10 +256,9 @@ static void tc574_detach(struct pcmcia_device *p_dev); | |||
256 | with Card Services. | 256 | with Card Services. |
257 | */ | 257 | */ |
258 | 258 | ||
259 | static int tc574_attach(struct pcmcia_device *p_dev) | 259 | static int tc574_probe(struct pcmcia_device *link) |
260 | { | 260 | { |
261 | struct el3_private *lp; | 261 | struct el3_private *lp; |
262 | dev_link_t *link; | ||
263 | struct net_device *dev; | 262 | struct net_device *dev; |
264 | 263 | ||
265 | DEBUG(0, "3c574_attach()\n"); | 264 | DEBUG(0, "3c574_attach()\n"); |
@@ -269,8 +268,8 @@ static int tc574_attach(struct pcmcia_device *p_dev) | |||
269 | if (!dev) | 268 | if (!dev) |
270 | return -ENOMEM; | 269 | return -ENOMEM; |
271 | lp = netdev_priv(dev); | 270 | lp = netdev_priv(dev); |
272 | link = &lp->link; | ||
273 | link->priv = dev; | 271 | link->priv = dev; |
272 | lp->p_dev = link; | ||
274 | 273 | ||
275 | spin_lock_init(&lp->window_lock); | 274 | spin_lock_init(&lp->window_lock); |
276 | link->io.NumPorts1 = 32; | 275 | link->io.NumPorts1 = 32; |
@@ -280,7 +279,6 @@ static int tc574_attach(struct pcmcia_device *p_dev) | |||
280 | link->irq.Handler = &el3_interrupt; | 279 | link->irq.Handler = &el3_interrupt; |
281 | link->irq.Instance = dev; | 280 | link->irq.Instance = dev; |
282 | link->conf.Attributes = CONF_ENABLE_IRQ; | 281 | link->conf.Attributes = CONF_ENABLE_IRQ; |
283 | link->conf.Vcc = 50; | ||
284 | link->conf.IntType = INT_MEMORY_AND_IO; | 282 | link->conf.IntType = INT_MEMORY_AND_IO; |
285 | link->conf.ConfigIndex = 1; | 283 | link->conf.ConfigIndex = 1; |
286 | link->conf.Present = PRESENT_OPTION; | 284 | link->conf.Present = PRESENT_OPTION; |
@@ -298,13 +296,7 @@ static int tc574_attach(struct pcmcia_device *p_dev) | |||
298 | dev->watchdog_timeo = TX_TIMEOUT; | 296 | dev->watchdog_timeo = TX_TIMEOUT; |
299 | #endif | 297 | #endif |
300 | 298 | ||
301 | link->handle = p_dev; | 299 | return tc574_config(link); |
302 | p_dev->instance = link; | ||
303 | |||
304 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
305 | tc574_config(link); | ||
306 | |||
307 | return 0; | ||
308 | } /* tc574_attach */ | 300 | } /* tc574_attach */ |
309 | 301 | ||
310 | /* | 302 | /* |
@@ -316,18 +308,16 @@ static int tc574_attach(struct pcmcia_device *p_dev) | |||
316 | 308 | ||
317 | */ | 309 | */ |
318 | 310 | ||
319 | static void tc574_detach(struct pcmcia_device *p_dev) | 311 | static void tc574_detach(struct pcmcia_device *link) |
320 | { | 312 | { |
321 | dev_link_t *link = dev_to_instance(p_dev); | ||
322 | struct net_device *dev = link->priv; | 313 | struct net_device *dev = link->priv; |
323 | 314 | ||
324 | DEBUG(0, "3c574_detach(0x%p)\n", link); | 315 | DEBUG(0, "3c574_detach(0x%p)\n", link); |
325 | 316 | ||
326 | if (link->dev) | 317 | if (link->dev_node) |
327 | unregister_netdev(dev); | 318 | unregister_netdev(dev); |
328 | 319 | ||
329 | if (link->state & DEV_CONFIG) | 320 | tc574_release(link); |
330 | tc574_release(link); | ||
331 | 321 | ||
332 | free_netdev(dev); | 322 | free_netdev(dev); |
333 | } /* tc574_detach */ | 323 | } /* tc574_detach */ |
@@ -343,9 +333,8 @@ static void tc574_detach(struct pcmcia_device *p_dev) | |||
343 | 333 | ||
344 | static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; | 334 | static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; |
345 | 335 | ||
346 | static void tc574_config(dev_link_t *link) | 336 | static int tc574_config(struct pcmcia_device *link) |
347 | { | 337 | { |
348 | client_handle_t handle = link->handle; | ||
349 | struct net_device *dev = link->priv; | 338 | struct net_device *dev = link->priv; |
350 | struct el3_private *lp = netdev_priv(dev); | 339 | struct el3_private *lp = netdev_priv(dev); |
351 | tuple_t tuple; | 340 | tuple_t tuple; |
@@ -363,30 +352,27 @@ static void tc574_config(dev_link_t *link) | |||
363 | 352 | ||
364 | tuple.Attributes = 0; | 353 | tuple.Attributes = 0; |
365 | tuple.DesiredTuple = CISTPL_CONFIG; | 354 | tuple.DesiredTuple = CISTPL_CONFIG; |
366 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 355 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
367 | tuple.TupleData = (cisdata_t *)buf; | 356 | tuple.TupleData = (cisdata_t *)buf; |
368 | tuple.TupleDataMax = 64; | 357 | tuple.TupleDataMax = 64; |
369 | tuple.TupleOffset = 0; | 358 | tuple.TupleOffset = 0; |
370 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 359 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
371 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 360 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
372 | link->conf.ConfigBase = parse.config.base; | 361 | link->conf.ConfigBase = parse.config.base; |
373 | link->conf.Present = parse.config.rmask[0]; | 362 | link->conf.Present = parse.config.rmask[0]; |
374 | 363 | ||
375 | /* Configure card */ | ||
376 | link->state |= DEV_CONFIG; | ||
377 | |||
378 | link->io.IOAddrLines = 16; | 364 | link->io.IOAddrLines = 16; |
379 | for (i = j = 0; j < 0x400; j += 0x20) { | 365 | for (i = j = 0; j < 0x400; j += 0x20) { |
380 | link->io.BasePort1 = j ^ 0x300; | 366 | link->io.BasePort1 = j ^ 0x300; |
381 | i = pcmcia_request_io(link->handle, &link->io); | 367 | i = pcmcia_request_io(link, &link->io); |
382 | if (i == CS_SUCCESS) break; | 368 | if (i == CS_SUCCESS) break; |
383 | } | 369 | } |
384 | if (i != CS_SUCCESS) { | 370 | if (i != CS_SUCCESS) { |
385 | cs_error(link->handle, RequestIO, i); | 371 | cs_error(link, RequestIO, i); |
386 | goto failed; | 372 | goto failed; |
387 | } | 373 | } |
388 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 374 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
389 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 375 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
390 | 376 | ||
391 | dev->irq = link->irq.AssignedIRQ; | 377 | dev->irq = link->irq.AssignedIRQ; |
392 | dev->base_addr = link->io.BasePort1; | 378 | dev->base_addr = link->io.BasePort1; |
@@ -397,8 +383,8 @@ static void tc574_config(dev_link_t *link) | |||
397 | the hardware address. The future products may include a modem chip | 383 | the hardware address. The future products may include a modem chip |
398 | and put the address in the CIS. */ | 384 | and put the address in the CIS. */ |
399 | tuple.DesiredTuple = 0x88; | 385 | tuple.DesiredTuple = 0x88; |
400 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { | 386 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { |
401 | pcmcia_get_tuple_data(handle, &tuple); | 387 | pcmcia_get_tuple_data(link, &tuple); |
402 | for (i = 0; i < 3; i++) | 388 | for (i = 0; i < 3; i++) |
403 | phys_addr[i] = htons(buf[i]); | 389 | phys_addr[i] = htons(buf[i]); |
404 | } else { | 390 | } else { |
@@ -412,9 +398,9 @@ static void tc574_config(dev_link_t *link) | |||
412 | } | 398 | } |
413 | } | 399 | } |
414 | tuple.DesiredTuple = CISTPL_VERS_1; | 400 | tuple.DesiredTuple = CISTPL_VERS_1; |
415 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS && | 401 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS && |
416 | pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS && | 402 | pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS && |
417 | pcmcia_parse_tuple(handle, &tuple, &parse) == CS_SUCCESS) { | 403 | pcmcia_parse_tuple(link, &tuple, &parse) == CS_SUCCESS) { |
418 | cardname = parse.version_1.str + parse.version_1.ofs[1]; | 404 | cardname = parse.version_1.str + parse.version_1.ofs[1]; |
419 | } else | 405 | } else |
420 | cardname = "3Com 3c574"; | 406 | cardname = "3Com 3c574"; |
@@ -473,13 +459,12 @@ static void tc574_config(dev_link_t *link) | |||
473 | } | 459 | } |
474 | } | 460 | } |
475 | 461 | ||
476 | link->state &= ~DEV_CONFIG_PENDING; | 462 | link->dev_node = &lp->node; |
477 | link->dev = &lp->node; | 463 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
478 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
479 | 464 | ||
480 | if (register_netdev(dev) != 0) { | 465 | if (register_netdev(dev) != 0) { |
481 | printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n"); | 466 | printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n"); |
482 | link->dev = NULL; | 467 | link->dev_node = NULL; |
483 | goto failed; | 468 | goto failed; |
484 | } | 469 | } |
485 | 470 | ||
@@ -493,13 +478,13 @@ static void tc574_config(dev_link_t *link) | |||
493 | 8 << config.u.ram_size, ram_split[config.u.ram_split], | 478 | 8 << config.u.ram_size, ram_split[config.u.ram_split], |
494 | config.u.autoselect ? "autoselect " : ""); | 479 | config.u.autoselect ? "autoselect " : ""); |
495 | 480 | ||
496 | return; | 481 | return 0; |
497 | 482 | ||
498 | cs_failed: | 483 | cs_failed: |
499 | cs_error(link->handle, last_fn, last_ret); | 484 | cs_error(link, last_fn, last_ret); |
500 | failed: | 485 | failed: |
501 | tc574_release(link); | 486 | tc574_release(link); |
502 | return; | 487 | return -ENODEV; |
503 | 488 | ||
504 | } /* tc574_config */ | 489 | } /* tc574_config */ |
505 | 490 | ||
@@ -509,44 +494,28 @@ failed: | |||
509 | still open, this will be postponed until it is closed. | 494 | still open, this will be postponed until it is closed. |
510 | */ | 495 | */ |
511 | 496 | ||
512 | static void tc574_release(dev_link_t *link) | 497 | static void tc574_release(struct pcmcia_device *link) |
513 | { | 498 | { |
514 | DEBUG(0, "3c574_release(0x%p)\n", link); | 499 | pcmcia_disable_device(link); |
515 | |||
516 | pcmcia_release_configuration(link->handle); | ||
517 | pcmcia_release_io(link->handle, &link->io); | ||
518 | pcmcia_release_irq(link->handle, &link->irq); | ||
519 | |||
520 | link->state &= ~DEV_CONFIG; | ||
521 | } | 500 | } |
522 | 501 | ||
523 | static int tc574_suspend(struct pcmcia_device *p_dev) | 502 | static int tc574_suspend(struct pcmcia_device *link) |
524 | { | 503 | { |
525 | dev_link_t *link = dev_to_instance(p_dev); | ||
526 | struct net_device *dev = link->priv; | 504 | struct net_device *dev = link->priv; |
527 | 505 | ||
528 | link->state |= DEV_SUSPEND; | 506 | if (link->open) |
529 | if (link->state & DEV_CONFIG) { | 507 | netif_device_detach(dev); |
530 | if (link->open) | ||
531 | netif_device_detach(dev); | ||
532 | pcmcia_release_configuration(link->handle); | ||
533 | } | ||
534 | 508 | ||
535 | return 0; | 509 | return 0; |
536 | } | 510 | } |
537 | 511 | ||
538 | static int tc574_resume(struct pcmcia_device *p_dev) | 512 | static int tc574_resume(struct pcmcia_device *link) |
539 | { | 513 | { |
540 | dev_link_t *link = dev_to_instance(p_dev); | ||
541 | struct net_device *dev = link->priv; | 514 | struct net_device *dev = link->priv; |
542 | 515 | ||
543 | link->state &= ~DEV_SUSPEND; | 516 | if (link->open) { |
544 | if (link->state & DEV_CONFIG) { | 517 | tc574_reset(dev); |
545 | pcmcia_request_configuration(link->handle, &link->conf); | 518 | netif_device_attach(dev); |
546 | if (link->open) { | ||
547 | tc574_reset(dev); | ||
548 | netif_device_attach(dev); | ||
549 | } | ||
550 | } | 519 | } |
551 | 520 | ||
552 | return 0; | 521 | return 0; |
@@ -757,9 +726,9 @@ static void tc574_reset(struct net_device *dev) | |||
757 | static int el3_open(struct net_device *dev) | 726 | static int el3_open(struct net_device *dev) |
758 | { | 727 | { |
759 | struct el3_private *lp = netdev_priv(dev); | 728 | struct el3_private *lp = netdev_priv(dev); |
760 | dev_link_t *link = &lp->link; | 729 | struct pcmcia_device *link = lp->p_dev; |
761 | 730 | ||
762 | if (!DEV_OK(link)) | 731 | if (!pcmcia_dev_present(link)) |
763 | return -ENODEV; | 732 | return -ENODEV; |
764 | 733 | ||
765 | link->open++; | 734 | link->open++; |
@@ -1203,11 +1172,11 @@ static int el3_close(struct net_device *dev) | |||
1203 | { | 1172 | { |
1204 | kio_addr_t ioaddr = dev->base_addr; | 1173 | kio_addr_t ioaddr = dev->base_addr; |
1205 | struct el3_private *lp = netdev_priv(dev); | 1174 | struct el3_private *lp = netdev_priv(dev); |
1206 | dev_link_t *link = &lp->link; | 1175 | struct pcmcia_device *link = lp->p_dev; |
1207 | 1176 | ||
1208 | DEBUG(2, "%s: shutting down ethercard.\n", dev->name); | 1177 | DEBUG(2, "%s: shutting down ethercard.\n", dev->name); |
1209 | 1178 | ||
1210 | if (DEV_OK(link)) { | 1179 | if (pcmcia_dev_present(link)) { |
1211 | unsigned long flags; | 1180 | unsigned long flags; |
1212 | 1181 | ||
1213 | /* Turn off statistics ASAP. We update lp->stats below. */ | 1182 | /* Turn off statistics ASAP. We update lp->stats below. */ |
@@ -1246,7 +1215,7 @@ static struct pcmcia_driver tc574_driver = { | |||
1246 | .drv = { | 1215 | .drv = { |
1247 | .name = "3c574_cs", | 1216 | .name = "3c574_cs", |
1248 | }, | 1217 | }, |
1249 | .probe = tc574_attach, | 1218 | .probe = tc574_probe, |
1250 | .remove = tc574_detach, | 1219 | .remove = tc574_detach, |
1251 | .id_table = tc574_ids, | 1220 | .id_table = tc574_ids, |
1252 | .suspend = tc574_suspend, | 1221 | .suspend = tc574_suspend, |
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 3dba50849da7..875a0fe251e7 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c | |||
@@ -105,7 +105,7 @@ enum RxFilter { | |||
105 | #define TX_TIMEOUT ((400*HZ)/1000) | 105 | #define TX_TIMEOUT ((400*HZ)/1000) |
106 | 106 | ||
107 | struct el3_private { | 107 | struct el3_private { |
108 | dev_link_t link; | 108 | struct pcmcia_device *p_dev; |
109 | dev_node_t node; | 109 | dev_node_t node; |
110 | struct net_device_stats stats; | 110 | struct net_device_stats stats; |
111 | /* For transceiver monitoring */ | 111 | /* For transceiver monitoring */ |
@@ -142,8 +142,8 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; | |||
142 | 142 | ||
143 | /*====================================================================*/ | 143 | /*====================================================================*/ |
144 | 144 | ||
145 | static void tc589_config(dev_link_t *link); | 145 | static int tc589_config(struct pcmcia_device *link); |
146 | static void tc589_release(dev_link_t *link); | 146 | static void tc589_release(struct pcmcia_device *link); |
147 | 147 | ||
148 | static u16 read_eeprom(kio_addr_t ioaddr, int index); | 148 | static u16 read_eeprom(kio_addr_t ioaddr, int index); |
149 | static void tc589_reset(struct net_device *dev); | 149 | static void tc589_reset(struct net_device *dev); |
@@ -170,10 +170,9 @@ static void tc589_detach(struct pcmcia_device *p_dev); | |||
170 | 170 | ||
171 | ======================================================================*/ | 171 | ======================================================================*/ |
172 | 172 | ||
173 | static int tc589_attach(struct pcmcia_device *p_dev) | 173 | static int tc589_probe(struct pcmcia_device *link) |
174 | { | 174 | { |
175 | struct el3_private *lp; | 175 | struct el3_private *lp; |
176 | dev_link_t *link; | ||
177 | struct net_device *dev; | 176 | struct net_device *dev; |
178 | 177 | ||
179 | DEBUG(0, "3c589_attach()\n"); | 178 | DEBUG(0, "3c589_attach()\n"); |
@@ -183,8 +182,8 @@ static int tc589_attach(struct pcmcia_device *p_dev) | |||
183 | if (!dev) | 182 | if (!dev) |
184 | return -ENOMEM; | 183 | return -ENOMEM; |
185 | lp = netdev_priv(dev); | 184 | lp = netdev_priv(dev); |
186 | link = &lp->link; | ||
187 | link->priv = dev; | 185 | link->priv = dev; |
186 | lp->p_dev = link; | ||
188 | 187 | ||
189 | spin_lock_init(&lp->lock); | 188 | spin_lock_init(&lp->lock); |
190 | link->io.NumPorts1 = 16; | 189 | link->io.NumPorts1 = 16; |
@@ -194,7 +193,6 @@ static int tc589_attach(struct pcmcia_device *p_dev) | |||
194 | link->irq.Handler = &el3_interrupt; | 193 | link->irq.Handler = &el3_interrupt; |
195 | link->irq.Instance = dev; | 194 | link->irq.Instance = dev; |
196 | link->conf.Attributes = CONF_ENABLE_IRQ; | 195 | link->conf.Attributes = CONF_ENABLE_IRQ; |
197 | link->conf.Vcc = 50; | ||
198 | link->conf.IntType = INT_MEMORY_AND_IO; | 196 | link->conf.IntType = INT_MEMORY_AND_IO; |
199 | link->conf.ConfigIndex = 1; | 197 | link->conf.ConfigIndex = 1; |
200 | link->conf.Present = PRESENT_OPTION; | 198 | link->conf.Present = PRESENT_OPTION; |
@@ -213,13 +211,7 @@ static int tc589_attach(struct pcmcia_device *p_dev) | |||
213 | #endif | 211 | #endif |
214 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 212 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
215 | 213 | ||
216 | link->handle = p_dev; | 214 | return tc589_config(link); |
217 | p_dev->instance = link; | ||
218 | |||
219 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
220 | tc589_config(link); | ||
221 | |||
222 | return 0; | ||
223 | } /* tc589_attach */ | 215 | } /* tc589_attach */ |
224 | 216 | ||
225 | /*====================================================================== | 217 | /*====================================================================== |
@@ -231,18 +223,16 @@ static int tc589_attach(struct pcmcia_device *p_dev) | |||
231 | 223 | ||
232 | ======================================================================*/ | 224 | ======================================================================*/ |
233 | 225 | ||
234 | static void tc589_detach(struct pcmcia_device *p_dev) | 226 | static void tc589_detach(struct pcmcia_device *link) |
235 | { | 227 | { |
236 | dev_link_t *link = dev_to_instance(p_dev); | ||
237 | struct net_device *dev = link->priv; | 228 | struct net_device *dev = link->priv; |
238 | 229 | ||
239 | DEBUG(0, "3c589_detach(0x%p)\n", link); | 230 | DEBUG(0, "3c589_detach(0x%p)\n", link); |
240 | 231 | ||
241 | if (link->dev) | 232 | if (link->dev_node) |
242 | unregister_netdev(dev); | 233 | unregister_netdev(dev); |
243 | 234 | ||
244 | if (link->state & DEV_CONFIG) | 235 | tc589_release(link); |
245 | tc589_release(link); | ||
246 | 236 | ||
247 | free_netdev(dev); | 237 | free_netdev(dev); |
248 | } /* tc589_detach */ | 238 | } /* tc589_detach */ |
@@ -258,9 +248,8 @@ static void tc589_detach(struct pcmcia_device *p_dev) | |||
258 | #define CS_CHECK(fn, ret) \ | 248 | #define CS_CHECK(fn, ret) \ |
259 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 249 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
260 | 250 | ||
261 | static void tc589_config(dev_link_t *link) | 251 | static int tc589_config(struct pcmcia_device *link) |
262 | { | 252 | { |
263 | client_handle_t handle = link->handle; | ||
264 | struct net_device *dev = link->priv; | 253 | struct net_device *dev = link->priv; |
265 | struct el3_private *lp = netdev_priv(dev); | 254 | struct el3_private *lp = netdev_priv(dev); |
266 | tuple_t tuple; | 255 | tuple_t tuple; |
@@ -275,43 +264,40 @@ static void tc589_config(dev_link_t *link) | |||
275 | phys_addr = (u16 *)dev->dev_addr; | 264 | phys_addr = (u16 *)dev->dev_addr; |
276 | tuple.Attributes = 0; | 265 | tuple.Attributes = 0; |
277 | tuple.DesiredTuple = CISTPL_CONFIG; | 266 | tuple.DesiredTuple = CISTPL_CONFIG; |
278 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 267 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
279 | tuple.TupleData = (cisdata_t *)buf; | 268 | tuple.TupleData = (cisdata_t *)buf; |
280 | tuple.TupleDataMax = sizeof(buf); | 269 | tuple.TupleDataMax = sizeof(buf); |
281 | tuple.TupleOffset = 0; | 270 | tuple.TupleOffset = 0; |
282 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 271 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
283 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 272 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
284 | link->conf.ConfigBase = parse.config.base; | 273 | link->conf.ConfigBase = parse.config.base; |
285 | link->conf.Present = parse.config.rmask[0]; | 274 | link->conf.Present = parse.config.rmask[0]; |
286 | 275 | ||
287 | /* Is this a 3c562? */ | 276 | /* Is this a 3c562? */ |
288 | tuple.DesiredTuple = CISTPL_MANFID; | 277 | tuple.DesiredTuple = CISTPL_MANFID; |
289 | tuple.Attributes = TUPLE_RETURN_COMMON; | 278 | tuple.Attributes = TUPLE_RETURN_COMMON; |
290 | if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && | 279 | if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && |
291 | (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) { | 280 | (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) { |
292 | if (le16_to_cpu(buf[0]) != MANFID_3COM) | 281 | if (le16_to_cpu(buf[0]) != MANFID_3COM) |
293 | printk(KERN_INFO "3c589_cs: hmmm, is this really a " | 282 | printk(KERN_INFO "3c589_cs: hmmm, is this really a " |
294 | "3Com card??\n"); | 283 | "3Com card??\n"); |
295 | multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562); | 284 | multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562); |
296 | } | 285 | } |
297 | |||
298 | /* Configure card */ | ||
299 | link->state |= DEV_CONFIG; | ||
300 | 286 | ||
301 | /* For the 3c562, the base address must be xx00-xx7f */ | 287 | /* For the 3c562, the base address must be xx00-xx7f */ |
302 | link->io.IOAddrLines = 16; | 288 | link->io.IOAddrLines = 16; |
303 | for (i = j = 0; j < 0x400; j += 0x10) { | 289 | for (i = j = 0; j < 0x400; j += 0x10) { |
304 | if (multi && (j & 0x80)) continue; | 290 | if (multi && (j & 0x80)) continue; |
305 | link->io.BasePort1 = j ^ 0x300; | 291 | link->io.BasePort1 = j ^ 0x300; |
306 | i = pcmcia_request_io(link->handle, &link->io); | 292 | i = pcmcia_request_io(link, &link->io); |
307 | if (i == CS_SUCCESS) break; | 293 | if (i == CS_SUCCESS) break; |
308 | } | 294 | } |
309 | if (i != CS_SUCCESS) { | 295 | if (i != CS_SUCCESS) { |
310 | cs_error(link->handle, RequestIO, i); | 296 | cs_error(link, RequestIO, i); |
311 | goto failed; | 297 | goto failed; |
312 | } | 298 | } |
313 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 299 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
314 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 300 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
315 | 301 | ||
316 | dev->irq = link->irq.AssignedIRQ; | 302 | dev->irq = link->irq.AssignedIRQ; |
317 | dev->base_addr = link->io.BasePort1; | 303 | dev->base_addr = link->io.BasePort1; |
@@ -321,8 +307,8 @@ static void tc589_config(dev_link_t *link) | |||
321 | /* The 3c589 has an extra EEPROM for configuration info, including | 307 | /* The 3c589 has an extra EEPROM for configuration info, including |
322 | the hardware address. The 3c562 puts the address in the CIS. */ | 308 | the hardware address. The 3c562 puts the address in the CIS. */ |
323 | tuple.DesiredTuple = 0x88; | 309 | tuple.DesiredTuple = 0x88; |
324 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { | 310 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { |
325 | pcmcia_get_tuple_data(handle, &tuple); | 311 | pcmcia_get_tuple_data(link, &tuple); |
326 | for (i = 0; i < 3; i++) | 312 | for (i = 0; i < 3; i++) |
327 | phys_addr[i] = htons(buf[i]); | 313 | phys_addr[i] = htons(buf[i]); |
328 | } else { | 314 | } else { |
@@ -346,13 +332,12 @@ static void tc589_config(dev_link_t *link) | |||
346 | else | 332 | else |
347 | printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); | 333 | printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); |
348 | 334 | ||
349 | link->dev = &lp->node; | 335 | link->dev_node = &lp->node; |
350 | link->state &= ~DEV_CONFIG_PENDING; | 336 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
351 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
352 | 337 | ||
353 | if (register_netdev(dev) != 0) { | 338 | if (register_netdev(dev) != 0) { |
354 | printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); | 339 | printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); |
355 | link->dev = NULL; | 340 | link->dev_node = NULL; |
356 | goto failed; | 341 | goto failed; |
357 | } | 342 | } |
358 | 343 | ||
@@ -366,14 +351,13 @@ static void tc589_config(dev_link_t *link) | |||
366 | printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n", | 351 | printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n", |
367 | (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], | 352 | (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], |
368 | if_names[dev->if_port]); | 353 | if_names[dev->if_port]); |
369 | return; | 354 | return 0; |
370 | 355 | ||
371 | cs_failed: | 356 | cs_failed: |
372 | cs_error(link->handle, last_fn, last_ret); | 357 | cs_error(link, last_fn, last_ret); |
373 | failed: | 358 | failed: |
374 | tc589_release(link); | 359 | tc589_release(link); |
375 | return; | 360 | return -ENODEV; |
376 | |||
377 | } /* tc589_config */ | 361 | } /* tc589_config */ |
378 | 362 | ||
379 | /*====================================================================== | 363 | /*====================================================================== |
@@ -384,44 +368,28 @@ failed: | |||
384 | 368 | ||
385 | ======================================================================*/ | 369 | ======================================================================*/ |
386 | 370 | ||
387 | static void tc589_release(dev_link_t *link) | 371 | static void tc589_release(struct pcmcia_device *link) |
388 | { | 372 | { |
389 | DEBUG(0, "3c589_release(0x%p)\n", link); | 373 | pcmcia_disable_device(link); |
390 | |||
391 | pcmcia_release_configuration(link->handle); | ||
392 | pcmcia_release_io(link->handle, &link->io); | ||
393 | pcmcia_release_irq(link->handle, &link->irq); | ||
394 | |||
395 | link->state &= ~DEV_CONFIG; | ||
396 | } | 374 | } |
397 | 375 | ||
398 | static int tc589_suspend(struct pcmcia_device *p_dev) | 376 | static int tc589_suspend(struct pcmcia_device *link) |
399 | { | 377 | { |
400 | dev_link_t *link = dev_to_instance(p_dev); | ||
401 | struct net_device *dev = link->priv; | 378 | struct net_device *dev = link->priv; |
402 | 379 | ||
403 | link->state |= DEV_SUSPEND; | 380 | if (link->open) |
404 | if (link->state & DEV_CONFIG) { | 381 | netif_device_detach(dev); |
405 | if (link->open) | ||
406 | netif_device_detach(dev); | ||
407 | pcmcia_release_configuration(link->handle); | ||
408 | } | ||
409 | 382 | ||
410 | return 0; | 383 | return 0; |
411 | } | 384 | } |
412 | 385 | ||
413 | static int tc589_resume(struct pcmcia_device *p_dev) | 386 | static int tc589_resume(struct pcmcia_device *link) |
414 | { | 387 | { |
415 | dev_link_t *link = dev_to_instance(p_dev); | ||
416 | struct net_device *dev = link->priv; | 388 | struct net_device *dev = link->priv; |
417 | 389 | ||
418 | link->state &= ~DEV_SUSPEND; | 390 | if (link->open) { |
419 | if (link->state & DEV_CONFIG) { | 391 | tc589_reset(dev); |
420 | pcmcia_request_configuration(link->handle, &link->conf); | 392 | netif_device_attach(dev); |
421 | if (link->open) { | ||
422 | tc589_reset(dev); | ||
423 | netif_device_attach(dev); | ||
424 | } | ||
425 | } | 393 | } |
426 | 394 | ||
427 | return 0; | 395 | return 0; |
@@ -587,9 +555,9 @@ static int el3_config(struct net_device *dev, struct ifmap *map) | |||
587 | static int el3_open(struct net_device *dev) | 555 | static int el3_open(struct net_device *dev) |
588 | { | 556 | { |
589 | struct el3_private *lp = netdev_priv(dev); | 557 | struct el3_private *lp = netdev_priv(dev); |
590 | dev_link_t *link = &lp->link; | 558 | struct pcmcia_device *link = lp->p_dev; |
591 | 559 | ||
592 | if (!DEV_OK(link)) | 560 | if (!pcmcia_dev_present(link)) |
593 | return -ENODEV; | 561 | return -ENODEV; |
594 | 562 | ||
595 | link->open++; | 563 | link->open++; |
@@ -848,9 +816,9 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev) | |||
848 | { | 816 | { |
849 | struct el3_private *lp = netdev_priv(dev); | 817 | struct el3_private *lp = netdev_priv(dev); |
850 | unsigned long flags; | 818 | unsigned long flags; |
851 | dev_link_t *link = &lp->link; | 819 | struct pcmcia_device *link = lp->p_dev; |
852 | 820 | ||
853 | if (DEV_OK(link)) { | 821 | if (pcmcia_dev_present(link)) { |
854 | spin_lock_irqsave(&lp->lock, flags); | 822 | spin_lock_irqsave(&lp->lock, flags); |
855 | update_stats(dev); | 823 | update_stats(dev); |
856 | spin_unlock_irqrestore(&lp->lock, flags); | 824 | spin_unlock_irqrestore(&lp->lock, flags); |
@@ -950,11 +918,11 @@ static int el3_rx(struct net_device *dev) | |||
950 | static void set_multicast_list(struct net_device *dev) | 918 | static void set_multicast_list(struct net_device *dev) |
951 | { | 919 | { |
952 | struct el3_private *lp = netdev_priv(dev); | 920 | struct el3_private *lp = netdev_priv(dev); |
953 | dev_link_t *link = &lp->link; | 921 | struct pcmcia_device *link = lp->p_dev; |
954 | kio_addr_t ioaddr = dev->base_addr; | 922 | kio_addr_t ioaddr = dev->base_addr; |
955 | u16 opts = SetRxFilter | RxStation | RxBroadcast; | 923 | u16 opts = SetRxFilter | RxStation | RxBroadcast; |
956 | 924 | ||
957 | if (!(DEV_OK(link))) return; | 925 | if (!pcmcia_dev_present(link)) return; |
958 | if (dev->flags & IFF_PROMISC) | 926 | if (dev->flags & IFF_PROMISC) |
959 | opts |= RxMulticast | RxProm; | 927 | opts |= RxMulticast | RxProm; |
960 | else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) | 928 | else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) |
@@ -965,12 +933,12 @@ static void set_multicast_list(struct net_device *dev) | |||
965 | static int el3_close(struct net_device *dev) | 933 | static int el3_close(struct net_device *dev) |
966 | { | 934 | { |
967 | struct el3_private *lp = netdev_priv(dev); | 935 | struct el3_private *lp = netdev_priv(dev); |
968 | dev_link_t *link = &lp->link; | 936 | struct pcmcia_device *link = lp->p_dev; |
969 | kio_addr_t ioaddr = dev->base_addr; | 937 | kio_addr_t ioaddr = dev->base_addr; |
970 | 938 | ||
971 | DEBUG(1, "%s: shutting down ethercard.\n", dev->name); | 939 | DEBUG(1, "%s: shutting down ethercard.\n", dev->name); |
972 | 940 | ||
973 | if (DEV_OK(link)) { | 941 | if (pcmcia_dev_present(link)) { |
974 | /* Turn off statistics ASAP. We update lp->stats below. */ | 942 | /* Turn off statistics ASAP. We update lp->stats below. */ |
975 | outw(StatsDisable, ioaddr + EL3_CMD); | 943 | outw(StatsDisable, ioaddr + EL3_CMD); |
976 | 944 | ||
@@ -1020,7 +988,7 @@ static struct pcmcia_driver tc589_driver = { | |||
1020 | .drv = { | 988 | .drv = { |
1021 | .name = "3c589_cs", | 989 | .name = "3c589_cs", |
1022 | }, | 990 | }, |
1023 | .probe = tc589_attach, | 991 | .probe = tc589_probe, |
1024 | .remove = tc589_detach, | 992 | .remove = tc589_detach, |
1025 | .id_table = tc589_ids, | 993 | .id_table = tc589_ids, |
1026 | .suspend = tc589_suspend, | 994 | .suspend = tc589_suspend, |
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 1cc94b2d76c1..448a09488529 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c | |||
@@ -86,8 +86,8 @@ static char *version = | |||
86 | 86 | ||
87 | /*====================================================================*/ | 87 | /*====================================================================*/ |
88 | 88 | ||
89 | static void axnet_config(dev_link_t *link); | 89 | static int axnet_config(struct pcmcia_device *link); |
90 | static void axnet_release(dev_link_t *link); | 90 | static void axnet_release(struct pcmcia_device *link); |
91 | static int axnet_open(struct net_device *dev); | 91 | static int axnet_open(struct net_device *dev); |
92 | static int axnet_close(struct net_device *dev); | 92 | static int axnet_close(struct net_device *dev); |
93 | static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 93 | static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
@@ -117,7 +117,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs *regs); | |||
117 | /*====================================================================*/ | 117 | /*====================================================================*/ |
118 | 118 | ||
119 | typedef struct axnet_dev_t { | 119 | typedef struct axnet_dev_t { |
120 | dev_link_t link; | 120 | struct pcmcia_device *p_dev; |
121 | dev_node_t node; | 121 | dev_node_t node; |
122 | caddr_t base; | 122 | caddr_t base; |
123 | struct timer_list watchdog; | 123 | struct timer_list watchdog; |
@@ -142,10 +142,9 @@ static inline axnet_dev_t *PRIV(struct net_device *dev) | |||
142 | 142 | ||
143 | ======================================================================*/ | 143 | ======================================================================*/ |
144 | 144 | ||
145 | static int axnet_attach(struct pcmcia_device *p_dev) | 145 | static int axnet_probe(struct pcmcia_device *link) |
146 | { | 146 | { |
147 | axnet_dev_t *info; | 147 | axnet_dev_t *info; |
148 | dev_link_t *link; | ||
149 | struct net_device *dev; | 148 | struct net_device *dev; |
150 | 149 | ||
151 | DEBUG(0, "axnet_attach()\n"); | 150 | DEBUG(0, "axnet_attach()\n"); |
@@ -157,7 +156,7 @@ static int axnet_attach(struct pcmcia_device *p_dev) | |||
157 | return -ENOMEM; | 156 | return -ENOMEM; |
158 | 157 | ||
159 | info = PRIV(dev); | 158 | info = PRIV(dev); |
160 | link = &info->link; | 159 | info->p_dev = link; |
161 | link->priv = dev; | 160 | link->priv = dev; |
162 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 161 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
163 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 162 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
@@ -169,13 +168,7 @@ static int axnet_attach(struct pcmcia_device *p_dev) | |||
169 | dev->do_ioctl = &axnet_ioctl; | 168 | dev->do_ioctl = &axnet_ioctl; |
170 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 169 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
171 | 170 | ||
172 | link->handle = p_dev; | 171 | return axnet_config(link); |
173 | p_dev->instance = link; | ||
174 | |||
175 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
176 | axnet_config(link); | ||
177 | |||
178 | return 0; | ||
179 | } /* axnet_attach */ | 172 | } /* axnet_attach */ |
180 | 173 | ||
181 | /*====================================================================== | 174 | /*====================================================================== |
@@ -187,18 +180,16 @@ static int axnet_attach(struct pcmcia_device *p_dev) | |||
187 | 180 | ||
188 | ======================================================================*/ | 181 | ======================================================================*/ |
189 | 182 | ||
190 | static void axnet_detach(struct pcmcia_device *p_dev) | 183 | static void axnet_detach(struct pcmcia_device *link) |
191 | { | 184 | { |
192 | dev_link_t *link = dev_to_instance(p_dev); | ||
193 | struct net_device *dev = link->priv; | 185 | struct net_device *dev = link->priv; |
194 | 186 | ||
195 | DEBUG(0, "axnet_detach(0x%p)\n", link); | 187 | DEBUG(0, "axnet_detach(0x%p)\n", link); |
196 | 188 | ||
197 | if (link->dev) | 189 | if (link->dev_node) |
198 | unregister_netdev(dev); | 190 | unregister_netdev(dev); |
199 | 191 | ||
200 | if (link->state & DEV_CONFIG) | 192 | axnet_release(link); |
201 | axnet_release(link); | ||
202 | 193 | ||
203 | free_netdev(dev); | 194 | free_netdev(dev); |
204 | } /* axnet_detach */ | 195 | } /* axnet_detach */ |
@@ -209,7 +200,7 @@ static void axnet_detach(struct pcmcia_device *p_dev) | |||
209 | 200 | ||
210 | ======================================================================*/ | 201 | ======================================================================*/ |
211 | 202 | ||
212 | static int get_prom(dev_link_t *link) | 203 | static int get_prom(struct pcmcia_device *link) |
213 | { | 204 | { |
214 | struct net_device *dev = link->priv; | 205 | struct net_device *dev = link->priv; |
215 | kio_addr_t ioaddr = dev->base_addr; | 206 | kio_addr_t ioaddr = dev->base_addr; |
@@ -263,7 +254,7 @@ static int get_prom(dev_link_t *link) | |||
263 | #define CS_CHECK(fn, ret) \ | 254 | #define CS_CHECK(fn, ret) \ |
264 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 255 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
265 | 256 | ||
266 | static int try_io_port(dev_link_t *link) | 257 | static int try_io_port(struct pcmcia_device *link) |
267 | { | 258 | { |
268 | int j, ret; | 259 | int j, ret; |
269 | if (link->io.NumPorts1 == 32) { | 260 | if (link->io.NumPorts1 == 32) { |
@@ -284,25 +275,23 @@ static int try_io_port(dev_link_t *link) | |||
284 | for (j = 0; j < 0x400; j += 0x20) { | 275 | for (j = 0; j < 0x400; j += 0x20) { |
285 | link->io.BasePort1 = j ^ 0x300; | 276 | link->io.BasePort1 = j ^ 0x300; |
286 | link->io.BasePort2 = (j ^ 0x300) + 0x10; | 277 | link->io.BasePort2 = (j ^ 0x300) + 0x10; |
287 | ret = pcmcia_request_io(link->handle, &link->io); | 278 | ret = pcmcia_request_io(link, &link->io); |
288 | if (ret == CS_SUCCESS) return ret; | 279 | if (ret == CS_SUCCESS) return ret; |
289 | } | 280 | } |
290 | return ret; | 281 | return ret; |
291 | } else { | 282 | } else { |
292 | return pcmcia_request_io(link->handle, &link->io); | 283 | return pcmcia_request_io(link, &link->io); |
293 | } | 284 | } |
294 | } | 285 | } |
295 | 286 | ||
296 | static void axnet_config(dev_link_t *link) | 287 | static int axnet_config(struct pcmcia_device *link) |
297 | { | 288 | { |
298 | client_handle_t handle = link->handle; | ||
299 | struct net_device *dev = link->priv; | 289 | struct net_device *dev = link->priv; |
300 | axnet_dev_t *info = PRIV(dev); | 290 | axnet_dev_t *info = PRIV(dev); |
301 | tuple_t tuple; | 291 | tuple_t tuple; |
302 | cisparse_t parse; | 292 | cisparse_t parse; |
303 | int i, j, last_ret, last_fn; | 293 | int i, j, last_ret, last_fn; |
304 | u_short buf[64]; | 294 | u_short buf[64]; |
305 | config_info_t conf; | ||
306 | 295 | ||
307 | DEBUG(0, "axnet_config(0x%p)\n", link); | 296 | DEBUG(0, "axnet_config(0x%p)\n", link); |
308 | 297 | ||
@@ -311,29 +300,22 @@ static void axnet_config(dev_link_t *link) | |||
311 | tuple.TupleDataMax = sizeof(buf); | 300 | tuple.TupleDataMax = sizeof(buf); |
312 | tuple.TupleOffset = 0; | 301 | tuple.TupleOffset = 0; |
313 | tuple.DesiredTuple = CISTPL_CONFIG; | 302 | tuple.DesiredTuple = CISTPL_CONFIG; |
314 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 303 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
315 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 304 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
316 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 305 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
317 | link->conf.ConfigBase = parse.config.base; | 306 | link->conf.ConfigBase = parse.config.base; |
318 | /* don't trust the CIS on this; Linksys got it wrong */ | 307 | /* don't trust the CIS on this; Linksys got it wrong */ |
319 | link->conf.Present = 0x63; | 308 | link->conf.Present = 0x63; |
320 | 309 | ||
321 | /* Configure card */ | ||
322 | link->state |= DEV_CONFIG; | ||
323 | |||
324 | /* Look up current Vcc */ | ||
325 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); | ||
326 | link->conf.Vcc = conf.Vcc; | ||
327 | |||
328 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 310 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
329 | tuple.Attributes = 0; | 311 | tuple.Attributes = 0; |
330 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 312 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
331 | while (last_ret == CS_SUCCESS) { | 313 | while (last_ret == CS_SUCCESS) { |
332 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 314 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
333 | cistpl_io_t *io = &(parse.cftable_entry.io); | 315 | cistpl_io_t *io = &(parse.cftable_entry.io); |
334 | 316 | ||
335 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | 317 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || |
336 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0 || | 318 | pcmcia_parse_tuple(link, &tuple, &parse) != 0 || |
337 | cfg->index == 0 || cfg->io.nwin == 0) | 319 | cfg->index == 0 || cfg->io.nwin == 0) |
338 | goto next_entry; | 320 | goto next_entry; |
339 | 321 | ||
@@ -355,21 +337,21 @@ static void axnet_config(dev_link_t *link) | |||
355 | if (last_ret == CS_SUCCESS) break; | 337 | if (last_ret == CS_SUCCESS) break; |
356 | } | 338 | } |
357 | next_entry: | 339 | next_entry: |
358 | last_ret = pcmcia_get_next_tuple(handle, &tuple); | 340 | last_ret = pcmcia_get_next_tuple(link, &tuple); |
359 | } | 341 | } |
360 | if (last_ret != CS_SUCCESS) { | 342 | if (last_ret != CS_SUCCESS) { |
361 | cs_error(handle, RequestIO, last_ret); | 343 | cs_error(link, RequestIO, last_ret); |
362 | goto failed; | 344 | goto failed; |
363 | } | 345 | } |
364 | 346 | ||
365 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | 347 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
366 | 348 | ||
367 | if (link->io.NumPorts2 == 8) { | 349 | if (link->io.NumPorts2 == 8) { |
368 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 350 | link->conf.Attributes |= CONF_ENABLE_SPKR; |
369 | link->conf.Status = CCSR_AUDIO_ENA; | 351 | link->conf.Status = CCSR_AUDIO_ENA; |
370 | } | 352 | } |
371 | 353 | ||
372 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | 354 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
373 | dev->irq = link->irq.AssignedIRQ; | 355 | dev->irq = link->irq.AssignedIRQ; |
374 | dev->base_addr = link->io.BasePort1; | 356 | dev->base_addr = link->io.BasePort1; |
375 | 357 | ||
@@ -406,7 +388,7 @@ static void axnet_config(dev_link_t *link) | |||
406 | Bit 2 of CCSR is active low. */ | 388 | Bit 2 of CCSR is active low. */ |
407 | if (i == 32) { | 389 | if (i == 32) { |
408 | conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 }; | 390 | conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 }; |
409 | pcmcia_access_configuration_register(link->handle, ®); | 391 | pcmcia_access_configuration_register(link, ®); |
410 | for (i = 0; i < 32; i++) { | 392 | for (i = 0; i < 32; i++) { |
411 | j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); | 393 | j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); |
412 | if ((j != 0) && (j != 0xffff)) break; | 394 | if ((j != 0) && (j != 0xffff)) break; |
@@ -414,13 +396,12 @@ static void axnet_config(dev_link_t *link) | |||
414 | } | 396 | } |
415 | 397 | ||
416 | info->phy_id = (i < 32) ? i : -1; | 398 | info->phy_id = (i < 32) ? i : -1; |
417 | link->dev = &info->node; | 399 | link->dev_node = &info->node; |
418 | link->state &= ~DEV_CONFIG_PENDING; | 400 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
419 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
420 | 401 | ||
421 | if (register_netdev(dev) != 0) { | 402 | if (register_netdev(dev) != 0) { |
422 | printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n"); | 403 | printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n"); |
423 | link->dev = NULL; | 404 | link->dev_node = NULL; |
424 | goto failed; | 405 | goto failed; |
425 | } | 406 | } |
426 | 407 | ||
@@ -436,14 +417,13 @@ static void axnet_config(dev_link_t *link) | |||
436 | } else { | 417 | } else { |
437 | printk(KERN_NOTICE " No MII transceivers found!\n"); | 418 | printk(KERN_NOTICE " No MII transceivers found!\n"); |
438 | } | 419 | } |
439 | return; | 420 | return 0; |
440 | 421 | ||
441 | cs_failed: | 422 | cs_failed: |
442 | cs_error(link->handle, last_fn, last_ret); | 423 | cs_error(link, last_fn, last_ret); |
443 | failed: | 424 | failed: |
444 | axnet_release(link); | 425 | axnet_release(link); |
445 | link->state &= ~DEV_CONFIG_PENDING; | 426 | return -ENODEV; |
446 | return; | ||
447 | } /* axnet_config */ | 427 | } /* axnet_config */ |
448 | 428 | ||
449 | /*====================================================================== | 429 | /*====================================================================== |
@@ -454,45 +434,29 @@ failed: | |||
454 | 434 | ||
455 | ======================================================================*/ | 435 | ======================================================================*/ |
456 | 436 | ||
457 | static void axnet_release(dev_link_t *link) | 437 | static void axnet_release(struct pcmcia_device *link) |
458 | { | 438 | { |
459 | DEBUG(0, "axnet_release(0x%p)\n", link); | 439 | pcmcia_disable_device(link); |
460 | |||
461 | pcmcia_release_configuration(link->handle); | ||
462 | pcmcia_release_io(link->handle, &link->io); | ||
463 | pcmcia_release_irq(link->handle, &link->irq); | ||
464 | |||
465 | link->state &= ~DEV_CONFIG; | ||
466 | } | 440 | } |
467 | 441 | ||
468 | static int axnet_suspend(struct pcmcia_device *p_dev) | 442 | static int axnet_suspend(struct pcmcia_device *link) |
469 | { | 443 | { |
470 | dev_link_t *link = dev_to_instance(p_dev); | ||
471 | struct net_device *dev = link->priv; | 444 | struct net_device *dev = link->priv; |
472 | 445 | ||
473 | link->state |= DEV_SUSPEND; | 446 | if (link->open) |
474 | if (link->state & DEV_CONFIG) { | 447 | netif_device_detach(dev); |
475 | if (link->open) | ||
476 | netif_device_detach(dev); | ||
477 | pcmcia_release_configuration(link->handle); | ||
478 | } | ||
479 | 448 | ||
480 | return 0; | 449 | return 0; |
481 | } | 450 | } |
482 | 451 | ||
483 | static int axnet_resume(struct pcmcia_device *p_dev) | 452 | static int axnet_resume(struct pcmcia_device *link) |
484 | { | 453 | { |
485 | dev_link_t *link = dev_to_instance(p_dev); | ||
486 | struct net_device *dev = link->priv; | 454 | struct net_device *dev = link->priv; |
487 | 455 | ||
488 | link->state &= ~DEV_SUSPEND; | 456 | if (link->open) { |
489 | if (link->state & DEV_CONFIG) { | 457 | axnet_reset_8390(dev); |
490 | pcmcia_request_configuration(link->handle, &link->conf); | 458 | AX88190_init(dev, 1); |
491 | if (link->open) { | 459 | netif_device_attach(dev); |
492 | axnet_reset_8390(dev); | ||
493 | AX88190_init(dev, 1); | ||
494 | netif_device_attach(dev); | ||
495 | } | ||
496 | } | 460 | } |
497 | 461 | ||
498 | return 0; | 462 | return 0; |
@@ -562,11 +526,11 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value) | |||
562 | static int axnet_open(struct net_device *dev) | 526 | static int axnet_open(struct net_device *dev) |
563 | { | 527 | { |
564 | axnet_dev_t *info = PRIV(dev); | 528 | axnet_dev_t *info = PRIV(dev); |
565 | dev_link_t *link = &info->link; | 529 | struct pcmcia_device *link = info->p_dev; |
566 | 530 | ||
567 | DEBUG(2, "axnet_open('%s')\n", dev->name); | 531 | DEBUG(2, "axnet_open('%s')\n", dev->name); |
568 | 532 | ||
569 | if (!DEV_OK(link)) | 533 | if (!pcmcia_dev_present(link)) |
570 | return -ENODEV; | 534 | return -ENODEV; |
571 | 535 | ||
572 | link->open++; | 536 | link->open++; |
@@ -588,7 +552,7 @@ static int axnet_open(struct net_device *dev) | |||
588 | static int axnet_close(struct net_device *dev) | 552 | static int axnet_close(struct net_device *dev) |
589 | { | 553 | { |
590 | axnet_dev_t *info = PRIV(dev); | 554 | axnet_dev_t *info = PRIV(dev); |
591 | dev_link_t *link = &info->link; | 555 | struct pcmcia_device *link = info->p_dev; |
592 | 556 | ||
593 | DEBUG(2, "axnet_close('%s')\n", dev->name); | 557 | DEBUG(2, "axnet_close('%s')\n", dev->name); |
594 | 558 | ||
@@ -833,7 +797,7 @@ static struct pcmcia_driver axnet_cs_driver = { | |||
833 | .drv = { | 797 | .drv = { |
834 | .name = "axnet_cs", | 798 | .name = "axnet_cs", |
835 | }, | 799 | }, |
836 | .probe = axnet_attach, | 800 | .probe = axnet_probe, |
837 | .remove = axnet_detach, | 801 | .remove = axnet_detach, |
838 | .id_table = axnet_ids, | 802 | .id_table = axnet_ids, |
839 | .suspend = axnet_suspend, | 803 | .suspend = axnet_suspend, |
@@ -1596,7 +1560,7 @@ static void ei_receive(struct net_device *dev) | |||
1596 | 1560 | ||
1597 | static void ei_rx_overrun(struct net_device *dev) | 1561 | static void ei_rx_overrun(struct net_device *dev) |
1598 | { | 1562 | { |
1599 | axnet_dev_t *info = (axnet_dev_t *)dev; | 1563 | axnet_dev_t *info = PRIV(dev); |
1600 | long e8390_base = dev->base_addr; | 1564 | long e8390_base = dev->base_addr; |
1601 | unsigned char was_txing, must_resend = 0; | 1565 | unsigned char was_txing, must_resend = 0; |
1602 | struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); | 1566 | struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); |
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 2827a48ea37c..441de824ab6b 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c | |||
@@ -118,8 +118,8 @@ MODULE_LICENSE("GPL"); | |||
118 | 118 | ||
119 | /*====================================================================*/ | 119 | /*====================================================================*/ |
120 | 120 | ||
121 | static void com20020_config(dev_link_t *link); | 121 | static int com20020_config(struct pcmcia_device *link); |
122 | static void com20020_release(dev_link_t *link); | 122 | static void com20020_release(struct pcmcia_device *link); |
123 | 123 | ||
124 | static void com20020_detach(struct pcmcia_device *p_dev); | 124 | static void com20020_detach(struct pcmcia_device *p_dev); |
125 | 125 | ||
@@ -138,9 +138,8 @@ typedef struct com20020_dev_t { | |||
138 | 138 | ||
139 | ======================================================================*/ | 139 | ======================================================================*/ |
140 | 140 | ||
141 | static int com20020_attach(struct pcmcia_device *p_dev) | 141 | static int com20020_probe(struct pcmcia_device *p_dev) |
142 | { | 142 | { |
143 | dev_link_t *link; | ||
144 | com20020_dev_t *info; | 143 | com20020_dev_t *info; |
145 | struct net_device *dev; | 144 | struct net_device *dev; |
146 | struct arcnet_local *lp; | 145 | struct arcnet_local *lp; |
@@ -148,10 +147,6 @@ static int com20020_attach(struct pcmcia_device *p_dev) | |||
148 | DEBUG(0, "com20020_attach()\n"); | 147 | DEBUG(0, "com20020_attach()\n"); |
149 | 148 | ||
150 | /* Create new network device */ | 149 | /* Create new network device */ |
151 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); | ||
152 | if (!link) | ||
153 | return -ENOMEM; | ||
154 | |||
155 | info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); | 150 | info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); |
156 | if (!info) | 151 | if (!info) |
157 | goto fail_alloc_info; | 152 | goto fail_alloc_info; |
@@ -161,7 +156,6 @@ static int com20020_attach(struct pcmcia_device *p_dev) | |||
161 | goto fail_alloc_dev; | 156 | goto fail_alloc_dev; |
162 | 157 | ||
163 | memset(info, 0, sizeof(struct com20020_dev_t)); | 158 | memset(info, 0, sizeof(struct com20020_dev_t)); |
164 | memset(link, 0, sizeof(struct dev_link_t)); | ||
165 | lp = dev->priv; | 159 | lp = dev->priv; |
166 | lp->timeout = timeout; | 160 | lp->timeout = timeout; |
167 | lp->backplane = backplane; | 161 | lp->backplane = backplane; |
@@ -172,28 +166,23 @@ static int com20020_attach(struct pcmcia_device *p_dev) | |||
172 | /* fill in our module parameters as defaults */ | 166 | /* fill in our module parameters as defaults */ |
173 | dev->dev_addr[0] = node; | 167 | dev->dev_addr[0] = node; |
174 | 168 | ||
175 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 169 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
176 | link->io.NumPorts1 = 16; | 170 | p_dev->io.NumPorts1 = 16; |
177 | link->io.IOAddrLines = 16; | 171 | p_dev->io.IOAddrLines = 16; |
178 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 172 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
179 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 173 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
180 | link->conf.Attributes = CONF_ENABLE_IRQ; | 174 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; |
181 | link->conf.Vcc = 50; | 175 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
182 | link->conf.IntType = INT_MEMORY_AND_IO; | 176 | p_dev->conf.Present = PRESENT_OPTION; |
183 | link->conf.Present = PRESENT_OPTION; | ||
184 | |||
185 | link->irq.Instance = info->dev = dev; | ||
186 | link->priv = info; | ||
187 | 177 | ||
188 | link->state |= DEV_PRESENT; | 178 | p_dev->irq.Instance = info->dev = dev; |
189 | com20020_config(link); | 179 | p_dev->priv = info; |
190 | 180 | ||
191 | return 0; | 181 | return com20020_config(p_dev); |
192 | 182 | ||
193 | fail_alloc_dev: | 183 | fail_alloc_dev: |
194 | kfree(info); | 184 | kfree(info); |
195 | fail_alloc_info: | 185 | fail_alloc_info: |
196 | kfree(link); | ||
197 | return -ENOMEM; | 186 | return -ENOMEM; |
198 | } /* com20020_attach */ | 187 | } /* com20020_attach */ |
199 | 188 | ||
@@ -206,9 +195,8 @@ fail_alloc_info: | |||
206 | 195 | ||
207 | ======================================================================*/ | 196 | ======================================================================*/ |
208 | 197 | ||
209 | static void com20020_detach(struct pcmcia_device *p_dev) | 198 | static void com20020_detach(struct pcmcia_device *link) |
210 | { | 199 | { |
211 | dev_link_t *link = dev_to_instance(p_dev); | ||
212 | struct com20020_dev_t *info = link->priv; | 200 | struct com20020_dev_t *info = link->priv; |
213 | struct net_device *dev = info->dev; | 201 | struct net_device *dev = info->dev; |
214 | 202 | ||
@@ -216,7 +204,7 @@ static void com20020_detach(struct pcmcia_device *p_dev) | |||
216 | 204 | ||
217 | DEBUG(0, "com20020_detach(0x%p)\n", link); | 205 | DEBUG(0, "com20020_detach(0x%p)\n", link); |
218 | 206 | ||
219 | if (link->dev) { | 207 | if (link->dev_node) { |
220 | DEBUG(1,"unregister...\n"); | 208 | DEBUG(1,"unregister...\n"); |
221 | 209 | ||
222 | unregister_netdev(dev); | 210 | unregister_netdev(dev); |
@@ -229,8 +217,7 @@ static void com20020_detach(struct pcmcia_device *p_dev) | |||
229 | free_irq(dev->irq, dev); | 217 | free_irq(dev->irq, dev); |
230 | } | 218 | } |
231 | 219 | ||
232 | if (link->state & DEV_CONFIG) | 220 | com20020_release(link); |
233 | com20020_release(link); | ||
234 | 221 | ||
235 | /* Unlink device structure, free bits */ | 222 | /* Unlink device structure, free bits */ |
236 | DEBUG(1,"unlinking...\n"); | 223 | DEBUG(1,"unlinking...\n"); |
@@ -245,8 +232,6 @@ static void com20020_detach(struct pcmcia_device *p_dev) | |||
245 | DEBUG(1,"kfree2...\n"); | 232 | DEBUG(1,"kfree2...\n"); |
246 | kfree(info); | 233 | kfree(info); |
247 | } | 234 | } |
248 | DEBUG(1,"kfree3...\n"); | ||
249 | kfree(link); | ||
250 | 235 | ||
251 | } /* com20020_detach */ | 236 | } /* com20020_detach */ |
252 | 237 | ||
@@ -261,10 +246,9 @@ static void com20020_detach(struct pcmcia_device *p_dev) | |||
261 | #define CS_CHECK(fn, ret) \ | 246 | #define CS_CHECK(fn, ret) \ |
262 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 247 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
263 | 248 | ||
264 | static void com20020_config(dev_link_t *link) | 249 | static int com20020_config(struct pcmcia_device *link) |
265 | { | 250 | { |
266 | struct arcnet_local *lp; | 251 | struct arcnet_local *lp; |
267 | client_handle_t handle; | ||
268 | tuple_t tuple; | 252 | tuple_t tuple; |
269 | cisparse_t parse; | 253 | cisparse_t parse; |
270 | com20020_dev_t *info; | 254 | com20020_dev_t *info; |
@@ -273,7 +257,6 @@ static void com20020_config(dev_link_t *link) | |||
273 | u_char buf[64]; | 257 | u_char buf[64]; |
274 | int ioaddr; | 258 | int ioaddr; |
275 | 259 | ||
276 | handle = link->handle; | ||
277 | info = link->priv; | 260 | info = link->priv; |
278 | dev = info->dev; | 261 | dev = info->dev; |
279 | 262 | ||
@@ -286,14 +269,11 @@ static void com20020_config(dev_link_t *link) | |||
286 | tuple.TupleDataMax = 64; | 269 | tuple.TupleDataMax = 64; |
287 | tuple.TupleOffset = 0; | 270 | tuple.TupleOffset = 0; |
288 | tuple.DesiredTuple = CISTPL_CONFIG; | 271 | tuple.DesiredTuple = CISTPL_CONFIG; |
289 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 272 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
290 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 273 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
291 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 274 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
292 | link->conf.ConfigBase = parse.config.base; | 275 | link->conf.ConfigBase = parse.config.base; |
293 | 276 | ||
294 | /* Configure card */ | ||
295 | link->state |= DEV_CONFIG; | ||
296 | |||
297 | DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1); | 277 | DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1); |
298 | i = !CS_SUCCESS; | 278 | i = !CS_SUCCESS; |
299 | if (!link->io.BasePort1) | 279 | if (!link->io.BasePort1) |
@@ -301,13 +281,13 @@ static void com20020_config(dev_link_t *link) | |||
301 | for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) | 281 | for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) |
302 | { | 282 | { |
303 | link->io.BasePort1 = ioaddr; | 283 | link->io.BasePort1 = ioaddr; |
304 | i = pcmcia_request_io(link->handle, &link->io); | 284 | i = pcmcia_request_io(link, &link->io); |
305 | if (i == CS_SUCCESS) | 285 | if (i == CS_SUCCESS) |
306 | break; | 286 | break; |
307 | } | 287 | } |
308 | } | 288 | } |
309 | else | 289 | else |
310 | i = pcmcia_request_io(link->handle, &link->io); | 290 | i = pcmcia_request_io(link, &link->io); |
311 | 291 | ||
312 | if (i != CS_SUCCESS) | 292 | if (i != CS_SUCCESS) |
313 | { | 293 | { |
@@ -321,7 +301,7 @@ static void com20020_config(dev_link_t *link) | |||
321 | DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n", | 301 | DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n", |
322 | link->irq.AssignedIRQ, | 302 | link->irq.AssignedIRQ, |
323 | link->irq.IRQInfo1, link->irq.IRQInfo2); | 303 | link->irq.IRQInfo1, link->irq.IRQInfo2); |
324 | i = pcmcia_request_irq(link->handle, &link->irq); | 304 | i = pcmcia_request_irq(link, &link->irq); |
325 | if (i != CS_SUCCESS) | 305 | if (i != CS_SUCCESS) |
326 | { | 306 | { |
327 | DEBUG(1,"arcnet: requestIRQ failed totally!\n"); | 307 | DEBUG(1,"arcnet: requestIRQ failed totally!\n"); |
@@ -330,7 +310,7 @@ static void com20020_config(dev_link_t *link) | |||
330 | 310 | ||
331 | dev->irq = link->irq.AssignedIRQ; | 311 | dev->irq = link->irq.AssignedIRQ; |
332 | 312 | ||
333 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 313 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
334 | 314 | ||
335 | if (com20020_check(dev)) | 315 | if (com20020_check(dev)) |
336 | { | 316 | { |
@@ -342,15 +322,14 @@ static void com20020_config(dev_link_t *link) | |||
342 | lp->card_name = "PCMCIA COM20020"; | 322 | lp->card_name = "PCMCIA COM20020"; |
343 | lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ | 323 | lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ |
344 | 324 | ||
345 | link->dev = &info->node; | 325 | link->dev_node = &info->node; |
346 | link->state &= ~DEV_CONFIG_PENDING; | 326 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
347 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
348 | 327 | ||
349 | i = com20020_found(dev, 0); /* calls register_netdev */ | 328 | i = com20020_found(dev, 0); /* calls register_netdev */ |
350 | 329 | ||
351 | if (i != 0) { | 330 | if (i != 0) { |
352 | DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n"); | 331 | DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n"); |
353 | link->dev = NULL; | 332 | link->dev_node = NULL; |
354 | goto failed; | 333 | goto failed; |
355 | } | 334 | } |
356 | 335 | ||
@@ -358,13 +337,14 @@ static void com20020_config(dev_link_t *link) | |||
358 | 337 | ||
359 | DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n", | 338 | DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n", |
360 | dev->name, dev->base_addr, dev->irq); | 339 | dev->name, dev->base_addr, dev->irq); |
361 | return; | 340 | return 0; |
362 | 341 | ||
363 | cs_failed: | 342 | cs_failed: |
364 | cs_error(link->handle, last_fn, last_ret); | 343 | cs_error(link, last_fn, last_ret); |
365 | failed: | 344 | failed: |
366 | DEBUG(1,"com20020_config failed...\n"); | 345 | DEBUG(1,"com20020_config failed...\n"); |
367 | com20020_release(link); | 346 | com20020_release(link); |
347 | return -ENODEV; | ||
368 | } /* com20020_config */ | 348 | } /* com20020_config */ |
369 | 349 | ||
370 | /*====================================================================== | 350 | /*====================================================================== |
@@ -375,52 +355,33 @@ failed: | |||
375 | 355 | ||
376 | ======================================================================*/ | 356 | ======================================================================*/ |
377 | 357 | ||
378 | static void com20020_release(dev_link_t *link) | 358 | static void com20020_release(struct pcmcia_device *link) |
379 | { | 359 | { |
380 | 360 | DEBUG(0, "com20020_release(0x%p)\n", link); | |
381 | DEBUG(1,"release...\n"); | 361 | pcmcia_disable_device(link); |
382 | |||
383 | DEBUG(0, "com20020_release(0x%p)\n", link); | ||
384 | |||
385 | pcmcia_release_configuration(link->handle); | ||
386 | pcmcia_release_io(link->handle, &link->io); | ||
387 | pcmcia_release_irq(link->handle, &link->irq); | ||
388 | |||
389 | link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); | ||
390 | } | 362 | } |
391 | 363 | ||
392 | static int com20020_suspend(struct pcmcia_device *p_dev) | 364 | static int com20020_suspend(struct pcmcia_device *link) |
393 | { | 365 | { |
394 | dev_link_t *link = dev_to_instance(p_dev); | ||
395 | com20020_dev_t *info = link->priv; | 366 | com20020_dev_t *info = link->priv; |
396 | struct net_device *dev = info->dev; | 367 | struct net_device *dev = info->dev; |
397 | 368 | ||
398 | link->state |= DEV_SUSPEND; | 369 | if (link->open) |
399 | if (link->state & DEV_CONFIG) { | 370 | netif_device_detach(dev); |
400 | if (link->open) { | ||
401 | netif_device_detach(dev); | ||
402 | } | ||
403 | pcmcia_release_configuration(link->handle); | ||
404 | } | ||
405 | 371 | ||
406 | return 0; | 372 | return 0; |
407 | } | 373 | } |
408 | 374 | ||
409 | static int com20020_resume(struct pcmcia_device *p_dev) | 375 | static int com20020_resume(struct pcmcia_device *link) |
410 | { | 376 | { |
411 | dev_link_t *link = dev_to_instance(p_dev); | ||
412 | com20020_dev_t *info = link->priv; | 377 | com20020_dev_t *info = link->priv; |
413 | struct net_device *dev = info->dev; | 378 | struct net_device *dev = info->dev; |
414 | 379 | ||
415 | link->state &= ~DEV_SUSPEND; | 380 | if (link->open) { |
416 | if (link->state & DEV_CONFIG) { | 381 | int ioaddr = dev->base_addr; |
417 | pcmcia_request_configuration(link->handle, &link->conf); | 382 | struct arcnet_local *lp = dev->priv; |
418 | if (link->open) { | 383 | ARCRESET; |
419 | int ioaddr = dev->base_addr; | 384 | } |
420 | struct arcnet_local *lp = dev->priv; | ||
421 | ARCRESET; | ||
422 | } | ||
423 | } | ||
424 | 385 | ||
425 | return 0; | 386 | return 0; |
426 | } | 387 | } |
@@ -436,7 +397,7 @@ static struct pcmcia_driver com20020_cs_driver = { | |||
436 | .drv = { | 397 | .drv = { |
437 | .name = "com20020_cs", | 398 | .name = "com20020_cs", |
438 | }, | 399 | }, |
439 | .probe = com20020_attach, | 400 | .probe = com20020_probe, |
440 | .remove = com20020_detach, | 401 | .remove = com20020_detach, |
441 | .id_table = com20020_ids, | 402 | .id_table = com20020_ids, |
442 | .suspend = com20020_suspend, | 403 | .suspend = com20020_suspend, |
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index b7ac14ba8877..09b11761cdfa 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c | |||
@@ -84,10 +84,10 @@ static char *version = DRV_NAME ".c " DRV_VERSION " 2002/03/23"; | |||
84 | /* | 84 | /* |
85 | PCMCIA event handlers | 85 | PCMCIA event handlers |
86 | */ | 86 | */ |
87 | static void fmvj18x_config(dev_link_t *link); | 87 | static int fmvj18x_config(struct pcmcia_device *link); |
88 | static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id); | 88 | static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id); |
89 | static int fmvj18x_setup_mfc(dev_link_t *link); | 89 | static int fmvj18x_setup_mfc(struct pcmcia_device *link); |
90 | static void fmvj18x_release(dev_link_t *link); | 90 | static void fmvj18x_release(struct pcmcia_device *link); |
91 | static void fmvj18x_detach(struct pcmcia_device *p_dev); | 91 | static void fmvj18x_detach(struct pcmcia_device *p_dev); |
92 | 92 | ||
93 | /* | 93 | /* |
@@ -116,7 +116,7 @@ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, | |||
116 | driver specific data structure | 116 | driver specific data structure |
117 | */ | 117 | */ |
118 | typedef struct local_info_t { | 118 | typedef struct local_info_t { |
119 | dev_link_t link; | 119 | struct pcmcia_device *p_dev; |
120 | dev_node_t node; | 120 | dev_node_t node; |
121 | struct net_device_stats stats; | 121 | struct net_device_stats stats; |
122 | long open_time; | 122 | long open_time; |
@@ -228,10 +228,9 @@ typedef struct local_info_t { | |||
228 | #define BANK_1U 0x24 /* bank 1 (CONFIG_1) */ | 228 | #define BANK_1U 0x24 /* bank 1 (CONFIG_1) */ |
229 | #define BANK_2U 0x28 /* bank 2 (CONFIG_1) */ | 229 | #define BANK_2U 0x28 /* bank 2 (CONFIG_1) */ |
230 | 230 | ||
231 | static int fmvj18x_attach(struct pcmcia_device *p_dev) | 231 | static int fmvj18x_probe(struct pcmcia_device *link) |
232 | { | 232 | { |
233 | local_info_t *lp; | 233 | local_info_t *lp; |
234 | dev_link_t *link; | ||
235 | struct net_device *dev; | 234 | struct net_device *dev; |
236 | 235 | ||
237 | DEBUG(0, "fmvj18x_attach()\n"); | 236 | DEBUG(0, "fmvj18x_attach()\n"); |
@@ -241,8 +240,8 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev) | |||
241 | if (!dev) | 240 | if (!dev) |
242 | return -ENOMEM; | 241 | return -ENOMEM; |
243 | lp = netdev_priv(dev); | 242 | lp = netdev_priv(dev); |
244 | link = &lp->link; | ||
245 | link->priv = dev; | 243 | link->priv = dev; |
244 | lp->p_dev = link; | ||
246 | 245 | ||
247 | /* The io structure describes IO port mapping */ | 246 | /* The io structure describes IO port mapping */ |
248 | link->io.NumPorts1 = 32; | 247 | link->io.NumPorts1 = 32; |
@@ -257,7 +256,6 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev) | |||
257 | 256 | ||
258 | /* General socket configuration */ | 257 | /* General socket configuration */ |
259 | link->conf.Attributes = CONF_ENABLE_IRQ; | 258 | link->conf.Attributes = CONF_ENABLE_IRQ; |
260 | link->conf.Vcc = 50; | ||
261 | link->conf.IntType = INT_MEMORY_AND_IO; | 259 | link->conf.IntType = INT_MEMORY_AND_IO; |
262 | 260 | ||
263 | /* The FMVJ18x specific entries in the device structure. */ | 261 | /* The FMVJ18x specific entries in the device structure. */ |
@@ -274,29 +272,21 @@ static int fmvj18x_attach(struct pcmcia_device *p_dev) | |||
274 | #endif | 272 | #endif |
275 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 273 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
276 | 274 | ||
277 | link->handle = p_dev; | 275 | return fmvj18x_config(link); |
278 | p_dev->instance = link; | ||
279 | |||
280 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
281 | fmvj18x_config(link); | ||
282 | |||
283 | return 0; | ||
284 | } /* fmvj18x_attach */ | 276 | } /* fmvj18x_attach */ |
285 | 277 | ||
286 | /*====================================================================*/ | 278 | /*====================================================================*/ |
287 | 279 | ||
288 | static void fmvj18x_detach(struct pcmcia_device *p_dev) | 280 | static void fmvj18x_detach(struct pcmcia_device *link) |
289 | { | 281 | { |
290 | dev_link_t *link = dev_to_instance(p_dev); | ||
291 | struct net_device *dev = link->priv; | 282 | struct net_device *dev = link->priv; |
292 | 283 | ||
293 | DEBUG(0, "fmvj18x_detach(0x%p)\n", link); | 284 | DEBUG(0, "fmvj18x_detach(0x%p)\n", link); |
294 | 285 | ||
295 | if (link->dev) | 286 | if (link->dev_node) |
296 | unregister_netdev(dev); | 287 | unregister_netdev(dev); |
297 | 288 | ||
298 | if (link->state & DEV_CONFIG) | 289 | fmvj18x_release(link); |
299 | fmvj18x_release(link); | ||
300 | 290 | ||
301 | free_netdev(dev); | 291 | free_netdev(dev); |
302 | } /* fmvj18x_detach */ | 292 | } /* fmvj18x_detach */ |
@@ -306,7 +296,7 @@ static void fmvj18x_detach(struct pcmcia_device *p_dev) | |||
306 | #define CS_CHECK(fn, ret) \ | 296 | #define CS_CHECK(fn, ret) \ |
307 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 297 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
308 | 298 | ||
309 | static int mfc_try_io_port(dev_link_t *link) | 299 | static int mfc_try_io_port(struct pcmcia_device *link) |
310 | { | 300 | { |
311 | int i, ret; | 301 | int i, ret; |
312 | static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; | 302 | static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; |
@@ -318,13 +308,13 @@ static int mfc_try_io_port(dev_link_t *link) | |||
318 | link->io.NumPorts2 = 0; | 308 | link->io.NumPorts2 = 0; |
319 | printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n"); | 309 | printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n"); |
320 | } | 310 | } |
321 | ret = pcmcia_request_io(link->handle, &link->io); | 311 | ret = pcmcia_request_io(link, &link->io); |
322 | if (ret == CS_SUCCESS) return ret; | 312 | if (ret == CS_SUCCESS) return ret; |
323 | } | 313 | } |
324 | return ret; | 314 | return ret; |
325 | } | 315 | } |
326 | 316 | ||
327 | static int ungermann_try_io_port(dev_link_t *link) | 317 | static int ungermann_try_io_port(struct pcmcia_device *link) |
328 | { | 318 | { |
329 | int ret; | 319 | int ret; |
330 | kio_addr_t ioaddr; | 320 | kio_addr_t ioaddr; |
@@ -334,7 +324,7 @@ static int ungermann_try_io_port(dev_link_t *link) | |||
334 | */ | 324 | */ |
335 | for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) { | 325 | for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) { |
336 | link->io.BasePort1 = ioaddr; | 326 | link->io.BasePort1 = ioaddr; |
337 | ret = pcmcia_request_io(link->handle, &link->io); | 327 | ret = pcmcia_request_io(link, &link->io); |
338 | if (ret == CS_SUCCESS) { | 328 | if (ret == CS_SUCCESS) { |
339 | /* calculate ConfigIndex value */ | 329 | /* calculate ConfigIndex value */ |
340 | link->conf.ConfigIndex = | 330 | link->conf.ConfigIndex = |
@@ -345,9 +335,8 @@ static int ungermann_try_io_port(dev_link_t *link) | |||
345 | return ret; /* RequestIO failed */ | 335 | return ret; /* RequestIO failed */ |
346 | } | 336 | } |
347 | 337 | ||
348 | static void fmvj18x_config(dev_link_t *link) | 338 | static int fmvj18x_config(struct pcmcia_device *link) |
349 | { | 339 | { |
350 | client_handle_t handle = link->handle; | ||
351 | struct net_device *dev = link->priv; | 340 | struct net_device *dev = link->priv; |
352 | local_info_t *lp = netdev_priv(dev); | 341 | local_info_t *lp = netdev_priv(dev); |
353 | tuple_t tuple; | 342 | tuple_t tuple; |
@@ -366,42 +355,34 @@ static void fmvj18x_config(dev_link_t *link) | |||
366 | registers. | 355 | registers. |
367 | */ | 356 | */ |
368 | tuple.DesiredTuple = CISTPL_CONFIG; | 357 | tuple.DesiredTuple = CISTPL_CONFIG; |
369 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 358 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
370 | tuple.TupleData = (u_char *)buf; | 359 | tuple.TupleData = (u_char *)buf; |
371 | tuple.TupleDataMax = 64; | 360 | tuple.TupleDataMax = 64; |
372 | tuple.TupleOffset = 0; | 361 | tuple.TupleOffset = 0; |
373 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 362 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
374 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 363 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
375 | |||
376 | /* Configure card */ | ||
377 | link->state |= DEV_CONFIG; | ||
378 | 364 | ||
379 | link->conf.ConfigBase = parse.config.base; | 365 | link->conf.ConfigBase = parse.config.base; |
380 | link->conf.Present = parse.config.rmask[0]; | 366 | link->conf.Present = parse.config.rmask[0]; |
381 | 367 | ||
382 | tuple.DesiredTuple = CISTPL_FUNCE; | 368 | tuple.DesiredTuple = CISTPL_FUNCE; |
383 | tuple.TupleOffset = 0; | 369 | tuple.TupleOffset = 0; |
384 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { | 370 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { |
385 | /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ | 371 | /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ |
386 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 372 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
387 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 373 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
388 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 374 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
389 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 375 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
390 | link->conf.ConfigIndex = parse.cftable_entry.index; | 376 | link->conf.ConfigIndex = parse.cftable_entry.index; |
391 | tuple.DesiredTuple = CISTPL_MANFID; | 377 | tuple.DesiredTuple = CISTPL_MANFID; |
392 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) | 378 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) |
393 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 379 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
394 | else | 380 | else |
395 | buf[0] = 0xffff; | 381 | buf[0] = 0xffff; |
396 | switch (le16_to_cpu(buf[0])) { | 382 | switch (le16_to_cpu(buf[0])) { |
397 | case MANFID_TDK: | 383 | case MANFID_TDK: |
398 | cardtype = TDK; | 384 | cardtype = TDK; |
399 | if (le16_to_cpu(buf[1]) == PRODID_TDK_CF010) { | 385 | if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410 |
400 | cs_status_t status; | ||
401 | pcmcia_get_status(handle, &status); | ||
402 | if (status.CardState & CS_EVENT_3VCARD) | ||
403 | link->conf.Vcc = 33; /* inserted in 3.3V slot */ | ||
404 | } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410 | ||
405 | || le16_to_cpu(buf[1]) == PRODID_TDK_NP9610 | 386 | || le16_to_cpu(buf[1]) == PRODID_TDK_NP9610 |
406 | || le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) { | 387 | || le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) { |
407 | /* MultiFunction Card */ | 388 | /* MultiFunction Card */ |
@@ -429,8 +410,8 @@ static void fmvj18x_config(dev_link_t *link) | |||
429 | } else { | 410 | } else { |
430 | /* old type card */ | 411 | /* old type card */ |
431 | tuple.DesiredTuple = CISTPL_MANFID; | 412 | tuple.DesiredTuple = CISTPL_MANFID; |
432 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) | 413 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) |
433 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 414 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
434 | else | 415 | else |
435 | buf[0] = 0xffff; | 416 | buf[0] = 0xffff; |
436 | switch (le16_to_cpu(buf[0])) { | 417 | switch (le16_to_cpu(buf[0])) { |
@@ -461,10 +442,10 @@ static void fmvj18x_config(dev_link_t *link) | |||
461 | ret = ungermann_try_io_port(link); | 442 | ret = ungermann_try_io_port(link); |
462 | if (ret != CS_SUCCESS) goto cs_failed; | 443 | if (ret != CS_SUCCESS) goto cs_failed; |
463 | } else { | 444 | } else { |
464 | CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); | 445 | CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); |
465 | } | 446 | } |
466 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 447 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
467 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 448 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
468 | dev->irq = link->irq.AssignedIRQ; | 449 | dev->irq = link->irq.AssignedIRQ; |
469 | dev->base_addr = link->io.BasePort1; | 450 | dev->base_addr = link->io.BasePort1; |
470 | 451 | ||
@@ -493,17 +474,17 @@ static void fmvj18x_config(dev_link_t *link) | |||
493 | case CONTEC: | 474 | case CONTEC: |
494 | tuple.DesiredTuple = CISTPL_FUNCE; | 475 | tuple.DesiredTuple = CISTPL_FUNCE; |
495 | tuple.TupleOffset = 0; | 476 | tuple.TupleOffset = 0; |
496 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 477 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
497 | tuple.TupleOffset = 0; | 478 | tuple.TupleOffset = 0; |
498 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 479 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
499 | if (cardtype == MBH10304) { | 480 | if (cardtype == MBH10304) { |
500 | /* MBH10304's CIS_FUNCE is corrupted */ | 481 | /* MBH10304's CIS_FUNCE is corrupted */ |
501 | node_id = &(tuple.TupleData[5]); | 482 | node_id = &(tuple.TupleData[5]); |
502 | card_name = "FMV-J182"; | 483 | card_name = "FMV-J182"; |
503 | } else { | 484 | } else { |
504 | while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) { | 485 | while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) { |
505 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); | 486 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); |
506 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 487 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
507 | } | 488 | } |
508 | node_id = &(tuple.TupleData[2]); | 489 | node_id = &(tuple.TupleData[2]); |
509 | if( cardtype == TDK ) { | 490 | if( cardtype == TDK ) { |
@@ -545,13 +526,12 @@ static void fmvj18x_config(dev_link_t *link) | |||
545 | } | 526 | } |
546 | 527 | ||
547 | lp->cardtype = cardtype; | 528 | lp->cardtype = cardtype; |
548 | link->dev = &lp->node; | 529 | link->dev_node = &lp->node; |
549 | link->state &= ~DEV_CONFIG_PENDING; | 530 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
550 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
551 | 531 | ||
552 | if (register_netdev(dev) != 0) { | 532 | if (register_netdev(dev) != 0) { |
553 | printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n"); | 533 | printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n"); |
554 | link->dev = NULL; | 534 | link->dev_node = NULL; |
555 | goto failed; | 535 | goto failed; |
556 | } | 536 | } |
557 | 537 | ||
@@ -564,19 +544,18 @@ static void fmvj18x_config(dev_link_t *link) | |||
564 | for (i = 0; i < 6; i++) | 544 | for (i = 0; i < 6; i++) |
565 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); | 545 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); |
566 | 546 | ||
567 | return; | 547 | return 0; |
568 | 548 | ||
569 | cs_failed: | 549 | cs_failed: |
570 | /* All Card Services errors end up here */ | 550 | /* All Card Services errors end up here */ |
571 | cs_error(link->handle, last_fn, last_ret); | 551 | cs_error(link, last_fn, last_ret); |
572 | failed: | 552 | failed: |
573 | fmvj18x_release(link); | 553 | fmvj18x_release(link); |
574 | link->state &= ~DEV_CONFIG_PENDING; | 554 | return -ENODEV; |
575 | |||
576 | } /* fmvj18x_config */ | 555 | } /* fmvj18x_config */ |
577 | /*====================================================================*/ | 556 | /*====================================================================*/ |
578 | 557 | ||
579 | static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id) | 558 | static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id) |
580 | { | 559 | { |
581 | win_req_t req; | 560 | win_req_t req; |
582 | memreq_t mem; | 561 | memreq_t mem; |
@@ -587,9 +566,9 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id) | |||
587 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 566 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; |
588 | req.Base = 0; req.Size = 0; | 567 | req.Base = 0; req.Size = 0; |
589 | req.AccessSpeed = 0; | 568 | req.AccessSpeed = 0; |
590 | i = pcmcia_request_window(&link->handle, &req, &link->win); | 569 | i = pcmcia_request_window(&link, &req, &link->win); |
591 | if (i != CS_SUCCESS) { | 570 | if (i != CS_SUCCESS) { |
592 | cs_error(link->handle, RequestWindow, i); | 571 | cs_error(link, RequestWindow, i); |
593 | return -1; | 572 | return -1; |
594 | } | 573 | } |
595 | 574 | ||
@@ -623,13 +602,13 @@ static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id) | |||
623 | iounmap(base); | 602 | iounmap(base); |
624 | j = pcmcia_release_window(link->win); | 603 | j = pcmcia_release_window(link->win); |
625 | if (j != CS_SUCCESS) | 604 | if (j != CS_SUCCESS) |
626 | cs_error(link->handle, ReleaseWindow, j); | 605 | cs_error(link, ReleaseWindow, j); |
627 | return (i != 0x200) ? 0 : -1; | 606 | return (i != 0x200) ? 0 : -1; |
628 | 607 | ||
629 | } /* fmvj18x_get_hwinfo */ | 608 | } /* fmvj18x_get_hwinfo */ |
630 | /*====================================================================*/ | 609 | /*====================================================================*/ |
631 | 610 | ||
632 | static int fmvj18x_setup_mfc(dev_link_t *link) | 611 | static int fmvj18x_setup_mfc(struct pcmcia_device *link) |
633 | { | 612 | { |
634 | win_req_t req; | 613 | win_req_t req; |
635 | memreq_t mem; | 614 | memreq_t mem; |
@@ -642,9 +621,9 @@ static int fmvj18x_setup_mfc(dev_link_t *link) | |||
642 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 621 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; |
643 | req.Base = 0; req.Size = 0; | 622 | req.Base = 0; req.Size = 0; |
644 | req.AccessSpeed = 0; | 623 | req.AccessSpeed = 0; |
645 | i = pcmcia_request_window(&link->handle, &req, &link->win); | 624 | i = pcmcia_request_window(&link, &req, &link->win); |
646 | if (i != CS_SUCCESS) { | 625 | if (i != CS_SUCCESS) { |
647 | cs_error(link->handle, RequestWindow, i); | 626 | cs_error(link, RequestWindow, i); |
648 | return -1; | 627 | return -1; |
649 | } | 628 | } |
650 | 629 | ||
@@ -666,54 +645,35 @@ static int fmvj18x_setup_mfc(dev_link_t *link) | |||
666 | iounmap(base); | 645 | iounmap(base); |
667 | j = pcmcia_release_window(link->win); | 646 | j = pcmcia_release_window(link->win); |
668 | if (j != CS_SUCCESS) | 647 | if (j != CS_SUCCESS) |
669 | cs_error(link->handle, ReleaseWindow, j); | 648 | cs_error(link, ReleaseWindow, j); |
670 | return 0; | 649 | return 0; |
671 | 650 | ||
672 | } | 651 | } |
673 | /*====================================================================*/ | 652 | /*====================================================================*/ |
674 | 653 | ||
675 | static void fmvj18x_release(dev_link_t *link) | 654 | static void fmvj18x_release(struct pcmcia_device *link) |
676 | { | 655 | { |
677 | 656 | DEBUG(0, "fmvj18x_release(0x%p)\n", link); | |
678 | DEBUG(0, "fmvj18x_release(0x%p)\n", link); | 657 | pcmcia_disable_device(link); |
679 | |||
680 | /* Don't bother checking to see if these succeed or not */ | ||
681 | pcmcia_release_window(link->win); | ||
682 | pcmcia_release_configuration(link->handle); | ||
683 | pcmcia_release_io(link->handle, &link->io); | ||
684 | pcmcia_release_irq(link->handle, &link->irq); | ||
685 | |||
686 | link->state &= ~DEV_CONFIG; | ||
687 | } | 658 | } |
688 | 659 | ||
689 | static int fmvj18x_suspend(struct pcmcia_device *p_dev) | 660 | static int fmvj18x_suspend(struct pcmcia_device *link) |
690 | { | 661 | { |
691 | dev_link_t *link = dev_to_instance(p_dev); | ||
692 | struct net_device *dev = link->priv; | 662 | struct net_device *dev = link->priv; |
693 | 663 | ||
694 | link->state |= DEV_SUSPEND; | 664 | if (link->open) |
695 | if (link->state & DEV_CONFIG) { | 665 | netif_device_detach(dev); |
696 | if (link->open) | ||
697 | netif_device_detach(dev); | ||
698 | pcmcia_release_configuration(link->handle); | ||
699 | } | ||
700 | |||
701 | 666 | ||
702 | return 0; | 667 | return 0; |
703 | } | 668 | } |
704 | 669 | ||
705 | static int fmvj18x_resume(struct pcmcia_device *p_dev) | 670 | static int fmvj18x_resume(struct pcmcia_device *link) |
706 | { | 671 | { |
707 | dev_link_t *link = dev_to_instance(p_dev); | ||
708 | struct net_device *dev = link->priv; | 672 | struct net_device *dev = link->priv; |
709 | 673 | ||
710 | link->state &= ~DEV_SUSPEND; | 674 | if (link->open) { |
711 | if (link->state & DEV_CONFIG) { | 675 | fjn_reset(dev); |
712 | pcmcia_request_configuration(link->handle, &link->conf); | 676 | netif_device_attach(dev); |
713 | if (link->open) { | ||
714 | fjn_reset(dev); | ||
715 | netif_device_attach(dev); | ||
716 | } | ||
717 | } | 677 | } |
718 | 678 | ||
719 | return 0; | 679 | return 0; |
@@ -751,7 +711,7 @@ static struct pcmcia_driver fmvj18x_cs_driver = { | |||
751 | .drv = { | 711 | .drv = { |
752 | .name = "fmvj18x_cs", | 712 | .name = "fmvj18x_cs", |
753 | }, | 713 | }, |
754 | .probe = fmvj18x_attach, | 714 | .probe = fmvj18x_probe, |
755 | .remove = fmvj18x_detach, | 715 | .remove = fmvj18x_detach, |
756 | .id_table = fmvj18x_ids, | 716 | .id_table = fmvj18x_ids, |
757 | .suspend = fmvj18x_suspend, | 717 | .suspend = fmvj18x_suspend, |
@@ -1148,11 +1108,11 @@ static int fjn_config(struct net_device *dev, struct ifmap *map){ | |||
1148 | static int fjn_open(struct net_device *dev) | 1108 | static int fjn_open(struct net_device *dev) |
1149 | { | 1109 | { |
1150 | struct local_info_t *lp = netdev_priv(dev); | 1110 | struct local_info_t *lp = netdev_priv(dev); |
1151 | dev_link_t *link = &lp->link; | 1111 | struct pcmcia_device *link = lp->p_dev; |
1152 | 1112 | ||
1153 | DEBUG(4, "fjn_open('%s').\n", dev->name); | 1113 | DEBUG(4, "fjn_open('%s').\n", dev->name); |
1154 | 1114 | ||
1155 | if (!DEV_OK(link)) | 1115 | if (!pcmcia_dev_present(link)) |
1156 | return -ENODEV; | 1116 | return -ENODEV; |
1157 | 1117 | ||
1158 | link->open++; | 1118 | link->open++; |
@@ -1173,7 +1133,7 @@ static int fjn_open(struct net_device *dev) | |||
1173 | static int fjn_close(struct net_device *dev) | 1133 | static int fjn_close(struct net_device *dev) |
1174 | { | 1134 | { |
1175 | struct local_info_t *lp = netdev_priv(dev); | 1135 | struct local_info_t *lp = netdev_priv(dev); |
1176 | dev_link_t *link = &lp->link; | 1136 | struct pcmcia_device *link = lp->p_dev; |
1177 | kio_addr_t ioaddr = dev->base_addr; | 1137 | kio_addr_t ioaddr = dev->base_addr; |
1178 | 1138 | ||
1179 | DEBUG(4, "fjn_close('%s').\n", dev->name); | 1139 | DEBUG(4, "fjn_close('%s').\n", dev->name); |
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index b9c7e39576f5..b8fe70b85641 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c | |||
@@ -105,15 +105,15 @@ MODULE_LICENSE("GPL"); | |||
105 | 105 | ||
106 | /*====================================================================*/ | 106 | /*====================================================================*/ |
107 | 107 | ||
108 | static void ibmtr_config(dev_link_t *link); | 108 | static int ibmtr_config(struct pcmcia_device *link); |
109 | static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase); | 109 | static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase); |
110 | static void ibmtr_release(dev_link_t *link); | 110 | static void ibmtr_release(struct pcmcia_device *link); |
111 | static void ibmtr_detach(struct pcmcia_device *p_dev); | 111 | static void ibmtr_detach(struct pcmcia_device *p_dev); |
112 | 112 | ||
113 | /*====================================================================*/ | 113 | /*====================================================================*/ |
114 | 114 | ||
115 | typedef struct ibmtr_dev_t { | 115 | typedef struct ibmtr_dev_t { |
116 | dev_link_t link; | 116 | struct pcmcia_device *p_dev; |
117 | struct net_device *dev; | 117 | struct net_device *dev; |
118 | dev_node_t node; | 118 | dev_node_t node; |
119 | window_handle_t sram_win_handle; | 119 | window_handle_t sram_win_handle; |
@@ -138,12 +138,11 @@ static struct ethtool_ops netdev_ethtool_ops = { | |||
138 | 138 | ||
139 | ======================================================================*/ | 139 | ======================================================================*/ |
140 | 140 | ||
141 | static int ibmtr_attach(struct pcmcia_device *p_dev) | 141 | static int ibmtr_attach(struct pcmcia_device *link) |
142 | { | 142 | { |
143 | ibmtr_dev_t *info; | 143 | ibmtr_dev_t *info; |
144 | dev_link_t *link; | ||
145 | struct net_device *dev; | 144 | struct net_device *dev; |
146 | 145 | ||
147 | DEBUG(0, "ibmtr_attach()\n"); | 146 | DEBUG(0, "ibmtr_attach()\n"); |
148 | 147 | ||
149 | /* Create new token-ring device */ | 148 | /* Create new token-ring device */ |
@@ -156,7 +155,7 @@ static int ibmtr_attach(struct pcmcia_device *p_dev) | |||
156 | return -ENOMEM; | 155 | return -ENOMEM; |
157 | } | 156 | } |
158 | 157 | ||
159 | link = &info->link; | 158 | info->p_dev = link; |
160 | link->priv = info; | 159 | link->priv = info; |
161 | info->ti = netdev_priv(dev); | 160 | info->ti = netdev_priv(dev); |
162 | 161 | ||
@@ -167,21 +166,14 @@ static int ibmtr_attach(struct pcmcia_device *p_dev) | |||
167 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 166 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
168 | link->irq.Handler = &tok_interrupt; | 167 | link->irq.Handler = &tok_interrupt; |
169 | link->conf.Attributes = CONF_ENABLE_IRQ; | 168 | link->conf.Attributes = CONF_ENABLE_IRQ; |
170 | link->conf.Vcc = 50; | ||
171 | link->conf.IntType = INT_MEMORY_AND_IO; | 169 | link->conf.IntType = INT_MEMORY_AND_IO; |
172 | link->conf.Present = PRESENT_OPTION; | 170 | link->conf.Present = PRESENT_OPTION; |
173 | 171 | ||
174 | link->irq.Instance = info->dev = dev; | 172 | link->irq.Instance = info->dev = dev; |
175 | |||
176 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | ||
177 | |||
178 | link->handle = p_dev; | ||
179 | p_dev->instance = link; | ||
180 | 173 | ||
181 | link->state |= DEV_PRESENT; | 174 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
182 | ibmtr_config(link); | ||
183 | 175 | ||
184 | return 0; | 176 | return ibmtr_config(link); |
185 | } /* ibmtr_attach */ | 177 | } /* ibmtr_attach */ |
186 | 178 | ||
187 | /*====================================================================== | 179 | /*====================================================================== |
@@ -193,23 +185,22 @@ static int ibmtr_attach(struct pcmcia_device *p_dev) | |||
193 | 185 | ||
194 | ======================================================================*/ | 186 | ======================================================================*/ |
195 | 187 | ||
196 | static void ibmtr_detach(struct pcmcia_device *p_dev) | 188 | static void ibmtr_detach(struct pcmcia_device *link) |
197 | { | 189 | { |
198 | dev_link_t *link = dev_to_instance(p_dev); | ||
199 | struct ibmtr_dev_t *info = link->priv; | 190 | struct ibmtr_dev_t *info = link->priv; |
200 | struct net_device *dev = info->dev; | 191 | struct net_device *dev = info->dev; |
201 | 192 | ||
202 | DEBUG(0, "ibmtr_detach(0x%p)\n", link); | 193 | DEBUG(0, "ibmtr_detach(0x%p)\n", link); |
203 | 194 | ||
204 | if (link->dev) | 195 | if (link->dev_node) |
205 | unregister_netdev(dev); | 196 | unregister_netdev(dev); |
206 | 197 | ||
207 | { | 198 | { |
208 | struct tok_info *ti = netdev_priv(dev); | 199 | struct tok_info *ti = netdev_priv(dev); |
209 | del_timer_sync(&(ti->tr_timer)); | 200 | del_timer_sync(&(ti->tr_timer)); |
210 | } | 201 | } |
211 | if (link->state & DEV_CONFIG) | 202 | |
212 | ibmtr_release(link); | 203 | ibmtr_release(link); |
213 | 204 | ||
214 | free_netdev(dev); | 205 | free_netdev(dev); |
215 | kfree(info); | 206 | kfree(info); |
@@ -226,9 +217,8 @@ static void ibmtr_detach(struct pcmcia_device *p_dev) | |||
226 | #define CS_CHECK(fn, ret) \ | 217 | #define CS_CHECK(fn, ret) \ |
227 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 218 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
228 | 219 | ||
229 | static void ibmtr_config(dev_link_t *link) | 220 | static int ibmtr_config(struct pcmcia_device *link) |
230 | { | 221 | { |
231 | client_handle_t handle = link->handle; | ||
232 | ibmtr_dev_t *info = link->priv; | 222 | ibmtr_dev_t *info = link->priv; |
233 | struct net_device *dev = info->dev; | 223 | struct net_device *dev = info->dev; |
234 | struct tok_info *ti = netdev_priv(dev); | 224 | struct tok_info *ti = netdev_priv(dev); |
@@ -246,29 +236,25 @@ static void ibmtr_config(dev_link_t *link) | |||
246 | tuple.TupleDataMax = 64; | 236 | tuple.TupleDataMax = 64; |
247 | tuple.TupleOffset = 0; | 237 | tuple.TupleOffset = 0; |
248 | tuple.DesiredTuple = CISTPL_CONFIG; | 238 | tuple.DesiredTuple = CISTPL_CONFIG; |
249 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 239 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
250 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 240 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
251 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 241 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
252 | link->conf.ConfigBase = parse.config.base; | 242 | link->conf.ConfigBase = parse.config.base; |
253 | |||
254 | /* Configure card */ | ||
255 | link->state |= DEV_CONFIG; | ||
256 | |||
257 | link->conf.ConfigIndex = 0x61; | 243 | link->conf.ConfigIndex = 0x61; |
258 | 244 | ||
259 | /* Determine if this is PRIMARY or ALTERNATE. */ | 245 | /* Determine if this is PRIMARY or ALTERNATE. */ |
260 | 246 | ||
261 | /* Try PRIMARY card at 0xA20-0xA23 */ | 247 | /* Try PRIMARY card at 0xA20-0xA23 */ |
262 | link->io.BasePort1 = 0xA20; | 248 | link->io.BasePort1 = 0xA20; |
263 | i = pcmcia_request_io(link->handle, &link->io); | 249 | i = pcmcia_request_io(link, &link->io); |
264 | if (i != CS_SUCCESS) { | 250 | if (i != CS_SUCCESS) { |
265 | /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */ | 251 | /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */ |
266 | link->io.BasePort1 = 0xA24; | 252 | link->io.BasePort1 = 0xA24; |
267 | CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io)); | 253 | CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); |
268 | } | 254 | } |
269 | dev->base_addr = link->io.BasePort1; | 255 | dev->base_addr = link->io.BasePort1; |
270 | 256 | ||
271 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 257 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
272 | dev->irq = link->irq.AssignedIRQ; | 258 | dev->irq = link->irq.AssignedIRQ; |
273 | ti->irq = link->irq.AssignedIRQ; | 259 | ti->irq = link->irq.AssignedIRQ; |
274 | ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); | 260 | ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); |
@@ -279,7 +265,7 @@ static void ibmtr_config(dev_link_t *link) | |||
279 | req.Base = 0; | 265 | req.Base = 0; |
280 | req.Size = 0x2000; | 266 | req.Size = 0x2000; |
281 | req.AccessSpeed = 250; | 267 | req.AccessSpeed = 250; |
282 | CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); | 268 | CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); |
283 | 269 | ||
284 | mem.CardOffset = mmiobase; | 270 | mem.CardOffset = mmiobase; |
285 | mem.Page = 0; | 271 | mem.Page = 0; |
@@ -292,7 +278,7 @@ static void ibmtr_config(dev_link_t *link) | |||
292 | req.Base = 0; | 278 | req.Base = 0; |
293 | req.Size = sramsize * 1024; | 279 | req.Size = sramsize * 1024; |
294 | req.AccessSpeed = 250; | 280 | req.AccessSpeed = 250; |
295 | CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &info->sram_win_handle)); | 281 | CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &info->sram_win_handle)); |
296 | 282 | ||
297 | mem.CardOffset = srambase; | 283 | mem.CardOffset = srambase; |
298 | mem.Page = 0; | 284 | mem.Page = 0; |
@@ -302,21 +288,20 @@ static void ibmtr_config(dev_link_t *link) | |||
302 | ti->sram_virt = ioremap(req.Base, req.Size); | 288 | ti->sram_virt = ioremap(req.Base, req.Size); |
303 | ti->sram_phys = req.Base; | 289 | ti->sram_phys = req.Base; |
304 | 290 | ||
305 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 291 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
306 | 292 | ||
307 | /* Set up the Token-Ring Controller Configuration Register and | 293 | /* Set up the Token-Ring Controller Configuration Register and |
308 | turn on the card. Check the "Local Area Network Credit Card | 294 | turn on the card. Check the "Local Area Network Credit Card |
309 | Adapters Technical Reference" SC30-3585 for this info. */ | 295 | Adapters Technical Reference" SC30-3585 for this info. */ |
310 | ibmtr_hw_setup(dev, mmiobase); | 296 | ibmtr_hw_setup(dev, mmiobase); |
311 | 297 | ||
312 | link->dev = &info->node; | 298 | link->dev_node = &info->node; |
313 | link->state &= ~DEV_CONFIG_PENDING; | 299 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
314 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
315 | 300 | ||
316 | i = ibmtr_probe_card(dev); | 301 | i = ibmtr_probe_card(dev); |
317 | if (i != 0) { | 302 | if (i != 0) { |
318 | printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n"); | 303 | printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n"); |
319 | link->dev = NULL; | 304 | link->dev_node = NULL; |
320 | goto failed; | 305 | goto failed; |
321 | } | 306 | } |
322 | 307 | ||
@@ -330,12 +315,13 @@ static void ibmtr_config(dev_link_t *link) | |||
330 | for (i = 0; i < TR_ALEN; i++) | 315 | for (i = 0; i < TR_ALEN; i++) |
331 | printk("%02X", dev->dev_addr[i]); | 316 | printk("%02X", dev->dev_addr[i]); |
332 | printk("\n"); | 317 | printk("\n"); |
333 | return; | 318 | return 0; |
334 | 319 | ||
335 | cs_failed: | 320 | cs_failed: |
336 | cs_error(link->handle, last_fn, last_ret); | 321 | cs_error(link, last_fn, last_ret); |
337 | failed: | 322 | failed: |
338 | ibmtr_release(link); | 323 | ibmtr_release(link); |
324 | return -ENODEV; | ||
339 | } /* ibmtr_config */ | 325 | } /* ibmtr_config */ |
340 | 326 | ||
341 | /*====================================================================== | 327 | /*====================================================================== |
@@ -346,56 +332,41 @@ failed: | |||
346 | 332 | ||
347 | ======================================================================*/ | 333 | ======================================================================*/ |
348 | 334 | ||
349 | static void ibmtr_release(dev_link_t *link) | 335 | static void ibmtr_release(struct pcmcia_device *link) |
350 | { | 336 | { |
351 | ibmtr_dev_t *info = link->priv; | 337 | ibmtr_dev_t *info = link->priv; |
352 | struct net_device *dev = info->dev; | 338 | struct net_device *dev = info->dev; |
353 | |||
354 | DEBUG(0, "ibmtr_release(0x%p)\n", link); | ||
355 | 339 | ||
356 | pcmcia_release_configuration(link->handle); | 340 | DEBUG(0, "ibmtr_release(0x%p)\n", link); |
357 | pcmcia_release_io(link->handle, &link->io); | ||
358 | pcmcia_release_irq(link->handle, &link->irq); | ||
359 | if (link->win) { | ||
360 | struct tok_info *ti = netdev_priv(dev); | ||
361 | iounmap(ti->mmio); | ||
362 | pcmcia_release_window(link->win); | ||
363 | pcmcia_release_window(info->sram_win_handle); | ||
364 | } | ||
365 | 341 | ||
366 | link->state &= ~DEV_CONFIG; | 342 | if (link->win) { |
343 | struct tok_info *ti = netdev_priv(dev); | ||
344 | iounmap(ti->mmio); | ||
345 | pcmcia_release_window(info->sram_win_handle); | ||
346 | } | ||
347 | pcmcia_disable_device(link); | ||
367 | } | 348 | } |
368 | 349 | ||
369 | static int ibmtr_suspend(struct pcmcia_device *p_dev) | 350 | static int ibmtr_suspend(struct pcmcia_device *link) |
370 | { | 351 | { |
371 | dev_link_t *link = dev_to_instance(p_dev); | ||
372 | ibmtr_dev_t *info = link->priv; | 352 | ibmtr_dev_t *info = link->priv; |
373 | struct net_device *dev = info->dev; | 353 | struct net_device *dev = info->dev; |
374 | 354 | ||
375 | link->state |= DEV_SUSPEND; | 355 | if (link->open) |
376 | if (link->state & DEV_CONFIG) { | 356 | netif_device_detach(dev); |
377 | if (link->open) | ||
378 | netif_device_detach(dev); | ||
379 | pcmcia_release_configuration(link->handle); | ||
380 | } | ||
381 | 357 | ||
382 | return 0; | 358 | return 0; |
383 | } | 359 | } |
384 | 360 | ||
385 | static int ibmtr_resume(struct pcmcia_device *p_dev) | 361 | static int ibmtr_resume(struct pcmcia_device *link) |
386 | { | 362 | { |
387 | dev_link_t *link = dev_to_instance(p_dev); | ||
388 | ibmtr_dev_t *info = link->priv; | 363 | ibmtr_dev_t *info = link->priv; |
389 | struct net_device *dev = info->dev; | 364 | struct net_device *dev = info->dev; |
390 | 365 | ||
391 | link->state &= ~DEV_SUSPEND; | 366 | if (link->open) { |
392 | if (link->state & DEV_CONFIG) { | 367 | ibmtr_probe(dev); /* really? */ |
393 | pcmcia_request_configuration(link->handle, &link->conf); | 368 | netif_device_attach(dev); |
394 | if (link->open) { | 369 | } |
395 | ibmtr_probe(dev); /* really? */ | ||
396 | netif_device_attach(dev); | ||
397 | } | ||
398 | } | ||
399 | 370 | ||
400 | return 0; | 371 | return 0; |
401 | } | 372 | } |
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index 787176c57fd9..4260c2128f47 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c | |||
@@ -362,7 +362,7 @@ typedef struct _mace_statistics { | |||
362 | } mace_statistics; | 362 | } mace_statistics; |
363 | 363 | ||
364 | typedef struct _mace_private { | 364 | typedef struct _mace_private { |
365 | dev_link_t link; | 365 | struct pcmcia_device *p_dev; |
366 | dev_node_t node; | 366 | dev_node_t node; |
367 | struct net_device_stats linux_stats; /* Linux statistics counters */ | 367 | struct net_device_stats linux_stats; /* Linux statistics counters */ |
368 | mace_statistics mace_stats; /* MACE chip statistics counters */ | 368 | mace_statistics mace_stats; /* MACE chip statistics counters */ |
@@ -417,8 +417,8 @@ INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); | |||
417 | Function Prototypes | 417 | Function Prototypes |
418 | ---------------------------------------------------------------------------- */ | 418 | ---------------------------------------------------------------------------- */ |
419 | 419 | ||
420 | static void nmclan_config(dev_link_t *link); | 420 | static int nmclan_config(struct pcmcia_device *link); |
421 | static void nmclan_release(dev_link_t *link); | 421 | static void nmclan_release(struct pcmcia_device *link); |
422 | 422 | ||
423 | static void nmclan_reset(struct net_device *dev); | 423 | static void nmclan_reset(struct net_device *dev); |
424 | static int mace_config(struct net_device *dev, struct ifmap *map); | 424 | static int mace_config(struct net_device *dev, struct ifmap *map); |
@@ -443,10 +443,9 @@ nmclan_attach | |||
443 | Services. | 443 | Services. |
444 | ---------------------------------------------------------------------------- */ | 444 | ---------------------------------------------------------------------------- */ |
445 | 445 | ||
446 | static int nmclan_attach(struct pcmcia_device *p_dev) | 446 | static int nmclan_probe(struct pcmcia_device *link) |
447 | { | 447 | { |
448 | mace_private *lp; | 448 | mace_private *lp; |
449 | dev_link_t *link; | ||
450 | struct net_device *dev; | 449 | struct net_device *dev; |
451 | 450 | ||
452 | DEBUG(0, "nmclan_attach()\n"); | 451 | DEBUG(0, "nmclan_attach()\n"); |
@@ -457,7 +456,7 @@ static int nmclan_attach(struct pcmcia_device *p_dev) | |||
457 | if (!dev) | 456 | if (!dev) |
458 | return -ENOMEM; | 457 | return -ENOMEM; |
459 | lp = netdev_priv(dev); | 458 | lp = netdev_priv(dev); |
460 | link = &lp->link; | 459 | lp->p_dev = link; |
461 | link->priv = dev; | 460 | link->priv = dev; |
462 | 461 | ||
463 | spin_lock_init(&lp->bank_lock); | 462 | spin_lock_init(&lp->bank_lock); |
@@ -469,7 +468,6 @@ static int nmclan_attach(struct pcmcia_device *p_dev) | |||
469 | link->irq.Handler = &mace_interrupt; | 468 | link->irq.Handler = &mace_interrupt; |
470 | link->irq.Instance = dev; | 469 | link->irq.Instance = dev; |
471 | link->conf.Attributes = CONF_ENABLE_IRQ; | 470 | link->conf.Attributes = CONF_ENABLE_IRQ; |
472 | link->conf.Vcc = 50; | ||
473 | link->conf.IntType = INT_MEMORY_AND_IO; | 471 | link->conf.IntType = INT_MEMORY_AND_IO; |
474 | link->conf.ConfigIndex = 1; | 472 | link->conf.ConfigIndex = 1; |
475 | link->conf.Present = PRESENT_OPTION; | 473 | link->conf.Present = PRESENT_OPTION; |
@@ -489,13 +487,7 @@ static int nmclan_attach(struct pcmcia_device *p_dev) | |||
489 | dev->watchdog_timeo = TX_TIMEOUT; | 487 | dev->watchdog_timeo = TX_TIMEOUT; |
490 | #endif | 488 | #endif |
491 | 489 | ||
492 | link->handle = p_dev; | 490 | return nmclan_config(link); |
493 | p_dev->instance = link; | ||
494 | |||
495 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
496 | nmclan_config(link); | ||
497 | |||
498 | return 0; | ||
499 | } /* nmclan_attach */ | 491 | } /* nmclan_attach */ |
500 | 492 | ||
501 | /* ---------------------------------------------------------------------------- | 493 | /* ---------------------------------------------------------------------------- |
@@ -506,18 +498,16 @@ nmclan_detach | |||
506 | when the device is released. | 498 | when the device is released. |
507 | ---------------------------------------------------------------------------- */ | 499 | ---------------------------------------------------------------------------- */ |
508 | 500 | ||
509 | static void nmclan_detach(struct pcmcia_device *p_dev) | 501 | static void nmclan_detach(struct pcmcia_device *link) |
510 | { | 502 | { |
511 | dev_link_t *link = dev_to_instance(p_dev); | ||
512 | struct net_device *dev = link->priv; | 503 | struct net_device *dev = link->priv; |
513 | 504 | ||
514 | DEBUG(0, "nmclan_detach(0x%p)\n", link); | 505 | DEBUG(0, "nmclan_detach(0x%p)\n", link); |
515 | 506 | ||
516 | if (link->dev) | 507 | if (link->dev_node) |
517 | unregister_netdev(dev); | 508 | unregister_netdev(dev); |
518 | 509 | ||
519 | if (link->state & DEV_CONFIG) | 510 | nmclan_release(link); |
520 | nmclan_release(link); | ||
521 | 511 | ||
522 | free_netdev(dev); | 512 | free_netdev(dev); |
523 | } /* nmclan_detach */ | 513 | } /* nmclan_detach */ |
@@ -661,9 +651,8 @@ nmclan_config | |||
661 | #define CS_CHECK(fn, ret) \ | 651 | #define CS_CHECK(fn, ret) \ |
662 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 652 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
663 | 653 | ||
664 | static void nmclan_config(dev_link_t *link) | 654 | static int nmclan_config(struct pcmcia_device *link) |
665 | { | 655 | { |
666 | client_handle_t handle = link->handle; | ||
667 | struct net_device *dev = link->priv; | 656 | struct net_device *dev = link->priv; |
668 | mace_private *lp = netdev_priv(dev); | 657 | mace_private *lp = netdev_priv(dev); |
669 | tuple_t tuple; | 658 | tuple_t tuple; |
@@ -679,17 +668,14 @@ static void nmclan_config(dev_link_t *link) | |||
679 | tuple.TupleDataMax = 64; | 668 | tuple.TupleDataMax = 64; |
680 | tuple.TupleOffset = 0; | 669 | tuple.TupleOffset = 0; |
681 | tuple.DesiredTuple = CISTPL_CONFIG; | 670 | tuple.DesiredTuple = CISTPL_CONFIG; |
682 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 671 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
683 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 672 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
684 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 673 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
685 | link->conf.ConfigBase = parse.config.base; | 674 | link->conf.ConfigBase = parse.config.base; |
686 | 675 | ||
687 | /* Configure card */ | 676 | CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); |
688 | link->state |= DEV_CONFIG; | 677 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
689 | 678 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); | |
690 | CS_CHECK(RequestIO, pcmcia_request_io(handle, &link->io)); | ||
691 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | ||
692 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | ||
693 | dev->irq = link->irq.AssignedIRQ; | 679 | dev->irq = link->irq.AssignedIRQ; |
694 | dev->base_addr = link->io.BasePort1; | 680 | dev->base_addr = link->io.BasePort1; |
695 | 681 | ||
@@ -700,8 +686,8 @@ static void nmclan_config(dev_link_t *link) | |||
700 | tuple.TupleData = buf; | 686 | tuple.TupleData = buf; |
701 | tuple.TupleDataMax = 64; | 687 | tuple.TupleDataMax = 64; |
702 | tuple.TupleOffset = 0; | 688 | tuple.TupleOffset = 0; |
703 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 689 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
704 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 690 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
705 | memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN); | 691 | memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN); |
706 | 692 | ||
707 | /* Verify configuration by reading the MACE ID. */ | 693 | /* Verify configuration by reading the MACE ID. */ |
@@ -716,8 +702,7 @@ static void nmclan_config(dev_link_t *link) | |||
716 | } else { | 702 | } else { |
717 | printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should" | 703 | printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should" |
718 | " be 0x40 0x?9\n", sig[0], sig[1]); | 704 | " be 0x40 0x?9\n", sig[0], sig[1]); |
719 | link->state &= ~DEV_CONFIG_PENDING; | 705 | return -ENODEV; |
720 | return; | ||
721 | } | 706 | } |
722 | } | 707 | } |
723 | 708 | ||
@@ -730,14 +715,13 @@ static void nmclan_config(dev_link_t *link) | |||
730 | else | 715 | else |
731 | printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n"); | 716 | printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n"); |
732 | 717 | ||
733 | link->dev = &lp->node; | 718 | link->dev_node = &lp->node; |
734 | link->state &= ~DEV_CONFIG_PENDING; | 719 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
735 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
736 | 720 | ||
737 | i = register_netdev(dev); | 721 | i = register_netdev(dev); |
738 | if (i != 0) { | 722 | if (i != 0) { |
739 | printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n"); | 723 | printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n"); |
740 | link->dev = NULL; | 724 | link->dev_node = NULL; |
741 | goto failed; | 725 | goto failed; |
742 | } | 726 | } |
743 | 727 | ||
@@ -747,14 +731,13 @@ static void nmclan_config(dev_link_t *link) | |||
747 | dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]); | 731 | dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]); |
748 | for (i = 0; i < 6; i++) | 732 | for (i = 0; i < 6; i++) |
749 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); | 733 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); |
750 | return; | 734 | return 0; |
751 | 735 | ||
752 | cs_failed: | 736 | cs_failed: |
753 | cs_error(link->handle, last_fn, last_ret); | 737 | cs_error(link, last_fn, last_ret); |
754 | failed: | 738 | failed: |
755 | nmclan_release(link); | 739 | nmclan_release(link); |
756 | return; | 740 | return -ENODEV; |
757 | |||
758 | } /* nmclan_config */ | 741 | } /* nmclan_config */ |
759 | 742 | ||
760 | /* ---------------------------------------------------------------------------- | 743 | /* ---------------------------------------------------------------------------- |
@@ -763,46 +746,29 @@ nmclan_release | |||
763 | net device, and release the PCMCIA configuration. If the device | 746 | net device, and release the PCMCIA configuration. If the device |
764 | is still open, this will be postponed until it is closed. | 747 | is still open, this will be postponed until it is closed. |
765 | ---------------------------------------------------------------------------- */ | 748 | ---------------------------------------------------------------------------- */ |
766 | static void nmclan_release(dev_link_t *link) | 749 | static void nmclan_release(struct pcmcia_device *link) |
767 | { | 750 | { |
768 | 751 | DEBUG(0, "nmclan_release(0x%p)\n", link); | |
769 | DEBUG(0, "nmclan_release(0x%p)\n", link); | 752 | pcmcia_disable_device(link); |
770 | |||
771 | pcmcia_release_configuration(link->handle); | ||
772 | pcmcia_release_io(link->handle, &link->io); | ||
773 | pcmcia_release_irq(link->handle, &link->irq); | ||
774 | |||
775 | link->state &= ~DEV_CONFIG; | ||
776 | } | 753 | } |
777 | 754 | ||
778 | static int nmclan_suspend(struct pcmcia_device *p_dev) | 755 | static int nmclan_suspend(struct pcmcia_device *link) |
779 | { | 756 | { |
780 | dev_link_t *link = dev_to_instance(p_dev); | ||
781 | struct net_device *dev = link->priv; | 757 | struct net_device *dev = link->priv; |
782 | 758 | ||
783 | link->state |= DEV_SUSPEND; | 759 | if (link->open) |
784 | if (link->state & DEV_CONFIG) { | 760 | netif_device_detach(dev); |
785 | if (link->open) | ||
786 | netif_device_detach(dev); | ||
787 | pcmcia_release_configuration(link->handle); | ||
788 | } | ||
789 | |||
790 | 761 | ||
791 | return 0; | 762 | return 0; |
792 | } | 763 | } |
793 | 764 | ||
794 | static int nmclan_resume(struct pcmcia_device *p_dev) | 765 | static int nmclan_resume(struct pcmcia_device *link) |
795 | { | 766 | { |
796 | dev_link_t *link = dev_to_instance(p_dev); | ||
797 | struct net_device *dev = link->priv; | 767 | struct net_device *dev = link->priv; |
798 | 768 | ||
799 | link->state &= ~DEV_SUSPEND; | 769 | if (link->open) { |
800 | if (link->state & DEV_CONFIG) { | 770 | nmclan_reset(dev); |
801 | pcmcia_request_configuration(link->handle, &link->conf); | 771 | netif_device_attach(dev); |
802 | if (link->open) { | ||
803 | nmclan_reset(dev); | ||
804 | netif_device_attach(dev); | ||
805 | } | ||
806 | } | 772 | } |
807 | 773 | ||
808 | return 0; | 774 | return 0; |
@@ -818,7 +784,7 @@ static void nmclan_reset(struct net_device *dev) | |||
818 | mace_private *lp = netdev_priv(dev); | 784 | mace_private *lp = netdev_priv(dev); |
819 | 785 | ||
820 | #if RESET_XILINX | 786 | #if RESET_XILINX |
821 | dev_link_t *link = &lp->link; | 787 | struct pcmcia_device *link = &lp->link; |
822 | conf_reg_t reg; | 788 | conf_reg_t reg; |
823 | u_long OrigCorValue; | 789 | u_long OrigCorValue; |
824 | 790 | ||
@@ -827,7 +793,7 @@ static void nmclan_reset(struct net_device *dev) | |||
827 | reg.Action = CS_READ; | 793 | reg.Action = CS_READ; |
828 | reg.Offset = CISREG_COR; | 794 | reg.Offset = CISREG_COR; |
829 | reg.Value = 0; | 795 | reg.Value = 0; |
830 | pcmcia_access_configuration_register(link->handle, ®); | 796 | pcmcia_access_configuration_register(link, ®); |
831 | OrigCorValue = reg.Value; | 797 | OrigCorValue = reg.Value; |
832 | 798 | ||
833 | /* Reset Xilinx */ | 799 | /* Reset Xilinx */ |
@@ -836,12 +802,12 @@ static void nmclan_reset(struct net_device *dev) | |||
836 | DEBUG(1, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n", | 802 | DEBUG(1, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n", |
837 | OrigCorValue); | 803 | OrigCorValue); |
838 | reg.Value = COR_SOFT_RESET; | 804 | reg.Value = COR_SOFT_RESET; |
839 | pcmcia_access_configuration_register(link->handle, ®); | 805 | pcmcia_access_configuration_register(link, ®); |
840 | /* Need to wait for 20 ms for PCMCIA to finish reset. */ | 806 | /* Need to wait for 20 ms for PCMCIA to finish reset. */ |
841 | 807 | ||
842 | /* Restore original COR configuration index */ | 808 | /* Restore original COR configuration index */ |
843 | reg.Value = COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK); | 809 | reg.Value = COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK); |
844 | pcmcia_access_configuration_register(link->handle, ®); | 810 | pcmcia_access_configuration_register(link, ®); |
845 | /* Xilinx is now completely reset along with the MACE chip. */ | 811 | /* Xilinx is now completely reset along with the MACE chip. */ |
846 | lp->tx_free_frames=AM2150_MAX_TX_FRAMES; | 812 | lp->tx_free_frames=AM2150_MAX_TX_FRAMES; |
847 | 813 | ||
@@ -885,9 +851,9 @@ static int mace_open(struct net_device *dev) | |||
885 | { | 851 | { |
886 | kio_addr_t ioaddr = dev->base_addr; | 852 | kio_addr_t ioaddr = dev->base_addr; |
887 | mace_private *lp = netdev_priv(dev); | 853 | mace_private *lp = netdev_priv(dev); |
888 | dev_link_t *link = &lp->link; | 854 | struct pcmcia_device *link = lp->p_dev; |
889 | 855 | ||
890 | if (!DEV_OK(link)) | 856 | if (!pcmcia_dev_present(link)) |
891 | return -ENODEV; | 857 | return -ENODEV; |
892 | 858 | ||
893 | link->open++; | 859 | link->open++; |
@@ -908,7 +874,7 @@ static int mace_close(struct net_device *dev) | |||
908 | { | 874 | { |
909 | kio_addr_t ioaddr = dev->base_addr; | 875 | kio_addr_t ioaddr = dev->base_addr; |
910 | mace_private *lp = netdev_priv(dev); | 876 | mace_private *lp = netdev_priv(dev); |
911 | dev_link_t *link = &lp->link; | 877 | struct pcmcia_device *link = lp->p_dev; |
912 | 878 | ||
913 | DEBUG(2, "%s: shutting down ethercard.\n", dev->name); | 879 | DEBUG(2, "%s: shutting down ethercard.\n", dev->name); |
914 | 880 | ||
@@ -963,12 +929,12 @@ mace_start_xmit | |||
963 | static void mace_tx_timeout(struct net_device *dev) | 929 | static void mace_tx_timeout(struct net_device *dev) |
964 | { | 930 | { |
965 | mace_private *lp = netdev_priv(dev); | 931 | mace_private *lp = netdev_priv(dev); |
966 | dev_link_t *link = &lp->link; | 932 | struct pcmcia_device *link = lp->p_dev; |
967 | 933 | ||
968 | printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name); | 934 | printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name); |
969 | #if RESET_ON_TIMEOUT | 935 | #if RESET_ON_TIMEOUT |
970 | printk("resetting card\n"); | 936 | printk("resetting card\n"); |
971 | pcmcia_reset_card(link->handle, NULL); | 937 | pcmcia_reset_card(link, NULL); |
972 | #else /* #if RESET_ON_TIMEOUT */ | 938 | #else /* #if RESET_ON_TIMEOUT */ |
973 | printk("NOT resetting card\n"); | 939 | printk("NOT resetting card\n"); |
974 | #endif /* #if RESET_ON_TIMEOUT */ | 940 | #endif /* #if RESET_ON_TIMEOUT */ |
@@ -1635,7 +1601,7 @@ static struct pcmcia_driver nmclan_cs_driver = { | |||
1635 | .drv = { | 1601 | .drv = { |
1636 | .name = "nmclan_cs", | 1602 | .name = "nmclan_cs", |
1637 | }, | 1603 | }, |
1638 | .probe = nmclan_attach, | 1604 | .probe = nmclan_probe, |
1639 | .remove = nmclan_detach, | 1605 | .remove = nmclan_detach, |
1640 | .id_table = nmclan_ids, | 1606 | .id_table = nmclan_ids, |
1641 | .suspend = nmclan_suspend, | 1607 | .suspend = nmclan_suspend, |
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index b46e5f703efa..d090df413049 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c | |||
@@ -103,8 +103,8 @@ module_param_array(hw_addr, int, NULL, 0); | |||
103 | /*====================================================================*/ | 103 | /*====================================================================*/ |
104 | 104 | ||
105 | static void mii_phy_probe(struct net_device *dev); | 105 | static void mii_phy_probe(struct net_device *dev); |
106 | static void pcnet_config(dev_link_t *link); | 106 | static int pcnet_config(struct pcmcia_device *link); |
107 | static void pcnet_release(dev_link_t *link); | 107 | static void pcnet_release(struct pcmcia_device *link); |
108 | static int pcnet_open(struct net_device *dev); | 108 | static int pcnet_open(struct net_device *dev); |
109 | static int pcnet_close(struct net_device *dev); | 109 | static int pcnet_close(struct net_device *dev); |
110 | static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 110 | static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
@@ -113,9 +113,9 @@ static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs); | |||
113 | static void ei_watchdog(u_long arg); | 113 | static void ei_watchdog(u_long arg); |
114 | static void pcnet_reset_8390(struct net_device *dev); | 114 | static void pcnet_reset_8390(struct net_device *dev); |
115 | static int set_config(struct net_device *dev, struct ifmap *map); | 115 | static int set_config(struct net_device *dev, struct ifmap *map); |
116 | static int setup_shmem_window(dev_link_t *link, int start_pg, | 116 | static int setup_shmem_window(struct pcmcia_device *link, int start_pg, |
117 | int stop_pg, int cm_offset); | 117 | int stop_pg, int cm_offset); |
118 | static int setup_dma_config(dev_link_t *link, int start_pg, | 118 | static int setup_dma_config(struct pcmcia_device *link, int start_pg, |
119 | int stop_pg); | 119 | int stop_pg); |
120 | 120 | ||
121 | static void pcnet_detach(struct pcmcia_device *p_dev); | 121 | static void pcnet_detach(struct pcmcia_device *p_dev); |
@@ -214,7 +214,7 @@ static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII }; | |||
214 | static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII }; | 214 | static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII }; |
215 | 215 | ||
216 | typedef struct pcnet_dev_t { | 216 | typedef struct pcnet_dev_t { |
217 | dev_link_t link; | 217 | struct pcmcia_device *p_dev; |
218 | dev_node_t node; | 218 | dev_node_t node; |
219 | u_int flags; | 219 | u_int flags; |
220 | void __iomem *base; | 220 | void __iomem *base; |
@@ -240,10 +240,9 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev) | |||
240 | 240 | ||
241 | ======================================================================*/ | 241 | ======================================================================*/ |
242 | 242 | ||
243 | static int pcnet_probe(struct pcmcia_device *p_dev) | 243 | static int pcnet_probe(struct pcmcia_device *link) |
244 | { | 244 | { |
245 | pcnet_dev_t *info; | 245 | pcnet_dev_t *info; |
246 | dev_link_t *link; | ||
247 | struct net_device *dev; | 246 | struct net_device *dev; |
248 | 247 | ||
249 | DEBUG(0, "pcnet_attach()\n"); | 248 | DEBUG(0, "pcnet_attach()\n"); |
@@ -252,7 +251,7 @@ static int pcnet_probe(struct pcmcia_device *p_dev) | |||
252 | dev = __alloc_ei_netdev(sizeof(pcnet_dev_t)); | 251 | dev = __alloc_ei_netdev(sizeof(pcnet_dev_t)); |
253 | if (!dev) return -ENOMEM; | 252 | if (!dev) return -ENOMEM; |
254 | info = PRIV(dev); | 253 | info = PRIV(dev); |
255 | link = &info->link; | 254 | info->p_dev = link; |
256 | link->priv = dev; | 255 | link->priv = dev; |
257 | 256 | ||
258 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 257 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
@@ -265,13 +264,7 @@ static int pcnet_probe(struct pcmcia_device *p_dev) | |||
265 | dev->stop = &pcnet_close; | 264 | dev->stop = &pcnet_close; |
266 | dev->set_config = &set_config; | 265 | dev->set_config = &set_config; |
267 | 266 | ||
268 | link->handle = p_dev; | 267 | return pcnet_config(link); |
269 | p_dev->instance = link; | ||
270 | |||
271 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
272 | pcnet_config(link); | ||
273 | |||
274 | return 0; | ||
275 | } /* pcnet_attach */ | 268 | } /* pcnet_attach */ |
276 | 269 | ||
277 | /*====================================================================== | 270 | /*====================================================================== |
@@ -283,18 +276,16 @@ static int pcnet_probe(struct pcmcia_device *p_dev) | |||
283 | 276 | ||
284 | ======================================================================*/ | 277 | ======================================================================*/ |
285 | 278 | ||
286 | static void pcnet_detach(struct pcmcia_device *p_dev) | 279 | static void pcnet_detach(struct pcmcia_device *link) |
287 | { | 280 | { |
288 | dev_link_t *link = dev_to_instance(p_dev); | ||
289 | struct net_device *dev = link->priv; | 281 | struct net_device *dev = link->priv; |
290 | 282 | ||
291 | DEBUG(0, "pcnet_detach(0x%p)\n", link); | 283 | DEBUG(0, "pcnet_detach(0x%p)\n", link); |
292 | 284 | ||
293 | if (link->dev) | 285 | if (link->dev_node) |
294 | unregister_netdev(dev); | 286 | unregister_netdev(dev); |
295 | 287 | ||
296 | if (link->state & DEV_CONFIG) | 288 | pcnet_release(link); |
297 | pcnet_release(link); | ||
298 | 289 | ||
299 | free_netdev(dev); | 290 | free_netdev(dev); |
300 | } /* pcnet_detach */ | 291 | } /* pcnet_detach */ |
@@ -306,7 +297,7 @@ static void pcnet_detach(struct pcmcia_device *p_dev) | |||
306 | 297 | ||
307 | ======================================================================*/ | 298 | ======================================================================*/ |
308 | 299 | ||
309 | static hw_info_t *get_hwinfo(dev_link_t *link) | 300 | static hw_info_t *get_hwinfo(struct pcmcia_device *link) |
310 | { | 301 | { |
311 | struct net_device *dev = link->priv; | 302 | struct net_device *dev = link->priv; |
312 | win_req_t req; | 303 | win_req_t req; |
@@ -318,9 +309,9 @@ static hw_info_t *get_hwinfo(dev_link_t *link) | |||
318 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 309 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; |
319 | req.Base = 0; req.Size = 0; | 310 | req.Base = 0; req.Size = 0; |
320 | req.AccessSpeed = 0; | 311 | req.AccessSpeed = 0; |
321 | i = pcmcia_request_window(&link->handle, &req, &link->win); | 312 | i = pcmcia_request_window(&link, &req, &link->win); |
322 | if (i != CS_SUCCESS) { | 313 | if (i != CS_SUCCESS) { |
323 | cs_error(link->handle, RequestWindow, i); | 314 | cs_error(link, RequestWindow, i); |
324 | return NULL; | 315 | return NULL; |
325 | } | 316 | } |
326 | 317 | ||
@@ -343,7 +334,7 @@ static hw_info_t *get_hwinfo(dev_link_t *link) | |||
343 | iounmap(virt); | 334 | iounmap(virt); |
344 | j = pcmcia_release_window(link->win); | 335 | j = pcmcia_release_window(link->win); |
345 | if (j != CS_SUCCESS) | 336 | if (j != CS_SUCCESS) |
346 | cs_error(link->handle, ReleaseWindow, j); | 337 | cs_error(link, ReleaseWindow, j); |
347 | return (i < NR_INFO) ? hw_info+i : NULL; | 338 | return (i < NR_INFO) ? hw_info+i : NULL; |
348 | } /* get_hwinfo */ | 339 | } /* get_hwinfo */ |
349 | 340 | ||
@@ -355,7 +346,7 @@ static hw_info_t *get_hwinfo(dev_link_t *link) | |||
355 | 346 | ||
356 | ======================================================================*/ | 347 | ======================================================================*/ |
357 | 348 | ||
358 | static hw_info_t *get_prom(dev_link_t *link) | 349 | static hw_info_t *get_prom(struct pcmcia_device *link) |
359 | { | 350 | { |
360 | struct net_device *dev = link->priv; | 351 | struct net_device *dev = link->priv; |
361 | kio_addr_t ioaddr = dev->base_addr; | 352 | kio_addr_t ioaddr = dev->base_addr; |
@@ -409,7 +400,7 @@ static hw_info_t *get_prom(dev_link_t *link) | |||
409 | 400 | ||
410 | ======================================================================*/ | 401 | ======================================================================*/ |
411 | 402 | ||
412 | static hw_info_t *get_dl10019(dev_link_t *link) | 403 | static hw_info_t *get_dl10019(struct pcmcia_device *link) |
413 | { | 404 | { |
414 | struct net_device *dev = link->priv; | 405 | struct net_device *dev = link->priv; |
415 | int i; | 406 | int i; |
@@ -431,7 +422,7 @@ static hw_info_t *get_dl10019(dev_link_t *link) | |||
431 | 422 | ||
432 | ======================================================================*/ | 423 | ======================================================================*/ |
433 | 424 | ||
434 | static hw_info_t *get_ax88190(dev_link_t *link) | 425 | static hw_info_t *get_ax88190(struct pcmcia_device *link) |
435 | { | 426 | { |
436 | struct net_device *dev = link->priv; | 427 | struct net_device *dev = link->priv; |
437 | kio_addr_t ioaddr = dev->base_addr; | 428 | kio_addr_t ioaddr = dev->base_addr; |
@@ -464,7 +455,7 @@ static hw_info_t *get_ax88190(dev_link_t *link) | |||
464 | 455 | ||
465 | ======================================================================*/ | 456 | ======================================================================*/ |
466 | 457 | ||
467 | static hw_info_t *get_hwired(dev_link_t *link) | 458 | static hw_info_t *get_hwired(struct pcmcia_device *link) |
468 | { | 459 | { |
469 | struct net_device *dev = link->priv; | 460 | struct net_device *dev = link->priv; |
470 | int i; | 461 | int i; |
@@ -491,7 +482,7 @@ static hw_info_t *get_hwired(dev_link_t *link) | |||
491 | #define CS_CHECK(fn, ret) \ | 482 | #define CS_CHECK(fn, ret) \ |
492 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 483 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
493 | 484 | ||
494 | static int try_io_port(dev_link_t *link) | 485 | static int try_io_port(struct pcmcia_device *link) |
495 | { | 486 | { |
496 | int j, ret; | 487 | int j, ret; |
497 | if (link->io.NumPorts1 == 32) { | 488 | if (link->io.NumPorts1 == 32) { |
@@ -512,18 +503,17 @@ static int try_io_port(dev_link_t *link) | |||
512 | for (j = 0; j < 0x400; j += 0x20) { | 503 | for (j = 0; j < 0x400; j += 0x20) { |
513 | link->io.BasePort1 = j ^ 0x300; | 504 | link->io.BasePort1 = j ^ 0x300; |
514 | link->io.BasePort2 = (j ^ 0x300) + 0x10; | 505 | link->io.BasePort2 = (j ^ 0x300) + 0x10; |
515 | ret = pcmcia_request_io(link->handle, &link->io); | 506 | ret = pcmcia_request_io(link, &link->io); |
516 | if (ret == CS_SUCCESS) return ret; | 507 | if (ret == CS_SUCCESS) return ret; |
517 | } | 508 | } |
518 | return ret; | 509 | return ret; |
519 | } else { | 510 | } else { |
520 | return pcmcia_request_io(link->handle, &link->io); | 511 | return pcmcia_request_io(link, &link->io); |
521 | } | 512 | } |
522 | } | 513 | } |
523 | 514 | ||
524 | static void pcnet_config(dev_link_t *link) | 515 | static int pcnet_config(struct pcmcia_device *link) |
525 | { | 516 | { |
526 | client_handle_t handle = link->handle; | ||
527 | struct net_device *dev = link->priv; | 517 | struct net_device *dev = link->priv; |
528 | pcnet_dev_t *info = PRIV(dev); | 518 | pcnet_dev_t *info = PRIV(dev); |
529 | tuple_t tuple; | 519 | tuple_t tuple; |
@@ -531,7 +521,6 @@ static void pcnet_config(dev_link_t *link) | |||
531 | int i, last_ret, last_fn, start_pg, stop_pg, cm_offset; | 521 | int i, last_ret, last_fn, start_pg, stop_pg, cm_offset; |
532 | int manfid = 0, prodid = 0, has_shmem = 0; | 522 | int manfid = 0, prodid = 0, has_shmem = 0; |
533 | u_short buf[64]; | 523 | u_short buf[64]; |
534 | config_info_t conf; | ||
535 | hw_info_t *hw_info; | 524 | hw_info_t *hw_info; |
536 | 525 | ||
537 | DEBUG(0, "pcnet_config(0x%p)\n", link); | 526 | DEBUG(0, "pcnet_config(0x%p)\n", link); |
@@ -541,36 +530,29 @@ static void pcnet_config(dev_link_t *link) | |||
541 | tuple.TupleDataMax = sizeof(buf); | 530 | tuple.TupleDataMax = sizeof(buf); |
542 | tuple.TupleOffset = 0; | 531 | tuple.TupleOffset = 0; |
543 | tuple.DesiredTuple = CISTPL_CONFIG; | 532 | tuple.DesiredTuple = CISTPL_CONFIG; |
544 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 533 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
545 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 534 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
546 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 535 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
547 | link->conf.ConfigBase = parse.config.base; | 536 | link->conf.ConfigBase = parse.config.base; |
548 | link->conf.Present = parse.config.rmask[0]; | 537 | link->conf.Present = parse.config.rmask[0]; |
549 | 538 | ||
550 | /* Configure card */ | ||
551 | link->state |= DEV_CONFIG; | ||
552 | |||
553 | /* Look up current Vcc */ | ||
554 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); | ||
555 | link->conf.Vcc = conf.Vcc; | ||
556 | |||
557 | tuple.DesiredTuple = CISTPL_MANFID; | 539 | tuple.DesiredTuple = CISTPL_MANFID; |
558 | tuple.Attributes = TUPLE_RETURN_COMMON; | 540 | tuple.Attributes = TUPLE_RETURN_COMMON; |
559 | if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && | 541 | if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && |
560 | (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) { | 542 | (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) { |
561 | manfid = le16_to_cpu(buf[0]); | 543 | manfid = le16_to_cpu(buf[0]); |
562 | prodid = le16_to_cpu(buf[1]); | 544 | prodid = le16_to_cpu(buf[1]); |
563 | } | 545 | } |
564 | 546 | ||
565 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 547 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
566 | tuple.Attributes = 0; | 548 | tuple.Attributes = 0; |
567 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 549 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
568 | while (last_ret == CS_SUCCESS) { | 550 | while (last_ret == CS_SUCCESS) { |
569 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 551 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
570 | cistpl_io_t *io = &(parse.cftable_entry.io); | 552 | cistpl_io_t *io = &(parse.cftable_entry.io); |
571 | 553 | ||
572 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | 554 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || |
573 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0 || | 555 | pcmcia_parse_tuple(link, &tuple, &parse) != 0 || |
574 | cfg->index == 0 || cfg->io.nwin == 0) | 556 | cfg->index == 0 || cfg->io.nwin == 0) |
575 | goto next_entry; | 557 | goto next_entry; |
576 | 558 | ||
@@ -594,14 +576,14 @@ static void pcnet_config(dev_link_t *link) | |||
594 | if (last_ret == CS_SUCCESS) break; | 576 | if (last_ret == CS_SUCCESS) break; |
595 | } | 577 | } |
596 | next_entry: | 578 | next_entry: |
597 | last_ret = pcmcia_get_next_tuple(handle, &tuple); | 579 | last_ret = pcmcia_get_next_tuple(link, &tuple); |
598 | } | 580 | } |
599 | if (last_ret != CS_SUCCESS) { | 581 | if (last_ret != CS_SUCCESS) { |
600 | cs_error(handle, RequestIO, last_ret); | 582 | cs_error(link, RequestIO, last_ret); |
601 | goto failed; | 583 | goto failed; |
602 | } | 584 | } |
603 | 585 | ||
604 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | 586 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
605 | 587 | ||
606 | if (link->io.NumPorts2 == 8) { | 588 | if (link->io.NumPorts2 == 8) { |
607 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 589 | link->conf.Attributes |= CONF_ENABLE_SPKR; |
@@ -611,7 +593,7 @@ static void pcnet_config(dev_link_t *link) | |||
611 | (prodid == PRODID_IBM_HOME_AND_AWAY)) | 593 | (prodid == PRODID_IBM_HOME_AND_AWAY)) |
612 | link->conf.ConfigIndex |= 0x10; | 594 | link->conf.ConfigIndex |= 0x10; |
613 | 595 | ||
614 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | 596 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
615 | dev->irq = link->irq.AssignedIRQ; | 597 | dev->irq = link->irq.AssignedIRQ; |
616 | dev->base_addr = link->io.BasePort1; | 598 | dev->base_addr = link->io.BasePort1; |
617 | if (info->flags & HAS_MISC_REG) { | 599 | if (info->flags & HAS_MISC_REG) { |
@@ -679,9 +661,8 @@ static void pcnet_config(dev_link_t *link) | |||
679 | info->eth_phy = 0; | 661 | info->eth_phy = 0; |
680 | } | 662 | } |
681 | 663 | ||
682 | link->dev = &info->node; | 664 | link->dev_node = &info->node; |
683 | link->state &= ~DEV_CONFIG_PENDING; | 665 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
684 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
685 | 666 | ||
686 | #ifdef CONFIG_NET_POLL_CONTROLLER | 667 | #ifdef CONFIG_NET_POLL_CONTROLLER |
687 | dev->poll_controller = ei_poll; | 668 | dev->poll_controller = ei_poll; |
@@ -689,7 +670,7 @@ static void pcnet_config(dev_link_t *link) | |||
689 | 670 | ||
690 | if (register_netdev(dev) != 0) { | 671 | if (register_netdev(dev) != 0) { |
691 | printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n"); | 672 | printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n"); |
692 | link->dev = NULL; | 673 | link->dev_node = NULL; |
693 | goto failed; | 674 | goto failed; |
694 | } | 675 | } |
695 | 676 | ||
@@ -712,14 +693,13 @@ static void pcnet_config(dev_link_t *link) | |||
712 | printk(" hw_addr "); | 693 | printk(" hw_addr "); |
713 | for (i = 0; i < 6; i++) | 694 | for (i = 0; i < 6; i++) |
714 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); | 695 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); |
715 | return; | 696 | return 0; |
716 | 697 | ||
717 | cs_failed: | 698 | cs_failed: |
718 | cs_error(link->handle, last_fn, last_ret); | 699 | cs_error(link, last_fn, last_ret); |
719 | failed: | 700 | failed: |
720 | pcnet_release(link); | 701 | pcnet_release(link); |
721 | link->state &= ~DEV_CONFIG_PENDING; | 702 | return -ENODEV; |
722 | return; | ||
723 | } /* pcnet_config */ | 703 | } /* pcnet_config */ |
724 | 704 | ||
725 | /*====================================================================== | 705 | /*====================================================================== |
@@ -730,21 +710,16 @@ failed: | |||
730 | 710 | ||
731 | ======================================================================*/ | 711 | ======================================================================*/ |
732 | 712 | ||
733 | static void pcnet_release(dev_link_t *link) | 713 | static void pcnet_release(struct pcmcia_device *link) |
734 | { | 714 | { |
735 | pcnet_dev_t *info = PRIV(link->priv); | 715 | pcnet_dev_t *info = PRIV(link->priv); |
736 | 716 | ||
737 | DEBUG(0, "pcnet_release(0x%p)\n", link); | 717 | DEBUG(0, "pcnet_release(0x%p)\n", link); |
738 | 718 | ||
739 | if (info->flags & USE_SHMEM) { | 719 | if (info->flags & USE_SHMEM) |
740 | iounmap(info->base); | 720 | iounmap(info->base); |
741 | pcmcia_release_window(link->win); | ||
742 | } | ||
743 | pcmcia_release_configuration(link->handle); | ||
744 | pcmcia_release_io(link->handle, &link->io); | ||
745 | pcmcia_release_irq(link->handle, &link->irq); | ||
746 | 721 | ||
747 | link->state &= ~DEV_CONFIG; | 722 | pcmcia_disable_device(link); |
748 | } | 723 | } |
749 | 724 | ||
750 | /*====================================================================== | 725 | /*====================================================================== |
@@ -756,34 +731,24 @@ static void pcnet_release(dev_link_t *link) | |||
756 | 731 | ||
757 | ======================================================================*/ | 732 | ======================================================================*/ |
758 | 733 | ||
759 | static int pcnet_suspend(struct pcmcia_device *p_dev) | 734 | static int pcnet_suspend(struct pcmcia_device *link) |
760 | { | 735 | { |
761 | dev_link_t *link = dev_to_instance(p_dev); | ||
762 | struct net_device *dev = link->priv; | 736 | struct net_device *dev = link->priv; |
763 | 737 | ||
764 | link->state |= DEV_SUSPEND; | 738 | if (link->open) |
765 | if (link->state & DEV_CONFIG) { | 739 | netif_device_detach(dev); |
766 | if (link->open) | ||
767 | netif_device_detach(dev); | ||
768 | pcmcia_release_configuration(link->handle); | ||
769 | } | ||
770 | 740 | ||
771 | return 0; | 741 | return 0; |
772 | } | 742 | } |
773 | 743 | ||
774 | static int pcnet_resume(struct pcmcia_device *p_dev) | 744 | static int pcnet_resume(struct pcmcia_device *link) |
775 | { | 745 | { |
776 | dev_link_t *link = dev_to_instance(p_dev); | ||
777 | struct net_device *dev = link->priv; | 746 | struct net_device *dev = link->priv; |
778 | 747 | ||
779 | link->state &= ~DEV_SUSPEND; | 748 | if (link->open) { |
780 | if (link->state & DEV_CONFIG) { | 749 | pcnet_reset_8390(dev); |
781 | pcmcia_request_configuration(link->handle, &link->conf); | 750 | NS8390_init(dev, 1); |
782 | if (link->open) { | 751 | netif_device_attach(dev); |
783 | pcnet_reset_8390(dev); | ||
784 | NS8390_init(dev, 1); | ||
785 | netif_device_attach(dev); | ||
786 | } | ||
787 | } | 752 | } |
788 | 753 | ||
789 | return 0; | 754 | return 0; |
@@ -1023,11 +988,11 @@ static void mii_phy_probe(struct net_device *dev) | |||
1023 | static int pcnet_open(struct net_device *dev) | 988 | static int pcnet_open(struct net_device *dev) |
1024 | { | 989 | { |
1025 | pcnet_dev_t *info = PRIV(dev); | 990 | pcnet_dev_t *info = PRIV(dev); |
1026 | dev_link_t *link = &info->link; | 991 | struct pcmcia_device *link = info->p_dev; |
1027 | 992 | ||
1028 | DEBUG(2, "pcnet_open('%s')\n", dev->name); | 993 | DEBUG(2, "pcnet_open('%s')\n", dev->name); |
1029 | 994 | ||
1030 | if (!DEV_OK(link)) | 995 | if (!pcmcia_dev_present(link)) |
1031 | return -ENODEV; | 996 | return -ENODEV; |
1032 | 997 | ||
1033 | link->open++; | 998 | link->open++; |
@@ -1051,7 +1016,7 @@ static int pcnet_open(struct net_device *dev) | |||
1051 | static int pcnet_close(struct net_device *dev) | 1016 | static int pcnet_close(struct net_device *dev) |
1052 | { | 1017 | { |
1053 | pcnet_dev_t *info = PRIV(dev); | 1018 | pcnet_dev_t *info = PRIV(dev); |
1054 | dev_link_t *link = &info->link; | 1019 | struct pcmcia_device *link = info->p_dev; |
1055 | 1020 | ||
1056 | DEBUG(2, "pcnet_close('%s')\n", dev->name); | 1021 | DEBUG(2, "pcnet_close('%s')\n", dev->name); |
1057 | 1022 | ||
@@ -1429,7 +1394,7 @@ static void dma_block_output(struct net_device *dev, int count, | |||
1429 | 1394 | ||
1430 | /*====================================================================*/ | 1395 | /*====================================================================*/ |
1431 | 1396 | ||
1432 | static int setup_dma_config(dev_link_t *link, int start_pg, | 1397 | static int setup_dma_config(struct pcmcia_device *link, int start_pg, |
1433 | int stop_pg) | 1398 | int stop_pg) |
1434 | { | 1399 | { |
1435 | struct net_device *dev = link->priv; | 1400 | struct net_device *dev = link->priv; |
@@ -1532,7 +1497,7 @@ static void shmem_block_output(struct net_device *dev, int count, | |||
1532 | 1497 | ||
1533 | /*====================================================================*/ | 1498 | /*====================================================================*/ |
1534 | 1499 | ||
1535 | static int setup_shmem_window(dev_link_t *link, int start_pg, | 1500 | static int setup_shmem_window(struct pcmcia_device *link, int start_pg, |
1536 | int stop_pg, int cm_offset) | 1501 | int stop_pg, int cm_offset) |
1537 | { | 1502 | { |
1538 | struct net_device *dev = link->priv; | 1503 | struct net_device *dev = link->priv; |
@@ -1554,7 +1519,7 @@ static int setup_shmem_window(dev_link_t *link, int start_pg, | |||
1554 | req.Attributes |= WIN_USE_WAIT; | 1519 | req.Attributes |= WIN_USE_WAIT; |
1555 | req.Base = 0; req.Size = window_size; | 1520 | req.Base = 0; req.Size = window_size; |
1556 | req.AccessSpeed = mem_speed; | 1521 | req.AccessSpeed = mem_speed; |
1557 | CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); | 1522 | CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); |
1558 | 1523 | ||
1559 | mem.CardOffset = (start_pg << 8) + cm_offset; | 1524 | mem.CardOffset = (start_pg << 8) + cm_offset; |
1560 | offset = mem.CardOffset % window_size; | 1525 | offset = mem.CardOffset % window_size; |
@@ -1595,7 +1560,7 @@ static int setup_shmem_window(dev_link_t *link, int start_pg, | |||
1595 | return 0; | 1560 | return 0; |
1596 | 1561 | ||
1597 | cs_failed: | 1562 | cs_failed: |
1598 | cs_error(link->handle, last_fn, last_ret); | 1563 | cs_error(link, last_fn, last_ret); |
1599 | failed: | 1564 | failed: |
1600 | return 1; | 1565 | return 1; |
1601 | } | 1566 | } |
@@ -1674,6 +1639,7 @@ static struct pcmcia_device_id pcnet_ids[] = { | |||
1674 | PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), | 1639 | PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), |
1675 | PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), | 1640 | PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), |
1676 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), | 1641 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), |
1642 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d), | ||
1677 | PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), | 1643 | PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), |
1678 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa), | 1644 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa), |
1679 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9), | 1645 | PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9), |
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 8839c4faafd6..e74bf5014ef6 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include <pcmcia/cisreg.h> | 49 | #include <pcmcia/cisreg.h> |
50 | #include <pcmcia/ciscode.h> | 50 | #include <pcmcia/ciscode.h> |
51 | #include <pcmcia/ds.h> | 51 | #include <pcmcia/ds.h> |
52 | #include <pcmcia/ss.h> | ||
52 | 53 | ||
53 | #include <asm/io.h> | 54 | #include <asm/io.h> |
54 | #include <asm/system.h> | 55 | #include <asm/system.h> |
@@ -103,7 +104,7 @@ static const char *version = | |||
103 | #define MEMORY_WAIT_TIME 8 | 104 | #define MEMORY_WAIT_TIME 8 |
104 | 105 | ||
105 | struct smc_private { | 106 | struct smc_private { |
106 | dev_link_t link; | 107 | struct pcmcia_device *p_dev; |
107 | spinlock_t lock; | 108 | spinlock_t lock; |
108 | u_short manfid; | 109 | u_short manfid; |
109 | u_short cardid; | 110 | u_short cardid; |
@@ -278,8 +279,8 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002, | |||
278 | /*====================================================================*/ | 279 | /*====================================================================*/ |
279 | 280 | ||
280 | static void smc91c92_detach(struct pcmcia_device *p_dev); | 281 | static void smc91c92_detach(struct pcmcia_device *p_dev); |
281 | static void smc91c92_config(dev_link_t *link); | 282 | static int smc91c92_config(struct pcmcia_device *link); |
282 | static void smc91c92_release(dev_link_t *link); | 283 | static void smc91c92_release(struct pcmcia_device *link); |
283 | 284 | ||
284 | static int smc_open(struct net_device *dev); | 285 | static int smc_open(struct net_device *dev); |
285 | static int smc_close(struct net_device *dev); | 286 | static int smc_close(struct net_device *dev); |
@@ -308,10 +309,9 @@ static struct ethtool_ops ethtool_ops; | |||
308 | 309 | ||
309 | ======================================================================*/ | 310 | ======================================================================*/ |
310 | 311 | ||
311 | static int smc91c92_attach(struct pcmcia_device *p_dev) | 312 | static int smc91c92_probe(struct pcmcia_device *link) |
312 | { | 313 | { |
313 | struct smc_private *smc; | 314 | struct smc_private *smc; |
314 | dev_link_t *link; | ||
315 | struct net_device *dev; | 315 | struct net_device *dev; |
316 | 316 | ||
317 | DEBUG(0, "smc91c92_attach()\n"); | 317 | DEBUG(0, "smc91c92_attach()\n"); |
@@ -321,7 +321,7 @@ static int smc91c92_attach(struct pcmcia_device *p_dev) | |||
321 | if (!dev) | 321 | if (!dev) |
322 | return -ENOMEM; | 322 | return -ENOMEM; |
323 | smc = netdev_priv(dev); | 323 | smc = netdev_priv(dev); |
324 | link = &smc->link; | 324 | smc->p_dev = link; |
325 | link->priv = dev; | 325 | link->priv = dev; |
326 | 326 | ||
327 | spin_lock_init(&smc->lock); | 327 | spin_lock_init(&smc->lock); |
@@ -333,7 +333,6 @@ static int smc91c92_attach(struct pcmcia_device *p_dev) | |||
333 | link->irq.Handler = &smc_interrupt; | 333 | link->irq.Handler = &smc_interrupt; |
334 | link->irq.Instance = dev; | 334 | link->irq.Instance = dev; |
335 | link->conf.Attributes = CONF_ENABLE_IRQ; | 335 | link->conf.Attributes = CONF_ENABLE_IRQ; |
336 | link->conf.Vcc = 50; | ||
337 | link->conf.IntType = INT_MEMORY_AND_IO; | 336 | link->conf.IntType = INT_MEMORY_AND_IO; |
338 | 337 | ||
339 | /* The SMC91c92-specific entries in the device structure. */ | 338 | /* The SMC91c92-specific entries in the device structure. */ |
@@ -357,13 +356,7 @@ static int smc91c92_attach(struct pcmcia_device *p_dev) | |||
357 | smc->mii_if.phy_id_mask = 0x1f; | 356 | smc->mii_if.phy_id_mask = 0x1f; |
358 | smc->mii_if.reg_num_mask = 0x1f; | 357 | smc->mii_if.reg_num_mask = 0x1f; |
359 | 358 | ||
360 | link->handle = p_dev; | 359 | return smc91c92_config(link); |
361 | p_dev->instance = link; | ||
362 | |||
363 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
364 | smc91c92_config(link); | ||
365 | |||
366 | return 0; | ||
367 | } /* smc91c92_attach */ | 360 | } /* smc91c92_attach */ |
368 | 361 | ||
369 | /*====================================================================== | 362 | /*====================================================================== |
@@ -375,18 +368,16 @@ static int smc91c92_attach(struct pcmcia_device *p_dev) | |||
375 | 368 | ||
376 | ======================================================================*/ | 369 | ======================================================================*/ |
377 | 370 | ||
378 | static void smc91c92_detach(struct pcmcia_device *p_dev) | 371 | static void smc91c92_detach(struct pcmcia_device *link) |
379 | { | 372 | { |
380 | dev_link_t *link = dev_to_instance(p_dev); | ||
381 | struct net_device *dev = link->priv; | 373 | struct net_device *dev = link->priv; |
382 | 374 | ||
383 | DEBUG(0, "smc91c92_detach(0x%p)\n", link); | 375 | DEBUG(0, "smc91c92_detach(0x%p)\n", link); |
384 | 376 | ||
385 | if (link->dev) | 377 | if (link->dev_node) |
386 | unregister_netdev(dev); | 378 | unregister_netdev(dev); |
387 | 379 | ||
388 | if (link->state & DEV_CONFIG) | 380 | smc91c92_release(link); |
389 | smc91c92_release(link); | ||
390 | 381 | ||
391 | free_netdev(dev); | 382 | free_netdev(dev); |
392 | } /* smc91c92_detach */ | 383 | } /* smc91c92_detach */ |
@@ -414,7 +405,7 @@ static int cvt_ascii_address(struct net_device *dev, char *s) | |||
414 | 405 | ||
415 | /*====================================================================*/ | 406 | /*====================================================================*/ |
416 | 407 | ||
417 | static int first_tuple(client_handle_t handle, tuple_t *tuple, | 408 | static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, |
418 | cisparse_t *parse) | 409 | cisparse_t *parse) |
419 | { | 410 | { |
420 | int i; | 411 | int i; |
@@ -425,7 +416,7 @@ static int first_tuple(client_handle_t handle, tuple_t *tuple, | |||
425 | return pcmcia_parse_tuple(handle, tuple, parse); | 416 | return pcmcia_parse_tuple(handle, tuple, parse); |
426 | } | 417 | } |
427 | 418 | ||
428 | static int next_tuple(client_handle_t handle, tuple_t *tuple, | 419 | static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, |
429 | cisparse_t *parse) | 420 | cisparse_t *parse) |
430 | { | 421 | { |
431 | int i; | 422 | int i; |
@@ -447,7 +438,7 @@ static int next_tuple(client_handle_t handle, tuple_t *tuple, | |||
447 | 438 | ||
448 | ======================================================================*/ | 439 | ======================================================================*/ |
449 | 440 | ||
450 | static int mhz_3288_power(dev_link_t *link) | 441 | static int mhz_3288_power(struct pcmcia_device *link) |
451 | { | 442 | { |
452 | struct net_device *dev = link->priv; | 443 | struct net_device *dev = link->priv; |
453 | struct smc_private *smc = netdev_priv(dev); | 444 | struct smc_private *smc = netdev_priv(dev); |
@@ -469,7 +460,7 @@ static int mhz_3288_power(dev_link_t *link) | |||
469 | return 0; | 460 | return 0; |
470 | } | 461 | } |
471 | 462 | ||
472 | static int mhz_mfc_config(dev_link_t *link) | 463 | static int mhz_mfc_config(struct pcmcia_device *link) |
473 | { | 464 | { |
474 | struct net_device *dev = link->priv; | 465 | struct net_device *dev = link->priv; |
475 | struct smc_private *smc = netdev_priv(dev); | 466 | struct smc_private *smc = netdev_priv(dev); |
@@ -504,7 +495,7 @@ static int mhz_mfc_config(dev_link_t *link) | |||
504 | tuple->TupleDataMax = 255; | 495 | tuple->TupleDataMax = 255; |
505 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; | 496 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; |
506 | 497 | ||
507 | i = first_tuple(link->handle, tuple, parse); | 498 | i = first_tuple(link, tuple, parse); |
508 | /* The Megahertz combo cards have modem-like CIS entries, so | 499 | /* The Megahertz combo cards have modem-like CIS entries, so |
509 | we have to explicitly try a bunch of port combinations. */ | 500 | we have to explicitly try a bunch of port combinations. */ |
510 | while (i == CS_SUCCESS) { | 501 | while (i == CS_SUCCESS) { |
@@ -513,11 +504,11 @@ static int mhz_mfc_config(dev_link_t *link) | |||
513 | for (k = 0; k < 0x400; k += 0x10) { | 504 | for (k = 0; k < 0x400; k += 0x10) { |
514 | if (k & 0x80) continue; | 505 | if (k & 0x80) continue; |
515 | link->io.BasePort1 = k ^ 0x300; | 506 | link->io.BasePort1 = k ^ 0x300; |
516 | i = pcmcia_request_io(link->handle, &link->io); | 507 | i = pcmcia_request_io(link, &link->io); |
517 | if (i == CS_SUCCESS) break; | 508 | if (i == CS_SUCCESS) break; |
518 | } | 509 | } |
519 | if (i == CS_SUCCESS) break; | 510 | if (i == CS_SUCCESS) break; |
520 | i = next_tuple(link->handle, tuple, parse); | 511 | i = next_tuple(link, tuple, parse); |
521 | } | 512 | } |
522 | if (i != CS_SUCCESS) | 513 | if (i != CS_SUCCESS) |
523 | goto free_cfg_mem; | 514 | goto free_cfg_mem; |
@@ -527,7 +518,7 @@ static int mhz_mfc_config(dev_link_t *link) | |||
527 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 518 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; |
528 | req.Base = req.Size = 0; | 519 | req.Base = req.Size = 0; |
529 | req.AccessSpeed = 0; | 520 | req.AccessSpeed = 0; |
530 | i = pcmcia_request_window(&link->handle, &req, &link->win); | 521 | i = pcmcia_request_window(&link, &req, &link->win); |
531 | if (i != CS_SUCCESS) | 522 | if (i != CS_SUCCESS) |
532 | goto free_cfg_mem; | 523 | goto free_cfg_mem; |
533 | smc->base = ioremap(req.Base, req.Size); | 524 | smc->base = ioremap(req.Base, req.Size); |
@@ -546,9 +537,8 @@ free_cfg_mem: | |||
546 | return i; | 537 | return i; |
547 | } | 538 | } |
548 | 539 | ||
549 | static int mhz_setup(dev_link_t *link) | 540 | static int mhz_setup(struct pcmcia_device *link) |
550 | { | 541 | { |
551 | client_handle_t handle = link->handle; | ||
552 | struct net_device *dev = link->priv; | 542 | struct net_device *dev = link->priv; |
553 | struct smc_cfg_mem *cfg_mem; | 543 | struct smc_cfg_mem *cfg_mem; |
554 | tuple_t *tuple; | 544 | tuple_t *tuple; |
@@ -571,13 +561,13 @@ static int mhz_setup(dev_link_t *link) | |||
571 | /* Read the station address from the CIS. It is stored as the last | 561 | /* Read the station address from the CIS. It is stored as the last |
572 | (fourth) string in the Version 1 Version/ID tuple. */ | 562 | (fourth) string in the Version 1 Version/ID tuple. */ |
573 | tuple->DesiredTuple = CISTPL_VERS_1; | 563 | tuple->DesiredTuple = CISTPL_VERS_1; |
574 | if (first_tuple(handle, tuple, parse) != CS_SUCCESS) { | 564 | if (first_tuple(link, tuple, parse) != CS_SUCCESS) { |
575 | rc = -1; | 565 | rc = -1; |
576 | goto free_cfg_mem; | 566 | goto free_cfg_mem; |
577 | } | 567 | } |
578 | /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ | 568 | /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ |
579 | if (next_tuple(handle, tuple, parse) != CS_SUCCESS) | 569 | if (next_tuple(link, tuple, parse) != CS_SUCCESS) |
580 | first_tuple(handle, tuple, parse); | 570 | first_tuple(link, tuple, parse); |
581 | if (parse->version_1.ns > 3) { | 571 | if (parse->version_1.ns > 3) { |
582 | station_addr = parse->version_1.str + parse->version_1.ofs[3]; | 572 | station_addr = parse->version_1.str + parse->version_1.ofs[3]; |
583 | if (cvt_ascii_address(dev, station_addr) == 0) { | 573 | if (cvt_ascii_address(dev, station_addr) == 0) { |
@@ -588,11 +578,11 @@ static int mhz_setup(dev_link_t *link) | |||
588 | 578 | ||
589 | /* Another possibility: for the EM3288, in a special tuple */ | 579 | /* Another possibility: for the EM3288, in a special tuple */ |
590 | tuple->DesiredTuple = 0x81; | 580 | tuple->DesiredTuple = 0x81; |
591 | if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) { | 581 | if (pcmcia_get_first_tuple(link, tuple) != CS_SUCCESS) { |
592 | rc = -1; | 582 | rc = -1; |
593 | goto free_cfg_mem; | 583 | goto free_cfg_mem; |
594 | } | 584 | } |
595 | if (pcmcia_get_tuple_data(handle, tuple) != CS_SUCCESS) { | 585 | if (pcmcia_get_tuple_data(link, tuple) != CS_SUCCESS) { |
596 | rc = -1; | 586 | rc = -1; |
597 | goto free_cfg_mem; | 587 | goto free_cfg_mem; |
598 | } | 588 | } |
@@ -616,7 +606,7 @@ free_cfg_mem: | |||
616 | 606 | ||
617 | ======================================================================*/ | 607 | ======================================================================*/ |
618 | 608 | ||
619 | static void mot_config(dev_link_t *link) | 609 | static void mot_config(struct pcmcia_device *link) |
620 | { | 610 | { |
621 | struct net_device *dev = link->priv; | 611 | struct net_device *dev = link->priv; |
622 | struct smc_private *smc = netdev_priv(dev); | 612 | struct smc_private *smc = netdev_priv(dev); |
@@ -637,7 +627,7 @@ static void mot_config(dev_link_t *link) | |||
637 | mdelay(100); | 627 | mdelay(100); |
638 | } | 628 | } |
639 | 629 | ||
640 | static int mot_setup(dev_link_t *link) | 630 | static int mot_setup(struct pcmcia_device *link) |
641 | { | 631 | { |
642 | struct net_device *dev = link->priv; | 632 | struct net_device *dev = link->priv; |
643 | kio_addr_t ioaddr = dev->base_addr; | 633 | kio_addr_t ioaddr = dev->base_addr; |
@@ -671,7 +661,7 @@ static int mot_setup(dev_link_t *link) | |||
671 | 661 | ||
672 | /*====================================================================*/ | 662 | /*====================================================================*/ |
673 | 663 | ||
674 | static int smc_config(dev_link_t *link) | 664 | static int smc_config(struct pcmcia_device *link) |
675 | { | 665 | { |
676 | struct net_device *dev = link->priv; | 666 | struct net_device *dev = link->priv; |
677 | struct smc_cfg_mem *cfg_mem; | 667 | struct smc_cfg_mem *cfg_mem; |
@@ -696,16 +686,16 @@ static int smc_config(dev_link_t *link) | |||
696 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; | 686 | tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; |
697 | 687 | ||
698 | link->io.NumPorts1 = 16; | 688 | link->io.NumPorts1 = 16; |
699 | i = first_tuple(link->handle, tuple, parse); | 689 | i = first_tuple(link, tuple, parse); |
700 | while (i != CS_NO_MORE_ITEMS) { | 690 | while (i != CS_NO_MORE_ITEMS) { |
701 | if (i == CS_SUCCESS) { | 691 | if (i == CS_SUCCESS) { |
702 | link->conf.ConfigIndex = cf->index; | 692 | link->conf.ConfigIndex = cf->index; |
703 | link->io.BasePort1 = cf->io.win[0].base; | 693 | link->io.BasePort1 = cf->io.win[0].base; |
704 | link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; | 694 | link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK; |
705 | i = pcmcia_request_io(link->handle, &link->io); | 695 | i = pcmcia_request_io(link, &link->io); |
706 | if (i == CS_SUCCESS) break; | 696 | if (i == CS_SUCCESS) break; |
707 | } | 697 | } |
708 | i = next_tuple(link->handle, tuple, parse); | 698 | i = next_tuple(link, tuple, parse); |
709 | } | 699 | } |
710 | if (i == CS_SUCCESS) | 700 | if (i == CS_SUCCESS) |
711 | dev->base_addr = link->io.BasePort1; | 701 | dev->base_addr = link->io.BasePort1; |
@@ -714,9 +704,8 @@ static int smc_config(dev_link_t *link) | |||
714 | return i; | 704 | return i; |
715 | } | 705 | } |
716 | 706 | ||
717 | static int smc_setup(dev_link_t *link) | 707 | static int smc_setup(struct pcmcia_device *link) |
718 | { | 708 | { |
719 | client_handle_t handle = link->handle; | ||
720 | struct net_device *dev = link->priv; | 709 | struct net_device *dev = link->priv; |
721 | struct smc_cfg_mem *cfg_mem; | 710 | struct smc_cfg_mem *cfg_mem; |
722 | tuple_t *tuple; | 711 | tuple_t *tuple; |
@@ -739,11 +728,11 @@ static int smc_setup(dev_link_t *link) | |||
739 | 728 | ||
740 | /* Check for a LAN function extension tuple */ | 729 | /* Check for a LAN function extension tuple */ |
741 | tuple->DesiredTuple = CISTPL_FUNCE; | 730 | tuple->DesiredTuple = CISTPL_FUNCE; |
742 | i = first_tuple(handle, tuple, parse); | 731 | i = first_tuple(link, tuple, parse); |
743 | while (i == CS_SUCCESS) { | 732 | while (i == CS_SUCCESS) { |
744 | if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID) | 733 | if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID) |
745 | break; | 734 | break; |
746 | i = next_tuple(handle, tuple, parse); | 735 | i = next_tuple(link, tuple, parse); |
747 | } | 736 | } |
748 | if (i == CS_SUCCESS) { | 737 | if (i == CS_SUCCESS) { |
749 | node_id = (cistpl_lan_node_id_t *)parse->funce.data; | 738 | node_id = (cistpl_lan_node_id_t *)parse->funce.data; |
@@ -756,7 +745,7 @@ static int smc_setup(dev_link_t *link) | |||
756 | } | 745 | } |
757 | /* Try the third string in the Version 1 Version/ID tuple. */ | 746 | /* Try the third string in the Version 1 Version/ID tuple. */ |
758 | tuple->DesiredTuple = CISTPL_VERS_1; | 747 | tuple->DesiredTuple = CISTPL_VERS_1; |
759 | if (first_tuple(handle, tuple, parse) != CS_SUCCESS) { | 748 | if (first_tuple(link, tuple, parse) != CS_SUCCESS) { |
760 | rc = -1; | 749 | rc = -1; |
761 | goto free_cfg_mem; | 750 | goto free_cfg_mem; |
762 | } | 751 | } |
@@ -774,7 +763,7 @@ free_cfg_mem: | |||
774 | 763 | ||
775 | /*====================================================================*/ | 764 | /*====================================================================*/ |
776 | 765 | ||
777 | static int osi_config(dev_link_t *link) | 766 | static int osi_config(struct pcmcia_device *link) |
778 | { | 767 | { |
779 | struct net_device *dev = link->priv; | 768 | struct net_device *dev = link->priv; |
780 | static const kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; | 769 | static const kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; |
@@ -794,22 +783,21 @@ static int osi_config(dev_link_t *link) | |||
794 | 783 | ||
795 | for (i = j = 0; j < 4; j++) { | 784 | for (i = j = 0; j < 4; j++) { |
796 | link->io.BasePort2 = com[j]; | 785 | link->io.BasePort2 = com[j]; |
797 | i = pcmcia_request_io(link->handle, &link->io); | 786 | i = pcmcia_request_io(link, &link->io); |
798 | if (i == CS_SUCCESS) break; | 787 | if (i == CS_SUCCESS) break; |
799 | } | 788 | } |
800 | if (i != CS_SUCCESS) { | 789 | if (i != CS_SUCCESS) { |
801 | /* Fallback: turn off hard decode */ | 790 | /* Fallback: turn off hard decode */ |
802 | link->conf.ConfigIndex = 0x03; | 791 | link->conf.ConfigIndex = 0x03; |
803 | link->io.NumPorts2 = 0; | 792 | link->io.NumPorts2 = 0; |
804 | i = pcmcia_request_io(link->handle, &link->io); | 793 | i = pcmcia_request_io(link, &link->io); |
805 | } | 794 | } |
806 | dev->base_addr = link->io.BasePort1 + 0x10; | 795 | dev->base_addr = link->io.BasePort1 + 0x10; |
807 | return i; | 796 | return i; |
808 | } | 797 | } |
809 | 798 | ||
810 | static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) | 799 | static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid) |
811 | { | 800 | { |
812 | client_handle_t handle = link->handle; | ||
813 | struct net_device *dev = link->priv; | 801 | struct net_device *dev = link->priv; |
814 | struct smc_cfg_mem *cfg_mem; | 802 | struct smc_cfg_mem *cfg_mem; |
815 | tuple_t *tuple; | 803 | tuple_t *tuple; |
@@ -830,12 +818,12 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) | |||
830 | 818 | ||
831 | /* Read the station address from tuple 0x90, subtuple 0x04 */ | 819 | /* Read the station address from tuple 0x90, subtuple 0x04 */ |
832 | tuple->DesiredTuple = 0x90; | 820 | tuple->DesiredTuple = 0x90; |
833 | i = pcmcia_get_first_tuple(handle, tuple); | 821 | i = pcmcia_get_first_tuple(link, tuple); |
834 | while (i == CS_SUCCESS) { | 822 | while (i == CS_SUCCESS) { |
835 | i = pcmcia_get_tuple_data(handle, tuple); | 823 | i = pcmcia_get_tuple_data(link, tuple); |
836 | if ((i != CS_SUCCESS) || (buf[0] == 0x04)) | 824 | if ((i != CS_SUCCESS) || (buf[0] == 0x04)) |
837 | break; | 825 | break; |
838 | i = pcmcia_get_next_tuple(handle, tuple); | 826 | i = pcmcia_get_next_tuple(link, tuple); |
839 | } | 827 | } |
840 | if (i != CS_SUCCESS) { | 828 | if (i != CS_SUCCESS) { |
841 | rc = -1; | 829 | rc = -1; |
@@ -868,57 +856,47 @@ free_cfg_mem: | |||
868 | return rc; | 856 | return rc; |
869 | } | 857 | } |
870 | 858 | ||
871 | static int smc91c92_suspend(struct pcmcia_device *p_dev) | 859 | static int smc91c92_suspend(struct pcmcia_device *link) |
872 | { | 860 | { |
873 | dev_link_t *link = dev_to_instance(p_dev); | ||
874 | struct net_device *dev = link->priv; | 861 | struct net_device *dev = link->priv; |
875 | 862 | ||
876 | link->state |= DEV_SUSPEND; | 863 | if (link->open) |
877 | if (link->state & DEV_CONFIG) { | 864 | netif_device_detach(dev); |
878 | if (link->open) | ||
879 | netif_device_detach(dev); | ||
880 | pcmcia_release_configuration(link->handle); | ||
881 | } | ||
882 | 865 | ||
883 | return 0; | 866 | return 0; |
884 | } | 867 | } |
885 | 868 | ||
886 | static int smc91c92_resume(struct pcmcia_device *p_dev) | 869 | static int smc91c92_resume(struct pcmcia_device *link) |
887 | { | 870 | { |
888 | dev_link_t *link = dev_to_instance(p_dev); | ||
889 | struct net_device *dev = link->priv; | 871 | struct net_device *dev = link->priv; |
890 | struct smc_private *smc = netdev_priv(dev); | 872 | struct smc_private *smc = netdev_priv(dev); |
891 | int i; | 873 | int i; |
892 | 874 | ||
893 | link->state &= ~DEV_SUSPEND; | 875 | if ((smc->manfid == MANFID_MEGAHERTZ) && |
894 | if (link->state & DEV_CONFIG) { | 876 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)) |
895 | if ((smc->manfid == MANFID_MEGAHERTZ) && | 877 | mhz_3288_power(link); |
896 | (smc->cardid == PRODID_MEGAHERTZ_EM3288)) | 878 | if (smc->manfid == MANFID_MOTOROLA) |
897 | mhz_3288_power(link); | 879 | mot_config(link); |
898 | pcmcia_request_configuration(link->handle, &link->conf); | 880 | if ((smc->manfid == MANFID_OSITECH) && |
899 | if (smc->manfid == MANFID_MOTOROLA) | 881 | (smc->cardid != PRODID_OSITECH_SEVEN)) { |
900 | mot_config(link); | 882 | /* Power up the card and enable interrupts */ |
901 | if ((smc->manfid == MANFID_OSITECH) && | 883 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); |
902 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | 884 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); |
903 | /* Power up the card and enable interrupts */ | 885 | } |
904 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); | 886 | if (((smc->manfid == MANFID_OSITECH) && |
905 | set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); | 887 | (smc->cardid == PRODID_OSITECH_SEVEN)) || |
906 | } | 888 | ((smc->manfid == MANFID_PSION) && |
907 | if (((smc->manfid == MANFID_OSITECH) && | 889 | (smc->cardid == PRODID_PSION_NET100))) { |
908 | (smc->cardid == PRODID_OSITECH_SEVEN)) || | 890 | /* Download the Seven of Diamonds firmware */ |
909 | ((smc->manfid == MANFID_PSION) && | 891 | for (i = 0; i < sizeof(__Xilinx7OD); i++) { |
910 | (smc->cardid == PRODID_PSION_NET100))) { | 892 | outb(__Xilinx7OD[i], link->io.BasePort1+2); |
911 | /* Download the Seven of Diamonds firmware */ | 893 | udelay(50); |
912 | for (i = 0; i < sizeof(__Xilinx7OD); i++) { | ||
913 | outb(__Xilinx7OD[i], link->io.BasePort1+2); | ||
914 | udelay(50); | ||
915 | } | ||
916 | } | ||
917 | if (link->open) { | ||
918 | smc_reset(dev); | ||
919 | netif_device_attach(dev); | ||
920 | } | 894 | } |
921 | } | 895 | } |
896 | if (link->open) { | ||
897 | smc_reset(dev); | ||
898 | netif_device_attach(dev); | ||
899 | } | ||
922 | 900 | ||
923 | return 0; | 901 | return 0; |
924 | } | 902 | } |
@@ -931,7 +909,7 @@ static int smc91c92_resume(struct pcmcia_device *p_dev) | |||
931 | 909 | ||
932 | ======================================================================*/ | 910 | ======================================================================*/ |
933 | 911 | ||
934 | static int check_sig(dev_link_t *link) | 912 | static int check_sig(struct pcmcia_device *link) |
935 | { | 913 | { |
936 | struct net_device *dev = link->priv; | 914 | struct net_device *dev = link->priv; |
937 | kio_addr_t ioaddr = dev->base_addr; | 915 | kio_addr_t ioaddr = dev->base_addr; |
@@ -964,13 +942,15 @@ static int check_sig(dev_link_t *link) | |||
964 | } | 942 | } |
965 | 943 | ||
966 | if (width) { | 944 | if (width) { |
967 | printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); | 945 | modconf_t mod = { |
968 | smc91c92_suspend(link->handle); | 946 | .Attributes = CONF_IO_CHANGE_WIDTH, |
969 | pcmcia_release_io(link->handle, &link->io); | 947 | }; |
970 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 948 | printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); |
971 | pcmcia_request_io(link->handle, &link->io); | 949 | |
972 | smc91c92_resume(link->handle); | 950 | smc91c92_suspend(link); |
973 | return check_sig(link); | 951 | pcmcia_modify_configuration(link, &mod); |
952 | smc91c92_resume(link); | ||
953 | return check_sig(link); | ||
974 | } | 954 | } |
975 | return -ENODEV; | 955 | return -ENODEV; |
976 | } | 956 | } |
@@ -984,11 +964,10 @@ static int check_sig(dev_link_t *link) | |||
984 | ======================================================================*/ | 964 | ======================================================================*/ |
985 | 965 | ||
986 | #define CS_EXIT_TEST(ret, svc, label) \ | 966 | #define CS_EXIT_TEST(ret, svc, label) \ |
987 | if (ret != CS_SUCCESS) { cs_error(link->handle, svc, ret); goto label; } | 967 | if (ret != CS_SUCCESS) { cs_error(link, svc, ret); goto label; } |
988 | 968 | ||
989 | static void smc91c92_config(dev_link_t *link) | 969 | static int smc91c92_config(struct pcmcia_device *link) |
990 | { | 970 | { |
991 | client_handle_t handle = link->handle; | ||
992 | struct net_device *dev = link->priv; | 971 | struct net_device *dev = link->priv; |
993 | struct smc_private *smc = netdev_priv(dev); | 972 | struct smc_private *smc = netdev_priv(dev); |
994 | struct smc_cfg_mem *cfg_mem; | 973 | struct smc_cfg_mem *cfg_mem; |
@@ -1015,21 +994,18 @@ static void smc91c92_config(dev_link_t *link) | |||
1015 | tuple->TupleDataMax = 64; | 994 | tuple->TupleDataMax = 64; |
1016 | 995 | ||
1017 | tuple->DesiredTuple = CISTPL_CONFIG; | 996 | tuple->DesiredTuple = CISTPL_CONFIG; |
1018 | i = first_tuple(handle, tuple, parse); | 997 | i = first_tuple(link, tuple, parse); |
1019 | CS_EXIT_TEST(i, ParseTuple, config_failed); | 998 | CS_EXIT_TEST(i, ParseTuple, config_failed); |
1020 | link->conf.ConfigBase = parse->config.base; | 999 | link->conf.ConfigBase = parse->config.base; |
1021 | link->conf.Present = parse->config.rmask[0]; | 1000 | link->conf.Present = parse->config.rmask[0]; |
1022 | 1001 | ||
1023 | tuple->DesiredTuple = CISTPL_MANFID; | 1002 | tuple->DesiredTuple = CISTPL_MANFID; |
1024 | tuple->Attributes = TUPLE_RETURN_COMMON; | 1003 | tuple->Attributes = TUPLE_RETURN_COMMON; |
1025 | if (first_tuple(handle, tuple, parse) == CS_SUCCESS) { | 1004 | if (first_tuple(link, tuple, parse) == CS_SUCCESS) { |
1026 | smc->manfid = parse->manfid.manf; | 1005 | smc->manfid = parse->manfid.manf; |
1027 | smc->cardid = parse->manfid.card; | 1006 | smc->cardid = parse->manfid.card; |
1028 | } | 1007 | } |
1029 | 1008 | ||
1030 | /* Configure card */ | ||
1031 | link->state |= DEV_CONFIG; | ||
1032 | |||
1033 | if ((smc->manfid == MANFID_OSITECH) && | 1009 | if ((smc->manfid == MANFID_OSITECH) && |
1034 | (smc->cardid != PRODID_OSITECH_SEVEN)) { | 1010 | (smc->cardid != PRODID_OSITECH_SEVEN)) { |
1035 | i = osi_config(link); | 1011 | i = osi_config(link); |
@@ -1043,9 +1019,9 @@ static void smc91c92_config(dev_link_t *link) | |||
1043 | } | 1019 | } |
1044 | CS_EXIT_TEST(i, RequestIO, config_failed); | 1020 | CS_EXIT_TEST(i, RequestIO, config_failed); |
1045 | 1021 | ||
1046 | i = pcmcia_request_irq(link->handle, &link->irq); | 1022 | i = pcmcia_request_irq(link, &link->irq); |
1047 | CS_EXIT_TEST(i, RequestIRQ, config_failed); | 1023 | CS_EXIT_TEST(i, RequestIRQ, config_failed); |
1048 | i = pcmcia_request_configuration(link->handle, &link->conf); | 1024 | i = pcmcia_request_configuration(link, &link->conf); |
1049 | CS_EXIT_TEST(i, RequestConfiguration, config_failed); | 1025 | CS_EXIT_TEST(i, RequestConfiguration, config_failed); |
1050 | 1026 | ||
1051 | if (smc->manfid == MANFID_MOTOROLA) | 1027 | if (smc->manfid == MANFID_MOTOROLA) |
@@ -1124,13 +1100,12 @@ static void smc91c92_config(dev_link_t *link) | |||
1124 | SMC_SELECT_BANK(0); | 1100 | SMC_SELECT_BANK(0); |
1125 | } | 1101 | } |
1126 | 1102 | ||
1127 | link->dev = &smc->node; | 1103 | link->dev_node = &smc->node; |
1128 | link->state &= ~DEV_CONFIG_PENDING; | 1104 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
1129 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
1130 | 1105 | ||
1131 | if (register_netdev(dev) != 0) { | 1106 | if (register_netdev(dev) != 0) { |
1132 | printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n"); | 1107 | printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n"); |
1133 | link->dev = NULL; | 1108 | link->dev_node = NULL; |
1134 | goto config_undo; | 1109 | goto config_undo; |
1135 | } | 1110 | } |
1136 | 1111 | ||
@@ -1160,15 +1135,14 @@ static void smc91c92_config(dev_link_t *link) | |||
1160 | } | 1135 | } |
1161 | } | 1136 | } |
1162 | kfree(cfg_mem); | 1137 | kfree(cfg_mem); |
1163 | return; | 1138 | return 0; |
1164 | 1139 | ||
1165 | config_undo: | 1140 | config_undo: |
1166 | unregister_netdev(dev); | 1141 | unregister_netdev(dev); |
1167 | config_failed: /* CS_EXIT_TEST() calls jump to here... */ | 1142 | config_failed: /* CS_EXIT_TEST() calls jump to here... */ |
1168 | smc91c92_release(link); | 1143 | smc91c92_release(link); |
1169 | link->state &= ~DEV_CONFIG_PENDING; | ||
1170 | kfree(cfg_mem); | 1144 | kfree(cfg_mem); |
1171 | 1145 | return -ENODEV; | |
1172 | } /* smc91c92_config */ | 1146 | } /* smc91c92_config */ |
1173 | 1147 | ||
1174 | /*====================================================================== | 1148 | /*====================================================================== |
@@ -1179,22 +1153,15 @@ config_failed: /* CS_EXIT_TEST() calls jump to here... */ | |||
1179 | 1153 | ||
1180 | ======================================================================*/ | 1154 | ======================================================================*/ |
1181 | 1155 | ||
1182 | static void smc91c92_release(dev_link_t *link) | 1156 | static void smc91c92_release(struct pcmcia_device *link) |
1183 | { | 1157 | { |
1184 | 1158 | DEBUG(0, "smc91c92_release(0x%p)\n", link); | |
1185 | DEBUG(0, "smc91c92_release(0x%p)\n", link); | 1159 | if (link->win) { |
1186 | 1160 | struct net_device *dev = link->priv; | |
1187 | pcmcia_release_configuration(link->handle); | 1161 | struct smc_private *smc = netdev_priv(dev); |
1188 | pcmcia_release_io(link->handle, &link->io); | 1162 | iounmap(smc->base); |
1189 | pcmcia_release_irq(link->handle, &link->irq); | 1163 | } |
1190 | if (link->win) { | 1164 | pcmcia_disable_device(link); |
1191 | struct net_device *dev = link->priv; | ||
1192 | struct smc_private *smc = netdev_priv(dev); | ||
1193 | iounmap(smc->base); | ||
1194 | pcmcia_release_window(link->win); | ||
1195 | } | ||
1196 | |||
1197 | link->state &= ~DEV_CONFIG; | ||
1198 | } | 1165 | } |
1199 | 1166 | ||
1200 | /*====================================================================== | 1167 | /*====================================================================== |
@@ -1283,7 +1250,7 @@ static void smc_dump(struct net_device *dev) | |||
1283 | static int smc_open(struct net_device *dev) | 1250 | static int smc_open(struct net_device *dev) |
1284 | { | 1251 | { |
1285 | struct smc_private *smc = netdev_priv(dev); | 1252 | struct smc_private *smc = netdev_priv(dev); |
1286 | dev_link_t *link = &smc->link; | 1253 | struct pcmcia_device *link = smc->p_dev; |
1287 | 1254 | ||
1288 | #ifdef PCMCIA_DEBUG | 1255 | #ifdef PCMCIA_DEBUG |
1289 | DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n", | 1256 | DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n", |
@@ -1292,7 +1259,7 @@ static int smc_open(struct net_device *dev) | |||
1292 | #endif | 1259 | #endif |
1293 | 1260 | ||
1294 | /* Check that the PCMCIA card is still here. */ | 1261 | /* Check that the PCMCIA card is still here. */ |
1295 | if (!DEV_OK(link)) | 1262 | if (!pcmcia_dev_present(link)) |
1296 | return -ENODEV; | 1263 | return -ENODEV; |
1297 | /* Physical device present signature. */ | 1264 | /* Physical device present signature. */ |
1298 | if (check_sig(link) < 0) { | 1265 | if (check_sig(link) < 0) { |
@@ -1320,7 +1287,7 @@ static int smc_open(struct net_device *dev) | |||
1320 | static int smc_close(struct net_device *dev) | 1287 | static int smc_close(struct net_device *dev) |
1321 | { | 1288 | { |
1322 | struct smc_private *smc = netdev_priv(dev); | 1289 | struct smc_private *smc = netdev_priv(dev); |
1323 | dev_link_t *link = &smc->link; | 1290 | struct pcmcia_device *link = smc->p_dev; |
1324 | kio_addr_t ioaddr = dev->base_addr; | 1291 | kio_addr_t ioaddr = dev->base_addr; |
1325 | 1292 | ||
1326 | DEBUG(0, "%s: smc_close(), status %4.4x.\n", | 1293 | DEBUG(0, "%s: smc_close(), status %4.4x.\n", |
@@ -2311,7 +2278,7 @@ static struct pcmcia_driver smc91c92_cs_driver = { | |||
2311 | .drv = { | 2278 | .drv = { |
2312 | .name = "smc91c92_cs", | 2279 | .name = "smc91c92_cs", |
2313 | }, | 2280 | }, |
2314 | .probe = smc91c92_attach, | 2281 | .probe = smc91c92_probe, |
2315 | .remove = smc91c92_detach, | 2282 | .remove = smc91c92_detach, |
2316 | .id_table = smc91c92_ids, | 2283 | .id_table = smc91c92_ids, |
2317 | .suspend = smc91c92_suspend, | 2284 | .suspend = smc91c92_suspend, |
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index e8f849e12976..71f45056a70c 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c | |||
@@ -289,9 +289,9 @@ static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, | |||
289 | * and ejection events. They are invoked from the event handler. | 289 | * and ejection events. They are invoked from the event handler. |
290 | */ | 290 | */ |
291 | 291 | ||
292 | static int has_ce2_string(dev_link_t * link); | 292 | static int has_ce2_string(struct pcmcia_device * link); |
293 | static void xirc2ps_config(dev_link_t * link); | 293 | static int xirc2ps_config(struct pcmcia_device * link); |
294 | static void xirc2ps_release(dev_link_t * link); | 294 | static void xirc2ps_release(struct pcmcia_device * link); |
295 | 295 | ||
296 | /**************** | 296 | /**************** |
297 | * The attach() and detach() entry points are used to create and destroy | 297 | * The attach() and detach() entry points are used to create and destroy |
@@ -313,10 +313,10 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs | |||
313 | /**************** | 313 | /**************** |
314 | * A linked list of "instances" of the device. Each actual | 314 | * A linked list of "instances" of the device. Each actual |
315 | * PCMCIA card corresponds to one device instance, and is described | 315 | * PCMCIA card corresponds to one device instance, and is described |
316 | * by one dev_link_t structure (defined in ds.h). | 316 | * by one struct pcmcia_device structure (defined in ds.h). |
317 | * | 317 | * |
318 | * You may not want to use a linked list for this -- for example, the | 318 | * You may not want to use a linked list for this -- for example, the |
319 | * memory card driver uses an array of dev_link_t pointers, where minor | 319 | * memory card driver uses an array of struct pcmcia_device pointers, where minor |
320 | * device numbers are used to derive the corresponding array index. | 320 | * device numbers are used to derive the corresponding array index. |
321 | */ | 321 | */ |
322 | 322 | ||
@@ -326,13 +326,13 @@ static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs | |||
326 | * example, ethernet cards, modems). In other cases, there may be | 326 | * example, ethernet cards, modems). In other cases, there may be |
327 | * many actual or logical devices (SCSI adapters, memory cards with | 327 | * many actual or logical devices (SCSI adapters, memory cards with |
328 | * multiple partitions). The dev_node_t structures need to be kept | 328 | * multiple partitions). The dev_node_t structures need to be kept |
329 | * in a linked list starting at the 'dev' field of a dev_link_t | 329 | * in a linked list starting at the 'dev' field of a struct pcmcia_device |
330 | * structure. We allocate them in the card's private data structure, | 330 | * structure. We allocate them in the card's private data structure, |
331 | * because they generally can't be allocated dynamically. | 331 | * because they generally can't be allocated dynamically. |
332 | */ | 332 | */ |
333 | 333 | ||
334 | typedef struct local_info_t { | 334 | typedef struct local_info_t { |
335 | dev_link_t link; | 335 | struct pcmcia_device *p_dev; |
336 | dev_node_t node; | 336 | dev_node_t node; |
337 | struct net_device_stats stats; | 337 | struct net_device_stats stats; |
338 | int card_type; | 338 | int card_type; |
@@ -355,7 +355,7 @@ static void do_tx_timeout(struct net_device *dev); | |||
355 | static struct net_device_stats *do_get_stats(struct net_device *dev); | 355 | static struct net_device_stats *do_get_stats(struct net_device *dev); |
356 | static void set_addresses(struct net_device *dev); | 356 | static void set_addresses(struct net_device *dev); |
357 | static void set_multicast_list(struct net_device *dev); | 357 | static void set_multicast_list(struct net_device *dev); |
358 | static int set_card_type(dev_link_t *link, const void *s); | 358 | static int set_card_type(struct pcmcia_device *link, const void *s); |
359 | static int do_config(struct net_device *dev, struct ifmap *map); | 359 | static int do_config(struct net_device *dev, struct ifmap *map); |
360 | static int do_open(struct net_device *dev); | 360 | static int do_open(struct net_device *dev); |
361 | static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 361 | static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
@@ -368,7 +368,7 @@ static int do_stop(struct net_device *dev); | |||
368 | 368 | ||
369 | /*=============== Helper functions =========================*/ | 369 | /*=============== Helper functions =========================*/ |
370 | static int | 370 | static int |
371 | first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | 371 | first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) |
372 | { | 372 | { |
373 | int err; | 373 | int err; |
374 | 374 | ||
@@ -379,7 +379,7 @@ first_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | |||
379 | } | 379 | } |
380 | 380 | ||
381 | static int | 381 | static int |
382 | next_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse) | 382 | next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) |
383 | { | 383 | { |
384 | int err; | 384 | int err; |
385 | 385 | ||
@@ -553,9 +553,8 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len) | |||
553 | */ | 553 | */ |
554 | 554 | ||
555 | static int | 555 | static int |
556 | xirc2ps_attach(struct pcmcia_device *p_dev) | 556 | xirc2ps_probe(struct pcmcia_device *link) |
557 | { | 557 | { |
558 | dev_link_t *link; | ||
559 | struct net_device *dev; | 558 | struct net_device *dev; |
560 | local_info_t *local; | 559 | local_info_t *local; |
561 | 560 | ||
@@ -566,12 +565,11 @@ xirc2ps_attach(struct pcmcia_device *p_dev) | |||
566 | if (!dev) | 565 | if (!dev) |
567 | return -ENOMEM; | 566 | return -ENOMEM; |
568 | local = netdev_priv(dev); | 567 | local = netdev_priv(dev); |
569 | link = &local->link; | 568 | local->p_dev = link; |
570 | link->priv = dev; | 569 | link->priv = dev; |
571 | 570 | ||
572 | /* General socket configuration */ | 571 | /* General socket configuration */ |
573 | link->conf.Attributes = CONF_ENABLE_IRQ; | 572 | link->conf.Attributes = CONF_ENABLE_IRQ; |
574 | link->conf.Vcc = 50; | ||
575 | link->conf.IntType = INT_MEMORY_AND_IO; | 573 | link->conf.IntType = INT_MEMORY_AND_IO; |
576 | link->conf.ConfigIndex = 1; | 574 | link->conf.ConfigIndex = 1; |
577 | link->conf.Present = PRESENT_OPTION; | 575 | link->conf.Present = PRESENT_OPTION; |
@@ -593,13 +591,7 @@ xirc2ps_attach(struct pcmcia_device *p_dev) | |||
593 | dev->watchdog_timeo = TX_TIMEOUT; | 591 | dev->watchdog_timeo = TX_TIMEOUT; |
594 | #endif | 592 | #endif |
595 | 593 | ||
596 | link->handle = p_dev; | 594 | return xirc2ps_config(link); |
597 | p_dev->instance = link; | ||
598 | |||
599 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
600 | xirc2ps_config(link); | ||
601 | |||
602 | return 0; | ||
603 | } /* xirc2ps_attach */ | 595 | } /* xirc2ps_attach */ |
604 | 596 | ||
605 | /**************** | 597 | /**************** |
@@ -610,18 +602,16 @@ xirc2ps_attach(struct pcmcia_device *p_dev) | |||
610 | */ | 602 | */ |
611 | 603 | ||
612 | static void | 604 | static void |
613 | xirc2ps_detach(struct pcmcia_device *p_dev) | 605 | xirc2ps_detach(struct pcmcia_device *link) |
614 | { | 606 | { |
615 | dev_link_t *link = dev_to_instance(p_dev); | ||
616 | struct net_device *dev = link->priv; | 607 | struct net_device *dev = link->priv; |
617 | 608 | ||
618 | DEBUG(0, "detach(0x%p)\n", link); | 609 | DEBUG(0, "detach(0x%p)\n", link); |
619 | 610 | ||
620 | if (link->dev) | 611 | if (link->dev_node) |
621 | unregister_netdev(dev); | 612 | unregister_netdev(dev); |
622 | 613 | ||
623 | if (link->state & DEV_CONFIG) | 614 | xirc2ps_release(link); |
624 | xirc2ps_release(link); | ||
625 | 615 | ||
626 | free_netdev(dev); | 616 | free_netdev(dev); |
627 | } /* xirc2ps_detach */ | 617 | } /* xirc2ps_detach */ |
@@ -645,7 +635,7 @@ xirc2ps_detach(struct pcmcia_device *p_dev) | |||
645 | * | 635 | * |
646 | */ | 636 | */ |
647 | static int | 637 | static int |
648 | set_card_type(dev_link_t *link, const void *s) | 638 | set_card_type(struct pcmcia_device *link, const void *s) |
649 | { | 639 | { |
650 | struct net_device *dev = link->priv; | 640 | struct net_device *dev = link->priv; |
651 | local_info_t *local = netdev_priv(dev); | 641 | local_info_t *local = netdev_priv(dev); |
@@ -714,9 +704,8 @@ set_card_type(dev_link_t *link, const void *s) | |||
714 | * Returns: true if this is a CE2 | 704 | * Returns: true if this is a CE2 |
715 | */ | 705 | */ |
716 | static int | 706 | static int |
717 | has_ce2_string(dev_link_t * link) | 707 | has_ce2_string(struct pcmcia_device * link) |
718 | { | 708 | { |
719 | client_handle_t handle = link->handle; | ||
720 | tuple_t tuple; | 709 | tuple_t tuple; |
721 | cisparse_t parse; | 710 | cisparse_t parse; |
722 | u_char buf[256]; | 711 | u_char buf[256]; |
@@ -726,7 +715,7 @@ has_ce2_string(dev_link_t * link) | |||
726 | tuple.TupleDataMax = 254; | 715 | tuple.TupleDataMax = 254; |
727 | tuple.TupleOffset = 0; | 716 | tuple.TupleOffset = 0; |
728 | tuple.DesiredTuple = CISTPL_VERS_1; | 717 | tuple.DesiredTuple = CISTPL_VERS_1; |
729 | if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) { | 718 | if (!first_tuple(link, &tuple, &parse) && parse.version_1.ns > 2) { |
730 | if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2")) | 719 | if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2")) |
731 | return 1; | 720 | return 1; |
732 | } | 721 | } |
@@ -738,10 +727,9 @@ has_ce2_string(dev_link_t * link) | |||
738 | * is received, to configure the PCMCIA socket, and to make the | 727 | * is received, to configure the PCMCIA socket, and to make the |
739 | * ethernet device available to the system. | 728 | * ethernet device available to the system. |
740 | */ | 729 | */ |
741 | static void | 730 | static int |
742 | xirc2ps_config(dev_link_t * link) | 731 | xirc2ps_config(struct pcmcia_device * link) |
743 | { | 732 | { |
744 | client_handle_t handle = link->handle; | ||
745 | struct net_device *dev = link->priv; | 733 | struct net_device *dev = link->priv; |
746 | local_info_t *local = netdev_priv(dev); | 734 | local_info_t *local = netdev_priv(dev); |
747 | tuple_t tuple; | 735 | tuple_t tuple; |
@@ -767,7 +755,7 @@ xirc2ps_config(dev_link_t * link) | |||
767 | 755 | ||
768 | /* Is this a valid card */ | 756 | /* Is this a valid card */ |
769 | tuple.DesiredTuple = CISTPL_MANFID; | 757 | tuple.DesiredTuple = CISTPL_MANFID; |
770 | if ((err=first_tuple(handle, &tuple, &parse))) { | 758 | if ((err=first_tuple(link, &tuple, &parse))) { |
771 | printk(KNOT_XIRC "manfid not found in CIS\n"); | 759 | printk(KNOT_XIRC "manfid not found in CIS\n"); |
772 | goto failure; | 760 | goto failure; |
773 | } | 761 | } |
@@ -803,15 +791,15 @@ xirc2ps_config(dev_link_t * link) | |||
803 | 791 | ||
804 | /* get configuration stuff */ | 792 | /* get configuration stuff */ |
805 | tuple.DesiredTuple = CISTPL_CONFIG; | 793 | tuple.DesiredTuple = CISTPL_CONFIG; |
806 | if ((err=first_tuple(handle, &tuple, &parse))) | 794 | if ((err=first_tuple(link, &tuple, &parse))) |
807 | goto cis_error; | 795 | goto cis_error; |
808 | link->conf.ConfigBase = parse.config.base; | 796 | link->conf.ConfigBase = parse.config.base; |
809 | link->conf.Present = parse.config.rmask[0]; | 797 | link->conf.Present = parse.config.rmask[0]; |
810 | 798 | ||
811 | /* get the ethernet address from the CIS */ | 799 | /* get the ethernet address from the CIS */ |
812 | tuple.DesiredTuple = CISTPL_FUNCE; | 800 | tuple.DesiredTuple = CISTPL_FUNCE; |
813 | for (err = first_tuple(handle, &tuple, &parse); !err; | 801 | for (err = first_tuple(link, &tuple, &parse); !err; |
814 | err = next_tuple(handle, &tuple, &parse)) { | 802 | err = next_tuple(link, &tuple, &parse)) { |
815 | /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries: | 803 | /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries: |
816 | * the first one with a length of zero the second correct - | 804 | * the first one with a length of zero the second correct - |
817 | * so I skip all entries with length 0 */ | 805 | * so I skip all entries with length 0 */ |
@@ -821,8 +809,8 @@ xirc2ps_config(dev_link_t * link) | |||
821 | } | 809 | } |
822 | if (err) { /* not found: try to get the node-id from tuple 0x89 */ | 810 | if (err) { /* not found: try to get the node-id from tuple 0x89 */ |
823 | tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */ | 811 | tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */ |
824 | if ((err = pcmcia_get_first_tuple(handle, &tuple)) == 0 && | 812 | if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 && |
825 | (err = pcmcia_get_tuple_data(handle, &tuple)) == 0) { | 813 | (err = pcmcia_get_tuple_data(link, &tuple)) == 0) { |
826 | if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID) | 814 | if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID) |
827 | memcpy(&parse, buf, 8); | 815 | memcpy(&parse, buf, 8); |
828 | else | 816 | else |
@@ -831,8 +819,8 @@ xirc2ps_config(dev_link_t * link) | |||
831 | } | 819 | } |
832 | if (err) { /* another try (James Lehmer's CE2 version 4.1)*/ | 820 | if (err) { /* another try (James Lehmer's CE2 version 4.1)*/ |
833 | tuple.DesiredTuple = CISTPL_FUNCE; | 821 | tuple.DesiredTuple = CISTPL_FUNCE; |
834 | for (err = first_tuple(handle, &tuple, &parse); !err; | 822 | for (err = first_tuple(link, &tuple, &parse); !err; |
835 | err = next_tuple(handle, &tuple, &parse)) { | 823 | err = next_tuple(link, &tuple, &parse)) { |
836 | if (parse.funce.type == 0x02 && parse.funce.data[0] == 1 | 824 | if (parse.funce.type == 0x02 && parse.funce.data[0] == 1 |
837 | && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) { | 825 | && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) { |
838 | buf[1] = 4; | 826 | buf[1] = 4; |
@@ -853,9 +841,6 @@ xirc2ps_config(dev_link_t * link) | |||
853 | for (i=0; i < 6; i++) | 841 | for (i=0; i < 6; i++) |
854 | dev->dev_addr[i] = node_id->id[i]; | 842 | dev->dev_addr[i] = node_id->id[i]; |
855 | 843 | ||
856 | /* Configure card */ | ||
857 | link->state |= DEV_CONFIG; | ||
858 | |||
859 | link->io.IOAddrLines =10; | 844 | link->io.IOAddrLines =10; |
860 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | 845 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; |
861 | link->irq.Attributes = IRQ_HANDLE_PRESENT; | 846 | link->irq.Attributes = IRQ_HANDLE_PRESENT; |
@@ -875,14 +860,14 @@ xirc2ps_config(dev_link_t * link) | |||
875 | * Ethernet port */ | 860 | * Ethernet port */ |
876 | link->io.NumPorts1 = 16; /* no Mako stuff anymore */ | 861 | link->io.NumPorts1 = 16; /* no Mako stuff anymore */ |
877 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 862 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
878 | for (err = first_tuple(handle, &tuple, &parse); !err; | 863 | for (err = first_tuple(link, &tuple, &parse); !err; |
879 | err = next_tuple(handle, &tuple, &parse)) { | 864 | err = next_tuple(link, &tuple, &parse)) { |
880 | if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { | 865 | if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { |
881 | for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { | 866 | for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { |
882 | link->conf.ConfigIndex = cf->index ; | 867 | link->conf.ConfigIndex = cf->index ; |
883 | link->io.BasePort2 = cf->io.win[0].base; | 868 | link->io.BasePort2 = cf->io.win[0].base; |
884 | link->io.BasePort1 = ioaddr; | 869 | link->io.BasePort1 = ioaddr; |
885 | if (!(err=pcmcia_request_io(link->handle, &link->io))) | 870 | if (!(err=pcmcia_request_io(link, &link->io))) |
886 | goto port_found; | 871 | goto port_found; |
887 | } | 872 | } |
888 | } | 873 | } |
@@ -896,15 +881,15 @@ xirc2ps_config(dev_link_t * link) | |||
896 | */ | 881 | */ |
897 | for (pass=0; pass < 2; pass++) { | 882 | for (pass=0; pass < 2; pass++) { |
898 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 883 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
899 | for (err = first_tuple(handle, &tuple, &parse); !err; | 884 | for (err = first_tuple(link, &tuple, &parse); !err; |
900 | err = next_tuple(handle, &tuple, &parse)){ | 885 | err = next_tuple(link, &tuple, &parse)){ |
901 | if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){ | 886 | if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){ |
902 | link->conf.ConfigIndex = cf->index ; | 887 | link->conf.ConfigIndex = cf->index ; |
903 | link->io.BasePort2 = cf->io.win[0].base; | 888 | link->io.BasePort2 = cf->io.win[0].base; |
904 | link->io.BasePort1 = link->io.BasePort2 | 889 | link->io.BasePort1 = link->io.BasePort2 |
905 | + (pass ? (cf->index & 0x20 ? -24:8) | 890 | + (pass ? (cf->index & 0x20 ? -24:8) |
906 | : (cf->index & 0x20 ? 8:-24)); | 891 | : (cf->index & 0x20 ? 8:-24)); |
907 | if (!(err=pcmcia_request_io(link->handle, &link->io))) | 892 | if (!(err=pcmcia_request_io(link, &link->io))) |
908 | goto port_found; | 893 | goto port_found; |
909 | } | 894 | } |
910 | } | 895 | } |
@@ -919,12 +904,12 @@ xirc2ps_config(dev_link_t * link) | |||
919 | link->io.NumPorts1 = 16; | 904 | link->io.NumPorts1 = 16; |
920 | for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { | 905 | for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { |
921 | link->io.BasePort1 = ioaddr; | 906 | link->io.BasePort1 = ioaddr; |
922 | if (!(err=pcmcia_request_io(link->handle, &link->io))) | 907 | if (!(err=pcmcia_request_io(link, &link->io))) |
923 | goto port_found; | 908 | goto port_found; |
924 | } | 909 | } |
925 | link->io.BasePort1 = 0; /* let CS decide */ | 910 | link->io.BasePort1 = 0; /* let CS decide */ |
926 | if ((err=pcmcia_request_io(link->handle, &link->io))) { | 911 | if ((err=pcmcia_request_io(link, &link->io))) { |
927 | cs_error(link->handle, RequestIO, err); | 912 | cs_error(link, RequestIO, err); |
928 | goto config_error; | 913 | goto config_error; |
929 | } | 914 | } |
930 | } | 915 | } |
@@ -936,8 +921,8 @@ xirc2ps_config(dev_link_t * link) | |||
936 | * Now allocate an interrupt line. Note that this does not | 921 | * Now allocate an interrupt line. Note that this does not |
937 | * actually assign a handler to the interrupt. | 922 | * actually assign a handler to the interrupt. |
938 | */ | 923 | */ |
939 | if ((err=pcmcia_request_irq(link->handle, &link->irq))) { | 924 | if ((err=pcmcia_request_irq(link, &link->irq))) { |
940 | cs_error(link->handle, RequestIRQ, err); | 925 | cs_error(link, RequestIRQ, err); |
941 | goto config_error; | 926 | goto config_error; |
942 | } | 927 | } |
943 | 928 | ||
@@ -945,8 +930,8 @@ xirc2ps_config(dev_link_t * link) | |||
945 | * This actually configures the PCMCIA socket -- setting up | 930 | * This actually configures the PCMCIA socket -- setting up |
946 | * the I/O windows and the interrupt mapping. | 931 | * the I/O windows and the interrupt mapping. |
947 | */ | 932 | */ |
948 | if ((err=pcmcia_request_configuration(link->handle, &link->conf))) { | 933 | if ((err=pcmcia_request_configuration(link, &link->conf))) { |
949 | cs_error(link->handle, RequestConfiguration, err); | 934 | cs_error(link, RequestConfiguration, err); |
950 | goto config_error; | 935 | goto config_error; |
951 | } | 936 | } |
952 | 937 | ||
@@ -963,15 +948,15 @@ xirc2ps_config(dev_link_t * link) | |||
963 | reg.Action = CS_WRITE; | 948 | reg.Action = CS_WRITE; |
964 | reg.Offset = CISREG_IOBASE_0; | 949 | reg.Offset = CISREG_IOBASE_0; |
965 | reg.Value = link->io.BasePort2 & 0xff; | 950 | reg.Value = link->io.BasePort2 & 0xff; |
966 | if ((err = pcmcia_access_configuration_register(link->handle, ®))) { | 951 | if ((err = pcmcia_access_configuration_register(link, ®))) { |
967 | cs_error(link->handle, AccessConfigurationRegister, err); | 952 | cs_error(link, AccessConfigurationRegister, err); |
968 | goto config_error; | 953 | goto config_error; |
969 | } | 954 | } |
970 | reg.Action = CS_WRITE; | 955 | reg.Action = CS_WRITE; |
971 | reg.Offset = CISREG_IOBASE_1; | 956 | reg.Offset = CISREG_IOBASE_1; |
972 | reg.Value = (link->io.BasePort2 >> 8) & 0xff; | 957 | reg.Value = (link->io.BasePort2 >> 8) & 0xff; |
973 | if ((err = pcmcia_access_configuration_register(link->handle, ®))) { | 958 | if ((err = pcmcia_access_configuration_register(link, ®))) { |
974 | cs_error(link->handle, AccessConfigurationRegister, err); | 959 | cs_error(link, AccessConfigurationRegister, err); |
975 | goto config_error; | 960 | goto config_error; |
976 | } | 961 | } |
977 | 962 | ||
@@ -982,15 +967,15 @@ xirc2ps_config(dev_link_t * link) | |||
982 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 967 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; |
983 | req.Base = req.Size = 0; | 968 | req.Base = req.Size = 0; |
984 | req.AccessSpeed = 0; | 969 | req.AccessSpeed = 0; |
985 | if ((err = pcmcia_request_window(&link->handle, &req, &link->win))) { | 970 | if ((err = pcmcia_request_window(&link, &req, &link->win))) { |
986 | cs_error(link->handle, RequestWindow, err); | 971 | cs_error(link, RequestWindow, err); |
987 | goto config_error; | 972 | goto config_error; |
988 | } | 973 | } |
989 | local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800; | 974 | local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800; |
990 | mem.CardOffset = 0x0; | 975 | mem.CardOffset = 0x0; |
991 | mem.Page = 0; | 976 | mem.Page = 0; |
992 | if ((err = pcmcia_map_mem_page(link->win, &mem))) { | 977 | if ((err = pcmcia_map_mem_page(link->win, &mem))) { |
993 | cs_error(link->handle, MapMemPage, err); | 978 | cs_error(link, MapMemPage, err); |
994 | goto config_error; | 979 | goto config_error; |
995 | } | 980 | } |
996 | 981 | ||
@@ -1050,13 +1035,12 @@ xirc2ps_config(dev_link_t * link) | |||
1050 | if (local->dingo) | 1035 | if (local->dingo) |
1051 | do_reset(dev, 1); /* a kludge to make the cem56 work */ | 1036 | do_reset(dev, 1); /* a kludge to make the cem56 work */ |
1052 | 1037 | ||
1053 | link->dev = &local->node; | 1038 | link->dev_node = &local->node; |
1054 | link->state &= ~DEV_CONFIG_PENDING; | 1039 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
1055 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
1056 | 1040 | ||
1057 | if ((err=register_netdev(dev))) { | 1041 | if ((err=register_netdev(dev))) { |
1058 | printk(KNOT_XIRC "register_netdev() failed\n"); | 1042 | printk(KNOT_XIRC "register_netdev() failed\n"); |
1059 | link->dev = NULL; | 1043 | link->dev_node = NULL; |
1060 | goto config_error; | 1044 | goto config_error; |
1061 | } | 1045 | } |
1062 | 1046 | ||
@@ -1069,17 +1053,16 @@ xirc2ps_config(dev_link_t * link) | |||
1069 | printk("%c%02X", i?':':' ', dev->dev_addr[i]); | 1053 | printk("%c%02X", i?':':' ', dev->dev_addr[i]); |
1070 | printk("\n"); | 1054 | printk("\n"); |
1071 | 1055 | ||
1072 | return; | 1056 | return 0; |
1073 | 1057 | ||
1074 | config_error: | 1058 | config_error: |
1075 | link->state &= ~DEV_CONFIG_PENDING; | ||
1076 | xirc2ps_release(link); | 1059 | xirc2ps_release(link); |
1077 | return; | 1060 | return -ENODEV; |
1078 | 1061 | ||
1079 | cis_error: | 1062 | cis_error: |
1080 | printk(KNOT_XIRC "unable to parse CIS\n"); | 1063 | printk(KNOT_XIRC "unable to parse CIS\n"); |
1081 | failure: | 1064 | failure: |
1082 | link->state &= ~DEV_CONFIG_PENDING; | 1065 | return -ENODEV; |
1083 | } /* xirc2ps_config */ | 1066 | } /* xirc2ps_config */ |
1084 | 1067 | ||
1085 | /**************** | 1068 | /**************** |
@@ -1088,57 +1071,41 @@ xirc2ps_config(dev_link_t * link) | |||
1088 | * still open, this will be postponed until it is closed. | 1071 | * still open, this will be postponed until it is closed. |
1089 | */ | 1072 | */ |
1090 | static void | 1073 | static void |
1091 | xirc2ps_release(dev_link_t *link) | 1074 | xirc2ps_release(struct pcmcia_device *link) |
1092 | { | 1075 | { |
1076 | DEBUG(0, "release(0x%p)\n", link); | ||
1093 | 1077 | ||
1094 | DEBUG(0, "release(0x%p)\n", link); | 1078 | if (link->win) { |
1095 | 1079 | struct net_device *dev = link->priv; | |
1096 | if (link->win) { | 1080 | local_info_t *local = netdev_priv(dev); |
1097 | struct net_device *dev = link->priv; | 1081 | if (local->dingo) |
1098 | local_info_t *local = netdev_priv(dev); | 1082 | iounmap(local->dingo_ccr - 0x0800); |
1099 | if (local->dingo) | 1083 | } |
1100 | iounmap(local->dingo_ccr - 0x0800); | 1084 | pcmcia_disable_device(link); |
1101 | pcmcia_release_window(link->win); | ||
1102 | } | ||
1103 | pcmcia_release_configuration(link->handle); | ||
1104 | pcmcia_release_io(link->handle, &link->io); | ||
1105 | pcmcia_release_irq(link->handle, &link->irq); | ||
1106 | link->state &= ~DEV_CONFIG; | ||
1107 | |||
1108 | } /* xirc2ps_release */ | 1085 | } /* xirc2ps_release */ |
1109 | 1086 | ||
1110 | /*====================================================================*/ | 1087 | /*====================================================================*/ |
1111 | 1088 | ||
1112 | 1089 | ||
1113 | static int xirc2ps_suspend(struct pcmcia_device *p_dev) | 1090 | static int xirc2ps_suspend(struct pcmcia_device *link) |
1114 | { | 1091 | { |
1115 | dev_link_t *link = dev_to_instance(p_dev); | ||
1116 | struct net_device *dev = link->priv; | 1092 | struct net_device *dev = link->priv; |
1117 | 1093 | ||
1118 | link->state |= DEV_SUSPEND; | 1094 | if (link->open) { |
1119 | if (link->state & DEV_CONFIG) { | 1095 | netif_device_detach(dev); |
1120 | if (link->open) { | 1096 | do_powerdown(dev); |
1121 | netif_device_detach(dev); | ||
1122 | do_powerdown(dev); | ||
1123 | } | ||
1124 | pcmcia_release_configuration(link->handle); | ||
1125 | } | 1097 | } |
1126 | 1098 | ||
1127 | return 0; | 1099 | return 0; |
1128 | } | 1100 | } |
1129 | 1101 | ||
1130 | static int xirc2ps_resume(struct pcmcia_device *p_dev) | 1102 | static int xirc2ps_resume(struct pcmcia_device *link) |
1131 | { | 1103 | { |
1132 | dev_link_t *link = dev_to_instance(p_dev); | ||
1133 | struct net_device *dev = link->priv; | 1104 | struct net_device *dev = link->priv; |
1134 | 1105 | ||
1135 | link->state &= ~DEV_SUSPEND; | 1106 | if (link->open) { |
1136 | if (link->state & DEV_CONFIG) { | 1107 | do_reset(dev,1); |
1137 | pcmcia_request_configuration(link->handle, &link->conf); | 1108 | netif_device_attach(dev); |
1138 | if (link->open) { | ||
1139 | do_reset(dev,1); | ||
1140 | netif_device_attach(dev); | ||
1141 | } | ||
1142 | } | 1109 | } |
1143 | 1110 | ||
1144 | return 0; | 1111 | return 0; |
@@ -1552,13 +1519,13 @@ static int | |||
1552 | do_open(struct net_device *dev) | 1519 | do_open(struct net_device *dev) |
1553 | { | 1520 | { |
1554 | local_info_t *lp = netdev_priv(dev); | 1521 | local_info_t *lp = netdev_priv(dev); |
1555 | dev_link_t *link = &lp->link; | 1522 | struct pcmcia_device *link = lp->p_dev; |
1556 | 1523 | ||
1557 | DEBUG(0, "do_open(%p)\n", dev); | 1524 | DEBUG(0, "do_open(%p)\n", dev); |
1558 | 1525 | ||
1559 | /* Check that the PCMCIA card is still here. */ | 1526 | /* Check that the PCMCIA card is still here. */ |
1560 | /* Physical device present signature. */ | 1527 | /* Physical device present signature. */ |
1561 | if (!DEV_OK(link)) | 1528 | if (!pcmcia_dev_present(link)) |
1562 | return -ENODEV; | 1529 | return -ENODEV; |
1563 | 1530 | ||
1564 | /* okay */ | 1531 | /* okay */ |
@@ -1882,7 +1849,7 @@ do_stop(struct net_device *dev) | |||
1882 | { | 1849 | { |
1883 | kio_addr_t ioaddr = dev->base_addr; | 1850 | kio_addr_t ioaddr = dev->base_addr; |
1884 | local_info_t *lp = netdev_priv(dev); | 1851 | local_info_t *lp = netdev_priv(dev); |
1885 | dev_link_t *link = &lp->link; | 1852 | struct pcmcia_device *link = lp->p_dev; |
1886 | 1853 | ||
1887 | DEBUG(0, "do_stop(%p)\n", dev); | 1854 | DEBUG(0, "do_stop(%p)\n", dev); |
1888 | 1855 | ||
@@ -1935,7 +1902,7 @@ static struct pcmcia_driver xirc2ps_cs_driver = { | |||
1935 | .drv = { | 1902 | .drv = { |
1936 | .name = "xirc2ps_cs", | 1903 | .name = "xirc2ps_cs", |
1937 | }, | 1904 | }, |
1938 | .probe = xirc2ps_attach, | 1905 | .probe = xirc2ps_probe, |
1939 | .remove = xirc2ps_detach, | 1906 | .remove = xirc2ps_detach, |
1940 | .id_table = xirc2ps_ids, | 1907 | .id_table = xirc2ps_ids, |
1941 | .suspend = xirc2ps_suspend, | 1908 | .suspend = xirc2ps_suspend, |
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 35dbf05c7f06..a70c2b0cc104 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -78,6 +78,8 @@ static const struct pci_device_id skge_id_table[] = { | |||
78 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, | 78 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, |
79 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, | 79 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, |
80 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), }, | 80 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), }, |
81 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, | ||
82 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, | ||
81 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, | 83 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, |
82 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ | 84 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ |
83 | { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) }, | 85 | { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) }, |
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 68f9c206a620..227df9876a2c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -51,7 +51,7 @@ | |||
51 | #include "sky2.h" | 51 | #include "sky2.h" |
52 | 52 | ||
53 | #define DRV_NAME "sky2" | 53 | #define DRV_NAME "sky2" |
54 | #define DRV_VERSION "1.1" | 54 | #define DRV_VERSION "1.2" |
55 | #define PFX DRV_NAME " " | 55 | #define PFX DRV_NAME " " |
56 | 56 | ||
57 | /* | 57 | /* |
@@ -99,8 +99,6 @@ MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); | |||
99 | static const struct pci_device_id sky2_id_table[] = { | 99 | static const struct pci_device_id sky2_id_table[] = { |
100 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, | 100 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, |
101 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, | 101 | { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, |
102 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, | ||
103 | { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, | ||
104 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, | 102 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, |
105 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, | 103 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, |
106 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, | 104 | { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, |
@@ -579,8 +577,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
579 | reg = gma_read16(hw, port, GM_PHY_ADDR); | 577 | reg = gma_read16(hw, port, GM_PHY_ADDR); |
580 | gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR); | 578 | gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR); |
581 | 579 | ||
582 | for (i = 0; i < GM_MIB_CNT_SIZE; i++) | 580 | for (i = GM_MIB_CNT_BASE; i <= GM_MIB_CNT_END; i += 4) |
583 | gma_read16(hw, port, GM_MIB_CNT_BASE + 8 * i); | 581 | gma_read16(hw, port, i); |
584 | gma_write16(hw, port, GM_PHY_ADDR, reg); | 582 | gma_write16(hw, port, GM_PHY_ADDR, reg); |
585 | 583 | ||
586 | /* transmit control */ | 584 | /* transmit control */ |
@@ -927,8 +925,7 @@ static inline struct sk_buff *sky2_alloc_skb(unsigned int size, gfp_t gfp_mask) | |||
927 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); | 925 | skb = alloc_skb(size + RX_SKB_ALIGN, gfp_mask); |
928 | if (likely(skb)) { | 926 | if (likely(skb)) { |
929 | unsigned long p = (unsigned long) skb->data; | 927 | unsigned long p = (unsigned long) skb->data; |
930 | skb_reserve(skb, | 928 | skb_reserve(skb, ALIGN(p, RX_SKB_ALIGN) - p); |
931 | ((p + RX_SKB_ALIGN - 1) & ~(RX_SKB_ALIGN - 1)) - p); | ||
932 | } | 929 | } |
933 | 930 | ||
934 | return skb; | 931 | return skb; |
@@ -1688,13 +1685,12 @@ static void sky2_tx_timeout(struct net_device *dev) | |||
1688 | } | 1685 | } |
1689 | 1686 | ||
1690 | 1687 | ||
1691 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | ||
1692 | /* Want receive buffer size to be multiple of 64 bits | 1688 | /* Want receive buffer size to be multiple of 64 bits |
1693 | * and incl room for vlan and truncation | 1689 | * and incl room for vlan and truncation |
1694 | */ | 1690 | */ |
1695 | static inline unsigned sky2_buf_size(int mtu) | 1691 | static inline unsigned sky2_buf_size(int mtu) |
1696 | { | 1692 | { |
1697 | return roundup(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; | 1693 | return ALIGN(mtu + ETH_HLEN + VLAN_HLEN, 8) + 8; |
1698 | } | 1694 | } |
1699 | 1695 | ||
1700 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) | 1696 | static int sky2_change_mtu(struct net_device *dev, int new_mtu) |
@@ -2088,6 +2084,20 @@ static void sky2_descriptor_error(struct sky2_hw *hw, unsigned port, | |||
2088 | } | 2084 | } |
2089 | } | 2085 | } |
2090 | 2086 | ||
2087 | /* If idle then force a fake soft NAPI poll once a second | ||
2088 | * to work around cases where sharing an edge triggered interrupt. | ||
2089 | */ | ||
2090 | static void sky2_idle(unsigned long arg) | ||
2091 | { | ||
2092 | struct net_device *dev = (struct net_device *) arg; | ||
2093 | |||
2094 | local_irq_disable(); | ||
2095 | if (__netif_rx_schedule_prep(dev)) | ||
2096 | __netif_rx_schedule(dev); | ||
2097 | local_irq_enable(); | ||
2098 | } | ||
2099 | |||
2100 | |||
2091 | static int sky2_poll(struct net_device *dev0, int *budget) | 2101 | static int sky2_poll(struct net_device *dev0, int *budget) |
2092 | { | 2102 | { |
2093 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; | 2103 | struct sky2_hw *hw = ((struct sky2_port *) netdev_priv(dev0))->hw; |
@@ -2095,6 +2105,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2095 | int work_done = 0; | 2105 | int work_done = 0; |
2096 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); | 2106 | u32 status = sky2_read32(hw, B0_Y2_SP_EISR); |
2097 | 2107 | ||
2108 | restart_poll: | ||
2098 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { | 2109 | if (unlikely(status & ~Y2_IS_STAT_BMU)) { |
2099 | if (status & Y2_IS_HW_ERR) | 2110 | if (status & Y2_IS_HW_ERR) |
2100 | sky2_hw_intr(hw); | 2111 | sky2_hw_intr(hw); |
@@ -2125,7 +2136,7 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2125 | } | 2136 | } |
2126 | 2137 | ||
2127 | if (status & Y2_IS_STAT_BMU) { | 2138 | if (status & Y2_IS_STAT_BMU) { |
2128 | work_done = sky2_status_intr(hw, work_limit); | 2139 | work_done += sky2_status_intr(hw, work_limit - work_done); |
2129 | *budget -= work_done; | 2140 | *budget -= work_done; |
2130 | dev0->quota -= work_done; | 2141 | dev0->quota -= work_done; |
2131 | 2142 | ||
@@ -2135,9 +2146,24 @@ static int sky2_poll(struct net_device *dev0, int *budget) | |||
2135 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); | 2146 | sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); |
2136 | } | 2147 | } |
2137 | 2148 | ||
2138 | netif_rx_complete(dev0); | 2149 | mod_timer(&hw->idle_timer, jiffies + HZ); |
2150 | |||
2151 | local_irq_disable(); | ||
2152 | __netif_rx_complete(dev0); | ||
2139 | 2153 | ||
2140 | status = sky2_read32(hw, B0_Y2_SP_LISR); | 2154 | status = sky2_read32(hw, B0_Y2_SP_LISR); |
2155 | |||
2156 | if (unlikely(status)) { | ||
2157 | /* More work pending, try and keep going */ | ||
2158 | if (__netif_rx_schedule_prep(dev0)) { | ||
2159 | __netif_rx_reschedule(dev0, work_done); | ||
2160 | status = sky2_read32(hw, B0_Y2_SP_EISR); | ||
2161 | local_irq_enable(); | ||
2162 | goto restart_poll; | ||
2163 | } | ||
2164 | } | ||
2165 | |||
2166 | local_irq_enable(); | ||
2141 | return 0; | 2167 | return 0; |
2142 | } | 2168 | } |
2143 | 2169 | ||
@@ -2155,8 +2181,6 @@ static irqreturn_t sky2_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
2155 | prefetch(&hw->st_le[hw->st_idx]); | 2181 | prefetch(&hw->st_le[hw->st_idx]); |
2156 | if (likely(__netif_rx_schedule_prep(dev0))) | 2182 | if (likely(__netif_rx_schedule_prep(dev0))) |
2157 | __netif_rx_schedule(dev0); | 2183 | __netif_rx_schedule(dev0); |
2158 | else | ||
2159 | printk(KERN_DEBUG PFX "irq race detected\n"); | ||
2160 | 2184 | ||
2161 | return IRQ_HANDLED; | 2185 | return IRQ_HANDLED; |
2162 | } | 2186 | } |
@@ -2195,7 +2219,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) | |||
2195 | } | 2219 | } |
2196 | 2220 | ||
2197 | 2221 | ||
2198 | static int sky2_reset(struct sky2_hw *hw) | 2222 | static int __devinit sky2_reset(struct sky2_hw *hw) |
2199 | { | 2223 | { |
2200 | u16 status; | 2224 | u16 status; |
2201 | u8 t8, pmd_type; | 2225 | u8 t8, pmd_type; |
@@ -3278,6 +3302,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, | |||
3278 | 3302 | ||
3279 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); | 3303 | sky2_write32(hw, B0_IMSK, Y2_IS_BASE); |
3280 | 3304 | ||
3305 | setup_timer(&hw->idle_timer, sky2_idle, (unsigned long) dev); | ||
3306 | |||
3281 | pci_set_drvdata(pdev, hw); | 3307 | pci_set_drvdata(pdev, hw); |
3282 | 3308 | ||
3283 | return 0; | 3309 | return 0; |
@@ -3313,13 +3339,15 @@ static void __devexit sky2_remove(struct pci_dev *pdev) | |||
3313 | if (!hw) | 3339 | if (!hw) |
3314 | return; | 3340 | return; |
3315 | 3341 | ||
3342 | del_timer_sync(&hw->idle_timer); | ||
3343 | |||
3344 | sky2_write32(hw, B0_IMSK, 0); | ||
3316 | dev0 = hw->dev[0]; | 3345 | dev0 = hw->dev[0]; |
3317 | dev1 = hw->dev[1]; | 3346 | dev1 = hw->dev[1]; |
3318 | if (dev1) | 3347 | if (dev1) |
3319 | unregister_netdev(dev1); | 3348 | unregister_netdev(dev1); |
3320 | unregister_netdev(dev0); | 3349 | unregister_netdev(dev0); |
3321 | 3350 | ||
3322 | sky2_write32(hw, B0_IMSK, 0); | ||
3323 | sky2_set_power_state(hw, PCI_D3hot); | 3351 | sky2_set_power_state(hw, PCI_D3hot); |
3324 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); | 3352 | sky2_write16(hw, B0_Y2LED, LED_STAT_OFF); |
3325 | sky2_write8(hw, B0_CTST, CS_RST_SET); | 3353 | sky2_write8(hw, B0_CTST, CS_RST_SET); |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 62532b4e45c5..b026f5653f04 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
@@ -1375,7 +1375,7 @@ enum { | |||
1375 | GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */ | 1375 | GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */ |
1376 | /* MIB Counters */ | 1376 | /* MIB Counters */ |
1377 | GM_MIB_CNT_BASE = 0x0100, /* Base Address of MIB Counters */ | 1377 | GM_MIB_CNT_BASE = 0x0100, /* Base Address of MIB Counters */ |
1378 | GM_MIB_CNT_SIZE = 256, | 1378 | GM_MIB_CNT_END = 0x025C, /* Last MIB counter */ |
1379 | }; | 1379 | }; |
1380 | 1380 | ||
1381 | 1381 | ||
@@ -1880,6 +1880,8 @@ struct sky2_hw { | |||
1880 | struct sky2_status_le *st_le; | 1880 | struct sky2_status_le *st_le; |
1881 | u32 st_idx; | 1881 | u32 st_idx; |
1882 | dma_addr_t st_dma; | 1882 | dma_addr_t st_dma; |
1883 | |||
1884 | struct timer_list idle_timer; | ||
1883 | int msi_detected; | 1885 | int msi_detected; |
1884 | wait_queue_head_t msi_wait; | 1886 | wait_queue_head_t msi_wait; |
1885 | }; | 1887 | }; |
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 35b18057fbdd..9b7805be21da 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c | |||
@@ -335,7 +335,7 @@ do { \ | |||
335 | 335 | ||
336 | 336 | ||
337 | /* These identify the driver base version and may not be removed. */ | 337 | /* These identify the driver base version and may not be removed. */ |
338 | static char version[] __devinitdata = | 338 | static const char version[] __devinitdata = |
339 | KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n" | 339 | KERN_INFO "starfire.c:v1.03 7/26/2000 Written by Donald Becker <becker@scyld.com>\n" |
340 | KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; | 340 | KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n"; |
341 | 341 | ||
@@ -2122,8 +2122,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev) | |||
2122 | struct net_device *dev = pci_get_drvdata(pdev); | 2122 | struct net_device *dev = pci_get_drvdata(pdev); |
2123 | struct netdev_private *np = netdev_priv(dev); | 2123 | struct netdev_private *np = netdev_priv(dev); |
2124 | 2124 | ||
2125 | if (!dev) | 2125 | BUG_ON(!dev); |
2126 | BUG(); | ||
2127 | 2126 | ||
2128 | unregister_netdev(dev); | 2127 | unregister_netdev(dev); |
2129 | 2128 | ||
diff --git a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c index cb0aba95d4e3..046371ee5bbe 100644 --- a/drivers/net/sungem_phy.c +++ b/drivers/net/sungem_phy.c | |||
@@ -275,7 +275,7 @@ static int bcm5411_init(struct mii_phy* phy) | |||
275 | return 0; | 275 | return 0; |
276 | } | 276 | } |
277 | 277 | ||
278 | static int bcm5411_suspend(struct mii_phy* phy) | 278 | static int generic_suspend(struct mii_phy* phy) |
279 | { | 279 | { |
280 | phy_write(phy, MII_BMCR, BMCR_PDOWN); | 280 | phy_write(phy, MII_BMCR, BMCR_PDOWN); |
281 | 281 | ||
@@ -738,7 +738,7 @@ static struct mii_phy_def bcm5401_phy_def = { | |||
738 | /* Broadcom BCM 5411 */ | 738 | /* Broadcom BCM 5411 */ |
739 | static struct mii_phy_ops bcm5411_phy_ops = { | 739 | static struct mii_phy_ops bcm5411_phy_ops = { |
740 | .init = bcm5411_init, | 740 | .init = bcm5411_init, |
741 | .suspend = bcm5411_suspend, | 741 | .suspend = generic_suspend, |
742 | .setup_aneg = bcm54xx_setup_aneg, | 742 | .setup_aneg = bcm54xx_setup_aneg, |
743 | .setup_forced = bcm54xx_setup_forced, | 743 | .setup_forced = bcm54xx_setup_forced, |
744 | .poll_link = genmii_poll_link, | 744 | .poll_link = genmii_poll_link, |
@@ -757,7 +757,7 @@ static struct mii_phy_def bcm5411_phy_def = { | |||
757 | /* Broadcom BCM 5421 */ | 757 | /* Broadcom BCM 5421 */ |
758 | static struct mii_phy_ops bcm5421_phy_ops = { | 758 | static struct mii_phy_ops bcm5421_phy_ops = { |
759 | .init = bcm5421_init, | 759 | .init = bcm5421_init, |
760 | .suspend = bcm5411_suspend, | 760 | .suspend = generic_suspend, |
761 | .setup_aneg = bcm54xx_setup_aneg, | 761 | .setup_aneg = bcm54xx_setup_aneg, |
762 | .setup_forced = bcm54xx_setup_forced, | 762 | .setup_forced = bcm54xx_setup_forced, |
763 | .poll_link = genmii_poll_link, | 763 | .poll_link = genmii_poll_link, |
@@ -776,7 +776,7 @@ static struct mii_phy_def bcm5421_phy_def = { | |||
776 | /* Broadcom BCM 5421 built-in K2 */ | 776 | /* Broadcom BCM 5421 built-in K2 */ |
777 | static struct mii_phy_ops bcm5421k2_phy_ops = { | 777 | static struct mii_phy_ops bcm5421k2_phy_ops = { |
778 | .init = bcm5421_init, | 778 | .init = bcm5421_init, |
779 | .suspend = bcm5411_suspend, | 779 | .suspend = generic_suspend, |
780 | .setup_aneg = bcm54xx_setup_aneg, | 780 | .setup_aneg = bcm54xx_setup_aneg, |
781 | .setup_forced = bcm54xx_setup_forced, | 781 | .setup_forced = bcm54xx_setup_forced, |
782 | .poll_link = genmii_poll_link, | 782 | .poll_link = genmii_poll_link, |
@@ -795,7 +795,7 @@ static struct mii_phy_def bcm5421k2_phy_def = { | |||
795 | /* Broadcom BCM 5462 built-in Vesta */ | 795 | /* Broadcom BCM 5462 built-in Vesta */ |
796 | static struct mii_phy_ops bcm5462V_phy_ops = { | 796 | static struct mii_phy_ops bcm5462V_phy_ops = { |
797 | .init = bcm5421_init, | 797 | .init = bcm5421_init, |
798 | .suspend = bcm5411_suspend, | 798 | .suspend = generic_suspend, |
799 | .setup_aneg = bcm54xx_setup_aneg, | 799 | .setup_aneg = bcm54xx_setup_aneg, |
800 | .setup_forced = bcm54xx_setup_forced, | 800 | .setup_forced = bcm54xx_setup_forced, |
801 | .poll_link = genmii_poll_link, | 801 | .poll_link = genmii_poll_link, |
@@ -816,6 +816,7 @@ static struct mii_phy_def bcm5462V_phy_def = { | |||
816 | * would be useful here) --BenH. | 816 | * would be useful here) --BenH. |
817 | */ | 817 | */ |
818 | static struct mii_phy_ops marvell_phy_ops = { | 818 | static struct mii_phy_ops marvell_phy_ops = { |
819 | .suspend = generic_suspend, | ||
819 | .setup_aneg = marvell_setup_aneg, | 820 | .setup_aneg = marvell_setup_aneg, |
820 | .setup_forced = marvell_setup_forced, | 821 | .setup_forced = marvell_setup_forced, |
821 | .poll_link = genmii_poll_link, | 822 | .poll_link = genmii_poll_link, |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 964c09644832..73e271e59c6a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -69,8 +69,8 @@ | |||
69 | 69 | ||
70 | #define DRV_MODULE_NAME "tg3" | 70 | #define DRV_MODULE_NAME "tg3" |
71 | #define PFX DRV_MODULE_NAME ": " | 71 | #define PFX DRV_MODULE_NAME ": " |
72 | #define DRV_MODULE_VERSION "3.55" | 72 | #define DRV_MODULE_VERSION "3.56" |
73 | #define DRV_MODULE_RELDATE "Mar 27, 2006" | 73 | #define DRV_MODULE_RELDATE "Apr 1, 2006" |
74 | 74 | ||
75 | #define TG3_DEF_MAC_MODE 0 | 75 | #define TG3_DEF_MAC_MODE 0 |
76 | #define TG3_DEF_RX_MODE 0 | 76 | #define TG3_DEF_RX_MODE 0 |
@@ -497,18 +497,18 @@ static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) | |||
497 | unsigned long flags; | 497 | unsigned long flags; |
498 | 498 | ||
499 | spin_lock_irqsave(&tp->indirect_lock, flags); | 499 | spin_lock_irqsave(&tp->indirect_lock, flags); |
500 | if (tp->write32 != tg3_write_indirect_reg32) { | 500 | if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { |
501 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); | ||
502 | tw32_f(TG3PCI_MEM_WIN_DATA, val); | ||
503 | |||
504 | /* Always leave this as zero. */ | ||
505 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); | ||
506 | } else { | ||
507 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); | 501 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); |
508 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); | 502 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); |
509 | 503 | ||
510 | /* Always leave this as zero. */ | 504 | /* Always leave this as zero. */ |
511 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); | 505 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); |
506 | } else { | ||
507 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); | ||
508 | tw32_f(TG3PCI_MEM_WIN_DATA, val); | ||
509 | |||
510 | /* Always leave this as zero. */ | ||
511 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); | ||
512 | } | 512 | } |
513 | spin_unlock_irqrestore(&tp->indirect_lock, flags); | 513 | spin_unlock_irqrestore(&tp->indirect_lock, flags); |
514 | } | 514 | } |
@@ -518,18 +518,18 @@ static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val) | |||
518 | unsigned long flags; | 518 | unsigned long flags; |
519 | 519 | ||
520 | spin_lock_irqsave(&tp->indirect_lock, flags); | 520 | spin_lock_irqsave(&tp->indirect_lock, flags); |
521 | if (tp->write32 != tg3_write_indirect_reg32) { | 521 | if (tp->tg3_flags & TG3_FLAG_SRAM_USE_CONFIG) { |
522 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); | ||
523 | *val = tr32(TG3PCI_MEM_WIN_DATA); | ||
524 | |||
525 | /* Always leave this as zero. */ | ||
526 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); | ||
527 | } else { | ||
528 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); | 522 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off); |
529 | pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); | 523 | pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val); |
530 | 524 | ||
531 | /* Always leave this as zero. */ | 525 | /* Always leave this as zero. */ |
532 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); | 526 | pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0); |
527 | } else { | ||
528 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off); | ||
529 | *val = tr32(TG3PCI_MEM_WIN_DATA); | ||
530 | |||
531 | /* Always leave this as zero. */ | ||
532 | tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0); | ||
533 | } | 533 | } |
534 | spin_unlock_irqrestore(&tp->indirect_lock, flags); | 534 | spin_unlock_irqrestore(&tp->indirect_lock, flags); |
535 | } | 535 | } |
@@ -2966,9 +2966,7 @@ static void tg3_tx(struct tg3 *tp) | |||
2966 | struct sk_buff *skb = ri->skb; | 2966 | struct sk_buff *skb = ri->skb; |
2967 | int i; | 2967 | int i; |
2968 | 2968 | ||
2969 | if (unlikely(skb == NULL)) | 2969 | BUG_ON(skb == NULL); |
2970 | BUG(); | ||
2971 | |||
2972 | pci_unmap_single(tp->pdev, | 2970 | pci_unmap_single(tp->pdev, |
2973 | pci_unmap_addr(ri, mapping), | 2971 | pci_unmap_addr(ri, mapping), |
2974 | skb_headlen(skb), | 2972 | skb_headlen(skb), |
@@ -2979,12 +2977,10 @@ static void tg3_tx(struct tg3 *tp) | |||
2979 | sw_idx = NEXT_TX(sw_idx); | 2977 | sw_idx = NEXT_TX(sw_idx); |
2980 | 2978 | ||
2981 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 2979 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
2982 | if (unlikely(sw_idx == hw_idx)) | 2980 | BUG_ON(sw_idx == hw_idx); |
2983 | BUG(); | ||
2984 | 2981 | ||
2985 | ri = &tp->tx_buffers[sw_idx]; | 2982 | ri = &tp->tx_buffers[sw_idx]; |
2986 | if (unlikely(ri->skb != NULL)) | 2983 | BUG_ON(ri->skb != NULL); |
2987 | BUG(); | ||
2988 | 2984 | ||
2989 | pci_unmap_page(tp->pdev, | 2985 | pci_unmap_page(tp->pdev, |
2990 | pci_unmap_addr(ri, mapping), | 2986 | pci_unmap_addr(ri, mapping), |
@@ -4935,9 +4931,8 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 offset) | |||
4935 | { | 4931 | { |
4936 | int i; | 4932 | int i; |
4937 | 4933 | ||
4938 | if (offset == TX_CPU_BASE && | 4934 | BUG_ON(offset == TX_CPU_BASE && |
4939 | (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) | 4935 | (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)); |
4940 | BUG(); | ||
4941 | 4936 | ||
4942 | if (offset == RX_CPU_BASE) { | 4937 | if (offset == RX_CPU_BASE) { |
4943 | for (i = 0; i < 10000; i++) { | 4938 | for (i = 0; i < 10000; i++) { |
@@ -5840,10 +5835,14 @@ static int tg3_reset_hw(struct tg3 *tp) | |||
5840 | GRC_MODE_NO_TX_PHDR_CSUM | | 5835 | GRC_MODE_NO_TX_PHDR_CSUM | |
5841 | GRC_MODE_NO_RX_PHDR_CSUM); | 5836 | GRC_MODE_NO_RX_PHDR_CSUM); |
5842 | tp->grc_mode |= GRC_MODE_HOST_SENDBDS; | 5837 | tp->grc_mode |= GRC_MODE_HOST_SENDBDS; |
5843 | if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM) | 5838 | |
5844 | tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; | 5839 | /* Pseudo-header checksum is done by hardware logic and not |
5845 | if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM) | 5840 | * the offload processers, so make the chip do the pseudo- |
5846 | tp->grc_mode |= GRC_MODE_NO_RX_PHDR_CSUM; | 5841 | * header checksums on receive. For transmit it is more |
5842 | * convenient to do the pseudo-header checksum in software | ||
5843 | * as Linux does that on transmit for us in all cases. | ||
5844 | */ | ||
5845 | tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM; | ||
5847 | 5846 | ||
5848 | tw32(GRC_MODE, | 5847 | tw32(GRC_MODE, |
5849 | tp->grc_mode | | 5848 | tp->grc_mode | |
@@ -8046,9 +8045,13 @@ static int tg3_test_nvram(struct tg3 *tp) | |||
8046 | for (i = 0; i < size; i++) | 8045 | for (i = 0; i < size; i++) |
8047 | csum8 += buf8[i]; | 8046 | csum8 += buf8[i]; |
8048 | 8047 | ||
8049 | if (csum8 == 0) | 8048 | if (csum8 == 0) { |
8050 | return 0; | 8049 | err = 0; |
8051 | return -EIO; | 8050 | goto out; |
8051 | } | ||
8052 | |||
8053 | err = -EIO; | ||
8054 | goto out; | ||
8052 | } | 8055 | } |
8053 | 8056 | ||
8054 | /* Bootstrap checksum at offset 0x10 */ | 8057 | /* Bootstrap checksum at offset 0x10 */ |
@@ -9543,8 +9546,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) | |||
9543 | tp->led_ctrl = LED_CTRL_MODE_PHY_1; | 9546 | tp->led_ctrl = LED_CTRL_MODE_PHY_1; |
9544 | 9547 | ||
9545 | /* Do not even try poking around in here on Sun parts. */ | 9548 | /* Do not even try poking around in here on Sun parts. */ |
9546 | if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) | 9549 | if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { |
9550 | /* All SUN chips are built-in LOMs. */ | ||
9551 | tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; | ||
9547 | return; | 9552 | return; |
9553 | } | ||
9548 | 9554 | ||
9549 | tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); | 9555 | tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val); |
9550 | if (val == NIC_SRAM_DATA_SIG_MAGIC) { | 9556 | if (val == NIC_SRAM_DATA_SIG_MAGIC) { |
@@ -9642,9 +9648,7 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp) | |||
9642 | tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) | 9648 | tp->pdev->subsystem_vendor == PCI_VENDOR_ID_DELL) |
9643 | tp->led_ctrl = LED_CTRL_MODE_PHY_2; | 9649 | tp->led_ctrl = LED_CTRL_MODE_PHY_2; |
9644 | 9650 | ||
9645 | if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700) && | 9651 | if (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP) |
9646 | (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) && | ||
9647 | (nic_cfg & NIC_SRAM_DATA_CFG_EEPROM_WP)) | ||
9648 | tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; | 9652 | tp->tg3_flags |= TG3_FLAG_EEPROM_WRITE_PROT; |
9649 | 9653 | ||
9650 | if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { | 9654 | if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { |
@@ -10269,6 +10273,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
10269 | pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); | 10273 | pci_write_config_word(tp->pdev, PCI_COMMAND, pci_cmd); |
10270 | } | 10274 | } |
10271 | 10275 | ||
10276 | if (tp->write32 == tg3_write_indirect_reg32 || | ||
10277 | ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) && | ||
10278 | (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || | ||
10279 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) || | ||
10280 | (tp->tg3_flags2 & TG3_FLG2_SUN_570X)) | ||
10281 | tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG; | ||
10282 | |||
10272 | /* Get eeprom hw config before calling tg3_set_power_state(). | 10283 | /* Get eeprom hw config before calling tg3_set_power_state(). |
10273 | * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be | 10284 | * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be |
10274 | * determined before calling tg3_set_power_state() so that | 10285 | * determined before calling tg3_set_power_state() so that |
@@ -10311,15 +10322,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) | |||
10311 | if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0) | 10322 | if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0) |
10312 | tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS; | 10323 | tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS; |
10313 | 10324 | ||
10314 | /* Pseudo-header checksum is done by hardware logic and not | ||
10315 | * the offload processers, so make the chip do the pseudo- | ||
10316 | * header checksums on receive. For transmit it is more | ||
10317 | * convenient to do the pseudo-header checksum in software | ||
10318 | * as Linux does that on transmit for us in all cases. | ||
10319 | */ | ||
10320 | tp->tg3_flags |= TG3_FLAG_NO_TX_PSEUDO_CSUM; | ||
10321 | tp->tg3_flags &= ~TG3_FLAG_NO_RX_PSEUDO_CSUM; | ||
10322 | |||
10323 | /* Derive initial jumbo mode from MTU assigned in | 10325 | /* Derive initial jumbo mode from MTU assigned in |
10324 | * ether_setup() via the alloc_etherdev() call | 10326 | * ether_setup() via the alloc_etherdev() call |
10325 | */ | 10327 | */ |
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index c43cc3264202..8c8b987d1250 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h | |||
@@ -2171,8 +2171,7 @@ struct tg3 { | |||
2171 | #define TG3_FLAG_PCIX_MODE 0x00020000 | 2171 | #define TG3_FLAG_PCIX_MODE 0x00020000 |
2172 | #define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 | 2172 | #define TG3_FLAG_PCI_HIGH_SPEED 0x00040000 |
2173 | #define TG3_FLAG_PCI_32BIT 0x00080000 | 2173 | #define TG3_FLAG_PCI_32BIT 0x00080000 |
2174 | #define TG3_FLAG_NO_TX_PSEUDO_CSUM 0x00100000 | 2174 | #define TG3_FLAG_SRAM_USE_CONFIG 0x00100000 |
2175 | #define TG3_FLAG_NO_RX_PSEUDO_CSUM 0x00200000 | ||
2176 | #define TG3_FLAG_SERDES_WOL_CAP 0x00400000 | 2175 | #define TG3_FLAG_SERDES_WOL_CAP 0x00400000 |
2177 | #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 | 2176 | #define TG3_FLAG_JUMBO_RING_ENABLE 0x00800000 |
2178 | #define TG3_FLAG_10_100_ONLY 0x01000000 | 2177 | #define TG3_FLAG_10_100_ONLY 0x01000000 |
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c index 9345e68c451e..649d8ea354f5 100644 --- a/drivers/net/tokenring/abyss.c +++ b/drivers/net/tokenring/abyss.c | |||
@@ -438,8 +438,7 @@ static void __devexit abyss_detach (struct pci_dev *pdev) | |||
438 | { | 438 | { |
439 | struct net_device *dev = pci_get_drvdata(pdev); | 439 | struct net_device *dev = pci_get_drvdata(pdev); |
440 | 440 | ||
441 | if (!dev) | 441 | BUG_ON(!dev); |
442 | BUG(); | ||
443 | unregister_netdev(dev); | 442 | unregister_netdev(dev); |
444 | release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT); | 443 | release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT); |
445 | free_irq(dev->irq, dev); | 444 | free_irq(dev->irq, dev); |
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c index 3a25d191ea4a..19e6f4dfd69c 100644 --- a/drivers/net/tokenring/madgemc.c +++ b/drivers/net/tokenring/madgemc.c | |||
@@ -735,8 +735,7 @@ static int __devexit madgemc_remove(struct device *device) | |||
735 | struct net_local *tp; | 735 | struct net_local *tp; |
736 | struct card_info *card; | 736 | struct card_info *card; |
737 | 737 | ||
738 | if (!dev) | 738 | BUG_ON(!dev); |
739 | BUG(); | ||
740 | 739 | ||
741 | tp = dev->priv; | 740 | tp = dev->priv; |
742 | card = tp->tmspriv; | 741 | card = tp->tmspriv; |
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index c1ce87a5f8d3..d9258d42090c 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c | |||
@@ -134,7 +134,7 @@ static const int multicast_filter_limit = 32; | |||
134 | #include "typhoon.h" | 134 | #include "typhoon.h" |
135 | #include "typhoon-firmware.h" | 135 | #include "typhoon-firmware.h" |
136 | 136 | ||
137 | static char version[] __devinitdata = | 137 | static const char version[] __devinitdata = |
138 | "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 138 | "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; |
139 | 139 | ||
140 | MODULE_AUTHOR("David Dillow <dave@thedillows.org>"); | 140 | MODULE_AUTHOR("David Dillow <dave@thedillows.org>"); |
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index a9b2150909d6..6a23964c1317 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c | |||
@@ -469,7 +469,7 @@ struct rhine_private { | |||
469 | struct sk_buff *tx_skbuff[TX_RING_SIZE]; | 469 | struct sk_buff *tx_skbuff[TX_RING_SIZE]; |
470 | dma_addr_t tx_skbuff_dma[TX_RING_SIZE]; | 470 | dma_addr_t tx_skbuff_dma[TX_RING_SIZE]; |
471 | 471 | ||
472 | /* Tx bounce buffers */ | 472 | /* Tx bounce buffers (Rhine-I only) */ |
473 | unsigned char *tx_buf[TX_RING_SIZE]; | 473 | unsigned char *tx_buf[TX_RING_SIZE]; |
474 | unsigned char *tx_bufs; | 474 | unsigned char *tx_bufs; |
475 | dma_addr_t tx_bufs_dma; | 475 | dma_addr_t tx_bufs_dma; |
@@ -1043,7 +1043,8 @@ static void alloc_tbufs(struct net_device* dev) | |||
1043 | rp->tx_ring[i].desc_length = cpu_to_le32(TXDESC); | 1043 | rp->tx_ring[i].desc_length = cpu_to_le32(TXDESC); |
1044 | next += sizeof(struct tx_desc); | 1044 | next += sizeof(struct tx_desc); |
1045 | rp->tx_ring[i].next_desc = cpu_to_le32(next); | 1045 | rp->tx_ring[i].next_desc = cpu_to_le32(next); |
1046 | rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ]; | 1046 | if (rp->quirks & rqRhineI) |
1047 | rp->tx_buf[i] = &rp->tx_bufs[i * PKT_BUF_SZ]; | ||
1047 | } | 1048 | } |
1048 | rp->tx_ring[i-1].next_desc = cpu_to_le32(rp->tx_ring_dma); | 1049 | rp->tx_ring[i-1].next_desc = cpu_to_le32(rp->tx_ring_dma); |
1049 | 1050 | ||
@@ -1091,7 +1092,7 @@ static void rhine_check_media(struct net_device *dev, unsigned int init_media) | |||
1091 | } | 1092 | } |
1092 | 1093 | ||
1093 | /* Called after status of force_media possibly changed */ | 1094 | /* Called after status of force_media possibly changed */ |
1094 | void rhine_set_carrier(struct mii_if_info *mii) | 1095 | static void rhine_set_carrier(struct mii_if_info *mii) |
1095 | { | 1096 | { |
1096 | if (mii->force_media) { | 1097 | if (mii->force_media) { |
1097 | /* autoneg is off: Link is always assumed to be up */ | 1098 | /* autoneg is off: Link is always assumed to be up */ |
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 883cf7da10fc..b5328b0ff927 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig | |||
@@ -410,103 +410,6 @@ config WAN_ROUTER_DRIVERS | |||
410 | 410 | ||
411 | If unsure, say N. | 411 | If unsure, say N. |
412 | 412 | ||
413 | config VENDOR_SANGOMA | ||
414 | tristate "Sangoma WANPIPE(tm) multiprotocol cards" | ||
415 | depends on WAN_ROUTER_DRIVERS && WAN_ROUTER && (PCI || ISA) && BROKEN | ||
416 | ---help--- | ||
417 | Driver for S514-PCI/ISA Synchronous Data Link Adapters (SDLA). | ||
418 | |||
419 | WANPIPE from Sangoma Technologies Inc. <http://www.sangoma.com/> | ||
420 | is a family of intelligent multiprotocol WAN adapters with data | ||
421 | transfer rates up to 4Mbps. Cards support: | ||
422 | |||
423 | - X.25, Frame Relay, PPP, Cisco HDLC protocols. | ||
424 | |||
425 | - API for protocols like HDLC (LAPB), HDLC Streaming, X.25, | ||
426 | Frame Relay and BiSync. | ||
427 | |||
428 | - Ethernet Bridging over Frame Relay protocol. | ||
429 | |||
430 | - MULTILINK PPP | ||
431 | |||
432 | - Async PPP (Modem Dialup) | ||
433 | |||
434 | The next questions will ask you about the protocols you want | ||
435 | the driver to support. | ||
436 | |||
437 | If you have one or more of these cards, say M to this option; | ||
438 | and read <file:Documentation/networking/wan-router.txt>. | ||
439 | |||
440 | To compile this driver as a module, choose M here: the | ||
441 | module will be called wanpipe. | ||
442 | |||
443 | config WANPIPE_CHDLC | ||
444 | bool "WANPIPE Cisco HDLC support" | ||
445 | depends on VENDOR_SANGOMA | ||
446 | ---help--- | ||
447 | Connect a WANPIPE card to a leased line using the Cisco HDLC. | ||
448 | |||
449 | - Supports Dual Port Cisco HDLC on the S514-PCI/S508-ISA cards | ||
450 | which allows user to build applications using the HDLC streaming API. | ||
451 | |||
452 | - CHDLC Streaming MULTILINK PPP that can bind multiple WANPIPE T1 | ||
453 | cards into a single logical channel. | ||
454 | |||
455 | Say Y and the Cisco HDLC support, HDLC streaming API and | ||
456 | MULTILINK PPP will be included in the driver. | ||
457 | |||
458 | config WANPIPE_FR | ||
459 | bool "WANPIPE Frame Relay support" | ||
460 | depends on VENDOR_SANGOMA | ||
461 | help | ||
462 | Connect a WANPIPE card to a Frame Relay network, or use Frame Relay | ||
463 | API to develop custom applications. | ||
464 | |||
465 | Contains the Ethernet Bridging over Frame Relay feature, where | ||
466 | a WANPIPE frame relay link can be directly connected to the Linux | ||
467 | kernel bridge. The Frame Relay option is supported on S514-PCI | ||
468 | and S508-ISA cards. | ||
469 | |||
470 | Say Y and the Frame Relay support will be included in the driver. | ||
471 | |||
472 | config WANPIPE_X25 | ||
473 | bool "WANPIPE X.25 support" | ||
474 | depends on VENDOR_SANGOMA | ||
475 | help | ||
476 | Connect a WANPIPE card to an X.25 network. | ||
477 | |||
478 | Includes the X.25 API support for custom applications over the | ||
479 | X.25 protocol. The X.25 option is supported on S514-PCI and | ||
480 | S508-ISA cards. | ||
481 | |||
482 | Say Y and the X.25 support will be included in the driver. | ||
483 | |||
484 | config WANPIPE_PPP | ||
485 | bool "WANPIPE PPP support" | ||
486 | depends on VENDOR_SANGOMA | ||
487 | help | ||
488 | Connect a WANPIPE card to a leased line using Point-to-Point | ||
489 | Protocol (PPP). | ||
490 | |||
491 | The PPP option is supported on S514-PCI/S508-ISA cards. | ||
492 | |||
493 | Say Y and the PPP support will be included in the driver. | ||
494 | |||
495 | config WANPIPE_MULTPPP | ||
496 | bool "WANPIPE Multi-Port PPP support" | ||
497 | depends on VENDOR_SANGOMA | ||
498 | help | ||
499 | Connect a WANPIPE card to a leased line using Point-to-Point | ||
500 | Protocol (PPP). | ||
501 | |||
502 | Uses in-kernel SyncPPP protocol over the Sangoma HDLC Streaming | ||
503 | adapter. In this case each Sangoma adapter port can support an | ||
504 | independent PPP connection. For example, a single Quad-Port PCI | ||
505 | adapter can support up to four independent PPP links. The PPP | ||
506 | option is supported on S514-PCI/S508-ISA cards. | ||
507 | |||
508 | Say Y and the Multi-Port PPP support will be included in the driver. | ||
509 | |||
510 | config CYCLADES_SYNC | 413 | config CYCLADES_SYNC |
511 | tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)" | 414 | tristate "Cyclom 2X(tm) cards (EXPERIMENTAL)" |
512 | depends on WAN_ROUTER_DRIVERS && (PCI || ISA) | 415 | depends on WAN_ROUTER_DRIVERS && (PCI || ISA) |
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile index ce6c56b903e7..823c6d5ab90d 100644 --- a/drivers/net/wan/Makefile +++ b/drivers/net/wan/Makefile | |||
@@ -5,14 +5,6 @@ | |||
5 | # Rewritten to use lists instead of if-statements. | 5 | # Rewritten to use lists instead of if-statements. |
6 | # | 6 | # |
7 | 7 | ||
8 | wanpipe-y := sdlamain.o sdla_ft1.o | ||
9 | wanpipe-$(CONFIG_WANPIPE_X25) += sdla_x25.o | ||
10 | wanpipe-$(CONFIG_WANPIPE_FR) += sdla_fr.o | ||
11 | wanpipe-$(CONFIG_WANPIPE_CHDLC) += sdla_chdlc.o | ||
12 | wanpipe-$(CONFIG_WANPIPE_PPP) += sdla_ppp.o | ||
13 | wanpipe-$(CONFIG_WANPIPE_MULTPPP) += wanpipe_multppp.o | ||
14 | wanpipe-objs := $(wanpipe-y) | ||
15 | |||
16 | cyclomx-y := cycx_main.o | 8 | cyclomx-y := cycx_main.o |
17 | cyclomx-$(CONFIG_CYCLOMX_X25) += cycx_x25.o | 9 | cyclomx-$(CONFIG_CYCLOMX_X25) += cycx_x25.o |
18 | cyclomx-objs := $(cyclomx-y) | 10 | cyclomx-objs := $(cyclomx-y) |
@@ -43,11 +35,6 @@ obj-$(CONFIG_LANMEDIA) += lmc/ | |||
43 | 35 | ||
44 | obj-$(CONFIG_DLCI) += dlci.o | 36 | obj-$(CONFIG_DLCI) += dlci.o |
45 | obj-$(CONFIG_SDLA) += sdla.o | 37 | obj-$(CONFIG_SDLA) += sdla.o |
46 | ifeq ($(CONFIG_WANPIPE_MULTPPP),y) | ||
47 | obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o syncppp.o | ||
48 | else | ||
49 | obj-$(CONFIG_VENDOR_SANGOMA) += sdladrv.o wanpipe.o | ||
50 | endif | ||
51 | obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o | 38 | obj-$(CONFIG_CYCLADES_SYNC) += cycx_drv.o cyclomx.o |
52 | obj-$(CONFIG_LAPBETHER) += lapbether.o | 39 | obj-$(CONFIG_LAPBETHER) += lapbether.o |
53 | obj-$(CONFIG_SBNI) += sbni.o | 40 | obj-$(CONFIG_SBNI) += sbni.o |
diff --git a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c deleted file mode 100644 index 496d29237e92..000000000000 --- a/drivers/net/wan/sdla_chdlc.c +++ /dev/null | |||
@@ -1,4428 +0,0 @@ | |||
1 | /***************************************************************************** | ||
2 | * sdla_chdlc.c WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module. | ||
3 | * | ||
4 | * Authors: Nenad Corbic <ncorbic@sangoma.com> | ||
5 | * Gideon Hack | ||
6 | * | ||
7 | * Copyright: (c) 1995-2001 Sangoma Technologies Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | * ============================================================================ | ||
14 | * Feb 28, 2001 Nenad Corbic Updated if_tx_timeout() routine for | ||
15 | * 2.4.X kernels. | ||
16 | * Jan 25, 2001 Nenad Corbic Added a TTY Sync serial driver over the | ||
17 | * HDLC streaming protocol | ||
18 | * Added a TTY Async serial driver over the | ||
19 | * Async protocol. | ||
20 | * Dec 15, 2000 Nenad Corbic Updated for 2.4.X Kernel support | ||
21 | * Nov 13, 2000 Nenad Corbic Added true interface type encoding option. | ||
22 | * Tcpdump doesn't support CHDLC inteface | ||
23 | * types, to fix this "true type" option will set | ||
24 | * the interface type to RAW IP mode. | ||
25 | * Nov 07, 2000 Nenad Corbic Added security features for UDP debugging: | ||
26 | * Deny all and specify allowed requests. | ||
27 | * Jun 20, 2000 Nenad Corbic Fixed the API IP ERROR bug. Caused by the | ||
28 | * latest update. | ||
29 | * May 09, 2000 Nenad Corbic Option to bring down an interface | ||
30 | * upon disconnect. | ||
31 | * Mar 23, 2000 Nenad Corbic Improved task queue, bh handling. | ||
32 | * Mar 16, 2000 Nenad Corbic Fixed the SLARP Dynamic IP addressing. | ||
33 | * Mar 06, 2000 Nenad Corbic Bug Fix: corrupted mbox recovery. | ||
34 | * Feb 10, 2000 Gideon Hack Added ASYNC support. | ||
35 | * Feb 09, 2000 Nenad Corbic Fixed two shutdown bugs in update() and | ||
36 | * if_stats() functions. | ||
37 | * Jan 24, 2000 Nenad Corbic Fixed a startup wanpipe state racing, | ||
38 | * condition between if_open and isr. | ||
39 | * Jan 10, 2000 Nenad Corbic Added new socket API support. | ||
40 | * Dev 15, 1999 Nenad Corbic Fixed up header files for 2.0.X kernels | ||
41 | * Nov 20, 1999 Nenad Corbic Fixed zero length API bug. | ||
42 | * Sep 30, 1999 Nenad Corbic Fixed dynamic IP and route setup. | ||
43 | * Sep 23, 1999 Nenad Corbic Added SMP support, fixed tracing | ||
44 | * Sep 13, 1999 Nenad Corbic Split up Port 0 and 1 into separate devices. | ||
45 | * Jun 02, 1999 Gideon Hack Added support for the S514 adapter. | ||
46 | * Oct 30, 1998 Jaspreet Singh Added Support for CHDLC API (HDLC STREAMING). | ||
47 | * Oct 28, 1998 Jaspreet Singh Added Support for Dual Port CHDLC. | ||
48 | * Aug 07, 1998 David Fong Initial version. | ||
49 | *****************************************************************************/ | ||
50 | |||
51 | #include <linux/module.h> | ||
52 | #include <linux/kernel.h> /* printk(), and other useful stuff */ | ||
53 | #include <linux/stddef.h> /* offsetof(), etc. */ | ||
54 | #include <linux/errno.h> /* return codes */ | ||
55 | #include <linux/string.h> /* inline memset(), etc. */ | ||
56 | #include <linux/slab.h> /* kmalloc(), kfree() */ | ||
57 | #include <linux/wanrouter.h> /* WAN router definitions */ | ||
58 | #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ | ||
59 | #include <linux/if_arp.h> /* ARPHRD_* defines */ | ||
60 | |||
61 | |||
62 | #include <asm/uaccess.h> | ||
63 | #include <linux/inetdevice.h> | ||
64 | #include <linux/netdevice.h> | ||
65 | |||
66 | #include <linux/in.h> /* sockaddr_in */ | ||
67 | #include <linux/inet.h> | ||
68 | #include <linux/if.h> | ||
69 | #include <asm/byteorder.h> /* htons(), etc. */ | ||
70 | #include <linux/sdlapci.h> | ||
71 | #include <asm/io.h> | ||
72 | |||
73 | #include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */ | ||
74 | #include <linux/sdla_asy.h> /* CHDLC (async) API definitions */ | ||
75 | |||
76 | #include <linux/if_wanpipe_common.h> /* Socket Driver common area */ | ||
77 | #include <linux/if_wanpipe.h> | ||
78 | |||
79 | /* TTY Includes */ | ||
80 | #include <linux/tty.h> | ||
81 | #include <linux/tty_flip.h> | ||
82 | #include <linux/serial.h> | ||
83 | |||
84 | |||
85 | /****** Defines & Macros ****************************************************/ | ||
86 | |||
87 | /* reasons for enabling the timer interrupt on the adapter */ | ||
88 | #define TMR_INT_ENABLED_UDP 0x01 | ||
89 | #define TMR_INT_ENABLED_UPDATE 0x02 | ||
90 | #define TMR_INT_ENABLED_CONFIG 0x10 | ||
91 | |||
92 | #define MAX_IP_ERRORS 10 | ||
93 | |||
94 | #define TTY_CHDLC_MAX_MTU 2000 | ||
95 | #define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */ | ||
96 | #define CHDLC_HDR_LEN 1 | ||
97 | |||
98 | #define CHDLC_API 0x01 | ||
99 | |||
100 | #define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" ) | ||
101 | #define MAX_BH_BUFF 10 | ||
102 | |||
103 | //#define PRINT_DEBUG | ||
104 | #ifdef PRINT_DEBUG | ||
105 | #define dbg_printk(format, a...) printk(format, ## a) | ||
106 | #else | ||
107 | #define dbg_printk(format, a...) | ||
108 | #endif | ||
109 | |||
110 | /******Data Structures*****************************************************/ | ||
111 | |||
112 | /* This structure is placed in the private data area of the device structure. | ||
113 | * The card structure used to occupy the private area but now the following | ||
114 | * structure will incorporate the card structure along with CHDLC specific data | ||
115 | */ | ||
116 | |||
117 | typedef struct chdlc_private_area | ||
118 | { | ||
119 | wanpipe_common_t common; | ||
120 | sdla_t *card; | ||
121 | int TracingEnabled; /* For enabling Tracing */ | ||
122 | unsigned long curr_trace_addr; /* Used for Tracing */ | ||
123 | unsigned long start_trace_addr; | ||
124 | unsigned long end_trace_addr; | ||
125 | unsigned long base_addr_trace_buffer; | ||
126 | unsigned long end_addr_trace_buffer; | ||
127 | unsigned short number_trace_elements; | ||
128 | unsigned available_buffer_space; | ||
129 | unsigned long router_start_time; | ||
130 | unsigned char route_status; | ||
131 | unsigned char route_removed; | ||
132 | unsigned long tick_counter; /* For 5s timeout counter */ | ||
133 | unsigned long router_up_time; | ||
134 | u32 IP_address; /* IP addressing */ | ||
135 | u32 IP_netmask; | ||
136 | u32 ip_local; | ||
137 | u32 ip_remote; | ||
138 | u32 ip_local_tmp; | ||
139 | u32 ip_remote_tmp; | ||
140 | u8 ip_error; | ||
141 | u8 config_chdlc; | ||
142 | u8 config_chdlc_timeout; | ||
143 | unsigned char mc; /* Mulitcast support on/off */ | ||
144 | unsigned short udp_pkt_lgth; /* udp packet processing */ | ||
145 | char udp_pkt_src; | ||
146 | char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; | ||
147 | unsigned short timer_int_enabled; | ||
148 | char update_comms_stats; /* updating comms stats */ | ||
149 | |||
150 | bh_data_t *bh_head; /* Circular buffer for chdlc_bh */ | ||
151 | unsigned long tq_working; | ||
152 | volatile int bh_write; | ||
153 | volatile int bh_read; | ||
154 | atomic_t bh_buff_used; | ||
155 | |||
156 | unsigned char interface_down; | ||
157 | |||
158 | /* Polling work queue entry. Each interface | ||
159 | * has its own work queue entry, which is used | ||
160 | * to defer events from the interrupt */ | ||
161 | struct work_struct poll_work; | ||
162 | struct timer_list poll_delay_timer; | ||
163 | |||
164 | u8 gateway; | ||
165 | u8 true_if_encoding; | ||
166 | //FIXME: add driver stats as per frame relay! | ||
167 | |||
168 | } chdlc_private_area_t; | ||
169 | |||
170 | /* Route Status options */ | ||
171 | #define NO_ROUTE 0x00 | ||
172 | #define ADD_ROUTE 0x01 | ||
173 | #define ROUTE_ADDED 0x02 | ||
174 | #define REMOVE_ROUTE 0x03 | ||
175 | |||
176 | |||
177 | /* variable for keeping track of enabling/disabling FT1 monitor status */ | ||
178 | static int rCount = 0; | ||
179 | |||
180 | /* variable for tracking how many interfaces to open for WANPIPE on the | ||
181 | two ports */ | ||
182 | |||
183 | extern void disable_irq(unsigned int); | ||
184 | extern void enable_irq(unsigned int); | ||
185 | |||
186 | /****** Function Prototypes *************************************************/ | ||
187 | /* WAN link driver entry points. These are called by the WAN router module. */ | ||
188 | static int update(struct wan_device* wandev); | ||
189 | static int new_if(struct wan_device* wandev, struct net_device* dev, | ||
190 | wanif_conf_t* conf); | ||
191 | |||
192 | /* Network device interface */ | ||
193 | static int if_init(struct net_device* dev); | ||
194 | static int if_open(struct net_device* dev); | ||
195 | static int if_close(struct net_device* dev); | ||
196 | static int if_header(struct sk_buff* skb, struct net_device* dev, | ||
197 | unsigned short type, void* daddr, void* saddr, | ||
198 | unsigned len); | ||
199 | |||
200 | static int if_rebuild_hdr (struct sk_buff *skb); | ||
201 | static struct net_device_stats* if_stats(struct net_device* dev); | ||
202 | |||
203 | static int if_send(struct sk_buff* skb, struct net_device* dev); | ||
204 | |||
205 | /* CHDLC Firmware interface functions */ | ||
206 | static int chdlc_configure (sdla_t* card, void* data); | ||
207 | static int chdlc_comm_enable (sdla_t* card); | ||
208 | static int chdlc_read_version (sdla_t* card, char* str); | ||
209 | static int chdlc_set_intr_mode (sdla_t* card, unsigned mode); | ||
210 | static int chdlc_send (sdla_t* card, void* data, unsigned len); | ||
211 | static int chdlc_read_comm_err_stats (sdla_t* card); | ||
212 | static int chdlc_read_op_stats (sdla_t* card); | ||
213 | static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb); | ||
214 | |||
215 | |||
216 | static int chdlc_disable_comm_shutdown (sdla_t *card); | ||
217 | static void if_tx_timeout(struct net_device *dev); | ||
218 | |||
219 | /* Miscellaneous CHDLC Functions */ | ||
220 | static int set_chdlc_config (sdla_t* card); | ||
221 | static void init_chdlc_tx_rx_buff( sdla_t* card); | ||
222 | static int process_chdlc_exception(sdla_t *card); | ||
223 | static int process_global_exception(sdla_t *card); | ||
224 | static int update_comms_stats(sdla_t* card, | ||
225 | chdlc_private_area_t* chdlc_priv_area); | ||
226 | static int configure_ip (sdla_t* card); | ||
227 | static int unconfigure_ip (sdla_t* card); | ||
228 | static void process_route(sdla_t *card); | ||
229 | static void port_set_state (sdla_t *card, int); | ||
230 | static int config_chdlc (sdla_t *card); | ||
231 | static void disable_comm (sdla_t *card); | ||
232 | |||
233 | static void trigger_chdlc_poll(struct net_device *dev); | ||
234 | static void chdlc_poll(struct net_device *dev); | ||
235 | static void chdlc_poll_delay (unsigned long dev_ptr); | ||
236 | |||
237 | |||
238 | /* Miscellaneous asynchronous interface Functions */ | ||
239 | static int set_asy_config (sdla_t* card); | ||
240 | static int asy_comm_enable (sdla_t* card); | ||
241 | |||
242 | /* Interrupt handlers */ | ||
243 | static void wpc_isr (sdla_t* card); | ||
244 | static void rx_intr (sdla_t* card); | ||
245 | static void timer_intr(sdla_t *); | ||
246 | |||
247 | /* Bottom half handlers */ | ||
248 | static void chdlc_work(struct net_device *dev); | ||
249 | static int chdlc_work_cleanup(struct net_device *dev); | ||
250 | static int bh_enqueue(struct net_device *dev, struct sk_buff *skb); | ||
251 | |||
252 | /* Miscellaneous functions */ | ||
253 | static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev, | ||
254 | struct sk_buff *skb); | ||
255 | static int reply_udp( unsigned char *data, unsigned int mbox_len ); | ||
256 | static int intr_test( sdla_t* card); | ||
257 | static int udp_pkt_type( struct sk_buff *skb , sdla_t* card); | ||
258 | static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, | ||
259 | struct sk_buff *skb, struct net_device* dev, | ||
260 | chdlc_private_area_t* chdlc_priv_area); | ||
261 | static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev, | ||
262 | chdlc_private_area_t* chdlc_priv_area); | ||
263 | static unsigned short calc_checksum (char *, int); | ||
264 | static void s508_lock (sdla_t *card, unsigned long *smp_flags); | ||
265 | static void s508_unlock (sdla_t *card, unsigned long *smp_flags); | ||
266 | |||
267 | |||
268 | static int Intr_test_counter; | ||
269 | |||
270 | /* TTY Global Definitions */ | ||
271 | |||
272 | #define NR_PORTS 4 | ||
273 | #define WAN_TTY_MAJOR 226 | ||
274 | #define WAN_TTY_MINOR 0 | ||
275 | |||
276 | #define WAN_CARD(port) (tty_card_map[port]) | ||
277 | #define MIN_PORT 0 | ||
278 | #define MAX_PORT NR_PORTS-1 | ||
279 | |||
280 | #define CRC_LENGTH 2 | ||
281 | |||
282 | static int wanpipe_tty_init(sdla_t *card); | ||
283 | static void wanpipe_tty_receive(sdla_t *, unsigned, unsigned int); | ||
284 | static void wanpipe_tty_trigger_poll(sdla_t *card); | ||
285 | |||
286 | static struct tty_driver serial_driver; | ||
287 | static int tty_init_cnt=0; | ||
288 | |||
289 | static struct serial_state rs_table[NR_PORTS]; | ||
290 | |||
291 | static char tty_driver_mode=WANOPT_TTY_SYNC; | ||
292 | |||
293 | static char *opt_decode[] = {"NONE","CRTSCTS","XONXOFF-RX", | ||
294 | "CRTSCTS XONXOFF-RX","XONXOFF-TX", | ||
295 | "CRTSCTS XONXOFF-TX","CRTSCTS XONXOFF"}; | ||
296 | static char *p_decode[] = {"NONE","ODD","EVEN"}; | ||
297 | |||
298 | static void* tty_card_map[NR_PORTS] = {NULL,NULL,NULL,NULL}; | ||
299 | |||
300 | |||
301 | /****** Public Functions ****************************************************/ | ||
302 | |||
303 | /*============================================================================ | ||
304 | * Cisco HDLC protocol initialization routine. | ||
305 | * | ||
306 | * This routine is called by the main WANPIPE module during setup. At this | ||
307 | * point adapter is completely initialized and firmware is running. | ||
308 | * o read firmware version (to make sure it's alive) | ||
309 | * o configure adapter | ||
310 | * o initialize protocol-specific fields of the adapter data space. | ||
311 | * | ||
312 | * Return: 0 o.k. | ||
313 | * < 0 failure. | ||
314 | */ | ||
315 | int wpc_init (sdla_t* card, wandev_conf_t* conf) | ||
316 | { | ||
317 | unsigned char port_num; | ||
318 | int err; | ||
319 | unsigned long max_permitted_baud = 0; | ||
320 | SHARED_MEMORY_INFO_STRUCT *flags; | ||
321 | |||
322 | union | ||
323 | { | ||
324 | char str[80]; | ||
325 | } u; | ||
326 | volatile CHDLC_MAILBOX_STRUCT* mb; | ||
327 | CHDLC_MAILBOX_STRUCT* mb1; | ||
328 | unsigned long timeout; | ||
329 | |||
330 | /* Verify configuration ID */ | ||
331 | if (conf->config_id != WANCONFIG_CHDLC) { | ||
332 | printk(KERN_INFO "%s: invalid configuration ID %u!\n", | ||
333 | card->devname, conf->config_id); | ||
334 | return -EINVAL; | ||
335 | } | ||
336 | |||
337 | /* Find out which Port to use */ | ||
338 | if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){ | ||
339 | if (card->next){ | ||
340 | |||
341 | if (conf->comm_port != card->next->u.c.comm_port){ | ||
342 | card->u.c.comm_port = conf->comm_port; | ||
343 | }else{ | ||
344 | printk(KERN_INFO "%s: ERROR - %s port used!\n", | ||
345 | card->wandev.name, PORT(conf->comm_port)); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | }else{ | ||
349 | card->u.c.comm_port = conf->comm_port; | ||
350 | } | ||
351 | }else{ | ||
352 | printk(KERN_INFO "%s: ERROR - Invalid Port Selected!\n", | ||
353 | card->wandev.name); | ||
354 | return -EINVAL; | ||
355 | } | ||
356 | |||
357 | |||
358 | /* Initialize protocol-specific fields */ | ||
359 | if(card->hw.type != SDLA_S514){ | ||
360 | |||
361 | if (card->u.c.comm_port == WANOPT_PRI){ | ||
362 | card->mbox = (void *) card->hw.dpmbase; | ||
363 | }else{ | ||
364 | card->mbox = (void *) card->hw.dpmbase + | ||
365 | SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT; | ||
366 | } | ||
367 | }else{ | ||
368 | /* for a S514 adapter, set a pointer to the actual mailbox in the */ | ||
369 | /* allocated virtual memory area */ | ||
370 | if (card->u.c.comm_port == WANOPT_PRI){ | ||
371 | card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT; | ||
372 | }else{ | ||
373 | card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT; | ||
374 | } | ||
375 | } | ||
376 | |||
377 | mb = mb1 = card->mbox; | ||
378 | |||
379 | if (!card->configured){ | ||
380 | |||
381 | /* The board will place an 'I' in the return code to indicate that it is | ||
382 | ready to accept commands. We expect this to be completed in less | ||
383 | than 1 second. */ | ||
384 | |||
385 | timeout = jiffies; | ||
386 | while (mb->return_code != 'I') /* Wait 1s for board to initialize */ | ||
387 | if ((jiffies - timeout) > 1*HZ) break; | ||
388 | |||
389 | if (mb->return_code != 'I') { | ||
390 | printk(KERN_INFO | ||
391 | "%s: Initialization not completed by adapter\n", | ||
392 | card->devname); | ||
393 | printk(KERN_INFO "Please contact Sangoma representative.\n"); | ||
394 | return -EIO; | ||
395 | } | ||
396 | } | ||
397 | |||
398 | /* Read firmware version. Note that when adapter initializes, it | ||
399 | * clears the mailbox, so it may appear that the first command was | ||
400 | * executed successfully when in fact it was merely erased. To work | ||
401 | * around this, we execute the first command twice. | ||
402 | */ | ||
403 | |||
404 | if (chdlc_read_version(card, u.str)) | ||
405 | return -EIO; | ||
406 | |||
407 | printk(KERN_INFO "%s: Running Cisco HDLC firmware v%s\n", | ||
408 | card->devname, u.str); | ||
409 | |||
410 | card->isr = &wpc_isr; | ||
411 | card->poll = NULL; | ||
412 | card->exec = NULL; | ||
413 | card->wandev.update = &update; | ||
414 | card->wandev.new_if = &new_if; | ||
415 | card->wandev.del_if = NULL; | ||
416 | card->wandev.udp_port = conf->udp_port; | ||
417 | card->disable_comm = &disable_comm; | ||
418 | card->wandev.new_if_cnt = 0; | ||
419 | |||
420 | /* reset the number of times the 'update()' proc has been called */ | ||
421 | card->u.c.update_call_count = 0; | ||
422 | |||
423 | card->wandev.ttl = conf->ttl; | ||
424 | card->wandev.interface = conf->interface; | ||
425 | |||
426 | if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&& | ||
427 | card->hw.type != SDLA_S514){ | ||
428 | printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n", | ||
429 | card->devname, PORT(card->u.c.comm_port)); | ||
430 | return -EIO; | ||
431 | } | ||
432 | |||
433 | card->wandev.clocking = conf->clocking; | ||
434 | |||
435 | port_num = card->u.c.comm_port; | ||
436 | |||
437 | /* in API mode, we can configure for "receive only" buffering */ | ||
438 | if(card->hw.type == SDLA_S514) { | ||
439 | card->u.c.receive_only = conf->receive_only; | ||
440 | if(conf->receive_only) { | ||
441 | printk(KERN_INFO | ||
442 | "%s: Configured for 'receive only' mode\n", | ||
443 | card->devname); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | /* Setup Port Bps */ | ||
448 | |||
449 | if(card->wandev.clocking) { | ||
450 | if((port_num == WANOPT_PRI) || card->u.c.receive_only) { | ||
451 | /* For Primary Port 0 */ | ||
452 | max_permitted_baud = | ||
453 | (card->hw.type == SDLA_S514) ? | ||
454 | PRI_MAX_BAUD_RATE_S514 : | ||
455 | PRI_MAX_BAUD_RATE_S508; | ||
456 | |||
457 | }else if(port_num == WANOPT_SEC) { | ||
458 | /* For Secondary Port 1 */ | ||
459 | max_permitted_baud = | ||
460 | (card->hw.type == SDLA_S514) ? | ||
461 | SEC_MAX_BAUD_RATE_S514 : | ||
462 | SEC_MAX_BAUD_RATE_S508; | ||
463 | } | ||
464 | |||
465 | if(conf->bps > max_permitted_baud) { | ||
466 | conf->bps = max_permitted_baud; | ||
467 | printk(KERN_INFO "%s: Baud too high!\n", | ||
468 | card->wandev.name); | ||
469 | printk(KERN_INFO "%s: Baud rate set to %lu bps\n", | ||
470 | card->wandev.name, max_permitted_baud); | ||
471 | } | ||
472 | card->wandev.bps = conf->bps; | ||
473 | }else{ | ||
474 | card->wandev.bps = 0; | ||
475 | } | ||
476 | |||
477 | /* Setup the Port MTU */ | ||
478 | if((port_num == WANOPT_PRI) || card->u.c.receive_only) { | ||
479 | |||
480 | /* For Primary Port 0 */ | ||
481 | card->wandev.mtu = | ||
482 | (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ? | ||
483 | min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) : | ||
484 | CHDLC_DFLT_DATA_LEN; | ||
485 | } else if(port_num == WANOPT_SEC) { | ||
486 | /* For Secondary Port 1 */ | ||
487 | card->wandev.mtu = | ||
488 | (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ? | ||
489 | min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) : | ||
490 | CHDLC_DFLT_DATA_LEN; | ||
491 | } | ||
492 | |||
493 | /* Set up the interrupt status area */ | ||
494 | /* Read the CHDLC Configuration and obtain: | ||
495 | * Ptr to shared memory infor struct | ||
496 | * Use this pointer to calculate the value of card->u.c.flags ! | ||
497 | */ | ||
498 | mb1->buffer_length = 0; | ||
499 | mb1->command = READ_CHDLC_CONFIGURATION; | ||
500 | err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT; | ||
501 | if(err != COMMAND_OK) { | ||
502 | if(card->hw.type != SDLA_S514) | ||
503 | enable_irq(card->hw.irq); | ||
504 | |||
505 | chdlc_error(card, err, mb1); | ||
506 | return -EIO; | ||
507 | } | ||
508 | |||
509 | if(card->hw.type == SDLA_S514){ | ||
510 | card->u.c.flags = (void *)(card->hw.dpmbase + | ||
511 | (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)-> | ||
512 | ptr_shared_mem_info_struct)); | ||
513 | }else{ | ||
514 | card->u.c.flags = (void *)(card->hw.dpmbase + | ||
515 | (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)-> | ||
516 | ptr_shared_mem_info_struct % SDLA_WINDOWSIZE)); | ||
517 | } | ||
518 | |||
519 | flags = card->u.c.flags; | ||
520 | |||
521 | /* This is for the ports link state */ | ||
522 | card->wandev.state = WAN_DUALPORT; | ||
523 | card->u.c.state = WAN_DISCONNECTED; | ||
524 | |||
525 | |||
526 | if (!card->wandev.piggyback){ | ||
527 | int err; | ||
528 | |||
529 | /* Perform interrupt testing */ | ||
530 | err = intr_test(card); | ||
531 | |||
532 | if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { | ||
533 | printk(KERN_INFO "%s: Interrupt test failed (%i)\n", | ||
534 | card->devname, Intr_test_counter); | ||
535 | printk(KERN_INFO "%s: Please choose another interrupt\n", | ||
536 | card->devname); | ||
537 | return -EIO; | ||
538 | } | ||
539 | |||
540 | printk(KERN_INFO "%s: Interrupt test passed (%i)\n", | ||
541 | card->devname, Intr_test_counter); | ||
542 | card->configured = 1; | ||
543 | } | ||
544 | |||
545 | if ((card->tty_opt=conf->tty) == WANOPT_YES){ | ||
546 | int err; | ||
547 | card->tty_minor = conf->tty_minor; | ||
548 | |||
549 | /* On ASYNC connections internal clocking | ||
550 | * is mandatory */ | ||
551 | if ((card->u.c.async_mode = conf->tty_mode)){ | ||
552 | card->wandev.clocking = 1; | ||
553 | } | ||
554 | err=wanpipe_tty_init(card); | ||
555 | if (err){ | ||
556 | return err; | ||
557 | } | ||
558 | }else{ | ||
559 | |||
560 | |||
561 | if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){ | ||
562 | printk (KERN_INFO "%s: " | ||
563 | "Failed to set interrupt triggers!\n", | ||
564 | card->devname); | ||
565 | return -EIO; | ||
566 | } | ||
567 | |||
568 | /* Mask the Timer interrupt */ | ||
569 | flags->interrupt_info_struct.interrupt_permission &= | ||
570 | ~APP_INT_ON_TIMER; | ||
571 | } | ||
572 | |||
573 | /* If we are using CHDLC in backup mode, this flag will | ||
574 | * indicate not to look for IP addresses in config_chdlc()*/ | ||
575 | card->u.c.backup = conf->backup; | ||
576 | |||
577 | printk(KERN_INFO "\n"); | ||
578 | |||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | /******* WAN Device Driver Entry Points *************************************/ | ||
583 | |||
584 | /*============================================================================ | ||
585 | * Update device status & statistics | ||
586 | * This procedure is called when updating the PROC file system and returns | ||
587 | * various communications statistics. These statistics are accumulated from 3 | ||
588 | * different locations: | ||
589 | * 1) The 'if_stats' recorded for the device. | ||
590 | * 2) Communication error statistics on the adapter. | ||
591 | * 3) CHDLC operational statistics on the adapter. | ||
592 | * The board level statistics are read during a timer interrupt. Note that we | ||
593 | * read the error and operational statistics during consecitive timer ticks so | ||
594 | * as to minimize the time that we are inside the interrupt handler. | ||
595 | * | ||
596 | */ | ||
597 | static int update(struct wan_device* wandev) | ||
598 | { | ||
599 | sdla_t* card = wandev->private; | ||
600 | struct net_device* dev; | ||
601 | volatile chdlc_private_area_t* chdlc_priv_area; | ||
602 | SHARED_MEMORY_INFO_STRUCT *flags; | ||
603 | unsigned long timeout; | ||
604 | |||
605 | /* sanity checks */ | ||
606 | if((wandev == NULL) || (wandev->private == NULL)) | ||
607 | return -EFAULT; | ||
608 | |||
609 | if(wandev->state == WAN_UNCONFIGURED) | ||
610 | return -ENODEV; | ||
611 | |||
612 | /* more sanity checks */ | ||
613 | if(!card->u.c.flags) | ||
614 | return -ENODEV; | ||
615 | |||
616 | if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) | ||
617 | return -EAGAIN; | ||
618 | |||
619 | if((dev=card->wandev.dev) == NULL) | ||
620 | return -ENODEV; | ||
621 | |||
622 | if((chdlc_priv_area=dev->priv) == NULL) | ||
623 | return -ENODEV; | ||
624 | |||
625 | flags = card->u.c.flags; | ||
626 | if(chdlc_priv_area->update_comms_stats){ | ||
627 | return -EAGAIN; | ||
628 | } | ||
629 | |||
630 | /* we will need 2 timer interrupts to complete the */ | ||
631 | /* reading of the statistics */ | ||
632 | chdlc_priv_area->update_comms_stats = 2; | ||
633 | flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER; | ||
634 | chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE; | ||
635 | |||
636 | /* wait a maximum of 1 second for the statistics to be updated */ | ||
637 | timeout = jiffies; | ||
638 | for(;;) { | ||
639 | if(chdlc_priv_area->update_comms_stats == 0) | ||
640 | break; | ||
641 | if ((jiffies - timeout) > (1 * HZ)){ | ||
642 | chdlc_priv_area->update_comms_stats = 0; | ||
643 | chdlc_priv_area->timer_int_enabled &= | ||
644 | ~TMR_INT_ENABLED_UPDATE; | ||
645 | return -EAGAIN; | ||
646 | } | ||
647 | } | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | |||
652 | |||
653 | /*============================================================================ | ||
654 | * Create new logical channel. | ||
655 | * This routine is called by the router when ROUTER_IFNEW IOCTL is being | ||
656 | * handled. | ||
657 | * o parse media- and hardware-specific configuration | ||
658 | * o make sure that a new channel can be created | ||
659 | * o allocate resources, if necessary | ||
660 | * o prepare network device structure for registaration. | ||
661 | * | ||
662 | * Return: 0 o.k. | ||
663 | * < 0 failure (channel will not be created) | ||
664 | */ | ||
665 | static int new_if(struct wan_device* wandev, struct net_device* dev, | ||
666 | wanif_conf_t* conf) | ||
667 | { | ||
668 | sdla_t* card = wandev->private; | ||
669 | chdlc_private_area_t* chdlc_priv_area; | ||
670 | |||
671 | |||
672 | printk(KERN_INFO "%s: Configuring Interface: %s\n", | ||
673 | card->devname, conf->name); | ||
674 | |||
675 | if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) { | ||
676 | printk(KERN_INFO "%s: Invalid interface name!\n", | ||
677 | card->devname); | ||
678 | return -EINVAL; | ||
679 | } | ||
680 | |||
681 | /* allocate and initialize private data */ | ||
682 | chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL); | ||
683 | |||
684 | if(chdlc_priv_area == NULL) | ||
685 | return -ENOMEM; | ||
686 | |||
687 | memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t)); | ||
688 | |||
689 | chdlc_priv_area->card = card; | ||
690 | chdlc_priv_area->common.sk = NULL; | ||
691 | chdlc_priv_area->common.func = NULL; | ||
692 | |||
693 | /* initialize data */ | ||
694 | strcpy(card->u.c.if_name, conf->name); | ||
695 | |||
696 | if(card->wandev.new_if_cnt > 0) { | ||
697 | kfree(chdlc_priv_area); | ||
698 | return -EEXIST; | ||
699 | } | ||
700 | |||
701 | card->wandev.new_if_cnt++; | ||
702 | |||
703 | chdlc_priv_area->TracingEnabled = 0; | ||
704 | chdlc_priv_area->route_status = NO_ROUTE; | ||
705 | chdlc_priv_area->route_removed = 0; | ||
706 | |||
707 | card->u.c.async_mode = conf->async_mode; | ||
708 | |||
709 | /* setup for asynchronous mode */ | ||
710 | if(conf->async_mode) { | ||
711 | printk(KERN_INFO "%s: Configuring for asynchronous mode\n", | ||
712 | wandev->name); | ||
713 | |||
714 | if(card->u.c.comm_port == WANOPT_PRI) { | ||
715 | printk(KERN_INFO | ||
716 | "%s:Asynchronous mode on secondary port only\n", | ||
717 | wandev->name); | ||
718 | kfree(chdlc_priv_area); | ||
719 | return -EINVAL; | ||
720 | } | ||
721 | |||
722 | if(strcmp(conf->usedby, "WANPIPE") == 0) { | ||
723 | printk(KERN_INFO | ||
724 | "%s: Running in WANIPE Async Mode\n", wandev->name); | ||
725 | card->u.c.usedby = WANPIPE; | ||
726 | }else{ | ||
727 | card->u.c.usedby = API; | ||
728 | } | ||
729 | |||
730 | if(!card->wandev.clocking) { | ||
731 | printk(KERN_INFO | ||
732 | "%s: Asynch. clocking must be 'Internal'\n", | ||
733 | wandev->name); | ||
734 | kfree(chdlc_priv_area); | ||
735 | return -EINVAL; | ||
736 | } | ||
737 | |||
738 | if((card->wandev.bps < MIN_ASY_BAUD_RATE) || | ||
739 | (card->wandev.bps > MAX_ASY_BAUD_RATE)) { | ||
740 | printk(KERN_INFO "%s: Selected baud rate is invalid.\n", | ||
741 | wandev->name); | ||
742 | printk(KERN_INFO "Must be between %u and %u bps.\n", | ||
743 | MIN_ASY_BAUD_RATE, MAX_ASY_BAUD_RATE); | ||
744 | kfree(chdlc_priv_area); | ||
745 | return -EINVAL; | ||
746 | } | ||
747 | |||
748 | card->u.c.api_options = 0; | ||
749 | if (conf->asy_data_trans == WANOPT_YES) { | ||
750 | card->u.c.api_options |= ASY_RX_DATA_TRANSPARENT; | ||
751 | } | ||
752 | |||
753 | card->u.c.protocol_options = 0; | ||
754 | if (conf->rts_hs_for_receive == WANOPT_YES) { | ||
755 | card->u.c.protocol_options |= ASY_RTS_HS_FOR_RX; | ||
756 | } | ||
757 | if (conf->xon_xoff_hs_for_receive == WANOPT_YES) { | ||
758 | card->u.c.protocol_options |= ASY_XON_XOFF_HS_FOR_RX; | ||
759 | } | ||
760 | if (conf->xon_xoff_hs_for_transmit == WANOPT_YES) { | ||
761 | card->u.c.protocol_options |= ASY_XON_XOFF_HS_FOR_TX; | ||
762 | } | ||
763 | if (conf->dcd_hs_for_transmit == WANOPT_YES) { | ||
764 | card->u.c.protocol_options |= ASY_DCD_HS_FOR_TX; | ||
765 | } | ||
766 | if (conf->cts_hs_for_transmit == WANOPT_YES) { | ||
767 | card->u.c.protocol_options |= ASY_CTS_HS_FOR_TX; | ||
768 | } | ||
769 | |||
770 | card->u.c.tx_bits_per_char = conf->tx_bits_per_char; | ||
771 | card->u.c.rx_bits_per_char = conf->rx_bits_per_char; | ||
772 | card->u.c.stop_bits = conf->stop_bits; | ||
773 | card->u.c.parity = conf->parity; | ||
774 | card->u.c.break_timer = conf->break_timer; | ||
775 | card->u.c.inter_char_timer = conf->inter_char_timer; | ||
776 | card->u.c.rx_complete_length = conf->rx_complete_length; | ||
777 | card->u.c.xon_char = conf->xon_char; | ||
778 | |||
779 | } else { /* setup for synchronous mode */ | ||
780 | |||
781 | card->u.c.protocol_options = 0; | ||
782 | if (conf->ignore_dcd == WANOPT_YES){ | ||
783 | card->u.c.protocol_options |= IGNORE_DCD_FOR_LINK_STAT; | ||
784 | } | ||
785 | if (conf->ignore_cts == WANOPT_YES){ | ||
786 | card->u.c.protocol_options |= IGNORE_CTS_FOR_LINK_STAT; | ||
787 | } | ||
788 | |||
789 | if (conf->ignore_keepalive == WANOPT_YES) { | ||
790 | card->u.c.protocol_options |= | ||
791 | IGNORE_KPALV_FOR_LINK_STAT; | ||
792 | card->u.c.kpalv_tx = MIN_Tx_KPALV_TIMER; | ||
793 | card->u.c.kpalv_rx = MIN_Rx_KPALV_TIMER; | ||
794 | card->u.c.kpalv_err = MIN_KPALV_ERR_TOL; | ||
795 | |||
796 | } else { /* Do not ignore keepalives */ | ||
797 | card->u.c.kpalv_tx = | ||
798 | ((conf->keepalive_tx_tmr - MIN_Tx_KPALV_TIMER) | ||
799 | >= 0) ? | ||
800 | min_t(unsigned int, conf->keepalive_tx_tmr,MAX_Tx_KPALV_TIMER) : | ||
801 | DEFAULT_Tx_KPALV_TIMER; | ||
802 | |||
803 | card->u.c.kpalv_rx = | ||
804 | ((conf->keepalive_rx_tmr - MIN_Rx_KPALV_TIMER) | ||
805 | >= 0) ? | ||
806 | min_t(unsigned int, conf->keepalive_rx_tmr,MAX_Rx_KPALV_TIMER) : | ||
807 | DEFAULT_Rx_KPALV_TIMER; | ||
808 | |||
809 | card->u.c.kpalv_err = | ||
810 | ((conf->keepalive_err_margin-MIN_KPALV_ERR_TOL) | ||
811 | >= 0) ? | ||
812 | min_t(unsigned int, conf->keepalive_err_margin, | ||
813 | MAX_KPALV_ERR_TOL) : | ||
814 | DEFAULT_KPALV_ERR_TOL; | ||
815 | } | ||
816 | |||
817 | /* Setup slarp timer to control delay between slarps */ | ||
818 | card->u.c.slarp_timer = | ||
819 | ((conf->slarp_timer - MIN_SLARP_REQ_TIMER) >= 0) ? | ||
820 | min_t(unsigned int, conf->slarp_timer, MAX_SLARP_REQ_TIMER) : | ||
821 | DEFAULT_SLARP_REQ_TIMER; | ||
822 | |||
823 | if (conf->hdlc_streaming == WANOPT_YES) { | ||
824 | printk(KERN_INFO "%s: Enabling HDLC STREAMING Mode\n", | ||
825 | wandev->name); | ||
826 | card->u.c.protocol_options = HDLC_STREAMING_MODE; | ||
827 | } | ||
828 | |||
829 | if ((chdlc_priv_area->true_if_encoding = conf->true_if_encoding) == WANOPT_YES){ | ||
830 | printk(KERN_INFO | ||
831 | "%s: Enabling, true interface type encoding.\n", | ||
832 | card->devname); | ||
833 | } | ||
834 | |||
835 | /* Setup wanpipe as a router (WANPIPE) or as an API */ | ||
836 | if( strcmp(conf->usedby, "WANPIPE") == 0) { | ||
837 | |||
838 | printk(KERN_INFO "%s: Running in WANPIPE mode!\n", | ||
839 | wandev->name); | ||
840 | card->u.c.usedby = WANPIPE; | ||
841 | |||
842 | /* Option to bring down the interface when | ||
843 | * the link goes down */ | ||
844 | if (conf->if_down){ | ||
845 | set_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down); | ||
846 | printk(KERN_INFO | ||
847 | "%s: Dynamic interface configuration enabled\n", | ||
848 | card->devname); | ||
849 | } | ||
850 | |||
851 | } else if( strcmp(conf->usedby, "API") == 0) { | ||
852 | card->u.c.usedby = API; | ||
853 | printk(KERN_INFO "%s: Running in API mode !\n", | ||
854 | wandev->name); | ||
855 | } | ||
856 | } | ||
857 | |||
858 | /* Tells us that if this interface is a | ||
859 | * gateway or not */ | ||
860 | if ((chdlc_priv_area->gateway = conf->gateway) == WANOPT_YES){ | ||
861 | printk(KERN_INFO "%s: Interface %s is set as a gateway.\n", | ||
862 | card->devname,card->u.c.if_name); | ||
863 | } | ||
864 | |||
865 | /* Get Multicast Information */ | ||
866 | chdlc_priv_area->mc = conf->mc; | ||
867 | |||
868 | /* prepare network device data space for registration */ | ||
869 | strcpy(dev->name,card->u.c.if_name); | ||
870 | |||
871 | dev->init = &if_init; | ||
872 | dev->priv = chdlc_priv_area; | ||
873 | |||
874 | /* Initialize the polling work routine */ | ||
875 | INIT_WORK(&chdlc_priv_area->poll_work, (void*)(void*)chdlc_poll, dev); | ||
876 | |||
877 | /* Initialize the polling delay timer */ | ||
878 | init_timer(&chdlc_priv_area->poll_delay_timer); | ||
879 | chdlc_priv_area->poll_delay_timer.data = (unsigned long)dev; | ||
880 | chdlc_priv_area->poll_delay_timer.function = chdlc_poll_delay; | ||
881 | |||
882 | printk(KERN_INFO "\n"); | ||
883 | |||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | |||
888 | /****** Network Device Interface ********************************************/ | ||
889 | |||
890 | /*============================================================================ | ||
891 | * Initialize Linux network interface. | ||
892 | * | ||
893 | * This routine is called only once for each interface, during Linux network | ||
894 | * interface registration. Returning anything but zero will fail interface | ||
895 | * registration. | ||
896 | */ | ||
897 | static int if_init(struct net_device* dev) | ||
898 | { | ||
899 | chdlc_private_area_t* chdlc_priv_area = dev->priv; | ||
900 | sdla_t* card = chdlc_priv_area->card; | ||
901 | struct wan_device* wandev = &card->wandev; | ||
902 | |||
903 | /* Initialize device driver entry points */ | ||
904 | dev->open = &if_open; | ||
905 | dev->stop = &if_close; | ||
906 | dev->hard_header = &if_header; | ||
907 | dev->rebuild_header = &if_rebuild_hdr; | ||
908 | dev->hard_start_xmit = &if_send; | ||
909 | dev->get_stats = &if_stats; | ||
910 | dev->tx_timeout = &if_tx_timeout; | ||
911 | dev->watchdog_timeo = TX_TIMEOUT; | ||
912 | |||
913 | /* Initialize media-specific parameters */ | ||
914 | dev->flags |= IFF_POINTOPOINT; | ||
915 | dev->flags |= IFF_NOARP; | ||
916 | |||
917 | /* Enable Mulitcasting if user selected */ | ||
918 | if (chdlc_priv_area->mc == WANOPT_YES){ | ||
919 | dev->flags |= IFF_MULTICAST; | ||
920 | } | ||
921 | |||
922 | if (chdlc_priv_area->true_if_encoding){ | ||
923 | dev->type = ARPHRD_HDLC; /* This breaks the tcpdump */ | ||
924 | }else{ | ||
925 | dev->type = ARPHRD_PPP; | ||
926 | } | ||
927 | |||
928 | dev->mtu = card->wandev.mtu; | ||
929 | /* for API usage, add the API header size to the requested MTU size */ | ||
930 | if(card->u.c.usedby == API) { | ||
931 | dev->mtu += sizeof(api_tx_hdr_t); | ||
932 | } | ||
933 | |||
934 | dev->hard_header_len = CHDLC_HDR_LEN; | ||
935 | |||
936 | /* Initialize hardware parameters */ | ||
937 | dev->irq = wandev->irq; | ||
938 | dev->dma = wandev->dma; | ||
939 | dev->base_addr = wandev->ioport; | ||
940 | dev->mem_start = wandev->maddr; | ||
941 | dev->mem_end = wandev->maddr + wandev->msize - 1; | ||
942 | |||
943 | /* Set transmit buffer queue length | ||
944 | * If too low packets will not be retransmitted | ||
945 | * by stack. | ||
946 | */ | ||
947 | dev->tx_queue_len = 100; | ||
948 | SET_MODULE_OWNER(dev); | ||
949 | |||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | /*============================================================================ | ||
954 | * Open network interface. | ||
955 | * o enable communications and interrupts. | ||
956 | * o prevent module from unloading by incrementing use count | ||
957 | * | ||
958 | * Return 0 if O.k. or errno. | ||
959 | */ | ||
960 | static int if_open(struct net_device* dev) | ||
961 | { | ||
962 | chdlc_private_area_t* chdlc_priv_area = dev->priv; | ||
963 | sdla_t* card = chdlc_priv_area->card; | ||
964 | struct timeval tv; | ||
965 | int err = 0; | ||
966 | |||
967 | /* Only one open per interface is allowed */ | ||
968 | |||
969 | if (netif_running(dev)) | ||
970 | return -EBUSY; | ||
971 | |||
972 | /* Initialize the work queue entry */ | ||
973 | chdlc_priv_area->tq_working=0; | ||
974 | |||
975 | INIT_WORK(&chdlc_priv_area->common.wanpipe_work, | ||
976 | (void *)(void *)chdlc_work, dev); | ||
977 | |||
978 | /* Allocate and initialize BH circular buffer */ | ||
979 | /* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */ | ||
980 | chdlc_priv_area->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC); | ||
981 | memset(chdlc_priv_area->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1))); | ||
982 | atomic_set(&chdlc_priv_area->bh_buff_used, 0); | ||
983 | |||
984 | do_gettimeofday(&tv); | ||
985 | chdlc_priv_area->router_start_time = tv.tv_sec; | ||
986 | |||
987 | netif_start_queue(dev); | ||
988 | |||
989 | wanpipe_open(card); | ||
990 | |||
991 | /* TTY is configured during wanpipe_set_termios | ||
992 | * call, not here */ | ||
993 | if (card->tty_opt) | ||
994 | return err; | ||
995 | |||
996 | set_bit(0,&chdlc_priv_area->config_chdlc); | ||
997 | chdlc_priv_area->config_chdlc_timeout=jiffies; | ||
998 | |||
999 | /* Start the CHDLC configuration after 1sec delay. | ||
1000 | * This will give the interface initilization time | ||
1001 | * to finish its configuration */ | ||
1002 | mod_timer(&chdlc_priv_area->poll_delay_timer, jiffies + HZ); | ||
1003 | return err; | ||
1004 | } | ||
1005 | |||
1006 | /*============================================================================ | ||
1007 | * Close network interface. | ||
1008 | * o if this is the last close, then disable communications and interrupts. | ||
1009 | * o reset flags. | ||
1010 | */ | ||
1011 | static int if_close(struct net_device* dev) | ||
1012 | { | ||
1013 | chdlc_private_area_t* chdlc_priv_area = dev->priv; | ||
1014 | sdla_t* card = chdlc_priv_area->card; | ||
1015 | |||
1016 | if (chdlc_priv_area->bh_head){ | ||
1017 | int i; | ||
1018 | struct sk_buff *skb; | ||
1019 | |||
1020 | for (i=0; i<(MAX_BH_BUFF+1); i++){ | ||
1021 | skb = ((bh_data_t *)&chdlc_priv_area->bh_head[i])->skb; | ||
1022 | if (skb != NULL){ | ||
1023 | dev_kfree_skb_any(skb); | ||
1024 | } | ||
1025 | } | ||
1026 | kfree(chdlc_priv_area->bh_head); | ||
1027 | chdlc_priv_area->bh_head=NULL; | ||
1028 | } | ||
1029 | |||
1030 | netif_stop_queue(dev); | ||
1031 | wanpipe_close(card); | ||
1032 | del_timer(&chdlc_priv_area->poll_delay_timer); | ||
1033 | return 0; | ||
1034 | } | ||
1035 | |||
1036 | static void disable_comm (sdla_t *card) | ||
1037 | { | ||
1038 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
1039 | |||
1040 | if (card->u.c.comm_enabled){ | ||
1041 | chdlc_disable_comm_shutdown (card); | ||
1042 | }else{ | ||
1043 | flags->interrupt_info_struct.interrupt_permission = 0; | ||
1044 | } | ||
1045 | |||
1046 | if (!tty_init_cnt) | ||
1047 | return; | ||
1048 | |||
1049 | if (card->tty_opt){ | ||
1050 | struct serial_state * state; | ||
1051 | if (!(--tty_init_cnt)){ | ||
1052 | int e1; | ||
1053 | serial_driver.refcount=0; | ||
1054 | |||
1055 | if ((e1 = tty_unregister_driver(&serial_driver))) | ||
1056 | printk("SERIAL: failed to unregister serial driver (%d)\n", | ||
1057 | e1); | ||
1058 | printk(KERN_INFO "%s: Unregistering TTY Driver, Major %i\n", | ||
1059 | card->devname,WAN_TTY_MAJOR); | ||
1060 | } | ||
1061 | card->tty=NULL; | ||
1062 | tty_card_map[card->tty_minor]=NULL; | ||
1063 | state = &rs_table[card->tty_minor]; | ||
1064 | memset(state, 0, sizeof(*state)); | ||
1065 | } | ||
1066 | return; | ||
1067 | } | ||
1068 | |||
1069 | |||
1070 | /*============================================================================ | ||
1071 | * Build media header. | ||
1072 | * | ||
1073 | * The trick here is to put packet type (Ethertype) into 'protocol' field of | ||
1074 | * the socket buffer, so that we don't forget it. If packet type is not | ||
1075 | * supported, set skb->protocol to 0 and discard packet later. | ||
1076 | * | ||
1077 | * Return: media header length. | ||
1078 | */ | ||
1079 | static int if_header(struct sk_buff* skb, struct net_device* dev, | ||
1080 | unsigned short type, void* daddr, void* saddr, | ||
1081 | unsigned len) | ||
1082 | { | ||
1083 | skb->protocol = htons(type); | ||
1084 | |||
1085 | return CHDLC_HDR_LEN; | ||
1086 | } | ||
1087 | |||
1088 | |||
1089 | /*============================================================================ | ||
1090 | * Handle transmit timeout event from netif watchdog | ||
1091 | */ | ||
1092 | static void if_tx_timeout(struct net_device *dev) | ||
1093 | { | ||
1094 | chdlc_private_area_t* chan = dev->priv; | ||
1095 | sdla_t *card = chan->card; | ||
1096 | |||
1097 | /* If our device stays busy for at least 5 seconds then we will | ||
1098 | * kick start the device by making dev->tbusy = 0. We expect | ||
1099 | * that our device never stays busy more than 5 seconds. So this | ||
1100 | * is only used as a last resort. | ||
1101 | */ | ||
1102 | |||
1103 | ++card->wandev.stats.collisions; | ||
1104 | |||
1105 | printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); | ||
1106 | netif_wake_queue (dev); | ||
1107 | } | ||
1108 | |||
1109 | |||
1110 | |||
1111 | /*============================================================================ | ||
1112 | * Re-build media header. | ||
1113 | * | ||
1114 | * Return: 1 physical address resolved. | ||
1115 | * 0 physical address not resolved | ||
1116 | */ | ||
1117 | static int if_rebuild_hdr (struct sk_buff *skb) | ||
1118 | { | ||
1119 | return 1; | ||
1120 | } | ||
1121 | |||
1122 | |||
1123 | /*============================================================================ | ||
1124 | * Send a packet on a network interface. | ||
1125 | * o set tbusy flag (marks start of the transmission) to block a timer-based | ||
1126 | * transmit from overlapping. | ||
1127 | * o check link state. If link is not up, then drop the packet. | ||
1128 | * o execute adapter send command. | ||
1129 | * o free socket buffer | ||
1130 | * | ||
1131 | * Return: 0 complete (socket buffer must be freed) | ||
1132 | * non-0 packet may be re-transmitted (tbusy must be set) | ||
1133 | * | ||
1134 | * Notes: | ||
1135 | * 1. This routine is called either by the protocol stack or by the "net | ||
1136 | * bottom half" (with interrupts enabled). | ||
1137 | * 2. Setting tbusy flag will inhibit further transmit requests from the | ||
1138 | * protocol stack and can be used for flow control with protocol layer. | ||
1139 | */ | ||
1140 | static int if_send(struct sk_buff* skb, struct net_device* dev) | ||
1141 | { | ||
1142 | chdlc_private_area_t *chdlc_priv_area = dev->priv; | ||
1143 | sdla_t *card = chdlc_priv_area->card; | ||
1144 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
1145 | INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct; | ||
1146 | int udp_type = 0; | ||
1147 | unsigned long smp_flags; | ||
1148 | int err=0; | ||
1149 | |||
1150 | netif_stop_queue(dev); | ||
1151 | |||
1152 | if (skb == NULL){ | ||
1153 | /* If we get here, some higher layer thinks we've missed an | ||
1154 | * tx-done interrupt. | ||
1155 | */ | ||
1156 | printk(KERN_INFO "%s: interface %s got kicked!\n", | ||
1157 | card->devname, dev->name); | ||
1158 | |||
1159 | netif_wake_queue(dev); | ||
1160 | return 0; | ||
1161 | } | ||
1162 | |||
1163 | if (ntohs(skb->protocol) != htons(PVC_PROT)){ | ||
1164 | |||
1165 | /* check the udp packet type */ | ||
1166 | |||
1167 | udp_type = udp_pkt_type(skb, card); | ||
1168 | |||
1169 | if (udp_type == UDP_CPIPE_TYPE){ | ||
1170 | if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev, | ||
1171 | chdlc_priv_area)){ | ||
1172 | chdlc_int->interrupt_permission |= | ||
1173 | APP_INT_ON_TIMER; | ||
1174 | } | ||
1175 | netif_start_queue(dev); | ||
1176 | return 0; | ||
1177 | } | ||
1178 | |||
1179 | /* check to see if the source IP address is a broadcast or */ | ||
1180 | /* multicast IP address */ | ||
1181 | if(chk_bcast_mcast_addr(card, dev, skb)){ | ||
1182 | ++card->wandev.stats.tx_dropped; | ||
1183 | dev_kfree_skb_any(skb); | ||
1184 | netif_start_queue(dev); | ||
1185 | return 0; | ||
1186 | } | ||
1187 | } | ||
1188 | |||
1189 | /* Lock the 508 Card: SMP is supported */ | ||
1190 | if(card->hw.type != SDLA_S514){ | ||
1191 | s508_lock(card,&smp_flags); | ||
1192 | } | ||
1193 | |||
1194 | if(test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) { | ||
1195 | |||
1196 | printk(KERN_INFO "%s: Critical in if_send: %lx\n", | ||
1197 | card->wandev.name,card->wandev.critical); | ||
1198 | ++card->wandev.stats.tx_dropped; | ||
1199 | netif_start_queue(dev); | ||
1200 | goto if_send_exit_crit; | ||
1201 | } | ||
1202 | |||
1203 | if(card->u.c.state != WAN_CONNECTED){ | ||
1204 | ++card->wandev.stats.tx_dropped; | ||
1205 | netif_start_queue(dev); | ||
1206 | |||
1207 | }else if(!skb->protocol){ | ||
1208 | ++card->wandev.stats.tx_errors; | ||
1209 | netif_start_queue(dev); | ||
1210 | |||
1211 | }else { | ||
1212 | void* data = skb->data; | ||
1213 | unsigned len = skb->len; | ||
1214 | unsigned char attr; | ||
1215 | |||
1216 | /* If it's an API packet pull off the API | ||
1217 | * header. Also check that the packet size | ||
1218 | * is larger than the API header | ||
1219 | */ | ||
1220 | if (card->u.c.usedby == API){ | ||
1221 | api_tx_hdr_t* api_tx_hdr; | ||
1222 | |||
1223 | /* discard the frame if we are configured for */ | ||
1224 | /* 'receive only' mode or if there is no data */ | ||
1225 | if (card->u.c.receive_only || | ||
1226 | (len <= sizeof(api_tx_hdr_t))) { | ||
1227 | |||
1228 | ++card->wandev.stats.tx_dropped; | ||
1229 | netif_start_queue(dev); | ||
1230 | goto if_send_exit_crit; | ||
1231 | } | ||
1232 | |||
1233 | api_tx_hdr = (api_tx_hdr_t *)data; | ||
1234 | attr = api_tx_hdr->attr; | ||
1235 | data += sizeof(api_tx_hdr_t); | ||
1236 | len -= sizeof(api_tx_hdr_t); | ||
1237 | } | ||
1238 | |||
1239 | if(chdlc_send(card, data, len)) { | ||
1240 | netif_stop_queue(dev); | ||
1241 | }else{ | ||
1242 | ++card->wandev.stats.tx_packets; | ||
1243 | card->wandev.stats.tx_bytes += len; | ||
1244 | |||
1245 | netif_start_queue(dev); | ||
1246 | |||
1247 | dev->trans_start = jiffies; | ||
1248 | } | ||
1249 | } | ||
1250 | |||
1251 | if_send_exit_crit: | ||
1252 | |||
1253 | if (!(err=netif_queue_stopped(dev))) { | ||
1254 | dev_kfree_skb_any(skb); | ||
1255 | }else{ | ||
1256 | chdlc_priv_area->tick_counter = jiffies; | ||
1257 | chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME; | ||
1258 | } | ||
1259 | |||
1260 | clear_bit(SEND_CRIT, (void*)&card->wandev.critical); | ||
1261 | if(card->hw.type != SDLA_S514){ | ||
1262 | s508_unlock(card,&smp_flags); | ||
1263 | } | ||
1264 | |||
1265 | return err; | ||
1266 | } | ||
1267 | |||
1268 | |||
1269 | /*============================================================================ | ||
1270 | * Check to see if the packet to be transmitted contains a broadcast or | ||
1271 | * multicast source IP address. | ||
1272 | */ | ||
1273 | |||
1274 | static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev, | ||
1275 | struct sk_buff *skb) | ||
1276 | { | ||
1277 | u32 src_ip_addr; | ||
1278 | u32 broadcast_ip_addr = 0; | ||
1279 | struct in_device *in_dev; | ||
1280 | |||
1281 | /* read the IP source address from the outgoing packet */ | ||
1282 | src_ip_addr = *(u32 *)(skb->data + 12); | ||
1283 | |||
1284 | /* read the IP broadcast address for the device */ | ||
1285 | in_dev = dev->ip_ptr; | ||
1286 | if(in_dev != NULL) { | ||
1287 | struct in_ifaddr *ifa= in_dev->ifa_list; | ||
1288 | if(ifa != NULL) | ||
1289 | broadcast_ip_addr = ifa->ifa_broadcast; | ||
1290 | else | ||
1291 | return 0; | ||
1292 | } | ||
1293 | |||
1294 | /* check if the IP Source Address is a Broadcast address */ | ||
1295 | if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { | ||
1296 | printk(KERN_INFO "%s: Broadcast Source Address silently discarded\n", | ||
1297 | card->devname); | ||
1298 | return 1; | ||
1299 | } | ||
1300 | |||
1301 | /* check if the IP Source Address is a Multicast address */ | ||
1302 | if((ntohl(src_ip_addr) >= 0xE0000001) && | ||
1303 | (ntohl(src_ip_addr) <= 0xFFFFFFFE)) { | ||
1304 | printk(KERN_INFO "%s: Multicast Source Address silently discarded\n", | ||
1305 | card->devname); | ||
1306 | return 1; | ||
1307 | } | ||
1308 | |||
1309 | return 0; | ||
1310 | } | ||
1311 | |||
1312 | |||
1313 | /*============================================================================ | ||
1314 | * Reply to UDP Management system. | ||
1315 | * Return length of reply. | ||
1316 | */ | ||
1317 | static int reply_udp( unsigned char *data, unsigned int mbox_len ) | ||
1318 | { | ||
1319 | |||
1320 | unsigned short len, udp_length, temp, ip_length; | ||
1321 | unsigned long ip_temp; | ||
1322 | int even_bound = 0; | ||
1323 | chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data; | ||
1324 | |||
1325 | /* Set length of packet */ | ||
1326 | len = sizeof(ip_pkt_t)+ | ||
1327 | sizeof(udp_pkt_t)+ | ||
1328 | sizeof(wp_mgmt_t)+ | ||
1329 | sizeof(cblock_t)+ | ||
1330 | sizeof(trace_info_t)+ | ||
1331 | mbox_len; | ||
1332 | |||
1333 | /* fill in UDP reply */ | ||
1334 | c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; | ||
1335 | |||
1336 | /* fill in UDP length */ | ||
1337 | udp_length = sizeof(udp_pkt_t)+ | ||
1338 | sizeof(wp_mgmt_t)+ | ||
1339 | sizeof(cblock_t)+ | ||
1340 | sizeof(trace_info_t)+ | ||
1341 | mbox_len; | ||
1342 | |||
1343 | /* put it on an even boundary */ | ||
1344 | if ( udp_length & 0x0001 ) { | ||
1345 | udp_length += 1; | ||
1346 | len += 1; | ||
1347 | even_bound = 1; | ||
1348 | } | ||
1349 | |||
1350 | temp = (udp_length<<8)|(udp_length>>8); | ||
1351 | c_udp_pkt->udp_pkt.udp_length = temp; | ||
1352 | |||
1353 | /* swap UDP ports */ | ||
1354 | temp = c_udp_pkt->udp_pkt.udp_src_port; | ||
1355 | c_udp_pkt->udp_pkt.udp_src_port = | ||
1356 | c_udp_pkt->udp_pkt.udp_dst_port; | ||
1357 | c_udp_pkt->udp_pkt.udp_dst_port = temp; | ||
1358 | |||
1359 | /* add UDP pseudo header */ | ||
1360 | temp = 0x1100; | ||
1361 | *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp; | ||
1362 | temp = (udp_length<<8)|(udp_length>>8); | ||
1363 | *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp; | ||
1364 | |||
1365 | |||
1366 | /* calculate UDP checksum */ | ||
1367 | c_udp_pkt->udp_pkt.udp_checksum = 0; | ||
1368 | c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET); | ||
1369 | |||
1370 | /* fill in IP length */ | ||
1371 | ip_length = len; | ||
1372 | temp = (ip_length<<8)|(ip_length>>8); | ||
1373 | c_udp_pkt->ip_pkt.total_length = temp; | ||
1374 | |||
1375 | /* swap IP addresses */ | ||
1376 | ip_temp = c_udp_pkt->ip_pkt.ip_src_address; | ||
1377 | c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address; | ||
1378 | c_udp_pkt->ip_pkt.ip_dst_address = ip_temp; | ||
1379 | |||
1380 | /* fill in IP checksum */ | ||
1381 | c_udp_pkt->ip_pkt.hdr_checksum = 0; | ||
1382 | c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t)); | ||
1383 | |||
1384 | return len; | ||
1385 | |||
1386 | } /* reply_udp */ | ||
1387 | |||
1388 | unsigned short calc_checksum (char *data, int len) | ||
1389 | { | ||
1390 | unsigned short temp; | ||
1391 | unsigned long sum=0; | ||
1392 | int i; | ||
1393 | |||
1394 | for( i = 0; i <len; i+=2 ) { | ||
1395 | memcpy(&temp,&data[i],2); | ||
1396 | sum += (unsigned long)temp; | ||
1397 | } | ||
1398 | |||
1399 | while (sum >> 16 ) { | ||
1400 | sum = (sum & 0xffffUL) + (sum >> 16); | ||
1401 | } | ||
1402 | |||
1403 | temp = (unsigned short)sum; | ||
1404 | temp = ~temp; | ||
1405 | |||
1406 | if( temp == 0 ) | ||
1407 | temp = 0xffff; | ||
1408 | |||
1409 | return temp; | ||
1410 | } | ||
1411 | |||
1412 | |||
1413 | /*============================================================================ | ||
1414 | * Get ethernet-style interface statistics. | ||
1415 | * Return a pointer to struct enet_statistics. | ||
1416 | */ | ||
1417 | static struct net_device_stats* if_stats(struct net_device* dev) | ||
1418 | { | ||
1419 | sdla_t *my_card; | ||
1420 | chdlc_private_area_t* chdlc_priv_area; | ||
1421 | |||
1422 | if ((chdlc_priv_area=dev->priv) == NULL) | ||
1423 | return NULL; | ||
1424 | |||
1425 | my_card = chdlc_priv_area->card; | ||
1426 | return &my_card->wandev.stats; | ||
1427 | } | ||
1428 | |||
1429 | |||
1430 | /****** Cisco HDLC Firmware Interface Functions *******************************/ | ||
1431 | |||
1432 | /*============================================================================ | ||
1433 | * Read firmware code version. | ||
1434 | * Put code version as ASCII string in str. | ||
1435 | */ | ||
1436 | static int chdlc_read_version (sdla_t* card, char* str) | ||
1437 | { | ||
1438 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1439 | int len; | ||
1440 | char err; | ||
1441 | mb->buffer_length = 0; | ||
1442 | mb->command = READ_CHDLC_CODE_VERSION; | ||
1443 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1444 | |||
1445 | if(err != COMMAND_OK) { | ||
1446 | chdlc_error(card,err,mb); | ||
1447 | } | ||
1448 | else if (str) { /* is not null */ | ||
1449 | len = mb->buffer_length; | ||
1450 | memcpy(str, mb->data, len); | ||
1451 | str[len] = '\0'; | ||
1452 | } | ||
1453 | return (err); | ||
1454 | } | ||
1455 | |||
1456 | /*----------------------------------------------------------------------------- | ||
1457 | * Configure CHDLC firmware. | ||
1458 | */ | ||
1459 | static int chdlc_configure (sdla_t* card, void* data) | ||
1460 | { | ||
1461 | int err; | ||
1462 | CHDLC_MAILBOX_STRUCT *mailbox = card->mbox; | ||
1463 | int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT); | ||
1464 | |||
1465 | mailbox->buffer_length = data_length; | ||
1466 | memcpy(mailbox->data, data, data_length); | ||
1467 | mailbox->command = SET_CHDLC_CONFIGURATION; | ||
1468 | err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT; | ||
1469 | |||
1470 | if (err != COMMAND_OK) chdlc_error (card, err, mailbox); | ||
1471 | |||
1472 | return err; | ||
1473 | } | ||
1474 | |||
1475 | |||
1476 | /*============================================================================ | ||
1477 | * Set interrupt mode -- HDLC Version. | ||
1478 | */ | ||
1479 | |||
1480 | static int chdlc_set_intr_mode (sdla_t* card, unsigned mode) | ||
1481 | { | ||
1482 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1483 | CHDLC_INT_TRIGGERS_STRUCT* int_data = | ||
1484 | (CHDLC_INT_TRIGGERS_STRUCT *)mb->data; | ||
1485 | int err; | ||
1486 | |||
1487 | int_data->CHDLC_interrupt_triggers = mode; | ||
1488 | int_data->IRQ = card->hw.irq; | ||
1489 | int_data->interrupt_timer = 1; | ||
1490 | |||
1491 | mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT); | ||
1492 | mb->command = SET_CHDLC_INTERRUPT_TRIGGERS; | ||
1493 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1494 | if (err != COMMAND_OK) | ||
1495 | chdlc_error (card, err, mb); | ||
1496 | return err; | ||
1497 | } | ||
1498 | |||
1499 | |||
1500 | /*=========================================================== | ||
1501 | * chdlc_disable_comm_shutdown | ||
1502 | * | ||
1503 | * Shutdown() disables the communications. We must | ||
1504 | * have a sparate functions, because we must not | ||
1505 | * call chdlc_error() hander since the private | ||
1506 | * area has already been replaced */ | ||
1507 | |||
1508 | static int chdlc_disable_comm_shutdown (sdla_t *card) | ||
1509 | { | ||
1510 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1511 | CHDLC_INT_TRIGGERS_STRUCT* int_data = | ||
1512 | (CHDLC_INT_TRIGGERS_STRUCT *)mb->data; | ||
1513 | int err; | ||
1514 | |||
1515 | /* Disable Interrutps */ | ||
1516 | int_data->CHDLC_interrupt_triggers = 0; | ||
1517 | int_data->IRQ = card->hw.irq; | ||
1518 | int_data->interrupt_timer = 1; | ||
1519 | |||
1520 | mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT); | ||
1521 | mb->command = SET_CHDLC_INTERRUPT_TRIGGERS; | ||
1522 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1523 | |||
1524 | /* Disable Communications */ | ||
1525 | |||
1526 | if (card->u.c.async_mode) { | ||
1527 | mb->command = DISABLE_ASY_COMMUNICATIONS; | ||
1528 | }else{ | ||
1529 | mb->command = DISABLE_CHDLC_COMMUNICATIONS; | ||
1530 | } | ||
1531 | |||
1532 | mb->buffer_length = 0; | ||
1533 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1534 | |||
1535 | card->u.c.comm_enabled = 0; | ||
1536 | |||
1537 | return 0; | ||
1538 | } | ||
1539 | |||
1540 | /*============================================================================ | ||
1541 | * Enable communications. | ||
1542 | */ | ||
1543 | |||
1544 | static int chdlc_comm_enable (sdla_t* card) | ||
1545 | { | ||
1546 | int err; | ||
1547 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1548 | |||
1549 | mb->buffer_length = 0; | ||
1550 | mb->command = ENABLE_CHDLC_COMMUNICATIONS; | ||
1551 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1552 | if (err != COMMAND_OK) | ||
1553 | chdlc_error(card, err, mb); | ||
1554 | else | ||
1555 | card->u.c.comm_enabled = 1; | ||
1556 | |||
1557 | return err; | ||
1558 | } | ||
1559 | |||
1560 | /*============================================================================ | ||
1561 | * Read communication error statistics. | ||
1562 | */ | ||
1563 | static int chdlc_read_comm_err_stats (sdla_t* card) | ||
1564 | { | ||
1565 | int err; | ||
1566 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1567 | |||
1568 | mb->buffer_length = 0; | ||
1569 | mb->command = READ_COMMS_ERROR_STATS; | ||
1570 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1571 | if (err != COMMAND_OK) | ||
1572 | chdlc_error(card,err,mb); | ||
1573 | return err; | ||
1574 | } | ||
1575 | |||
1576 | |||
1577 | /*============================================================================ | ||
1578 | * Read CHDLC operational statistics. | ||
1579 | */ | ||
1580 | static int chdlc_read_op_stats (sdla_t* card) | ||
1581 | { | ||
1582 | int err; | ||
1583 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1584 | |||
1585 | mb->buffer_length = 0; | ||
1586 | mb->command = READ_CHDLC_OPERATIONAL_STATS; | ||
1587 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1588 | if (err != COMMAND_OK) | ||
1589 | chdlc_error(card,err,mb); | ||
1590 | return err; | ||
1591 | } | ||
1592 | |||
1593 | |||
1594 | /*============================================================================ | ||
1595 | * Update communications error and general packet statistics. | ||
1596 | */ | ||
1597 | static int update_comms_stats(sdla_t* card, | ||
1598 | chdlc_private_area_t* chdlc_priv_area) | ||
1599 | { | ||
1600 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1601 | COMMS_ERROR_STATS_STRUCT* err_stats; | ||
1602 | CHDLC_OPERATIONAL_STATS_STRUCT *op_stats; | ||
1603 | |||
1604 | /* on the first timer interrupt, read the comms error statistics */ | ||
1605 | if(chdlc_priv_area->update_comms_stats == 2) { | ||
1606 | if(chdlc_read_comm_err_stats(card)) | ||
1607 | return 1; | ||
1608 | err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data; | ||
1609 | card->wandev.stats.rx_over_errors = | ||
1610 | err_stats->Rx_overrun_err_count; | ||
1611 | card->wandev.stats.rx_crc_errors = | ||
1612 | err_stats->CRC_err_count; | ||
1613 | card->wandev.stats.rx_frame_errors = | ||
1614 | err_stats->Rx_abort_count; | ||
1615 | card->wandev.stats.rx_fifo_errors = | ||
1616 | err_stats->Rx_dis_pri_bfrs_full_count; | ||
1617 | card->wandev.stats.rx_missed_errors = | ||
1618 | card->wandev.stats.rx_fifo_errors; | ||
1619 | card->wandev.stats.tx_aborted_errors = | ||
1620 | err_stats->sec_Tx_abort_count; | ||
1621 | } | ||
1622 | |||
1623 | /* on the second timer interrupt, read the operational statistics */ | ||
1624 | else { | ||
1625 | if(chdlc_read_op_stats(card)) | ||
1626 | return 1; | ||
1627 | op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data; | ||
1628 | card->wandev.stats.rx_length_errors = | ||
1629 | (op_stats->Rx_Data_discard_short_count + | ||
1630 | op_stats->Rx_Data_discard_long_count); | ||
1631 | } | ||
1632 | |||
1633 | return 0; | ||
1634 | } | ||
1635 | |||
1636 | /*============================================================================ | ||
1637 | * Send packet. | ||
1638 | * Return: 0 - o.k. | ||
1639 | * 1 - no transmit buffers available | ||
1640 | */ | ||
1641 | static int chdlc_send (sdla_t* card, void* data, unsigned len) | ||
1642 | { | ||
1643 | CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf; | ||
1644 | |||
1645 | if (txbuf->opp_flag) | ||
1646 | return 1; | ||
1647 | |||
1648 | sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len); | ||
1649 | |||
1650 | txbuf->frame_length = len; | ||
1651 | txbuf->opp_flag = 1; /* start transmission */ | ||
1652 | |||
1653 | /* Update transmit buffer control fields */ | ||
1654 | card->u.c.txbuf = ++txbuf; | ||
1655 | |||
1656 | if ((void*)txbuf > card->u.c.txbuf_last) | ||
1657 | card->u.c.txbuf = card->u.c.txbuf_base; | ||
1658 | |||
1659 | return 0; | ||
1660 | } | ||
1661 | |||
1662 | /****** Firmware Error Handler **********************************************/ | ||
1663 | |||
1664 | /*============================================================================ | ||
1665 | * Firmware error handler. | ||
1666 | * This routine is called whenever firmware command returns non-zero | ||
1667 | * return code. | ||
1668 | * | ||
1669 | * Return zero if previous command has to be cancelled. | ||
1670 | */ | ||
1671 | static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb) | ||
1672 | { | ||
1673 | unsigned cmd = mb->command; | ||
1674 | |||
1675 | switch (err) { | ||
1676 | |||
1677 | case CMD_TIMEOUT: | ||
1678 | printk(KERN_INFO "%s: command 0x%02X timed out!\n", | ||
1679 | card->devname, cmd); | ||
1680 | break; | ||
1681 | |||
1682 | case S514_BOTH_PORTS_SAME_CLK_MODE: | ||
1683 | if(cmd == SET_CHDLC_CONFIGURATION) { | ||
1684 | printk(KERN_INFO | ||
1685 | "%s: Configure both ports for the same clock source\n", | ||
1686 | card->devname); | ||
1687 | break; | ||
1688 | } | ||
1689 | |||
1690 | default: | ||
1691 | printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n", | ||
1692 | card->devname, cmd, err); | ||
1693 | } | ||
1694 | |||
1695 | return 0; | ||
1696 | } | ||
1697 | |||
1698 | |||
1699 | /********** Bottom Half Handlers ********************************************/ | ||
1700 | |||
1701 | /* NOTE: There is no API, BH support for Kernels lower than 2.2.X. | ||
1702 | * DO NOT INSERT ANY CODE HERE, NOTICE THE | ||
1703 | * PREPROCESSOR STATEMENT ABOVE, UNLESS YOU KNOW WHAT YOU ARE | ||
1704 | * DOING */ | ||
1705 | |||
1706 | static void chdlc_work(struct net_device * dev) | ||
1707 | { | ||
1708 | chdlc_private_area_t* chan = dev->priv; | ||
1709 | sdla_t *card = chan->card; | ||
1710 | struct sk_buff *skb; | ||
1711 | |||
1712 | if (atomic_read(&chan->bh_buff_used) == 0){ | ||
1713 | clear_bit(0, &chan->tq_working); | ||
1714 | return; | ||
1715 | } | ||
1716 | |||
1717 | while (atomic_read(&chan->bh_buff_used)){ | ||
1718 | |||
1719 | skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb; | ||
1720 | |||
1721 | if (skb != NULL){ | ||
1722 | |||
1723 | if (chan->common.sk == NULL || chan->common.func == NULL){ | ||
1724 | ++card->wandev.stats.rx_dropped; | ||
1725 | dev_kfree_skb_any(skb); | ||
1726 | chdlc_work_cleanup(dev); | ||
1727 | continue; | ||
1728 | } | ||
1729 | |||
1730 | if (chan->common.func(skb,dev,chan->common.sk) != 0){ | ||
1731 | /* Sock full cannot send, queue us for another | ||
1732 | * try */ | ||
1733 | atomic_set(&chan->common.receive_block,1); | ||
1734 | return; | ||
1735 | }else{ | ||
1736 | chdlc_work_cleanup(dev); | ||
1737 | } | ||
1738 | }else{ | ||
1739 | chdlc_work_cleanup(dev); | ||
1740 | } | ||
1741 | } | ||
1742 | clear_bit(0, &chan->tq_working); | ||
1743 | |||
1744 | return; | ||
1745 | } | ||
1746 | |||
1747 | static int chdlc_work_cleanup(struct net_device *dev) | ||
1748 | { | ||
1749 | chdlc_private_area_t* chan = dev->priv; | ||
1750 | |||
1751 | ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL; | ||
1752 | |||
1753 | if (chan->bh_read == MAX_BH_BUFF){ | ||
1754 | chan->bh_read=0; | ||
1755 | }else{ | ||
1756 | ++chan->bh_read; | ||
1757 | } | ||
1758 | |||
1759 | atomic_dec(&chan->bh_buff_used); | ||
1760 | return 0; | ||
1761 | } | ||
1762 | |||
1763 | |||
1764 | |||
1765 | static int bh_enqueue(struct net_device *dev, struct sk_buff *skb) | ||
1766 | { | ||
1767 | /* Check for full */ | ||
1768 | chdlc_private_area_t* chan = dev->priv; | ||
1769 | sdla_t *card = chan->card; | ||
1770 | |||
1771 | if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){ | ||
1772 | ++card->wandev.stats.rx_dropped; | ||
1773 | dev_kfree_skb_any(skb); | ||
1774 | return 1; | ||
1775 | } | ||
1776 | |||
1777 | ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb; | ||
1778 | |||
1779 | if (chan->bh_write == MAX_BH_BUFF){ | ||
1780 | chan->bh_write=0; | ||
1781 | }else{ | ||
1782 | ++chan->bh_write; | ||
1783 | } | ||
1784 | |||
1785 | atomic_inc(&chan->bh_buff_used); | ||
1786 | |||
1787 | return 0; | ||
1788 | } | ||
1789 | |||
1790 | /* END OF API BH Support */ | ||
1791 | |||
1792 | |||
1793 | /****** Interrupt Handlers **************************************************/ | ||
1794 | |||
1795 | /*============================================================================ | ||
1796 | * Cisco HDLC interrupt service routine. | ||
1797 | */ | ||
1798 | static void wpc_isr (sdla_t* card) | ||
1799 | { | ||
1800 | struct net_device* dev; | ||
1801 | SHARED_MEMORY_INFO_STRUCT* flags = NULL; | ||
1802 | int i; | ||
1803 | sdla_t *my_card; | ||
1804 | |||
1805 | |||
1806 | /* Check for which port the interrupt has been generated | ||
1807 | * Since Secondary Port is piggybacking on the Primary | ||
1808 | * the check must be done here. | ||
1809 | */ | ||
1810 | |||
1811 | flags = card->u.c.flags; | ||
1812 | if (!flags->interrupt_info_struct.interrupt_type){ | ||
1813 | /* Check for a second port (piggybacking) */ | ||
1814 | if ((my_card = card->next)){ | ||
1815 | flags = my_card->u.c.flags; | ||
1816 | if (flags->interrupt_info_struct.interrupt_type){ | ||
1817 | card = my_card; | ||
1818 | card->isr(card); | ||
1819 | return; | ||
1820 | } | ||
1821 | } | ||
1822 | } | ||
1823 | |||
1824 | flags = card->u.c.flags; | ||
1825 | card->in_isr = 1; | ||
1826 | dev = card->wandev.dev; | ||
1827 | |||
1828 | /* If we get an interrupt with no network device, stop the interrupts | ||
1829 | * and issue an error */ | ||
1830 | if (!card->tty_opt && !dev && | ||
1831 | flags->interrupt_info_struct.interrupt_type != | ||
1832 | COMMAND_COMPLETE_APP_INT_PEND){ | ||
1833 | |||
1834 | goto isr_done; | ||
1835 | } | ||
1836 | |||
1837 | /* if critical due to peripheral operations | ||
1838 | * ie. update() or getstats() then reset the interrupt and | ||
1839 | * wait for the board to retrigger. | ||
1840 | */ | ||
1841 | if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { | ||
1842 | printk(KERN_INFO "ISR CRIT TO PERI\n"); | ||
1843 | goto isr_done; | ||
1844 | } | ||
1845 | |||
1846 | /* On a 508 Card, if critical due to if_send | ||
1847 | * Major Error !!! */ | ||
1848 | if(card->hw.type != SDLA_S514) { | ||
1849 | if(test_bit(SEND_CRIT, (void*)&card->wandev.critical)) { | ||
1850 | printk(KERN_INFO "%s: Critical while in ISR: %lx\n", | ||
1851 | card->devname, card->wandev.critical); | ||
1852 | card->in_isr = 0; | ||
1853 | flags->interrupt_info_struct.interrupt_type = 0; | ||
1854 | return; | ||
1855 | } | ||
1856 | } | ||
1857 | |||
1858 | switch(flags->interrupt_info_struct.interrupt_type) { | ||
1859 | |||
1860 | case RX_APP_INT_PEND: /* 0x01: receive interrupt */ | ||
1861 | rx_intr(card); | ||
1862 | break; | ||
1863 | |||
1864 | case TX_APP_INT_PEND: /* 0x02: transmit interrupt */ | ||
1865 | flags->interrupt_info_struct.interrupt_permission &= | ||
1866 | ~APP_INT_ON_TX_FRAME; | ||
1867 | |||
1868 | if (card->tty_opt){ | ||
1869 | wanpipe_tty_trigger_poll(card); | ||
1870 | break; | ||
1871 | } | ||
1872 | |||
1873 | if (dev && netif_queue_stopped(dev)){ | ||
1874 | if (card->u.c.usedby == API){ | ||
1875 | netif_start_queue(dev); | ||
1876 | wakeup_sk_bh(dev); | ||
1877 | }else{ | ||
1878 | netif_wake_queue(dev); | ||
1879 | } | ||
1880 | } | ||
1881 | break; | ||
1882 | |||
1883 | case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */ | ||
1884 | ++ Intr_test_counter; | ||
1885 | break; | ||
1886 | |||
1887 | case CHDLC_EXCEP_COND_APP_INT_PEND: /* 0x20 */ | ||
1888 | process_chdlc_exception(card); | ||
1889 | break; | ||
1890 | |||
1891 | case GLOBAL_EXCEP_COND_APP_INT_PEND: | ||
1892 | process_global_exception(card); | ||
1893 | break; | ||
1894 | |||
1895 | case TIMER_APP_INT_PEND: | ||
1896 | timer_intr(card); | ||
1897 | break; | ||
1898 | |||
1899 | default: | ||
1900 | printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", | ||
1901 | card->devname, | ||
1902 | flags->interrupt_info_struct.interrupt_type); | ||
1903 | printk(KERN_INFO "Code name: "); | ||
1904 | for(i = 0; i < 4; i ++) | ||
1905 | printk(KERN_INFO "%c", | ||
1906 | flags->global_info_struct.codename[i]); | ||
1907 | printk(KERN_INFO "\nCode version: "); | ||
1908 | for(i = 0; i < 4; i ++) | ||
1909 | printk(KERN_INFO "%c", | ||
1910 | flags->global_info_struct.codeversion[i]); | ||
1911 | printk(KERN_INFO "\n"); | ||
1912 | break; | ||
1913 | } | ||
1914 | |||
1915 | isr_done: | ||
1916 | |||
1917 | card->in_isr = 0; | ||
1918 | flags->interrupt_info_struct.interrupt_type = 0; | ||
1919 | return; | ||
1920 | } | ||
1921 | |||
1922 | /*============================================================================ | ||
1923 | * Receive interrupt handler. | ||
1924 | */ | ||
1925 | static void rx_intr (sdla_t* card) | ||
1926 | { | ||
1927 | struct net_device *dev; | ||
1928 | chdlc_private_area_t *chdlc_priv_area; | ||
1929 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
1930 | CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb; | ||
1931 | struct sk_buff *skb; | ||
1932 | unsigned len; | ||
1933 | unsigned addr = rxbuf->ptr_data_bfr; | ||
1934 | void *buf; | ||
1935 | int i,udp_type; | ||
1936 | |||
1937 | if (rxbuf->opp_flag != 0x01) { | ||
1938 | printk(KERN_INFO | ||
1939 | "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", | ||
1940 | card->devname, (unsigned)rxbuf, rxbuf->opp_flag); | ||
1941 | printk(KERN_INFO "Code name: "); | ||
1942 | for(i = 0; i < 4; i ++) | ||
1943 | printk(KERN_INFO "%c", | ||
1944 | flags->global_info_struct.codename[i]); | ||
1945 | printk(KERN_INFO "\nCode version: "); | ||
1946 | for(i = 0; i < 4; i ++) | ||
1947 | printk(KERN_INFO "%c", | ||
1948 | flags->global_info_struct.codeversion[i]); | ||
1949 | printk(KERN_INFO "\n"); | ||
1950 | |||
1951 | |||
1952 | /* Bug Fix: Mar 6 2000 | ||
1953 | * If we get a corrupted mailbox, it measn that driver | ||
1954 | * is out of sync with the firmware. There is no recovery. | ||
1955 | * If we don't turn off all interrupts for this card | ||
1956 | * the machine will crash. | ||
1957 | */ | ||
1958 | printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname); | ||
1959 | printk(KERN_INFO "Please contact Sangoma Technologies !\n"); | ||
1960 | chdlc_set_intr_mode(card,0); | ||
1961 | return; | ||
1962 | } | ||
1963 | |||
1964 | len = rxbuf->frame_length; | ||
1965 | |||
1966 | if (card->tty_opt){ | ||
1967 | |||
1968 | if (rxbuf->error_flag){ | ||
1969 | goto rx_exit; | ||
1970 | } | ||
1971 | |||
1972 | if (len <= CRC_LENGTH){ | ||
1973 | goto rx_exit; | ||
1974 | } | ||
1975 | |||
1976 | if (!card->u.c.async_mode){ | ||
1977 | len -= CRC_LENGTH; | ||
1978 | } | ||
1979 | |||
1980 | wanpipe_tty_receive(card,addr,len); | ||
1981 | goto rx_exit; | ||
1982 | } | ||
1983 | |||
1984 | dev = card->wandev.dev; | ||
1985 | |||
1986 | if (!dev){ | ||
1987 | goto rx_exit; | ||
1988 | } | ||
1989 | |||
1990 | if (!netif_running(dev)) | ||
1991 | goto rx_exit; | ||
1992 | |||
1993 | chdlc_priv_area = dev->priv; | ||
1994 | |||
1995 | |||
1996 | /* Allocate socket buffer */ | ||
1997 | skb = dev_alloc_skb(len); | ||
1998 | |||
1999 | if (skb == NULL) { | ||
2000 | printk(KERN_INFO "%s: no socket buffers available!\n", | ||
2001 | card->devname); | ||
2002 | ++card->wandev.stats.rx_dropped; | ||
2003 | goto rx_exit; | ||
2004 | } | ||
2005 | |||
2006 | /* Copy data to the socket buffer */ | ||
2007 | if((addr + len) > card->u.c.rx_top + 1) { | ||
2008 | unsigned tmp = card->u.c.rx_top - addr + 1; | ||
2009 | buf = skb_put(skb, tmp); | ||
2010 | sdla_peek(&card->hw, addr, buf, tmp); | ||
2011 | addr = card->u.c.rx_base; | ||
2012 | len -= tmp; | ||
2013 | } | ||
2014 | |||
2015 | buf = skb_put(skb, len); | ||
2016 | sdla_peek(&card->hw, addr, buf, len); | ||
2017 | |||
2018 | skb->protocol = htons(ETH_P_IP); | ||
2019 | |||
2020 | card->wandev.stats.rx_packets ++; | ||
2021 | card->wandev.stats.rx_bytes += skb->len; | ||
2022 | udp_type = udp_pkt_type( skb, card ); | ||
2023 | |||
2024 | if(udp_type == UDP_CPIPE_TYPE) { | ||
2025 | if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, | ||
2026 | card, skb, dev, chdlc_priv_area)) { | ||
2027 | flags->interrupt_info_struct. | ||
2028 | interrupt_permission |= | ||
2029 | APP_INT_ON_TIMER; | ||
2030 | } | ||
2031 | } else if(card->u.c.usedby == API) { | ||
2032 | |||
2033 | api_rx_hdr_t* api_rx_hdr; | ||
2034 | skb_push(skb, sizeof(api_rx_hdr_t)); | ||
2035 | api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00]; | ||
2036 | api_rx_hdr->error_flag = rxbuf->error_flag; | ||
2037 | api_rx_hdr->time_stamp = rxbuf->time_stamp; | ||
2038 | |||
2039 | skb->protocol = htons(PVC_PROT); | ||
2040 | skb->mac.raw = skb->data; | ||
2041 | skb->dev = dev; | ||
2042 | skb->pkt_type = WAN_PACKET_DATA; | ||
2043 | |||
2044 | bh_enqueue(dev, skb); | ||
2045 | |||
2046 | if (!test_and_set_bit(0,&chdlc_priv_area->tq_working)) | ||
2047 | wanpipe_queue_work(&chdlc_priv_area->common.wanpipe_work); | ||
2048 | }else{ | ||
2049 | /* FIXME: we should check to see if the received packet is a | ||
2050 | multicast packet so that we can increment the multicast | ||
2051 | statistic | ||
2052 | ++ chdlc_priv_area->if_stats.multicast; | ||
2053 | */ | ||
2054 | /* Pass it up the protocol stack */ | ||
2055 | |||
2056 | skb->dev = dev; | ||
2057 | skb->mac.raw = skb->data; | ||
2058 | netif_rx(skb); | ||
2059 | dev->last_rx = jiffies; | ||
2060 | } | ||
2061 | |||
2062 | rx_exit: | ||
2063 | /* Release buffer element and calculate a pointer to the next one */ | ||
2064 | rxbuf->opp_flag = 0x00; | ||
2065 | card->u.c.rxmb = ++ rxbuf; | ||
2066 | if((void*)rxbuf > card->u.c.rxbuf_last){ | ||
2067 | card->u.c.rxmb = card->u.c.rxbuf_base; | ||
2068 | } | ||
2069 | } | ||
2070 | |||
2071 | /*============================================================================ | ||
2072 | * Timer interrupt handler. | ||
2073 | * The timer interrupt is used for two purposes: | ||
2074 | * 1) Processing udp calls from 'cpipemon'. | ||
2075 | * 2) Reading board-level statistics for updating the proc file system. | ||
2076 | */ | ||
2077 | void timer_intr(sdla_t *card) | ||
2078 | { | ||
2079 | struct net_device* dev; | ||
2080 | chdlc_private_area_t* chdlc_priv_area = NULL; | ||
2081 | SHARED_MEMORY_INFO_STRUCT* flags = NULL; | ||
2082 | |||
2083 | if ((dev = card->wandev.dev)==NULL){ | ||
2084 | flags = card->u.c.flags; | ||
2085 | flags->interrupt_info_struct.interrupt_permission &= | ||
2086 | ~APP_INT_ON_TIMER; | ||
2087 | return; | ||
2088 | } | ||
2089 | |||
2090 | chdlc_priv_area = dev->priv; | ||
2091 | |||
2092 | if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) { | ||
2093 | if (!config_chdlc(card)){ | ||
2094 | chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG; | ||
2095 | } | ||
2096 | } | ||
2097 | |||
2098 | /* process a udp call if pending */ | ||
2099 | if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) { | ||
2100 | process_udp_mgmt_pkt(card, dev, | ||
2101 | chdlc_priv_area); | ||
2102 | chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP; | ||
2103 | } | ||
2104 | |||
2105 | /* read the communications statistics if required */ | ||
2106 | if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) { | ||
2107 | update_comms_stats(card, chdlc_priv_area); | ||
2108 | if(!(-- chdlc_priv_area->update_comms_stats)) { | ||
2109 | chdlc_priv_area->timer_int_enabled &= | ||
2110 | ~TMR_INT_ENABLED_UPDATE; | ||
2111 | } | ||
2112 | } | ||
2113 | |||
2114 | /* only disable the timer interrupt if there are no udp or statistic */ | ||
2115 | /* updates pending */ | ||
2116 | if(!chdlc_priv_area->timer_int_enabled) { | ||
2117 | flags = card->u.c.flags; | ||
2118 | flags->interrupt_info_struct.interrupt_permission &= | ||
2119 | ~APP_INT_ON_TIMER; | ||
2120 | } | ||
2121 | } | ||
2122 | |||
2123 | /*------------------------------------------------------------------------------ | ||
2124 | Miscellaneous Functions | ||
2125 | - set_chdlc_config() used to set configuration options on the board | ||
2126 | ------------------------------------------------------------------------------*/ | ||
2127 | |||
2128 | static int set_chdlc_config(sdla_t* card) | ||
2129 | { | ||
2130 | CHDLC_CONFIGURATION_STRUCT cfg; | ||
2131 | |||
2132 | memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT)); | ||
2133 | |||
2134 | if(card->wandev.clocking){ | ||
2135 | cfg.baud_rate = card->wandev.bps; | ||
2136 | } | ||
2137 | |||
2138 | cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ? | ||
2139 | INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35; | ||
2140 | |||
2141 | cfg.modem_config_options = 0; | ||
2142 | cfg.modem_status_timer = 100; | ||
2143 | |||
2144 | cfg.CHDLC_protocol_options = card->u.c.protocol_options; | ||
2145 | |||
2146 | if (card->tty_opt){ | ||
2147 | cfg.CHDLC_API_options = DISCARD_RX_ERROR_FRAMES; | ||
2148 | } | ||
2149 | |||
2150 | cfg.percent_data_buffer_for_Tx = (card->u.c.receive_only) ? 0 : 50; | ||
2151 | cfg.CHDLC_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT | | ||
2152 | CHDLC_RX_DATA_BYTE_COUNT_STAT); | ||
2153 | |||
2154 | if (card->tty_opt){ | ||
2155 | card->wandev.mtu = TTY_CHDLC_MAX_MTU; | ||
2156 | } | ||
2157 | cfg.max_CHDLC_data_field_length = card->wandev.mtu; | ||
2158 | cfg.transmit_keepalive_timer = card->u.c.kpalv_tx; | ||
2159 | cfg.receive_keepalive_timer = card->u.c.kpalv_rx; | ||
2160 | cfg.keepalive_error_tolerance = card->u.c.kpalv_err; | ||
2161 | cfg.SLARP_request_timer = card->u.c.slarp_timer; | ||
2162 | |||
2163 | if (cfg.SLARP_request_timer) { | ||
2164 | cfg.IP_address = 0; | ||
2165 | cfg.IP_netmask = 0; | ||
2166 | |||
2167 | }else if (card->wandev.dev){ | ||
2168 | struct net_device *dev = card->wandev.dev; | ||
2169 | chdlc_private_area_t *chdlc_priv_area = dev->priv; | ||
2170 | |||
2171 | struct in_device *in_dev = dev->ip_ptr; | ||
2172 | |||
2173 | if(in_dev != NULL) { | ||
2174 | struct in_ifaddr *ifa = in_dev->ifa_list; | ||
2175 | |||
2176 | if (ifa != NULL ) { | ||
2177 | cfg.IP_address = ntohl(ifa->ifa_local); | ||
2178 | cfg.IP_netmask = ntohl(ifa->ifa_mask); | ||
2179 | chdlc_priv_area->IP_address = ntohl(ifa->ifa_local); | ||
2180 | chdlc_priv_area->IP_netmask = ntohl(ifa->ifa_mask); | ||
2181 | } | ||
2182 | } | ||
2183 | |||
2184 | /* FIXME: We must re-think this message in next release | ||
2185 | if((cfg.IP_address & 0x000000FF) > 2) { | ||
2186 | printk(KERN_WARNING "\n"); | ||
2187 | printk(KERN_WARNING " WARNING:%s configured with an\n", | ||
2188 | card->devname); | ||
2189 | printk(KERN_WARNING " invalid local IP address.\n"); | ||
2190 | printk(KERN_WARNING " Slarp pragmatics will fail.\n"); | ||
2191 | printk(KERN_WARNING " IP address should be of the\n"); | ||
2192 | printk(KERN_WARNING " format A.B.C.1 or A.B.C.2.\n"); | ||
2193 | } | ||
2194 | */ | ||
2195 | } | ||
2196 | |||
2197 | return chdlc_configure(card, &cfg); | ||
2198 | } | ||
2199 | |||
2200 | |||
2201 | /*----------------------------------------------------------------------------- | ||
2202 | set_asy_config() used to set asynchronous configuration options on the board | ||
2203 | ------------------------------------------------------------------------------*/ | ||
2204 | |||
2205 | static int set_asy_config(sdla_t* card) | ||
2206 | { | ||
2207 | |||
2208 | ASY_CONFIGURATION_STRUCT cfg; | ||
2209 | CHDLC_MAILBOX_STRUCT *mailbox = card->mbox; | ||
2210 | int err; | ||
2211 | |||
2212 | memset(&cfg, 0, sizeof(ASY_CONFIGURATION_STRUCT)); | ||
2213 | |||
2214 | if(card->wandev.clocking) | ||
2215 | cfg.baud_rate = card->wandev.bps; | ||
2216 | |||
2217 | cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ? | ||
2218 | INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35; | ||
2219 | |||
2220 | cfg.modem_config_options = 0; | ||
2221 | cfg.asy_API_options = card->u.c.api_options; | ||
2222 | cfg.asy_protocol_options = card->u.c.protocol_options; | ||
2223 | cfg.Tx_bits_per_char = card->u.c.tx_bits_per_char; | ||
2224 | cfg.Rx_bits_per_char = card->u.c.rx_bits_per_char; | ||
2225 | cfg.stop_bits = card->u.c.stop_bits; | ||
2226 | cfg.parity = card->u.c.parity; | ||
2227 | cfg.break_timer = card->u.c.break_timer; | ||
2228 | cfg.asy_Rx_inter_char_timer = card->u.c.inter_char_timer; | ||
2229 | cfg.asy_Rx_complete_length = card->u.c.rx_complete_length; | ||
2230 | cfg.XON_char = card->u.c.xon_char; | ||
2231 | cfg.XOFF_char = card->u.c.xoff_char; | ||
2232 | cfg.asy_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT | | ||
2233 | CHDLC_RX_DATA_BYTE_COUNT_STAT); | ||
2234 | |||
2235 | mailbox->buffer_length = sizeof(ASY_CONFIGURATION_STRUCT); | ||
2236 | memcpy(mailbox->data, &cfg, mailbox->buffer_length); | ||
2237 | mailbox->command = SET_ASY_CONFIGURATION; | ||
2238 | err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT; | ||
2239 | if (err != COMMAND_OK) | ||
2240 | chdlc_error (card, err, mailbox); | ||
2241 | return err; | ||
2242 | } | ||
2243 | |||
2244 | /*============================================================================ | ||
2245 | * Enable asynchronous communications. | ||
2246 | */ | ||
2247 | |||
2248 | static int asy_comm_enable (sdla_t* card) | ||
2249 | { | ||
2250 | |||
2251 | int err; | ||
2252 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
2253 | |||
2254 | mb->buffer_length = 0; | ||
2255 | mb->command = ENABLE_ASY_COMMUNICATIONS; | ||
2256 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
2257 | if (err != COMMAND_OK && card->wandev.dev) | ||
2258 | chdlc_error(card, err, mb); | ||
2259 | |||
2260 | if (!err) | ||
2261 | card->u.c.comm_enabled = 1; | ||
2262 | |||
2263 | return err; | ||
2264 | } | ||
2265 | |||
2266 | /*============================================================================ | ||
2267 | * Process global exception condition | ||
2268 | */ | ||
2269 | static int process_global_exception(sdla_t *card) | ||
2270 | { | ||
2271 | CHDLC_MAILBOX_STRUCT* mbox = card->mbox; | ||
2272 | int err; | ||
2273 | |||
2274 | mbox->buffer_length = 0; | ||
2275 | mbox->command = READ_GLOBAL_EXCEPTION_CONDITION; | ||
2276 | err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT; | ||
2277 | |||
2278 | if(err != CMD_TIMEOUT ){ | ||
2279 | |||
2280 | switch(mbox->return_code) { | ||
2281 | |||
2282 | case EXCEP_MODEM_STATUS_CHANGE: | ||
2283 | |||
2284 | printk(KERN_INFO "%s: Modem status change\n", | ||
2285 | card->devname); | ||
2286 | |||
2287 | switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) { | ||
2288 | case (DCD_HIGH): | ||
2289 | printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname); | ||
2290 | break; | ||
2291 | case (CTS_HIGH): | ||
2292 | printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname); | ||
2293 | break; | ||
2294 | case ((DCD_HIGH | CTS_HIGH)): | ||
2295 | printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname); | ||
2296 | break; | ||
2297 | default: | ||
2298 | printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname); | ||
2299 | break; | ||
2300 | } | ||
2301 | break; | ||
2302 | |||
2303 | case EXCEP_TRC_DISABLED: | ||
2304 | printk(KERN_INFO "%s: Line trace disabled\n", | ||
2305 | card->devname); | ||
2306 | break; | ||
2307 | |||
2308 | case EXCEP_IRQ_TIMEOUT: | ||
2309 | printk(KERN_INFO "%s: IRQ timeout occurred\n", | ||
2310 | card->devname); | ||
2311 | break; | ||
2312 | |||
2313 | case 0x17: | ||
2314 | if (card->tty_opt){ | ||
2315 | if (card->tty && card->tty_open){ | ||
2316 | printk(KERN_INFO | ||
2317 | "%s: Modem Hangup Exception: Hanging Up!\n", | ||
2318 | card->devname); | ||
2319 | tty_hangup(card->tty); | ||
2320 | } | ||
2321 | break; | ||
2322 | } | ||
2323 | |||
2324 | /* If TTY is not used just drop throught */ | ||
2325 | |||
2326 | default: | ||
2327 | printk(KERN_INFO "%s: Global exception %x\n", | ||
2328 | card->devname, mbox->return_code); | ||
2329 | break; | ||
2330 | } | ||
2331 | } | ||
2332 | return 0; | ||
2333 | } | ||
2334 | |||
2335 | |||
2336 | /*============================================================================ | ||
2337 | * Process chdlc exception condition | ||
2338 | */ | ||
2339 | static int process_chdlc_exception(sdla_t *card) | ||
2340 | { | ||
2341 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
2342 | int err; | ||
2343 | |||
2344 | mb->buffer_length = 0; | ||
2345 | mb->command = READ_CHDLC_EXCEPTION_CONDITION; | ||
2346 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
2347 | if(err != CMD_TIMEOUT) { | ||
2348 | |||
2349 | switch (err) { | ||
2350 | |||
2351 | case EXCEP_LINK_ACTIVE: | ||
2352 | port_set_state(card, WAN_CONNECTED); | ||
2353 | trigger_chdlc_poll(card->wandev.dev); | ||
2354 | break; | ||
2355 | |||
2356 | case EXCEP_LINK_INACTIVE_MODEM: | ||
2357 | port_set_state(card, WAN_DISCONNECTED); | ||
2358 | unconfigure_ip(card); | ||
2359 | trigger_chdlc_poll(card->wandev.dev); | ||
2360 | break; | ||
2361 | |||
2362 | case EXCEP_LINK_INACTIVE_KPALV: | ||
2363 | port_set_state(card, WAN_DISCONNECTED); | ||
2364 | printk(KERN_INFO "%s: Keepalive timer expired.\n", | ||
2365 | card->devname); | ||
2366 | unconfigure_ip(card); | ||
2367 | trigger_chdlc_poll(card->wandev.dev); | ||
2368 | break; | ||
2369 | |||
2370 | case EXCEP_IP_ADDRESS_DISCOVERED: | ||
2371 | if (configure_ip(card)) | ||
2372 | return -1; | ||
2373 | break; | ||
2374 | |||
2375 | case EXCEP_LOOPBACK_CONDITION: | ||
2376 | printk(KERN_INFO "%s: Loopback Condition Detected.\n", | ||
2377 | card->devname); | ||
2378 | break; | ||
2379 | |||
2380 | case NO_CHDLC_EXCEP_COND_TO_REPORT: | ||
2381 | printk(KERN_INFO "%s: No exceptions reported.\n", | ||
2382 | card->devname); | ||
2383 | break; | ||
2384 | } | ||
2385 | |||
2386 | } | ||
2387 | return 0; | ||
2388 | } | ||
2389 | |||
2390 | |||
2391 | /*============================================================================ | ||
2392 | * Configure IP from SLARP negotiation | ||
2393 | * This adds dynamic routes when SLARP has provided valid addresses | ||
2394 | */ | ||
2395 | |||
2396 | static int configure_ip (sdla_t* card) | ||
2397 | { | ||
2398 | struct net_device *dev = card->wandev.dev; | ||
2399 | chdlc_private_area_t *chdlc_priv_area; | ||
2400 | char err; | ||
2401 | |||
2402 | if (!dev) | ||
2403 | return 0; | ||
2404 | |||
2405 | chdlc_priv_area = dev->priv; | ||
2406 | |||
2407 | |||
2408 | /* set to discover */ | ||
2409 | if(card->u.c.slarp_timer != 0x00) { | ||
2410 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
2411 | CHDLC_CONFIGURATION_STRUCT *cfg; | ||
2412 | |||
2413 | mb->buffer_length = 0; | ||
2414 | mb->command = READ_CHDLC_CONFIGURATION; | ||
2415 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
2416 | |||
2417 | if(err != COMMAND_OK) { | ||
2418 | chdlc_error(card,err,mb); | ||
2419 | return -1; | ||
2420 | } | ||
2421 | |||
2422 | cfg = (CHDLC_CONFIGURATION_STRUCT *)mb->data; | ||
2423 | chdlc_priv_area->IP_address = cfg->IP_address; | ||
2424 | chdlc_priv_area->IP_netmask = cfg->IP_netmask; | ||
2425 | |||
2426 | /* Set flag to add route */ | ||
2427 | chdlc_priv_area->route_status = ADD_ROUTE; | ||
2428 | |||
2429 | /* The idea here is to add the route in the poll routine. | ||
2430 | This way, we aren't in interrupt context when adding routes */ | ||
2431 | trigger_chdlc_poll(dev); | ||
2432 | } | ||
2433 | |||
2434 | return 0; | ||
2435 | } | ||
2436 | |||
2437 | |||
2438 | /*============================================================================ | ||
2439 | * Un-Configure IP negotiated by SLARP | ||
2440 | * This removes dynamic routes when the link becomes inactive. | ||
2441 | */ | ||
2442 | |||
2443 | static int unconfigure_ip (sdla_t* card) | ||
2444 | { | ||
2445 | struct net_device *dev = card->wandev.dev; | ||
2446 | chdlc_private_area_t *chdlc_priv_area; | ||
2447 | |||
2448 | if (!dev) | ||
2449 | return 0; | ||
2450 | |||
2451 | chdlc_priv_area= dev->priv; | ||
2452 | |||
2453 | if (chdlc_priv_area->route_status == ROUTE_ADDED) { | ||
2454 | |||
2455 | /* Note: If this function is called, the | ||
2456 | * port state has been DISCONNECTED. This state | ||
2457 | * change will trigger a poll_disconnected | ||
2458 | * function, that will check for this condition. | ||
2459 | */ | ||
2460 | chdlc_priv_area->route_status = REMOVE_ROUTE; | ||
2461 | |||
2462 | } | ||
2463 | return 0; | ||
2464 | } | ||
2465 | |||
2466 | /*============================================================================ | ||
2467 | * Routine to add/remove routes | ||
2468 | * Called like a polling routine when Routes are flagged to be added/removed. | ||
2469 | */ | ||
2470 | |||
2471 | static void process_route (sdla_t *card) | ||
2472 | { | ||
2473 | struct net_device *dev = card->wandev.dev; | ||
2474 | unsigned char port_num; | ||
2475 | chdlc_private_area_t *chdlc_priv_area = NULL; | ||
2476 | u32 local_IP_addr = 0; | ||
2477 | u32 remote_IP_addr = 0; | ||
2478 | u32 IP_netmask, IP_addr; | ||
2479 | int err = 0; | ||
2480 | struct in_device *in_dev; | ||
2481 | mm_segment_t fs; | ||
2482 | struct ifreq if_info; | ||
2483 | struct sockaddr_in *if_data1, *if_data2; | ||
2484 | |||
2485 | chdlc_priv_area = dev->priv; | ||
2486 | port_num = card->u.c.comm_port; | ||
2487 | |||
2488 | /* Bug Fix Mar 16 2000 | ||
2489 | * AND the IP address to the Mask before checking | ||
2490 | * the last two bits. */ | ||
2491 | |||
2492 | if((chdlc_priv_area->route_status == ADD_ROUTE) && | ||
2493 | ((chdlc_priv_area->IP_address & ~chdlc_priv_area->IP_netmask) > 2)) { | ||
2494 | |||
2495 | printk(KERN_INFO "%s: Dynamic route failure.\n",card->devname); | ||
2496 | |||
2497 | if(card->u.c.slarp_timer) { | ||
2498 | u32 addr_net = htonl(chdlc_priv_area->IP_address); | ||
2499 | |||
2500 | printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u received\n", | ||
2501 | card->devname, | ||
2502 | NIPQUAD(addr_net)); | ||
2503 | printk(KERN_INFO "%s: from remote station.\n", | ||
2504 | card->devname); | ||
2505 | |||
2506 | }else{ | ||
2507 | u32 addr_net = htonl(chdlc_priv_area->IP_address); | ||
2508 | |||
2509 | printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u issued\n", | ||
2510 | card->devname, | ||
2511 | NIPQUAD(addr_net)); | ||
2512 | printk(KERN_INFO "%s: to remote station. Local\n", | ||
2513 | card->devname); | ||
2514 | printk(KERN_INFO "%s: IP address must be A.B.C.1\n", | ||
2515 | card->devname); | ||
2516 | printk(KERN_INFO "%s: or A.B.C.2.\n",card->devname); | ||
2517 | } | ||
2518 | |||
2519 | /* remove the route due to the IP address error condition */ | ||
2520 | chdlc_priv_area->route_status = REMOVE_ROUTE; | ||
2521 | err = 1; | ||
2522 | } | ||
2523 | |||
2524 | /* If we are removing a route with bad IP addressing, then use the */ | ||
2525 | /* locally configured IP addresses */ | ||
2526 | if((chdlc_priv_area->route_status == REMOVE_ROUTE) && err) { | ||
2527 | |||
2528 | /* do not remove a bad route that has already been removed */ | ||
2529 | if(chdlc_priv_area->route_removed) { | ||
2530 | return; | ||
2531 | } | ||
2532 | |||
2533 | in_dev = dev->ip_ptr; | ||
2534 | |||
2535 | if(in_dev != NULL) { | ||
2536 | struct in_ifaddr *ifa = in_dev->ifa_list; | ||
2537 | if (ifa != NULL ) { | ||
2538 | local_IP_addr = ifa->ifa_local; | ||
2539 | IP_netmask = ifa->ifa_mask; | ||
2540 | } | ||
2541 | } | ||
2542 | }else{ | ||
2543 | /* According to Cisco HDLC, if the point-to-point address is | ||
2544 | A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa. | ||
2545 | */ | ||
2546 | IP_netmask = ntohl(chdlc_priv_area->IP_netmask); | ||
2547 | remote_IP_addr = ntohl(chdlc_priv_area->IP_address); | ||
2548 | |||
2549 | |||
2550 | /* If Netmask is 255.255.255.255 the local address | ||
2551 | * calculation will fail. Default it back to 255.255.255.0 */ | ||
2552 | if (IP_netmask == 0xffffffff) | ||
2553 | IP_netmask &= 0x00ffffff; | ||
2554 | |||
2555 | /* Bug Fix Mar 16 2000 | ||
2556 | * AND the Remote IP address with IP netmask, instead | ||
2557 | * of static netmask of 255.255.255.0 */ | ||
2558 | local_IP_addr = (remote_IP_addr & IP_netmask) + | ||
2559 | (~remote_IP_addr & ntohl(0x0003)); | ||
2560 | |||
2561 | if(!card->u.c.slarp_timer) { | ||
2562 | IP_addr = local_IP_addr; | ||
2563 | local_IP_addr = remote_IP_addr; | ||
2564 | remote_IP_addr = IP_addr; | ||
2565 | } | ||
2566 | } | ||
2567 | |||
2568 | fs = get_fs(); /* Save file system */ | ||
2569 | set_fs(get_ds()); /* Get user space block */ | ||
2570 | |||
2571 | /* Setup a structure for adding/removing routes */ | ||
2572 | memset(&if_info, 0, sizeof(if_info)); | ||
2573 | strcpy(if_info.ifr_name, dev->name); | ||
2574 | |||
2575 | switch (chdlc_priv_area->route_status) { | ||
2576 | |||
2577 | case ADD_ROUTE: | ||
2578 | |||
2579 | if(!card->u.c.slarp_timer) { | ||
2580 | if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; | ||
2581 | if_data2->sin_addr.s_addr = remote_IP_addr; | ||
2582 | if_data2->sin_family = AF_INET; | ||
2583 | err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); | ||
2584 | } else { | ||
2585 | if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; | ||
2586 | if_data1->sin_addr.s_addr = local_IP_addr; | ||
2587 | if_data1->sin_family = AF_INET; | ||
2588 | if(!(err = devinet_ioctl(SIOCSIFADDR, &if_info))){ | ||
2589 | if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; | ||
2590 | if_data2->sin_addr.s_addr = remote_IP_addr; | ||
2591 | if_data2->sin_family = AF_INET; | ||
2592 | err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); | ||
2593 | } | ||
2594 | } | ||
2595 | |||
2596 | if(err) { | ||
2597 | printk(KERN_INFO "%s: Add route %u.%u.%u.%u failed (%d)\n", | ||
2598 | card->devname, NIPQUAD(remote_IP_addr), err); | ||
2599 | } else { | ||
2600 | ((chdlc_private_area_t *)dev->priv)->route_status = ROUTE_ADDED; | ||
2601 | printk(KERN_INFO "%s: Dynamic route added.\n", | ||
2602 | card->devname); | ||
2603 | printk(KERN_INFO "%s: Local IP addr : %u.%u.%u.%u\n", | ||
2604 | card->devname, NIPQUAD(local_IP_addr)); | ||
2605 | printk(KERN_INFO "%s: Remote IP addr: %u.%u.%u.%u\n", | ||
2606 | card->devname, NIPQUAD(remote_IP_addr)); | ||
2607 | chdlc_priv_area->route_removed = 0; | ||
2608 | } | ||
2609 | break; | ||
2610 | |||
2611 | |||
2612 | case REMOVE_ROUTE: | ||
2613 | |||
2614 | /* Change the local ip address of the interface to 0. | ||
2615 | * This will also delete the destination route. | ||
2616 | */ | ||
2617 | if(!card->u.c.slarp_timer) { | ||
2618 | if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; | ||
2619 | if_data2->sin_addr.s_addr = 0; | ||
2620 | if_data2->sin_family = AF_INET; | ||
2621 | err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); | ||
2622 | } else { | ||
2623 | if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; | ||
2624 | if_data1->sin_addr.s_addr = 0; | ||
2625 | if_data1->sin_family = AF_INET; | ||
2626 | err = devinet_ioctl(SIOCSIFADDR,&if_info); | ||
2627 | |||
2628 | } | ||
2629 | if(err) { | ||
2630 | printk(KERN_INFO | ||
2631 | "%s: Remove route %u.%u.%u.%u failed, (err %d)\n", | ||
2632 | card->devname, NIPQUAD(remote_IP_addr), | ||
2633 | err); | ||
2634 | } else { | ||
2635 | ((chdlc_private_area_t *)dev->priv)->route_status = | ||
2636 | NO_ROUTE; | ||
2637 | printk(KERN_INFO "%s: Dynamic route removed: %u.%u.%u.%u\n", | ||
2638 | card->devname, NIPQUAD(local_IP_addr)); | ||
2639 | chdlc_priv_area->route_removed = 1; | ||
2640 | } | ||
2641 | break; | ||
2642 | } | ||
2643 | |||
2644 | set_fs(fs); /* Restore file system */ | ||
2645 | |||
2646 | } | ||
2647 | |||
2648 | |||
2649 | /*============================================================================= | ||
2650 | * Store a UDP management packet for later processing. | ||
2651 | */ | ||
2652 | |||
2653 | static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, | ||
2654 | struct sk_buff *skb, struct net_device* dev, | ||
2655 | chdlc_private_area_t* chdlc_priv_area) | ||
2656 | { | ||
2657 | int udp_pkt_stored = 0; | ||
2658 | |||
2659 | if(!chdlc_priv_area->udp_pkt_lgth && | ||
2660 | (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) { | ||
2661 | chdlc_priv_area->udp_pkt_lgth = skb->len; | ||
2662 | chdlc_priv_area->udp_pkt_src = udp_pkt_src; | ||
2663 | memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len); | ||
2664 | chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP; | ||
2665 | udp_pkt_stored = 1; | ||
2666 | } | ||
2667 | |||
2668 | if(udp_pkt_src == UDP_PKT_FRM_STACK){ | ||
2669 | dev_kfree_skb_any(skb); | ||
2670 | }else{ | ||
2671 | dev_kfree_skb_any(skb); | ||
2672 | } | ||
2673 | |||
2674 | return(udp_pkt_stored); | ||
2675 | } | ||
2676 | |||
2677 | |||
2678 | /*============================================================================= | ||
2679 | * Process UDP management packet. | ||
2680 | */ | ||
2681 | |||
2682 | static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev, | ||
2683 | chdlc_private_area_t* chdlc_priv_area ) | ||
2684 | { | ||
2685 | unsigned char *buf; | ||
2686 | unsigned int frames, len; | ||
2687 | struct sk_buff *new_skb; | ||
2688 | unsigned short buffer_length, real_len; | ||
2689 | unsigned long data_ptr; | ||
2690 | unsigned data_length; | ||
2691 | int udp_mgmt_req_valid = 1; | ||
2692 | CHDLC_MAILBOX_STRUCT *mb = card->mbox; | ||
2693 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
2694 | chdlc_udp_pkt_t *chdlc_udp_pkt; | ||
2695 | struct timeval tv; | ||
2696 | int err; | ||
2697 | char ut_char; | ||
2698 | |||
2699 | chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data; | ||
2700 | |||
2701 | if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){ | ||
2702 | |||
2703 | /* Only these commands are support for remote debugging. | ||
2704 | * All others are not */ | ||
2705 | switch(chdlc_udp_pkt->cblock.command) { | ||
2706 | |||
2707 | case READ_GLOBAL_STATISTICS: | ||
2708 | case READ_MODEM_STATUS: | ||
2709 | case READ_CHDLC_LINK_STATUS: | ||
2710 | case CPIPE_ROUTER_UP_TIME: | ||
2711 | case READ_COMMS_ERROR_STATS: | ||
2712 | case READ_CHDLC_OPERATIONAL_STATS: | ||
2713 | |||
2714 | /* These two commands are executed for | ||
2715 | * each request */ | ||
2716 | case READ_CHDLC_CONFIGURATION: | ||
2717 | case READ_CHDLC_CODE_VERSION: | ||
2718 | udp_mgmt_req_valid = 1; | ||
2719 | break; | ||
2720 | default: | ||
2721 | udp_mgmt_req_valid = 0; | ||
2722 | break; | ||
2723 | } | ||
2724 | } | ||
2725 | |||
2726 | if(!udp_mgmt_req_valid) { | ||
2727 | |||
2728 | /* set length to 0 */ | ||
2729 | chdlc_udp_pkt->cblock.buffer_length = 0; | ||
2730 | |||
2731 | /* set return code */ | ||
2732 | chdlc_udp_pkt->cblock.return_code = 0xCD; | ||
2733 | |||
2734 | if (net_ratelimit()){ | ||
2735 | printk(KERN_INFO | ||
2736 | "%s: Warning, Illegal UDP command attempted from network: %x\n", | ||
2737 | card->devname,chdlc_udp_pkt->cblock.command); | ||
2738 | } | ||
2739 | |||
2740 | } else { | ||
2741 | unsigned long trace_status_cfg_addr = 0; | ||
2742 | TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct; | ||
2743 | TRACE_STATUS_ELEMENT_STRUCT trace_element_struct; | ||
2744 | |||
2745 | switch(chdlc_udp_pkt->cblock.command) { | ||
2746 | |||
2747 | case CPIPE_ENABLE_TRACING: | ||
2748 | if (!chdlc_priv_area->TracingEnabled) { | ||
2749 | |||
2750 | /* OPERATE_DATALINE_MONITOR */ | ||
2751 | |||
2752 | mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT); | ||
2753 | mb->command = SET_TRACE_CONFIGURATION; | ||
2754 | |||
2755 | ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> | ||
2756 | trace_config = TRACE_ACTIVE; | ||
2757 | /* Trace delay mode is not used because it slows | ||
2758 | down transfer and results in a standoff situation | ||
2759 | when there is a lot of data */ | ||
2760 | |||
2761 | /* Configure the Trace based on user inputs */ | ||
2762 | ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |= | ||
2763 | chdlc_udp_pkt->data[0]; | ||
2764 | |||
2765 | ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> | ||
2766 | trace_deactivation_timer = 4000; | ||
2767 | |||
2768 | |||
2769 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
2770 | if (err != COMMAND_OK) { | ||
2771 | chdlc_error(card,err,mb); | ||
2772 | card->TracingEnabled = 0; | ||
2773 | chdlc_udp_pkt->cblock.return_code = err; | ||
2774 | mb->buffer_length = 0; | ||
2775 | break; | ||
2776 | } | ||
2777 | |||
2778 | /* Get the base address of the trace element list */ | ||
2779 | mb->buffer_length = 0; | ||
2780 | mb->command = READ_TRACE_CONFIGURATION; | ||
2781 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
2782 | |||
2783 | if (err != COMMAND_OK) { | ||
2784 | chdlc_error(card,err,mb); | ||
2785 | chdlc_priv_area->TracingEnabled = 0; | ||
2786 | chdlc_udp_pkt->cblock.return_code = err; | ||
2787 | mb->buffer_length = 0; | ||
2788 | break; | ||
2789 | } | ||
2790 | |||
2791 | trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *) | ||
2792 | mb->data) -> ptr_trace_stat_el_cfg_struct; | ||
2793 | |||
2794 | sdla_peek(&card->hw, trace_status_cfg_addr, | ||
2795 | &trace_cfg_struct, sizeof(trace_cfg_struct)); | ||
2796 | |||
2797 | chdlc_priv_area->start_trace_addr = trace_cfg_struct. | ||
2798 | base_addr_trace_status_elements; | ||
2799 | |||
2800 | chdlc_priv_area->number_trace_elements = | ||
2801 | trace_cfg_struct.number_trace_status_elements; | ||
2802 | |||
2803 | chdlc_priv_area->end_trace_addr = (unsigned long) | ||
2804 | ((TRACE_STATUS_ELEMENT_STRUCT *) | ||
2805 | chdlc_priv_area->start_trace_addr + | ||
2806 | (chdlc_priv_area->number_trace_elements - 1)); | ||
2807 | |||
2808 | chdlc_priv_area->base_addr_trace_buffer = | ||
2809 | trace_cfg_struct.base_addr_trace_buffer; | ||
2810 | |||
2811 | chdlc_priv_area->end_addr_trace_buffer = | ||
2812 | trace_cfg_struct.end_addr_trace_buffer; | ||
2813 | |||
2814 | chdlc_priv_area->curr_trace_addr = | ||
2815 | trace_cfg_struct.next_trace_element_to_use; | ||
2816 | |||
2817 | chdlc_priv_area->available_buffer_space = 2000 - | ||
2818 | sizeof(ip_pkt_t) - | ||
2819 | sizeof(udp_pkt_t) - | ||
2820 | sizeof(wp_mgmt_t) - | ||
2821 | sizeof(cblock_t) - | ||
2822 | sizeof(trace_info_t); | ||
2823 | } | ||
2824 | chdlc_udp_pkt->cblock.return_code = COMMAND_OK; | ||
2825 | mb->buffer_length = 0; | ||
2826 | chdlc_priv_area->TracingEnabled = 1; | ||
2827 | break; | ||
2828 | |||
2829 | |||
2830 | case CPIPE_DISABLE_TRACING: | ||
2831 | if (chdlc_priv_area->TracingEnabled) { | ||
2832 | |||
2833 | /* OPERATE_DATALINE_MONITOR */ | ||
2834 | mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT); | ||
2835 | mb->command = SET_TRACE_CONFIGURATION; | ||
2836 | ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> | ||
2837 | trace_config = TRACE_INACTIVE; | ||
2838 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
2839 | } | ||
2840 | |||
2841 | chdlc_priv_area->TracingEnabled = 0; | ||
2842 | chdlc_udp_pkt->cblock.return_code = COMMAND_OK; | ||
2843 | mb->buffer_length = 0; | ||
2844 | break; | ||
2845 | |||
2846 | |||
2847 | case CPIPE_GET_TRACE_INFO: | ||
2848 | |||
2849 | if (!chdlc_priv_area->TracingEnabled) { | ||
2850 | chdlc_udp_pkt->cblock.return_code = 1; | ||
2851 | mb->buffer_length = 0; | ||
2852 | break; | ||
2853 | } | ||
2854 | |||
2855 | chdlc_udp_pkt->trace_info.ismoredata = 0x00; | ||
2856 | buffer_length = 0; /* offset of packet already occupied */ | ||
2857 | |||
2858 | for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){ | ||
2859 | |||
2860 | trace_pkt_t *trace_pkt = (trace_pkt_t *) | ||
2861 | &chdlc_udp_pkt->data[buffer_length]; | ||
2862 | |||
2863 | sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr, | ||
2864 | (unsigned char *)&trace_element_struct, | ||
2865 | sizeof(TRACE_STATUS_ELEMENT_STRUCT)); | ||
2866 | |||
2867 | if (trace_element_struct.opp_flag == 0x00) { | ||
2868 | break; | ||
2869 | } | ||
2870 | |||
2871 | /* get pointer to real data */ | ||
2872 | data_ptr = trace_element_struct.ptr_data_bfr; | ||
2873 | |||
2874 | /* See if there is actual data on the trace buffer */ | ||
2875 | if (data_ptr){ | ||
2876 | data_length = trace_element_struct.trace_length; | ||
2877 | }else{ | ||
2878 | data_length = 0; | ||
2879 | chdlc_udp_pkt->trace_info.ismoredata = 0x01; | ||
2880 | } | ||
2881 | |||
2882 | if( (chdlc_priv_area->available_buffer_space - buffer_length) | ||
2883 | < ( sizeof(trace_pkt_t) + data_length) ) { | ||
2884 | |||
2885 | /* indicate there are more frames on board & exit */ | ||
2886 | chdlc_udp_pkt->trace_info.ismoredata = 0x01; | ||
2887 | break; | ||
2888 | } | ||
2889 | |||
2890 | trace_pkt->status = trace_element_struct.trace_type; | ||
2891 | |||
2892 | trace_pkt->time_stamp = | ||
2893 | trace_element_struct.trace_time_stamp; | ||
2894 | |||
2895 | trace_pkt->real_length = | ||
2896 | trace_element_struct.trace_length; | ||
2897 | |||
2898 | /* see if we can fit the frame into the user buffer */ | ||
2899 | real_len = trace_pkt->real_length; | ||
2900 | |||
2901 | if (data_ptr == 0) { | ||
2902 | trace_pkt->data_avail = 0x00; | ||
2903 | } else { | ||
2904 | unsigned tmp = 0; | ||
2905 | |||
2906 | /* get the data from circular buffer | ||
2907 | must check for end of buffer */ | ||
2908 | trace_pkt->data_avail = 0x01; | ||
2909 | |||
2910 | if ((data_ptr + real_len) > | ||
2911 | chdlc_priv_area->end_addr_trace_buffer + 1){ | ||
2912 | |||
2913 | tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1; | ||
2914 | sdla_peek(&card->hw, data_ptr, | ||
2915 | trace_pkt->data,tmp); | ||
2916 | data_ptr = chdlc_priv_area->base_addr_trace_buffer; | ||
2917 | } | ||
2918 | |||
2919 | sdla_peek(&card->hw, data_ptr, | ||
2920 | &trace_pkt->data[tmp], real_len - tmp); | ||
2921 | } | ||
2922 | |||
2923 | /* zero the opp flag to show we got the frame */ | ||
2924 | ut_char = 0x00; | ||
2925 | sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1); | ||
2926 | |||
2927 | /* now move onto the next frame */ | ||
2928 | chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT); | ||
2929 | |||
2930 | /* check if we went over the last address */ | ||
2931 | if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) { | ||
2932 | chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr; | ||
2933 | } | ||
2934 | |||
2935 | if(trace_pkt->data_avail == 0x01) { | ||
2936 | buffer_length += real_len - 1; | ||
2937 | } | ||
2938 | |||
2939 | /* for the header */ | ||
2940 | buffer_length += sizeof(trace_pkt_t); | ||
2941 | |||
2942 | } /* For Loop */ | ||
2943 | |||
2944 | if (frames == chdlc_priv_area->number_trace_elements){ | ||
2945 | chdlc_udp_pkt->trace_info.ismoredata = 0x01; | ||
2946 | } | ||
2947 | chdlc_udp_pkt->trace_info.num_frames = frames; | ||
2948 | |||
2949 | mb->buffer_length = buffer_length; | ||
2950 | chdlc_udp_pkt->cblock.buffer_length = buffer_length; | ||
2951 | |||
2952 | chdlc_udp_pkt->cblock.return_code = COMMAND_OK; | ||
2953 | |||
2954 | break; | ||
2955 | |||
2956 | |||
2957 | case CPIPE_FT1_READ_STATUS: | ||
2958 | ((unsigned char *)chdlc_udp_pkt->data )[0] = | ||
2959 | flags->FT1_info_struct.parallel_port_A_input; | ||
2960 | |||
2961 | ((unsigned char *)chdlc_udp_pkt->data )[1] = | ||
2962 | flags->FT1_info_struct.parallel_port_B_input; | ||
2963 | |||
2964 | chdlc_udp_pkt->cblock.return_code = COMMAND_OK; | ||
2965 | chdlc_udp_pkt->cblock.buffer_length = 2; | ||
2966 | mb->buffer_length = 2; | ||
2967 | break; | ||
2968 | |||
2969 | case CPIPE_ROUTER_UP_TIME: | ||
2970 | do_gettimeofday( &tv ); | ||
2971 | chdlc_priv_area->router_up_time = tv.tv_sec - | ||
2972 | chdlc_priv_area->router_start_time; | ||
2973 | *(unsigned long *)&chdlc_udp_pkt->data = | ||
2974 | chdlc_priv_area->router_up_time; | ||
2975 | mb->buffer_length = sizeof(unsigned long); | ||
2976 | chdlc_udp_pkt->cblock.buffer_length = sizeof(unsigned long); | ||
2977 | chdlc_udp_pkt->cblock.return_code = COMMAND_OK; | ||
2978 | break; | ||
2979 | |||
2980 | case FT1_MONITOR_STATUS_CTRL: | ||
2981 | /* Enable FT1 MONITOR STATUS */ | ||
2982 | if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) || | ||
2983 | (chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) { | ||
2984 | |||
2985 | if( rCount++ != 0 ) { | ||
2986 | chdlc_udp_pkt->cblock. | ||
2987 | return_code = COMMAND_OK; | ||
2988 | mb->buffer_length = 1; | ||
2989 | break; | ||
2990 | } | ||
2991 | } | ||
2992 | |||
2993 | /* Disable FT1 MONITOR STATUS */ | ||
2994 | if( chdlc_udp_pkt->data[0] == 0) { | ||
2995 | |||
2996 | if( --rCount != 0) { | ||
2997 | chdlc_udp_pkt->cblock. | ||
2998 | return_code = COMMAND_OK; | ||
2999 | mb->buffer_length = 1; | ||
3000 | break; | ||
3001 | } | ||
3002 | } | ||
3003 | goto dflt_1; | ||
3004 | |||
3005 | default: | ||
3006 | dflt_1: | ||
3007 | /* it's a board command */ | ||
3008 | mb->command = chdlc_udp_pkt->cblock.command; | ||
3009 | mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length; | ||
3010 | if (mb->buffer_length) { | ||
3011 | memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt-> | ||
3012 | data, mb->buffer_length); | ||
3013 | } | ||
3014 | /* run the command on the board */ | ||
3015 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
3016 | if (err != COMMAND_OK) { | ||
3017 | break; | ||
3018 | } | ||
3019 | |||
3020 | /* copy the result back to our buffer */ | ||
3021 | memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t)); | ||
3022 | |||
3023 | if (mb->buffer_length) { | ||
3024 | memcpy(&chdlc_udp_pkt->data, &mb->data, | ||
3025 | mb->buffer_length); | ||
3026 | } | ||
3027 | |||
3028 | } /* end of switch */ | ||
3029 | } /* end of else */ | ||
3030 | |||
3031 | /* Fill UDP TTL */ | ||
3032 | chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl; | ||
3033 | |||
3034 | len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length); | ||
3035 | |||
3036 | |||
3037 | if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){ | ||
3038 | |||
3039 | /* Must check if we interrupted if_send() routine. The | ||
3040 | * tx buffers might be used. If so drop the packet */ | ||
3041 | if (!test_bit(SEND_CRIT,&card->wandev.critical)) { | ||
3042 | |||
3043 | if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) { | ||
3044 | ++ card->wandev.stats.tx_packets; | ||
3045 | card->wandev.stats.tx_bytes += len; | ||
3046 | } | ||
3047 | } | ||
3048 | } else { | ||
3049 | |||
3050 | /* Pass it up the stack | ||
3051 | Allocate socket buffer */ | ||
3052 | if ((new_skb = dev_alloc_skb(len)) != NULL) { | ||
3053 | /* copy data into new_skb */ | ||
3054 | |||
3055 | buf = skb_put(new_skb, len); | ||
3056 | memcpy(buf, chdlc_priv_area->udp_pkt_data, len); | ||
3057 | |||
3058 | /* Decapsulate pkt and pass it up the protocol stack */ | ||
3059 | new_skb->protocol = htons(ETH_P_IP); | ||
3060 | new_skb->dev = dev; | ||
3061 | new_skb->mac.raw = new_skb->data; | ||
3062 | |||
3063 | netif_rx(new_skb); | ||
3064 | dev->last_rx = jiffies; | ||
3065 | } else { | ||
3066 | |||
3067 | printk(KERN_INFO "%s: no socket buffers available!\n", | ||
3068 | card->devname); | ||
3069 | } | ||
3070 | } | ||
3071 | |||
3072 | chdlc_priv_area->udp_pkt_lgth = 0; | ||
3073 | |||
3074 | return 0; | ||
3075 | } | ||
3076 | |||
3077 | /*============================================================================ | ||
3078 | * Initialize Receive and Transmit Buffers. | ||
3079 | */ | ||
3080 | |||
3081 | static void init_chdlc_tx_rx_buff( sdla_t* card) | ||
3082 | { | ||
3083 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
3084 | CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config; | ||
3085 | CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config; | ||
3086 | char err; | ||
3087 | |||
3088 | mb->buffer_length = 0; | ||
3089 | mb->command = READ_CHDLC_CONFIGURATION; | ||
3090 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
3091 | |||
3092 | if(err != COMMAND_OK) { | ||
3093 | if (card->wandev.dev){ | ||
3094 | chdlc_error(card,err,mb); | ||
3095 | } | ||
3096 | return; | ||
3097 | } | ||
3098 | |||
3099 | if(card->hw.type == SDLA_S514) { | ||
3100 | tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + | ||
3101 | (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> | ||
3102 | ptr_CHDLC_Tx_stat_el_cfg_struct)); | ||
3103 | rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + | ||
3104 | (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> | ||
3105 | ptr_CHDLC_Rx_stat_el_cfg_struct)); | ||
3106 | |||
3107 | /* Setup Head and Tails for buffers */ | ||
3108 | card->u.c.txbuf_base = (void *)(card->hw.dpmbase + | ||
3109 | tx_config->base_addr_Tx_status_elements); | ||
3110 | card->u.c.txbuf_last = | ||
3111 | (CHDLC_DATA_TX_STATUS_EL_STRUCT *) | ||
3112 | card->u.c.txbuf_base + | ||
3113 | (tx_config->number_Tx_status_elements - 1); | ||
3114 | |||
3115 | card->u.c.rxbuf_base = (void *)(card->hw.dpmbase + | ||
3116 | rx_config->base_addr_Rx_status_elements); | ||
3117 | card->u.c.rxbuf_last = | ||
3118 | (CHDLC_DATA_RX_STATUS_EL_STRUCT *) | ||
3119 | card->u.c.rxbuf_base + | ||
3120 | (rx_config->number_Rx_status_elements - 1); | ||
3121 | |||
3122 | /* Set up next pointer to be used */ | ||
3123 | card->u.c.txbuf = (void *)(card->hw.dpmbase + | ||
3124 | tx_config->next_Tx_status_element_to_use); | ||
3125 | card->u.c.rxmb = (void *)(card->hw.dpmbase + | ||
3126 | rx_config->next_Rx_status_element_to_use); | ||
3127 | } | ||
3128 | else { | ||
3129 | tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + | ||
3130 | (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> | ||
3131 | ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE)); | ||
3132 | |||
3133 | rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + | ||
3134 | (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> | ||
3135 | ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE)); | ||
3136 | |||
3137 | /* Setup Head and Tails for buffers */ | ||
3138 | card->u.c.txbuf_base = (void *)(card->hw.dpmbase + | ||
3139 | (tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE)); | ||
3140 | card->u.c.txbuf_last = | ||
3141 | (CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base | ||
3142 | + (tx_config->number_Tx_status_elements - 1); | ||
3143 | card->u.c.rxbuf_base = (void *)(card->hw.dpmbase + | ||
3144 | (rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE)); | ||
3145 | card->u.c.rxbuf_last = | ||
3146 | (CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base | ||
3147 | + (rx_config->number_Rx_status_elements - 1); | ||
3148 | |||
3149 | /* Set up next pointer to be used */ | ||
3150 | card->u.c.txbuf = (void *)(card->hw.dpmbase + | ||
3151 | (tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE)); | ||
3152 | card->u.c.rxmb = (void *)(card->hw.dpmbase + | ||
3153 | (rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE)); | ||
3154 | } | ||
3155 | |||
3156 | /* Setup Actual Buffer Start and end addresses */ | ||
3157 | card->u.c.rx_base = rx_config->base_addr_Rx_buffer; | ||
3158 | card->u.c.rx_top = rx_config->end_addr_Rx_buffer; | ||
3159 | |||
3160 | } | ||
3161 | |||
3162 | /*============================================================================= | ||
3163 | * Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR | ||
3164 | * _TEST_COUNTER times. | ||
3165 | */ | ||
3166 | static int intr_test( sdla_t* card) | ||
3167 | { | ||
3168 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
3169 | int err,i; | ||
3170 | |||
3171 | Intr_test_counter = 0; | ||
3172 | |||
3173 | err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE); | ||
3174 | |||
3175 | if (err == CMD_OK) { | ||
3176 | for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) { | ||
3177 | mb->buffer_length = 0; | ||
3178 | mb->command = READ_CHDLC_CODE_VERSION; | ||
3179 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
3180 | if (err != CMD_OK) | ||
3181 | chdlc_error(card, err, mb); | ||
3182 | } | ||
3183 | } | ||
3184 | else { | ||
3185 | return err; | ||
3186 | } | ||
3187 | |||
3188 | err = chdlc_set_intr_mode(card, 0); | ||
3189 | |||
3190 | if (err != CMD_OK) | ||
3191 | return err; | ||
3192 | |||
3193 | return 0; | ||
3194 | } | ||
3195 | |||
3196 | /*============================================================================== | ||
3197 | * Determine what type of UDP call it is. CPIPEAB ? | ||
3198 | */ | ||
3199 | static int udp_pkt_type(struct sk_buff *skb, sdla_t* card) | ||
3200 | { | ||
3201 | chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data; | ||
3202 | |||
3203 | #ifdef _WAN_UDP_DEBUG | ||
3204 | printk(KERN_INFO "SIG %s = %s\n\ | ||
3205 | UPP %x = %x\n\ | ||
3206 | PRT %x = %x\n\ | ||
3207 | REQ %i = %i\n\ | ||
3208 | 36 th = %x 37th = %x\n", | ||
3209 | chdlc_udp_pkt->wp_mgmt.signature, | ||
3210 | UDPMGMT_SIGNATURE, | ||
3211 | chdlc_udp_pkt->udp_pkt.udp_dst_port, | ||
3212 | ntohs(card->wandev.udp_port), | ||
3213 | chdlc_udp_pkt->ip_pkt.protocol, | ||
3214 | UDPMGMT_UDP_PROTOCOL, | ||
3215 | chdlc_udp_pkt->wp_mgmt.request_reply, | ||
3216 | UDPMGMT_REQUEST, | ||
3217 | skb->data[36], skb->data[37]); | ||
3218 | #endif | ||
3219 | |||
3220 | if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) && | ||
3221 | (chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) && | ||
3222 | (chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) && | ||
3223 | (chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) { | ||
3224 | |||
3225 | return UDP_CPIPE_TYPE; | ||
3226 | |||
3227 | }else{ | ||
3228 | return UDP_INVALID_TYPE; | ||
3229 | } | ||
3230 | } | ||
3231 | |||
3232 | /*============================================================================ | ||
3233 | * Set PORT state. | ||
3234 | */ | ||
3235 | static void port_set_state (sdla_t *card, int state) | ||
3236 | { | ||
3237 | if (card->u.c.state != state) | ||
3238 | { | ||
3239 | switch (state) | ||
3240 | { | ||
3241 | case WAN_CONNECTED: | ||
3242 | printk (KERN_INFO "%s: Link connected!\n", | ||
3243 | card->devname); | ||
3244 | break; | ||
3245 | |||
3246 | case WAN_CONNECTING: | ||
3247 | printk (KERN_INFO "%s: Link connecting...\n", | ||
3248 | card->devname); | ||
3249 | break; | ||
3250 | |||
3251 | case WAN_DISCONNECTED: | ||
3252 | printk (KERN_INFO "%s: Link disconnected!\n", | ||
3253 | card->devname); | ||
3254 | break; | ||
3255 | } | ||
3256 | |||
3257 | card->wandev.state = card->u.c.state = state; | ||
3258 | if (card->wandev.dev){ | ||
3259 | struct net_device *dev = card->wandev.dev; | ||
3260 | chdlc_private_area_t *chdlc_priv_area = dev->priv; | ||
3261 | chdlc_priv_area->common.state = state; | ||
3262 | } | ||
3263 | } | ||
3264 | } | ||
3265 | |||
3266 | /*=========================================================================== | ||
3267 | * config_chdlc | ||
3268 | * | ||
3269 | * Configure the chdlc protocol and enable communications. | ||
3270 | * | ||
3271 | * The if_open() function binds this function to the poll routine. | ||
3272 | * Therefore, this function will run every time the chdlc interface | ||
3273 | * is brought up. We cannot run this function from the if_open | ||
3274 | * because if_open does not have access to the remote IP address. | ||
3275 | * | ||
3276 | * If the communications are not enabled, proceed to configure | ||
3277 | * the card and enable communications. | ||
3278 | * | ||
3279 | * If the communications are enabled, it means that the interface | ||
3280 | * was shutdown by ether the user or driver. In this case, we | ||
3281 | * have to check that the IP addresses have not changed. If | ||
3282 | * the IP addresses have changed, we have to reconfigure the firmware | ||
3283 | * and update the changed IP addresses. Otherwise, just exit. | ||
3284 | * | ||
3285 | */ | ||
3286 | |||
3287 | static int config_chdlc (sdla_t *card) | ||
3288 | { | ||
3289 | struct net_device *dev = card->wandev.dev; | ||
3290 | chdlc_private_area_t *chdlc_priv_area = dev->priv; | ||
3291 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
3292 | |||
3293 | if (card->u.c.comm_enabled){ | ||
3294 | |||
3295 | /* Jun 20. 2000: NC | ||
3296 | * IP addresses are not used in the API mode */ | ||
3297 | |||
3298 | if ((chdlc_priv_area->ip_local_tmp != chdlc_priv_area->ip_local || | ||
3299 | chdlc_priv_area->ip_remote_tmp != chdlc_priv_area->ip_remote) && | ||
3300 | card->u.c.usedby == WANPIPE) { | ||
3301 | |||
3302 | /* The IP addersses have changed, we must | ||
3303 | * stop the communications and reconfigure | ||
3304 | * the card. Reason: the firmware must know | ||
3305 | * the local and remote IP addresses. */ | ||
3306 | disable_comm(card); | ||
3307 | port_set_state(card, WAN_DISCONNECTED); | ||
3308 | printk(KERN_INFO | ||
3309 | "%s: IP addresses changed!\n", | ||
3310 | card->devname); | ||
3311 | printk(KERN_INFO | ||
3312 | "%s: Restarting communications ...\n", | ||
3313 | card->devname); | ||
3314 | }else{ | ||
3315 | /* IP addresses are the same and the link is up, | ||
3316 | * we don't have to do anything here. Therefore, exit */ | ||
3317 | return 0; | ||
3318 | } | ||
3319 | } | ||
3320 | |||
3321 | chdlc_priv_area->ip_local = chdlc_priv_area->ip_local_tmp; | ||
3322 | chdlc_priv_area->ip_remote = chdlc_priv_area->ip_remote_tmp; | ||
3323 | |||
3324 | |||
3325 | /* Setup the Board for asynchronous mode */ | ||
3326 | if (card->u.c.async_mode){ | ||
3327 | |||
3328 | if (set_asy_config(card)) { | ||
3329 | printk (KERN_INFO "%s: Failed CHDLC Async configuration!\n", | ||
3330 | card->devname); | ||
3331 | return 0; | ||
3332 | } | ||
3333 | }else{ | ||
3334 | /* Setup the Board for CHDLC */ | ||
3335 | if (set_chdlc_config(card)) { | ||
3336 | printk (KERN_INFO "%s: Failed CHDLC configuration!\n", | ||
3337 | card->devname); | ||
3338 | return 0; | ||
3339 | } | ||
3340 | } | ||
3341 | |||
3342 | /* Set interrupt mode and mask */ | ||
3343 | if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME | | ||
3344 | APP_INT_ON_GLOBAL_EXCEP_COND | | ||
3345 | APP_INT_ON_TX_FRAME | | ||
3346 | APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){ | ||
3347 | printk (KERN_INFO "%s: Failed to set interrupt triggers!\n", | ||
3348 | card->devname); | ||
3349 | return 0; | ||
3350 | } | ||
3351 | |||
3352 | |||
3353 | /* Mask the Transmit and Timer interrupt */ | ||
3354 | flags->interrupt_info_struct.interrupt_permission &= | ||
3355 | ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER); | ||
3356 | |||
3357 | /* In TTY mode, receive interrupt will be enabled during | ||
3358 | * wanpipe_tty_open() operation */ | ||
3359 | if (card->tty_opt){ | ||
3360 | flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_RX_FRAME; | ||
3361 | } | ||
3362 | |||
3363 | /* Enable communications */ | ||
3364 | if (card->u.c.async_mode){ | ||
3365 | if (asy_comm_enable(card) != 0) { | ||
3366 | printk(KERN_INFO "%s: Failed to enable async commnunication!\n", | ||
3367 | card->devname); | ||
3368 | flags->interrupt_info_struct.interrupt_permission = 0; | ||
3369 | card->u.c.comm_enabled=0; | ||
3370 | chdlc_set_intr_mode(card,0); | ||
3371 | return 0; | ||
3372 | } | ||
3373 | }else{ | ||
3374 | if (chdlc_comm_enable(card) != 0) { | ||
3375 | printk(KERN_INFO "%s: Failed to enable chdlc communications!\n", | ||
3376 | card->devname); | ||
3377 | flags->interrupt_info_struct.interrupt_permission = 0; | ||
3378 | card->u.c.comm_enabled=0; | ||
3379 | chdlc_set_intr_mode(card,0); | ||
3380 | return 0; | ||
3381 | } | ||
3382 | } | ||
3383 | |||
3384 | /* Initialize Rx/Tx buffer control fields */ | ||
3385 | init_chdlc_tx_rx_buff(card); | ||
3386 | port_set_state(card, WAN_CONNECTING); | ||
3387 | return 0; | ||
3388 | } | ||
3389 | |||
3390 | |||
3391 | /*============================================================ | ||
3392 | * chdlc_poll | ||
3393 | * | ||
3394 | * Rationale: | ||
3395 | * We cannot manipulate the routing tables, or | ||
3396 | * ip addresses withing the interrupt. Therefore | ||
3397 | * we must perform such actons outside an interrupt | ||
3398 | * at a later time. | ||
3399 | * | ||
3400 | * Description: | ||
3401 | * CHDLC polling routine, responsible for | ||
3402 | * shutting down interfaces upon disconnect | ||
3403 | * and adding/removing routes. | ||
3404 | * | ||
3405 | * Usage: | ||
3406 | * This function is executed for each CHDLC | ||
3407 | * interface through a tq_schedule bottom half. | ||
3408 | * | ||
3409 | * trigger_chdlc_poll() function is used to kick | ||
3410 | * the chldc_poll routine. | ||
3411 | */ | ||
3412 | |||
3413 | static void chdlc_poll(struct net_device *dev) | ||
3414 | { | ||
3415 | chdlc_private_area_t *chdlc_priv_area; | ||
3416 | sdla_t *card; | ||
3417 | u8 check_gateway=0; | ||
3418 | SHARED_MEMORY_INFO_STRUCT* flags; | ||
3419 | |||
3420 | |||
3421 | if (!dev || (chdlc_priv_area=dev->priv) == NULL) | ||
3422 | return; | ||
3423 | |||
3424 | card = chdlc_priv_area->card; | ||
3425 | flags = card->u.c.flags; | ||
3426 | |||
3427 | /* (Re)Configuraiton is in progress, stop what you are | ||
3428 | * doing and get out */ | ||
3429 | if (test_bit(PERI_CRIT,&card->wandev.critical)){ | ||
3430 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3431 | return; | ||
3432 | } | ||
3433 | |||
3434 | /* if_open() function has triggered the polling routine | ||
3435 | * to determine the configured IP addresses. Once the | ||
3436 | * addresses are found, trigger the chdlc configuration */ | ||
3437 | if (test_bit(0,&chdlc_priv_area->config_chdlc)){ | ||
3438 | |||
3439 | chdlc_priv_area->ip_local_tmp = get_ip_address(dev,WAN_LOCAL_IP); | ||
3440 | chdlc_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP); | ||
3441 | |||
3442 | /* Jun 20. 2000 Bug Fix | ||
3443 | * Only perform this check in WANPIPE mode, since | ||
3444 | * IP addresses are not used in the API mode. */ | ||
3445 | |||
3446 | if (chdlc_priv_area->ip_local_tmp == chdlc_priv_area->ip_remote_tmp && | ||
3447 | card->u.c.slarp_timer == 0x00 && | ||
3448 | !card->u.c.backup && | ||
3449 | card->u.c.usedby == WANPIPE){ | ||
3450 | |||
3451 | if (++chdlc_priv_area->ip_error > MAX_IP_ERRORS){ | ||
3452 | printk(KERN_INFO "\n%s: --- WARNING ---\n", | ||
3453 | card->devname); | ||
3454 | printk(KERN_INFO | ||
3455 | "%s: The local IP address is the same as the\n", | ||
3456 | card->devname); | ||
3457 | printk(KERN_INFO | ||
3458 | "%s: Point-to-Point IP address.\n", | ||
3459 | card->devname); | ||
3460 | printk(KERN_INFO "%s: --- WARNING ---\n\n", | ||
3461 | card->devname); | ||
3462 | }else{ | ||
3463 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3464 | chdlc_priv_area->poll_delay_timer.expires = jiffies+HZ; | ||
3465 | add_timer(&chdlc_priv_area->poll_delay_timer); | ||
3466 | return; | ||
3467 | } | ||
3468 | } | ||
3469 | |||
3470 | clear_bit(0,&chdlc_priv_area->config_chdlc); | ||
3471 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3472 | |||
3473 | chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG; | ||
3474 | flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER; | ||
3475 | return; | ||
3476 | } | ||
3477 | /* Dynamic interface implementation, as well as dynamic | ||
3478 | * routing. */ | ||
3479 | |||
3480 | switch (card->u.c.state){ | ||
3481 | |||
3482 | case WAN_DISCONNECTED: | ||
3483 | |||
3484 | /* If the dynamic interface configuration is on, and interface | ||
3485 | * is up, then bring down the netowrk interface */ | ||
3486 | |||
3487 | if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) && | ||
3488 | !test_bit(DEV_DOWN, &chdlc_priv_area->interface_down) && | ||
3489 | card->wandev.dev->flags & IFF_UP){ | ||
3490 | |||
3491 | printk(KERN_INFO "%s: Interface %s down.\n", | ||
3492 | card->devname,card->wandev.dev->name); | ||
3493 | change_dev_flags(card->wandev.dev,(card->wandev.dev->flags&~IFF_UP)); | ||
3494 | set_bit(DEV_DOWN,&chdlc_priv_area->interface_down); | ||
3495 | chdlc_priv_area->route_status = NO_ROUTE; | ||
3496 | |||
3497 | }else{ | ||
3498 | /* We need to check if the local IP address is | ||
3499 | * zero. If it is, we shouldn't try to remove it. | ||
3500 | */ | ||
3501 | |||
3502 | if (card->wandev.dev->flags & IFF_UP && | ||
3503 | get_ip_address(card->wandev.dev,WAN_LOCAL_IP) && | ||
3504 | chdlc_priv_area->route_status != NO_ROUTE && | ||
3505 | card->u.c.slarp_timer){ | ||
3506 | |||
3507 | process_route(card); | ||
3508 | } | ||
3509 | } | ||
3510 | break; | ||
3511 | |||
3512 | case WAN_CONNECTED: | ||
3513 | |||
3514 | /* In SMP machine this code can execute before the interface | ||
3515 | * comes up. In this case, we must make sure that we do not | ||
3516 | * try to bring up the interface before dev_open() is finished */ | ||
3517 | |||
3518 | |||
3519 | /* DEV_DOWN will be set only when we bring down the interface | ||
3520 | * for the very first time. This way we know that it was us | ||
3521 | * that brought the interface down */ | ||
3522 | |||
3523 | if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) && | ||
3524 | test_bit(DEV_DOWN, &chdlc_priv_area->interface_down) && | ||
3525 | !(card->wandev.dev->flags & IFF_UP)){ | ||
3526 | |||
3527 | printk(KERN_INFO "%s: Interface %s up.\n", | ||
3528 | card->devname,card->wandev.dev->name); | ||
3529 | change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP)); | ||
3530 | clear_bit(DEV_DOWN,&chdlc_priv_area->interface_down); | ||
3531 | check_gateway=1; | ||
3532 | } | ||
3533 | |||
3534 | if (chdlc_priv_area->route_status == ADD_ROUTE && | ||
3535 | card->u.c.slarp_timer){ | ||
3536 | |||
3537 | process_route(card); | ||
3538 | check_gateway=1; | ||
3539 | } | ||
3540 | |||
3541 | if (chdlc_priv_area->gateway && check_gateway) | ||
3542 | add_gateway(card,dev); | ||
3543 | |||
3544 | break; | ||
3545 | } | ||
3546 | |||
3547 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3548 | } | ||
3549 | |||
3550 | /*============================================================ | ||
3551 | * trigger_chdlc_poll | ||
3552 | * | ||
3553 | * Description: | ||
3554 | * Add a chdlc_poll() work entry into the keventd work queue | ||
3555 | * for a specific dlci/interface. This will kick | ||
3556 | * the fr_poll() routine at a later time. | ||
3557 | * | ||
3558 | * Usage: | ||
3559 | * Interrupts use this to defer a taks to | ||
3560 | * a polling routine. | ||
3561 | * | ||
3562 | */ | ||
3563 | static void trigger_chdlc_poll(struct net_device *dev) | ||
3564 | { | ||
3565 | chdlc_private_area_t *chdlc_priv_area; | ||
3566 | sdla_t *card; | ||
3567 | |||
3568 | if (!dev) | ||
3569 | return; | ||
3570 | |||
3571 | if ((chdlc_priv_area = dev->priv)==NULL) | ||
3572 | return; | ||
3573 | |||
3574 | card = chdlc_priv_area->card; | ||
3575 | |||
3576 | if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){ | ||
3577 | return; | ||
3578 | } | ||
3579 | if (test_bit(PERI_CRIT,&card->wandev.critical)){ | ||
3580 | return; | ||
3581 | } | ||
3582 | schedule_work(&chdlc_priv_area->poll_work); | ||
3583 | } | ||
3584 | |||
3585 | |||
3586 | static void chdlc_poll_delay (unsigned long dev_ptr) | ||
3587 | { | ||
3588 | struct net_device *dev = (struct net_device *)dev_ptr; | ||
3589 | trigger_chdlc_poll(dev); | ||
3590 | } | ||
3591 | |||
3592 | |||
3593 | void s508_lock (sdla_t *card, unsigned long *smp_flags) | ||
3594 | { | ||
3595 | spin_lock_irqsave(&card->wandev.lock, *smp_flags); | ||
3596 | if (card->next){ | ||
3597 | spin_lock(&card->next->wandev.lock); | ||
3598 | } | ||
3599 | } | ||
3600 | |||
3601 | void s508_unlock (sdla_t *card, unsigned long *smp_flags) | ||
3602 | { | ||
3603 | if (card->next){ | ||
3604 | spin_unlock(&card->next->wandev.lock); | ||
3605 | } | ||
3606 | spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); | ||
3607 | } | ||
3608 | |||
3609 | //*********** TTY SECTION **************** | ||
3610 | |||
3611 | static void wanpipe_tty_trigger_tx_irq(sdla_t *card) | ||
3612 | { | ||
3613 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
3614 | INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct; | ||
3615 | chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME; | ||
3616 | } | ||
3617 | |||
3618 | static void wanpipe_tty_trigger_poll(sdla_t *card) | ||
3619 | { | ||
3620 | schedule_work(&card->tty_work); | ||
3621 | } | ||
3622 | |||
3623 | static void tty_poll_work (void* data) | ||
3624 | { | ||
3625 | sdla_t *card = (sdla_t*)data; | ||
3626 | struct tty_struct *tty; | ||
3627 | |||
3628 | if ((tty=card->tty)==NULL) | ||
3629 | return; | ||
3630 | |||
3631 | tty_wakeup(tty); | ||
3632 | #if defined(SERIAL_HAVE_POLL_WAIT) | ||
3633 | wake_up_interruptible(&tty->poll_wait); | ||
3634 | #endif | ||
3635 | return; | ||
3636 | } | ||
3637 | |||
3638 | static void wanpipe_tty_close(struct tty_struct *tty, struct file * filp) | ||
3639 | { | ||
3640 | sdla_t *card; | ||
3641 | unsigned long smp_flags; | ||
3642 | |||
3643 | if (!tty || !tty->driver_data){ | ||
3644 | return; | ||
3645 | } | ||
3646 | |||
3647 | card = (sdla_t*)tty->driver_data; | ||
3648 | |||
3649 | if (!card) | ||
3650 | return; | ||
3651 | |||
3652 | printk(KERN_INFO "%s: Closing TTY Driver!\n", | ||
3653 | card->devname); | ||
3654 | |||
3655 | /* Sanity Check */ | ||
3656 | if (!card->tty_open) | ||
3657 | return; | ||
3658 | |||
3659 | wanpipe_close(card); | ||
3660 | if (--card->tty_open == 0){ | ||
3661 | |||
3662 | lock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
3663 | card->tty=NULL; | ||
3664 | chdlc_disable_comm_shutdown(card); | ||
3665 | unlock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
3666 | |||
3667 | kfree(card->tty_buf); | ||
3668 | card->tty_buf = NULL; | ||
3669 | kfree(card->tty_rx); | ||
3670 | card->tty_rx = NULL; | ||
3671 | } | ||
3672 | return; | ||
3673 | } | ||
3674 | static int wanpipe_tty_open(struct tty_struct *tty, struct file * filp) | ||
3675 | { | ||
3676 | unsigned long smp_flags; | ||
3677 | sdla_t *card; | ||
3678 | |||
3679 | if (!tty){ | ||
3680 | return -ENODEV; | ||
3681 | } | ||
3682 | |||
3683 | if (!tty->driver_data){ | ||
3684 | int port; | ||
3685 | port = tty->index; | ||
3686 | if ((port < 0) || (port >= NR_PORTS)) | ||
3687 | return -ENODEV; | ||
3688 | |||
3689 | tty->driver_data = WAN_CARD(port); | ||
3690 | if (!tty->driver_data) | ||
3691 | return -ENODEV; | ||
3692 | } | ||
3693 | |||
3694 | card = (sdla_t*)tty->driver_data; | ||
3695 | |||
3696 | if (!card){ | ||
3697 | lock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
3698 | card->tty=NULL; | ||
3699 | unlock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
3700 | return -ENODEV; | ||
3701 | } | ||
3702 | |||
3703 | printk(KERN_INFO "%s: Opening TTY Driver!\n", | ||
3704 | card->devname); | ||
3705 | |||
3706 | if (card->tty_open == 0){ | ||
3707 | lock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
3708 | card->tty=tty; | ||
3709 | unlock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
3710 | |||
3711 | if (!card->tty_buf){ | ||
3712 | card->tty_buf = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL); | ||
3713 | if (!card->tty_buf){ | ||
3714 | card->tty_buf=NULL; | ||
3715 | card->tty=NULL; | ||
3716 | return -ENOMEM; | ||
3717 | } | ||
3718 | } | ||
3719 | |||
3720 | if (!card->tty_rx){ | ||
3721 | card->tty_rx = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL); | ||
3722 | if (!card->tty_rx){ | ||
3723 | /* Free the buffer above */ | ||
3724 | kfree(card->tty_buf); | ||
3725 | card->tty_buf=NULL; | ||
3726 | card->tty=NULL; | ||
3727 | return -ENOMEM; | ||
3728 | } | ||
3729 | } | ||
3730 | } | ||
3731 | |||
3732 | ++card->tty_open; | ||
3733 | wanpipe_open(card); | ||
3734 | return 0; | ||
3735 | } | ||
3736 | |||
3737 | static int wanpipe_tty_write(struct tty_struct * tty, const unsigned char *buf, int count) | ||
3738 | { | ||
3739 | unsigned long smp_flags=0; | ||
3740 | sdla_t *card=NULL; | ||
3741 | |||
3742 | if (!tty){ | ||
3743 | dbg_printk(KERN_INFO "NO TTY in Write\n"); | ||
3744 | return -ENODEV; | ||
3745 | } | ||
3746 | |||
3747 | card = (sdla_t *)tty->driver_data; | ||
3748 | |||
3749 | if (!card){ | ||
3750 | dbg_printk(KERN_INFO "No Card in TTY Write\n"); | ||
3751 | return -ENODEV; | ||
3752 | } | ||
3753 | |||
3754 | if (count > card->wandev.mtu){ | ||
3755 | dbg_printk(KERN_INFO "Frame too big in Write %i Max: %i\n", | ||
3756 | count,card->wandev.mtu); | ||
3757 | return -EINVAL; | ||
3758 | } | ||
3759 | |||
3760 | if (card->wandev.state != WAN_CONNECTED){ | ||
3761 | dbg_printk(KERN_INFO "Card not connected in TTY Write\n"); | ||
3762 | return -EINVAL; | ||
3763 | } | ||
3764 | |||
3765 | /* Lock the 508 Card: SMP is supported */ | ||
3766 | if(card->hw.type != SDLA_S514){ | ||
3767 | s508_lock(card,&smp_flags); | ||
3768 | } | ||
3769 | |||
3770 | if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){ | ||
3771 | printk(KERN_INFO "%s: Critical in TTY Write\n", | ||
3772 | card->devname); | ||
3773 | |||
3774 | /* Lock the 508 Card: SMP is supported */ | ||
3775 | if(card->hw.type != SDLA_S514) | ||
3776 | s508_unlock(card,&smp_flags); | ||
3777 | |||
3778 | return -EINVAL; | ||
3779 | } | ||
3780 | |||
3781 | if (chdlc_send(card,(void*)buf,count)){ | ||
3782 | dbg_printk(KERN_INFO "%s: Failed to send, retry later: kernel!\n", | ||
3783 | card->devname); | ||
3784 | clear_bit(SEND_CRIT,(void*)&card->wandev.critical); | ||
3785 | |||
3786 | wanpipe_tty_trigger_tx_irq(card); | ||
3787 | |||
3788 | if(card->hw.type != SDLA_S514) | ||
3789 | s508_unlock(card,&smp_flags); | ||
3790 | return 0; | ||
3791 | } | ||
3792 | dbg_printk(KERN_INFO "%s: Packet sent OK: %i\n",card->devname,count); | ||
3793 | clear_bit(SEND_CRIT,(void*)&card->wandev.critical); | ||
3794 | |||
3795 | if(card->hw.type != SDLA_S514) | ||
3796 | s508_unlock(card,&smp_flags); | ||
3797 | |||
3798 | return count; | ||
3799 | } | ||
3800 | |||
3801 | static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len) | ||
3802 | { | ||
3803 | unsigned offset=0; | ||
3804 | unsigned olen=len; | ||
3805 | char fp=0; | ||
3806 | struct tty_struct *tty; | ||
3807 | int i; | ||
3808 | struct tty_ldisc *ld; | ||
3809 | |||
3810 | if (!card->tty_open){ | ||
3811 | dbg_printk(KERN_INFO "%s: TTY not open during receive\n", | ||
3812 | card->devname); | ||
3813 | return; | ||
3814 | } | ||
3815 | |||
3816 | if ((tty=card->tty) == NULL){ | ||
3817 | dbg_printk(KERN_INFO "%s: No TTY on receive\n", | ||
3818 | card->devname); | ||
3819 | return; | ||
3820 | } | ||
3821 | |||
3822 | if (!tty->driver_data){ | ||
3823 | dbg_printk(KERN_INFO "%s: No Driver Data, or Flip on receive\n", | ||
3824 | card->devname); | ||
3825 | return; | ||
3826 | } | ||
3827 | |||
3828 | |||
3829 | if (card->u.c.async_mode){ | ||
3830 | if ((tty->flip.count+len) >= TTY_FLIPBUF_SIZE){ | ||
3831 | if (net_ratelimit()){ | ||
3832 | printk(KERN_INFO | ||
3833 | "%s: Received packet size too big: %i bytes, Max: %i!\n", | ||
3834 | card->devname,len,TTY_FLIPBUF_SIZE); | ||
3835 | } | ||
3836 | return; | ||
3837 | } | ||
3838 | |||
3839 | |||
3840 | if((addr + len) > card->u.c.rx_top + 1) { | ||
3841 | offset = card->u.c.rx_top - addr + 1; | ||
3842 | |||
3843 | sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, offset); | ||
3844 | |||
3845 | addr = card->u.c.rx_base; | ||
3846 | len -= offset; | ||
3847 | |||
3848 | tty->flip.char_buf_ptr+=offset; | ||
3849 | tty->flip.count+=offset; | ||
3850 | for (i=0;i<offset;i++){ | ||
3851 | *tty->flip.flag_buf_ptr = 0; | ||
3852 | tty->flip.flag_buf_ptr++; | ||
3853 | } | ||
3854 | } | ||
3855 | |||
3856 | sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, len); | ||
3857 | |||
3858 | tty->flip.char_buf_ptr+=len; | ||
3859 | card->tty->flip.count+=len; | ||
3860 | for (i=0;i<len;i++){ | ||
3861 | *tty->flip.flag_buf_ptr = 0; | ||
3862 | tty->flip.flag_buf_ptr++; | ||
3863 | } | ||
3864 | |||
3865 | tty->low_latency=1; | ||
3866 | tty_flip_buffer_push(tty); | ||
3867 | }else{ | ||
3868 | if (!card->tty_rx){ | ||
3869 | if (net_ratelimit()){ | ||
3870 | printk(KERN_INFO | ||
3871 | "%s: Receive sync buffer not available!\n", | ||
3872 | card->devname); | ||
3873 | } | ||
3874 | return; | ||
3875 | } | ||
3876 | |||
3877 | if (len > TTY_CHDLC_MAX_MTU){ | ||
3878 | if (net_ratelimit()){ | ||
3879 | printk(KERN_INFO | ||
3880 | "%s: Received packet size too big: %i bytes, Max: %i!\n", | ||
3881 | card->devname,len,TTY_FLIPBUF_SIZE); | ||
3882 | } | ||
3883 | return; | ||
3884 | } | ||
3885 | |||
3886 | |||
3887 | if((addr + len) > card->u.c.rx_top + 1) { | ||
3888 | offset = card->u.c.rx_top - addr + 1; | ||
3889 | |||
3890 | sdla_peek(&card->hw, addr, card->tty_rx, offset); | ||
3891 | |||
3892 | addr = card->u.c.rx_base; | ||
3893 | len -= offset; | ||
3894 | } | ||
3895 | sdla_peek(&card->hw, addr, card->tty_rx+offset, len); | ||
3896 | ld = tty_ldisc_ref(tty); | ||
3897 | if (ld) { | ||
3898 | if (ld->receive_buf) | ||
3899 | ld->receive_buf(tty,card->tty_rx,&fp,olen); | ||
3900 | tty_ldisc_deref(ld); | ||
3901 | }else{ | ||
3902 | if (net_ratelimit()){ | ||
3903 | printk(KERN_INFO | ||
3904 | "%s: NO TTY Sync line discipline!\n", | ||
3905 | card->devname); | ||
3906 | } | ||
3907 | } | ||
3908 | } | ||
3909 | |||
3910 | dbg_printk(KERN_INFO "%s: Received Data %i\n",card->devname,olen); | ||
3911 | return; | ||
3912 | } | ||
3913 | |||
3914 | #if 0 | ||
3915 | static int wanpipe_tty_ioctl(struct tty_struct *tty, struct file * file, | ||
3916 | unsigned int cmd, unsigned long arg) | ||
3917 | { | ||
3918 | return -ENOIOCTLCMD; | ||
3919 | } | ||
3920 | #endif | ||
3921 | |||
3922 | static void wanpipe_tty_stop(struct tty_struct *tty) | ||
3923 | { | ||
3924 | return; | ||
3925 | } | ||
3926 | |||
3927 | static void wanpipe_tty_start(struct tty_struct *tty) | ||
3928 | { | ||
3929 | return; | ||
3930 | } | ||
3931 | |||
3932 | static int config_tty (sdla_t *card) | ||
3933 | { | ||
3934 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
3935 | |||
3936 | /* Setup the Board for asynchronous mode */ | ||
3937 | if (card->u.c.async_mode){ | ||
3938 | |||
3939 | if (set_asy_config(card)) { | ||
3940 | printk (KERN_INFO "%s: Failed CHDLC Async configuration!\n", | ||
3941 | card->devname); | ||
3942 | return -EINVAL; | ||
3943 | } | ||
3944 | }else{ | ||
3945 | /* Setup the Board for CHDLC */ | ||
3946 | if (set_chdlc_config(card)) { | ||
3947 | printk (KERN_INFO "%s: Failed CHDLC configuration!\n", | ||
3948 | card->devname); | ||
3949 | return -EINVAL; | ||
3950 | } | ||
3951 | } | ||
3952 | |||
3953 | /* Set interrupt mode and mask */ | ||
3954 | if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME | | ||
3955 | APP_INT_ON_GLOBAL_EXCEP_COND | | ||
3956 | APP_INT_ON_TX_FRAME | | ||
3957 | APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){ | ||
3958 | printk (KERN_INFO "%s: Failed to set interrupt triggers!\n", | ||
3959 | card->devname); | ||
3960 | return -EINVAL; | ||
3961 | } | ||
3962 | |||
3963 | |||
3964 | /* Mask the Transmit and Timer interrupt */ | ||
3965 | flags->interrupt_info_struct.interrupt_permission &= | ||
3966 | ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER); | ||
3967 | |||
3968 | |||
3969 | /* Enable communications */ | ||
3970 | if (card->u.c.async_mode){ | ||
3971 | if (asy_comm_enable(card) != 0) { | ||
3972 | printk(KERN_INFO "%s: Failed to enable async commnunication!\n", | ||
3973 | card->devname); | ||
3974 | flags->interrupt_info_struct.interrupt_permission = 0; | ||
3975 | card->u.c.comm_enabled=0; | ||
3976 | chdlc_set_intr_mode(card,0); | ||
3977 | return -EINVAL; | ||
3978 | } | ||
3979 | }else{ | ||
3980 | if (chdlc_comm_enable(card) != 0) { | ||
3981 | printk(KERN_INFO "%s: Failed to enable chdlc communications!\n", | ||
3982 | card->devname); | ||
3983 | flags->interrupt_info_struct.interrupt_permission = 0; | ||
3984 | card->u.c.comm_enabled=0; | ||
3985 | chdlc_set_intr_mode(card,0); | ||
3986 | return -EINVAL; | ||
3987 | } | ||
3988 | } | ||
3989 | |||
3990 | /* Initialize Rx/Tx buffer control fields */ | ||
3991 | init_chdlc_tx_rx_buff(card); | ||
3992 | port_set_state(card, WAN_CONNECTING); | ||
3993 | return 0; | ||
3994 | } | ||
3995 | |||
3996 | |||
3997 | static int change_speed(sdla_t *card, struct tty_struct *tty, | ||
3998 | struct termios *old_termios) | ||
3999 | { | ||
4000 | int baud, ret=0; | ||
4001 | unsigned cflag; | ||
4002 | int dbits,sbits,parity,handshaking; | ||
4003 | |||
4004 | cflag = tty->termios->c_cflag; | ||
4005 | |||
4006 | /* There is always one stop bit */ | ||
4007 | sbits=WANOPT_ONE; | ||
4008 | |||
4009 | /* Parity is defaulted to NONE */ | ||
4010 | parity = WANOPT_NONE; | ||
4011 | |||
4012 | handshaking=0; | ||
4013 | |||
4014 | /* byte size and parity */ | ||
4015 | switch (cflag & CSIZE) { | ||
4016 | case CS5: dbits = 5; break; | ||
4017 | case CS6: dbits = 6; break; | ||
4018 | case CS7: dbits = 7; break; | ||
4019 | case CS8: dbits = 8; break; | ||
4020 | /* Never happens, but GCC is too dumb to figure it out */ | ||
4021 | default: dbits = 8; break; | ||
4022 | } | ||
4023 | |||
4024 | /* One more stop bit should be supported, thus increment | ||
4025 | * the number of stop bits Max=2 */ | ||
4026 | if (cflag & CSTOPB) { | ||
4027 | sbits = WANOPT_TWO; | ||
4028 | } | ||
4029 | if (cflag & PARENB) { | ||
4030 | parity = WANOPT_EVEN; | ||
4031 | } | ||
4032 | if (cflag & PARODD){ | ||
4033 | parity = WANOPT_ODD; | ||
4034 | } | ||
4035 | |||
4036 | /* Determine divisor based on baud rate */ | ||
4037 | baud = tty_get_baud_rate(tty); | ||
4038 | |||
4039 | if (!baud) | ||
4040 | baud = 9600; /* B0 transition handled in rs_set_termios */ | ||
4041 | |||
4042 | if (cflag & CRTSCTS) { | ||
4043 | handshaking|=ASY_RTS_HS_FOR_RX; | ||
4044 | } | ||
4045 | |||
4046 | if (I_IGNPAR(tty)) | ||
4047 | parity = WANOPT_NONE; | ||
4048 | |||
4049 | if (I_IXOFF(tty)){ | ||
4050 | handshaking|=ASY_XON_XOFF_HS_FOR_RX; | ||
4051 | handshaking|=ASY_XON_XOFF_HS_FOR_TX; | ||
4052 | } | ||
4053 | |||
4054 | if (I_IXON(tty)){ | ||
4055 | handshaking|=ASY_XON_XOFF_HS_FOR_RX; | ||
4056 | handshaking|=ASY_XON_XOFF_HS_FOR_TX; | ||
4057 | } | ||
4058 | |||
4059 | if (card->u.c.async_mode){ | ||
4060 | if (card->wandev.bps != baud) | ||
4061 | ret=1; | ||
4062 | card->wandev.bps = baud; | ||
4063 | } | ||
4064 | |||
4065 | if (card->u.c.async_mode){ | ||
4066 | if (card->u.c.protocol_options != handshaking) | ||
4067 | ret=1; | ||
4068 | card->u.c.protocol_options = handshaking; | ||
4069 | |||
4070 | if (card->u.c.tx_bits_per_char != dbits) | ||
4071 | ret=1; | ||
4072 | card->u.c.tx_bits_per_char = dbits; | ||
4073 | |||
4074 | if (card->u.c.rx_bits_per_char != dbits) | ||
4075 | ret=1; | ||
4076 | card->u.c.rx_bits_per_char = dbits; | ||
4077 | |||
4078 | if (card->u.c.stop_bits != sbits) | ||
4079 | ret=1; | ||
4080 | card->u.c.stop_bits = sbits; | ||
4081 | |||
4082 | if (card->u.c.parity != parity) | ||
4083 | ret=1; | ||
4084 | card->u.c.parity = parity; | ||
4085 | |||
4086 | card->u.c.break_timer = 50; | ||
4087 | card->u.c.inter_char_timer = 10; | ||
4088 | card->u.c.rx_complete_length = 100; | ||
4089 | card->u.c.xon_char = 0xFE; | ||
4090 | }else{ | ||
4091 | card->u.c.protocol_options = HDLC_STREAMING_MODE; | ||
4092 | } | ||
4093 | |||
4094 | return ret; | ||
4095 | } | ||
4096 | |||
4097 | |||
4098 | static void wanpipe_tty_set_termios(struct tty_struct *tty, struct termios *old_termios) | ||
4099 | { | ||
4100 | sdla_t *card; | ||
4101 | int err=1; | ||
4102 | |||
4103 | if (!tty){ | ||
4104 | return; | ||
4105 | } | ||
4106 | |||
4107 | card = (sdla_t *)tty->driver_data; | ||
4108 | |||
4109 | if (!card) | ||
4110 | return; | ||
4111 | |||
4112 | if (change_speed(card, tty, old_termios) || !card->u.c.comm_enabled){ | ||
4113 | unsigned long smp_flags; | ||
4114 | |||
4115 | if (card->u.c.comm_enabled){ | ||
4116 | lock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
4117 | chdlc_disable_comm_shutdown(card); | ||
4118 | unlock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
4119 | } | ||
4120 | lock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
4121 | err = config_tty(card); | ||
4122 | unlock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
4123 | if (card->u.c.async_mode){ | ||
4124 | printk(KERN_INFO "%s: TTY Async Configuration:\n" | ||
4125 | " Baud =%i\n" | ||
4126 | " Handshaking =%s\n" | ||
4127 | " Tx Dbits =%i\n" | ||
4128 | " Rx Dbits =%i\n" | ||
4129 | " Parity =%s\n" | ||
4130 | " Stop Bits =%i\n", | ||
4131 | card->devname, | ||
4132 | card->wandev.bps, | ||
4133 | opt_decode[card->u.c.protocol_options], | ||
4134 | card->u.c.tx_bits_per_char, | ||
4135 | card->u.c.rx_bits_per_char, | ||
4136 | p_decode[card->u.c.parity] , | ||
4137 | card->u.c.stop_bits); | ||
4138 | }else{ | ||
4139 | printk(KERN_INFO "%s: TTY Sync Configuration:\n" | ||
4140 | " Baud =%i\n" | ||
4141 | " Protocol =HDLC_STREAMING\n", | ||
4142 | card->devname,card->wandev.bps); | ||
4143 | } | ||
4144 | if (!err){ | ||
4145 | port_set_state(card,WAN_CONNECTED); | ||
4146 | }else{ | ||
4147 | port_set_state(card,WAN_DISCONNECTED); | ||
4148 | } | ||
4149 | } | ||
4150 | return; | ||
4151 | } | ||
4152 | |||
4153 | static void wanpipe_tty_put_char(struct tty_struct *tty, unsigned char ch) | ||
4154 | { | ||
4155 | sdla_t *card; | ||
4156 | unsigned long smp_flags=0; | ||
4157 | |||
4158 | if (!tty){ | ||
4159 | return; | ||
4160 | } | ||
4161 | |||
4162 | card = (sdla_t *)tty->driver_data; | ||
4163 | |||
4164 | if (!card) | ||
4165 | return; | ||
4166 | |||
4167 | if (card->wandev.state != WAN_CONNECTED) | ||
4168 | return; | ||
4169 | |||
4170 | if(card->hw.type != SDLA_S514) | ||
4171 | s508_lock(card,&smp_flags); | ||
4172 | |||
4173 | if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){ | ||
4174 | |||
4175 | wanpipe_tty_trigger_tx_irq(card); | ||
4176 | |||
4177 | if(card->hw.type != SDLA_S514) | ||
4178 | s508_unlock(card,&smp_flags); | ||
4179 | return; | ||
4180 | } | ||
4181 | |||
4182 | if (chdlc_send(card,(void*)&ch,1)){ | ||
4183 | wanpipe_tty_trigger_tx_irq(card); | ||
4184 | dbg_printk("%s: Failed to TX char!\n",card->devname); | ||
4185 | } | ||
4186 | |||
4187 | dbg_printk("%s: Char TX OK\n",card->devname); | ||
4188 | |||
4189 | clear_bit(SEND_CRIT,(void*)&card->wandev.critical); | ||
4190 | |||
4191 | if(card->hw.type != SDLA_S514) | ||
4192 | s508_unlock(card,&smp_flags); | ||
4193 | |||
4194 | return; | ||
4195 | } | ||
4196 | |||
4197 | static void wanpipe_tty_flush_chars(struct tty_struct *tty) | ||
4198 | { | ||
4199 | return; | ||
4200 | } | ||
4201 | |||
4202 | static void wanpipe_tty_flush_buffer(struct tty_struct *tty) | ||
4203 | { | ||
4204 | if (!tty) | ||
4205 | return; | ||
4206 | |||
4207 | #if defined(SERIAL_HAVE_POLL_WAIT) | ||
4208 | wake_up_interruptible(&tty->poll_wait); | ||
4209 | #endif | ||
4210 | tty_wakeup(tty); | ||
4211 | return; | ||
4212 | } | ||
4213 | |||
4214 | /* | ||
4215 | * This function is used to send a high-priority XON/XOFF character to | ||
4216 | * the device | ||
4217 | */ | ||
4218 | static void wanpipe_tty_send_xchar(struct tty_struct *tty, char ch) | ||
4219 | { | ||
4220 | return; | ||
4221 | } | ||
4222 | |||
4223 | |||
4224 | static int wanpipe_tty_chars_in_buffer(struct tty_struct *tty) | ||
4225 | { | ||
4226 | return 0; | ||
4227 | } | ||
4228 | |||
4229 | |||
4230 | static int wanpipe_tty_write_room(struct tty_struct *tty) | ||
4231 | { | ||
4232 | sdla_t *card; | ||
4233 | |||
4234 | printk(KERN_INFO "TTY Write Room\n"); | ||
4235 | |||
4236 | if (!tty){ | ||
4237 | return 0; | ||
4238 | } | ||
4239 | |||
4240 | card = (sdla_t *)tty->driver_data; | ||
4241 | if (!card) | ||
4242 | return 0; | ||
4243 | |||
4244 | if (card->wandev.state != WAN_CONNECTED) | ||
4245 | return 0; | ||
4246 | |||
4247 | return SEC_MAX_NO_DATA_BYTES_IN_FRAME; | ||
4248 | } | ||
4249 | |||
4250 | |||
4251 | static int set_modem_status(sdla_t *card, unsigned char data) | ||
4252 | { | ||
4253 | CHDLC_MAILBOX_STRUCT *mb = card->mbox; | ||
4254 | int err; | ||
4255 | |||
4256 | mb->buffer_length=1; | ||
4257 | mb->command=SET_MODEM_STATUS; | ||
4258 | mb->data[0]=data; | ||
4259 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
4260 | if (err != COMMAND_OK) | ||
4261 | chdlc_error (card, err, mb); | ||
4262 | |||
4263 | return err; | ||
4264 | } | ||
4265 | |||
4266 | static void wanpipe_tty_hangup(struct tty_struct *tty) | ||
4267 | { | ||
4268 | sdla_t *card; | ||
4269 | unsigned long smp_flags; | ||
4270 | |||
4271 | printk(KERN_INFO "TTY Hangup!\n"); | ||
4272 | |||
4273 | if (!tty){ | ||
4274 | return; | ||
4275 | } | ||
4276 | |||
4277 | card = (sdla_t *)tty->driver_data; | ||
4278 | if (!card) | ||
4279 | return; | ||
4280 | |||
4281 | lock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
4282 | set_modem_status(card,0); | ||
4283 | unlock_adapter_irq(&card->wandev.lock,&smp_flags); | ||
4284 | return; | ||
4285 | } | ||
4286 | |||
4287 | static void wanpipe_tty_break(struct tty_struct *tty, int break_state) | ||
4288 | { | ||
4289 | return; | ||
4290 | } | ||
4291 | |||
4292 | static void wanpipe_tty_wait_until_sent(struct tty_struct *tty, int timeout) | ||
4293 | { | ||
4294 | return; | ||
4295 | } | ||
4296 | |||
4297 | static void wanpipe_tty_throttle(struct tty_struct * tty) | ||
4298 | { | ||
4299 | return; | ||
4300 | } | ||
4301 | |||
4302 | static void wanpipe_tty_unthrottle(struct tty_struct * tty) | ||
4303 | { | ||
4304 | return; | ||
4305 | } | ||
4306 | |||
4307 | int wanpipe_tty_read_proc(char *page, char **start, off_t off, int count, | ||
4308 | int *eof, void *data) | ||
4309 | { | ||
4310 | return 0; | ||
4311 | } | ||
4312 | |||
4313 | /* | ||
4314 | * The serial driver boot-time initialization code! | ||
4315 | */ | ||
4316 | int wanpipe_tty_init(sdla_t *card) | ||
4317 | { | ||
4318 | struct serial_state * state; | ||
4319 | |||
4320 | /* Initialize the tty_driver structure */ | ||
4321 | |||
4322 | if (card->tty_minor < 0 || card->tty_minor > NR_PORTS){ | ||
4323 | printk(KERN_INFO "%s: Illegal Minor TTY number (0-4): %i\n", | ||
4324 | card->devname,card->tty_minor); | ||
4325 | return -EINVAL; | ||
4326 | } | ||
4327 | |||
4328 | if (WAN_CARD(card->tty_minor)){ | ||
4329 | printk(KERN_INFO "%s: TTY Minor %i, already in use\n", | ||
4330 | card->devname,card->tty_minor); | ||
4331 | return -EBUSY; | ||
4332 | } | ||
4333 | |||
4334 | if (tty_init_cnt==0){ | ||
4335 | |||
4336 | printk(KERN_INFO "%s: TTY %s Driver Init: Major %i, Minor Range %i-%i\n", | ||
4337 | card->devname, | ||
4338 | card->u.c.async_mode ? "ASYNC" : "SYNC", | ||
4339 | WAN_TTY_MAJOR,MIN_PORT,MAX_PORT); | ||
4340 | |||
4341 | tty_driver_mode = card->u.c.async_mode; | ||
4342 | |||
4343 | memset(&serial_driver, 0, sizeof(struct tty_driver)); | ||
4344 | serial_driver.magic = TTY_DRIVER_MAGIC; | ||
4345 | serial_driver.owner = THIS_MODULE; | ||
4346 | serial_driver.driver_name = "wanpipe_tty"; | ||
4347 | serial_driver.name = "ttyW"; | ||
4348 | serial_driver.major = WAN_TTY_MAJOR; | ||
4349 | serial_driver.minor_start = WAN_TTY_MINOR; | ||
4350 | serial_driver.num = NR_PORTS; | ||
4351 | serial_driver.type = TTY_DRIVER_TYPE_SERIAL; | ||
4352 | serial_driver.subtype = SERIAL_TYPE_NORMAL; | ||
4353 | |||
4354 | serial_driver.init_termios = tty_std_termios; | ||
4355 | serial_driver.init_termios.c_cflag = | ||
4356 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
4357 | serial_driver.flags = TTY_DRIVER_REAL_RAW; | ||
4358 | |||
4359 | serial_driver.refcount = 1; /* !@!@^#^&!! */ | ||
4360 | |||
4361 | serial_driver.open = wanpipe_tty_open; | ||
4362 | serial_driver.close = wanpipe_tty_close; | ||
4363 | serial_driver.write = wanpipe_tty_write; | ||
4364 | |||
4365 | serial_driver.put_char = wanpipe_tty_put_char; | ||
4366 | serial_driver.flush_chars = wanpipe_tty_flush_chars; | ||
4367 | serial_driver.write_room = wanpipe_tty_write_room; | ||
4368 | serial_driver.chars_in_buffer = wanpipe_tty_chars_in_buffer; | ||
4369 | serial_driver.flush_buffer = wanpipe_tty_flush_buffer; | ||
4370 | //serial_driver.ioctl = wanpipe_tty_ioctl; | ||
4371 | serial_driver.throttle = wanpipe_tty_throttle; | ||
4372 | serial_driver.unthrottle = wanpipe_tty_unthrottle; | ||
4373 | serial_driver.send_xchar = wanpipe_tty_send_xchar; | ||
4374 | serial_driver.set_termios = wanpipe_tty_set_termios; | ||
4375 | serial_driver.stop = wanpipe_tty_stop; | ||
4376 | serial_driver.start = wanpipe_tty_start; | ||
4377 | serial_driver.hangup = wanpipe_tty_hangup; | ||
4378 | serial_driver.break_ctl = wanpipe_tty_break; | ||
4379 | serial_driver.wait_until_sent = wanpipe_tty_wait_until_sent; | ||
4380 | serial_driver.read_proc = wanpipe_tty_read_proc; | ||
4381 | |||
4382 | if (tty_register_driver(&serial_driver)){ | ||
4383 | printk(KERN_INFO "%s: Failed to register serial driver!\n", | ||
4384 | card->devname); | ||
4385 | } | ||
4386 | } | ||
4387 | |||
4388 | |||
4389 | /* The subsequent ports must comply to the initial configuration */ | ||
4390 | if (tty_driver_mode != card->u.c.async_mode){ | ||
4391 | printk(KERN_INFO "%s: Error: TTY Driver operation mode mismatch!\n", | ||
4392 | card->devname); | ||
4393 | printk(KERN_INFO "%s: The TTY driver is configured for %s!\n", | ||
4394 | card->devname, tty_driver_mode ? "ASYNC" : "SYNC"); | ||
4395 | return -EINVAL; | ||
4396 | } | ||
4397 | |||
4398 | tty_init_cnt++; | ||
4399 | |||
4400 | printk(KERN_INFO "%s: Initializing TTY %s Driver Minor %i\n", | ||
4401 | card->devname, | ||
4402 | tty_driver_mode ? "ASYNC" : "SYNC", | ||
4403 | card->tty_minor); | ||
4404 | |||
4405 | tty_card_map[card->tty_minor] = card; | ||
4406 | state = &rs_table[card->tty_minor]; | ||
4407 | |||
4408 | state->magic = SSTATE_MAGIC; | ||
4409 | state->line = 0; | ||
4410 | state->type = PORT_UNKNOWN; | ||
4411 | state->custom_divisor = 0; | ||
4412 | state->close_delay = 5*HZ/10; | ||
4413 | state->closing_wait = 30*HZ; | ||
4414 | state->icount.cts = state->icount.dsr = | ||
4415 | state->icount.rng = state->icount.dcd = 0; | ||
4416 | state->icount.rx = state->icount.tx = 0; | ||
4417 | state->icount.frame = state->icount.parity = 0; | ||
4418 | state->icount.overrun = state->icount.brk = 0; | ||
4419 | state->irq = card->wandev.irq; | ||
4420 | |||
4421 | INIT_WORK(&card->tty_work, tty_poll_work, (void*)card); | ||
4422 | return 0; | ||
4423 | } | ||
4424 | |||
4425 | |||
4426 | MODULE_LICENSE("GPL"); | ||
4427 | |||
4428 | /****** End ****************************************************************/ | ||
diff --git a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c deleted file mode 100644 index 7f1ce9d4333e..000000000000 --- a/drivers/net/wan/sdla_fr.c +++ /dev/null | |||
@@ -1,5061 +0,0 @@ | |||
1 | /***************************************************************************** | ||
2 | * sdla_fr.c WANPIPE(tm) Multiprotocol WAN Link Driver. Frame relay module. | ||
3 | * | ||
4 | * Author(s): Nenad Corbic <ncorbic@sangoma.com> | ||
5 | * Gideon Hack | ||
6 | * | ||
7 | * Copyright: (c) 1995-2001 Sangoma Technologies Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | * ============================================================================ | ||
14 | * Nov 23, 2000 Nenad Corbic o Added support for 2.4.X kernels | ||
15 | * Nov 15, 2000 David Rokavarg | ||
16 | * Nenad Corbic o Added frame relay bridging support. | ||
17 | * Original code from Mark Wells and Kristian Hoffmann has | ||
18 | * been integrated into the frame relay driver. | ||
19 | * Nov 13, 2000 Nenad Corbic o Added true interface type encoding option. | ||
20 | * Tcpdump doesn't support Frame Relay inteface | ||
21 | * types, to fix this true type option will set | ||
22 | * the interface type to RAW IP mode. | ||
23 | * Nov 07, 2000 Nenad Corbic o Added security features for UDP debugging: | ||
24 | * Deny all and specify allowed requests. | ||
25 | * Nov 06, 2000 Nenad Corbic o Wanpipe interfaces conform to raw packet interfaces. | ||
26 | * Moved the if_header into the if_send() routine. | ||
27 | * The if_header() was breaking the libpcap | ||
28 | * support. i.e. support for tcpdump, ethereal ... | ||
29 | * Oct 12. 2000 Nenad Corbic o Added error message in fr_configure | ||
30 | * Jul 31, 2000 Nenad Corbic o Fixed the Router UP Time. | ||
31 | * Apr 28, 2000 Nenad Corbic o Added the option to shutdown an interface | ||
32 | * when the channel gets disconnected. | ||
33 | * Apr 28, 2000 Nenad Corbic o Added M.Grants patch: disallow duplicate | ||
34 | * interface setups. | ||
35 | * Apr 25, 2000 Nenad Corbic o Added M.Grants patch: dynamically add/remove | ||
36 | * new dlcis/interfaces. | ||
37 | * Mar 23, 2000 Nenad Corbic o Improved task queue, bh handling. | ||
38 | * Mar 16, 2000 Nenad Corbic o Added Inverse ARP support | ||
39 | * Mar 13, 2000 Nenad Corbic o Added new socket API support. | ||
40 | * Mar 06, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery. | ||
41 | * Feb 24, 2000 Nenad Corbic o Fixed up FT1 UDP debugging problem. | ||
42 | * Dev 15, 1999 Nenad Corbic o Fixed up header files for 2.0.X kernels | ||
43 | * | ||
44 | * Nov 08, 1999 Nenad Corbic o Combined all debug UDP calls into one function | ||
45 | * o Removed the ARP support. This has to be done | ||
46 | * in the next version. | ||
47 | * o Only a Node can implement NO signalling. | ||
48 | * Initialize DLCI during if_open() if NO | ||
49 | * signalling. | ||
50 | * o Took out IPX support, implement in next | ||
51 | * version | ||
52 | * Sep 29, 1999 Nenad Corbic o Added SMP support and changed the update | ||
53 | * function to use timer interrupt. | ||
54 | * o Fixed the CIR bug: Set the value of BC | ||
55 | * to CIR when the CIR is enabled. | ||
56 | * o Updated comments, statistics and tracing. | ||
57 | * Jun 02, 1999 Gideon Hack o Updated for S514 support. | ||
58 | * Sep 18, 1998 Jaspreet Singh o Updated for 2.2.X kernels. | ||
59 | * Jul 31, 1998 Jaspreet Singh o Removed wpf_poll routine. The channel/DLCI | ||
60 | * status is received through an event interrupt. | ||
61 | * Jul 08, 1998 David Fong o Added inverse ARP support. | ||
62 | * Mar 26, 1997 Jaspreet Singh o Returning return codes for failed UDP cmds. | ||
63 | * Jan 28, 1997 Jaspreet Singh o Improved handling of inactive DLCIs. | ||
64 | * Dec 30, 1997 Jaspreet Singh o Replaced dev_tint() with mark_bh(NET_BH) | ||
65 | * Dec 16, 1997 Jaspreet Singh o Implemented Multiple IPX support. | ||
66 | * Nov 26, 1997 Jaspreet Singh o Improved load sharing with multiple boards | ||
67 | * o Added Cli() to protect enabling of interrupts | ||
68 | * while polling is called. | ||
69 | * Nov 24, 1997 Jaspreet Singh o Added counters to avoid enabling of interrupts | ||
70 | * when they have been disabled by another | ||
71 | * interface or routine (eg. wpf_poll). | ||
72 | * Nov 06, 1997 Jaspreet Singh o Added INTR_TEST_MODE to avoid polling | ||
73 | * routine disable interrupts during interrupt | ||
74 | * testing. | ||
75 | * Oct 20, 1997 Jaspreet Singh o Added hooks in for Router UP time. | ||
76 | * Oct 16, 1997 Jaspreet Singh o The critical flag is used to maintain flow | ||
77 | * control by avoiding RACE conditions. The | ||
78 | * cli() and restore_flags() are taken out. | ||
79 | * The fr_channel structure is appended for | ||
80 | * Driver Statistics. | ||
81 | * Oct 15, 1997 Farhan Thawar o updated if_send() and receive for IPX | ||
82 | * Aug 29, 1997 Farhan Thawar o Removed most of the cli() and sti() | ||
83 | * o Abstracted the UDP management stuff | ||
84 | * o Now use tbusy and critical more intelligently | ||
85 | * Jul 21, 1997 Jaspreet Singh o Can configure T391, T392, N391, N392 & N393 | ||
86 | * through router.conf. | ||
87 | * o Protected calls to sdla_peek() by adDing | ||
88 | * save_flags(), cli() and restore_flags(). | ||
89 | * o Added error message for Inactive DLCIs in | ||
90 | * fr_event() and update_chan_state(). | ||
91 | * o Fixed freeing up of buffers using kfree() | ||
92 | * when packets are received. | ||
93 | * Jul 07, 1997 Jaspreet Singh o Added configurable TTL for UDP packets | ||
94 | * o Added ability to discard multicast and | ||
95 | * broadcast source addressed packets | ||
96 | * Jun 27, 1997 Jaspreet Singh o Added FT1 monitor capabilities | ||
97 | * New case (0x44) statement in if_send routine | ||
98 | * Added a global variable rCount to keep track | ||
99 | * of FT1 status enabled on the board. | ||
100 | * May 29, 1997 Jaspreet Singh o Fixed major Flow Control Problem | ||
101 | * With multiple boards a problem was seen where | ||
102 | * the second board always stopped transmitting | ||
103 | * packet after running for a while. The code | ||
104 | * got into a stage where the interrupts were | ||
105 | * disabled and dev->tbusy was set to 1. | ||
106 | * This caused the If_send() routine to get into | ||
107 | * the if clause for it(0,dev->tbusy) | ||
108 | * forever. | ||
109 | * The code got into this stage due to an | ||
110 | * interrupt occurring within the if clause for | ||
111 | * set_bit(0,dev->tbusy). Since an interrupt | ||
112 | * disables furhter transmit interrupt and | ||
113 | * makes dev->tbusy = 0, this effect was undone | ||
114 | * by making dev->tbusy = 1 in the if clause. | ||
115 | * The Fix checks to see if Transmit interrupts | ||
116 | * are disabled then do not make dev->tbusy = 1 | ||
117 | * Introduced a global variable: int_occur and | ||
118 | * added tx_int_enabled in the wan_device | ||
119 | * structure. | ||
120 | * May 21, 1997 Jaspreet Singh o Fixed UDP Management for multiple | ||
121 | * boards. | ||
122 | * | ||
123 | * Apr 25, 1997 Farhan Thawar o added UDP Management stuff | ||
124 | * o fixed bug in if_send() and tx_intr() to | ||
125 | * sleep and wakeup all devices | ||
126 | * Mar 11, 1997 Farhan Thawar Version 3.1.1 | ||
127 | * o fixed (+1) bug in fr508_rx_intr() | ||
128 | * o changed if_send() to return 0 if | ||
129 | * wandev.critical() is true | ||
130 | * o free socket buffer in if_send() if | ||
131 | * returning 0 | ||
132 | * o added tx_intr() routine | ||
133 | * Jan 30, 1997 Gene Kozin Version 3.1.0 | ||
134 | * o implemented exec() entry point | ||
135 | * o fixed a bug causing driver configured as | ||
136 | * a FR switch to be stuck in WAN_ | ||
137 | * mode | ||
138 | * Jan 02, 1997 Gene Kozin Initial version. | ||
139 | *****************************************************************************/ | ||
140 | |||
141 | #include <linux/module.h> | ||
142 | #include <linux/kernel.h> /* printk(), and other useful stuff */ | ||
143 | #include <linux/stddef.h> /* offsetof(), etc. */ | ||
144 | #include <linux/errno.h> /* return codes */ | ||
145 | #include <linux/string.h> /* inline memset(), etc. */ | ||
146 | #include <linux/slab.h> /* kmalloc(), kfree() */ | ||
147 | #include <linux/wanrouter.h> /* WAN router definitions */ | ||
148 | #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ | ||
149 | #include <linux/workqueue.h> | ||
150 | #include <linux/if_arp.h> /* ARPHRD_* defines */ | ||
151 | #include <asm/byteorder.h> /* htons(), etc. */ | ||
152 | #include <asm/io.h> /* for inb(), outb(), etc. */ | ||
153 | #include <linux/time.h> /* for do_gettimeofday */ | ||
154 | #include <linux/in.h> /* sockaddr_in */ | ||
155 | #include <linux/jiffies.h> /* time_after() macro */ | ||
156 | #include <asm/errno.h> | ||
157 | |||
158 | #include <linux/ip.h> | ||
159 | #include <linux/if.h> | ||
160 | |||
161 | #include <linux/if_wanpipe_common.h> /* Wanpipe Socket */ | ||
162 | #include <linux/if_wanpipe.h> | ||
163 | |||
164 | #include <linux/sdla_fr.h> /* frame relay firmware API definitions */ | ||
165 | |||
166 | #include <asm/uaccess.h> | ||
167 | #include <linux/inetdevice.h> | ||
168 | #include <linux/netdevice.h> | ||
169 | |||
170 | #include <net/route.h> /* Dynamic Route Creation */ | ||
171 | #include <linux/etherdevice.h> /* eth_type_trans() used for bridging */ | ||
172 | #include <linux/random.h> | ||
173 | |||
174 | /****** Defines & Macros ****************************************************/ | ||
175 | |||
176 | #define MAX_CMD_RETRY 10 /* max number of firmware retries */ | ||
177 | |||
178 | #define FR_HEADER_LEN 8 /* max encapsulation header size */ | ||
179 | #define FR_CHANNEL_MTU 1500 /* unfragmented logical channel MTU */ | ||
180 | |||
181 | /* Q.922 frame types */ | ||
182 | #define Q922_UI 0x03 /* Unnumbered Info frame */ | ||
183 | #define Q922_XID 0xAF | ||
184 | |||
185 | /* DLCI configured or not */ | ||
186 | #define DLCI_NOT_CONFIGURED 0x00 | ||
187 | #define DLCI_CONFIG_PENDING 0x01 | ||
188 | #define DLCI_CONFIGURED 0x02 | ||
189 | |||
190 | /* CIR enabled or not */ | ||
191 | #define CIR_ENABLED 0x00 | ||
192 | #define CIR_DISABLED 0x01 | ||
193 | |||
194 | #define FRAME_RELAY_API 1 | ||
195 | #define MAX_BH_BUFF 10 | ||
196 | |||
197 | /* For handle_IPXWAN() */ | ||
198 | #define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b))) | ||
199 | |||
200 | /****** Data Structures *****************************************************/ | ||
201 | |||
202 | /* This is an extention of the 'struct device' we create for each network | ||
203 | * interface to keep the rest of channel-specific data. | ||
204 | */ | ||
205 | typedef struct fr_channel | ||
206 | { | ||
207 | wanpipe_common_t common; | ||
208 | char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */ | ||
209 | unsigned dlci_configured ; /* check whether configured or not */ | ||
210 | unsigned cir_status; /* check whether CIR enabled or not */ | ||
211 | unsigned dlci; /* logical channel number */ | ||
212 | unsigned cir; /* committed information rate */ | ||
213 | unsigned bc; /* committed burst size */ | ||
214 | unsigned be; /* excess burst size */ | ||
215 | unsigned mc; /* multicast support on or off */ | ||
216 | unsigned tx_int_status; /* Transmit Interrupt Status */ | ||
217 | unsigned short pkt_length; /* Packet Length */ | ||
218 | unsigned long router_start_time;/* Router start time in seconds */ | ||
219 | unsigned long tick_counter; /* counter for transmit time out */ | ||
220 | char dev_pending_devtint; /* interface pending dev_tint() */ | ||
221 | void *dlci_int_interface; /* pointer to the DLCI Interface */ | ||
222 | unsigned long IB_addr; /* physical address of Interface Byte */ | ||
223 | unsigned long state_tick; /* time of the last state change */ | ||
224 | unsigned char enable_IPX; /* Enable/Disable the use of IPX */ | ||
225 | unsigned long network_number; /* Internal Network Number for IPX*/ | ||
226 | sdla_t *card; /* -> owner */ | ||
227 | unsigned route_flag; /* Add/Rem dest addr in route tables */ | ||
228 | unsigned inarp; /* Inverse Arp Request status */ | ||
229 | long inarp_ready; /* Ready to send requests */ | ||
230 | int inarp_interval; /* Time between InArp Requests */ | ||
231 | unsigned long inarp_tick; /* InArp jiffies tick counter */ | ||
232 | long interface_down; /* Bring interface down on disconnect */ | ||
233 | struct net_device_stats ifstats; /* interface statistics */ | ||
234 | if_send_stat_t drvstats_if_send; | ||
235 | rx_intr_stat_t drvstats_rx_intr; | ||
236 | pipe_mgmt_stat_t drvstats_gen; | ||
237 | unsigned long router_up_time; | ||
238 | |||
239 | unsigned short transmit_length; | ||
240 | struct sk_buff *delay_skb; | ||
241 | |||
242 | bh_data_t *bh_head; /* Circular buffer for chdlc_bh */ | ||
243 | unsigned long tq_working; | ||
244 | volatile int bh_write; | ||
245 | volatile int bh_read; | ||
246 | atomic_t bh_buff_used; | ||
247 | |||
248 | /* Polling task queue. Each interface | ||
249 | * has its own task queue, which is used | ||
250 | * to defer events from the interrupt */ | ||
251 | struct work_struct fr_poll_work; | ||
252 | struct timer_list fr_arp_timer; | ||
253 | |||
254 | u32 ip_local; | ||
255 | u32 ip_remote; | ||
256 | long config_dlci; | ||
257 | long unconfig_dlci; | ||
258 | |||
259 | /* Whether this interface should be setup as a gateway. | ||
260 | * Used by dynamic route setup code */ | ||
261 | u8 gateway; | ||
262 | |||
263 | /* True interface type */ | ||
264 | u8 true_if_encoding; | ||
265 | u8 fr_header[FR_HEADER_LEN]; | ||
266 | char fr_header_len; | ||
267 | |||
268 | } fr_channel_t; | ||
269 | |||
270 | /* Route Flag options */ | ||
271 | #define NO_ROUTE 0x00 | ||
272 | #define ADD_ROUTE 0x01 | ||
273 | #define ROUTE_ADDED 0x02 | ||
274 | #define REMOVE_ROUTE 0x03 | ||
275 | #define ARP_REQ 0x04 | ||
276 | |||
277 | /* inarp options */ | ||
278 | #define INARP_NONE 0x00 | ||
279 | #define INARP_REQUEST 0x01 | ||
280 | #define INARP_CONFIGURED 0x02 | ||
281 | |||
282 | /* reasons for enabling the timer interrupt on the adapter */ | ||
283 | #define TMR_INT_ENABLED_UDP 0x01 | ||
284 | #define TMR_INT_ENABLED_UPDATE 0x02 | ||
285 | #define TMR_INT_ENABLED_ARP 0x04 | ||
286 | #define TMR_INT_ENABLED_UPDATE_STATE 0x08 | ||
287 | #define TMR_INT_ENABLED_CONFIG 0x10 | ||
288 | #define TMR_INT_ENABLED_UNCONFIG 0x20 | ||
289 | |||
290 | |||
291 | typedef struct dlci_status | ||
292 | { | ||
293 | unsigned short dlci PACKED; | ||
294 | unsigned char state PACKED; | ||
295 | } dlci_status_t; | ||
296 | |||
297 | typedef struct dlci_IB_mapping | ||
298 | { | ||
299 | unsigned short dlci PACKED; | ||
300 | unsigned long addr_value PACKED; | ||
301 | } dlci_IB_mapping_t; | ||
302 | |||
303 | /* This structure is used for DLCI list Tx interrupt mode. It is used to | ||
304 | enable interrupt bit and set the packet length for transmission | ||
305 | */ | ||
306 | typedef struct fr_dlci_interface | ||
307 | { | ||
308 | unsigned char gen_interrupt PACKED; | ||
309 | unsigned short packet_length PACKED; | ||
310 | unsigned char reserved PACKED; | ||
311 | } fr_dlci_interface_t; | ||
312 | |||
313 | /* variable for keeping track of enabling/disabling FT1 monitor status */ | ||
314 | static int rCount = 0; | ||
315 | |||
316 | extern void disable_irq(unsigned int); | ||
317 | extern void enable_irq(unsigned int); | ||
318 | |||
319 | /* variable for keeping track of number of interrupts generated during | ||
320 | * interrupt test routine | ||
321 | */ | ||
322 | static int Intr_test_counter; | ||
323 | |||
324 | /****** Function Prototypes *************************************************/ | ||
325 | |||
326 | /* WAN link driver entry points. These are called by the WAN router module. */ | ||
327 | static int update(struct wan_device *wandev); | ||
328 | static int new_if(struct wan_device *wandev, struct net_device *dev, | ||
329 | wanif_conf_t *conf); | ||
330 | static int del_if(struct wan_device *wandev, struct net_device *dev); | ||
331 | static void disable_comm (sdla_t *card); | ||
332 | |||
333 | /* WANPIPE-specific entry points */ | ||
334 | static int wpf_exec(struct sdla *card, void *u_cmd, void *u_data); | ||
335 | |||
336 | /* Network device interface */ | ||
337 | static int if_init(struct net_device *dev); | ||
338 | static int if_open(struct net_device *dev); | ||
339 | static int if_close(struct net_device *dev); | ||
340 | |||
341 | static void if_tx_timeout(struct net_device *dev); | ||
342 | |||
343 | static int if_rebuild_hdr (struct sk_buff *skb); | ||
344 | |||
345 | static int if_send(struct sk_buff *skb, struct net_device *dev); | ||
346 | static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev, | ||
347 | struct sk_buff *skb); | ||
348 | static struct net_device_stats *if_stats(struct net_device *dev); | ||
349 | |||
350 | /* Interrupt handlers */ | ||
351 | static void fr_isr(sdla_t *card); | ||
352 | static void rx_intr(sdla_t *card); | ||
353 | static void tx_intr(sdla_t *card); | ||
354 | static void timer_intr(sdla_t *card); | ||
355 | static void spur_intr(sdla_t *card); | ||
356 | |||
357 | /* Frame relay firmware interface functions */ | ||
358 | static int fr_read_version(sdla_t *card, char *str); | ||
359 | static int fr_configure(sdla_t *card, fr_conf_t *conf); | ||
360 | static int fr_dlci_configure(sdla_t *card, fr_dlc_conf_t *conf, unsigned dlci); | ||
361 | static int fr_init_dlci (sdla_t *card, fr_channel_t *chan); | ||
362 | static int fr_set_intr_mode (sdla_t *card, unsigned mode, unsigned mtu, unsigned short timeout); | ||
363 | static int fr_comm_enable(sdla_t *card); | ||
364 | static void fr_comm_disable(sdla_t *card); | ||
365 | static int fr_get_err_stats(sdla_t *card); | ||
366 | static int fr_get_stats(sdla_t *card); | ||
367 | static int fr_add_dlci(sdla_t *card, int dlci); | ||
368 | static int fr_activate_dlci(sdla_t *card, int dlci); | ||
369 | static int fr_delete_dlci (sdla_t* card, int dlci); | ||
370 | static int fr_issue_isf(sdla_t *card, int isf); | ||
371 | static int fr_send(sdla_t *card, int dlci, unsigned char attr, int len, | ||
372 | void *buf); | ||
373 | static int fr_send_data_header(sdla_t *card, int dlci, unsigned char attr, int len, | ||
374 | void *buf,unsigned char hdr_len); | ||
375 | static unsigned int fr_send_hdr(sdla_t *card, int dlci, unsigned int offset); | ||
376 | |||
377 | static int check_dlci_config (sdla_t *card, fr_channel_t *chan); | ||
378 | static void initialize_rx_tx_buffers (sdla_t *card); | ||
379 | |||
380 | |||
381 | /* Firmware asynchronous event handlers */ | ||
382 | static int fr_event(sdla_t *card, int event, fr_mbox_t *mbox); | ||
383 | static int fr_modem_failure(sdla_t *card, fr_mbox_t *mbox); | ||
384 | static int fr_dlci_change(sdla_t *card, fr_mbox_t *mbox); | ||
385 | |||
386 | /* Miscellaneous functions */ | ||
387 | static int update_chan_state(struct net_device *dev); | ||
388 | static void set_chan_state(struct net_device *dev, int state); | ||
389 | static struct net_device *find_channel(sdla_t *card, unsigned dlci); | ||
390 | static int is_tx_ready(sdla_t *card, fr_channel_t *chan); | ||
391 | static unsigned int dec_to_uint(unsigned char *str, int len); | ||
392 | static int reply_udp( unsigned char *data, unsigned int mbox_len ); | ||
393 | |||
394 | static int intr_test( sdla_t* card ); | ||
395 | static void init_chan_statistics( fr_channel_t* chan ); | ||
396 | static void init_global_statistics( sdla_t* card ); | ||
397 | static void read_DLCI_IB_mapping( sdla_t* card, fr_channel_t* chan ); | ||
398 | static int setup_for_delayed_transmit(struct net_device* dev, | ||
399 | struct sk_buff *skb); | ||
400 | |||
401 | struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev); | ||
402 | static int check_tx_status(sdla_t *card, struct net_device *dev); | ||
403 | |||
404 | /* Frame Relay Socket API */ | ||
405 | static void trigger_fr_bh (fr_channel_t *); | ||
406 | static void fr_bh(struct net_device *dev); | ||
407 | static int fr_bh_cleanup(struct net_device *dev); | ||
408 | static int bh_enqueue(struct net_device *dev, struct sk_buff *skb); | ||
409 | |||
410 | static void trigger_fr_poll(struct net_device *dev); | ||
411 | static void fr_poll(struct net_device *dev); | ||
412 | //static void add_gateway(struct net_device *dev); | ||
413 | |||
414 | static void trigger_unconfig_fr(struct net_device *dev); | ||
415 | static void unconfig_fr (sdla_t *); | ||
416 | |||
417 | static void trigger_config_fr (sdla_t *); | ||
418 | static void config_fr (sdla_t *); | ||
419 | |||
420 | |||
421 | /* Inverse ARP and Dynamic routing functions */ | ||
422 | int process_ARP(arphdr_1490_t *ArpPacket, sdla_t *card, struct net_device *dev); | ||
423 | int is_arp(void *buf); | ||
424 | int send_inarp_request(sdla_t *card, struct net_device *dev); | ||
425 | |||
426 | static void trigger_fr_arp(struct net_device *dev); | ||
427 | static void fr_arp (unsigned long data); | ||
428 | |||
429 | |||
430 | /* Udp management functions */ | ||
431 | static int process_udp_mgmt_pkt(sdla_t *card); | ||
432 | static int udp_pkt_type( struct sk_buff *skb, sdla_t *card ); | ||
433 | static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card, | ||
434 | struct sk_buff *skb, int dlci); | ||
435 | |||
436 | /* IPX functions */ | ||
437 | static void switch_net_numbers(unsigned char *sendpacket, | ||
438 | unsigned long network_number, unsigned char incoming); | ||
439 | |||
440 | static int handle_IPXWAN(unsigned char *sendpacket, char *devname, | ||
441 | unsigned char enable_IPX, unsigned long network_number); | ||
442 | |||
443 | /* Lock Functions: SMP supported */ | ||
444 | void s508_s514_unlock(sdla_t *card, unsigned long *smp_flags); | ||
445 | void s508_s514_lock(sdla_t *card, unsigned long *smp_flags); | ||
446 | |||
447 | unsigned short calc_checksum (char *, int); | ||
448 | static int setup_fr_header(struct sk_buff *skb, | ||
449 | struct net_device* dev, char op_mode); | ||
450 | |||
451 | |||
452 | /****** Public Functions ****************************************************/ | ||
453 | |||
454 | /*============================================================================ | ||
455 | * Frame relay protocol initialization routine. | ||
456 | * | ||
457 | * This routine is called by the main WANPIPE module during setup. At this | ||
458 | * point adapter is completely initialized and firmware is running. | ||
459 | * o read firmware version (to make sure it's alive) | ||
460 | * o configure adapter | ||
461 | * o initialize protocol-specific fields of the adapter data space. | ||
462 | * | ||
463 | * Return: 0 o.k. | ||
464 | * < 0 failure. | ||
465 | */ | ||
466 | int wpf_init(sdla_t *card, wandev_conf_t *conf) | ||
467 | { | ||
468 | |||
469 | int err; | ||
470 | fr508_flags_t* flags; | ||
471 | |||
472 | union | ||
473 | { | ||
474 | char str[80]; | ||
475 | fr_conf_t cfg; | ||
476 | } u; | ||
477 | |||
478 | fr_buf_info_t* buf_info; | ||
479 | int i; | ||
480 | |||
481 | |||
482 | printk(KERN_INFO "\n"); | ||
483 | |||
484 | /* Verify configuration ID */ | ||
485 | if (conf->config_id != WANCONFIG_FR) { | ||
486 | |||
487 | printk(KERN_INFO "%s: invalid configuration ID %u!\n", | ||
488 | card->devname, conf->config_id); | ||
489 | return -EINVAL; | ||
490 | |||
491 | } | ||
492 | |||
493 | /* Initialize protocol-specific fields of adapter data space */ | ||
494 | switch (card->hw.fwid) { | ||
495 | |||
496 | case SFID_FR508: | ||
497 | card->mbox = (void*)(card->hw.dpmbase + | ||
498 | FR508_MBOX_OFFS); | ||
499 | card->flags = (void*)(card->hw.dpmbase + | ||
500 | FR508_FLAG_OFFS); | ||
501 | if(card->hw.type == SDLA_S514) { | ||
502 | card->mbox += FR_MB_VECTOR; | ||
503 | card->flags += FR_MB_VECTOR; | ||
504 | } | ||
505 | card->isr = &fr_isr; | ||
506 | break; | ||
507 | |||
508 | default: | ||
509 | return -EINVAL; | ||
510 | } | ||
511 | |||
512 | flags = card->flags; | ||
513 | |||
514 | /* Read firmware version. Note that when adapter initializes, it | ||
515 | * clears the mailbox, so it may appear that the first command was | ||
516 | * executed successfully when in fact it was merely erased. To work | ||
517 | * around this, we execute the first command twice. | ||
518 | */ | ||
519 | |||
520 | if (fr_read_version(card, NULL) || fr_read_version(card, u.str)) | ||
521 | return -EIO; | ||
522 | |||
523 | printk(KERN_INFO "%s: running frame relay firmware v%s\n", | ||
524 | card->devname, u.str); | ||
525 | |||
526 | /* Adjust configuration */ | ||
527 | conf->mtu += FR_HEADER_LEN; | ||
528 | conf->mtu = (conf->mtu >= MIN_LGTH_FR_DATA_CFG) ? | ||
529 | min_t(unsigned int, conf->mtu, FR_MAX_NO_DATA_BYTES_IN_FRAME) : | ||
530 | FR_CHANNEL_MTU + FR_HEADER_LEN; | ||
531 | |||
532 | conf->bps = min_t(unsigned int, conf->bps, 2048000); | ||
533 | |||
534 | /* Initialze the configuration structure sent to the board to zero */ | ||
535 | memset(&u.cfg, 0, sizeof(u.cfg)); | ||
536 | |||
537 | memset(card->u.f.dlci_to_dev_map, 0, sizeof(card->u.f.dlci_to_dev_map)); | ||
538 | |||
539 | /* Configure adapter firmware */ | ||
540 | |||
541 | u.cfg.mtu = conf->mtu; | ||
542 | u.cfg.kbps = conf->bps / 1000; | ||
543 | |||
544 | u.cfg.cir_fwd = u.cfg.cir_bwd = 16; | ||
545 | u.cfg.bc_fwd = u.cfg.bc_bwd = 16; | ||
546 | |||
547 | u.cfg.options = 0x0000; | ||
548 | printk(KERN_INFO "%s: Global CIR enabled by Default\n", card->devname); | ||
549 | |||
550 | switch (conf->u.fr.signalling) { | ||
551 | |||
552 | case WANOPT_FR_ANSI: | ||
553 | u.cfg.options = 0x0000; | ||
554 | break; | ||
555 | |||
556 | case WANOPT_FR_Q933: | ||
557 | u.cfg.options |= 0x0200; | ||
558 | break; | ||
559 | |||
560 | case WANOPT_FR_LMI: | ||
561 | u.cfg.options |= 0x0400; | ||
562 | break; | ||
563 | |||
564 | case WANOPT_NO: | ||
565 | u.cfg.options |= 0x0800; | ||
566 | break; | ||
567 | default: | ||
568 | printk(KERN_INFO "%s: Illegal Signalling option\n", | ||
569 | card->wandev.name); | ||
570 | return -EINVAL; | ||
571 | } | ||
572 | |||
573 | |||
574 | card->wandev.signalling = conf->u.fr.signalling; | ||
575 | |||
576 | if (conf->station == WANOPT_CPE) { | ||
577 | |||
578 | |||
579 | if (conf->u.fr.signalling == WANOPT_NO){ | ||
580 | printk(KERN_INFO | ||
581 | "%s: ERROR - For NO signalling, station must be set to Node!", | ||
582 | card->devname); | ||
583 | return -EINVAL; | ||
584 | } | ||
585 | |||
586 | u.cfg.station = 0; | ||
587 | u.cfg.options |= 0x8000; /* auto config DLCI */ | ||
588 | card->u.f.dlci_num = 0; | ||
589 | |||
590 | } else { | ||
591 | |||
592 | u.cfg.station = 1; /* switch emulation mode */ | ||
593 | |||
594 | /* For switch emulation we have to create a list of dlci(s) | ||
595 | * that will be sent to be global SET_DLCI_CONFIGURATION | ||
596 | * command in fr_configure() routine. | ||
597 | */ | ||
598 | |||
599 | card->u.f.dlci_num = min_t(unsigned int, max_t(unsigned int, conf->u.fr.dlci_num, 1), 100); | ||
600 | |||
601 | for ( i = 0; i < card->u.f.dlci_num; i++) { | ||
602 | |||
603 | card->u.f.node_dlci[i] = (unsigned short) | ||
604 | conf->u.fr.dlci[i] ? conf->u.fr.dlci[i] : 16; | ||
605 | |||
606 | } | ||
607 | } | ||
608 | |||
609 | if (conf->clocking == WANOPT_INTERNAL) | ||
610 | u.cfg.port |= 0x0001; | ||
611 | |||
612 | if (conf->interface == WANOPT_RS232) | ||
613 | u.cfg.port |= 0x0002; | ||
614 | |||
615 | if (conf->u.fr.t391) | ||
616 | u.cfg.t391 = min_t(unsigned int, conf->u.fr.t391, 30); | ||
617 | else | ||
618 | u.cfg.t391 = 5; | ||
619 | |||
620 | if (conf->u.fr.t392) | ||
621 | u.cfg.t392 = min_t(unsigned int, conf->u.fr.t392, 30); | ||
622 | else | ||
623 | u.cfg.t392 = 15; | ||
624 | |||
625 | if (conf->u.fr.n391) | ||
626 | u.cfg.n391 = min_t(unsigned int, conf->u.fr.n391, 255); | ||
627 | else | ||
628 | u.cfg.n391 = 2; | ||
629 | |||
630 | if (conf->u.fr.n392) | ||
631 | u.cfg.n392 = min_t(unsigned int, conf->u.fr.n392, 10); | ||
632 | else | ||
633 | u.cfg.n392 = 3; | ||
634 | |||
635 | if (conf->u.fr.n393) | ||
636 | u.cfg.n393 = min_t(unsigned int, conf->u.fr.n393, 10); | ||
637 | else | ||
638 | u.cfg.n393 = 4; | ||
639 | |||
640 | if (fr_configure(card, &u.cfg)) | ||
641 | return -EIO; | ||
642 | |||
643 | if (card->hw.type == SDLA_S514) { | ||
644 | |||
645 | buf_info = (void*)(card->hw.dpmbase + FR_MB_VECTOR + | ||
646 | FR508_RXBC_OFFS); | ||
647 | |||
648 | card->rxmb = (void*)(buf_info->rse_next + card->hw.dpmbase); | ||
649 | |||
650 | card->u.f.rxmb_base = | ||
651 | (void*)(buf_info->rse_base + card->hw.dpmbase); | ||
652 | |||
653 | card->u.f.rxmb_last = | ||
654 | (void*)(buf_info->rse_base + | ||
655 | (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) + | ||
656 | card->hw.dpmbase); | ||
657 | }else{ | ||
658 | buf_info = (void*)(card->hw.dpmbase + FR508_RXBC_OFFS); | ||
659 | |||
660 | card->rxmb = (void*)(buf_info->rse_next - | ||
661 | FR_MB_VECTOR + card->hw.dpmbase); | ||
662 | |||
663 | card->u.f.rxmb_base = | ||
664 | (void*)(buf_info->rse_base - | ||
665 | FR_MB_VECTOR + card->hw.dpmbase); | ||
666 | |||
667 | card->u.f.rxmb_last = | ||
668 | (void*)(buf_info->rse_base + | ||
669 | (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) - | ||
670 | FR_MB_VECTOR + card->hw.dpmbase); | ||
671 | } | ||
672 | |||
673 | card->u.f.rx_base = buf_info->buf_base; | ||
674 | card->u.f.rx_top = buf_info->buf_top; | ||
675 | |||
676 | card->u.f.tx_interrupts_pending = 0; | ||
677 | |||
678 | card->wandev.mtu = conf->mtu; | ||
679 | card->wandev.bps = conf->bps; | ||
680 | card->wandev.interface = conf->interface; | ||
681 | card->wandev.clocking = conf->clocking; | ||
682 | card->wandev.station = conf->station; | ||
683 | card->poll = NULL; | ||
684 | card->exec = &wpf_exec; | ||
685 | card->wandev.update = &update; | ||
686 | card->wandev.new_if = &new_if; | ||
687 | card->wandev.del_if = &del_if; | ||
688 | card->wandev.state = WAN_DISCONNECTED; | ||
689 | card->wandev.ttl = conf->ttl; | ||
690 | card->wandev.udp_port = conf->udp_port; | ||
691 | card->disable_comm = &disable_comm; | ||
692 | card->u.f.arp_dev = NULL; | ||
693 | |||
694 | /* Intialize global statistics for a card */ | ||
695 | init_global_statistics( card ); | ||
696 | |||
697 | card->TracingEnabled = 0; | ||
698 | |||
699 | /* Interrupt Test */ | ||
700 | Intr_test_counter = 0; | ||
701 | card->intr_mode = INTR_TEST_MODE; | ||
702 | err = intr_test( card ); | ||
703 | |||
704 | printk(KERN_INFO "%s: End of Interrupt Test rc=0x%x count=%i\n", | ||
705 | card->devname,err,Intr_test_counter); | ||
706 | |||
707 | if (err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { | ||
708 | printk(KERN_ERR "%s: Interrupt Test Failed, Counter: %i\n", | ||
709 | card->devname, Intr_test_counter); | ||
710 | printk(KERN_ERR "Please choose another interrupt\n"); | ||
711 | err = -EIO; | ||
712 | return err; | ||
713 | } | ||
714 | |||
715 | printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n", | ||
716 | card->devname, Intr_test_counter); | ||
717 | |||
718 | |||
719 | /* Apr 28 2000. Nenad Corbic | ||
720 | * Enable commnunications here, not in if_open or new_if, since | ||
721 | * interfaces come down when the link is disconnected. | ||
722 | */ | ||
723 | |||
724 | /* If you enable comms and then set ints, you get a Tx int as you | ||
725 | * perform the SET_INT_TRIGGERS command. So, we only set int | ||
726 | * triggers and then adjust the interrupt mask (to disable Tx ints) | ||
727 | * before enabling comms. | ||
728 | */ | ||
729 | if (fr_set_intr_mode(card, (FR_INTR_RXRDY | FR_INTR_TXRDY | | ||
730 | FR_INTR_DLC | FR_INTR_TIMER | FR_INTR_TX_MULT_DLCIs) , | ||
731 | card->wandev.mtu, 0)) { | ||
732 | return -EIO; | ||
733 | } | ||
734 | |||
735 | flags->imask &= ~(FR_INTR_TXRDY | FR_INTR_TIMER); | ||
736 | |||
737 | if (fr_comm_enable(card)) { | ||
738 | return -EIO; | ||
739 | } | ||
740 | wanpipe_set_state(card, WAN_CONNECTED); | ||
741 | spin_lock_init(&card->u.f.if_send_lock); | ||
742 | |||
743 | printk(KERN_INFO "\n"); | ||
744 | |||
745 | return 0; | ||
746 | } | ||
747 | |||
748 | /******* WAN Device Driver Entry Points *************************************/ | ||
749 | |||
750 | /*============================================================================ | ||
751 | * Update device status & statistics. | ||
752 | */ | ||
753 | static int update(struct wan_device* wandev) | ||
754 | { | ||
755 | volatile sdla_t* card; | ||
756 | unsigned long timeout; | ||
757 | fr508_flags_t* flags; | ||
758 | |||
759 | /* sanity checks */ | ||
760 | if ((wandev == NULL) || (wandev->private == NULL)) | ||
761 | return -EFAULT; | ||
762 | |||
763 | if (wandev->state == WAN_UNCONFIGURED) | ||
764 | return -ENODEV; | ||
765 | |||
766 | card = wandev->private; | ||
767 | flags = card->flags; | ||
768 | |||
769 | |||
770 | card->u.f.update_comms_stats = 1; | ||
771 | card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UPDATE; | ||
772 | flags->imask |= FR_INTR_TIMER; | ||
773 | timeout = jiffies; | ||
774 | for(;;) { | ||
775 | if(card->u.f.update_comms_stats == 0) | ||
776 | break; | ||
777 | if (time_after(jiffies, timeout + 1 * HZ)){ | ||
778 | card->u.f.update_comms_stats = 0; | ||
779 | return -EAGAIN; | ||
780 | } | ||
781 | } | ||
782 | |||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | /*============================================================================ | ||
787 | * Create new logical channel. | ||
788 | * This routine is called by the router when ROUTER_IFNEW IOCTL is being | ||
789 | * handled. | ||
790 | * o parse media- and hardware-specific configuration | ||
791 | * o make sure that a new channel can be created | ||
792 | * o allocate resources, if necessary | ||
793 | * o prepare network device structure for registaration. | ||
794 | * | ||
795 | * Return: 0 o.k. | ||
796 | * < 0 failure (channel will not be created) | ||
797 | */ | ||
798 | static int new_if(struct wan_device* wandev, struct net_device* dev, | ||
799 | wanif_conf_t* conf) | ||
800 | { | ||
801 | sdla_t* card = wandev->private; | ||
802 | fr_channel_t* chan; | ||
803 | int dlci = 0; | ||
804 | int err = 0; | ||
805 | |||
806 | |||
807 | if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) { | ||
808 | |||
809 | printk(KERN_INFO "%s: Invalid interface name!\n", | ||
810 | card->devname); | ||
811 | return -EINVAL; | ||
812 | } | ||
813 | |||
814 | /* allocate and initialize private data */ | ||
815 | chan = kmalloc(sizeof(fr_channel_t), GFP_KERNEL); | ||
816 | |||
817 | if (chan == NULL) | ||
818 | return -ENOMEM; | ||
819 | |||
820 | memset(chan, 0, sizeof(fr_channel_t)); | ||
821 | strcpy(chan->name, conf->name); | ||
822 | chan->card = card; | ||
823 | |||
824 | /* verify media address */ | ||
825 | if (isdigit(conf->addr[0])) { | ||
826 | |||
827 | dlci = dec_to_uint(conf->addr, 0); | ||
828 | |||
829 | if (dlci && (dlci <= HIGHEST_VALID_DLCI)) { | ||
830 | |||
831 | chan->dlci = dlci; | ||
832 | |||
833 | } else { | ||
834 | |||
835 | printk(KERN_ERR | ||
836 | "%s: Invalid DLCI %u on interface %s!\n", | ||
837 | wandev->name, dlci, chan->name); | ||
838 | err = -EINVAL; | ||
839 | } | ||
840 | |||
841 | } else { | ||
842 | printk(KERN_ERR | ||
843 | "%s: Invalid media address on interface %s!\n", | ||
844 | wandev->name, chan->name); | ||
845 | err = -EINVAL; | ||
846 | } | ||
847 | |||
848 | if ((chan->true_if_encoding = conf->true_if_encoding) == WANOPT_YES){ | ||
849 | printk(KERN_INFO | ||
850 | "%s: Enabling, true interface type encoding.\n", | ||
851 | card->devname); | ||
852 | } | ||
853 | |||
854 | |||
855 | |||
856 | /* Setup wanpipe as a router (WANPIPE) even if it is | ||
857 | * a bridged DLCI, or as an API | ||
858 | */ | ||
859 | if (strcmp(conf->usedby, "WANPIPE") == 0 || | ||
860 | strcmp(conf->usedby, "BRIDGE") == 0 || | ||
861 | strcmp(conf->usedby, "BRIDGE_N") == 0){ | ||
862 | |||
863 | if(strcmp(conf->usedby, "WANPIPE") == 0){ | ||
864 | chan->common.usedby = WANPIPE; | ||
865 | |||
866 | printk(KERN_INFO "%s: Running in WANPIPE mode.\n", | ||
867 | card->devname); | ||
868 | |||
869 | }else if(strcmp(conf->usedby, "BRIDGE") == 0){ | ||
870 | |||
871 | chan->common.usedby = BRIDGE; | ||
872 | |||
873 | printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE) mode.\n", | ||
874 | card->devname); | ||
875 | }else if( strcmp(conf->usedby, "BRIDGE_N") == 0 ){ | ||
876 | |||
877 | chan->common.usedby = BRIDGE_NODE; | ||
878 | |||
879 | printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE_NODE) mode.\n", | ||
880 | card->devname); | ||
881 | } | ||
882 | |||
883 | if (!err){ | ||
884 | /* Dynamic interface configuration option. | ||
885 | * On disconnect, if the options is selected, | ||
886 | * the interface will be brought down */ | ||
887 | if (conf->if_down == WANOPT_YES){ | ||
888 | set_bit(DYN_OPT_ON,&chan->interface_down); | ||
889 | printk(KERN_INFO | ||
890 | "%s: Dynamic interface configuration enabled.\n", | ||
891 | card->devname); | ||
892 | } | ||
893 | } | ||
894 | |||
895 | } else if(strcmp(conf->usedby, "API") == 0){ | ||
896 | |||
897 | chan->common.usedby = API; | ||
898 | printk(KERN_INFO "%s: Running in API mode.\n", | ||
899 | wandev->name); | ||
900 | } | ||
901 | |||
902 | if (err) { | ||
903 | |||
904 | kfree(chan); | ||
905 | return err; | ||
906 | } | ||
907 | |||
908 | /* place cir,be,bc and other channel specific information into the | ||
909 | * chan structure | ||
910 | */ | ||
911 | if (conf->cir) { | ||
912 | |||
913 | chan->cir = max_t(unsigned int, 1, | ||
914 | min_t(unsigned int, conf->cir, 512)); | ||
915 | chan->cir_status = CIR_ENABLED; | ||
916 | |||
917 | |||
918 | /* If CIR is enabled, force BC to equal CIR | ||
919 | * this solves number of potential problems if CIR is | ||
920 | * set and BC is not | ||
921 | */ | ||
922 | chan->bc = chan->cir; | ||
923 | |||
924 | if (conf->be){ | ||
925 | chan->be = max_t(unsigned int, | ||
926 | 0, min_t(unsigned int, conf->be, 511)); | ||
927 | }else{ | ||
928 | conf->be = 0; | ||
929 | } | ||
930 | |||
931 | printk (KERN_INFO "%s: CIR enabled for DLCI %i \n", | ||
932 | wandev->name,chan->dlci); | ||
933 | printk (KERN_INFO "%s: CIR = %i ; BC = %i ; BE = %i\n", | ||
934 | wandev->name,chan->cir,chan->bc,chan->be); | ||
935 | |||
936 | |||
937 | }else{ | ||
938 | chan->cir_status = CIR_DISABLED; | ||
939 | printk (KERN_INFO "%s: CIR disabled for DLCI %i\n", | ||
940 | wandev->name,chan->dlci); | ||
941 | } | ||
942 | |||
943 | chan->mc = conf->mc; | ||
944 | |||
945 | if (conf->inarp == WANOPT_YES){ | ||
946 | printk(KERN_INFO "%s: Inverse ARP Support Enabled\n",card->devname); | ||
947 | chan->inarp = conf->inarp ? INARP_REQUEST : INARP_NONE; | ||
948 | chan->inarp_interval = conf->inarp_interval ? conf->inarp_interval : 10; | ||
949 | }else{ | ||
950 | printk(KERN_INFO "%s: Inverse ARP Support Disabled\n",card->devname); | ||
951 | chan->inarp = INARP_NONE; | ||
952 | chan->inarp_interval = 10; | ||
953 | } | ||
954 | |||
955 | |||
956 | chan->dlci_configured = DLCI_NOT_CONFIGURED; | ||
957 | |||
958 | |||
959 | /*FIXME: IPX disabled in this WANPIPE version */ | ||
960 | if (conf->enable_IPX == WANOPT_YES){ | ||
961 | printk(KERN_INFO "%s: ERROR - This version of WANPIPE doesn't support IPX\n", | ||
962 | card->devname); | ||
963 | kfree(chan); | ||
964 | return -EINVAL; | ||
965 | }else{ | ||
966 | chan->enable_IPX = WANOPT_NO; | ||
967 | } | ||
968 | |||
969 | if (conf->network_number){ | ||
970 | chan->network_number = conf->network_number; | ||
971 | }else{ | ||
972 | chan->network_number = 0xDEADBEEF; | ||
973 | } | ||
974 | |||
975 | chan->route_flag = NO_ROUTE; | ||
976 | |||
977 | init_chan_statistics(chan); | ||
978 | |||
979 | chan->transmit_length = 0; | ||
980 | |||
981 | /* prepare network device data space for registration */ | ||
982 | strcpy(dev->name,chan->name); | ||
983 | |||
984 | dev->init = &if_init; | ||
985 | dev->priv = chan; | ||
986 | |||
987 | /* Initialize FR Polling Task Queue | ||
988 | * We need a poll routine for each network | ||
989 | * interface. | ||
990 | */ | ||
991 | INIT_WORK(&chan->fr_poll_work, (void *)fr_poll, dev); | ||
992 | |||
993 | init_timer(&chan->fr_arp_timer); | ||
994 | chan->fr_arp_timer.data=(unsigned long)dev; | ||
995 | chan->fr_arp_timer.function = fr_arp; | ||
996 | |||
997 | wandev->new_if_cnt++; | ||
998 | |||
999 | /* Tells us that if this interface is a | ||
1000 | * gateway or not */ | ||
1001 | if ((chan->gateway = conf->gateway) == WANOPT_YES){ | ||
1002 | printk(KERN_INFO "%s: Interface %s is set as a gateway.\n", | ||
1003 | card->devname,dev->name); | ||
1004 | } | ||
1005 | |||
1006 | /* M. Grant Patch Apr 28 2000 | ||
1007 | * Disallow duplicate dlci configurations. */ | ||
1008 | if (card->u.f.dlci_to_dev_map[chan->dlci] != NULL) { | ||
1009 | kfree(chan); | ||
1010 | return -EBUSY; | ||
1011 | } | ||
1012 | |||
1013 | /* Configure this dlci at a later date, when | ||
1014 | * the interface comes up. i.e. when if_open() | ||
1015 | * executes */ | ||
1016 | set_bit(0,&chan->config_dlci); | ||
1017 | |||
1018 | printk(KERN_INFO "\n"); | ||
1019 | |||
1020 | return 0; | ||
1021 | } | ||
1022 | |||
1023 | /*============================================================================ | ||
1024 | * Delete logical channel. | ||
1025 | */ | ||
1026 | static int del_if(struct wan_device* wandev, struct net_device* dev) | ||
1027 | { | ||
1028 | fr_channel_t* chan = dev->priv; | ||
1029 | unsigned long smp_flags=0; | ||
1030 | |||
1031 | /* This interface is dead, make sure the | ||
1032 | * ARP timer is stopped */ | ||
1033 | del_timer(&chan->fr_arp_timer); | ||
1034 | |||
1035 | /* If we are a NODE, we must unconfigure this DLCI | ||
1036 | * Trigger an unconfigure command that will | ||
1037 | * be executed in timer interrupt. We must wait | ||
1038 | * for the command to complete. */ | ||
1039 | trigger_unconfig_fr(dev); | ||
1040 | |||
1041 | lock_adapter_irq(&wandev->lock, &smp_flags); | ||
1042 | wandev->new_if_cnt--; | ||
1043 | unlock_adapter_irq(&wandev->lock, &smp_flags); | ||
1044 | |||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1048 | |||
1049 | /*===================================================================== | ||
1050 | * disable_comm | ||
1051 | * | ||
1052 | * Description: | ||
1053 | * Disable communications. | ||
1054 | * This code runs in shutdown (sdlamain.c) | ||
1055 | * under critical flag. Therefore it is not | ||
1056 | * necessary to set a critical flag here | ||
1057 | * | ||
1058 | * Usage: | ||
1059 | * Commnunications are disabled only on a card | ||
1060 | * shutdown. | ||
1061 | */ | ||
1062 | |||
1063 | static void disable_comm (sdla_t *card) | ||
1064 | { | ||
1065 | printk(KERN_INFO "%s: Disabling Communications!\n", | ||
1066 | card->devname); | ||
1067 | fr_comm_disable(card); | ||
1068 | } | ||
1069 | |||
1070 | /****** WANPIPE-specific entry points ***************************************/ | ||
1071 | |||
1072 | /*============================================================================ | ||
1073 | * Execute adapter interface command. | ||
1074 | */ | ||
1075 | static int wpf_exec (struct sdla* card, void* u_cmd, void* u_data) | ||
1076 | { | ||
1077 | fr_mbox_t* mbox = card->mbox; | ||
1078 | int retry = MAX_CMD_RETRY; | ||
1079 | int err, len; | ||
1080 | fr_cmd_t cmd; | ||
1081 | |||
1082 | if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd))) | ||
1083 | return -EFAULT; | ||
1084 | |||
1085 | /* execute command */ | ||
1086 | do | ||
1087 | { | ||
1088 | memcpy(&mbox->cmd, &cmd, sizeof(cmd)); | ||
1089 | |||
1090 | if (cmd.length){ | ||
1091 | if( copy_from_user((void*)&mbox->data, u_data, cmd.length)) | ||
1092 | return -EFAULT; | ||
1093 | } | ||
1094 | |||
1095 | if (sdla_exec(mbox)) | ||
1096 | err = mbox->cmd.result; | ||
1097 | |||
1098 | else return -EIO; | ||
1099 | |||
1100 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
1101 | |||
1102 | /* return result */ | ||
1103 | if (copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(fr_cmd_t))) | ||
1104 | return -EFAULT; | ||
1105 | |||
1106 | len = mbox->cmd.length; | ||
1107 | |||
1108 | if (len && u_data && !copy_to_user(u_data, (void*)&mbox->data, len)) | ||
1109 | return -EFAULT; | ||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1113 | /****** Network Device Interface ********************************************/ | ||
1114 | |||
1115 | /*============================================================================ | ||
1116 | * Initialize Linux network interface. | ||
1117 | * | ||
1118 | * This routine is called only once for each interface, during Linux network | ||
1119 | * interface registration. Returning anything but zero will fail interface | ||
1120 | * registration. | ||
1121 | */ | ||
1122 | static int if_init(struct net_device* dev) | ||
1123 | { | ||
1124 | fr_channel_t* chan = dev->priv; | ||
1125 | sdla_t* card = chan->card; | ||
1126 | struct wan_device* wandev = &card->wandev; | ||
1127 | |||
1128 | /* Initialize device driver entry points */ | ||
1129 | dev->open = &if_open; | ||
1130 | dev->stop = &if_close; | ||
1131 | dev->hard_header = NULL; | ||
1132 | dev->rebuild_header = &if_rebuild_hdr; | ||
1133 | dev->hard_start_xmit = &if_send; | ||
1134 | dev->get_stats = &if_stats; | ||
1135 | dev->tx_timeout = &if_tx_timeout; | ||
1136 | dev->watchdog_timeo = TX_TIMEOUT; | ||
1137 | |||
1138 | if (chan->common.usedby == WANPIPE || chan->common.usedby == API){ | ||
1139 | |||
1140 | /* Initialize media-specific parameters */ | ||
1141 | if (chan->true_if_encoding){ | ||
1142 | dev->type = ARPHRD_DLCI; /* This breaks tcpdump */ | ||
1143 | }else{ | ||
1144 | dev->type = ARPHRD_PPP; /* ARP h/w type */ | ||
1145 | } | ||
1146 | |||
1147 | dev->flags |= IFF_POINTOPOINT; | ||
1148 | dev->flags |= IFF_NOARP; | ||
1149 | |||
1150 | /* Enable Multicast addressing */ | ||
1151 | if (chan->mc == WANOPT_YES){ | ||
1152 | dev->flags |= IFF_MULTICAST; | ||
1153 | } | ||
1154 | |||
1155 | dev->mtu = wandev->mtu - FR_HEADER_LEN; | ||
1156 | /* For an API, the maximum number of bytes that the stack will pass | ||
1157 | to the driver is (dev->mtu + dev->hard_header_len). So, adjust the | ||
1158 | mtu so that a frame of maximum size can be transmitted by the API. | ||
1159 | */ | ||
1160 | if(chan->common.usedby == API) { | ||
1161 | dev->mtu += (sizeof(api_tx_hdr_t) - FR_HEADER_LEN); | ||
1162 | } | ||
1163 | |||
1164 | dev->hard_header_len = FR_HEADER_LEN;/* media header length */ | ||
1165 | dev->addr_len = 2; /* hardware address length */ | ||
1166 | *(unsigned short*)dev->dev_addr = htons(chan->dlci); | ||
1167 | |||
1168 | /* Set transmit buffer queue length */ | ||
1169 | dev->tx_queue_len = 100; | ||
1170 | |||
1171 | }else{ | ||
1172 | |||
1173 | /* Setup the interface for Bridging */ | ||
1174 | int hw_addr=0; | ||
1175 | ether_setup(dev); | ||
1176 | |||
1177 | /* Use a random number to generate the MAC address */ | ||
1178 | memcpy(dev->dev_addr, "\xFE\xFC\x00\x00\x00\x00", 6); | ||
1179 | get_random_bytes(&hw_addr, sizeof(hw_addr)); | ||
1180 | *(int *)(dev->dev_addr + 2) += hw_addr; | ||
1181 | } | ||
1182 | |||
1183 | /* Initialize hardware parameters (just for reference) */ | ||
1184 | dev->irq = wandev->irq; | ||
1185 | dev->dma = wandev->dma; | ||
1186 | dev->base_addr = wandev->ioport; | ||
1187 | dev->mem_start = wandev->maddr; | ||
1188 | dev->mem_end = wandev->maddr + wandev->msize - 1; | ||
1189 | SET_MODULE_OWNER(dev); | ||
1190 | |||
1191 | return 0; | ||
1192 | } | ||
1193 | |||
1194 | /*============================================================================ | ||
1195 | * Open network interface. | ||
1196 | * o if this is the first open, then enable communications and interrupts. | ||
1197 | * o prevent module from unloading by incrementing use count | ||
1198 | * | ||
1199 | * Return 0 if O.k. or errno. | ||
1200 | */ | ||
1201 | static int if_open(struct net_device* dev) | ||
1202 | { | ||
1203 | fr_channel_t* chan = dev->priv; | ||
1204 | sdla_t* card = chan->card; | ||
1205 | int err = 0; | ||
1206 | struct timeval tv; | ||
1207 | |||
1208 | if (netif_running(dev)) | ||
1209 | return -EBUSY; | ||
1210 | |||
1211 | /* Initialize the task queue */ | ||
1212 | chan->tq_working=0; | ||
1213 | |||
1214 | INIT_WORK(&chan->common.wanpipe_work, (void *)fr_bh, dev); | ||
1215 | |||
1216 | /* Allocate and initialize BH circular buffer */ | ||
1217 | chan->bh_head = kmalloc((sizeof(bh_data_t)*MAX_BH_BUFF),GFP_ATOMIC); | ||
1218 | memset(chan->bh_head,0,(sizeof(bh_data_t)*MAX_BH_BUFF)); | ||
1219 | atomic_set(&chan->bh_buff_used, 0); | ||
1220 | |||
1221 | netif_start_queue(dev); | ||
1222 | |||
1223 | wanpipe_open(card); | ||
1224 | do_gettimeofday( &tv ); | ||
1225 | chan->router_start_time = tv.tv_sec; | ||
1226 | |||
1227 | if (test_bit(0,&chan->config_dlci)){ | ||
1228 | trigger_config_fr (card); | ||
1229 | }else if (chan->inarp == INARP_REQUEST){ | ||
1230 | trigger_fr_arp(dev); | ||
1231 | } | ||
1232 | |||
1233 | return err; | ||
1234 | } | ||
1235 | |||
1236 | /*============================================================================ | ||
1237 | * Close network interface. | ||
1238 | * o if this is the last open, then disable communications and interrupts. | ||
1239 | * o reset flags. | ||
1240 | */ | ||
1241 | static int if_close(struct net_device* dev) | ||
1242 | { | ||
1243 | fr_channel_t* chan = dev->priv; | ||
1244 | sdla_t* card = chan->card; | ||
1245 | |||
1246 | if (chan->inarp == INARP_CONFIGURED) { | ||
1247 | chan->inarp = INARP_REQUEST; | ||
1248 | } | ||
1249 | |||
1250 | netif_stop_queue(dev); | ||
1251 | wanpipe_close(card); | ||
1252 | |||
1253 | return 0; | ||
1254 | } | ||
1255 | |||
1256 | /*============================================================================ | ||
1257 | * Re-build media header. | ||
1258 | * | ||
1259 | * Return: 1 physical address resolved. | ||
1260 | * 0 physical address not resolved | ||
1261 | */ | ||
1262 | static int if_rebuild_hdr (struct sk_buff* skb) | ||
1263 | { | ||
1264 | struct net_device *dev = skb->dev; | ||
1265 | fr_channel_t* chan = dev->priv; | ||
1266 | sdla_t* card = chan->card; | ||
1267 | |||
1268 | printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n", | ||
1269 | card->devname, dev->name); | ||
1270 | return 1; | ||
1271 | } | ||
1272 | |||
1273 | /*============================================================================ | ||
1274 | * Handle transmit timeout event from netif watchdog | ||
1275 | */ | ||
1276 | static void if_tx_timeout(struct net_device *dev) | ||
1277 | { | ||
1278 | fr_channel_t* chan = dev->priv; | ||
1279 | sdla_t *card = chan->card; | ||
1280 | |||
1281 | /* If our device stays busy for at least 5 seconds then we will | ||
1282 | * kick start the device by making dev->tbusy = 0. We expect | ||
1283 | * that our device never stays busy more than 5 seconds. So this | ||
1284 | * is only used as a last resort. | ||
1285 | */ | ||
1286 | |||
1287 | chan->drvstats_if_send.if_send_tbusy++; | ||
1288 | ++chan->ifstats.collisions; | ||
1289 | |||
1290 | printk (KERN_INFO "%s: Transmit timed out on %s\n", | ||
1291 | card->devname, dev->name); | ||
1292 | chan->drvstats_if_send.if_send_tbusy_timeout++; | ||
1293 | netif_wake_queue (dev); | ||
1294 | |||
1295 | } | ||
1296 | |||
1297 | |||
1298 | /*============================================================================ | ||
1299 | * Send a packet on a network interface. | ||
1300 | * o set tbusy flag (marks start of the transmission) to block a timer-based | ||
1301 | * transmit from overlapping. | ||
1302 | * o set critical flag when accessing board. | ||
1303 | * o check link state. If link is not up, then drop the packet. | ||
1304 | * o check channel status. If it's down then initiate a call. | ||
1305 | * o pass a packet to corresponding WAN device. | ||
1306 | * o free socket buffer | ||
1307 | * | ||
1308 | * Return: 0 complete (socket buffer must be freed) | ||
1309 | * non-0 packet may be re-transmitted (tbusy must be set) | ||
1310 | * | ||
1311 | * Notes: | ||
1312 | * 1. This routine is called either by the protocol stack or by the "net | ||
1313 | * bottom half" (with interrupts enabled). | ||
1314 | * | ||
1315 | * 2. Using netif_start_queue() and netif_stop_queue() | ||
1316 | * will inhibit further transmit requests from the protocol stack | ||
1317 | * and can be used for flow control with protocol layer. | ||
1318 | */ | ||
1319 | static int if_send(struct sk_buff* skb, struct net_device* dev) | ||
1320 | { | ||
1321 | fr_channel_t* chan = dev->priv; | ||
1322 | sdla_t* card = chan->card; | ||
1323 | int err; | ||
1324 | unsigned char *sendpacket; | ||
1325 | fr508_flags_t* adptr_flags = card->flags; | ||
1326 | int udp_type; | ||
1327 | long delay_tx_queued = 0; | ||
1328 | unsigned long smp_flags=0; | ||
1329 | unsigned char attr = 0; | ||
1330 | |||
1331 | chan->drvstats_if_send.if_send_entry++; | ||
1332 | |||
1333 | netif_stop_queue(dev); | ||
1334 | |||
1335 | if (skb == NULL) { | ||
1336 | /* if we get here, some higher layer thinks we've missed an | ||
1337 | * tx-done interrupt. | ||
1338 | */ | ||
1339 | printk(KERN_INFO "%s: interface %s got kicked!\n", | ||
1340 | card->devname, dev->name); | ||
1341 | chan->drvstats_if_send.if_send_skb_null ++; | ||
1342 | |||
1343 | netif_wake_queue(dev); | ||
1344 | return 0; | ||
1345 | } | ||
1346 | |||
1347 | /* If a peripheral task is running just drop packets */ | ||
1348 | if (test_bit(PERI_CRIT, &card->wandev.critical)){ | ||
1349 | |||
1350 | printk(KERN_INFO "%s: Critical in if_send(): Peripheral running!\n", | ||
1351 | card->devname); | ||
1352 | |||
1353 | dev_kfree_skb_any(skb); | ||
1354 | netif_start_queue(dev); | ||
1355 | return 0; | ||
1356 | } | ||
1357 | |||
1358 | /* We must set the 'tbusy' flag if we already have a packet queued for | ||
1359 | transmission in the transmit interrupt handler. However, we must | ||
1360 | ensure that the transmit interrupt does not reset the 'tbusy' flag | ||
1361 | just before we set it, as this will result in a "transmit timeout". | ||
1362 | */ | ||
1363 | set_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); | ||
1364 | if(chan->transmit_length) { | ||
1365 | netif_stop_queue(dev); | ||
1366 | chan->tick_counter = jiffies; | ||
1367 | clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); | ||
1368 | return 1; | ||
1369 | } | ||
1370 | clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); | ||
1371 | |||
1372 | /* Move the if_header() code to here. By inserting frame | ||
1373 | * relay header in if_header() we would break the | ||
1374 | * tcpdump and other packet sniffers */ | ||
1375 | chan->fr_header_len = setup_fr_header(skb,dev,chan->common.usedby); | ||
1376 | if (chan->fr_header_len < 0 ){ | ||
1377 | ++chan->ifstats.tx_dropped; | ||
1378 | ++card->wandev.stats.tx_dropped; | ||
1379 | |||
1380 | dev_kfree_skb_any(skb); | ||
1381 | netif_start_queue(dev); | ||
1382 | return 0; | ||
1383 | } | ||
1384 | |||
1385 | sendpacket = skb->data; | ||
1386 | |||
1387 | udp_type = udp_pkt_type(skb, card); | ||
1388 | |||
1389 | if(udp_type != UDP_INVALID_TYPE) { | ||
1390 | if(store_udp_mgmt_pkt(udp_type, UDP_PKT_FRM_STACK, card, skb, | ||
1391 | chan->dlci)) { | ||
1392 | adptr_flags->imask |= FR_INTR_TIMER; | ||
1393 | if (udp_type == UDP_FPIPE_TYPE){ | ||
1394 | chan->drvstats_if_send. | ||
1395 | if_send_PIPE_request ++; | ||
1396 | } | ||
1397 | } | ||
1398 | netif_start_queue(dev); | ||
1399 | return 0; | ||
1400 | } | ||
1401 | |||
1402 | //FIXME: can we do better than sendpacket[2]? | ||
1403 | if ((chan->common.usedby == WANPIPE) && (sendpacket[2] == 0x45)) { | ||
1404 | |||
1405 | /* check to see if the source IP address is a broadcast or */ | ||
1406 | /* multicast IP address */ | ||
1407 | if(chk_bcast_mcast_addr(card, dev, skb)){ | ||
1408 | ++chan->ifstats.tx_dropped; | ||
1409 | ++card->wandev.stats.tx_dropped; | ||
1410 | dev_kfree_skb_any(skb); | ||
1411 | netif_start_queue(dev); | ||
1412 | return 0; | ||
1413 | } | ||
1414 | } | ||
1415 | |||
1416 | |||
1417 | /* Lock the S514/S508 card: SMP Supported */ | ||
1418 | s508_s514_lock(card,&smp_flags); | ||
1419 | |||
1420 | if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) { | ||
1421 | |||
1422 | chan->drvstats_if_send.if_send_critical_non_ISR ++; | ||
1423 | chan->ifstats.tx_dropped ++; | ||
1424 | printk(KERN_INFO "%s Critical in IF_SEND: if_send() already running!\n", | ||
1425 | card->devname); | ||
1426 | goto if_send_start_and_exit; | ||
1427 | } | ||
1428 | |||
1429 | /* API packet check: minimum packet size must be greater than | ||
1430 | * 16 byte API header */ | ||
1431 | if((chan->common.usedby == API) && (skb->len <= sizeof(api_tx_hdr_t))) { | ||
1432 | ++chan->ifstats.tx_dropped; | ||
1433 | ++card->wandev.stats.tx_dropped; | ||
1434 | |||
1435 | |||
1436 | goto if_send_start_and_exit; | ||
1437 | |||
1438 | }else{ | ||
1439 | /* During API transmission, get rid of the API header */ | ||
1440 | if (chan->common.usedby == API) { | ||
1441 | api_tx_hdr_t* api_tx_hdr; | ||
1442 | api_tx_hdr = (api_tx_hdr_t*)&skb->data[0x00]; | ||
1443 | attr = api_tx_hdr->attr; | ||
1444 | skb_pull(skb,sizeof(api_tx_hdr_t)); | ||
1445 | } | ||
1446 | } | ||
1447 | |||
1448 | if (card->wandev.state != WAN_CONNECTED) { | ||
1449 | chan->drvstats_if_send.if_send_wan_disconnected ++; | ||
1450 | ++chan->ifstats.tx_dropped; | ||
1451 | ++card->wandev.stats.tx_dropped; | ||
1452 | |||
1453 | } else if (chan->common.state != WAN_CONNECTED) { | ||
1454 | chan->drvstats_if_send.if_send_dlci_disconnected ++; | ||
1455 | |||
1456 | /* Update the DLCI state in timer interrupt */ | ||
1457 | card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UPDATE_STATE; | ||
1458 | adptr_flags->imask |= FR_INTR_TIMER; | ||
1459 | |||
1460 | ++chan->ifstats.tx_dropped; | ||
1461 | ++card->wandev.stats.tx_dropped; | ||
1462 | |||
1463 | } else if (!is_tx_ready(card, chan)) { | ||
1464 | /* No tx buffers available, store for delayed transmit */ | ||
1465 | if (!setup_for_delayed_transmit(dev, skb)){ | ||
1466 | set_bit(1,&delay_tx_queued); | ||
1467 | } | ||
1468 | chan->drvstats_if_send.if_send_no_bfrs++; | ||
1469 | |||
1470 | } else if (!skb->protocol) { | ||
1471 | /* No protocols drop packet */ | ||
1472 | chan->drvstats_if_send.if_send_protocol_error ++; | ||
1473 | ++card->wandev.stats.tx_errors; | ||
1474 | |||
1475 | } else if (test_bit(ARP_CRIT,&card->wandev.critical)){ | ||
1476 | /* We are trying to send an ARP Packet, block IP data until | ||
1477 | * ARP is sent */ | ||
1478 | ++chan->ifstats.tx_dropped; | ||
1479 | ++card->wandev.stats.tx_dropped; | ||
1480 | |||
1481 | } else { | ||
1482 | //FIXME: IPX is not implemented in this version of Frame Relay ? | ||
1483 | if((chan->common.usedby == WANPIPE) && | ||
1484 | sendpacket[1] == 0x00 && | ||
1485 | sendpacket[2] == 0x80 && | ||
1486 | sendpacket[6] == 0x81 && | ||
1487 | sendpacket[7] == 0x37) { | ||
1488 | |||
1489 | if( chan->enable_IPX ) { | ||
1490 | switch_net_numbers(sendpacket, | ||
1491 | chan->network_number, 0); | ||
1492 | } else { | ||
1493 | //FIXME: Take this out when IPX is fixed | ||
1494 | printk(KERN_INFO | ||
1495 | "%s: WARNING: Unsupported IPX data in send, packet dropped\n", | ||
1496 | card->devname); | ||
1497 | } | ||
1498 | |||
1499 | }else{ | ||
1500 | err = fr_send_data_header(card, chan->dlci, attr, skb->len, skb->data, chan->fr_header_len); | ||
1501 | if (err) { | ||
1502 | switch(err) { | ||
1503 | case FRRES_CIR_OVERFLOW: | ||
1504 | case FRRES_BUFFER_OVERFLOW: | ||
1505 | if (!setup_for_delayed_transmit(dev, skb)){ | ||
1506 | set_bit(1,&delay_tx_queued); | ||
1507 | } | ||
1508 | chan->drvstats_if_send. | ||
1509 | if_send_adptr_bfrs_full ++; | ||
1510 | break; | ||
1511 | |||
1512 | case FRRES_TOO_LONG: | ||
1513 | if (net_ratelimit()){ | ||
1514 | printk(KERN_INFO | ||
1515 | "%s: Error: Frame too long, transmission failed %i\n", | ||
1516 | card->devname, (unsigned int)skb->len); | ||
1517 | } | ||
1518 | /* Drop down to default */ | ||
1519 | default: | ||
1520 | chan->drvstats_if_send. | ||
1521 | if_send_dlci_disconnected ++; | ||
1522 | ++chan->ifstats.tx_dropped; | ||
1523 | ++card->wandev.stats.tx_dropped; | ||
1524 | break; | ||
1525 | } | ||
1526 | } else { | ||
1527 | chan->drvstats_if_send. | ||
1528 | if_send_bfr_passed_to_adptr++; | ||
1529 | ++chan->ifstats.tx_packets; | ||
1530 | ++card->wandev.stats.tx_packets; | ||
1531 | |||
1532 | chan->ifstats.tx_bytes += skb->len; | ||
1533 | card->wandev.stats.tx_bytes += skb->len; | ||
1534 | dev->trans_start = jiffies; | ||
1535 | } | ||
1536 | } | ||
1537 | } | ||
1538 | |||
1539 | if_send_start_and_exit: | ||
1540 | |||
1541 | netif_start_queue(dev); | ||
1542 | |||
1543 | /* If we queued the packet for transmission, we must not | ||
1544 | * deallocate it. The packet is unlinked from the IP stack | ||
1545 | * not copied. Therefore, we must keep the original packet */ | ||
1546 | if (!test_bit(1,&delay_tx_queued)) { | ||
1547 | dev_kfree_skb_any(skb); | ||
1548 | }else{ | ||
1549 | adptr_flags->imask |= FR_INTR_TXRDY; | ||
1550 | card->u.f.tx_interrupts_pending ++; | ||
1551 | } | ||
1552 | |||
1553 | clear_bit(SEND_CRIT, (void*)&card->wandev.critical); | ||
1554 | |||
1555 | s508_s514_unlock(card,&smp_flags); | ||
1556 | |||
1557 | return 0; | ||
1558 | } | ||
1559 | |||
1560 | |||
1561 | |||
1562 | /*============================================================================ | ||
1563 | * Setup so that a frame can be transmitted on the occurrence of a transmit | ||
1564 | * interrupt. | ||
1565 | */ | ||
1566 | static int setup_for_delayed_transmit(struct net_device* dev, | ||
1567 | struct sk_buff *skb) | ||
1568 | { | ||
1569 | fr_channel_t* chan = dev->priv; | ||
1570 | sdla_t* card = chan->card; | ||
1571 | fr_dlci_interface_t* dlci_interface; | ||
1572 | int len = skb->len; | ||
1573 | |||
1574 | /* Check that the dlci is properly configured, | ||
1575 | * before using tx interrupt */ | ||
1576 | if (!chan->dlci_int_interface){ | ||
1577 | if (net_ratelimit()){ | ||
1578 | printk(KERN_INFO | ||
1579 | "%s: ERROR on DLCI %i: Not configured properly !\n", | ||
1580 | card->devname, chan->dlci); | ||
1581 | printk(KERN_INFO "%s: Please contact Sangoma Technologies\n", | ||
1582 | card->devname); | ||
1583 | } | ||
1584 | return 1; | ||
1585 | } | ||
1586 | |||
1587 | dlci_interface = chan->dlci_int_interface; | ||
1588 | |||
1589 | if(chan->transmit_length) { | ||
1590 | printk(KERN_INFO "%s: Big mess in setup_for_del...\n", | ||
1591 | card->devname); | ||
1592 | return 1; | ||
1593 | } | ||
1594 | |||
1595 | if(len > FR_MAX_NO_DATA_BYTES_IN_FRAME) { | ||
1596 | //FIXME: increment some statistic */ | ||
1597 | return 1; | ||
1598 | } | ||
1599 | |||
1600 | chan->transmit_length = len; | ||
1601 | chan->delay_skb = skb; | ||
1602 | |||
1603 | dlci_interface->gen_interrupt |= FR_INTR_TXRDY; | ||
1604 | dlci_interface->packet_length = len; | ||
1605 | |||
1606 | /* Turn on TX interrupt at the end of if_send */ | ||
1607 | return 0; | ||
1608 | } | ||
1609 | |||
1610 | |||
1611 | /*============================================================================ | ||
1612 | * Check to see if the packet to be transmitted contains a broadcast or | ||
1613 | * multicast source IP address. | ||
1614 | * Return 0 if not broadcast/multicast address, otherwise return 1. | ||
1615 | */ | ||
1616 | |||
1617 | static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev, | ||
1618 | struct sk_buff *skb) | ||
1619 | { | ||
1620 | u32 src_ip_addr; | ||
1621 | u32 broadcast_ip_addr = 0; | ||
1622 | struct in_device *in_dev; | ||
1623 | fr_channel_t* chan = dev->priv; | ||
1624 | |||
1625 | /* read the IP source address from the outgoing packet */ | ||
1626 | src_ip_addr = *(u32 *)(skb->data + 14); | ||
1627 | |||
1628 | /* read the IP broadcast address for the device */ | ||
1629 | in_dev = dev->ip_ptr; | ||
1630 | if(in_dev != NULL) { | ||
1631 | struct in_ifaddr *ifa= in_dev->ifa_list; | ||
1632 | if(ifa != NULL) | ||
1633 | broadcast_ip_addr = ifa->ifa_broadcast; | ||
1634 | else | ||
1635 | return 0; | ||
1636 | } | ||
1637 | |||
1638 | /* check if the IP Source Address is a Broadcast address */ | ||
1639 | if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { | ||
1640 | printk(KERN_INFO | ||
1641 | "%s: Broadcast Source Address silently discarded\n", | ||
1642 | card->devname); | ||
1643 | return 1; | ||
1644 | } | ||
1645 | |||
1646 | /* check if the IP Source Address is a Multicast address */ | ||
1647 | if((chan->mc == WANOPT_NO) && (ntohl(src_ip_addr) >= 0xE0000001) && | ||
1648 | (ntohl(src_ip_addr) <= 0xFFFFFFFE)) { | ||
1649 | printk(KERN_INFO | ||
1650 | "%s: Multicast Source Address silently discarded\n", | ||
1651 | card->devname); | ||
1652 | return 1; | ||
1653 | } | ||
1654 | |||
1655 | return 0; | ||
1656 | } | ||
1657 | |||
1658 | /*============================================================================ | ||
1659 | * Reply to UDP Management system. | ||
1660 | * Return nothing. | ||
1661 | */ | ||
1662 | static int reply_udp( unsigned char *data, unsigned int mbox_len ) | ||
1663 | { | ||
1664 | unsigned short len, udp_length, temp, ip_length; | ||
1665 | unsigned long ip_temp; | ||
1666 | int even_bound = 0; | ||
1667 | |||
1668 | |||
1669 | fr_udp_pkt_t *fr_udp_pkt = (fr_udp_pkt_t *)data; | ||
1670 | |||
1671 | /* Set length of packet */ | ||
1672 | len = //sizeof(fr_encap_hdr_t)+ | ||
1673 | sizeof(ip_pkt_t)+ | ||
1674 | sizeof(udp_pkt_t)+ | ||
1675 | sizeof(wp_mgmt_t)+ | ||
1676 | sizeof(cblock_t)+ | ||
1677 | mbox_len; | ||
1678 | |||
1679 | |||
1680 | /* fill in UDP reply */ | ||
1681 | fr_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; | ||
1682 | |||
1683 | /* fill in UDP length */ | ||
1684 | udp_length = sizeof(udp_pkt_t)+ | ||
1685 | sizeof(wp_mgmt_t)+ | ||
1686 | sizeof(cblock_t)+ | ||
1687 | mbox_len; | ||
1688 | |||
1689 | |||
1690 | /* put it on an even boundary */ | ||
1691 | if ( udp_length & 0x0001 ) { | ||
1692 | udp_length += 1; | ||
1693 | len += 1; | ||
1694 | even_bound = 1; | ||
1695 | } | ||
1696 | |||
1697 | temp = (udp_length<<8)|(udp_length>>8); | ||
1698 | fr_udp_pkt->udp_pkt.udp_length = temp; | ||
1699 | |||
1700 | /* swap UDP ports */ | ||
1701 | temp = fr_udp_pkt->udp_pkt.udp_src_port; | ||
1702 | fr_udp_pkt->udp_pkt.udp_src_port = | ||
1703 | fr_udp_pkt->udp_pkt.udp_dst_port; | ||
1704 | fr_udp_pkt->udp_pkt.udp_dst_port = temp; | ||
1705 | |||
1706 | |||
1707 | |||
1708 | /* add UDP pseudo header */ | ||
1709 | temp = 0x1100; | ||
1710 | *((unsigned short *) | ||
1711 | (fr_udp_pkt->data+mbox_len+even_bound)) = temp; | ||
1712 | temp = (udp_length<<8)|(udp_length>>8); | ||
1713 | *((unsigned short *) | ||
1714 | (fr_udp_pkt->data+mbox_len+even_bound+2)) = temp; | ||
1715 | |||
1716 | /* calculate UDP checksum */ | ||
1717 | fr_udp_pkt->udp_pkt.udp_checksum = 0; | ||
1718 | |||
1719 | fr_udp_pkt->udp_pkt.udp_checksum = | ||
1720 | calc_checksum(&data[UDP_OFFSET/*+sizeof(fr_encap_hdr_t)*/], | ||
1721 | udp_length+UDP_OFFSET); | ||
1722 | |||
1723 | /* fill in IP length */ | ||
1724 | ip_length = udp_length + sizeof(ip_pkt_t); | ||
1725 | temp = (ip_length<<8)|(ip_length>>8); | ||
1726 | fr_udp_pkt->ip_pkt.total_length = temp; | ||
1727 | |||
1728 | /* swap IP addresses */ | ||
1729 | ip_temp = fr_udp_pkt->ip_pkt.ip_src_address; | ||
1730 | fr_udp_pkt->ip_pkt.ip_src_address = | ||
1731 | fr_udp_pkt->ip_pkt.ip_dst_address; | ||
1732 | fr_udp_pkt->ip_pkt.ip_dst_address = ip_temp; | ||
1733 | |||
1734 | |||
1735 | /* fill in IP checksum */ | ||
1736 | fr_udp_pkt->ip_pkt.hdr_checksum = 0; | ||
1737 | fr_udp_pkt->ip_pkt.hdr_checksum = | ||
1738 | calc_checksum(&data[/*sizeof(fr_encap_hdr_t)*/0], | ||
1739 | sizeof(ip_pkt_t)); | ||
1740 | |||
1741 | return len; | ||
1742 | } /* reply_udp */ | ||
1743 | |||
1744 | unsigned short calc_checksum (char *data, int len) | ||
1745 | { | ||
1746 | unsigned short temp; | ||
1747 | unsigned long sum=0; | ||
1748 | int i; | ||
1749 | |||
1750 | for( i = 0; i <len; i+=2 ) { | ||
1751 | memcpy(&temp,&data[i],2); | ||
1752 | sum += (unsigned long)temp; | ||
1753 | } | ||
1754 | |||
1755 | while (sum >> 16 ) { | ||
1756 | sum = (sum & 0xffffUL) + (sum >> 16); | ||
1757 | } | ||
1758 | |||
1759 | temp = (unsigned short)sum; | ||
1760 | temp = ~temp; | ||
1761 | |||
1762 | if( temp == 0 ) | ||
1763 | temp = 0xffff; | ||
1764 | |||
1765 | return temp; | ||
1766 | } | ||
1767 | |||
1768 | /* | ||
1769 | If incoming is 0 (outgoing)- if the net numbers is ours make it 0 | ||
1770 | if incoming is 1 - if the net number is 0 make it ours | ||
1771 | |||
1772 | */ | ||
1773 | static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming) | ||
1774 | { | ||
1775 | unsigned long pnetwork_number; | ||
1776 | |||
1777 | pnetwork_number = (unsigned long)((sendpacket[14] << 24) + | ||
1778 | (sendpacket[15] << 16) + (sendpacket[16] << 8) + | ||
1779 | sendpacket[17]); | ||
1780 | |||
1781 | if (!incoming) { | ||
1782 | /* If the destination network number is ours, make it 0 */ | ||
1783 | if( pnetwork_number == network_number) { | ||
1784 | sendpacket[14] = sendpacket[15] = sendpacket[16] = | ||
1785 | sendpacket[17] = 0x00; | ||
1786 | } | ||
1787 | } else { | ||
1788 | /* If the incoming network is 0, make it ours */ | ||
1789 | if( pnetwork_number == 0) { | ||
1790 | sendpacket[14] = (unsigned char)(network_number >> 24); | ||
1791 | sendpacket[15] = (unsigned char)((network_number & | ||
1792 | 0x00FF0000) >> 16); | ||
1793 | sendpacket[16] = (unsigned char)((network_number & | ||
1794 | 0x0000FF00) >> 8); | ||
1795 | sendpacket[17] = (unsigned char)(network_number & | ||
1796 | 0x000000FF); | ||
1797 | } | ||
1798 | } | ||
1799 | |||
1800 | |||
1801 | pnetwork_number = (unsigned long)((sendpacket[26] << 24) + | ||
1802 | (sendpacket[27] << 16) + (sendpacket[28] << 8) + | ||
1803 | sendpacket[29]); | ||
1804 | |||
1805 | if( !incoming ) { | ||
1806 | /* If the source network is ours, make it 0 */ | ||
1807 | if( pnetwork_number == network_number) { | ||
1808 | sendpacket[26] = sendpacket[27] = sendpacket[28] = | ||
1809 | sendpacket[29] = 0x00; | ||
1810 | } | ||
1811 | } else { | ||
1812 | /* If the source network is 0, make it ours */ | ||
1813 | if( pnetwork_number == 0 ) { | ||
1814 | sendpacket[26] = (unsigned char)(network_number >> 24); | ||
1815 | sendpacket[27] = (unsigned char)((network_number & | ||
1816 | 0x00FF0000) >> 16); | ||
1817 | sendpacket[28] = (unsigned char)((network_number & | ||
1818 | 0x0000FF00) >> 8); | ||
1819 | sendpacket[29] = (unsigned char)(network_number & | ||
1820 | 0x000000FF); | ||
1821 | } | ||
1822 | } | ||
1823 | } /* switch_net_numbers */ | ||
1824 | |||
1825 | /*============================================================================ | ||
1826 | * Get ethernet-style interface statistics. | ||
1827 | * Return a pointer to struct enet_statistics. | ||
1828 | */ | ||
1829 | static struct net_device_stats *if_stats(struct net_device *dev) | ||
1830 | { | ||
1831 | fr_channel_t* chan = dev->priv; | ||
1832 | |||
1833 | if(chan == NULL) | ||
1834 | return NULL; | ||
1835 | |||
1836 | return &chan->ifstats; | ||
1837 | } | ||
1838 | |||
1839 | /****** Interrupt Handlers **************************************************/ | ||
1840 | |||
1841 | /*============================================================================ | ||
1842 | * fr_isr: S508 frame relay interrupt service routine. | ||
1843 | * | ||
1844 | * Description: | ||
1845 | * Frame relay main interrupt service route. This | ||
1846 | * function check the interrupt type and takes | ||
1847 | * the appropriate action. | ||
1848 | */ | ||
1849 | static void fr_isr (sdla_t* card) | ||
1850 | { | ||
1851 | fr508_flags_t* flags = card->flags; | ||
1852 | char *ptr = &flags->iflag; | ||
1853 | int i,err; | ||
1854 | fr_mbox_t* mbox = card->mbox; | ||
1855 | |||
1856 | /* This flag prevents nesting of interrupts. See sdla_isr() routine | ||
1857 | * in sdlamain.c. */ | ||
1858 | card->in_isr = 1; | ||
1859 | |||
1860 | ++card->statistics.isr_entry; | ||
1861 | |||
1862 | |||
1863 | /* All peripheral (configuraiton, re-configuration) events | ||
1864 | * take presidence over the ISR. Thus, retrigger */ | ||
1865 | if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { | ||
1866 | ++card->statistics.isr_already_critical; | ||
1867 | goto fr_isr_exit; | ||
1868 | } | ||
1869 | |||
1870 | if(card->hw.type != SDLA_S514) { | ||
1871 | if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) { | ||
1872 | printk(KERN_INFO "%s: Critical while in ISR: If Send Running!\n", | ||
1873 | card->devname); | ||
1874 | ++card->statistics.isr_already_critical; | ||
1875 | goto fr_isr_exit; | ||
1876 | } | ||
1877 | } | ||
1878 | |||
1879 | switch (flags->iflag) { | ||
1880 | |||
1881 | case FR_INTR_RXRDY: /* receive interrupt */ | ||
1882 | ++card->statistics.isr_rx; | ||
1883 | rx_intr(card); | ||
1884 | break; | ||
1885 | |||
1886 | |||
1887 | case FR_INTR_TXRDY: /* transmit interrupt */ | ||
1888 | ++ card->statistics.isr_tx; | ||
1889 | tx_intr(card); | ||
1890 | break; | ||
1891 | |||
1892 | case FR_INTR_READY: | ||
1893 | Intr_test_counter++; | ||
1894 | ++card->statistics.isr_intr_test; | ||
1895 | break; | ||
1896 | |||
1897 | case FR_INTR_DLC: /* Event interrupt occurred */ | ||
1898 | mbox->cmd.command = FR_READ_STATUS; | ||
1899 | mbox->cmd.length = 0; | ||
1900 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
1901 | if (err) | ||
1902 | fr_event(card, err, mbox); | ||
1903 | break; | ||
1904 | |||
1905 | case FR_INTR_TIMER: /* Timer interrupt */ | ||
1906 | timer_intr(card); | ||
1907 | break; | ||
1908 | |||
1909 | default: | ||
1910 | ++card->statistics.isr_spurious; | ||
1911 | spur_intr(card); | ||
1912 | printk(KERN_INFO "%s: Interrupt Type 0x%02X!\n", | ||
1913 | card->devname, flags->iflag); | ||
1914 | |||
1915 | printk(KERN_INFO "%s: ID Bytes = ",card->devname); | ||
1916 | for(i = 0; i < 8; i ++) | ||
1917 | printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); | ||
1918 | printk(KERN_INFO "\n"); | ||
1919 | |||
1920 | break; | ||
1921 | } | ||
1922 | |||
1923 | fr_isr_exit: | ||
1924 | |||
1925 | card->in_isr = 0; | ||
1926 | flags->iflag = 0; | ||
1927 | return; | ||
1928 | } | ||
1929 | |||
1930 | |||
1931 | |||
1932 | /*=========================================================== | ||
1933 | * rx_intr Receive interrupt handler. | ||
1934 | * | ||
1935 | * Description | ||
1936 | * Upon receiveing an interrupt: | ||
1937 | * 1. Check that the firmware is in sync with | ||
1938 | * the driver. | ||
1939 | * 2. Find an appropriate network interface | ||
1940 | * based on the received dlci number. | ||
1941 | * 3. Check that the netowrk interface exists | ||
1942 | * and that it's setup properly. | ||
1943 | * 4. Copy the data into an skb buffer. | ||
1944 | * 5. Check the packet type and take | ||
1945 | * appropriate acton: UPD, API, ARP or Data. | ||
1946 | */ | ||
1947 | |||
1948 | static void rx_intr (sdla_t* card) | ||
1949 | { | ||
1950 | fr_rx_buf_ctl_t* frbuf = card->rxmb; | ||
1951 | fr508_flags_t* flags = card->flags; | ||
1952 | fr_channel_t* chan; | ||
1953 | char *ptr = &flags->iflag; | ||
1954 | struct sk_buff* skb; | ||
1955 | struct net_device* dev; | ||
1956 | void* buf; | ||
1957 | unsigned dlci, len, offs, len_incl_hdr; | ||
1958 | int i, udp_type; | ||
1959 | |||
1960 | |||
1961 | /* Check that firmware buffers are in sync */ | ||
1962 | if (frbuf->flag != 0x01) { | ||
1963 | |||
1964 | printk(KERN_INFO | ||
1965 | "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", | ||
1966 | card->devname, (unsigned)frbuf, frbuf->flag); | ||
1967 | |||
1968 | printk(KERN_INFO "%s: ID Bytes = ",card->devname); | ||
1969 | for(i = 0; i < 8; i ++) | ||
1970 | printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); | ||
1971 | printk(KERN_INFO "\n"); | ||
1972 | |||
1973 | ++card->statistics.rx_intr_corrupt_rx_bfr; | ||
1974 | |||
1975 | /* Bug Fix: Mar 6 2000 | ||
1976 | * If we get a corrupted mailbox, it means that driver | ||
1977 | * is out of sync with the firmware. There is no recovery. | ||
1978 | * If we don't turn off all interrupts for this card | ||
1979 | * the machine will crash. | ||
1980 | */ | ||
1981 | printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname); | ||
1982 | printk(KERN_INFO "Please contact Sangoma Technologies !\n"); | ||
1983 | fr_set_intr_mode(card, 0, 0, 0); | ||
1984 | return; | ||
1985 | } | ||
1986 | |||
1987 | len = frbuf->length; | ||
1988 | dlci = frbuf->dlci; | ||
1989 | offs = frbuf->offset; | ||
1990 | |||
1991 | /* Find the network interface for this packet */ | ||
1992 | dev = find_channel(card, dlci); | ||
1993 | |||
1994 | |||
1995 | /* Check that the network interface is active and | ||
1996 | * properly setup */ | ||
1997 | if (dev == NULL) { | ||
1998 | if( net_ratelimit()) { | ||
1999 | printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n", | ||
2000 | card->devname, dlci); | ||
2001 | } | ||
2002 | ++card->statistics.rx_intr_on_orphaned_DLCI; | ||
2003 | ++card->wandev.stats.rx_dropped; | ||
2004 | goto rx_done; | ||
2005 | } | ||
2006 | |||
2007 | if ((chan = dev->priv) == NULL){ | ||
2008 | if( net_ratelimit()) { | ||
2009 | printk(KERN_INFO "%s: received data on unconfigured DLCI %d!\n", | ||
2010 | card->devname, dlci); | ||
2011 | } | ||
2012 | ++card->statistics.rx_intr_on_orphaned_DLCI; | ||
2013 | ++card->wandev.stats.rx_dropped; | ||
2014 | goto rx_done; | ||
2015 | } | ||
2016 | |||
2017 | skb = dev_alloc_skb(len); | ||
2018 | |||
2019 | if (!netif_running(dev) || (skb == NULL)){ | ||
2020 | |||
2021 | ++chan->ifstats.rx_dropped; | ||
2022 | |||
2023 | if(skb == NULL) { | ||
2024 | if (net_ratelimit()) { | ||
2025 | printk(KERN_INFO | ||
2026 | "%s: no socket buffers available!\n", | ||
2027 | card->devname); | ||
2028 | } | ||
2029 | chan->drvstats_rx_intr.rx_intr_no_socket ++; | ||
2030 | } | ||
2031 | |||
2032 | if (!netif_running(dev)){ | ||
2033 | chan->drvstats_rx_intr. | ||
2034 | rx_intr_dev_not_started ++; | ||
2035 | if (skb){ | ||
2036 | dev_kfree_skb_any(skb); | ||
2037 | } | ||
2038 | } | ||
2039 | goto rx_done; | ||
2040 | } | ||
2041 | |||
2042 | /* Copy data from the board into the socket buffer */ | ||
2043 | if ((offs + len) > card->u.f.rx_top + 1) { | ||
2044 | unsigned tmp = card->u.f.rx_top - offs + 1; | ||
2045 | |||
2046 | buf = skb_put(skb, tmp); | ||
2047 | sdla_peek(&card->hw, offs, buf, tmp); | ||
2048 | offs = card->u.f.rx_base; | ||
2049 | len -= tmp; | ||
2050 | } | ||
2051 | |||
2052 | buf = skb_put(skb, len); | ||
2053 | sdla_peek(&card->hw, offs, buf, len); | ||
2054 | |||
2055 | |||
2056 | /* We got the packet from the bard. | ||
2057 | * Check the packet type and take appropriate action */ | ||
2058 | |||
2059 | udp_type = udp_pkt_type( skb, card ); | ||
2060 | |||
2061 | if(udp_type != UDP_INVALID_TYPE) { | ||
2062 | |||
2063 | /* UDP Debug packet received, store the | ||
2064 | * packet and handle it in timer interrupt */ | ||
2065 | |||
2066 | skb_pull(skb, 1); | ||
2067 | if (wanrouter_type_trans(skb, dev)){ | ||
2068 | if(store_udp_mgmt_pkt(udp_type,UDP_PKT_FRM_NETWORK,card,skb,dlci)){ | ||
2069 | |||
2070 | flags->imask |= FR_INTR_TIMER; | ||
2071 | |||
2072 | if (udp_type == UDP_FPIPE_TYPE){ | ||
2073 | ++chan->drvstats_rx_intr.rx_intr_PIPE_request; | ||
2074 | } | ||
2075 | } | ||
2076 | } | ||
2077 | |||
2078 | }else if (chan->common.usedby == API) { | ||
2079 | |||
2080 | /* We are in API mode. | ||
2081 | * Add an API header to the RAW packet | ||
2082 | * and queue it into a circular buffer. | ||
2083 | * Then kick the fr_bh() bottom half handler */ | ||
2084 | |||
2085 | api_rx_hdr_t* api_rx_hdr; | ||
2086 | chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack ++; | ||
2087 | chan->ifstats.rx_packets ++; | ||
2088 | card->wandev.stats.rx_packets ++; | ||
2089 | |||
2090 | chan->ifstats.rx_bytes += skb->len; | ||
2091 | card->wandev.stats.rx_bytes += skb->len; | ||
2092 | |||
2093 | skb_push(skb, sizeof(api_rx_hdr_t)); | ||
2094 | api_rx_hdr = (api_rx_hdr_t*)&skb->data[0x00]; | ||
2095 | api_rx_hdr->attr = frbuf->attr; | ||
2096 | api_rx_hdr->time_stamp = frbuf->tmstamp; | ||
2097 | |||
2098 | skb->protocol = htons(ETH_P_IP); | ||
2099 | skb->mac.raw = skb->data; | ||
2100 | skb->dev = dev; | ||
2101 | skb->pkt_type = WAN_PACKET_DATA; | ||
2102 | |||
2103 | bh_enqueue(dev, skb); | ||
2104 | |||
2105 | trigger_fr_bh(chan); | ||
2106 | |||
2107 | }else if (handle_IPXWAN(skb->data,chan->name,chan->enable_IPX, chan->network_number)){ | ||
2108 | |||
2109 | //FIXME: Frame Relay IPX is not supported, Yet ! | ||
2110 | //if (chan->enable_IPX) { | ||
2111 | // fr_send(card, dlci, 0, skb->len,skb->data); | ||
2112 | //} | ||
2113 | dev_kfree_skb_any(skb); | ||
2114 | |||
2115 | } else if (is_arp(skb->data)) { | ||
2116 | |||
2117 | /* ARP support enabled Mar 16 2000 | ||
2118 | * Process incoming ARP reply/request, setup | ||
2119 | * dynamic routes. */ | ||
2120 | |||
2121 | if (process_ARP((arphdr_1490_t *)skb->data, card, dev)) { | ||
2122 | if (net_ratelimit()){ | ||
2123 | printk (KERN_INFO | ||
2124 | "%s: Error processing ARP Packet.\n", | ||
2125 | card->devname); | ||
2126 | } | ||
2127 | } | ||
2128 | dev_kfree_skb_any(skb); | ||
2129 | |||
2130 | } else if (skb->data[0] != 0x03) { | ||
2131 | |||
2132 | if (net_ratelimit()) { | ||
2133 | printk(KERN_INFO "%s: Non IETF packet discarded.\n", | ||
2134 | card->devname); | ||
2135 | } | ||
2136 | dev_kfree_skb_any(skb); | ||
2137 | |||
2138 | } else { | ||
2139 | |||
2140 | len_incl_hdr = skb->len; | ||
2141 | /* Decapsulate packet and pass it up the | ||
2142 | protocol stack */ | ||
2143 | skb->dev = dev; | ||
2144 | |||
2145 | if (chan->common.usedby == BRIDGE || chan->common.usedby == BRIDGE_NODE){ | ||
2146 | |||
2147 | /* Make sure it's an Ethernet frame, otherwise drop it */ | ||
2148 | if (!memcmp(skb->data, "\x03\x00\x80\x00\x80\xC2\x00\x07", 8)) { | ||
2149 | skb_pull(skb, 8); | ||
2150 | skb->protocol=eth_type_trans(skb,dev); | ||
2151 | }else{ | ||
2152 | ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack; | ||
2153 | ++chan->ifstats.rx_errors; | ||
2154 | ++card->wandev.stats.rx_errors; | ||
2155 | goto rx_done; | ||
2156 | } | ||
2157 | }else{ | ||
2158 | |||
2159 | /* remove hardware header */ | ||
2160 | buf = skb_pull(skb, 1); | ||
2161 | |||
2162 | if (!wanrouter_type_trans(skb, dev)) { | ||
2163 | |||
2164 | /* can't decapsulate packet */ | ||
2165 | dev_kfree_skb_any(skb); | ||
2166 | |||
2167 | ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack; | ||
2168 | ++chan->ifstats.rx_errors; | ||
2169 | ++card->wandev.stats.rx_errors; | ||
2170 | goto rx_done; | ||
2171 | } | ||
2172 | skb->mac.raw = skb->data; | ||
2173 | } | ||
2174 | |||
2175 | |||
2176 | /* Send a packet up the IP stack */ | ||
2177 | skb->dev->last_rx = jiffies; | ||
2178 | netif_rx(skb); | ||
2179 | ++chan->drvstats_rx_intr.rx_intr_bfr_passed_to_stack; | ||
2180 | ++chan->ifstats.rx_packets; | ||
2181 | ++card->wandev.stats.rx_packets; | ||
2182 | |||
2183 | chan->ifstats.rx_bytes += len_incl_hdr; | ||
2184 | card->wandev.stats.rx_bytes += len_incl_hdr; | ||
2185 | } | ||
2186 | |||
2187 | rx_done: | ||
2188 | |||
2189 | /* Release buffer element and calculate a pointer to the next one */ | ||
2190 | frbuf->flag = 0; | ||
2191 | card->rxmb = ++frbuf; | ||
2192 | if ((void*)frbuf > card->u.f.rxmb_last) | ||
2193 | card->rxmb = card->u.f.rxmb_base; | ||
2194 | |||
2195 | } | ||
2196 | |||
2197 | /*================================================================== | ||
2198 | * tx_intr: Transmit interrupt handler. | ||
2199 | * | ||
2200 | * Rationale: | ||
2201 | * If the board is busy transmitting, if_send() will | ||
2202 | * buffers a single packet and turn on | ||
2203 | * the tx interrupt. Tx interrupt will be called | ||
2204 | * by the board, once the firmware can send more | ||
2205 | * data. Thus, no polling is required. | ||
2206 | * | ||
2207 | * Description: | ||
2208 | * Tx interrupt is called for each | ||
2209 | * configured dlci channel. Thus: | ||
2210 | * 1. Obtain the netowrk interface based on the | ||
2211 | * dlci number. | ||
2212 | * 2. Check that network interface is up and | ||
2213 | * properly setup. | ||
2214 | * 3. Check for a buffered packet. | ||
2215 | * 4. Transmit the packet. | ||
2216 | * 5. If we are in WANPIPE mode, mark the | ||
2217 | * NET_BH handler. | ||
2218 | * 6. If we are in API mode, kick | ||
2219 | * the AF_WANPIPE socket for more data. | ||
2220 | * | ||
2221 | */ | ||
2222 | static void tx_intr(sdla_t *card) | ||
2223 | { | ||
2224 | fr508_flags_t* flags = card->flags; | ||
2225 | fr_tx_buf_ctl_t* bctl; | ||
2226 | struct net_device* dev; | ||
2227 | fr_channel_t* chan; | ||
2228 | |||
2229 | if(card->hw.type == SDLA_S514){ | ||
2230 | bctl = (void*)(flags->tse_offs + card->hw.dpmbase); | ||
2231 | }else{ | ||
2232 | bctl = (void*)(flags->tse_offs - FR_MB_VECTOR + | ||
2233 | card->hw.dpmbase); | ||
2234 | } | ||
2235 | |||
2236 | /* Find the structure and make it unbusy */ | ||
2237 | dev = find_channel(card, flags->dlci); | ||
2238 | if (dev == NULL){ | ||
2239 | printk(KERN_INFO "NO DEV IN TX Interrupt\n"); | ||
2240 | goto end_of_tx_intr; | ||
2241 | } | ||
2242 | |||
2243 | if ((chan = dev->priv) == NULL){ | ||
2244 | printk(KERN_INFO "NO CHAN IN TX Interrupt\n"); | ||
2245 | goto end_of_tx_intr; | ||
2246 | } | ||
2247 | |||
2248 | if(!chan->transmit_length || !chan->delay_skb) { | ||
2249 | printk(KERN_INFO "%s: tx int error - transmit length zero\n", | ||
2250 | card->wandev.name); | ||
2251 | goto end_of_tx_intr; | ||
2252 | } | ||
2253 | |||
2254 | /* If the 'if_send()' procedure is currently checking the 'tbusy' | ||
2255 | status, then we cannot transmit. Instead, we configure the microcode | ||
2256 | so as to re-issue this transmit interrupt at a later stage. | ||
2257 | */ | ||
2258 | if (test_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical)) { | ||
2259 | |||
2260 | fr_dlci_interface_t* dlci_interface = chan->dlci_int_interface; | ||
2261 | bctl->flag = 0xA0; | ||
2262 | dlci_interface->gen_interrupt |= FR_INTR_TXRDY; | ||
2263 | return; | ||
2264 | |||
2265 | }else{ | ||
2266 | bctl->dlci = flags->dlci; | ||
2267 | bctl->length = chan->transmit_length+chan->fr_header_len; | ||
2268 | sdla_poke(&card->hw, | ||
2269 | fr_send_hdr(card,bctl->dlci,bctl->offset), | ||
2270 | chan->delay_skb->data, | ||
2271 | chan->delay_skb->len); | ||
2272 | bctl->flag = 0xC0; | ||
2273 | |||
2274 | ++chan->ifstats.tx_packets; | ||
2275 | ++card->wandev.stats.tx_packets; | ||
2276 | chan->ifstats.tx_bytes += chan->transmit_length; | ||
2277 | card->wandev.stats.tx_bytes += chan->transmit_length; | ||
2278 | |||
2279 | /* We must free an sk buffer, which we used | ||
2280 | * for delayed transmission; Otherwise, the sock | ||
2281 | * will run out of memory */ | ||
2282 | dev_kfree_skb_any(chan->delay_skb); | ||
2283 | |||
2284 | chan->delay_skb = NULL; | ||
2285 | chan->transmit_length = 0; | ||
2286 | |||
2287 | dev->trans_start = jiffies; | ||
2288 | |||
2289 | if (netif_queue_stopped(dev)){ | ||
2290 | /* If using API, than wakeup socket BH handler */ | ||
2291 | if (chan->common.usedby == API){ | ||
2292 | netif_start_queue(dev); | ||
2293 | wakeup_sk_bh(dev); | ||
2294 | }else{ | ||
2295 | netif_wake_queue(dev); | ||
2296 | } | ||
2297 | } | ||
2298 | } | ||
2299 | |||
2300 | end_of_tx_intr: | ||
2301 | |||
2302 | /* if any other interfaces have transmit interrupts pending, | ||
2303 | * do not disable the global transmit interrupt */ | ||
2304 | if(!(-- card->u.f.tx_interrupts_pending)) | ||
2305 | flags->imask &= ~FR_INTR_TXRDY; | ||
2306 | |||
2307 | |||
2308 | } | ||
2309 | |||
2310 | |||
2311 | /*============================================================================ | ||
2312 | * timer_intr: Timer interrupt handler. | ||
2313 | * | ||
2314 | * Rationale: | ||
2315 | * All commans must be executed within the timer | ||
2316 | * interrupt since no two commands should execute | ||
2317 | * at the same time. | ||
2318 | * | ||
2319 | * Description: | ||
2320 | * The timer interrupt is used to: | ||
2321 | * 1. Processing udp calls from 'fpipemon'. | ||
2322 | * 2. Processing update calls from /proc file system | ||
2323 | * 3. Reading board-level statistics for | ||
2324 | * updating the proc file system. | ||
2325 | * 4. Sending inverse ARP request packets. | ||
2326 | * 5. Configure a dlci/channel. | ||
2327 | * 6. Unconfigure a dlci/channel. (Node only) | ||
2328 | */ | ||
2329 | |||
2330 | static void timer_intr(sdla_t *card) | ||
2331 | { | ||
2332 | fr508_flags_t* flags = card->flags; | ||
2333 | |||
2334 | /* UDP Debuging: fpipemon call */ | ||
2335 | if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UDP) { | ||
2336 | if(card->u.f.udp_type == UDP_FPIPE_TYPE) { | ||
2337 | if(process_udp_mgmt_pkt(card)) { | ||
2338 | card->u.f.timer_int_enabled &= | ||
2339 | ~TMR_INT_ENABLED_UDP; | ||
2340 | } | ||
2341 | } | ||
2342 | } | ||
2343 | |||
2344 | /* /proc update call : triggered from update() */ | ||
2345 | if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UPDATE) { | ||
2346 | fr_get_err_stats(card); | ||
2347 | fr_get_stats(card); | ||
2348 | card->u.f.update_comms_stats = 0; | ||
2349 | card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; | ||
2350 | } | ||
2351 | |||
2352 | /* Update the channel state call. This is call is | ||
2353 | * triggered by if_send() function */ | ||
2354 | if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UPDATE_STATE){ | ||
2355 | struct net_device *dev; | ||
2356 | if (card->wandev.state == WAN_CONNECTED){ | ||
2357 | for (dev = card->wandev.dev; dev; | ||
2358 | dev = *((struct net_device **)dev->priv)){ | ||
2359 | fr_channel_t *chan = dev->priv; | ||
2360 | if (chan->common.state != WAN_CONNECTED){ | ||
2361 | update_chan_state(dev); | ||
2362 | } | ||
2363 | } | ||
2364 | } | ||
2365 | card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE_STATE; | ||
2366 | } | ||
2367 | |||
2368 | /* configure a dlci/channel */ | ||
2369 | if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_CONFIG){ | ||
2370 | config_fr(card); | ||
2371 | card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG; | ||
2372 | } | ||
2373 | |||
2374 | /* unconfigure a dlci/channel */ | ||
2375 | if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_UNCONFIG){ | ||
2376 | unconfig_fr(card); | ||
2377 | card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UNCONFIG; | ||
2378 | } | ||
2379 | |||
2380 | |||
2381 | /* Transmit ARP packets */ | ||
2382 | if (card->u.f.timer_int_enabled & TMR_INT_ENABLED_ARP){ | ||
2383 | int i=0; | ||
2384 | struct net_device *dev; | ||
2385 | |||
2386 | if (card->u.f.arp_dev == NULL) | ||
2387 | card->u.f.arp_dev = card->wandev.dev; | ||
2388 | |||
2389 | dev = card->u.f.arp_dev; | ||
2390 | |||
2391 | for (;;){ | ||
2392 | |||
2393 | fr_channel_t *chan = dev->priv; | ||
2394 | |||
2395 | /* If the interface is brought down cancel sending In-ARPs */ | ||
2396 | if (!(dev->flags&IFF_UP)){ | ||
2397 | clear_bit(0,&chan->inarp_ready); | ||
2398 | } | ||
2399 | |||
2400 | if (test_bit(0,&chan->inarp_ready)){ | ||
2401 | |||
2402 | if (check_tx_status(card,dev)){ | ||
2403 | set_bit(ARP_CRIT,&card->wandev.critical); | ||
2404 | break; | ||
2405 | } | ||
2406 | |||
2407 | if (!send_inarp_request(card,dev)){ | ||
2408 | trigger_fr_arp(dev); | ||
2409 | chan->inarp_tick = jiffies; | ||
2410 | } | ||
2411 | |||
2412 | clear_bit(0,&chan->inarp_ready); | ||
2413 | dev = move_dev_to_next(card,dev); | ||
2414 | break; | ||
2415 | } | ||
2416 | dev = move_dev_to_next(card,dev); | ||
2417 | |||
2418 | if (++i == card->wandev.new_if_cnt){ | ||
2419 | card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_ARP; | ||
2420 | break; | ||
2421 | } | ||
2422 | } | ||
2423 | card->u.f.arp_dev = dev; | ||
2424 | } | ||
2425 | |||
2426 | if(!card->u.f.timer_int_enabled) | ||
2427 | flags->imask &= ~FR_INTR_TIMER; | ||
2428 | } | ||
2429 | |||
2430 | |||
2431 | /*============================================================================ | ||
2432 | * spur_intr: Spurious interrupt handler. | ||
2433 | * | ||
2434 | * Description: | ||
2435 | * We don't know this interrupt. | ||
2436 | * Print a warning. | ||
2437 | */ | ||
2438 | |||
2439 | static void spur_intr (sdla_t* card) | ||
2440 | { | ||
2441 | if (net_ratelimit()){ | ||
2442 | printk(KERN_INFO "%s: spurious interrupt!\n", card->devname); | ||
2443 | } | ||
2444 | } | ||
2445 | |||
2446 | |||
2447 | //FIXME: Fix the IPX in next version | ||
2448 | /*=========================================================================== | ||
2449 | * Return 0 for non-IPXWAN packet | ||
2450 | * 1 for IPXWAN packet or IPX is not enabled! | ||
2451 | * FIXME: Use a IPX structure here not offsets | ||
2452 | */ | ||
2453 | static int handle_IPXWAN(unsigned char *sendpacket, | ||
2454 | char *devname, unsigned char enable_IPX, | ||
2455 | unsigned long network_number) | ||
2456 | { | ||
2457 | int i; | ||
2458 | |||
2459 | if( sendpacket[1] == 0x00 && sendpacket[2] == 0x80 && | ||
2460 | sendpacket[6] == 0x81 && sendpacket[7] == 0x37) { | ||
2461 | |||
2462 | /* It's an IPX packet */ | ||
2463 | if (!enable_IPX){ | ||
2464 | /* Return 1 so we don't pass it up the stack. */ | ||
2465 | //FIXME: Take this out when IPX is fixed | ||
2466 | if (net_ratelimit()){ | ||
2467 | printk (KERN_INFO | ||
2468 | "%s: WARNING: Unsupported IPX packet received and dropped\n", | ||
2469 | devname); | ||
2470 | } | ||
2471 | return 1; | ||
2472 | } | ||
2473 | } else { | ||
2474 | /* It's not IPX so return and pass it up the stack. */ | ||
2475 | return 0; | ||
2476 | } | ||
2477 | |||
2478 | if( sendpacket[24] == 0x90 && sendpacket[25] == 0x04){ | ||
2479 | /* It's IPXWAN */ | ||
2480 | |||
2481 | if( sendpacket[10] == 0x02 && sendpacket[42] == 0x00){ | ||
2482 | |||
2483 | /* It's a timer request packet */ | ||
2484 | printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n", | ||
2485 | devname); | ||
2486 | |||
2487 | /* Go through the routing options and answer no to every | ||
2488 | * option except Unnumbered RIP/SAP | ||
2489 | */ | ||
2490 | for(i = 49; sendpacket[i] == 0x00; i += 5){ | ||
2491 | /* 0x02 is the option for Unnumbered RIP/SAP */ | ||
2492 | if( sendpacket[i + 4] != 0x02){ | ||
2493 | sendpacket[i + 1] = 0; | ||
2494 | } | ||
2495 | } | ||
2496 | |||
2497 | /* Skip over the extended Node ID option */ | ||
2498 | if( sendpacket[i] == 0x04 ){ | ||
2499 | i += 8; | ||
2500 | } | ||
2501 | |||
2502 | /* We also want to turn off all header compression opt. | ||
2503 | */ | ||
2504 | for(; sendpacket[i] == 0x80 ;){ | ||
2505 | sendpacket[i + 1] = 0; | ||
2506 | i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4; | ||
2507 | } | ||
2508 | |||
2509 | /* Set the packet type to timer response */ | ||
2510 | sendpacket[42] = 0x01; | ||
2511 | |||
2512 | printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n", | ||
2513 | devname); | ||
2514 | |||
2515 | } else if( sendpacket[42] == 0x02 ){ | ||
2516 | |||
2517 | /* This is an information request packet */ | ||
2518 | printk(KERN_INFO | ||
2519 | "%s: Received IPXWAN Information Request packet\n", | ||
2520 | devname); | ||
2521 | |||
2522 | /* Set the packet type to information response */ | ||
2523 | sendpacket[42] = 0x03; | ||
2524 | |||
2525 | /* Set the router name */ | ||
2526 | sendpacket[59] = 'F'; | ||
2527 | sendpacket[60] = 'P'; | ||
2528 | sendpacket[61] = 'I'; | ||
2529 | sendpacket[62] = 'P'; | ||
2530 | sendpacket[63] = 'E'; | ||
2531 | sendpacket[64] = '-'; | ||
2532 | sendpacket[65] = CVHexToAscii(network_number >> 28); | ||
2533 | sendpacket[66] = CVHexToAscii((network_number & 0x0F000000)>> 24); | ||
2534 | sendpacket[67] = CVHexToAscii((network_number & 0x00F00000)>> 20); | ||
2535 | sendpacket[68] = CVHexToAscii((network_number & 0x000F0000)>> 16); | ||
2536 | sendpacket[69] = CVHexToAscii((network_number & 0x0000F000)>> 12); | ||
2537 | sendpacket[70] = CVHexToAscii((network_number & 0x00000F00)>> 8); | ||
2538 | sendpacket[71] = CVHexToAscii((network_number & 0x000000F0)>> 4); | ||
2539 | sendpacket[72] = CVHexToAscii(network_number & 0x0000000F); | ||
2540 | for(i = 73; i < 107; i+= 1) | ||
2541 | { | ||
2542 | sendpacket[i] = 0; | ||
2543 | } | ||
2544 | |||
2545 | printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n", | ||
2546 | devname); | ||
2547 | } else { | ||
2548 | |||
2549 | printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname); | ||
2550 | return 0; | ||
2551 | } | ||
2552 | |||
2553 | /* Set the WNodeID to our network address */ | ||
2554 | sendpacket[43] = (unsigned char)(network_number >> 24); | ||
2555 | sendpacket[44] = (unsigned char)((network_number & 0x00FF0000) >> 16); | ||
2556 | sendpacket[45] = (unsigned char)((network_number & 0x0000FF00) >> 8); | ||
2557 | sendpacket[46] = (unsigned char)(network_number & 0x000000FF); | ||
2558 | |||
2559 | return 1; | ||
2560 | } | ||
2561 | |||
2562 | /* If we get here, it's an IPX-data packet so it'll get passed up the | ||
2563 | * stack. | ||
2564 | * switch the network numbers | ||
2565 | */ | ||
2566 | switch_net_numbers(sendpacket, network_number ,1); | ||
2567 | return 0; | ||
2568 | } | ||
2569 | /*============================================================================ | ||
2570 | * process_route | ||
2571 | * | ||
2572 | * Rationale: | ||
2573 | * If the interface goes down, or we receive an ARP request, | ||
2574 | * we have to change the network interface ip addresses. | ||
2575 | * This cannot be done within the interrupt. | ||
2576 | * | ||
2577 | * Description: | ||
2578 | * | ||
2579 | * This routine is called as a polling routine to dynamically | ||
2580 | * add/delete routes negotiated by inverse ARP. It is in this | ||
2581 | * "task" because we don't want routes to be added while in | ||
2582 | * interrupt context. | ||
2583 | * | ||
2584 | * Usage: | ||
2585 | * This function is called by fr_poll() polling funtion. | ||
2586 | */ | ||
2587 | |||
2588 | static void process_route(struct net_device *dev) | ||
2589 | { | ||
2590 | fr_channel_t *chan = dev->priv; | ||
2591 | sdla_t *card = chan->card; | ||
2592 | |||
2593 | struct ifreq if_info; | ||
2594 | struct sockaddr_in *if_data; | ||
2595 | mm_segment_t fs = get_fs(); | ||
2596 | u32 ip_tmp; | ||
2597 | int err; | ||
2598 | |||
2599 | |||
2600 | switch(chan->route_flag){ | ||
2601 | |||
2602 | case ADD_ROUTE: | ||
2603 | |||
2604 | /* Set remote addresses */ | ||
2605 | memset(&if_info, 0, sizeof(if_info)); | ||
2606 | strcpy(if_info.ifr_name, dev->name); | ||
2607 | |||
2608 | set_fs(get_ds()); /* get user space block */ | ||
2609 | |||
2610 | if_data = (struct sockaddr_in *)&if_info.ifr_dstaddr; | ||
2611 | if_data->sin_addr.s_addr = chan->ip_remote; | ||
2612 | if_data->sin_family = AF_INET; | ||
2613 | err = devinet_ioctl( SIOCSIFDSTADDR, &if_info ); | ||
2614 | |||
2615 | set_fs(fs); /* restore old block */ | ||
2616 | |||
2617 | if (err) { | ||
2618 | printk(KERN_INFO | ||
2619 | "%s: Route Add failed. Error: %d\n", | ||
2620 | card->devname,err); | ||
2621 | printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n", | ||
2622 | chan->name, NIPQUAD(chan->ip_remote)); | ||
2623 | |||
2624 | }else { | ||
2625 | printk(KERN_INFO "%s: Route Added Successfully: %u.%u.%u.%u\n", | ||
2626 | card->devname,NIPQUAD(chan->ip_remote)); | ||
2627 | chan->route_flag = ROUTE_ADDED; | ||
2628 | } | ||
2629 | break; | ||
2630 | |||
2631 | case REMOVE_ROUTE: | ||
2632 | |||
2633 | /* Set remote addresses */ | ||
2634 | memset(&if_info, 0, sizeof(if_info)); | ||
2635 | strcpy(if_info.ifr_name, dev->name); | ||
2636 | |||
2637 | ip_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP); | ||
2638 | |||
2639 | set_fs(get_ds()); /* get user space block */ | ||
2640 | |||
2641 | if_data = (struct sockaddr_in *)&if_info.ifr_dstaddr; | ||
2642 | if_data->sin_addr.s_addr = 0; | ||
2643 | if_data->sin_family = AF_INET; | ||
2644 | err = devinet_ioctl( SIOCSIFDSTADDR, &if_info ); | ||
2645 | |||
2646 | set_fs(fs); | ||
2647 | |||
2648 | if (err) { | ||
2649 | printk(KERN_INFO | ||
2650 | "%s: Deleting of route failed. Error: %d\n", | ||
2651 | card->devname,err); | ||
2652 | printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n", | ||
2653 | dev->name,NIPQUAD(chan->ip_remote) ); | ||
2654 | |||
2655 | } else { | ||
2656 | printk(KERN_INFO "%s: Route Removed Sucessfuly: %u.%u.%u.%u\n", | ||
2657 | card->devname,NIPQUAD(ip_tmp)); | ||
2658 | chan->route_flag = NO_ROUTE; | ||
2659 | } | ||
2660 | break; | ||
2661 | |||
2662 | } /* Case Statement */ | ||
2663 | |||
2664 | } | ||
2665 | |||
2666 | |||
2667 | |||
2668 | /****** Frame Relay Firmware-Specific Functions *****************************/ | ||
2669 | |||
2670 | /*============================================================================ | ||
2671 | * Read firmware code version. | ||
2672 | * o fill string str with firmware version info. | ||
2673 | */ | ||
2674 | static int fr_read_version (sdla_t* card, char* str) | ||
2675 | { | ||
2676 | fr_mbox_t* mbox = card->mbox; | ||
2677 | int retry = MAX_CMD_RETRY; | ||
2678 | int err; | ||
2679 | |||
2680 | do | ||
2681 | { | ||
2682 | mbox->cmd.command = FR_READ_CODE_VERSION; | ||
2683 | mbox->cmd.length = 0; | ||
2684 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2685 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
2686 | |||
2687 | if (!err && str) { | ||
2688 | int len = mbox->cmd.length; | ||
2689 | memcpy(str, mbox->data, len); | ||
2690 | str[len] = '\0'; | ||
2691 | } | ||
2692 | return err; | ||
2693 | } | ||
2694 | |||
2695 | /*============================================================================ | ||
2696 | * Set global configuration. | ||
2697 | */ | ||
2698 | static int fr_configure (sdla_t* card, fr_conf_t *conf) | ||
2699 | { | ||
2700 | fr_mbox_t* mbox = card->mbox; | ||
2701 | int retry = MAX_CMD_RETRY; | ||
2702 | int dlci_num = card->u.f.dlci_num; | ||
2703 | int err, i; | ||
2704 | |||
2705 | do | ||
2706 | { | ||
2707 | memcpy(mbox->data, conf, sizeof(fr_conf_t)); | ||
2708 | |||
2709 | if (dlci_num) for (i = 0; i < dlci_num; ++i) | ||
2710 | ((fr_conf_t*)mbox->data)->dlci[i] = | ||
2711 | card->u.f.node_dlci[i]; | ||
2712 | |||
2713 | mbox->cmd.command = FR_SET_CONFIG; | ||
2714 | mbox->cmd.length = | ||
2715 | sizeof(fr_conf_t) + dlci_num * sizeof(short); | ||
2716 | |||
2717 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2718 | |||
2719 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
2720 | |||
2721 | /*NC Oct 12 2000 */ | ||
2722 | if (err != CMD_OK){ | ||
2723 | printk(KERN_ERR "%s: Frame Relay Configuration Failed: rc=0x%x\n", | ||
2724 | card->devname,err); | ||
2725 | } | ||
2726 | |||
2727 | return err; | ||
2728 | } | ||
2729 | |||
2730 | /*============================================================================ | ||
2731 | * Set DLCI configuration. | ||
2732 | */ | ||
2733 | static int fr_dlci_configure (sdla_t* card, fr_dlc_conf_t *conf, unsigned dlci) | ||
2734 | { | ||
2735 | fr_mbox_t* mbox = card->mbox; | ||
2736 | int retry = MAX_CMD_RETRY; | ||
2737 | int err; | ||
2738 | |||
2739 | do | ||
2740 | { | ||
2741 | memcpy(mbox->data, conf, sizeof(fr_dlc_conf_t)); | ||
2742 | mbox->cmd.dlci = (unsigned short) dlci; | ||
2743 | mbox->cmd.command = FR_SET_CONFIG; | ||
2744 | mbox->cmd.length = sizeof(fr_dlc_conf_t); | ||
2745 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2746 | } while (err && retry--); | ||
2747 | |||
2748 | return err; | ||
2749 | } | ||
2750 | /*============================================================================ | ||
2751 | * Set interrupt mode. | ||
2752 | */ | ||
2753 | static int fr_set_intr_mode (sdla_t* card, unsigned mode, unsigned mtu, | ||
2754 | unsigned short timeout) | ||
2755 | { | ||
2756 | fr_mbox_t* mbox = card->mbox; | ||
2757 | fr508_intr_ctl_t* ictl = (void*)mbox->data; | ||
2758 | int retry = MAX_CMD_RETRY; | ||
2759 | int err; | ||
2760 | |||
2761 | do | ||
2762 | { | ||
2763 | memset(ictl, 0, sizeof(fr508_intr_ctl_t)); | ||
2764 | ictl->mode = mode; | ||
2765 | ictl->tx_len = mtu; | ||
2766 | ictl->irq = card->hw.irq; | ||
2767 | |||
2768 | /* indicate timeout on timer */ | ||
2769 | if (mode & 0x20) ictl->timeout = timeout; | ||
2770 | |||
2771 | mbox->cmd.length = sizeof(fr508_intr_ctl_t); | ||
2772 | mbox->cmd.command = FR_SET_INTR_MODE; | ||
2773 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2774 | |||
2775 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
2776 | |||
2777 | return err; | ||
2778 | } | ||
2779 | |||
2780 | /*============================================================================ | ||
2781 | * Enable communications. | ||
2782 | */ | ||
2783 | static int fr_comm_enable (sdla_t* card) | ||
2784 | { | ||
2785 | fr_mbox_t* mbox = card->mbox; | ||
2786 | int retry = MAX_CMD_RETRY; | ||
2787 | int err; | ||
2788 | |||
2789 | do | ||
2790 | { | ||
2791 | mbox->cmd.command = FR_COMM_ENABLE; | ||
2792 | mbox->cmd.length = 0; | ||
2793 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2794 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
2795 | |||
2796 | return err; | ||
2797 | } | ||
2798 | |||
2799 | /*============================================================================ | ||
2800 | * fr_comm_disable | ||
2801 | * | ||
2802 | * Warning: This functin is called by the shutdown() procedure. It is void | ||
2803 | * since dev->priv are has already been deallocated and no | ||
2804 | * error checking is possible using fr_event() function. | ||
2805 | */ | ||
2806 | static void fr_comm_disable (sdla_t* card) | ||
2807 | { | ||
2808 | fr_mbox_t* mbox = card->mbox; | ||
2809 | int retry = MAX_CMD_RETRY; | ||
2810 | int err; | ||
2811 | |||
2812 | do { | ||
2813 | mbox->cmd.command = FR_SET_MODEM_STATUS; | ||
2814 | mbox->cmd.length = 1; | ||
2815 | mbox->data[0] = 0; | ||
2816 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2817 | } while (err && retry--); | ||
2818 | |||
2819 | retry = MAX_CMD_RETRY; | ||
2820 | |||
2821 | do | ||
2822 | { | ||
2823 | mbox->cmd.command = FR_COMM_DISABLE; | ||
2824 | mbox->cmd.length = 0; | ||
2825 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2826 | } while (err && retry--); | ||
2827 | |||
2828 | return; | ||
2829 | } | ||
2830 | |||
2831 | |||
2832 | |||
2833 | /*============================================================================ | ||
2834 | * Get communications error statistics. | ||
2835 | */ | ||
2836 | static int fr_get_err_stats (sdla_t* card) | ||
2837 | { | ||
2838 | fr_mbox_t* mbox = card->mbox; | ||
2839 | int retry = MAX_CMD_RETRY; | ||
2840 | int err; | ||
2841 | |||
2842 | |||
2843 | do | ||
2844 | { | ||
2845 | mbox->cmd.command = FR_READ_ERROR_STATS; | ||
2846 | mbox->cmd.length = 0; | ||
2847 | mbox->cmd.dlci = 0; | ||
2848 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2849 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
2850 | |||
2851 | if (!err) { | ||
2852 | fr_comm_stat_t* stats = (void*)mbox->data; | ||
2853 | card->wandev.stats.rx_over_errors = stats->rx_overruns; | ||
2854 | card->wandev.stats.rx_crc_errors = stats->rx_bad_crc; | ||
2855 | card->wandev.stats.rx_missed_errors = stats->rx_aborts; | ||
2856 | card->wandev.stats.rx_length_errors = stats->rx_too_long; | ||
2857 | card->wandev.stats.tx_aborted_errors = stats->tx_aborts; | ||
2858 | |||
2859 | } | ||
2860 | |||
2861 | return err; | ||
2862 | } | ||
2863 | |||
2864 | /*============================================================================ | ||
2865 | * Get statistics. | ||
2866 | */ | ||
2867 | static int fr_get_stats (sdla_t* card) | ||
2868 | { | ||
2869 | fr_mbox_t* mbox = card->mbox; | ||
2870 | int retry = MAX_CMD_RETRY; | ||
2871 | int err; | ||
2872 | |||
2873 | |||
2874 | do | ||
2875 | { | ||
2876 | mbox->cmd.command = FR_READ_STATISTICS; | ||
2877 | mbox->cmd.length = 0; | ||
2878 | mbox->cmd.dlci = 0; | ||
2879 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2880 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
2881 | |||
2882 | if (!err) { | ||
2883 | fr_link_stat_t* stats = (void*)mbox->data; | ||
2884 | card->wandev.stats.rx_frame_errors = stats->rx_bad_format; | ||
2885 | card->wandev.stats.rx_dropped = | ||
2886 | stats->rx_dropped + stats->rx_dropped2; | ||
2887 | } | ||
2888 | |||
2889 | return err; | ||
2890 | } | ||
2891 | |||
2892 | /*============================================================================ | ||
2893 | * Add DLCI(s) (Access Node only!). | ||
2894 | * This routine will perform the ADD_DLCIs command for the specified DLCI. | ||
2895 | */ | ||
2896 | static int fr_add_dlci (sdla_t* card, int dlci) | ||
2897 | { | ||
2898 | fr_mbox_t* mbox = card->mbox; | ||
2899 | int retry = MAX_CMD_RETRY; | ||
2900 | int err; | ||
2901 | |||
2902 | do | ||
2903 | { | ||
2904 | unsigned short* dlci_list = (void*)mbox->data; | ||
2905 | |||
2906 | mbox->cmd.length = sizeof(short); | ||
2907 | dlci_list[0] = dlci; | ||
2908 | mbox->cmd.command = FR_ADD_DLCI; | ||
2909 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2910 | |||
2911 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
2912 | |||
2913 | return err; | ||
2914 | } | ||
2915 | |||
2916 | /*============================================================================ | ||
2917 | * Activate DLCI(s) (Access Node only!). | ||
2918 | * This routine will perform the ACTIVATE_DLCIs command with a DLCI number. | ||
2919 | */ | ||
2920 | static int fr_activate_dlci (sdla_t* card, int dlci) | ||
2921 | { | ||
2922 | fr_mbox_t* mbox = card->mbox; | ||
2923 | int retry = MAX_CMD_RETRY; | ||
2924 | int err; | ||
2925 | |||
2926 | do | ||
2927 | { | ||
2928 | unsigned short* dlci_list = (void*)mbox->data; | ||
2929 | |||
2930 | mbox->cmd.length = sizeof(short); | ||
2931 | dlci_list[0] = dlci; | ||
2932 | mbox->cmd.command = FR_ACTIVATE_DLCI; | ||
2933 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2934 | |||
2935 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
2936 | |||
2937 | return err; | ||
2938 | } | ||
2939 | |||
2940 | /*============================================================================ | ||
2941 | * Delete DLCI(s) (Access Node only!). | ||
2942 | * This routine will perform the DELETE_DLCIs command with a DLCI number. | ||
2943 | */ | ||
2944 | static int fr_delete_dlci (sdla_t* card, int dlci) | ||
2945 | { | ||
2946 | fr_mbox_t* mbox = card->mbox; | ||
2947 | int retry = MAX_CMD_RETRY; | ||
2948 | int err; | ||
2949 | |||
2950 | do | ||
2951 | { | ||
2952 | unsigned short* dlci_list = (void*)mbox->data; | ||
2953 | |||
2954 | mbox->cmd.length = sizeof(short); | ||
2955 | dlci_list[0] = dlci; | ||
2956 | mbox->cmd.command = FR_DELETE_DLCI; | ||
2957 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2958 | |||
2959 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
2960 | |||
2961 | return err; | ||
2962 | } | ||
2963 | |||
2964 | |||
2965 | |||
2966 | /*============================================================================ | ||
2967 | * Issue in-channel signalling frame. | ||
2968 | */ | ||
2969 | static int fr_issue_isf (sdla_t* card, int isf) | ||
2970 | { | ||
2971 | fr_mbox_t* mbox = card->mbox; | ||
2972 | int retry = MAX_CMD_RETRY; | ||
2973 | int err; | ||
2974 | |||
2975 | do | ||
2976 | { | ||
2977 | mbox->data[0] = isf; | ||
2978 | mbox->cmd.length = 1; | ||
2979 | mbox->cmd.command = FR_ISSUE_IS_FRAME; | ||
2980 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2981 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
2982 | |||
2983 | return err; | ||
2984 | } | ||
2985 | |||
2986 | |||
2987 | static unsigned int fr_send_hdr (sdla_t*card, int dlci, unsigned int offset) | ||
2988 | { | ||
2989 | struct net_device *dev = find_channel(card,dlci); | ||
2990 | fr_channel_t *chan; | ||
2991 | |||
2992 | if (!dev || !(chan=dev->priv)) | ||
2993 | return offset; | ||
2994 | |||
2995 | if (chan->fr_header_len){ | ||
2996 | sdla_poke(&card->hw, offset, chan->fr_header, chan->fr_header_len); | ||
2997 | } | ||
2998 | |||
2999 | return offset+chan->fr_header_len; | ||
3000 | } | ||
3001 | |||
3002 | /*============================================================================ | ||
3003 | * Send a frame on a selected DLCI. | ||
3004 | */ | ||
3005 | static int fr_send_data_header (sdla_t* card, int dlci, unsigned char attr, int len, | ||
3006 | void *buf, unsigned char hdr_len) | ||
3007 | { | ||
3008 | fr_mbox_t* mbox = card->mbox + 0x800; | ||
3009 | int retry = MAX_CMD_RETRY; | ||
3010 | int err; | ||
3011 | |||
3012 | do | ||
3013 | { | ||
3014 | mbox->cmd.dlci = dlci; | ||
3015 | mbox->cmd.attr = attr; | ||
3016 | mbox->cmd.length = len+hdr_len; | ||
3017 | mbox->cmd.command = FR_WRITE; | ||
3018 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
3019 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
3020 | |||
3021 | if (!err) { | ||
3022 | fr_tx_buf_ctl_t* frbuf; | ||
3023 | |||
3024 | if(card->hw.type == SDLA_S514) | ||
3025 | frbuf = (void*)(*(unsigned long*)mbox->data + | ||
3026 | card->hw.dpmbase); | ||
3027 | else | ||
3028 | frbuf = (void*)(*(unsigned long*)mbox->data - | ||
3029 | FR_MB_VECTOR + card->hw.dpmbase); | ||
3030 | |||
3031 | sdla_poke(&card->hw, fr_send_hdr(card,dlci,frbuf->offset), buf, len); | ||
3032 | frbuf->flag = 0x01; | ||
3033 | } | ||
3034 | |||
3035 | return err; | ||
3036 | } | ||
3037 | |||
3038 | static int fr_send (sdla_t* card, int dlci, unsigned char attr, int len, | ||
3039 | void *buf) | ||
3040 | { | ||
3041 | fr_mbox_t* mbox = card->mbox + 0x800; | ||
3042 | int retry = MAX_CMD_RETRY; | ||
3043 | int err; | ||
3044 | |||
3045 | do | ||
3046 | { | ||
3047 | mbox->cmd.dlci = dlci; | ||
3048 | mbox->cmd.attr = attr; | ||
3049 | mbox->cmd.length = len; | ||
3050 | mbox->cmd.command = FR_WRITE; | ||
3051 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
3052 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
3053 | |||
3054 | if (!err) { | ||
3055 | fr_tx_buf_ctl_t* frbuf; | ||
3056 | |||
3057 | if(card->hw.type == SDLA_S514) | ||
3058 | frbuf = (void*)(*(unsigned long*)mbox->data + | ||
3059 | card->hw.dpmbase); | ||
3060 | else | ||
3061 | frbuf = (void*)(*(unsigned long*)mbox->data - | ||
3062 | FR_MB_VECTOR + card->hw.dpmbase); | ||
3063 | |||
3064 | sdla_poke(&card->hw, frbuf->offset, buf, len); | ||
3065 | frbuf->flag = 0x01; | ||
3066 | } | ||
3067 | |||
3068 | return err; | ||
3069 | } | ||
3070 | |||
3071 | |||
3072 | /****** Firmware Asynchronous Event Handlers ********************************/ | ||
3073 | |||
3074 | /*============================================================================ | ||
3075 | * Main asyncronous event/error handler. | ||
3076 | * This routine is called whenever firmware command returns non-zero | ||
3077 | * return code. | ||
3078 | * | ||
3079 | * Return zero if previous command has to be cancelled. | ||
3080 | */ | ||
3081 | static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox) | ||
3082 | { | ||
3083 | fr508_flags_t* flags = card->flags; | ||
3084 | char *ptr = &flags->iflag; | ||
3085 | int i; | ||
3086 | |||
3087 | switch (event) { | ||
3088 | |||
3089 | case FRRES_MODEM_FAILURE: | ||
3090 | return fr_modem_failure(card, mbox); | ||
3091 | |||
3092 | case FRRES_CHANNEL_DOWN: { | ||
3093 | struct net_device *dev; | ||
3094 | |||
3095 | /* Remove all routes from associated DLCI's */ | ||
3096 | for (dev = card->wandev.dev; dev; | ||
3097 | dev = *((struct net_device **)dev->priv)) { | ||
3098 | fr_channel_t *chan = dev->priv; | ||
3099 | if (chan->route_flag == ROUTE_ADDED) { | ||
3100 | chan->route_flag = REMOVE_ROUTE; | ||
3101 | } | ||
3102 | |||
3103 | if (chan->inarp == INARP_CONFIGURED) { | ||
3104 | chan->inarp = INARP_REQUEST; | ||
3105 | } | ||
3106 | |||
3107 | /* If the link becomes disconnected then, | ||
3108 | * all channels will be disconnected | ||
3109 | * as well. | ||
3110 | */ | ||
3111 | set_chan_state(dev,WAN_DISCONNECTED); | ||
3112 | } | ||
3113 | |||
3114 | wanpipe_set_state(card, WAN_DISCONNECTED); | ||
3115 | return 1; | ||
3116 | } | ||
3117 | |||
3118 | case FRRES_CHANNEL_UP: { | ||
3119 | struct net_device *dev; | ||
3120 | |||
3121 | /* FIXME: Only startup devices that are on the list */ | ||
3122 | |||
3123 | for (dev = card->wandev.dev; dev; | ||
3124 | dev = *((struct net_device **)dev->priv)) { | ||
3125 | |||
3126 | set_chan_state(dev,WAN_CONNECTED); | ||
3127 | } | ||
3128 | |||
3129 | wanpipe_set_state(card, WAN_CONNECTED); | ||
3130 | return 1; | ||
3131 | } | ||
3132 | |||
3133 | case FRRES_DLCI_CHANGE: | ||
3134 | return fr_dlci_change(card, mbox); | ||
3135 | |||
3136 | case FRRES_DLCI_MISMATCH: | ||
3137 | printk(KERN_INFO "%s: DLCI list mismatch!\n", | ||
3138 | card->devname); | ||
3139 | return 1; | ||
3140 | |||
3141 | case CMD_TIMEOUT: | ||
3142 | printk(KERN_ERR "%s: command 0x%02X timed out!\n", | ||
3143 | card->devname, mbox->cmd.command); | ||
3144 | printk(KERN_INFO "%s: ID Bytes = ",card->devname); | ||
3145 | for(i = 0; i < 8; i ++) | ||
3146 | printk(KERN_INFO "0x%02X ", *(ptr + 0x18 + i)); | ||
3147 | printk(KERN_INFO "\n"); | ||
3148 | |||
3149 | break; | ||
3150 | |||
3151 | case FRRES_DLCI_INACTIVE: | ||
3152 | break; | ||
3153 | |||
3154 | case FRRES_CIR_OVERFLOW: | ||
3155 | break; | ||
3156 | |||
3157 | case FRRES_BUFFER_OVERFLOW: | ||
3158 | break; | ||
3159 | |||
3160 | default: | ||
3161 | printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n" | ||
3162 | , card->devname, mbox->cmd.command, event); | ||
3163 | } | ||
3164 | |||
3165 | return 0; | ||
3166 | } | ||
3167 | |||
3168 | /*============================================================================ | ||
3169 | * Handle modem error. | ||
3170 | * | ||
3171 | * Return zero if previous command has to be cancelled. | ||
3172 | */ | ||
3173 | static int fr_modem_failure (sdla_t *card, fr_mbox_t* mbox) | ||
3174 | { | ||
3175 | printk(KERN_INFO "%s: physical link down! (modem error 0x%02X)\n", | ||
3176 | card->devname, mbox->data[0]); | ||
3177 | |||
3178 | switch (mbox->cmd.command){ | ||
3179 | case FR_WRITE: | ||
3180 | |||
3181 | case FR_READ: | ||
3182 | return 0; | ||
3183 | } | ||
3184 | |||
3185 | return 1; | ||
3186 | } | ||
3187 | |||
3188 | /*============================================================================ | ||
3189 | * Handle DLCI status change. | ||
3190 | * | ||
3191 | * Return zero if previous command has to be cancelled. | ||
3192 | */ | ||
3193 | static int fr_dlci_change (sdla_t *card, fr_mbox_t* mbox) | ||
3194 | { | ||
3195 | dlci_status_t* status = (void*)mbox->data; | ||
3196 | int cnt = mbox->cmd.length / sizeof(dlci_status_t); | ||
3197 | fr_channel_t *chan; | ||
3198 | struct net_device* dev2; | ||
3199 | |||
3200 | |||
3201 | for (; cnt; --cnt, ++status) { | ||
3202 | |||
3203 | unsigned short dlci= status->dlci; | ||
3204 | struct net_device* dev = find_channel(card, dlci); | ||
3205 | |||
3206 | if (dev == NULL){ | ||
3207 | printk(KERN_INFO | ||
3208 | "%s: CPE contains unconfigured DLCI= %d\n", | ||
3209 | card->devname, dlci); | ||
3210 | |||
3211 | printk(KERN_INFO | ||
3212 | "%s: unconfigured DLCI %d reported by network\n" | ||
3213 | , card->devname, dlci); | ||
3214 | |||
3215 | }else{ | ||
3216 | if (status->state == FR_LINK_INOPER) { | ||
3217 | printk(KERN_INFO | ||
3218 | "%s: DLCI %u is inactive!\n", | ||
3219 | card->devname, dlci); | ||
3220 | |||
3221 | if (dev && netif_running(dev)) | ||
3222 | set_chan_state(dev, WAN_DISCONNECTED); | ||
3223 | } | ||
3224 | |||
3225 | if (status->state & FR_DLCI_DELETED) { | ||
3226 | |||
3227 | printk(KERN_INFO | ||
3228 | "%s: DLCI %u has been deleted!\n", | ||
3229 | card->devname, dlci); | ||
3230 | |||
3231 | if (dev && netif_running(dev)){ | ||
3232 | |||
3233 | fr_channel_t *chan = dev->priv; | ||
3234 | |||
3235 | if (chan->route_flag == ROUTE_ADDED) { | ||
3236 | chan->route_flag = REMOVE_ROUTE; | ||
3237 | /* The state change will trigger | ||
3238 | * the fr polling routine */ | ||
3239 | } | ||
3240 | |||
3241 | if (chan->inarp == INARP_CONFIGURED) { | ||
3242 | chan->inarp = INARP_REQUEST; | ||
3243 | } | ||
3244 | |||
3245 | set_chan_state(dev, WAN_DISCONNECTED); | ||
3246 | } | ||
3247 | |||
3248 | } else if (status->state & FR_DLCI_ACTIVE) { | ||
3249 | |||
3250 | chan = dev->priv; | ||
3251 | |||
3252 | /* This flag is used for configuring specific | ||
3253 | DLCI(s) when they become active. | ||
3254 | */ | ||
3255 | chan->dlci_configured = DLCI_CONFIG_PENDING; | ||
3256 | |||
3257 | set_chan_state(dev, WAN_CONNECTED); | ||
3258 | |||
3259 | } | ||
3260 | } | ||
3261 | } | ||
3262 | |||
3263 | for (dev2 = card->wandev.dev; dev2; | ||
3264 | dev2 = *((struct net_device **)dev2->priv)){ | ||
3265 | |||
3266 | chan = dev2->priv; | ||
3267 | |||
3268 | if (chan->dlci_configured == DLCI_CONFIG_PENDING) { | ||
3269 | if (fr_init_dlci(card, chan)){ | ||
3270 | return 1; | ||
3271 | } | ||
3272 | } | ||
3273 | |||
3274 | } | ||
3275 | return 1; | ||
3276 | } | ||
3277 | |||
3278 | |||
3279 | static int fr_init_dlci (sdla_t *card, fr_channel_t *chan) | ||
3280 | { | ||
3281 | fr_dlc_conf_t cfg; | ||
3282 | |||
3283 | memset(&cfg, 0, sizeof(cfg)); | ||
3284 | |||
3285 | if ( chan->cir_status == CIR_DISABLED) { | ||
3286 | |||
3287 | cfg.cir_fwd = cfg.cir_bwd = 16; | ||
3288 | cfg.bc_fwd = cfg.bc_bwd = 16; | ||
3289 | cfg.conf_flags = 0x0001; | ||
3290 | |||
3291 | }else if (chan->cir_status == CIR_ENABLED) { | ||
3292 | |||
3293 | cfg.cir_fwd = cfg.cir_bwd = chan->cir; | ||
3294 | cfg.bc_fwd = cfg.bc_bwd = chan->bc; | ||
3295 | cfg.be_fwd = cfg.be_bwd = chan->be; | ||
3296 | cfg.conf_flags = 0x0000; | ||
3297 | } | ||
3298 | |||
3299 | if (fr_dlci_configure( card, &cfg , chan->dlci)){ | ||
3300 | printk(KERN_INFO | ||
3301 | "%s: DLCI Configure failed for %d\n", | ||
3302 | card->devname, chan->dlci); | ||
3303 | return 1; | ||
3304 | } | ||
3305 | |||
3306 | chan->dlci_configured = DLCI_CONFIGURED; | ||
3307 | |||
3308 | /* Read the interface byte mapping into the channel | ||
3309 | * structure. | ||
3310 | */ | ||
3311 | read_DLCI_IB_mapping( card, chan ); | ||
3312 | |||
3313 | return 0; | ||
3314 | } | ||
3315 | /******* Miscellaneous ******************************************************/ | ||
3316 | |||
3317 | /*============================================================================ | ||
3318 | * Update channel state. | ||
3319 | */ | ||
3320 | static int update_chan_state(struct net_device* dev) | ||
3321 | { | ||
3322 | fr_channel_t* chan = dev->priv; | ||
3323 | sdla_t* card = chan->card; | ||
3324 | fr_mbox_t* mbox = card->mbox; | ||
3325 | int retry = MAX_CMD_RETRY; | ||
3326 | int err; | ||
3327 | |||
3328 | do | ||
3329 | { | ||
3330 | mbox->cmd.command = FR_LIST_ACTIVE_DLCI; | ||
3331 | mbox->cmd.length = 0; | ||
3332 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
3333 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
3334 | |||
3335 | if (!err) { | ||
3336 | |||
3337 | unsigned short* list = (void*)mbox->data; | ||
3338 | int cnt = mbox->cmd.length / sizeof(short); | ||
3339 | |||
3340 | err=1; | ||
3341 | |||
3342 | for (; cnt; --cnt, ++list) { | ||
3343 | |||
3344 | if (*list == chan->dlci) { | ||
3345 | set_chan_state(dev, WAN_CONNECTED); | ||
3346 | |||
3347 | |||
3348 | /* May 23 2000. NC | ||
3349 | * When a dlci is added or restarted, | ||
3350 | * the dlci_int_interface pointer must | ||
3351 | * be reinitialized. */ | ||
3352 | if (!chan->dlci_int_interface){ | ||
3353 | err=fr_init_dlci (card,chan); | ||
3354 | } | ||
3355 | break; | ||
3356 | } | ||
3357 | } | ||
3358 | } | ||
3359 | |||
3360 | return err; | ||
3361 | } | ||
3362 | |||
3363 | /*============================================================================ | ||
3364 | * Set channel state. | ||
3365 | */ | ||
3366 | static void set_chan_state(struct net_device* dev, int state) | ||
3367 | { | ||
3368 | fr_channel_t* chan = dev->priv; | ||
3369 | sdla_t* card = chan->card; | ||
3370 | |||
3371 | if (chan->common.state != state) { | ||
3372 | |||
3373 | switch (state) { | ||
3374 | |||
3375 | case WAN_CONNECTED: | ||
3376 | printk(KERN_INFO | ||
3377 | "%s: Interface %s: DLCI %d connected\n", | ||
3378 | card->devname, dev->name, chan->dlci); | ||
3379 | |||
3380 | /* If the interface was previoulsy down, | ||
3381 | * bring it up, since the channel is active */ | ||
3382 | |||
3383 | trigger_fr_poll (dev); | ||
3384 | trigger_fr_arp (dev); | ||
3385 | break; | ||
3386 | |||
3387 | case WAN_CONNECTING: | ||
3388 | printk(KERN_INFO | ||
3389 | "%s: Interface %s: DLCI %d connecting\n", | ||
3390 | card->devname, dev->name, chan->dlci); | ||
3391 | break; | ||
3392 | |||
3393 | case WAN_DISCONNECTED: | ||
3394 | printk (KERN_INFO | ||
3395 | "%s: Interface %s: DLCI %d disconnected!\n", | ||
3396 | card->devname, dev->name, chan->dlci); | ||
3397 | |||
3398 | /* If the interface is up, bring it down, | ||
3399 | * since the channel is now disconnected */ | ||
3400 | trigger_fr_poll (dev); | ||
3401 | break; | ||
3402 | } | ||
3403 | |||
3404 | chan->common.state = state; | ||
3405 | } | ||
3406 | |||
3407 | chan->state_tick = jiffies; | ||
3408 | } | ||
3409 | |||
3410 | /*============================================================================ | ||
3411 | * Find network device by its channel number. | ||
3412 | * | ||
3413 | * We need this critical flag because we change | ||
3414 | * the dlci_to_dev_map outside the interrupt. | ||
3415 | * | ||
3416 | * NOTE: del_if() functions updates this array, it uses | ||
3417 | * the spin locks to avoid corruption. | ||
3418 | */ | ||
3419 | static struct net_device* find_channel(sdla_t* card, unsigned dlci) | ||
3420 | { | ||
3421 | if(dlci > HIGHEST_VALID_DLCI) | ||
3422 | return NULL; | ||
3423 | |||
3424 | return(card->u.f.dlci_to_dev_map[dlci]); | ||
3425 | } | ||
3426 | |||
3427 | /*============================================================================ | ||
3428 | * Check to see if a frame can be sent. If no transmit buffers available, | ||
3429 | * enable transmit interrupts. | ||
3430 | * | ||
3431 | * Return: 1 - Tx buffer(s) available | ||
3432 | * 0 - no buffers available | ||
3433 | */ | ||
3434 | static int is_tx_ready (sdla_t* card, fr_channel_t* chan) | ||
3435 | { | ||
3436 | unsigned char sb; | ||
3437 | |||
3438 | if(card->hw.type == SDLA_S514) | ||
3439 | return 1; | ||
3440 | |||
3441 | sb = inb(card->hw.port); | ||
3442 | if (sb & 0x02) | ||
3443 | return 1; | ||
3444 | |||
3445 | return 0; | ||
3446 | } | ||
3447 | |||
3448 | /*============================================================================ | ||
3449 | * Convert decimal string to unsigned integer. | ||
3450 | * If len != 0 then only 'len' characters of the string are converted. | ||
3451 | */ | ||
3452 | static unsigned int dec_to_uint (unsigned char* str, int len) | ||
3453 | { | ||
3454 | unsigned val; | ||
3455 | |||
3456 | if (!len) | ||
3457 | len = strlen(str); | ||
3458 | |||
3459 | for (val = 0; len && isdigit(*str); ++str, --len) | ||
3460 | val = (val * 10) + (*str - (unsigned)'0'); | ||
3461 | |||
3462 | return val; | ||
3463 | } | ||
3464 | |||
3465 | |||
3466 | |||
3467 | /*============================================================================= | ||
3468 | * Store a UDP management packet for later processing. | ||
3469 | */ | ||
3470 | |||
3471 | static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card, | ||
3472 | struct sk_buff *skb, int dlci) | ||
3473 | { | ||
3474 | int udp_pkt_stored = 0; | ||
3475 | |||
3476 | struct net_device *dev = find_channel(card, dlci); | ||
3477 | fr_channel_t *chan; | ||
3478 | |||
3479 | if (!dev || !(chan=dev->priv)) | ||
3480 | return 1; | ||
3481 | |||
3482 | if(!card->u.f.udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)){ | ||
3483 | card->u.f.udp_pkt_lgth = skb->len + chan->fr_header_len; | ||
3484 | card->u.f.udp_type = udp_type; | ||
3485 | card->u.f.udp_pkt_src = udp_pkt_src; | ||
3486 | card->u.f.udp_dlci = dlci; | ||
3487 | memcpy(card->u.f.udp_pkt_data, skb->data, skb->len); | ||
3488 | card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UDP; | ||
3489 | udp_pkt_stored = 1; | ||
3490 | |||
3491 | }else{ | ||
3492 | printk(KERN_INFO "ERROR: UDP packet not stored for DLCI %d\n", | ||
3493 | dlci); | ||
3494 | } | ||
3495 | |||
3496 | if(udp_pkt_src == UDP_PKT_FRM_STACK){ | ||
3497 | dev_kfree_skb_any(skb); | ||
3498 | }else{ | ||
3499 | dev_kfree_skb_any(skb); | ||
3500 | } | ||
3501 | |||
3502 | return(udp_pkt_stored); | ||
3503 | } | ||
3504 | |||
3505 | |||
3506 | /*============================================================================== | ||
3507 | * Process UDP call of type FPIPE8ND | ||
3508 | */ | ||
3509 | static int process_udp_mgmt_pkt(sdla_t* card) | ||
3510 | { | ||
3511 | |||
3512 | int c_retry = MAX_CMD_RETRY; | ||
3513 | unsigned char *buf; | ||
3514 | unsigned char frames; | ||
3515 | unsigned int len; | ||
3516 | unsigned short buffer_length; | ||
3517 | struct sk_buff *new_skb; | ||
3518 | fr_mbox_t* mbox = card->mbox; | ||
3519 | int err; | ||
3520 | struct timeval tv; | ||
3521 | int udp_mgmt_req_valid = 1; | ||
3522 | struct net_device* dev; | ||
3523 | fr_channel_t* chan; | ||
3524 | fr_udp_pkt_t *fr_udp_pkt; | ||
3525 | unsigned short num_trc_els; | ||
3526 | fr_trc_el_t* ptr_trc_el; | ||
3527 | fr_trc_el_t trc_el; | ||
3528 | fpipemon_trc_t* fpipemon_trc; | ||
3529 | |||
3530 | char udp_pkt_src = card->u.f.udp_pkt_src; | ||
3531 | int dlci = card->u.f.udp_dlci; | ||
3532 | |||
3533 | /* Find network interface for this packet */ | ||
3534 | dev = find_channel(card, dlci); | ||
3535 | if (!dev){ | ||
3536 | card->u.f.udp_pkt_lgth = 0; | ||
3537 | return 1; | ||
3538 | } | ||
3539 | if ((chan = dev->priv) == NULL){ | ||
3540 | card->u.f.udp_pkt_lgth = 0; | ||
3541 | return 1; | ||
3542 | } | ||
3543 | |||
3544 | /* If the UDP packet is from the network, we are going to have to | ||
3545 | transmit a response. Before doing so, we must check to see that | ||
3546 | we are not currently transmitting a frame (in 'if_send()') and | ||
3547 | that we are not already in a 'delayed transmit' state. | ||
3548 | */ | ||
3549 | if(udp_pkt_src == UDP_PKT_FRM_NETWORK) { | ||
3550 | if (check_tx_status(card,dev)){ | ||
3551 | card->u.f.udp_pkt_lgth = 0; | ||
3552 | return 1; | ||
3553 | } | ||
3554 | } | ||
3555 | |||
3556 | fr_udp_pkt = (fr_udp_pkt_t *)card->u.f.udp_pkt_data; | ||
3557 | |||
3558 | if(udp_pkt_src == UDP_PKT_FRM_NETWORK) { | ||
3559 | |||
3560 | switch(fr_udp_pkt->cblock.command) { | ||
3561 | |||
3562 | case FR_READ_MODEM_STATUS: | ||
3563 | case FR_READ_STATUS: | ||
3564 | case FPIPE_ROUTER_UP_TIME: | ||
3565 | case FR_READ_ERROR_STATS: | ||
3566 | case FPIPE_DRIVER_STAT_GEN: | ||
3567 | case FR_READ_STATISTICS: | ||
3568 | case FR_READ_ADD_DLC_STATS: | ||
3569 | case FR_READ_CONFIG: | ||
3570 | case FR_READ_CODE_VERSION: | ||
3571 | udp_mgmt_req_valid = 1; | ||
3572 | break; | ||
3573 | default: | ||
3574 | udp_mgmt_req_valid = 0; | ||
3575 | break; | ||
3576 | } | ||
3577 | } | ||
3578 | |||
3579 | if(!udp_mgmt_req_valid) { | ||
3580 | /* set length to 0 */ | ||
3581 | fr_udp_pkt->cblock.length = 0; | ||
3582 | /* set return code */ | ||
3583 | fr_udp_pkt->cblock.result = 0xCD; | ||
3584 | |||
3585 | chan->drvstats_gen.UDP_PIPE_mgmt_direction_err ++; | ||
3586 | |||
3587 | if (net_ratelimit()){ | ||
3588 | printk(KERN_INFO | ||
3589 | "%s: Warning, Illegal UDP command attempted from network: %x\n", | ||
3590 | card->devname,fr_udp_pkt->cblock.command); | ||
3591 | } | ||
3592 | |||
3593 | } else { | ||
3594 | |||
3595 | switch(fr_udp_pkt->cblock.command) { | ||
3596 | |||
3597 | case FPIPE_ENABLE_TRACING: | ||
3598 | if(!card->TracingEnabled) { | ||
3599 | do { | ||
3600 | mbox->cmd.command = FR_SET_TRACE_CONFIG; | ||
3601 | mbox->cmd.length = 1; | ||
3602 | mbox->cmd.dlci = 0x00; | ||
3603 | mbox->data[0] = fr_udp_pkt->data[0] | | ||
3604 | RESET_TRC; | ||
3605 | err = sdla_exec(mbox) ? | ||
3606 | mbox->cmd.result : CMD_TIMEOUT; | ||
3607 | } while (err && c_retry-- && fr_event(card, err, | ||
3608 | mbox)); | ||
3609 | |||
3610 | if(err) { | ||
3611 | card->TracingEnabled = 0; | ||
3612 | /* set the return code */ | ||
3613 | fr_udp_pkt->cblock.result = | ||
3614 | mbox->cmd.result; | ||
3615 | mbox->cmd.length = 0; | ||
3616 | break; | ||
3617 | } | ||
3618 | |||
3619 | sdla_peek(&card->hw, NO_TRC_ELEMENTS_OFF, | ||
3620 | &num_trc_els, 2); | ||
3621 | sdla_peek(&card->hw, BASE_TRC_ELEMENTS_OFF, | ||
3622 | &card->u.f.trc_el_base, 4); | ||
3623 | card->u.f.curr_trc_el = card->u.f.trc_el_base; | ||
3624 | card->u.f.trc_el_last = card->u.f.curr_trc_el + | ||
3625 | ((num_trc_els - 1) * | ||
3626 | sizeof(fr_trc_el_t)); | ||
3627 | |||
3628 | /* Calculate the maximum trace data area in */ | ||
3629 | /* the UDP packet */ | ||
3630 | card->u.f.trc_bfr_space=(MAX_LGTH_UDP_MGNT_PKT - | ||
3631 | //sizeof(fr_encap_hdr_t) - | ||
3632 | sizeof(ip_pkt_t) - | ||
3633 | sizeof(udp_pkt_t) - | ||
3634 | sizeof(wp_mgmt_t) - | ||
3635 | sizeof(cblock_t)); | ||
3636 | |||
3637 | /* set return code */ | ||
3638 | fr_udp_pkt->cblock.result = 0; | ||
3639 | |||
3640 | } else { | ||
3641 | /* set return code to line trace already | ||
3642 | enabled */ | ||
3643 | fr_udp_pkt->cblock.result = 1; | ||
3644 | } | ||
3645 | |||
3646 | mbox->cmd.length = 0; | ||
3647 | card->TracingEnabled = 1; | ||
3648 | break; | ||
3649 | |||
3650 | |||
3651 | case FPIPE_DISABLE_TRACING: | ||
3652 | if(card->TracingEnabled) { | ||
3653 | |||
3654 | do { | ||
3655 | mbox->cmd.command = FR_SET_TRACE_CONFIG; | ||
3656 | mbox->cmd.length = 1; | ||
3657 | mbox->cmd.dlci = 0x00; | ||
3658 | mbox->data[0] = ~ACTIVATE_TRC; | ||
3659 | err = sdla_exec(mbox) ? | ||
3660 | mbox->cmd.result : CMD_TIMEOUT; | ||
3661 | } while (err && c_retry-- && fr_event(card, err, mbox)); | ||
3662 | } | ||
3663 | |||
3664 | /* set return code */ | ||
3665 | fr_udp_pkt->cblock.result = 0; | ||
3666 | mbox->cmd.length = 0; | ||
3667 | card->TracingEnabled = 0; | ||
3668 | break; | ||
3669 | |||
3670 | case FPIPE_GET_TRACE_INFO: | ||
3671 | |||
3672 | /* Line trace cannot be performed on the 502 */ | ||
3673 | if(!card->TracingEnabled) { | ||
3674 | /* set return code */ | ||
3675 | fr_udp_pkt->cblock.result = 1; | ||
3676 | mbox->cmd.length = 0; | ||
3677 | break; | ||
3678 | } | ||
3679 | |||
3680 | ptr_trc_el = (void *)card->u.f.curr_trc_el; | ||
3681 | |||
3682 | buffer_length = 0; | ||
3683 | fr_udp_pkt->data[0x00] = 0x00; | ||
3684 | |||
3685 | for(frames = 0; frames < MAX_FRMS_TRACED; frames ++) { | ||
3686 | |||
3687 | sdla_peek(&card->hw, (unsigned long)ptr_trc_el, | ||
3688 | (void *)&trc_el.flag, | ||
3689 | sizeof(fr_trc_el_t)); | ||
3690 | if(trc_el.flag == 0x00) { | ||
3691 | break; | ||
3692 | } | ||
3693 | if((card->u.f.trc_bfr_space - buffer_length) | ||
3694 | < sizeof(fpipemon_trc_hdr_t)) { | ||
3695 | fr_udp_pkt->data[0x00] |= MORE_TRC_DATA; | ||
3696 | break; | ||
3697 | } | ||
3698 | |||
3699 | fpipemon_trc = | ||
3700 | (fpipemon_trc_t *)&fr_udp_pkt->data[buffer_length]; | ||
3701 | fpipemon_trc->fpipemon_trc_hdr.status = | ||
3702 | trc_el.attr; | ||
3703 | fpipemon_trc->fpipemon_trc_hdr.tmstamp = | ||
3704 | trc_el.tmstamp; | ||
3705 | fpipemon_trc->fpipemon_trc_hdr.length = | ||
3706 | trc_el.length; | ||
3707 | |||
3708 | if(!trc_el.offset || !trc_el.length) { | ||
3709 | |||
3710 | fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x00; | ||
3711 | |||
3712 | }else if((trc_el.length + sizeof(fpipemon_trc_hdr_t) + 1) > | ||
3713 | (card->u.f.trc_bfr_space - buffer_length)){ | ||
3714 | |||
3715 | fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x00; | ||
3716 | fr_udp_pkt->data[0x00] |= MORE_TRC_DATA; | ||
3717 | |||
3718 | }else { | ||
3719 | fpipemon_trc->fpipemon_trc_hdr.data_passed = 0x01; | ||
3720 | sdla_peek(&card->hw, trc_el.offset, | ||
3721 | fpipemon_trc->data, | ||
3722 | trc_el.length); | ||
3723 | } | ||
3724 | |||
3725 | trc_el.flag = 0x00; | ||
3726 | sdla_poke(&card->hw, (unsigned long)ptr_trc_el, | ||
3727 | &trc_el.flag, 1); | ||
3728 | |||
3729 | ptr_trc_el ++; | ||
3730 | if((void *)ptr_trc_el > card->u.f.trc_el_last) | ||
3731 | ptr_trc_el = (void*)card->u.f.trc_el_base; | ||
3732 | |||
3733 | buffer_length += sizeof(fpipemon_trc_hdr_t); | ||
3734 | if(fpipemon_trc->fpipemon_trc_hdr.data_passed) { | ||
3735 | buffer_length += trc_el.length; | ||
3736 | } | ||
3737 | |||
3738 | if(fr_udp_pkt->data[0x00] & MORE_TRC_DATA) { | ||
3739 | break; | ||
3740 | } | ||
3741 | } | ||
3742 | |||
3743 | if(frames == MAX_FRMS_TRACED) { | ||
3744 | fr_udp_pkt->data[0x00] |= MORE_TRC_DATA; | ||
3745 | } | ||
3746 | |||
3747 | card->u.f.curr_trc_el = (void *)ptr_trc_el; | ||
3748 | |||
3749 | /* set the total number of frames passed */ | ||
3750 | fr_udp_pkt->data[0x00] |= | ||
3751 | ((frames << 1) & (MAX_FRMS_TRACED << 1)); | ||
3752 | |||
3753 | /* set the data length and return code */ | ||
3754 | fr_udp_pkt->cblock.length = mbox->cmd.length = buffer_length; | ||
3755 | fr_udp_pkt->cblock.result = 0; | ||
3756 | break; | ||
3757 | |||
3758 | case FPIPE_FT1_READ_STATUS: | ||
3759 | sdla_peek(&card->hw, 0xF020, | ||
3760 | &fr_udp_pkt->data[0x00] , 2); | ||
3761 | fr_udp_pkt->cblock.length = mbox->cmd.length = 2; | ||
3762 | fr_udp_pkt->cblock.result = 0; | ||
3763 | break; | ||
3764 | |||
3765 | case FPIPE_FLUSH_DRIVER_STATS: | ||
3766 | init_chan_statistics(chan); | ||
3767 | init_global_statistics(card); | ||
3768 | mbox->cmd.length = 0; | ||
3769 | break; | ||
3770 | |||
3771 | case FPIPE_ROUTER_UP_TIME: | ||
3772 | do_gettimeofday(&tv); | ||
3773 | chan->router_up_time = tv.tv_sec - | ||
3774 | chan->router_start_time; | ||
3775 | *(unsigned long *)&fr_udp_pkt->data = | ||
3776 | chan->router_up_time; | ||
3777 | mbox->cmd.length = fr_udp_pkt->cblock.length = 4; | ||
3778 | fr_udp_pkt->cblock.result = 0; | ||
3779 | break; | ||
3780 | |||
3781 | case FPIPE_DRIVER_STAT_IFSEND: | ||
3782 | memcpy(fr_udp_pkt->data, | ||
3783 | &chan->drvstats_if_send.if_send_entry, | ||
3784 | sizeof(if_send_stat_t)); | ||
3785 | mbox->cmd.length = fr_udp_pkt->cblock.length =sizeof(if_send_stat_t); | ||
3786 | fr_udp_pkt->cblock.result = 0; | ||
3787 | break; | ||
3788 | |||
3789 | case FPIPE_DRIVER_STAT_INTR: | ||
3790 | |||
3791 | memcpy(fr_udp_pkt->data, | ||
3792 | &card->statistics.isr_entry, | ||
3793 | sizeof(global_stats_t)); | ||
3794 | |||
3795 | memcpy(&fr_udp_pkt->data[sizeof(global_stats_t)], | ||
3796 | &chan->drvstats_rx_intr.rx_intr_no_socket, | ||
3797 | sizeof(rx_intr_stat_t)); | ||
3798 | |||
3799 | mbox->cmd.length = fr_udp_pkt->cblock.length = | ||
3800 | sizeof(global_stats_t) + | ||
3801 | sizeof(rx_intr_stat_t); | ||
3802 | fr_udp_pkt->cblock.result = 0; | ||
3803 | break; | ||
3804 | |||
3805 | case FPIPE_DRIVER_STAT_GEN: | ||
3806 | memcpy(fr_udp_pkt->data, | ||
3807 | &chan->drvstats_gen.UDP_PIPE_mgmt_kmalloc_err, | ||
3808 | sizeof(pipe_mgmt_stat_t)); | ||
3809 | |||
3810 | memcpy(&fr_udp_pkt->data[sizeof(pipe_mgmt_stat_t)], | ||
3811 | &card->statistics, sizeof(global_stats_t)); | ||
3812 | |||
3813 | mbox->cmd.length = fr_udp_pkt->cblock.length = sizeof(global_stats_t)+ | ||
3814 | sizeof(rx_intr_stat_t); | ||
3815 | fr_udp_pkt->cblock.result = 0; | ||
3816 | break; | ||
3817 | |||
3818 | |||
3819 | case FR_FT1_STATUS_CTRL: | ||
3820 | if(fr_udp_pkt->data[0] == 1) { | ||
3821 | if(rCount++ != 0 ){ | ||
3822 | fr_udp_pkt->cblock.result = 0; | ||
3823 | mbox->cmd.length = 1; | ||
3824 | break; | ||
3825 | } | ||
3826 | } | ||
3827 | |||
3828 | /* Disable FT1 MONITOR STATUS */ | ||
3829 | if(fr_udp_pkt->data[0] == 0) { | ||
3830 | if( --rCount != 0) { | ||
3831 | fr_udp_pkt->cblock.result = 0; | ||
3832 | mbox->cmd.length = 1; | ||
3833 | break; | ||
3834 | } | ||
3835 | } | ||
3836 | goto udp_mgmt_dflt; | ||
3837 | |||
3838 | |||
3839 | default: | ||
3840 | udp_mgmt_dflt: | ||
3841 | do { | ||
3842 | memcpy(&mbox->cmd, | ||
3843 | &fr_udp_pkt->cblock.command, | ||
3844 | sizeof(fr_cmd_t)); | ||
3845 | if(mbox->cmd.length) { | ||
3846 | memcpy(&mbox->data, | ||
3847 | (char *)fr_udp_pkt->data, | ||
3848 | mbox->cmd.length); | ||
3849 | } | ||
3850 | |||
3851 | err = sdla_exec(mbox) ? mbox->cmd.result : | ||
3852 | CMD_TIMEOUT; | ||
3853 | } while (err && c_retry-- && fr_event(card, err, mbox)); | ||
3854 | |||
3855 | if(!err) | ||
3856 | chan->drvstats_gen. | ||
3857 | UDP_PIPE_mgmt_adptr_cmnd_OK ++; | ||
3858 | else | ||
3859 | chan->drvstats_gen. | ||
3860 | UDP_PIPE_mgmt_adptr_cmnd_timeout ++; | ||
3861 | |||
3862 | /* copy the result back to our buffer */ | ||
3863 | memcpy(&fr_udp_pkt->cblock.command, | ||
3864 | &mbox->cmd, sizeof(fr_cmd_t)); | ||
3865 | |||
3866 | if(mbox->cmd.length) { | ||
3867 | memcpy(&fr_udp_pkt->data, | ||
3868 | &mbox->data, mbox->cmd.length); | ||
3869 | } | ||
3870 | } | ||
3871 | } | ||
3872 | |||
3873 | /* Fill UDP TTL */ | ||
3874 | fr_udp_pkt->ip_pkt.ttl = card->wandev.ttl; | ||
3875 | len = reply_udp(card->u.f.udp_pkt_data, mbox->cmd.length); | ||
3876 | |||
3877 | if(udp_pkt_src == UDP_PKT_FRM_NETWORK) { | ||
3878 | |||
3879 | chan->fr_header_len=2; | ||
3880 | chan->fr_header[0]=Q922_UI; | ||
3881 | chan->fr_header[1]=NLPID_IP; | ||
3882 | |||
3883 | err = fr_send_data_header(card, dlci, 0, len, | ||
3884 | card->u.f.udp_pkt_data,chan->fr_header_len); | ||
3885 | if (err){ | ||
3886 | chan->drvstats_gen.UDP_PIPE_mgmt_adptr_send_passed ++; | ||
3887 | }else{ | ||
3888 | chan->drvstats_gen.UDP_PIPE_mgmt_adptr_send_failed ++; | ||
3889 | } | ||
3890 | |||
3891 | } else { | ||
3892 | /* Allocate socket buffer */ | ||
3893 | if((new_skb = dev_alloc_skb(len)) != NULL) { | ||
3894 | |||
3895 | /* copy data into new_skb */ | ||
3896 | buf = skb_put(new_skb, len); | ||
3897 | memcpy(buf, card->u.f.udp_pkt_data, len); | ||
3898 | |||
3899 | chan->drvstats_gen. | ||
3900 | UDP_PIPE_mgmt_passed_to_stack ++; | ||
3901 | new_skb->dev = dev; | ||
3902 | new_skb->protocol = htons(ETH_P_IP); | ||
3903 | new_skb->mac.raw = new_skb->data; | ||
3904 | netif_rx(new_skb); | ||
3905 | |||
3906 | } else { | ||
3907 | chan->drvstats_gen.UDP_PIPE_mgmt_no_socket ++; | ||
3908 | printk(KERN_INFO | ||
3909 | "%s: UDP mgmt cmnd, no socket buffers available!\n", | ||
3910 | card->devname); | ||
3911 | } | ||
3912 | } | ||
3913 | |||
3914 | card->u.f.udp_pkt_lgth = 0; | ||
3915 | |||
3916 | return 1; | ||
3917 | } | ||
3918 | |||
3919 | /*============================================================================== | ||
3920 | * Send Inverse ARP Request | ||
3921 | */ | ||
3922 | |||
3923 | int send_inarp_request(sdla_t *card, struct net_device *dev) | ||
3924 | { | ||
3925 | int err=0; | ||
3926 | |||
3927 | arphdr_1490_t *ArpPacket; | ||
3928 | arphdr_fr_t *arphdr; | ||
3929 | fr_channel_t *chan = dev->priv; | ||
3930 | struct in_device *in_dev; | ||
3931 | |||
3932 | in_dev = dev->ip_ptr; | ||
3933 | |||
3934 | if(in_dev != NULL ) { | ||
3935 | |||
3936 | ArpPacket = kmalloc(sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), GFP_ATOMIC); | ||
3937 | /* SNAP Header indicating ARP */ | ||
3938 | ArpPacket->control = 0x03; | ||
3939 | ArpPacket->pad = 0x00; | ||
3940 | ArpPacket->NLPID = 0x80; | ||
3941 | ArpPacket->OUI[0] = 0; | ||
3942 | ArpPacket->OUI[1] = 0; | ||
3943 | ArpPacket->OUI[2] = 0; | ||
3944 | ArpPacket->PID = 0x0608; | ||
3945 | |||
3946 | arphdr = (arphdr_fr_t *)(ArpPacket + 1); // Go to ARP Packet | ||
3947 | |||
3948 | /* InARP request */ | ||
3949 | arphdr->ar_hrd = 0x0F00; /* Frame Relay HW type */ | ||
3950 | arphdr->ar_pro = 0x0008; /* IP Protocol */ | ||
3951 | arphdr->ar_hln = 2; /* HW addr length */ | ||
3952 | arphdr->ar_pln = 4; /* IP addr length */ | ||
3953 | arphdr->ar_op = htons(0x08); /* InARP Request */ | ||
3954 | arphdr->ar_sha = 0; /* src HW DLCI - Doesn't matter */ | ||
3955 | if(in_dev->ifa_list != NULL) | ||
3956 | arphdr->ar_sip = in_dev->ifa_list->ifa_local; /* Local Address */else | ||
3957 | arphdr->ar_sip = 0; | ||
3958 | arphdr->ar_tha = 0; /* dst HW DLCI - Doesn't matter */ | ||
3959 | arphdr->ar_tip = 0; /* Remote Address -- what we want */ | ||
3960 | |||
3961 | err = fr_send(card, chan->dlci, 0, sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), | ||
3962 | (void *)ArpPacket); | ||
3963 | |||
3964 | if (!err){ | ||
3965 | printk(KERN_INFO "\n%s: Sending InARP request on DLCI %d.\n", | ||
3966 | card->devname, chan->dlci); | ||
3967 | clear_bit(ARP_CRIT,&card->wandev.critical); | ||
3968 | } | ||
3969 | |||
3970 | kfree(ArpPacket); | ||
3971 | }else{ | ||
3972 | printk(KERN_INFO "%s: INARP ERROR: %s doesn't have a local IP address!\n", | ||
3973 | card->devname,dev->name); | ||
3974 | return 1; | ||
3975 | } | ||
3976 | |||
3977 | return 0; | ||
3978 | } | ||
3979 | |||
3980 | |||
3981 | /*============================================================================== | ||
3982 | * Check packet for ARP Type | ||
3983 | */ | ||
3984 | |||
3985 | int is_arp(void *buf) | ||
3986 | { | ||
3987 | arphdr_1490_t *arphdr = (arphdr_1490_t *)buf; | ||
3988 | |||
3989 | if (arphdr->pad == 0x00 && | ||
3990 | arphdr->NLPID == 0x80 && | ||
3991 | arphdr->PID == 0x0608) | ||
3992 | return 1; | ||
3993 | else return 0; | ||
3994 | } | ||
3995 | |||
3996 | /*============================================================================== | ||
3997 | * Process ARP Packet Type | ||
3998 | */ | ||
3999 | |||
4000 | int process_ARP(arphdr_1490_t *ArpPacket, sdla_t *card, struct net_device* dev) | ||
4001 | { | ||
4002 | |||
4003 | |||
4004 | arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */ | ||
4005 | fr_rx_buf_ctl_t* frbuf = card->rxmb; | ||
4006 | struct in_device *in_dev; | ||
4007 | fr_channel_t *chan = dev->priv; | ||
4008 | |||
4009 | /* Before we transmit ARP packet, we must check | ||
4010 | * to see that we are not currently transmitting a | ||
4011 | * frame (in 'if_send()') and that we are not | ||
4012 | * already in a 'delayed transmit' state. */ | ||
4013 | if (check_tx_status(card,dev)){ | ||
4014 | if (net_ratelimit()){ | ||
4015 | printk(KERN_INFO "%s: Disabling comminication to process ARP\n", | ||
4016 | card->devname); | ||
4017 | } | ||
4018 | set_bit(ARP_CRIT,&card->wandev.critical); | ||
4019 | return 0; | ||
4020 | } | ||
4021 | |||
4022 | in_dev = dev->ip_ptr; | ||
4023 | |||
4024 | /* Check that IP addresses exist for our network address */ | ||
4025 | if (in_dev == NULL || in_dev->ifa_list == NULL) | ||
4026 | return -1; | ||
4027 | |||
4028 | switch (ntohs(arphdr->ar_op)) { | ||
4029 | |||
4030 | case 0x08: // Inverse ARP request -- Send Reply, add route. | ||
4031 | |||
4032 | /* Check for valid Address */ | ||
4033 | printk(KERN_INFO "%s: Recvd PtP addr -InArp Req: %u.%u.%u.%u\n", | ||
4034 | card->devname, NIPQUAD(arphdr->ar_sip)); | ||
4035 | |||
4036 | |||
4037 | /* Check that the network address is the same as ours, only | ||
4038 | * if the netowrk mask is not 255.255.255.255. Otherwise | ||
4039 | * this check would not make sense */ | ||
4040 | |||
4041 | if (in_dev->ifa_list->ifa_mask != 0xFFFFFFFF && | ||
4042 | (in_dev->ifa_list->ifa_mask & arphdr->ar_sip) != | ||
4043 | (in_dev->ifa_list->ifa_mask & in_dev->ifa_list->ifa_local)){ | ||
4044 | printk(KERN_INFO | ||
4045 | "%s: Invalid PtP address. %u.%u.%u.%u InARP ignored.\n", | ||
4046 | card->devname,NIPQUAD(arphdr->ar_sip)); | ||
4047 | |||
4048 | printk(KERN_INFO "%s: mask %u.%u.%u.%u\n", | ||
4049 | card->devname, NIPQUAD(in_dev->ifa_list->ifa_mask)); | ||
4050 | printk(KERN_INFO "%s: local %u.%u.%u.%u\n", | ||
4051 | card->devname,NIPQUAD(in_dev->ifa_list->ifa_local)); | ||
4052 | return -1; | ||
4053 | } | ||
4054 | |||
4055 | if (in_dev->ifa_list->ifa_local == arphdr->ar_sip){ | ||
4056 | printk(KERN_INFO | ||
4057 | "%s: Local addr = PtP addr. InARP ignored.\n", | ||
4058 | card->devname); | ||
4059 | return -1; | ||
4060 | } | ||
4061 | |||
4062 | arphdr->ar_op = htons(0x09); /* InARP Reply */ | ||
4063 | |||
4064 | /* Set addresses */ | ||
4065 | arphdr->ar_tip = arphdr->ar_sip; | ||
4066 | arphdr->ar_sip = in_dev->ifa_list->ifa_local; | ||
4067 | |||
4068 | chan->ip_local = in_dev->ifa_list->ifa_local; | ||
4069 | chan->ip_remote = arphdr->ar_sip; | ||
4070 | |||
4071 | fr_send(card, frbuf->dlci, 0, frbuf->length, (void *)ArpPacket); | ||
4072 | |||
4073 | if (test_bit(ARP_CRIT,&card->wandev.critical)){ | ||
4074 | if (net_ratelimit()){ | ||
4075 | printk(KERN_INFO "%s: ARP Processed Enabling Communication!\n", | ||
4076 | card->devname); | ||
4077 | } | ||
4078 | } | ||
4079 | clear_bit(ARP_CRIT,&card->wandev.critical); | ||
4080 | |||
4081 | chan->ip_local = in_dev->ifa_list->ifa_local; | ||
4082 | chan->ip_remote = arphdr->ar_sip; | ||
4083 | |||
4084 | /* Add Route Flag */ | ||
4085 | /* The route will be added in the polling routine so | ||
4086 | that it is not interrupt context. */ | ||
4087 | |||
4088 | chan->route_flag = ADD_ROUTE; | ||
4089 | trigger_fr_poll (dev); | ||
4090 | |||
4091 | break; | ||
4092 | |||
4093 | case 0x09: // Inverse ARP reply | ||
4094 | |||
4095 | /* Check for valid Address */ | ||
4096 | printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Reply\n", | ||
4097 | card->devname, NIPQUAD(arphdr->ar_sip)); | ||
4098 | |||
4099 | |||
4100 | /* Compare network addresses, only if network mask | ||
4101 | * is not 255.255.255.255 It would not make sense | ||
4102 | * to perform this test if the mask was all 1's */ | ||
4103 | |||
4104 | if (in_dev->ifa_list->ifa_mask != 0xffffffff && | ||
4105 | (in_dev->ifa_list->ifa_mask & arphdr->ar_sip) != | ||
4106 | (in_dev->ifa_list->ifa_mask & in_dev->ifa_list->ifa_local)) { | ||
4107 | |||
4108 | printk(KERN_INFO "%s: Invalid PtP address. InARP ignored.\n", | ||
4109 | card->devname); | ||
4110 | return -1; | ||
4111 | } | ||
4112 | |||
4113 | /* Make sure that the received IP address is not | ||
4114 | * the same as our own local address */ | ||
4115 | if (in_dev->ifa_list->ifa_local == arphdr->ar_sip) { | ||
4116 | printk(KERN_INFO "%s: Local addr = PtP addr. InARP ignored.\n", | ||
4117 | card->devname); | ||
4118 | return -1; | ||
4119 | } | ||
4120 | |||
4121 | chan->ip_local = in_dev->ifa_list->ifa_local; | ||
4122 | chan->ip_remote = arphdr->ar_sip; | ||
4123 | |||
4124 | /* Add Route Flag */ | ||
4125 | /* The route will be added in the polling routine so | ||
4126 | that it is not interrupt context. */ | ||
4127 | |||
4128 | chan->route_flag = ADD_ROUTE; | ||
4129 | chan->inarp = INARP_CONFIGURED; | ||
4130 | trigger_fr_poll(dev); | ||
4131 | |||
4132 | break; | ||
4133 | default: | ||
4134 | break; // ARP's and RARP's -- Shouldn't happen. | ||
4135 | } | ||
4136 | |||
4137 | return 0; | ||
4138 | } | ||
4139 | |||
4140 | |||
4141 | /*============================================================ | ||
4142 | * trigger_fr_arp | ||
4143 | * | ||
4144 | * Description: | ||
4145 | * Add an fr_arp() task into a arp | ||
4146 | * timer handler for a specific dlci/interface. | ||
4147 | * This will kick the fr_arp() routine | ||
4148 | * within the specified time interval. | ||
4149 | * | ||
4150 | * Usage: | ||
4151 | * This timer is used to send ARP requests at | ||
4152 | * certain time intervals. | ||
4153 | * Called by an interrupt to request an action | ||
4154 | * at a later date. | ||
4155 | */ | ||
4156 | |||
4157 | static void trigger_fr_arp(struct net_device *dev) | ||
4158 | { | ||
4159 | fr_channel_t* chan = dev->priv; | ||
4160 | |||
4161 | mod_timer(&chan->fr_arp_timer, jiffies + chan->inarp_interval * HZ); | ||
4162 | return; | ||
4163 | } | ||
4164 | |||
4165 | |||
4166 | |||
4167 | /*============================================================================== | ||
4168 | * ARP Request Action | ||
4169 | * | ||
4170 | * This funciton is called by timer interrupt to send an arp request | ||
4171 | * to the remote end. | ||
4172 | */ | ||
4173 | |||
4174 | static void fr_arp (unsigned long data) | ||
4175 | { | ||
4176 | struct net_device *dev = (struct net_device *)data; | ||
4177 | fr_channel_t *chan = dev->priv; | ||
4178 | volatile sdla_t *card = chan->card; | ||
4179 | fr508_flags_t* flags = card->flags; | ||
4180 | |||
4181 | /* Send ARP packets for all devs' until | ||
4182 | * ARP state changes to CONFIGURED */ | ||
4183 | |||
4184 | if (chan->inarp == INARP_REQUEST && | ||
4185 | chan->common.state == WAN_CONNECTED && | ||
4186 | card->wandev.state == WAN_CONNECTED){ | ||
4187 | set_bit(0,&chan->inarp_ready); | ||
4188 | card->u.f.timer_int_enabled |= TMR_INT_ENABLED_ARP; | ||
4189 | flags->imask |= FR_INTR_TIMER; | ||
4190 | } | ||
4191 | |||
4192 | return; | ||
4193 | } | ||
4194 | |||
4195 | |||
4196 | /*============================================================================== | ||
4197 | * Perform the Interrupt Test by running the READ_CODE_VERSION command MAX_INTR_ | ||
4198 | * TEST_COUNTER times. | ||
4199 | */ | ||
4200 | static int intr_test( sdla_t* card ) | ||
4201 | { | ||
4202 | fr_mbox_t* mb = card->mbox; | ||
4203 | int err,i; | ||
4204 | |||
4205 | err = fr_set_intr_mode(card, FR_INTR_READY, card->wandev.mtu, 0 ); | ||
4206 | |||
4207 | if (err == CMD_OK) { | ||
4208 | |||
4209 | for ( i = 0; i < MAX_INTR_TEST_COUNTER; i++ ) { | ||
4210 | /* Run command READ_CODE_VERSION */ | ||
4211 | mb->cmd.length = 0; | ||
4212 | mb->cmd.command = FR_READ_CODE_VERSION; | ||
4213 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
4214 | if (err != CMD_OK) | ||
4215 | fr_event(card, err, mb); | ||
4216 | } | ||
4217 | |||
4218 | } else { | ||
4219 | return err; | ||
4220 | } | ||
4221 | |||
4222 | err = fr_set_intr_mode( card, 0, card->wandev.mtu, 0 ); | ||
4223 | |||
4224 | if( err != CMD_OK ) | ||
4225 | return err; | ||
4226 | |||
4227 | return 0; | ||
4228 | } | ||
4229 | |||
4230 | /*============================================================================== | ||
4231 | * Determine what type of UDP call it is. FPIPE8ND ? | ||
4232 | */ | ||
4233 | static int udp_pkt_type( struct sk_buff *skb, sdla_t* card ) | ||
4234 | { | ||
4235 | fr_udp_pkt_t *fr_udp_pkt = (fr_udp_pkt_t *)skb->data; | ||
4236 | |||
4237 | /* Quick HACK */ | ||
4238 | |||
4239 | |||
4240 | if((fr_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) && | ||
4241 | (fr_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45) && | ||
4242 | (fr_udp_pkt->udp_pkt.udp_dst_port == | ||
4243 | ntohs(card->wandev.udp_port)) && | ||
4244 | (fr_udp_pkt->wp_mgmt.request_reply == | ||
4245 | UDPMGMT_REQUEST)) { | ||
4246 | if(!strncmp(fr_udp_pkt->wp_mgmt.signature, | ||
4247 | UDPMGMT_FPIPE_SIGNATURE, 8)){ | ||
4248 | return UDP_FPIPE_TYPE; | ||
4249 | } | ||
4250 | } | ||
4251 | return UDP_INVALID_TYPE; | ||
4252 | } | ||
4253 | |||
4254 | |||
4255 | /*============================================================================== | ||
4256 | * Initializes the Statistics values in the fr_channel structure. | ||
4257 | */ | ||
4258 | void init_chan_statistics( fr_channel_t* chan) | ||
4259 | { | ||
4260 | memset(&chan->drvstats_if_send.if_send_entry, 0, | ||
4261 | sizeof(if_send_stat_t)); | ||
4262 | memset(&chan->drvstats_rx_intr.rx_intr_no_socket, 0, | ||
4263 | sizeof(rx_intr_stat_t)); | ||
4264 | memset(&chan->drvstats_gen.UDP_PIPE_mgmt_kmalloc_err, 0, | ||
4265 | sizeof(pipe_mgmt_stat_t)); | ||
4266 | } | ||
4267 | |||
4268 | /*============================================================================== | ||
4269 | * Initializes the Statistics values in the Sdla_t structure. | ||
4270 | */ | ||
4271 | void init_global_statistics( sdla_t* card ) | ||
4272 | { | ||
4273 | /* Intialize global statistics for a card */ | ||
4274 | memset(&card->statistics.isr_entry, 0, sizeof(global_stats_t)); | ||
4275 | } | ||
4276 | |||
4277 | static void read_DLCI_IB_mapping( sdla_t* card, fr_channel_t* chan ) | ||
4278 | { | ||
4279 | fr_mbox_t* mbox = card->mbox; | ||
4280 | int retry = MAX_CMD_RETRY; | ||
4281 | dlci_IB_mapping_t* result; | ||
4282 | int err, counter, found; | ||
4283 | |||
4284 | do { | ||
4285 | mbox->cmd.command = FR_READ_DLCI_IB_MAPPING; | ||
4286 | mbox->cmd.length = 0; | ||
4287 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
4288 | } while (err && retry-- && fr_event(card, err, mbox)); | ||
4289 | |||
4290 | if( mbox->cmd.result != 0){ | ||
4291 | printk(KERN_INFO "%s: Read DLCI IB Mapping failed\n", | ||
4292 | chan->name); | ||
4293 | } | ||
4294 | |||
4295 | counter = mbox->cmd.length / sizeof(dlci_IB_mapping_t); | ||
4296 | result = (void *)mbox->data; | ||
4297 | |||
4298 | found = 0; | ||
4299 | for (; counter; --counter, ++result) { | ||
4300 | if ( result->dlci == chan->dlci ) { | ||
4301 | chan->IB_addr = result->addr_value; | ||
4302 | if(card->hw.type == SDLA_S514){ | ||
4303 | chan->dlci_int_interface = | ||
4304 | (void*)(card->hw.dpmbase + | ||
4305 | chan->IB_addr); | ||
4306 | }else{ | ||
4307 | chan->dlci_int_interface = | ||
4308 | (void*)(card->hw.dpmbase + | ||
4309 | (chan->IB_addr & 0x00001FFF)); | ||
4310 | |||
4311 | } | ||
4312 | found = 1; | ||
4313 | break; | ||
4314 | } | ||
4315 | } | ||
4316 | if (!found) | ||
4317 | printk( KERN_INFO "%s: DLCI %d not found by IB MAPPING cmd\n", | ||
4318 | card->devname, chan->dlci); | ||
4319 | } | ||
4320 | |||
4321 | |||
4322 | |||
4323 | void s508_s514_lock(sdla_t *card, unsigned long *smp_flags) | ||
4324 | { | ||
4325 | if (card->hw.type != SDLA_S514){ | ||
4326 | |||
4327 | spin_lock_irqsave(&card->wandev.lock, *smp_flags); | ||
4328 | }else{ | ||
4329 | spin_lock(&card->u.f.if_send_lock); | ||
4330 | } | ||
4331 | return; | ||
4332 | } | ||
4333 | |||
4334 | |||
4335 | void s508_s514_unlock(sdla_t *card, unsigned long *smp_flags) | ||
4336 | { | ||
4337 | if (card->hw.type != SDLA_S514){ | ||
4338 | |||
4339 | spin_unlock_irqrestore (&card->wandev.lock, *smp_flags); | ||
4340 | }else{ | ||
4341 | spin_unlock(&card->u.f.if_send_lock); | ||
4342 | } | ||
4343 | return; | ||
4344 | } | ||
4345 | |||
4346 | |||
4347 | |||
4348 | /*---------------------------------------------------------------------- | ||
4349 | RECEIVE INTERRUPT: BOTTOM HALF HANDLERS | ||
4350 | ----------------------------------------------------------------------*/ | ||
4351 | |||
4352 | |||
4353 | /*======================================================== | ||
4354 | * bh_enqueue | ||
4355 | * | ||
4356 | * Description: | ||
4357 | * Insert a received packet into a circular | ||
4358 | * rx queue. This packet will be picked up | ||
4359 | * by fr_bh() and sent up the stack to the | ||
4360 | * user. | ||
4361 | * | ||
4362 | * Usage: | ||
4363 | * This function is called by rx interrupt, | ||
4364 | * in API mode. | ||
4365 | * | ||
4366 | */ | ||
4367 | |||
4368 | static int bh_enqueue(struct net_device *dev, struct sk_buff *skb) | ||
4369 | { | ||
4370 | /* Check for full */ | ||
4371 | fr_channel_t* chan = dev->priv; | ||
4372 | sdla_t *card = chan->card; | ||
4373 | |||
4374 | |||
4375 | if (atomic_read(&chan->bh_buff_used) == MAX_BH_BUFF){ | ||
4376 | ++card->wandev.stats.rx_dropped; | ||
4377 | dev_kfree_skb_any(skb); | ||
4378 | return 1; | ||
4379 | } | ||
4380 | |||
4381 | ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb; | ||
4382 | |||
4383 | if (chan->bh_write == (MAX_BH_BUFF-1)){ | ||
4384 | chan->bh_write=0; | ||
4385 | }else{ | ||
4386 | ++chan->bh_write; | ||
4387 | } | ||
4388 | |||
4389 | atomic_inc(&chan->bh_buff_used); | ||
4390 | |||
4391 | return 0; | ||
4392 | } | ||
4393 | |||
4394 | |||
4395 | /*======================================================== | ||
4396 | * trigger_fr_bh | ||
4397 | * | ||
4398 | * Description: | ||
4399 | * Kick the fr_bh() handler | ||
4400 | * | ||
4401 | * Usage: | ||
4402 | * rx interrupt calls this function during | ||
4403 | * the API mode. | ||
4404 | */ | ||
4405 | |||
4406 | static void trigger_fr_bh (fr_channel_t *chan) | ||
4407 | { | ||
4408 | if (!test_and_set_bit(0,&chan->tq_working)){ | ||
4409 | wanpipe_queue_work(&chan->common.wanpipe_work); | ||
4410 | } | ||
4411 | } | ||
4412 | |||
4413 | |||
4414 | /*======================================================== | ||
4415 | * fr_bh | ||
4416 | * | ||
4417 | * Description: | ||
4418 | * Frame relay receive BH handler. | ||
4419 | * Dequeue data from the BH circular | ||
4420 | * buffer and pass it up the API sock. | ||
4421 | * | ||
4422 | * Rationale: | ||
4423 | * This fuction is used to offload the | ||
4424 | * rx_interrupt during API operation mode. | ||
4425 | * The fr_bh() function executes for each | ||
4426 | * dlci/interface. | ||
4427 | * | ||
4428 | * Once receive interrupt copies data from the | ||
4429 | * card into an skb buffer, the skb buffer | ||
4430 | * is appended to a circular BH buffer. | ||
4431 | * Then the interrupt kicks fr_bh() to finish the | ||
4432 | * job at a later time (not within the interrupt). | ||
4433 | * | ||
4434 | * Usage: | ||
4435 | * Interrupts use this to defer a task to | ||
4436 | * a polling routine. | ||
4437 | * | ||
4438 | */ | ||
4439 | |||
4440 | static void fr_bh(struct net_device * dev) | ||
4441 | { | ||
4442 | fr_channel_t* chan = dev->priv; | ||
4443 | sdla_t *card = chan->card; | ||
4444 | struct sk_buff *skb; | ||
4445 | |||
4446 | if (atomic_read(&chan->bh_buff_used) == 0){ | ||
4447 | clear_bit(0, &chan->tq_working); | ||
4448 | return; | ||
4449 | } | ||
4450 | |||
4451 | while (atomic_read(&chan->bh_buff_used)){ | ||
4452 | |||
4453 | if (chan->common.sk == NULL || chan->common.func == NULL){ | ||
4454 | clear_bit(0, &chan->tq_working); | ||
4455 | return; | ||
4456 | } | ||
4457 | |||
4458 | skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb; | ||
4459 | |||
4460 | if (skb != NULL){ | ||
4461 | |||
4462 | if (chan->common.sk == NULL || chan->common.func == NULL){ | ||
4463 | ++card->wandev.stats.rx_dropped; | ||
4464 | ++chan->ifstats.rx_dropped; | ||
4465 | dev_kfree_skb_any(skb); | ||
4466 | fr_bh_cleanup(dev); | ||
4467 | continue; | ||
4468 | } | ||
4469 | |||
4470 | if (chan->common.func(skb,dev,chan->common.sk) != 0){ | ||
4471 | /* Sock full cannot send, queue us for | ||
4472 | * another try */ | ||
4473 | atomic_set(&chan->common.receive_block,1); | ||
4474 | return; | ||
4475 | }else{ | ||
4476 | fr_bh_cleanup(dev); | ||
4477 | } | ||
4478 | }else{ | ||
4479 | fr_bh_cleanup(dev); | ||
4480 | } | ||
4481 | } | ||
4482 | clear_bit(0, &chan->tq_working); | ||
4483 | |||
4484 | return; | ||
4485 | } | ||
4486 | |||
4487 | static int fr_bh_cleanup(struct net_device *dev) | ||
4488 | { | ||
4489 | fr_channel_t* chan = dev->priv; | ||
4490 | |||
4491 | ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL; | ||
4492 | |||
4493 | if (chan->bh_read == (MAX_BH_BUFF-1)){ | ||
4494 | chan->bh_read=0; | ||
4495 | }else{ | ||
4496 | ++chan->bh_read; | ||
4497 | } | ||
4498 | |||
4499 | atomic_dec(&chan->bh_buff_used); | ||
4500 | return 0; | ||
4501 | } | ||
4502 | |||
4503 | |||
4504 | /*---------------------------------------------------------------------- | ||
4505 | POLL BH HANDLERS AND KICK ROUTINES | ||
4506 | ----------------------------------------------------------------------*/ | ||
4507 | |||
4508 | /*============================================================ | ||
4509 | * trigger_fr_poll | ||
4510 | * | ||
4511 | * Description: | ||
4512 | * Add a fr_poll() task into a tq_scheduler bh handler | ||
4513 | * for a specific dlci/interface. This will kick | ||
4514 | * the fr_poll() routine at a later time. | ||
4515 | * | ||
4516 | * Usage: | ||
4517 | * Interrupts use this to defer a taks to | ||
4518 | * a polling routine. | ||
4519 | * | ||
4520 | */ | ||
4521 | static void trigger_fr_poll(struct net_device *dev) | ||
4522 | { | ||
4523 | fr_channel_t* chan = dev->priv; | ||
4524 | schedule_work(&chan->fr_poll_work); | ||
4525 | return; | ||
4526 | } | ||
4527 | |||
4528 | |||
4529 | /*============================================================ | ||
4530 | * fr_poll | ||
4531 | * | ||
4532 | * Rationale: | ||
4533 | * We cannot manipulate the routing tables, or | ||
4534 | * ip addresses withing the interrupt. Therefore | ||
4535 | * we must perform such actons outside an interrupt | ||
4536 | * at a later time. | ||
4537 | * | ||
4538 | * Description: | ||
4539 | * Frame relay polling routine, responsible for | ||
4540 | * shutting down interfaces upon disconnect | ||
4541 | * and adding/removing routes. | ||
4542 | * | ||
4543 | * Usage: | ||
4544 | * This function is executed for each frame relay | ||
4545 | * dlci/interface through a tq_schedule bottom half. | ||
4546 | * | ||
4547 | * trigger_fr_poll() function is used to kick | ||
4548 | * the fr_poll routine. | ||
4549 | */ | ||
4550 | |||
4551 | static void fr_poll(struct net_device *dev) | ||
4552 | { | ||
4553 | |||
4554 | fr_channel_t* chan; | ||
4555 | sdla_t *card; | ||
4556 | u8 check_gateway=0; | ||
4557 | |||
4558 | if (!dev || (chan = dev->priv) == NULL) | ||
4559 | return; | ||
4560 | |||
4561 | card = chan->card; | ||
4562 | |||
4563 | /* (Re)Configuraiton is in progress, stop what you are | ||
4564 | * doing and get out */ | ||
4565 | if (test_bit(PERI_CRIT,&card->wandev.critical)){ | ||
4566 | return; | ||
4567 | } | ||
4568 | |||
4569 | switch (chan->common.state){ | ||
4570 | |||
4571 | case WAN_DISCONNECTED: | ||
4572 | |||
4573 | if (test_bit(DYN_OPT_ON,&chan->interface_down) && | ||
4574 | !test_bit(DEV_DOWN, &chan->interface_down) && | ||
4575 | dev->flags&IFF_UP){ | ||
4576 | |||
4577 | printk(KERN_INFO "%s: Interface %s is Down.\n", | ||
4578 | card->devname,dev->name); | ||
4579 | change_dev_flags(dev,dev->flags&~IFF_UP); | ||
4580 | set_bit(DEV_DOWN, &chan->interface_down); | ||
4581 | chan->route_flag = NO_ROUTE; | ||
4582 | |||
4583 | }else{ | ||
4584 | if (chan->inarp != INARP_NONE) | ||
4585 | process_route(dev); | ||
4586 | } | ||
4587 | break; | ||
4588 | |||
4589 | case WAN_CONNECTED: | ||
4590 | |||
4591 | if (test_bit(DYN_OPT_ON,&chan->interface_down) && | ||
4592 | test_bit(DEV_DOWN, &chan->interface_down) && | ||
4593 | !(dev->flags&IFF_UP)){ | ||
4594 | |||
4595 | printk(KERN_INFO "%s: Interface %s is Up.\n", | ||
4596 | card->devname,dev->name); | ||
4597 | |||
4598 | change_dev_flags(dev,dev->flags|IFF_UP); | ||
4599 | clear_bit(DEV_DOWN, &chan->interface_down); | ||
4600 | check_gateway=1; | ||
4601 | } | ||
4602 | |||
4603 | if (chan->inarp != INARP_NONE){ | ||
4604 | process_route(dev); | ||
4605 | check_gateway=1; | ||
4606 | } | ||
4607 | |||
4608 | if (chan->gateway && check_gateway) | ||
4609 | add_gateway(card,dev); | ||
4610 | |||
4611 | break; | ||
4612 | |||
4613 | } | ||
4614 | |||
4615 | return; | ||
4616 | } | ||
4617 | |||
4618 | /*============================================================== | ||
4619 | * check_tx_status | ||
4620 | * | ||
4621 | * Rationale: | ||
4622 | * We cannot transmit from an interrupt while | ||
4623 | * the if_send is transmitting data. Therefore, | ||
4624 | * we must check whether the tx buffers are | ||
4625 | * begin used, before we transmit from an | ||
4626 | * interrupt. | ||
4627 | * | ||
4628 | * Description: | ||
4629 | * Checks whether it's safe to use the transmit | ||
4630 | * buffers. | ||
4631 | * | ||
4632 | * Usage: | ||
4633 | * ARP and UDP handling routines use this function | ||
4634 | * because, they need to transmit data during | ||
4635 | * an interrupt. | ||
4636 | */ | ||
4637 | |||
4638 | static int check_tx_status(sdla_t *card, struct net_device *dev) | ||
4639 | { | ||
4640 | |||
4641 | if (card->hw.type == SDLA_S514){ | ||
4642 | if (test_bit(SEND_CRIT, (void*)&card->wandev.critical) || | ||
4643 | test_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical)) { | ||
4644 | return 1; | ||
4645 | } | ||
4646 | } | ||
4647 | |||
4648 | if (netif_queue_stopped(dev) || (card->u.f.tx_interrupts_pending)) | ||
4649 | return 1; | ||
4650 | |||
4651 | return 0; | ||
4652 | } | ||
4653 | |||
4654 | /*=============================================================== | ||
4655 | * move_dev_to_next | ||
4656 | * | ||
4657 | * Description: | ||
4658 | * Move the dev pointer to the next location in the | ||
4659 | * link list. Check if we are at the end of the | ||
4660 | * list, if so start from the begining. | ||
4661 | * | ||
4662 | * Usage: | ||
4663 | * Timer interrupt uses this function to efficiently | ||
4664 | * step through the devices that need to send ARP data. | ||
4665 | * | ||
4666 | */ | ||
4667 | |||
4668 | struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev) | ||
4669 | { | ||
4670 | if (card->wandev.new_if_cnt != 1){ | ||
4671 | if (!*((struct net_device **)dev->priv)) | ||
4672 | return card->wandev.dev; | ||
4673 | else | ||
4674 | return *((struct net_device **)dev->priv); | ||
4675 | } | ||
4676 | return dev; | ||
4677 | } | ||
4678 | |||
4679 | /*============================================================== | ||
4680 | * trigger_config_fr | ||
4681 | * | ||
4682 | * Rationale: | ||
4683 | * All commands must be performed inside of a | ||
4684 | * interrupt. | ||
4685 | * | ||
4686 | * Description: | ||
4687 | * Kick the config_fr() routine throught the | ||
4688 | * timer interrupt. | ||
4689 | */ | ||
4690 | |||
4691 | |||
4692 | static void trigger_config_fr (sdla_t *card) | ||
4693 | { | ||
4694 | fr508_flags_t* flags = card->flags; | ||
4695 | |||
4696 | card->u.f.timer_int_enabled |= TMR_INT_ENABLED_CONFIG; | ||
4697 | flags->imask |= FR_INTR_TIMER; | ||
4698 | } | ||
4699 | |||
4700 | |||
4701 | /*============================================================== | ||
4702 | * config_fr | ||
4703 | * | ||
4704 | * Rationale: | ||
4705 | * All commands must be performed inside of a | ||
4706 | * interrupt. | ||
4707 | & | ||
4708 | * Description: | ||
4709 | * Configure a DLCI. This function is executed | ||
4710 | * by a timer_interrupt. The if_open() function | ||
4711 | * triggers it. | ||
4712 | * | ||
4713 | * Usage: | ||
4714 | * new_if() collects all data necessary to | ||
4715 | * configure the DLCI. It sets the chan->dlci_ready | ||
4716 | * bit. When the if_open() function is executed | ||
4717 | * it checks this bit, and if its set it triggers | ||
4718 | * the timer interrupt to execute the config_fr() | ||
4719 | * function. | ||
4720 | */ | ||
4721 | |||
4722 | static void config_fr (sdla_t *card) | ||
4723 | { | ||
4724 | struct net_device *dev; | ||
4725 | fr_channel_t *chan; | ||
4726 | |||
4727 | for (dev = card->wandev.dev; dev; | ||
4728 | dev = *((struct net_device **)dev->priv)) { | ||
4729 | |||
4730 | if ((chan=dev->priv) == NULL) | ||
4731 | continue; | ||
4732 | |||
4733 | if (!test_bit(0,&chan->config_dlci)) | ||
4734 | continue; | ||
4735 | |||
4736 | clear_bit(0,&chan->config_dlci); | ||
4737 | |||
4738 | /* If signalling is set to NO, then setup | ||
4739 | * DLCI addresses right away. Don't have to wait for | ||
4740 | * link to connect. | ||
4741 | */ | ||
4742 | if (card->wandev.signalling == WANOPT_NO){ | ||
4743 | printk(KERN_INFO "%s: Signalling set to NO: Mapping DLCI's\n", | ||
4744 | card->wandev.name); | ||
4745 | if (fr_init_dlci(card,chan)){ | ||
4746 | printk(KERN_INFO "%s: ERROR: Failed to configure DLCI %i !\n", | ||
4747 | card->devname, chan->dlci); | ||
4748 | return; | ||
4749 | } | ||
4750 | } | ||
4751 | |||
4752 | if (card->wandev.station == WANOPT_CPE) { | ||
4753 | |||
4754 | update_chan_state(dev); | ||
4755 | |||
4756 | /* CPE: issue full status enquiry */ | ||
4757 | fr_issue_isf(card, FR_ISF_FSE); | ||
4758 | |||
4759 | } else { | ||
4760 | /* FR switch: activate DLCI(s) */ | ||
4761 | |||
4762 | /* For Switch emulation we have to ADD and ACTIVATE | ||
4763 | * the DLCI(s) that were configured with the SET_DLCI_ | ||
4764 | * CONFIGURATION command. Add and Activate will fail if | ||
4765 | * DLCI specified is not included in the list. | ||
4766 | * | ||
4767 | * Also If_open is called once for each interface. But | ||
4768 | * it does not get in here for all the interface. So | ||
4769 | * we have to pass the entire list of DLCI(s) to add | ||
4770 | * activate routines. | ||
4771 | */ | ||
4772 | |||
4773 | if (!check_dlci_config (card, chan)){ | ||
4774 | fr_add_dlci(card, chan->dlci); | ||
4775 | fr_activate_dlci(card, chan->dlci); | ||
4776 | } | ||
4777 | } | ||
4778 | |||
4779 | card->u.f.dlci_to_dev_map[chan->dlci] = dev; | ||
4780 | } | ||
4781 | return; | ||
4782 | } | ||
4783 | |||
4784 | |||
4785 | /*============================================================== | ||
4786 | * config_fr | ||
4787 | * | ||
4788 | * Rationale: | ||
4789 | * All commands must be executed during an interrupt. | ||
4790 | * | ||
4791 | * Description: | ||
4792 | * Trigger uncofig_fr() function through | ||
4793 | * the timer interrupt. | ||
4794 | * | ||
4795 | */ | ||
4796 | |||
4797 | static void trigger_unconfig_fr(struct net_device *dev) | ||
4798 | { | ||
4799 | fr_channel_t *chan = dev->priv; | ||
4800 | volatile sdla_t *card = chan->card; | ||
4801 | unsigned long timeout; | ||
4802 | fr508_flags_t* flags = card->flags; | ||
4803 | int reset_critical=0; | ||
4804 | |||
4805 | if (test_bit(PERI_CRIT,(void*)&card->wandev.critical)){ | ||
4806 | clear_bit(PERI_CRIT,(void*)&card->wandev.critical); | ||
4807 | reset_critical=1; | ||
4808 | } | ||
4809 | |||
4810 | /* run unconfig_dlci() function | ||
4811 | * throught the timer interrupt */ | ||
4812 | set_bit(0,(void*)&chan->unconfig_dlci); | ||
4813 | card->u.f.timer_int_enabled |= TMR_INT_ENABLED_UNCONFIG; | ||
4814 | flags->imask |= FR_INTR_TIMER; | ||
4815 | |||
4816 | /* Wait for the command to complete */ | ||
4817 | timeout = jiffies; | ||
4818 | for(;;) { | ||
4819 | |||
4820 | if(!(card->u.f.timer_int_enabled & TMR_INT_ENABLED_UNCONFIG)) | ||
4821 | break; | ||
4822 | |||
4823 | if (time_after(jiffies, timeout + 1 * HZ)){ | ||
4824 | card->u.f.timer_int_enabled &= ~TMR_INT_ENABLED_UNCONFIG; | ||
4825 | printk(KERN_INFO "%s: Failed to delete DLCI %i\n", | ||
4826 | card->devname,chan->dlci); | ||
4827 | break; | ||
4828 | } | ||
4829 | } | ||
4830 | |||
4831 | if (reset_critical){ | ||
4832 | set_bit(PERI_CRIT,(void*)&card->wandev.critical); | ||
4833 | } | ||
4834 | } | ||
4835 | |||
4836 | /*============================================================== | ||
4837 | * unconfig_fr | ||
4838 | * | ||
4839 | * Rationale: | ||
4840 | * All commands must be executed during an interrupt. | ||
4841 | * | ||
4842 | * Description: | ||
4843 | * Remove the dlci from firmware. | ||
4844 | * This funciton is used in NODE shutdown. | ||
4845 | */ | ||
4846 | |||
4847 | static void unconfig_fr (sdla_t *card) | ||
4848 | { | ||
4849 | struct net_device *dev; | ||
4850 | fr_channel_t *chan; | ||
4851 | |||
4852 | for (dev = card->wandev.dev; dev; | ||
4853 | dev = *((struct net_device **)dev->priv)){ | ||
4854 | |||
4855 | if ((chan=dev->priv) == NULL) | ||
4856 | continue; | ||
4857 | |||
4858 | if (!test_bit(0,&chan->unconfig_dlci)) | ||
4859 | continue; | ||
4860 | |||
4861 | clear_bit(0,&chan->unconfig_dlci); | ||
4862 | |||
4863 | if (card->wandev.station == WANOPT_NODE){ | ||
4864 | printk(KERN_INFO "%s: Unconfiguring DLCI %i\n", | ||
4865 | card->devname,chan->dlci); | ||
4866 | fr_delete_dlci(card,chan->dlci); | ||
4867 | } | ||
4868 | card->u.f.dlci_to_dev_map[chan->dlci] = NULL; | ||
4869 | } | ||
4870 | } | ||
4871 | |||
4872 | static int setup_fr_header(struct sk_buff *skb, struct net_device* dev, | ||
4873 | char op_mode) | ||
4874 | { | ||
4875 | fr_channel_t *chan=dev->priv; | ||
4876 | |||
4877 | if (op_mode == WANPIPE) { | ||
4878 | chan->fr_header[0]=Q922_UI; | ||
4879 | |||
4880 | switch (htons(skb->protocol)){ | ||
4881 | case ETH_P_IP: | ||
4882 | chan->fr_header[1]=NLPID_IP; | ||
4883 | break; | ||
4884 | default: | ||
4885 | return -EINVAL; | ||
4886 | } | ||
4887 | |||
4888 | return 2; | ||
4889 | } | ||
4890 | |||
4891 | /* If we are in bridging mode, we must apply | ||
4892 | * an Ethernet header | ||
4893 | */ | ||
4894 | if (op_mode == BRIDGE || op_mode == BRIDGE_NODE) { | ||
4895 | /* Encapsulate the packet as a bridged Ethernet frame. */ | ||
4896 | #ifdef DEBUG | ||
4897 | printk(KERN_INFO "%s: encapsulating skb for frame relay\n", | ||
4898 | dev->name); | ||
4899 | #endif | ||
4900 | chan->fr_header[0] = 0x03; | ||
4901 | chan->fr_header[1] = 0x00; | ||
4902 | chan->fr_header[2] = 0x80; | ||
4903 | chan->fr_header[3] = 0x00; | ||
4904 | chan->fr_header[4] = 0x80; | ||
4905 | chan->fr_header[5] = 0xC2; | ||
4906 | chan->fr_header[6] = 0x00; | ||
4907 | chan->fr_header[7] = 0x07; | ||
4908 | |||
4909 | /* Yuck. */ | ||
4910 | skb->protocol = ETH_P_802_3; | ||
4911 | return 8; | ||
4912 | } | ||
4913 | |||
4914 | return 0; | ||
4915 | } | ||
4916 | |||
4917 | |||
4918 | static int check_dlci_config (sdla_t *card, fr_channel_t *chan) | ||
4919 | { | ||
4920 | fr_mbox_t* mbox = card->mbox; | ||
4921 | int err=0; | ||
4922 | fr_conf_t *conf=NULL; | ||
4923 | unsigned short dlci_num = chan->dlci; | ||
4924 | int dlci_offset=0; | ||
4925 | struct net_device *dev = NULL; | ||
4926 | |||
4927 | mbox->cmd.command = FR_READ_CONFIG; | ||
4928 | mbox->cmd.length = 0; | ||
4929 | mbox->cmd.dlci = dlci_num; | ||
4930 | |||
4931 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
4932 | |||
4933 | if (err == CMD_OK){ | ||
4934 | return 0; | ||
4935 | } | ||
4936 | |||
4937 | for (dev = card->wandev.dev; dev; | ||
4938 | dev=*((struct net_device **)dev->priv)) | ||
4939 | set_chan_state(dev,WAN_DISCONNECTED); | ||
4940 | |||
4941 | printk(KERN_INFO "DLCI %i Not configured, configuring\n",dlci_num); | ||
4942 | |||
4943 | mbox->cmd.command = FR_COMM_DISABLE; | ||
4944 | mbox->cmd.length = 0; | ||
4945 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
4946 | if (err != CMD_OK){ | ||
4947 | fr_event(card, err, mbox); | ||
4948 | return 2; | ||
4949 | } | ||
4950 | |||
4951 | printk(KERN_INFO "Disabled Communications \n"); | ||
4952 | |||
4953 | mbox->cmd.command = FR_READ_CONFIG; | ||
4954 | mbox->cmd.length = 0; | ||
4955 | mbox->cmd.dlci = 0; | ||
4956 | |||
4957 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
4958 | |||
4959 | if (err != CMD_OK){ | ||
4960 | fr_event(card, err, mbox); | ||
4961 | return 2; | ||
4962 | } | ||
4963 | |||
4964 | conf = (fr_conf_t *)mbox->data; | ||
4965 | |||
4966 | dlci_offset=0; | ||
4967 | for (dev = card->wandev.dev; dev; | ||
4968 | dev = *((struct net_device **)dev->priv)) { | ||
4969 | fr_channel_t *chan_tmp = dev->priv; | ||
4970 | conf->dlci[dlci_offset] = chan_tmp->dlci; | ||
4971 | dlci_offset++; | ||
4972 | } | ||
4973 | |||
4974 | printk(KERN_INFO "Got Fr configuration Buffer Length is %x Dlci %i Dlci Off %i\n", | ||
4975 | mbox->cmd.length, | ||
4976 | mbox->cmd.length > 0x20 ? conf->dlci[0] : -1, | ||
4977 | dlci_offset ); | ||
4978 | |||
4979 | mbox->cmd.length = 0x20 + dlci_offset*2; | ||
4980 | |||
4981 | mbox->cmd.command = FR_SET_CONFIG; | ||
4982 | mbox->cmd.dlci = 0; | ||
4983 | |||
4984 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
4985 | |||
4986 | if (err != CMD_OK){ | ||
4987 | fr_event(card, err, mbox); | ||
4988 | return 2; | ||
4989 | } | ||
4990 | |||
4991 | initialize_rx_tx_buffers (card); | ||
4992 | |||
4993 | |||
4994 | printk(KERN_INFO "Configuraiton Succeded for new DLCI %i\n",dlci_num); | ||
4995 | |||
4996 | if (fr_comm_enable (card)){ | ||
4997 | return 2; | ||
4998 | } | ||
4999 | |||
5000 | printk(KERN_INFO "Enabling Communications \n"); | ||
5001 | |||
5002 | for (dev = card->wandev.dev; dev; | ||
5003 | dev = *((struct net_device **)dev->priv)) { | ||
5004 | fr_channel_t *chan_tmp = dev->priv; | ||
5005 | fr_init_dlci(card,chan_tmp); | ||
5006 | fr_add_dlci(card, chan_tmp->dlci); | ||
5007 | fr_activate_dlci(card, chan_tmp->dlci); | ||
5008 | } | ||
5009 | |||
5010 | printk(KERN_INFO "END OF CONFIGURAITON %i\n",dlci_num); | ||
5011 | |||
5012 | return 1; | ||
5013 | } | ||
5014 | |||
5015 | static void initialize_rx_tx_buffers (sdla_t *card) | ||
5016 | { | ||
5017 | fr_buf_info_t* buf_info; | ||
5018 | |||
5019 | if (card->hw.type == SDLA_S514) { | ||
5020 | |||
5021 | buf_info = (void*)(card->hw.dpmbase + FR_MB_VECTOR + | ||
5022 | FR508_RXBC_OFFS); | ||
5023 | |||
5024 | card->rxmb = (void*)(buf_info->rse_next + card->hw.dpmbase); | ||
5025 | |||
5026 | card->u.f.rxmb_base = | ||
5027 | (void*)(buf_info->rse_base + card->hw.dpmbase); | ||
5028 | |||
5029 | card->u.f.rxmb_last = | ||
5030 | (void*)(buf_info->rse_base + | ||
5031 | (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) + | ||
5032 | card->hw.dpmbase); | ||
5033 | }else{ | ||
5034 | buf_info = (void*)(card->hw.dpmbase + FR508_RXBC_OFFS); | ||
5035 | |||
5036 | card->rxmb = (void*)(buf_info->rse_next - | ||
5037 | FR_MB_VECTOR + card->hw.dpmbase); | ||
5038 | |||
5039 | card->u.f.rxmb_base = | ||
5040 | (void*)(buf_info->rse_base - | ||
5041 | FR_MB_VECTOR + card->hw.dpmbase); | ||
5042 | |||
5043 | card->u.f.rxmb_last = | ||
5044 | (void*)(buf_info->rse_base + | ||
5045 | (buf_info->rse_num - 1) * sizeof(fr_rx_buf_ctl_t) - | ||
5046 | FR_MB_VECTOR + card->hw.dpmbase); | ||
5047 | } | ||
5048 | |||
5049 | card->u.f.rx_base = buf_info->buf_base; | ||
5050 | card->u.f.rx_top = buf_info->buf_top; | ||
5051 | |||
5052 | card->u.f.tx_interrupts_pending = 0; | ||
5053 | |||
5054 | return; | ||
5055 | } | ||
5056 | |||
5057 | |||
5058 | |||
5059 | MODULE_LICENSE("GPL"); | ||
5060 | |||
5061 | /****** End *****************************************************************/ | ||
diff --git a/drivers/net/wan/sdla_ft1.c b/drivers/net/wan/sdla_ft1.c deleted file mode 100644 index 9d6528a50f7b..000000000000 --- a/drivers/net/wan/sdla_ft1.c +++ /dev/null | |||
@@ -1,345 +0,0 @@ | |||
1 | /***************************************************************************** | ||
2 | * sdla_chdlc.c WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module. | ||
3 | * | ||
4 | * Authors: Nenad Corbic <ncorbic@sangoma.com> | ||
5 | * Gideon Hack | ||
6 | * | ||
7 | * Copyright: (c) 1995-1999 Sangoma Technologies Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | * ============================================================================ | ||
14 | * Sep 30, 1999 Nenad Corbic Fixed dynamic IP and route setup. | ||
15 | * Sep 23, 1999 Nenad Corbic Added SMP support, fixed tracing | ||
16 | * Sep 13, 1999 Nenad Corbic Split up Port 0 and 1 into separate devices. | ||
17 | * Jun 02, 1999 Gideon Hack Added support for the S514 adapter. | ||
18 | * Oct 30, 1998 Jaspreet Singh Added Support for CHDLC API (HDLC STREAMING). | ||
19 | * Oct 28, 1998 Jaspreet Singh Added Support for Dual Port CHDLC. | ||
20 | * Aug 07, 1998 David Fong Initial version. | ||
21 | *****************************************************************************/ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/kernel.h> /* printk(), and other useful stuff */ | ||
25 | #include <linux/stddef.h> /* offsetof(), etc. */ | ||
26 | #include <linux/errno.h> /* return codes */ | ||
27 | #include <linux/string.h> /* inline memset(), etc. */ | ||
28 | #include <linux/slab.h> /* kmalloc(), kfree() */ | ||
29 | #include <linux/wanrouter.h> /* WAN router definitions */ | ||
30 | #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ | ||
31 | #include <linux/if_arp.h> /* ARPHRD_* defines */ | ||
32 | #include <linux/jiffies.h> /* time_after() macro */ | ||
33 | |||
34 | #include <linux/inetdevice.h> | ||
35 | #include <asm/uaccess.h> | ||
36 | |||
37 | #include <linux/in.h> /* sockaddr_in */ | ||
38 | #include <linux/inet.h> | ||
39 | #include <linux/if.h> | ||
40 | #include <asm/byteorder.h> /* htons(), etc. */ | ||
41 | #include <linux/sdlapci.h> | ||
42 | #include <asm/io.h> | ||
43 | |||
44 | #include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */ | ||
45 | |||
46 | /****** Defines & Macros ****************************************************/ | ||
47 | |||
48 | /* reasons for enabling the timer interrupt on the adapter */ | ||
49 | #define TMR_INT_ENABLED_UDP 0x0001 | ||
50 | #define TMR_INT_ENABLED_UPDATE 0x0002 | ||
51 | |||
52 | #define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */ | ||
53 | #define CHDLC_HDR_LEN 1 | ||
54 | |||
55 | #define IFF_POINTTOPOINT 0x10 | ||
56 | |||
57 | #define WANPIPE 0x00 | ||
58 | #define API 0x01 | ||
59 | #define CHDLC_API 0x01 | ||
60 | |||
61 | #define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" ) | ||
62 | |||
63 | |||
64 | /******Data Structures*****************************************************/ | ||
65 | |||
66 | /* This structure is placed in the private data area of the device structure. | ||
67 | * The card structure used to occupy the private area but now the following | ||
68 | * structure will incorporate the card structure along with CHDLC specific data | ||
69 | */ | ||
70 | |||
71 | typedef struct chdlc_private_area | ||
72 | { | ||
73 | struct net_device *slave; | ||
74 | sdla_t *card; | ||
75 | int TracingEnabled; /* For enabling Tracing */ | ||
76 | unsigned long curr_trace_addr; /* Used for Tracing */ | ||
77 | unsigned long start_trace_addr; | ||
78 | unsigned long end_trace_addr; | ||
79 | unsigned long base_addr_trace_buffer; | ||
80 | unsigned long end_addr_trace_buffer; | ||
81 | unsigned short number_trace_elements; | ||
82 | unsigned available_buffer_space; | ||
83 | unsigned long router_start_time; | ||
84 | unsigned char route_status; | ||
85 | unsigned char route_removed; | ||
86 | unsigned long tick_counter; /* For 5s timeout counter */ | ||
87 | unsigned long router_up_time; | ||
88 | u32 IP_address; /* IP addressing */ | ||
89 | u32 IP_netmask; | ||
90 | unsigned char mc; /* Mulitcast support on/off */ | ||
91 | unsigned short udp_pkt_lgth; /* udp packet processing */ | ||
92 | char udp_pkt_src; | ||
93 | char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; | ||
94 | unsigned short timer_int_enabled; | ||
95 | char update_comms_stats; /* updating comms stats */ | ||
96 | //FIXME: add driver stats as per frame relay! | ||
97 | |||
98 | } chdlc_private_area_t; | ||
99 | |||
100 | /* Route Status options */ | ||
101 | #define NO_ROUTE 0x00 | ||
102 | #define ADD_ROUTE 0x01 | ||
103 | #define ROUTE_ADDED 0x02 | ||
104 | #define REMOVE_ROUTE 0x03 | ||
105 | |||
106 | |||
107 | /****** Function Prototypes *************************************************/ | ||
108 | /* WAN link driver entry points. These are called by the WAN router module. */ | ||
109 | static int wpft1_exec (struct sdla *card, void *u_cmd, void *u_data); | ||
110 | static int chdlc_read_version (sdla_t* card, char* str); | ||
111 | static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb); | ||
112 | |||
113 | /****** Public Functions ****************************************************/ | ||
114 | |||
115 | /*============================================================================ | ||
116 | * Cisco HDLC protocol initialization routine. | ||
117 | * | ||
118 | * This routine is called by the main WANPIPE module during setup. At this | ||
119 | * point adapter is completely initialized and firmware is running. | ||
120 | * o read firmware version (to make sure it's alive) | ||
121 | * o configure adapter | ||
122 | * o initialize protocol-specific fields of the adapter data space. | ||
123 | * | ||
124 | * Return: 0 o.k. | ||
125 | * < 0 failure. | ||
126 | */ | ||
127 | int wpft1_init (sdla_t* card, wandev_conf_t* conf) | ||
128 | { | ||
129 | unsigned char port_num; | ||
130 | int err; | ||
131 | |||
132 | union | ||
133 | { | ||
134 | char str[80]; | ||
135 | } u; | ||
136 | volatile CHDLC_MAILBOX_STRUCT* mb; | ||
137 | CHDLC_MAILBOX_STRUCT* mb1; | ||
138 | unsigned long timeout; | ||
139 | |||
140 | /* Verify configuration ID */ | ||
141 | if (conf->config_id != WANCONFIG_CHDLC) { | ||
142 | printk(KERN_INFO "%s: invalid configuration ID %u!\n", | ||
143 | card->devname, conf->config_id); | ||
144 | return -EINVAL; | ||
145 | } | ||
146 | |||
147 | /* Use primary port */ | ||
148 | card->u.c.comm_port = 0; | ||
149 | |||
150 | |||
151 | /* Initialize protocol-specific fields */ | ||
152 | if(card->hw.type != SDLA_S514){ | ||
153 | card->mbox = (void *) card->hw.dpmbase; | ||
154 | }else{ | ||
155 | card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT; | ||
156 | } | ||
157 | |||
158 | mb = mb1 = card->mbox; | ||
159 | |||
160 | if (!card->configured){ | ||
161 | |||
162 | /* The board will place an 'I' in the return code to indicate that it is | ||
163 | ready to accept commands. We expect this to be completed in less | ||
164 | than 1 second. */ | ||
165 | |||
166 | timeout = jiffies; | ||
167 | while (mb->return_code != 'I') /* Wait 1s for board to initialize */ | ||
168 | if (time_after(jiffies, timeout + 1*HZ)) break; | ||
169 | |||
170 | if (mb->return_code != 'I') { | ||
171 | printk(KERN_INFO | ||
172 | "%s: Initialization not completed by adapter\n", | ||
173 | card->devname); | ||
174 | printk(KERN_INFO "Please contact Sangoma representative.\n"); | ||
175 | return -EIO; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | /* Read firmware version. Note that when adapter initializes, it | ||
180 | * clears the mailbox, so it may appear that the first command was | ||
181 | * executed successfully when in fact it was merely erased. To work | ||
182 | * around this, we execute the first command twice. | ||
183 | */ | ||
184 | |||
185 | if (chdlc_read_version(card, u.str)) | ||
186 | return -EIO; | ||
187 | |||
188 | printk(KERN_INFO "%s: Running FT1 Configuration firmware v%s\n", | ||
189 | card->devname, u.str); | ||
190 | |||
191 | card->isr = NULL; | ||
192 | card->poll = NULL; | ||
193 | card->exec = &wpft1_exec; | ||
194 | card->wandev.update = NULL; | ||
195 | card->wandev.new_if = NULL; | ||
196 | card->wandev.del_if = NULL; | ||
197 | card->wandev.state = WAN_DUALPORT; | ||
198 | card->wandev.udp_port = conf->udp_port; | ||
199 | |||
200 | card->wandev.new_if_cnt = 0; | ||
201 | |||
202 | /* This is for the ports link state */ | ||
203 | card->u.c.state = WAN_DISCONNECTED; | ||
204 | |||
205 | /* reset the number of times the 'update()' proc has been called */ | ||
206 | card->u.c.update_call_count = 0; | ||
207 | |||
208 | card->wandev.ttl = 0x7F; | ||
209 | card->wandev.interface = 0; | ||
210 | |||
211 | card->wandev.clocking = 0; | ||
212 | |||
213 | port_num = card->u.c.comm_port; | ||
214 | |||
215 | /* Setup Port Bps */ | ||
216 | |||
217 | card->wandev.bps = 0; | ||
218 | |||
219 | card->wandev.mtu = MIN_LGTH_CHDLC_DATA_CFG; | ||
220 | |||
221 | /* Set up the interrupt status area */ | ||
222 | /* Read the CHDLC Configuration and obtain: | ||
223 | * Ptr to shared memory infor struct | ||
224 | * Use this pointer to calculate the value of card->u.c.flags ! | ||
225 | */ | ||
226 | mb1->buffer_length = 0; | ||
227 | mb1->command = READ_CHDLC_CONFIGURATION; | ||
228 | err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT; | ||
229 | if(err != COMMAND_OK) { | ||
230 | chdlc_error(card, err, mb1); | ||
231 | return -EIO; | ||
232 | } | ||
233 | |||
234 | if(card->hw.type == SDLA_S514){ | ||
235 | card->u.c.flags = (void *)(card->hw.dpmbase + | ||
236 | (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)-> | ||
237 | ptr_shared_mem_info_struct)); | ||
238 | }else{ | ||
239 | card->u.c.flags = (void *)(card->hw.dpmbase + | ||
240 | (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)-> | ||
241 | ptr_shared_mem_info_struct % SDLA_WINDOWSIZE)); | ||
242 | } | ||
243 | |||
244 | card->wandev.state = WAN_FT1_READY; | ||
245 | printk(KERN_INFO "%s: FT1 Config Ready !\n",card->devname); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static int wpft1_exec(sdla_t *card, void *u_cmd, void *u_data) | ||
251 | { | ||
252 | CHDLC_MAILBOX_STRUCT* mbox = card->mbox; | ||
253 | int len; | ||
254 | |||
255 | if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){ | ||
256 | return -EFAULT; | ||
257 | } | ||
258 | |||
259 | len = mbox->buffer_length; | ||
260 | |||
261 | if (len) { | ||
262 | if( copy_from_user((void*)&mbox->data, u_data, len)){ | ||
263 | return -EFAULT; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | /* execute command */ | ||
268 | if (!sdla_exec(mbox)){ | ||
269 | return -EIO; | ||
270 | } | ||
271 | |||
272 | /* return result */ | ||
273 | if( copy_to_user(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t))){ | ||
274 | return -EFAULT; | ||
275 | } | ||
276 | |||
277 | len = mbox->buffer_length; | ||
278 | |||
279 | if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){ | ||
280 | return -EFAULT; | ||
281 | } | ||
282 | |||
283 | return 0; | ||
284 | |||
285 | } | ||
286 | |||
287 | /*============================================================================ | ||
288 | * Read firmware code version. | ||
289 | * Put code version as ASCII string in str. | ||
290 | */ | ||
291 | static int chdlc_read_version (sdla_t* card, char* str) | ||
292 | { | ||
293 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
294 | int len; | ||
295 | char err; | ||
296 | mb->buffer_length = 0; | ||
297 | mb->command = READ_CHDLC_CODE_VERSION; | ||
298 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
299 | |||
300 | if(err != COMMAND_OK) { | ||
301 | chdlc_error(card,err,mb); | ||
302 | } | ||
303 | else if (str) { /* is not null */ | ||
304 | len = mb->buffer_length; | ||
305 | memcpy(str, mb->data, len); | ||
306 | str[len] = '\0'; | ||
307 | } | ||
308 | return (err); | ||
309 | } | ||
310 | |||
311 | /*============================================================================ | ||
312 | * Firmware error handler. | ||
313 | * This routine is called whenever firmware command returns non-zero | ||
314 | * return code. | ||
315 | * | ||
316 | * Return zero if previous command has to be cancelled. | ||
317 | */ | ||
318 | static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb) | ||
319 | { | ||
320 | unsigned cmd = mb->command; | ||
321 | |||
322 | switch (err) { | ||
323 | |||
324 | case CMD_TIMEOUT: | ||
325 | printk(KERN_ERR "%s: command 0x%02X timed out!\n", | ||
326 | card->devname, cmd); | ||
327 | break; | ||
328 | |||
329 | case S514_BOTH_PORTS_SAME_CLK_MODE: | ||
330 | if(cmd == SET_CHDLC_CONFIGURATION) { | ||
331 | printk(KERN_INFO | ||
332 | "%s: Configure both ports for the same clock source\n", | ||
333 | card->devname); | ||
334 | break; | ||
335 | } | ||
336 | |||
337 | default: | ||
338 | printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n", | ||
339 | card->devname, cmd, err); | ||
340 | } | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c deleted file mode 100644 index a4b489cccbbf..000000000000 --- a/drivers/net/wan/sdla_ppp.c +++ /dev/null | |||
@@ -1,3430 +0,0 @@ | |||
1 | /***************************************************************************** | ||
2 | * sdla_ppp.c WANPIPE(tm) Multiprotocol WAN Link Driver. PPP module. | ||
3 | * | ||
4 | * Author: Nenad Corbic <ncorbic@sangoma.com> | ||
5 | * | ||
6 | * Copyright: (c) 1995-2001 Sangoma Technologies Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * ============================================================================ | ||
13 | * Feb 28, 2001 Nenad Corbic o Updated if_tx_timeout() routine for | ||
14 | * 2.4.X kernels. | ||
15 | * Nov 29, 2000 Nenad Corbic o Added the 2.4.x kernel support: | ||
16 | * get_ip_address() function has moved | ||
17 | * into the ppp_poll() routine. It cannot | ||
18 | * be called from an interrupt. | ||
19 | * Nov 07, 2000 Nenad Corbic o Added security features for UDP debugging: | ||
20 | * Deny all and specify allowed requests. | ||
21 | * May 02, 2000 Nenad Corbic o Added the dynamic interface shutdown | ||
22 | * option. When the link goes down, the | ||
23 | * network interface IFF_UP flag is reset. | ||
24 | * Mar 06, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery. | ||
25 | * Feb 25, 2000 Nenad Corbic o Fixed the FT1 UDP debugger problem. | ||
26 | * Feb 09, 2000 Nenad Coribc o Shutdown bug fix. update() was called | ||
27 | * with NULL dev pointer: no check. | ||
28 | * Jan 24, 2000 Nenad Corbic o Disabled use of CMD complete inter. | ||
29 | * Dev 15, 1999 Nenad Corbic o Fixed up header files for 2.0.X kernels | ||
30 | * Oct 25, 1999 Nenad Corbic o Support for 2.0.X kernels | ||
31 | * Moved dynamic route processing into | ||
32 | * a polling routine. | ||
33 | * Oct 07, 1999 Nenad Corbic o Support for S514 PCI card. | ||
34 | * Gideon Hack o UPD and Updates executed using timer interrupt | ||
35 | * Sep 10, 1999 Nenad Corbic o Fixed up the /proc statistics | ||
36 | * Jul 20, 1999 Nenad Corbic o Remove the polling routines and use | ||
37 | * interrupts instead. | ||
38 | * Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X Kernels. | ||
39 | * Aug 13, 1998 Jaspreet Singh o Improved Line Tracing. | ||
40 | * Jun 22, 1998 David Fong o Added remote IP address assignment | ||
41 | * Mar 15, 1998 Alan Cox o 2.1.8x basic port. | ||
42 | * Apr 16, 1998 Jaspreet Singh o using htons() for the IPX protocol. | ||
43 | * Dec 09, 1997 Jaspreet Singh o Added PAP and CHAP. | ||
44 | * o Implemented new routines like | ||
45 | * ppp_set_inbnd_auth(), ppp_set_outbnd_auth(), | ||
46 | * tokenize() and strstrip(). | ||
47 | * Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs | ||
48 | * while they have been disabled. | ||
49 | * Nov 24, 1997 Jaspreet Singh o Fixed another RACE condition caused by | ||
50 | * disabling and enabling of irqs. | ||
51 | * o Added new counters for stats on disable/enable | ||
52 | * IRQs. | ||
53 | * Nov 10, 1997 Jaspreet Singh o Initialized 'skb->mac.raw' to 'skb->data' | ||
54 | * before every netif_rx(). | ||
55 | * o Free up the device structure in del_if(). | ||
56 | * Nov 07, 1997 Jaspreet Singh o Changed the delay to zero for Line tracing | ||
57 | * command. | ||
58 | * Oct 20, 1997 Jaspreet Singh o Added hooks in for Router UP time. | ||
59 | * Oct 16, 1997 Jaspreet Singh o The critical flag is used to maintain flow | ||
60 | * control by avoiding RACE conditions. The | ||
61 | * cli() and restore_flags() are taken out. | ||
62 | * A new structure, "ppp_private_area", is added | ||
63 | * to provide Driver Statistics. | ||
64 | * Jul 21, 1997 Jaspreet Singh o Protected calls to sdla_peek() by adding | ||
65 | * save_flags(), cli() and restore_flags(). | ||
66 | * Jul 07, 1997 Jaspreet Singh o Added configurable TTL for UDP packets | ||
67 | * o Added ability to discard mulitcast and | ||
68 | * broacast source addressed packets. | ||
69 | * Jun 27, 1997 Jaspreet Singh o Added FT1 monitor capabilities | ||
70 | * New case (0x25) statement in if_send routine. | ||
71 | * Added a global variable rCount to keep track | ||
72 | * of FT1 status enabled on the board. | ||
73 | * May 22, 1997 Jaspreet Singh o Added change in the PPP_SET_CONFIG command for | ||
74 | * 508 card to reflect changes in the new | ||
75 | * ppp508.sfm for supporting:continous transmission | ||
76 | * of Configure-Request packets without receiving a | ||
77 | * reply | ||
78 | * OR-ed 0x300 to conf_flags | ||
79 | * o Changed connect_tmout from 900 to 0 | ||
80 | * May 21, 1997 Jaspreet Singh o Fixed UDP Management for multiple boards | ||
81 | * Apr 25, 1997 Farhan Thawar o added UDP Management stuff | ||
82 | * Mar 11, 1997 Farhan Thawar Version 3.1.1 | ||
83 | * o fixed (+1) bug in rx_intr() | ||
84 | * o changed if_send() to return 0 if | ||
85 | * wandev.critical() is true | ||
86 | * o free socket buffer in if_send() if | ||
87 | * returning 0 | ||
88 | * Jan 15, 1997 Gene Kozin Version 3.1.0 | ||
89 | * o implemented exec() entry point | ||
90 | * Jan 06, 1997 Gene Kozin Initial version. | ||
91 | *****************************************************************************/ | ||
92 | |||
93 | #include <linux/module.h> | ||
94 | #include <linux/kernel.h> /* printk(), and other useful stuff */ | ||
95 | #include <linux/stddef.h> /* offsetof(), etc. */ | ||
96 | #include <linux/errno.h> /* return codes */ | ||
97 | #include <linux/string.h> /* inline memset(), etc. */ | ||
98 | #include <linux/slab.h> /* kmalloc(), kfree() */ | ||
99 | #include <linux/wanrouter.h> /* WAN router definitions */ | ||
100 | #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ | ||
101 | #include <linux/if_arp.h> /* ARPHRD_* defines */ | ||
102 | #include <asm/byteorder.h> /* htons(), etc. */ | ||
103 | #include <linux/in.h> /* sockaddr_in */ | ||
104 | #include <linux/jiffies.h> /* time_after() macro */ | ||
105 | |||
106 | |||
107 | #include <asm/uaccess.h> | ||
108 | #include <linux/inetdevice.h> | ||
109 | #include <linux/netdevice.h> | ||
110 | |||
111 | #include <linux/if.h> | ||
112 | #include <linux/sdla_ppp.h> /* PPP firmware API definitions */ | ||
113 | #include <linux/sdlasfm.h> /* S514 Type Definition */ | ||
114 | /****** Defines & Macros ****************************************************/ | ||
115 | |||
116 | #define PPP_DFLT_MTU 1500 /* default MTU */ | ||
117 | #define PPP_MAX_MTU 4000 /* maximum MTU */ | ||
118 | #define PPP_HDR_LEN 1 | ||
119 | |||
120 | #define MAX_IP_ERRORS 100 | ||
121 | |||
122 | #define CONNECT_TIMEOUT (90*HZ) /* link connection timeout */ | ||
123 | #define HOLD_DOWN_TIME (5*HZ) /* link hold down time : Changed from 30 to 5 */ | ||
124 | |||
125 | /* For handle_IPXWAN() */ | ||
126 | #define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b))) | ||
127 | |||
128 | /* Macro for enabling/disabling debugging comments */ | ||
129 | //#define NEX_DEBUG | ||
130 | #ifdef NEX_DEBUG | ||
131 | #define NEX_PRINTK(format, a...) printk(format, ## a) | ||
132 | #else | ||
133 | #define NEX_PRINTK(format, a...) | ||
134 | #endif /* NEX_DEBUG */ | ||
135 | |||
136 | #define DCD(a) ( a & 0x08 ? "HIGH" : "LOW" ) | ||
137 | #define CTS(a) ( a & 0x20 ? "HIGH" : "LOW" ) | ||
138 | #define LCP(a) ( a == 0x09 ? "OPEN" : "CLOSED" ) | ||
139 | #define IP(a) ( a == 0x09 ? "ENABLED" : "DISABLED" ) | ||
140 | |||
141 | #define TMR_INT_ENABLED_UPDATE 0x01 | ||
142 | #define TMR_INT_ENABLED_PPP_EVENT 0x02 | ||
143 | #define TMR_INT_ENABLED_UDP 0x04 | ||
144 | #define TMR_INT_ENABLED_CONFIG 0x20 | ||
145 | |||
146 | /* Set Configuraton Command Definitions */ | ||
147 | #define PERCENT_TX_BUFF 60 | ||
148 | #define TIME_BETWEEN_CONF_REQ 30 | ||
149 | #define TIME_BETWEEN_PAP_CHAP_REQ 30 | ||
150 | #define WAIT_PAP_CHAP_WITHOUT_REPLY 300 | ||
151 | #define WAIT_AFTER_DCD_CTS_LOW 5 | ||
152 | #define TIME_DCD_CTS_LOW_AFTER_LNK_DOWN 10 | ||
153 | #define WAIT_DCD_HIGH_AFTER_ENABLE_COMM 900 | ||
154 | #define MAX_CONF_REQ_WITHOUT_REPLY 10 | ||
155 | #define MAX_TERM_REQ_WITHOUT_REPLY 2 | ||
156 | #define NUM_CONF_NAK_WITHOUT_REPLY 5 | ||
157 | #define NUM_AUTH_REQ_WITHOUT_REPLY 10 | ||
158 | |||
159 | #define END_OFFSET 0x1F0 | ||
160 | |||
161 | |||
162 | /******Data Structures*****************************************************/ | ||
163 | |||
164 | /* This structure is placed in the private data area of the device structure. | ||
165 | * The card structure used to occupy the private area but now the following | ||
166 | * structure will incorporate the card structure along with PPP specific data | ||
167 | */ | ||
168 | |||
169 | typedef struct ppp_private_area | ||
170 | { | ||
171 | struct net_device *slave; | ||
172 | sdla_t* card; | ||
173 | unsigned long router_start_time; /*router start time in sec */ | ||
174 | unsigned long tick_counter; /*used for 5 second counter*/ | ||
175 | unsigned mc; /*multicast support on or off*/ | ||
176 | unsigned char enable_IPX; | ||
177 | unsigned long network_number; | ||
178 | unsigned char pap; | ||
179 | unsigned char chap; | ||
180 | unsigned char sysname[31]; /* system name for in-bnd auth*/ | ||
181 | unsigned char userid[511]; /* list of user ids */ | ||
182 | unsigned char passwd[511]; /* list of passwords */ | ||
183 | unsigned protocol; /* SKB Protocol */ | ||
184 | u32 ip_local; /* Local IP Address */ | ||
185 | u32 ip_remote; /* remote IP Address */ | ||
186 | |||
187 | u32 ip_local_tmp; | ||
188 | u32 ip_remote_tmp; | ||
189 | |||
190 | unsigned char timer_int_enabled; /* Who enabled the timer inter*/ | ||
191 | unsigned char update_comms_stats; /* Used by update function */ | ||
192 | unsigned long curr_trace_addr; /* Trace information */ | ||
193 | unsigned long start_trace_addr; | ||
194 | unsigned long end_trace_addr; | ||
195 | |||
196 | unsigned char interface_down; /* Brind down interface when channel | ||
197 | goes down */ | ||
198 | unsigned long config_wait_timeout; /* After if_open() if in dynamic if mode, | ||
199 | wait a few seconds before configuring */ | ||
200 | |||
201 | unsigned short udp_pkt_lgth; | ||
202 | char udp_pkt_src; | ||
203 | char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; | ||
204 | |||
205 | /* PPP specific statistics */ | ||
206 | |||
207 | if_send_stat_t if_send_stat; | ||
208 | rx_intr_stat_t rx_intr_stat; | ||
209 | pipe_mgmt_stat_t pipe_mgmt_stat; | ||
210 | |||
211 | unsigned long router_up_time; | ||
212 | |||
213 | /* Polling work queue entry. Each interface | ||
214 | * has its own work queue entry, which is used | ||
215 | * to defer events from the interrupt */ | ||
216 | struct work_struct poll_work; | ||
217 | struct timer_list poll_delay_timer; | ||
218 | |||
219 | u8 gateway; | ||
220 | u8 config_ppp; | ||
221 | u8 ip_error; | ||
222 | |||
223 | }ppp_private_area_t; | ||
224 | |||
225 | /* variable for keeping track of enabling/disabling FT1 monitor status */ | ||
226 | static int rCount = 0; | ||
227 | |||
228 | extern void disable_irq(unsigned int); | ||
229 | extern void enable_irq(unsigned int); | ||
230 | |||
231 | /****** Function Prototypes *************************************************/ | ||
232 | |||
233 | /* WAN link driver entry points. These are called by the WAN router module. */ | ||
234 | static int update(struct wan_device *wandev); | ||
235 | static int new_if(struct wan_device *wandev, struct net_device *dev, | ||
236 | wanif_conf_t *conf); | ||
237 | static int del_if(struct wan_device *wandev, struct net_device *dev); | ||
238 | |||
239 | /* WANPIPE-specific entry points */ | ||
240 | static int wpp_exec (struct sdla *card, void *u_cmd, void *u_data); | ||
241 | |||
242 | /* Network device interface */ | ||
243 | static int if_init(struct net_device *dev); | ||
244 | static int if_open(struct net_device *dev); | ||
245 | static int if_close(struct net_device *dev); | ||
246 | static int if_header(struct sk_buff *skb, struct net_device *dev, | ||
247 | unsigned short type, | ||
248 | void *daddr, void *saddr, unsigned len); | ||
249 | |||
250 | static void if_tx_timeout(struct net_device *dev); | ||
251 | |||
252 | static int if_rebuild_hdr(struct sk_buff *skb); | ||
253 | static struct net_device_stats *if_stats(struct net_device *dev); | ||
254 | static int if_send(struct sk_buff *skb, struct net_device *dev); | ||
255 | |||
256 | |||
257 | /* PPP firmware interface functions */ | ||
258 | static int ppp_read_version(sdla_t *card, char *str); | ||
259 | static int ppp_set_outbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area); | ||
260 | static int ppp_set_inbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area); | ||
261 | static int ppp_configure(sdla_t *card, void *data); | ||
262 | static int ppp_set_intr_mode(sdla_t *card, unsigned char mode); | ||
263 | static int ppp_comm_enable(sdla_t *card); | ||
264 | static int ppp_comm_disable(sdla_t *card); | ||
265 | static int ppp_comm_disable_shutdown(sdla_t *card); | ||
266 | static int ppp_get_err_stats(sdla_t *card); | ||
267 | static int ppp_send(sdla_t *card, void *data, unsigned len, unsigned proto); | ||
268 | static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb); | ||
269 | |||
270 | static void wpp_isr(sdla_t *card); | ||
271 | static void rx_intr(sdla_t *card); | ||
272 | static void event_intr(sdla_t *card); | ||
273 | static void timer_intr(sdla_t *card); | ||
274 | |||
275 | /* Background polling routines */ | ||
276 | static void process_route(sdla_t *card); | ||
277 | static void retrigger_comm(sdla_t *card); | ||
278 | |||
279 | /* Miscellaneous functions */ | ||
280 | static int read_info( sdla_t *card ); | ||
281 | static int read_connection_info (sdla_t *card); | ||
282 | static void remove_route( sdla_t *card ); | ||
283 | static int config508(struct net_device *dev, sdla_t *card); | ||
284 | static void show_disc_cause(sdla_t * card, unsigned cause); | ||
285 | static int reply_udp( unsigned char *data, unsigned int mbox_len ); | ||
286 | static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev, | ||
287 | ppp_private_area_t *ppp_priv_area); | ||
288 | static void init_ppp_tx_rx_buff( sdla_t *card ); | ||
289 | static int intr_test( sdla_t *card ); | ||
290 | static int udp_pkt_type( struct sk_buff *skb , sdla_t *card); | ||
291 | static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area); | ||
292 | static void init_global_statistics( sdla_t *card ); | ||
293 | static int tokenize(char *str, char **tokens); | ||
294 | static char* strstrip(char *str, char *s); | ||
295 | static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev, | ||
296 | struct sk_buff *skb); | ||
297 | |||
298 | static int config_ppp (sdla_t *); | ||
299 | static void ppp_poll(struct net_device *dev); | ||
300 | static void trigger_ppp_poll(struct net_device *dev); | ||
301 | static void ppp_poll_delay (unsigned long dev_ptr); | ||
302 | |||
303 | |||
304 | static int Read_connection_info; | ||
305 | static int Intr_test_counter; | ||
306 | static unsigned short available_buffer_space; | ||
307 | |||
308 | |||
309 | /* IPX functions */ | ||
310 | static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, | ||
311 | unsigned char incoming); | ||
312 | static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_PX, | ||
313 | unsigned long network_number, unsigned short proto); | ||
314 | |||
315 | /* Lock Functions */ | ||
316 | static void s508_lock (sdla_t *card, unsigned long *smp_flags); | ||
317 | static void s508_unlock (sdla_t *card, unsigned long *smp_flags); | ||
318 | |||
319 | static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, | ||
320 | struct sk_buff *skb, struct net_device* dev, | ||
321 | ppp_private_area_t* ppp_priv_area ); | ||
322 | static unsigned short calc_checksum (char *data, int len); | ||
323 | static void disable_comm (sdla_t *card); | ||
324 | static int detect_and_fix_tx_bug (sdla_t *card); | ||
325 | |||
326 | /****** Public Functions ****************************************************/ | ||
327 | |||
328 | /*============================================================================ | ||
329 | * PPP protocol initialization routine. | ||
330 | * | ||
331 | * This routine is called by the main WANPIPE module during setup. At this | ||
332 | * point adapter is completely initialized and firmware is running. | ||
333 | * o read firmware version (to make sure it's alive) | ||
334 | * o configure adapter | ||
335 | * o initialize protocol-specific fields of the adapter data space. | ||
336 | * | ||
337 | * Return: 0 o.k. | ||
338 | * < 0 failure. | ||
339 | */ | ||
340 | int wpp_init(sdla_t *card, wandev_conf_t *conf) | ||
341 | { | ||
342 | ppp_flags_t *flags; | ||
343 | union | ||
344 | { | ||
345 | char str[80]; | ||
346 | } u; | ||
347 | |||
348 | /* Verify configuration ID */ | ||
349 | if (conf->config_id != WANCONFIG_PPP) { | ||
350 | |||
351 | printk(KERN_INFO "%s: invalid configuration ID %u!\n", | ||
352 | card->devname, conf->config_id); | ||
353 | return -EINVAL; | ||
354 | |||
355 | } | ||
356 | |||
357 | /* Initialize miscellaneous pointers to structures on the adapter */ | ||
358 | switch (card->hw.type) { | ||
359 | |||
360 | case SDLA_S508: | ||
361 | card->mbox =(void*)(card->hw.dpmbase + PPP508_MB_OFFS); | ||
362 | card->flags=(void*)(card->hw.dpmbase + PPP508_FLG_OFFS); | ||
363 | break; | ||
364 | |||
365 | case SDLA_S514: | ||
366 | card->mbox =(void*)(card->hw.dpmbase + PPP514_MB_OFFS); | ||
367 | card->flags=(void*)(card->hw.dpmbase + PPP514_FLG_OFFS); | ||
368 | break; | ||
369 | |||
370 | default: | ||
371 | return -EINVAL; | ||
372 | |||
373 | } | ||
374 | flags = card->flags; | ||
375 | |||
376 | /* Read firmware version. Note that when adapter initializes, it | ||
377 | * clears the mailbox, so it may appear that the first command was | ||
378 | * executed successfully when in fact it was merely erased. To work | ||
379 | * around this, we execute the first command twice. | ||
380 | */ | ||
381 | if (ppp_read_version(card, NULL) || ppp_read_version(card, u.str)) | ||
382 | return -EIO; | ||
383 | |||
384 | printk(KERN_INFO "%s: running PPP firmware v%s\n",card->devname, u.str); | ||
385 | /* Adjust configuration and set defaults */ | ||
386 | card->wandev.mtu = (conf->mtu) ? | ||
387 | min_t(unsigned int, conf->mtu, PPP_MAX_MTU) : PPP_DFLT_MTU; | ||
388 | |||
389 | card->wandev.bps = conf->bps; | ||
390 | card->wandev.interface = conf->interface; | ||
391 | card->wandev.clocking = conf->clocking; | ||
392 | card->wandev.station = conf->station; | ||
393 | card->isr = &wpp_isr; | ||
394 | card->poll = NULL; | ||
395 | card->exec = &wpp_exec; | ||
396 | card->wandev.update = &update; | ||
397 | card->wandev.new_if = &new_if; | ||
398 | card->wandev.del_if = &del_if; | ||
399 | card->wandev.udp_port = conf->udp_port; | ||
400 | card->wandev.ttl = conf->ttl; | ||
401 | card->wandev.state = WAN_DISCONNECTED; | ||
402 | card->disable_comm = &disable_comm; | ||
403 | card->irq_dis_if_send_count = 0; | ||
404 | card->irq_dis_poll_count = 0; | ||
405 | card->u.p.authenticator = conf->u.ppp.authenticator; | ||
406 | card->u.p.ip_mode = conf->u.ppp.ip_mode ? | ||
407 | conf->u.ppp.ip_mode : WANOPT_PPP_STATIC; | ||
408 | card->TracingEnabled = 0; | ||
409 | Read_connection_info = 1; | ||
410 | |||
411 | /* initialize global statistics */ | ||
412 | init_global_statistics( card ); | ||
413 | |||
414 | |||
415 | |||
416 | if (!card->configured){ | ||
417 | int err; | ||
418 | |||
419 | Intr_test_counter = 0; | ||
420 | err = intr_test(card); | ||
421 | |||
422 | if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { | ||
423 | printk("%s: Interrupt Test Failed, Counter: %i\n", | ||
424 | card->devname, Intr_test_counter); | ||
425 | printk( "%s: Please choose another interrupt\n",card->devname); | ||
426 | return -EIO; | ||
427 | } | ||
428 | |||
429 | printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n", | ||
430 | card->devname, Intr_test_counter); | ||
431 | card->configured = 1; | ||
432 | } | ||
433 | |||
434 | ppp_set_intr_mode(card, PPP_INTR_TIMER); | ||
435 | |||
436 | /* Turn off the transmit and timer interrupt */ | ||
437 | flags->imask &= ~PPP_INTR_TIMER; | ||
438 | |||
439 | printk(KERN_INFO "\n"); | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | /******* WAN Device Driver Entry Points *************************************/ | ||
445 | |||
446 | /*============================================================================ | ||
447 | * Update device status & statistics. | ||
448 | */ | ||
449 | static int update(struct wan_device *wandev) | ||
450 | { | ||
451 | sdla_t* card = wandev->private; | ||
452 | struct net_device* dev; | ||
453 | volatile ppp_private_area_t *ppp_priv_area; | ||
454 | ppp_flags_t *flags = card->flags; | ||
455 | unsigned long timeout; | ||
456 | |||
457 | /* sanity checks */ | ||
458 | if ((wandev == NULL) || (wandev->private == NULL)) | ||
459 | return -EFAULT; | ||
460 | |||
461 | if (wandev->state == WAN_UNCONFIGURED) | ||
462 | return -ENODEV; | ||
463 | |||
464 | /* Shutdown bug fix. This function can be | ||
465 | * called with NULL dev pointer during | ||
466 | * shutdown | ||
467 | */ | ||
468 | if ((dev=card->wandev.dev) == NULL){ | ||
469 | return -ENODEV; | ||
470 | } | ||
471 | |||
472 | if ((ppp_priv_area=dev->priv) == NULL){ | ||
473 | return -ENODEV; | ||
474 | } | ||
475 | |||
476 | ppp_priv_area->update_comms_stats = 2; | ||
477 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UPDATE; | ||
478 | flags->imask |= PPP_INTR_TIMER; | ||
479 | |||
480 | /* wait a maximum of 1 second for the statistics to be updated */ | ||
481 | timeout = jiffies; | ||
482 | for(;;) { | ||
483 | if(ppp_priv_area->update_comms_stats == 0){ | ||
484 | break; | ||
485 | } | ||
486 | if (time_after(jiffies, timeout + 1 * HZ)){ | ||
487 | ppp_priv_area->update_comms_stats = 0; | ||
488 | ppp_priv_area->timer_int_enabled &= | ||
489 | ~TMR_INT_ENABLED_UPDATE; | ||
490 | return -EAGAIN; | ||
491 | } | ||
492 | } | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | /*============================================================================ | ||
498 | * Create new logical channel. | ||
499 | * This routine is called by the router when ROUTER_IFNEW IOCTL is being | ||
500 | * handled. | ||
501 | * o parse media- and hardware-specific configuration | ||
502 | * o make sure that a new channel can be created | ||
503 | * o allocate resources, if necessary | ||
504 | * o prepare network device structure for registaration. | ||
505 | * | ||
506 | * Return: 0 o.k. | ||
507 | * < 0 failure (channel will not be created) | ||
508 | */ | ||
509 | static int new_if(struct wan_device *wandev, struct net_device *dev, | ||
510 | wanif_conf_t *conf) | ||
511 | { | ||
512 | sdla_t *card = wandev->private; | ||
513 | ppp_private_area_t *ppp_priv_area; | ||
514 | |||
515 | if (wandev->ndev) | ||
516 | return -EEXIST; | ||
517 | |||
518 | |||
519 | printk(KERN_INFO "%s: Configuring Interface: %s\n", | ||
520 | card->devname, conf->name); | ||
521 | |||
522 | if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) { | ||
523 | |||
524 | printk(KERN_INFO "%s: Invalid interface name!\n", | ||
525 | card->devname); | ||
526 | return -EINVAL; | ||
527 | |||
528 | } | ||
529 | |||
530 | /* allocate and initialize private data */ | ||
531 | ppp_priv_area = kmalloc(sizeof(ppp_private_area_t), GFP_KERNEL); | ||
532 | |||
533 | if( ppp_priv_area == NULL ) | ||
534 | return -ENOMEM; | ||
535 | |||
536 | memset(ppp_priv_area, 0, sizeof(ppp_private_area_t)); | ||
537 | |||
538 | ppp_priv_area->card = card; | ||
539 | |||
540 | /* initialize data */ | ||
541 | strcpy(card->u.p.if_name, conf->name); | ||
542 | |||
543 | /* initialize data in ppp_private_area structure */ | ||
544 | |||
545 | init_ppp_priv_struct( ppp_priv_area ); | ||
546 | |||
547 | ppp_priv_area->mc = conf->mc; | ||
548 | ppp_priv_area->pap = conf->pap; | ||
549 | ppp_priv_area->chap = conf->chap; | ||
550 | |||
551 | /* Option to bring down the interface when | ||
552 | * the link goes down */ | ||
553 | if (conf->if_down){ | ||
554 | set_bit(DYN_OPT_ON,&ppp_priv_area->interface_down); | ||
555 | printk("%s: Dynamic interface configuration enabled\n", | ||
556 | card->devname); | ||
557 | } | ||
558 | |||
559 | /* If no user ids are specified */ | ||
560 | if(!strlen(conf->userid) && (ppp_priv_area->pap||ppp_priv_area->chap)){ | ||
561 | kfree(ppp_priv_area); | ||
562 | return -EINVAL; | ||
563 | } | ||
564 | |||
565 | /* If no passwords are specified */ | ||
566 | if(!strlen(conf->passwd) && (ppp_priv_area->pap||ppp_priv_area->chap)){ | ||
567 | kfree(ppp_priv_area); | ||
568 | return -EINVAL; | ||
569 | } | ||
570 | |||
571 | if(strlen(conf->sysname) > 31){ | ||
572 | kfree(ppp_priv_area); | ||
573 | return -EINVAL; | ||
574 | } | ||
575 | |||
576 | /* If no system name is specified */ | ||
577 | if(!strlen(conf->sysname) && (card->u.p.authenticator)){ | ||
578 | kfree(ppp_priv_area); | ||
579 | return -EINVAL; | ||
580 | } | ||
581 | |||
582 | /* copy the data into the ppp private structure */ | ||
583 | memcpy(ppp_priv_area->userid, conf->userid, strlen(conf->userid)); | ||
584 | memcpy(ppp_priv_area->passwd, conf->passwd, strlen(conf->passwd)); | ||
585 | memcpy(ppp_priv_area->sysname, conf->sysname, strlen(conf->sysname)); | ||
586 | |||
587 | |||
588 | ppp_priv_area->enable_IPX = conf->enable_IPX; | ||
589 | if (conf->network_number){ | ||
590 | ppp_priv_area->network_number = conf->network_number; | ||
591 | }else{ | ||
592 | ppp_priv_area->network_number = 0xDEADBEEF; | ||
593 | } | ||
594 | |||
595 | /* Tells us that if this interface is a | ||
596 | * gateway or not */ | ||
597 | if ((ppp_priv_area->gateway = conf->gateway) == WANOPT_YES){ | ||
598 | printk(KERN_INFO "%s: Interface %s is set as a gateway.\n", | ||
599 | card->devname,card->u.p.if_name); | ||
600 | } | ||
601 | |||
602 | /* prepare network device data space for registration */ | ||
603 | strcpy(dev->name,card->u.p.if_name); | ||
604 | |||
605 | dev->init = &if_init; | ||
606 | dev->priv = ppp_priv_area; | ||
607 | dev->mtu = min_t(unsigned int, dev->mtu, card->wandev.mtu); | ||
608 | |||
609 | /* Initialize the polling work routine */ | ||
610 | INIT_WORK(&ppp_priv_area->poll_work, (void*)(void*)ppp_poll, dev); | ||
611 | |||
612 | /* Initialize the polling delay timer */ | ||
613 | init_timer(&ppp_priv_area->poll_delay_timer); | ||
614 | ppp_priv_area->poll_delay_timer.data = (unsigned long)dev; | ||
615 | ppp_priv_area->poll_delay_timer.function = ppp_poll_delay; | ||
616 | |||
617 | |||
618 | /* Since we start with dummy IP addresses we can say | ||
619 | * that route exists */ | ||
620 | printk(KERN_INFO "\n"); | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | /*============================================================================ | ||
626 | * Delete logical channel. | ||
627 | */ | ||
628 | static int del_if(struct wan_device *wandev, struct net_device *dev) | ||
629 | { | ||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | static void disable_comm (sdla_t *card) | ||
634 | { | ||
635 | ppp_comm_disable_shutdown(card); | ||
636 | return; | ||
637 | } | ||
638 | |||
639 | /****** WANPIPE-specific entry points ***************************************/ | ||
640 | |||
641 | /*============================================================================ | ||
642 | * Execute adapter interface command. | ||
643 | */ | ||
644 | |||
645 | //FIXME: Why do we need this ???? | ||
646 | static int wpp_exec(struct sdla *card, void *u_cmd, void *u_data) | ||
647 | { | ||
648 | ppp_mbox_t *mbox = card->mbox; | ||
649 | int len; | ||
650 | |||
651 | if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t))) | ||
652 | return -EFAULT; | ||
653 | |||
654 | len = mbox->cmd.length; | ||
655 | |||
656 | if (len) { | ||
657 | |||
658 | if( copy_from_user((void*)&mbox->data, u_data, len)) | ||
659 | return -EFAULT; | ||
660 | |||
661 | } | ||
662 | |||
663 | /* execute command */ | ||
664 | if (!sdla_exec(mbox)) | ||
665 | return -EIO; | ||
666 | |||
667 | /* return result */ | ||
668 | if( copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t))) | ||
669 | return -EFAULT; | ||
670 | len = mbox->cmd.length; | ||
671 | |||
672 | if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)) | ||
673 | return -EFAULT; | ||
674 | |||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | /****** Network Device Interface ********************************************/ | ||
679 | |||
680 | /*============================================================================ | ||
681 | * Initialize Linux network interface. | ||
682 | * | ||
683 | * This routine is called only once for each interface, during Linux network | ||
684 | * interface registration. Returning anything but zero will fail interface | ||
685 | * registration. | ||
686 | */ | ||
687 | static int if_init(struct net_device *dev) | ||
688 | { | ||
689 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
690 | sdla_t *card = ppp_priv_area->card; | ||
691 | struct wan_device *wandev = &card->wandev; | ||
692 | |||
693 | /* Initialize device driver entry points */ | ||
694 | dev->open = &if_open; | ||
695 | dev->stop = &if_close; | ||
696 | dev->hard_header = &if_header; | ||
697 | dev->rebuild_header = &if_rebuild_hdr; | ||
698 | dev->hard_start_xmit = &if_send; | ||
699 | dev->get_stats = &if_stats; | ||
700 | dev->tx_timeout = &if_tx_timeout; | ||
701 | dev->watchdog_timeo = TX_TIMEOUT; | ||
702 | |||
703 | /* Initialize media-specific parameters */ | ||
704 | dev->type = ARPHRD_PPP; /* ARP h/w type */ | ||
705 | dev->flags |= IFF_POINTOPOINT; | ||
706 | dev->flags |= IFF_NOARP; | ||
707 | |||
708 | /* Enable Mulitcasting if specified by user*/ | ||
709 | if (ppp_priv_area->mc == WANOPT_YES){ | ||
710 | dev->flags |= IFF_MULTICAST; | ||
711 | } | ||
712 | |||
713 | dev->mtu = wandev->mtu; | ||
714 | dev->hard_header_len = PPP_HDR_LEN; /* media header length */ | ||
715 | |||
716 | /* Initialize hardware parameters (just for reference) */ | ||
717 | dev->irq = wandev->irq; | ||
718 | dev->dma = wandev->dma; | ||
719 | dev->base_addr = wandev->ioport; | ||
720 | dev->mem_start = wandev->maddr; | ||
721 | dev->mem_end = wandev->maddr + wandev->msize - 1; | ||
722 | |||
723 | /* Set transmit buffer queue length */ | ||
724 | dev->tx_queue_len = 100; | ||
725 | SET_MODULE_OWNER(dev); | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | /*============================================================================ | ||
731 | * Open network interface. | ||
732 | * o enable communications and interrupts. | ||
733 | * o prevent module from unloading by incrementing use count | ||
734 | * | ||
735 | * Return 0 if O.k. or errno. | ||
736 | */ | ||
737 | static int if_open(struct net_device *dev) | ||
738 | { | ||
739 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
740 | sdla_t *card = ppp_priv_area->card; | ||
741 | struct timeval tv; | ||
742 | //unsigned long smp_flags; | ||
743 | |||
744 | if (netif_running(dev)) | ||
745 | return -EBUSY; | ||
746 | |||
747 | wanpipe_open(card); | ||
748 | |||
749 | netif_start_queue(dev); | ||
750 | |||
751 | do_gettimeofday( &tv ); | ||
752 | ppp_priv_area->router_start_time = tv.tv_sec; | ||
753 | |||
754 | /* We cannot configure the card here because we don't | ||
755 | * have access to the interface IP addresses. | ||
756 | * Once the interface initilization is complete, we will be | ||
757 | * able to access the IP addresses. Therefore, | ||
758 | * configure the ppp link in the poll routine */ | ||
759 | set_bit(0,&ppp_priv_area->config_ppp); | ||
760 | ppp_priv_area->config_wait_timeout=jiffies; | ||
761 | |||
762 | /* Start the PPP configuration after 1sec delay. | ||
763 | * This will give the interface initilization time | ||
764 | * to finish its configuration */ | ||
765 | mod_timer(&ppp_priv_area->poll_delay_timer, jiffies + HZ); | ||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | /*============================================================================ | ||
770 | * Close network interface. | ||
771 | * o if this is the last open, then disable communications and interrupts. | ||
772 | * o reset flags. | ||
773 | */ | ||
774 | static int if_close(struct net_device *dev) | ||
775 | { | ||
776 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
777 | sdla_t *card = ppp_priv_area->card; | ||
778 | |||
779 | netif_stop_queue(dev); | ||
780 | wanpipe_close(card); | ||
781 | |||
782 | del_timer (&ppp_priv_area->poll_delay_timer); | ||
783 | return 0; | ||
784 | } | ||
785 | |||
786 | /*============================================================================ | ||
787 | * Build media header. | ||
788 | * | ||
789 | * The trick here is to put packet type (Ethertype) into 'protocol' field of | ||
790 | * the socket buffer, so that we don't forget it. If packet type is not | ||
791 | * supported, set skb->protocol to 0 and discard packet later. | ||
792 | * | ||
793 | * Return: media header length. | ||
794 | */ | ||
795 | static int if_header(struct sk_buff *skb, struct net_device *dev, | ||
796 | unsigned short type, void *daddr, void *saddr, unsigned len) | ||
797 | { | ||
798 | switch (type) | ||
799 | { | ||
800 | case ETH_P_IP: | ||
801 | case ETH_P_IPX: | ||
802 | skb->protocol = htons(type); | ||
803 | break; | ||
804 | |||
805 | default: | ||
806 | skb->protocol = 0; | ||
807 | } | ||
808 | |||
809 | return PPP_HDR_LEN; | ||
810 | } | ||
811 | |||
812 | /*============================================================================ | ||
813 | * Re-build media header. | ||
814 | * | ||
815 | * Return: 1 physical address resolved. | ||
816 | * 0 physical address not resolved | ||
817 | */ | ||
818 | static int if_rebuild_hdr (struct sk_buff *skb) | ||
819 | { | ||
820 | struct net_device *dev = skb->dev; | ||
821 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
822 | sdla_t *card = ppp_priv_area->card; | ||
823 | |||
824 | printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n", | ||
825 | card->devname, dev->name); | ||
826 | return 1; | ||
827 | } | ||
828 | |||
829 | /*============================================================================ | ||
830 | * Handle transmit timeout event from netif watchdog | ||
831 | */ | ||
832 | static void if_tx_timeout(struct net_device *dev) | ||
833 | { | ||
834 | ppp_private_area_t* chan = dev->priv; | ||
835 | sdla_t *card = chan->card; | ||
836 | |||
837 | /* If our device stays busy for at least 5 seconds then we will | ||
838 | * kick start the device by making dev->tbusy = 0. We expect | ||
839 | * that our device never stays busy more than 5 seconds. So this | ||
840 | * is only used as a last resort. | ||
841 | */ | ||
842 | |||
843 | ++ chan->if_send_stat.if_send_tbusy; | ||
844 | ++card->wandev.stats.collisions; | ||
845 | |||
846 | printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); | ||
847 | ++chan->if_send_stat.if_send_tbusy_timeout; | ||
848 | netif_wake_queue (dev); | ||
849 | } | ||
850 | |||
851 | |||
852 | |||
853 | /*============================================================================ | ||
854 | * Send a packet on a network interface. | ||
855 | * o set tbusy flag (marks start of the transmission) to block a timer-based | ||
856 | * transmit from overlapping. | ||
857 | * o check link state. If link is not up, then drop the packet. | ||
858 | * o execute adapter send command. | ||
859 | * o free socket buffer | ||
860 | * | ||
861 | * Return: 0 complete (socket buffer must be freed) | ||
862 | * non-0 packet may be re-transmitted (tbusy must be set) | ||
863 | * | ||
864 | * Notes: | ||
865 | * 1. This routine is called either by the protocol stack or by the "net | ||
866 | * bottom half" (with interrupts enabled). | ||
867 | * 2. Setting tbusy flag will inhibit further transmit requests from the | ||
868 | * protocol stack and can be used for flow control with protocol layer. | ||
869 | */ | ||
870 | static int if_send (struct sk_buff *skb, struct net_device *dev) | ||
871 | { | ||
872 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
873 | sdla_t *card = ppp_priv_area->card; | ||
874 | unsigned char *sendpacket; | ||
875 | unsigned long smp_flags; | ||
876 | ppp_flags_t *flags = card->flags; | ||
877 | int udp_type; | ||
878 | int err=0; | ||
879 | |||
880 | ++ppp_priv_area->if_send_stat.if_send_entry; | ||
881 | |||
882 | netif_stop_queue(dev); | ||
883 | |||
884 | if (skb == NULL) { | ||
885 | |||
886 | /* If we get here, some higher layer thinks we've missed an | ||
887 | * tx-done interrupt. | ||
888 | */ | ||
889 | printk(KERN_INFO "%s: interface %s got kicked!\n", | ||
890 | card->devname, dev->name); | ||
891 | |||
892 | ++ppp_priv_area->if_send_stat.if_send_skb_null; | ||
893 | |||
894 | netif_wake_queue(dev); | ||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | sendpacket = skb->data; | ||
899 | |||
900 | udp_type = udp_pkt_type( skb, card ); | ||
901 | |||
902 | |||
903 | if (udp_type == UDP_PTPIPE_TYPE){ | ||
904 | if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev, | ||
905 | ppp_priv_area)){ | ||
906 | flags->imask |= PPP_INTR_TIMER; | ||
907 | } | ||
908 | ++ppp_priv_area->if_send_stat.if_send_PIPE_request; | ||
909 | netif_start_queue(dev); | ||
910 | return 0; | ||
911 | } | ||
912 | |||
913 | /* Check for broadcast and multicast addresses | ||
914 | * If found, drop (deallocate) a packet and return. | ||
915 | */ | ||
916 | if(chk_bcast_mcast_addr(card, dev, skb)){ | ||
917 | ++card->wandev.stats.tx_dropped; | ||
918 | dev_kfree_skb_any(skb); | ||
919 | netif_start_queue(dev); | ||
920 | return 0; | ||
921 | } | ||
922 | |||
923 | |||
924 | if(card->hw.type != SDLA_S514){ | ||
925 | s508_lock(card,&smp_flags); | ||
926 | } | ||
927 | |||
928 | if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) { | ||
929 | |||
930 | printk(KERN_INFO "%s: Critical in if_send: %lx\n", | ||
931 | card->wandev.name,card->wandev.critical); | ||
932 | |||
933 | ++card->wandev.stats.tx_dropped; | ||
934 | ++ppp_priv_area->if_send_stat.if_send_critical_non_ISR; | ||
935 | netif_start_queue(dev); | ||
936 | goto if_send_exit_crit; | ||
937 | } | ||
938 | |||
939 | if (card->wandev.state != WAN_CONNECTED) { | ||
940 | |||
941 | ++ppp_priv_area->if_send_stat.if_send_wan_disconnected; | ||
942 | ++card->wandev.stats.tx_dropped; | ||
943 | netif_start_queue(dev); | ||
944 | |||
945 | } else if (!skb->protocol) { | ||
946 | ++ppp_priv_area->if_send_stat.if_send_protocol_error; | ||
947 | ++card->wandev.stats.tx_errors; | ||
948 | netif_start_queue(dev); | ||
949 | |||
950 | } else { | ||
951 | |||
952 | /*If it's IPX change the network numbers to 0 if they're ours.*/ | ||
953 | if( skb->protocol == htons(ETH_P_IPX) ) { | ||
954 | if(ppp_priv_area->enable_IPX) { | ||
955 | switch_net_numbers( skb->data, | ||
956 | ppp_priv_area->network_number, 0); | ||
957 | } else { | ||
958 | ++card->wandev.stats.tx_dropped; | ||
959 | netif_start_queue(dev); | ||
960 | goto if_send_exit_crit; | ||
961 | } | ||
962 | } | ||
963 | |||
964 | if (ppp_send(card, skb->data, skb->len, skb->protocol)) { | ||
965 | netif_stop_queue(dev); | ||
966 | ++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full; | ||
967 | ++ppp_priv_area->if_send_stat.if_send_tx_int_enabled; | ||
968 | } else { | ||
969 | ++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr; | ||
970 | ++card->wandev.stats.tx_packets; | ||
971 | card->wandev.stats.tx_bytes += skb->len; | ||
972 | netif_start_queue(dev); | ||
973 | dev->trans_start = jiffies; | ||
974 | } | ||
975 | } | ||
976 | |||
977 | if_send_exit_crit: | ||
978 | |||
979 | if (!(err=netif_queue_stopped(dev))){ | ||
980 | dev_kfree_skb_any(skb); | ||
981 | }else{ | ||
982 | ppp_priv_area->tick_counter = jiffies; | ||
983 | flags->imask |= PPP_INTR_TXRDY; /* unmask Tx interrupts */ | ||
984 | } | ||
985 | |||
986 | clear_bit(SEND_CRIT,&card->wandev.critical); | ||
987 | if(card->hw.type != SDLA_S514){ | ||
988 | s508_unlock(card,&smp_flags); | ||
989 | } | ||
990 | |||
991 | return err; | ||
992 | } | ||
993 | |||
994 | |||
995 | /*============================================================================= | ||
996 | * Store a UDP management packet for later processing. | ||
997 | */ | ||
998 | |||
999 | static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, | ||
1000 | struct sk_buff *skb, struct net_device* dev, | ||
1001 | ppp_private_area_t* ppp_priv_area ) | ||
1002 | { | ||
1003 | int udp_pkt_stored = 0; | ||
1004 | |||
1005 | if(!ppp_priv_area->udp_pkt_lgth && (skb->len<=MAX_LGTH_UDP_MGNT_PKT)){ | ||
1006 | ppp_priv_area->udp_pkt_lgth = skb->len; | ||
1007 | ppp_priv_area->udp_pkt_src = udp_pkt_src; | ||
1008 | memcpy(ppp_priv_area->udp_pkt_data, skb->data, skb->len); | ||
1009 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UDP; | ||
1010 | ppp_priv_area->protocol = skb->protocol; | ||
1011 | udp_pkt_stored = 1; | ||
1012 | }else{ | ||
1013 | if (skb->len > MAX_LGTH_UDP_MGNT_PKT){ | ||
1014 | printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n", | ||
1015 | card->devname, skb->len); | ||
1016 | }else{ | ||
1017 | printk(KERN_INFO "%s: PIPEMON UPD request already pending\n", | ||
1018 | card->devname); | ||
1019 | } | ||
1020 | ppp_priv_area->udp_pkt_lgth = 0; | ||
1021 | } | ||
1022 | |||
1023 | if(udp_pkt_src == UDP_PKT_FRM_STACK){ | ||
1024 | dev_kfree_skb_any(skb); | ||
1025 | }else{ | ||
1026 | dev_kfree_skb_any(skb); | ||
1027 | } | ||
1028 | |||
1029 | return(udp_pkt_stored); | ||
1030 | } | ||
1031 | |||
1032 | |||
1033 | |||
1034 | /*============================================================================ | ||
1035 | * Reply to UDP Management system. | ||
1036 | * Return length of reply. | ||
1037 | */ | ||
1038 | static int reply_udp( unsigned char *data, unsigned int mbox_len ) | ||
1039 | { | ||
1040 | unsigned short len, udp_length, temp, ip_length; | ||
1041 | unsigned long ip_temp; | ||
1042 | int even_bound = 0; | ||
1043 | ppp_udp_pkt_t *p_udp_pkt = (ppp_udp_pkt_t *)data; | ||
1044 | |||
1045 | /* Set length of packet */ | ||
1046 | len = sizeof(ip_pkt_t)+ | ||
1047 | sizeof(udp_pkt_t)+ | ||
1048 | sizeof(wp_mgmt_t)+ | ||
1049 | sizeof(cblock_t)+ | ||
1050 | mbox_len; | ||
1051 | |||
1052 | /* fill in UDP reply */ | ||
1053 | p_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; | ||
1054 | |||
1055 | /* fill in UDP length */ | ||
1056 | udp_length = sizeof(udp_pkt_t)+ | ||
1057 | sizeof(wp_mgmt_t)+ | ||
1058 | sizeof(cblock_t)+ | ||
1059 | mbox_len; | ||
1060 | |||
1061 | |||
1062 | /* put it on an even boundary */ | ||
1063 | if ( udp_length & 0x0001 ) { | ||
1064 | udp_length += 1; | ||
1065 | len += 1; | ||
1066 | even_bound=1; | ||
1067 | } | ||
1068 | |||
1069 | temp = (udp_length<<8)|(udp_length>>8); | ||
1070 | p_udp_pkt->udp_pkt.udp_length = temp; | ||
1071 | |||
1072 | |||
1073 | /* swap UDP ports */ | ||
1074 | temp = p_udp_pkt->udp_pkt.udp_src_port; | ||
1075 | p_udp_pkt->udp_pkt.udp_src_port = | ||
1076 | p_udp_pkt->udp_pkt.udp_dst_port; | ||
1077 | p_udp_pkt->udp_pkt.udp_dst_port = temp; | ||
1078 | |||
1079 | |||
1080 | /* add UDP pseudo header */ | ||
1081 | temp = 0x1100; | ||
1082 | *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound)) = temp; | ||
1083 | temp = (udp_length<<8)|(udp_length>>8); | ||
1084 | *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound+2)) = temp; | ||
1085 | |||
1086 | /* calculate UDP checksum */ | ||
1087 | p_udp_pkt->udp_pkt.udp_checksum = 0; | ||
1088 | p_udp_pkt->udp_pkt.udp_checksum = | ||
1089 | calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET); | ||
1090 | |||
1091 | /* fill in IP length */ | ||
1092 | ip_length = udp_length + sizeof(ip_pkt_t); | ||
1093 | temp = (ip_length<<8)|(ip_length>>8); | ||
1094 | p_udp_pkt->ip_pkt.total_length = temp; | ||
1095 | |||
1096 | /* swap IP addresses */ | ||
1097 | ip_temp = p_udp_pkt->ip_pkt.ip_src_address; | ||
1098 | p_udp_pkt->ip_pkt.ip_src_address = p_udp_pkt->ip_pkt.ip_dst_address; | ||
1099 | p_udp_pkt->ip_pkt.ip_dst_address = ip_temp; | ||
1100 | |||
1101 | /* fill in IP checksum */ | ||
1102 | p_udp_pkt->ip_pkt.hdr_checksum = 0; | ||
1103 | p_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t)); | ||
1104 | |||
1105 | return len; | ||
1106 | |||
1107 | } /* reply_udp */ | ||
1108 | |||
1109 | unsigned short calc_checksum (char *data, int len) | ||
1110 | { | ||
1111 | unsigned short temp; | ||
1112 | unsigned long sum=0; | ||
1113 | int i; | ||
1114 | |||
1115 | for( i = 0; i <len; i+=2 ) { | ||
1116 | memcpy(&temp,&data[i],2); | ||
1117 | sum += (unsigned long)temp; | ||
1118 | } | ||
1119 | |||
1120 | while (sum >> 16 ) { | ||
1121 | sum = (sum & 0xffffUL) + (sum >> 16); | ||
1122 | } | ||
1123 | |||
1124 | temp = (unsigned short)sum; | ||
1125 | temp = ~temp; | ||
1126 | |||
1127 | if( temp == 0 ) | ||
1128 | temp = 0xffff; | ||
1129 | |||
1130 | return temp; | ||
1131 | } | ||
1132 | |||
1133 | /* | ||
1134 | If incoming is 0 (outgoing)- if the net numbers is ours make it 0 | ||
1135 | if incoming is 1 - if the net number is 0 make it ours | ||
1136 | |||
1137 | */ | ||
1138 | static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming) | ||
1139 | { | ||
1140 | unsigned long pnetwork_number; | ||
1141 | |||
1142 | pnetwork_number = (unsigned long)((sendpacket[6] << 24) + | ||
1143 | (sendpacket[7] << 16) + (sendpacket[8] << 8) + | ||
1144 | sendpacket[9]); | ||
1145 | |||
1146 | if (!incoming) { | ||
1147 | //If the destination network number is ours, make it 0 | ||
1148 | if( pnetwork_number == network_number) { | ||
1149 | sendpacket[6] = sendpacket[7] = sendpacket[8] = | ||
1150 | sendpacket[9] = 0x00; | ||
1151 | } | ||
1152 | } else { | ||
1153 | //If the incoming network is 0, make it ours | ||
1154 | if( pnetwork_number == 0) { | ||
1155 | sendpacket[6] = (unsigned char)(network_number >> 24); | ||
1156 | sendpacket[7] = (unsigned char)((network_number & | ||
1157 | 0x00FF0000) >> 16); | ||
1158 | sendpacket[8] = (unsigned char)((network_number & | ||
1159 | 0x0000FF00) >> 8); | ||
1160 | sendpacket[9] = (unsigned char)(network_number & | ||
1161 | 0x000000FF); | ||
1162 | } | ||
1163 | } | ||
1164 | |||
1165 | |||
1166 | pnetwork_number = (unsigned long)((sendpacket[18] << 24) + | ||
1167 | (sendpacket[19] << 16) + (sendpacket[20] << 8) + | ||
1168 | sendpacket[21]); | ||
1169 | |||
1170 | if( !incoming ) { | ||
1171 | //If the source network is ours, make it 0 | ||
1172 | if( pnetwork_number == network_number) { | ||
1173 | sendpacket[18] = sendpacket[19] = sendpacket[20] = | ||
1174 | sendpacket[21] = 0x00; | ||
1175 | } | ||
1176 | } else { | ||
1177 | //If the source network is 0, make it ours | ||
1178 | if( pnetwork_number == 0 ) { | ||
1179 | sendpacket[18] = (unsigned char)(network_number >> 24); | ||
1180 | sendpacket[19] = (unsigned char)((network_number & | ||
1181 | 0x00FF0000) >> 16); | ||
1182 | sendpacket[20] = (unsigned char)((network_number & | ||
1183 | 0x0000FF00) >> 8); | ||
1184 | sendpacket[21] = (unsigned char)(network_number & | ||
1185 | 0x000000FF); | ||
1186 | } | ||
1187 | } | ||
1188 | } /* switch_net_numbers */ | ||
1189 | |||
1190 | /*============================================================================ | ||
1191 | * Get ethernet-style interface statistics. | ||
1192 | * Return a pointer to struct net_device_stats. | ||
1193 | */ | ||
1194 | static struct net_device_stats *if_stats(struct net_device *dev) | ||
1195 | { | ||
1196 | |||
1197 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
1198 | sdla_t* card; | ||
1199 | |||
1200 | if( ppp_priv_area == NULL ) | ||
1201 | return NULL; | ||
1202 | |||
1203 | card = ppp_priv_area->card; | ||
1204 | return &card->wandev.stats; | ||
1205 | } | ||
1206 | |||
1207 | /****** PPP Firmware Interface Functions ************************************/ | ||
1208 | |||
1209 | /*============================================================================ | ||
1210 | * Read firmware code version. | ||
1211 | * Put code version as ASCII string in str. | ||
1212 | */ | ||
1213 | static int ppp_read_version(sdla_t *card, char *str) | ||
1214 | { | ||
1215 | ppp_mbox_t *mb = card->mbox; | ||
1216 | int err; | ||
1217 | |||
1218 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1219 | mb->cmd.command = PPP_READ_CODE_VERSION; | ||
1220 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1221 | |||
1222 | if (err != CMD_OK) | ||
1223 | |||
1224 | ppp_error(card, err, mb); | ||
1225 | |||
1226 | else if (str) { | ||
1227 | |||
1228 | int len = mb->cmd.length; | ||
1229 | |||
1230 | memcpy(str, mb->data, len); | ||
1231 | str[len] = '\0'; | ||
1232 | |||
1233 | } | ||
1234 | |||
1235 | return err; | ||
1236 | } | ||
1237 | /*=========================================================================== | ||
1238 | * Set Out-Bound Authentication. | ||
1239 | */ | ||
1240 | static int ppp_set_outbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area) | ||
1241 | { | ||
1242 | ppp_mbox_t *mb = card->mbox; | ||
1243 | int err; | ||
1244 | |||
1245 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1246 | memset(&mb->data, 0, (strlen(ppp_priv_area->userid) + | ||
1247 | strlen(ppp_priv_area->passwd) + 2 ) ); | ||
1248 | memcpy(mb->data, ppp_priv_area->userid, strlen(ppp_priv_area->userid)); | ||
1249 | memcpy((mb->data + strlen(ppp_priv_area->userid) + 1), | ||
1250 | ppp_priv_area->passwd, strlen(ppp_priv_area->passwd)); | ||
1251 | |||
1252 | mb->cmd.length = strlen(ppp_priv_area->userid) + | ||
1253 | strlen(ppp_priv_area->passwd) + 2 ; | ||
1254 | |||
1255 | mb->cmd.command = PPP_SET_OUTBOUND_AUTH; | ||
1256 | |||
1257 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1258 | |||
1259 | if (err != CMD_OK) | ||
1260 | ppp_error(card, err, mb); | ||
1261 | |||
1262 | return err; | ||
1263 | } | ||
1264 | |||
1265 | /*=========================================================================== | ||
1266 | * Set In-Bound Authentication. | ||
1267 | */ | ||
1268 | static int ppp_set_inbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area) | ||
1269 | { | ||
1270 | ppp_mbox_t *mb = card->mbox; | ||
1271 | int err, i; | ||
1272 | char* user_tokens[32]; | ||
1273 | char* pass_tokens[32]; | ||
1274 | int userids, passwds; | ||
1275 | int add_ptr; | ||
1276 | |||
1277 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1278 | memset(&mb->data, 0, 1008); | ||
1279 | memcpy(mb->data, ppp_priv_area->sysname, | ||
1280 | strlen(ppp_priv_area->sysname)); | ||
1281 | |||
1282 | /* Parse the userid string and the password string and build a string | ||
1283 | to copy it to the data area of the command structure. The string | ||
1284 | will look like "SYS_NAME<NULL>USER1<NULL>PASS1<NULL>USER2<NULL>PASS2 | ||
1285 | ....<NULL> " | ||
1286 | */ | ||
1287 | userids = tokenize( ppp_priv_area->userid, user_tokens); | ||
1288 | passwds = tokenize( ppp_priv_area->passwd, pass_tokens); | ||
1289 | |||
1290 | if (userids != passwds){ | ||
1291 | printk(KERN_INFO "%s: Number of passwords does not equal the number of user ids\n", card->devname); | ||
1292 | return 1; | ||
1293 | } | ||
1294 | |||
1295 | add_ptr = strlen(ppp_priv_area->sysname) + 1; | ||
1296 | for (i=0; i<userids; i++){ | ||
1297 | memcpy((mb->data + add_ptr), user_tokens[i], | ||
1298 | strlen(user_tokens[i])); | ||
1299 | memcpy((mb->data + add_ptr + strlen(user_tokens[i]) + 1), | ||
1300 | pass_tokens[i], strlen(pass_tokens[i])); | ||
1301 | add_ptr = add_ptr + strlen(user_tokens[i]) + 1 + | ||
1302 | strlen(pass_tokens[i]) + 1; | ||
1303 | } | ||
1304 | |||
1305 | mb->cmd.length = add_ptr + 1; | ||
1306 | mb->cmd.command = PPP_SET_INBOUND_AUTH; | ||
1307 | |||
1308 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1309 | |||
1310 | if (err != CMD_OK) | ||
1311 | ppp_error(card, err, mb); | ||
1312 | |||
1313 | return err; | ||
1314 | } | ||
1315 | |||
1316 | |||
1317 | /*============================================================================ | ||
1318 | * Tokenize string. | ||
1319 | * Parse a string of the following syntax: | ||
1320 | * <arg1>,<arg2>,... | ||
1321 | * and fill array of tokens with pointers to string elements. | ||
1322 | * | ||
1323 | */ | ||
1324 | static int tokenize (char *str, char **tokens) | ||
1325 | { | ||
1326 | int cnt = 0; | ||
1327 | |||
1328 | tokens[0] = strsep(&str, "/"); | ||
1329 | while (tokens[cnt] && (cnt < 32 - 1)) | ||
1330 | { | ||
1331 | tokens[cnt] = strstrip(tokens[cnt], " \t"); | ||
1332 | tokens[++cnt] = strsep(&str, "/"); | ||
1333 | } | ||
1334 | return cnt; | ||
1335 | } | ||
1336 | |||
1337 | /*============================================================================ | ||
1338 | * Strip leading and trailing spaces off the string str. | ||
1339 | */ | ||
1340 | static char* strstrip (char *str, char* s) | ||
1341 | { | ||
1342 | char *eos = str + strlen(str); /* -> end of string */ | ||
1343 | |||
1344 | while (*str && strchr(s, *str)) | ||
1345 | ++str /* strip leading spaces */ | ||
1346 | ; | ||
1347 | while ((eos > str) && strchr(s, *(eos - 1))) | ||
1348 | --eos /* strip trailing spaces */ | ||
1349 | ; | ||
1350 | *eos = '\0'; | ||
1351 | return str; | ||
1352 | } | ||
1353 | /*============================================================================ | ||
1354 | * Configure PPP firmware. | ||
1355 | */ | ||
1356 | static int ppp_configure(sdla_t *card, void *data) | ||
1357 | { | ||
1358 | ppp_mbox_t *mb = card->mbox; | ||
1359 | int data_len = sizeof(ppp508_conf_t); | ||
1360 | int err; | ||
1361 | |||
1362 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1363 | memcpy(mb->data, data, data_len); | ||
1364 | mb->cmd.length = data_len; | ||
1365 | mb->cmd.command = PPP_SET_CONFIG; | ||
1366 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1367 | |||
1368 | if (err != CMD_OK) | ||
1369 | ppp_error(card, err, mb); | ||
1370 | |||
1371 | return err; | ||
1372 | } | ||
1373 | |||
1374 | /*============================================================================ | ||
1375 | * Set interrupt mode. | ||
1376 | */ | ||
1377 | static int ppp_set_intr_mode(sdla_t *card, unsigned char mode) | ||
1378 | { | ||
1379 | ppp_mbox_t *mb = card->mbox; | ||
1380 | ppp_intr_info_t *ppp_intr_data = (ppp_intr_info_t *) &mb->data[0]; | ||
1381 | int err; | ||
1382 | |||
1383 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1384 | ppp_intr_data->i_enable = mode; | ||
1385 | |||
1386 | ppp_intr_data->irq = card->hw.irq; | ||
1387 | mb->cmd.length = 2; | ||
1388 | |||
1389 | /* If timer has been enabled, set the timer delay to 1sec */ | ||
1390 | if (mode & 0x80){ | ||
1391 | ppp_intr_data->timer_len = 250; //5;//100; //250; | ||
1392 | mb->cmd.length = 4; | ||
1393 | } | ||
1394 | |||
1395 | mb->cmd.command = PPP_SET_INTR_FLAGS; | ||
1396 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1397 | |||
1398 | if (err != CMD_OK) | ||
1399 | ppp_error(card, err, mb); | ||
1400 | |||
1401 | |||
1402 | return err; | ||
1403 | } | ||
1404 | |||
1405 | /*============================================================================ | ||
1406 | * Enable communications. | ||
1407 | */ | ||
1408 | static int ppp_comm_enable(sdla_t *card) | ||
1409 | { | ||
1410 | ppp_mbox_t *mb = card->mbox; | ||
1411 | int err; | ||
1412 | |||
1413 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1414 | mb->cmd.command = PPP_COMM_ENABLE; | ||
1415 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1416 | |||
1417 | if (err != CMD_OK) | ||
1418 | ppp_error(card, err, mb); | ||
1419 | else | ||
1420 | card->u.p.comm_enabled = 1; | ||
1421 | |||
1422 | return err; | ||
1423 | } | ||
1424 | |||
1425 | /*============================================================================ | ||
1426 | * Disable communications. | ||
1427 | */ | ||
1428 | static int ppp_comm_disable(sdla_t *card) | ||
1429 | { | ||
1430 | ppp_mbox_t *mb = card->mbox; | ||
1431 | int err; | ||
1432 | |||
1433 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1434 | mb->cmd.command = PPP_COMM_DISABLE; | ||
1435 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1436 | if (err != CMD_OK) | ||
1437 | ppp_error(card, err, mb); | ||
1438 | else | ||
1439 | card->u.p.comm_enabled = 0; | ||
1440 | |||
1441 | return err; | ||
1442 | } | ||
1443 | |||
1444 | static int ppp_comm_disable_shutdown(sdla_t *card) | ||
1445 | { | ||
1446 | ppp_mbox_t *mb = card->mbox; | ||
1447 | ppp_intr_info_t *ppp_intr_data; | ||
1448 | int err; | ||
1449 | |||
1450 | if (!mb){ | ||
1451 | return 1; | ||
1452 | } | ||
1453 | |||
1454 | ppp_intr_data = (ppp_intr_info_t *) &mb->data[0]; | ||
1455 | |||
1456 | /* Disable all interrupts */ | ||
1457 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1458 | ppp_intr_data->i_enable = 0; | ||
1459 | |||
1460 | ppp_intr_data->irq = card->hw.irq; | ||
1461 | mb->cmd.length = 2; | ||
1462 | |||
1463 | mb->cmd.command = PPP_SET_INTR_FLAGS; | ||
1464 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1465 | |||
1466 | /* Disable communicatinons */ | ||
1467 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1468 | mb->cmd.command = PPP_COMM_DISABLE; | ||
1469 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1470 | |||
1471 | card->u.p.comm_enabled = 0; | ||
1472 | |||
1473 | return 0; | ||
1474 | } | ||
1475 | |||
1476 | |||
1477 | |||
1478 | /*============================================================================ | ||
1479 | * Get communications error statistics. | ||
1480 | */ | ||
1481 | static int ppp_get_err_stats(sdla_t *card) | ||
1482 | { | ||
1483 | ppp_mbox_t *mb = card->mbox; | ||
1484 | int err; | ||
1485 | |||
1486 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1487 | mb->cmd.command = PPP_READ_ERROR_STATS; | ||
1488 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1489 | |||
1490 | if (err == CMD_OK) { | ||
1491 | |||
1492 | ppp_err_stats_t* stats = (void*)mb->data; | ||
1493 | card->wandev.stats.rx_over_errors = stats->rx_overrun; | ||
1494 | card->wandev.stats.rx_crc_errors = stats->rx_bad_crc; | ||
1495 | card->wandev.stats.rx_missed_errors = stats->rx_abort; | ||
1496 | card->wandev.stats.rx_length_errors = stats->rx_lost; | ||
1497 | card->wandev.stats.tx_aborted_errors = stats->tx_abort; | ||
1498 | |||
1499 | } else | ||
1500 | ppp_error(card, err, mb); | ||
1501 | |||
1502 | return err; | ||
1503 | } | ||
1504 | |||
1505 | /*============================================================================ | ||
1506 | * Send packet. | ||
1507 | * Return: 0 - o.k. | ||
1508 | * 1 - no transmit buffers available | ||
1509 | */ | ||
1510 | static int ppp_send (sdla_t *card, void *data, unsigned len, unsigned proto) | ||
1511 | { | ||
1512 | ppp_buf_ctl_t *txbuf = card->u.p.txbuf; | ||
1513 | |||
1514 | if (txbuf->flag) | ||
1515 | return 1; | ||
1516 | |||
1517 | sdla_poke(&card->hw, txbuf->buf.ptr, data, len); | ||
1518 | |||
1519 | txbuf->length = len; /* frame length */ | ||
1520 | |||
1521 | if (proto == htons(ETH_P_IPX)) | ||
1522 | txbuf->proto = 0x01; /* protocol ID */ | ||
1523 | else | ||
1524 | txbuf->proto = 0x00; /* protocol ID */ | ||
1525 | |||
1526 | txbuf->flag = 1; /* start transmission */ | ||
1527 | |||
1528 | /* Update transmit buffer control fields */ | ||
1529 | card->u.p.txbuf = ++txbuf; | ||
1530 | |||
1531 | if ((void*)txbuf > card->u.p.txbuf_last) | ||
1532 | card->u.p.txbuf = card->u.p.txbuf_base; | ||
1533 | |||
1534 | return 0; | ||
1535 | } | ||
1536 | |||
1537 | /****** Firmware Error Handler **********************************************/ | ||
1538 | |||
1539 | /*============================================================================ | ||
1540 | * Firmware error handler. | ||
1541 | * This routine is called whenever firmware command returns non-zero | ||
1542 | * return code. | ||
1543 | * | ||
1544 | * Return zero if previous command has to be cancelled. | ||
1545 | */ | ||
1546 | static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb) | ||
1547 | { | ||
1548 | unsigned cmd = mb->cmd.command; | ||
1549 | |||
1550 | switch (err) { | ||
1551 | |||
1552 | case CMD_TIMEOUT: | ||
1553 | printk(KERN_ERR "%s: command 0x%02X timed out!\n", | ||
1554 | card->devname, cmd); | ||
1555 | break; | ||
1556 | |||
1557 | default: | ||
1558 | printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n" | ||
1559 | , card->devname, cmd, err); | ||
1560 | } | ||
1561 | |||
1562 | return 0; | ||
1563 | } | ||
1564 | |||
1565 | /****** Interrupt Handlers **************************************************/ | ||
1566 | |||
1567 | /*============================================================================ | ||
1568 | * PPP interrupt service routine. | ||
1569 | */ | ||
1570 | static void wpp_isr (sdla_t *card) | ||
1571 | { | ||
1572 | ppp_flags_t *flags = card->flags; | ||
1573 | char *ptr = &flags->iflag; | ||
1574 | struct net_device *dev = card->wandev.dev; | ||
1575 | int i; | ||
1576 | |||
1577 | card->in_isr = 1; | ||
1578 | ++card->statistics.isr_entry; | ||
1579 | |||
1580 | if (!dev && flags->iflag != PPP_INTR_CMD){ | ||
1581 | card->in_isr = 0; | ||
1582 | flags->iflag = 0; | ||
1583 | return; | ||
1584 | } | ||
1585 | |||
1586 | if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { | ||
1587 | card->in_isr = 0; | ||
1588 | flags->iflag = 0; | ||
1589 | return; | ||
1590 | } | ||
1591 | |||
1592 | |||
1593 | if(card->hw.type != SDLA_S514){ | ||
1594 | if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) { | ||
1595 | ++card->statistics.isr_already_critical; | ||
1596 | printk (KERN_INFO "%s: Critical while in ISR!\n", | ||
1597 | card->devname); | ||
1598 | card->in_isr = 0; | ||
1599 | flags->iflag = 0; | ||
1600 | return; | ||
1601 | } | ||
1602 | } | ||
1603 | |||
1604 | switch (flags->iflag) { | ||
1605 | |||
1606 | case PPP_INTR_RXRDY: /* receive interrupt 0x01 (bit 0)*/ | ||
1607 | ++card->statistics.isr_rx; | ||
1608 | rx_intr(card); | ||
1609 | break; | ||
1610 | |||
1611 | case PPP_INTR_TXRDY: /* transmit interrupt 0x02 (bit 1)*/ | ||
1612 | ++card->statistics.isr_tx; | ||
1613 | flags->imask &= ~PPP_INTR_TXRDY; | ||
1614 | netif_wake_queue(dev); | ||
1615 | break; | ||
1616 | |||
1617 | case PPP_INTR_CMD: /* interface command completed */ | ||
1618 | ++Intr_test_counter; | ||
1619 | ++card->statistics.isr_intr_test; | ||
1620 | break; | ||
1621 | |||
1622 | case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/ | ||
1623 | case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/ | ||
1624 | case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/ | ||
1625 | case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */ | ||
1626 | event_intr(card); | ||
1627 | break; | ||
1628 | |||
1629 | case PPP_INTR_TIMER: | ||
1630 | timer_intr(card); | ||
1631 | break; | ||
1632 | |||
1633 | default: /* unexpected interrupt */ | ||
1634 | ++card->statistics.isr_spurious; | ||
1635 | printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", | ||
1636 | card->devname, flags->iflag); | ||
1637 | printk(KERN_INFO "%s: ID Bytes = ",card->devname); | ||
1638 | for(i = 0; i < 8; i ++) | ||
1639 | printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); | ||
1640 | printk(KERN_INFO "\n"); | ||
1641 | } | ||
1642 | |||
1643 | card->in_isr = 0; | ||
1644 | flags->iflag = 0; | ||
1645 | return; | ||
1646 | } | ||
1647 | |||
1648 | /*============================================================================ | ||
1649 | * Receive interrupt handler. | ||
1650 | */ | ||
1651 | static void rx_intr(sdla_t *card) | ||
1652 | { | ||
1653 | ppp_buf_ctl_t *rxbuf = card->rxmb; | ||
1654 | struct net_device *dev = card->wandev.dev; | ||
1655 | ppp_private_area_t *ppp_priv_area; | ||
1656 | struct sk_buff *skb; | ||
1657 | unsigned len; | ||
1658 | void *buf; | ||
1659 | int i; | ||
1660 | ppp_flags_t *flags = card->flags; | ||
1661 | char *ptr = &flags->iflag; | ||
1662 | int udp_type; | ||
1663 | |||
1664 | |||
1665 | if (rxbuf->flag != 0x01) { | ||
1666 | |||
1667 | printk(KERN_INFO | ||
1668 | "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", | ||
1669 | card->devname, (unsigned)rxbuf, rxbuf->flag); | ||
1670 | |||
1671 | printk(KERN_INFO "%s: ID Bytes = ",card->devname); | ||
1672 | |||
1673 | for(i = 0; i < 8; i ++) | ||
1674 | printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); | ||
1675 | printk(KERN_INFO "\n"); | ||
1676 | |||
1677 | ++card->statistics.rx_intr_corrupt_rx_bfr; | ||
1678 | |||
1679 | |||
1680 | /* Bug Fix: Mar 6 2000 | ||
1681 | * If we get a corrupted mailbox, it means that driver | ||
1682 | * is out of sync with the firmware. There is no recovery. | ||
1683 | * If we don't turn off all interrupts for this card | ||
1684 | * the machine will crash. | ||
1685 | */ | ||
1686 | printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname); | ||
1687 | printk(KERN_INFO "Please contact Sangoma Technologies !\n"); | ||
1688 | ppp_set_intr_mode(card,0); | ||
1689 | return; | ||
1690 | } | ||
1691 | |||
1692 | if (dev && netif_running(dev) && dev->priv){ | ||
1693 | |||
1694 | len = rxbuf->length; | ||
1695 | ppp_priv_area = dev->priv; | ||
1696 | |||
1697 | /* Allocate socket buffer */ | ||
1698 | skb = dev_alloc_skb(len); | ||
1699 | |||
1700 | if (skb != NULL) { | ||
1701 | |||
1702 | /* Copy data to the socket buffer */ | ||
1703 | unsigned addr = rxbuf->buf.ptr; | ||
1704 | |||
1705 | if ((addr + len) > card->u.p.rx_top + 1) { | ||
1706 | |||
1707 | unsigned tmp = card->u.p.rx_top - addr + 1; | ||
1708 | buf = skb_put(skb, tmp); | ||
1709 | sdla_peek(&card->hw, addr, buf, tmp); | ||
1710 | addr = card->u.p.rx_base; | ||
1711 | len -= tmp; | ||
1712 | } | ||
1713 | buf = skb_put(skb, len); | ||
1714 | sdla_peek(&card->hw, addr, buf, len); | ||
1715 | |||
1716 | /* Decapsulate packet */ | ||
1717 | switch (rxbuf->proto) { | ||
1718 | |||
1719 | case 0x00: | ||
1720 | skb->protocol = htons(ETH_P_IP); | ||
1721 | break; | ||
1722 | |||
1723 | case 0x01: | ||
1724 | skb->protocol = htons(ETH_P_IPX); | ||
1725 | break; | ||
1726 | } | ||
1727 | |||
1728 | udp_type = udp_pkt_type( skb, card ); | ||
1729 | |||
1730 | if (udp_type == UDP_PTPIPE_TYPE){ | ||
1731 | |||
1732 | /* Handle a UDP Request in Timer Interrupt */ | ||
1733 | if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, card, skb, dev, | ||
1734 | ppp_priv_area)){ | ||
1735 | flags->imask |= PPP_INTR_TIMER; | ||
1736 | } | ||
1737 | ++ppp_priv_area->rx_intr_stat.rx_intr_PIPE_request; | ||
1738 | |||
1739 | |||
1740 | } else if (handle_IPXWAN(skb->data,card->devname, | ||
1741 | ppp_priv_area->enable_IPX, | ||
1742 | ppp_priv_area->network_number, | ||
1743 | skb->protocol)) { | ||
1744 | |||
1745 | /* Handle an IPXWAN packet */ | ||
1746 | if( ppp_priv_area->enable_IPX) { | ||
1747 | |||
1748 | /* Make sure we are not already sending */ | ||
1749 | if (!test_bit(SEND_CRIT, &card->wandev.critical)){ | ||
1750 | ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX)); | ||
1751 | } | ||
1752 | dev_kfree_skb_any(skb); | ||
1753 | |||
1754 | } else { | ||
1755 | ++card->wandev.stats.rx_dropped; | ||
1756 | } | ||
1757 | } else { | ||
1758 | /* Pass data up the protocol stack */ | ||
1759 | skb->dev = dev; | ||
1760 | skb->mac.raw = skb->data; | ||
1761 | |||
1762 | ++card->wandev.stats.rx_packets; | ||
1763 | card->wandev.stats.rx_bytes += skb->len; | ||
1764 | ++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack; | ||
1765 | netif_rx(skb); | ||
1766 | dev->last_rx = jiffies; | ||
1767 | } | ||
1768 | |||
1769 | } else { | ||
1770 | |||
1771 | if (net_ratelimit()){ | ||
1772 | printk(KERN_INFO "%s: no socket buffers available!\n", | ||
1773 | card->devname); | ||
1774 | } | ||
1775 | ++card->wandev.stats.rx_dropped; | ||
1776 | ++ppp_priv_area->rx_intr_stat.rx_intr_no_socket; | ||
1777 | } | ||
1778 | |||
1779 | } else { | ||
1780 | ++card->statistics.rx_intr_dev_not_started; | ||
1781 | } | ||
1782 | |||
1783 | /* Release buffer element and calculate a pointer to the next one */ | ||
1784 | rxbuf->flag = 0x00; | ||
1785 | card->rxmb = ++rxbuf; | ||
1786 | if ((void*)rxbuf > card->u.p.rxbuf_last) | ||
1787 | card->rxmb = card->u.p.rxbuf_base; | ||
1788 | } | ||
1789 | |||
1790 | |||
1791 | void event_intr (sdla_t *card) | ||
1792 | { | ||
1793 | |||
1794 | struct net_device* dev = card->wandev.dev; | ||
1795 | ppp_private_area_t* ppp_priv_area = dev->priv; | ||
1796 | volatile ppp_flags_t *flags = card->flags; | ||
1797 | |||
1798 | switch (flags->iflag){ | ||
1799 | |||
1800 | case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/ | ||
1801 | |||
1802 | if (net_ratelimit()){ | ||
1803 | printk (KERN_INFO "%s: Modem status: DCD=%s CTS=%s\n", | ||
1804 | card->devname, DCD(flags->mstatus), CTS(flags->mstatus)); | ||
1805 | } | ||
1806 | break; | ||
1807 | |||
1808 | case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/ | ||
1809 | |||
1810 | NEX_PRINTK (KERN_INFO "Data link disconnected intr Cause %X\n", | ||
1811 | flags->disc_cause); | ||
1812 | |||
1813 | if (flags->disc_cause & | ||
1814 | (PPP_LOCAL_TERMINATION | PPP_DCD_CTS_DROP | | ||
1815 | PPP_REMOTE_TERMINATION)) { | ||
1816 | |||
1817 | if (card->u.p.ip_mode == WANOPT_PPP_PEER) { | ||
1818 | set_bit(0,&Read_connection_info); | ||
1819 | } | ||
1820 | wanpipe_set_state(card, WAN_DISCONNECTED); | ||
1821 | |||
1822 | show_disc_cause(card, flags->disc_cause); | ||
1823 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; | ||
1824 | flags->imask |= PPP_INTR_TIMER; | ||
1825 | trigger_ppp_poll(dev); | ||
1826 | } | ||
1827 | break; | ||
1828 | |||
1829 | case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/ | ||
1830 | |||
1831 | NEX_PRINTK (KERN_INFO "%s: PPP Link Open, LCP=%s IP=%s\n", | ||
1832 | card->devname,LCP(flags->lcp_state), | ||
1833 | IP(flags->ip_state)); | ||
1834 | |||
1835 | if (flags->lcp_state == 0x09 && | ||
1836 | (flags->ip_state == 0x09 || flags->ipx_state == 0x09)){ | ||
1837 | |||
1838 | /* Initialize the polling timer and set the state | ||
1839 | * to WAN_CONNNECTED */ | ||
1840 | |||
1841 | |||
1842 | /* BUG FIX: When the protocol restarts, during heavy | ||
1843 | * traffic, board tx buffers and driver tx buffers | ||
1844 | * can go out of sync. This checks the condition | ||
1845 | * and if the tx buffers are out of sync, the | ||
1846 | * protocols are restarted. | ||
1847 | * I don't know why the board tx buffer is out | ||
1848 | * of sync. It could be that a packets is tx | ||
1849 | * while the link is down, but that is not | ||
1850 | * possible. The other possiblility is that the | ||
1851 | * firmware doesn't reinitialize properly. | ||
1852 | * FIXME: A better fix should be found. | ||
1853 | */ | ||
1854 | if (detect_and_fix_tx_bug(card)){ | ||
1855 | |||
1856 | ppp_comm_disable(card); | ||
1857 | |||
1858 | wanpipe_set_state(card, WAN_DISCONNECTED); | ||
1859 | |||
1860 | ppp_priv_area->timer_int_enabled |= | ||
1861 | TMR_INT_ENABLED_PPP_EVENT; | ||
1862 | flags->imask |= PPP_INTR_TIMER; | ||
1863 | break; | ||
1864 | } | ||
1865 | |||
1866 | card->state_tick = jiffies; | ||
1867 | wanpipe_set_state(card, WAN_CONNECTED); | ||
1868 | |||
1869 | NEX_PRINTK(KERN_INFO "CON: L Tx: %lx B Tx: %lx || L Rx %lx B Rx %lx\n", | ||
1870 | (unsigned long)card->u.p.txbuf, *card->u.p.txbuf_next, | ||
1871 | (unsigned long)card->rxmb, *card->u.p.rxbuf_next); | ||
1872 | |||
1873 | /* Tell timer interrupt that PPP event occurred */ | ||
1874 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; | ||
1875 | flags->imask |= PPP_INTR_TIMER; | ||
1876 | |||
1877 | /* If we are in PEER mode, we must first obtain the | ||
1878 | * IP information and then go into the poll routine */ | ||
1879 | if (card->u.p.ip_mode != WANOPT_PPP_PEER){ | ||
1880 | trigger_ppp_poll(dev); | ||
1881 | } | ||
1882 | } | ||
1883 | break; | ||
1884 | |||
1885 | case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */ | ||
1886 | |||
1887 | NEX_PRINTK(KERN_INFO "DTR Drop Timeout Interrrupt \n"); | ||
1888 | |||
1889 | if (card->u.p.ip_mode == WANOPT_PPP_PEER) { | ||
1890 | set_bit(0,&Read_connection_info); | ||
1891 | } | ||
1892 | |||
1893 | wanpipe_set_state(card, WAN_DISCONNECTED); | ||
1894 | |||
1895 | show_disc_cause(card, flags->disc_cause); | ||
1896 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; | ||
1897 | flags->imask |= PPP_INTR_TIMER; | ||
1898 | trigger_ppp_poll(dev); | ||
1899 | break; | ||
1900 | |||
1901 | default: | ||
1902 | printk(KERN_INFO "%s: Error, Invalid PPP Event\n",card->devname); | ||
1903 | } | ||
1904 | } | ||
1905 | |||
1906 | |||
1907 | |||
1908 | /* TIMER INTERRUPT */ | ||
1909 | |||
1910 | void timer_intr (sdla_t *card) | ||
1911 | { | ||
1912 | |||
1913 | struct net_device* dev = card->wandev.dev; | ||
1914 | ppp_private_area_t* ppp_priv_area = dev->priv; | ||
1915 | ppp_flags_t *flags = card->flags; | ||
1916 | |||
1917 | |||
1918 | if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG){ | ||
1919 | if (!config_ppp(card)){ | ||
1920 | ppp_priv_area->timer_int_enabled &= | ||
1921 | ~TMR_INT_ENABLED_CONFIG; | ||
1922 | } | ||
1923 | } | ||
1924 | |||
1925 | /* Update statistics */ | ||
1926 | if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE){ | ||
1927 | ppp_get_err_stats(card); | ||
1928 | if(!(--ppp_priv_area->update_comms_stats)){ | ||
1929 | ppp_priv_area->timer_int_enabled &= | ||
1930 | ~TMR_INT_ENABLED_UPDATE; | ||
1931 | } | ||
1932 | } | ||
1933 | |||
1934 | /* PPIPEMON UDP request */ | ||
1935 | |||
1936 | if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP){ | ||
1937 | process_udp_mgmt_pkt(card,dev, ppp_priv_area); | ||
1938 | ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP; | ||
1939 | } | ||
1940 | |||
1941 | /* PPP Event */ | ||
1942 | if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_PPP_EVENT){ | ||
1943 | |||
1944 | if (card->wandev.state == WAN_DISCONNECTED){ | ||
1945 | retrigger_comm(card); | ||
1946 | } | ||
1947 | |||
1948 | /* If the state is CONNECTING, it means that communicatins were | ||
1949 | * enabled. When the remote side enables its comminication we | ||
1950 | * should get an interrupt PPP_INTR_OPEN, thus turn off polling | ||
1951 | */ | ||
1952 | |||
1953 | else if (card->wandev.state == WAN_CONNECTING){ | ||
1954 | /* Turn off the timer interrupt */ | ||
1955 | ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT; | ||
1956 | } | ||
1957 | |||
1958 | /* If state is connected and we are in PEER mode | ||
1959 | * poll for an IP address which will be provided by remote end. | ||
1960 | */ | ||
1961 | else if ((card->wandev.state == WAN_CONNECTED && | ||
1962 | card->u.p.ip_mode == WANOPT_PPP_PEER) && | ||
1963 | test_bit(0,&Read_connection_info)){ | ||
1964 | |||
1965 | card->state_tick = jiffies; | ||
1966 | if (read_connection_info (card)){ | ||
1967 | printk(KERN_INFO "%s: Failed to read PEER IP Addresses\n", | ||
1968 | card->devname); | ||
1969 | }else{ | ||
1970 | clear_bit(0,&Read_connection_info); | ||
1971 | set_bit(1,&Read_connection_info); | ||
1972 | trigger_ppp_poll(dev); | ||
1973 | } | ||
1974 | }else{ | ||
1975 | //FIXME Put the comment back int | ||
1976 | ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT; | ||
1977 | } | ||
1978 | |||
1979 | }/* End of PPP_EVENT */ | ||
1980 | |||
1981 | |||
1982 | /* Only disable the timer interrupt if there are no udp, statistic */ | ||
1983 | /* updates or events pending */ | ||
1984 | if(!ppp_priv_area->timer_int_enabled) { | ||
1985 | flags->imask &= ~PPP_INTR_TIMER; | ||
1986 | } | ||
1987 | } | ||
1988 | |||
1989 | |||
1990 | static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto) | ||
1991 | { | ||
1992 | int i; | ||
1993 | |||
1994 | if( proto == htons(ETH_P_IPX) ) { | ||
1995 | //It's an IPX packet | ||
1996 | if(!enable_IPX) { | ||
1997 | //Return 1 so we don't pass it up the stack. | ||
1998 | return 1; | ||
1999 | } | ||
2000 | } else { | ||
2001 | //It's not IPX so pass it up the stack. | ||
2002 | return 0; | ||
2003 | } | ||
2004 | |||
2005 | if( sendpacket[16] == 0x90 && | ||
2006 | sendpacket[17] == 0x04) | ||
2007 | { | ||
2008 | //It's IPXWAN | ||
2009 | |||
2010 | if( sendpacket[2] == 0x02 && | ||
2011 | sendpacket[34] == 0x00) | ||
2012 | { | ||
2013 | //It's a timer request packet | ||
2014 | printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname); | ||
2015 | |||
2016 | //Go through the routing options and answer no to every | ||
2017 | //option except Unnumbered RIP/SAP | ||
2018 | for(i = 41; sendpacket[i] == 0x00; i += 5) | ||
2019 | { | ||
2020 | //0x02 is the option for Unnumbered RIP/SAP | ||
2021 | if( sendpacket[i + 4] != 0x02) | ||
2022 | { | ||
2023 | sendpacket[i + 1] = 0; | ||
2024 | } | ||
2025 | } | ||
2026 | |||
2027 | //Skip over the extended Node ID option | ||
2028 | if( sendpacket[i] == 0x04 ) | ||
2029 | { | ||
2030 | i += 8; | ||
2031 | } | ||
2032 | |||
2033 | //We also want to turn off all header compression opt. | ||
2034 | for(; sendpacket[i] == 0x80 ;) | ||
2035 | { | ||
2036 | sendpacket[i + 1] = 0; | ||
2037 | i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4; | ||
2038 | } | ||
2039 | |||
2040 | //Set the packet type to timer response | ||
2041 | sendpacket[34] = 0x01; | ||
2042 | |||
2043 | printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname); | ||
2044 | } | ||
2045 | else if( sendpacket[34] == 0x02 ) | ||
2046 | { | ||
2047 | //This is an information request packet | ||
2048 | printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname); | ||
2049 | |||
2050 | //Set the packet type to information response | ||
2051 | sendpacket[34] = 0x03; | ||
2052 | |||
2053 | //Set the router name | ||
2054 | sendpacket[51] = 'P'; | ||
2055 | sendpacket[52] = 'T'; | ||
2056 | sendpacket[53] = 'P'; | ||
2057 | sendpacket[54] = 'I'; | ||
2058 | sendpacket[55] = 'P'; | ||
2059 | sendpacket[56] = 'E'; | ||
2060 | sendpacket[57] = '-'; | ||
2061 | sendpacket[58] = CVHexToAscii(network_number >> 28); | ||
2062 | sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24); | ||
2063 | sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20); | ||
2064 | sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16); | ||
2065 | sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12); | ||
2066 | sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8); | ||
2067 | sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4); | ||
2068 | sendpacket[65] = CVHexToAscii(network_number & 0x0000000F); | ||
2069 | for(i = 66; i < 99; i+= 1) | ||
2070 | { | ||
2071 | sendpacket[i] = 0; | ||
2072 | } | ||
2073 | |||
2074 | printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname); | ||
2075 | } | ||
2076 | else | ||
2077 | { | ||
2078 | printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname); | ||
2079 | return 0; | ||
2080 | } | ||
2081 | |||
2082 | //Set the WNodeID to our network address | ||
2083 | sendpacket[35] = (unsigned char)(network_number >> 24); | ||
2084 | sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16); | ||
2085 | sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8); | ||
2086 | sendpacket[38] = (unsigned char)(network_number & 0x000000FF); | ||
2087 | |||
2088 | return 1; | ||
2089 | } else { | ||
2090 | //If we get here it's an IPX-data packet, so it'll get passed up the stack. | ||
2091 | |||
2092 | //switch the network numbers | ||
2093 | switch_net_numbers(sendpacket, network_number, 1); | ||
2094 | return 0; | ||
2095 | } | ||
2096 | } | ||
2097 | |||
2098 | /****** Background Polling Routines ****************************************/ | ||
2099 | |||
2100 | /* All polling functions are invoked by the TIMER interrupt in the wpp_isr | ||
2101 | * routine. | ||
2102 | */ | ||
2103 | |||
2104 | /*============================================================================ | ||
2105 | * Monitor active link phase. | ||
2106 | */ | ||
2107 | static void process_route (sdla_t *card) | ||
2108 | { | ||
2109 | ppp_flags_t *flags = card->flags; | ||
2110 | struct net_device *dev = card->wandev.dev; | ||
2111 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
2112 | |||
2113 | if ((card->u.p.ip_mode == WANOPT_PPP_PEER) && | ||
2114 | (flags->ip_state == 0x09)){ | ||
2115 | |||
2116 | /* We get ip_local from the firmware in PEER mode. | ||
2117 | * Therefore, if ip_local is 0, we failed to obtain | ||
2118 | * the remote IP address. */ | ||
2119 | if (ppp_priv_area->ip_local == 0) | ||
2120 | return; | ||
2121 | |||
2122 | printk(KERN_INFO "%s: IPCP State Opened.\n", card->devname); | ||
2123 | if (read_info( card )) { | ||
2124 | printk(KERN_INFO | ||
2125 | "%s: An error occurred in IP assignment.\n", | ||
2126 | card->devname); | ||
2127 | } else { | ||
2128 | struct in_device *in_dev = dev->ip_ptr; | ||
2129 | if (in_dev != NULL ) { | ||
2130 | struct in_ifaddr *ifa = in_dev->ifa_list; | ||
2131 | |||
2132 | printk(KERN_INFO "%s: Assigned Lcl. Addr: %u.%u.%u.%u\n", | ||
2133 | card->devname, NIPQUAD(ifa->ifa_local)); | ||
2134 | printk(KERN_INFO "%s: Assigned Rmt. Addr: %u.%u.%u.%u\n", | ||
2135 | card->devname, NIPQUAD(ifa->ifa_address)); | ||
2136 | }else{ | ||
2137 | printk(KERN_INFO | ||
2138 | "%s: Error: Failed to add a route for PPP interface %s\n", | ||
2139 | card->devname,dev->name); | ||
2140 | } | ||
2141 | } | ||
2142 | } | ||
2143 | } | ||
2144 | |||
2145 | /*============================================================================ | ||
2146 | * Monitor physical link disconnected phase. | ||
2147 | * o if interface is up and the hold-down timeout has expired, then retry | ||
2148 | * connection. | ||
2149 | */ | ||
2150 | static void retrigger_comm(sdla_t *card) | ||
2151 | { | ||
2152 | struct net_device *dev = card->wandev.dev; | ||
2153 | |||
2154 | if (dev && ((jiffies - card->state_tick) > HOLD_DOWN_TIME)) { | ||
2155 | |||
2156 | wanpipe_set_state(card, WAN_CONNECTING); | ||
2157 | |||
2158 | if(ppp_comm_enable(card) == CMD_OK){ | ||
2159 | init_ppp_tx_rx_buff( card ); | ||
2160 | } | ||
2161 | } | ||
2162 | } | ||
2163 | |||
2164 | /****** Miscellaneous Functions *********************************************/ | ||
2165 | |||
2166 | /*============================================================================ | ||
2167 | * Configure S508 adapter. | ||
2168 | */ | ||
2169 | static int config508(struct net_device *dev, sdla_t *card) | ||
2170 | { | ||
2171 | ppp508_conf_t cfg; | ||
2172 | struct in_device *in_dev = dev->ip_ptr; | ||
2173 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
2174 | |||
2175 | /* Prepare PPP configuration structure */ | ||
2176 | memset(&cfg, 0, sizeof(ppp508_conf_t)); | ||
2177 | |||
2178 | if (card->wandev.clocking) | ||
2179 | cfg.line_speed = card->wandev.bps; | ||
2180 | |||
2181 | if (card->wandev.interface == WANOPT_RS232) | ||
2182 | cfg.conf_flags |= INTERFACE_LEVEL_RS232; | ||
2183 | |||
2184 | |||
2185 | cfg.conf_flags |= DONT_TERMINATE_LNK_MAX_CONFIG; /*send Configure-Request packets forever*/ | ||
2186 | cfg.txbuf_percent = PERCENT_TX_BUFF; /* % of Tx bufs */ | ||
2187 | cfg.mtu_local = card->wandev.mtu; | ||
2188 | cfg.mtu_remote = card->wandev.mtu; /* Default */ | ||
2189 | cfg.restart_tmr = TIME_BETWEEN_CONF_REQ; /* 30 = 3sec */ | ||
2190 | cfg.auth_rsrt_tmr = TIME_BETWEEN_PAP_CHAP_REQ; /* 30 = 3sec */ | ||
2191 | cfg.auth_wait_tmr = WAIT_PAP_CHAP_WITHOUT_REPLY; /* 300 = 30s */ | ||
2192 | cfg.mdm_fail_tmr = WAIT_AFTER_DCD_CTS_LOW; /* 5 = 0.5s */ | ||
2193 | cfg.dtr_drop_tmr = TIME_DCD_CTS_LOW_AFTER_LNK_DOWN; /* 10 = 1s */ | ||
2194 | cfg.connect_tmout = WAIT_DCD_HIGH_AFTER_ENABLE_COMM; /* 900 = 90s */ | ||
2195 | cfg.conf_retry = MAX_CONF_REQ_WITHOUT_REPLY; /* 10 = 1s */ | ||
2196 | cfg.term_retry = MAX_TERM_REQ_WITHOUT_REPLY; /* 2 times */ | ||
2197 | cfg.fail_retry = NUM_CONF_NAK_WITHOUT_REPLY; /* 5 times */ | ||
2198 | cfg.auth_retry = NUM_AUTH_REQ_WITHOUT_REPLY; /* 10 times */ | ||
2199 | |||
2200 | |||
2201 | if( !card->u.p.authenticator ) { | ||
2202 | printk(KERN_INFO "%s: Device is not configured as an authenticator\n", | ||
2203 | card->devname); | ||
2204 | cfg.auth_options = NO_AUTHENTICATION; | ||
2205 | }else{ | ||
2206 | printk(KERN_INFO "%s: Device is configured as an authenticator\n", | ||
2207 | card->devname); | ||
2208 | cfg.auth_options = INBOUND_AUTH; | ||
2209 | } | ||
2210 | |||
2211 | if( ppp_priv_area->pap == WANOPT_YES){ | ||
2212 | cfg.auth_options |=PAP_AUTH; | ||
2213 | printk(KERN_INFO "%s: Pap enabled\n", card->devname); | ||
2214 | } | ||
2215 | if( ppp_priv_area->chap == WANOPT_YES){ | ||
2216 | cfg.auth_options |= CHAP_AUTH; | ||
2217 | printk(KERN_INFO "%s: Chap enabled\n", card->devname); | ||
2218 | } | ||
2219 | |||
2220 | |||
2221 | if (ppp_priv_area->enable_IPX == WANOPT_YES){ | ||
2222 | printk(KERN_INFO "%s: Enabling IPX Protocol\n",card->devname); | ||
2223 | cfg.ipx_options = ENABLE_IPX | ROUTING_PROT_DEFAULT; | ||
2224 | }else{ | ||
2225 | cfg.ipx_options = DISABLE_IPX; | ||
2226 | } | ||
2227 | |||
2228 | switch (card->u.p.ip_mode) { | ||
2229 | |||
2230 | case WANOPT_PPP_STATIC: | ||
2231 | |||
2232 | printk(KERN_INFO "%s: PPP IP Mode: STATIC\n",card->devname); | ||
2233 | cfg.ip_options = L_AND_R_IP_NO_ASSIG | | ||
2234 | ENABLE_IP; | ||
2235 | cfg.ip_local = in_dev->ifa_list->ifa_local; | ||
2236 | cfg.ip_remote = in_dev->ifa_list->ifa_address; | ||
2237 | /* Debugging code used to check that IP addresses | ||
2238 | * obtained from the kernel are correct */ | ||
2239 | |||
2240 | NEX_PRINTK(KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n", | ||
2241 | NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name); | ||
2242 | break; | ||
2243 | |||
2244 | case WANOPT_PPP_HOST: | ||
2245 | |||
2246 | printk(KERN_INFO "%s: PPP IP Mode: HOST\n",card->devname); | ||
2247 | cfg.ip_options = L_IP_LOCAL_ASSIG | | ||
2248 | R_IP_LOCAL_ASSIG | | ||
2249 | ENABLE_IP; | ||
2250 | cfg.ip_local = in_dev->ifa_list->ifa_local; | ||
2251 | cfg.ip_remote = in_dev->ifa_list->ifa_address; | ||
2252 | /* Debugging code used to check that IP addresses | ||
2253 | * obtained from the kernel are correct */ | ||
2254 | NEX_PRINTK (KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n", | ||
2255 | NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name); | ||
2256 | |||
2257 | break; | ||
2258 | |||
2259 | case WANOPT_PPP_PEER: | ||
2260 | |||
2261 | printk(KERN_INFO "%s: PPP IP Mode: PEER\n",card->devname); | ||
2262 | cfg.ip_options = L_IP_REMOTE_ASSIG | | ||
2263 | R_IP_REMOTE_ASSIG | | ||
2264 | ENABLE_IP; | ||
2265 | cfg.ip_local = 0x00; | ||
2266 | cfg.ip_remote = 0x00; | ||
2267 | break; | ||
2268 | |||
2269 | default: | ||
2270 | printk(KERN_INFO "%s: ERROR: Unsupported PPP Mode Selected\n", | ||
2271 | card->devname); | ||
2272 | printk(KERN_INFO "%s: PPP IP Modes: STATIC, PEER or HOST\n", | ||
2273 | card->devname); | ||
2274 | return 1; | ||
2275 | } | ||
2276 | |||
2277 | return ppp_configure(card, &cfg); | ||
2278 | } | ||
2279 | |||
2280 | /*============================================================================ | ||
2281 | * Show disconnection cause. | ||
2282 | */ | ||
2283 | static void show_disc_cause(sdla_t *card, unsigned cause) | ||
2284 | { | ||
2285 | if (cause & 0x0802) | ||
2286 | |||
2287 | printk(KERN_INFO "%s: link terminated by peer\n", | ||
2288 | card->devname); | ||
2289 | |||
2290 | else if (cause & 0x0004) | ||
2291 | |||
2292 | printk(KERN_INFO "%s: link terminated by user\n", | ||
2293 | card->devname); | ||
2294 | |||
2295 | else if (cause & 0x0008) | ||
2296 | |||
2297 | printk(KERN_INFO "%s: authentication failed\n", card->devname); | ||
2298 | |||
2299 | else if (cause & 0x0010) | ||
2300 | |||
2301 | printk(KERN_INFO | ||
2302 | "%s: authentication protocol negotiation failed\n", | ||
2303 | card->devname); | ||
2304 | |||
2305 | else if (cause & 0x0020) | ||
2306 | |||
2307 | printk(KERN_INFO | ||
2308 | "%s: peer's request for authentication rejected\n", | ||
2309 | card->devname); | ||
2310 | |||
2311 | else if (cause & 0x0040) | ||
2312 | |||
2313 | printk(KERN_INFO "%s: MRU option rejected by peer\n", | ||
2314 | card->devname); | ||
2315 | |||
2316 | else if (cause & 0x0080) | ||
2317 | |||
2318 | printk(KERN_INFO "%s: peer's MRU was too small\n", | ||
2319 | card->devname); | ||
2320 | |||
2321 | else if (cause & 0x0100) | ||
2322 | |||
2323 | printk(KERN_INFO "%s: failed to negotiate peer's LCP options\n", | ||
2324 | card->devname); | ||
2325 | |||
2326 | else if (cause & 0x0200) | ||
2327 | |||
2328 | printk(KERN_INFO "%s: failed to negotiate peer's IPCP options\n" | ||
2329 | , card->devname); | ||
2330 | |||
2331 | else if (cause & 0x0400) | ||
2332 | |||
2333 | printk(KERN_INFO | ||
2334 | "%s: failed to negotiate peer's IPXCP options\n", | ||
2335 | card->devname); | ||
2336 | } | ||
2337 | |||
2338 | /*============================================================================= | ||
2339 | * Process UDP call of type PTPIPEAB. | ||
2340 | */ | ||
2341 | static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev, | ||
2342 | ppp_private_area_t *ppp_priv_area ) | ||
2343 | { | ||
2344 | unsigned char buf2[5]; | ||
2345 | unsigned char *buf; | ||
2346 | unsigned int frames, len; | ||
2347 | struct sk_buff *new_skb; | ||
2348 | unsigned short data_length, buffer_length, real_len; | ||
2349 | unsigned long data_ptr; | ||
2350 | int udp_mgmt_req_valid = 1; | ||
2351 | ppp_mbox_t *mbox = card->mbox; | ||
2352 | struct timeval tv; | ||
2353 | int err; | ||
2354 | ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t*)&ppp_priv_area->udp_pkt_data; | ||
2355 | |||
2356 | memcpy(&buf2, &card->wandev.udp_port, 2 ); | ||
2357 | |||
2358 | |||
2359 | if(ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { | ||
2360 | |||
2361 | switch(ppp_udp_pkt->cblock.command) { | ||
2362 | |||
2363 | case PPIPE_GET_IBA_DATA: | ||
2364 | case PPP_READ_CONFIG: | ||
2365 | case PPP_GET_CONNECTION_INFO: | ||
2366 | case PPIPE_ROUTER_UP_TIME: | ||
2367 | case PPP_READ_STATISTICS: | ||
2368 | case PPP_READ_ERROR_STATS: | ||
2369 | case PPP_READ_PACKET_STATS: | ||
2370 | case PPP_READ_LCP_STATS: | ||
2371 | case PPP_READ_IPCP_STATS: | ||
2372 | case PPP_READ_IPXCP_STATS: | ||
2373 | case PPP_READ_PAP_STATS: | ||
2374 | case PPP_READ_CHAP_STATS: | ||
2375 | case PPP_READ_CODE_VERSION: | ||
2376 | udp_mgmt_req_valid = 1; | ||
2377 | break; | ||
2378 | |||
2379 | default: | ||
2380 | udp_mgmt_req_valid = 0; | ||
2381 | break; | ||
2382 | } | ||
2383 | } | ||
2384 | |||
2385 | if(!udp_mgmt_req_valid) { | ||
2386 | |||
2387 | /* set length to 0 */ | ||
2388 | ppp_udp_pkt->cblock.length = 0x00; | ||
2389 | |||
2390 | /* set return code */ | ||
2391 | ppp_udp_pkt->cblock.result = 0xCD; | ||
2392 | ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_direction_err; | ||
2393 | |||
2394 | if (net_ratelimit()){ | ||
2395 | printk(KERN_INFO | ||
2396 | "%s: Warning, Illegal UDP command attempted from network: %x\n", | ||
2397 | card->devname,ppp_udp_pkt->cblock.command); | ||
2398 | } | ||
2399 | } else { | ||
2400 | /* Initialize the trace element */ | ||
2401 | trace_element_t trace_element; | ||
2402 | |||
2403 | switch (ppp_udp_pkt->cblock.command){ | ||
2404 | |||
2405 | /* PPIPE_ENABLE_TRACING */ | ||
2406 | case PPIPE_ENABLE_TRACING: | ||
2407 | if (!card->TracingEnabled) { | ||
2408 | |||
2409 | /* OPERATE_DATALINE_MONITOR */ | ||
2410 | mbox->cmd.command = PPP_DATALINE_MONITOR; | ||
2411 | mbox->cmd.length = 0x01; | ||
2412 | mbox->data[0] = ppp_udp_pkt->data[0]; | ||
2413 | err = sdla_exec(mbox) ? | ||
2414 | mbox->cmd.result : CMD_TIMEOUT; | ||
2415 | |||
2416 | if (err != CMD_OK) { | ||
2417 | |||
2418 | ppp_error(card, err, mbox); | ||
2419 | card->TracingEnabled = 0; | ||
2420 | |||
2421 | /* set the return code */ | ||
2422 | |||
2423 | ppp_udp_pkt->cblock.result = mbox->cmd.result; | ||
2424 | mbox->cmd.length = 0; | ||
2425 | break; | ||
2426 | } | ||
2427 | |||
2428 | sdla_peek(&card->hw, 0xC000, &buf2, 2); | ||
2429 | |||
2430 | ppp_priv_area->curr_trace_addr = 0; | ||
2431 | memcpy(&ppp_priv_area->curr_trace_addr, &buf2, 2); | ||
2432 | ppp_priv_area->start_trace_addr = | ||
2433 | ppp_priv_area->curr_trace_addr; | ||
2434 | ppp_priv_area->end_trace_addr = | ||
2435 | ppp_priv_area->start_trace_addr + END_OFFSET; | ||
2436 | |||
2437 | /* MAX_SEND_BUFFER_SIZE - 28 (IP header) | ||
2438 | - 32 (ppipemon CBLOCK) */ | ||
2439 | available_buffer_space = MAX_LGTH_UDP_MGNT_PKT - | ||
2440 | sizeof(ip_pkt_t)- | ||
2441 | sizeof(udp_pkt_t)- | ||
2442 | sizeof(wp_mgmt_t)- | ||
2443 | sizeof(cblock_t); | ||
2444 | } | ||
2445 | ppp_udp_pkt->cblock.result = 0; | ||
2446 | mbox->cmd.length = 0; | ||
2447 | card->TracingEnabled = 1; | ||
2448 | break; | ||
2449 | |||
2450 | /* PPIPE_DISABLE_TRACING */ | ||
2451 | case PPIPE_DISABLE_TRACING: | ||
2452 | |||
2453 | if(card->TracingEnabled) { | ||
2454 | |||
2455 | /* OPERATE_DATALINE_MONITOR */ | ||
2456 | mbox->cmd.command = 0x33; | ||
2457 | mbox->cmd.length = 1; | ||
2458 | mbox->data[0] = 0x00; | ||
2459 | err = sdla_exec(mbox) ? | ||
2460 | mbox->cmd.result : CMD_TIMEOUT; | ||
2461 | |||
2462 | } | ||
2463 | |||
2464 | /*set return code*/ | ||
2465 | ppp_udp_pkt->cblock.result = 0; | ||
2466 | mbox->cmd.length = 0; | ||
2467 | card->TracingEnabled = 0; | ||
2468 | break; | ||
2469 | |||
2470 | /* PPIPE_GET_TRACE_INFO */ | ||
2471 | case PPIPE_GET_TRACE_INFO: | ||
2472 | |||
2473 | if(!card->TracingEnabled) { | ||
2474 | /* set return code */ | ||
2475 | ppp_udp_pkt->cblock.result = 1; | ||
2476 | mbox->cmd.length = 0; | ||
2477 | } | ||
2478 | |||
2479 | buffer_length = 0; | ||
2480 | |||
2481 | /* frames < 62, where 62 is the number of trace | ||
2482 | information elements. There is in total 496 | ||
2483 | bytes of space and each trace information | ||
2484 | element is 8 bytes. | ||
2485 | */ | ||
2486 | for ( frames=0; frames<62; frames++) { | ||
2487 | |||
2488 | trace_pkt_t *trace_pkt = (trace_pkt_t *) | ||
2489 | &ppp_udp_pkt->data[buffer_length]; | ||
2490 | |||
2491 | /* Read the whole trace packet */ | ||
2492 | sdla_peek(&card->hw, ppp_priv_area->curr_trace_addr, | ||
2493 | &trace_element, sizeof(trace_element_t)); | ||
2494 | |||
2495 | /* no data on board so exit */ | ||
2496 | if( trace_element.opp_flag == 0x00 ) | ||
2497 | break; | ||
2498 | |||
2499 | data_ptr = trace_element.trace_data_ptr; | ||
2500 | |||
2501 | /* See if there is actual data on the trace buffer */ | ||
2502 | if (data_ptr){ | ||
2503 | data_length = trace_element.trace_length; | ||
2504 | }else{ | ||
2505 | data_length = 0; | ||
2506 | ppp_udp_pkt->data[0] |= 0x02; | ||
2507 | } | ||
2508 | |||
2509 | //FIXME: Do we need this check | ||
2510 | if ((available_buffer_space - buffer_length) | ||
2511 | < (sizeof(trace_element_t)+1)){ | ||
2512 | |||
2513 | /*indicate we have more frames | ||
2514 | * on board and exit | ||
2515 | */ | ||
2516 | ppp_udp_pkt->data[0] |= 0x02; | ||
2517 | break; | ||
2518 | } | ||
2519 | |||
2520 | trace_pkt->status = trace_element.trace_type; | ||
2521 | trace_pkt->time_stamp = trace_element.trace_time_stamp; | ||
2522 | trace_pkt->real_length = trace_element.trace_length; | ||
2523 | |||
2524 | real_len = trace_element.trace_length; | ||
2525 | |||
2526 | if(data_ptr == 0){ | ||
2527 | trace_pkt->data_avail = 0x00; | ||
2528 | }else{ | ||
2529 | /* we can take it next time */ | ||
2530 | if ((available_buffer_space - buffer_length)< | ||
2531 | (real_len + sizeof(trace_pkt_t))){ | ||
2532 | |||
2533 | ppp_udp_pkt->data[0] |= 0x02; | ||
2534 | break; | ||
2535 | } | ||
2536 | trace_pkt->data_avail = 0x01; | ||
2537 | |||
2538 | /* get the data */ | ||
2539 | sdla_peek(&card->hw, data_ptr, | ||
2540 | &trace_pkt->data, | ||
2541 | real_len); | ||
2542 | } | ||
2543 | /* zero the opp flag to | ||
2544 | show we got the frame */ | ||
2545 | buf2[0] = 0x00; | ||
2546 | sdla_poke(&card->hw, ppp_priv_area->curr_trace_addr, | ||
2547 | &buf2, 1); | ||
2548 | |||
2549 | /* now move onto the next | ||
2550 | frame */ | ||
2551 | ppp_priv_area->curr_trace_addr += 8; | ||
2552 | |||
2553 | /* check if we passed the last address */ | ||
2554 | if ( ppp_priv_area->curr_trace_addr >= | ||
2555 | ppp_priv_area->end_trace_addr){ | ||
2556 | |||
2557 | ppp_priv_area->curr_trace_addr = | ||
2558 | ppp_priv_area->start_trace_addr; | ||
2559 | } | ||
2560 | |||
2561 | /* update buffer length and make sure its even */ | ||
2562 | |||
2563 | if ( trace_pkt->data_avail == 0x01 ) { | ||
2564 | buffer_length += real_len - 1; | ||
2565 | } | ||
2566 | |||
2567 | /* for the header */ | ||
2568 | buffer_length += 8; | ||
2569 | |||
2570 | if( buffer_length & 0x0001 ) | ||
2571 | buffer_length += 1; | ||
2572 | } | ||
2573 | |||
2574 | /* ok now set the total number of frames passed | ||
2575 | in the high 5 bits */ | ||
2576 | ppp_udp_pkt->data[0] |= (frames << 2); | ||
2577 | |||
2578 | /* set the data length */ | ||
2579 | mbox->cmd.length = buffer_length; | ||
2580 | ppp_udp_pkt->cblock.length = buffer_length; | ||
2581 | |||
2582 | /* set return code */ | ||
2583 | ppp_udp_pkt->cblock.result = 0; | ||
2584 | break; | ||
2585 | |||
2586 | /* PPIPE_GET_IBA_DATA */ | ||
2587 | case PPIPE_GET_IBA_DATA: | ||
2588 | |||
2589 | mbox->cmd.length = 0x09; | ||
2590 | |||
2591 | sdla_peek(&card->hw, 0xF003, &ppp_udp_pkt->data, | ||
2592 | mbox->cmd.length); | ||
2593 | |||
2594 | /* set the length of the data */ | ||
2595 | ppp_udp_pkt->cblock.length = 0x09; | ||
2596 | |||
2597 | /* set return code */ | ||
2598 | ppp_udp_pkt->cblock.result = 0x00; | ||
2599 | ppp_udp_pkt->cblock.result = 0; | ||
2600 | break; | ||
2601 | |||
2602 | /* PPIPE_FT1_READ_STATUS */ | ||
2603 | case PPIPE_FT1_READ_STATUS: | ||
2604 | sdla_peek(&card->hw, 0xF020, &ppp_udp_pkt->data[0], 2); | ||
2605 | ppp_udp_pkt->cblock.length = mbox->cmd.length = 2; | ||
2606 | ppp_udp_pkt->cblock.result = 0; | ||
2607 | break; | ||
2608 | |||
2609 | case PPIPE_FLUSH_DRIVER_STATS: | ||
2610 | init_ppp_priv_struct( ppp_priv_area ); | ||
2611 | init_global_statistics( card ); | ||
2612 | mbox->cmd.length = 0; | ||
2613 | ppp_udp_pkt->cblock.result = 0; | ||
2614 | break; | ||
2615 | |||
2616 | |||
2617 | case PPIPE_ROUTER_UP_TIME: | ||
2618 | |||
2619 | do_gettimeofday( &tv ); | ||
2620 | ppp_priv_area->router_up_time = tv.tv_sec - | ||
2621 | ppp_priv_area->router_start_time; | ||
2622 | *(unsigned long *)&ppp_udp_pkt->data = ppp_priv_area->router_up_time; | ||
2623 | mbox->cmd.length = 4; | ||
2624 | ppp_udp_pkt->cblock.result = 0; | ||
2625 | break; | ||
2626 | |||
2627 | /* PPIPE_DRIVER_STATISTICS */ | ||
2628 | case PPIPE_DRIVER_STAT_IFSEND: | ||
2629 | memcpy(&ppp_udp_pkt->data, &ppp_priv_area->if_send_stat, | ||
2630 | sizeof(if_send_stat_t)); | ||
2631 | |||
2632 | |||
2633 | ppp_udp_pkt->cblock.result = 0; | ||
2634 | ppp_udp_pkt->cblock.length = sizeof(if_send_stat_t); | ||
2635 | mbox->cmd.length = sizeof(if_send_stat_t); | ||
2636 | break; | ||
2637 | |||
2638 | case PPIPE_DRIVER_STAT_INTR: | ||
2639 | memcpy(&ppp_udp_pkt->data, &card->statistics, | ||
2640 | sizeof(global_stats_t)); | ||
2641 | |||
2642 | memcpy(&ppp_udp_pkt->data+sizeof(global_stats_t), | ||
2643 | &ppp_priv_area->rx_intr_stat, | ||
2644 | sizeof(rx_intr_stat_t)); | ||
2645 | |||
2646 | ppp_udp_pkt->cblock.result = 0; | ||
2647 | ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+ | ||
2648 | sizeof(rx_intr_stat_t); | ||
2649 | mbox->cmd.length = ppp_udp_pkt->cblock.length; | ||
2650 | break; | ||
2651 | |||
2652 | case PPIPE_DRIVER_STAT_GEN: | ||
2653 | memcpy( &ppp_udp_pkt->data, | ||
2654 | &ppp_priv_area->pipe_mgmt_stat, | ||
2655 | sizeof(pipe_mgmt_stat_t)); | ||
2656 | |||
2657 | memcpy(&ppp_udp_pkt->data+sizeof(pipe_mgmt_stat_t), | ||
2658 | &card->statistics, sizeof(global_stats_t)); | ||
2659 | |||
2660 | ppp_udp_pkt->cblock.result = 0; | ||
2661 | ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+ | ||
2662 | sizeof(rx_intr_stat_t); | ||
2663 | mbox->cmd.length = ppp_udp_pkt->cblock.length; | ||
2664 | break; | ||
2665 | |||
2666 | |||
2667 | /* FT1 MONITOR STATUS */ | ||
2668 | case FT1_MONITOR_STATUS_CTRL: | ||
2669 | |||
2670 | /* Enable FT1 MONITOR STATUS */ | ||
2671 | if( ppp_udp_pkt->data[0] == 1) { | ||
2672 | |||
2673 | if( rCount++ != 0 ) { | ||
2674 | ppp_udp_pkt->cblock.result = 0; | ||
2675 | mbox->cmd.length = 1; | ||
2676 | break; | ||
2677 | } | ||
2678 | } | ||
2679 | |||
2680 | /* Disable FT1 MONITOR STATUS */ | ||
2681 | if( ppp_udp_pkt->data[0] == 0) { | ||
2682 | |||
2683 | if( --rCount != 0) { | ||
2684 | ppp_udp_pkt->cblock.result = 0; | ||
2685 | mbox->cmd.length = 1; | ||
2686 | break; | ||
2687 | } | ||
2688 | } | ||
2689 | goto udp_dflt_cmd; | ||
2690 | |||
2691 | /* WARNING: FIXME: This should be fixed. | ||
2692 | * The FT1 Status Ctrl doesn't have a break | ||
2693 | * statment. Thus, no code must be inserted | ||
2694 | * HERE: between default and above case statement */ | ||
2695 | |||
2696 | default: | ||
2697 | udp_dflt_cmd: | ||
2698 | |||
2699 | /* it's a board command */ | ||
2700 | mbox->cmd.command = ppp_udp_pkt->cblock.command; | ||
2701 | mbox->cmd.length = ppp_udp_pkt->cblock.length; | ||
2702 | |||
2703 | if(mbox->cmd.length) { | ||
2704 | memcpy(&mbox->data,(unsigned char *)ppp_udp_pkt->data, | ||
2705 | mbox->cmd.length); | ||
2706 | } | ||
2707 | |||
2708 | /* run the command on the board */ | ||
2709 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2710 | |||
2711 | if (err != CMD_OK) { | ||
2712 | |||
2713 | ppp_error(card, err, mbox); | ||
2714 | ++ppp_priv_area->pipe_mgmt_stat. | ||
2715 | UDP_PIPE_mgmt_adptr_cmnd_timeout; | ||
2716 | break; | ||
2717 | } | ||
2718 | |||
2719 | ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_OK; | ||
2720 | |||
2721 | /* copy the result back to our buffer */ | ||
2722 | memcpy(&ppp_udp_pkt->cblock,mbox, sizeof(cblock_t)); | ||
2723 | |||
2724 | if(mbox->cmd.length) { | ||
2725 | memcpy(&ppp_udp_pkt->data,&mbox->data,mbox->cmd.length); | ||
2726 | } | ||
2727 | |||
2728 | } /* end of switch */ | ||
2729 | } /* end of else */ | ||
2730 | |||
2731 | /* Fill UDP TTL */ | ||
2732 | ppp_udp_pkt->ip_pkt.ttl = card->wandev.ttl; | ||
2733 | len = reply_udp(ppp_priv_area->udp_pkt_data, mbox->cmd.length); | ||
2734 | |||
2735 | if (ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { | ||
2736 | |||
2737 | /* Make sure we are not already sending */ | ||
2738 | if (!test_bit(SEND_CRIT,&card->wandev.critical)){ | ||
2739 | ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_adptr; | ||
2740 | ppp_send(card,ppp_priv_area->udp_pkt_data,len,ppp_priv_area->protocol); | ||
2741 | } | ||
2742 | |||
2743 | } else { | ||
2744 | |||
2745 | /* Pass it up the stack | ||
2746 | Allocate socket buffer */ | ||
2747 | if ((new_skb = dev_alloc_skb(len)) != NULL) { | ||
2748 | |||
2749 | /* copy data into new_skb */ | ||
2750 | |||
2751 | buf = skb_put(new_skb, len); | ||
2752 | memcpy(buf,ppp_priv_area->udp_pkt_data, len); | ||
2753 | |||
2754 | ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_stack; | ||
2755 | |||
2756 | /* Decapsulate packet and pass it up the protocol | ||
2757 | stack */ | ||
2758 | new_skb->protocol = htons(ETH_P_IP); | ||
2759 | new_skb->dev = dev; | ||
2760 | new_skb->mac.raw = new_skb->data; | ||
2761 | netif_rx(new_skb); | ||
2762 | dev->last_rx = jiffies; | ||
2763 | |||
2764 | } else { | ||
2765 | |||
2766 | ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_no_socket; | ||
2767 | printk(KERN_INFO "no socket buffers available!\n"); | ||
2768 | } | ||
2769 | } | ||
2770 | |||
2771 | ppp_priv_area->udp_pkt_lgth = 0; | ||
2772 | |||
2773 | return; | ||
2774 | } | ||
2775 | |||
2776 | /*============================================================================= | ||
2777 | * Initial the ppp_private_area structure. | ||
2778 | */ | ||
2779 | static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area ) | ||
2780 | { | ||
2781 | |||
2782 | memset(&ppp_priv_area->if_send_stat, 0, sizeof(if_send_stat_t)); | ||
2783 | memset(&ppp_priv_area->rx_intr_stat, 0, sizeof(rx_intr_stat_t)); | ||
2784 | memset(&ppp_priv_area->pipe_mgmt_stat, 0, sizeof(pipe_mgmt_stat_t)); | ||
2785 | } | ||
2786 | |||
2787 | /*============================================================================ | ||
2788 | * Initialize Global Statistics | ||
2789 | */ | ||
2790 | static void init_global_statistics( sdla_t *card ) | ||
2791 | { | ||
2792 | memset(&card->statistics, 0, sizeof(global_stats_t)); | ||
2793 | } | ||
2794 | |||
2795 | /*============================================================================ | ||
2796 | * Initialize Receive and Transmit Buffers. | ||
2797 | */ | ||
2798 | static void init_ppp_tx_rx_buff( sdla_t *card ) | ||
2799 | { | ||
2800 | ppp508_buf_info_t* info; | ||
2801 | |||
2802 | if (card->hw.type == SDLA_S514) { | ||
2803 | |||
2804 | info = (void*)(card->hw.dpmbase + PPP514_BUF_OFFS); | ||
2805 | |||
2806 | card->u.p.txbuf_base = (void*)(card->hw.dpmbase + | ||
2807 | info->txb_ptr); | ||
2808 | |||
2809 | card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base + | ||
2810 | (info->txb_num - 1); | ||
2811 | |||
2812 | card->u.p.rxbuf_base = (void*)(card->hw.dpmbase + | ||
2813 | info->rxb_ptr); | ||
2814 | |||
2815 | card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base + | ||
2816 | (info->rxb_num - 1); | ||
2817 | |||
2818 | } else { | ||
2819 | |||
2820 | info = (void*)(card->hw.dpmbase + PPP508_BUF_OFFS); | ||
2821 | |||
2822 | card->u.p.txbuf_base = (void*)(card->hw.dpmbase + | ||
2823 | (info->txb_ptr - PPP508_MB_VECT)); | ||
2824 | |||
2825 | card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base + | ||
2826 | (info->txb_num - 1); | ||
2827 | |||
2828 | card->u.p.rxbuf_base = (void*)(card->hw.dpmbase + | ||
2829 | (info->rxb_ptr - PPP508_MB_VECT)); | ||
2830 | |||
2831 | card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base + | ||
2832 | (info->rxb_num - 1); | ||
2833 | } | ||
2834 | |||
2835 | card->u.p.txbuf_next = (unsigned long*)&info->txb_nxt; | ||
2836 | card->u.p.rxbuf_next = (unsigned long*)&info->rxb1_ptr; | ||
2837 | |||
2838 | card->u.p.rx_base = info->rxb_base; | ||
2839 | card->u.p.rx_top = info->rxb_end; | ||
2840 | |||
2841 | card->u.p.txbuf = card->u.p.txbuf_base; | ||
2842 | card->rxmb = card->u.p.rxbuf_base; | ||
2843 | |||
2844 | } | ||
2845 | |||
2846 | /*============================================================================= | ||
2847 | * Read Connection Information (ie for Remote IP address assginment). | ||
2848 | * Called when ppp interface connected. | ||
2849 | */ | ||
2850 | static int read_info( sdla_t *card ) | ||
2851 | { | ||
2852 | struct net_device *dev = card->wandev.dev; | ||
2853 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
2854 | int err; | ||
2855 | |||
2856 | struct ifreq if_info; | ||
2857 | struct sockaddr_in *if_data1, *if_data2; | ||
2858 | mm_segment_t fs; | ||
2859 | |||
2860 | /* Set Local and remote addresses */ | ||
2861 | memset(&if_info, 0, sizeof(if_info)); | ||
2862 | strcpy(if_info.ifr_name, dev->name); | ||
2863 | |||
2864 | |||
2865 | fs = get_fs(); | ||
2866 | set_fs(get_ds()); /* get user space block */ | ||
2867 | |||
2868 | /* Change the local and remote ip address of the interface. | ||
2869 | * This will also add in the destination route. | ||
2870 | */ | ||
2871 | if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; | ||
2872 | if_data1->sin_addr.s_addr = ppp_priv_area->ip_local; | ||
2873 | if_data1->sin_family = AF_INET; | ||
2874 | err = devinet_ioctl( SIOCSIFADDR, &if_info ); | ||
2875 | if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; | ||
2876 | if_data2->sin_addr.s_addr = ppp_priv_area->ip_remote; | ||
2877 | if_data2->sin_family = AF_INET; | ||
2878 | err = devinet_ioctl( SIOCSIFDSTADDR, &if_info ); | ||
2879 | |||
2880 | set_fs(fs); /* restore old block */ | ||
2881 | |||
2882 | if (err) { | ||
2883 | printk (KERN_INFO "%s: Adding of route failed: %i\n", | ||
2884 | card->devname,err); | ||
2885 | printk (KERN_INFO "%s: Local : %u.%u.%u.%u\n", | ||
2886 | card->devname,NIPQUAD(ppp_priv_area->ip_local)); | ||
2887 | printk (KERN_INFO "%s: Remote: %u.%u.%u.%u\n", | ||
2888 | card->devname,NIPQUAD(ppp_priv_area->ip_remote)); | ||
2889 | } | ||
2890 | return err; | ||
2891 | } | ||
2892 | |||
2893 | /*============================================================================= | ||
2894 | * Remove Dynamic Route. | ||
2895 | * Called when ppp interface disconnected. | ||
2896 | */ | ||
2897 | |||
2898 | static void remove_route( sdla_t *card ) | ||
2899 | { | ||
2900 | |||
2901 | struct net_device *dev = card->wandev.dev; | ||
2902 | long ip_addr; | ||
2903 | int err; | ||
2904 | |||
2905 | mm_segment_t fs; | ||
2906 | struct ifreq if_info; | ||
2907 | struct sockaddr_in *if_data1; | ||
2908 | struct in_device *in_dev = dev->ip_ptr; | ||
2909 | struct in_ifaddr *ifa = in_dev->ifa_list; | ||
2910 | |||
2911 | ip_addr = ifa->ifa_local; | ||
2912 | |||
2913 | /* Set Local and remote addresses */ | ||
2914 | memset(&if_info, 0, sizeof(if_info)); | ||
2915 | strcpy(if_info.ifr_name, dev->name); | ||
2916 | |||
2917 | fs = get_fs(); | ||
2918 | set_fs(get_ds()); /* get user space block */ | ||
2919 | |||
2920 | /* Change the local ip address of the interface to 0. | ||
2921 | * This will also delete the destination route. | ||
2922 | */ | ||
2923 | if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; | ||
2924 | if_data1->sin_addr.s_addr = 0; | ||
2925 | if_data1->sin_family = AF_INET; | ||
2926 | err = devinet_ioctl( SIOCSIFADDR, &if_info ); | ||
2927 | |||
2928 | set_fs(fs); /* restore old block */ | ||
2929 | |||
2930 | |||
2931 | if (err) { | ||
2932 | printk (KERN_INFO "%s: Deleting dynamic route failed %d!\n", | ||
2933 | card->devname, err); | ||
2934 | return; | ||
2935 | }else{ | ||
2936 | printk (KERN_INFO "%s: PPP Deleting dynamic route %u.%u.%u.%u successfuly\n", | ||
2937 | card->devname, NIPQUAD(ip_addr)); | ||
2938 | } | ||
2939 | return; | ||
2940 | } | ||
2941 | |||
2942 | /*============================================================================= | ||
2943 | * Perform the Interrupt Test by running the READ_CODE_VERSION command MAX_INTR | ||
2944 | * _TEST_COUNTER times. | ||
2945 | */ | ||
2946 | static int intr_test( sdla_t *card ) | ||
2947 | { | ||
2948 | ppp_mbox_t *mb = card->mbox; | ||
2949 | int err,i; | ||
2950 | |||
2951 | err = ppp_set_intr_mode( card, 0x08 ); | ||
2952 | |||
2953 | if (err == CMD_OK) { | ||
2954 | |||
2955 | for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) { | ||
2956 | /* Run command READ_CODE_VERSION */ | ||
2957 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
2958 | mb->cmd.length = 0; | ||
2959 | mb->cmd.command = PPP_READ_CODE_VERSION; | ||
2960 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
2961 | if (err != CMD_OK) | ||
2962 | ppp_error(card, err, mb); | ||
2963 | } | ||
2964 | } | ||
2965 | else return err; | ||
2966 | |||
2967 | err = ppp_set_intr_mode( card, 0 ); | ||
2968 | if (err != CMD_OK) | ||
2969 | return err; | ||
2970 | |||
2971 | return 0; | ||
2972 | } | ||
2973 | |||
2974 | /*============================================================================== | ||
2975 | * Determine what type of UDP call it is. DRVSTATS or PTPIPEAB ? | ||
2976 | */ | ||
2977 | static int udp_pkt_type( struct sk_buff *skb, sdla_t *card ) | ||
2978 | { | ||
2979 | unsigned char *sendpacket; | ||
2980 | unsigned char buf2[5]; | ||
2981 | ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t *)skb->data; | ||
2982 | |||
2983 | sendpacket = skb->data; | ||
2984 | memcpy(&buf2, &card->wandev.udp_port, 2); | ||
2985 | |||
2986 | if( ppp_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45 && /* IP packet */ | ||
2987 | sendpacket[9] == 0x11 && /* UDP packet */ | ||
2988 | sendpacket[22] == buf2[1] && /* UDP Port */ | ||
2989 | sendpacket[23] == buf2[0] && | ||
2990 | sendpacket[36] == 0x01 ) { | ||
2991 | |||
2992 | if ( sendpacket[28] == 0x50 && /* PTPIPEAB: Signature */ | ||
2993 | sendpacket[29] == 0x54 && | ||
2994 | sendpacket[30] == 0x50 && | ||
2995 | sendpacket[31] == 0x49 && | ||
2996 | sendpacket[32] == 0x50 && | ||
2997 | sendpacket[33] == 0x45 && | ||
2998 | sendpacket[34] == 0x41 && | ||
2999 | sendpacket[35] == 0x42 ){ | ||
3000 | |||
3001 | return UDP_PTPIPE_TYPE; | ||
3002 | |||
3003 | } else if(sendpacket[28] == 0x44 && /* DRVSTATS: Signature */ | ||
3004 | sendpacket[29] == 0x52 && | ||
3005 | sendpacket[30] == 0x56 && | ||
3006 | sendpacket[31] == 0x53 && | ||
3007 | sendpacket[32] == 0x54 && | ||
3008 | sendpacket[33] == 0x41 && | ||
3009 | sendpacket[34] == 0x54 && | ||
3010 | sendpacket[35] == 0x53 ){ | ||
3011 | |||
3012 | return UDP_DRVSTATS_TYPE; | ||
3013 | |||
3014 | } else | ||
3015 | return UDP_INVALID_TYPE; | ||
3016 | |||
3017 | } else | ||
3018 | return UDP_INVALID_TYPE; | ||
3019 | |||
3020 | } | ||
3021 | |||
3022 | /*============================================================================ | ||
3023 | * Check to see if the packet to be transmitted contains a broadcast or | ||
3024 | * multicast source IP address. | ||
3025 | */ | ||
3026 | |||
3027 | static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev, | ||
3028 | struct sk_buff *skb) | ||
3029 | { | ||
3030 | u32 src_ip_addr; | ||
3031 | u32 broadcast_ip_addr = 0; | ||
3032 | struct in_device *in_dev; | ||
3033 | |||
3034 | /* read the IP source address from the outgoing packet */ | ||
3035 | src_ip_addr = *(u32 *)(skb->data + 12); | ||
3036 | |||
3037 | /* read the IP broadcast address for the device */ | ||
3038 | in_dev = dev->ip_ptr; | ||
3039 | if(in_dev != NULL) { | ||
3040 | struct in_ifaddr *ifa= in_dev->ifa_list; | ||
3041 | if(ifa != NULL) | ||
3042 | broadcast_ip_addr = ifa->ifa_broadcast; | ||
3043 | else | ||
3044 | return 0; | ||
3045 | } | ||
3046 | |||
3047 | /* check if the IP Source Address is a Broadcast address */ | ||
3048 | if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { | ||
3049 | printk(KERN_INFO "%s: Broadcast Source Address silently discarded\n", | ||
3050 | card->devname); | ||
3051 | return 1; | ||
3052 | } | ||
3053 | |||
3054 | /* check if the IP Source Address is a Multicast address */ | ||
3055 | if((ntohl(src_ip_addr) >= 0xE0000001) && | ||
3056 | (ntohl(src_ip_addr) <= 0xFFFFFFFE)) { | ||
3057 | printk(KERN_INFO "%s: Multicast Source Address silently discarded\n", | ||
3058 | card->devname); | ||
3059 | return 1; | ||
3060 | } | ||
3061 | |||
3062 | return 0; | ||
3063 | } | ||
3064 | |||
3065 | void s508_lock (sdla_t *card, unsigned long *smp_flags) | ||
3066 | { | ||
3067 | spin_lock_irqsave(&card->wandev.lock, *smp_flags); | ||
3068 | } | ||
3069 | |||
3070 | void s508_unlock (sdla_t *card, unsigned long *smp_flags) | ||
3071 | { | ||
3072 | spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); | ||
3073 | } | ||
3074 | |||
3075 | static int read_connection_info (sdla_t *card) | ||
3076 | { | ||
3077 | ppp_mbox_t *mb = card->mbox; | ||
3078 | struct net_device *dev = card->wandev.dev; | ||
3079 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
3080 | ppp508_connect_info_t *ppp508_connect_info; | ||
3081 | int err; | ||
3082 | |||
3083 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
3084 | mb->cmd.length = 0; | ||
3085 | mb->cmd.command = PPP_GET_CONNECTION_INFO; | ||
3086 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
3087 | |||
3088 | if (err != CMD_OK) { | ||
3089 | ppp_error(card, err, mb); | ||
3090 | ppp_priv_area->ip_remote = 0; | ||
3091 | ppp_priv_area->ip_local = 0; | ||
3092 | } | ||
3093 | else { | ||
3094 | ppp508_connect_info = (ppp508_connect_info_t *)mb->data; | ||
3095 | ppp_priv_area->ip_remote = ppp508_connect_info->ip_remote; | ||
3096 | ppp_priv_area->ip_local = ppp508_connect_info->ip_local; | ||
3097 | |||
3098 | NEX_PRINTK(KERN_INFO "READ CONNECTION GOT IP ADDRESS %x, %x\n", | ||
3099 | ppp_priv_area->ip_remote, | ||
3100 | ppp_priv_area->ip_local); | ||
3101 | } | ||
3102 | |||
3103 | return err; | ||
3104 | } | ||
3105 | |||
3106 | /*=============================================================================== | ||
3107 | * config_ppp | ||
3108 | * | ||
3109 | * Configure the ppp protocol and enable communications. | ||
3110 | * | ||
3111 | * The if_open function binds this function to the poll routine. | ||
3112 | * Therefore, this function will run every time the ppp interface | ||
3113 | * is brought up. | ||
3114 | * | ||
3115 | * If the communications are not enabled, proceed to configure | ||
3116 | * the card and enable communications. | ||
3117 | * | ||
3118 | * If the communications are enabled, it means that the interface | ||
3119 | * was shutdown by ether the user or driver. In this case, we | ||
3120 | * have to check that the IP addresses have not changed. If | ||
3121 | * the IP addresses changed, we have to reconfigure the firmware | ||
3122 | * and update the changed IP addresses. Otherwise, just exit. | ||
3123 | */ | ||
3124 | static int config_ppp (sdla_t *card) | ||
3125 | { | ||
3126 | |||
3127 | struct net_device *dev = card->wandev.dev; | ||
3128 | ppp_flags_t *flags = card->flags; | ||
3129 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
3130 | |||
3131 | if (card->u.p.comm_enabled){ | ||
3132 | |||
3133 | if (ppp_priv_area->ip_local_tmp != ppp_priv_area->ip_local || | ||
3134 | ppp_priv_area->ip_remote_tmp != ppp_priv_area->ip_remote){ | ||
3135 | |||
3136 | /* The IP addersses have changed, we must | ||
3137 | * stop the communications and reconfigure | ||
3138 | * the card. Reason: the firmware must know | ||
3139 | * the local and remote IP addresses. */ | ||
3140 | disable_comm(card); | ||
3141 | wanpipe_set_state(card, WAN_DISCONNECTED); | ||
3142 | printk(KERN_INFO | ||
3143 | "%s: IP addresses changed!\n", | ||
3144 | card->devname); | ||
3145 | printk(KERN_INFO "%s: Restarting communications ...\n", | ||
3146 | card->devname); | ||
3147 | }else{ | ||
3148 | /* IP addresses are the same and the link is up, | ||
3149 | * we don't have to do anything here. Therefore, exit */ | ||
3150 | return 0; | ||
3151 | } | ||
3152 | } | ||
3153 | |||
3154 | /* Record the new IP addreses */ | ||
3155 | ppp_priv_area->ip_local = ppp_priv_area->ip_local_tmp; | ||
3156 | ppp_priv_area->ip_remote = ppp_priv_area->ip_remote_tmp; | ||
3157 | |||
3158 | if (config508(dev, card)){ | ||
3159 | printk(KERN_INFO "%s: Failed to configure PPP device\n", | ||
3160 | card->devname); | ||
3161 | return 0; | ||
3162 | } | ||
3163 | |||
3164 | if (ppp_set_intr_mode(card, PPP_INTR_RXRDY| | ||
3165 | PPP_INTR_TXRDY| | ||
3166 | PPP_INTR_MODEM| | ||
3167 | PPP_INTR_DISC | | ||
3168 | PPP_INTR_OPEN | | ||
3169 | PPP_INTR_DROP_DTR | | ||
3170 | PPP_INTR_TIMER)) { | ||
3171 | |||
3172 | printk(KERN_INFO "%s: Failed to configure board interrupts !\n", | ||
3173 | card->devname); | ||
3174 | return 0; | ||
3175 | } | ||
3176 | |||
3177 | /* Turn off the transmit and timer interrupt */ | ||
3178 | flags->imask &= ~(PPP_INTR_TXRDY | PPP_INTR_TIMER) ; | ||
3179 | |||
3180 | |||
3181 | /* If you are not the authenticator and any one of the protocol is | ||
3182 | * enabled then we call the set_out_bound_authentication. | ||
3183 | */ | ||
3184 | if ( !card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)) { | ||
3185 | if ( ppp_set_outbnd_auth(card, ppp_priv_area) ){ | ||
3186 | printk(KERN_INFO "%s: Outbound authentication failed !\n", | ||
3187 | card->devname); | ||
3188 | return 0; | ||
3189 | } | ||
3190 | } | ||
3191 | |||
3192 | /* If you are the authenticator and any one of the protocol is enabled | ||
3193 | * then we call the set_in_bound_authentication. | ||
3194 | */ | ||
3195 | if (card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)){ | ||
3196 | if (ppp_set_inbnd_auth(card, ppp_priv_area)){ | ||
3197 | printk(KERN_INFO "%s: Inbound authentication failed !\n", | ||
3198 | card->devname); | ||
3199 | return 0; | ||
3200 | } | ||
3201 | } | ||
3202 | |||
3203 | /* If we fail to enable communications here it's OK, | ||
3204 | * since the DTR timer will cause a disconnected, which | ||
3205 | * will retrigger communication in timer_intr() */ | ||
3206 | if (ppp_comm_enable(card) == CMD_OK) { | ||
3207 | wanpipe_set_state(card, WAN_CONNECTING); | ||
3208 | init_ppp_tx_rx_buff(card); | ||
3209 | } | ||
3210 | |||
3211 | return 0; | ||
3212 | } | ||
3213 | |||
3214 | /*============================================================ | ||
3215 | * ppp_poll | ||
3216 | * | ||
3217 | * Rationale: | ||
3218 | * We cannot manipulate the routing tables, or | ||
3219 | * ip addresses withing the interrupt. Therefore | ||
3220 | * we must perform such actons outside an interrupt | ||
3221 | * at a later time. | ||
3222 | * | ||
3223 | * Description: | ||
3224 | * PPP polling routine, responsible for | ||
3225 | * shutting down interfaces upon disconnect | ||
3226 | * and adding/removing routes. | ||
3227 | * | ||
3228 | * Usage: | ||
3229 | * This function is executed for each ppp | ||
3230 | * interface through a tq_schedule bottom half. | ||
3231 | * | ||
3232 | * trigger_ppp_poll() function is used to kick | ||
3233 | * the ppp_poll routine. | ||
3234 | */ | ||
3235 | static void ppp_poll(struct net_device *dev) | ||
3236 | { | ||
3237 | ppp_private_area_t *ppp_priv_area; | ||
3238 | sdla_t *card; | ||
3239 | u8 check_gateway=0; | ||
3240 | ppp_flags_t *flags; | ||
3241 | |||
3242 | if (!dev || (ppp_priv_area = dev->priv) == NULL) | ||
3243 | return; | ||
3244 | |||
3245 | card = ppp_priv_area->card; | ||
3246 | flags = card->flags; | ||
3247 | |||
3248 | /* Shutdown is in progress, stop what you are | ||
3249 | * doing and get out */ | ||
3250 | if (test_bit(PERI_CRIT,&card->wandev.critical)){ | ||
3251 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3252 | return; | ||
3253 | } | ||
3254 | |||
3255 | /* if_open() function has triggered the polling routine | ||
3256 | * to determine the configured IP addresses. Once the | ||
3257 | * addresses are found, trigger the chdlc configuration */ | ||
3258 | if (test_bit(0,&ppp_priv_area->config_ppp)){ | ||
3259 | |||
3260 | ppp_priv_area->ip_local_tmp = get_ip_address(dev,WAN_LOCAL_IP); | ||
3261 | ppp_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP); | ||
3262 | |||
3263 | if (ppp_priv_area->ip_local_tmp == ppp_priv_area->ip_remote_tmp && | ||
3264 | card->u.p.ip_mode == WANOPT_PPP_HOST){ | ||
3265 | |||
3266 | if (++ppp_priv_area->ip_error > MAX_IP_ERRORS){ | ||
3267 | printk(KERN_INFO "\n%s: --- WARNING ---\n", | ||
3268 | card->devname); | ||
3269 | printk(KERN_INFO "%s: The local IP address is the same as the\n", | ||
3270 | card->devname); | ||
3271 | printk(KERN_INFO "%s: Point-to-Point IP address.\n", | ||
3272 | card->devname); | ||
3273 | printk(KERN_INFO "%s: --- WARNING ---\n\n", | ||
3274 | card->devname); | ||
3275 | }else{ | ||
3276 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3277 | ppp_priv_area->poll_delay_timer.expires = jiffies+HZ; | ||
3278 | add_timer(&ppp_priv_area->poll_delay_timer); | ||
3279 | return; | ||
3280 | } | ||
3281 | } | ||
3282 | |||
3283 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG; | ||
3284 | flags->imask |= PPP_INTR_TIMER; | ||
3285 | ppp_priv_area->ip_error=0; | ||
3286 | |||
3287 | clear_bit(0,&ppp_priv_area->config_ppp); | ||
3288 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3289 | return; | ||
3290 | } | ||
3291 | |||
3292 | /* Dynamic interface implementation, as well as dynamic | ||
3293 | * routing. */ | ||
3294 | |||
3295 | switch (card->wandev.state) { | ||
3296 | |||
3297 | case WAN_DISCONNECTED: | ||
3298 | |||
3299 | /* If the dynamic interface configuration is on, and interface | ||
3300 | * is up, then bring down the netowrk interface */ | ||
3301 | |||
3302 | if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) && | ||
3303 | !test_bit(DEV_DOWN,&ppp_priv_area->interface_down) && | ||
3304 | card->wandev.dev->flags & IFF_UP){ | ||
3305 | |||
3306 | printk(KERN_INFO "%s: Interface %s down.\n", | ||
3307 | card->devname,card->wandev.dev->name); | ||
3308 | change_dev_flags(card->wandev.dev, | ||
3309 | (card->wandev.dev->flags&~IFF_UP)); | ||
3310 | set_bit(DEV_DOWN,&ppp_priv_area->interface_down); | ||
3311 | }else{ | ||
3312 | /* We need to check if the local IP address is | ||
3313 | * zero. If it is, we shouldn't try to remove it. | ||
3314 | * For some reason the kernel crashes badly if | ||
3315 | * we try to remove the route twice */ | ||
3316 | |||
3317 | if (card->wandev.dev->flags & IFF_UP && | ||
3318 | get_ip_address(card->wandev.dev,WAN_LOCAL_IP) && | ||
3319 | card->u.p.ip_mode == WANOPT_PPP_PEER){ | ||
3320 | |||
3321 | remove_route(card); | ||
3322 | } | ||
3323 | } | ||
3324 | break; | ||
3325 | |||
3326 | case WAN_CONNECTED: | ||
3327 | |||
3328 | /* In SMP machine this code can execute before the interface | ||
3329 | * comes up. In this case, we must make sure that we do not | ||
3330 | * try to bring up the interface before dev_open() is finished */ | ||
3331 | |||
3332 | |||
3333 | /* DEV_DOWN will be set only when we bring down the interface | ||
3334 | * for the very first time. This way we know that it was us | ||
3335 | * that brought the interface down */ | ||
3336 | |||
3337 | if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) && | ||
3338 | test_bit(DEV_DOWN, &ppp_priv_area->interface_down) && | ||
3339 | !(card->wandev.dev->flags & IFF_UP)){ | ||
3340 | |||
3341 | printk(KERN_INFO "%s: Interface %s up.\n", | ||
3342 | card->devname,card->wandev.dev->name); | ||
3343 | |||
3344 | change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP)); | ||
3345 | clear_bit(DEV_DOWN,&ppp_priv_area->interface_down); | ||
3346 | check_gateway=1; | ||
3347 | } | ||
3348 | |||
3349 | if ((card->u.p.ip_mode == WANOPT_PPP_PEER) && | ||
3350 | test_bit(1,&Read_connection_info)) { | ||
3351 | |||
3352 | process_route(card); | ||
3353 | clear_bit(1,&Read_connection_info); | ||
3354 | check_gateway=1; | ||
3355 | } | ||
3356 | |||
3357 | if (ppp_priv_area->gateway && check_gateway) | ||
3358 | add_gateway(card,dev); | ||
3359 | |||
3360 | break; | ||
3361 | } | ||
3362 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3363 | return; | ||
3364 | } | ||
3365 | |||
3366 | /*============================================================ | ||
3367 | * trigger_ppp_poll | ||
3368 | * | ||
3369 | * Description: | ||
3370 | * Add a ppp_poll() task into a tq_scheduler bh handler | ||
3371 | * for a specific interface. This will kick | ||
3372 | * the ppp_poll() routine at a later time. | ||
3373 | * | ||
3374 | * Usage: | ||
3375 | * Interrupts use this to defer a taks to | ||
3376 | * a polling routine. | ||
3377 | * | ||
3378 | */ | ||
3379 | |||
3380 | static void trigger_ppp_poll(struct net_device *dev) | ||
3381 | { | ||
3382 | ppp_private_area_t *ppp_priv_area; | ||
3383 | if ((ppp_priv_area=dev->priv) != NULL){ | ||
3384 | |||
3385 | sdla_t *card = ppp_priv_area->card; | ||
3386 | |||
3387 | if (test_bit(PERI_CRIT,&card->wandev.critical)){ | ||
3388 | return; | ||
3389 | } | ||
3390 | |||
3391 | if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){ | ||
3392 | return; | ||
3393 | } | ||
3394 | |||
3395 | schedule_work(&ppp_priv_area->poll_work); | ||
3396 | } | ||
3397 | return; | ||
3398 | } | ||
3399 | |||
3400 | static void ppp_poll_delay (unsigned long dev_ptr) | ||
3401 | { | ||
3402 | struct net_device *dev = (struct net_device *)dev_ptr; | ||
3403 | trigger_ppp_poll(dev); | ||
3404 | } | ||
3405 | |||
3406 | /*============================================================ | ||
3407 | * detect_and_fix_tx_bug | ||
3408 | * | ||
3409 | * Description: | ||
3410 | * On connect, if the board tx buffer ptr is not the same | ||
3411 | * as the driver tx buffer ptr, we found a firmware bug. | ||
3412 | * Report the bug to the above layer. To fix the | ||
3413 | * error restart communications again. | ||
3414 | * | ||
3415 | * Usage: | ||
3416 | * | ||
3417 | */ | ||
3418 | |||
3419 | static int detect_and_fix_tx_bug (sdla_t *card) | ||
3420 | { | ||
3421 | if (((unsigned long)card->u.p.txbuf_base&0xFFF) != ((*card->u.p.txbuf_next)&0xFFF)){ | ||
3422 | NEX_PRINTK(KERN_INFO "Major Error, Fix the bug\n"); | ||
3423 | return 1; | ||
3424 | } | ||
3425 | return 0; | ||
3426 | } | ||
3427 | |||
3428 | MODULE_LICENSE("GPL"); | ||
3429 | |||
3430 | /****** End *****************************************************************/ | ||
diff --git a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c deleted file mode 100644 index 63f846d6f3a6..000000000000 --- a/drivers/net/wan/sdla_x25.c +++ /dev/null | |||
@@ -1,5497 +0,0 @@ | |||
1 | /***************************************************************************** | ||
2 | * sdla_x25.c WANPIPE(tm) Multiprotocol WAN Link Driver. X.25 module. | ||
3 | * | ||
4 | * Author: Nenad Corbic <ncorbic@sangoma.com> | ||
5 | * | ||
6 | * Copyright: (c) 1995-2001 Sangoma Technologies Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * ============================================================================ | ||
13 | * Apr 03, 2001 Nenad Corbic o Fixed the rx_skb=NULL bug in x25 in rx_intr(). | ||
14 | * Dec 26, 2000 Nenad Corbic o Added a new polling routine, that uses | ||
15 | * a kernel timer (more efficient). | ||
16 | * Dec 25, 2000 Nenad Corbic o Updated for 2.4.X kernel | ||
17 | * Jul 26, 2000 Nenad Corbic o Increased the local packet buffering | ||
18 | * for API to 4096+header_size. | ||
19 | * Jul 17, 2000 Nenad Corbic o Fixed the x25 startup bug. Enable | ||
20 | * communications only after all interfaces | ||
21 | * come up. HIGH SVC/PVC is used to calculate | ||
22 | * the number of channels. | ||
23 | * Enable protocol only after all interfaces | ||
24 | * are enabled. | ||
25 | * Jul 10, 2000 Nenad Corbic o Fixed the M_BIT bug. | ||
26 | * Apr 25, 2000 Nenad Corbic o Pass Modem messages to the API. | ||
27 | * Disable idle timeout in X25 API. | ||
28 | * Apr 14, 2000 Nenad Corbic o Fixed: Large LCN number support. | ||
29 | * Maximum LCN number is 4095. | ||
30 | * Maximum number of X25 channels is 255. | ||
31 | * Apr 06, 2000 Nenad Corbic o Added SMP Support. | ||
32 | * Mar 29, 2000 Nenad Corbic o Added support for S514 PCI Card | ||
33 | * Mar 23, 2000 Nenad Corbic o Improved task queue, BH handling. | ||
34 | * Mar 14, 2000 Nenad Corbic o Updated Protocol Violation handling | ||
35 | * routines. Bug Fix. | ||
36 | * Mar 10, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery. | ||
37 | * Mar 09, 2000 Nenad Corbic o Fixed the auto HDLC bug. | ||
38 | * Mar 08, 2000 Nenad Corbic o Fixed LAPB HDLC startup problems. | ||
39 | * Application must bring the link up | ||
40 | * before tx/rx, and bring the | ||
41 | * link down on close(). | ||
42 | * Mar 06, 2000 Nenad Corbic o Added an option for logging call setup | ||
43 | * information. | ||
44 | * Feb 29, 2000 Nenad Corbic o Added support for LAPB HDLC API | ||
45 | * Feb 25, 2000 Nenad Corbic o Fixed the modem failure handling. | ||
46 | * No Modem OOB message will be passed | ||
47 | * to the user. | ||
48 | * Feb 21, 2000 Nenad Corbic o Added Xpipemon Debug Support | ||
49 | * Dec 30, 1999 Nenad Corbic o Socket based X25API | ||
50 | * Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X kernel | ||
51 | * Mar 15, 1998 Alan Cox o 2.1.x porting | ||
52 | * Dec 19, 1997 Jaspreet Singh o Added multi-channel IPX support | ||
53 | * Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs | ||
54 | * when they are disabled. | ||
55 | * Nov 17, 1997 Farhan Thawar o Added IPX support | ||
56 | * o Changed if_send() to now buffer packets when | ||
57 | * the board is busy | ||
58 | * o Removed queueing of packets via the polling | ||
59 | * routing | ||
60 | * o Changed if_send() critical flags to properly | ||
61 | * handle race conditions | ||
62 | * Nov 06, 1997 Farhan Thawar o Added support for SVC timeouts | ||
63 | * o Changed PVC encapsulation to ETH_P_IP | ||
64 | * Jul 21, 1997 Jaspreet Singh o Fixed freeing up of buffers using kfree() | ||
65 | * when packets are received. | ||
66 | * Mar 11, 1997 Farhan Thawar Version 3.1.1 | ||
67 | * o added support for V35 | ||
68 | * o changed if_send() to return 0 if | ||
69 | * wandev.critical() is true | ||
70 | * o free socket buffer in if_send() if | ||
71 | * returning 0 | ||
72 | * o added support for single '@' address to | ||
73 | * accept all incoming calls | ||
74 | * o fixed bug in set_chan_state() to disconnect | ||
75 | * Jan 15, 1997 Gene Kozin Version 3.1.0 | ||
76 | * o implemented exec() entry point | ||
77 | * Jan 07, 1997 Gene Kozin Initial version. | ||
78 | *****************************************************************************/ | ||
79 | |||
80 | /*====================================================== | ||
81 | * Includes | ||
82 | *=====================================================*/ | ||
83 | |||
84 | #include <linux/module.h> | ||
85 | #include <linux/kernel.h> /* printk(), and other useful stuff */ | ||
86 | #include <linux/stddef.h> /* offsetof(), etc. */ | ||
87 | #include <linux/errno.h> /* return codes */ | ||
88 | #include <linux/string.h> /* inline memset(), etc. */ | ||
89 | #include <linux/ctype.h> | ||
90 | #include <linux/slab.h> /* kmalloc(), kfree() */ | ||
91 | #include <linux/wanrouter.h> /* WAN router definitions */ | ||
92 | #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ | ||
93 | #include <linux/workqueue.h> | ||
94 | #include <linux/jiffies.h> /* time_after() macro */ | ||
95 | #include <asm/byteorder.h> /* htons(), etc. */ | ||
96 | #include <asm/atomic.h> | ||
97 | #include <linux/delay.h> /* Experimental delay */ | ||
98 | |||
99 | #include <asm/uaccess.h> | ||
100 | |||
101 | #include <linux/if.h> | ||
102 | #include <linux/if_arp.h> | ||
103 | #include <linux/sdla_x25.h> /* X.25 firmware API definitions */ | ||
104 | #include <linux/if_wanpipe_common.h> | ||
105 | #include <linux/if_wanpipe.h> | ||
106 | |||
107 | |||
108 | /*====================================================== | ||
109 | * Defines & Macros | ||
110 | *=====================================================*/ | ||
111 | |||
112 | |||
113 | #define CMD_OK 0 /* normal firmware return code */ | ||
114 | #define CMD_TIMEOUT 0xFF /* firmware command timed out */ | ||
115 | #define MAX_CMD_RETRY 10 /* max number of firmware retries */ | ||
116 | |||
117 | #define X25_CHAN_MTU 4096 /* unfragmented logical channel MTU */ | ||
118 | #define X25_HRDHDR_SZ 7 /* max encapsulation header size */ | ||
119 | #define X25_CONCT_TMOUT (90*HZ) /* link connection timeout */ | ||
120 | #define X25_RECON_TMOUT (10*HZ) /* link connection timeout */ | ||
121 | #define CONNECT_TIMEOUT (90*HZ) /* link connection timeout */ | ||
122 | #define HOLD_DOWN_TIME (30*HZ) /* link hold down time */ | ||
123 | #define MAX_BH_BUFF 10 | ||
124 | #define M_BIT 0x01 | ||
125 | |||
126 | //#define PRINT_DEBUG 1 | ||
127 | #ifdef PRINT_DEBUG | ||
128 | #define DBG_PRINTK(format, a...) printk(format, ## a) | ||
129 | #else | ||
130 | #define DBG_PRINTK(format, a...) | ||
131 | #endif | ||
132 | |||
133 | #define TMR_INT_ENABLED_POLL_ACTIVE 0x01 | ||
134 | #define TMR_INT_ENABLED_POLL_CONNECT_ON 0x02 | ||
135 | #define TMR_INT_ENABLED_POLL_CONNECT_OFF 0x04 | ||
136 | #define TMR_INT_ENABLED_POLL_DISCONNECT 0x08 | ||
137 | #define TMR_INT_ENABLED_CMD_EXEC 0x10 | ||
138 | #define TMR_INT_ENABLED_UPDATE 0x20 | ||
139 | #define TMR_INT_ENABLED_UDP_PKT 0x40 | ||
140 | |||
141 | #define MAX_X25_ADDR_SIZE 16 | ||
142 | #define MAX_X25_DATA_SIZE 129 | ||
143 | #define MAX_X25_FACL_SIZE 110 | ||
144 | |||
145 | #define TRY_CMD_AGAIN 2 | ||
146 | #define DELAY_RESULT 1 | ||
147 | #define RETURN_RESULT 0 | ||
148 | |||
149 | #define DCD(x) (x & 0x03 ? "HIGH" : "LOW") | ||
150 | #define CTS(x) (x & 0x05 ? "HIGH" : "LOW") | ||
151 | |||
152 | |||
153 | /* Driver will not write log messages about | ||
154 | * modem status if defined.*/ | ||
155 | #define MODEM_NOT_LOG 1 | ||
156 | |||
157 | /*==================================================== | ||
158 | * For IPXWAN | ||
159 | *===================================================*/ | ||
160 | |||
161 | #define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b))) | ||
162 | |||
163 | |||
164 | /*==================================================== | ||
165 | * MEMORY DEBUGGING FUNCTION | ||
166 | *==================================================== | ||
167 | |||
168 | #define KMEM_SAFETYZONE 8 | ||
169 | |||
170 | static void * dbg_kmalloc(unsigned int size, int prio, int line) { | ||
171 | int i = 0; | ||
172 | void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio); | ||
173 | char * c1 = v; | ||
174 | c1 += sizeof(unsigned int); | ||
175 | *((unsigned int *)v) = size; | ||
176 | |||
177 | for (i = 0; i < KMEM_SAFETYZONE; i++) { | ||
178 | c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D'; | ||
179 | c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F'; | ||
180 | c1 += 8; | ||
181 | } | ||
182 | c1 += size; | ||
183 | for (i = 0; i < KMEM_SAFETYZONE; i++) { | ||
184 | c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G'; | ||
185 | c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L'; | ||
186 | c1 += 8; | ||
187 | } | ||
188 | v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8; | ||
189 | printk(KERN_INFO "line %d kmalloc(%d,%d) = %p\n",line,size,prio,v); | ||
190 | return v; | ||
191 | } | ||
192 | static void dbg_kfree(void * v, int line) { | ||
193 | unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8)); | ||
194 | unsigned int size = *sp; | ||
195 | char * c1 = ((char *)v) - KMEM_SAFETYZONE*8; | ||
196 | int i = 0; | ||
197 | for (i = 0; i < KMEM_SAFETYZONE; i++) { | ||
198 | if ( c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D' | ||
199 | || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') { | ||
200 | printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v); | ||
201 | printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8, | ||
202 | c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] ); | ||
203 | } | ||
204 | c1 += 8; | ||
205 | } | ||
206 | c1 += size; | ||
207 | for (i = 0; i < KMEM_SAFETYZONE; i++) { | ||
208 | if ( c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G' | ||
209 | || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L' | ||
210 | ) { | ||
211 | printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v); | ||
212 | printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8, | ||
213 | c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] ); | ||
214 | } | ||
215 | c1 += 8; | ||
216 | } | ||
217 | printk(KERN_INFO "line %d kfree(%p)\n",line,v); | ||
218 | v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8); | ||
219 | kfree(v); | ||
220 | } | ||
221 | |||
222 | #define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__) | ||
223 | #define kfree(x) dbg_kfree(x,__LINE__) | ||
224 | |||
225 | ==============================================================*/ | ||
226 | |||
227 | |||
228 | |||
229 | /*=============================================== | ||
230 | * Data Structures | ||
231 | *===============================================*/ | ||
232 | |||
233 | |||
234 | /*======================================================== | ||
235 | * Name: x25_channel | ||
236 | * | ||
237 | * Purpose: To hold private informaton for each | ||
238 | * logical channel. | ||
239 | * | ||
240 | * Rationale: Per-channel debugging is possible if each | ||
241 | * channel has its own private area. | ||
242 | * | ||
243 | * Assumptions: | ||
244 | * | ||
245 | * Description: This is an extention of the struct net_device | ||
246 | * we create for each network interface to keep | ||
247 | * the rest of X.25 channel-specific data. | ||
248 | * | ||
249 | * Construct: Typedef | ||
250 | */ | ||
251 | typedef struct x25_channel | ||
252 | { | ||
253 | wanpipe_common_t common; /* common area for x25api and socket */ | ||
254 | char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */ | ||
255 | char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */ | ||
256 | unsigned tx_pkt_size; | ||
257 | unsigned short protocol; /* ethertype, 0 - multiplexed */ | ||
258 | char drop_sequence; /* mark sequence for dropping */ | ||
259 | unsigned long state_tick; /* time of the last state change */ | ||
260 | unsigned idle_timeout; /* sec, before disconnecting */ | ||
261 | unsigned long i_timeout_sofar; /* # of sec's we've been idle */ | ||
262 | unsigned hold_timeout; /* sec, before re-connecting */ | ||
263 | unsigned long tick_counter; /* counter for transmit time out */ | ||
264 | char devtint; /* Weather we should dev_tint() */ | ||
265 | struct sk_buff* rx_skb; /* receive socket buffer */ | ||
266 | struct sk_buff* tx_skb; /* transmit socket buffer */ | ||
267 | |||
268 | bh_data_t *bh_head; /* Circular buffer for x25api_bh */ | ||
269 | unsigned long tq_working; | ||
270 | volatile int bh_write; | ||
271 | volatile int bh_read; | ||
272 | atomic_t bh_buff_used; | ||
273 | |||
274 | sdla_t* card; /* -> owner */ | ||
275 | struct net_device *dev; /* -> bound devce */ | ||
276 | |||
277 | int ch_idx; | ||
278 | unsigned char enable_IPX; | ||
279 | unsigned long network_number; | ||
280 | struct net_device_stats ifstats; /* interface statistics */ | ||
281 | unsigned short transmit_length; | ||
282 | unsigned short tx_offset; | ||
283 | char transmit_buffer[X25_CHAN_MTU+sizeof(x25api_hdr_t)]; | ||
284 | |||
285 | if_send_stat_t if_send_stat; | ||
286 | rx_intr_stat_t rx_intr_stat; | ||
287 | pipe_mgmt_stat_t pipe_mgmt_stat; | ||
288 | |||
289 | unsigned long router_start_time; /* Router start time in seconds */ | ||
290 | unsigned long router_up_time; | ||
291 | |||
292 | } x25_channel_t; | ||
293 | |||
294 | /* FIXME Take this out */ | ||
295 | |||
296 | #ifdef NEX_OLD_CALL_INFO | ||
297 | typedef struct x25_call_info | ||
298 | { | ||
299 | char dest[17]; PACKED;/* ASCIIZ destination address */ | ||
300 | char src[17]; PACKED;/* ASCIIZ source address */ | ||
301 | char nuser; PACKED;/* number of user data bytes */ | ||
302 | unsigned char user[127]; PACKED;/* user data */ | ||
303 | char nfacil; PACKED;/* number of facilities */ | ||
304 | struct | ||
305 | { | ||
306 | unsigned char code; PACKED; | ||
307 | unsigned char parm; PACKED; | ||
308 | } facil[64]; /* facilities */ | ||
309 | } x25_call_info_t; | ||
310 | #else | ||
311 | typedef struct x25_call_info | ||
312 | { | ||
313 | char dest[MAX_X25_ADDR_SIZE] PACKED;/* ASCIIZ destination address */ | ||
314 | char src[MAX_X25_ADDR_SIZE] PACKED;/* ASCIIZ source address */ | ||
315 | unsigned char nuser PACKED; | ||
316 | unsigned char user[MAX_X25_DATA_SIZE] PACKED;/* user data */ | ||
317 | unsigned char nfacil PACKED; | ||
318 | unsigned char facil[MAX_X25_FACL_SIZE] PACKED; | ||
319 | unsigned short lcn PACKED; | ||
320 | } x25_call_info_t; | ||
321 | #endif | ||
322 | |||
323 | |||
324 | |||
325 | /*=============================================== | ||
326 | * Private Function Prototypes | ||
327 | *==============================================*/ | ||
328 | |||
329 | |||
330 | /*================================================= | ||
331 | * WAN link driver entry points. These are | ||
332 | * called by the WAN router module. | ||
333 | */ | ||
334 | static int update(struct wan_device* wandev); | ||
335 | static int new_if(struct wan_device* wandev, struct net_device* dev, | ||
336 | wanif_conf_t* conf); | ||
337 | static int del_if(struct wan_device* wandev, struct net_device* dev); | ||
338 | static void disable_comm (sdla_t* card); | ||
339 | static void disable_comm_shutdown(sdla_t *card); | ||
340 | |||
341 | |||
342 | |||
343 | /*================================================= | ||
344 | * WANPIPE-specific entry points | ||
345 | */ | ||
346 | static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data); | ||
347 | static void x25api_bh(struct net_device *dev); | ||
348 | static int x25api_bh_cleanup(struct net_device *dev); | ||
349 | static int bh_enqueue(struct net_device *dev, struct sk_buff *skb); | ||
350 | |||
351 | |||
352 | /*================================================= | ||
353 | * Network device interface | ||
354 | */ | ||
355 | static int if_init(struct net_device* dev); | ||
356 | static int if_open(struct net_device* dev); | ||
357 | static int if_close(struct net_device* dev); | ||
358 | static int if_header(struct sk_buff* skb, struct net_device* dev, | ||
359 | unsigned short type, void* daddr, void* saddr, unsigned len); | ||
360 | static int if_rebuild_hdr (struct sk_buff* skb); | ||
361 | static int if_send(struct sk_buff* skb, struct net_device* dev); | ||
362 | static struct net_device_stats *if_stats(struct net_device* dev); | ||
363 | |||
364 | static void if_tx_timeout(struct net_device *dev); | ||
365 | |||
366 | /*================================================= | ||
367 | * Interrupt handlers | ||
368 | */ | ||
369 | static void wpx_isr (sdla_t *); | ||
370 | static void rx_intr (sdla_t *); | ||
371 | static void tx_intr (sdla_t *); | ||
372 | static void status_intr (sdla_t *); | ||
373 | static void event_intr (sdla_t *); | ||
374 | static void spur_intr (sdla_t *); | ||
375 | static void timer_intr (sdla_t *); | ||
376 | |||
377 | static int tx_intr_send(sdla_t *card, struct net_device *dev); | ||
378 | static struct net_device *move_dev_to_next(sdla_t *card, | ||
379 | struct net_device *dev); | ||
380 | |||
381 | /*================================================= | ||
382 | * Background polling routines | ||
383 | */ | ||
384 | static void wpx_poll (sdla_t* card); | ||
385 | static void poll_disconnected (sdla_t* card); | ||
386 | static void poll_connecting (sdla_t* card); | ||
387 | static void poll_active (sdla_t* card); | ||
388 | static void trigger_x25_poll(sdla_t *card); | ||
389 | static void x25_timer_routine(unsigned long data); | ||
390 | |||
391 | |||
392 | |||
393 | /*================================================= | ||
394 | * X.25 firmware interface functions | ||
395 | */ | ||
396 | static int x25_get_version (sdla_t* card, char* str); | ||
397 | static int x25_configure (sdla_t* card, TX25Config* conf); | ||
398 | static int hdlc_configure (sdla_t* card, TX25Config* conf); | ||
399 | static int set_hdlc_level (sdla_t* card); | ||
400 | static int x25_get_err_stats (sdla_t* card); | ||
401 | static int x25_get_stats (sdla_t* card); | ||
402 | static int x25_set_intr_mode (sdla_t* card, int mode); | ||
403 | static int x25_close_hdlc (sdla_t* card); | ||
404 | static int x25_open_hdlc (sdla_t* card); | ||
405 | static int x25_setup_hdlc (sdla_t* card); | ||
406 | static int x25_set_dtr (sdla_t* card, int dtr); | ||
407 | static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan); | ||
408 | static int x25_place_call (sdla_t* card, x25_channel_t* chan); | ||
409 | static int x25_accept_call (sdla_t* card, int lcn, int qdm); | ||
410 | static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn); | ||
411 | static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf); | ||
412 | static int x25_fetch_events (sdla_t* card); | ||
413 | static int x25_error (sdla_t* card, int err, int cmd, int lcn); | ||
414 | |||
415 | /*================================================= | ||
416 | * X.25 asynchronous event handlers | ||
417 | */ | ||
418 | static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb); | ||
419 | static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb); | ||
420 | static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb); | ||
421 | static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb); | ||
422 | static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb); | ||
423 | |||
424 | |||
425 | /*================================================= | ||
426 | * Miscellaneous functions | ||
427 | */ | ||
428 | static int connect (sdla_t* card); | ||
429 | static int disconnect (sdla_t* card); | ||
430 | static struct net_device* get_dev_by_lcn(struct wan_device* wandev, | ||
431 | unsigned lcn); | ||
432 | static int chan_connect(struct net_device* dev); | ||
433 | static int chan_disc(struct net_device* dev); | ||
434 | static void set_chan_state(struct net_device* dev, int state); | ||
435 | static int chan_send(struct net_device *dev, void* buff, unsigned data_len, | ||
436 | unsigned char tx_intr); | ||
437 | static unsigned char bps_to_speed_code (unsigned long bps); | ||
438 | static unsigned int dec_to_uint (unsigned char* str, int len); | ||
439 | static unsigned int hex_to_uint (unsigned char*, int); | ||
440 | static void parse_call_info (unsigned char*, x25_call_info_t*); | ||
441 | static struct net_device *find_channel(sdla_t *card, unsigned lcn); | ||
442 | static void bind_lcn_to_dev(sdla_t *card, struct net_device *dev, unsigned lcn); | ||
443 | static void setup_for_delayed_transmit(struct net_device *dev, | ||
444 | void *buf, unsigned len); | ||
445 | |||
446 | |||
447 | /*================================================= | ||
448 | * X25 API Functions | ||
449 | */ | ||
450 | static int wanpipe_pull_data_in_skb(sdla_t *card, struct net_device *dev, | ||
451 | struct sk_buff **); | ||
452 | static void timer_intr_exec(sdla_t *, unsigned char); | ||
453 | static int execute_delayed_cmd(sdla_t *card, struct net_device *dev, | ||
454 | mbox_cmd_t *usr_cmd, char bad_cmd); | ||
455 | static int api_incoming_call (sdla_t*, TX25Mbox *, int); | ||
456 | static int alloc_and_init_skb_buf (sdla_t *,struct sk_buff **, int); | ||
457 | static void send_delayed_cmd_result(sdla_t *card, struct net_device *dev, | ||
458 | TX25Mbox* mbox); | ||
459 | static int clear_confirm_event (sdla_t *, TX25Mbox*); | ||
460 | static void send_oob_msg (sdla_t *card, struct net_device *dev, TX25Mbox *mbox); | ||
461 | static int timer_intr_cmd_exec(sdla_t *card); | ||
462 | static void api_oob_event (sdla_t *card,TX25Mbox *mbox); | ||
463 | static int check_bad_command(sdla_t *card, struct net_device *dev); | ||
464 | static int channel_disconnect(sdla_t* card, struct net_device *dev); | ||
465 | static void hdlc_link_down (sdla_t*); | ||
466 | |||
467 | /*================================================= | ||
468 | * XPIPEMON Functions | ||
469 | */ | ||
470 | static int process_udp_mgmt_pkt(sdla_t *); | ||
471 | static int udp_pkt_type( struct sk_buff *, sdla_t*); | ||
472 | static int reply_udp( unsigned char *, unsigned int); | ||
473 | static void init_x25_channel_struct( x25_channel_t *); | ||
474 | static void init_global_statistics( sdla_t *); | ||
475 | static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t *card, | ||
476 | struct net_device *dev, | ||
477 | struct sk_buff *skb, int lcn); | ||
478 | static unsigned short calc_checksum (char *, int); | ||
479 | |||
480 | |||
481 | |||
482 | /*================================================= | ||
483 | * IPX functions | ||
484 | */ | ||
485 | static void switch_net_numbers(unsigned char *, unsigned long, unsigned char); | ||
486 | static int handle_IPXWAN(unsigned char *, char *, unsigned char , | ||
487 | unsigned long , unsigned short ); | ||
488 | |||
489 | extern void disable_irq(unsigned int); | ||
490 | extern void enable_irq(unsigned int); | ||
491 | |||
492 | static void S508_S514_lock(sdla_t *, unsigned long *); | ||
493 | static void S508_S514_unlock(sdla_t *, unsigned long *); | ||
494 | |||
495 | |||
496 | /*================================================= | ||
497 | * Global Variables | ||
498 | *=================================================*/ | ||
499 | |||
500 | |||
501 | |||
502 | /*================================================= | ||
503 | * Public Functions | ||
504 | *=================================================*/ | ||
505 | |||
506 | |||
507 | |||
508 | |||
509 | /*=================================================================== | ||
510 | * wpx_init: X.25 Protocol Initialization routine. | ||
511 | * | ||
512 | * Purpose: To initialize the protocol/firmware. | ||
513 | * | ||
514 | * Rationale: This function is called by setup() function, in | ||
515 | * sdlamain.c, to dynamically setup the x25 protocol. | ||
516 | * This is the first protocol specific function, which | ||
517 | * executes once on startup. | ||
518 | * | ||
519 | * Description: This procedure initializes the x25 firmware and | ||
520 | * sets up the mailbox, transmit and receive buffer | ||
521 | * pointers. It also initializes all debugging structures | ||
522 | * and sets up the X25 environment. | ||
523 | * | ||
524 | * Sets up hardware options defined by user in [wanpipe#] | ||
525 | * section of wanpipe#.conf configuration file. | ||
526 | * | ||
527 | * At this point adapter is completely initialized | ||
528 | * and X.25 firmware is running. | ||
529 | * o read firmware version (to make sure it's alive) | ||
530 | * o configure adapter | ||
531 | * o initialize protocol-specific fields of the | ||
532 | * adapter data space. | ||
533 | * | ||
534 | * Called by: setup() function in sdlamain.c | ||
535 | * | ||
536 | * Assumptions: None | ||
537 | * | ||
538 | * Warnings: None | ||
539 | * | ||
540 | * Return: 0 o.k. | ||
541 | * < 0 failure. | ||
542 | */ | ||
543 | |||
544 | int wpx_init (sdla_t* card, wandev_conf_t* conf) | ||
545 | { | ||
546 | union{ | ||
547 | char str[80]; | ||
548 | TX25Config cfg; | ||
549 | } u; | ||
550 | |||
551 | /* Verify configuration ID */ | ||
552 | if (conf->config_id != WANCONFIG_X25){ | ||
553 | printk(KERN_INFO "%s: invalid configuration ID %u!\n", | ||
554 | card->devname, conf->config_id) | ||
555 | ; | ||
556 | return -EINVAL; | ||
557 | } | ||
558 | |||
559 | /* Initialize protocol-specific fields */ | ||
560 | card->mbox = (void*)(card->hw.dpmbase + X25_MBOX_OFFS); | ||
561 | card->rxmb = (void*)(card->hw.dpmbase + X25_RXMBOX_OFFS); | ||
562 | card->flags = (void*)(card->hw.dpmbase + X25_STATUS_OFFS); | ||
563 | |||
564 | /* Initialize for S514 Card */ | ||
565 | if(card->hw.type == SDLA_S514) { | ||
566 | card->mbox += X25_MB_VECTOR; | ||
567 | card->flags += X25_MB_VECTOR; | ||
568 | card->rxmb += X25_MB_VECTOR; | ||
569 | } | ||
570 | |||
571 | |||
572 | /* Read firmware version. Note that when adapter initializes, it | ||
573 | * clears the mailbox, so it may appear that the first command was | ||
574 | * executed successfully when in fact it was merely erased. To work | ||
575 | * around this, we execute the first command twice. | ||
576 | */ | ||
577 | if (x25_get_version(card, NULL) || x25_get_version(card, u.str)) | ||
578 | return -EIO; | ||
579 | |||
580 | |||
581 | /* X25 firmware can run ether in X25 or LAPB HDLC mode. | ||
582 | * Check the user defined option and configure accordingly */ | ||
583 | if (conf->u.x25.LAPB_hdlc_only == WANOPT_YES){ | ||
584 | if (set_hdlc_level(card) != CMD_OK){ | ||
585 | return -EIO; | ||
586 | }else{ | ||
587 | printk(KERN_INFO "%s: running LAP_B HDLC firmware v%s\n", | ||
588 | card->devname, u.str); | ||
589 | } | ||
590 | card->u.x.LAPB_hdlc = 1; | ||
591 | }else{ | ||
592 | printk(KERN_INFO "%s: running X.25 firmware v%s\n", | ||
593 | card->devname, u.str); | ||
594 | card->u.x.LAPB_hdlc = 0; | ||
595 | } | ||
596 | |||
597 | /* Configure adapter. Here we set resonable defaults, then parse | ||
598 | * device configuration structure and set configuration options. | ||
599 | * Most configuration options are verified and corrected (if | ||
600 | * necessary) since we can't rely on the adapter to do so. | ||
601 | */ | ||
602 | memset(&u.cfg, 0, sizeof(u.cfg)); | ||
603 | u.cfg.t1 = 3; | ||
604 | u.cfg.n2 = 10; | ||
605 | u.cfg.autoHdlc = 1; /* automatic HDLC connection */ | ||
606 | u.cfg.hdlcWindow = 7; | ||
607 | u.cfg.pktWindow = 2; | ||
608 | u.cfg.station = 1; /* DTE */ | ||
609 | u.cfg.options = 0x0090; /* disable D-bit pragmatics */ | ||
610 | u.cfg.ccittCompat = 1988; | ||
611 | u.cfg.t10t20 = 30; | ||
612 | u.cfg.t11t21 = 30; | ||
613 | u.cfg.t12t22 = 30; | ||
614 | u.cfg.t13t23 = 30; | ||
615 | u.cfg.t16t26 = 30; | ||
616 | u.cfg.t28 = 30; | ||
617 | u.cfg.r10r20 = 5; | ||
618 | u.cfg.r12r22 = 5; | ||
619 | u.cfg.r13r23 = 5; | ||
620 | u.cfg.responseOpt = 1; /* RR's after every packet */ | ||
621 | |||
622 | if (card->u.x.LAPB_hdlc){ | ||
623 | u.cfg.hdlcMTU = 1027; | ||
624 | } | ||
625 | |||
626 | if (conf->u.x25.x25_conf_opt){ | ||
627 | u.cfg.options = conf->u.x25.x25_conf_opt; | ||
628 | } | ||
629 | |||
630 | if (conf->clocking != WANOPT_EXTERNAL) | ||
631 | u.cfg.baudRate = bps_to_speed_code(conf->bps); | ||
632 | |||
633 | if (conf->station != WANOPT_DTE){ | ||
634 | u.cfg.station = 0; /* DCE mode */ | ||
635 | } | ||
636 | |||
637 | if (conf->interface != WANOPT_RS232 ){ | ||
638 | u.cfg.hdlcOptions |= 0x80; /* V35 mode */ | ||
639 | } | ||
640 | |||
641 | /* adjust MTU */ | ||
642 | if (!conf->mtu || (conf->mtu >= 1024)) | ||
643 | card->wandev.mtu = 1024; | ||
644 | else if (conf->mtu >= 512) | ||
645 | card->wandev.mtu = 512; | ||
646 | else if (conf->mtu >= 256) | ||
647 | card->wandev.mtu = 256; | ||
648 | else if (conf->mtu >= 128) | ||
649 | card->wandev.mtu = 128; | ||
650 | else | ||
651 | card->wandev.mtu = 64; | ||
652 | |||
653 | u.cfg.defPktSize = u.cfg.pktMTU = card->wandev.mtu; | ||
654 | |||
655 | if (conf->u.x25.hi_pvc){ | ||
656 | card->u.x.hi_pvc = min_t(unsigned int, conf->u.x25.hi_pvc, MAX_LCN_NUM); | ||
657 | card->u.x.lo_pvc = min_t(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc); | ||
658 | } | ||
659 | |||
660 | if (conf->u.x25.hi_svc){ | ||
661 | card->u.x.hi_svc = min_t(unsigned int, conf->u.x25.hi_svc, MAX_LCN_NUM); | ||
662 | card->u.x.lo_svc = min_t(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc); | ||
663 | } | ||
664 | |||
665 | /* Figure out the total number of channels to configure */ | ||
666 | card->u.x.num_of_ch = 0; | ||
667 | if (card->u.x.hi_svc != 0){ | ||
668 | card->u.x.num_of_ch = (card->u.x.hi_svc - card->u.x.lo_svc) + 1; | ||
669 | } | ||
670 | if (card->u.x.hi_pvc != 0){ | ||
671 | card->u.x.num_of_ch += (card->u.x.hi_pvc - card->u.x.lo_pvc) + 1; | ||
672 | } | ||
673 | |||
674 | if (card->u.x.num_of_ch == 0){ | ||
675 | printk(KERN_INFO "%s: ERROR, Minimum number of PVC/SVC channels is 1 !\n" | ||
676 | "%s: Please set the Lowest/Highest PVC/SVC values !\n", | ||
677 | card->devname,card->devname); | ||
678 | return -ECHRNG; | ||
679 | } | ||
680 | |||
681 | u.cfg.loPVC = card->u.x.lo_pvc; | ||
682 | u.cfg.hiPVC = card->u.x.hi_pvc; | ||
683 | u.cfg.loTwoWaySVC = card->u.x.lo_svc; | ||
684 | u.cfg.hiTwoWaySVC = card->u.x.hi_svc; | ||
685 | |||
686 | if (conf->u.x25.hdlc_window) | ||
687 | u.cfg.hdlcWindow = min_t(unsigned int, conf->u.x25.hdlc_window, 7); | ||
688 | if (conf->u.x25.pkt_window) | ||
689 | u.cfg.pktWindow = min_t(unsigned int, conf->u.x25.pkt_window, 7); | ||
690 | |||
691 | if (conf->u.x25.t1) | ||
692 | u.cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30); | ||
693 | if (conf->u.x25.t2) | ||
694 | u.cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 29); | ||
695 | if (conf->u.x25.t4) | ||
696 | u.cfg.t4 = min_t(unsigned int, conf->u.x25.t4, 240); | ||
697 | if (conf->u.x25.n2) | ||
698 | u.cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30); | ||
699 | |||
700 | if (conf->u.x25.t10_t20) | ||
701 | u.cfg.t10t20 = min_t(unsigned int, conf->u.x25.t10_t20,255); | ||
702 | if (conf->u.x25.t11_t21) | ||
703 | u.cfg.t11t21 = min_t(unsigned int, conf->u.x25.t11_t21,255); | ||
704 | if (conf->u.x25.t12_t22) | ||
705 | u.cfg.t12t22 = min_t(unsigned int, conf->u.x25.t12_t22,255); | ||
706 | if (conf->u.x25.t13_t23) | ||
707 | u.cfg.t13t23 = min_t(unsigned int, conf->u.x25.t13_t23,255); | ||
708 | if (conf->u.x25.t16_t26) | ||
709 | u.cfg.t16t26 = min_t(unsigned int, conf->u.x25.t16_t26, 255); | ||
710 | if (conf->u.x25.t28) | ||
711 | u.cfg.t28 = min_t(unsigned int, conf->u.x25.t28, 255); | ||
712 | |||
713 | if (conf->u.x25.r10_r20) | ||
714 | u.cfg.r10r20 = min_t(unsigned int, conf->u.x25.r10_r20,250); | ||
715 | if (conf->u.x25.r12_r22) | ||
716 | u.cfg.r12r22 = min_t(unsigned int, conf->u.x25.r12_r22,250); | ||
717 | if (conf->u.x25.r13_r23) | ||
718 | u.cfg.r13r23 = min_t(unsigned int, conf->u.x25.r13_r23,250); | ||
719 | |||
720 | |||
721 | if (conf->u.x25.ccitt_compat) | ||
722 | u.cfg.ccittCompat = conf->u.x25.ccitt_compat; | ||
723 | |||
724 | /* initialize adapter */ | ||
725 | if (card->u.x.LAPB_hdlc){ | ||
726 | if (hdlc_configure(card, &u.cfg) != CMD_OK) | ||
727 | return -EIO; | ||
728 | }else{ | ||
729 | if (x25_configure(card, &u.cfg) != CMD_OK) | ||
730 | return -EIO; | ||
731 | } | ||
732 | |||
733 | if ((x25_close_hdlc(card) != CMD_OK) || /* close HDLC link */ | ||
734 | (x25_set_dtr(card, 0) != CMD_OK)) /* drop DTR */ | ||
735 | return -EIO; | ||
736 | |||
737 | /* Initialize protocol-specific fields of adapter data space */ | ||
738 | card->wandev.bps = conf->bps; | ||
739 | card->wandev.interface = conf->interface; | ||
740 | card->wandev.clocking = conf->clocking; | ||
741 | card->wandev.station = conf->station; | ||
742 | card->isr = &wpx_isr; | ||
743 | card->poll = NULL; //&wpx_poll; | ||
744 | card->disable_comm = &disable_comm; | ||
745 | card->exec = &wpx_exec; | ||
746 | card->wandev.update = &update; | ||
747 | card->wandev.new_if = &new_if; | ||
748 | card->wandev.del_if = &del_if; | ||
749 | |||
750 | /* WARNING: This function cannot exit with an error | ||
751 | * after the change of state */ | ||
752 | card->wandev.state = WAN_DISCONNECTED; | ||
753 | |||
754 | card->wandev.enable_tx_int = 0; | ||
755 | card->irq_dis_if_send_count = 0; | ||
756 | card->irq_dis_poll_count = 0; | ||
757 | card->u.x.tx_dev = NULL; | ||
758 | card->u.x.no_dev = 0; | ||
759 | |||
760 | |||
761 | /* Configure for S514 PCI Card */ | ||
762 | if (card->hw.type == SDLA_S514) { | ||
763 | card->u.x.hdlc_buf_status = | ||
764 | (volatile unsigned char *) | ||
765 | (card->hw.dpmbase + X25_MB_VECTOR+ X25_MISC_HDLC_BITS); | ||
766 | }else{ | ||
767 | card->u.x.hdlc_buf_status = | ||
768 | (volatile unsigned char *)(card->hw.dpmbase + X25_MISC_HDLC_BITS); | ||
769 | } | ||
770 | |||
771 | card->u.x.poll_device=NULL; | ||
772 | card->wandev.udp_port = conf->udp_port; | ||
773 | |||
774 | /* Enable or disable call setup logging */ | ||
775 | if (conf->u.x25.logging == WANOPT_YES){ | ||
776 | printk(KERN_INFO "%s: Enabling Call Logging.\n", | ||
777 | card->devname); | ||
778 | card->u.x.logging = 1; | ||
779 | }else{ | ||
780 | card->u.x.logging = 0; | ||
781 | } | ||
782 | |||
783 | /* Enable or disable modem status reporting */ | ||
784 | if (conf->u.x25.oob_on_modem == WANOPT_YES){ | ||
785 | printk(KERN_INFO "%s: Enabling OOB on Modem change.\n", | ||
786 | card->devname); | ||
787 | card->u.x.oob_on_modem = 1; | ||
788 | }else{ | ||
789 | card->u.x.oob_on_modem = 0; | ||
790 | } | ||
791 | |||
792 | init_global_statistics(card); | ||
793 | |||
794 | INIT_WORK(&card->u.x.x25_poll_work, (void *)wpx_poll, card); | ||
795 | |||
796 | init_timer(&card->u.x.x25_timer); | ||
797 | card->u.x.x25_timer.data = (unsigned long)card; | ||
798 | card->u.x.x25_timer.function = x25_timer_routine; | ||
799 | |||
800 | return 0; | ||
801 | } | ||
802 | |||
803 | /*========================================================= | ||
804 | * WAN Device Driver Entry Points | ||
805 | *========================================================*/ | ||
806 | |||
807 | /*============================================================ | ||
808 | * Name: update(), Update device status & statistics. | ||
809 | * | ||
810 | * Purpose: To provide debugging and statitical | ||
811 | * information to the /proc file system. | ||
812 | * /proc/net/wanrouter/wanpipe# | ||
813 | * | ||
814 | * Rationale: The /proc file system is used to collect | ||
815 | * information about the kernel and drivers. | ||
816 | * Using the /proc file system the user | ||
817 | * can see exactly what the sangoma drivers are | ||
818 | * doing. And in what state they are in. | ||
819 | * | ||
820 | * Description: Collect all driver statistical information | ||
821 | * and pass it to the top laywer. | ||
822 | * | ||
823 | * Since we have to execute a debugging command, | ||
824 | * to obtain firmware statitics, we trigger a | ||
825 | * UPDATE function within the timer interrtup. | ||
826 | * We wait until the timer update is complete. | ||
827 | * Once complete return the appropriate return | ||
828 | * code to indicate that the update was successful. | ||
829 | * | ||
830 | * Called by: device_stat() in wanmain.c | ||
831 | * | ||
832 | * Assumptions: | ||
833 | * | ||
834 | * Warnings: This function will degrade the performance | ||
835 | * of the router, since it uses the mailbox. | ||
836 | * | ||
837 | * Return: 0 OK | ||
838 | * <0 Failed (or busy). | ||
839 | */ | ||
840 | |||
841 | static int update(struct wan_device* wandev) | ||
842 | { | ||
843 | volatile sdla_t* card; | ||
844 | TX25Status* status; | ||
845 | unsigned long timeout; | ||
846 | |||
847 | /* sanity checks */ | ||
848 | if ((wandev == NULL) || (wandev->private == NULL)) | ||
849 | return -EFAULT; | ||
850 | |||
851 | if (wandev->state == WAN_UNCONFIGURED) | ||
852 | return -ENODEV; | ||
853 | |||
854 | if (test_bit(SEND_CRIT, (void*)&wandev->critical)) | ||
855 | return -EAGAIN; | ||
856 | |||
857 | if (!wandev->dev) | ||
858 | return -ENODEV; | ||
859 | |||
860 | card = wandev->private; | ||
861 | status = card->flags; | ||
862 | |||
863 | card->u.x.timer_int_enabled |= TMR_INT_ENABLED_UPDATE; | ||
864 | status->imask |= INTR_ON_TIMER; | ||
865 | timeout = jiffies; | ||
866 | |||
867 | for (;;){ | ||
868 | if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE)){ | ||
869 | break; | ||
870 | } | ||
871 | if (time_after(jiffies, timeout + 1*HZ)){ | ||
872 | card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; | ||
873 | return -EAGAIN; | ||
874 | } | ||
875 | } | ||
876 | return 0; | ||
877 | } | ||
878 | |||
879 | |||
880 | /*=================================================================== | ||
881 | * Name: new_if | ||
882 | * | ||
883 | * Purpose: To allocate and initialize resources for a | ||
884 | * new logical channel. | ||
885 | * | ||
886 | * Rationale: A new channel can be added dynamically via | ||
887 | * ioctl call. | ||
888 | * | ||
889 | * Description: Allocate a private channel structure, x25_channel_t. | ||
890 | * Parse the user interface options from wanpipe#.conf | ||
891 | * configuration file. | ||
892 | * Bind the private are into the network device private | ||
893 | * area pointer (dev->priv). | ||
894 | * Prepare the network device structure for registration. | ||
895 | * | ||
896 | * Called by: ROUTER_IFNEW Ioctl call, from wanrouter_ioctl() | ||
897 | * (wanmain.c) | ||
898 | * | ||
899 | * Assumptions: None | ||
900 | * | ||
901 | * Warnings: None | ||
902 | * | ||
903 | * Return: 0 Ok | ||
904 | * <0 Failed (channel will not be created) | ||
905 | */ | ||
906 | static int new_if(struct wan_device* wandev, struct net_device* dev, | ||
907 | wanif_conf_t* conf) | ||
908 | { | ||
909 | sdla_t* card = wandev->private; | ||
910 | x25_channel_t* chan; | ||
911 | int err = 0; | ||
912 | |||
913 | if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)){ | ||
914 | printk(KERN_INFO "%s: invalid interface name!\n", | ||
915 | card->devname); | ||
916 | return -EINVAL; | ||
917 | } | ||
918 | |||
919 | if(card->wandev.new_if_cnt++ > 0 && card->u.x.LAPB_hdlc) { | ||
920 | printk(KERN_INFO "%s: Error: Running LAPB HDLC Mode !\n", | ||
921 | card->devname); | ||
922 | printk(KERN_INFO | ||
923 | "%s: Maximum number of network interfaces must be one !\n", | ||
924 | card->devname); | ||
925 | return -EEXIST; | ||
926 | } | ||
927 | |||
928 | /* allocate and initialize private data */ | ||
929 | chan = kmalloc(sizeof(x25_channel_t), GFP_ATOMIC); | ||
930 | if (chan == NULL){ | ||
931 | return -ENOMEM; | ||
932 | } | ||
933 | |||
934 | memset(chan, 0, sizeof(x25_channel_t)); | ||
935 | |||
936 | /* Bug Fix: Seg Err on PVC startup | ||
937 | * It must be here since bind_lcn_to_dev expects | ||
938 | * it bellow */ | ||
939 | dev->priv = chan; | ||
940 | |||
941 | strcpy(chan->name, conf->name); | ||
942 | chan->card = card; | ||
943 | chan->dev = dev; | ||
944 | chan->common.sk = NULL; | ||
945 | chan->common.func = NULL; | ||
946 | chan->common.rw_bind = 0; | ||
947 | chan->tx_skb = chan->rx_skb = NULL; | ||
948 | |||
949 | /* verify media address */ | ||
950 | if (conf->addr[0] == '@'){ /* SVC */ | ||
951 | chan->common.svc = 1; | ||
952 | strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ); | ||
953 | |||
954 | /* Set channel timeouts (default if not specified) */ | ||
955 | chan->idle_timeout = (conf->idle_timeout) ? | ||
956 | conf->idle_timeout : 90; | ||
957 | chan->hold_timeout = (conf->hold_timeout) ? | ||
958 | conf->hold_timeout : 10; | ||
959 | |||
960 | }else if (isdigit(conf->addr[0])){ /* PVC */ | ||
961 | int lcn = dec_to_uint(conf->addr, 0); | ||
962 | |||
963 | if ((lcn >= card->u.x.lo_pvc) && (lcn <= card->u.x.hi_pvc)){ | ||
964 | bind_lcn_to_dev (card, dev, lcn); | ||
965 | }else{ | ||
966 | printk(KERN_ERR | ||
967 | "%s: PVC %u is out of range on interface %s!\n", | ||
968 | wandev->name, lcn, chan->name); | ||
969 | err = -EINVAL; | ||
970 | } | ||
971 | }else{ | ||
972 | printk(KERN_ERR | ||
973 | "%s: invalid media address on interface %s!\n", | ||
974 | wandev->name, chan->name); | ||
975 | err = -EINVAL; | ||
976 | } | ||
977 | |||
978 | if(strcmp(conf->usedby, "WANPIPE") == 0){ | ||
979 | printk(KERN_INFO "%s: Running in WANPIPE mode %s\n", | ||
980 | wandev->name, chan->name); | ||
981 | chan->common.usedby = WANPIPE; | ||
982 | chan->protocol = htons(ETH_P_IP); | ||
983 | |||
984 | }else if(strcmp(conf->usedby, "API") == 0){ | ||
985 | chan->common.usedby = API; | ||
986 | printk(KERN_INFO "%s: Running in API mode %s\n", | ||
987 | wandev->name, chan->name); | ||
988 | chan->protocol = htons(X25_PROT); | ||
989 | } | ||
990 | |||
991 | |||
992 | if (err){ | ||
993 | kfree(chan); | ||
994 | dev->priv = NULL; | ||
995 | return err; | ||
996 | } | ||
997 | |||
998 | chan->enable_IPX = conf->enable_IPX; | ||
999 | |||
1000 | if (chan->enable_IPX) | ||
1001 | chan->protocol = htons(ETH_P_IPX); | ||
1002 | |||
1003 | if (conf->network_number) | ||
1004 | chan->network_number = conf->network_number; | ||
1005 | else | ||
1006 | chan->network_number = 0xDEADBEEF; | ||
1007 | |||
1008 | /* prepare network device data space for registration */ | ||
1009 | strcpy(dev->name,chan->name); | ||
1010 | |||
1011 | dev->init = &if_init; | ||
1012 | |||
1013 | init_x25_channel_struct(chan); | ||
1014 | |||
1015 | return 0; | ||
1016 | } | ||
1017 | |||
1018 | /*=================================================================== | ||
1019 | * Name: del_if(), Remove a logical channel. | ||
1020 | * | ||
1021 | * Purpose: To dynamically remove a logical channel. | ||
1022 | * | ||
1023 | * Rationale: Each logical channel should be dynamically | ||
1024 | * removable. This functin is called by an | ||
1025 | * IOCTL_IFDEL ioctl call or shutdown(). | ||
1026 | * | ||
1027 | * Description: Do nothing. | ||
1028 | * | ||
1029 | * Called by: IOCTL_IFDEL : wanrouter_ioctl() from wanmain.c | ||
1030 | * shutdown() from sdlamain.c | ||
1031 | * | ||
1032 | * Assumptions: | ||
1033 | * | ||
1034 | * Warnings: | ||
1035 | * | ||
1036 | * Return: 0 Ok. Void function. | ||
1037 | */ | ||
1038 | |||
1039 | //FIXME Del IF Should be taken out now. | ||
1040 | |||
1041 | static int del_if(struct wan_device* wandev, struct net_device* dev) | ||
1042 | { | ||
1043 | return 0; | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | /*============================================================ | ||
1048 | * Name: wpx_exec | ||
1049 | * | ||
1050 | * Description: Execute adapter interface command. | ||
1051 | * This option is currently dissabled. | ||
1052 | *===========================================================*/ | ||
1053 | |||
1054 | static int wpx_exec (struct sdla* card, void* u_cmd, void* u_data) | ||
1055 | { | ||
1056 | return 0; | ||
1057 | } | ||
1058 | |||
1059 | /*============================================================ | ||
1060 | * Name: disable_comm | ||
1061 | * | ||
1062 | * Description: Disable communications during shutdown. | ||
1063 | * Dont check return code because there is | ||
1064 | * nothing we can do about it. | ||
1065 | * | ||
1066 | * Warning: Dev and private areas are gone at this point. | ||
1067 | *===========================================================*/ | ||
1068 | |||
1069 | static void disable_comm(sdla_t* card) | ||
1070 | { | ||
1071 | disable_comm_shutdown(card); | ||
1072 | del_timer(&card->u.x.x25_timer); | ||
1073 | return; | ||
1074 | } | ||
1075 | |||
1076 | |||
1077 | /*============================================================ | ||
1078 | * Network Device Interface | ||
1079 | *===========================================================*/ | ||
1080 | |||
1081 | /*=================================================================== | ||
1082 | * Name: if_init(), Netowrk Interface Initialization | ||
1083 | * | ||
1084 | * Purpose: To initialize a network interface device structure. | ||
1085 | * | ||
1086 | * Rationale: During network interface startup, the if_init | ||
1087 | * is called by the kernel to initialize the | ||
1088 | * netowrk device structure. Thus a driver | ||
1089 | * can customze a network device. | ||
1090 | * | ||
1091 | * Description: Initialize the netowrk device call back | ||
1092 | * routines. This is where we tell the kernel | ||
1093 | * which function to use when it wants to send | ||
1094 | * via our interface. | ||
1095 | * Furthermore, we initialize the device flags, | ||
1096 | * MTU and physical address of the board. | ||
1097 | * | ||
1098 | * Called by: Kernel (/usr/src/linux/net/core/dev.c) | ||
1099 | * (dev->init()) | ||
1100 | * | ||
1101 | * Assumptions: None | ||
1102 | * | ||
1103 | * Warnings: None | ||
1104 | * | ||
1105 | * Return: 0 Ok : Void function. | ||
1106 | */ | ||
1107 | static int if_init(struct net_device* dev) | ||
1108 | { | ||
1109 | x25_channel_t* chan = dev->priv; | ||
1110 | sdla_t* card = chan->card; | ||
1111 | struct wan_device* wandev = &card->wandev; | ||
1112 | |||
1113 | /* Initialize device driver entry points */ | ||
1114 | dev->open = &if_open; | ||
1115 | dev->stop = &if_close; | ||
1116 | dev->hard_header = &if_header; | ||
1117 | dev->rebuild_header = &if_rebuild_hdr; | ||
1118 | dev->hard_start_xmit = &if_send; | ||
1119 | dev->get_stats = &if_stats; | ||
1120 | dev->tx_timeout = &if_tx_timeout; | ||
1121 | dev->watchdog_timeo = TX_TIMEOUT; | ||
1122 | |||
1123 | /* Initialize media-specific parameters */ | ||
1124 | dev->type = ARPHRD_PPP; /* ARP h/w type */ | ||
1125 | dev->flags |= IFF_POINTOPOINT; | ||
1126 | dev->flags |= IFF_NOARP; | ||
1127 | |||
1128 | if (chan->common.usedby == API){ | ||
1129 | dev->mtu = X25_CHAN_MTU+sizeof(x25api_hdr_t); | ||
1130 | }else{ | ||
1131 | dev->mtu = card->wandev.mtu; | ||
1132 | } | ||
1133 | |||
1134 | dev->hard_header_len = X25_HRDHDR_SZ; /* media header length */ | ||
1135 | dev->addr_len = 2; /* hardware address length */ | ||
1136 | |||
1137 | if (!chan->common.svc){ | ||
1138 | *(unsigned short*)dev->dev_addr = htons(chan->common.lcn); | ||
1139 | } | ||
1140 | |||
1141 | /* Initialize hardware parameters (just for reference) */ | ||
1142 | dev->irq = wandev->irq; | ||
1143 | dev->dma = wandev->dma; | ||
1144 | dev->base_addr = wandev->ioport; | ||
1145 | dev->mem_start = (unsigned long)wandev->maddr; | ||
1146 | dev->mem_end = wandev->maddr + wandev->msize - 1; | ||
1147 | |||
1148 | /* Set transmit buffer queue length */ | ||
1149 | dev->tx_queue_len = 100; | ||
1150 | SET_MODULE_OWNER(dev); | ||
1151 | |||
1152 | /* FIXME Why are we doing this */ | ||
1153 | set_chan_state(dev, WAN_DISCONNECTED); | ||
1154 | return 0; | ||
1155 | } | ||
1156 | |||
1157 | |||
1158 | /*=================================================================== | ||
1159 | * Name: if_open(), Open/Bring up the Netowrk Interface | ||
1160 | * | ||
1161 | * Purpose: To bring up a network interface. | ||
1162 | * | ||
1163 | * Rationale: | ||
1164 | * | ||
1165 | * Description: Open network interface. | ||
1166 | * o prevent module from unloading by incrementing use count | ||
1167 | * o if link is disconnected then initiate connection | ||
1168 | * | ||
1169 | * Called by: Kernel (/usr/src/linux/net/core/dev.c) | ||
1170 | * (dev->open()) | ||
1171 | * | ||
1172 | * Assumptions: None | ||
1173 | * | ||
1174 | * Warnings: None | ||
1175 | * | ||
1176 | * Return: 0 Ok | ||
1177 | * <0 Failure: Interface will not come up. | ||
1178 | */ | ||
1179 | |||
1180 | static int if_open(struct net_device* dev) | ||
1181 | { | ||
1182 | x25_channel_t* chan = dev->priv; | ||
1183 | sdla_t* card = chan->card; | ||
1184 | struct timeval tv; | ||
1185 | unsigned long smp_flags; | ||
1186 | |||
1187 | if (netif_running(dev)) | ||
1188 | return -EBUSY; | ||
1189 | |||
1190 | chan->tq_working = 0; | ||
1191 | |||
1192 | /* Initialize the workqueue */ | ||
1193 | INIT_WORK(&chan->common.wanpipe_work, (void *)x25api_bh, dev); | ||
1194 | |||
1195 | /* Allocate and initialize BH circular buffer */ | ||
1196 | /* Add 1 to MAX_BH_BUFF so we don't have test with (MAX_BH_BUFF-1) */ | ||
1197 | chan->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC); | ||
1198 | |||
1199 | if (chan->bh_head == NULL){ | ||
1200 | printk(KERN_INFO "%s: ERROR, failed to allocate memory ! BH_BUFFERS !\n", | ||
1201 | card->devname); | ||
1202 | |||
1203 | return -ENOBUFS; | ||
1204 | } | ||
1205 | memset(chan->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1))); | ||
1206 | atomic_set(&chan->bh_buff_used, 0); | ||
1207 | |||
1208 | /* Increment the number of interfaces */ | ||
1209 | ++card->u.x.no_dev; | ||
1210 | |||
1211 | wanpipe_open(card); | ||
1212 | |||
1213 | /* LAPB protocol only uses one interface, thus | ||
1214 | * start the protocol after it comes up. */ | ||
1215 | if (card->u.x.LAPB_hdlc){ | ||
1216 | if (card->open_cnt == 1){ | ||
1217 | TX25Status* status = card->flags; | ||
1218 | S508_S514_lock(card, &smp_flags); | ||
1219 | x25_set_intr_mode(card, INTR_ON_TIMER); | ||
1220 | status->imask &= ~INTR_ON_TIMER; | ||
1221 | S508_S514_unlock(card, &smp_flags); | ||
1222 | } | ||
1223 | }else{ | ||
1224 | /* X25 can have multiple interfaces thus, start the | ||
1225 | * protocol once all interfaces are up */ | ||
1226 | |||
1227 | //FIXME: There is a bug here. If interface is | ||
1228 | //brought down and up, it will try to enable comm. | ||
1229 | if (card->open_cnt == card->u.x.num_of_ch){ | ||
1230 | |||
1231 | S508_S514_lock(card, &smp_flags); | ||
1232 | connect(card); | ||
1233 | S508_S514_unlock(card, &smp_flags); | ||
1234 | |||
1235 | mod_timer(&card->u.x.x25_timer, jiffies + HZ); | ||
1236 | } | ||
1237 | } | ||
1238 | /* Device is not up until the we are in connected state */ | ||
1239 | do_gettimeofday( &tv ); | ||
1240 | chan->router_start_time = tv.tv_sec; | ||
1241 | |||
1242 | netif_start_queue(dev); | ||
1243 | |||
1244 | return 0; | ||
1245 | } | ||
1246 | |||
1247 | /*=================================================================== | ||
1248 | * Name: if_close(), Close/Bring down the Netowrk Interface | ||
1249 | * | ||
1250 | * Purpose: To bring down a network interface. | ||
1251 | * | ||
1252 | * Rationale: | ||
1253 | * | ||
1254 | * Description: Close network interface. | ||
1255 | * o decrement use module use count | ||
1256 | * | ||
1257 | * Called by: Kernel (/usr/src/linux/net/core/dev.c) | ||
1258 | * (dev->close()) | ||
1259 | * ifconfig <name> down: will trigger the kernel | ||
1260 | * which will call this function. | ||
1261 | * | ||
1262 | * Assumptions: None | ||
1263 | * | ||
1264 | * Warnings: None | ||
1265 | * | ||
1266 | * Return: 0 Ok | ||
1267 | * <0 Failure: Interface will not exit properly. | ||
1268 | */ | ||
1269 | static int if_close(struct net_device* dev) | ||
1270 | { | ||
1271 | x25_channel_t* chan = dev->priv; | ||
1272 | sdla_t* card = chan->card; | ||
1273 | unsigned long smp_flags; | ||
1274 | |||
1275 | netif_stop_queue(dev); | ||
1276 | |||
1277 | if ((chan->common.state == WAN_CONNECTED) || | ||
1278 | (chan->common.state == WAN_CONNECTING)){ | ||
1279 | S508_S514_lock(card, &smp_flags); | ||
1280 | chan_disc(dev); | ||
1281 | S508_S514_unlock(card, &smp_flags); | ||
1282 | } | ||
1283 | |||
1284 | wanpipe_close(card); | ||
1285 | |||
1286 | S508_S514_lock(card, &smp_flags); | ||
1287 | if (chan->bh_head){ | ||
1288 | int i; | ||
1289 | struct sk_buff *skb; | ||
1290 | |||
1291 | for (i=0; i<(MAX_BH_BUFF+1); i++){ | ||
1292 | skb = ((bh_data_t *)&chan->bh_head[i])->skb; | ||
1293 | if (skb != NULL){ | ||
1294 | dev_kfree_skb_any(skb); | ||
1295 | } | ||
1296 | } | ||
1297 | kfree(chan->bh_head); | ||
1298 | chan->bh_head=NULL; | ||
1299 | } | ||
1300 | S508_S514_unlock(card, &smp_flags); | ||
1301 | |||
1302 | /* If this is the last close, disconnect physical link */ | ||
1303 | if (!card->open_cnt){ | ||
1304 | S508_S514_lock(card, &smp_flags); | ||
1305 | disconnect(card); | ||
1306 | x25_set_intr_mode(card, 0); | ||
1307 | S508_S514_unlock(card, &smp_flags); | ||
1308 | } | ||
1309 | |||
1310 | /* Decrement the number of interfaces */ | ||
1311 | --card->u.x.no_dev; | ||
1312 | return 0; | ||
1313 | } | ||
1314 | |||
1315 | /*====================================================================== | ||
1316 | * Build media header. | ||
1317 | * o encapsulate packet according to encapsulation type. | ||
1318 | * | ||
1319 | * The trick here is to put packet type (Ethertype) into 'protocol' | ||
1320 | * field of the socket buffer, so that we don't forget it. | ||
1321 | * If encapsulation fails, set skb->protocol to 0 and discard | ||
1322 | * packet later. | ||
1323 | * | ||
1324 | * Return: media header length. | ||
1325 | *======================================================================*/ | ||
1326 | |||
1327 | static int if_header(struct sk_buff* skb, struct net_device* dev, | ||
1328 | unsigned short type, void* daddr, void* saddr, | ||
1329 | unsigned len) | ||
1330 | { | ||
1331 | x25_channel_t* chan = dev->priv; | ||
1332 | int hdr_len = dev->hard_header_len; | ||
1333 | |||
1334 | skb->protocol = htons(type); | ||
1335 | if (!chan->protocol){ | ||
1336 | hdr_len = wanrouter_encapsulate(skb, dev, type); | ||
1337 | if (hdr_len < 0){ | ||
1338 | hdr_len = 0; | ||
1339 | skb->protocol = htons(0); | ||
1340 | } | ||
1341 | } | ||
1342 | return hdr_len; | ||
1343 | } | ||
1344 | |||
1345 | /*=============================================================== | ||
1346 | * Re-build media header. | ||
1347 | * | ||
1348 | * Return: 1 physical address resolved. | ||
1349 | * 0 physical address not resolved | ||
1350 | *==============================================================*/ | ||
1351 | |||
1352 | static int if_rebuild_hdr (struct sk_buff* skb) | ||
1353 | { | ||
1354 | struct net_device *dev = skb->dev; | ||
1355 | x25_channel_t* chan = dev->priv; | ||
1356 | sdla_t* card = chan->card; | ||
1357 | |||
1358 | printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n", | ||
1359 | card->devname, dev->name); | ||
1360 | return 1; | ||
1361 | } | ||
1362 | |||
1363 | |||
1364 | /*============================================================================ | ||
1365 | * Handle transmit timeout event from netif watchdog | ||
1366 | */ | ||
1367 | static void if_tx_timeout(struct net_device *dev) | ||
1368 | { | ||
1369 | x25_channel_t* chan = dev->priv; | ||
1370 | sdla_t *card = chan->card; | ||
1371 | |||
1372 | /* If our device stays busy for at least 5 seconds then we will | ||
1373 | * kick start the device by making dev->tbusy = 0. We expect | ||
1374 | * that our device never stays busy more than 5 seconds. So this | ||
1375 | * is only used as a last resort. | ||
1376 | */ | ||
1377 | |||
1378 | ++chan->if_send_stat.if_send_tbusy_timeout; | ||
1379 | printk (KERN_INFO "%s: Transmit timed out on %s\n", | ||
1380 | card->devname, dev->name); | ||
1381 | netif_wake_queue (dev); | ||
1382 | } | ||
1383 | |||
1384 | |||
1385 | /*========================================================================= | ||
1386 | * Send a packet on a network interface. | ||
1387 | * o set tbusy flag (marks start of the transmission). | ||
1388 | * o check link state. If link is not up, then drop the packet. | ||
1389 | * o check channel status. If it's down then initiate a call. | ||
1390 | * o pass a packet to corresponding WAN device. | ||
1391 | * o free socket buffer | ||
1392 | * | ||
1393 | * Return: 0 complete (socket buffer must be freed) | ||
1394 | * non-0 packet may be re-transmitted (tbusy must be set) | ||
1395 | * | ||
1396 | * Notes: | ||
1397 | * 1. This routine is called either by the protocol stack or by the "net | ||
1398 | * bottom half" (with interrupts enabled). | ||
1399 | * 2. Setting tbusy flag will inhibit further transmit requests from the | ||
1400 | * protocol stack and can be used for flow control with protocol layer. | ||
1401 | * | ||
1402 | *========================================================================*/ | ||
1403 | |||
1404 | static int if_send(struct sk_buff* skb, struct net_device* dev) | ||
1405 | { | ||
1406 | x25_channel_t* chan = dev->priv; | ||
1407 | sdla_t* card = chan->card; | ||
1408 | TX25Status* status = card->flags; | ||
1409 | int udp_type; | ||
1410 | unsigned long smp_flags=0; | ||
1411 | |||
1412 | ++chan->if_send_stat.if_send_entry; | ||
1413 | |||
1414 | netif_stop_queue(dev); | ||
1415 | |||
1416 | /* No need to check frame length, since socket code | ||
1417 | * will perform the check for us */ | ||
1418 | |||
1419 | chan->tick_counter = jiffies; | ||
1420 | |||
1421 | /* Critical region starts here */ | ||
1422 | S508_S514_lock(card, &smp_flags); | ||
1423 | |||
1424 | if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){ | ||
1425 | printk(KERN_INFO "Hit critical in if_send()! %lx\n",card->wandev.critical); | ||
1426 | goto if_send_crit_exit; | ||
1427 | } | ||
1428 | |||
1429 | udp_type = udp_pkt_type(skb, card); | ||
1430 | |||
1431 | if(udp_type != UDP_INVALID_TYPE) { | ||
1432 | |||
1433 | if(store_udp_mgmt_pkt(udp_type, UDP_PKT_FRM_STACK, card, dev, skb, | ||
1434 | chan->common.lcn)) { | ||
1435 | |||
1436 | status->imask |= INTR_ON_TIMER; | ||
1437 | if (udp_type == UDP_XPIPE_TYPE){ | ||
1438 | chan->if_send_stat.if_send_PIPE_request++; | ||
1439 | } | ||
1440 | } | ||
1441 | netif_start_queue(dev); | ||
1442 | clear_bit(SEND_CRIT,(void*)&card->wandev.critical); | ||
1443 | S508_S514_unlock(card, &smp_flags); | ||
1444 | return 0; | ||
1445 | } | ||
1446 | |||
1447 | if (chan->transmit_length){ | ||
1448 | //FIXME: This check doesn't make sense any more | ||
1449 | if (chan->common.state != WAN_CONNECTED){ | ||
1450 | chan->transmit_length=0; | ||
1451 | atomic_set(&chan->common.driver_busy,0); | ||
1452 | }else{ | ||
1453 | netif_stop_queue(dev); | ||
1454 | ++card->u.x.tx_interrupts_pending; | ||
1455 | status->imask |= INTR_ON_TX_FRAME; | ||
1456 | clear_bit(SEND_CRIT,(void*)&card->wandev.critical); | ||
1457 | S508_S514_unlock(card, &smp_flags); | ||
1458 | return 1; | ||
1459 | } | ||
1460 | } | ||
1461 | |||
1462 | if (card->wandev.state != WAN_CONNECTED){ | ||
1463 | ++chan->ifstats.tx_dropped; | ||
1464 | ++card->wandev.stats.tx_dropped; | ||
1465 | ++chan->if_send_stat.if_send_wan_disconnected; | ||
1466 | |||
1467 | }else if ( chan->protocol && (chan->protocol != skb->protocol)){ | ||
1468 | printk(KERN_INFO | ||
1469 | "%s: unsupported Ethertype 0x%04X on interface %s!\n", | ||
1470 | chan->name, htons(skb->protocol), dev->name); | ||
1471 | |||
1472 | printk(KERN_INFO "PROTO %Xn", htons(chan->protocol)); | ||
1473 | ++chan->ifstats.tx_errors; | ||
1474 | ++chan->ifstats.tx_dropped; | ||
1475 | ++card->wandev.stats.tx_dropped; | ||
1476 | ++chan->if_send_stat.if_send_protocol_error; | ||
1477 | |||
1478 | }else switch (chan->common.state){ | ||
1479 | |||
1480 | case WAN_DISCONNECTED: | ||
1481 | /* Try to establish connection. If succeded, then start | ||
1482 | * transmission, else drop a packet. | ||
1483 | */ | ||
1484 | if (chan->common.usedby == API){ | ||
1485 | ++chan->ifstats.tx_dropped; | ||
1486 | ++card->wandev.stats.tx_dropped; | ||
1487 | break; | ||
1488 | }else{ | ||
1489 | if (chan_connect(dev) != 0){ | ||
1490 | ++chan->ifstats.tx_dropped; | ||
1491 | ++card->wandev.stats.tx_dropped; | ||
1492 | break; | ||
1493 | } | ||
1494 | } | ||
1495 | /* fall through */ | ||
1496 | |||
1497 | case WAN_CONNECTED: | ||
1498 | if( skb->protocol == htons(ETH_P_IPX)) { | ||
1499 | if(chan->enable_IPX) { | ||
1500 | switch_net_numbers( skb->data, | ||
1501 | chan->network_number, 0); | ||
1502 | } else { | ||
1503 | ++card->wandev.stats.tx_dropped; | ||
1504 | ++chan->ifstats.tx_dropped; | ||
1505 | ++chan->if_send_stat.if_send_protocol_error; | ||
1506 | goto if_send_crit_exit; | ||
1507 | } | ||
1508 | } | ||
1509 | /* We never drop here, if cannot send than, copy | ||
1510 | * a packet into a transmit buffer | ||
1511 | */ | ||
1512 | chan_send(dev, skb->data, skb->len, 0); | ||
1513 | break; | ||
1514 | |||
1515 | default: | ||
1516 | ++chan->ifstats.tx_dropped; | ||
1517 | ++card->wandev.stats.tx_dropped; | ||
1518 | break; | ||
1519 | } | ||
1520 | |||
1521 | |||
1522 | if_send_crit_exit: | ||
1523 | |||
1524 | dev_kfree_skb_any(skb); | ||
1525 | |||
1526 | netif_start_queue(dev); | ||
1527 | clear_bit(SEND_CRIT,(void*)&card->wandev.critical); | ||
1528 | S508_S514_unlock(card, &smp_flags); | ||
1529 | return 0; | ||
1530 | } | ||
1531 | |||
1532 | /*============================================================================ | ||
1533 | * Setup so that a frame can be transmitted on the occurrence of a transmit | ||
1534 | * interrupt. | ||
1535 | *===========================================================================*/ | ||
1536 | |||
1537 | static void setup_for_delayed_transmit(struct net_device* dev, void* buf, | ||
1538 | unsigned len) | ||
1539 | { | ||
1540 | x25_channel_t* chan = dev->priv; | ||
1541 | sdla_t* card = chan->card; | ||
1542 | TX25Status* status = card->flags; | ||
1543 | |||
1544 | ++chan->if_send_stat.if_send_adptr_bfrs_full; | ||
1545 | |||
1546 | if(chan->transmit_length) { | ||
1547 | printk(KERN_INFO "%s: Error, transmit length set in delayed transmit!\n", | ||
1548 | card->devname); | ||
1549 | return; | ||
1550 | } | ||
1551 | |||
1552 | if (chan->common.usedby == API){ | ||
1553 | if (len > X25_CHAN_MTU+sizeof(x25api_hdr_t)) { | ||
1554 | ++chan->ifstats.tx_dropped; | ||
1555 | ++card->wandev.stats.tx_dropped; | ||
1556 | printk(KERN_INFO "%s: Length is too big for delayed transmit\n", | ||
1557 | card->devname); | ||
1558 | return; | ||
1559 | } | ||
1560 | }else{ | ||
1561 | if (len > X25_MAX_DATA) { | ||
1562 | ++chan->ifstats.tx_dropped; | ||
1563 | ++card->wandev.stats.tx_dropped; | ||
1564 | printk(KERN_INFO "%s: Length is too big for delayed transmit\n", | ||
1565 | card->devname); | ||
1566 | return; | ||
1567 | } | ||
1568 | } | ||
1569 | |||
1570 | chan->transmit_length = len; | ||
1571 | atomic_set(&chan->common.driver_busy,1); | ||
1572 | memcpy(chan->transmit_buffer, buf, len); | ||
1573 | |||
1574 | ++chan->if_send_stat.if_send_tx_int_enabled; | ||
1575 | |||
1576 | /* Enable Transmit Interrupt */ | ||
1577 | ++card->u.x.tx_interrupts_pending; | ||
1578 | status->imask |= INTR_ON_TX_FRAME; | ||
1579 | } | ||
1580 | |||
1581 | |||
1582 | /*=============================================================== | ||
1583 | * net_device_stats | ||
1584 | * | ||
1585 | * Get ethernet-style interface statistics. | ||
1586 | * Return a pointer to struct enet_statistics. | ||
1587 | * | ||
1588 | *==============================================================*/ | ||
1589 | static struct net_device_stats *if_stats(struct net_device* dev) | ||
1590 | { | ||
1591 | x25_channel_t *chan = dev->priv; | ||
1592 | |||
1593 | if(chan == NULL) | ||
1594 | return NULL; | ||
1595 | |||
1596 | return &chan->ifstats; | ||
1597 | } | ||
1598 | |||
1599 | |||
1600 | /* | ||
1601 | * Interrupt Handlers | ||
1602 | */ | ||
1603 | |||
1604 | /* | ||
1605 | * X.25 Interrupt Service Routine. | ||
1606 | */ | ||
1607 | |||
1608 | static void wpx_isr (sdla_t* card) | ||
1609 | { | ||
1610 | TX25Status* status = card->flags; | ||
1611 | |||
1612 | card->in_isr = 1; | ||
1613 | ++card->statistics.isr_entry; | ||
1614 | |||
1615 | if (test_bit(PERI_CRIT,(void*)&card->wandev.critical)){ | ||
1616 | card->in_isr=0; | ||
1617 | status->iflags = 0; | ||
1618 | return; | ||
1619 | } | ||
1620 | |||
1621 | if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)){ | ||
1622 | |||
1623 | printk(KERN_INFO "%s: wpx_isr: wandev.critical set to 0x%02lx, int type = 0x%02x\n", | ||
1624 | card->devname, card->wandev.critical, status->iflags); | ||
1625 | card->in_isr = 0; | ||
1626 | status->iflags = 0; | ||
1627 | return; | ||
1628 | } | ||
1629 | |||
1630 | /* For all interrupts set the critical flag to CRITICAL_RX_INTR. | ||
1631 | * If the if_send routine is called with this flag set it will set | ||
1632 | * the enable transmit flag to 1. (for a delayed interrupt) | ||
1633 | */ | ||
1634 | switch (status->iflags){ | ||
1635 | |||
1636 | case RX_INTR_PENDING: /* receive interrupt */ | ||
1637 | rx_intr(card); | ||
1638 | break; | ||
1639 | |||
1640 | case TX_INTR_PENDING: /* transmit interrupt */ | ||
1641 | tx_intr(card); | ||
1642 | break; | ||
1643 | |||
1644 | case MODEM_INTR_PENDING: /* modem status interrupt */ | ||
1645 | status_intr(card); | ||
1646 | break; | ||
1647 | |||
1648 | case X25_ASY_TRANS_INTR_PENDING: /* network event interrupt */ | ||
1649 | event_intr(card); | ||
1650 | break; | ||
1651 | |||
1652 | case TIMER_INTR_PENDING: | ||
1653 | timer_intr(card); | ||
1654 | break; | ||
1655 | |||
1656 | default: /* unwanted interrupt */ | ||
1657 | spur_intr(card); | ||
1658 | } | ||
1659 | |||
1660 | card->in_isr = 0; | ||
1661 | status->iflags = 0; /* clear interrupt condition */ | ||
1662 | } | ||
1663 | |||
1664 | /* | ||
1665 | * Receive interrupt handler. | ||
1666 | * This routine handles fragmented IP packets using M-bit according to the | ||
1667 | * RFC1356. | ||
1668 | * o map ligical channel number to network interface. | ||
1669 | * o allocate socket buffer or append received packet to the existing one. | ||
1670 | * o if M-bit is reset (i.e. it's the last packet in a sequence) then | ||
1671 | * decapsulate packet and pass socket buffer to the protocol stack. | ||
1672 | * | ||
1673 | * Notes: | ||
1674 | * 1. When allocating a socket buffer, if M-bit is set then more data is | ||
1675 | * coming and we have to allocate buffer for the maximum IP packet size | ||
1676 | * expected on this channel. | ||
1677 | * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no | ||
1678 | * socket buffers available) the whole packet sequence must be discarded. | ||
1679 | */ | ||
1680 | |||
1681 | static void rx_intr (sdla_t* card) | ||
1682 | { | ||
1683 | TX25Mbox* rxmb = card->rxmb; | ||
1684 | unsigned lcn = rxmb->cmd.lcn; | ||
1685 | struct net_device* dev = find_channel(card,lcn); | ||
1686 | x25_channel_t* chan; | ||
1687 | struct sk_buff* skb=NULL; | ||
1688 | |||
1689 | if (dev == NULL){ | ||
1690 | /* Invalid channel, discard packet */ | ||
1691 | printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n", | ||
1692 | card->devname, lcn); | ||
1693 | return; | ||
1694 | } | ||
1695 | |||
1696 | chan = dev->priv; | ||
1697 | chan->i_timeout_sofar = jiffies; | ||
1698 | |||
1699 | |||
1700 | /* Copy the data from the board, into an | ||
1701 | * skb buffer | ||
1702 | */ | ||
1703 | if (wanpipe_pull_data_in_skb(card,dev,&skb)){ | ||
1704 | ++chan->ifstats.rx_dropped; | ||
1705 | ++card->wandev.stats.rx_dropped; | ||
1706 | ++chan->rx_intr_stat.rx_intr_no_socket; | ||
1707 | ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; | ||
1708 | return; | ||
1709 | } | ||
1710 | |||
1711 | dev->last_rx = jiffies; /* timestamp */ | ||
1712 | |||
1713 | |||
1714 | /* ------------ API ----------------*/ | ||
1715 | |||
1716 | if (chan->common.usedby == API){ | ||
1717 | |||
1718 | if (bh_enqueue(dev, skb)){ | ||
1719 | ++chan->ifstats.rx_dropped; | ||
1720 | ++card->wandev.stats.rx_dropped; | ||
1721 | ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; | ||
1722 | dev_kfree_skb_any(skb); | ||
1723 | return; | ||
1724 | } | ||
1725 | |||
1726 | ++chan->ifstats.rx_packets; | ||
1727 | chan->ifstats.rx_bytes += skb->len; | ||
1728 | |||
1729 | |||
1730 | chan->rx_skb = NULL; | ||
1731 | if (!test_and_set_bit(0, &chan->tq_working)){ | ||
1732 | wanpipe_queue_work(&chan->common.wanpipe_work); | ||
1733 | } | ||
1734 | return; | ||
1735 | } | ||
1736 | |||
1737 | |||
1738 | /* ------------- WANPIPE -------------------*/ | ||
1739 | |||
1740 | /* set rx_skb to NULL so we won't access it later when kernel already owns it */ | ||
1741 | chan->rx_skb=NULL; | ||
1742 | |||
1743 | /* Decapsulate packet, if necessary */ | ||
1744 | if (!skb->protocol && !wanrouter_type_trans(skb, dev)){ | ||
1745 | /* can't decapsulate packet */ | ||
1746 | dev_kfree_skb_any(skb); | ||
1747 | ++chan->ifstats.rx_errors; | ||
1748 | ++chan->ifstats.rx_dropped; | ||
1749 | ++card->wandev.stats.rx_dropped; | ||
1750 | ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; | ||
1751 | |||
1752 | }else{ | ||
1753 | if( handle_IPXWAN(skb->data, chan->name, | ||
1754 | chan->enable_IPX, chan->network_number, | ||
1755 | skb->protocol)){ | ||
1756 | |||
1757 | if( chan->enable_IPX ){ | ||
1758 | if(chan_send(dev, skb->data, skb->len,0)){ | ||
1759 | chan->tx_skb = skb; | ||
1760 | }else{ | ||
1761 | dev_kfree_skb_any(skb); | ||
1762 | ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; | ||
1763 | } | ||
1764 | }else{ | ||
1765 | /* increment IPX packet dropped statistic */ | ||
1766 | ++chan->ifstats.rx_dropped; | ||
1767 | ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; | ||
1768 | } | ||
1769 | }else{ | ||
1770 | skb->mac.raw = skb->data; | ||
1771 | chan->ifstats.rx_bytes += skb->len; | ||
1772 | ++chan->ifstats.rx_packets; | ||
1773 | ++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack; | ||
1774 | netif_rx(skb); | ||
1775 | } | ||
1776 | } | ||
1777 | |||
1778 | return; | ||
1779 | } | ||
1780 | |||
1781 | |||
1782 | static int wanpipe_pull_data_in_skb(sdla_t *card, struct net_device *dev, | ||
1783 | struct sk_buff **skb) | ||
1784 | { | ||
1785 | void *bufptr; | ||
1786 | TX25Mbox* rxmb = card->rxmb; | ||
1787 | unsigned len = rxmb->cmd.length; /* packet length */ | ||
1788 | unsigned qdm = rxmb->cmd.qdm; /* Q,D and M bits */ | ||
1789 | x25_channel_t *chan = dev->priv; | ||
1790 | struct sk_buff *new_skb = *skb; | ||
1791 | |||
1792 | if (chan->common.usedby == WANPIPE){ | ||
1793 | if (chan->drop_sequence){ | ||
1794 | if (!(qdm & 0x01)){ | ||
1795 | chan->drop_sequence = 0; | ||
1796 | } | ||
1797 | return 1; | ||
1798 | } | ||
1799 | new_skb = chan->rx_skb; | ||
1800 | }else{ | ||
1801 | /* Add on the API header to the received | ||
1802 | * data | ||
1803 | */ | ||
1804 | len += sizeof(x25api_hdr_t); | ||
1805 | } | ||
1806 | |||
1807 | if (new_skb == NULL){ | ||
1808 | int bufsize; | ||
1809 | |||
1810 | if (chan->common.usedby == WANPIPE){ | ||
1811 | bufsize = (qdm & 0x01) ? dev->mtu : len; | ||
1812 | }else{ | ||
1813 | bufsize = len; | ||
1814 | } | ||
1815 | |||
1816 | /* Allocate new socket buffer */ | ||
1817 | new_skb = dev_alloc_skb(bufsize + dev->hard_header_len); | ||
1818 | if (new_skb == NULL){ | ||
1819 | printk(KERN_INFO "%s: no socket buffers available!\n", | ||
1820 | card->devname); | ||
1821 | chan->drop_sequence = 1; /* set flag */ | ||
1822 | ++chan->ifstats.rx_dropped; | ||
1823 | return 1; | ||
1824 | } | ||
1825 | } | ||
1826 | |||
1827 | if (skb_tailroom(new_skb) < len){ | ||
1828 | /* No room for the packet. Call off the whole thing! */ | ||
1829 | dev_kfree_skb_any(new_skb); | ||
1830 | if (chan->common.usedby == WANPIPE){ | ||
1831 | chan->rx_skb = NULL; | ||
1832 | if (qdm & 0x01){ | ||
1833 | chan->drop_sequence = 1; | ||
1834 | } | ||
1835 | } | ||
1836 | |||
1837 | printk(KERN_INFO "%s: unexpectedly long packet sequence " | ||
1838 | "on interface %s!\n", card->devname, dev->name); | ||
1839 | ++chan->ifstats.rx_length_errors; | ||
1840 | return 1; | ||
1841 | } | ||
1842 | |||
1843 | bufptr = skb_put(new_skb,len); | ||
1844 | |||
1845 | |||
1846 | if (chan->common.usedby == API){ | ||
1847 | /* Fill in the x25api header | ||
1848 | */ | ||
1849 | x25api_t * api_data = (x25api_t*)bufptr; | ||
1850 | api_data->hdr.qdm = rxmb->cmd.qdm; | ||
1851 | api_data->hdr.cause = rxmb->cmd.cause; | ||
1852 | api_data->hdr.diagn = rxmb->cmd.diagn; | ||
1853 | api_data->hdr.length = rxmb->cmd.length; | ||
1854 | memcpy(api_data->data, rxmb->data, rxmb->cmd.length); | ||
1855 | }else{ | ||
1856 | memcpy(bufptr, rxmb->data, len); | ||
1857 | } | ||
1858 | |||
1859 | new_skb->dev = dev; | ||
1860 | |||
1861 | if (chan->common.usedby == API){ | ||
1862 | new_skb->mac.raw = new_skb->data; | ||
1863 | new_skb->protocol = htons(X25_PROT); | ||
1864 | new_skb->pkt_type = WAN_PACKET_DATA; | ||
1865 | }else{ | ||
1866 | new_skb->protocol = chan->protocol; | ||
1867 | chan->rx_skb = new_skb; | ||
1868 | } | ||
1869 | |||
1870 | /* If qdm bit is set, more data is coming | ||
1871 | * thus, exit and wait for more data before | ||
1872 | * sending the packet up. (Used by router only) | ||
1873 | */ | ||
1874 | if ((qdm & 0x01) && (chan->common.usedby == WANPIPE)) | ||
1875 | return 1; | ||
1876 | |||
1877 | *skb = new_skb; | ||
1878 | |||
1879 | return 0; | ||
1880 | } | ||
1881 | |||
1882 | /*=============================================================== | ||
1883 | * tx_intr | ||
1884 | * | ||
1885 | * Transmit interrupt handler. | ||
1886 | * For each dev, check that there is something to send. | ||
1887 | * If data available, transmit. | ||
1888 | * | ||
1889 | *===============================================================*/ | ||
1890 | |||
1891 | static void tx_intr (sdla_t* card) | ||
1892 | { | ||
1893 | struct net_device *dev; | ||
1894 | TX25Status* status = card->flags; | ||
1895 | unsigned char more_to_tx=0; | ||
1896 | x25_channel_t *chan=NULL; | ||
1897 | int i=0; | ||
1898 | |||
1899 | if (card->u.x.tx_dev == NULL){ | ||
1900 | card->u.x.tx_dev = card->wandev.dev; | ||
1901 | } | ||
1902 | |||
1903 | dev = card->u.x.tx_dev; | ||
1904 | |||
1905 | for (;;){ | ||
1906 | |||
1907 | chan = dev->priv; | ||
1908 | if (chan->transmit_length){ | ||
1909 | /* Device was set to transmit, check if the TX | ||
1910 | * buffers are available | ||
1911 | */ | ||
1912 | if (chan->common.state != WAN_CONNECTED){ | ||
1913 | chan->transmit_length = 0; | ||
1914 | atomic_set(&chan->common.driver_busy,0); | ||
1915 | chan->tx_offset=0; | ||
1916 | if (netif_queue_stopped(dev)){ | ||
1917 | if (chan->common.usedby == API){ | ||
1918 | netif_start_queue(dev); | ||
1919 | wakeup_sk_bh(dev); | ||
1920 | }else{ | ||
1921 | netif_wake_queue(dev); | ||
1922 | } | ||
1923 | } | ||
1924 | dev = move_dev_to_next(card,dev); | ||
1925 | break; | ||
1926 | } | ||
1927 | |||
1928 | if ((status->cflags[chan->ch_idx] & 0x40 || card->u.x.LAPB_hdlc) && | ||
1929 | (*card->u.x.hdlc_buf_status & 0x40) ){ | ||
1930 | /* Tx buffer available, we can send */ | ||
1931 | |||
1932 | if (tx_intr_send(card, dev)){ | ||
1933 | more_to_tx=1; | ||
1934 | } | ||
1935 | |||
1936 | /* If more than one interface present, move the | ||
1937 | * device pointer to the next interface, so on the | ||
1938 | * next TX interrupt we will try sending from it. | ||
1939 | */ | ||
1940 | dev = move_dev_to_next(card,dev); | ||
1941 | break; | ||
1942 | }else{ | ||
1943 | /* Tx buffers not available, but device set | ||
1944 | * the TX interrupt. Set more_to_tx and try | ||
1945 | * to transmit for other devices. | ||
1946 | */ | ||
1947 | more_to_tx=1; | ||
1948 | dev = move_dev_to_next(card,dev); | ||
1949 | } | ||
1950 | |||
1951 | }else{ | ||
1952 | /* This device was not set to transmit, | ||
1953 | * go to next | ||
1954 | */ | ||
1955 | dev = move_dev_to_next(card,dev); | ||
1956 | } | ||
1957 | |||
1958 | if (++i == card->u.x.no_dev){ | ||
1959 | if (!more_to_tx){ | ||
1960 | DBG_PRINTK(KERN_INFO "%s: Nothing to Send in TX INTR\n", | ||
1961 | card->devname); | ||
1962 | } | ||
1963 | break; | ||
1964 | } | ||
1965 | |||
1966 | } //End of FOR | ||
1967 | |||
1968 | card->u.x.tx_dev = dev; | ||
1969 | |||
1970 | if (!more_to_tx){ | ||
1971 | /* if any other interfaces have transmit interrupts pending, */ | ||
1972 | /* do not disable the global transmit interrupt */ | ||
1973 | if (!(--card->u.x.tx_interrupts_pending)){ | ||
1974 | status->imask &= ~INTR_ON_TX_FRAME; | ||
1975 | } | ||
1976 | } | ||
1977 | return; | ||
1978 | } | ||
1979 | |||
1980 | /*=============================================================== | ||
1981 | * move_dev_to_next | ||
1982 | * | ||
1983 | * | ||
1984 | *===============================================================*/ | ||
1985 | |||
1986 | |||
1987 | struct net_device *move_dev_to_next(sdla_t *card, struct net_device *dev) | ||
1988 | { | ||
1989 | if (card->u.x.no_dev != 1){ | ||
1990 | if (!*((struct net_device **)dev->priv)) | ||
1991 | return card->wandev.dev; | ||
1992 | else | ||
1993 | return *((struct net_device **)dev->priv); | ||
1994 | } | ||
1995 | return dev; | ||
1996 | } | ||
1997 | |||
1998 | /*=============================================================== | ||
1999 | * tx_intr_send | ||
2000 | * | ||
2001 | * | ||
2002 | *===============================================================*/ | ||
2003 | |||
2004 | static int tx_intr_send(sdla_t *card, struct net_device *dev) | ||
2005 | { | ||
2006 | x25_channel_t* chan = dev->priv; | ||
2007 | |||
2008 | if (chan_send (dev,chan->transmit_buffer,chan->transmit_length,1)){ | ||
2009 | |||
2010 | /* Packet was split up due to its size, do not disable | ||
2011 | * tx_intr | ||
2012 | */ | ||
2013 | return 1; | ||
2014 | } | ||
2015 | |||
2016 | chan->transmit_length=0; | ||
2017 | atomic_set(&chan->common.driver_busy,0); | ||
2018 | chan->tx_offset=0; | ||
2019 | |||
2020 | /* If we are in API mode, wakeup the | ||
2021 | * sock BH handler, not the NET_BH */ | ||
2022 | if (netif_queue_stopped(dev)){ | ||
2023 | if (chan->common.usedby == API){ | ||
2024 | netif_start_queue(dev); | ||
2025 | wakeup_sk_bh(dev); | ||
2026 | }else{ | ||
2027 | netif_wake_queue(dev); | ||
2028 | } | ||
2029 | } | ||
2030 | return 0; | ||
2031 | } | ||
2032 | |||
2033 | |||
2034 | /*=============================================================== | ||
2035 | * timer_intr | ||
2036 | * | ||
2037 | * Timer interrupt handler. | ||
2038 | * Check who called the timer interrupt and perform | ||
2039 | * action accordingly. | ||
2040 | * | ||
2041 | *===============================================================*/ | ||
2042 | |||
2043 | static void timer_intr (sdla_t *card) | ||
2044 | { | ||
2045 | TX25Status* status = card->flags; | ||
2046 | |||
2047 | if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC){ | ||
2048 | |||
2049 | if (timer_intr_cmd_exec(card) == 0){ | ||
2050 | card->u.x.timer_int_enabled &= | ||
2051 | ~TMR_INT_ENABLED_CMD_EXEC; | ||
2052 | } | ||
2053 | |||
2054 | }else if(card->u.x.timer_int_enabled & TMR_INT_ENABLED_UDP_PKT) { | ||
2055 | |||
2056 | if ((*card->u.x.hdlc_buf_status & 0x40) && | ||
2057 | card->u.x.udp_type == UDP_XPIPE_TYPE){ | ||
2058 | |||
2059 | if(process_udp_mgmt_pkt(card)) { | ||
2060 | card->u.x.timer_int_enabled &= | ||
2061 | ~TMR_INT_ENABLED_UDP_PKT; | ||
2062 | } | ||
2063 | } | ||
2064 | |||
2065 | }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_ACTIVE) { | ||
2066 | |||
2067 | struct net_device *dev = card->u.x.poll_device; | ||
2068 | x25_channel_t *chan = NULL; | ||
2069 | |||
2070 | if (!dev){ | ||
2071 | card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE; | ||
2072 | return; | ||
2073 | } | ||
2074 | chan = dev->priv; | ||
2075 | |||
2076 | printk(KERN_INFO | ||
2077 | "%s: Closing down Idle link %s on LCN %d\n", | ||
2078 | card->devname,chan->name,chan->common.lcn); | ||
2079 | chan->i_timeout_sofar = jiffies; | ||
2080 | chan_disc(dev); | ||
2081 | card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_ACTIVE; | ||
2082 | card->u.x.poll_device=NULL; | ||
2083 | |||
2084 | }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_ON) { | ||
2085 | |||
2086 | wanpipe_set_state(card, WAN_CONNECTED); | ||
2087 | if (card->u.x.LAPB_hdlc){ | ||
2088 | struct net_device *dev = card->wandev.dev; | ||
2089 | set_chan_state(dev,WAN_CONNECTED); | ||
2090 | send_delayed_cmd_result(card,dev,card->mbox); | ||
2091 | } | ||
2092 | |||
2093 | /* 0x8F enable all interrupts */ | ||
2094 | x25_set_intr_mode(card, INTR_ON_RX_FRAME| | ||
2095 | INTR_ON_TX_FRAME| | ||
2096 | INTR_ON_MODEM_STATUS_CHANGE| | ||
2097 | //INTR_ON_COMMAND_COMPLETE| | ||
2098 | X25_ASY_TRANS_INTR_PENDING | | ||
2099 | INTR_ON_TIMER | | ||
2100 | DIRECT_RX_INTR_USAGE | ||
2101 | ); | ||
2102 | |||
2103 | status->imask &= ~INTR_ON_TX_FRAME; /* mask Tx interrupts */ | ||
2104 | card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_ON; | ||
2105 | |||
2106 | }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_CONNECT_OFF) { | ||
2107 | |||
2108 | //printk(KERN_INFO "Poll connect, Turning OFF\n"); | ||
2109 | disconnect(card); | ||
2110 | card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_CONNECT_OFF; | ||
2111 | |||
2112 | }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_POLL_DISCONNECT) { | ||
2113 | |||
2114 | //printk(KERN_INFO "POll disconnect, trying to connect\n"); | ||
2115 | connect(card); | ||
2116 | card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_POLL_DISCONNECT; | ||
2117 | |||
2118 | }else if (card->u.x.timer_int_enabled & TMR_INT_ENABLED_UPDATE){ | ||
2119 | |||
2120 | if (*card->u.x.hdlc_buf_status & 0x40){ | ||
2121 | x25_get_err_stats(card); | ||
2122 | x25_get_stats(card); | ||
2123 | card->u.x.timer_int_enabled &= ~TMR_INT_ENABLED_UPDATE; | ||
2124 | } | ||
2125 | } | ||
2126 | |||
2127 | if(!card->u.x.timer_int_enabled){ | ||
2128 | //printk(KERN_INFO "Turning Timer Off \n"); | ||
2129 | status->imask &= ~INTR_ON_TIMER; | ||
2130 | } | ||
2131 | } | ||
2132 | |||
2133 | /*==================================================================== | ||
2134 | * Modem status interrupt handler. | ||
2135 | *===================================================================*/ | ||
2136 | static void status_intr (sdla_t* card) | ||
2137 | { | ||
2138 | |||
2139 | /* Added to avoid Modem status message flooding */ | ||
2140 | static TX25ModemStatus last_stat; | ||
2141 | |||
2142 | TX25Mbox* mbox = card->mbox; | ||
2143 | TX25ModemStatus *modem_status; | ||
2144 | struct net_device *dev; | ||
2145 | x25_channel_t *chan; | ||
2146 | int err; | ||
2147 | |||
2148 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2149 | mbox->cmd.command = X25_READ_MODEM_STATUS; | ||
2150 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2151 | if (err){ | ||
2152 | x25_error(card, err, X25_READ_MODEM_STATUS, 0); | ||
2153 | }else{ | ||
2154 | |||
2155 | modem_status = (TX25ModemStatus*)mbox->data; | ||
2156 | |||
2157 | /* Check if the last status was the same | ||
2158 | * if it was, do NOT print message again */ | ||
2159 | |||
2160 | if (last_stat.status != modem_status->status){ | ||
2161 | |||
2162 | printk(KERN_INFO "%s: Modem Status Change: DCD=%s, CTS=%s\n", | ||
2163 | card->devname,DCD(modem_status->status),CTS(modem_status->status)); | ||
2164 | |||
2165 | last_stat.status = modem_status->status; | ||
2166 | |||
2167 | if (card->u.x.oob_on_modem){ | ||
2168 | |||
2169 | mbox->cmd.pktType = mbox->cmd.command; | ||
2170 | mbox->cmd.result = 0x08; | ||
2171 | |||
2172 | /* Send a OOB to all connected sockets */ | ||
2173 | for (dev = card->wandev.dev; dev; | ||
2174 | dev = *((struct net_device**)dev->priv)) { | ||
2175 | chan=dev->priv; | ||
2176 | if (chan->common.usedby == API){ | ||
2177 | send_oob_msg(card,dev,mbox); | ||
2178 | } | ||
2179 | } | ||
2180 | |||
2181 | /* The modem OOB message will probably kill the | ||
2182 | * the link. If we don't clear the flag here, | ||
2183 | * a deadlock could occur */ | ||
2184 | if (atomic_read(&card->u.x.command_busy)){ | ||
2185 | atomic_set(&card->u.x.command_busy,0); | ||
2186 | } | ||
2187 | } | ||
2188 | } | ||
2189 | } | ||
2190 | |||
2191 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2192 | mbox->cmd.command = X25_HDLC_LINK_STATUS; | ||
2193 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2194 | if (err){ | ||
2195 | x25_error(card, err, X25_HDLC_LINK_STATUS, 0); | ||
2196 | } | ||
2197 | |||
2198 | } | ||
2199 | |||
2200 | /*==================================================================== | ||
2201 | * Network event interrupt handler. | ||
2202 | *===================================================================*/ | ||
2203 | static void event_intr (sdla_t* card) | ||
2204 | { | ||
2205 | x25_fetch_events(card); | ||
2206 | } | ||
2207 | |||
2208 | /*==================================================================== | ||
2209 | * Spurious interrupt handler. | ||
2210 | * o print a warning | ||
2211 | * o | ||
2212 | *====================================================================*/ | ||
2213 | |||
2214 | static void spur_intr (sdla_t* card) | ||
2215 | { | ||
2216 | printk(KERN_INFO "%s: spurious interrupt!\n", card->devname); | ||
2217 | } | ||
2218 | |||
2219 | |||
2220 | /* | ||
2221 | * Background Polling Routines | ||
2222 | */ | ||
2223 | |||
2224 | /*==================================================================== | ||
2225 | * Main polling routine. | ||
2226 | * This routine is repeatedly called by the WANPIPE 'thread' to allow for | ||
2227 | * time-dependent housekeeping work. | ||
2228 | * | ||
2229 | * Notes: | ||
2230 | * 1. This routine may be called on interrupt context with all interrupts | ||
2231 | * enabled. Beware! | ||
2232 | *====================================================================*/ | ||
2233 | |||
2234 | static void wpx_poll (sdla_t *card) | ||
2235 | { | ||
2236 | if (!card->wandev.dev){ | ||
2237 | goto wpx_poll_exit; | ||
2238 | } | ||
2239 | |||
2240 | if (card->open_cnt != card->u.x.num_of_ch){ | ||
2241 | goto wpx_poll_exit; | ||
2242 | } | ||
2243 | |||
2244 | if (test_bit(PERI_CRIT,&card->wandev.critical)){ | ||
2245 | goto wpx_poll_exit; | ||
2246 | } | ||
2247 | |||
2248 | if (test_bit(SEND_CRIT,&card->wandev.critical)){ | ||
2249 | goto wpx_poll_exit; | ||
2250 | } | ||
2251 | |||
2252 | switch(card->wandev.state){ | ||
2253 | case WAN_CONNECTED: | ||
2254 | poll_active(card); | ||
2255 | break; | ||
2256 | |||
2257 | case WAN_CONNECTING: | ||
2258 | poll_connecting(card); | ||
2259 | break; | ||
2260 | |||
2261 | case WAN_DISCONNECTED: | ||
2262 | poll_disconnected(card); | ||
2263 | break; | ||
2264 | } | ||
2265 | |||
2266 | wpx_poll_exit: | ||
2267 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
2268 | return; | ||
2269 | } | ||
2270 | |||
2271 | static void trigger_x25_poll(sdla_t *card) | ||
2272 | { | ||
2273 | schedule_work(&card->u.x.x25_poll_work); | ||
2274 | } | ||
2275 | |||
2276 | /*==================================================================== | ||
2277 | * Handle physical link establishment phase. | ||
2278 | * o if connection timed out, disconnect the link. | ||
2279 | *===================================================================*/ | ||
2280 | |||
2281 | static void poll_connecting (sdla_t* card) | ||
2282 | { | ||
2283 | volatile TX25Status* status = card->flags; | ||
2284 | |||
2285 | if (status->gflags & X25_HDLC_ABM){ | ||
2286 | |||
2287 | timer_intr_exec (card, TMR_INT_ENABLED_POLL_CONNECT_ON); | ||
2288 | |||
2289 | }else if ((jiffies - card->state_tick) > CONNECT_TIMEOUT){ | ||
2290 | |||
2291 | timer_intr_exec (card, TMR_INT_ENABLED_POLL_CONNECT_OFF); | ||
2292 | |||
2293 | } | ||
2294 | } | ||
2295 | |||
2296 | /*==================================================================== | ||
2297 | * Handle physical link disconnected phase. | ||
2298 | * o if hold-down timeout has expired and there are open interfaces, | ||
2299 | * connect link. | ||
2300 | *===================================================================*/ | ||
2301 | |||
2302 | static void poll_disconnected (sdla_t* card) | ||
2303 | { | ||
2304 | struct net_device *dev; | ||
2305 | x25_channel_t *chan; | ||
2306 | TX25Status* status = card->flags; | ||
2307 | |||
2308 | if (!card->u.x.LAPB_hdlc && card->open_cnt && | ||
2309 | ((jiffies - card->state_tick) > HOLD_DOWN_TIME)){ | ||
2310 | timer_intr_exec(card, TMR_INT_ENABLED_POLL_DISCONNECT); | ||
2311 | } | ||
2312 | |||
2313 | |||
2314 | if ((dev=card->wandev.dev) == NULL) | ||
2315 | return; | ||
2316 | |||
2317 | if ((chan=dev->priv) == NULL) | ||
2318 | return; | ||
2319 | |||
2320 | if (chan->common.usedby == API && | ||
2321 | atomic_read(&chan->common.command) && | ||
2322 | card->u.x.LAPB_hdlc){ | ||
2323 | |||
2324 | if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC)) | ||
2325 | card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC; | ||
2326 | |||
2327 | if (!(status->imask & INTR_ON_TIMER)) | ||
2328 | status->imask |= INTR_ON_TIMER; | ||
2329 | } | ||
2330 | |||
2331 | } | ||
2332 | |||
2333 | /*==================================================================== | ||
2334 | * Handle active link phase. | ||
2335 | * o fetch X.25 asynchronous events. | ||
2336 | * o kick off transmission on all interfaces. | ||
2337 | *===================================================================*/ | ||
2338 | |||
2339 | static void poll_active (sdla_t* card) | ||
2340 | { | ||
2341 | struct net_device* dev; | ||
2342 | TX25Status* status = card->flags; | ||
2343 | |||
2344 | for (dev = card->wandev.dev; dev; | ||
2345 | dev = *((struct net_device **)dev->priv)){ | ||
2346 | x25_channel_t* chan = dev->priv; | ||
2347 | |||
2348 | /* If SVC has been idle long enough, close virtual circuit */ | ||
2349 | if ( chan->common.svc && | ||
2350 | chan->common.state == WAN_CONNECTED && | ||
2351 | chan->common.usedby == WANPIPE ){ | ||
2352 | |||
2353 | if( (jiffies - chan->i_timeout_sofar) / HZ > chan->idle_timeout ){ | ||
2354 | /* Close svc */ | ||
2355 | card->u.x.poll_device=dev; | ||
2356 | timer_intr_exec (card, TMR_INT_ENABLED_POLL_ACTIVE); | ||
2357 | } | ||
2358 | } | ||
2359 | |||
2360 | #ifdef PRINT_DEBUG | ||
2361 | chan->ifstats.tx_compressed = atomic_read(&chan->common.command); | ||
2362 | chan->ifstats.tx_errors = chan->common.state; | ||
2363 | chan->ifstats.rx_fifo_errors = atomic_read(&card->u.x.command_busy); | ||
2364 | ++chan->ifstats.tx_bytes; | ||
2365 | |||
2366 | chan->ifstats.rx_fifo_errors=atomic_read(&chan->common.disconnect); | ||
2367 | chan->ifstats.multicast=atomic_read(&chan->bh_buff_used); | ||
2368 | chan->ifstats.rx_length_errors=*card->u.x.hdlc_buf_status; | ||
2369 | #endif | ||
2370 | |||
2371 | if (chan->common.usedby == API && | ||
2372 | atomic_read(&chan->common.command) && | ||
2373 | !card->u.x.LAPB_hdlc){ | ||
2374 | |||
2375 | if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC)) | ||
2376 | card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC; | ||
2377 | |||
2378 | if (!(status->imask & INTR_ON_TIMER)) | ||
2379 | status->imask |= INTR_ON_TIMER; | ||
2380 | } | ||
2381 | |||
2382 | if ((chan->common.usedby == API) && | ||
2383 | atomic_read(&chan->common.disconnect)){ | ||
2384 | |||
2385 | if (chan->common.state == WAN_DISCONNECTED){ | ||
2386 | atomic_set(&chan->common.disconnect,0); | ||
2387 | return; | ||
2388 | } | ||
2389 | |||
2390 | atomic_set(&chan->common.command,X25_CLEAR_CALL); | ||
2391 | if (!(card->u.x.timer_int_enabled & TMR_INT_ENABLED_CMD_EXEC)) | ||
2392 | card->u.x.timer_int_enabled |= TMR_INT_ENABLED_CMD_EXEC; | ||
2393 | |||
2394 | if (!(status->imask & INTR_ON_TIMER)) | ||
2395 | status->imask |= INTR_ON_TIMER; | ||
2396 | } | ||
2397 | } | ||
2398 | } | ||
2399 | |||
2400 | static void timer_intr_exec(sdla_t *card, unsigned char TYPE) | ||
2401 | { | ||
2402 | TX25Status* status = card->flags; | ||
2403 | card->u.x.timer_int_enabled |= TYPE; | ||
2404 | if (!(status->imask & INTR_ON_TIMER)) | ||
2405 | status->imask |= INTR_ON_TIMER; | ||
2406 | } | ||
2407 | |||
2408 | |||
2409 | /*==================================================================== | ||
2410 | * SDLA Firmware-Specific Functions | ||
2411 | * | ||
2412 | * Almost all X.25 commands can unexpetedly fail due to so called 'X.25 | ||
2413 | * asynchronous events' such as restart, interrupt, incoming call request, | ||
2414 | * call clear request, etc. They can't be ignored and have to be delt with | ||
2415 | * immediately. To tackle with this problem we execute each interface | ||
2416 | * command in a loop until good return code is received or maximum number | ||
2417 | * of retries is reached. Each interface command returns non-zero return | ||
2418 | * code, an asynchronous event/error handler x25_error() is called. | ||
2419 | *====================================================================*/ | ||
2420 | |||
2421 | /*==================================================================== | ||
2422 | * Read X.25 firmware version. | ||
2423 | * Put code version as ASCII string in str. | ||
2424 | *===================================================================*/ | ||
2425 | |||
2426 | static int x25_get_version (sdla_t* card, char* str) | ||
2427 | { | ||
2428 | TX25Mbox* mbox = card->mbox; | ||
2429 | int retry = MAX_CMD_RETRY; | ||
2430 | int err; | ||
2431 | |||
2432 | do | ||
2433 | { | ||
2434 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2435 | mbox->cmd.command = X25_READ_CODE_VERSION; | ||
2436 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2437 | } while (err && retry-- && | ||
2438 | x25_error(card, err, X25_READ_CODE_VERSION, 0)); | ||
2439 | |||
2440 | if (!err && str) | ||
2441 | { | ||
2442 | int len = mbox->cmd.length; | ||
2443 | |||
2444 | memcpy(str, mbox->data, len); | ||
2445 | str[len] = '\0'; | ||
2446 | } | ||
2447 | return err; | ||
2448 | } | ||
2449 | |||
2450 | /*==================================================================== | ||
2451 | * Configure adapter. | ||
2452 | *===================================================================*/ | ||
2453 | |||
2454 | static int x25_configure (sdla_t* card, TX25Config* conf) | ||
2455 | { | ||
2456 | TX25Mbox* mbox = card->mbox; | ||
2457 | int retry = MAX_CMD_RETRY; | ||
2458 | int err; | ||
2459 | |||
2460 | do{ | ||
2461 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2462 | memcpy(mbox->data, (void*)conf, sizeof(TX25Config)); | ||
2463 | mbox->cmd.length = sizeof(TX25Config); | ||
2464 | mbox->cmd.command = X25_SET_CONFIGURATION; | ||
2465 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2466 | } while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0)); | ||
2467 | return err; | ||
2468 | } | ||
2469 | |||
2470 | /*==================================================================== | ||
2471 | * Configure adapter for HDLC only. | ||
2472 | *===================================================================*/ | ||
2473 | |||
2474 | static int hdlc_configure (sdla_t* card, TX25Config* conf) | ||
2475 | { | ||
2476 | TX25Mbox* mbox = card->mbox; | ||
2477 | int retry = MAX_CMD_RETRY; | ||
2478 | int err; | ||
2479 | |||
2480 | do{ | ||
2481 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2482 | memcpy(mbox->data, (void*)conf, sizeof(TX25Config)); | ||
2483 | mbox->cmd.length = sizeof(TX25Config); | ||
2484 | mbox->cmd.command = X25_HDLC_SET_CONFIG; | ||
2485 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2486 | } while (err && retry-- && x25_error(card, err, X25_SET_CONFIGURATION, 0)); | ||
2487 | |||
2488 | return err; | ||
2489 | } | ||
2490 | |||
2491 | static int set_hdlc_level (sdla_t* card) | ||
2492 | { | ||
2493 | |||
2494 | TX25Mbox* mbox = card->mbox; | ||
2495 | int retry = MAX_CMD_RETRY; | ||
2496 | int err; | ||
2497 | |||
2498 | do{ | ||
2499 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2500 | mbox->cmd.command = SET_PROTOCOL_LEVEL; | ||
2501 | mbox->cmd.length = 1; | ||
2502 | mbox->data[0] = HDLC_LEVEL; //| DO_HDLC_LEVEL_ERROR_CHECKING; | ||
2503 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2504 | } while (err && retry-- && x25_error(card, err, SET_PROTOCOL_LEVEL, 0)); | ||
2505 | |||
2506 | return err; | ||
2507 | } | ||
2508 | |||
2509 | |||
2510 | |||
2511 | /*==================================================================== | ||
2512 | * Get communications error statistics. | ||
2513 | *====================================================================*/ | ||
2514 | |||
2515 | static int x25_get_err_stats (sdla_t* card) | ||
2516 | { | ||
2517 | TX25Mbox* mbox = card->mbox; | ||
2518 | int retry = MAX_CMD_RETRY; | ||
2519 | int err; | ||
2520 | |||
2521 | do | ||
2522 | { | ||
2523 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2524 | mbox->cmd.command = X25_HDLC_READ_COMM_ERR; | ||
2525 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2526 | } while (err && retry-- && x25_error(card, err, X25_HDLC_READ_COMM_ERR, 0)); | ||
2527 | |||
2528 | if (!err) | ||
2529 | { | ||
2530 | THdlcCommErr* stats = (void*)mbox->data; | ||
2531 | |||
2532 | card->wandev.stats.rx_over_errors = stats->rxOverrun; | ||
2533 | card->wandev.stats.rx_crc_errors = stats->rxBadCrc; | ||
2534 | card->wandev.stats.rx_missed_errors = stats->rxAborted; | ||
2535 | card->wandev.stats.tx_aborted_errors = stats->txAborted; | ||
2536 | } | ||
2537 | return err; | ||
2538 | } | ||
2539 | |||
2540 | /*==================================================================== | ||
2541 | * Get protocol statistics. | ||
2542 | *===================================================================*/ | ||
2543 | |||
2544 | static int x25_get_stats (sdla_t* card) | ||
2545 | { | ||
2546 | TX25Mbox* mbox = card->mbox; | ||
2547 | int retry = MAX_CMD_RETRY; | ||
2548 | int err; | ||
2549 | |||
2550 | do | ||
2551 | { | ||
2552 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2553 | mbox->cmd.command = X25_READ_STATISTICS; | ||
2554 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2555 | } while (err && retry-- && x25_error(card, err, X25_READ_STATISTICS, 0)) ; | ||
2556 | |||
2557 | if (!err) | ||
2558 | { | ||
2559 | TX25Stats* stats = (void*)mbox->data; | ||
2560 | |||
2561 | card->wandev.stats.rx_packets = stats->rxData; | ||
2562 | card->wandev.stats.tx_packets = stats->txData; | ||
2563 | } | ||
2564 | return err; | ||
2565 | } | ||
2566 | |||
2567 | /*==================================================================== | ||
2568 | * Close HDLC link. | ||
2569 | *===================================================================*/ | ||
2570 | |||
2571 | static int x25_close_hdlc (sdla_t* card) | ||
2572 | { | ||
2573 | TX25Mbox* mbox = card->mbox; | ||
2574 | int retry = MAX_CMD_RETRY; | ||
2575 | int err; | ||
2576 | |||
2577 | do | ||
2578 | { | ||
2579 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2580 | mbox->cmd.command = X25_HDLC_LINK_CLOSE; | ||
2581 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2582 | } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_CLOSE, 0)); | ||
2583 | |||
2584 | return err; | ||
2585 | } | ||
2586 | |||
2587 | |||
2588 | /*==================================================================== | ||
2589 | * Open HDLC link. | ||
2590 | *===================================================================*/ | ||
2591 | |||
2592 | static int x25_open_hdlc (sdla_t* card) | ||
2593 | { | ||
2594 | TX25Mbox* mbox = card->mbox; | ||
2595 | int retry = MAX_CMD_RETRY; | ||
2596 | int err; | ||
2597 | |||
2598 | do | ||
2599 | { | ||
2600 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2601 | mbox->cmd.command = X25_HDLC_LINK_OPEN; | ||
2602 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2603 | } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_OPEN, 0)); | ||
2604 | |||
2605 | return err; | ||
2606 | } | ||
2607 | |||
2608 | /*===================================================================== | ||
2609 | * Setup HDLC link. | ||
2610 | *====================================================================*/ | ||
2611 | static int x25_setup_hdlc (sdla_t* card) | ||
2612 | { | ||
2613 | TX25Mbox* mbox = card->mbox; | ||
2614 | int retry = MAX_CMD_RETRY; | ||
2615 | int err; | ||
2616 | |||
2617 | do | ||
2618 | { | ||
2619 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2620 | mbox->cmd.command = X25_HDLC_LINK_SETUP; | ||
2621 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2622 | } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_SETUP, 0)); | ||
2623 | |||
2624 | return err; | ||
2625 | } | ||
2626 | |||
2627 | /*==================================================================== | ||
2628 | * Set (raise/drop) DTR. | ||
2629 | *===================================================================*/ | ||
2630 | |||
2631 | static int x25_set_dtr (sdla_t* card, int dtr) | ||
2632 | { | ||
2633 | TX25Mbox* mbox = card->mbox; | ||
2634 | int retry = MAX_CMD_RETRY; | ||
2635 | int err; | ||
2636 | |||
2637 | do | ||
2638 | { | ||
2639 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2640 | mbox->data[0] = 0; | ||
2641 | mbox->data[2] = 0; | ||
2642 | mbox->data[1] = dtr ? 0x02 : 0x01; | ||
2643 | mbox->cmd.length = 3; | ||
2644 | mbox->cmd.command = X25_SET_GLOBAL_VARS; | ||
2645 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2646 | } while (err && retry-- && x25_error(card, err, X25_SET_GLOBAL_VARS, 0)); | ||
2647 | |||
2648 | return err; | ||
2649 | } | ||
2650 | |||
2651 | /*==================================================================== | ||
2652 | * Set interrupt mode. | ||
2653 | *===================================================================*/ | ||
2654 | |||
2655 | static int x25_set_intr_mode (sdla_t* card, int mode) | ||
2656 | { | ||
2657 | TX25Mbox* mbox = card->mbox; | ||
2658 | int retry = MAX_CMD_RETRY; | ||
2659 | int err; | ||
2660 | |||
2661 | do | ||
2662 | { | ||
2663 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2664 | mbox->data[0] = mode; | ||
2665 | if (card->hw.fwid == SFID_X25_508){ | ||
2666 | mbox->data[1] = card->hw.irq; | ||
2667 | mbox->data[2] = 2; | ||
2668 | mbox->cmd.length = 3; | ||
2669 | }else { | ||
2670 | mbox->cmd.length = 1; | ||
2671 | } | ||
2672 | mbox->cmd.command = X25_SET_INTERRUPT_MODE; | ||
2673 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2674 | } while (err && retry-- && x25_error(card, err, X25_SET_INTERRUPT_MODE, 0)); | ||
2675 | |||
2676 | return err; | ||
2677 | } | ||
2678 | |||
2679 | /*==================================================================== | ||
2680 | * Read X.25 channel configuration. | ||
2681 | *===================================================================*/ | ||
2682 | |||
2683 | static int x25_get_chan_conf (sdla_t* card, x25_channel_t* chan) | ||
2684 | { | ||
2685 | TX25Mbox* mbox = card->mbox; | ||
2686 | int retry = MAX_CMD_RETRY; | ||
2687 | int lcn = chan->common.lcn; | ||
2688 | int err; | ||
2689 | |||
2690 | do{ | ||
2691 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2692 | mbox->cmd.lcn = lcn; | ||
2693 | mbox->cmd.command = X25_READ_CHANNEL_CONFIG; | ||
2694 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2695 | } while (err && retry-- && x25_error(card, err, X25_READ_CHANNEL_CONFIG, lcn)); | ||
2696 | |||
2697 | if (!err) | ||
2698 | { | ||
2699 | TX25Status* status = card->flags; | ||
2700 | |||
2701 | /* calculate an offset into the array of status bytes */ | ||
2702 | if (card->u.x.hi_svc <= X25_MAX_CHAN){ | ||
2703 | |||
2704 | chan->ch_idx = lcn - 1; | ||
2705 | |||
2706 | }else{ | ||
2707 | int offset; | ||
2708 | |||
2709 | /* FIX: Apr 14 2000 : Nenad Corbic | ||
2710 | * The data field was being compared to 0x1F using | ||
2711 | * '&&' instead of '&'. | ||
2712 | * This caused X25API to fail for LCNs greater than 255. | ||
2713 | */ | ||
2714 | switch (mbox->data[0] & 0x1F) | ||
2715 | { | ||
2716 | case 0x01: | ||
2717 | offset = status->pvc_map; break; | ||
2718 | case 0x03: | ||
2719 | offset = status->icc_map; break; | ||
2720 | case 0x07: | ||
2721 | offset = status->twc_map; break; | ||
2722 | case 0x0B: | ||
2723 | offset = status->ogc_map; break; | ||
2724 | default: | ||
2725 | offset = 0; | ||
2726 | } | ||
2727 | chan->ch_idx = lcn - 1 - offset; | ||
2728 | } | ||
2729 | |||
2730 | /* get actual transmit packet size on this channel */ | ||
2731 | switch(mbox->data[1] & 0x38) | ||
2732 | { | ||
2733 | case 0x00: | ||
2734 | chan->tx_pkt_size = 16; | ||
2735 | break; | ||
2736 | case 0x08: | ||
2737 | chan->tx_pkt_size = 32; | ||
2738 | break; | ||
2739 | case 0x10: | ||
2740 | chan->tx_pkt_size = 64; | ||
2741 | break; | ||
2742 | case 0x18: | ||
2743 | chan->tx_pkt_size = 128; | ||
2744 | break; | ||
2745 | case 0x20: | ||
2746 | chan->tx_pkt_size = 256; | ||
2747 | break; | ||
2748 | case 0x28: | ||
2749 | chan->tx_pkt_size = 512; | ||
2750 | break; | ||
2751 | case 0x30: | ||
2752 | chan->tx_pkt_size = 1024; | ||
2753 | break; | ||
2754 | } | ||
2755 | if (card->u.x.logging) | ||
2756 | printk(KERN_INFO "%s: X.25 packet size on LCN %d is %d.\n", | ||
2757 | card->devname, lcn, chan->tx_pkt_size); | ||
2758 | } | ||
2759 | return err; | ||
2760 | } | ||
2761 | |||
2762 | /*==================================================================== | ||
2763 | * Place X.25 call. | ||
2764 | *====================================================================*/ | ||
2765 | |||
2766 | static int x25_place_call (sdla_t* card, x25_channel_t* chan) | ||
2767 | { | ||
2768 | TX25Mbox* mbox = card->mbox; | ||
2769 | int retry = MAX_CMD_RETRY; | ||
2770 | int err; | ||
2771 | char str[64]; | ||
2772 | |||
2773 | |||
2774 | if (chan->protocol == htons(ETH_P_IP)){ | ||
2775 | sprintf(str, "-d%s -uCC", chan->addr); | ||
2776 | |||
2777 | }else if (chan->protocol == htons(ETH_P_IPX)){ | ||
2778 | sprintf(str, "-d%s -u800000008137", chan->addr); | ||
2779 | |||
2780 | } | ||
2781 | |||
2782 | do | ||
2783 | { | ||
2784 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2785 | strcpy(mbox->data, str); | ||
2786 | mbox->cmd.length = strlen(str); | ||
2787 | mbox->cmd.command = X25_PLACE_CALL; | ||
2788 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2789 | } while (err && retry-- && x25_error(card, err, X25_PLACE_CALL, 0)); | ||
2790 | |||
2791 | if (!err){ | ||
2792 | bind_lcn_to_dev (card, chan->dev, mbox->cmd.lcn); | ||
2793 | } | ||
2794 | return err; | ||
2795 | } | ||
2796 | |||
2797 | /*==================================================================== | ||
2798 | * Accept X.25 call. | ||
2799 | *====================================================================*/ | ||
2800 | |||
2801 | static int x25_accept_call (sdla_t* card, int lcn, int qdm) | ||
2802 | { | ||
2803 | TX25Mbox* mbox = card->mbox; | ||
2804 | int retry = MAX_CMD_RETRY; | ||
2805 | int err; | ||
2806 | |||
2807 | do | ||
2808 | { | ||
2809 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2810 | mbox->cmd.lcn = lcn; | ||
2811 | mbox->cmd.qdm = qdm; | ||
2812 | mbox->cmd.command = X25_ACCEPT_CALL; | ||
2813 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2814 | } while (err && retry-- && x25_error(card, err, X25_ACCEPT_CALL, lcn)); | ||
2815 | |||
2816 | return err; | ||
2817 | } | ||
2818 | |||
2819 | /*==================================================================== | ||
2820 | * Clear X.25 call. | ||
2821 | *====================================================================*/ | ||
2822 | |||
2823 | static int x25_clear_call (sdla_t* card, int lcn, int cause, int diagn) | ||
2824 | { | ||
2825 | TX25Mbox* mbox = card->mbox; | ||
2826 | int retry = MAX_CMD_RETRY; | ||
2827 | int err; | ||
2828 | |||
2829 | do | ||
2830 | { | ||
2831 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2832 | mbox->cmd.lcn = lcn; | ||
2833 | mbox->cmd.cause = cause; | ||
2834 | mbox->cmd.diagn = diagn; | ||
2835 | mbox->cmd.command = X25_CLEAR_CALL; | ||
2836 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2837 | } while (err && retry-- && x25_error(card, err, X25_CLEAR_CALL, lcn)); | ||
2838 | |||
2839 | return err; | ||
2840 | } | ||
2841 | |||
2842 | /*==================================================================== | ||
2843 | * Send X.25 data packet. | ||
2844 | *====================================================================*/ | ||
2845 | |||
2846 | static int x25_send (sdla_t* card, int lcn, int qdm, int len, void* buf) | ||
2847 | { | ||
2848 | TX25Mbox* mbox = card->mbox; | ||
2849 | int retry = MAX_CMD_RETRY; | ||
2850 | int err; | ||
2851 | unsigned char cmd; | ||
2852 | |||
2853 | if (card->u.x.LAPB_hdlc) | ||
2854 | cmd = X25_HDLC_WRITE; | ||
2855 | else | ||
2856 | cmd = X25_WRITE; | ||
2857 | |||
2858 | do | ||
2859 | { | ||
2860 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2861 | memcpy(mbox->data, buf, len); | ||
2862 | mbox->cmd.length = len; | ||
2863 | mbox->cmd.lcn = lcn; | ||
2864 | |||
2865 | if (card->u.x.LAPB_hdlc){ | ||
2866 | mbox->cmd.pf = qdm; | ||
2867 | }else{ | ||
2868 | mbox->cmd.qdm = qdm; | ||
2869 | } | ||
2870 | |||
2871 | mbox->cmd.command = cmd; | ||
2872 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2873 | } while (err && retry-- && x25_error(card, err, cmd , lcn)); | ||
2874 | |||
2875 | |||
2876 | /* If buffers are busy the return code for LAPB HDLC is | ||
2877 | * 1. The above functions are looking for return code | ||
2878 | * of X25RES_NOT_READY if busy. */ | ||
2879 | |||
2880 | if (card->u.x.LAPB_hdlc && err == 1){ | ||
2881 | err = X25RES_NOT_READY; | ||
2882 | } | ||
2883 | |||
2884 | return err; | ||
2885 | } | ||
2886 | |||
2887 | /*==================================================================== | ||
2888 | * Fetch X.25 asynchronous events. | ||
2889 | *===================================================================*/ | ||
2890 | |||
2891 | static int x25_fetch_events (sdla_t* card) | ||
2892 | { | ||
2893 | TX25Status* status = card->flags; | ||
2894 | TX25Mbox* mbox = card->mbox; | ||
2895 | int err = 0; | ||
2896 | |||
2897 | if (status->gflags & 0x20) | ||
2898 | { | ||
2899 | memset(&mbox->cmd, 0, sizeof(TX25Cmd)); | ||
2900 | mbox->cmd.command = X25_IS_DATA_AVAILABLE; | ||
2901 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2902 | if (err) x25_error(card, err, X25_IS_DATA_AVAILABLE, 0); | ||
2903 | } | ||
2904 | return err; | ||
2905 | } | ||
2906 | |||
2907 | /*==================================================================== | ||
2908 | * X.25 asynchronous event/error handler. | ||
2909 | * This routine is called each time interface command returns | ||
2910 | * non-zero return code to handle X.25 asynchronous events and | ||
2911 | * common errors. Return non-zero to repeat command or zero to | ||
2912 | * cancel it. | ||
2913 | * | ||
2914 | * Notes: | ||
2915 | * 1. This function may be called recursively, as handling some of the | ||
2916 | * asynchronous events (e.g. call request) requires execution of the | ||
2917 | * interface command(s) that, in turn, may also return asynchronous | ||
2918 | * events. To avoid re-entrancy problems we copy mailbox to dynamically | ||
2919 | * allocated memory before processing events. | ||
2920 | *====================================================================*/ | ||
2921 | |||
2922 | static int x25_error (sdla_t* card, int err, int cmd, int lcn) | ||
2923 | { | ||
2924 | int retry = 1; | ||
2925 | unsigned dlen = ((TX25Mbox*)card->mbox)->cmd.length; | ||
2926 | TX25Mbox* mb; | ||
2927 | |||
2928 | mb = kmalloc(sizeof(TX25Mbox) + dlen, GFP_ATOMIC); | ||
2929 | if (mb == NULL) | ||
2930 | { | ||
2931 | printk(KERN_ERR "%s: x25_error() out of memory!\n", | ||
2932 | card->devname); | ||
2933 | return 0; | ||
2934 | } | ||
2935 | memcpy(mb, card->mbox, sizeof(TX25Mbox) + dlen); | ||
2936 | switch (err){ | ||
2937 | |||
2938 | case X25RES_ASYNC_PACKET: /* X.25 asynchronous packet was received */ | ||
2939 | |||
2940 | mb->data[dlen] = '\0'; | ||
2941 | |||
2942 | switch (mb->cmd.pktType & 0x7F){ | ||
2943 | |||
2944 | case ASE_CALL_RQST: /* incoming call */ | ||
2945 | retry = incoming_call(card, cmd, lcn, mb); | ||
2946 | break; | ||
2947 | |||
2948 | case ASE_CALL_ACCEPTED: /* connected */ | ||
2949 | retry = call_accepted(card, cmd, lcn, mb); | ||
2950 | break; | ||
2951 | |||
2952 | case ASE_CLEAR_RQST: /* call clear request */ | ||
2953 | retry = call_cleared(card, cmd, lcn, mb); | ||
2954 | break; | ||
2955 | |||
2956 | case ASE_RESET_RQST: /* reset request */ | ||
2957 | printk(KERN_INFO "%s: X.25 reset request on LCN %d! " | ||
2958 | "Cause:0x%02X Diagn:0x%02X\n", | ||
2959 | card->devname, mb->cmd.lcn, mb->cmd.cause, | ||
2960 | mb->cmd.diagn); | ||
2961 | api_oob_event (card,mb); | ||
2962 | break; | ||
2963 | |||
2964 | case ASE_RESTART_RQST: /* restart request */ | ||
2965 | retry = restart_event(card, cmd, lcn, mb); | ||
2966 | break; | ||
2967 | |||
2968 | case ASE_CLEAR_CONFRM: | ||
2969 | if (clear_confirm_event (card,mb)) | ||
2970 | break; | ||
2971 | |||
2972 | /* I use the goto statement here so if | ||
2973 | * somebody inserts code between the | ||
2974 | * case and default, we will not have | ||
2975 | * ghost problems */ | ||
2976 | |||
2977 | goto dflt_1; | ||
2978 | |||
2979 | default: | ||
2980 | dflt_1: | ||
2981 | printk(KERN_INFO "%s: X.25 event 0x%02X on LCN %d! " | ||
2982 | "Cause:0x%02X Diagn:0x%02X\n", | ||
2983 | card->devname, mb->cmd.pktType, | ||
2984 | mb->cmd.lcn, mb->cmd.cause, mb->cmd.diagn); | ||
2985 | } | ||
2986 | break; | ||
2987 | |||
2988 | case X25RES_PROTO_VIOLATION: /* X.25 protocol violation indication */ | ||
2989 | |||
2990 | /* Bug Fix: Mar 14 2000 | ||
2991 | * The Protocol violation error conditions were | ||
2992 | * not handled previously */ | ||
2993 | |||
2994 | switch (mb->cmd.pktType & 0x7F){ | ||
2995 | |||
2996 | case PVE_CLEAR_RQST: /* Clear request */ | ||
2997 | retry = call_cleared(card, cmd, lcn, mb); | ||
2998 | break; | ||
2999 | |||
3000 | case PVE_RESET_RQST: /* Reset request */ | ||
3001 | printk(KERN_INFO "%s: X.25 reset request on LCN %d! " | ||
3002 | "Cause:0x%02X Diagn:0x%02X\n", | ||
3003 | card->devname, mb->cmd.lcn, mb->cmd.cause, | ||
3004 | mb->cmd.diagn); | ||
3005 | api_oob_event (card,mb); | ||
3006 | break; | ||
3007 | |||
3008 | case PVE_RESTART_RQST: /* Restart request */ | ||
3009 | retry = restart_event(card, cmd, lcn, mb); | ||
3010 | break; | ||
3011 | |||
3012 | default : | ||
3013 | printk(KERN_INFO | ||
3014 | "%s: X.25 protocol violation on LCN %d! " | ||
3015 | "Packet:0x%02X Cause:0x%02X Diagn:0x%02X\n", | ||
3016 | card->devname, mb->cmd.lcn, | ||
3017 | mb->cmd.pktType & 0x7F, mb->cmd.cause, mb->cmd.diagn); | ||
3018 | api_oob_event(card,mb); | ||
3019 | } | ||
3020 | break; | ||
3021 | |||
3022 | case 0x42: /* X.25 timeout */ | ||
3023 | retry = timeout_event(card, cmd, lcn, mb); | ||
3024 | break; | ||
3025 | |||
3026 | case 0x43: /* X.25 retry limit exceeded */ | ||
3027 | printk(KERN_INFO | ||
3028 | "%s: exceeded X.25 retry limit on LCN %d! " | ||
3029 | "Packet:0x%02X Diagn:0x%02X\n", card->devname, | ||
3030 | mb->cmd.lcn, mb->cmd.pktType, mb->cmd.diagn) | ||
3031 | ; | ||
3032 | break; | ||
3033 | |||
3034 | case 0x08: /* modem failure */ | ||
3035 | #ifndef MODEM_NOT_LOG | ||
3036 | printk(KERN_INFO "%s: modem failure!\n", card->devname); | ||
3037 | #endif /* MODEM_NOT_LOG */ | ||
3038 | api_oob_event(card,mb); | ||
3039 | break; | ||
3040 | |||
3041 | case 0x09: /* N2 retry limit */ | ||
3042 | printk(KERN_INFO "%s: exceeded HDLC retry limit!\n", | ||
3043 | card->devname); | ||
3044 | api_oob_event(card,mb); | ||
3045 | break; | ||
3046 | |||
3047 | case 0x06: /* unnumbered frame was received while in ABM */ | ||
3048 | printk(KERN_INFO "%s: received Unnumbered frame 0x%02X!\n", | ||
3049 | card->devname, mb->data[0]); | ||
3050 | api_oob_event(card,mb); | ||
3051 | break; | ||
3052 | |||
3053 | case CMD_TIMEOUT: | ||
3054 | printk(KERN_ERR "%s: command 0x%02X timed out!\n", | ||
3055 | card->devname, cmd) | ||
3056 | ; | ||
3057 | retry = 0; /* abort command */ | ||
3058 | break; | ||
3059 | |||
3060 | case X25RES_NOT_READY: | ||
3061 | retry = 1; | ||
3062 | break; | ||
3063 | |||
3064 | case 0x01: | ||
3065 | if (card->u.x.LAPB_hdlc) | ||
3066 | break; | ||
3067 | |||
3068 | if (mb->cmd.command == 0x16) | ||
3069 | break; | ||
3070 | /* I use the goto statement here so if | ||
3071 | * somebody inserts code between the | ||
3072 | * case and default, we will not have | ||
3073 | * ghost problems */ | ||
3074 | goto dflt_2; | ||
3075 | |||
3076 | default: | ||
3077 | dflt_2: | ||
3078 | printk(KERN_INFO "%s: command 0x%02X returned 0x%02X! Lcn %i\n", | ||
3079 | card->devname, cmd, err, mb->cmd.lcn) | ||
3080 | ; | ||
3081 | retry = 0; /* abort command */ | ||
3082 | } | ||
3083 | kfree(mb); | ||
3084 | return retry; | ||
3085 | } | ||
3086 | |||
3087 | /*==================================================================== | ||
3088 | * X.25 Asynchronous Event Handlers | ||
3089 | * These functions are called by the x25_error() and should return 0, if | ||
3090 | * the command resulting in the asynchronous event must be aborted. | ||
3091 | *====================================================================*/ | ||
3092 | |||
3093 | |||
3094 | |||
3095 | /*==================================================================== | ||
3096 | *Handle X.25 incoming call request. | ||
3097 | * RFC 1356 establishes the following rules: | ||
3098 | * 1. The first octet in the Call User Data (CUD) field of the call | ||
3099 | * request packet contains NLPID identifying protocol encapsulation | ||
3100 | * 2. Calls MUST NOT be accepted unless router supports requested | ||
3101 | * protocol encapsulation. | ||
3102 | * 3. A diagnostic code 249 defined by ISO/IEC 8208 may be used | ||
3103 | * when clearing a call because protocol encapsulation is not | ||
3104 | * supported. | ||
3105 | * 4. If an incoming call is received while a call request is | ||
3106 | * pending (i.e. call collision has occurred), the incoming call | ||
3107 | * shall be rejected and call request shall be retried. | ||
3108 | *====================================================================*/ | ||
3109 | |||
3110 | static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb) | ||
3111 | { | ||
3112 | struct wan_device* wandev = &card->wandev; | ||
3113 | int new_lcn = mb->cmd.lcn; | ||
3114 | struct net_device* dev = get_dev_by_lcn(wandev, new_lcn); | ||
3115 | x25_channel_t* chan = NULL; | ||
3116 | int accept = 0; /* set to '1' if o.k. to accept call */ | ||
3117 | unsigned int user_data; | ||
3118 | x25_call_info_t* info; | ||
3119 | |||
3120 | /* Make sure there is no call collision */ | ||
3121 | if (dev != NULL) | ||
3122 | { | ||
3123 | printk(KERN_INFO | ||
3124 | "%s: X.25 incoming call collision on LCN %d!\n", | ||
3125 | card->devname, new_lcn); | ||
3126 | |||
3127 | x25_clear_call(card, new_lcn, 0, 0); | ||
3128 | return 1; | ||
3129 | } | ||
3130 | |||
3131 | /* Make sure D bit is not set in call request */ | ||
3132 | //FIXME: THIS IS NOT TURE !!!! TAKE IT OUT | ||
3133 | // if (mb->cmd.qdm & 0x02) | ||
3134 | // { | ||
3135 | // printk(KERN_INFO | ||
3136 | // "%s: X.25 incoming call on LCN %d with D-bit set!\n", | ||
3137 | // card->devname, new_lcn); | ||
3138 | // | ||
3139 | // x25_clear_call(card, new_lcn, 0, 0); | ||
3140 | // return 1; | ||
3141 | // } | ||
3142 | |||
3143 | /* Parse call request data */ | ||
3144 | info = kmalloc(sizeof(x25_call_info_t), GFP_ATOMIC); | ||
3145 | if (info == NULL) | ||
3146 | { | ||
3147 | printk(KERN_ERR | ||
3148 | "%s: not enough memory to parse X.25 incoming call " | ||
3149 | "on LCN %d!\n", card->devname, new_lcn); | ||
3150 | x25_clear_call(card, new_lcn, 0, 0); | ||
3151 | return 1; | ||
3152 | } | ||
3153 | |||
3154 | parse_call_info(mb->data, info); | ||
3155 | |||
3156 | if (card->u.x.logging) | ||
3157 | printk(KERN_INFO "\n%s: X.25 incoming call on LCN %d!\n", | ||
3158 | card->devname, new_lcn); | ||
3159 | |||
3160 | /* Conver the first two ASCII characters into an | ||
3161 | * interger. Used to check the incoming protocol | ||
3162 | */ | ||
3163 | user_data = hex_to_uint(info->user,2); | ||
3164 | |||
3165 | /* Find available channel */ | ||
3166 | for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) { | ||
3167 | chan = dev->priv; | ||
3168 | |||
3169 | if (chan->common.usedby == API) | ||
3170 | continue; | ||
3171 | |||
3172 | if (!chan->common.svc || (chan->common.state != WAN_DISCONNECTED)) | ||
3173 | continue; | ||
3174 | |||
3175 | if (user_data == NLPID_IP && chan->protocol != htons(ETH_P_IP)){ | ||
3176 | printk(KERN_INFO "IP packet but configured for IPX : %x, %x\n", | ||
3177 | htons(chan->protocol), info->user[0]); | ||
3178 | continue; | ||
3179 | } | ||
3180 | |||
3181 | if (user_data == NLPID_SNAP && chan->protocol != htons(ETH_P_IPX)){ | ||
3182 | printk(KERN_INFO "IPX packet but configured for IP: %x\n", | ||
3183 | htons(chan->protocol)); | ||
3184 | continue; | ||
3185 | } | ||
3186 | if (strcmp(info->src, chan->addr) == 0) | ||
3187 | break; | ||
3188 | |||
3189 | /* If just an '@' is specified, accept all incoming calls */ | ||
3190 | if (strcmp(chan->addr, "") == 0) | ||
3191 | break; | ||
3192 | } | ||
3193 | |||
3194 | if (dev == NULL){ | ||
3195 | |||
3196 | /* If the call is not for any WANPIPE interfaces | ||
3197 | * check to see if there is an API listening queue | ||
3198 | * waiting for data. If there is send the packet | ||
3199 | * up the stack. | ||
3200 | */ | ||
3201 | if (card->sk != NULL && card->func != NULL){ | ||
3202 | if (api_incoming_call(card,mb,new_lcn)){ | ||
3203 | x25_clear_call(card, new_lcn, 0, 0); | ||
3204 | } | ||
3205 | accept = 0; | ||
3206 | }else{ | ||
3207 | printk(KERN_INFO "%s: no channels available!\n", | ||
3208 | card->devname); | ||
3209 | |||
3210 | x25_clear_call(card, new_lcn, 0, 0); | ||
3211 | } | ||
3212 | |||
3213 | }else if (info->nuser == 0){ | ||
3214 | |||
3215 | printk(KERN_INFO | ||
3216 | "%s: no user data in incoming call on LCN %d!\n", | ||
3217 | card->devname, new_lcn) | ||
3218 | ; | ||
3219 | x25_clear_call(card, new_lcn, 0, 0); | ||
3220 | |||
3221 | }else switch (info->user[0]){ | ||
3222 | |||
3223 | case 0: /* multiplexed */ | ||
3224 | chan->protocol = htons(0); | ||
3225 | accept = 1; | ||
3226 | break; | ||
3227 | |||
3228 | case NLPID_IP: /* IP datagrams */ | ||
3229 | accept = 1; | ||
3230 | break; | ||
3231 | |||
3232 | case NLPID_SNAP: /* IPX datagrams */ | ||
3233 | accept = 1; | ||
3234 | break; | ||
3235 | |||
3236 | default: | ||
3237 | printk(KERN_INFO | ||
3238 | "%s: unsupported NLPID 0x%02X in incoming call " | ||
3239 | "on LCN %d!\n", card->devname, info->user[0], new_lcn); | ||
3240 | x25_clear_call(card, new_lcn, 0, 249); | ||
3241 | } | ||
3242 | |||
3243 | if (accept && (x25_accept_call(card, new_lcn, 0) == CMD_OK)){ | ||
3244 | |||
3245 | bind_lcn_to_dev (card, chan->dev, new_lcn); | ||
3246 | |||
3247 | if (x25_get_chan_conf(card, chan) == CMD_OK) | ||
3248 | set_chan_state(dev, WAN_CONNECTED); | ||
3249 | else | ||
3250 | x25_clear_call(card, new_lcn, 0, 0); | ||
3251 | } | ||
3252 | kfree(info); | ||
3253 | return 1; | ||
3254 | } | ||
3255 | |||
3256 | /*==================================================================== | ||
3257 | * Handle accepted call. | ||
3258 | *====================================================================*/ | ||
3259 | |||
3260 | static int call_accepted (sdla_t* card, int cmd, int lcn, TX25Mbox* mb) | ||
3261 | { | ||
3262 | unsigned new_lcn = mb->cmd.lcn; | ||
3263 | struct net_device* dev = find_channel(card, new_lcn); | ||
3264 | x25_channel_t* chan; | ||
3265 | |||
3266 | if (dev == NULL){ | ||
3267 | printk(KERN_INFO | ||
3268 | "%s: clearing orphaned connection on LCN %d!\n", | ||
3269 | card->devname, new_lcn); | ||
3270 | x25_clear_call(card, new_lcn, 0, 0); | ||
3271 | return 1; | ||
3272 | } | ||
3273 | |||
3274 | if (card->u.x.logging) | ||
3275 | printk(KERN_INFO "%s: X.25 call accepted on Dev %s and LCN %d!\n", | ||
3276 | card->devname, dev->name, new_lcn); | ||
3277 | |||
3278 | /* Get channel configuration and notify router */ | ||
3279 | chan = dev->priv; | ||
3280 | if (x25_get_chan_conf(card, chan) != CMD_OK) | ||
3281 | { | ||
3282 | x25_clear_call(card, new_lcn, 0, 0); | ||
3283 | return 1; | ||
3284 | } | ||
3285 | |||
3286 | set_chan_state(dev, WAN_CONNECTED); | ||
3287 | |||
3288 | if (chan->common.usedby == API){ | ||
3289 | send_delayed_cmd_result(card,dev,mb); | ||
3290 | bind_lcn_to_dev (card, dev, new_lcn); | ||
3291 | } | ||
3292 | |||
3293 | return 1; | ||
3294 | } | ||
3295 | |||
3296 | /*==================================================================== | ||
3297 | * Handle cleared call. | ||
3298 | *====================================================================*/ | ||
3299 | |||
3300 | static int call_cleared (sdla_t* card, int cmd, int lcn, TX25Mbox* mb) | ||
3301 | { | ||
3302 | unsigned new_lcn = mb->cmd.lcn; | ||
3303 | struct net_device* dev = find_channel(card, new_lcn); | ||
3304 | x25_channel_t *chan; | ||
3305 | unsigned char old_state; | ||
3306 | |||
3307 | if (card->u.x.logging){ | ||
3308 | printk(KERN_INFO "%s: X.25 clear request on LCN %d! Cause:0x%02X " | ||
3309 | "Diagn:0x%02X\n", | ||
3310 | card->devname, new_lcn, mb->cmd.cause, mb->cmd.diagn); | ||
3311 | } | ||
3312 | |||
3313 | if (dev == NULL){ | ||
3314 | printk(KERN_INFO "%s: X.25 clear request : No device for clear\n", | ||
3315 | card->devname); | ||
3316 | return 1; | ||
3317 | } | ||
3318 | |||
3319 | chan=dev->priv; | ||
3320 | |||
3321 | old_state = chan->common.state; | ||
3322 | |||
3323 | set_chan_state(dev, WAN_DISCONNECTED); | ||
3324 | |||
3325 | if (chan->common.usedby == API){ | ||
3326 | |||
3327 | switch (old_state){ | ||
3328 | |||
3329 | case WAN_CONNECTING: | ||
3330 | send_delayed_cmd_result(card,dev,mb); | ||
3331 | break; | ||
3332 | case WAN_CONNECTED: | ||
3333 | send_oob_msg(card,dev,mb); | ||
3334 | break; | ||
3335 | } | ||
3336 | } | ||
3337 | |||
3338 | return ((cmd == X25_WRITE) && (lcn == new_lcn)) ? 0 : 1; | ||
3339 | } | ||
3340 | |||
3341 | /*==================================================================== | ||
3342 | * Handle X.25 restart event. | ||
3343 | *====================================================================*/ | ||
3344 | |||
3345 | static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb) | ||
3346 | { | ||
3347 | struct wan_device* wandev = &card->wandev; | ||
3348 | struct net_device* dev; | ||
3349 | x25_channel_t *chan; | ||
3350 | unsigned char old_state; | ||
3351 | |||
3352 | printk(KERN_INFO | ||
3353 | "%s: X.25 restart request! Cause:0x%02X Diagn:0x%02X\n", | ||
3354 | card->devname, mb->cmd.cause, mb->cmd.diagn); | ||
3355 | |||
3356 | /* down all logical channels */ | ||
3357 | for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) { | ||
3358 | chan=dev->priv; | ||
3359 | old_state = chan->common.state; | ||
3360 | |||
3361 | set_chan_state(dev, WAN_DISCONNECTED); | ||
3362 | |||
3363 | if (chan->common.usedby == API){ | ||
3364 | switch (old_state){ | ||
3365 | |||
3366 | case WAN_CONNECTING: | ||
3367 | send_delayed_cmd_result(card,dev,mb); | ||
3368 | break; | ||
3369 | case WAN_CONNECTED: | ||
3370 | send_oob_msg(card,dev,mb); | ||
3371 | break; | ||
3372 | } | ||
3373 | } | ||
3374 | } | ||
3375 | return (cmd == X25_WRITE) ? 0 : 1; | ||
3376 | } | ||
3377 | |||
3378 | /*==================================================================== | ||
3379 | * Handle timeout event. | ||
3380 | *====================================================================*/ | ||
3381 | |||
3382 | static int timeout_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb) | ||
3383 | { | ||
3384 | unsigned new_lcn = mb->cmd.lcn; | ||
3385 | |||
3386 | if (mb->cmd.pktType == 0x05) /* call request time out */ | ||
3387 | { | ||
3388 | struct net_device* dev = find_channel(card,new_lcn); | ||
3389 | |||
3390 | printk(KERN_INFO "%s: X.25 call timed timeout on LCN %d!\n", | ||
3391 | card->devname, new_lcn); | ||
3392 | |||
3393 | if (dev){ | ||
3394 | x25_channel_t *chan = dev->priv; | ||
3395 | set_chan_state(dev, WAN_DISCONNECTED); | ||
3396 | |||
3397 | if (chan->common.usedby == API){ | ||
3398 | send_delayed_cmd_result(card,dev,card->mbox); | ||
3399 | } | ||
3400 | } | ||
3401 | }else{ | ||
3402 | printk(KERN_INFO "%s: X.25 packet 0x%02X timeout on LCN %d!\n", | ||
3403 | card->devname, mb->cmd.pktType, new_lcn); | ||
3404 | } | ||
3405 | return 1; | ||
3406 | } | ||
3407 | |||
3408 | /* | ||
3409 | * Miscellaneous | ||
3410 | */ | ||
3411 | |||
3412 | /*==================================================================== | ||
3413 | * Establish physical connection. | ||
3414 | * o open HDLC and raise DTR | ||
3415 | * | ||
3416 | * Return: 0 connection established | ||
3417 | * 1 connection is in progress | ||
3418 | * <0 error | ||
3419 | *===================================================================*/ | ||
3420 | |||
3421 | static int connect (sdla_t* card) | ||
3422 | { | ||
3423 | TX25Status* status = card->flags; | ||
3424 | |||
3425 | if (x25_open_hdlc(card) || x25_setup_hdlc(card)) | ||
3426 | return -EIO; | ||
3427 | |||
3428 | wanpipe_set_state(card, WAN_CONNECTING); | ||
3429 | |||
3430 | x25_set_intr_mode(card, INTR_ON_TIMER); | ||
3431 | status->imask &= ~INTR_ON_TIMER; | ||
3432 | |||
3433 | return 1; | ||
3434 | } | ||
3435 | |||
3436 | /* | ||
3437 | * Tear down physical connection. | ||
3438 | * o close HDLC link | ||
3439 | * o drop DTR | ||
3440 | * | ||
3441 | * Return: 0 | ||
3442 | * <0 error | ||
3443 | */ | ||
3444 | |||
3445 | static int disconnect (sdla_t* card) | ||
3446 | { | ||
3447 | wanpipe_set_state(card, WAN_DISCONNECTED); | ||
3448 | x25_set_intr_mode(card, INTR_ON_TIMER); /* disable all interrupt except timer */ | ||
3449 | x25_close_hdlc(card); /* close HDLC link */ | ||
3450 | x25_set_dtr(card, 0); /* drop DTR */ | ||
3451 | return 0; | ||
3452 | } | ||
3453 | |||
3454 | /* | ||
3455 | * Find network device by its channel number. | ||
3456 | */ | ||
3457 | |||
3458 | static struct net_device* get_dev_by_lcn(struct wan_device* wandev, | ||
3459 | unsigned lcn) | ||
3460 | { | ||
3461 | struct net_device* dev; | ||
3462 | |||
3463 | for (dev = wandev->dev; dev; dev = *((struct net_device **)dev->priv)) | ||
3464 | if (((x25_channel_t*)dev->priv)->common.lcn == lcn) | ||
3465 | break; | ||
3466 | return dev; | ||
3467 | } | ||
3468 | |||
3469 | /* | ||
3470 | * Initiate connection on the logical channel. | ||
3471 | * o for PVC we just get channel configuration | ||
3472 | * o for SVCs place an X.25 call | ||
3473 | * | ||
3474 | * Return: 0 connected | ||
3475 | * >0 connection in progress | ||
3476 | * <0 failure | ||
3477 | */ | ||
3478 | |||
3479 | static int chan_connect(struct net_device* dev) | ||
3480 | { | ||
3481 | x25_channel_t* chan = dev->priv; | ||
3482 | sdla_t* card = chan->card; | ||
3483 | |||
3484 | if (chan->common.svc && chan->common.usedby == WANPIPE){ | ||
3485 | if (!chan->addr[0]){ | ||
3486 | printk(KERN_INFO "%s: No Destination Address\n", | ||
3487 | card->devname); | ||
3488 | return -EINVAL; /* no destination address */ | ||
3489 | } | ||
3490 | printk(KERN_INFO "%s: placing X.25 call to %s ...\n", | ||
3491 | card->devname, chan->addr); | ||
3492 | |||
3493 | if (x25_place_call(card, chan) != CMD_OK) | ||
3494 | return -EIO; | ||
3495 | |||
3496 | set_chan_state(dev, WAN_CONNECTING); | ||
3497 | return 1; | ||
3498 | }else{ | ||
3499 | if (x25_get_chan_conf(card, chan) != CMD_OK) | ||
3500 | return -EIO; | ||
3501 | |||
3502 | set_chan_state(dev, WAN_CONNECTED); | ||
3503 | } | ||
3504 | return 0; | ||
3505 | } | ||
3506 | |||
3507 | /* | ||
3508 | * Disconnect logical channel. | ||
3509 | * o if SVC then clear X.25 call | ||
3510 | */ | ||
3511 | |||
3512 | static int chan_disc(struct net_device* dev) | ||
3513 | { | ||
3514 | x25_channel_t* chan = dev->priv; | ||
3515 | |||
3516 | if (chan->common.svc){ | ||
3517 | x25_clear_call(chan->card, chan->common.lcn, 0, 0); | ||
3518 | |||
3519 | /* For API we disconnect on clear | ||
3520 | * confirmation. | ||
3521 | */ | ||
3522 | if (chan->common.usedby == API) | ||
3523 | return 0; | ||
3524 | } | ||
3525 | |||
3526 | set_chan_state(dev, WAN_DISCONNECTED); | ||
3527 | |||
3528 | return 0; | ||
3529 | } | ||
3530 | |||
3531 | /* | ||
3532 | * Set logical channel state. | ||
3533 | */ | ||
3534 | |||
3535 | static void set_chan_state(struct net_device* dev, int state) | ||
3536 | { | ||
3537 | x25_channel_t* chan = dev->priv; | ||
3538 | sdla_t* card = chan->card; | ||
3539 | unsigned long flags; | ||
3540 | |||
3541 | save_flags(flags); | ||
3542 | cli(); | ||
3543 | if (chan->common.state != state) | ||
3544 | { | ||
3545 | switch (state) | ||
3546 | { | ||
3547 | case WAN_CONNECTED: | ||
3548 | if (card->u.x.logging){ | ||
3549 | printk (KERN_INFO | ||
3550 | "%s: interface %s connected, lcn %i !\n", | ||
3551 | card->devname, dev->name,chan->common.lcn); | ||
3552 | } | ||
3553 | *(unsigned short*)dev->dev_addr = htons(chan->common.lcn); | ||
3554 | chan->i_timeout_sofar = jiffies; | ||
3555 | |||
3556 | /* LAPB is PVC Based */ | ||
3557 | if (card->u.x.LAPB_hdlc) | ||
3558 | chan->common.svc=0; | ||
3559 | break; | ||
3560 | |||
3561 | case WAN_CONNECTING: | ||
3562 | if (card->u.x.logging){ | ||
3563 | printk (KERN_INFO | ||
3564 | "%s: interface %s connecting, lcn %i ...\n", | ||
3565 | card->devname, dev->name, chan->common.lcn); | ||
3566 | } | ||
3567 | break; | ||
3568 | |||
3569 | case WAN_DISCONNECTED: | ||
3570 | if (card->u.x.logging){ | ||
3571 | printk (KERN_INFO | ||
3572 | "%s: interface %s disconnected, lcn %i !\n", | ||
3573 | card->devname, dev->name,chan->common.lcn); | ||
3574 | } | ||
3575 | atomic_set(&chan->common.disconnect,0); | ||
3576 | |||
3577 | if (chan->common.svc) { | ||
3578 | *(unsigned short*)dev->dev_addr = 0; | ||
3579 | card->u.x.svc_to_dev_map[(chan->common.lcn%X25_MAX_CHAN)]=NULL; | ||
3580 | chan->common.lcn = 0; | ||
3581 | } | ||
3582 | |||
3583 | if (chan->transmit_length){ | ||
3584 | chan->transmit_length=0; | ||
3585 | atomic_set(&chan->common.driver_busy,0); | ||
3586 | chan->tx_offset=0; | ||
3587 | if (netif_queue_stopped(dev)){ | ||
3588 | netif_wake_queue(dev); | ||
3589 | } | ||
3590 | } | ||
3591 | atomic_set(&chan->common.command,0); | ||
3592 | break; | ||
3593 | |||
3594 | case WAN_DISCONNECTING: | ||
3595 | if (card->u.x.logging){ | ||
3596 | printk (KERN_INFO | ||
3597 | "\n%s: interface %s disconnecting, lcn %i ...\n", | ||
3598 | card->devname, dev->name,chan->common.lcn); | ||
3599 | } | ||
3600 | atomic_set(&chan->common.disconnect,0); | ||
3601 | break; | ||
3602 | } | ||
3603 | chan->common.state = state; | ||
3604 | } | ||
3605 | chan->state_tick = jiffies; | ||
3606 | restore_flags(flags); | ||
3607 | } | ||
3608 | |||
3609 | /* | ||
3610 | * Send packet on a logical channel. | ||
3611 | * When this function is called, tx_skb field of the channel data | ||
3612 | * space points to the transmit socket buffer. When transmission | ||
3613 | * is complete, release socket buffer and reset 'tbusy' flag. | ||
3614 | * | ||
3615 | * Return: 0 - transmission complete | ||
3616 | * 1 - busy | ||
3617 | * | ||
3618 | * Notes: | ||
3619 | * 1. If packet length is greater than MTU for this channel, we'll fragment | ||
3620 | * the packet into 'complete sequence' using M-bit. | ||
3621 | * 2. When transmission is complete, an event notification should be issued | ||
3622 | * to the router. | ||
3623 | */ | ||
3624 | |||
3625 | static int chan_send(struct net_device* dev, void* buff, unsigned data_len, | ||
3626 | unsigned char tx_intr) | ||
3627 | { | ||
3628 | x25_channel_t* chan = dev->priv; | ||
3629 | sdla_t* card = chan->card; | ||
3630 | TX25Status* status = card->flags; | ||
3631 | unsigned len=0, qdm=0, res=0, orig_len = 0; | ||
3632 | void *data; | ||
3633 | |||
3634 | /* Check to see if channel is ready */ | ||
3635 | if ((!(status->cflags[chan->ch_idx] & 0x40) && !card->u.x.LAPB_hdlc) || | ||
3636 | !(*card->u.x.hdlc_buf_status & 0x40)){ | ||
3637 | |||
3638 | if (!tx_intr){ | ||
3639 | setup_for_delayed_transmit (dev, buff, data_len); | ||
3640 | return 0; | ||
3641 | }else{ | ||
3642 | /* By returning 0 to tx_intr the packet will be dropped */ | ||
3643 | ++card->wandev.stats.tx_dropped; | ||
3644 | ++chan->ifstats.tx_dropped; | ||
3645 | printk(KERN_INFO "%s: ERROR, Tx intr could not send, dropping %s:\n", | ||
3646 | card->devname,dev->name); | ||
3647 | ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr; | ||
3648 | return 0; | ||
3649 | } | ||
3650 | } | ||
3651 | |||
3652 | if (chan->common.usedby == API){ | ||
3653 | /* Remove the API Header */ | ||
3654 | x25api_hdr_t *api_data = (x25api_hdr_t *)buff; | ||
3655 | |||
3656 | /* Set the qdm bits from the packet header | ||
3657 | * User has the option to set the qdm bits | ||
3658 | */ | ||
3659 | qdm = api_data->qdm; | ||
3660 | |||
3661 | orig_len = len = data_len - sizeof(x25api_hdr_t); | ||
3662 | data = (unsigned char*)buff + sizeof(x25api_hdr_t); | ||
3663 | }else{ | ||
3664 | data = buff; | ||
3665 | orig_len = len = data_len; | ||
3666 | } | ||
3667 | |||
3668 | if (tx_intr){ | ||
3669 | /* We are in tx_intr, minus the tx_offset from | ||
3670 | * the total length. The tx_offset part of the | ||
3671 | * data has already been sent. Also, move the | ||
3672 | * data pointer to proper offset location. | ||
3673 | */ | ||
3674 | len -= chan->tx_offset; | ||
3675 | data = (unsigned char*)data + chan->tx_offset; | ||
3676 | } | ||
3677 | |||
3678 | /* Check if the packet length is greater than MTU | ||
3679 | * If YES: Cut the len to MTU and set the M bit | ||
3680 | */ | ||
3681 | if (len > chan->tx_pkt_size && !card->u.x.LAPB_hdlc){ | ||
3682 | len = chan->tx_pkt_size; | ||
3683 | qdm |= M_BIT; | ||
3684 | } | ||
3685 | |||
3686 | |||
3687 | /* Pass only first three bits of the qdm byte to the send | ||
3688 | * routine. In case user sets any other bit which might | ||
3689 | * cause errors. | ||
3690 | */ | ||
3691 | |||
3692 | switch(x25_send(card, chan->common.lcn, (qdm&0x07), len, data)){ | ||
3693 | case 0x00: /* success */ | ||
3694 | chan->i_timeout_sofar = jiffies; | ||
3695 | |||
3696 | dev->trans_start=jiffies; | ||
3697 | |||
3698 | if ((qdm & M_BIT) && !card->u.x.LAPB_hdlc){ | ||
3699 | if (!tx_intr){ | ||
3700 | /* The M bit was set, which means that part of the | ||
3701 | * packet has been sent. Copy the packet into a buffer | ||
3702 | * and set the offset to len, so on next tx_inter | ||
3703 | * the packet will be sent using the below offset. | ||
3704 | */ | ||
3705 | chan->tx_offset += len; | ||
3706 | |||
3707 | ++chan->ifstats.tx_packets; | ||
3708 | chan->ifstats.tx_bytes += len; | ||
3709 | |||
3710 | if (chan->tx_offset < orig_len){ | ||
3711 | setup_for_delayed_transmit (dev, buff, data_len); | ||
3712 | } | ||
3713 | res=0; | ||
3714 | }else{ | ||
3715 | /* We are already in tx_inter, thus data is already | ||
3716 | * in the buffer. Update the offset and wait for | ||
3717 | * next tx_intr. We add on to the offset, since data can | ||
3718 | * be X number of times larger than max data size. | ||
3719 | */ | ||
3720 | ++chan->ifstats.tx_packets; | ||
3721 | chan->ifstats.tx_bytes += len; | ||
3722 | |||
3723 | ++chan->if_send_stat.if_send_bfr_passed_to_adptr; | ||
3724 | chan->tx_offset += len; | ||
3725 | |||
3726 | /* The user can set the qdm bit as well. | ||
3727 | * If the entire packet was sent and qdm is still | ||
3728 | * set, than it's the user who has set the M bit. In that, | ||
3729 | * case indicate that the packet was send by returning | ||
3730 | * 0 and wait for a new packet. Otherwise, wait for next | ||
3731 | * tx interrupt to send the rest of the packet */ | ||
3732 | |||
3733 | if (chan->tx_offset < orig_len){ | ||
3734 | res=1; | ||
3735 | }else{ | ||
3736 | res=0; | ||
3737 | } | ||
3738 | } | ||
3739 | }else{ | ||
3740 | ++chan->ifstats.tx_packets; | ||
3741 | chan->ifstats.tx_bytes += len; | ||
3742 | ++chan->if_send_stat.if_send_bfr_passed_to_adptr; | ||
3743 | res=0; | ||
3744 | } | ||
3745 | break; | ||
3746 | |||
3747 | case 0x33: /* Tx busy */ | ||
3748 | if (tx_intr){ | ||
3749 | printk(KERN_INFO "%s: Tx_intr: Big Error dropping packet %s\n", | ||
3750 | card->devname,dev->name); | ||
3751 | ++chan->ifstats.tx_dropped; | ||
3752 | ++card->wandev.stats.tx_dropped; | ||
3753 | ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr; | ||
3754 | res=0; | ||
3755 | }else{ | ||
3756 | DBG_PRINTK(KERN_INFO | ||
3757 | "%s: Send: Big Error should have tx: storring %s\n", | ||
3758 | card->devname,dev->name); | ||
3759 | setup_for_delayed_transmit (dev, buff, data_len); | ||
3760 | res=1; | ||
3761 | } | ||
3762 | break; | ||
3763 | |||
3764 | default: /* failure */ | ||
3765 | ++chan->ifstats.tx_errors; | ||
3766 | if (tx_intr){ | ||
3767 | printk(KERN_INFO "%s: Tx_intr: Failure to send, dropping %s\n", | ||
3768 | card->devname,dev->name); | ||
3769 | ++chan->ifstats.tx_dropped; | ||
3770 | ++card->wandev.stats.tx_dropped; | ||
3771 | ++chan->if_send_stat.if_send_bfr_not_passed_to_adptr; | ||
3772 | res=0; | ||
3773 | }else{ | ||
3774 | DBG_PRINTK(KERN_INFO "%s: Send: Failure to send !!!, storing %s\n", | ||
3775 | card->devname,dev->name); | ||
3776 | setup_for_delayed_transmit (dev, buff, data_len); | ||
3777 | res=1; | ||
3778 | } | ||
3779 | break; | ||
3780 | } | ||
3781 | return res; | ||
3782 | } | ||
3783 | |||
3784 | |||
3785 | /* | ||
3786 | * Parse X.25 call request data and fill x25_call_info_t structure. | ||
3787 | */ | ||
3788 | |||
3789 | static void parse_call_info (unsigned char* str, x25_call_info_t* info) | ||
3790 | { | ||
3791 | memset(info, 0, sizeof(x25_call_info_t)); | ||
3792 | for (; *str; ++str) | ||
3793 | { | ||
3794 | int i; | ||
3795 | unsigned char ch; | ||
3796 | |||
3797 | if (*str == '-') switch (str[1]) { | ||
3798 | |||
3799 | /* Take minus 2 off the maximum size so that | ||
3800 | * last byte is 0. This way we can use string | ||
3801 | * manipulaton functions on call information. | ||
3802 | */ | ||
3803 | |||
3804 | case 'd': /* destination address */ | ||
3805 | for (i = 0; i < (MAX_X25_ADDR_SIZE-2); ++i){ | ||
3806 | ch = str[2+i]; | ||
3807 | if (isspace(ch)) break; | ||
3808 | info->dest[i] = ch; | ||
3809 | } | ||
3810 | break; | ||
3811 | |||
3812 | case 's': /* source address */ | ||
3813 | for (i = 0; i < (MAX_X25_ADDR_SIZE-2); ++i){ | ||
3814 | ch = str[2+i]; | ||
3815 | if (isspace(ch)) break; | ||
3816 | info->src[i] = ch; | ||
3817 | } | ||
3818 | break; | ||
3819 | |||
3820 | case 'u': /* user data */ | ||
3821 | for (i = 0; i < (MAX_X25_DATA_SIZE-2); ++i){ | ||
3822 | ch = str[2+i]; | ||
3823 | if (isspace(ch)) break; | ||
3824 | info->user[i] = ch; | ||
3825 | } | ||
3826 | info->nuser = i; | ||
3827 | break; | ||
3828 | |||
3829 | case 'f': /* facilities */ | ||
3830 | for (i = 0; i < (MAX_X25_FACL_SIZE-2); ++i){ | ||
3831 | ch = str[2+i]; | ||
3832 | if (isspace(ch)) break; | ||
3833 | info->facil[i] = ch; | ||
3834 | } | ||
3835 | info->nfacil = i; | ||
3836 | break; | ||
3837 | } | ||
3838 | } | ||
3839 | } | ||
3840 | |||
3841 | /* | ||
3842 | * Convert line speed in bps to a number used by S502 code. | ||
3843 | */ | ||
3844 | |||
3845 | static unsigned char bps_to_speed_code (unsigned long bps) | ||
3846 | { | ||
3847 | unsigned char number; | ||
3848 | |||
3849 | if (bps <= 1200) number = 0x01; | ||
3850 | else if (bps <= 2400) number = 0x02; | ||
3851 | else if (bps <= 4800) number = 0x03; | ||
3852 | else if (bps <= 9600) number = 0x04; | ||
3853 | else if (bps <= 19200) number = 0x05; | ||
3854 | else if (bps <= 38400) number = 0x06; | ||
3855 | else if (bps <= 45000) number = 0x07; | ||
3856 | else if (bps <= 56000) number = 0x08; | ||
3857 | else if (bps <= 64000) number = 0x09; | ||
3858 | else if (bps <= 74000) number = 0x0A; | ||
3859 | else if (bps <= 112000) number = 0x0B; | ||
3860 | else if (bps <= 128000) number = 0x0C; | ||
3861 | else number = 0x0D; | ||
3862 | |||
3863 | return number; | ||
3864 | } | ||
3865 | |||
3866 | /* | ||
3867 | * Convert decimal string to unsigned integer. | ||
3868 | * If len != 0 then only 'len' characters of the string are converted. | ||
3869 | */ | ||
3870 | |||
3871 | static unsigned int dec_to_uint (unsigned char* str, int len) | ||
3872 | { | ||
3873 | unsigned val; | ||
3874 | |||
3875 | if (!len) | ||
3876 | len = strlen(str); | ||
3877 | |||
3878 | for (val = 0; len && isdigit(*str); ++str, --len) | ||
3879 | val = (val * 10) + (*str - (unsigned)'0'); | ||
3880 | |||
3881 | return val; | ||
3882 | } | ||
3883 | |||
3884 | /* | ||
3885 | * Convert hex string to unsigned integer. | ||
3886 | * If len != 0 then only 'len' characters of the string are conferted. | ||
3887 | */ | ||
3888 | |||
3889 | static unsigned int hex_to_uint (unsigned char* str, int len) | ||
3890 | { | ||
3891 | unsigned val, ch; | ||
3892 | |||
3893 | if (!len) | ||
3894 | len = strlen(str); | ||
3895 | |||
3896 | for (val = 0; len; ++str, --len) | ||
3897 | { | ||
3898 | ch = *str; | ||
3899 | if (isdigit(ch)) | ||
3900 | val = (val << 4) + (ch - (unsigned)'0'); | ||
3901 | else if (isxdigit(ch)) | ||
3902 | val = (val << 4) + ((ch & 0xDF) - (unsigned)'A' + 10); | ||
3903 | else break; | ||
3904 | } | ||
3905 | return val; | ||
3906 | } | ||
3907 | |||
3908 | |||
3909 | static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto) | ||
3910 | { | ||
3911 | int i; | ||
3912 | |||
3913 | if( proto == ETH_P_IPX) { | ||
3914 | /* It's an IPX packet */ | ||
3915 | if(!enable_IPX) { | ||
3916 | /* Return 1 so we don't pass it up the stack. */ | ||
3917 | return 1; | ||
3918 | } | ||
3919 | } else { | ||
3920 | /* It's not IPX so pass it up the stack.*/ | ||
3921 | return 0; | ||
3922 | } | ||
3923 | |||
3924 | if( sendpacket[16] == 0x90 && | ||
3925 | sendpacket[17] == 0x04) | ||
3926 | { | ||
3927 | /* It's IPXWAN */ | ||
3928 | |||
3929 | if( sendpacket[2] == 0x02 && | ||
3930 | sendpacket[34] == 0x00) | ||
3931 | { | ||
3932 | /* It's a timer request packet */ | ||
3933 | printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname); | ||
3934 | |||
3935 | /* Go through the routing options and answer no to every | ||
3936 | * option except Unnumbered RIP/SAP | ||
3937 | */ | ||
3938 | for(i = 41; sendpacket[i] == 0x00; i += 5) | ||
3939 | { | ||
3940 | /* 0x02 is the option for Unnumbered RIP/SAP */ | ||
3941 | if( sendpacket[i + 4] != 0x02) | ||
3942 | { | ||
3943 | sendpacket[i + 1] = 0; | ||
3944 | } | ||
3945 | } | ||
3946 | |||
3947 | /* Skip over the extended Node ID option */ | ||
3948 | if( sendpacket[i] == 0x04 ) | ||
3949 | { | ||
3950 | i += 8; | ||
3951 | } | ||
3952 | |||
3953 | /* We also want to turn off all header compression opt. */ | ||
3954 | for(; sendpacket[i] == 0x80 ;) | ||
3955 | { | ||
3956 | sendpacket[i + 1] = 0; | ||
3957 | i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4; | ||
3958 | } | ||
3959 | |||
3960 | /* Set the packet type to timer response */ | ||
3961 | sendpacket[34] = 0x01; | ||
3962 | |||
3963 | printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname); | ||
3964 | } | ||
3965 | else if( sendpacket[34] == 0x02 ) | ||
3966 | { | ||
3967 | /* This is an information request packet */ | ||
3968 | printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname); | ||
3969 | |||
3970 | /* Set the packet type to information response */ | ||
3971 | sendpacket[34] = 0x03; | ||
3972 | |||
3973 | /* Set the router name */ | ||
3974 | sendpacket[51] = 'X'; | ||
3975 | sendpacket[52] = 'T'; | ||
3976 | sendpacket[53] = 'P'; | ||
3977 | sendpacket[54] = 'I'; | ||
3978 | sendpacket[55] = 'P'; | ||
3979 | sendpacket[56] = 'E'; | ||
3980 | sendpacket[57] = '-'; | ||
3981 | sendpacket[58] = CVHexToAscii(network_number >> 28); | ||
3982 | sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24); | ||
3983 | sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20); | ||
3984 | sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16); | ||
3985 | sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12); | ||
3986 | sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8); | ||
3987 | sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4); | ||
3988 | sendpacket[65] = CVHexToAscii(network_number & 0x0000000F); | ||
3989 | for(i = 66; i < 99; i+= 1) | ||
3990 | { | ||
3991 | sendpacket[i] = 0; | ||
3992 | } | ||
3993 | |||
3994 | printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname); | ||
3995 | } | ||
3996 | else | ||
3997 | { | ||
3998 | printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname); | ||
3999 | return 0; | ||
4000 | } | ||
4001 | |||
4002 | /* Set the WNodeID to our network address */ | ||
4003 | sendpacket[35] = (unsigned char)(network_number >> 24); | ||
4004 | sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16); | ||
4005 | sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8); | ||
4006 | sendpacket[38] = (unsigned char)(network_number & 0x000000FF); | ||
4007 | |||
4008 | return 1; | ||
4009 | } else { | ||
4010 | /*If we get here it's an IPX-data packet, so it'll get passed up the stack. | ||
4011 | */ | ||
4012 | /* switch the network numbers */ | ||
4013 | switch_net_numbers(sendpacket, network_number, 1); | ||
4014 | return 0; | ||
4015 | } | ||
4016 | } | ||
4017 | |||
4018 | /* | ||
4019 | * If incoming is 0 (outgoing)- if the net numbers is ours make it 0 | ||
4020 | * if incoming is 1 - if the net number is 0 make it ours | ||
4021 | */ | ||
4022 | |||
4023 | static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming) | ||
4024 | { | ||
4025 | unsigned long pnetwork_number; | ||
4026 | |||
4027 | pnetwork_number = (unsigned long)((sendpacket[6] << 24) + | ||
4028 | (sendpacket[7] << 16) + (sendpacket[8] << 8) + | ||
4029 | sendpacket[9]); | ||
4030 | |||
4031 | |||
4032 | if (!incoming) { | ||
4033 | /*If the destination network number is ours, make it 0 */ | ||
4034 | if( pnetwork_number == network_number) { | ||
4035 | sendpacket[6] = sendpacket[7] = sendpacket[8] = | ||
4036 | sendpacket[9] = 0x00; | ||
4037 | } | ||
4038 | } else { | ||
4039 | /* If the incoming network is 0, make it ours */ | ||
4040 | if( pnetwork_number == 0) { | ||
4041 | sendpacket[6] = (unsigned char)(network_number >> 24); | ||
4042 | sendpacket[7] = (unsigned char)((network_number & | ||
4043 | 0x00FF0000) >> 16); | ||
4044 | sendpacket[8] = (unsigned char)((network_number & | ||
4045 | 0x0000FF00) >> 8); | ||
4046 | sendpacket[9] = (unsigned char)(network_number & | ||
4047 | 0x000000FF); | ||
4048 | } | ||
4049 | } | ||
4050 | |||
4051 | |||
4052 | pnetwork_number = (unsigned long)((sendpacket[18] << 24) + | ||
4053 | (sendpacket[19] << 16) + (sendpacket[20] << 8) + | ||
4054 | sendpacket[21]); | ||
4055 | |||
4056 | |||
4057 | if( !incoming ) { | ||
4058 | /* If the source network is ours, make it 0 */ | ||
4059 | if( pnetwork_number == network_number) { | ||
4060 | sendpacket[18] = sendpacket[19] = sendpacket[20] = | ||
4061 | sendpacket[21] = 0x00; | ||
4062 | } | ||
4063 | } else { | ||
4064 | /* If the source network is 0, make it ours */ | ||
4065 | if( pnetwork_number == 0 ) { | ||
4066 | sendpacket[18] = (unsigned char)(network_number >> 24); | ||
4067 | sendpacket[19] = (unsigned char)((network_number & | ||
4068 | 0x00FF0000) >> 16); | ||
4069 | sendpacket[20] = (unsigned char)((network_number & | ||
4070 | 0x0000FF00) >> 8); | ||
4071 | sendpacket[21] = (unsigned char)(network_number & | ||
4072 | 0x000000FF); | ||
4073 | } | ||
4074 | } | ||
4075 | } /* switch_net_numbers */ | ||
4076 | |||
4077 | |||
4078 | |||
4079 | |||
4080 | /********************* X25API SPECIFIC FUNCTIONS ****************/ | ||
4081 | |||
4082 | |||
4083 | /*=============================================================== | ||
4084 | * find_channel | ||
4085 | * | ||
4086 | * Manages the lcn to device map. It increases performance | ||
4087 | * because it eliminates the need to search through the link | ||
4088 | * list for a device which is bounded to a specific lcn. | ||
4089 | * | ||
4090 | *===============================================================*/ | ||
4091 | |||
4092 | |||
4093 | struct net_device *find_channel(sdla_t *card, unsigned lcn) | ||
4094 | { | ||
4095 | if (card->u.x.LAPB_hdlc){ | ||
4096 | |||
4097 | return card->wandev.dev; | ||
4098 | |||
4099 | }else{ | ||
4100 | /* We don't know whether the incoming lcn | ||
4101 | * is a PVC or an SVC channel. But we do know that | ||
4102 | * the lcn cannot be for both the PVC and the SVC | ||
4103 | * channel. | ||
4104 | |||
4105 | * If the lcn number is greater or equal to 255, | ||
4106 | * take the modulo 255 of that number. We only have | ||
4107 | * 255 locations, thus higher numbers must be mapped | ||
4108 | * to a number between 0 and 245. | ||
4109 | |||
4110 | * We must separate pvc's and svc's since two don't | ||
4111 | * have to be contiguous. Meaning pvc's can start | ||
4112 | * from 1 to 10 and svc's can start from 256 to 266. | ||
4113 | * But 256%255 is 1, i.e. CONFLICT. | ||
4114 | */ | ||
4115 | |||
4116 | |||
4117 | /* Highest LCN number must be less or equal to 4096 */ | ||
4118 | if ((lcn <= MAX_LCN_NUM) && (lcn > 0)){ | ||
4119 | |||
4120 | if (lcn < X25_MAX_CHAN){ | ||
4121 | if (card->u.x.svc_to_dev_map[lcn]) | ||
4122 | return card->u.x.svc_to_dev_map[lcn]; | ||
4123 | |||
4124 | if (card->u.x.pvc_to_dev_map[lcn]) | ||
4125 | return card->u.x.pvc_to_dev_map[lcn]; | ||
4126 | |||
4127 | }else{ | ||
4128 | int new_lcn = lcn%X25_MAX_CHAN; | ||
4129 | if (card->u.x.svc_to_dev_map[new_lcn]) | ||
4130 | return card->u.x.svc_to_dev_map[new_lcn]; | ||
4131 | |||
4132 | if (card->u.x.pvc_to_dev_map[new_lcn]) | ||
4133 | return card->u.x.pvc_to_dev_map[new_lcn]; | ||
4134 | } | ||
4135 | } | ||
4136 | return NULL; | ||
4137 | } | ||
4138 | } | ||
4139 | |||
4140 | void bind_lcn_to_dev(sdla_t *card, struct net_device *dev, unsigned lcn) | ||
4141 | { | ||
4142 | x25_channel_t *chan = dev->priv; | ||
4143 | |||
4144 | /* Modulo the lcn number by X25_MAX_CHAN (255) | ||
4145 | * because the lcn number can be greater than 255 | ||
4146 | * | ||
4147 | * We need to split svc and pvc since they don't have | ||
4148 | * to be contigous. | ||
4149 | */ | ||
4150 | |||
4151 | if (chan->common.svc){ | ||
4152 | card->u.x.svc_to_dev_map[(lcn % X25_MAX_CHAN)] = dev; | ||
4153 | }else{ | ||
4154 | card->u.x.pvc_to_dev_map[(lcn % X25_MAX_CHAN)] = dev; | ||
4155 | } | ||
4156 | chan->common.lcn = lcn; | ||
4157 | } | ||
4158 | |||
4159 | |||
4160 | |||
4161 | /*=============================================================== | ||
4162 | * x25api_bh | ||
4163 | * | ||
4164 | * | ||
4165 | *==============================================================*/ | ||
4166 | |||
4167 | static void x25api_bh(struct net_device* dev) | ||
4168 | { | ||
4169 | x25_channel_t* chan = dev->priv; | ||
4170 | sdla_t* card = chan->card; | ||
4171 | struct sk_buff *skb; | ||
4172 | |||
4173 | if (atomic_read(&chan->bh_buff_used) == 0){ | ||
4174 | printk(KERN_INFO "%s: BH Buffer Empty in BH\n", | ||
4175 | card->devname); | ||
4176 | clear_bit(0, &chan->tq_working); | ||
4177 | return; | ||
4178 | } | ||
4179 | |||
4180 | while (atomic_read(&chan->bh_buff_used)){ | ||
4181 | |||
4182 | /* If the sock is in the process of unlinking the | ||
4183 | * driver from the socket, we must get out. | ||
4184 | * This never happends but is a sanity check. */ | ||
4185 | if (test_bit(0,&chan->common.common_critical)){ | ||
4186 | clear_bit(0, &chan->tq_working); | ||
4187 | return; | ||
4188 | } | ||
4189 | |||
4190 | /* If LAPB HDLC, do not drop packets if socket is | ||
4191 | * not connected. Let the buffer fill up and | ||
4192 | * turn off rx interrupt */ | ||
4193 | if (card->u.x.LAPB_hdlc){ | ||
4194 | if (chan->common.sk == NULL || chan->common.func == NULL){ | ||
4195 | clear_bit(0, &chan->tq_working); | ||
4196 | return; | ||
4197 | } | ||
4198 | } | ||
4199 | |||
4200 | skb = ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb; | ||
4201 | |||
4202 | if (skb == NULL){ | ||
4203 | printk(KERN_INFO "%s: BH Skb empty for read %i\n", | ||
4204 | card->devname,chan->bh_read); | ||
4205 | }else{ | ||
4206 | |||
4207 | if (chan->common.sk == NULL || chan->common.func == NULL){ | ||
4208 | printk(KERN_INFO "%s: BH: Socket disconnected, dropping\n", | ||
4209 | card->devname); | ||
4210 | dev_kfree_skb_any(skb); | ||
4211 | x25api_bh_cleanup(dev); | ||
4212 | ++chan->ifstats.rx_dropped; | ||
4213 | ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; | ||
4214 | continue; | ||
4215 | } | ||
4216 | |||
4217 | |||
4218 | if (chan->common.func(skb,dev,chan->common.sk) != 0){ | ||
4219 | /* Sock full cannot send, queue us for another | ||
4220 | * try | ||
4221 | */ | ||
4222 | printk(KERN_INFO "%s: BH: !!! Packet failed to send !!!!! \n", | ||
4223 | card->devname); | ||
4224 | atomic_set(&chan->common.receive_block,1); | ||
4225 | return; | ||
4226 | }else{ | ||
4227 | x25api_bh_cleanup(dev); | ||
4228 | ++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack; | ||
4229 | } | ||
4230 | } | ||
4231 | } | ||
4232 | clear_bit(0, &chan->tq_working); | ||
4233 | |||
4234 | return; | ||
4235 | } | ||
4236 | |||
4237 | /*=============================================================== | ||
4238 | * x25api_bh_cleanup | ||
4239 | * | ||
4240 | * | ||
4241 | *==============================================================*/ | ||
4242 | |||
4243 | static int x25api_bh_cleanup(struct net_device *dev) | ||
4244 | { | ||
4245 | x25_channel_t* chan = dev->priv; | ||
4246 | sdla_t *card = chan->card; | ||
4247 | TX25Status* status = card->flags; | ||
4248 | |||
4249 | |||
4250 | ((bh_data_t *)&chan->bh_head[chan->bh_read])->skb = NULL; | ||
4251 | |||
4252 | if (chan->bh_read == MAX_BH_BUFF){ | ||
4253 | chan->bh_read=0; | ||
4254 | }else{ | ||
4255 | ++chan->bh_read; | ||
4256 | } | ||
4257 | |||
4258 | /* If the Receive interrupt was off, it means | ||
4259 | * that we filled up our circular buffer. Check | ||
4260 | * that we have space in the buffer. If so | ||
4261 | * turn the RX interrupt back on. | ||
4262 | */ | ||
4263 | if (!(status->imask & INTR_ON_RX_FRAME)){ | ||
4264 | if (atomic_read(&chan->bh_buff_used) < (MAX_BH_BUFF+1)){ | ||
4265 | printk(KERN_INFO "%s: BH: Turning on the interrupt\n", | ||
4266 | card->devname); | ||
4267 | status->imask |= INTR_ON_RX_FRAME; | ||
4268 | } | ||
4269 | } | ||
4270 | |||
4271 | atomic_dec(&chan->bh_buff_used); | ||
4272 | return 0; | ||
4273 | } | ||
4274 | |||
4275 | |||
4276 | /*=============================================================== | ||
4277 | * bh_enqueue | ||
4278 | * | ||
4279 | * | ||
4280 | *==============================================================*/ | ||
4281 | |||
4282 | static int bh_enqueue(struct net_device *dev, struct sk_buff *skb) | ||
4283 | { | ||
4284 | x25_channel_t* chan = dev->priv; | ||
4285 | sdla_t *card = chan->card; | ||
4286 | TX25Status* status = card->flags; | ||
4287 | |||
4288 | if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){ | ||
4289 | printk(KERN_INFO "%s: Bottom half buffer FULL\n", | ||
4290 | card->devname); | ||
4291 | return 1; | ||
4292 | } | ||
4293 | |||
4294 | ((bh_data_t *)&chan->bh_head[chan->bh_write])->skb = skb; | ||
4295 | |||
4296 | if (chan->bh_write == MAX_BH_BUFF){ | ||
4297 | chan->bh_write=0; | ||
4298 | }else{ | ||
4299 | ++chan->bh_write; | ||
4300 | } | ||
4301 | |||
4302 | atomic_inc(&chan->bh_buff_used); | ||
4303 | |||
4304 | if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){ | ||
4305 | printk(KERN_INFO "%s: Buffer is now full, Turning off RX Intr\n", | ||
4306 | card->devname); | ||
4307 | status->imask &= ~INTR_ON_RX_FRAME; | ||
4308 | } | ||
4309 | |||
4310 | return 0; | ||
4311 | } | ||
4312 | |||
4313 | |||
4314 | /*=============================================================== | ||
4315 | * timer_intr_cmd_exec | ||
4316 | * | ||
4317 | * Called by timer interrupt to execute a command | ||
4318 | *===============================================================*/ | ||
4319 | |||
4320 | static int timer_intr_cmd_exec (sdla_t* card) | ||
4321 | { | ||
4322 | struct net_device *dev; | ||
4323 | unsigned char more_to_exec=0; | ||
4324 | volatile x25_channel_t *chan=NULL; | ||
4325 | int i=0,bad_cmd=0,err=0; | ||
4326 | |||
4327 | if (card->u.x.cmd_dev == NULL){ | ||
4328 | card->u.x.cmd_dev = card->wandev.dev; | ||
4329 | } | ||
4330 | |||
4331 | dev = card->u.x.cmd_dev; | ||
4332 | |||
4333 | for (;;){ | ||
4334 | |||
4335 | chan = dev->priv; | ||
4336 | |||
4337 | if (atomic_read(&chan->common.command)){ | ||
4338 | |||
4339 | bad_cmd = check_bad_command(card,dev); | ||
4340 | |||
4341 | if ((!chan->common.mbox || atomic_read(&chan->common.disconnect)) && | ||
4342 | !bad_cmd){ | ||
4343 | |||
4344 | /* Socket has died or exited, We must bring the | ||
4345 | * channel down before anybody else tries to | ||
4346 | * use it */ | ||
4347 | err = channel_disconnect(card,dev); | ||
4348 | }else{ | ||
4349 | err = execute_delayed_cmd(card, dev, | ||
4350 | (mbox_cmd_t*)chan->common.mbox, | ||
4351 | bad_cmd); | ||
4352 | } | ||
4353 | |||
4354 | switch (err){ | ||
4355 | |||
4356 | case RETURN_RESULT: | ||
4357 | |||
4358 | /* Return the result to the socket without | ||
4359 | * delay. NO_WAIT Command */ | ||
4360 | atomic_set(&chan->common.command,0); | ||
4361 | if (atomic_read(&card->u.x.command_busy)) | ||
4362 | atomic_set(&card->u.x.command_busy,0); | ||
4363 | |||
4364 | send_delayed_cmd_result(card,dev,card->mbox); | ||
4365 | |||
4366 | more_to_exec=0; | ||
4367 | break; | ||
4368 | case DELAY_RESULT: | ||
4369 | |||
4370 | /* Wait for the remote to respond, before | ||
4371 | * sending the result up to the socket. | ||
4372 | * WAIT command */ | ||
4373 | if (atomic_read(&card->u.x.command_busy)) | ||
4374 | atomic_set(&card->u.x.command_busy,0); | ||
4375 | |||
4376 | atomic_set(&chan->common.command,0); | ||
4377 | more_to_exec=0; | ||
4378 | break; | ||
4379 | default: | ||
4380 | |||
4381 | /* If command could not be executed for | ||
4382 | * some reason (i.e return code 0x33 busy) | ||
4383 | * set the more_to_exec bit which will | ||
4384 | * indicate that this command must be exectued | ||
4385 | * again during next timer interrupt | ||
4386 | */ | ||
4387 | more_to_exec=1; | ||
4388 | if (atomic_read(&card->u.x.command_busy) == 0) | ||
4389 | atomic_set(&card->u.x.command_busy,1); | ||
4390 | break; | ||
4391 | } | ||
4392 | |||
4393 | bad_cmd=0; | ||
4394 | |||
4395 | /* If flags is set, there are no hdlc buffers, | ||
4396 | * thus, wait for the next pass and try the | ||
4397 | * same command again. Otherwise, start searching | ||
4398 | * from next device on the next pass. | ||
4399 | */ | ||
4400 | if (!more_to_exec){ | ||
4401 | dev = move_dev_to_next(card,dev); | ||
4402 | } | ||
4403 | break; | ||
4404 | }else{ | ||
4405 | /* This device has nothing to execute, | ||
4406 | * go to next. | ||
4407 | */ | ||
4408 | if (atomic_read(&card->u.x.command_busy)) | ||
4409 | atomic_set(&card->u.x.command_busy,0); | ||
4410 | dev = move_dev_to_next(card,dev); | ||
4411 | } | ||
4412 | |||
4413 | if (++i == card->u.x.no_dev){ | ||
4414 | if (!more_to_exec){ | ||
4415 | DBG_PRINTK(KERN_INFO "%s: Nothing to execute in Timer\n", | ||
4416 | card->devname); | ||
4417 | if (atomic_read(&card->u.x.command_busy)){ | ||
4418 | atomic_set(&card->u.x.command_busy,0); | ||
4419 | } | ||
4420 | } | ||
4421 | break; | ||
4422 | } | ||
4423 | |||
4424 | } //End of FOR | ||
4425 | |||
4426 | card->u.x.cmd_dev = dev; | ||
4427 | |||
4428 | if (more_to_exec){ | ||
4429 | /* If more commands are pending, do not turn off timer | ||
4430 | * interrupt */ | ||
4431 | return 1; | ||
4432 | }else{ | ||
4433 | /* No more commands, turn off timer interrupt */ | ||
4434 | return 0; | ||
4435 | } | ||
4436 | } | ||
4437 | |||
4438 | /*=============================================================== | ||
4439 | * execute_delayed_cmd | ||
4440 | * | ||
4441 | * Execute an API command which was passed down from the | ||
4442 | * sock. Sock is very limited in which commands it can | ||
4443 | * execute. Wait and No Wait commands are supported. | ||
4444 | * Place Call, Clear Call and Reset wait commands, where | ||
4445 | * Accept Call is a no_wait command. | ||
4446 | * | ||
4447 | *===============================================================*/ | ||
4448 | |||
4449 | static int execute_delayed_cmd(sdla_t* card, struct net_device *dev, | ||
4450 | mbox_cmd_t *usr_cmd, char bad_cmd) | ||
4451 | { | ||
4452 | TX25Mbox* mbox = card->mbox; | ||
4453 | int err; | ||
4454 | x25_channel_t *chan = dev->priv; | ||
4455 | int delay=RETURN_RESULT; | ||
4456 | |||
4457 | if (!(*card->u.x.hdlc_buf_status & 0x40) && !bad_cmd){ | ||
4458 | return TRY_CMD_AGAIN; | ||
4459 | } | ||
4460 | |||
4461 | /* This way a command is guaranteed to be executed for | ||
4462 | * a specific lcn, the network interface is bound to. */ | ||
4463 | usr_cmd->cmd.lcn = chan->common.lcn; | ||
4464 | |||
4465 | |||
4466 | /* If channel is pvc, instead of place call | ||
4467 | * run x25_channel configuration. If running LAPB HDLC | ||
4468 | * enable communications. | ||
4469 | */ | ||
4470 | if ((!chan->common.svc) && (usr_cmd->cmd.command == X25_PLACE_CALL)){ | ||
4471 | |||
4472 | if (card->u.x.LAPB_hdlc){ | ||
4473 | DBG_PRINTK(KERN_INFO "LAPB: Connecting\n"); | ||
4474 | connect(card); | ||
4475 | set_chan_state(dev,WAN_CONNECTING); | ||
4476 | return DELAY_RESULT; | ||
4477 | }else{ | ||
4478 | DBG_PRINTK(KERN_INFO "%s: PVC is CONNECTING\n",card->devname); | ||
4479 | if (x25_get_chan_conf(card, chan) == CMD_OK){ | ||
4480 | set_chan_state(dev, WAN_CONNECTED); | ||
4481 | }else{ | ||
4482 | set_chan_state(dev, WAN_DISCONNECTED); | ||
4483 | } | ||
4484 | return RETURN_RESULT; | ||
4485 | } | ||
4486 | } | ||
4487 | |||
4488 | /* Copy the socket mbox command onto the board */ | ||
4489 | |||
4490 | memcpy(&mbox->cmd, &usr_cmd->cmd, sizeof(TX25Cmd)); | ||
4491 | if (usr_cmd->cmd.length){ | ||
4492 | memcpy(mbox->data, usr_cmd->data, usr_cmd->cmd.length); | ||
4493 | } | ||
4494 | |||
4495 | /* Check if command is bad. We need to copy the cmd into | ||
4496 | * the buffer regardless since we return the, mbox to | ||
4497 | * the user */ | ||
4498 | if (bad_cmd){ | ||
4499 | mbox->cmd.result=0x01; | ||
4500 | return RETURN_RESULT; | ||
4501 | } | ||
4502 | |||
4503 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
4504 | |||
4505 | if (err != CMD_OK && err != X25RES_NOT_READY) | ||
4506 | x25_error(card, err, usr_cmd->cmd.command, usr_cmd->cmd.lcn); | ||
4507 | |||
4508 | if (mbox->cmd.result == X25RES_NOT_READY){ | ||
4509 | return TRY_CMD_AGAIN; | ||
4510 | } | ||
4511 | |||
4512 | switch (mbox->cmd.command){ | ||
4513 | |||
4514 | case X25_PLACE_CALL: | ||
4515 | |||
4516 | switch (mbox->cmd.result){ | ||
4517 | |||
4518 | case CMD_OK: | ||
4519 | |||
4520 | /* Check if Place call is a wait command or a | ||
4521 | * no wait command */ | ||
4522 | if (atomic_read(&chan->common.command) & 0x80) | ||
4523 | delay=RETURN_RESULT; | ||
4524 | else | ||
4525 | delay=DELAY_RESULT; | ||
4526 | |||
4527 | |||
4528 | DBG_PRINTK(KERN_INFO "\n%s: PLACE CALL Binding dev %s to lcn %i\n", | ||
4529 | card->devname,dev->name, mbox->cmd.lcn); | ||
4530 | |||
4531 | bind_lcn_to_dev (card, dev, mbox->cmd.lcn); | ||
4532 | set_chan_state(dev, WAN_CONNECTING); | ||
4533 | break; | ||
4534 | |||
4535 | |||
4536 | default: | ||
4537 | delay=RETURN_RESULT; | ||
4538 | set_chan_state(dev, WAN_DISCONNECTED); | ||
4539 | break; | ||
4540 | } | ||
4541 | break; | ||
4542 | |||
4543 | case X25_ACCEPT_CALL: | ||
4544 | |||
4545 | switch (mbox->cmd.result){ | ||
4546 | |||
4547 | case CMD_OK: | ||
4548 | |||
4549 | DBG_PRINTK(KERN_INFO "\n%s: ACCEPT Binding dev %s to lcn %i\n", | ||
4550 | card->devname,dev->name,mbox->cmd.lcn); | ||
4551 | |||
4552 | bind_lcn_to_dev (card, dev, mbox->cmd.lcn); | ||
4553 | |||
4554 | if (x25_get_chan_conf(card, chan) == CMD_OK){ | ||
4555 | |||
4556 | set_chan_state(dev, WAN_CONNECTED); | ||
4557 | delay=RETURN_RESULT; | ||
4558 | |||
4559 | }else{ | ||
4560 | if (x25_clear_call(card, usr_cmd->cmd.lcn, 0, 0) == CMD_OK){ | ||
4561 | /* if clear is successful, wait for clear confirm | ||
4562 | */ | ||
4563 | delay=DELAY_RESULT; | ||
4564 | }else{ | ||
4565 | /* Do not change the state here. If we fail | ||
4566 | * the accept the return code is send up | ||
4567 | *the stack, which will ether retry | ||
4568 | * or clear the call | ||
4569 | */ | ||
4570 | DBG_PRINTK(KERN_INFO | ||
4571 | "%s: ACCEPT: STATE MAY BE CURRUPTED 2 !!!!!\n", | ||
4572 | card->devname); | ||
4573 | delay=RETURN_RESULT; | ||
4574 | } | ||
4575 | } | ||
4576 | break; | ||
4577 | |||
4578 | |||
4579 | case X25RES_ASYNC_PACKET: | ||
4580 | delay=TRY_CMD_AGAIN; | ||
4581 | break; | ||
4582 | |||
4583 | default: | ||
4584 | DBG_PRINTK(KERN_INFO "%s: ACCEPT FAILED\n",card->devname); | ||
4585 | if (x25_clear_call(card, usr_cmd->cmd.lcn, 0, 0) == CMD_OK){ | ||
4586 | delay=DELAY_RESULT; | ||
4587 | }else{ | ||
4588 | /* Do not change the state here. If we fail the accept. The | ||
4589 | * return code is send up the stack, which will ether retry | ||
4590 | * or clear the call */ | ||
4591 | DBG_PRINTK(KERN_INFO | ||
4592 | "%s: ACCEPT: STATE MAY BE CORRUPTED 1 !!!!!\n", | ||
4593 | card->devname); | ||
4594 | delay=RETURN_RESULT; | ||
4595 | } | ||
4596 | } | ||
4597 | break; | ||
4598 | |||
4599 | case X25_CLEAR_CALL: | ||
4600 | |||
4601 | switch (mbox->cmd.result){ | ||
4602 | |||
4603 | case CMD_OK: | ||
4604 | DBG_PRINTK(KERN_INFO | ||
4605 | "CALL CLEAR OK: Dev %s Mbox Lcn %i Chan Lcn %i\n", | ||
4606 | dev->name,mbox->cmd.lcn,chan->common.lcn); | ||
4607 | set_chan_state(dev, WAN_DISCONNECTING); | ||
4608 | delay = DELAY_RESULT; | ||
4609 | break; | ||
4610 | |||
4611 | case X25RES_CHANNEL_IN_USE: | ||
4612 | case X25RES_ASYNC_PACKET: | ||
4613 | delay = TRY_CMD_AGAIN; | ||
4614 | break; | ||
4615 | |||
4616 | case X25RES_LINK_NOT_IN_ABM: | ||
4617 | case X25RES_INVAL_LCN: | ||
4618 | case X25RES_INVAL_STATE: | ||
4619 | set_chan_state(dev, WAN_DISCONNECTED); | ||
4620 | delay = RETURN_RESULT; | ||
4621 | break; | ||
4622 | |||
4623 | default: | ||
4624 | /* If command did not execute because of user | ||
4625 | * fault, do not change the state. This will | ||
4626 | * signal the socket that clear command failed. | ||
4627 | * User can retry or close the socket. | ||
4628 | * When socket gets killed, it will set the | ||
4629 | * chan->disconnect which will signal | ||
4630 | * driver to clear the call */ | ||
4631 | printk(KERN_INFO "%s: Clear Command Failed, Rc %x\n", | ||
4632 | card->devname,mbox->cmd.command); | ||
4633 | delay = RETURN_RESULT; | ||
4634 | } | ||
4635 | break; | ||
4636 | } | ||
4637 | |||
4638 | return delay; | ||
4639 | } | ||
4640 | |||
4641 | /*=============================================================== | ||
4642 | * api_incoming_call | ||
4643 | * | ||
4644 | * Pass an incoming call request up the listening | ||
4645 | * sock. If the API sock is not listening reject the | ||
4646 | * call. | ||
4647 | * | ||
4648 | *===============================================================*/ | ||
4649 | |||
4650 | static int api_incoming_call (sdla_t* card, TX25Mbox *mbox, int lcn) | ||
4651 | { | ||
4652 | struct sk_buff *skb; | ||
4653 | int len = sizeof(TX25Cmd)+mbox->cmd.length; | ||
4654 | |||
4655 | if (alloc_and_init_skb_buf(card, &skb, len)){ | ||
4656 | printk(KERN_INFO "%s: API incoming call, no memory\n",card->devname); | ||
4657 | return 1; | ||
4658 | } | ||
4659 | |||
4660 | memcpy(skb_put(skb,len),&mbox->cmd,len); | ||
4661 | |||
4662 | skb->mac.raw = skb->data; | ||
4663 | skb->protocol = htons(X25_PROT); | ||
4664 | skb->pkt_type = WAN_PACKET_ASYNC; | ||
4665 | |||
4666 | if (card->func(skb,card->sk) < 0){ | ||
4667 | printk(KERN_INFO "%s: MAJOR ERROR: Failed to send up place call \n",card->devname); | ||
4668 | dev_kfree_skb_any(skb); | ||
4669 | return 1; | ||
4670 | } | ||
4671 | |||
4672 | return 0; | ||
4673 | } | ||
4674 | |||
4675 | /*=============================================================== | ||
4676 | * send_delayed_cmd_result | ||
4677 | * | ||
4678 | * Wait commands like PLEACE CALL or CLEAR CALL must wait | ||
4679 | * until the result arrives. This function passes | ||
4680 | * the result to a waiting sock. | ||
4681 | * | ||
4682 | *===============================================================*/ | ||
4683 | static void send_delayed_cmd_result(sdla_t *card, struct net_device *dev, | ||
4684 | TX25Mbox* mbox) | ||
4685 | { | ||
4686 | x25_channel_t *chan = dev->priv; | ||
4687 | mbox_cmd_t *usr_cmd = (mbox_cmd_t *)chan->common.mbox; | ||
4688 | struct sk_buff *skb; | ||
4689 | int len=sizeof(unsigned char); | ||
4690 | |||
4691 | atomic_set(&chan->common.command,0); | ||
4692 | |||
4693 | /* If the sock is in the process of unlinking the | ||
4694 | * driver from the socket, we must get out. | ||
4695 | * This never happends but is a sanity check. */ | ||
4696 | if (test_bit(0,&chan->common.common_critical)){ | ||
4697 | return; | ||
4698 | } | ||
4699 | |||
4700 | if (!usr_cmd || !chan->common.sk || !chan->common.func){ | ||
4701 | DBG_PRINTK(KERN_INFO "Delay result: Sock not bounded sk: %u, func: %u, mbox: %u\n", | ||
4702 | (unsigned int)chan->common.sk, | ||
4703 | (unsigned int)chan->common.func, | ||
4704 | (unsigned int)usr_cmd); | ||
4705 | return; | ||
4706 | } | ||
4707 | |||
4708 | memcpy(&usr_cmd->cmd, &mbox->cmd, sizeof(TX25Cmd)); | ||
4709 | if (mbox->cmd.length > 0){ | ||
4710 | memcpy(usr_cmd->data, mbox->data, mbox->cmd.length); | ||
4711 | } | ||
4712 | |||
4713 | if (alloc_and_init_skb_buf(card,&skb,len)){ | ||
4714 | printk(KERN_INFO "Delay result: No sock buffers\n"); | ||
4715 | return; | ||
4716 | } | ||
4717 | |||
4718 | memcpy(skb_put(skb,len),&mbox->cmd.command,len); | ||
4719 | |||
4720 | skb->mac.raw = skb->data; | ||
4721 | skb->pkt_type = WAN_PACKET_CMD; | ||
4722 | |||
4723 | chan->common.func(skb,dev,chan->common.sk); | ||
4724 | } | ||
4725 | |||
4726 | /*=============================================================== | ||
4727 | * clear_confirm_event | ||
4728 | * | ||
4729 | * Pass the clear confirmation event up the sock. The | ||
4730 | * API will disconnect only after the clear confirmation | ||
4731 | * has been received. | ||
4732 | * | ||
4733 | * Depending on the state, clear confirmation could | ||
4734 | * be an OOB event, or a result of an API command. | ||
4735 | *===============================================================*/ | ||
4736 | |||
4737 | static int clear_confirm_event (sdla_t *card, TX25Mbox* mb) | ||
4738 | { | ||
4739 | struct net_device *dev; | ||
4740 | x25_channel_t *chan; | ||
4741 | unsigned char old_state; | ||
4742 | |||
4743 | dev = find_channel(card,mb->cmd.lcn); | ||
4744 | if (!dev){ | ||
4745 | DBG_PRINTK(KERN_INFO "%s: *** GOT CLEAR BUT NO DEV %i\n", | ||
4746 | card->devname,mb->cmd.lcn); | ||
4747 | return 0; | ||
4748 | } | ||
4749 | |||
4750 | chan=dev->priv; | ||
4751 | DBG_PRINTK(KERN_INFO "%s: GOT CLEAR CONFIRM %s: Mbox lcn %i Chan lcn %i\n", | ||
4752 | card->devname, dev->name, mb->cmd.lcn, chan->common.lcn); | ||
4753 | |||
4754 | /* If not API fall through to default. | ||
4755 | * If API, send the result to a waiting | ||
4756 | * socket. | ||
4757 | */ | ||
4758 | |||
4759 | old_state = chan->common.state; | ||
4760 | set_chan_state(dev, WAN_DISCONNECTED); | ||
4761 | |||
4762 | if (chan->common.usedby == API){ | ||
4763 | switch (old_state) { | ||
4764 | |||
4765 | case WAN_DISCONNECTING: | ||
4766 | case WAN_CONNECTING: | ||
4767 | send_delayed_cmd_result(card,dev,mb); | ||
4768 | break; | ||
4769 | case WAN_CONNECTED: | ||
4770 | send_oob_msg(card,dev,mb); | ||
4771 | break; | ||
4772 | } | ||
4773 | return 1; | ||
4774 | } | ||
4775 | |||
4776 | return 0; | ||
4777 | } | ||
4778 | |||
4779 | /*=============================================================== | ||
4780 | * send_oob_msg | ||
4781 | * | ||
4782 | * Construct an NEM Message and pass it up the connected | ||
4783 | * sock. If the sock is not bounded discard the NEM. | ||
4784 | * | ||
4785 | *===============================================================*/ | ||
4786 | |||
4787 | static void send_oob_msg(sdla_t *card, struct net_device *dev, TX25Mbox *mbox) | ||
4788 | { | ||
4789 | x25_channel_t *chan = dev->priv; | ||
4790 | mbox_cmd_t *usr_cmd = (mbox_cmd_t *)chan->common.mbox; | ||
4791 | struct sk_buff *skb; | ||
4792 | int len=sizeof(x25api_hdr_t)+mbox->cmd.length; | ||
4793 | x25api_t *api_hdr; | ||
4794 | |||
4795 | /* If the sock is in the process of unlinking the | ||
4796 | * driver from the socket, we must get out. | ||
4797 | * This never happends but is a sanity check. */ | ||
4798 | if (test_bit(0,&chan->common.common_critical)){ | ||
4799 | return; | ||
4800 | } | ||
4801 | |||
4802 | if (!usr_cmd || !chan->common.sk || !chan->common.func){ | ||
4803 | DBG_PRINTK(KERN_INFO "OOB MSG: Sock not bounded\n"); | ||
4804 | return; | ||
4805 | } | ||
4806 | |||
4807 | memcpy(&usr_cmd->cmd, &mbox->cmd, sizeof(TX25Cmd)); | ||
4808 | if (mbox->cmd.length > 0){ | ||
4809 | memcpy(usr_cmd->data, mbox->data, mbox->cmd.length); | ||
4810 | } | ||
4811 | |||
4812 | if (alloc_and_init_skb_buf(card,&skb,len)){ | ||
4813 | printk(KERN_INFO "%s: OOB MSG: No sock buffers\n",card->devname); | ||
4814 | return; | ||
4815 | } | ||
4816 | |||
4817 | api_hdr = (x25api_t*)skb_put(skb,len); | ||
4818 | api_hdr->hdr.pktType = mbox->cmd.pktType & 0x7F; | ||
4819 | api_hdr->hdr.qdm = mbox->cmd.qdm; | ||
4820 | api_hdr->hdr.cause = mbox->cmd.cause; | ||
4821 | api_hdr->hdr.diagn = mbox->cmd.diagn; | ||
4822 | api_hdr->hdr.length = mbox->cmd.length; | ||
4823 | api_hdr->hdr.result = mbox->cmd.result; | ||
4824 | api_hdr->hdr.lcn = mbox->cmd.lcn; | ||
4825 | |||
4826 | if (mbox->cmd.length > 0){ | ||
4827 | memcpy(api_hdr->data,mbox->data,mbox->cmd.length); | ||
4828 | } | ||
4829 | |||
4830 | skb->mac.raw = skb->data; | ||
4831 | skb->pkt_type = WAN_PACKET_ERR; | ||
4832 | |||
4833 | if (chan->common.func(skb,dev,chan->common.sk) < 0){ | ||
4834 | if (bh_enqueue(dev,skb)){ | ||
4835 | printk(KERN_INFO "%s: Dropping OOB MSG\n",card->devname); | ||
4836 | dev_kfree_skb_any(skb); | ||
4837 | } | ||
4838 | } | ||
4839 | |||
4840 | DBG_PRINTK(KERN_INFO "%s: OOB MSG OK, %s, lcn %i\n", | ||
4841 | card->devname, dev->name, mbox->cmd.lcn); | ||
4842 | } | ||
4843 | |||
4844 | /*=============================================================== | ||
4845 | * alloc_and_init_skb_buf | ||
4846 | * | ||
4847 | * Allocate and initialize an skb buffer. | ||
4848 | * | ||
4849 | *===============================================================*/ | ||
4850 | |||
4851 | static int alloc_and_init_skb_buf (sdla_t *card, struct sk_buff **skb, int len) | ||
4852 | { | ||
4853 | struct sk_buff *new_skb = *skb; | ||
4854 | |||
4855 | new_skb = dev_alloc_skb(len + X25_HRDHDR_SZ); | ||
4856 | if (new_skb == NULL){ | ||
4857 | printk(KERN_INFO "%s: no socket buffers available!\n", | ||
4858 | card->devname); | ||
4859 | return 1; | ||
4860 | } | ||
4861 | |||
4862 | if (skb_tailroom(new_skb) < len){ | ||
4863 | /* No room for the packet. Call off the whole thing! */ | ||
4864 | dev_kfree_skb_any(new_skb); | ||
4865 | printk(KERN_INFO "%s: Listen: unexpectedly long packet sequence\n" | ||
4866 | ,card->devname); | ||
4867 | *skb = NULL; | ||
4868 | return 1; | ||
4869 | } | ||
4870 | |||
4871 | *skb = new_skb; | ||
4872 | return 0; | ||
4873 | |||
4874 | } | ||
4875 | |||
4876 | /*=============================================================== | ||
4877 | * api_oob_event | ||
4878 | * | ||
4879 | * Send an OOB event up to the sock | ||
4880 | * | ||
4881 | *===============================================================*/ | ||
4882 | |||
4883 | static void api_oob_event (sdla_t *card,TX25Mbox *mbox) | ||
4884 | { | ||
4885 | struct net_device *dev = find_channel(card, mbox->cmd.lcn); | ||
4886 | x25_channel_t *chan; | ||
4887 | |||
4888 | if (!dev) | ||
4889 | return; | ||
4890 | |||
4891 | chan=dev->priv; | ||
4892 | |||
4893 | if (chan->common.usedby == API) | ||
4894 | send_oob_msg(card,dev,mbox); | ||
4895 | |||
4896 | } | ||
4897 | |||
4898 | |||
4899 | |||
4900 | |||
4901 | static int channel_disconnect(sdla_t* card, struct net_device *dev) | ||
4902 | { | ||
4903 | |||
4904 | int err; | ||
4905 | x25_channel_t *chan = dev->priv; | ||
4906 | |||
4907 | DBG_PRINTK(KERN_INFO "%s: TIMER: %s, Device down disconnecting\n", | ||
4908 | card->devname,dev->name); | ||
4909 | |||
4910 | if (chan->common.svc){ | ||
4911 | err = x25_clear_call(card,chan->common.lcn,0,0); | ||
4912 | }else{ | ||
4913 | /* If channel is PVC or LAPB HDLC, there is no call | ||
4914 | * to be cleared, thus drop down to the default | ||
4915 | * area | ||
4916 | */ | ||
4917 | err = 1; | ||
4918 | } | ||
4919 | |||
4920 | switch (err){ | ||
4921 | |||
4922 | case X25RES_CHANNEL_IN_USE: | ||
4923 | case X25RES_NOT_READY: | ||
4924 | err = TRY_CMD_AGAIN; | ||
4925 | break; | ||
4926 | case CMD_OK: | ||
4927 | DBG_PRINTK(KERN_INFO "CALL CLEAR OK: Dev %s Chan Lcn %i\n", | ||
4928 | dev->name,chan->common.lcn); | ||
4929 | |||
4930 | set_chan_state(dev,WAN_DISCONNECTING); | ||
4931 | atomic_set(&chan->common.command,0); | ||
4932 | err = DELAY_RESULT; | ||
4933 | break; | ||
4934 | default: | ||
4935 | /* If LAPB HDLC protocol, bring the whole link down | ||
4936 | * once the application terminates | ||
4937 | */ | ||
4938 | |||
4939 | set_chan_state(dev,WAN_DISCONNECTED); | ||
4940 | |||
4941 | if (card->u.x.LAPB_hdlc){ | ||
4942 | DBG_PRINTK(KERN_INFO "LAPB: Disconnecting Link\n"); | ||
4943 | hdlc_link_down (card); | ||
4944 | } | ||
4945 | atomic_set(&chan->common.command,0); | ||
4946 | err = RETURN_RESULT; | ||
4947 | break; | ||
4948 | } | ||
4949 | |||
4950 | return err; | ||
4951 | } | ||
4952 | |||
4953 | static void hdlc_link_down (sdla_t *card) | ||
4954 | { | ||
4955 | TX25Mbox* mbox = card->mbox; | ||
4956 | int retry = 5; | ||
4957 | int err=0; | ||
4958 | |||
4959 | do { | ||
4960 | memset(mbox,0,sizeof(TX25Mbox)); | ||
4961 | mbox->cmd.command = X25_HDLC_LINK_DISC; | ||
4962 | mbox->cmd.length = 1; | ||
4963 | mbox->data[0]=0; | ||
4964 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
4965 | |||
4966 | } while (err && retry-- && x25_error(card, err, X25_HDLC_LINK_DISC, 0)); | ||
4967 | |||
4968 | if (err) | ||
4969 | printk(KERN_INFO "%s: Hdlc Link Down Failed %x\n",card->devname,err); | ||
4970 | |||
4971 | disconnect (card); | ||
4972 | |||
4973 | } | ||
4974 | |||
4975 | static int check_bad_command(sdla_t* card, struct net_device *dev) | ||
4976 | { | ||
4977 | x25_channel_t *chan = dev->priv; | ||
4978 | int bad_cmd = 0; | ||
4979 | |||
4980 | switch (atomic_read(&chan->common.command)&0x7F){ | ||
4981 | |||
4982 | case X25_PLACE_CALL: | ||
4983 | if (chan->common.state != WAN_DISCONNECTED) | ||
4984 | bad_cmd=1; | ||
4985 | break; | ||
4986 | case X25_CLEAR_CALL: | ||
4987 | if (chan->common.state == WAN_DISCONNECTED) | ||
4988 | bad_cmd=1; | ||
4989 | break; | ||
4990 | case X25_ACCEPT_CALL: | ||
4991 | if (chan->common.state != WAN_CONNECTING) | ||
4992 | bad_cmd=1; | ||
4993 | break; | ||
4994 | case X25_RESET: | ||
4995 | if (chan->common.state != WAN_CONNECTED) | ||
4996 | bad_cmd=1; | ||
4997 | break; | ||
4998 | default: | ||
4999 | bad_cmd=1; | ||
5000 | break; | ||
5001 | } | ||
5002 | |||
5003 | if (bad_cmd){ | ||
5004 | printk(KERN_INFO "%s: Invalid State, BAD Command %x, dev %s, lcn %i, st %i\n", | ||
5005 | card->devname,atomic_read(&chan->common.command),dev->name, | ||
5006 | chan->common.lcn, chan->common.state); | ||
5007 | } | ||
5008 | |||
5009 | return bad_cmd; | ||
5010 | } | ||
5011 | |||
5012 | |||
5013 | |||
5014 | /*************************** XPIPEMON FUNCTIONS **************************/ | ||
5015 | |||
5016 | /*============================================================================== | ||
5017 | * Process UDP call of type XPIPE | ||
5018 | */ | ||
5019 | |||
5020 | static int process_udp_mgmt_pkt(sdla_t *card) | ||
5021 | { | ||
5022 | int c_retry = MAX_CMD_RETRY; | ||
5023 | unsigned int len; | ||
5024 | struct sk_buff *new_skb; | ||
5025 | TX25Mbox *mbox = card->mbox; | ||
5026 | int err; | ||
5027 | int udp_mgmt_req_valid = 1; | ||
5028 | struct net_device *dev; | ||
5029 | x25_channel_t *chan; | ||
5030 | unsigned short lcn; | ||
5031 | struct timeval tv; | ||
5032 | |||
5033 | |||
5034 | x25_udp_pkt_t *x25_udp_pkt; | ||
5035 | x25_udp_pkt = (x25_udp_pkt_t *)card->u.x.udp_pkt_data; | ||
5036 | |||
5037 | dev = card->u.x.udp_dev; | ||
5038 | chan = dev->priv; | ||
5039 | lcn = chan->common.lcn; | ||
5040 | |||
5041 | switch(x25_udp_pkt->cblock.command) { | ||
5042 | |||
5043 | /* XPIPE_ENABLE_TRACE */ | ||
5044 | case XPIPE_ENABLE_TRACING: | ||
5045 | |||
5046 | /* XPIPE_GET_TRACE_INFO */ | ||
5047 | case XPIPE_GET_TRACE_INFO: | ||
5048 | |||
5049 | /* SET FT1 MODE */ | ||
5050 | case XPIPE_SET_FT1_MODE: | ||
5051 | |||
5052 | if(card->u.x.udp_pkt_src == UDP_PKT_FRM_NETWORK) { | ||
5053 | ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_direction_err; | ||
5054 | udp_mgmt_req_valid = 0; | ||
5055 | break; | ||
5056 | } | ||
5057 | |||
5058 | /* XPIPE_FT1_READ_STATUS */ | ||
5059 | case XPIPE_FT1_READ_STATUS: | ||
5060 | |||
5061 | /* FT1 MONITOR STATUS */ | ||
5062 | case XPIPE_FT1_STATUS_CTRL: | ||
5063 | if(card->hw.fwid != SFID_X25_508) { | ||
5064 | ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_type_err; | ||
5065 | udp_mgmt_req_valid = 0; | ||
5066 | break; | ||
5067 | } | ||
5068 | default: | ||
5069 | break; | ||
5070 | } | ||
5071 | |||
5072 | if(!udp_mgmt_req_valid) { | ||
5073 | /* set length to 0 */ | ||
5074 | x25_udp_pkt->cblock.length = 0; | ||
5075 | /* set return code */ | ||
5076 | x25_udp_pkt->cblock.result = (card->hw.fwid != SFID_X25_508) ? 0x1F : 0xCD; | ||
5077 | |||
5078 | } else { | ||
5079 | |||
5080 | switch (x25_udp_pkt->cblock.command) { | ||
5081 | |||
5082 | |||
5083 | case XPIPE_FLUSH_DRIVER_STATS: | ||
5084 | init_x25_channel_struct(chan); | ||
5085 | init_global_statistics(card); | ||
5086 | mbox->cmd.length = 0; | ||
5087 | break; | ||
5088 | |||
5089 | |||
5090 | case XPIPE_DRIVER_STAT_IFSEND: | ||
5091 | memcpy(x25_udp_pkt->data, &chan->if_send_stat, sizeof(if_send_stat_t)); | ||
5092 | mbox->cmd.length = sizeof(if_send_stat_t); | ||
5093 | x25_udp_pkt->cblock.length = mbox->cmd.length; | ||
5094 | break; | ||
5095 | |||
5096 | case XPIPE_DRIVER_STAT_INTR: | ||
5097 | memcpy(&x25_udp_pkt->data[0], &card->statistics, sizeof(global_stats_t)); | ||
5098 | memcpy(&x25_udp_pkt->data[sizeof(global_stats_t)], | ||
5099 | &chan->rx_intr_stat, sizeof(rx_intr_stat_t)); | ||
5100 | |||
5101 | mbox->cmd.length = sizeof(global_stats_t) + | ||
5102 | sizeof(rx_intr_stat_t); | ||
5103 | x25_udp_pkt->cblock.length = mbox->cmd.length; | ||
5104 | break; | ||
5105 | |||
5106 | case XPIPE_DRIVER_STAT_GEN: | ||
5107 | memcpy(x25_udp_pkt->data, | ||
5108 | &chan->pipe_mgmt_stat.UDP_PIPE_mgmt_kmalloc_err, | ||
5109 | sizeof(pipe_mgmt_stat_t)); | ||
5110 | |||
5111 | memcpy(&x25_udp_pkt->data[sizeof(pipe_mgmt_stat_t)], | ||
5112 | &card->statistics, sizeof(global_stats_t)); | ||
5113 | |||
5114 | x25_udp_pkt->cblock.result = 0; | ||
5115 | x25_udp_pkt->cblock.length = sizeof(global_stats_t)+ | ||
5116 | sizeof(rx_intr_stat_t); | ||
5117 | mbox->cmd.length = x25_udp_pkt->cblock.length; | ||
5118 | break; | ||
5119 | |||
5120 | case XPIPE_ROUTER_UP_TIME: | ||
5121 | do_gettimeofday(&tv); | ||
5122 | chan->router_up_time = tv.tv_sec - chan->router_start_time; | ||
5123 | *(unsigned long *)&x25_udp_pkt->data = chan->router_up_time; | ||
5124 | x25_udp_pkt->cblock.length = mbox->cmd.length = 4; | ||
5125 | x25_udp_pkt->cblock.result = 0; | ||
5126 | break; | ||
5127 | |||
5128 | default : | ||
5129 | |||
5130 | do { | ||
5131 | memcpy(&mbox->cmd, &x25_udp_pkt->cblock.command, sizeof(TX25Cmd)); | ||
5132 | if(mbox->cmd.length){ | ||
5133 | memcpy(&mbox->data, | ||
5134 | (char *)x25_udp_pkt->data, | ||
5135 | mbox->cmd.length); | ||
5136 | } | ||
5137 | |||
5138 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
5139 | } while (err && c_retry-- && x25_error(card, err, mbox->cmd.command, 0)); | ||
5140 | |||
5141 | |||
5142 | if ( err == CMD_OK || | ||
5143 | (err == 1 && | ||
5144 | (mbox->cmd.command == 0x06 || | ||
5145 | mbox->cmd.command == 0x16) ) ){ | ||
5146 | |||
5147 | ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_OK; | ||
5148 | } else { | ||
5149 | ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_timeout; | ||
5150 | } | ||
5151 | |||
5152 | /* copy the result back to our buffer */ | ||
5153 | memcpy(&x25_udp_pkt->cblock.command, &mbox->cmd, sizeof(TX25Cmd)); | ||
5154 | |||
5155 | if(mbox->cmd.length) { | ||
5156 | memcpy(&x25_udp_pkt->data, &mbox->data, mbox->cmd.length); | ||
5157 | } | ||
5158 | break; | ||
5159 | |||
5160 | } //switch | ||
5161 | |||
5162 | } | ||
5163 | |||
5164 | /* Fill UDP TTL */ | ||
5165 | |||
5166 | x25_udp_pkt->ip_pkt.ttl = card->wandev.ttl; | ||
5167 | len = reply_udp(card->u.x.udp_pkt_data, mbox->cmd.length); | ||
5168 | |||
5169 | |||
5170 | if(card->u.x.udp_pkt_src == UDP_PKT_FRM_NETWORK) { | ||
5171 | |||
5172 | err = x25_send(card, lcn, 0, len, card->u.x.udp_pkt_data); | ||
5173 | if (!err) | ||
5174 | ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_send_passed; | ||
5175 | else | ||
5176 | ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_send_failed; | ||
5177 | |||
5178 | } else { | ||
5179 | |||
5180 | /* Allocate socket buffer */ | ||
5181 | if((new_skb = dev_alloc_skb(len)) != NULL) { | ||
5182 | void *buf; | ||
5183 | |||
5184 | /* copy data into new_skb */ | ||
5185 | buf = skb_put(new_skb, len); | ||
5186 | memcpy(buf, card->u.x.udp_pkt_data, len); | ||
5187 | |||
5188 | /* Decapsulate packet and pass it up the protocol | ||
5189 | stack */ | ||
5190 | new_skb->dev = dev; | ||
5191 | |||
5192 | if (chan->common.usedby == API) | ||
5193 | new_skb->protocol = htons(X25_PROT); | ||
5194 | else | ||
5195 | new_skb->protocol = htons(ETH_P_IP); | ||
5196 | |||
5197 | new_skb->mac.raw = new_skb->data; | ||
5198 | |||
5199 | netif_rx(new_skb); | ||
5200 | ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_stack; | ||
5201 | |||
5202 | } else { | ||
5203 | ++chan->pipe_mgmt_stat.UDP_PIPE_mgmt_no_socket; | ||
5204 | printk(KERN_INFO | ||
5205 | "%s: UDP mgmt cmnd, no socket buffers available!\n", | ||
5206 | card->devname); | ||
5207 | } | ||
5208 | } | ||
5209 | |||
5210 | card->u.x.udp_pkt_lgth = 0; | ||
5211 | |||
5212 | return 1; | ||
5213 | } | ||
5214 | |||
5215 | |||
5216 | /*============================================================================== | ||
5217 | * Determine what type of UDP call it is. DRVSTATS or XPIPE8ND ? | ||
5218 | */ | ||
5219 | static int udp_pkt_type( struct sk_buff *skb, sdla_t* card ) | ||
5220 | { | ||
5221 | x25_udp_pkt_t *x25_udp_pkt = (x25_udp_pkt_t *)skb->data; | ||
5222 | |||
5223 | if((x25_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) && | ||
5224 | (x25_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45) && | ||
5225 | (x25_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) && | ||
5226 | (x25_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) { | ||
5227 | |||
5228 | if(!strncmp(x25_udp_pkt->wp_mgmt.signature, | ||
5229 | UDPMGMT_XPIPE_SIGNATURE, 8)){ | ||
5230 | return UDP_XPIPE_TYPE; | ||
5231 | }else{ | ||
5232 | printk(KERN_INFO "%s: UDP Packet, Failed Signature !\n", | ||
5233 | card->devname); | ||
5234 | } | ||
5235 | } | ||
5236 | |||
5237 | return UDP_INVALID_TYPE; | ||
5238 | } | ||
5239 | |||
5240 | |||
5241 | /*============================================================================ | ||
5242 | * Reply to UDP Management system. | ||
5243 | * Return nothing. | ||
5244 | */ | ||
5245 | static int reply_udp( unsigned char *data, unsigned int mbox_len ) | ||
5246 | { | ||
5247 | unsigned short len, udp_length, temp, ip_length; | ||
5248 | unsigned long ip_temp; | ||
5249 | int even_bound = 0; | ||
5250 | |||
5251 | |||
5252 | x25_udp_pkt_t *x25_udp_pkt = (x25_udp_pkt_t *)data; | ||
5253 | |||
5254 | /* Set length of packet */ | ||
5255 | len = sizeof(ip_pkt_t)+ | ||
5256 | sizeof(udp_pkt_t)+ | ||
5257 | sizeof(wp_mgmt_t)+ | ||
5258 | sizeof(cblock_t)+ | ||
5259 | mbox_len; | ||
5260 | |||
5261 | |||
5262 | /* fill in UDP reply */ | ||
5263 | x25_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; | ||
5264 | |||
5265 | /* fill in UDP length */ | ||
5266 | udp_length = sizeof(udp_pkt_t)+ | ||
5267 | sizeof(wp_mgmt_t)+ | ||
5268 | sizeof(cblock_t)+ | ||
5269 | mbox_len; | ||
5270 | |||
5271 | |||
5272 | /* put it on an even boundary */ | ||
5273 | if ( udp_length & 0x0001 ) { | ||
5274 | udp_length += 1; | ||
5275 | len += 1; | ||
5276 | even_bound = 1; | ||
5277 | } | ||
5278 | |||
5279 | temp = (udp_length<<8)|(udp_length>>8); | ||
5280 | x25_udp_pkt->udp_pkt.udp_length = temp; | ||
5281 | |||
5282 | /* swap UDP ports */ | ||
5283 | temp = x25_udp_pkt->udp_pkt.udp_src_port; | ||
5284 | x25_udp_pkt->udp_pkt.udp_src_port = | ||
5285 | x25_udp_pkt->udp_pkt.udp_dst_port; | ||
5286 | x25_udp_pkt->udp_pkt.udp_dst_port = temp; | ||
5287 | |||
5288 | |||
5289 | |||
5290 | /* add UDP pseudo header */ | ||
5291 | temp = 0x1100; | ||
5292 | *((unsigned short *) | ||
5293 | (x25_udp_pkt->data+mbox_len+even_bound)) = temp; | ||
5294 | temp = (udp_length<<8)|(udp_length>>8); | ||
5295 | *((unsigned short *) | ||
5296 | (x25_udp_pkt->data+mbox_len+even_bound+2)) = temp; | ||
5297 | |||
5298 | /* calculate UDP checksum */ | ||
5299 | x25_udp_pkt->udp_pkt.udp_checksum = 0; | ||
5300 | |||
5301 | x25_udp_pkt->udp_pkt.udp_checksum = | ||
5302 | calc_checksum(&data[UDP_OFFSET], udp_length+UDP_OFFSET); | ||
5303 | |||
5304 | /* fill in IP length */ | ||
5305 | ip_length = len; | ||
5306 | temp = (ip_length<<8)|(ip_length>>8); | ||
5307 | x25_udp_pkt->ip_pkt.total_length = temp; | ||
5308 | |||
5309 | /* swap IP addresses */ | ||
5310 | ip_temp = x25_udp_pkt->ip_pkt.ip_src_address; | ||
5311 | x25_udp_pkt->ip_pkt.ip_src_address = | ||
5312 | x25_udp_pkt->ip_pkt.ip_dst_address; | ||
5313 | x25_udp_pkt->ip_pkt.ip_dst_address = ip_temp; | ||
5314 | |||
5315 | |||
5316 | /* fill in IP checksum */ | ||
5317 | x25_udp_pkt->ip_pkt.hdr_checksum = 0; | ||
5318 | x25_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data, sizeof(ip_pkt_t)); | ||
5319 | |||
5320 | return len; | ||
5321 | } /* reply_udp */ | ||
5322 | |||
5323 | unsigned short calc_checksum (char *data, int len) | ||
5324 | { | ||
5325 | unsigned short temp; | ||
5326 | unsigned long sum=0; | ||
5327 | int i; | ||
5328 | |||
5329 | for( i = 0; i <len; i+=2 ) { | ||
5330 | memcpy(&temp,&data[i],2); | ||
5331 | sum += (unsigned long)temp; | ||
5332 | } | ||
5333 | |||
5334 | while (sum >> 16 ) { | ||
5335 | sum = (sum & 0xffffUL) + (sum >> 16); | ||
5336 | } | ||
5337 | |||
5338 | temp = (unsigned short)sum; | ||
5339 | temp = ~temp; | ||
5340 | |||
5341 | if( temp == 0 ) | ||
5342 | temp = 0xffff; | ||
5343 | |||
5344 | return temp; | ||
5345 | } | ||
5346 | |||
5347 | /*============================================================================= | ||
5348 | * Store a UDP management packet for later processing. | ||
5349 | */ | ||
5350 | |||
5351 | static int store_udp_mgmt_pkt(int udp_type, char udp_pkt_src, sdla_t* card, | ||
5352 | struct net_device *dev, struct sk_buff *skb, | ||
5353 | int lcn) | ||
5354 | { | ||
5355 | int udp_pkt_stored = 0; | ||
5356 | |||
5357 | if(!card->u.x.udp_pkt_lgth && (skb->len <= MAX_LGTH_UDP_MGNT_PKT)){ | ||
5358 | card->u.x.udp_pkt_lgth = skb->len; | ||
5359 | card->u.x.udp_type = udp_type; | ||
5360 | card->u.x.udp_pkt_src = udp_pkt_src; | ||
5361 | card->u.x.udp_lcn = lcn; | ||
5362 | card->u.x.udp_dev = dev; | ||
5363 | memcpy(card->u.x.udp_pkt_data, skb->data, skb->len); | ||
5364 | card->u.x.timer_int_enabled |= TMR_INT_ENABLED_UDP_PKT; | ||
5365 | udp_pkt_stored = 1; | ||
5366 | |||
5367 | }else{ | ||
5368 | printk(KERN_INFO "%s: ERROR: UDP packet not stored for LCN %d\n", | ||
5369 | card->devname,lcn); | ||
5370 | } | ||
5371 | |||
5372 | if(udp_pkt_src == UDP_PKT_FRM_STACK){ | ||
5373 | dev_kfree_skb_any(skb); | ||
5374 | }else{ | ||
5375 | dev_kfree_skb_any(skb); | ||
5376 | } | ||
5377 | |||
5378 | return(udp_pkt_stored); | ||
5379 | } | ||
5380 | |||
5381 | |||
5382 | |||
5383 | /*============================================================================= | ||
5384 | * Initial the ppp_private_area structure. | ||
5385 | */ | ||
5386 | static void init_x25_channel_struct( x25_channel_t *chan ) | ||
5387 | { | ||
5388 | memset(&chan->if_send_stat.if_send_entry,0,sizeof(if_send_stat_t)); | ||
5389 | memset(&chan->rx_intr_stat.rx_intr_no_socket,0,sizeof(rx_intr_stat_t)); | ||
5390 | memset(&chan->pipe_mgmt_stat.UDP_PIPE_mgmt_kmalloc_err,0,sizeof(pipe_mgmt_stat_t)); | ||
5391 | } | ||
5392 | |||
5393 | /*============================================================================ | ||
5394 | * Initialize Global Statistics | ||
5395 | */ | ||
5396 | static void init_global_statistics( sdla_t *card ) | ||
5397 | { | ||
5398 | memset(&card->statistics.isr_entry,0,sizeof(global_stats_t)); | ||
5399 | } | ||
5400 | |||
5401 | |||
5402 | /*=============================================================== | ||
5403 | * SMP Support | ||
5404 | * ==============================================================*/ | ||
5405 | |||
5406 | static void S508_S514_lock(sdla_t *card, unsigned long *smp_flags) | ||
5407 | { | ||
5408 | spin_lock_irqsave(&card->wandev.lock, *smp_flags); | ||
5409 | } | ||
5410 | static void S508_S514_unlock(sdla_t *card, unsigned long *smp_flags) | ||
5411 | { | ||
5412 | spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); | ||
5413 | } | ||
5414 | |||
5415 | /*=============================================================== | ||
5416 | * x25_timer_routine | ||
5417 | * | ||
5418 | * A more efficient polling routine. Each half a second | ||
5419 | * queue a polling task. We want to do the polling in a | ||
5420 | * task not timer, because timer runs in interrupt time. | ||
5421 | * | ||
5422 | * FIXME Polling should be rethinked. | ||
5423 | *==============================================================*/ | ||
5424 | |||
5425 | static void x25_timer_routine(unsigned long data) | ||
5426 | { | ||
5427 | sdla_t *card = (sdla_t*)data; | ||
5428 | |||
5429 | if (!card->wandev.dev){ | ||
5430 | printk(KERN_INFO "%s: Stopping the X25 Poll Timer: No Dev.\n", | ||
5431 | card->devname); | ||
5432 | return; | ||
5433 | } | ||
5434 | |||
5435 | if (card->open_cnt != card->u.x.num_of_ch){ | ||
5436 | printk(KERN_INFO "%s: Stopping the X25 Poll Timer: Interface down.\n", | ||
5437 | card->devname); | ||
5438 | return; | ||
5439 | } | ||
5440 | |||
5441 | if (test_bit(PERI_CRIT,&card->wandev.critical)){ | ||
5442 | printk(KERN_INFO "%s: Stopping the X25 Poll Timer: Shutting down.\n", | ||
5443 | card->devname); | ||
5444 | return; | ||
5445 | } | ||
5446 | |||
5447 | if (!test_and_set_bit(POLL_CRIT,&card->wandev.critical)){ | ||
5448 | trigger_x25_poll(card); | ||
5449 | } | ||
5450 | |||
5451 | card->u.x.x25_timer.expires=jiffies+(HZ>>1); | ||
5452 | add_timer(&card->u.x.x25_timer); | ||
5453 | return; | ||
5454 | } | ||
5455 | |||
5456 | void disable_comm_shutdown(sdla_t *card) | ||
5457 | { | ||
5458 | TX25Mbox* mbox = card->mbox; | ||
5459 | int err; | ||
5460 | |||
5461 | /* Turn of interrutps */ | ||
5462 | mbox->data[0] = 0; | ||
5463 | if (card->hw.fwid == SFID_X25_508){ | ||
5464 | mbox->data[1] = card->hw.irq; | ||
5465 | mbox->data[2] = 2; | ||
5466 | mbox->cmd.length = 3; | ||
5467 | }else { | ||
5468 | mbox->cmd.length = 1; | ||
5469 | } | ||
5470 | mbox->cmd.command = X25_SET_INTERRUPT_MODE; | ||
5471 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
5472 | if (err) | ||
5473 | printk(KERN_INFO "INTERRUPT OFF FAIED %x\n",err); | ||
5474 | |||
5475 | /* Bring down HDLC */ | ||
5476 | mbox->cmd.command = X25_HDLC_LINK_CLOSE; | ||
5477 | mbox->cmd.length = 0; | ||
5478 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
5479 | if (err) | ||
5480 | printk(KERN_INFO "LINK CLOSED FAILED %x\n",err); | ||
5481 | |||
5482 | |||
5483 | /* Brind down DTR */ | ||
5484 | mbox->data[0] = 0; | ||
5485 | mbox->data[2] = 0; | ||
5486 | mbox->data[1] = 0x01; | ||
5487 | mbox->cmd.length = 3; | ||
5488 | mbox->cmd.command = X25_SET_GLOBAL_VARS; | ||
5489 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
5490 | if (err) | ||
5491 | printk(KERN_INFO "DTR DOWN FAILED %x\n",err); | ||
5492 | |||
5493 | } | ||
5494 | |||
5495 | MODULE_LICENSE("GPL"); | ||
5496 | |||
5497 | /****** End *****************************************************************/ | ||
diff --git a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c deleted file mode 100644 index 032c0f81928e..000000000000 --- a/drivers/net/wan/sdladrv.c +++ /dev/null | |||
@@ -1,2314 +0,0 @@ | |||
1 | /***************************************************************************** | ||
2 | * sdladrv.c SDLA Support Module. Main module. | ||
3 | * | ||
4 | * This module is a library of common hardware-specific functions | ||
5 | * used by all Sangoma drivers. | ||
6 | * | ||
7 | * Author: Gideon Hack | ||
8 | * | ||
9 | * Copyright: (c) 1995-2000 Sangoma Technologies Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License | ||
13 | * as published by the Free Software Foundation; either version | ||
14 | * 2 of the License, or (at your option) any later version. | ||
15 | * ============================================================================ | ||
16 | * Mar 20, 2001 Nenad Corbic Added the auto_pci_cfg filed, to support | ||
17 | * the PCISLOT #0. | ||
18 | * Apr 04, 2000 Nenad Corbic Fixed the auto memory detection code. | ||
19 | * The memory test at address 0xC8000. | ||
20 | * Mar 09, 2000 Nenad Corbic Added Gideon's Bug Fix: clear pci | ||
21 | * interrupt flags on initial load. | ||
22 | * Jun 02, 1999 Gideon Hack Added support for the S514 adapter. | ||
23 | * Updates for Linux 2.2.X kernels. | ||
24 | * Sep 17, 1998 Jaspreet Singh Updates for linux 2.2.X kernels | ||
25 | * Dec 20, 1996 Gene Kozin Version 3.0.0. Complete overhaul. | ||
26 | * Jul 12, 1996 Gene Kozin Changes for Linux 2.0 compatibility. | ||
27 | * Jun 12, 1996 Gene Kozin Added support for S503 card. | ||
28 | * Apr 30, 1996 Gene Kozin SDLA hardware interrupt is acknowledged before | ||
29 | * calling protocolspecific ISR. | ||
30 | * Register I/O ports with Linux kernel. | ||
31 | * Miscellaneous bug fixes. | ||
32 | * Dec 20, 1995 Gene Kozin Fixed a bug in interrupt routine. | ||
33 | * Oct 14, 1995 Gene Kozin Initial version. | ||
34 | *****************************************************************************/ | ||
35 | |||
36 | /***************************************************************************** | ||
37 | * Notes: | ||
38 | * ------ | ||
39 | * 1. This code is ment to be system-independent (as much as possible). To | ||
40 | * achive this, various macros are used to hide system-specific interfaces. | ||
41 | * To compile this code, one of the following constants must be defined: | ||
42 | * | ||
43 | * Platform Define | ||
44 | * -------- ------ | ||
45 | * Linux _LINUX_ | ||
46 | * SCO Unix _SCO_UNIX_ | ||
47 | * | ||
48 | * 2. Supported adapter types: | ||
49 | * | ||
50 | * S502A | ||
51 | * ES502A (S502E) | ||
52 | * S503 | ||
53 | * S507 | ||
54 | * S508 (S509) | ||
55 | * | ||
56 | * 3. S502A Notes: | ||
57 | * | ||
58 | * There is no separate DPM window enable/disable control in S502A. It | ||
59 | * opens immediately after a window number it written to the HMCR | ||
60 | * register. To close the window, HMCR has to be written a value | ||
61 | * ????1111b (e.g. 0x0F or 0xFF). | ||
62 | * | ||
63 | * S502A DPM window cannot be located at offset E000 (e.g. 0xAE000). | ||
64 | * | ||
65 | * There should be a delay of ??? before reading back S502A status | ||
66 | * register. | ||
67 | * | ||
68 | * 4. S502E Notes: | ||
69 | * | ||
70 | * S502E has a h/w bug: although default IRQ line state is HIGH, enabling | ||
71 | * interrupts by setting bit 1 of the control register (BASE) to '1' | ||
72 | * causes it to go LOW! Therefore, disabling interrupts by setting that | ||
73 | * bit to '0' causes low-to-high transition on IRQ line (ghosty | ||
74 | * interrupt). The same occurs when disabling CPU by resetting bit 0 of | ||
75 | * CPU control register (BASE+3) - see the next note. | ||
76 | * | ||
77 | * S502E CPU and DPM control is limited: | ||
78 | * | ||
79 | * o CPU cannot be stopped independently. Resetting bit 0 of the CPUi | ||
80 | * control register (BASE+3) shuts the board down entirely, including | ||
81 | * DPM; | ||
82 | * | ||
83 | * o DPM access cannot be controlled dynamically. Ones CPU is started, | ||
84 | * bit 1 of the control register (BASE) is used to enable/disable IRQ, | ||
85 | * so that access to shared memory cannot be disabled while CPU is | ||
86 | * running. | ||
87 | ****************************************************************************/ | ||
88 | |||
89 | #define _LINUX_ | ||
90 | |||
91 | #if defined(_LINUX_) /****** Linux *******************************/ | ||
92 | |||
93 | #include <linux/config.h> | ||
94 | #include <linux/kernel.h> /* printk(), and other useful stuff */ | ||
95 | #include <linux/stddef.h> /* offsetof(), etc. */ | ||
96 | #include <linux/errno.h> /* return codes */ | ||
97 | #include <linux/string.h> /* inline memset(), etc. */ | ||
98 | #include <linux/module.h> /* support for loadable modules */ | ||
99 | #include <linux/jiffies.h> /* for jiffies, HZ, etc. */ | ||
100 | #include <linux/sdladrv.h> /* API definitions */ | ||
101 | #include <linux/sdlasfm.h> /* SDLA firmware module definitions */ | ||
102 | #include <linux/sdlapci.h> /* SDLA PCI hardware definitions */ | ||
103 | #include <linux/pci.h> /* PCI defines and function prototypes */ | ||
104 | #include <asm/io.h> /* for inb(), outb(), etc. */ | ||
105 | |||
106 | #define _INB(port) (inb(port)) | ||
107 | #define _OUTB(port, byte) (outb((byte),(port))) | ||
108 | #define SYSTEM_TICK jiffies | ||
109 | |||
110 | #include <linux/init.h> | ||
111 | |||
112 | |||
113 | #elif defined(_SCO_UNIX_) /****** SCO Unix ****************************/ | ||
114 | |||
115 | #if !defined(INKERNEL) | ||
116 | #error This code MUST be compiled in kernel mode! | ||
117 | #endif | ||
118 | #include <sys/sdladrv.h> /* API definitions */ | ||
119 | #include <sys/sdlasfm.h> /* SDLA firmware module definitions */ | ||
120 | #include <sys/inline.h> /* for inb(), outb(), etc. */ | ||
121 | #define _INB(port) (inb(port)) | ||
122 | #define _OUTB(port, byte) (outb((port),(byte))) | ||
123 | #define SYSTEM_TICK lbolt | ||
124 | |||
125 | #else | ||
126 | #error Unknown system type! | ||
127 | #endif | ||
128 | |||
129 | #define MOD_VERSION 3 | ||
130 | #define MOD_RELEASE 0 | ||
131 | |||
132 | #define SDLA_IODELAY 100 /* I/O Rd/Wr delay, 10 works for 486DX2-66 */ | ||
133 | #define EXEC_DELAY 20 /* shared memory access delay, mks */ | ||
134 | #define EXEC_TIMEOUT (HZ*2) /* command timeout, in ticks */ | ||
135 | |||
136 | /* I/O port address range */ | ||
137 | #define S502A_IORANGE 3 | ||
138 | #define S502E_IORANGE 4 | ||
139 | #define S503_IORANGE 3 | ||
140 | #define S507_IORANGE 4 | ||
141 | #define S508_IORANGE 4 | ||
142 | |||
143 | /* Maximum amount of memory */ | ||
144 | #define S502_MAXMEM 0x10000L | ||
145 | #define S503_MAXMEM 0x10000L | ||
146 | #define S507_MAXMEM 0x40000L | ||
147 | #define S508_MAXMEM 0x40000L | ||
148 | |||
149 | /* Minimum amount of memory */ | ||
150 | #define S502_MINMEM 0x8000L | ||
151 | #define S503_MINMEM 0x8000L | ||
152 | #define S507_MINMEM 0x20000L | ||
153 | #define S508_MINMEM 0x20000L | ||
154 | #define NO_PORT -1 | ||
155 | |||
156 | |||
157 | |||
158 | |||
159 | |||
160 | /****** Function Prototypes *************************************************/ | ||
161 | |||
162 | /* Hardware-specific functions */ | ||
163 | static int sdla_detect (sdlahw_t* hw); | ||
164 | static int sdla_autodpm (sdlahw_t* hw); | ||
165 | static int sdla_setdpm (sdlahw_t* hw); | ||
166 | static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len); | ||
167 | static int sdla_init (sdlahw_t* hw); | ||
168 | static unsigned long sdla_memtest (sdlahw_t* hw); | ||
169 | static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo); | ||
170 | static unsigned char make_config_byte (sdlahw_t* hw); | ||
171 | static int sdla_start (sdlahw_t* hw, unsigned addr); | ||
172 | |||
173 | static int init_s502a (sdlahw_t* hw); | ||
174 | static int init_s502e (sdlahw_t* hw); | ||
175 | static int init_s503 (sdlahw_t* hw); | ||
176 | static int init_s507 (sdlahw_t* hw); | ||
177 | static int init_s508 (sdlahw_t* hw); | ||
178 | |||
179 | static int detect_s502a (int port); | ||
180 | static int detect_s502e (int port); | ||
181 | static int detect_s503 (int port); | ||
182 | static int detect_s507 (int port); | ||
183 | static int detect_s508 (int port); | ||
184 | static int detect_s514 (sdlahw_t* hw); | ||
185 | static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card); | ||
186 | |||
187 | /* Miscellaneous functions */ | ||
188 | static void peek_by_4 (unsigned long src, void* buf, unsigned len); | ||
189 | static void poke_by_4 (unsigned long dest, void* buf, unsigned len); | ||
190 | static int calibrate_delay (int mks); | ||
191 | static int get_option_index (unsigned* optlist, unsigned optval); | ||
192 | static unsigned check_memregion (void* ptr, unsigned len); | ||
193 | static unsigned test_memregion (void* ptr, unsigned len); | ||
194 | static unsigned short checksum (unsigned char* buf, unsigned len); | ||
195 | static int init_pci_slot(sdlahw_t *); | ||
196 | |||
197 | static int pci_probe(sdlahw_t *hw); | ||
198 | |||
199 | /****** Global Data ********************************************************** | ||
200 | * Note: All data must be explicitly initialized!!! | ||
201 | */ | ||
202 | |||
203 | static struct pci_device_id sdladrv_pci_tbl[] = { | ||
204 | { V3_VENDOR_ID, V3_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, }, | ||
205 | { } /* Terminating entry */ | ||
206 | }; | ||
207 | MODULE_DEVICE_TABLE(pci, sdladrv_pci_tbl); | ||
208 | |||
209 | MODULE_LICENSE("GPL"); | ||
210 | |||
211 | /* private data */ | ||
212 | static char modname[] = "sdladrv"; | ||
213 | static char fullname[] = "SDLA Support Module"; | ||
214 | static char copyright[] = "(c) 1995-1999 Sangoma Technologies Inc."; | ||
215 | static unsigned exec_idle; | ||
216 | |||
217 | /* Hardware configuration options. | ||
218 | * These are arrays of configuration options used by verification routines. | ||
219 | * The first element of each array is its size (i.e. number of options). | ||
220 | */ | ||
221 | static unsigned s502_port_options[] = | ||
222 | { 4, 0x250, 0x300, 0x350, 0x360 } | ||
223 | ; | ||
224 | static unsigned s503_port_options[] = | ||
225 | { 8, 0x250, 0x254, 0x300, 0x304, 0x350, 0x354, 0x360, 0x364 } | ||
226 | ; | ||
227 | static unsigned s508_port_options[] = | ||
228 | { 8, 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390 } | ||
229 | ; | ||
230 | |||
231 | static unsigned s502a_irq_options[] = { 0 }; | ||
232 | static unsigned s502e_irq_options[] = { 4, 2, 3, 5, 7 }; | ||
233 | static unsigned s503_irq_options[] = { 5, 2, 3, 4, 5, 7 }; | ||
234 | static unsigned s508_irq_options[] = { 8, 3, 4, 5, 7, 10, 11, 12, 15 }; | ||
235 | |||
236 | static unsigned s502a_dpmbase_options[] = | ||
237 | { | ||
238 | 28, | ||
239 | 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, | ||
240 | 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, | ||
241 | 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, | ||
242 | 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, | ||
243 | }; | ||
244 | static unsigned s507_dpmbase_options[] = | ||
245 | { | ||
246 | 32, | ||
247 | 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000, | ||
248 | 0xB0000, 0xB2000, 0xB4000, 0xB6000, 0xB8000, 0xBA000, 0xBC000, 0xBE000, | ||
249 | 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000, | ||
250 | 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000, | ||
251 | }; | ||
252 | static unsigned s508_dpmbase_options[] = /* incl. S502E and S503 */ | ||
253 | { | ||
254 | 32, | ||
255 | 0xA0000, 0xA2000, 0xA4000, 0xA6000, 0xA8000, 0xAA000, 0xAC000, 0xAE000, | ||
256 | 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, 0xCE000, | ||
257 | 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000, 0xDE000, | ||
258 | 0xE0000, 0xE2000, 0xE4000, 0xE6000, 0xE8000, 0xEA000, 0xEC000, 0xEE000, | ||
259 | }; | ||
260 | |||
261 | /* | ||
262 | static unsigned s502_dpmsize_options[] = { 2, 0x2000, 0x10000 }; | ||
263 | static unsigned s507_dpmsize_options[] = { 2, 0x2000, 0x4000 }; | ||
264 | static unsigned s508_dpmsize_options[] = { 1, 0x2000 }; | ||
265 | */ | ||
266 | |||
267 | static unsigned s502a_pclk_options[] = { 2, 3600, 7200 }; | ||
268 | static unsigned s502e_pclk_options[] = { 5, 3600, 5000, 7200, 8000, 10000 }; | ||
269 | static unsigned s503_pclk_options[] = { 3, 7200, 8000, 10000 }; | ||
270 | static unsigned s507_pclk_options[] = { 1, 12288 }; | ||
271 | static unsigned s508_pclk_options[] = { 1, 16000 }; | ||
272 | |||
273 | /* Host memory control register masks */ | ||
274 | static unsigned char s502a_hmcr[] = | ||
275 | { | ||
276 | 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, /* A0000 - AC000 */ | ||
277 | 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, /* C0000 - CC000 */ | ||
278 | 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, /* D0000 - DC000 */ | ||
279 | 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, /* E0000 - EC000 */ | ||
280 | }; | ||
281 | static unsigned char s502e_hmcr[] = | ||
282 | { | ||
283 | 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E, /* A0000 - AE000 */ | ||
284 | 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, /* C0000 - CE000 */ | ||
285 | 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, /* D0000 - DE000 */ | ||
286 | 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3E, /* E0000 - EE000 */ | ||
287 | }; | ||
288 | static unsigned char s507_hmcr[] = | ||
289 | { | ||
290 | 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, /* A0000 - AE000 */ | ||
291 | 0x40, 0x42, 0x44, 0x46, 0x48, 0x4A, 0x4C, 0x4E, /* B0000 - BE000 */ | ||
292 | 0x80, 0x82, 0x84, 0x86, 0x88, 0x8A, 0x8C, 0x8E, /* C0000 - CE000 */ | ||
293 | 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE, /* E0000 - EE000 */ | ||
294 | }; | ||
295 | static unsigned char s508_hmcr[] = | ||
296 | { | ||
297 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* A0000 - AE000 */ | ||
298 | 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* C0000 - CE000 */ | ||
299 | 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, /* D0000 - DE000 */ | ||
300 | 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, /* E0000 - EE000 */ | ||
301 | }; | ||
302 | |||
303 | static unsigned char s507_irqmask[] = | ||
304 | { | ||
305 | 0x00, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, 0xE0 | ||
306 | }; | ||
307 | |||
308 | static int pci_slot_ar[MAX_S514_CARDS]; | ||
309 | |||
310 | /******* Kernel Loadable Module Entry Points ********************************/ | ||
311 | |||
312 | /*============================================================================ | ||
313 | * Module 'insert' entry point. | ||
314 | * o print announcement | ||
315 | * o initialize static data | ||
316 | * o calibrate SDLA shared memory access delay. | ||
317 | * | ||
318 | * Return: 0 Ok | ||
319 | * < 0 error. | ||
320 | * Context: process | ||
321 | */ | ||
322 | |||
323 | static int __init sdladrv_init(void) | ||
324 | { | ||
325 | int i=0; | ||
326 | |||
327 | printk(KERN_INFO "%s v%u.%u %s\n", | ||
328 | fullname, MOD_VERSION, MOD_RELEASE, copyright); | ||
329 | exec_idle = calibrate_delay(EXEC_DELAY); | ||
330 | #ifdef WANDEBUG | ||
331 | printk(KERN_DEBUG "%s: exec_idle = %d\n", modname, exec_idle); | ||
332 | #endif | ||
333 | |||
334 | /* Initialize the PCI Card array, which | ||
335 | * will store flags, used to mark | ||
336 | * card initialization state */ | ||
337 | for (i=0; i<MAX_S514_CARDS; i++) | ||
338 | pci_slot_ar[i] = 0xFF; | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | /*============================================================================ | ||
344 | * Module 'remove' entry point. | ||
345 | * o release all remaining system resources | ||
346 | */ | ||
347 | static void __exit sdladrv_cleanup(void) | ||
348 | { | ||
349 | } | ||
350 | |||
351 | module_init(sdladrv_init); | ||
352 | module_exit(sdladrv_cleanup); | ||
353 | |||
354 | /******* Kernel APIs ********************************************************/ | ||
355 | |||
356 | /*============================================================================ | ||
357 | * Set up adapter. | ||
358 | * o detect adapter type | ||
359 | * o verify hardware configuration options | ||
360 | * o check for hardware conflicts | ||
361 | * o set up adapter shared memory | ||
362 | * o test adapter memory | ||
363 | * o load firmware | ||
364 | * Return: 0 ok. | ||
365 | * < 0 error | ||
366 | */ | ||
367 | |||
368 | EXPORT_SYMBOL(sdla_setup); | ||
369 | |||
370 | int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len) | ||
371 | { | ||
372 | unsigned* irq_opt = NULL; /* IRQ options */ | ||
373 | unsigned* dpmbase_opt = NULL; /* DPM window base options */ | ||
374 | unsigned* pclk_opt = NULL; /* CPU clock rate options */ | ||
375 | int err=0; | ||
376 | |||
377 | if (sdla_detect(hw)) { | ||
378 | if(hw->type != SDLA_S514) | ||
379 | printk(KERN_INFO "%s: no SDLA card found at port 0x%X\n", | ||
380 | modname, hw->port); | ||
381 | return -EINVAL; | ||
382 | } | ||
383 | |||
384 | if(hw->type != SDLA_S514) { | ||
385 | printk(KERN_INFO "%s: found S%04u card at port 0x%X.\n", | ||
386 | modname, hw->type, hw->port); | ||
387 | |||
388 | hw->dpmsize = SDLA_WINDOWSIZE; | ||
389 | switch (hw->type) { | ||
390 | case SDLA_S502A: | ||
391 | hw->io_range = S502A_IORANGE; | ||
392 | irq_opt = s502a_irq_options; | ||
393 | dpmbase_opt = s502a_dpmbase_options; | ||
394 | pclk_opt = s502a_pclk_options; | ||
395 | break; | ||
396 | |||
397 | case SDLA_S502E: | ||
398 | hw->io_range = S502E_IORANGE; | ||
399 | irq_opt = s502e_irq_options; | ||
400 | dpmbase_opt = s508_dpmbase_options; | ||
401 | pclk_opt = s502e_pclk_options; | ||
402 | break; | ||
403 | |||
404 | case SDLA_S503: | ||
405 | hw->io_range = S503_IORANGE; | ||
406 | irq_opt = s503_irq_options; | ||
407 | dpmbase_opt = s508_dpmbase_options; | ||
408 | pclk_opt = s503_pclk_options; | ||
409 | break; | ||
410 | |||
411 | case SDLA_S507: | ||
412 | hw->io_range = S507_IORANGE; | ||
413 | irq_opt = s508_irq_options; | ||
414 | dpmbase_opt = s507_dpmbase_options; | ||
415 | pclk_opt = s507_pclk_options; | ||
416 | break; | ||
417 | |||
418 | case SDLA_S508: | ||
419 | hw->io_range = S508_IORANGE; | ||
420 | irq_opt = s508_irq_options; | ||
421 | dpmbase_opt = s508_dpmbase_options; | ||
422 | pclk_opt = s508_pclk_options; | ||
423 | break; | ||
424 | } | ||
425 | |||
426 | /* Verify IRQ configuration options */ | ||
427 | if (!get_option_index(irq_opt, hw->irq)) { | ||
428 | printk(KERN_INFO "%s: IRQ %d is invalid!\n", | ||
429 | modname, hw->irq); | ||
430 | return -EINVAL; | ||
431 | } | ||
432 | |||
433 | /* Verify CPU clock rate configuration options */ | ||
434 | if (hw->pclk == 0) | ||
435 | hw->pclk = pclk_opt[1]; /* use default */ | ||
436 | |||
437 | else if (!get_option_index(pclk_opt, hw->pclk)) { | ||
438 | printk(KERN_INFO "%s: CPU clock %u is invalid!\n", | ||
439 | modname, hw->pclk); | ||
440 | return -EINVAL; | ||
441 | } | ||
442 | printk(KERN_INFO "%s: assuming CPU clock rate of %u kHz.\n", | ||
443 | modname, hw->pclk); | ||
444 | |||
445 | /* Setup adapter dual-port memory window and test memory */ | ||
446 | if (hw->dpmbase == 0) { | ||
447 | err = sdla_autodpm(hw); | ||
448 | if (err) { | ||
449 | printk(KERN_INFO | ||
450 | "%s: can't find available memory region!\n", | ||
451 | modname); | ||
452 | return err; | ||
453 | } | ||
454 | } | ||
455 | else if (!get_option_index(dpmbase_opt, | ||
456 | virt_to_phys(hw->dpmbase))) { | ||
457 | printk(KERN_INFO | ||
458 | "%s: memory address 0x%lX is invalid!\n", | ||
459 | modname, virt_to_phys(hw->dpmbase)); | ||
460 | return -EINVAL; | ||
461 | } | ||
462 | else if (sdla_setdpm(hw)) { | ||
463 | printk(KERN_INFO | ||
464 | "%s: 8K memory region at 0x%lX is not available!\n", | ||
465 | modname, virt_to_phys(hw->dpmbase)); | ||
466 | return -EINVAL; | ||
467 | } | ||
468 | printk(KERN_INFO | ||
469 | "%s: dual-port memory window is set at 0x%lX.\n", | ||
470 | modname, virt_to_phys(hw->dpmbase)); | ||
471 | |||
472 | |||
473 | /* If we find memory in 0xE**** Memory region, | ||
474 | * warn the user to disable the SHADOW RAM. | ||
475 | * Since memory corruption can occur if SHADOW is | ||
476 | * enabled. This can causes random crashes ! */ | ||
477 | if (virt_to_phys(hw->dpmbase) >= 0xE0000){ | ||
478 | printk(KERN_WARNING "\n%s: !!!!!!!! WARNING !!!!!!!!\n",modname); | ||
479 | printk(KERN_WARNING "%s: WANPIPE is using 0x%lX memory region !!!\n", | ||
480 | modname, virt_to_phys(hw->dpmbase)); | ||
481 | printk(KERN_WARNING " Please disable the SHADOW RAM, otherwise\n"); | ||
482 | printk(KERN_WARNING " your system might crash randomly from time to time !\n"); | ||
483 | printk(KERN_WARNING "%s: !!!!!!!! WARNING !!!!!!!!\n\n",modname); | ||
484 | } | ||
485 | } | ||
486 | |||
487 | else { | ||
488 | hw->memory = test_memregion((void*)hw->dpmbase, | ||
489 | MAX_SIZEOF_S514_MEMORY); | ||
490 | if(hw->memory < (256 * 1024)) { | ||
491 | printk(KERN_INFO | ||
492 | "%s: error in testing S514 memory (0x%lX)\n", | ||
493 | modname, hw->memory); | ||
494 | sdla_down(hw); | ||
495 | return -EINVAL; | ||
496 | } | ||
497 | } | ||
498 | |||
499 | printk(KERN_INFO "%s: found %luK bytes of on-board memory\n", | ||
500 | modname, hw->memory / 1024); | ||
501 | |||
502 | /* Load firmware. If loader fails then shut down adapter */ | ||
503 | err = sdla_load(hw, sfm, len); | ||
504 | if (err) sdla_down(hw); /* shutdown adapter */ | ||
505 | |||
506 | return err; | ||
507 | } | ||
508 | |||
509 | /*============================================================================ | ||
510 | * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc. | ||
511 | */ | ||
512 | |||
513 | EXPORT_SYMBOL(sdla_down); | ||
514 | |||
515 | int sdla_down (sdlahw_t* hw) | ||
516 | { | ||
517 | unsigned port = hw->port; | ||
518 | int i; | ||
519 | unsigned char CPU_no; | ||
520 | u32 int_config, int_status; | ||
521 | |||
522 | if(!port && (hw->type != SDLA_S514)) | ||
523 | return -EFAULT; | ||
524 | |||
525 | switch (hw->type) { | ||
526 | case SDLA_S502A: | ||
527 | _OUTB(port, 0x08); /* halt CPU */ | ||
528 | _OUTB(port, 0x08); | ||
529 | _OUTB(port, 0x08); | ||
530 | hw->regs[0] = 0x08; | ||
531 | _OUTB(port + 1, 0xFF); /* close memory window */ | ||
532 | hw->regs[1] = 0xFF; | ||
533 | break; | ||
534 | |||
535 | case SDLA_S502E: | ||
536 | _OUTB(port + 3, 0); /* stop CPU */ | ||
537 | _OUTB(port, 0); /* reset board */ | ||
538 | for (i = 0; i < S502E_IORANGE; ++i) | ||
539 | hw->regs[i] = 0 | ||
540 | ; | ||
541 | break; | ||
542 | |||
543 | case SDLA_S503: | ||
544 | case SDLA_S507: | ||
545 | case SDLA_S508: | ||
546 | _OUTB(port, 0); /* reset board logic */ | ||
547 | hw->regs[0] = 0; | ||
548 | break; | ||
549 | |||
550 | case SDLA_S514: | ||
551 | /* halt the adapter */ | ||
552 | *(char *)hw->vector = S514_CPU_HALT; | ||
553 | CPU_no = hw->S514_cpu_no[0]; | ||
554 | |||
555 | /* disable the PCI IRQ and disable memory access */ | ||
556 | pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config); | ||
557 | int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A : ~PCI_DISABLE_IRQ_CPU_B; | ||
558 | pci_write_config_dword(hw->pci_dev, PCI_INT_CONFIG, int_config); | ||
559 | read_S514_int_stat(hw, &int_status); | ||
560 | S514_intack(hw, int_status); | ||
561 | if(CPU_no == S514_CPU_A) | ||
562 | pci_write_config_dword(hw->pci_dev, PCI_MAP0_DWORD, | ||
563 | PCI_CPU_A_MEM_DISABLE); | ||
564 | else | ||
565 | pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD, | ||
566 | PCI_CPU_B_MEM_DISABLE); | ||
567 | |||
568 | /* free up the allocated virtual memory */ | ||
569 | iounmap((void *)hw->dpmbase); | ||
570 | iounmap((void *)hw->vector); | ||
571 | break; | ||
572 | |||
573 | |||
574 | default: | ||
575 | return -EINVAL; | ||
576 | } | ||
577 | return 0; | ||
578 | } | ||
579 | |||
580 | /*============================================================================ | ||
581 | * Map shared memory window into SDLA address space. | ||
582 | */ | ||
583 | |||
584 | EXPORT_SYMBOL(sdla_mapmem); | ||
585 | |||
586 | int sdla_mapmem (sdlahw_t* hw, unsigned long addr) | ||
587 | { | ||
588 | unsigned port = hw->port; | ||
589 | register int tmp; | ||
590 | |||
591 | switch (hw->type) { | ||
592 | case SDLA_S502A: | ||
593 | case SDLA_S502E: | ||
594 | if (addr < S502_MAXMEM) { /* verify parameter */ | ||
595 | tmp = addr >> 13; /* convert to register mask */ | ||
596 | _OUTB(port + 2, tmp); | ||
597 | hw->regs[2] = tmp; | ||
598 | } | ||
599 | else return -EINVAL; | ||
600 | break; | ||
601 | |||
602 | case SDLA_S503: | ||
603 | if (addr < S503_MAXMEM) { /* verify parameter */ | ||
604 | tmp = (hw->regs[0] & 0x8F) | ((addr >> 9) & 0x70); | ||
605 | _OUTB(port, tmp); | ||
606 | hw->regs[0] = tmp; | ||
607 | } | ||
608 | else return -EINVAL; | ||
609 | break; | ||
610 | |||
611 | case SDLA_S507: | ||
612 | if (addr < S507_MAXMEM) { | ||
613 | if (!(_INB(port) & 0x02)) | ||
614 | return -EIO; | ||
615 | tmp = addr >> 13; /* convert to register mask */ | ||
616 | _OUTB(port + 2, tmp); | ||
617 | hw->regs[2] = tmp; | ||
618 | } | ||
619 | else return -EINVAL; | ||
620 | break; | ||
621 | |||
622 | case SDLA_S508: | ||
623 | if (addr < S508_MAXMEM) { | ||
624 | tmp = addr >> 13; /* convert to register mask */ | ||
625 | _OUTB(port + 2, tmp); | ||
626 | hw->regs[2] = tmp; | ||
627 | } | ||
628 | else return -EINVAL; | ||
629 | break; | ||
630 | |||
631 | case SDLA_S514: | ||
632 | return 0; | ||
633 | |||
634 | default: | ||
635 | return -EINVAL; | ||
636 | } | ||
637 | hw->vector = addr & 0xFFFFE000L; | ||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | /*============================================================================ | ||
642 | * Enable interrupt generation. | ||
643 | */ | ||
644 | |||
645 | static int sdla_inten (sdlahw_t* hw) | ||
646 | { | ||
647 | unsigned port = hw->port; | ||
648 | int tmp, i; | ||
649 | |||
650 | switch (hw->type) { | ||
651 | case SDLA_S502E: | ||
652 | /* Note thar interrupt control operations on S502E are allowed | ||
653 | * only if CPU is enabled (bit 0 of status register is set). | ||
654 | */ | ||
655 | if (_INB(port) & 0x01) { | ||
656 | _OUTB(port, 0x02); /* bit1 = 1, bit2 = 0 */ | ||
657 | _OUTB(port, 0x06); /* bit1 = 1, bit2 = 1 */ | ||
658 | hw->regs[0] = 0x06; | ||
659 | } | ||
660 | else return -EIO; | ||
661 | break; | ||
662 | |||
663 | case SDLA_S503: | ||
664 | tmp = hw->regs[0] | 0x04; | ||
665 | _OUTB(port, tmp); | ||
666 | hw->regs[0] = tmp; /* update mirror */ | ||
667 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
668 | if (!(_INB(port) & 0x02)) /* verify */ | ||
669 | return -EIO; | ||
670 | break; | ||
671 | |||
672 | case SDLA_S508: | ||
673 | tmp = hw->regs[0] | 0x10; | ||
674 | _OUTB(port, tmp); | ||
675 | hw->regs[0] = tmp; /* update mirror */ | ||
676 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
677 | if (!(_INB(port + 1) & 0x10)) /* verify */ | ||
678 | return -EIO; | ||
679 | break; | ||
680 | |||
681 | case SDLA_S502A: | ||
682 | case SDLA_S507: | ||
683 | break; | ||
684 | |||
685 | case SDLA_S514: | ||
686 | break; | ||
687 | |||
688 | default: | ||
689 | return -EINVAL; | ||
690 | |||
691 | } | ||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | /*============================================================================ | ||
696 | * Disable interrupt generation. | ||
697 | */ | ||
698 | |||
699 | #if 0 | ||
700 | int sdla_intde (sdlahw_t* hw) | ||
701 | { | ||
702 | unsigned port = hw->port; | ||
703 | int tmp, i; | ||
704 | |||
705 | switch (hw->type) { | ||
706 | case SDLA_S502E: | ||
707 | /* Notes: | ||
708 | * 1) interrupt control operations are allowed only if CPU is | ||
709 | * enabled (bit 0 of status register is set). | ||
710 | * 2) disabling interrupts using bit 1 of control register | ||
711 | * causes IRQ line go high, therefore we are going to use | ||
712 | * 0x04 instead: lower it to inhibit interrupts to PC. | ||
713 | */ | ||
714 | if (_INB(port) & 0x01) { | ||
715 | _OUTB(port, hw->regs[0] & ~0x04); | ||
716 | hw->regs[0] &= ~0x04; | ||
717 | } | ||
718 | else return -EIO; | ||
719 | break; | ||
720 | |||
721 | case SDLA_S503: | ||
722 | tmp = hw->regs[0] & ~0x04; | ||
723 | _OUTB(port, tmp); | ||
724 | hw->regs[0] = tmp; /* update mirror */ | ||
725 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
726 | if (_INB(port) & 0x02) /* verify */ | ||
727 | return -EIO; | ||
728 | break; | ||
729 | |||
730 | case SDLA_S508: | ||
731 | tmp = hw->regs[0] & ~0x10; | ||
732 | _OUTB(port, tmp); | ||
733 | hw->regs[0] = tmp; /* update mirror */ | ||
734 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
735 | if (_INB(port) & 0x10) /* verify */ | ||
736 | return -EIO; | ||
737 | break; | ||
738 | |||
739 | case SDLA_S502A: | ||
740 | case SDLA_S507: | ||
741 | break; | ||
742 | |||
743 | default: | ||
744 | return -EINVAL; | ||
745 | } | ||
746 | return 0; | ||
747 | } | ||
748 | #endif /* 0 */ | ||
749 | |||
750 | /*============================================================================ | ||
751 | * Acknowledge SDLA hardware interrupt. | ||
752 | */ | ||
753 | |||
754 | static int sdla_intack (sdlahw_t* hw) | ||
755 | { | ||
756 | unsigned port = hw->port; | ||
757 | int tmp; | ||
758 | |||
759 | switch (hw->type) { | ||
760 | case SDLA_S502E: | ||
761 | /* To acknoledge hardware interrupt we have to toggle bit 3 of | ||
762 | * control register: \_/ | ||
763 | * Note that interrupt control operations on S502E are allowed | ||
764 | * only if CPU is enabled (bit 1 of status register is set). | ||
765 | */ | ||
766 | if (_INB(port) & 0x01) { | ||
767 | tmp = hw->regs[0] & ~0x04; | ||
768 | _OUTB(port, tmp); | ||
769 | tmp |= 0x04; | ||
770 | _OUTB(port, tmp); | ||
771 | hw->regs[0] = tmp; | ||
772 | } | ||
773 | else return -EIO; | ||
774 | break; | ||
775 | |||
776 | case SDLA_S503: | ||
777 | if (_INB(port) & 0x04) { | ||
778 | tmp = hw->regs[0] & ~0x08; | ||
779 | _OUTB(port, tmp); | ||
780 | tmp |= 0x08; | ||
781 | _OUTB(port, tmp); | ||
782 | hw->regs[0] = tmp; | ||
783 | } | ||
784 | break; | ||
785 | |||
786 | case SDLA_S502A: | ||
787 | case SDLA_S507: | ||
788 | case SDLA_S508: | ||
789 | break; | ||
790 | |||
791 | default: | ||
792 | return -EINVAL; | ||
793 | } | ||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | |||
798 | /*============================================================================ | ||
799 | * Acknowledge S514 hardware interrupt. | ||
800 | */ | ||
801 | |||
802 | EXPORT_SYMBOL(S514_intack); | ||
803 | |||
804 | void S514_intack (sdlahw_t* hw, u32 int_status) | ||
805 | { | ||
806 | pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status); | ||
807 | } | ||
808 | |||
809 | |||
810 | /*============================================================================ | ||
811 | * Read the S514 hardware interrupt status. | ||
812 | */ | ||
813 | |||
814 | EXPORT_SYMBOL(read_S514_int_stat); | ||
815 | |||
816 | void read_S514_int_stat (sdlahw_t* hw, u32* int_status) | ||
817 | { | ||
818 | pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status); | ||
819 | } | ||
820 | |||
821 | |||
822 | /*============================================================================ | ||
823 | * Generate an interrupt to adapter's CPU. | ||
824 | */ | ||
825 | |||
826 | #if 0 | ||
827 | int sdla_intr (sdlahw_t* hw) | ||
828 | { | ||
829 | unsigned port = hw->port; | ||
830 | |||
831 | switch (hw->type) { | ||
832 | case SDLA_S502A: | ||
833 | if (!(_INB(port) & 0x40)) { | ||
834 | _OUTB(port, 0x10); /* issue NMI to CPU */ | ||
835 | hw->regs[0] = 0x10; | ||
836 | } | ||
837 | else return -EIO; | ||
838 | break; | ||
839 | |||
840 | case SDLA_S507: | ||
841 | if ((_INB(port) & 0x06) == 0x06) { | ||
842 | _OUTB(port + 3, 0); | ||
843 | } | ||
844 | else return -EIO; | ||
845 | break; | ||
846 | |||
847 | case SDLA_S508: | ||
848 | if (_INB(port + 1) & 0x02) { | ||
849 | _OUTB(port, 0x08); | ||
850 | } | ||
851 | else return -EIO; | ||
852 | break; | ||
853 | |||
854 | case SDLA_S502E: | ||
855 | case SDLA_S503: | ||
856 | default: | ||
857 | return -EINVAL; | ||
858 | } | ||
859 | return 0; | ||
860 | } | ||
861 | #endif /* 0 */ | ||
862 | |||
863 | /*============================================================================ | ||
864 | * Execute Adapter Command. | ||
865 | * o Set exec flag. | ||
866 | * o Busy-wait until flag is reset. | ||
867 | * o Return number of loops made, or 0 if command timed out. | ||
868 | */ | ||
869 | |||
870 | EXPORT_SYMBOL(sdla_exec); | ||
871 | |||
872 | int sdla_exec (void* opflag) | ||
873 | { | ||
874 | volatile unsigned char* flag = opflag; | ||
875 | unsigned long tstop; | ||
876 | int nloops; | ||
877 | |||
878 | if(readb(flag) != 0x00) { | ||
879 | printk(KERN_INFO | ||
880 | "WANPIPE: opp flag set on entry to sdla_exec\n"); | ||
881 | return 0; | ||
882 | } | ||
883 | |||
884 | writeb(0x01, flag); | ||
885 | |||
886 | tstop = SYSTEM_TICK + EXEC_TIMEOUT; | ||
887 | |||
888 | for (nloops = 1; (readb(flag) == 0x01); ++ nloops) { | ||
889 | unsigned delay = exec_idle; | ||
890 | while (-- delay); /* delay */ | ||
891 | if (SYSTEM_TICK > tstop) return 0; /* time is up! */ | ||
892 | } | ||
893 | return nloops; | ||
894 | } | ||
895 | |||
896 | /*============================================================================ | ||
897 | * Read absolute adapter memory. | ||
898 | * Transfer data from adapter's memory to data buffer. | ||
899 | * | ||
900 | * Note: | ||
901 | * Care should be taken when crossing dual-port memory window boundary. | ||
902 | * This function is not atomic, so caller must disable interrupt if | ||
903 | * interrupt routines are accessing adapter shared memory. | ||
904 | */ | ||
905 | |||
906 | EXPORT_SYMBOL(sdla_peek); | ||
907 | |||
908 | int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len) | ||
909 | { | ||
910 | |||
911 | if (addr + len > hw->memory) /* verify arguments */ | ||
912 | return -EINVAL; | ||
913 | |||
914 | if(hw->type == SDLA_S514) { /* copy data for the S514 adapter */ | ||
915 | peek_by_4 ((unsigned long)hw->dpmbase + addr, buf, len); | ||
916 | return 0; | ||
917 | } | ||
918 | |||
919 | else { /* copy data for the S508 adapter */ | ||
920 | unsigned long oldvec = hw->vector; | ||
921 | unsigned winsize = hw->dpmsize; | ||
922 | unsigned curpos, curlen; /* current offset and block size */ | ||
923 | unsigned long curvec; /* current DPM window vector */ | ||
924 | int err = 0; | ||
925 | |||
926 | while (len && !err) { | ||
927 | curpos = addr % winsize; /* current window offset */ | ||
928 | curvec = addr - curpos; /* current window vector */ | ||
929 | curlen = (len > (winsize - curpos)) ? | ||
930 | (winsize - curpos) : len; | ||
931 | /* Relocate window and copy block of data */ | ||
932 | err = sdla_mapmem(hw, curvec); | ||
933 | peek_by_4 ((unsigned long)hw->dpmbase + curpos, buf, | ||
934 | curlen); | ||
935 | addr += curlen; | ||
936 | buf = (char*)buf + curlen; | ||
937 | len -= curlen; | ||
938 | } | ||
939 | |||
940 | /* Restore DPM window position */ | ||
941 | sdla_mapmem(hw, oldvec); | ||
942 | return err; | ||
943 | } | ||
944 | } | ||
945 | |||
946 | |||
947 | /*============================================================================ | ||
948 | * Read data from adapter's memory to a data buffer in 4-byte chunks. | ||
949 | * Note that we ensure that the SDLA memory address is on a 4-byte boundary | ||
950 | * before we begin moving the data in 4-byte chunks. | ||
951 | */ | ||
952 | |||
953 | static void peek_by_4 (unsigned long src, void* buf, unsigned len) | ||
954 | { | ||
955 | |||
956 | /* byte copy data until we get to a 4-byte boundary */ | ||
957 | while (len && (src & 0x03)) { | ||
958 | *(char *)buf ++ = readb(src ++); | ||
959 | len --; | ||
960 | } | ||
961 | |||
962 | /* copy data in 4-byte chunks */ | ||
963 | while (len >= 4) { | ||
964 | *(unsigned long *)buf = readl(src); | ||
965 | buf += 4; | ||
966 | src += 4; | ||
967 | len -= 4; | ||
968 | } | ||
969 | |||
970 | /* byte copy any remaining data */ | ||
971 | while (len) { | ||
972 | *(char *)buf ++ = readb(src ++); | ||
973 | len --; | ||
974 | } | ||
975 | } | ||
976 | |||
977 | |||
978 | /*============================================================================ | ||
979 | * Write Absolute Adapter Memory. | ||
980 | * Transfer data from data buffer to adapter's memory. | ||
981 | * | ||
982 | * Note: | ||
983 | * Care should be taken when crossing dual-port memory window boundary. | ||
984 | * This function is not atomic, so caller must disable interrupt if | ||
985 | * interrupt routines are accessing adapter shared memory. | ||
986 | */ | ||
987 | |||
988 | EXPORT_SYMBOL(sdla_poke); | ||
989 | |||
990 | int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len) | ||
991 | { | ||
992 | |||
993 | if (addr + len > hw->memory) /* verify arguments */ | ||
994 | return -EINVAL; | ||
995 | |||
996 | if(hw->type == SDLA_S514) { /* copy data for the S514 adapter */ | ||
997 | poke_by_4 ((unsigned long)hw->dpmbase + addr, buf, len); | ||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | else { /* copy data for the S508 adapter */ | ||
1002 | unsigned long oldvec = hw->vector; | ||
1003 | unsigned winsize = hw->dpmsize; | ||
1004 | unsigned curpos, curlen; /* current offset and block size */ | ||
1005 | unsigned long curvec; /* current DPM window vector */ | ||
1006 | int err = 0; | ||
1007 | |||
1008 | while (len && !err) { | ||
1009 | curpos = addr % winsize; /* current window offset */ | ||
1010 | curvec = addr - curpos; /* current window vector */ | ||
1011 | curlen = (len > (winsize - curpos)) ? | ||
1012 | (winsize - curpos) : len; | ||
1013 | /* Relocate window and copy block of data */ | ||
1014 | sdla_mapmem(hw, curvec); | ||
1015 | poke_by_4 ((unsigned long)hw->dpmbase + curpos, buf, | ||
1016 | curlen); | ||
1017 | addr += curlen; | ||
1018 | buf = (char*)buf + curlen; | ||
1019 | len -= curlen; | ||
1020 | } | ||
1021 | |||
1022 | /* Restore DPM window position */ | ||
1023 | sdla_mapmem(hw, oldvec); | ||
1024 | return err; | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | |||
1029 | /*============================================================================ | ||
1030 | * Write from a data buffer to adapter's memory in 4-byte chunks. | ||
1031 | * Note that we ensure that the SDLA memory address is on a 4-byte boundary | ||
1032 | * before we begin moving the data in 4-byte chunks. | ||
1033 | */ | ||
1034 | |||
1035 | static void poke_by_4 (unsigned long dest, void* buf, unsigned len) | ||
1036 | { | ||
1037 | |||
1038 | /* byte copy data until we get to a 4-byte boundary */ | ||
1039 | while (len && (dest & 0x03)) { | ||
1040 | writeb (*(char *)buf ++, dest ++); | ||
1041 | len --; | ||
1042 | } | ||
1043 | |||
1044 | /* copy data in 4-byte chunks */ | ||
1045 | while (len >= 4) { | ||
1046 | writel (*(unsigned long *)buf, dest); | ||
1047 | dest += 4; | ||
1048 | buf += 4; | ||
1049 | len -= 4; | ||
1050 | } | ||
1051 | |||
1052 | /* byte copy any remaining data */ | ||
1053 | while (len) { | ||
1054 | writeb (*(char *)buf ++ , dest ++); | ||
1055 | len --; | ||
1056 | } | ||
1057 | } | ||
1058 | |||
1059 | |||
1060 | #ifdef DONT_COMPIPLE_THIS | ||
1061 | #endif /* DONT_COMPIPLE_THIS */ | ||
1062 | |||
1063 | /****** Hardware-Specific Functions *****************************************/ | ||
1064 | |||
1065 | /*============================================================================ | ||
1066 | * Detect adapter type. | ||
1067 | * o if adapter type is specified then call detection routine for that adapter | ||
1068 | * type. Otherwise call detection routines for every adapter types until | ||
1069 | * adapter is detected. | ||
1070 | * | ||
1071 | * Notes: | ||
1072 | * 1) Detection tests are destructive! Adapter will be left in shutdown state | ||
1073 | * after the test. | ||
1074 | */ | ||
1075 | static int sdla_detect (sdlahw_t* hw) | ||
1076 | { | ||
1077 | unsigned port = hw->port; | ||
1078 | int err = 0; | ||
1079 | |||
1080 | if (!port && (hw->type != SDLA_S514)) | ||
1081 | return -EFAULT; | ||
1082 | |||
1083 | switch (hw->type) { | ||
1084 | case SDLA_S502A: | ||
1085 | if (!detect_s502a(port)) err = -ENODEV; | ||
1086 | break; | ||
1087 | |||
1088 | case SDLA_S502E: | ||
1089 | if (!detect_s502e(port)) err = -ENODEV; | ||
1090 | break; | ||
1091 | |||
1092 | case SDLA_S503: | ||
1093 | if (!detect_s503(port)) err = -ENODEV; | ||
1094 | break; | ||
1095 | |||
1096 | case SDLA_S507: | ||
1097 | if (!detect_s507(port)) err = -ENODEV; | ||
1098 | break; | ||
1099 | |||
1100 | case SDLA_S508: | ||
1101 | if (!detect_s508(port)) err = -ENODEV; | ||
1102 | break; | ||
1103 | |||
1104 | case SDLA_S514: | ||
1105 | if (!detect_s514(hw)) err = -ENODEV; | ||
1106 | break; | ||
1107 | |||
1108 | default: | ||
1109 | if (detect_s502a(port)) | ||
1110 | hw->type = SDLA_S502A; | ||
1111 | else if (detect_s502e(port)) | ||
1112 | hw->type = SDLA_S502E; | ||
1113 | else if (detect_s503(port)) | ||
1114 | hw->type = SDLA_S503; | ||
1115 | else if (detect_s507(port)) | ||
1116 | hw->type = SDLA_S507; | ||
1117 | else if (detect_s508(port)) | ||
1118 | hw->type = SDLA_S508; | ||
1119 | else err = -ENODEV; | ||
1120 | } | ||
1121 | return err; | ||
1122 | } | ||
1123 | |||
1124 | /*============================================================================ | ||
1125 | * Autoselect memory region. | ||
1126 | * o try all available DMP address options from the top down until success. | ||
1127 | */ | ||
1128 | static int sdla_autodpm (sdlahw_t* hw) | ||
1129 | { | ||
1130 | int i, err = -EINVAL; | ||
1131 | unsigned* opt; | ||
1132 | |||
1133 | switch (hw->type) { | ||
1134 | case SDLA_S502A: | ||
1135 | opt = s502a_dpmbase_options; | ||
1136 | break; | ||
1137 | |||
1138 | case SDLA_S502E: | ||
1139 | case SDLA_S503: | ||
1140 | case SDLA_S508: | ||
1141 | opt = s508_dpmbase_options; | ||
1142 | break; | ||
1143 | |||
1144 | case SDLA_S507: | ||
1145 | opt = s507_dpmbase_options; | ||
1146 | break; | ||
1147 | |||
1148 | default: | ||
1149 | return -EINVAL; | ||
1150 | } | ||
1151 | |||
1152 | /* Start testing from 8th position, address | ||
1153 | * 0xC8000 from the 508 address table. | ||
1154 | * We don't want to test A**** addresses, since | ||
1155 | * they are usually used for Video */ | ||
1156 | for (i = 8; i <= opt[0] && err; i++) { | ||
1157 | hw->dpmbase = phys_to_virt(opt[i]); | ||
1158 | err = sdla_setdpm(hw); | ||
1159 | } | ||
1160 | return err; | ||
1161 | } | ||
1162 | |||
1163 | /*============================================================================ | ||
1164 | * Set up adapter dual-port memory window. | ||
1165 | * o shut down adapter | ||
1166 | * o make sure that no physical memory exists in this region, i.e entire | ||
1167 | * region reads 0xFF and is not writable when adapter is shut down. | ||
1168 | * o initialize adapter hardware | ||
1169 | * o make sure that region is usable with SDLA card, i.e. we can write to it | ||
1170 | * when adapter is configured. | ||
1171 | */ | ||
1172 | static int sdla_setdpm (sdlahw_t* hw) | ||
1173 | { | ||
1174 | int err; | ||
1175 | |||
1176 | /* Shut down card and verify memory region */ | ||
1177 | sdla_down(hw); | ||
1178 | if (check_memregion(hw->dpmbase, hw->dpmsize)) | ||
1179 | return -EINVAL; | ||
1180 | |||
1181 | /* Initialize adapter and test on-board memory segment by segment. | ||
1182 | * If memory size appears to be less than shared memory window size, | ||
1183 | * assume that memory region is unusable. | ||
1184 | */ | ||
1185 | err = sdla_init(hw); | ||
1186 | if (err) return err; | ||
1187 | |||
1188 | if (sdla_memtest(hw) < hw->dpmsize) { /* less than window size */ | ||
1189 | sdla_down(hw); | ||
1190 | return -EIO; | ||
1191 | } | ||
1192 | sdla_mapmem(hw, 0L); /* set window vector at bottom */ | ||
1193 | return 0; | ||
1194 | } | ||
1195 | |||
1196 | /*============================================================================ | ||
1197 | * Load adapter from the memory image of the SDLA firmware module. | ||
1198 | * o verify firmware integrity and compatibility | ||
1199 | * o start adapter up | ||
1200 | */ | ||
1201 | static int sdla_load (sdlahw_t* hw, sfm_t* sfm, unsigned len) | ||
1202 | { | ||
1203 | |||
1204 | int i; | ||
1205 | |||
1206 | /* Verify firmware signature */ | ||
1207 | if (strcmp(sfm->signature, SFM_SIGNATURE)) { | ||
1208 | printk(KERN_INFO "%s: not SDLA firmware!\n", | ||
1209 | modname); | ||
1210 | return -EINVAL; | ||
1211 | } | ||
1212 | |||
1213 | /* Verify firmware module format version */ | ||
1214 | if (sfm->version != SFM_VERSION) { | ||
1215 | printk(KERN_INFO | ||
1216 | "%s: firmware format %u rejected! Expecting %u.\n", | ||
1217 | modname, sfm->version, SFM_VERSION); | ||
1218 | return -EINVAL; | ||
1219 | } | ||
1220 | |||
1221 | /* Verify firmware module length and checksum */ | ||
1222 | if ((len - offsetof(sfm_t, image) != sfm->info.codesize) || | ||
1223 | (checksum((void*)&sfm->info, | ||
1224 | sizeof(sfm_info_t) + sfm->info.codesize) != sfm->checksum)) { | ||
1225 | printk(KERN_INFO "%s: firmware corrupted!\n", modname); | ||
1226 | return -EINVAL; | ||
1227 | } | ||
1228 | |||
1229 | /* Announce */ | ||
1230 | printk(KERN_INFO "%s: loading %s (ID=%u)...\n", modname, | ||
1231 | (sfm->descr[0] != '\0') ? sfm->descr : "unknown firmware", | ||
1232 | sfm->info.codeid); | ||
1233 | |||
1234 | if(hw->type == SDLA_S514) | ||
1235 | printk(KERN_INFO "%s: loading S514 adapter, CPU %c\n", | ||
1236 | modname, hw->S514_cpu_no[0]); | ||
1237 | |||
1238 | /* Scan through the list of compatible adapters and make sure our | ||
1239 | * adapter type is listed. | ||
1240 | */ | ||
1241 | for (i = 0; | ||
1242 | (i < SFM_MAX_SDLA) && (sfm->info.adapter[i] != hw->type); | ||
1243 | ++i); | ||
1244 | |||
1245 | if (i == SFM_MAX_SDLA) { | ||
1246 | printk(KERN_INFO "%s: firmware is not compatible with S%u!\n", | ||
1247 | modname, hw->type); | ||
1248 | return -EINVAL; | ||
1249 | } | ||
1250 | |||
1251 | |||
1252 | /* Make sure there is enough on-board memory */ | ||
1253 | if (hw->memory < sfm->info.memsize) { | ||
1254 | printk(KERN_INFO | ||
1255 | "%s: firmware needs %lu bytes of on-board memory!\n", | ||
1256 | modname, sfm->info.memsize); | ||
1257 | return -EINVAL; | ||
1258 | } | ||
1259 | |||
1260 | /* Move code onto adapter */ | ||
1261 | if (sdla_poke(hw, sfm->info.codeoffs, sfm->image, sfm->info.codesize)) { | ||
1262 | printk(KERN_INFO "%s: failed to load code segment!\n", | ||
1263 | modname); | ||
1264 | return -EIO; | ||
1265 | } | ||
1266 | |||
1267 | /* Prepare boot-time configuration data and kick-off CPU */ | ||
1268 | sdla_bootcfg(hw, &sfm->info); | ||
1269 | if (sdla_start(hw, sfm->info.startoffs)) { | ||
1270 | printk(KERN_INFO "%s: Damn... Adapter won't start!\n", | ||
1271 | modname); | ||
1272 | return -EIO; | ||
1273 | } | ||
1274 | |||
1275 | /* position DPM window over the mailbox and enable interrupts */ | ||
1276 | if (sdla_mapmem(hw, sfm->info.winoffs) || sdla_inten(hw)) { | ||
1277 | printk(KERN_INFO "%s: adapter hardware failure!\n", | ||
1278 | modname); | ||
1279 | return -EIO; | ||
1280 | } | ||
1281 | hw->fwid = sfm->info.codeid; /* set firmware ID */ | ||
1282 | return 0; | ||
1283 | } | ||
1284 | |||
1285 | /*============================================================================ | ||
1286 | * Initialize SDLA hardware: setup memory window, IRQ, etc. | ||
1287 | */ | ||
1288 | static int sdla_init (sdlahw_t* hw) | ||
1289 | { | ||
1290 | int i; | ||
1291 | |||
1292 | for (i = 0; i < SDLA_MAXIORANGE; ++i) | ||
1293 | hw->regs[i] = 0; | ||
1294 | |||
1295 | switch (hw->type) { | ||
1296 | case SDLA_S502A: return init_s502a(hw); | ||
1297 | case SDLA_S502E: return init_s502e(hw); | ||
1298 | case SDLA_S503: return init_s503(hw); | ||
1299 | case SDLA_S507: return init_s507(hw); | ||
1300 | case SDLA_S508: return init_s508(hw); | ||
1301 | } | ||
1302 | return -EINVAL; | ||
1303 | } | ||
1304 | |||
1305 | /*============================================================================ | ||
1306 | * Test adapter on-board memory. | ||
1307 | * o slide DPM window from the bottom up and test adapter memory segment by | ||
1308 | * segment. | ||
1309 | * Return adapter memory size. | ||
1310 | */ | ||
1311 | static unsigned long sdla_memtest (sdlahw_t* hw) | ||
1312 | { | ||
1313 | unsigned long memsize; | ||
1314 | unsigned winsize; | ||
1315 | |||
1316 | for (memsize = 0, winsize = hw->dpmsize; | ||
1317 | !sdla_mapmem(hw, memsize) && | ||
1318 | (test_memregion(hw->dpmbase, winsize) == winsize) | ||
1319 | ; | ||
1320 | memsize += winsize) | ||
1321 | ; | ||
1322 | hw->memory = memsize; | ||
1323 | return memsize; | ||
1324 | } | ||
1325 | |||
1326 | /*============================================================================ | ||
1327 | * Prepare boot-time firmware configuration data. | ||
1328 | * o position DPM window | ||
1329 | * o initialize configuration data area | ||
1330 | */ | ||
1331 | static int sdla_bootcfg (sdlahw_t* hw, sfm_info_t* sfminfo) | ||
1332 | { | ||
1333 | unsigned char* data; | ||
1334 | |||
1335 | if (!sfminfo->datasize) return 0; /* nothing to do */ | ||
1336 | |||
1337 | if (sdla_mapmem(hw, sfminfo->dataoffs) != 0) | ||
1338 | return -EIO; | ||
1339 | |||
1340 | if(hw->type == SDLA_S514) | ||
1341 | data = (void*)(hw->dpmbase + sfminfo->dataoffs); | ||
1342 | else | ||
1343 | data = (void*)((u8 *)hw->dpmbase + | ||
1344 | (sfminfo->dataoffs - hw->vector)); | ||
1345 | |||
1346 | memset_io (data, 0, sfminfo->datasize); | ||
1347 | |||
1348 | writeb (make_config_byte(hw), &data[0x00]); | ||
1349 | |||
1350 | switch (sfminfo->codeid) { | ||
1351 | case SFID_X25_502: | ||
1352 | case SFID_X25_508: | ||
1353 | writeb (3, &data[0x01]); /* T1 timer */ | ||
1354 | writeb (10, &data[0x03]); /* N2 */ | ||
1355 | writeb (7, &data[0x06]); /* HDLC window size */ | ||
1356 | writeb (1, &data[0x0B]); /* DTE */ | ||
1357 | writeb (2, &data[0x0C]); /* X.25 packet window size */ | ||
1358 | writew (128, &data[0x0D]); /* default X.25 data size */ | ||
1359 | writew (128, &data[0x0F]); /* maximum X.25 data size */ | ||
1360 | break; | ||
1361 | } | ||
1362 | return 0; | ||
1363 | } | ||
1364 | |||
1365 | /*============================================================================ | ||
1366 | * Prepare configuration byte identifying adapter type and CPU clock rate. | ||
1367 | */ | ||
1368 | static unsigned char make_config_byte (sdlahw_t* hw) | ||
1369 | { | ||
1370 | unsigned char byte = 0; | ||
1371 | |||
1372 | switch (hw->pclk) { | ||
1373 | case 5000: byte = 0x01; break; | ||
1374 | case 7200: byte = 0x02; break; | ||
1375 | case 8000: byte = 0x03; break; | ||
1376 | case 10000: byte = 0x04; break; | ||
1377 | case 16000: byte = 0x05; break; | ||
1378 | } | ||
1379 | |||
1380 | switch (hw->type) { | ||
1381 | case SDLA_S502E: byte |= 0x80; break; | ||
1382 | case SDLA_S503: byte |= 0x40; break; | ||
1383 | } | ||
1384 | return byte; | ||
1385 | } | ||
1386 | |||
1387 | /*============================================================================ | ||
1388 | * Start adapter's CPU. | ||
1389 | * o calculate a pointer to adapter's cold boot entry point | ||
1390 | * o position DPM window | ||
1391 | * o place boot instruction (jp addr) at cold boot entry point | ||
1392 | * o start CPU | ||
1393 | */ | ||
1394 | static int sdla_start (sdlahw_t* hw, unsigned addr) | ||
1395 | { | ||
1396 | unsigned port = hw->port; | ||
1397 | unsigned char *bootp; | ||
1398 | int err, tmp, i; | ||
1399 | |||
1400 | if (!port && (hw->type != SDLA_S514)) return -EFAULT; | ||
1401 | |||
1402 | switch (hw->type) { | ||
1403 | case SDLA_S502A: | ||
1404 | bootp = hw->dpmbase; | ||
1405 | bootp += 0x66; | ||
1406 | break; | ||
1407 | |||
1408 | case SDLA_S502E: | ||
1409 | case SDLA_S503: | ||
1410 | case SDLA_S507: | ||
1411 | case SDLA_S508: | ||
1412 | case SDLA_S514: | ||
1413 | bootp = hw->dpmbase; | ||
1414 | break; | ||
1415 | |||
1416 | default: | ||
1417 | return -EINVAL; | ||
1418 | } | ||
1419 | |||
1420 | err = sdla_mapmem(hw, 0); | ||
1421 | if (err) return err; | ||
1422 | |||
1423 | writeb (0xC3, bootp); /* Z80: 'jp' opcode */ | ||
1424 | bootp ++; | ||
1425 | writew (addr, bootp); | ||
1426 | |||
1427 | switch (hw->type) { | ||
1428 | case SDLA_S502A: | ||
1429 | _OUTB(port, 0x10); /* issue NMI to CPU */ | ||
1430 | hw->regs[0] = 0x10; | ||
1431 | break; | ||
1432 | |||
1433 | case SDLA_S502E: | ||
1434 | _OUTB(port + 3, 0x01); /* start CPU */ | ||
1435 | hw->regs[3] = 0x01; | ||
1436 | for (i = 0; i < SDLA_IODELAY; ++i); | ||
1437 | if (_INB(port) & 0x01) { /* verify */ | ||
1438 | /* | ||
1439 | * Enabling CPU changes functionality of the | ||
1440 | * control register, so we have to reset its | ||
1441 | * mirror. | ||
1442 | */ | ||
1443 | _OUTB(port, 0); /* disable interrupts */ | ||
1444 | hw->regs[0] = 0; | ||
1445 | } | ||
1446 | else return -EIO; | ||
1447 | break; | ||
1448 | |||
1449 | case SDLA_S503: | ||
1450 | tmp = hw->regs[0] | 0x09; /* set bits 0 and 3 */ | ||
1451 | _OUTB(port, tmp); | ||
1452 | hw->regs[0] = tmp; /* update mirror */ | ||
1453 | for (i = 0; i < SDLA_IODELAY; ++i); | ||
1454 | if (!(_INB(port) & 0x01)) /* verify */ | ||
1455 | return -EIO; | ||
1456 | break; | ||
1457 | |||
1458 | case SDLA_S507: | ||
1459 | tmp = hw->regs[0] | 0x02; | ||
1460 | _OUTB(port, tmp); | ||
1461 | hw->regs[0] = tmp; /* update mirror */ | ||
1462 | for (i = 0; i < SDLA_IODELAY; ++i); | ||
1463 | if (!(_INB(port) & 0x04)) /* verify */ | ||
1464 | return -EIO; | ||
1465 | break; | ||
1466 | |||
1467 | case SDLA_S508: | ||
1468 | tmp = hw->regs[0] | 0x02; | ||
1469 | _OUTB(port, tmp); | ||
1470 | hw->regs[0] = tmp; /* update mirror */ | ||
1471 | for (i = 0; i < SDLA_IODELAY; ++i); | ||
1472 | if (!(_INB(port + 1) & 0x02)) /* verify */ | ||
1473 | return -EIO; | ||
1474 | break; | ||
1475 | |||
1476 | case SDLA_S514: | ||
1477 | writeb (S514_CPU_START, hw->vector); | ||
1478 | break; | ||
1479 | |||
1480 | default: | ||
1481 | return -EINVAL; | ||
1482 | } | ||
1483 | return 0; | ||
1484 | } | ||
1485 | |||
1486 | /*============================================================================ | ||
1487 | * Initialize S502A adapter. | ||
1488 | */ | ||
1489 | static int init_s502a (sdlahw_t* hw) | ||
1490 | { | ||
1491 | unsigned port = hw->port; | ||
1492 | int tmp, i; | ||
1493 | |||
1494 | if (!detect_s502a(port)) | ||
1495 | return -ENODEV; | ||
1496 | |||
1497 | hw->regs[0] = 0x08; | ||
1498 | hw->regs[1] = 0xFF; | ||
1499 | |||
1500 | /* Verify configuration options */ | ||
1501 | i = get_option_index(s502a_dpmbase_options, virt_to_phys(hw->dpmbase)); | ||
1502 | if (i == 0) | ||
1503 | return -EINVAL; | ||
1504 | |||
1505 | tmp = s502a_hmcr[i - 1]; | ||
1506 | switch (hw->dpmsize) { | ||
1507 | case 0x2000: | ||
1508 | tmp |= 0x01; | ||
1509 | break; | ||
1510 | |||
1511 | case 0x10000L: | ||
1512 | break; | ||
1513 | |||
1514 | default: | ||
1515 | return -EINVAL; | ||
1516 | } | ||
1517 | |||
1518 | /* Setup dual-port memory window (this also enables memory access) */ | ||
1519 | _OUTB(port + 1, tmp); | ||
1520 | hw->regs[1] = tmp; | ||
1521 | hw->regs[0] = 0x08; | ||
1522 | return 0; | ||
1523 | } | ||
1524 | |||
1525 | /*============================================================================ | ||
1526 | * Initialize S502E adapter. | ||
1527 | */ | ||
1528 | static int init_s502e (sdlahw_t* hw) | ||
1529 | { | ||
1530 | unsigned port = hw->port; | ||
1531 | int tmp, i; | ||
1532 | |||
1533 | if (!detect_s502e(port)) | ||
1534 | return -ENODEV; | ||
1535 | |||
1536 | /* Verify configuration options */ | ||
1537 | i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase)); | ||
1538 | if (i == 0) | ||
1539 | return -EINVAL; | ||
1540 | |||
1541 | tmp = s502e_hmcr[i - 1]; | ||
1542 | switch (hw->dpmsize) { | ||
1543 | case 0x2000: | ||
1544 | tmp |= 0x01; | ||
1545 | break; | ||
1546 | |||
1547 | case 0x10000L: | ||
1548 | break; | ||
1549 | |||
1550 | default: | ||
1551 | return -EINVAL; | ||
1552 | } | ||
1553 | |||
1554 | /* Setup dual-port memory window */ | ||
1555 | _OUTB(port + 1, tmp); | ||
1556 | hw->regs[1] = tmp; | ||
1557 | |||
1558 | /* Enable memory access */ | ||
1559 | _OUTB(port, 0x02); | ||
1560 | hw->regs[0] = 0x02; | ||
1561 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1562 | return (_INB(port) & 0x02) ? 0 : -EIO; | ||
1563 | } | ||
1564 | |||
1565 | /*============================================================================ | ||
1566 | * Initialize S503 adapter. | ||
1567 | * --------------------------------------------------------------------------- | ||
1568 | */ | ||
1569 | static int init_s503 (sdlahw_t* hw) | ||
1570 | { | ||
1571 | unsigned port = hw->port; | ||
1572 | int tmp, i; | ||
1573 | |||
1574 | if (!detect_s503(port)) | ||
1575 | return -ENODEV; | ||
1576 | |||
1577 | /* Verify configuration options */ | ||
1578 | i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase)); | ||
1579 | if (i == 0) | ||
1580 | return -EINVAL; | ||
1581 | |||
1582 | tmp = s502e_hmcr[i - 1]; | ||
1583 | switch (hw->dpmsize) { | ||
1584 | case 0x2000: | ||
1585 | tmp |= 0x01; | ||
1586 | break; | ||
1587 | |||
1588 | case 0x10000L: | ||
1589 | break; | ||
1590 | |||
1591 | default: | ||
1592 | return -EINVAL; | ||
1593 | } | ||
1594 | |||
1595 | /* Setup dual-port memory window */ | ||
1596 | _OUTB(port + 1, tmp); | ||
1597 | hw->regs[1] = tmp; | ||
1598 | |||
1599 | /* Enable memory access */ | ||
1600 | _OUTB(port, 0x02); | ||
1601 | hw->regs[0] = 0x02; /* update mirror */ | ||
1602 | return 0; | ||
1603 | } | ||
1604 | |||
1605 | /*============================================================================ | ||
1606 | * Initialize S507 adapter. | ||
1607 | */ | ||
1608 | static int init_s507 (sdlahw_t* hw) | ||
1609 | { | ||
1610 | unsigned port = hw->port; | ||
1611 | int tmp, i; | ||
1612 | |||
1613 | if (!detect_s507(port)) | ||
1614 | return -ENODEV; | ||
1615 | |||
1616 | /* Verify configuration options */ | ||
1617 | i = get_option_index(s507_dpmbase_options, virt_to_phys(hw->dpmbase)); | ||
1618 | if (i == 0) | ||
1619 | return -EINVAL; | ||
1620 | |||
1621 | tmp = s507_hmcr[i - 1]; | ||
1622 | switch (hw->dpmsize) { | ||
1623 | case 0x2000: | ||
1624 | tmp |= 0x01; | ||
1625 | break; | ||
1626 | |||
1627 | case 0x10000L: | ||
1628 | break; | ||
1629 | |||
1630 | default: | ||
1631 | return -EINVAL; | ||
1632 | } | ||
1633 | |||
1634 | /* Enable adapter's logic */ | ||
1635 | _OUTB(port, 0x01); | ||
1636 | hw->regs[0] = 0x01; | ||
1637 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1638 | if (!(_INB(port) & 0x20)) | ||
1639 | return -EIO; | ||
1640 | |||
1641 | /* Setup dual-port memory window */ | ||
1642 | _OUTB(port + 1, tmp); | ||
1643 | hw->regs[1] = tmp; | ||
1644 | |||
1645 | /* Enable memory access */ | ||
1646 | tmp = hw->regs[0] | 0x04; | ||
1647 | if (hw->irq) { | ||
1648 | i = get_option_index(s508_irq_options, hw->irq); | ||
1649 | if (i) tmp |= s507_irqmask[i - 1]; | ||
1650 | } | ||
1651 | _OUTB(port, tmp); | ||
1652 | hw->regs[0] = tmp; /* update mirror */ | ||
1653 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1654 | return (_INB(port) & 0x08) ? 0 : -EIO; | ||
1655 | } | ||
1656 | |||
1657 | /*============================================================================ | ||
1658 | * Initialize S508 adapter. | ||
1659 | */ | ||
1660 | static int init_s508 (sdlahw_t* hw) | ||
1661 | { | ||
1662 | unsigned port = hw->port; | ||
1663 | int tmp, i; | ||
1664 | |||
1665 | if (!detect_s508(port)) | ||
1666 | return -ENODEV; | ||
1667 | |||
1668 | /* Verify configuration options */ | ||
1669 | i = get_option_index(s508_dpmbase_options, virt_to_phys(hw->dpmbase)); | ||
1670 | if (i == 0) | ||
1671 | return -EINVAL; | ||
1672 | |||
1673 | /* Setup memory configuration */ | ||
1674 | tmp = s508_hmcr[i - 1]; | ||
1675 | _OUTB(port + 1, tmp); | ||
1676 | hw->regs[1] = tmp; | ||
1677 | |||
1678 | /* Enable memory access */ | ||
1679 | _OUTB(port, 0x04); | ||
1680 | hw->regs[0] = 0x04; /* update mirror */ | ||
1681 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1682 | return (_INB(port + 1) & 0x04) ? 0 : -EIO; | ||
1683 | } | ||
1684 | |||
1685 | /*============================================================================ | ||
1686 | * Detect S502A adapter. | ||
1687 | * Following tests are used to detect S502A adapter: | ||
1688 | * 1. All registers other than status (BASE) should read 0xFF | ||
1689 | * 2. After writing 00001000b to control register, status register should | ||
1690 | * read 01000000b. | ||
1691 | * 3. After writing 0 to control register, status register should still | ||
1692 | * read 01000000b. | ||
1693 | * 4. After writing 00000100b to control register, status register should | ||
1694 | * read 01000100b. | ||
1695 | * Return 1 if detected o.k. or 0 if failed. | ||
1696 | * Note: This test is destructive! Adapter will be left in shutdown | ||
1697 | * state after the test. | ||
1698 | */ | ||
1699 | static int detect_s502a (int port) | ||
1700 | { | ||
1701 | int i, j; | ||
1702 | |||
1703 | if (!get_option_index(s502_port_options, port)) | ||
1704 | return 0; | ||
1705 | |||
1706 | for (j = 1; j < SDLA_MAXIORANGE; ++j) { | ||
1707 | if (_INB(port + j) != 0xFF) | ||
1708 | return 0; | ||
1709 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1710 | } | ||
1711 | |||
1712 | _OUTB(port, 0x08); /* halt CPU */ | ||
1713 | _OUTB(port, 0x08); | ||
1714 | _OUTB(port, 0x08); | ||
1715 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1716 | if (_INB(port) != 0x40) | ||
1717 | return 0; | ||
1718 | _OUTB(port, 0x00); | ||
1719 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1720 | if (_INB(port) != 0x40) | ||
1721 | return 0; | ||
1722 | _OUTB(port, 0x04); | ||
1723 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1724 | if (_INB(port) != 0x44) | ||
1725 | return 0; | ||
1726 | |||
1727 | /* Reset adapter */ | ||
1728 | _OUTB(port, 0x08); | ||
1729 | _OUTB(port, 0x08); | ||
1730 | _OUTB(port, 0x08); | ||
1731 | _OUTB(port + 1, 0xFF); | ||
1732 | return 1; | ||
1733 | } | ||
1734 | |||
1735 | /*============================================================================ | ||
1736 | * Detect S502E adapter. | ||
1737 | * Following tests are used to verify adapter presence: | ||
1738 | * 1. All registers other than status (BASE) should read 0xFF. | ||
1739 | * 2. After writing 0 to CPU control register (BASE+3), status register | ||
1740 | * (BASE) should read 11111000b. | ||
1741 | * 3. After writing 00000100b to port BASE (set bit 2), status register | ||
1742 | * (BASE) should read 11111100b. | ||
1743 | * Return 1 if detected o.k. or 0 if failed. | ||
1744 | * Note: This test is destructive! Adapter will be left in shutdown | ||
1745 | * state after the test. | ||
1746 | */ | ||
1747 | static int detect_s502e (int port) | ||
1748 | { | ||
1749 | int i, j; | ||
1750 | |||
1751 | if (!get_option_index(s502_port_options, port)) | ||
1752 | return 0; | ||
1753 | for (j = 1; j < SDLA_MAXIORANGE; ++j) { | ||
1754 | if (_INB(port + j) != 0xFF) | ||
1755 | return 0; | ||
1756 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1757 | } | ||
1758 | |||
1759 | _OUTB(port + 3, 0); /* CPU control reg. */ | ||
1760 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1761 | if (_INB(port) != 0xF8) /* read status */ | ||
1762 | return 0; | ||
1763 | _OUTB(port, 0x04); /* set bit 2 */ | ||
1764 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1765 | if (_INB(port) != 0xFC) /* verify */ | ||
1766 | return 0; | ||
1767 | |||
1768 | /* Reset adapter */ | ||
1769 | _OUTB(port, 0); | ||
1770 | return 1; | ||
1771 | } | ||
1772 | |||
1773 | /*============================================================================ | ||
1774 | * Detect s503 adapter. | ||
1775 | * Following tests are used to verify adapter presence: | ||
1776 | * 1. All registers other than status (BASE) should read 0xFF. | ||
1777 | * 2. After writing 0 to control register (BASE), status register (BASE) | ||
1778 | * should read 11110000b. | ||
1779 | * 3. After writing 00000100b (set bit 2) to control register (BASE), | ||
1780 | * status register should read 11110010b. | ||
1781 | * Return 1 if detected o.k. or 0 if failed. | ||
1782 | * Note: This test is destructive! Adapter will be left in shutdown | ||
1783 | * state after the test. | ||
1784 | */ | ||
1785 | static int detect_s503 (int port) | ||
1786 | { | ||
1787 | int i, j; | ||
1788 | |||
1789 | if (!get_option_index(s503_port_options, port)) | ||
1790 | return 0; | ||
1791 | for (j = 1; j < SDLA_MAXIORANGE; ++j) { | ||
1792 | if (_INB(port + j) != 0xFF) | ||
1793 | return 0; | ||
1794 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1795 | } | ||
1796 | |||
1797 | _OUTB(port, 0); /* reset control reg.*/ | ||
1798 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1799 | if (_INB(port) != 0xF0) /* read status */ | ||
1800 | return 0; | ||
1801 | _OUTB(port, 0x04); /* set bit 2 */ | ||
1802 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1803 | if (_INB(port) != 0xF2) /* verify */ | ||
1804 | return 0; | ||
1805 | |||
1806 | /* Reset adapter */ | ||
1807 | _OUTB(port, 0); | ||
1808 | return 1; | ||
1809 | } | ||
1810 | |||
1811 | /*============================================================================ | ||
1812 | * Detect s507 adapter. | ||
1813 | * Following tests are used to detect s507 adapter: | ||
1814 | * 1. All ports should read the same value. | ||
1815 | * 2. After writing 0x00 to control register, status register should read | ||
1816 | * ?011000?b. | ||
1817 | * 3. After writing 0x01 to control register, status register should read | ||
1818 | * ?011001?b. | ||
1819 | * Return 1 if detected o.k. or 0 if failed. | ||
1820 | * Note: This test is destructive! Adapter will be left in shutdown | ||
1821 | * state after the test. | ||
1822 | */ | ||
1823 | static int detect_s507 (int port) | ||
1824 | { | ||
1825 | int tmp, i, j; | ||
1826 | |||
1827 | if (!get_option_index(s508_port_options, port)) | ||
1828 | return 0; | ||
1829 | tmp = _INB(port); | ||
1830 | for (j = 1; j < S507_IORANGE; ++j) { | ||
1831 | if (_INB(port + j) != tmp) | ||
1832 | return 0; | ||
1833 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1834 | } | ||
1835 | |||
1836 | _OUTB(port, 0x00); | ||
1837 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1838 | if ((_INB(port) & 0x7E) != 0x30) | ||
1839 | return 0; | ||
1840 | _OUTB(port, 0x01); | ||
1841 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1842 | if ((_INB(port) & 0x7E) != 0x32) | ||
1843 | return 0; | ||
1844 | |||
1845 | /* Reset adapter */ | ||
1846 | _OUTB(port, 0x00); | ||
1847 | return 1; | ||
1848 | } | ||
1849 | |||
1850 | /*============================================================================ | ||
1851 | * Detect s508 adapter. | ||
1852 | * Following tests are used to detect s508 adapter: | ||
1853 | * 1. After writing 0x00 to control register, status register should read | ||
1854 | * ??000000b. | ||
1855 | * 2. After writing 0x10 to control register, status register should read | ||
1856 | * ??010000b | ||
1857 | * Return 1 if detected o.k. or 0 if failed. | ||
1858 | * Note: This test is destructive! Adapter will be left in shutdown | ||
1859 | * state after the test. | ||
1860 | */ | ||
1861 | static int detect_s508 (int port) | ||
1862 | { | ||
1863 | int i; | ||
1864 | |||
1865 | if (!get_option_index(s508_port_options, port)) | ||
1866 | return 0; | ||
1867 | _OUTB(port, 0x00); | ||
1868 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1869 | if ((_INB(port + 1) & 0x3F) != 0x00) | ||
1870 | return 0; | ||
1871 | _OUTB(port, 0x10); | ||
1872 | for (i = 0; i < SDLA_IODELAY; ++i); /* delay */ | ||
1873 | if ((_INB(port + 1) & 0x3F) != 0x10) | ||
1874 | return 0; | ||
1875 | |||
1876 | /* Reset adapter */ | ||
1877 | _OUTB(port, 0x00); | ||
1878 | return 1; | ||
1879 | } | ||
1880 | |||
1881 | /*============================================================================ | ||
1882 | * Detect s514 PCI adapter. | ||
1883 | * Return 1 if detected o.k. or 0 if failed. | ||
1884 | * Note: This test is destructive! Adapter will be left in shutdown | ||
1885 | * state after the test. | ||
1886 | */ | ||
1887 | static int detect_s514 (sdlahw_t* hw) | ||
1888 | { | ||
1889 | unsigned char CPU_no, slot_no, auto_slot_cfg; | ||
1890 | int number_S514_cards = 0; | ||
1891 | u32 S514_mem_base_addr = 0; | ||
1892 | u32 ut_u32; | ||
1893 | struct pci_dev *pci_dev; | ||
1894 | |||
1895 | |||
1896 | #ifndef CONFIG_PCI | ||
1897 | printk(KERN_INFO "%s: Linux not compiled for PCI usage!\n", modname); | ||
1898 | return 0; | ||
1899 | #endif | ||
1900 | |||
1901 | /* | ||
1902 | The 'setup()' procedure in 'sdlamain.c' passes the CPU number and the | ||
1903 | slot number defined in 'router.conf' via the 'port' definition. | ||
1904 | */ | ||
1905 | CPU_no = hw->S514_cpu_no[0]; | ||
1906 | slot_no = hw->S514_slot_no; | ||
1907 | auto_slot_cfg = hw->auto_pci_cfg; | ||
1908 | |||
1909 | if (auto_slot_cfg){ | ||
1910 | printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot=Auto\n", | ||
1911 | modname, CPU_no); | ||
1912 | |||
1913 | }else{ | ||
1914 | printk(KERN_INFO "%s: srch... S514 card, CPU %c, Slot #%d\n", | ||
1915 | modname, CPU_no, slot_no); | ||
1916 | } | ||
1917 | |||
1918 | /* check to see that CPU A or B has been selected in 'router.conf' */ | ||
1919 | switch(CPU_no) { | ||
1920 | case S514_CPU_A: | ||
1921 | case S514_CPU_B: | ||
1922 | break; | ||
1923 | |||
1924 | default: | ||
1925 | printk(KERN_INFO "%s: S514 CPU definition invalid.\n", | ||
1926 | modname); | ||
1927 | printk(KERN_INFO "Must be 'A' or 'B'\n"); | ||
1928 | return 0; | ||
1929 | } | ||
1930 | |||
1931 | number_S514_cards = find_s514_adapter(hw, 0); | ||
1932 | if(!number_S514_cards) | ||
1933 | return 0; | ||
1934 | |||
1935 | /* we are using a single S514 adapter with a slot of 0 so re-read the */ | ||
1936 | /* location of this adapter */ | ||
1937 | if((number_S514_cards == 1) && auto_slot_cfg) { | ||
1938 | number_S514_cards = find_s514_adapter(hw, 1); | ||
1939 | if(!number_S514_cards) { | ||
1940 | printk(KERN_INFO "%s: Error finding PCI card\n", | ||
1941 | modname); | ||
1942 | return 0; | ||
1943 | } | ||
1944 | } | ||
1945 | |||
1946 | pci_dev = hw->pci_dev; | ||
1947 | /* read the physical memory base address */ | ||
1948 | S514_mem_base_addr = (CPU_no == S514_CPU_A) ? | ||
1949 | (pci_dev->resource[1].start) : | ||
1950 | (pci_dev->resource[2].start); | ||
1951 | |||
1952 | printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n", | ||
1953 | modname, S514_mem_base_addr); | ||
1954 | if(!S514_mem_base_addr) { | ||
1955 | if(CPU_no == S514_CPU_B) | ||
1956 | printk(KERN_INFO "%s: CPU #B not present on the card\n", modname); | ||
1957 | else | ||
1958 | printk(KERN_INFO "%s: No PCI memory allocated to card\n", modname); | ||
1959 | return 0; | ||
1960 | } | ||
1961 | |||
1962 | /* enable the PCI memory */ | ||
1963 | pci_read_config_dword(pci_dev, | ||
1964 | (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, | ||
1965 | &ut_u32); | ||
1966 | pci_write_config_dword(pci_dev, | ||
1967 | (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, | ||
1968 | (ut_u32 | PCI_MEMORY_ENABLE)); | ||
1969 | |||
1970 | /* check the IRQ allocated and enable IRQ usage */ | ||
1971 | if(!(hw->irq = pci_dev->irq)) { | ||
1972 | printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n", | ||
1973 | modname); | ||
1974 | return 0; | ||
1975 | } | ||
1976 | |||
1977 | /* BUG FIX : Mar 6 2000 | ||
1978 | * On a initial loading of the card, we must check | ||
1979 | * and clear PCI interrupt bits, due to a reset | ||
1980 | * problem on some other boards. i.e. An interrupt | ||
1981 | * might be pending, even after system bootup, | ||
1982 | * in which case, when starting wanrouter the machine | ||
1983 | * would crash. | ||
1984 | */ | ||
1985 | if (init_pci_slot(hw)) | ||
1986 | return 0; | ||
1987 | |||
1988 | pci_read_config_dword(pci_dev, PCI_INT_CONFIG, &ut_u32); | ||
1989 | ut_u32 |= (CPU_no == S514_CPU_A) ? | ||
1990 | PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B; | ||
1991 | pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32); | ||
1992 | |||
1993 | printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n", | ||
1994 | modname, hw->irq); | ||
1995 | |||
1996 | /* map the physical PCI memory to virtual memory */ | ||
1997 | hw->dpmbase = ioremap((unsigned long)S514_mem_base_addr, | ||
1998 | (unsigned long)MAX_SIZEOF_S514_MEMORY); | ||
1999 | /* map the physical control register memory to virtual memory */ | ||
2000 | hw->vector = (unsigned long)ioremap( | ||
2001 | (unsigned long)(S514_mem_base_addr + S514_CTRL_REG_BYTE), | ||
2002 | (unsigned long)16); | ||
2003 | |||
2004 | if(!hw->dpmbase || !hw->vector) { | ||
2005 | printk(KERN_INFO "%s: PCI virtual memory allocation failed\n", | ||
2006 | modname); | ||
2007 | return 0; | ||
2008 | } | ||
2009 | |||
2010 | /* halt the adapter */ | ||
2011 | writeb (S514_CPU_HALT, hw->vector); | ||
2012 | |||
2013 | return 1; | ||
2014 | } | ||
2015 | |||
2016 | /*============================================================================ | ||
2017 | * Find the S514 PCI adapter in the PCI bus. | ||
2018 | * Return the number of S514 adapters found (0 if no adapter found). | ||
2019 | */ | ||
2020 | static int find_s514_adapter(sdlahw_t* hw, char find_first_S514_card) | ||
2021 | { | ||
2022 | unsigned char slot_no; | ||
2023 | int number_S514_cards = 0; | ||
2024 | char S514_found_in_slot = 0; | ||
2025 | u16 PCI_subsys_vendor; | ||
2026 | |||
2027 | struct pci_dev *pci_dev = NULL; | ||
2028 | |||
2029 | slot_no = hw->S514_slot_no; | ||
2030 | |||
2031 | while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev)) | ||
2032 | != NULL) { | ||
2033 | |||
2034 | pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD, | ||
2035 | &PCI_subsys_vendor); | ||
2036 | |||
2037 | if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR) | ||
2038 | continue; | ||
2039 | |||
2040 | hw->pci_dev = pci_dev; | ||
2041 | |||
2042 | if(find_first_S514_card) | ||
2043 | return(1); | ||
2044 | |||
2045 | number_S514_cards ++; | ||
2046 | |||
2047 | printk(KERN_INFO | ||
2048 | "%s: S514 card found, slot #%d (devfn 0x%X)\n", | ||
2049 | modname, ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK), | ||
2050 | pci_dev->devfn); | ||
2051 | |||
2052 | if (hw->auto_pci_cfg){ | ||
2053 | hw->S514_slot_no = ((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK); | ||
2054 | slot_no = hw->S514_slot_no; | ||
2055 | |||
2056 | }else if (((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK) == slot_no){ | ||
2057 | S514_found_in_slot = 1; | ||
2058 | break; | ||
2059 | } | ||
2060 | } | ||
2061 | |||
2062 | /* if no S514 adapter has been found, then exit */ | ||
2063 | if (!number_S514_cards) { | ||
2064 | printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname); | ||
2065 | return 0; | ||
2066 | } | ||
2067 | /* if more than one S514 card has been found, then the user must have */ /* defined a slot number so that the correct adapter is used */ | ||
2068 | else if ((number_S514_cards > 1) && hw->auto_pci_cfg) { | ||
2069 | printk(KERN_INFO "%s: Error, PCI Slot autodetect Failed! \n" | ||
2070 | "%s: More than one S514 adapter found.\n" | ||
2071 | "%s: Disable the Autodetect feature and supply\n" | ||
2072 | "%s: the PCISLOT numbers for each card.\n", | ||
2073 | modname,modname,modname,modname); | ||
2074 | return 0; | ||
2075 | } | ||
2076 | /* if the user has specified a slot number and the S514 adapter has */ | ||
2077 | /* not been found in that slot, then exit */ | ||
2078 | else if (!hw->auto_pci_cfg && !S514_found_in_slot) { | ||
2079 | printk(KERN_INFO | ||
2080 | "%s: Error, S514 card not found in specified slot #%d\n", | ||
2081 | modname, slot_no); | ||
2082 | return 0; | ||
2083 | } | ||
2084 | |||
2085 | return (number_S514_cards); | ||
2086 | } | ||
2087 | |||
2088 | |||
2089 | |||
2090 | /******* Miscellaneous ******************************************************/ | ||
2091 | |||
2092 | /*============================================================================ | ||
2093 | * Calibrate SDLA memory access delay. | ||
2094 | * Count number of idle loops made within 1 second and then calculate the | ||
2095 | * number of loops that should be made to achive desired delay. | ||
2096 | */ | ||
2097 | static int calibrate_delay (int mks) | ||
2098 | { | ||
2099 | unsigned int delay; | ||
2100 | unsigned long stop; | ||
2101 | |||
2102 | for (delay = 0, stop = SYSTEM_TICK + HZ; SYSTEM_TICK < stop; ++delay); | ||
2103 | return (delay/(1000000L/mks) + 1); | ||
2104 | } | ||
2105 | |||
2106 | /*============================================================================ | ||
2107 | * Get option's index into the options list. | ||
2108 | * Return option's index (1 .. N) or zero if option is invalid. | ||
2109 | */ | ||
2110 | static int get_option_index (unsigned* optlist, unsigned optval) | ||
2111 | { | ||
2112 | int i; | ||
2113 | |||
2114 | for (i = 1; i <= optlist[0]; ++i) | ||
2115 | if ( optlist[i] == optval) | ||
2116 | return i; | ||
2117 | return 0; | ||
2118 | } | ||
2119 | |||
2120 | /*============================================================================ | ||
2121 | * Check memory region to see if it's available. | ||
2122 | * Return: 0 ok. | ||
2123 | */ | ||
2124 | static unsigned check_memregion (void* ptr, unsigned len) | ||
2125 | { | ||
2126 | volatile unsigned char* p = ptr; | ||
2127 | |||
2128 | for (; len && (readb (p) == 0xFF); --len, ++p) { | ||
2129 | writeb (0, p); /* attempt to write 0 */ | ||
2130 | if (readb(p) != 0xFF) { /* still has to read 0xFF */ | ||
2131 | writeb (0xFF, p);/* restore original value */ | ||
2132 | break; /* not good */ | ||
2133 | } | ||
2134 | } | ||
2135 | |||
2136 | return len; | ||
2137 | } | ||
2138 | |||
2139 | /*============================================================================ | ||
2140 | * Test memory region. | ||
2141 | * Return: size of the region that passed the test. | ||
2142 | * Note: Region size must be multiple of 2 ! | ||
2143 | */ | ||
2144 | static unsigned test_memregion (void* ptr, unsigned len) | ||
2145 | { | ||
2146 | volatile unsigned short* w_ptr; | ||
2147 | unsigned len_w = len >> 1; /* region len in words */ | ||
2148 | unsigned i; | ||
2149 | |||
2150 | for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr) | ||
2151 | writew (0xAA55, w_ptr); | ||
2152 | |||
2153 | for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr) | ||
2154 | if (readw (w_ptr) != 0xAA55) { | ||
2155 | len_w = i; | ||
2156 | break; | ||
2157 | } | ||
2158 | |||
2159 | for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr) | ||
2160 | writew (0x55AA, w_ptr); | ||
2161 | |||
2162 | for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr) | ||
2163 | if (readw(w_ptr) != 0x55AA) { | ||
2164 | len_w = i; | ||
2165 | break; | ||
2166 | } | ||
2167 | |||
2168 | for (i = 0, w_ptr = ptr; i < len_w; ++i, ++w_ptr) | ||
2169 | writew (0, w_ptr); | ||
2170 | |||
2171 | return len_w << 1; | ||
2172 | } | ||
2173 | |||
2174 | /*============================================================================ | ||
2175 | * Calculate 16-bit CRC using CCITT polynomial. | ||
2176 | */ | ||
2177 | static unsigned short checksum (unsigned char* buf, unsigned len) | ||
2178 | { | ||
2179 | unsigned short crc = 0; | ||
2180 | unsigned mask, flag; | ||
2181 | |||
2182 | for (; len; --len, ++buf) { | ||
2183 | for (mask = 0x80; mask; mask >>= 1) { | ||
2184 | flag = (crc & 0x8000); | ||
2185 | crc <<= 1; | ||
2186 | crc |= ((*buf & mask) ? 1 : 0); | ||
2187 | if (flag) crc ^= 0x1021; | ||
2188 | } | ||
2189 | } | ||
2190 | return crc; | ||
2191 | } | ||
2192 | |||
2193 | static int init_pci_slot(sdlahw_t *hw) | ||
2194 | { | ||
2195 | |||
2196 | u32 int_status; | ||
2197 | int volatile found=0; | ||
2198 | int i=0; | ||
2199 | |||
2200 | /* Check if this is a very first load for a specific | ||
2201 | * pci card. If it is, clear the interrput bits, and | ||
2202 | * set the flag indicating that this card was initialized. | ||
2203 | */ | ||
2204 | |||
2205 | for (i=0; (i<MAX_S514_CARDS) && !found; i++){ | ||
2206 | if (pci_slot_ar[i] == hw->S514_slot_no){ | ||
2207 | found=1; | ||
2208 | break; | ||
2209 | } | ||
2210 | if (pci_slot_ar[i] == 0xFF){ | ||
2211 | break; | ||
2212 | } | ||
2213 | } | ||
2214 | |||
2215 | if (!found){ | ||
2216 | read_S514_int_stat(hw,&int_status); | ||
2217 | S514_intack(hw,int_status); | ||
2218 | if (i == MAX_S514_CARDS){ | ||
2219 | printk(KERN_INFO "%s: Critical Error !!!\n",modname); | ||
2220 | printk(KERN_INFO | ||
2221 | "%s: Number of Sangoma PCI cards exceeded maximum limit.\n", | ||
2222 | modname); | ||
2223 | printk(KERN_INFO "Please contact Sangoma Technologies\n"); | ||
2224 | return 1; | ||
2225 | } | ||
2226 | pci_slot_ar[i] = hw->S514_slot_no; | ||
2227 | } | ||
2228 | return 0; | ||
2229 | } | ||
2230 | |||
2231 | static int pci_probe(sdlahw_t *hw) | ||
2232 | { | ||
2233 | |||
2234 | unsigned char slot_no; | ||
2235 | int number_S514_cards = 0; | ||
2236 | u16 PCI_subsys_vendor; | ||
2237 | u16 PCI_card_type; | ||
2238 | |||
2239 | struct pci_dev *pci_dev = NULL; | ||
2240 | struct pci_bus *bus = NULL; | ||
2241 | |||
2242 | slot_no = 0; | ||
2243 | |||
2244 | while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev)) | ||
2245 | != NULL) { | ||
2246 | |||
2247 | pci_read_config_word(pci_dev, PCI_SUBSYS_VENDOR_WORD, | ||
2248 | &PCI_subsys_vendor); | ||
2249 | |||
2250 | if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR) | ||
2251 | continue; | ||
2252 | |||
2253 | pci_read_config_word(pci_dev, PCI_CARD_TYPE, | ||
2254 | &PCI_card_type); | ||
2255 | |||
2256 | bus = pci_dev->bus; | ||
2257 | |||
2258 | /* A dual cpu card can support up to 4 physical connections, | ||
2259 | * where a single cpu card can support up to 2 physical | ||
2260 | * connections. The FT1 card can only support a single | ||
2261 | * connection, however we cannot distinguish between a Single | ||
2262 | * CPU card and an FT1 card. */ | ||
2263 | if (PCI_card_type == S514_DUAL_CPU){ | ||
2264 | number_S514_cards += 4; | ||
2265 | printk(KERN_INFO | ||
2266 | "wanpipe: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n", | ||
2267 | bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK), | ||
2268 | pci_dev->irq); | ||
2269 | }else{ | ||
2270 | number_S514_cards += 2; | ||
2271 | printk(KERN_INFO | ||
2272 | "wanpipe: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n", | ||
2273 | bus->number,((pci_dev->devfn >> 3) & PCI_DEV_SLOT_MASK), | ||
2274 | pci_dev->irq); | ||
2275 | } | ||
2276 | } | ||
2277 | |||
2278 | return number_S514_cards; | ||
2279 | |||
2280 | } | ||
2281 | |||
2282 | |||
2283 | |||
2284 | EXPORT_SYMBOL(wanpipe_hw_probe); | ||
2285 | |||
2286 | unsigned wanpipe_hw_probe(void) | ||
2287 | { | ||
2288 | sdlahw_t hw; | ||
2289 | unsigned* opt = s508_port_options; | ||
2290 | unsigned cardno=0; | ||
2291 | int i; | ||
2292 | |||
2293 | memset(&hw, 0, sizeof(hw)); | ||
2294 | |||
2295 | for (i = 1; i <= opt[0]; i++) { | ||
2296 | if (detect_s508(opt[i])){ | ||
2297 | /* S508 card can support up to two physical links */ | ||
2298 | cardno+=2; | ||
2299 | printk(KERN_INFO "wanpipe: S508-ISA card found, port 0x%x\n",opt[i]); | ||
2300 | } | ||
2301 | } | ||
2302 | |||
2303 | #ifdef CONFIG_PCI | ||
2304 | hw.S514_slot_no = 0; | ||
2305 | cardno += pci_probe(&hw); | ||
2306 | #else | ||
2307 | printk(KERN_INFO "wanpipe: Warning, Kernel not compiled for PCI support!\n"); | ||
2308 | printk(KERN_INFO "wanpipe: PCI Hardware Probe Failed!\n"); | ||
2309 | #endif | ||
2310 | |||
2311 | return cardno; | ||
2312 | } | ||
2313 | |||
2314 | /****** End *****************************************************************/ | ||
diff --git a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c deleted file mode 100644 index 7a8b22a7ea31..000000000000 --- a/drivers/net/wan/sdlamain.c +++ /dev/null | |||
@@ -1,1346 +0,0 @@ | |||
1 | /**************************************************************************** | ||
2 | * sdlamain.c WANPIPE(tm) Multiprotocol WAN Link Driver. Main module. | ||
3 | * | ||
4 | * Author: Nenad Corbic <ncorbic@sangoma.com> | ||
5 | * Gideon Hack | ||
6 | * | ||
7 | * Copyright: (c) 1995-2000 Sangoma Technologies Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | * ============================================================================ | ||
14 | * Dec 22, 2000 Nenad Corbic Updated for 2.4.X kernels. | ||
15 | * Removed the polling routine. | ||
16 | * Nov 13, 2000 Nenad Corbic Added hw probing on module load and dynamic | ||
17 | * device allocation. | ||
18 | * Nov 7, 2000 Nenad Corbic Fixed the Multi-Port PPP for kernels | ||
19 | * 2.2.16 and above. | ||
20 | * Aug 2, 2000 Nenad Corbic Block the Multi-Port PPP from running on | ||
21 | * kernels 2.2.16 or greater. The SyncPPP | ||
22 | * has changed. | ||
23 | * Jul 25, 2000 Nenad Corbic Updated the Piggiback support for MultPPPP. | ||
24 | * Jul 13, 2000 Nenad Corbic Added Multi-PPP support. | ||
25 | * Feb 02, 2000 Nenad Corbic Fixed up piggyback probing and selection. | ||
26 | * Sep 23, 1999 Nenad Corbic Added support for SMP | ||
27 | * Sep 13, 1999 Nenad Corbic Each port is treated as a separate device. | ||
28 | * Jun 02, 1999 Gideon Hack Added support for the S514 adapter. | ||
29 | * Updates for Linux 2.2.X kernels. | ||
30 | * Sep 17, 1998 Jaspreet Singh Updated for 2.1.121+ kernel | ||
31 | * Nov 28, 1997 Jaspreet Singh Changed DRV_RELEASE to 1 | ||
32 | * Nov 10, 1997 Jaspreet Singh Changed sti() to restore_flags(); | ||
33 | * Nov 06, 1997 Jaspreet Singh Changed DRV_VERSION to 4 and DRV_RELEASE to 0 | ||
34 | * Oct 20, 1997 Jaspreet Singh Modified sdla_isr routine so that card->in_isr | ||
35 | * assignments are taken out and placed in the | ||
36 | * sdla_ppp.c, sdla_fr.c and sdla_x25.c isr | ||
37 | * routines. Took out 'wandev->tx_int_enabled' and | ||
38 | * replaced it with 'wandev->enable_tx_int'. | ||
39 | * May 29, 1997 Jaspreet Singh Flow Control Problem | ||
40 | * added "wandev->tx_int_enabled=1" line in the | ||
41 | * init module. This line initializes the flag for | ||
42 | * preventing Interrupt disabled with device set to | ||
43 | * busy | ||
44 | * Jan 15, 1997 Gene Kozin Version 3.1.0 | ||
45 | * o added UDP management stuff | ||
46 | * Jan 02, 1997 Gene Kozin Initial version. | ||
47 | *****************************************************************************/ | ||
48 | |||
49 | #include <linux/config.h> /* OS configuration options */ | ||
50 | #include <linux/stddef.h> /* offsetof(), etc. */ | ||
51 | #include <linux/errno.h> /* return codes */ | ||
52 | #include <linux/string.h> /* inline memset(), etc. */ | ||
53 | #include <linux/init.h> | ||
54 | #include <linux/slab.h> /* kmalloc(), kfree() */ | ||
55 | #include <linux/kernel.h> /* printk(), and other useful stuff */ | ||
56 | #include <linux/module.h> /* support for loadable modules */ | ||
57 | #include <linux/ioport.h> /* request_region(), release_region() */ | ||
58 | #include <linux/wanrouter.h> /* WAN router definitions */ | ||
59 | #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ | ||
60 | #include <linux/rcupdate.h> | ||
61 | |||
62 | #include <linux/in.h> | ||
63 | #include <asm/io.h> /* phys_to_virt() */ | ||
64 | #include <linux/pci.h> | ||
65 | #include <linux/sdlapci.h> | ||
66 | #include <linux/if_wanpipe_common.h> | ||
67 | |||
68 | #include <asm/uaccess.h> /* kernel <-> user copy */ | ||
69 | #include <linux/inetdevice.h> | ||
70 | |||
71 | #include <linux/ip.h> | ||
72 | #include <net/route.h> | ||
73 | |||
74 | #define KMEM_SAFETYZONE 8 | ||
75 | |||
76 | |||
77 | #ifndef CONFIG_WANPIPE_FR | ||
78 | #define wpf_init(a,b) (-EPROTONOSUPPORT) | ||
79 | #endif | ||
80 | |||
81 | #ifndef CONFIG_WANPIPE_CHDLC | ||
82 | #define wpc_init(a,b) (-EPROTONOSUPPORT) | ||
83 | #endif | ||
84 | |||
85 | #ifndef CONFIG_WANPIPE_X25 | ||
86 | #define wpx_init(a,b) (-EPROTONOSUPPORT) | ||
87 | #endif | ||
88 | |||
89 | #ifndef CONFIG_WANPIPE_PPP | ||
90 | #define wpp_init(a,b) (-EPROTONOSUPPORT) | ||
91 | #endif | ||
92 | |||
93 | #ifndef CONFIG_WANPIPE_MULTPPP | ||
94 | #define wsppp_init(a,b) (-EPROTONOSUPPORT) | ||
95 | #endif | ||
96 | |||
97 | |||
98 | /***********FOR DEBUGGING PURPOSES********************************************* | ||
99 | static void * dbg_kmalloc(unsigned int size, int prio, int line) { | ||
100 | int i = 0; | ||
101 | void * v = kmalloc(size+sizeof(unsigned int)+2*KMEM_SAFETYZONE*8,prio); | ||
102 | char * c1 = v; | ||
103 | c1 += sizeof(unsigned int); | ||
104 | *((unsigned int *)v) = size; | ||
105 | |||
106 | for (i = 0; i < KMEM_SAFETYZONE; i++) { | ||
107 | c1[0] = 'D'; c1[1] = 'E'; c1[2] = 'A'; c1[3] = 'D'; | ||
108 | c1[4] = 'B'; c1[5] = 'E'; c1[6] = 'E'; c1[7] = 'F'; | ||
109 | c1 += 8; | ||
110 | } | ||
111 | c1 += size; | ||
112 | for (i = 0; i < KMEM_SAFETYZONE; i++) { | ||
113 | c1[0] = 'M'; c1[1] = 'U'; c1[2] = 'N'; c1[3] = 'G'; | ||
114 | c1[4] = 'W'; c1[5] = 'A'; c1[6] = 'L'; c1[7] = 'L'; | ||
115 | c1 += 8; | ||
116 | } | ||
117 | v = ((char *)v) + sizeof(unsigned int) + KMEM_SAFETYZONE*8; | ||
118 | printk(KERN_INFO "line %d kmalloc(%d,%d) = %p\n",line,size,prio,v); | ||
119 | return v; | ||
120 | } | ||
121 | static void dbg_kfree(void * v, int line) { | ||
122 | unsigned int * sp = (unsigned int *)(((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8)); | ||
123 | unsigned int size = *sp; | ||
124 | char * c1 = ((char *)v) - KMEM_SAFETYZONE*8; | ||
125 | int i = 0; | ||
126 | for (i = 0; i < KMEM_SAFETYZONE; i++) { | ||
127 | if ( c1[0] != 'D' || c1[1] != 'E' || c1[2] != 'A' || c1[3] != 'D' | ||
128 | || c1[4] != 'B' || c1[5] != 'E' || c1[6] != 'E' || c1[7] != 'F') { | ||
129 | printk(KERN_INFO "kmalloced block at %p has been corrupted (underrun)!\n",v); | ||
130 | printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8, | ||
131 | c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] ); | ||
132 | } | ||
133 | c1 += 8; | ||
134 | } | ||
135 | c1 += size; | ||
136 | for (i = 0; i < KMEM_SAFETYZONE; i++) { | ||
137 | if ( c1[0] != 'M' || c1[1] != 'U' || c1[2] != 'N' || c1[3] != 'G' | ||
138 | || c1[4] != 'W' || c1[5] != 'A' || c1[6] != 'L' || c1[7] != 'L' | ||
139 | ) { | ||
140 | printk(KERN_INFO "kmalloced block at %p has been corrupted (overrun):\n",v); | ||
141 | printk(KERN_INFO " %4x: %2x %2x %2x %2x %2x %2x %2x %2x\n", i*8, | ||
142 | c1[0],c1[1],c1[2],c1[3],c1[4],c1[5],c1[6],c1[7] ); | ||
143 | } | ||
144 | c1 += 8; | ||
145 | } | ||
146 | printk(KERN_INFO "line %d kfree(%p)\n",line,v); | ||
147 | v = ((char *)v) - (sizeof(unsigned int) + KMEM_SAFETYZONE*8); | ||
148 | kfree(v); | ||
149 | } | ||
150 | |||
151 | #define kmalloc(x,y) dbg_kmalloc(x,y,__LINE__) | ||
152 | #define kfree(x) dbg_kfree(x,__LINE__) | ||
153 | ******************************************************************************/ | ||
154 | |||
155 | |||
156 | |||
157 | /****** Defines & Macros ****************************************************/ | ||
158 | |||
159 | #ifdef _DEBUG_ | ||
160 | #define STATIC | ||
161 | #else | ||
162 | #define STATIC static | ||
163 | #endif | ||
164 | |||
165 | #define DRV_VERSION 5 /* version number */ | ||
166 | #define DRV_RELEASE 0 /* release (minor version) number */ | ||
167 | #define MAX_CARDS 16 /* max number of adapters */ | ||
168 | |||
169 | #ifndef CONFIG_WANPIPE_CARDS /* configurable option */ | ||
170 | #define CONFIG_WANPIPE_CARDS 1 | ||
171 | #endif | ||
172 | |||
173 | #define CMD_OK 0 /* normal firmware return code */ | ||
174 | #define CMD_TIMEOUT 0xFF /* firmware command timed out */ | ||
175 | #define MAX_CMD_RETRY 10 /* max number of firmware retries */ | ||
176 | /****** Function Prototypes *************************************************/ | ||
177 | |||
178 | extern void disable_irq(unsigned int); | ||
179 | extern void enable_irq(unsigned int); | ||
180 | |||
181 | /* WAN link driver entry points */ | ||
182 | static int setup(struct wan_device* wandev, wandev_conf_t* conf); | ||
183 | static int shutdown(struct wan_device* wandev); | ||
184 | static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg); | ||
185 | |||
186 | /* IOCTL handlers */ | ||
187 | static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump); | ||
188 | static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int); | ||
189 | |||
190 | /* Miscellaneous functions */ | ||
191 | STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs); | ||
192 | static void release_hw (sdla_t *card); | ||
193 | |||
194 | static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int*); | ||
195 | static int check_s514_conflicts (sdla_t* card,wandev_conf_t* conf, int*); | ||
196 | |||
197 | |||
198 | /****** Global Data ********************************************************** | ||
199 | * Note: All data must be explicitly initialized!!! | ||
200 | */ | ||
201 | |||
202 | /* private data */ | ||
203 | static char drvname[] = "wanpipe"; | ||
204 | static char fullname[] = "WANPIPE(tm) Multiprotocol Driver"; | ||
205 | static char copyright[] = "(c) 1995-2000 Sangoma Technologies Inc."; | ||
206 | static int ncards; | ||
207 | static sdla_t* card_array; /* adapter data space */ | ||
208 | |||
209 | /* Wanpipe's own workqueue, used for all API's. | ||
210 | * All protocol specific tasks will be inserted | ||
211 | * into the "wanpipe_wq" workqueue. | ||
212 | |||
213 | * The kernel workqueue mechanism will execute | ||
214 | * all pending tasks in the "wanpipe_wq" workqueue. | ||
215 | */ | ||
216 | |||
217 | struct workqueue_struct *wanpipe_wq; | ||
218 | DECLARE_WORK(wanpipe_work, NULL, NULL); | ||
219 | |||
220 | static int wanpipe_bh_critical; | ||
221 | |||
222 | /******* Kernel Loadable Module Entry Points ********************************/ | ||
223 | |||
224 | /*============================================================================ | ||
225 | * Module 'insert' entry point. | ||
226 | * o print announcement | ||
227 | * o allocate adapter data space | ||
228 | * o initialize static data | ||
229 | * o register all cards with WAN router | ||
230 | * o calibrate SDLA shared memory access delay. | ||
231 | * | ||
232 | * Return: 0 Ok | ||
233 | * < 0 error. | ||
234 | * Context: process | ||
235 | */ | ||
236 | |||
237 | static int __init wanpipe_init(void) | ||
238 | { | ||
239 | int cnt, err = 0; | ||
240 | |||
241 | printk(KERN_INFO "%s v%u.%u %s\n", | ||
242 | fullname, DRV_VERSION, DRV_RELEASE, copyright); | ||
243 | |||
244 | wanpipe_wq = create_workqueue("wanpipe_wq"); | ||
245 | if (!wanpipe_wq) | ||
246 | return -ENOMEM; | ||
247 | |||
248 | /* Probe for wanpipe cards and return the number found */ | ||
249 | printk(KERN_INFO "wanpipe: Probing for WANPIPE hardware.\n"); | ||
250 | ncards = wanpipe_hw_probe(); | ||
251 | if (ncards){ | ||
252 | printk(KERN_INFO "wanpipe: Allocating maximum %i devices: wanpipe%i - wanpipe%i.\n",ncards,1,ncards); | ||
253 | }else{ | ||
254 | printk(KERN_INFO "wanpipe: No S514/S508 cards found, unloading modules!\n"); | ||
255 | destroy_workqueue(wanpipe_wq); | ||
256 | return -ENODEV; | ||
257 | } | ||
258 | |||
259 | /* Verify number of cards and allocate adapter data space */ | ||
260 | card_array = kmalloc(sizeof(sdla_t) * ncards, GFP_KERNEL); | ||
261 | if (card_array == NULL) { | ||
262 | destroy_workqueue(wanpipe_wq); | ||
263 | return -ENOMEM; | ||
264 | } | ||
265 | |||
266 | memset(card_array, 0, sizeof(sdla_t) * ncards); | ||
267 | |||
268 | /* Register adapters with WAN router */ | ||
269 | for (cnt = 0; cnt < ncards; ++ cnt) { | ||
270 | sdla_t* card = &card_array[cnt]; | ||
271 | struct wan_device* wandev = &card->wandev; | ||
272 | |||
273 | card->next = NULL; | ||
274 | sprintf(card->devname, "%s%d", drvname, cnt + 1); | ||
275 | wandev->magic = ROUTER_MAGIC; | ||
276 | wandev->name = card->devname; | ||
277 | wandev->private = card; | ||
278 | wandev->enable_tx_int = 0; | ||
279 | wandev->setup = &setup; | ||
280 | wandev->shutdown = &shutdown; | ||
281 | wandev->ioctl = &ioctl; | ||
282 | err = register_wan_device(wandev); | ||
283 | if (err) { | ||
284 | printk(KERN_INFO | ||
285 | "%s: %s registration failed with error %d!\n", | ||
286 | drvname, card->devname, err); | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | if (cnt){ | ||
291 | ncards = cnt; /* adjust actual number of cards */ | ||
292 | }else { | ||
293 | kfree(card_array); | ||
294 | destroy_workqueue(wanpipe_wq); | ||
295 | printk(KERN_INFO "IN Init Module: NO Cards registered\n"); | ||
296 | err = -ENODEV; | ||
297 | } | ||
298 | |||
299 | return err; | ||
300 | } | ||
301 | |||
302 | /*============================================================================ | ||
303 | * Module 'remove' entry point. | ||
304 | * o unregister all adapters from the WAN router | ||
305 | * o release all remaining system resources | ||
306 | */ | ||
307 | static void __exit wanpipe_cleanup(void) | ||
308 | { | ||
309 | int i; | ||
310 | |||
311 | if (!ncards) | ||
312 | return; | ||
313 | |||
314 | for (i = 0; i < ncards; ++i) { | ||
315 | sdla_t* card = &card_array[i]; | ||
316 | unregister_wan_device(card->devname); | ||
317 | } | ||
318 | destroy_workqueue(wanpipe_wq); | ||
319 | kfree(card_array); | ||
320 | |||
321 | printk(KERN_INFO "\nwanpipe: WANPIPE Modules Unloaded.\n"); | ||
322 | } | ||
323 | |||
324 | module_init(wanpipe_init); | ||
325 | module_exit(wanpipe_cleanup); | ||
326 | |||
327 | /******* WAN Device Driver Entry Points *************************************/ | ||
328 | |||
329 | /*============================================================================ | ||
330 | * Setup/configure WAN link driver. | ||
331 | * o check adapter state | ||
332 | * o make sure firmware is present in configuration | ||
333 | * o make sure I/O port and IRQ are specified | ||
334 | * o make sure I/O region is available | ||
335 | * o allocate interrupt vector | ||
336 | * o setup SDLA hardware | ||
337 | * o call appropriate routine to perform protocol-specific initialization | ||
338 | * o mark I/O region as used | ||
339 | * o if this is the first active card, then schedule background task | ||
340 | * | ||
341 | * This function is called when router handles ROUTER_SETUP IOCTL. The | ||
342 | * configuration structure is in kernel memory (including extended data, if | ||
343 | * any). | ||
344 | */ | ||
345 | |||
346 | static int setup(struct wan_device* wandev, wandev_conf_t* conf) | ||
347 | { | ||
348 | sdla_t* card; | ||
349 | int err = 0; | ||
350 | int irq=0; | ||
351 | |||
352 | /* Sanity checks */ | ||
353 | if ((wandev == NULL) || (wandev->private == NULL) || (conf == NULL)){ | ||
354 | printk(KERN_INFO | ||
355 | "%s: Failed Sdlamain Setup wandev %u, card %u, conf %u !\n", | ||
356 | wandev->name, | ||
357 | (unsigned int)wandev,(unsigned int)wandev->private, | ||
358 | (unsigned int)conf); | ||
359 | return -EFAULT; | ||
360 | } | ||
361 | |||
362 | printk(KERN_INFO "%s: Starting WAN Setup\n", wandev->name); | ||
363 | |||
364 | card = wandev->private; | ||
365 | if (wandev->state != WAN_UNCONFIGURED){ | ||
366 | printk(KERN_INFO "%s: failed sdlamain setup, busy!\n", | ||
367 | wandev->name); | ||
368 | return -EBUSY; /* already configured */ | ||
369 | } | ||
370 | |||
371 | printk(KERN_INFO "\nProcessing WAN device %s...\n", wandev->name); | ||
372 | |||
373 | /* Initialize the counters for each wandev | ||
374 | * Used for counting number of times new_if and | ||
375 | * del_if get called. | ||
376 | */ | ||
377 | wandev->del_if_cnt = 0; | ||
378 | wandev->new_if_cnt = 0; | ||
379 | wandev->config_id = conf->config_id; | ||
380 | |||
381 | if (!conf->data_size || (conf->data == NULL)) { | ||
382 | printk(KERN_INFO | ||
383 | "%s: firmware not found in configuration data!\n", | ||
384 | wandev->name); | ||
385 | return -EINVAL; | ||
386 | } | ||
387 | |||
388 | /* Check for resource conflicts and setup the | ||
389 | * card for piggibacking if necessary */ | ||
390 | if(!conf->S514_CPU_no[0]) { | ||
391 | if ((err=check_s508_conflicts(card,conf,&irq)) != 0){ | ||
392 | return err; | ||
393 | } | ||
394 | }else { | ||
395 | if ((err=check_s514_conflicts(card,conf,&irq)) != 0){ | ||
396 | return err; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | /* If the current card has already been configured | ||
401 | * or it's a piggyback card, do not try to allocate | ||
402 | * resources. | ||
403 | */ | ||
404 | if (!card->wandev.piggyback && !card->configured){ | ||
405 | |||
406 | /* Configure hardware, load firmware, etc. */ | ||
407 | memset(&card->hw, 0, sizeof(sdlahw_t)); | ||
408 | |||
409 | /* for an S514 adapter, pass the CPU number and the slot number read */ | ||
410 | /* from 'router.conf' to the 'sdla_setup()' function via the 'port' */ | ||
411 | /* parameter */ | ||
412 | if (conf->S514_CPU_no[0]){ | ||
413 | |||
414 | card->hw.S514_cpu_no[0] = conf->S514_CPU_no[0]; | ||
415 | card->hw.S514_slot_no = conf->PCI_slot_no; | ||
416 | card->hw.auto_pci_cfg = conf->auto_pci_cfg; | ||
417 | |||
418 | if (card->hw.auto_pci_cfg == WANOPT_YES){ | ||
419 | printk(KERN_INFO "%s: Setting CPU to %c and Slot to Auto\n", | ||
420 | card->devname, card->hw.S514_cpu_no[0]); | ||
421 | }else{ | ||
422 | printk(KERN_INFO "%s: Setting CPU to %c and Slot to %i\n", | ||
423 | card->devname, card->hw.S514_cpu_no[0], card->hw.S514_slot_no); | ||
424 | } | ||
425 | |||
426 | }else{ | ||
427 | /* 508 Card io port and irq initialization */ | ||
428 | card->hw.port = conf->ioport; | ||
429 | card->hw.irq = (conf->irq == 9) ? 2 : conf->irq; | ||
430 | } | ||
431 | |||
432 | |||
433 | /* Compute the virtual address of the card in kernel space */ | ||
434 | if(conf->maddr){ | ||
435 | card->hw.dpmbase = phys_to_virt(conf->maddr); | ||
436 | }else{ | ||
437 | card->hw.dpmbase = (void *)conf->maddr; | ||
438 | } | ||
439 | |||
440 | card->hw.dpmsize = SDLA_WINDOWSIZE; | ||
441 | |||
442 | /* set the adapter type if using an S514 adapter */ | ||
443 | card->hw.type = (conf->S514_CPU_no[0]) ? SDLA_S514 : conf->hw_opt[0]; | ||
444 | card->hw.pclk = conf->hw_opt[1]; | ||
445 | |||
446 | err = sdla_setup(&card->hw, conf->data, conf->data_size); | ||
447 | if (err){ | ||
448 | printk(KERN_INFO "%s: Hardware setup Failed %i\n", | ||
449 | card->devname,err); | ||
450 | return err; | ||
451 | } | ||
452 | |||
453 | if(card->hw.type != SDLA_S514) | ||
454 | irq = (conf->irq == 2) ? 9 : conf->irq; /* IRQ2 -> IRQ9 */ | ||
455 | else | ||
456 | irq = card->hw.irq; | ||
457 | |||
458 | /* request an interrupt vector - note that interrupts may be shared */ | ||
459 | /* when using the S514 PCI adapter */ | ||
460 | |||
461 | if(request_irq(irq, sdla_isr, | ||
462 | (card->hw.type == SDLA_S514) ? SA_SHIRQ : 0, | ||
463 | wandev->name, card)){ | ||
464 | |||
465 | printk(KERN_INFO "%s: Can't reserve IRQ %d!\n", wandev->name, irq); | ||
466 | return -EINVAL; | ||
467 | } | ||
468 | |||
469 | }else{ | ||
470 | printk(KERN_INFO "%s: Card Configured %lu or Piggybacking %i!\n", | ||
471 | wandev->name,card->configured,card->wandev.piggyback); | ||
472 | } | ||
473 | |||
474 | |||
475 | if (!card->configured){ | ||
476 | |||
477 | /* Initialize the Spin lock */ | ||
478 | printk(KERN_INFO "%s: Initializing for SMP\n",wandev->name); | ||
479 | |||
480 | /* Piggyback spin lock has already been initialized, | ||
481 | * in check_s514/s508_conflicts() */ | ||
482 | if (!card->wandev.piggyback){ | ||
483 | spin_lock_init(&card->wandev.lock); | ||
484 | } | ||
485 | |||
486 | /* Intialize WAN device data space */ | ||
487 | wandev->irq = irq; | ||
488 | wandev->dma = 0; | ||
489 | if(card->hw.type != SDLA_S514){ | ||
490 | wandev->ioport = card->hw.port; | ||
491 | }else{ | ||
492 | wandev->S514_cpu_no[0] = card->hw.S514_cpu_no[0]; | ||
493 | wandev->S514_slot_no = card->hw.S514_slot_no; | ||
494 | } | ||
495 | wandev->maddr = (unsigned long)card->hw.dpmbase; | ||
496 | wandev->msize = card->hw.dpmsize; | ||
497 | wandev->hw_opt[0] = card->hw.type; | ||
498 | wandev->hw_opt[1] = card->hw.pclk; | ||
499 | wandev->hw_opt[2] = card->hw.memory; | ||
500 | wandev->hw_opt[3] = card->hw.fwid; | ||
501 | } | ||
502 | |||
503 | /* Protocol-specific initialization */ | ||
504 | switch (card->hw.fwid) { | ||
505 | |||
506 | case SFID_X25_502: | ||
507 | case SFID_X25_508: | ||
508 | printk(KERN_INFO "%s: Starting X.25 Protocol Init.\n", | ||
509 | card->devname); | ||
510 | err = wpx_init(card, conf); | ||
511 | break; | ||
512 | case SFID_FR502: | ||
513 | case SFID_FR508: | ||
514 | printk(KERN_INFO "%s: Starting Frame Relay Protocol Init.\n", | ||
515 | card->devname); | ||
516 | err = wpf_init(card, conf); | ||
517 | break; | ||
518 | case SFID_PPP502: | ||
519 | case SFID_PPP508: | ||
520 | printk(KERN_INFO "%s: Starting PPP Protocol Init.\n", | ||
521 | card->devname); | ||
522 | err = wpp_init(card, conf); | ||
523 | break; | ||
524 | |||
525 | case SFID_CHDLC508: | ||
526 | case SFID_CHDLC514: | ||
527 | if (conf->ft1){ | ||
528 | printk(KERN_INFO "%s: Starting FT1 CSU/DSU Config Driver.\n", | ||
529 | card->devname); | ||
530 | err = wpft1_init(card, conf); | ||
531 | break; | ||
532 | |||
533 | }else if (conf->config_id == WANCONFIG_MPPP){ | ||
534 | printk(KERN_INFO "%s: Starting Multi-Port PPP Protocol Init.\n", | ||
535 | card->devname); | ||
536 | err = wsppp_init(card,conf); | ||
537 | break; | ||
538 | |||
539 | }else{ | ||
540 | printk(KERN_INFO "%s: Starting CHDLC Protocol Init.\n", | ||
541 | card->devname); | ||
542 | err = wpc_init(card, conf); | ||
543 | break; | ||
544 | } | ||
545 | default: | ||
546 | printk(KERN_INFO "%s: Error, Firmware is not supported %X %X!\n", | ||
547 | wandev->name,card->hw.fwid,SFID_CHDLC508); | ||
548 | err = -EPROTONOSUPPORT; | ||
549 | } | ||
550 | |||
551 | if (err != 0){ | ||
552 | if (err == -EPROTONOSUPPORT){ | ||
553 | printk(KERN_INFO | ||
554 | "%s: Error, Protocol selected has not been compiled!\n", | ||
555 | card->devname); | ||
556 | printk(KERN_INFO | ||
557 | "%s: Re-configure the kernel and re-build the modules!\n", | ||
558 | card->devname); | ||
559 | } | ||
560 | |||
561 | release_hw(card); | ||
562 | wandev->state = WAN_UNCONFIGURED; | ||
563 | return err; | ||
564 | } | ||
565 | |||
566 | |||
567 | /* Reserve I/O region and schedule background task */ | ||
568 | if(card->hw.type != SDLA_S514 && !card->wandev.piggyback) | ||
569 | if (!request_region(card->hw.port, card->hw.io_range, | ||
570 | wandev->name)) { | ||
571 | printk(KERN_WARNING "port 0x%04x busy\n", card->hw.port); | ||
572 | release_hw(card); | ||
573 | wandev->state = WAN_UNCONFIGURED; | ||
574 | return -EBUSY; | ||
575 | } | ||
576 | |||
577 | /* Only use the polling routine for the X25 protocol */ | ||
578 | |||
579 | card->wandev.critical=0; | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | /*================================================================== | ||
584 | * configure_s508_card | ||
585 | * | ||
586 | * For a S508 adapter, check for a possible configuration error in that | ||
587 | * we are loading an adapter in the same IO port as a previously loaded S508 | ||
588 | * card. | ||
589 | */ | ||
590 | |||
591 | static int check_s508_conflicts (sdla_t* card,wandev_conf_t* conf, int *irq) | ||
592 | { | ||
593 | unsigned long smp_flags; | ||
594 | int i; | ||
595 | |||
596 | if (conf->ioport <= 0) { | ||
597 | printk(KERN_INFO | ||
598 | "%s: can't configure without I/O port address!\n", | ||
599 | card->wandev.name); | ||
600 | return -EINVAL; | ||
601 | } | ||
602 | |||
603 | if (conf->irq <= 0) { | ||
604 | printk(KERN_INFO "%s: can't configure without IRQ!\n", | ||
605 | card->wandev.name); | ||
606 | return -EINVAL; | ||
607 | } | ||
608 | |||
609 | if (test_bit(0,&card->configured)) | ||
610 | return 0; | ||
611 | |||
612 | |||
613 | /* Check for already loaded card with the same IO port and IRQ | ||
614 | * If found, copy its hardware configuration and use its | ||
615 | * resources (i.e. piggybacking) | ||
616 | */ | ||
617 | |||
618 | for (i = 0; i < ncards; i++) { | ||
619 | sdla_t *nxt_card = &card_array[i]; | ||
620 | |||
621 | /* Skip the current card ptr */ | ||
622 | if (nxt_card == card) | ||
623 | continue; | ||
624 | |||
625 | |||
626 | /* Find a card that is already configured with the | ||
627 | * same IO Port */ | ||
628 | if ((nxt_card->hw.type == SDLA_S508) && | ||
629 | (nxt_card->hw.port == conf->ioport) && | ||
630 | (nxt_card->next == NULL)){ | ||
631 | |||
632 | /* We found a card the card that has same configuration | ||
633 | * as us. This means, that we must setup this card in | ||
634 | * piggibacking mode. However, only CHDLC and MPPP protocol | ||
635 | * support this setup */ | ||
636 | |||
637 | if ((conf->config_id == WANCONFIG_CHDLC || | ||
638 | conf->config_id == WANCONFIG_MPPP) && | ||
639 | (nxt_card->wandev.config_id == WANCONFIG_CHDLC || | ||
640 | nxt_card->wandev.config_id == WANCONFIG_MPPP)){ | ||
641 | |||
642 | *irq = nxt_card->hw.irq; | ||
643 | memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t)); | ||
644 | |||
645 | /* The master could already be running, we must | ||
646 | * set this as a critical area */ | ||
647 | lock_adapter_irq(&nxt_card->wandev.lock, &smp_flags); | ||
648 | |||
649 | nxt_card->next = card; | ||
650 | card->next = nxt_card; | ||
651 | |||
652 | card->wandev.piggyback = WANOPT_YES; | ||
653 | |||
654 | /* We must initialise the piggiback spin lock here | ||
655 | * since isr will try to lock card->next if it | ||
656 | * exists */ | ||
657 | spin_lock_init(&card->wandev.lock); | ||
658 | |||
659 | unlock_adapter_irq(&nxt_card->wandev.lock, &smp_flags); | ||
660 | break; | ||
661 | }else{ | ||
662 | /* Trying to run piggibacking with a wrong protocol */ | ||
663 | printk(KERN_INFO "%s: ERROR: Resource busy, ioport: 0x%x\n" | ||
664 | "%s: This protocol doesn't support\n" | ||
665 | "%s: multi-port operation!\n", | ||
666 | card->devname,nxt_card->hw.port, | ||
667 | card->devname,card->devname); | ||
668 | return -EEXIST; | ||
669 | } | ||
670 | } | ||
671 | } | ||
672 | |||
673 | |||
674 | /* Make sure I/O port region is available only if we are the | ||
675 | * master device. If we are running in piggybacking mode, | ||
676 | * we will use the resources of the master card. */ | ||
677 | if (!card->wandev.piggyback) { | ||
678 | struct resource *rr = | ||
679 | request_region(conf->ioport, SDLA_MAXIORANGE, "sdlamain"); | ||
680 | release_region(conf->ioport, SDLA_MAXIORANGE); | ||
681 | |||
682 | if (!rr) { | ||
683 | printk(KERN_INFO | ||
684 | "%s: I/O region 0x%X - 0x%X is in use!\n", | ||
685 | card->wandev.name, conf->ioport, | ||
686 | conf->ioport + SDLA_MAXIORANGE - 1); | ||
687 | return -EINVAL; | ||
688 | } | ||
689 | } | ||
690 | |||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | /*================================================================== | ||
695 | * configure_s514_card | ||
696 | * | ||
697 | * For a S514 adapter, check for a possible configuration error in that | ||
698 | * we are loading an adapter in the same slot as a previously loaded S514 | ||
699 | * card. | ||
700 | */ | ||
701 | |||
702 | |||
703 | static int check_s514_conflicts(sdla_t* card,wandev_conf_t* conf, int *irq) | ||
704 | { | ||
705 | unsigned long smp_flags; | ||
706 | int i; | ||
707 | |||
708 | if (test_bit(0,&card->configured)) | ||
709 | return 0; | ||
710 | |||
711 | |||
712 | /* Check for already loaded card with the same IO port and IRQ | ||
713 | * If found, copy its hardware configuration and use its | ||
714 | * resources (i.e. piggybacking) | ||
715 | */ | ||
716 | |||
717 | for (i = 0; i < ncards; i ++) { | ||
718 | |||
719 | sdla_t* nxt_card = &card_array[i]; | ||
720 | if(nxt_card == card) | ||
721 | continue; | ||
722 | |||
723 | if((nxt_card->hw.type == SDLA_S514) && | ||
724 | (nxt_card->hw.S514_slot_no == conf->PCI_slot_no) && | ||
725 | (nxt_card->hw.S514_cpu_no[0] == conf->S514_CPU_no[0])&& | ||
726 | (nxt_card->next == NULL)){ | ||
727 | |||
728 | |||
729 | if ((conf->config_id == WANCONFIG_CHDLC || | ||
730 | conf->config_id == WANCONFIG_MPPP) && | ||
731 | (nxt_card->wandev.config_id == WANCONFIG_CHDLC || | ||
732 | nxt_card->wandev.config_id == WANCONFIG_MPPP)){ | ||
733 | |||
734 | *irq = nxt_card->hw.irq; | ||
735 | memcpy(&card->hw, &nxt_card->hw, sizeof(sdlahw_t)); | ||
736 | |||
737 | /* The master could already be running, we must | ||
738 | * set this as a critical area */ | ||
739 | lock_adapter_irq(&nxt_card->wandev.lock,&smp_flags); | ||
740 | nxt_card->next = card; | ||
741 | card->next = nxt_card; | ||
742 | |||
743 | card->wandev.piggyback = WANOPT_YES; | ||
744 | |||
745 | /* We must initialise the piggiback spin lock here | ||
746 | * since isr will try to lock card->next if it | ||
747 | * exists */ | ||
748 | spin_lock_init(&card->wandev.lock); | ||
749 | |||
750 | unlock_adapter_irq(&nxt_card->wandev.lock,&smp_flags); | ||
751 | |||
752 | }else{ | ||
753 | /* Trying to run piggibacking with a wrong protocol */ | ||
754 | printk(KERN_INFO "%s: ERROR: Resource busy: CPU %c PCISLOT %i\n" | ||
755 | "%s: This protocol doesn't support\n" | ||
756 | "%s: multi-port operation!\n", | ||
757 | card->devname, | ||
758 | conf->S514_CPU_no[0],conf->PCI_slot_no, | ||
759 | card->devname,card->devname); | ||
760 | return -EEXIST; | ||
761 | } | ||
762 | } | ||
763 | } | ||
764 | |||
765 | return 0; | ||
766 | } | ||
767 | |||
768 | |||
769 | |||
770 | /*============================================================================ | ||
771 | * Shut down WAN link driver. | ||
772 | * o shut down adapter hardware | ||
773 | * o release system resources. | ||
774 | * | ||
775 | * This function is called by the router when device is being unregistered or | ||
776 | * when it handles ROUTER_DOWN IOCTL. | ||
777 | */ | ||
778 | static int shutdown(struct wan_device* wandev) | ||
779 | { | ||
780 | sdla_t *card; | ||
781 | int err=0; | ||
782 | |||
783 | /* sanity checks */ | ||
784 | if ((wandev == NULL) || (wandev->private == NULL)){ | ||
785 | return -EFAULT; | ||
786 | } | ||
787 | |||
788 | if (wandev->state == WAN_UNCONFIGURED){ | ||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | card = wandev->private; | ||
793 | |||
794 | if (card->tty_opt){ | ||
795 | if (card->tty_open){ | ||
796 | printk(KERN_INFO | ||
797 | "%s: Shutdown Failed: TTY is still open\n", | ||
798 | card->devname); | ||
799 | return -EBUSY; | ||
800 | } | ||
801 | } | ||
802 | |||
803 | wandev->state = WAN_UNCONFIGURED; | ||
804 | |||
805 | set_bit(PERI_CRIT,(void*)&wandev->critical); | ||
806 | |||
807 | /* In case of piggibacking, make sure that | ||
808 | * we never try to shutdown both devices at the same | ||
809 | * time, because they depend on one another */ | ||
810 | |||
811 | if (card->disable_comm){ | ||
812 | card->disable_comm(card); | ||
813 | } | ||
814 | |||
815 | /* Release Resources */ | ||
816 | release_hw(card); | ||
817 | |||
818 | /* only free the allocated I/O range if not an S514 adapter */ | ||
819 | if (wandev->hw_opt[0] != SDLA_S514 && !card->configured){ | ||
820 | release_region(card->hw.port, card->hw.io_range); | ||
821 | } | ||
822 | |||
823 | if (!card->configured){ | ||
824 | memset(&card->hw, 0, sizeof(sdlahw_t)); | ||
825 | if (card->next){ | ||
826 | memset(&card->next->hw, 0, sizeof(sdlahw_t)); | ||
827 | } | ||
828 | } | ||
829 | |||
830 | |||
831 | clear_bit(PERI_CRIT,(void*)&wandev->critical); | ||
832 | return err; | ||
833 | } | ||
834 | |||
835 | static void release_hw (sdla_t *card) | ||
836 | { | ||
837 | sdla_t *nxt_card; | ||
838 | |||
839 | |||
840 | /* Check if next device exists */ | ||
841 | if (card->next){ | ||
842 | nxt_card = card->next; | ||
843 | /* If next device is down then release resources */ | ||
844 | if (nxt_card->wandev.state == WAN_UNCONFIGURED){ | ||
845 | if (card->wandev.piggyback){ | ||
846 | /* If this device is piggyback then use | ||
847 | * information of the master device | ||
848 | */ | ||
849 | printk(KERN_INFO "%s: Piggyback shutting down\n",card->devname); | ||
850 | sdla_down(&card->next->hw); | ||
851 | free_irq(card->wandev.irq, card->next); | ||
852 | card->configured = 0; | ||
853 | card->next->configured = 0; | ||
854 | card->wandev.piggyback = 0; | ||
855 | }else{ | ||
856 | /* Master device shutting down */ | ||
857 | printk(KERN_INFO "%s: Master shutting down\n",card->devname); | ||
858 | sdla_down(&card->hw); | ||
859 | free_irq(card->wandev.irq, card); | ||
860 | card->configured = 0; | ||
861 | card->next->configured = 0; | ||
862 | } | ||
863 | }else{ | ||
864 | printk(KERN_INFO "%s: Device still running %i\n", | ||
865 | nxt_card->devname,nxt_card->wandev.state); | ||
866 | |||
867 | card->configured = 1; | ||
868 | } | ||
869 | }else{ | ||
870 | printk(KERN_INFO "%s: Master shutting down\n",card->devname); | ||
871 | sdla_down(&card->hw); | ||
872 | free_irq(card->wandev.irq, card); | ||
873 | card->configured = 0; | ||
874 | } | ||
875 | return; | ||
876 | } | ||
877 | |||
878 | |||
879 | /*============================================================================ | ||
880 | * Driver I/O control. | ||
881 | * o verify arguments | ||
882 | * o perform requested action | ||
883 | * | ||
884 | * This function is called when router handles one of the reserved user | ||
885 | * IOCTLs. Note that 'arg' stil points to user address space. | ||
886 | */ | ||
887 | static int ioctl(struct wan_device* wandev, unsigned cmd, unsigned long arg) | ||
888 | { | ||
889 | sdla_t* card; | ||
890 | int err; | ||
891 | |||
892 | /* sanity checks */ | ||
893 | if ((wandev == NULL) || (wandev->private == NULL)) | ||
894 | return -EFAULT; | ||
895 | if (wandev->state == WAN_UNCONFIGURED) | ||
896 | return -ENODEV; | ||
897 | |||
898 | card = wandev->private; | ||
899 | |||
900 | if(card->hw.type != SDLA_S514){ | ||
901 | disable_irq(card->hw.irq); | ||
902 | } | ||
903 | |||
904 | if (test_bit(SEND_CRIT, (void*)&wandev->critical)) { | ||
905 | return -EAGAIN; | ||
906 | } | ||
907 | |||
908 | switch (cmd) { | ||
909 | case WANPIPE_DUMP: | ||
910 | err = ioctl_dump(wandev->private, (void*)arg); | ||
911 | break; | ||
912 | |||
913 | case WANPIPE_EXEC: | ||
914 | err = ioctl_exec(wandev->private, (void*)arg, cmd); | ||
915 | break; | ||
916 | default: | ||
917 | err = -EINVAL; | ||
918 | } | ||
919 | |||
920 | return err; | ||
921 | } | ||
922 | |||
923 | /****** Driver IOCTL Handlers ***********************************************/ | ||
924 | |||
925 | /*============================================================================ | ||
926 | * Dump adapter memory to user buffer. | ||
927 | * o verify request structure | ||
928 | * o copy request structure to kernel data space | ||
929 | * o verify length/offset | ||
930 | * o verify user buffer | ||
931 | * o copy adapter memory image to user buffer | ||
932 | * | ||
933 | * Note: when dumping memory, this routine switches curent dual-port memory | ||
934 | * vector, so care must be taken to avoid racing conditions. | ||
935 | */ | ||
936 | static int ioctl_dump (sdla_t* card, sdla_dump_t* u_dump) | ||
937 | { | ||
938 | sdla_dump_t dump; | ||
939 | unsigned winsize; | ||
940 | unsigned long oldvec; /* DPM window vector */ | ||
941 | unsigned long smp_flags; | ||
942 | int err = 0; | ||
943 | |||
944 | if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t))) | ||
945 | return -EFAULT; | ||
946 | |||
947 | if ((dump.magic != WANPIPE_MAGIC) || | ||
948 | (dump.offset + dump.length > card->hw.memory)) | ||
949 | return -EINVAL; | ||
950 | |||
951 | winsize = card->hw.dpmsize; | ||
952 | |||
953 | if(card->hw.type != SDLA_S514) { | ||
954 | |||
955 | lock_adapter_irq(&card->wandev.lock, &smp_flags); | ||
956 | |||
957 | oldvec = card->hw.vector; | ||
958 | while (dump.length) { | ||
959 | /* current offset */ | ||
960 | unsigned pos = dump.offset % winsize; | ||
961 | /* current vector */ | ||
962 | unsigned long vec = dump.offset - pos; | ||
963 | unsigned len = (dump.length > (winsize - pos)) ? | ||
964 | (winsize - pos) : dump.length; | ||
965 | /* relocate window */ | ||
966 | if (sdla_mapmem(&card->hw, vec) != 0) { | ||
967 | err = -EIO; | ||
968 | break; | ||
969 | } | ||
970 | |||
971 | if(copy_to_user((void *)dump.ptr, | ||
972 | (u8 *)card->hw.dpmbase + pos, len)){ | ||
973 | |||
974 | unlock_adapter_irq(&card->wandev.lock, &smp_flags); | ||
975 | return -EFAULT; | ||
976 | } | ||
977 | |||
978 | dump.length -= len; | ||
979 | dump.offset += len; | ||
980 | dump.ptr = (char*)dump.ptr + len; | ||
981 | } | ||
982 | |||
983 | sdla_mapmem(&card->hw, oldvec);/* restore DPM window position */ | ||
984 | unlock_adapter_irq(&card->wandev.lock, &smp_flags); | ||
985 | |||
986 | }else { | ||
987 | |||
988 | if(copy_to_user((void *)dump.ptr, | ||
989 | (u8 *)card->hw.dpmbase + dump.offset, dump.length)){ | ||
990 | return -EFAULT; | ||
991 | } | ||
992 | } | ||
993 | |||
994 | return err; | ||
995 | } | ||
996 | |||
997 | /*============================================================================ | ||
998 | * Execute adapter firmware command. | ||
999 | * o verify request structure | ||
1000 | * o copy request structure to kernel data space | ||
1001 | * o call protocol-specific 'exec' function | ||
1002 | */ | ||
1003 | static int ioctl_exec (sdla_t* card, sdla_exec_t* u_exec, int cmd) | ||
1004 | { | ||
1005 | sdla_exec_t exec; | ||
1006 | int err=0; | ||
1007 | |||
1008 | if (card->exec == NULL && cmd == WANPIPE_EXEC){ | ||
1009 | return -ENODEV; | ||
1010 | } | ||
1011 | |||
1012 | if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t))) | ||
1013 | return -EFAULT; | ||
1014 | |||
1015 | if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL)) | ||
1016 | return -EINVAL; | ||
1017 | |||
1018 | switch (cmd) { | ||
1019 | case WANPIPE_EXEC: | ||
1020 | err = card->exec(card, exec.cmd, exec.data); | ||
1021 | break; | ||
1022 | } | ||
1023 | return err; | ||
1024 | } | ||
1025 | |||
1026 | /******* Miscellaneous ******************************************************/ | ||
1027 | |||
1028 | /*============================================================================ | ||
1029 | * SDLA Interrupt Service Routine. | ||
1030 | * o acknowledge SDLA hardware interrupt. | ||
1031 | * o call protocol-specific interrupt service routine, if any. | ||
1032 | */ | ||
1033 | STATIC irqreturn_t sdla_isr (int irq, void* dev_id, struct pt_regs *regs) | ||
1034 | { | ||
1035 | #define card ((sdla_t*)dev_id) | ||
1036 | |||
1037 | if(card->hw.type == SDLA_S514) { /* handle interrrupt on S514 */ | ||
1038 | u32 int_status; | ||
1039 | unsigned char CPU_no = card->hw.S514_cpu_no[0]; | ||
1040 | unsigned char card_found_for_IRQ; | ||
1041 | u8 IRQ_count = 0; | ||
1042 | |||
1043 | for(;;) { | ||
1044 | |||
1045 | read_S514_int_stat(&card->hw, &int_status); | ||
1046 | |||
1047 | /* check if the interrupt is for this device */ | ||
1048 | if(!((unsigned char)int_status & | ||
1049 | (IRQ_CPU_A | IRQ_CPU_B))) | ||
1050 | return IRQ_HANDLED; | ||
1051 | |||
1052 | /* if the IRQ is for both CPUs on the same adapter, */ | ||
1053 | /* then alter the interrupt status so as to handle */ | ||
1054 | /* one CPU at a time */ | ||
1055 | if(((unsigned char)int_status & (IRQ_CPU_A | IRQ_CPU_B)) | ||
1056 | == (IRQ_CPU_A | IRQ_CPU_B)) { | ||
1057 | int_status &= (CPU_no == S514_CPU_A) ? | ||
1058 | ~IRQ_CPU_B : ~IRQ_CPU_A; | ||
1059 | } | ||
1060 | |||
1061 | card_found_for_IRQ = 0; | ||
1062 | |||
1063 | /* check to see that the CPU number for this device */ | ||
1064 | /* corresponds to the interrupt status read */ | ||
1065 | switch (CPU_no) { | ||
1066 | case S514_CPU_A: | ||
1067 | if((unsigned char)int_status & | ||
1068 | IRQ_CPU_A) | ||
1069 | card_found_for_IRQ = 1; | ||
1070 | break; | ||
1071 | |||
1072 | case S514_CPU_B: | ||
1073 | if((unsigned char)int_status & | ||
1074 | IRQ_CPU_B) | ||
1075 | card_found_for_IRQ = 1; | ||
1076 | break; | ||
1077 | } | ||
1078 | |||
1079 | /* exit if the interrupt is for another CPU on the */ | ||
1080 | /* same IRQ */ | ||
1081 | if(!card_found_for_IRQ) | ||
1082 | return IRQ_HANDLED; | ||
1083 | |||
1084 | if (!card || | ||
1085 | (card->wandev.state == WAN_UNCONFIGURED && !card->configured)){ | ||
1086 | printk(KERN_INFO | ||
1087 | "Received IRQ %d for CPU #%c\n", | ||
1088 | irq, CPU_no); | ||
1089 | printk(KERN_INFO | ||
1090 | "IRQ for unconfigured adapter\n"); | ||
1091 | S514_intack(&card->hw, int_status); | ||
1092 | return IRQ_HANDLED; | ||
1093 | } | ||
1094 | |||
1095 | if (card->in_isr) { | ||
1096 | printk(KERN_INFO | ||
1097 | "%s: interrupt re-entrancy on IRQ %d\n", | ||
1098 | card->devname, card->wandev.irq); | ||
1099 | S514_intack(&card->hw, int_status); | ||
1100 | return IRQ_HANDLED; | ||
1101 | } | ||
1102 | |||
1103 | spin_lock(&card->wandev.lock); | ||
1104 | if (card->next){ | ||
1105 | spin_lock(&card->next->wandev.lock); | ||
1106 | } | ||
1107 | |||
1108 | S514_intack(&card->hw, int_status); | ||
1109 | if (card->isr) | ||
1110 | card->isr(card); | ||
1111 | |||
1112 | if (card->next){ | ||
1113 | spin_unlock(&card->next->wandev.lock); | ||
1114 | } | ||
1115 | spin_unlock(&card->wandev.lock); | ||
1116 | |||
1117 | /* handle a maximum of two interrupts (one for each */ | ||
1118 | /* CPU on the adapter) before returning */ | ||
1119 | if((++ IRQ_count) == 2) | ||
1120 | return IRQ_HANDLED; | ||
1121 | } | ||
1122 | } | ||
1123 | |||
1124 | else { /* handle interrupt on S508 adapter */ | ||
1125 | |||
1126 | if (!card || ((card->wandev.state == WAN_UNCONFIGURED) && !card->configured)) | ||
1127 | return IRQ_HANDLED; | ||
1128 | |||
1129 | if (card->in_isr) { | ||
1130 | printk(KERN_INFO | ||
1131 | "%s: interrupt re-entrancy on IRQ %d!\n", | ||
1132 | card->devname, card->wandev.irq); | ||
1133 | return IRQ_HANDLED; | ||
1134 | } | ||
1135 | |||
1136 | spin_lock(&card->wandev.lock); | ||
1137 | if (card->next){ | ||
1138 | spin_lock(&card->next->wandev.lock); | ||
1139 | } | ||
1140 | |||
1141 | sdla_intack(&card->hw); | ||
1142 | if (card->isr) | ||
1143 | card->isr(card); | ||
1144 | |||
1145 | if (card->next){ | ||
1146 | spin_unlock(&card->next->wandev.lock); | ||
1147 | } | ||
1148 | spin_unlock(&card->wandev.lock); | ||
1149 | |||
1150 | } | ||
1151 | return IRQ_HANDLED; | ||
1152 | #undef card | ||
1153 | } | ||
1154 | |||
1155 | /*============================================================================ | ||
1156 | * This routine is called by the protocol-specific modules when network | ||
1157 | * interface is being open. The only reason we need this, is because we | ||
1158 | * have to call MOD_INC_USE_COUNT, but cannot include 'module.h' where it's | ||
1159 | * defined more than once into the same kernel module. | ||
1160 | */ | ||
1161 | void wanpipe_open (sdla_t* card) | ||
1162 | { | ||
1163 | ++card->open_cnt; | ||
1164 | } | ||
1165 | |||
1166 | /*============================================================================ | ||
1167 | * This routine is called by the protocol-specific modules when network | ||
1168 | * interface is being closed. The only reason we need this, is because we | ||
1169 | * have to call MOD_DEC_USE_COUNT, but cannot include 'module.h' where it's | ||
1170 | * defined more than once into the same kernel module. | ||
1171 | */ | ||
1172 | void wanpipe_close (sdla_t* card) | ||
1173 | { | ||
1174 | --card->open_cnt; | ||
1175 | } | ||
1176 | |||
1177 | /*============================================================================ | ||
1178 | * Set WAN device state. | ||
1179 | */ | ||
1180 | void wanpipe_set_state (sdla_t* card, int state) | ||
1181 | { | ||
1182 | if (card->wandev.state != state) { | ||
1183 | switch (state) { | ||
1184 | case WAN_CONNECTED: | ||
1185 | printk (KERN_INFO "%s: link connected!\n", | ||
1186 | card->devname); | ||
1187 | break; | ||
1188 | |||
1189 | case WAN_CONNECTING: | ||
1190 | printk (KERN_INFO "%s: link connecting...\n", | ||
1191 | card->devname); | ||
1192 | break; | ||
1193 | |||
1194 | case WAN_DISCONNECTED: | ||
1195 | printk (KERN_INFO "%s: link disconnected!\n", | ||
1196 | card->devname); | ||
1197 | break; | ||
1198 | } | ||
1199 | card->wandev.state = state; | ||
1200 | } | ||
1201 | card->state_tick = jiffies; | ||
1202 | } | ||
1203 | |||
1204 | sdla_t * wanpipe_find_card (char *name) | ||
1205 | { | ||
1206 | int cnt; | ||
1207 | for (cnt = 0; cnt < ncards; ++ cnt) { | ||
1208 | sdla_t* card = &card_array[cnt]; | ||
1209 | if (!strcmp(card->devname,name)) | ||
1210 | return card; | ||
1211 | } | ||
1212 | return NULL; | ||
1213 | } | ||
1214 | |||
1215 | sdla_t * wanpipe_find_card_num (int num) | ||
1216 | { | ||
1217 | if (num < 1 || num > ncards) | ||
1218 | return NULL; | ||
1219 | num--; | ||
1220 | return &card_array[num]; | ||
1221 | } | ||
1222 | |||
1223 | /* | ||
1224 | * @work_pointer: work_struct to be done; | ||
1225 | * should already have PREPARE_WORK() or | ||
1226 | * INIT_WORK() done on it by caller; | ||
1227 | */ | ||
1228 | void wanpipe_queue_work (struct work_struct *work_pointer) | ||
1229 | { | ||
1230 | if (test_and_set_bit(1, (void*)&wanpipe_bh_critical)) | ||
1231 | printk(KERN_INFO "CRITICAL IN QUEUING WORK\n"); | ||
1232 | |||
1233 | queue_work(wanpipe_wq, work_pointer); | ||
1234 | clear_bit(1,(void*)&wanpipe_bh_critical); | ||
1235 | } | ||
1236 | |||
1237 | void wakeup_sk_bh(struct net_device *dev) | ||
1238 | { | ||
1239 | wanpipe_common_t *chan = dev->priv; | ||
1240 | |||
1241 | if (test_bit(0,&chan->common_critical)) | ||
1242 | return; | ||
1243 | |||
1244 | if (chan->sk && chan->tx_timer){ | ||
1245 | chan->tx_timer->expires=jiffies+1; | ||
1246 | add_timer(chan->tx_timer); | ||
1247 | } | ||
1248 | } | ||
1249 | |||
1250 | int change_dev_flags(struct net_device *dev, unsigned flags) | ||
1251 | { | ||
1252 | struct ifreq if_info; | ||
1253 | mm_segment_t fs = get_fs(); | ||
1254 | int err; | ||
1255 | |||
1256 | memset(&if_info, 0, sizeof(if_info)); | ||
1257 | strcpy(if_info.ifr_name, dev->name); | ||
1258 | if_info.ifr_flags = flags; | ||
1259 | |||
1260 | set_fs(get_ds()); /* get user space block */ | ||
1261 | err = devinet_ioctl(SIOCSIFFLAGS, &if_info); | ||
1262 | set_fs(fs); | ||
1263 | |||
1264 | return err; | ||
1265 | } | ||
1266 | |||
1267 | unsigned long get_ip_address(struct net_device *dev, int option) | ||
1268 | { | ||
1269 | |||
1270 | struct in_ifaddr *ifaddr; | ||
1271 | struct in_device *in_dev; | ||
1272 | unsigned long addr = 0; | ||
1273 | |||
1274 | rcu_read_lock(); | ||
1275 | if ((in_dev = __in_dev_get_rcu(dev)) == NULL){ | ||
1276 | goto out; | ||
1277 | } | ||
1278 | |||
1279 | if ((ifaddr = in_dev->ifa_list)== NULL ){ | ||
1280 | goto out; | ||
1281 | } | ||
1282 | |||
1283 | switch (option){ | ||
1284 | |||
1285 | case WAN_LOCAL_IP: | ||
1286 | addr = ifaddr->ifa_local; | ||
1287 | break; | ||
1288 | |||
1289 | case WAN_POINTOPOINT_IP: | ||
1290 | addr = ifaddr->ifa_address; | ||
1291 | break; | ||
1292 | |||
1293 | case WAN_NETMASK_IP: | ||
1294 | addr = ifaddr->ifa_mask; | ||
1295 | break; | ||
1296 | |||
1297 | case WAN_BROADCAST_IP: | ||
1298 | addr = ifaddr->ifa_broadcast; | ||
1299 | break; | ||
1300 | default: | ||
1301 | break; | ||
1302 | } | ||
1303 | |||
1304 | out: | ||
1305 | rcu_read_unlock(); | ||
1306 | return addr; | ||
1307 | } | ||
1308 | |||
1309 | void add_gateway(sdla_t *card, struct net_device *dev) | ||
1310 | { | ||
1311 | mm_segment_t oldfs; | ||
1312 | struct rtentry route; | ||
1313 | int res; | ||
1314 | |||
1315 | memset((char*)&route,0,sizeof(struct rtentry)); | ||
1316 | |||
1317 | ((struct sockaddr_in *) | ||
1318 | &(route.rt_dst))->sin_addr.s_addr = 0; | ||
1319 | ((struct sockaddr_in *) | ||
1320 | &(route.rt_dst))->sin_family = AF_INET; | ||
1321 | |||
1322 | ((struct sockaddr_in *) | ||
1323 | &(route.rt_genmask))->sin_addr.s_addr = 0; | ||
1324 | ((struct sockaddr_in *) | ||
1325 | &(route.rt_genmask)) ->sin_family = AF_INET; | ||
1326 | |||
1327 | |||
1328 | route.rt_flags = 0; | ||
1329 | route.rt_dev = dev->name; | ||
1330 | |||
1331 | oldfs = get_fs(); | ||
1332 | set_fs(get_ds()); | ||
1333 | res = ip_rt_ioctl(SIOCADDRT,&route); | ||
1334 | set_fs(oldfs); | ||
1335 | |||
1336 | if (res == 0){ | ||
1337 | printk(KERN_INFO "%s: Gateway added for %s\n", | ||
1338 | card->devname,dev->name); | ||
1339 | } | ||
1340 | |||
1341 | return; | ||
1342 | } | ||
1343 | |||
1344 | MODULE_LICENSE("GPL"); | ||
1345 | |||
1346 | /****** End *********************************************************/ | ||
diff --git a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c deleted file mode 100644 index 812a1183c502..000000000000 --- a/drivers/net/wan/wanpipe_multppp.c +++ /dev/null | |||
@@ -1,2358 +0,0 @@ | |||
1 | /***************************************************************************** | ||
2 | * wanpipe_multppp.c Multi-Port PPP driver module. | ||
3 | * | ||
4 | * Authors: Nenad Corbic <ncorbic@sangoma.com> | ||
5 | * | ||
6 | * Copyright: (c) 1995-2001 Sangoma Technologies Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * ============================================================================ | ||
13 | * Dec 15 2000 Updated for 2.4.X kernel | ||
14 | * Nov 15 2000 Fixed the SyncPPP support for kernels 2.2.16 and higher. | ||
15 | * The pppstruct has changed. | ||
16 | * Jul 13 2000 Using the kernel Syncppp module on top of RAW Wanpipe CHDLC | ||
17 | * module. | ||
18 | *****************************************************************************/ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/kernel.h> /* printk(), and other useful stuff */ | ||
22 | #include <linux/stddef.h> /* offsetof(), etc. */ | ||
23 | #include <linux/errno.h> /* return codes */ | ||
24 | #include <linux/string.h> /* inline memset(), etc. */ | ||
25 | #include <linux/slab.h> /* kmalloc(), kfree() */ | ||
26 | #include <linux/wanrouter.h> /* WAN router definitions */ | ||
27 | #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ | ||
28 | #include <linux/if_arp.h> /* ARPHRD_* defines */ | ||
29 | #include <linux/jiffies.h> /* time_after() macro */ | ||
30 | |||
31 | #include <linux/in.h> /* sockaddr_in */ | ||
32 | #include <linux/inet.h> | ||
33 | #include <linux/if.h> | ||
34 | #include <asm/byteorder.h> /* htons(), etc. */ | ||
35 | #include <linux/sdlapci.h> | ||
36 | #include <asm/io.h> | ||
37 | |||
38 | #include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */ | ||
39 | #include <linux/sdla_asy.h> /* CHDLC (async) API definitions */ | ||
40 | |||
41 | #include <linux/if_wanpipe_common.h> /* Socket Driver common area */ | ||
42 | #include <linux/if_wanpipe.h> | ||
43 | |||
44 | |||
45 | #include <linux/inetdevice.h> | ||
46 | #include <asm/uaccess.h> | ||
47 | |||
48 | #include <net/syncppp.h> | ||
49 | |||
50 | |||
51 | /****** Defines & Macros ****************************************************/ | ||
52 | |||
53 | #ifdef _DEBUG_ | ||
54 | #define STATIC | ||
55 | #else | ||
56 | #define STATIC static | ||
57 | #endif | ||
58 | |||
59 | /* reasons for enabling the timer interrupt on the adapter */ | ||
60 | #define TMR_INT_ENABLED_UDP 0x01 | ||
61 | #define TMR_INT_ENABLED_UPDATE 0x02 | ||
62 | #define TMR_INT_ENABLED_CONFIG 0x04 | ||
63 | |||
64 | #define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */ | ||
65 | #define CHDLC_HDR_LEN 1 | ||
66 | |||
67 | #define IFF_POINTTOPOINT 0x10 | ||
68 | |||
69 | #define CHDLC_API 0x01 | ||
70 | |||
71 | #define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" ) | ||
72 | #define MAX_BH_BUFF 10 | ||
73 | |||
74 | #define CRC_LENGTH 2 | ||
75 | #define PPP_HEADER_LEN 4 | ||
76 | |||
77 | /******Data Structures*****************************************************/ | ||
78 | |||
79 | /* This structure is placed in the private data area of the device structure. | ||
80 | * The card structure used to occupy the private area but now the following | ||
81 | * structure will incorporate the card structure along with CHDLC specific data | ||
82 | */ | ||
83 | |||
84 | typedef struct chdlc_private_area | ||
85 | { | ||
86 | void *if_ptr; /* General Pointer used by SPPP */ | ||
87 | wanpipe_common_t common; | ||
88 | sdla_t *card; | ||
89 | int TracingEnabled; /* For enabling Tracing */ | ||
90 | unsigned long curr_trace_addr; /* Used for Tracing */ | ||
91 | unsigned long start_trace_addr; | ||
92 | unsigned long end_trace_addr; | ||
93 | unsigned long base_addr_trace_buffer; | ||
94 | unsigned long end_addr_trace_buffer; | ||
95 | unsigned short number_trace_elements; | ||
96 | unsigned available_buffer_space; | ||
97 | unsigned long router_start_time; | ||
98 | unsigned char route_status; | ||
99 | unsigned char route_removed; | ||
100 | unsigned long tick_counter; /* For 5s timeout counter */ | ||
101 | unsigned long router_up_time; | ||
102 | u32 IP_address; /* IP addressing */ | ||
103 | u32 IP_netmask; | ||
104 | unsigned char mc; /* Mulitcast support on/off */ | ||
105 | unsigned short udp_pkt_lgth; /* udp packet processing */ | ||
106 | char udp_pkt_src; | ||
107 | char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; | ||
108 | unsigned short timer_int_enabled; | ||
109 | char update_comms_stats; /* updating comms stats */ | ||
110 | |||
111 | //FIXME: add driver stats as per frame relay! | ||
112 | |||
113 | } chdlc_private_area_t; | ||
114 | |||
115 | /* Route Status options */ | ||
116 | #define NO_ROUTE 0x00 | ||
117 | #define ADD_ROUTE 0x01 | ||
118 | #define ROUTE_ADDED 0x02 | ||
119 | #define REMOVE_ROUTE 0x03 | ||
120 | |||
121 | |||
122 | /* variable for keeping track of enabling/disabling FT1 monitor status */ | ||
123 | static int rCount = 0; | ||
124 | |||
125 | /* variable for tracking how many interfaces to open for WANPIPE on the | ||
126 | two ports */ | ||
127 | |||
128 | extern void disable_irq(unsigned int); | ||
129 | extern void enable_irq(unsigned int); | ||
130 | |||
131 | /****** Function Prototypes *************************************************/ | ||
132 | /* WAN link driver entry points. These are called by the WAN router module. */ | ||
133 | static int update(struct wan_device* wandev); | ||
134 | static int new_if(struct wan_device* wandev, struct net_device* dev, | ||
135 | wanif_conf_t* conf); | ||
136 | static int del_if(struct wan_device* wandev, struct net_device* dev); | ||
137 | |||
138 | /* Network device interface */ | ||
139 | static int if_init(struct net_device* dev); | ||
140 | static int if_open(struct net_device* dev); | ||
141 | static int if_close(struct net_device* dev); | ||
142 | static int if_send(struct sk_buff* skb, struct net_device* dev); | ||
143 | static struct net_device_stats* if_stats(struct net_device* dev); | ||
144 | |||
145 | static void if_tx_timeout(struct net_device *dev); | ||
146 | |||
147 | /* CHDLC Firmware interface functions */ | ||
148 | static int chdlc_configure (sdla_t* card, void* data); | ||
149 | static int chdlc_comm_enable (sdla_t* card); | ||
150 | static int chdlc_comm_disable (sdla_t* card); | ||
151 | static int chdlc_read_version (sdla_t* card, char* str); | ||
152 | static int chdlc_set_intr_mode (sdla_t* card, unsigned mode); | ||
153 | static int chdlc_send (sdla_t* card, void* data, unsigned len); | ||
154 | static int chdlc_read_comm_err_stats (sdla_t* card); | ||
155 | static int chdlc_read_op_stats (sdla_t* card); | ||
156 | static int config_chdlc (sdla_t *card); | ||
157 | |||
158 | |||
159 | /* Miscellaneous CHDLC Functions */ | ||
160 | static int set_chdlc_config (sdla_t* card); | ||
161 | static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev); | ||
162 | static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb); | ||
163 | static int process_chdlc_exception(sdla_t *card); | ||
164 | static int process_global_exception(sdla_t *card); | ||
165 | static int update_comms_stats(sdla_t* card, | ||
166 | chdlc_private_area_t* chdlc_priv_area); | ||
167 | static void port_set_state (sdla_t *card, int); | ||
168 | |||
169 | /* Interrupt handlers */ | ||
170 | static void wsppp_isr (sdla_t* card); | ||
171 | static void rx_intr (sdla_t* card); | ||
172 | static void timer_intr(sdla_t *); | ||
173 | |||
174 | /* Miscellaneous functions */ | ||
175 | static int reply_udp( unsigned char *data, unsigned int mbox_len ); | ||
176 | static int intr_test( sdla_t* card); | ||
177 | static int udp_pkt_type( struct sk_buff *skb , sdla_t* card); | ||
178 | static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, | ||
179 | struct sk_buff *skb, struct net_device* dev, | ||
180 | chdlc_private_area_t* chdlc_priv_area); | ||
181 | static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev, | ||
182 | chdlc_private_area_t* chdlc_priv_area); | ||
183 | static unsigned short calc_checksum (char *, int); | ||
184 | static void s508_lock (sdla_t *card, unsigned long *smp_flags); | ||
185 | static void s508_unlock (sdla_t *card, unsigned long *smp_flags); | ||
186 | static void send_ppp_term_request(struct net_device *dev); | ||
187 | |||
188 | |||
189 | static int Intr_test_counter; | ||
190 | /****** Public Functions ****************************************************/ | ||
191 | |||
192 | /*============================================================================ | ||
193 | * Cisco HDLC protocol initialization routine. | ||
194 | * | ||
195 | * This routine is called by the main WANPIPE module during setup. At this | ||
196 | * point adapter is completely initialized and firmware is running. | ||
197 | * o read firmware version (to make sure it's alive) | ||
198 | * o configure adapter | ||
199 | * o initialize protocol-specific fields of the adapter data space. | ||
200 | * | ||
201 | * Return: 0 o.k. | ||
202 | * < 0 failure. | ||
203 | */ | ||
204 | int wsppp_init (sdla_t* card, wandev_conf_t* conf) | ||
205 | { | ||
206 | unsigned char port_num; | ||
207 | int err; | ||
208 | unsigned long max_permitted_baud = 0; | ||
209 | SHARED_MEMORY_INFO_STRUCT *flags; | ||
210 | |||
211 | union | ||
212 | { | ||
213 | char str[80]; | ||
214 | } u; | ||
215 | volatile CHDLC_MAILBOX_STRUCT* mb; | ||
216 | CHDLC_MAILBOX_STRUCT* mb1; | ||
217 | unsigned long timeout; | ||
218 | |||
219 | /* Verify configuration ID */ | ||
220 | if (conf->config_id != WANCONFIG_MPPP) { | ||
221 | printk(KERN_INFO "%s: invalid configuration ID %u!\n", | ||
222 | card->devname, conf->config_id); | ||
223 | return -EINVAL; | ||
224 | } | ||
225 | |||
226 | /* Find out which Port to use */ | ||
227 | if ((conf->comm_port == WANOPT_PRI) || (conf->comm_port == WANOPT_SEC)){ | ||
228 | if (card->next){ | ||
229 | |||
230 | if (conf->comm_port != card->next->u.c.comm_port){ | ||
231 | card->u.c.comm_port = conf->comm_port; | ||
232 | }else{ | ||
233 | printk(KERN_ERR "%s: ERROR - %s port used!\n", | ||
234 | card->wandev.name, PORT(conf->comm_port)); | ||
235 | return -EINVAL; | ||
236 | } | ||
237 | }else{ | ||
238 | card->u.c.comm_port = conf->comm_port; | ||
239 | } | ||
240 | }else{ | ||
241 | printk(KERN_ERR "%s: ERROR - Invalid Port Selected!\n", | ||
242 | card->wandev.name); | ||
243 | return -EINVAL; | ||
244 | } | ||
245 | |||
246 | |||
247 | /* Initialize protocol-specific fields */ | ||
248 | if(card->hw.type != SDLA_S514){ | ||
249 | |||
250 | if (card->u.c.comm_port == WANOPT_PRI){ | ||
251 | card->mbox = (void *) card->hw.dpmbase; | ||
252 | }else{ | ||
253 | card->mbox = (void *) card->hw.dpmbase + | ||
254 | SEC_BASE_ADDR_MB_STRUCT - PRI_BASE_ADDR_MB_STRUCT; | ||
255 | } | ||
256 | }else{ | ||
257 | /* for a S514 adapter, set a pointer to the actual mailbox in the */ | ||
258 | /* allocated virtual memory area */ | ||
259 | if (card->u.c.comm_port == WANOPT_PRI){ | ||
260 | card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT; | ||
261 | }else{ | ||
262 | card->mbox = (void *) card->hw.dpmbase + SEC_BASE_ADDR_MB_STRUCT; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | mb = mb1 = card->mbox; | ||
267 | |||
268 | if (!card->configured){ | ||
269 | |||
270 | /* The board will place an 'I' in the return code to indicate that it is | ||
271 | ready to accept commands. We expect this to be completed in less | ||
272 | than 1 second. */ | ||
273 | |||
274 | timeout = jiffies + 1 * HZ; | ||
275 | while (mb->return_code != 'I') /* Wait 1s for board to initialize */ | ||
276 | if (time_after(jiffies, timeout)) break; | ||
277 | |||
278 | if (mb->return_code != 'I') { | ||
279 | printk(KERN_INFO | ||
280 | "%s: Initialization not completed by adapter\n", | ||
281 | card->devname); | ||
282 | printk(KERN_INFO "Please contact Sangoma representative.\n"); | ||
283 | return -EIO; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | /* Read firmware version. Note that when adapter initializes, it | ||
288 | * clears the mailbox, so it may appear that the first command was | ||
289 | * executed successfully when in fact it was merely erased. To work | ||
290 | * around this, we execute the first command twice. | ||
291 | */ | ||
292 | |||
293 | if (chdlc_read_version(card, u.str)) | ||
294 | return -EIO; | ||
295 | |||
296 | printk(KERN_INFO "%s: Running Raw CHDLC firmware v%s\n" | ||
297 | "%s: for Multi-Port PPP protocol.\n", | ||
298 | card->devname,u.str,card->devname); | ||
299 | |||
300 | card->isr = &wsppp_isr; | ||
301 | card->poll = NULL; | ||
302 | card->exec = NULL; | ||
303 | card->wandev.update = &update; | ||
304 | card->wandev.new_if = &new_if; | ||
305 | card->wandev.del_if = &del_if; | ||
306 | card->wandev.udp_port = conf->udp_port; | ||
307 | |||
308 | card->wandev.new_if_cnt = 0; | ||
309 | |||
310 | /* reset the number of times the 'update()' proc has been called */ | ||
311 | card->u.c.update_call_count = 0; | ||
312 | |||
313 | card->wandev.ttl = conf->ttl; | ||
314 | card->wandev.interface = conf->interface; | ||
315 | |||
316 | if ((card->u.c.comm_port == WANOPT_SEC && conf->interface == WANOPT_V35)&& | ||
317 | card->hw.type != SDLA_S514){ | ||
318 | printk(KERN_INFO "%s: ERROR - V35 Interface not supported on S508 %s port \n", | ||
319 | card->devname, PORT(card->u.c.comm_port)); | ||
320 | return -EIO; | ||
321 | } | ||
322 | |||
323 | |||
324 | card->wandev.clocking = conf->clocking; | ||
325 | |||
326 | port_num = card->u.c.comm_port; | ||
327 | |||
328 | /* Setup Port Bps */ | ||
329 | |||
330 | if(card->wandev.clocking) { | ||
331 | if((port_num == WANOPT_PRI) || card->u.c.receive_only) { | ||
332 | /* For Primary Port 0 */ | ||
333 | max_permitted_baud = | ||
334 | (card->hw.type == SDLA_S514) ? | ||
335 | PRI_MAX_BAUD_RATE_S514 : | ||
336 | PRI_MAX_BAUD_RATE_S508; | ||
337 | } | ||
338 | else if(port_num == WANOPT_SEC) { | ||
339 | /* For Secondary Port 1 */ | ||
340 | max_permitted_baud = | ||
341 | (card->hw.type == SDLA_S514) ? | ||
342 | SEC_MAX_BAUD_RATE_S514 : | ||
343 | SEC_MAX_BAUD_RATE_S508; | ||
344 | } | ||
345 | |||
346 | if(conf->bps > max_permitted_baud) { | ||
347 | conf->bps = max_permitted_baud; | ||
348 | printk(KERN_INFO "%s: Baud too high!\n", | ||
349 | card->wandev.name); | ||
350 | printk(KERN_INFO "%s: Baud rate set to %lu bps\n", | ||
351 | card->wandev.name, max_permitted_baud); | ||
352 | } | ||
353 | |||
354 | card->wandev.bps = conf->bps; | ||
355 | }else{ | ||
356 | card->wandev.bps = 0; | ||
357 | } | ||
358 | |||
359 | /* Setup the Port MTU */ | ||
360 | if((port_num == WANOPT_PRI) || card->u.c.receive_only) { | ||
361 | |||
362 | /* For Primary Port 0 */ | ||
363 | card->wandev.mtu = | ||
364 | (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ? | ||
365 | min_t(unsigned int, conf->mtu, PRI_MAX_NO_DATA_BYTES_IN_FRAME) : | ||
366 | CHDLC_DFLT_DATA_LEN; | ||
367 | } else if(port_num == WANOPT_SEC) { | ||
368 | /* For Secondary Port 1 */ | ||
369 | card->wandev.mtu = | ||
370 | (conf->mtu >= MIN_LGTH_CHDLC_DATA_CFG) ? | ||
371 | min_t(unsigned int, conf->mtu, SEC_MAX_NO_DATA_BYTES_IN_FRAME) : | ||
372 | CHDLC_DFLT_DATA_LEN; | ||
373 | } | ||
374 | |||
375 | /* Add on a PPP Header */ | ||
376 | card->wandev.mtu += PPP_HEADER_LEN; | ||
377 | |||
378 | /* Set up the interrupt status area */ | ||
379 | /* Read the CHDLC Configuration and obtain: | ||
380 | * Ptr to shared memory infor struct | ||
381 | * Use this pointer to calculate the value of card->u.c.flags ! | ||
382 | */ | ||
383 | mb1->buffer_length = 0; | ||
384 | mb1->command = READ_CHDLC_CONFIGURATION; | ||
385 | err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT; | ||
386 | if(err != COMMAND_OK) { | ||
387 | clear_bit(1, (void*)&card->wandev.critical); | ||
388 | |||
389 | if(card->hw.type != SDLA_S514) | ||
390 | enable_irq(card->hw.irq); | ||
391 | |||
392 | chdlc_error(card, err, mb1); | ||
393 | return -EIO; | ||
394 | } | ||
395 | |||
396 | if(card->hw.type == SDLA_S514){ | ||
397 | card->u.c.flags = (void *)(card->hw.dpmbase + | ||
398 | (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)-> | ||
399 | ptr_shared_mem_info_struct)); | ||
400 | }else{ | ||
401 | card->u.c.flags = (void *)(card->hw.dpmbase + | ||
402 | (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)-> | ||
403 | ptr_shared_mem_info_struct % SDLA_WINDOWSIZE)); | ||
404 | } | ||
405 | |||
406 | flags = card->u.c.flags; | ||
407 | |||
408 | /* This is for the ports link state */ | ||
409 | card->wandev.state = WAN_DUALPORT; | ||
410 | card->u.c.state = WAN_DISCONNECTED; | ||
411 | |||
412 | |||
413 | if (!card->wandev.piggyback){ | ||
414 | err = intr_test(card); | ||
415 | |||
416 | if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { | ||
417 | printk(KERN_ERR "%s: Interrupt test failed (%i)\n", | ||
418 | card->devname, Intr_test_counter); | ||
419 | printk(KERN_ERR "%s: Please choose another interrupt\n", | ||
420 | card->devname); | ||
421 | return -EIO; | ||
422 | } | ||
423 | |||
424 | printk(KERN_INFO "%s: Interrupt test passed (%i)\n", | ||
425 | card->devname, Intr_test_counter); | ||
426 | } | ||
427 | |||
428 | |||
429 | if (chdlc_set_intr_mode(card, APP_INT_ON_TIMER)){ | ||
430 | printk (KERN_INFO "%s: Failed to set interrupt triggers!\n", | ||
431 | card->devname); | ||
432 | return -EIO; | ||
433 | } | ||
434 | |||
435 | /* Mask the Timer interrupt */ | ||
436 | flags->interrupt_info_struct.interrupt_permission &= | ||
437 | ~APP_INT_ON_TIMER; | ||
438 | |||
439 | printk(KERN_INFO "\n"); | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | /******* WAN Device Driver Entry Points *************************************/ | ||
445 | |||
446 | /*============================================================================ | ||
447 | * Update device status & statistics | ||
448 | * This procedure is called when updating the PROC file system and returns | ||
449 | * various communications statistics. These statistics are accumulated from 3 | ||
450 | * different locations: | ||
451 | * 1) The 'if_stats' recorded for the device. | ||
452 | * 2) Communication error statistics on the adapter. | ||
453 | * 3) CHDLC operational statistics on the adapter. | ||
454 | * The board level statistics are read during a timer interrupt. Note that we | ||
455 | * read the error and operational statistics during consecitive timer ticks so | ||
456 | * as to minimize the time that we are inside the interrupt handler. | ||
457 | * | ||
458 | */ | ||
459 | static int update(struct wan_device* wandev) | ||
460 | { | ||
461 | sdla_t* card = wandev->private; | ||
462 | struct net_device* dev; | ||
463 | volatile chdlc_private_area_t* chdlc_priv_area; | ||
464 | SHARED_MEMORY_INFO_STRUCT *flags; | ||
465 | unsigned long timeout; | ||
466 | |||
467 | /* sanity checks */ | ||
468 | if((wandev == NULL) || (wandev->private == NULL)) | ||
469 | return -EFAULT; | ||
470 | |||
471 | if(wandev->state == WAN_UNCONFIGURED) | ||
472 | return -ENODEV; | ||
473 | |||
474 | /* more sanity checks */ | ||
475 | if(!card->u.c.flags) | ||
476 | return -ENODEV; | ||
477 | |||
478 | if((dev=card->wandev.dev) == NULL) | ||
479 | return -ENODEV; | ||
480 | |||
481 | if((chdlc_priv_area=dev->priv) == NULL) | ||
482 | return -ENODEV; | ||
483 | |||
484 | flags = card->u.c.flags; | ||
485 | |||
486 | if(chdlc_priv_area->update_comms_stats){ | ||
487 | return -EAGAIN; | ||
488 | } | ||
489 | |||
490 | /* we will need 2 timer interrupts to complete the */ | ||
491 | /* reading of the statistics */ | ||
492 | chdlc_priv_area->update_comms_stats = 2; | ||
493 | flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER; | ||
494 | chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UPDATE; | ||
495 | |||
496 | /* wait a maximum of 1 second for the statistics to be updated */ | ||
497 | timeout = jiffies + 1 * HZ; | ||
498 | for(;;) { | ||
499 | if(chdlc_priv_area->update_comms_stats == 0) | ||
500 | break; | ||
501 | if (time_after(jiffies, timeout)){ | ||
502 | chdlc_priv_area->update_comms_stats = 0; | ||
503 | chdlc_priv_area->timer_int_enabled &= | ||
504 | ~TMR_INT_ENABLED_UPDATE; | ||
505 | return -EAGAIN; | ||
506 | } | ||
507 | } | ||
508 | |||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | |||
513 | /*============================================================================ | ||
514 | * Create new logical channel. | ||
515 | * This routine is called by the router when ROUTER_IFNEW IOCTL is being | ||
516 | * handled. | ||
517 | * o parse media- and hardware-specific configuration | ||
518 | * o make sure that a new channel can be created | ||
519 | * o allocate resources, if necessary | ||
520 | * o prepare network device structure for registaration. | ||
521 | * | ||
522 | * Return: 0 o.k. | ||
523 | * < 0 failure (channel will not be created) | ||
524 | */ | ||
525 | static int new_if(struct wan_device* wandev, struct net_device* pdev, | ||
526 | wanif_conf_t* conf) | ||
527 | { | ||
528 | |||
529 | struct ppp_device *pppdev = (struct ppp_device *)pdev; | ||
530 | struct net_device *dev = NULL; | ||
531 | struct sppp *sp; | ||
532 | sdla_t* card = wandev->private; | ||
533 | chdlc_private_area_t* chdlc_priv_area; | ||
534 | |||
535 | if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) { | ||
536 | printk(KERN_INFO "%s: invalid interface name!\n", | ||
537 | card->devname); | ||
538 | return -EINVAL; | ||
539 | } | ||
540 | |||
541 | /* allocate and initialize private data */ | ||
542 | chdlc_priv_area = kmalloc(sizeof(chdlc_private_area_t), GFP_KERNEL); | ||
543 | |||
544 | if(chdlc_priv_area == NULL) | ||
545 | return -ENOMEM; | ||
546 | |||
547 | memset(chdlc_priv_area, 0, sizeof(chdlc_private_area_t)); | ||
548 | |||
549 | chdlc_priv_area->card = card; | ||
550 | |||
551 | /* initialize data */ | ||
552 | strcpy(card->u.c.if_name, conf->name); | ||
553 | |||
554 | if(card->wandev.new_if_cnt > 0) { | ||
555 | kfree(chdlc_priv_area); | ||
556 | return -EEXIST; | ||
557 | } | ||
558 | |||
559 | card->wandev.new_if_cnt++; | ||
560 | |||
561 | chdlc_priv_area->TracingEnabled = 0; | ||
562 | |||
563 | //We don't need this any more | ||
564 | chdlc_priv_area->route_status = NO_ROUTE; | ||
565 | chdlc_priv_area->route_removed = 0; | ||
566 | |||
567 | printk(KERN_INFO "%s: Firmware running in HDLC STREAMING Mode\n", | ||
568 | wandev->name); | ||
569 | |||
570 | /* Setup wanpipe as a router (WANPIPE) or as an API */ | ||
571 | if( strcmp(conf->usedby, "WANPIPE") == 0) { | ||
572 | printk(KERN_INFO "%s: Driver running in WANPIPE mode!\n", | ||
573 | wandev->name); | ||
574 | card->u.c.usedby = WANPIPE; | ||
575 | } else { | ||
576 | printk(KERN_INFO | ||
577 | "%s: API Mode is not supported for SyncPPP!\n", | ||
578 | wandev->name); | ||
579 | kfree(chdlc_priv_area); | ||
580 | return -EINVAL; | ||
581 | } | ||
582 | |||
583 | /* Get Multicast Information */ | ||
584 | chdlc_priv_area->mc = conf->mc; | ||
585 | |||
586 | |||
587 | chdlc_priv_area->if_ptr = pppdev; | ||
588 | |||
589 | /* prepare network device data space for registration */ | ||
590 | |||
591 | strcpy(dev->name,card->u.c.if_name); | ||
592 | |||
593 | /* Attach PPP protocol layer to pppdev | ||
594 | * The sppp_attach() will initilize the dev structure | ||
595 | * and setup ppp layer protocols. | ||
596 | * All we have to do is to bind in: | ||
597 | * if_open(), if_close(), if_send() and get_stats() functions. | ||
598 | */ | ||
599 | sppp_attach(pppdev); | ||
600 | dev = pppdev->dev; | ||
601 | sp = &pppdev->sppp; | ||
602 | |||
603 | /* Enable PPP Debugging */ | ||
604 | // FIXME Fix this up somehow | ||
605 | //sp->pp_flags |= PP_DEBUG; | ||
606 | sp->pp_flags &= ~PP_CISCO; | ||
607 | |||
608 | dev->init = &if_init; | ||
609 | dev->priv = chdlc_priv_area; | ||
610 | |||
611 | return 0; | ||
612 | } | ||
613 | |||
614 | |||
615 | |||
616 | |||
617 | /*============================================================================ | ||
618 | * Delete logical channel. | ||
619 | */ | ||
620 | static int del_if(struct wan_device* wandev, struct net_device* dev) | ||
621 | { | ||
622 | chdlc_private_area_t *chdlc_priv_area = dev->priv; | ||
623 | sdla_t *card = chdlc_priv_area->card; | ||
624 | unsigned long smp_lock; | ||
625 | |||
626 | /* Detach the PPP layer */ | ||
627 | printk(KERN_INFO "%s: Detaching SyncPPP Module from %s\n", | ||
628 | wandev->name,dev->name); | ||
629 | |||
630 | lock_adapter_irq(&wandev->lock,&smp_lock); | ||
631 | |||
632 | sppp_detach(dev); | ||
633 | chdlc_priv_area->if_ptr=NULL; | ||
634 | |||
635 | chdlc_set_intr_mode(card, 0); | ||
636 | if (card->u.c.comm_enabled) | ||
637 | chdlc_comm_disable(card); | ||
638 | unlock_adapter_irq(&wandev->lock,&smp_lock); | ||
639 | |||
640 | port_set_state(card, WAN_DISCONNECTED); | ||
641 | |||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | |||
646 | /****** Network Device Interface ********************************************/ | ||
647 | |||
648 | /*============================================================================ | ||
649 | * Initialize Linux network interface. | ||
650 | * | ||
651 | * This routine is called only once for each interface, during Linux network | ||
652 | * interface registration. Returning anything but zero will fail interface | ||
653 | * registration. | ||
654 | */ | ||
655 | static int if_init(struct net_device* dev) | ||
656 | { | ||
657 | chdlc_private_area_t* chdlc_priv_area = dev->priv; | ||
658 | sdla_t* card = chdlc_priv_area->card; | ||
659 | struct wan_device* wandev = &card->wandev; | ||
660 | |||
661 | /* NOTE: Most of the dev initialization was | ||
662 | * done in sppp_attach(), called by new_if() | ||
663 | * function. All we have to do here is | ||
664 | * to link four major routines below. | ||
665 | */ | ||
666 | |||
667 | /* Initialize device driver entry points */ | ||
668 | dev->open = &if_open; | ||
669 | dev->stop = &if_close; | ||
670 | dev->hard_start_xmit = &if_send; | ||
671 | dev->get_stats = &if_stats; | ||
672 | dev->tx_timeout = &if_tx_timeout; | ||
673 | dev->watchdog_timeo = TX_TIMEOUT; | ||
674 | |||
675 | |||
676 | /* Initialize hardware parameters */ | ||
677 | dev->irq = wandev->irq; | ||
678 | dev->dma = wandev->dma; | ||
679 | dev->base_addr = wandev->ioport; | ||
680 | dev->mem_start = wandev->maddr; | ||
681 | dev->mem_end = wandev->maddr + wandev->msize - 1; | ||
682 | |||
683 | /* Set transmit buffer queue length | ||
684 | * If we over fill this queue the packets will | ||
685 | * be droped by the kernel. | ||
686 | * sppp_attach() sets this to 10, but | ||
687 | * 100 will give us more room at low speeds. | ||
688 | */ | ||
689 | dev->tx_queue_len = 100; | ||
690 | |||
691 | return 0; | ||
692 | } | ||
693 | |||
694 | |||
695 | /*============================================================================ | ||
696 | * Handle transmit timeout event from netif watchdog | ||
697 | */ | ||
698 | static void if_tx_timeout(struct net_device *dev) | ||
699 | { | ||
700 | chdlc_private_area_t* chan = dev->priv; | ||
701 | sdla_t *card = chan->card; | ||
702 | |||
703 | /* If our device stays busy for at least 5 seconds then we will | ||
704 | * kick start the device by making dev->tbusy = 0. We expect | ||
705 | * that our device never stays busy more than 5 seconds. So this | ||
706 | * is only used as a last resort. | ||
707 | */ | ||
708 | |||
709 | ++card->wandev.stats.collisions; | ||
710 | |||
711 | printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); | ||
712 | netif_wake_queue (dev); | ||
713 | } | ||
714 | |||
715 | |||
716 | /*============================================================================ | ||
717 | * Open network interface. | ||
718 | * o enable communications and interrupts. | ||
719 | * o prevent module from unloading by incrementing use count | ||
720 | * | ||
721 | * Return 0 if O.k. or errno. | ||
722 | */ | ||
723 | static int if_open(struct net_device* dev) | ||
724 | { | ||
725 | chdlc_private_area_t* chdlc_priv_area = dev->priv; | ||
726 | sdla_t* card = chdlc_priv_area->card; | ||
727 | struct timeval tv; | ||
728 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
729 | |||
730 | /* Only one open per interface is allowed */ | ||
731 | if (netif_running(dev)) | ||
732 | return -EBUSY; | ||
733 | |||
734 | /* Start PPP Layer */ | ||
735 | if (sppp_open(dev)){ | ||
736 | return -EIO; | ||
737 | } | ||
738 | |||
739 | do_gettimeofday(&tv); | ||
740 | chdlc_priv_area->router_start_time = tv.tv_sec; | ||
741 | |||
742 | netif_start_queue(dev); | ||
743 | |||
744 | wanpipe_open(card); | ||
745 | |||
746 | chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG; | ||
747 | flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER; | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | /*============================================================================ | ||
752 | * Close network interface. | ||
753 | * o if this is the last close, then disable communications and interrupts. | ||
754 | * o reset flags. | ||
755 | */ | ||
756 | static int if_close(struct net_device* dev) | ||
757 | { | ||
758 | chdlc_private_area_t* chdlc_priv_area = dev->priv; | ||
759 | sdla_t* card = chdlc_priv_area->card; | ||
760 | |||
761 | /* Stop the PPP Layer */ | ||
762 | sppp_close(dev); | ||
763 | netif_stop_queue(dev); | ||
764 | |||
765 | wanpipe_close(card); | ||
766 | |||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | /*============================================================================ | ||
771 | * Send a packet on a network interface. | ||
772 | * o set tbusy flag (marks start of the transmission) to block a timer-based | ||
773 | * transmit from overlapping. | ||
774 | * o check link state. If link is not up, then drop the packet. | ||
775 | * o execute adapter send command. | ||
776 | * o free socket buffer | ||
777 | * | ||
778 | * Return: 0 complete (socket buffer must be freed) | ||
779 | * non-0 packet may be re-transmitted (tbusy must be set) | ||
780 | * | ||
781 | * Notes: | ||
782 | * 1. This routine is called either by the protocol stack or by the "net | ||
783 | * bottom half" (with interrupts enabled). | ||
784 | * 2. Setting tbusy flag will inhibit further transmit requests from the | ||
785 | * protocol stack and can be used for flow control with protocol layer. | ||
786 | */ | ||
787 | static int if_send(struct sk_buff* skb, struct net_device* dev) | ||
788 | { | ||
789 | chdlc_private_area_t *chdlc_priv_area = dev->priv; | ||
790 | sdla_t *card = chdlc_priv_area->card; | ||
791 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
792 | INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct; | ||
793 | int udp_type = 0; | ||
794 | unsigned long smp_flags; | ||
795 | int err=0; | ||
796 | |||
797 | netif_stop_queue(dev); | ||
798 | |||
799 | |||
800 | if (skb == NULL){ | ||
801 | /* If we get here, some higher layer thinks we've missed an | ||
802 | * tx-done interrupt. | ||
803 | */ | ||
804 | printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n", | ||
805 | card->devname, dev->name); | ||
806 | |||
807 | netif_wake_queue(dev); | ||
808 | return 0; | ||
809 | } | ||
810 | |||
811 | if (ntohs(skb->protocol) != htons(PVC_PROT)){ | ||
812 | /* check the udp packet type */ | ||
813 | |||
814 | udp_type = udp_pkt_type(skb, card); | ||
815 | if (udp_type == UDP_CPIPE_TYPE){ | ||
816 | if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev, | ||
817 | chdlc_priv_area)){ | ||
818 | chdlc_int->interrupt_permission |= | ||
819 | APP_INT_ON_TIMER; | ||
820 | } | ||
821 | netif_start_queue(dev); | ||
822 | return 0; | ||
823 | } | ||
824 | } | ||
825 | |||
826 | /* Lock the 508 Card: SMP is supported */ | ||
827 | if(card->hw.type != SDLA_S514){ | ||
828 | s508_lock(card,&smp_flags); | ||
829 | } | ||
830 | |||
831 | if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)){ | ||
832 | |||
833 | printk(KERN_INFO "%s: Critical in if_send: %lx\n", | ||
834 | card->wandev.name,card->wandev.critical); | ||
835 | ++card->wandev.stats.tx_dropped; | ||
836 | netif_start_queue(dev); | ||
837 | goto if_send_crit_exit; | ||
838 | } | ||
839 | |||
840 | if (card->wandev.state != WAN_CONNECTED){ | ||
841 | ++card->wandev.stats.tx_dropped; | ||
842 | netif_start_queue(dev); | ||
843 | goto if_send_crit_exit; | ||
844 | } | ||
845 | |||
846 | if (chdlc_send(card, skb->data, skb->len)){ | ||
847 | netif_stop_queue(dev); | ||
848 | |||
849 | }else{ | ||
850 | ++card->wandev.stats.tx_packets; | ||
851 | card->wandev.stats.tx_bytes += skb->len; | ||
852 | dev->trans_start = jiffies; | ||
853 | netif_start_queue(dev); | ||
854 | } | ||
855 | |||
856 | if_send_crit_exit: | ||
857 | if (!(err=netif_queue_stopped(dev))){ | ||
858 | dev_kfree_skb_any(skb); | ||
859 | }else{ | ||
860 | chdlc_priv_area->tick_counter = jiffies; | ||
861 | chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME; | ||
862 | } | ||
863 | |||
864 | clear_bit(SEND_CRIT, (void*)&card->wandev.critical); | ||
865 | if(card->hw.type != SDLA_S514){ | ||
866 | s508_unlock(card,&smp_flags); | ||
867 | } | ||
868 | |||
869 | return err; | ||
870 | } | ||
871 | |||
872 | |||
873 | /*============================================================================ | ||
874 | * Reply to UDP Management system. | ||
875 | * Return length of reply. | ||
876 | */ | ||
877 | static int reply_udp( unsigned char *data, unsigned int mbox_len ) | ||
878 | { | ||
879 | |||
880 | unsigned short len, udp_length, temp, ip_length; | ||
881 | unsigned long ip_temp; | ||
882 | int even_bound = 0; | ||
883 | chdlc_udp_pkt_t *c_udp_pkt = (chdlc_udp_pkt_t *)data; | ||
884 | |||
885 | /* Set length of packet */ | ||
886 | len = sizeof(ip_pkt_t)+ | ||
887 | sizeof(udp_pkt_t)+ | ||
888 | sizeof(wp_mgmt_t)+ | ||
889 | sizeof(cblock_t)+ | ||
890 | sizeof(trace_info_t)+ | ||
891 | mbox_len; | ||
892 | |||
893 | /* fill in UDP reply */ | ||
894 | c_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; | ||
895 | |||
896 | /* fill in UDP length */ | ||
897 | udp_length = sizeof(udp_pkt_t)+ | ||
898 | sizeof(wp_mgmt_t)+ | ||
899 | sizeof(cblock_t)+ | ||
900 | sizeof(trace_info_t)+ | ||
901 | mbox_len; | ||
902 | |||
903 | /* put it on an even boundary */ | ||
904 | if ( udp_length & 0x0001 ) { | ||
905 | udp_length += 1; | ||
906 | len += 1; | ||
907 | even_bound = 1; | ||
908 | } | ||
909 | |||
910 | temp = (udp_length<<8)|(udp_length>>8); | ||
911 | c_udp_pkt->udp_pkt.udp_length = temp; | ||
912 | |||
913 | /* swap UDP ports */ | ||
914 | temp = c_udp_pkt->udp_pkt.udp_src_port; | ||
915 | c_udp_pkt->udp_pkt.udp_src_port = | ||
916 | c_udp_pkt->udp_pkt.udp_dst_port; | ||
917 | c_udp_pkt->udp_pkt.udp_dst_port = temp; | ||
918 | |||
919 | /* add UDP pseudo header */ | ||
920 | temp = 0x1100; | ||
921 | *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound)) = temp; | ||
922 | temp = (udp_length<<8)|(udp_length>>8); | ||
923 | *((unsigned short *)(c_udp_pkt->data+mbox_len+even_bound+2)) = temp; | ||
924 | |||
925 | |||
926 | /* calculate UDP checksum */ | ||
927 | c_udp_pkt->udp_pkt.udp_checksum = 0; | ||
928 | c_udp_pkt->udp_pkt.udp_checksum = calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET); | ||
929 | |||
930 | /* fill in IP length */ | ||
931 | ip_length = len; | ||
932 | temp = (ip_length<<8)|(ip_length>>8); | ||
933 | c_udp_pkt->ip_pkt.total_length = temp; | ||
934 | |||
935 | /* swap IP addresses */ | ||
936 | ip_temp = c_udp_pkt->ip_pkt.ip_src_address; | ||
937 | c_udp_pkt->ip_pkt.ip_src_address = c_udp_pkt->ip_pkt.ip_dst_address; | ||
938 | c_udp_pkt->ip_pkt.ip_dst_address = ip_temp; | ||
939 | |||
940 | /* fill in IP checksum */ | ||
941 | c_udp_pkt->ip_pkt.hdr_checksum = 0; | ||
942 | c_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t)); | ||
943 | |||
944 | return len; | ||
945 | |||
946 | } /* reply_udp */ | ||
947 | |||
948 | unsigned short calc_checksum (char *data, int len) | ||
949 | { | ||
950 | unsigned short temp; | ||
951 | unsigned long sum=0; | ||
952 | int i; | ||
953 | |||
954 | for( i = 0; i <len; i+=2 ) { | ||
955 | memcpy(&temp,&data[i],2); | ||
956 | sum += (unsigned long)temp; | ||
957 | } | ||
958 | |||
959 | while (sum >> 16 ) { | ||
960 | sum = (sum & 0xffffUL) + (sum >> 16); | ||
961 | } | ||
962 | |||
963 | temp = (unsigned short)sum; | ||
964 | temp = ~temp; | ||
965 | |||
966 | if( temp == 0 ) | ||
967 | temp = 0xffff; | ||
968 | |||
969 | return temp; | ||
970 | } | ||
971 | |||
972 | |||
973 | /*============================================================================ | ||
974 | * Get ethernet-style interface statistics. | ||
975 | * Return a pointer to struct enet_statistics. | ||
976 | */ | ||
977 | static struct net_device_stats* if_stats(struct net_device* dev) | ||
978 | { | ||
979 | sdla_t *my_card; | ||
980 | chdlc_private_area_t* chdlc_priv_area; | ||
981 | |||
982 | /* Shutdown bug fix. In del_if() we kill | ||
983 | * dev->priv pointer. This function, gets | ||
984 | * called after del_if(), thus check | ||
985 | * if pointer has been deleted */ | ||
986 | if ((chdlc_priv_area=dev->priv) == NULL) | ||
987 | return NULL; | ||
988 | |||
989 | my_card = chdlc_priv_area->card; | ||
990 | return &my_card->wandev.stats; | ||
991 | } | ||
992 | |||
993 | |||
994 | /****** Cisco HDLC Firmware Interface Functions *******************************/ | ||
995 | |||
996 | /*============================================================================ | ||
997 | * Read firmware code version. | ||
998 | * Put code version as ASCII string in str. | ||
999 | */ | ||
1000 | static int chdlc_read_version (sdla_t* card, char* str) | ||
1001 | { | ||
1002 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1003 | int len; | ||
1004 | char err; | ||
1005 | mb->buffer_length = 0; | ||
1006 | mb->command = READ_CHDLC_CODE_VERSION; | ||
1007 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1008 | |||
1009 | if(err != COMMAND_OK) { | ||
1010 | chdlc_error(card,err,mb); | ||
1011 | } | ||
1012 | else if (str) { /* is not null */ | ||
1013 | len = mb->buffer_length; | ||
1014 | memcpy(str, mb->data, len); | ||
1015 | str[len] = '\0'; | ||
1016 | } | ||
1017 | return (err); | ||
1018 | } | ||
1019 | |||
1020 | /*----------------------------------------------------------------------------- | ||
1021 | * Configure CHDLC firmware. | ||
1022 | */ | ||
1023 | static int chdlc_configure (sdla_t* card, void* data) | ||
1024 | { | ||
1025 | int err; | ||
1026 | CHDLC_MAILBOX_STRUCT *mailbox = card->mbox; | ||
1027 | int data_length = sizeof(CHDLC_CONFIGURATION_STRUCT); | ||
1028 | |||
1029 | mailbox->buffer_length = data_length; | ||
1030 | memcpy(mailbox->data, data, data_length); | ||
1031 | mailbox->command = SET_CHDLC_CONFIGURATION; | ||
1032 | err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT; | ||
1033 | |||
1034 | if (err != COMMAND_OK) chdlc_error (card, err, mailbox); | ||
1035 | |||
1036 | return err; | ||
1037 | } | ||
1038 | |||
1039 | |||
1040 | /*============================================================================ | ||
1041 | * Set interrupt mode -- HDLC Version. | ||
1042 | */ | ||
1043 | |||
1044 | static int chdlc_set_intr_mode (sdla_t* card, unsigned mode) | ||
1045 | { | ||
1046 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1047 | CHDLC_INT_TRIGGERS_STRUCT* int_data = | ||
1048 | (CHDLC_INT_TRIGGERS_STRUCT *)mb->data; | ||
1049 | int err; | ||
1050 | |||
1051 | int_data->CHDLC_interrupt_triggers = mode; | ||
1052 | int_data->IRQ = card->hw.irq; | ||
1053 | int_data->interrupt_timer = 1; | ||
1054 | |||
1055 | mb->buffer_length = sizeof(CHDLC_INT_TRIGGERS_STRUCT); | ||
1056 | mb->command = SET_CHDLC_INTERRUPT_TRIGGERS; | ||
1057 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1058 | if (err != COMMAND_OK) | ||
1059 | chdlc_error (card, err, mb); | ||
1060 | return err; | ||
1061 | } | ||
1062 | |||
1063 | |||
1064 | /*============================================================================ | ||
1065 | * Enable communications. | ||
1066 | */ | ||
1067 | |||
1068 | static int chdlc_comm_enable (sdla_t* card) | ||
1069 | { | ||
1070 | int err; | ||
1071 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1072 | |||
1073 | mb->buffer_length = 0; | ||
1074 | mb->command = ENABLE_CHDLC_COMMUNICATIONS; | ||
1075 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1076 | if (err != COMMAND_OK) | ||
1077 | chdlc_error(card, err, mb); | ||
1078 | else | ||
1079 | card->u.c.comm_enabled=1; | ||
1080 | |||
1081 | return err; | ||
1082 | } | ||
1083 | |||
1084 | /*============================================================================ | ||
1085 | * Disable communications and Drop the Modem lines (DCD and RTS). | ||
1086 | */ | ||
1087 | static int chdlc_comm_disable (sdla_t* card) | ||
1088 | { | ||
1089 | int err; | ||
1090 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1091 | |||
1092 | mb->buffer_length = 0; | ||
1093 | mb->command = DISABLE_CHDLC_COMMUNICATIONS; | ||
1094 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1095 | if (err != COMMAND_OK) | ||
1096 | chdlc_error(card,err,mb); | ||
1097 | |||
1098 | return err; | ||
1099 | } | ||
1100 | |||
1101 | /*============================================================================ | ||
1102 | * Read communication error statistics. | ||
1103 | */ | ||
1104 | static int chdlc_read_comm_err_stats (sdla_t* card) | ||
1105 | { | ||
1106 | int err; | ||
1107 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1108 | |||
1109 | mb->buffer_length = 0; | ||
1110 | mb->command = READ_COMMS_ERROR_STATS; | ||
1111 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1112 | if (err != COMMAND_OK) | ||
1113 | chdlc_error(card,err,mb); | ||
1114 | return err; | ||
1115 | } | ||
1116 | |||
1117 | |||
1118 | /*============================================================================ | ||
1119 | * Read CHDLC operational statistics. | ||
1120 | */ | ||
1121 | static int chdlc_read_op_stats (sdla_t* card) | ||
1122 | { | ||
1123 | int err; | ||
1124 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1125 | |||
1126 | mb->buffer_length = 0; | ||
1127 | mb->command = READ_CHDLC_OPERATIONAL_STATS; | ||
1128 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1129 | if (err != COMMAND_OK) | ||
1130 | chdlc_error(card,err,mb); | ||
1131 | return err; | ||
1132 | } | ||
1133 | |||
1134 | |||
1135 | /*============================================================================ | ||
1136 | * Update communications error and general packet statistics. | ||
1137 | */ | ||
1138 | static int update_comms_stats(sdla_t* card, | ||
1139 | chdlc_private_area_t* chdlc_priv_area) | ||
1140 | { | ||
1141 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1142 | COMMS_ERROR_STATS_STRUCT* err_stats; | ||
1143 | CHDLC_OPERATIONAL_STATS_STRUCT *op_stats; | ||
1144 | |||
1145 | /* on the first timer interrupt, read the comms error statistics */ | ||
1146 | if(chdlc_priv_area->update_comms_stats == 2) { | ||
1147 | if(chdlc_read_comm_err_stats(card)) | ||
1148 | return 1; | ||
1149 | err_stats = (COMMS_ERROR_STATS_STRUCT *)mb->data; | ||
1150 | card->wandev.stats.rx_over_errors = | ||
1151 | err_stats->Rx_overrun_err_count; | ||
1152 | card->wandev.stats.rx_crc_errors = | ||
1153 | err_stats->CRC_err_count; | ||
1154 | card->wandev.stats.rx_frame_errors = | ||
1155 | err_stats->Rx_abort_count; | ||
1156 | card->wandev.stats.rx_fifo_errors = | ||
1157 | err_stats->Rx_dis_pri_bfrs_full_count; | ||
1158 | card->wandev.stats.rx_missed_errors = | ||
1159 | card->wandev.stats.rx_fifo_errors; | ||
1160 | card->wandev.stats.tx_aborted_errors = | ||
1161 | err_stats->sec_Tx_abort_count; | ||
1162 | } | ||
1163 | |||
1164 | /* on the second timer interrupt, read the operational statistics */ | ||
1165 | else { | ||
1166 | if(chdlc_read_op_stats(card)) | ||
1167 | return 1; | ||
1168 | op_stats = (CHDLC_OPERATIONAL_STATS_STRUCT *)mb->data; | ||
1169 | card->wandev.stats.rx_length_errors = | ||
1170 | (op_stats->Rx_Data_discard_short_count + | ||
1171 | op_stats->Rx_Data_discard_long_count); | ||
1172 | } | ||
1173 | |||
1174 | return 0; | ||
1175 | } | ||
1176 | |||
1177 | /*============================================================================ | ||
1178 | * Send packet. | ||
1179 | * Return: 0 - o.k. | ||
1180 | * 1 - no transmit buffers available | ||
1181 | */ | ||
1182 | static int chdlc_send (sdla_t* card, void* data, unsigned len) | ||
1183 | { | ||
1184 | CHDLC_DATA_TX_STATUS_EL_STRUCT *txbuf = card->u.c.txbuf; | ||
1185 | |||
1186 | if (txbuf->opp_flag) | ||
1187 | return 1; | ||
1188 | |||
1189 | sdla_poke(&card->hw, txbuf->ptr_data_bfr, data, len); | ||
1190 | |||
1191 | txbuf->frame_length = len; | ||
1192 | txbuf->opp_flag = 1; /* start transmission */ | ||
1193 | |||
1194 | /* Update transmit buffer control fields */ | ||
1195 | card->u.c.txbuf = ++txbuf; | ||
1196 | |||
1197 | if ((void*)txbuf > card->u.c.txbuf_last) | ||
1198 | card->u.c.txbuf = card->u.c.txbuf_base; | ||
1199 | |||
1200 | return 0; | ||
1201 | } | ||
1202 | |||
1203 | /****** Firmware Error Handler **********************************************/ | ||
1204 | |||
1205 | /*============================================================================ | ||
1206 | * Firmware error handler. | ||
1207 | * This routine is called whenever firmware command returns non-zero | ||
1208 | * return code. | ||
1209 | * | ||
1210 | * Return zero if previous command has to be cancelled. | ||
1211 | */ | ||
1212 | static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb) | ||
1213 | { | ||
1214 | unsigned cmd = mb->command; | ||
1215 | |||
1216 | switch (err) { | ||
1217 | |||
1218 | case CMD_TIMEOUT: | ||
1219 | printk(KERN_ERR "%s: command 0x%02X timed out!\n", | ||
1220 | card->devname, cmd); | ||
1221 | break; | ||
1222 | |||
1223 | case S514_BOTH_PORTS_SAME_CLK_MODE: | ||
1224 | if(cmd == SET_CHDLC_CONFIGURATION) { | ||
1225 | printk(KERN_INFO | ||
1226 | "%s: Configure both ports for the same clock source\n", | ||
1227 | card->devname); | ||
1228 | break; | ||
1229 | } | ||
1230 | |||
1231 | default: | ||
1232 | printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n", | ||
1233 | card->devname, cmd, err); | ||
1234 | } | ||
1235 | |||
1236 | return 0; | ||
1237 | } | ||
1238 | |||
1239 | /****** Interrupt Handlers **************************************************/ | ||
1240 | |||
1241 | /*============================================================================ | ||
1242 | * Cisco HDLC interrupt service routine. | ||
1243 | */ | ||
1244 | STATIC void wsppp_isr (sdla_t* card) | ||
1245 | { | ||
1246 | struct net_device* dev; | ||
1247 | SHARED_MEMORY_INFO_STRUCT* flags = NULL; | ||
1248 | int i; | ||
1249 | sdla_t *my_card; | ||
1250 | |||
1251 | |||
1252 | /* Check for which port the interrupt has been generated | ||
1253 | * Since Secondary Port is piggybacking on the Primary | ||
1254 | * the check must be done here. | ||
1255 | */ | ||
1256 | |||
1257 | flags = card->u.c.flags; | ||
1258 | if (!flags->interrupt_info_struct.interrupt_type){ | ||
1259 | /* Check for a second port (piggybacking) */ | ||
1260 | if((my_card = card->next)){ | ||
1261 | flags = my_card->u.c.flags; | ||
1262 | if (flags->interrupt_info_struct.interrupt_type){ | ||
1263 | card = my_card; | ||
1264 | card->isr(card); | ||
1265 | return; | ||
1266 | } | ||
1267 | } | ||
1268 | } | ||
1269 | |||
1270 | dev = card->wandev.dev; | ||
1271 | card->in_isr = 1; | ||
1272 | flags = card->u.c.flags; | ||
1273 | |||
1274 | /* If we get an interrupt with no network device, stop the interrupts | ||
1275 | * and issue an error */ | ||
1276 | if ((!dev || !dev->priv) && flags->interrupt_info_struct.interrupt_type != | ||
1277 | COMMAND_COMPLETE_APP_INT_PEND){ | ||
1278 | goto isr_done; | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | /* if critical due to peripheral operations | ||
1283 | * ie. update() or getstats() then reset the interrupt and | ||
1284 | * wait for the board to retrigger. | ||
1285 | */ | ||
1286 | if(test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { | ||
1287 | flags->interrupt_info_struct. | ||
1288 | interrupt_type = 0; | ||
1289 | goto isr_done; | ||
1290 | } | ||
1291 | |||
1292 | |||
1293 | /* On a 508 Card, if critical due to if_send | ||
1294 | * Major Error !!! | ||
1295 | */ | ||
1296 | if(card->hw.type != SDLA_S514) { | ||
1297 | if(test_bit(0, (void*)&card->wandev.critical)) { | ||
1298 | printk(KERN_INFO "%s: Critical while in ISR: %lx\n", | ||
1299 | card->devname, card->wandev.critical); | ||
1300 | goto isr_done; | ||
1301 | } | ||
1302 | } | ||
1303 | |||
1304 | switch(flags->interrupt_info_struct.interrupt_type) { | ||
1305 | |||
1306 | case RX_APP_INT_PEND: /* 0x01: receive interrupt */ | ||
1307 | rx_intr(card); | ||
1308 | break; | ||
1309 | |||
1310 | case TX_APP_INT_PEND: /* 0x02: transmit interrupt */ | ||
1311 | flags->interrupt_info_struct.interrupt_permission &= | ||
1312 | ~APP_INT_ON_TX_FRAME; | ||
1313 | |||
1314 | netif_wake_queue(dev); | ||
1315 | break; | ||
1316 | |||
1317 | case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */ | ||
1318 | ++ Intr_test_counter; | ||
1319 | break; | ||
1320 | |||
1321 | case CHDLC_EXCEP_COND_APP_INT_PEND: /* 0x20 */ | ||
1322 | process_chdlc_exception(card); | ||
1323 | break; | ||
1324 | |||
1325 | case GLOBAL_EXCEP_COND_APP_INT_PEND: | ||
1326 | process_global_exception(card); | ||
1327 | break; | ||
1328 | |||
1329 | case TIMER_APP_INT_PEND: | ||
1330 | timer_intr(card); | ||
1331 | break; | ||
1332 | |||
1333 | default: | ||
1334 | printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", | ||
1335 | card->devname, | ||
1336 | flags->interrupt_info_struct.interrupt_type); | ||
1337 | printk(KERN_INFO "Code name: "); | ||
1338 | for(i = 0; i < 4; i ++) | ||
1339 | printk(KERN_INFO "%c", | ||
1340 | flags->global_info_struct.codename[i]); | ||
1341 | printk(KERN_INFO "\nCode version: "); | ||
1342 | for(i = 0; i < 4; i ++) | ||
1343 | printk(KERN_INFO "%c", | ||
1344 | flags->global_info_struct.codeversion[i]); | ||
1345 | printk(KERN_INFO "\n"); | ||
1346 | break; | ||
1347 | } | ||
1348 | |||
1349 | isr_done: | ||
1350 | card->in_isr = 0; | ||
1351 | flags->interrupt_info_struct.interrupt_type = 0; | ||
1352 | } | ||
1353 | |||
1354 | /*============================================================================ | ||
1355 | * Receive interrupt handler. | ||
1356 | */ | ||
1357 | static void rx_intr (sdla_t* card) | ||
1358 | { | ||
1359 | struct net_device *dev; | ||
1360 | chdlc_private_area_t *chdlc_priv_area; | ||
1361 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
1362 | CHDLC_DATA_RX_STATUS_EL_STRUCT *rxbuf = card->u.c.rxmb; | ||
1363 | struct sk_buff *skb; | ||
1364 | unsigned len; | ||
1365 | unsigned addr = rxbuf->ptr_data_bfr; | ||
1366 | void *buf; | ||
1367 | int i,udp_type; | ||
1368 | |||
1369 | if (rxbuf->opp_flag != 0x01) { | ||
1370 | printk(KERN_INFO | ||
1371 | "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", | ||
1372 | card->devname, (unsigned)rxbuf, rxbuf->opp_flag); | ||
1373 | printk(KERN_INFO "Code name: "); | ||
1374 | for(i = 0; i < 4; i ++) | ||
1375 | printk(KERN_INFO "%c", | ||
1376 | flags->global_info_struct.codename[i]); | ||
1377 | printk(KERN_INFO "\nCode version: "); | ||
1378 | for(i = 0; i < 4; i ++) | ||
1379 | printk(KERN_INFO "%c", | ||
1380 | flags->global_info_struct.codeversion[i]); | ||
1381 | printk(KERN_INFO "\n"); | ||
1382 | |||
1383 | |||
1384 | /* Bug Fix: Mar 6 2000 | ||
1385 | * If we get a corrupted mailbox, it measn that driver | ||
1386 | * is out of sync with the firmware. There is no recovery. | ||
1387 | * If we don't turn off all interrupts for this card | ||
1388 | * the machine will crash. | ||
1389 | */ | ||
1390 | printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname); | ||
1391 | printk(KERN_INFO "Please contact Sangoma Technologies !\n"); | ||
1392 | chdlc_set_intr_mode(card,0); | ||
1393 | return; | ||
1394 | } | ||
1395 | |||
1396 | dev = card->wandev.dev; | ||
1397 | |||
1398 | if (!dev){ | ||
1399 | goto rx_exit; | ||
1400 | } | ||
1401 | |||
1402 | if (!netif_running(dev)){ | ||
1403 | goto rx_exit; | ||
1404 | } | ||
1405 | |||
1406 | chdlc_priv_area = dev->priv; | ||
1407 | |||
1408 | if (rxbuf->error_flag){ | ||
1409 | goto rx_exit; | ||
1410 | } | ||
1411 | /* Take off two CRC bytes */ | ||
1412 | |||
1413 | if (rxbuf->frame_length < 7 || rxbuf->frame_length > 1506 ){ | ||
1414 | goto rx_exit; | ||
1415 | } | ||
1416 | |||
1417 | len = rxbuf->frame_length - CRC_LENGTH; | ||
1418 | |||
1419 | /* Allocate socket buffer */ | ||
1420 | skb = dev_alloc_skb(len); | ||
1421 | |||
1422 | if (skb == NULL) { | ||
1423 | if (net_ratelimit()){ | ||
1424 | printk(KERN_INFO "%s: no socket buffers available!\n", | ||
1425 | card->devname); | ||
1426 | } | ||
1427 | ++card->wandev.stats.rx_dropped; | ||
1428 | goto rx_exit; | ||
1429 | } | ||
1430 | |||
1431 | /* Copy data to the socket buffer */ | ||
1432 | if((addr + len) > card->u.c.rx_top + 1) { | ||
1433 | unsigned tmp = card->u.c.rx_top - addr + 1; | ||
1434 | buf = skb_put(skb, tmp); | ||
1435 | sdla_peek(&card->hw, addr, buf, tmp); | ||
1436 | addr = card->u.c.rx_base; | ||
1437 | len -= tmp; | ||
1438 | } | ||
1439 | |||
1440 | buf = skb_put(skb, len); | ||
1441 | sdla_peek(&card->hw, addr, buf, len); | ||
1442 | |||
1443 | skb->protocol = htons(ETH_P_WAN_PPP); | ||
1444 | |||
1445 | card->wandev.stats.rx_packets ++; | ||
1446 | card->wandev.stats.rx_bytes += skb->len; | ||
1447 | udp_type = udp_pkt_type( skb, card ); | ||
1448 | |||
1449 | if(udp_type == UDP_CPIPE_TYPE) { | ||
1450 | if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, | ||
1451 | card, skb, dev, chdlc_priv_area)) { | ||
1452 | flags->interrupt_info_struct. | ||
1453 | interrupt_permission |= | ||
1454 | APP_INT_ON_TIMER; | ||
1455 | } | ||
1456 | }else{ | ||
1457 | /* Pass it up the protocol stack */ | ||
1458 | skb->dev = dev; | ||
1459 | skb->mac.raw = skb->data; | ||
1460 | netif_rx(skb); | ||
1461 | dev->last_rx = jiffies; | ||
1462 | } | ||
1463 | |||
1464 | rx_exit: | ||
1465 | /* Release buffer element and calculate a pointer to the next one */ | ||
1466 | rxbuf->opp_flag = 0x00; | ||
1467 | card->u.c.rxmb = ++ rxbuf; | ||
1468 | if((void*)rxbuf > card->u.c.rxbuf_last){ | ||
1469 | card->u.c.rxmb = card->u.c.rxbuf_base; | ||
1470 | } | ||
1471 | } | ||
1472 | |||
1473 | /*============================================================================ | ||
1474 | * Timer interrupt handler. | ||
1475 | * The timer interrupt is used for two purposes: | ||
1476 | * 1) Processing udp calls from 'cpipemon'. | ||
1477 | * 2) Reading board-level statistics for updating the proc file system. | ||
1478 | */ | ||
1479 | void timer_intr(sdla_t *card) | ||
1480 | { | ||
1481 | struct net_device* dev; | ||
1482 | chdlc_private_area_t* chdlc_priv_area = NULL; | ||
1483 | SHARED_MEMORY_INFO_STRUCT* flags = NULL; | ||
1484 | |||
1485 | dev = card->wandev.dev; | ||
1486 | chdlc_priv_area = dev->priv; | ||
1487 | |||
1488 | if (chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG) { | ||
1489 | if (!config_chdlc(card)){ | ||
1490 | chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_CONFIG; | ||
1491 | } | ||
1492 | } | ||
1493 | |||
1494 | /* process a udp call if pending */ | ||
1495 | if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP) { | ||
1496 | process_udp_mgmt_pkt(card, dev, | ||
1497 | chdlc_priv_area); | ||
1498 | chdlc_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP; | ||
1499 | } | ||
1500 | |||
1501 | |||
1502 | /* read the communications statistics if required */ | ||
1503 | if(chdlc_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE) { | ||
1504 | update_comms_stats(card, chdlc_priv_area); | ||
1505 | if(!(-- chdlc_priv_area->update_comms_stats)) { | ||
1506 | chdlc_priv_area->timer_int_enabled &= | ||
1507 | ~TMR_INT_ENABLED_UPDATE; | ||
1508 | } | ||
1509 | } | ||
1510 | |||
1511 | /* only disable the timer interrupt if there are no udp or statistic */ | ||
1512 | /* updates pending */ | ||
1513 | if(!chdlc_priv_area->timer_int_enabled) { | ||
1514 | flags = card->u.c.flags; | ||
1515 | flags->interrupt_info_struct.interrupt_permission &= | ||
1516 | ~APP_INT_ON_TIMER; | ||
1517 | } | ||
1518 | } | ||
1519 | |||
1520 | /*------------------------------------------------------------------------------ | ||
1521 | Miscellaneous Functions | ||
1522 | - set_chdlc_config() used to set configuration options on the board | ||
1523 | ------------------------------------------------------------------------------*/ | ||
1524 | |||
1525 | static int set_chdlc_config(sdla_t* card) | ||
1526 | { | ||
1527 | |||
1528 | CHDLC_CONFIGURATION_STRUCT cfg; | ||
1529 | |||
1530 | memset(&cfg, 0, sizeof(CHDLC_CONFIGURATION_STRUCT)); | ||
1531 | |||
1532 | if(card->wandev.clocking) | ||
1533 | cfg.baud_rate = card->wandev.bps; | ||
1534 | |||
1535 | cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ? | ||
1536 | INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35; | ||
1537 | |||
1538 | cfg.modem_config_options = 0; | ||
1539 | //API OPTIONS | ||
1540 | cfg.CHDLC_API_options = DISCARD_RX_ERROR_FRAMES; | ||
1541 | cfg.modem_status_timer = 100; | ||
1542 | cfg.CHDLC_protocol_options = HDLC_STREAMING_MODE; | ||
1543 | cfg.percent_data_buffer_for_Tx = 50; | ||
1544 | cfg.CHDLC_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT | | ||
1545 | CHDLC_RX_DATA_BYTE_COUNT_STAT); | ||
1546 | cfg.max_CHDLC_data_field_length = card->wandev.mtu; | ||
1547 | |||
1548 | cfg.transmit_keepalive_timer = 0; | ||
1549 | cfg.receive_keepalive_timer = 0; | ||
1550 | cfg.keepalive_error_tolerance = 0; | ||
1551 | cfg.SLARP_request_timer = 0; | ||
1552 | |||
1553 | cfg.IP_address = 0; | ||
1554 | cfg.IP_netmask = 0; | ||
1555 | |||
1556 | return chdlc_configure(card, &cfg); | ||
1557 | } | ||
1558 | |||
1559 | /*============================================================================ | ||
1560 | * Process global exception condition | ||
1561 | */ | ||
1562 | static int process_global_exception(sdla_t *card) | ||
1563 | { | ||
1564 | CHDLC_MAILBOX_STRUCT* mbox = card->mbox; | ||
1565 | int err; | ||
1566 | |||
1567 | mbox->buffer_length = 0; | ||
1568 | mbox->command = READ_GLOBAL_EXCEPTION_CONDITION; | ||
1569 | err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT; | ||
1570 | |||
1571 | if(err != CMD_TIMEOUT ){ | ||
1572 | |||
1573 | switch(mbox->return_code) { | ||
1574 | |||
1575 | case EXCEP_MODEM_STATUS_CHANGE: | ||
1576 | |||
1577 | printk(KERN_INFO "%s: Modem status change\n", | ||
1578 | card->devname); | ||
1579 | |||
1580 | switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) { | ||
1581 | case (DCD_HIGH): | ||
1582 | printk(KERN_INFO "%s: DCD high, CTS low\n",card->devname); | ||
1583 | break; | ||
1584 | case (CTS_HIGH): | ||
1585 | printk(KERN_INFO "%s: DCD low, CTS high\n",card->devname); | ||
1586 | break; | ||
1587 | case ((DCD_HIGH | CTS_HIGH)): | ||
1588 | printk(KERN_INFO "%s: DCD high, CTS high\n",card->devname); | ||
1589 | break; | ||
1590 | default: | ||
1591 | printk(KERN_INFO "%s: DCD low, CTS low\n",card->devname); | ||
1592 | break; | ||
1593 | } | ||
1594 | |||
1595 | if (!(mbox->data[0] & DCD_HIGH) || !(mbox->data[0] & DCD_HIGH)){ | ||
1596 | //printk(KERN_INFO "Sending TERM Request Manually !\n"); | ||
1597 | send_ppp_term_request(card->wandev.dev); | ||
1598 | } | ||
1599 | break; | ||
1600 | |||
1601 | case EXCEP_TRC_DISABLED: | ||
1602 | printk(KERN_INFO "%s: Line trace disabled\n", | ||
1603 | card->devname); | ||
1604 | break; | ||
1605 | |||
1606 | case EXCEP_IRQ_TIMEOUT: | ||
1607 | printk(KERN_INFO "%s: IRQ timeout occurred\n", | ||
1608 | card->devname); | ||
1609 | break; | ||
1610 | |||
1611 | default: | ||
1612 | printk(KERN_INFO "%s: Global exception %x\n", | ||
1613 | card->devname, mbox->return_code); | ||
1614 | break; | ||
1615 | } | ||
1616 | } | ||
1617 | return 0; | ||
1618 | } | ||
1619 | |||
1620 | |||
1621 | /*============================================================================ | ||
1622 | * Process chdlc exception condition | ||
1623 | */ | ||
1624 | static int process_chdlc_exception(sdla_t *card) | ||
1625 | { | ||
1626 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
1627 | int err; | ||
1628 | |||
1629 | mb->buffer_length = 0; | ||
1630 | mb->command = READ_CHDLC_EXCEPTION_CONDITION; | ||
1631 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1632 | if(err != CMD_TIMEOUT) { | ||
1633 | |||
1634 | switch (err) { | ||
1635 | |||
1636 | case EXCEP_LINK_ACTIVE: | ||
1637 | port_set_state(card, WAN_CONNECTED); | ||
1638 | break; | ||
1639 | |||
1640 | case EXCEP_LINK_INACTIVE_MODEM: | ||
1641 | port_set_state(card, WAN_DISCONNECTED); | ||
1642 | break; | ||
1643 | |||
1644 | case EXCEP_LOOPBACK_CONDITION: | ||
1645 | printk(KERN_INFO "%s: Loopback Condition Detected.\n", | ||
1646 | card->devname); | ||
1647 | break; | ||
1648 | |||
1649 | case NO_CHDLC_EXCEP_COND_TO_REPORT: | ||
1650 | printk(KERN_INFO "%s: No exceptions reported.\n", | ||
1651 | card->devname); | ||
1652 | break; | ||
1653 | default: | ||
1654 | printk(KERN_INFO "%s: Exception Condition %x!\n", | ||
1655 | card->devname,err); | ||
1656 | break; | ||
1657 | } | ||
1658 | |||
1659 | } | ||
1660 | return 0; | ||
1661 | } | ||
1662 | |||
1663 | |||
1664 | /*============================================================================= | ||
1665 | * Store a UDP management packet for later processing. | ||
1666 | */ | ||
1667 | |||
1668 | static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, | ||
1669 | struct sk_buff *skb, struct net_device* dev, | ||
1670 | chdlc_private_area_t* chdlc_priv_area ) | ||
1671 | { | ||
1672 | int udp_pkt_stored = 0; | ||
1673 | |||
1674 | if(!chdlc_priv_area->udp_pkt_lgth && | ||
1675 | (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) { | ||
1676 | chdlc_priv_area->udp_pkt_lgth = skb->len; | ||
1677 | chdlc_priv_area->udp_pkt_src = udp_pkt_src; | ||
1678 | memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len); | ||
1679 | chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP; | ||
1680 | udp_pkt_stored = 1; | ||
1681 | } | ||
1682 | |||
1683 | if(udp_pkt_src == UDP_PKT_FRM_STACK) | ||
1684 | dev_kfree_skb_any(skb); | ||
1685 | else | ||
1686 | dev_kfree_skb_any(skb); | ||
1687 | |||
1688 | return(udp_pkt_stored); | ||
1689 | } | ||
1690 | |||
1691 | |||
1692 | /*============================================================================= | ||
1693 | * Process UDP management packet. | ||
1694 | */ | ||
1695 | |||
1696 | static int process_udp_mgmt_pkt(sdla_t* card, struct net_device* dev, | ||
1697 | chdlc_private_area_t* chdlc_priv_area ) | ||
1698 | { | ||
1699 | unsigned char *buf; | ||
1700 | unsigned int frames, len; | ||
1701 | struct sk_buff *new_skb; | ||
1702 | unsigned short buffer_length, real_len; | ||
1703 | unsigned long data_ptr; | ||
1704 | unsigned data_length; | ||
1705 | int udp_mgmt_req_valid = 1; | ||
1706 | CHDLC_MAILBOX_STRUCT *mb = card->mbox; | ||
1707 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
1708 | chdlc_udp_pkt_t *chdlc_udp_pkt; | ||
1709 | struct timeval tv; | ||
1710 | int err; | ||
1711 | char ut_char; | ||
1712 | |||
1713 | chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data; | ||
1714 | |||
1715 | if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { | ||
1716 | |||
1717 | switch(chdlc_udp_pkt->cblock.command) { | ||
1718 | case READ_GLOBAL_STATISTICS: | ||
1719 | case READ_MODEM_STATUS: | ||
1720 | case READ_CHDLC_LINK_STATUS: | ||
1721 | case CPIPE_ROUTER_UP_TIME: | ||
1722 | case READ_COMMS_ERROR_STATS: | ||
1723 | case READ_CHDLC_OPERATIONAL_STATS: | ||
1724 | |||
1725 | /* These two commands are executed for | ||
1726 | * each request */ | ||
1727 | case READ_CHDLC_CONFIGURATION: | ||
1728 | case READ_CHDLC_CODE_VERSION: | ||
1729 | udp_mgmt_req_valid = 1; | ||
1730 | break; | ||
1731 | default: | ||
1732 | udp_mgmt_req_valid = 0; | ||
1733 | break; | ||
1734 | } | ||
1735 | } | ||
1736 | |||
1737 | if(!udp_mgmt_req_valid) { | ||
1738 | |||
1739 | /* set length to 0 */ | ||
1740 | chdlc_udp_pkt->cblock.buffer_length = 0; | ||
1741 | |||
1742 | /* set return code */ | ||
1743 | chdlc_udp_pkt->cblock.return_code = 0xCD; | ||
1744 | |||
1745 | if (net_ratelimit()){ | ||
1746 | printk(KERN_INFO | ||
1747 | "%s: Warning, Illegal UDP command attempted from network: %x\n", | ||
1748 | card->devname,chdlc_udp_pkt->cblock.command); | ||
1749 | } | ||
1750 | |||
1751 | } else { | ||
1752 | unsigned long trace_status_cfg_addr = 0; | ||
1753 | TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct; | ||
1754 | TRACE_STATUS_ELEMENT_STRUCT trace_element_struct; | ||
1755 | |||
1756 | switch(chdlc_udp_pkt->cblock.command) { | ||
1757 | |||
1758 | case CPIPE_ENABLE_TRACING: | ||
1759 | if (!chdlc_priv_area->TracingEnabled) { | ||
1760 | |||
1761 | /* OPERATE_DATALINE_MONITOR */ | ||
1762 | |||
1763 | mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT); | ||
1764 | mb->command = SET_TRACE_CONFIGURATION; | ||
1765 | |||
1766 | ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> | ||
1767 | trace_config = TRACE_ACTIVE; | ||
1768 | /* Trace delay mode is not used because it slows | ||
1769 | down transfer and results in a standoff situation | ||
1770 | when there is a lot of data */ | ||
1771 | |||
1772 | /* Configure the Trace based on user inputs */ | ||
1773 | ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |= | ||
1774 | chdlc_udp_pkt->data[0]; | ||
1775 | |||
1776 | ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> | ||
1777 | trace_deactivation_timer = 4000; | ||
1778 | |||
1779 | |||
1780 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1781 | if (err != COMMAND_OK) { | ||
1782 | chdlc_error(card,err,mb); | ||
1783 | card->TracingEnabled = 0; | ||
1784 | chdlc_udp_pkt->cblock.return_code = err; | ||
1785 | mb->buffer_length = 0; | ||
1786 | break; | ||
1787 | } | ||
1788 | |||
1789 | /* Get the base address of the trace element list */ | ||
1790 | mb->buffer_length = 0; | ||
1791 | mb->command = READ_TRACE_CONFIGURATION; | ||
1792 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1793 | |||
1794 | if (err != COMMAND_OK) { | ||
1795 | chdlc_error(card,err,mb); | ||
1796 | chdlc_priv_area->TracingEnabled = 0; | ||
1797 | chdlc_udp_pkt->cblock.return_code = err; | ||
1798 | mb->buffer_length = 0; | ||
1799 | break; | ||
1800 | } | ||
1801 | |||
1802 | trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *) | ||
1803 | mb->data) -> ptr_trace_stat_el_cfg_struct; | ||
1804 | |||
1805 | sdla_peek(&card->hw, trace_status_cfg_addr, | ||
1806 | &trace_cfg_struct, sizeof(trace_cfg_struct)); | ||
1807 | |||
1808 | chdlc_priv_area->start_trace_addr = trace_cfg_struct. | ||
1809 | base_addr_trace_status_elements; | ||
1810 | |||
1811 | chdlc_priv_area->number_trace_elements = | ||
1812 | trace_cfg_struct.number_trace_status_elements; | ||
1813 | |||
1814 | chdlc_priv_area->end_trace_addr = (unsigned long) | ||
1815 | ((TRACE_STATUS_ELEMENT_STRUCT *) | ||
1816 | chdlc_priv_area->start_trace_addr + | ||
1817 | (chdlc_priv_area->number_trace_elements - 1)); | ||
1818 | |||
1819 | chdlc_priv_area->base_addr_trace_buffer = | ||
1820 | trace_cfg_struct.base_addr_trace_buffer; | ||
1821 | |||
1822 | chdlc_priv_area->end_addr_trace_buffer = | ||
1823 | trace_cfg_struct.end_addr_trace_buffer; | ||
1824 | |||
1825 | chdlc_priv_area->curr_trace_addr = | ||
1826 | trace_cfg_struct.next_trace_element_to_use; | ||
1827 | |||
1828 | chdlc_priv_area->available_buffer_space = 2000 - | ||
1829 | sizeof(ip_pkt_t) - | ||
1830 | sizeof(udp_pkt_t) - | ||
1831 | sizeof(wp_mgmt_t) - | ||
1832 | sizeof(cblock_t) - | ||
1833 | sizeof(trace_info_t); | ||
1834 | } | ||
1835 | chdlc_udp_pkt->cblock.return_code = COMMAND_OK; | ||
1836 | mb->buffer_length = 0; | ||
1837 | chdlc_priv_area->TracingEnabled = 1; | ||
1838 | break; | ||
1839 | |||
1840 | |||
1841 | case CPIPE_DISABLE_TRACING: | ||
1842 | if (chdlc_priv_area->TracingEnabled) { | ||
1843 | |||
1844 | /* OPERATE_DATALINE_MONITOR */ | ||
1845 | mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT); | ||
1846 | mb->command = SET_TRACE_CONFIGURATION; | ||
1847 | ((LINE_TRACE_CONFIG_STRUCT *)mb->data)-> | ||
1848 | trace_config = TRACE_INACTIVE; | ||
1849 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
1850 | } | ||
1851 | |||
1852 | chdlc_priv_area->TracingEnabled = 0; | ||
1853 | chdlc_udp_pkt->cblock.return_code = COMMAND_OK; | ||
1854 | mb->buffer_length = 0; | ||
1855 | break; | ||
1856 | |||
1857 | |||
1858 | case CPIPE_GET_TRACE_INFO: | ||
1859 | |||
1860 | if (!chdlc_priv_area->TracingEnabled) { | ||
1861 | chdlc_udp_pkt->cblock.return_code = 1; | ||
1862 | mb->buffer_length = 0; | ||
1863 | break; | ||
1864 | } | ||
1865 | |||
1866 | chdlc_udp_pkt->trace_info.ismoredata = 0x00; | ||
1867 | buffer_length = 0; /* offset of packet already occupied */ | ||
1868 | |||
1869 | for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){ | ||
1870 | |||
1871 | trace_pkt_t *trace_pkt = (trace_pkt_t *) | ||
1872 | &chdlc_udp_pkt->data[buffer_length]; | ||
1873 | |||
1874 | sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr, | ||
1875 | (unsigned char *)&trace_element_struct, | ||
1876 | sizeof(TRACE_STATUS_ELEMENT_STRUCT)); | ||
1877 | |||
1878 | if (trace_element_struct.opp_flag == 0x00) { | ||
1879 | break; | ||
1880 | } | ||
1881 | |||
1882 | /* get pointer to real data */ | ||
1883 | data_ptr = trace_element_struct.ptr_data_bfr; | ||
1884 | |||
1885 | /* See if there is actual data on the trace buffer */ | ||
1886 | if (data_ptr){ | ||
1887 | data_length = trace_element_struct.trace_length; | ||
1888 | }else{ | ||
1889 | data_length = 0; | ||
1890 | chdlc_udp_pkt->trace_info.ismoredata = 0x01; | ||
1891 | } | ||
1892 | |||
1893 | if( (chdlc_priv_area->available_buffer_space - buffer_length) | ||
1894 | < ( sizeof(trace_pkt_t) + data_length) ) { | ||
1895 | |||
1896 | /* indicate there are more frames on board & exit */ | ||
1897 | chdlc_udp_pkt->trace_info.ismoredata = 0x01; | ||
1898 | break; | ||
1899 | } | ||
1900 | |||
1901 | trace_pkt->status = trace_element_struct.trace_type; | ||
1902 | |||
1903 | trace_pkt->time_stamp = | ||
1904 | trace_element_struct.trace_time_stamp; | ||
1905 | |||
1906 | trace_pkt->real_length = | ||
1907 | trace_element_struct.trace_length; | ||
1908 | |||
1909 | /* see if we can fit the frame into the user buffer */ | ||
1910 | real_len = trace_pkt->real_length; | ||
1911 | |||
1912 | if (data_ptr == 0) { | ||
1913 | trace_pkt->data_avail = 0x00; | ||
1914 | } else { | ||
1915 | unsigned tmp = 0; | ||
1916 | |||
1917 | /* get the data from circular buffer | ||
1918 | must check for end of buffer */ | ||
1919 | trace_pkt->data_avail = 0x01; | ||
1920 | |||
1921 | if ((data_ptr + real_len) > | ||
1922 | chdlc_priv_area->end_addr_trace_buffer + 1){ | ||
1923 | |||
1924 | tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1; | ||
1925 | sdla_peek(&card->hw, data_ptr, | ||
1926 | trace_pkt->data,tmp); | ||
1927 | data_ptr = chdlc_priv_area->base_addr_trace_buffer; | ||
1928 | } | ||
1929 | |||
1930 | sdla_peek(&card->hw, data_ptr, | ||
1931 | &trace_pkt->data[tmp], real_len - tmp); | ||
1932 | } | ||
1933 | |||
1934 | /* zero the opp flag to show we got the frame */ | ||
1935 | ut_char = 0x00; | ||
1936 | sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1); | ||
1937 | |||
1938 | /* now move onto the next frame */ | ||
1939 | chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT); | ||
1940 | |||
1941 | /* check if we went over the last address */ | ||
1942 | if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) { | ||
1943 | chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr; | ||
1944 | } | ||
1945 | |||
1946 | if(trace_pkt->data_avail == 0x01) { | ||
1947 | buffer_length += real_len - 1; | ||
1948 | } | ||
1949 | |||
1950 | /* for the header */ | ||
1951 | buffer_length += sizeof(trace_pkt_t); | ||
1952 | |||
1953 | } /* For Loop */ | ||
1954 | |||
1955 | if (frames == chdlc_priv_area->number_trace_elements){ | ||
1956 | chdlc_udp_pkt->trace_info.ismoredata = 0x01; | ||
1957 | } | ||
1958 | chdlc_udp_pkt->trace_info.num_frames = frames; | ||
1959 | |||
1960 | mb->buffer_length = buffer_length; | ||
1961 | chdlc_udp_pkt->cblock.buffer_length = buffer_length; | ||
1962 | |||
1963 | chdlc_udp_pkt->cblock.return_code = COMMAND_OK; | ||
1964 | |||
1965 | break; | ||
1966 | |||
1967 | |||
1968 | case CPIPE_FT1_READ_STATUS: | ||
1969 | ((unsigned char *)chdlc_udp_pkt->data )[0] = | ||
1970 | flags->FT1_info_struct.parallel_port_A_input; | ||
1971 | |||
1972 | ((unsigned char *)chdlc_udp_pkt->data )[1] = | ||
1973 | flags->FT1_info_struct.parallel_port_B_input; | ||
1974 | |||
1975 | chdlc_udp_pkt->cblock.return_code = COMMAND_OK; | ||
1976 | mb->buffer_length = 2; | ||
1977 | break; | ||
1978 | |||
1979 | case CPIPE_ROUTER_UP_TIME: | ||
1980 | do_gettimeofday( &tv ); | ||
1981 | chdlc_priv_area->router_up_time = tv.tv_sec - | ||
1982 | chdlc_priv_area->router_start_time; | ||
1983 | *(unsigned long *)&chdlc_udp_pkt->data = | ||
1984 | chdlc_priv_area->router_up_time; | ||
1985 | mb->buffer_length = sizeof(unsigned long); | ||
1986 | break; | ||
1987 | |||
1988 | case FT1_MONITOR_STATUS_CTRL: | ||
1989 | /* Enable FT1 MONITOR STATUS */ | ||
1990 | if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) || | ||
1991 | (chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) { | ||
1992 | |||
1993 | if( rCount++ != 0 ) { | ||
1994 | chdlc_udp_pkt->cblock. | ||
1995 | return_code = COMMAND_OK; | ||
1996 | mb->buffer_length = 1; | ||
1997 | break; | ||
1998 | } | ||
1999 | } | ||
2000 | |||
2001 | /* Disable FT1 MONITOR STATUS */ | ||
2002 | if( chdlc_udp_pkt->data[0] == 0) { | ||
2003 | |||
2004 | if( --rCount != 0) { | ||
2005 | chdlc_udp_pkt->cblock. | ||
2006 | return_code = COMMAND_OK; | ||
2007 | mb->buffer_length = 1; | ||
2008 | break; | ||
2009 | } | ||
2010 | } | ||
2011 | |||
2012 | default: | ||
2013 | /* it's a board command */ | ||
2014 | mb->command = chdlc_udp_pkt->cblock.command; | ||
2015 | mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length; | ||
2016 | if (mb->buffer_length) { | ||
2017 | memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt-> | ||
2018 | data, mb->buffer_length); | ||
2019 | } | ||
2020 | /* run the command on the board */ | ||
2021 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
2022 | if (err != COMMAND_OK) { | ||
2023 | break; | ||
2024 | } | ||
2025 | |||
2026 | /* copy the result back to our buffer */ | ||
2027 | memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t)); | ||
2028 | |||
2029 | if (mb->buffer_length) { | ||
2030 | memcpy(&chdlc_udp_pkt->data, &mb->data, | ||
2031 | mb->buffer_length); | ||
2032 | } | ||
2033 | |||
2034 | } /* end of switch */ | ||
2035 | } /* end of else */ | ||
2036 | |||
2037 | /* Fill UDP TTL */ | ||
2038 | chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl; | ||
2039 | |||
2040 | len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length); | ||
2041 | |||
2042 | if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { | ||
2043 | if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) { | ||
2044 | ++ card->wandev.stats.tx_packets; | ||
2045 | card->wandev.stats.tx_bytes += len; | ||
2046 | } | ||
2047 | } else { | ||
2048 | |||
2049 | /* Pass it up the stack | ||
2050 | Allocate socket buffer */ | ||
2051 | if ((new_skb = dev_alloc_skb(len)) != NULL) { | ||
2052 | /* copy data into new_skb */ | ||
2053 | |||
2054 | buf = skb_put(new_skb, len); | ||
2055 | memcpy(buf, chdlc_priv_area->udp_pkt_data, len); | ||
2056 | |||
2057 | /* Decapsulate pkt and pass it up the protocol stack */ | ||
2058 | new_skb->protocol = htons(ETH_P_IP); | ||
2059 | new_skb->dev = dev; | ||
2060 | new_skb->mac.raw = new_skb->data; | ||
2061 | |||
2062 | netif_rx(new_skb); | ||
2063 | dev->last_rx = jiffies; | ||
2064 | } else { | ||
2065 | |||
2066 | printk(KERN_INFO "%s: no socket buffers available!\n", | ||
2067 | card->devname); | ||
2068 | } | ||
2069 | } | ||
2070 | |||
2071 | chdlc_priv_area->udp_pkt_lgth = 0; | ||
2072 | |||
2073 | return 0; | ||
2074 | } | ||
2075 | |||
2076 | /*============================================================================ | ||
2077 | * Initialize Receive and Transmit Buffers. | ||
2078 | */ | ||
2079 | |||
2080 | static void init_chdlc_tx_rx_buff(sdla_t* card, struct net_device *dev) | ||
2081 | { | ||
2082 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
2083 | CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config; | ||
2084 | CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config; | ||
2085 | char err; | ||
2086 | |||
2087 | mb->buffer_length = 0; | ||
2088 | mb->command = READ_CHDLC_CONFIGURATION; | ||
2089 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
2090 | |||
2091 | if(err != COMMAND_OK) { | ||
2092 | chdlc_error(card,err,mb); | ||
2093 | return; | ||
2094 | } | ||
2095 | |||
2096 | if(card->hw.type == SDLA_S514) { | ||
2097 | tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + | ||
2098 | (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> | ||
2099 | ptr_CHDLC_Tx_stat_el_cfg_struct)); | ||
2100 | rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + | ||
2101 | (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> | ||
2102 | ptr_CHDLC_Rx_stat_el_cfg_struct)); | ||
2103 | |||
2104 | /* Setup Head and Tails for buffers */ | ||
2105 | card->u.c.txbuf_base = (void *)(card->hw.dpmbase + | ||
2106 | tx_config->base_addr_Tx_status_elements); | ||
2107 | card->u.c.txbuf_last = | ||
2108 | (CHDLC_DATA_TX_STATUS_EL_STRUCT *) | ||
2109 | card->u.c.txbuf_base + | ||
2110 | (tx_config->number_Tx_status_elements - 1); | ||
2111 | |||
2112 | card->u.c.rxbuf_base = (void *)(card->hw.dpmbase + | ||
2113 | rx_config->base_addr_Rx_status_elements); | ||
2114 | card->u.c.rxbuf_last = | ||
2115 | (CHDLC_DATA_RX_STATUS_EL_STRUCT *) | ||
2116 | card->u.c.rxbuf_base + | ||
2117 | (rx_config->number_Rx_status_elements - 1); | ||
2118 | |||
2119 | /* Set up next pointer to be used */ | ||
2120 | card->u.c.txbuf = (void *)(card->hw.dpmbase + | ||
2121 | tx_config->next_Tx_status_element_to_use); | ||
2122 | card->u.c.rxmb = (void *)(card->hw.dpmbase + | ||
2123 | rx_config->next_Rx_status_element_to_use); | ||
2124 | } | ||
2125 | else { | ||
2126 | tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + | ||
2127 | (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> | ||
2128 | ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE)); | ||
2129 | |||
2130 | rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase + | ||
2131 | (((CHDLC_CONFIGURATION_STRUCT *)mb->data)-> | ||
2132 | ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE)); | ||
2133 | |||
2134 | /* Setup Head and Tails for buffers */ | ||
2135 | card->u.c.txbuf_base = (void *)(card->hw.dpmbase + | ||
2136 | (tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE)); | ||
2137 | card->u.c.txbuf_last = | ||
2138 | (CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base | ||
2139 | + (tx_config->number_Tx_status_elements - 1); | ||
2140 | card->u.c.rxbuf_base = (void *)(card->hw.dpmbase + | ||
2141 | (rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE)); | ||
2142 | card->u.c.rxbuf_last = | ||
2143 | (CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base | ||
2144 | + (rx_config->number_Rx_status_elements - 1); | ||
2145 | |||
2146 | /* Set up next pointer to be used */ | ||
2147 | card->u.c.txbuf = (void *)(card->hw.dpmbase + | ||
2148 | (tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE)); | ||
2149 | card->u.c.rxmb = (void *)(card->hw.dpmbase + | ||
2150 | (rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE)); | ||
2151 | } | ||
2152 | |||
2153 | /* Setup Actual Buffer Start and end addresses */ | ||
2154 | card->u.c.rx_base = rx_config->base_addr_Rx_buffer; | ||
2155 | card->u.c.rx_top = rx_config->end_addr_Rx_buffer; | ||
2156 | |||
2157 | } | ||
2158 | |||
2159 | /*============================================================================= | ||
2160 | * Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR | ||
2161 | * _TEST_COUNTER times. | ||
2162 | */ | ||
2163 | static int intr_test( sdla_t* card) | ||
2164 | { | ||
2165 | CHDLC_MAILBOX_STRUCT* mb = card->mbox; | ||
2166 | int err,i; | ||
2167 | |||
2168 | Intr_test_counter = 0; | ||
2169 | |||
2170 | /* The critical flag is unset because during initialization (if_open) | ||
2171 | * we want the interrupts to be enabled so that when the wpc_isr is | ||
2172 | * called it does not exit due to critical flag set. | ||
2173 | */ | ||
2174 | |||
2175 | err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE); | ||
2176 | |||
2177 | if (err == CMD_OK) { | ||
2178 | for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) { | ||
2179 | mb->buffer_length = 0; | ||
2180 | mb->command = READ_CHDLC_CODE_VERSION; | ||
2181 | err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT; | ||
2182 | } | ||
2183 | } | ||
2184 | else { | ||
2185 | return err; | ||
2186 | } | ||
2187 | |||
2188 | err = chdlc_set_intr_mode(card, 0); | ||
2189 | |||
2190 | if (err != CMD_OK) | ||
2191 | return err; | ||
2192 | |||
2193 | return 0; | ||
2194 | } | ||
2195 | |||
2196 | /*============================================================================== | ||
2197 | * Determine what type of UDP call it is. CPIPEAB ? | ||
2198 | */ | ||
2199 | static int udp_pkt_type(struct sk_buff *skb, sdla_t* card) | ||
2200 | { | ||
2201 | chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data; | ||
2202 | |||
2203 | if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) && | ||
2204 | (chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) && | ||
2205 | (chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) && | ||
2206 | (chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) { | ||
2207 | return UDP_CPIPE_TYPE; | ||
2208 | } | ||
2209 | else return UDP_INVALID_TYPE; | ||
2210 | } | ||
2211 | |||
2212 | /*============================================================================ | ||
2213 | * Set PORT state. | ||
2214 | */ | ||
2215 | static void port_set_state (sdla_t *card, int state) | ||
2216 | { | ||
2217 | struct net_device *dev = card->wandev.dev; | ||
2218 | chdlc_private_area_t *chdlc_priv_area = dev->priv; | ||
2219 | |||
2220 | if (card->u.c.state != state) | ||
2221 | { | ||
2222 | switch (state) | ||
2223 | { | ||
2224 | case WAN_CONNECTED: | ||
2225 | printk (KERN_INFO "%s: HDLC link connected!\n", | ||
2226 | card->devname); | ||
2227 | break; | ||
2228 | |||
2229 | case WAN_CONNECTING: | ||
2230 | printk (KERN_INFO "%s: HDLC link connecting...\n", | ||
2231 | card->devname); | ||
2232 | break; | ||
2233 | |||
2234 | case WAN_DISCONNECTED: | ||
2235 | printk (KERN_INFO "%s: HDLC link disconnected!\n", | ||
2236 | card->devname); | ||
2237 | break; | ||
2238 | } | ||
2239 | |||
2240 | card->wandev.state = card->u.c.state = state; | ||
2241 | chdlc_priv_area->common.state = state; | ||
2242 | } | ||
2243 | } | ||
2244 | |||
2245 | void s508_lock (sdla_t *card, unsigned long *smp_flags) | ||
2246 | { | ||
2247 | spin_lock_irqsave(&card->wandev.lock, *smp_flags); | ||
2248 | if (card->next){ | ||
2249 | /* It is ok to use spin_lock here, since we | ||
2250 | * already turned off interrupts */ | ||
2251 | spin_lock(&card->next->wandev.lock); | ||
2252 | } | ||
2253 | } | ||
2254 | |||
2255 | void s508_unlock (sdla_t *card, unsigned long *smp_flags) | ||
2256 | { | ||
2257 | if (card->next){ | ||
2258 | spin_unlock(&card->next->wandev.lock); | ||
2259 | } | ||
2260 | spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); | ||
2261 | } | ||
2262 | |||
2263 | |||
2264 | |||
2265 | /*=========================================================================== | ||
2266 | * config_chdlc | ||
2267 | * | ||
2268 | * Configure the chdlc protocol and enable communications. | ||
2269 | * | ||
2270 | * The if_open() function binds this function to the poll routine. | ||
2271 | * Therefore, this function will run every time the chdlc interface | ||
2272 | * is brought up. We cannot run this function from the if_open | ||
2273 | * because if_open does not have access to the remote IP address. | ||
2274 | * | ||
2275 | * If the communications are not enabled, proceed to configure | ||
2276 | * the card and enable communications. | ||
2277 | * | ||
2278 | * If the communications are enabled, it means that the interface | ||
2279 | * was shutdown by ether the user or driver. In this case, we | ||
2280 | * have to check that the IP addresses have not changed. If | ||
2281 | * the IP addresses have changed, we have to reconfigure the firmware | ||
2282 | * and update the changed IP addresses. Otherwise, just exit. | ||
2283 | * | ||
2284 | */ | ||
2285 | |||
2286 | static int config_chdlc (sdla_t *card) | ||
2287 | { | ||
2288 | struct net_device *dev = card->wandev.dev; | ||
2289 | SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; | ||
2290 | |||
2291 | if (card->u.c.comm_enabled){ | ||
2292 | chdlc_comm_disable(card); | ||
2293 | port_set_state(card, WAN_DISCONNECTED); | ||
2294 | } | ||
2295 | |||
2296 | if (set_chdlc_config(card)) { | ||
2297 | printk(KERN_INFO "%s: CHDLC Configuration Failed!\n", | ||
2298 | card->devname); | ||
2299 | return 0; | ||
2300 | } | ||
2301 | init_chdlc_tx_rx_buff(card, dev); | ||
2302 | |||
2303 | /* Set interrupt mode and mask */ | ||
2304 | if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME | | ||
2305 | APP_INT_ON_GLOBAL_EXCEP_COND | | ||
2306 | APP_INT_ON_TX_FRAME | | ||
2307 | APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){ | ||
2308 | printk (KERN_INFO "%s: Failed to set interrupt triggers!\n", | ||
2309 | card->devname); | ||
2310 | return 0; | ||
2311 | } | ||
2312 | |||
2313 | |||
2314 | /* Mask the Transmit and Timer interrupt */ | ||
2315 | flags->interrupt_info_struct.interrupt_permission &= | ||
2316 | ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER); | ||
2317 | |||
2318 | |||
2319 | if (chdlc_comm_enable(card) != 0) { | ||
2320 | printk(KERN_INFO "%s: Failed to enable chdlc communications!\n", | ||
2321 | card->devname); | ||
2322 | flags->interrupt_info_struct.interrupt_permission = 0; | ||
2323 | card->u.c.comm_enabled=0; | ||
2324 | chdlc_set_intr_mode(card,0); | ||
2325 | return 0; | ||
2326 | } | ||
2327 | |||
2328 | /* Initialize Rx/Tx buffer control fields */ | ||
2329 | port_set_state(card, WAN_CONNECTING); | ||
2330 | return 0; | ||
2331 | } | ||
2332 | |||
2333 | |||
2334 | static void send_ppp_term_request(struct net_device *dev) | ||
2335 | { | ||
2336 | struct sk_buff *new_skb; | ||
2337 | unsigned char *buf; | ||
2338 | |||
2339 | if ((new_skb = dev_alloc_skb(8)) != NULL) { | ||
2340 | /* copy data into new_skb */ | ||
2341 | |||
2342 | buf = skb_put(new_skb, 8); | ||
2343 | sprintf(buf,"%c%c%c%c%c%c%c%c", 0xFF,0x03,0xC0,0x21,0x05,0x98,0x00,0x07); | ||
2344 | |||
2345 | /* Decapsulate pkt and pass it up the protocol stack */ | ||
2346 | new_skb->protocol = htons(ETH_P_WAN_PPP); | ||
2347 | new_skb->dev = dev; | ||
2348 | new_skb->mac.raw = new_skb->data; | ||
2349 | |||
2350 | netif_rx(new_skb); | ||
2351 | dev->last_rx = jiffies; | ||
2352 | } | ||
2353 | } | ||
2354 | |||
2355 | |||
2356 | MODULE_LICENSE("GPL"); | ||
2357 | |||
2358 | /****** End ****************************************************************/ | ||
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index bad09ebdb50b..e0874cbfefea 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -6,7 +6,7 @@ menu "Wireless LAN (non-hamradio)" | |||
6 | depends on NETDEVICES | 6 | depends on NETDEVICES |
7 | 7 | ||
8 | config NET_RADIO | 8 | config NET_RADIO |
9 | bool "Wireless LAN drivers (non-hamradio)" | 9 | bool "Wireless LAN drivers (non-hamradio) & Wireless Extensions" |
10 | select WIRELESS_EXT | 10 | select WIRELESS_EXT |
11 | ---help--- | 11 | ---help--- |
12 | Support for wireless LANs and everything having to do with radio, | 12 | Support for wireless LANs and everything having to do with radio, |
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 108d9fed8f07..00764ddd74d8 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c | |||
@@ -3139,6 +3139,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) | |||
3139 | } | 3139 | } |
3140 | if ( status & EV_LINK ) { | 3140 | if ( status & EV_LINK ) { |
3141 | union iwreq_data wrqu; | 3141 | union iwreq_data wrqu; |
3142 | int scan_forceloss = 0; | ||
3142 | /* The link status has changed, if you want to put a | 3143 | /* The link status has changed, if you want to put a |
3143 | monitor hook in, do it here. (Remember that | 3144 | monitor hook in, do it here. (Remember that |
3144 | interrupts are still disabled!) | 3145 | interrupts are still disabled!) |
@@ -3157,7 +3158,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) | |||
3157 | code) */ | 3158 | code) */ |
3158 | #define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason | 3159 | #define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason |
3159 | code) */ | 3160 | code) */ |
3160 | #define ASSOCIATED 0x0400 /* Assocatied */ | 3161 | #define ASSOCIATED 0x0400 /* Associated */ |
3162 | #define REASSOCIATED 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */ | ||
3161 | #define RC_RESERVED 0 /* Reserved return code */ | 3163 | #define RC_RESERVED 0 /* Reserved return code */ |
3162 | #define RC_NOREASON 1 /* Unspecified reason */ | 3164 | #define RC_NOREASON 1 /* Unspecified reason */ |
3163 | #define RC_AUTHINV 2 /* Previous authentication invalid */ | 3165 | #define RC_AUTHINV 2 /* Previous authentication invalid */ |
@@ -3174,44 +3176,30 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs) | |||
3174 | leaving BSS */ | 3176 | leaving BSS */ |
3175 | #define RC_NOAUTH 9 /* Station requesting (Re)Association is not | 3177 | #define RC_NOAUTH 9 /* Station requesting (Re)Association is not |
3176 | Authenticated with the responding station */ | 3178 | Authenticated with the responding station */ |
3177 | if (newStatus != ASSOCIATED) { | 3179 | if (newStatus == FORCELOSS && apriv->scan_timeout > 0) |
3178 | if (auto_wep && !apriv->expires) { | 3180 | scan_forceloss = 1; |
3179 | apriv->expires = RUN_AT(3*HZ); | 3181 | if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) { |
3180 | wake_up_interruptible(&apriv->thr_wait); | ||
3181 | } | ||
3182 | } else { | ||
3183 | struct task_struct *task = apriv->task; | ||
3184 | if (auto_wep) | 3182 | if (auto_wep) |
3185 | apriv->expires = 0; | 3183 | apriv->expires = 0; |
3186 | if (task) | 3184 | if (apriv->task) |
3187 | wake_up_process (task); | 3185 | wake_up_process (apriv->task); |
3188 | set_bit(FLAG_UPDATE_UNI, &apriv->flags); | 3186 | set_bit(FLAG_UPDATE_UNI, &apriv->flags); |
3189 | set_bit(FLAG_UPDATE_MULTI, &apriv->flags); | 3187 | set_bit(FLAG_UPDATE_MULTI, &apriv->flags); |
3190 | } | 3188 | |
3191 | /* Question : is ASSOCIATED the only status | ||
3192 | * that is valid ? We want to catch handover | ||
3193 | * and reassociations as valid status | ||
3194 | * Jean II */ | ||
3195 | if(newStatus == ASSOCIATED) { | ||
3196 | #if 0 | ||
3197 | /* FIXME: Grabbing scan results here | ||
3198 | * seems to be too early??? Just wait for | ||
3199 | * timeout instead. */ | ||
3200 | if (apriv->scan_timeout > 0) { | ||
3201 | set_bit(JOB_SCAN_RESULTS, &apriv->flags); | ||
3202 | wake_up_interruptible(&apriv->thr_wait); | ||
3203 | } | ||
3204 | #endif | ||
3205 | if (down_trylock(&apriv->sem) != 0) { | 3189 | if (down_trylock(&apriv->sem) != 0) { |
3206 | set_bit(JOB_EVENT, &apriv->flags); | 3190 | set_bit(JOB_EVENT, &apriv->flags); |
3207 | wake_up_interruptible(&apriv->thr_wait); | 3191 | wake_up_interruptible(&apriv->thr_wait); |
3208 | } else | 3192 | } else |
3209 | airo_send_event(dev); | 3193 | airo_send_event(dev); |
3210 | } else { | 3194 | } else if (!scan_forceloss) { |
3211 | memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); | 3195 | if (auto_wep && !apriv->expires) { |
3212 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 3196 | apriv->expires = RUN_AT(3*HZ); |
3197 | wake_up_interruptible(&apriv->thr_wait); | ||
3198 | } | ||
3213 | 3199 | ||
3214 | /* Send event to user space */ | 3200 | /* Send event to user space */ |
3201 | memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); | ||
3202 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
3215 | wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL); | 3203 | wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL); |
3216 | } | 3204 | } |
3217 | } | 3205 | } |
@@ -7136,10 +7124,10 @@ static int airo_set_scan(struct net_device *dev, | |||
7136 | goto out; | 7124 | goto out; |
7137 | 7125 | ||
7138 | /* Initiate a scan command */ | 7126 | /* Initiate a scan command */ |
7127 | ai->scan_timeout = RUN_AT(3*HZ); | ||
7139 | memset(&cmd, 0, sizeof(cmd)); | 7128 | memset(&cmd, 0, sizeof(cmd)); |
7140 | cmd.cmd=CMD_LISTBSS; | 7129 | cmd.cmd=CMD_LISTBSS; |
7141 | issuecommand(ai, &cmd, &rsp); | 7130 | issuecommand(ai, &cmd, &rsp); |
7142 | ai->scan_timeout = RUN_AT(3*HZ); | ||
7143 | wake = 1; | 7131 | wake = 1; |
7144 | 7132 | ||
7145 | out: | 7133 | out: |
diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index a496460ce224..af0cbb6c5c0c 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c | |||
@@ -80,8 +80,8 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); | |||
80 | event handler. | 80 | event handler. |
81 | */ | 81 | */ |
82 | 82 | ||
83 | static void airo_config(dev_link_t *link); | 83 | static int airo_config(struct pcmcia_device *link); |
84 | static void airo_release(dev_link_t *link); | 84 | static void airo_release(struct pcmcia_device *link); |
85 | 85 | ||
86 | /* | 86 | /* |
87 | The attach() and detach() entry points are used to create and destroy | 87 | The attach() and detach() entry points are used to create and destroy |
@@ -101,10 +101,10 @@ static void airo_detach(struct pcmcia_device *p_dev); | |||
101 | /* | 101 | /* |
102 | A linked list of "instances" of the aironet device. Each actual | 102 | A linked list of "instances" of the aironet device. Each actual |
103 | PCMCIA card corresponds to one device instance, and is described | 103 | PCMCIA card corresponds to one device instance, and is described |
104 | by one dev_link_t structure (defined in ds.h). | 104 | by one struct pcmcia_device structure (defined in ds.h). |
105 | 105 | ||
106 | You may not want to use a linked list for this -- for example, the | 106 | You may not want to use a linked list for this -- for example, the |
107 | memory card driver uses an array of dev_link_t pointers, where minor | 107 | memory card driver uses an array of struct pcmcia_device pointers, where minor |
108 | device numbers are used to derive the corresponding array index. | 108 | device numbers are used to derive the corresponding array index. |
109 | */ | 109 | */ |
110 | 110 | ||
@@ -114,7 +114,7 @@ static void airo_detach(struct pcmcia_device *p_dev); | |||
114 | example, ethernet cards, modems). In other cases, there may be | 114 | example, ethernet cards, modems). In other cases, there may be |
115 | many actual or logical devices (SCSI adapters, memory cards with | 115 | many actual or logical devices (SCSI adapters, memory cards with |
116 | multiple partitions). The dev_node_t structures need to be kept | 116 | multiple partitions). The dev_node_t structures need to be kept |
117 | in a linked list starting at the 'dev' field of a dev_link_t | 117 | in a linked list starting at the 'dev' field of a struct pcmcia_device |
118 | structure. We allocate them in the card's private data structure, | 118 | structure. We allocate them in the card's private data structure, |
119 | because they generally shouldn't be allocated dynamically. | 119 | because they generally shouldn't be allocated dynamically. |
120 | 120 | ||
@@ -141,24 +141,16 @@ typedef struct local_info_t { | |||
141 | 141 | ||
142 | ======================================================================*/ | 142 | ======================================================================*/ |
143 | 143 | ||
144 | static int airo_attach(struct pcmcia_device *p_dev) | 144 | static int airo_probe(struct pcmcia_device *p_dev) |
145 | { | 145 | { |
146 | dev_link_t *link; | ||
147 | local_info_t *local; | 146 | local_info_t *local; |
148 | 147 | ||
149 | DEBUG(0, "airo_attach()\n"); | 148 | DEBUG(0, "airo_attach()\n"); |
150 | 149 | ||
151 | /* Initialize the dev_link_t structure */ | ||
152 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); | ||
153 | if (!link) { | ||
154 | printk(KERN_ERR "airo_cs: no memory for new device\n"); | ||
155 | return -ENOMEM; | ||
156 | } | ||
157 | |||
158 | /* Interrupt setup */ | 150 | /* Interrupt setup */ |
159 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 151 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
160 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 152 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
161 | link->irq.Handler = NULL; | 153 | p_dev->irq.Handler = NULL; |
162 | 154 | ||
163 | /* | 155 | /* |
164 | General socket configuration defaults can go here. In this | 156 | General socket configuration defaults can go here. In this |
@@ -167,26 +159,18 @@ static int airo_attach(struct pcmcia_device *p_dev) | |||
167 | and attributes of IO windows) are fixed by the nature of the | 159 | and attributes of IO windows) are fixed by the nature of the |
168 | device, and can be hard-wired here. | 160 | device, and can be hard-wired here. |
169 | */ | 161 | */ |
170 | link->conf.Attributes = 0; | 162 | p_dev->conf.Attributes = 0; |
171 | link->conf.Vcc = 50; | 163 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
172 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
173 | 164 | ||
174 | /* Allocate space for private device-specific data */ | 165 | /* Allocate space for private device-specific data */ |
175 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); | 166 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); |
176 | if (!local) { | 167 | if (!local) { |
177 | printk(KERN_ERR "airo_cs: no memory for new device\n"); | 168 | printk(KERN_ERR "airo_cs: no memory for new device\n"); |
178 | kfree (link); | ||
179 | return -ENOMEM; | 169 | return -ENOMEM; |
180 | } | 170 | } |
181 | link->priv = local; | 171 | p_dev->priv = local; |
182 | 172 | ||
183 | link->handle = p_dev; | 173 | return airo_config(p_dev); |
184 | p_dev->instance = link; | ||
185 | |||
186 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
187 | airo_config(link); | ||
188 | |||
189 | return 0; | ||
190 | } /* airo_attach */ | 174 | } /* airo_attach */ |
191 | 175 | ||
192 | /*====================================================================== | 176 | /*====================================================================== |
@@ -198,14 +182,11 @@ static int airo_attach(struct pcmcia_device *p_dev) | |||
198 | 182 | ||
199 | ======================================================================*/ | 183 | ======================================================================*/ |
200 | 184 | ||
201 | static void airo_detach(struct pcmcia_device *p_dev) | 185 | static void airo_detach(struct pcmcia_device *link) |
202 | { | 186 | { |
203 | dev_link_t *link = dev_to_instance(p_dev); | ||
204 | |||
205 | DEBUG(0, "airo_detach(0x%p)\n", link); | 187 | DEBUG(0, "airo_detach(0x%p)\n", link); |
206 | 188 | ||
207 | if (link->state & DEV_CONFIG) | 189 | airo_release(link); |
208 | airo_release(link); | ||
209 | 190 | ||
210 | if ( ((local_info_t*)link->priv)->eth_dev ) { | 191 | if ( ((local_info_t*)link->priv)->eth_dev ) { |
211 | stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); | 192 | stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); |
@@ -213,7 +194,6 @@ static void airo_detach(struct pcmcia_device *p_dev) | |||
213 | ((local_info_t*)link->priv)->eth_dev = NULL; | 194 | ((local_info_t*)link->priv)->eth_dev = NULL; |
214 | 195 | ||
215 | kfree(link->priv); | 196 | kfree(link->priv); |
216 | kfree(link); | ||
217 | } /* airo_detach */ | 197 | } /* airo_detach */ |
218 | 198 | ||
219 | /*====================================================================== | 199 | /*====================================================================== |
@@ -227,9 +207,8 @@ static void airo_detach(struct pcmcia_device *p_dev) | |||
227 | #define CS_CHECK(fn, ret) \ | 207 | #define CS_CHECK(fn, ret) \ |
228 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 208 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
229 | 209 | ||
230 | static void airo_config(dev_link_t *link) | 210 | static int airo_config(struct pcmcia_device *link) |
231 | { | 211 | { |
232 | client_handle_t handle; | ||
233 | tuple_t tuple; | 212 | tuple_t tuple; |
234 | cisparse_t parse; | 213 | cisparse_t parse; |
235 | local_info_t *dev; | 214 | local_info_t *dev; |
@@ -237,8 +216,7 @@ static void airo_config(dev_link_t *link) | |||
237 | u_char buf[64]; | 216 | u_char buf[64]; |
238 | win_req_t req; | 217 | win_req_t req; |
239 | memreq_t map; | 218 | memreq_t map; |
240 | 219 | ||
241 | handle = link->handle; | ||
242 | dev = link->priv; | 220 | dev = link->priv; |
243 | 221 | ||
244 | DEBUG(0, "airo_config(0x%p)\n", link); | 222 | DEBUG(0, "airo_config(0x%p)\n", link); |
@@ -252,15 +230,12 @@ static void airo_config(dev_link_t *link) | |||
252 | tuple.TupleData = buf; | 230 | tuple.TupleData = buf; |
253 | tuple.TupleDataMax = sizeof(buf); | 231 | tuple.TupleDataMax = sizeof(buf); |
254 | tuple.TupleOffset = 0; | 232 | tuple.TupleOffset = 0; |
255 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 233 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
256 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 234 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
257 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 235 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
258 | link->conf.ConfigBase = parse.config.base; | 236 | link->conf.ConfigBase = parse.config.base; |
259 | link->conf.Present = parse.config.rmask[0]; | 237 | link->conf.Present = parse.config.rmask[0]; |
260 | 238 | ||
261 | /* Configure card */ | ||
262 | link->state |= DEV_CONFIG; | ||
263 | |||
264 | /* | 239 | /* |
265 | In this loop, we scan the CIS for configuration table entries, | 240 | In this loop, we scan the CIS for configuration table entries, |
266 | each of which describes a valid card configuration, including | 241 | each of which describes a valid card configuration, including |
@@ -274,12 +249,12 @@ static void airo_config(dev_link_t *link) | |||
274 | will only use the CIS to fill in implementation-defined details. | 249 | will only use the CIS to fill in implementation-defined details. |
275 | */ | 250 | */ |
276 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 251 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
277 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 252 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
278 | while (1) { | 253 | while (1) { |
279 | cistpl_cftable_entry_t dflt = { 0 }; | 254 | cistpl_cftable_entry_t dflt = { 0 }; |
280 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 255 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
281 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | 256 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || |
282 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0) | 257 | pcmcia_parse_tuple(link, &tuple, &parse) != 0) |
283 | goto next_entry; | 258 | goto next_entry; |
284 | 259 | ||
285 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; | 260 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; |
@@ -294,16 +269,11 @@ static void airo_config(dev_link_t *link) | |||
294 | 269 | ||
295 | /* Use power settings for Vcc and Vpp if present */ | 270 | /* Use power settings for Vcc and Vpp if present */ |
296 | /* Note that the CIS values need to be rescaled */ | 271 | /* Note that the CIS values need to be rescaled */ |
297 | if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) | ||
298 | link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000; | ||
299 | else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) | ||
300 | link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000; | ||
301 | |||
302 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | 272 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) |
303 | link->conf.Vpp1 = link->conf.Vpp2 = | 273 | link->conf.Vpp = |
304 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | 274 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; |
305 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) | 275 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) |
306 | link->conf.Vpp1 = link->conf.Vpp2 = | 276 | link->conf.Vpp = |
307 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; | 277 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; |
308 | 278 | ||
309 | /* Do we need to allocate an interrupt? */ | 279 | /* Do we need to allocate an interrupt? */ |
@@ -329,12 +299,12 @@ static void airo_config(dev_link_t *link) | |||
329 | } | 299 | } |
330 | 300 | ||
331 | /* This reserves IO space but doesn't actually enable it */ | 301 | /* This reserves IO space but doesn't actually enable it */ |
332 | if (pcmcia_request_io(link->handle, &link->io) != 0) | 302 | if (pcmcia_request_io(link, &link->io) != 0) |
333 | goto next_entry; | 303 | goto next_entry; |
334 | 304 | ||
335 | /* | 305 | /* |
336 | Now set up a common memory window, if needed. There is room | 306 | Now set up a common memory window, if needed. There is room |
337 | in the dev_link_t structure for one memory window handle, | 307 | in the struct pcmcia_device structure for one memory window handle, |
338 | but if the base addresses need to be saved, or if multiple | 308 | but if the base addresses need to be saved, or if multiple |
339 | windows are needed, the info should go in the private data | 309 | windows are needed, the info should go in the private data |
340 | structure for this device. | 310 | structure for this device. |
@@ -350,7 +320,7 @@ static void airo_config(dev_link_t *link) | |||
350 | req.Base = mem->win[0].host_addr; | 320 | req.Base = mem->win[0].host_addr; |
351 | req.Size = mem->win[0].len; | 321 | req.Size = mem->win[0].len; |
352 | req.AccessSpeed = 0; | 322 | req.AccessSpeed = 0; |
353 | if (pcmcia_request_window(&link->handle, &req, &link->win) != 0) | 323 | if (pcmcia_request_window(&link, &req, &link->win) != 0) |
354 | goto next_entry; | 324 | goto next_entry; |
355 | map.Page = 0; map.CardOffset = mem->win[0].card_addr; | 325 | map.Page = 0; map.CardOffset = mem->win[0].card_addr; |
356 | if (pcmcia_map_mem_page(link->win, &map) != 0) | 326 | if (pcmcia_map_mem_page(link->win, &map) != 0) |
@@ -360,7 +330,7 @@ static void airo_config(dev_link_t *link) | |||
360 | break; | 330 | break; |
361 | 331 | ||
362 | next_entry: | 332 | next_entry: |
363 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); | 333 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); |
364 | } | 334 | } |
365 | 335 | ||
366 | /* | 336 | /* |
@@ -369,33 +339,32 @@ static void airo_config(dev_link_t *link) | |||
369 | irq structure is initialized. | 339 | irq structure is initialized. |
370 | */ | 340 | */ |
371 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | 341 | if (link->conf.Attributes & CONF_ENABLE_IRQ) |
372 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 342 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
373 | 343 | ||
374 | /* | 344 | /* |
375 | This actually configures the PCMCIA socket -- setting up | 345 | This actually configures the PCMCIA socket -- setting up |
376 | the I/O windows and the interrupt mapping, and putting the | 346 | the I/O windows and the interrupt mapping, and putting the |
377 | card and host interface into "Memory and IO" mode. | 347 | card and host interface into "Memory and IO" mode. |
378 | */ | 348 | */ |
379 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 349 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
380 | ((local_info_t*)link->priv)->eth_dev = | 350 | ((local_info_t*)link->priv)->eth_dev = |
381 | init_airo_card( link->irq.AssignedIRQ, | 351 | init_airo_card( link->irq.AssignedIRQ, |
382 | link->io.BasePort1, 1, &handle_to_dev(handle) ); | 352 | link->io.BasePort1, 1, &handle_to_dev(link) ); |
383 | if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed; | 353 | if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed; |
384 | 354 | ||
385 | /* | 355 | /* |
386 | At this point, the dev_node_t structure(s) need to be | 356 | At this point, the dev_node_t structure(s) need to be |
387 | initialized and arranged in a linked list at link->dev. | 357 | initialized and arranged in a linked list at link->dev_node. |
388 | */ | 358 | */ |
389 | strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); | 359 | strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); |
390 | dev->node.major = dev->node.minor = 0; | 360 | dev->node.major = dev->node.minor = 0; |
391 | link->dev = &dev->node; | 361 | link->dev_node = &dev->node; |
392 | 362 | ||
393 | /* Finally, report what we've done */ | 363 | /* Finally, report what we've done */ |
394 | printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", | 364 | printk(KERN_INFO "%s: index 0x%02x: ", |
395 | dev->node.dev_name, link->conf.ConfigIndex, | 365 | dev->node.dev_name, link->conf.ConfigIndex); |
396 | link->conf.Vcc/10, link->conf.Vcc%10); | 366 | if (link->conf.Vpp) |
397 | if (link->conf.Vpp1) | 367 | printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); |
398 | printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); | ||
399 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | 368 | if (link->conf.Attributes & CONF_ENABLE_IRQ) |
400 | printk(", irq %d", link->irq.AssignedIRQ); | 369 | printk(", irq %d", link->irq.AssignedIRQ); |
401 | if (link->io.NumPorts1) | 370 | if (link->io.NumPorts1) |
@@ -408,14 +377,12 @@ static void airo_config(dev_link_t *link) | |||
408 | printk(", mem 0x%06lx-0x%06lx", req.Base, | 377 | printk(", mem 0x%06lx-0x%06lx", req.Base, |
409 | req.Base+req.Size-1); | 378 | req.Base+req.Size-1); |
410 | printk("\n"); | 379 | printk("\n"); |
411 | 380 | return 0; | |
412 | link->state &= ~DEV_CONFIG_PENDING; | 381 | |
413 | return; | ||
414 | |||
415 | cs_failed: | 382 | cs_failed: |
416 | cs_error(link->handle, last_fn, last_ret); | 383 | cs_error(link, last_fn, last_ret); |
417 | airo_release(link); | 384 | airo_release(link); |
418 | 385 | return -ENODEV; | |
419 | } /* airo_config */ | 386 | } /* airo_config */ |
420 | 387 | ||
421 | /*====================================================================== | 388 | /*====================================================================== |
@@ -426,51 +393,26 @@ static void airo_config(dev_link_t *link) | |||
426 | 393 | ||
427 | ======================================================================*/ | 394 | ======================================================================*/ |
428 | 395 | ||
429 | static void airo_release(dev_link_t *link) | 396 | static void airo_release(struct pcmcia_device *link) |
430 | { | 397 | { |
431 | DEBUG(0, "airo_release(0x%p)\n", link); | 398 | DEBUG(0, "airo_release(0x%p)\n", link); |
432 | 399 | pcmcia_disable_device(link); | |
433 | /* Unlink the device chain */ | ||
434 | link->dev = NULL; | ||
435 | |||
436 | /* | ||
437 | In a normal driver, additional code may be needed to release | ||
438 | other kernel data structures associated with this device. | ||
439 | */ | ||
440 | |||
441 | /* Don't bother checking to see if these succeed or not */ | ||
442 | if (link->win) | ||
443 | pcmcia_release_window(link->win); | ||
444 | pcmcia_release_configuration(link->handle); | ||
445 | if (link->io.NumPorts1) | ||
446 | pcmcia_release_io(link->handle, &link->io); | ||
447 | if (link->irq.AssignedIRQ) | ||
448 | pcmcia_release_irq(link->handle, &link->irq); | ||
449 | link->state &= ~DEV_CONFIG; | ||
450 | } | 400 | } |
451 | 401 | ||
452 | static int airo_suspend(struct pcmcia_device *p_dev) | 402 | static int airo_suspend(struct pcmcia_device *link) |
453 | { | 403 | { |
454 | dev_link_t *link = dev_to_instance(p_dev); | ||
455 | local_info_t *local = link->priv; | 404 | local_info_t *local = link->priv; |
456 | 405 | ||
457 | link->state |= DEV_SUSPEND; | 406 | netif_device_detach(local->eth_dev); |
458 | if (link->state & DEV_CONFIG) { | ||
459 | netif_device_detach(local->eth_dev); | ||
460 | pcmcia_release_configuration(link->handle); | ||
461 | } | ||
462 | 407 | ||
463 | return 0; | 408 | return 0; |
464 | } | 409 | } |
465 | 410 | ||
466 | static int airo_resume(struct pcmcia_device *p_dev) | 411 | static int airo_resume(struct pcmcia_device *link) |
467 | { | 412 | { |
468 | dev_link_t *link = dev_to_instance(p_dev); | ||
469 | local_info_t *local = link->priv; | 413 | local_info_t *local = link->priv; |
470 | 414 | ||
471 | link->state &= ~DEV_SUSPEND; | 415 | if (link->open) { |
472 | if (link->state & DEV_CONFIG) { | ||
473 | pcmcia_request_configuration(link->handle, &link->conf); | ||
474 | reset_airo_card(local->eth_dev); | 416 | reset_airo_card(local->eth_dev); |
475 | netif_device_attach(local->eth_dev); | 417 | netif_device_attach(local->eth_dev); |
476 | } | 418 | } |
@@ -492,7 +434,7 @@ static struct pcmcia_driver airo_driver = { | |||
492 | .drv = { | 434 | .drv = { |
493 | .name = "airo_cs", | 435 | .name = "airo_cs", |
494 | }, | 436 | }, |
495 | .probe = airo_attach, | 437 | .probe = airo_probe, |
496 | .remove = airo_detach, | 438 | .remove = airo_detach, |
497 | .id_table = airo_ids, | 439 | .id_table = airo_ids, |
498 | .suspend = airo_suspend, | 440 | .suspend = airo_suspend, |
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 87afa6878f26..8606c88886fc 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
@@ -3463,6 +3463,7 @@ static void atmel_command_irq(struct atmel_private *priv) | |||
3463 | u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET)); | 3463 | u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET)); |
3464 | u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET)); | 3464 | u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET)); |
3465 | int fast_scan; | 3465 | int fast_scan; |
3466 | union iwreq_data wrqu; | ||
3466 | 3467 | ||
3467 | if (status == CMD_STATUS_IDLE || | 3468 | if (status == CMD_STATUS_IDLE || |
3468 | status == CMD_STATUS_IN_PROGRESS) | 3469 | status == CMD_STATUS_IN_PROGRESS) |
@@ -3487,6 +3488,7 @@ static void atmel_command_irq(struct atmel_private *priv) | |||
3487 | atmel_scan(priv, 1); | 3488 | atmel_scan(priv, 1); |
3488 | } else { | 3489 | } else { |
3489 | int bss_index = retrieve_bss(priv); | 3490 | int bss_index = retrieve_bss(priv); |
3491 | int notify_scan_complete = 1; | ||
3490 | if (bss_index != -1) { | 3492 | if (bss_index != -1) { |
3491 | atmel_join_bss(priv, bss_index); | 3493 | atmel_join_bss(priv, bss_index); |
3492 | } else if (priv->operating_mode == IW_MODE_ADHOC && | 3494 | } else if (priv->operating_mode == IW_MODE_ADHOC && |
@@ -3495,8 +3497,14 @@ static void atmel_command_irq(struct atmel_private *priv) | |||
3495 | } else { | 3497 | } else { |
3496 | priv->fast_scan = !fast_scan; | 3498 | priv->fast_scan = !fast_scan; |
3497 | atmel_scan(priv, 1); | 3499 | atmel_scan(priv, 1); |
3500 | notify_scan_complete = 0; | ||
3498 | } | 3501 | } |
3499 | priv->site_survey_state = SITE_SURVEY_COMPLETED; | 3502 | priv->site_survey_state = SITE_SURVEY_COMPLETED; |
3503 | if (notify_scan_complete) { | ||
3504 | wrqu.data.length = 0; | ||
3505 | wrqu.data.flags = 0; | ||
3506 | wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); | ||
3507 | } | ||
3500 | } | 3508 | } |
3501 | break; | 3509 | break; |
3502 | 3510 | ||
@@ -3509,6 +3517,9 @@ static void atmel_command_irq(struct atmel_private *priv) | |||
3509 | priv->site_survey_state = SITE_SURVEY_COMPLETED; | 3517 | priv->site_survey_state = SITE_SURVEY_COMPLETED; |
3510 | if (priv->station_is_associated) { | 3518 | if (priv->station_is_associated) { |
3511 | atmel_enter_state(priv, STATION_STATE_READY); | 3519 | atmel_enter_state(priv, STATION_STATE_READY); |
3520 | wrqu.data.length = 0; | ||
3521 | wrqu.data.flags = 0; | ||
3522 | wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); | ||
3512 | } else { | 3523 | } else { |
3513 | atmel_scan(priv, 1); | 3524 | atmel_scan(priv, 1); |
3514 | } | 3525 | } |
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index d6f4a5a3e55a..26bf1127524d 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c | |||
@@ -91,8 +91,8 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards"); | |||
91 | event handler. | 91 | event handler. |
92 | */ | 92 | */ |
93 | 93 | ||
94 | static void atmel_config(dev_link_t *link); | 94 | static int atmel_config(struct pcmcia_device *link); |
95 | static void atmel_release(dev_link_t *link); | 95 | static void atmel_release(struct pcmcia_device *link); |
96 | 96 | ||
97 | /* | 97 | /* |
98 | The attach() and detach() entry points are used to create and destroy | 98 | The attach() and detach() entry points are used to create and destroy |
@@ -112,10 +112,10 @@ static void atmel_detach(struct pcmcia_device *p_dev); | |||
112 | /* | 112 | /* |
113 | A linked list of "instances" of the atmelnet device. Each actual | 113 | A linked list of "instances" of the atmelnet device. Each actual |
114 | PCMCIA card corresponds to one device instance, and is described | 114 | PCMCIA card corresponds to one device instance, and is described |
115 | by one dev_link_t structure (defined in ds.h). | 115 | by one struct pcmcia_device structure (defined in ds.h). |
116 | 116 | ||
117 | You may not want to use a linked list for this -- for example, the | 117 | You may not want to use a linked list for this -- for example, the |
118 | memory card driver uses an array of dev_link_t pointers, where minor | 118 | memory card driver uses an array of struct pcmcia_device pointers, where minor |
119 | device numbers are used to derive the corresponding array index. | 119 | device numbers are used to derive the corresponding array index. |
120 | */ | 120 | */ |
121 | 121 | ||
@@ -125,7 +125,7 @@ static void atmel_detach(struct pcmcia_device *p_dev); | |||
125 | example, ethernet cards, modems). In other cases, there may be | 125 | example, ethernet cards, modems). In other cases, there may be |
126 | many actual or logical devices (SCSI adapters, memory cards with | 126 | many actual or logical devices (SCSI adapters, memory cards with |
127 | multiple partitions). The dev_node_t structures need to be kept | 127 | multiple partitions). The dev_node_t structures need to be kept |
128 | in a linked list starting at the 'dev' field of a dev_link_t | 128 | in a linked list starting at the 'dev' field of a struct pcmcia_device |
129 | structure. We allocate them in the card's private data structure, | 129 | structure. We allocate them in the card's private data structure, |
130 | because they generally shouldn't be allocated dynamically. | 130 | because they generally shouldn't be allocated dynamically. |
131 | 131 | ||
@@ -152,24 +152,16 @@ typedef struct local_info_t { | |||
152 | 152 | ||
153 | ======================================================================*/ | 153 | ======================================================================*/ |
154 | 154 | ||
155 | static int atmel_attach(struct pcmcia_device *p_dev) | 155 | static int atmel_probe(struct pcmcia_device *p_dev) |
156 | { | 156 | { |
157 | dev_link_t *link; | ||
158 | local_info_t *local; | 157 | local_info_t *local; |
159 | 158 | ||
160 | DEBUG(0, "atmel_attach()\n"); | 159 | DEBUG(0, "atmel_attach()\n"); |
161 | 160 | ||
162 | /* Initialize the dev_link_t structure */ | ||
163 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); | ||
164 | if (!link) { | ||
165 | printk(KERN_ERR "atmel_cs: no memory for new device\n"); | ||
166 | return -ENOMEM; | ||
167 | } | ||
168 | |||
169 | /* Interrupt setup */ | 161 | /* Interrupt setup */ |
170 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 162 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
171 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 163 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
172 | link->irq.Handler = NULL; | 164 | p_dev->irq.Handler = NULL; |
173 | 165 | ||
174 | /* | 166 | /* |
175 | General socket configuration defaults can go here. In this | 167 | General socket configuration defaults can go here. In this |
@@ -178,26 +170,18 @@ static int atmel_attach(struct pcmcia_device *p_dev) | |||
178 | and attributes of IO windows) are fixed by the nature of the | 170 | and attributes of IO windows) are fixed by the nature of the |
179 | device, and can be hard-wired here. | 171 | device, and can be hard-wired here. |
180 | */ | 172 | */ |
181 | link->conf.Attributes = 0; | 173 | p_dev->conf.Attributes = 0; |
182 | link->conf.Vcc = 50; | 174 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
183 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
184 | 175 | ||
185 | /* Allocate space for private device-specific data */ | 176 | /* Allocate space for private device-specific data */ |
186 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); | 177 | local = kzalloc(sizeof(local_info_t), GFP_KERNEL); |
187 | if (!local) { | 178 | if (!local) { |
188 | printk(KERN_ERR "atmel_cs: no memory for new device\n"); | 179 | printk(KERN_ERR "atmel_cs: no memory for new device\n"); |
189 | kfree (link); | ||
190 | return -ENOMEM; | 180 | return -ENOMEM; |
191 | } | 181 | } |
192 | link->priv = local; | 182 | p_dev->priv = local; |
193 | 183 | ||
194 | link->handle = p_dev; | 184 | return atmel_config(p_dev); |
195 | p_dev->instance = link; | ||
196 | |||
197 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
198 | atmel_config(link); | ||
199 | |||
200 | return 0; | ||
201 | } /* atmel_attach */ | 185 | } /* atmel_attach */ |
202 | 186 | ||
203 | /*====================================================================== | 187 | /*====================================================================== |
@@ -209,17 +193,13 @@ static int atmel_attach(struct pcmcia_device *p_dev) | |||
209 | 193 | ||
210 | ======================================================================*/ | 194 | ======================================================================*/ |
211 | 195 | ||
212 | static void atmel_detach(struct pcmcia_device *p_dev) | 196 | static void atmel_detach(struct pcmcia_device *link) |
213 | { | 197 | { |
214 | dev_link_t *link = dev_to_instance(p_dev); | ||
215 | |||
216 | DEBUG(0, "atmel_detach(0x%p)\n", link); | 198 | DEBUG(0, "atmel_detach(0x%p)\n", link); |
217 | 199 | ||
218 | if (link->state & DEV_CONFIG) | 200 | atmel_release(link); |
219 | atmel_release(link); | ||
220 | 201 | ||
221 | kfree(link->priv); | 202 | kfree(link->priv); |
222 | kfree(link); | ||
223 | } | 203 | } |
224 | 204 | ||
225 | /*====================================================================== | 205 | /*====================================================================== |
@@ -236,19 +216,17 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
236 | /* Call-back function to interrogate PCMCIA-specific information | 216 | /* Call-back function to interrogate PCMCIA-specific information |
237 | about the current existance of the card */ | 217 | about the current existance of the card */ |
238 | static int card_present(void *arg) | 218 | static int card_present(void *arg) |
239 | { | 219 | { |
240 | dev_link_t *link = (dev_link_t *)arg; | 220 | struct pcmcia_device *link = (struct pcmcia_device *)arg; |
241 | if (link->state & DEV_SUSPEND) | 221 | |
242 | return 0; | 222 | if (pcmcia_dev_present(link)) |
243 | else if (link->state & DEV_PRESENT) | ||
244 | return 1; | 223 | return 1; |
245 | 224 | ||
246 | return 0; | 225 | return 0; |
247 | } | 226 | } |
248 | 227 | ||
249 | static void atmel_config(dev_link_t *link) | 228 | static int atmel_config(struct pcmcia_device *link) |
250 | { | 229 | { |
251 | client_handle_t handle; | ||
252 | tuple_t tuple; | 230 | tuple_t tuple; |
253 | cisparse_t parse; | 231 | cisparse_t parse; |
254 | local_info_t *dev; | 232 | local_info_t *dev; |
@@ -256,9 +234,8 @@ static void atmel_config(dev_link_t *link) | |||
256 | u_char buf[64]; | 234 | u_char buf[64]; |
257 | struct pcmcia_device_id *did; | 235 | struct pcmcia_device_id *did; |
258 | 236 | ||
259 | handle = link->handle; | ||
260 | dev = link->priv; | 237 | dev = link->priv; |
261 | did = handle_to_dev(handle).driver_data; | 238 | did = handle_to_dev(link).driver_data; |
262 | 239 | ||
263 | DEBUG(0, "atmel_config(0x%p)\n", link); | 240 | DEBUG(0, "atmel_config(0x%p)\n", link); |
264 | 241 | ||
@@ -272,15 +249,12 @@ static void atmel_config(dev_link_t *link) | |||
272 | registers. | 249 | registers. |
273 | */ | 250 | */ |
274 | tuple.DesiredTuple = CISTPL_CONFIG; | 251 | tuple.DesiredTuple = CISTPL_CONFIG; |
275 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 252 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
276 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 253 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
277 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 254 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
278 | link->conf.ConfigBase = parse.config.base; | 255 | link->conf.ConfigBase = parse.config.base; |
279 | link->conf.Present = parse.config.rmask[0]; | 256 | link->conf.Present = parse.config.rmask[0]; |
280 | 257 | ||
281 | /* Configure card */ | ||
282 | link->state |= DEV_CONFIG; | ||
283 | |||
284 | /* | 258 | /* |
285 | In this loop, we scan the CIS for configuration table entries, | 259 | In this loop, we scan the CIS for configuration table entries, |
286 | each of which describes a valid card configuration, including | 260 | each of which describes a valid card configuration, including |
@@ -294,12 +268,12 @@ static void atmel_config(dev_link_t *link) | |||
294 | will only use the CIS to fill in implementation-defined details. | 268 | will only use the CIS to fill in implementation-defined details. |
295 | */ | 269 | */ |
296 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 270 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
297 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 271 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
298 | while (1) { | 272 | while (1) { |
299 | cistpl_cftable_entry_t dflt = { 0 }; | 273 | cistpl_cftable_entry_t dflt = { 0 }; |
300 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 274 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
301 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | 275 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || |
302 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0) | 276 | pcmcia_parse_tuple(link, &tuple, &parse) != 0) |
303 | goto next_entry; | 277 | goto next_entry; |
304 | 278 | ||
305 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; | 279 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; |
@@ -314,16 +288,11 @@ static void atmel_config(dev_link_t *link) | |||
314 | 288 | ||
315 | /* Use power settings for Vcc and Vpp if present */ | 289 | /* Use power settings for Vcc and Vpp if present */ |
316 | /* Note that the CIS values need to be rescaled */ | 290 | /* Note that the CIS values need to be rescaled */ |
317 | if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) | ||
318 | link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000; | ||
319 | else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) | ||
320 | link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000; | ||
321 | |||
322 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) | 291 | if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) |
323 | link->conf.Vpp1 = link->conf.Vpp2 = | 292 | link->conf.Vpp = |
324 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; | 293 | cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; |
325 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) | 294 | else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) |
326 | link->conf.Vpp1 = link->conf.Vpp2 = | 295 | link->conf.Vpp = |
327 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; | 296 | dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; |
328 | 297 | ||
329 | /* Do we need to allocate an interrupt? */ | 298 | /* Do we need to allocate an interrupt? */ |
@@ -349,14 +318,14 @@ static void atmel_config(dev_link_t *link) | |||
349 | } | 318 | } |
350 | 319 | ||
351 | /* This reserves IO space but doesn't actually enable it */ | 320 | /* This reserves IO space but doesn't actually enable it */ |
352 | if (pcmcia_request_io(link->handle, &link->io) != 0) | 321 | if (pcmcia_request_io(link, &link->io) != 0) |
353 | goto next_entry; | 322 | goto next_entry; |
354 | 323 | ||
355 | /* If we got this far, we're cool! */ | 324 | /* If we got this far, we're cool! */ |
356 | break; | 325 | break; |
357 | 326 | ||
358 | next_entry: | 327 | next_entry: |
359 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple)); | 328 | CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); |
360 | } | 329 | } |
361 | 330 | ||
362 | /* | 331 | /* |
@@ -365,14 +334,14 @@ static void atmel_config(dev_link_t *link) | |||
365 | irq structure is initialized. | 334 | irq structure is initialized. |
366 | */ | 335 | */ |
367 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | 336 | if (link->conf.Attributes & CONF_ENABLE_IRQ) |
368 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 337 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
369 | 338 | ||
370 | /* | 339 | /* |
371 | This actually configures the PCMCIA socket -- setting up | 340 | This actually configures the PCMCIA socket -- setting up |
372 | the I/O windows and the interrupt mapping, and putting the | 341 | the I/O windows and the interrupt mapping, and putting the |
373 | card and host interface into "Memory and IO" mode. | 342 | card and host interface into "Memory and IO" mode. |
374 | */ | 343 | */ |
375 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 344 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
376 | 345 | ||
377 | if (link->irq.AssignedIRQ == 0) { | 346 | if (link->irq.AssignedIRQ == 0) { |
378 | printk(KERN_ALERT | 347 | printk(KERN_ALERT |
@@ -384,7 +353,7 @@ static void atmel_config(dev_link_t *link) | |||
384 | init_atmel_card(link->irq.AssignedIRQ, | 353 | init_atmel_card(link->irq.AssignedIRQ, |
385 | link->io.BasePort1, | 354 | link->io.BasePort1, |
386 | did ? did->driver_info : ATMEL_FW_TYPE_NONE, | 355 | did ? did->driver_info : ATMEL_FW_TYPE_NONE, |
387 | &handle_to_dev(handle), | 356 | &handle_to_dev(link), |
388 | card_present, | 357 | card_present, |
389 | link); | 358 | link); |
390 | if (!((local_info_t*)link->priv)->eth_dev) | 359 | if (!((local_info_t*)link->priv)->eth_dev) |
@@ -393,18 +362,18 @@ static void atmel_config(dev_link_t *link) | |||
393 | 362 | ||
394 | /* | 363 | /* |
395 | At this point, the dev_node_t structure(s) need to be | 364 | At this point, the dev_node_t structure(s) need to be |
396 | initialized and arranged in a linked list at link->dev. | 365 | initialized and arranged in a linked list at link->dev_node. |
397 | */ | 366 | */ |
398 | strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); | 367 | strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); |
399 | dev->node.major = dev->node.minor = 0; | 368 | dev->node.major = dev->node.minor = 0; |
400 | link->dev = &dev->node; | 369 | link->dev_node = &dev->node; |
401 | 370 | ||
402 | link->state &= ~DEV_CONFIG_PENDING; | 371 | return 0; |
403 | return; | 372 | |
404 | |||
405 | cs_failed: | 373 | cs_failed: |
406 | cs_error(link->handle, last_fn, last_ret); | 374 | cs_error(link, last_fn, last_ret); |
407 | atmel_release(link); | 375 | atmel_release(link); |
376 | return -ENODEV; | ||
408 | } | 377 | } |
409 | 378 | ||
410 | /*====================================================================== | 379 | /*====================================================================== |
@@ -415,53 +384,34 @@ static void atmel_config(dev_link_t *link) | |||
415 | 384 | ||
416 | ======================================================================*/ | 385 | ======================================================================*/ |
417 | 386 | ||
418 | static void atmel_release(dev_link_t *link) | 387 | static void atmel_release(struct pcmcia_device *link) |
419 | { | 388 | { |
420 | struct net_device *dev = ((local_info_t*)link->priv)->eth_dev; | 389 | struct net_device *dev = ((local_info_t*)link->priv)->eth_dev; |
421 | 390 | ||
422 | DEBUG(0, "atmel_release(0x%p)\n", link); | 391 | DEBUG(0, "atmel_release(0x%p)\n", link); |
423 | 392 | ||
424 | /* Unlink the device chain */ | 393 | if (dev) |
425 | link->dev = NULL; | ||
426 | |||
427 | if (dev) | ||
428 | stop_atmel_card(dev); | 394 | stop_atmel_card(dev); |
429 | ((local_info_t*)link->priv)->eth_dev = NULL; | 395 | ((local_info_t*)link->priv)->eth_dev = NULL; |
430 | 396 | ||
431 | /* Don't bother checking to see if these succeed or not */ | 397 | pcmcia_disable_device(link); |
432 | pcmcia_release_configuration(link->handle); | ||
433 | if (link->io.NumPorts1) | ||
434 | pcmcia_release_io(link->handle, &link->io); | ||
435 | if (link->irq.AssignedIRQ) | ||
436 | pcmcia_release_irq(link->handle, &link->irq); | ||
437 | link->state &= ~DEV_CONFIG; | ||
438 | } | 398 | } |
439 | 399 | ||
440 | static int atmel_suspend(struct pcmcia_device *dev) | 400 | static int atmel_suspend(struct pcmcia_device *link) |
441 | { | 401 | { |
442 | dev_link_t *link = dev_to_instance(dev); | ||
443 | local_info_t *local = link->priv; | 402 | local_info_t *local = link->priv; |
444 | 403 | ||
445 | link->state |= DEV_SUSPEND; | 404 | netif_device_detach(local->eth_dev); |
446 | if (link->state & DEV_CONFIG) { | ||
447 | netif_device_detach(local->eth_dev); | ||
448 | pcmcia_release_configuration(link->handle); | ||
449 | } | ||
450 | 405 | ||
451 | return 0; | 406 | return 0; |
452 | } | 407 | } |
453 | 408 | ||
454 | static int atmel_resume(struct pcmcia_device *dev) | 409 | static int atmel_resume(struct pcmcia_device *link) |
455 | { | 410 | { |
456 | dev_link_t *link = dev_to_instance(dev); | ||
457 | local_info_t *local = link->priv; | 411 | local_info_t *local = link->priv; |
458 | 412 | ||
459 | link->state &= ~DEV_SUSPEND; | 413 | atmel_open(local->eth_dev); |
460 | if (link->state & DEV_CONFIG) { | 414 | netif_device_attach(local->eth_dev); |
461 | pcmcia_request_configuration(link->handle, &link->conf); | ||
462 | atmel_open(local->eth_dev); | ||
463 | netif_device_attach(local->eth_dev); | ||
464 | } | ||
465 | 415 | ||
466 | return 0; | 416 | return 0; |
467 | } | 417 | } |
@@ -515,7 +465,7 @@ static struct pcmcia_driver atmel_driver = { | |||
515 | .drv = { | 465 | .drv = { |
516 | .name = "atmel_cs", | 466 | .name = "atmel_cs", |
517 | }, | 467 | }, |
518 | .probe = atmel_attach, | 468 | .probe = atmel_probe, |
519 | .remove = atmel_detach, | 469 | .remove = atmel_detach, |
520 | .id_table = atmel_ids, | 470 | .id_table = atmel_ids, |
521 | .suspend = atmel_suspend, | 471 | .suspend = atmel_suspend, |
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig index 418465600a77..25ea4748f0b9 100644 --- a/drivers/net/wireless/bcm43xx/Kconfig +++ b/drivers/net/wireless/bcm43xx/Kconfig | |||
@@ -17,8 +17,11 @@ config BCM43XX_DEBUG | |||
17 | 17 | ||
18 | config BCM43XX_DMA | 18 | config BCM43XX_DMA |
19 | bool | 19 | bool |
20 | depends on BCM43XX | ||
21 | |||
20 | config BCM43XX_PIO | 22 | config BCM43XX_PIO |
21 | bool | 23 | bool |
24 | depends on BCM43XX | ||
22 | 25 | ||
23 | choice | 26 | choice |
24 | prompt "BCM43xx data transfer mode" | 27 | prompt "BCM43xx data transfer mode" |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index dcadd295de4f..2e83083935e1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h | |||
@@ -15,7 +15,6 @@ | |||
15 | 15 | ||
16 | #include "bcm43xx_debugfs.h" | 16 | #include "bcm43xx_debugfs.h" |
17 | #include "bcm43xx_leds.h" | 17 | #include "bcm43xx_leds.h" |
18 | #include "bcm43xx_sysfs.h" | ||
19 | 18 | ||
20 | 19 | ||
21 | #define PFX KBUILD_MODNAME ": " | 20 | #define PFX KBUILD_MODNAME ": " |
@@ -638,8 +637,6 @@ struct bcm43xx_key { | |||
638 | }; | 637 | }; |
639 | 638 | ||
640 | struct bcm43xx_private { | 639 | struct bcm43xx_private { |
641 | struct bcm43xx_sysfs sysfs; | ||
642 | |||
643 | struct ieee80211_device *ieee; | 640 | struct ieee80211_device *ieee; |
644 | struct ieee80211softmac_device *softmac; | 641 | struct ieee80211softmac_device *softmac; |
645 | 642 | ||
@@ -772,6 +769,20 @@ struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) | |||
772 | return ieee80211softmac_priv(dev); | 769 | return ieee80211softmac_priv(dev); |
773 | } | 770 | } |
774 | 771 | ||
772 | struct device; | ||
773 | |||
774 | static inline | ||
775 | struct bcm43xx_private * dev_to_bcm(struct device *dev) | ||
776 | { | ||
777 | struct net_device *net_dev; | ||
778 | struct bcm43xx_private *bcm; | ||
779 | |||
780 | net_dev = dev_get_drvdata(dev); | ||
781 | bcm = bcm43xx_priv(net_dev); | ||
782 | |||
783 | return bcm; | ||
784 | } | ||
785 | |||
775 | 786 | ||
776 | /* Helper function, which returns a boolean. | 787 | /* Helper function, which returns a boolean. |
777 | * TRUE, if PIO is used; FALSE, if DMA is used. | 788 | * TRUE, if PIO is used; FALSE, if DMA is used. |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c index d2c3401e9b70..35a4fcb6d923 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | |||
@@ -452,12 +452,12 @@ void bcm43xx_printk_dump(const char *data, | |||
452 | size_t i; | 452 | size_t i; |
453 | char c; | 453 | char c; |
454 | 454 | ||
455 | printk(KERN_INFO PFX "Data dump (%s, %u bytes):", | 455 | printk(KERN_INFO PFX "Data dump (%s, %zd bytes):", |
456 | description, size); | 456 | description, size); |
457 | for (i = 0; i < size; i++) { | 457 | for (i = 0; i < size; i++) { |
458 | c = data[i]; | 458 | c = data[i]; |
459 | if (i % 8 == 0) | 459 | if (i % 8 == 0) |
460 | printk("\n" KERN_INFO PFX "0x%08x: 0x%02x, ", i, c & 0xff); | 460 | printk("\n" KERN_INFO PFX "0x%08zx: 0x%02x, ", i, c & 0xff); |
461 | else | 461 | else |
462 | printk("0x%02x, ", c & 0xff); | 462 | printk("0x%02x, ", c & 0xff); |
463 | } | 463 | } |
@@ -472,12 +472,12 @@ void bcm43xx_printk_bitdump(const unsigned char *data, | |||
472 | int j; | 472 | int j; |
473 | const unsigned char *d; | 473 | const unsigned char *d; |
474 | 474 | ||
475 | printk(KERN_INFO PFX "*** Bitdump (%s, %u bytes, %s) ***", | 475 | printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***", |
476 | description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB"); | 476 | description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB"); |
477 | for (i = 0; i < bytes; i++) { | 477 | for (i = 0; i < bytes; i++) { |
478 | d = data + i; | 478 | d = data + i; |
479 | if (i % 8 == 0) | 479 | if (i % 8 == 0) |
480 | printk("\n" KERN_INFO PFX "0x%08x: ", i); | 480 | printk("\n" KERN_INFO PFX "0x%08zx: ", i); |
481 | if (msb_to_lsb) { | 481 | if (msb_to_lsb) { |
482 | for (j = 7; j >= 0; j--) { | 482 | for (j = 7; j >= 0; j--) { |
483 | if (*d & (1 << j)) | 483 | if (*d & (1 << j)) |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index c3681b8f09b4..bbecba02e697 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c | |||
@@ -196,8 +196,9 @@ static int alloc_ringmemory(struct bcm43xx_dmaring *ring) | |||
196 | } | 196 | } |
197 | if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) { | 197 | if (ring->dmabase + BCM43xx_DMA_RINGMEMSIZE > BCM43xx_DMA_BUSADDRMAX) { |
198 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G " | 198 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RINGMEMORY >1G " |
199 | "(0x%08x, len: %lu)\n", | 199 | "(0x%llx, len: %lu)\n", |
200 | ring->dmabase, BCM43xx_DMA_RINGMEMSIZE); | 200 | (unsigned long long)ring->dmabase, |
201 | BCM43xx_DMA_RINGMEMSIZE); | ||
201 | dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, | 202 | dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, |
202 | ring->vbase, ring->dmabase); | 203 | ring->vbase, ring->dmabase); |
203 | return -ENOMEM; | 204 | return -ENOMEM; |
@@ -307,8 +308,8 @@ static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, | |||
307 | unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); | 308 | unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); |
308 | dev_kfree_skb_any(skb); | 309 | dev_kfree_skb_any(skb); |
309 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G " | 310 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA RX SKB >1G " |
310 | "(0x%08x, len: %u)\n", | 311 | "(0x%llx, len: %u)\n", |
311 | dmaaddr, ring->rx_buffersize); | 312 | (unsigned long long)dmaaddr, ring->rx_buffersize); |
312 | return -ENOMEM; | 313 | return -ENOMEM; |
313 | } | 314 | } |
314 | meta->skb = skb; | 315 | meta->skb = skb; |
@@ -729,8 +730,8 @@ static int dma_tx_fragment(struct bcm43xx_dmaring *ring, | |||
729 | if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) { | 730 | if (unlikely(meta->dmaaddr + skb->len > BCM43xx_DMA_BUSADDRMAX)) { |
730 | return_slot(ring, slot); | 731 | return_slot(ring, slot); |
731 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G " | 732 | printk(KERN_ERR PFX ">>>FATAL ERROR<<< DMA TX SKB >1G " |
732 | "(0x%08x, len: %u)\n", | 733 | "(0x%llx, len: %u)\n", |
733 | meta->dmaaddr, skb->len); | 734 | (unsigned long long)meta->dmaaddr, skb->len); |
734 | return -ENOMEM; | 735 | return -ENOMEM; |
735 | } | 736 | } |
736 | 737 | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index 2d520e4b0276..b7d77638ba8c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h | |||
@@ -213,6 +213,14 @@ static inline | |||
213 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) | 213 | void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) |
214 | { | 214 | { |
215 | } | 215 | } |
216 | static inline | ||
217 | void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) | ||
218 | { | ||
219 | } | ||
220 | static inline | ||
221 | void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) | ||
222 | { | ||
223 | } | ||
216 | 224 | ||
217 | #endif /* CONFIG_BCM43XX_DMA */ | 225 | #endif /* CONFIG_BCM43XX_DMA */ |
218 | #endif /* BCM43xx_DMA_H_ */ | 226 | #endif /* BCM43xx_DMA_H_ */ |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index c37371fc9e01..9a06e61df0a2 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include "bcm43xx_wx.h" | 52 | #include "bcm43xx_wx.h" |
53 | #include "bcm43xx_ethtool.h" | 53 | #include "bcm43xx_ethtool.h" |
54 | #include "bcm43xx_xmit.h" | 54 | #include "bcm43xx_xmit.h" |
55 | #include "bcm43xx_sysfs.h" | ||
55 | 56 | ||
56 | 57 | ||
57 | MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); | 58 | MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); |
@@ -3522,6 +3523,7 @@ static inline int bcm43xx_tx(struct bcm43xx_private *bcm, | |||
3522 | err = bcm43xx_pio_tx(bcm, txb); | 3523 | err = bcm43xx_pio_tx(bcm, txb); |
3523 | else | 3524 | else |
3524 | err = bcm43xx_dma_tx(bcm, txb); | 3525 | err = bcm43xx_dma_tx(bcm, txb); |
3526 | bcm->net_dev->trans_start = jiffies; | ||
3525 | 3527 | ||
3526 | return err; | 3528 | return err; |
3527 | } | 3529 | } |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c index 0a66f43ca0c0..33137165727f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c | |||
@@ -2151,6 +2151,7 @@ int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) | |||
2151 | phy->tssi2dbm = NULL; | 2151 | phy->tssi2dbm = NULL; |
2152 | printk(KERN_ERR PFX "Could not generate " | 2152 | printk(KERN_ERR PFX "Could not generate " |
2153 | "tssi2dBm table\n"); | 2153 | "tssi2dBm table\n"); |
2154 | kfree(dyn_tssi2dbm); | ||
2154 | return -ENODEV; | 2155 | return -ENODEV; |
2155 | } | 2156 | } |
2156 | phy->tssi2dbm = dyn_tssi2dbm; | 2157 | phy->tssi2dbm = dyn_tssi2dbm; |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c index c59ddd40680d..0aa1bd269a25 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "bcm43xx_pio.h" | 27 | #include "bcm43xx_pio.h" |
28 | #include "bcm43xx_main.h" | 28 | #include "bcm43xx_main.h" |
29 | #include "bcm43xx_xmit.h" | 29 | #include "bcm43xx_xmit.h" |
30 | #include "bcm43xx_power.h" | ||
30 | 31 | ||
31 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
32 | 33 | ||
@@ -44,10 +45,10 @@ static void tx_octet(struct bcm43xx_pioqueue *queue, | |||
44 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 45 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
45 | octet); | 46 | octet); |
46 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 47 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
47 | BCM43xx_PIO_TXCTL_WRITEHI); | 48 | BCM43xx_PIO_TXCTL_WRITELO); |
48 | } else { | 49 | } else { |
49 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 50 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
50 | BCM43xx_PIO_TXCTL_WRITEHI); | 51 | BCM43xx_PIO_TXCTL_WRITELO); |
51 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 52 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
52 | octet); | 53 | octet); |
53 | } | 54 | } |
@@ -103,7 +104,7 @@ static void tx_complete(struct bcm43xx_pioqueue *queue, | |||
103 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, | 104 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, |
104 | skb->data[skb->len - 1]); | 105 | skb->data[skb->len - 1]); |
105 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 106 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
106 | BCM43xx_PIO_TXCTL_WRITEHI | | 107 | BCM43xx_PIO_TXCTL_WRITELO | |
107 | BCM43xx_PIO_TXCTL_COMPLETE); | 108 | BCM43xx_PIO_TXCTL_COMPLETE); |
108 | } else { | 109 | } else { |
109 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | 110 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, |
@@ -112,9 +113,10 @@ static void tx_complete(struct bcm43xx_pioqueue *queue, | |||
112 | } | 113 | } |
113 | 114 | ||
114 | static u16 generate_cookie(struct bcm43xx_pioqueue *queue, | 115 | static u16 generate_cookie(struct bcm43xx_pioqueue *queue, |
115 | int packetindex) | 116 | struct bcm43xx_pio_txpacket *packet) |
116 | { | 117 | { |
117 | u16 cookie = 0x0000; | 118 | u16 cookie = 0x0000; |
119 | int packetindex; | ||
118 | 120 | ||
119 | /* We use the upper 4 bits for the PIO | 121 | /* We use the upper 4 bits for the PIO |
120 | * controller ID and the lower 12 bits | 122 | * controller ID and the lower 12 bits |
@@ -135,6 +137,7 @@ static u16 generate_cookie(struct bcm43xx_pioqueue *queue, | |||
135 | default: | 137 | default: |
136 | assert(0); | 138 | assert(0); |
137 | } | 139 | } |
140 | packetindex = pio_txpacket_getindex(packet); | ||
138 | assert(((u16)packetindex & 0xF000) == 0x0000); | 141 | assert(((u16)packetindex & 0xF000) == 0x0000); |
139 | cookie |= (u16)packetindex; | 142 | cookie |= (u16)packetindex; |
140 | 143 | ||
@@ -184,7 +187,7 @@ static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, | |||
184 | bcm43xx_generate_txhdr(queue->bcm, | 187 | bcm43xx_generate_txhdr(queue->bcm, |
185 | &txhdr, skb->data, skb->len, | 188 | &txhdr, skb->data, skb->len, |
186 | (packet->xmitted_frags == 0), | 189 | (packet->xmitted_frags == 0), |
187 | generate_cookie(queue, pio_txpacket_getindex(packet))); | 190 | generate_cookie(queue, packet)); |
188 | 191 | ||
189 | tx_start(queue); | 192 | tx_start(queue); |
190 | octets = skb->len + sizeof(txhdr); | 193 | octets = skb->len + sizeof(txhdr); |
@@ -241,7 +244,7 @@ static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) | |||
241 | queue->tx_devq_packets++; | 244 | queue->tx_devq_packets++; |
242 | queue->tx_devq_used += octets; | 245 | queue->tx_devq_used += octets; |
243 | 246 | ||
244 | assert(packet->xmitted_frags <= packet->txb->nr_frags); | 247 | assert(packet->xmitted_frags < packet->txb->nr_frags); |
245 | packet->xmitted_frags++; | 248 | packet->xmitted_frags++; |
246 | packet->xmitted_octets += octets; | 249 | packet->xmitted_octets += octets; |
247 | } | 250 | } |
@@ -257,8 +260,14 @@ static void tx_tasklet(unsigned long d) | |||
257 | unsigned long flags; | 260 | unsigned long flags; |
258 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; | 261 | struct bcm43xx_pio_txpacket *packet, *tmp_packet; |
259 | int err; | 262 | int err; |
263 | u16 txctl; | ||
260 | 264 | ||
261 | bcm43xx_lock_mmio(bcm, flags); | 265 | bcm43xx_lock_mmio(bcm, flags); |
266 | |||
267 | txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); | ||
268 | if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) | ||
269 | goto out_unlock; | ||
270 | |||
262 | list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { | 271 | list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { |
263 | assert(packet->xmitted_frags < packet->txb->nr_frags); | 272 | assert(packet->xmitted_frags < packet->txb->nr_frags); |
264 | if (packet->xmitted_frags == 0) { | 273 | if (packet->xmitted_frags == 0) { |
@@ -288,6 +297,7 @@ static void tx_tasklet(unsigned long d) | |||
288 | next_packet: | 297 | next_packet: |
289 | continue; | 298 | continue; |
290 | } | 299 | } |
300 | out_unlock: | ||
291 | bcm43xx_unlock_mmio(bcm, flags); | 301 | bcm43xx_unlock_mmio(bcm, flags); |
292 | } | 302 | } |
293 | 303 | ||
@@ -330,12 +340,19 @@ struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, | |||
330 | (unsigned long)queue); | 340 | (unsigned long)queue); |
331 | 341 | ||
332 | value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); | 342 | value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); |
333 | value |= BCM43xx_SBF_XFER_REG_BYTESWAP; | 343 | value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP; |
334 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); | 344 | bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); |
335 | 345 | ||
336 | qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); | 346 | qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); |
347 | if (qsize == 0) { | ||
348 | printk(KERN_ERR PFX "ERROR: This card does not support PIO " | ||
349 | "operation mode. Please use DMA mode " | ||
350 | "(module parameter pio=0).\n"); | ||
351 | goto err_freequeue; | ||
352 | } | ||
337 | if (qsize <= BCM43xx_PIO_TXQADJUST) { | 353 | if (qsize <= BCM43xx_PIO_TXQADJUST) { |
338 | printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", qsize); | 354 | printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", |
355 | qsize); | ||
339 | goto err_freequeue; | 356 | goto err_freequeue; |
340 | } | 357 | } |
341 | qsize -= BCM43xx_PIO_TXQADJUST; | 358 | qsize -= BCM43xx_PIO_TXQADJUST; |
@@ -444,15 +461,10 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm, | |||
444 | { | 461 | { |
445 | struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; | 462 | struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; |
446 | struct bcm43xx_pio_txpacket *packet; | 463 | struct bcm43xx_pio_txpacket *packet; |
447 | u16 tmp; | ||
448 | 464 | ||
449 | assert(!queue->tx_suspended); | 465 | assert(!queue->tx_suspended); |
450 | assert(!list_empty(&queue->txfree)); | 466 | assert(!list_empty(&queue->txfree)); |
451 | 467 | ||
452 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); | ||
453 | if (tmp & BCM43xx_PIO_TXCTL_SUSPEND) | ||
454 | return -EBUSY; | ||
455 | |||
456 | packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); | 468 | packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); |
457 | packet->txb = txb; | 469 | packet->txb = txb; |
458 | packet->xmitted_frags = 0; | 470 | packet->xmitted_frags = 0; |
@@ -462,7 +474,7 @@ int bcm43xx_pio_tx(struct bcm43xx_private *bcm, | |||
462 | assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); | 474 | assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); |
463 | 475 | ||
464 | /* Suspend TX, if we are out of packets in the "free" queue. */ | 476 | /* Suspend TX, if we are out of packets in the "free" queue. */ |
465 | if (unlikely(list_empty(&queue->txfree))) { | 477 | if (list_empty(&queue->txfree)) { |
466 | netif_stop_queue(queue->bcm->net_dev); | 478 | netif_stop_queue(queue->bcm->net_dev); |
467 | queue->tx_suspended = 1; | 479 | queue->tx_suspended = 1; |
468 | } | 480 | } |
@@ -480,15 +492,15 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
480 | 492 | ||
481 | queue = parse_cookie(bcm, status->cookie, &packet); | 493 | queue = parse_cookie(bcm, status->cookie, &packet); |
482 | assert(queue); | 494 | assert(queue); |
483 | //TODO | 495 | |
484 | if (!queue) | ||
485 | return; | ||
486 | free_txpacket(packet, 1); | 496 | free_txpacket(packet, 1); |
487 | if (unlikely(queue->tx_suspended)) { | 497 | if (queue->tx_suspended) { |
488 | queue->tx_suspended = 0; | 498 | queue->tx_suspended = 0; |
489 | netif_wake_queue(queue->bcm->net_dev); | 499 | netif_wake_queue(queue->bcm->net_dev); |
490 | } | 500 | } |
491 | /* If there are packets on the txqueue, poke the tasklet. */ | 501 | /* If there are packets on the txqueue, poke the tasklet |
502 | * to transmit them. | ||
503 | */ | ||
492 | if (!list_empty(&queue->txqueue)) | 504 | if (!list_empty(&queue->txqueue)) |
493 | tasklet_schedule(&queue->txtask); | 505 | tasklet_schedule(&queue->txtask); |
494 | } | 506 | } |
@@ -519,12 +531,9 @@ void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) | |||
519 | int i, preamble_readwords; | 531 | int i, preamble_readwords; |
520 | struct sk_buff *skb; | 532 | struct sk_buff *skb; |
521 | 533 | ||
522 | return; | ||
523 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); | 534 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); |
524 | if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) { | 535 | if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) |
525 | dprintkl(KERN_ERR PFX "PIO RX: No data available\n");//TODO: remove this printk. | ||
526 | return; | 536 | return; |
527 | } | ||
528 | bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, | 537 | bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, |
529 | BCM43xx_PIO_RXCTL_DATAAVAILABLE); | 538 | BCM43xx_PIO_RXCTL_DATAAVAILABLE); |
530 | 539 | ||
@@ -538,8 +547,7 @@ return; | |||
538 | return; | 547 | return; |
539 | data_ready: | 548 | data_ready: |
540 | 549 | ||
541 | //FIXME: endianess in this function. | 550 | len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
542 | len = le16_to_cpu(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); | ||
543 | if (unlikely(len > 0x700)) { | 551 | if (unlikely(len > 0x700)) { |
544 | pio_rx_error(queue, 0, "len > 0x700"); | 552 | pio_rx_error(queue, 0, "len > 0x700"); |
545 | return; | 553 | return; |
@@ -555,7 +563,7 @@ data_ready: | |||
555 | preamble_readwords = 18 / sizeof(u16); | 563 | preamble_readwords = 18 / sizeof(u16); |
556 | for (i = 0; i < preamble_readwords; i++) { | 564 | for (i = 0; i < preamble_readwords; i++) { |
557 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); | 565 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
558 | preamble[i + 1] = cpu_to_be16(tmp);//FIXME? | 566 | preamble[i + 1] = cpu_to_le16(tmp); |
559 | } | 567 | } |
560 | rxhdr = (struct bcm43xx_rxhdr *)preamble; | 568 | rxhdr = (struct bcm43xx_rxhdr *)preamble; |
561 | rxflags2 = le16_to_cpu(rxhdr->flags2); | 569 | rxflags2 = le16_to_cpu(rxhdr->flags2); |
@@ -591,16 +599,40 @@ data_ready: | |||
591 | } | 599 | } |
592 | skb_put(skb, len); | 600 | skb_put(skb, len); |
593 | for (i = 0; i < len - 1; i += 2) { | 601 | for (i = 0; i < len - 1; i += 2) { |
594 | tmp = cpu_to_be16(bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA)); | 602 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
595 | *((u16 *)(skb->data + i)) = tmp; | 603 | *((u16 *)(skb->data + i)) = cpu_to_le16(tmp); |
596 | } | 604 | } |
597 | if (len % 2) { | 605 | if (len % 2) { |
598 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); | 606 | tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); |
599 | skb->data[len - 1] = (tmp & 0x00FF); | 607 | skb->data[len - 1] = (tmp & 0x00FF); |
608 | /* The specs say the following is required, but | ||
609 | * it is wrong and corrupts the PLCP. If we don't do | ||
610 | * this, the PLCP seems to be correct. So ifdef it out for now. | ||
611 | */ | ||
612 | #if 0 | ||
600 | if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) | 613 | if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) |
601 | skb->data[0x20] = (tmp & 0xFF00) >> 8; | 614 | skb->data[2] = (tmp & 0xFF00) >> 8; |
602 | else | 615 | else |
603 | skb->data[0x1E] = (tmp & 0xFF00) >> 8; | 616 | skb->data[0] = (tmp & 0xFF00) >> 8; |
617 | #endif | ||
604 | } | 618 | } |
619 | skb_trim(skb, len - IEEE80211_FCS_LEN); | ||
605 | bcm43xx_rx(queue->bcm, skb, rxhdr); | 620 | bcm43xx_rx(queue->bcm, skb, rxhdr); |
606 | } | 621 | } |
622 | |||
623 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) | ||
624 | { | ||
625 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1); | ||
626 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | ||
627 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) | ||
628 | | BCM43xx_PIO_TXCTL_SUSPEND); | ||
629 | } | ||
630 | |||
631 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | ||
632 | { | ||
633 | bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, | ||
634 | bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) | ||
635 | & ~BCM43xx_PIO_TXCTL_SUSPEND); | ||
636 | bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1); | ||
637 | tasklet_schedule(&queue->txtask); | ||
638 | } | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h index 970627bc1769..dfc78209e3a3 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h | |||
@@ -14,8 +14,8 @@ | |||
14 | #define BCM43xx_PIO_RXCTL 0x08 | 14 | #define BCM43xx_PIO_RXCTL 0x08 |
15 | #define BCM43xx_PIO_RXDATA 0x0A | 15 | #define BCM43xx_PIO_RXDATA 0x0A |
16 | 16 | ||
17 | #define BCM43xx_PIO_TXCTL_WRITEHI (1 << 0) | 17 | #define BCM43xx_PIO_TXCTL_WRITELO (1 << 0) |
18 | #define BCM43xx_PIO_TXCTL_WRITELO (1 << 1) | 18 | #define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1) |
19 | #define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) | 19 | #define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) |
20 | #define BCM43xx_PIO_TXCTL_INIT (1 << 3) | 20 | #define BCM43xx_PIO_TXCTL_INIT (1 << 3) |
21 | #define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) | 21 | #define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) |
@@ -95,6 +95,7 @@ void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, | |||
95 | u16 offset, u16 value) | 95 | u16 offset, u16 value) |
96 | { | 96 | { |
97 | bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); | 97 | bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); |
98 | mmiowb(); | ||
98 | } | 99 | } |
99 | 100 | ||
100 | 101 | ||
@@ -107,6 +108,9 @@ void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, | |||
107 | struct bcm43xx_xmitstatus *status); | 108 | struct bcm43xx_xmitstatus *status); |
108 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); | 109 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); |
109 | 110 | ||
111 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue); | ||
112 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue); | ||
113 | |||
110 | #else /* CONFIG_BCM43XX_PIO */ | 114 | #else /* CONFIG_BCM43XX_PIO */ |
111 | 115 | ||
112 | static inline | 116 | static inline |
@@ -133,6 +137,14 @@ static inline | |||
133 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) | 137 | void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) |
134 | { | 138 | { |
135 | } | 139 | } |
140 | static inline | ||
141 | void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) | ||
142 | { | ||
143 | } | ||
144 | static inline | ||
145 | void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) | ||
146 | { | ||
147 | } | ||
136 | 148 | ||
137 | #endif /* CONFIG_BCM43XX_PIO */ | 149 | #endif /* CONFIG_BCM43XX_PIO */ |
138 | #endif /* BCM43xx_PIO_H_ */ | 150 | #endif /* BCM43xx_PIO_H_ */ |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c index 3c92b62807c5..6569da3a7a39 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c | |||
@@ -35,77 +35,101 @@ | |||
35 | #include "bcm43xx_main.h" | 35 | #include "bcm43xx_main.h" |
36 | 36 | ||
37 | 37 | ||
38 | /* Get the Slow Clock Source */ | ||
39 | static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm) | ||
40 | { | ||
41 | u32 tmp; | ||
42 | int err; | ||
43 | |||
44 | assert(bcm->current_core == &bcm->core_chipcommon); | ||
45 | if (bcm->current_core->rev < 6) { | ||
46 | if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA || | ||
47 | bcm->bustype == BCM43xx_BUSTYPE_SB) | ||
48 | return BCM43xx_PCTL_CLKSRC_XTALOS; | ||
49 | if (bcm->bustype == BCM43xx_BUSTYPE_PCI) { | ||
50 | err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp); | ||
51 | assert(!err); | ||
52 | if (tmp & 0x10) | ||
53 | return BCM43xx_PCTL_CLKSRC_PCI; | ||
54 | return BCM43xx_PCTL_CLKSRC_XTALOS; | ||
55 | } | ||
56 | } | ||
57 | if (bcm->current_core->rev < 10) { | ||
58 | tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); | ||
59 | tmp &= 0x7; | ||
60 | if (tmp == 0) | ||
61 | return BCM43xx_PCTL_CLKSRC_LOPWROS; | ||
62 | if (tmp == 1) | ||
63 | return BCM43xx_PCTL_CLKSRC_XTALOS; | ||
64 | if (tmp == 2) | ||
65 | return BCM43xx_PCTL_CLKSRC_PCI; | ||
66 | } | ||
67 | |||
68 | return BCM43xx_PCTL_CLKSRC_XTALOS; | ||
69 | } | ||
70 | |||
38 | /* Get max/min slowclock frequency | 71 | /* Get max/min slowclock frequency |
39 | * as described in http://bcm-specs.sipsolutions.net/PowerControl | 72 | * as described in http://bcm-specs.sipsolutions.net/PowerControl |
40 | */ | 73 | */ |
41 | static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm, | 74 | static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm, |
42 | int get_max) | 75 | int get_max) |
43 | { | 76 | { |
44 | int limit = 0; | 77 | int limit; |
78 | int clocksrc; | ||
45 | int divisor; | 79 | int divisor; |
46 | int selection; | ||
47 | int err; | ||
48 | u32 tmp; | 80 | u32 tmp; |
49 | struct bcm43xx_coreinfo *old_core; | ||
50 | 81 | ||
51 | if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) | 82 | assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL); |
52 | goto out; | 83 | assert(bcm->current_core == &bcm->core_chipcommon); |
53 | old_core = bcm->current_core; | ||
54 | err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); | ||
55 | if (err) | ||
56 | goto out; | ||
57 | 84 | ||
85 | clocksrc = bcm43xx_pctl_get_slowclksrc(bcm); | ||
58 | if (bcm->current_core->rev < 6) { | 86 | if (bcm->current_core->rev < 6) { |
59 | if ((bcm->bustype == BCM43xx_BUSTYPE_PCMCIA) || | 87 | switch (clocksrc) { |
60 | (bcm->bustype == BCM43xx_BUSTYPE_SB)) { | 88 | case BCM43xx_PCTL_CLKSRC_PCI: |
61 | selection = 1; | 89 | divisor = 64; |
90 | break; | ||
91 | case BCM43xx_PCTL_CLKSRC_XTALOS: | ||
62 | divisor = 32; | 92 | divisor = 32; |
63 | } else { | 93 | break; |
64 | err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp); | 94 | default: |
65 | if (err) { | 95 | assert(0); |
66 | printk(KERN_ERR PFX "clockfreqlimit pcicfg read failure\n"); | 96 | divisor = 1; |
67 | goto out_switchback; | ||
68 | } | ||
69 | if (tmp & 0x10) { | ||
70 | /* PCI */ | ||
71 | selection = 2; | ||
72 | divisor = 64; | ||
73 | } else { | ||
74 | /* XTAL */ | ||
75 | selection = 1; | ||
76 | divisor = 32; | ||
77 | } | ||
78 | } | 97 | } |
79 | } else if (bcm->current_core->rev < 10) { | 98 | } else if (bcm->current_core->rev < 10) { |
80 | selection = (tmp & 0x07); | 99 | switch (clocksrc) { |
81 | if (selection) { | 100 | case BCM43xx_PCTL_CLKSRC_LOPWROS: |
101 | divisor = 1; | ||
102 | break; | ||
103 | case BCM43xx_PCTL_CLKSRC_XTALOS: | ||
104 | case BCM43xx_PCTL_CLKSRC_PCI: | ||
82 | tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); | 105 | tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); |
83 | divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16)); | 106 | divisor = ((tmp & 0xFFFF0000) >> 16) + 1; |
84 | } else | 107 | divisor *= 4; |
108 | break; | ||
109 | default: | ||
110 | assert(0); | ||
85 | divisor = 1; | 111 | divisor = 1; |
112 | } | ||
86 | } else { | 113 | } else { |
87 | tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL); | 114 | tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL); |
88 | divisor = 4 * (1 + ((tmp & 0xFFFF0000) >> 16)); | 115 | divisor = ((tmp & 0xFFFF0000) >> 16) + 1; |
89 | selection = 1; | 116 | divisor *= 4; |
90 | } | 117 | } |
91 | 118 | ||
92 | switch (selection) { | 119 | switch (clocksrc) { |
93 | case 0: | 120 | case BCM43xx_PCTL_CLKSRC_LOPWROS: |
94 | /* LPO */ | ||
95 | if (get_max) | 121 | if (get_max) |
96 | limit = 43000; | 122 | limit = 43000; |
97 | else | 123 | else |
98 | limit = 25000; | 124 | limit = 25000; |
99 | break; | 125 | break; |
100 | case 1: | 126 | case BCM43xx_PCTL_CLKSRC_XTALOS: |
101 | /* XTAL */ | ||
102 | if (get_max) | 127 | if (get_max) |
103 | limit = 20200000; | 128 | limit = 20200000; |
104 | else | 129 | else |
105 | limit = 19800000; | 130 | limit = 19800000; |
106 | break; | 131 | break; |
107 | case 2: | 132 | case BCM43xx_PCTL_CLKSRC_PCI: |
108 | /* PCI */ | ||
109 | if (get_max) | 133 | if (get_max) |
110 | limit = 34000000; | 134 | limit = 34000000; |
111 | else | 135 | else |
@@ -113,17 +137,14 @@ static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm, | |||
113 | break; | 137 | break; |
114 | default: | 138 | default: |
115 | assert(0); | 139 | assert(0); |
140 | limit = 0; | ||
116 | } | 141 | } |
117 | limit /= divisor; | 142 | limit /= divisor; |
118 | 143 | ||
119 | out_switchback: | ||
120 | err = bcm43xx_switch_core(bcm, old_core); | ||
121 | assert(err == 0); | ||
122 | |||
123 | out: | ||
124 | return limit; | 144 | return limit; |
125 | } | 145 | } |
126 | 146 | ||
147 | |||
127 | /* init power control | 148 | /* init power control |
128 | * as described in http://bcm-specs.sipsolutions.net/PowerControl | 149 | * as described in http://bcm-specs.sipsolutions.net/PowerControl |
129 | */ | 150 | */ |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h index 5f63640810bd..c966ab3a5a8c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_power.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.h | |||
@@ -33,6 +33,15 @@ | |||
33 | 33 | ||
34 | #include <linux/types.h> | 34 | #include <linux/types.h> |
35 | 35 | ||
36 | /* Clock sources */ | ||
37 | enum { | ||
38 | /* PCI clock */ | ||
39 | BCM43xx_PCTL_CLKSRC_PCI, | ||
40 | /* Crystal slow clock oscillator */ | ||
41 | BCM43xx_PCTL_CLKSRC_XTALOS, | ||
42 | /* Low power oscillator */ | ||
43 | BCM43xx_PCTL_CLKSRC_LOPWROS, | ||
44 | }; | ||
36 | 45 | ||
37 | struct bcm43xx_private; | 46 | struct bcm43xx_private; |
38 | 47 | ||
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c index c44d890b949b..b438f48e891d 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | |||
@@ -71,14 +71,46 @@ static int get_boolean(const char *buf, size_t count) | |||
71 | return -EINVAL; | 71 | return -EINVAL; |
72 | } | 72 | } |
73 | 73 | ||
74 | static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len) | ||
75 | { | ||
76 | int i, pos = 0; | ||
77 | |||
78 | for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { | ||
79 | pos += snprintf(buf + pos, buf_len - pos - 1, | ||
80 | "%04X", swab16(sprom[i]) & 0xFFFF); | ||
81 | } | ||
82 | pos += snprintf(buf + pos, buf_len - pos - 1, "\n"); | ||
83 | |||
84 | return pos + 1; | ||
85 | } | ||
86 | |||
87 | static int hex2sprom(u16 *sprom, const char *dump, size_t len) | ||
88 | { | ||
89 | char tmp[5] = { 0 }; | ||
90 | int cnt = 0; | ||
91 | unsigned long parsed; | ||
92 | |||
93 | if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2) | ||
94 | return -EINVAL; | ||
95 | |||
96 | while (cnt < BCM43xx_SPROM_SIZE) { | ||
97 | memcpy(tmp, dump, 4); | ||
98 | dump += 4; | ||
99 | parsed = simple_strtoul(tmp, NULL, 16); | ||
100 | sprom[cnt++] = swab16((u16)parsed); | ||
101 | } | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
74 | static ssize_t bcm43xx_attr_sprom_show(struct device *dev, | 106 | static ssize_t bcm43xx_attr_sprom_show(struct device *dev, |
75 | struct device_attribute *attr, | 107 | struct device_attribute *attr, |
76 | char *buf) | 108 | char *buf) |
77 | { | 109 | { |
78 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom); | 110 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
79 | u16 *sprom; | 111 | u16 *sprom; |
80 | unsigned long flags; | 112 | unsigned long flags; |
81 | int i, err; | 113 | int err; |
82 | 114 | ||
83 | if (!capable(CAP_NET_ADMIN)) | 115 | if (!capable(CAP_NET_ADMIN)) |
84 | return -EPERM; | 116 | return -EPERM; |
@@ -91,55 +123,53 @@ static ssize_t bcm43xx_attr_sprom_show(struct device *dev, | |||
91 | bcm43xx_lock_mmio(bcm, flags); | 123 | bcm43xx_lock_mmio(bcm, flags); |
92 | assert(bcm->initialized); | 124 | assert(bcm->initialized); |
93 | err = bcm43xx_sprom_read(bcm, sprom); | 125 | err = bcm43xx_sprom_read(bcm, sprom); |
94 | if (!err) { | 126 | if (!err) |
95 | for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { | 127 | err = sprom2hex(sprom, buf, PAGE_SIZE); |
96 | buf[i * 2] = sprom[i] & 0x00FF; | ||
97 | buf[i * 2 + 1] = (sprom[i] & 0xFF00) >> 8; | ||
98 | } | ||
99 | } | ||
100 | bcm43xx_unlock_mmio(bcm, flags); | 128 | bcm43xx_unlock_mmio(bcm, flags); |
101 | kfree(sprom); | 129 | kfree(sprom); |
102 | 130 | ||
103 | return err ? err : BCM43xx_SPROM_SIZE * sizeof(u16); | 131 | return err; |
104 | } | 132 | } |
105 | 133 | ||
106 | static ssize_t bcm43xx_attr_sprom_store(struct device *dev, | 134 | static ssize_t bcm43xx_attr_sprom_store(struct device *dev, |
107 | struct device_attribute *attr, | 135 | struct device_attribute *attr, |
108 | const char *buf, size_t count) | 136 | const char *buf, size_t count) |
109 | { | 137 | { |
110 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_sprom); | 138 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
111 | u16 *sprom; | 139 | u16 *sprom; |
112 | unsigned long flags; | 140 | unsigned long flags; |
113 | int i, err; | 141 | int err; |
114 | 142 | ||
115 | if (!capable(CAP_NET_ADMIN)) | 143 | if (!capable(CAP_NET_ADMIN)) |
116 | return -EPERM; | 144 | return -EPERM; |
117 | 145 | ||
118 | if (count != BCM43xx_SPROM_SIZE * sizeof(u16)) | ||
119 | return -EINVAL; | ||
120 | sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), | 146 | sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), |
121 | GFP_KERNEL); | 147 | GFP_KERNEL); |
122 | if (!sprom) | 148 | if (!sprom) |
123 | return -ENOMEM; | 149 | return -ENOMEM; |
124 | for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { | 150 | err = hex2sprom(sprom, buf, count); |
125 | sprom[i] = buf[i * 2] & 0xFF; | 151 | if (err) |
126 | sprom[i] |= ((u16)(buf[i * 2 + 1] & 0xFF)) << 8; | 152 | goto out_kfree; |
127 | } | ||
128 | bcm43xx_lock_mmio(bcm, flags); | 153 | bcm43xx_lock_mmio(bcm, flags); |
129 | assert(bcm->initialized); | 154 | assert(bcm->initialized); |
130 | err = bcm43xx_sprom_write(bcm, sprom); | 155 | err = bcm43xx_sprom_write(bcm, sprom); |
131 | bcm43xx_unlock_mmio(bcm, flags); | 156 | bcm43xx_unlock_mmio(bcm, flags); |
157 | out_kfree: | ||
132 | kfree(sprom); | 158 | kfree(sprom); |
133 | 159 | ||
134 | return err ? err : count; | 160 | return err ? err : count; |
135 | 161 | ||
136 | } | 162 | } |
137 | 163 | ||
164 | static DEVICE_ATTR(sprom, 0600, | ||
165 | bcm43xx_attr_sprom_show, | ||
166 | bcm43xx_attr_sprom_store); | ||
167 | |||
138 | static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, | 168 | static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, |
139 | struct device_attribute *attr, | 169 | struct device_attribute *attr, |
140 | char *buf) | 170 | char *buf) |
141 | { | 171 | { |
142 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode); | 172 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
143 | unsigned long flags; | 173 | unsigned long flags; |
144 | int err; | 174 | int err; |
145 | ssize_t count = 0; | 175 | ssize_t count = 0; |
@@ -175,7 +205,7 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, | |||
175 | struct device_attribute *attr, | 205 | struct device_attribute *attr, |
176 | const char *buf, size_t count) | 206 | const char *buf, size_t count) |
177 | { | 207 | { |
178 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_interfmode); | 208 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
179 | unsigned long flags; | 209 | unsigned long flags; |
180 | int err; | 210 | int err; |
181 | int mode; | 211 | int mode; |
@@ -215,11 +245,15 @@ static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, | |||
215 | return err ? err : count; | 245 | return err ? err : count; |
216 | } | 246 | } |
217 | 247 | ||
248 | static DEVICE_ATTR(interference, 0644, | ||
249 | bcm43xx_attr_interfmode_show, | ||
250 | bcm43xx_attr_interfmode_store); | ||
251 | |||
218 | static ssize_t bcm43xx_attr_preamble_show(struct device *dev, | 252 | static ssize_t bcm43xx_attr_preamble_show(struct device *dev, |
219 | struct device_attribute *attr, | 253 | struct device_attribute *attr, |
220 | char *buf) | 254 | char *buf) |
221 | { | 255 | { |
222 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble); | 256 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
223 | unsigned long flags; | 257 | unsigned long flags; |
224 | int err; | 258 | int err; |
225 | ssize_t count; | 259 | ssize_t count; |
@@ -245,7 +279,7 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, | |||
245 | struct device_attribute *attr, | 279 | struct device_attribute *attr, |
246 | const char *buf, size_t count) | 280 | const char *buf, size_t count) |
247 | { | 281 | { |
248 | struct bcm43xx_private *bcm = devattr_to_bcm(attr, attr_preamble); | 282 | struct bcm43xx_private *bcm = dev_to_bcm(dev); |
249 | unsigned long flags; | 283 | unsigned long flags; |
250 | int err; | 284 | int err; |
251 | int value; | 285 | int value; |
@@ -267,56 +301,41 @@ static ssize_t bcm43xx_attr_preamble_store(struct device *dev, | |||
267 | return err ? err : count; | 301 | return err ? err : count; |
268 | } | 302 | } |
269 | 303 | ||
304 | static DEVICE_ATTR(shortpreamble, 0644, | ||
305 | bcm43xx_attr_preamble_show, | ||
306 | bcm43xx_attr_preamble_store); | ||
307 | |||
270 | int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) | 308 | int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) |
271 | { | 309 | { |
272 | struct device *dev = &bcm->pci_dev->dev; | 310 | struct device *dev = &bcm->pci_dev->dev; |
273 | struct bcm43xx_sysfs *sysfs = &bcm->sysfs; | ||
274 | int err; | 311 | int err; |
275 | 312 | ||
276 | assert(bcm->initialized); | 313 | assert(bcm->initialized); |
277 | 314 | ||
278 | sysfs->attr_sprom.attr.name = "sprom"; | 315 | err = device_create_file(dev, &dev_attr_sprom); |
279 | sysfs->attr_sprom.attr.owner = THIS_MODULE; | ||
280 | sysfs->attr_sprom.attr.mode = 0600; | ||
281 | sysfs->attr_sprom.show = bcm43xx_attr_sprom_show; | ||
282 | sysfs->attr_sprom.store = bcm43xx_attr_sprom_store; | ||
283 | err = device_create_file(dev, &sysfs->attr_sprom); | ||
284 | if (err) | 316 | if (err) |
285 | goto out; | 317 | goto out; |
286 | 318 | err = device_create_file(dev, &dev_attr_interference); | |
287 | sysfs->attr_interfmode.attr.name = "interference"; | ||
288 | sysfs->attr_interfmode.attr.owner = THIS_MODULE; | ||
289 | sysfs->attr_interfmode.attr.mode = 0600; | ||
290 | sysfs->attr_interfmode.show = bcm43xx_attr_interfmode_show; | ||
291 | sysfs->attr_interfmode.store = bcm43xx_attr_interfmode_store; | ||
292 | err = device_create_file(dev, &sysfs->attr_interfmode); | ||
293 | if (err) | 319 | if (err) |
294 | goto err_remove_sprom; | 320 | goto err_remove_sprom; |
295 | 321 | err = device_create_file(dev, &dev_attr_shortpreamble); | |
296 | sysfs->attr_preamble.attr.name = "shortpreamble"; | ||
297 | sysfs->attr_preamble.attr.owner = THIS_MODULE; | ||
298 | sysfs->attr_preamble.attr.mode = 0600; | ||
299 | sysfs->attr_preamble.show = bcm43xx_attr_preamble_show; | ||
300 | sysfs->attr_preamble.store = bcm43xx_attr_preamble_store; | ||
301 | err = device_create_file(dev, &sysfs->attr_preamble); | ||
302 | if (err) | 322 | if (err) |
303 | goto err_remove_interfmode; | 323 | goto err_remove_interfmode; |
304 | 324 | ||
305 | out: | 325 | out: |
306 | return err; | 326 | return err; |
307 | err_remove_interfmode: | 327 | err_remove_interfmode: |
308 | device_remove_file(dev, &sysfs->attr_interfmode); | 328 | device_remove_file(dev, &dev_attr_interference); |
309 | err_remove_sprom: | 329 | err_remove_sprom: |
310 | device_remove_file(dev, &sysfs->attr_sprom); | 330 | device_remove_file(dev, &dev_attr_sprom); |
311 | goto out; | 331 | goto out; |
312 | } | 332 | } |
313 | 333 | ||
314 | void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm) | 334 | void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm) |
315 | { | 335 | { |
316 | struct device *dev = &bcm->pci_dev->dev; | 336 | struct device *dev = &bcm->pci_dev->dev; |
317 | struct bcm43xx_sysfs *sysfs = &bcm->sysfs; | ||
318 | 337 | ||
319 | device_remove_file(dev, &sysfs->attr_preamble); | 338 | device_remove_file(dev, &dev_attr_shortpreamble); |
320 | device_remove_file(dev, &sysfs->attr_interfmode); | 339 | device_remove_file(dev, &dev_attr_interference); |
321 | device_remove_file(dev, &sysfs->attr_sprom); | 340 | device_remove_file(dev, &dev_attr_sprom); |
322 | } | 341 | } |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h index 57f14514e3e0..cc701df71e2a 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h | |||
@@ -1,22 +1,6 @@ | |||
1 | #ifndef BCM43xx_SYSFS_H_ | 1 | #ifndef BCM43xx_SYSFS_H_ |
2 | #define BCM43xx_SYSFS_H_ | 2 | #define BCM43xx_SYSFS_H_ |
3 | 3 | ||
4 | #include <linux/device.h> | ||
5 | |||
6 | |||
7 | struct bcm43xx_sysfs { | ||
8 | struct device_attribute attr_sprom; | ||
9 | struct device_attribute attr_interfmode; | ||
10 | struct device_attribute attr_preamble; | ||
11 | }; | ||
12 | |||
13 | #define devattr_to_bcm(attr, attr_name) ({ \ | ||
14 | struct bcm43xx_sysfs *__s; struct bcm43xx_private *__p; \ | ||
15 | __s = container_of((attr), struct bcm43xx_sysfs, attr_name); \ | ||
16 | __p = container_of(__s, struct bcm43xx_private, sysfs); \ | ||
17 | __p; \ | ||
18 | }) | ||
19 | |||
20 | struct bcm43xx_private; | 4 | struct bcm43xx_private; |
21 | 5 | ||
22 | int bcm43xx_sysfs_register(struct bcm43xx_private *bcm); | 6 | int bcm43xx_sysfs_register(struct bcm43xx_private *bcm); |
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 3daee828ef4b..3edbb481a0a0 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c | |||
@@ -962,22 +962,22 @@ static const struct iw_priv_args bcm43xx_priv_wx_args[] = { | |||
962 | { | 962 | { |
963 | .cmd = PRIV_WX_SET_SHORTPREAMBLE, | 963 | .cmd = PRIV_WX_SET_SHORTPREAMBLE, |
964 | .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | 964 | .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
965 | .name = "set_shortpreambl", | 965 | .name = "set_shortpreamb", |
966 | }, | 966 | }, |
967 | { | 967 | { |
968 | .cmd = PRIV_WX_GET_SHORTPREAMBLE, | 968 | .cmd = PRIV_WX_GET_SHORTPREAMBLE, |
969 | .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, | 969 | .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, |
970 | .name = "get_shortpreambl", | 970 | .name = "get_shortpreamb", |
971 | }, | 971 | }, |
972 | { | 972 | { |
973 | .cmd = PRIV_WX_SET_SWENCRYPTION, | 973 | .cmd = PRIV_WX_SET_SWENCRYPTION, |
974 | .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, | 974 | .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, |
975 | .name = "set_swencryption", | 975 | .name = "set_swencrypt", |
976 | }, | 976 | }, |
977 | { | 977 | { |
978 | .cmd = PRIV_WX_GET_SWENCRYPTION, | 978 | .cmd = PRIV_WX_GET_SWENCRYPTION, |
979 | .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, | 979 | .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, |
980 | .name = "get_swencryption", | 980 | .name = "get_swencrypt", |
981 | }, | 981 | }, |
982 | { | 982 | { |
983 | .cmd = PRIV_WX_SPROM_WRITE, | 983 | .cmd = PRIV_WX_SPROM_WRITE, |
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index d335b250923a..55bed923fbe9 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c | |||
@@ -42,7 +42,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry"); | |||
42 | /* struct local_info::hw_priv */ | 42 | /* struct local_info::hw_priv */ |
43 | struct hostap_cs_priv { | 43 | struct hostap_cs_priv { |
44 | dev_node_t node; | 44 | dev_node_t node; |
45 | dev_link_t *link; | 45 | struct pcmcia_device *link; |
46 | int sandisk_connectplus; | 46 | int sandisk_connectplus; |
47 | }; | 47 | }; |
48 | 48 | ||
@@ -204,15 +204,13 @@ static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len) | |||
204 | 204 | ||
205 | static void prism2_detach(struct pcmcia_device *p_dev); | 205 | static void prism2_detach(struct pcmcia_device *p_dev); |
206 | static void prism2_release(u_long arg); | 206 | static void prism2_release(u_long arg); |
207 | static int prism2_config(dev_link_t *link); | 207 | static int prism2_config(struct pcmcia_device *link); |
208 | 208 | ||
209 | 209 | ||
210 | static int prism2_pccard_card_present(local_info_t *local) | 210 | static int prism2_pccard_card_present(local_info_t *local) |
211 | { | 211 | { |
212 | struct hostap_cs_priv *hw_priv = local->hw_priv; | 212 | struct hostap_cs_priv *hw_priv = local->hw_priv; |
213 | if (hw_priv != NULL && hw_priv->link != NULL && | 213 | if (hw_priv != NULL && hw_priv->link != NULL && pcmcia_dev_present(hw_priv->link)) |
214 | ((hw_priv->link->state & (DEV_PRESENT | DEV_CONFIG)) == | ||
215 | (DEV_PRESENT | DEV_CONFIG))) | ||
216 | return 1; | 214 | return 1; |
217 | return 0; | 215 | return 0; |
218 | } | 216 | } |
@@ -237,7 +235,7 @@ static void sandisk_set_iobase(local_info_t *local) | |||
237 | reg.Action = CS_WRITE; | 235 | reg.Action = CS_WRITE; |
238 | reg.Offset = 0x10; /* 0x3f0 IO base 1 */ | 236 | reg.Offset = 0x10; /* 0x3f0 IO base 1 */ |
239 | reg.Value = hw_priv->link->io.BasePort1 & 0x00ff; | 237 | reg.Value = hw_priv->link->io.BasePort1 & 0x00ff; |
240 | res = pcmcia_access_configuration_register(hw_priv->link->handle, | 238 | res = pcmcia_access_configuration_register(hw_priv->link, |
241 | ®); | 239 | ®); |
242 | if (res != CS_SUCCESS) { | 240 | if (res != CS_SUCCESS) { |
243 | printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -" | 241 | printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -" |
@@ -249,7 +247,7 @@ static void sandisk_set_iobase(local_info_t *local) | |||
249 | reg.Action = CS_WRITE; | 247 | reg.Action = CS_WRITE; |
250 | reg.Offset = 0x12; /* 0x3f2 IO base 2 */ | 248 | reg.Offset = 0x12; /* 0x3f2 IO base 2 */ |
251 | reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8; | 249 | reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8; |
252 | res = pcmcia_access_configuration_register(hw_priv->link->handle, | 250 | res = pcmcia_access_configuration_register(hw_priv->link, |
253 | ®); | 251 | ®); |
254 | if (res != CS_SUCCESS) { | 252 | if (res != CS_SUCCESS) { |
255 | printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -" | 253 | printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -" |
@@ -301,9 +299,9 @@ static int sandisk_enable_wireless(struct net_device *dev) | |||
301 | tuple.TupleData = buf; | 299 | tuple.TupleData = buf; |
302 | tuple.TupleDataMax = sizeof(buf); | 300 | tuple.TupleDataMax = sizeof(buf); |
303 | tuple.TupleOffset = 0; | 301 | tuple.TupleOffset = 0; |
304 | if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) || | 302 | if (pcmcia_get_first_tuple(hw_priv->link, &tuple) || |
305 | pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) || | 303 | pcmcia_get_tuple_data(hw_priv->link, &tuple) || |
306 | pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) || | 304 | pcmcia_parse_tuple(hw_priv->link, &tuple, parse) || |
307 | parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) { | 305 | parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) { |
308 | /* No SanDisk manfid found */ | 306 | /* No SanDisk manfid found */ |
309 | ret = -ENODEV; | 307 | ret = -ENODEV; |
@@ -311,9 +309,9 @@ static int sandisk_enable_wireless(struct net_device *dev) | |||
311 | } | 309 | } |
312 | 310 | ||
313 | tuple.DesiredTuple = CISTPL_LONGLINK_MFC; | 311 | tuple.DesiredTuple = CISTPL_LONGLINK_MFC; |
314 | if (pcmcia_get_first_tuple(hw_priv->link->handle, &tuple) || | 312 | if (pcmcia_get_first_tuple(hw_priv->link, &tuple) || |
315 | pcmcia_get_tuple_data(hw_priv->link->handle, &tuple) || | 313 | pcmcia_get_tuple_data(hw_priv->link, &tuple) || |
316 | pcmcia_parse_tuple(hw_priv->link->handle, &tuple, parse) || | 314 | pcmcia_parse_tuple(hw_priv->link, &tuple, parse) || |
317 | parse->longlink_mfc.nfn < 2) { | 315 | parse->longlink_mfc.nfn < 2) { |
318 | /* No multi-function links found */ | 316 | /* No multi-function links found */ |
319 | ret = -ENODEV; | 317 | ret = -ENODEV; |
@@ -328,7 +326,7 @@ static int sandisk_enable_wireless(struct net_device *dev) | |||
328 | reg.Action = CS_WRITE; | 326 | reg.Action = CS_WRITE; |
329 | reg.Offset = CISREG_COR; | 327 | reg.Offset = CISREG_COR; |
330 | reg.Value = COR_SOFT_RESET; | 328 | reg.Value = COR_SOFT_RESET; |
331 | res = pcmcia_access_configuration_register(hw_priv->link->handle, | 329 | res = pcmcia_access_configuration_register(hw_priv->link, |
332 | ®); | 330 | ®); |
333 | if (res != CS_SUCCESS) { | 331 | if (res != CS_SUCCESS) { |
334 | printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", | 332 | printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", |
@@ -345,7 +343,7 @@ static int sandisk_enable_wireless(struct net_device *dev) | |||
345 | * will be enabled during the first cor_sreset call. | 343 | * will be enabled during the first cor_sreset call. |
346 | */ | 344 | */ |
347 | reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA; | 345 | reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA; |
348 | res = pcmcia_access_configuration_register(hw_priv->link->handle, | 346 | res = pcmcia_access_configuration_register(hw_priv->link, |
349 | ®); | 347 | ®); |
350 | if (res != CS_SUCCESS) { | 348 | if (res != CS_SUCCESS) { |
351 | printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", | 349 | printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", |
@@ -380,7 +378,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local) | |||
380 | reg.Action = CS_READ; | 378 | reg.Action = CS_READ; |
381 | reg.Offset = CISREG_COR; | 379 | reg.Offset = CISREG_COR; |
382 | reg.Value = 0; | 380 | reg.Value = 0; |
383 | res = pcmcia_access_configuration_register(hw_priv->link->handle, | 381 | res = pcmcia_access_configuration_register(hw_priv->link, |
384 | ®); | 382 | ®); |
385 | if (res != CS_SUCCESS) { | 383 | if (res != CS_SUCCESS) { |
386 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n", | 384 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n", |
@@ -392,7 +390,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local) | |||
392 | 390 | ||
393 | reg.Action = CS_WRITE; | 391 | reg.Action = CS_WRITE; |
394 | reg.Value |= COR_SOFT_RESET; | 392 | reg.Value |= COR_SOFT_RESET; |
395 | res = pcmcia_access_configuration_register(hw_priv->link->handle, | 393 | res = pcmcia_access_configuration_register(hw_priv->link, |
396 | ®); | 394 | ®); |
397 | if (res != CS_SUCCESS) { | 395 | if (res != CS_SUCCESS) { |
398 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n", | 396 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n", |
@@ -405,7 +403,7 @@ static void prism2_pccard_cor_sreset(local_info_t *local) | |||
405 | reg.Value &= ~COR_SOFT_RESET; | 403 | reg.Value &= ~COR_SOFT_RESET; |
406 | if (hw_priv->sandisk_connectplus) | 404 | if (hw_priv->sandisk_connectplus) |
407 | reg.Value |= COR_IREQ_ENA; | 405 | reg.Value |= COR_IREQ_ENA; |
408 | res = pcmcia_access_configuration_register(hw_priv->link->handle, | 406 | res = pcmcia_access_configuration_register(hw_priv->link, |
409 | ®); | 407 | ®); |
410 | if (res != CS_SUCCESS) { | 408 | if (res != CS_SUCCESS) { |
411 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n", | 409 | printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n", |
@@ -439,7 +437,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) | |||
439 | reg.Action = CS_READ; | 437 | reg.Action = CS_READ; |
440 | reg.Offset = CISREG_COR; | 438 | reg.Offset = CISREG_COR; |
441 | reg.Value = 0; | 439 | reg.Value = 0; |
442 | res = pcmcia_access_configuration_register(hw_priv->link->handle, | 440 | res = pcmcia_access_configuration_register(hw_priv->link, |
443 | ®); | 441 | ®); |
444 | if (res != CS_SUCCESS) { | 442 | if (res != CS_SUCCESS) { |
445 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 " | 443 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 " |
@@ -452,7 +450,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) | |||
452 | 450 | ||
453 | reg.Action = CS_WRITE; | 451 | reg.Action = CS_WRITE; |
454 | reg.Value |= COR_SOFT_RESET; | 452 | reg.Value |= COR_SOFT_RESET; |
455 | res = pcmcia_access_configuration_register(hw_priv->link->handle, | 453 | res = pcmcia_access_configuration_register(hw_priv->link, |
456 | ®); | 454 | ®); |
457 | if (res != CS_SUCCESS) { | 455 | if (res != CS_SUCCESS) { |
458 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 " | 456 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 " |
@@ -466,7 +464,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) | |||
466 | reg.Action = CS_WRITE; | 464 | reg.Action = CS_WRITE; |
467 | reg.Value = hcr; | 465 | reg.Value = hcr; |
468 | reg.Offset = CISREG_CCSR; | 466 | reg.Offset = CISREG_CCSR; |
469 | res = pcmcia_access_configuration_register(hw_priv->link->handle, | 467 | res = pcmcia_access_configuration_register(hw_priv->link, |
470 | ®); | 468 | ®); |
471 | if (res != CS_SUCCESS) { | 469 | if (res != CS_SUCCESS) { |
472 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 " | 470 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 " |
@@ -478,7 +476,7 @@ static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) | |||
478 | reg.Action = CS_WRITE; | 476 | reg.Action = CS_WRITE; |
479 | reg.Offset = CISREG_COR; | 477 | reg.Offset = CISREG_COR; |
480 | reg.Value = old_cor & ~COR_SOFT_RESET; | 478 | reg.Value = old_cor & ~COR_SOFT_RESET; |
481 | res = pcmcia_access_configuration_register(hw_priv->link->handle, | 479 | res = pcmcia_access_configuration_register(hw_priv->link, |
482 | ®); | 480 | ®); |
483 | if (res != CS_SUCCESS) { | 481 | if (res != CS_SUCCESS) { |
484 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 " | 482 | printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 " |
@@ -501,40 +499,27 @@ static struct prism2_helper_functions prism2_pccard_funcs = | |||
501 | 499 | ||
502 | /* allocate local data and register with CardServices | 500 | /* allocate local data and register with CardServices |
503 | * initialize dev_link structure, but do not configure the card yet */ | 501 | * initialize dev_link structure, but do not configure the card yet */ |
504 | static int prism2_attach(struct pcmcia_device *p_dev) | 502 | static int hostap_cs_probe(struct pcmcia_device *p_dev) |
505 | { | 503 | { |
506 | dev_link_t *link; | 504 | int ret; |
507 | |||
508 | link = kmalloc(sizeof(dev_link_t), GFP_KERNEL); | ||
509 | if (link == NULL) | ||
510 | return -ENOMEM; | ||
511 | |||
512 | memset(link, 0, sizeof(dev_link_t)); | ||
513 | 505 | ||
514 | PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); | 506 | PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); |
515 | link->conf.Vcc = 33; | 507 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
516 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
517 | |||
518 | link->handle = p_dev; | ||
519 | p_dev->instance = link; | ||
520 | 508 | ||
521 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 509 | ret = prism2_config(p_dev); |
522 | if (prism2_config(link)) | 510 | if (ret) { |
523 | PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n"); | 511 | PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n"); |
512 | } | ||
524 | 513 | ||
525 | return 0; | 514 | return ret; |
526 | } | 515 | } |
527 | 516 | ||
528 | 517 | ||
529 | static void prism2_detach(struct pcmcia_device *p_dev) | 518 | static void prism2_detach(struct pcmcia_device *link) |
530 | { | 519 | { |
531 | dev_link_t *link = dev_to_instance(p_dev); | ||
532 | |||
533 | PDEBUG(DEBUG_FLOW, "prism2_detach\n"); | 520 | PDEBUG(DEBUG_FLOW, "prism2_detach\n"); |
534 | 521 | ||
535 | if (link->state & DEV_CONFIG) { | 522 | prism2_release((u_long)link); |
536 | prism2_release((u_long)link); | ||
537 | } | ||
538 | 523 | ||
539 | /* release net devices */ | 524 | /* release net devices */ |
540 | if (link->priv) { | 525 | if (link->priv) { |
@@ -547,7 +532,6 @@ static void prism2_detach(struct pcmcia_device *p_dev) | |||
547 | prism2_free_local_data(dev); | 532 | prism2_free_local_data(dev); |
548 | kfree(hw_priv); | 533 | kfree(hw_priv); |
549 | } | 534 | } |
550 | kfree(link); | ||
551 | } | 535 | } |
552 | 536 | ||
553 | 537 | ||
@@ -558,7 +542,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
558 | do { int ret = (retf); \ | 542 | do { int ret = (retf); \ |
559 | if (ret != 0) { \ | 543 | if (ret != 0) { \ |
560 | PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \ | 544 | PDEBUG(DEBUG_EXTRA, "CardServices(" #fn ") returned %d\n", ret); \ |
561 | cs_error(link->handle, fn, ret); \ | 545 | cs_error(link, fn, ret); \ |
562 | goto next_entry; \ | 546 | goto next_entry; \ |
563 | } \ | 547 | } \ |
564 | } while (0) | 548 | } while (0) |
@@ -566,7 +550,7 @@ if (ret != 0) { \ | |||
566 | 550 | ||
567 | /* run after a CARD_INSERTION event is received to configure the PCMCIA | 551 | /* run after a CARD_INSERTION event is received to configure the PCMCIA |
568 | * socket and make the device available to the system */ | 552 | * socket and make the device available to the system */ |
569 | static int prism2_config(dev_link_t *link) | 553 | static int prism2_config(struct pcmcia_device *link) |
570 | { | 554 | { |
571 | struct net_device *dev; | 555 | struct net_device *dev; |
572 | struct hostap_interface *iface; | 556 | struct hostap_interface *iface; |
@@ -595,27 +579,24 @@ static int prism2_config(dev_link_t *link) | |||
595 | tuple.TupleData = buf; | 579 | tuple.TupleData = buf; |
596 | tuple.TupleDataMax = sizeof(buf); | 580 | tuple.TupleDataMax = sizeof(buf); |
597 | tuple.TupleOffset = 0; | 581 | tuple.TupleOffset = 0; |
598 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple)); | 582 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
599 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link->handle, &tuple)); | 583 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
600 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link->handle, &tuple, parse)); | 584 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse)); |
601 | link->conf.ConfigBase = parse->config.base; | 585 | link->conf.ConfigBase = parse->config.base; |
602 | link->conf.Present = parse->config.rmask[0]; | 586 | link->conf.Present = parse->config.rmask[0]; |
603 | 587 | ||
604 | CS_CHECK(GetConfigurationInfo, | 588 | CS_CHECK(GetConfigurationInfo, |
605 | pcmcia_get_configuration_info(link->handle, &conf)); | 589 | pcmcia_get_configuration_info(link, &conf)); |
606 | PDEBUG(DEBUG_HW, "%s: %s Vcc=%d (from config)\n", dev_info, | ||
607 | ignore_cis_vcc ? "ignoring" : "setting", conf.Vcc); | ||
608 | link->conf.Vcc = conf.Vcc; | ||
609 | 590 | ||
610 | /* Look for an appropriate configuration table entry in the CIS */ | 591 | /* Look for an appropriate configuration table entry in the CIS */ |
611 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 592 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
612 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link->handle, &tuple)); | 593 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
613 | for (;;) { | 594 | for (;;) { |
614 | cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); | 595 | cistpl_cftable_entry_t *cfg = &(parse->cftable_entry); |
615 | CFG_CHECK2(GetTupleData, | 596 | CFG_CHECK2(GetTupleData, |
616 | pcmcia_get_tuple_data(link->handle, &tuple)); | 597 | pcmcia_get_tuple_data(link, &tuple)); |
617 | CFG_CHECK2(ParseTuple, | 598 | CFG_CHECK2(ParseTuple, |
618 | pcmcia_parse_tuple(link->handle, &tuple, parse)); | 599 | pcmcia_parse_tuple(link, &tuple, parse)); |
619 | 600 | ||
620 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | 601 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) |
621 | dflt = *cfg; | 602 | dflt = *cfg; |
@@ -650,10 +631,10 @@ static int prism2_config(dev_link_t *link) | |||
650 | } | 631 | } |
651 | 632 | ||
652 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 633 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) |
653 | link->conf.Vpp1 = link->conf.Vpp2 = | 634 | link->conf.Vpp = |
654 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 635 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; |
655 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | 636 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) |
656 | link->conf.Vpp1 = link->conf.Vpp2 = | 637 | link->conf.Vpp = |
657 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | 638 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; |
658 | 639 | ||
659 | /* Do we need to allocate an interrupt? */ | 640 | /* Do we need to allocate an interrupt? */ |
@@ -695,19 +676,19 @@ static int prism2_config(dev_link_t *link) | |||
695 | 676 | ||
696 | /* This reserves IO space but doesn't actually enable it */ | 677 | /* This reserves IO space but doesn't actually enable it */ |
697 | CFG_CHECK2(RequestIO, | 678 | CFG_CHECK2(RequestIO, |
698 | pcmcia_request_io(link->handle, &link->io)); | 679 | pcmcia_request_io(link, &link->io)); |
699 | 680 | ||
700 | /* This configuration table entry is OK */ | 681 | /* This configuration table entry is OK */ |
701 | break; | 682 | break; |
702 | 683 | ||
703 | next_entry: | 684 | next_entry: |
704 | CS_CHECK(GetNextTuple, | 685 | CS_CHECK(GetNextTuple, |
705 | pcmcia_get_next_tuple(link->handle, &tuple)); | 686 | pcmcia_get_next_tuple(link, &tuple)); |
706 | } | 687 | } |
707 | 688 | ||
708 | /* Need to allocate net_device before requesting IRQ handler */ | 689 | /* Need to allocate net_device before requesting IRQ handler */ |
709 | dev = prism2_init_local_data(&prism2_pccard_funcs, 0, | 690 | dev = prism2_init_local_data(&prism2_pccard_funcs, 0, |
710 | &handle_to_dev(link->handle)); | 691 | &handle_to_dev(link)); |
711 | if (dev == NULL) | 692 | if (dev == NULL) |
712 | goto failed; | 693 | goto failed; |
713 | link->priv = dev; | 694 | link->priv = dev; |
@@ -717,7 +698,7 @@ static int prism2_config(dev_link_t *link) | |||
717 | local->hw_priv = hw_priv; | 698 | local->hw_priv = hw_priv; |
718 | hw_priv->link = link; | 699 | hw_priv->link = link; |
719 | strcpy(hw_priv->node.dev_name, dev->name); | 700 | strcpy(hw_priv->node.dev_name, dev->name); |
720 | link->dev = &hw_priv->node; | 701 | link->dev_node = &hw_priv->node; |
721 | 702 | ||
722 | /* | 703 | /* |
723 | * Allocate an interrupt line. Note that this does not assign a | 704 | * Allocate an interrupt line. Note that this does not assign a |
@@ -730,7 +711,7 @@ static int prism2_config(dev_link_t *link) | |||
730 | link->irq.Handler = prism2_interrupt; | 711 | link->irq.Handler = prism2_interrupt; |
731 | link->irq.Instance = dev; | 712 | link->irq.Instance = dev; |
732 | CS_CHECK(RequestIRQ, | 713 | CS_CHECK(RequestIRQ, |
733 | pcmcia_request_irq(link->handle, &link->irq)); | 714 | pcmcia_request_irq(link, &link->irq)); |
734 | } | 715 | } |
735 | 716 | ||
736 | /* | 717 | /* |
@@ -739,18 +720,17 @@ static int prism2_config(dev_link_t *link) | |||
739 | * card and host interface into "Memory and IO" mode. | 720 | * card and host interface into "Memory and IO" mode. |
740 | */ | 721 | */ |
741 | CS_CHECK(RequestConfiguration, | 722 | CS_CHECK(RequestConfiguration, |
742 | pcmcia_request_configuration(link->handle, &link->conf)); | 723 | pcmcia_request_configuration(link, &link->conf)); |
743 | 724 | ||
744 | dev->irq = link->irq.AssignedIRQ; | 725 | dev->irq = link->irq.AssignedIRQ; |
745 | dev->base_addr = link->io.BasePort1; | 726 | dev->base_addr = link->io.BasePort1; |
746 | 727 | ||
747 | /* Finally, report what we've done */ | 728 | /* Finally, report what we've done */ |
748 | printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", | 729 | printk(KERN_INFO "%s: index 0x%02x: ", |
749 | dev_info, link->conf.ConfigIndex, | 730 | dev_info, link->conf.ConfigIndex); |
750 | link->conf.Vcc / 10, link->conf.Vcc % 10); | 731 | if (link->conf.Vpp) |
751 | if (link->conf.Vpp1) | 732 | printk(", Vpp %d.%d", link->conf.Vpp / 10, |
752 | printk(", Vpp %d.%d", link->conf.Vpp1 / 10, | 733 | link->conf.Vpp % 10); |
753 | link->conf.Vpp1 % 10); | ||
754 | if (link->conf.Attributes & CONF_ENABLE_IRQ) | 734 | if (link->conf.Attributes & CONF_ENABLE_IRQ) |
755 | printk(", irq %d", link->irq.AssignedIRQ); | 735 | printk(", irq %d", link->irq.AssignedIRQ); |
756 | if (link->io.NumPorts1) | 736 | if (link->io.NumPorts1) |
@@ -761,9 +741,6 @@ static int prism2_config(dev_link_t *link) | |||
761 | link->io.BasePort2+link->io.NumPorts2-1); | 741 | link->io.BasePort2+link->io.NumPorts2-1); |
762 | printk("\n"); | 742 | printk("\n"); |
763 | 743 | ||
764 | link->state |= DEV_CONFIG; | ||
765 | link->state &= ~DEV_CONFIG_PENDING; | ||
766 | |||
767 | local->shutdown = 0; | 744 | local->shutdown = 0; |
768 | 745 | ||
769 | sandisk_enable_wireless(dev); | 746 | sandisk_enable_wireless(dev); |
@@ -778,7 +755,7 @@ static int prism2_config(dev_link_t *link) | |||
778 | return ret; | 755 | return ret; |
779 | 756 | ||
780 | cs_failed: | 757 | cs_failed: |
781 | cs_error(link->handle, last_fn, last_ret); | 758 | cs_error(link, last_fn, last_ret); |
782 | 759 | ||
783 | failed: | 760 | failed: |
784 | kfree(parse); | 761 | kfree(parse); |
@@ -790,7 +767,7 @@ static int prism2_config(dev_link_t *link) | |||
790 | 767 | ||
791 | static void prism2_release(u_long arg) | 768 | static void prism2_release(u_long arg) |
792 | { | 769 | { |
793 | dev_link_t *link = (dev_link_t *)arg; | 770 | struct pcmcia_device *link = (struct pcmcia_device *)arg; |
794 | 771 | ||
795 | PDEBUG(DEBUG_FLOW, "prism2_release\n"); | 772 | PDEBUG(DEBUG_FLOW, "prism2_release\n"); |
796 | 773 | ||
@@ -799,71 +776,54 @@ static void prism2_release(u_long arg) | |||
799 | struct hostap_interface *iface; | 776 | struct hostap_interface *iface; |
800 | 777 | ||
801 | iface = netdev_priv(dev); | 778 | iface = netdev_priv(dev); |
802 | if (link->state & DEV_CONFIG) | 779 | prism2_hw_shutdown(dev, 0); |
803 | prism2_hw_shutdown(dev, 0); | ||
804 | iface->local->shutdown = 1; | 780 | iface->local->shutdown = 1; |
805 | } | 781 | } |
806 | 782 | ||
807 | if (link->win) | 783 | pcmcia_disable_device(link); |
808 | pcmcia_release_window(link->win); | ||
809 | pcmcia_release_configuration(link->handle); | ||
810 | if (link->io.NumPorts1) | ||
811 | pcmcia_release_io(link->handle, &link->io); | ||
812 | if (link->irq.AssignedIRQ) | ||
813 | pcmcia_release_irq(link->handle, &link->irq); | ||
814 | |||
815 | link->state &= ~DEV_CONFIG; | ||
816 | |||
817 | PDEBUG(DEBUG_FLOW, "release - done\n"); | 784 | PDEBUG(DEBUG_FLOW, "release - done\n"); |
818 | } | 785 | } |
819 | 786 | ||
820 | static int hostap_cs_suspend(struct pcmcia_device *p_dev) | 787 | static int hostap_cs_suspend(struct pcmcia_device *link) |
821 | { | 788 | { |
822 | dev_link_t *link = dev_to_instance(p_dev); | ||
823 | struct net_device *dev = (struct net_device *) link->priv; | 789 | struct net_device *dev = (struct net_device *) link->priv; |
824 | int dev_open = 0; | 790 | int dev_open = 0; |
791 | struct hostap_interface *iface = NULL; | ||
825 | 792 | ||
826 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info); | 793 | if (dev) |
827 | 794 | iface = netdev_priv(dev); | |
828 | link->state |= DEV_SUSPEND; | ||
829 | 795 | ||
830 | if (link->state & DEV_CONFIG) { | 796 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info); |
831 | struct hostap_interface *iface = netdev_priv(dev); | 797 | if (iface && iface->local) |
832 | if (iface && iface->local) | 798 | dev_open = iface->local->num_dev_open > 0; |
833 | dev_open = iface->local->num_dev_open > 0; | 799 | if (dev_open) { |
834 | if (dev_open) { | 800 | netif_stop_queue(dev); |
835 | netif_stop_queue(dev); | 801 | netif_device_detach(dev); |
836 | netif_device_detach(dev); | ||
837 | } | ||
838 | prism2_suspend(dev); | ||
839 | pcmcia_release_configuration(link->handle); | ||
840 | } | 802 | } |
803 | prism2_suspend(dev); | ||
841 | 804 | ||
842 | return 0; | 805 | return 0; |
843 | } | 806 | } |
844 | 807 | ||
845 | static int hostap_cs_resume(struct pcmcia_device *p_dev) | 808 | static int hostap_cs_resume(struct pcmcia_device *link) |
846 | { | 809 | { |
847 | dev_link_t *link = dev_to_instance(p_dev); | ||
848 | struct net_device *dev = (struct net_device *) link->priv; | 810 | struct net_device *dev = (struct net_device *) link->priv; |
849 | int dev_open = 0; | 811 | int dev_open = 0; |
812 | struct hostap_interface *iface = NULL; | ||
850 | 813 | ||
851 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info); | 814 | if (dev) |
815 | iface = netdev_priv(dev); | ||
852 | 816 | ||
853 | link->state &= ~DEV_SUSPEND; | 817 | PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info); |
854 | if (link->state & DEV_CONFIG) { | ||
855 | struct hostap_interface *iface = netdev_priv(dev); | ||
856 | if (iface && iface->local) | ||
857 | dev_open = iface->local->num_dev_open > 0; | ||
858 | 818 | ||
859 | pcmcia_request_configuration(link->handle, &link->conf); | 819 | if (iface && iface->local) |
820 | dev_open = iface->local->num_dev_open > 0; | ||
860 | 821 | ||
861 | prism2_hw_shutdown(dev, 1); | 822 | prism2_hw_shutdown(dev, 1); |
862 | prism2_hw_config(dev, dev_open ? 0 : 1); | 823 | prism2_hw_config(dev, dev_open ? 0 : 1); |
863 | if (dev_open) { | 824 | if (dev_open) { |
864 | netif_device_attach(dev); | 825 | netif_device_attach(dev); |
865 | netif_start_queue(dev); | 826 | netif_start_queue(dev); |
866 | } | ||
867 | } | 827 | } |
868 | 828 | ||
869 | return 0; | 829 | return 0; |
@@ -930,7 +890,7 @@ static struct pcmcia_driver hostap_driver = { | |||
930 | .drv = { | 890 | .drv = { |
931 | .name = "hostap_cs", | 891 | .name = "hostap_cs", |
932 | }, | 892 | }, |
933 | .probe = prism2_attach, | 893 | .probe = hostap_cs_probe, |
934 | .remove = prism2_detach, | 894 | .remove = prism2_detach, |
935 | .owner = THIS_MODULE, | 895 | .owner = THIS_MODULE, |
936 | .id_table = hostap_cs_ids, | 896 | .id_table = hostap_cs_ids, |
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 8b37e824dfcb..8399de581893 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
@@ -1860,7 +1860,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1860 | memset(&iwe, 0, sizeof(iwe)); | 1860 | memset(&iwe, 0, sizeof(iwe)); |
1861 | iwe.cmd = SIOCGIWFREQ; | 1861 | iwe.cmd = SIOCGIWFREQ; |
1862 | if (scan) { | 1862 | if (scan) { |
1863 | chan = scan->chid; | 1863 | chan = le16_to_cpu(scan->chid); |
1864 | } else if (bss) { | 1864 | } else if (bss) { |
1865 | chan = bss->chan; | 1865 | chan = bss->chan; |
1866 | } else { | 1866 | } else { |
@@ -1868,7 +1868,7 @@ static char * __prism2_translate_scan(local_info_t *local, | |||
1868 | } | 1868 | } |
1869 | 1869 | ||
1870 | if (chan > 0) { | 1870 | if (chan > 0) { |
1871 | iwe.u.freq.m = freq_list[le16_to_cpu(chan - 1)] * 100000; | 1871 | iwe.u.freq.m = freq_list[chan - 1] * 100000; |
1872 | iwe.u.freq.e = 1; | 1872 | iwe.u.freq.e = 1; |
1873 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 1873 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, |
1874 | IW_EV_FREQ_LEN); | 1874 | IW_EV_FREQ_LEN); |
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 9dce522526c5..bca89cff85a6 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c | |||
@@ -5573,8 +5573,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv, | |||
5573 | case IEEE80211_52GHZ_BAND: | 5573 | case IEEE80211_52GHZ_BAND: |
5574 | network->mode = IEEE_A; | 5574 | network->mode = IEEE_A; |
5575 | i = ieee80211_channel_to_index(priv->ieee, priv->channel); | 5575 | i = ieee80211_channel_to_index(priv->ieee, priv->channel); |
5576 | if (i == -1) | 5576 | BUG_ON(i == -1); |
5577 | BUG(); | ||
5578 | if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { | 5577 | if (geo->a[i].flags & IEEE80211_CH_PASSIVE_ONLY) { |
5579 | IPW_WARNING("Overriding invalid channel\n"); | 5578 | IPW_WARNING("Overriding invalid channel\n"); |
5580 | priv->channel = geo->a[0].channel; | 5579 | priv->channel = geo->a[0].channel; |
@@ -5587,8 +5586,7 @@ static void ipw_adhoc_create(struct ipw_priv *priv, | |||
5587 | else | 5586 | else |
5588 | network->mode = IEEE_B; | 5587 | network->mode = IEEE_B; |
5589 | i = ieee80211_channel_to_index(priv->ieee, priv->channel); | 5588 | i = ieee80211_channel_to_index(priv->ieee, priv->channel); |
5590 | if (i == -1) | 5589 | BUG_ON(i == -1); |
5591 | BUG(); | ||
5592 | if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) { | 5590 | if (geo->bg[i].flags & IEEE80211_CH_PASSIVE_ONLY) { |
5593 | IPW_WARNING("Overriding invalid channel\n"); | 5591 | IPW_WARNING("Overriding invalid channel\n"); |
5594 | priv->channel = geo->bg[0].channel; | 5592 | priv->channel = geo->bg[0].channel; |
@@ -6715,8 +6713,7 @@ static int ipw_qos_association(struct ipw_priv *priv, | |||
6715 | 6713 | ||
6716 | switch (priv->ieee->iw_mode) { | 6714 | switch (priv->ieee->iw_mode) { |
6717 | case IW_MODE_ADHOC: | 6715 | case IW_MODE_ADHOC: |
6718 | if (!(network->capability & WLAN_CAPABILITY_IBSS)) | 6716 | BUG_ON(!(network->capability & WLAN_CAPABILITY_IBSS)); |
6719 | BUG(); | ||
6720 | 6717 | ||
6721 | qos_data = &ibss_data; | 6718 | qos_data = &ibss_data; |
6722 | break; | 6719 | break; |
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c index 75ce6ddb0cf5..9343d970537b 100644 --- a/drivers/net/wireless/netwave_cs.c +++ b/drivers/net/wireless/netwave_cs.c | |||
@@ -190,8 +190,8 @@ module_param(mem_speed, int, 0); | |||
190 | /*====================================================================*/ | 190 | /*====================================================================*/ |
191 | 191 | ||
192 | /* PCMCIA (Card Services) related functions */ | 192 | /* PCMCIA (Card Services) related functions */ |
193 | static void netwave_release(dev_link_t *link); /* Card removal */ | 193 | static void netwave_release(struct pcmcia_device *link); /* Card removal */ |
194 | static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card | 194 | static int netwave_pcmcia_config(struct pcmcia_device *arg); /* Runs after card |
195 | insertion */ | 195 | insertion */ |
196 | static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */ | 196 | static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */ |
197 | 197 | ||
@@ -221,10 +221,10 @@ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev); | |||
221 | static void set_multicast_list(struct net_device *dev); | 221 | static void set_multicast_list(struct net_device *dev); |
222 | 222 | ||
223 | /* | 223 | /* |
224 | A dev_link_t structure has fields for most things that are needed | 224 | A struct pcmcia_device structure has fields for most things that are needed |
225 | to keep track of a socket, but there will usually be some device | 225 | to keep track of a socket, but there will usually be some device |
226 | specific information that also needs to be kept track of. The | 226 | specific information that also needs to be kept track of. The |
227 | 'priv' pointer in a dev_link_t structure can be used to point to | 227 | 'priv' pointer in a struct pcmcia_device structure can be used to point to |
228 | a device-specific private data structure, like this. | 228 | a device-specific private data structure, like this. |
229 | 229 | ||
230 | A driver needs to provide a dev_node_t structure for each device | 230 | A driver needs to provide a dev_node_t structure for each device |
@@ -232,7 +232,7 @@ static void set_multicast_list(struct net_device *dev); | |||
232 | example, ethernet cards, modems). In other cases, there may be | 232 | example, ethernet cards, modems). In other cases, there may be |
233 | many actual or logical devices (SCSI adapters, memory cards with | 233 | many actual or logical devices (SCSI adapters, memory cards with |
234 | multiple partitions). The dev_node_t structures need to be kept | 234 | multiple partitions). The dev_node_t structures need to be kept |
235 | in a linked list starting at the 'dev' field of a dev_link_t | 235 | in a linked list starting at the 'dev' field of a struct pcmcia_device |
236 | structure. We allocate them in the card's private data structure, | 236 | structure. We allocate them in the card's private data structure, |
237 | because they generally can't be allocated dynamically. | 237 | because they generally can't be allocated dynamically. |
238 | */ | 238 | */ |
@@ -268,7 +268,7 @@ struct site_survey { | |||
268 | }; | 268 | }; |
269 | 269 | ||
270 | typedef struct netwave_private { | 270 | typedef struct netwave_private { |
271 | dev_link_t link; | 271 | struct pcmcia_device *p_dev; |
272 | spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ | 272 | spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ |
273 | dev_node_t node; | 273 | dev_node_t node; |
274 | u_char __iomem *ramBase; | 274 | u_char __iomem *ramBase; |
@@ -376,20 +376,19 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev) | |||
376 | * configure the card at this point -- we wait until we receive a | 376 | * configure the card at this point -- we wait until we receive a |
377 | * card insertion event. | 377 | * card insertion event. |
378 | */ | 378 | */ |
379 | static int netwave_attach(struct pcmcia_device *p_dev) | 379 | static int netwave_probe(struct pcmcia_device *link) |
380 | { | 380 | { |
381 | dev_link_t *link; | ||
382 | struct net_device *dev; | 381 | struct net_device *dev; |
383 | netwave_private *priv; | 382 | netwave_private *priv; |
384 | 383 | ||
385 | DEBUG(0, "netwave_attach()\n"); | 384 | DEBUG(0, "netwave_attach()\n"); |
386 | 385 | ||
387 | /* Initialize the dev_link_t structure */ | 386 | /* Initialize the struct pcmcia_device structure */ |
388 | dev = alloc_etherdev(sizeof(netwave_private)); | 387 | dev = alloc_etherdev(sizeof(netwave_private)); |
389 | if (!dev) | 388 | if (!dev) |
390 | return -ENOMEM; | 389 | return -ENOMEM; |
391 | priv = netdev_priv(dev); | 390 | priv = netdev_priv(dev); |
392 | link = &priv->link; | 391 | priv->p_dev = link; |
393 | link->priv = dev; | 392 | link->priv = dev; |
394 | 393 | ||
395 | /* The io structure describes IO port mapping */ | 394 | /* The io structure describes IO port mapping */ |
@@ -406,7 +405,6 @@ static int netwave_attach(struct pcmcia_device *p_dev) | |||
406 | 405 | ||
407 | /* General socket configuration */ | 406 | /* General socket configuration */ |
408 | link->conf.Attributes = CONF_ENABLE_IRQ; | 407 | link->conf.Attributes = CONF_ENABLE_IRQ; |
409 | link->conf.Vcc = 50; | ||
410 | link->conf.IntType = INT_MEMORY_AND_IO; | 408 | link->conf.IntType = INT_MEMORY_AND_IO; |
411 | link->conf.ConfigIndex = 1; | 409 | link->conf.ConfigIndex = 1; |
412 | link->conf.Present = PRESENT_OPTION; | 410 | link->conf.Present = PRESENT_OPTION; |
@@ -430,13 +428,7 @@ static int netwave_attach(struct pcmcia_device *p_dev) | |||
430 | dev->stop = &netwave_close; | 428 | dev->stop = &netwave_close; |
431 | link->irq.Instance = dev; | 429 | link->irq.Instance = dev; |
432 | 430 | ||
433 | link->handle = p_dev; | 431 | return netwave_pcmcia_config( link); |
434 | p_dev->instance = link; | ||
435 | |||
436 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
437 | netwave_pcmcia_config( link); | ||
438 | |||
439 | return 0; | ||
440 | } /* netwave_attach */ | 432 | } /* netwave_attach */ |
441 | 433 | ||
442 | /* | 434 | /* |
@@ -447,17 +439,15 @@ static int netwave_attach(struct pcmcia_device *p_dev) | |||
447 | * structures are freed. Otherwise, the structures will be freed | 439 | * structures are freed. Otherwise, the structures will be freed |
448 | * when the device is released. | 440 | * when the device is released. |
449 | */ | 441 | */ |
450 | static void netwave_detach(struct pcmcia_device *p_dev) | 442 | static void netwave_detach(struct pcmcia_device *link) |
451 | { | 443 | { |
452 | dev_link_t *link = dev_to_instance(p_dev); | ||
453 | struct net_device *dev = link->priv; | 444 | struct net_device *dev = link->priv; |
454 | 445 | ||
455 | DEBUG(0, "netwave_detach(0x%p)\n", link); | 446 | DEBUG(0, "netwave_detach(0x%p)\n", link); |
456 | 447 | ||
457 | if (link->state & DEV_CONFIG) | 448 | netwave_release(link); |
458 | netwave_release(link); | ||
459 | 449 | ||
460 | if (link->dev) | 450 | if (link->dev_node) |
461 | unregister_netdev(dev); | 451 | unregister_netdev(dev); |
462 | 452 | ||
463 | free_netdev(dev); | 453 | free_netdev(dev); |
@@ -743,8 +733,7 @@ static const struct iw_handler_def netwave_handler_def = | |||
743 | #define CS_CHECK(fn, ret) \ | 733 | #define CS_CHECK(fn, ret) \ |
744 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 734 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
745 | 735 | ||
746 | static void netwave_pcmcia_config(dev_link_t *link) { | 736 | static int netwave_pcmcia_config(struct pcmcia_device *link) { |
747 | client_handle_t handle = link->handle; | ||
748 | struct net_device *dev = link->priv; | 737 | struct net_device *dev = link->priv; |
749 | netwave_private *priv = netdev_priv(dev); | 738 | netwave_private *priv = netdev_priv(dev); |
750 | tuple_t tuple; | 739 | tuple_t tuple; |
@@ -766,15 +755,12 @@ static void netwave_pcmcia_config(dev_link_t *link) { | |||
766 | tuple.TupleDataMax = 64; | 755 | tuple.TupleDataMax = 64; |
767 | tuple.TupleOffset = 0; | 756 | tuple.TupleOffset = 0; |
768 | tuple.DesiredTuple = CISTPL_CONFIG; | 757 | tuple.DesiredTuple = CISTPL_CONFIG; |
769 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 758 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
770 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 759 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
771 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 760 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
772 | link->conf.ConfigBase = parse.config.base; | 761 | link->conf.ConfigBase = parse.config.base; |
773 | link->conf.Present = parse.config.rmask[0]; | 762 | link->conf.Present = parse.config.rmask[0]; |
774 | 763 | ||
775 | /* Configure card */ | ||
776 | link->state |= DEV_CONFIG; | ||
777 | |||
778 | /* | 764 | /* |
779 | * Try allocating IO ports. This tries a few fixed addresses. | 765 | * Try allocating IO ports. This tries a few fixed addresses. |
780 | * If you want, you can also read the card's config table to | 766 | * If you want, you can also read the card's config table to |
@@ -782,11 +768,11 @@ static void netwave_pcmcia_config(dev_link_t *link) { | |||
782 | */ | 768 | */ |
783 | for (i = j = 0x0; j < 0x400; j += 0x20) { | 769 | for (i = j = 0x0; j < 0x400; j += 0x20) { |
784 | link->io.BasePort1 = j ^ 0x300; | 770 | link->io.BasePort1 = j ^ 0x300; |
785 | i = pcmcia_request_io(link->handle, &link->io); | 771 | i = pcmcia_request_io(link, &link->io); |
786 | if (i == CS_SUCCESS) break; | 772 | if (i == CS_SUCCESS) break; |
787 | } | 773 | } |
788 | if (i != CS_SUCCESS) { | 774 | if (i != CS_SUCCESS) { |
789 | cs_error(link->handle, RequestIO, i); | 775 | cs_error(link, RequestIO, i); |
790 | goto failed; | 776 | goto failed; |
791 | } | 777 | } |
792 | 778 | ||
@@ -794,16 +780,16 @@ static void netwave_pcmcia_config(dev_link_t *link) { | |||
794 | * Now allocate an interrupt line. Note that this does not | 780 | * Now allocate an interrupt line. Note that this does not |
795 | * actually assign a handler to the interrupt. | 781 | * actually assign a handler to the interrupt. |
796 | */ | 782 | */ |
797 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | 783 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
798 | 784 | ||
799 | /* | 785 | /* |
800 | * This actually configures the PCMCIA socket -- setting up | 786 | * This actually configures the PCMCIA socket -- setting up |
801 | * the I/O windows and the interrupt mapping. | 787 | * the I/O windows and the interrupt mapping. |
802 | */ | 788 | */ |
803 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | 789 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
804 | 790 | ||
805 | /* | 791 | /* |
806 | * Allocate a 32K memory window. Note that the dev_link_t | 792 | * Allocate a 32K memory window. Note that the struct pcmcia_device |
807 | * structure provides space for one window handle -- if your | 793 | * structure provides space for one window handle -- if your |
808 | * device needs several windows, you'll need to keep track of | 794 | * device needs several windows, you'll need to keep track of |
809 | * the handles in your private data structure, dev->priv. | 795 | * the handles in your private data structure, dev->priv. |
@@ -813,7 +799,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { | |||
813 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE; | 799 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE; |
814 | req.Base = 0; req.Size = 0x8000; | 800 | req.Base = 0; req.Size = 0x8000; |
815 | req.AccessSpeed = mem_speed; | 801 | req.AccessSpeed = mem_speed; |
816 | CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); | 802 | CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); |
817 | mem.CardOffset = 0x20000; mem.Page = 0; | 803 | mem.CardOffset = 0x20000; mem.Page = 0; |
818 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); | 804 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); |
819 | 805 | ||
@@ -823,7 +809,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { | |||
823 | 809 | ||
824 | dev->irq = link->irq.AssignedIRQ; | 810 | dev->irq = link->irq.AssignedIRQ; |
825 | dev->base_addr = link->io.BasePort1; | 811 | dev->base_addr = link->io.BasePort1; |
826 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | 812 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
827 | 813 | ||
828 | if (register_netdev(dev) != 0) { | 814 | if (register_netdev(dev) != 0) { |
829 | printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n"); | 815 | printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n"); |
@@ -831,8 +817,7 @@ static void netwave_pcmcia_config(dev_link_t *link) { | |||
831 | } | 817 | } |
832 | 818 | ||
833 | strcpy(priv->node.dev_name, dev->name); | 819 | strcpy(priv->node.dev_name, dev->name); |
834 | link->dev = &priv->node; | 820 | link->dev_node = &priv->node; |
835 | link->state &= ~DEV_CONFIG_PENDING; | ||
836 | 821 | ||
837 | /* Reset card before reading physical address */ | 822 | /* Reset card before reading physical address */ |
838 | netwave_doreset(dev->base_addr, ramBase); | 823 | netwave_doreset(dev->base_addr, ramBase); |
@@ -852,12 +837,13 @@ static void netwave_pcmcia_config(dev_link_t *link) { | |||
852 | printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n", | 837 | printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n", |
853 | get_uint16(ramBase + NETWAVE_EREG_ARW), | 838 | get_uint16(ramBase + NETWAVE_EREG_ARW), |
854 | get_uint16(ramBase + NETWAVE_EREG_ARW+2)); | 839 | get_uint16(ramBase + NETWAVE_EREG_ARW+2)); |
855 | return; | 840 | return 0; |
856 | 841 | ||
857 | cs_failed: | 842 | cs_failed: |
858 | cs_error(link->handle, last_fn, last_ret); | 843 | cs_error(link, last_fn, last_ret); |
859 | failed: | 844 | failed: |
860 | netwave_release(link); | 845 | netwave_release(link); |
846 | return -ENODEV; | ||
861 | } /* netwave_pcmcia_config */ | 847 | } /* netwave_pcmcia_config */ |
862 | 848 | ||
863 | /* | 849 | /* |
@@ -867,52 +853,35 @@ failed: | |||
867 | * device, and release the PCMCIA configuration. If the device is | 853 | * device, and release the PCMCIA configuration. If the device is |
868 | * still open, this will be postponed until it is closed. | 854 | * still open, this will be postponed until it is closed. |
869 | */ | 855 | */ |
870 | static void netwave_release(dev_link_t *link) | 856 | static void netwave_release(struct pcmcia_device *link) |
871 | { | 857 | { |
872 | struct net_device *dev = link->priv; | 858 | struct net_device *dev = link->priv; |
873 | netwave_private *priv = netdev_priv(dev); | 859 | netwave_private *priv = netdev_priv(dev); |
874 | |||
875 | DEBUG(0, "netwave_release(0x%p)\n", link); | ||
876 | 860 | ||
877 | /* Don't bother checking to see if these succeed or not */ | 861 | DEBUG(0, "netwave_release(0x%p)\n", link); |
878 | if (link->win) { | ||
879 | iounmap(priv->ramBase); | ||
880 | pcmcia_release_window(link->win); | ||
881 | } | ||
882 | pcmcia_release_configuration(link->handle); | ||
883 | pcmcia_release_io(link->handle, &link->io); | ||
884 | pcmcia_release_irq(link->handle, &link->irq); | ||
885 | 862 | ||
886 | link->state &= ~DEV_CONFIG; | 863 | pcmcia_disable_device(link); |
864 | if (link->win) | ||
865 | iounmap(priv->ramBase); | ||
887 | } | 866 | } |
888 | 867 | ||
889 | static int netwave_suspend(struct pcmcia_device *p_dev) | 868 | static int netwave_suspend(struct pcmcia_device *link) |
890 | { | 869 | { |
891 | dev_link_t *link = dev_to_instance(p_dev); | ||
892 | struct net_device *dev = link->priv; | 870 | struct net_device *dev = link->priv; |
893 | 871 | ||
894 | link->state |= DEV_SUSPEND; | 872 | if (link->open) |
895 | if (link->state & DEV_CONFIG) { | 873 | netif_device_detach(dev); |
896 | if (link->open) | ||
897 | netif_device_detach(dev); | ||
898 | pcmcia_release_configuration(link->handle); | ||
899 | } | ||
900 | 874 | ||
901 | return 0; | 875 | return 0; |
902 | } | 876 | } |
903 | 877 | ||
904 | static int netwave_resume(struct pcmcia_device *p_dev) | 878 | static int netwave_resume(struct pcmcia_device *link) |
905 | { | 879 | { |
906 | dev_link_t *link = dev_to_instance(p_dev); | ||
907 | struct net_device *dev = link->priv; | 880 | struct net_device *dev = link->priv; |
908 | 881 | ||
909 | link->state &= ~DEV_SUSPEND; | 882 | if (link->open) { |
910 | if (link->state & DEV_CONFIG) { | 883 | netwave_reset(dev); |
911 | pcmcia_request_configuration(link->handle, &link->conf); | 884 | netif_device_attach(dev); |
912 | if (link->open) { | ||
913 | netwave_reset(dev); | ||
914 | netif_device_attach(dev); | ||
915 | } | ||
916 | } | 885 | } |
917 | 886 | ||
918 | return 0; | 887 | return 0; |
@@ -1119,7 +1088,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs | |||
1119 | u_char __iomem *ramBase; | 1088 | u_char __iomem *ramBase; |
1120 | struct net_device *dev = (struct net_device *)dev_id; | 1089 | struct net_device *dev = (struct net_device *)dev_id; |
1121 | struct netwave_private *priv = netdev_priv(dev); | 1090 | struct netwave_private *priv = netdev_priv(dev); |
1122 | dev_link_t *link = &priv->link; | 1091 | struct pcmcia_device *link = priv->p_dev; |
1123 | int i; | 1092 | int i; |
1124 | 1093 | ||
1125 | if (!netif_device_present(dev)) | 1094 | if (!netif_device_present(dev)) |
@@ -1138,7 +1107,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs | |||
1138 | 1107 | ||
1139 | status = inb(iobase + NETWAVE_REG_ASR); | 1108 | status = inb(iobase + NETWAVE_REG_ASR); |
1140 | 1109 | ||
1141 | if (!DEV_OK(link)) { | 1110 | if (!pcmcia_dev_present(link)) { |
1142 | DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x " | 1111 | DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x " |
1143 | "from removed or suspended card!\n", status); | 1112 | "from removed or suspended card!\n", status); |
1144 | break; | 1113 | break; |
@@ -1373,11 +1342,11 @@ static int netwave_rx(struct net_device *dev) | |||
1373 | 1342 | ||
1374 | static int netwave_open(struct net_device *dev) { | 1343 | static int netwave_open(struct net_device *dev) { |
1375 | netwave_private *priv = netdev_priv(dev); | 1344 | netwave_private *priv = netdev_priv(dev); |
1376 | dev_link_t *link = &priv->link; | 1345 | struct pcmcia_device *link = priv->p_dev; |
1377 | 1346 | ||
1378 | DEBUG(1, "netwave_open: starting.\n"); | 1347 | DEBUG(1, "netwave_open: starting.\n"); |
1379 | 1348 | ||
1380 | if (!DEV_OK(link)) | 1349 | if (!pcmcia_dev_present(link)) |
1381 | return -ENODEV; | 1350 | return -ENODEV; |
1382 | 1351 | ||
1383 | link->open++; | 1352 | link->open++; |
@@ -1390,7 +1359,7 @@ static int netwave_open(struct net_device *dev) { | |||
1390 | 1359 | ||
1391 | static int netwave_close(struct net_device *dev) { | 1360 | static int netwave_close(struct net_device *dev) { |
1392 | netwave_private *priv = netdev_priv(dev); | 1361 | netwave_private *priv = netdev_priv(dev); |
1393 | dev_link_t *link = &priv->link; | 1362 | struct pcmcia_device *link = priv->p_dev; |
1394 | 1363 | ||
1395 | DEBUG(1, "netwave_close: finishing.\n"); | 1364 | DEBUG(1, "netwave_close: finishing.\n"); |
1396 | 1365 | ||
@@ -1411,7 +1380,7 @@ static struct pcmcia_driver netwave_driver = { | |||
1411 | .drv = { | 1380 | .drv = { |
1412 | .name = "netwave_cs", | 1381 | .name = "netwave_cs", |
1413 | }, | 1382 | }, |
1414 | .probe = netwave_attach, | 1383 | .probe = netwave_probe, |
1415 | .remove = netwave_detach, | 1384 | .remove = netwave_detach, |
1416 | .id_table = netwave_ids, | 1385 | .id_table = netwave_ids, |
1417 | .suspend = netwave_suspend, | 1386 | .suspend = netwave_suspend, |
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 8dfdfbd5966c..06523e2a8471 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
@@ -390,7 +390,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) | |||
390 | } | 390 | } |
391 | } else { | 391 | } else { |
392 | struct { | 392 | struct { |
393 | __le16 qual, signal, noise; | 393 | __le16 qual, signal, noise, unused; |
394 | } __attribute__ ((packed)) cq; | 394 | } __attribute__ ((packed)) cq; |
395 | 395 | ||
396 | err = HERMES_READ_RECORD(hw, USER_BAP, | 396 | err = HERMES_READ_RECORD(hw, USER_BAP, |
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index ec6f2a48895b..434f7d7ad841 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
@@ -49,7 +49,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket | |||
49 | /* PCMCIA specific device information (goes in the card field of | 49 | /* PCMCIA specific device information (goes in the card field of |
50 | * struct orinoco_private */ | 50 | * struct orinoco_private */ |
51 | struct orinoco_pccard { | 51 | struct orinoco_pccard { |
52 | dev_link_t link; | 52 | struct pcmcia_device *p_dev; |
53 | dev_node_t node; | 53 | dev_node_t node; |
54 | 54 | ||
55 | /* Used to handle hard reset */ | 55 | /* Used to handle hard reset */ |
@@ -63,8 +63,8 @@ struct orinoco_pccard { | |||
63 | /* Function prototypes */ | 63 | /* Function prototypes */ |
64 | /********************************************************************/ | 64 | /********************************************************************/ |
65 | 65 | ||
66 | static void orinoco_cs_config(dev_link_t *link); | 66 | static int orinoco_cs_config(struct pcmcia_device *link); |
67 | static void orinoco_cs_release(dev_link_t *link); | 67 | static void orinoco_cs_release(struct pcmcia_device *link); |
68 | static void orinoco_cs_detach(struct pcmcia_device *p_dev); | 68 | static void orinoco_cs_detach(struct pcmcia_device *p_dev); |
69 | 69 | ||
70 | /********************************************************************/ | 70 | /********************************************************************/ |
@@ -75,13 +75,13 @@ static int | |||
75 | orinoco_cs_hard_reset(struct orinoco_private *priv) | 75 | orinoco_cs_hard_reset(struct orinoco_private *priv) |
76 | { | 76 | { |
77 | struct orinoco_pccard *card = priv->card; | 77 | struct orinoco_pccard *card = priv->card; |
78 | dev_link_t *link = &card->link; | 78 | struct pcmcia_device *link = card->p_dev; |
79 | int err; | 79 | int err; |
80 | 80 | ||
81 | /* We need atomic ops here, because we're not holding the lock */ | 81 | /* We need atomic ops here, because we're not holding the lock */ |
82 | set_bit(0, &card->hard_reset_in_progress); | 82 | set_bit(0, &card->hard_reset_in_progress); |
83 | 83 | ||
84 | err = pcmcia_reset_card(link->handle, NULL); | 84 | err = pcmcia_reset_card(link, NULL); |
85 | if (err) | 85 | if (err) |
86 | return err; | 86 | return err; |
87 | 87 | ||
@@ -104,12 +104,11 @@ orinoco_cs_hard_reset(struct orinoco_private *priv) | |||
104 | * configure the card at this point -- we wait until we receive a card | 104 | * configure the card at this point -- we wait until we receive a card |
105 | * insertion event. */ | 105 | * insertion event. */ |
106 | static int | 106 | static int |
107 | orinoco_cs_attach(struct pcmcia_device *p_dev) | 107 | orinoco_cs_probe(struct pcmcia_device *link) |
108 | { | 108 | { |
109 | struct net_device *dev; | 109 | struct net_device *dev; |
110 | struct orinoco_private *priv; | 110 | struct orinoco_private *priv; |
111 | struct orinoco_pccard *card; | 111 | struct orinoco_pccard *card; |
112 | dev_link_t *link; | ||
113 | 112 | ||
114 | dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); | 113 | dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); |
115 | if (! dev) | 114 | if (! dev) |
@@ -118,7 +117,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev) | |||
118 | card = priv->card; | 117 | card = priv->card; |
119 | 118 | ||
120 | /* Link both structures together */ | 119 | /* Link both structures together */ |
121 | link = &card->link; | 120 | card->p_dev = link; |
122 | link->priv = dev; | 121 | link->priv = dev; |
123 | 122 | ||
124 | /* Interrupt setup */ | 123 | /* Interrupt setup */ |
@@ -135,16 +134,7 @@ orinoco_cs_attach(struct pcmcia_device *p_dev) | |||
135 | link->conf.Attributes = 0; | 134 | link->conf.Attributes = 0; |
136 | link->conf.IntType = INT_MEMORY_AND_IO; | 135 | link->conf.IntType = INT_MEMORY_AND_IO; |
137 | 136 | ||
138 | /* Register with Card Services */ | 137 | return orinoco_cs_config(link); |
139 | link->next = NULL; | ||
140 | |||
141 | link->handle = p_dev; | ||
142 | p_dev->instance = link; | ||
143 | |||
144 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
145 | orinoco_cs_config(link); | ||
146 | |||
147 | return 0; | ||
148 | } /* orinoco_cs_attach */ | 138 | } /* orinoco_cs_attach */ |
149 | 139 | ||
150 | /* | 140 | /* |
@@ -153,16 +143,14 @@ orinoco_cs_attach(struct pcmcia_device *p_dev) | |||
153 | * are freed. Otherwise, the structures will be freed when the device | 143 | * are freed. Otherwise, the structures will be freed when the device |
154 | * is released. | 144 | * is released. |
155 | */ | 145 | */ |
156 | static void orinoco_cs_detach(struct pcmcia_device *p_dev) | 146 | static void orinoco_cs_detach(struct pcmcia_device *link) |
157 | { | 147 | { |
158 | dev_link_t *link = dev_to_instance(p_dev); | ||
159 | struct net_device *dev = link->priv; | 148 | struct net_device *dev = link->priv; |
160 | 149 | ||
161 | if (link->state & DEV_CONFIG) | 150 | orinoco_cs_release(link); |
162 | orinoco_cs_release(link); | ||
163 | 151 | ||
164 | DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); | 152 | DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); |
165 | if (link->dev) { | 153 | if (link->dev_node) { |
166 | DEBUG(0, PFX "About to unregister net device %p\n", | 154 | DEBUG(0, PFX "About to unregister net device %p\n", |
167 | dev); | 155 | dev); |
168 | unregister_netdev(dev); | 156 | unregister_netdev(dev); |
@@ -180,11 +168,10 @@ static void orinoco_cs_detach(struct pcmcia_device *p_dev) | |||
180 | last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ | 168 | last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \ |
181 | } while (0) | 169 | } while (0) |
182 | 170 | ||
183 | static void | 171 | static int |
184 | orinoco_cs_config(dev_link_t *link) | 172 | orinoco_cs_config(struct pcmcia_device *link) |
185 | { | 173 | { |
186 | struct net_device *dev = link->priv; | 174 | struct net_device *dev = link->priv; |
187 | client_handle_t handle = link->handle; | ||
188 | struct orinoco_private *priv = netdev_priv(dev); | 175 | struct orinoco_private *priv = netdev_priv(dev); |
189 | struct orinoco_pccard *card = priv->card; | 176 | struct orinoco_pccard *card = priv->card; |
190 | hermes_t *hw = &priv->hw; | 177 | hermes_t *hw = &priv->hw; |
@@ -196,7 +183,7 @@ orinoco_cs_config(dev_link_t *link) | |||
196 | cisparse_t parse; | 183 | cisparse_t parse; |
197 | void __iomem *mem; | 184 | void __iomem *mem; |
198 | 185 | ||
199 | CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info)); | 186 | CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info)); |
200 | 187 | ||
201 | /* | 188 | /* |
202 | * This reads the card's CONFIG tuple to find its | 189 | * This reads the card's CONFIG tuple to find its |
@@ -207,19 +194,15 @@ orinoco_cs_config(dev_link_t *link) | |||
207 | tuple.TupleData = buf; | 194 | tuple.TupleData = buf; |
208 | tuple.TupleDataMax = sizeof(buf); | 195 | tuple.TupleDataMax = sizeof(buf); |
209 | tuple.TupleOffset = 0; | 196 | tuple.TupleOffset = 0; |
210 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 197 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
211 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 198 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
212 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 199 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
213 | link->conf.ConfigBase = parse.config.base; | 200 | link->conf.ConfigBase = parse.config.base; |
214 | link->conf.Present = parse.config.rmask[0]; | 201 | link->conf.Present = parse.config.rmask[0]; |
215 | 202 | ||
216 | /* Configure card */ | ||
217 | link->state |= DEV_CONFIG; | ||
218 | |||
219 | /* Look up the current Vcc */ | 203 | /* Look up the current Vcc */ |
220 | CS_CHECK(GetConfigurationInfo, | 204 | CS_CHECK(GetConfigurationInfo, |
221 | pcmcia_get_configuration_info(handle, &conf)); | 205 | pcmcia_get_configuration_info(link, &conf)); |
222 | link->conf.Vcc = conf.Vcc; | ||
223 | 206 | ||
224 | /* | 207 | /* |
225 | * In this loop, we scan the CIS for configuration table | 208 | * In this loop, we scan the CIS for configuration table |
@@ -236,13 +219,13 @@ orinoco_cs_config(dev_link_t *link) | |||
236 | * implementation-defined details. | 219 | * implementation-defined details. |
237 | */ | 220 | */ |
238 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 221 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
239 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 222 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
240 | while (1) { | 223 | while (1) { |
241 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 224 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
242 | cistpl_cftable_entry_t dflt = { .index = 0 }; | 225 | cistpl_cftable_entry_t dflt = { .index = 0 }; |
243 | 226 | ||
244 | if ( (pcmcia_get_tuple_data(handle, &tuple) != 0) | 227 | if ( (pcmcia_get_tuple_data(link, &tuple) != 0) |
245 | || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0)) | 228 | || (pcmcia_parse_tuple(link, &tuple, &parse) != 0)) |
246 | goto next_entry; | 229 | goto next_entry; |
247 | 230 | ||
248 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | 231 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) |
@@ -274,10 +257,10 @@ orinoco_cs_config(dev_link_t *link) | |||
274 | } | 257 | } |
275 | 258 | ||
276 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 259 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) |
277 | link->conf.Vpp1 = link->conf.Vpp2 = | 260 | link->conf.Vpp = |
278 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 261 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; |
279 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | 262 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) |
280 | link->conf.Vpp1 = link->conf.Vpp2 = | 263 | link->conf.Vpp = |
281 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | 264 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; |
282 | 265 | ||
283 | /* Do we need to allocate an interrupt? */ | 266 | /* Do we need to allocate an interrupt? */ |
@@ -307,7 +290,7 @@ orinoco_cs_config(dev_link_t *link) | |||
307 | } | 290 | } |
308 | 291 | ||
309 | /* This reserves IO space but doesn't actually enable it */ | 292 | /* This reserves IO space but doesn't actually enable it */ |
310 | if (pcmcia_request_io(link->handle, &link->io) != 0) | 293 | if (pcmcia_request_io(link, &link->io) != 0) |
311 | goto next_entry; | 294 | goto next_entry; |
312 | } | 295 | } |
313 | 296 | ||
@@ -317,9 +300,8 @@ orinoco_cs_config(dev_link_t *link) | |||
317 | break; | 300 | break; |
318 | 301 | ||
319 | next_entry: | 302 | next_entry: |
320 | if (link->io.NumPorts1) | 303 | pcmcia_disable_device(link); |
321 | pcmcia_release_io(link->handle, &link->io); | 304 | last_ret = pcmcia_get_next_tuple(link, &tuple); |
322 | last_ret = pcmcia_get_next_tuple(handle, &tuple); | ||
323 | if (last_ret == CS_NO_MORE_ITEMS) { | 305 | if (last_ret == CS_NO_MORE_ITEMS) { |
324 | printk(KERN_ERR PFX "GetNextTuple(): No matching " | 306 | printk(KERN_ERR PFX "GetNextTuple(): No matching " |
325 | "CIS configuration. Maybe you need the " | 307 | "CIS configuration. Maybe you need the " |
@@ -333,7 +315,7 @@ orinoco_cs_config(dev_link_t *link) | |||
333 | * a handler to the interrupt, unless the 'Handler' member of | 315 | * a handler to the interrupt, unless the 'Handler' member of |
334 | * the irq structure is initialized. | 316 | * the irq structure is initialized. |
335 | */ | 317 | */ |
336 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 318 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
337 | 319 | ||
338 | /* We initialize the hermes structure before completing PCMCIA | 320 | /* We initialize the hermes structure before completing PCMCIA |
339 | * configuration just in case the interrupt handler gets | 321 | * configuration just in case the interrupt handler gets |
@@ -350,7 +332,7 @@ orinoco_cs_config(dev_link_t *link) | |||
350 | * card and host interface into "Memory and IO" mode. | 332 | * card and host interface into "Memory and IO" mode. |
351 | */ | 333 | */ |
352 | CS_CHECK(RequestConfiguration, | 334 | CS_CHECK(RequestConfiguration, |
353 | pcmcia_request_configuration(link->handle, &link->conf)); | 335 | pcmcia_request_configuration(link, &link->conf)); |
354 | 336 | ||
355 | /* Ok, we have the configuration, prepare to register the netdev */ | 337 | /* Ok, we have the configuration, prepare to register the netdev */ |
356 | dev->base_addr = link->io.BasePort1; | 338 | dev->base_addr = link->io.BasePort1; |
@@ -358,7 +340,7 @@ orinoco_cs_config(dev_link_t *link) | |||
358 | SET_MODULE_OWNER(dev); | 340 | SET_MODULE_OWNER(dev); |
359 | card->node.major = card->node.minor = 0; | 341 | card->node.major = card->node.minor = 0; |
360 | 342 | ||
361 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | 343 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
362 | /* Tell the stack we exist */ | 344 | /* Tell the stack we exist */ |
363 | if (register_netdev(dev) != 0) { | 345 | if (register_netdev(dev) != 0) { |
364 | printk(KERN_ERR PFX "register_netdev() failed\n"); | 346 | printk(KERN_ERR PFX "register_netdev() failed\n"); |
@@ -366,20 +348,18 @@ orinoco_cs_config(dev_link_t *link) | |||
366 | } | 348 | } |
367 | 349 | ||
368 | /* At this point, the dev_node_t structure(s) needs to be | 350 | /* At this point, the dev_node_t structure(s) needs to be |
369 | * initialized and arranged in a linked list at link->dev. */ | 351 | * initialized and arranged in a linked list at link->dev_node. */ |
370 | strcpy(card->node.dev_name, dev->name); | 352 | strcpy(card->node.dev_name, dev->name); |
371 | link->dev = &card->node; /* link->dev being non-NULL is also | 353 | link->dev_node = &card->node; /* link->dev_node being non-NULL is also |
372 | used to indicate that the | 354 | used to indicate that the |
373 | net_device has been registered */ | 355 | net_device has been registered */ |
374 | link->state &= ~DEV_CONFIG_PENDING; | ||
375 | 356 | ||
376 | /* Finally, report what we've done */ | 357 | /* Finally, report what we've done */ |
377 | printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d", | 358 | printk(KERN_DEBUG "%s: index 0x%02x: ", |
378 | dev->name, link->conf.ConfigIndex, | 359 | dev->name, link->conf.ConfigIndex); |
379 | link->conf.Vcc / 10, link->conf.Vcc % 10); | 360 | if (link->conf.Vpp) |
380 | if (link->conf.Vpp1) | 361 | printk(", Vpp %d.%d", link->conf.Vpp / 10, |
381 | printk(", Vpp %d.%d", link->conf.Vpp1 / 10, | 362 | link->conf.Vpp % 10); |
382 | link->conf.Vpp1 % 10); | ||
383 | printk(", irq %d", link->irq.AssignedIRQ); | 363 | printk(", irq %d", link->irq.AssignedIRQ); |
384 | if (link->io.NumPorts1) | 364 | if (link->io.NumPorts1) |
385 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, | 365 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, |
@@ -389,13 +369,14 @@ orinoco_cs_config(dev_link_t *link) | |||
389 | link->io.BasePort2 + link->io.NumPorts2 - 1); | 369 | link->io.BasePort2 + link->io.NumPorts2 - 1); |
390 | printk("\n"); | 370 | printk("\n"); |
391 | 371 | ||
392 | return; | 372 | return 0; |
393 | 373 | ||
394 | cs_failed: | 374 | cs_failed: |
395 | cs_error(link->handle, last_fn, last_ret); | 375 | cs_error(link, last_fn, last_ret); |
396 | 376 | ||
397 | failed: | 377 | failed: |
398 | orinoco_cs_release(link); | 378 | orinoco_cs_release(link); |
379 | return -ENODEV; | ||
399 | } /* orinoco_cs_config */ | 380 | } /* orinoco_cs_config */ |
400 | 381 | ||
401 | /* | 382 | /* |
@@ -404,7 +385,7 @@ orinoco_cs_config(dev_link_t *link) | |||
404 | * still open, this will be postponed until it is closed. | 385 | * still open, this will be postponed until it is closed. |
405 | */ | 386 | */ |
406 | static void | 387 | static void |
407 | orinoco_cs_release(dev_link_t *link) | 388 | orinoco_cs_release(struct pcmcia_device *link) |
408 | { | 389 | { |
409 | struct net_device *dev = link->priv; | 390 | struct net_device *dev = link->priv; |
410 | struct orinoco_private *priv = netdev_priv(dev); | 391 | struct orinoco_private *priv = netdev_priv(dev); |
@@ -416,88 +397,68 @@ orinoco_cs_release(dev_link_t *link) | |||
416 | priv->hw_unavailable++; | 397 | priv->hw_unavailable++; |
417 | spin_unlock_irqrestore(&priv->lock, flags); | 398 | spin_unlock_irqrestore(&priv->lock, flags); |
418 | 399 | ||
419 | /* Don't bother checking to see if these succeed or not */ | 400 | pcmcia_disable_device(link); |
420 | pcmcia_release_configuration(link->handle); | ||
421 | if (link->io.NumPorts1) | ||
422 | pcmcia_release_io(link->handle, &link->io); | ||
423 | if (link->irq.AssignedIRQ) | ||
424 | pcmcia_release_irq(link->handle, &link->irq); | ||
425 | link->state &= ~DEV_CONFIG; | ||
426 | if (priv->hw.iobase) | 401 | if (priv->hw.iobase) |
427 | ioport_unmap(priv->hw.iobase); | 402 | ioport_unmap(priv->hw.iobase); |
428 | } /* orinoco_cs_release */ | 403 | } /* orinoco_cs_release */ |
429 | 404 | ||
430 | static int orinoco_cs_suspend(struct pcmcia_device *p_dev) | 405 | static int orinoco_cs_suspend(struct pcmcia_device *link) |
431 | { | 406 | { |
432 | dev_link_t *link = dev_to_instance(p_dev); | ||
433 | struct net_device *dev = link->priv; | 407 | struct net_device *dev = link->priv; |
434 | struct orinoco_private *priv = netdev_priv(dev); | 408 | struct orinoco_private *priv = netdev_priv(dev); |
435 | struct orinoco_pccard *card = priv->card; | 409 | struct orinoco_pccard *card = priv->card; |
436 | int err = 0; | 410 | int err = 0; |
437 | unsigned long flags; | 411 | unsigned long flags; |
438 | 412 | ||
439 | link->state |= DEV_SUSPEND; | 413 | /* This is probably racy, but I can't think of |
440 | if (link->state & DEV_CONFIG) { | 414 | a better way, short of rewriting the PCMCIA |
441 | /* This is probably racy, but I can't think of | 415 | layer to not suck :-( */ |
442 | a better way, short of rewriting the PCMCIA | 416 | if (! test_bit(0, &card->hard_reset_in_progress)) { |
443 | layer to not suck :-( */ | 417 | spin_lock_irqsave(&priv->lock, flags); |
444 | if (! test_bit(0, &card->hard_reset_in_progress)) { | ||
445 | spin_lock_irqsave(&priv->lock, flags); | ||
446 | 418 | ||
447 | err = __orinoco_down(dev); | 419 | err = __orinoco_down(dev); |
448 | if (err) | 420 | if (err) |
449 | printk(KERN_WARNING "%s: Error %d downing interface\n", | 421 | printk(KERN_WARNING "%s: Error %d downing interface\n", |
450 | dev->name, err); | 422 | dev->name, err); |
451 | 423 | ||
452 | netif_device_detach(dev); | 424 | netif_device_detach(dev); |
453 | priv->hw_unavailable++; | 425 | priv->hw_unavailable++; |
454 | 426 | ||
455 | spin_unlock_irqrestore(&priv->lock, flags); | 427 | spin_unlock_irqrestore(&priv->lock, flags); |
456 | } | ||
457 | |||
458 | pcmcia_release_configuration(link->handle); | ||
459 | } | 428 | } |
460 | 429 | ||
461 | return 0; | 430 | return 0; |
462 | } | 431 | } |
463 | 432 | ||
464 | static int orinoco_cs_resume(struct pcmcia_device *p_dev) | 433 | static int orinoco_cs_resume(struct pcmcia_device *link) |
465 | { | 434 | { |
466 | dev_link_t *link = dev_to_instance(p_dev); | ||
467 | struct net_device *dev = link->priv; | 435 | struct net_device *dev = link->priv; |
468 | struct orinoco_private *priv = netdev_priv(dev); | 436 | struct orinoco_private *priv = netdev_priv(dev); |
469 | struct orinoco_pccard *card = priv->card; | 437 | struct orinoco_pccard *card = priv->card; |
470 | int err = 0; | 438 | int err = 0; |
471 | unsigned long flags; | 439 | unsigned long flags; |
472 | 440 | ||
473 | link->state &= ~DEV_SUSPEND; | 441 | if (! test_bit(0, &card->hard_reset_in_progress)) { |
474 | if (link->state & DEV_CONFIG) { | 442 | err = orinoco_reinit_firmware(dev); |
475 | /* FIXME: should we double check that this is | 443 | if (err) { |
476 | * the same card as we had before */ | 444 | printk(KERN_ERR "%s: Error %d re-initializing firmware\n", |
477 | pcmcia_request_configuration(link->handle, &link->conf); | 445 | dev->name, err); |
478 | 446 | return -EIO; | |
479 | if (! test_bit(0, &card->hard_reset_in_progress)) { | 447 | } |
480 | err = orinoco_reinit_firmware(dev); | ||
481 | if (err) { | ||
482 | printk(KERN_ERR "%s: Error %d re-initializing firmware\n", | ||
483 | dev->name, err); | ||
484 | return -EIO; | ||
485 | } | ||
486 | |||
487 | spin_lock_irqsave(&priv->lock, flags); | ||
488 | 448 | ||
489 | netif_device_attach(dev); | 449 | spin_lock_irqsave(&priv->lock, flags); |
490 | priv->hw_unavailable--; | ||
491 | 450 | ||
492 | if (priv->open && ! priv->hw_unavailable) { | 451 | netif_device_attach(dev); |
493 | err = __orinoco_up(dev); | 452 | priv->hw_unavailable--; |
494 | if (err) | ||
495 | printk(KERN_ERR "%s: Error %d restarting card\n", | ||
496 | dev->name, err); | ||
497 | } | ||
498 | 453 | ||
499 | spin_unlock_irqrestore(&priv->lock, flags); | 454 | if (priv->open && ! priv->hw_unavailable) { |
455 | err = __orinoco_up(dev); | ||
456 | if (err) | ||
457 | printk(KERN_ERR "%s: Error %d restarting card\n", | ||
458 | dev->name, err); | ||
500 | } | 459 | } |
460 | |||
461 | spin_unlock_irqrestore(&priv->lock, flags); | ||
501 | } | 462 | } |
502 | 463 | ||
503 | return 0; | 464 | return 0; |
@@ -604,7 +565,7 @@ static struct pcmcia_driver orinoco_driver = { | |||
604 | .drv = { | 565 | .drv = { |
605 | .name = DRIVER_NAME, | 566 | .name = DRIVER_NAME, |
606 | }, | 567 | }, |
607 | .probe = orinoco_cs_attach, | 568 | .probe = orinoco_cs_probe, |
608 | .remove = orinoco_cs_detach, | 569 | .remove = orinoco_cs_detach, |
609 | .id_table = orinoco_cs_ids, | 570 | .id_table = orinoco_cs_ids, |
610 | .suspend = orinoco_cs_suspend, | 571 | .suspend = orinoco_cs_suspend, |
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 7880d8c31aad..879eb427607c 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c | |||
@@ -90,8 +90,8 @@ module_param(pc_debug, int, 0); | |||
90 | #define DEBUG(n, args...) | 90 | #define DEBUG(n, args...) |
91 | #endif | 91 | #endif |
92 | /** Prototypes based on PCMCIA skeleton driver *******************************/ | 92 | /** Prototypes based on PCMCIA skeleton driver *******************************/ |
93 | static void ray_config(dev_link_t *link); | 93 | static int ray_config(struct pcmcia_device *link); |
94 | static void ray_release(dev_link_t *link); | 94 | static void ray_release(struct pcmcia_device *link); |
95 | static void ray_detach(struct pcmcia_device *p_dev); | 95 | static void ray_detach(struct pcmcia_device *p_dev); |
96 | 96 | ||
97 | /***** Prototypes indicated by device structure ******************************/ | 97 | /***** Prototypes indicated by device structure ******************************/ |
@@ -190,20 +190,17 @@ static int bc; | |||
190 | static char *phy_addr = NULL; | 190 | static char *phy_addr = NULL; |
191 | 191 | ||
192 | 192 | ||
193 | /* A linked list of "instances" of the ray device. Each actual | 193 | /* A struct pcmcia_device structure has fields for most things that are needed |
194 | PCMCIA card corresponds to one device instance, and is described | ||
195 | by one dev_link_t structure (defined in ds.h). | ||
196 | */ | ||
197 | static dev_link_t *dev_list = NULL; | ||
198 | |||
199 | /* A dev_link_t structure has fields for most things that are needed | ||
200 | to keep track of a socket, but there will usually be some device | 194 | to keep track of a socket, but there will usually be some device |
201 | specific information that also needs to be kept track of. The | 195 | specific information that also needs to be kept track of. The |
202 | 'priv' pointer in a dev_link_t structure can be used to point to | 196 | 'priv' pointer in a struct pcmcia_device structure can be used to point to |
203 | a device-specific private data structure, like this. | 197 | a device-specific private data structure, like this. |
204 | */ | 198 | */ |
205 | static unsigned int ray_mem_speed = 500; | 199 | static unsigned int ray_mem_speed = 500; |
206 | 200 | ||
201 | /* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */ | ||
202 | static struct pcmcia_device *this_device = NULL; | ||
203 | |||
207 | MODULE_AUTHOR("Corey Thomas <corey@world.std.com>"); | 204 | MODULE_AUTHOR("Corey Thomas <corey@world.std.com>"); |
208 | MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver"); | 205 | MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver"); |
209 | MODULE_LICENSE("GPL"); | 206 | MODULE_LICENSE("GPL"); |
@@ -306,56 +303,46 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world. | |||
306 | configure the card at this point -- we wait until we receive a | 303 | configure the card at this point -- we wait until we receive a |
307 | card insertion event. | 304 | card insertion event. |
308 | =============================================================================*/ | 305 | =============================================================================*/ |
309 | static int ray_attach(struct pcmcia_device *p_dev) | 306 | static int ray_probe(struct pcmcia_device *p_dev) |
310 | { | 307 | { |
311 | dev_link_t *link; | ||
312 | ray_dev_t *local; | 308 | ray_dev_t *local; |
313 | struct net_device *dev; | 309 | struct net_device *dev; |
314 | |||
315 | DEBUG(1, "ray_attach()\n"); | ||
316 | 310 | ||
317 | /* Initialize the dev_link_t structure */ | 311 | DEBUG(1, "ray_attach()\n"); |
318 | link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); | ||
319 | |||
320 | if (!link) | ||
321 | return -ENOMEM; | ||
322 | 312 | ||
323 | /* Allocate space for private device-specific data */ | 313 | /* Allocate space for private device-specific data */ |
324 | dev = alloc_etherdev(sizeof(ray_dev_t)); | 314 | dev = alloc_etherdev(sizeof(ray_dev_t)); |
325 | |||
326 | if (!dev) | 315 | if (!dev) |
327 | goto fail_alloc_dev; | 316 | goto fail_alloc_dev; |
328 | 317 | ||
329 | local = dev->priv; | 318 | local = dev->priv; |
330 | 319 | local->finder = p_dev; | |
331 | memset(link, 0, sizeof(struct dev_link_t)); | ||
332 | 320 | ||
333 | /* The io structure describes IO port mapping. None used here */ | 321 | /* The io structure describes IO port mapping. None used here */ |
334 | link->io.NumPorts1 = 0; | 322 | p_dev->io.NumPorts1 = 0; |
335 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 323 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
336 | link->io.IOAddrLines = 5; | 324 | p_dev->io.IOAddrLines = 5; |
337 | 325 | ||
338 | /* Interrupt setup. For PCMCIA, driver takes what's given */ | 326 | /* Interrupt setup. For PCMCIA, driver takes what's given */ |
339 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | 327 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; |
340 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 328 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
341 | link->irq.Handler = &ray_interrupt; | 329 | p_dev->irq.Handler = &ray_interrupt; |
342 | 330 | ||
343 | /* General socket configuration */ | 331 | /* General socket configuration */ |
344 | link->conf.Attributes = CONF_ENABLE_IRQ; | 332 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; |
345 | link->conf.Vcc = 50; | 333 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
346 | link->conf.IntType = INT_MEMORY_AND_IO; | 334 | p_dev->conf.ConfigIndex = 1; |
347 | link->conf.ConfigIndex = 1; | 335 | p_dev->conf.Present = PRESENT_OPTION; |
348 | link->conf.Present = PRESENT_OPTION; | 336 | |
349 | 337 | p_dev->priv = dev; | |
350 | link->priv = dev; | 338 | p_dev->irq.Instance = dev; |
351 | link->irq.Instance = dev; | ||
352 | 339 | ||
353 | local->finder = link; | 340 | local->finder = p_dev; |
354 | local->card_status = CARD_INSERTED; | 341 | local->card_status = CARD_INSERTED; |
355 | local->authentication_state = UNAUTHENTICATED; | 342 | local->authentication_state = UNAUTHENTICATED; |
356 | local->num_multi = 0; | 343 | local->num_multi = 0; |
357 | DEBUG(2,"ray_attach link = %p, dev = %p, local = %p, intr = %p\n", | 344 | DEBUG(2,"ray_attach p_dev = %p, dev = %p, local = %p, intr = %p\n", |
358 | link,dev,local,&ray_interrupt); | 345 | p_dev,dev,local,&ray_interrupt); |
359 | 346 | ||
360 | /* Raylink entries in the device structure */ | 347 | /* Raylink entries in the device structure */ |
361 | dev->hard_start_xmit = &ray_dev_start_xmit; | 348 | dev->hard_start_xmit = &ray_dev_start_xmit; |
@@ -379,16 +366,10 @@ static int ray_attach(struct pcmcia_device *p_dev) | |||
379 | 366 | ||
380 | init_timer(&local->timer); | 367 | init_timer(&local->timer); |
381 | 368 | ||
382 | link->handle = p_dev; | 369 | this_device = p_dev; |
383 | p_dev->instance = link; | 370 | return ray_config(p_dev); |
384 | |||
385 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
386 | ray_config(link); | ||
387 | |||
388 | return 0; | ||
389 | 371 | ||
390 | fail_alloc_dev: | 372 | fail_alloc_dev: |
391 | kfree(link); | ||
392 | return -ENOMEM; | 373 | return -ENOMEM; |
393 | } /* ray_attach */ | 374 | } /* ray_attach */ |
394 | /*============================================================================= | 375 | /*============================================================================= |
@@ -397,37 +378,25 @@ fail_alloc_dev: | |||
397 | structures are freed. Otherwise, the structures will be freed | 378 | structures are freed. Otherwise, the structures will be freed |
398 | when the device is released. | 379 | when the device is released. |
399 | =============================================================================*/ | 380 | =============================================================================*/ |
400 | static void ray_detach(struct pcmcia_device *p_dev) | 381 | static void ray_detach(struct pcmcia_device *link) |
401 | { | 382 | { |
402 | dev_link_t *link = dev_to_instance(p_dev); | ||
403 | dev_link_t **linkp; | ||
404 | struct net_device *dev; | 383 | struct net_device *dev; |
405 | ray_dev_t *local; | 384 | ray_dev_t *local; |
406 | 385 | ||
407 | DEBUG(1, "ray_detach(0x%p)\n", link); | 386 | DEBUG(1, "ray_detach(0x%p)\n", link); |
408 | |||
409 | /* Locate device structure */ | ||
410 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
411 | if (*linkp == link) break; | ||
412 | if (*linkp == NULL) | ||
413 | return; | ||
414 | 387 | ||
388 | this_device = NULL; | ||
415 | dev = link->priv; | 389 | dev = link->priv; |
416 | 390 | ||
417 | if (link->state & DEV_CONFIG) { | 391 | ray_release(link); |
418 | ray_release(link); | ||
419 | 392 | ||
420 | local = (ray_dev_t *)dev->priv; | 393 | local = (ray_dev_t *)dev->priv; |
421 | del_timer(&local->timer); | 394 | del_timer(&local->timer); |
422 | } | ||
423 | 395 | ||
424 | /* Unlink device structure, free pieces */ | ||
425 | *linkp = link->next; | ||
426 | if (link->priv) { | 396 | if (link->priv) { |
427 | if (link->dev) unregister_netdev(dev); | 397 | if (link->dev_node) unregister_netdev(dev); |
428 | free_netdev(dev); | 398 | free_netdev(dev); |
429 | } | 399 | } |
430 | kfree(link); | ||
431 | DEBUG(2,"ray_cs ray_detach ending\n"); | 400 | DEBUG(2,"ray_cs ray_detach ending\n"); |
432 | } /* ray_detach */ | 401 | } /* ray_detach */ |
433 | /*============================================================================= | 402 | /*============================================================================= |
@@ -438,9 +407,8 @@ static void ray_detach(struct pcmcia_device *p_dev) | |||
438 | #define CS_CHECK(fn, ret) \ | 407 | #define CS_CHECK(fn, ret) \ |
439 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 408 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
440 | #define MAX_TUPLE_SIZE 128 | 409 | #define MAX_TUPLE_SIZE 128 |
441 | static void ray_config(dev_link_t *link) | 410 | static int ray_config(struct pcmcia_device *link) |
442 | { | 411 | { |
443 | client_handle_t handle = link->handle; | ||
444 | tuple_t tuple; | 412 | tuple_t tuple; |
445 | cisparse_t parse; | 413 | cisparse_t parse; |
446 | int last_fn = 0, last_ret = 0; | 414 | int last_fn = 0, last_ret = 0; |
@@ -455,48 +423,45 @@ static void ray_config(dev_link_t *link) | |||
455 | 423 | ||
456 | /* This reads the card's CONFIG tuple to find its configuration regs */ | 424 | /* This reads the card's CONFIG tuple to find its configuration regs */ |
457 | tuple.DesiredTuple = CISTPL_CONFIG; | 425 | tuple.DesiredTuple = CISTPL_CONFIG; |
458 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 426 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
459 | tuple.TupleData = buf; | 427 | tuple.TupleData = buf; |
460 | tuple.TupleDataMax = MAX_TUPLE_SIZE; | 428 | tuple.TupleDataMax = MAX_TUPLE_SIZE; |
461 | tuple.TupleOffset = 0; | 429 | tuple.TupleOffset = 0; |
462 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 430 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
463 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 431 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
464 | link->conf.ConfigBase = parse.config.base; | 432 | link->conf.ConfigBase = parse.config.base; |
465 | link->conf.Present = parse.config.rmask[0]; | 433 | link->conf.Present = parse.config.rmask[0]; |
466 | 434 | ||
467 | /* Determine card type and firmware version */ | 435 | /* Determine card type and firmware version */ |
468 | buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0; | 436 | buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0; |
469 | tuple.DesiredTuple = CISTPL_VERS_1; | 437 | tuple.DesiredTuple = CISTPL_VERS_1; |
470 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 438 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
471 | tuple.TupleData = buf; | 439 | tuple.TupleData = buf; |
472 | tuple.TupleDataMax = MAX_TUPLE_SIZE; | 440 | tuple.TupleDataMax = MAX_TUPLE_SIZE; |
473 | tuple.TupleOffset = 2; | 441 | tuple.TupleOffset = 2; |
474 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 442 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
475 | 443 | ||
476 | for (i=0; i<tuple.TupleDataLen - 4; i++) | 444 | for (i=0; i<tuple.TupleDataLen - 4; i++) |
477 | if (buf[i] == 0) buf[i] = ' '; | 445 | if (buf[i] == 0) buf[i] = ' '; |
478 | printk(KERN_INFO "ray_cs Detected: %s\n",buf); | 446 | printk(KERN_INFO "ray_cs Detected: %s\n",buf); |
479 | 447 | ||
480 | /* Configure card */ | ||
481 | link->state |= DEV_CONFIG; | ||
482 | |||
483 | /* Now allocate an interrupt line. Note that this does not | 448 | /* Now allocate an interrupt line. Note that this does not |
484 | actually assign a handler to the interrupt. | 449 | actually assign a handler to the interrupt. |
485 | */ | 450 | */ |
486 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 451 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
487 | dev->irq = link->irq.AssignedIRQ; | 452 | dev->irq = link->irq.AssignedIRQ; |
488 | 453 | ||
489 | /* This actually configures the PCMCIA socket -- setting up | 454 | /* This actually configures the PCMCIA socket -- setting up |
490 | the I/O windows and the interrupt mapping. | 455 | the I/O windows and the interrupt mapping. |
491 | */ | 456 | */ |
492 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 457 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
493 | 458 | ||
494 | /*** Set up 32k window for shared memory (transmit and control) ************/ | 459 | /*** Set up 32k window for shared memory (transmit and control) ************/ |
495 | req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; | 460 | req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; |
496 | req.Base = 0; | 461 | req.Base = 0; |
497 | req.Size = 0x8000; | 462 | req.Size = 0x8000; |
498 | req.AccessSpeed = ray_mem_speed; | 463 | req.AccessSpeed = ray_mem_speed; |
499 | CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win)); | 464 | CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); |
500 | mem.CardOffset = 0x0000; mem.Page = 0; | 465 | mem.CardOffset = 0x0000; mem.Page = 0; |
501 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); | 466 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); |
502 | local->sram = ioremap(req.Base,req.Size); | 467 | local->sram = ioremap(req.Base,req.Size); |
@@ -506,7 +471,7 @@ static void ray_config(dev_link_t *link) | |||
506 | req.Base = 0; | 471 | req.Base = 0; |
507 | req.Size = 0x4000; | 472 | req.Size = 0x4000; |
508 | req.AccessSpeed = ray_mem_speed; | 473 | req.AccessSpeed = ray_mem_speed; |
509 | CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle)); | 474 | CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->rmem_handle)); |
510 | mem.CardOffset = 0x8000; mem.Page = 0; | 475 | mem.CardOffset = 0x8000; mem.Page = 0; |
511 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem)); | 476 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem)); |
512 | local->rmem = ioremap(req.Base,req.Size); | 477 | local->rmem = ioremap(req.Base,req.Size); |
@@ -516,7 +481,7 @@ static void ray_config(dev_link_t *link) | |||
516 | req.Base = 0; | 481 | req.Base = 0; |
517 | req.Size = 0x1000; | 482 | req.Size = 0x1000; |
518 | req.AccessSpeed = ray_mem_speed; | 483 | req.AccessSpeed = ray_mem_speed; |
519 | CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle)); | 484 | CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &local->amem_handle)); |
520 | mem.CardOffset = 0x0000; mem.Page = 0; | 485 | mem.CardOffset = 0x0000; mem.Page = 0; |
521 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem)); | 486 | CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem)); |
522 | local->amem = ioremap(req.Base,req.Size); | 487 | local->amem = ioremap(req.Base,req.Size); |
@@ -526,32 +491,32 @@ static void ray_config(dev_link_t *link) | |||
526 | DEBUG(3,"ray_config amem=%p\n",local->amem); | 491 | DEBUG(3,"ray_config amem=%p\n",local->amem); |
527 | if (ray_init(dev) < 0) { | 492 | if (ray_init(dev) < 0) { |
528 | ray_release(link); | 493 | ray_release(link); |
529 | return; | 494 | return -ENODEV; |
530 | } | 495 | } |
531 | 496 | ||
532 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | 497 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
533 | i = register_netdev(dev); | 498 | i = register_netdev(dev); |
534 | if (i != 0) { | 499 | if (i != 0) { |
535 | printk("ray_config register_netdev() failed\n"); | 500 | printk("ray_config register_netdev() failed\n"); |
536 | ray_release(link); | 501 | ray_release(link); |
537 | return; | 502 | return i; |
538 | } | 503 | } |
539 | 504 | ||
540 | strcpy(local->node.dev_name, dev->name); | 505 | strcpy(local->node.dev_name, dev->name); |
541 | link->dev = &local->node; | 506 | link->dev_node = &local->node; |
542 | 507 | ||
543 | link->state &= ~DEV_CONFIG_PENDING; | ||
544 | printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ", | 508 | printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ", |
545 | dev->name, dev->irq); | 509 | dev->name, dev->irq); |
546 | for (i = 0; i < 6; i++) | 510 | for (i = 0; i < 6; i++) |
547 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); | 511 | printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n")); |
548 | 512 | ||
549 | return; | 513 | return 0; |
550 | 514 | ||
551 | cs_failed: | 515 | cs_failed: |
552 | cs_error(link->handle, last_fn, last_ret); | 516 | cs_error(link, last_fn, last_ret); |
553 | 517 | ||
554 | ray_release(link); | 518 | ray_release(link); |
519 | return -ENODEV; | ||
555 | } /* ray_config */ | 520 | } /* ray_config */ |
556 | 521 | ||
557 | static inline struct ccs __iomem *ccs_base(ray_dev_t *dev) | 522 | static inline struct ccs __iomem *ccs_base(ray_dev_t *dev) |
@@ -578,9 +543,9 @@ static int ray_init(struct net_device *dev) | |||
578 | UCHAR *p; | 543 | UCHAR *p; |
579 | struct ccs __iomem *pccs; | 544 | struct ccs __iomem *pccs; |
580 | ray_dev_t *local = (ray_dev_t *)dev->priv; | 545 | ray_dev_t *local = (ray_dev_t *)dev->priv; |
581 | dev_link_t *link = local->finder; | 546 | struct pcmcia_device *link = local->finder; |
582 | DEBUG(1, "ray_init(0x%p)\n", dev); | 547 | DEBUG(1, "ray_init(0x%p)\n", dev); |
583 | if (!(link->state & DEV_PRESENT)) { | 548 | if (!(pcmcia_dev_present(link))) { |
584 | DEBUG(0,"ray_init - device not present\n"); | 549 | DEBUG(0,"ray_init - device not present\n"); |
585 | return -1; | 550 | return -1; |
586 | } | 551 | } |
@@ -640,10 +605,10 @@ static int dl_startup_params(struct net_device *dev) | |||
640 | int ccsindex; | 605 | int ccsindex; |
641 | ray_dev_t *local = (ray_dev_t *)dev->priv; | 606 | ray_dev_t *local = (ray_dev_t *)dev->priv; |
642 | struct ccs __iomem *pccs; | 607 | struct ccs __iomem *pccs; |
643 | dev_link_t *link = local->finder; | 608 | struct pcmcia_device *link = local->finder; |
644 | 609 | ||
645 | DEBUG(1,"dl_startup_params entered\n"); | 610 | DEBUG(1,"dl_startup_params entered\n"); |
646 | if (!(link->state & DEV_PRESENT)) { | 611 | if (!(pcmcia_dev_present(link))) { |
647 | DEBUG(2,"ray_cs dl_startup_params - device not present\n"); | 612 | DEBUG(2,"ray_cs dl_startup_params - device not present\n"); |
648 | return -1; | 613 | return -1; |
649 | } | 614 | } |
@@ -747,9 +712,9 @@ static void verify_dl_startup(u_long data) | |||
747 | ray_dev_t *local = (ray_dev_t *)data; | 712 | ray_dev_t *local = (ray_dev_t *)data; |
748 | struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs; | 713 | struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs; |
749 | UCHAR status; | 714 | UCHAR status; |
750 | dev_link_t *link = local->finder; | 715 | struct pcmcia_device *link = local->finder; |
751 | 716 | ||
752 | if (!(link->state & DEV_PRESENT)) { | 717 | if (!(pcmcia_dev_present(link))) { |
753 | DEBUG(2,"ray_cs verify_dl_startup - device not present\n"); | 718 | DEBUG(2,"ray_cs verify_dl_startup - device not present\n"); |
754 | return; | 719 | return; |
755 | } | 720 | } |
@@ -787,8 +752,8 @@ static void start_net(u_long data) | |||
787 | ray_dev_t *local = (ray_dev_t *)data; | 752 | ray_dev_t *local = (ray_dev_t *)data; |
788 | struct ccs __iomem *pccs; | 753 | struct ccs __iomem *pccs; |
789 | int ccsindex; | 754 | int ccsindex; |
790 | dev_link_t *link = local->finder; | 755 | struct pcmcia_device *link = local->finder; |
791 | if (!(link->state & DEV_PRESENT)) { | 756 | if (!(pcmcia_dev_present(link))) { |
792 | DEBUG(2,"ray_cs start_net - device not present\n"); | 757 | DEBUG(2,"ray_cs start_net - device not present\n"); |
793 | return; | 758 | return; |
794 | } | 759 | } |
@@ -814,9 +779,9 @@ static void join_net(u_long data) | |||
814 | 779 | ||
815 | struct ccs __iomem *pccs; | 780 | struct ccs __iomem *pccs; |
816 | int ccsindex; | 781 | int ccsindex; |
817 | dev_link_t *link = local->finder; | 782 | struct pcmcia_device *link = local->finder; |
818 | 783 | ||
819 | if (!(link->state & DEV_PRESENT)) { | 784 | if (!(pcmcia_dev_present(link))) { |
820 | DEBUG(2,"ray_cs join_net - device not present\n"); | 785 | DEBUG(2,"ray_cs join_net - device not present\n"); |
821 | return; | 786 | return; |
822 | } | 787 | } |
@@ -840,7 +805,7 @@ static void join_net(u_long data) | |||
840 | device, and release the PCMCIA configuration. If the device is | 805 | device, and release the PCMCIA configuration. If the device is |
841 | still open, this will be postponed until it is closed. | 806 | still open, this will be postponed until it is closed. |
842 | =============================================================================*/ | 807 | =============================================================================*/ |
843 | static void ray_release(dev_link_t *link) | 808 | static void ray_release(struct pcmcia_device *link) |
844 | { | 809 | { |
845 | struct net_device *dev = link->priv; | 810 | struct net_device *dev = link->priv; |
846 | ray_dev_t *local = dev->priv; | 811 | ray_dev_t *local = dev->priv; |
@@ -849,56 +814,38 @@ static void ray_release(dev_link_t *link) | |||
849 | DEBUG(1, "ray_release(0x%p)\n", link); | 814 | DEBUG(1, "ray_release(0x%p)\n", link); |
850 | 815 | ||
851 | del_timer(&local->timer); | 816 | del_timer(&local->timer); |
852 | link->state &= ~DEV_CONFIG; | ||
853 | 817 | ||
854 | iounmap(local->sram); | 818 | iounmap(local->sram); |
855 | iounmap(local->rmem); | 819 | iounmap(local->rmem); |
856 | iounmap(local->amem); | 820 | iounmap(local->amem); |
857 | /* Do bother checking to see if these succeed or not */ | 821 | /* Do bother checking to see if these succeed or not */ |
858 | i = pcmcia_release_window(link->win); | ||
859 | if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(link->win) ret = %x\n",i); | ||
860 | i = pcmcia_release_window(local->amem_handle); | 822 | i = pcmcia_release_window(local->amem_handle); |
861 | if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i); | 823 | if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i); |
862 | i = pcmcia_release_window(local->rmem_handle); | 824 | i = pcmcia_release_window(local->rmem_handle); |
863 | if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i); | 825 | if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i); |
864 | i = pcmcia_release_configuration(link->handle); | 826 | pcmcia_disable_device(link); |
865 | if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseConfiguration ret = %x\n",i); | ||
866 | i = pcmcia_release_irq(link->handle, &link->irq); | ||
867 | if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i); | ||
868 | 827 | ||
869 | DEBUG(2,"ray_release ending\n"); | 828 | DEBUG(2,"ray_release ending\n"); |
870 | } | 829 | } |
871 | 830 | ||
872 | static int ray_suspend(struct pcmcia_device *p_dev) | 831 | static int ray_suspend(struct pcmcia_device *link) |
873 | { | 832 | { |
874 | dev_link_t *link = dev_to_instance(p_dev); | ||
875 | struct net_device *dev = link->priv; | 833 | struct net_device *dev = link->priv; |
876 | 834 | ||
877 | link->state |= DEV_SUSPEND; | 835 | if (link->open) |
878 | if (link->state & DEV_CONFIG) { | 836 | netif_device_detach(dev); |
879 | if (link->open) | ||
880 | netif_device_detach(dev); | ||
881 | |||
882 | pcmcia_release_configuration(link->handle); | ||
883 | } | ||
884 | |||
885 | 837 | ||
886 | return 0; | 838 | return 0; |
887 | } | 839 | } |
888 | 840 | ||
889 | static int ray_resume(struct pcmcia_device *p_dev) | 841 | static int ray_resume(struct pcmcia_device *link) |
890 | { | 842 | { |
891 | dev_link_t *link = dev_to_instance(p_dev); | ||
892 | struct net_device *dev = link->priv; | 843 | struct net_device *dev = link->priv; |
893 | 844 | ||
894 | link->state &= ~DEV_SUSPEND; | 845 | if (link->open) { |
895 | if (link->state & DEV_CONFIG) { | 846 | ray_reset(dev); |
896 | pcmcia_request_configuration(link->handle, &link->conf); | 847 | netif_device_attach(dev); |
897 | if (link->open) { | 848 | } |
898 | ray_reset(dev); | ||
899 | netif_device_attach(dev); | ||
900 | } | ||
901 | } | ||
902 | 849 | ||
903 | return 0; | 850 | return 0; |
904 | } | 851 | } |
@@ -910,10 +857,10 @@ int ray_dev_init(struct net_device *dev) | |||
910 | int i; | 857 | int i; |
911 | #endif /* RAY_IMMEDIATE_INIT */ | 858 | #endif /* RAY_IMMEDIATE_INIT */ |
912 | ray_dev_t *local = dev->priv; | 859 | ray_dev_t *local = dev->priv; |
913 | dev_link_t *link = local->finder; | 860 | struct pcmcia_device *link = local->finder; |
914 | 861 | ||
915 | DEBUG(1,"ray_dev_init(dev=%p)\n",dev); | 862 | DEBUG(1,"ray_dev_init(dev=%p)\n",dev); |
916 | if (!(link->state & DEV_PRESENT)) { | 863 | if (!(pcmcia_dev_present(link))) { |
917 | DEBUG(2,"ray_dev_init - device not present\n"); | 864 | DEBUG(2,"ray_dev_init - device not present\n"); |
918 | return -1; | 865 | return -1; |
919 | } | 866 | } |
@@ -944,10 +891,10 @@ int ray_dev_init(struct net_device *dev) | |||
944 | static int ray_dev_config(struct net_device *dev, struct ifmap *map) | 891 | static int ray_dev_config(struct net_device *dev, struct ifmap *map) |
945 | { | 892 | { |
946 | ray_dev_t *local = dev->priv; | 893 | ray_dev_t *local = dev->priv; |
947 | dev_link_t *link = local->finder; | 894 | struct pcmcia_device *link = local->finder; |
948 | /* Dummy routine to satisfy device structure */ | 895 | /* Dummy routine to satisfy device structure */ |
949 | DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map); | 896 | DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map); |
950 | if (!(link->state & DEV_PRESENT)) { | 897 | if (!(pcmcia_dev_present(link))) { |
951 | DEBUG(2,"ray_dev_config - device not present\n"); | 898 | DEBUG(2,"ray_dev_config - device not present\n"); |
952 | return -1; | 899 | return -1; |
953 | } | 900 | } |
@@ -958,10 +905,10 @@ static int ray_dev_config(struct net_device *dev, struct ifmap *map) | |||
958 | static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) | 905 | static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev) |
959 | { | 906 | { |
960 | ray_dev_t *local = dev->priv; | 907 | ray_dev_t *local = dev->priv; |
961 | dev_link_t *link = local->finder; | 908 | struct pcmcia_device *link = local->finder; |
962 | short length = skb->len; | 909 | short length = skb->len; |
963 | 910 | ||
964 | if (!(link->state & DEV_PRESENT)) { | 911 | if (!(pcmcia_dev_present(link))) { |
965 | DEBUG(2,"ray_dev_start_xmit - device not present\n"); | 912 | DEBUG(2,"ray_dev_start_xmit - device not present\n"); |
966 | return -1; | 913 | return -1; |
967 | } | 914 | } |
@@ -1570,7 +1517,7 @@ static int ray_commit(struct net_device *dev, | |||
1570 | static iw_stats * ray_get_wireless_stats(struct net_device * dev) | 1517 | static iw_stats * ray_get_wireless_stats(struct net_device * dev) |
1571 | { | 1518 | { |
1572 | ray_dev_t * local = (ray_dev_t *) dev->priv; | 1519 | ray_dev_t * local = (ray_dev_t *) dev->priv; |
1573 | dev_link_t *link = local->finder; | 1520 | struct pcmcia_device *link = local->finder; |
1574 | struct status __iomem *p = local->sram + STATUS_BASE; | 1521 | struct status __iomem *p = local->sram + STATUS_BASE; |
1575 | 1522 | ||
1576 | if(local == (ray_dev_t *) NULL) | 1523 | if(local == (ray_dev_t *) NULL) |
@@ -1588,7 +1535,7 @@ static iw_stats * ray_get_wireless_stats(struct net_device * dev) | |||
1588 | } | 1535 | } |
1589 | #endif /* WIRELESS_SPY */ | 1536 | #endif /* WIRELESS_SPY */ |
1590 | 1537 | ||
1591 | if((link->state & DEV_PRESENT)) { | 1538 | if(pcmcia_dev_present(link)) { |
1592 | local->wstats.qual.noise = readb(&p->rxnoise); | 1539 | local->wstats.qual.noise = readb(&p->rxnoise); |
1593 | local->wstats.qual.updated |= 4; | 1540 | local->wstats.qual.updated |= 4; |
1594 | } | 1541 | } |
@@ -1657,18 +1604,14 @@ static const struct iw_handler_def ray_handler_def = | |||
1657 | /*===========================================================================*/ | 1604 | /*===========================================================================*/ |
1658 | static int ray_open(struct net_device *dev) | 1605 | static int ray_open(struct net_device *dev) |
1659 | { | 1606 | { |
1660 | dev_link_t *link; | ||
1661 | ray_dev_t *local = (ray_dev_t *)dev->priv; | 1607 | ray_dev_t *local = (ray_dev_t *)dev->priv; |
1608 | struct pcmcia_device *link; | ||
1609 | link = local->finder; | ||
1662 | 1610 | ||
1663 | DEBUG(1, "ray_open('%s')\n", dev->name); | 1611 | DEBUG(1, "ray_open('%s')\n", dev->name); |
1664 | 1612 | ||
1665 | for (link = dev_list; link; link = link->next) | 1613 | if (link->open == 0) |
1666 | if (link->priv == dev) break; | 1614 | local->num_multi = 0; |
1667 | if (!DEV_OK(link)) { | ||
1668 | return -ENODEV; | ||
1669 | } | ||
1670 | |||
1671 | if (link->open == 0) local->num_multi = 0; | ||
1672 | link->open++; | 1615 | link->open++; |
1673 | 1616 | ||
1674 | /* If the card is not started, time to start it ! - Jean II */ | 1617 | /* If the card is not started, time to start it ! - Jean II */ |
@@ -1695,15 +1638,12 @@ static int ray_open(struct net_device *dev) | |||
1695 | /*===========================================================================*/ | 1638 | /*===========================================================================*/ |
1696 | static int ray_dev_close(struct net_device *dev) | 1639 | static int ray_dev_close(struct net_device *dev) |
1697 | { | 1640 | { |
1698 | dev_link_t *link; | 1641 | ray_dev_t *local = (ray_dev_t *)dev->priv; |
1642 | struct pcmcia_device *link; | ||
1643 | link = local->finder; | ||
1699 | 1644 | ||
1700 | DEBUG(1, "ray_dev_close('%s')\n", dev->name); | 1645 | DEBUG(1, "ray_dev_close('%s')\n", dev->name); |
1701 | 1646 | ||
1702 | for (link = dev_list; link; link = link->next) | ||
1703 | if (link->priv == dev) break; | ||
1704 | if (link == NULL) | ||
1705 | return -ENODEV; | ||
1706 | |||
1707 | link->open--; | 1647 | link->open--; |
1708 | netif_stop_queue(dev); | 1648 | netif_stop_queue(dev); |
1709 | 1649 | ||
@@ -1725,9 +1665,9 @@ static void ray_reset(struct net_device *dev) { | |||
1725 | static int interrupt_ecf(ray_dev_t *local, int ccs) | 1665 | static int interrupt_ecf(ray_dev_t *local, int ccs) |
1726 | { | 1666 | { |
1727 | int i = 50; | 1667 | int i = 50; |
1728 | dev_link_t *link = local->finder; | 1668 | struct pcmcia_device *link = local->finder; |
1729 | 1669 | ||
1730 | if (!(link->state & DEV_PRESENT)) { | 1670 | if (!(pcmcia_dev_present(link))) { |
1731 | DEBUG(2,"ray_cs interrupt_ecf - device not present\n"); | 1671 | DEBUG(2,"ray_cs interrupt_ecf - device not present\n"); |
1732 | return -1; | 1672 | return -1; |
1733 | } | 1673 | } |
@@ -1752,9 +1692,9 @@ static int get_free_tx_ccs(ray_dev_t *local) | |||
1752 | { | 1692 | { |
1753 | int i; | 1693 | int i; |
1754 | struct ccs __iomem *pccs = ccs_base(local); | 1694 | struct ccs __iomem *pccs = ccs_base(local); |
1755 | dev_link_t *link = local->finder; | 1695 | struct pcmcia_device *link = local->finder; |
1756 | 1696 | ||
1757 | if (!(link->state & DEV_PRESENT)) { | 1697 | if (!(pcmcia_dev_present(link))) { |
1758 | DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n"); | 1698 | DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n"); |
1759 | return ECARDGONE; | 1699 | return ECARDGONE; |
1760 | } | 1700 | } |
@@ -1783,9 +1723,9 @@ static int get_free_ccs(ray_dev_t *local) | |||
1783 | { | 1723 | { |
1784 | int i; | 1724 | int i; |
1785 | struct ccs __iomem *pccs = ccs_base(local); | 1725 | struct ccs __iomem *pccs = ccs_base(local); |
1786 | dev_link_t *link = local->finder; | 1726 | struct pcmcia_device *link = local->finder; |
1787 | 1727 | ||
1788 | if (!(link->state & DEV_PRESENT)) { | 1728 | if (!(pcmcia_dev_present(link))) { |
1789 | DEBUG(2,"ray_cs get_free_ccs - device not present\n"); | 1729 | DEBUG(2,"ray_cs get_free_ccs - device not present\n"); |
1790 | return ECARDGONE; | 1730 | return ECARDGONE; |
1791 | } | 1731 | } |
@@ -1858,9 +1798,9 @@ static int parse_addr(char *in_str, UCHAR *out) | |||
1858 | static struct net_device_stats *ray_get_stats(struct net_device *dev) | 1798 | static struct net_device_stats *ray_get_stats(struct net_device *dev) |
1859 | { | 1799 | { |
1860 | ray_dev_t *local = (ray_dev_t *)dev->priv; | 1800 | ray_dev_t *local = (ray_dev_t *)dev->priv; |
1861 | dev_link_t *link = local->finder; | 1801 | struct pcmcia_device *link = local->finder; |
1862 | struct status __iomem *p = local->sram + STATUS_BASE; | 1802 | struct status __iomem *p = local->sram + STATUS_BASE; |
1863 | if (!(link->state & DEV_PRESENT)) { | 1803 | if (!(pcmcia_dev_present(link))) { |
1864 | DEBUG(2,"ray_cs net_device_stats - device not present\n"); | 1804 | DEBUG(2,"ray_cs net_device_stats - device not present\n"); |
1865 | return &local->stats; | 1805 | return &local->stats; |
1866 | } | 1806 | } |
@@ -1888,12 +1828,12 @@ static struct net_device_stats *ray_get_stats(struct net_device *dev) | |||
1888 | static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len) | 1828 | static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len) |
1889 | { | 1829 | { |
1890 | ray_dev_t *local = (ray_dev_t *)dev->priv; | 1830 | ray_dev_t *local = (ray_dev_t *)dev->priv; |
1891 | dev_link_t *link = local->finder; | 1831 | struct pcmcia_device *link = local->finder; |
1892 | int ccsindex; | 1832 | int ccsindex; |
1893 | int i; | 1833 | int i; |
1894 | struct ccs __iomem *pccs; | 1834 | struct ccs __iomem *pccs; |
1895 | 1835 | ||
1896 | if (!(link->state & DEV_PRESENT)) { | 1836 | if (!(pcmcia_dev_present(link))) { |
1897 | DEBUG(2,"ray_update_parm - device not present\n"); | 1837 | DEBUG(2,"ray_update_parm - device not present\n"); |
1898 | return; | 1838 | return; |
1899 | } | 1839 | } |
@@ -1925,10 +1865,10 @@ static void ray_update_multi_list(struct net_device *dev, int all) | |||
1925 | struct ccs __iomem *pccs; | 1865 | struct ccs __iomem *pccs; |
1926 | int i = 0; | 1866 | int i = 0; |
1927 | ray_dev_t *local = (ray_dev_t *)dev->priv; | 1867 | ray_dev_t *local = (ray_dev_t *)dev->priv; |
1928 | dev_link_t *link = local->finder; | 1868 | struct pcmcia_device *link = local->finder; |
1929 | void __iomem *p = local->sram + HOST_TO_ECF_BASE; | 1869 | void __iomem *p = local->sram + HOST_TO_ECF_BASE; |
1930 | 1870 | ||
1931 | if (!(link->state & DEV_PRESENT)) { | 1871 | if (!(pcmcia_dev_present(link))) { |
1932 | DEBUG(2,"ray_update_multi_list - device not present\n"); | 1872 | DEBUG(2,"ray_update_multi_list - device not present\n"); |
1933 | return; | 1873 | return; |
1934 | } | 1874 | } |
@@ -2005,7 +1945,7 @@ static void set_multicast_list(struct net_device *dev) | |||
2005 | static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) | 1945 | static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) |
2006 | { | 1946 | { |
2007 | struct net_device *dev = (struct net_device *)dev_id; | 1947 | struct net_device *dev = (struct net_device *)dev_id; |
2008 | dev_link_t *link; | 1948 | struct pcmcia_device *link; |
2009 | ray_dev_t *local; | 1949 | ray_dev_t *local; |
2010 | struct ccs __iomem *pccs; | 1950 | struct ccs __iomem *pccs; |
2011 | struct rcs __iomem *prcs; | 1951 | struct rcs __iomem *prcs; |
@@ -2020,8 +1960,8 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) | |||
2020 | DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev); | 1960 | DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev); |
2021 | 1961 | ||
2022 | local = (ray_dev_t *)dev->priv; | 1962 | local = (ray_dev_t *)dev->priv; |
2023 | link = (dev_link_t *)local->finder; | 1963 | link = (struct pcmcia_device *)local->finder; |
2024 | if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) { | 1964 | if (!pcmcia_dev_present(link)) { |
2025 | DEBUG(2,"ray_cs interrupt from device not present or suspended.\n"); | 1965 | DEBUG(2,"ray_cs interrupt from device not present or suspended.\n"); |
2026 | return IRQ_NONE; | 1966 | return IRQ_NONE; |
2027 | } | 1967 | } |
@@ -2540,9 +2480,9 @@ static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs) | |||
2540 | /*===========================================================================*/ | 2480 | /*===========================================================================*/ |
2541 | static void authenticate(ray_dev_t *local) | 2481 | static void authenticate(ray_dev_t *local) |
2542 | { | 2482 | { |
2543 | dev_link_t *link = local->finder; | 2483 | struct pcmcia_device *link = local->finder; |
2544 | DEBUG(0,"ray_cs Starting authentication.\n"); | 2484 | DEBUG(0,"ray_cs Starting authentication.\n"); |
2545 | if (!(link->state & DEV_PRESENT)) { | 2485 | if (!(pcmcia_dev_present(link))) { |
2546 | DEBUG(2,"ray_cs authenticate - device not present\n"); | 2486 | DEBUG(2,"ray_cs authenticate - device not present\n"); |
2547 | return; | 2487 | return; |
2548 | } | 2488 | } |
@@ -2606,10 +2546,10 @@ static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, | |||
2606 | static void associate(ray_dev_t *local) | 2546 | static void associate(ray_dev_t *local) |
2607 | { | 2547 | { |
2608 | struct ccs __iomem *pccs; | 2548 | struct ccs __iomem *pccs; |
2609 | dev_link_t *link = local->finder; | 2549 | struct pcmcia_device *link = local->finder; |
2610 | struct net_device *dev = link->priv; | 2550 | struct net_device *dev = link->priv; |
2611 | int ccsindex; | 2551 | int ccsindex; |
2612 | if (!(link->state & DEV_PRESENT)) { | 2552 | if (!(pcmcia_dev_present(link))) { |
2613 | DEBUG(2,"ray_cs associate - device not present\n"); | 2553 | DEBUG(2,"ray_cs associate - device not present\n"); |
2614 | return; | 2554 | return; |
2615 | } | 2555 | } |
@@ -2689,14 +2629,14 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len) | |||
2689 | * eg ifconfig | 2629 | * eg ifconfig |
2690 | */ | 2630 | */ |
2691 | int i; | 2631 | int i; |
2692 | dev_link_t *link; | 2632 | struct pcmcia_device *link; |
2693 | struct net_device *dev; | 2633 | struct net_device *dev; |
2694 | ray_dev_t *local; | 2634 | ray_dev_t *local; |
2695 | UCHAR *p; | 2635 | UCHAR *p; |
2696 | struct freq_hop_element *pfh; | 2636 | struct freq_hop_element *pfh; |
2697 | UCHAR c[33]; | 2637 | UCHAR c[33]; |
2698 | 2638 | ||
2699 | link = dev_list; | 2639 | link = this_device; |
2700 | if (!link) | 2640 | if (!link) |
2701 | return 0; | 2641 | return 0; |
2702 | dev = (struct net_device *)link->priv; | 2642 | dev = (struct net_device *)link->priv; |
@@ -2898,7 +2838,7 @@ static struct pcmcia_driver ray_driver = { | |||
2898 | .drv = { | 2838 | .drv = { |
2899 | .name = "ray_cs", | 2839 | .name = "ray_cs", |
2900 | }, | 2840 | }, |
2901 | .probe = ray_attach, | 2841 | .probe = ray_probe, |
2902 | .remove = ray_detach, | 2842 | .remove = ray_detach, |
2903 | .id_table = ray_ids, | 2843 | .id_table = ray_ids, |
2904 | .suspend = ray_suspend, | 2844 | .suspend = ray_suspend, |
@@ -2940,7 +2880,6 @@ static void __exit exit_ray_cs(void) | |||
2940 | #endif | 2880 | #endif |
2941 | 2881 | ||
2942 | pcmcia_unregister_driver(&ray_driver); | 2882 | pcmcia_unregister_driver(&ray_driver); |
2943 | BUG_ON(dev_list != NULL); | ||
2944 | } /* exit_ray_cs */ | 2883 | } /* exit_ray_cs */ |
2945 | 2884 | ||
2946 | module_init(init_ray_cs); | 2885 | module_init(init_ray_cs); |
diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h index 42660fe64bfd..bd73ebf03340 100644 --- a/drivers/net/wireless/ray_cs.h +++ b/drivers/net/wireless/ray_cs.h | |||
@@ -31,7 +31,7 @@ typedef struct ray_dev_t { | |||
31 | void __iomem *sram; /* pointer to beginning of shared RAM */ | 31 | void __iomem *sram; /* pointer to beginning of shared RAM */ |
32 | void __iomem *amem; /* pointer to attribute mem window */ | 32 | void __iomem *amem; /* pointer to attribute mem window */ |
33 | void __iomem *rmem; /* pointer to receive buffer window */ | 33 | void __iomem *rmem; /* pointer to receive buffer window */ |
34 | dev_link_t *finder; /* pointer back to dev_link_t for card */ | 34 | struct pcmcia_device *finder; /* pointer back to struct pcmcia_device for card */ |
35 | struct timer_list timer; | 35 | struct timer_list timer; |
36 | long tx_ccs_lock; | 36 | long tx_ccs_lock; |
37 | long ccs_lock; | 37 | long ccs_lock; |
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c index 5fa6fbe35bb9..f7b77ce54d7b 100644 --- a/drivers/net/wireless/spectrum_cs.c +++ b/drivers/net/wireless/spectrum_cs.c | |||
@@ -63,7 +63,7 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket | |||
63 | /* PCMCIA specific device information (goes in the card field of | 63 | /* PCMCIA specific device information (goes in the card field of |
64 | * struct orinoco_private */ | 64 | * struct orinoco_private */ |
65 | struct orinoco_pccard { | 65 | struct orinoco_pccard { |
66 | dev_link_t link; | 66 | struct pcmcia_device *p_dev; |
67 | dev_node_t node; | 67 | dev_node_t node; |
68 | }; | 68 | }; |
69 | 69 | ||
@@ -71,8 +71,8 @@ struct orinoco_pccard { | |||
71 | /* Function prototypes */ | 71 | /* Function prototypes */ |
72 | /********************************************************************/ | 72 | /********************************************************************/ |
73 | 73 | ||
74 | static void spectrum_cs_config(dev_link_t *link); | 74 | static int spectrum_cs_config(struct pcmcia_device *link); |
75 | static void spectrum_cs_release(dev_link_t *link); | 75 | static void spectrum_cs_release(struct pcmcia_device *link); |
76 | 76 | ||
77 | /********************************************************************/ | 77 | /********************************************************************/ |
78 | /* Firmware downloader */ | 78 | /* Firmware downloader */ |
@@ -238,14 +238,14 @@ spectrum_aux_open(hermes_t *hw) | |||
238 | * If IDLE is 1, stop the firmware, so that it can be safely rewritten. | 238 | * If IDLE is 1, stop the firmware, so that it can be safely rewritten. |
239 | */ | 239 | */ |
240 | static int | 240 | static int |
241 | spectrum_reset(dev_link_t *link, int idle) | 241 | spectrum_reset(struct pcmcia_device *link, int idle) |
242 | { | 242 | { |
243 | int last_ret, last_fn; | 243 | int last_ret, last_fn; |
244 | conf_reg_t reg; | 244 | conf_reg_t reg; |
245 | u_int save_cor; | 245 | u_int save_cor; |
246 | 246 | ||
247 | /* Doing it if hardware is gone is guaranteed crash */ | 247 | /* Doing it if hardware is gone is guaranteed crash */ |
248 | if (!(link->state & DEV_CONFIG)) | 248 | if (pcmcia_dev_present(link)) |
249 | return -ENODEV; | 249 | return -ENODEV; |
250 | 250 | ||
251 | /* Save original COR value */ | 251 | /* Save original COR value */ |
@@ -253,7 +253,7 @@ spectrum_reset(dev_link_t *link, int idle) | |||
253 | reg.Action = CS_READ; | 253 | reg.Action = CS_READ; |
254 | reg.Offset = CISREG_COR; | 254 | reg.Offset = CISREG_COR; |
255 | CS_CHECK(AccessConfigurationRegister, | 255 | CS_CHECK(AccessConfigurationRegister, |
256 | pcmcia_access_configuration_register(link->handle, ®)); | 256 | pcmcia_access_configuration_register(link, ®)); |
257 | save_cor = reg.Value; | 257 | save_cor = reg.Value; |
258 | 258 | ||
259 | /* Soft-Reset card */ | 259 | /* Soft-Reset card */ |
@@ -261,14 +261,14 @@ spectrum_reset(dev_link_t *link, int idle) | |||
261 | reg.Offset = CISREG_COR; | 261 | reg.Offset = CISREG_COR; |
262 | reg.Value = (save_cor | COR_SOFT_RESET); | 262 | reg.Value = (save_cor | COR_SOFT_RESET); |
263 | CS_CHECK(AccessConfigurationRegister, | 263 | CS_CHECK(AccessConfigurationRegister, |
264 | pcmcia_access_configuration_register(link->handle, ®)); | 264 | pcmcia_access_configuration_register(link, ®)); |
265 | udelay(1000); | 265 | udelay(1000); |
266 | 266 | ||
267 | /* Read CCSR */ | 267 | /* Read CCSR */ |
268 | reg.Action = CS_READ; | 268 | reg.Action = CS_READ; |
269 | reg.Offset = CISREG_CCSR; | 269 | reg.Offset = CISREG_CCSR; |
270 | CS_CHECK(AccessConfigurationRegister, | 270 | CS_CHECK(AccessConfigurationRegister, |
271 | pcmcia_access_configuration_register(link->handle, ®)); | 271 | pcmcia_access_configuration_register(link, ®)); |
272 | 272 | ||
273 | /* | 273 | /* |
274 | * Start or stop the firmware. Memory width bit should be | 274 | * Start or stop the firmware. Memory width bit should be |
@@ -278,7 +278,7 @@ spectrum_reset(dev_link_t *link, int idle) | |||
278 | reg.Offset = CISREG_CCSR; | 278 | reg.Offset = CISREG_CCSR; |
279 | reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16); | 279 | reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16); |
280 | CS_CHECK(AccessConfigurationRegister, | 280 | CS_CHECK(AccessConfigurationRegister, |
281 | pcmcia_access_configuration_register(link->handle, ®)); | 281 | pcmcia_access_configuration_register(link, ®)); |
282 | udelay(1000); | 282 | udelay(1000); |
283 | 283 | ||
284 | /* Restore original COR configuration index */ | 284 | /* Restore original COR configuration index */ |
@@ -286,12 +286,12 @@ spectrum_reset(dev_link_t *link, int idle) | |||
286 | reg.Offset = CISREG_COR; | 286 | reg.Offset = CISREG_COR; |
287 | reg.Value = (save_cor & ~COR_SOFT_RESET); | 287 | reg.Value = (save_cor & ~COR_SOFT_RESET); |
288 | CS_CHECK(AccessConfigurationRegister, | 288 | CS_CHECK(AccessConfigurationRegister, |
289 | pcmcia_access_configuration_register(link->handle, ®)); | 289 | pcmcia_access_configuration_register(link, ®)); |
290 | udelay(1000); | 290 | udelay(1000); |
291 | return 0; | 291 | return 0; |
292 | 292 | ||
293 | cs_failed: | 293 | cs_failed: |
294 | cs_error(link->handle, last_fn, last_ret); | 294 | cs_error(link, last_fn, last_ret); |
295 | return -ENODEV; | 295 | return -ENODEV; |
296 | } | 296 | } |
297 | 297 | ||
@@ -441,7 +441,7 @@ spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block) | |||
441 | * care of the PDA - read it and then write it on top of the firmware. | 441 | * care of the PDA - read it and then write it on top of the firmware. |
442 | */ | 442 | */ |
443 | static int | 443 | static int |
444 | spectrum_dl_image(hermes_t *hw, dev_link_t *link, | 444 | spectrum_dl_image(hermes_t *hw, struct pcmcia_device *link, |
445 | const unsigned char *image) | 445 | const unsigned char *image) |
446 | { | 446 | { |
447 | int ret; | 447 | int ret; |
@@ -505,14 +505,13 @@ spectrum_dl_image(hermes_t *hw, dev_link_t *link, | |||
505 | * reset on the card, to make sure it's in a sane state. | 505 | * reset on the card, to make sure it's in a sane state. |
506 | */ | 506 | */ |
507 | static int | 507 | static int |
508 | spectrum_dl_firmware(hermes_t *hw, dev_link_t *link) | 508 | spectrum_dl_firmware(hermes_t *hw, struct pcmcia_device *link) |
509 | { | 509 | { |
510 | int ret; | 510 | int ret; |
511 | client_handle_t handle = link->handle; | ||
512 | const struct firmware *fw_entry; | 511 | const struct firmware *fw_entry; |
513 | 512 | ||
514 | if (request_firmware(&fw_entry, primary_fw_name, | 513 | if (request_firmware(&fw_entry, primary_fw_name, |
515 | &handle_to_dev(handle)) == 0) { | 514 | &handle_to_dev(link)) == 0) { |
516 | primsym = fw_entry->data; | 515 | primsym = fw_entry->data; |
517 | } else { | 516 | } else { |
518 | printk(KERN_ERR PFX "Cannot find firmware: %s\n", | 517 | printk(KERN_ERR PFX "Cannot find firmware: %s\n", |
@@ -521,7 +520,7 @@ spectrum_dl_firmware(hermes_t *hw, dev_link_t *link) | |||
521 | } | 520 | } |
522 | 521 | ||
523 | if (request_firmware(&fw_entry, secondary_fw_name, | 522 | if (request_firmware(&fw_entry, secondary_fw_name, |
524 | &handle_to_dev(handle)) == 0) { | 523 | &handle_to_dev(link)) == 0) { |
525 | secsym = fw_entry->data; | 524 | secsym = fw_entry->data; |
526 | } else { | 525 | } else { |
527 | printk(KERN_ERR PFX "Cannot find firmware: %s\n", | 526 | printk(KERN_ERR PFX "Cannot find firmware: %s\n", |
@@ -554,12 +553,12 @@ static int | |||
554 | spectrum_cs_hard_reset(struct orinoco_private *priv) | 553 | spectrum_cs_hard_reset(struct orinoco_private *priv) |
555 | { | 554 | { |
556 | struct orinoco_pccard *card = priv->card; | 555 | struct orinoco_pccard *card = priv->card; |
557 | dev_link_t *link = &card->link; | 556 | struct pcmcia_device *link = card->p_dev; |
558 | int err; | 557 | int err; |
559 | 558 | ||
560 | if (!hermes_present(&priv->hw)) { | 559 | if (!hermes_present(&priv->hw)) { |
561 | /* The firmware needs to be reloaded */ | 560 | /* The firmware needs to be reloaded */ |
562 | if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) { | 561 | if (spectrum_dl_firmware(&priv->hw, link) != 0) { |
563 | printk(KERN_ERR PFX "Firmware download failed\n"); | 562 | printk(KERN_ERR PFX "Firmware download failed\n"); |
564 | err = -ENODEV; | 563 | err = -ENODEV; |
565 | } | 564 | } |
@@ -584,12 +583,11 @@ spectrum_cs_hard_reset(struct orinoco_private *priv) | |||
584 | * configure the card at this point -- we wait until we receive a card | 583 | * configure the card at this point -- we wait until we receive a card |
585 | * insertion event. */ | 584 | * insertion event. */ |
586 | static int | 585 | static int |
587 | spectrum_cs_attach(struct pcmcia_device *p_dev) | 586 | spectrum_cs_probe(struct pcmcia_device *link) |
588 | { | 587 | { |
589 | struct net_device *dev; | 588 | struct net_device *dev; |
590 | struct orinoco_private *priv; | 589 | struct orinoco_private *priv; |
591 | struct orinoco_pccard *card; | 590 | struct orinoco_pccard *card; |
592 | dev_link_t *link; | ||
593 | 591 | ||
594 | dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); | 592 | dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); |
595 | if (! dev) | 593 | if (! dev) |
@@ -598,7 +596,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev) | |||
598 | card = priv->card; | 596 | card = priv->card; |
599 | 597 | ||
600 | /* Link both structures together */ | 598 | /* Link both structures together */ |
601 | link = &card->link; | 599 | card->p_dev = link; |
602 | link->priv = dev; | 600 | link->priv = dev; |
603 | 601 | ||
604 | /* Interrupt setup */ | 602 | /* Interrupt setup */ |
@@ -615,13 +613,7 @@ spectrum_cs_attach(struct pcmcia_device *p_dev) | |||
615 | link->conf.Attributes = 0; | 613 | link->conf.Attributes = 0; |
616 | link->conf.IntType = INT_MEMORY_AND_IO; | 614 | link->conf.IntType = INT_MEMORY_AND_IO; |
617 | 615 | ||
618 | link->handle = p_dev; | 616 | return spectrum_cs_config(link); |
619 | p_dev->instance = link; | ||
620 | |||
621 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
622 | spectrum_cs_config(link); | ||
623 | |||
624 | return 0; | ||
625 | } /* spectrum_cs_attach */ | 617 | } /* spectrum_cs_attach */ |
626 | 618 | ||
627 | /* | 619 | /* |
@@ -630,16 +622,14 @@ spectrum_cs_attach(struct pcmcia_device *p_dev) | |||
630 | * are freed. Otherwise, the structures will be freed when the device | 622 | * are freed. Otherwise, the structures will be freed when the device |
631 | * is released. | 623 | * is released. |
632 | */ | 624 | */ |
633 | static void spectrum_cs_detach(struct pcmcia_device *p_dev) | 625 | static void spectrum_cs_detach(struct pcmcia_device *link) |
634 | { | 626 | { |
635 | dev_link_t *link = dev_to_instance(p_dev); | ||
636 | struct net_device *dev = link->priv; | 627 | struct net_device *dev = link->priv; |
637 | 628 | ||
638 | if (link->state & DEV_CONFIG) | 629 | spectrum_cs_release(link); |
639 | spectrum_cs_release(link); | ||
640 | 630 | ||
641 | DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); | 631 | DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node); |
642 | if (link->dev) { | 632 | if (link->dev_node) { |
643 | DEBUG(0, PFX "About to unregister net device %p\n", | 633 | DEBUG(0, PFX "About to unregister net device %p\n", |
644 | dev); | 634 | dev); |
645 | unregister_netdev(dev); | 635 | unregister_netdev(dev); |
@@ -653,11 +643,10 @@ static void spectrum_cs_detach(struct pcmcia_device *p_dev) | |||
653 | * device available to the system. | 643 | * device available to the system. |
654 | */ | 644 | */ |
655 | 645 | ||
656 | static void | 646 | static int |
657 | spectrum_cs_config(dev_link_t *link) | 647 | spectrum_cs_config(struct pcmcia_device *link) |
658 | { | 648 | { |
659 | struct net_device *dev = link->priv; | 649 | struct net_device *dev = link->priv; |
660 | client_handle_t handle = link->handle; | ||
661 | struct orinoco_private *priv = netdev_priv(dev); | 650 | struct orinoco_private *priv = netdev_priv(dev); |
662 | struct orinoco_pccard *card = priv->card; | 651 | struct orinoco_pccard *card = priv->card; |
663 | hermes_t *hw = &priv->hw; | 652 | hermes_t *hw = &priv->hw; |
@@ -669,7 +658,7 @@ spectrum_cs_config(dev_link_t *link) | |||
669 | cisparse_t parse; | 658 | cisparse_t parse; |
670 | void __iomem *mem; | 659 | void __iomem *mem; |
671 | 660 | ||
672 | CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info)); | 661 | CS_CHECK(ValidateCIS, pcmcia_validate_cis(link, &info)); |
673 | 662 | ||
674 | /* | 663 | /* |
675 | * This reads the card's CONFIG tuple to find its | 664 | * This reads the card's CONFIG tuple to find its |
@@ -680,19 +669,15 @@ spectrum_cs_config(dev_link_t *link) | |||
680 | tuple.TupleData = buf; | 669 | tuple.TupleData = buf; |
681 | tuple.TupleDataMax = sizeof(buf); | 670 | tuple.TupleDataMax = sizeof(buf); |
682 | tuple.TupleOffset = 0; | 671 | tuple.TupleOffset = 0; |
683 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 672 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
684 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 673 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
685 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 674 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
686 | link->conf.ConfigBase = parse.config.base; | 675 | link->conf.ConfigBase = parse.config.base; |
687 | link->conf.Present = parse.config.rmask[0]; | 676 | link->conf.Present = parse.config.rmask[0]; |
688 | 677 | ||
689 | /* Configure card */ | ||
690 | link->state |= DEV_CONFIG; | ||
691 | |||
692 | /* Look up the current Vcc */ | 678 | /* Look up the current Vcc */ |
693 | CS_CHECK(GetConfigurationInfo, | 679 | CS_CHECK(GetConfigurationInfo, |
694 | pcmcia_get_configuration_info(handle, &conf)); | 680 | pcmcia_get_configuration_info(link, &conf)); |
695 | link->conf.Vcc = conf.Vcc; | ||
696 | 681 | ||
697 | /* | 682 | /* |
698 | * In this loop, we scan the CIS for configuration table | 683 | * In this loop, we scan the CIS for configuration table |
@@ -709,13 +694,13 @@ spectrum_cs_config(dev_link_t *link) | |||
709 | * implementation-defined details. | 694 | * implementation-defined details. |
710 | */ | 695 | */ |
711 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 696 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
712 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 697 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
713 | while (1) { | 698 | while (1) { |
714 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 699 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
715 | cistpl_cftable_entry_t dflt = { .index = 0 }; | 700 | cistpl_cftable_entry_t dflt = { .index = 0 }; |
716 | 701 | ||
717 | if ( (pcmcia_get_tuple_data(handle, &tuple) != 0) | 702 | if ( (pcmcia_get_tuple_data(link, &tuple) != 0) |
718 | || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0)) | 703 | || (pcmcia_parse_tuple(link, &tuple, &parse) != 0)) |
719 | goto next_entry; | 704 | goto next_entry; |
720 | 705 | ||
721 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | 706 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) |
@@ -747,10 +732,10 @@ spectrum_cs_config(dev_link_t *link) | |||
747 | } | 732 | } |
748 | 733 | ||
749 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | 734 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) |
750 | link->conf.Vpp1 = link->conf.Vpp2 = | 735 | link->conf.Vpp = |
751 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | 736 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; |
752 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | 737 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) |
753 | link->conf.Vpp1 = link->conf.Vpp2 = | 738 | link->conf.Vpp = |
754 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | 739 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; |
755 | 740 | ||
756 | /* Do we need to allocate an interrupt? */ | 741 | /* Do we need to allocate an interrupt? */ |
@@ -780,7 +765,7 @@ spectrum_cs_config(dev_link_t *link) | |||
780 | } | 765 | } |
781 | 766 | ||
782 | /* This reserves IO space but doesn't actually enable it */ | 767 | /* This reserves IO space but doesn't actually enable it */ |
783 | if (pcmcia_request_io(link->handle, &link->io) != 0) | 768 | if (pcmcia_request_io(link, &link->io) != 0) |
784 | goto next_entry; | 769 | goto next_entry; |
785 | } | 770 | } |
786 | 771 | ||
@@ -790,9 +775,8 @@ spectrum_cs_config(dev_link_t *link) | |||
790 | break; | 775 | break; |
791 | 776 | ||
792 | next_entry: | 777 | next_entry: |
793 | if (link->io.NumPorts1) | 778 | pcmcia_disable_device(link); |
794 | pcmcia_release_io(link->handle, &link->io); | 779 | last_ret = pcmcia_get_next_tuple(link, &tuple); |
795 | last_ret = pcmcia_get_next_tuple(handle, &tuple); | ||
796 | if (last_ret == CS_NO_MORE_ITEMS) { | 780 | if (last_ret == CS_NO_MORE_ITEMS) { |
797 | printk(KERN_ERR PFX "GetNextTuple(): No matching " | 781 | printk(KERN_ERR PFX "GetNextTuple(): No matching " |
798 | "CIS configuration. Maybe you need the " | 782 | "CIS configuration. Maybe you need the " |
@@ -806,7 +790,7 @@ spectrum_cs_config(dev_link_t *link) | |||
806 | * a handler to the interrupt, unless the 'Handler' member of | 790 | * a handler to the interrupt, unless the 'Handler' member of |
807 | * the irq structure is initialized. | 791 | * the irq structure is initialized. |
808 | */ | 792 | */ |
809 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 793 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
810 | 794 | ||
811 | /* We initialize the hermes structure before completing PCMCIA | 795 | /* We initialize the hermes structure before completing PCMCIA |
812 | * configuration just in case the interrupt handler gets | 796 | * configuration just in case the interrupt handler gets |
@@ -823,7 +807,7 @@ spectrum_cs_config(dev_link_t *link) | |||
823 | * card and host interface into "Memory and IO" mode. | 807 | * card and host interface into "Memory and IO" mode. |
824 | */ | 808 | */ |
825 | CS_CHECK(RequestConfiguration, | 809 | CS_CHECK(RequestConfiguration, |
826 | pcmcia_request_configuration(link->handle, &link->conf)); | 810 | pcmcia_request_configuration(link, &link->conf)); |
827 | 811 | ||
828 | /* Ok, we have the configuration, prepare to register the netdev */ | 812 | /* Ok, we have the configuration, prepare to register the netdev */ |
829 | dev->base_addr = link->io.BasePort1; | 813 | dev->base_addr = link->io.BasePort1; |
@@ -836,7 +820,7 @@ spectrum_cs_config(dev_link_t *link) | |||
836 | goto failed; | 820 | goto failed; |
837 | } | 821 | } |
838 | 822 | ||
839 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | 823 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
840 | /* Tell the stack we exist */ | 824 | /* Tell the stack we exist */ |
841 | if (register_netdev(dev) != 0) { | 825 | if (register_netdev(dev) != 0) { |
842 | printk(KERN_ERR PFX "register_netdev() failed\n"); | 826 | printk(KERN_ERR PFX "register_netdev() failed\n"); |
@@ -844,20 +828,18 @@ spectrum_cs_config(dev_link_t *link) | |||
844 | } | 828 | } |
845 | 829 | ||
846 | /* At this point, the dev_node_t structure(s) needs to be | 830 | /* At this point, the dev_node_t structure(s) needs to be |
847 | * initialized and arranged in a linked list at link->dev. */ | 831 | * initialized and arranged in a linked list at link->dev_node. */ |
848 | strcpy(card->node.dev_name, dev->name); | 832 | strcpy(card->node.dev_name, dev->name); |
849 | link->dev = &card->node; /* link->dev being non-NULL is also | 833 | link->dev_node = &card->node; /* link->dev_node being non-NULL is also |
850 | used to indicate that the | 834 | used to indicate that the |
851 | net_device has been registered */ | 835 | net_device has been registered */ |
852 | link->state &= ~DEV_CONFIG_PENDING; | ||
853 | 836 | ||
854 | /* Finally, report what we've done */ | 837 | /* Finally, report what we've done */ |
855 | printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d", | 838 | printk(KERN_DEBUG "%s: index 0x%02x: ", |
856 | dev->name, link->conf.ConfigIndex, | 839 | dev->name, link->conf.ConfigIndex); |
857 | link->conf.Vcc / 10, link->conf.Vcc % 10); | 840 | if (link->conf.Vpp) |
858 | if (link->conf.Vpp1) | 841 | printk(", Vpp %d.%d", link->conf.Vpp / 10, |
859 | printk(", Vpp %d.%d", link->conf.Vpp1 / 10, | 842 | link->conf.Vpp % 10); |
860 | link->conf.Vpp1 % 10); | ||
861 | printk(", irq %d", link->irq.AssignedIRQ); | 843 | printk(", irq %d", link->irq.AssignedIRQ); |
862 | if (link->io.NumPorts1) | 844 | if (link->io.NumPorts1) |
863 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, | 845 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, |
@@ -867,13 +849,14 @@ spectrum_cs_config(dev_link_t *link) | |||
867 | link->io.BasePort2 + link->io.NumPorts2 - 1); | 849 | link->io.BasePort2 + link->io.NumPorts2 - 1); |
868 | printk("\n"); | 850 | printk("\n"); |
869 | 851 | ||
870 | return; | 852 | return 0; |
871 | 853 | ||
872 | cs_failed: | 854 | cs_failed: |
873 | cs_error(link->handle, last_fn, last_ret); | 855 | cs_error(link, last_fn, last_ret); |
874 | 856 | ||
875 | failed: | 857 | failed: |
876 | spectrum_cs_release(link); | 858 | spectrum_cs_release(link); |
859 | return -ENODEV; | ||
877 | } /* spectrum_cs_config */ | 860 | } /* spectrum_cs_config */ |
878 | 861 | ||
879 | /* | 862 | /* |
@@ -882,7 +865,7 @@ spectrum_cs_config(dev_link_t *link) | |||
882 | * still open, this will be postponed until it is closed. | 865 | * still open, this will be postponed until it is closed. |
883 | */ | 866 | */ |
884 | static void | 867 | static void |
885 | spectrum_cs_release(dev_link_t *link) | 868 | spectrum_cs_release(struct pcmcia_device *link) |
886 | { | 869 | { |
887 | struct net_device *dev = link->priv; | 870 | struct net_device *dev = link->priv; |
888 | struct orinoco_private *priv = netdev_priv(dev); | 871 | struct orinoco_private *priv = netdev_priv(dev); |
@@ -894,64 +877,46 @@ spectrum_cs_release(dev_link_t *link) | |||
894 | priv->hw_unavailable++; | 877 | priv->hw_unavailable++; |
895 | spin_unlock_irqrestore(&priv->lock, flags); | 878 | spin_unlock_irqrestore(&priv->lock, flags); |
896 | 879 | ||
897 | /* Don't bother checking to see if these succeed or not */ | 880 | pcmcia_disable_device(link); |
898 | pcmcia_release_configuration(link->handle); | ||
899 | if (link->io.NumPorts1) | ||
900 | pcmcia_release_io(link->handle, &link->io); | ||
901 | if (link->irq.AssignedIRQ) | ||
902 | pcmcia_release_irq(link->handle, &link->irq); | ||
903 | link->state &= ~DEV_CONFIG; | ||
904 | if (priv->hw.iobase) | 881 | if (priv->hw.iobase) |
905 | ioport_unmap(priv->hw.iobase); | 882 | ioport_unmap(priv->hw.iobase); |
906 | } /* spectrum_cs_release */ | 883 | } /* spectrum_cs_release */ |
907 | 884 | ||
908 | 885 | ||
909 | static int | 886 | static int |
910 | spectrum_cs_suspend(struct pcmcia_device *p_dev) | 887 | spectrum_cs_suspend(struct pcmcia_device *link) |
911 | { | 888 | { |
912 | dev_link_t *link = dev_to_instance(p_dev); | ||
913 | struct net_device *dev = link->priv; | 889 | struct net_device *dev = link->priv; |
914 | struct orinoco_private *priv = netdev_priv(dev); | 890 | struct orinoco_private *priv = netdev_priv(dev); |
915 | unsigned long flags; | 891 | unsigned long flags; |
916 | int err = 0; | 892 | int err = 0; |
917 | 893 | ||
918 | link->state |= DEV_SUSPEND; | ||
919 | /* Mark the device as stopped, to block IO until later */ | 894 | /* Mark the device as stopped, to block IO until later */ |
920 | if (link->state & DEV_CONFIG) { | 895 | spin_lock_irqsave(&priv->lock, flags); |
921 | spin_lock_irqsave(&priv->lock, flags); | ||
922 | |||
923 | err = __orinoco_down(dev); | ||
924 | if (err) | ||
925 | printk(KERN_WARNING "%s: Error %d downing interface\n", | ||
926 | dev->name, err); | ||
927 | 896 | ||
928 | netif_device_detach(dev); | 897 | err = __orinoco_down(dev); |
929 | priv->hw_unavailable++; | 898 | if (err) |
899 | printk(KERN_WARNING "%s: Error %d downing interface\n", | ||
900 | dev->name, err); | ||
930 | 901 | ||
931 | spin_unlock_irqrestore(&priv->lock, flags); | 902 | netif_device_detach(dev); |
903 | priv->hw_unavailable++; | ||
932 | 904 | ||
933 | pcmcia_release_configuration(link->handle); | 905 | spin_unlock_irqrestore(&priv->lock, flags); |
934 | } | ||
935 | 906 | ||
936 | return 0; | 907 | return 0; |
937 | } | 908 | } |
938 | 909 | ||
939 | static int | 910 | static int |
940 | spectrum_cs_resume(struct pcmcia_device *p_dev) | 911 | spectrum_cs_resume(struct pcmcia_device *link) |
941 | { | 912 | { |
942 | dev_link_t *link = dev_to_instance(p_dev); | ||
943 | struct net_device *dev = link->priv; | 913 | struct net_device *dev = link->priv; |
944 | struct orinoco_private *priv = netdev_priv(dev); | 914 | struct orinoco_private *priv = netdev_priv(dev); |
945 | 915 | ||
946 | link->state &= ~DEV_SUSPEND; | 916 | netif_device_attach(dev); |
947 | if (link->state & DEV_CONFIG) { | 917 | priv->hw_unavailable--; |
948 | /* FIXME: should we double check that this is | 918 | schedule_work(&priv->reset_work); |
949 | * the same card as we had before */ | 919 | |
950 | pcmcia_request_configuration(link->handle, &link->conf); | ||
951 | netif_device_attach(dev); | ||
952 | priv->hw_unavailable--; | ||
953 | schedule_work(&priv->reset_work); | ||
954 | } | ||
955 | return 0; | 920 | return 0; |
956 | } | 921 | } |
957 | 922 | ||
@@ -979,7 +944,7 @@ static struct pcmcia_driver orinoco_driver = { | |||
979 | .drv = { | 944 | .drv = { |
980 | .name = DRIVER_NAME, | 945 | .name = DRIVER_NAME, |
981 | }, | 946 | }, |
982 | .probe = spectrum_cs_attach, | 947 | .probe = spectrum_cs_probe, |
983 | .remove = spectrum_cs_detach, | 948 | .remove = spectrum_cs_detach, |
984 | .suspend = spectrum_cs_suspend, | 949 | .suspend = spectrum_cs_suspend, |
985 | .resume = spectrum_cs_resume, | 950 | .resume = spectrum_cs_resume, |
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 98122f3a4bc2..f7724eb2fa7e 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c | |||
@@ -1005,7 +1005,7 @@ static inline void | |||
1005 | wv_82593_reconfig(struct net_device * dev) | 1005 | wv_82593_reconfig(struct net_device * dev) |
1006 | { | 1006 | { |
1007 | net_local * lp = netdev_priv(dev); | 1007 | net_local * lp = netdev_priv(dev); |
1008 | dev_link_t * link = lp->link; | 1008 | struct pcmcia_device * link = lp->link; |
1009 | unsigned long flags; | 1009 | unsigned long flags; |
1010 | 1010 | ||
1011 | /* Arm the flag, will be cleard in wv_82593_config() */ | 1011 | /* Arm the flag, will be cleard in wv_82593_config() */ |
@@ -3744,16 +3744,16 @@ wv_pcmcia_reset(struct net_device * dev) | |||
3744 | { | 3744 | { |
3745 | int i; | 3745 | int i; |
3746 | conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 }; | 3746 | conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 }; |
3747 | dev_link_t * link = ((net_local *)netdev_priv(dev))->link; | 3747 | struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link; |
3748 | 3748 | ||
3749 | #ifdef DEBUG_CONFIG_TRACE | 3749 | #ifdef DEBUG_CONFIG_TRACE |
3750 | printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name); | 3750 | printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name); |
3751 | #endif | 3751 | #endif |
3752 | 3752 | ||
3753 | i = pcmcia_access_configuration_register(link->handle, ®); | 3753 | i = pcmcia_access_configuration_register(link, ®); |
3754 | if(i != CS_SUCCESS) | 3754 | if(i != CS_SUCCESS) |
3755 | { | 3755 | { |
3756 | cs_error(link->handle, AccessConfigurationRegister, i); | 3756 | cs_error(link, AccessConfigurationRegister, i); |
3757 | return FALSE; | 3757 | return FALSE; |
3758 | } | 3758 | } |
3759 | 3759 | ||
@@ -3764,19 +3764,19 @@ wv_pcmcia_reset(struct net_device * dev) | |||
3764 | 3764 | ||
3765 | reg.Action = CS_WRITE; | 3765 | reg.Action = CS_WRITE; |
3766 | reg.Value = reg.Value | COR_SW_RESET; | 3766 | reg.Value = reg.Value | COR_SW_RESET; |
3767 | i = pcmcia_access_configuration_register(link->handle, ®); | 3767 | i = pcmcia_access_configuration_register(link, ®); |
3768 | if(i != CS_SUCCESS) | 3768 | if(i != CS_SUCCESS) |
3769 | { | 3769 | { |
3770 | cs_error(link->handle, AccessConfigurationRegister, i); | 3770 | cs_error(link, AccessConfigurationRegister, i); |
3771 | return FALSE; | 3771 | return FALSE; |
3772 | } | 3772 | } |
3773 | 3773 | ||
3774 | reg.Action = CS_WRITE; | 3774 | reg.Action = CS_WRITE; |
3775 | reg.Value = COR_LEVEL_IRQ | COR_CONFIG; | 3775 | reg.Value = COR_LEVEL_IRQ | COR_CONFIG; |
3776 | i = pcmcia_access_configuration_register(link->handle, ®); | 3776 | i = pcmcia_access_configuration_register(link, ®); |
3777 | if(i != CS_SUCCESS) | 3777 | if(i != CS_SUCCESS) |
3778 | { | 3778 | { |
3779 | cs_error(link->handle, AccessConfigurationRegister, i); | 3779 | cs_error(link, AccessConfigurationRegister, i); |
3780 | return FALSE; | 3780 | return FALSE; |
3781 | } | 3781 | } |
3782 | 3782 | ||
@@ -3940,9 +3940,8 @@ wv_hw_reset(struct net_device * dev) | |||
3940 | * (called by wavelan_event()) | 3940 | * (called by wavelan_event()) |
3941 | */ | 3941 | */ |
3942 | static inline int | 3942 | static inline int |
3943 | wv_pcmcia_config(dev_link_t * link) | 3943 | wv_pcmcia_config(struct pcmcia_device * link) |
3944 | { | 3944 | { |
3945 | client_handle_t handle = link->handle; | ||
3946 | tuple_t tuple; | 3945 | tuple_t tuple; |
3947 | cisparse_t parse; | 3946 | cisparse_t parse; |
3948 | struct net_device * dev = (struct net_device *) link->priv; | 3947 | struct net_device * dev = (struct net_device *) link->priv; |
@@ -3965,16 +3964,16 @@ wv_pcmcia_config(dev_link_t * link) | |||
3965 | { | 3964 | { |
3966 | tuple.Attributes = 0; | 3965 | tuple.Attributes = 0; |
3967 | tuple.DesiredTuple = CISTPL_CONFIG; | 3966 | tuple.DesiredTuple = CISTPL_CONFIG; |
3968 | i = pcmcia_get_first_tuple(handle, &tuple); | 3967 | i = pcmcia_get_first_tuple(link, &tuple); |
3969 | if(i != CS_SUCCESS) | 3968 | if(i != CS_SUCCESS) |
3970 | break; | 3969 | break; |
3971 | tuple.TupleData = (cisdata_t *)buf; | 3970 | tuple.TupleData = (cisdata_t *)buf; |
3972 | tuple.TupleDataMax = 64; | 3971 | tuple.TupleDataMax = 64; |
3973 | tuple.TupleOffset = 0; | 3972 | tuple.TupleOffset = 0; |
3974 | i = pcmcia_get_tuple_data(handle, &tuple); | 3973 | i = pcmcia_get_tuple_data(link, &tuple); |
3975 | if(i != CS_SUCCESS) | 3974 | if(i != CS_SUCCESS) |
3976 | break; | 3975 | break; |
3977 | i = pcmcia_parse_tuple(handle, &tuple, &parse); | 3976 | i = pcmcia_parse_tuple(link, &tuple, &parse); |
3978 | if(i != CS_SUCCESS) | 3977 | if(i != CS_SUCCESS) |
3979 | break; | 3978 | break; |
3980 | link->conf.ConfigBase = parse.config.base; | 3979 | link->conf.ConfigBase = parse.config.base; |
@@ -3983,19 +3982,16 @@ wv_pcmcia_config(dev_link_t * link) | |||
3983 | while(0); | 3982 | while(0); |
3984 | if(i != CS_SUCCESS) | 3983 | if(i != CS_SUCCESS) |
3985 | { | 3984 | { |
3986 | cs_error(link->handle, ParseTuple, i); | 3985 | cs_error(link, ParseTuple, i); |
3987 | link->state &= ~DEV_CONFIG_PENDING; | ||
3988 | return FALSE; | 3986 | return FALSE; |
3989 | } | 3987 | } |
3990 | 3988 | ||
3991 | /* Configure card */ | ||
3992 | link->state |= DEV_CONFIG; | ||
3993 | do | 3989 | do |
3994 | { | 3990 | { |
3995 | i = pcmcia_request_io(link->handle, &link->io); | 3991 | i = pcmcia_request_io(link, &link->io); |
3996 | if(i != CS_SUCCESS) | 3992 | if(i != CS_SUCCESS) |
3997 | { | 3993 | { |
3998 | cs_error(link->handle, RequestIO, i); | 3994 | cs_error(link, RequestIO, i); |
3999 | break; | 3995 | break; |
4000 | } | 3996 | } |
4001 | 3997 | ||
@@ -4003,10 +3999,10 @@ wv_pcmcia_config(dev_link_t * link) | |||
4003 | * Now allocate an interrupt line. Note that this does not | 3999 | * Now allocate an interrupt line. Note that this does not |
4004 | * actually assign a handler to the interrupt. | 4000 | * actually assign a handler to the interrupt. |
4005 | */ | 4001 | */ |
4006 | i = pcmcia_request_irq(link->handle, &link->irq); | 4002 | i = pcmcia_request_irq(link, &link->irq); |
4007 | if(i != CS_SUCCESS) | 4003 | if(i != CS_SUCCESS) |
4008 | { | 4004 | { |
4009 | cs_error(link->handle, RequestIRQ, i); | 4005 | cs_error(link, RequestIRQ, i); |
4010 | break; | 4006 | break; |
4011 | } | 4007 | } |
4012 | 4008 | ||
@@ -4015,15 +4011,15 @@ wv_pcmcia_config(dev_link_t * link) | |||
4015 | * the I/O windows and the interrupt mapping. | 4011 | * the I/O windows and the interrupt mapping. |
4016 | */ | 4012 | */ |
4017 | link->conf.ConfigIndex = 1; | 4013 | link->conf.ConfigIndex = 1; |
4018 | i = pcmcia_request_configuration(link->handle, &link->conf); | 4014 | i = pcmcia_request_configuration(link, &link->conf); |
4019 | if(i != CS_SUCCESS) | 4015 | if(i != CS_SUCCESS) |
4020 | { | 4016 | { |
4021 | cs_error(link->handle, RequestConfiguration, i); | 4017 | cs_error(link, RequestConfiguration, i); |
4022 | break; | 4018 | break; |
4023 | } | 4019 | } |
4024 | 4020 | ||
4025 | /* | 4021 | /* |
4026 | * Allocate a small memory window. Note that the dev_link_t | 4022 | * Allocate a small memory window. Note that the struct pcmcia_device |
4027 | * structure provides space for one window handle -- if your | 4023 | * structure provides space for one window handle -- if your |
4028 | * device needs several windows, you'll need to keep track of | 4024 | * device needs several windows, you'll need to keep track of |
4029 | * the handles in your private data structure, link->priv. | 4025 | * the handles in your private data structure, link->priv. |
@@ -4031,10 +4027,10 @@ wv_pcmcia_config(dev_link_t * link) | |||
4031 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; | 4027 | req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; |
4032 | req.Base = req.Size = 0; | 4028 | req.Base = req.Size = 0; |
4033 | req.AccessSpeed = mem_speed; | 4029 | req.AccessSpeed = mem_speed; |
4034 | i = pcmcia_request_window(&link->handle, &req, &link->win); | 4030 | i = pcmcia_request_window(&link, &req, &link->win); |
4035 | if(i != CS_SUCCESS) | 4031 | if(i != CS_SUCCESS) |
4036 | { | 4032 | { |
4037 | cs_error(link->handle, RequestWindow, i); | 4033 | cs_error(link, RequestWindow, i); |
4038 | break; | 4034 | break; |
4039 | } | 4035 | } |
4040 | 4036 | ||
@@ -4046,7 +4042,7 @@ wv_pcmcia_config(dev_link_t * link) | |||
4046 | i = pcmcia_map_mem_page(link->win, &mem); | 4042 | i = pcmcia_map_mem_page(link->win, &mem); |
4047 | if(i != CS_SUCCESS) | 4043 | if(i != CS_SUCCESS) |
4048 | { | 4044 | { |
4049 | cs_error(link->handle, MapMemPage, i); | 4045 | cs_error(link, MapMemPage, i); |
4050 | break; | 4046 | break; |
4051 | } | 4047 | } |
4052 | 4048 | ||
@@ -4060,7 +4056,7 @@ wv_pcmcia_config(dev_link_t * link) | |||
4060 | lp->mem, dev->irq, (u_int) dev->base_addr); | 4056 | lp->mem, dev->irq, (u_int) dev->base_addr); |
4061 | #endif | 4057 | #endif |
4062 | 4058 | ||
4063 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | 4059 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
4064 | i = register_netdev(dev); | 4060 | i = register_netdev(dev); |
4065 | if(i != 0) | 4061 | if(i != 0) |
4066 | { | 4062 | { |
@@ -4072,7 +4068,6 @@ wv_pcmcia_config(dev_link_t * link) | |||
4072 | } | 4068 | } |
4073 | while(0); /* Humm... Disguised goto !!! */ | 4069 | while(0); /* Humm... Disguised goto !!! */ |
4074 | 4070 | ||
4075 | link->state &= ~DEV_CONFIG_PENDING; | ||
4076 | /* If any step failed, release any partially configured state */ | 4071 | /* If any step failed, release any partially configured state */ |
4077 | if(i != 0) | 4072 | if(i != 0) |
4078 | { | 4073 | { |
@@ -4081,7 +4076,7 @@ wv_pcmcia_config(dev_link_t * link) | |||
4081 | } | 4076 | } |
4082 | 4077 | ||
4083 | strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name); | 4078 | strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name); |
4084 | link->dev = &((net_local *) netdev_priv(dev))->node; | 4079 | link->dev_node = &((net_local *) netdev_priv(dev))->node; |
4085 | 4080 | ||
4086 | #ifdef DEBUG_CONFIG_TRACE | 4081 | #ifdef DEBUG_CONFIG_TRACE |
4087 | printk(KERN_DEBUG "<-wv_pcmcia_config()\n"); | 4082 | printk(KERN_DEBUG "<-wv_pcmcia_config()\n"); |
@@ -4096,26 +4091,20 @@ wv_pcmcia_config(dev_link_t * link) | |||
4096 | * still open, this will be postponed until it is closed. | 4091 | * still open, this will be postponed until it is closed. |
4097 | */ | 4092 | */ |
4098 | static void | 4093 | static void |
4099 | wv_pcmcia_release(dev_link_t *link) | 4094 | wv_pcmcia_release(struct pcmcia_device *link) |
4100 | { | 4095 | { |
4101 | struct net_device * dev = (struct net_device *) link->priv; | 4096 | struct net_device * dev = (struct net_device *) link->priv; |
4102 | net_local * lp = netdev_priv(dev); | 4097 | net_local * lp = netdev_priv(dev); |
4103 | 4098 | ||
4104 | #ifdef DEBUG_CONFIG_TRACE | 4099 | #ifdef DEBUG_CONFIG_TRACE |
4105 | printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link); | 4100 | printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link); |
4106 | #endif | 4101 | #endif |
4107 | 4102 | ||
4108 | /* Don't bother checking to see if these succeed or not */ | 4103 | iounmap(lp->mem); |
4109 | iounmap(lp->mem); | 4104 | pcmcia_disable_device(link); |
4110 | pcmcia_release_window(link->win); | ||
4111 | pcmcia_release_configuration(link->handle); | ||
4112 | pcmcia_release_io(link->handle, &link->io); | ||
4113 | pcmcia_release_irq(link->handle, &link->irq); | ||
4114 | |||
4115 | link->state &= ~DEV_CONFIG; | ||
4116 | 4105 | ||
4117 | #ifdef DEBUG_CONFIG_TRACE | 4106 | #ifdef DEBUG_CONFIG_TRACE |
4118 | printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); | 4107 | printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); |
4119 | #endif | 4108 | #endif |
4120 | } | 4109 | } |
4121 | 4110 | ||
@@ -4479,7 +4468,7 @@ static int | |||
4479 | wavelan_open(struct net_device * dev) | 4468 | wavelan_open(struct net_device * dev) |
4480 | { | 4469 | { |
4481 | net_local * lp = netdev_priv(dev); | 4470 | net_local * lp = netdev_priv(dev); |
4482 | dev_link_t * link = lp->link; | 4471 | struct pcmcia_device * link = lp->link; |
4483 | kio_addr_t base = dev->base_addr; | 4472 | kio_addr_t base = dev->base_addr; |
4484 | 4473 | ||
4485 | #ifdef DEBUG_CALLBACK_TRACE | 4474 | #ifdef DEBUG_CALLBACK_TRACE |
@@ -4533,7 +4522,7 @@ wavelan_open(struct net_device * dev) | |||
4533 | static int | 4522 | static int |
4534 | wavelan_close(struct net_device * dev) | 4523 | wavelan_close(struct net_device * dev) |
4535 | { | 4524 | { |
4536 | dev_link_t * link = ((net_local *)netdev_priv(dev))->link; | 4525 | struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link; |
4537 | kio_addr_t base = dev->base_addr; | 4526 | kio_addr_t base = dev->base_addr; |
4538 | 4527 | ||
4539 | #ifdef DEBUG_CALLBACK_TRACE | 4528 | #ifdef DEBUG_CALLBACK_TRACE |
@@ -4587,45 +4576,36 @@ wavelan_close(struct net_device * dev) | |||
4587 | * card insertion event. | 4576 | * card insertion event. |
4588 | */ | 4577 | */ |
4589 | static int | 4578 | static int |
4590 | wavelan_attach(struct pcmcia_device *p_dev) | 4579 | wavelan_probe(struct pcmcia_device *p_dev) |
4591 | { | 4580 | { |
4592 | dev_link_t * link; /* Info for cardmgr */ | ||
4593 | struct net_device * dev; /* Interface generic data */ | 4581 | struct net_device * dev; /* Interface generic data */ |
4594 | net_local * lp; /* Interface specific data */ | 4582 | net_local * lp; /* Interface specific data */ |
4583 | int ret; | ||
4595 | 4584 | ||
4596 | #ifdef DEBUG_CALLBACK_TRACE | 4585 | #ifdef DEBUG_CALLBACK_TRACE |
4597 | printk(KERN_DEBUG "-> wavelan_attach()\n"); | 4586 | printk(KERN_DEBUG "-> wavelan_attach()\n"); |
4598 | #endif | 4587 | #endif |
4599 | 4588 | ||
4600 | /* Initialize the dev_link_t structure */ | ||
4601 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); | ||
4602 | if (!link) return -ENOMEM; | ||
4603 | |||
4604 | /* The io structure describes IO port mapping */ | 4589 | /* The io structure describes IO port mapping */ |
4605 | link->io.NumPorts1 = 8; | 4590 | p_dev->io.NumPorts1 = 8; |
4606 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 4591 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
4607 | link->io.IOAddrLines = 3; | 4592 | p_dev->io.IOAddrLines = 3; |
4608 | 4593 | ||
4609 | /* Interrupt setup */ | 4594 | /* Interrupt setup */ |
4610 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | 4595 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; |
4611 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 4596 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
4612 | link->irq.Handler = wavelan_interrupt; | 4597 | p_dev->irq.Handler = wavelan_interrupt; |
4613 | 4598 | ||
4614 | /* General socket configuration */ | 4599 | /* General socket configuration */ |
4615 | link->conf.Attributes = CONF_ENABLE_IRQ; | 4600 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; |
4616 | link->conf.Vcc = 50; | 4601 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
4617 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
4618 | |||
4619 | /* Chain drivers */ | ||
4620 | link->next = NULL; | ||
4621 | 4602 | ||
4622 | /* Allocate the generic data structure */ | 4603 | /* Allocate the generic data structure */ |
4623 | dev = alloc_etherdev(sizeof(net_local)); | 4604 | dev = alloc_etherdev(sizeof(net_local)); |
4624 | if (!dev) { | 4605 | if (!dev) |
4625 | kfree(link); | ||
4626 | return -ENOMEM; | 4606 | return -ENOMEM; |
4627 | } | 4607 | |
4628 | link->priv = link->irq.Instance = dev; | 4608 | p_dev->priv = p_dev->irq.Instance = dev; |
4629 | 4609 | ||
4630 | lp = netdev_priv(dev); | 4610 | lp = netdev_priv(dev); |
4631 | 4611 | ||
@@ -4642,7 +4622,6 @@ wavelan_attach(struct pcmcia_device *p_dev) | |||
4642 | spin_lock_init(&lp->spinlock); | 4622 | spin_lock_init(&lp->spinlock); |
4643 | 4623 | ||
4644 | /* back links */ | 4624 | /* back links */ |
4645 | lp->link = link; | ||
4646 | lp->dev = dev; | 4625 | lp->dev = dev; |
4647 | 4626 | ||
4648 | /* wavelan NET3 callbacks */ | 4627 | /* wavelan NET3 callbacks */ |
@@ -4668,15 +4647,18 @@ wavelan_attach(struct pcmcia_device *p_dev) | |||
4668 | /* Other specific data */ | 4647 | /* Other specific data */ |
4669 | dev->mtu = WAVELAN_MTU; | 4648 | dev->mtu = WAVELAN_MTU; |
4670 | 4649 | ||
4671 | link->handle = p_dev; | 4650 | ret = wv_pcmcia_config(p_dev); |
4672 | p_dev->instance = link; | 4651 | if (ret) |
4652 | return ret; | ||
4673 | 4653 | ||
4674 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | 4654 | ret = wv_hw_config(dev); |
4675 | if(wv_pcmcia_config(link) && | 4655 | if (ret) { |
4676 | wv_hw_config(dev)) | ||
4677 | wv_init_info(dev); | ||
4678 | else | ||
4679 | dev->irq = 0; | 4656 | dev->irq = 0; |
4657 | pcmcia_disable_device(p_dev); | ||
4658 | return ret; | ||
4659 | } | ||
4660 | |||
4661 | wv_init_info(dev); | ||
4680 | 4662 | ||
4681 | #ifdef DEBUG_CALLBACK_TRACE | 4663 | #ifdef DEBUG_CALLBACK_TRACE |
4682 | printk(KERN_DEBUG "<- wavelan_attach()\n"); | 4664 | printk(KERN_DEBUG "<- wavelan_attach()\n"); |
@@ -4693,25 +4675,14 @@ wavelan_attach(struct pcmcia_device *p_dev) | |||
4693 | * is released. | 4675 | * is released. |
4694 | */ | 4676 | */ |
4695 | static void | 4677 | static void |
4696 | wavelan_detach(struct pcmcia_device *p_dev) | 4678 | wavelan_detach(struct pcmcia_device *link) |
4697 | { | 4679 | { |
4698 | dev_link_t *link = dev_to_instance(p_dev); | ||
4699 | |||
4700 | #ifdef DEBUG_CALLBACK_TRACE | 4680 | #ifdef DEBUG_CALLBACK_TRACE |
4701 | printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); | 4681 | printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); |
4702 | #endif | 4682 | #endif |
4703 | 4683 | ||
4704 | /* | 4684 | /* Some others haven't done their job : give them another chance */ |
4705 | * If the device is currently configured and active, we won't | 4685 | wv_pcmcia_release(link); |
4706 | * actually delete it yet. Instead, it is marked so that when the | ||
4707 | * release() function is called, that will trigger a proper | ||
4708 | * detach(). | ||
4709 | */ | ||
4710 | if(link->state & DEV_CONFIG) | ||
4711 | { | ||
4712 | /* Some others haven't done their job : give them another chance */ | ||
4713 | wv_pcmcia_release(link); | ||
4714 | } | ||
4715 | 4686 | ||
4716 | /* Free pieces */ | 4687 | /* Free pieces */ |
4717 | if(link->priv) | 4688 | if(link->priv) |
@@ -4720,23 +4691,21 @@ wavelan_detach(struct pcmcia_device *p_dev) | |||
4720 | 4691 | ||
4721 | /* Remove ourselves from the kernel list of ethernet devices */ | 4692 | /* Remove ourselves from the kernel list of ethernet devices */ |
4722 | /* Warning : can't be called from interrupt, timer or wavelan_close() */ | 4693 | /* Warning : can't be called from interrupt, timer or wavelan_close() */ |
4723 | if (link->dev) | 4694 | if (link->dev_node) |
4724 | unregister_netdev(dev); | 4695 | unregister_netdev(dev); |
4725 | link->dev = NULL; | 4696 | link->dev_node = NULL; |
4726 | ((net_local *)netdev_priv(dev))->link = NULL; | 4697 | ((net_local *)netdev_priv(dev))->link = NULL; |
4727 | ((net_local *)netdev_priv(dev))->dev = NULL; | 4698 | ((net_local *)netdev_priv(dev))->dev = NULL; |
4728 | free_netdev(dev); | 4699 | free_netdev(dev); |
4729 | } | 4700 | } |
4730 | kfree(link); | ||
4731 | 4701 | ||
4732 | #ifdef DEBUG_CALLBACK_TRACE | 4702 | #ifdef DEBUG_CALLBACK_TRACE |
4733 | printk(KERN_DEBUG "<- wavelan_detach()\n"); | 4703 | printk(KERN_DEBUG "<- wavelan_detach()\n"); |
4734 | #endif | 4704 | #endif |
4735 | } | 4705 | } |
4736 | 4706 | ||
4737 | static int wavelan_suspend(struct pcmcia_device *p_dev) | 4707 | static int wavelan_suspend(struct pcmcia_device *link) |
4738 | { | 4708 | { |
4739 | dev_link_t *link = dev_to_instance(p_dev); | ||
4740 | struct net_device * dev = (struct net_device *) link->priv; | 4709 | struct net_device * dev = (struct net_device *) link->priv; |
4741 | 4710 | ||
4742 | /* NB: wavelan_close will be called, but too late, so we are | 4711 | /* NB: wavelan_close will be called, but too late, so we are |
@@ -4748,36 +4717,22 @@ static int wavelan_suspend(struct pcmcia_device *p_dev) | |||
4748 | /* Stop receiving new messages and wait end of transmission */ | 4717 | /* Stop receiving new messages and wait end of transmission */ |
4749 | wv_ru_stop(dev); | 4718 | wv_ru_stop(dev); |
4750 | 4719 | ||
4720 | if (link->open) | ||
4721 | netif_device_detach(dev); | ||
4722 | |||
4751 | /* Power down the module */ | 4723 | /* Power down the module */ |
4752 | hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT)); | 4724 | hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT)); |
4753 | 4725 | ||
4754 | /* The card is now suspended */ | ||
4755 | link->state |= DEV_SUSPEND; | ||
4756 | |||
4757 | if(link->state & DEV_CONFIG) | ||
4758 | { | ||
4759 | if(link->open) | ||
4760 | netif_device_detach(dev); | ||
4761 | pcmcia_release_configuration(link->handle); | ||
4762 | } | ||
4763 | |||
4764 | return 0; | 4726 | return 0; |
4765 | } | 4727 | } |
4766 | 4728 | ||
4767 | static int wavelan_resume(struct pcmcia_device *p_dev) | 4729 | static int wavelan_resume(struct pcmcia_device *link) |
4768 | { | 4730 | { |
4769 | dev_link_t *link = dev_to_instance(p_dev); | ||
4770 | struct net_device * dev = (struct net_device *) link->priv; | 4731 | struct net_device * dev = (struct net_device *) link->priv; |
4771 | 4732 | ||
4772 | link->state &= ~DEV_SUSPEND; | 4733 | if (link->open) { |
4773 | if(link->state & DEV_CONFIG) | 4734 | wv_hw_reset(dev); |
4774 | { | 4735 | netif_device_attach(dev); |
4775 | pcmcia_request_configuration(link->handle, &link->conf); | ||
4776 | if(link->open) /* If RESET -> True, If RESUME -> False ? */ | ||
4777 | { | ||
4778 | wv_hw_reset(dev); | ||
4779 | netif_device_attach(dev); | ||
4780 | } | ||
4781 | } | 4736 | } |
4782 | 4737 | ||
4783 | return 0; | 4738 | return 0; |
@@ -4798,7 +4753,7 @@ static struct pcmcia_driver wavelan_driver = { | |||
4798 | .drv = { | 4753 | .drv = { |
4799 | .name = "wavelan_cs", | 4754 | .name = "wavelan_cs", |
4800 | }, | 4755 | }, |
4801 | .probe = wavelan_attach, | 4756 | .probe = wavelan_probe, |
4802 | .remove = wavelan_detach, | 4757 | .remove = wavelan_detach, |
4803 | .id_table = wavelan_ids, | 4758 | .id_table = wavelan_ids, |
4804 | .suspend = wavelan_suspend, | 4759 | .suspend = wavelan_suspend, |
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h index 451f6271dcbc..c65fe7a391ec 100644 --- a/drivers/net/wireless/wavelan_cs.p.h +++ b/drivers/net/wireless/wavelan_cs.p.h | |||
@@ -602,7 +602,7 @@ struct net_local | |||
602 | dev_node_t node; /* ???? What is this stuff ???? */ | 602 | dev_node_t node; /* ???? What is this stuff ???? */ |
603 | struct net_device * dev; /* Reverse link... */ | 603 | struct net_device * dev; /* Reverse link... */ |
604 | spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ | 604 | spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ |
605 | dev_link_t * link; /* pcmcia structure */ | 605 | struct pcmcia_device * link; /* pcmcia structure */ |
606 | en_stats stats; /* Ethernet interface statistics */ | 606 | en_stats stats; /* Ethernet interface statistics */ |
607 | int nresets; /* Number of hw resets */ | 607 | int nresets; /* Number of hw resets */ |
608 | u_char configured; /* If it is configured */ | 608 | u_char configured; /* If it is configured */ |
@@ -733,9 +733,9 @@ static int | |||
733 | static inline void | 733 | static inline void |
734 | wv_hw_reset(struct net_device *); /* Same, + start receiver unit */ | 734 | wv_hw_reset(struct net_device *); /* Same, + start receiver unit */ |
735 | static inline int | 735 | static inline int |
736 | wv_pcmcia_config(dev_link_t *); /* Configure the pcmcia interface */ | 736 | wv_pcmcia_config(struct pcmcia_device *); /* Configure the pcmcia interface */ |
737 | static void | 737 | static void |
738 | wv_pcmcia_release(dev_link_t *);/* Remove a device */ | 738 | wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */ |
739 | /* ---------------------- INTERRUPT HANDLING ---------------------- */ | 739 | /* ---------------------- INTERRUPT HANDLING ---------------------- */ |
740 | static irqreturn_t | 740 | static irqreturn_t |
741 | wavelan_interrupt(int, /* Interrupt handler */ | 741 | wavelan_interrupt(int, /* Interrupt handler */ |
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h index 4303c50c2ab6..65ceb088f700 100644 --- a/drivers/net/wireless/wl3501.h +++ b/drivers/net/wireless/wl3501.h | |||
@@ -611,5 +611,6 @@ struct wl3501_card { | |||
611 | struct iw_spy_data spy_data; | 611 | struct iw_spy_data spy_data; |
612 | struct iw_public_data wireless_data; | 612 | struct iw_public_data wireless_data; |
613 | struct dev_node_t node; | 613 | struct dev_node_t node; |
614 | struct pcmcia_device *p_dev; | ||
614 | }; | 615 | }; |
615 | #endif | 616 | #endif |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 48e10b0c7e74..e52a650f6737 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -103,8 +103,8 @@ module_param(pc_debug, int, 0); | |||
103 | * release a socket, in response to card insertion and ejection events. They | 103 | * release a socket, in response to card insertion and ejection events. They |
104 | * are invoked from the wl24 event handler. | 104 | * are invoked from the wl24 event handler. |
105 | */ | 105 | */ |
106 | static void wl3501_config(dev_link_t *link); | 106 | static int wl3501_config(struct pcmcia_device *link); |
107 | static void wl3501_release(dev_link_t *link); | 107 | static void wl3501_release(struct pcmcia_device *link); |
108 | 108 | ||
109 | /* | 109 | /* |
110 | * The dev_info variable is the "key" that is used to match up this | 110 | * The dev_info variable is the "key" that is used to match up this |
@@ -226,17 +226,6 @@ static void iw_copy_mgmt_info_element(struct iw_mgmt_info_element *to, | |||
226 | iw_set_mgmt_info_element(from->id, to, from->data, from->len); | 226 | iw_set_mgmt_info_element(from->id, to, from->data, from->len); |
227 | } | 227 | } |
228 | 228 | ||
229 | /* | ||
230 | * A linked list of "instances" of the wl24 device. Each actual PCMCIA card | ||
231 | * corresponds to one device instance, and is described by one dev_link_t | ||
232 | * structure (defined in ds.h). | ||
233 | * | ||
234 | * You may not want to use a linked list for this -- for example, the memory | ||
235 | * card driver uses an array of dev_link_t pointers, where minor device numbers | ||
236 | * are used to derive the corresponding array index. | ||
237 | */ | ||
238 | static dev_link_t *wl3501_dev_list; | ||
239 | |||
240 | static inline void wl3501_switch_page(struct wl3501_card *this, u8 page) | 229 | static inline void wl3501_switch_page(struct wl3501_card *this, u8 page) |
241 | { | 230 | { |
242 | wl3501_outb(page, this->base_addr + WL3501_NIC_BSS); | 231 | wl3501_outb(page, this->base_addr + WL3501_NIC_BSS); |
@@ -1281,15 +1270,10 @@ static int wl3501_close(struct net_device *dev) | |||
1281 | struct wl3501_card *this = dev->priv; | 1270 | struct wl3501_card *this = dev->priv; |
1282 | int rc = -ENODEV; | 1271 | int rc = -ENODEV; |
1283 | unsigned long flags; | 1272 | unsigned long flags; |
1284 | dev_link_t *link; | 1273 | struct pcmcia_device *link; |
1274 | link = this->p_dev; | ||
1285 | 1275 | ||
1286 | spin_lock_irqsave(&this->lock, flags); | 1276 | spin_lock_irqsave(&this->lock, flags); |
1287 | /* Check if the device is in wl3501_dev_list */ | ||
1288 | for (link = wl3501_dev_list; link; link = link->next) | ||
1289 | if (link->priv == dev) | ||
1290 | break; | ||
1291 | if (!link) | ||
1292 | goto out; | ||
1293 | link->open--; | 1277 | link->open--; |
1294 | 1278 | ||
1295 | /* Stop wl3501_hard_start_xmit() from now on */ | 1279 | /* Stop wl3501_hard_start_xmit() from now on */ |
@@ -1301,7 +1285,6 @@ static int wl3501_close(struct net_device *dev) | |||
1301 | 1285 | ||
1302 | rc = 0; | 1286 | rc = 0; |
1303 | printk(KERN_INFO "%s: WL3501 closed\n", dev->name); | 1287 | printk(KERN_INFO "%s: WL3501 closed\n", dev->name); |
1304 | out: | ||
1305 | spin_unlock_irqrestore(&this->lock, flags); | 1288 | spin_unlock_irqrestore(&this->lock, flags); |
1306 | return rc; | 1289 | return rc; |
1307 | } | 1290 | } |
@@ -1400,14 +1383,11 @@ static int wl3501_open(struct net_device *dev) | |||
1400 | int rc = -ENODEV; | 1383 | int rc = -ENODEV; |
1401 | struct wl3501_card *this = dev->priv; | 1384 | struct wl3501_card *this = dev->priv; |
1402 | unsigned long flags; | 1385 | unsigned long flags; |
1403 | dev_link_t *link; | 1386 | struct pcmcia_device *link; |
1387 | link = this->p_dev; | ||
1404 | 1388 | ||
1405 | spin_lock_irqsave(&this->lock, flags); | 1389 | spin_lock_irqsave(&this->lock, flags); |
1406 | /* Check if the device is in wl3501_dev_list */ | 1390 | if (!pcmcia_dev_present(link)) |
1407 | for (link = wl3501_dev_list; link; link = link->next) | ||
1408 | if (link->priv == dev) | ||
1409 | break; | ||
1410 | if (!DEV_OK(link)) | ||
1411 | goto out; | 1391 | goto out; |
1412 | netif_device_attach(dev); | 1392 | netif_device_attach(dev); |
1413 | link->open++; | 1393 | link->open++; |
@@ -1497,38 +1477,23 @@ static struct ethtool_ops ops = { | |||
1497 | * Services. If it has been released, all local data structures are freed. | 1477 | * Services. If it has been released, all local data structures are freed. |
1498 | * Otherwise, the structures will be freed when the device is released. | 1478 | * Otherwise, the structures will be freed when the device is released. |
1499 | */ | 1479 | */ |
1500 | static void wl3501_detach(struct pcmcia_device *p_dev) | 1480 | static void wl3501_detach(struct pcmcia_device *link) |
1501 | { | 1481 | { |
1502 | dev_link_t *link = dev_to_instance(p_dev); | ||
1503 | dev_link_t **linkp; | ||
1504 | struct net_device *dev = link->priv; | 1482 | struct net_device *dev = link->priv; |
1505 | 1483 | ||
1506 | /* Locate device structure */ | ||
1507 | for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next) | ||
1508 | if (*linkp == link) | ||
1509 | break; | ||
1510 | if (!*linkp) | ||
1511 | goto out; | ||
1512 | |||
1513 | /* If the device is currently configured and active, we won't actually | 1484 | /* If the device is currently configured and active, we won't actually |
1514 | * delete it yet. Instead, it is marked so that when the release() | 1485 | * delete it yet. Instead, it is marked so that when the release() |
1515 | * function is called, that will trigger a proper detach(). */ | 1486 | * function is called, that will trigger a proper detach(). */ |
1516 | 1487 | ||
1517 | if (link->state & DEV_CONFIG) { | 1488 | while (link->open > 0) |
1518 | while (link->open > 0) | 1489 | wl3501_close(dev); |
1519 | wl3501_close(dev); | ||
1520 | |||
1521 | netif_device_detach(dev); | ||
1522 | wl3501_release(link); | ||
1523 | } | ||
1524 | 1490 | ||
1525 | /* Unlink device structure, free pieces */ | 1491 | netif_device_detach(dev); |
1526 | *linkp = link->next; | 1492 | wl3501_release(link); |
1527 | 1493 | ||
1528 | if (link->priv) | 1494 | if (link->priv) |
1529 | free_netdev(link->priv); | 1495 | free_netdev(link->priv); |
1530 | kfree(link); | 1496 | |
1531 | out: | ||
1532 | return; | 1497 | return; |
1533 | } | 1498 | } |
1534 | 1499 | ||
@@ -1953,33 +1918,26 @@ static const struct iw_handler_def wl3501_handler_def = { | |||
1953 | * The dev_link structure is initialized, but we don't actually configure the | 1918 | * The dev_link structure is initialized, but we don't actually configure the |
1954 | * card at this point -- we wait until we receive a card insertion event. | 1919 | * card at this point -- we wait until we receive a card insertion event. |
1955 | */ | 1920 | */ |
1956 | static int wl3501_attach(struct pcmcia_device *p_dev) | 1921 | static int wl3501_probe(struct pcmcia_device *p_dev) |
1957 | { | 1922 | { |
1958 | dev_link_t *link; | ||
1959 | struct net_device *dev; | 1923 | struct net_device *dev; |
1960 | struct wl3501_card *this; | 1924 | struct wl3501_card *this; |
1961 | 1925 | ||
1962 | /* Initialize the dev_link_t structure */ | ||
1963 | link = kzalloc(sizeof(*link), GFP_KERNEL); | ||
1964 | if (!link) | ||
1965 | return -ENOMEM; | ||
1966 | |||
1967 | /* The io structure describes IO port mapping */ | 1926 | /* The io structure describes IO port mapping */ |
1968 | link->io.NumPorts1 = 16; | 1927 | p_dev->io.NumPorts1 = 16; |
1969 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | 1928 | p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; |
1970 | link->io.IOAddrLines = 5; | 1929 | p_dev->io.IOAddrLines = 5; |
1971 | 1930 | ||
1972 | /* Interrupt setup */ | 1931 | /* Interrupt setup */ |
1973 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | 1932 | p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; |
1974 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 1933 | p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; |
1975 | link->irq.Handler = wl3501_interrupt; | 1934 | p_dev->irq.Handler = wl3501_interrupt; |
1976 | 1935 | ||
1977 | /* General socket configuration */ | 1936 | /* General socket configuration */ |
1978 | link->conf.Attributes = CONF_ENABLE_IRQ; | 1937 | p_dev->conf.Attributes = CONF_ENABLE_IRQ; |
1979 | link->conf.Vcc = 50; | 1938 | p_dev->conf.IntType = INT_MEMORY_AND_IO; |
1980 | link->conf.IntType = INT_MEMORY_AND_IO; | 1939 | p_dev->conf.ConfigIndex = 1; |
1981 | link->conf.ConfigIndex = 1; | 1940 | p_dev->conf.Present = PRESENT_OPTION; |
1982 | link->conf.Present = PRESENT_OPTION; | ||
1983 | 1941 | ||
1984 | dev = alloc_etherdev(sizeof(struct wl3501_card)); | 1942 | dev = alloc_etherdev(sizeof(struct wl3501_card)); |
1985 | if (!dev) | 1943 | if (!dev) |
@@ -1992,22 +1950,15 @@ static int wl3501_attach(struct pcmcia_device *p_dev) | |||
1992 | dev->get_stats = wl3501_get_stats; | 1950 | dev->get_stats = wl3501_get_stats; |
1993 | this = dev->priv; | 1951 | this = dev->priv; |
1994 | this->wireless_data.spy_data = &this->spy_data; | 1952 | this->wireless_data.spy_data = &this->spy_data; |
1953 | this->p_dev = p_dev; | ||
1995 | dev->wireless_data = &this->wireless_data; | 1954 | dev->wireless_data = &this->wireless_data; |
1996 | dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def; | 1955 | dev->wireless_handlers = (struct iw_handler_def *)&wl3501_handler_def; |
1997 | SET_ETHTOOL_OPS(dev, &ops); | 1956 | SET_ETHTOOL_OPS(dev, &ops); |
1998 | netif_stop_queue(dev); | 1957 | netif_stop_queue(dev); |
1999 | link->priv = link->irq.Instance = dev; | 1958 | p_dev->priv = p_dev->irq.Instance = dev; |
2000 | |||
2001 | link->handle = p_dev; | ||
2002 | p_dev->instance = link; | ||
2003 | |||
2004 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
2005 | wl3501_config(link); | ||
2006 | 1959 | ||
2007 | return 0; | 1960 | return wl3501_config(p_dev); |
2008 | out_link: | 1961 | out_link: |
2009 | kfree(link); | ||
2010 | link = NULL; | ||
2011 | return -ENOMEM; | 1962 | return -ENOMEM; |
2012 | } | 1963 | } |
2013 | 1964 | ||
@@ -2022,11 +1973,10 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |||
2022 | * received, to configure the PCMCIA socket, and to make the ethernet device | 1973 | * received, to configure the PCMCIA socket, and to make the ethernet device |
2023 | * available to the system. | 1974 | * available to the system. |
2024 | */ | 1975 | */ |
2025 | static void wl3501_config(dev_link_t *link) | 1976 | static int wl3501_config(struct pcmcia_device *link) |
2026 | { | 1977 | { |
2027 | tuple_t tuple; | 1978 | tuple_t tuple; |
2028 | cisparse_t parse; | 1979 | cisparse_t parse; |
2029 | client_handle_t handle = link->handle; | ||
2030 | struct net_device *dev = link->priv; | 1980 | struct net_device *dev = link->priv; |
2031 | int i = 0, j, last_fn, last_ret; | 1981 | int i = 0, j, last_fn, last_ret; |
2032 | unsigned char bf[64]; | 1982 | unsigned char bf[64]; |
@@ -2035,18 +1985,15 @@ static void wl3501_config(dev_link_t *link) | |||
2035 | /* This reads the card's CONFIG tuple to find its config registers. */ | 1985 | /* This reads the card's CONFIG tuple to find its config registers. */ |
2036 | tuple.Attributes = 0; | 1986 | tuple.Attributes = 0; |
2037 | tuple.DesiredTuple = CISTPL_CONFIG; | 1987 | tuple.DesiredTuple = CISTPL_CONFIG; |
2038 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 1988 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
2039 | tuple.TupleData = bf; | 1989 | tuple.TupleData = bf; |
2040 | tuple.TupleDataMax = sizeof(bf); | 1990 | tuple.TupleDataMax = sizeof(bf); |
2041 | tuple.TupleOffset = 0; | 1991 | tuple.TupleOffset = 0; |
2042 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 1992 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
2043 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 1993 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
2044 | link->conf.ConfigBase = parse.config.base; | 1994 | link->conf.ConfigBase = parse.config.base; |
2045 | link->conf.Present = parse.config.rmask[0]; | 1995 | link->conf.Present = parse.config.rmask[0]; |
2046 | 1996 | ||
2047 | /* Configure card */ | ||
2048 | link->state |= DEV_CONFIG; | ||
2049 | |||
2050 | /* Try allocating IO ports. This tries a few fixed addresses. If you | 1997 | /* Try allocating IO ports. This tries a few fixed addresses. If you |
2051 | * want, you can also read the card's config table to pick addresses -- | 1998 | * want, you can also read the card's config table to pick addresses -- |
2052 | * see the serial driver for an example. */ | 1999 | * see the serial driver for an example. */ |
@@ -2056,28 +2003,28 @@ static void wl3501_config(dev_link_t *link) | |||
2056 | * 0x200-0x2ff, and so on, because this seems safer */ | 2003 | * 0x200-0x2ff, and so on, because this seems safer */ |
2057 | link->io.BasePort1 = j; | 2004 | link->io.BasePort1 = j; |
2058 | link->io.BasePort2 = link->io.BasePort1 + 0x10; | 2005 | link->io.BasePort2 = link->io.BasePort1 + 0x10; |
2059 | i = pcmcia_request_io(link->handle, &link->io); | 2006 | i = pcmcia_request_io(link, &link->io); |
2060 | if (i == CS_SUCCESS) | 2007 | if (i == CS_SUCCESS) |
2061 | break; | 2008 | break; |
2062 | } | 2009 | } |
2063 | if (i != CS_SUCCESS) { | 2010 | if (i != CS_SUCCESS) { |
2064 | cs_error(link->handle, RequestIO, i); | 2011 | cs_error(link, RequestIO, i); |
2065 | goto failed; | 2012 | goto failed; |
2066 | } | 2013 | } |
2067 | 2014 | ||
2068 | /* Now allocate an interrupt line. Note that this does not actually | 2015 | /* Now allocate an interrupt line. Note that this does not actually |
2069 | * assign a handler to the interrupt. */ | 2016 | * assign a handler to the interrupt. */ |
2070 | 2017 | ||
2071 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 2018 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
2072 | 2019 | ||
2073 | /* This actually configures the PCMCIA socket -- setting up the I/O | 2020 | /* This actually configures the PCMCIA socket -- setting up the I/O |
2074 | * windows and the interrupt mapping. */ | 2021 | * windows and the interrupt mapping. */ |
2075 | 2022 | ||
2076 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 2023 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
2077 | 2024 | ||
2078 | dev->irq = link->irq.AssignedIRQ; | 2025 | dev->irq = link->irq.AssignedIRQ; |
2079 | dev->base_addr = link->io.BasePort1; | 2026 | dev->base_addr = link->io.BasePort1; |
2080 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | 2027 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
2081 | if (register_netdev(dev)) { | 2028 | if (register_netdev(dev)) { |
2082 | printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n"); | 2029 | printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n"); |
2083 | goto failed; | 2030 | goto failed; |
@@ -2088,10 +2035,9 @@ static void wl3501_config(dev_link_t *link) | |||
2088 | this = dev->priv; | 2035 | this = dev->priv; |
2089 | /* | 2036 | /* |
2090 | * At this point, the dev_node_t structure(s) should be initialized and | 2037 | * At this point, the dev_node_t structure(s) should be initialized and |
2091 | * arranged in a linked list at link->dev. | 2038 | * arranged in a linked list at link->dev_node. |
2092 | */ | 2039 | */ |
2093 | link->dev = &this->node; | 2040 | link->dev_node = &this->node; |
2094 | link->state &= ~DEV_CONFIG_PENDING; | ||
2095 | 2041 | ||
2096 | this->base_addr = dev->base_addr; | 2042 | this->base_addr = dev->base_addr; |
2097 | 2043 | ||
@@ -2127,13 +2073,13 @@ static void wl3501_config(dev_link_t *link) | |||
2127 | spin_lock_init(&this->lock); | 2073 | spin_lock_init(&this->lock); |
2128 | init_waitqueue_head(&this->wait); | 2074 | init_waitqueue_head(&this->wait); |
2129 | netif_start_queue(dev); | 2075 | netif_start_queue(dev); |
2130 | goto out; | 2076 | return 0; |
2077 | |||
2131 | cs_failed: | 2078 | cs_failed: |
2132 | cs_error(link->handle, last_fn, last_ret); | 2079 | cs_error(link, last_fn, last_ret); |
2133 | failed: | 2080 | failed: |
2134 | wl3501_release(link); | 2081 | wl3501_release(link); |
2135 | out: | 2082 | return -ENODEV; |
2136 | return; | ||
2137 | } | 2083 | } |
2138 | 2084 | ||
2139 | /** | 2085 | /** |
@@ -2144,52 +2090,36 @@ out: | |||
2144 | * and release the PCMCIA configuration. If the device is still open, this | 2090 | * and release the PCMCIA configuration. If the device is still open, this |
2145 | * will be postponed until it is closed. | 2091 | * will be postponed until it is closed. |
2146 | */ | 2092 | */ |
2147 | static void wl3501_release(dev_link_t *link) | 2093 | static void wl3501_release(struct pcmcia_device *link) |
2148 | { | 2094 | { |
2149 | struct net_device *dev = link->priv; | 2095 | struct net_device *dev = link->priv; |
2150 | 2096 | ||
2151 | /* Unlink the device chain */ | 2097 | /* Unlink the device chain */ |
2152 | if (link->dev) { | 2098 | if (link->dev_node) |
2153 | unregister_netdev(dev); | 2099 | unregister_netdev(dev); |
2154 | link->dev = NULL; | ||
2155 | } | ||
2156 | 2100 | ||
2157 | /* Don't bother checking to see if these succeed or not */ | 2101 | pcmcia_disable_device(link); |
2158 | pcmcia_release_configuration(link->handle); | ||
2159 | pcmcia_release_io(link->handle, &link->io); | ||
2160 | pcmcia_release_irq(link->handle, &link->irq); | ||
2161 | link->state &= ~DEV_CONFIG; | ||
2162 | } | 2102 | } |
2163 | 2103 | ||
2164 | static int wl3501_suspend(struct pcmcia_device *p_dev) | 2104 | static int wl3501_suspend(struct pcmcia_device *link) |
2165 | { | 2105 | { |
2166 | dev_link_t *link = dev_to_instance(p_dev); | ||
2167 | struct net_device *dev = link->priv; | 2106 | struct net_device *dev = link->priv; |
2168 | 2107 | ||
2169 | link->state |= DEV_SUSPEND; | ||
2170 | |||
2171 | wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND); | 2108 | wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND); |
2172 | if (link->state & DEV_CONFIG) { | 2109 | if (link->open) |
2173 | if (link->open) | 2110 | netif_device_detach(dev); |
2174 | netif_device_detach(dev); | ||
2175 | pcmcia_release_configuration(link->handle); | ||
2176 | } | ||
2177 | 2111 | ||
2178 | return 0; | 2112 | return 0; |
2179 | } | 2113 | } |
2180 | 2114 | ||
2181 | static int wl3501_resume(struct pcmcia_device *p_dev) | 2115 | static int wl3501_resume(struct pcmcia_device *link) |
2182 | { | 2116 | { |
2183 | dev_link_t *link = dev_to_instance(p_dev); | ||
2184 | struct net_device *dev = link->priv; | 2117 | struct net_device *dev = link->priv; |
2185 | 2118 | ||
2186 | wl3501_pwr_mgmt(dev->priv, WL3501_RESUME); | 2119 | wl3501_pwr_mgmt(dev->priv, WL3501_RESUME); |
2187 | if (link->state & DEV_CONFIG) { | 2120 | if (link->open) { |
2188 | pcmcia_request_configuration(link->handle, &link->conf); | 2121 | wl3501_reset(dev); |
2189 | if (link->open) { | 2122 | netif_device_attach(dev); |
2190 | wl3501_reset(dev); | ||
2191 | netif_device_attach(dev); | ||
2192 | } | ||
2193 | } | 2123 | } |
2194 | 2124 | ||
2195 | return 0; | 2125 | return 0; |
@@ -2207,7 +2137,7 @@ static struct pcmcia_driver wl3501_driver = { | |||
2207 | .drv = { | 2137 | .drv = { |
2208 | .name = "wl3501_cs", | 2138 | .name = "wl3501_cs", |
2209 | }, | 2139 | }, |
2210 | .probe = wl3501_attach, | 2140 | .probe = wl3501_probe, |
2211 | .remove = wl3501_detach, | 2141 | .remove = wl3501_detach, |
2212 | .id_table = wl3501_ids, | 2142 | .id_table = wl3501_ids, |
2213 | .suspend = wl3501_suspend, | 2143 | .suspend = wl3501_suspend, |
@@ -2221,9 +2151,7 @@ static int __init wl3501_init_module(void) | |||
2221 | 2151 | ||
2222 | static void __exit wl3501_exit_module(void) | 2152 | static void __exit wl3501_exit_module(void) |
2223 | { | 2153 | { |
2224 | dprintk(0, ": unloading"); | ||
2225 | pcmcia_unregister_driver(&wl3501_driver); | 2154 | pcmcia_unregister_driver(&wl3501_driver); |
2226 | BUG_ON(wl3501_dev_list != NULL); | ||
2227 | } | 2155 | } |
2228 | 2156 | ||
2229 | module_init(wl3501_init_module); | 2157 | module_init(wl3501_init_module); |
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c index 75d56bfef0ee..fd0f43b7db5b 100644 --- a/drivers/net/yellowfin.c +++ b/drivers/net/yellowfin.c | |||
@@ -1441,8 +1441,7 @@ static void __devexit yellowfin_remove_one (struct pci_dev *pdev) | |||
1441 | struct net_device *dev = pci_get_drvdata(pdev); | 1441 | struct net_device *dev = pci_get_drvdata(pdev); |
1442 | struct yellowfin_private *np; | 1442 | struct yellowfin_private *np; |
1443 | 1443 | ||
1444 | if (!dev) | 1444 | BUG_ON(!dev); |
1445 | BUG(); | ||
1446 | np = netdev_priv(dev); | 1445 | np = netdev_priv(dev); |
1447 | 1446 | ||
1448 | pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, | 1447 | pci_free_consistent(pdev, STATUS_TOTAL_SIZE, np->tx_status, |