diff options
| author | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-06 03:47:18 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-06 03:47:18 -0400 |
| commit | 5bcaa155797ab62ed363932ec0f02fbcb5db1ef1 (patch) | |
| tree | 1db633712bd47ce72ac5a1aed62b3417733ac63a | |
| parent | 1e231efe50ffe4d291be24d2fe393188de9c4b08 (diff) | |
| parent | 3a48c4c2d52a08e12319ab7caacad0a9b88e6cb4 (diff) | |
Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
| -rw-r--r-- | drivers/net/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/net/chelsio/common.h | 4 | ||||
| -rw-r--r-- | drivers/net/chelsio/cxgb2.c | 2 | ||||
| -rw-r--r-- | drivers/net/e1000/e1000_hw.h | 2 | ||||
| -rw-r--r-- | drivers/net/mv643xx_eth.c | 139 | ||||
| -rw-r--r-- | drivers/net/mv643xx_eth.h | 4 | ||||
| -rw-r--r-- | drivers/net/ne3210.c | 9 | ||||
| -rw-r--r-- | drivers/net/phy/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/net/phy/mdio_bus.c | 2 | ||||
| -rw-r--r-- | drivers/net/s2io.c | 14 | ||||
| -rw-r--r-- | drivers/net/sis190.c | 131 | ||||
| -rw-r--r-- | drivers/net/tulip/uli526x.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/Kconfig | 38 | ||||
| -rw-r--r-- | drivers/net/wireless/Makefile | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ipw2100.c | 69 | ||||
| -rw-r--r-- | drivers/net/wireless/ipw2200.h | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/orinoco.c | 93 | ||||
| -rw-r--r-- | drivers/net/wireless/orinoco_cs.c | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/orinoco_nortel.c | 324 | ||||
| -rw-r--r-- | drivers/net/wireless/spectrum_cs.c | 1120 | ||||
| -rw-r--r-- | net/core/ethtool.c | 2 |
21 files changed, 1736 insertions, 234 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 7d8bcb38797a..ae9e7a579b94 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
| @@ -397,7 +397,7 @@ config SUN3LANCE | |||
| 397 | If you're not building a kernel for a Sun 3, say N. | 397 | If you're not building a kernel for a Sun 3, say N. |
| 398 | 398 | ||
| 399 | config SUN3_82586 | 399 | config SUN3_82586 |
| 400 | tristate "Sun3 on-board Intel 82586 support" | 400 | bool "Sun3 on-board Intel 82586 support" |
| 401 | depends on NET_ETHERNET && SUN3 | 401 | depends on NET_ETHERNET && SUN3 |
| 402 | help | 402 | help |
| 403 | This driver enables support for the on-board Intel 82586 based | 403 | This driver enables support for the on-board Intel 82586 based |
| @@ -1924,12 +1924,15 @@ config R8169_VLAN | |||
| 1924 | If in doubt, say Y. | 1924 | If in doubt, say Y. |
| 1925 | 1925 | ||
| 1926 | config SIS190 | 1926 | config SIS190 |
| 1927 | tristate "SiS190 gigabit ethernet support" | 1927 | tristate "SiS190/SiS191 gigabit ethernet support" |
| 1928 | depends on PCI | 1928 | depends on PCI |
| 1929 | select CRC32 | 1929 | select CRC32 |
| 1930 | select MII | 1930 | select MII |
| 1931 | ---help--- | 1931 | ---help--- |
| 1932 | Say Y here if you have a SiS 190 PCI Gigabit Ethernet adapter. | 1932 | Say Y here if you have a SiS 190 PCI Fast Ethernet adapter or |
| 1933 | a SiS 191 PCI Gigabit Ethernet adapter. Both are expected to | ||
| 1934 | appear in lan on motherboard designs which are based on SiS 965 | ||
| 1935 | and SiS 966 south bridge. | ||
| 1933 | 1936 | ||
| 1934 | To compile this driver as a module, choose M here: the module | 1937 | To compile this driver as a module, choose M here: the module |
| 1935 | will be called sis190. This is recommended. | 1938 | will be called sis190. This is recommended. |
diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index f09348802b46..bf3e7b6a7a18 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h | |||
| @@ -88,7 +88,7 @@ struct t1_rx_mode { | |||
| 88 | 88 | ||
| 89 | static inline u8 *t1_get_next_mcaddr(struct t1_rx_mode *rm) | 89 | static inline u8 *t1_get_next_mcaddr(struct t1_rx_mode *rm) |
| 90 | { | 90 | { |
| 91 | u8 *addr = 0; | 91 | u8 *addr = NULL; |
| 92 | 92 | ||
| 93 | if (rm->idx++ < rm->dev->mc_count) { | 93 | if (rm->idx++ < rm->dev->mc_count) { |
| 94 | addr = rm->list->dmi_addr; | 94 | addr = rm->list->dmi_addr; |
| @@ -190,7 +190,7 @@ struct sge; | |||
| 190 | struct peespi; | 190 | struct peespi; |
| 191 | 191 | ||
| 192 | struct adapter { | 192 | struct adapter { |
| 193 | u8 *regs; | 193 | u8 __iomem *regs; |
| 194 | struct pci_dev *pdev; | 194 | struct pci_dev *pdev; |
| 195 | unsigned long registered_device_map; | 195 | unsigned long registered_device_map; |
| 196 | unsigned long open_device_map; | 196 | unsigned long open_device_map; |
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 28ae478b386d..349ebe783ed6 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c | |||
| @@ -824,7 +824,7 @@ static void cxgb_proc_cleanup(struct adapter *adapter, | |||
| 824 | static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd) | 824 | static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd) |
| 825 | { | 825 | { |
| 826 | struct adapter *adapter = dev->priv; | 826 | struct adapter *adapter = dev->priv; |
| 827 | struct mii_ioctl_data *data = (struct mii_ioctl_data *)&req->ifr_data; | 827 | struct mii_ioctl_data *data = if_mii(req); |
| 828 | 828 | ||
| 829 | switch (cmd) { | 829 | switch (cmd) { |
| 830 | case SIOCGMIIPHY: | 830 | case SIOCGMIIPHY: |
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 93e9f8788751..51c2b3a18b6f 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h | |||
| @@ -1270,7 +1270,7 @@ struct e1000_hw_stats { | |||
| 1270 | 1270 | ||
| 1271 | /* Structure containing variables used by the shared code (e1000_hw.c) */ | 1271 | /* Structure containing variables used by the shared code (e1000_hw.c) */ |
| 1272 | struct e1000_hw { | 1272 | struct e1000_hw { |
| 1273 | uint8_t *hw_addr; | 1273 | uint8_t __iomem *hw_addr; |
| 1274 | uint8_t *flash_address; | 1274 | uint8_t *flash_address; |
| 1275 | e1000_mac_type mac_type; | 1275 | e1000_mac_type mac_type; |
| 1276 | e1000_phy_type phy_type; | 1276 | e1000_phy_type phy_type; |
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index fb6b232069d6..7c9dbc8c9423 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
| @@ -58,11 +58,10 @@ | |||
| 58 | 58 | ||
| 59 | #define INT_CAUSE_UNMASK_ALL 0x0007ffff | 59 | #define INT_CAUSE_UNMASK_ALL 0x0007ffff |
| 60 | #define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff | 60 | #define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff |
| 61 | #ifdef MV643XX_RX_QUEUE_FILL_ON_TASK | ||
| 62 | #define INT_CAUSE_MASK_ALL 0x00000000 | 61 | #define INT_CAUSE_MASK_ALL 0x00000000 |
| 62 | #define INT_CAUSE_MASK_ALL_EXT 0x00000000 | ||
| 63 | #define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL | 63 | #define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL |
| 64 | #define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT | 64 | #define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT |
| 65 | #endif | ||
| 66 | 65 | ||
| 67 | #ifdef MV643XX_CHECKSUM_OFFLOAD_TX | 66 | #ifdef MV643XX_CHECKSUM_OFFLOAD_TX |
| 68 | #define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1) | 67 | #define MAX_DESCS_PER_SKB (MAX_SKB_FRAGS + 1) |
| @@ -259,14 +258,13 @@ static void mv643xx_eth_update_mac_address(struct net_device *dev) | |||
| 259 | static void mv643xx_eth_set_rx_mode(struct net_device *dev) | 258 | static void mv643xx_eth_set_rx_mode(struct net_device *dev) |
| 260 | { | 259 | { |
| 261 | struct mv643xx_private *mp = netdev_priv(dev); | 260 | struct mv643xx_private *mp = netdev_priv(dev); |
| 262 | u32 config_reg; | ||
| 263 | 261 | ||
| 264 | config_reg = ethernet_get_config_reg(mp->port_num); | ||
| 265 | if (dev->flags & IFF_PROMISC) | 262 | if (dev->flags & IFF_PROMISC) |
| 266 | config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; | 263 | mp->port_config |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; |
| 267 | else | 264 | else |
| 268 | config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; | 265 | mp->port_config &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE; |
| 269 | ethernet_set_config_reg(mp->port_num, config_reg); | 266 | |
| 267 | mv_write(MV643XX_ETH_PORT_CONFIG_REG(mp->port_num), mp->port_config); | ||
| 270 | } | 268 | } |
| 271 | 269 | ||
| 272 | /* | 270 | /* |
| @@ -369,15 +367,6 @@ static int mv643xx_eth_free_tx_queue(struct net_device *dev, | |||
| 369 | 367 | ||
| 370 | dev_kfree_skb_irq(pkt_info.return_info); | 368 | dev_kfree_skb_irq(pkt_info.return_info); |
| 371 | released = 0; | 369 | released = 0; |
| 372 | |||
| 373 | /* | ||
| 374 | * Decrement the number of outstanding skbs counter on | ||
| 375 | * the TX queue. | ||
| 376 | */ | ||
| 377 | if (mp->tx_ring_skbs == 0) | ||
| 378 | panic("ERROR - TX outstanding SKBs" | ||
| 379 | " counter is corrupted"); | ||
| 380 | mp->tx_ring_skbs--; | ||
| 381 | } else | 370 | } else |
| 382 | dma_unmap_page(NULL, pkt_info.buf_ptr, | 371 | dma_unmap_page(NULL, pkt_info.buf_ptr, |
| 383 | pkt_info.byte_cnt, DMA_TO_DEVICE); | 372 | pkt_info.byte_cnt, DMA_TO_DEVICE); |
| @@ -412,15 +401,13 @@ static int mv643xx_eth_receive_queue(struct net_device *dev) | |||
| 412 | struct pkt_info pkt_info; | 401 | struct pkt_info pkt_info; |
| 413 | 402 | ||
| 414 | #ifdef MV643XX_NAPI | 403 | #ifdef MV643XX_NAPI |
| 415 | while (eth_port_receive(mp, &pkt_info) == ETH_OK && budget > 0) { | 404 | while (budget-- > 0 && eth_port_receive(mp, &pkt_info) == ETH_OK) { |
| 416 | #else | 405 | #else |
| 417 | while (eth_port_receive(mp, &pkt_info) == ETH_OK) { | 406 | while (eth_port_receive(mp, &pkt_info) == ETH_OK) { |
| 418 | #endif | 407 | #endif |
| 419 | mp->rx_ring_skbs--; | 408 | mp->rx_ring_skbs--; |
| 420 | received_packets++; | 409 | received_packets++; |
| 421 | #ifdef MV643XX_NAPI | 410 | |
| 422 | budget--; | ||
| 423 | #endif | ||
| 424 | /* Update statistics. Note byte count includes 4 byte CRC count */ | 411 | /* Update statistics. Note byte count includes 4 byte CRC count */ |
| 425 | stats->rx_packets++; | 412 | stats->rx_packets++; |
| 426 | stats->rx_bytes += pkt_info.byte_cnt; | 413 | stats->rx_bytes += pkt_info.byte_cnt; |
| @@ -1044,9 +1031,6 @@ static void mv643xx_tx(struct net_device *dev) | |||
| 1044 | DMA_TO_DEVICE); | 1031 | DMA_TO_DEVICE); |
| 1045 | 1032 | ||
| 1046 | dev_kfree_skb_irq(pkt_info.return_info); | 1033 | dev_kfree_skb_irq(pkt_info.return_info); |
| 1047 | |||
| 1048 | if (mp->tx_ring_skbs) | ||
| 1049 | mp->tx_ring_skbs--; | ||
| 1050 | } else | 1034 | } else |
| 1051 | dma_unmap_page(NULL, pkt_info.buf_ptr, | 1035 | dma_unmap_page(NULL, pkt_info.buf_ptr, |
| 1052 | pkt_info.byte_cnt, DMA_TO_DEVICE); | 1036 | pkt_info.byte_cnt, DMA_TO_DEVICE); |
| @@ -1189,7 +1173,6 @@ linear: | |||
| 1189 | pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len, | 1173 | pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len, |
| 1190 | DMA_TO_DEVICE); | 1174 | DMA_TO_DEVICE); |
| 1191 | pkt_info.return_info = skb; | 1175 | pkt_info.return_info = skb; |
| 1192 | mp->tx_ring_skbs++; | ||
| 1193 | status = eth_port_send(mp, &pkt_info); | 1176 | status = eth_port_send(mp, &pkt_info); |
| 1194 | if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) | 1177 | if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) |
| 1195 | printk(KERN_ERR "%s: Error on transmitting packet\n", | 1178 | printk(KERN_ERR "%s: Error on transmitting packet\n", |
| @@ -1274,7 +1257,6 @@ linear: | |||
| 1274 | pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT | | 1257 | pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT | |
| 1275 | ETH_TX_LAST_DESC; | 1258 | ETH_TX_LAST_DESC; |
| 1276 | pkt_info.return_info = skb; | 1259 | pkt_info.return_info = skb; |
| 1277 | mp->tx_ring_skbs++; | ||
| 1278 | } else { | 1260 | } else { |
| 1279 | pkt_info.return_info = 0; | 1261 | pkt_info.return_info = 0; |
| 1280 | } | 1262 | } |
| @@ -1311,7 +1293,6 @@ linear: | |||
| 1311 | pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len, | 1293 | pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len, |
| 1312 | DMA_TO_DEVICE); | 1294 | DMA_TO_DEVICE); |
| 1313 | pkt_info.return_info = skb; | 1295 | pkt_info.return_info = skb; |
| 1314 | mp->tx_ring_skbs++; | ||
| 1315 | status = eth_port_send(mp, &pkt_info); | 1296 | status = eth_port_send(mp, &pkt_info); |
| 1316 | if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) | 1297 | if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) |
| 1317 | printk(KERN_ERR "%s: Error on transmitting packet\n", | 1298 | printk(KERN_ERR "%s: Error on transmitting packet\n", |
| @@ -1356,6 +1337,43 @@ static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev) | |||
| 1356 | return &mp->stats; | 1337 | return &mp->stats; |
| 1357 | } | 1338 | } |
| 1358 | 1339 | ||
| 1340 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 1341 | static inline void mv643xx_enable_irq(struct mv643xx_private *mp) | ||
| 1342 | { | ||
| 1343 | int port_num = mp->port_num; | ||
| 1344 | unsigned long flags; | ||
| 1345 | |||
| 1346 | spin_lock_irqsave(&mp->lock, flags); | ||
| 1347 | mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), | ||
| 1348 | INT_CAUSE_UNMASK_ALL); | ||
| 1349 | mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), | ||
| 1350 | INT_CAUSE_UNMASK_ALL_EXT); | ||
| 1351 | spin_unlock_irqrestore(&mp->lock, flags); | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | static inline void mv643xx_disable_irq(struct mv643xx_private *mp) | ||
| 1355 | { | ||
| 1356 | int port_num = mp->port_num; | ||
| 1357 | unsigned long flags; | ||
| 1358 | |||
| 1359 | spin_lock_irqsave(&mp->lock, flags); | ||
| 1360 | mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), | ||
| 1361 | INT_CAUSE_MASK_ALL); | ||
| 1362 | mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), | ||
| 1363 | INT_CAUSE_MASK_ALL_EXT); | ||
| 1364 | spin_unlock_irqrestore(&mp->lock, flags); | ||
| 1365 | } | ||
| 1366 | |||
| 1367 | static void mv643xx_netpoll(struct net_device *netdev) | ||
| 1368 | { | ||
| 1369 | struct mv643xx_private *mp = netdev_priv(netdev); | ||
| 1370 | |||
| 1371 | mv643xx_disable_irq(mp); | ||
| 1372 | mv643xx_eth_int_handler(netdev->irq, netdev, NULL); | ||
| 1373 | mv643xx_enable_irq(mp); | ||
| 1374 | } | ||
| 1375 | #endif | ||
| 1376 | |||
| 1359 | /*/ | 1377 | /*/ |
| 1360 | * mv643xx_eth_probe | 1378 | * mv643xx_eth_probe |
| 1361 | * | 1379 | * |
| @@ -1406,6 +1424,10 @@ static int mv643xx_eth_probe(struct device *ddev) | |||
| 1406 | dev->weight = 64; | 1424 | dev->weight = 64; |
| 1407 | #endif | 1425 | #endif |
| 1408 | 1426 | ||
| 1427 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 1428 | dev->poll_controller = mv643xx_netpoll; | ||
| 1429 | #endif | ||
| 1430 | |||
| 1409 | dev->watchdog_timeo = 2 * HZ; | 1431 | dev->watchdog_timeo = 2 * HZ; |
| 1410 | dev->tx_queue_len = mp->tx_ring_size; | 1432 | dev->tx_queue_len = mp->tx_ring_size; |
| 1411 | dev->base_addr = 0; | 1433 | dev->base_addr = 0; |
| @@ -1883,6 +1905,9 @@ static void eth_port_start(struct mv643xx_private *mp) | |||
| 1883 | /* Enable port Rx. */ | 1905 | /* Enable port Rx. */ |
| 1884 | mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), | 1906 | mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), |
| 1885 | mp->port_rx_queue_command); | 1907 | mp->port_rx_queue_command); |
| 1908 | |||
| 1909 | /* Disable port bandwidth limits by clearing MTU register */ | ||
| 1910 | mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0); | ||
| 1886 | } | 1911 | } |
| 1887 | 1912 | ||
| 1888 | /* | 1913 | /* |
| @@ -2292,34 +2317,6 @@ static void eth_port_reset(unsigned int port_num) | |||
| 2292 | mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data); | 2317 | mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data); |
| 2293 | } | 2318 | } |
| 2294 | 2319 | ||
| 2295 | /* | ||
| 2296 | * ethernet_set_config_reg - Set specified bits in configuration register. | ||
| 2297 | * | ||
| 2298 | * DESCRIPTION: | ||
| 2299 | * This function sets specified bits in the given ethernet | ||
| 2300 | * configuration register. | ||
| 2301 | * | ||
| 2302 | * INPUT: | ||
| 2303 | * unsigned int eth_port_num Ethernet Port number. | ||
| 2304 | * unsigned int value 32 bit value. | ||
| 2305 | * | ||
| 2306 | * OUTPUT: | ||
| 2307 | * The set bits in the value parameter are set in the configuration | ||
| 2308 | * register. | ||
| 2309 | * | ||
| 2310 | * RETURN: | ||
| 2311 | * None. | ||
| 2312 | * | ||
| 2313 | */ | ||
| 2314 | static void ethernet_set_config_reg(unsigned int eth_port_num, | ||
| 2315 | unsigned int value) | ||
| 2316 | { | ||
| 2317 | unsigned int eth_config_reg; | ||
| 2318 | |||
| 2319 | eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num)); | ||
| 2320 | eth_config_reg |= value; | ||
| 2321 | mv_write(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num), eth_config_reg); | ||
| 2322 | } | ||
| 2323 | 2320 | ||
| 2324 | static int eth_port_autoneg_supported(unsigned int eth_port_num) | 2321 | static int eth_port_autoneg_supported(unsigned int eth_port_num) |
| 2325 | { | 2322 | { |
| @@ -2346,31 +2343,6 @@ static int eth_port_link_is_up(unsigned int eth_port_num) | |||
| 2346 | } | 2343 | } |
| 2347 | 2344 | ||
| 2348 | /* | 2345 | /* |
| 2349 | * ethernet_get_config_reg - Get the port configuration register | ||
| 2350 | * | ||
| 2351 | * DESCRIPTION: | ||
| 2352 | * This function returns the configuration register value of the given | ||
| 2353 | * ethernet port. | ||
| 2354 | * | ||
| 2355 | * INPUT: | ||
| 2356 | * unsigned int eth_port_num Ethernet Port number. | ||
| 2357 | * | ||
| 2358 | * OUTPUT: | ||
| 2359 | * None. | ||
| 2360 | * | ||
| 2361 | * RETURN: | ||
| 2362 | * Port configuration register value. | ||
| 2363 | */ | ||
| 2364 | static unsigned int ethernet_get_config_reg(unsigned int eth_port_num) | ||
| 2365 | { | ||
| 2366 | unsigned int eth_config_reg; | ||
| 2367 | |||
| 2368 | eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_EXTEND_REG | ||
| 2369 | (eth_port_num)); | ||
| 2370 | return eth_config_reg; | ||
| 2371 | } | ||
| 2372 | |||
| 2373 | /* | ||
| 2374 | * eth_port_read_smi_reg - Read PHY registers | 2346 | * eth_port_read_smi_reg - Read PHY registers |
| 2375 | * | 2347 | * |
| 2376 | * DESCRIPTION: | 2348 | * DESCRIPTION: |
| @@ -2528,6 +2500,9 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, | |||
| 2528 | return ETH_ERROR; | 2500 | return ETH_ERROR; |
| 2529 | } | 2501 | } |
| 2530 | 2502 | ||
| 2503 | mp->tx_ring_skbs++; | ||
| 2504 | BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); | ||
| 2505 | |||
| 2531 | /* Get the Tx Desc ring indexes */ | 2506 | /* Get the Tx Desc ring indexes */ |
| 2532 | tx_desc_curr = mp->tx_curr_desc_q; | 2507 | tx_desc_curr = mp->tx_curr_desc_q; |
| 2533 | tx_desc_used = mp->tx_used_desc_q; | 2508 | tx_desc_used = mp->tx_used_desc_q; |
| @@ -2594,6 +2569,9 @@ static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp, | |||
| 2594 | if (mp->tx_resource_err) | 2569 | if (mp->tx_resource_err) |
| 2595 | return ETH_QUEUE_FULL; | 2570 | return ETH_QUEUE_FULL; |
| 2596 | 2571 | ||
| 2572 | mp->tx_ring_skbs++; | ||
| 2573 | BUG_ON(mp->tx_ring_skbs > mp->tx_ring_size); | ||
| 2574 | |||
| 2597 | /* Get the Tx Desc ring indexes */ | 2575 | /* Get the Tx Desc ring indexes */ |
| 2598 | tx_desc_curr = mp->tx_curr_desc_q; | 2576 | tx_desc_curr = mp->tx_curr_desc_q; |
| 2599 | tx_desc_used = mp->tx_used_desc_q; | 2577 | tx_desc_used = mp->tx_used_desc_q; |
| @@ -2694,6 +2672,9 @@ static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp, | |||
| 2694 | /* Any Tx return cancels the Tx resource error status */ | 2672 | /* Any Tx return cancels the Tx resource error status */ |
| 2695 | mp->tx_resource_err = 0; | 2673 | mp->tx_resource_err = 0; |
| 2696 | 2674 | ||
| 2675 | BUG_ON(mp->tx_ring_skbs == 0); | ||
| 2676 | mp->tx_ring_skbs--; | ||
| 2677 | |||
| 2697 | return ETH_OK; | 2678 | return ETH_OK; |
| 2698 | } | 2679 | } |
| 2699 | 2680 | ||
diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index 7678b59c2952..bcfda5192da0 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h | |||
| @@ -408,10 +408,6 @@ static void eth_port_init(struct mv643xx_private *mp); | |||
| 408 | static void eth_port_reset(unsigned int eth_port_num); | 408 | static void eth_port_reset(unsigned int eth_port_num); |
| 409 | static void eth_port_start(struct mv643xx_private *mp); | 409 | static void eth_port_start(struct mv643xx_private *mp); |
| 410 | 410 | ||
| 411 | static void ethernet_set_config_reg(unsigned int eth_port_num, | ||
| 412 | unsigned int value); | ||
| 413 | static unsigned int ethernet_get_config_reg(unsigned int eth_port_num); | ||
| 414 | |||
| 415 | /* Port MAC address routines */ | 411 | /* Port MAC address routines */ |
| 416 | static void eth_port_uc_addr_set(unsigned int eth_port_num, | 412 | static void eth_port_uc_addr_set(unsigned int eth_port_num, |
| 417 | unsigned char *p_addr); | 413 | unsigned char *p_addr); |
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c index 6c92f0969015..73501d846588 100644 --- a/drivers/net/ne3210.c +++ b/drivers/net/ne3210.c | |||
| @@ -26,9 +26,6 @@ | |||
| 26 | Updated to EISA probing API 5/2003 by Marc Zyngier. | 26 | Updated to EISA probing API 5/2003 by Marc Zyngier. |
| 27 | */ | 27 | */ |
| 28 | 28 | ||
| 29 | static const char *version = | ||
| 30 | "ne3210.c: Driver revision v0.03, 30/09/98\n"; | ||
| 31 | |||
| 32 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 33 | #include <linux/eisa.h> | 30 | #include <linux/eisa.h> |
| 34 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
| @@ -197,7 +194,7 @@ static int __init ne3210_eisa_probe (struct device *device) | |||
| 197 | ei_status.priv = phys_mem; | 194 | ei_status.priv = phys_mem; |
| 198 | 195 | ||
| 199 | if (ei_debug > 0) | 196 | if (ei_debug > 0) |
| 200 | printk(version); | 197 | printk("ne3210 loaded.\n"); |
| 201 | 198 | ||
| 202 | ei_status.reset_8390 = &ne3210_reset_8390; | 199 | ei_status.reset_8390 = &ne3210_reset_8390; |
| 203 | ei_status.block_input = &ne3210_block_input; | 200 | ei_status.block_input = &ne3210_block_input; |
| @@ -360,12 +357,12 @@ MODULE_DESCRIPTION("NE3210 EISA Ethernet driver"); | |||
| 360 | MODULE_LICENSE("GPL"); | 357 | MODULE_LICENSE("GPL"); |
| 361 | MODULE_DEVICE_TABLE(eisa, ne3210_ids); | 358 | MODULE_DEVICE_TABLE(eisa, ne3210_ids); |
| 362 | 359 | ||
| 363 | int ne3210_init(void) | 360 | static int ne3210_init(void) |
| 364 | { | 361 | { |
| 365 | return eisa_driver_register (&ne3210_eisa_driver); | 362 | return eisa_driver_register (&ne3210_eisa_driver); |
| 366 | } | 363 | } |
| 367 | 364 | ||
| 368 | void ne3210_cleanup(void) | 365 | static void ne3210_cleanup(void) |
| 369 | { | 366 | { |
| 370 | eisa_driver_unregister (&ne3210_eisa_driver); | 367 | eisa_driver_unregister (&ne3210_eisa_driver); |
| 371 | } | 368 | } |
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 6a2fe3583478..14f4de1a8180 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig | |||
| @@ -6,7 +6,7 @@ menu "PHY device support" | |||
| 6 | 6 | ||
| 7 | config PHYLIB | 7 | config PHYLIB |
| 8 | tristate "PHY Device support and infrastructure" | 8 | tristate "PHY Device support and infrastructure" |
| 9 | depends on NET_ETHERNET | 9 | depends on NET_ETHERNET && (BROKEN || !ARCH_S390) |
| 10 | help | 10 | help |
| 11 | Ethernet controllers are usually attached to PHY | 11 | Ethernet controllers are usually attached to PHY |
| 12 | devices. This option provides infrastructure for | 12 | devices. This option provides infrastructure for |
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 5e81494e9a9a..90630672703d 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
| @@ -170,7 +170,7 @@ int __init mdio_bus_init(void) | |||
| 170 | return bus_register(&mdio_bus_type); | 170 | return bus_register(&mdio_bus_type); |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | void __exit mdio_bus_exit(void) | 173 | void mdio_bus_exit(void) |
| 174 | { | 174 | { |
| 175 | bus_unregister(&mdio_bus_type); | 175 | bus_unregister(&mdio_bus_type); |
| 176 | } | 176 | } |
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 7ca78228b104..5dda043bd9d7 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
| @@ -686,7 +686,7 @@ static void free_shared_mem(struct s2io_nic *nic) | |||
| 686 | 686 | ||
| 687 | static int s2io_verify_pci_mode(nic_t *nic) | 687 | static int s2io_verify_pci_mode(nic_t *nic) |
| 688 | { | 688 | { |
| 689 | XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; | 689 | XENA_dev_config_t __iomem *bar0 = nic->bar0; |
| 690 | register u64 val64 = 0; | 690 | register u64 val64 = 0; |
| 691 | int mode; | 691 | int mode; |
| 692 | 692 | ||
| @@ -704,7 +704,7 @@ static int s2io_verify_pci_mode(nic_t *nic) | |||
| 704 | */ | 704 | */ |
| 705 | static int s2io_print_pci_mode(nic_t *nic) | 705 | static int s2io_print_pci_mode(nic_t *nic) |
| 706 | { | 706 | { |
| 707 | XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; | 707 | XENA_dev_config_t __iomem *bar0 = nic->bar0; |
| 708 | register u64 val64 = 0; | 708 | register u64 val64 = 0; |
| 709 | int mode; | 709 | int mode; |
| 710 | struct config_param *config = &nic->config; | 710 | struct config_param *config = &nic->config; |
| @@ -1403,7 +1403,7 @@ static int init_nic(struct s2io_nic *nic) | |||
| 1403 | writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q4q7); | 1403 | writeq(0xffbbffbbffbbffbbULL, &bar0->mc_pause_thresh_q4q7); |
| 1404 | 1404 | ||
| 1405 | /* Disable RMAC PAD STRIPPING */ | 1405 | /* Disable RMAC PAD STRIPPING */ |
| 1406 | add = (void *) &bar0->mac_cfg; | 1406 | add = &bar0->mac_cfg; |
| 1407 | val64 = readq(&bar0->mac_cfg); | 1407 | val64 = readq(&bar0->mac_cfg); |
| 1408 | val64 &= ~(MAC_CFG_RMAC_STRIP_PAD); | 1408 | val64 &= ~(MAC_CFG_RMAC_STRIP_PAD); |
| 1409 | writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); | 1409 | writeq(RMAC_CFG_KEY(0x4C0D), &bar0->rmac_cfg_key); |
| @@ -1934,7 +1934,7 @@ static int start_nic(struct s2io_nic *nic) | |||
| 1934 | val64 |= 0x0000800000000000ULL; | 1934 | val64 |= 0x0000800000000000ULL; |
| 1935 | writeq(val64, &bar0->gpio_control); | 1935 | writeq(val64, &bar0->gpio_control); |
| 1936 | val64 = 0x0411040400000000ULL; | 1936 | val64 = 0x0411040400000000ULL; |
| 1937 | writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700)); | 1937 | writeq(val64, (void __iomem *)bar0 + 0x2700); |
| 1938 | } | 1938 | } |
| 1939 | 1939 | ||
| 1940 | /* | 1940 | /* |
| @@ -2395,7 +2395,7 @@ static int s2io_poll(struct net_device *dev, int *budget) | |||
| 2395 | int pkt_cnt = 0, org_pkts_to_process; | 2395 | int pkt_cnt = 0, org_pkts_to_process; |
| 2396 | mac_info_t *mac_control; | 2396 | mac_info_t *mac_control; |
| 2397 | struct config_param *config; | 2397 | struct config_param *config; |
| 2398 | XENA_dev_config_t *bar0 = (XENA_dev_config_t *) nic->bar0; | 2398 | XENA_dev_config_t __iomem *bar0 = nic->bar0; |
| 2399 | u64 val64; | 2399 | u64 val64; |
| 2400 | int i; | 2400 | int i; |
| 2401 | 2401 | ||
| @@ -2831,7 +2831,7 @@ void s2io_reset(nic_t * sp) | |||
| 2831 | val64 |= 0x0000800000000000ULL; | 2831 | val64 |= 0x0000800000000000ULL; |
| 2832 | writeq(val64, &bar0->gpio_control); | 2832 | writeq(val64, &bar0->gpio_control); |
| 2833 | val64 = 0x0411040400000000ULL; | 2833 | val64 = 0x0411040400000000ULL; |
| 2834 | writeq(val64, (void __iomem *) ((u8 *) bar0 + 0x2700)); | 2834 | writeq(val64, (void __iomem *)bar0 + 0x2700); |
| 2835 | } | 2835 | } |
| 2836 | 2836 | ||
| 2837 | /* | 2837 | /* |
| @@ -3234,7 +3234,7 @@ s2io_alarm_handle(unsigned long data) | |||
| 3234 | 3234 | ||
| 3235 | static void s2io_txpic_intr_handle(nic_t *sp) | 3235 | static void s2io_txpic_intr_handle(nic_t *sp) |
| 3236 | { | 3236 | { |
| 3237 | XENA_dev_config_t *bar0 = (XENA_dev_config_t *) sp->bar0; | 3237 | XENA_dev_config_t __iomem *bar0 = sp->bar0; |
| 3238 | u64 val64; | 3238 | u64 val64; |
| 3239 | 3239 | ||
| 3240 | val64 = readq(&bar0->pic_int_status); | 3240 | val64 = readq(&bar0->pic_int_status); |
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c index bf3440aa6c24..92f75529eff8 100644 --- a/drivers/net/sis190.c +++ b/drivers/net/sis190.c | |||
| @@ -179,14 +179,6 @@ enum sis190_register_content { | |||
| 179 | TxInterFrameGapShift = 24, | 179 | TxInterFrameGapShift = 24, |
| 180 | TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ | 180 | TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ |
| 181 | 181 | ||
| 182 | /* StationControl */ | ||
| 183 | _1000bpsF = 0x1c00, | ||
| 184 | _1000bpsH = 0x0c00, | ||
| 185 | _100bpsF = 0x1800, | ||
| 186 | _100bpsH = 0x0800, | ||
| 187 | _10bpsF = 0x1400, | ||
| 188 | _10bpsH = 0x0400, | ||
| 189 | |||
| 190 | LinkStatus = 0x02, // unused | 182 | LinkStatus = 0x02, // unused |
| 191 | FullDup = 0x01, // unused | 183 | FullDup = 0x01, // unused |
| 192 | 184 | ||
| @@ -279,6 +271,12 @@ enum sis190_eeprom_address { | |||
| 279 | EEPROMMACAddr = 0x03 | 271 | EEPROMMACAddr = 0x03 |
| 280 | }; | 272 | }; |
| 281 | 273 | ||
| 274 | enum sis190_feature { | ||
| 275 | F_HAS_RGMII = 1, | ||
| 276 | F_PHY_88E1111 = 2, | ||
| 277 | F_PHY_BCM5461 = 4 | ||
| 278 | }; | ||
| 279 | |||
| 282 | struct sis190_private { | 280 | struct sis190_private { |
| 283 | void __iomem *mmio_addr; | 281 | void __iomem *mmio_addr; |
| 284 | struct pci_dev *pci_dev; | 282 | struct pci_dev *pci_dev; |
| @@ -300,6 +298,7 @@ struct sis190_private { | |||
| 300 | u32 msg_enable; | 298 | u32 msg_enable; |
| 301 | struct mii_if_info mii_if; | 299 | struct mii_if_info mii_if; |
| 302 | struct list_head first_phy; | 300 | struct list_head first_phy; |
| 301 | u32 features; | ||
| 303 | }; | 302 | }; |
| 304 | 303 | ||
| 305 | struct sis190_phy { | 304 | struct sis190_phy { |
| @@ -321,24 +320,25 @@ static struct mii_chip_info { | |||
| 321 | const char *name; | 320 | const char *name; |
| 322 | u16 id[2]; | 321 | u16 id[2]; |
| 323 | unsigned int type; | 322 | unsigned int type; |
| 323 | u32 feature; | ||
| 324 | } mii_chip_table[] = { | 324 | } mii_chip_table[] = { |
| 325 | { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN }, | 325 | { "Broadcom PHY BCM5461", { 0x0020, 0x60c0 }, LAN, F_PHY_BCM5461 }, |
| 326 | { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN }, | 326 | { "Agere PHY ET1101B", { 0x0282, 0xf010 }, LAN, 0 }, |
| 327 | { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN }, | 327 | { "Marvell PHY 88E1111", { 0x0141, 0x0cc0 }, LAN, F_PHY_88E1111 }, |
| 328 | { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN }, | 328 | { "Realtek PHY RTL8201", { 0x0000, 0x8200 }, LAN, 0 }, |
| 329 | { NULL, } | 329 | { NULL, } |
| 330 | }; | 330 | }; |
| 331 | 331 | ||
| 332 | const static struct { | 332 | const static struct { |
| 333 | const char *name; | 333 | const char *name; |
| 334 | u8 version; /* depend on docs */ | ||
| 335 | u32 RxConfigMask; /* clear the bits supported by this chip */ | ||
| 336 | } sis_chip_info[] = { | 334 | } sis_chip_info[] = { |
| 337 | { DRV_NAME, 0x00, 0xff7e1880, }, | 335 | { "SiS 190 PCI Fast Ethernet adapter" }, |
| 336 | { "SiS 191 PCI Gigabit Ethernet adapter" }, | ||
| 338 | }; | 337 | }; |
| 339 | 338 | ||
| 340 | static struct pci_device_id sis190_pci_tbl[] __devinitdata = { | 339 | static struct pci_device_id sis190_pci_tbl[] __devinitdata = { |
| 341 | { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 }, | 340 | { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 }, |
| 341 | { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 }, | ||
| 342 | { 0, }, | 342 | { 0, }, |
| 343 | }; | 343 | }; |
| 344 | 344 | ||
| @@ -360,7 +360,7 @@ MODULE_VERSION(DRV_VERSION); | |||
| 360 | MODULE_LICENSE("GPL"); | 360 | MODULE_LICENSE("GPL"); |
| 361 | 361 | ||
| 362 | static const u32 sis190_intr_mask = | 362 | static const u32 sis190_intr_mask = |
| 363 | RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt; | 363 | RxQEmpty | RxQInt | TxQ1Int | TxQ0Int | RxHalt | TxHalt | LinkChange; |
| 364 | 364 | ||
| 365 | /* | 365 | /* |
| 366 | * Maximum number of multicast addresses to filter (vs. Rx-all-multicast). | 366 | * Maximum number of multicast addresses to filter (vs. Rx-all-multicast). |
| @@ -879,11 +879,6 @@ static void sis190_hw_start(struct net_device *dev) | |||
| 879 | 879 | ||
| 880 | SIS_W32(IntrStatus, 0xffffffff); | 880 | SIS_W32(IntrStatus, 0xffffffff); |
| 881 | SIS_W32(IntrMask, 0x0); | 881 | SIS_W32(IntrMask, 0x0); |
| 882 | /* | ||
| 883 | * Default is 100Mbps. | ||
| 884 | * A bit strange: 100Mbps is 0x1801 elsewhere -- FR 2005/06/09 | ||
| 885 | */ | ||
| 886 | SIS_W16(StationControl, 0x1901); | ||
| 887 | SIS_W32(GMIIControl, 0x0); | 882 | SIS_W32(GMIIControl, 0x0); |
| 888 | SIS_W32(TxMacControl, 0x60); | 883 | SIS_W32(TxMacControl, 0x60); |
| 889 | SIS_W16(RxMacControl, 0x02); | 884 | SIS_W16(RxMacControl, 0x02); |
| @@ -923,35 +918,30 @@ static void sis190_phy_task(void * data) | |||
| 923 | BMSR_ANEGCOMPLETE)) { | 918 | BMSR_ANEGCOMPLETE)) { |
| 924 | net_link(tp, KERN_WARNING "%s: PHY reset until link up.\n", | 919 | net_link(tp, KERN_WARNING "%s: PHY reset until link up.\n", |
| 925 | dev->name); | 920 | dev->name); |
| 921 | netif_carrier_off(dev); | ||
| 926 | mdio_write(ioaddr, phy_id, MII_BMCR, val | BMCR_RESET); | 922 | mdio_write(ioaddr, phy_id, MII_BMCR, val | BMCR_RESET); |
| 927 | mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT); | 923 | mod_timer(&tp->timer, jiffies + SIS190_PHY_TIMEOUT); |
| 928 | } else { | 924 | } else { |
| 929 | /* Rejoice ! */ | 925 | /* Rejoice ! */ |
| 930 | struct { | 926 | struct { |
| 931 | int val; | 927 | int val; |
| 928 | u32 ctl; | ||
| 932 | const char *msg; | 929 | const char *msg; |
| 933 | u16 ctl; | ||
| 934 | } reg31[] = { | 930 | } reg31[] = { |
| 935 | { LPA_1000XFULL | LPA_SLCT, | 931 | { LPA_1000XFULL | LPA_SLCT, 0x07000c00 | 0x00001000, |
| 936 | "1000 Mbps Full Duplex", | 932 | "1000 Mbps Full Duplex" }, |
| 937 | 0x01 | _1000bpsF }, | 933 | { LPA_1000XHALF | LPA_SLCT, 0x07000c00, |
| 938 | { LPA_1000XHALF | LPA_SLCT, | 934 | "1000 Mbps Half Duplex" }, |
| 939 | "1000 Mbps Half Duplex", | 935 | { LPA_100FULL, 0x04000800 | 0x00001000, |
| 940 | 0x01 | _1000bpsH }, | 936 | "100 Mbps Full Duplex" }, |
| 941 | { LPA_100FULL, | 937 | { LPA_100HALF, 0x04000800, |
| 942 | "100 Mbps Full Duplex", | 938 | "100 Mbps Half Duplex" }, |
| 943 | 0x01 | _100bpsF }, | 939 | { LPA_10FULL, 0x04000400 | 0x00001000, |
| 944 | { LPA_100HALF, | 940 | "10 Mbps Full Duplex" }, |
| 945 | "100 Mbps Half Duplex", | 941 | { LPA_10HALF, 0x04000400, |
| 946 | 0x01 | _100bpsH }, | 942 | "10 Mbps Half Duplex" }, |
| 947 | { LPA_10FULL, | 943 | { 0, 0x04000400, "unknown" } |
| 948 | "10 Mbps Full Duplex", | 944 | }, *p; |
| 949 | 0x01 | _10bpsF }, | ||
| 950 | { LPA_10HALF, | ||
| 951 | "10 Mbps Half Duplex", | ||
| 952 | 0x01 | _10bpsH }, | ||
| 953 | { 0, "unknown", 0x0000 } | ||
| 954 | }, *p; | ||
| 955 | u16 adv; | 945 | u16 adv; |
| 956 | 946 | ||
| 957 | val = mdio_read(ioaddr, phy_id, 0x1f); | 947 | val = mdio_read(ioaddr, phy_id, 0x1f); |
| @@ -964,12 +954,29 @@ static void sis190_phy_task(void * data) | |||
| 964 | 954 | ||
| 965 | val &= adv; | 955 | val &= adv; |
| 966 | 956 | ||
| 967 | for (p = reg31; p->ctl; p++) { | 957 | for (p = reg31; p->val; p++) { |
| 968 | if ((val & p->val) == p->val) | 958 | if ((val & p->val) == p->val) |
| 969 | break; | 959 | break; |
| 970 | } | 960 | } |
| 971 | if (p->ctl) | 961 | |
| 972 | SIS_W16(StationControl, p->ctl); | 962 | p->ctl |= SIS_R32(StationControl) & ~0x0f001c00; |
| 963 | |||
| 964 | if ((tp->features & F_HAS_RGMII) && | ||
| 965 | (tp->features & F_PHY_BCM5461)) { | ||
| 966 | // Set Tx Delay in RGMII mode. | ||
| 967 | mdio_write(ioaddr, phy_id, 0x18, 0xf1c7); | ||
| 968 | udelay(200); | ||
| 969 | mdio_write(ioaddr, phy_id, 0x1c, 0x8c00); | ||
| 970 | p->ctl |= 0x03000000; | ||
| 971 | } | ||
| 972 | |||
| 973 | SIS_W32(StationControl, p->ctl); | ||
| 974 | |||
| 975 | if (tp->features & F_HAS_RGMII) { | ||
| 976 | SIS_W32(RGDelay, 0x0441); | ||
| 977 | SIS_W32(RGDelay, 0x0440); | ||
| 978 | } | ||
| 979 | |||
| 973 | net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name, | 980 | net_link(tp, KERN_INFO "%s: link on %s mode.\n", dev->name, |
| 974 | p->msg); | 981 | p->msg); |
| 975 | netif_carrier_on(dev); | 982 | netif_carrier_on(dev); |
| @@ -1308,6 +1315,7 @@ static void sis190_init_phy(struct net_device *dev, struct sis190_private *tp, | |||
| 1308 | phy->type = (p->type == MIX) ? | 1315 | phy->type = (p->type == MIX) ? |
| 1309 | ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ? | 1316 | ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ? |
| 1310 | LAN : HOME) : p->type; | 1317 | LAN : HOME) : p->type; |
| 1318 | tp->features |= p->feature; | ||
| 1311 | } else | 1319 | } else |
| 1312 | phy->type = UNKNOWN; | 1320 | phy->type = UNKNOWN; |
| 1313 | 1321 | ||
| @@ -1316,6 +1324,25 @@ static void sis190_init_phy(struct net_device *dev, struct sis190_private *tp, | |||
| 1316 | (phy->type == UNKNOWN) ? "Unknown PHY" : p->name, phy_id); | 1324 | (phy->type == UNKNOWN) ? "Unknown PHY" : p->name, phy_id); |
| 1317 | } | 1325 | } |
| 1318 | 1326 | ||
| 1327 | static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp) | ||
| 1328 | { | ||
| 1329 | if (tp->features & F_PHY_88E1111) { | ||
| 1330 | void __iomem *ioaddr = tp->mmio_addr; | ||
| 1331 | int phy_id = tp->mii_if.phy_id; | ||
| 1332 | u16 reg[2][2] = { | ||
| 1333 | { 0x808b, 0x0ce1 }, | ||
| 1334 | { 0x808f, 0x0c60 } | ||
| 1335 | }, *p; | ||
| 1336 | |||
| 1337 | p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1]; | ||
| 1338 | |||
| 1339 | mdio_write(ioaddr, phy_id, 0x1b, p[0]); | ||
| 1340 | udelay(200); | ||
| 1341 | mdio_write(ioaddr, phy_id, 0x14, p[1]); | ||
| 1342 | udelay(200); | ||
| 1343 | } | ||
| 1344 | } | ||
| 1345 | |||
| 1319 | /** | 1346 | /** |
| 1320 | * sis190_mii_probe - Probe MII PHY for sis190 | 1347 | * sis190_mii_probe - Probe MII PHY for sis190 |
| 1321 | * @dev: the net device to probe for | 1348 | * @dev: the net device to probe for |
| @@ -1366,6 +1393,8 @@ static int __devinit sis190_mii_probe(struct net_device *dev) | |||
| 1366 | /* Select default PHY for mac */ | 1393 | /* Select default PHY for mac */ |
| 1367 | sis190_default_phy(dev); | 1394 | sis190_default_phy(dev); |
| 1368 | 1395 | ||
| 1396 | sis190_mii_probe_88e1111_fixup(tp); | ||
| 1397 | |||
| 1369 | mii_if->dev = dev; | 1398 | mii_if->dev = dev; |
| 1370 | mii_if->mdio_read = __mdio_read; | 1399 | mii_if->mdio_read = __mdio_read; |
| 1371 | mii_if->mdio_write = __mdio_write; | 1400 | mii_if->mdio_write = __mdio_write; |
| @@ -1505,6 +1534,11 @@ static void sis190_tx_timeout(struct net_device *dev) | |||
| 1505 | netif_wake_queue(dev); | 1534 | netif_wake_queue(dev); |
| 1506 | } | 1535 | } |
| 1507 | 1536 | ||
| 1537 | static void sis190_set_rgmii(struct sis190_private *tp, u8 reg) | ||
| 1538 | { | ||
| 1539 | tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0; | ||
| 1540 | } | ||
| 1541 | |||
| 1508 | static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, | 1542 | static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, |
| 1509 | struct net_device *dev) | 1543 | struct net_device *dev) |
| 1510 | { | 1544 | { |
| @@ -1532,6 +1566,8 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev, | |||
| 1532 | ((u16 *)dev->dev_addr)[0] = le16_to_cpu(w); | 1566 | ((u16 *)dev->dev_addr)[0] = le16_to_cpu(w); |
| 1533 | } | 1567 | } |
| 1534 | 1568 | ||
| 1569 | sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo)); | ||
| 1570 | |||
| 1535 | return 0; | 1571 | return 0; |
| 1536 | } | 1572 | } |
| 1537 | 1573 | ||
| @@ -1577,6 +1613,8 @@ static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev, | |||
| 1577 | outb(0x12, 0x78); | 1613 | outb(0x12, 0x78); |
| 1578 | reg = inb(0x79); | 1614 | reg = inb(0x79); |
| 1579 | 1615 | ||
| 1616 | sis190_set_rgmii(tp, reg); | ||
| 1617 | |||
| 1580 | /* Restore the value to ISA Bridge */ | 1618 | /* Restore the value to ISA Bridge */ |
| 1581 | pci_write_config_byte(isa_bridge, 0x48, tmp8); | 1619 | pci_write_config_byte(isa_bridge, 0x48, tmp8); |
| 1582 | pci_dev_put(isa_bridge); | 1620 | pci_dev_put(isa_bridge); |
| @@ -1799,6 +1837,9 @@ static int __devinit sis190_init_one(struct pci_dev *pdev, | |||
| 1799 | dev->dev_addr[2], dev->dev_addr[3], | 1837 | dev->dev_addr[2], dev->dev_addr[3], |
| 1800 | dev->dev_addr[4], dev->dev_addr[5]); | 1838 | dev->dev_addr[4], dev->dev_addr[5]); |
| 1801 | 1839 | ||
| 1840 | net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name, | ||
| 1841 | (tp->features & F_HAS_RGMII) ? "RGMII" : "GMII"); | ||
| 1842 | |||
| 1802 | netif_carrier_off(dev); | 1843 | netif_carrier_off(dev); |
| 1803 | 1844 | ||
| 1804 | sis190_set_speed_auto(dev); | 1845 | sis190_set_speed_auto(dev); |
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 5ae22b7bc5ca..1a4316336256 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c | |||
| @@ -21,7 +21,6 @@ | |||
| 21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 22 | #include <linux/string.h> | 22 | #include <linux/string.h> |
| 23 | #include <linux/timer.h> | 23 | #include <linux/timer.h> |
| 24 | #include <linux/ptrace.h> | ||
| 25 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
| 26 | #include <linux/ioport.h> | 25 | #include <linux/ioport.h> |
| 27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| @@ -34,6 +33,7 @@ | |||
| 34 | #include <linux/skbuff.h> | 33 | #include <linux/skbuff.h> |
| 35 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
| 36 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
| 36 | #include <linux/dma-mapping.h> | ||
| 37 | 37 | ||
| 38 | #include <asm/processor.h> | 38 | #include <asm/processor.h> |
| 39 | #include <asm/bitops.h> | 39 | #include <asm/bitops.h> |
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index dd7dbf7b14d4..00a07f32a81e 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
| @@ -289,8 +289,8 @@ config APPLE_AIRPORT | |||
| 289 | a non-standard interface | 289 | a non-standard interface |
| 290 | 290 | ||
| 291 | config PLX_HERMES | 291 | config PLX_HERMES |
| 292 | tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.) (EXPERIMENTAL)" | 292 | tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)" |
| 293 | depends on PCI && HERMES && EXPERIMENTAL | 293 | depends on PCI && HERMES |
| 294 | help | 294 | help |
| 295 | Enable support for PCMCIA cards supported by the "Hermes" (aka | 295 | Enable support for PCMCIA cards supported by the "Hermes" (aka |
| 296 | orinoco) driver when used in PLX9052 based PCI adaptors. These | 296 | orinoco) driver when used in PLX9052 based PCI adaptors. These |
| @@ -299,12 +299,9 @@ config PLX_HERMES | |||
| 299 | 802.11b PCMCIA cards can be used in desktop machines. The Netgear | 299 | 802.11b PCMCIA cards can be used in desktop machines. The Netgear |
| 300 | MA301 is such an adaptor. | 300 | MA301 is such an adaptor. |
| 301 | 301 | ||
| 302 | Support for these adaptors is so far still incomplete and buggy. | ||
| 303 | You have been warned. | ||
| 304 | |||
| 305 | config TMD_HERMES | 302 | config TMD_HERMES |
| 306 | tristate "Hermes in TMD7160 based PCI adaptor support (EXPERIMENTAL)" | 303 | tristate "Hermes in TMD7160 based PCI adaptor support" |
| 307 | depends on PCI && HERMES && EXPERIMENTAL | 304 | depends on PCI && HERMES |
| 308 | help | 305 | help |
| 309 | Enable support for PCMCIA cards supported by the "Hermes" (aka | 306 | Enable support for PCMCIA cards supported by the "Hermes" (aka |
| 310 | orinoco) driver when used in TMD7160 based PCI adaptors. These | 307 | orinoco) driver when used in TMD7160 based PCI adaptors. These |
| @@ -312,12 +309,18 @@ config TMD_HERMES | |||
| 312 | PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that | 309 | PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that |
| 313 | 802.11b PCMCIA cards can be used in desktop machines. | 310 | 802.11b PCMCIA cards can be used in desktop machines. |
| 314 | 311 | ||
| 315 | Support for these adaptors is so far still incomplete and buggy. | 312 | config NORTEL_HERMES |
| 316 | You have been warned. | 313 | tristate "Nortel emobility PCI adaptor support" |
| 314 | depends on PCI && HERMES | ||
| 315 | help | ||
| 316 | Enable support for PCMCIA cards supported by the "Hermes" (aka | ||
| 317 | orinoco) driver when used in Nortel emobility PCI adaptors. These | ||
| 318 | adaptors are not full PCMCIA controllers, but act as a more limited | ||
| 319 | PCI <-> PCMCIA bridge. | ||
| 317 | 320 | ||
| 318 | config PCI_HERMES | 321 | config PCI_HERMES |
| 319 | tristate "Prism 2.5 PCI 802.11b adaptor support (EXPERIMENTAL)" | 322 | tristate "Prism 2.5 PCI 802.11b adaptor support" |
| 320 | depends on PCI && HERMES && EXPERIMENTAL | 323 | depends on PCI && HERMES |
| 321 | help | 324 | help |
| 322 | Enable support for PCI and mini-PCI 802.11b wireless NICs based on | 325 | Enable support for PCI and mini-PCI 802.11b wireless NICs based on |
| 323 | the Prism 2.5 chipset. These are true PCI cards, not the 802.11b | 326 | the Prism 2.5 chipset. These are true PCI cards, not the 802.11b |
| @@ -372,6 +375,19 @@ config PCMCIA_HERMES | |||
| 372 | configure your card and that /etc/pcmcia/wireless.opts works: | 375 | configure your card and that /etc/pcmcia/wireless.opts works: |
| 373 | <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>. | 376 | <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>. |
| 374 | 377 | ||
| 378 | config PCMCIA_SPECTRUM | ||
| 379 | tristate "Symbol Spectrum24 Trilogy PCMCIA card support" | ||
| 380 | depends on NET_RADIO && PCMCIA && HERMES | ||
| 381 | ---help--- | ||
| 382 | |||
| 383 | This is a driver for 802.11b cards using RAM-loadable Symbol | ||
| 384 | firmware, such as Symbol Wireless Networker LA4100, CompactFlash | ||
| 385 | cards by Socket Communications and Intel PRO/Wireless 2011B. | ||
| 386 | |||
| 387 | This driver requires firmware download on startup. Utilities | ||
| 388 | for downloading Symbol firmware are available at | ||
| 389 | <http://sourceforge.net/projects/orinoco/> | ||
| 390 | |||
| 375 | config AIRO_CS | 391 | config AIRO_CS |
| 376 | tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards" | 392 | tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards" |
| 377 | depends on NET_RADIO && PCMCIA && (BROKEN || !M32R) | 393 | depends on NET_RADIO && PCMCIA && (BROKEN || !M32R) |
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 0953cc0cdee6..3a6f7ba326ca 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile | |||
| @@ -22,6 +22,8 @@ obj-$(CONFIG_APPLE_AIRPORT) += airport.o | |||
| 22 | obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o | 22 | obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o |
| 23 | obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o | 23 | obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o |
| 24 | obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o | 24 | obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o |
| 25 | obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o | ||
| 26 | obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o | ||
| 25 | 27 | ||
| 26 | obj-$(CONFIG_AIRO) += airo.o | 28 | obj-$(CONFIG_AIRO) += airo.o |
| 27 | obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o | 29 | obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o |
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index a47fce4beadf..2414e6493aa5 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c | |||
| @@ -327,38 +327,38 @@ static struct iw_handler_def ipw2100_wx_handler_def; | |||
| 327 | 327 | ||
| 328 | static inline void read_register(struct net_device *dev, u32 reg, u32 *val) | 328 | static inline void read_register(struct net_device *dev, u32 reg, u32 *val) |
| 329 | { | 329 | { |
| 330 | *val = readl((void *)(dev->base_addr + reg)); | 330 | *val = readl((void __iomem *)(dev->base_addr + reg)); |
| 331 | IPW_DEBUG_IO("r: 0x%08X => 0x%08X\n", reg, *val); | 331 | IPW_DEBUG_IO("r: 0x%08X => 0x%08X\n", reg, *val); |
| 332 | } | 332 | } |
| 333 | 333 | ||
| 334 | static inline void write_register(struct net_device *dev, u32 reg, u32 val) | 334 | static inline void write_register(struct net_device *dev, u32 reg, u32 val) |
| 335 | { | 335 | { |
| 336 | writel(val, (void *)(dev->base_addr + reg)); | 336 | writel(val, (void __iomem *)(dev->base_addr + reg)); |
| 337 | IPW_DEBUG_IO("w: 0x%08X <= 0x%08X\n", reg, val); | 337 | IPW_DEBUG_IO("w: 0x%08X <= 0x%08X\n", reg, val); |
| 338 | } | 338 | } |
| 339 | 339 | ||
| 340 | static inline void read_register_word(struct net_device *dev, u32 reg, u16 *val) | 340 | static inline void read_register_word(struct net_device *dev, u32 reg, u16 *val) |
| 341 | { | 341 | { |
| 342 | *val = readw((void *)(dev->base_addr + reg)); | 342 | *val = readw((void __iomem *)(dev->base_addr + reg)); |
| 343 | IPW_DEBUG_IO("r: 0x%08X => %04X\n", reg, *val); | 343 | IPW_DEBUG_IO("r: 0x%08X => %04X\n", reg, *val); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | static inline void read_register_byte(struct net_device *dev, u32 reg, u8 *val) | 346 | static inline void read_register_byte(struct net_device *dev, u32 reg, u8 *val) |
| 347 | { | 347 | { |
| 348 | *val = readb((void *)(dev->base_addr + reg)); | 348 | *val = readb((void __iomem *)(dev->base_addr + reg)); |
| 349 | IPW_DEBUG_IO("r: 0x%08X => %02X\n", reg, *val); | 349 | IPW_DEBUG_IO("r: 0x%08X => %02X\n", reg, *val); |
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | static inline void write_register_word(struct net_device *dev, u32 reg, u16 val) | 352 | static inline void write_register_word(struct net_device *dev, u32 reg, u16 val) |
| 353 | { | 353 | { |
| 354 | writew(val, (void *)(dev->base_addr + reg)); | 354 | writew(val, (void __iomem *)(dev->base_addr + reg)); |
| 355 | IPW_DEBUG_IO("w: 0x%08X <= %04X\n", reg, val); | 355 | IPW_DEBUG_IO("w: 0x%08X <= %04X\n", reg, val); |
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | 358 | ||
| 359 | static inline void write_register_byte(struct net_device *dev, u32 reg, u8 val) | 359 | static inline void write_register_byte(struct net_device *dev, u32 reg, u8 val) |
| 360 | { | 360 | { |
| 361 | writeb(val, (void *)(dev->base_addr + reg)); | 361 | writeb(val, (void __iomem *)(dev->base_addr + reg)); |
| 362 | IPW_DEBUG_IO("w: 0x%08X =< %02X\n", reg, val); | 362 | IPW_DEBUG_IO("w: 0x%08X =< %02X\n", reg, val); |
| 363 | } | 363 | } |
| 364 | 364 | ||
| @@ -498,7 +498,7 @@ static inline void read_nic_memory(struct net_device *dev, u32 addr, u32 len, | |||
| 498 | static inline int ipw2100_hw_is_adapter_in_system(struct net_device *dev) | 498 | static inline int ipw2100_hw_is_adapter_in_system(struct net_device *dev) |
| 499 | { | 499 | { |
| 500 | return (dev->base_addr && | 500 | return (dev->base_addr && |
| 501 | (readl((void *)(dev->base_addr + IPW_REG_DOA_DEBUG_AREA_START)) | 501 | (readl((void __iomem *)(dev->base_addr + IPW_REG_DOA_DEBUG_AREA_START)) |
| 502 | == IPW_DATA_DOA_DEBUG_VALUE)); | 502 | == IPW_DATA_DOA_DEBUG_VALUE)); |
| 503 | } | 503 | } |
| 504 | 504 | ||
| @@ -2125,19 +2125,19 @@ static void isr_indicate_scanning(struct ipw2100_priv *priv, u32 status) | |||
| 2125 | } | 2125 | } |
| 2126 | 2126 | ||
| 2127 | static const struct ipw2100_status_indicator status_handlers[] = { | 2127 | static const struct ipw2100_status_indicator status_handlers[] = { |
| 2128 | IPW2100_HANDLER(IPW_STATE_INITIALIZED, 0), | 2128 | IPW2100_HANDLER(IPW_STATE_INITIALIZED, NULL), |
| 2129 | IPW2100_HANDLER(IPW_STATE_COUNTRY_FOUND, 0), | 2129 | IPW2100_HANDLER(IPW_STATE_COUNTRY_FOUND, NULL), |
| 2130 | IPW2100_HANDLER(IPW_STATE_ASSOCIATED, isr_indicate_associated), | 2130 | IPW2100_HANDLER(IPW_STATE_ASSOCIATED, isr_indicate_associated), |
| 2131 | IPW2100_HANDLER(IPW_STATE_ASSN_LOST, isr_indicate_association_lost), | 2131 | IPW2100_HANDLER(IPW_STATE_ASSN_LOST, isr_indicate_association_lost), |
| 2132 | IPW2100_HANDLER(IPW_STATE_ASSN_CHANGED, 0), | 2132 | IPW2100_HANDLER(IPW_STATE_ASSN_CHANGED, NULL), |
| 2133 | IPW2100_HANDLER(IPW_STATE_SCAN_COMPLETE, isr_scan_complete), | 2133 | IPW2100_HANDLER(IPW_STATE_SCAN_COMPLETE, isr_scan_complete), |
| 2134 | IPW2100_HANDLER(IPW_STATE_ENTERED_PSP, 0), | 2134 | IPW2100_HANDLER(IPW_STATE_ENTERED_PSP, NULL), |
| 2135 | IPW2100_HANDLER(IPW_STATE_LEFT_PSP, 0), | 2135 | IPW2100_HANDLER(IPW_STATE_LEFT_PSP, NULL), |
| 2136 | IPW2100_HANDLER(IPW_STATE_RF_KILL, isr_indicate_rf_kill), | 2136 | IPW2100_HANDLER(IPW_STATE_RF_KILL, isr_indicate_rf_kill), |
| 2137 | IPW2100_HANDLER(IPW_STATE_DISABLED, 0), | 2137 | IPW2100_HANDLER(IPW_STATE_DISABLED, NULL), |
| 2138 | IPW2100_HANDLER(IPW_STATE_POWER_DOWN, 0), | 2138 | IPW2100_HANDLER(IPW_STATE_POWER_DOWN, NULL), |
| 2139 | IPW2100_HANDLER(IPW_STATE_SCANNING, isr_indicate_scanning), | 2139 | IPW2100_HANDLER(IPW_STATE_SCANNING, isr_indicate_scanning), |
| 2140 | IPW2100_HANDLER(-1, 0) | 2140 | IPW2100_HANDLER(-1, NULL) |
| 2141 | }; | 2141 | }; |
| 2142 | 2142 | ||
| 2143 | 2143 | ||
| @@ -6327,7 +6327,7 @@ static void ipw2100_irq_tasklet(struct ipw2100_priv *priv); | |||
| 6327 | 6327 | ||
| 6328 | static struct net_device *ipw2100_alloc_device( | 6328 | static struct net_device *ipw2100_alloc_device( |
| 6329 | struct pci_dev *pci_dev, | 6329 | struct pci_dev *pci_dev, |
| 6330 | char *base_addr, | 6330 | void __iomem *base_addr, |
| 6331 | unsigned long mem_start, | 6331 | unsigned long mem_start, |
| 6332 | unsigned long mem_len) | 6332 | unsigned long mem_len) |
| 6333 | { | 6333 | { |
| @@ -6474,7 +6474,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, | |||
| 6474 | const struct pci_device_id *ent) | 6474 | const struct pci_device_id *ent) |
| 6475 | { | 6475 | { |
| 6476 | unsigned long mem_start, mem_len, mem_flags; | 6476 | unsigned long mem_start, mem_len, mem_flags; |
| 6477 | char *base_addr = NULL; | 6477 | void __iomem *base_addr = NULL; |
| 6478 | struct net_device *dev = NULL; | 6478 | struct net_device *dev = NULL; |
| 6479 | struct ipw2100_priv *priv = NULL; | 6479 | struct ipw2100_priv *priv = NULL; |
| 6480 | int err = 0; | 6480 | int err = 0; |
| @@ -6664,7 +6664,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, | |||
| 6664 | } | 6664 | } |
| 6665 | 6665 | ||
| 6666 | if (base_addr) | 6666 | if (base_addr) |
| 6667 | iounmap((char*)base_addr); | 6667 | iounmap(base_addr); |
| 6668 | 6668 | ||
| 6669 | pci_release_regions(pci_dev); | 6669 | pci_release_regions(pci_dev); |
| 6670 | pci_disable_device(pci_dev); | 6670 | pci_disable_device(pci_dev); |
| @@ -6714,7 +6714,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) | |||
| 6714 | free_irq(dev->irq, priv); | 6714 | free_irq(dev->irq, priv); |
| 6715 | 6715 | ||
| 6716 | if (dev->base_addr) | 6716 | if (dev->base_addr) |
| 6717 | iounmap((unsigned char *)dev->base_addr); | 6717 | iounmap((void __iomem *)dev->base_addr); |
| 6718 | 6718 | ||
| 6719 | free_ieee80211(dev); | 6719 | free_ieee80211(dev); |
| 6720 | } | 6720 | } |
| @@ -8574,6 +8574,7 @@ static int ipw2100_ucode_download(struct ipw2100_priv *priv, | |||
| 8574 | struct net_device *dev = priv->net_dev; | 8574 | struct net_device *dev = priv->net_dev; |
| 8575 | const unsigned char *microcode_data = fw->uc.data; | 8575 | const unsigned char *microcode_data = fw->uc.data; |
| 8576 | unsigned int microcode_data_left = fw->uc.size; | 8576 | unsigned int microcode_data_left = fw->uc.size; |
| 8577 | void __iomem *reg = (void __iomem *)dev->base_addr; | ||
| 8577 | 8578 | ||
| 8578 | struct symbol_alive_response response; | 8579 | struct symbol_alive_response response; |
| 8579 | int i, j; | 8580 | int i, j; |
| @@ -8581,23 +8582,23 @@ static int ipw2100_ucode_download(struct ipw2100_priv *priv, | |||
| 8581 | 8582 | ||
| 8582 | /* Symbol control */ | 8583 | /* Symbol control */ |
| 8583 | write_nic_word(dev, IPW2100_CONTROL_REG, 0x703); | 8584 | write_nic_word(dev, IPW2100_CONTROL_REG, 0x703); |
| 8584 | readl((void *)(dev->base_addr)); | 8585 | readl(reg); |
| 8585 | write_nic_word(dev, IPW2100_CONTROL_REG, 0x707); | 8586 | write_nic_word(dev, IPW2100_CONTROL_REG, 0x707); |
| 8586 | readl((void *)(dev->base_addr)); | 8587 | readl(reg); |
| 8587 | 8588 | ||
| 8588 | /* HW config */ | 8589 | /* HW config */ |
| 8589 | write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */ | 8590 | write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */ |
| 8590 | readl((void *)(dev->base_addr)); | 8591 | readl(reg); |
| 8591 | write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */ | 8592 | write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */ |
| 8592 | readl((void *)(dev->base_addr)); | 8593 | readl(reg); |
| 8593 | 8594 | ||
| 8594 | /* EN_CS_ACCESS bit to reset control store pointer */ | 8595 | /* EN_CS_ACCESS bit to reset control store pointer */ |
| 8595 | write_nic_byte(dev, 0x210000, 0x40); | 8596 | write_nic_byte(dev, 0x210000, 0x40); |
| 8596 | readl((void *)(dev->base_addr)); | 8597 | readl(reg); |
| 8597 | write_nic_byte(dev, 0x210000, 0x0); | 8598 | write_nic_byte(dev, 0x210000, 0x0); |
| 8598 | readl((void *)(dev->base_addr)); | 8599 | readl(reg); |
| 8599 | write_nic_byte(dev, 0x210000, 0x40); | 8600 | write_nic_byte(dev, 0x210000, 0x40); |
| 8600 | readl((void *)(dev->base_addr)); | 8601 | readl(reg); |
| 8601 | 8602 | ||
| 8602 | /* copy microcode from buffer into Symbol */ | 8603 | /* copy microcode from buffer into Symbol */ |
| 8603 | 8604 | ||
| @@ -8609,31 +8610,31 @@ static int ipw2100_ucode_download(struct ipw2100_priv *priv, | |||
| 8609 | 8610 | ||
| 8610 | /* EN_CS_ACCESS bit to reset the control store pointer */ | 8611 | /* EN_CS_ACCESS bit to reset the control store pointer */ |
| 8611 | write_nic_byte(dev, 0x210000, 0x0); | 8612 | write_nic_byte(dev, 0x210000, 0x0); |
| 8612 | readl((void *)(dev->base_addr)); | 8613 | readl(reg); |
| 8613 | 8614 | ||
| 8614 | /* Enable System (Reg 0) | 8615 | /* Enable System (Reg 0) |
| 8615 | * first enable causes garbage in RX FIFO */ | 8616 | * first enable causes garbage in RX FIFO */ |
| 8616 | write_nic_byte(dev, 0x210000, 0x0); | 8617 | write_nic_byte(dev, 0x210000, 0x0); |
| 8617 | readl((void *)(dev->base_addr)); | 8618 | readl(reg); |
| 8618 | write_nic_byte(dev, 0x210000, 0x80); | 8619 | write_nic_byte(dev, 0x210000, 0x80); |
| 8619 | readl((void *)(dev->base_addr)); | 8620 | readl(reg); |
| 8620 | 8621 | ||
| 8621 | /* Reset External Baseband Reg */ | 8622 | /* Reset External Baseband Reg */ |
| 8622 | write_nic_word(dev, IPW2100_CONTROL_REG, 0x703); | 8623 | write_nic_word(dev, IPW2100_CONTROL_REG, 0x703); |
| 8623 | readl((void *)(dev->base_addr)); | 8624 | readl(reg); |
| 8624 | write_nic_word(dev, IPW2100_CONTROL_REG, 0x707); | 8625 | write_nic_word(dev, IPW2100_CONTROL_REG, 0x707); |
| 8625 | readl((void *)(dev->base_addr)); | 8626 | readl(reg); |
| 8626 | 8627 | ||
| 8627 | /* HW Config (Reg 5) */ | 8628 | /* HW Config (Reg 5) */ |
| 8628 | write_nic_byte(dev, 0x210014, 0x72); // fifo width =16 | 8629 | write_nic_byte(dev, 0x210014, 0x72); // fifo width =16 |
| 8629 | readl((void *)(dev->base_addr)); | 8630 | readl(reg); |
| 8630 | write_nic_byte(dev, 0x210014, 0x72); // fifo width =16 | 8631 | write_nic_byte(dev, 0x210014, 0x72); // fifo width =16 |
| 8631 | readl((void *)(dev->base_addr)); | 8632 | readl(reg); |
| 8632 | 8633 | ||
| 8633 | /* Enable System (Reg 0) | 8634 | /* Enable System (Reg 0) |
| 8634 | * second enable should be OK */ | 8635 | * second enable should be OK */ |
| 8635 | write_nic_byte(dev, 0x210000, 0x00); // clear enable system | 8636 | write_nic_byte(dev, 0x210000, 0x00); // clear enable system |
| 8636 | readl((void *)(dev->base_addr)); | 8637 | readl(reg); |
| 8637 | write_nic_byte(dev, 0x210000, 0x80); // set enable system | 8638 | write_nic_byte(dev, 0x210000, 0x80); // set enable system |
| 8638 | 8639 | ||
| 8639 | /* check Symbol is enabled - upped this from 5 as it wasn't always | 8640 | /* check Symbol is enabled - upped this from 5 as it wasn't always |
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index dc3e7bc805fc..66bb5903537f 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/etherdevice.h> | 42 | #include <linux/etherdevice.h> |
| 43 | #include <linux/delay.h> | 43 | #include <linux/delay.h> |
| 44 | #include <linux/random.h> | 44 | #include <linux/random.h> |
| 45 | #include <linux/dma-mapping.h> | ||
| 45 | 46 | ||
| 46 | #include <linux/firmware.h> | 47 | #include <linux/firmware.h> |
| 47 | #include <linux/wireless.h> | 48 | #include <linux/wireless.h> |
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index d7947358e49d..8de49fe57233 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c | |||
| @@ -1053,8 +1053,9 @@ static void orinoco_join_ap(struct net_device *dev) | |||
| 1053 | u16 channel; | 1053 | u16 channel; |
| 1054 | } __attribute__ ((packed)) req; | 1054 | } __attribute__ ((packed)) req; |
| 1055 | const int atom_len = offsetof(struct prism2_scan_apinfo, atim); | 1055 | const int atom_len = offsetof(struct prism2_scan_apinfo, atim); |
| 1056 | struct prism2_scan_apinfo *atom; | 1056 | struct prism2_scan_apinfo *atom = NULL; |
| 1057 | int offset = 4; | 1057 | int offset = 4; |
| 1058 | int found = 0; | ||
| 1058 | u8 *buf; | 1059 | u8 *buf; |
| 1059 | u16 len; | 1060 | u16 len; |
| 1060 | 1061 | ||
| @@ -1089,15 +1090,18 @@ static void orinoco_join_ap(struct net_device *dev) | |||
| 1089 | * we were requested to join */ | 1090 | * we were requested to join */ |
| 1090 | for (; offset + atom_len <= len; offset += atom_len) { | 1091 | for (; offset + atom_len <= len; offset += atom_len) { |
| 1091 | atom = (struct prism2_scan_apinfo *) (buf + offset); | 1092 | atom = (struct prism2_scan_apinfo *) (buf + offset); |
| 1092 | if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) | 1093 | if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) { |
| 1093 | goto found; | 1094 | found = 1; |
| 1095 | break; | ||
| 1096 | } | ||
| 1094 | } | 1097 | } |
| 1095 | 1098 | ||
| 1096 | DEBUG(1, "%s: Requested AP not found in scan results\n", | 1099 | if (! found) { |
| 1097 | dev->name); | 1100 | DEBUG(1, "%s: Requested AP not found in scan results\n", |
| 1098 | goto out; | 1101 | dev->name); |
| 1102 | goto out; | ||
| 1103 | } | ||
| 1099 | 1104 | ||
| 1100 | found: | ||
| 1101 | memcpy(req.bssid, priv->desired_bssid, ETH_ALEN); | 1105 | memcpy(req.bssid, priv->desired_bssid, ETH_ALEN); |
| 1102 | req.channel = atom->channel; /* both are little-endian */ | 1106 | req.channel = atom->channel; /* both are little-endian */ |
| 1103 | err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST, | 1107 | err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST, |
| @@ -1284,8 +1288,10 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) | |||
| 1284 | /* Read scan data */ | 1288 | /* Read scan data */ |
| 1285 | err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, | 1289 | err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, |
| 1286 | infofid, sizeof(info)); | 1290 | infofid, sizeof(info)); |
| 1287 | if (err) | 1291 | if (err) { |
| 1292 | kfree(buf); | ||
| 1288 | break; | 1293 | break; |
| 1294 | } | ||
| 1289 | 1295 | ||
| 1290 | #ifdef ORINOCO_DEBUG | 1296 | #ifdef ORINOCO_DEBUG |
| 1291 | { | 1297 | { |
| @@ -4021,7 +4027,8 @@ static int orinoco_ioctl_setscan(struct net_device *dev, | |||
| 4021 | } | 4027 | } |
| 4022 | 4028 | ||
| 4023 | /* Translate scan data returned from the card to a card independant | 4029 | /* Translate scan data returned from the card to a card independant |
| 4024 | * format that the Wireless Tools will understand - Jean II */ | 4030 | * format that the Wireless Tools will understand - Jean II |
| 4031 | * Return message length or -errno for fatal errors */ | ||
| 4025 | static inline int orinoco_translate_scan(struct net_device *dev, | 4032 | static inline int orinoco_translate_scan(struct net_device *dev, |
| 4026 | char *buffer, | 4033 | char *buffer, |
| 4027 | char *scan, | 4034 | char *scan, |
| @@ -4061,13 +4068,19 @@ static inline int orinoco_translate_scan(struct net_device *dev, | |||
| 4061 | break; | 4068 | break; |
| 4062 | case FIRMWARE_TYPE_INTERSIL: | 4069 | case FIRMWARE_TYPE_INTERSIL: |
| 4063 | offset = 4; | 4070 | offset = 4; |
| 4064 | if (priv->has_hostscan) | 4071 | if (priv->has_hostscan) { |
| 4065 | atom_len = scan[0] + (scan[1] << 8); | 4072 | atom_len = le16_to_cpup((u16 *)scan); |
| 4066 | else | 4073 | /* Sanity check for atom_len */ |
| 4074 | if (atom_len < sizeof(struct prism2_scan_apinfo)) { | ||
| 4075 | printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n", | ||
| 4076 | dev->name, atom_len); | ||
| 4077 | return -EIO; | ||
| 4078 | } | ||
| 4079 | } else | ||
| 4067 | atom_len = offsetof(struct prism2_scan_apinfo, atim); | 4080 | atom_len = offsetof(struct prism2_scan_apinfo, atim); |
| 4068 | break; | 4081 | break; |
| 4069 | default: | 4082 | default: |
| 4070 | return 0; | 4083 | return -EOPNOTSUPP; |
| 4071 | } | 4084 | } |
| 4072 | 4085 | ||
| 4073 | /* Check that we got an whole number of atoms */ | 4086 | /* Check that we got an whole number of atoms */ |
| @@ -4075,7 +4088,7 @@ static inline int orinoco_translate_scan(struct net_device *dev, | |||
| 4075 | printk(KERN_ERR "%s: Unexpected scan data length %d, " | 4088 | printk(KERN_ERR "%s: Unexpected scan data length %d, " |
| 4076 | "atom_len %d, offset %d\n", dev->name, scan_len, | 4089 | "atom_len %d, offset %d\n", dev->name, scan_len, |
| 4077 | atom_len, offset); | 4090 | atom_len, offset); |
| 4078 | return 0; | 4091 | return -EIO; |
| 4079 | } | 4092 | } |
| 4080 | 4093 | ||
| 4081 | /* Read the entries one by one */ | 4094 | /* Read the entries one by one */ |
| @@ -4210,33 +4223,41 @@ static int orinoco_ioctl_getscan(struct net_device *dev, | |||
| 4210 | /* We have some results to push back to user space */ | 4223 | /* We have some results to push back to user space */ |
| 4211 | 4224 | ||
| 4212 | /* Translate to WE format */ | 4225 | /* Translate to WE format */ |
| 4213 | srq->length = orinoco_translate_scan(dev, extra, | 4226 | int ret = orinoco_translate_scan(dev, extra, |
| 4214 | priv->scan_result, | 4227 | priv->scan_result, |
| 4215 | priv->scan_len); | 4228 | priv->scan_len); |
| 4216 | 4229 | ||
| 4217 | /* Return flags */ | 4230 | if (ret < 0) { |
| 4218 | srq->flags = (__u16) priv->scan_mode; | 4231 | err = ret; |
| 4232 | kfree(priv->scan_result); | ||
| 4233 | priv->scan_result = NULL; | ||
| 4234 | } else { | ||
| 4235 | srq->length = ret; | ||
| 4219 | 4236 | ||
| 4220 | /* Results are here, so scan no longer in progress */ | 4237 | /* Return flags */ |
| 4221 | priv->scan_inprogress = 0; | 4238 | srq->flags = (__u16) priv->scan_mode; |
| 4222 | 4239 | ||
| 4223 | /* In any case, Scan results will be cleaned up in the | 4240 | /* In any case, Scan results will be cleaned up in the |
| 4224 | * reset function and when exiting the driver. | 4241 | * reset function and when exiting the driver. |
| 4225 | * The person triggering the scanning may never come to | 4242 | * The person triggering the scanning may never come to |
| 4226 | * pick the results, so we need to do it in those places. | 4243 | * pick the results, so we need to do it in those places. |
| 4227 | * Jean II */ | 4244 | * Jean II */ |
| 4228 | 4245 | ||
| 4229 | #ifdef SCAN_SINGLE_READ | 4246 | #ifdef SCAN_SINGLE_READ |
| 4230 | /* If you enable this option, only one client (the first | 4247 | /* If you enable this option, only one client (the first |
| 4231 | * one) will be able to read the result (and only one | 4248 | * one) will be able to read the result (and only one |
| 4232 | * time). If there is multiple concurent clients that | 4249 | * time). If there is multiple concurent clients that |
| 4233 | * want to read scan results, this behavior is not | 4250 | * want to read scan results, this behavior is not |
| 4234 | * advisable - Jean II */ | 4251 | * advisable - Jean II */ |
| 4235 | kfree(priv->scan_result); | 4252 | kfree(priv->scan_result); |
| 4236 | priv->scan_result = NULL; | 4253 | priv->scan_result = NULL; |
| 4237 | #endif /* SCAN_SINGLE_READ */ | 4254 | #endif /* SCAN_SINGLE_READ */ |
| 4238 | /* Here, if too much time has elapsed since last scan, | 4255 | /* Here, if too much time has elapsed since last scan, |
| 4239 | * we may want to clean up scan results... - Jean II */ | 4256 | * we may want to clean up scan results... - Jean II */ |
| 4257 | } | ||
| 4258 | |||
| 4259 | /* Scan is no longer in progress */ | ||
| 4260 | priv->scan_inprogress = 0; | ||
| 4240 | } | 4261 | } |
| 4241 | 4262 | ||
| 4242 | orinoco_unlock(priv, &flags); | 4263 | orinoco_unlock(priv, &flags); |
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 1cc1492083c9..d1fb1bab8aa8 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c | |||
| @@ -604,7 +604,6 @@ static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | |||
| 604 | 604 | ||
| 605 | static struct pcmcia_device_id orinoco_cs_ids[] = { | 605 | static struct pcmcia_device_id orinoco_cs_ids[] = { |
| 606 | PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), | 606 | PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), |
| 607 | PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), | ||
| 608 | PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), | 607 | PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), |
| 609 | PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), | 608 | PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), |
| 610 | PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), | 609 | PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), |
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c new file mode 100644 index 000000000000..86fa58e5cfac --- /dev/null +++ b/drivers/net/wireless/orinoco_nortel.c | |||
| @@ -0,0 +1,324 @@ | |||
| 1 | /* orinoco_nortel.c | ||
| 2 | * | ||
| 3 | * Driver for Prism II devices which would usually be driven by orinoco_cs, | ||
| 4 | * but are connected to the PCI bus by a Nortel PCI-PCMCIA-Adapter. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2002 Tobias Hoffmann | ||
| 7 | * (C) 2003 Christoph Jungegger <disdos@traum404.de> | ||
| 8 | * | ||
| 9 | * Some of this code is borrowed from orinoco_plx.c | ||
| 10 | * Copyright (C) 2001 Daniel Barlow | ||
| 11 | * Some of this code is borrowed from orinoco_pci.c | ||
| 12 | * Copyright (C) 2001 Jean Tourrilhes | ||
| 13 | * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing | ||
| 14 | * has been copied from it. linux-wlan-ng-0.1.10 is originally : | ||
| 15 | * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. | ||
| 16 | * | ||
| 17 | * The contents of this file are subject to the Mozilla Public License | ||
| 18 | * Version 1.1 (the "License"); you may not use this file except in | ||
| 19 | * compliance with the License. You may obtain a copy of the License | ||
| 20 | * at http://www.mozilla.org/MPL/ | ||
| 21 | * | ||
| 22 | * Software distributed under the License is distributed on an "AS IS" | ||
| 23 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See | ||
| 24 | * the License for the specific language governing rights and | ||
| 25 | * limitations under the License. | ||
| 26 | * | ||
| 27 | * Alternatively, the contents of this file may be used under the | ||
| 28 | * terms of the GNU General Public License version 2 (the "GPL"), in | ||
| 29 | * which case the provisions of the GPL are applicable instead of the | ||
| 30 | * above. If you wish to allow the use of your version of this file | ||
| 31 | * only under the terms of the GPL and not to allow others to use your | ||
| 32 | * version of this file under the MPL, indicate your decision by | ||
| 33 | * deleting the provisions above and replace them with the notice and | ||
| 34 | * other provisions required by the GPL. If you do not delete the | ||
| 35 | * provisions above, a recipient may use your version of this file | ||
| 36 | * under either the MPL or the GPL. | ||
| 37 | */ | ||
| 38 | |||
| 39 | #define DRIVER_NAME "orinoco_nortel" | ||
| 40 | #define PFX DRIVER_NAME ": " | ||
| 41 | |||
| 42 | #include <linux/config.h> | ||
| 43 | |||
| 44 | #include <linux/module.h> | ||
| 45 | #include <linux/kernel.h> | ||
| 46 | #include <linux/init.h> | ||
| 47 | #include <linux/sched.h> | ||
| 48 | #include <linux/ptrace.h> | ||
| 49 | #include <linux/slab.h> | ||
| 50 | #include <linux/string.h> | ||
| 51 | #include <linux/timer.h> | ||
| 52 | #include <linux/ioport.h> | ||
| 53 | #include <asm/uaccess.h> | ||
| 54 | #include <asm/io.h> | ||
| 55 | #include <asm/system.h> | ||
| 56 | #include <linux/netdevice.h> | ||
| 57 | #include <linux/if_arp.h> | ||
| 58 | #include <linux/etherdevice.h> | ||
| 59 | #include <linux/list.h> | ||
| 60 | #include <linux/pci.h> | ||
| 61 | #include <linux/fcntl.h> | ||
| 62 | |||
| 63 | #include <pcmcia/cisreg.h> | ||
| 64 | |||
| 65 | #include "hermes.h" | ||
| 66 | #include "orinoco.h" | ||
| 67 | |||
| 68 | #define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */ | ||
| 69 | #define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ | ||
| 70 | |||
| 71 | |||
| 72 | /* Nortel specific data */ | ||
| 73 | struct nortel_pci_card { | ||
| 74 | unsigned long iobase1; | ||
| 75 | unsigned long iobase2; | ||
| 76 | }; | ||
| 77 | |||
| 78 | /* | ||
| 79 | * Do a soft reset of the PCI card using the Configuration Option Register | ||
| 80 | * We need this to get going... | ||
| 81 | * This is the part of the code that is strongly inspired from wlan-ng | ||
| 82 | * | ||
| 83 | * Note bis : Don't try to access HERMES_CMD during the reset phase. | ||
| 84 | * It just won't work ! | ||
| 85 | */ | ||
| 86 | static int nortel_pci_cor_reset(struct orinoco_private *priv) | ||
| 87 | { | ||
| 88 | struct nortel_pci_card *card = priv->card; | ||
| 89 | |||
| 90 | /* Assert the reset until the card notice */ | ||
| 91 | outw_p(8, card->iobase1 + 2); | ||
| 92 | inw(card->iobase2 + COR_OFFSET); | ||
| 93 | outw_p(0x80, card->iobase2 + COR_OFFSET); | ||
| 94 | mdelay(1); | ||
| 95 | |||
| 96 | /* Give time for the card to recover from this hard effort */ | ||
| 97 | outw_p(0, card->iobase2 + COR_OFFSET); | ||
| 98 | outw_p(0, card->iobase2 + COR_OFFSET); | ||
| 99 | mdelay(1); | ||
| 100 | |||
| 101 | /* set COR as usual */ | ||
| 102 | outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); | ||
| 103 | outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); | ||
| 104 | mdelay(1); | ||
| 105 | |||
| 106 | outw_p(0x228, card->iobase1 + 2); | ||
| 107 | |||
| 108 | return 0; | ||
| 109 | } | ||
| 110 | |||
| 111 | int nortel_pci_hw_init(struct nortel_pci_card *card) | ||
| 112 | { | ||
| 113 | int i; | ||
| 114 | u32 reg; | ||
| 115 | |||
| 116 | /* setup bridge */ | ||
| 117 | if (inw(card->iobase1) & 1) { | ||
| 118 | printk(KERN_ERR PFX "brg1 answer1 wrong\n"); | ||
| 119 | return -EBUSY; | ||
| 120 | } | ||
| 121 | outw_p(0x118, card->iobase1 + 2); | ||
| 122 | outw_p(0x108, card->iobase1 + 2); | ||
| 123 | mdelay(30); | ||
| 124 | outw_p(0x8, card->iobase1 + 2); | ||
| 125 | for (i = 0; i < 30; i++) { | ||
| 126 | mdelay(30); | ||
| 127 | if (inw(card->iobase1) & 0x10) { | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | } | ||
| 131 | if (i == 30) { | ||
| 132 | printk(KERN_ERR PFX "brg1 timed out\n"); | ||
| 133 | return -EBUSY; | ||
| 134 | } | ||
| 135 | if (inw(card->iobase2 + 0xe0) & 1) { | ||
| 136 | printk(KERN_ERR PFX "brg2 answer1 wrong\n"); | ||
| 137 | return -EBUSY; | ||
| 138 | } | ||
| 139 | if (inw(card->iobase2 + 0xe2) & 1) { | ||
| 140 | printk(KERN_ERR PFX "brg2 answer2 wrong\n"); | ||
| 141 | return -EBUSY; | ||
| 142 | } | ||
| 143 | if (inw(card->iobase2 + 0xe4) & 1) { | ||
| 144 | printk(KERN_ERR PFX "brg2 answer3 wrong\n"); | ||
| 145 | return -EBUSY; | ||
| 146 | } | ||
| 147 | |||
| 148 | /* set the PCMCIA COR-Register */ | ||
| 149 | outw_p(COR_VALUE, card->iobase2 + COR_OFFSET); | ||
| 150 | mdelay(1); | ||
| 151 | reg = inw(card->iobase2 + COR_OFFSET); | ||
| 152 | if (reg != COR_VALUE) { | ||
| 153 | printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n", | ||
| 154 | reg); | ||
| 155 | return -EBUSY; | ||
| 156 | } | ||
| 157 | |||
| 158 | /* set leds */ | ||
| 159 | outw_p(1, card->iobase1 + 10); | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | static int nortel_pci_init_one(struct pci_dev *pdev, | ||
| 164 | const struct pci_device_id *ent) | ||
| 165 | { | ||
| 166 | int err; | ||
| 167 | struct orinoco_private *priv; | ||
| 168 | struct nortel_pci_card *card; | ||
| 169 | struct net_device *dev; | ||
| 170 | void __iomem *iomem; | ||
| 171 | |||
| 172 | err = pci_enable_device(pdev); | ||
| 173 | if (err) { | ||
| 174 | printk(KERN_ERR PFX "Cannot enable PCI device\n"); | ||
| 175 | return err; | ||
| 176 | } | ||
| 177 | |||
| 178 | err = pci_request_regions(pdev, DRIVER_NAME); | ||
| 179 | if (err != 0) { | ||
| 180 | printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); | ||
| 181 | goto fail_resources; | ||
| 182 | } | ||
| 183 | |||
| 184 | iomem = pci_iomap(pdev, 3, 0); | ||
| 185 | if (!iomem) { | ||
| 186 | err = -ENOMEM; | ||
| 187 | goto fail_map_io; | ||
| 188 | } | ||
| 189 | |||
| 190 | /* Allocate network device */ | ||
| 191 | dev = alloc_orinocodev(sizeof(*card), nortel_pci_cor_reset); | ||
| 192 | if (!dev) { | ||
| 193 | printk(KERN_ERR PFX "Cannot allocate network device\n"); | ||
| 194 | err = -ENOMEM; | ||
| 195 | goto fail_alloc; | ||
| 196 | } | ||
| 197 | |||
| 198 | priv = netdev_priv(dev); | ||
| 199 | card = priv->card; | ||
| 200 | card->iobase1 = pci_resource_start(pdev, 0); | ||
| 201 | card->iobase2 = pci_resource_start(pdev, 1); | ||
| 202 | dev->base_addr = pci_resource_start(pdev, 2); | ||
| 203 | SET_MODULE_OWNER(dev); | ||
| 204 | SET_NETDEV_DEV(dev, &pdev->dev); | ||
| 205 | |||
| 206 | hermes_struct_init(&priv->hw, iomem, HERMES_16BIT_REGSPACING); | ||
| 207 | |||
| 208 | printk(KERN_DEBUG PFX "Detected Nortel PCI device at %s irq:%d, " | ||
| 209 | "io addr:0x%lx\n", pci_name(pdev), pdev->irq, dev->base_addr); | ||
| 210 | |||
| 211 | err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, | ||
| 212 | dev->name, dev); | ||
| 213 | if (err) { | ||
| 214 | printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq); | ||
| 215 | err = -EBUSY; | ||
| 216 | goto fail_irq; | ||
| 217 | } | ||
| 218 | dev->irq = pdev->irq; | ||
| 219 | |||
| 220 | err = nortel_pci_hw_init(card); | ||
| 221 | if (err) { | ||
| 222 | printk(KERN_ERR PFX "Hardware initialization failed\n"); | ||
| 223 | goto fail; | ||
| 224 | } | ||
| 225 | |||
| 226 | err = nortel_pci_cor_reset(priv); | ||
| 227 | if (err) { | ||
| 228 | printk(KERN_ERR PFX "Initial reset failed\n"); | ||
| 229 | goto fail; | ||
| 230 | } | ||
| 231 | |||
| 232 | |||
| 233 | err = register_netdev(dev); | ||
| 234 | if (err) { | ||
| 235 | printk(KERN_ERR PFX "Cannot register network device\n"); | ||
| 236 | goto fail; | ||
| 237 | } | ||
| 238 | |||
| 239 | pci_set_drvdata(pdev, dev); | ||
| 240 | |||
| 241 | return 0; | ||
| 242 | |||
| 243 | fail: | ||
| 244 | free_irq(pdev->irq, dev); | ||
| 245 | |||
| 246 | fail_irq: | ||
| 247 | pci_set_drvdata(pdev, NULL); | ||
| 248 | free_orinocodev(dev); | ||
| 249 | |||
| 250 | fail_alloc: | ||
| 251 | pci_iounmap(pdev, iomem); | ||
| 252 | |||
| 253 | fail_map_io: | ||
| 254 | pci_release_regions(pdev); | ||
| 255 | |||
| 256 | fail_resources: | ||
| 257 | pci_disable_device(pdev); | ||
| 258 | |||
| 259 | return err; | ||
| 260 | } | ||
| 261 | |||
| 262 | static void __devexit nortel_pci_remove_one(struct pci_dev *pdev) | ||
| 263 | { | ||
| 264 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 265 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 266 | struct nortel_pci_card *card = priv->card; | ||
| 267 | |||
| 268 | /* clear leds */ | ||
| 269 | outw_p(0, card->iobase1 + 10); | ||
| 270 | |||
| 271 | unregister_netdev(dev); | ||
| 272 | free_irq(dev->irq, dev); | ||
| 273 | pci_set_drvdata(pdev, NULL); | ||
| 274 | free_orinocodev(dev); | ||
| 275 | pci_iounmap(pdev, priv->hw.iobase); | ||
| 276 | pci_release_regions(pdev); | ||
| 277 | pci_disable_device(pdev); | ||
| 278 | } | ||
| 279 | |||
| 280 | |||
| 281 | static struct pci_device_id nortel_pci_id_table[] = { | ||
| 282 | /* Nortel emobility PCI */ | ||
| 283 | {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, | ||
| 284 | {0,}, | ||
| 285 | }; | ||
| 286 | |||
| 287 | MODULE_DEVICE_TABLE(pci, nortel_pci_id_table); | ||
| 288 | |||
| 289 | static struct pci_driver nortel_pci_driver = { | ||
| 290 | .name = DRIVER_NAME, | ||
| 291 | .id_table = nortel_pci_id_table, | ||
| 292 | .probe = nortel_pci_init_one, | ||
| 293 | .remove = __devexit_p(nortel_pci_remove_one), | ||
| 294 | }; | ||
| 295 | |||
| 296 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | ||
| 297 | " (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)"; | ||
| 298 | MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>"); | ||
| 299 | MODULE_DESCRIPTION | ||
| 300 | ("Driver for wireless LAN cards using the Nortel PCI bridge"); | ||
| 301 | MODULE_LICENSE("Dual MPL/GPL"); | ||
| 302 | |||
| 303 | static int __init nortel_pci_init(void) | ||
| 304 | { | ||
| 305 | printk(KERN_DEBUG "%s\n", version); | ||
| 306 | return pci_module_init(&nortel_pci_driver); | ||
| 307 | } | ||
| 308 | |||
| 309 | static void __exit nortel_pci_exit(void) | ||
| 310 | { | ||
| 311 | pci_unregister_driver(&nortel_pci_driver); | ||
| 312 | ssleep(1); | ||
| 313 | } | ||
| 314 | |||
| 315 | module_init(nortel_pci_init); | ||
| 316 | module_exit(nortel_pci_exit); | ||
| 317 | |||
| 318 | /* | ||
| 319 | * Local variables: | ||
| 320 | * c-indent-level: 8 | ||
| 321 | * c-basic-offset: 8 | ||
| 322 | * tab-width: 8 | ||
| 323 | * End: | ||
| 324 | */ | ||
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c new file mode 100644 index 000000000000..39c6cdf7f3f7 --- /dev/null +++ b/drivers/net/wireless/spectrum_cs.c | |||
| @@ -0,0 +1,1120 @@ | |||
| 1 | /* | ||
| 2 | * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as | ||
| 3 | * Symbol Wireless Networker LA4100, CompactFlash cards by Socket | ||
| 4 | * Communications and Intel PRO/Wireless 2011B. | ||
| 5 | * | ||
| 6 | * The driver implements Symbol firmware download. The rest is handled | ||
| 7 | * in hermes.c and orinoco.c. | ||
| 8 | * | ||
| 9 | * Utilities for downloading the Symbol firmware are available at | ||
| 10 | * http://sourceforge.net/projects/orinoco/ | ||
| 11 | * | ||
| 12 | * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org> | ||
| 13 | * Portions based on orinoco_cs.c: | ||
| 14 | * Copyright (C) David Gibson, Linuxcare Australia | ||
| 15 | * Portions based on Spectrum24tDnld.c from original spectrum24 driver: | ||
| 16 | * Copyright (C) Symbol Technologies. | ||
| 17 | * | ||
| 18 | * See copyright notice in file orinoco.c. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #define DRIVER_NAME "spectrum_cs" | ||
| 22 | #define PFX DRIVER_NAME ": " | ||
| 23 | |||
| 24 | #include <linux/config.h> | ||
| 25 | #ifdef __IN_PCMCIA_PACKAGE__ | ||
| 26 | #include <pcmcia/k_compat.h> | ||
| 27 | #endif /* __IN_PCMCIA_PACKAGE__ */ | ||
| 28 | |||
| 29 | #include <linux/module.h> | ||
| 30 | #include <linux/kernel.h> | ||
| 31 | #include <linux/init.h> | ||
| 32 | #include <linux/sched.h> | ||
| 33 | #include <linux/ptrace.h> | ||
| 34 | #include <linux/slab.h> | ||
| 35 | #include <linux/string.h> | ||
| 36 | #include <linux/ioport.h> | ||
| 37 | #include <linux/netdevice.h> | ||
| 38 | #include <linux/if_arp.h> | ||
| 39 | #include <linux/etherdevice.h> | ||
| 40 | #include <linux/wireless.h> | ||
| 41 | |||
| 42 | #include <pcmcia/cs_types.h> | ||
| 43 | #include <pcmcia/cs.h> | ||
| 44 | #include <pcmcia/cistpl.h> | ||
| 45 | #include <pcmcia/cisreg.h> | ||
| 46 | #include <pcmcia/ds.h> | ||
| 47 | |||
| 48 | #include <asm/uaccess.h> | ||
| 49 | #include <asm/io.h> | ||
| 50 | #include <asm/system.h> | ||
| 51 | |||
| 52 | #include "orinoco.h" | ||
| 53 | |||
| 54 | /* | ||
| 55 | * If SPECTRUM_FW_INCLUDED is defined, the firmware is hardcoded into | ||
| 56 | * the driver. Use get_symbol_fw script to generate spectrum_fw.h and | ||
| 57 | * copy it to the same directory as spectrum_cs.c. | ||
| 58 | * | ||
| 59 | * If SPECTRUM_FW_INCLUDED is not defined, the firmware is loaded at the | ||
| 60 | * runtime using hotplug. Use the same get_symbol_fw script to generate | ||
| 61 | * files symbol_sp24t_prim_fw symbol_sp24t_sec_fw, copy them to the | ||
| 62 | * hotplug firmware directory (typically /usr/lib/hotplug/firmware) and | ||
| 63 | * make sure that you have hotplug installed and enabled in the kernel. | ||
| 64 | */ | ||
| 65 | /* #define SPECTRUM_FW_INCLUDED 1 */ | ||
| 66 | |||
| 67 | #ifdef SPECTRUM_FW_INCLUDED | ||
| 68 | /* Header with the firmware */ | ||
| 69 | #include "spectrum_fw.h" | ||
| 70 | #else /* !SPECTRUM_FW_INCLUDED */ | ||
| 71 | #include <linux/firmware.h> | ||
| 72 | static unsigned char *primsym; | ||
| 73 | static unsigned char *secsym; | ||
| 74 | static const char primary_fw_name[] = "symbol_sp24t_prim_fw"; | ||
| 75 | static const char secondary_fw_name[] = "symbol_sp24t_sec_fw"; | ||
| 76 | #endif /* !SPECTRUM_FW_INCLUDED */ | ||
| 77 | |||
| 78 | /********************************************************************/ | ||
| 79 | /* Module stuff */ | ||
| 80 | /********************************************************************/ | ||
| 81 | |||
| 82 | MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>"); | ||
| 83 | MODULE_DESCRIPTION("Driver for Symbol Spectrum24 Trilogy cards with firmware downloader"); | ||
| 84 | MODULE_LICENSE("Dual MPL/GPL"); | ||
| 85 | |||
| 86 | /* Module parameters */ | ||
| 87 | |||
| 88 | /* Some D-Link cards have buggy CIS. They do work at 5v properly, but | ||
| 89 | * don't have any CIS entry for it. This workaround it... */ | ||
| 90 | static int ignore_cis_vcc; /* = 0 */ | ||
| 91 | module_param(ignore_cis_vcc, int, 0); | ||
| 92 | MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket"); | ||
| 93 | |||
| 94 | /********************************************************************/ | ||
| 95 | /* Magic constants */ | ||
| 96 | /********************************************************************/ | ||
| 97 | |||
| 98 | /* | ||
| 99 | * The dev_info variable is the "key" that is used to match up this | ||
| 100 | * device driver with appropriate cards, through the card | ||
| 101 | * configuration database. | ||
| 102 | */ | ||
| 103 | static dev_info_t dev_info = DRIVER_NAME; | ||
| 104 | |||
| 105 | /********************************************************************/ | ||
| 106 | /* Data structures */ | ||
| 107 | /********************************************************************/ | ||
| 108 | |||
| 109 | /* PCMCIA specific device information (goes in the card field of | ||
| 110 | * struct orinoco_private */ | ||
| 111 | struct orinoco_pccard { | ||
| 112 | dev_link_t link; | ||
| 113 | dev_node_t node; | ||
| 114 | }; | ||
| 115 | |||
| 116 | /* | ||
| 117 | * A linked list of "instances" of the device. Each actual PCMCIA | ||
| 118 | * card corresponds to one device instance, and is described by one | ||
| 119 | * dev_link_t structure (defined in ds.h). | ||
| 120 | */ | ||
| 121 | static dev_link_t *dev_list; /* = NULL */ | ||
| 122 | |||
| 123 | /********************************************************************/ | ||
| 124 | /* Function prototypes */ | ||
| 125 | /********************************************************************/ | ||
| 126 | |||
| 127 | /* device methods */ | ||
| 128 | static int spectrum_cs_hard_reset(struct orinoco_private *priv); | ||
| 129 | |||
| 130 | /* PCMCIA gumpf */ | ||
| 131 | static void spectrum_cs_config(dev_link_t * link); | ||
| 132 | static void spectrum_cs_release(dev_link_t * link); | ||
| 133 | static int spectrum_cs_event(event_t event, int priority, | ||
| 134 | event_callback_args_t * args); | ||
| 135 | |||
| 136 | static dev_link_t *spectrum_cs_attach(void); | ||
| 137 | static void spectrum_cs_detach(dev_link_t *); | ||
| 138 | |||
| 139 | /********************************************************************/ | ||
| 140 | /* Firmware downloader */ | ||
| 141 | /********************************************************************/ | ||
| 142 | |||
| 143 | /* Position of PDA in the adapter memory */ | ||
| 144 | #define EEPROM_ADDR 0x3000 | ||
| 145 | #define EEPROM_LEN 0x200 | ||
| 146 | #define PDA_OFFSET 0x100 | ||
| 147 | |||
| 148 | #define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET) | ||
| 149 | #define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2) | ||
| 150 | |||
| 151 | /* Constants for the CISREG_CCSR register */ | ||
| 152 | #define HCR_RUN 0x07 /* run firmware after reset */ | ||
| 153 | #define HCR_IDLE 0x0E /* don't run firmware after reset */ | ||
| 154 | #define HCR_MEM16 0x10 /* memory width bit, should be preserved */ | ||
| 155 | |||
| 156 | /* | ||
| 157 | * AUX port access. To unlock the AUX port write the access keys to the | ||
| 158 | * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL | ||
| 159 | * register. Then read it and make sure it's HERMES_AUX_ENABLED. | ||
| 160 | */ | ||
| 161 | #define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */ | ||
| 162 | #define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */ | ||
| 163 | #define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */ | ||
| 164 | |||
| 165 | #define HERMES_AUX_PW0 0xFE01 | ||
| 166 | #define HERMES_AUX_PW1 0xDC23 | ||
| 167 | #define HERMES_AUX_PW2 0xBA45 | ||
| 168 | |||
| 169 | /* End markers */ | ||
| 170 | #define PDI_END 0x00000000 /* End of PDA */ | ||
| 171 | #define BLOCK_END 0xFFFFFFFF /* Last image block */ | ||
| 172 | #define TEXT_END 0x1A /* End of text header */ | ||
| 173 | |||
| 174 | /* | ||
| 175 | * The following structures have little-endian fields denoted by | ||
| 176 | * the leading underscore. Don't access them directly - use inline | ||
| 177 | * functions defined below. | ||
| 178 | */ | ||
| 179 | |||
| 180 | /* | ||
| 181 | * The binary image to be downloaded consists of series of data blocks. | ||
| 182 | * Each block has the following structure. | ||
| 183 | */ | ||
| 184 | struct dblock { | ||
| 185 | u32 _addr; /* adapter address where to write the block */ | ||
| 186 | u16 _len; /* length of the data only, in bytes */ | ||
| 187 | char data[0]; /* data to be written */ | ||
| 188 | } __attribute__ ((packed)); | ||
| 189 | |||
| 190 | /* | ||
| 191 | * Plug Data References are located in in the image after the last data | ||
| 192 | * block. They refer to areas in the adapter memory where the plug data | ||
| 193 | * items with matching ID should be written. | ||
| 194 | */ | ||
| 195 | struct pdr { | ||
| 196 | u32 _id; /* record ID */ | ||
| 197 | u32 _addr; /* adapter address where to write the data */ | ||
| 198 | u32 _len; /* expected length of the data, in bytes */ | ||
| 199 | char next[0]; /* next PDR starts here */ | ||
| 200 | } __attribute__ ((packed)); | ||
| 201 | |||
| 202 | |||
| 203 | /* | ||
| 204 | * Plug Data Items are located in the EEPROM read from the adapter by | ||
| 205 | * primary firmware. They refer to the device-specific data that should | ||
| 206 | * be plugged into the secondary firmware. | ||
| 207 | */ | ||
| 208 | struct pdi { | ||
| 209 | u16 _len; /* length of ID and data, in words */ | ||
| 210 | u16 _id; /* record ID */ | ||
| 211 | char data[0]; /* plug data */ | ||
| 212 | } __attribute__ ((packed));; | ||
| 213 | |||
| 214 | |||
| 215 | /* Functions for access to little-endian data */ | ||
| 216 | static inline u32 | ||
| 217 | dblock_addr(const struct dblock *blk) | ||
| 218 | { | ||
| 219 | return le32_to_cpu(blk->_addr); | ||
| 220 | } | ||
| 221 | |||
| 222 | static inline u32 | ||
| 223 | dblock_len(const struct dblock *blk) | ||
| 224 | { | ||
| 225 | return le16_to_cpu(blk->_len); | ||
| 226 | } | ||
| 227 | |||
| 228 | static inline u32 | ||
| 229 | pdr_id(const struct pdr *pdr) | ||
| 230 | { | ||
| 231 | return le32_to_cpu(pdr->_id); | ||
| 232 | } | ||
| 233 | |||
| 234 | static inline u32 | ||
| 235 | pdr_addr(const struct pdr *pdr) | ||
| 236 | { | ||
| 237 | return le32_to_cpu(pdr->_addr); | ||
| 238 | } | ||
| 239 | |||
| 240 | static inline u32 | ||
| 241 | pdr_len(const struct pdr *pdr) | ||
| 242 | { | ||
| 243 | return le32_to_cpu(pdr->_len); | ||
| 244 | } | ||
| 245 | |||
| 246 | static inline u32 | ||
| 247 | pdi_id(const struct pdi *pdi) | ||
| 248 | { | ||
| 249 | return le16_to_cpu(pdi->_id); | ||
| 250 | } | ||
| 251 | |||
| 252 | /* Return length of the data only, in bytes */ | ||
| 253 | static inline u32 | ||
| 254 | pdi_len(const struct pdi *pdi) | ||
| 255 | { | ||
| 256 | return 2 * (le16_to_cpu(pdi->_len) - 1); | ||
| 257 | } | ||
| 258 | |||
| 259 | |||
| 260 | /* Set address of the auxiliary port */ | ||
| 261 | static inline void | ||
| 262 | spectrum_aux_setaddr(hermes_t *hw, u32 addr) | ||
| 263 | { | ||
| 264 | hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); | ||
| 265 | hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); | ||
| 266 | } | ||
| 267 | |||
| 268 | |||
| 269 | /* Open access to the auxiliary port */ | ||
| 270 | static int | ||
| 271 | spectrum_aux_open(hermes_t *hw) | ||
| 272 | { | ||
| 273 | int i; | ||
| 274 | |||
| 275 | /* Already open? */ | ||
| 276 | if (hermes_read_reg(hw, HERMES_CONTROL) == HERMES_AUX_ENABLED) | ||
| 277 | return 0; | ||
| 278 | |||
| 279 | hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0); | ||
| 280 | hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1); | ||
| 281 | hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2); | ||
| 282 | hermes_write_reg(hw, HERMES_CONTROL, HERMES_AUX_ENABLE); | ||
| 283 | |||
| 284 | for (i = 0; i < 20; i++) { | ||
| 285 | udelay(10); | ||
| 286 | if (hermes_read_reg(hw, HERMES_CONTROL) == | ||
| 287 | HERMES_AUX_ENABLED) | ||
| 288 | return 0; | ||
| 289 | } | ||
| 290 | |||
| 291 | return -EBUSY; | ||
| 292 | } | ||
| 293 | |||
| 294 | |||
| 295 | #define CS_CHECK(fn, ret) \ | ||
| 296 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | ||
| 297 | |||
| 298 | /* | ||
| 299 | * Reset the card using configuration registers COR and CCSR. | ||
| 300 | * If IDLE is 1, stop the firmware, so that it can be safely rewritten. | ||
| 301 | */ | ||
| 302 | static int | ||
| 303 | spectrum_reset(dev_link_t *link, int idle) | ||
| 304 | { | ||
| 305 | int last_ret, last_fn; | ||
| 306 | conf_reg_t reg; | ||
| 307 | u_int save_cor; | ||
| 308 | |||
| 309 | /* Doing it if hardware is gone is guaranteed crash */ | ||
| 310 | if (!(link->state & DEV_CONFIG)) | ||
| 311 | return -ENODEV; | ||
| 312 | |||
| 313 | /* Save original COR value */ | ||
| 314 | reg.Function = 0; | ||
| 315 | reg.Action = CS_READ; | ||
| 316 | reg.Offset = CISREG_COR; | ||
| 317 | CS_CHECK(AccessConfigurationRegister, | ||
| 318 | pcmcia_access_configuration_register(link->handle, ®)); | ||
| 319 | save_cor = reg.Value; | ||
| 320 | |||
| 321 | /* Soft-Reset card */ | ||
| 322 | reg.Action = CS_WRITE; | ||
| 323 | reg.Offset = CISREG_COR; | ||
| 324 | reg.Value = (save_cor | COR_SOFT_RESET); | ||
| 325 | CS_CHECK(AccessConfigurationRegister, | ||
| 326 | pcmcia_access_configuration_register(link->handle, ®)); | ||
| 327 | udelay(1000); | ||
| 328 | |||
| 329 | /* Read CCSR */ | ||
| 330 | reg.Action = CS_READ; | ||
| 331 | reg.Offset = CISREG_CCSR; | ||
| 332 | CS_CHECK(AccessConfigurationRegister, | ||
| 333 | pcmcia_access_configuration_register(link->handle, ®)); | ||
| 334 | |||
| 335 | /* | ||
| 336 | * Start or stop the firmware. Memory width bit should be | ||
| 337 | * preserved from the value we've just read. | ||
| 338 | */ | ||
| 339 | reg.Action = CS_WRITE; | ||
| 340 | reg.Offset = CISREG_CCSR; | ||
| 341 | reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16); | ||
| 342 | CS_CHECK(AccessConfigurationRegister, | ||
| 343 | pcmcia_access_configuration_register(link->handle, ®)); | ||
| 344 | udelay(1000); | ||
| 345 | |||
| 346 | /* Restore original COR configuration index */ | ||
| 347 | reg.Action = CS_WRITE; | ||
| 348 | reg.Offset = CISREG_COR; | ||
| 349 | reg.Value = (save_cor & ~COR_SOFT_RESET); | ||
| 350 | CS_CHECK(AccessConfigurationRegister, | ||
| 351 | pcmcia_access_configuration_register(link->handle, ®)); | ||
| 352 | udelay(1000); | ||
| 353 | return 0; | ||
| 354 | |||
| 355 | cs_failed: | ||
| 356 | cs_error(link->handle, last_fn, last_ret); | ||
| 357 | return -ENODEV; | ||
| 358 | } | ||
| 359 | |||
| 360 | |||
| 361 | /* | ||
| 362 | * Scan PDR for the record with the specified RECORD_ID. | ||
| 363 | * If it's not found, return NULL. | ||
| 364 | */ | ||
| 365 | static struct pdr * | ||
| 366 | spectrum_find_pdr(struct pdr *first_pdr, u32 record_id) | ||
| 367 | { | ||
| 368 | struct pdr *pdr = first_pdr; | ||
| 369 | |||
| 370 | while (pdr_id(pdr) != PDI_END) { | ||
| 371 | /* | ||
| 372 | * PDR area is currently not terminated by PDI_END. | ||
| 373 | * It's followed by CRC records, which have the type | ||
| 374 | * field where PDR has length. The type can be 0 or 1. | ||
| 375 | */ | ||
| 376 | if (pdr_len(pdr) < 2) | ||
| 377 | return NULL; | ||
| 378 | |||
| 379 | /* If the record ID matches, we are done */ | ||
| 380 | if (pdr_id(pdr) == record_id) | ||
| 381 | return pdr; | ||
| 382 | |||
| 383 | pdr = (struct pdr *) pdr->next; | ||
| 384 | } | ||
| 385 | return NULL; | ||
| 386 | } | ||
| 387 | |||
| 388 | |||
| 389 | /* Process one Plug Data Item - find corresponding PDR and plug it */ | ||
| 390 | static int | ||
| 391 | spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi) | ||
| 392 | { | ||
| 393 | struct pdr *pdr; | ||
| 394 | |||
| 395 | /* Find the PDI corresponding to this PDR */ | ||
| 396 | pdr = spectrum_find_pdr(first_pdr, pdi_id(pdi)); | ||
| 397 | |||
| 398 | /* No match is found, safe to ignore */ | ||
| 399 | if (!pdr) | ||
| 400 | return 0; | ||
| 401 | |||
| 402 | /* Lengths of the data in PDI and PDR must match */ | ||
| 403 | if (pdi_len(pdi) != pdr_len(pdr)) | ||
| 404 | return -EINVAL; | ||
| 405 | |||
| 406 | /* do the actual plugging */ | ||
| 407 | spectrum_aux_setaddr(hw, pdr_addr(pdr)); | ||
| 408 | hermes_write_words(hw, HERMES_AUXDATA, pdi->data, | ||
| 409 | pdi_len(pdi) / 2); | ||
| 410 | |||
| 411 | return 0; | ||
| 412 | } | ||
| 413 | |||
| 414 | |||
| 415 | /* Read PDA from the adapter */ | ||
| 416 | static int | ||
| 417 | spectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len) | ||
| 418 | { | ||
| 419 | int ret; | ||
| 420 | int pda_size; | ||
| 421 | |||
| 422 | /* Issue command to read EEPROM */ | ||
| 423 | ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); | ||
| 424 | if (ret) | ||
| 425 | return ret; | ||
| 426 | |||
| 427 | /* Open auxiliary port */ | ||
| 428 | ret = spectrum_aux_open(hw); | ||
| 429 | if (ret) | ||
| 430 | return ret; | ||
| 431 | |||
| 432 | /* read PDA from EEPROM */ | ||
| 433 | spectrum_aux_setaddr(hw, PDA_ADDR); | ||
| 434 | hermes_read_words(hw, HERMES_AUXDATA, pda, pda_len / 2); | ||
| 435 | |||
| 436 | /* Check PDA length */ | ||
| 437 | pda_size = le16_to_cpu(pda[0]); | ||
| 438 | if (pda_size > pda_len) | ||
| 439 | return -EINVAL; | ||
| 440 | |||
| 441 | return 0; | ||
| 442 | } | ||
| 443 | |||
| 444 | |||
| 445 | /* Parse PDA and write the records into the adapter */ | ||
| 446 | static int | ||
| 447 | spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block, | ||
| 448 | u16 *pda) | ||
| 449 | { | ||
| 450 | int ret; | ||
| 451 | struct pdi *pdi; | ||
| 452 | struct pdr *first_pdr; | ||
| 453 | const struct dblock *blk = first_block; | ||
| 454 | |||
| 455 | /* Skip all blocks to locate Plug Data References */ | ||
| 456 | while (dblock_addr(blk) != BLOCK_END) | ||
| 457 | blk = (struct dblock *) &blk->data[dblock_len(blk)]; | ||
| 458 | |||
| 459 | first_pdr = (struct pdr *) blk; | ||
| 460 | |||
| 461 | /* Go through every PDI and plug them into the adapter */ | ||
| 462 | pdi = (struct pdi *) (pda + 2); | ||
| 463 | while (pdi_id(pdi) != PDI_END) { | ||
| 464 | ret = spectrum_plug_pdi(hw, first_pdr, pdi); | ||
| 465 | if (ret) | ||
| 466 | return ret; | ||
| 467 | |||
| 468 | /* Increment to the next PDI */ | ||
| 469 | pdi = (struct pdi *) &pdi->data[pdi_len(pdi)]; | ||
| 470 | } | ||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | |||
| 474 | |||
| 475 | /* Load firmware blocks into the adapter */ | ||
| 476 | static int | ||
| 477 | spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block) | ||
| 478 | { | ||
| 479 | const struct dblock *blk; | ||
| 480 | u32 blkaddr; | ||
| 481 | u32 blklen; | ||
| 482 | |||
| 483 | blk = first_block; | ||
| 484 | blkaddr = dblock_addr(blk); | ||
| 485 | blklen = dblock_len(blk); | ||
| 486 | |||
| 487 | while (dblock_addr(blk) != BLOCK_END) { | ||
| 488 | spectrum_aux_setaddr(hw, blkaddr); | ||
| 489 | hermes_write_words(hw, HERMES_AUXDATA, blk->data, | ||
| 490 | blklen / 2); | ||
| 491 | |||
| 492 | blk = (struct dblock *) &blk->data[blklen]; | ||
| 493 | blkaddr = dblock_addr(blk); | ||
| 494 | blklen = dblock_len(blk); | ||
| 495 | } | ||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | |||
| 500 | /* | ||
| 501 | * Process a firmware image - stop the card, load the firmware, reset | ||
| 502 | * the card and make sure it responds. For the secondary firmware take | ||
| 503 | * care of the PDA - read it and then write it on top of the firmware. | ||
| 504 | */ | ||
| 505 | static int | ||
| 506 | spectrum_dl_image(hermes_t *hw, dev_link_t *link, | ||
| 507 | const unsigned char *image) | ||
| 508 | { | ||
| 509 | int ret; | ||
| 510 | const unsigned char *ptr; | ||
| 511 | const struct dblock *first_block; | ||
| 512 | |||
| 513 | /* Plug Data Area (PDA) */ | ||
| 514 | u16 pda[PDA_WORDS]; | ||
| 515 | |||
| 516 | /* Binary block begins after the 0x1A marker */ | ||
| 517 | ptr = image; | ||
| 518 | while (*ptr++ != TEXT_END); | ||
| 519 | first_block = (const struct dblock *) ptr; | ||
| 520 | |||
| 521 | /* Read the PDA */ | ||
| 522 | if (image != primsym) { | ||
| 523 | ret = spectrum_read_pda(hw, pda, sizeof(pda)); | ||
| 524 | if (ret) | ||
| 525 | return ret; | ||
| 526 | } | ||
| 527 | |||
| 528 | /* Stop the firmware, so that it can be safely rewritten */ | ||
| 529 | ret = spectrum_reset(link, 1); | ||
| 530 | if (ret) | ||
| 531 | return ret; | ||
| 532 | |||
| 533 | /* Program the adapter with new firmware */ | ||
| 534 | ret = spectrum_load_blocks(hw, first_block); | ||
| 535 | if (ret) | ||
| 536 | return ret; | ||
| 537 | |||
| 538 | /* Write the PDA to the adapter */ | ||
| 539 | if (image != primsym) { | ||
| 540 | ret = spectrum_apply_pda(hw, first_block, pda); | ||
| 541 | if (ret) | ||
| 542 | return ret; | ||
| 543 | } | ||
| 544 | |||
| 545 | /* Run the firmware */ | ||
| 546 | ret = spectrum_reset(link, 0); | ||
| 547 | if (ret) | ||
| 548 | return ret; | ||
| 549 | |||
| 550 | /* Reset hermes chip and make sure it responds */ | ||
| 551 | ret = hermes_init(hw); | ||
| 552 | |||
| 553 | /* hermes_reset() should return 0 with the secondary firmware */ | ||
| 554 | if (image != primsym && ret != 0) | ||
| 555 | return -ENODEV; | ||
| 556 | |||
| 557 | /* And this should work with any firmware */ | ||
| 558 | if (!hermes_present(hw)) | ||
| 559 | return -ENODEV; | ||
| 560 | |||
| 561 | return 0; | ||
| 562 | } | ||
| 563 | |||
| 564 | |||
| 565 | /* | ||
| 566 | * Download the firmware into the card, this also does a PCMCIA soft | ||
| 567 | * reset on the card, to make sure it's in a sane state. | ||
| 568 | */ | ||
| 569 | static int | ||
| 570 | spectrum_dl_firmware(hermes_t *hw, dev_link_t *link) | ||
| 571 | { | ||
| 572 | int ret; | ||
| 573 | client_handle_t handle = link->handle; | ||
| 574 | |||
| 575 | #ifndef SPECTRUM_FW_INCLUDED | ||
| 576 | const struct firmware *fw_entry; | ||
| 577 | |||
| 578 | if (request_firmware(&fw_entry, primary_fw_name, | ||
| 579 | &handle_to_dev(handle)) == 0) { | ||
| 580 | primsym = fw_entry->data; | ||
| 581 | } else { | ||
| 582 | printk(KERN_ERR PFX "Cannot find firmware: %s\n", | ||
| 583 | primary_fw_name); | ||
| 584 | return -ENOENT; | ||
| 585 | } | ||
| 586 | |||
| 587 | if (request_firmware(&fw_entry, secondary_fw_name, | ||
| 588 | &handle_to_dev(handle)) == 0) { | ||
| 589 | secsym = fw_entry->data; | ||
| 590 | } else { | ||
| 591 | printk(KERN_ERR PFX "Cannot find firmware: %s\n", | ||
| 592 | secondary_fw_name); | ||
| 593 | return -ENOENT; | ||
| 594 | } | ||
| 595 | #endif | ||
| 596 | |||
| 597 | /* Load primary firmware */ | ||
| 598 | ret = spectrum_dl_image(hw, link, primsym); | ||
| 599 | if (ret) { | ||
| 600 | printk(KERN_ERR PFX "Primary firmware download failed\n"); | ||
| 601 | return ret; | ||
| 602 | } | ||
| 603 | |||
| 604 | /* Load secondary firmware */ | ||
| 605 | ret = spectrum_dl_image(hw, link, secsym); | ||
| 606 | |||
| 607 | if (ret) { | ||
| 608 | printk(KERN_ERR PFX "Secondary firmware download failed\n"); | ||
| 609 | } | ||
| 610 | |||
| 611 | return ret; | ||
| 612 | } | ||
| 613 | |||
| 614 | /********************************************************************/ | ||
| 615 | /* Device methods */ | ||
| 616 | /********************************************************************/ | ||
| 617 | |||
| 618 | static int | ||
| 619 | spectrum_cs_hard_reset(struct orinoco_private *priv) | ||
| 620 | { | ||
| 621 | struct orinoco_pccard *card = priv->card; | ||
| 622 | dev_link_t *link = &card->link; | ||
| 623 | int err; | ||
| 624 | |||
| 625 | if (!hermes_present(&priv->hw)) { | ||
| 626 | /* The firmware needs to be reloaded */ | ||
| 627 | if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) { | ||
| 628 | printk(KERN_ERR PFX "Firmware download failed\n"); | ||
| 629 | err = -ENODEV; | ||
| 630 | } | ||
| 631 | } else { | ||
| 632 | /* Soft reset using COR and HCR */ | ||
| 633 | spectrum_reset(link, 0); | ||
| 634 | } | ||
| 635 | |||
| 636 | return 0; | ||
| 637 | } | ||
| 638 | |||
| 639 | /********************************************************************/ | ||
| 640 | /* PCMCIA stuff */ | ||
| 641 | /********************************************************************/ | ||
| 642 | |||
| 643 | /* | ||
| 644 | * This creates an "instance" of the driver, allocating local data | ||
| 645 | * structures for one device. The device is registered with Card | ||
| 646 | * Services. | ||
| 647 | * | ||
| 648 | * The dev_link structure is initialized, but we don't actually | ||
| 649 | * configure the card at this point -- we wait until we receive a card | ||
| 650 | * insertion event. */ | ||
| 651 | static dev_link_t * | ||
| 652 | spectrum_cs_attach(void) | ||
| 653 | { | ||
| 654 | struct net_device *dev; | ||
| 655 | struct orinoco_private *priv; | ||
| 656 | struct orinoco_pccard *card; | ||
| 657 | dev_link_t *link; | ||
| 658 | client_reg_t client_reg; | ||
| 659 | int ret; | ||
| 660 | |||
| 661 | dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); | ||
| 662 | if (! dev) | ||
| 663 | return NULL; | ||
| 664 | priv = netdev_priv(dev); | ||
| 665 | card = priv->card; | ||
| 666 | |||
| 667 | /* Link both structures together */ | ||
| 668 | link = &card->link; | ||
| 669 | link->priv = dev; | ||
| 670 | |||
| 671 | /* Interrupt setup */ | ||
| 672 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; | ||
| 673 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | ||
| 674 | link->irq.Handler = orinoco_interrupt; | ||
| 675 | link->irq.Instance = dev; | ||
| 676 | |||
| 677 | /* General socket configuration defaults can go here. In this | ||
| 678 | * client, we assume very little, and rely on the CIS for | ||
| 679 | * almost everything. In most clients, many details (i.e., | ||
| 680 | * number, sizes, and attributes of IO windows) are fixed by | ||
| 681 | * the nature of the device, and can be hard-wired here. */ | ||
| 682 | link->conf.Attributes = 0; | ||
| 683 | link->conf.IntType = INT_MEMORY_AND_IO; | ||
| 684 | |||
| 685 | /* Register with Card Services */ | ||
| 686 | /* FIXME: need a lock? */ | ||
| 687 | link->next = dev_list; | ||
| 688 | dev_list = link; | ||
| 689 | |||
| 690 | client_reg.dev_info = &dev_info; | ||
| 691 | client_reg.Version = 0x0210; /* FIXME: what does this mean? */ | ||
| 692 | client_reg.event_callback_args.client_data = link; | ||
| 693 | |||
| 694 | ret = pcmcia_register_client(&link->handle, &client_reg); | ||
| 695 | if (ret != CS_SUCCESS) { | ||
| 696 | cs_error(link->handle, RegisterClient, ret); | ||
| 697 | spectrum_cs_detach(link); | ||
| 698 | return NULL; | ||
| 699 | } | ||
| 700 | |||
| 701 | return link; | ||
| 702 | } /* spectrum_cs_attach */ | ||
| 703 | |||
| 704 | /* | ||
| 705 | * This deletes a driver "instance". The device is de-registered with | ||
| 706 | * Card Services. If it has been released, all local data structures | ||
| 707 | * are freed. Otherwise, the structures will be freed when the device | ||
| 708 | * is released. | ||
| 709 | */ | ||
| 710 | static void spectrum_cs_detach(dev_link_t *link) | ||
| 711 | { | ||
| 712 | dev_link_t **linkp; | ||
| 713 | struct net_device *dev = link->priv; | ||
| 714 | |||
| 715 | /* Locate device structure */ | ||
| 716 | for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) | ||
| 717 | if (*linkp == link) | ||
| 718 | break; | ||
| 719 | |||
| 720 | BUG_ON(*linkp == NULL); | ||
| 721 | |||
| 722 | if (link->state & DEV_CONFIG) | ||
| 723 | spectrum_cs_release(link); | ||
| 724 | |||
| 725 | /* Break the link with Card Services */ | ||
| 726 | if (link->handle) | ||
| 727 | pcmcia_deregister_client(link->handle); | ||
| 728 | |||
| 729 | /* Unlink device structure, and free it */ | ||
| 730 | *linkp = link->next; | ||
| 731 | DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); | ||
| 732 | if (link->dev) { | ||
| 733 | DEBUG(0, PFX "About to unregister net device %p\n", | ||
| 734 | dev); | ||
| 735 | unregister_netdev(dev); | ||
| 736 | } | ||
| 737 | free_orinocodev(dev); | ||
| 738 | } /* spectrum_cs_detach */ | ||
| 739 | |||
| 740 | /* | ||
| 741 | * spectrum_cs_config() is scheduled to run after a CARD_INSERTION | ||
| 742 | * event is received, to configure the PCMCIA socket, and to make the | ||
| 743 | * device available to the system. | ||
| 744 | */ | ||
| 745 | |||
| 746 | static void | ||
| 747 | spectrum_cs_config(dev_link_t *link) | ||
| 748 | { | ||
| 749 | struct net_device *dev = link->priv; | ||
| 750 | client_handle_t handle = link->handle; | ||
| 751 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 752 | struct orinoco_pccard *card = priv->card; | ||
| 753 | hermes_t *hw = &priv->hw; | ||
| 754 | int last_fn, last_ret; | ||
| 755 | u_char buf[64]; | ||
| 756 | config_info_t conf; | ||
| 757 | cisinfo_t info; | ||
| 758 | tuple_t tuple; | ||
| 759 | cisparse_t parse; | ||
| 760 | void __iomem *mem; | ||
| 761 | |||
| 762 | CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info)); | ||
| 763 | |||
| 764 | /* | ||
| 765 | * This reads the card's CONFIG tuple to find its | ||
| 766 | * configuration registers. | ||
| 767 | */ | ||
| 768 | tuple.DesiredTuple = CISTPL_CONFIG; | ||
| 769 | tuple.Attributes = 0; | ||
| 770 | tuple.TupleData = buf; | ||
| 771 | tuple.TupleDataMax = sizeof(buf); | ||
| 772 | tuple.TupleOffset = 0; | ||
| 773 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
| 774 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | ||
| 775 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | ||
| 776 | link->conf.ConfigBase = parse.config.base; | ||
| 777 | link->conf.Present = parse.config.rmask[0]; | ||
| 778 | |||
| 779 | /* Configure card */ | ||
| 780 | link->state |= DEV_CONFIG; | ||
| 781 | |||
| 782 | /* Look up the current Vcc */ | ||
| 783 | CS_CHECK(GetConfigurationInfo, | ||
| 784 | pcmcia_get_configuration_info(handle, &conf)); | ||
| 785 | link->conf.Vcc = conf.Vcc; | ||
| 786 | |||
| 787 | /* | ||
| 788 | * In this loop, we scan the CIS for configuration table | ||
| 789 | * entries, each of which describes a valid card | ||
| 790 | * configuration, including voltage, IO window, memory window, | ||
| 791 | * and interrupt settings. | ||
| 792 | * | ||
| 793 | * We make no assumptions about the card to be configured: we | ||
| 794 | * use just the information available in the CIS. In an ideal | ||
| 795 | * world, this would work for any PCMCIA card, but it requires | ||
| 796 | * a complete and accurate CIS. In practice, a driver usually | ||
| 797 | * "knows" most of these things without consulting the CIS, | ||
| 798 | * and most client drivers will only use the CIS to fill in | ||
| 799 | * implementation-defined details. | ||
| 800 | */ | ||
| 801 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | ||
| 802 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | ||
| 803 | while (1) { | ||
| 804 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | ||
| 805 | cistpl_cftable_entry_t dflt = { .index = 0 }; | ||
| 806 | |||
| 807 | if ( (pcmcia_get_tuple_data(handle, &tuple) != 0) | ||
| 808 | || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0)) | ||
| 809 | goto next_entry; | ||
| 810 | |||
| 811 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | ||
| 812 | dflt = *cfg; | ||
| 813 | if (cfg->index == 0) | ||
| 814 | goto next_entry; | ||
| 815 | link->conf.ConfigIndex = cfg->index; | ||
| 816 | |||
| 817 | /* Does this card need audio output? */ | ||
| 818 | if (cfg->flags & CISTPL_CFTABLE_AUDIO) { | ||
| 819 | link->conf.Attributes |= CONF_ENABLE_SPKR; | ||
| 820 | link->conf.Status = CCSR_AUDIO_ENA; | ||
| 821 | } | ||
| 822 | |||
| 823 | /* Use power settings for Vcc and Vpp if present */ | ||
| 824 | /* Note that the CIS values need to be rescaled */ | ||
| 825 | if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
| 826 | if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
| 827 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
| 828 | if (!ignore_cis_vcc) | ||
| 829 | goto next_entry; | ||
| 830 | } | ||
| 831 | } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) { | ||
| 832 | if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) { | ||
| 833 | DEBUG(2, "spectrum_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n", conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000); | ||
| 834 | if(!ignore_cis_vcc) | ||
| 835 | goto next_entry; | ||
| 836 | } | ||
| 837 | } | ||
| 838 | |||
| 839 | if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
| 840 | link->conf.Vpp1 = link->conf.Vpp2 = | ||
| 841 | cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
| 842 | else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM)) | ||
| 843 | link->conf.Vpp1 = link->conf.Vpp2 = | ||
| 844 | dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000; | ||
| 845 | |||
| 846 | /* Do we need to allocate an interrupt? */ | ||
| 847 | link->conf.Attributes |= CONF_ENABLE_IRQ; | ||
| 848 | |||
| 849 | /* IO window settings */ | ||
| 850 | link->io.NumPorts1 = link->io.NumPorts2 = 0; | ||
| 851 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { | ||
| 852 | cistpl_io_t *io = | ||
| 853 | (cfg->io.nwin) ? &cfg->io : &dflt.io; | ||
| 854 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | ||
| 855 | if (!(io->flags & CISTPL_IO_8BIT)) | ||
| 856 | link->io.Attributes1 = | ||
| 857 | IO_DATA_PATH_WIDTH_16; | ||
| 858 | if (!(io->flags & CISTPL_IO_16BIT)) | ||
| 859 | link->io.Attributes1 = | ||
| 860 | IO_DATA_PATH_WIDTH_8; | ||
| 861 | link->io.IOAddrLines = | ||
| 862 | io->flags & CISTPL_IO_LINES_MASK; | ||
| 863 | link->io.BasePort1 = io->win[0].base; | ||
| 864 | link->io.NumPorts1 = io->win[0].len; | ||
| 865 | if (io->nwin > 1) { | ||
| 866 | link->io.Attributes2 = | ||
| 867 | link->io.Attributes1; | ||
| 868 | link->io.BasePort2 = io->win[1].base; | ||
| 869 | link->io.NumPorts2 = io->win[1].len; | ||
| 870 | } | ||
| 871 | |||
| 872 | /* This reserves IO space but doesn't actually enable it */ | ||
| 873 | if (pcmcia_request_io(link->handle, &link->io) != 0) | ||
| 874 | goto next_entry; | ||
| 875 | } | ||
| 876 | |||
| 877 | |||
| 878 | /* If we got this far, we're cool! */ | ||
| 879 | |||
| 880 | break; | ||
| 881 | |||
| 882 | next_entry: | ||
| 883 | if (link->io.NumPorts1) | ||
| 884 | pcmcia_release_io(link->handle, &link->io); | ||
| 885 | last_ret = pcmcia_get_next_tuple(handle, &tuple); | ||
| 886 | if (last_ret == CS_NO_MORE_ITEMS) { | ||
| 887 | printk(KERN_ERR PFX "GetNextTuple(): No matching " | ||
| 888 | "CIS configuration. Maybe you need the " | ||
| 889 | "ignore_cis_vcc=1 parameter.\n"); | ||
| 890 | goto cs_failed; | ||
| 891 | } | ||
| 892 | } | ||
| 893 | |||
| 894 | /* | ||
| 895 | * Allocate an interrupt line. Note that this does not assign | ||
| 896 | * a handler to the interrupt, unless the 'Handler' member of | ||
| 897 | * the irq structure is initialized. | ||
| 898 | */ | ||
| 899 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | ||
| 900 | |||
| 901 | /* We initialize the hermes structure before completing PCMCIA | ||
| 902 | * configuration just in case the interrupt handler gets | ||
| 903 | * called. */ | ||
| 904 | mem = ioport_map(link->io.BasePort1, link->io.NumPorts1); | ||
| 905 | if (!mem) | ||
| 906 | goto cs_failed; | ||
| 907 | |||
| 908 | hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); | ||
| 909 | |||
| 910 | /* | ||
| 911 | * This actually configures the PCMCIA socket -- setting up | ||
| 912 | * the I/O windows and the interrupt mapping, and putting the | ||
| 913 | * card and host interface into "Memory and IO" mode. | ||
| 914 | */ | ||
| 915 | CS_CHECK(RequestConfiguration, | ||
| 916 | pcmcia_request_configuration(link->handle, &link->conf)); | ||
| 917 | |||
| 918 | /* Ok, we have the configuration, prepare to register the netdev */ | ||
| 919 | dev->base_addr = link->io.BasePort1; | ||
| 920 | dev->irq = link->irq.AssignedIRQ; | ||
| 921 | SET_MODULE_OWNER(dev); | ||
| 922 | card->node.major = card->node.minor = 0; | ||
| 923 | |||
| 924 | /* Reset card and download firmware */ | ||
| 925 | if (spectrum_cs_hard_reset(priv) != 0) { | ||
| 926 | goto failed; | ||
| 927 | } | ||
| 928 | |||
| 929 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
| 930 | /* Tell the stack we exist */ | ||
| 931 | if (register_netdev(dev) != 0) { | ||
| 932 | printk(KERN_ERR PFX "register_netdev() failed\n"); | ||
| 933 | goto failed; | ||
| 934 | } | ||
| 935 | |||
| 936 | /* At this point, the dev_node_t structure(s) needs to be | ||
| 937 | * initialized and arranged in a linked list at link->dev. */ | ||
| 938 | strcpy(card->node.dev_name, dev->name); | ||
| 939 | link->dev = &card->node; /* link->dev being non-NULL is also | ||
| 940 | used to indicate that the | ||
| 941 | net_device has been registered */ | ||
| 942 | link->state &= ~DEV_CONFIG_PENDING; | ||
| 943 | |||
| 944 | /* Finally, report what we've done */ | ||
| 945 | printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d", | ||
| 946 | dev->name, link->conf.ConfigIndex, | ||
| 947 | link->conf.Vcc / 10, link->conf.Vcc % 10); | ||
| 948 | if (link->conf.Vpp1) | ||
| 949 | printk(", Vpp %d.%d", link->conf.Vpp1 / 10, | ||
| 950 | link->conf.Vpp1 % 10); | ||
| 951 | printk(", irq %d", link->irq.AssignedIRQ); | ||
| 952 | if (link->io.NumPorts1) | ||
| 953 | printk(", io 0x%04x-0x%04x", link->io.BasePort1, | ||
| 954 | link->io.BasePort1 + link->io.NumPorts1 - 1); | ||
| 955 | if (link->io.NumPorts2) | ||
| 956 | printk(" & 0x%04x-0x%04x", link->io.BasePort2, | ||
| 957 | link->io.BasePort2 + link->io.NumPorts2 - 1); | ||
| 958 | printk("\n"); | ||
| 959 | |||
| 960 | return; | ||
| 961 | |||
| 962 | cs_failed: | ||
| 963 | cs_error(link->handle, last_fn, last_ret); | ||
| 964 | |||
| 965 | failed: | ||
| 966 | spectrum_cs_release(link); | ||
| 967 | } /* spectrum_cs_config */ | ||
| 968 | |||
| 969 | /* | ||
| 970 | * After a card is removed, spectrum_cs_release() will unregister the | ||
| 971 | * device, and release the PCMCIA configuration. If the device is | ||
| 972 | * still open, this will be postponed until it is closed. | ||
| 973 | */ | ||
| 974 | static void | ||
| 975 | spectrum_cs_release(dev_link_t *link) | ||
| 976 | { | ||
| 977 | struct net_device *dev = link->priv; | ||
| 978 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 979 | unsigned long flags; | ||
| 980 | |||
| 981 | /* We're committed to taking the device away now, so mark the | ||
| 982 | * hardware as unavailable */ | ||
| 983 | spin_lock_irqsave(&priv->lock, flags); | ||
| 984 | priv->hw_unavailable++; | ||
| 985 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 986 | |||
| 987 | /* Don't bother checking to see if these succeed or not */ | ||
| 988 | pcmcia_release_configuration(link->handle); | ||
| 989 | if (link->io.NumPorts1) | ||
| 990 | pcmcia_release_io(link->handle, &link->io); | ||
| 991 | if (link->irq.AssignedIRQ) | ||
| 992 | pcmcia_release_irq(link->handle, &link->irq); | ||
| 993 | link->state &= ~DEV_CONFIG; | ||
| 994 | if (priv->hw.iobase) | ||
| 995 | ioport_unmap(priv->hw.iobase); | ||
| 996 | } /* spectrum_cs_release */ | ||
| 997 | |||
| 998 | /* | ||
| 999 | * The card status event handler. Mostly, this schedules other stuff | ||
| 1000 | * to run after an event is received. | ||
| 1001 | */ | ||
| 1002 | static int | ||
| 1003 | spectrum_cs_event(event_t event, int priority, | ||
| 1004 | event_callback_args_t * args) | ||
| 1005 | { | ||
| 1006 | dev_link_t *link = args->client_data; | ||
| 1007 | struct net_device *dev = link->priv; | ||
| 1008 | struct orinoco_private *priv = netdev_priv(dev); | ||
| 1009 | int err = 0; | ||
| 1010 | unsigned long flags; | ||
| 1011 | |||
| 1012 | switch (event) { | ||
| 1013 | case CS_EVENT_CARD_REMOVAL: | ||
| 1014 | link->state &= ~DEV_PRESENT; | ||
| 1015 | if (link->state & DEV_CONFIG) { | ||
| 1016 | unsigned long flags; | ||
| 1017 | |||
| 1018 | spin_lock_irqsave(&priv->lock, flags); | ||
| 1019 | netif_device_detach(dev); | ||
| 1020 | priv->hw_unavailable++; | ||
| 1021 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 1022 | } | ||
| 1023 | break; | ||
| 1024 | |||
| 1025 | case CS_EVENT_CARD_INSERTION: | ||
| 1026 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
| 1027 | spectrum_cs_config(link); | ||
| 1028 | break; | ||
| 1029 | |||
| 1030 | case CS_EVENT_PM_SUSPEND: | ||
| 1031 | link->state |= DEV_SUSPEND; | ||
| 1032 | /* Fall through... */ | ||
| 1033 | case CS_EVENT_RESET_PHYSICAL: | ||
| 1034 | /* Mark the device as stopped, to block IO until later */ | ||
| 1035 | if (link->state & DEV_CONFIG) { | ||
| 1036 | /* This is probably racy, but I can't think of | ||
| 1037 | a better way, short of rewriting the PCMCIA | ||
| 1038 | layer to not suck :-( */ | ||
| 1039 | spin_lock_irqsave(&priv->lock, flags); | ||
| 1040 | |||
| 1041 | err = __orinoco_down(dev); | ||
| 1042 | if (err) | ||
| 1043 | printk(KERN_WARNING "%s: %s: Error %d downing interface\n", | ||
| 1044 | dev->name, | ||
| 1045 | event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL", | ||
| 1046 | err); | ||
| 1047 | |||
| 1048 | netif_device_detach(dev); | ||
| 1049 | priv->hw_unavailable++; | ||
| 1050 | |||
| 1051 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 1052 | |||
| 1053 | pcmcia_release_configuration(link->handle); | ||
| 1054 | } | ||
| 1055 | break; | ||
| 1056 | |||
| 1057 | case CS_EVENT_PM_RESUME: | ||
| 1058 | link->state &= ~DEV_SUSPEND; | ||
| 1059 | /* Fall through... */ | ||
| 1060 | case CS_EVENT_CARD_RESET: | ||
| 1061 | if (link->state & DEV_CONFIG) { | ||
| 1062 | /* FIXME: should we double check that this is | ||
| 1063 | * the same card as we had before */ | ||
| 1064 | pcmcia_request_configuration(link->handle, &link->conf); | ||
| 1065 | netif_device_attach(dev); | ||
| 1066 | priv->hw_unavailable--; | ||
| 1067 | schedule_work(&priv->reset_work); | ||
| 1068 | } | ||
| 1069 | break; | ||
| 1070 | } | ||
| 1071 | |||
| 1072 | return err; | ||
| 1073 | } /* spectrum_cs_event */ | ||
| 1074 | |||
| 1075 | /********************************************************************/ | ||
| 1076 | /* Module initialization */ | ||
| 1077 | /********************************************************************/ | ||
| 1078 | |||
| 1079 | /* Can't be declared "const" or the whole __initdata section will | ||
| 1080 | * become const */ | ||
| 1081 | static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION | ||
| 1082 | " (Pavel Roskin <proski@gnu.org>," | ||
| 1083 | " David Gibson <hermes@gibson.dropbear.id.au>, et al)"; | ||
| 1084 | |||
| 1085 | static struct pcmcia_device_id spectrum_cs_ids[] = { | ||
| 1086 | PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4100 */ | ||
| 1087 | PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */ | ||
| 1088 | PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0001), /* Intel PRO/Wireless 2011B */ | ||
| 1089 | PCMCIA_DEVICE_NULL, | ||
| 1090 | }; | ||
| 1091 | MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids); | ||
| 1092 | |||
| 1093 | static struct pcmcia_driver orinoco_driver = { | ||
| 1094 | .owner = THIS_MODULE, | ||
| 1095 | .drv = { | ||
| 1096 | .name = DRIVER_NAME, | ||
| 1097 | }, | ||
| 1098 | .attach = spectrum_cs_attach, | ||
| 1099 | .event = spectrum_cs_event, | ||
| 1100 | .detach = spectrum_cs_detach, | ||
| 1101 | .id_table = spectrum_cs_ids, | ||
| 1102 | }; | ||
| 1103 | |||
| 1104 | static int __init | ||
| 1105 | init_spectrum_cs(void) | ||
| 1106 | { | ||
| 1107 | printk(KERN_DEBUG "%s\n", version); | ||
| 1108 | |||
| 1109 | return pcmcia_register_driver(&orinoco_driver); | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | static void __exit | ||
| 1113 | exit_spectrum_cs(void) | ||
| 1114 | { | ||
| 1115 | pcmcia_unregister_driver(&orinoco_driver); | ||
| 1116 | BUG_ON(dev_list != NULL); | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | module_init(init_spectrum_cs); | ||
| 1120 | module_exit(exit_spectrum_cs); | ||
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 289c1b5a8e4a..404b761e82ce 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -695,7 +695,7 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) | |||
| 695 | return ret; | 695 | return ret; |
| 696 | } | 696 | } |
| 697 | 697 | ||
| 698 | static int ethtool_get_perm_addr(struct net_device *dev, void *useraddr) | 698 | static int ethtool_get_perm_addr(struct net_device *dev, void __user *useraddr) |
| 699 | { | 699 | { |
| 700 | struct ethtool_perm_addr epaddr; | 700 | struct ethtool_perm_addr epaddr; |
| 701 | u8 *data; | 701 | u8 *data; |
