main.c (8806B)
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 37static 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}; 42MODULE_DEVICE_TABLE(pcmcia, ipw_ids); 43 44static void ipwireless_detach(struct pcmcia_device *link); 45 46/* 47 * Module params 48 */ 49/* Debug mode: more verbose, print sent/recv bytes */ 50int ipwireless_debug; 51int ipwireless_loopback; 52int ipwireless_out_queue = 10; 53 54module_param_named(debug, ipwireless_debug, int, 0); 55module_param_named(loopback, ipwireless_loopback, int, 0); 56module_param_named(out_queue, ipwireless_out_queue, int, 0); 57MODULE_PARM_DESC(debug, "switch on debug messages [0]"); 58MODULE_PARM_DESC(loopback, 59 "debug: enable ras_raw channel [0]"); 60MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]"); 61 62/* Executes in process context. */ 63static 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 71static 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 79static 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 154exit4: 155 iounmap(ipw->attr_memory); 156exit3: 157 release_mem_region(p_dev->resource[2]->start, 158 resource_size(p_dev->resource[2])); 159exit2: 160 iounmap(ipw->common_memory); 161exit1: 162 release_region(p_dev->resource[0]->start, 163 resource_size(p_dev->resource[0])); 164exit: 165 pcmcia_disable_device(p_dev); 166 return ret; 167} 168 169static 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 224exit: 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 239static 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 */ 265static 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 */ 300static 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 315static 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 */ 327static 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 */ 345static void __exit exit_ipwireless(void) 346{ 347 pcmcia_unregister_driver(&me); 348 ipwireless_tty_release(); 349} 350 351module_init(init_ipwireless); 352module_exit(exit_ipwireless); 353 354MODULE_AUTHOR(IPWIRELESS_PCMCIA_AUTHOR); 355MODULE_DESCRIPTION(IPWIRELESS_PCCARD_NAME " " IPWIRELESS_PCMCIA_VERSION); 356MODULE_LICENSE("GPL");