diff options
Diffstat (limited to 'drivers/net/pcmcia/3c589_cs.c')
-rw-r--r-- | drivers/net/pcmcia/3c589_cs.c | 122 |
1 files changed, 45 insertions, 77 deletions
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 3dba50849da7..875a0fe251e7 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c | |||
@@ -105,7 +105,7 @@ enum RxFilter { | |||
105 | #define TX_TIMEOUT ((400*HZ)/1000) | 105 | #define TX_TIMEOUT ((400*HZ)/1000) |
106 | 106 | ||
107 | struct el3_private { | 107 | struct el3_private { |
108 | dev_link_t link; | 108 | struct pcmcia_device *p_dev; |
109 | dev_node_t node; | 109 | dev_node_t node; |
110 | struct net_device_stats stats; | 110 | struct net_device_stats stats; |
111 | /* For transceiver monitoring */ | 111 | /* For transceiver monitoring */ |
@@ -142,8 +142,8 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; | |||
142 | 142 | ||
143 | /*====================================================================*/ | 143 | /*====================================================================*/ |
144 | 144 | ||
145 | static void tc589_config(dev_link_t *link); | 145 | static int tc589_config(struct pcmcia_device *link); |
146 | static void tc589_release(dev_link_t *link); | 146 | static void tc589_release(struct pcmcia_device *link); |
147 | 147 | ||
148 | static u16 read_eeprom(kio_addr_t ioaddr, int index); | 148 | static u16 read_eeprom(kio_addr_t ioaddr, int index); |
149 | static void tc589_reset(struct net_device *dev); | 149 | static void tc589_reset(struct net_device *dev); |
@@ -170,10 +170,9 @@ static void tc589_detach(struct pcmcia_device *p_dev); | |||
170 | 170 | ||
171 | ======================================================================*/ | 171 | ======================================================================*/ |
172 | 172 | ||
173 | static int tc589_attach(struct pcmcia_device *p_dev) | 173 | static int tc589_probe(struct pcmcia_device *link) |
174 | { | 174 | { |
175 | struct el3_private *lp; | 175 | struct el3_private *lp; |
176 | dev_link_t *link; | ||
177 | struct net_device *dev; | 176 | struct net_device *dev; |
178 | 177 | ||
179 | DEBUG(0, "3c589_attach()\n"); | 178 | DEBUG(0, "3c589_attach()\n"); |
@@ -183,8 +182,8 @@ static int tc589_attach(struct pcmcia_device *p_dev) | |||
183 | if (!dev) | 182 | if (!dev) |
184 | return -ENOMEM; | 183 | return -ENOMEM; |
185 | lp = netdev_priv(dev); | 184 | lp = netdev_priv(dev); |
186 | link = &lp->link; | ||
187 | link->priv = dev; | 185 | link->priv = dev; |
186 | lp->p_dev = link; | ||
188 | 187 | ||
189 | spin_lock_init(&lp->lock); | 188 | spin_lock_init(&lp->lock); |
190 | link->io.NumPorts1 = 16; | 189 | link->io.NumPorts1 = 16; |
@@ -194,7 +193,6 @@ static int tc589_attach(struct pcmcia_device *p_dev) | |||
194 | link->irq.Handler = &el3_interrupt; | 193 | link->irq.Handler = &el3_interrupt; |
195 | link->irq.Instance = dev; | 194 | link->irq.Instance = dev; |
196 | link->conf.Attributes = CONF_ENABLE_IRQ; | 195 | link->conf.Attributes = CONF_ENABLE_IRQ; |
197 | link->conf.Vcc = 50; | ||
198 | link->conf.IntType = INT_MEMORY_AND_IO; | 196 | link->conf.IntType = INT_MEMORY_AND_IO; |
199 | link->conf.ConfigIndex = 1; | 197 | link->conf.ConfigIndex = 1; |
200 | link->conf.Present = PRESENT_OPTION; | 198 | link->conf.Present = PRESENT_OPTION; |
@@ -213,13 +211,7 @@ static int tc589_attach(struct pcmcia_device *p_dev) | |||
213 | #endif | 211 | #endif |
214 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 212 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
215 | 213 | ||
216 | link->handle = p_dev; | 214 | return tc589_config(link); |
217 | p_dev->instance = link; | ||
218 | |||
219 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
220 | tc589_config(link); | ||
221 | |||
222 | return 0; | ||
223 | } /* tc589_attach */ | 215 | } /* tc589_attach */ |
224 | 216 | ||
225 | /*====================================================================== | 217 | /*====================================================================== |
@@ -231,18 +223,16 @@ static int tc589_attach(struct pcmcia_device *p_dev) | |||
231 | 223 | ||
232 | ======================================================================*/ | 224 | ======================================================================*/ |
233 | 225 | ||
234 | static void tc589_detach(struct pcmcia_device *p_dev) | 226 | static void tc589_detach(struct pcmcia_device *link) |
235 | { | 227 | { |
236 | dev_link_t *link = dev_to_instance(p_dev); | ||
237 | struct net_device *dev = link->priv; | 228 | struct net_device *dev = link->priv; |
238 | 229 | ||
239 | DEBUG(0, "3c589_detach(0x%p)\n", link); | 230 | DEBUG(0, "3c589_detach(0x%p)\n", link); |
240 | 231 | ||
241 | if (link->dev) | 232 | if (link->dev_node) |
242 | unregister_netdev(dev); | 233 | unregister_netdev(dev); |
243 | 234 | ||
244 | if (link->state & DEV_CONFIG) | 235 | tc589_release(link); |
245 | tc589_release(link); | ||
246 | 236 | ||
247 | free_netdev(dev); | 237 | free_netdev(dev); |
248 | } /* tc589_detach */ | 238 | } /* tc589_detach */ |
@@ -258,9 +248,8 @@ static void tc589_detach(struct pcmcia_device *p_dev) | |||
258 | #define CS_CHECK(fn, ret) \ | 248 | #define CS_CHECK(fn, ret) \ |
259 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 249 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
260 | 250 | ||
261 | static void tc589_config(dev_link_t *link) | 251 | static int tc589_config(struct pcmcia_device *link) |
262 | { | 252 | { |
263 | client_handle_t handle = link->handle; | ||
264 | struct net_device *dev = link->priv; | 253 | struct net_device *dev = link->priv; |
265 | struct el3_private *lp = netdev_priv(dev); | 254 | struct el3_private *lp = netdev_priv(dev); |
266 | tuple_t tuple; | 255 | tuple_t tuple; |
@@ -275,43 +264,40 @@ static void tc589_config(dev_link_t *link) | |||
275 | phys_addr = (u16 *)dev->dev_addr; | 264 | phys_addr = (u16 *)dev->dev_addr; |
276 | tuple.Attributes = 0; | 265 | tuple.Attributes = 0; |
277 | tuple.DesiredTuple = CISTPL_CONFIG; | 266 | tuple.DesiredTuple = CISTPL_CONFIG; |
278 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 267 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
279 | tuple.TupleData = (cisdata_t *)buf; | 268 | tuple.TupleData = (cisdata_t *)buf; |
280 | tuple.TupleDataMax = sizeof(buf); | 269 | tuple.TupleDataMax = sizeof(buf); |
281 | tuple.TupleOffset = 0; | 270 | tuple.TupleOffset = 0; |
282 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 271 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
283 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 272 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
284 | link->conf.ConfigBase = parse.config.base; | 273 | link->conf.ConfigBase = parse.config.base; |
285 | link->conf.Present = parse.config.rmask[0]; | 274 | link->conf.Present = parse.config.rmask[0]; |
286 | 275 | ||
287 | /* Is this a 3c562? */ | 276 | /* Is this a 3c562? */ |
288 | tuple.DesiredTuple = CISTPL_MANFID; | 277 | tuple.DesiredTuple = CISTPL_MANFID; |
289 | tuple.Attributes = TUPLE_RETURN_COMMON; | 278 | tuple.Attributes = TUPLE_RETURN_COMMON; |
290 | if ((pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) && | 279 | if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && |
291 | (pcmcia_get_tuple_data(handle, &tuple) == CS_SUCCESS)) { | 280 | (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) { |
292 | if (le16_to_cpu(buf[0]) != MANFID_3COM) | 281 | if (le16_to_cpu(buf[0]) != MANFID_3COM) |
293 | printk(KERN_INFO "3c589_cs: hmmm, is this really a " | 282 | printk(KERN_INFO "3c589_cs: hmmm, is this really a " |
294 | "3Com card??\n"); | 283 | "3Com card??\n"); |
295 | multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562); | 284 | multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562); |
296 | } | 285 | } |
297 | |||
298 | /* Configure card */ | ||
299 | link->state |= DEV_CONFIG; | ||
300 | 286 | ||
301 | /* For the 3c562, the base address must be xx00-xx7f */ | 287 | /* For the 3c562, the base address must be xx00-xx7f */ |
302 | link->io.IOAddrLines = 16; | 288 | link->io.IOAddrLines = 16; |
303 | for (i = j = 0; j < 0x400; j += 0x10) { | 289 | for (i = j = 0; j < 0x400; j += 0x10) { |
304 | if (multi && (j & 0x80)) continue; | 290 | if (multi && (j & 0x80)) continue; |
305 | link->io.BasePort1 = j ^ 0x300; | 291 | link->io.BasePort1 = j ^ 0x300; |
306 | i = pcmcia_request_io(link->handle, &link->io); | 292 | i = pcmcia_request_io(link, &link->io); |
307 | if (i == CS_SUCCESS) break; | 293 | if (i == CS_SUCCESS) break; |
308 | } | 294 | } |
309 | if (i != CS_SUCCESS) { | 295 | if (i != CS_SUCCESS) { |
310 | cs_error(link->handle, RequestIO, i); | 296 | cs_error(link, RequestIO, i); |
311 | goto failed; | 297 | goto failed; |
312 | } | 298 | } |
313 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); | 299 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
314 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); | 300 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
315 | 301 | ||
316 | dev->irq = link->irq.AssignedIRQ; | 302 | dev->irq = link->irq.AssignedIRQ; |
317 | dev->base_addr = link->io.BasePort1; | 303 | dev->base_addr = link->io.BasePort1; |
@@ -321,8 +307,8 @@ static void tc589_config(dev_link_t *link) | |||
321 | /* The 3c589 has an extra EEPROM for configuration info, including | 307 | /* The 3c589 has an extra EEPROM for configuration info, including |
322 | the hardware address. The 3c562 puts the address in the CIS. */ | 308 | the hardware address. The 3c562 puts the address in the CIS. */ |
323 | tuple.DesiredTuple = 0x88; | 309 | tuple.DesiredTuple = 0x88; |
324 | if (pcmcia_get_first_tuple(handle, &tuple) == CS_SUCCESS) { | 310 | if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) { |
325 | pcmcia_get_tuple_data(handle, &tuple); | 311 | pcmcia_get_tuple_data(link, &tuple); |
326 | for (i = 0; i < 3; i++) | 312 | for (i = 0; i < 3; i++) |
327 | phys_addr[i] = htons(buf[i]); | 313 | phys_addr[i] = htons(buf[i]); |
328 | } else { | 314 | } else { |
@@ -346,13 +332,12 @@ static void tc589_config(dev_link_t *link) | |||
346 | else | 332 | else |
347 | printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); | 333 | printk(KERN_ERR "3c589_cs: invalid if_port requested\n"); |
348 | 334 | ||
349 | link->dev = &lp->node; | 335 | link->dev_node = &lp->node; |
350 | link->state &= ~DEV_CONFIG_PENDING; | 336 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
351 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
352 | 337 | ||
353 | if (register_netdev(dev) != 0) { | 338 | if (register_netdev(dev) != 0) { |
354 | printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); | 339 | printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); |
355 | link->dev = NULL; | 340 | link->dev_node = NULL; |
356 | goto failed; | 341 | goto failed; |
357 | } | 342 | } |
358 | 343 | ||
@@ -366,14 +351,13 @@ static void tc589_config(dev_link_t *link) | |||
366 | printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n", | 351 | printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n", |
367 | (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], | 352 | (fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], |
368 | if_names[dev->if_port]); | 353 | if_names[dev->if_port]); |
369 | return; | 354 | return 0; |
370 | 355 | ||
371 | cs_failed: | 356 | cs_failed: |
372 | cs_error(link->handle, last_fn, last_ret); | 357 | cs_error(link, last_fn, last_ret); |
373 | failed: | 358 | failed: |
374 | tc589_release(link); | 359 | tc589_release(link); |
375 | return; | 360 | return -ENODEV; |
376 | |||
377 | } /* tc589_config */ | 361 | } /* tc589_config */ |
378 | 362 | ||
379 | /*====================================================================== | 363 | /*====================================================================== |
@@ -384,44 +368,28 @@ failed: | |||
384 | 368 | ||
385 | ======================================================================*/ | 369 | ======================================================================*/ |
386 | 370 | ||
387 | static void tc589_release(dev_link_t *link) | 371 | static void tc589_release(struct pcmcia_device *link) |
388 | { | 372 | { |
389 | DEBUG(0, "3c589_release(0x%p)\n", link); | 373 | pcmcia_disable_device(link); |
390 | |||
391 | pcmcia_release_configuration(link->handle); | ||
392 | pcmcia_release_io(link->handle, &link->io); | ||
393 | pcmcia_release_irq(link->handle, &link->irq); | ||
394 | |||
395 | link->state &= ~DEV_CONFIG; | ||
396 | } | 374 | } |
397 | 375 | ||
398 | static int tc589_suspend(struct pcmcia_device *p_dev) | 376 | static int tc589_suspend(struct pcmcia_device *link) |
399 | { | 377 | { |
400 | dev_link_t *link = dev_to_instance(p_dev); | ||
401 | struct net_device *dev = link->priv; | 378 | struct net_device *dev = link->priv; |
402 | 379 | ||
403 | link->state |= DEV_SUSPEND; | 380 | if (link->open) |
404 | if (link->state & DEV_CONFIG) { | 381 | netif_device_detach(dev); |
405 | if (link->open) | ||
406 | netif_device_detach(dev); | ||
407 | pcmcia_release_configuration(link->handle); | ||
408 | } | ||
409 | 382 | ||
410 | return 0; | 383 | return 0; |
411 | } | 384 | } |
412 | 385 | ||
413 | static int tc589_resume(struct pcmcia_device *p_dev) | 386 | static int tc589_resume(struct pcmcia_device *link) |
414 | { | 387 | { |
415 | dev_link_t *link = dev_to_instance(p_dev); | ||
416 | struct net_device *dev = link->priv; | 388 | struct net_device *dev = link->priv; |
417 | 389 | ||
418 | link->state &= ~DEV_SUSPEND; | 390 | if (link->open) { |
419 | if (link->state & DEV_CONFIG) { | 391 | tc589_reset(dev); |
420 | pcmcia_request_configuration(link->handle, &link->conf); | 392 | netif_device_attach(dev); |
421 | if (link->open) { | ||
422 | tc589_reset(dev); | ||
423 | netif_device_attach(dev); | ||
424 | } | ||
425 | } | 393 | } |
426 | 394 | ||
427 | return 0; | 395 | return 0; |
@@ -587,9 +555,9 @@ static int el3_config(struct net_device *dev, struct ifmap *map) | |||
587 | static int el3_open(struct net_device *dev) | 555 | static int el3_open(struct net_device *dev) |
588 | { | 556 | { |
589 | struct el3_private *lp = netdev_priv(dev); | 557 | struct el3_private *lp = netdev_priv(dev); |
590 | dev_link_t *link = &lp->link; | 558 | struct pcmcia_device *link = lp->p_dev; |
591 | 559 | ||
592 | if (!DEV_OK(link)) | 560 | if (!pcmcia_dev_present(link)) |
593 | return -ENODEV; | 561 | return -ENODEV; |
594 | 562 | ||
595 | link->open++; | 563 | link->open++; |
@@ -848,9 +816,9 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev) | |||
848 | { | 816 | { |
849 | struct el3_private *lp = netdev_priv(dev); | 817 | struct el3_private *lp = netdev_priv(dev); |
850 | unsigned long flags; | 818 | unsigned long flags; |
851 | dev_link_t *link = &lp->link; | 819 | struct pcmcia_device *link = lp->p_dev; |
852 | 820 | ||
853 | if (DEV_OK(link)) { | 821 | if (pcmcia_dev_present(link)) { |
854 | spin_lock_irqsave(&lp->lock, flags); | 822 | spin_lock_irqsave(&lp->lock, flags); |
855 | update_stats(dev); | 823 | update_stats(dev); |
856 | spin_unlock_irqrestore(&lp->lock, flags); | 824 | spin_unlock_irqrestore(&lp->lock, flags); |
@@ -950,11 +918,11 @@ static int el3_rx(struct net_device *dev) | |||
950 | static void set_multicast_list(struct net_device *dev) | 918 | static void set_multicast_list(struct net_device *dev) |
951 | { | 919 | { |
952 | struct el3_private *lp = netdev_priv(dev); | 920 | struct el3_private *lp = netdev_priv(dev); |
953 | dev_link_t *link = &lp->link; | 921 | struct pcmcia_device *link = lp->p_dev; |
954 | kio_addr_t ioaddr = dev->base_addr; | 922 | kio_addr_t ioaddr = dev->base_addr; |
955 | u16 opts = SetRxFilter | RxStation | RxBroadcast; | 923 | u16 opts = SetRxFilter | RxStation | RxBroadcast; |
956 | 924 | ||
957 | if (!(DEV_OK(link))) return; | 925 | if (!pcmcia_dev_present(link)) return; |
958 | if (dev->flags & IFF_PROMISC) | 926 | if (dev->flags & IFF_PROMISC) |
959 | opts |= RxMulticast | RxProm; | 927 | opts |= RxMulticast | RxProm; |
960 | else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) | 928 | else if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) |
@@ -965,12 +933,12 @@ static void set_multicast_list(struct net_device *dev) | |||
965 | static int el3_close(struct net_device *dev) | 933 | static int el3_close(struct net_device *dev) |
966 | { | 934 | { |
967 | struct el3_private *lp = netdev_priv(dev); | 935 | struct el3_private *lp = netdev_priv(dev); |
968 | dev_link_t *link = &lp->link; | 936 | struct pcmcia_device *link = lp->p_dev; |
969 | kio_addr_t ioaddr = dev->base_addr; | 937 | kio_addr_t ioaddr = dev->base_addr; |
970 | 938 | ||
971 | DEBUG(1, "%s: shutting down ethercard.\n", dev->name); | 939 | DEBUG(1, "%s: shutting down ethercard.\n", dev->name); |
972 | 940 | ||
973 | if (DEV_OK(link)) { | 941 | if (pcmcia_dev_present(link)) { |
974 | /* Turn off statistics ASAP. We update lp->stats below. */ | 942 | /* Turn off statistics ASAP. We update lp->stats below. */ |
975 | outw(StatsDisable, ioaddr + EL3_CMD); | 943 | outw(StatsDisable, ioaddr + EL3_CMD); |
976 | 944 | ||
@@ -1020,7 +988,7 @@ static struct pcmcia_driver tc589_driver = { | |||
1020 | .drv = { | 988 | .drv = { |
1021 | .name = "3c589_cs", | 989 | .name = "3c589_cs", |
1022 | }, | 990 | }, |
1023 | .probe = tc589_attach, | 991 | .probe = tc589_probe, |
1024 | .remove = tc589_detach, | 992 | .remove = tc589_detach, |
1025 | .id_table = tc589_ids, | 993 | .id_table = tc589_ids, |
1026 | .suspend = tc589_suspend, | 994 | .suspend = tc589_suspend, |