f024f23c69eb743eeb477c5da9a0a64973206c8d
[openwrt/staging/wigyori.git] / target / linux / brcm63xx-2.6 / files / drivers / serial / bcm63xx_cons.c
1 /*
2 <:copyright-gpl
3 Copyright 2002 Broadcom Corp. All Rights Reserved.
4
5 This program is free software; you can distribute it and/or modify it
6 under the terms of the GNU General Public License (Version 2) as
7 published by the Free Software Foundation.
8
9 This program is distributed in the hope it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 :>
18 */
19
20 /* Description: Serial port driver for the BCM963XX. */
21
22 #define CARDNAME "bcm963xx_serial driver"
23 #define VERSION "2.0"
24 #define VER_STR CARDNAME " v" VERSION "\n"
25
26
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/version.h>
30 #include <linux/init.h>
31 #include <linux/slab.h>
32 #include <linux/interrupt.h>
33 #include <linux/spinlock.h>
34
35 /* for definition of struct console */
36 #include <linux/console.h>
37 #include <linux/tty.h>
38 #include <linux/tty_flip.h>
39 #include <linux/serial.h>
40 #include <linux/serialP.h>
41 #include <asm/uaccess.h>
42
43 #include <bcmtypes.h>
44 #include <board.h>
45 #include <bcm_map_part.h>
46 #include <bcm_intr.h>
47 #include <6348_map_part.h>
48 #include <6348_intr.h>
49
50 static DEFINE_SPINLOCK(bcm963xx_serial_lock);
51
52 extern void _putc(char);
53 extern void _puts(const char *);
54
55 typedef struct bcm_serial {
56 volatile Uart * port;
57 int type;
58 int flags;
59 int irq;
60 int baud_base;
61 int blocked_open;
62 unsigned short close_delay;
63 unsigned short closing_wait;
64 unsigned short line; /* port/line number */
65 unsigned short cflags; /* line configuration flag */
66 unsigned short x_char; /* xon/xoff character */
67 unsigned short read_status_mask; /* mask for read condition */
68 unsigned short ignore_status_mask; /* mask for ignore condition */
69 unsigned long event; /* mask used in BH */
70 int xmit_head; /* Position of the head */
71 int xmit_tail; /* Position of the tail */
72 int xmit_cnt; /* Count of the chars in the buffer */
73 int count; /* indicates how many times it has been opened */
74 int magic;
75
76 struct async_icount icount; /* keep track of things ... */
77 struct tty_struct *tty; /* tty associated */
78 struct termios normal_termios;
79
80 wait_queue_head_t open_wait;
81 wait_queue_head_t close_wait;
82
83 long session; /* Session of opening process */
84 long pgrp; /* pgrp of opening process */
85
86 unsigned char is_initialized;
87 } Context;
88
89
90 /*---------------------------------------------------------------------*/
91 /* Define bits in the Interrupt Enable register */
92 /*---------------------------------------------------------------------*/
93 /* Enable receive interrupt */
94 #define RXINT (RXFIFONE|RXOVFERR)
95
96 /* Enable transmit interrupt */
97 #define TXINT (TXFIFOEMT|TXUNDERR|TXOVFERR)
98
99 /* Enable receiver line status interrupt */
100 #define LSINT (RXBRK|RXPARERR|RXFRAMERR)
101
102 #define BCM_NUM_UARTS 1
103
104 #define BD_BCM63XX_TIMER_CLOCK_INPUT (FPERIPH)
105
106
107 static struct bcm_serial multi[BCM_NUM_UARTS];
108 static struct bcm_serial *lines[BCM_NUM_UARTS];
109 static struct tty_driver *serial_driver;
110 static struct termios *serial_termios[BCM_NUM_UARTS];
111 static struct termios *serial_termios_locked[BCM_NUM_UARTS];
112
113
114 static void bcm_stop (struct tty_struct *tty);
115 static void bcm_start (struct tty_struct *tty);
116 static inline void receive_chars (struct bcm_serial * info);
117 static int startup (struct bcm_serial *info);
118 static void shutdown (struct bcm_serial * info);
119 static void change_speed( volatile Uart *pUart, tcflag_t cFlag );
120 static void bcm63xx_cons_flush_chars (struct tty_struct *tty);
121 static int bcm63xx_cons_write (struct tty_struct *tty,
122 const unsigned char *buf, int count);
123 static int bcm63xx_cons_write_room (struct tty_struct *tty);
124 static int bcm_chars_in_buffer (struct tty_struct *tty);
125 static void bcm_flush_buffer (struct tty_struct *tty);
126 static void bcm_throttle (struct tty_struct *tty);
127 static void bcm_unthrottle (struct tty_struct *tty);
128 static void bcm_send_xchar (struct tty_struct *tty, char ch);
129 static int get_serial_info(struct bcm_serial *info, struct serial_struct *retinfo);
130 static int set_serial_info (struct bcm_serial *info, struct serial_struct *new_info);
131 static int get_lsr_info (struct bcm_serial *info, unsigned int *value);
132 static void send_break (struct bcm_serial *info, int duration);
133 static int bcm_ioctl (struct tty_struct * tty, struct file * file,
134 unsigned int cmd, unsigned long arg);
135 static void bcm_set_termios (struct tty_struct *tty, struct termios *old_termios);
136 static void bcm63xx_cons_close (struct tty_struct *tty, struct file *filp);
137 static void bcm_hangup (struct tty_struct *tty);
138 static int block_til_ready (struct tty_struct *tty, struct file *filp, struct bcm_serial *info);
139 static int bcm63xx_cons_open (struct tty_struct * tty, struct file * filp);
140 static int __init bcm63xx_serialinit(void);
141
142
143 /*
144 * ------------------------------------------------------------
145 * rs_stop () and rs_start ()
146 *
147 * These routines are called before setting or resetting
148 * tty->stopped. They enable or disable transmitter interrupts,
149 * as necessary.
150 * ------------------------------------------------------------
151 */
152 static void bcm_stop (struct tty_struct *tty)
153 {
154 }
155
156 static void bcm_start (struct tty_struct *tty)
157 {
158 _puts(CARDNAME " Start\n");
159 }
160
161 /*
162 * ------------------------------------------------------------
163 * receive_char ()
164 *
165 * This routine deals with inputs from any lines.
166 * ------------------------------------------------------------
167 */
168 static inline void receive_chars (struct bcm_serial * info)
169 {
170 struct tty_struct *tty = 0;
171 struct async_icount * icount;
172 int ignore = 0;
173 unsigned short status, tmp;
174 UCHAR ch = 0;
175 while ((status = info->port->intStatus) & RXINT)
176 {
177 char flag_char = TTY_NORMAL;
178
179 if (status & RXFIFONE)
180 ch = info->port->Data; // Read the character
181 tty = info->tty; /* now tty points to the proper dev */
182 icount = &info->icount;
183 if (! tty)
184 break;
185 if (!tty_buffer_request_room(tty, 1))
186 break;
187 icount->rx++;
188 if (status & RXBRK)
189 {
190 flag_char = TTY_BREAK;
191 icount->brk++;
192 }
193 // keep track of the statistics
194 if (status & (RXFRAMERR | RXPARERR | RXOVFERR))
195 {
196 if (status & RXPARERR) /* parity error */
197 icount->parity++;
198 else
199 if (status & RXFRAMERR) /* frame error */
200 icount->frame++;
201 if (status & RXOVFERR)
202 {
203 // Overflow. Reset the RX FIFO
204 info->port->fifoctl |= RSTRXFIFOS;
205 icount->overrun++;
206 }
207 // check to see if we should ignore the character
208 // and mask off conditions that should be ignored
209 if (status & info->ignore_status_mask)
210 {
211 if (++ignore > 100 )
212 break;
213 goto ignore_char;
214 }
215 // Mask off the error conditions we want to ignore
216 tmp = status & info->read_status_mask;
217 if (tmp & RXPARERR)
218 {
219 flag_char = TTY_PARITY;
220 }
221 else
222 if (tmp & RXFRAMERR)
223 {
224 flag_char = TTY_FRAME;
225 }
226 if (tmp & RXOVFERR)
227 {
228 tty_insert_flip_char(tty, ch, flag_char);
229 ch = 0;
230 flag_char = TTY_OVERRUN;
231 if (!tty_buffer_request_room(tty, 1))
232 break;
233 }
234 }
235 tty_insert_flip_char(tty, ch, flag_char);
236 }
237 ignore_char:;
238 tty_flip_buffer_push(tty);
239 tty_schedule_flip(tty);
240
241 }
242
243
244 /*
245 * ------------------------------------------------------------
246 * bcm_interrupt ()
247 *
248 * this is the main interrupt routine for the chip.
249 * It deals with the multiple ports.
250 * ------------------------------------------------------------
251 */
252 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
253 static irqreturn_t bcm_interrupt (int irq, void * dev)
254 #else
255 static void bcm_interrupt (int irq, void * dev, struct pt_regs * regs)
256 #endif
257 {
258 struct bcm_serial * info = lines[0];
259 UINT16 intStat;
260
261 /* get pending interrupt flags from UART */
262
263 /* Mask with only the serial interrupts that are enabled */
264 intStat = info->port->intStatus & info->port->intMask;
265 while (intStat)
266 {
267 if (intStat & RXINT)
268 receive_chars (info);
269 else
270 if (intStat & TXINT)
271 info->port->intStatus = TXINT;
272 else /* don't know what it was, so let's mask it */
273 info->port->intMask &= ~intStat;
274
275 intStat = info->port->intStatus & info->port->intMask;
276 }
277
278 // Clear the interrupt
279 BcmHalInterruptEnable (INTERRUPT_ID_UART);
280 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
281 return IRQ_HANDLED;
282 #endif
283 }
284
285 /*
286 * -------------------------------------------------------------------
287 * startup ()
288 *
289 * various initialization tasks
290 * -------------------------------------------------------------------
291 */
292 static int startup (struct bcm_serial *info)
293 {
294 // Port is already started...
295 return 0;
296 }
297
298 /*
299 * -------------------------------------------------------------------
300 * shutdown ()
301 *
302 * This routine will shutdown a serial port; interrupts are disabled, and
303 * DTR is dropped if the hangup on close termio flag is on.
304 * -------------------------------------------------------------------
305 */
306 static void shutdown (struct bcm_serial * info)
307 {
308 unsigned long flags;
309 if (!info->is_initialized)
310 return;
311
312 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
313
314 info->port->control &= ~(BRGEN|TXEN|RXEN);
315 if (info->tty)
316 set_bit (TTY_IO_ERROR, &info->tty->flags);
317 info->is_initialized = 0;
318
319 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
320 }
321 /*
322 * -------------------------------------------------------------------
323 * change_speed ()
324 *
325 * Set the baud rate, character size, parity and stop bits.
326 * -------------------------------------------------------------------
327 */
328 static void change_speed( volatile Uart *pUart, tcflag_t cFlag )
329 {
330 unsigned long ulFlags, ulBaud, ulClockFreqHz, ulTmp;
331
332 spin_lock_irqsave(&bcm963xx_serial_lock, ulFlags);
333 switch( cFlag & (CBAUD | CBAUDEX) )
334 {
335 case B115200:
336 ulBaud = 115200;
337 break;
338 case B57600:
339 ulBaud = 57600;
340 break;
341 case B38400:
342 ulBaud = 38400;
343 break;
344 case B19200:
345 ulBaud = 19200;
346 break;
347 case B9600:
348 ulBaud = 9600;
349 break;
350 case B4800:
351 ulBaud = 4800;
352 break;
353 case B2400:
354 ulBaud = 2400;
355 break;
356 case B1800:
357 ulBaud = 1800;
358 break;
359 case B1200:
360 ulBaud = 1200;
361 break;
362 case B600:
363 ulBaud = 600;
364 break;
365 case B300:
366 ulBaud = 300;
367 break;
368 case B200:
369 ulBaud = 200;
370 break;
371 case B150:
372 ulBaud = 150;
373 break;
374 case B134:
375 ulBaud = 134;
376 break;
377 case B110:
378 ulBaud = 110;
379 break;
380 case B75:
381 ulBaud = 75;
382 break;
383 case B50:
384 ulBaud = 50;
385 break;
386 default:
387 ulBaud = 115200;
388 break;
389 }
390
391 /* Calculate buad rate. */
392 ulClockFreqHz = BD_BCM63XX_TIMER_CLOCK_INPUT;
393 ulTmp = (ulClockFreqHz / ulBaud) / 16;
394 if( ulTmp & 0x01 )
395 ulTmp /= 2; /* Rounding up, so sub is already accounted for */
396 else
397 ulTmp = (ulTmp / 2) - 1; /* Rounding down so we must sub 1 */
398 pUart->baudword = ulTmp;
399
400 /* Set character size, stop bits and parity. */
401 switch( cFlag & CSIZE )
402 {
403 case CS5:
404 ulTmp = BITS5SYM; /* select transmit 5 bit data size */
405 break;
406 case CS6:
407 ulTmp = BITS6SYM; /* select transmit 6 bit data size */
408 break;
409 case CS7:
410 ulTmp = BITS7SYM; /* select transmit 7 bit data size */
411 break;
412 default:
413 ulTmp = BITS8SYM; /* select transmit 8 bit data size */
414 break;
415 }
416 if( cFlag & CSTOPB )
417 ulTmp |= TWOSTOP; /* select 2 stop bits */
418 else
419 ulTmp |= ONESTOP; /* select one stop bit */
420
421 /* Write these values into the config reg. */
422 pUart->config = ulTmp;
423 pUart->control &= ~(RXPARITYEN | TXPARITYEN | RXPARITYEVEN | TXPARITYEVEN);
424 switch( cFlag & (PARENB | PARODD) )
425 {
426 case PARENB|PARODD:
427 pUart->control |= RXPARITYEN | TXPARITYEN;
428 break;
429 case PARENB:
430 pUart->control |= RXPARITYEN | TXPARITYEN | RXPARITYEVEN | TXPARITYEVEN;
431 break;
432 default:
433 pUart->control |= 0;
434 break;
435 }
436
437 /* Reset and flush uart */
438 pUart->fifoctl = RSTTXFIFOS | RSTRXFIFOS;
439 spin_unlock_irqrestore(&bcm963xx_serial_lock, ulFlags);
440 }
441
442
443 /*
444 * -------------------------------------------------------------------
445 * bcm_flush_char ()
446 *
447 * Nothing to flush. Polled I/O is used.
448 * -------------------------------------------------------------------
449 */
450 static void bcm63xx_cons_flush_chars (struct tty_struct *tty)
451 {
452 }
453
454
455 /*
456 * -------------------------------------------------------------------
457 * bcm63xx_cons_write ()
458 *
459 * Main output routine using polled I/O.
460 * -------------------------------------------------------------------
461 */
462 static int bcm63xx_cons_write (struct tty_struct *tty,
463 const unsigned char *buf, int count)
464 {
465 int c;
466
467 for (c = 0; c < count; c++)
468 _putc(buf[c]);
469 return count;
470 }
471
472 /*
473 * -------------------------------------------------------------------
474 * bcm63xx_cons_write_room ()
475 *
476 * Compute the amount of space available for writing.
477 * -------------------------------------------------------------------
478 */
479 static int bcm63xx_cons_write_room (struct tty_struct *tty)
480 {
481 /* Pick a number. Any number. Polled I/O is used. */
482 return 1024;
483 }
484
485 /*
486 * -------------------------------------------------------------------
487 * bcm_chars_in_buffer ()
488 *
489 * compute the amount of char left to be transmitted
490 * -------------------------------------------------------------------
491 */
492 static int bcm_chars_in_buffer (struct tty_struct *tty)
493 {
494 return 0;
495 }
496
497 /*
498 * -------------------------------------------------------------------
499 * bcm_flush_buffer ()
500 *
501 * Empty the output buffer
502 * -------------------------------------------------------------------
503 */
504 static void bcm_flush_buffer (struct tty_struct *tty)
505 {
506 tty_wakeup(tty);
507 }
508
509 /*
510 * ------------------------------------------------------------
511 * bcm_throttle () and bcm_unthrottle ()
512 *
513 * This routine is called by the upper-layer tty layer to signal that
514 * incoming characters should be throttled (or not).
515 * ------------------------------------------------------------
516 */
517 static void bcm_throttle (struct tty_struct *tty)
518 {
519 struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
520 if (I_IXOFF(tty))
521 info->x_char = STOP_CHAR(tty);
522 }
523
524 static void bcm_unthrottle (struct tty_struct *tty)
525 {
526 struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
527 if (I_IXOFF(tty))
528 {
529 if (info->x_char)
530 info->x_char = 0;
531 else
532 info->x_char = START_CHAR(tty);
533 }
534 }
535
536 static void bcm_send_xchar (struct tty_struct *tty, char ch)
537 {
538 struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
539 info->x_char = ch;
540 if (ch)
541 bcm_start (info->tty);
542 }
543
544 /*
545 * ------------------------------------------------------------
546 * rs_ioctl () and friends
547 * ------------------------------------------------------------
548 */
549 static int get_serial_info(struct bcm_serial *info, struct serial_struct *retinfo)
550 {
551 struct serial_struct tmp;
552
553 if (!retinfo)
554 return -EFAULT;
555
556 memset (&tmp, 0, sizeof(tmp));
557 tmp.type = info->type;
558 tmp.line = info->line;
559 tmp.port = (int) info->port;
560 tmp.irq = info->irq;
561 tmp.flags = 0;
562 tmp.baud_base = info->baud_base;
563 tmp.close_delay = info->close_delay;
564 tmp.closing_wait = info->closing_wait;
565
566 return copy_to_user (retinfo, &tmp, sizeof(*retinfo));
567 }
568
569 static int set_serial_info (struct bcm_serial *info, struct serial_struct *new_info)
570 {
571 struct serial_struct new_serial;
572 struct bcm_serial old_info;
573 int retval = 0;
574
575 if (!new_info)
576 return -EFAULT;
577
578 copy_from_user (&new_serial, new_info, sizeof(new_serial));
579 old_info = *info;
580
581 if (!capable(CAP_SYS_ADMIN))
582 return -EPERM;
583
584
585 if (info->count > 1)
586 return -EBUSY;
587
588 /* OK, past this point, all the error checking has been done.
589 * At this point, we start making changes.....
590 */
591 info->baud_base = new_serial.baud_base;
592 info->type = new_serial.type;
593 info->close_delay = new_serial.close_delay;
594 info->closing_wait = new_serial.closing_wait;
595 retval = startup (info);
596 return retval;
597 }
598
599 /*
600 * get_lsr_info - get line status register info
601 *
602 * Purpose: Let user call ioctl() to get info when the UART physically
603 * is emptied. On bus types like RS485, the transmitter must
604 * release the bus after transmitting. This must be done when
605 * the transmit shift register is empty, not be done when the
606 * transmit holding register is empty. This functionality
607 * allows an RS485 driver to be written in user space.
608 */
609 static int get_lsr_info (struct bcm_serial *info, unsigned int *value)
610 {
611 return( 0 );
612 }
613
614 /*
615 * This routine sends a break character out the serial port.
616 */
617 static void send_break (struct bcm_serial *info, int duration)
618 {
619 unsigned long flags;
620
621 if (!info->port)
622 return;
623
624 current->state = TASK_INTERRUPTIBLE;
625
626 /*save_flags (flags);
627 cli();*/
628 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
629
630 info->port->control |= XMITBREAK;
631 schedule_timeout(duration);
632 info->port->control &= ~XMITBREAK;
633
634 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
635 //restore_flags (flags);
636 }
637
638 static int bcm_ioctl (struct tty_struct * tty, struct file * file,
639 unsigned int cmd, unsigned long arg)
640 {
641 int error;
642 struct bcm_serial * info = (struct bcm_serial *)tty->driver_data;
643 int retval;
644
645 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
646 (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
647 (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT))
648 {
649 if (tty->flags & (1 << TTY_IO_ERROR))
650 return -EIO;
651 }
652 switch (cmd)
653 {
654
655 case TCSBRK: /* SVID version: non-zero arg --> no break */
656 retval = tty_check_change (tty);
657 if (retval)
658 return retval;
659 tty_wait_until_sent (tty, 0);
660 if (!arg)
661 send_break (info, HZ/4); /* 1/4 second */
662 return 0;
663
664 case TCSBRKP: /* support for POSIX tcsendbreak() */
665 retval = tty_check_change (tty);
666 if (retval)
667 return retval;
668 tty_wait_until_sent (tty, 0);
669 send_break (info, arg ? arg*(HZ/10) : HZ/4);
670 return 0;
671
672 case TIOCGSOFTCAR:
673 error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(long));
674 if (!error)
675 return -EFAULT;
676 else
677 {
678 put_user (C_CLOCAL(tty) ? 1 : 0, (unsigned long *)arg);
679 return 0;
680 }
681
682 case TIOCSSOFTCAR:
683 error = get_user (arg, (unsigned long *)arg);
684 if (error)
685 return error;
686 tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0));
687 return 0;
688
689 case TIOCGSERIAL:
690 error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(struct serial_struct));
691 if (!error)
692 return -EFAULT;
693 else
694 return get_serial_info (info, (struct serial_struct *)arg);
695
696 case TIOCSSERIAL:
697 return set_serial_info (info, (struct serial_struct *) arg);
698
699 case TIOCSERGETLSR: /* Get line status register */
700 error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(unsigned int));
701 if (!error)
702 return -EFAULT;
703 else
704 return get_lsr_info (info, (unsigned int *)arg);
705
706 case TIOCSERGSTRUCT:
707 error = access_ok (VERIFY_WRITE, (void *)arg, sizeof(struct bcm_serial));
708 if (!error)
709 return -EFAULT;
710 else
711 {
712 copy_to_user((struct bcm_serial *)arg, info, sizeof(struct bcm_serial));
713 return 0;
714 }
715
716 default:
717 return -ENOIOCTLCMD;
718 }
719 return 0;
720 }
721
722 static void bcm_set_termios (struct tty_struct *tty, struct termios *old_termios)
723 {
724 struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
725
726 if( tty->termios->c_cflag != old_termios->c_cflag )
727 change_speed (info->port, tty->termios->c_cflag);
728 }
729
730 /*
731 * ------------------------------------------------------------
732 * bcm63xx_cons_close()
733 *
734 * This routine is called when the serial port gets closed. First, we
735 * wait for the last remaining data to be sent. Then, we turn off
736 * the transmit enable and receive enable flags.
737 * ------------------------------------------------------------
738 */
739 static void bcm63xx_cons_close (struct tty_struct *tty, struct file *filp)
740 {
741 struct bcm_serial * info = (struct bcm_serial *)tty->driver_data;
742 unsigned long flags;
743
744 if (!info)
745 return;
746
747 /*save_flags (flags);
748 cli();*/
749 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
750
751 if (tty_hung_up_p (filp))
752 {
753 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
754 //restore_flags (flags);
755 return;
756 }
757
758 if ((tty->count == 1) && (info->count != 1))
759 {
760
761 /* Uh, oh. tty->count is 1, which means that the tty
762 * structure will be freed. Info->count should always
763 * be one in these conditions. If it's greater than
764 * one, we've got real problems, since it means the
765 * serial port won't be shutdown.
766 */
767 printk("bcm63xx_cons_close: bad serial port count; tty->count is 1, "
768 "info->count is %d\n", info->count);
769 info->count = 1;
770 }
771
772 if (--info->count < 0)
773 {
774 printk("ds_close: bad serial port count for ttys%d: %d\n",
775 info->line, info->count);
776 info->count = 0;
777 }
778
779 if (info->count)
780 {
781 //restore_flags (flags);
782 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
783 return;
784 }
785
786 /* Now we wait for the transmit buffer to clear; and we notify
787 * the line discipline to only process XON/XOFF characters.
788 */
789 tty->closing = 1;
790
791 /* At this point we stop accepting input. To do this, we
792 * disable the receive line status interrupts.
793 */
794 shutdown (info);
795 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
796 if (tty->driver->flush_buffer)
797 tty->driver->flush_buffer (tty);
798 #else
799 if (tty->driver.flush_buffer)
800 tty->driver.flush_buffer (tty);
801 #endif
802 if (tty->ldisc.flush_buffer)
803 tty->ldisc.flush_buffer (tty);
804
805 tty->closing = 0;
806 info->event = 0;
807 info->tty = 0;
808 if (tty->ldisc.num != tty_ldisc_get(N_TTY)->num)
809 {
810 if (tty->ldisc.close)
811 (tty->ldisc.close)(tty);
812 tty->ldisc = *tty_ldisc_get(N_TTY);
813 tty->termios->c_line = N_TTY;
814 if (tty->ldisc.open)
815 (tty->ldisc.open)(tty);
816 }
817 if (info->blocked_open)
818 {
819 if (info->close_delay)
820 {
821 current->state = TASK_INTERRUPTIBLE;
822 schedule_timeout(info->close_delay);
823 }
824 wake_up_interruptible (&info->open_wait);
825 }
826 wake_up_interruptible (&info->close_wait);
827
828 //restore_flags (flags);
829 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
830 }
831
832 /*
833 * bcm_hangup () --- called by tty_hangup() when a hangup is signaled.
834 */
835 static void bcm_hangup (struct tty_struct *tty)
836 {
837
838 struct bcm_serial *info = (struct bcm_serial *)tty->driver_data;
839
840 shutdown (info);
841 info->event = 0;
842 info->count = 0;
843 info->tty = 0;
844 wake_up_interruptible (&info->open_wait);
845 }
846
847 /*
848 * ------------------------------------------------------------
849 * rs_open() and friends
850 * ------------------------------------------------------------
851 */
852 static int block_til_ready (struct tty_struct *tty, struct file *filp,
853 struct bcm_serial *info)
854 {
855 return 0;
856 }
857
858 /*
859 * This routine is called whenever a serial port is opened. It
860 * enables interrupts for a serial port. It also performs the
861 * serial-specific initialization for the tty structure.
862 */
863 static int bcm63xx_cons_open (struct tty_struct * tty, struct file * filp)
864 {
865 struct bcm_serial *info;
866 int retval, line;
867
868 // Make sure we're only opening on of the ports we support
869 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
870 line = MINOR(tty->driver->cdev.dev) - tty->driver->minor_start;
871 #else
872 line = MINOR(tty->device) - tty->driver.minor_start;
873 #endif
874
875 if ((line < 0) || (line >= BCM_NUM_UARTS))
876 return -ENODEV;
877
878 info = lines[line];
879
880 tty->low_latency=1;
881 info->port->intMask = 0; /* Clear any pending interrupts */
882 info->port->intMask = RXINT; /* Enable RX */
883
884 info->count++;
885 tty->driver_data = info;
886 info->tty = tty;
887 BcmHalInterruptEnable (INTERRUPT_ID_UART);
888
889 // Start up serial port
890 retval = startup (info);
891 if (retval)
892 return retval;
893
894 retval = block_til_ready (tty, filp, info);
895 if (retval)
896 return retval;
897
898
899 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
900 info->pgrp = process_group(current);
901 info->session = current->signal->session;
902 #else
903 info->session = current->session;
904 info->pgrp = current->pgrp;
905 #endif
906
907 return 0;
908 }
909
910
911 static struct tty_operations rs_ops = {
912 .open = bcm63xx_cons_open,
913 .close = bcm63xx_cons_close,
914 .write = bcm63xx_cons_write,
915 .flush_chars = bcm63xx_cons_flush_chars,
916 .write_room = bcm63xx_cons_write_room,
917 .chars_in_buffer = bcm_chars_in_buffer,
918 .flush_buffer = bcm_flush_buffer,
919 .ioctl = bcm_ioctl,
920 .throttle = bcm_throttle,
921 .unthrottle = bcm_unthrottle,
922 .send_xchar = bcm_send_xchar,
923 .set_termios = bcm_set_termios,
924 .stop = bcm_stop,
925 .start = bcm_start,
926 .hangup = bcm_hangup,
927 };
928
929 /* --------------------------------------------------------------------------
930 Name: bcm63xx_serialinit
931 Purpose: Initialize our BCM63xx serial driver
932 -------------------------------------------------------------------------- */
933 static int __init bcm63xx_serialinit(void)
934 {
935 int i, flags;
936 struct bcm_serial * info;
937
938 // Print the driver version information
939 printk(VER_STR);
940 serial_driver = alloc_tty_driver(BCM_NUM_UARTS);
941 if (!serial_driver)
942 return -ENOMEM;
943
944 serial_driver->owner = THIS_MODULE;
945 // serial_driver->devfs_name = "tts/";
946 // serial_driver.magic = TTY_DRIVER_MAGIC;
947 serial_driver->name = "ttyS";
948 serial_driver->major = TTY_MAJOR;
949 serial_driver->minor_start = 64;
950 // serial_driver.num = BCM_NUM_UARTS;
951 serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
952 serial_driver->subtype = SERIAL_TYPE_NORMAL;
953 serial_driver->init_termios = tty_std_termios;
954 serial_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
955 serial_driver->flags = TTY_DRIVER_REAL_RAW;
956
957 serial_driver->termios = serial_termios;
958 serial_driver->termios_locked = serial_termios_locked;
959
960 tty_set_operations(serial_driver, &rs_ops);
961
962 if (tty_register_driver (serial_driver))
963 panic("Couldn't register serial driver\n");
964
965 //save_flags(flags); cli();
966 spin_lock_irqsave(&bcm963xx_serial_lock, flags);
967
968 for (i = 0; i < BCM_NUM_UARTS; i++)
969 {
970 info = &multi[i];
971 lines[i] = info;
972 info->magic = SERIAL_MAGIC;
973 info->port = (Uart *) ((char *)UART_BASE + (i * 0x20));
974 info->tty = 0;
975 info->irq = (2 - i) + 8;
976 info->line = i;
977 info->close_delay = 50;
978 info->closing_wait = 3000;
979 info->x_char = 0;
980 info->event = 0;
981 info->count = 0;
982 info->blocked_open = 0;
983 info->normal_termios = serial_driver->init_termios;
984 init_waitqueue_head(&info->open_wait);
985 init_waitqueue_head(&info->close_wait);
986
987 /* If we are pointing to address zero then punt - not correctly
988 * set up in setup.c to handle this.
989 */
990 if (! info->port)
991 return 0;
992 BcmHalMapInterrupt(bcm_interrupt, 0, INTERRUPT_ID_UART);
993 }
994
995 /* order matters here... the trick is that flags
996 * is updated... in request_irq - to immediatedly obliterate
997 * it is unwise.
998 */
999 spin_unlock_irqrestore(&bcm963xx_serial_lock, flags);
1000 return 0;
1001 }
1002
1003 module_init(bcm63xx_serialinit);
1004
1005 /* --------------------------------------------------------------------------
1006 Name: bcm_console_print
1007 Purpose: bcm_console_print is registered for printk.
1008 The console_lock must be held when we get here.
1009 -------------------------------------------------------------------------- */
1010 static void bcm_console_print (struct console * cons, const char * str,
1011 unsigned int count)
1012 {
1013 unsigned int i;
1014 //_puts(str);
1015 for(i=0; i<count; i++, str++)
1016 {
1017 _putc(*str);
1018 if (*str == 10)
1019 {
1020 _putc(13);
1021 }
1022 }
1023 }
1024
1025 static struct tty_driver * bcm_console_device(struct console * c, int *index)
1026 {
1027 *index = c->index;
1028 return serial_driver;
1029 }
1030
1031 static int __init bcm_console_setup(struct console * co, char * options)
1032 {
1033 return 0;
1034 }
1035
1036 static struct console bcm_sercons = {
1037 .name = "ttyS",
1038 .write = bcm_console_print,
1039 .device = bcm_console_device,
1040 .setup = bcm_console_setup,
1041 .flags = CON_PRINTBUFFER,
1042 .index = -1,
1043 };
1044
1045 static int __init bcm63xx_console_init(void)
1046 {
1047 register_console(&bcm_sercons);
1048 return 0;
1049 }
1050
1051 console_initcall(bcm63xx_console_init);