diff options
Diffstat (limited to 'drivers/char/synclink_gt.c')
-rw-r--r-- | drivers/char/synclink_gt.c | 136 |
1 files changed, 54 insertions, 82 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 08911ed66494..f329f459817c 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: synclink_gt.c,v 4.50 2007/07/25 19:29:25 paulkf Exp $ | ||
3 | * | ||
4 | * Device driver for Microgate SyncLink GT serial adapters. | 2 | * Device driver for Microgate SyncLink GT serial adapters. |
5 | * | 3 | * |
6 | * written by Paul Fulghum for Microgate Corporation | 4 | * written by Paul Fulghum for Microgate Corporation |
@@ -91,7 +89,6 @@ | |||
91 | * module identification | 89 | * module identification |
92 | */ | 90 | */ |
93 | static char *driver_name = "SyncLink GT"; | 91 | static char *driver_name = "SyncLink GT"; |
94 | static char *driver_version = "$Revision: 4.50 $"; | ||
95 | static char *tty_driver_name = "synclink_gt"; | 92 | static char *tty_driver_name = "synclink_gt"; |
96 | static char *tty_dev_prefix = "ttySLG"; | 93 | static char *tty_dev_prefix = "ttySLG"; |
97 | MODULE_LICENSE("GPL"); | 94 | MODULE_LICENSE("GPL"); |
@@ -720,44 +717,9 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
720 | return; | 717 | return; |
721 | DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); | 718 | DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count)); |
722 | 719 | ||
723 | if (!info->port.count) | 720 | if (tty_port_close_start(&info->port, tty, filp) == 0) |
724 | return; | ||
725 | |||
726 | if (tty_hung_up_p(filp)) | ||
727 | goto cleanup; | ||
728 | |||
729 | if ((tty->count == 1) && (info->port.count != 1)) { | ||
730 | /* | ||
731 | * tty->count is 1 and the tty structure will be freed. | ||
732 | * info->port.count should be one in this case. | ||
733 | * if it's not, correct it so that the port is shutdown. | ||
734 | */ | ||
735 | DBGERR(("%s close: bad refcount; tty->count=1, " | ||
736 | "info->port.count=%d\n", info->device_name, info->port.count)); | ||
737 | info->port.count = 1; | ||
738 | } | ||
739 | |||
740 | info->port.count--; | ||
741 | |||
742 | /* if at least one open remaining, leave hardware active */ | ||
743 | if (info->port.count) | ||
744 | goto cleanup; | 721 | goto cleanup; |
745 | 722 | ||
746 | info->port.flags |= ASYNC_CLOSING; | ||
747 | |||
748 | /* set tty->closing to notify line discipline to | ||
749 | * only process XON/XOFF characters. Only the N_TTY | ||
750 | * discipline appears to use this (ppp does not). | ||
751 | */ | ||
752 | tty->closing = 1; | ||
753 | |||
754 | /* wait for transmit data to clear all layers */ | ||
755 | |||
756 | if (info->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { | ||
757 | DBGINFO(("%s call tty_wait_until_sent\n", info->device_name)); | ||
758 | tty_wait_until_sent(tty, info->port.closing_wait); | ||
759 | } | ||
760 | |||
761 | if (info->port.flags & ASYNC_INITIALIZED) | 723 | if (info->port.flags & ASYNC_INITIALIZED) |
762 | wait_until_sent(tty, info->timeout); | 724 | wait_until_sent(tty, info->timeout); |
763 | flush_buffer(tty); | 725 | flush_buffer(tty); |
@@ -765,20 +727,8 @@ static void close(struct tty_struct *tty, struct file *filp) | |||
765 | 727 | ||
766 | shutdown(info); | 728 | shutdown(info); |
767 | 729 | ||
768 | tty->closing = 0; | 730 | tty_port_close_end(&info->port, tty); |
769 | info->port.tty = NULL; | 731 | info->port.tty = NULL; |
770 | |||
771 | if (info->port.blocked_open) { | ||
772 | if (info->port.close_delay) { | ||
773 | msleep_interruptible(jiffies_to_msecs(info->port.close_delay)); | ||
774 | } | ||
775 | wake_up_interruptible(&info->port.open_wait); | ||
776 | } | ||
777 | |||
778 | info->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | ||
779 | |||
780 | wake_up_interruptible(&info->port.close_wait); | ||
781 | |||
782 | cleanup: | 732 | cleanup: |
783 | DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); | 733 | DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count)); |
784 | } | 734 | } |
@@ -1356,7 +1306,7 @@ static int read_proc(char *page, char **start, off_t off, int count, | |||
1356 | off_t begin = 0; | 1306 | off_t begin = 0; |
1357 | struct slgt_info *info; | 1307 | struct slgt_info *info; |
1358 | 1308 | ||
1359 | len += sprintf(page, "synclink_gt driver:%s\n", driver_version); | 1309 | len += sprintf(page, "synclink_gt driver\n"); |
1360 | 1310 | ||
1361 | info = slgt_device_list; | 1311 | info = slgt_device_list; |
1362 | while( info ) { | 1312 | while( info ) { |
@@ -2488,7 +2438,7 @@ static void program_hw(struct slgt_info *info) | |||
2488 | info->ri_chkcount = 0; | 2438 | info->ri_chkcount = 0; |
2489 | info->dsr_chkcount = 0; | 2439 | info->dsr_chkcount = 0; |
2490 | 2440 | ||
2491 | slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR); | 2441 | slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR | IRQ_RI); |
2492 | get_signals(info); | 2442 | get_signals(info); |
2493 | 2443 | ||
2494 | if (info->netcount || | 2444 | if (info->netcount || |
@@ -3132,6 +3082,29 @@ static int tiocmset(struct tty_struct *tty, struct file *file, | |||
3132 | return 0; | 3082 | return 0; |
3133 | } | 3083 | } |
3134 | 3084 | ||
3085 | static int carrier_raised(struct tty_port *port) | ||
3086 | { | ||
3087 | unsigned long flags; | ||
3088 | struct slgt_info *info = container_of(port, struct slgt_info, port); | ||
3089 | |||
3090 | spin_lock_irqsave(&info->lock,flags); | ||
3091 | get_signals(info); | ||
3092 | spin_unlock_irqrestore(&info->lock,flags); | ||
3093 | return (info->signals & SerialSignal_DCD) ? 1 : 0; | ||
3094 | } | ||
3095 | |||
3096 | static void raise_dtr_rts(struct tty_port *port) | ||
3097 | { | ||
3098 | unsigned long flags; | ||
3099 | struct slgt_info *info = container_of(port, struct slgt_info, port); | ||
3100 | |||
3101 | spin_lock_irqsave(&info->lock,flags); | ||
3102 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3103 | set_signals(info); | ||
3104 | spin_unlock_irqrestore(&info->lock,flags); | ||
3105 | } | ||
3106 | |||
3107 | |||
3135 | /* | 3108 | /* |
3136 | * block current process until the device is ready to open | 3109 | * block current process until the device is ready to open |
3137 | */ | 3110 | */ |
@@ -3143,12 +3116,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3143 | bool do_clocal = false; | 3116 | bool do_clocal = false; |
3144 | bool extra_count = false; | 3117 | bool extra_count = false; |
3145 | unsigned long flags; | 3118 | unsigned long flags; |
3119 | int cd; | ||
3120 | struct tty_port *port = &info->port; | ||
3146 | 3121 | ||
3147 | DBGINFO(("%s block_til_ready\n", tty->driver->name)); | 3122 | DBGINFO(("%s block_til_ready\n", tty->driver->name)); |
3148 | 3123 | ||
3149 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ | 3124 | if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){ |
3150 | /* nonblock mode is set or port is not enabled */ | 3125 | /* nonblock mode is set or port is not enabled */ |
3151 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3126 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3152 | return 0; | 3127 | return 0; |
3153 | } | 3128 | } |
3154 | 3129 | ||
@@ -3157,46 +3132,38 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3157 | 3132 | ||
3158 | /* Wait for carrier detect and the line to become | 3133 | /* Wait for carrier detect and the line to become |
3159 | * free (i.e., not in use by the callout). While we are in | 3134 | * free (i.e., not in use by the callout). While we are in |
3160 | * this loop, info->port.count is dropped by one, so that | 3135 | * this loop, port->count is dropped by one, so that |
3161 | * close() knows when to free things. We restore it upon | 3136 | * close() knows when to free things. We restore it upon |
3162 | * exit, either normal or abnormal. | 3137 | * exit, either normal or abnormal. |
3163 | */ | 3138 | */ |
3164 | 3139 | ||
3165 | retval = 0; | 3140 | retval = 0; |
3166 | add_wait_queue(&info->port.open_wait, &wait); | 3141 | add_wait_queue(&port->open_wait, &wait); |
3167 | 3142 | ||
3168 | spin_lock_irqsave(&info->lock, flags); | 3143 | spin_lock_irqsave(&info->lock, flags); |
3169 | if (!tty_hung_up_p(filp)) { | 3144 | if (!tty_hung_up_p(filp)) { |
3170 | extra_count = true; | 3145 | extra_count = true; |
3171 | info->port.count--; | 3146 | port->count--; |
3172 | } | 3147 | } |
3173 | spin_unlock_irqrestore(&info->lock, flags); | 3148 | spin_unlock_irqrestore(&info->lock, flags); |
3174 | info->port.blocked_open++; | 3149 | port->blocked_open++; |
3175 | 3150 | ||
3176 | while (1) { | 3151 | while (1) { |
3177 | if ((tty->termios->c_cflag & CBAUD)) { | 3152 | if ((tty->termios->c_cflag & CBAUD)) |
3178 | spin_lock_irqsave(&info->lock,flags); | 3153 | tty_port_raise_dtr_rts(port); |
3179 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
3180 | set_signals(info); | ||
3181 | spin_unlock_irqrestore(&info->lock,flags); | ||
3182 | } | ||
3183 | 3154 | ||
3184 | set_current_state(TASK_INTERRUPTIBLE); | 3155 | set_current_state(TASK_INTERRUPTIBLE); |
3185 | 3156 | ||
3186 | if (tty_hung_up_p(filp) || !(info->port.flags & ASYNC_INITIALIZED)){ | 3157 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){ |
3187 | retval = (info->port.flags & ASYNC_HUP_NOTIFY) ? | 3158 | retval = (port->flags & ASYNC_HUP_NOTIFY) ? |
3188 | -EAGAIN : -ERESTARTSYS; | 3159 | -EAGAIN : -ERESTARTSYS; |
3189 | break; | 3160 | break; |
3190 | } | 3161 | } |
3191 | 3162 | ||
3192 | spin_lock_irqsave(&info->lock,flags); | 3163 | cd = tty_port_carrier_raised(port); |
3193 | get_signals(info); | ||
3194 | spin_unlock_irqrestore(&info->lock,flags); | ||
3195 | 3164 | ||
3196 | if (!(info->port.flags & ASYNC_CLOSING) && | 3165 | if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd )) |
3197 | (do_clocal || (info->signals & SerialSignal_DCD)) ) { | ||
3198 | break; | 3166 | break; |
3199 | } | ||
3200 | 3167 | ||
3201 | if (signal_pending(current)) { | 3168 | if (signal_pending(current)) { |
3202 | retval = -ERESTARTSYS; | 3169 | retval = -ERESTARTSYS; |
@@ -3208,14 +3175,14 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3208 | } | 3175 | } |
3209 | 3176 | ||
3210 | set_current_state(TASK_RUNNING); | 3177 | set_current_state(TASK_RUNNING); |
3211 | remove_wait_queue(&info->port.open_wait, &wait); | 3178 | remove_wait_queue(&port->open_wait, &wait); |
3212 | 3179 | ||
3213 | if (extra_count) | 3180 | if (extra_count) |
3214 | info->port.count++; | 3181 | port->count++; |
3215 | info->port.blocked_open--; | 3182 | port->blocked_open--; |
3216 | 3183 | ||
3217 | if (!retval) | 3184 | if (!retval) |
3218 | info->port.flags |= ASYNC_NORMAL_ACTIVE; | 3185 | port->flags |= ASYNC_NORMAL_ACTIVE; |
3219 | 3186 | ||
3220 | DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); | 3187 | DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval)); |
3221 | return retval; | 3188 | return retval; |
@@ -3444,6 +3411,11 @@ static void add_device(struct slgt_info *info) | |||
3444 | #endif | 3411 | #endif |
3445 | } | 3412 | } |
3446 | 3413 | ||
3414 | static const struct tty_port_operations slgt_port_ops = { | ||
3415 | .carrier_raised = carrier_raised, | ||
3416 | .raise_dtr_rts = raise_dtr_rts, | ||
3417 | }; | ||
3418 | |||
3447 | /* | 3419 | /* |
3448 | * allocate device instance structure, return NULL on failure | 3420 | * allocate device instance structure, return NULL on failure |
3449 | */ | 3421 | */ |
@@ -3458,6 +3430,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev | |||
3458 | driver_name, adapter_num, port_num)); | 3430 | driver_name, adapter_num, port_num)); |
3459 | } else { | 3431 | } else { |
3460 | tty_port_init(&info->port); | 3432 | tty_port_init(&info->port); |
3433 | info->port.ops = &slgt_port_ops; | ||
3461 | info->magic = MGSL_MAGIC; | 3434 | info->magic = MGSL_MAGIC; |
3462 | INIT_WORK(&info->task, bh_handler); | 3435 | INIT_WORK(&info->task, bh_handler); |
3463 | info->max_frame_size = 4096; | 3436 | info->max_frame_size = 4096; |
@@ -3600,7 +3573,7 @@ static void slgt_cleanup(void) | |||
3600 | struct slgt_info *info; | 3573 | struct slgt_info *info; |
3601 | struct slgt_info *tmp; | 3574 | struct slgt_info *tmp; |
3602 | 3575 | ||
3603 | printk("unload %s %s\n", driver_name, driver_version); | 3576 | printk(KERN_INFO "unload %s\n", driver_name); |
3604 | 3577 | ||
3605 | if (serial_driver) { | 3578 | if (serial_driver) { |
3606 | for (info=slgt_device_list ; info != NULL ; info=info->next_device) | 3579 | for (info=slgt_device_list ; info != NULL ; info=info->next_device) |
@@ -3643,7 +3616,7 @@ static int __init slgt_init(void) | |||
3643 | { | 3616 | { |
3644 | int rc; | 3617 | int rc; |
3645 | 3618 | ||
3646 | printk("%s %s\n", driver_name, driver_version); | 3619 | printk(KERN_INFO "%s\n", driver_name); |
3647 | 3620 | ||
3648 | serial_driver = alloc_tty_driver(MAX_DEVICES); | 3621 | serial_driver = alloc_tty_driver(MAX_DEVICES); |
3649 | if (!serial_driver) { | 3622 | if (!serial_driver) { |
@@ -3674,9 +3647,8 @@ static int __init slgt_init(void) | |||
3674 | goto error; | 3647 | goto error; |
3675 | } | 3648 | } |
3676 | 3649 | ||
3677 | printk("%s %s, tty major#%d\n", | 3650 | printk(KERN_INFO "%s, tty major#%d\n", |
3678 | driver_name, driver_version, | 3651 | driver_name, serial_driver->major); |
3679 | serial_driver->major); | ||
3680 | 3652 | ||
3681 | slgt_device_count = 0; | 3653 | slgt_device_count = 0; |
3682 | if ((rc = pci_register_driver(&pci_driver)) < 0) { | 3654 | if ((rc = pci_register_driver(&pci_driver)) < 0) { |