linux/drivers/char/vme_scc.c
<<
>>
Prefs
   1/*
   2 * drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports
   3 * implementation.
   4 * Copyright 1999 Richard Hirst <richard@sleepie.demon.co.uk>
   5 *
   6 * Based on atari_SCC.c which was
   7 *   Copyright 1994-95 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
   8 *   Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o
   9 *
  10 * This file is subject to the terms and conditions of the GNU General Public
  11 * License.  See the file COPYING in the main directory of this archive
  12 * for more details.
  13 *
  14 */
  15
  16#include <linux/module.h>
  17#include <linux/kdev_t.h>
  18#include <asm/io.h>
  19#include <linux/kernel.h>
  20#include <linux/ioport.h>
  21#include <linux/interrupt.h>
  22#include <linux/errno.h>
  23#include <linux/tty.h>
  24#include <linux/tty_flip.h>
  25#include <linux/mm.h>
  26#include <linux/serial.h>
  27#include <linux/fcntl.h>
  28#include <linux/major.h>
  29#include <linux/delay.h>
  30#include <linux/slab.h>
  31#include <linux/miscdevice.h>
  32#include <linux/console.h>
  33#include <linux/init.h>
  34#include <asm/setup.h>
  35#include <asm/bootinfo.h>
  36
  37#ifdef CONFIG_MVME147_SCC
  38#include <asm/mvme147hw.h>
  39#endif
  40#ifdef CONFIG_MVME162_SCC
  41#include <asm/mvme16xhw.h>
  42#endif
  43#ifdef CONFIG_BVME6000_SCC
  44#include <asm/bvme6000hw.h>
  45#endif
  46
  47#include <linux/generic_serial.h>
  48#include "scc.h"
  49
  50
  51#define CHANNEL_A       0
  52#define CHANNEL_B       1
  53
  54#define SCC_MINOR_BASE  64
  55
  56/* Shadows for all SCC write registers */
  57static unsigned char scc_shadow[2][16];
  58
  59/* Location to access for SCC register access delay */
  60static volatile unsigned char *scc_del = NULL;
  61
  62/* To keep track of STATUS_REG state for detection of Ext/Status int source */
  63static unsigned char scc_last_status_reg[2];
  64
  65/***************************** Prototypes *****************************/
  66
  67/* Function prototypes */
  68static void scc_disable_tx_interrupts(void * ptr);
  69static void scc_enable_tx_interrupts(void * ptr);
  70static void scc_disable_rx_interrupts(void * ptr);
  71static void scc_enable_rx_interrupts(void * ptr);
  72static int  scc_carrier_raised(struct tty_port *port);
  73static void scc_shutdown_port(void * ptr);
  74static int scc_set_real_termios(void  *ptr);
  75static void scc_hungup(void  *ptr);
  76static void scc_close(void  *ptr);
  77static int scc_chars_in_buffer(void * ptr);
  78static int scc_open(struct tty_struct * tty, struct file * filp);
  79static int scc_ioctl(struct tty_struct * tty, struct file * filp,
  80                     unsigned int cmd, unsigned long arg);
  81static void scc_throttle(struct tty_struct *tty);
  82static void scc_unthrottle(struct tty_struct *tty);
  83static irqreturn_t scc_tx_int(int irq, void *data);
  84static irqreturn_t scc_rx_int(int irq, void *data);
  85static irqreturn_t scc_stat_int(int irq, void *data);
  86static irqreturn_t scc_spcond_int(int irq, void *data);
  87static void scc_setsignals(struct scc_port *port, int dtr, int rts);
  88static int scc_break_ctl(struct tty_struct *tty, int break_state);
  89
  90static struct tty_driver *scc_driver;
  91
  92static struct scc_port scc_ports[2];
  93
  94/*---------------------------------------------------------------------------
  95 * Interface from generic_serial.c back here
  96 *--------------------------------------------------------------------------*/
  97
  98static struct real_driver scc_real_driver = {
  99        scc_disable_tx_interrupts,
 100        scc_enable_tx_interrupts,
 101        scc_disable_rx_interrupts,
 102        scc_enable_rx_interrupts,
 103        scc_shutdown_port,
 104        scc_set_real_termios,
 105        scc_chars_in_buffer,
 106        scc_close,
 107        scc_hungup,
 108        NULL
 109};
 110
 111
 112static const struct tty_operations scc_ops = {
 113        .open   = scc_open,
 114        .close = gs_close,
 115        .write = gs_write,
 116        .put_char = gs_put_char,
 117        .flush_chars = gs_flush_chars,
 118        .write_room = gs_write_room,
 119        .chars_in_buffer = gs_chars_in_buffer,
 120        .flush_buffer = gs_flush_buffer,
 121        .ioctl = scc_ioctl,
 122        .throttle = scc_throttle,
 123        .unthrottle = scc_unthrottle,
 124        .set_termios = gs_set_termios,
 125        .stop = gs_stop,
 126        .start = gs_start,
 127        .hangup = gs_hangup,
 128        .break_ctl = scc_break_ctl,
 129};
 130
 131static const struct tty_port_operations scc_port_ops = {
 132        .carrier_raised = scc_carrier_raised,
 133};
 134
 135/*----------------------------------------------------------------------------
 136 * vme_scc_init() and support functions
 137 *---------------------------------------------------------------------------*/
 138
 139static int scc_init_drivers(void)
 140{
 141        int error;
 142
 143        scc_driver = alloc_tty_driver(2);
 144        if (!scc_driver)
 145                return -ENOMEM;
 146        scc_driver->owner = THIS_MODULE;
 147        scc_driver->driver_name = "scc";
 148        scc_driver->name = "ttyS";
 149        scc_driver->major = TTY_MAJOR;
 150        scc_driver->minor_start = SCC_MINOR_BASE;
 151        scc_driver->type = TTY_DRIVER_TYPE_SERIAL;
 152        scc_driver->subtype = SERIAL_TYPE_NORMAL;
 153        scc_driver->init_termios = tty_std_termios;
 154        scc_driver->init_termios.c_cflag =
 155          B9600 | CS8 | CREAD | HUPCL | CLOCAL;
 156        scc_driver->init_termios.c_ispeed = 9600;
 157        scc_driver->init_termios.c_ospeed = 9600;
 158        scc_driver->flags = TTY_DRIVER_REAL_RAW;
 159        tty_set_operations(scc_driver, &scc_ops);
 160
 161        if ((error = tty_register_driver(scc_driver))) {
 162                printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n",
 163                       error);
 164                put_tty_driver(scc_driver);
 165                return 1;
 166        }
 167
 168        return 0;
 169}
 170
 171
 172/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1).
 173 */
 174
 175static void scc_init_portstructs(void)
 176{
 177        struct scc_port *port;
 178        int i;
 179
 180        for (i = 0; i < 2; i++) {
 181                port = scc_ports + i;
 182                tty_port_init(&port->gs.port);
 183                port->gs.port.ops = &scc_port_ops;
 184                port->gs.magic = SCC_MAGIC;
 185                port->gs.close_delay = HZ/2;
 186                port->gs.closing_wait = 30 * HZ;
 187                port->gs.rd = &scc_real_driver;
 188#ifdef NEW_WRITE_LOCKING
 189                port->gs.port_write_mutex = MUTEX;
 190#endif
 191                init_waitqueue_head(&port->gs.port.open_wait);
 192                init_waitqueue_head(&port->gs.port.close_wait);
 193        }
 194}
 195
 196
 197#ifdef CONFIG_MVME147_SCC
 198static int mvme147_scc_init(void)
 199{
 200        struct scc_port *port;
 201        int error;
 202
 203        printk(KERN_INFO "SCC: MVME147 Serial Driver\n");
 204        /* Init channel A */
 205        port = &scc_ports[0];
 206        port->channel = CHANNEL_A;
 207        port->ctrlp = (volatile unsigned char *)M147_SCC_A_ADDR;
 208        port->datap = port->ctrlp + 1;
 209        port->port_a = &scc_ports[0];
 210        port->port_b = &scc_ports[1];
 211        error = request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
 212                            "SCC-A TX", port);
 213        if (error)
 214                goto fail;
 215        error = request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
 216                            "SCC-A status", port);
 217        if (error)
 218                goto fail_free_a_tx;
 219        error = request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
 220                            "SCC-A RX", port);
 221        if (error)
 222                goto fail_free_a_stat;
 223        error = request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int,
 224                            IRQF_DISABLED, "SCC-A special cond", port);
 225        if (error)
 226                goto fail_free_a_rx;
 227
 228        {
 229                SCC_ACCESS_INIT(port);
 230
 231                /* disable interrupts for this channel */
 232                SCCwrite(INT_AND_DMA_REG, 0);
 233                /* Set the interrupt vector */
 234                SCCwrite(INT_VECTOR_REG, MVME147_IRQ_SCC_BASE);
 235                /* Interrupt parameters: vector includes status, status low */
 236                SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
 237                SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
 238        }
 239
 240        /* Init channel B */
 241        port = &scc_ports[1];
 242        port->channel = CHANNEL_B;
 243        port->ctrlp = (volatile unsigned char *)M147_SCC_B_ADDR;
 244        port->datap = port->ctrlp + 1;
 245        port->port_a = &scc_ports[0];
 246        port->port_b = &scc_ports[1];
 247        error = request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
 248                            "SCC-B TX", port);
 249        if (error)
 250                goto fail_free_a_spcond;
 251        error = request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
 252                            "SCC-B status", port);
 253        if (error)
 254                goto fail_free_b_tx;
 255        error = request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
 256                            "SCC-B RX", port);
 257        if (error)
 258                goto fail_free_b_stat;
 259        error = request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int,
 260                            IRQF_DISABLED, "SCC-B special cond", port);
 261        if (error)
 262                goto fail_free_b_rx;
 263
 264        {
 265                SCC_ACCESS_INIT(port);
 266
 267                /* disable interrupts for this channel */
 268                SCCwrite(INT_AND_DMA_REG, 0);
 269        }
 270
 271        /* Ensure interrupts are enabled in the PCC chip */
 272        m147_pcc->serial_cntrl=PCC_LEVEL_SERIAL|PCC_INT_ENAB;
 273
 274        /* Initialise the tty driver structures and register */
 275        scc_init_portstructs();
 276        scc_init_drivers();
 277
 278        return 0;
 279
 280fail_free_b_rx:
 281        free_irq(MVME147_IRQ_SCCB_RX, port);
 282fail_free_b_stat:
 283        free_irq(MVME147_IRQ_SCCB_STAT, port);
 284fail_free_b_tx:
 285        free_irq(MVME147_IRQ_SCCB_TX, port);
 286fail_free_a_spcond:
 287        free_irq(MVME147_IRQ_SCCA_SPCOND, port);
 288fail_free_a_rx:
 289        free_irq(MVME147_IRQ_SCCA_RX, port);
 290fail_free_a_stat:
 291        free_irq(MVME147_IRQ_SCCA_STAT, port);
 292fail_free_a_tx:
 293        free_irq(MVME147_IRQ_SCCA_TX, port);
 294fail:
 295        return error;
 296}
 297#endif
 298
 299
 300#ifdef CONFIG_MVME162_SCC
 301static int mvme162_scc_init(void)
 302{
 303        struct scc_port *port;
 304        int error;
 305
 306        if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
 307                return (-ENODEV);
 308
 309        printk(KERN_INFO "SCC: MVME162 Serial Driver\n");
 310        /* Init channel A */
 311        port = &scc_ports[0];
 312        port->channel = CHANNEL_A;
 313        port->ctrlp = (volatile unsigned char *)MVME_SCC_A_ADDR;
 314        port->datap = port->ctrlp + 2;
 315        port->port_a = &scc_ports[0];
 316        port->port_b = &scc_ports[1];
 317        error = request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
 318                            "SCC-A TX", port);
 319        if (error)
 320                goto fail;
 321        error = request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
 322                            "SCC-A status", port);
 323        if (error)
 324                goto fail_free_a_tx;
 325        error = request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
 326                            "SCC-A RX", port);
 327        if (error)
 328                goto fail_free_a_stat;
 329        error = request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int,
 330                            IRQF_DISABLED, "SCC-A special cond", port);
 331        if (error)
 332                goto fail_free_a_rx;
 333
 334        {
 335                SCC_ACCESS_INIT(port);
 336
 337                /* disable interrupts for this channel */
 338                SCCwrite(INT_AND_DMA_REG, 0);
 339                /* Set the interrupt vector */
 340                SCCwrite(INT_VECTOR_REG, MVME162_IRQ_SCC_BASE);
 341                /* Interrupt parameters: vector includes status, status low */
 342                SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
 343                SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
 344        }
 345
 346        /* Init channel B */
 347        port = &scc_ports[1];
 348        port->channel = CHANNEL_B;
 349        port->ctrlp = (volatile unsigned char *)MVME_SCC_B_ADDR;
 350        port->datap = port->ctrlp + 2;
 351        port->port_a = &scc_ports[0];
 352        port->port_b = &scc_ports[1];
 353        error = request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
 354                            "SCC-B TX", port);
 355        if (error)
 356                goto fail_free_a_spcond;
 357        error = request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
 358                            "SCC-B status", port);
 359        if (error)
 360                goto fail_free_b_tx;
 361        error = request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
 362                            "SCC-B RX", port);
 363        if (error)
 364                goto fail_free_b_stat;
 365        error = request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int,
 366                            IRQF_DISABLED, "SCC-B special cond", port);
 367        if (error)
 368                goto fail_free_b_rx;
 369
 370        {
 371                SCC_ACCESS_INIT(port);  /* Either channel will do */
 372
 373                /* disable interrupts for this channel */
 374                SCCwrite(INT_AND_DMA_REG, 0);
 375        }
 376
 377        /* Ensure interrupts are enabled in the MC2 chip */
 378        *(volatile char *)0xfff4201d = 0x14;
 379
 380        /* Initialise the tty driver structures and register */
 381        scc_init_portstructs();
 382        scc_init_drivers();
 383
 384        return 0;
 385
 386fail_free_b_rx:
 387        free_irq(MVME162_IRQ_SCCB_RX, port);
 388fail_free_b_stat:
 389        free_irq(MVME162_IRQ_SCCB_STAT, port);
 390fail_free_b_tx:
 391        free_irq(MVME162_IRQ_SCCB_TX, port);
 392fail_free_a_spcond:
 393        free_irq(MVME162_IRQ_SCCA_SPCOND, port);
 394fail_free_a_rx:
 395        free_irq(MVME162_IRQ_SCCA_RX, port);
 396fail_free_a_stat:
 397        free_irq(MVME162_IRQ_SCCA_STAT, port);
 398fail_free_a_tx:
 399        free_irq(MVME162_IRQ_SCCA_TX, port);
 400fail:
 401        return error;
 402}
 403#endif
 404
 405
 406#ifdef CONFIG_BVME6000_SCC
 407static int bvme6000_scc_init(void)
 408{
 409        struct scc_port *port;
 410        int error;
 411
 412        printk(KERN_INFO "SCC: BVME6000 Serial Driver\n");
 413        /* Init channel A */
 414        port = &scc_ports[0];
 415        port->channel = CHANNEL_A;
 416        port->ctrlp = (volatile unsigned char *)BVME_SCC_A_ADDR;
 417        port->datap = port->ctrlp + 4;
 418        port->port_a = &scc_ports[0];
 419        port->port_b = &scc_ports[1];
 420        error = request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
 421                            "SCC-A TX", port);
 422        if (error)
 423                goto fail;
 424        error = request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
 425                            "SCC-A status", port);
 426        if (error)
 427                goto fail_free_a_tx;
 428        error = request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
 429                            "SCC-A RX", port);
 430        if (error)
 431                goto fail_free_a_stat;
 432        error = request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int,
 433                            IRQF_DISABLED, "SCC-A special cond", port);
 434        if (error)
 435                goto fail_free_a_rx;
 436
 437        {
 438                SCC_ACCESS_INIT(port);
 439
 440                /* disable interrupts for this channel */
 441                SCCwrite(INT_AND_DMA_REG, 0);
 442                /* Set the interrupt vector */
 443                SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE);
 444                /* Interrupt parameters: vector includes status, status low */
 445                SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
 446                SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
 447        }
 448
 449        /* Init channel B */
 450        port = &scc_ports[1];
 451        port->channel = CHANNEL_B;
 452        port->ctrlp = (volatile unsigned char *)BVME_SCC_B_ADDR;
 453        port->datap = port->ctrlp + 4;
 454        port->port_a = &scc_ports[0];
 455        port->port_b = &scc_ports[1];
 456        error = request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
 457                            "SCC-B TX", port);
 458        if (error)
 459                goto fail_free_a_spcond;
 460        error = request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
 461                            "SCC-B status", port);
 462        if (error)
 463                goto fail_free_b_tx;
 464        error = request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
 465                            "SCC-B RX", port);
 466        if (error)
 467                goto fail_free_b_stat;
 468        error = request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int,
 469                            IRQF_DISABLED, "SCC-B special cond", port);
 470        if (error)
 471                goto fail_free_b_rx;
 472
 473        {
 474                SCC_ACCESS_INIT(port);  /* Either channel will do */
 475
 476                /* disable interrupts for this channel */
 477                SCCwrite(INT_AND_DMA_REG, 0);
 478        }
 479
 480        /* Initialise the tty driver structures and register */
 481        scc_init_portstructs();
 482        scc_init_drivers();
 483
 484        return 0;
 485
 486fail:
 487        free_irq(BVME_IRQ_SCCA_STAT, port);
 488fail_free_a_tx:
 489        free_irq(BVME_IRQ_SCCA_RX, port);
 490fail_free_a_stat:
 491        free_irq(BVME_IRQ_SCCA_SPCOND, port);
 492fail_free_a_rx:
 493        free_irq(BVME_IRQ_SCCB_TX, port);
 494fail_free_a_spcond:
 495        free_irq(BVME_IRQ_SCCB_STAT, port);
 496fail_free_b_tx:
 497        free_irq(BVME_IRQ_SCCB_RX, port);
 498fail_free_b_stat:
 499        free_irq(BVME_IRQ_SCCB_SPCOND, port);
 500fail_free_b_rx:
 501        return error;
 502}
 503#endif
 504
 505
 506static int vme_scc_init(void)
 507{
 508        int res = -ENODEV;
 509
 510#ifdef CONFIG_MVME147_SCC
 511        if (MACH_IS_MVME147)
 512                res = mvme147_scc_init();
 513#endif
 514#ifdef CONFIG_MVME162_SCC
 515        if (MACH_IS_MVME16x)
 516                res = mvme162_scc_init();
 517#endif
 518#ifdef CONFIG_BVME6000_SCC
 519        if (MACH_IS_BVME6000)
 520                res = bvme6000_scc_init();
 521#endif
 522        return res;
 523}
 524
 525module_init(vme_scc_init);
 526
 527
 528/*---------------------------------------------------------------------------
 529 * Interrupt handlers
 530 *--------------------------------------------------------------------------*/
 531
 532static irqreturn_t scc_rx_int(int irq, void *data)
 533{
 534        unsigned char   ch;
 535        struct scc_port *port = data;
 536        struct tty_struct *tty = port->gs.port.tty;
 537        SCC_ACCESS_INIT(port);
 538
 539        ch = SCCread_NB(RX_DATA_REG);
 540        if (!tty) {
 541                printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
 542                SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 543                return IRQ_HANDLED;
 544        }
 545        tty_insert_flip_char(tty, ch, 0);
 546
 547        /* Check if another character is already ready; in that case, the
 548         * spcond_int() function must be used, because this character may have an
 549         * error condition that isn't signalled by the interrupt vector used!
 550         */
 551        if (SCCread(INT_PENDING_REG) &
 552            (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
 553                scc_spcond_int (irq, data);
 554                return IRQ_HANDLED;
 555        }
 556
 557        SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 558
 559        tty_flip_buffer_push(tty);
 560        return IRQ_HANDLED;
 561}
 562
 563
 564static irqreturn_t scc_spcond_int(int irq, void *data)
 565{
 566        struct scc_port *port = data;
 567        struct tty_struct *tty = port->gs.port.tty;
 568        unsigned char   stat, ch, err;
 569        int             int_pending_mask = port->channel == CHANNEL_A ?
 570                                           IPR_A_RX : IPR_B_RX;
 571        SCC_ACCESS_INIT(port);
 572        
 573        if (!tty) {
 574                printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
 575                SCCwrite(COMMAND_REG, CR_ERROR_RESET);
 576                SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 577                return IRQ_HANDLED;
 578        }
 579        do {
 580                stat = SCCread(SPCOND_STATUS_REG);
 581                ch = SCCread_NB(RX_DATA_REG);
 582
 583                if (stat & SCSR_RX_OVERRUN)
 584                        err = TTY_OVERRUN;
 585                else if (stat & SCSR_PARITY_ERR)
 586                        err = TTY_PARITY;
 587                else if (stat & SCSR_CRC_FRAME_ERR)
 588                        err = TTY_FRAME;
 589                else
 590                        err = 0;
 591
 592                tty_insert_flip_char(tty, ch, err);
 593
 594                /* ++TeSche: *All* errors have to be cleared manually,
 595                 * else the condition persists for the next chars
 596                 */
 597                if (err)
 598                  SCCwrite(COMMAND_REG, CR_ERROR_RESET);
 599
 600        } while(SCCread(INT_PENDING_REG) & int_pending_mask);
 601
 602        SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 603
 604        tty_flip_buffer_push(tty);
 605        return IRQ_HANDLED;
 606}
 607
 608
 609static irqreturn_t scc_tx_int(int irq, void *data)
 610{
 611        struct scc_port *port = data;
 612        SCC_ACCESS_INIT(port);
 613
 614        if (!port->gs.port.tty) {
 615                printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
 616                SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
 617                SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
 618                SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 619                return IRQ_HANDLED;
 620        }
 621        while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) {
 622                if (port->x_char) {
 623                        SCCwrite(TX_DATA_REG, port->x_char);
 624                        port->x_char = 0;
 625                }
 626                else if ((port->gs.xmit_cnt <= 0) ||
 627                         port->gs.port.tty->stopped ||
 628                         port->gs.port.tty->hw_stopped)
 629                        break;
 630                else {
 631                        SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]);
 632                        port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1);
 633                        if (--port->gs.xmit_cnt <= 0)
 634                                break;
 635                }
 636        }
 637        if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped ||
 638            port->gs.port.tty->hw_stopped) {
 639                /* disable tx interrupts */
 640                SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
 641                SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
 642                port->gs.port.flags &= ~GS_TX_INTEN;
 643        }
 644        if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars)
 645                tty_wakeup(port->gs.port.tty);
 646
 647        SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 648        return IRQ_HANDLED;
 649}
 650
 651
 652static irqreturn_t scc_stat_int(int irq, void *data)
 653{
 654        struct scc_port *port = data;
 655        unsigned channel = port->channel;
 656        unsigned char   last_sr, sr, changed;
 657        SCC_ACCESS_INIT(port);
 658
 659        last_sr = scc_last_status_reg[channel];
 660        sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG);
 661        changed = last_sr ^ sr;
 662
 663        if (changed & SR_DCD) {
 664                port->c_dcd = !!(sr & SR_DCD);
 665                if (!(port->gs.port.flags & ASYNC_CHECK_CD))
 666                        ;       /* Don't report DCD changes */
 667                else if (port->c_dcd) {
 668                        wake_up_interruptible(&port->gs.port.open_wait);
 669                }
 670                else {
 671                        if (port->gs.port.tty)
 672                                tty_hangup (port->gs.port.tty);
 673                }
 674        }
 675        SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
 676        SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
 677        return IRQ_HANDLED;
 678}
 679
 680
 681/*---------------------------------------------------------------------------
 682 * generic_serial.c callback funtions
 683 *--------------------------------------------------------------------------*/
 684
 685static void scc_disable_tx_interrupts(void *ptr)
 686{
 687        struct scc_port *port = ptr;
 688        unsigned long   flags;
 689        SCC_ACCESS_INIT(port);
 690
 691        local_irq_save(flags);
 692        SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
 693        port->gs.port.flags &= ~GS_TX_INTEN;
 694        local_irq_restore(flags);
 695}
 696
 697
 698static void scc_enable_tx_interrupts(void *ptr)
 699{
 700        struct scc_port *port = ptr;
 701        unsigned long   flags;
 702        SCC_ACCESS_INIT(port);
 703
 704        local_irq_save(flags);
 705        SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
 706        /* restart the transmitter */
 707        scc_tx_int (0, port);
 708        local_irq_restore(flags);
 709}
 710
 711
 712static void scc_disable_rx_interrupts(void *ptr)
 713{
 714        struct scc_port *port = ptr;
 715        unsigned long   flags;
 716        SCC_ACCESS_INIT(port);
 717
 718        local_irq_save(flags);
 719        SCCmod(INT_AND_DMA_REG,
 720            ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);
 721        local_irq_restore(flags);
 722}
 723
 724
 725static void scc_enable_rx_interrupts(void *ptr)
 726{
 727        struct scc_port *port = ptr;
 728        unsigned long   flags;
 729        SCC_ACCESS_INIT(port);
 730
 731        local_irq_save(flags);
 732        SCCmod(INT_AND_DMA_REG, 0xff,
 733                IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);
 734        local_irq_restore(flags);
 735}
 736
 737
 738static int scc_carrier_raised(struct tty_port *port)
 739{
 740        struct scc_port *sc = container_of(port, struct scc_port, gs.port);
 741        unsigned channel = sc->channel;
 742
 743        return !!(scc_last_status_reg[channel] & SR_DCD);
 744}
 745
 746
 747static void scc_shutdown_port(void *ptr)
 748{
 749        struct scc_port *port = ptr;
 750
 751        port->gs.port.flags &= ~ GS_ACTIVE;
 752        if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
 753                scc_setsignals (port, 0, 0);
 754        }
 755}
 756
 757
 758static int scc_set_real_termios (void *ptr)
 759{
 760        /* the SCC has char sizes 5,7,6,8 in that order! */
 761        static int chsize_map[4] = { 0, 2, 1, 3 };
 762        unsigned cflag, baud, chsize, channel, brgval = 0;
 763        unsigned long flags;
 764        struct scc_port *port = ptr;
 765        SCC_ACCESS_INIT(port);
 766
 767        if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0;
 768
 769        channel = port->channel;
 770
 771        if (channel == CHANNEL_A)
 772                return 0;               /* Settings controlled by boot PROM */
 773
 774        cflag  = port->gs.port.tty->termios->c_cflag;
 775        baud = port->gs.baud;
 776        chsize = (cflag & CSIZE) >> 4;
 777
 778        if (baud == 0) {
 779                /* speed == 0 -> drop DTR */
 780                local_irq_save(flags);
 781                SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);
 782                local_irq_restore(flags);
 783                return 0;
 784        }
 785        else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||
 786                 (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) ||
 787                 (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) {
 788                printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud);
 789                return 0;
 790        }
 791
 792        if (cflag & CLOCAL)
 793                port->gs.port.flags &= ~ASYNC_CHECK_CD;
 794        else
 795                port->gs.port.flags |= ASYNC_CHECK_CD;
 796
 797#ifdef CONFIG_MVME147_SCC
 798        if (MACH_IS_MVME147)
 799                brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
 800#endif
 801#ifdef CONFIG_MVME162_SCC
 802        if (MACH_IS_MVME16x)
 803                brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
 804#endif
 805#ifdef CONFIG_BVME6000_SCC
 806        if (MACH_IS_BVME6000)
 807                brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2;
 808#endif
 809        /* Now we have all parameters and can go to set them: */
 810        local_irq_save(flags);
 811
 812        /* receiver's character size and auto-enables */
 813        SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),
 814                        (chsize_map[chsize] << 6) |
 815                        ((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0));
 816        /* parity and stop bits (both, Tx and Rx), clock mode never changes */
 817        SCCmod (AUX1_CTRL_REG,
 818                ~(A1CR_PARITY_MASK | A1CR_MODE_MASK),
 819                ((cflag & PARENB
 820                  ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN)
 821                  : A1CR_PARITY_NONE)
 822                 | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1)));
 823        /* sender's character size, set DTR for valid baud rate */
 824        SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR);
 825        /* clock sources never change */
 826        /* disable BRG before changing the value */
 827        SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0);
 828        /* BRG value */
 829        SCCwrite(TIMER_LOW_REG, brgval & 0xff);
 830        SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff);
 831        /* BRG enable, and clock source never changes */
 832        SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
 833
 834        local_irq_restore(flags);
 835
 836        return 0;
 837}
 838
 839
 840static int scc_chars_in_buffer (void *ptr)
 841{
 842        struct scc_port *port = ptr;
 843        SCC_ACCESS_INIT(port);
 844
 845        return (SCCread (SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0  : 1;
 846}
 847
 848
 849/* Comment taken from sx.c (2.4.0):
 850   I haven't the foggiest why the decrement use count has to happen
 851   here. The whole linux serial drivers stuff needs to be redesigned.
 852   My guess is that this is a hack to minimize the impact of a bug
 853   elsewhere. Thinking about it some more. (try it sometime) Try
 854   running minicom on a serial port that is driven by a modularized
 855   driver. Have the modem hangup. Then remove the driver module. Then
 856   exit minicom.  I expect an "oops".  -- REW */
 857
 858static void scc_hungup(void *ptr)
 859{
 860        scc_disable_tx_interrupts(ptr);
 861        scc_disable_rx_interrupts(ptr);
 862}
 863
 864
 865static void scc_close(void *ptr)
 866{
 867        scc_disable_tx_interrupts(ptr);
 868        scc_disable_rx_interrupts(ptr);
 869}
 870
 871
 872/*---------------------------------------------------------------------------
 873 * Internal support functions
 874 *--------------------------------------------------------------------------*/
 875
 876static void scc_setsignals(struct scc_port *port, int dtr, int rts)
 877{
 878        unsigned long flags;
 879        unsigned char t;
 880        SCC_ACCESS_INIT(port);
 881
 882        local_irq_save(flags);
 883        t = SCCread(TX_CTRL_REG);
 884        if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR);
 885        if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS);
 886        SCCwrite(TX_CTRL_REG, t);
 887        local_irq_restore(flags);
 888}
 889
 890
 891static void scc_send_xchar(struct tty_struct *tty, char ch)
 892{
 893        struct scc_port *port = tty->driver_data;
 894
 895        port->x_char = ch;
 896        if (ch)
 897                scc_enable_tx_interrupts(port);
 898}
 899
 900
 901/*---------------------------------------------------------------------------
 902 * Driver entrypoints referenced from above
 903 *--------------------------------------------------------------------------*/
 904
 905static int scc_open (struct tty_struct * tty, struct file * filp)
 906{
 907        int line = tty->index;
 908        int retval;
 909        struct scc_port *port = &scc_ports[line];
 910        int i, channel = port->channel;
 911        unsigned long   flags;
 912        SCC_ACCESS_INIT(port);
 913#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_MVME147_SCC)
 914        static const struct {
 915                unsigned reg, val;
 916        } mvme_init_tab[] = {
 917                /* Values for MVME162 and MVME147 */
 918                /* no parity, 1 stop bit, async, 1:16 */
 919                { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
 920                /* parity error is special cond, ints disabled, no DMA */
 921                { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
 922                /* Rx 8 bits/char, no auto enable, Rx off */
 923                { RX_CTRL_REG, RCR_CHSIZE_8 },
 924                /* DTR off, Tx 8 bits/char, RTS off, Tx off */
 925                { TX_CTRL_REG, TCR_CHSIZE_8 },
 926                /* special features off */
 927                { AUX2_CTRL_REG, 0 },
 928                { CLK_CTRL_REG, CCR_RXCLK_BRG | CCR_TXCLK_BRG },
 929                { DPLL_CTRL_REG, DCR_BRG_ENAB | DCR_BRG_USE_PCLK },
 930                /* Start Rx */
 931                { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
 932                /* Start Tx */
 933                { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
 934                /* Ext/Stat ints: DCD only */
 935                { INT_CTRL_REG, ICR_ENAB_DCD_INT },
 936                /* Reset Ext/Stat ints */
 937                { COMMAND_REG, CR_EXTSTAT_RESET },
 938                /* ...again */
 939                { COMMAND_REG, CR_EXTSTAT_RESET },
 940        };
 941#endif
 942#if defined(CONFIG_BVME6000_SCC)
 943        static const struct {
 944                unsigned reg, val;
 945        } bvme_init_tab[] = {
 946                /* Values for BVME6000 */
 947                /* no parity, 1 stop bit, async, 1:16 */
 948                { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
 949                /* parity error is special cond, ints disabled, no DMA */
 950                { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
 951                /* Rx 8 bits/char, no auto enable, Rx off */
 952                { RX_CTRL_REG, RCR_CHSIZE_8 },
 953                /* DTR off, Tx 8 bits/char, RTS off, Tx off */
 954                { TX_CTRL_REG, TCR_CHSIZE_8 },
 955                /* special features off */
 956                { AUX2_CTRL_REG, 0 },
 957                { CLK_CTRL_REG, CCR_RTxC_XTAL | CCR_RXCLK_BRG | CCR_TXCLK_BRG },
 958                { DPLL_CTRL_REG, DCR_BRG_ENAB },
 959                /* Start Rx */
 960                { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
 961                /* Start Tx */
 962                { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
 963                /* Ext/Stat ints: DCD only */
 964                { INT_CTRL_REG, ICR_ENAB_DCD_INT },
 965                /* Reset Ext/Stat ints */
 966                { COMMAND_REG, CR_EXTSTAT_RESET },
 967                /* ...again */
 968                { COMMAND_REG, CR_EXTSTAT_RESET },
 969        };
 970#endif
 971        if (!(port->gs.port.flags & ASYNC_INITIALIZED)) {
 972                local_irq_save(flags);
 973#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
 974                if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
 975                        for (i = 0; i < ARRAY_SIZE(mvme_init_tab); ++i)
 976                                SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val);
 977                }
 978#endif
 979#if defined(CONFIG_BVME6000_SCC)
 980                if (MACH_IS_BVME6000) {
 981                        for (i = 0; i < ARRAY_SIZE(bvme_init_tab); ++i)
 982                                SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val);
 983                }
 984#endif
 985
 986                /* remember status register for detection of DCD and CTS changes */
 987                scc_last_status_reg[channel] = SCCread(STATUS_REG);
 988
 989                port->c_dcd = 0;        /* Prevent initial 1->0 interrupt */
 990                scc_setsignals (port, 1,1);
 991                local_irq_restore(flags);
 992        }
 993
 994        tty->driver_data = port;
 995        port->gs.port.tty = tty;
 996        port->gs.port.count++;
 997        retval = gs_init_port(&port->gs);
 998        if (retval) {
 999                port->gs.port.count--;
1000                return retval;
1001        }
1002        port->gs.port.flags |= GS_ACTIVE;
1003        retval = gs_block_til_ready(port, filp);
1004
1005        if (retval) {
1006                port->gs.port.count--;
1007                return retval;
1008        }
1009
1010        port->c_dcd = tty_port_carrier_raised(&port->gs.port);
1011
1012        scc_enable_rx_interrupts(port);
1013
1014        return 0;
1015}
1016
1017
1018static void scc_throttle (struct tty_struct * tty)
1019{
1020        struct scc_port *port = tty->driver_data;
1021        unsigned long   flags;
1022        SCC_ACCESS_INIT(port);
1023
1024        if (tty->termios->c_cflag & CRTSCTS) {
1025                local_irq_save(flags);
1026                SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
1027                local_irq_restore(flags);
1028        }
1029        if (I_IXOFF(tty))
1030                scc_send_xchar(tty, STOP_CHAR(tty));
1031}
1032
1033
1034static void scc_unthrottle (struct tty_struct * tty)
1035{
1036        struct scc_port *port = tty->driver_data;
1037        unsigned long   flags;
1038        SCC_ACCESS_INIT(port);
1039
1040        if (tty->termios->c_cflag & CRTSCTS) {
1041                local_irq_save(flags);
1042                SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);
1043                local_irq_restore(flags);
1044        }
1045        if (I_IXOFF(tty))
1046                scc_send_xchar(tty, START_CHAR(tty));
1047}
1048
1049
1050static int scc_ioctl(struct tty_struct *tty, struct file *file,
1051                     unsigned int cmd, unsigned long arg)
1052{
1053        return -ENOIOCTLCMD;
1054}
1055
1056
1057static int scc_break_ctl(struct tty_struct *tty, int break_state)
1058{
1059        struct scc_port *port = tty->driver_data;
1060        unsigned long   flags;
1061        SCC_ACCESS_INIT(port);
1062
1063        local_irq_save(flags);
1064        SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, 
1065                        break_state ? TCR_SEND_BREAK : 0);
1066        local_irq_restore(flags);
1067        return 0;
1068}
1069
1070
1071/*---------------------------------------------------------------------------
1072 * Serial console stuff...
1073 *--------------------------------------------------------------------------*/
1074
1075#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0)
1076
1077static void scc_ch_write (char ch)
1078{
1079        volatile char *p = NULL;
1080        
1081#ifdef CONFIG_MVME147_SCC
1082        if (MACH_IS_MVME147)
1083                p = (volatile char *)M147_SCC_A_ADDR;
1084#endif
1085#ifdef CONFIG_MVME162_SCC
1086        if (MACH_IS_MVME16x)
1087                p = (volatile char *)MVME_SCC_A_ADDR;
1088#endif
1089#ifdef CONFIG_BVME6000_SCC
1090        if (MACH_IS_BVME6000)
1091                p = (volatile char *)BVME_SCC_A_ADDR;
1092#endif
1093
1094        do {
1095                scc_delay();
1096        }
1097        while (!(*p & 4));
1098        scc_delay();
1099        *p = 8;
1100        scc_delay();
1101        *p = ch;
1102}
1103
1104/* The console must be locked when we get here. */
1105
1106static void scc_console_write (struct console *co, const char *str, unsigned count)
1107{
1108        unsigned long   flags;
1109
1110        local_irq_save(flags);
1111
1112        while (count--)
1113        {
1114                if (*str == '\n')
1115                        scc_ch_write ('\r');
1116                scc_ch_write (*str++);
1117        }
1118        local_irq_restore(flags);
1119}
1120
1121static struct tty_driver *scc_console_device(struct console *c, int *index)
1122{
1123        *index = c->index;
1124        return scc_driver;
1125}
1126
1127static struct console sercons = {
1128        .name           = "ttyS",
1129        .write          = scc_console_write,
1130        .device         = scc_console_device,
1131        .flags          = CON_PRINTBUFFER,
1132        .index          = -1,
1133};
1134
1135
1136static int __init vme_scc_console_init(void)
1137{
1138        if (vme_brdtype == VME_TYPE_MVME147 ||
1139                        vme_brdtype == VME_TYPE_MVME162 ||
1140                        vme_brdtype == VME_TYPE_MVME172 ||
1141                        vme_brdtype == VME_TYPE_BVME4000 ||
1142                        vme_brdtype == VME_TYPE_BVME6000)
1143                register_console(&sercons);
1144        return 0;
1145}
1146console_initcall(vme_scc_console_init);
1147