On Mon, 28 Jan 2008 18:19:29 +0100 David Sterba wrote:

[resending due to send problems, sorry about any dups]

> Hi Linus,
> 
> I'm submitting driver for IPWireless PC Card modem for inclusion to 2.6.25.
> 
> The driver has been in -mm series as ipwireless_cs.git tree for
> some time and has passed through lkml (http://lkml.org/lkml/2007/12/12/165).
> The PCMCIA subsystem is unmaintained, so I'm sending it directly as Andrew
> suggested.
> 
> David Sterba
> ---
> From: David Sterba <[EMAIL PROTECTED]>
> 
> ipwireless: driver for PC Card, 3G internet connection
> 
> The driver is manufactured by IPWireless.
> 
> Rewieved-by: Jiri Slaby <[EMAIL PROTECTED]>
> Signed-off-by: Ben Martel <[EMAIL PROTECTED]>
> Signed-off-by: Stephen Blackheath <[EMAIL PROTECTED]>
> Signed-off-by: David Sterba <[EMAIL PROTECTED]>
> Signed-off-by: Jiri Kosina <[EMAIL PROTECTED]>
> ---
>  MAINTAINERS                                     |    8 
>  drivers/char/pcmcia/Kconfig                     |    9 
>  drivers/char/pcmcia/Makefile                    |    2 
>  drivers/char/pcmcia/ipwireless/Makefile         |   10 
>  drivers/char/pcmcia/ipwireless/hardware.c       | 1784 
> ++++++++++++++++++++++++
>  drivers/char/pcmcia/ipwireless/hardware.h       |   63 
>  drivers/char/pcmcia/ipwireless/main.c           |  496 ++++++
>  drivers/char/pcmcia/ipwireless/main.h           |   70 
>  drivers/char/pcmcia/ipwireless/network.c        |  513 ++++++
>  drivers/char/pcmcia/ipwireless/network.h        |   54 
>  drivers/char/pcmcia/ipwireless/setup_protocol.h |  108 +
>  drivers/char/pcmcia/ipwireless/tty.c            |  687 +++++++++
>  drivers/char/pcmcia/ipwireless/tty.h            |   48 
>  13 files changed, 3852 insertions(+)
> ---
> diff --git a/drivers/char/pcmcia/ipwireless/hardware.c 
> b/drivers/char/pcmcia/ipwireless/hardware.c
> new file mode 100644
> index 0000000..de31f48
> --- /dev/null
> +++ b/drivers/char/pcmcia/ipwireless/hardware.c
> @@ -0,0 +1,1784 @@
> +/*
> + * IPWireless 3G PCMCIA Network Driver
> + *
> + * Original code
> + *   by Stephen Blackheath <[EMAIL PROTECTED]>,
> + *      Ben Martel <[EMAIL PROTECTED]>
> + *
> + * Copyrighted as follows:
> + *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
> + *
> + * Various driver changes and rewrites, port to new kernels
> + *   Copyright (C) 2006-2007 Jiri Kosina
> + *
> + * Misc code cleanups and updates
> + *   Copyright (C) 2007 David Sterba
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/irq.h>
> +#include <linux/kernel.h>
> +#include <linux/list.h>
> +#include <linux/slab.h>
> +
> +#include "hardware.h"
> +#include "setup_protocol.h"
> +#include "network.h"
> +#include "main.h"
> +
> +/* Function prototypes */
> +static void ipw_send_setup_packet(struct ipw_hardware *hw);
> +static void handle_received_SETUP_packet(struct ipw_hardware *ipw,
> +                                      unsigned int address,
> +                                      unsigned char *data, int len,
> +                                      int is_last);
> +static void ipwireless_setup_timer(unsigned long data);
> +static void handle_received_CTRL_packet(struct ipw_hardware *hw,
> +             unsigned int channel_idx, unsigned char *data, int len);
> +
> +/*#define TIMING_DIAGNOSTICS*/
> +
> +#ifdef TIMING_DIAGNOSTICS
> +
> +static struct timing_stats {
> +     unsigned long last_report_time;
> +     unsigned long read_time;
> +     unsigned long write_time;
> +     unsigned long read_bytes;
> +     unsigned long write_bytes;
> +     unsigned long start_time;
> +};
> +
...
> +/* Protocol ids */
> +enum {
> +     /* Identifier for the Com Data protocol */
> +     TL_PROTOCOLID_COM_DATA = 0,
> +
> +     /* Identifier for the Com Control protocol */
> +     TL_PROTOCOLID_COM_CTRL = 1,
> +
> +     /* Identifier for the Setup protocol */
> +     TL_PROTOCOLID_SETUP = 2
> +};
> +
> +/* Number of bytes in NL packet header (can not do

cannot

> + * sizeof(nl_packet_header) since it's a bitfield) */
> +#define NL_FIRST_PACKET_HEADER_SIZE        3
> +
> +/* Number of bytes in NL packet header (can not do

cannot

> + * sizeof(nl_packet_header) since it's a bitfield) */
> +#define NL_FOLLOWING_PACKET_HEADER_SIZE    1
> +
> +struct nl_first_paket_header {

                   packet ?

> +#if defined(__BIG_ENDIAN)
> +     unsigned char packet_rank:2;
> +     unsigned char address:3;
> +     unsigned char protocol:3;
> +#else
> +     unsigned char protocol:3;
> +     unsigned char address:3;
> +     unsigned char packet_rank:2;
> +#endif

>From C99 spec:
"The order of allocation of bit-fields within a unit (high-order to
low-order or low-order to high-order) is implementation-defined."

so if the order/location of these bitfields is important (from one
system to another), you should use bit masks instead of bitfields
for them.

> +     unsigned char length_lsb;
> +     unsigned char length_msb;
> +};
> +
> +struct nl_packet_header {
> +#if defined(__BIG_ENDIAN)
> +     unsigned char packet_rank:2;
> +     unsigned char address:3;
> +     unsigned char protocol:3;
> +#else
> +     unsigned char protocol:3;
> +     unsigned char address:3;
> +     unsigned char packet_rank:2;
> +#endif
> +};
> +
> +/* Value of 'packet_rank' above */
> +#define NL_INTERMEDIATE_PACKET    0x0
> +#define NL_LAST_PACKET            0x1
> +#define NL_FIRST_PACKET           0x2
> +
> +union nl_packet {
> +     /* Network packet header of the first packet (a special case) */
> +     struct nl_first_paket_header hdr_first;
> +     /* Network packet header of the following packets (if any) */
> +     struct nl_packet_header hdr;
> +     /* Complete network packet (header + data) */
> +     unsigned char rawpkt[LL_MTU_MAX];
> +} __attribute__ ((__packed__));
> +
> +#define HW_VERSION_UNKNOWN -1
> +#define HW_VERSION_1 1
> +#define HW_VERSION_2 2
> +
...
> +
> +/*
> + * Packet info structure for tx packets.
> + * Note: not all the fields defined here are required for all protocols
> + */
> +struct ipw_tx_packet {
> +     struct list_head queue;
> +     /* channel idx + 1 */
> +     unsigned char dest_addr;
> +     /* SETUP, CTRL or DATA */
> +     unsigned char protocol;
> +     /* Length of data block, which starts at the end of this structure */
> +     unsigned short length;
> +     /* Sending state */
> +     /* Offset of where we've sent up to so far */
> +     unsigned long offset;
> +     /* Count of packet fragments, starting at 0 */
> +     int fragment_count;
> +
> +     /* Called after packet is sent and before is freed */
> +     void (*packet_callback) (void *cb_data, unsigned int packet_length);
> +     void *callback_data;
> +};
> +
> +/* Signals from DTE */
> +enum ComCtrl_DTESignal {
> +     ComCtrl_RTS = 0,
> +     ComCtrl_DTR = 1
> +};
> +
> +/* Signals from DCE */
> +enum ComCtrl_DCESignal {
> +     ComCtrl_CTS = 2,
> +     ComCtrl_DCD = 3,
> +     ComCtrl_DSR = 4,
> +     ComCtrl_RI = 5
> +};
> +
> +struct ipw_control_packet_body {
> +     /* ComCtrl_DTESignal or ComCtrl_DCESignal */
> +     unsigned char sig_no;
> +     /* ComCtrl_SET(0) or ComCtrl_CLEAR(1) */
> +     unsigned char value;
> +} __attribute__ ((__packed__));
> +
> +struct ipw_control_packet {
> +     struct ipw_tx_packet header;
> +     struct ipw_control_packet_body body;
> +};
> +
> +struct ipw_rx_packet {
> +     struct list_head queue;
> +     unsigned int capacity;
> +     unsigned int length;
> +     unsigned int protocol;
> +     unsigned int channel_idx;
> +};
> +
> +#ifdef IPWIRELESS_STATE_DEBUG
> +int ipwireless_dump_hardware_state(char *p, struct ipw_hardware *hw)
> +{
> +     int idx = 0;
> +
> +     idx += sprintf(p + idx, "debug: initializing=%d\n", hw->initializing);
> +     idx += sprintf(p + idx, "debug: tx_ready=%d\n", hw->tx_ready);
> +     idx += sprintf(p + idx, "debug: tx_queued=%d\n", hw->tx_queued);
> +     idx += sprintf(p + idx, "debug: rx_ready=%d\n", hw->rx_ready);
> +     idx += sprintf(p + idx, "debug: rx_bytes_queued=%d\n",
> +                     hw->rx_bytes_queued);
> +     idx += sprintf(p + idx, "debug: blocking_rx=%d\n", hw->blocking_rx);
> +     idx += sprintf(p + idx, "debug: removed=%d\n", hw->removed);
> +     idx += sprintf(p + idx, "debug: hardware.shutting_down=%d\n",
> +                     hw->shutting_down);
> +     idx += sprintf(p + idx, "debug: to_setup=%d\n",
> +                     hw->to_setup);
> +     return idx;

check for/prevent overflow of <p> ?

> +}
> +#endif
> +
> +static char *data_type(const unsigned char *buf, unsigned length)
> +{
> +     struct nl_packet_header *hdr = (struct nl_packet_header *) buf;
> +
> +     if (length == 0)
> +             return "     ";
> +
> +     if (hdr->packet_rank & NL_FIRST_PACKET) {
> +             switch (hdr->protocol) {
> +             case TL_PROTOCOLID_COM_DATA:    return "DATA ";
> +             case TL_PROTOCOLID_COM_CTRL:    return "CTRL ";
> +             case TL_PROTOCOLID_SETUP:       return "SETUP";
> +             default: return "???? ";
> +             }
> +     } else
> +             return "     ";
> +}
> +
> +#define DUMP_MAX_BYTES 64
> +
> +static void dump_data_bytes(const char *type, const unsigned char *data,
> +                         unsigned length)
> +{
> +     char prefix[56];
> +
> +     sprintf(prefix, IPWIRELESS_PCCARD_NAME ": %s %s ",
> +                     type, data_type(data, length));
> +     print_hex_dump_bytes(prefix, 0, (void *)data,
> +                     length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES);
> +}
> +
...

> +
> +/*
> + * Retrieve a packet from the IPW hardware.
> + */
> +static void do_receive_packet(struct ipw_hardware *hw)
> +{
> +     unsigned short len;
> +     unsigned int i;
> +     unsigned char pkt[LL_MTU_MAX];
> +
> +     start_timing();
> +
> +     if (hw->hw_version == HW_VERSION_1) {
> +             len = inw(hw->base_port + IODRR);
> +             if (len > hw->ll_mtu) {
> +                     printk(KERN_INFO IPWIRELESS_PCCARD_NAME
> +                            ": received a packet of %d bytes - "
> +                            "longer than the MTU!\n", (unsigned int)len);
> +                     outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR);
> +                     return;
> +             }
> +
> +             for (i = 0; i < len; i += 2) {
> +                     __le16 raw_data = inw(hw->base_port + IODRR);
> +                     unsigned short data = le16_to_cpu(raw_data);
> +
> +                     pkt[i] = (unsigned char) data;
> +                     pkt[i + 1] = (unsigned char) (data >> 8);
> +             }
> +     } else {
> +             len = inw(hw->base_port + IODMADPR);
> +             if (len > hw->ll_mtu) {
> +                     printk(KERN_INFO IPWIRELESS_PCCARD_NAME
> +                            ": received a packet of %d bytes - "
> +                            "longer than the MTU!\n", (unsigned int)len);
> +                     writew(MEMRX_PCINTACKK,
> +                             &hw->memory_info_regs->memreg_pc_interrupt_ack);
> +                     return;
> +             }
> +
> +             for (i = 0; i < len; i += 2) {
> +                     __le16 raw_data = inw(hw->base_port + IODMADPR);
> +                     unsigned short data = le16_to_cpu(raw_data);
> +
> +                     pkt[i] = (unsigned char) data;
> +                     pkt[i + 1] = (unsigned char) (data >> 8);
> +             }
> +
> +             while ((i & 3) != 2) {
> +                     inw(hw->base_port + IODMADPR);
> +                     i += 2;
> +             }
> +     }
> +
> +     acknowledge_data_read(hw);
> +
> +     if (ipwireless_debug)
> +             dump_data_bytes("recv", pkt, len);
> +
> +     handle_received_packet(hw, (union nl_packet *) pkt, len);
> +
> +     end_read_timing(len);
> +}
> +
> +static int get_current_packet_priority(struct ipw_hardware *hw)
> +{
> +     /*
> +      * If we're initializing, don't send anything of higher priority than
> +      * PRIO_SETUP.  The network layer therefore need not care about
> +      * hardware initialization - any of its stuff will simply be queued
> +      * until setup is complete.
> +      */
> +     return (hw->to_setup || hw->initializing
> +                     ? PRIO_SETUP + 1 :
> +                     NL_NUM_OF_PRIORITIES);
> +}
> +
> +/*
> + * @return 1 if something has been received from hw

What's with the '@'?

> + */
> +static int get_packets_from_hw(struct ipw_hardware *hw)
> +{
> +     int received = 0;
> +     unsigned long flags;
> +
> +     spin_lock_irqsave(&hw->spinlock, flags);
> +     while (hw->rx_ready && !hw->blocking_rx) {
> +             received = 1;
> +             hw->rx_ready--;
> +             spin_unlock_irqrestore(&hw->spinlock, flags);
> +
> +             do_receive_packet(hw);
> +
> +             spin_lock_irqsave(&hw->spinlock, flags);
> +     }
> +     spin_unlock_irqrestore(&hw->spinlock, flags);
> +
> +     return received;
> +}
> +
> +/*
> + * Send pending packet up to given priority, prioritize SETUP data until
> + * hardware is fully setup.
> + *
> + * @return 1 if more packets can be sent

ditto.

> + */
> +static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
> +{
> +     int more_to_send = 0;
> +     unsigned long flags;
> +
> +     spin_lock_irqsave(&hw->spinlock, flags);
> +     if (hw->tx_queued && hw->tx_ready != 0) {
> +             int priority;
> +             struct ipw_tx_packet *packet = NULL;
> +
> +             hw->tx_ready--;
> +
> +             /* Pick a packet */
> +             for (priority = 0; priority < priority_limit; priority++) {
> +                     if (!list_empty(&hw->tx_queue[priority])) {
> +                             packet = list_first_entry(
> +                                             &hw->tx_queue[priority],
> +                                             struct ipw_tx_packet,
> +                                             queue);
> +
> +                             list_del(&packet->queue);
> +
> +                             break;
> +                     }
> +             }
> +             if (!packet) {
> +                     hw->tx_queued = 0;
> +                     spin_unlock_irqrestore(&hw->spinlock, flags);
> +                     return 0;
> +             }
> +             spin_unlock_irqrestore(&hw->spinlock, flags);
> +
> +             /* Send */
> +             do_send_packet(hw, packet);
> +
> +             /* Check if more to send */
> +             spin_lock_irqsave(&hw->spinlock, flags);
> +             for (priority = 0; priority < priority_limit; priority++)
> +                     if (!list_empty(&hw->tx_queue[priority])) {
> +                             more_to_send = 1;
> +                             break;
> +                     }
> +
> +             if (!more_to_send)
> +                     hw->tx_queued = 0;
> +     }
> +     spin_unlock_irqrestore(&hw->spinlock, flags);
> +
> +     return more_to_send;
> +}
> +
> +/*
> + * Send and receive all queued packets.
> + */
> +static void ipwireless_do_tasklet(unsigned long hw_)
> +{
> +     struct ipw_hardware *hw = (struct ipw_hardware *) hw_;
> +     unsigned long flags;
> +
> +     spin_lock_irqsave(&hw->spinlock, flags);
> +     if (hw->shutting_down) {
> +             spin_unlock_irqrestore(&hw->spinlock, flags);
> +             return;
> +     }
> +
> +     if (hw->to_setup == 1) {
> +             /*
> +              * Initial setup data sent to hardware
> +              */
> +             hw->to_setup = 2;
> +             spin_unlock_irqrestore(&hw->spinlock, flags);
> +
> +             ipw_setup_hardware(hw);
> +             ipw_send_setup_packet(hw);
> +
> +             send_pending_packet(hw, PRIO_SETUP + 1);
> +             get_packets_from_hw(hw);
> +     } else {
> +             int priority_limit = get_current_packet_priority(hw);
> +             int again;
> +
> +             spin_unlock_irqrestore(&hw->spinlock, flags);
> +
> +             do {
> +                     again = send_pending_packet(hw, priority_limit);
> +                     again |= get_packets_from_hw(hw);
> +             } while (again);
> +     }
> +}
> +
> +/*!

and the '!' ?

> + * @return true if the card is physically present.
> + */
> +static int is_card_present(struct ipw_hardware *hw)
> +{
> +     if (hw->hw_version == HW_VERSION_1)
> +             return inw(hw->base_port + IOIR) != (unsigned short) 0xFFFF;
> +     else
> +             return readl(&hw->memory_info_regs->memreg_card_present) ==
> +                 CARD_PRESENT_VALUE;
> +}
> +
...
> +/* This handles the actual initialization of the card */
> +static void __handle_setup_get_version_rsp(struct ipw_hardware *hw)
> +{
> +     struct ipw_setup_config_packet *config_packet;
> +     struct ipw_setup_config_done_packet *config_done_packet;
> +     struct ipw_setup_open_packet *open_packet;
> +     struct ipw_setup_info_packet *info_packet;
> +     int port;
> +     unsigned int channel_idx;
> +
> +     /* generate config packet */
> +     for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
> +             config_packet = alloc_ctrl_packet(
> +                             sizeof(struct ipw_setup_config_packet),
> +                             ADDR_SETUP_PROT,
> +                             TL_PROTOCOLID_SETUP,
> +                             TL_SETUP_SIGNO_CONFIG_MSG);
> +             if (!config_packet)
> +                     goto exit_nomem;
> +             config_packet->header.length = sizeof(struct TlSetupConfigMsg);
> +             config_packet->body.port_no = port;
> +             config_packet->body.prio_data = PRIO_DATA;
> +             config_packet->body.prio_ctrl = PRIO_CTRL;
> +             send_packet(hw, PRIO_SETUP, &config_packet->header);
> +     }
> +     config_done_packet = alloc_ctrl_packet(
> +                     sizeof(struct ipw_setup_config_done_packet),
> +                     ADDR_SETUP_PROT,
> +                     TL_PROTOCOLID_SETUP,
> +                     TL_SETUP_SIGNO_CONFIG_DONE_MSG);
> +     if (!config_done_packet)
> +             goto exit_nomem;
> +     config_done_packet->header.length = sizeof(struct TlSetupConfigDoneMsg);
> +     send_packet(hw, PRIO_SETUP, &config_done_packet->header);
> +
> +     /* generate open packet */
> +     for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
> +             open_packet = alloc_ctrl_packet(
> +                             sizeof(struct ipw_setup_open_packet),
> +                             ADDR_SETUP_PROT,
> +                             TL_PROTOCOLID_SETUP,
> +                             TL_SETUP_SIGNO_OPEN_MSG);
> +             if (!open_packet)
> +                     goto exit_nomem;
> +             open_packet->header.length = sizeof(struct TlSetupOpenMsg);
> +             open_packet->body.port_no = port;
> +             send_packet(hw, PRIO_SETUP, &open_packet->header);
> +     }
> +     for (channel_idx = 0;
> +                     channel_idx < NL_NUM_OF_ADDRESSES; channel_idx++) {
> +             int ret;
> +
> +             ret = set_DTR(hw, PRIO_SETUP, channel_idx,
> +                     (hw->control_lines[channel_idx] &
> +                      IPW_CONTROL_LINE_DTR) != 0);
> +             if (ret) {
> +                     printk(KERN_ERR IPWIRELESS_PCCARD_NAME
> +                                     "error setting DTR (%d)\n", ret);
> +                     return;
> +             }
> +
> +             set_RTS(hw, PRIO_SETUP, channel_idx,
> +                     (hw->control_lines [channel_idx] &
> +                      IPW_CONTROL_LINE_RTS) != 0);
> +             if (ret) {
> +                     printk(KERN_ERR IPWIRELESS_PCCARD_NAME
> +                                     "error setting RTS (%d)\n", ret);
> +                     return;
> +             }
> +     }
> +     /*
> +      * For NDIS we assume that we are using sync PPP frames, for COM async.
> +      * This driver uses NDIS mode too. We don't bother with translation
> +      * from async -> sync PPP.
> +      */
> +     info_packet = alloc_ctrl_packet(sizeof(struct ipw_setup_info_packet),
> +                     ADDR_SETUP_PROT,
> +                     TL_PROTOCOLID_SETUP,
> +                     TL_SETUP_SIGNO_INFO_MSG);
> +     if (!info_packet)
> +             goto exit_nomem;
> +     info_packet->header.length = sizeof(struct TlSetupInfoMsg);
> +     info_packet->body.driver_type = NDISWAN_DRIVER;
> +     info_packet->body.major_version = NDISWAN_DRIVER_MAJOR_VERSION;
> +     info_packet->body.minor_version = NDISWAN_DRIVER_MINOR_VERSION;
> +     send_packet(hw, PRIO_SETUP, &info_packet->header);
> +
> +     /* Initialization is now complete, so we clear the 'to_setup' flag */
> +     hw->to_setup = 0;
> +
> +     return;
> +
> +exit_nomem:
> +     printk(KERN_ERR IPWIRELESS_PCCARD_NAME
> +                     "not enough memory to alloc control packet\n");

Need ":" and/or space between CARD_NAME and following string.
(in several places)

> +     hw->to_setup = -1;
> +}
> +
> +static void handle_setup_get_version_rsp(struct ipw_hardware *hw,
> +             unsigned char vers_no)
> +{
> +     del_timer(&hw->setup_timer);
> +     hw->initializing = 0;
> +     printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": card is ready.\n");
> +
> +     if (vers_no == TL_SETUP_VERSION)
> +             __handle_setup_get_version_rsp(hw);
> +     else
> +             printk(KERN_ERR
> +                             IPWIRELESS_PCCARD_NAME
> +                             ": invalid hardware version no %u\n",
> +                             (unsigned int) vers_no);
> +}
> +
...

> diff --git a/drivers/char/pcmcia/ipwireless/main.c 
> b/drivers/char/pcmcia/ipwireless/main.c
> new file mode 100644
> index 0000000..cab5722
> --- /dev/null
> +++ b/drivers/char/pcmcia/ipwireless/main.c
> @@ -0,0 +1,496 @@
> +/*
> + * IPWireless 3G PCMCIA Network Driver
> + *
> + * Original code
> + *   by Stephen Blackheath <[EMAIL PROTECTED]>,
> + *      Ben Martel <[EMAIL PROTECTED]>
> + *
> + * Copyrighted as follows:
> + *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
> + *
> + * Various driver changes and rewrites, port to new kernels
> + *   Copyright (C) 2006-2007 Jiri Kosina
> + *
> + * Misc code cleanups and updates
> + *   Copyright (C) 2007 David Sterba
> + */
> +
> +#include "hardware.h"
> +#include "network.h"
> +#include "main.h"
> +#include "tty.h"
> +
> +#include <linux/delay.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/sched.h>
> +#include <linux/slab.h>
> +
> +#include <pcmcia/version.h>
> +#include <pcmcia/cisreg.h>
> +#include <pcmcia/device_id.h>
> +#include <pcmcia/ss.h>
> +#include <pcmcia/ds.h>
> +#include <pcmcia/cs.h>
> +
> +static struct pcmcia_device_id ipw_ids[] = {
> +     PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
> +     PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0200),
> +     PCMCIA_DEVICE_NULL
> +};
> +MODULE_DEVICE_TABLE(pcmcia, ipw_ids);
> +
> +static void ipwireless_detach(struct pcmcia_device *link);
> +
> +/* Module params */
> +int ipwireless_debug;
> +int ipwireless_loopback;
> +int ipwireless_out_queue = 1;
> +static int major;
> +
> +module_param(major, int, 0);
> +module_param(ipwireless_debug, int, 0);
> +module_param(ipwireless_loopback, int, 0);
> +module_param(ipwireless_out_queue, int, 0);
> +MODULE_PARM_DESC(major, "ttyIPWp major number [0]");
> +MODULE_PARM_DESC(ipwireless_debug, "switch on debug messages [0]");
> +MODULE_PARM_DESC(ipwireless_debug, "switch on loopback mode [0]");
> +MODULE_PARM_DESC(ipwireless_debug, "set size of outgoing queue [1]");

Will these parameters be documented anywhere?

HERE:
> diff --git a/drivers/char/pcmcia/ipwireless/network.c 
> b/drivers/char/pcmcia/ipwireless/network.c
> new file mode 100644
> index 0000000..c16e928
> --- /dev/null
> +++ b/drivers/char/pcmcia/ipwireless/network.c
> @@ -0,0 +1,513 @@
> +/*
> + * IPWireless 3G PCMCIA Network Driver
> + *
> + * Original code
> + *   by Stephen Blackheath <[EMAIL PROTECTED]>,
> + *      Ben Martel <[EMAIL PROTECTED]>
> + *
> + * Copyrighted as follows:
> + *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
> + *
> + * Various driver changes and rewrites, port to new kernels
> + *   Copyright (C) 2006-2007 Jiri Kosina
> + *
> + * Misc code cleanups and updates
> + *   Copyright (C) 2007 David Sterba
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/kernel.h>
> +#include <linux/mutex.h>
> +#include <linux/netdevice.h>
> +#include <linux/ppp_channel.h>
> +#include <linux/ppp_defs.h>
> +#include <linux/if_ppp.h>
> +#include <linux/skbuff.h>
> +
> +#include "network.h"
> +#include "hardware.h"
> +#include "main.h"
> +#include "tty.h"
> +
> +struct ipw_network {
> +     /* Hardware context, used for calls to hardware layer. */
> +     struct ipw_hardware *hardware;
> +     /* Context for kernel 'generic_ppp' functionality */
> +     struct ppp_channel *ppp_channel;
> +     /* tty context connected with IPW console */
> +     struct ipw_tty 
> *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS];
> +     /* True if ppp needs waking up once we're ready to xmit */
> +     int ppp_blocked;
> +     /* Number of packets queued up in hardware module. */
> +     int outgoing_packets_queued;
> +     /* Spinlock to avoid interrupts during shutdown */
> +     spinlock_t spinlock;
> +     struct mutex close_lock;
> +
> +     /* PPP ioctl data, not actually used anywere */
> +     unsigned int flags;
> +     unsigned int rbits;
> +     u32 xaccm[8];
> +     u32 raccm;
> +     int mru;
> +
> +     int shutting_down;
> +     unsigned int ras_control_lines;
> +
> +     struct work_struct work_go_online;
> +     struct work_struct work_go_offline;
> +};
> +
> +
> +#ifdef IPWIRELESS_STATE_DEBUG
> +int ipwireless_dump_network_state(char *p, struct ipw_network *network)
> +{
> +     int idx = 0;
> +
> +     idx += sprintf(p + idx, "debug: ppp_blocked=%d\n",
> +                     network->ppp_blocked);
> +     idx += sprintf(p + idx, "debug: outgoing_packets_queued=%d\n",
> +                     network->outgoing_packets_queued);
> +     idx += sprintf(p + idx, "debug: network.shutting_down=%d\n",
> +                     network->shutting_down);

check for overflow of 'p'?

> +     return idx;
> +}
> +#endif
> +


> diff --git a/drivers/char/pcmcia/ipwireless/setup_protocol.h 
> b/drivers/char/pcmcia/ipwireless/setup_protocol.h
> new file mode 100644
> index 0000000..46f2c57
> --- /dev/null
> +++ b/drivers/char/pcmcia/ipwireless/setup_protocol.h
> @@ -0,0 +1,108 @@
> +/*
> + * IPWireless 3G PCMCIA Network Driver
> + *
> + * Original code
> + *   by Stephen Blackheath <[EMAIL PROTECTED]>,
> + *      Ben Martel <[EMAIL PROTECTED]>
> + *
> + * Copyrighted as follows:
> + *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
> + *
> + * Various driver changes and rewrites, port to new kernels
> + *   Copyright (C) 2006-2007 Jiri Kosina
> + *
> + * Misc code cleanups and updates
> + *   Copyright (C) 2007 David Sterba
> + */
> +
> +#ifndef _IPWIRELESS_CS_SETUP_PROTOCOL_H_
> +#define _IPWIRELESS_CS_SETUP_PROTOCOL_H_
> +
> +/* Version of the setup protocol and transport protocols */
> +#define TL_SETUP_VERSION             1
> +
> +#define TL_SETUP_VERSION_QRY_TMO     1000
> +#define TL_SETUP_MAX_VERSION_QRY     30
> +
> +/* Message numbers 0-9 are obsoleted and must not be reused! */
> +#define TL_SETUP_SIGNO_GET_VERSION_QRY       10
> +#define TL_SETUP_SIGNO_GET_VERSION_RSP       11
> +#define TL_SETUP_SIGNO_CONFIG_MSG    12
> +#define TL_SETUP_SIGNO_CONFIG_DONE_MSG       13
> +#define TL_SETUP_SIGNO_OPEN_MSG              14
> +#define TL_SETUP_SIGNO_CLOSE_MSG     15
> +
> +#define TL_SETUP_SIGNO_INFO_MSG     20
> +#define TL_SETUP_SIGNO_INFO_MSG_ACK 21
> +
> +#define TL_SETUP_SIGNO_REBOOT_MSG      22
> +#define TL_SETUP_SIGNO_REBOOT_MSG_ACK  23
> +
> +/* Syncronous start-messages */

        Synchronous

> +struct TlSetupGetVersionQry {
> +     unsigned char sig_no;           /* TL_SETUP_SIGNO_GET_VERSION_QRY */
> +} __attribute__ ((__packed__));
> +

---
~Randy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to