Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * IPWireless 3G PCMCIA Network Driver
0004  *
0005  * Original code
0006  *   by Stephen Blackheath <stephen@blacksapphire.com>,
0007  *      Ben Martel <benm@symmetric.co.nz>
0008  *
0009  * Copyrighted as follows:
0010  *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
0011  *
0012  * Various driver changes and rewrites, port to new kernels
0013  *   Copyright (C) 2006-2007 Jiri Kosina
0014  *
0015  * Misc code cleanups and updates
0016  *   Copyright (C) 2007 David Sterba
0017  */
0018 
0019 #include "hardware.h"
0020 #include "network.h"
0021 #include "main.h"
0022 #include "tty.h"
0023 
0024 #include <linux/delay.h>
0025 #include <linux/init.h>
0026 #include <linux/io.h>
0027 #include <linux/kernel.h>
0028 #include <linux/module.h>
0029 #include <linux/sched.h>
0030 #include <linux/slab.h>
0031 
0032 #include <pcmcia/cisreg.h>
0033 #include <pcmcia/device_id.h>
0034 #include <pcmcia/ss.h>
0035 #include <pcmcia/ds.h>
0036 
0037 static const struct pcmcia_device_id ipw_ids[] = {
0038     PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
0039     PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0200),
0040     PCMCIA_DEVICE_NULL
0041 };
0042 MODULE_DEVICE_TABLE(pcmcia, ipw_ids);
0043 
0044 static void ipwireless_detach(struct pcmcia_device *link);
0045 
0046 /*
0047  * Module params
0048  */
0049 /* Debug mode: more verbose, print sent/recv bytes */
0050 int ipwireless_debug;
0051 int ipwireless_loopback;
0052 int ipwireless_out_queue = 10;
0053 
0054 module_param_named(debug, ipwireless_debug, int, 0);
0055 module_param_named(loopback, ipwireless_loopback, int, 0);
0056 module_param_named(out_queue, ipwireless_out_queue, int, 0);
0057 MODULE_PARM_DESC(debug, "switch on debug messages [0]");
0058 MODULE_PARM_DESC(loopback,
0059         "debug: enable ras_raw channel [0]");
0060 MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]");
0061 
0062 /* Executes in process context. */
0063 static void signalled_reboot_work(struct work_struct *work_reboot)
0064 {
0065     struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,
0066             work_reboot);
0067     struct pcmcia_device *link = ipw->link;
0068     pcmcia_reset_card(link->socket);
0069 }
0070 
0071 static void signalled_reboot_callback(void *callback_data)
0072 {
0073     struct ipw_dev *ipw = (struct ipw_dev *) callback_data;
0074 
0075     /* Delegate to process context. */
0076     schedule_work(&ipw->work_reboot);
0077 }
0078 
0079 static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
0080 {
0081     struct ipw_dev *ipw = priv_data;
0082     int ret;
0083 
0084     p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
0085     p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
0086 
0087     /* 0x40 causes it to generate level mode interrupts. */
0088     /* 0x04 enables IREQ pin. */
0089     p_dev->config_index |= 0x44;
0090     p_dev->io_lines = 16;
0091     ret = pcmcia_request_io(p_dev);
0092     if (ret)
0093         return ret;
0094 
0095     if (!request_region(p_dev->resource[0]->start,
0096                 resource_size(p_dev->resource[0]),
0097                 IPWIRELESS_PCCARD_NAME)) {
0098         ret = -EBUSY;
0099         goto exit;
0100     }
0101 
0102     p_dev->resource[2]->flags |=
0103         WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
0104 
0105     ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
0106     if (ret != 0)
0107         goto exit1;
0108 
0109     ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
0110     if (ret != 0)
0111         goto exit1;
0112 
0113     ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
0114 
0115     ipw->common_memory = ioremap(p_dev->resource[2]->start,
0116                 resource_size(p_dev->resource[2]));
0117     if (!ipw->common_memory) {
0118         ret = -ENOMEM;
0119         goto exit1;
0120     }
0121     if (!request_mem_region(p_dev->resource[2]->start,
0122                 resource_size(p_dev->resource[2]),
0123                 IPWIRELESS_PCCARD_NAME)) {
0124         ret = -EBUSY;
0125         goto exit2;
0126     }
0127 
0128     p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM |
0129                     WIN_ENABLE;
0130     p_dev->resource[3]->end = 0; /* this used to be 0x1000 */
0131     ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0);
0132     if (ret != 0)
0133         goto exit3;
0134 
0135     ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0);
0136     if (ret != 0)
0137         goto exit3;
0138 
0139     ipw->attr_memory = ioremap(p_dev->resource[3]->start,
0140                 resource_size(p_dev->resource[3]));
0141     if (!ipw->attr_memory) {
0142         ret = -ENOMEM;
0143         goto exit3;
0144     }
0145     if (!request_mem_region(p_dev->resource[3]->start,
0146                 resource_size(p_dev->resource[3]),
0147                 IPWIRELESS_PCCARD_NAME)) {
0148         ret = -EBUSY;
0149         goto exit4;
0150     }
0151 
0152     return 0;
0153 
0154 exit4:
0155     iounmap(ipw->attr_memory);
0156 exit3:
0157     release_mem_region(p_dev->resource[2]->start,
0158             resource_size(p_dev->resource[2]));
0159 exit2:
0160     iounmap(ipw->common_memory);
0161 exit1:
0162     release_region(p_dev->resource[0]->start,
0163                resource_size(p_dev->resource[0]));
0164 exit:
0165     pcmcia_disable_device(p_dev);
0166     return ret;
0167 }
0168 
0169 static int config_ipwireless(struct ipw_dev *ipw)
0170 {
0171     struct pcmcia_device *link = ipw->link;
0172     int ret = 0;
0173 
0174     ipw->is_v2_card = 0;
0175     link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM |
0176         CONF_ENABLE_IRQ;
0177 
0178     ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
0179     if (ret != 0)
0180         return ret;
0181 
0182     INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
0183 
0184     ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
0185                     ipw->attr_memory, ipw->common_memory,
0186                     ipw->is_v2_card, signalled_reboot_callback,
0187                     ipw);
0188 
0189     ret = pcmcia_request_irq(link, ipwireless_interrupt);
0190     if (ret != 0)
0191         goto exit;
0192 
0193     printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
0194             ipw->is_v2_card ? "V2/V3" : "V1");
0195     printk(KERN_INFO IPWIRELESS_PCCARD_NAME
0196         ": I/O ports %pR, irq %d\n", link->resource[0],
0197             (unsigned int) link->irq);
0198     if (ipw->attr_memory && ipw->common_memory)
0199         printk(KERN_INFO IPWIRELESS_PCCARD_NAME
0200             ": attr memory %pR, common memory %pR\n",
0201             link->resource[3],
0202             link->resource[2]);
0203 
0204     ipw->network = ipwireless_network_create(ipw->hardware);
0205     if (!ipw->network)
0206         goto exit;
0207 
0208     ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network);
0209     if (!ipw->tty)
0210         goto exit;
0211 
0212     ipwireless_init_hardware_v2_v3(ipw->hardware);
0213 
0214     /*
0215      * Do the RequestConfiguration last, because it enables interrupts.
0216      * Then we don't get any interrupts before we're ready for them.
0217      */
0218     ret = pcmcia_enable_device(link);
0219     if (ret != 0)
0220         goto exit;
0221 
0222     return 0;
0223 
0224 exit:
0225     if (ipw->common_memory) {
0226         release_mem_region(link->resource[2]->start,
0227                 resource_size(link->resource[2]));
0228         iounmap(ipw->common_memory);
0229     }
0230     if (ipw->attr_memory) {
0231         release_mem_region(link->resource[3]->start,
0232                 resource_size(link->resource[3]));
0233         iounmap(ipw->attr_memory);
0234     }
0235     pcmcia_disable_device(link);
0236     return -1;
0237 }
0238 
0239 static void release_ipwireless(struct ipw_dev *ipw)
0240 {
0241     release_region(ipw->link->resource[0]->start,
0242                resource_size(ipw->link->resource[0]));
0243     if (ipw->common_memory) {
0244         release_mem_region(ipw->link->resource[2]->start,
0245                 resource_size(ipw->link->resource[2]));
0246         iounmap(ipw->common_memory);
0247     }
0248     if (ipw->attr_memory) {
0249         release_mem_region(ipw->link->resource[3]->start,
0250                 resource_size(ipw->link->resource[3]));
0251         iounmap(ipw->attr_memory);
0252     }
0253     pcmcia_disable_device(ipw->link);
0254 }
0255 
0256 /*
0257  * ipwireless_attach() creates an "instance" of the driver, allocating
0258  * local data structures for one device (one interface).  The device
0259  * is registered with Card Services.
0260  *
0261  * The pcmcia_device structure is initialized, but we don't actually
0262  * configure the card at this point -- we wait until we receive a
0263  * card insertion event.
0264  */
0265 static int ipwireless_attach(struct pcmcia_device *link)
0266 {
0267     struct ipw_dev *ipw;
0268     int ret;
0269 
0270     ipw = kzalloc(sizeof(struct ipw_dev), GFP_KERNEL);
0271     if (!ipw)
0272         return -ENOMEM;
0273 
0274     ipw->link = link;
0275     link->priv = ipw;
0276 
0277     ipw->hardware = ipwireless_hardware_create();
0278     if (!ipw->hardware) {
0279         kfree(ipw);
0280         return -ENOMEM;
0281     }
0282     /* RegisterClient will call config_ipwireless */
0283 
0284     ret = config_ipwireless(ipw);
0285 
0286     if (ret != 0) {
0287         ipwireless_detach(link);
0288         return ret;
0289     }
0290 
0291     return 0;
0292 }
0293 
0294 /*
0295  * This deletes a driver "instance".  The device is de-registered with
0296  * Card Services.  If it has been released, all local data structures
0297  * are freed.  Otherwise, the structures will be freed when the device
0298  * is released.
0299  */
0300 static void ipwireless_detach(struct pcmcia_device *link)
0301 {
0302     struct ipw_dev *ipw = link->priv;
0303 
0304     release_ipwireless(ipw);
0305 
0306     if (ipw->tty != NULL)
0307         ipwireless_tty_free(ipw->tty);
0308     if (ipw->network != NULL)
0309         ipwireless_network_free(ipw->network);
0310     if (ipw->hardware != NULL)
0311         ipwireless_hardware_free(ipw->hardware);
0312     kfree(ipw);
0313 }
0314 
0315 static struct pcmcia_driver me = {
0316     .owner      = THIS_MODULE,
0317     .probe          = ipwireless_attach,
0318     .remove         = ipwireless_detach,
0319     .name       = IPWIRELESS_PCCARD_NAME,
0320     .id_table       = ipw_ids
0321 };
0322 
0323 /*
0324  * Module insertion : initialisation of the module.
0325  * Register the card with cardmgr...
0326  */
0327 static int __init init_ipwireless(void)
0328 {
0329     int ret;
0330 
0331     ret = ipwireless_tty_init();
0332     if (ret != 0)
0333         return ret;
0334 
0335     ret = pcmcia_register_driver(&me);
0336     if (ret != 0)
0337         ipwireless_tty_release();
0338 
0339     return ret;
0340 }
0341 
0342 /*
0343  * Module removal
0344  */
0345 static void __exit exit_ipwireless(void)
0346 {
0347     pcmcia_unregister_driver(&me);
0348     ipwireless_tty_release();
0349 }
0350 
0351 module_init(init_ipwireless);
0352 module_exit(exit_ipwireless);
0353 
0354 MODULE_AUTHOR(IPWIRELESS_PCMCIA_AUTHOR);
0355 MODULE_DESCRIPTION(IPWIRELESS_PCCARD_NAME " " IPWIRELESS_PCMCIA_VERSION);
0356 MODULE_LICENSE("GPL");