WorkStruct: make allyesconfig
[safe/jmp/linux-2.6] / drivers / char / synclink_gt.c
index 03a7f20..07f34d4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: synclink_gt.c,v 4.25 2006/02/06 21:20:33 paulkf Exp $
+ * $Id: synclink_gt.c,v 4.36 2006/08/28 20:47:14 paulkf Exp $
  *
  * Device driver for Microgate SyncLink GT serial adapters.
  *
@@ -46,7 +46,6 @@
 //#define DBGRBUF(info) dump_rbufs(info)
 
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/errno.h>
  * module identification
  */
 static char *driver_name     = "SyncLink GT";
-static char *driver_version  = "$Revision: 4.25 $";
+static char *driver_version  = "$Revision: 4.36 $";
 static char *tty_driver_name = "synclink_gt";
 static char *tty_dev_prefix  = "ttySLG";
 MODULE_LICENSE("GPL");
 #define MGSL_MAGIC 0x5401
-#define MAX_DEVICES 12
+#define MAX_DEVICES 32
 
 static struct pci_device_id pci_table[] = {
        {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT2_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {0,}, /* terminate list */
@@ -391,8 +391,8 @@ static MGSL_PARAMS default_params = {
 #define DESC_LIST_SIZE 4096
 
 #define MASK_PARITY  BIT1
-#define MASK_FRAMING BIT2
-#define MASK_BREAK   BIT3
+#define MASK_FRAMING BIT0
+#define MASK_BREAK   BIT14
 #define MASK_OVERRUN BIT4
 
 #define GSR   0x00 /* global status */
@@ -461,7 +461,7 @@ static int  adapter_test(struct slgt_info *info);
 static void reset_adapter(struct slgt_info *info);
 static void reset_port(struct slgt_info *info);
 static void async_mode(struct slgt_info *info);
-static void hdlc_mode(struct slgt_info *info);
+static void sync_mode(struct slgt_info *info);
 
 static void rx_stop(struct slgt_info *info);
 static void rx_start(struct slgt_info *info);
@@ -485,13 +485,13 @@ static void enable_loopback(struct slgt_info *info);
 static void set_rate(struct slgt_info *info, u32 data_rate);
 
 static int  bh_action(struct slgt_info *info);
-static void bh_handler(void* context);
+static void bh_handler(struct work_struct *work);
 static void bh_transmit(struct slgt_info *info);
 static void isr_serial(struct slgt_info *info);
 static void isr_rdma(struct slgt_info *info);
 static void isr_txeom(struct slgt_info *info, unsigned short status);
 static void isr_tdma(struct slgt_info *info);
-static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t slgt_interrupt(int irq, void *dev_id);
 
 static int  alloc_dma_bufs(struct slgt_info *info);
 static void free_dma_bufs(struct slgt_info *info);
@@ -881,7 +881,9 @@ static int write(struct tty_struct *tty,
        if (!count)
                goto cleanup;
 
-       if (info->params.mode == MGSL_MODE_RAW) {
+       if (info->params.mode == MGSL_MODE_RAW ||
+           info->params.mode == MGSL_MODE_MONOSYNC ||
+           info->params.mode == MGSL_MODE_BISYNC) {
                unsigned int bufs_needed = (count/DMABUFSIZE);
                unsigned int bufs_free = free_tbuf_count(info);
                if (count % DMABUFSIZE)
@@ -1497,8 +1499,10 @@ static int hdlcdev_open(struct net_device *dev)
        spin_lock_irqsave(&info->lock, flags);
        get_signals(info);
        spin_unlock_irqrestore(&info->lock, flags);
-       hdlc_set_carrier(info->signals & SerialSignal_DCD, dev);
-
+       if (info->signals & SerialSignal_DCD)
+               netif_carrier_on(dev);
+       else
+               netif_carrier_off(dev);
        return 0;
 }
 
@@ -1798,17 +1802,17 @@ static void rx_async(struct slgt_info *info)
 
                        stat = 0;
 
-                       if ((status = *(p+1) & (BIT9 + BIT8))) {
-                               if (status & BIT9)
+                       if ((status = *(p+1) & (BIT1 + BIT0))) {
+                               if (status & BIT1)
                                        icount->parity++;
-                               else if (status & BIT8)
+                               else if (status & BIT0)
                                        icount->frame++;
                                /* discard char if tty control flags say so */
                                if (status & info->ignore_status_mask)
                                        continue;
-                               if (status & BIT9)
+                               if (status & BIT1)
                                        stat = TTY_PARITY;
-                               else if (status & BIT8)
+                               else if (status & BIT0)
                                        stat = TTY_FRAME;
                        }
                        if (tty) {
@@ -1874,9 +1878,9 @@ static int bh_action(struct slgt_info *info)
 /*
  * perform bottom half processing
  */
-static void bh_handler(void* context)
+static void bh_handler(struct work_struct *work)
 {
-       struct slgt_info *info = context;
+       struct slgt_info *info = container_of(work, struct slgt_info, task);
        int action;
 
        if (!info)
@@ -1895,6 +1899,8 @@ static void bh_handler(void* context)
                                while(rx_get_frame(info));
                                break;
                        case MGSL_MODE_RAW:
+                       case MGSL_MODE_MONOSYNC:
+                       case MGSL_MODE_BISYNC:
                                while(rx_get_buf(info));
                                break;
                        }
@@ -1997,8 +2003,12 @@ static void dcd_change(struct slgt_info *info)
                info->input_signal_events.dcd_down++;
        }
 #ifdef CONFIG_HDLC
-       if (info->netcount)
-               hdlc_set_carrier(info->signals & SerialSignal_DCD, info->netdev);
+       if (info->netcount) {
+               if (info->signals & SerialSignal_DCD)
+                       netif_carrier_on(info->netdev);
+               else
+                       netif_carrier_off(info->netdev);
+       }
 #endif
        wake_up_interruptible(&info->status_event_wait_q);
        wake_up_interruptible(&info->event_wait_q);
@@ -2207,9 +2217,8 @@ static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int
  *
  *     irq     interrupt number
  *     dev_id  device ID supplied during interrupt registration
- *     regs    interrupted processor context
  */
-static irqreturn_t slgt_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+static irqreturn_t slgt_interrupt(int irq, void *dev_id)
 {
        struct slgt_info *info;
        unsigned int gsr;
@@ -2356,10 +2365,9 @@ static void program_hw(struct slgt_info *info)
        rx_stop(info);
        tx_stop(info);
 
-       if (info->params.mode == MGSL_MODE_HDLC ||
-           info->params.mode == MGSL_MODE_RAW ||
+       if (info->params.mode != MGSL_MODE_ASYNC ||
            info->netcount)
-               hdlc_mode(info);
+               sync_mode(info);
        else
                async_mode(info);
 
@@ -2558,6 +2566,10 @@ static int rx_enable(struct slgt_info *info, int enable)
        if (enable) {
                if (!info->rx_enabled)
                        rx_start(info);
+               else if (enable == 2) {
+                       /* force hunt mode (write 1 to RCR[3]) */
+                       wr_reg16(info, RCR, rd_reg16(info, RCR) | BIT3);
+               }
        } else {
                if (info->rx_enabled)
                        rx_stop(info);
@@ -3277,6 +3289,9 @@ static void add_device(struct slgt_info *info)
        case SYNCLINK_GT_DEVICE_ID:
                devstr = "GT";
                break;
+       case SYNCLINK_GT2_DEVICE_ID:
+               devstr = "GT2";
+               break;
        case SYNCLINK_GT4_DEVICE_ID:
                devstr = "GT4";
                break;
@@ -3311,7 +3326,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
        } else {
                memset(info, 0, sizeof(struct slgt_info));
                info->magic = MGSL_MAGIC;
-               INIT_WORK(&info->task, bh_handler, info);
+               INIT_WORK(&info->task, bh_handler);
                info->max_frame_size = 4096;
                info->raw_rx_size = DMABUFSIZE;
                info->close_delay = 5*HZ/10;
@@ -3340,7 +3355,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
                info->phys_reg_addr = pci_resource_start(pdev,0);
 
                info->bus_type = MGSL_BUS_TYPE_PCI;
-               info->irq_flags = SA_SHIRQ;
+               info->irq_flags = IRQF_SHARED;
 
                info->init_error = -1; /* assume error, set to 0 on successful init */
        }
@@ -3354,7 +3369,9 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
        int i;
        int port_count = 1;
 
-       if (pdev->device == SYNCLINK_GT4_DEVICE_ID)
+       if (pdev->device == SYNCLINK_GT2_DEVICE_ID)
+               port_count = 2;
+       else if (pdev->device == SYNCLINK_GT4_DEVICE_ID)
                port_count = 4;
 
        /* allocate device instances for all ports */
@@ -3423,7 +3440,7 @@ static void __devexit remove_one(struct pci_dev *dev)
 {
 }
 
-static struct tty_operations ops = {
+static const struct tty_operations ops = {
        .open = open,
        .close = close,
        .write = write,
@@ -3737,7 +3754,7 @@ static void tx_start(struct slgt_info *info)
 {
        if (!info->tx_enabled) {
                wr_reg16(info, TCR,
-                       (unsigned short)(rd_reg16(info, TCR) | BIT1));
+                        (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2));
                info->tx_enabled = TRUE;
        }
 
@@ -3764,13 +3781,18 @@ static void tx_start(struct slgt_info *info)
                                tdma_reset(info);
                                /* set 1st descriptor address */
                                wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc);
-                               if (info->params.mode == MGSL_MODE_RAW)
+                               switch(info->params.mode) {
+                               case MGSL_MODE_RAW:
+                               case MGSL_MODE_MONOSYNC:
+                               case MGSL_MODE_BISYNC:
                                        wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */
-                               else
+                                       break;
+                               default:
                                        wr_reg32(info, TDCSR, BIT0); /* DMA enable */
+                               }
                        }
 
-                       if (info->params.mode != MGSL_MODE_RAW) {
+                       if (info->params.mode == MGSL_MODE_HDLC) {
                                info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
                                add_timer(&info->tx_timer);
                        }
@@ -3803,7 +3825,6 @@ static void tx_stop(struct slgt_info *info)
        /* reset and disable transmitter */
        val = rd_reg16(info, TCR) & ~BIT1;          /* clear enable bit */
        wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
-       wr_reg16(info, TCR, val);                  /* clear reset */
 
        slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
 
@@ -3971,7 +3992,7 @@ static void async_mode(struct slgt_info *info)
                enable_loopback(info);
 }
 
-static void hdlc_mode(struct slgt_info *info)
+static void sync_mode(struct slgt_info *info)
 {
        unsigned short val;
 
@@ -3981,7 +4002,7 @@ static void hdlc_mode(struct slgt_info *info)
 
        /* TCR (tx control)
         *
-        * 15..13  mode, 000=HDLC 001=raw sync
+        * 15..13  mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync
         * 12..10  encoding
         * 09      CRC enable
         * 08      CRC32
@@ -3995,8 +4016,11 @@ static void hdlc_mode(struct slgt_info *info)
         */
        val = 0;
 
-       if (info->params.mode == MGSL_MODE_RAW)
-               val |= BIT13;
+       switch(info->params.mode) {
+       case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
+       case MGSL_MODE_BISYNC:   val |= BIT15; break;
+       case MGSL_MODE_RAW:      val |= BIT13; break;
+       }
        if (info->if_mode & MGSL_INTERFACE_RTS_EN)
                val |= BIT7;
 
@@ -4047,7 +4071,7 @@ static void hdlc_mode(struct slgt_info *info)
 
        /* RCR (rx control)
         *
-        * 15..13  mode, 000=HDLC 001=raw sync
+        * 15..13  mode, 000=HDLC 001=raw 010=async 011=monosync 100=bisync
         * 12..10  encoding
         * 09      CRC enable
         * 08      CRC32
@@ -4058,8 +4082,11 @@ static void hdlc_mode(struct slgt_info *info)
         */
        val = 0;
 
-       if (info->params.mode == MGSL_MODE_RAW)
-               val |= BIT13;
+       switch(info->params.mode) {
+       case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
+       case MGSL_MODE_BISYNC:   val |= BIT15; break;
+       case MGSL_MODE_RAW:      val |= BIT13; break;
+       }
 
        switch(info->params.encoding)
        {
@@ -4298,10 +4325,15 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last
        while(!done) {
                /* reset current buffer for reuse */
                info->rbufs[i].status = 0;
-               if (info->params.mode == MGSL_MODE_RAW)
+               switch(info->params.mode) {
+               case MGSL_MODE_RAW:
+               case MGSL_MODE_MONOSYNC:
+               case MGSL_MODE_BISYNC:
                        set_desc_count(info->rbufs[i], info->raw_rx_size);
-               else
+                       break;
+               default:
                        set_desc_count(info->rbufs[i], DMABUFSIZE);
+               }
 
                if (i == last)
                        done = 1;
@@ -4466,13 +4498,24 @@ cleanup:
 static int rx_get_buf(struct slgt_info *info)
 {
        unsigned int i = info->rbuf_current;
+       unsigned int count;
 
        if (!desc_complete(info->rbufs[i]))
                return 0;
-       DBGDATA(info, info->rbufs[i].buf, desc_count(info->rbufs[i]), "rx");
-       DBGINFO(("rx_get_buf size=%d\n", desc_count(info->rbufs[i])));
-       ldisc_receive_buf(info->tty, info->rbufs[i].buf,
-                         info->flag_buf, desc_count(info->rbufs[i]));
+       count = desc_count(info->rbufs[i]);
+       switch(info->params.mode) {
+       case MGSL_MODE_MONOSYNC:
+       case MGSL_MODE_BISYNC:
+               /* ignore residue in byte synchronous modes */
+               if (desc_residue(info->rbufs[i]))
+                       count--;
+               break;
+       }
+       DBGDATA(info, info->rbufs[i].buf, count, "rx");
+       DBGINFO(("rx_get_buf size=%d\n", count));
+       if (count)
+               ldisc_receive_buf(info->tty, info->rbufs[i].buf,
+                                 info->flag_buf, count);
        free_rbufs(info, i, i);
        return 1;
 }
@@ -4538,8 +4581,13 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size)
                size -= count;
                buf  += count;
 
-               if (!size && info->params.mode != MGSL_MODE_RAW)
-                       set_desc_eof(*d, 1); /* HDLC: set EOF of last desc */
+               /*
+                * set EOF bit for last buffer of HDLC frame or
+                * for every buffer in raw mode
+                */
+               if ((!size && info->params.mode == MGSL_MODE_HDLC) ||
+                   info->params.mode == MGSL_MODE_RAW)
+                       set_desc_eof(*d, 1);
                else
                        set_desc_eof(*d, 0);
 
@@ -4702,13 +4750,13 @@ static int loopback_test(struct slgt_info *info)
 static int adapter_test(struct slgt_info *info)
 {
        DBGINFO(("testing %s\n", info->device_name));
-       if ((info->init_error = register_test(info)) < 0) {
+       if (register_test(info) < 0) {
                printk("register test failure %s addr=%08X\n",
                        info->device_name, info->phys_reg_addr);
-       } else if ((info->init_error = irq_test(info)) < 0) {
+       } else if (irq_test(info) < 0) {
                printk("IRQ test failure %s IRQ=%d\n",
                        info->device_name, info->irq_level);
-       } else if ((info->init_error = loopback_test(info)) < 0) {
+       } else if (loopback_test(info) < 0) {
                printk("loopback test failure %s\n", info->device_name);
        }
        return info->init_error;
@@ -4751,6 +4799,6 @@ static void rx_timeout(unsigned long context)
        spin_lock_irqsave(&info->lock, flags);
        info->pending_bh |= BH_RECEIVE;
        spin_unlock_irqrestore(&info->lock, flags);
-       bh_handler(info);
+       bh_handler(&info->task);
 }