Import 2.3.9pre5
[davej-history.git] / drivers / char / dz.c
blobc26a448e85202cad16018324f7a6031719cf83fd
1 /*
2 * dz.c: Serial port driver for DECStations equiped
3 * with the DZ chipset.
5 * Copyright (C) 1998 Olivier A. D. Lebaillif
6 *
7 * Email: olivier.lebaillif@ifrsys.com
9 * [31-AUG-98] triemer
10 * Changed IRQ to use Harald's dec internals interrupts.h
11 * removed base_addr code - moving address assignment to setup.c
12 * Changed name of dz_init to rs_init to be consistent with tc code
13 * [13-NOV-98] triemer fixed code to receive characters
14 * after patches by harald to irq code.
15 * [09-JAN-99] triemer minor fix for schedule - due to removal of timeout
16 * field from "current" - somewhere between 2.1.121 and 2.1.131
19 #ifdef MODULE
20 #include <linux/module.h>
21 #include <linux/version.h>
22 #else
23 #define MOD_INC_USE_COUNT
24 #define MOD_DEC_USE_COUNT
25 #endif
27 #include <linux/kernel.h>
28 #include <linux/sched.h>
29 #include <linux/init.h>
30 #include <linux/malloc.h>
31 #include <linux/mm.h>
32 #include <linux/major.h>
33 #include <linux/param.h>
34 #include <linux/tqueue.h>
35 #include <linux/interrupt.h>
36 #include <asm-mips/wbflush.h>
37 /* for definition of SERIAL */
38 #include <asm/dec/interrupts.h>
40 /* for definition of struct console */
41 #ifdef CONFIG_SERIAL_CONSOLE
42 #define CONSOLE_LINE (3)
43 #include <linux/console.h>
44 #endif /* ifdef CONFIG_SERIAL_CONSOLE */
46 #include <linux/tty.h>
47 #include <linux/tty_flip.h>
48 #include <linux/serial.h>
50 #include <asm/uaccess.h>
51 #include <asm/irq.h>
52 #include <asm/dec/machtype.h>
53 #include <asm/dec/kn01.h>
54 #include <asm/dec/kn02.h>
56 #define DEBUG_DZ 1
57 #ifdef DEBUG_DZ
58 #include <linux/tty.h>
59 #include <linux/major.h>
60 #include <linux/ptrace.h>
61 #include <linux/init.h>
62 #include <linux/console.h>
63 #include <linux/fs.h>
64 #include <asm/bootinfo.h>
66 extern int (*prom_printf) (char *,...);
67 #endif
71 #include "dz.h"
73 #define DZ_INTR_DEBUG 1
75 DECLARE_TASK_QUEUE(tq_serial);
77 extern struct wait_queue *keypress_wait;
78 static struct dz_serial *lines[4];
79 static unsigned char tmp_buffer[256];
83 #ifdef DEBUG_DZ
85 * debugging code to send out chars via prom
87 static void debug_console( const char *s,int count)
89 unsigned i;
91 for (i = 0; i < count; i++) {
92 if (*s == 10)
93 prom_printf("%c", 13);
94 prom_printf("%c", *s++);
97 #endif
100 * ------------------------------------------------------------
101 * dz_in () and dz_out ()
103 * These routines are used to access the registers of the DZ
104 * chip, hiding relocation differences between implementation.
105 * ------------------------------------------------------------
108 static inline unsigned short dz_in (struct dz_serial *info, unsigned offset)
110 volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset);
111 return *addr;
114 static inline void dz_out (struct dz_serial *info, unsigned offset, unsigned short value)
117 volatile unsigned short *addr = (volatile unsigned short *)(info->port + offset);
118 *addr = value;
123 * ------------------------------------------------------------
124 * rs_stop () and rs_start ()
126 * These routines are called before setting or resetting
127 * tty->stopped. They enable or disable transmitter interrupts,
128 * as necessary.
129 * ------------------------------------------------------------
132 static void dz_stop (struct tty_struct *tty)
134 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
135 unsigned short mask, tmp;
138 mask = 1 << info->line;
139 tmp = dz_in (info, DZ_TCR); /* read the TX flag */
141 tmp &= ~mask; /* clear the TX flag */
142 dz_out (info, DZ_TCR, tmp);
145 static void dz_start (struct tty_struct *tty)
147 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
148 unsigned short mask, tmp;
150 mask = 1 << info->line;
151 tmp = dz_in (info, DZ_TCR); /* read the TX flag */
153 tmp |= mask; /* set the TX flag */
154 dz_out (info, DZ_TCR, tmp);
159 * ------------------------------------------------------------
160 * Here starts the interrupt handling routines. All of the
161 * following subroutines are declared as inline and are folded
162 * into dz_interrupt. They were separated out for readability's
163 * sake.
165 * Note: rs_interrupt() is a "fast" interrupt, which means that it
166 * runs with interrupts turned off. People who may want to modify
167 * rs_interrupt() should try to keep the interrupt handler as fast as
168 * possible. After you are done making modifications, it is not a bad
169 * idea to do:
171 * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer dz.c
173 * and look at the resulting assemble code in serial.s.
175 * ------------------------------------------------------------
179 * ------------------------------------------------------------
180 * dz_sched_event ()
182 * This routine is used by the interrupt handler to schedule
183 * processing in the software interrupt portion of the driver.
184 * ------------------------------------------------------------
186 static inline void dz_sched_event (struct dz_serial *info, int event)
188 info->event |= 1 << event;
189 queue_task (&info->tqueue, &tq_serial);
190 mark_bh (SERIAL_BH);
194 * ------------------------------------------------------------
195 * receive_char ()
197 * This routine deals with inputs from any lines.
198 * ------------------------------------------------------------
200 static inline void receive_chars (struct dz_serial *info_in)
203 struct dz_serial *info;
204 struct tty_struct *tty = 0;
205 struct async_icount *icount;
206 int ignore = 0;
207 unsigned short status, tmp;
208 unsigned char ch;
210 /* this code is going to be a problem...
211 the call to tty_flip_buffer is going to need
212 to be rethought...
216 status = dz_in (info_in, DZ_RBUF);
217 info = lines[LINE(status)];
219 /* punt so we don't get duplicate characters */
220 if (!(status & DZ_DVAL))
221 goto ignore_char;
224 ch = UCHAR(status); /* grab the char */
226 #ifdef 0
227 if (info->is_console) {
228 if (ch == 0) return; /* it's a break ... */
230 wake_up (&keypress_wait); /* It is a 'keyboard interrupt' ;-) */
232 #endif
234 tty = info->tty; /* now tty points to the proper dev */
235 icount = &info->icount;
237 if (!tty) break;
238 if (tty->flip.count >= TTY_FLIPBUF_SIZE) break;
240 *tty->flip.char_buf_ptr = ch;
241 *tty->flip.flag_buf_ptr = 0;
242 icount->rx++;
244 /* keep track of the statistics */
245 if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) {
246 if (status & DZ_PERR) /* parity error */
247 icount->parity++;
248 else if (status & DZ_FERR) /* frame error */
249 icount->frame++;
250 if (status & DZ_OERR) /* overrun error */
251 icount->overrun++;
253 /* check to see if we should ignore the character
254 and mask off conditions that should be ignored
257 if (status & info->ignore_status_mask) {
258 if (++ignore > 100 ) break;
259 goto ignore_char;
262 /* mask off the error conditions we want to ignore */
263 tmp = status & info->read_status_mask;
265 if (tmp & DZ_PERR)
267 *tty->flip.flag_buf_ptr = TTY_PARITY;
268 debug_console("PERR\n",5);
270 else if (tmp & DZ_FERR)
272 *tty->flip.flag_buf_ptr = TTY_FRAME;
273 debug_console("FERR\n",5);
275 if (tmp & DZ_OERR)
277 debug_console("OERR\n",5);
278 if (tty->flip.count < TTY_FLIPBUF_SIZE) {
279 tty->flip.count++;
280 tty->flip.flag_buf_ptr++;
281 tty->flip.char_buf_ptr++;
282 *tty->flip.flag_buf_ptr = TTY_OVERRUN;
286 tty->flip.flag_buf_ptr++;
287 tty->flip.char_buf_ptr++;
288 tty->flip.count++;
289 ignore_char:
290 } while (status & DZ_DVAL);
292 if (tty)
293 tty_flip_buffer_push(tty);
297 * ------------------------------------------------------------
298 * transmit_char ()
300 * This routine deals with outputs to any lines.
301 * ------------------------------------------------------------
303 static inline void transmit_chars (struct dz_serial *info)
305 unsigned char tmp;
309 if (info->x_char) { /* XON/XOFF chars */
310 dz_out (info, DZ_TDR, info->x_char);
311 info->icount.tx++;
312 info->x_char = 0;
313 return;
316 /* if nothing to do or stopped or hardware stopped */
317 if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) {
318 dz_stop (info->tty);
319 return;
322 /* if something to do ... (rember the dz has no output fifo so we go one char at a time :-< */
323 tmp = (unsigned short)info->xmit_buf[info->xmit_tail++];
324 dz_out (info, DZ_TDR, tmp);
325 info->xmit_tail = info->xmit_tail & (DZ_XMIT_SIZE - 1);
326 info->icount.tx++;
328 if (--info->xmit_cnt < WAKEUP_CHARS)
329 dz_sched_event (info, DZ_EVENT_WRITE_WAKEUP);
332 /* Are we done */
333 if (info->xmit_cnt <= 0) dz_stop (info->tty);
337 * ------------------------------------------------------------
338 * check_modem_status ()
340 * Only valid for the MODEM line duh !
341 * ------------------------------------------------------------
343 static inline void check_modem_status (struct dz_serial *info)
345 unsigned short status;
347 /* if not ne modem line just return */
348 if (info->line != DZ_MODEM) return;
350 status = dz_in (info, DZ_MSR);
352 /* it's easy, since DSR2 is the only bit in the register */
353 if (status) info->icount.dsr++;
357 * ------------------------------------------------------------
358 * dz_interrupt ()
360 * this is the main interrupt routine for the DZ chip.
361 * It deals with the multiple ports.
362 * ------------------------------------------------------------
364 static void dz_interrupt (int irq, void *dev, struct pt_regs *regs)
366 struct dz_serial *info;
367 unsigned short status;
369 status = dz_in ((struct dz_serial *)dev, DZ_CSR); /* get the reason why we just got an irq */
370 info = lines[LINE(status)]; /* re-arrange info the proper port */
372 if (status & DZ_RDONE)
373 receive_chars (info); /* the receive function */
375 if (status & DZ_TRDY)
376 transmit_chars (info);
380 * -------------------------------------------------------------------
381 * Here ends the DZ interrupt routines.
382 * -------------------------------------------------------------------
386 * This routine is used to handle the "bottom half" processing for the
387 * serial driver, known also the "software interrupt" processing.
388 * This processing is done at the kernel interrupt level, after the
389 * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
390 * is where time-consuming activities which can not be done in the
391 * interrupt driver proper are done; the interrupt driver schedules
392 * them using rs_sched_event(), and they get done here.
394 static void do_serial_bh (void)
396 run_task_queue (&tq_serial);
399 static void do_softint (void *private_data)
401 struct dz_serial *info = (struct dz_serial *)private_data;
402 struct tty_struct *tty = info->tty;
404 if (!tty) return;
406 if (test_and_clear_bit (DZ_EVENT_WRITE_WAKEUP, &info->event)) {
407 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
408 (tty->ldisc.write_wakeup) (tty);
409 wake_up_interruptible (&tty->write_wait);
414 * -------------------------------------------------------------------
415 * This routine is called from the scheduler tqueue when the interrupt
416 * routine has signalled that a hangup has occurred. The path of
417 * hangup processing is:
419 * serial interrupt routine -> (scheduler tqueue) ->
420 * do_serial_hangup() -> tty->hangup() -> rs_hangup()
421 * -------------------------------------------------------------------
423 static void do_serial_hangup (void *private_data)
425 struct dz_serial *info = (struct dz_serial *)private_data;
426 struct tty_struct *tty = info->tty;;
428 if (!tty) return;
430 tty_hangup (tty);
434 * -------------------------------------------------------------------
435 * startup ()
437 * various initialization tasks
438 * -------------------------------------------------------------------
440 static int startup (struct dz_serial *info)
442 unsigned long page, flags;
443 unsigned short tmp;
445 if (info->is_initialized) return 0;
447 save_flags (flags);
448 cli ();
450 if (!info->port) {
451 if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags);
452 restore_flags (flags);
453 return -ENODEV;
456 if (!info->xmit_buf) {
457 page = get_free_page (GFP_KERNEL);
458 if (!page) {
459 restore_flags (flags);
460 return -ENOMEM;
462 info->xmit_buf = (unsigned char *)page;
465 if (info->tty) clear_bit (TTY_IO_ERROR, &info->tty->flags);
467 /* enable the interrupt and the scanning */
468 tmp = dz_in (info, DZ_CSR);
469 tmp |= (DZ_RIE | DZ_TIE | DZ_MSE);
470 dz_out (info, DZ_CSR, tmp);
472 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
474 /* set up the speed */
475 change_speed (info);
477 /* clear the line transmitter buffer
478 I can't figure out why I need to do this - but
479 its necessary - in order for the console portion
480 and the interrupt portion to live happily side by side.
483 /* clear the line transmitter buffer
484 I can't figure out why I need to do this - but
485 its necessary - in order for the console portion
486 and the interrupt portion to live happily side by side.
489 info->is_initialized = 1;
491 restore_flags (flags);
492 return 0;
496 * -------------------------------------------------------------------
497 * shutdown ()
499 * This routine will shutdown a serial port; interrupts are disabled, and
500 * DTR is dropped if the hangup on close termio flag is on.
501 * -------------------------------------------------------------------
503 static void shutdown (struct dz_serial *info)
505 unsigned long flags;
506 unsigned short tmp;
508 if (!info->is_initialized) return;
510 save_flags (flags);
511 cli ();
513 dz_stop (info->tty);
517 info->cflags &= ~DZ_CREAD; /* turn off receive enable flag */
518 dz_out (info, DZ_LPR, info->cflags);
520 if (info->xmit_buf) { /* free Tx buffer */
521 free_page ((unsigned long)info->xmit_buf);
522 info->xmit_buf = 0;
525 if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
526 tmp = dz_in (info, DZ_TCR);
527 if (tmp & DZ_MODEM_DTR) {
528 tmp &= ~DZ_MODEM_DTR;
529 dz_out (info, DZ_TCR, tmp);
533 if (info->tty) set_bit (TTY_IO_ERROR, &info->tty->flags);
535 info->is_initialized = 0;
536 restore_flags (flags);
540 * -------------------------------------------------------------------
541 * change_speed ()
543 * set the baud rate.
544 * -------------------------------------------------------------------
546 static void change_speed (struct dz_serial *info)
548 unsigned long flags;
549 unsigned cflag;
550 int baud;
552 if (!info->tty || !info->tty->termios) return;
554 save_flags (flags);
555 cli ();
557 info->cflags = info->line;
559 cflag = info->tty->termios->c_cflag;
561 switch (cflag & CSIZE) {
562 case CS5: info->cflags |= DZ_CS5; break;
563 case CS6: info->cflags |= DZ_CS6; break;
564 case CS7: info->cflags |= DZ_CS7; break;
565 case CS8:
566 default: info->cflags |= DZ_CS8;
569 if (cflag & CSTOPB) info->cflags |= DZ_CSTOPB;
570 if (cflag & PARENB) info->cflags |= DZ_PARENB;
571 if (cflag & PARODD) info->cflags |= DZ_PARODD;
573 baud = tty_get_baud_rate (info->tty);
574 switch (baud) {
575 case 50 : info->cflags |= DZ_B50; break;
576 case 75 : info->cflags |= DZ_B75; break;
577 case 110 : info->cflags |= DZ_B110; break;
578 case 134 : info->cflags |= DZ_B134; break;
579 case 150 : info->cflags |= DZ_B150; break;
580 case 300 : info->cflags |= DZ_B300; break;
581 case 600 : info->cflags |= DZ_B600; break;
582 case 1200: info->cflags |= DZ_B1200; break;
583 case 1800: info->cflags |= DZ_B1800; break;
584 case 2000: info->cflags |= DZ_B2000; break;
585 case 2400: info->cflags |= DZ_B2400; break;
586 case 3600: info->cflags |= DZ_B3600; break;
587 case 4800: info->cflags |= DZ_B4800; break;
588 case 7200: info->cflags |= DZ_B7200; break;
589 case 9600:
590 default : info->cflags |= DZ_B9600;
593 info->cflags |= DZ_RXENAB;
594 dz_out (info, DZ_LPR, info->cflags);
596 /* setup accept flag */
597 info->read_status_mask = DZ_OERR;
598 if (I_INPCK(info->tty))
599 info->read_status_mask |= (DZ_FERR | DZ_PERR);
601 /* characters to ignore */
602 info->ignore_status_mask = 0;
603 if (I_IGNPAR(info->tty))
604 info->ignore_status_mask |= (DZ_FERR | DZ_PERR);
606 restore_flags (flags);
610 * -------------------------------------------------------------------
611 * dz_flush_char ()
613 * Flush the buffer.
614 * -------------------------------------------------------------------
616 static void dz_flush_chars (struct tty_struct *tty)
618 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
619 unsigned long flags;
621 if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf)
622 return;
624 save_flags (flags);
625 cli ();
627 dz_start (info->tty);
629 restore_flags (flags);
634 * -------------------------------------------------------------------
635 * dz_write ()
637 * main output routine.
638 * -------------------------------------------------------------------
640 static int dz_write (struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
642 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
643 unsigned long flags;
644 int c, ret = 0;
646 if (!tty ) return ret;
647 if (!info->xmit_buf) return ret;
648 if (!tmp_buf) tmp_buf = tmp_buffer;
652 if (from_user) {
654 down (&tmp_buf_sem);
655 while (1) {
656 c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
657 if (c <= 0) break;
659 c -= copy_from_user (tmp_buf, buf, c);
660 if (!c) {
661 if (!ret) ret = -EFAULT;
662 break;
665 save_flags (flags);
666 cli ();
668 c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
669 memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
670 info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1));
671 info->xmit_cnt += c;
673 restore_flags(flags);
675 buf += c;
676 count -= c;
677 ret += c;
680 up (&tmp_buf_sem);
681 } else {
684 while (1) {
685 save_flags (flags);
686 cli ();
688 c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
689 if (c <= 0) {
690 restore_flags (flags);
691 break;
693 memcpy (info->xmit_buf + info->xmit_head, buf, c);
694 info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE-1));
695 info->xmit_cnt += c;
697 restore_flags (flags);
699 buf += c;
700 count -= c;
701 ret += c;
706 if (info->xmit_cnt)
708 if (!tty->stopped)
710 if (!tty->hw_stopped)
712 dz_start (info->tty);
716 return ret;
720 * -------------------------------------------------------------------
721 * dz_write_room ()
723 * compute the amount of space available for writing.
724 * -------------------------------------------------------------------
726 static int dz_write_room (struct tty_struct *tty)
728 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
729 int ret;
731 ret = DZ_XMIT_SIZE - info->xmit_cnt - 1;
732 if (ret < 0) ret = 0;
733 return ret;
737 * -------------------------------------------------------------------
738 * dz_chars_in_buffer ()
740 * compute the amount of char left to be transmitted
741 * -------------------------------------------------------------------
743 static int dz_chars_in_buffer (struct tty_struct *tty)
745 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
747 return info->xmit_cnt;
751 * -------------------------------------------------------------------
752 * dz_flush_buffer ()
754 * Empty the output buffer
755 * -------------------------------------------------------------------
757 static void dz_flush_buffer (struct tty_struct *tty)
759 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
761 cli ();
762 info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
763 sti ();
765 wake_up_interruptible (&tty->write_wait);
767 if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
768 (tty->ldisc.write_wakeup)(tty);
772 * ------------------------------------------------------------
773 * dz_throttle () and dz_unthrottle ()
775 * This routine is called by the upper-layer tty layer to signal that
776 * incoming characters should be throttled (or not).
777 * ------------------------------------------------------------
779 static void dz_throttle (struct tty_struct *tty)
781 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
783 if (I_IXOFF(tty))
784 info->x_char = STOP_CHAR(tty);
787 static void dz_unthrottle (struct tty_struct *tty)
789 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
791 if (I_IXOFF(tty)) {
792 if (info->x_char)
793 info->x_char = 0;
794 else
795 info->x_char = START_CHAR(tty);
799 static void dz_send_xchar (struct tty_struct *tty, char ch)
801 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
803 info->x_char = ch;
805 if (ch) dz_start (info->tty);
809 * ------------------------------------------------------------
810 * rs_ioctl () and friends
811 * ------------------------------------------------------------
813 static int get_serial_info (struct dz_serial *info, struct serial_struct *retinfo)
815 struct serial_struct tmp;
817 if (!retinfo)
818 return -EFAULT;
820 memset (&tmp, 0, sizeof(tmp));
822 tmp.type = info->type;
823 tmp.line = info->line;
824 tmp.port = info->port;
825 tmp.irq = SERIAL;
826 tmp.flags = info->flags;
827 tmp.baud_base = info->baud_base;
828 tmp.close_delay = info->close_delay;
829 tmp.closing_wait = info->closing_wait;
831 return copy_to_user (retinfo, &tmp, sizeof(*retinfo));
834 static int set_serial_info (struct dz_serial *info, struct serial_struct *new_info)
836 struct serial_struct new_serial;
837 struct dz_serial old_info;
838 int retval = 0;
840 if (!new_info)
841 return -EFAULT;
843 copy_from_user (&new_serial, new_info, sizeof(new_serial));
844 old_info = *info;
846 if (!suser())
847 return -EPERM;
849 if (info->count > 1)
850 return -EBUSY;
853 * OK, past this point, all the error checking has been done.
854 * At this point, we start making changes.....
857 info->baud_base = new_serial.baud_base;
858 info->type = new_serial.type;
859 info->close_delay = new_serial.close_delay;
860 info->closing_wait = new_serial.closing_wait;
862 retval = startup (info);
863 return retval;
867 * get_lsr_info - get line status register info
869 * Purpose: Let user call ioctl() to get info when the UART physically
870 * is emptied. On bus types like RS485, the transmitter must
871 * release the bus after transmitting. This must be done when
872 * the transmit shift register is empty, not be done when the
873 * transmit holding register is empty. This functionality
874 * allows an RS485 driver to be written in user space.
876 static int get_lsr_info (struct dz_serial *info, unsigned int *value)
878 unsigned short status = dz_in (info, DZ_LPR);
880 return put_user (status, value);
884 * This routine sends a break character out the serial port.
886 static void send_break (struct dz_serial *info, int duration)
888 unsigned long flags;
889 unsigned short tmp, mask;
891 if (!info->port)
892 return;
894 mask = 1 << info->line;
895 tmp = dz_in (info, DZ_TCR);
896 tmp |= mask;
898 current->state = TASK_INTERRUPTIBLE;
900 save_flags (flags);
901 cli();
903 dz_out (info, DZ_TCR, tmp);
905 schedule_timeout(jiffies + duration);
907 tmp &= ~mask;
908 dz_out (info, DZ_TCR, tmp);
910 restore_flags (flags);
913 static int dz_ioctl (struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
915 int error;
916 struct dz_serial * info = (struct dz_serial *)tty->driver_data;
917 int retval;
919 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
920 (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
921 (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
922 if (tty->flags & (1 << TTY_IO_ERROR))
923 return -EIO;
926 switch (cmd) {
927 case TCSBRK: /* SVID version: non-zero arg --> no break */
928 retval = tty_check_change (tty);
929 if (retval)
930 return retval;
931 tty_wait_until_sent (tty, 0);
932 if (!arg)
933 send_break (info, HZ/4); /* 1/4 second */
934 return 0;
936 case TCSBRKP: /* support for POSIX tcsendbreak() */
937 retval = tty_check_change (tty);
938 if (retval)
939 return retval;
940 tty_wait_until_sent (tty, 0);
941 send_break (info, arg ? arg*(HZ/10) : HZ/4);
942 return 0;
944 case TIOCGSOFTCAR:
945 error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(long));
946 if (error)
947 return error;
948 put_user (C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
949 return 0;
951 case TIOCSSOFTCAR:
952 error = get_user (arg, (unsigned long *)arg);
953 if (error)
954 return error;
955 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
956 return 0;
958 case TIOCGSERIAL:
959 error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct serial_struct));
960 if (error)
961 return error;
962 return get_serial_info (info, (struct serial_struct *)arg);
964 case TIOCSSERIAL:
965 return set_serial_info (info, (struct serial_struct *) arg);
967 case TIOCSERGETLSR: /* Get line status register */
968 error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(unsigned int));
969 if (error)
970 return error;
971 else
972 return get_lsr_info (info, (unsigned int *)arg);
974 case TIOCSERGSTRUCT:
975 error = verify_area (VERIFY_WRITE, (void *)arg, sizeof(struct dz_serial));
976 if (error)
977 return error;
978 copy_to_user((struct dz_serial *)arg, info, sizeof(struct dz_serial));
979 return 0;
981 default:
982 return -ENOIOCTLCMD;
985 return 0;
988 static void dz_set_termios (struct tty_struct *tty,
989 struct termios *old_termios)
991 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
993 if (tty->termios->c_cflag == old_termios->c_cflag)
994 return;
996 change_speed (info);
998 if ((old_termios->c_cflag & CRTSCTS) &&
999 !(tty->termios->c_cflag & CRTSCTS)) {
1000 tty->hw_stopped = 0;
1001 dz_start (tty);
1006 * ------------------------------------------------------------
1007 * dz_close()
1009 * This routine is called when the serial port gets closed. First, we
1010 * wait for the last remaining data to be sent. Then, we turn off
1011 * the transmit enable and receive enable flags.
1012 * ------------------------------------------------------------
1014 static void dz_close (struct tty_struct *tty, struct file *filp)
1016 struct dz_serial * info = (struct dz_serial *)tty->driver_data;
1017 unsigned long flags;
1019 if (!info) return;
1021 save_flags (flags);
1022 cli();
1024 if (tty_hung_up_p (filp)) {
1025 restore_flags (flags);
1026 return;
1029 if ((tty->count == 1) && (info->count != 1)) {
1031 * Uh, oh. tty->count is 1, which means that the tty
1032 * structure will be freed. Info->count should always
1033 * be one in these conditions. If it's greater than
1034 * one, we've got real problems, since it means the
1035 * serial port won't be shutdown.
1037 printk("dz_close: bad serial port count; tty->count is 1, "
1038 "info->count is %d\n", info->count);
1039 info->count = 1;
1042 if (--info->count < 0) {
1043 printk("rs_close: bad serial port count for ttys%d: %d\n",
1044 info->line, info->count);
1045 info->count = 0;
1048 if (info->count) {
1049 restore_flags (flags);
1050 return;
1052 info->flags |= DZ_CLOSING;
1054 * Save the termios structure, since this port may have
1055 * separate termios for callout and dialin.
1057 if (info->flags & DZ_NORMAL_ACTIVE)
1058 info->normal_termios = *tty->termios;
1059 if (info->flags & DZ_CALLOUT_ACTIVE)
1060 info->callout_termios = *tty->termios;
1062 * Now we wait for the transmit buffer to clear; and we notify
1063 * the line discipline to only process XON/XOFF characters.
1065 tty->closing = 1;
1067 if (info->closing_wait != DZ_CLOSING_WAIT_NONE)
1068 tty_wait_until_sent (tty, info->closing_wait);
1071 * At this point we stop accepting input. To do this, we
1072 * disable the receive line status interrupts.
1075 shutdown (info);
1077 if (tty->driver.flush_buffer)
1078 tty->driver.flush_buffer (tty);
1079 if (tty->ldisc.flush_buffer)
1080 tty->ldisc.flush_buffer (tty);
1081 tty->closing = 0;
1082 info->event = 0;
1083 info->tty = 0;
1085 if (tty->ldisc.num != ldiscs[N_TTY].num) {
1086 if (tty->ldisc.close)
1087 (tty->ldisc.close)(tty);
1088 tty->ldisc = ldiscs[N_TTY];
1089 tty->termios->c_line = N_TTY;
1090 if (tty->ldisc.open)
1091 (tty->ldisc.open)(tty);
1093 if (info->blocked_open) {
1094 if (info->close_delay) {
1095 current->state = TASK_INTERRUPTIBLE;
1096 schedule_timeout(jiffies + info->close_delay);
1098 wake_up_interruptible (&info->open_wait);
1101 info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE | DZ_CLOSING);
1102 wake_up_interruptible (&info->close_wait);
1104 restore_flags (flags);
1108 * dz_hangup () --- called by tty_hangup() when a hangup is signaled.
1110 static void dz_hangup (struct tty_struct *tty)
1112 struct dz_serial *info = (struct dz_serial *)tty->driver_data;
1114 dz_flush_buffer (tty);
1115 shutdown (info);
1116 info->event = 0;
1117 info->count = 0;
1118 info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE);
1119 info->tty = 0;
1120 wake_up_interruptible (&info->open_wait);
1124 * ------------------------------------------------------------
1125 * rs_open() and friends
1126 * ------------------------------------------------------------
1128 static int block_til_ready (struct tty_struct *tty, struct file *filp, struct dz_serial *info)
1130 struct wait_queue wait = { current, NULL };
1131 int retval;
1132 int do_clocal = 0;
1135 * If the device is in the middle of being closed, then block
1136 * until it's done, and then try again.
1138 if (info->flags & DZ_CLOSING) {
1139 interruptible_sleep_on (&info->close_wait);
1140 return -EAGAIN;
1144 * If this is a callout device, then just make sure the normal
1145 * device isn't being used.
1147 if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
1148 if (info->flags & DZ_NORMAL_ACTIVE)
1149 return -EBUSY;
1151 if ((info->flags & DZ_CALLOUT_ACTIVE) &&
1152 (info->flags & DZ_SESSION_LOCKOUT) &&
1153 (info->session != current->session))
1154 return -EBUSY;
1156 if ((info->flags & DZ_CALLOUT_ACTIVE) &&
1157 (info->flags & DZ_PGRP_LOCKOUT) &&
1158 (info->pgrp != current->pgrp))
1159 return -EBUSY;
1160 info->flags |= DZ_CALLOUT_ACTIVE;
1161 return 0;
1165 * If non-blocking mode is set, or the port is not enabled,
1166 * then make the check up front and then exit.
1168 if ((filp->f_flags & O_NONBLOCK) ||
1169 (tty->flags & (1 << TTY_IO_ERROR))) {
1170 if (info->flags & DZ_CALLOUT_ACTIVE)
1171 return -EBUSY;
1172 info->flags |= DZ_NORMAL_ACTIVE;
1173 return 0;
1176 if (info->flags & DZ_CALLOUT_ACTIVE) {
1177 if (info->normal_termios.c_cflag & CLOCAL)
1178 do_clocal = 1;
1179 } else {
1180 if (tty->termios->c_cflag & CLOCAL)
1181 do_clocal = 1;
1185 * Block waiting for the carrier detect and the line to become
1186 * free (i.e., not in use by the callout). While we are in
1187 * this loop, info->count is dropped by one, so that
1188 * dz_close() knows when to free things. We restore it upon
1189 * exit, either normal or abnormal.
1191 retval = 0;
1192 add_wait_queue (&info->open_wait, &wait);
1194 info->count--;
1195 info->blocked_open++;
1196 while (1) {
1197 current->state = TASK_INTERRUPTIBLE;
1198 if (tty_hung_up_p (filp) || !(info->is_initialized)) {
1199 retval = -EAGAIN;
1200 break;
1202 if (!(info->flags & DZ_CALLOUT_ACTIVE) &&
1203 !(info->flags & DZ_CLOSING) && do_clocal)
1204 break;
1205 if (signal_pending (current)) {
1206 retval = -ERESTARTSYS;
1207 break;
1209 schedule();
1212 current->state = TASK_RUNNING;
1213 remove_wait_queue (&info->open_wait, &wait);
1214 if (!tty_hung_up_p(filp))
1215 info->count++;
1216 info->blocked_open--;
1218 if (retval)
1219 return retval;
1220 info->flags |= DZ_NORMAL_ACTIVE;
1221 return 0;
1225 * This routine is called whenever a serial port is opened. It
1226 * enables interrupts for a serial port. It also performs the
1227 * serial-specific initialization for the tty structure.
1229 static int dz_open (struct tty_struct *tty, struct file *filp)
1231 struct dz_serial *info;
1232 int retval, line;
1234 line = MINOR(tty->device) - tty->driver.minor_start;
1236 /* The dz lines for the mouse/keyboard must be
1237 * opened using their respective drivers.
1239 if ((line < 0) || (line >= DZ_NB_PORT))
1240 return -ENODEV;
1242 if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE))
1243 return -ENODEV;
1245 info = lines[line];
1246 info->count++;
1248 tty->driver_data = info;
1249 info->tty = tty;
1252 * Start up serial port
1254 retval = startup (info);
1255 if (retval)
1256 return retval;
1260 retval = block_til_ready (tty, filp, info);
1261 if (retval)
1262 return retval;
1264 if ((info->count == 1) && (info->flags & DZ_SPLIT_TERMIOS)) {
1265 if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
1266 *tty->termios = info->normal_termios;
1267 else
1268 *tty->termios = info->callout_termios;
1269 change_speed (info);
1273 info->session = current->session;
1274 info->pgrp = current->pgrp;
1275 return 0;
1278 static void show_serial_version (void)
1280 printk("%s%s\n", dz_name, dz_version);
1284 __initfunc(int dz_init(void))
1286 int i, flags;
1287 struct dz_serial *info;
1289 /* Setup base handler, and timer table. */
1290 init_bh (SERIAL_BH, do_serial_bh);
1292 show_serial_version ();
1294 memset(&serial_driver, 0, sizeof(struct tty_driver));
1295 serial_driver.magic = TTY_DRIVER_MAGIC;
1296 serial_driver.name = "ttyS";
1297 serial_driver.major = TTY_MAJOR;
1298 serial_driver.minor_start = 64;
1299 serial_driver.num = DZ_NB_PORT;
1300 serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
1301 serial_driver.subtype = SERIAL_TYPE_NORMAL;
1302 serial_driver.init_termios = tty_std_termios;
1304 serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1305 serial_driver.flags = TTY_DRIVER_REAL_RAW;
1306 serial_driver.refcount = &serial_refcount;
1307 serial_driver.table = serial_table;
1308 serial_driver.termios = serial_termios;
1309 serial_driver.termios_locked = serial_termios_locked;
1311 serial_driver.open = dz_open;
1312 serial_driver.close = dz_close;
1313 serial_driver.write = dz_write;
1314 serial_driver.flush_chars = dz_flush_chars;
1315 serial_driver.write_room = dz_write_room;
1316 serial_driver.chars_in_buffer = dz_chars_in_buffer;
1317 serial_driver.flush_buffer = dz_flush_buffer;
1318 serial_driver.ioctl = dz_ioctl;
1319 serial_driver.throttle = dz_throttle;
1320 serial_driver.unthrottle = dz_unthrottle;
1321 serial_driver.send_xchar = dz_send_xchar;
1322 serial_driver.set_termios = dz_set_termios;
1323 serial_driver.stop = dz_stop;
1324 serial_driver.start = dz_start;
1325 serial_driver.hangup = dz_hangup;
1328 * The callout device is just like normal device except for
1329 * major number and the subtype code.
1331 callout_driver = serial_driver;
1332 callout_driver.name = "cua";
1333 callout_driver.major = TTYAUX_MAJOR;
1334 callout_driver.subtype = SERIAL_TYPE_CALLOUT;
1336 if (tty_register_driver (&serial_driver))
1337 panic("Couldn't register serial driver\n");
1338 if (tty_register_driver (&callout_driver))
1339 panic("Couldn't register callout driver\n");
1340 save_flags(flags); cli();
1342 i = 0;
1343 for (info = &multi[i]; i < DZ_NB_PORT; i++)
1345 lines[i] = info;
1346 info->magic = SERIAL_MAGIC;
1348 if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100))
1349 info->port = (unsigned long) KN01_DZ11_BASE;
1350 else
1351 info->port = (unsigned long) KN02_DZ11_BASE;
1353 info->line = i;
1354 info->tty = 0;
1355 info->close_delay = 50;
1356 info->closing_wait = 3000;
1357 info->x_char = 0;
1358 info->event = 0;
1359 info->count = 0;
1360 info->blocked_open = 0;
1361 info->tqueue.routine = do_softint;
1362 info->tqueue.data = info;
1363 info->tqueue_hangup.routine = do_serial_hangup;
1364 info->tqueue_hangup.data = info;
1365 info->callout_termios = callout_driver.init_termios;
1366 info->normal_termios = serial_driver.init_termios;
1367 info->open_wait = 0;
1368 info->close_wait = 0;
1370 /* If we are pointing to address zero then punt - not correctly
1371 set up in setup.c to handle this. */
1372 if (! info->port)
1373 return 0;
1375 printk("ttyS%02d at 0x%04x (irq = %d)\n", info->line, info->port, SERIAL);
1378 /* reset the chip */
1379 #ifndef CONFIG_SERIAL_CONSOLE
1380 dz_out(info, DZ_CSR, DZ_CLR);
1381 while ((tmp = dz_in(info,DZ_CSR)) & DZ_CLR) ;
1382 wbflush();
1384 /* enable scanning */
1385 dz_out(info, DZ_CSR, DZ_MSE);
1386 #endif
1388 /* order matters here... the trick is that flags
1389 is updated... in request_irq - to immediatedly obliterate
1390 it is unwise. */
1391 restore_flags(flags);
1394 if (request_irq (SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0]))
1395 panic ("Unable to register DZ interrupt\n");
1397 return 0;
1400 #ifdef CONFIG_SERIAL_CONSOLE
1401 static void dz_console_put_char (unsigned char ch)
1403 long flags;
1404 int loops = 2500;
1405 unsigned short tmp = ch;
1406 /* this code sends stuff out to serial device - spinning its
1407 wheels and waiting. */
1409 /* force the issue - point it at lines[3]*/
1410 dz_console=&multi[CONSOLE_LINE];
1412 save_flags(flags);
1413 cli();
1416 /* spin our wheels */
1417 while (((dz_in(dz_console,DZ_TCR) & DZ_TRDY) != DZ_TRDY) && loops--)
1420 /* Actually transmit the character. */
1421 dz_out (dz_console, DZ_TDR, tmp);
1423 restore_flags(flags);
1426 * -------------------------------------------------------------------
1427 * dz_console_print ()
1429 * dz_console_print is registered for printk.
1430 * -------------------------------------------------------------------
1432 static void dz_console_print (struct console *cons,
1433 const char *str,
1434 unsigned int count)
1436 #ifdef DEBUG_DZ
1437 prom_printf((char *)str);
1438 #endif
1439 while (count--)
1441 if (*str == '\n')
1442 dz_console_put_char ('\r');
1443 dz_console_put_char (*str++);
1447 static int dz_console_wait_key(struct console *co)
1449 return 0;
1452 static kdev_t dz_console_device(struct console *c)
1454 return MKDEV(TTY_MAJOR, 64 + c->index);
1457 __initfunc(static int dz_console_setup(struct console *co, char *options))
1459 int baud = 9600;
1460 int bits = 8;
1461 int parity = 'n';
1462 int cflag = CREAD | HUPCL | CLOCAL;
1463 char *s;
1464 unsigned short mask,tmp;
1466 if (options) {
1467 baud = simple_strtoul(options, NULL, 10);
1468 s = options;
1469 while(*s >= '0' && *s <= '9')
1470 s++;
1471 if (*s)
1472 parity = *s++;
1473 if (*s)
1474 bits = *s - '0';
1478 * Now construct a cflag setting.
1480 switch(baud) {
1481 case 1200:
1482 cflag |= DZ_B1200;
1483 break;
1484 case 2400:
1485 cflag |= DZ_B2400;
1486 break;
1487 case 4800:
1488 cflag |= DZ_B4800;
1489 break;
1490 case 9600:
1491 default:
1492 cflag |= DZ_B9600;
1493 break;
1495 switch(bits) {
1496 case 7:
1497 cflag |= DZ_CS7;
1498 break;
1499 default:
1500 case 8:
1501 cflag |= DZ_CS8;
1502 break;
1504 switch(parity) {
1505 case 'o': case 'O':
1506 cflag |= DZ_PARODD;
1507 break;
1508 case 'e': case 'E':
1509 cflag |= DZ_PARENB;
1510 break;
1512 co->cflag = cflag;
1514 /* TOFIX: force to console line */
1515 dz_console = &multi[CONSOLE_LINE];
1516 if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100))
1517 dz_console->port = KN01_DZ11_BASE;
1518 else
1519 dz_console->port = KN02_DZ11_BASE;
1520 dz_console->line = CONSOLE_LINE;
1522 dz_out(dz_console, DZ_CSR, DZ_CLR);
1523 while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR)
1526 /* enable scanning */
1527 dz_out(dz_console, DZ_CSR, DZ_MSE);
1529 /* Set up flags... */
1530 dz_console->cflags = 0;
1531 dz_console->cflags |= DZ_B9600;
1532 dz_console->cflags |= DZ_CS8;
1533 dz_console->cflags |= DZ_PARENB;
1534 dz_out (dz_console, DZ_LPR, dz_console->cflags);
1537 mask = 1 << dz_console->line;
1538 tmp = dz_in (dz_console, DZ_TCR); /* read the TX flag */
1539 if (!(tmp & mask)) {
1540 tmp |= mask; /* set the TX flag */
1541 dz_out (dz_console, DZ_TCR, tmp);
1545 /* TOFIX: force to console line */
1546 dz_console = &multi[CONSOLE_LINE];
1547 if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100))
1548 dz_console->port = KN01_DZ11_BASE;
1549 else
1550 dz_console->port = KN02_DZ11_BASE;
1551 dz_console->line = CONSOLE_LINE;
1553 dz_out(dz_console, DZ_CSR, DZ_CLR);
1554 while ((tmp = dz_in(dz_console,DZ_CSR)) & DZ_CLR)
1557 /* enable scanning */
1558 dz_out(dz_console, DZ_CSR, DZ_MSE);
1560 /* Set up flags... */
1561 dz_console->cflags = 0;
1562 dz_console->cflags |= DZ_B9600;
1563 dz_console->cflags |= DZ_CS8;
1564 dz_console->cflags |= DZ_PARENB;
1565 dz_out (dz_console, DZ_LPR, dz_console->cflags);
1568 mask = 1 << dz_console->line;
1569 tmp = dz_in (dz_console, DZ_TCR); /* read the TX flag */
1570 if (!(tmp & mask)) {
1571 tmp |= mask; /* set the TX flag */
1572 dz_out (dz_console, DZ_TCR, tmp);
1576 return 0;
1579 static struct console dz_sercons = {
1580 "ttyS",
1581 dz_console_print,
1582 NULL,
1583 dz_console_device,
1584 dz_console_wait_key,
1585 NULL,
1586 dz_console_setup,
1587 CON_CONSDEV | CON_PRINTBUFFER,
1588 CONSOLE_LINE,
1590 NULL
1593 __initfunc (long dz_serial_console_init(long kmem_start, long kmem_end))
1595 register_console(&dz_sercons);
1597 return kmem_start;
1600 #endif /* ifdef CONFIG_SERIAL_CONSOLE */