ref: d93edcf773cf571173e24867e186cecef3b98af8
parent: e8dc10b3b573fb5b696d8667826cd16629983494
author: mia soweli <inbox@tachibana-labs.org>
date: Wed Aug 30 11:16:41 EDT 2023
*: let's get directories
--- a/dat.h
+++ /dev/null
@@ -1,147 +1,0 @@
-typedef struct Conf Conf;
-typedef struct Confmem Confmem;
-typedef struct FPsave FPsave;
-typedef struct Label Label;
-typedef struct Lock Lock;
-typedef struct Mach Mach;
-typedef struct MMMU MMMU;
-typedef struct Page Page;
-typedef struct Proc Proc;
-typedef struct PFPU PFPU;
-typedef struct PMMU PMMU;
-typedef struct Ureg Ureg;
-
-typedef u32int PTE;
-typedef uvlong Tval;
-
-#pragma incomplete Ureg
-
-#define MAXSYSARG 5
-#define AOUT_MAGIC (E_MAGIC)
-
-struct Lock {
- ulong key;
- u32int sr;
- uintptr pc;
- Proc *p;
- Mach *m;
- int isilock;
-};
-
-struct Label {
- uintptr sp;
- uintptr pc;
-};
-
-struct Confmem {
- uintptr base;
- uintptr limit;
- uintptr kbase;
- uintptr klimit;
- ulong npage;
-};
-
-struct Conf {
- ulong nmach;
- ulong nproc;
- Confmem mem[1];
- ulong npage;
- ulong upages;
- ulong copymode;
- ulong ialloc;
- ulong pipeqsize;
- ulong nimage;
- ulong nswap;
- int nswppo;
- int monitor;
-};
-
-struct FPsave {
- ulong exc;
- ulong scr;
- uchar regs[256];
-};
-
-struct PFPU {
- enum {
- FPinit,
- FPactive,
- FPinactive,
-
- FPillegal = 0x100,
- } fpstate;
- FPsave fpsave[1];
-};
-
-#define NCOLOR 1
-struct PMMU {
- Page *mmul2;
- Page *mmul2cache;
-};
-
-struct MMMU {
- PTE *mmul1;
- uint mmupid;
-};
-
-#include "../port/portdat.h"
-
-struct Mach {
- int machno;
- uintptr splpc;
- Proc *proc;
- MMMU;
-
- PMach;
-
- u32int save[5];
- uintptr stack[1];
-};
-
-typedef struct ISAConf ISAConf;
-typedef struct Devport Devport;
-typedef struct DevConf DevConf;
-
-#define BUSUNKNOWN 0
-#define BUSMODEM 1
-
-#define NISAOPT 8
-struct ISAConf {
- char *type;
- uintptr port;
- int irq;
- ulong dma;
- ulong mem;
- ulong size;
- ulong freq;
-
- int nopt;
- char *opt[NISAOPT];
-};
-
-struct Devport {
- ulong port;
- int size;
-};
-
-struct DevConf {
- ulong intnum;
- char *type;
- int nports;
- Devport *ports;
-};
-
-typedef void KMap;
-#define VA(p) ((uintptr)(p))
-#define kmap(p) (KMap*)((p)->pa|KZERO)
-#define kunmap(p)
-#define kmapinval()
-#define getpgcolor(p) 0
-
-struct {
- char machs[MAXMACH];
- int exiting;
-} active;
-
-extern register Mach *m;
-extern register Proc *up;
--- a/devkbd.c
+++ /dev/null
@@ -1,243 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "../port/error.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/i2c.h"
-
-enum {
- Rctrl = 0xd2,
- Csoftreset = 1<<0,
- Csoftmode = 1<<1,
- Cenable = 1<<6,
- Rcode = 0xdb,
- Risr = 0xe3,
- Rimr = 0xe4,
- Ikp = 1<<0,
- Ilk = 1<<1,
- Ito = 1<<2,
- Rsir = 0xe7,
- Redr = 0xe8,
- Ekpfalling = 1<<0,
- Ekprising = 1<<1,
- Elkfalling = 1<<2,
- Elkrising = 1<<3,
- Etofalling = 1<<4,
- Etorising = 1<<5,
- Emisfalling = 1<<6,
- Emisrising = 1<<7,
- Rsih = 0xe9,
- Scor = 1<<2,
-};
-
-enum {
- Qdir,
- Qscan,
-};
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
- Ref;
- Lock;
-
- I2Cdev *dev;
- Queue *q;
-
- uchar cur[8];
- uchar prev[8];
-};
-
-static Ctlr ctlr;
-static Dirtab kbdtab[] = {
- ".", {Qdir, 0, QTDIR}, 0, 0555,
- "scancode", {Qscan, 0, QTFILE}, 0, 0440,
-};
-
-static u8int
-csr8r(Ctlr *ctlr, u8int r)
-{
- uchar buf;
-
- i2crecv(ctlr->dev, &buf, sizeof(buf), r);
- return buf;
-}
-
-static u8int
-csr8w(Ctlr *ctlr, u8int r, u8int w)
-{
- i2csend(ctlr->dev, &w, sizeof(w), r);
- return w;
-}
-
-static void
-kbdinterrupt(Ureg *, void*)
-{
- int i, j, c, k;
-
- ilock(&ctlr);
- if(!(csr8r(&ctlr, Risr) & Ikp)) {
- iunlock(&ctlr);
- return;
- }
-
- /* scan key columns */
- for(i = 0; i < 8; i++) {
- ctlr.prev[i] = ctlr.cur[i];
- ctlr.cur[i] = csr8r(&ctlr, Rcode + i);
-
- /* changed? */
- c = ctlr.cur[i] ^ ctlr.prev[i];
- if(!c)
- continue;
-
- /* scan key rows */
- for(j = 0; j < 8; j++) {
- if(!(c & (1 << j)))
- continue;
-
- /* pressed or released? */
- k = i << 3 | j;
- if(ctlr.prev[i] & (1 << j))
- k |= 0x80;
-
- qproduce(ctlr.q, &k, 1);
- }
- }
-
- iunlock(&ctlr);
-}
-
-static void
-kbdreset(void)
-{
- ilock(&ctlr);
- ctlr.q = qopen(1024, Qcoalesce, 0, 0);
- if(!ctlr.q) {
- iunlock(&ctlr);
- return;
- }
-
- ctlr.dev = i2cdev(i2cbus("i2c1"), 0x4a);
- if(!ctlr.dev) {
- iunlock(&ctlr);
- return;
- }
-
- ctlr.dev->subaddr = 1;
- ctlr.dev->size = 0x100;
-
- csr8w(&ctlr, Rctrl, Csoftreset | Csoftmode | Cenable);
- csr8w(&ctlr, Rsih, Scor);
- csr8w(&ctlr, Rimr, ~Ikp);
-
- intrenable(IRQTWL, kbdinterrupt, nil, BUSUNKNOWN, "kbd");
- iunlock(&ctlr);
-}
-
-static void
-kbdshutdown(void)
-{
-}
-
-static Chan *
-kbdattach(char *spec)
-{
- if(!ctlr.dev)
- error(Enonexist);
-
- return devattach(L'b', spec);
-}
-
-static Walkqid *
-kbdwalk(Chan *c, Chan *nc, char **name, int nname)
-{
- return devwalk(c, nc, name, nname, kbdtab, nelem(kbdtab), devgen);
-}
-
-static int
-kbdstat(Chan *c, uchar *dp, int n)
-{
- return devstat(c, dp, n, kbdtab, nelem(kbdtab), devgen);
-}
-
-static Chan *
-kbdopen(Chan *c, int mode)
-{
- if(!iseve)
- error(Eperm);
-
- if(c->qid.path == Qscan) {
- if(waserror()) {
- decref(&ctlr);
- nexterror();
- }
-
- if(incref(&ctlr) != 1)
- error(Einuse);
-
- c = devopen(c, mode, kbdtab, nelem(kbdtab), devgen);
- poperror();
- return c;
- }
-
- return devopen(c, mode, kbdtab, nelem(kbdtab), devgen);
-}
-
-static void
-kbdclose(Chan *c)
-{
- if((c->flag & COPEN) && c->qid.path == Qscan)
- decref(&ctlr);
-}
-
-static Block*
-kbdbread(Chan *c, long n, ulong off)
-{
- if(c->qid.path == Qscan)
- return qbread(ctlr.q, n);
-
- return devbread(c, n, off);
-}
-
-static long
-kbdread(Chan *c, void *a, long n, vlong)
-{
- if(c->qid.path == Qscan)
- return qread(ctlr.q, a, n);
-
- if(c->qid.path == Qdir)
- return devdirread(c, a, n, kbdtab, nelem(kbdtab), devgen);
-
- error(Egreg);
- return 0;
-}
-
-static long
-kbdwrite(Chan *, void *, long, vlong)
-{
- error(Egreg);
- return 0;
-}
-
-Dev kbddevtab = {
- L'b',
- "kbd",
-
- kbdreset,
- devinit,
- kbdshutdown,
- kbdattach,
- kbdwalk,
- kbdstat,
- kbdopen,
- devcreate,
- kbdclose,
- kbdread,
- kbdbread,
- kbdwrite,
- devbwrite,
- devremove,
- devwstat,
-};
--- a/devrtc.c
+++ /dev/null
@@ -1,202 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "../port/error.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/i2c.h"
-
-enum {
- Rsec = 0x1c,
- Rmin = 0x1d,
- Rhour = 0x1e,
- Rday = 0x1f,
- Rmonth = 0x20,
- Ryear = 0x21,
- Rweeks = 0x22,
- Rctrl = 0x29,
- Cget = 1<<6,
-
- Qdir = 0,
- Qrtc,
-
- SecMin = 60,
- SecHour = 60*SecMin,
- SecDay = 24*SecHour,
-};
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
- I2Cdev *dev;
-
- int sec;
- int min;
- int hour;
- int day;
- int month;
- int year;
-};
-
-static Ctlr ctlr;
-static int dmsize[] = { 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-static int ldmsize[] = { 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-static Dirtab rtctab[] = {
- ".", {Qdir, 0, QTDIR}, 0, 0555,
- "rtc", {Qrtc, 0, QTFILE}, 0, 0440,
-};
-
-#define bcddec(x) (((x) & 0xf) + ((x) >> 4) * 10)
-#define bcdenc(x) (((x / 10) << 4) + (x) % 10)
-#define leap(x) (((x) % 4) == 0 && ((x % 100) != 0 || (x % 400) == 0))
-
-static u8int
-csr8r(Ctlr *ctlr, u8int r)
-{
- uchar buf;
-
- i2crecv(ctlr->dev, &buf, sizeof(buf), r);
- return buf;
-}
-
-static u8int
-csr8w(Ctlr *ctlr, u8int r, u8int w)
-{
- i2csend(ctlr->dev, &w, sizeof(w), r);
- return w;
-}
-
-static vlong
-rtcsnarf(void)
-{
- vlong s;
- int i;
-
- /* latch and snarf */
- csr8w(&ctlr, Rctrl, csr8r(&ctlr, Rctrl) | Cget);
- ctlr.sec = bcddec(csr8r(&ctlr, Rsec)) % 60;
- ctlr.min = bcddec(csr8r(&ctlr, Rmin)) % 60;
- ctlr.hour = bcddec(csr8r(&ctlr, Rhour)) % 24;
- ctlr.day = bcddec(csr8r(&ctlr, Rday));
- ctlr.month = bcddec(csr8r(&ctlr, Rmonth));
- ctlr.year = bcddec(csr8r(&ctlr, Ryear)) % 100;
- ctlr.year += 2000;
-
- /* seconds per year */
- s = 0;
- for(i = 1970; i < ctlr.year; i++) {
- if(leap(i))
- s += ldmsize[0] * SecDay;
- else
- s += dmsize[0] * SecDay;
- }
-
- /* seconds per month */
- for(i = 1; i < ctlr.month; i++) {
- if(leap(ctlr.year))
- s += ldmsize[i] * SecDay;
- else
- s += dmsize[i] * SecDay;
- }
-
- /* days, hours, minutes, seconds */
- s += (ctlr.day - 1) * SecDay;
- s += ctlr.hour * SecHour;
- s += ctlr.min * SecMin;
- s += ctlr.sec;
- return s;
-}
-
-static void
-rtcreset(void)
-{
- ctlr.dev = i2cdev(i2cbus("i2c1"), 0x4b);
- if(!ctlr.dev)
- return;
-
- ctlr.dev->subaddr = 1;
- ctlr.dev->size = 0x100;
-}
-
-static void
-rtcshutdown(void)
-{
-}
-
-static Chan *
-rtcattach(char *spec)
-{
- if(!ctlr.dev)
- error(Enonexist);
-
- return devattach('r', spec);
-}
-
-static Walkqid *
-rtcwalk(Chan *c, Chan *nc, char **name, int nname)
-{
- return devwalk(c, nc, name, nname, rtctab, nelem(rtctab), devgen);
-}
-
-static int
-rtcstat(Chan *c, uchar *dp, int n)
-{
- return devstat(c, dp, n, rtctab, nelem(rtctab), devgen);
-}
-
-static Chan *
-rtcopen(Chan *c, int mode)
-{
- mode = openmode(mode);
- if(c->qid.path == Qrtc) {
- if(!iseve() && mode != OREAD)
- error(Eperm);
- }
-
- return devopen(c, mode, rtctab, nelem(rtctab), devgen);
-}
-
-static void
-rtcclose(Chan *)
-{
-}
-
-static long
-rtcread(Chan *c, void *a, long n, vlong off)
-{
- if(c->qid.path == Qdir)
- return devdirread(c, a, n, rtctab, nelem(rtctab), devgen);
- if(c->qid.path == Qrtc)
- return readnum(off, a, n, rtcsnarf(), 12);
-
- error(Egreg);
- return 0;
-}
-
-static long
-rtcwrite(Chan *, void *, long, vlong)
-{
- error(Egreg);
- return 0;
-}
-
-Dev rtcdevtab = {
- 'r',
- "rtc",
-
- rtcreset,
- devinit,
- rtcshutdown,
- rtcattach,
- rtcwalk,
- rtcstat,
- rtcopen,
- devcreate,
- rtcclose,
- rtcread,
- devbread,
- rtcwrite,
- devbwrite,
- devremove,
- devwstat,
-};
--- a/fns.h
+++ /dev/null
@@ -1,77 +1,0 @@
-#include "../port/portfns.h"
-
-#define KADDR(a) ((void*)(a))
-#define PADDR(a) ((uintptr)(a))
-
-#define userureg(ur) (((ur)->psr & PsrMask) == PsrMusr)
-
-void* ucallocalign(usize, int, usize);
-void* ucalloc(usize);
-
-int cmpswap(long *, long, long);
-int cas(long *, long, long);
-int tas(void *);
-
-void evenaddr(uintptr va);
-void procrestore(Proc *);
-void procsave(Proc *);
-void procsetup(Proc *);
-void procfork(Proc *);
-
-void coherence(void);
-void idlehands(void);
-void touser(void*);
-void setR13(uint, u32int*);
-ulong getdfsr(void);
-ulong getifsr(void);
-uintptr getdfar(void);
-uintptr getifar(void);
-void setvectors(uintptr);
-void breakpt(void);
-
-char* getconf(char*);
-int isaconfig(char *, int, ISAConf *);
-
-void mmuinvalidate(void);
-void* mmuuncache(void*, usize);
-uintptr cankaddr(uintptr);
-
-ulong µs(void);
-void delay(int);
-void microdelay(int);
-void cycles(uvlong*);
-
-void dumpureg(Ureg*);
-void dumpstackureg(Ureg*);
-
-void intrenable(int, void (*f)(Ureg *, void*), void *, int, char*);
-void intrdisable(int, void (*f)(Ureg *, void*), void *, int, char*);
-void intr(Ureg *);
-
-void uartinit(void);
-void mmuinit(void);
-void trapinit(void);
-void intrinit(void);
-void timerinit(void);
-void screeninit(void);
-
-void links(void);
-
-void l1icacheinv(void);
-void l1dcachewb(void);
-void l1dcacheinv(void);
-void l1dcachewbinv(void);
-void l1ucachewbinv(void);
-
-void l2idcacheinv(void);
-void l2idcachewb(void);
-void l2idcachewbinv(void);
-void l2ucachewbinv(void);
-
-
-void fpinit(void);
-void fpoff(void);
-void fpclear(void);
-
-void fpsave(FPsave *);
-void fprestore(FPsave *);
--- a/i2cn900.c
+++ /dev/null
@@ -1,224 +1,0 @@
-#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/i2c.h"
-
-enum {
- Rrev = 0x00,
- Rie = 0x04,
- Ris = 0x08,
- Ial = 1 << 0, /* arbitration lost */
- Inack = 1 << 1, /* no acknowledgement */
- Iardy = 1 << 2, /* address ready */
- Irrdy = 1 << 3, /* receive ready */
- Ixrdy = 1 << 4, /* transmit ready */
- Ibb = 1 << 12, /* bus busy */
- Iall = 0xffff,
-
- Rwe = 0x0c,
- Rsyss = 0x10,
- SSreset = 1 << 0, /* reset status */
-
- Rbuf = 0x14,
- Rcnt = 0x18,
- Rdata = 0x1c,
- Rsysc = 0x20,
- SCreset = 1 << 1, /* software reset */
-
- Rcon = 0x24,
- Cstt = 1 << 0, /* start condition */
- Cstp = 1 << 1, /* stop condiction */
- Cxoa3 = 1 << 4, /* expand address */
- Cxoa2 = 1 << 5,
- Cxoa1 = 1 << 6,
- Cxoa0 = 1 << 7,
- Cxa = 1 << 8,
- Ctrx = 1 << 9, /* transmit mode */
- Cmst = 1 << 10, /* master mode */
- Cstb = 1 << 11, /* start byte */
- Cen = 1 << 15, /* enable */
-
- Raddr = 0x2c,
-};
-
-#define csr32r(c, r) ((c)->io[(r)/4])
-#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
- u32int *io;
- ulong irq;
-
- Rendez;
-};
-
-static Ctlr ctlr[] = {
- { .io = (u32int*) PHYSI2C1, .irq = IRQI2C1 },
- { .io = (u32int*) PHYSI2C2, .irq = IRQI2C2 },
- { .io = (u32int*) PHYSI2C3, .irq = IRQI2C3 },
-};
-
-static void
-n900i2cwaitbus(Ctlr *ctlr)
-{
- /* FIXME: timeout here? */
- while(csr32r(ctlr, Ris) & Ibb)
- ;
-}
-
-static int
-n900i2cwaitirq(void *arg)
-{
- Ctlr *ctlr = arg; return csr32r(ctlr, Ris);
-}
-
-static uint
-n900i2cwait(Ctlr *ctlr)
-{
- uint s;
-
- /* FIXME: timeout here? */
- while(!(s = csr32r(ctlr, Ris))) {
- if(!up || !islo())
- continue;
-
- tsleep(ctlr, n900i2cwaitirq, ctlr, 5);
- }
-
- return s;
-}
-
-static void
-n900i2cflush(Ctlr *ctlr)
-{
- while(csr32r(ctlr, Ris) & Irrdy) {
- USED(csr32r(ctlr, Rdata));
- csr32w(ctlr, Ris, Irrdy);
- }
-}
-
-static void
-n900i2cintr(Ureg *, void *arg)
-{
- Ctlr *ctlr;
-
- ctlr = arg;
- wakeup(ctlr);
-}
-
-static int
-n900i2cinit(I2Cbus *bus)
-{
- Ctlr *ctlr;
-
- /* reset the ctlr */
- ctlr = bus->ctlr;
- csr32w(ctlr, Rsysc, SCreset);
- csr32w(ctlr, Rcon, Cen);
-
- /* FIXME: timeout here? */
- while(!(csr32r(ctlr, Rsyss) & SSreset))
- ;
-
- intrenable(ctlr->irq, n900i2cintr, ctlr, 0, bus->name);
- return 0;
-}
-
-static int
-n900i2cio(I2Cbus *bus, uchar *pkt, int olen, int ilen)
-{
- Ctlr *ctlr;
- uint con, addr, stat;
- uint o;
-
- ctlr = bus->ctlr;
- if(olen <= 0 || pkt == nil)
- return -1;
-
- o = 0;
- con = Cen | Cmst | Ctrx | Cstp | Cstt;
- if((pkt[o] & 0xf8) == 0xf0) {
- /* 10-bit address: qemu has bugs, nothing on the n900 needs them.
- * con |= Cxa;
- * addr = ((pkt[o++] & 6) << 7) | pkt[o++];
- */
- return -1;
- } else {
- /* 7-bit address */
- addr = pkt[o++] >> 1;
- }
-
- /* wait for bus */
- n900i2cwaitbus(ctlr);
-
- /* first attempt to probe, will get nack here if no dev */
- csr32w(ctlr, Rcnt, olen);
- csr32w(ctlr, Raddr, addr);
- csr32w(ctlr, Rcon, con);
- stat = n900i2cwait(ctlr);
- if(stat & Inack || stat & Ial) {
- o = -1; goto err;
- }
-
- /* transmit */
- while(o < olen) {
- stat = n900i2cwait(ctlr);
- if(stat == 0 || stat & Inack || stat & Ial) {
- o = -1; goto err;
- }
-
- if(stat & Iardy) {
- csr32w(ctlr, Ris, Iardy);
- break;
- }
-
- if(stat & Ixrdy) {
- csr32w(ctlr, Rdata, pkt[o++]);
- csr32w(ctlr, Ris, Ixrdy);
- }
- }
-
- /* receive */
- csr32w(ctlr, Rcnt, ilen);
- csr32w(ctlr, Raddr, addr);
- csr32w(ctlr, Rcon, Cen | Cmst | Cstp | Cstt);
- while(o < olen + ilen) {
- stat = n900i2cwait(ctlr);
- if(stat == 0 || stat & Inack || stat & Ial) {
- o = -1; goto err;
- }
-
- if(stat & Iardy) {
- csr32w(ctlr, Ris, Iardy);
- break;
- }
-
- if(stat & Irrdy) {
- pkt[o++] = csr32r(ctlr, Rdata);
- csr32w(ctlr, Ris, Irrdy);
- }
- }
-
-err:
- n900i2cflush(ctlr);
- csr32w(ctlr, Ris, Iall);
- return o;
-}
-
-void
-i2cn900link(void)
-{
- int i;
- static I2Cbus bus[] = {
- { "i2c1", 4000000, &ctlr[0], n900i2cinit, n900i2cio },
- { "i2c2", 4000000, &ctlr[1], n900i2cinit, n900i2cio },
- { "i2c3", 4000000, &ctlr[2], n900i2cinit, n900i2cio },
- };
-
- for(i = 0; i < nelem(bus); i++)
- addi2cbus(&bus[i]);
-}
--- a/init9.s
+++ /dev/null
@@ -1,12 +1,0 @@
-TEXT main(SB), 1, $8
- MOVW $setR12(SB), R12
- MOVW $boot(SB), R0
-
- ADD $12, R13, R1
-
- MOVW R0, 4(R13)
- MOVW R1, 8(R13)
-
- BL startboot(SB)
-_limbo:
- B _limbo
--- a/intr.c
+++ /dev/null
@@ -1,199 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-enum {
- Rrev = 0x00,
- Rsysconf = 0x10,
- Rsysstat = 0x14,
- Rirq = 0x40,
- Rfiq = 0x44,
- Rcontrol = 0x48,
- Cnewirqgen = 1<<0,
- Rprot = 0x4c,
- Ridle = 0x50,
- Rirqprio = 0x60,
- Rfiqprio = 0x64,
- Rthreshold = 0x68,
-
- Ritr = 0x80,
- Rmir = 0x84,
- Rmirclear = 0x88,
- Rmirset = 0x8c,
- Risrset = 0x90,
- Risrclear = 0x94,
- Rirqpend = 0x98,
- Rfiqpend = 0x9c,
-
- Rilr = 0x100,
-};
-
-enum {
- Nmir = 3,
- Nitr = 3,
- Nintrs = 96,
-};
-
-#define Ritrn(n) (Ritrn + 32*(n))
-#define Rmirn(n) (Rmirn + 32*(n))
-#define Rmirclearn(n) (Rmirclear + 32*(n))
-#define Rmirsetn(n) (Rmirset + 32*(n))
-#define Rirqpendn(n) (Rirqpend + 32*(n))
-#define Rfiqpendn(n) (Rfiqpend + 32*(n))
-
-#define Rilrn(n) (Rilr + 4*(n))
-
-#define csr32r(c, r) ((c)->io[(r)/4])
-#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
-
-typedef struct Intr Intr;
-typedef struct Ctlr Ctlr;
-
-struct Intr {
- void (*f)(Ureg *, void *);
- void *arg;
- char *name;
-
- Intr *next;
-};
-
-struct Ctlr {
- Lock;
-
- u32int *io;
-
- Intr *intrs[Nintrs];
-};
-
-static Ctlr ctlrmpu = { .io = (u32int*) PHYSINTRMPU };
-
-void
-intrinit(void)
-{
- Ctlr *ctlr = &ctlrmpu;
- int i;
-
- /* mask all interrupts */
- for (i = 0; i < Nmir; i++)
- csr32w(ctlr, Rmirsetn(i), ~0);
-
- /* protection off, threshold off, set all intrs priority 0, mapped to irq */
- csr32w(ctlr, Rcontrol, 0);
- csr32w(ctlr, Rthreshold, 0xff);
- for (i = 0; i < Nintrs; i++)
- csr32w(ctlr, Rilrn(i), 0);
-
- coherence();
-}
-
-void
-intrenable(int n, void (*f)(Ureg *, void *), void *arg, int, char *name)
-{
- Ctlr *ctlr = &ctlrmpu;
- Intr *intr;
-
- if (n >= nelem(ctlr->intrs) || n < 0)
- panic("intrenable %d", n);
-
- intr = malloc(sizeof(*intr));
- if(!intr)
- panic("intrenable: no memory for interrupt");
-
- intr->f = f;
- intr->arg = arg;
- intr->name = name;
-
- lock(ctlr);
-
- /* chain this interrupt */
- intr->next = ctlr->intrs[n];
- ctlr->intrs[n] = intr;
-
- /* new handler assigned, unmask this interrupt */
- csr32w(ctlr, Rmirclearn(n >> 5), 1 << (n & 31));
-
- unlock(ctlr);
- coherence();
-}
-
-void
-intrdisable(int n, void (*f)(Ureg *, void *), void *arg, int, char *name)
-{
- Ctlr *ctlr = &ctlrmpu;
- Intr *intr, **ip;
-
- if (n >= nelem(ctlr->intrs) || n < 0)
- panic("intrdisable %d", n);
-
- lock(ctlr);
- for(ip = &ctlr->intrs[n]; intr = *ip; ip = &intr->next) {
- if(intr->f == f && intr->arg == arg && strcmp(intr->name, name) == 0) {
- *ip = intr->next;
- free(intr);
- break;
- }
- }
-
- /* no more handlers assigned, mask this interrupt */
- if(ctlr->intrs[n] == nil)
- csr32w(ctlr, Rmirsetn(n >> 5), 1 << (n & 31));
-
- unlock(ctlr);
- coherence();
-}
-
-void
-intr(Ureg *ureg)
-{
- Ctlr *ctlr = &ctlrmpu;
- Intr *intr;
- int n, h, s;
-
- h = 0;
- n = csr32r(ctlr, Rirq) & 0x7f;
- s = csr32r(ctlr, Rirq) & ~0x7f;
- if(s) {
- /* interrupt controller reports spurious interrupt flag. */
- iprint("cpu%d: spurious interrupt\n", m->machno);
- csr32w(ctlr, Rcontrol, Cnewirqgen);
- return;
- }
-
- if(n >= nelem(ctlr->intrs)) {
- iprint("cpu%d: invalid interrupt %d\n", m->machno, n);
- csr32w(ctlr, Rcontrol, Cnewirqgen);
- return;
- }
-
- /* call all handlers for this interrupt number */
- for (intr = ctlr->intrs[n]; intr; intr = intr->next) {
- if(intr->f) {
- if(islo())
- panic("trap: islo() in interrupt handler\n");
-
- intr->f(ureg, intr->arg);
- if(islo())
- panic("trap: islo() after interrupt handler\n");
- }
-
- h++;
- }
-
- csr32w(ctlr, Rcontrol, Cnewirqgen);
- coherence();
-
- if(!h) iprint("cpu%d: spurious interrupt %d\n", m->machno, n);
- if(up) {
- if(n >= IRQTIMER1 && n <= IRQTIMER11) {
- if(up->delaysched) {
- splhi();
- sched();
- }
- } else {
- preempted();
- }
- }
-}
--- a/io.h
+++ /dev/null
@@ -1,63 +1,0 @@
-#define PHYSL4 0x40000000
-#define PHYSL4END 0x50000000
-
-#define PHYSTIMER1 0x48318000
-#define PHYSTIMER2 0x49032000
-#define PHYSTIMER3 0x49034000
-#define PHYSTIMER4 0x49036000
-#define PHYSTIMER5 0x49038000
-#define PHYSTIMER6 0x4903a000
-#define PHYSTIMER7 0x4903c000
-#define PHYSTIMER8 0x4903e000
-#define PHYSTIMER9 0x49040000
-#define PHYSTIMER10 0x48086000
-#define PHYSTIMER11 0x48088000
-
-#define PHYSUART1 0x4806a000
-#define PHYSUART2 0x4806c000
-#define PHYSUART3 0x49020000
-
-#define PHYSI2C1 0x48070000
-#define PHYSI2C2 0x48072000
-#define PHYSI2C3 0x48060000
-
-#define PHYSMMC1 0x4809c000
-#define PHYSMMC2 0x480b4000
-#define PHYSMMC3 0x480ad000
-
-#define PHYSDSS 0x48050000
-
-#define PHYSINTRMODEM 0x480c7000
-#define PHYSINTRMPU 0x48200000
-
-#define PHYSL3 0x68000000
-#define PHYSL3END 0x70000000
-
-#define PHYSMEM 0x80000000
-#define PHYSMEMEND 0x90000000
-
-#define IRQTIMER1 37
-#define IRQTIMER2 38
-#define IRQTIMER3 39
-#define IRQTIMER4 40
-#define IRQTIMER5 41
-#define IRQTIMER6 42
-#define IRQTIMER7 43
-#define IRQTIMER8 44
-#define IRQTIMER9 45
-#define IRQTIMER10 46
-#define IRQTIMER11 47
-
-#define IRQUART1 72
-#define IRQUART2 73
-#define IRQUART3 74
-
-#define IRQI2C1 56
-#define IRQI2C2 57
-#define IRQI2C3 61
-
-#define IRQMMC1 83
-#define IRQMMC2 86
-#define IRQMMC3 94
-
-#define IRQTWL 7
--- a/l.s
+++ /dev/null
@@ -1,354 +1,0 @@
-#include "mem.h"
-#include "io.h"
-
-TEXT _start(SB), $-4
- /* load static base */
- MOVW $setR12(SB), R12
-
- /* fiqs and irqs off, svc mode (cortex a8 trm figure 2.12) */
- MOVW $(PsrDfiq|PsrDirq|PsrMsvc), R0
- MOVW R0, CPSR
-
- /* mmu and l1 caches off (cortex a8 trm table 3.46) */
- MRC 15, 0, R0, C1, C0, 0
- BIC $(1<<12), R0 /* level 1 instruction cache */
- BIC $(1<<1), R0 /* level 1 data cache */
- BIC $(1<<0), R0 /* mmu */
- MCR 15, 0, R0, C1, C0, 0
- ISB
-
- /* l2 caches off (cortex a8 trm table 3.49) */
- MCR 15, 0, R0, C1, C0, 1
- BIC $(1<<1), R0 /* level 2 cache */
- MCR 15, 0, R0, C1, C0, 1
- ISB
-
- /* fill mach with 0 */
- MOVW $0, R0
- MOVW $MACH(0), R1
- MOVW $MACH(MAXMACH), R2
-zeromach:
- MOVW R0, (R1)
- ADD $4, R1
- CMP R1, R2
- BNE zeromach
-
- /* fill page tables with 0 */
- MOVW R0, R0
- MOVW $MACHL1(0), R1 /* bottom of l1 tables */
- MOVW $MACHL1(MAXMACH), R2 /* top of l1 tables */
-zeropte:
- MOVW R0, (R1)
- ADD $4, R1
- CMP R1, R2
- BNE zeropte
-
- /* fill bss with 0 */
- MOVW $0, R0
- MOVW $edata(SB), R1
- MOVW $end(SB), R2
-zerobss:
- MOVW R0, (R1)
- ADD $4, R1
- CMP R1, R2
- BNE zerobss
-
- /* fill page tables for memory:
- * 1mb section, cached, buffered, kernel read-write */
- MOVW $((1<<1)|(1<<2)|(1<<3)|(1<<10)), R1
- MOVW $PHYSMEM, R2
- MOVW $(MACHL1(0)+L1X(PHYSMEM)), R3
- MOVW $(MACHL1(0)+L1X(PHYSMEMEND)), R4
-ptemem:
- ORR R2, R1, R0
- MOVW R0, (R3)
- ADD $(MiB), R2
- ADD $4, R3
- CMP R3, R4
- BNE ptemem
-
- /* fill page tables for l4 interconnect:
- * 1mb section, kernel read-write */
- MOVW $((1<<1)|(1<<4)|(1<<10)), R1
- MOVW $PHYSL4, R2
- MOVW $(MACHL1(0)+L1X(PHYSL4)), R3
- MOVW $(MACHL1(0)+L1X(PHYSL4END)), R4
-ptel4:
- ORR R2, R1, R0
- MOVW R0, (R3)
- ADD $(MiB), R2
- ADD $4, R3
- CMP R3, R4
- BNE ptel4
-
- /* fill page tables for l3 interconnect:
- * 1mb section, kernel read-write */
- MOVW $((1<<1)|(1<<4)|(1<<10)), R1
- MOVW $PHYSL3, R2
- MOVW $(MACHL1(0)+L1X(PHYSL3)), R3
- MOVW $(MACHL1(0)+L1X(PHYSL3END)), R4
-ptel3:
- ORR R2, R1, R0
- MOVW R0, (R3)
- ADD $(MiB), R2
- ADD $4, R3
- CMP R3, R4
- BNE ptel3
-
- /* fpu on (set bits 20-23 in CPACR) but disabled */
- MRC 15, 0, R0, C1, C0, 2
- ORR $(0xf<<20), R0
- MCR 15, 0, R0, C1, C0, 2
-
- VMRS(FPEXC, 0)
- BIC $(FPEXCEX|FPEXCEN), R0
- VMSR(0, FPEXC)
-
- /* invalidate caches */
- BL l1dcacheinv(SB)
- BL l1icacheinv(SB)
-
- /* l2 caches back on */
- MRC 15, 0, R0, C1, C0, 1
- ORR $(1<<1), R0
- MCR 15, 0, R0, C1, C0, 1
-
- /* l1 caches back on */
- MRC 15, 0, R0, C1, C0, 0
- ORR $(1<<12), R0
- ORR $(1<<1), R0
- MCR 15, 0, R0, C1, C0, 0
-
- /* set domain access control to client. */
- MOVW $1, R0
- BL putdac(SB)
-
- /* set translation table base */
- MOVW $MACHL1(0), R0
- BL putttb(SB)
-
- /* mmu on, time to get virtual */
- MOVW $virt(SB), R2
- BL mmuinvalidate(SB)
- BL mmuenable(SB)
- MOVW R2, R15
-
-TEXT virt(SB), $-4
- /* setup register variables */
- MOVW $setR12(SB), R12
- MOVW $(MACH(0)), R(Rmach)
- MOVW $0, R(Rup)
-
- /* setup stack in mach */
- MOVW $(MACH(0)), R13
- ADD $(MACHSZ), R13
- SUB $4, R13
-
- BL main(SB)
-
-_limbo:
- BL idlehands(SB)
- B _limbo
-
- /* hack to load div */
- BL _div(SB)
-
-
-TEXT mmuenable(SB), 1, $-4
- MRC 15, 0, R0, C1, C0, 0
- ORR $(1<<0), R0
- MCR 15, 0, R0, C1, C0, 0
- MCR 15, 0, R0, C7, C5, 6
- DMB; DSB; ISB
- RET
-
-TEXT mmudisable(SB), 1, $-4
- MRC 15, 0, R0, C1, C0, 0
- BIC $(1<<0), R0
- MCR 15, 0, R0, C1, C0, 0
- MCR 15, 0, R0, C7, C5, 6
- DMB; DSB; ISB
- RET
-
-TEXT mmuinvalidate(SB), 1, $-4
- MOVW CPSR, R1
- CPSID
-
- MOVW R15, R0
- MCR 15, 0, R0, C8, C7, 0
- MCR 15, 0, R0, C7, C5, 6
- DMB; DSB; ISB
-
- MOVW R1, CPSR
- RET
-
-/* get and put domain access control */
-TEXT getdac(SB), 1, $-4; MCR 15, 0, R0, C3, C0; RET
-TEXT putdac(SB), 1, $-4
- MRC 15, 0, R0, C3, C0
- ISB
- RET
-
-
-/* get and put translation table base */
-TEXT getttb(SB), 1, $-4; MRC 15, 0, R0, C2, C0, 0; RET
-TEXT putttb(SB), 1, $-4
- MCR 15, 0, R0, C2, C0, 0
- MCR 15, 0, R0, C2, C0, 1
- ISB
- RET
-
-TEXT getdfsr(SB), $-4; MRC 15, 0, R0, C5, C0, 0; RET
-TEXT getifsr(SB), $-4; MRC 15, 0, R0, C5, C0, 1; RET
-TEXT getdfar(SB), $-4; MRC 15, 0, R0, C6, C0, 0; RET
-TEXT getifar(SB), $-4; MRC 15, 0, R0, C6, C0, 2; RET
-
-TEXT setvectors(SB), $-4;
- MCR 15, 0, R0, C12, C0, 0
- RET
-
-TEXT setlabel(SB), $-4
- MOVW R13, 0(R0)
- MOVW R14, 4(R0)
- MOVW $0, R0
- RET
-
-TEXT gotolabel(SB), $-4
- MOVW 0(R0), R13
- MOVW 4(R0), R14
- MOVW $1, R0
- RET
-
-TEXT cas(SB), $0
-TEXT cmpswap(SB), $0
- MOVW ov+4(FP), R1
- MOVW nv+8(FP), R2
-casspin:
- LDREX (R0), R3
- CMP R3, R1
- BNE casfail
- STREX R2, (R0), R4
- CMP $0, R4
- BNE casspin
- MOVW $1, R0
- DMB
- RET
-casfail:
- CLREX
- MOVW $0, R0
- RET
-
-TEXT tas(SB), $0
-TEXT _tas(SB), $0
- MOVW $0xdeaddead, R2
-tasspin:
- LDREX (R0), R1
- STREX R2, (R0), R3
- CMP $0, R3
- BNE tasspin
- MOVW R1, R0
- DMB
- RET
-
-TEXT idlehands(SB), $-4
- DMB; DSB; ISB
- WFI
- RET
-
-TEXT coherence(SB), $-4
- DMB; DSB; ISB
- RET
-
-TEXT splhi(SB), $-4
- MOVW R14, 4(R(Rmach))
- MOVW CPSR, R0
- CPSID
- RET
-
-TEXT spllo(SB), $-4
- MOVW CPSR, R0
- CPSIE
- RET
-
-TEXT splx(SB), $-4
- MOVW R14, 4(R(Rmach))
- MOVW R0, R1
- MOVW CPSR, R0
- MOVW R1, CPSR
- RET
-
-TEXT spldone(SB), $-4
- RET
-
-TEXT islo(SB), $0
- MOVW CPSR, R0
- AND $(PsrDirq), R0
- EOR $(PsrDirq), R0
- RET
-
-TEXT perfticks(SB), $0
- MCR 15, 0, R0, C9, C13, 0
- RET
-
-TEXT touser(SB), $-4
- MOVM.DB.W [R0], (R13)
- MOVM.S (R13), [R13]
- ADD $4, R13
-
- MOVW CPSR, R0
- BIC $(PsrMask|PsrDirq|PsrDfiq), R0
- ORR $PsrMusr, R0
- MOVW R0, SPSR
-
- MOVW $(UTZERO+0x20), R0
- MOVM.DB.W [R0], (R13)
-
- MOVM.IA.S.W (R13), [R15]
-
-TEXT forkret(SB), $-4
- ADD $(15*4), R13
- MOVW 8(R13), R14
- MOVW 4(R13), R0
- MOVW R0, SPSR
- MOVM.DB.S (R13), [R0-R14]
- ADD $8, R13
- MOVM.IA.S.W (R13), [R15]
-
-TEXT peek(SB), $0
- MOVW src+0(FP), R0
- MOVW dst+4(FP), R1
- MOVW cnt+8(FP), R2
-TEXT _peekinst(SB), $0
-_peekloop:
- MOVB (R0), R3
- MOVB R3, (R1)
- SUB.S $1, R0
- BNE _peekloop
- RET
-
-TEXT fpinit(SB), $0
- MOVW $FPEXCEN, R0
- VMSR(0, FPEXC)
- MOVW $0, R0
- VMSR(0, FPSCR)
- RET
-
-TEXT fpoff(SB), $0
-TEXT fpclear(SB), $0
- MOVW $0, R1
- VMSR(1, FPEXC)
- RET
-
-TEXT fpsave(SB), $0
- VMRS(FPEXC, 1)
- VMRS(FPSCR, 2)
- MOVM.IA.W [R1-R2], (R0)
- VSTMIA
- RET
-
-TEXT fprestore(SB), $0
- MOVM.IA.W (R0), [R1-R2]
- VMSR(1, FPEXC)
- VMSR(2, FPSCR)
- VLDMIA
- RET
--- a/lcache.s
+++ /dev/null
@@ -1,121 +1,0 @@
-#include "mem.h"
-#include "io.h"
-
-/* l1 instruction cache invalidate */
-TEXT l1icacheinv(SB), $-4
- MOVW $0, R0
- MCR 15, 0, R0, C7, C5, 0
- ISB
- RET
-
-/* l1 data cache writeback */
-TEXT l1dcachewb(SB), $-4
- MOVW $cacheopwb(SB), R0
- MOVW $0, R1
- B cacheop(SB)
-
-/* l1 data cache invalidate */
-TEXT l1dcacheinv(SB), $-4
- MOVW $cacheopinv(SB), R0
- MOVW $0, R1
- B cacheop(SB)
-
-/* l1 data cache writeback + invalidate */
-TEXT l1dcachewbinv(SB), $-4
- MOVW $cacheopwbinv(SB), R0
- MOVW $0, R1
- B cacheop(SB)
-
-/* l1 unified instruction + data cache writeback + invalidate */
-TEXT l1ucachewbinv(SB), $-4
- MOVM.DB.W [R14], (SP)
- BL l1dcachewbinv(SB)
- BL l1icacheinv(SB)
- MOVM.IA.W (SP), [R14]
- RET
-
-/* l2 instruction + data cache writeback */
-TEXT l2idcachewb(SB), $-4
- MOVW $cacheopwb(SB), R0
- MOVW $1, R1
- B cacheop(SB)
-
-/* l2 instruction + data cache invalidate */
-TEXT l2idcacheinv(SB), $-4
- MOVW $cacheopinv(SB), R0
- MOVW $1, R1
- B cacheop(SB)
-
-/* l2 instruction + data cache writeback + invalidate */
-TEXT l2idcachewbinv(SB), $-4
- MOVW $cacheopwbinv(SB), R0
- MOVW $1, R1
- B cacheop(SB)
-
-/* l1 unified instruction + data cache writeback + invalidate */
-TEXT l2ucachewbinv(SB), $-4
- MOVM.DB.W [R14], (SP)
- BL l2idcachewbinv(SB)
- BL l2idcacheinv(SB)
- MOVM.IA.W (SP), [R14]
- RET
-
-/* set/way operations for cacheop */
-TEXT cacheopwb(SB), $-4; MCR 15, 0, R0, C7, C10, 2; RET
-TEXT cacheopinv(SB), $-4; MCR 15, 0, R0, C7, C6, 2; RET
-TEXT cacheopwbinv(SB), $-4; MCR 15, 0, R0, C7, C14, 2; RET
-
-#define Rop R2
-#define Rcache R3
-#define Rways R4
-#define Rwayshift R5
-#define Rsets R6
-#define Rsetshift R7
-#define Rset R8
-
-/* apply a cache operation to the whole cache */
-TEXT cacheop(SB), $-4
- /* stash */
- MOVM.DB.W [R2,R14], (SP)
- MOVW R0, Rop
- MOVW R1, Rcache
-
- /* get cache geometry */
- MCR 15, 2, Rcache, C0, C0, 0; ISB
- MRC 15, 1, R0, C0, C0, 0
-
- /* compute ways = ((R0 >> 3) & 0x3ff) + 1) */
- SRA $3, R0, Rways
- AND $0x3ff, Rways
- ADD $1, Rways
-
- /* compute wayshift = log₂(ways) */
- CLZ(4, 5) /* Rways, Rwayshift */
- ADD $1, Rwayshift
-
- /* compute sets = ((R0 >> 13) & 0x7fff) + 1) */
- SRA $13, R0, Rsets
- AND $0x7fff, Rsets
- ADD $1, Rsets
-
- /* compute setshift = log₂(cache line size) */
- AND $0x7, R0, Rsetshift
- ADD $4, Rsetshift
-
-cacheopways:
- MOVW Rsets, Rset
-cacheopsets:
- /* compute set / way register contents */
- SLL Rwayshift, Rways, R0
- SLL Rsetshift, Rset, R1
- ORR R1, R0
- SLL $1, Rcache, R1
- ORR R1, R0
-
- BL (Rop)
- SUB $1, Rset; CMP $0, Rset; BEQ cacheopsets /* loop sets */
- SUB $1, Rways; CMP $0, Rways; BEQ cacheopways /* loop ways */
-
- /* restore */
- MOVM.IA.W (SP), [R2,R14]
- RET
--- a/ltrap.s
+++ /dev/null
@@ -1,201 +1,0 @@
-#include "mem.h"
-#include "io.h"
-
-TEXT vectors(SB), $-4
- MOVW 24(R15), R15
- MOVW 24(R15), R15
- MOVW 24(R15), R15
- MOVW 24(R15), R15
- MOVW 24(R15), R15
- MOVW 24(R15), R15
- MOVW 24(R15), R15
- MOVW 24(R15), R15
-
-TEXT vtable(SB), $-4
- WORD $_vund(SB)
- WORD $_vund(SB)
- WORD $_vsvc(SB)
- WORD $_viabt(SB)
- WORD $_vdabt(SB)
- WORD $_vund(SB)
- WORD $_virq(SB)
- WORD $_vfiq(SB)
-
-TEXT _vsvc(SB), $-4
- CLREX
- DSB
-
- /* stash in ureg */
- MOVM.DB.W [R14], (R13) /* ureg->pc */
- MOVW SPSR, R14
- MOVM.DB.W [R14], (R13) /* ureg->psr */
- MOVW $PsrMsvc, R14
- MOVM.DB.W [R14], (R13) /* ureg->type */
-
- /* save user regs.
- * not MOVM.DB.W.S because the saved value of R13 is undefined.
- * (arm v7 manual §A8.8.199) */
- MOVM.DB.S [R0-R14], (R13)
- SUB $(15*4), R13
-
- /* get our sb, mach, up */
- MOVW $setR12(SB), R12
- MOVW $(MACH(0)), R(Rmach)
- MOVW 8(R(Rmach)), R(Rup)
-
- /* make space for debugger and go to syscall passing ureg */
- MOVW R13, R0
- SUB $8, R13
- BL syscall(SB)
- ADD $8, R13
-
- /* restore link, spsr */
- ADD $(15*4), R13
- MOVW 8(R13), R14
- MOVW 4(R13), R0
- MOVW R0, SPSR
-
- /* restore user regs */
- MOVM.DB.S (R13), [R0-R14]
-
- /* pop past ureg->type, ureg->psr and restore ureg->pc.
- * omap and others have RFE here but 5a has no idea about newer instructions
- * and simulates it with the MOVM below */
- ADD $8, R13
- MOVM.IA.S.W (R13), [R15]
-
-TEXT _viabt(SB), $-4
- CLREX
- DSB
- MOVM.IA [R0-R4], (R13)
- MOVW $PsrMiabt, R0
- B _vswitch
-
-TEXT _vdabt(SB), $-4
- CLREX
- DSB
- MOVM.IA [R0-R4], (R13)
- MOVW $PsrMdabt, R0
- B _vswitch
-
-TEXT _virq(SB), $-4
- CLREX
- DSB
- MOVM.IA [R0-R4], (R13)
- MOVW $PsrMirq, R0
- B _vswitch
-
-TEXT _vfiq(SB), $-4
- CLREX
- DSB
- MOVM.IA [R0-R4], (R13)
- MOVW $PsrMfiq, R0
- B _vswitch
-
-TEXT _vund(SB), $-4
- CLREX
- DSB
- MOVM.IA [R0-R4], (R13)
- MOVW $PsrMund, R0
- B _vswitch
-
-_vswitch:
- /* stash pointer to previous R0-R4, stash SPSR and R14 for ureg */
- MOVW SPSR, R1
- MOVW R14, R2
- MOVW R13, R3
-
- /* back to svc mode */
- MOVW CPSR, R14
- BIC $PsrMask, R14
- ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
- MOVW R14, CPSR
-
- /* from user or kernel mode? */
- AND.S $0xf, R1, R4
- BEQ _vuser
-
- /* from kernel mode */
- /* set ureg->type, ureg->psr, ureg->pc */
- MOVM.DB.W [R0-R2], (R13)
- MOVM.IA (R3), [R0-R4]
-
- /* save kernel regs
- * not MOVM.DB.W.S because the saved value of R13 is undefined.
- * (arm v7 manual §A8.8.199) */
- MOVM.DB [R0-R14], (R13)
- SUB $(15*4), R13
-
- /* get our sb, mach, up */
- MOVW $setR12(SB), R12
-
- /* make space for debugger and go to trap passing ureg */
- MOVW R13, R0
- SUB $8, R13
- BL trap(SB)
- ADD $8, R13
-
- /* restore link, spsr */
- ADD $(15*4), R13
- MOVW 8(R13), R14
- MOVW 4(R13), R0
- MOVW R0, SPSR
-
- /* restore kernel regs */
- MOVM.DB (R13), [R0-R14]
-
- /* pop past ureg->type, ureg->psr, and restore ureg->pc. */
- ADD $8, R13
- MOVM.IA.S.W (R13), [R15]
-
-_vuser:
- /* from user mode */
- /* set ureg->type, ureg->psr, ureg->pc */
- MOVM.DB.W [R0-R2], (R13)
- MOVM.IA (R3), [R0-R4]
-
- /* save kernel regs
- * not MOVM.DB.W.S because the saved value of R13 is undefined.
- * (arm v7 manual §A8.8.199) */
- MOVM.DB.S [R0-R14], (R13)
- SUB $(15*4), R13
-
- /* get our sb, mach, up */
- MOVW $setR12(SB), R12
- MOVW $(MACH(0)), R(Rmach)
- MOVW 8(R(Rmach)), R(Rup)
-
- /* make space for debugger and go to trap passing ureg */
- MOVW R13, R0
- SUB $8, R13
- BL trap(SB)
- ADD $8, R13
-
- /* restore link, spsr */
- ADD $(15*4), R13
- MOVW 8(R13), R14
- MOVW 4(R13), R0
- MOVW R0, SPSR
-
- /* restore kernel regs */
- MOVM.DB.S (R13), [R0-R14]
-
- /* pop past ureg->type, ureg->psr, and restore ureg->pc */
- ADD $8, R13
- MOVM.IA.S.W (R13), [R15]
-
-TEXT setR13(SB), $-4
- MOVW 4(FP), R1
-
- /* switch to new mode */
- MOVW CPSR, R2
- BIC $PsrMask, R2, R3
- ORR R0, R3
- MOVW R3, CPSR
-
- /* set r13 */
- MOVW R1, R13
-
- /* back to old mode */
- MOVW R2, CPSR
- RET
--- a/main.c
+++ /dev/null
@@ -1,222 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-
-#include "tos.h"
-#include "ureg.h"
-#include "pool.h"
-
-#define MAXCONF 64
-
-static char *confname[MAXCONF];
-static char *confval[MAXCONF];
-static int nconf;
-
-Conf conf;
-
-char*
-getconf(char *name)
-{
- int i;
-
- for(i = 0; i < nconf; i++)
- if(cistrcmp(confname[i], name) == 0)
- return confval[i];
-
- return nil;
-}
-
-int
-isaconfig(char *, int, ISAConf *)
-{
- return 0;
-}
-
-void
-cpuidprint(void)
-{
- /* FIXME: how fast are we really? */
- print("cpu%d: %dMHz ARM Cortex-A8\n", m->machno, 600);
-}
-
-void
-plan9iniinit(void)
-{
- char *c, *p, *q;
- char *v[MAXCONF];
- int i, n;
-
- c = (char*) CONFADDR;
- for(p = q = c; *q; q++) {
- if(*q == '\r')
- continue;
- if(*q == '\t')
- *q = ' ';
- *p++ = *q;
- }
-
- *p = 0;
- n = getfields(c, v, MAXCONF, 1, "\n");
- for(i = 0; i < n; i++) {
- if(v[i][0] == '#')
- continue;
-
- c = strchr(v[i], '=');
- if(!c)
- continue;
-
- confname[nconf] = v[i];
- confval[nconf] = c;
- nconf++;
- }
-}
-
-void
-confinit(void)
-{
- int i;
- uintptr pa;
- ulong kp;
-
- conf.nmach = 1;
- conf.npage = 0;
- conf.mem[0].base = PHYSMEM;
- conf.mem[0].limit = PHYSMEMEND;
-
- pa = PADDR(PGROUND((uintptr)end));
- for(i = 0; i < nelem(conf.mem); i++) {
- if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
- conf.mem[i].base = pa;
-
- conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
- conf.npage += conf.mem[i].npage;
- }
-
- conf.upages = (conf.npage*80)/100;
- conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
-
- conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
- if(cpuserver)
- conf.nproc *= 3;
- if(conf.nproc > 4000)
- conf.nproc = 4000;
-
- conf.nswap = conf.npage*3;
- conf.nswppo = 4096;
- conf.nimage = 200;
- conf.copymode = 0;
-
- kp = conf.npage - conf.upages;
- kp *= BY2PG;
- kp -= conf.upages * sizeof(Page)
- + conf.nproc * sizeof(Proc*)
- + conf.nimage * sizeof(Image)
- + conf.nswap
- + conf.nswppo * sizeof(Page*);
-
- mainmem->maxsize = kp;
- if(!cpuserver)
- imagmem->maxsize = kp;
-}
-
-void
-machinit(void)
-{
- m->machno = 0;
-
- active.machs[0] = 1;
- active.exiting = 0;
-
- up = nil;
-}
-
-void
-init0(void)
-{
- char **sp, buf[KNAMELEN];
- int i;
-
- chandevinit();
- if(!waserror()) {
- ksetenv("cputype", "arm", 0);
- if(cpuserver)
- ksetenv("service", "cpu", 0);
- else
- ksetenv("service", "terminal", 0);
-
- snprint(buf, sizeof(buf), "nokia %s", conffile);
- ksetenv("terminal", buf, 0);
- ksetenv("console", "2", 0);
- ksetenv("kbmap", "n900", 0);
- for(i = 0; i < nconf; i++) {
- if(*confname[i] != '*')
- ksetenv(confname[i], confval[i], 0);
- ksetenv(confname[i], confval[i], 1);
- }
-
- poperror();
- }
-
- kproc("alarm", alarmkproc, 0);
-
- /* prepare stack for boot */
- sp = (char**)(USTKTOP - sizeof(Tos) - 8 - sizeof(sp[0])*4);
- sp[3] = sp[2] = sp[1] = nil;
- strcpy(sp[0] = (char*)&sp[4], "boot");
- touser(sp);
-}
-
-void
-main(void)
-{
- uartinit();
- machinit();
- mmuinit();
- plan9iniinit();
- confinit();
- printinit();
- quotefmtinstall();
- fmtinstall(L'H', encodefmt);
- print("\nPlan 9\n");
-
- xinit();
- trapinit();
- intrinit();
- timerinit();
- cpuidprint();
- procinit0();
- initseg();
- links();
-
- screeninit();
- chandevreset();
-
- pageinit();
- userinit();
- schedinit();
-
- panic("schedinit returned");
-}
-
-void
-exit(int)
-{
- for(;;)
- idlehands();
-}
-
-void
-reboot(void *, void *, ulong)
-{
-}
-
-void
-setupwatchpts(Proc *, Watchpt *, int n)
-{
- if(n > 0)
- error("no watchpoints");
-}
--- a/mem.h
+++ /dev/null
@@ -1,105 +1,0 @@
-#define KiB (1024u)
-#define MiB (1024*1024u)
-#define GiB (1024*1024*1024u)
-
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-
-#define Rmach 10
-#define Rup 9
-
-#define HZ (100)
-#define MS2HZ (1000/HZ)
-#define TK2SEC(t) ((t)/HZ)
-
-#define CONFADDR 0x80010000
-
-#define KZERO 0x80000000
-#define KTZERO 0x80020000
-#define KSTACK (8*KiB)
-
-#define UZERO 0
-#define UTZERO BY2PG
-#define USTKTOP 0x20000000
-#define USTKSIZE (16*MiB)
-
-#define MAXMACH 1
-#define MACHSZ (16*KiB)
-#define L1SZ (4*4096)
-#define L2SZ (4*256)
-
-#define L1X(va) ((((va)>>20) & 0xfff) << 2)
-
-#define MACH(n) (KZERO+(n)*MACHSZ)
-#define MACHP(n) ((Mach*)MACH(n))
-#define MACHL1(n) (MACH(MAXMACH)+(n)*L1SZ)
-#define MACHVEC(n) (MACHL1(MAXMACH)+(n)*64*4)
-
-#define BY2PG (4*KiB)
-#define BY2SE 4
-#define BY2WD 4
-#define BY2V 8
-
-#define CACHELINEZ 64
-#define BLOCKALIGN 32
-
-#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
-#define PGROUND(s) ROUND(s, BY2PG)
-#define PGSHIFT 12
-
-#define PTEMAPMEM MiB
-#define PTEPERTAB (PTEMAPMEM/BY2PG)
-#define SEGMAPSIZE 1984
-#define SSEGMAPSIZE 16
-
-#define PPN(p) ((p)&~(BY2PG-1))
-
-#define PTEVALID (1<<0)
-#define PTERONLY (0<<1)
-#define PTEWRITE (1<<1)
-#define PTECACHED (0<<2)
-#define PTEUNCACHED (1<<2)
-#define PTENOEXEC (1<<3)
-
-#define PsrDfiq 0x40
-#define PsrDirq 0x80
-
-#define PsrMusr 0x10
-#define PsrMfiq 0x11
-#define PsrMirq 0x12
-#define PsrMsvc 0x13
-#define PsrMmon 0x16
-#define PsrMiabt 0x17
-#define PsrMdabt 0x18
-#define PsrMund 0x1b
-#define PsrMsys 0x1f
-
-#define PsrMask 0x1f
-
-#define WFI WORD $0xe320f003
-#define DSB WORD $0xf57ff04f
-#define DMB WORD $0xf57ff05f
-#define ISB WORD $0xf57ff06f
-
-#define CPSIE WORD $0xf1080080
-#define CPSID WORD $0xf10c0080
-
-#define CLZ(s, d) WORD $(0xe16f0f10 | (d) << 12 | (s))
-#define VMSR(cpu, fp) WORD $(0xeee00a10|(fp)<<16|(cpu)<<12)
-#define VMRS(fp, cpu) WORD $(0xeef00a10|(fp)<<16|(cpu)<<12)
-
-#define FPSID 0x0
-#define FPSCR 0x1
-#define MVFR1 0x6
-#define MVFR0 0x7
-#define FPEXC 0x8
-#define FPEXCEX (1<<31)
-#define FPEXCEN (1<<30)
-
-/* vlmdia r0!, {d0-d15}
- * vldmia r0!, {d16-d31} */
-#define VLDMIA WORD $0xecb00b20; WORD $0xecf00b20;
-
-/* vstmia r0!, {d0-d15}
- * vstmia r0!, {d16-d31} */
-#define VSTMIA WORD $0xeca00b20; WORD $0xece00b20;
--- a/mkfile
+++ /dev/null
@@ -1,82 +1,0 @@
-CONF=n900
-CONFLIST=n900
-
-p=9
-objtype=arm
-ktzero=0x80020000
-
-</$objtype/mkfile
-
-DEVS=`{rc ../port/mkdevlist $CONF}
-PORT=\
- alarm.$O\
- alloc.$O\
- allocb.$O\
- auth.$O\
- cache.$O\
- chan.$O\
- dev.$O\
- edf.$O\
- fault.$O\
- mul64fract.$O\
- rebootcmd.$O\
- page.$O\
- parse.$O\
- pgrp.$O\
- portclock.$O\
- print.$O\
- proc.$O\
- qio.$O\
- qlock.$O\
- segment.$O\
- sysfile.$O\
- sysproc.$O\
- taslock.$O\
- tod.$O\
- xalloc.$O\
- random.$O\
- rdb.$O\
- syscallfmt.$O\
- userinit.$O\
- ucalloc.$O\
-
-OBJ=\
- l.$O\
- lcache.$O\
- ltrap.$O\
- main.$O\
- mmu.$O\
- timer.$O\
- trap.$O\
- intr.$O\
- $CONF.root.$O\
- $CONF.rootc.$O\
- $DEVS\
- $PORT\
-
-LIB=\
- /$objtype/lib/libmemlayer.a\
- /$objtype/lib/libmemdraw.a\
- /$objtype/lib/libdraw.a\
- /$objtype/lib/libip.a\
- /$objtype/lib/libsec.a\
- /$objtype/lib/libmp.a\
- /$objtype/lib/libc.a\
- /$objtype/lib/libdtracy.a\
-
-$p$CONF.u:D: $p$CONF
- aux/aout2uimage -o $target -Z0 $prereq
-
-$p$CONF:D: $OBJ $CONF.$O $LIB
- $LD -o $target -T$ktzero -l $prereq
-
-<../boot/bootmkfile
-<../port/portmkfile
-<|../port/mkbootrules $CONF
-
-initcode.out: init9.$O initcode.$O /$objtype/lib/libc.a
- $LD -l -R1 -s -o $target $prereq
-
-install:V: $p$CONF.u
- cp $p$CONF /$objtype/
- cp $p$CONF.u /$objtype/
--- a/mmcn900.c
+++ /dev/null
@@ -1,308 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "../port/error.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/pci.h"
-#include "../port/sd.h"
-
-enum {
- Rsysc = 0x10,
- SCreset = 1 << 1,
- Rsyss = 0x14,
- SSreset = 1 << 0,
- Rcsre = 0x24,
- Rcon = 0x28,
- Rpwcnt = 0x2c,
- Rblk = 0x104,
- Rarg = 0x108,
- Rcmd = 0x10c,
- CRnone = 0 << 16,
- CR136 = 1 << 16,
- CR48 = 2 << 16,
- CR48busy = 3 << 16,
- CRmask = 3 << 16,
-
- CFcheckidx = 1 << 19,
- CFcheckcrc = 1 << 20,
- CFdata = 1 << 21,
- CFdataread = 1 << 4,
- CFdatamulti = 1 << 5,
-
- CTnone = 0 << 22,
- CTbus = 1 << 22,
- CTfunc = 2 << 22,
- CTio = 3 << 22,
- Rrsp10 = 0x110,
- Rrsp32 = 0x114,
- Rrsp54 = 0x118,
- Rrsp76 = 0x11c,
- Rdata = 0x120,
- Rpstate = 0x124,
- Rhctl = 0x128,
- Rsysctl = 0x12c,
- Rstatus = 0x130,
- STcmd = 1 << 0,
- STtransfer = 1 << 1,
- STbufwrite = 1 << 4,
- STbufread = 1 << 5,
-
- STmaskok = 0xffff << 0,
- STmaskerr = 0xffff << 16,
- Rie = 0x134,
- Rise = 0x138,
- Rac12 = 0x13c,
- Rcapa = 0x140,
- Rcapacur = 0x148,
- Rrev = 0x1fc,
-};
-
-#define csr32r(c, r) ((c)->io[(r)/4])
-#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
- char *name;
- u32int *io;
- ulong irq;
-
- struct {
- uint bcount;
- uint bsize;
- } cmd;
-
- Lock;
- Rendez;
-};
-
-static int
-n900mmcinit(SDio *io)
-{
- Ctlr *ctlr;
-
- ctlr = io->aux;
- csr32w(ctlr, Rsysc, SCreset);
- while(!(csr32r(ctlr, Rsyss) & SSreset))
- ;
-
- return 0;
-}
-
-static void
-n900mmcenable(SDio *)
-{
-}
-
-static int
-n900mmcinquiry(SDio *, char *inquiry, int len)
-{
- return snprint(inquiry, len, "MMC Host Controller");
-}
-
-static void
-n900mmcintr(Ureg *, void *aux)
-{
- Ctlr *ctlr;
-
- ctlr = aux;
- ilock(ctlr);
- if(csr32r(ctlr, Rstatus) & STcmd)
- wakeup(ctlr);
-
- iunlock(ctlr);
-}
-
-static int
-n900mmcdone(void *aux)
-{
- Ctlr *ctlr = aux;
-
- if(csr32r(ctlr, Rstatus) & STcmd)
- return 1;
-
- return 0;
-}
-
-static int
-n900mmccmd(SDio *io, SDiocmd *iocmd, u32int arg, u32int *resp)
-{
- Ctlr *ctlr;
- u32int cmd;
-
- /* prepare flags for this command */
- ctlr = io->aux;
- cmd = iocmd->index << 24;
- switch(iocmd->resp) {
- case 0: cmd |= CRnone; break;
- case 2: cmd |= CR136 | CFcheckcrc; break;
- case 3: cmd |= CR48; break;
- case 1:
- if(iocmd->busy) {
- cmd |= CR48busy | CFcheckidx | CFcheckcrc;
- break;
- }
-
- default:
- cmd |= CR48 | CFcheckidx | CFcheckcrc;
- break;
- }
-
- /* if there is data, set the data, read, and multi flags */
- if(iocmd->data) {
- cmd |= CFdata;
- if(iocmd->data & 1)
- cmd |= CFdataread;
- if(iocmd->data > 2)
- cmd |= CFdatamulti;
- }
-
- /* off it goes, wait for a response */
- csr32w(ctlr, Rstatus, ~0);
- csr32w(ctlr, Rarg, arg);
- csr32w(ctlr, Rcmd, cmd);
-
- /* wait for command to be done */
- tsleep(ctlr, n900mmcdone, ctlr, 100);
- if(csr32r(ctlr, Rstatus) & STmaskerr)
- error(Eio);
-
- /* unpack the response */
- switch(cmd & CRmask) {
- case CRnone:
- resp[0] = 0;
- break;
-
- case CR136:
- resp[0] = csr32r(ctlr, Rrsp10);
- resp[1] = csr32r(ctlr, Rrsp32);
- resp[2] = csr32r(ctlr, Rrsp54);
- resp[3] = csr32r(ctlr, Rrsp76);
- break;
-
- case CR48:
- case CR48busy:
- resp[0] = csr32r(ctlr, Rrsp10);
- break;
- }
-
- return 0;
-}
-
-static void
-n900mmciosetup(SDio *io, int, void *, int bsize, int bcount)
-{
- Ctlr *ctlr;
-
- ctlr = io->aux;
- if(bsize == 0 || (bsize & 3) != 0)
- error(Egreg);
-
- ctlr->cmd.bsize = bsize;
- ctlr->cmd.bcount = bcount;
- csr32w(ctlr, Rblk, (bsize & 0x3ff) | (bcount << 16));
-}
-
-static void
-n900mmcbufread(Ctlr *ctlr, uchar *buf, int len)
-{
- for(len >>= 2; len > 0; len--) {
- *((u32int*)buf) = csr32r(ctlr, Rdata);
- buf += 4;
- }
-}
-
-static void
-n900mmcbufwrite(Ctlr *ctlr, uchar *buf, int len)
-{
- for(len >>= 2; len > 0; len--) {
- csr32w(ctlr, Rdata, *((u32int*)buf));
- buf += 4;
- }
-}
-
-static void
-n900mmcio(SDio *io, int write, uchar *buf, int len)
-{
- Ctlr *ctlr;
- u32int stat, n;
-
- ctlr = io->aux;
- if(len != ctlr->cmd.bsize * ctlr->cmd.bcount)
- error(Egreg);
-
- while(len > 0) {
- stat = csr32r(ctlr, Rstatus);
- if(stat & STmaskerr) {
- csr32w(ctlr, Rstatus, STmaskerr);
- error(Eio);
- }
-
- if(stat & STbufwrite) {
- csr32w(ctlr, Rstatus, STbufwrite);
- if(!write)
- error(Eio);
-
- n = len;
- if(n > ctlr->cmd.bsize)
- n = ctlr->cmd.bsize;
-
- n900mmcbufwrite(ctlr, buf, n);
- len -= n;
- buf += n;
- }
-
- if(stat & STbufread) {
- csr32w(ctlr, Rstatus, STbufread);
- if(write)
- error(Eio);
-
- n = len;
- if(n > ctlr->cmd.bsize)
- n = ctlr->cmd.bsize;
-
- n900mmcbufread(ctlr, buf, n);
- len -= n;
- buf += n;
- }
-
- if(stat & STtransfer) {
- csr32w(ctlr, Rstatus, STtransfer);
- if(len != 0)
- error(Eio);
- }
- }
-}
-
-static void
-n900mmcbus(SDio *, int, int)
-{
- /* FIXME: change bus width */
-}
-
-void
-mmcn900link(void)
-{
- int i;
- static Ctlr ctlr[2] = {
- { .name = "mmc1", .io = (u32int*) PHYSMMC1, .irq = IRQMMC1, },
- { .name = "mmc2", .io = (u32int*) PHYSMMC2, .irq = IRQMMC2, },
- };
-
- static SDio io[nelem(ctlr)];
- for(i = 0; i < nelem(io); i++) {
- io[i].name = "mmc",
- io[i].init = n900mmcinit,
- io[i].enable = n900mmcenable,
- io[i].inquiry = n900mmcinquiry,
- io[i].cmd = n900mmccmd,
- io[i].iosetup = n900mmciosetup,
- io[i].io = n900mmcio,
- io[i].bus = n900mmcbus,
- io[i].aux = &ctlr[i];
-
- addmmcio(&io[i]);
- intrenable(ctlr[i].irq, n900mmcintr, &ctlr[i], BUSUNKNOWN, ctlr[i].name);
- }
-}
--- a/mmu.c
+++ /dev/null
@@ -1,311 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-static int debug = 0;
-
-#define L1(va) (((va)>>20) & 0xfff)
-#define L2(va) (((va)>>12) & 0xff)
-#define L1AP(ap) (((ap) << 10) & 0xff) /* dont care about ap[2] */
-#define L2AP(ap) (((ap) << 4) & 0xff)
-
-enum {
- /* l1 descriptor type (arm v7 manual fig. 12.4) */
- L1coarse = 1,
- L1section = 2,
- L1fine = 3,
-
- /* l2 descriptor type (arm v7 manual fig. 12.5) */
- L2large = 1,
- L2small = 2,
- L2tiny = 3,
-
- Fnoexec = 1<<0,
- Fbuffered = 1<<2,
- Fcached = 1<<3,
-
- APkrw = 1, /* kernel read write */
- APuro = 2, /* user read only */
- APurw = 3, /* user read write */
-};
-
-void
-mmudebugl2(PTE *l2, uintptr va)
-{
- uintptr startpa, pa;
- uintptr startva, endva;
- int i, t;
-
- t = 0;
- startpa = 0;
- startva = endva = 0;
- for(i = 0; i < 256; i++) {
- pa = l2[i] & ~((4*KiB)-1);
- if(l2[i] == 0) {
- if(endva) {
- iprint("mmudebug: l2 type %#ux %#lux %#lux -> %#lux\n", t, startva, endva, startpa);
- endva = 0;
- }
- } else {
- if(!endva) {
- startva = va;
- startpa = pa;
- t = l2[i] & (L2large | L2small | L2tiny);
- }
-
- endva = va + (4*KiB);
- }
-
- va += (4*KiB);
- }
-
- if(endva)
- iprint("mmudebug: l2 type %#ux %#lux %#lux -> %#lux\n", t, startva, endva, startpa);
-}
-
-void
-mmudebug(char *where)
-{
- PTE *l1;
- uintptr pa, startpa;
- uintptr va, startva, endva;
- int i, t;
-
- if(!debug)
- return;
-
- iprint("mmudebug: %s pid %d\n", where, m->mmupid);
-
- t = 0;
- l1 = m->mmul1;
- startpa = 0;
- startva = endva = 0;
- for(va = i = 0; i < 4096; i++) {
- pa = l1[i] & ~(MiB-1);
- if(l1[i] == 0) {
- if(endva) {
- iprint("mmudebug: l1 type %#ux %#lux %#lux -> %#lux\n", t, startva, endva, startpa);
- endva = 0;
- }
- } else {
- if(!endva) {
- startva = va;
- startpa = pa;
- t = l1[i] & (L1coarse|L1section|L1fine);
- }
-
- if(t == L1coarse) {
- mmudebugl2((PTE*) (l1[i] & ~(KiB-1)), startva);
- endva = 0;
- } else {
- endva = va + MB;
- }
- }
-
- va += MB;
- }
-
- if(endva)
- iprint("mmudebug: l1 type %#ux %#lux %#lux -> %#lux\n", t, startva, endva, startpa);
-}
-
-void
-mmuinit(void)
-{
- m->mmul1 = (PTE*)MACHL1(m->machno);
-}
-
-static void
-mmul1empty(void)
-{
- memset(m->mmul1, 0, (ROUND(USTKTOP, MiB)/MiB)*sizeof(PTE));
-}
-
-static void
-mmul2empty(Proc *proc, int clear)
-{
- PTE *l1;
- Page **l2, *page;
-
- l1 = m->mmul1;
- l2 = &proc->mmul2;
- for(page = *l2; page != nil; page = page->next) {
- if(clear)
- memset((void*)page->va, 0, BY2PG);
-
- l1[page->daddr] = 0;
- l2 = &page->next;
- }
-
- *l2 = proc->mmul2cache;
- proc->mmul2cache = proc->mmul2;
- proc->mmul2 = nil;
-}
-
-void
-mmuswitch(Proc *proc)
-{
- PTE *l1;
- Page *page;
- int l1x;
-
- if(m->mmupid == proc->pid && !proc->newtlb)
- return;
- m->mmupid = proc->pid;
-
- /* write back and invalidate caches */
- l1ucachewbinv();
- l2ucachewbinv();
-
- if(proc->newtlb) {
- mmul2empty(proc, 1);
- proc->newtlb = 0;
- }
-
- mmul1empty();
-
- /* switch to new map */
- l1 = m->mmul1;
- for(page = proc->mmul2; page != nil; page = page->next) {
- l1x = page->daddr;
- l1[l1x] = PPN(page->pa)|L1coarse;
- }
-
- /* FIXME: excessive invalidation */
- l1ucachewbinv();
- l2ucachewbinv();
- mmuinvalidate();
- mmudebug("mmuswitch");
-}
-
-void
-mmurelease(Proc *proc)
-{
- l1ucachewbinv();
- l2ucachewbinv();
-
- mmul2empty(proc, 0);
-
- freepages(proc->mmul2cache, nil, 0);
- proc->mmul2cache = nil;
-
- mmul1empty();
-
- /* FIXME: excessive invalidation */
- l1ucachewbinv();
- l2ucachewbinv();
- mmuinvalidate();
- mmudebug("mmurelease");
-}
-
-void*
-mmuuncache(void *v, usize s)
-{
- PTE *l1;
- uintptr va;
-
- assert(!((uintptr)v & (MiB-1)) && s == MiB);
-
- va = (uintptr)v;
- l1 = &m->mmul1[L1(va)];
- if((*l1 & (L1fine|L1section|L1coarse)) != L1section)
- return nil;
-
- *l1 &= ~(Fbuffered|Fcached);
-
- /* FIXME: excessive invalidation */
- l1ucachewbinv();
- l2ucachewbinv();
- mmuinvalidate();
- mmudebug("mmuuncache");
-
- return v;
-}
-
-void
-putmmu(uintptr va, uintptr pa, Page *page)
-{
- int l1x, s, x;
- PTE *l1, *l2;
- Page *pg;
-
- l1x = L1(va);
- l1 = &m->mmul1[l1x];
-
- /* put l1 for l2 table if needed */
- if(*l1 == 0) {
- if(up->mmul2cache == nil) {
- pg = newpage(1, 0, 0);
- pg->va = VA(kmap(pg));
- } else {
- pg = up->mmul2cache;
- up->mmul2cache = pg->next;
- memset((void*)pg->va, 0, BY2PG);
- }
-
- pg->daddr = l1x;
- pg->next = up->mmul2;
- up->mmul2 = pg;
-
- /* FIXME: excessive invalidation */
- s = splhi();
- *l1 = PPN(pg->pa)|L1coarse;
- l1ucachewbinv();
- l2ucachewbinv();
- splx(s);
- }
-
- /* put l2 entry */
- x = L2small;
- if(!(pa & PTEUNCACHED))
- x |= Fbuffered|Fcached;
- if(pa & PTENOEXEC)
- x |= Fnoexec;
- if(pa & PTEWRITE)
- x |= L2AP(APurw);
- else
- x |= L2AP(APuro);
-
- l2 = KADDR(PPN(*l1)); l2[L2(va)] = PPN(pa)|x;
-
- /* FIXME: excessive invalidation */
- s = splhi();
- l1ucachewbinv();
- l2ucachewbinv();
- if(needtxtflush(page)) {
- l1icacheinv();
- donetxtflush(page);
- }
-
- splx(s);
- mmuinvalidate();
- mmudebug("putmmu");
-}
-
-void
-checkmmu(uintptr, uintptr)
-{
- /* this page is intentionally left blank */
-}
-
-void
-flushmmu(void)
-{
- uint s;
-
- s = splhi();
- up->newtlb = 1; mmuswitch(up);
- splx(s);
-}
-
-uintptr
-cankaddr(uintptr pa)
-{
- if(pa >= PHYSMEM && pa < PHYSMEMEND)
- return PHYSMEMEND-pa;
-
- return 0;
-}
--- a/n900
+++ /dev/null
@@ -1,49 +1,0 @@
-dev
- root
- cons
- swap
- env
- pipe
- proc
- mnt
- srv
- shr
- dup
- tls
- cap
- sd
- fs
- dtracy
-
- draw screen
-
- kbd devi2c
- rtc devi2c
-
- uart
- usb
- i2c
-
-misc
- uartn900
-
- sdmmc mmcn900
- sdloop
- sdram
-
- dtracysys
- dtracytimer
- dtracydev
-
-link
- i2cn900 devi2c
- mmcn900
-
-port
- int cpuserver = 0;
-
-bootdir
- /$objtype/bin/paqfs
- /$objtype/bin/auth/factotum
- boot
- bootfs.paq
--- a/screen.c
+++ /dev/null
@@ -1,373 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#define Image IMAGE
-#include <draw.h>
-#include <memdraw.h>
-#include "screen.h"
-
-enum {
- /* display controller registers */
- RDrev = 0x400,
- RDsysconf = 0x410,
- DSCidle = 1<<0,
- DSCreset = 1<<1,
- DSCidlesmart = 2<<3,
- RDsysstat = 0x414,
- DSSreset = 1<<0,
- RDirqstat = 0x418,
- RDirqen = 0x41c,
- RDcontrol = 0x440,
- DClcdon = 1<<0,
- DClcdactive = 1<<3,
- DClcdclockrun = 1<<27,
- DClcdenable = 1<<28,
- DClcdenablehi = 1<<29,
- DClcdbits24 = 3<<8,
- RDconfig = 0x444,
- DCNgamma = 1<<3,
- RDdefcolor = 0x44c,
- RDtranscolor = 0x454,
- RDlinestat = 0x45c,
- RDlineintr = 0x460,
- RDtimeh = 0x464,
- RDtimev = 0x468,
- RDsize = 0x47c,
-
- /* display controller graphics layer registers */
- RDgfxba = 0x480,
- RDgfxpos = 0x488,
- RDgfxsize = 0x48c,
- RDgfxattr = 0x4a0,
- DGAenable = 1<<0,
- DGAfmt = 0x6<<1,
- DGAburst = 0x2<<6,
- RDgfxrowinc = 0x4ac,
- RDgfxpixelinc = 0x4b0,
-};
-
-enum {
- Tab = 4,
- Scroll = 8,
-};
-
-#define RDdefcolorn(n) (RDdefcolor + (n)*4)
-#define RDtranscolorn(n) (RDtranscolor + (n)*4)
-
-#define RDgfxban(n) (RDgfxba + (n)*4)
-
-#define TIME(s, f, b) ((s & 0xff) | (f & 0xfff) << 8 | (b & 0xfff) << 20)
-#define POS(x, y) ((x)<<16 | (y))
-#define SIZE(w, h) ((h-1)<<16 | (w-1))
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
- Lock;
-
- u32int *io;
-
- Memdata scrdata;
- Memimage *scrimg;
- Memsubfont *scrfont;
-
- Rectangle win;
- Point font;
- Point pos;
-};
-
-static Ctlr ctlr = {
- .io = (u32int*) PHYSDSS,
-};
-
-#define csr32r(c, r) ((c)->io[(r)/4])
-#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
-
-static void myscreenputs(char *s, int n);
-
-static int
-screendatainit(Ctlr *ctlr)
-{
- Rectangle r;
-
- if(memimageinit() < 0)
- return -1;
-
- r = Rect(0, 0, 800, 480);
- ctlr->scrdata.ref = 1;
- ctlr->scrdata.bdata = ucalloc(r.max.x * r.max.y * 2);
- if(!ctlr->scrdata.bdata)
- return -1;
-
- ctlr->scrimg = allocmemimaged(r, RGB16, &ctlr->scrdata);
- if(!ctlr->scrimg)
- return -1;
-
- ctlr->scrfont = getmemdefont();
- return 0;
-}
-
-static Memimage*
-screenmkcolor(Memimage *scr, ulong color)
-{
- Memimage *i;
-
- i = allocmemimage(Rect(0, 0, 1, 1), scr->chan);
- if(i) {
- i->flags |= Frepl;
- i->clipr = scr->r;
- memfillcolor(i, color);
- }
-
- return i;
-}
-
-static void
-screenwin(Ctlr *ctlr)
-{
- Rectangle r;
- Memimage *i;
- Point p;
- int h;
-
- ctlr->font.y = h = ctlr->scrfont->height;
- ctlr->font.x = ctlr->scrfont->info[' '].width;
-
- r = ctlr->scrimg->r;
- if(i = screenmkcolor(ctlr->scrimg, 0x0D686BFF)) {
- memimagedraw(ctlr->scrimg, r, i, ZP, memopaque, ZP, S);
- freememimage(i);
- }
-
- r = insetrect(r, 16); memimagedraw(ctlr->scrimg, r, memblack, ZP, memopaque, ZP, S);
- r = insetrect(r, 4); memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S);
- if(i = screenmkcolor(ctlr->scrimg, 0xaaaaaaff)) {
- memimagedraw(ctlr->scrimg, Rpt(r.min, Pt(r.max.x, r.min.y+h+12)), i, ZP, memopaque, ZP, S);
- freememimage(i);
-
- r = insetrect(r, 6);
- p = r.min;
- memimagestring(ctlr->scrimg, p, memblack, ZP, getmemdefont(), " Plan 9 Console ");
- }
-
- ctlr->win = Rpt(addpt(r.min, Pt(0, h + 6)), subpt(r.max, Pt(6, 6)));
- ctlr->pos = ctlr->win.min;
- screenputs = myscreenputs;
-}
-
-void
-screeninit(void)
-{
- Ctlr *c;
-
- c = &ctlr;
- if(screendatainit(c) < 0)
- return;
-
- screenwin(c);
- screenputs(kmesg.buf, kmesg.n);
-
- /* reset the display controller */
- csr32w(c, RDsysconf, DSCreset);
- while(!(csr32r(c, RDsysstat) & DSSreset))
- ;
-
- /* configure the display controller */
- csr32w(c, RDsysconf, DSCidle | DSCidlesmart);
- csr32w(c, RDcontrol, DClcdbits24);
- csr32w(c, RDconfig, DCNgamma);
-
- /* configure display size and timings */
- csr32w(c, RDtimeh, TIME(3, 15, 11));
- csr32w(c, RDtimev, TIME(2, 3, 3));
- csr32w(c, RDsize, SIZE(800, 480));
-
- /* enable the lcd interface */
- csr32w(c, RDcontrol, csr32r(c, RDcontrol) | DClcdactive | DClcdclockrun | DClcdenablehi);
- csr32w(c, RDcontrol, csr32r(c, RDcontrol) | DClcdenable);
-
- /* configure the graphics layer */
- csr32w(c, RDgfxban(0), (uintptr) c->scrdata.bdata);
- csr32w(c, RDgfxpos, POS(c->scrimg->r.min.x, c->scrimg->r.min.y));
- csr32w(c, RDgfxsize, SIZE(c->scrimg->r.max.x, c->scrimg->r.max.y));
- csr32w(c, RDgfxattr, DGAfmt | DGAburst);
- csr32w(c, RDgfxrowinc, 1);
- csr32w(c, RDgfxpixelinc, 1);
-
- /* enable gfx pipeline and turn lcd on */
- csr32w(c, RDgfxattr, csr32r(c, RDgfxattr) | DGAenable);
- csr32w(c, RDcontrol, csr32r(c, RDcontrol) | DClcdon);
-
- conf.monitor = 1;
-}
-
-static void
-screenscroll(Ctlr *ctlr)
-{
- int o, h;
- Point p;
- Rectangle r;
-
- h = ctlr->font.y;
- o = Scroll * h;
- r = Rpt(ctlr->win.min, Pt(ctlr->win.max.x, ctlr->win.max.y - o));
- p = Pt(ctlr->win.min.x, ctlr->win.min.y + o);
- memimagedraw(ctlr->scrimg, r, ctlr->scrimg, p, nil, p, S);
- flushmemscreen(r);
-
- r = Rpt(Pt(ctlr->win.min.x, ctlr->win.max.y - o), ctlr->win.max);
- memimagedraw(ctlr->scrimg, r, memwhite, ZP, nil, ZP, S);
- flushmemscreen(r);
-
- ctlr->pos.y -= o;
-
-}
-
-static void
-screenputc(Ctlr *ctlr, char *buf)
-{
- Point p;
- Rectangle r;
- uint chr;
- int w, h;
- static int *xp;
- static int xbuf[256];
-
- w = ctlr->font.x;
- h = ctlr->font.y;
- if(xp < xbuf || xp >= &xbuf[nelem(xbuf)])
- xp = xbuf;
-
- switch(buf[0]) {
- case '\n':
- if(ctlr->pos.y + h >= ctlr->win.max.y)
- screenscroll(ctlr);
-
- ctlr->pos.y += h;
- screenputc(ctlr, "\r");
- break;
-
- case '\r':
- xp = xbuf;
- ctlr->pos.x = ctlr->win.min.x;
- break;
-
- case '\t':
- if(ctlr->pos.x >= ctlr->win.max.x - 4 * w)
- screenputc(ctlr, "\n");
-
- chr = (ctlr->pos.x - ctlr->win.min.x) / w;
- chr = Tab - chr % Tab;
- *xp++ = ctlr->pos.x;
-
- r = Rect(ctlr->pos.x, ctlr->pos.y, ctlr->pos.x + chr * w, ctlr->pos.y + h);
- memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S);
- flushmemscreen(r);
- ctlr->pos.x += chr * w;
- break;
-
- case '\b':
- if(xp <= xbuf)
- break;
-
- xp--;
- r = Rect(*xp, ctlr->pos.y, ctlr->pos.x, ctlr->pos.y + h);
- memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S);
- ctlr->pos.x = *xp;
- break;
-
- case '\0':
- break;
-
- default:
- p = memsubfontwidth(getmemdefont(), buf); w = p.x;
- if(ctlr->pos.x >= ctlr->win.max.x - w)
- screenputc(ctlr, "\n");
-
- *xp++ = ctlr->pos.x;
- r = Rect(ctlr->pos.x, ctlr->pos.y, ctlr->pos.x + w, ctlr->pos.y + h);
- memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S);
- memimagestring(ctlr->scrimg, ctlr->pos, memblack, ZP, getmemdefont(), buf);
- ctlr->pos.x += w;
- break;
- }
-}
-
-static void
-myscreenputs(char *s, int n)
-{
- Ctlr *c;
- Rune r;
- int i;
- char buf[UTFmax];
-
- c = &ctlr;
- if(!c->scrimg)
- return;
-
- if(!islo()) {
- /* don't deadlock trying to print in an interrupt */
- if(!canlock(c))
- return;
- } else {
- lock(c);
- }
-
- while(n > 0) {
- i = chartorune(&r, s);
- if(i == 0) {
- s++; n--;
- continue;
- }
-
- memmove(buf, s, i);
- buf[i] = 0;
- s += i; n -= i;
- screenputc(c, buf);
- }
-
- unlock(c);
-}
-
-Memdata*
-attachscreen(Rectangle *r, ulong *chan, int *d, int *width, int *softscreen)
-{
- Ctlr *c;
-
- c = &ctlr;
- if(!c->scrimg)
- return nil;
-
- *r = c->scrimg->r;
- *d = c->scrimg->depth;
- *chan = c->scrimg->chan;
- *width = c->scrimg->width;
- *softscreen = 1;
-
- c->scrdata.ref++;
- return &c->scrdata;
-}
-
-void
-getcolor(ulong, ulong *, ulong *, ulong *)
-{
-}
-
-int
-setcolor(ulong, ulong, ulong, ulong)
-{
- return 0;
-}
-
-void
-flushmemscreen(Rectangle)
-{
-}
-
-void
-mouseresize(void)
-{
-}
--- a/screen.h
+++ /dev/null
@@ -1,9 +1,0 @@
-void screeninit(void);
-void flushmemscreen(Rectangle);
-Memdata *attachscreen(Rectangle *, ulong *, int *, int *, int *);
-
-#define ishwimage(i) 1
-
-void mousectl(Cmdbuf*);
-void mouseresize(void);
-void mouseredraw(void);
--- /dev/null
+++ b/sys/src/9/n900/dat.h
@@ -1,0 +1,147 @@
+typedef struct Conf Conf;
+typedef struct Confmem Confmem;
+typedef struct FPsave FPsave;
+typedef struct Label Label;
+typedef struct Lock Lock;
+typedef struct Mach Mach;
+typedef struct MMMU MMMU;
+typedef struct Page Page;
+typedef struct Proc Proc;
+typedef struct PFPU PFPU;
+typedef struct PMMU PMMU;
+typedef struct Ureg Ureg;
+
+typedef u32int PTE;
+typedef uvlong Tval;
+
+#pragma incomplete Ureg
+
+#define MAXSYSARG 5
+#define AOUT_MAGIC (E_MAGIC)
+
+struct Lock {
+ ulong key;
+ u32int sr;
+ uintptr pc;
+ Proc *p;
+ Mach *m;
+ int isilock;
+};
+
+struct Label {
+ uintptr sp;
+ uintptr pc;
+};
+
+struct Confmem {
+ uintptr base;
+ uintptr limit;
+ uintptr kbase;
+ uintptr klimit;
+ ulong npage;
+};
+
+struct Conf {
+ ulong nmach;
+ ulong nproc;
+ Confmem mem[1];
+ ulong npage;
+ ulong upages;
+ ulong copymode;
+ ulong ialloc;
+ ulong pipeqsize;
+ ulong nimage;
+ ulong nswap;
+ int nswppo;
+ int monitor;
+};
+
+struct FPsave {
+ ulong exc;
+ ulong scr;
+ uchar regs[256];
+};
+
+struct PFPU {
+ enum {
+ FPinit,
+ FPactive,
+ FPinactive,
+
+ FPillegal = 0x100,
+ } fpstate;
+ FPsave fpsave[1];
+};
+
+#define NCOLOR 1
+struct PMMU {
+ Page *mmul2;
+ Page *mmul2cache;
+};
+
+struct MMMU {
+ PTE *mmul1;
+ uint mmupid;
+};
+
+#include "../port/portdat.h"
+
+struct Mach {
+ int machno;
+ uintptr splpc;
+ Proc *proc;
+ MMMU;
+
+ PMach;
+
+ u32int save[5];
+ uintptr stack[1];
+};
+
+typedef struct ISAConf ISAConf;
+typedef struct Devport Devport;
+typedef struct DevConf DevConf;
+
+#define BUSUNKNOWN 0
+#define BUSMODEM 1
+
+#define NISAOPT 8
+struct ISAConf {
+ char *type;
+ uintptr port;
+ int irq;
+ ulong dma;
+ ulong mem;
+ ulong size;
+ ulong freq;
+
+ int nopt;
+ char *opt[NISAOPT];
+};
+
+struct Devport {
+ ulong port;
+ int size;
+};
+
+struct DevConf {
+ ulong intnum;
+ char *type;
+ int nports;
+ Devport *ports;
+};
+
+typedef void KMap;
+#define VA(p) ((uintptr)(p))
+#define kmap(p) (KMap*)((p)->pa|KZERO)
+#define kunmap(p)
+#define kmapinval()
+#define getpgcolor(p) 0
+
+struct {
+ char machs[MAXMACH];
+ int exiting;
+} active;
+
+extern register Mach *m;
+extern register Proc *up;
--- /dev/null
+++ b/sys/src/9/n900/devkbd.c
@@ -1,0 +1,243 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "../port/error.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/i2c.h"
+
+enum {
+ Rctrl = 0xd2,
+ Csoftreset = 1<<0,
+ Csoftmode = 1<<1,
+ Cenable = 1<<6,
+ Rcode = 0xdb,
+ Risr = 0xe3,
+ Rimr = 0xe4,
+ Ikp = 1<<0,
+ Ilk = 1<<1,
+ Ito = 1<<2,
+ Rsir = 0xe7,
+ Redr = 0xe8,
+ Ekpfalling = 1<<0,
+ Ekprising = 1<<1,
+ Elkfalling = 1<<2,
+ Elkrising = 1<<3,
+ Etofalling = 1<<4,
+ Etorising = 1<<5,
+ Emisfalling = 1<<6,
+ Emisrising = 1<<7,
+ Rsih = 0xe9,
+ Scor = 1<<2,
+};
+
+enum {
+ Qdir,
+ Qscan,
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ Ref;
+ Lock;
+
+ I2Cdev *dev;
+ Queue *q;
+
+ uchar cur[8];
+ uchar prev[8];
+};
+
+static Ctlr ctlr;
+static Dirtab kbdtab[] = {
+ ".", {Qdir, 0, QTDIR}, 0, 0555,
+ "scancode", {Qscan, 0, QTFILE}, 0, 0440,
+};
+
+static u8int
+csr8r(Ctlr *ctlr, u8int r)
+{
+ uchar buf;
+
+ i2crecv(ctlr->dev, &buf, sizeof(buf), r);
+ return buf;
+}
+
+static u8int
+csr8w(Ctlr *ctlr, u8int r, u8int w)
+{
+ i2csend(ctlr->dev, &w, sizeof(w), r);
+ return w;
+}
+
+static void
+kbdinterrupt(Ureg *, void*)
+{
+ int i, j, c, k;
+
+ ilock(&ctlr);
+ if(!(csr8r(&ctlr, Risr) & Ikp)) {
+ iunlock(&ctlr);
+ return;
+ }
+
+ /* scan key columns */
+ for(i = 0; i < 8; i++) {
+ ctlr.prev[i] = ctlr.cur[i];
+ ctlr.cur[i] = csr8r(&ctlr, Rcode + i);
+
+ /* changed? */
+ c = ctlr.cur[i] ^ ctlr.prev[i];
+ if(!c)
+ continue;
+
+ /* scan key rows */
+ for(j = 0; j < 8; j++) {
+ if(!(c & (1 << j)))
+ continue;
+
+ /* pressed or released? */
+ k = i << 3 | j;
+ if(ctlr.prev[i] & (1 << j))
+ k |= 0x80;
+
+ qproduce(ctlr.q, &k, 1);
+ }
+ }
+
+ iunlock(&ctlr);
+}
+
+static void
+kbdreset(void)
+{
+ ilock(&ctlr);
+ ctlr.q = qopen(1024, Qcoalesce, 0, 0);
+ if(!ctlr.q) {
+ iunlock(&ctlr);
+ return;
+ }
+
+ ctlr.dev = i2cdev(i2cbus("i2c1"), 0x4a);
+ if(!ctlr.dev) {
+ iunlock(&ctlr);
+ return;
+ }
+
+ ctlr.dev->subaddr = 1;
+ ctlr.dev->size = 0x100;
+
+ csr8w(&ctlr, Rctrl, Csoftreset | Csoftmode | Cenable);
+ csr8w(&ctlr, Rsih, Scor);
+ csr8w(&ctlr, Rimr, ~Ikp);
+
+ intrenable(IRQTWL, kbdinterrupt, nil, BUSUNKNOWN, "kbd");
+ iunlock(&ctlr);
+}
+
+static void
+kbdshutdown(void)
+{
+}
+
+static Chan *
+kbdattach(char *spec)
+{
+ if(!ctlr.dev)
+ error(Enonexist);
+
+ return devattach(L'b', spec);
+}
+
+static Walkqid *
+kbdwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, kbdtab, nelem(kbdtab), devgen);
+}
+
+static int
+kbdstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, kbdtab, nelem(kbdtab), devgen);
+}
+
+static Chan *
+kbdopen(Chan *c, int mode)
+{
+ if(!iseve)
+ error(Eperm);
+
+ if(c->qid.path == Qscan) {
+ if(waserror()) {
+ decref(&ctlr);
+ nexterror();
+ }
+
+ if(incref(&ctlr) != 1)
+ error(Einuse);
+
+ c = devopen(c, mode, kbdtab, nelem(kbdtab), devgen);
+ poperror();
+ return c;
+ }
+
+ return devopen(c, mode, kbdtab, nelem(kbdtab), devgen);
+}
+
+static void
+kbdclose(Chan *c)
+{
+ if((c->flag & COPEN) && c->qid.path == Qscan)
+ decref(&ctlr);
+}
+
+static Block*
+kbdbread(Chan *c, long n, ulong off)
+{
+ if(c->qid.path == Qscan)
+ return qbread(ctlr.q, n);
+
+ return devbread(c, n, off);
+}
+
+static long
+kbdread(Chan *c, void *a, long n, vlong)
+{
+ if(c->qid.path == Qscan)
+ return qread(ctlr.q, a, n);
+
+ if(c->qid.path == Qdir)
+ return devdirread(c, a, n, kbdtab, nelem(kbdtab), devgen);
+
+ error(Egreg);
+ return 0;
+}
+
+static long
+kbdwrite(Chan *, void *, long, vlong)
+{
+ error(Egreg);
+ return 0;
+}
+
+Dev kbddevtab = {
+ L'b',
+ "kbd",
+
+ kbdreset,
+ devinit,
+ kbdshutdown,
+ kbdattach,
+ kbdwalk,
+ kbdstat,
+ kbdopen,
+ devcreate,
+ kbdclose,
+ kbdread,
+ kbdbread,
+ kbdwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
--- /dev/null
+++ b/sys/src/9/n900/devrtc.c
@@ -1,0 +1,202 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "../port/error.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/i2c.h"
+
+enum {
+ Rsec = 0x1c,
+ Rmin = 0x1d,
+ Rhour = 0x1e,
+ Rday = 0x1f,
+ Rmonth = 0x20,
+ Ryear = 0x21,
+ Rweeks = 0x22,
+ Rctrl = 0x29,
+ Cget = 1<<6,
+
+ Qdir = 0,
+ Qrtc,
+
+ SecMin = 60,
+ SecHour = 60*SecMin,
+ SecDay = 24*SecHour,
+};
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ I2Cdev *dev;
+
+ int sec;
+ int min;
+ int hour;
+ int day;
+ int month;
+ int year;
+};
+
+static Ctlr ctlr;
+static int dmsize[] = { 365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static int ldmsize[] = { 366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+static Dirtab rtctab[] = {
+ ".", {Qdir, 0, QTDIR}, 0, 0555,
+ "rtc", {Qrtc, 0, QTFILE}, 0, 0440,
+};
+
+#define bcddec(x) (((x) & 0xf) + ((x) >> 4) * 10)
+#define bcdenc(x) (((x / 10) << 4) + (x) % 10)
+#define leap(x) (((x) % 4) == 0 && ((x % 100) != 0 || (x % 400) == 0))
+
+static u8int
+csr8r(Ctlr *ctlr, u8int r)
+{
+ uchar buf;
+
+ i2crecv(ctlr->dev, &buf, sizeof(buf), r);
+ return buf;
+}
+
+static u8int
+csr8w(Ctlr *ctlr, u8int r, u8int w)
+{
+ i2csend(ctlr->dev, &w, sizeof(w), r);
+ return w;
+}
+
+static vlong
+rtcsnarf(void)
+{
+ vlong s;
+ int i;
+
+ /* latch and snarf */
+ csr8w(&ctlr, Rctrl, csr8r(&ctlr, Rctrl) | Cget);
+ ctlr.sec = bcddec(csr8r(&ctlr, Rsec)) % 60;
+ ctlr.min = bcddec(csr8r(&ctlr, Rmin)) % 60;
+ ctlr.hour = bcddec(csr8r(&ctlr, Rhour)) % 24;
+ ctlr.day = bcddec(csr8r(&ctlr, Rday));
+ ctlr.month = bcddec(csr8r(&ctlr, Rmonth));
+ ctlr.year = bcddec(csr8r(&ctlr, Ryear)) % 100;
+ ctlr.year += 2000;
+
+ /* seconds per year */
+ s = 0;
+ for(i = 1970; i < ctlr.year; i++) {
+ if(leap(i))
+ s += ldmsize[0] * SecDay;
+ else
+ s += dmsize[0] * SecDay;
+ }
+
+ /* seconds per month */
+ for(i = 1; i < ctlr.month; i++) {
+ if(leap(ctlr.year))
+ s += ldmsize[i] * SecDay;
+ else
+ s += dmsize[i] * SecDay;
+ }
+
+ /* days, hours, minutes, seconds */
+ s += (ctlr.day - 1) * SecDay;
+ s += ctlr.hour * SecHour;
+ s += ctlr.min * SecMin;
+ s += ctlr.sec;
+ return s;
+}
+
+static void
+rtcreset(void)
+{
+ ctlr.dev = i2cdev(i2cbus("i2c1"), 0x4b);
+ if(!ctlr.dev)
+ return;
+
+ ctlr.dev->subaddr = 1;
+ ctlr.dev->size = 0x100;
+}
+
+static void
+rtcshutdown(void)
+{
+}
+
+static Chan *
+rtcattach(char *spec)
+{
+ if(!ctlr.dev)
+ error(Enonexist);
+
+ return devattach('r', spec);
+}
+
+static Walkqid *
+rtcwalk(Chan *c, Chan *nc, char **name, int nname)
+{
+ return devwalk(c, nc, name, nname, rtctab, nelem(rtctab), devgen);
+}
+
+static int
+rtcstat(Chan *c, uchar *dp, int n)
+{
+ return devstat(c, dp, n, rtctab, nelem(rtctab), devgen);
+}
+
+static Chan *
+rtcopen(Chan *c, int mode)
+{
+ mode = openmode(mode);
+ if(c->qid.path == Qrtc) {
+ if(!iseve() && mode != OREAD)
+ error(Eperm);
+ }
+
+ return devopen(c, mode, rtctab, nelem(rtctab), devgen);
+}
+
+static void
+rtcclose(Chan *)
+{
+}
+
+static long
+rtcread(Chan *c, void *a, long n, vlong off)
+{
+ if(c->qid.path == Qdir)
+ return devdirread(c, a, n, rtctab, nelem(rtctab), devgen);
+ if(c->qid.path == Qrtc)
+ return readnum(off, a, n, rtcsnarf(), 12);
+
+ error(Egreg);
+ return 0;
+}
+
+static long
+rtcwrite(Chan *, void *, long, vlong)
+{
+ error(Egreg);
+ return 0;
+}
+
+Dev rtcdevtab = {
+ 'r',
+ "rtc",
+
+ rtcreset,
+ devinit,
+ rtcshutdown,
+ rtcattach,
+ rtcwalk,
+ rtcstat,
+ rtcopen,
+ devcreate,
+ rtcclose,
+ rtcread,
+ devbread,
+ rtcwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
--- /dev/null
+++ b/sys/src/9/n900/fns.h
@@ -1,0 +1,77 @@
+#include "../port/portfns.h"
+
+#define KADDR(a) ((void*)(a))
+#define PADDR(a) ((uintptr)(a))
+
+#define userureg(ur) (((ur)->psr & PsrMask) == PsrMusr)
+
+void* ucallocalign(usize, int, usize);
+void* ucalloc(usize);
+
+int cmpswap(long *, long, long);
+int cas(long *, long, long);
+int tas(void *);
+
+void evenaddr(uintptr va);
+void procrestore(Proc *);
+void procsave(Proc *);
+void procsetup(Proc *);
+void procfork(Proc *);
+
+void coherence(void);
+void idlehands(void);
+void touser(void*);
+void setR13(uint, u32int*);
+ulong getdfsr(void);
+ulong getifsr(void);
+uintptr getdfar(void);
+uintptr getifar(void);
+void setvectors(uintptr);
+void breakpt(void);
+
+char* getconf(char*);
+int isaconfig(char *, int, ISAConf *);
+
+void mmuinvalidate(void);
+void* mmuuncache(void*, usize);
+uintptr cankaddr(uintptr);
+
+ulong µs(void);
+void delay(int);
+void microdelay(int);
+void cycles(uvlong*);
+
+void dumpureg(Ureg*);
+void dumpstackureg(Ureg*);
+
+void intrenable(int, void (*f)(Ureg *, void*), void *, int, char*);
+void intrdisable(int, void (*f)(Ureg *, void*), void *, int, char*);
+void intr(Ureg *);
+
+void uartinit(void);
+void mmuinit(void);
+void trapinit(void);
+void intrinit(void);
+void timerinit(void);
+void screeninit(void);
+
+void links(void);
+
+void l1icacheinv(void);
+void l1dcachewb(void);
+void l1dcacheinv(void);
+void l1dcachewbinv(void);
+void l1ucachewbinv(void);
+
+void l2idcacheinv(void);
+void l2idcachewb(void);
+void l2idcachewbinv(void);
+void l2ucachewbinv(void);
+
+
+void fpinit(void);
+void fpoff(void);
+void fpclear(void);
+
+void fpsave(FPsave *);
+void fprestore(FPsave *);
--- /dev/null
+++ b/sys/src/9/n900/i2cn900.c
@@ -1,0 +1,224 @@
+#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/i2c.h"
+
+enum {
+ Rrev = 0x00,
+ Rie = 0x04,
+ Ris = 0x08,
+ Ial = 1 << 0, /* arbitration lost */
+ Inack = 1 << 1, /* no acknowledgement */
+ Iardy = 1 << 2, /* address ready */
+ Irrdy = 1 << 3, /* receive ready */
+ Ixrdy = 1 << 4, /* transmit ready */
+ Ibb = 1 << 12, /* bus busy */
+ Iall = 0xffff,
+
+ Rwe = 0x0c,
+ Rsyss = 0x10,
+ SSreset = 1 << 0, /* reset status */
+
+ Rbuf = 0x14,
+ Rcnt = 0x18,
+ Rdata = 0x1c,
+ Rsysc = 0x20,
+ SCreset = 1 << 1, /* software reset */
+
+ Rcon = 0x24,
+ Cstt = 1 << 0, /* start condition */
+ Cstp = 1 << 1, /* stop condiction */
+ Cxoa3 = 1 << 4, /* expand address */
+ Cxoa2 = 1 << 5,
+ Cxoa1 = 1 << 6,
+ Cxoa0 = 1 << 7,
+ Cxa = 1 << 8,
+ Ctrx = 1 << 9, /* transmit mode */
+ Cmst = 1 << 10, /* master mode */
+ Cstb = 1 << 11, /* start byte */
+ Cen = 1 << 15, /* enable */
+
+ Raddr = 0x2c,
+};
+
+#define csr32r(c, r) ((c)->io[(r)/4])
+#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ u32int *io;
+ ulong irq;
+
+ Rendez;
+};
+
+static Ctlr ctlr[] = {
+ { .io = (u32int*) PHYSI2C1, .irq = IRQI2C1 },
+ { .io = (u32int*) PHYSI2C2, .irq = IRQI2C2 },
+ { .io = (u32int*) PHYSI2C3, .irq = IRQI2C3 },
+};
+
+static void
+n900i2cwaitbus(Ctlr *ctlr)
+{
+ /* FIXME: timeout here? */
+ while(csr32r(ctlr, Ris) & Ibb)
+ ;
+}
+
+static int
+n900i2cwaitirq(void *arg)
+{
+ Ctlr *ctlr = arg; return csr32r(ctlr, Ris);
+}
+
+static uint
+n900i2cwait(Ctlr *ctlr)
+{
+ uint s;
+
+ /* FIXME: timeout here? */
+ while(!(s = csr32r(ctlr, Ris))) {
+ if(!up || !islo())
+ continue;
+
+ tsleep(ctlr, n900i2cwaitirq, ctlr, 5);
+ }
+
+ return s;
+}
+
+static void
+n900i2cflush(Ctlr *ctlr)
+{
+ while(csr32r(ctlr, Ris) & Irrdy) {
+ USED(csr32r(ctlr, Rdata));
+ csr32w(ctlr, Ris, Irrdy);
+ }
+}
+
+static void
+n900i2cintr(Ureg *, void *arg)
+{
+ Ctlr *ctlr;
+
+ ctlr = arg;
+ wakeup(ctlr);
+}
+
+static int
+n900i2cinit(I2Cbus *bus)
+{
+ Ctlr *ctlr;
+
+ /* reset the ctlr */
+ ctlr = bus->ctlr;
+ csr32w(ctlr, Rsysc, SCreset);
+ csr32w(ctlr, Rcon, Cen);
+
+ /* FIXME: timeout here? */
+ while(!(csr32r(ctlr, Rsyss) & SSreset))
+ ;
+
+ intrenable(ctlr->irq, n900i2cintr, ctlr, 0, bus->name);
+ return 0;
+}
+
+static int
+n900i2cio(I2Cbus *bus, uchar *pkt, int olen, int ilen)
+{
+ Ctlr *ctlr;
+ uint con, addr, stat;
+ uint o;
+
+ ctlr = bus->ctlr;
+ if(olen <= 0 || pkt == nil)
+ return -1;
+
+ o = 0;
+ con = Cen | Cmst | Ctrx | Cstp | Cstt;
+ if((pkt[o] & 0xf8) == 0xf0) {
+ /* 10-bit address: qemu has bugs, nothing on the n900 needs them.
+ * con |= Cxa;
+ * addr = ((pkt[o++] & 6) << 7) | pkt[o++];
+ */
+ return -1;
+ } else {
+ /* 7-bit address */
+ addr = pkt[o++] >> 1;
+ }
+
+ /* wait for bus */
+ n900i2cwaitbus(ctlr);
+
+ /* first attempt to probe, will get nack here if no dev */
+ csr32w(ctlr, Rcnt, olen);
+ csr32w(ctlr, Raddr, addr);
+ csr32w(ctlr, Rcon, con);
+ stat = n900i2cwait(ctlr);
+ if(stat & Inack || stat & Ial) {
+ o = -1; goto err;
+ }
+
+ /* transmit */
+ while(o < olen) {
+ stat = n900i2cwait(ctlr);
+ if(stat == 0 || stat & Inack || stat & Ial) {
+ o = -1; goto err;
+ }
+
+ if(stat & Iardy) {
+ csr32w(ctlr, Ris, Iardy);
+ break;
+ }
+
+ if(stat & Ixrdy) {
+ csr32w(ctlr, Rdata, pkt[o++]);
+ csr32w(ctlr, Ris, Ixrdy);
+ }
+ }
+
+ /* receive */
+ csr32w(ctlr, Rcnt, ilen);
+ csr32w(ctlr, Raddr, addr);
+ csr32w(ctlr, Rcon, Cen | Cmst | Cstp | Cstt);
+ while(o < olen + ilen) {
+ stat = n900i2cwait(ctlr);
+ if(stat == 0 || stat & Inack || stat & Ial) {
+ o = -1; goto err;
+ }
+
+ if(stat & Iardy) {
+ csr32w(ctlr, Ris, Iardy);
+ break;
+ }
+
+ if(stat & Irrdy) {
+ pkt[o++] = csr32r(ctlr, Rdata);
+ csr32w(ctlr, Ris, Irrdy);
+ }
+ }
+
+err:
+ n900i2cflush(ctlr);
+ csr32w(ctlr, Ris, Iall);
+ return o;
+}
+
+void
+i2cn900link(void)
+{
+ int i;
+ static I2Cbus bus[] = {
+ { "i2c1", 4000000, &ctlr[0], n900i2cinit, n900i2cio },
+ { "i2c2", 4000000, &ctlr[1], n900i2cinit, n900i2cio },
+ { "i2c3", 4000000, &ctlr[2], n900i2cinit, n900i2cio },
+ };
+
+ for(i = 0; i < nelem(bus); i++)
+ addi2cbus(&bus[i]);
+}
--- /dev/null
+++ b/sys/src/9/n900/init9.s
@@ -1,0 +1,12 @@
+TEXT main(SB), 1, $8
+ MOVW $setR12(SB), R12
+ MOVW $boot(SB), R0
+
+ ADD $12, R13, R1
+
+ MOVW R0, 4(R13)
+ MOVW R1, 8(R13)
+
+ BL startboot(SB)
+_limbo:
+ B _limbo
--- /dev/null
+++ b/sys/src/9/n900/intr.c
@@ -1,0 +1,199 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum {
+ Rrev = 0x00,
+ Rsysconf = 0x10,
+ Rsysstat = 0x14,
+ Rirq = 0x40,
+ Rfiq = 0x44,
+ Rcontrol = 0x48,
+ Cnewirqgen = 1<<0,
+ Rprot = 0x4c,
+ Ridle = 0x50,
+ Rirqprio = 0x60,
+ Rfiqprio = 0x64,
+ Rthreshold = 0x68,
+
+ Ritr = 0x80,
+ Rmir = 0x84,
+ Rmirclear = 0x88,
+ Rmirset = 0x8c,
+ Risrset = 0x90,
+ Risrclear = 0x94,
+ Rirqpend = 0x98,
+ Rfiqpend = 0x9c,
+
+ Rilr = 0x100,
+};
+
+enum {
+ Nmir = 3,
+ Nitr = 3,
+ Nintrs = 96,
+};
+
+#define Ritrn(n) (Ritrn + 32*(n))
+#define Rmirn(n) (Rmirn + 32*(n))
+#define Rmirclearn(n) (Rmirclear + 32*(n))
+#define Rmirsetn(n) (Rmirset + 32*(n))
+#define Rirqpendn(n) (Rirqpend + 32*(n))
+#define Rfiqpendn(n) (Rfiqpend + 32*(n))
+
+#define Rilrn(n) (Rilr + 4*(n))
+
+#define csr32r(c, r) ((c)->io[(r)/4])
+#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
+
+typedef struct Intr Intr;
+typedef struct Ctlr Ctlr;
+
+struct Intr {
+ void (*f)(Ureg *, void *);
+ void *arg;
+ char *name;
+
+ Intr *next;
+};
+
+struct Ctlr {
+ Lock;
+
+ u32int *io;
+
+ Intr *intrs[Nintrs];
+};
+
+static Ctlr ctlrmpu = { .io = (u32int*) PHYSINTRMPU };
+
+void
+intrinit(void)
+{
+ Ctlr *ctlr = &ctlrmpu;
+ int i;
+
+ /* mask all interrupts */
+ for (i = 0; i < Nmir; i++)
+ csr32w(ctlr, Rmirsetn(i), ~0);
+
+ /* protection off, threshold off, set all intrs priority 0, mapped to irq */
+ csr32w(ctlr, Rcontrol, 0);
+ csr32w(ctlr, Rthreshold, 0xff);
+ for (i = 0; i < Nintrs; i++)
+ csr32w(ctlr, Rilrn(i), 0);
+
+ coherence();
+}
+
+void
+intrenable(int n, void (*f)(Ureg *, void *), void *arg, int, char *name)
+{
+ Ctlr *ctlr = &ctlrmpu;
+ Intr *intr;
+
+ if (n >= nelem(ctlr->intrs) || n < 0)
+ panic("intrenable %d", n);
+
+ intr = malloc(sizeof(*intr));
+ if(!intr)
+ panic("intrenable: no memory for interrupt");
+
+ intr->f = f;
+ intr->arg = arg;
+ intr->name = name;
+
+ lock(ctlr);
+
+ /* chain this interrupt */
+ intr->next = ctlr->intrs[n];
+ ctlr->intrs[n] = intr;
+
+ /* new handler assigned, unmask this interrupt */
+ csr32w(ctlr, Rmirclearn(n >> 5), 1 << (n & 31));
+
+ unlock(ctlr);
+ coherence();
+}
+
+void
+intrdisable(int n, void (*f)(Ureg *, void *), void *arg, int, char *name)
+{
+ Ctlr *ctlr = &ctlrmpu;
+ Intr *intr, **ip;
+
+ if (n >= nelem(ctlr->intrs) || n < 0)
+ panic("intrdisable %d", n);
+
+ lock(ctlr);
+ for(ip = &ctlr->intrs[n]; intr = *ip; ip = &intr->next) {
+ if(intr->f == f && intr->arg == arg && strcmp(intr->name, name) == 0) {
+ *ip = intr->next;
+ free(intr);
+ break;
+ }
+ }
+
+ /* no more handlers assigned, mask this interrupt */
+ if(ctlr->intrs[n] == nil)
+ csr32w(ctlr, Rmirsetn(n >> 5), 1 << (n & 31));
+
+ unlock(ctlr);
+ coherence();
+}
+
+void
+intr(Ureg *ureg)
+{
+ Ctlr *ctlr = &ctlrmpu;
+ Intr *intr;
+ int n, h, s;
+
+ h = 0;
+ n = csr32r(ctlr, Rirq) & 0x7f;
+ s = csr32r(ctlr, Rirq) & ~0x7f;
+ if(s) {
+ /* interrupt controller reports spurious interrupt flag. */
+ iprint("cpu%d: spurious interrupt\n", m->machno);
+ csr32w(ctlr, Rcontrol, Cnewirqgen);
+ return;
+ }
+
+ if(n >= nelem(ctlr->intrs)) {
+ iprint("cpu%d: invalid interrupt %d\n", m->machno, n);
+ csr32w(ctlr, Rcontrol, Cnewirqgen);
+ return;
+ }
+
+ /* call all handlers for this interrupt number */
+ for (intr = ctlr->intrs[n]; intr; intr = intr->next) {
+ if(intr->f) {
+ if(islo())
+ panic("trap: islo() in interrupt handler\n");
+
+ intr->f(ureg, intr->arg);
+ if(islo())
+ panic("trap: islo() after interrupt handler\n");
+ }
+
+ h++;
+ }
+
+ csr32w(ctlr, Rcontrol, Cnewirqgen);
+ coherence();
+
+ if(!h) iprint("cpu%d: spurious interrupt %d\n", m->machno, n);
+ if(up) {
+ if(n >= IRQTIMER1 && n <= IRQTIMER11) {
+ if(up->delaysched) {
+ splhi();
+ sched();
+ }
+ } else {
+ preempted();
+ }
+ }
+}
--- /dev/null
+++ b/sys/src/9/n900/io.h
@@ -1,0 +1,63 @@
+#define PHYSL4 0x40000000
+#define PHYSL4END 0x50000000
+
+#define PHYSTIMER1 0x48318000
+#define PHYSTIMER2 0x49032000
+#define PHYSTIMER3 0x49034000
+#define PHYSTIMER4 0x49036000
+#define PHYSTIMER5 0x49038000
+#define PHYSTIMER6 0x4903a000
+#define PHYSTIMER7 0x4903c000
+#define PHYSTIMER8 0x4903e000
+#define PHYSTIMER9 0x49040000
+#define PHYSTIMER10 0x48086000
+#define PHYSTIMER11 0x48088000
+
+#define PHYSUART1 0x4806a000
+#define PHYSUART2 0x4806c000
+#define PHYSUART3 0x49020000
+
+#define PHYSI2C1 0x48070000
+#define PHYSI2C2 0x48072000
+#define PHYSI2C3 0x48060000
+
+#define PHYSMMC1 0x4809c000
+#define PHYSMMC2 0x480b4000
+#define PHYSMMC3 0x480ad000
+
+#define PHYSDSS 0x48050000
+
+#define PHYSINTRMODEM 0x480c7000
+#define PHYSINTRMPU 0x48200000
+
+#define PHYSL3 0x68000000
+#define PHYSL3END 0x70000000
+
+#define PHYSMEM 0x80000000
+#define PHYSMEMEND 0x90000000
+
+#define IRQTIMER1 37
+#define IRQTIMER2 38
+#define IRQTIMER3 39
+#define IRQTIMER4 40
+#define IRQTIMER5 41
+#define IRQTIMER6 42
+#define IRQTIMER7 43
+#define IRQTIMER8 44
+#define IRQTIMER9 45
+#define IRQTIMER10 46
+#define IRQTIMER11 47
+
+#define IRQUART1 72
+#define IRQUART2 73
+#define IRQUART3 74
+
+#define IRQI2C1 56
+#define IRQI2C2 57
+#define IRQI2C3 61
+
+#define IRQMMC1 83
+#define IRQMMC2 86
+#define IRQMMC3 94
+
+#define IRQTWL 7
--- /dev/null
+++ b/sys/src/9/n900/l.s
@@ -1,0 +1,354 @@
+#include "mem.h"
+#include "io.h"
+
+TEXT _start(SB), $-4
+ /* load static base */
+ MOVW $setR12(SB), R12
+
+ /* fiqs and irqs off, svc mode (cortex a8 trm figure 2.12) */
+ MOVW $(PsrDfiq|PsrDirq|PsrMsvc), R0
+ MOVW R0, CPSR
+
+ /* mmu and l1 caches off (cortex a8 trm table 3.46) */
+ MRC 15, 0, R0, C1, C0, 0
+ BIC $(1<<12), R0 /* level 1 instruction cache */
+ BIC $(1<<1), R0 /* level 1 data cache */
+ BIC $(1<<0), R0 /* mmu */
+ MCR 15, 0, R0, C1, C0, 0
+ ISB
+
+ /* l2 caches off (cortex a8 trm table 3.49) */
+ MCR 15, 0, R0, C1, C0, 1
+ BIC $(1<<1), R0 /* level 2 cache */
+ MCR 15, 0, R0, C1, C0, 1
+ ISB
+
+ /* fill mach with 0 */
+ MOVW $0, R0
+ MOVW $MACH(0), R1
+ MOVW $MACH(MAXMACH), R2
+zeromach:
+ MOVW R0, (R1)
+ ADD $4, R1
+ CMP R1, R2
+ BNE zeromach
+
+ /* fill page tables with 0 */
+ MOVW R0, R0
+ MOVW $MACHL1(0), R1 /* bottom of l1 tables */
+ MOVW $MACHL1(MAXMACH), R2 /* top of l1 tables */
+zeropte:
+ MOVW R0, (R1)
+ ADD $4, R1
+ CMP R1, R2
+ BNE zeropte
+
+ /* fill bss with 0 */
+ MOVW $0, R0
+ MOVW $edata(SB), R1
+ MOVW $end(SB), R2
+zerobss:
+ MOVW R0, (R1)
+ ADD $4, R1
+ CMP R1, R2
+ BNE zerobss
+
+ /* fill page tables for memory:
+ * 1mb section, cached, buffered, kernel read-write */
+ MOVW $((1<<1)|(1<<2)|(1<<3)|(1<<10)), R1
+ MOVW $PHYSMEM, R2
+ MOVW $(MACHL1(0)+L1X(PHYSMEM)), R3
+ MOVW $(MACHL1(0)+L1X(PHYSMEMEND)), R4
+ptemem:
+ ORR R2, R1, R0
+ MOVW R0, (R3)
+ ADD $(MiB), R2
+ ADD $4, R3
+ CMP R3, R4
+ BNE ptemem
+
+ /* fill page tables for l4 interconnect:
+ * 1mb section, kernel read-write */
+ MOVW $((1<<1)|(1<<4)|(1<<10)), R1
+ MOVW $PHYSL4, R2
+ MOVW $(MACHL1(0)+L1X(PHYSL4)), R3
+ MOVW $(MACHL1(0)+L1X(PHYSL4END)), R4
+ptel4:
+ ORR R2, R1, R0
+ MOVW R0, (R3)
+ ADD $(MiB), R2
+ ADD $4, R3
+ CMP R3, R4
+ BNE ptel4
+
+ /* fill page tables for l3 interconnect:
+ * 1mb section, kernel read-write */
+ MOVW $((1<<1)|(1<<4)|(1<<10)), R1
+ MOVW $PHYSL3, R2
+ MOVW $(MACHL1(0)+L1X(PHYSL3)), R3
+ MOVW $(MACHL1(0)+L1X(PHYSL3END)), R4
+ptel3:
+ ORR R2, R1, R0
+ MOVW R0, (R3)
+ ADD $(MiB), R2
+ ADD $4, R3
+ CMP R3, R4
+ BNE ptel3
+
+ /* fpu on (set bits 20-23 in CPACR) but disabled */
+ MRC 15, 0, R0, C1, C0, 2
+ ORR $(0xf<<20), R0
+ MCR 15, 0, R0, C1, C0, 2
+
+ VMRS(FPEXC, 0)
+ BIC $(FPEXCEX|FPEXCEN), R0
+ VMSR(0, FPEXC)
+
+ /* invalidate caches */
+ BL l1dcacheinv(SB)
+ BL l1icacheinv(SB)
+
+ /* l2 caches back on */
+ MRC 15, 0, R0, C1, C0, 1
+ ORR $(1<<1), R0
+ MCR 15, 0, R0, C1, C0, 1
+
+ /* l1 caches back on */
+ MRC 15, 0, R0, C1, C0, 0
+ ORR $(1<<12), R0
+ ORR $(1<<1), R0
+ MCR 15, 0, R0, C1, C0, 0
+
+ /* set domain access control to client. */
+ MOVW $1, R0
+ BL putdac(SB)
+
+ /* set translation table base */
+ MOVW $MACHL1(0), R0
+ BL putttb(SB)
+
+ /* mmu on, time to get virtual */
+ MOVW $virt(SB), R2
+ BL mmuinvalidate(SB)
+ BL mmuenable(SB)
+ MOVW R2, R15
+
+TEXT virt(SB), $-4
+ /* setup register variables */
+ MOVW $setR12(SB), R12
+ MOVW $(MACH(0)), R(Rmach)
+ MOVW $0, R(Rup)
+
+ /* setup stack in mach */
+ MOVW $(MACH(0)), R13
+ ADD $(MACHSZ), R13
+ SUB $4, R13
+
+ BL main(SB)
+
+_limbo:
+ BL idlehands(SB)
+ B _limbo
+
+ /* hack to load div */
+ BL _div(SB)
+
+
+TEXT mmuenable(SB), 1, $-4
+ MRC 15, 0, R0, C1, C0, 0
+ ORR $(1<<0), R0
+ MCR 15, 0, R0, C1, C0, 0
+ MCR 15, 0, R0, C7, C5, 6
+ DMB; DSB; ISB
+ RET
+
+TEXT mmudisable(SB), 1, $-4
+ MRC 15, 0, R0, C1, C0, 0
+ BIC $(1<<0), R0
+ MCR 15, 0, R0, C1, C0, 0
+ MCR 15, 0, R0, C7, C5, 6
+ DMB; DSB; ISB
+ RET
+
+TEXT mmuinvalidate(SB), 1, $-4
+ MOVW CPSR, R1
+ CPSID
+
+ MOVW R15, R0
+ MCR 15, 0, R0, C8, C7, 0
+ MCR 15, 0, R0, C7, C5, 6
+ DMB; DSB; ISB
+
+ MOVW R1, CPSR
+ RET
+
+/* get and put domain access control */
+TEXT getdac(SB), 1, $-4; MCR 15, 0, R0, C3, C0; RET
+TEXT putdac(SB), 1, $-4
+ MRC 15, 0, R0, C3, C0
+ ISB
+ RET
+
+
+/* get and put translation table base */
+TEXT getttb(SB), 1, $-4; MRC 15, 0, R0, C2, C0, 0; RET
+TEXT putttb(SB), 1, $-4
+ MCR 15, 0, R0, C2, C0, 0
+ MCR 15, 0, R0, C2, C0, 1
+ ISB
+ RET
+
+TEXT getdfsr(SB), $-4; MRC 15, 0, R0, C5, C0, 0; RET
+TEXT getifsr(SB), $-4; MRC 15, 0, R0, C5, C0, 1; RET
+TEXT getdfar(SB), $-4; MRC 15, 0, R0, C6, C0, 0; RET
+TEXT getifar(SB), $-4; MRC 15, 0, R0, C6, C0, 2; RET
+
+TEXT setvectors(SB), $-4;
+ MCR 15, 0, R0, C12, C0, 0
+ RET
+
+TEXT setlabel(SB), $-4
+ MOVW R13, 0(R0)
+ MOVW R14, 4(R0)
+ MOVW $0, R0
+ RET
+
+TEXT gotolabel(SB), $-4
+ MOVW 0(R0), R13
+ MOVW 4(R0), R14
+ MOVW $1, R0
+ RET
+
+TEXT cas(SB), $0
+TEXT cmpswap(SB), $0
+ MOVW ov+4(FP), R1
+ MOVW nv+8(FP), R2
+casspin:
+ LDREX (R0), R3
+ CMP R3, R1
+ BNE casfail
+ STREX R2, (R0), R4
+ CMP $0, R4
+ BNE casspin
+ MOVW $1, R0
+ DMB
+ RET
+casfail:
+ CLREX
+ MOVW $0, R0
+ RET
+
+TEXT tas(SB), $0
+TEXT _tas(SB), $0
+ MOVW $0xdeaddead, R2
+tasspin:
+ LDREX (R0), R1
+ STREX R2, (R0), R3
+ CMP $0, R3
+ BNE tasspin
+ MOVW R1, R0
+ DMB
+ RET
+
+TEXT idlehands(SB), $-4
+ DMB; DSB; ISB
+ WFI
+ RET
+
+TEXT coherence(SB), $-4
+ DMB; DSB; ISB
+ RET
+
+TEXT splhi(SB), $-4
+ MOVW R14, 4(R(Rmach))
+ MOVW CPSR, R0
+ CPSID
+ RET
+
+TEXT spllo(SB), $-4
+ MOVW CPSR, R0
+ CPSIE
+ RET
+
+TEXT splx(SB), $-4
+ MOVW R14, 4(R(Rmach))
+ MOVW R0, R1
+ MOVW CPSR, R0
+ MOVW R1, CPSR
+ RET
+
+TEXT spldone(SB), $-4
+ RET
+
+TEXT islo(SB), $0
+ MOVW CPSR, R0
+ AND $(PsrDirq), R0
+ EOR $(PsrDirq), R0
+ RET
+
+TEXT perfticks(SB), $0
+ MCR 15, 0, R0, C9, C13, 0
+ RET
+
+TEXT touser(SB), $-4
+ MOVM.DB.W [R0], (R13)
+ MOVM.S (R13), [R13]
+ ADD $4, R13
+
+ MOVW CPSR, R0
+ BIC $(PsrMask|PsrDirq|PsrDfiq), R0
+ ORR $PsrMusr, R0
+ MOVW R0, SPSR
+
+ MOVW $(UTZERO+0x20), R0
+ MOVM.DB.W [R0], (R13)
+
+ MOVM.IA.S.W (R13), [R15]
+
+TEXT forkret(SB), $-4
+ ADD $(15*4), R13
+ MOVW 8(R13), R14
+ MOVW 4(R13), R0
+ MOVW R0, SPSR
+ MOVM.DB.S (R13), [R0-R14]
+ ADD $8, R13
+ MOVM.IA.S.W (R13), [R15]
+
+TEXT peek(SB), $0
+ MOVW src+0(FP), R0
+ MOVW dst+4(FP), R1
+ MOVW cnt+8(FP), R2
+TEXT _peekinst(SB), $0
+_peekloop:
+ MOVB (R0), R3
+ MOVB R3, (R1)
+ SUB.S $1, R0
+ BNE _peekloop
+ RET
+
+TEXT fpinit(SB), $0
+ MOVW $FPEXCEN, R0
+ VMSR(0, FPEXC)
+ MOVW $0, R0
+ VMSR(0, FPSCR)
+ RET
+
+TEXT fpoff(SB), $0
+TEXT fpclear(SB), $0
+ MOVW $0, R1
+ VMSR(1, FPEXC)
+ RET
+
+TEXT fpsave(SB), $0
+ VMRS(FPEXC, 1)
+ VMRS(FPSCR, 2)
+ MOVM.IA.W [R1-R2], (R0)
+ VSTMIA
+ RET
+
+TEXT fprestore(SB), $0
+ MOVM.IA.W (R0), [R1-R2]
+ VMSR(1, FPEXC)
+ VMSR(2, FPSCR)
+ VLDMIA
+ RET
--- /dev/null
+++ b/sys/src/9/n900/lcache.s
@@ -1,0 +1,121 @@
+#include "mem.h"
+#include "io.h"
+
+/* l1 instruction cache invalidate */
+TEXT l1icacheinv(SB), $-4
+ MOVW $0, R0
+ MCR 15, 0, R0, C7, C5, 0
+ ISB
+ RET
+
+/* l1 data cache writeback */
+TEXT l1dcachewb(SB), $-4
+ MOVW $cacheopwb(SB), R0
+ MOVW $0, R1
+ B cacheop(SB)
+
+/* l1 data cache invalidate */
+TEXT l1dcacheinv(SB), $-4
+ MOVW $cacheopinv(SB), R0
+ MOVW $0, R1
+ B cacheop(SB)
+
+/* l1 data cache writeback + invalidate */
+TEXT l1dcachewbinv(SB), $-4
+ MOVW $cacheopwbinv(SB), R0
+ MOVW $0, R1
+ B cacheop(SB)
+
+/* l1 unified instruction + data cache writeback + invalidate */
+TEXT l1ucachewbinv(SB), $-4
+ MOVM.DB.W [R14], (SP)
+ BL l1dcachewbinv(SB)
+ BL l1icacheinv(SB)
+ MOVM.IA.W (SP), [R14]
+ RET
+
+/* l2 instruction + data cache writeback */
+TEXT l2idcachewb(SB), $-4
+ MOVW $cacheopwb(SB), R0
+ MOVW $1, R1
+ B cacheop(SB)
+
+/* l2 instruction + data cache invalidate */
+TEXT l2idcacheinv(SB), $-4
+ MOVW $cacheopinv(SB), R0
+ MOVW $1, R1
+ B cacheop(SB)
+
+/* l2 instruction + data cache writeback + invalidate */
+TEXT l2idcachewbinv(SB), $-4
+ MOVW $cacheopwbinv(SB), R0
+ MOVW $1, R1
+ B cacheop(SB)
+
+/* l1 unified instruction + data cache writeback + invalidate */
+TEXT l2ucachewbinv(SB), $-4
+ MOVM.DB.W [R14], (SP)
+ BL l2idcachewbinv(SB)
+ BL l2idcacheinv(SB)
+ MOVM.IA.W (SP), [R14]
+ RET
+
+/* set/way operations for cacheop */
+TEXT cacheopwb(SB), $-4; MCR 15, 0, R0, C7, C10, 2; RET
+TEXT cacheopinv(SB), $-4; MCR 15, 0, R0, C7, C6, 2; RET
+TEXT cacheopwbinv(SB), $-4; MCR 15, 0, R0, C7, C14, 2; RET
+
+#define Rop R2
+#define Rcache R3
+#define Rways R4
+#define Rwayshift R5
+#define Rsets R6
+#define Rsetshift R7
+#define Rset R8
+
+/* apply a cache operation to the whole cache */
+TEXT cacheop(SB), $-4
+ /* stash */
+ MOVM.DB.W [R2,R14], (SP)
+ MOVW R0, Rop
+ MOVW R1, Rcache
+
+ /* get cache geometry */
+ MCR 15, 2, Rcache, C0, C0, 0; ISB
+ MRC 15, 1, R0, C0, C0, 0
+
+ /* compute ways = ((R0 >> 3) & 0x3ff) + 1) */
+ SRA $3, R0, Rways
+ AND $0x3ff, Rways
+ ADD $1, Rways
+
+ /* compute wayshift = log₂(ways) */
+ CLZ(4, 5) /* Rways, Rwayshift */
+ ADD $1, Rwayshift
+
+ /* compute sets = ((R0 >> 13) & 0x7fff) + 1) */
+ SRA $13, R0, Rsets
+ AND $0x7fff, Rsets
+ ADD $1, Rsets
+
+ /* compute setshift = log₂(cache line size) */
+ AND $0x7, R0, Rsetshift
+ ADD $4, Rsetshift
+
+cacheopways:
+ MOVW Rsets, Rset
+cacheopsets:
+ /* compute set / way register contents */
+ SLL Rwayshift, Rways, R0
+ SLL Rsetshift, Rset, R1
+ ORR R1, R0
+ SLL $1, Rcache, R1
+ ORR R1, R0
+
+ BL (Rop)
+ SUB $1, Rset; CMP $0, Rset; BEQ cacheopsets /* loop sets */
+ SUB $1, Rways; CMP $0, Rways; BEQ cacheopways /* loop ways */
+
+ /* restore */
+ MOVM.IA.W (SP), [R2,R14]
+ RET
--- /dev/null
+++ b/sys/src/9/n900/ltrap.s
@@ -1,0 +1,201 @@
+#include "mem.h"
+#include "io.h"
+
+TEXT vectors(SB), $-4
+ MOVW 24(R15), R15
+ MOVW 24(R15), R15
+ MOVW 24(R15), R15
+ MOVW 24(R15), R15
+ MOVW 24(R15), R15
+ MOVW 24(R15), R15
+ MOVW 24(R15), R15
+ MOVW 24(R15), R15
+
+TEXT vtable(SB), $-4
+ WORD $_vund(SB)
+ WORD $_vund(SB)
+ WORD $_vsvc(SB)
+ WORD $_viabt(SB)
+ WORD $_vdabt(SB)
+ WORD $_vund(SB)
+ WORD $_virq(SB)
+ WORD $_vfiq(SB)
+
+TEXT _vsvc(SB), $-4
+ CLREX
+ DSB
+
+ /* stash in ureg */
+ MOVM.DB.W [R14], (R13) /* ureg->pc */
+ MOVW SPSR, R14
+ MOVM.DB.W [R14], (R13) /* ureg->psr */
+ MOVW $PsrMsvc, R14
+ MOVM.DB.W [R14], (R13) /* ureg->type */
+
+ /* save user regs.
+ * not MOVM.DB.W.S because the saved value of R13 is undefined.
+ * (arm v7 manual §A8.8.199) */
+ MOVM.DB.S [R0-R14], (R13)
+ SUB $(15*4), R13
+
+ /* get our sb, mach, up */
+ MOVW $setR12(SB), R12
+ MOVW $(MACH(0)), R(Rmach)
+ MOVW 8(R(Rmach)), R(Rup)
+
+ /* make space for debugger and go to syscall passing ureg */
+ MOVW R13, R0
+ SUB $8, R13
+ BL syscall(SB)
+ ADD $8, R13
+
+ /* restore link, spsr */
+ ADD $(15*4), R13
+ MOVW 8(R13), R14
+ MOVW 4(R13), R0
+ MOVW R0, SPSR
+
+ /* restore user regs */
+ MOVM.DB.S (R13), [R0-R14]
+
+ /* pop past ureg->type, ureg->psr and restore ureg->pc.
+ * omap and others have RFE here but 5a has no idea about newer instructions
+ * and simulates it with the MOVM below */
+ ADD $8, R13
+ MOVM.IA.S.W (R13), [R15]
+
+TEXT _viabt(SB), $-4
+ CLREX
+ DSB
+ MOVM.IA [R0-R4], (R13)
+ MOVW $PsrMiabt, R0
+ B _vswitch
+
+TEXT _vdabt(SB), $-4
+ CLREX
+ DSB
+ MOVM.IA [R0-R4], (R13)
+ MOVW $PsrMdabt, R0
+ B _vswitch
+
+TEXT _virq(SB), $-4
+ CLREX
+ DSB
+ MOVM.IA [R0-R4], (R13)
+ MOVW $PsrMirq, R0
+ B _vswitch
+
+TEXT _vfiq(SB), $-4
+ CLREX
+ DSB
+ MOVM.IA [R0-R4], (R13)
+ MOVW $PsrMfiq, R0
+ B _vswitch
+
+TEXT _vund(SB), $-4
+ CLREX
+ DSB
+ MOVM.IA [R0-R4], (R13)
+ MOVW $PsrMund, R0
+ B _vswitch
+
+_vswitch:
+ /* stash pointer to previous R0-R4, stash SPSR and R14 for ureg */
+ MOVW SPSR, R1
+ MOVW R14, R2
+ MOVW R13, R3
+
+ /* back to svc mode */
+ MOVW CPSR, R14
+ BIC $PsrMask, R14
+ ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14
+ MOVW R14, CPSR
+
+ /* from user or kernel mode? */
+ AND.S $0xf, R1, R4
+ BEQ _vuser
+
+ /* from kernel mode */
+ /* set ureg->type, ureg->psr, ureg->pc */
+ MOVM.DB.W [R0-R2], (R13)
+ MOVM.IA (R3), [R0-R4]
+
+ /* save kernel regs
+ * not MOVM.DB.W.S because the saved value of R13 is undefined.
+ * (arm v7 manual §A8.8.199) */
+ MOVM.DB [R0-R14], (R13)
+ SUB $(15*4), R13
+
+ /* get our sb, mach, up */
+ MOVW $setR12(SB), R12
+
+ /* make space for debugger and go to trap passing ureg */
+ MOVW R13, R0
+ SUB $8, R13
+ BL trap(SB)
+ ADD $8, R13
+
+ /* restore link, spsr */
+ ADD $(15*4), R13
+ MOVW 8(R13), R14
+ MOVW 4(R13), R0
+ MOVW R0, SPSR
+
+ /* restore kernel regs */
+ MOVM.DB (R13), [R0-R14]
+
+ /* pop past ureg->type, ureg->psr, and restore ureg->pc. */
+ ADD $8, R13
+ MOVM.IA.S.W (R13), [R15]
+
+_vuser:
+ /* from user mode */
+ /* set ureg->type, ureg->psr, ureg->pc */
+ MOVM.DB.W [R0-R2], (R13)
+ MOVM.IA (R3), [R0-R4]
+
+ /* save kernel regs
+ * not MOVM.DB.W.S because the saved value of R13 is undefined.
+ * (arm v7 manual §A8.8.199) */
+ MOVM.DB.S [R0-R14], (R13)
+ SUB $(15*4), R13
+
+ /* get our sb, mach, up */
+ MOVW $setR12(SB), R12
+ MOVW $(MACH(0)), R(Rmach)
+ MOVW 8(R(Rmach)), R(Rup)
+
+ /* make space for debugger and go to trap passing ureg */
+ MOVW R13, R0
+ SUB $8, R13
+ BL trap(SB)
+ ADD $8, R13
+
+ /* restore link, spsr */
+ ADD $(15*4), R13
+ MOVW 8(R13), R14
+ MOVW 4(R13), R0
+ MOVW R0, SPSR
+
+ /* restore kernel regs */
+ MOVM.DB.S (R13), [R0-R14]
+
+ /* pop past ureg->type, ureg->psr, and restore ureg->pc */
+ ADD $8, R13
+ MOVM.IA.S.W (R13), [R15]
+
+TEXT setR13(SB), $-4
+ MOVW 4(FP), R1
+
+ /* switch to new mode */
+ MOVW CPSR, R2
+ BIC $PsrMask, R2, R3
+ ORR R0, R3
+ MOVW R3, CPSR
+
+ /* set r13 */
+ MOVW R1, R13
+
+ /* back to old mode */
+ MOVW R2, CPSR
+ RET
--- /dev/null
+++ b/sys/src/9/n900/main.c
@@ -1,0 +1,222 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#include "tos.h"
+#include "ureg.h"
+#include "pool.h"
+
+#define MAXCONF 64
+
+static char *confname[MAXCONF];
+static char *confval[MAXCONF];
+static int nconf;
+
+Conf conf;
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nconf; i++)
+ if(cistrcmp(confname[i], name) == 0)
+ return confval[i];
+
+ return nil;
+}
+
+int
+isaconfig(char *, int, ISAConf *)
+{
+ return 0;
+}
+
+void
+cpuidprint(void)
+{
+ /* FIXME: how fast are we really? */
+ print("cpu%d: %dMHz ARM Cortex-A8\n", m->machno, 600);
+}
+
+void
+plan9iniinit(void)
+{
+ char *c, *p, *q;
+ char *v[MAXCONF];
+ int i, n;
+
+ c = (char*) CONFADDR;
+ for(p = q = c; *q; q++) {
+ if(*q == '\r')
+ continue;
+ if(*q == '\t')
+ *q = ' ';
+ *p++ = *q;
+ }
+
+ *p = 0;
+ n = getfields(c, v, MAXCONF, 1, "\n");
+ for(i = 0; i < n; i++) {
+ if(v[i][0] == '#')
+ continue;
+
+ c = strchr(v[i], '=');
+ if(!c)
+ continue;
+
+ confname[nconf] = v[i];
+ confval[nconf] = c;
+ nconf++;
+ }
+}
+
+void
+confinit(void)
+{
+ int i;
+ uintptr pa;
+ ulong kp;
+
+ conf.nmach = 1;
+ conf.npage = 0;
+ conf.mem[0].base = PHYSMEM;
+ conf.mem[0].limit = PHYSMEMEND;
+
+ pa = PADDR(PGROUND((uintptr)end));
+ for(i = 0; i < nelem(conf.mem); i++) {
+ if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
+ conf.mem[i].base = pa;
+
+ conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
+ conf.npage += conf.mem[i].npage;
+ }
+
+ conf.upages = (conf.npage*80)/100;
+ conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
+
+ conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
+ if(cpuserver)
+ conf.nproc *= 3;
+ if(conf.nproc > 4000)
+ conf.nproc = 4000;
+
+ conf.nswap = conf.npage*3;
+ conf.nswppo = 4096;
+ conf.nimage = 200;
+ conf.copymode = 0;
+
+ kp = conf.npage - conf.upages;
+ kp *= BY2PG;
+ kp -= conf.upages * sizeof(Page)
+ + conf.nproc * sizeof(Proc*)
+ + conf.nimage * sizeof(Image)
+ + conf.nswap
+ + conf.nswppo * sizeof(Page*);
+
+ mainmem->maxsize = kp;
+ if(!cpuserver)
+ imagmem->maxsize = kp;
+}
+
+void
+machinit(void)
+{
+ m->machno = 0;
+
+ active.machs[0] = 1;
+ active.exiting = 0;
+
+ up = nil;
+}
+
+void
+init0(void)
+{
+ char **sp, buf[KNAMELEN];
+ int i;
+
+ chandevinit();
+ if(!waserror()) {
+ ksetenv("cputype", "arm", 0);
+ if(cpuserver)
+ ksetenv("service", "cpu", 0);
+ else
+ ksetenv("service", "terminal", 0);
+
+ snprint(buf, sizeof(buf), "nokia %s", conffile);
+ ksetenv("terminal", buf, 0);
+ ksetenv("console", "2", 0);
+ ksetenv("kbmap", "n900", 0);
+ for(i = 0; i < nconf; i++) {
+ if(*confname[i] != '*')
+ ksetenv(confname[i], confval[i], 0);
+ ksetenv(confname[i], confval[i], 1);
+ }
+
+ poperror();
+ }
+
+ kproc("alarm", alarmkproc, 0);
+
+ /* prepare stack for boot */
+ sp = (char**)(USTKTOP - sizeof(Tos) - 8 - sizeof(sp[0])*4);
+ sp[3] = sp[2] = sp[1] = nil;
+ strcpy(sp[0] = (char*)&sp[4], "boot");
+ touser(sp);
+}
+
+void
+main(void)
+{
+ uartinit();
+ machinit();
+ mmuinit();
+ plan9iniinit();
+ confinit();
+ printinit();
+ quotefmtinstall();
+ fmtinstall(L'H', encodefmt);
+ print("\nPlan 9\n");
+
+ xinit();
+ trapinit();
+ intrinit();
+ timerinit();
+ cpuidprint();
+ procinit0();
+ initseg();
+ links();
+
+ screeninit();
+ chandevreset();
+
+ pageinit();
+ userinit();
+ schedinit();
+
+ panic("schedinit returned");
+}
+
+void
+exit(int)
+{
+ for(;;)
+ idlehands();
+}
+
+void
+reboot(void *, void *, ulong)
+{
+}
+
+void
+setupwatchpts(Proc *, Watchpt *, int n)
+{
+ if(n > 0)
+ error("no watchpoints");
+}
--- /dev/null
+++ b/sys/src/9/n900/mem.h
@@ -1,0 +1,105 @@
+#define KiB (1024u)
+#define MiB (1024*1024u)
+#define GiB (1024*1024*1024u)
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define Rmach 10
+#define Rup 9
+
+#define HZ (100)
+#define MS2HZ (1000/HZ)
+#define TK2SEC(t) ((t)/HZ)
+
+#define CONFADDR 0x80010000
+
+#define KZERO 0x80000000
+#define KTZERO 0x80020000
+#define KSTACK (8*KiB)
+
+#define UZERO 0
+#define UTZERO BY2PG
+#define USTKTOP 0x20000000
+#define USTKSIZE (16*MiB)
+
+#define MAXMACH 1
+#define MACHSZ (16*KiB)
+#define L1SZ (4*4096)
+#define L2SZ (4*256)
+
+#define L1X(va) ((((va)>>20) & 0xfff) << 2)
+
+#define MACH(n) (KZERO+(n)*MACHSZ)
+#define MACHP(n) ((Mach*)MACH(n))
+#define MACHL1(n) (MACH(MAXMACH)+(n)*L1SZ)
+#define MACHVEC(n) (MACHL1(MAXMACH)+(n)*64*4)
+
+#define BY2PG (4*KiB)
+#define BY2SE 4
+#define BY2WD 4
+#define BY2V 8
+
+#define CACHELINEZ 64
+#define BLOCKALIGN 32
+
+#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
+#define PGROUND(s) ROUND(s, BY2PG)
+#define PGSHIFT 12
+
+#define PTEMAPMEM MiB
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 1984
+#define SSEGMAPSIZE 16
+
+#define PPN(p) ((p)&~(BY2PG-1))
+
+#define PTEVALID (1<<0)
+#define PTERONLY (0<<1)
+#define PTEWRITE (1<<1)
+#define PTECACHED (0<<2)
+#define PTEUNCACHED (1<<2)
+#define PTENOEXEC (1<<3)
+
+#define PsrDfiq 0x40
+#define PsrDirq 0x80
+
+#define PsrMusr 0x10
+#define PsrMfiq 0x11
+#define PsrMirq 0x12
+#define PsrMsvc 0x13
+#define PsrMmon 0x16
+#define PsrMiabt 0x17
+#define PsrMdabt 0x18
+#define PsrMund 0x1b
+#define PsrMsys 0x1f
+
+#define PsrMask 0x1f
+
+#define WFI WORD $0xe320f003
+#define DSB WORD $0xf57ff04f
+#define DMB WORD $0xf57ff05f
+#define ISB WORD $0xf57ff06f
+
+#define CPSIE WORD $0xf1080080
+#define CPSID WORD $0xf10c0080
+
+#define CLZ(s, d) WORD $(0xe16f0f10 | (d) << 12 | (s))
+#define VMSR(cpu, fp) WORD $(0xeee00a10|(fp)<<16|(cpu)<<12)
+#define VMRS(fp, cpu) WORD $(0xeef00a10|(fp)<<16|(cpu)<<12)
+
+#define FPSID 0x0
+#define FPSCR 0x1
+#define MVFR1 0x6
+#define MVFR0 0x7
+#define FPEXC 0x8
+#define FPEXCEX (1<<31)
+#define FPEXCEN (1<<30)
+
+/* vlmdia r0!, {d0-d15}
+ * vldmia r0!, {d16-d31} */
+#define VLDMIA WORD $0xecb00b20; WORD $0xecf00b20;
+
+/* vstmia r0!, {d0-d15}
+ * vstmia r0!, {d16-d31} */
+#define VSTMIA WORD $0xeca00b20; WORD $0xece00b20;
--- /dev/null
+++ b/sys/src/9/n900/mkfile
@@ -1,0 +1,82 @@
+CONF=n900
+CONFLIST=n900
+
+p=9
+objtype=arm
+ktzero=0x80020000
+
+</$objtype/mkfile
+
+DEVS=`{rc ../port/mkdevlist $CONF}
+PORT=\
+ alarm.$O\
+ alloc.$O\
+ allocb.$O\
+ auth.$O\
+ cache.$O\
+ chan.$O\
+ dev.$O\
+ edf.$O\
+ fault.$O\
+ mul64fract.$O\
+ rebootcmd.$O\
+ page.$O\
+ parse.$O\
+ pgrp.$O\
+ portclock.$O\
+ print.$O\
+ proc.$O\
+ qio.$O\
+ qlock.$O\
+ segment.$O\
+ sysfile.$O\
+ sysproc.$O\
+ taslock.$O\
+ tod.$O\
+ xalloc.$O\
+ random.$O\
+ rdb.$O\
+ syscallfmt.$O\
+ userinit.$O\
+ ucalloc.$O\
+
+OBJ=\
+ l.$O\
+ lcache.$O\
+ ltrap.$O\
+ main.$O\
+ mmu.$O\
+ timer.$O\
+ trap.$O\
+ intr.$O\
+ $CONF.root.$O\
+ $CONF.rootc.$O\
+ $DEVS\
+ $PORT\
+
+LIB=\
+ /$objtype/lib/libmemlayer.a\
+ /$objtype/lib/libmemdraw.a\
+ /$objtype/lib/libdraw.a\
+ /$objtype/lib/libip.a\
+ /$objtype/lib/libsec.a\
+ /$objtype/lib/libmp.a\
+ /$objtype/lib/libc.a\
+ /$objtype/lib/libdtracy.a\
+
+$p$CONF.u:D: $p$CONF
+ aux/aout2uimage -o $target -Z0 $prereq
+
+$p$CONF:D: $OBJ $CONF.$O $LIB
+ $LD -o $target -T$ktzero -l $prereq
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+
+initcode.out: init9.$O initcode.$O /$objtype/lib/libc.a
+ $LD -l -R1 -s -o $target $prereq
+
+install:V: $p$CONF.u
+ cp $p$CONF /$objtype/
+ cp $p$CONF.u /$objtype/
--- /dev/null
+++ b/sys/src/9/n900/mmcn900.c
@@ -1,0 +1,308 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "../port/error.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/pci.h"
+#include "../port/sd.h"
+
+enum {
+ Rsysc = 0x10,
+ SCreset = 1 << 1,
+ Rsyss = 0x14,
+ SSreset = 1 << 0,
+ Rcsre = 0x24,
+ Rcon = 0x28,
+ Rpwcnt = 0x2c,
+ Rblk = 0x104,
+ Rarg = 0x108,
+ Rcmd = 0x10c,
+ CRnone = 0 << 16,
+ CR136 = 1 << 16,
+ CR48 = 2 << 16,
+ CR48busy = 3 << 16,
+ CRmask = 3 << 16,
+
+ CFcheckidx = 1 << 19,
+ CFcheckcrc = 1 << 20,
+ CFdata = 1 << 21,
+ CFdataread = 1 << 4,
+ CFdatamulti = 1 << 5,
+
+ CTnone = 0 << 22,
+ CTbus = 1 << 22,
+ CTfunc = 2 << 22,
+ CTio = 3 << 22,
+ Rrsp10 = 0x110,
+ Rrsp32 = 0x114,
+ Rrsp54 = 0x118,
+ Rrsp76 = 0x11c,
+ Rdata = 0x120,
+ Rpstate = 0x124,
+ Rhctl = 0x128,
+ Rsysctl = 0x12c,
+ Rstatus = 0x130,
+ STcmd = 1 << 0,
+ STtransfer = 1 << 1,
+ STbufwrite = 1 << 4,
+ STbufread = 1 << 5,
+
+ STmaskok = 0xffff << 0,
+ STmaskerr = 0xffff << 16,
+ Rie = 0x134,
+ Rise = 0x138,
+ Rac12 = 0x13c,
+ Rcapa = 0x140,
+ Rcapacur = 0x148,
+ Rrev = 0x1fc,
+};
+
+#define csr32r(c, r) ((c)->io[(r)/4])
+#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ char *name;
+ u32int *io;
+ ulong irq;
+
+ struct {
+ uint bcount;
+ uint bsize;
+ } cmd;
+
+ Lock;
+ Rendez;
+};
+
+static int
+n900mmcinit(SDio *io)
+{
+ Ctlr *ctlr;
+
+ ctlr = io->aux;
+ csr32w(ctlr, Rsysc, SCreset);
+ while(!(csr32r(ctlr, Rsyss) & SSreset))
+ ;
+
+ return 0;
+}
+
+static void
+n900mmcenable(SDio *)
+{
+}
+
+static int
+n900mmcinquiry(SDio *, char *inquiry, int len)
+{
+ return snprint(inquiry, len, "MMC Host Controller");
+}
+
+static void
+n900mmcintr(Ureg *, void *aux)
+{
+ Ctlr *ctlr;
+
+ ctlr = aux;
+ ilock(ctlr);
+ if(csr32r(ctlr, Rstatus) & STcmd)
+ wakeup(ctlr);
+
+ iunlock(ctlr);
+}
+
+static int
+n900mmcdone(void *aux)
+{
+ Ctlr *ctlr = aux;
+
+ if(csr32r(ctlr, Rstatus) & STcmd)
+ return 1;
+
+ return 0;
+}
+
+static int
+n900mmccmd(SDio *io, SDiocmd *iocmd, u32int arg, u32int *resp)
+{
+ Ctlr *ctlr;
+ u32int cmd;
+
+ /* prepare flags for this command */
+ ctlr = io->aux;
+ cmd = iocmd->index << 24;
+ switch(iocmd->resp) {
+ case 0: cmd |= CRnone; break;
+ case 2: cmd |= CR136 | CFcheckcrc; break;
+ case 3: cmd |= CR48; break;
+ case 1:
+ if(iocmd->busy) {
+ cmd |= CR48busy | CFcheckidx | CFcheckcrc;
+ break;
+ }
+
+ default:
+ cmd |= CR48 | CFcheckidx | CFcheckcrc;
+ break;
+ }
+
+ /* if there is data, set the data, read, and multi flags */
+ if(iocmd->data) {
+ cmd |= CFdata;
+ if(iocmd->data & 1)
+ cmd |= CFdataread;
+ if(iocmd->data > 2)
+ cmd |= CFdatamulti;
+ }
+
+ /* off it goes, wait for a response */
+ csr32w(ctlr, Rstatus, ~0);
+ csr32w(ctlr, Rarg, arg);
+ csr32w(ctlr, Rcmd, cmd);
+
+ /* wait for command to be done */
+ tsleep(ctlr, n900mmcdone, ctlr, 100);
+ if(csr32r(ctlr, Rstatus) & STmaskerr)
+ error(Eio);
+
+ /* unpack the response */
+ switch(cmd & CRmask) {
+ case CRnone:
+ resp[0] = 0;
+ break;
+
+ case CR136:
+ resp[0] = csr32r(ctlr, Rrsp10);
+ resp[1] = csr32r(ctlr, Rrsp32);
+ resp[2] = csr32r(ctlr, Rrsp54);
+ resp[3] = csr32r(ctlr, Rrsp76);
+ break;
+
+ case CR48:
+ case CR48busy:
+ resp[0] = csr32r(ctlr, Rrsp10);
+ break;
+ }
+
+ return 0;
+}
+
+static void
+n900mmciosetup(SDio *io, int, void *, int bsize, int bcount)
+{
+ Ctlr *ctlr;
+
+ ctlr = io->aux;
+ if(bsize == 0 || (bsize & 3) != 0)
+ error(Egreg);
+
+ ctlr->cmd.bsize = bsize;
+ ctlr->cmd.bcount = bcount;
+ csr32w(ctlr, Rblk, (bsize & 0x3ff) | (bcount << 16));
+}
+
+static void
+n900mmcbufread(Ctlr *ctlr, uchar *buf, int len)
+{
+ for(len >>= 2; len > 0; len--) {
+ *((u32int*)buf) = csr32r(ctlr, Rdata);
+ buf += 4;
+ }
+}
+
+static void
+n900mmcbufwrite(Ctlr *ctlr, uchar *buf, int len)
+{
+ for(len >>= 2; len > 0; len--) {
+ csr32w(ctlr, Rdata, *((u32int*)buf));
+ buf += 4;
+ }
+}
+
+static void
+n900mmcio(SDio *io, int write, uchar *buf, int len)
+{
+ Ctlr *ctlr;
+ u32int stat, n;
+
+ ctlr = io->aux;
+ if(len != ctlr->cmd.bsize * ctlr->cmd.bcount)
+ error(Egreg);
+
+ while(len > 0) {
+ stat = csr32r(ctlr, Rstatus);
+ if(stat & STmaskerr) {
+ csr32w(ctlr, Rstatus, STmaskerr);
+ error(Eio);
+ }
+
+ if(stat & STbufwrite) {
+ csr32w(ctlr, Rstatus, STbufwrite);
+ if(!write)
+ error(Eio);
+
+ n = len;
+ if(n > ctlr->cmd.bsize)
+ n = ctlr->cmd.bsize;
+
+ n900mmcbufwrite(ctlr, buf, n);
+ len -= n;
+ buf += n;
+ }
+
+ if(stat & STbufread) {
+ csr32w(ctlr, Rstatus, STbufread);
+ if(write)
+ error(Eio);
+
+ n = len;
+ if(n > ctlr->cmd.bsize)
+ n = ctlr->cmd.bsize;
+
+ n900mmcbufread(ctlr, buf, n);
+ len -= n;
+ buf += n;
+ }
+
+ if(stat & STtransfer) {
+ csr32w(ctlr, Rstatus, STtransfer);
+ if(len != 0)
+ error(Eio);
+ }
+ }
+}
+
+static void
+n900mmcbus(SDio *, int, int)
+{
+ /* FIXME: change bus width */
+}
+
+void
+mmcn900link(void)
+{
+ int i;
+ static Ctlr ctlr[2] = {
+ { .name = "mmc1", .io = (u32int*) PHYSMMC1, .irq = IRQMMC1, },
+ { .name = "mmc2", .io = (u32int*) PHYSMMC2, .irq = IRQMMC2, },
+ };
+
+ static SDio io[nelem(ctlr)];
+ for(i = 0; i < nelem(io); i++) {
+ io[i].name = "mmc",
+ io[i].init = n900mmcinit,
+ io[i].enable = n900mmcenable,
+ io[i].inquiry = n900mmcinquiry,
+ io[i].cmd = n900mmccmd,
+ io[i].iosetup = n900mmciosetup,
+ io[i].io = n900mmcio,
+ io[i].bus = n900mmcbus,
+ io[i].aux = &ctlr[i];
+
+ addmmcio(&io[i]);
+ intrenable(ctlr[i].irq, n900mmcintr, &ctlr[i], BUSUNKNOWN, ctlr[i].name);
+ }
+}
--- /dev/null
+++ b/sys/src/9/n900/mmu.c
@@ -1,0 +1,311 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+static int debug = 0;
+
+#define L1(va) (((va)>>20) & 0xfff)
+#define L2(va) (((va)>>12) & 0xff)
+#define L1AP(ap) (((ap) << 10) & 0xff) /* dont care about ap[2] */
+#define L2AP(ap) (((ap) << 4) & 0xff)
+
+enum {
+ /* l1 descriptor type (arm v7 manual fig. 12.4) */
+ L1coarse = 1,
+ L1section = 2,
+ L1fine = 3,
+
+ /* l2 descriptor type (arm v7 manual fig. 12.5) */
+ L2large = 1,
+ L2small = 2,
+ L2tiny = 3,
+
+ Fnoexec = 1<<0,
+ Fbuffered = 1<<2,
+ Fcached = 1<<3,
+
+ APkrw = 1, /* kernel read write */
+ APuro = 2, /* user read only */
+ APurw = 3, /* user read write */
+};
+
+void
+mmudebugl2(PTE *l2, uintptr va)
+{
+ uintptr startpa, pa;
+ uintptr startva, endva;
+ int i, t;
+
+ t = 0;
+ startpa = 0;
+ startva = endva = 0;
+ for(i = 0; i < 256; i++) {
+ pa = l2[i] & ~((4*KiB)-1);
+ if(l2[i] == 0) {
+ if(endva) {
+ iprint("mmudebug: l2 type %#ux %#lux %#lux -> %#lux\n", t, startva, endva, startpa);
+ endva = 0;
+ }
+ } else {
+ if(!endva) {
+ startva = va;
+ startpa = pa;
+ t = l2[i] & (L2large | L2small | L2tiny);
+ }
+
+ endva = va + (4*KiB);
+ }
+
+ va += (4*KiB);
+ }
+
+ if(endva)
+ iprint("mmudebug: l2 type %#ux %#lux %#lux -> %#lux\n", t, startva, endva, startpa);
+}
+
+void
+mmudebug(char *where)
+{
+ PTE *l1;
+ uintptr pa, startpa;
+ uintptr va, startva, endva;
+ int i, t;
+
+ if(!debug)
+ return;
+
+ iprint("mmudebug: %s pid %d\n", where, m->mmupid);
+
+ t = 0;
+ l1 = m->mmul1;
+ startpa = 0;
+ startva = endva = 0;
+ for(va = i = 0; i < 4096; i++) {
+ pa = l1[i] & ~(MiB-1);
+ if(l1[i] == 0) {
+ if(endva) {
+ iprint("mmudebug: l1 type %#ux %#lux %#lux -> %#lux\n", t, startva, endva, startpa);
+ endva = 0;
+ }
+ } else {
+ if(!endva) {
+ startva = va;
+ startpa = pa;
+ t = l1[i] & (L1coarse|L1section|L1fine);
+ }
+
+ if(t == L1coarse) {
+ mmudebugl2((PTE*) (l1[i] & ~(KiB-1)), startva);
+ endva = 0;
+ } else {
+ endva = va + MB;
+ }
+ }
+
+ va += MB;
+ }
+
+ if(endva)
+ iprint("mmudebug: l1 type %#ux %#lux %#lux -> %#lux\n", t, startva, endva, startpa);
+}
+
+void
+mmuinit(void)
+{
+ m->mmul1 = (PTE*)MACHL1(m->machno);
+}
+
+static void
+mmul1empty(void)
+{
+ memset(m->mmul1, 0, (ROUND(USTKTOP, MiB)/MiB)*sizeof(PTE));
+}
+
+static void
+mmul2empty(Proc *proc, int clear)
+{
+ PTE *l1;
+ Page **l2, *page;
+
+ l1 = m->mmul1;
+ l2 = &proc->mmul2;
+ for(page = *l2; page != nil; page = page->next) {
+ if(clear)
+ memset((void*)page->va, 0, BY2PG);
+
+ l1[page->daddr] = 0;
+ l2 = &page->next;
+ }
+
+ *l2 = proc->mmul2cache;
+ proc->mmul2cache = proc->mmul2;
+ proc->mmul2 = nil;
+}
+
+void
+mmuswitch(Proc *proc)
+{
+ PTE *l1;
+ Page *page;
+ int l1x;
+
+ if(m->mmupid == proc->pid && !proc->newtlb)
+ return;
+ m->mmupid = proc->pid;
+
+ /* write back and invalidate caches */
+ l1ucachewbinv();
+ l2ucachewbinv();
+
+ if(proc->newtlb) {
+ mmul2empty(proc, 1);
+ proc->newtlb = 0;
+ }
+
+ mmul1empty();
+
+ /* switch to new map */
+ l1 = m->mmul1;
+ for(page = proc->mmul2; page != nil; page = page->next) {
+ l1x = page->daddr;
+ l1[l1x] = PPN(page->pa)|L1coarse;
+ }
+
+ /* FIXME: excessive invalidation */
+ l1ucachewbinv();
+ l2ucachewbinv();
+ mmuinvalidate();
+ mmudebug("mmuswitch");
+}
+
+void
+mmurelease(Proc *proc)
+{
+ l1ucachewbinv();
+ l2ucachewbinv();
+
+ mmul2empty(proc, 0);
+
+ freepages(proc->mmul2cache, nil, 0);
+ proc->mmul2cache = nil;
+
+ mmul1empty();
+
+ /* FIXME: excessive invalidation */
+ l1ucachewbinv();
+ l2ucachewbinv();
+ mmuinvalidate();
+ mmudebug("mmurelease");
+}
+
+void*
+mmuuncache(void *v, usize s)
+{
+ PTE *l1;
+ uintptr va;
+
+ assert(!((uintptr)v & (MiB-1)) && s == MiB);
+
+ va = (uintptr)v;
+ l1 = &m->mmul1[L1(va)];
+ if((*l1 & (L1fine|L1section|L1coarse)) != L1section)
+ return nil;
+
+ *l1 &= ~(Fbuffered|Fcached);
+
+ /* FIXME: excessive invalidation */
+ l1ucachewbinv();
+ l2ucachewbinv();
+ mmuinvalidate();
+ mmudebug("mmuuncache");
+
+ return v;
+}
+
+void
+putmmu(uintptr va, uintptr pa, Page *page)
+{
+ int l1x, s, x;
+ PTE *l1, *l2;
+ Page *pg;
+
+ l1x = L1(va);
+ l1 = &m->mmul1[l1x];
+
+ /* put l1 for l2 table if needed */
+ if(*l1 == 0) {
+ if(up->mmul2cache == nil) {
+ pg = newpage(1, 0, 0);
+ pg->va = VA(kmap(pg));
+ } else {
+ pg = up->mmul2cache;
+ up->mmul2cache = pg->next;
+ memset((void*)pg->va, 0, BY2PG);
+ }
+
+ pg->daddr = l1x;
+ pg->next = up->mmul2;
+ up->mmul2 = pg;
+
+ /* FIXME: excessive invalidation */
+ s = splhi();
+ *l1 = PPN(pg->pa)|L1coarse;
+ l1ucachewbinv();
+ l2ucachewbinv();
+ splx(s);
+ }
+
+ /* put l2 entry */
+ x = L2small;
+ if(!(pa & PTEUNCACHED))
+ x |= Fbuffered|Fcached;
+ if(pa & PTENOEXEC)
+ x |= Fnoexec;
+ if(pa & PTEWRITE)
+ x |= L2AP(APurw);
+ else
+ x |= L2AP(APuro);
+
+ l2 = KADDR(PPN(*l1)); l2[L2(va)] = PPN(pa)|x;
+
+ /* FIXME: excessive invalidation */
+ s = splhi();
+ l1ucachewbinv();
+ l2ucachewbinv();
+ if(needtxtflush(page)) {
+ l1icacheinv();
+ donetxtflush(page);
+ }
+
+ splx(s);
+ mmuinvalidate();
+ mmudebug("putmmu");
+}
+
+void
+checkmmu(uintptr, uintptr)
+{
+ /* this page is intentionally left blank */
+}
+
+void
+flushmmu(void)
+{
+ uint s;
+
+ s = splhi();
+ up->newtlb = 1; mmuswitch(up);
+ splx(s);
+}
+
+uintptr
+cankaddr(uintptr pa)
+{
+ if(pa >= PHYSMEM && pa < PHYSMEMEND)
+ return PHYSMEMEND-pa;
+
+ return 0;
+}
--- /dev/null
+++ b/sys/src/9/n900/n900
@@ -1,0 +1,49 @@
+dev
+ root
+ cons
+ swap
+ env
+ pipe
+ proc
+ mnt
+ srv
+ shr
+ dup
+ tls
+ cap
+ sd
+ fs
+ dtracy
+
+ draw screen
+
+ kbd devi2c
+ rtc devi2c
+
+ uart
+ usb
+ i2c
+
+misc
+ uartn900
+
+ sdmmc mmcn900
+ sdloop
+ sdram
+
+ dtracysys
+ dtracytimer
+ dtracydev
+
+link
+ i2cn900 devi2c
+ mmcn900
+
+port
+ int cpuserver = 0;
+
+bootdir
+ /$objtype/bin/paqfs
+ /$objtype/bin/auth/factotum
+ boot
+ bootfs.paq
--- /dev/null
+++ b/sys/src/9/n900/screen.c
@@ -1,0 +1,373 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include "screen.h"
+
+enum {
+ /* display controller registers */
+ RDrev = 0x400,
+ RDsysconf = 0x410,
+ DSCidle = 1<<0,
+ DSCreset = 1<<1,
+ DSCidlesmart = 2<<3,
+ RDsysstat = 0x414,
+ DSSreset = 1<<0,
+ RDirqstat = 0x418,
+ RDirqen = 0x41c,
+ RDcontrol = 0x440,
+ DClcdon = 1<<0,
+ DClcdactive = 1<<3,
+ DClcdclockrun = 1<<27,
+ DClcdenable = 1<<28,
+ DClcdenablehi = 1<<29,
+ DClcdbits24 = 3<<8,
+ RDconfig = 0x444,
+ DCNgamma = 1<<3,
+ RDdefcolor = 0x44c,
+ RDtranscolor = 0x454,
+ RDlinestat = 0x45c,
+ RDlineintr = 0x460,
+ RDtimeh = 0x464,
+ RDtimev = 0x468,
+ RDsize = 0x47c,
+
+ /* display controller graphics layer registers */
+ RDgfxba = 0x480,
+ RDgfxpos = 0x488,
+ RDgfxsize = 0x48c,
+ RDgfxattr = 0x4a0,
+ DGAenable = 1<<0,
+ DGAfmt = 0x6<<1,
+ DGAburst = 0x2<<6,
+ RDgfxrowinc = 0x4ac,
+ RDgfxpixelinc = 0x4b0,
+};
+
+enum {
+ Tab = 4,
+ Scroll = 8,
+};
+
+#define RDdefcolorn(n) (RDdefcolor + (n)*4)
+#define RDtranscolorn(n) (RDtranscolor + (n)*4)
+
+#define RDgfxban(n) (RDgfxba + (n)*4)
+
+#define TIME(s, f, b) ((s & 0xff) | (f & 0xfff) << 8 | (b & 0xfff) << 20)
+#define POS(x, y) ((x)<<16 | (y))
+#define SIZE(w, h) ((h-1)<<16 | (w-1))
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ Lock;
+
+ u32int *io;
+
+ Memdata scrdata;
+ Memimage *scrimg;
+ Memsubfont *scrfont;
+
+ Rectangle win;
+ Point font;
+ Point pos;
+};
+
+static Ctlr ctlr = {
+ .io = (u32int*) PHYSDSS,
+};
+
+#define csr32r(c, r) ((c)->io[(r)/4])
+#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
+
+static void myscreenputs(char *s, int n);
+
+static int
+screendatainit(Ctlr *ctlr)
+{
+ Rectangle r;
+
+ if(memimageinit() < 0)
+ return -1;
+
+ r = Rect(0, 0, 800, 480);
+ ctlr->scrdata.ref = 1;
+ ctlr->scrdata.bdata = ucalloc(r.max.x * r.max.y * 2);
+ if(!ctlr->scrdata.bdata)
+ return -1;
+
+ ctlr->scrimg = allocmemimaged(r, RGB16, &ctlr->scrdata);
+ if(!ctlr->scrimg)
+ return -1;
+
+ ctlr->scrfont = getmemdefont();
+ return 0;
+}
+
+static Memimage*
+screenmkcolor(Memimage *scr, ulong color)
+{
+ Memimage *i;
+
+ i = allocmemimage(Rect(0, 0, 1, 1), scr->chan);
+ if(i) {
+ i->flags |= Frepl;
+ i->clipr = scr->r;
+ memfillcolor(i, color);
+ }
+
+ return i;
+}
+
+static void
+screenwin(Ctlr *ctlr)
+{
+ Rectangle r;
+ Memimage *i;
+ Point p;
+ int h;
+
+ ctlr->font.y = h = ctlr->scrfont->height;
+ ctlr->font.x = ctlr->scrfont->info[' '].width;
+
+ r = ctlr->scrimg->r;
+ if(i = screenmkcolor(ctlr->scrimg, 0x0D686BFF)) {
+ memimagedraw(ctlr->scrimg, r, i, ZP, memopaque, ZP, S);
+ freememimage(i);
+ }
+
+ r = insetrect(r, 16); memimagedraw(ctlr->scrimg, r, memblack, ZP, memopaque, ZP, S);
+ r = insetrect(r, 4); memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S);
+ if(i = screenmkcolor(ctlr->scrimg, 0xaaaaaaff)) {
+ memimagedraw(ctlr->scrimg, Rpt(r.min, Pt(r.max.x, r.min.y+h+12)), i, ZP, memopaque, ZP, S);
+ freememimage(i);
+
+ r = insetrect(r, 6);
+ p = r.min;
+ memimagestring(ctlr->scrimg, p, memblack, ZP, getmemdefont(), " Plan 9 Console ");
+ }
+
+ ctlr->win = Rpt(addpt(r.min, Pt(0, h + 6)), subpt(r.max, Pt(6, 6)));
+ ctlr->pos = ctlr->win.min;
+ screenputs = myscreenputs;
+}
+
+void
+screeninit(void)
+{
+ Ctlr *c;
+
+ c = &ctlr;
+ if(screendatainit(c) < 0)
+ return;
+
+ screenwin(c);
+ screenputs(kmesg.buf, kmesg.n);
+
+ /* reset the display controller */
+ csr32w(c, RDsysconf, DSCreset);
+ while(!(csr32r(c, RDsysstat) & DSSreset))
+ ;
+
+ /* configure the display controller */
+ csr32w(c, RDsysconf, DSCidle | DSCidlesmart);
+ csr32w(c, RDcontrol, DClcdbits24);
+ csr32w(c, RDconfig, DCNgamma);
+
+ /* configure display size and timings */
+ csr32w(c, RDtimeh, TIME(3, 15, 11));
+ csr32w(c, RDtimev, TIME(2, 3, 3));
+ csr32w(c, RDsize, SIZE(800, 480));
+
+ /* enable the lcd interface */
+ csr32w(c, RDcontrol, csr32r(c, RDcontrol) | DClcdactive | DClcdclockrun | DClcdenablehi);
+ csr32w(c, RDcontrol, csr32r(c, RDcontrol) | DClcdenable);
+
+ /* configure the graphics layer */
+ csr32w(c, RDgfxban(0), (uintptr) c->scrdata.bdata);
+ csr32w(c, RDgfxpos, POS(c->scrimg->r.min.x, c->scrimg->r.min.y));
+ csr32w(c, RDgfxsize, SIZE(c->scrimg->r.max.x, c->scrimg->r.max.y));
+ csr32w(c, RDgfxattr, DGAfmt | DGAburst);
+ csr32w(c, RDgfxrowinc, 1);
+ csr32w(c, RDgfxpixelinc, 1);
+
+ /* enable gfx pipeline and turn lcd on */
+ csr32w(c, RDgfxattr, csr32r(c, RDgfxattr) | DGAenable);
+ csr32w(c, RDcontrol, csr32r(c, RDcontrol) | DClcdon);
+
+ conf.monitor = 1;
+}
+
+static void
+screenscroll(Ctlr *ctlr)
+{
+ int o, h;
+ Point p;
+ Rectangle r;
+
+ h = ctlr->font.y;
+ o = Scroll * h;
+ r = Rpt(ctlr->win.min, Pt(ctlr->win.max.x, ctlr->win.max.y - o));
+ p = Pt(ctlr->win.min.x, ctlr->win.min.y + o);
+ memimagedraw(ctlr->scrimg, r, ctlr->scrimg, p, nil, p, S);
+ flushmemscreen(r);
+
+ r = Rpt(Pt(ctlr->win.min.x, ctlr->win.max.y - o), ctlr->win.max);
+ memimagedraw(ctlr->scrimg, r, memwhite, ZP, nil, ZP, S);
+ flushmemscreen(r);
+
+ ctlr->pos.y -= o;
+
+}
+
+static void
+screenputc(Ctlr *ctlr, char *buf)
+{
+ Point p;
+ Rectangle r;
+ uint chr;
+ int w, h;
+ static int *xp;
+ static int xbuf[256];
+
+ w = ctlr->font.x;
+ h = ctlr->font.y;
+ if(xp < xbuf || xp >= &xbuf[nelem(xbuf)])
+ xp = xbuf;
+
+ switch(buf[0]) {
+ case '\n':
+ if(ctlr->pos.y + h >= ctlr->win.max.y)
+ screenscroll(ctlr);
+
+ ctlr->pos.y += h;
+ screenputc(ctlr, "\r");
+ break;
+
+ case '\r':
+ xp = xbuf;
+ ctlr->pos.x = ctlr->win.min.x;
+ break;
+
+ case '\t':
+ if(ctlr->pos.x >= ctlr->win.max.x - 4 * w)
+ screenputc(ctlr, "\n");
+
+ chr = (ctlr->pos.x - ctlr->win.min.x) / w;
+ chr = Tab - chr % Tab;
+ *xp++ = ctlr->pos.x;
+
+ r = Rect(ctlr->pos.x, ctlr->pos.y, ctlr->pos.x + chr * w, ctlr->pos.y + h);
+ memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S);
+ flushmemscreen(r);
+ ctlr->pos.x += chr * w;
+ break;
+
+ case '\b':
+ if(xp <= xbuf)
+ break;
+
+ xp--;
+ r = Rect(*xp, ctlr->pos.y, ctlr->pos.x, ctlr->pos.y + h);
+ memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S);
+ ctlr->pos.x = *xp;
+ break;
+
+ case '\0':
+ break;
+
+ default:
+ p = memsubfontwidth(getmemdefont(), buf); w = p.x;
+ if(ctlr->pos.x >= ctlr->win.max.x - w)
+ screenputc(ctlr, "\n");
+
+ *xp++ = ctlr->pos.x;
+ r = Rect(ctlr->pos.x, ctlr->pos.y, ctlr->pos.x + w, ctlr->pos.y + h);
+ memimagedraw(ctlr->scrimg, r, memwhite, ZP, memopaque, ZP, S);
+ memimagestring(ctlr->scrimg, ctlr->pos, memblack, ZP, getmemdefont(), buf);
+ ctlr->pos.x += w;
+ break;
+ }
+}
+
+static void
+myscreenputs(char *s, int n)
+{
+ Ctlr *c;
+ Rune r;
+ int i;
+ char buf[UTFmax];
+
+ c = &ctlr;
+ if(!c->scrimg)
+ return;
+
+ if(!islo()) {
+ /* don't deadlock trying to print in an interrupt */
+ if(!canlock(c))
+ return;
+ } else {
+ lock(c);
+ }
+
+ while(n > 0) {
+ i = chartorune(&r, s);
+ if(i == 0) {
+ s++; n--;
+ continue;
+ }
+
+ memmove(buf, s, i);
+ buf[i] = 0;
+ s += i; n -= i;
+ screenputc(c, buf);
+ }
+
+ unlock(c);
+}
+
+Memdata*
+attachscreen(Rectangle *r, ulong *chan, int *d, int *width, int *softscreen)
+{
+ Ctlr *c;
+
+ c = &ctlr;
+ if(!c->scrimg)
+ return nil;
+
+ *r = c->scrimg->r;
+ *d = c->scrimg->depth;
+ *chan = c->scrimg->chan;
+ *width = c->scrimg->width;
+ *softscreen = 1;
+
+ c->scrdata.ref++;
+ return &c->scrdata;
+}
+
+void
+getcolor(ulong, ulong *, ulong *, ulong *)
+{
+}
+
+int
+setcolor(ulong, ulong, ulong, ulong)
+{
+ return 0;
+}
+
+void
+flushmemscreen(Rectangle)
+{
+}
+
+void
+mouseresize(void)
+{
+}
--- /dev/null
+++ b/sys/src/9/n900/screen.h
@@ -1,0 +1,9 @@
+void screeninit(void);
+void flushmemscreen(Rectangle);
+Memdata *attachscreen(Rectangle *, ulong *, int *, int *, int *);
+
+#define ishwimage(i) 1
+
+void mousectl(Cmdbuf*);
+void mouseresize(void);
+void mouseredraw(void);
--- /dev/null
+++ b/sys/src/9/n900/timer.c
@@ -1,0 +1,172 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum {
+ Rrev = 0x00,
+ Rsyscfg = 0x10,
+ Cidle = 1<<0,
+ Creset = 1<<1,
+ Rsysstat = 0x14,
+ Sreset = 1<<0,
+ Risr = 0x18,
+ Rier = 0x1c,
+ Imatch = 1<<0,
+ Ioverflow = 1<<1,
+ Icapture = 1<<2,
+ Rclr = 0x24,
+ CLst = 1<<0,
+ CLar = 1<<1,
+ CLtgovf = 1<<10,
+ CLtgmatch = 1<<11,
+ Rcrr = 0x28,
+ Rldr = 0x2c,
+};
+
+typedef union Counter Counter;
+typedef struct Ctlr Ctlr;
+
+union Counter {
+ uvlong cnt;
+ struct {
+ ulong cntlo;
+ ulong cnthi;
+ };
+};
+
+struct Ctlr {
+ Lock;
+ Counter;
+
+ u32int *io;
+};
+
+static Ctlr timers[] = {
+ { .io = (u32int*) PHYSTIMER1 }, /* for cycles */
+ { .io = (u32int*) PHYSTIMER2 }, /* for interrupts */
+};
+
+#define csr32r(c, r) ((c)->io[(r)/4])
+#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
+
+static void
+timerreset(Ctlr *ctlr)
+{
+ int i;
+ int cfg;
+
+ cfg = csr32r(ctlr, Rsyscfg);
+ cfg |= Creset;
+ cfg &= ~Cidle;
+
+ ilock(ctlr);
+ csr32w(ctlr, Rsyscfg, cfg);
+ for(i = 40000; i > 0; i++) {
+ if(csr32r(ctlr, Rsysstat) & Sreset)
+ break;
+ }
+
+ if(i == 0)
+ panic("clock reset failed");
+
+ iunlock(ctlr);
+}
+
+static void
+timerstartcycles(Ctlr *ctlr)
+{
+ timerreset(ctlr);
+
+ /* configure this timer for measuring cycles */
+ ilock(ctlr);
+ csr32w(ctlr, Rldr, 0);
+ csr32w(ctlr, Rclr, CLst | CLar);
+ iunlock(ctlr);
+}
+
+static void
+timerstartintr(Ctlr *ctlr, ulong t)
+{
+ timerreset(ctlr);
+
+ /* configure this timer for periodic interrupts */
+ ilock(ctlr);
+ csr32w(ctlr, Rier, Ioverflow);
+ csr32w(ctlr, Rldr, -t);
+ csr32w(ctlr, Rcrr, -t);
+ csr32w(ctlr, Rclr, CLst | CLar);
+ iunlock(ctlr);
+}
+
+static void
+timerinterrupt(Ureg *u, void *arg)
+{
+ Ctlr *ctlr = arg;
+ csr32w(ctlr, Risr, Ioverflow);
+
+ timerintr(u, 0);
+}
+
+void
+timerinit(void)
+{
+ intrenable(IRQTIMER2, timerinterrupt, &timers[1], BUSUNKNOWN, "timer");
+
+ timerstartcycles(&timers[0]);
+ timerstartintr(&timers[1], 32);
+}
+
+uvlong
+fastticks(uvlong *hz)
+{
+ Counter c;
+ Ctlr *ctlr;
+
+ /* FIXME: this has poor precision, but qemu has no cycle counter */
+ ctlr = &timers[0];
+ if(hz)
+ *hz = 32*1024;
+
+ ilock(ctlr);
+ c.cnt = ctlr->cnt;
+ c.cntlo = csr32r(ctlr, Rcrr);
+ if(c.cnt < ctlr->cnt)
+ c.cnthi++;
+
+ ctlr->cnt = c.cnt;
+ iunlock(ctlr);
+
+ return ctlr->cnt;
+}
+
+ulong
+µs(void)
+{
+ return fastticks2us(fastticks(nil));
+}
+
+void
+microdelay(int n)
+{
+ ulong now;
+
+ now = µs();
+ while(µs() - now < n)
+ ;
+}
+
+void
+delay(int n)
+{
+ while(--n >= 0)
+ microdelay(1000);
+}
+
+void
+timerset(Tval)
+{
+ /* FIXME: ? */
+}
--- /dev/null
+++ b/sys/src/9/n900/trap.c
@@ -1,0 +1,577 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+#include "../port/systab.h"
+
+#include "tos.h"
+#include "ureg.h"
+
+void
+callwithureg(void (*f) (Ureg *))
+{
+ Ureg u;
+
+ u.pc = getcallerpc(&f);
+ u.sp = (uintptr) &f - 4;
+ f(&u);
+}
+
+void
+dumpstackureg(Ureg *ureg)
+{
+ uintptr l, v, i, estack;
+ int x;
+
+ x = 0;
+ x += iprint("ktrace /arm/9n900 %#.8lux %#.8lux %#.8lux <<EOF\n",
+ ureg->pc, ureg->sp, ureg->r14);
+
+ i = 0;
+ if(up)
+ estack = (uintptr)up;
+ else
+ estack = (uintptr)m+MACHSZ;
+
+ x += iprint("estackx %p\n", estack);
+ for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)) {
+ v = *(uintptr*)l;
+ if((KTZERO < v && v < (uintptr)etext) || estack-l < 32) {
+ x += iprint("%.8p=%.8p ", l, v);
+ i++;
+ }
+
+ if(i == 4) {
+ i = 0;
+ x += iprint("\n");
+ }
+ }
+
+ if(i)
+ iprint("\n");
+ iprint("EOF\n");
+}
+
+void
+dumpstack(void)
+{
+ callwithureg(dumpstackureg);
+}
+
+void
+dumpureg(Ureg *ureg)
+{
+ if(up)
+ iprint("cpu%d: registers for %s %lud\n", m->machno, up->text, up->pid);
+ else
+ iprint("cpu%d: registers for kernel\n", m->machno);
+
+ iprint("r0 %#.8lux\tr1 %#.8lux\tr2 %#.8lux\tr3 %#.8lux\n", ureg->r0, ureg->r1, ureg->r2, ureg->r3);
+ iprint("r4 %#.8lux\tr5 %#.8lux\tr6 %#.8lux\tr7 %#.8lux\n", ureg->r4, ureg->r5, ureg->r6, ureg->r7);
+ iprint("r8 %#.8lux\tr9 %#.8lux\tr10 %#.8lux\tr11 %#.8lux\n", ureg->r8, ureg->r9, ureg->r10, ureg->r11);
+ iprint("r12 %#.8lux\tr13 %#.8lux\tr14 %#.8lux\tr15 %#.8lux\n", ureg->r12, ureg->r13, ureg->r14, ureg->pc);
+}
+
+
+uintptr
+userpc(void)
+{
+ return ((Ureg*)up->dbgreg)->pc;
+}
+
+uintptr
+dbgpc(Proc *)
+{
+ if(up->dbgreg)
+ return userpc();
+
+ return 0;
+}
+
+void
+procsetup(Proc *p)
+{
+ p->fpstate = FPinit;
+ fpoff();
+}
+
+void
+procsave(Proc *p)
+{
+ if(p->fpstate == FPactive) {
+ if(p->state == Moribund)
+ fpclear();
+ else
+ fpsave(p->fpsave);
+ p->fpstate = FPinactive;
+ }
+}
+
+void
+procrestore(Proc *)
+{
+}
+
+void
+procfork(Proc *p)
+{
+ ulong s;
+
+ s = splhi();
+ switch(up->fpstate & ~FPillegal) {
+ case FPactive:
+ fpsave(up->fpsave);
+ up->fpstate = FPinactive;
+ case FPinactive:
+ memmove(p->fpsave, up->fpsave, sizeof(FPsave));
+ p->fpstate = FPinactive;
+ }
+
+ splx(s);
+}
+
+void
+kprocchild(Proc *p, void (*entry)(void))
+{
+ p->sched.pc = (uintptr) entry;
+ p->sched.sp = (uintptr) p;
+}
+
+void
+forkchild(Proc *p, Ureg *ureg)
+{
+ Ureg *cureg;
+
+ p->sched.sp = (uintptr) p - sizeof(Ureg);
+ p->sched.pc = (uintptr) forkret;
+
+ cureg = (Ureg*) p->sched.sp;
+ memmove(cureg, ureg, sizeof(Ureg));
+ cureg->r0 = 0;
+}
+
+uintptr
+execregs(uintptr entry, ulong ssize, ulong nargs)
+{
+ ulong *sp;
+ Ureg *ureg;
+
+ sp = (ulong*)(USTKTOP - ssize); *--sp = nargs;
+ ureg = up->dbgreg;
+ ureg->sp = (uintptr) sp;
+ ureg->pc = entry;
+ ureg->r14 = 0;
+
+ return USTKTOP-sizeof(Tos);
+}
+
+void
+setkernur(Ureg *ureg, Proc *p)
+{
+ ureg->pc = p->sched.pc;
+ ureg->sp = p->sched.sp+4;
+ ureg->r14 = (uintptr) sched;
+}
+
+void
+setregisters(Ureg *ureg, char *pureg, char *uva, int n)
+{
+ uvlong v;
+
+ v = ureg->psr;
+ memmove(pureg, uva, n);
+ ureg->psr &= ~(PsrMask|PsrDfiq|PsrDirq);
+ ureg->psr |= v & (PsrMask|PsrDfiq|PsrDirq);
+}
+
+void
+evenaddr(uintptr addr)
+{
+ if(addr & 3) {
+ postnote(up, 1, "sys: odd address", NDebug);
+ error(Ebadarg);
+ }
+}
+
+int
+notify(Ureg *ureg)
+{
+ ulong s, sp;
+ char *msg;
+
+ if(up->procctl)
+ procctl();
+ if(up->nnote == 0)
+ return 0;
+
+ if(up->fpstate == FPactive) {
+ fpsave(up->fpsave);
+ up->fpstate = FPinactive;
+ }
+ up->fpstate |= FPillegal;
+
+ s = spllo();
+ qlock(&up->debug);
+ msg = popnote(ureg);
+ if(msg == nil) {
+ qunlock(&up->debug);
+ splhi();
+ return 0;
+ }
+
+ sp = ureg->sp;
+ sp -= 256;
+ sp -= sizeof(Ureg);
+
+ if(!okaddr((uintptr)up->notify, 1, 0)
+ || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)
+ || ((uintptr) up->notify & 3) != 0
+ || (sp & 3) != 0) {
+ qunlock(&up->debug);
+ pprint("suicide: bad address in notify\n");
+ pexit("Suicide", 0);
+ }
+
+ memmove((Ureg*)sp, ureg, sizeof(Ureg));
+ *(Ureg**)(sp-BY2WD) = up->ureg;
+ up->ureg = (void*)sp;
+ sp -= BY2WD+ERRMAX;
+ memmove((char*)sp, msg, ERRMAX);
+ sp -= 3*BY2WD;
+ *(uintptr*)(sp+2*BY2WD) = sp+3*BY2WD;
+ *(uintptr*)(sp+1*BY2WD) = (uintptr)up->ureg;
+ ureg->r0 = (uintptr) up->ureg;
+ ureg->sp = sp;
+ ureg->pc = (uintptr) up->notify;
+ ureg->r14 = 0;
+
+ qunlock(&up->debug);
+ splx(s);
+ return 1;
+}
+
+void
+noted(Ureg *ureg, ulong arg0)
+{
+ Ureg *nureg;
+ ulong oureg, sp;
+
+ qlock(&up->debug);
+ if(arg0 != NRSTR && !up->notified) {
+ qunlock(&up->debug);
+ iprint("called to noted when not notified\n");
+ pexit("Suicide", 0);
+ }
+
+ up->notified = 0;
+ up->fpstate &= ~FPillegal;
+ nureg = up->ureg;
+ oureg = (ulong) nureg;
+ if(!okaddr(oureg - BY2WD, BY2WD + sizeof(Ureg), 0) || (oureg & 3) != 0) {
+ qunlock(&up->debug);
+ pprint("bad ureg in noted or call to noted when not notifed\n");
+ pexit("Suicide", 0);
+ }
+
+ nureg->psr &= PsrMask|PsrDfiq|PsrDirq;
+ nureg->psr |= (ureg->psr & ~(PsrMask|PsrDfiq|PsrDirq));
+
+ memmove(ureg, nureg, sizeof(Ureg));
+ switch(arg0) {
+ case NCONT:
+ case NRSTR:
+ if(!okaddr(nureg->pc, BY2WD, 0) || (nureg->pc & 3) != 0
+ || !okaddr(nureg->sp, BY2WD, 0) || (nureg->sp & 3) != 0) {
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+
+ up->ureg = (Ureg *) (*(ulong*) (oureg - BY2WD));
+ qunlock(&up->debug);
+ break;
+
+ case NSAVE:
+ if(!okaddr(nureg->pc, BY2WD, 0) || (nureg->pc & 3) != 0
+ || !okaddr(nureg->sp, BY2WD, 0) || (nureg->sp & 3) != 0) {
+ qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
+ pexit("Suicide", 0);
+ }
+
+ qunlock(&up->debug);
+ sp = oureg - 4 * BY2WD - ERRMAX;
+ splhi();
+ ureg->sp = sp;
+ ureg->r0 = (uintptr) oureg;
+ ((ulong*) sp)[1] = oureg;
+ ((ulong*) sp)[0] = 0;
+ break;
+
+ default:
+ up->lastnote->flag = NDebug;
+ /* wet floor */
+
+ case NDFLT:
+ qunlock(&up->debug);
+ if(up->lastnote->flag == NDebug)
+ pprint("suicide: %s\n", up->lastnote->msg);
+
+ pexit(up->lastnote->msg, up->lastnote->flag != NDebug);
+ break;
+ }
+}
+
+void
+trapinit(void)
+{
+ extern ulong vectors[];
+
+ /* install stack pointer for other exception modes */
+ setR13(PsrMfiq, m->save);
+ setR13(PsrMirq, m->save);
+ setR13(PsrMiabt, m->save);
+ setR13(PsrMund, m->save);
+ setR13(PsrMsys, m->save);
+
+ /* install vectors and vtable to MACHVEC because vectors must be
+ * aligned on a 128 byte boundary */
+ memmove((ulong*)MACHVEC(m->machno), vectors, 64 * 4);
+
+ /* set vectors base address */
+ setvectors(MACHVEC(m->machno));
+}
+
+static void
+trapfpu(void)
+{
+ int s;
+
+ if((up->fpstate & FPillegal) != 0) {
+ postnote(up, 1, "sys: floating point in note handler", NDebug);
+ return;
+ }
+
+ switch(up->fpstate) {
+ case FPinit:
+ s = splhi();
+ fpinit(); up->fpstate = FPactive;
+ splx(s);
+ break;
+
+ case FPinactive:
+ s = splhi();
+ fprestore(up->fpsave); up->fpstate = FPactive;
+ splx(s);
+ break;
+
+ case FPactive:
+ postnote(up, 1, "sys: floating point error", NDebug);
+ break;
+ }
+}
+
+static void
+traparm(Ureg *ureg, ulong fsr, uintptr far)
+{
+ int user;
+ int read;
+ int syscall;
+
+ static char buf[ERRMAX];
+
+ read = (fsr & (1<<11)) == 0;
+ user = userureg(ureg);
+ if(!user) {
+ if(far >= USTKTOP)
+ panic("kernel fault: bad address pc=%#.8lux far=%#.8lux fsr=%#.8lux",
+ ureg->pc, far, fsr);
+ if(up == nil)
+ panic("kernel fault: no user process pc=%#.8lux far=%#.8lux fsr=%#.8lux",
+ ureg->pc, far, fsr);
+ }
+
+ if(up == nil) {
+ panic("user fault: up=nil pc=%#.8lux far=%#.8lux fsr=%#.8lux",
+ ureg->pc, far, fsr);
+ }
+
+ syscall = up->insyscall; up->insyscall = 1;
+ switch(fsr & 0x1f) {
+ case 0x03: /* l1 access flag fault */
+ case 0x05: /* l1 translation fault */
+ case 0x06: /* l2 access flag fault */
+ case 0x07: /* l2 translation fault */
+ case 0x09: /* l1 domain fault */
+ case 0x0b: /* l2 domain fault */
+ case 0x0d: /* l1 permission fault */
+ case 0x0f: /* l2 permission fault */
+ if(fault(far, ureg->pc, read) == 0)
+ break;
+
+ default:
+ if(!user)
+ panic("kernel fault: pc=%#.8lux far=%#.8lux fsr=%#.8lux",
+ ureg->pc, far, fsr);
+
+ dumpureg(ureg);
+ dumpstackureg(ureg);
+ snprint(buf, sizeof(buf), "sys: trap: fault %s far=%#.8lux fsr=%#.8lux",
+ read ? "read" : "write", far, fsr);
+ postnote(up, 1, buf, NDebug);
+ }
+
+ up->insyscall = syscall;
+}
+
+void
+trap(Ureg *ureg)
+{
+ int user;
+ u32int op, cp;
+
+ user = kenter(ureg);
+ switch(ureg->type) {
+ case PsrMfiq:
+ case PsrMirq:
+ ureg->pc -= 4;
+ intr(ureg);
+ break;
+
+ case PsrMiabt:
+ ureg->pc -= 4;
+ traparm(ureg, getifsr(), getifar());
+ break;
+
+ case PsrMdabt:
+ ureg->pc -= 8;
+ traparm(ureg, getdfsr(), getdfar());
+ break;
+
+ case PsrMund:
+ ureg->pc -= 4;
+ if(user) {
+ spllo();
+ if(okaddr(ureg->pc, 4, 0)) {
+ op = *(u32int*)ureg->pc;
+ if((op & 0x0f000000) == 0x0e000000 || (op & 0x0e000000) == 0x0c000000) {
+ cp = op >> 8 & 15;
+ if(cp == 10 || cp == 11) {
+ trapfpu();
+ break;
+ }
+ }
+ }
+
+ postnote(up, 1, "sys: trap: invalid opcode", NDebug);
+ break;
+ }
+
+ panic("invalid opcode at pc=%#.8lux lr=%#.8lux", ureg->pc, ureg->r14);
+ break;
+
+ default:
+ panic("unknown trap at pc=%#.8lux lr=%#.8lux", ureg->pc, ureg->r14);
+ break;
+ }
+
+ splhi();
+ if(user) {
+ if(up->procctl || up->nnote)
+ notify(ureg);
+
+ kexit(ureg);
+ }
+}
+
+void
+syscall(Ureg *ureg)
+{
+ char *e;
+ uintptr sp;
+ long ret;
+ int i, s;
+ ulong scallnr;
+ vlong startns, stopns;
+
+ if(!kenter(ureg))
+ panic("syscall: from kernel: pc=%#.8lux", ureg->pc);
+
+ m->syscall++;
+ up->insyscall = 1;
+ up->pc = ureg->pc;
+
+ scallnr = up->scallnr = ureg->r0;
+ sp = ureg->sp;
+
+ spllo();
+
+ up->nerrlab = 0;
+ ret = -1;
+ if(!waserror()) {
+ if(scallnr >= nsyscall) {
+ pprint("bad sys call number %lux pc %#lux", scallnr, ureg->pc);
+ postnote(up, 1, "sys: bad sys call", NDebug);
+ error(Ebadarg);
+ }
+
+ if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD)) {
+ validaddr(sp, sizeof(Sargs)+BY2WD, 0);
+ evenaddr(sp);
+ }
+
+ up->s = *((Sargs*)(sp + BY2WD));
+ up->psstate = sysctab[scallnr];
+ if (up->procctl == Proc_tracesyscall) {
+ syscallfmt(scallnr, ureg->pc, (va_list)up->s.args);
+ s = splhi();
+ up->procctl = Proc_stopme;
+ procctl();
+ splx(s);
+ startns = todget(nil);
+ }
+
+ ret = systab[scallnr]((va_list)up->s.args);
+ poperror();
+ } else {
+ e = up->syserrstr;
+ up->syserrstr = up->errstr;
+ up->errstr = e;
+ }
+
+ if(up->nerrlab) {
+ print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
+ for (i = 0; i < NERR; i++)
+ print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
+
+ panic("error stack");
+ }
+
+ ureg->r0 = ret;
+ if(up->procctl == Proc_tracesyscall) {
+ stopns = todget(nil);
+ sysretfmt(scallnr, (va_list)up->s.args, ret, startns, stopns);
+ s = splhi();
+ up->procctl = Proc_stopme;
+ procctl();
+ splx(s);
+ }
+
+ up->insyscall = 0;
+ up->psstate = 0;
+ if(scallnr == NOTED)
+ noted(ureg, *((ulong *)up->s.args));
+
+ if(scallnr != RFORK && (up->procctl || up->nnote)) {
+ splhi();
+ notify(ureg);
+ }
+
+ if(up->delaysched)
+ sched();
+
+ kexit(ureg);
+ splhi();
+}
--- /dev/null
+++ b/sys/src/9/n900/uartn900.c
@@ -1,0 +1,268 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum {
+ Rdll = 0x00,
+ Rrhr = 0x00,
+ Rthr = 0x00,
+ Rdlh = 0x04,
+ Rier = 0x04,
+ IErhr = 1 << 0,
+ IEthr = 1 << 1,
+ IEls = 1 << 2,
+ IEms = 1 << 3,
+ Riir = 0x08,
+ Ipending = 1 << 0,
+ Imodem = 0x00,
+ Ithr = 0x01,
+ Irhr = 0x02,
+ Ils = 0x03,
+ Irxt = 0x06,
+ Ixoff = 0x08,
+ Icts = 0x10,
+ Imask = 0x1f,
+ Rfcr = 0x08,
+ FCRen = 1 << 0,
+ Refr = 0x08,
+ Rlcr = 0x0c,
+ Rmcr = 0x10,
+ Rxon1 = 0x10,
+ Rlsr = 0x14,
+ LSRrxempty = 1 << 0,
+ LSRrxover = 1 << 1,
+ LSRrxparity = 1 << 2,
+ LSRrxframe = 1 << 3,
+ LSRrxbreak = 1 << 4,
+ LSRtxempty = 1 << 5,
+ LSRtxshift = 1 << 6,
+ LSRrxstat = 1 << 7,
+ Rxon2 = 0x14,
+ Rmsr = 0x18,
+ Rtcr = 0x18,
+ Rxoff1 = 0x18,
+ Rspr = 0x1c,
+ Rtlr = 0x1c,
+ Rxoff2 = 0x1c,
+ Rmdr1 = 0x20,
+ Rmdr2 = 0x24,
+ Rsysc = 0x54,
+ SCreset = 1 << 1,
+ Rsyss = 0x58,
+ SSreset = 1 << 0,
+};
+
+#define csr32r(c, r) ((c)->io[(r)/4])
+#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
+
+typedef struct Ctlr Ctlr;
+struct Ctlr {
+ Lock;
+
+ u32int *io;
+ ulong irq;
+
+ int ie;
+};
+
+extern PhysUart n900physuart;
+
+static Ctlr ctlr[] = {
+ { .io = (u32int*) PHYSUART1, .irq = IRQUART1, },
+ { .io = (u32int*) PHYSUART2, .irq = IRQUART2, },
+ { .io = (u32int*) PHYSUART3, .irq = IRQUART3, },
+};
+
+static Uart n900uart[] = {
+ {
+ .regs = &ctlr[0],
+ .name = "uart1",
+ .freq = 48000000,
+ .phys = &n900physuart,
+ .next = &n900uart[1],
+ },
+ {
+ .regs = &ctlr[1],
+ .name = "uart2",
+ .freq = 48000000,
+ .phys = &n900physuart,
+ .next = &n900uart[2],
+ },
+ {
+ .regs = &ctlr[2],
+ .name = "uart3",
+ .freq = 48000000,
+ .phys = &n900physuart,
+ .next = nil,
+ },
+};
+
+static Uart *
+n900uartpnp(void)
+{
+ return n900uart;
+}
+
+static long
+n900uartstatus(Uart *, void *, long, long)
+{
+ return 0;
+}
+
+static void
+n900uartintr(Ureg *, void *arg)
+{
+ Uart *uart;
+ Ctlr *ctlr;
+ int lsr;
+ char c;
+
+ uart = arg;
+ ctlr = uart->regs;
+
+ ilock(ctlr);
+ switch((csr32r(ctlr, Riir) >> 1) & Imask) {
+ case Ithr:
+ uartkick(uart);
+ break;
+
+ case Irhr:
+ while((lsr = csr32r(ctlr, Rlsr)) & LSRrxempty) {
+ c = csr32r(ctlr, Rrhr);
+
+ if(lsr & LSRrxover) { uart->oerr++; break; }
+ if(lsr & LSRrxparity) { uart->perr++; break; }
+ if(lsr & LSRrxframe) { uart->ferr++; break; }
+
+ uartrecv(uart, c);
+ }
+
+ break;
+ }
+
+ iunlock(ctlr);
+}
+
+static void
+n900uartenable(Uart *uart, int ie)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ ilock(ctlr);
+
+ csr32w(ctlr, Rsysc, SCreset);
+ while(!(csr32r(ctlr, Rsyss) & SSreset))
+ ;
+
+ csr32w(ctlr, Rfcr, FCRen);
+ if(ie) {
+ if(!ctlr->ie) {
+ intrenable(ctlr->irq, n900uartintr, uart, 0, uart->name);
+ ctlr->ie = 1;
+ }
+
+ csr32w(ctlr, Rier, IErhr);
+ }
+
+ iunlock(ctlr);
+}
+
+static void
+n900uartdisable(Uart *uart)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+
+ ilock(ctlr);
+ csr32w(ctlr, Rier, 0);
+ if(ctlr->ie) {
+ intrdisable(ctlr->irq, n900uartintr, uart, 0, uart->name);
+ ctlr->ie = 0;
+ }
+
+ iunlock(ctlr);
+}
+
+static void
+n900uartkick(Uart *uart)
+{
+ Ctlr *ctlr;
+ int i;
+
+ ctlr = uart->regs;
+ if(uart->blocked)
+ return;
+
+ for(i = 0; i < 128; i++) {
+ if(csr32r(ctlr, Rlsr) & LSRtxempty) {
+ if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
+ break;
+
+ csr32w(ctlr, Rthr, *uart->op++);
+ }
+ }
+}
+
+static int
+n900uartgetc(Uart *uart)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ while(!(csr32r(ctlr, Rlsr) & LSRrxempty))
+ ;
+
+ return csr32r(ctlr, Rrhr);
+}
+
+static void
+n900uartputc(Uart *uart, int c)
+{
+ Ctlr *ctlr;
+
+ ctlr = uart->regs;
+ while(!(csr32r(ctlr, Rlsr) & LSRtxempty))
+ ;
+
+ csr32w(ctlr, Rthr, c);
+}
+
+static void n900uartnop(Uart *, int) {}
+static int n900uartnope(Uart *, int) { return -1; }
+
+PhysUart n900physuart = {
+ .name = "n900",
+
+ .pnp = n900uartpnp,
+ .enable = n900uartenable,
+ .disable = n900uartdisable,
+ .kick = n900uartkick,
+ .status = n900uartstatus,
+ .getc = n900uartgetc,
+ .putc = n900uartputc,
+
+ .dobreak = n900uartnop,
+ .baud = n900uartnope,
+ .bits = n900uartnope,
+ .stop = n900uartnope,
+ .parity = n900uartnope,
+ .modemctl = n900uartnop,
+ .rts = n900uartnop,
+ .dtr = n900uartnop,
+ .fifo = n900uartnop,
+ .power = n900uartnop,
+};
+
+void
+uartinit(void)
+{
+ consuart = &n900uart[2];
+ consuart->console = 1;
+ uartputs(kmesg.buf, kmesg.n);
+}
--- a/timer.c
+++ /dev/null
@@ -1,172 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-enum {
- Rrev = 0x00,
- Rsyscfg = 0x10,
- Cidle = 1<<0,
- Creset = 1<<1,
- Rsysstat = 0x14,
- Sreset = 1<<0,
- Risr = 0x18,
- Rier = 0x1c,
- Imatch = 1<<0,
- Ioverflow = 1<<1,
- Icapture = 1<<2,
- Rclr = 0x24,
- CLst = 1<<0,
- CLar = 1<<1,
- CLtgovf = 1<<10,
- CLtgmatch = 1<<11,
- Rcrr = 0x28,
- Rldr = 0x2c,
-};
-
-typedef union Counter Counter;
-typedef struct Ctlr Ctlr;
-
-union Counter {
- uvlong cnt;
- struct {
- ulong cntlo;
- ulong cnthi;
- };
-};
-
-struct Ctlr {
- Lock;
- Counter;
-
- u32int *io;
-};
-
-static Ctlr timers[] = {
- { .io = (u32int*) PHYSTIMER1 }, /* for cycles */
- { .io = (u32int*) PHYSTIMER2 }, /* for interrupts */
-};
-
-#define csr32r(c, r) ((c)->io[(r)/4])
-#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
-
-static void
-timerreset(Ctlr *ctlr)
-{
- int i;
- int cfg;
-
- cfg = csr32r(ctlr, Rsyscfg);
- cfg |= Creset;
- cfg &= ~Cidle;
-
- ilock(ctlr);
- csr32w(ctlr, Rsyscfg, cfg);
- for(i = 40000; i > 0; i++) {
- if(csr32r(ctlr, Rsysstat) & Sreset)
- break;
- }
-
- if(i == 0)
- panic("clock reset failed");
-
- iunlock(ctlr);
-}
-
-static void
-timerstartcycles(Ctlr *ctlr)
-{
- timerreset(ctlr);
-
- /* configure this timer for measuring cycles */
- ilock(ctlr);
- csr32w(ctlr, Rldr, 0);
- csr32w(ctlr, Rclr, CLst | CLar);
- iunlock(ctlr);
-}
-
-static void
-timerstartintr(Ctlr *ctlr, ulong t)
-{
- timerreset(ctlr);
-
- /* configure this timer for periodic interrupts */
- ilock(ctlr);
- csr32w(ctlr, Rier, Ioverflow);
- csr32w(ctlr, Rldr, -t);
- csr32w(ctlr, Rcrr, -t);
- csr32w(ctlr, Rclr, CLst | CLar);
- iunlock(ctlr);
-}
-
-static void
-timerinterrupt(Ureg *u, void *arg)
-{
- Ctlr *ctlr = arg;
- csr32w(ctlr, Risr, Ioverflow);
-
- timerintr(u, 0);
-}
-
-void
-timerinit(void)
-{
- intrenable(IRQTIMER2, timerinterrupt, &timers[1], BUSUNKNOWN, "timer");
-
- timerstartcycles(&timers[0]);
- timerstartintr(&timers[1], 32);
-}
-
-uvlong
-fastticks(uvlong *hz)
-{
- Counter c;
- Ctlr *ctlr;
-
- /* FIXME: this has poor precision, but qemu has no cycle counter */
- ctlr = &timers[0];
- if(hz)
- *hz = 32*1024;
-
- ilock(ctlr);
- c.cnt = ctlr->cnt;
- c.cntlo = csr32r(ctlr, Rcrr);
- if(c.cnt < ctlr->cnt)
- c.cnthi++;
-
- ctlr->cnt = c.cnt;
- iunlock(ctlr);
-
- return ctlr->cnt;
-}
-
-ulong
-µs(void)
-{
- return fastticks2us(fastticks(nil));
-}
-
-void
-microdelay(int n)
-{
- ulong now;
-
- now = µs();
- while(µs() - now < n)
- ;
-}
-
-void
-delay(int n)
-{
- while(--n >= 0)
- microdelay(1000);
-}
-
-void
-timerset(Tval)
-{
- /* FIXME: ? */
-}
--- a/trap.c
+++ /dev/null
@@ -1,577 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-#include "../port/systab.h"
-
-#include "tos.h"
-#include "ureg.h"
-
-void
-callwithureg(void (*f) (Ureg *))
-{
- Ureg u;
-
- u.pc = getcallerpc(&f);
- u.sp = (uintptr) &f - 4;
- f(&u);
-}
-
-void
-dumpstackureg(Ureg *ureg)
-{
- uintptr l, v, i, estack;
- int x;
-
- x = 0;
- x += iprint("ktrace /arm/9n900 %#.8lux %#.8lux %#.8lux <<EOF\n",
- ureg->pc, ureg->sp, ureg->r14);
-
- i = 0;
- if(up)
- estack = (uintptr)up;
- else
- estack = (uintptr)m+MACHSZ;
-
- x += iprint("estackx %p\n", estack);
- for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)) {
- v = *(uintptr*)l;
- if((KTZERO < v && v < (uintptr)etext) || estack-l < 32) {
- x += iprint("%.8p=%.8p ", l, v);
- i++;
- }
-
- if(i == 4) {
- i = 0;
- x += iprint("\n");
- }
- }
-
- if(i)
- iprint("\n");
- iprint("EOF\n");
-}
-
-void
-dumpstack(void)
-{
- callwithureg(dumpstackureg);
-}
-
-void
-dumpureg(Ureg *ureg)
-{
- if(up)
- iprint("cpu%d: registers for %s %lud\n", m->machno, up->text, up->pid);
- else
- iprint("cpu%d: registers for kernel\n", m->machno);
-
- iprint("r0 %#.8lux\tr1 %#.8lux\tr2 %#.8lux\tr3 %#.8lux\n", ureg->r0, ureg->r1, ureg->r2, ureg->r3);
- iprint("r4 %#.8lux\tr5 %#.8lux\tr6 %#.8lux\tr7 %#.8lux\n", ureg->r4, ureg->r5, ureg->r6, ureg->r7);
- iprint("r8 %#.8lux\tr9 %#.8lux\tr10 %#.8lux\tr11 %#.8lux\n", ureg->r8, ureg->r9, ureg->r10, ureg->r11);
- iprint("r12 %#.8lux\tr13 %#.8lux\tr14 %#.8lux\tr15 %#.8lux\n", ureg->r12, ureg->r13, ureg->r14, ureg->pc);
-}
-
-
-uintptr
-userpc(void)
-{
- return ((Ureg*)up->dbgreg)->pc;
-}
-
-uintptr
-dbgpc(Proc *)
-{
- if(up->dbgreg)
- return userpc();
-
- return 0;
-}
-
-void
-procsetup(Proc *p)
-{
- p->fpstate = FPinit;
- fpoff();
-}
-
-void
-procsave(Proc *p)
-{
- if(p->fpstate == FPactive) {
- if(p->state == Moribund)
- fpclear();
- else
- fpsave(p->fpsave);
- p->fpstate = FPinactive;
- }
-}
-
-void
-procrestore(Proc *)
-{
-}
-
-void
-procfork(Proc *p)
-{
- ulong s;
-
- s = splhi();
- switch(up->fpstate & ~FPillegal) {
- case FPactive:
- fpsave(up->fpsave);
- up->fpstate = FPinactive;
- case FPinactive:
- memmove(p->fpsave, up->fpsave, sizeof(FPsave));
- p->fpstate = FPinactive;
- }
-
- splx(s);
-}
-
-void
-kprocchild(Proc *p, void (*entry)(void))
-{
- p->sched.pc = (uintptr) entry;
- p->sched.sp = (uintptr) p;
-}
-
-void
-forkchild(Proc *p, Ureg *ureg)
-{
- Ureg *cureg;
-
- p->sched.sp = (uintptr) p - sizeof(Ureg);
- p->sched.pc = (uintptr) forkret;
-
- cureg = (Ureg*) p->sched.sp;
- memmove(cureg, ureg, sizeof(Ureg));
- cureg->r0 = 0;
-}
-
-uintptr
-execregs(uintptr entry, ulong ssize, ulong nargs)
-{
- ulong *sp;
- Ureg *ureg;
-
- sp = (ulong*)(USTKTOP - ssize); *--sp = nargs;
- ureg = up->dbgreg;
- ureg->sp = (uintptr) sp;
- ureg->pc = entry;
- ureg->r14 = 0;
-
- return USTKTOP-sizeof(Tos);
-}
-
-void
-setkernur(Ureg *ureg, Proc *p)
-{
- ureg->pc = p->sched.pc;
- ureg->sp = p->sched.sp+4;
- ureg->r14 = (uintptr) sched;
-}
-
-void
-setregisters(Ureg *ureg, char *pureg, char *uva, int n)
-{
- uvlong v;
-
- v = ureg->psr;
- memmove(pureg, uva, n);
- ureg->psr &= ~(PsrMask|PsrDfiq|PsrDirq);
- ureg->psr |= v & (PsrMask|PsrDfiq|PsrDirq);
-}
-
-void
-evenaddr(uintptr addr)
-{
- if(addr & 3) {
- postnote(up, 1, "sys: odd address", NDebug);
- error(Ebadarg);
- }
-}
-
-int
-notify(Ureg *ureg)
-{
- ulong s, sp;
- char *msg;
-
- if(up->procctl)
- procctl();
- if(up->nnote == 0)
- return 0;
-
- if(up->fpstate == FPactive) {
- fpsave(up->fpsave);
- up->fpstate = FPinactive;
- }
- up->fpstate |= FPillegal;
-
- s = spllo();
- qlock(&up->debug);
- msg = popnote(ureg);
- if(msg == nil) {
- qunlock(&up->debug);
- splhi();
- return 0;
- }
-
- sp = ureg->sp;
- sp -= 256;
- sp -= sizeof(Ureg);
-
- if(!okaddr((uintptr)up->notify, 1, 0)
- || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)
- || ((uintptr) up->notify & 3) != 0
- || (sp & 3) != 0) {
- qunlock(&up->debug);
- pprint("suicide: bad address in notify\n");
- pexit("Suicide", 0);
- }
-
- memmove((Ureg*)sp, ureg, sizeof(Ureg));
- *(Ureg**)(sp-BY2WD) = up->ureg;
- up->ureg = (void*)sp;
- sp -= BY2WD+ERRMAX;
- memmove((char*)sp, msg, ERRMAX);
- sp -= 3*BY2WD;
- *(uintptr*)(sp+2*BY2WD) = sp+3*BY2WD;
- *(uintptr*)(sp+1*BY2WD) = (uintptr)up->ureg;
- ureg->r0 = (uintptr) up->ureg;
- ureg->sp = sp;
- ureg->pc = (uintptr) up->notify;
- ureg->r14 = 0;
-
- qunlock(&up->debug);
- splx(s);
- return 1;
-}
-
-void
-noted(Ureg *ureg, ulong arg0)
-{
- Ureg *nureg;
- ulong oureg, sp;
-
- qlock(&up->debug);
- if(arg0 != NRSTR && !up->notified) {
- qunlock(&up->debug);
- iprint("called to noted when not notified\n");
- pexit("Suicide", 0);
- }
-
- up->notified = 0;
- up->fpstate &= ~FPillegal;
- nureg = up->ureg;
- oureg = (ulong) nureg;
- if(!okaddr(oureg - BY2WD, BY2WD + sizeof(Ureg), 0) || (oureg & 3) != 0) {
- qunlock(&up->debug);
- pprint("bad ureg in noted or call to noted when not notifed\n");
- pexit("Suicide", 0);
- }
-
- nureg->psr &= PsrMask|PsrDfiq|PsrDirq;
- nureg->psr |= (ureg->psr & ~(PsrMask|PsrDfiq|PsrDirq));
-
- memmove(ureg, nureg, sizeof(Ureg));
- switch(arg0) {
- case NCONT:
- case NRSTR:
- if(!okaddr(nureg->pc, BY2WD, 0) || (nureg->pc & 3) != 0
- || !okaddr(nureg->sp, BY2WD, 0) || (nureg->sp & 3) != 0) {
- qunlock(&up->debug);
- pprint("suicide: trap in noted\n");
- pexit("Suicide", 0);
- }
-
- up->ureg = (Ureg *) (*(ulong*) (oureg - BY2WD));
- qunlock(&up->debug);
- break;
-
- case NSAVE:
- if(!okaddr(nureg->pc, BY2WD, 0) || (nureg->pc & 3) != 0
- || !okaddr(nureg->sp, BY2WD, 0) || (nureg->sp & 3) != 0) {
- qunlock(&up->debug);
- pprint("suicide: trap in noted\n");
- pexit("Suicide", 0);
- }
-
- qunlock(&up->debug);
- sp = oureg - 4 * BY2WD - ERRMAX;
- splhi();
- ureg->sp = sp;
- ureg->r0 = (uintptr) oureg;
- ((ulong*) sp)[1] = oureg;
- ((ulong*) sp)[0] = 0;
- break;
-
- default:
- up->lastnote->flag = NDebug;
- /* wet floor */
-
- case NDFLT:
- qunlock(&up->debug);
- if(up->lastnote->flag == NDebug)
- pprint("suicide: %s\n", up->lastnote->msg);
-
- pexit(up->lastnote->msg, up->lastnote->flag != NDebug);
- break;
- }
-}
-
-void
-trapinit(void)
-{
- extern ulong vectors[];
-
- /* install stack pointer for other exception modes */
- setR13(PsrMfiq, m->save);
- setR13(PsrMirq, m->save);
- setR13(PsrMiabt, m->save);
- setR13(PsrMund, m->save);
- setR13(PsrMsys, m->save);
-
- /* install vectors and vtable to MACHVEC because vectors must be
- * aligned on a 128 byte boundary */
- memmove((ulong*)MACHVEC(m->machno), vectors, 64 * 4);
-
- /* set vectors base address */
- setvectors(MACHVEC(m->machno));
-}
-
-static void
-trapfpu(void)
-{
- int s;
-
- if((up->fpstate & FPillegal) != 0) {
- postnote(up, 1, "sys: floating point in note handler", NDebug);
- return;
- }
-
- switch(up->fpstate) {
- case FPinit:
- s = splhi();
- fpinit(); up->fpstate = FPactive;
- splx(s);
- break;
-
- case FPinactive:
- s = splhi();
- fprestore(up->fpsave); up->fpstate = FPactive;
- splx(s);
- break;
-
- case FPactive:
- postnote(up, 1, "sys: floating point error", NDebug);
- break;
- }
-}
-
-static void
-traparm(Ureg *ureg, ulong fsr, uintptr far)
-{
- int user;
- int read;
- int syscall;
-
- static char buf[ERRMAX];
-
- read = (fsr & (1<<11)) == 0;
- user = userureg(ureg);
- if(!user) {
- if(far >= USTKTOP)
- panic("kernel fault: bad address pc=%#.8lux far=%#.8lux fsr=%#.8lux",
- ureg->pc, far, fsr);
- if(up == nil)
- panic("kernel fault: no user process pc=%#.8lux far=%#.8lux fsr=%#.8lux",
- ureg->pc, far, fsr);
- }
-
- if(up == nil) {
- panic("user fault: up=nil pc=%#.8lux far=%#.8lux fsr=%#.8lux",
- ureg->pc, far, fsr);
- }
-
- syscall = up->insyscall; up->insyscall = 1;
- switch(fsr & 0x1f) {
- case 0x03: /* l1 access flag fault */
- case 0x05: /* l1 translation fault */
- case 0x06: /* l2 access flag fault */
- case 0x07: /* l2 translation fault */
- case 0x09: /* l1 domain fault */
- case 0x0b: /* l2 domain fault */
- case 0x0d: /* l1 permission fault */
- case 0x0f: /* l2 permission fault */
- if(fault(far, ureg->pc, read) == 0)
- break;
-
- default:
- if(!user)
- panic("kernel fault: pc=%#.8lux far=%#.8lux fsr=%#.8lux",
- ureg->pc, far, fsr);
-
- dumpureg(ureg);
- dumpstackureg(ureg);
- snprint(buf, sizeof(buf), "sys: trap: fault %s far=%#.8lux fsr=%#.8lux",
- read ? "read" : "write", far, fsr);
- postnote(up, 1, buf, NDebug);
- }
-
- up->insyscall = syscall;
-}
-
-void
-trap(Ureg *ureg)
-{
- int user;
- u32int op, cp;
-
- user = kenter(ureg);
- switch(ureg->type) {
- case PsrMfiq:
- case PsrMirq:
- ureg->pc -= 4;
- intr(ureg);
- break;
-
- case PsrMiabt:
- ureg->pc -= 4;
- traparm(ureg, getifsr(), getifar());
- break;
-
- case PsrMdabt:
- ureg->pc -= 8;
- traparm(ureg, getdfsr(), getdfar());
- break;
-
- case PsrMund:
- ureg->pc -= 4;
- if(user) {
- spllo();
- if(okaddr(ureg->pc, 4, 0)) {
- op = *(u32int*)ureg->pc;
- if((op & 0x0f000000) == 0x0e000000 || (op & 0x0e000000) == 0x0c000000) {
- cp = op >> 8 & 15;
- if(cp == 10 || cp == 11) {
- trapfpu();
- break;
- }
- }
- }
-
- postnote(up, 1, "sys: trap: invalid opcode", NDebug);
- break;
- }
-
- panic("invalid opcode at pc=%#.8lux lr=%#.8lux", ureg->pc, ureg->r14);
- break;
-
- default:
- panic("unknown trap at pc=%#.8lux lr=%#.8lux", ureg->pc, ureg->r14);
- break;
- }
-
- splhi();
- if(user) {
- if(up->procctl || up->nnote)
- notify(ureg);
-
- kexit(ureg);
- }
-}
-
-void
-syscall(Ureg *ureg)
-{
- char *e;
- uintptr sp;
- long ret;
- int i, s;
- ulong scallnr;
- vlong startns, stopns;
-
- if(!kenter(ureg))
- panic("syscall: from kernel: pc=%#.8lux", ureg->pc);
-
- m->syscall++;
- up->insyscall = 1;
- up->pc = ureg->pc;
-
- scallnr = up->scallnr = ureg->r0;
- sp = ureg->sp;
-
- spllo();
-
- up->nerrlab = 0;
- ret = -1;
- if(!waserror()) {
- if(scallnr >= nsyscall) {
- pprint("bad sys call number %lux pc %#lux", scallnr, ureg->pc);
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
-
- if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD)) {
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
- evenaddr(sp);
- }
-
- up->s = *((Sargs*)(sp + BY2WD));
- up->psstate = sysctab[scallnr];
- if (up->procctl == Proc_tracesyscall) {
- syscallfmt(scallnr, ureg->pc, (va_list)up->s.args);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- startns = todget(nil);
- }
-
- ret = systab[scallnr]((va_list)up->s.args);
- poperror();
- } else {
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
- }
-
- if(up->nerrlab) {
- print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
- for (i = 0; i < NERR; i++)
- print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
-
- panic("error stack");
- }
-
- ureg->r0 = ret;
- if(up->procctl == Proc_tracesyscall) {
- stopns = todget(nil);
- sysretfmt(scallnr, (va_list)up->s.args, ret, startns, stopns);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- }
-
- up->insyscall = 0;
- up->psstate = 0;
- if(scallnr == NOTED)
- noted(ureg, *((ulong *)up->s.args));
-
- if(scallnr != RFORK && (up->procctl || up->nnote)) {
- splhi();
- notify(ureg);
- }
-
- if(up->delaysched)
- sched();
-
- kexit(ureg);
- splhi();
-}
--- a/uartn900.c
+++ /dev/null
@@ -1,268 +1,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-
-enum {
- Rdll = 0x00,
- Rrhr = 0x00,
- Rthr = 0x00,
- Rdlh = 0x04,
- Rier = 0x04,
- IErhr = 1 << 0,
- IEthr = 1 << 1,
- IEls = 1 << 2,
- IEms = 1 << 3,
- Riir = 0x08,
- Ipending = 1 << 0,
- Imodem = 0x00,
- Ithr = 0x01,
- Irhr = 0x02,
- Ils = 0x03,
- Irxt = 0x06,
- Ixoff = 0x08,
- Icts = 0x10,
- Imask = 0x1f,
- Rfcr = 0x08,
- FCRen = 1 << 0,
- Refr = 0x08,
- Rlcr = 0x0c,
- Rmcr = 0x10,
- Rxon1 = 0x10,
- Rlsr = 0x14,
- LSRrxempty = 1 << 0,
- LSRrxover = 1 << 1,
- LSRrxparity = 1 << 2,
- LSRrxframe = 1 << 3,
- LSRrxbreak = 1 << 4,
- LSRtxempty = 1 << 5,
- LSRtxshift = 1 << 6,
- LSRrxstat = 1 << 7,
- Rxon2 = 0x14,
- Rmsr = 0x18,
- Rtcr = 0x18,
- Rxoff1 = 0x18,
- Rspr = 0x1c,
- Rtlr = 0x1c,
- Rxoff2 = 0x1c,
- Rmdr1 = 0x20,
- Rmdr2 = 0x24,
- Rsysc = 0x54,
- SCreset = 1 << 1,
- Rsyss = 0x58,
- SSreset = 1 << 0,
-};
-
-#define csr32r(c, r) ((c)->io[(r)/4])
-#define csr32w(c, r, w) ((c)->io[(r)/4] = (w))
-
-typedef struct Ctlr Ctlr;
-struct Ctlr {
- Lock;
-
- u32int *io;
- ulong irq;
-
- int ie;
-};
-
-extern PhysUart n900physuart;
-
-static Ctlr ctlr[] = {
- { .io = (u32int*) PHYSUART1, .irq = IRQUART1, },
- { .io = (u32int*) PHYSUART2, .irq = IRQUART2, },
- { .io = (u32int*) PHYSUART3, .irq = IRQUART3, },
-};
-
-static Uart n900uart[] = {
- {
- .regs = &ctlr[0],
- .name = "uart1",
- .freq = 48000000,
- .phys = &n900physuart,
- .next = &n900uart[1],
- },
- {
- .regs = &ctlr[1],
- .name = "uart2",
- .freq = 48000000,
- .phys = &n900physuart,
- .next = &n900uart[2],
- },
- {
- .regs = &ctlr[2],
- .name = "uart3",
- .freq = 48000000,
- .phys = &n900physuart,
- .next = nil,
- },
-};
-
-static Uart *
-n900uartpnp(void)
-{
- return n900uart;
-}
-
-static long
-n900uartstatus(Uart *, void *, long, long)
-{
- return 0;
-}
-
-static void
-n900uartintr(Ureg *, void *arg)
-{
- Uart *uart;
- Ctlr *ctlr;
- int lsr;
- char c;
-
- uart = arg;
- ctlr = uart->regs;
-
- ilock(ctlr);
- switch((csr32r(ctlr, Riir) >> 1) & Imask) {
- case Ithr:
- uartkick(uart);
- break;
-
- case Irhr:
- while((lsr = csr32r(ctlr, Rlsr)) & LSRrxempty) {
- c = csr32r(ctlr, Rrhr);
-
- if(lsr & LSRrxover) { uart->oerr++; break; }
- if(lsr & LSRrxparity) { uart->perr++; break; }
- if(lsr & LSRrxframe) { uart->ferr++; break; }
-
- uartrecv(uart, c);
- }
-
- break;
- }
-
- iunlock(ctlr);
-}
-
-static void
-n900uartenable(Uart *uart, int ie)
-{
- Ctlr *ctlr;
-
- ctlr = uart->regs;
- ilock(ctlr);
-
- csr32w(ctlr, Rsysc, SCreset);
- while(!(csr32r(ctlr, Rsyss) & SSreset))
- ;
-
- csr32w(ctlr, Rfcr, FCRen);
- if(ie) {
- if(!ctlr->ie) {
- intrenable(ctlr->irq, n900uartintr, uart, 0, uart->name);
- ctlr->ie = 1;
- }
-
- csr32w(ctlr, Rier, IErhr);
- }
-
- iunlock(ctlr);
-}
-
-static void
-n900uartdisable(Uart *uart)
-{
- Ctlr *ctlr;
-
- ctlr = uart->regs;
-
- ilock(ctlr);
- csr32w(ctlr, Rier, 0);
- if(ctlr->ie) {
- intrdisable(ctlr->irq, n900uartintr, uart, 0, uart->name);
- ctlr->ie = 0;
- }
-
- iunlock(ctlr);
-}
-
-static void
-n900uartkick(Uart *uart)
-{
- Ctlr *ctlr;
- int i;
-
- ctlr = uart->regs;
- if(uart->blocked)
- return;
-
- for(i = 0; i < 128; i++) {
- if(csr32r(ctlr, Rlsr) & LSRtxempty) {
- if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
- break;
-
- csr32w(ctlr, Rthr, *uart->op++);
- }
- }
-}
-
-static int
-n900uartgetc(Uart *uart)
-{
- Ctlr *ctlr;
-
- ctlr = uart->regs;
- while(!(csr32r(ctlr, Rlsr) & LSRrxempty))
- ;
-
- return csr32r(ctlr, Rrhr);
-}
-
-static void
-n900uartputc(Uart *uart, int c)
-{
- Ctlr *ctlr;
-
- ctlr = uart->regs;
- while(!(csr32r(ctlr, Rlsr) & LSRtxempty))
- ;
-
- csr32w(ctlr, Rthr, c);
-}
-
-static void n900uartnop(Uart *, int) {}
-static int n900uartnope(Uart *, int) { return -1; }
-
-PhysUart n900physuart = {
- .name = "n900",
-
- .pnp = n900uartpnp,
- .enable = n900uartenable,
- .disable = n900uartdisable,
- .kick = n900uartkick,
- .status = n900uartstatus,
- .getc = n900uartgetc,
- .putc = n900uartputc,
-
- .dobreak = n900uartnop,
- .baud = n900uartnope,
- .bits = n900uartnope,
- .stop = n900uartnope,
- .parity = n900uartnope,
- .modemctl = n900uartnop,
- .rts = n900uartnop,
- .dtr = n900uartnop,
- .fifo = n900uartnop,
- .power = n900uartnop,
-};
-
-void
-uartinit(void)
-{
- consuart = &n900uart[2];
- consuart->console = 1;
- uartputs(kmesg.buf, kmesg.n);
-}