1 |
/* |
/* |
2 |
Copyright (C) 1995,96,98,99,2000,01 Free Software Foundation, Inc. |
Copyright (C) 1995,96,98,99,2000,01,02 Free Software Foundation, Inc. |
3 |
Written by Michael I. Bushnell, p/BSG. |
Written by Michael I. Bushnell, p/BSG. |
4 |
|
|
5 |
This file is part of the GNU Hurd. |
This file is part of the GNU Hurd. |
98 |
static int char_size_mask_xxx = 0xff; |
static int char_size_mask_xxx = 0xff; |
99 |
|
|
100 |
/* Forward */ |
/* Forward */ |
101 |
static void devio_desert_dtr (); |
static error_t devio_desert_dtr (); |
102 |
|
|
103 |
static void init_devio (void) __attribute__ ((constructor)); |
static error_t |
104 |
static void |
devio_init (void) |
|
init_devio () |
|
105 |
{ |
{ |
106 |
mach_port_t host_priv; |
mach_port_t host_priv; |
107 |
error_t err; |
error_t err; |
108 |
|
|
109 |
err = get_privileged_ports (&host_priv, &device_master); |
err = get_privileged_ports (&host_priv, &device_master); |
110 |
if (err) |
if (err) |
111 |
error (1, err, "Getting priviliged ports"); |
return err; |
112 |
mach_port_deallocate (mach_task_self (), host_priv); |
mach_port_deallocate (mach_task_self (), host_priv); |
113 |
phys_reply_class = ports_create_class (0, 0); |
phys_reply_class = ports_create_class (0, 0); |
114 |
|
return 0; |
115 |
} |
} |
116 |
|
|
117 |
/* XXX Convert a real speed to a bogus Mach speed. Return |
/* XXX Convert a real speed to a bogus Mach speed. Return |
237 |
|
|
238 |
/* If there are characters on the output queue and no |
/* If there are characters on the output queue and no |
239 |
pending output requests, then send them. */ |
pending output requests, then send them. */ |
240 |
static void |
static error_t |
241 |
devio_start_output () |
devio_start_output () |
242 |
{ |
{ |
243 |
char *cp; |
char *cp; |
247 |
size = qsize (outputq); |
size = qsize (outputq); |
248 |
|
|
249 |
if (!size || output_pending || (termflags & USER_OUTPUT_SUSP)) |
if (!size || output_pending || (termflags & USER_OUTPUT_SUSP)) |
250 |
return; |
return 0; |
251 |
|
|
252 |
if (output_stopped) |
if (output_stopped) |
253 |
{ |
{ |
278 |
devio_desert_dtr (); |
devio_desert_dtr (); |
279 |
else if (!err) |
else if (!err) |
280 |
output_pending = 1; |
output_pending = 1; |
281 |
|
return 0; |
282 |
} |
} |
283 |
|
|
284 |
error_t |
error_t |
369 |
return 0; |
return 0; |
370 |
} |
} |
371 |
|
|
372 |
static void |
static error_t |
373 |
devio_set_break () |
devio_set_break () |
374 |
{ |
{ |
375 |
device_set_status (phys_device, TTY_SET_BREAK, 0, 0); |
device_set_status (phys_device, TTY_SET_BREAK, 0, 0); |
376 |
|
return 0; |
377 |
} |
} |
378 |
|
|
379 |
static void |
static error_t |
380 |
devio_clear_break () |
devio_clear_break () |
381 |
{ |
{ |
382 |
device_set_status (phys_device, TTY_CLEAR_BREAK, 0, 0); |
device_set_status (phys_device, TTY_CLEAR_BREAK, 0, 0); |
383 |
|
return 0; |
384 |
} |
} |
385 |
|
|
386 |
static void |
static error_t |
387 |
devio_abandon_physical_output () |
devio_abandon_physical_output () |
388 |
{ |
{ |
389 |
int val = D_WRITE; |
int val = D_WRITE; |
391 |
/* If this variable is clear, then carrier is gone, so we |
/* If this variable is clear, then carrier is gone, so we |
392 |
have nothing to do. */ |
have nothing to do. */ |
393 |
if (!phys_reply_writes_pi) |
if (!phys_reply_writes_pi) |
394 |
return; |
return 0; |
395 |
|
|
396 |
mach_port_deallocate (mach_task_self (), phys_reply_writes); |
mach_port_deallocate (mach_task_self (), phys_reply_writes); |
397 |
ports_reallocate_port (phys_reply_writes_pi); |
ports_reallocate_port (phys_reply_writes_pi); |
400 |
device_set_status (phys_device, TTY_FLUSH, &val, TTY_FLUSH_COUNT); |
device_set_status (phys_device, TTY_FLUSH, &val, TTY_FLUSH_COUNT); |
401 |
npending_output = 0; |
npending_output = 0; |
402 |
output_pending = 0; |
output_pending = 0; |
403 |
|
return 0; |
404 |
} |
} |
405 |
|
|
406 |
static void |
static error_t |
407 |
devio_suspend_physical_output () |
devio_suspend_physical_output () |
408 |
{ |
{ |
409 |
if (!output_stopped) |
if (!output_stopped) |
411 |
device_set_status (phys_device, TTY_STOP, 0, 0); |
device_set_status (phys_device, TTY_STOP, 0, 0); |
412 |
output_stopped = 1; |
output_stopped = 1; |
413 |
} |
} |
414 |
|
return 0; |
415 |
} |
} |
416 |
|
|
417 |
static void |
static error_t |
418 |
devio_notice_input_flushed () |
devio_notice_input_flushed () |
419 |
{ |
{ |
420 |
|
return 0; |
421 |
} |
} |
422 |
|
|
423 |
static int |
static int |
466 |
return err; |
return err; |
467 |
} |
} |
468 |
|
|
469 |
static void |
static error_t |
470 |
devio_desert_dtr () |
devio_desert_dtr () |
471 |
{ |
{ |
472 |
int bits; |
int bits; |
477 |
(dev_status_t) &bits, TTY_MODEM_COUNT); |
(dev_status_t) &bits, TTY_MODEM_COUNT); |
478 |
|
|
479 |
report_carrier_off (); |
report_carrier_off (); |
480 |
|
return 0; |
481 |
} |
} |
482 |
|
|
483 |
static error_t |
static error_t |
587 |
/* Adjust physical state on the basis of the terminal state. |
/* Adjust physical state on the basis of the terminal state. |
588 |
Where it isn't possible, mutate terminal state to match |
Where it isn't possible, mutate terminal state to match |
589 |
reality. */ |
reality. */ |
590 |
static void |
static error_t |
591 |
devio_set_bits () |
devio_set_bits (struct termios *state) |
592 |
{ |
{ |
593 |
if (!(termstate.c_cflag & CIGNORE) && phys_device != MACH_PORT_NULL) |
if (!(state->c_cflag & CIGNORE) && phys_device != MACH_PORT_NULL) |
594 |
{ |
{ |
595 |
struct tty_status ttystat; |
struct tty_status ttystat; |
596 |
int cnt = TTY_STATUS_COUNT; |
int cnt = TTY_STATUS_COUNT; |
597 |
|
|
598 |
/* Find the current state. */ |
/* Find the current state. */ |
599 |
device_get_status (phys_device, TTY_STATUS, (dev_status_t) &ttystat, &cnt); |
device_get_status (phys_device, TTY_STATUS, (dev_status_t) &ttystat, &cnt); |
600 |
if (termstate.__ispeed) |
if (state->__ispeed) |
601 |
real_speed_to_bogus_speed (termstate.__ispeed, &ttystat.tt_ispeed); |
real_speed_to_bogus_speed (state->__ispeed, &ttystat.tt_ispeed); |
602 |
if (termstate.__ospeed) |
if (state->__ospeed) |
603 |
real_speed_to_bogus_speed (termstate.__ospeed, &ttystat.tt_ospeed); |
real_speed_to_bogus_speed (state->__ospeed, &ttystat.tt_ospeed); |
604 |
|
|
605 |
/* Try and set it. */ |
/* Try and set it. */ |
606 |
device_set_status (phys_device, TTY_STATUS, |
device_set_status (phys_device, TTY_STATUS, |
609 |
/* And now make termstate match reality. */ |
/* And now make termstate match reality. */ |
610 |
cnt = TTY_STATUS_COUNT; |
cnt = TTY_STATUS_COUNT; |
611 |
device_get_status (phys_device, TTY_STATUS, (dev_status_t) &ttystat, &cnt); |
device_get_status (phys_device, TTY_STATUS, (dev_status_t) &ttystat, &cnt); |
612 |
termstate.__ispeed = bogus_speed_to_real_speed (ttystat.tt_ispeed); |
state->__ispeed = bogus_speed_to_real_speed (ttystat.tt_ispeed); |
613 |
termstate.__ospeed = bogus_speed_to_real_speed (ttystat.tt_ospeed); |
state->__ospeed = bogus_speed_to_real_speed (ttystat.tt_ospeed); |
614 |
|
|
615 |
/* Mach forces us to use the normal stop bit convention: |
/* Mach forces us to use the normal stop bit convention: |
616 |
two bits at 110 bps; 1 bit otherwise. */ |
two bits at 110 bps; 1 bit otherwise. */ |
617 |
if (termstate.__ispeed == 110) |
if (state->__ispeed == 110) |
618 |
termstate.c_cflag |= CSTOPB; |
state->c_cflag |= CSTOPB; |
619 |
else |
else |
620 |
termstate.c_cflag &= ~CSTOPB; |
state->c_cflag &= ~CSTOPB; |
621 |
|
|
622 |
/* Figure out how to munge input, since we are unable to actually |
/* Figure out how to munge input, since we are unable to actually |
623 |
affect what the hardware does. */ |
affect what the hardware does. */ |
624 |
switch (termstate.c_cflag & CSIZE) |
switch (state->c_cflag & CSIZE) |
625 |
{ |
{ |
626 |
case CS5: |
case CS5: |
627 |
char_size_mask_xxx = 0x1f; |
char_size_mask_xxx = 0x1f; |
640 |
char_size_mask_xxx = 0xff; |
char_size_mask_xxx = 0xff; |
641 |
break; |
break; |
642 |
} |
} |
643 |
if (termstate.c_cflag & PARENB) |
if (state->c_cflag & PARENB) |
644 |
char_size_mask_xxx |= 0x80; |
char_size_mask_xxx |= 0x80; |
645 |
} |
} |
646 |
|
return 0; |
647 |
} |
} |
648 |
|
|
649 |
static void |
static error_t |
650 |
devio_mdmctl (int how, int bits) |
devio_mdmctl (int how, int bits) |
651 |
{ |
{ |
652 |
int oldbits, newbits; |
int oldbits, newbits; |
669 |
|
|
670 |
device_set_status (phys_device, TTY_MODEM, |
device_set_status (phys_device, TTY_MODEM, |
671 |
(dev_status_t) &newbits, TTY_MODEM_COUNT); |
(dev_status_t) &newbits, TTY_MODEM_COUNT); |
672 |
|
|
673 |
|
return 0; |
674 |
} |
} |
675 |
|
|
676 |
static int |
static error_t |
677 |
devio_mdmstate () |
devio_mdmstate (int *state) |
678 |
{ |
{ |
679 |
int bits, cnt; |
int bits, cnt; |
680 |
|
|
681 |
cnt = TTY_MODEM_COUNT; |
cnt = TTY_MODEM_COUNT; |
682 |
device_get_status (phys_device, TTY_MODEM, (dev_status_t) &bits, &cnt); |
device_get_status (phys_device, TTY_MODEM, (dev_status_t) &bits, &cnt); |
683 |
if (cnt != TTY_MODEM_COUNT) |
if (cnt == TTY_MODEM_COUNT) |
684 |
return 0; |
*state = bits; |
685 |
else |
else |
686 |
return bits; |
*state = 0; |
687 |
|
return 0; |
688 |
} |
} |
689 |
|
|
690 |
|
|
691 |
/* Unused stubs */ |
/* Unused stubs */ |
692 |
kern_return_t |
kern_return_t |
693 |
device_read_reply (mach_port_t port, |
device_read_reply (mach_port_t port, |
759 |
} |
} |
760 |
|
|
761 |
|
|
762 |
struct bottomhalf devio_bottom = |
const struct bottomhalf devio_bottom = |
763 |
{ |
{ |
764 |
|
TERM_ON_MACHDEV, |
765 |
|
devio_init, |
766 |
devio_start_output, |
devio_start_output, |
767 |
devio_set_break, |
devio_set_break, |
768 |
devio_clear_break, |
devio_clear_break, |