dz.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:37k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * dz.c: Serial port driver for DECStations equiped 
  3.  *       with the DZ chipset.
  4.  *
  5.  * Copyright (C) 1998 Olivier A. D. Lebaillif 
  6.  *             
  7.  * Email: olivier.lebaillif@ifrsys.com
  8.  *
  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
  17.  Qua Jun 27 15:02:26 BRT 2001
  18.  * [27-JUN-2001] Arnaldo Carvalho de Melo <acme@conectiva.com.br> - cleanups
  19.  *  
  20.  * Parts (C) 1999 David Airlie, airlied@linux.ie 
  21.  * [07-SEP-99] Bugfixes 
  22.  */
  23. #define DEBUG_DZ 1
  24. #include <linux/config.h>
  25. #include <linux/version.h>
  26. #include <linux/kernel.h>
  27. #include <linux/sched.h>
  28. #include <linux/init.h>
  29. #include <linux/slab.h>
  30. #include <linux/mm.h>
  31. #include <linux/major.h>
  32. #include <linux/module.h>
  33. #include <linux/param.h>
  34. #include <linux/tqueue.h>
  35. #include <linux/interrupt.h>
  36. #include <asm-mips/wbflush.h>
  37. #include <asm/dec/interrupts.h>
  38. #include <linux/console.h>
  39. #include <linux/tty.h>
  40. #include <linux/tty_flip.h>
  41. #include <linux/serial.h>
  42. #include <asm/uaccess.h>
  43. #include <asm/irq.h>
  44. #include <asm/dec/machtype.h>
  45. #include <asm/dec/kn01.h>
  46. #include <asm/dec/kn02.h>
  47. #include <linux/ptrace.h>
  48. #include <linux/fs.h>
  49. #include <asm/bootinfo.h>
  50. #define CONSOLE_LINE (3) /* for definition of struct console */
  51. extern int (*prom_printf) (char *,...);
  52. #include "dz.h"
  53. #define DZ_INTR_DEBUG 1
  54. DECLARE_TASK_QUEUE(tq_serial);
  55. static struct dz_serial *lines[4];
  56. static unsigned char tmp_buffer[256];
  57. #ifdef DEBUG_DZ
  58. /*
  59.  * debugging code to send out chars via prom 
  60.  */
  61. static void debug_console(const char *s, int count)
  62. {
  63. unsigned i;
  64. for (i = 0; i < count; i++) {
  65. if (*s == 10)
  66. prom_printf("%c", 13);
  67. prom_printf("%c", *s++);
  68. }
  69. }
  70. #endif
  71. /*
  72.  * ------------------------------------------------------------
  73.  * dz_in () and dz_out ()
  74.  *
  75.  * These routines are used to access the registers of the DZ 
  76.  * chip, hiding relocation differences between implementation.
  77.  * ------------------------------------------------------------
  78.  */
  79. static inline unsigned short dz_in(struct dz_serial *info, unsigned offset)
  80. {
  81. volatile unsigned short *addr =
  82. (volatile unsigned short *) (info->port + offset);
  83. return *addr;
  84. }
  85. static inline void dz_out(struct dz_serial *info, unsigned offset,
  86.                           unsigned short value)
  87. {
  88. volatile unsigned short *addr =
  89. (volatile unsigned short *) (info->port + offset);
  90. *addr = value;
  91. }
  92. /*
  93.  * ------------------------------------------------------------
  94.  * rs_stop () and rs_start ()
  95.  *
  96.  * These routines are called before setting or resetting 
  97.  * tty->stopped. They enable or disable transmitter interrupts, 
  98.  * as necessary.
  99.  * ------------------------------------------------------------
  100.  */
  101. static void dz_stop(struct tty_struct *tty)
  102. {
  103. struct dz_serial *info;
  104. unsigned short mask, tmp;
  105. if (tty == 0)
  106. return;
  107. info = (struct dz_serial *) tty->driver_data;
  108. mask = 1 << info->line;
  109. tmp = dz_in(info, DZ_TCR); /* read the TX flag */
  110. tmp &= ~mask; /* clear the TX flag */
  111. dz_out(info, DZ_TCR, tmp);
  112. }
  113. static void dz_start(struct tty_struct *tty)
  114. {
  115. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  116. unsigned short mask, tmp;
  117. mask = 1 << info->line;
  118. tmp = dz_in(info, DZ_TCR); /* read the TX flag */
  119. tmp |= mask; /* set the TX flag */
  120. dz_out(info, DZ_TCR, tmp);
  121. }
  122. /*
  123.  * ------------------------------------------------------------
  124.  * Here starts the interrupt handling routines.  All of the 
  125.  * following subroutines are declared as inline and are folded 
  126.  * into dz_interrupt.  They were separated out for readability's 
  127.  * sake. 
  128.  *
  129.  * Note: rs_interrupt() is a "fast" interrupt, which means that it
  130.  * runs with interrupts turned off.  People who may want to modify
  131.  * rs_interrupt() should try to keep the interrupt handler as fast as
  132.  * possible.  After you are done making modifications, it is not a bad
  133.  * idea to do:
  134.  * 
  135.  * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer dz.c
  136.  *
  137.  * and look at the resulting assemble code in serial.s.
  138.  *
  139.  * ------------------------------------------------------------
  140.  */
  141. /*
  142.  * ------------------------------------------------------------
  143.  * dz_sched_event ()
  144.  *
  145.  * This routine is used by the interrupt handler to schedule
  146.  * processing in the software interrupt portion of the driver.
  147.  * ------------------------------------------------------------
  148.  */
  149. static inline void dz_sched_event(struct dz_serial *info, int event)
  150. {
  151. info->event |= 1 << event;
  152. queue_task(&info->tqueue, &tq_serial);
  153. mark_bh(SERIAL_BH);
  154. }
  155. /*
  156.  * ------------------------------------------------------------
  157.  * receive_char ()
  158.  *
  159.  * This routine deals with inputs from any lines.
  160.  * ------------------------------------------------------------
  161.  */
  162. static inline void receive_chars(struct dz_serial *info_in)
  163. {
  164. struct dz_serial *info;
  165. struct tty_struct *tty = 0;
  166. struct async_icount *icount;
  167. int ignore = 0;
  168. unsigned short status, tmp;
  169. unsigned char ch;
  170. /* this code is going to be a problem...
  171.    the call to tty_flip_buffer is going to need
  172.    to be rethought...
  173.  */
  174. do {
  175. status = dz_in(info_in, DZ_RBUF);
  176. info = lines[LINE(status)];
  177. /* punt so we don't get duplicate characters */
  178. if (!(status & DZ_DVAL))
  179. goto ignore_char;
  180. ch = UCHAR(status); /* grab the char */
  181. #if 0
  182. if (info->is_console) {
  183. if (ch == 0)
  184. return; /* it's a break ... */
  185. }
  186. #endif
  187. tty = info->tty; /* now tty points to the proper dev */
  188. icount = &info->icount;
  189. if (!tty)
  190. break;
  191. if (tty->flip.count >= TTY_FLIPBUF_SIZE)
  192. break;
  193. *tty->flip.char_buf_ptr = ch;
  194. *tty->flip.flag_buf_ptr = 0;
  195. icount->rx++;
  196. /* keep track of the statistics */
  197. if (status & (DZ_OERR | DZ_FERR | DZ_PERR)) {
  198. if (status & DZ_PERR) /* parity error */
  199. icount->parity++;
  200. else if (status & DZ_FERR) /* frame error */
  201. icount->frame++;
  202. if (status & DZ_OERR) /* overrun error */
  203. icount->overrun++;
  204. /*  check to see if we should ignore the character
  205.    and mask off conditions that should be ignored
  206.  */
  207. if (status & info->ignore_status_mask) {
  208. if (++ignore > 100)
  209. break;
  210. goto ignore_char;
  211. }
  212. /* mask off the error conditions we want to ignore */
  213. tmp = status & info->read_status_mask;
  214. if (tmp & DZ_PERR) {
  215. *tty->flip.flag_buf_ptr = TTY_PARITY;
  216. debug_console("PERRn", 5);
  217. } else if (tmp & DZ_FERR) {
  218. *tty->flip.flag_buf_ptr = TTY_FRAME;
  219. debug_console("FERRn", 5);
  220. }
  221. if (tmp & DZ_OERR) {
  222. debug_console("OERRn", 5);
  223. if (tty->flip.count < TTY_FLIPBUF_SIZE) {
  224. tty->flip.count++;
  225. tty->flip.flag_buf_ptr++;
  226. tty->flip.char_buf_ptr++;
  227. *tty->flip.flag_buf_ptr = TTY_OVERRUN;
  228. }
  229. }
  230. }
  231. tty->flip.flag_buf_ptr++;
  232. tty->flip.char_buf_ptr++;
  233. tty->flip.count++;
  234.       ignore_char:
  235. } while (status & DZ_DVAL);
  236. if (tty)
  237. tty_flip_buffer_push(tty);
  238. }
  239. /*
  240.  * ------------------------------------------------------------
  241.  * transmit_char ()
  242.  *
  243.  * This routine deals with outputs to any lines.
  244.  * ------------------------------------------------------------
  245.  */
  246. static inline void transmit_chars(struct dz_serial *info)
  247. {
  248. unsigned char tmp;
  249. if (info->x_char) { /* XON/XOFF chars */
  250. dz_out(info, DZ_TDR, info->x_char);
  251. info->icount.tx++;
  252. info->x_char = 0;
  253. return;
  254. }
  255. /* if nothing to do or stopped or hardware stopped */
  256. if ((info->xmit_cnt <= 0) || info->tty->stopped || info->tty->hw_stopped) {
  257. dz_stop(info->tty);
  258. return;
  259. }
  260. /*
  261.  * if something to do ... (rember the dz has no output fifo so we go
  262.  * one char at a time :-<
  263.  */
  264. tmp = (unsigned short) info->xmit_buf[info->xmit_tail++];
  265. dz_out(info, DZ_TDR, tmp);
  266. info->xmit_tail = info->xmit_tail & (DZ_XMIT_SIZE - 1);
  267. info->icount.tx++;
  268. if (--info->xmit_cnt < WAKEUP_CHARS)
  269. dz_sched_event(info, DZ_EVENT_WRITE_WAKEUP);
  270. /* Are we done */
  271. if (info->xmit_cnt <= 0)
  272. dz_stop(info->tty);
  273. }
  274. /*
  275.  * ------------------------------------------------------------
  276.  * check_modem_status ()
  277.  *
  278.  * Only valid for the MODEM line duh !
  279.  * ------------------------------------------------------------
  280.  */
  281. static inline void check_modem_status(struct dz_serial *info)
  282. {
  283. unsigned short status;
  284. /* if not ne modem line just return */
  285. if (info->line != DZ_MODEM)
  286. return;
  287. status = dz_in(info, DZ_MSR);
  288. /* it's easy, since DSR2 is the only bit in the register */
  289. if (status)
  290. info->icount.dsr++;
  291. }
  292. /*
  293.  * ------------------------------------------------------------
  294.  * dz_interrupt ()
  295.  *
  296.  * this is the main interrupt routine for the DZ chip.
  297.  * It deals with the multiple ports.
  298.  * ------------------------------------------------------------
  299.  */
  300. static void dz_interrupt(int irq, void *dev, struct pt_regs *regs)
  301. {
  302. struct dz_serial *info;
  303. unsigned short status;
  304. /* get the reason why we just got an irq */
  305. status = dz_in((struct dz_serial *) dev, DZ_CSR);
  306. info = lines[LINE(status)]; /* re-arrange info the proper port */
  307. if (status & DZ_RDONE)
  308. receive_chars(info); /* the receive function */
  309. if (status & DZ_TRDY)
  310. transmit_chars(info);
  311. }
  312. /*
  313.  * -------------------------------------------------------------------
  314.  * Here ends the DZ interrupt routines.
  315.  * -------------------------------------------------------------------
  316.  */
  317. /*
  318.  * This routine is used to handle the "bottom half" processing for the
  319.  * serial driver, known also the "software interrupt" processing.
  320.  * This processing is done at the kernel interrupt level, after the
  321.  * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
  322.  * is where time-consuming activities which can not be done in the
  323.  * interrupt driver proper are done; the interrupt driver schedules
  324.  * them using rs_sched_event(), and they get done here.
  325.  */
  326. static void do_serial_bh(void)
  327. {
  328. run_task_queue(&tq_serial);
  329. }
  330. static void do_softint(void *private_data)
  331. {
  332. struct dz_serial *info = (struct dz_serial *) private_data;
  333. struct tty_struct *tty = info->tty;
  334. if (!tty)
  335. return;
  336. if (test_and_clear_bit(DZ_EVENT_WRITE_WAKEUP, &info->event)) {
  337. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
  338. (tty->ldisc.write_wakeup) (tty);
  339. wake_up_interruptible(&tty->write_wait);
  340. }
  341. }
  342. /*
  343.  * -------------------------------------------------------------------
  344.  * This routine is called from the scheduler tqueue when the interrupt
  345.  * routine has signalled that a hangup has occurred.  The path of
  346.  * hangup processing is:
  347.  *
  348.  *      serial interrupt routine -> (scheduler tqueue) ->
  349.  *      do_serial_hangup() -> tty->hangup() -> rs_hangup()
  350.  * ------------------------------------------------------------------- 
  351.  */
  352. static void do_serial_hangup(void *private_data)
  353. {
  354. struct dz_serial *info = (struct dz_serial *) private_data;
  355. struct tty_struct *tty = info->tty;;
  356. if (!tty)
  357. return;
  358. tty_hangup(tty);
  359. }
  360. /*
  361.  * -------------------------------------------------------------------
  362.  * startup ()
  363.  *
  364.  * various initialization tasks
  365.  * ------------------------------------------------------------------- 
  366.  */
  367. static int startup(struct dz_serial *info)
  368. {
  369. unsigned long page, flags;
  370. unsigned short tmp;
  371. if (info->is_initialized)
  372. return 0;
  373. save_flags(flags);
  374. cli();
  375. if (!info->port) {
  376. if (info->tty)
  377. set_bit(TTY_IO_ERROR, &info->tty->flags);
  378. restore_flags(flags);
  379. return -ENODEV;
  380. }
  381. if (!info->xmit_buf) {
  382. page = get_free_page(GFP_KERNEL);
  383. if (!page) {
  384. restore_flags(flags);
  385. return -ENOMEM;
  386. }
  387. info->xmit_buf = (unsigned char *) page;
  388. }
  389. if (info->tty)
  390. clear_bit(TTY_IO_ERROR, &info->tty->flags);
  391. /* enable the interrupt and the scanning */
  392. tmp = dz_in(info, DZ_CSR);
  393. tmp |= (DZ_RIE | DZ_TIE | DZ_MSE);
  394. dz_out(info, DZ_CSR, tmp);
  395. info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
  396. /* set up the speed */
  397. change_speed(info);
  398. /* clear the line transmitter buffer 
  399.    I can't figure out why I need to do this - but
  400.    its necessary - in order for the console portion
  401.    and the interrupt portion to live happily side by side.
  402.  */
  403. /* clear the line transmitter buffer 
  404.    I can't figure out why I need to do this - but
  405.    its necessary - in order for the console portion
  406.    and the interrupt portion to live happily side by side.
  407.  */
  408. info->is_initialized = 1;
  409. restore_flags(flags);
  410. return 0;
  411. }
  412. /* 
  413.  * -------------------------------------------------------------------
  414.  * shutdown ()
  415.  *
  416.  * This routine will shutdown a serial port; interrupts are disabled, and
  417.  * DTR is dropped if the hangup on close termio flag is on.
  418.  * ------------------------------------------------------------------- 
  419.  */
  420. static void shutdown(struct dz_serial *info)
  421. {
  422. unsigned long flags;
  423. unsigned short tmp;
  424. if (!info->is_initialized)
  425. return;
  426. save_flags(flags);
  427. cli();
  428. dz_stop(info->tty);
  429. info->cflags &= ~DZ_CREAD; /* turn off receive enable flag */
  430. dz_out(info, DZ_LPR, info->cflags);
  431. if (info->xmit_buf) { /* free Tx buffer */
  432. free_page((unsigned long) info->xmit_buf);
  433. info->xmit_buf = 0;
  434. }
  435. if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
  436. tmp = dz_in(info, DZ_TCR);
  437. if (tmp & DZ_MODEM_DTR) {
  438. tmp &= ~DZ_MODEM_DTR;
  439. dz_out(info, DZ_TCR, tmp);
  440. }
  441. }
  442. if (info->tty)
  443. set_bit(TTY_IO_ERROR, &info->tty->flags);
  444. info->is_initialized = 0;
  445. restore_flags(flags);
  446. }
  447. /* 
  448.  * -------------------------------------------------------------------
  449.  * change_speed ()
  450.  *
  451.  * set the baud rate.
  452.  * ------------------------------------------------------------------- 
  453.  */
  454. static void change_speed(struct dz_serial *info)
  455. {
  456. unsigned long flags;
  457. unsigned cflag;
  458. int baud;
  459. if (!info->tty || !info->tty->termios)
  460. return;
  461. save_flags(flags);
  462. cli();
  463. info->cflags = info->line;
  464. cflag = info->tty->termios->c_cflag;
  465. switch (cflag & CSIZE) {
  466. case CS5:
  467. info->cflags |= DZ_CS5;
  468. break;
  469. case CS6:
  470. info->cflags |= DZ_CS6;
  471. break;
  472. case CS7:
  473. info->cflags |= DZ_CS7;
  474. break;
  475. case CS8:
  476. default:
  477. info->cflags |= DZ_CS8;
  478. }
  479. if (cflag & CSTOPB)
  480. info->cflags |= DZ_CSTOPB;
  481. if (cflag & PARENB)
  482. info->cflags |= DZ_PARENB;
  483. if (cflag & PARODD)
  484. info->cflags |= DZ_PARODD;
  485. baud = tty_get_baud_rate(info->tty);
  486. switch (baud) {
  487. case 50:
  488. info->cflags |= DZ_B50;
  489. break;
  490. case 75:
  491. info->cflags |= DZ_B75;
  492. break;
  493. case 110:
  494. info->cflags |= DZ_B110;
  495. break;
  496. case 134:
  497. info->cflags |= DZ_B134;
  498. break;
  499. case 150:
  500. info->cflags |= DZ_B150;
  501. break;
  502. case 300:
  503. info->cflags |= DZ_B300;
  504. break;
  505. case 600:
  506. info->cflags |= DZ_B600;
  507. break;
  508. case 1200:
  509. info->cflags |= DZ_B1200;
  510. break;
  511. case 1800:
  512. info->cflags |= DZ_B1800;
  513. break;
  514. case 2000:
  515. info->cflags |= DZ_B2000;
  516. break;
  517. case 2400:
  518. info->cflags |= DZ_B2400;
  519. break;
  520. case 3600:
  521. info->cflags |= DZ_B3600;
  522. break;
  523. case 4800:
  524. info->cflags |= DZ_B4800;
  525. break;
  526. case 7200:
  527. info->cflags |= DZ_B7200;
  528. break;
  529. case 9600:
  530. default:
  531. info->cflags |= DZ_B9600;
  532. }
  533. info->cflags |= DZ_RXENAB;
  534. dz_out(info, DZ_LPR, info->cflags);
  535. /* setup accept flag */
  536. info->read_status_mask = DZ_OERR;
  537. if (I_INPCK(info->tty))
  538. info->read_status_mask |= (DZ_FERR | DZ_PERR);
  539. /* characters to ignore */
  540. info->ignore_status_mask = 0;
  541. if (I_IGNPAR(info->tty))
  542. info->ignore_status_mask |= (DZ_FERR | DZ_PERR);
  543. restore_flags(flags);
  544. }
  545. /* 
  546.  * -------------------------------------------------------------------
  547.  * dz_flush_char ()
  548.  *
  549.  * Flush the buffer.
  550.  * ------------------------------------------------------------------- 
  551.  */
  552. static void dz_flush_chars(struct tty_struct *tty)
  553. {
  554. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  555. unsigned long flags;
  556. if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || !info->xmit_buf)
  557. return;
  558. save_flags(flags);
  559. cli();
  560. dz_start(info->tty);
  561. restore_flags(flags);
  562. }
  563. /* 
  564.  * -------------------------------------------------------------------
  565.  * dz_write ()
  566.  *
  567.  * main output routine.
  568.  * ------------------------------------------------------------------- 
  569.  */
  570. static int dz_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
  571. {
  572. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  573. unsigned long flags;
  574. int c, ret = 0;
  575. if (!tty)
  576. return ret;
  577. if (!info->xmit_buf)
  578. return ret;
  579. if (!tmp_buf)
  580. tmp_buf = tmp_buffer;
  581. if (from_user) {
  582. down(&tmp_buf_sem);
  583. while (1) {
  584. c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
  585. if (c <= 0)
  586. break;
  587. c -= copy_from_user(tmp_buf, buf, c);
  588. if (!c) {
  589. if (!ret)
  590. ret = -EFAULT;
  591. break;
  592. }
  593. save_flags(flags);
  594. cli();
  595. c = MIN(c, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
  596. memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
  597. info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE - 1));
  598. info->xmit_cnt += c;
  599. restore_flags(flags);
  600. buf += c;
  601. count -= c;
  602. ret += c;
  603. }
  604. up(&tmp_buf_sem);
  605. } else {
  606. while (1) {
  607. save_flags(flags);
  608. cli();
  609. c = MIN(count, MIN(DZ_XMIT_SIZE - info->xmit_cnt - 1, DZ_XMIT_SIZE - info->xmit_head));
  610. if (c <= 0) {
  611. restore_flags(flags);
  612. break;
  613. }
  614. memcpy(info->xmit_buf + info->xmit_head, buf, c);
  615. info->xmit_head = ((info->xmit_head + c) & (DZ_XMIT_SIZE - 1));
  616. info->xmit_cnt += c;
  617. restore_flags(flags);
  618. buf += c;
  619. count -= c;
  620. ret += c;
  621. }
  622. }
  623. if (info->xmit_cnt) {
  624. if (!tty->stopped) {
  625. if (!tty->hw_stopped) {
  626. dz_start(info->tty);
  627. }
  628. }
  629. }
  630. return ret;
  631. }
  632. /* 
  633.  * -------------------------------------------------------------------
  634.  * dz_write_room ()
  635.  *
  636.  * compute the amount of space available for writing.
  637.  * ------------------------------------------------------------------- 
  638.  */
  639. static int dz_write_room(struct tty_struct *tty)
  640. {
  641. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  642. int ret;
  643. ret = DZ_XMIT_SIZE - info->xmit_cnt - 1;
  644. if (ret < 0)
  645. ret = 0;
  646. return ret;
  647. }
  648. /* 
  649.  * -------------------------------------------------------------------
  650.  * dz_chars_in_buffer ()
  651.  *
  652.  * compute the amount of char left to be transmitted
  653.  * ------------------------------------------------------------------- 
  654.  */
  655. static int dz_chars_in_buffer(struct tty_struct *tty)
  656. {
  657. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  658. return info->xmit_cnt;
  659. }
  660. /* 
  661.  * -------------------------------------------------------------------
  662.  * dz_flush_buffer ()
  663.  *
  664.  * Empty the output buffer
  665.  * ------------------------------------------------------------------- 
  666.  */
  667. static void dz_flush_buffer(struct tty_struct *tty)
  668. {
  669. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  670. cli();
  671. info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
  672. sti();
  673. wake_up_interruptible(&tty->write_wait);
  674. if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
  675. (tty->ldisc.write_wakeup) (tty);
  676. }
  677. /*
  678.  * ------------------------------------------------------------
  679.  * dz_throttle () and dz_unthrottle ()
  680.  * 
  681.  * This routine is called by the upper-layer tty layer to signal that
  682.  * incoming characters should be throttled (or not).
  683.  * ------------------------------------------------------------
  684.  */
  685. static void dz_throttle(struct tty_struct *tty)
  686. {
  687. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  688. if (I_IXOFF(tty))
  689. info->x_char = STOP_CHAR(tty);
  690. }
  691. static void dz_unthrottle(struct tty_struct *tty)
  692. {
  693. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  694. if (I_IXOFF(tty)) {
  695. if (info->x_char)
  696. info->x_char = 0;
  697. else
  698. info->x_char = START_CHAR(tty);
  699. }
  700. }
  701. static void dz_send_xchar(struct tty_struct *tty, char ch)
  702. {
  703. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  704. info->x_char = ch;
  705. if (ch)
  706. dz_start(info->tty);
  707. }
  708. /*
  709.  * ------------------------------------------------------------
  710.  * rs_ioctl () and friends
  711.  * ------------------------------------------------------------
  712.  */
  713. static int get_serial_info(struct dz_serial *info,
  714.                            struct serial_struct *retinfo)
  715. {
  716. struct serial_struct tmp;
  717. if (!retinfo)
  718. return -EFAULT;
  719. memset(&tmp, 0, sizeof(tmp));
  720. tmp.type = info->type;
  721. tmp.line = info->line;
  722. tmp.port = info->port;
  723. tmp.irq = SERIAL;
  724. tmp.flags = info->flags;
  725. tmp.baud_base = info->baud_base;
  726. tmp.close_delay = info->close_delay;
  727. tmp.closing_wait = info->closing_wait;
  728. return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
  729. }
  730. static int set_serial_info(struct dz_serial *info,
  731.                            struct serial_struct *new_info)
  732. {
  733. struct serial_struct new_serial;
  734. struct dz_serial old_info;
  735. int retval = 0;
  736. if (!new_info)
  737. return -EFAULT;
  738. if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
  739. return -EFAULT;
  740. old_info = *info;
  741. if (!capable(CAP_SYS_ADMIN))
  742. return -EPERM;
  743. if (info->count > 1)
  744. return -EBUSY;
  745. /*
  746.  * OK, past this point, all the error checking has been done.
  747.  * At this point, we start making changes.....
  748.  */
  749. info->baud_base = new_serial.baud_base;
  750. info->type = new_serial.type;
  751. info->close_delay = new_serial.close_delay;
  752. info->closing_wait = new_serial.closing_wait;
  753. retval = startup(info);
  754. return retval;
  755. }
  756. /*
  757.  * get_lsr_info - get line status register info
  758.  *
  759.  * Purpose: Let user call ioctl() to get info when the UART physically
  760.  *          is emptied.  On bus types like RS485, the transmitter must
  761.  *          release the bus after transmitting. This must be done when
  762.  *          the transmit shift register is empty, not be done when the
  763.  *          transmit holding register is empty.  This functionality
  764.  *          allows an RS485 driver to be written in user space. 
  765.  */
  766. static int get_lsr_info(struct dz_serial *info, unsigned int *value)
  767. {
  768. unsigned short status = dz_in(info, DZ_LPR);
  769. return put_user(status, value);
  770. }
  771. /*
  772.  * This routine sends a break character out the serial port.
  773.  */
  774. static void send_break(struct dz_serial *info, int duration)
  775. {
  776. unsigned long flags;
  777. unsigned short tmp, mask;
  778. if (!info->port)
  779. return;
  780. mask = 1 << info->line;
  781. tmp = dz_in(info, DZ_TCR);
  782. tmp |= mask;
  783. current->state = TASK_INTERRUPTIBLE;
  784. save_flags(flags);
  785. cli();
  786. dz_out(info, DZ_TCR, tmp);
  787. schedule_timeout(duration);
  788. tmp &= ~mask;
  789. dz_out(info, DZ_TCR, tmp);
  790. restore_flags(flags);
  791. }
  792. static int dz_ioctl(struct tty_struct *tty, struct file *file,
  793.     unsigned int cmd, unsigned long arg)
  794. {
  795. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  796. int retval;
  797. if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
  798.     (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD) &&
  799.     (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
  800. if (tty->flags & (1 << TTY_IO_ERROR))
  801. return -EIO;
  802. }
  803. switch (cmd) {
  804. case TCSBRK: /* SVID version: non-zero arg --> no break */
  805. retval = tty_check_change(tty);
  806. if (retval)
  807. return retval;
  808. tty_wait_until_sent(tty, 0);
  809. if (!arg)
  810. send_break(info, HZ / 4); /* 1/4 second */
  811. return 0;
  812. case TCSBRKP: /* support for POSIX tcsendbreak() */
  813. retval = tty_check_change(tty);
  814. if (retval)
  815. return retval;
  816. tty_wait_until_sent(tty, 0);
  817. send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
  818. return 0;
  819. case TIOCGSOFTCAR:
  820. return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
  821. case TIOCSSOFTCAR:
  822. if (get_user(arg, (unsigned long *) arg))
  823. return -EFAULT;
  824. tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
  825.                          (arg ? CLOCAL : 0));
  826. return 0;
  827. case TIOCGSERIAL:
  828. return get_serial_info(info, (struct serial_struct *) arg);
  829. case TIOCSSERIAL:
  830. return set_serial_info(info, (struct serial_struct *) arg);
  831. case TIOCSERGETLSR: /* Get line status register */
  832. return get_lsr_info(info, (unsigned int *) arg);
  833. case TIOCSERGSTRUCT:
  834. return copy_to_user((struct dz_serial *) arg, info,
  835.  sizeof(struct dz_serial)) ? -EFAULT : 0;
  836. default:
  837. return -ENOIOCTLCMD;
  838. }
  839. return 0;
  840. }
  841. static void dz_set_termios(struct tty_struct *tty,
  842.    struct termios *old_termios)
  843. {
  844. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  845. if (tty->termios->c_cflag == old_termios->c_cflag)
  846. return;
  847. change_speed(info);
  848. if ((old_termios->c_cflag & CRTSCTS) &&
  849.     !(tty->termios->c_cflag & CRTSCTS)) {
  850. tty->hw_stopped = 0;
  851. dz_start(tty);
  852. }
  853. }
  854. /*
  855.  * ------------------------------------------------------------
  856.  * dz_close()
  857.  * 
  858.  * This routine is called when the serial port gets closed.  First, we
  859.  * wait for the last remaining data to be sent.  Then, we turn off
  860.  * the transmit enable and receive enable flags.
  861.  * ------------------------------------------------------------
  862.  */
  863. static void dz_close(struct tty_struct *tty, struct file *filp)
  864. {
  865. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  866. unsigned long flags;
  867. if (!info)
  868. return;
  869. save_flags(flags);
  870. cli();
  871. if (tty_hung_up_p(filp)) {
  872. restore_flags(flags);
  873. return;
  874. }
  875. if ((tty->count == 1) && (info->count != 1)) {
  876. /*
  877.  * Uh, oh.  tty->count is 1, which means that the tty
  878.  * structure will be freed.  Info->count should always
  879.  * be one in these conditions.  If it's greater than
  880.  * one, we've got real problems, since it means the
  881.  * serial port won't be shutdown.
  882.  */
  883. printk("dz_close: bad serial port count; tty->count is 1, "
  884.        "info->count is %dn", info->count);
  885. info->count = 1;
  886. }
  887. if (--info->count < 0) {
  888. printk("ds_close: bad serial port count for ttyS%02d: %dn",
  889.        info->line, info->count);
  890. info->count = 0;
  891. }
  892. if (info->count) {
  893. restore_flags(flags);
  894. return;
  895. }
  896. info->flags |= DZ_CLOSING;
  897. /*
  898.  * Save the termios structure, since this port may have
  899.  * separate termios for callout and dialin.
  900.  */
  901. if (info->flags & DZ_NORMAL_ACTIVE)
  902. info->normal_termios = *tty->termios;
  903. if (info->flags & DZ_CALLOUT_ACTIVE)
  904. info->callout_termios = *tty->termios;
  905. /*
  906.  * Now we wait for the transmit buffer to clear; and we notify 
  907.  * the line discipline to only process XON/XOFF characters.
  908.  */
  909. tty->closing = 1;
  910. if (info->closing_wait != DZ_CLOSING_WAIT_NONE)
  911. tty_wait_until_sent(tty, info->closing_wait);
  912. /*
  913.  * At this point we stop accepting input.  To do this, we
  914.  * disable the receive line status interrupts.
  915.  */
  916. shutdown(info);
  917. if (tty->driver.flush_buffer)
  918. tty->driver.flush_buffer(tty);
  919. if (tty->ldisc.flush_buffer)
  920. tty->ldisc.flush_buffer(tty);
  921. tty->closing = 0;
  922. info->event = 0;
  923. info->tty = 0;
  924. if (tty->ldisc.num != ldiscs[N_TTY].num) {
  925. if (tty->ldisc.close)
  926. (tty->ldisc.close) (tty);
  927. tty->ldisc = ldiscs[N_TTY];
  928. tty->termios->c_line = N_TTY;
  929. if (tty->ldisc.open)
  930. (tty->ldisc.open) (tty);
  931. }
  932. if (info->blocked_open) {
  933. if (info->close_delay) {
  934. current->state = TASK_INTERRUPTIBLE;
  935. schedule_timeout(info->close_delay);
  936. }
  937. wake_up_interruptible(&info->open_wait);
  938. }
  939. info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE | DZ_CLOSING);
  940. wake_up_interruptible(&info->close_wait);
  941. restore_flags(flags);
  942. }
  943. /*
  944.  * dz_hangup () --- called by tty_hangup() when a hangup is signaled.
  945.  */
  946. static void dz_hangup(struct tty_struct *tty)
  947. {
  948. struct dz_serial *info = (struct dz_serial *) tty->driver_data;
  949. dz_flush_buffer(tty);
  950. shutdown(info);
  951. info->event = 0;
  952. info->count = 0;
  953. info->flags &= ~(DZ_NORMAL_ACTIVE | DZ_CALLOUT_ACTIVE);
  954. info->tty = 0;
  955. wake_up_interruptible(&info->open_wait);
  956. }
  957. /*
  958.  * ------------------------------------------------------------
  959.  * rs_open() and friends
  960.  * ------------------------------------------------------------
  961.  */
  962. static int block_til_ready(struct tty_struct *tty, struct file *filp, struct dz_serial *info)
  963. {
  964. DECLARE_WAITQUEUE(wait, current);
  965. int retval;
  966. int do_clocal = 0;
  967. /*
  968.  * If the device is in the middle of being closed, then block
  969.  * until it's done, and then try again.
  970.  */
  971. if (info->flags & DZ_CLOSING) {
  972. interruptible_sleep_on(&info->close_wait);
  973. return -EAGAIN;
  974. }
  975. /*
  976.  * If this is a callout device, then just make sure the normal
  977.  * device isn't being used.
  978.  */
  979. if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
  980. if (info->flags & DZ_NORMAL_ACTIVE)
  981. return -EBUSY;
  982. if ((info->flags & DZ_CALLOUT_ACTIVE) &&
  983.     (info->flags & DZ_SESSION_LOCKOUT) &&
  984.     (info->session != current->session))
  985. return -EBUSY;
  986. if ((info->flags & DZ_CALLOUT_ACTIVE) &&
  987.     (info->flags & DZ_PGRP_LOCKOUT) &&
  988.     (info->pgrp != current->pgrp))
  989. return -EBUSY;
  990. info->flags |= DZ_CALLOUT_ACTIVE;
  991. return 0;
  992. }
  993. /*
  994.  * If non-blocking mode is set, or the port is not enabled,
  995.  * then make the check up front and then exit.
  996.  */
  997. if ((filp->f_flags & O_NONBLOCK) ||
  998.     (tty->flags & (1 << TTY_IO_ERROR))) {
  999. if (info->flags & DZ_CALLOUT_ACTIVE)
  1000. return -EBUSY;
  1001. info->flags |= DZ_NORMAL_ACTIVE;
  1002. return 0;
  1003. }
  1004. if (info->flags & DZ_CALLOUT_ACTIVE) {
  1005. if (info->normal_termios.c_cflag & CLOCAL)
  1006. do_clocal = 1;
  1007. } else {
  1008. if (tty->termios->c_cflag & CLOCAL)
  1009. do_clocal = 1;
  1010. }
  1011. /*
  1012.  * Block waiting for the carrier detect and the line to become
  1013.  * free (i.e., not in use by the callout).  While we are in
  1014.  * this loop, info->count is dropped by one, so that
  1015.  * dz_close() knows when to free things.  We restore it upon
  1016.  * exit, either normal or abnormal.
  1017.  */
  1018. retval = 0;
  1019. add_wait_queue(&info->open_wait, &wait);
  1020. info->count--;
  1021. info->blocked_open++;
  1022. while (1) {
  1023. set_current_state(TASK_INTERRUPTIBLE);
  1024. if (tty_hung_up_p(filp) || !(info->is_initialized)) {
  1025. retval = -EAGAIN;
  1026. break;
  1027. }
  1028. if (!(info->flags & DZ_CALLOUT_ACTIVE) &&
  1029.     !(info->flags & DZ_CLOSING) && do_clocal)
  1030. break;
  1031. if (signal_pending(current)) {
  1032. retval = -ERESTARTSYS;
  1033. break;
  1034. }
  1035. schedule();
  1036. }
  1037. current->state = TASK_RUNNING;
  1038. remove_wait_queue(&info->open_wait, &wait);
  1039. if (!tty_hung_up_p(filp))
  1040. info->count++;
  1041. info->blocked_open--;
  1042. if (retval)
  1043. return retval;
  1044. info->flags |= DZ_NORMAL_ACTIVE;
  1045. return 0;
  1046. }
  1047. /*
  1048.  * This routine is called whenever a serial port is opened.  It
  1049.  * enables interrupts for a serial port. It also performs the 
  1050.  * serial-specific initialization for the tty structure.
  1051.  */
  1052. static int dz_open(struct tty_struct *tty, struct file *filp)
  1053. {
  1054. struct dz_serial *info;
  1055. int retval, line;
  1056. line = MINOR(tty->device) - tty->driver.minor_start;
  1057. /* The dz lines for the mouse/keyboard must be
  1058.  * opened using their respective drivers.
  1059.  */
  1060. if ((line < 0) || (line >= DZ_NB_PORT))
  1061. return -ENODEV;
  1062. if ((line == DZ_KEYBOARD) || (line == DZ_MOUSE))
  1063. return -ENODEV;
  1064. info = lines[line];
  1065. info->count++;
  1066. tty->driver_data = info;
  1067. info->tty = tty;
  1068. /*
  1069.  * Start up serial port
  1070.  */
  1071. retval = startup(info);
  1072. if (retval)
  1073. return retval;
  1074. retval = block_til_ready(tty, filp, info);
  1075. if (retval)
  1076. return retval;
  1077. if ((info->count == 1) && (info->flags & DZ_SPLIT_TERMIOS)) {
  1078. if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
  1079. *tty->termios = info->normal_termios;
  1080. else
  1081. *tty->termios = info->callout_termios;
  1082. change_speed(info);
  1083. }
  1084. info->session = current->session;
  1085. info->pgrp = current->pgrp;
  1086. return 0;
  1087. }
  1088. static void show_serial_version(void)
  1089. {
  1090. printk("%s%sn", dz_name, dz_version);
  1091. }
  1092. int __init dz_init(void)
  1093. {
  1094. int i, tmp;
  1095. long flags;
  1096. struct dz_serial *info;
  1097. /* Setup base handler, and timer table. */
  1098. init_bh(SERIAL_BH, do_serial_bh);
  1099. show_serial_version();
  1100. memset(&serial_driver, 0, sizeof(struct tty_driver));
  1101. serial_driver.magic = TTY_DRIVER_MAGIC;
  1102. #if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
  1103. serial_driver.name = "ttyS";
  1104. #else
  1105. serial_driver.name = "tts/%d";
  1106. #endif
  1107. serial_driver.major = TTY_MAJOR;
  1108. serial_driver.minor_start = 64;
  1109. serial_driver.num = DZ_NB_PORT;
  1110. serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
  1111. serial_driver.subtype = SERIAL_TYPE_NORMAL;
  1112. serial_driver.init_termios = tty_std_termios;
  1113. serial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL |
  1114.                                      CLOCAL;
  1115. serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
  1116. serial_driver.refcount = &serial_refcount;
  1117. serial_driver.table = serial_table;
  1118. serial_driver.termios = serial_termios;
  1119. serial_driver.termios_locked = serial_termios_locked;
  1120. serial_driver.open = dz_open;
  1121. serial_driver.close = dz_close;
  1122. serial_driver.write = dz_write;
  1123. serial_driver.flush_chars = dz_flush_chars;
  1124. serial_driver.write_room = dz_write_room;
  1125. serial_driver.chars_in_buffer = dz_chars_in_buffer;
  1126. serial_driver.flush_buffer = dz_flush_buffer;
  1127. serial_driver.ioctl = dz_ioctl;
  1128. serial_driver.throttle = dz_throttle;
  1129. serial_driver.unthrottle = dz_unthrottle;
  1130. serial_driver.send_xchar = dz_send_xchar;
  1131. serial_driver.set_termios = dz_set_termios;
  1132. serial_driver.stop = dz_stop;
  1133. serial_driver.start = dz_start;
  1134. serial_driver.hangup = dz_hangup;
  1135. /*
  1136.  * The callout device is just like normal device except for
  1137.  * major number and the subtype code.
  1138.  */
  1139. callout_driver = serial_driver;
  1140. #if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS))
  1141. callout_driver.name = "cua";
  1142. #else
  1143. callout_driver.name = "cua/%d";
  1144. #endif
  1145. callout_driver.major = TTYAUX_MAJOR;
  1146. callout_driver.subtype = SERIAL_TYPE_CALLOUT;
  1147. if (tty_register_driver(&serial_driver))
  1148. panic("Couldn't register serial driver");
  1149. if (tty_register_driver(&callout_driver))
  1150. panic("Couldn't register callout driver");
  1151. save_flags(flags);
  1152. cli();
  1153. for (i = 0; i < DZ_NB_PORT; i++) {
  1154. info = &multi[i];
  1155. lines[i] = info;
  1156. info->magic = SERIAL_MAGIC;
  1157. if (mips_machtype == MACH_DS23100 ||
  1158.     mips_machtype == MACH_DS5100)
  1159. info->port = (unsigned long) KN01_DZ11_BASE;
  1160. else
  1161. info->port = (unsigned long) KN02_DZ11_BASE;
  1162. info->line = i;
  1163. info->tty = 0;
  1164. info->close_delay = 50;
  1165. info->closing_wait = 3000;
  1166. info->x_char = 0;
  1167. info->event = 0;
  1168. info->count = 0;
  1169. info->blocked_open = 0;
  1170. info->tqueue.routine = do_softint;
  1171. info->tqueue.data = info;
  1172. info->tqueue_hangup.routine = do_serial_hangup;
  1173. info->tqueue_hangup.data = info;
  1174. info->callout_termios = callout_driver.init_termios;
  1175. info->normal_termios = serial_driver.init_termios;
  1176. init_waitqueue_head(&info->open_wait);
  1177. init_waitqueue_head(&info->close_wait);
  1178. /*
  1179.  * If we are pointing to address zero then punt - not correctly
  1180.  * set up in setup.c to handle this.
  1181.  */
  1182. if (!info->port)
  1183. return 0;
  1184. printk("ttyS%02d at 0x%08x (irq = %d)n", info->line,
  1185.        info->port, SERIAL);
  1186. tty_register_devfs(&serial_driver, 0,
  1187.  serial_driver.minor_start + info->line);
  1188. tty_register_devfs(&callout_driver, 0,
  1189. callout_driver.minor_start + info->line);
  1190. }
  1191. /* reset the chip */
  1192. #ifndef CONFIG_SERIAL_CONSOLE
  1193. dz_out(info, DZ_CSR, DZ_CLR);
  1194. while ((tmp = dz_in(info, DZ_CSR)) & DZ_CLR);
  1195. wbflush();
  1196. /* enable scanning */
  1197. dz_out(info, DZ_CSR, DZ_MSE);
  1198. #endif
  1199. /* order matters here... the trick is that flags
  1200.    is updated... in request_irq - to immediatedly obliterate
  1201.    it is unwise. */
  1202. restore_flags(flags);
  1203. if (request_irq(SERIAL, dz_interrupt, SA_INTERRUPT, "DZ", lines[0]))
  1204. panic("Unable to register DZ interrupt");
  1205. return 0;
  1206. }
  1207. #ifdef CONFIG_SERIAL_CONSOLE
  1208. static void dz_console_put_char(unsigned char ch)
  1209. {
  1210. unsigned long flags;
  1211. int loops = 2500;
  1212. unsigned short tmp = ch;
  1213. /* this code sends stuff out to serial device - spinning its
  1214.    wheels and waiting. */
  1215. /* force the issue - point it at lines[3] */
  1216. dz_console = &multi[CONSOLE_LINE];
  1217. save_flags(flags);
  1218. cli();
  1219. /* spin our wheels */
  1220. while (((dz_in(dz_console, DZ_CSR) & DZ_TRDY) != DZ_TRDY) && loops--);
  1221. /* Actually transmit the character. */
  1222. dz_out(dz_console, DZ_TDR, tmp);
  1223. restore_flags(flags);
  1224. }
  1225. /* 
  1226.  * -------------------------------------------------------------------
  1227.  * dz_console_print ()
  1228.  *
  1229.  * dz_console_print is registered for printk.
  1230.  * The console must be locked when we get here.
  1231.  * ------------------------------------------------------------------- 
  1232.  */
  1233. static void dz_console_print(struct console *cons,
  1234.      const char *str,
  1235.      unsigned int count)
  1236. {
  1237. #ifdef DEBUG_DZ
  1238. prom_printf((char *) str);
  1239. #endif
  1240. while (count--) {
  1241. if (*str == 'n')
  1242. dz_console_put_char('r');
  1243. dz_console_put_char(*str++);
  1244. }
  1245. }
  1246. static kdev_t dz_console_device(struct console *c)
  1247. {
  1248. return MKDEV(TTY_MAJOR, 64 + c->index);
  1249. }
  1250. static int __init dz_console_setup(struct console *co, char *options)
  1251. {
  1252. int baud = 9600;
  1253. int bits = 8;
  1254. int parity = 'n';
  1255. int cflag = CREAD | HUPCL | CLOCAL;
  1256. char *s;
  1257. unsigned short mask, tmp;
  1258. if (options) {
  1259. baud = simple_strtoul(options, NULL, 10);
  1260. s = options;
  1261. while (*s >= '0' && *s <= '9')
  1262. s++;
  1263. if (*s)
  1264. parity = *s++;
  1265. if (*s)
  1266. bits = *s - '0';
  1267. }
  1268. /*
  1269.  *    Now construct a cflag setting.
  1270.  */
  1271. switch (baud) {
  1272. case 1200:
  1273. cflag |= DZ_B1200;
  1274. break;
  1275. case 2400:
  1276. cflag |= DZ_B2400;
  1277. break;
  1278. case 4800:
  1279. cflag |= DZ_B4800;
  1280. break;
  1281. case 9600:
  1282. default:
  1283. cflag |= DZ_B9600;
  1284. break;
  1285. }
  1286. switch (bits) {
  1287. case 7:
  1288. cflag |= DZ_CS7;
  1289. break;
  1290. default:
  1291. case 8:
  1292. cflag |= DZ_CS8;
  1293. break;
  1294. }
  1295. switch (parity) {
  1296. case 'o':
  1297. case 'O':
  1298. cflag |= DZ_PARODD;
  1299. break;
  1300. case 'e':
  1301. case 'E':
  1302. cflag |= DZ_PARENB;
  1303. break;
  1304. }
  1305. co->cflag = cflag;
  1306. /* TOFIX: force to console line */
  1307. dz_console = &multi[CONSOLE_LINE];
  1308. if ((mips_machtype == MACH_DS23100) || (mips_machtype == MACH_DS5100))
  1309. dz_console->port = KN01_DZ11_BASE;
  1310. else
  1311. dz_console->port = KN02_DZ11_BASE;
  1312. dz_console->line = CONSOLE_LINE;
  1313. dz_out(dz_console, DZ_CSR, DZ_CLR);
  1314. while ((tmp = dz_in(dz_console, DZ_CSR)) & DZ_CLR);
  1315. /* enable scanning */
  1316. dz_out(dz_console, DZ_CSR, DZ_MSE);
  1317. /*  Set up flags... */
  1318. dz_console->cflags = 0;
  1319. dz_console->cflags |= DZ_B9600;
  1320. dz_console->cflags |= DZ_CS8;
  1321. dz_console->cflags |= DZ_PARENB;
  1322. dz_out(dz_console, DZ_LPR, dz_console->cflags);
  1323. mask = 1 << dz_console->line;
  1324. tmp = dz_in(dz_console, DZ_TCR); /* read the TX flag */
  1325. if (!(tmp & mask)) {
  1326. tmp |= mask; /* set the TX flag */
  1327. dz_out(dz_console, DZ_TCR, tmp);
  1328. }
  1329. return 0;
  1330. }
  1331. static struct console dz_sercons =
  1332. {
  1333.     name: "ttyS",
  1334.     write: dz_console_print,
  1335.     device: dz_console_device,
  1336.     setup: dz_console_setup,
  1337.     flags: CON_CONSDEV | CON_PRINTBUFFER,
  1338.     index: CONSOLE_LINE,
  1339. };
  1340. void __init dz_serial_console_init(void)
  1341. {
  1342. register_console(&dz_sercons);
  1343. }
  1344. #endif /* CONFIG_SERIAL_CONSOLE */
  1345. MODULE_LICENSE("GPL");