linux-old/drivers/char/serial167.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/char/serial167.c
   3 *
   4 * Driver for MVME166/7 board serial ports, which are via a CD2401.
   5 * Based very much on cyclades.c.
   6 *
   7 * MVME166/7 work by Richard Hirst [richard@sleepie.demon.co.uk]
   8 *
   9 * ==============================================================
  10 *
  11 * static char rcsid[] =
  12 * "$Revision: 1.36.1.4 $$Date: 1995/03/29 06:14:14 $";
  13 *
  14 *  linux/kernel/cyclades.c
  15 *
  16 * Maintained by Marcio Saito (cyclades@netcom.com) and
  17 * Randolph Bentson (bentson@grieg.seaslug.org)
  18 *
  19 * Much of the design and some of the code came from serial.c
  20 * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
  21 * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
  22 * and then fixed as suggested by Michael K. Johnson 12/12/92.
  23 *
  24 * This version does not support shared irq's.
  25 *
  26 * This module exports the following rs232 io functions:
  27 *   int cy_init(void);
  28 *   int  cy_open(struct tty_struct *tty, struct file *filp);
  29 *
  30 * $Log: cyclades.c,v $
  31 * Revision 1.36.1.4  1995/03/29  06:14:14  bentson
  32 * disambiguate between Cyclom-16Y and Cyclom-32Ye;
  33 *
  34 * Changes:
  35 *
  36 * 200 lines of changes record removed - RGH 11-10-95, starting work on
  37 * converting this to drive serial ports on mvme166 (cd2401).
  38 *
  39 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/25
  40 * - get rid of verify_area
  41 * - use get_user to access memory from userspace in set_threshold,
  42 *   set_default_threshold and set_timeout
  43 * - don't use the panic function in serial167_init
  44 * - do resource release on failure on serial167_init
  45 * - include missing restore_flags in mvme167_serial_console_setup
  46 */
  47
  48#include <linux/config.h>
  49#include <linux/errno.h>
  50#include <linux/signal.h>
  51#include <linux/sched.h>
  52#include <linux/timer.h>
  53#include <linux/tty.h>
  54#include <linux/interrupt.h>
  55#include <linux/serial.h>
  56#include <linux/serialP.h>
  57#include <linux/string.h>
  58#include <linux/fcntl.h>
  59#include <linux/ptrace.h>
  60#include <linux/serial167.h>
  61#include <linux/delay.h>
  62#include <linux/major.h>
  63#include <linux/mm.h>
  64#include <linux/console.h>
  65#include <linux/module.h>
  66
  67#include <asm/system.h>
  68#include <asm/io.h>
  69#include <asm/segment.h>
  70#include <asm/bitops.h>
  71#include <asm/mvme16xhw.h>
  72#include <asm/bootinfo.h>
  73#include <asm/setup.h>
  74
  75#include <linux/types.h>
  76#include <linux/kernel.h>
  77
  78#include <linux/version.h>
  79#include <asm/uaccess.h>
  80#include <linux/init.h>
  81
  82#define SERIAL_PARANOIA_CHECK
  83#undef  SERIAL_DEBUG_OPEN
  84#undef  SERIAL_DEBUG_THROTTLE
  85#undef  SERIAL_DEBUG_OTHER
  86#undef  SERIAL_DEBUG_IO
  87#undef  SERIAL_DEBUG_COUNT
  88#undef  SERIAL_DEBUG_DTR
  89#undef  CYCLOM_16Y_HACK
  90#define  CYCLOM_ENABLE_MONITORING
  91
  92#ifndef MIN
  93#define MIN(a,b)        ((a) < (b) ? (a) : (b))
  94#endif
  95
  96#define WAKEUP_CHARS 256
  97
  98#define STD_COM_FLAGS (0)
  99
 100#define SERIAL_TYPE_NORMAL  1
 101#define SERIAL_TYPE_CALLOUT 2
 102
 103
 104DECLARE_TASK_QUEUE(tq_cyclades);
 105
 106struct tty_driver cy_serial_driver, cy_callout_driver;
 107extern int serial_console;
 108static struct cyclades_port *serial_console_info = NULL;
 109static unsigned int serial_console_cflag = 0;
 110u_char initial_console_speed;
 111
 112/* Base address of cd2401 chip on mvme166/7 */
 113
 114#define BASE_ADDR (0xfff45000)
 115#define pcc2chip        ((volatile u_char *)0xfff42000)
 116#define PccSCCMICR      0x1d
 117#define PccSCCTICR      0x1e
 118#define PccSCCRICR      0x1f
 119#define PccTPIACKR      0x25
 120#define PccRPIACKR      0x27
 121#define PccIMLR         0x3f
 122
 123/* This is the per-port data structure */
 124struct cyclades_port cy_port[] = {
 125      /* CARD#  */
 126        {-1 },      /* ttyS0 */
 127        {-1 },      /* ttyS1 */
 128        {-1 },      /* ttyS2 */
 129        {-1 },      /* ttyS3 */
 130};
 131#define NR_PORTS        (sizeof(cy_port)/sizeof(struct cyclades_port))
 132
 133static int serial_refcount;
 134
 135static struct tty_struct *serial_table[NR_PORTS];
 136static struct termios *serial_termios[NR_PORTS];
 137static struct termios *serial_termios_locked[NR_PORTS];
 138
 139
 140/*
 141 * tmp_buf is used as a temporary buffer by serial_write.  We need to
 142 * lock it in case the copy_from_user blocks while swapping in a page,
 143 * and some other program tries to do a serial write at the same time.
 144 * Since the lock will only come under contention when the system is
 145 * swapping and available memory is low, it makes sense to share one
 146 * buffer across all the serial ports, since it significantly saves
 147 * memory if large numbers of serial ports are open.
 148 */
 149static unsigned char *tmp_buf = 0;
 150DECLARE_MUTEX(tmp_buf_sem);
 151
 152/*
 153 * This is used to look up the divisor speeds and the timeouts
 154 * We're normally limited to 15 distinct baud rates.  The extra
 155 * are accessed via settings in info->flags.
 156 *         0,     1,     2,     3,     4,     5,     6,     7,     8,     9,
 157 *        10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
 158 *                                                  HI            VHI
 159 */
 160static int baud_table[] = {
 161           0,    50,    75,   110,   134,   150,   200,   300,   600,  1200,
 162        1800,  2400,  4800,  9600, 19200, 38400, 57600, 76800,115200,150000,
 163        0};
 164
 165#if 0
 166static char baud_co[] = {  /* 25 MHz clock option table */
 167        /* value =>    00    01   02    03    04 */
 168        /* divide by    8    32   128   512  2048 */
 169        0x00,  0x04,  0x04,  0x04,  0x04,  0x04,  0x03,  0x03,  0x03,  0x02,
 170        0x02,  0x02,  0x01,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00};
 171
 172static char baud_bpr[] = {  /* 25 MHz baud rate period table */
 173        0x00,  0xf5,  0xa3,  0x6f,  0x5c,  0x51,  0xf5,  0xa3,  0x51,  0xa3,
 174        0x6d,  0x51,  0xa3,  0x51,  0xa3,  0x51,  0x36,  0x29,  0x1b,  0x15};
 175#endif
 176
 177/* I think 166 brd clocks 2401 at 20MHz.... */
 178
 179/* These values are written directly to tcor, and >> 5 for writing to rcor */
 180static u_char baud_co[] = {  /* 20 MHz clock option table */
 181        0x00,  0x80,  0x80,  0x80,  0x80,  0x80,  0x80,  0x60,  0x60,  0x40,
 182        0x40,  0x40,  0x20,  0x20,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00};
 183
 184/* These values written directly to tbpr/rbpr */
 185static u_char baud_bpr[] = {  /* 20 MHz baud rate period table */
 186        0x00,  0xc0,  0x80,  0x58,  0x6c,  0x40,  0xc0,  0x81,  0x40,  0x81,
 187        0x57,  0x40,  0x81,  0x40,  0x81,  0x40,  0x2b,  0x20,  0x15,  0x10};
 188
 189static u_char baud_cor4[] = {  /* receive threshold */
 190        0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,  0x0a,
 191        0x0a,  0x0a,  0x0a,  0x09,  0x09,  0x08,  0x08,  0x08,  0x08,  0x07};
 192
 193
 194
 195static void shutdown(struct cyclades_port *);
 196static int startup (struct cyclades_port *);
 197static void cy_throttle(struct tty_struct *);
 198static void cy_unthrottle(struct tty_struct *);
 199static void config_setup(struct cyclades_port *);
 200extern void console_print(const char *);
 201#ifdef CYCLOM_SHOW_STATUS
 202static void show_status(int);
 203#endif
 204
 205#ifdef CONFIG_REMOTE_DEBUG
 206static void debug_setup(void);
 207void queueDebugChar (int c);
 208int getDebugChar(void);
 209
 210#define DEBUG_PORT      1
 211#define DEBUG_LEN       256
 212
 213typedef struct {
 214        int     in;
 215        int     out;
 216        unsigned char   buf[DEBUG_LEN];
 217} debugq;
 218
 219debugq debugiq;
 220#endif
 221
 222/*
 223 * I have my own version of udelay(), as it is needed when initialising
 224 * the chip, before the delay loop has been calibrated.  Should probably
 225 * reference one of the vmechip2 or pccchip2 counter for an accurate
 226 * delay, but this wild guess will do for now.
 227 */
 228
 229void my_udelay (long us)
 230{
 231        u_char x;
 232        volatile u_char *p = &x;
 233        int i;
 234
 235        while (us--)
 236                for (i = 100; i; i--)
 237                        x |= *p;
 238}
 239
 240static inline int
 241serial_paranoia_check(struct cyclades_port *info,
 242                        dev_t device, const char *routine)
 243{
 244#ifdef SERIAL_PARANOIA_CHECK
 245    static const char *badmagic =
 246        "Warning: bad magic number for serial struct (%d, %d) in %s\n";
 247    static const char *badinfo =
 248        "Warning: null cyclades_port for (%d, %d) in %s\n";
 249    static const char *badrange =
 250        "Warning: cyclades_port out of range for (%d, %d) in %s\n";
 251
 252    if (!info) {
 253        printk(badinfo, MAJOR(device), MINOR(device), routine);
 254        return 1;
 255    }
 256
 257    if( (long)info < (long)(&cy_port[0])
 258    || (long)(&cy_port[NR_PORTS]) < (long)info ){
 259        printk(badrange, MAJOR(device), MINOR(device), routine);
 260        return 1;
 261    }
 262
 263    if (info->magic != CYCLADES_MAGIC) {
 264        printk(badmagic, MAJOR(device), MINOR(device), routine);
 265        return 1;
 266    }
 267#endif
 268        return 0;
 269} /* serial_paranoia_check */
 270
 271#if 0
 272/* The following diagnostic routines allow the driver to spew
 273   information on the screen, even (especially!) during interrupts.
 274 */
 275void
 276SP(char *data){
 277  unsigned long flags;
 278    save_flags(flags); cli();
 279        console_print(data);
 280    restore_flags(flags);
 281}
 282char scrn[2];
 283void
 284CP(char data){
 285  unsigned long flags;
 286    save_flags(flags); cli();
 287        scrn[0] = data;
 288        console_print(scrn);
 289    restore_flags(flags);
 290}/* CP */
 291
 292void CP1(int data) { (data<10)?  CP(data+'0'): CP(data+'A'-10); }/* CP1 */
 293void CP2(int data) { CP1((data>>4) & 0x0f); CP1( data & 0x0f); }/* CP2 */
 294void CP4(int data) { CP2((data>>8) & 0xff); CP2(data & 0xff); }/* CP4 */
 295void CP8(long data) { CP4((data>>16) & 0xffff); CP4(data & 0xffff); }/* CP8 */
 296#endif
 297
 298/* This routine waits up to 1000 micro-seconds for the previous
 299   command to the Cirrus chip to complete and then issues the
 300   new command.  An error is returned if the previous command
 301   didn't finish within the time limit.
 302 */
 303u_short
 304write_cy_cmd(volatile u_char *base_addr, u_char cmd)
 305{
 306  unsigned long flags;
 307  volatile int  i;
 308
 309    save_flags(flags); cli();
 310        /* Check to see that the previous command has completed */
 311        for(i = 0 ; i < 100 ; i++){
 312            if (base_addr[CyCCR] == 0){
 313                break;
 314            }
 315            my_udelay(10L);
 316        }
 317        /* if the CCR never cleared, the previous command
 318            didn't finish within the "reasonable time" */
 319        if ( i == 10 ) {
 320            restore_flags(flags);
 321            return (-1);
 322        }
 323
 324        /* Issue the new command */
 325        base_addr[CyCCR] = cmd;
 326    restore_flags(flags);
 327    return(0);
 328} /* write_cy_cmd */
 329
 330
 331/* cy_start and cy_stop provide software output flow control as a
 332   function of XON/XOFF, software CTS, and other such stuff. */
 333
 334static void
 335cy_stop(struct tty_struct *tty)
 336{
 337  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
 338  volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
 339  int channel;
 340  unsigned long flags;
 341
 342#ifdef SERIAL_DEBUG_OTHER
 343    printk("cy_stop ttyS%d\n", info->line); /* */
 344#endif
 345
 346    if (serial_paranoia_check(info, tty->device, "cy_stop"))
 347        return;
 348        
 349    channel = info->line;
 350
 351    save_flags(flags); cli();
 352        base_addr[CyCAR] = (u_char)(channel); /* index channel */
 353        base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
 354    restore_flags(flags);
 355
 356    return;
 357} /* cy_stop */
 358
 359static void
 360cy_start(struct tty_struct *tty)
 361{
 362  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
 363  volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
 364  int channel;
 365  unsigned long flags;
 366
 367#ifdef SERIAL_DEBUG_OTHER
 368    printk("cy_start ttyS%d\n", info->line); /* */
 369#endif
 370
 371    if (serial_paranoia_check(info, tty->device, "cy_start"))
 372        return;
 373        
 374    channel = info->line;
 375
 376    save_flags(flags); cli();
 377        base_addr[CyCAR] = (u_char)(channel);
 378        base_addr[CyIER] |= CyTxMpty;
 379    restore_flags(flags);
 380
 381    return;
 382} /* cy_start */
 383
 384
 385/*
 386 * This routine is used by the interrupt handler to schedule
 387 * processing in the software interrupt portion of the driver
 388 * (also known as the "bottom half").  This can be called any
 389 * number of times for any channel without harm.
 390 */
 391static inline void
 392cy_sched_event(struct cyclades_port *info, int event)
 393{
 394    info->event |= 1 << event; /* remember what kind of event and who */
 395    queue_task(&info->tqueue, &tq_cyclades); /* it belongs to */
 396    mark_bh(CYCLADES_BH);                       /* then trigger event */
 397} /* cy_sched_event */
 398
 399
 400/* The real interrupt service routines are called
 401   whenever the card wants its hand held--chars
 402   received, out buffer empty, modem change, etc.
 403 */
 404static void
 405cd2401_rxerr_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 406{
 407    struct tty_struct *tty;
 408    struct cyclades_port *info;
 409    volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
 410    unsigned char err, rfoc;
 411    int channel;
 412    char data;
 413
 414    /* determine the channel and change to that context */
 415    channel = (u_short ) (base_addr[CyLICR] >> 2);
 416    info = &cy_port[channel];
 417    info->last_active = jiffies;
 418
 419    if ((err = base_addr[CyRISR]) & CyTIMEOUT) {
 420        /* This is a receive timeout interrupt, ignore it */
 421        base_addr[CyREOIR] = CyNOTRANS;
 422        return;
 423    }
 424
 425    /* Read a byte of data if there is any - assume the error
 426     * is associated with this character */
 427
 428    if ((rfoc = base_addr[CyRFOC]) != 0)
 429        data = base_addr[CyRDR];
 430    else
 431        data = 0;
 432
 433    /* if there is nowhere to put the data, discard it */
 434    if(info->tty == 0) {
 435        base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
 436        return;
 437    }
 438    else { /* there is an open port for this data */
 439        tty = info->tty;
 440        if(err & info->ignore_status_mask){
 441            base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
 442            return;
 443        }
 444        if (tty->flip.count < TTY_FLIPBUF_SIZE){
 445            tty->flip.count++;
 446            if (err & info->read_status_mask){
 447                if(err & CyBREAK){
 448                    *tty->flip.flag_buf_ptr++ = TTY_BREAK;
 449                    *tty->flip.char_buf_ptr++ = data;
 450                    if (info->flags & ASYNC_SAK){
 451                        do_SAK(tty);
 452                    }
 453                }else if(err & CyFRAME){
 454                    *tty->flip.flag_buf_ptr++ = TTY_FRAME;
 455                    *tty->flip.char_buf_ptr++ = data;
 456                }else if(err & CyPARITY){
 457                    *tty->flip.flag_buf_ptr++ = TTY_PARITY;
 458                    *tty->flip.char_buf_ptr++ = data;
 459                }else if(err & CyOVERRUN){
 460                    *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
 461                    *tty->flip.char_buf_ptr++ = 0;
 462                    /*
 463                       If the flip buffer itself is
 464                       overflowing, we still loose
 465                       the next incoming character.
 466                     */
 467                    if(tty->flip.count < TTY_FLIPBUF_SIZE){
 468                        tty->flip.count++;
 469                        *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
 470                        *tty->flip.char_buf_ptr++ = data;
 471                    }
 472                /* These two conditions may imply */
 473                /* a normal read should be done. */
 474                /* else if(data & CyTIMEOUT) */
 475                /* else if(data & CySPECHAR) */
 476                }else{
 477                    *tty->flip.flag_buf_ptr++ = 0;
 478                    *tty->flip.char_buf_ptr++ = 0;
 479                }
 480            }else{
 481                *tty->flip.flag_buf_ptr++ = 0;
 482                *tty->flip.char_buf_ptr++ = 0;
 483            }
 484        }else{
 485            /* there was a software buffer overrun
 486               and nothing could be done about it!!! */
 487        }
 488    }
 489    queue_task(&tty->flip.tqueue, &tq_timer);
 490    /* end of service */
 491    base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
 492} /* cy_rxerr_interrupt */
 493
 494static void
 495cd2401_modem_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 496{
 497    struct cyclades_port *info;
 498    volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
 499    int channel;
 500    int mdm_change;
 501    int mdm_status;
 502
 503
 504    /* determine the channel and change to that context */
 505    channel = (u_short ) (base_addr[CyLICR] >> 2);
 506    info = &cy_port[channel];
 507    info->last_active = jiffies;
 508
 509    mdm_change = base_addr[CyMISR];
 510    mdm_status = base_addr[CyMSVR1];
 511
 512    if(info->tty == 0){ /* nowhere to put the data, ignore it */
 513        ;
 514    }else{
 515        if((mdm_change & CyDCD)
 516        && (info->flags & ASYNC_CHECK_CD)){
 517            if(mdm_status & CyDCD){
 518/* CP('!'); */
 519                cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP);
 520            }else if(!((info->flags & ASYNC_CALLOUT_ACTIVE)
 521                     &&(info->flags & ASYNC_CALLOUT_NOHUP))){
 522/* CP('@'); */
 523                cy_sched_event(info, Cy_EVENT_HANGUP);
 524            }
 525        }
 526        if((mdm_change & CyCTS)
 527        && (info->flags & ASYNC_CTS_FLOW)){
 528            if(info->tty->stopped){
 529                if(mdm_status & CyCTS){
 530                    /* !!! cy_start isn't used because... */
 531                    info->tty->stopped = 0;
 532                    base_addr[CyIER] |= CyTxMpty;
 533                    cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
 534                }
 535            }else{
 536                if(!(mdm_status & CyCTS)){
 537                    /* !!! cy_stop isn't used because... */
 538                    info->tty->stopped = 1;
 539                    base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
 540                }
 541            }
 542        }
 543        if(mdm_status & CyDSR){
 544        }
 545    }
 546    base_addr[CyMEOIR] = 0;
 547} /* cy_modem_interrupt */
 548
 549static void
 550cd2401_tx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 551{
 552    struct cyclades_port *info;
 553    volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
 554    int channel;
 555    int char_count, saved_cnt;
 556    int outch;
 557
 558    /* determine the channel and change to that context */
 559    channel = (u_short ) (base_addr[CyLICR] >> 2);
 560
 561#ifdef CONFIG_REMOTE_DEBUG
 562    if (channel == DEBUG_PORT) {
 563        panic ("TxInt on debug port!!!");
 564    }
 565#endif
 566
 567    info = &cy_port[channel];
 568
 569    /* validate the port number (as configured and open) */
 570    if( (channel < 0) || (NR_PORTS <= channel) ){
 571        base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
 572        base_addr[CyTEOIR] = CyNOTRANS;
 573        return;
 574    }
 575    info->last_active = jiffies;
 576    if(info->tty == 0){
 577        base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
 578        if (info->xmit_cnt < WAKEUP_CHARS) {
 579            cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
 580        }
 581        base_addr[CyTEOIR] = CyNOTRANS;
 582        return;
 583    }
 584
 585    /* load the on-chip space available for outbound data */
 586    saved_cnt = char_count = base_addr[CyTFTC];
 587
 588    if(info->x_char) { /* send special char */
 589        outch = info->x_char;
 590        base_addr[CyTDR] = outch;
 591        char_count--;
 592        info->x_char = 0;
 593    }
 594
 595    if (info->x_break){
 596        /*  The Cirrus chip requires the "Embedded Transmit
 597            Commands" of start break, delay, and end break
 598            sequences to be sent.  The duration of the
 599            break is given in TICs, which runs at HZ
 600            (typically 100) and the PPR runs at 200 Hz,
 601            so the delay is duration * 200/HZ, and thus a
 602            break can run from 1/100 sec to about 5/4 sec.
 603            Need to check these values - RGH 141095.
 604         */
 605        base_addr[CyTDR] = 0; /* start break */
 606        base_addr[CyTDR] = 0x81;
 607        base_addr[CyTDR] = 0; /* delay a bit */
 608        base_addr[CyTDR] = 0x82;
 609        base_addr[CyTDR] = info->x_break*200/HZ;
 610        base_addr[CyTDR] = 0; /* terminate break */
 611        base_addr[CyTDR] = 0x83;
 612        char_count -= 7;
 613        info->x_break = 0;
 614    }
 615
 616    while (char_count > 0){
 617        if (!info->xmit_cnt){
 618            base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
 619            break;
 620        }
 621        if (info->xmit_buf == 0){
 622            base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
 623            break;
 624        }
 625        if (info->tty->stopped || info->tty->hw_stopped){
 626            base_addr[CyIER] &= ~(CyTxMpty|CyTxRdy);
 627            break;
 628        }
 629        /* Because the Embedded Transmit Commands have been
 630           enabled, we must check to see if the escape
 631           character, NULL, is being sent.  If it is, we
 632           must ensure that there is room for it to be
 633           doubled in the output stream.  Therefore we
 634           no longer advance the pointer when the character
 635           is fetched, but rather wait until after the check
 636           for a NULL output character. (This is necessary
 637           because there may not be room for the two chars
 638           needed to send a NULL.
 639         */
 640        outch = info->xmit_buf[info->xmit_tail];
 641        if( outch ){
 642            info->xmit_cnt--;
 643            info->xmit_tail = (info->xmit_tail + 1)
 644                                      & (PAGE_SIZE - 1);
 645            base_addr[CyTDR] = outch;
 646            char_count--;
 647        }else{
 648            if(char_count > 1){
 649                info->xmit_cnt--;
 650                info->xmit_tail = (info->xmit_tail + 1)
 651                                          & (PAGE_SIZE - 1);
 652                base_addr[CyTDR] = outch;
 653                base_addr[CyTDR] = 0;
 654                char_count--;
 655                char_count--;
 656            }else{
 657                break;
 658            }
 659        }
 660    }
 661
 662    if (info->xmit_cnt < WAKEUP_CHARS) {
 663        cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
 664    }
 665    base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
 666} /* cy_tx_interrupt */
 667
 668static void
 669cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 670{
 671    struct tty_struct *tty;
 672    struct cyclades_port *info;
 673    volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
 674    int channel;
 675    char data;
 676    int char_count;
 677    int save_cnt;
 678
 679    /* determine the channel and change to that context */
 680    channel = (u_short ) (base_addr[CyLICR] >> 2);
 681    info = &cy_port[channel];
 682    info->last_active = jiffies;
 683    save_cnt = char_count = base_addr[CyRFOC];
 684
 685#ifdef CONFIG_REMOTE_DEBUG
 686    if (channel == DEBUG_PORT) {
 687        while (char_count--) {
 688            data = base_addr[CyRDR];
 689            queueDebugChar(data);
 690        }
 691    }
 692    else
 693#endif
 694    /* if there is nowhere to put the data, discard it */
 695    if(info->tty == 0){
 696        while(char_count--){
 697            data = base_addr[CyRDR];
 698        }
 699    }else{ /* there is an open port for this data */
 700        tty = info->tty;
 701        /* load # characters available from the chip */
 702
 703#ifdef CYCLOM_ENABLE_MONITORING
 704        ++info->mon.int_count;
 705        info->mon.char_count += char_count;
 706        if (char_count > info->mon.char_max)
 707            info->mon.char_max = char_count;
 708        info->mon.char_last = char_count;
 709#endif
 710        while(char_count--){
 711            data = base_addr[CyRDR];
 712            if (tty->flip.count >= TTY_FLIPBUF_SIZE){
 713                continue;
 714            }
 715            tty->flip.count++;
 716            *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
 717            *tty->flip.char_buf_ptr++ = data;
 718#ifdef CYCLOM_16Y_HACK
 719            udelay(10L);
 720#endif
 721        }
 722        queue_task(&tty->flip.tqueue, &tq_timer);
 723    }
 724    /* end of service */
 725    base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
 726} /* cy_rx_interrupt */
 727
 728/*
 729 * This routine is used to handle the "bottom half" processing for the
 730 * serial driver, known also the "software interrupt" processing.
 731 * This processing is done at the kernel interrupt level, after the
 732 * cy_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
 733 * is where time-consuming activities which can not be done in the
 734 * interrupt driver proper are done; the interrupt driver schedules
 735 * them using cy_sched_event(), and they get done here.
 736 *
 737 * This is done through one level of indirection--the task queue.
 738 * When a hardware interrupt service routine wants service by the
 739 * driver's bottom half, it enqueues the appropriate tq_struct (one
 740 * per port) to the tq_cyclades work queue and sets a request flag
 741 * via mark_bh for processing that queue.  When the time is right,
 742 * do_cyclades_bh is called (because of the mark_bh) and it requests
 743 * that the work queue be processed.
 744 *
 745 * Although this may seem unwieldy, it gives the system a way to
 746 * pass an argument (in this case the pointer to the cyclades_port
 747 * structure) to the bottom half of the driver.  Previous kernels
 748 * had to poll every port to see if that port needed servicing.
 749 */
 750static void
 751do_cyclades_bh(void)
 752{
 753    run_task_queue(&tq_cyclades);
 754} /* do_cyclades_bh */
 755
 756static void
 757do_softint(void *private_)
 758{
 759  struct cyclades_port *info = (struct cyclades_port *) private_;
 760  struct tty_struct    *tty;
 761
 762    tty = info->tty;
 763    if (!tty)
 764        return;
 765
 766    if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
 767        tty_hangup(info->tty);
 768        wake_up_interruptible(&info->open_wait);
 769        info->flags &= ~(ASYNC_NORMAL_ACTIVE|
 770                             ASYNC_CALLOUT_ACTIVE);
 771    }
 772    if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) {
 773        wake_up_interruptible(&info->open_wait);
 774    }
 775    if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
 776        tty_wakeup(tty);
 777    }
 778} /* do_softint */
 779
 780
 781/* This is called whenever a port becomes active;
 782   interrupts are enabled and DTR & RTS are turned on.
 783 */
 784static int
 785startup(struct cyclades_port * info)
 786{
 787  unsigned long flags;
 788  volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
 789  int channel;
 790
 791    if (info->flags & ASYNC_INITIALIZED){
 792        return 0;
 793    }
 794
 795    if (!info->type){
 796        if (info->tty){
 797            set_bit(TTY_IO_ERROR, &info->tty->flags);
 798        }
 799        return 0;
 800    }
 801    if (!info->xmit_buf){
 802        info->xmit_buf = (unsigned char *) get_free_page (GFP_KERNEL);
 803        if (!info->xmit_buf){
 804            return -ENOMEM;
 805        }
 806    }
 807
 808    config_setup(info);
 809
 810    channel = info->line;
 811
 812#ifdef SERIAL_DEBUG_OPEN
 813    printk("startup channel %d\n", channel);
 814#endif
 815
 816    save_flags(flags); cli();
 817        base_addr[CyCAR] = (u_char)channel;
 818        write_cy_cmd(base_addr,CyENB_RCVR|CyENB_XMTR);
 819
 820        base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */
 821        base_addr[CyMSVR1] = CyRTS;
 822/* CP('S');CP('1'); */
 823        base_addr[CyMSVR2] = CyDTR;
 824
 825#ifdef SERIAL_DEBUG_DTR
 826        printk("cyc: %d: raising DTR\n", __LINE__);
 827        printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
 828#endif
 829
 830        base_addr[CyIER] |= CyRxData;
 831        info->flags |= ASYNC_INITIALIZED;
 832
 833        if (info->tty){
 834            clear_bit(TTY_IO_ERROR, &info->tty->flags);
 835        }
 836        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
 837
 838    restore_flags(flags);
 839
 840#ifdef SERIAL_DEBUG_OPEN
 841    printk(" done\n");
 842#endif
 843    return 0;
 844} /* startup */
 845
 846void
 847start_xmit( struct cyclades_port *info )
 848{
 849  unsigned long flags;
 850  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
 851  int channel;
 852
 853    channel = info->line;
 854    save_flags(flags); cli();
 855        base_addr[CyCAR] = channel;
 856        base_addr[CyIER] |= CyTxMpty;
 857    restore_flags(flags);
 858} /* start_xmit */
 859
 860/*
 861 * This routine shuts down a serial port; interrupts are disabled,
 862 * and DTR is dropped if the hangup on close termio flag is on.
 863 */
 864static void
 865shutdown(struct cyclades_port * info)
 866{
 867  unsigned long flags;
 868  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
 869  int channel;
 870
 871    if (!(info->flags & ASYNC_INITIALIZED)){
 872/* CP('$'); */
 873        return;
 874    }
 875
 876    channel = info->line;
 877
 878#ifdef SERIAL_DEBUG_OPEN
 879    printk("shutdown channel %d\n", channel);
 880#endif
 881
 882    /* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE
 883       SENT BEFORE DROPPING THE LINE !!!  (Perhaps
 884       set some flag that is read when XMTY happens.)
 885       Other choices are to delay some fixed interval
 886       or schedule some later processing.
 887     */
 888    save_flags(flags); cli();
 889        if (info->xmit_buf){
 890            free_page((unsigned long) info->xmit_buf);
 891            info->xmit_buf = 0;
 892        }
 893
 894        base_addr[CyCAR] = (u_char)channel;
 895        if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
 896            base_addr[CyMSVR1] = 0;
 897/* CP('C');CP('1'); */
 898            base_addr[CyMSVR2] = 0;
 899#ifdef SERIAL_DEBUG_DTR
 900            printk("cyc: %d: dropping DTR\n", __LINE__);
 901            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
 902#endif
 903        }
 904        write_cy_cmd(base_addr,CyDIS_RCVR);
 905         /* it may be appropriate to clear _XMIT at
 906           some later date (after testing)!!! */
 907
 908        if (info->tty){
 909            set_bit(TTY_IO_ERROR, &info->tty->flags);
 910        }
 911        info->flags &= ~ASYNC_INITIALIZED;
 912    restore_flags(flags);
 913
 914#ifdef SERIAL_DEBUG_OPEN
 915    printk(" done\n");
 916#endif
 917    return;
 918} /* shutdown */
 919
 920/*
 921 * This routine finds or computes the various line characteristics.
 922 */
 923static void
 924config_setup(struct cyclades_port * info)
 925{
 926  unsigned long flags;
 927  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
 928  int channel;
 929  unsigned cflag;
 930  int   i;
 931  unsigned char ti, need_init_chan = 0;
 932
 933    if (!info->tty || !info->tty->termios){
 934        return;
 935    }
 936    if (info->line == -1){
 937        return;
 938    }
 939    cflag = info->tty->termios->c_cflag;
 940
 941    /* baud rate */
 942    i = cflag & CBAUD;
 943#ifdef CBAUDEX
 944/* Starting with kernel 1.1.65, there is direct support for
 945   higher baud rates.  The following code supports those
 946   changes.  The conditional aspect allows this driver to be
 947   used for earlier as well as later kernel versions.  (The
 948   mapping is slightly different from serial.c because there
 949   is still the possibility of supporting 75 kbit/sec with
 950   the Cyclades board.)
 951 */
 952    if (i & CBAUDEX) {
 953        if (i == B57600)
 954            i = 16;
 955        else if(i == B115200) 
 956            i = 18;
 957#ifdef B78600
 958        else if(i == B78600) 
 959            i = 17;
 960#endif
 961        else
 962            info->tty->termios->c_cflag &= ~CBAUDEX;
 963    }
 964#endif
 965    if (i == 15) {
 966            if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
 967                    i += 1;
 968            if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
 969                    i += 3;
 970    }
 971    /* Don't ever change the speed of the console port.  It will
 972     * run at the speed specified in bootinfo, or at 19.2K */
 973    /* Actually, it should run at whatever speed 166Bug was using */
 974    /* Note info->timeout isn't used at present */
 975    if (info != serial_console_info) {
 976        info->tbpr = baud_bpr[i]; /* Tx BPR */
 977        info->tco = baud_co[i]; /* Tx CO */
 978        info->rbpr = baud_bpr[i]; /* Rx BPR */
 979        info->rco = baud_co[i] >> 5; /* Rx CO */
 980        if (baud_table[i] == 134) {
 981            info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
 982            /* get it right for 134.5 baud */
 983        } else if (baud_table[i]) {
 984            info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2;
 985        /* this needs to be propagated into the card info */
 986        } else {
 987            info->timeout = 0;
 988        }
 989    }
 990    /* By tradition (is it a standard?) a baud rate of zero
 991       implies the line should be/has been closed.  A bit
 992       later in this routine such a test is performed. */
 993
 994    /* byte size and parity */
 995    info->cor7 = 0;
 996    info->cor6 = 0;
 997    info->cor5 = 0;
 998    info->cor4 = (info->default_threshold
 999                  ? info->default_threshold
1000                  : baud_cor4[i]); /* receive threshold */
1001    /* Following two lines added 101295, RGH. */
1002    /* It is obviously wrong to access CyCORx, and not info->corx here,
1003     * try and remember to fix it later! */
1004    channel = info->line;
1005    base_addr[CyCAR] = (u_char)channel;
1006    if (C_CLOCAL(info->tty)) {
1007        if (base_addr[CyIER] & CyMdmCh)
1008            base_addr[CyIER] &= ~CyMdmCh; /* without modem intr */
1009                               /* ignore 1->0 modem transitions */
1010        if (base_addr[CyCOR4] & (CyDSR|CyCTS|CyDCD))
1011            base_addr[CyCOR4] &= ~(CyDSR|CyCTS|CyDCD);
1012                               /* ignore 0->1 modem transitions */
1013        if (base_addr[CyCOR5] & (CyDSR|CyCTS|CyDCD))
1014            base_addr[CyCOR5] &= ~(CyDSR|CyCTS|CyDCD);
1015    } else {
1016        if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh)
1017            base_addr[CyIER] |= CyMdmCh; /* with modem intr */
1018                               /* act on 1->0 modem transitions */
1019        if ((base_addr[CyCOR4] & (CyDSR|CyCTS|CyDCD)) != (CyDSR|CyCTS|CyDCD))
1020            base_addr[CyCOR4] |= CyDSR|CyCTS|CyDCD;
1021                               /* act on 0->1 modem transitions */
1022        if ((base_addr[CyCOR5] & (CyDSR|CyCTS|CyDCD)) != (CyDSR|CyCTS|CyDCD))
1023            base_addr[CyCOR5] |= CyDSR|CyCTS|CyDCD;
1024    }
1025    info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP;
1026    info->cor2 = CyETC;
1027    switch(cflag & CSIZE){
1028    case CS5:
1029        info->cor1 = Cy_5_BITS;
1030        break;
1031    case CS6:
1032        info->cor1 = Cy_6_BITS;
1033        break;
1034    case CS7:
1035        info->cor1 = Cy_7_BITS;
1036        break;
1037    case CS8:
1038        info->cor1 = Cy_8_BITS;
1039        break;
1040    }
1041    if (cflag & PARENB){
1042        if (cflag & PARODD){
1043            info->cor1 |= CyPARITY_O;
1044        }else{
1045            info->cor1 |= CyPARITY_E;
1046        }
1047    }else{
1048        info->cor1 |= CyPARITY_NONE;
1049    }
1050        
1051    /* CTS flow control flag */
1052#if 0
1053    /* Don't complcate matters for now! RGH 141095 */
1054    if (cflag & CRTSCTS){
1055        info->flags |= ASYNC_CTS_FLOW;
1056        info->cor2 |= CyCtsAE;
1057    }else{
1058        info->flags &= ~ASYNC_CTS_FLOW;
1059        info->cor2 &= ~CyCtsAE;
1060    }
1061#endif
1062    if (cflag & CLOCAL)
1063        info->flags &= ~ASYNC_CHECK_CD;
1064    else
1065        info->flags |= ASYNC_CHECK_CD;
1066
1067     /***********************************************
1068        The hardware option, CyRtsAO, presents RTS when
1069        the chip has characters to send.  Since most modems
1070        use RTS as reverse (inbound) flow control, this
1071        option is not used.  If inbound flow control is
1072        necessary, DTR can be programmed to provide the
1073        appropriate signals for use with a non-standard
1074        cable.  Contact Marcio Saito for details.
1075     ***********************************************/
1076
1077    channel = info->line;
1078
1079    save_flags(flags); cli();
1080        base_addr[CyCAR] = (u_char)channel;
1081
1082        /* CyCMR set once only in mvme167_init_serial() */
1083        if (base_addr[CyLICR] != channel << 2)
1084            base_addr[CyLICR] = channel << 2;
1085        if (base_addr[CyLIVR] != 0x5c)
1086            base_addr[CyLIVR] = 0x5c;
1087
1088       /* tx and rx baud rate */
1089
1090        if (base_addr[CyCOR1] != info->cor1)
1091            need_init_chan = 1;
1092        if (base_addr[CyTCOR] != info->tco)
1093            base_addr[CyTCOR] = info->tco;
1094        if (base_addr[CyTBPR] != info->tbpr)
1095            base_addr[CyTBPR] = info->tbpr;
1096        if (base_addr[CyRCOR] != info->rco)
1097            base_addr[CyRCOR] = info->rco;
1098        if (base_addr[CyRBPR] != info->rbpr)
1099            base_addr[CyRBPR] = info->rbpr;
1100
1101        /* set line characteristics  according configuration */
1102
1103        if (base_addr[CySCHR1] != START_CHAR(info->tty))
1104            base_addr[CySCHR1] = START_CHAR(info->tty);
1105        if (base_addr[CySCHR2] != STOP_CHAR(info->tty))
1106            base_addr[CySCHR2] = STOP_CHAR(info->tty);
1107        if (base_addr[CySCRL] != START_CHAR(info->tty))
1108            base_addr[CySCRL] = START_CHAR(info->tty);
1109        if (base_addr[CySCRH] != START_CHAR(info->tty))
1110            base_addr[CySCRH] = START_CHAR(info->tty);
1111        if (base_addr[CyCOR1] != info->cor1)
1112            base_addr[CyCOR1] = info->cor1;
1113        if (base_addr[CyCOR2] != info->cor2)
1114            base_addr[CyCOR2] = info->cor2;
1115        if (base_addr[CyCOR3] != info->cor3)
1116            base_addr[CyCOR3] = info->cor3;
1117        if (base_addr[CyCOR4] != info->cor4)
1118            base_addr[CyCOR4] = info->cor4;
1119        if (base_addr[CyCOR5] != info->cor5)
1120            base_addr[CyCOR5] = info->cor5;
1121        if (base_addr[CyCOR6] != info->cor6)
1122            base_addr[CyCOR6] = info->cor6;
1123        if (base_addr[CyCOR7] != info->cor7)
1124            base_addr[CyCOR7] = info->cor7;
1125
1126        if (need_init_chan)
1127            write_cy_cmd(base_addr,CyINIT_CHAN);
1128
1129        base_addr[CyCAR] = (u_char)channel; /* !!! Is this needed? */
1130
1131        /* 2ms default rx timeout */
1132        ti = info->default_timeout ? info->default_timeout : 0x02;
1133        if (base_addr[CyRTPRL] != ti)
1134            base_addr[CyRTPRL] = ti;
1135        if (base_addr[CyRTPRH] != 0)
1136            base_addr[CyRTPRH] = 0;
1137
1138        /* Set up RTS here also ????? RGH 141095 */
1139        if(i == 0){ /* baud rate is zero, turn off line */
1140            if ((base_addr[CyMSVR2] & CyDTR) == CyDTR)
1141                base_addr[CyMSVR2] = 0;
1142#ifdef SERIAL_DEBUG_DTR
1143            printk("cyc: %d: dropping DTR\n", __LINE__);
1144            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
1145#endif
1146        }else{
1147            if ((base_addr[CyMSVR2] & CyDTR) != CyDTR)
1148                base_addr[CyMSVR2] = CyDTR;
1149#ifdef SERIAL_DEBUG_DTR
1150            printk("cyc: %d: raising DTR\n", __LINE__);
1151            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
1152#endif
1153        }
1154
1155        if (info->tty){
1156            clear_bit(TTY_IO_ERROR, &info->tty->flags);
1157        }
1158
1159    restore_flags(flags);
1160
1161} /* config_setup */
1162
1163
1164static void
1165cy_put_char(struct tty_struct *tty, unsigned char ch)
1166{
1167  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1168  unsigned long flags;
1169
1170#ifdef SERIAL_DEBUG_IO
1171    printk("cy_put_char ttyS%d(0x%02x)\n", info->line, ch);
1172#endif
1173
1174    if (serial_paranoia_check(info, tty->device, "cy_put_char"))
1175        return;
1176
1177    if (!tty || !info->xmit_buf)
1178        return;
1179
1180    save_flags(flags); cli();
1181        if (info->xmit_cnt >= PAGE_SIZE - 1) {
1182            restore_flags(flags);
1183            return;
1184        }
1185
1186        info->xmit_buf[info->xmit_head++] = ch;
1187        info->xmit_head &= PAGE_SIZE - 1;
1188        info->xmit_cnt++;
1189    restore_flags(flags);
1190} /* cy_put_char */
1191
1192
1193static void
1194cy_flush_chars(struct tty_struct *tty)
1195{
1196  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1197  unsigned long flags;
1198  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
1199  int channel;
1200                                
1201#ifdef SERIAL_DEBUG_IO
1202    printk("cy_flush_chars ttyS%d\n", info->line); /* */
1203#endif
1204
1205    if (serial_paranoia_check(info, tty->device, "cy_flush_chars"))
1206        return;
1207
1208    if (info->xmit_cnt <= 0 || tty->stopped
1209    || tty->hw_stopped || !info->xmit_buf)
1210        return;
1211
1212    channel = info->line;
1213
1214    save_flags(flags); cli();
1215        base_addr[CyCAR] = channel;
1216        base_addr[CyIER] |= CyTxMpty;
1217    restore_flags(flags);
1218} /* cy_flush_chars */
1219
1220
1221/* This routine gets called when tty_write has put something into
1222    the write_queue.  If the port is not already transmitting stuff,
1223    start it off by enabling interrupts.  The interrupt service
1224    routine will then ensure that the characters are sent.  If the
1225    port is already active, there is no need to kick it.
1226 */
1227static int
1228cy_write(struct tty_struct * tty, int from_user,
1229           const unsigned char *buf, int count)
1230{
1231  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1232  unsigned long flags;
1233  int c, total = 0;
1234
1235#ifdef SERIAL_DEBUG_IO
1236    printk("cy_write ttyS%d\n", info->line); /* */
1237#endif
1238
1239    if (serial_paranoia_check(info, tty->device, "cy_write")){
1240        return 0;
1241    }
1242        
1243    if (!tty || !info->xmit_buf || !tmp_buf){
1244        return 0;
1245    }
1246
1247    if (from_user) {
1248            down(&tmp_buf_sem);
1249            while (1) {
1250                    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1251                                       SERIAL_XMIT_SIZE - info->xmit_head));
1252                    if (c <= 0)
1253                            break;
1254
1255                    c -= copy_from_user(tmp_buf, buf, c);
1256                    if (!c) {
1257                            if (!total)
1258                                    total = -EFAULT;
1259                            break;
1260                    }
1261
1262                    save_flags(flags); cli();           
1263                    c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1264                                   SERIAL_XMIT_SIZE - info->xmit_head));
1265                    memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
1266                    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1267                    info->xmit_cnt += c;
1268                    restore_flags(flags);
1269
1270                    buf += c;
1271                    count -= c;
1272                    total += c;
1273            }
1274            up(&tmp_buf_sem);
1275    } else {
1276            while (1) {
1277                    save_flags(flags); cli();           
1278                    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
1279                                       SERIAL_XMIT_SIZE - info->xmit_head));
1280                    if (c <= 0) {
1281                            restore_flags(flags);
1282                            break;
1283                    }
1284
1285                    memcpy(info->xmit_buf + info->xmit_head, buf, c);
1286                    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
1287                    info->xmit_cnt += c;
1288                    restore_flags(flags);
1289
1290                    buf += c;
1291                    count -= c;
1292                    total += c;
1293            }
1294    }
1295
1296    if (info->xmit_cnt
1297    && !tty->stopped
1298    && !tty->hw_stopped ) {
1299        start_xmit(info);
1300    }
1301    return total;
1302} /* cy_write */
1303
1304
1305static int
1306cy_write_room(struct tty_struct *tty)
1307{
1308  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1309  int   ret;
1310                                
1311#ifdef SERIAL_DEBUG_IO
1312    printk("cy_write_room ttyS%d\n", info->line); /* */
1313#endif
1314
1315    if (serial_paranoia_check(info, tty->device, "cy_write_room"))
1316        return 0;
1317    ret = PAGE_SIZE - info->xmit_cnt - 1;
1318    if (ret < 0)
1319        ret = 0;
1320    return ret;
1321} /* cy_write_room */
1322
1323
1324static int
1325cy_chars_in_buffer(struct tty_struct *tty)
1326{
1327  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1328                                
1329#ifdef SERIAL_DEBUG_IO
1330    printk("cy_chars_in_buffer ttyS%d %d\n", info->line, info->xmit_cnt); /* */
1331#endif
1332
1333    if (serial_paranoia_check(info, tty->device, "cy_chars_in_buffer"))
1334        return 0;
1335
1336    return info->xmit_cnt;
1337} /* cy_chars_in_buffer */
1338
1339
1340static void
1341cy_flush_buffer(struct tty_struct *tty)
1342{
1343  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1344  unsigned long flags;
1345                                
1346#ifdef SERIAL_DEBUG_IO
1347    printk("cy_flush_buffer ttyS%d\n", info->line); /* */
1348#endif
1349
1350    if (serial_paranoia_check(info, tty->device, "cy_flush_buffer"))
1351        return;
1352    save_flags(flags); cli();
1353        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
1354    restore_flags(flags);
1355    wake_up_interruptible(&tty->write_wait);
1356    tty_wakeup(tty);
1357} /* cy_flush_buffer */
1358
1359
1360/* This routine is called by the upper-layer tty layer to signal
1361   that incoming characters should be throttled or that the
1362   throttle should be released.
1363 */
1364static void
1365cy_throttle(struct tty_struct * tty)
1366{
1367  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1368  unsigned long flags;
1369  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
1370  int channel;
1371
1372#ifdef SERIAL_DEBUG_THROTTLE
1373  char buf[64];
1374        
1375    printk("throttle %s: %d....\n", tty_name(tty, buf),
1376           tty->ldisc.chars_in_buffer(tty));
1377    printk("cy_throttle ttyS%d\n", info->line);
1378#endif
1379
1380    if (serial_paranoia_check(info, tty->device, "cy_nthrottle")){
1381            return;
1382    }
1383
1384    if (I_IXOFF(tty)) {
1385        info->x_char = STOP_CHAR(tty);
1386            /* Should use the "Send Special Character" feature!!! */
1387    }
1388
1389    channel = info->line;
1390
1391    save_flags(flags); cli();
1392        base_addr[CyCAR] = (u_char)channel;
1393        base_addr[CyMSVR1] = 0;
1394    restore_flags(flags);
1395
1396    return;
1397} /* cy_throttle */
1398
1399
1400static void
1401cy_unthrottle(struct tty_struct * tty)
1402{
1403  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1404  unsigned long flags;
1405  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
1406  int channel;
1407
1408#ifdef SERIAL_DEBUG_THROTTLE
1409  char buf[64];
1410        
1411    printk("throttle %s: %d....\n", tty_name(tty, buf),
1412           tty->ldisc.chars_in_buffer(tty));
1413    printk("cy_unthrottle ttyS%d\n", info->line);
1414#endif
1415
1416    if (serial_paranoia_check(info, tty->device, "cy_nthrottle")){
1417            return;
1418    }
1419
1420    if (I_IXOFF(tty)) {
1421        info->x_char = START_CHAR(tty);
1422        /* Should use the "Send Special Character" feature!!! */
1423    }
1424
1425    channel = info->line;
1426
1427    save_flags(flags); cli();
1428        base_addr[CyCAR] = (u_char)channel;
1429        base_addr[CyMSVR1] = CyRTS;
1430    restore_flags(flags);
1431
1432    return;
1433} /* cy_unthrottle */
1434
1435static int
1436get_serial_info(struct cyclades_port * info,
1437                           struct serial_struct * retinfo)
1438{
1439  struct serial_struct tmp;
1440
1441/* CP('g'); */
1442    if (!retinfo)
1443            return -EFAULT;
1444    memset(&tmp, 0, sizeof(tmp));
1445    tmp.type = info->type;
1446    tmp.line = info->line;
1447    tmp.port = info->line;
1448    tmp.irq = 0;
1449    tmp.flags = info->flags;
1450    tmp.baud_base = 0;          /*!!!*/
1451    tmp.close_delay = info->close_delay;
1452    tmp.custom_divisor = 0;     /*!!!*/
1453    tmp.hub6 = 0;               /*!!!*/
1454    return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0;
1455} /* get_serial_info */
1456
1457static int
1458set_serial_info(struct cyclades_port * info,
1459                           struct serial_struct * new_info)
1460{
1461  struct serial_struct new_serial;
1462  struct cyclades_port old_info;
1463
1464/* CP('s'); */
1465    if (!new_info)
1466            return -EFAULT;
1467    if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
1468            return -EFAULT;
1469    old_info = *info;
1470
1471    if (!suser()) {
1472            if ((new_serial.close_delay != info->close_delay) ||
1473                ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
1474                 (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
1475                    return -EPERM;
1476            info->flags = ((info->flags & ~ASYNC_USR_MASK) |
1477                           (new_serial.flags & ASYNC_USR_MASK));
1478            goto check_and_exit;
1479    }
1480
1481
1482    /*
1483     * OK, past this point, all the error checking has been done.
1484     * At this point, we start making changes.....
1485     */
1486
1487    info->flags = ((info->flags & ~ASYNC_FLAGS) |
1488                    (new_serial.flags & ASYNC_FLAGS));
1489    info->close_delay = new_serial.close_delay;
1490
1491
1492check_and_exit:
1493    if (info->flags & ASYNC_INITIALIZED){
1494        config_setup(info);
1495        return 0;
1496    }else{
1497        return startup(info);
1498    }
1499} /* set_serial_info */
1500
1501static int
1502get_modem_info(struct cyclades_port * info, unsigned int *value)
1503{
1504  int channel;
1505  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
1506  unsigned long flags;
1507  unsigned char status;
1508  unsigned int result;
1509
1510    channel = info->line;
1511
1512    save_flags(flags); cli();
1513        base_addr[CyCAR] = (u_char)channel;
1514        status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
1515    restore_flags(flags);
1516
1517    result =  ((status  & CyRTS) ? TIOCM_RTS : 0)
1518            | ((status  & CyDTR) ? TIOCM_DTR : 0)
1519            | ((status  & CyDCD) ? TIOCM_CAR : 0)
1520            | ((status  & CyDSR) ? TIOCM_DSR : 0)
1521            | ((status  & CyCTS) ? TIOCM_CTS : 0);
1522    return put_user(result,(unsigned int *) value);
1523} /* get_modem_info */
1524
1525static int
1526set_modem_info(struct cyclades_port * info, unsigned int cmd,
1527                          unsigned int *value)
1528{
1529  int channel;
1530  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
1531  unsigned long flags;
1532  unsigned int arg;
1533          
1534    if (get_user(arg, (unsigned long *) value))
1535        return -EFAULT;
1536    channel = info->line;
1537
1538    switch (cmd) {
1539    case TIOCMBIS:
1540        if (arg & TIOCM_RTS){
1541            save_flags(flags); cli();
1542                base_addr[CyCAR] = (u_char)channel;
1543                base_addr[CyMSVR1] = CyRTS;
1544            restore_flags(flags);
1545        }
1546        if (arg & TIOCM_DTR){
1547            save_flags(flags); cli();
1548            base_addr[CyCAR] = (u_char)channel;
1549/* CP('S');CP('2'); */
1550            base_addr[CyMSVR2] = CyDTR;
1551#ifdef SERIAL_DEBUG_DTR
1552            printk("cyc: %d: raising DTR\n", __LINE__);
1553            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
1554#endif
1555            restore_flags(flags);
1556        }
1557        break;
1558    case TIOCMBIC:
1559        if (arg & TIOCM_RTS){
1560            save_flags(flags); cli();
1561                base_addr[CyCAR] = (u_char)channel;
1562                base_addr[CyMSVR1] = 0;
1563            restore_flags(flags);
1564        }
1565        if (arg & TIOCM_DTR){
1566            save_flags(flags); cli();
1567            base_addr[CyCAR] = (u_char)channel;
1568/* CP('C');CP('2'); */
1569            base_addr[CyMSVR2] = 0;
1570#ifdef SERIAL_DEBUG_DTR
1571            printk("cyc: %d: dropping DTR\n", __LINE__);
1572            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
1573#endif
1574            restore_flags(flags);
1575        }
1576        break;
1577    case TIOCMSET:
1578        if (arg & TIOCM_RTS){
1579            save_flags(flags); cli();
1580                base_addr[CyCAR] = (u_char)channel;
1581                base_addr[CyMSVR1] = CyRTS;
1582            restore_flags(flags);
1583        }else{
1584            save_flags(flags); cli();
1585                base_addr[CyCAR] = (u_char)channel;
1586                base_addr[CyMSVR1] = 0;
1587            restore_flags(flags);
1588        }
1589        if (arg & TIOCM_DTR){
1590            save_flags(flags); cli();
1591            base_addr[CyCAR] = (u_char)channel;
1592/* CP('S');CP('3'); */
1593            base_addr[CyMSVR2] = CyDTR;
1594#ifdef SERIAL_DEBUG_DTR
1595            printk("cyc: %d: raising DTR\n", __LINE__);
1596            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
1597#endif
1598            restore_flags(flags);
1599        }else{
1600            save_flags(flags); cli();
1601            base_addr[CyCAR] = (u_char)channel;
1602/* CP('C');CP('3'); */
1603            base_addr[CyMSVR2] = 0;
1604#ifdef SERIAL_DEBUG_DTR
1605            printk("cyc: %d: dropping DTR\n", __LINE__);
1606            printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
1607#endif
1608            restore_flags(flags);
1609        }
1610        break;
1611    default:
1612                return -EINVAL;
1613        }
1614    return 0;
1615} /* set_modem_info */
1616
1617static void
1618send_break( struct cyclades_port * info, int duration)
1619{ /* Let the transmit ISR take care of this (since it
1620     requires stuffing characters into the output stream).
1621   */
1622    info->x_break = duration;
1623    if (!info->xmit_cnt ) {
1624        start_xmit(info);
1625    }
1626} /* send_break */
1627
1628static int
1629get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
1630{
1631
1632   if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
1633           return -EFAULT;
1634   info->mon.int_count  = 0;
1635   info->mon.char_count = 0;
1636   info->mon.char_max   = 0;
1637   info->mon.char_last  = 0;
1638   return 0;
1639}
1640
1641static int
1642set_threshold(struct cyclades_port * info, unsigned long *arg)
1643{
1644   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
1645   unsigned long value;
1646   int channel;
1647   
1648   if (get_user(value, arg))
1649           return -EFAULT;
1650
1651   channel = info->line;
1652   info->cor4 &= ~CyREC_FIFO;
1653   info->cor4 |= value & CyREC_FIFO;
1654   base_addr[CyCOR4] = info->cor4;
1655   return 0;
1656}
1657
1658static int
1659get_threshold(struct cyclades_port * info, unsigned long *value)
1660{
1661   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
1662   int channel;
1663   unsigned long tmp;
1664   
1665   channel = info->line;
1666
1667   tmp = base_addr[CyCOR4] & CyREC_FIFO;
1668   return put_user(tmp,value);
1669}
1670
1671static int
1672set_default_threshold(struct cyclades_port * info, unsigned long *arg)
1673{
1674   unsigned long value;
1675
1676   if (get_user(value, arg))
1677        return -EFAULT;
1678
1679   info->default_threshold = value & 0x0f;
1680   return 0;
1681}
1682
1683static int
1684get_default_threshold(struct cyclades_port * info, unsigned long *value)
1685{
1686   return put_user(info->default_threshold,value);
1687}
1688
1689static int
1690set_timeout(struct cyclades_port * info, unsigned long *arg)
1691{
1692   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
1693   int channel;
1694   unsigned long value;
1695
1696   if (get_user(value, arg))
1697           return -EFAULT;
1698   
1699   channel = info->line;
1700
1701   base_addr[CyRTPRL] = value & 0xff;
1702   base_addr[CyRTPRH] = (value >> 8) & 0xff;
1703   return 0;
1704}
1705
1706static int
1707get_timeout(struct cyclades_port * info, unsigned long *value)
1708{
1709   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
1710   int channel;
1711   unsigned long tmp;
1712   
1713   channel = info->line;
1714
1715   tmp = base_addr[CyRTPRL];
1716   return put_user(tmp,value);
1717}
1718
1719static int
1720set_default_timeout(struct cyclades_port * info, unsigned long value)
1721{
1722   info->default_timeout = value & 0xff;
1723   return 0;
1724}
1725
1726static int
1727get_default_timeout(struct cyclades_port * info, unsigned long *value)
1728{
1729   return put_user(info->default_timeout,value);
1730}
1731
1732static int
1733cy_ioctl(struct tty_struct *tty, struct file * file,
1734            unsigned int cmd, unsigned long arg)
1735{
1736  unsigned long val;
1737  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
1738  int ret_val = 0;
1739
1740#ifdef SERIAL_DEBUG_OTHER
1741    printk("cy_ioctl ttyS%d, cmd = %x arg = %lx\n", info->line, cmd, arg); /* */
1742#endif
1743
1744    switch (cmd) {
1745        case CYGETMON:
1746            ret_val = get_mon_info(info, (struct cyclades_monitor *)arg);
1747            break;
1748        case CYGETTHRESH:
1749            ret_val = get_threshold(info, (unsigned long *)arg);
1750            break;
1751        case CYSETTHRESH:
1752            ret_val = set_threshold(info, (unsigned long *)arg);
1753            break;
1754        case CYGETDEFTHRESH:
1755            ret_val = get_default_threshold(info, (unsigned long *)arg);
1756            break;
1757        case CYSETDEFTHRESH:
1758            ret_val = set_default_threshold(info, (unsigned long *)arg);
1759            break;
1760        case CYGETTIMEOUT:
1761            ret_val = get_timeout(info, (unsigned long *)arg);
1762            break;
1763        case CYSETTIMEOUT:
1764            ret_val = set_timeout(info, (unsigned long *)arg);
1765            break;
1766        case CYGETDEFTIMEOUT:
1767            ret_val = get_default_timeout(info, (unsigned long *)arg);
1768            break;
1769        case CYSETDEFTIMEOUT:
1770            ret_val = set_default_timeout(info, (unsigned long)arg);
1771            break;
1772        case TCSBRK:    /* SVID version: non-zero arg --> no break */
1773            ret_val = tty_check_change(tty);
1774            if (ret_val)
1775                    break;
1776            tty_wait_until_sent(tty,0);
1777            if (!arg)
1778                send_break(info, HZ/4); /* 1/4 second */
1779            break;
1780        case TCSBRKP:   /* support for POSIX tcsendbreak() */
1781            ret_val = tty_check_change(tty);
1782            if (ret_val)
1783                break;
1784            tty_wait_until_sent(tty,0);
1785            send_break(info, arg ? arg*(HZ/10) : HZ/4);
1786            break;
1787        case TIOCMBIS:
1788        case TIOCMBIC:
1789        case TIOCMSET:
1790            ret_val = set_modem_info(info, cmd, (unsigned int *) arg);
1791            break;
1792
1793/* The following commands are incompletely implemented!!! */
1794        case TIOCGSOFTCAR:
1795            ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
1796            break;
1797        case TIOCSSOFTCAR:
1798            ret_val = get_user(val, (unsigned long *) arg);
1799            if (ret_val)
1800                    break;
1801            tty->termios->c_cflag =
1802                    ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0));
1803            break;
1804        case TIOCMGET:
1805            ret_val = get_modem_info(info, (unsigned int *) arg);
1806            break;
1807        case TIOCGSERIAL:
1808            ret_val = get_serial_info(info, (struct serial_struct *) arg);
1809            break;
1810        case TIOCSSERIAL:
1811            ret_val = set_serial_info(info,
1812                                   (struct serial_struct *) arg);
1813            break;
1814        default:
1815            ret_val = -ENOIOCTLCMD;
1816    }
1817
1818#ifdef SERIAL_DEBUG_OTHER
1819    printk("cy_ioctl done\n");
1820#endif
1821
1822    return ret_val;
1823} /* cy_ioctl */
1824
1825
1826
1827
1828static void
1829cy_set_termios(struct tty_struct *tty, struct termios * old_termios)
1830{
1831  struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
1832
1833#ifdef SERIAL_DEBUG_OTHER
1834    printk("cy_set_termios ttyS%d\n", info->line);
1835#endif
1836
1837    if (tty->termios->c_cflag == old_termios->c_cflag)
1838        return;
1839    config_setup(info);
1840
1841    if ((old_termios->c_cflag & CRTSCTS) &&
1842        !(tty->termios->c_cflag & CRTSCTS)) {
1843            tty->stopped = 0;
1844            cy_start(tty);
1845    }
1846#ifdef tytso_patch_94Nov25_1726
1847    if (!(old_termios->c_cflag & CLOCAL) &&
1848        (tty->termios->c_cflag & CLOCAL))
1849            wake_up_interruptible(&info->open_wait);
1850#endif
1851
1852    return;
1853} /* cy_set_termios */
1854
1855
1856static void
1857cy_close(struct tty_struct * tty, struct file * filp)
1858{
1859  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
1860
1861/* CP('C'); */
1862#ifdef SERIAL_DEBUG_OTHER
1863    printk("cy_close ttyS%d\n", info->line);
1864#endif
1865
1866    if (!info
1867    || serial_paranoia_check(info, tty->device, "cy_close")){
1868        return;
1869    }
1870#ifdef SERIAL_DEBUG_OPEN
1871    printk("cy_close ttyS%d, count = %d\n", info->line, info->count);
1872#endif
1873
1874    if ((tty->count == 1) && (info->count != 1)) {
1875        /*
1876         * Uh, oh.  tty->count is 1, which means that the tty
1877         * structure will be freed.  Info->count should always
1878         * be one in these conditions.  If it's greater than
1879         * one, we've got real problems, since it means the
1880         * serial port won't be shutdown.
1881         */
1882        printk("cy_close: bad serial port count; tty->count is 1, "
1883           "info->count is %d\n", info->count);
1884        info->count = 1;
1885    }
1886#ifdef SERIAL_DEBUG_COUNT
1887    printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count - 1);
1888#endif
1889    if (--info->count < 0) {
1890        printk("cy_close: bad serial port count for ttys%d: %d\n",
1891               info->line, info->count);
1892#ifdef SERIAL_DEBUG_COUNT
1893    printk("cyc: %d: setting count to 0\n", __LINE__);
1894#endif
1895        info->count = 0;
1896    }
1897    if (info->count)
1898        return;
1899    info->flags |= ASYNC_CLOSING;
1900    /*
1901     * Save the termios structure, since this port may have
1902     * separate termios for callout and dialin.
1903     */
1904    if (info->flags & ASYNC_NORMAL_ACTIVE)
1905        info->normal_termios = *tty->termios;
1906    if (info->flags & ASYNC_CALLOUT_ACTIVE)
1907        info->callout_termios = *tty->termios;
1908    if (info->flags & ASYNC_INITIALIZED)
1909        tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
1910    shutdown(info);
1911    if (tty->driver.flush_buffer)
1912        tty->driver.flush_buffer(tty);
1913    tty_ldisc_flush(tty);
1914    info->event = 0;
1915    info->tty = 0;
1916    if (info->blocked_open) {
1917        if (info->close_delay) {
1918            current->state = TASK_INTERRUPTIBLE;
1919            schedule_timeout(info->close_delay);
1920        }
1921        wake_up_interruptible(&info->open_wait);
1922    }
1923    info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
1924                     ASYNC_CLOSING);
1925    wake_up_interruptible(&info->close_wait);
1926
1927#ifdef SERIAL_DEBUG_OTHER
1928    printk("cy_close done\n");
1929#endif
1930
1931    return;
1932} /* cy_close */
1933
1934/*
1935 * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
1936 */
1937void
1938cy_hangup(struct tty_struct *tty)
1939{
1940  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
1941        
1942#ifdef SERIAL_DEBUG_OTHER
1943    printk("cy_hangup ttyS%d\n", info->line); /* */
1944#endif
1945
1946    if (serial_paranoia_check(info, tty->device, "cy_hangup"))
1947        return;
1948    
1949    shutdown(info);
1950#if 0
1951    info->event = 0;
1952    info->count = 0;
1953#ifdef SERIAL_DEBUG_COUNT
1954    printk("cyc: %d: setting count to 0\n", __LINE__);
1955#endif
1956    info->tty = 0;
1957#endif
1958    info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
1959    wake_up_interruptible(&info->open_wait);
1960} /* cy_hangup */
1961
1962
1963
1964/*
1965 * ------------------------------------------------------------
1966 * cy_open() and friends
1967 * ------------------------------------------------------------
1968 */
1969
1970static int
1971block_til_ready(struct tty_struct *tty, struct file * filp,
1972                           struct cyclades_port *info)
1973{
1974  DECLARE_WAITQUEUE(wait, current);
1975  unsigned long flags;
1976  int channel;
1977  int retval;
1978  volatile u_char *base_addr = (u_char *)BASE_ADDR;
1979
1980    /*
1981     * If the device is in the middle of being closed, then block
1982     * until it's done, and then try again.
1983     */
1984    if (info->flags & ASYNC_CLOSING) {
1985        interruptible_sleep_on(&info->close_wait);
1986        if (info->flags & ASYNC_HUP_NOTIFY){
1987            return -EAGAIN;
1988        }else{
1989            return -ERESTARTSYS;
1990        }
1991    }
1992
1993    /*
1994     * If this is a callout device, then just make sure the normal
1995     * device isn't being used.
1996     */
1997    if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
1998        if (info->flags & ASYNC_NORMAL_ACTIVE){
1999            return -EBUSY;
2000        }
2001        if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
2002            (info->flags & ASYNC_SESSION_LOCKOUT) &&
2003            (info->session != current->session)){
2004            return -EBUSY;
2005        }
2006        if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
2007            (info->flags & ASYNC_PGRP_LOCKOUT) &&
2008            (info->pgrp != current->pgrp)){
2009            return -EBUSY;
2010        }
2011        info->flags |= ASYNC_CALLOUT_ACTIVE;
2012        return 0;
2013    }
2014
2015    /*
2016     * If non-blocking mode is set, then make the check up front
2017     * and then exit.
2018     */
2019    if (filp->f_flags & O_NONBLOCK) {
2020        if (info->flags & ASYNC_CALLOUT_ACTIVE){
2021            return -EBUSY;
2022        }
2023        info->flags |= ASYNC_NORMAL_ACTIVE;
2024        return 0;
2025    }
2026
2027    /*
2028     * Block waiting for the carrier detect and the line to become
2029     * free (i.e., not in use by the callout).  While we are in
2030     * this loop, info->count is dropped by one, so that
2031     * cy_close() knows when to free things.  We restore it upon
2032     * exit, either normal or abnormal.
2033     */
2034    retval = 0;
2035    add_wait_queue(&info->open_wait, &wait);
2036#ifdef SERIAL_DEBUG_OPEN
2037    printk("block_til_ready before block: ttyS%d, count = %d\n",
2038           info->line, info->count);/**/
2039#endif
2040    info->count--;
2041#ifdef SERIAL_DEBUG_COUNT
2042    printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
2043#endif
2044    info->blocked_open++;
2045
2046    channel = info->line;
2047
2048    while (1) {
2049        save_flags(flags); cli();
2050            if (!(info->flags & ASYNC_CALLOUT_ACTIVE)){
2051                base_addr[CyCAR] = (u_char)channel;
2052                base_addr[CyMSVR1] = CyRTS;
2053/* CP('S');CP('4'); */
2054                base_addr[CyMSVR2] = CyDTR;
2055#ifdef SERIAL_DEBUG_DTR
2056                printk("cyc: %d: raising DTR\n", __LINE__);
2057                printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1], base_addr[CyMSVR2]);
2058#endif
2059            }
2060        restore_flags(flags);
2061        set_current_state(TASK_INTERRUPTIBLE);
2062        if (tty_hung_up_p(filp)
2063        || !(info->flags & ASYNC_INITIALIZED) ){
2064            if (info->flags & ASYNC_HUP_NOTIFY) {
2065                retval = -EAGAIN;
2066            }else{
2067                retval = -ERESTARTSYS;
2068            }
2069            break;
2070        }
2071        save_flags(flags); cli();
2072            base_addr[CyCAR] = (u_char)channel;
2073/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */
2074            if (!(info->flags & ASYNC_CALLOUT_ACTIVE)
2075            && !(info->flags & ASYNC_CLOSING)
2076            && (C_CLOCAL(tty)
2077                || (base_addr[CyMSVR1] & CyDCD))) {
2078                    restore_flags(flags);
2079                    break;
2080            }
2081        restore_flags(flags);
2082        if (signal_pending(current)) {
2083            retval = -ERESTARTSYS;
2084            break;
2085        }
2086#ifdef SERIAL_DEBUG_OPEN
2087        printk("block_til_ready blocking: ttyS%d, count = %d\n",
2088               info->line, info->count);/**/
2089#endif
2090        schedule();
2091    }
2092    current->state = TASK_RUNNING;
2093    remove_wait_queue(&info->open_wait, &wait);
2094    if (!tty_hung_up_p(filp)){
2095        info->count++;
2096#ifdef SERIAL_DEBUG_COUNT
2097    printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
2098#endif
2099    }
2100    info->blocked_open--;
2101#ifdef SERIAL_DEBUG_OPEN
2102    printk("block_til_ready after blocking: ttyS%d, count = %d\n",
2103           info->line, info->count);/**/
2104#endif
2105    if (retval)
2106            return retval;
2107    info->flags |= ASYNC_NORMAL_ACTIVE;
2108    return 0;
2109} /* block_til_ready */
2110
2111/*
2112 * This routine is called whenever a serial port is opened.  It
2113 * performs the serial-specific initialization for the tty structure.
2114 */
2115int
2116cy_open(struct tty_struct *tty, struct file * filp)
2117{
2118  struct cyclades_port  *info;
2119  int retval, line;
2120
2121/* CP('O'); */
2122    line = MINOR(tty->device) - tty->driver.minor_start;
2123    if ((line < 0) || (NR_PORTS <= line)){
2124        return -ENODEV;
2125    }
2126    info = &cy_port[line];
2127    if (info->line < 0){
2128        return -ENODEV;
2129    }
2130#ifdef SERIAL_DEBUG_OTHER
2131    printk("cy_open ttyS%d\n", info->line); /* */
2132#endif
2133    if (serial_paranoia_check(info, tty->device, "cy_open")){
2134        return -ENODEV;
2135    }
2136#ifdef SERIAL_DEBUG_OPEN
2137    printk("cy_open ttyS%d, count = %d\n", info->line, info->count);/**/
2138#endif
2139    info->count++;
2140#ifdef SERIAL_DEBUG_COUNT
2141    printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
2142#endif
2143    tty->driver_data = info;
2144    info->tty = tty;
2145
2146    if (!tmp_buf) {
2147        tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL);
2148        if (!tmp_buf){
2149            return -ENOMEM;
2150        }
2151    }
2152
2153    if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
2154        if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
2155            *tty->termios = info->normal_termios;
2156        else 
2157            *tty->termios = info->callout_termios;
2158    }
2159    /*
2160     * Start up serial port
2161     */
2162    retval = startup(info);
2163    if (retval){
2164        return retval;
2165    }
2166
2167    retval = block_til_ready(tty, filp, info);
2168    if (retval) {
2169#ifdef SERIAL_DEBUG_OPEN
2170        printk("cy_open returning after block_til_ready with %d\n",
2171               retval);
2172#endif
2173        return retval;
2174    }
2175
2176    info->session = current->session;
2177    info->pgrp = current->pgrp;
2178
2179#ifdef SERIAL_DEBUG_OPEN
2180    printk("cy_open done\n");/**/
2181#endif
2182    return 0;
2183} /* cy_open */
2184
2185
2186
2187/*
2188 * ---------------------------------------------------------------------
2189 * serial167_init() and friends
2190 *
2191 * serial167_init() is called at boot-time to initialize the serial driver.
2192 * ---------------------------------------------------------------------
2193 */
2194
2195/*
2196 * This routine prints out the appropriate serial driver version
2197 * number, and identifies which options were configured into this
2198 * driver.
2199 */
2200static void
2201show_version(void)
2202{
2203    printk("MVME166/167 cd2401 driver\n");
2204} /* show_version */
2205
2206/* initialize chips on card -- return number of valid
2207   chips (which is number of ports/4) */
2208
2209/*
2210 * This initialises the hardware to a reasonable state.  It should
2211 * probe the chip first so as to copy 166-Bug setup as a default for
2212 * port 0.  It initialises CMR to CyASYNC; that is never done again, so
2213 * as to limit the number of CyINIT_CHAN commands in normal running.
2214 *
2215 * ... I wonder what I should do if this fails ...
2216 */
2217
2218void
2219mvme167_serial_console_setup(int cflag)
2220{
2221        volatile unsigned char* base_addr = (u_char *)BASE_ADDR;
2222        int ch;
2223        u_char spd;
2224        u_char rcor, rbpr, badspeed = 0;
2225        unsigned long flags;
2226
2227        save_flags(flags); cli();
2228
2229        /*
2230         * First probe channel zero of the chip, to see what speed has
2231         * been selected.
2232         */
2233
2234        base_addr[CyCAR] = 0;
2235
2236        rcor = base_addr[CyRCOR] << 5;
2237        rbpr = base_addr[CyRBPR];
2238
2239        for (spd = 0; spd < sizeof(baud_bpr); spd++)
2240                if (rbpr == baud_bpr[spd] && rcor == baud_co[spd])
2241                        break;
2242        if (spd >= sizeof(baud_bpr)) {
2243                spd = 14;       /* 19200 */
2244                badspeed = 1;   /* Failed to identify speed */
2245        }
2246        initial_console_speed = spd;
2247
2248        /* OK, we have chosen a speed, now reset and reinitialise */
2249
2250        my_udelay(20000L);      /* Allow time for any active o/p to complete */
2251        if(base_addr[CyCCR] != 0x00){
2252            restore_flags(flags);
2253            /* printk(" chip is never idle (CCR != 0)\n"); */
2254            return;
2255        }
2256
2257        base_addr[CyCCR] = CyCHIP_RESET;        /* Reset the chip */
2258        my_udelay(1000L);
2259
2260        if(base_addr[CyGFRCR] == 0x00){
2261            restore_flags(flags);
2262            /* printk(" chip is not responding (GFRCR stayed 0)\n"); */
2263            return;
2264        }
2265
2266        /*
2267         * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms
2268         * tick
2269         */
2270
2271        base_addr[CyTPR] = 10;
2272
2273        base_addr[CyPILR1] = 0x01;    /* Interrupt level for modem change */
2274        base_addr[CyPILR2] = 0x02;    /* Interrupt level for tx ints */
2275        base_addr[CyPILR3] = 0x03;    /* Interrupt level for rx ints */
2276
2277        /*
2278         * Attempt to set up all channels to something reasonable, and
2279         * bang out a INIT_CHAN command.  We should then be able to limit
2280         * the ammount of fiddling we have to do in normal running.
2281         */
2282
2283        for (ch = 3; ch >= 0 ; ch--) {
2284                base_addr[CyCAR] = (u_char)ch;
2285                base_addr[CyIER] = 0;
2286                base_addr[CyCMR] = CyASYNC;
2287                base_addr[CyLICR] = (u_char)ch << 2;
2288                base_addr[CyLIVR] = 0x5c;
2289                base_addr[CyTCOR] = baud_co[spd];
2290                base_addr[CyTBPR] = baud_bpr[spd];
2291                base_addr[CyRCOR] = baud_co[spd] >> 5;
2292                base_addr[CyRBPR] = baud_bpr[spd];
2293                base_addr[CySCHR1] = 'Q' & 0x1f;
2294                base_addr[CySCHR2] = 'X' & 0x1f;
2295                base_addr[CySCRL] = 0;
2296                base_addr[CySCRH] = 0;
2297                base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
2298                base_addr[CyCOR2] = 0;
2299                base_addr[CyCOR3] = Cy_1_STOP;
2300                base_addr[CyCOR4] = baud_cor4[spd];
2301                base_addr[CyCOR5] = 0;
2302                base_addr[CyCOR6] = 0;
2303                base_addr[CyCOR7] = 0;
2304                base_addr[CyRTPRL] = 2;
2305                base_addr[CyRTPRH] = 0;
2306                base_addr[CyMSVR1] = 0;
2307                base_addr[CyMSVR2] = 0;
2308                write_cy_cmd(base_addr,CyINIT_CHAN|CyDIS_RCVR|CyDIS_XMTR);
2309        }
2310
2311        /*
2312         * Now do specials for channel zero....
2313         */
2314
2315        base_addr[CyMSVR1] = CyRTS;
2316        base_addr[CyMSVR2] = CyDTR;
2317        base_addr[CyIER] = CyRxData;
2318        write_cy_cmd(base_addr,CyENB_RCVR|CyENB_XMTR);
2319
2320        restore_flags(flags);
2321
2322        my_udelay(20000L);      /* Let it all settle down */
2323
2324        printk("CD2401 initialised,  chip is rev 0x%02x\n", base_addr[CyGFRCR]);
2325        if (badspeed)
2326                printk("  WARNING:  Failed to identify line speed, rcor=%02x,rbpr=%02x\n",
2327                                        rcor >> 5, rbpr);
2328} /* serial_console_init */
2329
2330/* The serial driver boot-time initialization code!
2331    Hardware I/O ports are mapped to character special devices on a
2332    first found, first allocated manner.  That is, this code searches
2333    for Cyclom cards in the system.  As each is found, it is probed
2334    to discover how many chips (and thus how many ports) are present.
2335    These ports are mapped to the tty ports 64 and upward in monotonic
2336    fashion.  If an 8-port card is replaced with a 16-port card, the
2337    port mapping on a following card will shift.
2338
2339    This approach is different from what is used in the other serial
2340    device driver because the Cyclom is more properly a multiplexer,
2341    not just an aggregation of serial ports on one card.
2342
2343    If there are more cards with more ports than have been statically
2344    allocated above, a warning is printed and the extra ports are ignored.
2345 */
2346int
2347serial167_init(void)
2348{
2349  struct cyclades_port *info;
2350  int ret = 0;
2351  int good_ports = 0;
2352  int port_num = 0;
2353  int index;
2354  int DefSpeed;
2355#ifdef notyet
2356  struct sigaction sa;
2357#endif
2358
2359    if (!(mvme16x_config &MVME16x_CONFIG_GOT_CD2401))
2360        return 0;
2361
2362#if 0
2363scrn[1] = '\0';
2364#endif
2365
2366    show_version();
2367
2368    /* Has "console=0,9600n8" been used in bootinfo to change speed? */
2369    if (serial_console_cflag)
2370        DefSpeed = serial_console_cflag & 0017;
2371    else {
2372        DefSpeed = initial_console_speed;
2373        serial_console_info = &cy_port[0];
2374        serial_console_cflag = DefSpeed | CS8;
2375#if 0
2376        serial_console = 64; /*callout_driver.minor_start*/
2377#endif
2378    }
2379
2380    /* Initialize the tty_driver structure */
2381    
2382    memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
2383    cy_serial_driver.magic = TTY_DRIVER_MAGIC;
2384#ifdef CONFIG_DEVFS_FS
2385    cy_serial_driver.name = "tts/%d";
2386#else
2387    cy_serial_driver.name = "ttyS";
2388#endif
2389    cy_serial_driver.major = TTY_MAJOR;
2390    cy_serial_driver.minor_start = 64;
2391    cy_serial_driver.num = NR_PORTS;
2392    cy_serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
2393    cy_serial_driver.subtype = SERIAL_TYPE_NORMAL;
2394    cy_serial_driver.init_termios = tty_std_termios;
2395    cy_serial_driver.init_termios.c_cflag =
2396            B9600 | CS8 | CREAD | HUPCL | CLOCAL;
2397    cy_serial_driver.flags = TTY_DRIVER_REAL_RAW;
2398    cy_serial_driver.refcount = &serial_refcount;
2399    cy_serial_driver.table = serial_table;
2400    cy_serial_driver.termios = serial_termios;
2401    cy_serial_driver.termios_locked = serial_termios_locked;
2402    cy_serial_driver.open = cy_open;
2403    cy_serial_driver.close = cy_close;
2404    cy_serial_driver.write = cy_write;
2405    cy_serial_driver.put_char = cy_put_char;
2406    cy_serial_driver.flush_chars = cy_flush_chars;
2407    cy_serial_driver.write_room = cy_write_room;
2408    cy_serial_driver.chars_in_buffer = cy_chars_in_buffer;
2409    cy_serial_driver.flush_buffer = cy_flush_buffer;
2410    cy_serial_driver.ioctl = cy_ioctl;
2411    cy_serial_driver.throttle = cy_throttle;
2412    cy_serial_driver.unthrottle = cy_unthrottle;
2413    cy_serial_driver.set_termios = cy_set_termios;
2414    cy_serial_driver.stop = cy_stop;
2415    cy_serial_driver.start = cy_start;
2416    cy_serial_driver.hangup = cy_hangup;
2417
2418    /*
2419     * The callout device is just like normal device except for
2420     * major number and the subtype code.
2421     */
2422    cy_callout_driver = cy_serial_driver;
2423#ifdef CONFIG_DEVFS_FS
2424    cy_callout_driver.name = "cua/%d";
2425#else
2426    cy_callout_driver.name = "cua";
2427#endif
2428    cy_callout_driver.major = TTYAUX_MAJOR;
2429    cy_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
2430
2431    ret = tty_register_driver(&cy_serial_driver);
2432    if (ret) {
2433            printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
2434            return ret;
2435    }
2436    ret = tty_register_driver(&cy_callout_driver);
2437    if (ret) {
2438            printk(KERN_ERR "Couldn't register MVME166/7 callout driver\n");
2439            goto cleanup_serial_driver;
2440    }
2441
2442    init_bh(CYCLADES_BH, do_cyclades_bh);
2443
2444    port_num = 0;
2445    info = cy_port;
2446    for (index = 0; index < 1; index++) {
2447
2448        good_ports = 4;
2449
2450        if(port_num < NR_PORTS){
2451            while( good_ports-- && port_num < NR_PORTS){
2452                /*** initialize port ***/
2453                info->magic = CYCLADES_MAGIC;
2454                info->type = PORT_CIRRUS;
2455                info->card = index;
2456                info->line = port_num;
2457                info->flags = STD_COM_FLAGS;
2458                info->tty = 0;
2459                info->xmit_fifo_size = 12;
2460                info->cor1 = CyPARITY_NONE|Cy_8_BITS;
2461                info->cor2 = CyETC;
2462                info->cor3 = Cy_1_STOP;
2463                info->cor4 = 0x08; /* _very_ small receive threshold */
2464                info->cor5 = 0;
2465                info->cor6 = 0;
2466                info->cor7 = 0;
2467                info->tbpr = baud_bpr[DefSpeed]; /* Tx BPR */
2468                info->tco = baud_co[DefSpeed]; /* Tx CO */
2469                info->rbpr = baud_bpr[DefSpeed]; /* Rx BPR */
2470                info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */
2471                info->close_delay = 0;
2472                info->x_char = 0;
2473                info->event = 0;
2474                info->count = 0;
2475#ifdef SERIAL_DEBUG_COUNT
2476    printk("cyc: %d: setting count to 0\n", __LINE__);
2477#endif
2478                info->blocked_open = 0;
2479                info->default_threshold = 0;
2480                info->default_timeout = 0;
2481                info->tqueue.routine = do_softint;
2482                info->tqueue.data = info;
2483                info->callout_termios =cy_callout_driver.init_termios;
2484                info->normal_termios = cy_serial_driver.init_termios;
2485                init_waitqueue_head(&info->open_wait);
2486                init_waitqueue_head(&info->close_wait);
2487                /* info->session */
2488                /* info->pgrp */
2489/*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
2490                info->read_status_mask = CyTIMEOUT| CySPECHAR| CyBREAK
2491                                       | CyPARITY| CyFRAME| CyOVERRUN;
2492                /* info->timeout */
2493
2494                printk("ttyS%1d ", info->line);
2495                port_num++;info++;
2496                if(!(port_num & 7)){
2497                    printk("\n               ");
2498                }
2499            }
2500        }
2501        printk("\n");
2502    }
2503    while( port_num < NR_PORTS){
2504        info->line = -1;
2505        port_num++;info++;
2506    }
2507#ifdef CONFIG_REMOTE_DEBUG
2508    debug_setup();
2509#endif
2510    ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
2511                                "cd2401_errors", cd2401_rxerr_interrupt);
2512    if (ret) {
2513            printk(KERN_ERR "Could't get cd2401_errors IRQ");
2514            goto cleanup_callout_driver;
2515    }
2516
2517    ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
2518                                "cd2401_modem", cd2401_modem_interrupt);
2519    if (ret) {
2520            printk(KERN_ERR "Could't get cd2401_modem IRQ");
2521            goto cleanup_irq_cd2401_errors;
2522    }
2523
2524    ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
2525                                "cd2401_txints", cd2401_tx_interrupt);
2526    if (ret) {
2527            printk(KERN_ERR "Could't get cd2401_txints IRQ");
2528            goto cleanup_irq_cd2401_modem;
2529    }
2530
2531    ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
2532                                "cd2401_rxints", cd2401_rx_interrupt);
2533    if (ret) {
2534            printk(KERN_ERR "Could't get cd2401_rxints IRQ");
2535            goto cleanup_irq_cd2401_txints;
2536    }
2537
2538    /* Now we have registered the interrupt handlers, allow the interrupts */
2539
2540    pcc2chip[PccSCCMICR] = 0x15;                /* Serial ints are level 5 */
2541    pcc2chip[PccSCCTICR] = 0x15;
2542    pcc2chip[PccSCCRICR] = 0x15;
2543
2544    pcc2chip[PccIMLR] = 3;                      /* Allow PCC2 ints above 3!? */
2545
2546    return 0;
2547cleanup_irq_cd2401_txints:
2548    free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt);
2549cleanup_irq_cd2401_modem:
2550    free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt);
2551cleanup_irq_cd2401_errors:
2552    free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
2553cleanup_callout_driver:
2554    if (tty_unregister_driver(&cy_callout_driver))
2555            printk(KERN_ERR "Couldn't unregister MVME166/7 callout driver\n");
2556cleanup_serial_driver:
2557    if (tty_unregister_driver(&cy_serial_driver))
2558            printk(KERN_ERR "Couldn't unregister MVME166/7 serial driver\n");
2559    return ret;
2560} /* serial167_init */
2561
2562
2563#ifdef CYCLOM_SHOW_STATUS
2564static void
2565show_status(int line_num)
2566{
2567  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
2568  int channel;
2569  struct cyclades_port * info;
2570  unsigned long flags;
2571
2572    info = &cy_port[line_num];
2573    channel = info->line;
2574    printk("  channel %d\n", channel);/**/
2575
2576    printk(" cy_port\n");
2577    printk("  card line flags = %d %d %x\n",
2578                 info->card, info->line, info->flags);
2579    printk("  *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n",
2580                 (long)info->tty, info->read_status_mask,
2581                 info->timeout, info->xmit_fifo_size);
2582    printk("  cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n",
2583             info->cor1, info->cor2, info->cor3, info->cor4, info->cor5,
2584                        info->cor6, info->cor7);
2585    printk("  tbpr,tco,rbpr,rco = %d %d %d %d\n",
2586             info->tbpr, info->tco, info->rbpr, info->rco);
2587    printk("  close_delay event count = %d %d %d\n",
2588             info->close_delay, info->event, info->count);
2589    printk("  x_char blocked_open = %x %x\n",
2590             info->x_char, info->blocked_open);
2591    printk("  session pgrp open_wait = %lx %lx %lx\n",
2592             info->session, info->pgrp, (long)info->open_wait);
2593
2594
2595    save_flags(flags); cli();
2596
2597/* Global Registers */
2598
2599        printk(" CyGFRCR %x\n", base_addr[CyGFRCR]);
2600        printk(" CyCAR %x\n", base_addr[CyCAR]);
2601        printk(" CyRISR %x\n", base_addr[CyRISR]);
2602        printk(" CyTISR %x\n", base_addr[CyTISR]);
2603        printk(" CyMISR %x\n", base_addr[CyMISR]);
2604        printk(" CyRIR %x\n", base_addr[CyRIR]);
2605        printk(" CyTIR %x\n", base_addr[CyTIR]);
2606        printk(" CyMIR %x\n", base_addr[CyMIR]);
2607        printk(" CyTPR %x\n", base_addr[CyTPR]);
2608
2609        base_addr[CyCAR] = (u_char)channel;
2610
2611/* Virtual Registers */
2612
2613#if 0
2614        printk(" CyRIVR %x\n", base_addr[CyRIVR]);
2615        printk(" CyTIVR %x\n", base_addr[CyTIVR]);
2616        printk(" CyMIVR %x\n", base_addr[CyMIVR]);
2617        printk(" CyMISR %x\n", base_addr[CyMISR]);
2618#endif
2619
2620/* Channel Registers */
2621
2622        printk(" CyCCR %x\n", base_addr[CyCCR]);
2623        printk(" CyIER %x\n", base_addr[CyIER]);
2624        printk(" CyCOR1 %x\n", base_addr[CyCOR1]);
2625        printk(" CyCOR2 %x\n", base_addr[CyCOR2]);
2626        printk(" CyCOR3 %x\n", base_addr[CyCOR3]);
2627        printk(" CyCOR4 %x\n", base_addr[CyCOR4]);
2628        printk(" CyCOR5 %x\n", base_addr[CyCOR5]);
2629#if 0
2630        printk(" CyCCSR %x\n", base_addr[CyCCSR]);
2631        printk(" CyRDCR %x\n", base_addr[CyRDCR]);
2632#endif
2633        printk(" CySCHR1 %x\n", base_addr[CySCHR1]);
2634        printk(" CySCHR2 %x\n", base_addr[CySCHR2]);
2635#if 0
2636        printk(" CySCHR3 %x\n", base_addr[CySCHR3]);
2637        printk(" CySCHR4 %x\n", base_addr[CySCHR4]);
2638        printk(" CySCRL %x\n", base_addr[CySCRL]);
2639        printk(" CySCRH %x\n", base_addr[CySCRH]);
2640        printk(" CyLNC %x\n", base_addr[CyLNC]);
2641        printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]);
2642        printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]);
2643#endif
2644        printk(" CyRTPRL %x\n", base_addr[CyRTPRL]);
2645        printk(" CyRTPRH %x\n", base_addr[CyRTPRH]);
2646        printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]);
2647        printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]);
2648        printk(" CyRBPR %x\n", base_addr[CyRBPR]);
2649        printk(" CyRCOR %x\n", base_addr[CyRCOR]);
2650        printk(" CyTBPR %x\n", base_addr[CyTBPR]);
2651        printk(" CyTCOR %x\n", base_addr[CyTCOR]);
2652
2653    restore_flags(flags);
2654} /* show_status */
2655#endif
2656
2657
2658#if 0
2659/* Dummy routine in mvme16x/config.c for now */
2660
2661/* Serial console setup. Called from linux/init/main.c */
2662
2663void console_setup(char *str, int *ints)
2664{
2665        char *s;
2666        int baud, bits, parity;
2667        int cflag = 0;
2668
2669        /* Sanity check. */
2670        if (ints[0] > 3 || ints[1] > 3) return;
2671
2672        /* Get baud, bits and parity */
2673        baud = 2400;
2674        bits = 8;
2675        parity = 'n';
2676        if (ints[2]) baud = ints[2];
2677        if ((s = strchr(str, ','))) {
2678                do {
2679                        s++;
2680                } while(*s >= '0' && *s <= '9');
2681                if (*s) parity = *s++;
2682                if (*s) bits   = *s - '0';
2683        }
2684
2685        /* Now construct a cflag setting. */
2686        switch(baud) {
2687                case 1200:
2688                        cflag |= B1200;
2689                        break;
2690                case 9600:
2691                        cflag |= B9600;
2692                        break;
2693                case 19200:
2694                        cflag |= B19200;
2695                        break;
2696                case 38400:
2697                        cflag |= B38400;
2698                        break;
2699                case 2400:
2700                default:
2701                        cflag |= B2400;
2702                        break;
2703        }
2704        switch(bits) {
2705                case 7:
2706                        cflag |= CS7;
2707                        break;
2708                default:
2709                case 8:
2710                        cflag |= CS8;
2711                        break;
2712        }
2713        switch(parity) {
2714                case 'o': case 'O':
2715                        cflag |= PARODD;
2716                        break;
2717                case 'e': case 'E':
2718                        cflag |= PARENB;
2719                        break;
2720        }
2721
2722        serial_console_info = &cy_port[ints[1]];
2723        serial_console_cflag = cflag;
2724        serial_console = ints[1] + 64; /*callout_driver.minor_start*/
2725}
2726#endif
2727
2728/*
2729 * The following is probably out of date for 2.1.x serial console stuff.
2730 *
2731 * The console is registered early on from arch/m68k/kernel/setup.c, and
2732 * it therefore relies on the chip being setup correctly by 166-Bug.  This
2733 * seems reasonable, as the serial port has been used to invoke the system
2734 * boot.  It also means that this function must not rely on any data
2735 * initialisation performed by serial167_init() etc.
2736 *
2737 * Of course, once the console has been registered, we had better ensure
2738 * that serial167_init() doesn't leave the chip non-functional.
2739 *
2740 * The console must be locked when we get here.
2741 */
2742
2743void serial167_console_write(struct console *co, const char *str, unsigned count)
2744{
2745        volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
2746        unsigned long flags;
2747        volatile u_char sink;
2748        u_char ier;
2749        int port;
2750        u_char do_lf = 0;
2751        int i = 0;
2752
2753        save_flags(flags); cli();
2754
2755        /* Ensure transmitter is enabled! */
2756
2757        port = 0;
2758        base_addr[CyCAR] = (u_char)port;
2759        while (base_addr[CyCCR])
2760                ;
2761        base_addr[CyCCR] = CyENB_XMTR;
2762
2763        ier = base_addr[CyIER];
2764        base_addr[CyIER] = CyTxMpty;
2765
2766        while (1) {
2767                if (pcc2chip[PccSCCTICR] & 0x20)
2768                {
2769                        /* We have a Tx int. Acknowledge it */
2770                        sink = pcc2chip[PccTPIACKR];
2771                        if ((base_addr[CyLICR] >> 2) == port) {
2772                                if (i == count) {
2773                                        /* Last char of string is now output */
2774                                        base_addr[CyTEOIR] = CyNOTRANS;
2775                                        break;
2776                                }
2777                                if (do_lf) {
2778                                        base_addr[CyTDR] = '\n';
2779                                        str++;
2780                                        i++;
2781                                        do_lf = 0;
2782                                }
2783                                else if (*str == '\n') {
2784                                        base_addr[CyTDR] = '\r';
2785                                        do_lf = 1;
2786                                }
2787                                else {
2788                                        base_addr[CyTDR] = *str++;
2789                                        i++;
2790                                }
2791                                base_addr[CyTEOIR] = 0;
2792                        }
2793                        else
2794                                base_addr[CyTEOIR] = CyNOTRANS;
2795                }
2796        }
2797
2798        base_addr[CyIER] = ier;
2799
2800        restore_flags(flags);
2801}
2802
2803static kdev_t serial167_console_device(struct console *c)
2804{
2805        return MKDEV(TTY_MAJOR, 64 + c->index);
2806}
2807
2808
2809static int __init serial167_console_setup(struct console *co, char *options)
2810{
2811        return 0;
2812}
2813
2814
2815static struct console sercons = {
2816        name:           "ttyS",
2817        write:          serial167_console_write,
2818        device:         serial167_console_device,
2819        setup:          serial167_console_setup,
2820        flags:          CON_PRINTBUFFER,
2821        index:          -1,
2822};
2823
2824
2825void __init serial167_console_init(void)
2826{
2827        if (vme_brdtype == VME_TYPE_MVME166 ||
2828                        vme_brdtype == VME_TYPE_MVME167 ||
2829                        vme_brdtype == VME_TYPE_MVME177) {
2830                mvme167_serial_console_setup(0);
2831                register_console(&sercons);
2832        }
2833}
2834
2835#ifdef CONFIG_REMOTE_DEBUG
2836void putDebugChar (int c)
2837{
2838        volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
2839        unsigned long flags;
2840        volatile u_char sink;
2841        u_char ier;
2842        int port;
2843
2844        save_flags(flags); cli();
2845
2846        /* Ensure transmitter is enabled! */
2847
2848        port = DEBUG_PORT;
2849        base_addr[CyCAR] = (u_char)port;
2850        while (base_addr[CyCCR])
2851                ;
2852        base_addr[CyCCR] = CyENB_XMTR;
2853
2854        ier = base_addr[CyIER];
2855        base_addr[CyIER] = CyTxMpty;
2856
2857        while (1) {
2858                if (pcc2chip[PccSCCTICR] & 0x20)
2859                {
2860                        /* We have a Tx int. Acknowledge it */
2861                        sink = pcc2chip[PccTPIACKR];
2862                        if ((base_addr[CyLICR] >> 2) == port) {
2863                                base_addr[CyTDR] = c;
2864                                base_addr[CyTEOIR] = 0;
2865                                break;
2866                        }
2867                        else
2868                                base_addr[CyTEOIR] = CyNOTRANS;
2869                }
2870        }
2871
2872        base_addr[CyIER] = ier;
2873
2874        restore_flags(flags);
2875}
2876
2877int getDebugChar()
2878{
2879        volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
2880        unsigned long flags;
2881        volatile u_char sink;
2882        u_char ier;
2883        int port;
2884        int i, c;
2885
2886        i = debugiq.out;
2887        if (i != debugiq.in) {
2888                c = debugiq.buf[i];
2889                if (++i == DEBUG_LEN)
2890                        i = 0;
2891                debugiq.out = i;
2892                return c;
2893        }
2894        /* OK, nothing in queue, wait in poll loop */
2895
2896        save_flags(flags); cli();
2897
2898        /* Ensure receiver is enabled! */
2899
2900        port = DEBUG_PORT;
2901        base_addr[CyCAR] = (u_char)port;
2902#if 0
2903        while (base_addr[CyCCR])
2904                ;
2905        base_addr[CyCCR] = CyENB_RCVR;
2906#endif
2907        ier = base_addr[CyIER];
2908        base_addr[CyIER] = CyRxData;
2909
2910        while (1) {
2911                if (pcc2chip[PccSCCRICR] & 0x20)
2912                {
2913                        /* We have a Rx int. Acknowledge it */
2914                        sink = pcc2chip[PccRPIACKR];
2915                        if ((base_addr[CyLICR] >> 2) == port) {
2916                                int cnt = base_addr[CyRFOC];
2917                                while (cnt-- > 0)
2918                                {
2919                                        c = base_addr[CyRDR];
2920                                        if (c == 0)
2921                                                printk ("!! debug char is null (cnt=%d) !!", cnt);
2922                                        else
2923                                                queueDebugChar (c);
2924                                }
2925                                base_addr[CyREOIR] = 0;
2926                                i = debugiq.out;
2927                                if (i == debugiq.in)
2928                                        panic ("Debug input queue empty!");
2929                                c = debugiq.buf[i];
2930                                if (++i == DEBUG_LEN)
2931                                        i = 0;
2932                                debugiq.out = i;
2933                                break;
2934                        }
2935                        else
2936                                base_addr[CyREOIR] = CyNOTRANS;
2937                }
2938        }
2939
2940        base_addr[CyIER] = ier;
2941
2942        restore_flags(flags);
2943
2944        return (c);
2945}
2946
2947void queueDebugChar (int c)
2948{
2949        int i;
2950
2951        i = debugiq.in;
2952        debugiq.buf[i] = c;
2953        if (++i == DEBUG_LEN)
2954                i = 0;
2955        if (i != debugiq.out)
2956                debugiq.in = i;
2957}
2958
2959static void
2960debug_setup()
2961{
2962  unsigned long flags;
2963  volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
2964  int   i, cflag;
2965
2966    cflag = B19200;
2967
2968    save_flags(flags); cli();
2969
2970    for (i = 0; i < 4; i++)
2971    {
2972        base_addr[CyCAR] = i;
2973        base_addr[CyLICR] = i << 2;
2974    }
2975
2976    debugiq.in = debugiq.out = 0;
2977
2978    base_addr[CyCAR] = DEBUG_PORT;
2979
2980    /* baud rate */
2981    i = cflag & CBAUD;
2982
2983    base_addr[CyIER] = 0;
2984
2985    base_addr[CyCMR] = CyASYNC;
2986    base_addr[CyLICR] = DEBUG_PORT << 2;
2987    base_addr[CyLIVR] = 0x5c;
2988
2989    /* tx and rx baud rate */
2990
2991    base_addr[CyTCOR] = baud_co[i];
2992    base_addr[CyTBPR] = baud_bpr[i];
2993    base_addr[CyRCOR] = baud_co[i] >> 5;
2994    base_addr[CyRBPR] = baud_bpr[i];
2995
2996    /* set line characteristics  according configuration */
2997
2998    base_addr[CySCHR1] = 0;
2999    base_addr[CySCHR2] = 0;
3000    base_addr[CySCRL] = 0;
3001    base_addr[CySCRH] = 0;
3002    base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
3003    base_addr[CyCOR2] = 0;
3004    base_addr[CyCOR3] = Cy_1_STOP;
3005    base_addr[CyCOR4] = baud_cor4[i];
3006    base_addr[CyCOR5] = 0;
3007    base_addr[CyCOR6] = 0;
3008    base_addr[CyCOR7] = 0;
3009
3010    write_cy_cmd(base_addr,CyINIT_CHAN);
3011    write_cy_cmd(base_addr,CyENB_RCVR);
3012
3013    base_addr[CyCAR] = DEBUG_PORT; /* !!! Is this needed? */
3014
3015    base_addr[CyRTPRL] = 2;
3016    base_addr[CyRTPRH] = 0;
3017
3018    base_addr[CyMSVR1] = CyRTS;
3019    base_addr[CyMSVR2] = CyDTR;
3020
3021    base_addr[CyIER] = CyRxData;
3022
3023    restore_flags(flags);
3024
3025} /* debug_setup */
3026
3027#endif
3028
3029MODULE_LICENSE("GPL");
3030
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.