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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (C) 2000, 2001 Broadcom Corporation
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  * 
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  */
  18. /* 
  19.  * Driver support for the on-chip sb1250 dual-channel serial port,
  20.  * running in asynchronous mode.  Also, support for doing a serial console
  21.  * on one of those ports 
  22.  *
  23.  * The non-console part of this code is based heavily on the serial_21285.c
  24.  * driver also in this directory.  See tty_driver.h for a description of some
  25.  * of the driver functions, though it (like most of the inline code documentation :)
  26.  * is a bit out of date.  
  27.  */
  28. #include <linux/types.h>
  29. #include <linux/serial.h>
  30. #include <linux/module.h>
  31. #include <linux/console.h>
  32. #include <linux/kdev_t.h>
  33. #include <linux/major.h>
  34. #include <linux/termios.h>
  35. #include <linux/spinlock.h>
  36. #include <linux/irq.h>
  37. #include <linux/errno.h>
  38. #include <linux/tty.h>
  39. #include <linux/sched.h>
  40. #include <linux/tty_flip.h>
  41. #include <linux/timer.h>
  42. #include <linux/init.h>
  43. #include <asm/io.h>
  44. #include <asm/uaccess.h>
  45. #include <asm/sibyte/swarm.h>
  46. #include <asm/sibyte/sb1250.h>
  47. #include <asm/sibyte/sb1250_regs.h>
  48. #include <asm/sibyte/sb1250_uart.h>
  49. #include <asm/sibyte/sb1250_int.h>
  50. #include <asm/sibyte/64bit.h>
  51. /* Toggle spewing of debugging output */
  52. #undef DUART_SPEW
  53. #define DEFAULT_CFLAGS          (CS8 | B115200)
  54. /*
  55.   Still not sure what the termios structures set up here are for, 
  56.    but we have to supply pointers to them to register the tty driver
  57. */
  58. static struct tty_driver sb1250_duart_driver, sb1250_duart_callout_driver;
  59. static int ref_count;
  60. static struct tty_struct *duart_table[2];
  61. static struct termios    *duart_termios[2];
  62. static struct termios    *duart_termios_locked[2];
  63. /* This lock protects both the open flags for all the uart states as 
  64.    well as the reference count for the module */
  65. static spinlock_t          open_lock = SPIN_LOCK_UNLOCKED;
  66. /* Protect the writing stuff from contention */
  67. //static spinlock_t          console_lock = SPIN_LOCK_UNLOCKED;
  68. /* Bit fields of flags in the flags field below */
  69. #define SD_WRITE_WAKE       0x000000001
  70. typedef struct { 
  71. struct tty_struct   *tty;
  72. unsigned char       outp_buf[CONFIG_SB1250_DUART_OUTPUT_BUF_SIZE];
  73. unsigned int        outp_head;
  74. unsigned int        outp_tail;
  75. unsigned int        outp_count;
  76. spinlock_t          outp_lock;
  77. unsigned int        outp_stopped;
  78. unsigned int        open;
  79. unsigned long       flags;
  80. unsigned int        last_cflags;
  81. } uart_state_t;
  82. static uart_state_t uart_states[2] = { [0 ... 1] = {
  83. tty:                0,
  84. outp_head:          0,
  85. outp_tail:          0,
  86. outp_lock:          SPIN_LOCK_UNLOCKED,
  87. outp_count:         0,
  88. open:               0,
  89. flags:              0,
  90. last_cflags:        0,
  91. }};
  92. /*
  93.  * Inline functions local to this module 
  94.  */
  95. /*
  96.  * Mask out the passed interrupt lines at the duart level.  This should be
  97.  * called while holding the associated outp_lock.
  98.  */
  99. static inline void duart_mask_ints(unsigned int line, unsigned int mask)
  100. {
  101. u64 tmp;
  102. tmp = in64(IO_SPACE_BASE | A_DUART_IMRREG(line));
  103. tmp &= ~mask;
  104. out64(tmp, IO_SPACE_BASE | A_DUART_IMRREG(line));
  105. }
  106. /* Unmask the passed interrupt lines at the duart level */
  107. static inline void duart_unmask_ints(unsigned int line, unsigned int mask)
  108. {
  109. u64 tmp;
  110. tmp = in64(IO_SPACE_BASE | A_DUART_IMRREG(line));
  111. tmp |= mask;
  112. out64(tmp, IO_SPACE_BASE | A_DUART_IMRREG(line));
  113. }
  114. static inline unsigned long get_status_reg(unsigned int line)
  115. {
  116. return in64(IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_STATUS));
  117. }
  118. /* Derive which uart a call is for from the passed tty line.  */
  119. static inline unsigned int get_line(struct tty_struct *tty) 
  120. {
  121. unsigned int line = MINOR(tty->device) - 64;
  122. if (line > 1)
  123. printk(KERN_CRIT "Invalid linen");
  124. return line;
  125. }
  126. #define MIN(a, b) (((a)<(b))?(a):(b))
  127. /* 
  128.  * Generic interrupt handler for both channels.  dev_id is a pointer
  129.  * to the proper uart_states structure, so from that we can derive 
  130.  * which port interrupted 
  131.  */
  132. static void duart_int(int irq, void *dev_id, struct pt_regs *regs)
  133. {
  134. unsigned int line;
  135. uart_state_t *us = (uart_state_t *)dev_id;
  136. line = us-uart_states;
  137. #ifdef DUART_SPEW
  138. // setleds("INT!");
  139.         printk("DUART INTn");
  140. #endif
  141. /* We could query the ISR to figure out why we are here, but since
  142.    we are here, we may as well just take care of both rx and tx */
  143. spin_lock(&us->outp_lock);
  144. if (get_status_reg(line) & M_DUART_RX_RDY) {
  145. do {
  146. unsigned int status = get_status_reg(line);
  147. unsigned int ch = in64(IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_RX_HOLD));
  148. unsigned int flag = 0;
  149. if (status & 0x10) {
  150. tty_insert_flip_char(us->tty, 0, TTY_OVERRUN); }
  151. if (status & 0x20) {
  152. printk("Parity error!n");
  153. flag = TTY_PARITY;
  154. } else if (status & 0x40) {
  155. printk("Frame error!n");
  156. flag = TTY_FRAME;
  157. }
  158. tty_insert_flip_char(us->tty, ch, flag);
  159. } while (get_status_reg(line) & M_DUART_RX_RDY);
  160. tty_flip_buffer_push(us->tty);
  161. if ((get_status_reg(line) & M_DUART_TX_RDY) && us->outp_count) {
  162. do {
  163. out64(us->outp_buf[us->outp_head], IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_TX_HOLD));
  164. us->outp_head = (us->outp_head + 1) & (CONFIG_SB1250_DUART_OUTPUT_BUF_SIZE-1);
  165. us->outp_count--;
  166. } while ((get_status_reg(line) & M_DUART_TX_RDY) && us->outp_count);
  167. if (us->open && (us->flags & SD_WRITE_WAKE) &&
  168.     (us->outp_count < (CONFIG_SB1250_DUART_OUTPUT_BUF_SIZE/2))) {
  169. /* We told the discipline at one point that we had no space, so it went
  170.    to sleep.  Wake it up when we hit half empty */
  171. wake_up_interruptible(&us->tty->write_wait);
  172. }
  173. if (!us->outp_count) {
  174. duart_mask_ints(line, M_DUART_IMR_TX);
  175. }
  176. }
  177. spin_unlock(&us->outp_lock);
  178. }
  179. /*
  180.  *  Actual driver functions
  181.  */
  182. /* Return the number of characters we can accomodate in a write at this instant */
  183. static int duart_write_room(struct tty_struct *tty)
  184. {
  185. unsigned long flags;
  186. int retval;
  187. uart_state_t *us = &uart_states[get_line(tty)];
  188. spin_lock_irqsave(&us->outp_lock, flags);
  189. retval = CONFIG_SB1250_DUART_OUTPUT_BUF_SIZE - uart_states[get_line(tty)].outp_count;
  190. if (!retval) {
  191. us->flags |= SD_WRITE_WAKE;
  192. }
  193. spin_unlock_irqrestore(&us->outp_lock, flags);
  194. #ifdef DUART_SPEW
  195. printk("duart_write_room called, returning %in", retval);
  196. #endif
  197. return retval;
  198. }
  199. /* memcpy the data from src to destination, but take extra care if the
  200.    data is coming from user space */
  201. static inline int copy_buf(char *dest, const char *src, int size, int from_user) 
  202. {
  203. if (from_user) {
  204. (void) copy_from_user(dest, src, size); 
  205. } else {
  206. memcpy(dest, src, size);
  207. }
  208. return size;
  209. }
  210. /* Buffer up to count characters from buf to be written.  If we don't have other
  211.    characters buffered, enable the tx interrupt to start sending */
  212. static int duart_write(struct tty_struct * tty, int from_user,
  213.       const unsigned char *buf, int count)
  214. {
  215. uart_state_t *us;
  216. unsigned long flags;
  217. unsigned int line;
  218. int chars_written = 0;
  219. if (from_user && verify_area(VERIFY_READ, buf, count)) {
  220. return -EINVAL;
  221. }
  222. #ifdef DUART_SPEW
  223. printk("duart_write called for %i chars by %i (%s)n", count, current->pid, current->comm);
  224. #endif
  225. line = get_line(tty);
  226. us = &uart_states[line];
  227. spin_lock_irqsave(&us->outp_lock, flags);
  228. if (!count || (us->outp_count == CONFIG_SB1250_DUART_OUTPUT_BUF_SIZE)) {
  229. spin_unlock_irqrestore(&us->outp_lock, flags);
  230. return 0;
  231. }
  232. if (us->outp_tail < us->outp_head) {
  233. /* Straightforward case; copy from tail to head */
  234. chars_written += copy_buf(us->outp_buf + us->outp_tail, buf, 
  235.   MIN(count, us->outp_head - us->outp_tail), from_user);
  236. } else {
  237. /* Copy from tail to end of buffer, wrap around and then
  238.    copy to head */
  239. chars_written += copy_buf(us->outp_buf + us->outp_tail, buf, 
  240.   MIN(CONFIG_SB1250_DUART_OUTPUT_BUF_SIZE - us->outp_tail, count), 
  241.   from_user);
  242. if (chars_written < count) {
  243. chars_written += copy_buf(us->outp_buf, buf + chars_written,
  244.   MIN(us->outp_head, count - chars_written), from_user);
  245. }
  246. }
  247. us->outp_tail = (us->outp_tail + chars_written) &(CONFIG_SB1250_DUART_OUTPUT_BUF_SIZE-1);
  248. if (!(us->outp_count || us->outp_stopped)) {
  249. duart_unmask_ints(line, M_DUART_IMR_TX);
  250. }
  251. us->outp_count += chars_written;
  252. spin_unlock_irqrestore(&us->outp_lock, flags);
  253. return chars_written;
  254. }
  255. /* Buffer one character to be written.  If there's not room for it, just drop
  256.    it on the floor.  This is used for echo, among other things */
  257. static void duart_put_char(struct tty_struct *tty, u_char ch)
  258. {
  259. unsigned long flags;
  260. unsigned int line = get_line(tty);
  261. uart_state_t *us = &uart_states[line];
  262. #ifdef DUART_SPEW
  263. printk("duart_put_char called.  Char is %x (%c)n", (int)ch, ch);
  264. #endif
  265. spin_lock_irqsave(&us->outp_lock, flags);
  266. if (us->outp_count != CONFIG_SB1250_DUART_OUTPUT_BUF_SIZE) {
  267. us->outp_buf[us->outp_tail] = ch;
  268. us->outp_tail = (us->outp_tail + 1) &(CONFIG_SB1250_DUART_OUTPUT_BUF_SIZE-1);
  269. if (!(us->outp_count || us->outp_stopped)) {
  270. duart_unmask_ints(line, M_DUART_IMR_TX);
  271. }
  272. us->outp_count++;
  273. }
  274. spin_unlock_irqrestore(&us->outp_lock, flags);
  275. }
  276. /* Return the number of characters in the output buffer that have yet to be 
  277.    written */
  278. static int duart_chars_in_buffer(struct tty_struct *tty)
  279. {
  280. int retval;
  281. unsigned long flags;
  282. uart_state_t *us = &uart_states[get_line(tty)];
  283. spin_lock_irqsave(&us->outp_lock, flags);
  284. retval = us->outp_count;
  285. if (retval) {
  286. us->flags |= SD_WRITE_WAKE;
  287. }
  288. spin_unlock_irqrestore(&us->outp_lock, flags);
  289. #ifdef DUART_SPEW
  290. printk("duart_chars_in_buffer returning %in", retval);
  291. #endif
  292. return retval;
  293. }
  294. /* Kill everything we haven't yet shoved into the FIFO.  Turn off the
  295.    transmit interrupt since we've nothing more to transmit */
  296. static void duart_flush_buffer(struct tty_struct *tty)
  297. {
  298. unsigned long flags;
  299. unsigned int line = get_line(tty);
  300. uart_state_t *us = &uart_states[get_line(tty)];
  301. #ifdef DUART_SPEW
  302. printk("duart_flush_buffer calledn");
  303. #endif
  304. duart_mask_ints(line, M_DUART_IMR_TX);
  305. spin_lock_irqsave(&us->outp_lock, flags);
  306. us->outp_head = us->outp_tail = us->outp_count = 0;
  307. if (us->flags & SD_WRITE_WAKE) {
  308. wake_up_interruptible(&us->tty->write_wait);
  309. }
  310. spin_unlock_irqrestore(&us->outp_lock, flags);
  311. }
  312. /* See sb1250 user manual for details on these registers */
  313. static inline void duart_set_cflag(unsigned int line, unsigned int cflag)
  314. {
  315. unsigned int mode_reg1 = 0, mode_reg2 = 0;
  316. unsigned int clk_divisor;
  317. switch (cflag & CSIZE) {
  318. case CS7:
  319. mode_reg1 |= V_DUART_BITS_PER_CHAR_7;
  320. default:
  321. /* We don't handle CS5 or CS6...is there a way we're supposed to flag this? 
  322.    right now we just force them to CS8 */
  323. mode_reg1 |= 0x0;
  324. break;
  325. }
  326. if (cflag & CSTOPB) {
  327.         mode_reg2 |= M_DUART_STOP_BIT_LEN_2; /* XXX was: 0x4; */
  328. }
  329. if (!(cflag & PARENB)) {
  330.         mode_reg1 |= V_DUART_PARITY_MODE_NONE; /* XXX was: 0x8; */
  331. }
  332. if (cflag & PARODD) {
  333. mode_reg1 |= M_DUART_PARITY_TYPE_ODD;
  334. }
  335. /* Formula for this is (5000000/baud)-1, but we saturate
  336.    at 12 bits, which means we can't actually do anything less
  337.    that 1200 baud */
  338. switch (cflag & CBAUD) {
  339. case B200:
  340. case B300:
  341. case B1200: clk_divisor = 4095; break;
  342. case B1800: clk_divisor = 2776; break;
  343. case B2400: clk_divisor = 2082; break;
  344. case B4800: clk_divisor = 1040; break;
  345. default:
  346. case B9600: clk_divisor = 519; break;
  347. case B19200: clk_divisor = 259; break;
  348. case B38400: clk_divisor = 129; break;
  349. case B57600: clk_divisor = 85; break;
  350. case B115200: clk_divisor = 42; break;
  351. }
  352. out64(mode_reg1, IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_MODE_REG_1));
  353. out64(mode_reg2, IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_MODE_REG_2));
  354. out64(clk_divisor, IO_SPACE_BASE | A_DUART_CHANREG(line, R_DUART_CLK_SEL));
  355. uart_states[line].last_cflags = cflag;
  356. }
  357. /* Handle notification of a termios change.  */
  358. static void duart_set_termios(struct tty_struct *tty, struct termios *old)
  359. {
  360. #ifdef DUART_SPEW 
  361. printk("duart_set_termios called by %i (%s)n", current->pid, current->comm);
  362. #endif
  363. if (old && tty->termios->c_cflag == old->c_cflag)
  364. return;
  365. duart_set_cflag(get_line(tty), tty->termios->c_cflag);
  366. }
  367. /* Stop pushing stuff into the fifo, now.  Do the mask under the 
  368.    outp_lock to avoid races involving turning the interrupt line on/off */
  369. static void duart_stop(struct tty_struct *tty)
  370. {
  371. unsigned long flags;
  372. unsigned int line = get_line(tty);
  373. uart_state_t *us = &uart_states[line];
  374. #ifdef DUART_SPEW
  375. printk("duart_stop calledn");
  376. #endif
  377. spin_lock_irqsave(&us->outp_lock, flags);
  378. duart_mask_ints(get_line(tty), M_DUART_IMR_TX);
  379. us->outp_stopped = 1;
  380. spin_unlock_irqrestore(&us->outp_lock, flags);
  381. }
  382. static int duart_ioctl(struct tty_struct *tty, struct file * file,
  383.        unsigned int cmd, unsigned long arg)
  384. {
  385. /* if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
  386. return -ENODEV;*/
  387. switch (cmd) {
  388. case TIOCMGET:
  389. printk("Ignoring TIOCMGETn");
  390. break;
  391. case TIOCMBIS:
  392. printk("Ignoring TIOCMBISn");
  393. break;
  394. case TIOCMBIC:
  395. printk("Ignoring TIOCMBICn");
  396. break;
  397. case TIOCMSET:
  398. printk("Ignoring TIOCMSETn");
  399. break;
  400. case TIOCGSERIAL:
  401. printk("Ignoring TIOCGSERIALn");
  402. break;
  403. case TIOCSSERIAL:
  404. printk("Ignoring TIOCSSERIALn");
  405. break;
  406. case TIOCSERCONFIG:
  407. printk("Ignoring TIOCSERCONFIGn");
  408. break;
  409. case TIOCSERGETLSR: /* Get line status register */
  410. printk("Ignoring TIOCSERGETLSRn");
  411. break;
  412. case TIOCSERGSTRUCT:
  413. printk("Ignoring TIOCSERGSTRUCTn");
  414. break;
  415. case TIOCMIWAIT:
  416. printk("Ignoring TIOCMIWAITn");
  417. break;
  418. case TIOCGICOUNT:
  419. printk("Ignoring TIOCGICOUNTn");
  420. break;
  421. case TIOCSERGWILD:
  422. printk("Ignoring TIOCSERGWILDn");
  423. break;
  424. case TIOCSERSWILD:
  425. printk("Ignoring TIOCSERSWILDn");
  426. break;
  427. default:
  428. break;
  429. }
  430. // printk("Ignoring IOCTL %x from pid %i (%s)n", cmd, current->pid, current->comm);
  431. return -ENOIOCTLCMD;
  432. #if 0
  433. if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
  434.     (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
  435.     (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
  436. if (tty->flags & (1 << TTY_IO_ERROR))
  437. return -EIO;
  438. }
  439. switch (cmd) {
  440. case TIOCMGET:
  441. case TIOCMBIS:
  442. case TIOCMBIC:
  443. case TIOCMSET:
  444. case TIOCGSERIAL:
  445. case TIOCSSERIAL:
  446. case TIOCSERCONFIG:
  447. case TIOCSERGETLSR: /* Get line status register */
  448. case TIOCSERGSTRUCT:
  449. case TIOCMIWAIT:
  450. case TIOCGICOUNT:
  451. case TIOCSERGWILD:
  452. case TIOCSERSWILD:
  453. /* XXX Implement me! */
  454. printk("IOCTL needs implementing: %xn", cmd);
  455. default:
  456. printk("Unknown ioctl: %xn", cmd);
  457. }
  458. #endif
  459. return 0;
  460. }
  461. /* Stop pushing stuff into the fifo, now.  Do the mask under the 
  462.    outp_lock to avoid races involving turning the interrupt line on/off */
  463. static void duart_start(struct tty_struct *tty)
  464. {
  465. unsigned long flags;
  466. unsigned int line = get_line(tty);
  467. uart_state_t *us = &uart_states[line];
  468. #ifdef DUART_SPEW
  469. printk("duart_start calledn");
  470. #endif
  471. spin_lock_irqsave(&us->outp_lock, flags);
  472. if (us->outp_count) {
  473. duart_unmask_ints(get_line(tty), M_DUART_IMR_TX);
  474. }
  475. us->outp_stopped = 0;
  476. spin_unlock_irqrestore(&us->outp_lock, flags);
  477. }
  478. /* Not sure on the semantics of this; are we supposed to wait until the stuff
  479.    already in the hardware FIFO drains, or are we supposed to wait until 
  480.    we've drained the output buffer, too?  I'm assuming the former, 'cause thats
  481.    what the other drivers seem to assume 
  482. */
  483. static void duart_wait_until_sent(struct tty_struct *tty, int timeout)
  484. {
  485. unsigned long target_time;
  486. unsigned int line;
  487. uart_state_t *us;
  488. #ifdef DUART_SPEW
  489. printk("duart_wait_until_sent(%d)+n", timeout);
  490. #endif
  491. target_time = jiffies + timeout;
  492. line = get_line(tty);
  493. us = &uart_states[line];
  494. while (!(get_status_reg(line) & M_DUART_TX_EMT) && (jiffies < target_time)) {
  495.   schedule_timeout(1);
  496. }
  497. #ifdef DUART_SPEW
  498. printk("duart_wait_until_sent()-n");
  499. #endif
  500. }
  501. /*
  502.  * Open a tty line.  Note that this can be called multiple times, so ->open can
  503.  * be >1.  Only set up the tty struct if this is a "new" open, e.g. ->open was
  504.  * zero
  505.  */
  506. static int duart_open(struct tty_struct *tty, struct file *filp)
  507. {
  508. unsigned long flags;
  509. unsigned int line;
  510. uart_state_t *us;
  511. MOD_INC_USE_COUNT;
  512. #ifndef CONFIG_SIBYTE_SB1250_DUART_NO_PORT_1
  513. if (get_line(tty) > 1)
  514. #else
  515. if (get_line(tty) > 0)
  516. #endif
  517.                       {
  518. MOD_DEC_USE_COUNT;
  519. return -ENODEV;
  520. }
  521. #ifdef DUART_SPEW
  522. printk("duart_open called by %i (%s), tty is %p, rw is %p, ww is %pn", current->pid, current->comm, tty,
  523.        tty->read_wait, tty->write_wait);
  524. #endif
  525. line = get_line(tty);
  526. tty->driver_data = NULL;
  527. us = &uart_states[line];
  528. spin_lock_irqsave(&open_lock, flags);
  529. if (!us->open) {
  530. us->tty = tty;
  531. us->tty->termios->c_cflag = us->last_cflags;
  532. }
  533. us->open++;
  534. #ifdef FORCED_INPUT
  535. if (!line && (us->open == 1)) {
  536. next_inp = inp_cmds;
  537. init_timer(&inp_timer);
  538. inp_timer.expires = jiffies + 20;
  539. inp_timer.data = 0;
  540. inp_timer.function = stuff_char;
  541. stuff_char_tty = tty;
  542. add_timer(&inp_timer);
  543. }
  544. #endif
  545. duart_unmask_ints(line, M_DUART_IMR_RX);
  546. spin_unlock_irqrestore(&open_lock, flags);
  547. return 0;
  548. }
  549. /*
  550.  * Close a reference count out.  If reference count hits zero, null the
  551.  * tty, kill the interrupts.  The tty_io driver is responsible for making
  552.  * sure we've cleared out our internal buffers before calling close()
  553.  */
  554. static void duart_close(struct tty_struct *tty, struct file *filp)
  555. {
  556. unsigned long flags;
  557. unsigned int line = get_line(tty);
  558. uart_state_t *us = &uart_states[line];
  559. #ifdef DUART_SPEW
  560. printk("duart_close called by %i (%s)n", current->pid, current->comm);
  561. #endif
  562. spin_lock_irqsave(&open_lock, flags);
  563. us->open--;
  564. #if 0
  565. if (!us->open) {
  566. /* Flushing TX stuff here is conservative */
  567. duart_mask_ints(line, M_DUART_IMR_IN | M_DUART_IMR_BRK | M_DUART_IMR_RX | M_DUART_IMR_TX);
  568. spin_lock(&us->outp_lock);
  569. us->outp_head = us->outp_tail = us->outp_count = us->outp_stopped = 0;
  570. us->tty = NULL;
  571. spin_unlock(&us->outp_lock);
  572. }
  573. #endif
  574. ref_count--;
  575. spin_unlock_irqrestore(&open_lock, flags);
  576. MOD_DEC_USE_COUNT;
  577. }
  578. /* Set up the driver and register it, register the 2 1250 UART interrupts.  This
  579.    is called from tty_init, or as a part of the module init */
  580. static int __init sb1250_duart_init(void) 
  581. {
  582. sb1250_duart_driver.magic            = TTY_DRIVER_MAGIC;
  583. sb1250_duart_driver.driver_name      = "serial";
  584. #ifdef CONFIG_DEVFS_FS
  585. sb1250_duart_driver.name             = "tts/%d";
  586. #else
  587. sb1250_duart_driver.name             = "ttyS";
  588. #endif
  589. sb1250_duart_driver.major            = TTY_MAJOR;
  590. sb1250_duart_driver.minor_start      = 64;
  591. sb1250_duart_driver.num              = 2;
  592. sb1250_duart_driver.type             = TTY_DRIVER_TYPE_SERIAL;
  593. sb1250_duart_driver.subtype          = SERIAL_TYPE_NORMAL;
  594. sb1250_duart_driver.init_termios     = tty_std_termios;
  595. sb1250_duart_driver.flags            = TTY_DRIVER_REAL_RAW;
  596. sb1250_duart_driver.refcount         = &ref_count;
  597. sb1250_duart_driver.table            = duart_table;
  598. sb1250_duart_driver.termios          = duart_termios;
  599. sb1250_duart_driver.termios_locked   = duart_termios_locked;
  600. sb1250_duart_driver.open             = duart_open;
  601. sb1250_duart_driver.close            = duart_close;
  602. sb1250_duart_driver.write            = duart_write;
  603. sb1250_duart_driver.put_char         = duart_put_char;
  604. sb1250_duart_driver.write_room       = duart_write_room;
  605. sb1250_duart_driver.chars_in_buffer  = duart_chars_in_buffer;
  606. sb1250_duart_driver.flush_buffer     = duart_flush_buffer;
  607. sb1250_duart_driver.ioctl            = duart_ioctl;
  608. sb1250_duart_driver.set_termios      = duart_set_termios;
  609. sb1250_duart_driver.stop             = duart_stop;
  610. sb1250_duart_driver.start            = duart_start;
  611. sb1250_duart_driver.wait_until_sent  = duart_wait_until_sent;
  612. sb1250_duart_callout_driver          = sb1250_duart_driver;
  613. #ifdef CONFIG_DEVFS_FS
  614. sb1250_duart_callout_driver.name     = "cua/%d";
  615. #else
  616. sb1250_duart_callout_driver.name     = "cua";
  617. #endif
  618. sb1250_duart_callout_driver.major    = TTYAUX_MAJOR;
  619. sb1250_duart_callout_driver.subtype  = SERIAL_TYPE_CALLOUT;
  620. duart_mask_ints(0, 0xf);
  621. if (request_irq(K_INT_UART_0, duart_int, 0, "uart0", &uart_states[0])) {
  622. panic("Couldn't get uart0 interrupt line");
  623. }
  624. #ifndef CONFIG_SIBYTE_SB1250_DUART_NO_PORT_1
  625. duart_mask_ints(1, 0xf);
  626. if (request_irq(K_INT_UART_1, duart_int, 0, "uart1", &uart_states[1])) {
  627. panic("Couldn't get uart1 interrupt line");
  628. }
  629. #endif
  630. /* Interrupts are now active, our ISR can be called. */
  631. if (tty_register_driver(&sb1250_duart_driver)) {
  632. printk(KERN_ERR "Couldn't register sb1250 duart serial drivern");
  633. }
  634. if (tty_register_driver(&sb1250_duart_callout_driver)) {
  635. printk(KERN_ERR "Couldn't register sb1250 duart callout drivern");
  636. }
  637. duart_set_cflag(0, DEFAULT_CFLAGS);
  638. #ifndef CONFIG_SIBYTE_SB1250_DUART_NO_PORT_1
  639. duart_set_cflag(1, DEFAULT_CFLAGS);
  640. #endif
  641. return 0;
  642. }
  643. /* Unload the driver.  Unregister stuff, get ready to go away */
  644. static void __exit sb1250_duart_fini(void)
  645. {
  646. unsigned long flags;
  647. int ret;
  648. save_flags(flags);
  649. cli();
  650. ret = tty_unregister_driver(&sb1250_duart_callout_driver);
  651. if (ret) {
  652. printk(KERN_ERR "Unable to unregister sb1250 duart callout driver (%d)n", ret);
  653. }
  654. ret = tty_unregister_driver(&sb1250_duart_driver);
  655. if (ret) {
  656. printk(KERN_ERR "Unable to unregister sb1250 duart serial driver (%d)n", ret);
  657. }
  658. free_irq(K_INT_UART_0, &uart_states[0]);
  659. free_irq(K_INT_UART_1, &uart_states[1]);
  660. /* mask lines in the scd */
  661. disable_irq(K_INT_UART_0);
  662. disable_irq(K_INT_UART_1);
  663. restore_flags(flags);
  664. }
  665. module_init(sb1250_duart_init);
  666. module_exit(sb1250_duart_fini);
  667. MODULE_DESCRIPTION("SB1250 Duart serial driver");
  668. MODULE_AUTHOR("Justin Carlson <carlson@sibyte.com>");
  669. #ifdef CONFIG_SERIAL_CONSOLE
  670. /*
  671.  * Serial console stuff. 
  672.  * Very basic, polling driver for doing serial console output. 
  673.  * FIXME; there is a race here; we can't be sure that
  674.  * the tx is still empty without holding outp_lock for this line.
  675.  * Worst that can happen for now, though, is dropped characters.
  676.  */
  677. static void ser_console_write(struct console *cons, const char *str,
  678.                               unsigned int count)
  679. {
  680. unsigned int i;
  681. unsigned long flags;
  682. spin_lock_irqsave(&uart_states[0].outp_lock, flags);
  683. for (i = 0; i < count; i++) {
  684.                 if (str[i] == 'n') {
  685.                         /* Expand LF -> CRLF */
  686.                         while (!(get_status_reg(0) & M_DUART_TX_RDY)) {
  687.                                 /* Spin, doing nothing.  */
  688.                         }
  689. out64('r', IO_SPACE_BASE | A_DUART_CHANREG(0, R_DUART_TX_HOLD));
  690.                 }
  691. while (!(get_status_reg(0) & M_DUART_TX_RDY)) {
  692. /* Spin, doing nothing.  */
  693. }
  694. out64(str[i], IO_SPACE_BASE | A_DUART_CHANREG(0, R_DUART_TX_HOLD));
  695. }
  696. spin_unlock_irqrestore(&uart_states[0].outp_lock, flags);
  697. }
  698. static kdev_t ser_console_device(struct console *c)
  699. {
  700. return MKDEV(TTY_MAJOR, 64 + c->index);
  701. }
  702. static int ser_console_setup(struct console *cons, char *str)
  703. {
  704. /* Initialize the transmitter */
  705. duart_set_cflag(0, DEFAULT_CFLAGS);
  706. return 0;
  707. }
  708. static struct console sb1250_ser_cons = {
  709. name: "ttyS",
  710. write: ser_console_write,
  711. device: ser_console_device,
  712. setup: ser_console_setup,
  713. flags: CON_PRINTBUFFER,
  714. index: -1,
  715. };
  716. void __init sb1250_serial_console_init(void)
  717. {
  718. register_console(&sb1250_ser_cons);
  719. }
  720. #endif /* CONFIG_SERIAL_CONSOLE */