diff options
Diffstat (limited to 'os/ks32')
| -rwxr-xr-x | os/ks32/Mk | 7 | ||||
| -rw-r--r-- | os/ks32/NOTICE | 2 | ||||
| -rw-r--r-- | os/ks32/archevaluator7t.c | 161 | ||||
| -rw-r--r-- | os/ks32/armv7.h | 19 | ||||
| -rw-r--r-- | os/ks32/clock.c | 287 | ||||
| -rw-r--r-- | os/ks32/dat.h | 218 | ||||
| -rw-r--r-- | os/ks32/devuart.c | 719 | ||||
| -rw-r--r-- | os/ks32/download.ps | 1040 | ||||
| -rw-r--r-- | os/ks32/evaluator7t | 110 | ||||
| -rw-r--r-- | os/ks32/fns.h | 145 | ||||
| -rw-r--r-- | os/ks32/fpi.h | 61 | ||||
| -rw-r--r-- | os/ks32/fpiarm.c | 483 | ||||
| -rw-r--r-- | os/ks32/io.h | 168 | ||||
| -rw-r--r-- | os/ks32/l.s | 205 | ||||
| -rw-r--r-- | os/ks32/main.c | 289 | ||||
| -rw-r--r-- | os/ks32/mem.h | 54 | ||||
| -rw-r--r-- | os/ks32/mkfile | 115 | ||||
| -rw-r--r-- | os/ks32/not.c | 3 | ||||
| -rwxr-xr-x | os/ks32/squirt | 2 | ||||
| -rw-r--r-- | os/ks32/trap.c | 525 |
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), ®(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(®(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; +} |
