aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/specialix.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/specialix.c')
-rw-r--r--drivers/char/specialix.c73
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
184static struct tty_driver *specialix_driver; 184static struct tty_driver *specialix_driver;
185static unsigned char * tmp_buf;
186
187static 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
192static struct specialix_board sx_board[SX_NBOARD] = { 186static 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
203static struct timer_list missed_irq_timer; 197static struct timer_list missed_irq_timer;
204static irqreturn_t sx_interrupt(int irq, void * dev_id, struct pt_regs * regs); 198static 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 */
901static irqreturn_t sx_interrupt(int irq, void *dev_id, struct pt_regs *regs) 895static 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 */
2280static void do_sx_hangup(void *private_) 2264static 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
2329static void sx_set_termios(struct tty_struct * tty, struct termios * old_termios) 2314static 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
2355static void do_softint(void *private_) 2340static 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
2375static struct tty_operations sx_ops = { 2361static 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