[PATCH] const struct tty_operations
[linux-2.6-block.git] / drivers / char / synclink_gt.c
index 03edccc8a82338cac5b5ba6b7b8e7d0b3c115fd2..bdc7cb248b8f1818db19b0bbb09ae46904f8cd06 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.
  *
  * 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,},
@@ -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);
@@ -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) {
@@ -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);
@@ -2356,10 +2366,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 +2567,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);
@@ -3343,7 +3356,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 */
        }
@@ -3428,7 +3441,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,
@@ -3742,7 +3755,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;
        }
 
@@ -3769,13 +3782,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);
                        }
@@ -3808,7 +3826,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);
 
@@ -3976,7 +3993,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;
 
@@ -3986,7 +4003,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
@@ -4000,8 +4017,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;
 
@@ -4052,7 +4072,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
@@ -4063,8 +4083,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)
        {
@@ -4303,10 +4326,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;
@@ -4471,13 +4499,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;
 }
@@ -4543,8 +4582,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);