Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

dz.c

Go to the documentation of this file.
00001 /*
00002  * dz.c: Serial port driver for DECStations equiped 
00003  *       with the DZ chipset.
00004  *
00005  * Copyright (C) 1998 Olivier A. D. Lebaillif 
00006  *             
00007  * Email: olivier.lebaillif@ifrsys.com
00008  *
00009  * [31-AUG-98] triemer
00010  * Changed IRQ to use Harald's dec internals interrupts.h
00011  * removed base_addr code - moving address assignment to setup.c
00012  * Changed name of dz_init to rs_init to be consistent with tc code
00013  * [13-NOV-98] triemer fixed code to receive characters
00014  *    after patches by harald to irq code.  
00015  * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout
00016  *            field from "current" - somewhere between 2.1.121 and 2.1.131
00017  */
00018 
00019 #ifdef MODULE
00020 #include <linux/module.h>
00021 #include <linux/version.h>
00022 #else
00023 #define MOD_INC_USE_COUNT
00024 #define MOD_DEC_USE_COUNT
00025 #endif
00026 
00027 #include <linux/kernel.h>
00028 #include <linux/sched.h>
00029 #include <linux/init.h> 
00030 #include <linux/malloc.h>
00031 #include <linux/mm.h>
00032 #include <linux/major.h>
00033 #include <linux/param.h>
00034 #include <linux/tqueue.h>
00035 #include <linux/interrupt.h>
00036 #include <asm-mips/wbflush.h>
00037 /* for definition of SERIAL */
00038 #include <asm/dec/interrupts.h>
00039 
00040 /* for definition of struct console */
00041 #ifdef CONFIG_SERIAL_CONSOLE
00042 #define CONSOLE_LINE (3)
00043 #include <linux/console.h>
00044 #endif /* ifdef CONFIG_SERIAL_CONSOLE */
00045 
00046 #include <linux/tty.h>
00047 #include <linux/tty_flip.h>
00048 #include <linux/serial.h>
00049 
00050 #include <asm/uaccess.h>
00051 #include <asm/irq.h>
00052 #include <asm/dec/machtype.h>
00053 #include <asm/dec/kn01.h>
00054 #include <asm/dec/kn02.h>
00055 
00056 #define DEBUG_DZ 1
00057 #ifdef DEBUG_DZ
00058 #include <linux/tty.h>
00059 #include <linux/major.h>
00060 #include <linux/ptrace.h>
00061 #include <linux/init.h>
00062 #include <linux/console.h>
00063 #include <linux/fs.h>
00064 #include <asm/bootinfo.h>
00065 
00066 extern int (*prom_printf) (char *,...);
00067 #endif
00068 
00069 
00070 
00071 #include "dz.h"
00072 
00073 #define DZ_INTR_DEBUG 1
00074 
00075 DECLARE_TASK_QUEUE(tq_serial);
00076 
00077 extern struct wait_queue *keypress_wait;
00078 static struct dz_serial *lines[4];
00079 static unsigned char tmp_buffer[256];
00080 
00081 
00082 
00083 #ifdef DEBUG_DZ
00084 /*
00085  * debugging code to send out chars via prom 
00086  */
00087 static void debug_console( const char *s,int count)
00088 {
00089     unsigned i;
00090 
00091     for (i = 0; i < count; i++) {
00092        if (*s == 10)
00093            prom_printf("%c", 13);
00094        prom_printf("%c", *s++);
00095     }
00096 }
00097 #endif
00098 
00099 /*
00100  * ------------------------------------------------------------
00101  * dz_in () and dz_out ()
00102  *
00103  * These routines are used to access the registers of the DZ 
00104  * chip, hiding relocation differences between implementation.
00105  * ------------------------------------------------------------
00106  */
00107 
00108 static inline unsigned short dz_in (struct dz_serial *info, unsigned offset)
00109 {
00110   volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset);
00111   return *addr;
00112 }
00113 
00114 static inline void dz_out (struct dz_serial *info, unsigned offset, unsigned short value)
00115 {
00116 
00117     volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset);
00118   *addr = value;
00119 
00120 }
00121 
00122 /*
00123  * ------------------------------------------------------------
00124  * rs_stop () and rs_start ()
00125  *
00126  * These routines are called before setting or resetting 
00127  * tty->stopped. They enable or disable transmitter interrupts, 
00128  * as necessary.
00129  * ------------------------------------------------------------
00130  */
00131 
00132 static void dz_stop (struct tty_struct *tty)
00133 {
00134   struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00135   unsigned short mask, tmp;
00136 
00137          
00138   mask = 1 << info->line;
00139   tmp = dz_in (info, DZ_TCR);       /* read the TX flag */
00140 
00141     tmp &= ~mask;                   /* clear the TX flag */
00142     dz_out (info, DZ_TCR, tmp);
00143 }  
00144 
00145 static void dz_start (struct tty_struct *tty)
00146 {
00147   struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00148   unsigned short mask, tmp;
00149 
00150   mask = 1 << info->line;
00151   tmp = dz_in (info, DZ_TCR);      /* read the TX flag */
00152 
00153     tmp |= mask;                   /* set the TX flag */
00154     dz_out (info, DZ_TCR, tmp);
00155 
00156 }  
00157 
00158 /*
00159  * ------------------------------------------------------------
00160  * Here starts the interrupt handling routines.  All of the 
00161  * following subroutines are declared as inline and are folded 
00162  * into dz_interrupt.  They were separated out for readability's 
00163  * sake. 
00164  *
00165  * Note: rs_interrupt() is a "fast" interrupt, which means that it
00166  * runs with interrupts turned off.  People who may want to modify
00167  * rs_interrupt() should try to keep the interrupt handler as fast as
00168  * possible.  After you are done making modifications, it is not a bad
00169  * idea to do:
00170  * 
00171  * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer dz.c
00172  *
00173  * and look at the resulting assemble code in serial.s.
00174  *
00175  * ------------------------------------------------------------
00176  */
00177 
00178 /*
00179  * ------------------------------------------------------------
00180  * dz_sched_event ()
00181  *
00182  * This routine is used by the interrupt handler to schedule
00183  * processing in the software interrupt portion of the driver.
00184  * ------------------------------------------------------------
00185  */
00186 static inline void dz_sched_event (struct dz_serial *info, int event)
00187 {
00188   info->event |= 1 << event;
00189   queue_task (&info->tqueue, &tq_serial);
00190   mark_bh (SERIAL_BH);
00191 }
00192 
00193 /*
00194  * ------------------------------------------------------------
00195  * receive_char ()
00196  *
00197  * This routine deals with inputs from any lines.
00198  * ------------------------------------------------------------
00199  */
00200 static inline void receive_chars (struct dz_serial *info_in)
00201 {
00202 
00203   struct dz_serial *info;
00204   struct tty_struct *tty = 0;
00205   struct async_icount *icount;
00206   int ignore = 0;
00207   unsigned short status, tmp;
00208   unsigned char ch;
00209 
00210   /* this code is going to be a problem...
00211      the call to tty_flip_buffer is going to need
00212      to be rethought...
00213    */
00214   do
00215     {
00216       status = dz_in (info_in, DZ_RBUF);
00217       info = lines[LINE(status)];
00218 
00219       /* punt so we don't get duplicate characters */
00220       if (!(status & DZ_DVAL))
00221         goto ignore_char;
00222 
00223 
00224     ch = UCHAR(status);                /* grab the char */
00225 
00226 #ifdef 0
00227     if (info->is_console) {
00228       if (ch == 0) return;            /* it's a break ... */
00229 
00230       wake_up (&keypress_wait);       /* It is a 'keyboard interrupt' ;-) */
00231     }
00232 #endif
00233 
00234     tty = info->tty;                  /* now tty points to the proper dev */
00235     icount = &info->icount;
00236 
00237     if (!tty) break;
00238     if (tty->flip.count >= TTY_FLIPBUF_SIZE) break;
00239 
00240     *tty->flip.char_buf_ptr = ch;
00241     *tty->flip.flag_buf_ptr = 0;
00242     icount->rx++;
00243 
00244     /* keep track of the statistics */
00245     if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) {
00246       if (status & DZ_PERR)                /* parity error */
00247         icount->parity++;
00248       else if (status & DZ_FERR)           /* frame error */
00249         icount->frame++;
00250       if (status & DZ_OERR)                /* overrun error */
00251         icount->overrun++;
00252 
00253       /*  check to see if we should ignore the character
00254          and mask off conditions that should be ignored
00255       */
00256 
00257       if (status & info->ignore_status_mask) {
00258         if (++ignore > 100 ) break;
00259         goto ignore_char;
00260       }
00261 
00262       /* mask off the error conditions we want to ignore */
00263       tmp = status & info->read_status_mask;
00264 
00265       if (tmp & DZ_PERR)
00266         {
00267         *tty->flip.flag_buf_ptr = TTY_PARITY;
00268           debug_console("PERR\n",5);
00269         }
00270       else if (tmp & DZ_FERR)
00271         {
00272         *tty->flip.flag_buf_ptr = TTY_FRAME;
00273           debug_console("FERR\n",5);
00274         }
00275       if (tmp & DZ_OERR) 
00276         { 
00277           debug_console("OERR\n",5);
00278         if (tty->flip.count < TTY_FLIPBUF_SIZE) {
00279           tty->flip.count++;
00280           tty->flip.flag_buf_ptr++;
00281           tty->flip.char_buf_ptr++;
00282           *tty->flip.flag_buf_ptr = TTY_OVERRUN;
00283         }
00284       }
00285     }
00286     tty->flip.flag_buf_ptr++;
00287     tty->flip.char_buf_ptr++;
00288     tty->flip.count++;
00289   ignore_char:
00290   } while (status & DZ_DVAL);
00291 
00292   if (tty)
00293     tty_flip_buffer_push(tty);
00294 }
00295 
00296 /*
00297  * ------------------------------------------------------------
00298  * transmit_char ()
00299  *
00300  * This routine deals with outputs to any lines.
00301  * ------------------------------------------------------------
00302  */
00303 static inline void transmit_chars (struct dz_serial *info)
00304 {
00305   unsigned char tmp;
00306 
00307 
00308 
00309   if (info->x_char) {           /* XON/XOFF chars */
00310     dz_out (info, DZ_TDR, info->x_char);
00311     info->icount.tx++;
00312     info->x_char = 0;
00313     return;
00314   }
00315 
00316   /* if nothing to do or stopped or hardware stopped */
00317   if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) {
00318     dz_stop (info->tty);
00319     return;
00320   }
00321 
00322   /* if something to do ... (rember the dz has no output fifo so we go one char at a time :-< */
00323   tmp = (unsigned short)info->xmit_buf[info->xmit_tail++];
00324   dz_out (info, DZ_TDR, tmp);
00325   info->xmit_tail = info->xmit_tail & (DZ_XMIT_SIZE - 1);
00326   info->icount.tx++;
00327 
00328   if (--info->xmit_cnt < WAKEUP_CHARS)
00329     dz_sched_event (info, DZ_EVENT_WRITE_WAKEUP);
00330 
00331 
00332   /* Are we done */
00333   if (info->xmit_cnt <= 0) dz_stop (info->tty);
00334 }
00335 
00336 /*
00337  * ------------------------------------------------------------
00338  * check_modem_status ()
00339  *
00340  * Only valid for the MODEM line duh !
00341  * ------------------------------------------------------------
00342  */
00343 static inline void check_modem_status (struct dz_serial *info)
00344 {
00345   unsigned short status;
00346 
00347   /* if not ne modem line just return */
00348   if (info->line != DZ_MODEM) return;
00349 
00350   status = dz_in (info, DZ_MSR);
00351   
00352   /* it's easy, since DSR2 is the only bit in the register */
00353   if (status) info->icount.dsr++;
00354 }
00355 
00356 /*
00357  * ------------------------------------------------------------
00358  * dz_interrupt ()
00359  *
00360  * this is the main interrupt routine for the DZ chip.
00361  * It deals with the multiple ports.
00362  * ------------------------------------------------------------
00363  */
00364 static void dz_interrupt (int irq, void *dev, struct pt_regs *regs)
00365 {
00366   struct dz_serial *info;
00367   unsigned short status;
00368 
00369   status = dz_in ((struct dz_serial *)dev, DZ_CSR); /* get the reason why we just got an irq */
00370   info = lines[LINE(status)];     /* re-arrange info the proper port */
00371 
00372   if (status & DZ_RDONE) 
00373       receive_chars (info);          /* the receive function */
00374 
00375   if (status & DZ_TRDY) 
00376     transmit_chars (info);
00377 }
00378 
00379 /*
00380  * -------------------------------------------------------------------
00381  * Here ends the DZ interrupt routines.
00382  * -------------------------------------------------------------------
00383  */
00384 
00385 /*
00386  * This routine is used to handle the "bottom half" processing for the
00387  * serial driver, known also the "software interrupt" processing.
00388  * This processing is done at the kernel interrupt level, after the
00389  * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
00390  * is where time-consuming activities which can not be done in the
00391  * interrupt driver proper are done; the interrupt driver schedules
00392  * them using rs_sched_event(), and they get done here.
00393  */
00394 static void do_serial_bh (void)
00395 {
00396         run_task_queue (&tq_serial);
00397 }
00398 
00399 static void do_softint (void *private_data)
00400 {
00401   struct dz_serial *info = (struct dz_serial *)private_data;
00402   struct tty_struct *tty = info->tty;
00403 
00404   if (!tty) return;
00405 
00406   if (test_and_clear_bit (DZ_EVENT_WRITE_WAKEUP, &info->event)) {
00407     if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
00408       (tty->ldisc.write_wakeup) (tty);
00409     wake_up_interruptible (&tty->write_wait);
00410     wake_up_interruptible (&tty->poll_wait);
00411   }
00412 }
00413 
00414 /*
00415  * -------------------------------------------------------------------
00416  * This routine is called from the scheduler tqueue when the interrupt
00417  * routine has signalled that a hangup has occurred.  The path of
00418  * hangup processing is:
00419  *
00420  *      serial interrupt routine -> (scheduler tqueue) ->
00421  *      do_serial_hangup() -> tty->hangup() -> rs_hangup()
00422  * ------------------------------------------------------------------- 
00423  */
00424 static void do_serial_hangup (void *private_data)
00425 {
00426   struct dz_serial *info = (struct dz_serial *)private_data;
00427   struct tty_struct *tty = info->tty;;
00428         
00429   if (!tty) return;
00430 
00431   tty_hangup (tty);
00432 }
00433 
00434 /*
00435  * -------------------------------------------------------------------
00436  * startup ()
00437  *
00438  * various initialization tasks
00439  * ------------------------------------------------------------------- 
00440  */
00441 static int startup (struct dz_serial *info)
00442 {
00443   unsigned long page, flags;
00444   unsigned short tmp;
00445 
00446   if (info->is_initialized) return 0;
00447   
00448   save_flags (flags);
00449   cli ();
00450 
00451   if (!info->port) {
00452     if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags);
00453     restore_flags (flags);
00454     return -ENODEV;
00455   }
00456 
00457   if (!info->xmit_buf) {
00458     page = get_free_page (GFP_KERNEL);
00459     if (!page) {
00460       restore_flags (flags);
00461       return -ENOMEM;
00462     }
00463     info->xmit_buf = (unsigned char *)page;
00464   }
00465 
00466   if (info->tty) clear_bit (TTY_IO_ERROR, &info->tty->flags);
00467 
00468   /* enable the interrupt and the scanning */
00469   tmp = dz_in (info, DZ_CSR);
00470   tmp |= (DZ_RIE | DZ_TIE | DZ_MSE);
00471   dz_out (info, DZ_CSR, tmp);
00472 
00473   info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
00474 
00475   /* set up the speed */
00476   change_speed (info);
00477 
00478   /* clear the line transmitter buffer 
00479      I can't figure out why I need to do this - but
00480      its necessary - in order for the console portion
00481      and the interrupt portion to live happily side by side.
00482   */
00483 
00484   /* clear the line transmitter buffer 
00485      I can't figure out why I need to do this - but
00486      its necessary - in order for the console portion
00487      and the interrupt portion to live happily side by side.
00488   */
00489 
00490   info->is_initialized = 1;
00491 
00492   restore_flags (flags);
00493   return 0;
00494 }
00495 
00496 /* 
00497  * -------------------------------------------------------------------
00498  * shutdown ()
00499  *
00500  * This routine will shutdown a serial port; interrupts are disabled, and
00501  * DTR is dropped if the hangup on close termio flag is on.
00502  * ------------------------------------------------------------------- 
00503  */
00504 static void shutdown (struct dz_serial *info)
00505 {
00506   unsigned long flags;
00507   unsigned short tmp;
00508 
00509   if (!info->is_initialized) return;
00510 
00511   save_flags (flags);
00512   cli ();
00513 
00514   dz_stop (info->tty);
00515 
00516 
00517 
00518   info->cflags &= ~DZ_CREAD;          /* turn off receive enable flag */
00519   dz_out (info, DZ_LPR, info->cflags);
00520 
00521   if (info->xmit_buf) {               /* free Tx buffer */
00522     free_page ((unsigned long)info->xmit_buf);
00523     info->xmit_buf = 0;
00524   }
00525 
00526   if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
00527     tmp = dz_in (info, DZ_TCR);
00528     if (tmp & DZ_MODEM_DTR) {
00529       tmp &= ~DZ_MODEM_DTR;
00530       dz_out (info, DZ_TCR, tmp);
00531     }
00532   }
00533 
00534   if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags);
00535 
00536   info->is_initialized = 0;
00537   restore_flags (flags);
00538 }
00539 
00540 /* 
00541  * -------------------------------------------------------------------
00542  * change_speed ()
00543  *
00544  * set the baud rate.
00545  * ------------------------------------------------------------------- 
00546  */
00547 static void change_speed (struct dz_serial *info)
00548 {
00549   unsigned long flags;
00550   unsigned cflag;
00551   int baud;
00552 
00553   if (!info->tty || !info->tty->termios) return;
00554   
00555   save_flags (flags);
00556   cli ();
00557   
00558   info->cflags = info->line;
00559 
00560   cflag = info->tty->termios->c_cflag;
00561 
00562   switch (cflag & CSIZE) {
00563   case CS5: info->cflags |= DZ_CS5; break;
00564   case CS6: info->cflags |= DZ_CS6; break;
00565   case CS7: info->cflags |= DZ_CS7; break;
00566   case CS8: 
00567   default:  info->cflags |= DZ_CS8;
00568   }
00569 
00570   if (cflag & CSTOPB) info->cflags |= DZ_CSTOPB;
00571   if (cflag & PARENB) info->cflags |= DZ_PARENB;
00572   if (cflag & PARODD) info->cflags |= DZ_PARODD;
00573   
00574   baud = tty_get_baud_rate (info->tty);
00575   switch (baud) {
00576   case 50  :  info->cflags |= DZ_B50;   break;
00577   case 75  :  info->cflags |= DZ_B75;   break;
00578   case 110 :  info->cflags |= DZ_B110;  break;
00579   case 134 :  info->cflags |= DZ_B134;  break; 
00580   case 150 :  info->cflags |= DZ_B150;  break;
00581   case 300 :  info->cflags |= DZ_B300;  break; 
00582   case 600 :  info->cflags |= DZ_B600;  break;
00583   case 1200:  info->cflags |= DZ_B1200; break; 
00584   case 1800:  info->cflags |= DZ_B1800; break;
00585   case 2000:  info->cflags |= DZ_B2000; break;
00586   case 2400:  info->cflags |= DZ_B2400; break;
00587   case 3600:  info->cflags |= DZ_B3600; break; 
00588   case 4800:  info->cflags |= DZ_B4800; break;
00589   case 7200:  info->cflags |= DZ_B7200; break; 
00590   case 9600: 
00591   default  :  info->cflags |= DZ_B9600; 
00592   }
00593 
00594   info->cflags |= DZ_RXENAB;
00595   dz_out (info, DZ_LPR, info->cflags);
00596 
00597   /* setup accept flag */
00598   info->read_status_mask = DZ_OERR;
00599   if (I_INPCK(info->tty))
00600    info->read_status_mask |= (DZ_FERR | DZ_PERR); 
00601   
00602   /* characters to ignore */
00603   info->ignore_status_mask = 0;
00604   if (I_IGNPAR(info->tty))
00605     info->ignore_status_mask |= (DZ_FERR | DZ_PERR);
00606 
00607   restore_flags (flags);
00608 }
00609 
00610 /* 
00611  * -------------------------------------------------------------------
00612  * dz_flush_char ()
00613  *
00614  * Flush the buffer.
00615  * ------------------------------------------------------------------- 
00616  */
00617 static void dz_flush_chars (struct tty_struct *tty)
00618 {
00619   struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00620   unsigned long flags;
00621 
00622  if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf)
00623     return;
00624 
00625  save_flags (flags);
00626  cli ();  
00627 
00628  dz_start (info->tty);
00629 
00630  restore_flags (flags);
00631 }
00632 
00633 
00634 /* 
00635  * -------------------------------------------------------------------
00636  * dz_write ()
00637  *
00638  * main output routine.
00639  * ------------------------------------------------------------------- 
00640  */
00641 static int dz_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
00642 {
00643   struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00644   unsigned long flags;
00645   int c, ret = 0;
00646 
00647   if (!tty ) return ret;
00648   if (!info->xmit_buf) return ret;
00649   if (!tmp_buf) tmp_buf = tmp_buffer;
00650 
00651 
00652 
00653   if (from_user) {
00654 
00655     down (&tmp_buf_sem);
00656     while (1) {
00657       c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
00658       if (c <= 0) break;
00659 
00660       c -= copy_from_user (tmp_buf, buf, c);
00661       if (!c) {
00662         if (!ret) ret = -EFAULT;
00663         break;
00664       }
00665 
00666       save_flags (flags);
00667       cli ();
00668 
00669       c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
00670       memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
00671       info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1));
00672       info->xmit_cnt += c;
00673 
00674       restore_flags(flags);
00675 
00676       buf += c;
00677       count -= c;
00678       ret += c;
00679     }
00680     
00681     up (&tmp_buf_sem);
00682   } else {
00683 
00684 
00685     while (1) {
00686       save_flags (flags);
00687       cli ();     
00688 
00689       c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
00690       if (c <= 0) {
00691         restore_flags (flags);
00692         break;
00693       }
00694       memcpy (info->xmit_buf + info->xmit_head, buf, c);
00695       info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1));
00696       info->xmit_cnt += c;
00697 
00698       restore_flags (flags);
00699 
00700       buf += c;
00701       count -= c;
00702       ret += c;
00703     }
00704   }
00705 
00706 
00707   if (info->xmit_cnt)
00708     {
00709       if (!tty->stopped) 
00710         {
00711           if (!tty->hw_stopped)
00712             {
00713               dz_start (info->tty);
00714             }
00715         }
00716     }
00717   return ret;
00718 }
00719 
00720 /* 
00721  * -------------------------------------------------------------------
00722  * dz_write_room ()
00723  *
00724  * compute the amount of space available for writing.
00725  * ------------------------------------------------------------------- 
00726  */
00727 static int dz_write_room (struct tty_struct *tty)
00728 {
00729   struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00730   int ret;
00731                                 
00732   ret = DZ_XMIT_SIZE - info->xmit_cnt - 1;
00733   if (ret < 0) ret = 0;
00734   return ret;
00735 }
00736 
00737 /* 
00738  * -------------------------------------------------------------------
00739  * dz_chars_in_buffer ()
00740  *
00741  * compute the amount of char left to be transmitted
00742  * ------------------------------------------------------------------- 
00743  */
00744 static int dz_chars_in_buffer (struct tty_struct *tty)
00745 {
00746   struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00747   
00748   return info->xmit_cnt;
00749 }
00750 
00751 /* 
00752  * -------------------------------------------------------------------
00753  * dz_flush_buffer ()
00754  *
00755  * Empty the output buffer
00756  * ------------------------------------------------------------------- 
00757  */
00758 static void dz_flush_buffer (struct tty_struct *tty)
00759 {
00760   struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00761                                 
00762   cli ();
00763   info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
00764   sti ();
00765 
00766   wake_up_interruptible (&tty->write_wait);
00767   wake_up_interruptible (&tty->poll_wait);
00768 
00769   if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
00770     (tty->ldisc.write_wakeup)(tty);
00771 }
00772 
00773 /*
00774  * ------------------------------------------------------------
00775  * dz_throttle () and dz_unthrottle ()
00776  * 
00777  * This routine is called by the upper-layer tty layer to signal that
00778  * incoming characters should be throttled (or not).
00779  * ------------------------------------------------------------
00780  */
00781 static void dz_throttle (struct tty_struct *tty)
00782 {
00783   struct dz_serial *info = (struct dz_serial *)tty->driver_data;  
00784 
00785   if (I_IXOFF(tty))
00786     info->x_char = STOP_CHAR(tty);
00787 }
00788 
00789 static void dz_unthrottle (struct tty_struct *tty)
00790 {
00791   struct dz_serial *info = (struct dz_serial *)tty->driver_data;  
00792 
00793   if (I_IXOFF(tty)) {
00794     if (info->x_char)
00795       info->x_char = 0;
00796     else
00797       info->x_char = START_CHAR(tty);
00798   }
00799 }
00800 
00801 static void dz_send_xchar (struct tty_struct *tty, char ch)
00802 {
00803   struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00804 
00805   info->x_char = ch;
00806 
00807   if (ch) dz_start (info->tty);
00808 }
00809 
00810 /*
00811  * ------------------------------------------------------------
00812  * rs_ioctl () and friends
00813  * ------------------------------------------------------------
00814  */
00815 static int get_serial_info (struct dz_serial *info, struct serial_struct *retinfo)
00816 {
00817   struct serial_struct tmp;
00818   
00819   if (!retinfo)
00820     return -EFAULT;
00821 
00822   memset (&tmp, 0, sizeof(tmp));
00823 
00824   tmp.type = info->type;
00825   tmp.line = info->line;
00826   tmp.port = info->port;
00827   tmp.irq = SERIAL;
00828   tmp.flags = info->flags;
00829   tmp.baud_base = info->baud_base;
00830   tmp.close_delay = info->close_delay;
00831   tmp.closing_wait = info->closing_wait;
00832   
00833   return copy_to_user (retinfo, &tmp, sizeof(*retinfo));
00834 }
00835 
00836 static int set_serial_info (struct dz_serial *info, struct serial_struct *new_info)
00837 {
00838   struct serial_struct new_serial;
00839   struct dz_serial old_info;
00840   int retval = 0;
00841 
00842   if (!new_info)
00843     return -EFAULT;
00844 
00845   copy_from_user (&new_serial, new_info, sizeof(new_serial));
00846   old_info = *info;
00847 
00848   if (!suser())
00849     return -EPERM;
00850 
00851   if (info->count > 1)
00852     return -EBUSY;
00853 
00854   /*
00855    * OK, past this point, all the error checking has been done.
00856    * At this point, we start making changes.....
00857    */
00858   
00859   info->baud_base = new_serial.baud_base;
00860   info->type = new_serial.type;
00861   info->close_delay = new_serial.close_delay;
00862   info->closing_wait = new_serial.closing_wait;
00863 
00864   retval = startup (info);
00865   return retval;
00866 }
00867 
00868 /*
00869  * get_lsr_info - get line status register info
00870  *
00871  * Purpose: Let user call ioctl() to get info when the UART physically
00872  *          is emptied.  On bus types like RS485, the transmitter must
00873  *          release the bus after transmitting. This must be done when
00874  *          the transmit shift register is empty, not be done when the
00875  *          transmit holding register is empty.  This functionality
00876  *          allows an RS485 driver to be written in user space. 
00877  */
00878 static int get_lsr_info (struct dz_serial *info, unsigned int *value)
00879 {
00880   unsigned short status = dz_in (info, DZ_LPR);
00881 
00882   return put_user (status, value);
00883 }
00884 
00885 /*
00886  * This routine sends a break character out the serial port.
00887  */
00888 static void send_break (struct dz_serial *info, int duration)
00889 {
00890   unsigned long flags;
00891   unsigned short tmp, mask;
00892 
00893   if (!info->port)
00894     return;
00895 
00896   mask = 1 << info->line;
00897   tmp = dz_in (info, DZ_TCR);
00898   tmp |= mask;
00899 
00900   current->state = TASK_INTERRUPTIBLE;
00901 
00902   save_flags (flags);
00903   cli();
00904   
00905   dz_out (info, DZ_TCR, tmp);
00906   
00907   schedule_timeout(duration);
00908   
00909   tmp &= ~mask;
00910   dz_out (info, DZ_TCR, tmp);
00911   
00912   restore_flags (flags);
00913 }
00914 
00915 static int dz_ioctl (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
00916 {
00917   int error;
00918   struct dz_serial * info = (struct dz_serial *)tty->driver_data;
00919   int retval;
00920 
00921   if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
00922       (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
00923       (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
00924     if (tty->flags & (1 << TTY_IO_ERROR))
00925       return -EIO;
00926   }
00927 
00928   switch (cmd) {
00929   case TCSBRK:    /* SVID version: non-zero arg --> no break */
00930     retval = tty_check_change (tty);
00931     if (retval)
00932       return retval;
00933     tty_wait_until_sent (tty, 0);
00934     if (!arg)
00935       send_break (info, HZ/4); /* 1/4 second */
00936     return 0;
00937 
00938   case TCSBRKP:   /* support for POSIX tcsendbreak() */
00939     retval = tty_check_change (tty);
00940     if (retval)
00941       return retval;
00942     tty_wait_until_sent (tty, 0);
00943     send_break (info, arg ? arg*(HZ/10) : HZ/4);
00944     return 0;
00945 
00946   case TIOCGSOFTCAR:
00947     error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(long));
00948     if (error)
00949       return error;
00950     put_user (C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
00951     return 0;
00952 
00953   case TIOCSSOFTCAR:
00954     error = get_user (arg, (unsigned long *)arg);
00955     if (error)
00956       return error;
00957     tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
00958     return 0;
00959 
00960   case TIOCGSERIAL:
00961     error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct serial_struct));
00962     if (error)
00963       return error;
00964     return get_serial_info (info, (struct serial_struct *)arg);
00965 
00966   case TIOCSSERIAL:
00967     return set_serial_info (info, (struct serial_struct *) arg);
00968 
00969   case TIOCSERGETLSR: /* Get line status register */
00970     error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(unsigned int));
00971     if (error)
00972       return error;
00973     else
00974       return get_lsr_info (info, (unsigned int *)arg);
00975 
00976   case TIOCSERGSTRUCT:
00977     error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct dz_serial));
00978     if (error)
00979       return error;
00980     copy_to_user((struct dz_serial *)arg, info, sizeof(struct dz_serial));
00981     return 0;
00982     
00983   default:
00984     return -ENOIOCTLCMD;
00985   }
00986 
00987   return 0;
00988 }
00989 
00990 static void dz_set_termios (struct tty_struct *tty,
00991                             struct termios *old_termios)
00992 {
00993   struct dz_serial *info = (struct dz_serial *)tty->driver_data;
00994 
00995   if (tty->termios->c_cflag == old_termios->c_cflag)
00996     return;
00997 
00998   change_speed (info);
00999 
01000   if ((old_termios->c_cflag & CRTSCTS) &&
01001       !(tty->termios->c_cflag & CRTSCTS)) {
01002     tty->hw_stopped = 0;
01003     dz_start (tty);
01004   }
01005 }
01006 
01007 /*
01008  * ------------------------------------------------------------
01009  * dz_close()
01010  * 
01011  * This routine is called when the serial port gets closed.  First, we
01012  * wait for the last remaining data to be sent.  Then, we turn off
01013  * the transmit enable and receive enable flags.
01014  * ------------------------------------------------------------
01015  */
01016 static void dz_close (struct tty_struct *tty, struct file *filp)
01017 {
01018   struct dz_serial * info = (struct dz_serial *)tty->driver_data;
01019   unsigned long flags;
01020 
01021   if (!info) return;
01022         
01023   save_flags (flags); 
01024   cli();
01025         
01026   if (tty_hung_up_p (filp)) {
01027     restore_flags (flags);
01028     return;
01029   }
01030 
01031   if ((tty->count == 1) && (info->count != 1)) {
01032     /*
01033      * Uh, oh.  tty->count is 1, which means that the tty
01034      * structure will be freed.  Info->count should always
01035      * be one in these conditions.  If it's greater than
01036      * one, we've got real problems, since it means the
01037      * serial port won't be shutdown.
01038      */
01039     printk("dz_close: bad serial port count; tty->count is 1, "
01040                        "info->count is %d\n", info->count);
01041                 info->count = 1;
01042   }
01043 
01044   if (--info->count < 0) {
01045     printk("rs_close: bad serial port count for ttys%d: %d\n",
01046            info->line, info->count);
01047     info->count = 0;
01048   }
01049 
01050   if (info->count) {
01051     restore_flags (flags);
01052     return;
01053   }
01054   info->flags |= DZ_CLOSING;
01055   /*
01056    * Save the termios structure, since this port may have
01057    * separate termios for callout and dialin.
01058    */
01059   if (info->flags & DZ_NORMAL_ACTIVE)
01060     info->normal_termios = *tty->termios;
01061   if (info->flags & DZ_CALLOUT_ACTIVE)
01062     info->callout_termios = *tty->termios;
01063   /*
01064    * Now we wait for the transmit buffer to clear; and we notify 
01065    * the line discipline to only process XON/XOFF characters.
01066    */
01067   tty->closing = 1;
01068 
01069   if (info->closing_wait != DZ_CLOSING_WAIT_NONE)
01070     tty_wait_until_sent (tty, info->closing_wait);
01071 
01072   /*
01073    * At this point we stop accepting input.  To do this, we
01074    * disable the receive line status interrupts.
01075    */
01076 
01077   shutdown (info);
01078 
01079   if (tty->driver.flush_buffer)
01080     tty->driver.flush_buffer (tty);
01081   if (tty->ldisc.flush_buffer)
01082     tty->ldisc.flush_buffer (tty);
01083   tty->closing = 0;
01084   info->event = 0;
01085   info->tty = 0;
01086 
01087   if (tty->ldisc.num != ldiscs[N_TTY].num) {
01088     if (tty->ldisc.close)
01089       (tty->ldisc.close)(tty);
01090     tty->ldisc = ldiscs[N_TTY];
01091     tty->termios->c_line = N_TTY;
01092     if (tty->ldisc.open)
01093       (tty->ldisc.open)(tty);
01094   }
01095   if (info->blocked_open) {
01096     if (info->close_delay) {
01097       current->state = TASK_INTERRUPTIBLE;
01098       schedule_timeout(info->close_delay);
01099     }
01100     wake_up_interruptible (&info->open_wait);
01101   }
01102 
01103   info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE | DZ_CLOSING);
01104   wake_up_interruptible (&info->close_wait);
01105 
01106   restore_flags (flags);
01107 }
01108 
01109 /*
01110  * dz_hangup () --- called by tty_hangup() when a hangup is signaled.
01111  */
01112 static void dz_hangup (struct tty_struct *tty)
01113 {
01114   struct dz_serial *info = (struct dz_serial *)tty->driver_data;
01115   
01116   dz_flush_buffer (tty);
01117   shutdown (info);
01118   info->event = 0;
01119   info->count = 0;
01120   info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE);
01121   info->tty = 0;
01122   wake_up_interruptible (&info->open_wait);
01123 }
01124 
01125 /*
01126  * ------------------------------------------------------------
01127  * rs_open() and friends
01128  * ------------------------------------------------------------
01129  */
01130 static int block_til_ready (struct tty_struct *tty, struct file *filp, struct dz_serial *info)
01131 {
01132   struct wait_queue wait = { current, NULL };
01133   int retval;
01134   int do_clocal = 0;
01135 
01136   /*
01137    * If the device is in the middle of being closed, then block
01138    * until it's done, and then try again.
01139    */
01140   if (info->flags & DZ_CLOSING) {
01141     interruptible_sleep_on (&info->close_wait);
01142     return -EAGAIN;
01143   }
01144 
01145   /*
01146    * If this is a callout device, then just make sure the normal
01147    * device isn't being used.
01148    */
01149   if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
01150     if (info->flags & DZ_NORMAL_ACTIVE)
01151       return -EBUSY;
01152     
01153     if ((info->flags & DZ_CALLOUT_ACTIVE) &&
01154         (info->flags & DZ_SESSION_LOCKOUT) &&
01155         (info->session != current->session))
01156       return -EBUSY;
01157     
01158     if ((info->flags & DZ_CALLOUT_ACTIVE) &&
01159         (info->flags & DZ_PGRP_LOCKOUT) &&
01160         (info->pgrp != current->pgrp))
01161       return -EBUSY;
01162     info->flags |= DZ_CALLOUT_ACTIVE;
01163     return 0;
01164   }
01165 
01166   /*
01167    * If non-blocking mode is set, or the port is not enabled,
01168    * then make the check up front and then exit.
01169    */
01170   if ((filp->f_flags & O_NONBLOCK) ||
01171       (tty->flags & (1 << TTY_IO_ERROR))) {
01172     if (info->flags & DZ_CALLOUT_ACTIVE)
01173       return -EBUSY;
01174     info->flags |= DZ_NORMAL_ACTIVE;
01175     return 0;
01176   }
01177 
01178   if (info->flags & DZ_CALLOUT_ACTIVE) {
01179     if (info->normal_termios.c_cflag & CLOCAL)
01180       do_clocal = 1;
01181   } else {
01182     if (tty->termios->c_cflag & CLOCAL)
01183       do_clocal = 1;
01184   }
01185 
01186   /*
01187    * Block waiting for the carrier detect and the line to become
01188    * free (i.e., not in use by the callout).  While we are in
01189    * this loop, info->count is dropped by one, so that
01190    * dz_close() knows when to free things.  We restore it upon
01191    * exit, either normal or abnormal.
01192    */
01193   retval = 0;
01194   add_wait_queue (&info->open_wait, &wait);
01195 
01196   info->count--;
01197   info->blocked_open++;
01198   while (1) {
01199     current->state = TASK_INTERRUPTIBLE;
01200     if (tty_hung_up_p (filp) || !(info->is_initialized)) {
01201       retval = -EAGAIN;
01202       break;
01203     }
01204     if (!(info->flags & DZ_CALLOUT_ACTIVE) &&
01205         !(info->flags & DZ_CLOSING) && do_clocal)
01206       break;
01207     if (signal_pending (current)) {
01208       retval = -ERESTARTSYS;
01209       break;
01210     }
01211     schedule();
01212   }
01213                 
01214   current->state = TASK_RUNNING;
01215   remove_wait_queue (&info->open_wait, &wait);
01216   if (!tty_hung_up_p(filp))
01217     info->count++;
01218   info->blocked_open--;
01219 
01220   if (retval)
01221     return retval;
01222   info->flags |= DZ_NORMAL_ACTIVE;
01223   return 0;
01224 }       
01225 
01226 /*
01227  * This routine is called whenever a serial port is opened.  It
01228  * enables interrupts for a serial port. It also performs the 
01229  * serial-specific initialization for the tty structure.
01230  */
01231 static int dz_open (struct tty_struct *tty, struct file *filp)
01232 {
01233   struct dz_serial *info;
01234   int retval, line;
01235 
01236   line = MINOR(tty->device) - tty->driver.minor_start;
01237 
01238   /* The dz lines for the mouse/keyboard must be
01239    * opened using their respective drivers.
01240    */
01241   if ((line < 0) || (line >= DZ_NB_PORT))
01242     return -ENODEV;
01243 
01244   if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE))
01245     return -ENODEV;
01246 
01247   info = lines[line];
01248   info->count++;
01249 
01250   tty->driver_data = info;
01251   info->tty = tty;
01252 
01253   /*
01254    * Start up serial port
01255    */
01256   retval = startup (info);
01257   if (retval)
01258     return retval;
01259 
01260 
01261 
01262   retval = block_til_ready (tty, filp, info);
01263   if (retval)
01264     return retval;
01265 
01266   if ((info->count == 1) && (info->flags & DZ_SPLIT_TERMIOS)) {
01267     if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
01268       *tty->termios = info->normal_termios;
01269     else 
01270       *tty->termios = info->callout_termios;
01271     change_speed (info);
01272 
01273   }
01274 
01275   info->session = current->session;
01276   info->pgrp = current->pgrp;
01277   return 0;
01278 }
01279 
01280 static void show_serial_version (void)
01281 {
01282   printk("%s%s\n", dz_name, dz_version);
01283 }
01284 
01285 
01286 __initfunc(int dz_init(void))
01287 {
01288   int i, flags;
01289   struct dz_serial *info;
01290 
01291   /* Setup base handler, and timer table. */
01292   init_bh (SERIAL_BH, do_serial_bh);
01293 
01294   show_serial_version ();
01295 
01296   memset(&serial_driver, 0, sizeof(struct tty_driver));
01297   serial_driver.magic = TTY_DRIVER_MAGIC;
01298   serial_driver.name = "ttyS";
01299   serial_driver.major = TTY_MAJOR;
01300   serial_driver.minor_start = 64;
01301   serial_driver.num = DZ_NB_PORT;
01302   serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
01303   serial_driver.subtype = SERIAL_TYPE_NORMAL;
01304   serial_driver.init_termios = tty_std_termios;
01305 
01306   serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
01307   serial_driver.flags = TTY_DRIVER_REAL_RAW;
01308   serial_driver.refcount = &serial_refcount;
01309   serial_driver.table = serial_table;
01310   serial_driver.termios = serial_termios;
01311   serial_driver.termios_locked = serial_termios_locked;
01312 
01313   serial_driver.open = dz_open;
01314   serial_driver.close = dz_close;
01315   serial_driver.write = dz_write;
01316   serial_driver.flush_chars = dz_flush_chars;
01317   serial_driver.write_room = dz_write_room;
01318   serial_driver.chars_in_buffer = dz_chars_in_buffer;
01319   serial_driver.flush_buffer = dz_flush_buffer;
01320   serial_driver.ioctl = dz_ioctl;
01321   serial_driver.throttle = dz_throttle;
01322   serial_driver.unthrottle = dz_unthrottle;
01323   serial_driver.send_xchar = dz_send_xchar;
01324   serial_driver.set_termios = dz_set_termios;
01325   serial_driver.stop = dz_stop;
01326   serial_driver.start = dz_start;
01327   serial_driver.hangup = dz_hangup;
01328 
01329   /*
01330    * The callout device is just like normal device except for
01331    * major number and the subtype code.
01332    */
01333   callout_driver = serial_driver;
01334   callout_driver.name = "cua";
01335   callout_driver.major = TTYAUX_MAJOR;
01336   callout_driver.subtype = SERIAL_TYPE_CALLOUT;
01337 
01338   if (tty_register_driver (&serial_driver))
01339     panic("Couldn't register serial driver\n");
01340   if (tty_register_driver (&callout_driver))
01341     panic("Couldn't register callout driver\n");
01342   save_flags(flags); cli();
01343  
01344   i = 0;
01345   for (info = &multi[i]; i < DZ_NB_PORT;  i++) 
01346     {
01347       lines[i] = info;
01348     info->magic = SERIAL_MAGIC;
01349 
01350       if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100)) 
01351       info->port = (unsigned long) KN01_DZ11_BASE;
01352       else 
01353       info->port = (unsigned long) KN02_DZ11_BASE;
01354 
01355     info->line = i;
01356     info->tty = 0;
01357     info->close_delay = 50;
01358     info->closing_wait = 3000;
01359     info->x_char = 0;
01360     info->event = 0;
01361     info->count = 0;
01362     info->blocked_open = 0;
01363     info->tqueue.routine = do_softint;
01364     info->tqueue.data = info;
01365     info->tqueue_hangup.routine = do_serial_hangup;
01366     info->tqueue_hangup.data = info;
01367     info->callout_termios = callout_driver.init_termios;
01368     info->normal_termios = serial_driver.init_termios;
01369     info->open_wait = 0;
01370     info->close_wait = 0;
01371 
01372     /* If we are pointing to address zero then punt - not correctly
01373        set up in setup.c to handle this. */
01374     if (! info->port)
01375       return 0;
01376 
01377     printk("ttyS%02d at 0x%04x (irq = %d)\n", info->line, info->port, SERIAL);
01378   }
01379 
01380   /* reset the chip */
01381 #ifndef CONFIG_SERIAL_CONSOLE
01382   dz_out(info, DZ_CSR, DZ_CLR);
01383   while ((tmp = dz_in(info,DZ_CSR)) & DZ_CLR) ;
01384   wbflush();
01385   
01386   /* enable scanning */
01387    dz_out(info, DZ_CSR, DZ_MSE); 
01388 #endif
01389   
01390   /* order matters here... the trick is that flags
01391      is updated... in request_irq - to immediatedly obliterate
01392      it is unwise. */
01393   restore_flags(flags);
01394  
01395 
01396   if (request_irq (SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0]))
01397     panic ("Unable to register DZ interrupt\n");
01398  
01399   return 0;
01400 }
01401 
01402 #ifdef CONFIG_SERIAL_CONSOLE
01403 static void dz_console_put_char (unsigned char ch)
01404 {
01405   long flags;
01406   int  loops = 2500;
01407   unsigned short tmp = ch;
01408   /* this code sends stuff out to serial device - spinning its
01409       wheels and waiting. */
01410 
01411   /* force the issue - point it at lines[3]*/
01412   dz_console=&multi[CONSOLE_LINE];
01413 
01414   save_flags(flags);
01415   cli();
01416   
01417 
01418   /* spin our wheels */
01419   while (((dz_in(dz_console,DZ_TCR) & DZ_TRDY) != DZ_TRDY) &&  loops--)
01420     ;
01421   
01422   /* Actually transmit the character. */
01423   dz_out (dz_console, DZ_TDR, tmp);
01424 
01425   restore_flags(flags); 
01426 }
01427 /* 
01428  * -------------------------------------------------------------------
01429  * dz_console_print ()
01430  *
01431  * dz_console_print is registered for printk.
01432  * ------------------------------------------------------------------- 
01433  */
01434 static void dz_console_print (struct console *cons, 
01435                               const char *str, 
01436                               unsigned int count)
01437 {
01438 #ifdef DEBUG_DZ
01439   prom_printf((char *)str);
01440 #endif
01441   while (count--) 
01442     {
01443     if (*str == '\n')
01444         dz_console_put_char ('\r');
01445       dz_console_put_char (*str++);
01446   }
01447 }
01448 
01449 static int dz_console_wait_key(struct console *co)
01450 {
01451     return 0;
01452 }
01453 
01454 static kdev_t dz_console_device(struct console *c)
01455 {
01456         return MKDEV(TTY_MAJOR, 64 + c->index);
01457 }
01458 
01459 __initfunc(static int dz_console_setup(struct console *co, char *options))
01460 {
01461         int     baud = 9600;
01462         int     bits = 8;
01463         int     parity = 'n';
01464         int     cflag = CREAD | HUPCL | CLOCAL;
01465         char    *s;
01466         unsigned short mask,tmp;
01467 
01468