aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/line.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/drivers/line.c')
-rw-r--r--arch/um/drivers/line.c116
1 files changed, 47 insertions, 69 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index da81d22ec04a..851a7c8caae5 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
@@ -23,8 +23,9 @@
23 23
24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused) 24static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
25{ 25{
26 struct tty_struct *tty = data; 26 struct chan *chan = data;
27 struct line *line = tty->driver_data; 27 struct line *line = chan->line;
28 struct tty_struct *tty = line->tty;
28 29
29 if (line) 30 if (line)
30 chan_interrupt(&line->chan_list, &line->task, tty, irq); 31 chan_interrupt(&line->chan_list, &line->task, tty, irq);
@@ -33,10 +34,10 @@ static irqreturn_t line_interrupt(int irq, void *data, struct pt_regs *unused)
33 34
34static void line_timer_cb(void *arg) 35static void line_timer_cb(void *arg)
35{ 36{
36 struct tty_struct *tty = arg; 37 struct line *line = arg;
37 struct line *line = tty->driver_data;
38 38
39 line_interrupt(line->driver->read_irq, arg, NULL); 39 chan_interrupt(&line->chan_list, &line->task, line->tty,
40 line->driver->read_irq);
40} 41}
41 42
42/* Returns the free space inside the ring buffer of this line. 43/* Returns the free space inside the ring buffer of this line.
@@ -342,8 +343,9 @@ int line_ioctl(struct tty_struct *tty, struct file * file,
342static irqreturn_t line_write_interrupt(int irq, void *data, 343static irqreturn_t line_write_interrupt(int irq, void *data,
343 struct pt_regs *unused) 344 struct pt_regs *unused)
344{ 345{
345 struct tty_struct *tty = data; 346 struct chan *chan = data;
346 struct line *line = tty->driver_data; 347 struct line *line = chan->line;
348 struct tty_struct *tty = line->tty;
347 int err; 349 int err;
348 350
349 /* Interrupts are enabled here because we registered the interrupt with 351 /* Interrupts are enabled here because we registered the interrupt with
@@ -365,7 +367,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
365 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) && 367 if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
366 (tty->ldisc.write_wakeup != NULL)) 368 (tty->ldisc.write_wakeup != NULL))
367 (tty->ldisc.write_wakeup)(tty); 369 (tty->ldisc.write_wakeup)(tty);
368 370
369 /* BLOCKING mode 371 /* BLOCKING mode
370 * In blocking mode, everything sleeps on tty->write_wait. 372 * In blocking mode, everything sleeps on tty->write_wait.
371 * Sleeping in the console driver would break non-blocking 373 * Sleeping in the console driver would break non-blocking
@@ -377,52 +379,29 @@ static irqreturn_t line_write_interrupt(int irq, void *data,
377 return IRQ_HANDLED; 379 return IRQ_HANDLED;
378} 380}
379 381
380int line_setup_irq(int fd, int input, int output, struct tty_struct *tty) 382int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
381{ 383{
382 struct line *line = tty->driver_data;
383 struct line_driver *driver = line->driver; 384 struct line_driver *driver = line->driver;
384 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM; 385 int err = 0, flags = SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM;
385 386
386 if (input) 387 if (input)
387 err = um_request_irq(driver->read_irq, fd, IRQ_READ, 388 err = um_request_irq(driver->read_irq, fd, IRQ_READ,
388 line_interrupt, flags, 389 line_interrupt, flags,
389 driver->read_irq_name, tty); 390 driver->read_irq_name, data);
390 if (err) 391 if (err)
391 return err; 392 return err;
392 if (output) 393 if (output)
393 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE, 394 err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
394 line_write_interrupt, flags, 395 line_write_interrupt, flags,
395 driver->write_irq_name, tty); 396 driver->write_irq_name, data);
396 line->have_irq = 1; 397 line->have_irq = 1;
397 return err; 398 return err;
398} 399}
399 400
400void line_disable(struct tty_struct *tty, int current_irq)
401{
402 struct line *line = tty->driver_data;
403
404 if(!line->have_irq)
405 return;
406
407 if(line->driver->read_irq == current_irq)
408 free_irq_later(line->driver->read_irq, tty);
409 else {
410 free_irq(line->driver->read_irq, tty);
411 }
412
413 if(line->driver->write_irq == current_irq)
414 free_irq_later(line->driver->write_irq, tty);
415 else {
416 free_irq(line->driver->write_irq, tty);
417 }
418
419 line->have_irq = 0;
420}
421
422int line_open(struct line *lines, struct tty_struct *tty) 401int line_open(struct line *lines, struct tty_struct *tty)
423{ 402{
424 struct line *line; 403 struct line *line;
425 int err = 0; 404 int err = -ENODEV;
426 405
427 line = &lines[tty->index]; 406 line = &lines[tty->index];
428 tty->driver_data = line; 407 tty->driver_data = line;
@@ -430,29 +409,29 @@ int line_open(struct line *lines, struct tty_struct *tty)
430 /* The IRQ which takes this lock is not yet enabled and won't be run 409 /* The IRQ which takes this lock is not yet enabled and won't be run
431 * before the end, so we don't need to use spin_lock_irq.*/ 410 * before the end, so we don't need to use spin_lock_irq.*/
432 spin_lock(&line->lock); 411 spin_lock(&line->lock);
433 if (tty->count == 1) {
434 if (!line->valid) {
435 err = -ENODEV;
436 goto out;
437 }
438 412
439 err = open_chan(&line->chan_list); 413 tty->driver_data = line;
440 if(err) 414 line->tty = tty;
441 goto out; 415 if(!line->valid)
442 416 goto out;
443 /* Here the interrupt is registered.*/ 417
444 enable_chan(&line->chan_list, tty); 418 if(tty->count == 1){
445 INIT_WORK(&line->task, line_timer_cb, tty); 419 /* Here the device is opened, if necessary, and interrupt
446 } 420 * is registered.
421 */
422 enable_chan(line);
423 INIT_WORK(&line->task, line_timer_cb, line);
424
425 if(!line->sigio){
426 chan_enable_winch(&line->chan_list, tty);
427 line->sigio = 1;
428 }
447 429
448 if(!line->sigio){ 430 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
449 chan_enable_winch(&line->chan_list, tty); 431 &tty->winsize.ws_col);
450 line->sigio = 1;
451 } 432 }
452 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
453 &tty->winsize.ws_col);
454 line->count++;
455 433
434 err = 0;
456out: 435out:
457 spin_unlock(&line->lock); 436 spin_unlock(&line->lock);
458 return err; 437 return err;
@@ -472,15 +451,14 @@ void line_close(struct tty_struct *tty, struct file * filp)
472 /* We ignore the error anyway! */ 451 /* We ignore the error anyway! */
473 flush_buffer(line); 452 flush_buffer(line);
474 453
475 line->count--; 454 if(tty->count == 1){
476 if (tty->count == 1) { 455 line->tty = NULL;
477 line_disable(tty, -1);
478 tty->driver_data = NULL; 456 tty->driver_data = NULL;
479 }
480 457
481 if((line->count == 0) && line->sigio){ 458 if(line->sigio){
482 unregister_winch(tty); 459 unregister_winch(tty);
483 line->sigio = 0; 460 line->sigio = 0;
461 }
484 } 462 }
485 463
486 spin_unlock_irq(&line->lock); 464 spin_unlock_irq(&line->lock);
@@ -491,7 +469,7 @@ void close_lines(struct line *lines, int nlines)
491 int i; 469 int i;
492 470
493 for(i = 0; i < nlines; i++) 471 for(i = 0; i < nlines; i++)
494 close_chan(&lines[i].chan_list); 472 close_chan(&lines[i].chan_list, 0);
495} 473}
496 474
497/* Common setup code for both startup command line and mconsole initialization. 475/* Common setup code for both startup command line and mconsole initialization.
@@ -526,7 +504,7 @@ int line_setup(struct line *lines, unsigned int num, char *init)
526 return 0; 504 return 0;
527 } 505 }
528 else if (n >= 0){ 506 else if (n >= 0){
529 if (lines[n].count > 0) { 507 if (lines[n].tty != NULL) {
530 printk("line_setup - device %d is open\n", n); 508 printk("line_setup - device %d is open\n", n);
531 return 0; 509 return 0;
532 } 510 }
@@ -537,7 +515,7 @@ int line_setup(struct line *lines, unsigned int num, char *init)
537 else { 515 else {
538 lines[n].init_str = init; 516 lines[n].init_str = init;
539 lines[n].valid = 1; 517 lines[n].valid = 1;
540 } 518 }
541 } 519 }
542 } 520 }
543 else { 521 else {
@@ -578,7 +556,7 @@ int line_config(struct line *lines, unsigned int num, char *str,
578 return 1; 556 return 1;
579 557
580 line = &lines[n]; 558 line = &lines[n];
581 return parse_chan_pair(line->init_str, &line->chan_list, n, opts); 559 return parse_chan_pair(line->init_str, line, n, opts);
582} 560}
583 561
584int line_get_config(char *name, struct line *lines, unsigned int num, char *str, 562int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
@@ -604,7 +582,7 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
604 spin_lock(&line->lock); 582 spin_lock(&line->lock);
605 if(!line->valid) 583 if(!line->valid)
606 CONFIG_CHUNK(str, size, n, "none", 1); 584 CONFIG_CHUNK(str, size, n, "none", 1);
607 else if(line->count == 0) 585 else if(line->tty == NULL)
608 CONFIG_CHUNK(str, size, n, line->init_str, 1); 586 CONFIG_CHUNK(str, size, n, line->init_str, 1);
609 else n = chan_config_string(&line->chan_list, str, size, error_out); 587 else n = chan_config_string(&line->chan_list, str, size, error_out);
610 spin_unlock(&line->lock); 588 spin_unlock(&line->lock);
@@ -696,7 +674,7 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
696 if(line->init_str == NULL) 674 if(line->init_str == NULL)
697 printk("lines_init - kstrdup returned NULL\n"); 675 printk("lines_init - kstrdup returned NULL\n");
698 676
699 if(parse_chan_pair(line->init_str, &line->chan_list, i, opts)){ 677 if(parse_chan_pair(line->init_str, line, i, opts)){
700 printk("parse_chan_pair failed for device %d\n", i); 678 printk("parse_chan_pair failed for device %d\n", i);
701 line->valid = 0; 679 line->valid = 0;
702 } 680 }
@@ -831,7 +809,7 @@ char *add_xterm_umid(char *base)
831 umid = get_umid(1); 809 umid = get_umid(1);
832 if(umid == NULL) 810 if(umid == NULL)
833 return base; 811 return base;
834 812
835 len = strlen(base) + strlen(" ()") + strlen(umid) + 1; 813 len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
836 title = kmalloc(len, GFP_KERNEL); 814 title = kmalloc(len, GFP_KERNEL);
837 if(title == NULL){ 815 if(title == NULL){