root/drivers/tty/ipwireless/main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. signalled_reboot_work
  2. signalled_reboot_callback
  3. ipwireless_probe
  4. config_ipwireless
  5. release_ipwireless
  6. ipwireless_attach
  7. ipwireless_detach
  8. init_ipwireless
  9. exit_ipwireless

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * IPWireless 3G PCMCIA Network Driver
   4  *
   5  * Original code
   6  *   by Stephen Blackheath <stephen@blacksapphire.com>,
   7  *      Ben Martel <benm@symmetric.co.nz>
   8  *
   9  * Copyrighted as follows:
  10  *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
  11  *
  12  * Various driver changes and rewrites, port to new kernels
  13  *   Copyright (C) 2006-2007 Jiri Kosina
  14  *
  15  * Misc code cleanups and updates
  16  *   Copyright (C) 2007 David Sterba
  17  */
  18 
  19 #include "hardware.h"
  20 #include "network.h"
  21 #include "main.h"
  22 #include "tty.h"
  23 
  24 #include <linux/delay.h>
  25 #include <linux/init.h>
  26 #include <linux/io.h>
  27 #include <linux/kernel.h>
  28 #include <linux/module.h>
  29 #include <linux/sched.h>
  30 #include <linux/slab.h>
  31 
  32 #include <pcmcia/cisreg.h>
  33 #include <pcmcia/device_id.h>
  34 #include <pcmcia/ss.h>
  35 #include <pcmcia/ds.h>
  36 
  37 static const struct pcmcia_device_id ipw_ids[] = {
  38         PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
  39         PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0200),
  40         PCMCIA_DEVICE_NULL
  41 };
  42 MODULE_DEVICE_TABLE(pcmcia, ipw_ids);
  43 
  44 static void ipwireless_detach(struct pcmcia_device *link);
  45 
  46 /*
  47  * Module params
  48  */
  49 /* Debug mode: more verbose, print sent/recv bytes */
  50 int ipwireless_debug;
  51 int ipwireless_loopback;
  52 int ipwireless_out_queue = 10;
  53 
  54 module_param_named(debug, ipwireless_debug, int, 0);
  55 module_param_named(loopback, ipwireless_loopback, int, 0);
  56 module_param_named(out_queue, ipwireless_out_queue, int, 0);
  57 MODULE_PARM_DESC(debug, "switch on debug messages [0]");
  58 MODULE_PARM_DESC(loopback,
  59                 "debug: enable ras_raw channel [0]");
  60 MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]");
  61 
  62 /* Executes in process context. */
  63 static void signalled_reboot_work(struct work_struct *work_reboot)
  64 {
  65         struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,
  66                         work_reboot);
  67         struct pcmcia_device *link = ipw->link;
  68         pcmcia_reset_card(link->socket);
  69 }
  70 
  71 static void signalled_reboot_callback(void *callback_data)
  72 {
  73         struct ipw_dev *ipw = (struct ipw_dev *) callback_data;
  74 
  75         /* Delegate to process context. */
  76         schedule_work(&ipw->work_reboot);
  77 }
  78 
  79 static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
  80 {
  81         struct ipw_dev *ipw = priv_data;
  82         int ret;
  83 
  84         p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
  85         p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
  86 
  87         /* 0x40 causes it to generate level mode interrupts. */
  88         /* 0x04 enables IREQ pin. */
  89         p_dev->config_index |= 0x44;
  90         p_dev->io_lines = 16;
  91         ret = pcmcia_request_io(p_dev);
  92         if (ret)
  93                 return ret;
  94 
  95         if (!request_region(p_dev->resource[0]->start,
  96                             resource_size(p_dev->resource[0]),
  97                             IPWIRELESS_PCCARD_NAME)) {
  98                 ret = -EBUSY;
  99                 goto exit;
 100         }
 101 
 102         p_dev->resource[2]->flags |=
 103                 WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
 104 
 105         ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
 106         if (ret != 0)
 107                 goto exit1;
 108 
 109         ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
 110         if (ret != 0)
 111                 goto exit1;
 112 
 113         ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
 114 
 115         ipw->common_memory = ioremap(p_dev->resource[2]->start,
 116                                 resource_size(p_dev->resource[2]));
 117         if (!ipw->common_memory) {
 118                 ret = -ENOMEM;
 119                 goto exit1;
 120         }
 121         if (!request_mem_region(p_dev->resource[2]->start,
 122                                 resource_size(p_dev->resource[2]),
 123                                 IPWIRELESS_PCCARD_NAME)) {
 124                 ret = -EBUSY;
 125                 goto exit2;
 126         }
 127 
 128         p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM |
 129                                         WIN_ENABLE;
 130         p_dev->resource[3]->end = 0; /* this used to be 0x1000 */
 131         ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0);
 132         if (ret != 0)
 133                 goto exit3;
 134 
 135         ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0);
 136         if (ret != 0)
 137                 goto exit3;
 138 
 139         ipw->attr_memory = ioremap(p_dev->resource[3]->start,
 140                                 resource_size(p_dev->resource[3]));
 141         if (!ipw->attr_memory) {
 142                 ret = -ENOMEM;
 143                 goto exit3;
 144         }
 145         if (!request_mem_region(p_dev->resource[3]->start,
 146                                 resource_size(p_dev->resource[3]),
 147                                 IPWIRELESS_PCCARD_NAME)) {
 148                 ret = -EBUSY;
 149                 goto exit4;
 150         }
 151 
 152         return 0;
 153 
 154 exit4:
 155         iounmap(ipw->attr_memory);
 156 exit3:
 157         release_mem_region(p_dev->resource[2]->start,
 158                         resource_size(p_dev->resource[2]));
 159 exit2:
 160         iounmap(ipw->common_memory);
 161 exit1:
 162         release_region(p_dev->resource[0]->start,
 163                        resource_size(p_dev->resource[0]));
 164 exit:
 165         pcmcia_disable_device(p_dev);
 166         return ret;
 167 }
 168 
 169 static int config_ipwireless(struct ipw_dev *ipw)
 170 {
 171         struct pcmcia_device *link = ipw->link;
 172         int ret = 0;
 173 
 174         ipw->is_v2_card = 0;
 175         link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM |
 176                 CONF_ENABLE_IRQ;
 177 
 178         ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
 179         if (ret != 0)
 180                 return ret;
 181 
 182         INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
 183 
 184         ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
 185                                     ipw->attr_memory, ipw->common_memory,
 186                                     ipw->is_v2_card, signalled_reboot_callback,
 187                                     ipw);
 188 
 189         ret = pcmcia_request_irq(link, ipwireless_interrupt);
 190         if (ret != 0)
 191                 goto exit;
 192 
 193         printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
 194                         ipw->is_v2_card ? "V2/V3" : "V1");
 195         printk(KERN_INFO IPWIRELESS_PCCARD_NAME
 196                 ": I/O ports %pR, irq %d\n", link->resource[0],
 197                         (unsigned int) link->irq);
 198         if (ipw->attr_memory && ipw->common_memory)
 199                 printk(KERN_INFO IPWIRELESS_PCCARD_NAME
 200                         ": attr memory %pR, common memory %pR\n",
 201                         link->resource[3],
 202                         link->resource[2]);
 203 
 204         ipw->network = ipwireless_network_create(ipw->hardware);
 205         if (!ipw->network)
 206                 goto exit;
 207 
 208         ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network);
 209         if (!ipw->tty)
 210                 goto exit;
 211 
 212         ipwireless_init_hardware_v2_v3(ipw->hardware);
 213 
 214         /*
 215          * Do the RequestConfiguration last, because it enables interrupts.
 216          * Then we don't get any interrupts before we're ready for them.
 217          */
 218         ret = pcmcia_enable_device(link);
 219         if (ret != 0)
 220                 goto exit;
 221 
 222         return 0;
 223 
 224 exit:
 225         if (ipw->common_memory) {
 226                 release_mem_region(link->resource[2]->start,
 227                                 resource_size(link->resource[2]));
 228                 iounmap(ipw->common_memory);
 229         }
 230         if (ipw->attr_memory) {
 231                 release_mem_region(link->resource[3]->start,
 232                                 resource_size(link->resource[3]));
 233                 iounmap(ipw->attr_memory);
 234         }
 235         pcmcia_disable_device(link);
 236         return -1;
 237 }
 238 
 239 static void release_ipwireless(struct ipw_dev *ipw)
 240 {
 241         release_region(ipw->link->resource[0]->start,
 242                        resource_size(ipw->link->resource[0]));
 243         if (ipw->common_memory) {
 244                 release_mem_region(ipw->link->resource[2]->start,
 245                                 resource_size(ipw->link->resource[2]));
 246                 iounmap(ipw->common_memory);
 247         }
 248         if (ipw->attr_memory) {
 249                 release_mem_region(ipw->link->resource[3]->start,
 250                                 resource_size(ipw->link->resource[3]));
 251                 iounmap(ipw->attr_memory);
 252         }
 253         pcmcia_disable_device(ipw->link);
 254 }
 255 
 256 /*
 257  * ipwireless_attach() creates an "instance" of the driver, allocating
 258  * local data structures for one device (one interface).  The device
 259  * is registered with Card Services.
 260  *
 261  * The pcmcia_device structure is initialized, but we don't actually
 262  * configure the card at this point -- we wait until we receive a
 263  * card insertion event.
 264  */
 265 static int ipwireless_attach(struct pcmcia_device *link)
 266 {
 267         struct ipw_dev *ipw;
 268         int ret;
 269 
 270         ipw = kzalloc(sizeof(struct ipw_dev), GFP_KERNEL);
 271         if (!ipw)
 272                 return -ENOMEM;
 273 
 274         ipw->link = link;
 275         link->priv = ipw;
 276 
 277         ipw->hardware = ipwireless_hardware_create();
 278         if (!ipw->hardware) {
 279                 kfree(ipw);
 280                 return -ENOMEM;
 281         }
 282         /* RegisterClient will call config_ipwireless */
 283 
 284         ret = config_ipwireless(ipw);
 285 
 286         if (ret != 0) {
 287                 ipwireless_detach(link);
 288                 return ret;
 289         }
 290 
 291         return 0;
 292 }
 293 
 294 /*
 295  * This deletes a driver "instance".  The device is de-registered with
 296  * Card Services.  If it has been released, all local data structures
 297  * are freed.  Otherwise, the structures will be freed when the device
 298  * is released.
 299  */
 300 static void ipwireless_detach(struct pcmcia_device *link)
 301 {
 302         struct ipw_dev *ipw = link->priv;
 303 
 304         release_ipwireless(ipw);
 305 
 306         if (ipw->tty != NULL)
 307                 ipwireless_tty_free(ipw->tty);
 308         if (ipw->network != NULL)
 309                 ipwireless_network_free(ipw->network);
 310         if (ipw->hardware != NULL)
 311                 ipwireless_hardware_free(ipw->hardware);
 312         kfree(ipw);
 313 }
 314 
 315 static struct pcmcia_driver me = {
 316         .owner          = THIS_MODULE,
 317         .probe          = ipwireless_attach,
 318         .remove         = ipwireless_detach,
 319         .name           = IPWIRELESS_PCCARD_NAME,
 320         .id_table       = ipw_ids
 321 };
 322 
 323 /*
 324  * Module insertion : initialisation of the module.
 325  * Register the card with cardmgr...
 326  */
 327 static int __init init_ipwireless(void)
 328 {
 329         int ret;
 330 
 331         ret = ipwireless_tty_init();
 332         if (ret != 0)
 333                 return ret;
 334 
 335         ret = pcmcia_register_driver(&me);
 336         if (ret != 0)
 337                 ipwireless_tty_release();
 338 
 339         return ret;
 340 }
 341 
 342 /*
 343  * Module removal
 344  */
 345 static void __exit exit_ipwireless(void)
 346 {
 347         pcmcia_unregister_driver(&me);
 348         ipwireless_tty_release();
 349 }
 350 
 351 module_init(init_ipwireless);
 352 module_exit(exit_ipwireless);
 353 
 354 MODULE_AUTHOR(IPWIRELESS_PCMCIA_AUTHOR);
 355 MODULE_DESCRIPTION(IPWIRELESS_PCCARD_NAME " " IPWIRELESS_PCMCIA_VERSION);
 356 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */