diff options
Diffstat (limited to 'drivers/net/wireless/wavelan_cs.c')
-rw-r--r-- | drivers/net/wireless/wavelan_cs.c | 183 |
1 files changed, 48 insertions, 135 deletions
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index c822cad3333f..7e2039f52c49 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c | |||
@@ -4594,14 +4594,12 @@ wavelan_close(struct net_device * dev) | |||
4594 | * configure the card at this point -- we wait until we receive a | 4594 | * configure the card at this point -- we wait until we receive a |
4595 | * card insertion event. | 4595 | * card insertion event. |
4596 | */ | 4596 | */ |
4597 | static dev_link_t * | 4597 | static int |
4598 | wavelan_attach(void) | 4598 | wavelan_attach(struct pcmcia_device *p_dev) |
4599 | { | 4599 | { |
4600 | client_reg_t client_reg; /* Register with cardmgr */ | ||
4601 | dev_link_t * link; /* Info for cardmgr */ | 4600 | dev_link_t * link; /* Info for cardmgr */ |
4602 | struct net_device * dev; /* Interface generic data */ | 4601 | struct net_device * dev; /* Interface generic data */ |
4603 | net_local * lp; /* Interface specific data */ | 4602 | net_local * lp; /* Interface specific data */ |
4604 | int ret; | ||
4605 | 4603 | ||
4606 | #ifdef DEBUG_CALLBACK_TRACE | 4604 | #ifdef DEBUG_CALLBACK_TRACE |
4607 | printk(KERN_DEBUG "-> wavelan_attach()\n"); | 4605 | printk(KERN_DEBUG "-> wavelan_attach()\n"); |
@@ -4609,7 +4607,7 @@ wavelan_attach(void) | |||
4609 | 4607 | ||
4610 | /* Initialize the dev_link_t structure */ | 4608 | /* Initialize the dev_link_t structure */ |
4611 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); | 4609 | link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); |
4612 | if (!link) return NULL; | 4610 | if (!link) return -ENOMEM; |
4613 | 4611 | ||
4614 | /* The io structure describes IO port mapping */ | 4612 | /* The io structure describes IO port mapping */ |
4615 | link->io.NumPorts1 = 8; | 4613 | link->io.NumPorts1 = 8; |
@@ -4627,14 +4625,13 @@ wavelan_attach(void) | |||
4627 | link->conf.IntType = INT_MEMORY_AND_IO; | 4625 | link->conf.IntType = INT_MEMORY_AND_IO; |
4628 | 4626 | ||
4629 | /* Chain drivers */ | 4627 | /* Chain drivers */ |
4630 | link->next = dev_list; | 4628 | link->next = NULL; |
4631 | dev_list = link; | ||
4632 | 4629 | ||
4633 | /* Allocate the generic data structure */ | 4630 | /* Allocate the generic data structure */ |
4634 | dev = alloc_etherdev(sizeof(net_local)); | 4631 | dev = alloc_etherdev(sizeof(net_local)); |
4635 | if (!dev) { | 4632 | if (!dev) { |
4636 | kfree(link); | 4633 | kfree(link); |
4637 | return NULL; | 4634 | return -ENOMEM; |
4638 | } | 4635 | } |
4639 | link->priv = link->irq.Instance = dev; | 4636 | link->priv = link->irq.Instance = dev; |
4640 | 4637 | ||
@@ -4679,28 +4676,21 @@ wavelan_attach(void) | |||
4679 | /* Other specific data */ | 4676 | /* Other specific data */ |
4680 | dev->mtu = WAVELAN_MTU; | 4677 | dev->mtu = WAVELAN_MTU; |
4681 | 4678 | ||
4682 | /* Register with Card Services */ | 4679 | link->handle = p_dev; |
4683 | client_reg.dev_info = &dev_info; | 4680 | p_dev->instance = link; |
4684 | client_reg.Version = 0x0210; | ||
4685 | client_reg.event_callback_args.client_data = link; | ||
4686 | 4681 | ||
4687 | #ifdef DEBUG_CONFIG_INFO | 4682 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; |
4688 | printk(KERN_DEBUG "wavelan_attach(): almost done, calling pcmcia_register_client\n"); | 4683 | if(wv_pcmcia_config(link) && |
4689 | #endif | 4684 | wv_hw_config(dev)) |
4690 | 4685 | wv_init_info(dev); | |
4691 | ret = pcmcia_register_client(&link->handle, &client_reg); | 4686 | else |
4692 | if(ret != 0) | 4687 | dev->irq = 0; |
4693 | { | ||
4694 | cs_error(link->handle, RegisterClient, ret); | ||
4695 | wavelan_detach(link); | ||
4696 | return NULL; | ||
4697 | } | ||
4698 | 4688 | ||
4699 | #ifdef DEBUG_CALLBACK_TRACE | 4689 | #ifdef DEBUG_CALLBACK_TRACE |
4700 | printk(KERN_DEBUG "<- wavelan_attach()\n"); | 4690 | printk(KERN_DEBUG "<- wavelan_attach()\n"); |
4701 | #endif | 4691 | #endif |
4702 | 4692 | ||
4703 | return link; | 4693 | return 0; |
4704 | } | 4694 | } |
4705 | 4695 | ||
4706 | /*------------------------------------------------------------------*/ | 4696 | /*------------------------------------------------------------------*/ |
@@ -4711,8 +4701,10 @@ wavelan_attach(void) | |||
4711 | * is released. | 4701 | * is released. |
4712 | */ | 4702 | */ |
4713 | static void | 4703 | static void |
4714 | wavelan_detach(dev_link_t * link) | 4704 | wavelan_detach(struct pcmcia_device *p_dev) |
4715 | { | 4705 | { |
4706 | dev_link_t *link = dev_to_instance(p_dev); | ||
4707 | |||
4716 | #ifdef DEBUG_CALLBACK_TRACE | 4708 | #ifdef DEBUG_CALLBACK_TRACE |
4717 | printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); | 4709 | printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); |
4718 | #endif | 4710 | #endif |
@@ -4729,31 +4721,6 @@ wavelan_detach(dev_link_t * link) | |||
4729 | wv_pcmcia_release(link); | 4721 | wv_pcmcia_release(link); |
4730 | } | 4722 | } |
4731 | 4723 | ||
4732 | /* Break the link with Card Services */ | ||
4733 | if(link->handle) | ||
4734 | pcmcia_deregister_client(link->handle); | ||
4735 | |||
4736 | /* Remove the interface data from the linked list */ | ||
4737 | if(dev_list == link) | ||
4738 | dev_list = link->next; | ||
4739 | else | ||
4740 | { | ||
4741 | dev_link_t * prev = dev_list; | ||
4742 | |||
4743 | while((prev != (dev_link_t *) NULL) && (prev->next != link)) | ||
4744 | prev = prev->next; | ||
4745 | |||
4746 | if(prev == (dev_link_t *) NULL) | ||
4747 | { | ||
4748 | #ifdef DEBUG_CONFIG_ERRORS | ||
4749 | printk(KERN_WARNING "wavelan_detach : Attempting to remove a nonexistent device.\n"); | ||
4750 | #endif | ||
4751 | return; | ||
4752 | } | ||
4753 | |||
4754 | prev->next = link->next; | ||
4755 | } | ||
4756 | |||
4757 | /* Free pieces */ | 4724 | /* Free pieces */ |
4758 | if(link->priv) | 4725 | if(link->priv) |
4759 | { | 4726 | { |
@@ -4775,65 +4742,11 @@ wavelan_detach(dev_link_t * link) | |||
4775 | #endif | 4742 | #endif |
4776 | } | 4743 | } |
4777 | 4744 | ||
4778 | /*------------------------------------------------------------------*/ | 4745 | static int wavelan_suspend(struct pcmcia_device *p_dev) |
4779 | /* | ||
4780 | * The card status event handler. Mostly, this schedules other stuff | ||
4781 | * to run after an event is received. A CARD_REMOVAL event also sets | ||
4782 | * some flags to discourage the net drivers from trying to talk to the | ||
4783 | * card any more. | ||
4784 | */ | ||
4785 | static int | ||
4786 | wavelan_event(event_t event, /* The event received */ | ||
4787 | int priority, | ||
4788 | event_callback_args_t * args) | ||
4789 | { | 4746 | { |
4790 | dev_link_t * link = (dev_link_t *) args->client_data; | 4747 | dev_link_t *link = dev_to_instance(p_dev); |
4791 | struct net_device * dev = (struct net_device *) link->priv; | 4748 | struct net_device * dev = (struct net_device *) link->priv; |
4792 | |||
4793 | #ifdef DEBUG_CALLBACK_TRACE | ||
4794 | printk(KERN_DEBUG "->wavelan_event(): %s\n", | ||
4795 | ((event == CS_EVENT_REGISTRATION_COMPLETE)?"registration complete" : | ||
4796 | ((event == CS_EVENT_CARD_REMOVAL) ? "card removal" : | ||
4797 | ((event == CS_EVENT_CARD_INSERTION) ? "card insertion" : | ||
4798 | ((event == CS_EVENT_PM_SUSPEND) ? "pm suspend" : | ||
4799 | ((event == CS_EVENT_RESET_PHYSICAL) ? "physical reset" : | ||
4800 | ((event == CS_EVENT_PM_RESUME) ? "pm resume" : | ||
4801 | ((event == CS_EVENT_CARD_RESET) ? "card reset" : | ||
4802 | "unknown")))))))); | ||
4803 | #endif | ||
4804 | |||
4805 | switch(event) | ||
4806 | { | ||
4807 | case CS_EVENT_REGISTRATION_COMPLETE: | ||
4808 | #ifdef DEBUG_CONFIG_INFO | ||
4809 | printk(KERN_DEBUG "wavelan_cs: registration complete\n"); | ||
4810 | #endif | ||
4811 | break; | ||
4812 | 4749 | ||
4813 | case CS_EVENT_CARD_REMOVAL: | ||
4814 | /* Oups ! The card is no more there */ | ||
4815 | link->state &= ~DEV_PRESENT; | ||
4816 | if(link->state & DEV_CONFIG) | ||
4817 | { | ||
4818 | /* Accept no more transmissions */ | ||
4819 | netif_device_detach(dev); | ||
4820 | |||
4821 | /* Release the card */ | ||
4822 | wv_pcmcia_release(link); | ||
4823 | } | ||
4824 | break; | ||
4825 | |||
4826 | case CS_EVENT_CARD_INSERTION: | ||
4827 | /* Reset and configure the card */ | ||
4828 | link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; | ||
4829 | if(wv_pcmcia_config(link) && | ||
4830 | wv_hw_config(dev)) | ||
4831 | wv_init_info(dev); | ||
4832 | else | ||
4833 | dev->irq = 0; | ||
4834 | break; | ||
4835 | |||
4836 | case CS_EVENT_PM_SUSPEND: | ||
4837 | /* NB: wavelan_close will be called, but too late, so we are | 4750 | /* NB: wavelan_close will be called, but too late, so we are |
4838 | * obliged to close nicely the wavelan here. David, could you | 4751 | * obliged to close nicely the wavelan here. David, could you |
4839 | * close the device before suspending them ? And, by the way, | 4752 | * close the device before suspending them ? And, by the way, |
@@ -4848,38 +4761,37 @@ wavelan_event(event_t event, /* The event received */ | |||
4848 | 4761 | ||
4849 | /* The card is now suspended */ | 4762 | /* The card is now suspended */ |
4850 | link->state |= DEV_SUSPEND; | 4763 | link->state |= DEV_SUSPEND; |
4851 | /* Fall through... */ | 4764 | |
4852 | case CS_EVENT_RESET_PHYSICAL: | ||
4853 | if(link->state & DEV_CONFIG) | 4765 | if(link->state & DEV_CONFIG) |
4854 | { | 4766 | { |
4855 | if(link->open) | 4767 | if(link->open) |
4856 | netif_device_detach(dev); | 4768 | netif_device_detach(dev); |
4857 | pcmcia_release_configuration(link->handle); | 4769 | pcmcia_release_configuration(link->handle); |
4858 | } | 4770 | } |
4859 | break; | 4771 | |
4772 | return 0; | ||
4773 | } | ||
4774 | |||
4775 | static int wavelan_resume(struct pcmcia_device *p_dev) | ||
4776 | { | ||
4777 | dev_link_t *link = dev_to_instance(p_dev); | ||
4778 | struct net_device * dev = (struct net_device *) link->priv; | ||
4860 | 4779 | ||
4861 | case CS_EVENT_PM_RESUME: | ||
4862 | link->state &= ~DEV_SUSPEND; | 4780 | link->state &= ~DEV_SUSPEND; |
4863 | /* Fall through... */ | ||
4864 | case CS_EVENT_CARD_RESET: | ||
4865 | if(link->state & DEV_CONFIG) | 4781 | if(link->state & DEV_CONFIG) |
4866 | { | 4782 | { |
4867 | pcmcia_request_configuration(link->handle, &link->conf); | 4783 | pcmcia_request_configuration(link->handle, &link->conf); |
4868 | if(link->open) /* If RESET -> True, If RESUME -> False ? */ | 4784 | if(link->open) /* If RESET -> True, If RESUME -> False ? */ |
4869 | { | 4785 | { |
4870 | wv_hw_reset(dev); | 4786 | wv_hw_reset(dev); |
4871 | netif_device_attach(dev); | 4787 | netif_device_attach(dev); |
4872 | } | 4788 | } |
4873 | } | 4789 | } |
4874 | break; | ||
4875 | } | ||
4876 | 4790 | ||
4877 | #ifdef DEBUG_CALLBACK_TRACE | 4791 | return 0; |
4878 | printk(KERN_DEBUG "<-wavelan_event()\n"); | ||
4879 | #endif | ||
4880 | return 0; | ||
4881 | } | 4792 | } |
4882 | 4793 | ||
4794 | |||
4883 | static struct pcmcia_device_id wavelan_ids[] = { | 4795 | static struct pcmcia_device_id wavelan_ids[] = { |
4884 | PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975), | 4796 | PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975), |
4885 | PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06), | 4797 | PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06), |
@@ -4894,10 +4806,11 @@ static struct pcmcia_driver wavelan_driver = { | |||
4894 | .drv = { | 4806 | .drv = { |
4895 | .name = "wavelan_cs", | 4807 | .name = "wavelan_cs", |
4896 | }, | 4808 | }, |
4897 | .attach = wavelan_attach, | 4809 | .probe = wavelan_attach, |
4898 | .event = wavelan_event, | 4810 | .remove = wavelan_detach, |
4899 | .detach = wavelan_detach, | ||
4900 | .id_table = wavelan_ids, | 4811 | .id_table = wavelan_ids, |
4812 | .suspend = wavelan_suspend, | ||
4813 | .resume = wavelan_resume, | ||
4901 | }; | 4814 | }; |
4902 | 4815 | ||
4903 | static int __init | 4816 | static int __init |