diff options
author | Thomas Bushnell <thomas@gnu.org> | 1999-03-17 21:49:49 +0000 |
---|---|---|
committer | Thomas Bushnell <thomas@gnu.org> | 1999-03-17 21:49:49 +0000 |
commit | f24e60f1343c74beab961009ea4c545c805858e3 (patch) | |
tree | a2230172cce5772e3a8d24b8ccdf32af8b79e68f /term/devio.c | |
parent | 0af047580d3888861521979e4999722ccf9288f7 (diff) |
Wed Mar 17 16:32:05 1999 Thomas Bushnell, BSG <tb@mit.edu>
* users.c (S_term_get_peername): Compare BOTTOM against the
correct value, and call ports_port_deref with the proper name.
Reported by Yamashita TAKAO (az207@epa.go.jp).
* devio.c (devio_desert_dtr): Cast &BITS correctly in call to
device_set_status.
(device_open_reply): Alwas clean open_pending no matter what. Use
ERR instead of ERRNO. On fake opens, close the device before
deallocating the port.
Reported by Mark Kettenis (kettenis@gnu.org).
Tue Mar 16 01:04:06 1999 Thomas Bushnell, BSG <tb@mit.edu>
* devio.c (open_pending): Make an enum.
(devio_desert_dtr): Don't close the device, just set the TM_HUP
modem bit, which should cause a hangup to occur.
(devio_assert_dtr): Don't always open the device, instead use
initial_open the first time, and schedule a fake open the other
times.
(initial_open): New function, guts from old device_assert_dtr.
(device_open_reply): Distinguish replies from initial and fake
opens appropriately.
(ports_do_mach_notify_send_once): Test and set open_pending using
new enum values.
Diffstat (limited to 'term/devio.c')
-rw-r--r-- | term/devio.c | 168 |
1 files changed, 105 insertions, 63 deletions
diff --git a/term/devio.c b/term/devio.c index aeae5eaf..f8010bac 100644 --- a/term/devio.c +++ b/term/devio.c @@ -54,8 +54,13 @@ static int output_pending; /* This flag is set if there is an outstanding device_read. */ static int input_pending; -/* This flag is set if there is an outstanding device_open. */ -static int open_pending; +/* Tell the status of any pending open */ +static enum +{ + NOTPENDING, /* no open is pending */ + INITIAL, /* initial open of device pending */ + FAKE, /* open pending to block on dtr */ +} open_pending; static char pending_output[IO_INBAND_MAX]; static int npending_output; @@ -84,8 +89,6 @@ static int char_size_mask_xxx = 0xff; /* Forward */ static void devio_desert_dtr (); - - static void init_devio (void) __attribute__ ((constructor)); static void init_devio () @@ -393,37 +396,21 @@ devio_pending_output_size () return npending_output; } -static void -devio_desert_dtr () -{ - /* This will work, because we set the TF_HUPCLS bit earlier. */ - device_close (phys_device); - mach_port_deallocate (mach_task_self (), phys_device); - phys_device = MACH_PORT_NULL; - - mach_port_deallocate (mach_task_self (), phys_reply); - mach_port_deallocate (mach_task_self (), phys_reply_writes); - phys_reply = phys_reply_writes = MACH_PORT_NULL; - - ports_port_deref (phys_reply_pi); - ports_port_deref (phys_reply_writes_pi); - phys_reply_pi = phys_reply_writes_pi = 0; - - report_carrier_off (); -} - +/* Do this the first time the device is to be opened */ static error_t -devio_assert_dtr () +initial_open () { - error_t err; + assert (open_pending != FAKE); - if (open_pending || (phys_device != MACH_PORT_NULL)) + /* Nothing to do */ + if (open_pending == INITIAL) return 0; - + + assert (phys_device == MACH_PORT_NULL); assert (phys_reply == MACH_PORT_NULL); assert (phys_reply_pi == 0); - - err = ports_create_port (phys_reply_class, term_bucket, + + err = ports_create_port (phys_reply_class, term_bucket, sizeof (struct port_info), &phys_reply_pi); if (err) return err; @@ -442,11 +429,49 @@ devio_assert_dtr () phys_reply_pi = 0; } else - open_pending = 1; + open_pending = INITIAL; return err; } +static void +devio_desert_dtr () +{ + dev_status_t bits; + + /* Turn off DTR. */ + bits = TM_HUP; + device_set_status (phys_device, TTY_MODEM, + (dev_status_t) &bits, TTY_MODEM_COUNT); + + report_carrier_off (); +} + +static error_t +devio_assert_dtr () +{ + error_t err; + + /* The first time is special. */ + if (phys_device == MACH_PORT_NULL) + return initial_open (); + + /* Schedule a fake open to wait for DTR, unless one is already + happening. */ + assert (open_pending != INITIAL); + if (open_pending == FAKE) + return 0; + + err = device_open_request (device_master, phys_reply, + D_READ|D_WRITE, pterm_name); + + if (err) + return err; + + open_pending = FAKE; + return 0; +} + kern_return_t device_open_reply (mach_port_t replyport, int returncode, @@ -454,45 +479,65 @@ device_open_reply (mach_port_t replyport, { struct tty_status ttystat; int count = TTY_STATUS_COUNT; - error_t err; + error_t err = 0; if (replyport != phys_reply) return EOPNOTSUPP; mutex_lock (&global_lock); - open_pending = 0; + assert (open_pending != NOTPENDING); - if (returncode != 0) + if (open_pending == INITIAL) { - /* Bogus. */ - report_carrier_on (); - report_carrier_off (); + /* Special handling for the first open */ - mach_port_deallocate (mach_task_self (), phys_reply); - phys_reply = MACH_PORT_NULL; - ports_port_deref (phys_reply_pi); - phys_reply_pi = 0; - mutex_unlock (&global_lock); - return 0; - } + if (returncode != 0) + { + /* Bogus. */ + report_carrier_on (); + report_carrier_off (); - assert (phys_device == MACH_PORT_NULL); - assert (phys_reply_writes == MACH_PORT_NULL); - assert (phys_reply_writes_pi == 0); - phys_device = device; - errno = ports_create_port (phys_reply_class, term_bucket, - sizeof (struct port_info), - &phys_reply_writes_pi); - if (errno) + mach_port_deallocate (mach_task_self (), phys_reply); + phys_reply = MACH_PORT_NULL; + ports_port_deref (phys_reply_pi); + phys_reply_pi = 0; + + open_pending = NOTPENDING; + mutex_unlock (&global_lock); + return 0; + } + + assert (phys_device == MACH_PORT_NULL); + assert (phys_reply_writes == MACH_PORT_NULL); + assert (phys_reply_writes_pi == 0); + phys_device = device; + err = ports_create_port (phys_reply_class, term_bucket, + sizeof (struct port_info), + &phys_reply_writes_pi); + if (err) + { + open_pending = NOTPENDING; + mutex_unlock (&global_lock); + return err; + } + phys_reply_writes = ports_get_right (phys_reply_writes_pi); + mach_port_insert_right (mach_task_self (), phys_reply_writes, + phys_reply_writes, MACH_MSG_TYPE_MAKE_SEND); + + /* Schedule our first read */ + err = device_read_request_inband (phys_device, phys_reply, D_NOWAIT, + 0, vm_page_size); + + input_pending = 1; + } + else { - mutex_unlock (&global_lock); - return errno; + /* This was a fake open, only for the sake of assert DTR. */ + device_close (device); + mach_port_deallocate (mach_task_self (), device); } - phys_reply_writes = ports_get_right (phys_reply_writes_pi); - mach_port_insert_right (mach_task_self (), phys_reply_writes, - phys_reply_writes, MACH_MSG_TYPE_MAKE_SEND); - + device_get_status (phys_device, TTY_STATUS, (dev_status_t)&ttystat, &count); ttystat.tt_breakc = 0; @@ -500,14 +545,11 @@ device_open_reply (mach_port_t replyport, device_set_status (phys_device, TTY_STATUS, (dev_status_t)&ttystat, TTY_STATUS_COUNT); - err = device_read_request_inband (phys_device, phys_reply, D_NOWAIT, - 0, vm_page_size); - - input_pending = 1; report_carrier_on (); if (err) devio_desert_dtr (); + open_pending = NOTPENDING; mutex_unlock (&global_lock); return 0; @@ -661,9 +703,9 @@ ports_do_mach_notify_send_once (mach_port_t notify) else input_pending = 1; } - else if (open_pending) + else if (open_pending != NOTPENDING) { - open_pending = 0; + open_pending = NOTPENDiNG; report_carrier_on (); report_carrier_off (); |