ipwireless: driver for PC Card 3G/UMTS modem

The device is manufactured by IPWireless. In some countries (for
example Czech Republic, T-Mobile ISP) this card is shipped for service
called UMTS 4G.

It's a piece of PCMCIA "4G" UMTS PPP networking hardware that presents
itself as a serial character device (i.e. looks like usual modem to
userspace, accepts AT commands, etc).

Rewieved-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Ben Martel <benm@symmetric.co.nz>
Signed-off-by: Stephen Blackheath <stephen@symmetric.co.nz>
Signed-off-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by David Sterba and committed by Linus Torvalds 099dc4fb 151db1fc

+3862
+8
MAINTAINERS
··· 2150 2150 L: netdev@vger.kernel.org 2151 2151 S: Maintained 2152 2152 2153 + IPWIRELES DRIVER 2154 + P: Jiri Kosina 2155 + M: jkosina@suse.cz 2156 + P: David Sterba 2157 + M: dsterba@suse.cz 2158 + S: Maintained 2159 + T: git://git.kernel.org/pub/scm/linux/kernel/git/jikos/ipwireless_cs.git 2160 + 2153 2161 IRDA SUBSYSTEM 2154 2162 P: Samuel Ortiz 2155 2163 M: samuel@sortiz.org
+9
drivers/char/pcmcia/Kconfig
··· 43 43 (http://www.omnikey.com/), or a current development version of OpenCT 44 44 (http://www.opensc.org/). 45 45 46 + config IPWIRELESS 47 + tristate "IPWireless 3G UMTS PCMCIA card support" 48 + depends on PCMCIA 49 + select PPP 50 + help 51 + This is a driver for 3G UMTS PCMCIA card from IPWireless company. In 52 + some countries (for example Czech Republic, T-Mobile ISP) this card 53 + is shipped for service called UMTS 4G. 54 + 46 55 endmenu 47 56
+2
drivers/char/pcmcia/Makefile
··· 4 4 # Makefile for the Linux PCMCIA char device drivers. 5 5 # 6 6 7 + obj-y += ipwireless/ 8 + 7 9 obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o 8 10 obj-$(CONFIG_CARDMAN_4000) += cm4000_cs.o 9 11 obj-$(CONFIG_CARDMAN_4040) += cm4040_cs.o
+10
drivers/char/pcmcia/ipwireless/Makefile
··· 1 + # 2 + # drivers/char/pcmcia/ipwireless/Makefile 3 + # 4 + # Makefile for the IPWireless driver 5 + # 6 + 7 + obj-$(CONFIG_IPWIRELESS) += ipwireless.o 8 + 9 + ipwireless-objs := hardware.o main.o network.o tty.o 10 +
+1787
drivers/char/pcmcia/ipwireless/hardware.c
··· 1 + /* 2 + * IPWireless 3G PCMCIA Network Driver 3 + * 4 + * Original code 5 + * by Stephen Blackheath <stephen@blacksapphire.com>, 6 + * Ben Martel <benm@symmetric.co.nz> 7 + * 8 + * Copyrighted as follows: 9 + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) 10 + * 11 + * Various driver changes and rewrites, port to new kernels 12 + * Copyright (C) 2006-2007 Jiri Kosina 13 + * 14 + * Misc code cleanups and updates 15 + * Copyright (C) 2007 David Sterba 16 + */ 17 + 18 + #include <linux/interrupt.h> 19 + #include <linux/io.h> 20 + #include <linux/irq.h> 21 + #include <linux/kernel.h> 22 + #include <linux/list.h> 23 + #include <linux/slab.h> 24 + 25 + #include "hardware.h" 26 + #include "setup_protocol.h" 27 + #include "network.h" 28 + #include "main.h" 29 + 30 + static void ipw_send_setup_packet(struct ipw_hardware *hw); 31 + static void handle_received_SETUP_packet(struct ipw_hardware *ipw, 32 + unsigned int address, 33 + unsigned char *data, int len, 34 + int is_last); 35 + static void ipwireless_setup_timer(unsigned long data); 36 + static void handle_received_CTRL_packet(struct ipw_hardware *hw, 37 + unsigned int channel_idx, unsigned char *data, int len); 38 + 39 + /*#define TIMING_DIAGNOSTICS*/ 40 + 41 + #ifdef TIMING_DIAGNOSTICS 42 + 43 + static struct timing_stats { 44 + unsigned long last_report_time; 45 + unsigned long read_time; 46 + unsigned long write_time; 47 + unsigned long read_bytes; 48 + unsigned long write_bytes; 49 + unsigned long start_time; 50 + }; 51 + 52 + static void start_timing(void) 53 + { 54 + timing_stats.start_time = jiffies; 55 + } 56 + 57 + static void end_read_timing(unsigned length) 58 + { 59 + timing_stats.read_time += (jiffies - start_time); 60 + timing_stats.read_bytes += length + 2; 61 + report_timing(); 62 + } 63 + 64 + static void end_write_timing(unsigned length) 65 + { 66 + timing_stats.write_time += (jiffies - start_time); 67 + timing_stats.write_bytes += length + 2; 68 + report_timing(); 69 + } 70 + 71 + static void report_timing(void) 72 + { 73 + unsigned long since = jiffies - timing_stats.last_report_time; 74 + 75 + /* If it's been more than one second... */ 76 + if (since >= HZ) { 77 + int first = (timing_stats.last_report_time == 0); 78 + 79 + timing_stats.last_report_time = jiffies; 80 + if (!first) 81 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 82 + ": %u us elapsed - read %lu bytes in %u us, " 83 + "wrote %lu bytes in %u us\n", 84 + jiffies_to_usecs(since), 85 + timing_stats.read_bytes, 86 + jiffies_to_usecs(timing_stats.read_time), 87 + timing_stats.write_bytes, 88 + jiffies_to_usecs(timing_stats.write_time)); 89 + 90 + timing_stats.read_time = 0; 91 + timing_stats.write_time = 0; 92 + timing_stats.read_bytes = 0; 93 + timing_stats.write_bytes = 0; 94 + } 95 + } 96 + #else 97 + static void start_timing(void) { } 98 + static void end_read_timing(unsigned length) { } 99 + static void end_write_timing(unsigned length) { } 100 + #endif 101 + 102 + /* Imported IPW definitions */ 103 + 104 + #define LL_MTU_V1 318 105 + #define LL_MTU_V2 250 106 + #define LL_MTU_MAX (LL_MTU_V1 > LL_MTU_V2 ? LL_MTU_V1 : LL_MTU_V2) 107 + 108 + #define PRIO_DATA 2 109 + #define PRIO_CTRL 1 110 + #define PRIO_SETUP 0 111 + 112 + /* Addresses */ 113 + #define ADDR_SETUP_PROT 0 114 + 115 + /* Protocol ids */ 116 + enum { 117 + /* Identifier for the Com Data protocol */ 118 + TL_PROTOCOLID_COM_DATA = 0, 119 + 120 + /* Identifier for the Com Control protocol */ 121 + TL_PROTOCOLID_COM_CTRL = 1, 122 + 123 + /* Identifier for the Setup protocol */ 124 + TL_PROTOCOLID_SETUP = 2 125 + }; 126 + 127 + /* Number of bytes in NL packet header (cannot do 128 + * sizeof(nl_packet_header) since it's a bitfield) */ 129 + #define NL_FIRST_PACKET_HEADER_SIZE 3 130 + 131 + /* Number of bytes in NL packet header (cannot do 132 + * sizeof(nl_packet_header) since it's a bitfield) */ 133 + #define NL_FOLLOWING_PACKET_HEADER_SIZE 1 134 + 135 + struct nl_first_packet_header { 136 + #if defined(__BIG_ENDIAN_BITFIELD) 137 + unsigned char packet_rank:2; 138 + unsigned char address:3; 139 + unsigned char protocol:3; 140 + #else 141 + unsigned char protocol:3; 142 + unsigned char address:3; 143 + unsigned char packet_rank:2; 144 + #endif 145 + unsigned char length_lsb; 146 + unsigned char length_msb; 147 + }; 148 + 149 + struct nl_packet_header { 150 + #if defined(__BIG_ENDIAN_BITFIELD) 151 + unsigned char packet_rank:2; 152 + unsigned char address:3; 153 + unsigned char protocol:3; 154 + #else 155 + unsigned char protocol:3; 156 + unsigned char address:3; 157 + unsigned char packet_rank:2; 158 + #endif 159 + }; 160 + 161 + /* Value of 'packet_rank' above */ 162 + #define NL_INTERMEDIATE_PACKET 0x0 163 + #define NL_LAST_PACKET 0x1 164 + #define NL_FIRST_PACKET 0x2 165 + 166 + union nl_packet { 167 + /* Network packet header of the first packet (a special case) */ 168 + struct nl_first_packet_header hdr_first; 169 + /* Network packet header of the following packets (if any) */ 170 + struct nl_packet_header hdr; 171 + /* Complete network packet (header + data) */ 172 + unsigned char rawpkt[LL_MTU_MAX]; 173 + } __attribute__ ((__packed__)); 174 + 175 + #define HW_VERSION_UNKNOWN -1 176 + #define HW_VERSION_1 1 177 + #define HW_VERSION_2 2 178 + 179 + /* IPW I/O ports */ 180 + #define IOIER 0x00 /* Interrupt Enable Register */ 181 + #define IOIR 0x02 /* Interrupt Source/ACK register */ 182 + #define IODCR 0x04 /* Data Control Register */ 183 + #define IODRR 0x06 /* Data Read Register */ 184 + #define IODWR 0x08 /* Data Write Register */ 185 + #define IOESR 0x0A /* Embedded Driver Status Register */ 186 + #define IORXR 0x0C /* Rx Fifo Register (Host to Embedded) */ 187 + #define IOTXR 0x0E /* Tx Fifo Register (Embedded to Host) */ 188 + 189 + /* I/O ports and bit definitions for version 1 of the hardware */ 190 + 191 + /* IER bits*/ 192 + #define IER_RXENABLED 0x1 193 + #define IER_TXENABLED 0x2 194 + 195 + /* ISR bits */ 196 + #define IR_RXINTR 0x1 197 + #define IR_TXINTR 0x2 198 + 199 + /* DCR bits */ 200 + #define DCR_RXDONE 0x1 201 + #define DCR_TXDONE 0x2 202 + #define DCR_RXRESET 0x4 203 + #define DCR_TXRESET 0x8 204 + 205 + /* I/O ports and bit definitions for version 2 of the hardware */ 206 + 207 + struct MEMCCR { 208 + unsigned short reg_config_option; /* PCCOR: Configuration Option Register */ 209 + unsigned short reg_config_and_status; /* PCCSR: Configuration and Status Register */ 210 + unsigned short reg_pin_replacement; /* PCPRR: Pin Replacemant Register */ 211 + unsigned short reg_socket_and_copy; /* PCSCR: Socket and Copy Register */ 212 + unsigned short reg_ext_status; /* PCESR: Extendend Status Register */ 213 + unsigned short reg_io_base; /* PCIOB: I/O Base Register */ 214 + }; 215 + 216 + struct MEMINFREG { 217 + unsigned short memreg_tx_old; /* TX Register (R/W) */ 218 + unsigned short pad1; 219 + unsigned short memreg_rx_done; /* RXDone Register (R/W) */ 220 + unsigned short pad2; 221 + unsigned short memreg_rx; /* RX Register (R/W) */ 222 + unsigned short pad3; 223 + unsigned short memreg_pc_interrupt_ack; /* PC intr Ack Register (W) */ 224 + unsigned short pad4; 225 + unsigned long memreg_card_present;/* Mask for Host to check (R) for 226 + * CARD_PRESENT_VALUE */ 227 + unsigned short memreg_tx_new; /* TX2 (new) Register (R/W) */ 228 + }; 229 + 230 + #define IODMADPR 0x00 /* DMA Data Port Register (R/W) */ 231 + 232 + #define CARD_PRESENT_VALUE (0xBEEFCAFEUL) 233 + 234 + #define MEMTX_TX 0x0001 235 + #define MEMRX_RX 0x0001 236 + #define MEMRX_RX_DONE 0x0001 237 + #define MEMRX_PCINTACKK 0x0001 238 + #define MEMRX_MEMSPURIOUSINT 0x0001 239 + 240 + #define NL_NUM_OF_PRIORITIES 3 241 + #define NL_NUM_OF_PROTOCOLS 3 242 + #define NL_NUM_OF_ADDRESSES NO_OF_IPW_CHANNELS 243 + 244 + struct ipw_hardware { 245 + unsigned int base_port; 246 + short hw_version; 247 + unsigned short ll_mtu; 248 + spinlock_t spinlock; 249 + 250 + int initializing; 251 + int init_loops; 252 + struct timer_list setup_timer; 253 + 254 + int tx_ready; 255 + struct list_head tx_queue[NL_NUM_OF_PRIORITIES]; 256 + /* True if any packets are queued for transmission */ 257 + int tx_queued; 258 + 259 + int rx_bytes_queued; 260 + struct list_head rx_queue; 261 + /* Pool of rx_packet structures that are not currently used. */ 262 + struct list_head rx_pool; 263 + int rx_pool_size; 264 + /* True if reception of data is blocked while userspace processes it. */ 265 + int blocking_rx; 266 + /* True if there is RX data ready on the hardware. */ 267 + int rx_ready; 268 + unsigned short last_memtx_serial; 269 + /* 270 + * Newer versions of the V2 card firmware send serial numbers in the 271 + * MemTX register. 'serial_number_detected' is set true when we detect 272 + * a non-zero serial number (indicating the new firmware). Thereafter, 273 + * the driver can safely ignore the Timer Recovery re-sends to avoid 274 + * out-of-sync problems. 275 + */ 276 + int serial_number_detected; 277 + struct work_struct work_rx; 278 + 279 + /* True if we are to send the set-up data to the hardware. */ 280 + int to_setup; 281 + 282 + /* Card has been removed */ 283 + int removed; 284 + /* Saved irq value when we disable the interrupt. */ 285 + int irq; 286 + /* True if this driver is shutting down. */ 287 + int shutting_down; 288 + /* Modem control lines */ 289 + unsigned int control_lines[NL_NUM_OF_ADDRESSES]; 290 + struct ipw_rx_packet *packet_assembler[NL_NUM_OF_ADDRESSES]; 291 + 292 + struct tasklet_struct tasklet; 293 + 294 + /* The handle for the network layer, for the sending of events to it. */ 295 + struct ipw_network *network; 296 + struct MEMINFREG __iomem *memory_info_regs; 297 + struct MEMCCR __iomem *memregs_CCR; 298 + void (*reboot_callback) (void *data); 299 + void *reboot_callback_data; 300 + 301 + unsigned short __iomem *memreg_tx; 302 + }; 303 + 304 + /* 305 + * Packet info structure for tx packets. 306 + * Note: not all the fields defined here are required for all protocols 307 + */ 308 + struct ipw_tx_packet { 309 + struct list_head queue; 310 + /* channel idx + 1 */ 311 + unsigned char dest_addr; 312 + /* SETUP, CTRL or DATA */ 313 + unsigned char protocol; 314 + /* Length of data block, which starts at the end of this structure */ 315 + unsigned short length; 316 + /* Sending state */ 317 + /* Offset of where we've sent up to so far */ 318 + unsigned long offset; 319 + /* Count of packet fragments, starting at 0 */ 320 + int fragment_count; 321 + 322 + /* Called after packet is sent and before is freed */ 323 + void (*packet_callback) (void *cb_data, unsigned int packet_length); 324 + void *callback_data; 325 + }; 326 + 327 + /* Signals from DTE */ 328 + #define COMCTRL_RTS 0 329 + #define COMCTRL_DTR 1 330 + 331 + /* Signals from DCE */ 332 + #define COMCTRL_CTS 2 333 + #define COMCTRL_DCD 3 334 + #define COMCTRL_DSR 4 335 + #define COMCTRL_RI 5 336 + 337 + struct ipw_control_packet_body { 338 + /* DTE signal or DCE signal */ 339 + unsigned char sig_no; 340 + /* 0: set signal, 1: clear signal */ 341 + unsigned char value; 342 + } __attribute__ ((__packed__)); 343 + 344 + struct ipw_control_packet { 345 + struct ipw_tx_packet header; 346 + struct ipw_control_packet_body body; 347 + }; 348 + 349 + struct ipw_rx_packet { 350 + struct list_head queue; 351 + unsigned int capacity; 352 + unsigned int length; 353 + unsigned int protocol; 354 + unsigned int channel_idx; 355 + }; 356 + 357 + #ifdef IPWIRELESS_STATE_DEBUG 358 + int ipwireless_dump_hardware_state(char *p, size_t limit, 359 + struct ipw_hardware *hw) 360 + { 361 + return snprintf(p, limit, 362 + "debug: initializing=%d\n" 363 + "debug: tx_ready=%d\n" 364 + "debug: tx_queued=%d\n" 365 + "debug: rx_ready=%d\n" 366 + "debug: rx_bytes_queued=%d\n" 367 + "debug: blocking_rx=%d\n" 368 + "debug: removed=%d\n" 369 + "debug: hardware.shutting_down=%d\n" 370 + "debug: to_setup=%d\n", 371 + hw->initializing, 372 + hw->tx_ready, 373 + hw->tx_queued, 374 + hw->rx_ready, 375 + hw->rx_bytes_queued, 376 + hw->blocking_rx, 377 + hw->removed, 378 + hw->shutting_down, 379 + hw->to_setup); 380 + } 381 + #endif 382 + 383 + static char *data_type(const unsigned char *buf, unsigned length) 384 + { 385 + struct nl_packet_header *hdr = (struct nl_packet_header *) buf; 386 + 387 + if (length == 0) 388 + return " "; 389 + 390 + if (hdr->packet_rank & NL_FIRST_PACKET) { 391 + switch (hdr->protocol) { 392 + case TL_PROTOCOLID_COM_DATA: return "DATA "; 393 + case TL_PROTOCOLID_COM_CTRL: return "CTRL "; 394 + case TL_PROTOCOLID_SETUP: return "SETUP"; 395 + default: return "???? "; 396 + } 397 + } else 398 + return " "; 399 + } 400 + 401 + #define DUMP_MAX_BYTES 64 402 + 403 + static void dump_data_bytes(const char *type, const unsigned char *data, 404 + unsigned length) 405 + { 406 + char prefix[56]; 407 + 408 + sprintf(prefix, IPWIRELESS_PCCARD_NAME ": %s %s ", 409 + type, data_type(data, length)); 410 + print_hex_dump_bytes(prefix, 0, (void *)data, 411 + length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES); 412 + } 413 + 414 + static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, 415 + unsigned length) 416 + { 417 + int i; 418 + unsigned long flags; 419 + 420 + start_timing(); 421 + 422 + if (length == 0) 423 + return 0; 424 + 425 + if (length > hw->ll_mtu) 426 + return -1; 427 + 428 + if (ipwireless_debug) 429 + dump_data_bytes("send", data, length); 430 + 431 + spin_lock_irqsave(&hw->spinlock, flags); 432 + 433 + if (hw->hw_version == HW_VERSION_1) { 434 + outw((unsigned short) length, hw->base_port + IODWR); 435 + 436 + for (i = 0; i < length; i += 2) { 437 + unsigned short d = data[i]; 438 + __le16 raw_data; 439 + 440 + if (likely(i + 1 < length)) 441 + d |= data[i + 1] << 8; 442 + raw_data = cpu_to_le16(d); 443 + outw(raw_data, hw->base_port + IODWR); 444 + } 445 + 446 + outw(DCR_TXDONE, hw->base_port + IODCR); 447 + } else if (hw->hw_version == HW_VERSION_2) { 448 + outw((unsigned short) length, hw->base_port + IODMADPR); 449 + 450 + for (i = 0; i < length; i += 2) { 451 + unsigned short d = data[i]; 452 + __le16 raw_data; 453 + 454 + if ((i + 1 < length)) 455 + d |= data[i + 1] << 8; 456 + raw_data = cpu_to_le16(d); 457 + outw(raw_data, hw->base_port + IODMADPR); 458 + } 459 + while ((i & 3) != 2) { 460 + outw((unsigned short) 0xDEAD, hw->base_port + IODMADPR); 461 + i += 2; 462 + } 463 + writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx); 464 + } 465 + 466 + spin_unlock_irqrestore(&hw->spinlock, flags); 467 + 468 + end_write_timing(length); 469 + 470 + return 0; 471 + } 472 + 473 + static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) 474 + { 475 + unsigned short fragment_data_len; 476 + unsigned short data_left = packet->length - packet->offset; 477 + unsigned short header_size; 478 + union nl_packet pkt; 479 + 480 + header_size = 481 + (packet->fragment_count == 0) 482 + ? NL_FIRST_PACKET_HEADER_SIZE 483 + : NL_FOLLOWING_PACKET_HEADER_SIZE; 484 + fragment_data_len = hw->ll_mtu - header_size; 485 + if (data_left < fragment_data_len) 486 + fragment_data_len = data_left; 487 + 488 + pkt.hdr_first.protocol = packet->protocol; 489 + pkt.hdr_first.address = packet->dest_addr; 490 + pkt.hdr_first.packet_rank = 0; 491 + 492 + /* First packet? */ 493 + if (packet->fragment_count == 0) { 494 + pkt.hdr_first.packet_rank |= NL_FIRST_PACKET; 495 + pkt.hdr_first.length_lsb = (unsigned char) packet->length; 496 + pkt.hdr_first.length_msb = 497 + (unsigned char) (packet->length >> 8); 498 + } 499 + 500 + memcpy(pkt.rawpkt + header_size, 501 + ((unsigned char *) packet) + sizeof(struct ipw_tx_packet) + 502 + packet->offset, fragment_data_len); 503 + packet->offset += fragment_data_len; 504 + packet->fragment_count++; 505 + 506 + /* Last packet? (May also be first packet.) */ 507 + if (packet->offset == packet->length) 508 + pkt.hdr_first.packet_rank |= NL_LAST_PACKET; 509 + do_send_fragment(hw, pkt.rawpkt, header_size + fragment_data_len); 510 + 511 + /* If this packet has unsent data, then re-queue it. */ 512 + if (packet->offset < packet->length) { 513 + /* 514 + * Re-queue it at the head of the highest priority queue so 515 + * it goes before all other packets 516 + */ 517 + unsigned long flags; 518 + 519 + spin_lock_irqsave(&hw->spinlock, flags); 520 + list_add(&packet->queue, &hw->tx_queue[0]); 521 + spin_unlock_irqrestore(&hw->spinlock, flags); 522 + } else { 523 + if (packet->packet_callback) 524 + packet->packet_callback(packet->callback_data, 525 + packet->length); 526 + kfree(packet); 527 + } 528 + 529 + return 0; 530 + } 531 + 532 + static void ipw_setup_hardware(struct ipw_hardware *hw) 533 + { 534 + unsigned long flags; 535 + 536 + spin_lock_irqsave(&hw->spinlock, flags); 537 + if (hw->hw_version == HW_VERSION_1) { 538 + /* Reset RX FIFO */ 539 + outw(DCR_RXRESET, hw->base_port + IODCR); 540 + /* SB: Reset TX FIFO */ 541 + outw(DCR_TXRESET, hw->base_port + IODCR); 542 + 543 + /* Enable TX and RX interrupts. */ 544 + outw(IER_TXENABLED | IER_RXENABLED, hw->base_port + IOIER); 545 + } else { 546 + /* 547 + * Set INTRACK bit (bit 0), which means we must explicitly 548 + * acknowledge interrupts by clearing bit 2 of reg_config_and_status. 549 + */ 550 + unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status); 551 + 552 + csr |= 1; 553 + writew(csr, &hw->memregs_CCR->reg_config_and_status); 554 + } 555 + spin_unlock_irqrestore(&hw->spinlock, flags); 556 + } 557 + 558 + /* 559 + * If 'packet' is NULL, then this function allocates a new packet, setting its 560 + * length to 0 and ensuring it has the specified minimum amount of free space. 561 + * 562 + * If 'packet' is not NULL, then this function enlarges it if it doesn't 563 + * have the specified minimum amount of free space. 564 + * 565 + */ 566 + static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, 567 + struct ipw_rx_packet *packet, 568 + int minimum_free_space) 569 + { 570 + 571 + if (!packet) { 572 + unsigned long flags; 573 + 574 + /* 575 + * If this is the first fragment, then we will need to fetch a 576 + * packet to put it in. 577 + */ 578 + spin_lock_irqsave(&hw->spinlock, flags); 579 + /* If we have one in our pool, then pull it out. */ 580 + if (!list_empty(&hw->rx_pool)) { 581 + packet = list_first_entry(&hw->rx_pool, 582 + struct ipw_rx_packet, queue); 583 + list_del(&packet->queue); 584 + hw->rx_pool_size--; 585 + spin_unlock_irqrestore(&hw->spinlock, flags); 586 + } else { 587 + /* Otherwise allocate a new one. */ 588 + static int min_capacity = 256; 589 + int new_capacity; 590 + 591 + spin_unlock_irqrestore(&hw->spinlock, flags); 592 + new_capacity = 593 + minimum_free_space > min_capacity 594 + ? minimum_free_space 595 + : min_capacity; 596 + packet = kmalloc(sizeof(struct ipw_rx_packet) 597 + + new_capacity, GFP_ATOMIC); 598 + if (!packet) 599 + return NULL; 600 + packet->capacity = new_capacity; 601 + } 602 + packet->length = 0; 603 + } 604 + 605 + /* 606 + * If this packet does not have sufficient capacity for the data we 607 + * want to add, then make it bigger. 608 + */ 609 + if (packet->length + minimum_free_space > packet->capacity) { 610 + struct ipw_rx_packet *old_packet = packet; 611 + 612 + packet = kmalloc(sizeof(struct ipw_rx_packet) + 613 + old_packet->length + minimum_free_space, 614 + GFP_ATOMIC); 615 + if (!packet) 616 + return NULL; 617 + memcpy(packet, old_packet, 618 + sizeof(struct ipw_rx_packet) 619 + + old_packet->length); 620 + packet->capacity = old_packet->length + minimum_free_space; 621 + kfree(old_packet); 622 + } 623 + 624 + return packet; 625 + } 626 + 627 + static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet) 628 + { 629 + if (hw->rx_pool_size > 6) 630 + kfree(packet); 631 + else { 632 + hw->rx_pool_size++; 633 + list_add_tail(&packet->queue, &hw->rx_pool); 634 + } 635 + } 636 + 637 + static void queue_received_packet(struct ipw_hardware *hw, 638 + unsigned int protocol, unsigned int address, 639 + unsigned char *data, int length, int is_last) 640 + { 641 + unsigned int channel_idx = address - 1; 642 + struct ipw_rx_packet *packet = NULL; 643 + unsigned long flags; 644 + 645 + /* Discard packet if channel index is out of range. */ 646 + if (channel_idx >= NL_NUM_OF_ADDRESSES) { 647 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 648 + ": data packet has bad address %u\n", address); 649 + return; 650 + } 651 + 652 + /* 653 + * ->packet_assembler is safe to touch unlocked, this is the only place 654 + */ 655 + if (protocol == TL_PROTOCOLID_COM_DATA) { 656 + struct ipw_rx_packet **assem = 657 + &hw->packet_assembler[channel_idx]; 658 + 659 + /* 660 + * Create a new packet, or assembler already contains one 661 + * enlarge it by 'length' bytes. 662 + */ 663 + (*assem) = pool_allocate(hw, *assem, length); 664 + if (!(*assem)) { 665 + printk(KERN_ERR IPWIRELESS_PCCARD_NAME 666 + ": no memory for incomming data packet, dropped!\n"); 667 + return; 668 + } 669 + (*assem)->protocol = protocol; 670 + (*assem)->channel_idx = channel_idx; 671 + 672 + /* Append this packet data onto existing data. */ 673 + memcpy((unsigned char *)(*assem) + 674 + sizeof(struct ipw_rx_packet) 675 + + (*assem)->length, data, length); 676 + (*assem)->length += length; 677 + if (is_last) { 678 + packet = *assem; 679 + *assem = NULL; 680 + /* Count queued DATA bytes only */ 681 + spin_lock_irqsave(&hw->spinlock, flags); 682 + hw->rx_bytes_queued += packet->length; 683 + spin_unlock_irqrestore(&hw->spinlock, flags); 684 + } 685 + } else { 686 + /* If it's a CTRL packet, don't assemble, just queue it. */ 687 + packet = pool_allocate(hw, NULL, length); 688 + if (!packet) { 689 + printk(KERN_ERR IPWIRELESS_PCCARD_NAME 690 + ": no memory for incomming ctrl packet, dropped!\n"); 691 + return; 692 + } 693 + packet->protocol = protocol; 694 + packet->channel_idx = channel_idx; 695 + memcpy((unsigned char *)packet + sizeof(struct ipw_rx_packet), 696 + data, length); 697 + packet->length = length; 698 + } 699 + 700 + /* 701 + * If this is the last packet, then send the assembled packet on to the 702 + * network layer. 703 + */ 704 + if (packet) { 705 + spin_lock_irqsave(&hw->spinlock, flags); 706 + list_add_tail(&packet->queue, &hw->rx_queue); 707 + /* Block reception of incoming packets if queue is full. */ 708 + hw->blocking_rx = 709 + hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE; 710 + 711 + spin_unlock_irqrestore(&hw->spinlock, flags); 712 + schedule_work(&hw->work_rx); 713 + } 714 + } 715 + 716 + /* 717 + * Workqueue callback 718 + */ 719 + static void ipw_receive_data_work(struct work_struct *work_rx) 720 + { 721 + struct ipw_hardware *hw = 722 + container_of(work_rx, struct ipw_hardware, work_rx); 723 + unsigned long flags; 724 + 725 + spin_lock_irqsave(&hw->spinlock, flags); 726 + while (!list_empty(&hw->rx_queue)) { 727 + struct ipw_rx_packet *packet = 728 + list_first_entry(&hw->rx_queue, 729 + struct ipw_rx_packet, queue); 730 + 731 + if (hw->shutting_down) 732 + break; 733 + list_del(&packet->queue); 734 + 735 + /* 736 + * Note: ipwireless_network_packet_received must be called in a 737 + * process context (i.e. via schedule_work) because the tty 738 + * output code can sleep in the tty_flip_buffer_push call. 739 + */ 740 + if (packet->protocol == TL_PROTOCOLID_COM_DATA) { 741 + if (hw->network != NULL) { 742 + /* If the network hasn't been disconnected. */ 743 + spin_unlock_irqrestore(&hw->spinlock, flags); 744 + /* 745 + * This must run unlocked due to tty processing 746 + * and mutex locking 747 + */ 748 + ipwireless_network_packet_received( 749 + hw->network, 750 + packet->channel_idx, 751 + (unsigned char *)packet 752 + + sizeof(struct ipw_rx_packet), 753 + packet->length); 754 + spin_lock_irqsave(&hw->spinlock, flags); 755 + } 756 + /* Count queued DATA bytes only */ 757 + hw->rx_bytes_queued -= packet->length; 758 + } else { 759 + /* 760 + * This is safe to be called locked, callchain does 761 + * not block 762 + */ 763 + handle_received_CTRL_packet(hw, packet->channel_idx, 764 + (unsigned char *)packet 765 + + sizeof(struct ipw_rx_packet), 766 + packet->length); 767 + } 768 + pool_free(hw, packet); 769 + /* 770 + * Unblock reception of incoming packets if queue is no longer 771 + * full. 772 + */ 773 + hw->blocking_rx = 774 + hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE; 775 + if (hw->shutting_down) 776 + break; 777 + } 778 + spin_unlock_irqrestore(&hw->spinlock, flags); 779 + } 780 + 781 + static void handle_received_CTRL_packet(struct ipw_hardware *hw, 782 + unsigned int channel_idx, 783 + unsigned char *data, int len) 784 + { 785 + struct ipw_control_packet_body *body = 786 + (struct ipw_control_packet_body *) data; 787 + unsigned int changed_mask; 788 + 789 + if (len != sizeof(struct ipw_control_packet_body)) { 790 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 791 + ": control packet was %d bytes - wrong size!\n", 792 + len); 793 + return; 794 + } 795 + 796 + switch (body->sig_no) { 797 + case COMCTRL_CTS: 798 + changed_mask = IPW_CONTROL_LINE_CTS; 799 + break; 800 + case COMCTRL_DCD: 801 + changed_mask = IPW_CONTROL_LINE_DCD; 802 + break; 803 + case COMCTRL_DSR: 804 + changed_mask = IPW_CONTROL_LINE_DSR; 805 + break; 806 + case COMCTRL_RI: 807 + changed_mask = IPW_CONTROL_LINE_RI; 808 + break; 809 + default: 810 + changed_mask = 0; 811 + } 812 + 813 + if (changed_mask != 0) { 814 + if (body->value) 815 + hw->control_lines[channel_idx] |= changed_mask; 816 + else 817 + hw->control_lines[channel_idx] &= ~changed_mask; 818 + if (hw->network) 819 + ipwireless_network_notify_control_line_change( 820 + hw->network, 821 + channel_idx, 822 + hw->control_lines[channel_idx], 823 + changed_mask); 824 + } 825 + } 826 + 827 + static void handle_received_packet(struct ipw_hardware *hw, 828 + union nl_packet *packet, 829 + unsigned short len) 830 + { 831 + unsigned int protocol = packet->hdr.protocol; 832 + unsigned int address = packet->hdr.address; 833 + unsigned int header_length; 834 + unsigned char *data; 835 + unsigned int data_len; 836 + int is_last = packet->hdr.packet_rank & NL_LAST_PACKET; 837 + 838 + if (packet->hdr.packet_rank & NL_FIRST_PACKET) 839 + header_length = NL_FIRST_PACKET_HEADER_SIZE; 840 + else 841 + header_length = NL_FOLLOWING_PACKET_HEADER_SIZE; 842 + 843 + data = packet->rawpkt + header_length; 844 + data_len = len - header_length; 845 + switch (protocol) { 846 + case TL_PROTOCOLID_COM_DATA: 847 + case TL_PROTOCOLID_COM_CTRL: 848 + queue_received_packet(hw, protocol, address, data, data_len, 849 + is_last); 850 + break; 851 + case TL_PROTOCOLID_SETUP: 852 + handle_received_SETUP_packet(hw, address, data, data_len, 853 + is_last); 854 + break; 855 + } 856 + } 857 + 858 + static void acknowledge_data_read(struct ipw_hardware *hw) 859 + { 860 + if (hw->hw_version == HW_VERSION_1) 861 + outw(DCR_RXDONE, hw->base_port + IODCR); 862 + else 863 + writew(MEMRX_PCINTACKK, 864 + &hw->memory_info_regs->memreg_pc_interrupt_ack); 865 + } 866 + 867 + /* 868 + * Retrieve a packet from the IPW hardware. 869 + */ 870 + static void do_receive_packet(struct ipw_hardware *hw) 871 + { 872 + unsigned len; 873 + unsigned int i; 874 + unsigned char pkt[LL_MTU_MAX]; 875 + 876 + start_timing(); 877 + 878 + if (hw->hw_version == HW_VERSION_1) { 879 + len = inw(hw->base_port + IODRR); 880 + if (len > hw->ll_mtu) { 881 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 882 + ": received a packet of %u bytes - " 883 + "longer than the MTU!\n", len); 884 + outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR); 885 + return; 886 + } 887 + 888 + for (i = 0; i < len; i += 2) { 889 + __le16 raw_data = inw(hw->base_port + IODRR); 890 + unsigned short data = le16_to_cpu(raw_data); 891 + 892 + pkt[i] = (unsigned char) data; 893 + pkt[i + 1] = (unsigned char) (data >> 8); 894 + } 895 + } else { 896 + len = inw(hw->base_port + IODMADPR); 897 + if (len > hw->ll_mtu) { 898 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 899 + ": received a packet of %u bytes - " 900 + "longer than the MTU!\n", len); 901 + writew(MEMRX_PCINTACKK, 902 + &hw->memory_info_regs->memreg_pc_interrupt_ack); 903 + return; 904 + } 905 + 906 + for (i = 0; i < len; i += 2) { 907 + __le16 raw_data = inw(hw->base_port + IODMADPR); 908 + unsigned short data = le16_to_cpu(raw_data); 909 + 910 + pkt[i] = (unsigned char) data; 911 + pkt[i + 1] = (unsigned char) (data >> 8); 912 + } 913 + 914 + while ((i & 3) != 2) { 915 + inw(hw->base_port + IODMADPR); 916 + i += 2; 917 + } 918 + } 919 + 920 + acknowledge_data_read(hw); 921 + 922 + if (ipwireless_debug) 923 + dump_data_bytes("recv", pkt, len); 924 + 925 + handle_received_packet(hw, (union nl_packet *) pkt, len); 926 + 927 + end_read_timing(len); 928 + } 929 + 930 + static int get_current_packet_priority(struct ipw_hardware *hw) 931 + { 932 + /* 933 + * If we're initializing, don't send anything of higher priority than 934 + * PRIO_SETUP. The network layer therefore need not care about 935 + * hardware initialization - any of its stuff will simply be queued 936 + * until setup is complete. 937 + */ 938 + return (hw->to_setup || hw->initializing 939 + ? PRIO_SETUP + 1 : 940 + NL_NUM_OF_PRIORITIES); 941 + } 942 + 943 + /* 944 + * return 1 if something has been received from hw 945 + */ 946 + static int get_packets_from_hw(struct ipw_hardware *hw) 947 + { 948 + int received = 0; 949 + unsigned long flags; 950 + 951 + spin_lock_irqsave(&hw->spinlock, flags); 952 + while (hw->rx_ready && !hw->blocking_rx) { 953 + received = 1; 954 + hw->rx_ready--; 955 + spin_unlock_irqrestore(&hw->spinlock, flags); 956 + 957 + do_receive_packet(hw); 958 + 959 + spin_lock_irqsave(&hw->spinlock, flags); 960 + } 961 + spin_unlock_irqrestore(&hw->spinlock, flags); 962 + 963 + return received; 964 + } 965 + 966 + /* 967 + * Send pending packet up to given priority, prioritize SETUP data until 968 + * hardware is fully setup. 969 + * 970 + * return 1 if more packets can be sent 971 + */ 972 + static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) 973 + { 974 + int more_to_send = 0; 975 + unsigned long flags; 976 + 977 + spin_lock_irqsave(&hw->spinlock, flags); 978 + if (hw->tx_queued && hw->tx_ready != 0) { 979 + int priority; 980 + struct ipw_tx_packet *packet = NULL; 981 + 982 + hw->tx_ready--; 983 + 984 + /* Pick a packet */ 985 + for (priority = 0; priority < priority_limit; priority++) { 986 + if (!list_empty(&hw->tx_queue[priority])) { 987 + packet = list_first_entry( 988 + &hw->tx_queue[priority], 989 + struct ipw_tx_packet, 990 + queue); 991 + 992 + list_del(&packet->queue); 993 + 994 + break; 995 + } 996 + } 997 + if (!packet) { 998 + hw->tx_queued = 0; 999 + spin_unlock_irqrestore(&hw->spinlock, flags); 1000 + return 0; 1001 + } 1002 + spin_unlock_irqrestore(&hw->spinlock, flags); 1003 + 1004 + /* Send */ 1005 + do_send_packet(hw, packet); 1006 + 1007 + /* Check if more to send */ 1008 + spin_lock_irqsave(&hw->spinlock, flags); 1009 + for (priority = 0; priority < priority_limit; priority++) 1010 + if (!list_empty(&hw->tx_queue[priority])) { 1011 + more_to_send = 1; 1012 + break; 1013 + } 1014 + 1015 + if (!more_to_send) 1016 + hw->tx_queued = 0; 1017 + } 1018 + spin_unlock_irqrestore(&hw->spinlock, flags); 1019 + 1020 + return more_to_send; 1021 + } 1022 + 1023 + /* 1024 + * Send and receive all queued packets. 1025 + */ 1026 + static void ipwireless_do_tasklet(unsigned long hw_) 1027 + { 1028 + struct ipw_hardware *hw = (struct ipw_hardware *) hw_; 1029 + unsigned long flags; 1030 + 1031 + spin_lock_irqsave(&hw->spinlock, flags); 1032 + if (hw->shutting_down) { 1033 + spin_unlock_irqrestore(&hw->spinlock, flags); 1034 + return; 1035 + } 1036 + 1037 + if (hw->to_setup == 1) { 1038 + /* 1039 + * Initial setup data sent to hardware 1040 + */ 1041 + hw->to_setup = 2; 1042 + spin_unlock_irqrestore(&hw->spinlock, flags); 1043 + 1044 + ipw_setup_hardware(hw); 1045 + ipw_send_setup_packet(hw); 1046 + 1047 + send_pending_packet(hw, PRIO_SETUP + 1); 1048 + get_packets_from_hw(hw); 1049 + } else { 1050 + int priority_limit = get_current_packet_priority(hw); 1051 + int again; 1052 + 1053 + spin_unlock_irqrestore(&hw->spinlock, flags); 1054 + 1055 + do { 1056 + again = send_pending_packet(hw, priority_limit); 1057 + again |= get_packets_from_hw(hw); 1058 + } while (again); 1059 + } 1060 + } 1061 + 1062 + /* 1063 + * return true if the card is physically present. 1064 + */ 1065 + static int is_card_present(struct ipw_hardware *hw) 1066 + { 1067 + if (hw->hw_version == HW_VERSION_1) 1068 + return inw(hw->base_port + IOIR) != 0xFFFF; 1069 + else 1070 + return readl(&hw->memory_info_regs->memreg_card_present) == 1071 + CARD_PRESENT_VALUE; 1072 + } 1073 + 1074 + static irqreturn_t ipwireless_handle_v1_interrupt(int irq, 1075 + struct ipw_hardware *hw) 1076 + { 1077 + unsigned short irqn; 1078 + 1079 + irqn = inw(hw->base_port + IOIR); 1080 + 1081 + /* Check if card is present */ 1082 + if (irqn == 0xFFFF) 1083 + return IRQ_NONE; 1084 + else if (irqn != 0) { 1085 + unsigned short ack = 0; 1086 + unsigned long flags; 1087 + 1088 + /* Transmit complete. */ 1089 + if (irqn & IR_TXINTR) { 1090 + ack |= IR_TXINTR; 1091 + spin_lock_irqsave(&hw->spinlock, flags); 1092 + hw->tx_ready++; 1093 + spin_unlock_irqrestore(&hw->spinlock, flags); 1094 + } 1095 + /* Received data */ 1096 + if (irqn & IR_RXINTR) { 1097 + ack |= IR_RXINTR; 1098 + spin_lock_irqsave(&hw->spinlock, flags); 1099 + hw->rx_ready++; 1100 + spin_unlock_irqrestore(&hw->spinlock, flags); 1101 + } 1102 + if (ack != 0) { 1103 + outw(ack, hw->base_port + IOIR); 1104 + tasklet_schedule(&hw->tasklet); 1105 + } 1106 + return IRQ_HANDLED; 1107 + } 1108 + return IRQ_NONE; 1109 + } 1110 + 1111 + static void acknowledge_pcmcia_interrupt(struct ipw_hardware *hw) 1112 + { 1113 + unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status); 1114 + 1115 + csr &= 0xfffd; 1116 + writew(csr, &hw->memregs_CCR->reg_config_and_status); 1117 + } 1118 + 1119 + static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, 1120 + struct ipw_hardware *hw) 1121 + { 1122 + int tx = 0; 1123 + int rx = 0; 1124 + int rx_repeat = 0; 1125 + int try_mem_tx_old; 1126 + unsigned long flags; 1127 + 1128 + do { 1129 + 1130 + unsigned short memtx = readw(hw->memreg_tx); 1131 + unsigned short memtx_serial; 1132 + unsigned short memrxdone = 1133 + readw(&hw->memory_info_regs->memreg_rx_done); 1134 + 1135 + try_mem_tx_old = 0; 1136 + 1137 + /* check whether the interrupt was generated by ipwireless card */ 1138 + if (!(memtx & MEMTX_TX) && !(memrxdone & MEMRX_RX_DONE)) { 1139 + 1140 + /* check if the card uses memreg_tx_old register */ 1141 + if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) { 1142 + memtx = readw(&hw->memory_info_regs->memreg_tx_old); 1143 + if (memtx & MEMTX_TX) { 1144 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 1145 + ": Using memreg_tx_old\n"); 1146 + hw->memreg_tx = 1147 + &hw->memory_info_regs->memreg_tx_old; 1148 + } else { 1149 + return IRQ_NONE; 1150 + } 1151 + } else { 1152 + return IRQ_NONE; 1153 + } 1154 + } 1155 + 1156 + /* 1157 + * See if the card is physically present. Note that while it is 1158 + * powering up, it appears not to be present. 1159 + */ 1160 + if (!is_card_present(hw)) { 1161 + acknowledge_pcmcia_interrupt(hw); 1162 + return IRQ_HANDLED; 1163 + } 1164 + 1165 + memtx_serial = memtx & (unsigned short) 0xff00; 1166 + if (memtx & MEMTX_TX) { 1167 + writew(memtx_serial, hw->memreg_tx); 1168 + 1169 + if (hw->serial_number_detected) { 1170 + if (memtx_serial != hw->last_memtx_serial) { 1171 + hw->last_memtx_serial = memtx_serial; 1172 + spin_lock_irqsave(&hw->spinlock, flags); 1173 + hw->rx_ready++; 1174 + spin_unlock_irqrestore(&hw->spinlock, flags); 1175 + rx = 1; 1176 + } else 1177 + /* Ignore 'Timer Recovery' duplicates. */ 1178 + rx_repeat = 1; 1179 + } else { 1180 + /* 1181 + * If a non-zero serial number is seen, then enable 1182 + * serial number checking. 1183 + */ 1184 + if (memtx_serial != 0) { 1185 + hw->serial_number_detected = 1; 1186 + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME 1187 + ": memreg_tx serial num detected\n"); 1188 + 1189 + spin_lock_irqsave(&hw->spinlock, flags); 1190 + hw->rx_ready++; 1191 + spin_unlock_irqrestore(&hw->spinlock, flags); 1192 + } 1193 + rx = 1; 1194 + } 1195 + } 1196 + if (memrxdone & MEMRX_RX_DONE) { 1197 + writew(0, &hw->memory_info_regs->memreg_rx_done); 1198 + spin_lock_irqsave(&hw->spinlock, flags); 1199 + hw->tx_ready++; 1200 + spin_unlock_irqrestore(&hw->spinlock, flags); 1201 + tx = 1; 1202 + } 1203 + if (tx) 1204 + writew(MEMRX_PCINTACKK, 1205 + &hw->memory_info_regs->memreg_pc_interrupt_ack); 1206 + 1207 + acknowledge_pcmcia_interrupt(hw); 1208 + 1209 + if (tx || rx) 1210 + tasklet_schedule(&hw->tasklet); 1211 + else if (!rx_repeat) { 1212 + if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) { 1213 + if (hw->serial_number_detected) 1214 + printk(KERN_WARNING IPWIRELESS_PCCARD_NAME 1215 + ": spurious interrupt - new_tx mode\n"); 1216 + else { 1217 + printk(KERN_WARNING IPWIRELESS_PCCARD_NAME 1218 + ": no valid memreg_tx value - " 1219 + "switching to the old memreg_tx\n"); 1220 + hw->memreg_tx = 1221 + &hw->memory_info_regs->memreg_tx_old; 1222 + try_mem_tx_old = 1; 1223 + } 1224 + } else 1225 + printk(KERN_WARNING IPWIRELESS_PCCARD_NAME 1226 + ": spurious interrupt - old_tx mode\n"); 1227 + } 1228 + 1229 + } while (try_mem_tx_old == 1); 1230 + 1231 + return IRQ_HANDLED; 1232 + } 1233 + 1234 + irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs) 1235 + { 1236 + struct ipw_hardware *hw = dev_id; 1237 + 1238 + if (hw->hw_version == HW_VERSION_1) 1239 + return ipwireless_handle_v1_interrupt(irq, hw); 1240 + else 1241 + return ipwireless_handle_v2_v3_interrupt(irq, hw); 1242 + } 1243 + 1244 + static void flush_packets_to_hw(struct ipw_hardware *hw) 1245 + { 1246 + int priority_limit; 1247 + unsigned long flags; 1248 + 1249 + spin_lock_irqsave(&hw->spinlock, flags); 1250 + priority_limit = get_current_packet_priority(hw); 1251 + spin_unlock_irqrestore(&hw->spinlock, flags); 1252 + 1253 + while (send_pending_packet(hw, priority_limit)); 1254 + } 1255 + 1256 + static void send_packet(struct ipw_hardware *hw, int priority, 1257 + struct ipw_tx_packet *packet) 1258 + { 1259 + unsigned long flags; 1260 + 1261 + spin_lock_irqsave(&hw->spinlock, flags); 1262 + list_add_tail(&packet->queue, &hw->tx_queue[priority]); 1263 + hw->tx_queued = 1; 1264 + spin_unlock_irqrestore(&hw->spinlock, flags); 1265 + 1266 + flush_packets_to_hw(hw); 1267 + } 1268 + 1269 + /* Create data packet, non-atomic allocation */ 1270 + static void *alloc_data_packet(int data_size, 1271 + unsigned char dest_addr, 1272 + unsigned char protocol) 1273 + { 1274 + struct ipw_tx_packet *packet = kzalloc( 1275 + sizeof(struct ipw_tx_packet) + data_size, 1276 + GFP_ATOMIC); 1277 + 1278 + if (!packet) 1279 + return NULL; 1280 + 1281 + INIT_LIST_HEAD(&packet->queue); 1282 + packet->dest_addr = dest_addr; 1283 + packet->protocol = protocol; 1284 + packet->length = data_size; 1285 + 1286 + return packet; 1287 + } 1288 + 1289 + static void *alloc_ctrl_packet(int header_size, 1290 + unsigned char dest_addr, 1291 + unsigned char protocol, 1292 + unsigned char sig_no) 1293 + { 1294 + /* 1295 + * sig_no is located right after ipw_tx_packet struct in every 1296 + * CTRL or SETUP packets, we can use ipw_control_packet as a 1297 + * common struct 1298 + */ 1299 + struct ipw_control_packet *packet = kzalloc(header_size, GFP_ATOMIC); 1300 + 1301 + if (!packet) 1302 + return NULL; 1303 + 1304 + INIT_LIST_HEAD(&packet->header.queue); 1305 + packet->header.dest_addr = dest_addr; 1306 + packet->header.protocol = protocol; 1307 + packet->header.length = header_size - sizeof(struct ipw_tx_packet); 1308 + packet->body.sig_no = sig_no; 1309 + 1310 + return packet; 1311 + } 1312 + 1313 + int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx, 1314 + unsigned char *data, unsigned int length, 1315 + void (*callback) (void *cb, unsigned int length), 1316 + void *callback_data) 1317 + { 1318 + struct ipw_tx_packet *packet; 1319 + 1320 + packet = alloc_data_packet(length, 1321 + (unsigned char) (channel_idx + 1), 1322 + TL_PROTOCOLID_COM_DATA); 1323 + if (!packet) 1324 + return -ENOMEM; 1325 + packet->packet_callback = callback; 1326 + packet->callback_data = callback_data; 1327 + memcpy((unsigned char *) packet + 1328 + sizeof(struct ipw_tx_packet), data, length); 1329 + 1330 + send_packet(hw, PRIO_DATA, packet); 1331 + return 0; 1332 + } 1333 + 1334 + static int set_control_line(struct ipw_hardware *hw, int prio, 1335 + unsigned int channel_idx, int line, int state) 1336 + { 1337 + struct ipw_control_packet *packet; 1338 + int protocolid = TL_PROTOCOLID_COM_CTRL; 1339 + 1340 + if (prio == PRIO_SETUP) 1341 + protocolid = TL_PROTOCOLID_SETUP; 1342 + 1343 + packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet), 1344 + (unsigned char) (channel_idx + 1), 1345 + protocolid, line); 1346 + if (!packet) 1347 + return -ENOMEM; 1348 + packet->header.length = sizeof(struct ipw_control_packet_body); 1349 + packet->body.value = (unsigned char) (state == 0 ? 0 : 1); 1350 + send_packet(hw, prio, &packet->header); 1351 + return 0; 1352 + } 1353 + 1354 + 1355 + static int set_DTR(struct ipw_hardware *hw, int priority, 1356 + unsigned int channel_idx, int state) 1357 + { 1358 + if (state != 0) 1359 + hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_DTR; 1360 + else 1361 + hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_DTR; 1362 + 1363 + return set_control_line(hw, priority, channel_idx, COMCTRL_DTR, state); 1364 + } 1365 + 1366 + static int set_RTS(struct ipw_hardware *hw, int priority, 1367 + unsigned int channel_idx, int state) 1368 + { 1369 + if (state != 0) 1370 + hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_RTS; 1371 + else 1372 + hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_RTS; 1373 + 1374 + return set_control_line(hw, priority, channel_idx, COMCTRL_RTS, state); 1375 + } 1376 + 1377 + int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, 1378 + int state) 1379 + { 1380 + return set_DTR(hw, PRIO_CTRL, channel_idx, state); 1381 + } 1382 + 1383 + int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, 1384 + int state) 1385 + { 1386 + return set_RTS(hw, PRIO_CTRL, channel_idx, state); 1387 + } 1388 + 1389 + struct ipw_setup_get_version_query_packet { 1390 + struct ipw_tx_packet header; 1391 + struct tl_setup_get_version_qry body; 1392 + }; 1393 + 1394 + struct ipw_setup_config_packet { 1395 + struct ipw_tx_packet header; 1396 + struct tl_setup_config_msg body; 1397 + }; 1398 + 1399 + struct ipw_setup_config_done_packet { 1400 + struct ipw_tx_packet header; 1401 + struct tl_setup_config_done_msg body; 1402 + }; 1403 + 1404 + struct ipw_setup_open_packet { 1405 + struct ipw_tx_packet header; 1406 + struct tl_setup_open_msg body; 1407 + }; 1408 + 1409 + struct ipw_setup_info_packet { 1410 + struct ipw_tx_packet header; 1411 + struct tl_setup_info_msg body; 1412 + }; 1413 + 1414 + struct ipw_setup_reboot_msg_ack { 1415 + struct ipw_tx_packet header; 1416 + struct TlSetupRebootMsgAck body; 1417 + }; 1418 + 1419 + /* This handles the actual initialization of the card */ 1420 + static void __handle_setup_get_version_rsp(struct ipw_hardware *hw) 1421 + { 1422 + struct ipw_setup_config_packet *config_packet; 1423 + struct ipw_setup_config_done_packet *config_done_packet; 1424 + struct ipw_setup_open_packet *open_packet; 1425 + struct ipw_setup_info_packet *info_packet; 1426 + int port; 1427 + unsigned int channel_idx; 1428 + 1429 + /* generate config packet */ 1430 + for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) { 1431 + config_packet = alloc_ctrl_packet( 1432 + sizeof(struct ipw_setup_config_packet), 1433 + ADDR_SETUP_PROT, 1434 + TL_PROTOCOLID_SETUP, 1435 + TL_SETUP_SIGNO_CONFIG_MSG); 1436 + if (!config_packet) 1437 + goto exit_nomem; 1438 + config_packet->header.length = sizeof(struct tl_setup_config_msg); 1439 + config_packet->body.port_no = port; 1440 + config_packet->body.prio_data = PRIO_DATA; 1441 + config_packet->body.prio_ctrl = PRIO_CTRL; 1442 + send_packet(hw, PRIO_SETUP, &config_packet->header); 1443 + } 1444 + config_done_packet = alloc_ctrl_packet( 1445 + sizeof(struct ipw_setup_config_done_packet), 1446 + ADDR_SETUP_PROT, 1447 + TL_PROTOCOLID_SETUP, 1448 + TL_SETUP_SIGNO_CONFIG_DONE_MSG); 1449 + if (!config_done_packet) 1450 + goto exit_nomem; 1451 + config_done_packet->header.length = sizeof(struct tl_setup_config_done_msg); 1452 + send_packet(hw, PRIO_SETUP, &config_done_packet->header); 1453 + 1454 + /* generate open packet */ 1455 + for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) { 1456 + open_packet = alloc_ctrl_packet( 1457 + sizeof(struct ipw_setup_open_packet), 1458 + ADDR_SETUP_PROT, 1459 + TL_PROTOCOLID_SETUP, 1460 + TL_SETUP_SIGNO_OPEN_MSG); 1461 + if (!open_packet) 1462 + goto exit_nomem; 1463 + open_packet->header.length = sizeof(struct tl_setup_open_msg); 1464 + open_packet->body.port_no = port; 1465 + send_packet(hw, PRIO_SETUP, &open_packet->header); 1466 + } 1467 + for (channel_idx = 0; 1468 + channel_idx < NL_NUM_OF_ADDRESSES; channel_idx++) { 1469 + int ret; 1470 + 1471 + ret = set_DTR(hw, PRIO_SETUP, channel_idx, 1472 + (hw->control_lines[channel_idx] & 1473 + IPW_CONTROL_LINE_DTR) != 0); 1474 + if (ret) { 1475 + printk(KERN_ERR IPWIRELESS_PCCARD_NAME 1476 + ": error setting DTR (%d)\n", ret); 1477 + return; 1478 + } 1479 + 1480 + set_RTS(hw, PRIO_SETUP, channel_idx, 1481 + (hw->control_lines [channel_idx] & 1482 + IPW_CONTROL_LINE_RTS) != 0); 1483 + if (ret) { 1484 + printk(KERN_ERR IPWIRELESS_PCCARD_NAME 1485 + ": error setting RTS (%d)\n", ret); 1486 + return; 1487 + } 1488 + } 1489 + /* 1490 + * For NDIS we assume that we are using sync PPP frames, for COM async. 1491 + * This driver uses NDIS mode too. We don't bother with translation 1492 + * from async -> sync PPP. 1493 + */ 1494 + info_packet = alloc_ctrl_packet(sizeof(struct ipw_setup_info_packet), 1495 + ADDR_SETUP_PROT, 1496 + TL_PROTOCOLID_SETUP, 1497 + TL_SETUP_SIGNO_INFO_MSG); 1498 + if (!info_packet) 1499 + goto exit_nomem; 1500 + info_packet->header.length = sizeof(struct tl_setup_info_msg); 1501 + info_packet->body.driver_type = NDISWAN_DRIVER; 1502 + info_packet->body.major_version = NDISWAN_DRIVER_MAJOR_VERSION; 1503 + info_packet->body.minor_version = NDISWAN_DRIVER_MINOR_VERSION; 1504 + send_packet(hw, PRIO_SETUP, &info_packet->header); 1505 + 1506 + /* Initialization is now complete, so we clear the 'to_setup' flag */ 1507 + hw->to_setup = 0; 1508 + 1509 + return; 1510 + 1511 + exit_nomem: 1512 + printk(KERN_ERR IPWIRELESS_PCCARD_NAME 1513 + ": not enough memory to alloc control packet\n"); 1514 + hw->to_setup = -1; 1515 + } 1516 + 1517 + static void handle_setup_get_version_rsp(struct ipw_hardware *hw, 1518 + unsigned char vers_no) 1519 + { 1520 + del_timer(&hw->setup_timer); 1521 + hw->initializing = 0; 1522 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": card is ready.\n"); 1523 + 1524 + if (vers_no == TL_SETUP_VERSION) 1525 + __handle_setup_get_version_rsp(hw); 1526 + else 1527 + printk(KERN_ERR 1528 + IPWIRELESS_PCCARD_NAME 1529 + ": invalid hardware version no %u\n", 1530 + (unsigned int) vers_no); 1531 + } 1532 + 1533 + static void ipw_send_setup_packet(struct ipw_hardware *hw) 1534 + { 1535 + struct ipw_setup_get_version_query_packet *ver_packet; 1536 + 1537 + ver_packet = alloc_ctrl_packet( 1538 + sizeof(struct ipw_setup_get_version_query_packet), 1539 + ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP, 1540 + TL_SETUP_SIGNO_GET_VERSION_QRY); 1541 + ver_packet->header.length = sizeof(struct tl_setup_get_version_qry); 1542 + 1543 + /* 1544 + * Response is handled in handle_received_SETUP_packet 1545 + */ 1546 + send_packet(hw, PRIO_SETUP, &ver_packet->header); 1547 + } 1548 + 1549 + static void handle_received_SETUP_packet(struct ipw_hardware *hw, 1550 + unsigned int address, 1551 + unsigned char *data, int len, 1552 + int is_last) 1553 + { 1554 + union ipw_setup_rx_msg *rx_msg = (union ipw_setup_rx_msg *) data; 1555 + 1556 + if (address != ADDR_SETUP_PROT) { 1557 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 1558 + ": setup packet has bad address %d\n", address); 1559 + return; 1560 + } 1561 + 1562 + switch (rx_msg->sig_no) { 1563 + case TL_SETUP_SIGNO_GET_VERSION_RSP: 1564 + if (hw->to_setup) 1565 + handle_setup_get_version_rsp(hw, 1566 + rx_msg->version_rsp_msg.version); 1567 + break; 1568 + 1569 + case TL_SETUP_SIGNO_OPEN_MSG: 1570 + if (ipwireless_debug) { 1571 + unsigned int channel_idx = rx_msg->open_msg.port_no - 1; 1572 + 1573 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 1574 + ": OPEN_MSG [channel %u] reply received\n", 1575 + channel_idx); 1576 + } 1577 + break; 1578 + 1579 + case TL_SETUP_SIGNO_INFO_MSG_ACK: 1580 + if (ipwireless_debug) 1581 + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME 1582 + ": card successfully configured as NDISWAN\n"); 1583 + break; 1584 + 1585 + case TL_SETUP_SIGNO_REBOOT_MSG: 1586 + if (hw->to_setup) 1587 + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME 1588 + ": Setup not completed - ignoring reboot msg\n"); 1589 + else { 1590 + struct ipw_setup_reboot_msg_ack *packet; 1591 + 1592 + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME 1593 + ": Acknowledging REBOOT message\n"); 1594 + packet = alloc_ctrl_packet( 1595 + sizeof(struct ipw_setup_reboot_msg_ack), 1596 + ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP, 1597 + TL_SETUP_SIGNO_REBOOT_MSG_ACK); 1598 + packet->header.length = 1599 + sizeof(struct TlSetupRebootMsgAck); 1600 + send_packet(hw, PRIO_SETUP, &packet->header); 1601 + if (hw->reboot_callback) 1602 + hw->reboot_callback(hw->reboot_callback_data); 1603 + } 1604 + break; 1605 + 1606 + default: 1607 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 1608 + ": unknown setup message %u received\n", 1609 + (unsigned int) rx_msg->sig_no); 1610 + } 1611 + } 1612 + 1613 + static void do_close_hardware(struct ipw_hardware *hw) 1614 + { 1615 + unsigned int irqn; 1616 + 1617 + if (hw->hw_version == HW_VERSION_1) { 1618 + /* Disable TX and RX interrupts. */ 1619 + outw(0, hw->base_port + IOIER); 1620 + 1621 + /* Acknowledge any outstanding interrupt requests */ 1622 + irqn = inw(hw->base_port + IOIR); 1623 + if (irqn & IR_TXINTR) 1624 + outw(IR_TXINTR, hw->base_port + IOIR); 1625 + if (irqn & IR_RXINTR) 1626 + outw(IR_RXINTR, hw->base_port + IOIR); 1627 + 1628 + synchronize_irq(hw->irq); 1629 + } 1630 + } 1631 + 1632 + struct ipw_hardware *ipwireless_hardware_create(void) 1633 + { 1634 + int i; 1635 + struct ipw_hardware *hw = 1636 + kzalloc(sizeof(struct ipw_hardware), GFP_KERNEL); 1637 + 1638 + if (!hw) 1639 + return NULL; 1640 + 1641 + hw->irq = -1; 1642 + hw->initializing = 1; 1643 + hw->tx_ready = 1; 1644 + hw->rx_bytes_queued = 0; 1645 + hw->rx_pool_size = 0; 1646 + hw->last_memtx_serial = (unsigned short) 0xffff; 1647 + for (i = 0; i < NL_NUM_OF_PRIORITIES; i++) 1648 + INIT_LIST_HEAD(&hw->tx_queue[i]); 1649 + 1650 + INIT_LIST_HEAD(&hw->rx_queue); 1651 + INIT_LIST_HEAD(&hw->rx_pool); 1652 + spin_lock_init(&hw->spinlock); 1653 + tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw); 1654 + INIT_WORK(&hw->work_rx, ipw_receive_data_work); 1655 + setup_timer(&hw->setup_timer, ipwireless_setup_timer, 1656 + (unsigned long) hw); 1657 + 1658 + return hw; 1659 + } 1660 + 1661 + void ipwireless_init_hardware_v1(struct ipw_hardware *hw, 1662 + unsigned int base_port, 1663 + void __iomem *attr_memory, 1664 + void __iomem *common_memory, 1665 + int is_v2_card, 1666 + void (*reboot_callback) (void *data), 1667 + void *reboot_callback_data) 1668 + { 1669 + if (hw->removed) { 1670 + hw->removed = 0; 1671 + enable_irq(hw->irq); 1672 + } 1673 + hw->base_port = base_port; 1674 + hw->hw_version = is_v2_card ? HW_VERSION_2 : HW_VERSION_1; 1675 + hw->ll_mtu = hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2; 1676 + hw->memregs_CCR = (struct MEMCCR __iomem *) 1677 + ((unsigned short __iomem *) attr_memory + 0x200); 1678 + hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory; 1679 + hw->memreg_tx = &hw->memory_info_regs->memreg_tx_new; 1680 + hw->reboot_callback = reboot_callback; 1681 + hw->reboot_callback_data = reboot_callback_data; 1682 + } 1683 + 1684 + void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw) 1685 + { 1686 + hw->initializing = 1; 1687 + hw->init_loops = 0; 1688 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 1689 + ": waiting for card to start up...\n"); 1690 + ipwireless_setup_timer((unsigned long) hw); 1691 + } 1692 + 1693 + static void ipwireless_setup_timer(unsigned long data) 1694 + { 1695 + struct ipw_hardware *hw = (struct ipw_hardware *) data; 1696 + 1697 + hw->init_loops++; 1698 + 1699 + if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY && 1700 + hw->hw_version == HW_VERSION_2 && 1701 + hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) { 1702 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 1703 + ": failed to startup using TX2, trying TX\n"); 1704 + 1705 + hw->memreg_tx = &hw->memory_info_regs->memreg_tx_old; 1706 + hw->init_loops = 0; 1707 + } 1708 + /* Give up after a certain number of retries */ 1709 + if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY) { 1710 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 1711 + ": card failed to start up!\n"); 1712 + hw->initializing = 0; 1713 + } else { 1714 + /* Do not attempt to write to the board if it is not present. */ 1715 + if (is_card_present(hw)) { 1716 + unsigned long flags; 1717 + 1718 + spin_lock_irqsave(&hw->spinlock, flags); 1719 + hw->to_setup = 1; 1720 + hw->tx_ready = 1; 1721 + spin_unlock_irqrestore(&hw->spinlock, flags); 1722 + tasklet_schedule(&hw->tasklet); 1723 + } 1724 + 1725 + mod_timer(&hw->setup_timer, 1726 + jiffies + msecs_to_jiffies(TL_SETUP_VERSION_QRY_TMO)); 1727 + } 1728 + } 1729 + 1730 + /* 1731 + * Stop any interrupts from executing so that, once this function returns, 1732 + * other layers of the driver can be sure they won't get any more callbacks. 1733 + * Thus must be called on a proper process context. 1734 + */ 1735 + void ipwireless_stop_interrupts(struct ipw_hardware *hw) 1736 + { 1737 + if (!hw->shutting_down) { 1738 + /* Tell everyone we are going down. */ 1739 + hw->shutting_down = 1; 1740 + del_timer(&hw->setup_timer); 1741 + 1742 + /* Prevent the hardware from sending any more interrupts */ 1743 + do_close_hardware(hw); 1744 + } 1745 + } 1746 + 1747 + void ipwireless_hardware_free(struct ipw_hardware *hw) 1748 + { 1749 + int i; 1750 + struct ipw_rx_packet *rp, *rq; 1751 + struct ipw_tx_packet *tp, *tq; 1752 + 1753 + ipwireless_stop_interrupts(hw); 1754 + 1755 + flush_scheduled_work(); 1756 + 1757 + for (i = 0; i < NL_NUM_OF_ADDRESSES; i++) 1758 + if (hw->packet_assembler[i] != NULL) 1759 + kfree(hw->packet_assembler[i]); 1760 + 1761 + for (i = 0; i < NL_NUM_OF_PRIORITIES; i++) 1762 + list_for_each_entry_safe(tp, tq, &hw->tx_queue[i], queue) { 1763 + list_del(&tp->queue); 1764 + kfree(tp); 1765 + } 1766 + 1767 + list_for_each_entry_safe(rp, rq, &hw->rx_queue, queue) { 1768 + list_del(&rp->queue); 1769 + kfree(rp); 1770 + } 1771 + 1772 + list_for_each_entry_safe(rp, rq, &hw->rx_pool, queue) { 1773 + list_del(&rp->queue); 1774 + kfree(rp); 1775 + } 1776 + kfree(hw); 1777 + } 1778 + 1779 + /* 1780 + * Associate the specified network with this hardware, so it will receive events 1781 + * from it. 1782 + */ 1783 + void ipwireless_associate_network(struct ipw_hardware *hw, 1784 + struct ipw_network *network) 1785 + { 1786 + hw->network = network; 1787 + }
+64
drivers/char/pcmcia/ipwireless/hardware.h
··· 1 + /* 2 + * IPWireless 3G PCMCIA Network Driver 3 + * 4 + * Original code 5 + * by Stephen Blackheath <stephen@blacksapphire.com>, 6 + * Ben Martel <benm@symmetric.co.nz> 7 + * 8 + * Copyrighted as follows: 9 + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) 10 + * 11 + * Various driver changes and rewrites, port to new kernels 12 + * Copyright (C) 2006-2007 Jiri Kosina 13 + * 14 + * Misc code cleanups and updates 15 + * Copyright (C) 2007 David Sterba 16 + */ 17 + 18 + #ifndef _IPWIRELESS_CS_HARDWARE_H_ 19 + #define _IPWIRELESS_CS_HARDWARE_H_ 20 + 21 + #include <linux/types.h> 22 + #include <linux/sched.h> 23 + #include <linux/interrupt.h> 24 + 25 + #define IPW_CONTROL_LINE_CTS 0x0001 26 + #define IPW_CONTROL_LINE_DCD 0x0002 27 + #define IPW_CONTROL_LINE_DSR 0x0004 28 + #define IPW_CONTROL_LINE_RI 0x0008 29 + #define IPW_CONTROL_LINE_DTR 0x0010 30 + #define IPW_CONTROL_LINE_RTS 0x0020 31 + 32 + struct ipw_hardware; 33 + struct ipw_network; 34 + 35 + struct ipw_hardware *ipwireless_hardware_create(void); 36 + void ipwireless_hardware_free(struct ipw_hardware *hw); 37 + irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs); 38 + int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, 39 + int state); 40 + int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, 41 + int state); 42 + int ipwireless_send_packet(struct ipw_hardware *hw, 43 + unsigned int channel_idx, 44 + unsigned char *data, 45 + unsigned int length, 46 + void (*packet_sent_callback) (void *cb, 47 + unsigned int length), 48 + void *sent_cb_data); 49 + void ipwireless_associate_network(struct ipw_hardware *hw, 50 + struct ipw_network *net); 51 + void ipwireless_stop_interrupts(struct ipw_hardware *hw); 52 + void ipwireless_init_hardware_v1(struct ipw_hardware *hw, 53 + unsigned int base_port, 54 + void __iomem *attr_memory, 55 + void __iomem *common_memory, 56 + int is_v2_card, 57 + void (*reboot_cb) (void *data), 58 + void *reboot_cb_data); 59 + void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw); 60 + void ipwireless_sleep(unsigned int tenths); 61 + int ipwireless_dump_hardware_state(char *p, size_t limit, 62 + struct ipw_hardware *hw); 63 + 64 + #endif
+501
drivers/char/pcmcia/ipwireless/main.c
··· 1 + /* 2 + * IPWireless 3G PCMCIA Network Driver 3 + * 4 + * Original code 5 + * by Stephen Blackheath <stephen@blacksapphire.com>, 6 + * Ben Martel <benm@symmetric.co.nz> 7 + * 8 + * Copyrighted as follows: 9 + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) 10 + * 11 + * Various driver changes and rewrites, port to new kernels 12 + * Copyright (C) 2006-2007 Jiri Kosina 13 + * 14 + * Misc code cleanups and updates 15 + * Copyright (C) 2007 David Sterba 16 + */ 17 + 18 + #include "hardware.h" 19 + #include "network.h" 20 + #include "main.h" 21 + #include "tty.h" 22 + 23 + #include <linux/delay.h> 24 + #include <linux/init.h> 25 + #include <linux/io.h> 26 + #include <linux/kernel.h> 27 + #include <linux/module.h> 28 + #include <linux/sched.h> 29 + #include <linux/slab.h> 30 + 31 + #include <pcmcia/version.h> 32 + #include <pcmcia/cisreg.h> 33 + #include <pcmcia/device_id.h> 34 + #include <pcmcia/ss.h> 35 + #include <pcmcia/ds.h> 36 + #include <pcmcia/cs.h> 37 + 38 + static struct pcmcia_device_id ipw_ids[] = { 39 + PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100), 40 + PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0200), 41 + PCMCIA_DEVICE_NULL 42 + }; 43 + MODULE_DEVICE_TABLE(pcmcia, ipw_ids); 44 + 45 + static void ipwireless_detach(struct pcmcia_device *link); 46 + 47 + /* 48 + * Module params 49 + */ 50 + /* Debug mode: more verbose, print sent/recv bytes */ 51 + int ipwireless_debug; 52 + int ipwireless_loopback; 53 + int ipwireless_out_queue = 1; 54 + 55 + module_param_named(debug, ipwireless_debug, int, 0); 56 + module_param_named(loopback, ipwireless_loopback, int, 0); 57 + module_param_named(out_queue, ipwireless_out_queue, int, 0); 58 + MODULE_PARM_DESC(debug, "switch on debug messages [0]"); 59 + MODULE_PARM_DESC(loopback, 60 + "debug: enable ras_raw channel [0]"); 61 + MODULE_PARM_DESC(out_queue, "debug: set size of outgoing queue [1]"); 62 + 63 + /* Executes in process context. */ 64 + static void signalled_reboot_work(struct work_struct *work_reboot) 65 + { 66 + struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev, 67 + work_reboot); 68 + struct pcmcia_device *link = ipw->link; 69 + int ret = pccard_reset_card(link->socket); 70 + 71 + if (ret != CS_SUCCESS) 72 + cs_error(link, ResetCard, ret); 73 + } 74 + 75 + static void signalled_reboot_callback(void *callback_data) 76 + { 77 + struct ipw_dev *ipw = (struct ipw_dev *) callback_data; 78 + 79 + /* Delegate to process context. */ 80 + schedule_work(&ipw->work_reboot); 81 + } 82 + 83 + static int config_ipwireless(struct ipw_dev *ipw) 84 + { 85 + struct pcmcia_device *link = ipw->link; 86 + int ret; 87 + config_info_t conf; 88 + tuple_t tuple; 89 + unsigned short buf[64]; 90 + cisparse_t parse; 91 + unsigned short cor_value; 92 + win_req_t request_attr_memory; 93 + win_req_t request_common_memory; 94 + memreq_t memreq_attr_memory; 95 + memreq_t memreq_common_memory; 96 + 97 + ipw->is_v2_card = 0; 98 + 99 + tuple.Attributes = 0; 100 + tuple.TupleData = (cisdata_t *) buf; 101 + tuple.TupleDataMax = sizeof(buf); 102 + tuple.TupleOffset = 0; 103 + 104 + tuple.DesiredTuple = RETURN_FIRST_TUPLE; 105 + 106 + ret = pcmcia_get_first_tuple(link, &tuple); 107 + 108 + while (ret == 0) { 109 + ret = pcmcia_get_tuple_data(link, &tuple); 110 + 111 + if (ret != CS_SUCCESS) { 112 + cs_error(link, GetTupleData, ret); 113 + goto exit0; 114 + } 115 + ret = pcmcia_get_next_tuple(link, &tuple); 116 + } 117 + 118 + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 119 + 120 + ret = pcmcia_get_first_tuple(link, &tuple); 121 + 122 + if (ret != CS_SUCCESS) { 123 + cs_error(link, GetFirstTuple, ret); 124 + goto exit0; 125 + } 126 + 127 + ret = pcmcia_get_tuple_data(link, &tuple); 128 + 129 + if (ret != CS_SUCCESS) { 130 + cs_error(link, GetTupleData, ret); 131 + goto exit0; 132 + } 133 + 134 + ret = pcmcia_parse_tuple(link, &tuple, &parse); 135 + 136 + if (ret != CS_SUCCESS) { 137 + cs_error(link, ParseTuple, ret); 138 + goto exit0; 139 + } 140 + 141 + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; 142 + link->io.BasePort1 = parse.cftable_entry.io.win[0].base; 143 + link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; 144 + link->io.IOAddrLines = 16; 145 + 146 + link->irq.IRQInfo1 = parse.cftable_entry.irq.IRQInfo1; 147 + 148 + /* 0x40 causes it to generate level mode interrupts. */ 149 + /* 0x04 enables IREQ pin. */ 150 + cor_value = parse.cftable_entry.index | 0x44; 151 + link->conf.ConfigIndex = cor_value; 152 + 153 + /* IRQ and I/O settings */ 154 + tuple.DesiredTuple = CISTPL_CONFIG; 155 + 156 + ret = pcmcia_get_first_tuple(link, &tuple); 157 + 158 + if (ret != CS_SUCCESS) { 159 + cs_error(link, GetFirstTuple, ret); 160 + goto exit0; 161 + } 162 + 163 + ret = pcmcia_get_tuple_data(link, &tuple); 164 + 165 + if (ret != CS_SUCCESS) { 166 + cs_error(link, GetTupleData, ret); 167 + goto exit0; 168 + } 169 + 170 + ret = pcmcia_parse_tuple(link, &tuple, &parse); 171 + 172 + if (ret != CS_SUCCESS) { 173 + cs_error(link, GetTupleData, ret); 174 + goto exit0; 175 + } 176 + link->conf.Attributes = CONF_ENABLE_IRQ; 177 + link->conf.ConfigBase = parse.config.base; 178 + link->conf.Present = parse.config.rmask[0]; 179 + link->conf.IntType = INT_MEMORY_AND_IO; 180 + 181 + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; 182 + link->irq.Handler = ipwireless_interrupt; 183 + link->irq.Instance = ipw->hardware; 184 + 185 + ret = pcmcia_request_io(link, &link->io); 186 + 187 + if (ret != CS_SUCCESS) { 188 + cs_error(link, RequestIO, ret); 189 + goto exit0; 190 + } 191 + 192 + /* memory settings */ 193 + 194 + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; 195 + 196 + ret = pcmcia_get_first_tuple(link, &tuple); 197 + 198 + if (ret != CS_SUCCESS) { 199 + cs_error(link, GetFirstTuple, ret); 200 + goto exit1; 201 + } 202 + 203 + ret = pcmcia_get_tuple_data(link, &tuple); 204 + 205 + if (ret != CS_SUCCESS) { 206 + cs_error(link, GetTupleData, ret); 207 + goto exit1; 208 + } 209 + 210 + ret = pcmcia_parse_tuple(link, &tuple, &parse); 211 + 212 + if (ret != CS_SUCCESS) { 213 + cs_error(link, ParseTuple, ret); 214 + goto exit1; 215 + } 216 + 217 + if (parse.cftable_entry.mem.nwin > 0) { 218 + request_common_memory.Attributes = 219 + WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; 220 + request_common_memory.Base = 221 + parse.cftable_entry.mem.win[0].host_addr; 222 + request_common_memory.Size = parse.cftable_entry.mem.win[0].len; 223 + if (request_common_memory.Size < 0x1000) 224 + request_common_memory.Size = 0x1000; 225 + request_common_memory.AccessSpeed = 0; 226 + 227 + ret = pcmcia_request_window(&link, &request_common_memory, 228 + &ipw->handle_common_memory); 229 + 230 + if (ret != CS_SUCCESS) { 231 + cs_error(link, RequestWindow, ret); 232 + goto exit1; 233 + } 234 + 235 + memreq_common_memory.CardOffset = 236 + parse.cftable_entry.mem.win[0].card_addr; 237 + memreq_common_memory.Page = 0; 238 + 239 + ret = pcmcia_map_mem_page(ipw->handle_common_memory, 240 + &memreq_common_memory); 241 + 242 + if (ret != CS_SUCCESS) { 243 + cs_error(link, MapMemPage, ret); 244 + goto exit1; 245 + } 246 + 247 + ipw->is_v2_card = 248 + parse.cftable_entry.mem.win[0].len == 0x100; 249 + 250 + ipw->common_memory = ioremap(request_common_memory.Base, 251 + request_common_memory.Size); 252 + 253 + request_attr_memory.Attributes = 254 + WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; 255 + request_attr_memory.Base = 0; 256 + request_attr_memory.Size = 0; /* this used to be 0x1000 */ 257 + request_attr_memory.AccessSpeed = 0; 258 + 259 + ret = pcmcia_request_window(&link, &request_attr_memory, 260 + &ipw->handle_attr_memory); 261 + 262 + if (ret != CS_SUCCESS) { 263 + cs_error(link, RequestWindow, ret); 264 + goto exit2; 265 + } 266 + 267 + memreq_attr_memory.CardOffset = 0; 268 + memreq_attr_memory.Page = 0; 269 + 270 + ret = pcmcia_map_mem_page(ipw->handle_attr_memory, 271 + &memreq_attr_memory); 272 + 273 + if (ret != CS_SUCCESS) { 274 + cs_error(link, MapMemPage, ret); 275 + goto exit2; 276 + } 277 + 278 + ipw->attr_memory = ioremap(request_attr_memory.Base, 279 + request_attr_memory.Size); 280 + } 281 + 282 + INIT_WORK(&ipw->work_reboot, signalled_reboot_work); 283 + 284 + ipwireless_init_hardware_v1(ipw->hardware, link->io.BasePort1, 285 + ipw->attr_memory, ipw->common_memory, 286 + ipw->is_v2_card, signalled_reboot_callback, 287 + ipw); 288 + 289 + ret = pcmcia_request_irq(link, &link->irq); 290 + 291 + if (ret != CS_SUCCESS) { 292 + cs_error(link, RequestIRQ, ret); 293 + goto exit3; 294 + } 295 + 296 + /* Look up current Vcc */ 297 + 298 + ret = pcmcia_get_configuration_info(link, &conf); 299 + 300 + if (ret != CS_SUCCESS) { 301 + cs_error(link, GetConfigurationInfo, ret); 302 + goto exit4; 303 + } 304 + 305 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n", 306 + ipw->is_v2_card ? "V2/V3" : "V1"); 307 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 308 + ": I/O ports 0x%04x-0x%04x, irq %d\n", 309 + (unsigned int) link->io.BasePort1, 310 + (unsigned int) (link->io.BasePort1 + 311 + link->io.NumPorts1 - 1), 312 + (unsigned int) link->irq.AssignedIRQ); 313 + if (ipw->attr_memory && ipw->common_memory) 314 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 315 + ": attr memory 0x%08lx-0x%08lx, " 316 + "common memory 0x%08lx-0x%08lx\n", 317 + request_attr_memory.Base, 318 + request_attr_memory.Base 319 + + request_attr_memory.Size - 1, 320 + request_common_memory.Base, 321 + request_common_memory.Base 322 + + request_common_memory.Size - 1); 323 + 324 + ipw->network = ipwireless_network_create(ipw->hardware); 325 + if (!ipw->network) 326 + goto exit3; 327 + 328 + ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network, 329 + ipw->nodes); 330 + if (!ipw->tty) 331 + goto exit3; 332 + 333 + ipwireless_init_hardware_v2_v3(ipw->hardware); 334 + 335 + /* 336 + * Do the RequestConfiguration last, because it enables interrupts. 337 + * Then we don't get any interrupts before we're ready for them. 338 + */ 339 + ret = pcmcia_request_configuration(link, &link->conf); 340 + 341 + if (ret != CS_SUCCESS) { 342 + cs_error(link, RequestConfiguration, ret); 343 + goto exit4; 344 + } 345 + 346 + link->dev_node = &ipw->nodes[0]; 347 + 348 + return 0; 349 + 350 + exit4: 351 + pcmcia_disable_device(link); 352 + exit3: 353 + if (ipw->attr_memory) { 354 + iounmap(ipw->attr_memory); 355 + pcmcia_release_window(ipw->handle_attr_memory); 356 + pcmcia_disable_device(link); 357 + } 358 + exit2: 359 + if (ipw->common_memory) { 360 + iounmap(ipw->common_memory); 361 + pcmcia_release_window(ipw->handle_common_memory); 362 + } 363 + exit1: 364 + pcmcia_disable_device(link); 365 + exit0: 366 + return -1; 367 + } 368 + 369 + static void release_ipwireless(struct ipw_dev *ipw) 370 + { 371 + struct pcmcia_device *link = ipw->link; 372 + 373 + pcmcia_disable_device(link); 374 + 375 + if (ipw->common_memory) 376 + iounmap(ipw->common_memory); 377 + if (ipw->attr_memory) 378 + iounmap(ipw->attr_memory); 379 + if (ipw->common_memory) 380 + pcmcia_release_window(ipw->handle_common_memory); 381 + if (ipw->attr_memory) 382 + pcmcia_release_window(ipw->handle_attr_memory); 383 + pcmcia_disable_device(link); 384 + } 385 + 386 + /* 387 + * ipwireless_attach() creates an "instance" of the driver, allocating 388 + * local data structures for one device (one interface). The device 389 + * is registered with Card Services. 390 + * 391 + * The pcmcia_device structure is initialized, but we don't actually 392 + * configure the card at this point -- we wait until we receive a 393 + * card insertion event. 394 + */ 395 + static int ipwireless_attach(struct pcmcia_device *link) 396 + { 397 + struct ipw_dev *ipw; 398 + int ret; 399 + 400 + ipw = kzalloc(sizeof(struct ipw_dev), GFP_KERNEL); 401 + if (!ipw) 402 + return -ENOMEM; 403 + 404 + ipw->link = link; 405 + link->priv = ipw; 406 + link->irq.Instance = ipw; 407 + 408 + /* Link this device into our device list. */ 409 + link->dev_node = &ipw->nodes[0]; 410 + 411 + ipw->hardware = ipwireless_hardware_create(); 412 + if (!ipw->hardware) { 413 + kfree(ipw); 414 + return -ENOMEM; 415 + } 416 + /* RegisterClient will call config_ipwireless */ 417 + 418 + ret = config_ipwireless(ipw); 419 + 420 + if (ret != 0) { 421 + cs_error(link, RegisterClient, ret); 422 + ipwireless_detach(link); 423 + return ret; 424 + } 425 + 426 + return 0; 427 + } 428 + 429 + /* 430 + * This deletes a driver "instance". The device is de-registered with 431 + * Card Services. If it has been released, all local data structures 432 + * are freed. Otherwise, the structures will be freed when the device 433 + * is released. 434 + */ 435 + static void ipwireless_detach(struct pcmcia_device *link) 436 + { 437 + struct ipw_dev *ipw = link->priv; 438 + 439 + release_ipwireless(ipw); 440 + 441 + /* Break the link with Card Services */ 442 + if (link) 443 + pcmcia_disable_device(link); 444 + 445 + if (ipw->tty != NULL) 446 + ipwireless_tty_free(ipw->tty); 447 + if (ipw->network != NULL) 448 + ipwireless_network_free(ipw->network); 449 + if (ipw->hardware != NULL) 450 + ipwireless_hardware_free(ipw->hardware); 451 + kfree(ipw); 452 + } 453 + 454 + static struct pcmcia_driver me = { 455 + .owner = THIS_MODULE, 456 + .probe = ipwireless_attach, 457 + .remove = ipwireless_detach, 458 + .drv = { .name = IPWIRELESS_PCCARD_NAME }, 459 + .id_table = ipw_ids 460 + }; 461 + 462 + /* 463 + * Module insertion : initialisation of the module. 464 + * Register the card with cardmgr... 465 + */ 466 + static int __init init_ipwireless(void) 467 + { 468 + int ret; 469 + 470 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME " " 471 + IPWIRELESS_PCMCIA_VERSION " by " IPWIRELESS_PCMCIA_AUTHOR "\n"); 472 + 473 + ret = ipwireless_tty_init(); 474 + if (ret != 0) 475 + return ret; 476 + 477 + ret = pcmcia_register_driver(&me); 478 + if (ret != 0) 479 + ipwireless_tty_release(); 480 + 481 + return ret; 482 + } 483 + 484 + /* 485 + * Module removal 486 + */ 487 + static void __exit exit_ipwireless(void) 488 + { 489 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME " " 490 + IPWIRELESS_PCMCIA_VERSION " removed\n"); 491 + 492 + pcmcia_unregister_driver(&me); 493 + ipwireless_tty_release(); 494 + } 495 + 496 + module_init(init_ipwireless); 497 + module_exit(exit_ipwireless); 498 + 499 + MODULE_AUTHOR(IPWIRELESS_PCMCIA_AUTHOR); 500 + MODULE_DESCRIPTION(IPWIRELESS_PCCARD_NAME " " IPWIRELESS_PCMCIA_VERSION); 501 + MODULE_LICENSE("GPL");
+70
drivers/char/pcmcia/ipwireless/main.h
··· 1 + /* 2 + * IPWireless 3G PCMCIA Network Driver 3 + * 4 + * Original code 5 + * by Stephen Blackheath <stephen@blacksapphire.com>, 6 + * Ben Martel <benm@symmetric.co.nz> 7 + * 8 + * Copyrighted as follows: 9 + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) 10 + * 11 + * Various driver changes and rewrites, port to new kernels 12 + * Copyright (C) 2006-2007 Jiri Kosina 13 + * 14 + * Misc code cleanups and updates 15 + * Copyright (C) 2007 David Sterba 16 + */ 17 + 18 + #ifndef _IPWIRELESS_CS_H_ 19 + #define _IPWIRELESS_CS_H_ 20 + 21 + #include <linux/sched.h> 22 + #include <linux/types.h> 23 + 24 + #include <pcmcia/cs_types.h> 25 + #include <pcmcia/cs.h> 26 + #include <pcmcia/cistpl.h> 27 + #include <pcmcia/ds.h> 28 + 29 + #include "hardware.h" 30 + 31 + #define IPWIRELESS_PCCARD_NAME "ipwireless" 32 + #define IPWIRELESS_PCMCIA_VERSION "1.1" 33 + #define IPWIRELESS_PCMCIA_AUTHOR \ 34 + "Stephen Blackheath, Ben Martel, Jiri Kosina and David Sterba" 35 + 36 + #define IPWIRELESS_TX_QUEUE_SIZE 262144 37 + #define IPWIRELESS_RX_QUEUE_SIZE 262144 38 + 39 + #define IPWIRELESS_STATE_DEBUG 40 + 41 + struct ipw_hardware; 42 + struct ipw_network; 43 + struct ipw_tty; 44 + 45 + struct ipw_dev { 46 + struct pcmcia_device *link; 47 + int is_v2_card; 48 + window_handle_t handle_attr_memory; 49 + void __iomem *attr_memory; 50 + window_handle_t handle_common_memory; 51 + void __iomem *common_memory; 52 + dev_node_t nodes[2]; 53 + /* Reference to attribute memory, containing CIS data */ 54 + void *attribute_memory; 55 + 56 + /* Hardware context */ 57 + struct ipw_hardware *hardware; 58 + /* Network layer context */ 59 + struct ipw_network *network; 60 + /* TTY device context */ 61 + struct ipw_tty *tty; 62 + struct work_struct work_reboot; 63 + }; 64 + 65 + /* Module parametres */ 66 + extern int ipwireless_debug; 67 + extern int ipwireless_loopback; 68 + extern int ipwireless_out_queue; 69 + 70 + #endif
+512
drivers/char/pcmcia/ipwireless/network.c
··· 1 + /* 2 + * IPWireless 3G PCMCIA Network Driver 3 + * 4 + * Original code 5 + * by Stephen Blackheath <stephen@blacksapphire.com>, 6 + * Ben Martel <benm@symmetric.co.nz> 7 + * 8 + * Copyrighted as follows: 9 + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) 10 + * 11 + * Various driver changes and rewrites, port to new kernels 12 + * Copyright (C) 2006-2007 Jiri Kosina 13 + * 14 + * Misc code cleanups and updates 15 + * Copyright (C) 2007 David Sterba 16 + */ 17 + 18 + #include <linux/interrupt.h> 19 + #include <linux/kernel.h> 20 + #include <linux/mutex.h> 21 + #include <linux/netdevice.h> 22 + #include <linux/ppp_channel.h> 23 + #include <linux/ppp_defs.h> 24 + #include <linux/if_ppp.h> 25 + #include <linux/skbuff.h> 26 + 27 + #include "network.h" 28 + #include "hardware.h" 29 + #include "main.h" 30 + #include "tty.h" 31 + 32 + #define MAX_OUTGOING_PACKETS_QUEUED ipwireless_out_queue 33 + #define MAX_ASSOCIATED_TTYS 2 34 + 35 + #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) 36 + 37 + struct ipw_network { 38 + /* Hardware context, used for calls to hardware layer. */ 39 + struct ipw_hardware *hardware; 40 + /* Context for kernel 'generic_ppp' functionality */ 41 + struct ppp_channel *ppp_channel; 42 + /* tty context connected with IPW console */ 43 + struct ipw_tty *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS]; 44 + /* True if ppp needs waking up once we're ready to xmit */ 45 + int ppp_blocked; 46 + /* Number of packets queued up in hardware module. */ 47 + int outgoing_packets_queued; 48 + /* Spinlock to avoid interrupts during shutdown */ 49 + spinlock_t spinlock; 50 + struct mutex close_lock; 51 + 52 + /* PPP ioctl data, not actually used anywere */ 53 + unsigned int flags; 54 + unsigned int rbits; 55 + u32 xaccm[8]; 56 + u32 raccm; 57 + int mru; 58 + 59 + int shutting_down; 60 + unsigned int ras_control_lines; 61 + 62 + struct work_struct work_go_online; 63 + struct work_struct work_go_offline; 64 + }; 65 + 66 + 67 + #ifdef IPWIRELESS_STATE_DEBUG 68 + int ipwireless_dump_network_state(char *p, size_t limit, 69 + struct ipw_network *network) 70 + { 71 + return snprintf(p, limit, 72 + "debug: ppp_blocked=%d\n" 73 + "debug: outgoing_packets_queued=%d\n" 74 + "debug: network.shutting_down=%d\n", 75 + network->ppp_blocked, 76 + network->outgoing_packets_queued, 77 + network->shutting_down); 78 + } 79 + #endif 80 + 81 + static void notify_packet_sent(void *callback_data, unsigned int packet_length) 82 + { 83 + struct ipw_network *network = callback_data; 84 + unsigned long flags; 85 + 86 + spin_lock_irqsave(&network->spinlock, flags); 87 + network->outgoing_packets_queued--; 88 + if (network->ppp_channel != NULL) { 89 + if (network->ppp_blocked) { 90 + network->ppp_blocked = 0; 91 + spin_unlock_irqrestore(&network->spinlock, flags); 92 + ppp_output_wakeup(network->ppp_channel); 93 + if (ipwireless_debug) 94 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 95 + ": ppp unblocked\n"); 96 + } else 97 + spin_unlock_irqrestore(&network->spinlock, flags); 98 + } else 99 + spin_unlock_irqrestore(&network->spinlock, flags); 100 + } 101 + 102 + /* 103 + * Called by the ppp system when it has a packet to send to the hardware. 104 + */ 105 + static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, 106 + struct sk_buff *skb) 107 + { 108 + struct ipw_network *network = ppp_channel->private; 109 + unsigned long flags; 110 + 111 + spin_lock_irqsave(&network->spinlock, flags); 112 + if (network->outgoing_packets_queued < MAX_OUTGOING_PACKETS_QUEUED) { 113 + unsigned char *buf; 114 + static unsigned char header[] = { 115 + PPP_ALLSTATIONS, /* 0xff */ 116 + PPP_UI, /* 0x03 */ 117 + }; 118 + int ret; 119 + 120 + network->outgoing_packets_queued++; 121 + spin_unlock_irqrestore(&network->spinlock, flags); 122 + 123 + /* 124 + * If we have the requested amount of headroom in the skb we 125 + * were handed, then we can add the header efficiently. 126 + */ 127 + if (skb_headroom(skb) >= 2) { 128 + memcpy(skb_push(skb, 2), header, 2); 129 + ret = ipwireless_send_packet(network->hardware, 130 + IPW_CHANNEL_RAS, skb->data, 131 + skb->len, 132 + notify_packet_sent, 133 + network); 134 + if (ret == -1) { 135 + skb_pull(skb, 2); 136 + return 0; 137 + } 138 + } else { 139 + /* Otherwise (rarely) we do it inefficiently. */ 140 + buf = kmalloc(skb->len + 2, GFP_ATOMIC); 141 + if (!buf) 142 + return 0; 143 + memcpy(buf + 2, skb->data, skb->len); 144 + memcpy(buf, header, 2); 145 + ret = ipwireless_send_packet(network->hardware, 146 + IPW_CHANNEL_RAS, buf, 147 + skb->len + 2, 148 + notify_packet_sent, 149 + network); 150 + kfree(buf); 151 + if (ret == -1) 152 + return 0; 153 + } 154 + kfree_skb(skb); 155 + return 1; 156 + } else { 157 + /* 158 + * Otherwise reject the packet, and flag that the ppp system 159 + * needs to be unblocked once we are ready to send. 160 + */ 161 + network->ppp_blocked = 1; 162 + spin_unlock_irqrestore(&network->spinlock, flags); 163 + return 0; 164 + } 165 + } 166 + 167 + /* Handle an ioctl call that has come in via ppp. (copy of ppp_async_ioctl() */ 168 + static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel, 169 + unsigned int cmd, unsigned long arg) 170 + { 171 + struct ipw_network *network = ppp_channel->private; 172 + int err, val; 173 + u32 accm[8]; 174 + int __user *user_arg = (int __user *) arg; 175 + 176 + err = -EFAULT; 177 + switch (cmd) { 178 + case PPPIOCGFLAGS: 179 + val = network->flags | network->rbits; 180 + if (put_user(val, user_arg)) 181 + break; 182 + err = 0; 183 + break; 184 + 185 + case PPPIOCSFLAGS: 186 + if (get_user(val, user_arg)) 187 + break; 188 + network->flags = val & ~SC_RCV_BITS; 189 + network->rbits = val & SC_RCV_BITS; 190 + err = 0; 191 + break; 192 + 193 + case PPPIOCGASYNCMAP: 194 + if (put_user(network->xaccm[0], user_arg)) 195 + break; 196 + err = 0; 197 + break; 198 + 199 + case PPPIOCSASYNCMAP: 200 + if (get_user(network->xaccm[0], user_arg)) 201 + break; 202 + err = 0; 203 + break; 204 + 205 + case PPPIOCGRASYNCMAP: 206 + if (put_user(network->raccm, user_arg)) 207 + break; 208 + err = 0; 209 + break; 210 + 211 + case PPPIOCSRASYNCMAP: 212 + if (get_user(network->raccm, user_arg)) 213 + break; 214 + err = 0; 215 + break; 216 + 217 + case PPPIOCGXASYNCMAP: 218 + if (copy_to_user((void __user *) arg, network->xaccm, 219 + sizeof(network->xaccm))) 220 + break; 221 + err = 0; 222 + break; 223 + 224 + case PPPIOCSXASYNCMAP: 225 + if (copy_from_user(accm, (void __user *) arg, sizeof(accm))) 226 + break; 227 + accm[2] &= ~0x40000000U; /* can't escape 0x5e */ 228 + accm[3] |= 0x60000000U; /* must escape 0x7d, 0x7e */ 229 + memcpy(network->xaccm, accm, sizeof(network->xaccm)); 230 + err = 0; 231 + break; 232 + 233 + case PPPIOCGMRU: 234 + if (put_user(network->mru, user_arg)) 235 + break; 236 + err = 0; 237 + break; 238 + 239 + case PPPIOCSMRU: 240 + if (get_user(val, user_arg)) 241 + break; 242 + if (val < PPP_MRU) 243 + val = PPP_MRU; 244 + network->mru = val; 245 + err = 0; 246 + break; 247 + 248 + default: 249 + err = -ENOTTY; 250 + } 251 + 252 + return err; 253 + } 254 + 255 + static struct ppp_channel_ops ipwireless_ppp_channel_ops = { 256 + .start_xmit = ipwireless_ppp_start_xmit, 257 + .ioctl = ipwireless_ppp_ioctl 258 + }; 259 + 260 + static void do_go_online(struct work_struct *work_go_online) 261 + { 262 + struct ipw_network *network = 263 + container_of(work_go_online, struct ipw_network, 264 + work_go_online); 265 + unsigned long flags; 266 + 267 + spin_lock_irqsave(&network->spinlock, flags); 268 + if (!network->ppp_channel) { 269 + struct ppp_channel *channel; 270 + 271 + spin_unlock_irqrestore(&network->spinlock, flags); 272 + channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL); 273 + if (!channel) { 274 + printk(KERN_ERR IPWIRELESS_PCCARD_NAME 275 + ": unable to allocate PPP channel\n"); 276 + return; 277 + } 278 + channel->private = network; 279 + channel->mtu = 16384; /* Wild guess */ 280 + channel->hdrlen = 2; 281 + channel->ops = &ipwireless_ppp_channel_ops; 282 + 283 + network->flags = 0; 284 + network->rbits = 0; 285 + network->mru = PPP_MRU; 286 + memset(network->xaccm, 0, sizeof(network->xaccm)); 287 + network->xaccm[0] = ~0U; 288 + network->xaccm[3] = 0x60000000U; 289 + network->raccm = ~0U; 290 + ppp_register_channel(channel); 291 + spin_lock_irqsave(&network->spinlock, flags); 292 + network->ppp_channel = channel; 293 + } 294 + spin_unlock_irqrestore(&network->spinlock, flags); 295 + } 296 + 297 + static void do_go_offline(struct work_struct *work_go_offline) 298 + { 299 + struct ipw_network *network = 300 + container_of(work_go_offline, struct ipw_network, 301 + work_go_offline); 302 + unsigned long flags; 303 + 304 + mutex_lock(&network->close_lock); 305 + spin_lock_irqsave(&network->spinlock, flags); 306 + if (network->ppp_channel != NULL) { 307 + struct ppp_channel *channel = network->ppp_channel; 308 + 309 + network->ppp_channel = NULL; 310 + spin_unlock_irqrestore(&network->spinlock, flags); 311 + mutex_unlock(&network->close_lock); 312 + ppp_unregister_channel(channel); 313 + } else { 314 + spin_unlock_irqrestore(&network->spinlock, flags); 315 + mutex_unlock(&network->close_lock); 316 + } 317 + } 318 + 319 + void ipwireless_network_notify_control_line_change(struct ipw_network *network, 320 + unsigned int channel_idx, 321 + unsigned int control_lines, 322 + unsigned int changed_mask) 323 + { 324 + int i; 325 + 326 + if (channel_idx == IPW_CHANNEL_RAS) 327 + network->ras_control_lines = control_lines; 328 + 329 + for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) { 330 + struct ipw_tty *tty = 331 + network->associated_ttys[channel_idx][i]; 332 + 333 + /* 334 + * If it's associated with a tty (other than the RAS channel 335 + * when we're online), then send the data to that tty. The RAS 336 + * channel's data is handled above - it always goes through 337 + * ppp_generic. 338 + */ 339 + if (tty) 340 + ipwireless_tty_notify_control_line_change(tty, 341 + channel_idx, 342 + control_lines, 343 + changed_mask); 344 + } 345 + } 346 + 347 + /* 348 + * Some versions of firmware stuff packets with 0xff 0x03 (PPP: ALLSTATIONS, UI) 349 + * bytes, which are required on sent packet, but not always present on received 350 + * packets 351 + */ 352 + static struct sk_buff *ipw_packet_received_skb(unsigned char *data, 353 + unsigned int length) 354 + { 355 + struct sk_buff *skb; 356 + 357 + if (length > 2 && data[0] == PPP_ALLSTATIONS && data[1] == PPP_UI) { 358 + length -= 2; 359 + data += 2; 360 + } 361 + 362 + skb = dev_alloc_skb(length + 4); 363 + skb_reserve(skb, 2); 364 + memcpy(skb_put(skb, length), data, length); 365 + 366 + return skb; 367 + } 368 + 369 + void ipwireless_network_packet_received(struct ipw_network *network, 370 + unsigned int channel_idx, 371 + unsigned char *data, 372 + unsigned int length) 373 + { 374 + int i; 375 + unsigned long flags; 376 + 377 + for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) { 378 + struct ipw_tty *tty = network->associated_ttys[channel_idx][i]; 379 + 380 + /* 381 + * If it's associated with a tty (other than the RAS channel 382 + * when we're online), then send the data to that tty. The RAS 383 + * channel's data is handled above - it always goes through 384 + * ppp_generic. 385 + */ 386 + if (tty && channel_idx == IPW_CHANNEL_RAS 387 + && (network->ras_control_lines & 388 + IPW_CONTROL_LINE_DCD) != 0 389 + && ipwireless_tty_is_modem(tty)) { 390 + /* 391 + * If data came in on the RAS channel and this tty is 392 + * the modem tty, and we are online, then we send it to 393 + * the PPP layer. 394 + */ 395 + mutex_lock(&network->close_lock); 396 + spin_lock_irqsave(&network->spinlock, flags); 397 + if (network->ppp_channel != NULL) { 398 + struct sk_buff *skb; 399 + 400 + spin_unlock_irqrestore(&network->spinlock, 401 + flags); 402 + 403 + /* Send the data to the ppp_generic module. */ 404 + skb = ipw_packet_received_skb(data, length); 405 + ppp_input(network->ppp_channel, skb); 406 + } else 407 + spin_unlock_irqrestore(&network->spinlock, 408 + flags); 409 + mutex_unlock(&network->close_lock); 410 + } 411 + /* Otherwise we send it out the tty. */ 412 + else 413 + ipwireless_tty_received(tty, data, length); 414 + } 415 + } 416 + 417 + struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw) 418 + { 419 + struct ipw_network *network = 420 + kzalloc(sizeof(struct ipw_network), GFP_ATOMIC); 421 + 422 + if (!network) 423 + return NULL; 424 + 425 + spin_lock_init(&network->spinlock); 426 + mutex_init(&network->close_lock); 427 + 428 + network->hardware = hw; 429 + 430 + INIT_WORK(&network->work_go_online, do_go_online); 431 + INIT_WORK(&network->work_go_offline, do_go_offline); 432 + 433 + ipwireless_associate_network(hw, network); 434 + 435 + return network; 436 + } 437 + 438 + void ipwireless_network_free(struct ipw_network *network) 439 + { 440 + network->shutting_down = 1; 441 + 442 + ipwireless_ppp_close(network); 443 + flush_scheduled_work(); 444 + 445 + ipwireless_stop_interrupts(network->hardware); 446 + ipwireless_associate_network(network->hardware, NULL); 447 + 448 + kfree(network); 449 + } 450 + 451 + void ipwireless_associate_network_tty(struct ipw_network *network, 452 + unsigned int channel_idx, 453 + struct ipw_tty *tty) 454 + { 455 + int i; 456 + 457 + for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) 458 + if (network->associated_ttys[channel_idx][i] == NULL) { 459 + network->associated_ttys[channel_idx][i] = tty; 460 + break; 461 + } 462 + } 463 + 464 + void ipwireless_disassociate_network_ttys(struct ipw_network *network, 465 + unsigned int channel_idx) 466 + { 467 + int i; 468 + 469 + for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) 470 + network->associated_ttys[channel_idx][i] = NULL; 471 + } 472 + 473 + void ipwireless_ppp_open(struct ipw_network *network) 474 + { 475 + if (ipwireless_debug) 476 + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": online\n"); 477 + schedule_work(&network->work_go_online); 478 + } 479 + 480 + void ipwireless_ppp_close(struct ipw_network *network) 481 + { 482 + /* Disconnect from the wireless network. */ 483 + if (ipwireless_debug) 484 + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": offline\n"); 485 + schedule_work(&network->work_go_offline); 486 + } 487 + 488 + int ipwireless_ppp_channel_index(struct ipw_network *network) 489 + { 490 + int ret = -1; 491 + unsigned long flags; 492 + 493 + spin_lock_irqsave(&network->spinlock, flags); 494 + if (network->ppp_channel != NULL) 495 + ret = ppp_channel_index(network->ppp_channel); 496 + spin_unlock_irqrestore(&network->spinlock, flags); 497 + 498 + return ret; 499 + } 500 + 501 + int ipwireless_ppp_unit_number(struct ipw_network *network) 502 + { 503 + int ret = -1; 504 + unsigned long flags; 505 + 506 + spin_lock_irqsave(&network->spinlock, flags); 507 + if (network->ppp_channel != NULL) 508 + ret = ppp_unit_number(network->ppp_channel); 509 + spin_unlock_irqrestore(&network->spinlock, flags); 510 + 511 + return ret; 512 + }
+55
drivers/char/pcmcia/ipwireless/network.h
··· 1 + /* 2 + * IPWireless 3G PCMCIA Network Driver 3 + * 4 + * Original code 5 + * by Stephen Blackheath <stephen@blacksapphire.com>, 6 + * Ben Martel <benm@symmetric.co.nz> 7 + * 8 + * Copyrighted as follows: 9 + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) 10 + * 11 + * Various driver changes and rewrites, port to new kernels 12 + * Copyright (C) 2006-2007 Jiri Kosina 13 + * 14 + * Misc code cleanups and updates 15 + * Copyright (C) 2007 David Sterba 16 + */ 17 + 18 + #ifndef _IPWIRELESS_CS_NETWORK_H_ 19 + #define _IPWIRELESS_CS_NETWORK_H_ 20 + 21 + #include <linux/types.h> 22 + 23 + struct ipw_network; 24 + struct ipw_tty; 25 + struct ipw_hardware; 26 + 27 + /* Definitions of the different channels on the PCMCIA UE */ 28 + #define IPW_CHANNEL_RAS 0 29 + #define IPW_CHANNEL_DIALLER 1 30 + #define IPW_CHANNEL_CONSOLE 2 31 + #define NO_OF_IPW_CHANNELS 5 32 + 33 + void ipwireless_network_notify_control_line_change(struct ipw_network *net, 34 + unsigned int channel_idx, unsigned int control_lines, 35 + unsigned int control_mask); 36 + void ipwireless_network_packet_received(struct ipw_network *net, 37 + unsigned int channel_idx, unsigned char *data, 38 + unsigned int length); 39 + struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw); 40 + void ipwireless_network_free(struct ipw_network *net); 41 + void ipwireless_associate_network_tty(struct ipw_network *net, 42 + unsigned int channel_idx, struct ipw_tty *tty); 43 + void ipwireless_disassociate_network_ttys(struct ipw_network *net, 44 + unsigned int channel_idx); 45 + 46 + void ipwireless_ppp_open(struct ipw_network *net); 47 + 48 + void ipwireless_ppp_close(struct ipw_network *net); 49 + int ipwireless_ppp_channel_index(struct ipw_network *net); 50 + int ipwireless_ppp_unit_number(struct ipw_network *net); 51 + 52 + int ipwireless_dump_network_state(char *p, size_t limit, 53 + struct ipw_network *net); 54 + 55 + #endif
+108
drivers/char/pcmcia/ipwireless/setup_protocol.h
··· 1 + /* 2 + * IPWireless 3G PCMCIA Network Driver 3 + * 4 + * Original code 5 + * by Stephen Blackheath <stephen@blacksapphire.com>, 6 + * Ben Martel <benm@symmetric.co.nz> 7 + * 8 + * Copyrighted as follows: 9 + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) 10 + * 11 + * Various driver changes and rewrites, port to new kernels 12 + * Copyright (C) 2006-2007 Jiri Kosina 13 + * 14 + * Misc code cleanups and updates 15 + * Copyright (C) 2007 David Sterba 16 + */ 17 + 18 + #ifndef _IPWIRELESS_CS_SETUP_PROTOCOL_H_ 19 + #define _IPWIRELESS_CS_SETUP_PROTOCOL_H_ 20 + 21 + /* Version of the setup protocol and transport protocols */ 22 + #define TL_SETUP_VERSION 1 23 + 24 + #define TL_SETUP_VERSION_QRY_TMO 1000 25 + #define TL_SETUP_MAX_VERSION_QRY 30 26 + 27 + /* Message numbers 0-9 are obsoleted and must not be reused! */ 28 + #define TL_SETUP_SIGNO_GET_VERSION_QRY 10 29 + #define TL_SETUP_SIGNO_GET_VERSION_RSP 11 30 + #define TL_SETUP_SIGNO_CONFIG_MSG 12 31 + #define TL_SETUP_SIGNO_CONFIG_DONE_MSG 13 32 + #define TL_SETUP_SIGNO_OPEN_MSG 14 33 + #define TL_SETUP_SIGNO_CLOSE_MSG 15 34 + 35 + #define TL_SETUP_SIGNO_INFO_MSG 20 36 + #define TL_SETUP_SIGNO_INFO_MSG_ACK 21 37 + 38 + #define TL_SETUP_SIGNO_REBOOT_MSG 22 39 + #define TL_SETUP_SIGNO_REBOOT_MSG_ACK 23 40 + 41 + /* Synchronous start-messages */ 42 + struct tl_setup_get_version_qry { 43 + unsigned char sig_no; /* TL_SETUP_SIGNO_GET_VERSION_QRY */ 44 + } __attribute__ ((__packed__)); 45 + 46 + struct tl_setup_get_version_rsp { 47 + unsigned char sig_no; /* TL_SETUP_SIGNO_GET_VERSION_RSP */ 48 + unsigned char version; /* TL_SETUP_VERSION */ 49 + } __attribute__ ((__packed__)); 50 + 51 + struct tl_setup_config_msg { 52 + unsigned char sig_no; /* TL_SETUP_SIGNO_CONFIG_MSG */ 53 + unsigned char port_no; 54 + unsigned char prio_data; 55 + unsigned char prio_ctrl; 56 + } __attribute__ ((__packed__)); 57 + 58 + struct tl_setup_config_done_msg { 59 + unsigned char sig_no; /* TL_SETUP_SIGNO_CONFIG_DONE_MSG */ 60 + } __attribute__ ((__packed__)); 61 + 62 + /* Asyncronous messages */ 63 + struct tl_setup_open_msg { 64 + unsigned char sig_no; /* TL_SETUP_SIGNO_OPEN_MSG */ 65 + unsigned char port_no; 66 + } __attribute__ ((__packed__)); 67 + 68 + struct tl_setup_close_msg { 69 + unsigned char sig_no; /* TL_SETUP_SIGNO_CLOSE_MSG */ 70 + unsigned char port_no; 71 + } __attribute__ ((__packed__)); 72 + 73 + /* Driver type - for use in tl_setup_info_msg.driver_type */ 74 + #define COMM_DRIVER 0 75 + #define NDISWAN_DRIVER 1 76 + #define NDISWAN_DRIVER_MAJOR_VERSION 2 77 + #define NDISWAN_DRIVER_MINOR_VERSION 0 78 + 79 + /* 80 + * It should not matter when this message comes over as we just store the 81 + * results and send the ACK. 82 + */ 83 + struct tl_setup_info_msg { 84 + unsigned char sig_no; /* TL_SETUP_SIGNO_INFO_MSG */ 85 + unsigned char driver_type; 86 + unsigned char major_version; 87 + unsigned char minor_version; 88 + } __attribute__ ((__packed__)); 89 + 90 + struct tl_setup_info_msgAck { 91 + unsigned char sig_no; /* TL_SETUP_SIGNO_INFO_MSG_ACK */ 92 + } __attribute__ ((__packed__)); 93 + 94 + struct TlSetupRebootMsgAck { 95 + unsigned char sig_no; /* TL_SETUP_SIGNO_REBOOT_MSG_ACK */ 96 + } __attribute__ ((__packed__)); 97 + 98 + /* Define a union of all the msgs that the driver can receive from the card.*/ 99 + union ipw_setup_rx_msg { 100 + unsigned char sig_no; 101 + struct tl_setup_get_version_rsp version_rsp_msg; 102 + struct tl_setup_open_msg open_msg; 103 + struct tl_setup_close_msg close_msg; 104 + struct tl_setup_info_msg InfoMsg; 105 + struct tl_setup_info_msgAck info_msg_ack; 106 + } __attribute__ ((__packed__)); 107 + 108 + #endif /* _IPWIRELESS_CS_SETUP_PROTOCOL_H_ */
+688
drivers/char/pcmcia/ipwireless/tty.c
··· 1 + /* 2 + * IPWireless 3G PCMCIA Network Driver 3 + * 4 + * Original code 5 + * by Stephen Blackheath <stephen@blacksapphire.com>, 6 + * Ben Martel <benm@symmetric.co.nz> 7 + * 8 + * Copyrighted as follows: 9 + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) 10 + * 11 + * Various driver changes and rewrites, port to new kernels 12 + * Copyright (C) 2006-2007 Jiri Kosina 13 + * 14 + * Misc code cleanups and updates 15 + * Copyright (C) 2007 David Sterba 16 + */ 17 + 18 + #include <linux/init.h> 19 + #include <linux/kernel.h> 20 + #include <linux/module.h> 21 + #include <linux/mutex.h> 22 + #include <linux/ppp_defs.h> 23 + #include <linux/if.h> 24 + #include <linux/if_ppp.h> 25 + #include <linux/sched.h> 26 + #include <linux/serial.h> 27 + #include <linux/slab.h> 28 + #include <linux/tty.h> 29 + #include <linux/tty_driver.h> 30 + #include <linux/tty_flip.h> 31 + #include <linux/uaccess.h> 32 + #include <linux/version.h> 33 + 34 + #include "tty.h" 35 + #include "network.h" 36 + #include "hardware.h" 37 + #include "main.h" 38 + 39 + #define IPWIRELESS_PCMCIA_START (0) 40 + #define IPWIRELESS_PCMCIA_MINORS (24) 41 + #define IPWIRELESS_PCMCIA_MINOR_RANGE (8) 42 + 43 + #define TTYTYPE_MODEM (0) 44 + #define TTYTYPE_MONITOR (1) 45 + #define TTYTYPE_RAS_RAW (2) 46 + 47 + struct ipw_tty { 48 + int index; 49 + struct ipw_hardware *hardware; 50 + unsigned int channel_idx; 51 + unsigned int secondary_channel_idx; 52 + int tty_type; 53 + struct ipw_network *network; 54 + struct tty_struct *linux_tty; 55 + int open_count; 56 + unsigned int control_lines; 57 + struct mutex ipw_tty_mutex; 58 + int tx_bytes_queued; 59 + int closing; 60 + }; 61 + 62 + static struct ipw_tty *ttys[IPWIRELESS_PCMCIA_MINORS]; 63 + 64 + static struct tty_driver *ipw_tty_driver; 65 + 66 + static char *tty_type_name(int tty_type) 67 + { 68 + static char *channel_names[] = { 69 + "modem", 70 + "monitor", 71 + "RAS-raw" 72 + }; 73 + 74 + return channel_names[tty_type]; 75 + } 76 + 77 + static void report_registering(struct ipw_tty *tty) 78 + { 79 + char *iftype = tty_type_name(tty->tty_type); 80 + 81 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 82 + ": registering %s device ttyIPWp%d\n", iftype, tty->index); 83 + } 84 + 85 + static void report_deregistering(struct ipw_tty *tty) 86 + { 87 + char *iftype = tty_type_name(tty->tty_type); 88 + 89 + printk(KERN_INFO IPWIRELESS_PCCARD_NAME 90 + ": deregistering %s device ttyIPWp%d\n", iftype, 91 + tty->index); 92 + } 93 + 94 + static struct ipw_tty *get_tty(int minor) 95 + { 96 + if (minor < ipw_tty_driver->minor_start 97 + || minor >= ipw_tty_driver->minor_start + 98 + IPWIRELESS_PCMCIA_MINORS) 99 + return NULL; 100 + else { 101 + int minor_offset = minor - ipw_tty_driver->minor_start; 102 + 103 + /* 104 + * The 'ras_raw' channel is only available when 'loopback' mode 105 + * is enabled. 106 + * Number of minor starts with 16 (_RANGE * _RAS_RAW). 107 + */ 108 + if (!ipwireless_loopback && 109 + minor_offset >= 110 + IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW) 111 + return NULL; 112 + 113 + return ttys[minor_offset]; 114 + } 115 + } 116 + 117 + static int ipw_open(struct tty_struct *linux_tty, struct file *filp) 118 + { 119 + int minor = linux_tty->index; 120 + struct ipw_tty *tty = get_tty(minor); 121 + 122 + if (!tty) 123 + return -ENODEV; 124 + 125 + mutex_lock(&tty->ipw_tty_mutex); 126 + 127 + if (tty->closing) { 128 + mutex_unlock(&tty->ipw_tty_mutex); 129 + return -ENODEV; 130 + } 131 + if (tty->open_count == 0) 132 + tty->tx_bytes_queued = 0; 133 + 134 + tty->open_count++; 135 + 136 + tty->linux_tty = linux_tty; 137 + linux_tty->driver_data = tty; 138 + linux_tty->low_latency = 1; 139 + 140 + if (tty->tty_type == TTYTYPE_MODEM) 141 + ipwireless_ppp_open(tty->network); 142 + 143 + mutex_unlock(&tty->ipw_tty_mutex); 144 + 145 + return 0; 146 + } 147 + 148 + static void do_ipw_close(struct ipw_tty *tty) 149 + { 150 + tty->open_count--; 151 + 152 + if (tty->open_count == 0) { 153 + struct tty_struct *linux_tty = tty->linux_tty; 154 + 155 + if (linux_tty != NULL) { 156 + tty->linux_tty = NULL; 157 + linux_tty->driver_data = NULL; 158 + 159 + if (tty->tty_type == TTYTYPE_MODEM) 160 + ipwireless_ppp_close(tty->network); 161 + } 162 + } 163 + } 164 + 165 + static void ipw_hangup(struct tty_struct *linux_tty) 166 + { 167 + struct ipw_tty *tty = linux_tty->driver_data; 168 + 169 + if (!tty) 170 + return; 171 + 172 + mutex_lock(&tty->ipw_tty_mutex); 173 + if (tty->open_count == 0) { 174 + mutex_unlock(&tty->ipw_tty_mutex); 175 + return; 176 + } 177 + 178 + do_ipw_close(tty); 179 + 180 + mutex_unlock(&tty->ipw_tty_mutex); 181 + } 182 + 183 + static void ipw_close(struct tty_struct *linux_tty, struct file *filp) 184 + { 185 + ipw_hangup(linux_tty); 186 + } 187 + 188 + /* Take data received from hardware, and send it out the tty */ 189 + void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data, 190 + unsigned int length) 191 + { 192 + struct tty_struct *linux_tty; 193 + int work = 0; 194 + 195 + mutex_lock(&tty->ipw_tty_mutex); 196 + linux_tty = tty->linux_tty; 197 + if (linux_tty == NULL) { 198 + mutex_unlock(&tty->ipw_tty_mutex); 199 + return; 200 + } 201 + 202 + if (!tty->open_count) { 203 + mutex_unlock(&tty->ipw_tty_mutex); 204 + return; 205 + } 206 + mutex_unlock(&tty->ipw_tty_mutex); 207 + 208 + work = tty_insert_flip_string(linux_tty, data, length); 209 + 210 + if (work != length) 211 + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME 212 + ": %d chars not inserted to flip buffer!\n", 213 + length - work); 214 + 215 + /* 216 + * This may sleep if ->low_latency is set 217 + */ 218 + if (work) 219 + tty_flip_buffer_push(linux_tty); 220 + } 221 + 222 + static void ipw_write_packet_sent_callback(void *callback_data, 223 + unsigned int packet_length) 224 + { 225 + struct ipw_tty *tty = callback_data; 226 + 227 + /* 228 + * Packet has been sent, so we subtract the number of bytes from our 229 + * tally of outstanding TX bytes. 230 + */ 231 + tty->tx_bytes_queued -= packet_length; 232 + } 233 + 234 + static int ipw_write(struct tty_struct *linux_tty, 235 + const unsigned char *buf, int count) 236 + { 237 + struct ipw_tty *tty = linux_tty->driver_data; 238 + int room, ret; 239 + 240 + if (!tty) 241 + return -ENODEV; 242 + 243 + mutex_lock(&tty->ipw_tty_mutex); 244 + if (!tty->open_count) { 245 + mutex_unlock(&tty->ipw_tty_mutex); 246 + return -EINVAL; 247 + } 248 + 249 + room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued; 250 + if (room < 0) 251 + room = 0; 252 + /* Don't allow caller to write any more than we have room for */ 253 + if (count > room) 254 + count = room; 255 + 256 + if (count == 0) { 257 + mutex_unlock(&tty->ipw_tty_mutex); 258 + return 0; 259 + } 260 + 261 + ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS, 262 + (unsigned char *) buf, count, 263 + ipw_write_packet_sent_callback, tty); 264 + if (ret == -1) { 265 + mutex_unlock(&tty->ipw_tty_mutex); 266 + return 0; 267 + } 268 + 269 + tty->tx_bytes_queued += count; 270 + mutex_unlock(&tty->ipw_tty_mutex); 271 + 272 + return count; 273 + } 274 + 275 + static int ipw_write_room(struct tty_struct *linux_tty) 276 + { 277 + struct ipw_tty *tty = linux_tty->driver_data; 278 + int room; 279 + 280 + if (!tty) 281 + return -ENODEV; 282 + 283 + if (!tty->open_count) 284 + return -EINVAL; 285 + 286 + room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued; 287 + if (room < 0) 288 + room = 0; 289 + 290 + return room; 291 + } 292 + 293 + static int ipwireless_get_serial_info(struct ipw_tty *tty, 294 + struct serial_struct __user *retinfo) 295 + { 296 + struct serial_struct tmp; 297 + 298 + if (!retinfo) 299 + return (-EFAULT); 300 + 301 + memset(&tmp, 0, sizeof(tmp)); 302 + tmp.type = PORT_UNKNOWN; 303 + tmp.line = tty->index; 304 + tmp.port = 0; 305 + tmp.irq = 0; 306 + tmp.flags = 0; 307 + tmp.baud_base = 115200; 308 + tmp.close_delay = 0; 309 + tmp.closing_wait = 0; 310 + tmp.custom_divisor = 0; 311 + tmp.hub6 = 0; 312 + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) 313 + return -EFAULT; 314 + 315 + return 0; 316 + } 317 + 318 + static int ipw_chars_in_buffer(struct tty_struct *linux_tty) 319 + { 320 + struct ipw_tty *tty = linux_tty->driver_data; 321 + 322 + if (!tty) 323 + return -ENODEV; 324 + 325 + if (!tty->open_count) 326 + return -EINVAL; 327 + 328 + return tty->tx_bytes_queued; 329 + } 330 + 331 + static int get_control_lines(struct ipw_tty *tty) 332 + { 333 + unsigned int my = tty->control_lines; 334 + unsigned int out = 0; 335 + 336 + if (my & IPW_CONTROL_LINE_RTS) 337 + out |= TIOCM_RTS; 338 + if (my & IPW_CONTROL_LINE_DTR) 339 + out |= TIOCM_DTR; 340 + if (my & IPW_CONTROL_LINE_CTS) 341 + out |= TIOCM_CTS; 342 + if (my & IPW_CONTROL_LINE_DSR) 343 + out |= TIOCM_DSR; 344 + if (my & IPW_CONTROL_LINE_DCD) 345 + out |= TIOCM_CD; 346 + 347 + return out; 348 + } 349 + 350 + static int set_control_lines(struct ipw_tty *tty, unsigned int set, 351 + unsigned int clear) 352 + { 353 + int ret; 354 + 355 + if (set & TIOCM_RTS) { 356 + ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 1); 357 + if (ret) 358 + return ret; 359 + if (tty->secondary_channel_idx != -1) { 360 + ret = ipwireless_set_RTS(tty->hardware, 361 + tty->secondary_channel_idx, 1); 362 + if (ret) 363 + return ret; 364 + } 365 + } 366 + if (set & TIOCM_DTR) { 367 + ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 1); 368 + if (ret) 369 + return ret; 370 + if (tty->secondary_channel_idx != -1) { 371 + ret = ipwireless_set_DTR(tty->hardware, 372 + tty->secondary_channel_idx, 1); 373 + if (ret) 374 + return ret; 375 + } 376 + } 377 + if (clear & TIOCM_RTS) { 378 + ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 0); 379 + if (tty->secondary_channel_idx != -1) { 380 + ret = ipwireless_set_RTS(tty->hardware, 381 + tty->secondary_channel_idx, 0); 382 + if (ret) 383 + return ret; 384 + } 385 + } 386 + if (clear & TIOCM_DTR) { 387 + ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 0); 388 + if (tty->secondary_channel_idx != -1) { 389 + ret = ipwireless_set_DTR(tty->hardware, 390 + tty->secondary_channel_idx, 0); 391 + if (ret) 392 + return ret; 393 + } 394 + } 395 + return 0; 396 + } 397 + 398 + static int ipw_tiocmget(struct tty_struct *linux_tty, struct file *file) 399 + { 400 + struct ipw_tty *tty = linux_tty->driver_data; 401 + 402 + if (!tty) 403 + return -ENODEV; 404 + 405 + if (!tty->open_count) 406 + return -EINVAL; 407 + 408 + return get_control_lines(tty); 409 + } 410 + 411 + static int 412 + ipw_tiocmset(struct tty_struct *linux_tty, struct file *file, 413 + unsigned int set, unsigned int clear) 414 + { 415 + struct ipw_tty *tty = linux_tty->driver_data; 416 + 417 + if (!tty) 418 + return -ENODEV; 419 + 420 + if (!tty->open_count) 421 + return -EINVAL; 422 + 423 + return set_control_lines(tty, set, clear); 424 + } 425 + 426 + static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file, 427 + unsigned int cmd, unsigned long arg) 428 + { 429 + struct ipw_tty *tty = linux_tty->driver_data; 430 + 431 + if (!tty) 432 + return -ENODEV; 433 + 434 + if (!tty->open_count) 435 + return -EINVAL; 436 + 437 + switch (cmd) { 438 + case TIOCGSERIAL: 439 + return ipwireless_get_serial_info(tty, (void __user *) arg); 440 + 441 + case TIOCSSERIAL: 442 + return 0; /* Keeps the PCMCIA scripts happy. */ 443 + } 444 + 445 + if (tty->tty_type == TTYTYPE_MODEM) { 446 + switch (cmd) { 447 + case PPPIOCGCHAN: 448 + { 449 + int chan = ipwireless_ppp_channel_index( 450 + tty->network); 451 + 452 + if (chan < 0) 453 + return -ENODEV; 454 + if (put_user(chan, (int __user *) arg)) 455 + return -EFAULT; 456 + } 457 + return 0; 458 + 459 + case PPPIOCGUNIT: 460 + { 461 + int unit = ipwireless_ppp_unit_number( 462 + tty->network); 463 + 464 + if (unit < 0) 465 + return -ENODEV; 466 + if (put_user(unit, (int __user *) arg)) 467 + return -EFAULT; 468 + } 469 + return 0; 470 + 471 + case TCGETS: 472 + case TCGETA: 473 + return n_tty_ioctl(linux_tty, file, cmd, arg); 474 + 475 + case TCFLSH: 476 + return n_tty_ioctl(linux_tty, file, cmd, arg); 477 + 478 + case FIONREAD: 479 + { 480 + int val = 0; 481 + 482 + if (put_user(val, (int __user *) arg)) 483 + return -EFAULT; 484 + } 485 + return 0; 486 + } 487 + } 488 + 489 + return -ENOIOCTLCMD; 490 + } 491 + 492 + static int add_tty(dev_node_t *nodesp, int j, 493 + struct ipw_hardware *hardware, 494 + struct ipw_network *network, int channel_idx, 495 + int secondary_channel_idx, int tty_type) 496 + { 497 + ttys[j] = kzalloc(sizeof(struct ipw_tty), GFP_KERNEL); 498 + if (!ttys[j]) 499 + return -ENOMEM; 500 + ttys[j]->index = j; 501 + ttys[j]->hardware = hardware; 502 + ttys[j]->channel_idx = channel_idx; 503 + ttys[j]->secondary_channel_idx = secondary_channel_idx; 504 + ttys[j]->network = network; 505 + ttys[j]->tty_type = tty_type; 506 + mutex_init(&ttys[j]->ipw_tty_mutex); 507 + 508 + tty_register_device(ipw_tty_driver, j, NULL); 509 + ipwireless_associate_network_tty(network, channel_idx, ttys[j]); 510 + 511 + if (secondary_channel_idx != -1) 512 + ipwireless_associate_network_tty(network, 513 + secondary_channel_idx, 514 + ttys[j]); 515 + if (nodesp != NULL) { 516 + sprintf(nodesp->dev_name, "ttyIPWp%d", j); 517 + nodesp->major = ipw_tty_driver->major; 518 + nodesp->minor = j + ipw_tty_driver->minor_start; 519 + } 520 + if (get_tty(j + ipw_tty_driver->minor_start) == ttys[j]) 521 + report_registering(ttys[j]); 522 + return 0; 523 + } 524 + 525 + struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware, 526 + struct ipw_network *network, 527 + dev_node_t *nodes) 528 + { 529 + int i, j; 530 + 531 + for (i = 0; i < IPWIRELESS_PCMCIA_MINOR_RANGE; i++) { 532 + int allfree = 1; 533 + 534 + for (j = i; j < IPWIRELESS_PCMCIA_MINORS; 535 + j += IPWIRELESS_PCMCIA_MINOR_RANGE) 536 + if (ttys[j] != NULL) { 537 + allfree = 0; 538 + break; 539 + } 540 + 541 + if (allfree) { 542 + j = i; 543 + 544 + if (add_tty(&nodes[0], j, hardware, network, 545 + IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS, 546 + TTYTYPE_MODEM)) 547 + return NULL; 548 + 549 + j += IPWIRELESS_PCMCIA_MINOR_RANGE; 550 + if (add_tty(&nodes[1], j, hardware, network, 551 + IPW_CHANNEL_DIALLER, -1, 552 + TTYTYPE_MONITOR)) 553 + return NULL; 554 + 555 + j += IPWIRELESS_PCMCIA_MINOR_RANGE; 556 + if (add_tty(NULL, j, hardware, network, 557 + IPW_CHANNEL_RAS, -1, 558 + TTYTYPE_RAS_RAW)) 559 + return NULL; 560 + 561 + nodes[0].next = &nodes[1]; 562 + nodes[1].next = NULL; 563 + 564 + return ttys[i]; 565 + } 566 + } 567 + return NULL; 568 + } 569 + 570 + /* 571 + * Must be called before ipwireless_network_free(). 572 + */ 573 + void ipwireless_tty_free(struct ipw_tty *tty) 574 + { 575 + int j; 576 + struct ipw_network *network = ttys[tty->index]->network; 577 + 578 + for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS; 579 + j += IPWIRELESS_PCMCIA_MINOR_RANGE) { 580 + struct ipw_tty *ttyj = ttys[j]; 581 + 582 + if (ttyj) { 583 + mutex_lock(&ttyj->ipw_tty_mutex); 584 + if (get_tty(j + ipw_tty_driver->minor_start) == ttyj) 585 + report_deregistering(ttyj); 586 + ttyj->closing = 1; 587 + if (ttyj->linux_tty != NULL) { 588 + mutex_unlock(&ttyj->ipw_tty_mutex); 589 + tty_hangup(ttyj->linux_tty); 590 + /* Wait till the tty_hangup has completed */ 591 + flush_scheduled_work(); 592 + mutex_lock(&ttyj->ipw_tty_mutex); 593 + } 594 + while (ttyj->open_count) 595 + do_ipw_close(ttyj); 596 + ipwireless_disassociate_network_ttys(network, 597 + ttyj->channel_idx); 598 + tty_unregister_device(ipw_tty_driver, j); 599 + ttys[j] = NULL; 600 + mutex_unlock(&ttyj->ipw_tty_mutex); 601 + kfree(ttyj); 602 + } 603 + } 604 + } 605 + 606 + static struct tty_operations tty_ops = { 607 + .open = ipw_open, 608 + .close = ipw_close, 609 + .hangup = ipw_hangup, 610 + .write = ipw_write, 611 + .write_room = ipw_write_room, 612 + .ioctl = ipw_ioctl, 613 + .chars_in_buffer = ipw_chars_in_buffer, 614 + .tiocmget = ipw_tiocmget, 615 + .tiocmset = ipw_tiocmset, 616 + }; 617 + 618 + int ipwireless_tty_init(void) 619 + { 620 + int result; 621 + 622 + ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS); 623 + if (!ipw_tty_driver) 624 + return -ENOMEM; 625 + 626 + ipw_tty_driver->owner = THIS_MODULE; 627 + ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME; 628 + ipw_tty_driver->name = "ttyIPWp"; 629 + ipw_tty_driver->major = 0; 630 + ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START; 631 + ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; 632 + ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL; 633 + ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; 634 + ipw_tty_driver->init_termios = tty_std_termios; 635 + ipw_tty_driver->init_termios.c_cflag = 636 + B9600 | CS8 | CREAD | HUPCL | CLOCAL; 637 + ipw_tty_driver->init_termios.c_ispeed = 9600; 638 + ipw_tty_driver->init_termios.c_ospeed = 9600; 639 + tty_set_operations(ipw_tty_driver, &tty_ops); 640 + result = tty_register_driver(ipw_tty_driver); 641 + if (result) { 642 + printk(KERN_ERR IPWIRELESS_PCCARD_NAME 643 + ": failed to register tty driver\n"); 644 + put_tty_driver(ipw_tty_driver); 645 + return result; 646 + } 647 + 648 + return 0; 649 + } 650 + 651 + void ipwireless_tty_release(void) 652 + { 653 + int ret; 654 + 655 + ret = tty_unregister_driver(ipw_tty_driver); 656 + put_tty_driver(ipw_tty_driver); 657 + if (ret != 0) 658 + printk(KERN_ERR IPWIRELESS_PCCARD_NAME 659 + ": tty_unregister_driver failed with code %d\n", ret); 660 + } 661 + 662 + int ipwireless_tty_is_modem(struct ipw_tty *tty) 663 + { 664 + return tty->tty_type == TTYTYPE_MODEM; 665 + } 666 + 667 + void 668 + ipwireless_tty_notify_control_line_change(struct ipw_tty *tty, 669 + unsigned int channel_idx, 670 + unsigned int control_lines, 671 + unsigned int changed_mask) 672 + { 673 + unsigned int old_control_lines = tty->control_lines; 674 + 675 + tty->control_lines = (tty->control_lines & ~changed_mask) 676 + | (control_lines & changed_mask); 677 + 678 + /* 679 + * If DCD is de-asserted, we close the tty so pppd can tell that we 680 + * have gone offline. 681 + */ 682 + if ((old_control_lines & IPW_CONTROL_LINE_DCD) 683 + && !(tty->control_lines & IPW_CONTROL_LINE_DCD) 684 + && tty->linux_tty) { 685 + tty_hangup(tty->linux_tty); 686 + } 687 + } 688 +
+48
drivers/char/pcmcia/ipwireless/tty.h
··· 1 + /* 2 + * IPWireless 3G PCMCIA Network Driver 3 + * 4 + * Original code 5 + * by Stephen Blackheath <stephen@blacksapphire.com>, 6 + * Ben Martel <benm@symmetric.co.nz> 7 + * 8 + * Copyrighted as follows: 9 + * Copyright (C) 2004 by Symmetric Systems Ltd (NZ) 10 + * 11 + * Various driver changes and rewrites, port to new kernels 12 + * Copyright (C) 2006-2007 Jiri Kosina 13 + * 14 + * Misc code cleanups and updates 15 + * Copyright (C) 2007 David Sterba 16 + */ 17 + 18 + #ifndef _IPWIRELESS_CS_TTY_H_ 19 + #define _IPWIRELESS_CS_TTY_H_ 20 + 21 + #include <linux/types.h> 22 + #include <linux/sched.h> 23 + 24 + #include <pcmcia/cs_types.h> 25 + #include <pcmcia/cs.h> 26 + #include <pcmcia/cistpl.h> 27 + #include <pcmcia/ds.h> 28 + 29 + struct ipw_tty; 30 + struct ipw_network; 31 + struct ipw_hardware; 32 + 33 + int ipwireless_tty_init(void); 34 + void ipwireless_tty_release(void); 35 + 36 + struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hw, 37 + struct ipw_network *net, 38 + dev_node_t *nodes); 39 + void ipwireless_tty_free(struct ipw_tty *tty); 40 + void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data, 41 + unsigned int length); 42 + int ipwireless_tty_is_modem(struct ipw_tty *tty); 43 + void ipwireless_tty_notify_control_line_change(struct ipw_tty *tty, 44 + unsigned int channel_idx, 45 + unsigned int control_lines, 46 + unsigned int changed_mask); 47 + 48 + #endif