tty/serial: lay the foundations for the next set of reworks
[linux-2.6-block.git] / drivers / char / rocket.c
index 68c289fe2dc2c67ef49e4541ba22278f94a15f94..00cfb6c7fd4698b019188cfefb46ec457667a0bd 100644 (file)
@@ -83,6 +83,7 @@
 #include <linux/pci.h>
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
+#include <asm/unaligned.h>
 #include <linux/bitops.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
@@ -448,7 +449,8 @@ static void rp_do_transmit(struct r_port *info)
        while (1) {
                if (tty->stopped || tty->hw_stopped)
                        break;
-               c = min(info->xmit_fifo_room, min(info->xmit_cnt, XMIT_BUF_SIZE - info->xmit_tail));
+               c = min(info->xmit_fifo_room, info->xmit_cnt);
+               c = min(c, XMIT_BUF_SIZE - info->xmit_tail);
                if (c <= 0 || info->xmit_fifo_room <= 0)
                        break;
                sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
@@ -715,11 +717,10 @@ static void configure_r_port(struct r_port *info,
        unsigned rocketMode;
        int bits, baud, divisor;
        CHANNEL_t *cp;
+       struct ktermios *t = info->tty->termios;
 
-       if (!info->tty || !info->tty->termios)
-               return;
        cp = &info->channel;
-       cflag = info->tty->termios->c_cflag;
+       cflag = t->c_cflag;
 
        /* Byte size and parity */
        if ((cflag & CSIZE) == CS8) {
@@ -754,10 +755,7 @@ static void configure_r_port(struct r_port *info,
                baud = 9600;
        divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1;
        if ((divisor >= 8192 || divisor < 0) && old_termios) {
-               info->tty->termios->c_cflag &= ~CBAUD;
-               info->tty->termios->c_cflag |=
-                   (old_termios->c_cflag & CBAUD);
-               baud = tty_get_baud_rate(info->tty);
+               baud = tty_termios_baud_rate(old_termios);
                if (!baud)
                        baud = 9600;
                divisor = (rp_baud_base[info->board] / baud) - 1;
@@ -769,6 +767,9 @@ static void configure_r_port(struct r_port *info,
        info->cps = baud / bits;
        sSetBaud(cp, divisor);
 
+       /* FIXME: Should really back compute a baud rate from the divisor */
+       tty_encode_baud_rate(info->tty, baud, baud);
+
        if (cflag & CRTSCTS) {
                info->intmask |= DELTA_CTS;
                sEnCTSFlowCtl(cp);
@@ -1202,15 +1203,14 @@ static void rp_set_termios(struct tty_struct *tty,
 
        cflag = tty->termios->c_cflag;
 
-       if (cflag == old_termios->c_cflag)
-               return;
-
        /*
         * This driver doesn't support CS5 or CS6
         */
        if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
                tty->termios->c_cflag =
                    ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
+       /* Or CMSPAR */
+       tty->termios->c_cflag &= ~CMSPAR;
 
        configure_r_port(info, old_termios);
 
@@ -1314,7 +1314,7 @@ static int rp_tiocmset(struct tty_struct *tty, struct file *file,
        if (clear & TIOCM_DTR)
                info->channel.TxControl[3] &= ~SET_DTR;
 
-       sOutDW(info->channel.IndexAddr, *(DWord_t *) & (info->channel.TxControl[0]));
+       out32(info->channel.IndexAddr, info->channel.TxControl);
        return 0;
 }
 
@@ -1401,6 +1401,9 @@ static int reset_rm2(struct r_port *info, void __user *arg)
 {
        int reset;
 
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
        if (copy_from_user(&reset, arg, sizeof (int)))
                return -EFAULT;
        if (reset)
@@ -1431,29 +1434,38 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file,
 {
        struct r_port *info = (struct r_port *) tty->driver_data;
        void __user *argp = (void __user *)arg;
+       int ret = 0;
 
        if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
                return -ENXIO;
 
+       lock_kernel();
+
        switch (cmd) {
        case RCKP_GET_STRUCT:
                if (copy_to_user(argp, info, sizeof (struct r_port)))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               break;
        case RCKP_GET_CONFIG:
-               return get_config(info, argp);
+               ret = get_config(info, argp);
+               break;
        case RCKP_SET_CONFIG:
-               return set_config(info, argp);
+               ret = set_config(info, argp);
+               break;
        case RCKP_GET_PORTS:
-               return get_ports(info, argp);
+               ret = get_ports(info, argp);
+               break;
        case RCKP_RESET_RM2:
-               return reset_rm2(info, argp);
+               ret = reset_rm2(info, argp);
+               break;
        case RCKP_GET_VERSION:
-               return get_version(info, argp);
+               ret = get_version(info, argp);
+               break;
        default:
-               return -ENOIOCTLCMD;
+               ret = -ENOIOCTLCMD;
        }
-       return 0;
+       unlock_kernel();
+       return ret;
 }
 
 static void rp_send_xchar(struct tty_struct *tty, char ch)
@@ -1573,6 +1585,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
               jiffies);
        printk(KERN_INFO "cps=%d...\n", info->cps);
 #endif
+       lock_kernel();
        while (1) {
                txcnt = sGetTxCnt(cp);
                if (!txcnt) {
@@ -1600,6 +1613,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
                        break;
        }
        __set_current_state(TASK_RUNNING);
+       unlock_kernel();
 #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
        printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
 #endif
@@ -1747,10 +1761,10 @@ static int rp_write(struct tty_struct *tty,
 
        /*  Write remaining data into the port's xmit_buf */
        while (1) {
-               if (info->tty == 0)     /*   Seemingly obligatory check... */
+               if (!info->tty)         /* Seemingly obligatory check... */
                        goto end;
-
-               c = min(count, min(XMIT_BUF_SIZE - info->xmit_cnt - 1, XMIT_BUF_SIZE - info->xmit_head));
+               c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1);
+               c = min(c, XMIT_BUF_SIZE - info->xmit_head);
                if (c <= 0)
                        break;
 
@@ -2797,7 +2811,7 @@ static int sReadAiopNumChan(WordIO_t io)
        static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
 
        /* write to chan 0 SRAM */
-       sOutDW((DWordIO_t) io + _INDX_ADDR, *((DWord_t *) & R[0]));
+       out32((DWordIO_t) io + _INDX_ADDR, R);
        sOutW(io + _INDX_ADDR, 0);      /* read from SRAM, chan 0 */
        x = sInW(io + _INDX_DATA);
        sOutW(io + _INDX_ADDR, 0x4000); /* read from SRAM, chan 4 */
@@ -2863,7 +2877,7 @@ static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
                R[1] = RData[i + 1] + 0x10 * ChanNum;
                R[2] = RData[i + 2];
                R[3] = RData[i + 3];
-               sOutDW(ChP->IndexAddr, *((DWord_t *) & R[0]));
+               out32(ChP->IndexAddr, R);
        }
 
        ChR = ChP->R;
@@ -2886,43 +2900,43 @@ static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
        ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8);
        ChP->BaudDiv[2] = (Byte_t) brd9600;
        ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8);
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->BaudDiv[0]);
+       out32(ChP->IndexAddr, ChP->BaudDiv);
 
        ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL);
        ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8);
        ChP->TxControl[2] = 0;
        ChP->TxControl[3] = 0;
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
+       out32(ChP->IndexAddr, ChP->TxControl);
 
        ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL);
        ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8);
        ChP->RxControl[2] = 0;
        ChP->RxControl[3] = 0;
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
+       out32(ChP->IndexAddr, ChP->RxControl);
 
        ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS);
        ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8);
        ChP->TxEnables[2] = 0;
        ChP->TxEnables[3] = 0;
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxEnables[0]);
+       out32(ChP->IndexAddr, ChP->TxEnables);
 
        ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1);
        ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8);
        ChP->TxCompare[2] = 0;
        ChP->TxCompare[3] = 0;
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxCompare[0]);
+       out32(ChP->IndexAddr, ChP->TxCompare);
 
        ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1);
        ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8);
        ChP->TxReplace1[2] = 0;
        ChP->TxReplace1[3] = 0;
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace1[0]);
+       out32(ChP->IndexAddr, ChP->TxReplace1);
 
        ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2);
        ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8);
        ChP->TxReplace2[2] = 0;
        ChP->TxReplace2[3] = 0;
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxReplace2[0]);
+       out32(ChP->IndexAddr, ChP->TxReplace2);
 
        ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
        ChP->TxFIFO = ChOff + _TX_FIFO;
@@ -2978,7 +2992,7 @@ static void sStopRxProcessor(CHANNEL_T * ChP)
        R[1] = ChP->R[1];
        R[2] = 0x0a;
        R[3] = ChP->R[3];
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & R[0]);
+       out32(ChP->IndexAddr, R);
 }
 
 /***************************************************************************
@@ -3093,13 +3107,13 @@ static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
                *WordPtr = ChP->TxPrioBuf;      /* data byte address */
 
                DWBuf[2] = Data;        /* data byte value */
-               sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0])));  /* write it out */
+               out32(IndexAddr, DWBuf);        /* write it out */
 
                *WordPtr = ChP->TxPrioCnt;      /* Tx priority count address */
 
                DWBuf[2] = PRI_PEND + 1;        /* indicate 1 byte pending */
                DWBuf[3] = 0;   /* priority buffer pointer */
-               sOutDW(IndexAddr, *((DWord_t *) (&DWBuf[0])));  /* write it out */
+               out32(IndexAddr, DWBuf);        /* write it out */
        } else {                /* write it to Tx FIFO */
 
                sWriteTxByte(sGetTxRxDataIO(ChP), Data);
@@ -3146,11 +3160,11 @@ static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
        ChP->RxControl[2] |=
            ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
 
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
+       out32(ChP->IndexAddr, ChP->RxControl);
 
        ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN);
 
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
+       out32(ChP->IndexAddr, ChP->TxControl);
 
        if (Flags & CHANINT_EN) {
                Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
@@ -3189,9 +3203,9 @@ static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
 
        ChP->RxControl[2] &=
            ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->RxControl[0]);
+       out32(ChP->IndexAddr, ChP->RxControl);
        ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN);
-       sOutDW(ChP->IndexAddr, *(DWord_t *) & ChP->TxControl[0]);
+       out32(ChP->IndexAddr, ChP->TxControl);
 
        if (Flags & CHANINT_EN) {
                Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];