[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[openrisc] [PATCH] Would you like to have UART0 in a xterm ?
Hello everybody !
Here is a patch to improve simulator interraction with host.
Interraction is made through "channels". It is possible to associate
a channel with a peripheral (only UART for the momment). It obseletes
txfile and rxfile (UART only for now). Sorry to break compatibility :-(
Did I tell you it is for UART only for now ?!
sim.cfg have to change in the following way :
section uart
enabled = 1
nuarts = 1
device 0
baseaddr = 0x90000000
irq = 2
jitter = -1
16550 = 1
/*
* txfile = "oldway.tx"
* rxfile = "oldway.rx"
*/
channel = "file:newway.rx,newway.tx"
enddevice
end
One thing I like to do is:
section uart
enabled = 1
nuarts = 1
device 0
baseaddr = 0x90000000
irq = 2
jitter = -1
16550 = 1
channel = "file:/dev/tty10"
enddevice
end
But make sure the user running the simulation have the appropriate
permission on /dev/tty10. (Do Ctrl-Atl-F10 to see result and enjoy!)
Two other kind of channels are also available. The first one use file
descriptors provided at sim startup. To configure do:
section uart
enabled = 1
nuarts = 1
device 0
baseaddr = 0x90000000
irq = 2
jitter = -1
16550 = 1
channel = "fd:3,4"
enddevice
end
And launch sim this way:
$ or32-uclinux-sim linux 3< uart.rx 4> uart.tx
It is also possible to specify a fifo instead:
section uart
enabled = 1
nuarts = 1
device 0
baseaddr = 0x90000000
irq = 2
jitter = -1
16550 = 1
channel = "fd:3"
enddevice
end
Launch with:
$ mkfifo allo
$ or32-uclinux-sim linux 3<> allo
But the most useful one is with:
section uart
enabled = 1
nuarts = 1
device 0
baseaddr = 0x90000000
irq = 2
jitter = -1
16550 = 1
channel = "xterm"
enddevice
end
Enjoy!
Richard Prescott
diff -urN -X dontdiff or1ksim/BUGS or1ksim.richard/BUGS
--- or1ksim/BUGS Thu Oct 24 11:56:11 2002
+++ or1ksim.richard/BUGS Fri Aug 2 07:25:31 2002
@@ -13,4 +13,4 @@
* cuc is under heavy development and is not stable yet!!!
* cuc: entering cuc, leaving it and re-entering causes to double profiling information
-* channels/xterm: xterm get closed when 'Ctrl-C'ing the master console
+
diff -urN -X dontdiff or1ksim/Makefile.am or1ksim.richard/Makefile.am
--- or1ksim/Makefile.am Thu Jul 4 12:35:42 2002
+++ or1ksim.richard/Makefile.am Tue Oct 22 16:16:05 2002
@@ -14,6 +14,6 @@
cpu/or1k/libor1k.a support/libsupport.a mmu/libmmu.a \
bpb/libbpb.a cache/libcache.a peripheral/libperipheral.a \
tick/libtick.a pm/libpm.a pic/libpic.a debug/libdebug.a \
- vapi/libvapi.a cuc/libcuc.a
+ vapi/libvapi.a cuc/libcuc.a peripheral/channels/libchannels.a
sim_LDFLAGS = #-lreadline
diff -urN -X dontdiff or1ksim/configure.in or1ksim.richard/configure.in
--- or1ksim/configure.in Tue Jul 30 04:26:59 2002
+++ or1ksim.richard/configure.in Tue Oct 22 15:57:14 2002
@@ -219,6 +219,7 @@
INCLUDES="-I\${top_srcdir} -I\${top_srcdir}/cpu/common -I\${top_srcdir}/cpu/or1k \
-I\${top_srcdir}/cpu/$CPU_ARCH -I\${top_srcdir}/cache -I\${top_srcdir}/mmu \
-I\${top_srcdir}/bpb -I\${top_srcdir}/peripheral -I\${top_srcdir}/tick \
+-I\${top_srcdir}/peripheral/channels \
-I\${top_srcdir}/pm -I\${top_srcdir}/pic -I\${top_srcdir}/debug \
-I\${top_srcdir}/vapi -I\${top_srcdir}/support -I\${top_srcdir}/cuc"
AC_SUBST(INCLUDES)
@@ -226,8 +227,8 @@
AC_OUTPUT([Makefile bpb/Makefile cache/Makefile cpu/Makefile
cpu/common/Makefile cpu/or32/Makefile cuc/Makefile
cpu/or1k/Makefile cpu/dlx/Makefile debug/Makefile
- support/Makefile mmu/Makefile peripheral/Makefile tick/Makefile
- pm/Makefile pic/Makefile debug/Makefile vapi/Makefile],
+ support/Makefile mmu/Makefile peripheral/Makefile peripheral/channels/Makefile
+ tick/Makefile pm/Makefile pic/Makefile debug/Makefile vapi/Makefile],
[
# Makefile uses this timestamp file to record whether config.h is up to date.
echo > stamp-h
diff -urN -X dontdiff or1ksim/peripheral/16450.c or1ksim.richard/peripheral/16450.c
--- or1ksim/peripheral/16450.c Fri Aug 23 04:40:14 2002
+++ or1ksim.richard/peripheral/16450.c Tue Oct 22 19:50:51 2002
@@ -37,10 +37,12 @@
#include "pic.h"
#include "vapi.h"
#include "sched.h"
+#include "channel.h"
#define MIN(a,b) ((a) < (b) ? (a) : (b))
-static struct dev_16450 uarts[MAX_UARTS];
+static struct dev_16450 uarts[MAX_UARTS]; /* simulation info */
+static struct channel * channels[MAX_UARTS] = { NULL, }; /* emulation info */
static int thre_int;
/* Number of clock cycles (one clock cycle is one call to the uart_clock())
@@ -308,8 +310,8 @@
debug (4, "vapi_send (%08x, %08x)\n", config.uarts[uart].vapi_id, data);
vapi_send (config.uarts[uart].vapi_id, data);
} else {
- fputc((int)(uarts[uart].iregs.txser & 0xFF), uarts[uart].txfs);
- fflush(uarts[uart].txfs);
+ char buffer[1] = { uarts[uart].iregs.txser & 0xFF };
+ channel_write(channels[uart], buffer, 1);
}
}
uarts[uart].istat.txser_full = 0;
@@ -337,14 +339,14 @@
void uart_clock16 (int i)
{
int retval;
-
+
/* Schedule for later */
SCHED_ADD (uart_clock16, i, runtime.sim.cycles + UART_CLOCK_DIVIDER);
/* If VAPI is not selected, UART communicates with two file streams;
if VAPI is selected, we use VAPI streams. */
/* if txfs is corrupted, skip this uart. */
- if (!config.uarts[i].vapi_id && !uarts[i].txfs) return;
+ if (!config.uarts[i].vapi_id && !channel_ok(channels[i])) return;
if (uarts[i].vapi.next_break_cnt >= 0)
if (--uarts[i].vapi.next_break_cnt < 0) {
@@ -433,10 +435,17 @@
if(uarts[i].istat.rxser_full == 0) {
if (uarts[i].slowdown)
uarts[i].slowdown--;
- else if((retval = fgetc(uarts[i].rxfs)) != EOF) {
- uarts[i].iregs.rxser = (char)retval;
- uarts[i].istat.rxser_full = 1;
- } else uarts[i].slowdown = UART_FGETC_SLOWDOWN;
+ else {
+ char buffer[1];
+ retval = channel_read(channels[i], buffer, 1);
+ if(retval < 0)
+ perror(config.uarts[i].channel);
+ else if(retval > 0) {
+ uarts[i].iregs.rxser = buffer[0];
+ uarts[i].istat.rxser_full = 1;
+ } else
+ uarts[i].slowdown = UART_FGETC_SLOWDOWN;
+ }
}
} else { /* VAPI */
int received = 0;
@@ -563,24 +572,25 @@
if ((config.uarts[i].vapi_id & VAPI_DEVICE_ID) != i) {
fprintf (stderr, "ERROR: Wrong vapi_id (0x%x) for uart %i, last byte is required to be %02x; ignoring.\n", config.uarts[i].vapi_id, i, i);
config.uarts[i].vapi_id = 0;
- uarts[i].txfs = 0;
} else {
vapi_install_handler (config.uarts[i].vapi_id, uart_vapi_read);
register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
}
- } else if (config.uarts[i].txfile) { /* MM: Try to create stream. */
- if (!(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r"))
- && !(uarts[i].rxfs = fopen(config.uarts[i].rxfile, "r+"))) {
- debug (0, "WARNING: UART%d has problems with RX file stream.\n", i);
+ } else if (config.uarts[i].channel[0]) { /* MM: Try to create stream. */
+ if(channels[i])
+ channel_close(channels[i]);
+ else
+ channels[i] = channel_init(config.uarts[i].channel);
+ if(channel_open(channels[i]) < 0) {
+ debug (0, "WARNING: UART%d has problems with channel \"%s\".\n", i, config.uarts[i].channel);
continue;
}
- uarts[i].txfs = fopen(config.uarts[i].txfile, "a");
- if (uarts[i].rxfs && uarts[i].txfs && config.sim.verbose) {
+ if (config.sim.verbose)
PRINTF("UART%d at 0x%.8x uses ", i, config.uarts[i].baseaddr);
- PRINTF("%s for RX and %s for TX.\n", config.uarts[i].rxfile, config.uarts[i].txfile);
- } else
- debug (1, "WARNING: UART%d has problems with TX file stream.\n", i);
register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte);
+ } else {
+ debug (0, "WARNING: UART%d has no vapi nor channel specified\n", i);
+ continue;
}
if (config.uarts[i].uart16550)
@@ -634,7 +644,9 @@
PRINTF("Using IRQ%i\n", config.uarts[i].irq);
if (config.uarts[i].vapi_id)
PRINTF ("Connected to vapi ID=%x\n\n", config.uarts[i].vapi_id);
+ /* TODO: replace by a channel_status
else
PRINTF("RX fs: %p TX fs: %p\n\n", uarts[i].rxfs, uarts[i].txfs);
+ */
}
}
diff -urN -X dontdiff or1ksim/peripheral/16450.h or1ksim.richard/peripheral/16450.h
--- or1ksim/peripheral/16450.h Wed Apr 10 03:40:31 2002
+++ or1ksim.richard/peripheral/16450.h Tue Oct 22 16:40:27 2002
@@ -95,10 +95,6 @@
/* fgetc slowdown */
int slowdown;
-
- /* Required by standard file streams */
- FILE * rxfs;
- FILE * txfs;
};
/*
diff -urN -X dontdiff or1ksim/peripheral/Makefile.am or1ksim.richard/peripheral/Makefile.am
--- or1ksim/peripheral/Makefile.am Thu Aug 15 17:38:23 2002
+++ or1ksim.richard/peripheral/Makefile.am Tue Oct 22 11:41:26 2002
@@ -18,6 +18,8 @@
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
+SUBDIRS = channels
+
noinst_LIBRARIES = libperipheral.a
libperipheral_a_SOURCES = \
16450.c \
diff -urN -X dontdiff or1ksim/peripheral/channels/Makefile.am or1ksim.richard/peripheral/channels/Makefile.am
--- or1ksim/peripheral/channels/Makefile.am Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/Makefile.am Thu Oct 24 10:34:26 2002
@@ -0,0 +1,27 @@
+# Makefile -- Makefile for peripherals channels to host
+# Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+#
+# This file is part of OpenRISC 1000 Architectural Simulator.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+noinst_LIBRARIES = libchannels.a
+libchannels_a_SOURCES = \
+channel.c \
+fd.c \
+file.c \
+generic.c \
+xterm.c
diff -urN -X dontdiff or1ksim/peripheral/channels/channel.c or1ksim.richard/peripheral/channels/channel.c
--- or1ksim/peripheral/channels/channel.c Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/channel.c Thu Oct 24 10:21:30 2002
@@ -0,0 +1,243 @@
+/* channel.h -- Definition of types and structures for
+ peripheral to communicate with host. Addapted from UML.
+
+ Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define _GNU_SOURCE /* for strndup */
+
+#include <stdio.h> /* perror */
+#include <stdlib.h> /* exit */
+#include <malloc.h> /* calloc, free */
+#include <string.h> /* strndup, strcmp, strlen, strchr */
+#include <errno.h> /* errno */
+
+#include "channel.h"
+
+struct channel_factory
+{
+ const char * name;
+ const struct channel_ops * ops;
+ struct channel_factory * next;
+};
+
+extern struct channel_ops fd_channel_ops, file_channel_ops, xterm_channel_ops;
+
+static struct channel_factory preloaded[] =
+{
+ { "fd", &fd_channel_ops, &preloaded[1] },
+ { "file", &file_channel_ops, &preloaded[2] },
+ { "xterm", &xterm_channel_ops, NULL }
+};
+
+static struct channel_factory * head = &preloaded[0];
+
+static struct channel_factory * find_channel_factory(const char * name);
+
+struct channel * channel_init(const char * descriptor)
+{
+ struct channel * retval;
+ struct channel_factory * current;
+ char * args, * name;
+ int count;
+
+ if(!descriptor)
+ {
+ return NULL;
+ }
+
+ retval = (struct channel*)calloc(1, sizeof(struct channel));
+
+ if(!retval)
+ {
+ perror(descriptor);
+ exit(1);
+ }
+
+ args = strchr(descriptor, ':');
+
+ if(args)
+ {
+ count = args - descriptor;
+ args++;
+ }
+ else
+ {
+ count = strlen(descriptor);
+ }
+
+ name = (char*)strndup(descriptor, count);
+
+ if(!name)
+ {
+ perror(name);
+ exit(1);
+ }
+
+ current = find_channel_factory(name);
+
+ if(!current)
+ {
+ errno = ENODEV;
+ perror(descriptor);
+ exit(1);
+ }
+
+ retval->ops = current->ops;
+
+ free(name);
+
+ if(!retval->ops)
+ {
+ errno = ENODEV;
+ perror(descriptor);
+ exit(1);
+ }
+
+ if(retval->ops->init)
+ {
+ retval->data = (retval->ops->init)(args);
+
+ if(!retval->data)
+ {
+ perror(descriptor);
+ exit(1);
+ }
+ }
+
+ return retval;
+}
+
+int channel_open(struct channel * channel)
+{
+ if(channel && channel->ops && channel->ops->open)
+ {
+ return (channel->ops->open)(channel->data);
+ }
+ errno = ENOSYS;
+ return -1;
+}
+
+int channel_read(struct channel * channel, char * buffer, int size)
+{
+ if(channel && channel->ops && channel->ops->read)
+ {
+ return (channel->ops->read)(channel->data, buffer, size);
+ }
+ errno = ENOSYS;
+ return -1;
+}
+
+int channel_write(struct channel * channel, const char * buffer, int size)
+{
+ if(channel && channel->ops && channel->ops->write)
+ {
+ return (channel->ops->write)(channel->data, buffer, size);
+ }
+ errno = ENOSYS;
+ return -1;
+}
+
+void channel_close(struct channel * channel)
+{
+ if(channel && channel->ops && channel->ops->close)
+ {
+ (channel->ops->close)(channel->data);
+ }
+}
+
+void channel_free(struct channel * channel)
+{
+ if(channel && channel->ops && channel->ops->close)
+ {
+ (channel->ops->free)(channel->data);
+ free(channel);
+ }
+}
+
+
+int channel_ok(struct channel * channel)
+{
+ if(channel && channel->ops)
+ {
+ if(channel->ops->isok)
+ return (channel->ops->isok)(channel->data);
+ else
+ return 1;
+ }
+ return 0;
+}
+
+char * channel_status(struct channel * channel)
+{
+ if(channel && channel->ops && channel->ops->status)
+ {
+ return (channel->ops->status)(channel->data);
+ }
+ return "";
+}
+
+
+
+static struct channel_factory * find_channel_factory(const char * name)
+{
+ struct channel_factory * current = head;
+
+ current = head;
+ while(current && strcmp(current->name, name))
+ {
+ current = current->next;
+ }
+
+ return current;
+}
+
+int register_channel(const char * name, const struct channel_ops * ops)
+{
+ struct channel_factory * new;
+
+
+ if(find_channel_factory(name))
+ {
+ errno = EEXIST;
+ perror(name);
+ exit(1);
+ }
+
+ new = (struct channel_factory *)calloc(1, sizeof(struct channel_factory));
+
+ if(!new)
+ {
+ perror(name);
+ exit(1);
+ }
+
+ new->name = name;
+ new->ops = ops;
+ new->next = head;
+ head = new;
+
+ return (int)new; /* dummy */
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
+
diff -urN -X dontdiff or1ksim/peripheral/channels/channel.h or1ksim.richard/peripheral/channels/channel.h
--- or1ksim/peripheral/channels/channel.h Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/channel.h Tue Oct 22 17:13:10 2002
@@ -0,0 +1,68 @@
+/* channel.h -- Definition of types and structures for
+ peripheral to communicate with host. Addapted from UML.
+
+ Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef CHANNEL_H
+#define CHANNEL_H
+
+struct channel_ops
+{
+ void *(*init)(const char *);
+ int (*open)(void *);
+ void (*close)(void *);
+ int (*read)(void *, char *, int);
+ int (*write)(void *, const char *, int);
+ void (*free)(void *);
+ int (*isok)(void*);
+ char* (*status)(void*);
+};
+
+struct channel
+{
+ const struct channel_ops * ops;
+ void * data;
+};
+
+
+struct channel * channel_init(const char * descriptor);
+/* read operation in non-blocking */
+int channel_open(struct channel * channel);
+int channel_read(struct channel * channel, char * buffer, int size);
+int channel_write(struct channel * channel, const char * buffer, int size);
+void channel_free(struct channel * channel);
+int channel_ok(struct channel * channel);
+char * channel_status(struct channel * channel);
+
+void channel_close(struct channel * channel);
+
+int register_channel(const char * name, const struct channel_ops * ops);
+/* TODO: int unregister_channel(const char * name); */
+
+/* for those who wants to automatically register at startup */
+#define REGISTER_CHANNEL(NAME,OPS) \
+ static int NAME ## _dummy_register = register_channel(#NAME, OPS)
+
+#endif
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -urN -X dontdiff or1ksim/peripheral/channels/fd.c or1ksim.richard/peripheral/channels/fd.c
--- or1ksim/peripheral/channels/fd.c Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/fd.c Thu Oct 24 11:47:12 2002
@@ -0,0 +1,154 @@
+/* fd.c -- Definition of functions and structures for
+ peripheral to communicate with host through file descriptors
+
+ Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <sys/time.h> /* struct timeval */
+#include <sys/types.h> /* fd_set */
+#include <stdio.h> /* perror */
+#include <stdlib.h> /* atoi */
+#include <unistd.h> /* read, write, select */
+#include <malloc.h> /* calloc, free */
+#include <string.h> /* strchr */
+#include <errno.h> /* errno */
+
+#include "channel.h"
+#include "generic.h"
+#include "fd.h"
+
+static void * fd_init(const char * args)
+{
+ struct fd_channel * retval;
+
+ retval = (struct fd_channel*)calloc(1, sizeof(struct fd_channel));
+
+ if(!retval)
+ {
+ return NULL;
+ }
+
+
+ retval->fdin = atoi(args); /* so 0 if garbage */
+ /* TODO: strtoul */
+
+ args = strchr(args, ',');
+
+ if(args)
+ {
+ retval->fdout = atoi(args+1);
+ }
+ else
+ {
+ retval->fdout = retval->fdin;
+ }
+
+ return (void*)retval;
+}
+
+int fd_read(void * data, char * buffer, int size)
+{
+ struct fd_channel * fds = (struct fd_channel *)data;
+ struct timeval timeout = { 0, 0 };
+ fd_set rfds;
+ int retval;
+
+ if(!fds)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+ FD_ZERO(&rfds);
+ FD_SET(fds->fdin, &rfds);
+
+ retval = select(fds->fdin+1, &rfds, NULL, NULL, &timeout);
+
+ if(retval <= 0)
+ return retval;
+
+ return read(fds->fdin, buffer, size);
+}
+
+int fd_write(void * data, const char * buffer, int size)
+{
+ struct fd_channel * fds = (struct fd_channel *)data;
+ if(fds)
+ {
+ return write(fds->fdout, buffer, size);
+ }
+ errno = ENODEV;
+ return -1;
+}
+
+static int fd_isok(void * data)
+{
+ struct fd_channel * fds = (struct fd_channel *)data;
+ if(fds)
+ {
+ return fds->fdout != -1 && fds->fdin != -1;
+ }
+ return 0;
+}
+
+static int fd_status_fd(int fd, char * str, int size)
+{
+ if(fd == -1)
+ return snprintf(str, size, "closed");
+
+ return snprintf(str, size, "opened(fd=%d)", fd);
+}
+
+char * fd_status(void * data)
+{
+ static char retval[256];
+ int index = 0;
+
+ struct fd_channel * fds = (struct fd_channel *)data;
+ if(fds)
+ {
+ index += snprintf(retval + index, sizeof(retval) - index, "in ");
+ index += fd_status_fd(fds->fdin, retval + index, sizeof(retval) - index);
+
+ index += snprintf(retval + index, sizeof(retval) - index, "out ");
+ index += fd_status_fd(fds->fdout, retval + index, sizeof(retval) - index);
+ }
+ else
+ {
+ snprintf(retval, sizeof(retval), "(null)");
+ }
+ return retval;
+}
+
+struct channel_ops fd_channel_ops =
+{
+ init: fd_init,
+ open: generic_open,
+ close: generic_close,
+ read: fd_read,
+ write: fd_write,
+ free: generic_free,
+ isok: fd_isok,
+ status: fd_status,
+};
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -urN -X dontdiff or1ksim/peripheral/channels/fd.h or1ksim.richard/peripheral/channels/fd.h
--- or1ksim/peripheral/channels/fd.h Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/fd.h Tue Oct 22 15:27:30 2002
@@ -0,0 +1,34 @@
+/* generic.h -- Declaration of generic functions for peripheral to
+ * communicate with host
+
+ Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef FD_H
+#define FD_H
+
+struct fd_channel
+{
+ int fdin;
+ int fdout;
+};
+
+int fd_read(void * data, char * buffer, int size);
+int fd_write(void * data, const char * buffer, int size);
+
+#endif
diff -urN -X dontdiff or1ksim/peripheral/channels/file.c or1ksim.richard/peripheral/channels/file.c
--- or1ksim/peripheral/channels/file.c Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/file.c Thu Oct 24 11:46:14 2002
@@ -0,0 +1,156 @@
+/* file.c -- Definition of functions and structures for
+ peripheral to communicate with host through files
+
+ Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#define _GNU_SOURCE /* for strndup */
+
+#include <sys/types.h> /* open() */
+#include <sys/stat.h> /* open() */
+#include <fcntl.h> /* open() */
+#include <malloc.h> /* calloc(), free() */
+#include <string.h> /* strndup(), strchr() */
+#include <errno.h> /* errno */
+#include <unistd.h> /* close() */
+
+#include "channel.h" /* struct channel_ops */
+#include "fd.h" /* struct fd_channel, fd_read(), fd_write() */
+
+struct file_channel
+{
+ struct fd_channel fds;
+ char * namein;
+ char * nameout;
+};
+
+static void * file_init(const char * args)
+{
+ struct file_channel * retval;
+ char * nameout;
+
+ if(!args)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ retval = (struct file_channel*)calloc(1, sizeof(struct file_channel));
+
+ if(!retval)
+ {
+ return NULL;
+ }
+
+ retval->fds.fdin = -1;
+ retval->fds.fdout = -1;
+
+ nameout = strchr(args, ',');
+
+ if(nameout)
+ {
+ retval->namein = strndup(args, nameout - args);
+ retval->nameout = strdup(nameout+1);
+ }
+ else
+ {
+ retval->nameout = retval->namein = strdup(args);
+ }
+
+ return (void*)retval;
+}
+
+static int file_open(void * data)
+{
+ struct file_channel * files = (struct file_channel *)data;
+
+ if(!files)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+ if(files->namein == files->nameout)
+ {
+ /* if we have the same name in and out
+ * it cannot (logically) be a regular files.
+ * so we wont create one
+ */
+ files->fds.fdin = files->fds.fdout = open(files->namein, O_RDWR);
+
+ return files->fds.fdin < 0 ? -1 : 0;
+ }
+
+
+ files->fds.fdin = open(files->namein, O_RDONLY | O_CREAT, 0664);
+
+ if(files->fds.fdin < 0)
+ return -1;
+
+ files->fds.fdout = open(files->nameout, O_WRONLY | O_CREAT, 0664);
+
+ if(files->fds.fdout < 0)
+ {
+ close(files->fds.fdout);
+ files->fds.fdout = -1;
+ return -1;
+ }
+
+ return 0;
+}
+
+static void file_close(void * data)
+{
+ struct file_channel * files = (struct file_channel *)data;
+
+ if(files->fds.fdin != files->fds.fdout)
+ close(files->fds.fdin);
+
+ close(files->fds.fdout);
+
+ files->fds.fdin = -1;
+ files->fds.fdout = -1;
+}
+
+static void file_free(void * data)
+{
+ struct file_channel * files = (struct file_channel *)data;
+
+ if(files->namein != files->nameout)
+ free(files->namein);
+
+ free(files->nameout);
+
+ free(files);
+}
+
+struct channel_ops file_channel_ops =
+{
+ init: file_init,
+ open: file_open,
+ close: file_close,
+ read: fd_read,
+ write: fd_write,
+ free: file_free,
+};
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -urN -X dontdiff or1ksim/peripheral/channels/generic.c or1ksim.richard/peripheral/channels/generic.c
--- or1ksim/peripheral/channels/generic.c Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/generic.c Tue Oct 22 14:10:28 2002
@@ -0,0 +1,54 @@
+/* generic.c -- Definition of generic functions for peripheral to
+ * communicate with host
+
+ Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <malloc.h> /* free */
+#include <errno.h> /* errno */
+
+
+int generic_open(void * data)
+{
+ if(data)
+ {
+ return 0;
+ }
+ errno = ENODEV;
+ return -1;
+}
+
+void generic_close(void * data)
+{
+ return;
+}
+
+void generic_free(void * data)
+{
+ if(data)
+ {
+ free(data);
+ }
+}
+
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -urN -X dontdiff or1ksim/peripheral/channels/generic.h or1ksim.richard/peripheral/channels/generic.h
--- or1ksim/peripheral/channels/generic.h Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/generic.h Tue Oct 22 14:12:30 2002
@@ -0,0 +1,29 @@
+/* generic.h -- Declaration of generic functions for peripheral to
+ * communicate with host
+
+ Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef GENERIC_H
+#define GENERIC_H
+
+int generic_open(void * data);
+void generic_close(void * data);
+void generic_free(void * data);
+
+#endif
diff -urN -X dontdiff or1ksim/peripheral/channels/xterm.c or1ksim.richard/peripheral/channels/xterm.c
--- or1ksim/peripheral/channels/xterm.c Wed Dec 31 19:00:00 1969
+++ or1ksim.richard/peripheral/channels/xterm.c Thu Oct 24 11:45:00 2002
@@ -0,0 +1,207 @@
+/* xterm.c -- Definition of functions and structures for
+ peripheral to communicate with host through an xterm.
+ Inspired from SWI-Prolog by Jan Wielemaker (GPL too)
+ even if there is really few in common.
+
+ Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca>
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * I really dislike using stuff beginning with '_'
+ * They are suppose to be reserved for the compiler
+ * as explained in C standards.
+ */
+#define _XOPEN_SOURCE /* grantpt() and al. */
+#define _GNU_SOURCE /* on_exit */
+
+#include <sys/types.h> /* waitpid() */
+#include <sys/wait.h> /* waitpid() */
+#include <stdio.h> /* sprintf() */
+#include <stdlib.h> /* kill(), on_exit() */
+#include <unistd.h> /* close() */
+#include <fcntl.h> /* O_RDWR */
+#include <string.h> /* strchr() */
+#include <sys/stropts.h> /* grantpt(), unlockpt() */
+#include <termios.h> /* struct termios and al. */
+#include <signal.h> /* signal() and al. */
+#include <libgen.h> /* basename() */
+#include <errno.h> /* errno and al. */
+
+#include "channel.h"
+#include "generic.h"
+#include "fd.h"
+
+
+struct xterm_channel
+{
+ struct fd_channel fds;
+ int pid;
+};
+
+
+static void xterm_close(void * data)
+{
+ struct xterm_channel * xt = data;
+
+ if(!xt)
+ return;
+
+ if(xt->fds.fdin != -1)
+ close(xt->fds.fdin);
+
+ if(xt->pid != -1)
+ {
+ kill(xt->pid, SIGKILL);
+ waitpid(xt->pid, NULL, 0);
+ }
+
+ xt->fds.fdin = -1;
+ xt->fds.fdout = -1;
+ xt->pid = -1;
+}
+
+static void xterm_exit(int i, void * data)
+{
+ xterm_close(data);
+}
+
+static void * xterm_init(const char * input)
+{
+ struct xterm_channel * retval = malloc(sizeof(struct xterm_channel));
+ if(retval)
+ {
+ retval->fds.fdin = -1;
+ retval->fds.fdout = -1;
+ retval->pid = -1;
+ /* reset cause exit(1), leaving an xterm opened */
+ on_exit(xterm_exit, retval);
+ }
+ return (void*)retval;
+}
+
+
+
+static int xterm_open(void * data)
+{
+ struct xterm_channel * xt = data;
+ int master, retval;
+ char * slavename;
+ struct termios termio;
+ char arg[64], * fin;
+
+ if(!data)
+ {
+ errno = ENODEV;
+ return -1;
+ }
+
+
+ master = open("/dev/ptmx", O_RDWR);
+
+ if(master < 0)
+ return -1;
+
+ grantpt(master);
+ unlockpt(master);
+ slavename = (char*)ptsname(master);
+
+ if(!slavename)
+ {
+ errno = ENOTTY;
+ goto closemastererror;
+ }
+
+ xt->fds.fdout = xt->fds.fdin = open(slavename, O_RDWR);
+ if(xt->fds.fdout < 0) goto closemastererror;
+
+ retval = ioctl(xt->fds.fdin, I_PUSH, "ptem");
+ if(retval < 0) goto closeslaveerror;
+
+ retval = ioctl(xt->fds.fdin, I_PUSH, "ldterm");
+ if(retval < 0) goto closeslaveerror;
+
+ retval = tcgetattr(xt->fds.fdin, &termio);
+ if(retval < 0) goto closeslaveerror;
+
+
+ termio.c_lflag &= ~ECHO;
+ retval = tcsetattr(xt->fds.fdin, TCSADRAIN, &termio);
+ if(retval < 0) goto closeslaveerror;
+
+ xt->pid = fork();
+
+ if(xt->pid == -1) goto closeslaveerror;
+
+ if(xt->pid == 0)
+ {
+ /* Ctrl-C on sim still kill the xterm, grrr */
+ signal(SIGINT, SIG_IGN);
+
+ fin = slavename+strlen(slavename)-2;
+ if (strchr(fin, '/' ))
+ {
+ sprintf(arg, "-S%s/%d",
+ basename(slavename),
+ master);
+ }
+ else
+ {
+ sprintf(arg, "-S%c%c%d", fin[0], fin[1], master);
+ }
+ execlp("xterm", "xterm", arg, NULL);
+ write(master, "\n", 1);
+ exit(1);
+ }
+
+ do retval = read(xt->fds.fdin, &arg, 1);
+ while(retval >= 0 && arg[0] != '\n');
+
+ if(retval < 0) goto closeslaveerror;
+
+ termio.c_lflag |= ECHO;
+ retval = tcsetattr(xt->fds.fdin, TCSADRAIN, &termio);
+
+ if(retval < 0) goto closeslaveerror;
+
+ return 0;
+
+closeslaveerror:
+ close(xt->fds.fdin);
+
+closemastererror:
+ close(master);
+ xt->pid = xt->fds.fdin = xt->fds.fdout = -1;
+ return -1;
+}
+
+struct channel_ops xterm_channel_ops =
+{
+ init: xterm_init,
+ open: xterm_open,
+ close: xterm_close,
+ read: fd_read,
+ write: fd_write,
+ free: generic_free,
+};
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
+
diff -urN -X dontdiff or1ksim/sim-config.c or1ksim.richard/sim-config.c
--- or1ksim/sim-config.c Fri Aug 23 05:38:05 2002
+++ or1ksim.richard/sim-config.c Tue Oct 22 18:56:38 2002
@@ -365,8 +365,7 @@
void end_device ();
void uart_nuarts ();
void uart_baseaddr ();
-void uart_rxfile ();
-void uart_txfile ();
+void uart_channel ();
void uart_jitter ();
void uart_irq ();
void uart_16550 ();
@@ -503,8 +502,7 @@
{2, "irq", "=%i", uart_irq, (void *)(&tempL), 0},
{2, "16550", "=%i", uart_16550, (void *)(&tempL), 0},
{2, "jitter", "=%i", uart_jitter, (void *)(&tempL), 0},
-{2, "rxfile", "=\"%s\"", uart_rxfile, (void *)(&tempS[0]), 0},
-{2, "txfile", "=\"%s\"", uart_txfile, (void *)(&tempS[0]), 0},
+{2, "channel", "=\"%s\"", uart_channel, (void *)(&tempS[0]), 0},
{2, "vapi_id", "=0x%x", uart_vapi_id, (void *)(&tempUL), 0},
{3, "ndmas", "=%i", dma_ndmas, (void *)(&tempL), CPF_GLOBAL},
@@ -762,16 +760,9 @@
ERROR("invalid device number.");
}
-void uart_rxfile () {
+void uart_channel () {
if (current_device >= 0 && current_device < config.nuarts)
- strcpy (config.uarts[current_device].rxfile, tempS);
- else
- ERROR("invalid device number.");
-}
-
-void uart_txfile () {
- if (current_device >= 0 && current_device < config.nuarts)
- strcpy (config.uarts[current_device].txfile, tempS);
+ strcpy (config.uarts[current_device].channel, tempS);
else
ERROR("invalid device number.");
}
@@ -1479,8 +1470,8 @@
fprintf (f, " nuarts:%i, uarts:{", config.nuarts);
comma = 0;
for (i = 0; i < config.nuarts; i++) {
- fprintf (f, "%s\n {rxfile:\"%s\", txfile:\"%s\", jitter:%i, baseaddr:0x%08x, irq:%i, vapi_id:0x%08x, uart16550:%i}",
- comma ? "," :"", config.uarts[i].rxfile, config.uarts[i].txfile, config.uarts[i].jitter, config.uarts[i].baseaddr, config.uarts[i].irq,
+ fprintf (f, "%s\n {channel:\"%s\", jitter:%i, baseaddr:0x%08x, irq:%i, vapi_id:0x%08x, uart16550:%i}",
+ comma ? "," :"", config.uarts[i].channel, config.uarts[i].jitter, config.uarts[i].baseaddr, config.uarts[i].irq,
config.uarts[i].vapi_id, config.uarts[i].uart16550);
comma = 1;
}
diff -urN -X dontdiff or1ksim/sim-config.h or1ksim.richard/sim-config.h
--- or1ksim/sim-config.h Fri Aug 23 04:38:35 2002
+++ or1ksim.richard/sim-config.h Tue Oct 22 17:37:39 2002
@@ -46,13 +46,12 @@
int nuarts;
struct {
- char rxfile[STR_SIZE]; /* Filename for RX */
- char txfile[STR_SIZE]; /* Filename for TX (required) */
int jitter; /* CZ 250801 - in msecs...time to block */
unsigned long baseaddr; /* Naturally aligned base address */
int irq; /* IRQ of this device */
unsigned long vapi_id; /* VAPI id for this instance */
int uart16550; /* Whether this device is uart 16450 or 16550 */
+ char channel[STR_SIZE]; /* How to communicate with host */
} uarts[MAX_UARTS];
int ndmas;