diff options
Diffstat (limited to 'drivers/char/mxser.c')
-rw-r--r-- | drivers/char/mxser.c | 150 |
1 files changed, 31 insertions, 119 deletions
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 047766915411..402c9f217f83 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -541,74 +541,21 @@ static unsigned char mxser_get_msr(int baseaddr, int mode, int port) | |||
541 | return status; | 541 | return status; |
542 | } | 542 | } |
543 | 543 | ||
544 | static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp, | 544 | static int mxser_carrier_raised(struct tty_port *port) |
545 | struct mxser_port *port) | ||
546 | { | 545 | { |
547 | DECLARE_WAITQUEUE(wait, current); | 546 | struct mxser_port *mp = container_of(port, struct mxser_port, port); |
548 | int retval; | 547 | return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0; |
549 | int do_clocal = 0; | 548 | } |
550 | unsigned long flags; | ||
551 | |||
552 | /* | ||
553 | * If non-blocking mode is set, or the port is not enabled, | ||
554 | * then make the check up front and then exit. | ||
555 | */ | ||
556 | if ((filp->f_flags & O_NONBLOCK) || | ||
557 | test_bit(TTY_IO_ERROR, &tty->flags)) { | ||
558 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
559 | return 0; | ||
560 | } | ||
561 | 549 | ||
562 | if (tty->termios->c_cflag & CLOCAL) | 550 | static void mxser_raise_dtr_rts(struct tty_port *port) |
563 | do_clocal = 1; | 551 | { |
552 | struct mxser_port *mp = container_of(port, struct mxser_port, port); | ||
553 | unsigned long flags; | ||
564 | 554 | ||
565 | /* | 555 | spin_lock_irqsave(&mp->slock, flags); |
566 | * Block waiting for the carrier detect and the line to become | 556 | outb(inb(mp->ioaddr + UART_MCR) | |
567 | * free (i.e., not in use by the callout). While we are in | 557 | UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR); |
568 | * this loop, port->port.count is dropped by one, so that | 558 | spin_unlock_irqrestore(&mp->slock, flags); |
569 | * mxser_close() knows when to free things. We restore it upon | ||
570 | * exit, either normal or abnormal. | ||
571 | */ | ||
572 | retval = 0; | ||
573 | add_wait_queue(&port->port.open_wait, &wait); | ||
574 | |||
575 | spin_lock_irqsave(&port->slock, flags); | ||
576 | if (!tty_hung_up_p(filp)) | ||
577 | port->port.count--; | ||
578 | spin_unlock_irqrestore(&port->slock, flags); | ||
579 | port->port.blocked_open++; | ||
580 | while (1) { | ||
581 | spin_lock_irqsave(&port->slock, flags); | ||
582 | outb(inb(port->ioaddr + UART_MCR) | | ||
583 | UART_MCR_DTR | UART_MCR_RTS, port->ioaddr + UART_MCR); | ||
584 | spin_unlock_irqrestore(&port->slock, flags); | ||
585 | set_current_state(TASK_INTERRUPTIBLE); | ||
586 | if (tty_hung_up_p(filp) || !(port->port.flags & ASYNC_INITIALIZED)) { | ||
587 | if (port->port.flags & ASYNC_HUP_NOTIFY) | ||
588 | retval = -EAGAIN; | ||
589 | else | ||
590 | retval = -ERESTARTSYS; | ||
591 | break; | ||
592 | } | ||
593 | if (!(port->port.flags & ASYNC_CLOSING) && | ||
594 | (do_clocal || | ||
595 | (inb(port->ioaddr + UART_MSR) & UART_MSR_DCD))) | ||
596 | break; | ||
597 | if (signal_pending(current)) { | ||
598 | retval = -ERESTARTSYS; | ||
599 | break; | ||
600 | } | ||
601 | schedule(); | ||
602 | } | ||
603 | set_current_state(TASK_RUNNING); | ||
604 | remove_wait_queue(&port->port.open_wait, &wait); | ||
605 | if (!tty_hung_up_p(filp)) | ||
606 | port->port.count++; | ||
607 | port->port.blocked_open--; | ||
608 | if (retval) | ||
609 | return retval; | ||
610 | port->port.flags |= ASYNC_NORMAL_ACTIVE; | ||
611 | return 0; | ||
612 | } | 559 | } |
613 | 560 | ||
614 | static int mxser_set_baud(struct tty_struct *tty, long newspd) | 561 | static int mxser_set_baud(struct tty_struct *tty, long newspd) |
@@ -1087,14 +1034,14 @@ static int mxser_open(struct tty_struct *tty, struct file *filp) | |||
1087 | /* | 1034 | /* |
1088 | * Start up serial port | 1035 | * Start up serial port |
1089 | */ | 1036 | */ |
1090 | spin_lock_irqsave(&info->slock, flags); | 1037 | spin_lock_irqsave(&info->port.lock, flags); |
1091 | info->port.count++; | 1038 | info->port.count++; |
1092 | spin_unlock_irqrestore(&info->slock, flags); | 1039 | spin_unlock_irqrestore(&info->port.lock, flags); |
1093 | retval = mxser_startup(tty); | 1040 | retval = mxser_startup(tty); |
1094 | if (retval) | 1041 | if (retval) |
1095 | return retval; | 1042 | return retval; |
1096 | 1043 | ||
1097 | retval = mxser_block_til_ready(tty, filp, info); | 1044 | retval = tty_port_block_til_ready(&info->port, tty, filp); |
1098 | if (retval) | 1045 | if (retval) |
1099 | return retval; | 1046 | return retval; |
1100 | 1047 | ||
@@ -1133,58 +1080,27 @@ static void mxser_flush_buffer(struct tty_struct *tty) | |||
1133 | static void mxser_close(struct tty_struct *tty, struct file *filp) | 1080 | static void mxser_close(struct tty_struct *tty, struct file *filp) |
1134 | { | 1081 | { |
1135 | struct mxser_port *info = tty->driver_data; | 1082 | struct mxser_port *info = tty->driver_data; |
1083 | struct tty_port *port = &info->port; | ||
1136 | 1084 | ||
1137 | unsigned long timeout; | 1085 | unsigned long timeout; |
1138 | unsigned long flags; | ||
1139 | 1086 | ||
1140 | if (tty->index == MXSER_PORTS) | 1087 | if (tty->index == MXSER_PORTS) |
1141 | return; | 1088 | return; |
1142 | if (!info) | 1089 | if (!info) |
1143 | return; | 1090 | return; |
1144 | 1091 | ||
1145 | spin_lock_irqsave(&info->slock, flags); | 1092 | if (tty_port_close_start(port, tty, filp) == 0) |
1146 | |||
1147 | if (tty_hung_up_p(filp)) { | ||
1148 | spin_unlock_irqrestore(&info->slock, flags); | ||
1149 | return; | ||
1150 | } | ||
1151 | if ((tty->count == 1) && (info->port.count != 1)) { | ||
1152 | /* | ||
1153 | * Uh, oh. tty->count is 1, which means that the tty | ||
1154 | * structure will be freed. Info->port.count should always | ||
1155 | * be one in these conditions. If it's greater than | ||
1156 | * one, we've got real problems, since it means the | ||
1157 | * serial port won't be shutdown. | ||
1158 | */ | ||
1159 | printk(KERN_ERR "mxser_close: bad serial port count; " | ||
1160 | "tty->count is 1, info->port.count is %d\n", info->port.count); | ||
1161 | info->port.count = 1; | ||
1162 | } | ||
1163 | if (--info->port.count < 0) { | ||
1164 | printk(KERN_ERR "mxser_close: bad serial port count for " | ||
1165 | "ttys%d: %d\n", tty->index, info->port.count); | ||
1166 | info->port.count = 0; | ||
1167 | } | ||
1168 | if (info->port.count) { | ||
1169 | spin_unlock_irqrestore(&info->slock, flags); | ||
1170 | return; | 1093 | return; |
1171 | } | 1094 | |
1172 | info->port.flags |= ASYNC_CLOSING; | ||
1173 | spin_unlock_irqrestore(&info->slock, flags); | ||
1174 | /* | 1095 | /* |
1175 | * Save the termios structure, since this port may have | 1096 | * Save the termios structure, since this port may have |
1176 | * separate termios for callout and dialin. | 1097 | * separate termios for callout and dialin. |
1098 | * | ||
1099 | * FIXME: Can this go ? | ||
1177 | */ | 1100 | */ |
1178 | if (info->port.flags & ASYNC_NORMAL_ACTIVE) | 1101 | if (info->port.flags & ASYNC_NORMAL_ACTIVE) |
1179 | info->normal_termios = *tty->termios; | 1102 | info->normal_termios = *tty->termios; |
1180 | /* | 1103 | /* |
1181 | * Now we wait for the transmit buffer to clear; and we notify | ||
1182 | * the line discipline to only process XON/XOFF characters. | ||
1183 | */ | ||
1184 | tty->closing = 1; | ||
1185 | if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) | ||
1186 | tty_wait_until_sent(tty, info->port.closing_wait); | ||
1187 | /* | ||
1188 | * At this point we stop accepting input. To do this, we | 1104 | * At this point we stop accepting input. To do this, we |
1189 | * disable the receive line status interrupts, and tell the | 1105 | * disable the receive line status interrupts, and tell the |
1190 | * interrupt driver to stop checking the data ready bit in the | 1106 | * interrupt driver to stop checking the data ready bit in the |
@@ -1209,19 +1125,12 @@ static void mxser_close(struct tty_struct *tty, struct file *filp) | |||
1209 | } | 1125 | } |
1210 | } | 1126 | } |
1211 | mxser_shutdown(tty); | 1127 | mxser_shutdown(tty); |
1212 | |||
1213 | mxser_flush_buffer(tty); | 1128 | mxser_flush_buffer(tty); |
1214 | tty_ldisc_flush(tty); | ||
1215 | |||
1216 | tty->closing = 0; | ||
1217 | tty_port_tty_set(&info->port, NULL); | ||
1218 | if (info->port.blocked_open) { | ||
1219 | if (info->port.close_delay) | ||
1220 | schedule_timeout_interruptible(info->port.close_delay); | ||
1221 | wake_up_interruptible(&info->port.open_wait); | ||
1222 | } | ||
1223 | 1129 | ||
1224 | info->port.flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); | 1130 | /* Right now the tty_port set is done outside of the close_end helper |
1131 | as we don't yet have everyone using refcounts */ | ||
1132 | tty_port_close_end(port, tty); | ||
1133 | tty_port_tty_set(port, NULL); | ||
1225 | } | 1134 | } |
1226 | 1135 | ||
1227 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) | 1136 | static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count) |
@@ -2146,10 +2055,7 @@ static void mxser_hangup(struct tty_struct *tty) | |||
2146 | 2055 | ||
2147 | mxser_flush_buffer(tty); | 2056 | mxser_flush_buffer(tty); |
2148 | mxser_shutdown(tty); | 2057 | mxser_shutdown(tty); |
2149 | info->port.count = 0; | 2058 | tty_port_hangup(&info->port); |
2150 | info->port.flags &= ~ASYNC_NORMAL_ACTIVE; | ||
2151 | tty_port_tty_set(&info->port, NULL); | ||
2152 | wake_up_interruptible(&info->port.open_wait); | ||
2153 | } | 2059 | } |
2154 | 2060 | ||
2155 | /* | 2061 | /* |
@@ -2449,6 +2355,11 @@ static const struct tty_operations mxser_ops = { | |||
2449 | .tiocmset = mxser_tiocmset, | 2355 | .tiocmset = mxser_tiocmset, |
2450 | }; | 2356 | }; |
2451 | 2357 | ||
2358 | struct tty_port_operations mxser_port_ops = { | ||
2359 | .carrier_raised = mxser_carrier_raised, | ||
2360 | .raise_dtr_rts = mxser_raise_dtr_rts, | ||
2361 | }; | ||
2362 | |||
2452 | /* | 2363 | /* |
2453 | * The MOXA Smartio/Industio serial driver boot-time initialization code! | 2364 | * The MOXA Smartio/Industio serial driver boot-time initialization code! |
2454 | */ | 2365 | */ |
@@ -2482,6 +2393,7 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, | |||
2482 | for (i = 0; i < brd->info->nports; i++) { | 2393 | for (i = 0; i < brd->info->nports; i++) { |
2483 | info = &brd->ports[i]; | 2394 | info = &brd->ports[i]; |
2484 | tty_port_init(&info->port); | 2395 | tty_port_init(&info->port); |
2396 | info->port.ops = &mxser_port_ops; | ||
2485 | info->board = brd; | 2397 | info->board = brd; |
2486 | info->stop_rx = 0; | 2398 | info->stop_rx = 0; |
2487 | info->ldisc_stop_rx = 0; | 2399 | info->ldisc_stop_rx = 0; |