[Prev][Next][Index][Thread]

Re: Reading from stdin blocks all MzScheme threads



> Date:    Sat, 19 Dec 98 13:32:36 -0600
> From:    Matthew Flatt <mflatt@cs.rice.edu>
> Subject: MzScheme kernel
> 
> Reading from stdin blocks all MzScheme threads. This seems to be a
> limitation of the OSKit's default stdin support (no non-blocking
> reads on stdin, and select() always claims stdin is ready to read),
> but if so, it looks like MzScheme can talk to the console directly
> to fix the problem.

Here is a patch file to fix the problem that Matthew reported in his
message about MzScheme. These patches make the freebsd TTY driver code
and the serial/vga device code "operational." A new interface function
in the FreeBSD C library can then be used to switch the stdio streams
to a proper TTY device (instead of the trivially simple console
driver) that can handle select.

See examples/x86/extended/console_tty.c for a brief example of how to
initialize a console like device (in this example, the sio serial
driver), and then have the FreeBSD C library use the TTY associated
with it).

Note that this patch file was created by "cvs rdiff", which appears to
create patches relative to the directory containing the oskit tree,
not the oskit directory itself (that is, one level higher than you
think).

Have fun. Let us know if you have any problems.
Leigh

---

Index: oskit/com/ttystream_wrapper.c
diff -c /dev/null oskit/com/ttystream_wrapper.c:1.1.2.1
*** /dev/null	Thu Dec 31 12:00:28 1998
--- oskit/com/ttystream_wrapper.c	Thu Dec 31 05:40:04 1998
***************
*** 0 ****
--- 1,548 ----
+ /*
+  * Copyright (c) 1997-1998 University of Utah and the Flux Group.
+  * All rights reserved.
+  * @OSKIT-FLUX-GPLUS@
+  */
+ 
+ /*
+  * Definitions for a COM object containing and wrapping the interfaces
+  * contained in our character TTY implementation
+  */
+ 
+ #include <oskit/com.h>
+ #include <oskit/com/wrapper.h>
+ #include <oskit/c/stdlib.h>
+ #include <oskit/c/stdio.h>
+ #include <oskit/c/string.h>
+ #include <oskit/io/asyncio.h>
+ #include <oskit/io/ttystream.h>
+ #include <oskit/dev/tty.h>
+ 
+ /*
+  * Wrapped up ttystream interfaces.
+  */
+ typedef struct {
+ 	oskit_ttystream_t	ios;		/* COM I/O interface Nr. 1 */
+ 	oskit_asyncio_t		ioa;		/* COM I/O interface Nr. 2 */
+ 	unsigned		count;		/* reference count */
+ 	oskit_ttystream_t	*w_ios;		/* COM I/O interface Nr. 1 */
+ 	oskit_asyncio_t		*w_ioa;		/* COM I/O interface Nr. 2 */
+ 	void			(*before)(void *);
+ 	void			(*after)(void *);
+ 	void			*cookie;
+ } oskit_ttyimpl_t;
+ 
+ #define WRAPPERCALL(impl, ops, iface, call, args...) ({			      \
+ 	oskit_error_t __err;						      \
+ 	impl->before(impl->cookie);					      \
+ 	__err = oskit_##iface##_##call(impl->w_##ops ,##args);        	      \
+ 	impl->after(impl->cookie);					      \
+ 	__err; })
+ 
+ #define WRAPPERCALL_NOARGS(impl, ops, iface, call) ({			      \
+ 	oskit_error_t __err;						      \
+ 	impl->before(impl->cookie);					      \
+ 	__err = oskit_##iface##_##call(impl->w_##ops);	      	      	      \
+ 	impl->after(impl->cookie);					      \
+ 	__err; })
+ 
+ /*
+  * implementations of query, addref and release dealing with
+  * different COM interfaces.
+  */
+ 
+ /*
+  * query
+  */
+ static OSKIT_COMDECL
+ query(oskit_ttyimpl_t *b, const struct oskit_guid *iid, void **out_ihandle)
+ {
+ 	oskit_error_t rc = 0;
+ 
+ 	b->before(b->cookie);
+         if (memcmp(iid, &oskit_iunknown_iid, sizeof(*iid)) == 0 ||
+ 	    memcmp(iid, &oskit_stream_iid, sizeof(*iid)) == 0 ||
+             memcmp(iid, &oskit_ttystream_iid, sizeof(*iid)) == 0) {
+ 		*out_ihandle = &b->ios;
+ 		++b->count;
+ 		b->after(b->cookie);
+ 		return 0;
+         }
+ 
+         if (memcmp(iid, &oskit_asyncio_iid, sizeof(*iid)) == 0) {
+ 		if (b->w_ioa == 0) 
+ 			rc = oskit_ttystream_query(b->w_ios, 
+ 				&oskit_asyncio_iid, (void **)&b->w_ioa);
+ 		if (rc == 0) {
+ 			*out_ihandle = &b->ioa;
+ 			++b->count;
+ 			b->after(b->cookie);
+ 			return 0;
+ 		}
+ 	}
+ 	b->after(b->cookie);
+ 
+         *out_ihandle = NULL;
+         return OSKIT_E_NOINTERFACE;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_query(oskit_ttystream_t *f, const struct oskit_guid *iid, 
+ 	void **out_ihandle)
+ {
+         oskit_ttyimpl_t *b = (oskit_ttyimpl_t *)f;
+ 	return query(b, iid, out_ihandle);
+ }
+ 
+ static OSKIT_COMDECL
+ asyncio_query(oskit_asyncio_t *f, const struct oskit_guid *iid,
+ 	void **out_ihandle)
+ {
+         oskit_ttyimpl_t *b = (oskit_ttyimpl_t *)(f-1);
+ 	return query(b, iid, out_ihandle);
+ }
+ 
+ /*
+  * addref
+  */
+ static OSKIT_COMDECL_U
+ addref(oskit_ttyimpl_t *b)
+ {
+ 	unsigned	newcount;
+ 	b->before(b->cookie);
+ 	newcount = ++b->count;
+ 	b->after(b->cookie);
+ 	return newcount;
+ }
+ 
+ static OSKIT_COMDECL_U
+ ttystream_addref(oskit_ttystream_t *f)
+ {
+         oskit_ttyimpl_t *b = (oskit_ttyimpl_t *)f;
+ 	return addref(b);
+ }
+ 
+ static OSKIT_COMDECL_U
+ asyncio_addref(oskit_asyncio_t *f)
+ {
+         oskit_ttyimpl_t *b = (oskit_ttyimpl_t *)(f-1);
+ 	return addref(b);
+ }
+ 
+ /*
+  * release. The contained ttyimpl was released, so release the wrapper.
+  */
+ static OSKIT_COMDECL_U
+ release(oskit_ttyimpl_t *b)
+ {
+         unsigned newcount;
+ 
+ 	b->before(b->cookie);
+ 	if ((newcount = --b->count) == 0) {
+ 		if (b->w_ios)
+ 			oskit_ttystream_release(b->w_ios);
+ 		if (b->w_ioa)
+ 			oskit_asyncio_release(b->w_ioa);
+ 		b->after(b->cookie);
+ 		free(b);
+ 	} else {
+ 		b->after(b->cookie);
+ 	}
+ 	return newcount;
+ }
+ 
+ static OSKIT_COMDECL_U
+ ttystream_release(oskit_ttystream_t *f)
+ {
+         oskit_ttyimpl_t *b = (oskit_ttyimpl_t *)f;
+ 	return release(b);
+ }
+ 
+ static OSKIT_COMDECL_U
+ asyncio_release(oskit_asyncio_t *f)
+ {
+         oskit_ttyimpl_t *b = (oskit_ttyimpl_t *)(f-1);
+ 	return release(b);
+ }
+ 
+ /*******************************************************/
+ /******* Implementation of the oskit_ttystream_t if ********/
+ /*******************************************************/
+ 
+ static OSKIT_COMDECL
+ ttystream_read(oskit_ttystream_t *f,
+ 	       void *buf, oskit_u32_t len, oskit_u32_t *out_actual)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, read, buf, len, out_actual);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_write(oskit_ttystream_t *f, const void *buf,
+ 		oskit_u32_t len, oskit_u32_t *out_actual)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, write, buf, len, out_actual);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_seek(oskit_ttystream_t *f, oskit_s64_t ofs,
+ 	       oskit_seek_t whence, oskit_u64_t *out_newpos)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, seek, ofs, whence, out_newpos);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_setsize(oskit_ttystream_t *f, oskit_u64_t new_size)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, setsize, new_size);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_copyto(oskit_ttystream_t *f, oskit_ttystream_t *dst,
+ 		 oskit_u64_t size,
+ 		 oskit_u64_t *out_read,
+ 		 oskit_u64_t *out_written)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, copyto,
+ 			  dst, size, out_read, out_written);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_commit(oskit_ttystream_t *f, oskit_u32_t commit_flags)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, commit, commit_flags);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_revert(oskit_ttystream_t *f)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL_NOARGS(s, ios, ttystream, revert);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_lock_region(oskit_ttystream_t *f,
+ 		      oskit_u64_t offset,
+ 		      oskit_u64_t size, oskit_u32_t lock_type)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, lockregion,
+ 			  offset, size, lock_type);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_unlock_region(oskit_ttystream_t *f,
+ 			oskit_u64_t offset,
+ 			oskit_u64_t size, oskit_u32_t lock_type)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, unlockregion,
+ 			  offset, size, lock_type);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_stat(oskit_ttystream_t *f, oskit_stream_stat_t *out_stat,
+ 	       oskit_u32_t stat_flags)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, stat, out_stat, stat_flags);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_clone(oskit_ttystream_t *f, oskit_ttystream_t **out_stream)
+ {
+ 	oskit_ttyimpl_t		*s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t		err;
+ 	oskit_ttystream_t	*str;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, clone, &str);
+ 	if (err == 0) {
+ 		/* wrap the stream interface only !? */
+ 		err = oskit_wrap_ttystream(str, 
+ 					   s->before, s->after, s->cookie,
+ 					   out_stream);
+ 		oskit_ttystream_release(str);
+ 	}
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_getattr(oskit_ttystream_t *f, struct oskit_termios *out_attr)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, getattr, out_attr);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_setattr(oskit_ttystream_t *f,
+ 		  int actions, const struct oskit_termios *attr)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, setattr, actions, attr);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_sendbreak(oskit_ttystream_t *f, oskit_u32_t duration)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, sendbreak, duration);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_drain(oskit_ttystream_t *f)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL_NOARGS(s, ios, ttystream, drain);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_flush(oskit_ttystream_t *f, int queue_selector)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, flush, queue_selector);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_flow(oskit_ttystream_t *f, int action)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, flow, action);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_getpgrp(oskit_ttystream_t *f, oskit_pid_t *out_pid)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, getpgrp, out_pid);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_setpgrp(oskit_ttystream_t *f, oskit_pid_t new_pid)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, setpgrp, new_pid);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_ttyname(oskit_ttystream_t *f, char **out_name)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, ttyname, out_name);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ ttystream_getsid(oskit_ttystream_t *f, oskit_pid_t *out_pid)
+ {
+ 	oskit_ttyimpl_t *s = (oskit_ttyimpl_t *)(f);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(s, ios, ttystream, getsid, out_pid);
+ 
+ 	return err;
+ }
+ 
+ /*******************************************************/
+ /******* Implementation of the oskit_asyncio_t if *******/
+ /*******************************************************/
+ 
+ static OSKIT_COMDECL
+ asyncio_poll(oskit_asyncio_t *f)
+ {
+ 	oskit_ttyimpl_t *si = (oskit_ttyimpl_t *)(f-1);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL_NOARGS(si, ioa, asyncio, poll);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ asyncio_add_listener(oskit_asyncio_t *f, struct oskit_listener *l,
+ 	oskit_s32_t mask)
+ {
+ 	oskit_ttyimpl_t *si = (oskit_ttyimpl_t *)(f-1);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(si, ioa, asyncio, add_listener, l, mask);
+ 
+ 	return err;
+ }
+ 
+ static OSKIT_COMDECL
+ asyncio_remove_listener(oskit_asyncio_t *f, struct oskit_listener *l0)
+ {
+ 	oskit_ttyimpl_t *si = (oskit_ttyimpl_t *)(f-1);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL(si, ioa, asyncio, remove_listener, l0);
+ 
+ 	return err;
+ }
+ /*
+  * return the number of bytes that can be read, basically ioctl(FIONREAD)
+  */
+ static OSKIT_COMDECL
+ asyncio_readable(oskit_asyncio_t *f)
+ {
+ 	oskit_ttyimpl_t *si = (oskit_ttyimpl_t *)(f-1);
+ 	oskit_error_t	 err;
+ 
+ 	err = WRAPPERCALL_NOARGS(si, ioa, asyncio, readable);
+ 
+ 	return err;
+ }
+ 
+ /***************************************************************************/
+ /*
+  * vtables for interfaces exported by ttytreams
+  */
+ static struct oskit_ttystream_ops ttystreamops =
+ {
+ 	ttystream_query,
+ 	ttystream_addref,
+ 	ttystream_release,
+ 	ttystream_read,
+ 	ttystream_write,
+ 	ttystream_seek,
+ 	ttystream_setsize,
+ 	ttystream_copyto,
+ 	ttystream_commit,
+ 	ttystream_revert,
+ 	ttystream_lock_region,
+ 	ttystream_unlock_region,
+ 	ttystream_stat,
+ 	ttystream_clone,
+ 	ttystream_getattr, 
+ 	ttystream_setattr, 
+ 	ttystream_sendbreak, 
+ 	ttystream_drain, 
+ 	ttystream_flush, 
+ 	ttystream_flow, 
+ 	ttystream_getpgrp, 
+ 	ttystream_setpgrp,
+ 	ttystream_ttyname, 
+ 	ttystream_getsid
+ };
+ 
+ static struct oskit_asyncio_ops asyncioops =
+ {
+ 	asyncio_query,
+ 	asyncio_addref,
+ 	asyncio_release,
+ 	asyncio_poll,
+ 	asyncio_add_listener,
+ 	asyncio_remove_listener,
+ 	asyncio_readable
+ };
+ 
+ 
+ /*
+  * Wrap a ttyimpl in the thread specific version.
+  */
+ oskit_error_t
+ oskit_wrap_ttystream(struct oskit_ttystream *in,
+         void (*before)(),
+ 	void (*after)(),
+ 	void *cookie,
+ 	struct oskit_ttystream **out)
+ {
+         oskit_ttyimpl_t *newtty = malloc(sizeof(*newtty));
+ 
+         if (newtty == NULL)
+                 return OSKIT_ENOMEM;
+         memset(newtty, 0, sizeof(*newtty));
+ 
+         newtty->count = 1;
+         newtty->ios.ops = &ttystreamops;
+         newtty->ioa.ops = &asyncioops;
+ 	newtty->w_ios = in;
+ 	oskit_ttystream_addref(newtty->w_ios);
+ 
+ 	newtty->before = before;
+ 	newtty->after = after;
+ 	newtty->cookie = cookie;
+ 
+ 	*out = &newtty->ios;
+ 	return 0;
+ }
Index: oskit/examples/x86/extended/GNUmakerules
diff -c oskit/examples/x86/extended/GNUmakerules:1.7 oskit/examples/x86/extended/GNUmakerules:1.7.2.1
*** oskit/examples/x86/extended/GNUmakerules:1.7	Tue Dec 15 17:25:14 1998
--- oskit/examples/x86/extended/GNUmakerules	Thu Dec 31 06:36:56 1998
***************
*** 8,14 ****
  _oskit_examples_x86_threads_makerules__ = yes
  
  TARGETS = bmodfs mmap_dev_mem fsbmodmount gethostbyname hello netbsd_fs_posix \
! 		select socket_bsd testlinear vgatest video
  
  all: $(TARGETS)
  
--- 8,14 ----
  _oskit_examples_x86_threads_makerules__ = yes
  
  TARGETS = bmodfs mmap_dev_mem fsbmodmount gethostbyname hello netbsd_fs_posix \
! 		select socket_bsd testlinear vgatest video console_tty
  
  all: $(TARGETS)
  
***************
*** 183,187 ****
--- 183,200 ----
  	$(CC) -c -o $@ $(OSKIT_CFLAGS) $(CFLAGS) \
  	-DNEED_MORE_TYPES \
  	-I$(OSKIT_SRCDIR)/wimp/src -I$(OSKIT_SRCDIR)/wimp/oskit $<
+ 
+ console_tty: $(OBJDIR)/lib/multiboot.o console_tty.o $(DEPENDLIBS)
+ 	$(LD) -Ttext 100000 $(LDFLAGS) $(OSKIT_LDFLAGS) \
+ 		-o $@ $(filter-out %.a,$^)		\
+ 		-loskit_startup \
+ 		-loskit_bootp \
+ 		-loskit_freebsd_net \
+ 		-loskit_freebsd_dev \
+ 		-loskit_linux_dev -loskit_dev -loskit_kern \
+ 		-loskit_freebsd_c -loskit_com -loskit_lmm -loskit_netbsd_fs \
+ 		-loskit_diskpart -loskit_fs \
+ 		-loskit_freebsd_c -loskit_com \
+ 		$(OBJDIR)/lib/crtn.o
  endif
  
Index: oskit/examples/x86/extended/console_tty.c
diff -c /dev/null oskit/examples/x86/extended/console_tty.c:1.1.2.1
*** /dev/null	Thu Dec 31 12:00:30 1998
--- oskit/examples/x86/extended/console_tty.c	Thu Dec 31 09:35:50 1998
***************
*** 0 ****
--- 1,72 ----
+ /*
+  * Copyright (c) 1997-1998 University of Utah and the Flux Group.
+  * All rights reserved.
+  * @OSKIT-FLUX-GPLUS@
+  */
+ /*
+  * Simple program to demonstrate the use of the tty drivers as the
+  * console interface. After initializing the serial console device,
+  * have the C library reconstitute its notion of the stdio streams.
+  */
+ 
+ #include <stdio.h>
+ #include <malloc.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <oskit/io/ttystream.h>
+ #include <oskit/dev/dev.h>
+ #include <oskit/dev/tty.h>
+ #include <oskit/dev/freebsd.h>
+ #include <oskit/startup.h>
+ 
+ #define DISKNAME "wd1"
+ #define PARTITION "b"
+ 
+ int
+ main(int argc, char **argv)
+ {
+ 	char buf[128];
+ 	fd_set  in;
+ 	int rc;
+ 
+ 	start_clock();
+ 	
+ 	printf("Initializing device drivers...\n");
+ 	oskit_dev_init();
+ 	oskit_linux_init_ethernet_tulip();
+ 	oskit_linux_init_ethernet_eepro100();
+ 	oskit_linux_init_ide();
+ 
+ 	/*
+ 	 * This is the console TTY device. A serial line. 
+ 	 */
+ 	oskit_freebsd_init_sio();
+ 	
+ 	printf("Probing device drivers...\n");
+ 	oskit_dev_probe();
+ 
+ 	printf("Starting filesystem and network...\n");
+ 	start_fs(DISKNAME, PARTITION);
+ 	start_network();
+ 
+ 	/*
+ 	 * This is the crux of the biscuit!
+ 	 */
+ 	printf("Reconstituting stdio streams to console TTY...\n");
+ 	oskit_console_init();
+ 
+ 	printf("\nOkay, now type stuff and it will echo. Type ^D to exit\n");
+ 	
+ 	while (1) {
+ 		FD_ZERO(&in);
+ 		FD_SET(0, &in);
+ 		rc = select(1, &in, 0, 0, 0);
+ 
+ 		if (fgets(buf, 128, stdin) == NULL)
+ 			break;
+ 		
+ 		printf("%s", buf);
+ 	}
+ 
+ 	return 0;
+ }
Index: oskit/examples/x86/threads/GNUmakerules
diff -c oskit/examples/x86/threads/GNUmakerules:1.3 oskit/examples/x86/threads/GNUmakerules:1.3.2.1
*** oskit/examples/x86/threads/GNUmakerules:1.3	Tue Nov 10 06:25:31 1998
--- oskit/examples/x86/threads/GNUmakerules	Thu Dec 31 06:36:56 1998
***************
*** 7,13 ****
  ifndef _oskit_examples_x86_threads_makerules_
  _oskit_examples_x86_threads_makerules__ = yes
  
! TARGETS = dphils http_proxy disktest disknet
  
  all: $(TARGETS)
  
--- 7,13 ----
  ifndef _oskit_examples_x86_threads_makerules_
  _oskit_examples_x86_threads_makerules__ = yes
  
! TARGETS = dphils http_proxy disktest disknet console_tty
  
  all: $(TARGETS)
  
***************
*** 76,81 ****
--- 76,98 ----
  		-loskit_threads -loskit_svm -loskit_amm \
  		-loskit_bootp \
  		-loskit_freebsd_net \
+ 		-loskit_linux_dev -loskit_dev -loskit_kern \
+ 		-loskit_freebsd_c_r -loskit_com -loskit_lmm -loskit_netbsd_fs \
+ 		-loskit_diskpart -loskit_fs -loskit_freebsd_c_r -loskit_com \
+ 		-loskit_threads \
+ 		$(OBJDIR)/lib/crtn.o
+ 	cp $@ $@.gdb
+ 	$(STRIP) $@
+ 
+ console_tty: $(OBJDIR)/lib/multiboot.o console_tty.o \
+ 	$(DEPENDLIBS)
+ 	$(LD) -Ttext 100000 $(LDFLAGS) $(OSKIT_LDFLAGS) \
+ 		-o $@ $(filter-out %.a,$^) \
+ 		-loskit_startup \
+ 		-loskit_threads -loskit_svm -loskit_amm \
+ 		-loskit_bootp \
+ 		-loskit_freebsd_net \
+ 		-loskit_freebsd_dev \
  		-loskit_linux_dev -loskit_dev -loskit_kern \
  		-loskit_freebsd_c_r -loskit_com -loskit_lmm -loskit_netbsd_fs \
  		-loskit_diskpart -loskit_fs -loskit_freebsd_c_r -loskit_com \
Index: oskit/examples/x86/threads/console_tty.c
diff -c /dev/null oskit/examples/x86/threads/console_tty.c:1.1.2.1
*** /dev/null	Thu Dec 31 12:00:30 1998
--- oskit/examples/x86/threads/console_tty.c	Thu Dec 31 09:35:51 1998
***************
*** 0 ****
--- 1,85 ----
+ /*
+  * Copyright (c) 1997-1998 University of Utah and the Flux Group.
+  * All rights reserved.
+  * @OSKIT-FLUX-GPLUS@
+  */
+ /*
+  * Example program to test the function of device drivers
+  * that implement the oskit_ttydev interface.
+  * Specifically the FreeBSD syscons device.
+  *
+  * It prints out some stuff to the system console and then echos
+  * characters back until it sees 'X'.
+  */
+ 
+ #include <stdio.h>
+ #include <malloc.h>
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <oskit/io/ttystream.h>
+ #include <oskit/fs/file.h>	/* XXX OSKIT_O_RDWR */
+ #include <oskit/dev/dev.h>
+ #include <oskit/dev/tty.h>
+ #include <oskit/dev/freebsd.h>
+ #include <oskit/startup.h>
+ 
+ #define DISKNAME "wd1"
+ #define PARTITION "b"
+ 
+ int
+ main(int argc, char **argv)
+ {
+ 	int rc;
+ 	char buf[128];
+ 	fd_set  in;
+ 
+ 	/*
+ 	 * Init pthreads module.
+ 	 */
+ 	pthread_init(1);
+ 
+ 	start_clock();
+ 
+ 	printf("Initializing device drivers...\n");
+ 	osenv_process_lock();
+ 	oskit_dev_init();
+ 	oskit_linux_init_ethernet_tulip();
+ 	oskit_linux_init_ethernet_eepro100();
+ 	oskit_linux_init_ide();
+ 	
+ 	/*
+ 	 * This is the console TTY device. A serial line. 
+ 	 */
+ 	oskit_freebsd_init_sio();
+ 
+ 	printf("Probing device drivers...\n");
+ 	oskit_dev_probe();
+ 	osenv_process_unlock();
+ 
+ 	printf("Starting filesystem and network...\n");
+ 	start_fs_pthreads(DISKNAME, PARTITION);
+ 	start_network_pthreads();
+ 
+ 	/*
+ 	 * This is the crux of the biscuit! Note that this must come last
+ 	 * since all that device stuff above generates printfs, and thats
+ 	 * bad since the process lock is held. 
+ 	 */
+ 	printf("Reconstituting stdio streams to console TTY...\n");
+ 	oskit_console_init();
+ 	
+ 	printf("\nOkay, now type stuff and it will echo. Type ^D to exit\n");
+ 	
+ 	while (1) {
+ 		FD_ZERO(&in);
+ 		FD_SET(0, &in);
+ 		rc = select(1, &in, 0, 0, 0);
+ 
+ 		if (fgets(buf, 128, stdin) == NULL)
+ 			break;
+ 		
+ 		printf("%s", buf);
+ 	}
+ 
+ 	return 0;
+ }
Index: oskit/freebsd/dev/char.c
diff -c oskit/freebsd/dev/char.c:1.14 oskit/freebsd/dev/char.c:1.14.4.1
*** oskit/freebsd/dev/char.c:1.14	Wed Apr  8 16:43:45 1998
--- oskit/freebsd/dev/char.c	Thu Dec 31 05:59:39 1998
***************
*** 13,23 ****
--- 13,26 ----
  #include <sys/stat.h>
  #include <sys/termios.h>
  #include <sys/vnode.h>
+ #include <sys/ioctl.h>
  
  #include <oskit/com.h>
  #include <oskit/io/ttystream.h>
+ #include <oskit/io/asyncio.h>
  #include <oskit/dev/tty.h>
  #include <oskit/dev/freebsd.h>
+ #include <oskit/com/listener_mgr.h>
  
  #include "glue.h"
  
***************
*** 26,36 ****
--- 29,44 ----
  
  struct strm {
  	oskit_ttystream_t strmi;
+ 	oskit_asyncio_t	ioa;
  	int refs;
  	int major;
  	dev_t dev;
  	int flags;
  	int io_flag;
+ 	struct tty *tp;
+ 
+ 	struct listener_mgr *readers;	/* listeners for asyncio READ */
+ 	struct listener_mgr *writers;	/* listeners for asyncio WRITE*/
  };
  
  static OSKIT_COMDECL
***************
*** 46,51 ****
--- 54,65 ----
  		return 0;
  	}
  
+         if (memcmp(iid, &oskit_asyncio_iid, sizeof(*iid)) == 0) {
+ 		s->refs++;
+                 *out_ihandle = &s->ioa;
+                 return 0;
+ 	}
+ 
  	*out_ihandle = NULL;
  	return OSKIT_E_NOINTERFACE;
  }
***************
*** 72,77 ****
--- 86,93 ----
  		OSKIT_FREEBSD_CREATE_CURPROC(p);
  		cdevsw[s->major].d_close(s->dev, s->flags, S_IFCHR, curproc);
  		OSKIT_FREEBSD_DESTROY_CURPROC(p);
+ 		oskit_destroy_listener_mgr(s->readers);
+ 		oskit_destroy_listener_mgr(s->writers);
  		osenv_mem_free(s, 0, sizeof(*s));
  	}
  	return newcount;
***************
*** 415,420 ****
--- 431,599 ----
  	getsid
  };
  
+ /*******************************************************/
+ /******* Implementation of the oskit_asyncio_t if *******/
+ /*******************************************************/
+ 
+ /*
+  * XXX I put this in tty.c so as not to duplicate code here.
+  */
+ unsigned	ttyconds(struct tty *);
+ 
+ static OSKIT_COMDECL
+ char_asyncio_query(oskit_asyncio_t *f, const struct oskit_guid *iid,
+ 	void **out_ihandle)
+ {
+ 	oskit_ttystream_t *si = (oskit_ttystream_t *)(f - 1);
+ 	
+ 	return query(si, iid, out_ihandle);
+ }
+ 
+ static OSKIT_COMDECL_U
+ char_asyncio_addref(oskit_asyncio_t *f)
+ {
+ 	oskit_ttystream_t *si = (oskit_ttystream_t *)(f - 1);
+ 	
+ 	return add_ref(si);
+ }
+ 
+ static OSKIT_COMDECL_U
+ char_asyncio_release(oskit_asyncio_t *f)
+ {
+ 	oskit_ttystream_t *si = (oskit_ttystream_t *)(f - 1);
+ 	
+ 	return release(si);
+ }
+ 
+ /*
+  * Poll for currently pending asynchronous I/O conditions.
+  * If successful, returns a mask of the OSKIT_ASYNC_IO_* flags above,
+  * indicating which conditions are currently present.
+  */
+ static OSKIT_COMDECL
+ char_asyncio_poll(oskit_asyncio_t *f)
+ {
+ 	struct strm	*strm = (struct strm *)(f - 1);
+         oskit_u32_t     conds;
+         int		s;
+ 	
+ 	s = spltty();
+ 	conds = ttyconds(strm->tp);
+         splx(s);
+ 
+         return conds;
+ }
+ 
+ /*
+  * Add a callback object (a "listener" for async I/O events).
+  * When an event of interest occurs on this I/O object
+  * (i.e., when one of the three I/O conditions becomes true),
+  * all registered listeners will be called.
+  * Also, if successful, this method returns a mask
+  * describing which of the OSKIT_ASYNC_IO_* conditions are already true,
+  * which the caller must check in order to avoid missing events
+  * that occur just before the listener is registered.
+  */
+ static OSKIT_COMDECL
+ char_asyncio_add_listener(oskit_asyncio_t *f, struct oskit_listener *l,
+ 	oskit_s32_t mask)
+ {
+ 	struct strm	*strm = (struct strm *)(f - 1);
+ 	struct tty	*tp = strm->tp;
+         oskit_u32_t     conds;
+         int		s;
+ 	struct proc 	p;
+ 
+ 	OSKIT_FREEBSD_CREATE_CURPROC(p)
+         s = spltty();
+ 	conds = ttyconds(strm->tp);
+ 
+ 	/* for read and exceptional conditions */
+ 	if (mask & (OSKIT_ASYNCIO_READABLE | OSKIT_ASYNCIO_EXCEPTION))
+ 	{
+ 		oskit_listener_mgr_add(strm->readers, l);
+ 		curproc->p_sel = strm->readers;
+ 		selrecord(curproc, &tp->t_rsel);
+ 		curproc->p_sel = 0;
+ 	}
+ 
+ 	/* for write */
+ 	if (mask & OSKIT_ASYNCIO_WRITABLE)
+ 	{
+ 		oskit_listener_mgr_add(strm->writers, l);
+ 		curproc->p_sel = strm->writers;
+ 		selrecord(curproc, &tp->t_wsel);
+ 		curproc->p_sel = 0;
+ 	}
+ 	
+         splx(s);
+ 	OSKIT_FREEBSD_DESTROY_CURPROC(p)
+         return conds;
+ }
+ 
+ /*
+  * Remove a previously registered listener callback object.
+  * Returns an error if the specified callback has not been registered.
+  */
+ static OSKIT_COMDECL
+ char_asyncio_remove_listener(oskit_asyncio_t *f, struct oskit_listener *l0)
+ {
+ 	struct strm	*strm = (struct strm *)(f - 1);
+ 	struct tty	*tp = strm->tp;
+ 	oskit_error_t	rc1, rc2;
+ 	int		s;
+ 
+ 	s = spltty();
+ 
+ 	/*
+ 	 * we don't know where was added - if at all - so let's check
+ 	 * both lists
+ 	 *
+ 	 * turn off notifications if no listeners left
+ 	 */
+ 	rc1 = oskit_listener_mgr_remove(strm->readers, l0);
+ 	if (oskit_listener_mgr_count(strm->readers) == 0) {
+ 		tp->t_rsel.si_sel = 0;
+ 		tp->t_rsel.si_pid = 0;
+ 	}
+ 
+ 	rc2 = oskit_listener_mgr_remove(strm->writers, l0);
+ 	if (oskit_listener_mgr_count(strm->writers) == 0) {
+ 		tp->t_wsel.si_sel = 0;
+ 		tp->t_wsel.si_pid = 0;
+ 	}
+ 
+ 	splx(s);
+ 
+ 	/* flag error if both removes failed */
+ 	return (rc1 && rc2) ? OSKIT_E_INVALIDARG : 0;	/* is that right ? */
+ }
+ 
+ /*
+  * return the number of bytes that can be read, basically ioctl(FIONREAD)
+  */
+ static OSKIT_COMDECL
+ char_asyncio_readable(oskit_asyncio_t *f)
+ {
+ 	struct strm	*strm = (struct strm *)(f - 1);
+ 	int		count;
+ 
+ 	ioctl(strm, FIONREAD, (caddr_t)&count);
+ 	
+ 	return count;
+ }
+ 
+ static struct oskit_asyncio_ops asyncioops =
+ {
+ 	char_asyncio_query,
+ 	char_asyncio_addref,
+ 	char_asyncio_release,
+ 	char_asyncio_poll,
+ 	char_asyncio_add_listener,
+ 	char_asyncio_remove_listener,
+ 	char_asyncio_readable
+ };
+ 
  
  oskit_error_t 
  oskit_freebsd_chardev_open(int major, int minor, int flags,
***************
*** 438,444 ****
  	s->dev = makedev(major, minor);
  	s->flags = flags;
  	s->io_flag = (flags & O_NONBLOCK) ? IO_NDELAY : 0;
! 
  	OSKIT_FREEBSD_CREATE_CURPROC(p);
  
  	bsd_rc = cdevsw[major].d_open(s->dev, flags, S_IFCHR, curproc);
--- 617,623 ----
  	s->dev = makedev(major, minor);
  	s->flags = flags;
  	s->io_flag = (flags & O_NONBLOCK) ? IO_NDELAY : 0;
! 	
  	OSKIT_FREEBSD_CREATE_CURPROC(p);
  
  	bsd_rc = cdevsw[major].d_open(s->dev, flags, S_IFCHR, curproc);
***************
*** 449,454 ****
--- 628,638 ----
  		osenv_mem_free(s, 0, sizeof(*s));
  		return oskit_freebsd_xlate_errno(bsd_rc);
  	}
+ 
+ 	s->ioa.ops = &asyncioops;
+ 	s->readers = oskit_create_listener_mgr((oskit_iunknown_t *)&s->ioa);
+ 	s->writers = oskit_create_listener_mgr((oskit_iunknown_t *)&s->ioa);
+ 	s->tp      = cdevsw[major].d_devtotty(s->dev);
  
  	*out_ttystream = &s->strmi;
  	return 0;
Index: oskit/freebsd/dev/global.h
diff -c oskit/freebsd/dev/global.h:1.5 oskit/freebsd/dev/global.h:1.5.4.1
*** oskit/freebsd/dev/global.h:1.5	Wed Apr  8 16:43:45 1998
--- oskit/freebsd/dev/global.h	Thu Dec 31 06:00:52 1998
***************
*** 463,467 ****
--- 463,471 ----
  #define untimeout FDEV_FREEBSD_untimeout
  #define ureadc FDEV_FREEBSD_ureadc
  #define wakeup FDEV_FREEBSD_wakeup
+ #define register_swi FDEV_FREEBSD_register_swi
+ #define swi_dispatcher FDEV_FREEBSD_swi_dispatcher
+ #define swi_check FDEV_FREEBSD_swi_check
+ #define ttyconds FDEV_FREEBSD_ttyconds
  
  #endif /* _FREEBSD_DEV_GLOBAL_H_ */
Index: oskit/freebsd/dev/isa.c
diff -c oskit/freebsd/dev/isa.c:1.19 oskit/freebsd/dev/isa.c:1.19.4.1
*** oskit/freebsd/dev/isa.c:1.19	Wed Apr  8 16:43:47 1998
--- oskit/freebsd/dev/isa.c	Thu Dec 31 06:02:04 1998
***************
*** 6,11 ****
--- 6,12 ----
  
  #include <sys/param.h>
  #include <sys/devconf.h>
+ #include <sys/interrupt.h>
  
  #include <oskit/com.h>
  #include <oskit/dev/tty.h>
***************
*** 59,64 ****
--- 60,67 ----
  	dev->id_intr(dev->id_unit);
  
  	restore_cpl(cpl);
+ 
+ 	swi_check();
  }
  
  
Index: oskit/freebsd/libc/glue/console_tty.c
diff -c /dev/null oskit/freebsd/libc/glue/console_tty.c:1.1.2.1
*** /dev/null	Thu Dec 31 12:00:32 1998
--- oskit/freebsd/libc/glue/console_tty.c	Thu Dec 31 09:43:33 1998
***************
*** 0 ****
--- 1,132 ----
+ /*
+  * Copyright (c) 1997-1998 University of Utah and the Flux Group.
+  * All rights reserved.
+  * @OSKIT-FLUX-GPLUS@
+  */
+ 
+ /*
+  * Switch to a real tty driver for the console. If we find a tty driver
+  * to use, replace the console_stream used for stdin/stdout/stderr with
+  * it. The application should not call this unless it has initialized
+  * a console like device.
+  */
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <oskit/io/ttystream.h>
+ #include <oskit/fs/file.h>	/* XXX OSKIT_O_RDWR */
+ #include <oskit/dev/dev.h>
+ #include <oskit/dev/tty.h>
+ #include <oskit/io/asyncio.h>
+ #include <oskit/io/posixio.h>
+ #include <oskit/com/wrapper.h>
+ #include "fd.h"
+ 
+ /*
+  * Default settings for the console TTY.
+  */
+ #define	TTYDEF_IFLAG \
+ 	(OSKIT_BRKINT|OSKIT_ICRNL|OSKIT_IXON|OSKIT_IXANY)
+ #define TTYDEF_OFLAG \
+ 	(OSKIT_OPOST|OSKIT_ONLCR)
+ #define TTYDEF_LFLAG \
+ 	(OSKIT_ECHO|\
+ 	 OSKIT_ICANON|OSKIT_ISIG|OSKIT_IEXTEN|OSKIT_ECHOE|OSKIT_ECHOK)
+ #define	TTYDEF_CFLAG \
+ 	(OSKIT_CREAD|OSKIT_CS8|OSKIT_HUPCL)
+ 
+ void
+ oskit_console_init(void)
+ {
+ 	oskit_ttydev_t		**ttydev;
+ 	oskit_ttystream_t	*ttystrm;
+ 	oskit_termios_t		termios;
+ 	int			rc, ndev, i, enabled;
+ 
+ #ifdef  THREAD_SAFE
+ 	osenv_process_lock();
+ #endif
+ 	/*
+ 	 * Find all TTY device nodes.
+ 	 */
+ 	ndev = osenv_device_lookup(&oskit_ttydev_iid, (void***)&ttydev);
+ 	if (ndev <= 0)
+ 		panic("no TTY devices found!");
+ 
+ 	/*
+ 	 * Open the first TTY device found. I am going to say thats
+ 	 * the console device the application wanted to use.
+ 	 */
+ 	rc = oskit_ttydev_open(ttydev[0], OSKIT_O_RDWR, &ttystrm);
+ 	if (rc)
+ 		panic("unable to open tty0: %d", rc);
+ 
+ 	/*
+ 	 * Okay, release our references.
+ 	 */
+ 	for (i = 0; i < ndev; i++)
+ 		oskit_ttydev_release(ttydev[i]);
+ 
+ 	/*
+ 	 * Set properties for a normal tty.
+ 	 */
+ 	rc = oskit_ttystream_getattr(ttystrm, &termios);
+ 	if (rc)
+ 		panic("unable to getattr: %d", rc);
+ 	
+ 	termios.iflag = TTYDEF_IFLAG;
+ 	termios.oflag = TTYDEF_OFLAG;
+ 	termios.cflag = TTYDEF_CFLAG;
+ 	termios.lflag = TTYDEF_LFLAG;
+ 	termios.cc[3] = 8; /* ^H */
+ 	
+ 	rc = oskit_ttystream_setattr(ttystrm, OSKIT_TCSANOW, &termios);
+ 	if (rc)
+ 		panic("unable to setattr: %d", rc);
+ 
+ #ifdef  THREAD_SAFE
+ 	/*
+ 	 * Need to wrap the stream in a thread-safe wrapper.
+ 	 */
+ 	{
+ 		oskit_ttystream_t	*wrapped_ttystrm;
+ 		
+ 		rc = oskit_wrap_ttystream(ttystrm,
+ 			  (void (*)(void *))osenv_process_lock, 
+ 			  (void (*)(void *))osenv_process_unlock,
+ 			  0, &wrapped_ttystrm);
+ 
+ 		if (rc)
+ 			panic("oskit_wrap_ttystream() failed: "
+ 			      "errno 0x%x\n", rc);
+ 
+ 		/* Don't need the original anymore, the wrapper has a ref. */
+ 		oskit_ttystream_release(ttystrm);
+ 
+ 		ttystrm = wrapped_ttystrm;
+ 		osenv_process_unlock();
+ 	}
+ #endif
+ 	/*
+ 	 * Okay, now replace the console_stream for the stdio descriptors.
+ 	 */
+ 	if ((enabled = osenv_intr_enabled()))
+ 		osenv_intr_disable();
+ 		
+ 	fd_init();
+ 	fd_free(0);
+ 	fd_free(1);
+ 	fd_free(2);
+ 	fd_alloc((oskit_iunknown_t*)ttystrm, 0);
+ 	fd_alloc((oskit_iunknown_t*)ttystrm, 1);
+ 	fd_alloc((oskit_iunknown_t*)ttystrm, 2);
+ 
+ 	if (enabled)
+ 		osenv_intr_enable();
+ 
+ 	/*
+ 	 * Release our reference since fd_alloc took one for each.
+ 	 */
+ 	oskit_ttystream_release(ttystrm);
+ }
Index: oskit/freebsd/shared/kern_intr.c
diff -c /dev/null oskit/freebsd/shared/kern_intr.c:1.1.2.1
*** /dev/null	Thu Dec 31 12:00:36 1998
--- oskit/freebsd/shared/kern_intr.c	Thu Dec 31 09:40:52 1998
***************
*** 0 ****
--- 1,110 ----
+ /*
+  * Copyright (c) 1997-1998 University of Utah and the Flux Group.
+  * All rights reserved.
+  * @OSKIT-FLUX-GPLUS@
+  */
+ /*
+  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice unmodified, this list of conditions, and the following
+  *    disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  * $\Id: kern_intr.c,v 1.20 1998/09/26 14:25:31 dfr Exp $
+  *
+  */
+ 
+ #include <sys/types.h>
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/errno.h>
+ #include <sys/malloc.h>
+ #include <sys/interrupt.h>
+ #include <machine/spl.h>
+ #include "glue.h"
+ 
+ #define NSWI	16	/* XXX */
+ 
+ struct swilist {
+ 	swihand_t	*sl_handler;
+ 	struct swilist	*sl_next;
+ };
+ 
+ static struct swilist swilists[NSWI];
+ 
+ void
+ register_swi(intr, handler)
+ 	int intr;
+ 	swihand_t *handler;
+ {
+ 	struct swilist *slp, *slq;
+ 	int s;
+ 
+ 	if (intr < NHWI || intr >= NHWI + NSWI)
+ 		panic("register_swi: bad intr %d", intr);
+ 	slp = &swilists[intr - NHWI];
+ 	s = splhigh();
+ 
+ 	if (slp->sl_handler == NULL) {
+ 		slp->sl_handler = handler;
+ 	}
+ 	else {
+ 		slq = malloc(sizeof(*slq), M_DEVBUF, M_NOWAIT);
+ 
+ 		slq->sl_handler = handler;
+ 		slq->sl_next = NULL;
+ 
+ 		while (slp->sl_next != NULL)
+ 			slp = slp->sl_next;
+ 		slp->sl_next = slq;
+ 	}
+ 	splx(s);
+ }
+ 
+ void
+ swi_dispatcher(intr)
+ 	int intr;
+ {
+ 	struct swilist *slp = &swilists[intr - NHWI];
+ 
+ 	if (slp->sl_handler == NULL)
+ 		return;
+ 
+ 	do {
+ 		(*slp->sl_handler)();
+ 		slp = slp->sl_next;
+ 	} while (slp != NULL);
+ }
+ 
+ void
+ swi_check(void)
+ {
+ 	if (! oskit_freebsd_ipending)
+ 		return;
+ 
+ 	/*
+ 	 * XXX Just worry about TTY for now.
+ 	 */
+ 	if (oskit_freebsd_ipending & SWI_TTY_PENDING) {
+ 		swi_dispatcher(SWI_TTY);
+ 		oskit_freebsd_ipending &= ~SWI_TTY_PENDING;
+ 	}
+ }
Index: oskit/freebsd/src/sys/i386/include/cpufunc.h
diff -c oskit/freebsd/src/sys/i386/include/cpufunc.h:1.3 oskit/freebsd/src/sys/i386/include/cpufunc.h:1.3.4.1
*** oskit/freebsd/src/sys/i386/include/cpufunc.h:1.3	Sat May 31 11:11:46 1997
--- oskit/freebsd/src/sys/i386/include/cpufunc.h	Thu Dec 31 06:04:21 1998
***************
*** 62,74 ****
--- 62,82 ----
  static __inline void
  disable_intr(void)
  {
+ #ifdef OSKIT
+ 	osenv_intr_disable();
+ #else
  	__asm __volatile("cli" : : : "memory");
+ #endif
  }
  
  static __inline void
  enable_intr(void)
  {
+ #ifdef OSKIT
+ 	osenv_intr_enable();
+ #else
  	__asm __volatile("sti");
+ #endif
  }
  
  #define	HAVE_INLINE_FFS
Index: oskit/freebsd/src/sys/i386/isa/cy.c
diff -c oskit/freebsd/src/sys/i386/isa/cy.c:1.2 oskit/freebsd/src/sys/i386/isa/cy.c:1.2.4.1
*** oskit/freebsd/src/sys/i386/isa/cy.c:1.2	Mon Apr 28 09:45:53 1997
--- oskit/freebsd/src/sys/i386/isa/cy.c	Thu Dec 31 06:15:27 1998
***************
*** 86,91 ****
--- 86,92 ----
  #include <sys/malloc.h>
  #include <sys/syslog.h>
  #include <sys/devconf.h>
+ #include <sys/interrupt.h>
  
  #include <machine/clock.h>
  
***************
*** 589,594 ****
--- 590,596 ----
  
  	s = spltty();
  	com_addr(unit) = com;
+ 	register_swi(SWI_TTY, siopoll);
  	splx(s);
  		}
  	}
Index: oskit/freebsd/src/sys/i386/isa/rc.c
diff -c oskit/freebsd/src/sys/i386/isa/rc.c:1.1 oskit/freebsd/src/sys/i386/isa/rc.c:1.1.6.1
*** oskit/freebsd/src/sys/i386/isa/rc.c:1.1	Wed Apr 23 14:32:33 1997
--- oskit/freebsd/src/sys/i386/isa/rc.c	Thu Dec 31 06:15:27 1998
***************
*** 48,53 ****
--- 48,54 ----
  #include <sys/kernel.h>
  #include <sys/syslog.h>
  #include <sys/devconf.h>
+ #include <sys/interrupt.h>
  
  #include <machine/clock.h>
  
***************
*** 274,279 ****
--- 275,281 ----
  	}
  	rcb->rcb_probed = RC_ATTACHED;
  	if (!rc_wakeup_started) {
+ 		register_swi(SWI_TTY, rcpoll);
  		rc_wakeup((void *)NULL);
  		rc_wakeup_started = 0;
  	}
Index: oskit/freebsd/src/sys/i386/isa/sio.c
diff -c oskit/freebsd/src/sys/i386/isa/sio.c:1.3 oskit/freebsd/src/sys/i386/isa/sio.c:1.3.4.1
*** oskit/freebsd/src/sys/i386/isa/sio.c:1.3	Mon Apr 28 18:23:54 1997
--- oskit/freebsd/src/sys/i386/isa/sio.c	Thu Dec 31 06:15:27 1998
***************
*** 57,62 ****
--- 57,63 ----
  #include <sys/malloc.h>
  #include <sys/syslog.h>
  #include <sys/devconf.h>
+ #include <sys/interrupt.h>
  
  #include <machine/clock.h>
  
***************
*** 621,627 ****
  	termioschars(&com->it_in);
  	com->it_in.c_ispeed = com->it_in.c_ospeed = 
  		((boothowto & RB_FASTCONSOLE) && (unit == comconsole)) ? 
! 		B115200 : comdefaultrate;
  	com->it_out = com->it_in;
  
  	/* attempt to determine UART type */
--- 622,628 ----
  	termioschars(&com->it_in);
  	com->it_in.c_ispeed = com->it_in.c_ospeed = 
  		((boothowto & RB_FASTCONSOLE) && (unit == comconsole)) ? 
! 		B115200 : B115200;
  	com->it_out = com->it_in;
  
  	/* attempt to determine UART type */
***************
*** 745,750 ****
--- 746,752 ----
  
  	s = spltty();
  	com_addr(unit) = com;
+ 	register_swi(SWI_TTY, siopoll);
  	splx(s);
  	return (1);
  }
Index: oskit/freebsd/src/sys/kern/tty.c
diff -c oskit/freebsd/src/sys/kern/tty.c:1.3 oskit/freebsd/src/sys/kern/tty.c:1.3.4.1
*** oskit/freebsd/src/sys/kern/tty.c:1.3	Wed Apr  8 16:44:12 1998
--- oskit/freebsd/src/sys/kern/tty.c	Thu Dec 31 06:25:28 1998
***************
*** 2376,2378 ****
--- 2376,2402 ----
          free(tp, M_TTYS);
  }
  #endif /* 0 */
+ 
+ #ifdef OSKIT
+ #include <oskit/io/asyncio.h>
+ 
+ /*
+  * Well, this is dumb. Need to convert tty state into asyncio flags.
+  */
+ unsigned
+ ttyconds(tp)
+ 	struct tty *tp;
+ {
+ 	unsigned conds = 0;
+ 	
+ 	if (ttnread(tp) > 0 || ISSET(tp->t_state, TS_ZOMBIE))
+                 conds |= OSKIT_ASYNCIO_READABLE;
+ 	
+ 	if ((tp->t_outq.c_cc <= tp->t_lowat &&
+ 	     ISSET(tp->t_state, TS_CONNECTED))
+ 	    || ISSET(tp->t_state, TS_ZOMBIE))
+ 		conds |= OSKIT_ASYNCIO_WRITABLE;
+ 
+ 	return conds;
+ }
+ #endif
Index: oskit/freebsd/src/sys/sys/interrupt.h
diff -c /dev/null oskit/freebsd/src/sys/sys/interrupt.h:1.1.2.1
*** /dev/null	Thu Dec 31 12:00:56 1998
--- oskit/freebsd/src/sys/sys/interrupt.h	Thu Dec 31 09:40:52 1998
***************
*** 0 ****
--- 1,40 ----
+ /*
+  * Copyright (c) 1997-1998 University of Utah and the Flux Group.
+  * All rights reserved.
+  * @OSKIT-FLUX-GPLUS@
+  */
+ /*
+  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+  * All rights reserved.
+  *
+  * Redistribution and use in source and binary forms, with or without
+  * modification, are permitted provided that the following conditions
+  * are met:
+  * 1. Redistributions of source code must retain the above copyright
+  *    notice unmodified, this list of conditions, and the following
+  *    disclaimer.
+  * 2. Redistributions in binary form must reproduce the above copyright
+  *    notice, this list of conditions and the following disclaimer in the
+  *    documentation and/or other materials provided with the distribution.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  * $\Id: interrupt.h,v 1.7 1998/08/11 15:08:13 bde Exp $
+  */
+ 
+ typedef void swihand_t __P((void));
+ 
+ void	register_swi __P((int intr, swihand_t *handler));
+ void	swi_dispatcher __P((int intr));
+ void	swi_check __P((void));
+ void	unregister_swi __P((int intr, swihand_t *handler));
+ 
Index: oskit/oskit/c/fd.h
diff -c oskit/oskit/c/fd.h:1.21 oskit/oskit/c/fd.h:1.21.4.1
*** oskit/oskit/c/fd.h:1.21	Thu May  7 21:07:27 1998
--- oskit/oskit/c/fd.h	Thu Dec 31 06:29:21 1998
***************
*** 104,109 ****
--- 104,114 ----
  void	fd_lock_init(void);
  
  /*
+  * Initialize the fd layer.
+  */
+ void	fd_init(void);
+ 
+ /*
   * Allocate a new file descriptor and return the descriptor number.
   * The descriptor number allocated will be at least min_fd
   * (this is to support F_DUPFD; just pass 0 to allocate any descriptor).
Index: oskit/oskit/com/wrapper.h
diff -c oskit/oskit/com/wrapper.h:1.5 oskit/oskit/com/wrapper.h:1.5.2.1
*** oskit/oskit/com/wrapper.h:1.5	Fri Oct  9 05:29:03 1998
--- oskit/oskit/com/wrapper.h	Thu Dec 31 06:26:15 1998
***************
*** 13,18 ****
--- 13,19 ----
  
  struct oskit_socket;
  struct oskit_stream;
+ struct oskit_ttystream;
  struct oskit_asyncio;
  struct oskit_posixio;
  struct oskit_file;
***************
*** 42,47 ****
--- 43,55 ----
          void (*after)(void *),
  	void *cookie,
          struct oskit_stream **out);
+ 
+ oskit_error_t
+ oskit_wrap_ttystream(struct oskit_ttystream *in,
+         void (*before)(void *),
+         void (*after)(void *),
+ 	void *cookie,
+         struct oskit_ttystream **out);
  
  oskit_error_t
  oskit_wrap_asyncio(struct oskit_asyncio *in,
Index: oskit/oskit/io/ttystream.h
diff -c oskit/oskit/io/ttystream.h:1.18 oskit/oskit/io/ttystream.h:1.18.2.1
*** oskit/oskit/io/ttystream.h:1.18	Wed Nov  4 18:07:48 1998
--- oskit/oskit/io/ttystream.h	Thu Dec 31 06:28:19 1998
***************
*** 149,155 ****
  	OSKIT_COMDECL	(*seek)(oskit_ttystream_t *s, oskit_s64_t ofs,
  				oskit_seek_t whence, oskit_u64_t *out_newpos);
  	OSKIT_COMDECL	(*setsize)(oskit_ttystream_t *s, oskit_u64_t new_size);
! 	OSKIT_COMDECL	(*copyto)(oskit_ttystream_t *s, oskit_stream_t *dst,
  				  oskit_u64_t size,
  				   oskit_u64_t *out_read,
  				   oskit_u64_t *out_written);
--- 149,155 ----
  	OSKIT_COMDECL	(*seek)(oskit_ttystream_t *s, oskit_s64_t ofs,
  				oskit_seek_t whence, oskit_u64_t *out_newpos);
  	OSKIT_COMDECL	(*setsize)(oskit_ttystream_t *s, oskit_u64_t new_size);
! 	OSKIT_COMDECL	(*copyto)(oskit_ttystream_t *s, oskit_ttystream_t *dst,
  				  oskit_u64_t size,
  				   oskit_u64_t *out_read,
  				   oskit_u64_t *out_written);


Follow-Ups: