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 /drivers/net | |
parent | 1e231efe50ffe4d291be24d2fe393188de9c4b08 (diff) | |
parent | 3a48c4c2d52a08e12319ab7caacad0a9b88e6cb4 (diff) |
Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
Diffstat (limited to 'drivers/net')
-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 |
20 files changed, 1735 insertions, 233 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); | ||