[Prev][Next][Index][Thread]
Re: gnumach2 & the serial port
Roland McGrath <roland@frob.com> writes:
> Nice work! Can you show the code and say something about the problems and
> hacks you had to do?
Sure (I was hopping to conceal my cruel hacks :) I modified the oskit
sio driver so that only ttyS1 is initialised and ttyS0 left alone so
that remote debugging is still possible. The only real problem
was finding out why the base_irq_handler from oskit was called and not the
gnumach interrupt handler. Walking back through the IDT solved this
problem. In gnumach/i386/i386at/int_init.c the IDT entry for INT 3
got a special treatment. I had to disable that part, but I don't if
that was a bad idea. Doesn't seem so far.
With a small test program which opens the @isa@0x02f8 device and writes a
string I was able to see that it works somewhat. Of course on the
other end of the wire I got something scrambled but still a sign of
live. Most likely that the settings of the device are wrong.
> The main nonobvious thing we need is an interface for being notified on
> modem status changes. A simple thing is just to support asyncio and report
> "exceptional conditions" on a modem status change. So the caller wakes up
> and calls read_modem_control or whatever it is to see what's happened.
> Another idea is to structure it so that state transitions are never lost.
> i.e., each change in the modem control bits is a event that is queued like
> a byte of input. I haven't decided whether it seems important to have an
> interface that won't drop past states if there are multiple state changes
> before the caller gets around to polling after a notification.
Looking at the asyncio interface the first thing would be covered
'naturally' by it. It depends if dropping state changes is important
or not. I try to figure it out by looking how other system handle it.
> Another question is synchronization of status changes with input. I've
> [...]
> or, having stream_read block (return EAGAIN or another error for this case)
> until you've polled for status information.
This sounds more easier to implement. If it is no problem I would
rather do this one :)
According to your tips I will give it another try for the
oskit_serialstream_t interface.
thanks again for your explanations,
daniel
diff -ru ../gnumach/Makefile.in ./Makefile.in
--- ../gnumach/Makefile.in 2003-01-29 23:46:54.000000000 +0100
+++ ./Makefile.in 2003-02-08 13:13:50.000000000 +0100
@@ -135,7 +135,8 @@
ds_mem.c ds_bus.c \
ds_net.c \
ds_stream.c \
- ds_asyncio.c smp-glue.c
+ ds_asyncio.c smp-glue.c \
+ ds_serial.c
oskit-files = $(oskit-cfiles) ds_oskit.h
oskit-dirs-alpha := alpha pc
@@ -275,7 +276,7 @@
OSKIT_LIBDIR = @OSKIT_LIBDIR@
OSKIT_LIBS = -loskit_kern -loskit_lmm -loskit_com @SMP_LIBS@ \
-loskit_exec -loskit_unsupp \
- -loskit_dev -loskit_linux_dev \
+ -loskit_dev -loskit_linux_dev -loskit_freebsd_dev \
-loskit_diskpart
# These rules are useful for development, but have significant overhead.
diff -ru ../gnumach/i386/i386at/int_init.c ./i386/i386at/int_init.c
--- ../gnumach/i386/i386at/int_init.c 2002-11-08 17:29:34.000000000 +0100
+++ ./i386/i386at/int_init.c 2003-03-05 11:06:20.000000000 +0100
@@ -36,12 +36,12 @@
int i;
for (i = 0; i < 16; i++) {
- int com_irq = 3; /* XXX */
- if (i == com_irq) {
- intpri[i] == SPLDEBUG;
- form_pic_mask();
- }
- else
+/* int com_irq = 3; /\* XXX *\/ */
+/* if (i == com_irq) { */
+/* intpri[i] == SPLDEBUG; */
+/* form_pic_mask(); */
+/* } */
+/* else */
fill_irq_gate(i,
int_entry_table[i], KERNEL_CS,
ACC_PL_K|ACC_INTR_GATE);
diff -ru ../gnumach/oskit/ds_osenv.c ./oskit/ds_osenv.c
--- ../gnumach/oskit/ds_osenv.c 2002-11-09 23:28:04.000000000 +0100
+++ ./oskit/ds_osenv.c 2003-03-05 21:53:02.000000000 +0100
@@ -62,6 +62,7 @@
panic ("cannot create interrupt-driven console stream: %x\n", rc);
oskit_linux_init_osenv (mach_osenv);
+ oskit_freebsd_init_osenv (mach_osenv);
oskit_linux_init_devs ();
+ oskit_freebsd_init_sio ();
}
diff -ru ../gnumach/oskit/ds_oskit.h ./oskit/ds_oskit.h
--- ../gnumach/oskit/ds_oskit.h 2002-11-08 17:29:34.000000000 +0100
+++ ./oskit/ds_oskit.h 2003-02-09 18:37:32.000000000 +0100
@@ -52,6 +52,8 @@
#include <oskit/diskpart/diskpart.h>
#include <oskit/com/stream.h>
#include <oskit/io/asyncio.h>
+#include <oskit/io/ttystream.h>
+#include <oskit/dev/tty.h>
#include <oskit/dev/net.h>
#include <oskit/io/netio.h>
#if defined(__i386__)
@@ -90,6 +92,8 @@
struct {
oskit_stream_t *io;
oskit_asyncio_t *aio;
+ oskit_ttydev_t *td;
+ oskit_ttystream_t *si;
oskit_s32_t listening; /* OSKIT_ASYNCIO_* */
queue_head_t read_queue, write_queue; /* queued requests */
queue_chain_t ready_queue; /* when on device_ready_queue */
@@ -141,6 +145,7 @@
extern const struct device_ops net_device_ops;
extern const struct device_ops mem_device_ops;
extern const struct device_ops bus_device_ops;
+extern const struct device_ops ttystream_device_ops;
extern oskit_error_t ds_netdev_open (device_t dev, oskit_netdev_t *netdev);
diff -ru ../gnumach/oskit/ds_routines.c ./oskit/ds_routines.c
--- ../gnumach/oskit/ds_routines.c 2002-12-11 23:01:58.000000000 +0100
+++ ./oskit/ds_routines.c 2003-03-05 11:14:06.000000000 +0100
@@ -52,10 +52,12 @@
#ifdef HAVE_OSKIT_DEV_STREAM_H
# include <oskit/dev/stream.h>
#endif
+#include <oskit/dev/tty.h>
#include <oskit/dev/net.h>
#include <oskit/dev/linux.h>
#include <oskit/com/stream.h>
#include <oskit/c/stdlib.h>
+#include <oskit/fs/file.h> /* XXX OSKIT_O_RDONLY, OSKIT_O_WRONLY */
#include <oskit/machine/pc/direct_cons.h> /* XXX direct_cons_set_flags */
@@ -441,6 +443,16 @@
if ((void *) com_device == kmsg_stream && (mode & D_READ))
++kmsg_readers;
}
+ else if (oskit_device_query (com_device, &oskit_ttydev_iid,
+ (void **) &dev->com.stream.td) == 0)
+ {
+ ops = &ttystream_device_ops;
+ rc = oskit_ttydev_open (dev->com.stream.td,
+ ((mode & D_READ) ? OSKIT_O_RDONLY : 0) |
+ ((mode & D_WRITE) ? OSKIT_O_WRONLY : 0),
+ &dev->com.stream.si);
+ oskit_ttydev_release (dev->com.stream.td);
+ }
else if (oskit_device_query (com_device, &oskit_bus_iid,
(void **) &bus) == 0)
{
--- /dev/null 2003-02-13 09:27:53.000000000 +0100
+++ oskit/ds_serial.c 2003-03-05 21:46:26.000000000 +0100
@@ -0,0 +1,81 @@
+#include "ds_oskit.h"
+
+#include <oskit/io/ttystream.h>
+
+/* Straight forward implementation. I'm not sure if this implementation
+ handles all needed cases. Are there any message larger then we can
+ handle? (e.g. ds_blkio_write_inband) */
+io_return_t
+ds_ttystream_write_inband (device_t dev, ipc_port_t reply_port,
+ mach_msg_type_name_t reply_port_type,
+ dev_mode_t mode, recnum_t recnum,
+ io_buf_ptr_t data, unsigned int count,
+ int *bytes_written)
+{
+ oskit_error_t rc;
+ oskit_u32_t wrote;
+
+ rc = oskit_ttystream_write (dev->com.stream.si, data, count, &wrote);
+
+ if (rc)
+ return oskit_to_mach_error (rc);
+
+ if (wrote == count)
+ {
+ *bytes_written = wrote;
+ return D_SUCCESS;
+ }
+
+ return D_IO_ERROR; /* XXX maybe the wrong error code */
+}
+
+
+io_return_t
+ds_ttystream_read_inband (device_t dev, ipc_port_t reply_port,
+ mach_msg_type_name_t reply_port_type,
+ dev_mode_t mode, recnum_t recnum, int count,
+ char *data, unsigned *bytes_read)
+{
+ oskit_error_t rc;
+
+ if (count == 0)
+ {
+ *bytes_read = 0;
+ return D_SUCCESS;
+ }
+
+ rc = oskit_ttystream_read (dev->com.stream.si, data, count, bytes_read);
+ return oskit_to_mach_error (rc);
+}
+
+
+io_return_t
+ds_ttystream_set_status (device_t dev, dev_flavor_t flavor,
+ dev_status_t status,
+ mach_msg_type_number_t status_count)
+{
+ oskit_error_t rc;
+
+ INVALOP;
+}
+
+
+io_return_t
+ds_ttystream_get_status (device_t dev, dev_flavor_t flavor,
+ dev_status_t status,
+ mach_msg_type_number_t *status_count)
+{
+ oskit_error_t rc;
+
+ INVALOP;
+}
+
+
+const struct device_ops ttystream_device_ops =
+{
+ write_inband: ds_ttystream_write_inband,
+ read_inband: ds_ttystream_read_inband,
+ set_status: ds_ttystream_set_status,
+ get_status: ds_ttystream_get_status,
+ /* XXX close ?!? */
+};
References: