diff options
Diffstat (limited to 'arch/ia64')
-rw-r--r-- | arch/ia64/hp/sim/simserial.c | 160 |
1 files changed, 63 insertions, 97 deletions
diff --git a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c index 8b5a1342e119..7b6e60e9167b 100644 --- a/arch/ia64/hp/sim/simserial.c +++ b/arch/ia64/hp/sim/simserial.c | |||
@@ -163,7 +163,7 @@ static void receive_chars(struct tty_struct *tty) | |||
163 | */ | 163 | */ |
164 | static irqreturn_t rs_interrupt_single(int irq, void *dev_id) | 164 | static irqreturn_t rs_interrupt_single(int irq, void *dev_id) |
165 | { | 165 | { |
166 | struct async_struct *info = dev_id; | 166 | struct serial_state *info = dev_id; |
167 | 167 | ||
168 | if (!info->tty) { | 168 | if (!info->tty) { |
169 | printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); | 169 | printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); |
@@ -185,7 +185,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) | |||
185 | 185 | ||
186 | static int rs_put_char(struct tty_struct *tty, unsigned char ch) | 186 | static int rs_put_char(struct tty_struct *tty, unsigned char ch) |
187 | { | 187 | { |
188 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 188 | struct serial_state *info = tty->driver_data; |
189 | unsigned long flags; | 189 | unsigned long flags; |
190 | 190 | ||
191 | if (!tty || !info->xmit.buf) | 191 | if (!tty || !info->xmit.buf) |
@@ -202,12 +202,11 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch) | |||
202 | return 1; | 202 | return 1; |
203 | } | 203 | } |
204 | 204 | ||
205 | static void transmit_chars(struct async_struct *info, int *intr_done) | 205 | static void transmit_chars(struct serial_state *info, int *intr_done) |
206 | { | 206 | { |
207 | int count; | 207 | int count; |
208 | unsigned long flags; | 208 | unsigned long flags; |
209 | 209 | ||
210 | |||
211 | local_irq_save(flags); | 210 | local_irq_save(flags); |
212 | 211 | ||
213 | if (info->x_char) { | 212 | if (info->x_char) { |
@@ -215,7 +214,7 @@ static void transmit_chars(struct async_struct *info, int *intr_done) | |||
215 | 214 | ||
216 | console->write(console, &c, 1); | 215 | console->write(console, &c, 1); |
217 | 216 | ||
218 | info->state->icount.tx++; | 217 | info->icount.tx++; |
219 | info->x_char = 0; | 218 | info->x_char = 0; |
220 | 219 | ||
221 | goto out; | 220 | goto out; |
@@ -256,7 +255,7 @@ out: | |||
256 | 255 | ||
257 | static void rs_flush_chars(struct tty_struct *tty) | 256 | static void rs_flush_chars(struct tty_struct *tty) |
258 | { | 257 | { |
259 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 258 | struct serial_state *info = tty->driver_data; |
260 | 259 | ||
261 | if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped || | 260 | if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped || |
262 | !info->xmit.buf) | 261 | !info->xmit.buf) |
@@ -269,8 +268,8 @@ static void rs_flush_chars(struct tty_struct *tty) | |||
269 | static int rs_write(struct tty_struct * tty, | 268 | static int rs_write(struct tty_struct * tty, |
270 | const unsigned char *buf, int count) | 269 | const unsigned char *buf, int count) |
271 | { | 270 | { |
271 | struct serial_state *info = tty->driver_data; | ||
272 | int c, ret = 0; | 272 | int c, ret = 0; |
273 | struct async_struct *info = (struct async_struct *)tty->driver_data; | ||
274 | unsigned long flags; | 273 | unsigned long flags; |
275 | 274 | ||
276 | if (!tty || !info->xmit.buf || !tmp_buf) return 0; | 275 | if (!tty || !info->xmit.buf || !tmp_buf) return 0; |
@@ -303,21 +302,21 @@ static int rs_write(struct tty_struct * tty, | |||
303 | 302 | ||
304 | static int rs_write_room(struct tty_struct *tty) | 303 | static int rs_write_room(struct tty_struct *tty) |
305 | { | 304 | { |
306 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 305 | struct serial_state *info = tty->driver_data; |
307 | 306 | ||
308 | return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); | 307 | return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); |
309 | } | 308 | } |
310 | 309 | ||
311 | static int rs_chars_in_buffer(struct tty_struct *tty) | 310 | static int rs_chars_in_buffer(struct tty_struct *tty) |
312 | { | 311 | { |
313 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 312 | struct serial_state *info = tty->driver_data; |
314 | 313 | ||
315 | return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); | 314 | return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); |
316 | } | 315 | } |
317 | 316 | ||
318 | static void rs_flush_buffer(struct tty_struct *tty) | 317 | static void rs_flush_buffer(struct tty_struct *tty) |
319 | { | 318 | { |
320 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 319 | struct serial_state *info = tty->driver_data; |
321 | unsigned long flags; | 320 | unsigned long flags; |
322 | 321 | ||
323 | local_irq_save(flags); | 322 | local_irq_save(flags); |
@@ -333,7 +332,7 @@ static void rs_flush_buffer(struct tty_struct *tty) | |||
333 | */ | 332 | */ |
334 | static void rs_send_xchar(struct tty_struct *tty, char ch) | 333 | static void rs_send_xchar(struct tty_struct *tty, char ch) |
335 | { | 334 | { |
336 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 335 | struct serial_state *info = tty->driver_data; |
337 | 336 | ||
338 | info->x_char = ch; | 337 | info->x_char = ch; |
339 | if (ch) { | 338 | if (ch) { |
@@ -362,7 +361,7 @@ static void rs_throttle(struct tty_struct * tty) | |||
362 | 361 | ||
363 | static void rs_unthrottle(struct tty_struct * tty) | 362 | static void rs_unthrottle(struct tty_struct * tty) |
364 | { | 363 | { |
365 | struct async_struct *info = (struct async_struct *)tty->driver_data; | 364 | struct serial_state *info = tty->driver_data; |
366 | 365 | ||
367 | if (I_IXOFF(tty)) { | 366 | if (I_IXOFF(tty)) { |
368 | if (info->x_char) | 367 | if (info->x_char) |
@@ -443,23 +442,22 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
443 | * This routine will shutdown a serial port; interrupts are disabled, and | 442 | * This routine will shutdown a serial port; interrupts are disabled, and |
444 | * DTR is dropped if the hangup on close termio flag is on. | 443 | * DTR is dropped if the hangup on close termio flag is on. |
445 | */ | 444 | */ |
446 | static void shutdown(struct async_struct * info) | 445 | static void shutdown(struct serial_state *info) |
447 | { | 446 | { |
448 | unsigned long flags; | 447 | unsigned long flags; |
449 | struct serial_state *state = info->state; | ||
450 | 448 | ||
451 | if (!(state->flags & ASYNC_INITIALIZED)) | 449 | if (!(info->flags & ASYNC_INITIALIZED)) |
452 | return; | 450 | return; |
453 | 451 | ||
454 | #ifdef SIMSERIAL_DEBUG | 452 | #ifdef SIMSERIAL_DEBUG |
455 | printk("Shutting down serial port %d (irq %d)....", info->line, | 453 | printk("Shutting down serial port %d (irq %d)...\n", info->line, |
456 | state->irq); | 454 | info->irq); |
457 | #endif | 455 | #endif |
458 | 456 | ||
459 | local_irq_save(flags); | 457 | local_irq_save(flags); |
460 | { | 458 | { |
461 | if (state->irq) | 459 | if (info->irq) |
462 | free_irq(state->irq, info); | 460 | free_irq(info->irq, info); |
463 | 461 | ||
464 | if (info->xmit.buf) { | 462 | if (info->xmit.buf) { |
465 | free_page((unsigned long) info->xmit.buf); | 463 | free_page((unsigned long) info->xmit.buf); |
@@ -468,7 +466,7 @@ static void shutdown(struct async_struct * info) | |||
468 | 466 | ||
469 | if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); | 467 | if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); |
470 | 468 | ||
471 | state->flags &= ~ASYNC_INITIALIZED; | 469 | info->flags &= ~ASYNC_INITIALIZED; |
472 | } | 470 | } |
473 | local_irq_restore(flags); | 471 | local_irq_restore(flags); |
474 | } | 472 | } |
@@ -485,13 +483,11 @@ static void shutdown(struct async_struct * info) | |||
485 | */ | 483 | */ |
486 | static void rs_close(struct tty_struct *tty, struct file * filp) | 484 | static void rs_close(struct tty_struct *tty, struct file * filp) |
487 | { | 485 | { |
488 | struct async_struct * info = (struct async_struct *)tty->driver_data; | 486 | struct serial_state *info = tty->driver_data; |
489 | struct serial_state *state; | ||
490 | unsigned long flags; | 487 | unsigned long flags; |
491 | 488 | ||
492 | if (!info ) return; | 489 | if (!info) |
493 | 490 | return; | |
494 | state = info->state; | ||
495 | 491 | ||
496 | local_irq_save(flags); | 492 | local_irq_save(flags); |
497 | if (tty_hung_up_p(filp)) { | 493 | if (tty_hung_up_p(filp)) { |
@@ -502,30 +498,30 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
502 | return; | 498 | return; |
503 | } | 499 | } |
504 | #ifdef SIMSERIAL_DEBUG | 500 | #ifdef SIMSERIAL_DEBUG |
505 | printk("rs_close ttys%d, count = %d\n", info->line, state->count); | 501 | printk("rs_close ttys%d, count = %d\n", info->line, info->count); |
506 | #endif | 502 | #endif |
507 | if ((tty->count == 1) && (state->count != 1)) { | 503 | if ((tty->count == 1) && (info->count != 1)) { |
508 | /* | 504 | /* |
509 | * Uh, oh. tty->count is 1, which means that the tty | 505 | * Uh, oh. tty->count is 1, which means that the tty |
510 | * structure will be freed. state->count should always | 506 | * structure will be freed. info->count should always |
511 | * be one in these conditions. If it's greater than | 507 | * be one in these conditions. If it's greater than |
512 | * one, we've got real problems, since it means the | 508 | * one, we've got real problems, since it means the |
513 | * serial port won't be shutdown. | 509 | * serial port won't be shutdown. |
514 | */ | 510 | */ |
515 | printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, " | 511 | printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, " |
516 | "state->count is %d\n", state->count); | 512 | "info->count is %d\n", info->count); |
517 | state->count = 1; | 513 | info->count = 1; |
518 | } | 514 | } |
519 | if (--state->count < 0) { | 515 | if (--info->count < 0) { |
520 | printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", | 516 | printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", |
521 | state->line, state->count); | 517 | info->line, info->count); |
522 | state->count = 0; | 518 | info->count = 0; |
523 | } | 519 | } |
524 | if (state->count) { | 520 | if (info->count) { |
525 | local_irq_restore(flags); | 521 | local_irq_restore(flags); |
526 | return; | 522 | return; |
527 | } | 523 | } |
528 | state->flags |= ASYNC_CLOSING; | 524 | info->flags |= ASYNC_CLOSING; |
529 | local_irq_restore(flags); | 525 | local_irq_restore(flags); |
530 | 526 | ||
531 | /* | 527 | /* |
@@ -537,11 +533,11 @@ static void rs_close(struct tty_struct *tty, struct file * filp) | |||
537 | tty_ldisc_flush(tty); | 533 | tty_ldisc_flush(tty); |
538 | info->tty = NULL; | 534 | info->tty = NULL; |
539 | if (info->blocked_open) { | 535 | if (info->blocked_open) { |
540 | if (state->close_delay) | 536 | if (info->close_delay) |
541 | schedule_timeout_interruptible(state->close_delay); | 537 | schedule_timeout_interruptible(info->close_delay); |
542 | wake_up_interruptible(&info->open_wait); | 538 | wake_up_interruptible(&info->open_wait); |
543 | } | 539 | } |
544 | state->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); | 540 | info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); |
545 | wake_up_interruptible(&info->close_wait); | 541 | wake_up_interruptible(&info->close_wait); |
546 | } | 542 | } |
547 | 543 | ||
@@ -558,59 +554,28 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) | |||
558 | */ | 554 | */ |
559 | static void rs_hangup(struct tty_struct *tty) | 555 | static void rs_hangup(struct tty_struct *tty) |
560 | { | 556 | { |
561 | struct async_struct * info = (struct async_struct *)tty->driver_data; | 557 | struct serial_state *info = tty->driver_data; |
562 | struct serial_state *state = info->state; | ||
563 | 558 | ||
564 | #ifdef SIMSERIAL_DEBUG | 559 | #ifdef SIMSERIAL_DEBUG |
565 | printk("rs_hangup: called\n"); | 560 | printk("rs_hangup: called\n"); |
566 | #endif | 561 | #endif |
567 | 562 | ||
568 | rs_flush_buffer(tty); | 563 | rs_flush_buffer(tty); |
569 | if (state->flags & ASYNC_CLOSING) | 564 | if (info->flags & ASYNC_CLOSING) |
570 | return; | 565 | return; |
571 | shutdown(info); | 566 | shutdown(info); |
572 | 567 | ||
573 | state->count = 0; | 568 | info->count = 0; |
574 | state->flags &= ~ASYNC_NORMAL_ACTIVE; | 569 | info->flags &= ~ASYNC_NORMAL_ACTIVE; |
575 | info->tty = NULL; | 570 | info->tty = NULL; |
576 | wake_up_interruptible(&info->open_wait); | 571 | wake_up_interruptible(&info->open_wait); |
577 | } | 572 | } |
578 | 573 | ||
579 | 574 | ||
580 | static int get_async_struct(int line, struct async_struct **ret_info) | 575 | static int startup(struct serial_state *state) |
581 | { | ||
582 | struct async_struct *info; | ||
583 | struct serial_state *sstate; | ||
584 | |||
585 | sstate = rs_table + line; | ||
586 | sstate->count++; | ||
587 | if (sstate->info) { | ||
588 | *ret_info = sstate->info; | ||
589 | return 0; | ||
590 | } | ||
591 | info = kzalloc(sizeof(struct async_struct), GFP_KERNEL); | ||
592 | if (!info) { | ||
593 | sstate->count--; | ||
594 | return -ENOMEM; | ||
595 | } | ||
596 | init_waitqueue_head(&info->open_wait); | ||
597 | init_waitqueue_head(&info->close_wait); | ||
598 | info->state = sstate; | ||
599 | if (sstate->info) { | ||
600 | kfree(info); | ||
601 | *ret_info = sstate->info; | ||
602 | return 0; | ||
603 | } | ||
604 | *ret_info = sstate->info = info; | ||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | static int | ||
609 | startup(struct async_struct *info) | ||
610 | { | 576 | { |
611 | unsigned long flags; | 577 | unsigned long flags; |
612 | int retval=0; | 578 | int retval=0; |
613 | struct serial_state *state= info->state; | ||
614 | unsigned long page; | 579 | unsigned long page; |
615 | 580 | ||
616 | page = get_zeroed_page(GFP_KERNEL); | 581 | page = get_zeroed_page(GFP_KERNEL); |
@@ -625,17 +590,18 @@ startup(struct async_struct *info) | |||
625 | } | 590 | } |
626 | 591 | ||
627 | if (!state->port || !state->type) { | 592 | if (!state->port || !state->type) { |
628 | if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); | 593 | if (state->tty) |
594 | set_bit(TTY_IO_ERROR, &state->tty->flags); | ||
629 | free_page(page); | 595 | free_page(page); |
630 | goto errout; | 596 | goto errout; |
631 | } | 597 | } |
632 | if (info->xmit.buf) | 598 | if (state->xmit.buf) |
633 | free_page(page); | 599 | free_page(page); |
634 | else | 600 | else |
635 | info->xmit.buf = (unsigned char *) page; | 601 | state->xmit.buf = (unsigned char *) page; |
636 | 602 | ||
637 | #ifdef SIMSERIAL_DEBUG | 603 | #ifdef SIMSERIAL_DEBUG |
638 | printk("startup: ttys%d (irq %d)...", info->line, state->irq); | 604 | printk("startup: ttys%d (irq %d)...", state->line, state->irq); |
639 | #endif | 605 | #endif |
640 | 606 | ||
641 | /* | 607 | /* |
@@ -643,14 +609,15 @@ startup(struct async_struct *info) | |||
643 | */ | 609 | */ |
644 | if (state->irq) { | 610 | if (state->irq) { |
645 | retval = request_irq(state->irq, rs_interrupt_single, 0, | 611 | retval = request_irq(state->irq, rs_interrupt_single, 0, |
646 | "simserial", info); | 612 | "simserial", state); |
647 | if (retval) | 613 | if (retval) |
648 | goto errout; | 614 | goto errout; |
649 | } | 615 | } |
650 | 616 | ||
651 | if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); | 617 | if (state->tty) |
618 | clear_bit(TTY_IO_ERROR, &state->tty->flags); | ||
652 | 619 | ||
653 | info->xmit.head = info->xmit.tail = 0; | 620 | state->xmit.head = state->xmit.tail = 0; |
654 | 621 | ||
655 | #if 0 | 622 | #if 0 |
656 | /* | 623 | /* |
@@ -663,15 +630,15 @@ startup(struct async_struct *info) | |||
663 | /* | 630 | /* |
664 | * Set up the tty->alt_speed kludge | 631 | * Set up the tty->alt_speed kludge |
665 | */ | 632 | */ |
666 | if (info->tty) { | 633 | if (state->tty) { |
667 | if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) | 634 | if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) |
668 | info->tty->alt_speed = 57600; | 635 | state->tty->alt_speed = 57600; |
669 | if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) | 636 | if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) |
670 | info->tty->alt_speed = 115200; | 637 | state->tty->alt_speed = 115200; |
671 | if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) | 638 | if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) |
672 | info->tty->alt_speed = 230400; | 639 | state->tty->alt_speed = 230400; |
673 | if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) | 640 | if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) |
674 | info->tty->alt_speed = 460800; | 641 | state->tty->alt_speed = 460800; |
675 | } | 642 | } |
676 | 643 | ||
677 | state->flags |= ASYNC_INITIALIZED; | 644 | state->flags |= ASYNC_INITIALIZED; |
@@ -692,20 +659,18 @@ errout: | |||
692 | */ | 659 | */ |
693 | static int rs_open(struct tty_struct *tty, struct file * filp) | 660 | static int rs_open(struct tty_struct *tty, struct file * filp) |
694 | { | 661 | { |
695 | struct async_struct *info; | 662 | struct serial_state *info = rs_table + tty->index; |
696 | int retval; | 663 | int retval; |
697 | unsigned long page; | 664 | unsigned long page; |
698 | 665 | ||
699 | retval = get_async_struct(tty->index, &info); | 666 | info->count++; |
700 | if (retval) | ||
701 | return retval; | ||
702 | tty->driver_data = info; | ||
703 | info->tty = tty; | 667 | info->tty = tty; |
668 | tty->driver_data = info; | ||
704 | 669 | ||
705 | #ifdef SIMSERIAL_DEBUG | 670 | #ifdef SIMSERIAL_DEBUG |
706 | printk("rs_open %s, count = %d\n", tty->name, info->state->count); | 671 | printk("rs_open %s, count = %d\n", tty->name, info->count); |
707 | #endif | 672 | #endif |
708 | info->tty->low_latency = (info->state->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 673 | tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
709 | 674 | ||
710 | if (!tmp_buf) { | 675 | if (!tmp_buf) { |
711 | page = get_zeroed_page(GFP_KERNEL); | 676 | page = get_zeroed_page(GFP_KERNEL); |
@@ -720,12 +685,11 @@ static int rs_open(struct tty_struct *tty, struct file * filp) | |||
720 | /* | 685 | /* |
721 | * If the port is the middle of closing, bail out now | 686 | * If the port is the middle of closing, bail out now |
722 | */ | 687 | */ |
723 | if (tty_hung_up_p(filp) || | 688 | if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) { |
724 | (info->state->flags & ASYNC_CLOSING)) { | 689 | if (info->flags & ASYNC_CLOSING) |
725 | if (info->state->flags & ASYNC_CLOSING) | ||
726 | interruptible_sleep_on(&info->close_wait); | 690 | interruptible_sleep_on(&info->close_wait); |
727 | #ifdef SERIAL_DO_RESTART | 691 | #ifdef SERIAL_DO_RESTART |
728 | return ((info->state->flags & ASYNC_HUP_NOTIFY) ? | 692 | return ((info->flags & ASYNC_HUP_NOTIFY) ? |
729 | -EAGAIN : -ERESTARTSYS); | 693 | -EAGAIN : -ERESTARTSYS); |
730 | #else | 694 | #else |
731 | return -EAGAIN; | 695 | return -EAGAIN; |
@@ -865,6 +829,8 @@ simrs_init (void) | |||
865 | * Let's have a little bit of fun ! | 829 | * Let's have a little bit of fun ! |
866 | */ | 830 | */ |
867 | for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { | 831 | for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { |
832 | init_waitqueue_head(&state->open_wait); | ||
833 | init_waitqueue_head(&state->close_wait); | ||
868 | 834 | ||
869 | if (state->type == PORT_UNKNOWN) continue; | 835 | if (state->type == PORT_UNKNOWN) continue; |
870 | 836 | ||