diff options
Diffstat (limited to 'drivers/net/pcmcia/axnet_cs.c')
-rw-r--r-- | drivers/net/pcmcia/axnet_cs.c | 126 |
1 files changed, 45 insertions, 81 deletions
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 1cc94b2d76c1..56233afcb2b3 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c | |||
@@ -86,8 +86,8 @@ static char *version = | |||
86 | 86 | ||
87 | /*====================================================================*/ | 87 | /*====================================================================*/ |
88 | 88 | ||
89 | static void axnet_config(dev_link_t *link); | 89 | static int axnet_config(struct pcmcia_device *link); |
90 | static void axnet_release(dev_link_t *link); | 90 | static void axnet_release(struct pcmcia_device *link); |
91 | static int axnet_open(struct net_device *dev); | 91 | static int axnet_open(struct net_device *dev); |
92 | static int axnet_close(struct net_device *dev); | 92 | static int axnet_close(struct net_device *dev); |
93 | static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 93 | static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
@@ -117,7 +117,7 @@ static irqreturn_t ax_interrupt(int irq, void *dev_id, struct pt_regs *regs); | |||
117 | /*====================================================================*/ | 117 | /*====================================================================*/ |
118 | 118 | ||
119 | typedef struct axnet_dev_t { | 119 | typedef struct axnet_dev_t { |
120 | dev_link_t link; | 120 | struct pcmcia_device *p_dev; |
121 | dev_node_t node; | 121 | dev_node_t node; |
122 | caddr_t base; | 122 | caddr_t base; |
123 | struct timer_list watchdog; | 123 | struct timer_list watchdog; |
@@ -142,10 +142,9 @@ static inline axnet_dev_t *PRIV(struct net_device *dev) | |||
142 | 142 | ||
143 | ======================================================================*/ | 143 | ======================================================================*/ |
144 | 144 | ||
145 | static int axnet_attach(struct pcmcia_device *p_dev) | 145 | static int axnet_probe(struct pcmcia_device *link) |
146 | { | 146 | { |
147 | axnet_dev_t *info; | 147 | axnet_dev_t *info; |
148 | dev_link_t *link; | ||
149 | struct net_device *dev; | 148 | struct net_device *dev; |
150 | 149 | ||
151 | DEBUG(0, "axnet_attach()\n"); | 150 | DEBUG(0, "axnet_attach()\n"); |
@@ -157,7 +156,7 @@ static int axnet_attach(struct pcmcia_device *p_dev) | |||
157 | return -ENOMEM; | 156 | return -ENOMEM; |
158 | 157 | ||
159 | info = PRIV(dev); | 158 | info = PRIV(dev); |
160 | link = &info->link; | 159 | info->p_dev = link; |
161 | link->priv = dev; | 160 | link->priv = dev; |
162 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | 161 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; |
163 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | 162 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; |
@@ -169,13 +168,7 @@ static int axnet_attach(struct pcmcia_device *p_dev) | |||
169 | dev->do_ioctl = &axnet_ioctl; | 168 | dev->do_ioctl = &axnet_ioctl; |
170 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 169 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
171 | 170 | ||
172 | link->handle = p_dev; | 171 | return axnet_config(link); |
173 | p_dev->instance = link; | ||
174 | |||
175 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
176 | axnet_config(link); | ||
177 | |||
178 | return 0; | ||
179 | } /* axnet_attach */ | 172 | } /* axnet_attach */ |
180 | 173 | ||
181 | /*====================================================================== | 174 | /*====================================================================== |
@@ -187,18 +180,16 @@ static int axnet_attach(struct pcmcia_device *p_dev) | |||
187 | 180 | ||
188 | ======================================================================*/ | 181 | ======================================================================*/ |
189 | 182 | ||
190 | static void axnet_detach(struct pcmcia_device *p_dev) | 183 | static void axnet_detach(struct pcmcia_device *link) |
191 | { | 184 | { |
192 | dev_link_t *link = dev_to_instance(p_dev); | ||
193 | struct net_device *dev = link->priv; | 185 | struct net_device *dev = link->priv; |
194 | 186 | ||
195 | DEBUG(0, "axnet_detach(0x%p)\n", link); | 187 | DEBUG(0, "axnet_detach(0x%p)\n", link); |
196 | 188 | ||
197 | if (link->dev) | 189 | if (link->dev_node) |
198 | unregister_netdev(dev); | 190 | unregister_netdev(dev); |
199 | 191 | ||
200 | if (link->state & DEV_CONFIG) | 192 | axnet_release(link); |
201 | axnet_release(link); | ||
202 | 193 | ||
203 | free_netdev(dev); | 194 | free_netdev(dev); |
204 | } /* axnet_detach */ | 195 | } /* axnet_detach */ |
@@ -209,7 +200,7 @@ static void axnet_detach(struct pcmcia_device *p_dev) | |||
209 | 200 | ||
210 | ======================================================================*/ | 201 | ======================================================================*/ |
211 | 202 | ||
212 | static int get_prom(dev_link_t *link) | 203 | static int get_prom(struct pcmcia_device *link) |
213 | { | 204 | { |
214 | struct net_device *dev = link->priv; | 205 | struct net_device *dev = link->priv; |
215 | kio_addr_t ioaddr = dev->base_addr; | 206 | kio_addr_t ioaddr = dev->base_addr; |
@@ -263,7 +254,7 @@ static int get_prom(dev_link_t *link) | |||
263 | #define CS_CHECK(fn, ret) \ | 254 | #define CS_CHECK(fn, ret) \ |
264 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | 255 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) |
265 | 256 | ||
266 | static int try_io_port(dev_link_t *link) | 257 | static int try_io_port(struct pcmcia_device *link) |
267 | { | 258 | { |
268 | int j, ret; | 259 | int j, ret; |
269 | if (link->io.NumPorts1 == 32) { | 260 | if (link->io.NumPorts1 == 32) { |
@@ -284,25 +275,23 @@ static int try_io_port(dev_link_t *link) | |||
284 | for (j = 0; j < 0x400; j += 0x20) { | 275 | for (j = 0; j < 0x400; j += 0x20) { |
285 | link->io.BasePort1 = j ^ 0x300; | 276 | link->io.BasePort1 = j ^ 0x300; |
286 | link->io.BasePort2 = (j ^ 0x300) + 0x10; | 277 | link->io.BasePort2 = (j ^ 0x300) + 0x10; |
287 | ret = pcmcia_request_io(link->handle, &link->io); | 278 | ret = pcmcia_request_io(link, &link->io); |
288 | if (ret == CS_SUCCESS) return ret; | 279 | if (ret == CS_SUCCESS) return ret; |
289 | } | 280 | } |
290 | return ret; | 281 | return ret; |
291 | } else { | 282 | } else { |
292 | return pcmcia_request_io(link->handle, &link->io); | 283 | return pcmcia_request_io(link, &link->io); |
293 | } | 284 | } |
294 | } | 285 | } |
295 | 286 | ||
296 | static void axnet_config(dev_link_t *link) | 287 | static int axnet_config(struct pcmcia_device *link) |
297 | { | 288 | { |
298 | client_handle_t handle = link->handle; | ||
299 | struct net_device *dev = link->priv; | 289 | struct net_device *dev = link->priv; |
300 | axnet_dev_t *info = PRIV(dev); | 290 | axnet_dev_t *info = PRIV(dev); |
301 | tuple_t tuple; | 291 | tuple_t tuple; |
302 | cisparse_t parse; | 292 | cisparse_t parse; |
303 | int i, j, last_ret, last_fn; | 293 | int i, j, last_ret, last_fn; |
304 | u_short buf[64]; | 294 | u_short buf[64]; |
305 | config_info_t conf; | ||
306 | 295 | ||
307 | DEBUG(0, "axnet_config(0x%p)\n", link); | 296 | DEBUG(0, "axnet_config(0x%p)\n", link); |
308 | 297 | ||
@@ -311,29 +300,22 @@ static void axnet_config(dev_link_t *link) | |||
311 | tuple.TupleDataMax = sizeof(buf); | 300 | tuple.TupleDataMax = sizeof(buf); |
312 | tuple.TupleOffset = 0; | 301 | tuple.TupleOffset = 0; |
313 | tuple.DesiredTuple = CISTPL_CONFIG; | 302 | tuple.DesiredTuple = CISTPL_CONFIG; |
314 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 303 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
315 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); | 304 | CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); |
316 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); | 305 | CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); |
317 | link->conf.ConfigBase = parse.config.base; | 306 | link->conf.ConfigBase = parse.config.base; |
318 | /* don't trust the CIS on this; Linksys got it wrong */ | 307 | /* don't trust the CIS on this; Linksys got it wrong */ |
319 | link->conf.Present = 0x63; | 308 | link->conf.Present = 0x63; |
320 | 309 | ||
321 | /* Configure card */ | ||
322 | link->state |= DEV_CONFIG; | ||
323 | |||
324 | /* Look up current Vcc */ | ||
325 | CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); | ||
326 | link->conf.Vcc = conf.Vcc; | ||
327 | |||
328 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | 310 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; |
329 | tuple.Attributes = 0; | 311 | tuple.Attributes = 0; |
330 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); | 312 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); |
331 | while (last_ret == CS_SUCCESS) { | 313 | while (last_ret == CS_SUCCESS) { |
332 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); | 314 | cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); |
333 | cistpl_io_t *io = &(parse.cftable_entry.io); | 315 | cistpl_io_t *io = &(parse.cftable_entry.io); |
334 | 316 | ||
335 | if (pcmcia_get_tuple_data(handle, &tuple) != 0 || | 317 | if (pcmcia_get_tuple_data(link, &tuple) != 0 || |
336 | pcmcia_parse_tuple(handle, &tuple, &parse) != 0 || | 318 | pcmcia_parse_tuple(link, &tuple, &parse) != 0 || |
337 | cfg->index == 0 || cfg->io.nwin == 0) | 319 | cfg->index == 0 || cfg->io.nwin == 0) |
338 | goto next_entry; | 320 | goto next_entry; |
339 | 321 | ||
@@ -355,21 +337,21 @@ static void axnet_config(dev_link_t *link) | |||
355 | if (last_ret == CS_SUCCESS) break; | 337 | if (last_ret == CS_SUCCESS) break; |
356 | } | 338 | } |
357 | next_entry: | 339 | next_entry: |
358 | last_ret = pcmcia_get_next_tuple(handle, &tuple); | 340 | last_ret = pcmcia_get_next_tuple(link, &tuple); |
359 | } | 341 | } |
360 | if (last_ret != CS_SUCCESS) { | 342 | if (last_ret != CS_SUCCESS) { |
361 | cs_error(handle, RequestIO, last_ret); | 343 | cs_error(link, RequestIO, last_ret); |
362 | goto failed; | 344 | goto failed; |
363 | } | 345 | } |
364 | 346 | ||
365 | CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq)); | 347 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); |
366 | 348 | ||
367 | if (link->io.NumPorts2 == 8) { | 349 | if (link->io.NumPorts2 == 8) { |
368 | link->conf.Attributes |= CONF_ENABLE_SPKR; | 350 | link->conf.Attributes |= CONF_ENABLE_SPKR; |
369 | link->conf.Status = CCSR_AUDIO_ENA; | 351 | link->conf.Status = CCSR_AUDIO_ENA; |
370 | } | 352 | } |
371 | 353 | ||
372 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf)); | 354 | CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); |
373 | dev->irq = link->irq.AssignedIRQ; | 355 | dev->irq = link->irq.AssignedIRQ; |
374 | dev->base_addr = link->io.BasePort1; | 356 | dev->base_addr = link->io.BasePort1; |
375 | 357 | ||
@@ -406,7 +388,7 @@ static void axnet_config(dev_link_t *link) | |||
406 | Bit 2 of CCSR is active low. */ | 388 | Bit 2 of CCSR is active low. */ |
407 | if (i == 32) { | 389 | if (i == 32) { |
408 | conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 }; | 390 | conf_reg_t reg = { 0, CS_WRITE, CISREG_CCSR, 0x04 }; |
409 | pcmcia_access_configuration_register(link->handle, ®); | 391 | pcmcia_access_configuration_register(link, ®); |
410 | for (i = 0; i < 32; i++) { | 392 | for (i = 0; i < 32; i++) { |
411 | j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); | 393 | j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); |
412 | if ((j != 0) && (j != 0xffff)) break; | 394 | if ((j != 0) && (j != 0xffff)) break; |
@@ -414,13 +396,12 @@ static void axnet_config(dev_link_t *link) | |||
414 | } | 396 | } |
415 | 397 | ||
416 | info->phy_id = (i < 32) ? i : -1; | 398 | info->phy_id = (i < 32) ? i : -1; |
417 | link->dev = &info->node; | 399 | link->dev_node = &info->node; |
418 | link->state &= ~DEV_CONFIG_PENDING; | 400 | SET_NETDEV_DEV(dev, &handle_to_dev(link)); |
419 | SET_NETDEV_DEV(dev, &handle_to_dev(handle)); | ||
420 | 401 | ||
421 | if (register_netdev(dev) != 0) { | 402 | if (register_netdev(dev) != 0) { |
422 | printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n"); | 403 | printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n"); |
423 | link->dev = NULL; | 404 | link->dev_node = NULL; |
424 | goto failed; | 405 | goto failed; |
425 | } | 406 | } |
426 | 407 | ||
@@ -436,14 +417,13 @@ static void axnet_config(dev_link_t *link) | |||
436 | } else { | 417 | } else { |
437 | printk(KERN_NOTICE " No MII transceivers found!\n"); | 418 | printk(KERN_NOTICE " No MII transceivers found!\n"); |
438 | } | 419 | } |
439 | return; | 420 | return 0; |
440 | 421 | ||
441 | cs_failed: | 422 | cs_failed: |
442 | cs_error(link->handle, last_fn, last_ret); | 423 | cs_error(link, last_fn, last_ret); |
443 | failed: | 424 | failed: |
444 | axnet_release(link); | 425 | axnet_release(link); |
445 | link->state &= ~DEV_CONFIG_PENDING; | 426 | return -ENODEV; |
446 | return; | ||
447 | } /* axnet_config */ | 427 | } /* axnet_config */ |
448 | 428 | ||
449 | /*====================================================================== | 429 | /*====================================================================== |
@@ -454,45 +434,29 @@ failed: | |||
454 | 434 | ||
455 | ======================================================================*/ | 435 | ======================================================================*/ |
456 | 436 | ||
457 | static void axnet_release(dev_link_t *link) | 437 | static void axnet_release(struct pcmcia_device *link) |
458 | { | 438 | { |
459 | DEBUG(0, "axnet_release(0x%p)\n", link); | 439 | pcmcia_disable_device(link); |
460 | |||
461 | pcmcia_release_configuration(link->handle); | ||
462 | pcmcia_release_io(link->handle, &link->io); | ||
463 | pcmcia_release_irq(link->handle, &link->irq); | ||
464 | |||
465 | link->state &= ~DEV_CONFIG; | ||
466 | } | 440 | } |
467 | 441 | ||
468 | static int axnet_suspend(struct pcmcia_device *p_dev) | 442 | static int axnet_suspend(struct pcmcia_device *link) |
469 | { | 443 | { |
470 | dev_link_t *link = dev_to_instance(p_dev); | ||
471 | struct net_device *dev = link->priv; | 444 | struct net_device *dev = link->priv; |
472 | 445 | ||
473 | link->state |= DEV_SUSPEND; | 446 | if (link->open) |
474 | if (link->state & DEV_CONFIG) { | 447 | netif_device_detach(dev); |
475 | if (link->open) | ||
476 | netif_device_detach(dev); | ||
477 | pcmcia_release_configuration(link->handle); | ||
478 | } | ||
479 | 448 | ||
480 | return 0; | 449 | return 0; |
481 | } | 450 | } |
482 | 451 | ||
483 | static int axnet_resume(struct pcmcia_device *p_dev) | 452 | static int axnet_resume(struct pcmcia_device *link) |
484 | { | 453 | { |
485 | dev_link_t *link = dev_to_instance(p_dev); | ||
486 | struct net_device *dev = link->priv; | 454 | struct net_device *dev = link->priv; |
487 | 455 | ||
488 | link->state &= ~DEV_SUSPEND; | 456 | if (link->open) { |
489 | if (link->state & DEV_CONFIG) { | 457 | axnet_reset_8390(dev); |
490 | pcmcia_request_configuration(link->handle, &link->conf); | 458 | AX88190_init(dev, 1); |
491 | if (link->open) { | 459 | netif_device_attach(dev); |
492 | axnet_reset_8390(dev); | ||
493 | AX88190_init(dev, 1); | ||
494 | netif_device_attach(dev); | ||
495 | } | ||
496 | } | 460 | } |
497 | 461 | ||
498 | return 0; | 462 | return 0; |
@@ -562,11 +526,11 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value) | |||
562 | static int axnet_open(struct net_device *dev) | 526 | static int axnet_open(struct net_device *dev) |
563 | { | 527 | { |
564 | axnet_dev_t *info = PRIV(dev); | 528 | axnet_dev_t *info = PRIV(dev); |
565 | dev_link_t *link = &info->link; | 529 | struct pcmcia_device *link = info->p_dev; |
566 | 530 | ||
567 | DEBUG(2, "axnet_open('%s')\n", dev->name); | 531 | DEBUG(2, "axnet_open('%s')\n", dev->name); |
568 | 532 | ||
569 | if (!DEV_OK(link)) | 533 | if (!pcmcia_dev_present(link)) |
570 | return -ENODEV; | 534 | return -ENODEV; |
571 | 535 | ||
572 | link->open++; | 536 | link->open++; |
@@ -588,7 +552,7 @@ static int axnet_open(struct net_device *dev) | |||
588 | static int axnet_close(struct net_device *dev) | 552 | static int axnet_close(struct net_device *dev) |
589 | { | 553 | { |
590 | axnet_dev_t *info = PRIV(dev); | 554 | axnet_dev_t *info = PRIV(dev); |
591 | dev_link_t *link = &info->link; | 555 | struct pcmcia_device *link = info->p_dev; |
592 | 556 | ||
593 | DEBUG(2, "axnet_close('%s')\n", dev->name); | 557 | DEBUG(2, "axnet_close('%s')\n", dev->name); |
594 | 558 | ||
@@ -833,7 +797,7 @@ static struct pcmcia_driver axnet_cs_driver = { | |||
833 | .drv = { | 797 | .drv = { |
834 | .name = "axnet_cs", | 798 | .name = "axnet_cs", |
835 | }, | 799 | }, |
836 | .probe = axnet_attach, | 800 | .probe = axnet_probe, |
837 | .remove = axnet_detach, | 801 | .remove = axnet_detach, |
838 | .id_table = axnet_ids, | 802 | .id_table = axnet_ids, |
839 | .suspend = axnet_suspend, | 803 | .suspend = axnet_suspend, |