summaryrefslogtreecommitdiff
path: root/os/ks32
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /os/ks32
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/ks32')
-rwxr-xr-xos/ks32/Mk7
-rw-r--r--os/ks32/NOTICE2
-rw-r--r--os/ks32/archevaluator7t.c161
-rw-r--r--os/ks32/armv7.h19
-rw-r--r--os/ks32/clock.c287
-rw-r--r--os/ks32/dat.h218
-rw-r--r--os/ks32/devuart.c719
-rw-r--r--os/ks32/download.ps1040
-rw-r--r--os/ks32/evaluator7t110
-rw-r--r--os/ks32/fns.h145
-rw-r--r--os/ks32/fpi.h61
-rw-r--r--os/ks32/fpiarm.c483
-rw-r--r--os/ks32/io.h168
-rw-r--r--os/ks32/l.s205
-rw-r--r--os/ks32/main.c289
-rw-r--r--os/ks32/mem.h54
-rw-r--r--os/ks32/mkfile115
-rw-r--r--os/ks32/not.c3
-rwxr-xr-xos/ks32/squirt2
-rw-r--r--os/ks32/trap.c525
20 files changed, 4613 insertions, 0 deletions
diff --git a/os/ks32/Mk b/os/ks32/Mk
new file mode 100755
index 00000000..2a55d43d
--- /dev/null
+++ b/os/ks32/Mk
@@ -0,0 +1,7 @@
+#!/bin/rc
+rfork ne
+ROOT=/usr/inferno
+fn cd
+NPROC=3
+path=(/usr/inferno/Plan9/$cputype/bin $path)
+exec mk $*
diff --git a/os/ks32/NOTICE b/os/ks32/NOTICE
new file mode 100644
index 00000000..d82287de
--- /dev/null
+++ b/os/ks32/NOTICE
@@ -0,0 +1,2 @@
+Evaluator 7t Inferno port Copyright © 2000-2003 Vita Nuova Holdings Limited.
+Originally implemented by Nigel Roles
diff --git a/os/ks32/archevaluator7t.c b/os/ks32/archevaluator7t.c
new file mode 100644
index 00000000..223c11f0
--- /dev/null
+++ b/os/ks32/archevaluator7t.c
@@ -0,0 +1,161 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+extern int cflag;
+extern int consoleprint;
+extern int redirectconsole;
+extern int main_pool_pcnt;
+extern int heap_pool_pcnt;
+extern int image_pool_pcnt;
+
+void
+archreset(void)
+{
+}
+
+void
+archconfinit(void)
+{
+ conf.topofmem = 512 * 1024;
+ conf.flashbase = 0x01800000;
+ conf.cpuspeed = 50000000;
+
+ conf.useminicache = 1;
+ conf.cansetbacklight = 0;
+ conf.cansetcontrast = 0;
+ conf.remaplo = 0;
+}
+
+void
+archconsole(void)
+{
+ uartspecial(0, 57600, 'n', &kbdq, &printq, kbdcr2nl);
+}
+
+void
+archreboot(void)
+{
+}
+
+void
+setleds(uchar val)
+{
+ ulong leds = IOPDATA;
+ IOPDATA = (leds & ~0xf0) | ((val & 0xf) << 4);
+}
+
+static void
+setled7(uchar val)
+{
+ ulong leds = IOPDATA;
+ IOPDATA = (leds & ~(0x7f << 10)) | ((val & 0x7f) << 10);
+}
+
+#define LEDSEGA 0x01
+#define LEDSEGB 0x02
+#define LEDSEGC 0x04
+#define LEDSEGD 0x08
+#define LEDSEGE 0x10
+#define LEDSEGG 0x20
+#define LEDSEGF 0x40
+
+static uchar led7map[] = {
+[' '] 0,
+['0'] LEDSEGA | LEDSEGB | LEDSEGC | LEDSEGD | LEDSEGE | LEDSEGF,
+['1'] LEDSEGB | LEDSEGC,
+['2'] LEDSEGA | LEDSEGB | LEDSEGD | LEDSEGE | LEDSEGG,
+['3'] LEDSEGA | LEDSEGB | LEDSEGC | LEDSEGD | LEDSEGG,
+['4'] LEDSEGB | LEDSEGC | LEDSEGF | LEDSEGG,
+['5'] LEDSEGA | LEDSEGC | LEDSEGD | LEDSEGF | LEDSEGG,
+['6'] LEDSEGA | LEDSEGC | LEDSEGD | LEDSEGE | LEDSEGF | LEDSEGG,
+['7'] LEDSEGA |LEDSEGB | LEDSEGC,
+['8'] LEDSEGA | LEDSEGB | LEDSEGC | LEDSEGD | LEDSEGE | LEDSEGF | LEDSEGG,
+['9'] LEDSEGA | LEDSEGB | LEDSEGC | LEDSEGD | LEDSEGF | LEDSEGG,
+['A'] LEDSEGA | LEDSEGB | LEDSEGC | LEDSEGE | LEDSEGF | LEDSEGG,
+['B'] LEDSEGC | LEDSEGD | LEDSEGE | LEDSEGF | LEDSEGG,
+['C'] LEDSEGA | LEDSEGD | LEDSEGE | LEDSEGF,
+['D'] LEDSEGB | LEDSEGC | LEDSEGD | LEDSEGE | LEDSEGG,
+['E'] LEDSEGA | LEDSEGD | LEDSEGE | LEDSEGF | LEDSEGG,
+['F'] LEDSEGA | LEDSEGE | LEDSEGF | LEDSEGG,
+['H'] LEDSEGC | LEDSEGE | LEDSEGF | LEDSEGG,
+['P'] LEDSEGA | LEDSEGB | LEDSEGE | LEDSEGF | LEDSEGG,
+['R'] LEDSEGE | LEDSEGG,
+['S'] LEDSEGA | LEDSEGC | LEDSEGD | LEDSEGF | LEDSEGG,
+['T'] LEDSEGD | LEDSEGE | LEDSEGF | LEDSEGG,
+['U'] LEDSEGB | LEDSEGC | LEDSEGD | LEDSEGE | LEDSEGF,
+['~'] LEDSEGB | LEDSEGE | LEDSEGG,
+};
+
+void
+setled7ascii(char c)
+{
+ if (c <= '~')
+ setled7(led7map[c]);
+}
+
+void
+trace(char c)
+{
+ int i;
+// int x = splfhi();
+ setled7ascii(c);
+ for (i = 0; i < 2000000; i++)
+ ;
+// splx(x);
+}
+
+void
+ttrace()
+{
+ static char c = '6';
+
+ trace(c);
+ c = '6' + '7' -c;
+}
+
+void
+lights(ulong val)
+{
+ IOPDATA = (IOPDATA & (0x7ff << 4)) | ((val & 0x7ff) << 4);
+}
+
+void
+lcd_setbacklight(int)
+{
+}
+
+void
+lcd_setbrightness(ushort)
+{
+}
+
+void
+lcd_setcontrast(ushort)
+{
+}
+
+void
+archflashwp(int /*wp*/)
+{
+}
+
+void
+screenputs(char *, int)
+{
+}
+
+void
+cursorenable(void)
+{
+}
+
+void
+cursordisable(void)
+{
+}
diff --git a/os/ks32/armv7.h b/os/ks32/armv7.h
new file mode 100644
index 00000000..f3f605fa
--- /dev/null
+++ b/os/ks32/armv7.h
@@ -0,0 +1,19 @@
+/*
+ * PSR
+ */
+#define PsrMusr 0x10 /* mode */
+#define PsrMfiq 0x11
+#define PsrMirq 0x12
+#define PsrMsvc 0x13
+#define PsrMabt 0x17
+#define PsrMund 0x1B
+#define PsrMsys 0x1F
+#define PsrMask 0x1F
+
+#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
+#define PsrDirq 0x00000080 /* disable IRQ interrupts */
+
+#define PsrV 0x10000000 /* overflow */
+#define PsrC 0x20000000 /* carry/borrow/extend */
+#define PsrZ 0x40000000 /* zero */
+#define PsrN 0x80000000 /* negative/less than */
diff --git a/os/ks32/clock.c b/os/ks32/clock.c
new file mode 100644
index 00000000..ef72988a
--- /dev/null
+++ b/os/ks32/clock.c
@@ -0,0 +1,287 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ureg.h"
+
+static ulong timer_incr[2] = { 0, 0, };
+
+#define DISABLE(t, x) t->mod &= (x ? ~0x08 : ~0x01)
+#define ENABLE(t, x) t->mod = (t->mod & (x ? 0x38 : 0x7)) | (x ? (1 << 3) : (1 << 0))
+
+typedef struct Clock0link Clock0link;
+typedef struct Clock0link {
+ void (*clock)(void);
+ Clock0link* link;
+} Clock0link;
+
+static Clock0link *clock0link;
+static Lock clock0lock;
+static void (*prof_fcn)(Ureg *, int);
+
+Timer*
+addclock0link(void (*clock)(void), int)
+{
+ Clock0link *lp;
+
+ if((lp = malloc(sizeof(Clock0link))) == 0){
+ print("addclock0link: too many links\n");
+ return nil;
+ }
+ ilock(&clock0lock);
+ lp->clock = clock;
+ lp->link = clock0link;
+ clock0link = lp;
+ iunlock(&clock0lock);
+ return nil;
+}
+
+static void
+profintr(Ureg *ur, void*)
+{
+#ifdef PROF
+ OstmrReg *ost = OSTMRREG;
+ int t;
+
+ if ((ost->osmr[3] - ost->oscr) < 2*TIMER_HZ)
+ {
+ /* less than 2 seconds before reset, say something */
+ setpanic();
+ clockpoll();
+ dumpregs(ur);
+ panic("Watchdog timer will expire");
+ }
+
+ /* advance the profile clock tick */
+ ost->osmr[2] += timer_incr[2];
+ ost->ossr = (1 << 2); /* Clear the SR */
+ t = 1;
+ while((ost->osmr[2] - ost->oscr) > 0x80000000) {
+ ost->osmr[2] += timer_incr[2];
+ t++;
+ }
+ if (prof_fcn)
+ prof_fcn(ur, t);
+#else
+ USED(ur);
+#endif
+}
+
+static void
+clockintr(Ureg*, void*)
+{
+ Clock0link *lp;
+
+ m->ticks++;
+
+ checkalarms();
+
+ if(canlock(&clock0lock)){
+ for(lp = clock0link; lp; lp = lp->link)
+ if (lp->clock)
+ lp->clock();
+ unlock(&clock0lock);
+ }
+ intrclear(TIMERbit(0), 0);
+}
+
+/*
+int
+cticks(void)
+{
+ return m->ticks;
+}
+*/
+
+/*
+ * Synchronize to the next SCLK tick boundary at best SPI rate.
+ */
+void
+spi_tsync(void)
+{
+ /* Why has this been commented out? */
+
+ // don't need to waste any time here
+ //ulong t0;
+
+ //t0 = OSTMR->oscr;
+ //while (OSTMR->oscr == t0);
+}
+
+void
+timerdisable( int timer )
+{
+ TimerReg *t = TIMERREG;
+ if ((timer < 0) || (timer > 1))
+ return;
+ intrmask(TIMERbit(timer), 0);
+ DISABLE(t, timer);
+}
+
+void
+timerenable( int timer, int Hz, void (*f)(Ureg *, void*), void* a)
+{
+ TimerReg *t = TIMERREG;
+ if ((timer < 0) || (timer > 1))
+ return;
+ timerdisable(timer);
+ timer_incr[timer] = TIMER_HZ/Hz; /* set up freq */
+ t->data[timer] = timer_incr[timer];
+ ENABLE(t, timer);
+ intrenable(TIMERbit(timer), f, a, 0);
+}
+
+void
+installprof(void (*pf)(Ureg *, int))
+{
+#ifdef PROF
+ prof_fcn = pf;
+ timerenable( 2, HZ+1, profintr, 0);
+ timer_incr[2] = timer_incr[0]+63; /* fine tuning */
+#else
+ USED(pf);
+#endif
+}
+
+void
+clockinit(void)
+{
+ m->ticks = 0;
+ timerenable(0, HZ, clockintr, 0);
+}
+
+void
+clockpoll(void)
+{
+}
+
+void
+clockcheck(void)
+{
+}
+
+// macros for fixed-point math
+
+ulong _mularsv(ulong m0, ulong m1, ulong a, ulong s);
+
+/* truncated: */
+#define FXDPTDIV(a,b,n) ((ulong)(((uvlong)(a) << (n)) / (b)))
+#define MAXMUL(a,n) ((ulong)((((uvlong)1<<(n))-1)/(a)))
+#define MULDIV(x,a,b,n) (((x)*FXDPTDIV(a,b,n)) >> (n))
+#define MULDIV64(x,a,b,n) ((ulong)_mularsv(x, FXDPTDIV(a,b,n), 0, (n)))
+
+/* rounded: */
+#define FXDPTDIVR(a,b,n) ((ulong)((((uvlong)(a) << (n))+((b)/2)) / (b)))
+#define MAXMULR(a,n) ((ulong)((((uvlong)1<<(n))-1)/(a)))
+#define MULDIVR(x,a,b,n) (((x)*FXDPTDIVR(a,b,n)+(1<<((n)-1))) >> (n))
+#define MULDIVR64(x,a,b,n) ((ulong)_mularsv(x, FXDPTDIVR(a,b,n), 1<<((n)-1), (n)))
+
+
+// these routines are all limited to a maximum of 1165 seconds,
+// due to the wrap-around of the OSTIMER
+
+ulong
+timer_start(void)
+{
+ return TIMERREG->data[0];
+}
+
+ulong
+timer_ticks(ulong t0)
+{
+ return TIMERREG->data[0] - t0;
+}
+
+int
+timer_devwait(ulong *adr, ulong mask, ulong val, int ost)
+{
+ int i;
+ ulong t0 = timer_start();
+ while((*adr & mask) != val)
+ if(timer_ticks(t0) > ost)
+ return ((*adr & mask) == val) ? 0 : -1;
+ else
+ for (i = 0; i < 10; i++); /* don't pound OSCR too hard! (why not?) */
+ return 0;
+}
+
+void
+timer_setwatchdog(int t)
+{
+ USED(t);
+}
+
+void
+timer_delay(int t)
+{
+ ulong t0 = timer_start();
+ while(timer_ticks(t0) < t)
+ ;
+}
+
+
+ulong
+us2tmr(int us)
+{
+ return MULDIV64(us, TIMER_HZ, 1000000, 24);
+}
+
+int
+tmr2us(ulong t)
+{
+ return MULDIV64(t, 1000000, TIMER_HZ, 24);
+}
+
+void
+microdelay(int us)
+{
+ ulong t0 = timer_start();
+ ulong t = us2tmr(us);
+ while(timer_ticks(t0) <= t)
+ ;
+}
+
+
+ulong
+ms2tmr(int ms)
+{
+ return MULDIV64(ms, TIMER_HZ, 1000, 20);
+}
+
+int
+tmr2ms(ulong t)
+{
+ return MULDIV64(t, 1000, TIMER_HZ, 32);
+}
+
+void
+delay(int ms)
+{
+ ulong t0 = timer_start();
+ ulong t = ms2tmr(ms);
+ while(timer_ticks(t0) <= t)
+ clockpoll();
+}
+
+int
+srand()
+{
+ return 0;
+}
+
+int
+time()
+{
+ return 0;
+}
+
+uvlong
+fastticks(uvlong *hz)
+{
+ if(hz)
+ *hz = HZ;
+ return m->ticks;
+}
diff --git a/os/ks32/dat.h b/os/ks32/dat.h
new file mode 100644
index 00000000..70422b63
--- /dev/null
+++ b/os/ks32/dat.h
@@ -0,0 +1,218 @@
+typedef struct Conf Conf;
+typedef struct FPU FPU;
+typedef struct FPenv FPenv;
+typedef struct Label Label;
+typedef struct Lock Lock;
+typedef struct Mach Mach;
+typedef struct Ureg Ureg;
+typedef struct ISAConf ISAConf;
+typedef struct PCMmap PCMmap;
+typedef struct PCIcfg PCIcfg;
+typedef struct TouchPnt TouchPnt;
+typedef struct TouchTrans TouchTrans;
+typedef struct TouchCal TouchCal;
+typedef struct Vmode Vmode;
+
+typedef ulong Instr;
+
+#define ISAOPTLEN 16
+#define NISAOPT 8
+struct Conf
+{
+ ulong nmach; /* processors */
+ ulong nproc; /* processes */
+ ulong npage0; /* total physical pages of memory */
+ ulong npage1; /* total physical pages of memory */
+ ulong topofmem; /* highest physical address + 1 */
+ ulong npage; /* total physical pages of memory */
+ ulong base0; /* base of bank 0 */
+ ulong base1; /* base of bank 1 */
+ ulong ialloc; /* max interrupt time allocation in bytes */
+ ulong flashbase;
+ ulong cpuspeed;
+ ulong pagetable;
+
+ int useminicache; /* screen.c/lcd.c */
+ int cansetbacklight; /* screen.c/lcd.c */
+ int cansetcontrast; /* screen.c/lcd.c */
+ int remaplo; /* use alt ivec */
+ int textwrite; /* writeable text segment, for debug */
+};
+
+struct ISAConf {
+ char type[KNAMELEN];
+ ulong port;
+ ulong irq;
+ ulong sairq;
+ ulong dma;
+ ulong mem;
+ ulong size;
+ ulong freq;
+
+ int nopt;
+ char opt[NISAOPT][ISAOPTLEN];
+};
+
+/*
+ * FPenv.status
+ */
+enum
+{
+ FPINIT,
+ FPACTIVE,
+ FPINACTIVE,
+};
+
+struct FPenv
+{
+ ulong status;
+ ulong control;
+ ushort fpistate; /* emulated fp */
+ ulong regs[8][3]; /* emulated fp */
+};
+
+/*
+ * This structure must agree with fpsave and fprestore asm routines
+ */
+struct FPU
+{
+ FPenv env;
+ uchar regs[80]; /* floating point registers */
+};
+
+struct Label
+{
+ ulong sp;
+ ulong pc;
+};
+
+struct Lock
+{
+ ulong key;
+ ulong sr;
+ ulong pc;
+ int pri;
+};
+
+#include "../port/portdat.h"
+
+/*
+ * machine dependent definitions not used by ../port/dat.h
+ */
+struct Mach
+{
+ ulong ticks; /* of the clock since boot time */
+ Proc *proc; /* current process on this processor */
+ Label sched; /* scheduler wakeup */
+ Lock alarmlock; /* access to alarm list */
+ void *alarm; /* alarms bound to this clock */
+ int machno;
+ int nrdy;
+
+ int stack[1];
+};
+
+#define MACHP(n) (n == 0 ? (Mach*)(MACHADDR) : (Mach*)0)
+
+extern Mach Mach0;
+extern Mach *m;
+extern Proc *up;
+
+typedef struct MemBank {
+ uint pbase;
+ uint plimit;
+ uint vbase;
+ uint vlimit;
+} MemBank;
+
+enum {
+ // DMA configuration parameters
+
+ // DMA Direction
+ DmaOUT= 0,
+ DmaIN= 1,
+
+ // dma endianess
+ DmaLittle= 0,
+ DmaBig= 1,
+
+ // dma devices
+ DmaUDC= 0,
+ DmaSDLC= 2,
+ DmaUART0= 4,
+ DmaHSSP= 6,
+ DmaUART1= 7, // special case (is really 6)
+ DmaUART2= 8,
+ DmaMCPaudio= 10,
+ DmaMCPtelecom= 12,
+ DmaSSP= 14,
+};
+
+enum touch_source {
+ TOUCH_READ_X1, TOUCH_READ_X2, TOUCH_READ_X3, TOUCH_READ_X4,
+ TOUCH_READ_Y1, TOUCH_READ_Y2, TOUCH_READ_Y3, TOUCH_READ_Y4,
+ TOUCH_READ_P1, TOUCH_READ_P2,
+ TOUCH_READ_RX1, TOUCH_READ_RX2,
+ TOUCH_READ_RY1, TOUCH_READ_RY2,
+ TOUCH_NUMRAWCAL = 10,
+};
+
+struct TouchPnt {
+ int x;
+ int y;
+};
+
+struct TouchTrans {
+ int xxm;
+ int xym;
+ int yxm;
+ int yym;
+ int xa;
+ int ya;
+};
+
+struct TouchCal {
+ TouchPnt p[4]; // screen points
+ TouchPnt r[4][4];// raw points
+ TouchTrans t[4]; // transformations
+ TouchPnt err; // maximum error
+ TouchPnt var; // usual maximum variance for readings
+ int ptp; // pressure threshold for press
+ int ptr; // pressure threshold for release
+};
+
+extern TouchCal touchcal;
+
+struct Vmode {
+ int wid; /* 0 -> default or any match for all fields */
+ int hgt;
+ uchar d;
+ uchar hz;
+ ushort flags;
+};
+
+enum {
+ VMODE_MONO = 0x0001, /* monochrome display */
+ VMODE_COLOR = 0x0002, /* color (RGB) display */
+ VMODE_TFT = 0x0004, /* TFT (active matrix) display */
+ VMODE_STATIC = 0x0010, /* fixed palette */
+ VMODE_PSEUDO = 0x0020, /* changeable palette */
+ VMODE_LINEAR = 0x0100, /* linear frame buffer */
+ VMODE_PAGED = 0x0200, /* paged frame buffer */
+ VMODE_PLANAR = 0x1000, /* pixel bits split between planes */
+ VMODE_PACKED = 0x2000, /* pixel bits packed together */
+ VMODE_LILEND = 0x4000, /* little endian pixel layout */
+ VMODE_BIGEND = 0x8000, /* big endian pixel layout */
+};
+
+/*
+ * Interface to PCMCIA stubs
+ */
+enum {
+ /* argument to pcmpin() */
+ PCMready,
+ PCMeject,
+ PCMstschng,
+};
+
+#define swcursor 1
diff --git a/os/ks32/devuart.c b/os/ks32/devuart.c
new file mode 100644
index 00000000..2251dd59
--- /dev/null
+++ b/os/ks32/devuart.c
@@ -0,0 +1,719 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "../port/netif.h"
+
+/*
+ * currently no DMA or flow control (hardware or software)
+ */
+
+/*
+ * problems fixed from previous vsn:
+ *
+ * - no kick on queue's, so redirections weren't getting
+ * started until the clock tick
+ *
+ * - lots of unnecessary overhead
+ *
+ * - initialization sequencing
+ *
+ * - uart[n] no longer indexed before calling uartinstall()
+ */
+#define DEBUG if(0)iprint
+
+static void uartintr(Ureg*, void*);
+
+enum
+{
+ Stagesize= 1024,
+ Dmabufsize=Stagesize/2,
+ Nuart=7, /* max per machine */
+};
+
+typedef struct Uart Uart;
+struct Uart
+{
+ QLock;
+
+ int opens;
+
+ int enabled;
+
+ int port; /* 0 or 1 */
+ int kickme; /* for kick */
+ int frame; /* framing errors */
+ int overrun; /* rcvr overruns */
+ int perror; /* parity error */
+ int bps; /* baud rate */
+ uchar bits;
+ char parity;
+ uchar stop;
+
+ int inters; /* total interrupt count */
+ int rinters; /* interrupts due to read */
+ int winters; /* interrupts due to write */
+
+ int rcount; /* total read count */
+ int wcount; /* total output count */
+
+ /* buffers */
+ int (*putc)(Queue*, int);
+ Queue *iq;
+ Queue *oq;
+
+ UartReg *reg;
+
+ /* staging areas to avoid some of the per character costs */
+ uchar *ip;
+ uchar *ie;
+ uchar *op;
+ uchar *oe;
+
+ /* put large buffers last to aid register-offset optimizations: */
+ char name[KNAMELEN];
+ uchar istage[Stagesize];
+ uchar ostage[Stagesize];
+};
+
+#define UCON_ENABLEMASK (UCON_RXMDMASK | UCON_TXMDMASK | UCON_SINTMASK)
+#define UCON_ENABLESET (UCON_RXMDINT | UCON_TXMDINT | UCON_SINTON)
+#define UCON_DISABLESET (UCON_RXMDOFF | UCON_TXMDOFF | UCON_SINTOFF)
+
+static Uart *uart[Nuart];
+static int nuart;
+
+static uchar
+readstatus(Uart *p)
+{
+ UartReg *reg = p->reg;
+ uchar stat = reg->stat;
+ if (stat & USTAT_OV)
+ p->overrun++;
+ if (stat & USTAT_PE)
+ p->perror++;
+ if (stat & USTAT_FE)
+ p->frame++;
+ return stat;
+}
+
+static void
+uartset(Uart *p)
+{
+ UartReg *reg = p->reg;
+ ulong denom;
+ ulong brdiv;
+ int n;
+ uchar lcon;
+
+ lcon= ULCON_CLOCKMCLK | ULCON_IROFF;
+ lcon |= ULCON_WL5 + (p->bits - 5);
+ lcon |= p->stop == 1 ? ULCON_STOP1 : ULCON_STOP2;
+ switch (p->parity) {
+ default:
+ case 'n':
+ lcon |= ULCON_PMDNONE;
+ break;
+ case 'o':
+ lcon |= ULCON_PMDODD;
+ break;
+ case 'e':
+ lcon |= ULCON_PMDEVEN;
+ break;
+ }
+ reg->lcon = lcon;
+
+ /* clear the break and loopback bits; leave everything else alone */
+ reg->con = (reg->con & ~(UCON_BRKMASK | UCON_LOOPMASK)) | UCON_BRKOFF | UCON_LOOPOFF;
+
+ denom = 2 * 16 * p->bps;
+ brdiv = (TIMER_HZ + denom / 2) / denom - 1;
+ reg->brdiv = brdiv << 4;
+
+ /* set buffer length according to speed, to allow
+ * at most a 200ms delay before dumping the staging buffer
+ * into the input queue
+ */
+ n = p->bps/(10*1000/200);
+ p->ie = &p->istage[n < Stagesize ? n : Stagesize];
+}
+
+/*
+ * send break
+ */
+static void
+uartbreak(Uart *p, int ms)
+{
+ UartReg *reg = p->reg;
+ if(ms == 0)
+ ms = 200;
+ reg->con |= UCON_BRKON;
+ tsleep(&up->sleep, return0, 0, ms);
+ reg->con &= ~UCON_BRKON;
+}
+
+/*
+ * turn on a port
+ */
+static void
+uartenable(Uart *p)
+{
+ UartReg *reg = p->reg;
+
+ if(p->enabled)
+ return;
+
+ uartset(p);
+ // enable receive, transmit, and receive interrupt:
+ reg->con = (reg->con & UCON_ENABLEMASK) | UCON_ENABLESET;
+ p->enabled = 1;
+}
+
+/*
+ * turn off a port
+ */
+static void
+uartdisable(Uart *p)
+{
+ p->reg->con = (p->reg->con & UCON_ENABLEMASK) | UCON_DISABLESET;
+ p->enabled = 0;
+}
+
+/*
+ * put some bytes into the local queue to avoid calling
+ * qconsume for every character
+ */
+static int
+stageoutput(Uart *p)
+{
+ int n;
+ Queue *q = p->oq;
+
+ if(!q)
+ return 0;
+ n = qconsume(q, p->ostage, Stagesize);
+ if(n <= 0)
+ return 0;
+ p->op = p->ostage;
+ p->oe = p->ostage + n;
+ return n;
+}
+
+static void
+uartxmit(Uart *p)
+{
+ UartReg *reg = p->reg;
+ ulong gag = 1;
+ while(p->op < p->oe || stageoutput(p)) {
+ if(readstatus(p) & USTAT_TBE) {
+ DEBUG("T");
+ reg->txbuf = *(p->op++);
+ p->wcount++;
+ } else {
+ DEBUG("F");
+ gag = 0;
+ break;
+ }
+ }
+ if (gag) {
+ DEBUG("G");
+ p->kickme = 1;
+ intrmask(UARTTXbit(p->port), 0);
+ }
+}
+
+static void
+uartrecvq(Uart *p)
+{
+ uchar *cp = p->istage;
+ int n = p->ip - cp;
+
+ if(n == 0)
+ return;
+ if(p->putc)
+ while(n-- > 0)
+ p->putc(p->iq, *cp++);
+ else if(p->iq)
+ if(qproduce(p->iq, p->istage, n) < n)
+ print("qproduce flow control");
+ p->ip = p->istage;
+}
+
+static void
+uartrecv(Uart *p)
+{
+ UartReg *reg = p->reg;
+ uchar stat = readstatus(p);
+
+DEBUG("R");
+ if (stat & USTAT_RDR) {
+ int c;
+ c = reg->rxbuf;
+ if (c == '?') {
+ DEBUG("mod 0x%.8lx\n", INTREG->mod);
+ DEBUG("msk 0x%.8lx\n", INTREG->msk);
+ DEBUG("pnd 0x%.8lx\n", INTREG->pnd);
+ }
+ *p->ip++ = c;
+/* if(p->ip >= p->ie) */
+ uartrecvq(p);
+ p->rcount++;
+ }
+}
+
+static void
+uartkick(void *a)
+{
+ Uart *p = a;
+ int x = splhi();
+ DEBUG("k");
+ if (p->kickme) {
+ p->kickme = 0;
+ DEBUG("K");
+ intrunmask(UARTTXbit(p->port), 0);
+ }
+ splx(x);
+}
+
+/*
+ * UART Interrupt Handler
+ */
+static void
+uarttxintr(Ureg*, void* arg)
+{
+ Uart *p = arg;
+ intrclear(UARTTXbit(p->port), 0);
+ p->inters++;
+ p->winters++;
+ uartxmit(p);
+}
+
+static void
+uartrxintr(Ureg*, void* arg)
+{
+ Uart *p = arg;
+ intrclear(UARTRXbit(p->port), 0);
+ p->inters++;
+ p->rinters++;
+ uartrecv(p);
+}
+
+
+static void
+uartsetup(ulong port, char *name)
+{
+ Uart *p;
+
+ if(nuart >= Nuart)
+ return;
+
+ p = xalloc(sizeof(Uart));
+ uart[nuart++] = p;
+ strcpy(p->name, name);
+
+ p->reg = &UARTREG[port];
+ p->bps = 9600;
+ p->bits = 8;
+ p->parity = 'n';
+ p->stop = 1;
+ p->kickme = 0;
+ p->port = port;
+
+ p->iq = qopen(4*1024, 0, 0 , p);
+ p->oq = qopen(4*1024, 0, uartkick, p);
+
+ p->ip = p->istage;
+ p->ie = &p->istage[Stagesize];
+ p->op = p->ostage;
+ p->oe = p->ostage;
+
+ intrenable(UARTTXbit(port), uarttxintr, p, 0);
+ intrenable(UARTRXbit(port), uartrxintr, p, 0);
+}
+
+static void
+uartinstall(void)
+{
+ static int already;
+
+ if(already)
+ return;
+ already = 1;
+
+ uartsetup(0, "eia0");
+// uartsetup(1, "eia1");
+}
+
+/*
+ * called by main() to configure a duart port as a console or a mouse
+ */
+void
+uartspecial(int port, int bps, char parity, Queue **in, Queue **out, int (*putc)(Queue*, int))
+{
+ Uart *p;
+
+ uartinstall();
+ if(port >= nuart)
+ return;
+ p = uart[port];
+ if(bps)
+ p->bps = bps;
+ if(parity)
+ p->parity = parity;
+ uartenable(p);
+ p->putc = putc;
+ if(in)
+ *in = p->iq;
+ if(out)
+ *out = p->oq;
+ p->opens++;
+}
+
+Dirtab *uartdir;
+int ndir;
+
+static void
+setlength(int i)
+{
+ Uart *p;
+
+ if(i > 0){
+ p = uart[i];
+ if(p && p->opens && p->iq)
+ uartdir[1+3*i].length = qlen(p->iq);
+ } else for(i = 0; i < nuart; i++){
+ p = uart[i];
+ if(p && p->opens && p->iq)
+ uartdir[1+3*i].length = qlen(p->iq);
+ }
+}
+
+/*
+ * all uarts must be uartsetup() by this point or inside of uartinstall()
+ */
+static void
+uartreset(void)
+{
+ int i;
+ Dirtab *dp;
+
+ uartinstall();
+
+ ndir = 1+3*nuart;
+ uartdir = xalloc(ndir * sizeof(Dirtab));
+ dp = uartdir;
+ strcpy(dp->name, ".");
+ mkqid(&dp->qid, 0, 0, QTDIR);
+ dp->length = 0;
+ dp->perm = DMDIR|0555;
+ dp++;
+ for(i = 0; i < nuart; i++){
+ /* 3 directory entries per port */
+ strcpy(dp->name, uart[i]->name);
+ dp->qid.path = NETQID(i, Ndataqid);
+ dp->perm = 0660;
+ dp++;
+ sprint(dp->name, "%sctl", uart[i]->name);
+ dp->qid.path = NETQID(i, Nctlqid);
+ dp->perm = 0660;
+ dp++;
+ sprint(dp->name, "%sstatus", uart[i]->name);
+ dp->qid.path = NETQID(i, Nstatqid);
+ dp->perm = 0444;
+ dp++;
+ }
+}
+
+static Chan*
+uartattach(char *spec)
+{
+ return devattach('t', spec);
+}
+
+static Walkqid*
+uartwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, uartdir, ndir, devgen);
+}
+
+static int
+uartstat(Chan *c, uchar *dp, int n)
+{
+ if(NETTYPE(c->qid.path) == Ndataqid)
+ setlength(NETID(c->qid.path));
+ return devstat(c, dp, n, uartdir, ndir, devgen);
+}
+
+static Chan*
+uartopen(Chan *c, int omode)
+{
+ Uart *p;
+
+ c = devopen(c, omode, uartdir, ndir, devgen);
+
+ switch(NETTYPE(c->qid.path)){
+ case Nctlqid:
+ case Ndataqid:
+ p = uart[NETID(c->qid.path)];
+ qlock(p);
+ if(p->opens++ == 0){
+ uartenable(p);
+ qreopen(p->iq);
+ qreopen(p->oq);
+ }
+ qunlock(p);
+ break;
+ }
+
+ return c;
+}
+
+static void
+uartclose(Chan *c)
+{
+ Uart *p;
+
+ if(c->qid.type & QTDIR)
+ return;
+ if((c->flag & COPEN) == 0)
+ return;
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ case Nctlqid:
+ p = uart[NETID(c->qid.path)];
+ qlock(p);
+ if(--(p->opens) == 0){
+ uartdisable(p);
+ qclose(p->iq);
+ qclose(p->oq);
+ p->ip = p->istage;
+ }
+ qunlock(p);
+ break;
+ }
+}
+
+static long
+uartstatus(Chan *c, Uart *p, void *buf, long n, long offset)
+{
+ char str[256];
+ USED(c);
+
+ str[0] = 0;
+ sprint(str, "opens %d ferr %d oerr %d perr %d baud %d parity %c"
+ " intr %d rintr %d wintr %d"
+ " rcount %d wcount %d",
+ p->opens, p->frame, p->overrun, p->perror, p->bps, p->parity,
+ p->inters, p->rinters, p->winters,
+ p->rcount, p->wcount);
+
+ strcat(str, "\n");
+ return readstr(offset, buf, n, str);
+}
+
+static long
+uartread(Chan *c, void *buf, long n, vlong offset)
+{
+ Uart *p;
+
+ if(c->qid.type & QTDIR){
+ setlength(-1);
+ return devdirread(c, buf, n, uartdir, ndir, devgen);
+ }
+
+ p = uart[NETID(c->qid.path)];
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ return qread(p->iq, buf, n);
+ case Nctlqid:
+ return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE);
+ case Nstatqid:
+ return uartstatus(c, p, buf, n, offset);
+ }
+
+ return 0;
+}
+
+static void
+uartctl(Uart *p, char *cmd)
+{
+ int i, n;
+
+ /* let output drain for a while (up to 4 secs) */
+ for(i = 0; i < 200 && (qlen(p->oq) || (readstatus(p) & USTAT_TC) == 0); i++)
+ tsleep(&up->sleep, return0, 0, 20);
+
+ if(strncmp(cmd, "break", 5) == 0){
+ uartbreak(p, 0);
+ return;
+ }
+
+ n = atoi(cmd+1);
+ switch(*cmd){
+ case 'B':
+ case 'b':
+ if(n <= 0)
+ error(Ebadarg);
+ p->bps = n;
+ uartset(p);
+ break;
+ case 'f':
+ case 'F':
+ qflush(p->oq);
+ break;
+ case 'H':
+ case 'h':
+ qhangup(p->iq, 0);
+ qhangup(p->oq, 0);
+ break;
+ case 'L':
+ case 'l':
+ if(n < 7 || n > 8)
+ error(Ebadarg);
+ p->bits = n;
+ uartset(p);
+ break;
+ case 'n':
+ case 'N':
+ qnoblock(p->oq, n);
+ break;
+ case 'P':
+ case 'p':
+ p->parity = *(cmd+1);
+ uartset(p);
+ break;
+ case 'K':
+ case 'k':
+ uartbreak(p, n);
+ break;
+ case 'Q':
+ case 'q':
+ qsetlimit(p->iq, n);
+ qsetlimit(p->oq, n);
+ break;
+ case 's':
+ case 'S':
+ if(n < 1 || n > 2)
+ error(Ebadarg);
+ p->stop = n;
+ uartset(p);
+ break;
+ }
+}
+
+static long
+uartwrite(Chan *c, void *buf, long n, vlong offset)
+{
+ Uart *p;
+ char cmd[32];
+
+ USED(offset);
+
+ if(c->qid.type & QTDIR)
+ error(Eperm);
+
+ p = uart[NETID(c->qid.path)];
+
+ switch(NETTYPE(c->qid.path)){
+ case Ndataqid:
+ return qwrite(p->oq, buf, n);
+ case Nctlqid:
+
+ if(n >= sizeof(cmd))
+ n = sizeof(cmd)-1;
+ memmove(cmd, buf, n);
+ cmd[n] = 0;
+ uartctl(p, cmd);
+ return n;
+ }
+}
+
+static int
+uartwstat(Chan *c, uchar *dp, int n)
+{
+ error(Eperm);
+ return 0;
+#ifdef xxx
+ Dir d;
+ Dirtab *dt;
+
+ if(!iseve())
+ error(Eperm);
+ if(c->qid.type & QTDIR)
+ error(Eperm);
+ if(NETTYPE(c->qid.path) == Nstatqid)
+ error(Eperm);
+
+ dt = &uartdir[3 * NETID(c->qid.path)];
+ convM2D(dp, &d);
+ d.mode &= 0666;
+ dt[0].perm = dt[1].perm = d.mode;
+#endif
+}
+
+Dev uartdevtab = {
+ 't',
+ "uart",
+
+ uartreset,
+ devinit,
+ devshutdown,
+ uartattach,
+ uartwalk,
+ uartstat,
+ uartopen,
+ devcreate,
+ uartclose,
+ uartread,
+ devbread,
+ uartwrite,
+ devbwrite,
+ devremove,
+ uartwstat,
+};
+
+void
+uartputc(int c)
+{
+ UartReg *u;
+
+ if (!c)
+ return;
+ u = &UARTREG[1];
+ while ((u->stat & USTAT_TBE) == 0)
+ ;
+ u->txbuf = c;
+ if (c == '\n')
+ while((u->stat & USTAT_TC) == 0) /* flush xmit fifo */
+ ;
+}
+
+void
+uartputs(char *data, int len)
+{
+ int x;
+
+ clockpoll();
+ x = splfhi();
+ while (len--){
+ if(*data == '\n')
+ uartputc('\r');
+ uartputc(*data++);
+ }
+ splx(x);
+}
+
+int
+uartgetc(void)
+{
+ UartReg *u;
+
+ clockcheck();
+ u = &UARTREG[1];
+ while((u->stat & USTAT_RDR) == 0)
+ clockcheck();
+ return u->rxbuf;
+}
diff --git a/os/ks32/download.ps b/os/ks32/download.ps
new file mode 100644
index 00000000..8182bc4b
--- /dev/null
+++ b/os/ks32/download.ps
@@ -0,0 +1,1040 @@
+%!PS-Adobe-2.0
+%%Version: 0.1
+%%DocumentFonts: (atend)
+%%Pages: (atend)
+%%EndComments
+%
+% Version 3.3.2 prologue for troff files.
+%
+
+/#copies 1 store
+/aspectratio 1 def
+/formsperpage 1 def
+/landscape false def
+/linewidth .3 def
+/magnification 1 def
+/margin 0 def
+/orientation 0 def
+/resolution 720 def
+/rotation 1 def
+/xoffset 0 def
+/yoffset 0 def
+
+/roundpage true def
+/useclippath true def
+/pagebbox [0 0 612 792] def
+
+/R /Times-Roman def
+/I /Times-Italic def
+/B /Times-Bold def
+/BI /Times-BoldItalic def
+/H /Helvetica def
+/HI /Helvetica-Oblique def
+/HB /Helvetica-Bold def
+/HX /Helvetica-BoldOblique def
+/CW /Courier def
+/CO /Courier def
+/CI /Courier-Oblique def
+/CB /Courier-Bold def
+/CX /Courier-BoldOblique def
+/PA /Palatino-Roman def
+/PI /Palatino-Italic def
+/PB /Palatino-Bold def
+/PX /Palatino-BoldItalic def
+/Hr /Helvetica-Narrow def
+/Hi /Helvetica-Narrow-Oblique def
+/Hb /Helvetica-Narrow-Bold def
+/Hx /Helvetica-Narrow-BoldOblique def
+/KR /Bookman-Light def
+/KI /Bookman-LightItalic def
+/KB /Bookman-Demi def
+/KX /Bookman-DemiItalic def
+/AR /AvantGarde-Book def
+/AI /AvantGarde-BookOblique def
+/AB /AvantGarde-Demi def
+/AX /AvantGarde-DemiOblique def
+/NR /NewCenturySchlbk-Roman def
+/NI /NewCenturySchlbk-Italic def
+/NB /NewCenturySchlbk-Bold def
+/NX /NewCenturySchlbk-BoldItalic def
+/ZD /ZapfDingbats def
+/ZI /ZapfChancery-MediumItalic def
+/S /S def
+/S1 /S1 def
+/GR /Symbol def
+
+/inch {72 mul} bind def
+/min {2 copy gt {exch} if pop} bind def
+
+/setup {
+ counttomark 2 idiv {def} repeat pop
+
+ landscape {/orientation 90 orientation add def} if
+ /scaling 72 resolution div def
+ linewidth setlinewidth
+ 1 setlinecap
+
+ pagedimensions
+ xcenter ycenter translate
+ orientation rotation mul rotate
+ width 2 div neg height 2 div translate
+ xoffset inch yoffset inch neg translate
+ margin 2 div dup neg translate
+ magnification dup aspectratio mul scale
+ scaling scaling scale
+
+ addmetrics
+ 0 0 moveto
+} def
+
+/pagedimensions {
+ useclippath userdict /gotpagebbox known not and {
+ /pagebbox [clippath pathbbox newpath] def
+ roundpage currentdict /roundpagebbox known and {roundpagebbox} if
+ } if
+ pagebbox aload pop
+ 4 -1 roll exch 4 1 roll 4 copy
+ landscape {4 2 roll} if
+ sub /width exch def
+ sub /height exch def
+ add 2 div /xcenter exch def
+ add 2 div /ycenter exch def
+ userdict /gotpagebbox true put
+} def
+
+/addmetrics {
+ /Symbol /S null Sdefs cf
+ /Times-Roman /S1 StandardEncoding dup length array copy S1defs cf
+} def
+
+/pagesetup {
+ /page exch def
+ currentdict /pagedict known currentdict page known and {
+ page load pagedict exch get cvx exec
+ } if
+} def
+
+/decodingdefs [
+ {counttomark 2 idiv {y moveto show} repeat}
+ {neg /y exch def counttomark 2 idiv {y moveto show} repeat}
+ {neg moveto {2 index stringwidth pop sub exch div 0 32 4 -1 roll widthshow} repeat}
+ {neg moveto {spacewidth sub 0.0 32 4 -1 roll widthshow} repeat}
+ {counttomark 2 idiv {y moveto show} repeat}
+ {neg setfunnytext}
+] def
+
+/setdecoding {/t decodingdefs 3 -1 roll get bind def} bind def
+
+/w {neg moveto show} bind def
+/m {neg dup /y exch def moveto} bind def
+/done {/lastpage where {pop lastpage} if} def
+
+/f {
+ dup /font exch def findfont exch
+ dup /ptsize exch def scaling div dup /size exch def scalefont setfont
+ linewidth ptsize mul scaling 10 mul div setlinewidth
+ /spacewidth ( ) stringwidth pop def
+} bind def
+
+/changefont {
+ /fontheight exch def
+ /fontslant exch def
+ currentfont [
+ 1 0
+ fontheight ptsize div fontslant sin mul fontslant cos div
+ fontheight ptsize div
+ 0 0
+ ] makefont setfont
+} bind def
+
+/sf {f} bind def
+
+/cf {
+ dup length 2 idiv
+ /entries exch def
+ /chtab exch def
+ /newencoding exch def
+ /newfont exch def
+
+ findfont dup length 1 add dict
+ /newdict exch def
+ {1 index /FID ne {newdict 3 1 roll put}{pop pop} ifelse} forall
+
+ newencoding type /arraytype eq {newdict /Encoding newencoding put} if
+
+ newdict /Metrics entries dict put
+ newdict /Metrics get
+ begin
+ chtab aload pop
+ 1 1 entries {pop def} for
+ newfont newdict definefont pop
+ end
+} bind def
+
+%
+% A few arrays used to adjust reference points and character widths in some
+% of the printer resident fonts. If square roots are too high try changing
+% the lines describing /radical and /radicalex to,
+%
+% /radical [0 -75 550 0]
+% /radicalex [-50 -75 500 0]
+%
+% Move braceleftbt a bit - default PostScript character is off a bit.
+%
+
+/Sdefs [
+ /bracketlefttp [201 500]
+ /bracketleftbt [201 500]
+ /bracketrighttp [-81 380]
+ /bracketrightbt [-83 380]
+ /braceleftbt [203 490]
+ /bracketrightex [220 -125 500 0]
+ /radical [0 0 550 0]
+ /radicalex [-50 0 500 0]
+ /parenleftex [-20 -170 0 0]
+ /integral [100 -50 500 0]
+ /infinity [10 -75 730 0]
+] def
+
+/S1defs [
+ /underscore [0 80 500 0]
+ /endash [7 90 650 0]
+] def
+%
+% Tries to round clipping path dimensions, as stored in array pagebbox, so they
+% match one of the known sizes in the papersizes array. Lower left coordinates
+% are always set to 0.
+%
+
+/roundpagebbox {
+ 7 dict begin
+ /papersizes [8.5 inch 11 inch 14 inch 17 inch] def
+
+ /mappapersize {
+ /val exch def
+ /slop .5 inch def
+ /diff slop def
+ /j 0 def
+ 0 1 papersizes length 1 sub {
+ /i exch def
+ papersizes i get val sub abs
+ dup diff le {/diff exch def /j i def} {pop} ifelse
+ } for
+ diff slop lt {papersizes j get} {val} ifelse
+ } def
+
+ pagebbox 0 0 put
+ pagebbox 1 0 put
+ pagebbox dup 2 get mappapersize 2 exch put
+ pagebbox dup 3 get mappapersize 3 exch put
+ end
+} bind def
+
+%%EndProlog
+%%BeginSetup
+mark
+%
+% Encoding vector and redefinition of findfont for the ISO Latin1 standard.
+% The 18 characters missing from ROM based fonts on older printers are noted
+% below.
+%
+
+/ISOLatin1Encoding [
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /space
+ /exclam
+ /quotedbl
+ /numbersign
+ /dollar
+ /percent
+ /ampersand
+ /quoteright
+ /parenleft
+ /parenright
+ /asterisk
+ /plus
+ /comma
+ /minus
+ /period
+ /slash
+ /zero
+ /one
+ /two
+ /three
+ /four
+ /five
+ /six
+ /seven
+ /eight
+ /nine
+ /colon
+ /semicolon
+ /less
+ /equal
+ /greater
+ /question
+ /at
+ /A
+ /B
+ /C
+ /D
+ /E
+ /F
+ /G
+ /H
+ /I
+ /J
+ /K
+ /L
+ /M
+ /N
+ /O
+ /P
+ /Q
+ /R
+ /S
+ /T
+ /U
+ /V
+ /W
+ /X
+ /Y
+ /Z
+ /bracketleft
+ /backslash
+ /bracketright
+ /asciicircum
+ /underscore
+ /quoteleft
+ /a
+ /b
+ /c
+ /d
+ /e
+ /f
+ /g
+ /h
+ /i
+ /j
+ /k
+ /l
+ /m
+ /n
+ /o
+ /p
+ /q
+ /r
+ /s
+ /t
+ /u
+ /v
+ /w
+ /x
+ /y
+ /z
+ /braceleft
+ /bar
+ /braceright
+ /asciitilde
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /.notdef
+ /dotlessi
+ /grave
+ /acute
+ /circumflex
+ /tilde
+ /macron
+ /breve
+ /dotaccent
+ /dieresis
+ /.notdef
+ /ring
+ /cedilla
+ /.notdef
+ /hungarumlaut
+ /ogonek
+ /caron
+ /space
+ /exclamdown
+ /cent
+ /sterling
+ /currency
+ /yen
+ /brokenbar % missing
+ /section
+ /dieresis
+ /copyright
+ /ordfeminine
+ /guillemotleft
+ /logicalnot
+ /hyphen
+ /registered
+ /macron
+ /degree % missing
+ /plusminus % missing
+ /twosuperior % missing
+ /threesuperior % missing
+ /acute
+ /mu % missing
+ /paragraph
+ /periodcentered
+ /cedilla
+ /onesuperior % missing
+ /ordmasculine
+ /guillemotright
+ /onequarter % missing
+ /onehalf % missing
+ /threequarters % missing
+ /questiondown
+ /Agrave
+ /Aacute
+ /Acircumflex
+ /Atilde
+ /Adieresis
+ /Aring
+ /AE
+ /Ccedilla
+ /Egrave
+ /Eacute
+ /Ecircumflex
+ /Edieresis
+ /Igrave
+ /Iacute
+ /Icircumflex
+ /Idieresis
+ /Eth % missing
+ /Ntilde
+ /Ograve
+ /Oacute
+ /Ocircumflex
+ /Otilde
+ /Odieresis
+ /multiply % missing
+ /Oslash
+ /Ugrave
+ /Uacute
+ /Ucircumflex
+ /Udieresis
+ /Yacute % missing
+ /Thorn % missing
+ /germandbls
+ /agrave
+ /aacute
+ /acircumflex
+ /atilde
+ /adieresis
+ /aring
+ /ae
+ /ccedilla
+ /egrave
+ /eacute
+ /ecircumflex
+ /edieresis
+ /igrave
+ /iacute
+ /icircumflex
+ /idieresis
+ /eth % missing
+ /ntilde
+ /ograve
+ /oacute
+ /ocircumflex
+ /otilde
+ /odieresis
+ /divide % missing
+ /oslash
+ /ugrave
+ /uacute
+ /ucircumflex
+ /udieresis
+ /yacute % missing
+ /thorn % missing
+ /ydieresis
+] def
+
+/NewFontDirectory FontDirectory maxlength dict def
+
+%
+% Apparently no guarantee findfont is defined in systemdict so the obvious
+%
+% systemdict /findfont get exec
+%
+% can generate an error. So far the only exception is a VT600 (version 48.0).
+%
+
+userdict /@RealFindfont known not {
+ userdict begin
+ /@RealFindfont systemdict begin /findfont load end def
+ end
+} if
+
+/findfont {
+ dup NewFontDirectory exch known not {
+ dup
+ %dup systemdict /findfont get exec % not always in systemdict
+ dup userdict /@RealFindfont get exec
+ dup /Encoding get StandardEncoding eq {
+ dup length dict begin
+ {1 index /FID ne {def}{pop pop} ifelse} forall
+ /Encoding ISOLatin1Encoding def
+ currentdict
+ end
+ /DummyFontName exch definefont
+ } if
+ NewFontDirectory 3 1 roll put
+ } if
+ NewFontDirectory exch get
+} bind def
+
+%%Patch from lp
+%%EndPatch from lp
+
+setup
+%%EndSetup
+%%Page: 1 1
+/saveobj save def
+mark
+1 pagesetup
+12 /Times-Bold f
+(Connecting up the) 1322 1220 w
+(Arm) 2293 1220 w
+(Evaluator) 2562 1220 w
+(7t) 3106 1220 w
+(and Downloading Code) 3236 1220 w
+10 /Times-Italic f
+(Nigel Roles) 2648 1404 w
+(Vita Nuova Holdings Limited) 2292 1556 w
+(10th November 2000) 2461 1676 w
+10 /Times-Bold f
+(Introduction) 720 1924 w
+10 /Times-Roman f
+(This is just a quick note on how to download code to the Evaluator and run it.) 970 2082 w
+10 /Times-Bold f
+(Health Warning) 720 2330 w
+10 /Times-Roman f
+(I) 970 2488 w
+10 /Times-Italic f
+(think) 1033 2488 w
+10 /Times-Roman f
+(the) 1263 2488 w
+(interrupt) 1415 2488 w
+(and) 1789 2488 w
+(exception) 1963 2488 w
+(handling) 2382 2488 w
+(is) 2763 2488 w
+(OK;) 2861 2488 w
+(it's) 3064 2488 w
+(just) 3223 2488 w
+(that) 3399 2488 w
+(I) 3580 2488 w
+(had) 3644 2488 w
+(problems) 3819 2488 w
+(with) 4222 2488 w
+(supporting) 4431 2488 w
+(two) 4890 2488 w
+(serial ports, interrupt driven at the same time. You have been warned.) 720 2608 w
+10 /Times-Bold f
+(Connecting it up) 720 2856 w
+10 /Times-Roman f
+(The) 970 3014 w
+(board) 1156 3014 w
+(has) 1414 3014 w
+(Arm's) 1578 3014 w
+(standard) 1864 3014 w
+(Angel) 2233 3014 w
+(debugger) 2508 3014 w
+(monitor) 2910 3014 w
+(on) 3258 3014 w
+(board.) 3389 3014 w
+(You) 3672 3014 w
+(can) 3875 3014 w
+(read) 4044 3014 w
+(all) 4246 3014 w
+(about) 4377 3014 w
+(this) 4631 3014 w
+(in) 4808 3014 w
+(the) 4918 3014 w
+(documentation.) 720 3134 w
+(Whether) 1365 3134 w
+(you) 1734 3134 w
+(go to the trouble of installing the Windows tools is up to you, but do read how) 1910 3134 w
+(to operate the monitor.) 720 3254 w
+(Anyhow,) 970 3412 w
+(the) 1370 3412 w
+(board) 1523 3412 w
+(has) 1781 3412 w
+(two) 1945 3412 w
+(serial) 2126 3412 w
+(ports.) 2373 3412 w
+(The) 2629 3412 w
+(one) 2815 3412 w
+(nearest) 2990 3412 w
+(the) 3304 3412 w
+(LEDs) 3458 3412 w
+(is) 3723 3412 w
+(the) 3822 3412 w
+(debug) 3976 3412 w
+(and) 4252 3412 w
+(download) 4428 3412 w
+(port.) 4854 3412 w
+(The other is the console port when running Inferno.) 720 3532 w
+(You) 970 3690 w
+(only) 1172 3690 w
+(get) 1380 3690 w
+(one) 1532 3690 w
+(cable,) 1706 3690 w
+(so) 1971 3690 w
+(beg) 2090 3690 w
+(borrow) 2264 3690 w
+(or) 2583 3690 w
+(steal) 2697 3690 w
+(another) 2911 3690 w
+(cable.) 3241 3690 w
+(These) 3507 3690 w
+(are) 3776 3690 w
+(straight\255through) 3928 3690 w
+(9) 4603 3690 w
+(way) 4684 3690 w
+(to) 4881 3690 w
+(9) 4990 3690 w
+(way male to female cables. I bought a Belkin one from Staples at some horrid price.) 720 3810 w
+(Connect) 970 3968 w
+(both) 1336 3968 w
+(up) 1547 3968 w
+(to) 1680 3968 w
+(the) 1791 3968 w
+(back) 1946 3968 w
+(of) 2168 3968 w
+(your) 2285 3968 w
+(Plan) 2502 3968 w
+(9) 2714 3968 w
+(machine,) 2798 3968 w
+(and) 3195 3968 w
+(start) 3373 3968 w
+(terminal) 3579 3968 w
+(emulators) 3946 3968 w
+(on) 4374 3968 w
+(both.) 4508 3968 w
+(For) 4745 3968 w
+(the) 4918 3968 w
+(debug) 720 4088 w
+(and) 990 4088 w
+(download) 1160 4088 w
+(you) 1580 4088 w
+(need) 1756 4088 w
+(to) 1970 4088 w
+(run) 2074 4088 w
+(a specially modified version of) 2233 4088 w
+10 /Courier f
+(vt\(1\)) 3495 4088 w
+10 /Times-Roman f
+(which responds to the peculiar) 3820 4088 w
+(answer) 720 4208 w
+(back) 1030 4208 w
+(sequence) 1246 4208 w
+(that) 1639 4208 w
+(the) 1817 4208 w
+(Arm) 1967 4208 w
+(monitor) 2179 4208 w
+(has) 2525 4208 w
+(decided) 2687 4208 w
+(is) 3026 4208 w
+(appropriate) 3122 4208 w
+(for) 3605 4208 w
+(it) 3750 4208 w
+(to) 3835 4208 w
+(sense) 3942 4208 w
+(baud) 4187 4208 w
+(rate.) 4410 4208 w
+(As) 4638 4208 w
+(it) 4778 4208 w
+(hap\255) 4863 4208 w
+(pens,) 720 4328 w
+(I) 968 4328 w
+(have) 1041 4328 w
+(modified) 1269 4328 w
+(the) 1670 4328 w
+(version) 1832 4328 w
+(on) 2166 4328 w
+10 /Courier f
+(doppio) 2306 4328 w
+10 /Times-Roman f
+(.) 2666 4328 w
+(It) 2756 4328 w
+(should) 2856 4328 w
+(be) 3162 4328 w
+(possible) 3295 4328 w
+(via) 3662 4328 w
+(monitor) 3823 4328 w
+(commands) 4179 4328 w
+(to) 4651 4328 w
+(set) 4768 4328 w
+(the) 4918 4328 w
+(default) 720 4448 w
+(baud) 1031 4448 w
+(rate) 1259 4448 w
+(of) 1442 4448 w
+(the) 1559 4448 w
+(board) 1715 4448 w
+(to) 1976 4448 w
+(whatever) 2088 4448 w
+(you) 2487 4448 w
+(like.) 2671 4448 w
+(I) 2880 4448 w
+(lost) 2947 4448 w
+(patience) 3126 4448 w
+(after) 3492 4448 w
+(about) 3708 4448 w
+(a) 3964 4448 w
+(day,) 4042 4448 w
+(and) 4245 4448 w
+(hacked) 4423 4448 w
+10 /Courier f
+(vt\(1\)) 4740 4448 w
+10 /Times-Roman f
+(instead.) 720 4568 w
+(It) 1057 4568 w
+(was) 1146 4568 w
+(easier.) 1329 4568 w
+(So,) 1614 4568 w
+(the) 1773 4568 w
+(board) 1923 4568 w
+(will) 2178 4568 w
+(auto) 2362 4568 w
+(sense) 2562 4568 w
+(baud) 2806 4568 w
+(rate.) 3028 4568 w
+(The) 3230 4568 w
+(highest) 3413 4568 w
+(baud) 3730 4568 w
+(rate) 3952 4568 w
+(which) 4129 4568 w
+(is) 4401 4568 w
+(actually) 4496 4568 w
+(valid) 4840 4568 w
+(and hence will talk to Plan 9 is 57600. So the commands to configure the download window are) 720 4688 w
+9 /Courier-Bold f
+(term%) 1008 4852 w
+9 /Courier f
+(cd /usr/inferno/os/ks32) 1332 4852 w
+9 /Courier-Bold f
+(term%) 1008 4952 w
+9 /Courier f
+(vt) 1332 4952 w
+9 /Courier-Bold f
+(term%) 1008 5052 w
+9 /Courier f
+(con \255R \255b 57600 /dev/eia0) 1332 5052 w
+10 /Times-Roman f
+(You) 720 5236 w
+(can) 926 5236 w
+(choose) 1098 5236 w
+(other) 1409 5236 w
+(speeds,) 1648 5236 w
+(but) 1973 5236 w
+(57600) 2135 5236 w
+(is) 2419 5236 w
+(the) 2520 5236 w
+(maximum.) 2676 5236 w
+(For) 3141 5236 w
+(the) 3314 5236 w
+(console) 3470 5236 w
+(port,) 3809 5236 w
+10 /Courier f
+(vt\(1\)) 4029 5236 w
+10 /Times-Roman f
+(is) 4363 5236 w
+(not) 4465 5236 w
+(necessary.) 4628 5236 w
+(The baud rate is fixed in) 720 5356 w
+10 /Courier f
+(main.c) 1718 5356 w
+10 /Times-Roman f
+(at 57600, so the same) 2103 5356 w
+10 /Courier f
+(con) 2991 5356 w
+10 /Times-Roman f
+(command is appropriate.) 3196 5356 w
+(Now) 970 5514 w
+(plug) 1195 5514 w
+(in) 1404 5514 w
+(the) 1513 5514 w
+(power) 1666 5514 w
+(to) 1946 5514 w
+(the) 2055 5514 w
+(board.) 2208 5514 w
+(You) 2491 5514 w
+(should) 2694 5514 w
+(see) 2992 5514 w
+(the) 3150 5514 w
+(LEDs) 3303 5514 w
+(flick) 3567 5514 w
+(for) 3781 5514 w
+(bit,) 3928 5514 w
+(and) 4091 5514 w
+(then) 4267 5514 w
+(the) 4471 5514 w
+(7) 4625 5514 w
+(segment) 4707 5514 w
+(one shows 11. The download window should show) 720 5634 w
+9 /Courier-Bold f
+(Arm Evaluator7T Boot Monitor PreRelease 1.00) 1008 5798 w
+(Boot:) 1008 5898 w
+10 /Times-Roman f
+(Pressing) 720 6082 w
+(the) 1088 6082 w
+(reset) 1239 6082 w
+(button) 1456 6082 w
+(\(nearer) 1741 6082 w
+(of) 2051 6082 w
+(the) 2163 6082 w
+(two) 2314 6082 w
+(buttons) 2493 6082 w
+(to) 2817 6082 w
+(the) 2924 6082 w
+(CPU\),) 3075 6082 w
+(should) 3357 6082 w
+(cause) 3653 6082 w
+(the) 3903 6082 w
+(same) 4055 6082 w
+(message) 4290 6082 w
+(to) 4658 6082 w
+(be) 4766 6082 w
+(dis\255) 4890 6082 w
+(played.) 720 6202 w
+10 /Times-Bold f
+(Building the code) 720 6450 w
+10 /Courier f
+(mk\(1\)) 970 6608 w
+10 /Times-Roman f
+(in directory) 1295 6608 w
+10 /Courier f
+(/usr/inferno/os/ks32) 1783 6608 w
+10 /Times-Roman f
+(should build the code. You may need to do) 3008 6608 w
+9 /Courier f
+(bind \255b /usr/inferno/Plan9/386/bin /bin) 1008 6772 w
+10 /Times-Roman f
+(to get access to the compilers and tools.) 720 6956 w
+(The) 2357 6956 w
+(makes) 745 7076 w
+(an) 1026 7076 w
+(executable,) 1146 7076 w
+(converts) 1623 7076 w
+(it) 1987 7076 w
+(to) 2069 7076 w
+(the) 2173 7076 w
+(right) 2321 7076 w
+(format,) 2536 7076 w
+(and) 2853 7076 w
+10 /Courier f
+(uuencode) 3024 7076 w
+10 /Times-Roman f
+('s) 3504 7076 w
+(it) 3603 7076 w
+(to) 3686 7076 w
+(create) 3791 7076 w
+10 /Courier f
+(ievaluator7t.txt) 4055 7076 w
+10 /Times-Roman f
+(.) 5015 7076 w
+(Note) 720 7196 w
+(that) 1059 7196 w
+(as) 1354 7196 w
+(shipped,) 1582 7196 w
+(the) 2063 7196 w
+(configuration) 2330 7196 w
+(file) 3013 7196 w
+(\() 3291 7196 w
+10 /Courier f
+(evaluator7t) 3324 7196 w
+10 /Times-Roman f
+(\)) 3984 7196 w
+(includes) 4162 7196 w
+(the) 4640 7196 w
+(file) 4907 7196 w
+(November 22, 1900) 2482 7560 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 1 1
+%%Page: 2 2
+/saveobj save def
+mark
+2 pagesetup
+10 /Times-Roman f
+(\255 2 \255) 2797 480 w
+10 /Courier f
+(/usr/inferno/usr/nigel/cb.dis) 720 840 w
+10 /Times-Roman f
+(as) 2504 840 w
+(the) 2631 840 w
+(main) 2797 840 w
+(application.) 3041 840 w
+(This) 3554 840 w
+(is) 3776 840 w
+(John) 3887 840 w
+(Powers') 4121 840 w
+(Crackerbarrel) 4493 840 w
+(program which I used as a benchmark.) 720 960 w
+10 /Times-Bold f
+(Downloading the code) 720 1200 w
+10 /Times-Roman f
+(To download to the Evaluator type the command) 970 1356 w
+9 /Courier-Bold f
+(Boot:) 1008 1516 w
+9 /Courier f
+(download) 1332 1516 w
+9 /Courier-Bold f
+(Ready to download. Use 'transmit' option on terminal emulator to download file.) 1008 1616 w
+10 /Times-Roman f
+(break back to the) 720 1796 w
+10 /Courier f
+(con\(1\)) 1429 1796 w
+10 /Times-Roman f
+(command prompt with Control\255\\ and type the following command) 1814 1796 w
+9 /Courier-Bold f
+(>>>) 1008 1956 w
+9 /Courier f
+(!cat ievaluator7t.txt) 1224 1956 w
+10 /Times-Roman f
+(As a shorthand, you may instead type) 720 2136 w
+9 /Courier-Bold f
+(>>>) 1008 2296 w
+9 /Courier f
+(!squirt) 1224 2296 w
+10 /Times-Roman f
+(The) 970 2476 w
+(red) 1152 2476 w
+(LED) 1306 2476 w
+(should) 1527 2476 w
+(light) 1821 2476 w
+(indicating) 2032 2476 w
+(download.) 2459 2476 w
+(After) 2905 2476 w
+(a) 3142 2476 w
+(couple) 3214 2476 w
+(of) 3508 2476 w
+(minutes) 3644 2476 w
+(the) 3989 2476 w
+(light) 4139 2476 w
+(goes) 4351 2476 w
+(out) 4562 2476 w
+(and) 4718 2476 w
+(you) 4890 2476 w
+(see) 720 2596 w
+9 /Courier-Bold f
+(Loaded file ievaluator7t.aif at address 00008000, size=254200) 1008 2756 w
+(Boot:) 1008 2856 w
+10 /Times-Roman f
+(You will type) 720 3036 w
+9 /Courier-Bold f
+(Boot:) 1008 3196 w
+9 /Courier f
+(gos 8080) 1332 3196 w
+10 /Times-Roman f
+(to run the code at address 0x8080. This) 720 3376 w
+(should) 2316 3376 w
+(cause) 2609 3376 w
+(Inferno) 2856 3376 w
+(to) 3175 3376 w
+(boot) 3279 3376 w
+(and) 3483 3376 w
+(write) 3653 3376 w
+(stuff) 3884 3376 w
+(on) 4093 3376 w
+(the) 4219 3376 w
+(console) 4367 3376 w
+(port) 4698 3376 w
+(\(i.e.) 4885 3376 w
+(the other window\).) 720 3496 w
+10 /Times-Bold f
+(Useful Stuff) 720 3736 w
+10 /Times-Roman f
+(There is some useful debugging code in) 970 3892 w
+10 /Courier f
+(archevaluator7t.c) 2587 3892 w
+10 /Times-Roman f
+(and other places.) 3632 3892 w
+10 /Courier f
+(setled7ascii\(\)) 720 4048 w
+10 /Times-Roman f
+(This) 970 4168 w
+(function) 1177 4168 w
+(takes) 1539 4168 w
+(a) 1773 4168 w
+(single) 1846 4168 w
+(character,) 2115 4168 w
+(and) 2534 4168 w
+(attempts) 2708 4168 w
+(to) 3077 4168 w
+(put) 3185 4168 w
+(it) 3343 4168 w
+(on) 3429 4168 w
+(the) 3559 4168 w
+(LED.) 3711 4168 w
+(Clearly) 3960 4168 w
+(you) 4284 4168 w
+(won't) 4464 4168 w
+(get) 4727 4168 w
+(M's) 4879 4168 w
+(or N's. Read the source.) 970 4288 w
+10 /Courier f
+(iprint\(\)) 720 4444 w
+10 /Times-Roman f
+(Prints on the debug and download port.) 970 4564 w
+(November 22, 1900) 2482 7560 w
+cleartomark
+showpage
+saveobj restore
+%%EndPage: 2 2
+%%Trailer
+done
+%%DocumentFonts: Times-Roman Times-Italic Times-Bold Courier Courier-Bold
+%%Pages: 2
diff --git a/os/ks32/evaluator7t b/os/ks32/evaluator7t
new file mode 100644
index 00000000..93723933
--- /dev/null
+++ b/os/ks32/evaluator7t
@@ -0,0 +1,110 @@
+dev
+ root
+ cons archevaluator7t noscreen not
+# kbd
+# gpio
+# mnt
+# pipe
+ prog
+# srv
+# draw
+ uart
+# sapcm
+# flash
+# touch
+# ip bootp ip ipv6 ipaux iproute arp netlog ptclbsum iprouter plan9 nullmedium pktmedium
+# ether netif netaux ethermedium
+# ata
+
+ip
+# il
+# tcp
+# udp
+# rudp
+# igmp
+# ipifc
+# icmp
+# icmp6
+# ipmux
+
+lib
+ interp
+# tk
+# image
+# memlayer
+# memimage
+# keyring
+ sec
+# mp
+ kern
+
+mod
+ sys
+# draw
+# tk
+# keyring
+
+port
+ alarm
+ alloc
+ allocb
+ chan
+ dev
+ dial
+ dis
+ discall
+ exception
+ exportfs
+ inferno
+ latin1
+ nocache
+ nodynld
+ noenv
+ parse
+ pgrp
+ print
+ proc
+ qio
+ qlock
+ random
+ sysfile
+ taslock
+ xalloc
+
+link
+# lcd
+# ether589
+# ethertdk
+# pppmedium ppp compress
+
+code
+ int main_pool_pcnt = 60;
+ int heap_pool_pcnt = 40;
+ int image_pool_pcnt = 0;
+ int cflag = 0;
+
+ int consoleprint = 1;
+ int redirectconsole = 1;
+ char debug_keys = 1;
+ int panicreset = 0;
+ void pseudoRandomBytes(uchar *a, int n){memset(a, 0, n);}
+ int srvf2c(){return -1;} /* dummy */
+ Type *Trdchan;
+ Type *Twrchan;
+
+init
+ evalinit
+
+root
+ /chan
+ /dev
+ /dis
+# /usr/jrf/limbo/cb.dis
+# /usr/jrf/work/dl/test/test.dis
+# /o/abc.o
+ /dis/sh.dis
+ /net
+ /prog
+ /osinit.dis
+ /n/remote
+
diff --git a/os/ks32/fns.h b/os/ks32/fns.h
new file mode 100644
index 00000000..581590ab
--- /dev/null
+++ b/os/ks32/fns.h
@@ -0,0 +1,145 @@
+#include "../port/portfns.h"
+
+ulong aifinit(uchar *aifarr);
+void aamloop(int);
+void archconfinit(void);
+int archflash12v(int);
+void archflashwp(int);
+void archreboot(void);
+void archreset(void);
+void catchDref(char *s, void *v);
+void catchDval(char *s, ulong v, ulong m);
+void catchIref(char *s, void *a);
+void cisread(int slotno, void (*f)(int, uchar *));
+int cistrcmp(char *, char *);
+void cleanDentry(void *);
+void clockcheck(void);
+void clockinit(void);
+void clockpoll(void);
+#define coherence() /* nothing to do for cache coherence for uniprocessor */
+uint cpsrr(void);
+void cursorhide(void);
+void cursorunhide(void);
+void dmasetup(int channel, int device, int direction, int endianess);
+void dmastart(int channel, void *b1, int b1siz, void *b2, int b2siz);
+int dmacontinue(int channel, void *buf, int bufsize);
+void dmastop(int channel);
+int dmaerror(int channel);
+void dmareset(void);
+void drainWBuffer(void);
+void dumplongs(char *, ulong *, int);
+void dumpregs(Ureg* ureg);
+void dumpstk(ulong *);
+void flushDcache(void);
+void flushIDC(void);
+void flushIcache(void);
+void flushDentry(void *);
+void flushTLB(void);
+int fpiarm(Ureg*);
+void fpinit(void);
+ulong getcallerpc(void*);
+void gotopc(ulong);
+#define idlehands() /* nothing to do in the runproc */
+void intrenable(int, void (*)(Ureg*, void*), void*, int);
+void intrclear(int, int);
+void intrmask(int, int);
+void intrunmask(int, int);
+int iprint(char *fmt, ...);
+void installprof(void (*)(Ureg *, int));
+int isvalid_va(void*);
+void kbdinit(void);
+void lcd_setbacklight(int);
+void lcd_setbrightness(ushort);
+void lcd_setcontrast(ushort);
+void lcd_sethz(int);
+void lights(ulong);
+void setled7ascii(char);
+void links(void);
+ulong mcpgettfreq(void);
+void mcpinit(void);
+void mcpsettfreq(ulong tfreq);
+void mcpspeaker(int, int);
+void mcptelecomsetup(ulong hz, uchar adm, uchar xint, uchar rint);
+ushort mcpadcread(int ts);
+void mcptouchsetup(int ts);
+void mcptouchintrenable(void);
+void mcptouchintrdisable(void);
+void mcpgpiowrite(ushort mask, ushort data);
+void mcpgpiosetdir(ushort mask, ushort dir);
+ushort mcpgpioread(void);
+void mmuinit(void);
+ulong mmuctlregr(void);
+void mmuctlregw(ulong);
+ulong mmuregr(int);
+void mmuregw(int, ulong);
+void mmureset(void);
+void mouseinit(void);
+void nowriteSeg(void *, void *);
+void* pa2va(ulong);
+int pcmpin(int slot, int type);
+void pcmpower(int slotno, int on);
+int pcmpowered(int slotno);
+void pcmsetvcc(int slotno, int vcc);
+void pcmsetvpp(int slotno, int vpp);
+int pcmspecial(char *idstr, ISAConf *isa);
+void pcmspecialclose(int slotno);
+void pcmintrenable(int, void (*)(Ureg*, void*), void*);
+void putcsr(ulong);
+#define procsave(p)
+#define procrestore(p)
+void remaplomem(void);
+long rtctime(void);
+void* screenalloc(ulong);
+void screeninit(void);
+void screenputs(char*, int);
+int segflush(void*, ulong);
+void setpanic(void);
+void setr13(int, void*);
+uint spsrr(void);
+void touchrawcal(int q, int px, int py);
+int touchcalibrate(void);
+int touchreadxy(int *fx, int *fy);
+int touchpressed(void);
+int touchreleased(void);
+void touchsetrawcal(int q, int n, int v);
+int touchgetrawcal(int q, int n);
+void trapinit(void);
+void trapspecial(int (*)(Ureg *, uint));
+int uartprint(char*, ...);
+void uartspecial(int, int, char, Queue**, Queue**, int (*)(Queue*, int));
+void umbfree(ulong addr, int size);
+ulong umbmalloc(ulong addr, int size, int align);
+void umbscan(void);
+ulong va2pa(void*);
+void vectors(void);
+void vtable(void);
+#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
+int wasbusy(int);
+void _vfiqcall(void);
+void _virqcall(void);
+void _vundcall(void);
+void _vsvccall(void);
+void _vpabcall(void);
+void _vdabcall(void);
+void vgaputc(char);
+void writeBackBDC(void);
+void writeBackDC(void);
+
+#define KADDR(p) ((void *) p)
+#define PADDR(v) va2pa((void*)(v))
+
+// #define timer_start() (*OSCR)
+// #define timer_ticks(t) (*OSCR - (ulong)(t))
+#define DELAY(ms) timer_delay(MS2TMR(ms))
+#define MICRODELAY(us) timer_delay(US2TMR(us))
+ulong timer_start(void);
+ulong timer_ticks(ulong);
+int timer_devwait(ulong *adr, ulong mask, ulong val, int ost);
+void timer_setwatchdog(int ost);
+void timer_delay(int ost);
+ulong ms2tmr(int ms);
+int tmr2ms(ulong t);
+void delay(int ms);
+ulong us2tmr(int us);
+int tmr2us(ulong t);
+void microdelay(int us);
diff --git a/os/ks32/fpi.h b/os/ks32/fpi.h
new file mode 100644
index 00000000..dfb9b1df
--- /dev/null
+++ b/os/ks32/fpi.h
@@ -0,0 +1,61 @@
+typedef long Word;
+typedef unsigned long Single;
+typedef struct {
+ unsigned long h;
+ unsigned long l;
+} Double;
+
+enum {
+ FractBits = 28,
+ CarryBit = 0x10000000,
+ HiddenBit = 0x08000000,
+ MsBit = HiddenBit,
+ NGuardBits = 3,
+ GuardMask = 0x07,
+ LsBit = (1<<NGuardBits),
+
+ SingleExpBias = 127,
+ SingleExpMax = 255,
+ DoubleExpBias = 1023,
+ DoubleExpMax = 2047,
+
+ ExpBias = DoubleExpBias,
+ ExpInfinity = DoubleExpMax,
+};
+
+typedef struct {
+ unsigned char s;
+ short e;
+ long l; /* 0000FFFFFFFFFFFFFFFFFFFFFFFFFGGG */
+ long h; /* 0000HFFFFFFFFFFFFFFFFFFFFFFFFFFF */
+} Internal;
+
+#define IsWeird(n) ((n)->e >= ExpInfinity)
+#define IsInfinity(n) (IsWeird(n) && (n)->h == HiddenBit && (n)->l == 0)
+#define SetInfinity(n) ((n)->e = ExpInfinity, (n)->h = HiddenBit, (n)->l = 0)
+#define IsNaN(n) (IsWeird(n) && (((n)->h & ~HiddenBit) || (n)->l))
+#define SetQNaN(n) ((n)->s = 0, (n)->e = ExpInfinity, \
+ (n)->h = HiddenBit|(LsBit<<1), (n)->l = 0)
+#define IsZero(n) ((n)->e == 1 && (n)->h == 0 && (n)->l == 0)
+#define SetZero(n) ((n)->e = 1, (n)->h = 0, (n)->l = 0)
+
+/*
+ * fpi.c
+ */
+extern void fpiround(Internal *);
+extern void fpiadd(Internal *, Internal *, Internal *);
+extern void fpisub(Internal *, Internal *, Internal *);
+extern void fpimul(Internal *, Internal *, Internal *);
+extern void fpidiv(Internal *, Internal *, Internal *);
+extern int fpicmp(Internal *, Internal *);
+extern void fpinormalise(Internal*);
+
+/*
+ * fpimem.c
+ */
+extern void fpis2i(Internal *, void *);
+extern void fpid2i(Internal *, void *);
+extern void fpiw2i(Internal *, void *);
+extern void fpii2s(void *, Internal *);
+extern void fpii2d(void *, Internal *);
+extern void fpii2w(Word *, Internal *);
diff --git a/os/ks32/fpiarm.c b/os/ks32/fpiarm.c
new file mode 100644
index 00000000..717965b3
--- /dev/null
+++ b/os/ks32/fpiarm.c
@@ -0,0 +1,483 @@
+/*
+ * this doesn't attempt to implement ARM floating-point properties
+ * that aren't visible in the Inferno environment.
+ * all arithmetic is done in double precision.
+ * the FP trap status isn't updated.
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#include "ureg.h"
+
+#include "fpi.h"
+
+// #define R13OK undef this if correct kernel r13 isn't in Ureg; check calculation in fpiarm below
+
+#define REG(x) (*(long*)(((char*)ur)+roff[(x)]))
+#define FPENV (*ufp)
+#define FR(x) (*(Internal*)ufp->regs[(x)&7])
+
+/* BUG: check fetch (not worthwhile in Inferno) */
+#define getubyte(a) (*(uchar*)(a))
+#define getuword(a) (*(ushort*)(a))
+#define getulong(a) (*(ulong*)(a))
+
+typedef struct FP2 FP2;
+typedef struct FP1 FP1;
+
+struct FP2 {
+ char* name;
+ void (*f)(Internal, Internal, Internal*);
+};
+
+struct FP1 {
+ char* name;
+ void (*f)(Internal*, Internal*);
+};
+
+enum {
+ N = 1<<31,
+ Z = 1<<30,
+ C = 1<<29,
+ V = 1<<28,
+ REGPC = 15,
+};
+
+int fpemudebug = 0;
+
+#undef OFR
+#define OFR(X) ((ulong)&((Ureg*)0)->X)
+
+static int roff[] = {
+ OFR(r0), OFR(r1), OFR(r2), OFR(r3),
+ OFR(r4), OFR(r5), OFR(r6), OFR(r7),
+ OFR(r8), OFR(r9), OFR(r10), OFR(r11),
+#ifdef R13OK
+ OFR(r12), OFR(r13), OFR(r14), OFR(pc),
+#else
+ OFR(r12), OFR(type), OFR(r14), OFR(pc),
+#endif
+};
+
+static Internal fpconst[8] = { /* indexed by op&7 */
+ /* s, e, l, h */
+ {0, 0x1, 0x00000000, 0x00000000}, /* 0.0 */
+ {0, 0x3FF, 0x00000000, 0x08000000}, /* 1.0 */
+ {0, 0x400, 0x00000000, 0x08000000}, /* 2.0 */
+ {0, 0x400, 0x00000000, 0x0C000000}, /* 3.0 */
+ {0, 0x401, 0x00000000, 0x08000000}, /* 4.0 */
+ {0, 0x401, 0x00000000, 0x0A000000}, /* 5.0 */
+ {0, 0x3FE, 0x00000000, 0x08000000}, /* 0.5 */
+ {0, 0x402, 0x00000000, 0x0A000000}, /* 10.0 */
+};
+
+/*
+ * arm binary operations
+ */
+
+static void
+fadd(Internal m, Internal n, Internal *d)
+{
+ (m.s == n.s? fpiadd: fpisub)(&m, &n, d);
+}
+
+static void
+fsub(Internal m, Internal n, Internal *d)
+{
+ m.s ^= 1;
+ (m.s == n.s? fpiadd: fpisub)(&m, &n, d);
+}
+
+static void
+fsubr(Internal m, Internal n, Internal *d)
+{
+ n.s ^= 1;
+ (n.s == m.s? fpiadd: fpisub)(&n, &m, d);
+}
+
+static void
+fmul(Internal m, Internal n, Internal *d)
+{
+ fpimul(&m, &n, d);
+}
+
+static void
+fdiv(Internal m, Internal n, Internal *d)
+{
+ fpidiv(&m, &n, d);
+}
+
+static void
+fdivr(Internal m, Internal n, Internal *d)
+{
+ fpidiv(&n, &m, d);
+}
+
+/*
+ * arm unary operations
+ */
+
+static void
+fmov(Internal *m, Internal *d)
+{
+ *d = *m;
+}
+
+static void
+fmovn(Internal *m, Internal *d)
+{
+ *d = *m;
+ d->s ^= 1;
+}
+
+static void
+fabsf(Internal *m, Internal *d)
+{
+ *d = *m;
+ d->s = 0;
+}
+
+static void
+frnd(Internal *m, Internal *d)
+{
+ short e;
+
+ (m->s? fsub: fadd)(fpconst[6], *m, d);
+ if(IsWeird(d))
+ return;
+ fpiround(d);
+ e = (d->e - ExpBias) + 1;
+ if(e <= 0)
+ SetZero(d);
+ else if(e > FractBits){
+ if(e < 2*FractBits)
+ d->l &= ~((1<<(2*FractBits - e))-1);
+ }else{
+ d->l = 0;
+ if(e < FractBits)
+ d->h &= ~((1<<(FractBits-e))-1);
+ }
+}
+
+static FP1 optab1[16] = { /* Fd := OP Fm */
+[0] {"MOVF", fmov},
+[1] {"NEGF", fmovn},
+[2] {"ABSF", fabsf},
+[3] {"RNDF", frnd},
+[4] {"SQTF", /*fsqt*/0},
+/* LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN all `deprecated' */
+/* URD and NRM aren't implemented */
+};
+
+static FP2 optab2[16] = { /* Fd := Fn OP Fm */
+[0] {"ADDF", fadd},
+[1] {"MULF", fmul},
+[2] {"SUBF", fsub},
+[3] {"RSUBF", fsubr},
+[4] {"DIVF", fdiv},
+[5] {"RDIVF", fdivr},
+/* POW, RPW deprecated */
+[8] {"REMF", /*frem*/0},
+[9] {"FMF", fmul}, /* fast multiply */
+[10] {"FDV", fdiv}, /* fast divide */
+[11] {"FRD", fdivr}, /* fast reverse divide */
+/* POL deprecated */
+};
+
+static ulong
+fcmp(Internal *n, Internal *m)
+{
+ int i;
+
+ if(IsWeird(m) || IsWeird(n)){
+ /* BUG: should trap if not masked */
+ return V|C;
+ }
+ i = fpicmp(n, m);
+ if(i > 0)
+ return C;
+ else if(i == 0)
+ return C|Z;
+ else
+ return N;
+}
+
+static void
+fld(void (*f)(Internal*, void*), int d, ulong ea, int n, FPenv *ufp)
+{
+ void *mem;
+
+ mem = (void*)ea;
+ (*f)(&FR(d), mem);
+ if(fpemudebug)
+ print("MOV%c #%lux, F%d\n", n==8? 'D': 'F', ea, d);
+}
+
+static void
+fst(void (*f)(void*, Internal*), ulong ea, int s, int n, FPenv *ufp)
+{
+ Internal tmp;
+ void *mem;
+
+ mem = (void*)ea;
+ tmp = FR(s);
+ if(fpemudebug)
+ print("MOV%c F%d,#%lux\n", n==8? 'D': 'F', s, ea);
+ (*f)(mem, &tmp);
+}
+
+static int
+condok(int cc, int c)
+{
+ switch(c){
+ case 0: /* Z set */
+ return cc&Z;
+ case 1: /* Z clear */
+ return (cc&Z) == 0;
+ case 2: /* C set */
+ return cc&C;
+ case 3: /* C clear */
+ return (cc&C) == 0;
+ case 4: /* N set */
+ return cc&N;
+ case 5: /* N clear */
+ return (cc&N) == 0;
+ case 6: /* V set */
+ return cc&V;
+ case 7: /* V clear */
+ return (cc&V) == 0;
+ case 8: /* C set and Z clear */
+ return cc&C && (cc&Z) == 0;
+ case 9: /* C clear or Z set */
+ return (cc&C) == 0 || cc&Z;
+ case 10: /* N set and V set, or N clear and V clear */
+ return (~cc&(N|V))==0 || (cc&(N|V)) == 0;
+ case 11: /* N set and V clear, or N clear and V set */
+ return (cc&(N|V))==N || (cc&(N|V))==V;
+ case 12: /* Z clear, and either N set and V set or N clear and V clear */
+ return (cc&Z) == 0 && ((~cc&(N|V))==0 || (cc&(N|V))==0);
+ case 13: /* Z set, or N set and V clear or N clear and V set */
+ return (cc&Z) || (cc&(N|V))==N || (cc&(N|V))==V;
+ case 14: /* always */
+ return 1;
+ case 15: /* never (reserved) */
+ return 0;
+ }
+ return 0; /* not reached */
+}
+
+static void
+unimp(ulong pc, ulong op)
+{
+ char buf[60];
+
+ snprint(buf, sizeof(buf), "sys: fp: pc=%lux unimp fp 0x%.8lux", pc, op);
+ if(fpemudebug)
+ print("FPE: %s\n", buf);
+ error(buf);
+ /* no return */
+}
+
+static void
+fpemu(ulong pc, ulong op, Ureg *ur, FPenv *ufp)
+{
+ int rn, rd, tag, o;
+ long off;
+ ulong ea;
+ Internal tmp, *fm, *fn;
+
+ /* note: would update fault status here if we noted numeric exceptions */
+
+ /*
+ * LDF, STF; 10.1.1
+ */
+ if(((op>>25)&7) == 6){
+ if(op & (1<<22))
+ unimp(pc, op); /* packed or extended */
+ rn = (op>>16)&0xF;
+ off = (op&0xFF)<<2;
+ if((op & (1<<23)) == 0)
+ off = -off;
+ ea = REG(rn);
+ if(rn == REGPC)
+ ea += 8;
+ if(op & (1<<24))
+ ea += off;
+ rd = (op>>12)&7;
+ if(op & (1<<20)){
+ if(op & (1<<15))
+ fld(fpid2i, rd, ea, 8, ufp);
+ else
+ fld(fpis2i, rd, ea, 4, ufp);
+ }else{
+ if(op & (1<<15))
+ fst(fpii2d, ea, rd, 8, ufp);
+ else
+ fst(fpii2s, ea, rd, 4, ufp);
+ }
+ if((op & (1<<24)) == 0)
+ ea += off;
+ if(op & (1<<21))
+ REG(rn) = ea;
+ return;
+ }
+
+ /*
+ * CPRT/transfer, 10.3
+ */
+ if(op & (1<<4)){
+ rd = (op>>12) & 0xF;
+
+ /*
+ * compare, 10.3.1
+ */
+ if(rd == 15 && op & (1<<20)){
+ rn = (op>>16)&7;
+ fn = &FR(rn);
+ if(op & (1<<3)){
+ fm = &fpconst[op&7];
+ tag = 'C';
+ }else{
+ fm = &FR(op&7);
+ tag = 'F';
+ }
+ switch((op>>21)&7){
+ default:
+ unimp(pc, op);
+ case 4: /* CMF: Fn :: Fm */
+ case 6: /* CMFE: Fn :: Fm (with exception) */
+ ur->psr &= ~(N|C|Z|V);
+ ur->psr |= fcmp(fn, fm);
+ break;
+ case 5: /* CNF: Fn :: -Fm */
+ case 7: /* CNFE: Fn :: -Fm (with exception) */
+ tmp = *fm;
+ tmp.s ^= 1;
+ ur->psr &= ~(N|C|Z|V);
+ ur->psr |= fcmp(fn, &tmp);
+ break;
+ }
+ if(fpemudebug)
+ print("CMPF %c%d,F%ld =%x\n", tag, rn, op&7, ur->psr>>28);
+ return;
+ }
+
+ /*
+ * other transfer, 10.3
+ */
+ switch((op>>20)&0xF){
+ default:
+ unimp(pc, op);
+ case 0: /* FLT */
+ rn = (op>>16) & 7;
+ fpiw2i(&FR(rn), &REG(rd));
+ if(fpemudebug)
+ print("MOVW[FD] R%d, F%d\n", rd, rn);
+ break;
+ case 1: /* FIX */
+ if(op & (1<<3))
+ unimp(pc, op);
+ rn = op & 7;
+ tmp = FR(rn);
+ fpii2w(&REG(rd), &tmp);
+ if(fpemudebug)
+ print("MOV[FD]W F%d, R%d =%ld\n", rn, rd, REG(rd));
+ break;
+ case 2: /* FPSR := Rd */
+ FPENV.status = REG(rd);
+ if(fpemudebug)
+ print("MOVW R%d, FPSR\n", rd);
+ break;
+ case 3: /* Rd := FPSR */
+ REG(rd) = FPENV.status;
+ if(fpemudebug)
+ print("MOVW FPSR, R%d\n", rd);
+ break;
+ case 4: /* FPCR := Rd */
+ FPENV.control = REG(rd);
+ if(fpemudebug)
+ print("MOVW R%d, FPCR\n", rd);
+ break;
+ case 5: /* Rd := FPCR */
+ REG(rd) = FPENV.control;
+ if(fpemudebug)
+ print("MOVW FPCR, R%d\n", rd);
+ break;
+ }
+ return;
+ }
+
+ /*
+ * arithmetic
+ */
+
+ if(op & (1<<3)){ /* constant */
+ fm = &fpconst[op&7];
+ tag = 'C';
+ }else{
+ fm = &FR(op&7);
+ tag = 'F';
+ }
+ rd = (op>>12)&7;
+ o = (op>>20)&0xF;
+ if(op & (1<<15)){ /* monadic */
+ FP1 *fp;
+ fp = &optab1[o];
+ if(fp->f == nil)
+ unimp(pc, op);
+ if(fpemudebug)
+ print("%s %c%ld,F%d\n", fp->name, tag, op&7, rd);
+ (*fp->f)(fm, &FR(rd));
+ } else {
+ FP2 *fp;
+ fp = &optab2[o];
+ if(fp->f == nil)
+ unimp(pc, op);
+ rn = (op>>16)&7;
+ if(fpemudebug)
+ print("%s %c%ld,F%d,F%d\n", fp->name, tag, op&7, rn, rd);
+ (*fp->f)(*fm, FR(rn), &FR(rd));
+ }
+}
+
+/*
+ * returns the number of FP instructions emulated
+ */
+int
+fpiarm(Ureg *ur)
+{
+ ulong op, o;
+ FPenv *ufp;
+ int n;
+
+#ifndef R13OK
+/* ur->type = &ur->pc+1; /* calculate kernel sp/R13 and put it here for roff[13] */
+ ur->type = (ulong)(ur + 1);
+#endif
+ if (up == nil)
+ panic("fpiarm not in a process");
+ ufp = &up->env->fpu; /* because all the state is in Osenv, it need not be saved/restored */
+ if(ufp->fpistate != FPACTIVE) {
+ ufp->fpistate = FPACTIVE;
+ ufp->control = 0;
+ ufp->status = (0x01<<28)|(1<<12); /* software emulation, alternative C flag */
+ for(n = 0; n < 8; n++)
+ FR(n) = fpconst[0];
+ }
+ for(n=0;;n++){
+ op = getulong(ur->pc);
+ o = (op>>24) & 0xF;
+ if(((op>>8) & 0xF) != 1 || o != 0xE && (o&~1) != 0xC)
+ break;
+ if(condok(ur->psr, op>>28))
+ fpemu(ur->pc, op, ur, ufp);
+ ur->pc += 4;
+ if(anyhigher())
+ sched();
+ }
+ return n;
+}
diff --git a/os/ks32/io.h b/os/ks32/io.h
new file mode 100644
index 00000000..5e172140
--- /dev/null
+++ b/os/ks32/io.h
@@ -0,0 +1,168 @@
+/*
+ * Memory Map for Samsung ks32c50100
+ */
+
+#define SFRbase 0x7ff0000
+
+#define SYSCFG (*(ulong *)(SFRbase + 0))
+
+#define IOPbase (SFRbase + 0x5000)
+#define IOPMOD (*(ulong *)(IOPbase + 0))
+#define IOPCON (*(ulong *)(IOPbase + 4))
+#define IOPDATA (*(ulong *)(IOPbase + 8))
+
+#define MaxIRQbit 20 /* Maximum IRQ */
+#define EXT0bit 0
+#define EXT1bit 1
+#define EXT2bit 2
+#define EXT3bit 3
+#define UART0TXbit 4
+#define UART0RXbit 5
+#define UART1TXbit 6
+#define UART1RXbit 7
+#define GDMA0 8
+#define GDMA1 9
+#define TIMER0bit 10
+#define TIMER1bit 11
+#define HDLCATXbit 12
+#define HDLCARXbit 13
+#define HDLCBTXbit 14
+#define HDLCBRXbit 15
+#define ETHBDMATXbit 16
+#define ETHBDMARXbit 17
+#define ETHMACRXint 18
+#define ETHMAXTXint 19
+#define IICbit 20
+
+#define TIMERbit(n) (TIMER0bit + n)
+#define UARTTXbit(n) (UART0TXbit + (n) * 2)
+#define UARTRXbit(n) (UART0RXbit + (n) * 2)
+
+/*
+ * Interrupt controller
+ */
+
+#define INTbase (SFRbase + 0x4000)
+#define INTREG ((IntReg *)INTbase)
+
+typedef struct IntReg IntReg;
+struct IntReg {
+ ulong mod; /* 00 */
+ ulong pnd; /* 04 */
+ ulong msk; /* 08 */
+ ulong pri[6]; /* 0c */
+ ulong offset; /* 24 */
+ ulong pndpri; /* 28 */
+ ulong pndtst; /* 2c */
+ ulong oset_fiq; /* 30 */
+ ulong oset_irq; /* 34 */
+};
+
+/*
+ * UARTs
+ */
+#define UART0base (SFRbase + 0xd000)
+#define UART1base (SFRbase + 0xe000)
+#define UARTREG ((UartReg *)UART0base)
+
+typedef struct UartReg UartReg;
+struct UartReg {
+ ulong lcon; /* 00 */
+ ulong con; /* 04 */
+ ulong stat; /* 08 */
+ ulong txbuf; /* 0c */
+ ulong rxbuf; /* 10 */
+ ulong brdiv; /* 14 */
+ ulong pad[(UART1base - UART0base - 0x18) / 4];
+};
+
+#define ULCON_WLMASK 0x03
+#define ULCON_WL5 0x00
+#define ULCON_WL6 0x01
+#define ULCON_WL7 0x02
+#define ULCON_WL8 0x03
+
+#define ULCON_STOPMASK 0x04
+#define ULCON_STOP1 0x00
+#define ULCON_STOP2 0x04
+
+#define ULCON_PMDMASK 0x38
+#define ULCON_PMDNONE 0x00
+#define ULCON_PMDODD (4 << 3)
+#define ULCON_PMDEVEN (5 << 3)
+#define ULCON_PMDFORCE1 (6 << 3)
+#define ULCON_PMDFORCE0 (7 << 3)
+
+#define ULCON_CLOCKMASK 0x40
+#define ULCON_CLOCKMCLK 0x00
+#define ULCON_CLOCKUCLK (1 << 6)
+
+#define ULCON_IRMASK 0x80
+#define ULCON_IROFF 0x00
+#define ULCON_IRON 0x80
+
+#define UCON_RXMDMASK 0x03
+#define UCON_RXMDOFF 0x00
+#define UCON_RXMDINT 0x01
+#define UCON_RXMDGDMA0 0x02
+#define UCON_RXMDGDMA1 0x03
+
+#define UCON_SINTMASK 0x04
+#define UCON_SINTOFF 0x00
+#define UCON_SINTON 0x04
+
+#define UCON_TXMDMASK 0x18
+#define UCON_TXMDOFF (0 << 3)
+#define UCON_TXMDINT (1 << 3)
+#define UCON_TXMDGDMA0 (2 << 3)
+#define UCON_TXMDGDMA1 (3 << 3)
+
+#define UCON_DSRMASK 0x20
+#define UCON_DSRON (1 << 5)
+#define UCON_DSROFF (0 << 5)
+
+#define UCON_BRKMASK 0x40
+#define UCON_BRKON (1 << 6)
+#define UCON_BRKOFF (0 << 6)
+
+#define UCON_LOOPMASK 0x80
+#define UCON_LOOPON 0x80
+#define UCON_LOOPOFF 0x00
+
+#define USTAT_OV 0x01
+#define USTAT_PE 0x02
+#define USTAT_FE 0x04
+#define USTAT_BKD 0x08
+#define USTAT_DTR 0x10
+#define USTAT_RDR 0x20
+#define USTAT_TBE 0x40
+#define USTAT_TC 0x80
+
+/*
+ * Timers
+ */
+#define TIMERbase (SFRbase + 0x6000)
+#define TIMERREG ((TimerReg *)TIMERbase)
+
+typedef struct TimerReg TimerReg;
+struct TimerReg {
+ ulong mod;
+ ulong data[2];
+ ulong cnt[2];
+};
+
+/*
+ * PC compatibility support for PCMCIA drivers
+ */
+
+extern ulong ins(ulong); /* return ulong to prevent unecessary compiler shifting */
+void outs(ulong, int);
+#define inb(addr) (*((uchar*)(addr)))
+#define inl(addr) (*((ulong*)(addr)))
+ulong ins(ulong);
+#define outb(addr, val) *((uchar*)(addr)) = (val)
+#define outl(addr, val) *((ulong*)(addr)) = (val)
+
+void inss(ulong, void*, int);
+void outss(ulong, void*, int);
+
diff --git a/os/ks32/l.s b/os/ks32/l.s
new file mode 100644
index 00000000..30922a2d
--- /dev/null
+++ b/os/ks32/l.s
@@ -0,0 +1,205 @@
+#include "mem.h"
+
+/*
+ * Entered from the boot loader with
+ * supervisor mode, interrupts disabled;
+ */
+
+TEXT _startup(SB), $-4
+ MOVW $setR12(SB), R12 /* static base (SB) */
+ MOVW $Mach0(SB), R13
+ ADD $(KSTACK-4), R13 /* leave 4 bytes for link */
+
+ MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1 /* Switch to SVC mode */
+ MOVW R1, CPSR
+
+ BL main(SB) /* jump to kernel */
+
+dead:
+ B dead
+ BL _div(SB) /* hack to get _div etc loaded */
+
+GLOBL Mach0(SB), $KSTACK
+
+TEXT setr13(SB), $-4
+ MOVW 4(FP), R1
+
+ MOVW CPSR, R2
+ BIC $PsrMask, R2, R3
+ ORR R0, R3
+ MOVW R3, CPSR
+
+ MOVW R13, R0
+ MOVW R1, R13
+
+ MOVW R2, CPSR
+ RET
+
+TEXT _vundcall(SB), $-4
+_vund:
+ MOVM.DB [R0-R3], (R13)
+ MOVW $PsrMund, R0
+ B _vswitch
+
+TEXT _vsvccall(SB), $-4
+_vsvc:
+ MOVW.W R14, -4(R13)
+ MOVW CPSR, R14
+ MOVW.W R14, -4(R13)
+ BIC $PsrMask, R14
+ ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
+ MOVW R14, CPSR
+ MOVW $PsrMsvc, R14
+ MOVW.W R14, -4(R13)
+ B _vsaveu
+
+TEXT _vpabcall(SB), $-4
+_vpab:
+ MOVM.DB [R0-R3], (R13)
+ MOVW $PsrMabt, R0
+ B _vswitch
+
+TEXT _vdabcall(SB), $-4
+_vdab:
+ MOVM.DB [R0-R3], (R13)
+ MOVW $(PsrMabt+1), R0
+ B _vswitch
+
+TEXT _vfiqcall(SB), $-4 /* IRQ */
+_vfiq: /* FIQ */
+ MOVM.DB [R0-R3], (R13)
+ MOVW $PsrMfiq, R0
+ B _vswitch
+
+TEXT _virqcall(SB), $-4 /* IRQ */
+_virq:
+ MOVM.DB [R0-R3], (R13)
+ MOVW $PsrMirq, R0
+
+_vswitch: /* switch to svc mode */
+ MOVW SPSR, R1
+ MOVW R14, R2
+ MOVW R13, R3
+
+ MOVW CPSR, R14
+ BIC $PsrMask, R14
+ ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
+ MOVW R14, CPSR
+
+ MOVM.DB.W [R0-R2], (R13)
+ MOVM.DB (R3), [R0-R3]
+
+_vsaveu: /* Save Registers */
+ MOVW.W R14, -4(R13) /* save link */
+/* MCR CpMMU, 0, R0, C(0), C(0), 0 */
+
+ SUB $8, R13
+ MOVM.DB.W [R0-R12], (R13)
+
+ MOVW R0, R0 /* gratuitous noop */
+
+ MOVW $setR12(SB), R12 /* static base (SB) */
+ MOVW R13, R0 /* argument is ureg */
+ SUB $8, R13 /* space for arg+lnk*/
+ BL trap(SB)
+
+
+_vrfe: /* Restore Regs */
+ MOVW CPSR, R0 /* splhi on return */
+ ORR $(PsrDirq|PsrDfiq), R0, R1
+ MOVW R1, CPSR
+ ADD $(8+4*15), R13 /* [r0-R14]+argument+link */
+ MOVW (R13), R14 /* restore link */
+ MOVW 8(R13), R0
+ MOVW R0, SPSR
+ MOVM.DB.S (R13), [R0-R14] /* restore user registers */
+ MOVW R0, R0 /* gratuitous nop */
+ ADD $12, R13 /* skip saved link+type+SPSR*/
+ RFE /* MOVM.IA.S.W (R13), [R15] */
+
+TEXT splhi(SB), $-4
+ MOVW CPSR, R0
+ ORR $(PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT spllo(SB), $-4
+ MOVW CPSR, R0
+ BIC $(PsrDirq|PsrDfiq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT splx(SB), $-4
+ /* BUG - save PC in m->splpc - JB */
+
+TEXT splxpc(SB), $-4
+ MOVW R0, R1
+ MOVW CPSR, R0
+ MOVW R1, CPSR
+ RET
+
+TEXT islo(SB), $-4
+ MOVW CPSR, R0
+ AND $(PsrDirq), R0
+ EOR $(PsrDirq), R0
+ RET
+
+TEXT splfhi(SB), $-4
+ MOVW CPSR, R0
+ ORR $(PsrDfiq|PsrDirq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT splflo(SB), $-4
+ MOVW CPSR, R0
+ BIC $(PsrDfiq), R0, R1
+ MOVW R1, CPSR
+ RET
+
+TEXT cpsrr(SB), $-4
+ MOVW CPSR, R0
+ RET
+
+TEXT spsrr(SB), $-4
+ MOVW SPSR, R0
+ RET
+
+TEXT getcallerpc(SB), $-4
+ MOVW 0(R13), R0
+ RET
+
+TEXT _tas(SB), $-4
+ MOVW R0, R1
+ MOVW $0xDEADDEAD, R2
+ SWPW R2, (R1), R0
+ RET
+
+TEXT setlabel(SB), $-4
+ MOVW R13, 0(R0) /* sp */
+ MOVW R14, 4(R0) /* pc */
+ MOVW $0, R0
+ RET
+
+TEXT gotolabel(SB), $-4
+ MOVW 0(R0), R13 /* sp */
+ MOVW 4(R0), R14 /* pc */
+ MOVW $1, R0
+ BX (R14)
+
+TEXT outs(SB), $-4
+ MOVW 4(FP),R1
+ WORD $0xe1c010b0 /* STR H R1,[R0+0] */
+ RET
+
+TEXT ins(SB), $-4
+ WORD $0xe1d000b0 /* LDRHU R0,[R0+0] */
+ RET
+
+/* for devboot */
+TEXT gotopc(SB), $-4
+/*
+ MOVW R0, R1
+ MOVW bootparam(SB), R0
+ MOVW R1, PC
+*/
+ RET
diff --git a/os/ks32/main.c b/os/ks32/main.c
new file mode 100644
index 00000000..f338c5ca
--- /dev/null
+++ b/os/ks32/main.c
@@ -0,0 +1,289 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "io.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "version.h"
+
+Mach *m = (Mach*)MACHADDR;
+Proc *up = 0;
+Conf conf;
+
+extern ulong kerndate;
+extern int cflag;
+extern int consoleprint;
+extern int redirectconsole;
+extern int main_pool_pcnt;
+extern int heap_pool_pcnt;
+extern int image_pool_pcnt;
+extern int kernel_pool_pcnt;
+
+int
+segflush(void *p, ulong l)
+{
+ USED(p, l);
+ return 1;
+}
+
+static void
+poolsizeinit(void)
+{
+ ulong nb;
+
+ nb = conf.npage*BY2PG;
+ iprint("free memory %ld\n", nb);
+ poolsize(mainmem, (nb*main_pool_pcnt)/100, 0);
+ poolsize(heapmem, (nb*heap_pool_pcnt)/100, 0);
+ poolsize(imagmem, (nb*image_pool_pcnt)/100, 1);
+}
+
+void
+reboot(void)
+{
+ exit(0);
+}
+
+void
+halt(void)
+{
+ spllo();
+ print("cpu halted\n");
+ while(1);
+}
+
+void
+confinit(void)
+{
+ ulong base;
+
+ archconfinit();
+
+ base = PGROUND((ulong)end);
+ conf.base0 = base;
+
+ conf.base1 = 0;
+ conf.npage1 = 0;
+
+ conf.npage0 = (conf.topofmem - base)/BY2PG;
+
+ conf.npage = conf.npage0 + conf.npage1;
+ conf.ialloc = (((conf.npage*(main_pool_pcnt))/100)/2)*BY2PG;
+
+
+ conf.nproc = 20;
+// conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
+ conf.nmach = 1;
+}
+
+void
+machinit(void)
+{
+ memset(m, 0, sizeof(Mach)); /* clear the mach struct */
+}
+
+void
+cachemode(int size, int cenable, int wbenable)
+{
+ ulong sc = SYSCFG;
+ int cm;
+
+ switch (size) {
+ case 0:
+ default:
+ cm = 2;
+ break;
+ case 4096:
+ cm = 0;
+ break;
+ case 8192:
+ cm = 1;
+ break;
+ }
+ sc &= ~((3 << 4) | (1 << 2) | (1 << 1));
+ SYSCFG = sc | (cm << 4) | (cenable << 1) | (wbenable << 2);
+}
+
+void
+serputc()
+{
+ // dummy routine
+}
+
+void
+main(void)
+{
+ long *p, *ep;
+
+ /* clear the BSS by hand */
+ p = (long*)edata;
+ ep = (long*)end;
+ while(p < ep)
+ *p++ = 0;
+ // memset(edata, 0, end-edata); /* clear the BSS */
+ cachemode(8192, 1, 1);
+ machinit();
+ archreset();
+ confinit();
+ links();
+ xinit();
+ poolinit();
+ poolsizeinit();
+ trapinit();
+// mmuctlregw(mmuctlregr() | CpCDcache | CpCwb | CpCi32 | CpCd32 | CpCIcache);
+ clockinit();
+ printinit();
+// screeninit();
+ procinit();
+ chandevreset();
+
+ eve = strdup("inferno");
+
+ archconsole();
+// else
+// kbdinit();
+
+ print("\nInferno %s\n", VERSION);
+ print("conf %s (%lud) jit %d\n\n", conffile, kerndate, cflag);
+ userinit();
+// print("userinit over\n");
+ schedinit();
+}
+
+void
+init0(void)
+{
+ Osenv *o;
+
+// print("init0\n");
+ up->nerrlab = 0;
+ spllo();
+ if(waserror())
+ panic("init0 %r");
+
+ /*
+ * These are o.k. because rootinit is null.
+ * Then early kproc's will have a root and dot.
+ */
+ o = up->env;
+ o->pgrp->slash = namec("#/", Atodir, 0, 0);
+ cnameclose(o->pgrp->slash->name);
+ o->pgrp->slash->name = newcname("/");
+ o->pgrp->dot = cclone(o->pgrp->slash);
+
+ chandevinit();
+ poperror();
+// iprint("init0: disinit\n");
+// print("CXXXYYYYYYYYZZZZZZZ\n");
+ disinit("/osinit.dis");
+}
+
+void
+userinit()
+{
+ Proc *p;
+ Osenv *o;
+
+ p = newproc();
+ o = p->env;
+
+ o->fgrp = newfgrp(nil);
+
+ o->pgrp = newpgrp();
+ kstrdup(&o->user, eve);
+
+ strcpy(p->text, "interp");
+
+ p->fpstate = FPINIT;
+
+ /*
+ * Kernel Stack
+ *
+ * N.B. The -12 for the stack pointer is important.
+ * 4 bytes for gotolabel's return PC
+ */
+ p->sched.pc = (ulong)init0;
+ p->sched.sp = (ulong)p->kstack+KSTACK-8;
+
+ ready(p);
+}
+
+void
+exit(int inpanic)
+{
+ up = 0;
+
+ /* Shutdown running devices */
+ chandevshutdown();
+
+ if(inpanic){
+ print("Hit the reset button\n");
+ for(;;)clockpoll();
+ }
+ archreboot();
+}
+
+static void
+linkproc(void)
+{
+ spllo();
+ if (waserror())
+ print("error() underflow: %r\n");
+ else
+ (*up->kpfun)(up->arg);
+ pexit("end proc", 1);
+}
+
+void
+kprocchild(Proc *p, void (*func)(void*), void *arg)
+{
+ p->sched.pc = (ulong)linkproc;
+ p->sched.sp = (ulong)p->kstack+KSTACK-8;
+
+ p->kpfun = func;
+ p->arg = arg;
+}
+
+/* stubs */
+void
+setfsr(ulong x) {
+USED(x);
+}
+
+ulong
+getfsr(){
+return 0;
+}
+
+void
+setfcr(ulong x) {
+USED(x);
+}
+
+ulong
+getfcr(){
+return 0;
+}
+
+void
+fpinit(void)
+{
+}
+
+void
+FPsave(void*)
+{
+}
+
+void
+FPrestore(void*)
+{
+}
+
+ulong
+va2pa(void *v)
+{
+ return (ulong)v;
+}
+
diff --git a/os/ks32/mem.h b/os/ks32/mem.h
new file mode 100644
index 00000000..2b815feb
--- /dev/null
+++ b/os/ks32/mem.h
@@ -0,0 +1,54 @@
+/*
+ * Memory and machine-specific definitions. Used in C and assembler.
+ */
+
+/*
+ * Sizes
+ */
+#define _K_ 1024 /* 2^10 -> Kilo */
+#define _M_ 1048576 /* 2^20 -> Mega */
+#define _G_ 1073741824 /* 2^30 -> Giga */
+#define _T_ 1099511627776UL /* 2^40 -> Tera */
+#define BI2BY 8 /* bits per byte */
+#define BI2WD 32 /* bits per word */
+#define BY2WD 4 /* bytes per word */
+#define BY2V 8 /* bytes per double word */
+#define BY2PG 4096 /* bytes per page */
+#define WD2PG (BY2PG/BY2WD) /* words per page */
+#define PGSHIFT 12 /* log(BY2PG) */
+#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
+#define PGROUND(s) ROUND(s, BY2PG)
+#define BIT(n) (1<<n)
+#define BITS(a,b) ((1<<(b+1))-(1<<a))
+
+#define MAXMACH 1 /* max # cpus system can run */
+
+/*
+ * Time
+ */
+#define HZ (100) /* clock frequency */
+#define MS2HZ (1000/HZ) /* millisec per clock tick */
+#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
+#define MS2TK(t) ((t)/MS2HZ) /* milliseconds to ticks */
+
+/*
+ * More accurate time
+ */
+#define TIMER_HZ 50000000
+#define MS2TMR(t) ((ulong)(((uvlong)(t)*TIMER_HZ)/1000))
+#define US2TMR(t) ((ulong)(((uvlong)(t)*TIMER_HZ)/1000000))
+
+/*
+ * Address spaces
+ *
+*/
+
+#define KZERO 0x0
+#define MACHADDR ((ulong)&Mach0)
+/* #define MACHADDR (KZERO+0x00002000) /* should come from BootParam, */
+ /* or be automatically allocated */
+/* #define KTTB (KZERO+0x00004000) - comes from BootParam now */
+#define KTZERO bootparam->entry
+#define KSTACK 8192 /* Size of kernel stack */
+
+#include "armv7.h"
diff --git a/os/ks32/mkfile b/os/ks32/mkfile
new file mode 100644
index 00000000..c5868299
--- /dev/null
+++ b/os/ks32/mkfile
@@ -0,0 +1,115 @@
+<../../mkconfig
+
+#Configurable parameters
+
+CONF=evaluator7t #default configuration
+CONFLIST=evaluator7t
+
+SYSTARG=$OSTARG
+OBJTYPE=arm
+INSTALLDIR=$ROOT/Inferno/$OBJTYPE/bin #path of directory where kernel is installed
+#end configurable parameters
+
+<$ROOT/mkfiles/mkfile-$SYSTARG-$OBJTYPE #set vars based on target system
+
+<| $SHELLNAME ../port/mkdevlist $CONF #sets $IP, $DEVS, $ETHERS, $VGAS, $PORT, $MISC, $LIBS, $OTHERS
+
+KTZERO=0x8080
+
+OBJ=\
+ l.$O\
+ clock.$O\
+ fpi.$O\
+ fpiarm.$O\
+ fpimem.$O\
+ main.$O\
+ trap.$O\
+ $CONF.root.$O\
+ $IP\
+ $DEVS\
+ $ETHERS\
+ $LINKS\
+ $PORT\
+ $MISC\
+ $OTHERS\
+
+LIBNAMES=${LIBS:%=lib%.a}
+LIBDIRS=$LIBS
+
+HFILES=\
+ mem.h\
+ armv7.h\
+ dat.h\
+ fns.h\
+ io.h\
+ fpi.h\
+
+CFLAGS=-wFV -I$ROOT/Inferno/$OBJTYPE/include -I$ROOT/include -I$ROOT/libinterp -r
+KERNDATE=`{$NDATE}
+
+# default:V: i$CONF.gz i$CONF.p9.gz i$CONF.txt
+default:V: i$CONF.txt
+
+install:V: $INSTALLDIR/i$CONF $INSTALLDIR/i$CONF.gz $INSTALLDIR/i$CONF.p9.gz $INSTALLDIR/i$CONF.raw
+
+i$CONF.txt: i$CONF.aif
+ x=/bin/pub/uuencode
+ test -f $x || x=uuencode
+ $x i$CONF.aif i$CONF.aif >i$CONF.txt
+ mv i$CONF.txt xyz
+
+i$CONF: $OBJ $CONF.c $CONF.root.h $LIBNAMES
+ $CC $CFLAGS '-DKERNDATE='$KERNDATE $CONF.c
+ $LD -o $target -T$KTZERO -R4 -l $OBJ $CONF.$O $LIBFILES
+
+trap.t: trap.5
+ cp trap.5 trap.t
+trap.5: trap.c
+ 5c $CFLAGS trap.c
+
+# old "plan9" format executables for inf2.1 styxmon/sboot
+i$CONF.p9: $OBJ $CONF.c $CONF.root.h $LIBNAMES
+ $CC $CFLAGS '-DKERNDATE='$KERNDATE $CONF.c
+ $LD -o $target -T0x8020 -R4 -l $OBJ $CONF.$O $LIBFILES
+
+i$CONF.p9.gz: i$CONF.p9
+ rm -f i$CONF.p9.gz
+ gzip -9 <i$CONF.p9 >i$CONF.p9.gz
+
+# "raw" version of kernel for binary comparison testing
+i$CONF.raw: $OBJ $CONF.c $CONF.root.h $LIBNAMES
+ $CC $CFLAGS '-DKERNDATE='0 $CONF.c
+ $LD -s -o $target -T$KTZERO -R4 -l $OBJ $CONF.$O $LIBFILES
+
+i$CONF.aif: i$CONF
+ 5cv -s -H1 -T$KTZERO $prereq $target
+
+i$CONF.gz: i$CONF.aif
+ gzip -9 <$prereq >$target
+
+<../port/portmkfile
+
+../init/$INIT.dis: ../init/$INIT.b
+ cd ../init; mk $INIT.dis
+
+clock.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h
+devether.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h
+devsapcm.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h
+fault386.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h
+main.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h
+trap.$O: $ROOT/Inferno/$OBJTYPE/include/ureg.h
+
+devether.$O $ETHERS: etherif.h ../port/netif.h
+$IP devip.$O: ../ip/ip.h
+
+dummy:V:
+
+# to be moved to port/interp
+bench.h:D: ../../module/bench.m
+ rm -f $target && limbo -a -I../../module ../../module/bench.m > $target
+benchmod.h:D: ../../module/bench.m
+ rm -f $target && limbo -t Bench -I../../module ../../module/bench.m > $target
+devbench.$O: bench.h benchmod.h
+
+devuart.$O: devuart.c
+ $CC $CFLAGS devuart.c
diff --git a/os/ks32/not.c b/os/ks32/not.c
new file mode 100644
index 00000000..6546bd5d
--- /dev/null
+++ b/os/ks32/not.c
@@ -0,0 +1,3 @@
+void muxclose(){}
+void mntauth(){}
+void mntversion(){}
diff --git a/os/ks32/squirt b/os/ks32/squirt
new file mode 100755
index 00000000..b2da05e4
--- /dev/null
+++ b/os/ks32/squirt
@@ -0,0 +1,2 @@
+#!/bin/rc
+cat ievaluator7t.txt
diff --git a/os/ks32/trap.c b/os/ks32/trap.c
new file mode 100644
index 00000000..3d738c78
--- /dev/null
+++ b/os/ks32/trap.c
@@ -0,0 +1,525 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#define waslo(sr) (!((sr) & (PsrDirq|PsrDfiq)))
+
+typedef struct IrqEntry {
+ void (*r)(Ureg*, void*);
+ void *a;
+ int v;
+} IrqEntry;
+
+enum {
+ NumIRQbits = MaxIRQbit+1,
+
+};
+
+static IrqEntry Irq[NumIRQbits];
+
+Instr BREAK = 0xE6BAD010;
+
+int (*breakhandler)(Ureg*, Proc*);
+int (*catchdbg)(Ureg *, uint);
+
+void dumperrstk(void);
+/*
+ * Interrupt sources not masked by splhi() -- these are special
+ * interrupt handlers (e.g. profiler or watchdog), not allowed
+ * to share regular kernel data structures. All interrupts are
+ * masked by splfhi(), which should only be used herein.
+ */
+
+int splfhi(void); /* disable all */
+int splflo(void); /* enable FIQ */
+
+static int actIrq = -1; /* Active Irq handler, 0-31, or -1 if none */
+static int wasIrq = -1; /* Interrupted Irq handler */
+
+static Proc *iup; /* Interrupted kproc */
+
+void
+intrmask(int v, int tbdf)
+{
+ USED(tbdf);
+ if(v < 0 || v > MaxIRQbit)
+ panic("intrmask: irq source %d out of range\n", v);
+ INTREG->msk |= (1 << v);
+}
+
+void
+intrunmask(int v, int tbdf)
+{
+ USED(tbdf);
+ if(v < 0 || v > MaxIRQbit)
+ panic("intrunmask: irq source %d out of range\n", v);
+ INTREG->msk &= ~(1 << v);
+}
+
+void
+intrclear(int v, int tbdf)
+{
+ USED(tbdf);
+ if(v < 0 || v > MaxIRQbit)
+ panic("intrclear: irq source %d out of range\n", v);
+ INTREG->pnd = (1 << v);
+}
+
+void
+intrenable(int v, void (*f)(Ureg*, void*), void* a, int tbdf)
+{
+ int x;
+
+ USED(tbdf);
+ if(v < 0 || v > MaxIRQbit)
+ panic("intrenable: irq source %d out of range\n", v);
+ Irq[v].r = f;
+ Irq[v].a = a;
+
+ x = splfhi();
+ /* Enable the interrupt by clearing the mask bit */
+ INTREG->msk &= ~(1 << v);
+ splx(x);
+}
+
+ulong fiqstack[4];
+ulong irqstack[4];
+ulong abtstack[4];
+ulong undstack[4];
+
+static void
+safeintr(Ureg *, void *a)
+{
+ int v = (int)a;
+ int x;
+
+ /* No handler - clear the mask so we don't loop */
+ x = splfhi();
+ intrmask(v, 0);
+ splx(x);
+ iprint("SPURIOUS INTERRUPT %d\n", v);
+}
+
+static void
+trapv(int off, void (*f)(void))
+{
+ ulong *vloc;
+ int offset;
+
+ vloc = (ulong *)off;
+ offset = (((ulong *) f) - vloc)-2;
+ *vloc = (0xea << 24) | offset;
+}
+
+static void
+maskallints(void)
+{
+ INTREG->msk = 0x3fffff; /* mask out all interrupts */
+}
+
+void
+trapinit(void)
+{
+ int v;
+ IntReg *intr = INTREG;
+
+ intr->mod = 0; /* all interrupts to be done in IRQ mode */
+
+ /* set up stacks for various exceptions */
+ setr13(PsrMfiq, fiqstack+nelem(fiqstack));
+ setr13(PsrMirq, irqstack+nelem(irqstack));
+ setr13(PsrMabt, abtstack+nelem(abtstack));
+ setr13(PsrMund, undstack+nelem(undstack));
+
+ for (v = 0; v < nelem(Irq); v++) {
+ Irq[v].r = safeintr;
+ Irq[v].a = (void *)v;
+ Irq[v].v = v;
+ }
+
+ trapv(0x0, _vsvccall);
+ trapv(0x4, _vundcall);
+ trapv(0xc, _vpabcall);
+ trapv(0x10, _vdabcall);
+ trapv(0x18, _virqcall);
+ trapv(0x1c, _vfiqcall);
+ trapv(0x8, _vsvccall);
+ serwrite = uartputs;
+}
+
+static char *_trap_str[PsrMask+1] = {
+ [ PsrMfiq ] "Fiq interrupt",
+ [ PsrMirq ] "Mirq interrupt",
+ [ PsrMsvc ] "SVC/SWI Exception",
+ [ PsrMabt ] "Prefetch Abort/Data Abort",
+ [ PsrMabt+1 ] "Data Abort",
+ [ PsrMund ] "Undefined instruction",
+ [ PsrMsys ] "Sys trap"
+};
+
+static char *
+trap_str(int psr)
+{
+ char *str = _trap_str[psr & PsrMask];
+ if (!str)
+ str = "Undefined trap";
+ return(str);
+}
+
+static void
+sys_trap_error(int type)
+{
+ char errbuf[ERRMAX];
+ sprint(errbuf, "sys: trap: %s\n", trap_str(type));
+ error(errbuf);
+}
+
+void
+dflt(Ureg *ureg, ulong far)
+{
+ char buf[ERRMAX];
+
+ dumpregs(ureg);
+ sprint(buf, "trap: fault pc=%8.8lux addr=0x%lux", (ulong)ureg->pc, far);
+ disfault(ureg, buf);
+}
+
+/*
+ * All traps come here. It is slower to have all traps ca)
+ * rather than directly vectoring the handler.
+ * However, this avoids
+ * a lot of code dup and possible bugs.
+ * trap is called splfhi().
+ */
+
+void
+trap(Ureg* ureg)
+{
+ //
+ // This is here to make sure that a clock interrupt doesn't
+ // cause the process we just returned into to get scheduled
+ // before it single stepped to the next instruction.
+ //
+ static struct {int callsched;} c = {1};
+ int itype;
+ /*
+ * All interrupts/exceptions should be resumed at ureg->pc-4,
+ * except for Data Abort which resumes at ureg->pc-8.
+ */
+ itype = ureg->type;
+ if(itype == PsrMabt+1)
+ ureg->pc -= 8;
+ else
+ ureg->pc -= 4;
+ ureg->sp = (ulong)(ureg+1);
+ if (itype == PsrMirq || itype == PsrMfiq) { /* Interrupt Request */
+
+ Proc *saveup;
+ int t;
+
+ SET(t);
+ SET(saveup);
+
+ if (itype == PsrMirq) {
+ splflo(); /* Allow nonmasked interrupts */
+ if (saveup = up) {
+ t = m->ticks; /* CPU time per proc */
+ saveup->pc = ureg->pc; /* debug info */
+ saveup->dbgreg = ureg;
+ }
+ } else {
+ /* for profiler(wasbusy()): */
+ wasIrq = actIrq; /* Save ID of interrupted handler */
+ iup = up; /* Save ID of interrupted proc */
+ }
+
+ while (1) { /* Use up all the active interrupts */
+ ulong hpip;
+ IrqEntry *curIrq;
+ IntReg *intr = INTREG;
+
+ hpip = itype == PsrMirq ? intr->oset_irq : intr->oset_fiq;
+ if (hpip == 0x54)
+ break;
+ curIrq = Irq + (hpip >> 2);
+ actIrq = curIrq->v; /* show active interrupt handler */
+ up = 0; /* Make interrupted process invisible */
+ curIrq->r(ureg, curIrq->a); /* Call handler */
+ }
+ if (itype == PsrMirq) {
+ up = saveup; /* Make interrupted process visible */
+ actIrq = -1; /* No more interrupt handler running */
+ preemption(m->ticks - t);
+ saveup->dbgreg = nil;
+ } else {
+ actIrq = wasIrq;
+ up = iup;
+ }
+ return;
+ }
+
+ setled7ascii('E');
+ /* All other traps */
+ if (ureg->psr & PsrDfiq)
+ goto faultpanic;
+ if (up)
+ up->dbgreg = ureg;
+// setled7ascii('0' + itype);
+ switch(itype) {
+
+ case PsrMund: /* Undefined instruction */
+ if(*(ulong*)ureg->pc == BREAK && breakhandler) {
+ int s;
+ Proc *p;
+
+ p = up;
+ /* if (!waslo(ureg->psr) || (ureg->pc >= (ulong)splhi && ureg->pc < (ulong)islo))
+ p = 0; */
+ s = breakhandler(ureg, p);
+ if(s == BrkSched) {
+ c.callsched = 1;
+ sched();
+ } else if(s == BrkNoSched) {
+ c.callsched = 0;
+ if(up)
+ up->dbgreg = 0;
+ return;
+ }
+ break;
+ }
+ if (!up)
+ goto faultpanic;
+ spllo();
+ if (waserror()) {
+ if(waslo(ureg->psr) && (up->type == Interp))
+ disfault(ureg, up->env->errstr);
+ setpanic();
+ dumpregs(ureg);
+ panic("%s", up->env->errstr);
+ }
+ if (!fpiarm(ureg)) {
+ dumpregs(ureg);
+ sys_trap_error(ureg->type);
+ }
+ poperror();
+ break;
+
+ case PsrMsvc: /* Jump through 0 or SWI */
+ if (waslo(ureg->psr) && up && (up->type == Interp)) {
+ spllo();
+ dumpregs(ureg);
+ sys_trap_error(ureg->type);
+ }
+ goto faultpanic;
+
+ case PsrMabt: /* Prefetch abort */
+ if (catchdbg && catchdbg(ureg, 0))
+ break;
+ ureg->pc -= 4;
+ case PsrMabt+1: { /* Data abort */
+ if (waslo(ureg->psr) && up && (up->type == Interp)) {
+ spllo();
+ dflt(ureg, 0);
+ }
+ goto faultpanic;
+ }
+ default: /* ??? */
+faultpanic:
+ setpanic();
+ dumpregs(ureg);
+ panic("exception %uX %s\n", ureg->type, trap_str(ureg->type));
+ break;
+ }
+
+ splhi();
+ if(up)
+ up->dbgreg = 0; /* becomes invalid after return from trap */
+}
+
+void
+setpanic(void)
+{
+ extern void screenon(int);
+ extern int consoleprint;
+
+ if (breakhandler != 0) /* don't mess up debugger */
+ return;
+ maskallints();
+// spllo();
+ /* screenon(!consoleprint); */
+ consoleprint = 1;
+ serwrite = uartputs;
+}
+
+int
+isvalid_wa(void *v)
+{
+ return((ulong)v >= 0x8000 && (ulong)v < conf.topofmem && !((ulong)v & 3));
+}
+
+int
+isvalid_va(void *v)
+{
+ return((ulong)v >= 0x8000 && (ulong)v < conf.topofmem);
+}
+
+void
+dumplongs(char *msg, ulong *v, int n)
+{
+ int ii;
+ int ll;
+
+ ll = print("%s at %ulx: ", msg, v);
+ for (ii = 0; ii < n; ii++)
+ {
+ if (ll >= 60)
+ {
+ print("\n");
+ ll = print(" %ulx: ", v);
+ }
+ if (isvalid_va(v))
+ ll += print(" %ulx", *v++);
+ else
+ {
+ ll += print(" invalid");
+ break;
+ }
+ }
+ print("\n");
+ USED(ll);
+}
+
+void
+dumpregs(Ureg* ureg)
+{
+ Proc *p;
+
+ print("TRAP: %s", trap_str(ureg->type));
+ if ((ureg->psr & PsrMask) != PsrMsvc)
+ print(" in %s", trap_str(ureg->psr));
+/*
+ if ((ureg->type == PsrMabt) || (ureg->type == PsrMabt + 1))
+ print(" FSR %8.8luX FAR %8.8luX\n", mmuregr(CpFSR), mmuregr(CpFAR));
+*/
+ print("\n");
+ print("PSR %8.8uX type %2.2uX PC %8.8uX LINK %8.8uX\n",
+ ureg->psr, ureg->type, ureg->pc, ureg->link);
+ print("R14 %8.8uX R13 %8.8uX R12 %8.8uX R11 %8.8uX R10 %8.8uX\n",
+ ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
+ print("R9 %8.8uX R8 %8.8uX R7 %8.8uX R6 %8.8uX R5 %8.8uX\n",
+ ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
+ print("R4 %8.8uX R3 %8.8uX R2 %8.8uX R1 %8.8uX R0 %8.8uX\n",
+ ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
+ print("Stack is at: %8.8luX\n",ureg);
+ print("CPSR %8.8uX SPSR %8.8uX ", cpsrr(), spsrr());
+ print("PC %8.8lux LINK %8.8lux\n", (ulong)ureg->pc, (ulong)ureg->link);
+
+ p = (actIrq >= 0) ? iup : up;
+ if (p != nil)
+ print("Process stack: %lux-%lux\n",
+ p->kstack, p->kstack+KSTACK-4);
+ else
+ print("System stack: %lux-%lux\n",
+ (ulong)(m+1), (ulong)m+KSTACK-4);
+ dumplongs("stk", (ulong *)(ureg + 1), 16);
+ print("bl's: ");
+ dumpstk((ulong *)(ureg + 1));
+ if (isvalid_wa((void *)ureg->pc))
+ dumplongs("code", (ulong *)ureg->pc - 5, 12);
+
+ dumperrstk();
+ /* for(;;) ; */
+}
+
+void
+dumpstack(void)
+{
+ ulong l;
+
+ if (breakhandler != 0)
+ dumpstk(&l);
+}
+
+void
+dumpstk(ulong *l)
+{
+ ulong *v, i;
+ ulong inst;
+ ulong *estk;
+ uint len;
+
+ len = KSTACK/sizeof *l;
+ if (up == 0)
+ len -= l - (ulong *)m;
+ else
+ len -= l - (ulong *)up->kstack;
+
+ if (len > KSTACK/sizeof *l)
+ len = KSTACK/sizeof *l;
+ else if (len < 0)
+ len = 50;
+
+ i = 0;
+ for(estk = l + len; l<estk; l++) {
+ if (!isvalid_wa(l)) {
+ i += print("invalid(%lux)", l);
+ break;
+ }
+ v = (ulong *)*l;
+ if (isvalid_wa(v)) {
+ inst = *(v - 1);
+ if ( (
+ ((inst & 0x0ff0f000) == 0x0280f000)
+ &&
+ ((*(v-2) & 0x0ffff000) == 0x028fe000)
+ )
+ ||
+ ((inst & 0x0f000000) == 0x0b000000)
+ ) {
+ i += print("%8.8lux ", v);
+ }
+ }
+ if (i >= 60) {
+ print("\n");
+ i = print(" ");
+ }
+ }
+ if (i)
+ print("\n");
+}
+
+void
+dumperrstk(void)
+{
+ int ii, ll;
+
+ if (!up)
+ return;
+
+ ll = print("err stk: ");
+ for (ii = 0; ii < NERR; ii++) {
+ if (ii == up->nerrlab)
+ ll += print("* ");
+ if (up->errlab[ii].pc) {
+ ll += print(" %lux/%8.8lux",
+ up->errlab[ii].sp, up->errlab[ii].pc);
+ if (ll >= 60) {
+ print("\n");
+ ll = 0;
+ }
+ }
+ }
+ if (ll)
+ print("\n");
+}
+
+void
+trapspecial(int (*f)(Ureg *, uint))
+{
+ catchdbg = f;
+}