diff options
Diffstat (limited to 'drivers/char/specialix.c')
-rw-r--r-- | drivers/char/specialix.c | 73 |
1 files changed, 28 insertions, 45 deletions
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index a1d303f9a33d..20946f5127e0 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -182,12 +182,6 @@ static int sx_poll = HZ; | |||
182 | #define RS_EVENT_WRITE_WAKEUP 0 | 182 | #define RS_EVENT_WRITE_WAKEUP 0 |
183 | 183 | ||
184 | static struct tty_driver *specialix_driver; | 184 | static struct tty_driver *specialix_driver; |
185 | static unsigned char * tmp_buf; | ||
186 | |||
187 | static unsigned long baud_table[] = { | ||
188 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | ||
189 | 9600, 19200, 38400, 57600, 115200, 0, | ||
190 | }; | ||
191 | 185 | ||
192 | static struct specialix_board sx_board[SX_NBOARD] = { | 186 | static struct specialix_board sx_board[SX_NBOARD] = { |
193 | { 0, SX_IOBASE1, 9, }, | 187 | { 0, SX_IOBASE1, 9, }, |
@@ -201,7 +195,7 @@ static struct specialix_port sx_port[SX_NBOARD * SX_NPORT]; | |||
201 | 195 | ||
202 | #ifdef SPECIALIX_TIMER | 196 | #ifdef SPECIALIX_TIMER |
203 | static struct timer_list missed_irq_timer; | 197 | static struct timer_list missed_irq_timer; |
204 | static irqreturn_t sx_interrupt(int irq, void * dev_id, struct pt_regs * regs); | 198 | static irqreturn_t sx_interrupt(int irq, void * dev_id); |
205 | #endif | 199 | #endif |
206 | 200 | ||
207 | 201 | ||
@@ -898,7 +892,7 @@ static inline void sx_check_modem(struct specialix_board * bp) | |||
898 | 892 | ||
899 | 893 | ||
900 | /* The main interrupt processing routine */ | 894 | /* The main interrupt processing routine */ |
901 | static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 895 | static irqreturn_t sx_interrupt(int irq, void *dev_id) |
902 | { | 896 | { |
903 | unsigned char status; | 897 | unsigned char status; |
904 | unsigned char ack; | 898 | unsigned char ack; |
@@ -913,7 +907,7 @@ static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
913 | spin_lock_irqsave(&bp->lock, flags); | 907 | spin_lock_irqsave(&bp->lock, flags); |
914 | 908 | ||
915 | dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); | 909 | dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __FUNCTION__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); |
916 | if (!bp || !(bp->flags & SX_BOARD_ACTIVE)) { | 910 | if (!(bp->flags & SX_BOARD_ACTIVE)) { |
917 | dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq); | 911 | dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", irq); |
918 | spin_unlock_irqrestore(&bp->lock, flags); | 912 | spin_unlock_irqrestore(&bp->lock, flags); |
919 | func_exit(); | 913 | func_exit(); |
@@ -1087,24 +1081,16 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1087 | port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); | 1081 | port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); |
1088 | spin_unlock_irqrestore(&bp->lock, flags); | 1082 | spin_unlock_irqrestore(&bp->lock, flags); |
1089 | dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); | 1083 | dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); |
1090 | baud = C_BAUD(tty); | 1084 | baud = tty_get_baud_rate(tty); |
1091 | 1085 | ||
1092 | if (baud & CBAUDEX) { | 1086 | if (baud == 38400) { |
1093 | baud &= ~CBAUDEX; | ||
1094 | if (baud < 1 || baud > 2) | ||
1095 | port->tty->termios->c_cflag &= ~CBAUDEX; | ||
1096 | else | ||
1097 | baud += 15; | ||
1098 | } | ||
1099 | if (baud == 15) { | ||
1100 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | 1087 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) |
1101 | baud ++; | 1088 | baud = 57600; |
1102 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | 1089 | if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) |
1103 | baud += 2; | 1090 | baud = 115200; |
1104 | } | 1091 | } |
1105 | 1092 | ||
1106 | 1093 | if (!baud) { | |
1107 | if (!baud_table[baud]) { | ||
1108 | /* Drop DTR & exit */ | 1094 | /* Drop DTR & exit */ |
1109 | dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); | 1095 | dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); |
1110 | if (!SX_CRTSCTS (tty)) { | 1096 | if (!SX_CRTSCTS (tty)) { |
@@ -1134,7 +1120,7 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1134 | "This is an untested option, please be carefull.\n", | 1120 | "This is an untested option, please be carefull.\n", |
1135 | port_No (port), tmp); | 1121 | port_No (port), tmp); |
1136 | else | 1122 | else |
1137 | tmp = (((SX_OSCFREQ + baud_table[baud]/2) / baud_table[baud] + | 1123 | tmp = (((SX_OSCFREQ + baud/2) / baud + |
1138 | CD186x_TPC/2) / CD186x_TPC); | 1124 | CD186x_TPC/2) / CD186x_TPC); |
1139 | 1125 | ||
1140 | if ((tmp < 0x10) && time_before(again, jiffies)) { | 1126 | if ((tmp < 0x10) && time_before(again, jiffies)) { |
@@ -1159,11 +1145,9 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p | |||
1159 | sx_out(bp, CD186x_RBPRL, tmp & 0xff); | 1145 | sx_out(bp, CD186x_RBPRL, tmp & 0xff); |
1160 | sx_out(bp, CD186x_TBPRL, tmp & 0xff); | 1146 | sx_out(bp, CD186x_TBPRL, tmp & 0xff); |
1161 | spin_unlock_irqrestore(&bp->lock, flags); | 1147 | spin_unlock_irqrestore(&bp->lock, flags); |
1162 | if (port->custom_divisor) { | 1148 | if (port->custom_divisor) |
1163 | baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; | 1149 | baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; |
1164 | baud = ( baud + 5 ) / 10; | 1150 | baud = (baud + 5) / 10; /* Estimated CPS */ |
1165 | } else | ||
1166 | baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */ | ||
1167 | 1151 | ||
1168 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ | 1152 | /* Two timer ticks seems enough to wakeup something like SLIP driver */ |
1169 | tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; | 1153 | tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; |
@@ -1682,7 +1666,7 @@ static int sx_write(struct tty_struct * tty, | |||
1682 | 1666 | ||
1683 | bp = port_Board(port); | 1667 | bp = port_Board(port); |
1684 | 1668 | ||
1685 | if (!port->xmit_buf || !tmp_buf) { | 1669 | if (!port->xmit_buf) { |
1686 | func_exit(); | 1670 | func_exit(); |
1687 | return 0; | 1671 | return 0; |
1688 | } | 1672 | } |
@@ -2277,9 +2261,10 @@ static void sx_start(struct tty_struct * tty) | |||
2277 | * do_sx_hangup() -> tty->hangup() -> sx_hangup() | 2261 | * do_sx_hangup() -> tty->hangup() -> sx_hangup() |
2278 | * | 2262 | * |
2279 | */ | 2263 | */ |
2280 | static void do_sx_hangup(void *private_) | 2264 | static void do_sx_hangup(struct work_struct *work) |
2281 | { | 2265 | { |
2282 | struct specialix_port *port = (struct specialix_port *) private_; | 2266 | struct specialix_port *port = |
2267 | container_of(work, struct specialix_port, tqueue_hangup); | ||
2283 | struct tty_struct *tty; | 2268 | struct tty_struct *tty; |
2284 | 2269 | ||
2285 | func_enter(); | 2270 | func_enter(); |
@@ -2326,7 +2311,7 @@ static void sx_hangup(struct tty_struct * tty) | |||
2326 | } | 2311 | } |
2327 | 2312 | ||
2328 | 2313 | ||
2329 | static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios) | 2314 | static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios) |
2330 | { | 2315 | { |
2331 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; | 2316 | struct specialix_port *port = (struct specialix_port *)tty->driver_data; |
2332 | unsigned long flags; | 2317 | unsigned long flags; |
@@ -2352,9 +2337,10 @@ static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios | |||
2352 | } | 2337 | } |
2353 | 2338 | ||
2354 | 2339 | ||
2355 | static void do_softint(void *private_) | 2340 | static void do_softint(struct work_struct *work) |
2356 | { | 2341 | { |
2357 | struct specialix_port *port = (struct specialix_port *) private_; | 2342 | struct specialix_port *port = |
2343 | container_of(work, struct specialix_port, tqueue); | ||
2358 | struct tty_struct *tty; | 2344 | struct tty_struct *tty; |
2359 | 2345 | ||
2360 | func_enter(); | 2346 | func_enter(); |
@@ -2372,7 +2358,7 @@ static void do_softint(void *private_) | |||
2372 | func_exit(); | 2358 | func_exit(); |
2373 | } | 2359 | } |
2374 | 2360 | ||
2375 | static struct tty_operations sx_ops = { | 2361 | static const struct tty_operations sx_ops = { |
2376 | .open = sx_open, | 2362 | .open = sx_open, |
2377 | .close = sx_close, | 2363 | .close = sx_close, |
2378 | .write = sx_write, | 2364 | .write = sx_write, |
@@ -2406,12 +2392,6 @@ static int sx_init_drivers(void) | |||
2406 | return 1; | 2392 | return 1; |
2407 | } | 2393 | } |
2408 | 2394 | ||
2409 | if (!(tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL))) { | ||
2410 | printk(KERN_ERR "sx: Couldn't get free page.\n"); | ||
2411 | put_tty_driver(specialix_driver); | ||
2412 | func_exit(); | ||
2413 | return 1; | ||
2414 | } | ||
2415 | specialix_driver->owner = THIS_MODULE; | 2395 | specialix_driver->owner = THIS_MODULE; |
2416 | specialix_driver->name = "ttyW"; | 2396 | specialix_driver->name = "ttyW"; |
2417 | specialix_driver->major = SPECIALIX_NORMAL_MAJOR; | 2397 | specialix_driver->major = SPECIALIX_NORMAL_MAJOR; |
@@ -2420,12 +2400,13 @@ static int sx_init_drivers(void) | |||
2420 | specialix_driver->init_termios = tty_std_termios; | 2400 | specialix_driver->init_termios = tty_std_termios; |
2421 | specialix_driver->init_termios.c_cflag = | 2401 | specialix_driver->init_termios.c_cflag = |
2422 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 2402 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; |
2403 | specialix_driver->init_termios.c_ispeed = 9600; | ||
2404 | specialix_driver->init_termios.c_ospeed = 9600; | ||
2423 | specialix_driver->flags = TTY_DRIVER_REAL_RAW; | 2405 | specialix_driver->flags = TTY_DRIVER_REAL_RAW; |
2424 | tty_set_operations(specialix_driver, &sx_ops); | 2406 | tty_set_operations(specialix_driver, &sx_ops); |
2425 | 2407 | ||
2426 | if ((error = tty_register_driver(specialix_driver))) { | 2408 | if ((error = tty_register_driver(specialix_driver))) { |
2427 | put_tty_driver(specialix_driver); | 2409 | put_tty_driver(specialix_driver); |
2428 | free_page((unsigned long)tmp_buf); | ||
2429 | printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n", | 2410 | printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n", |
2430 | error); | 2411 | error); |
2431 | func_exit(); | 2412 | func_exit(); |
@@ -2434,8 +2415,8 @@ static int sx_init_drivers(void) | |||
2434 | memset(sx_port, 0, sizeof(sx_port)); | 2415 | memset(sx_port, 0, sizeof(sx_port)); |
2435 | for (i = 0; i < SX_NPORT * SX_NBOARD; i++) { | 2416 | for (i = 0; i < SX_NPORT * SX_NBOARD; i++) { |
2436 | sx_port[i].magic = SPECIALIX_MAGIC; | 2417 | sx_port[i].magic = SPECIALIX_MAGIC; |
2437 | INIT_WORK(&sx_port[i].tqueue, do_softint, &sx_port[i]); | 2418 | INIT_WORK(&sx_port[i].tqueue, do_softint); |
2438 | INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup, &sx_port[i]); | 2419 | INIT_WORK(&sx_port[i].tqueue_hangup, do_sx_hangup); |
2439 | sx_port[i].close_delay = 50 * HZ/100; | 2420 | sx_port[i].close_delay = 50 * HZ/100; |
2440 | sx_port[i].closing_wait = 3000 * HZ/100; | 2421 | sx_port[i].closing_wait = 3000 * HZ/100; |
2441 | init_waitqueue_head(&sx_port[i].open_wait); | 2422 | init_waitqueue_head(&sx_port[i].open_wait); |
@@ -2451,7 +2432,6 @@ static void sx_release_drivers(void) | |||
2451 | { | 2432 | { |
2452 | func_enter(); | 2433 | func_enter(); |
2453 | 2434 | ||
2454 | free_page((unsigned long)tmp_buf); | ||
2455 | tty_unregister_driver(specialix_driver); | 2435 | tty_unregister_driver(specialix_driver); |
2456 | put_tty_driver(specialix_driver); | 2436 | put_tty_driver(specialix_driver); |
2457 | func_exit(); | 2437 | func_exit(); |
@@ -2497,7 +2477,7 @@ static int __init specialix_init(void) | |||
2497 | i++; | 2477 | i++; |
2498 | continue; | 2478 | continue; |
2499 | } | 2479 | } |
2500 | pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, | 2480 | pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX, |
2501 | PCI_DEVICE_ID_SPECIALIX_IO8, | 2481 | PCI_DEVICE_ID_SPECIALIX_IO8, |
2502 | pdev); | 2482 | pdev); |
2503 | if (!pdev) break; | 2483 | if (!pdev) break; |
@@ -2513,6 +2493,9 @@ static int __init specialix_init(void) | |||
2513 | if (!sx_probe(&sx_board[i])) | 2493 | if (!sx_probe(&sx_board[i])) |
2514 | found ++; | 2494 | found ++; |
2515 | } | 2495 | } |
2496 | /* May exit pci_get sequence early with lots of boards */ | ||
2497 | if (pdev != NULL) | ||
2498 | pci_dev_put(pdev); | ||
2516 | } | 2499 | } |
2517 | #endif | 2500 | #endif |
2518 | 2501 | ||