]> git.lizzy.rs Git - plan9front.git/commitdiff
add cycv kernel
authoraiju <devnull@localhost>
Wed, 8 Jan 2020 02:35:01 +0000 (02:35 +0000)
committeraiju <devnull@localhost>
Wed, 8 Jan 2020 02:35:01 +0000 (02:35 +0000)
18 files changed:
sys/src/9/cycv/cycv [new file with mode: 0644]
sys/src/9/cycv/dat.h [new file with mode: 0644]
sys/src/9/cycv/devarch.c [new file with mode: 0644]
sys/src/9/cycv/fns.h [new file with mode: 0644]
sys/src/9/cycv/init9.s [new file with mode: 0644]
sys/src/9/cycv/intr.c [new file with mode: 0644]
sys/src/9/cycv/io.h [new file with mode: 0644]
sys/src/9/cycv/l.s [new file with mode: 0644]
sys/src/9/cycv/ltrap.s [new file with mode: 0644]
sys/src/9/cycv/main.c [new file with mode: 0644]
sys/src/9/cycv/mem.h [new file with mode: 0644]
sys/src/9/cycv/mkfile [new file with mode: 0644]
sys/src/9/cycv/mmu.c [new file with mode: 0644]
sys/src/9/cycv/timer.c [new file with mode: 0644]
sys/src/9/cycv/trap.c [new file with mode: 0644]
sys/src/9/cycv/uartcycv.c [new file with mode: 0644]
sys/src/9/mkfile
sys/src/9/port/portmkfile

diff --git a/sys/src/9/cycv/cycv b/sys/src/9/cycv/cycv
new file mode 100644 (file)
index 0000000..cc2e0ae
--- /dev/null
@@ -0,0 +1,55 @@
+dev
+       root
+       cons
+       swap
+#      arch
+       uart
+       mnt
+       srv
+       shr
+       proc
+       env
+       pipe
+       dup
+       ether netif
+       ip              arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
+       ssl
+       tls
+#      cap
+#      kprof
+       sd
+#      draw screen
+#      mouse
+#      usb
+       segment
+       
+link
+       ethermedium
+       loopbackmedium
+       netdevmedium
+#      usbehci usbehcizynq
+
+misc
+       uartcycv
+#      sdmmc           emmc
+       sdram
+
+ip
+       tcp
+       udp
+       rudp
+       ipifc
+       icmp
+       icmp6
+       gre
+       ipmux
+       esp
+
+port
+       int cpuserver = 0;
+
+bootdir
+       /$objtype/bin/paqfs
+       /$objtype/bin/auth/factotum
+       boot
+       bootfs.paq
diff --git a/sys/src/9/cycv/dat.h b/sys/src/9/cycv/dat.h
new file mode 100644 (file)
index 0000000..7195e7a
--- /dev/null
@@ -0,0 +1,202 @@
+typedef struct Conf    Conf;
+typedef struct Confmem Confmem;
+typedef struct FPsave  FPsave;
+typedef struct PFPU    PFPU;
+typedef struct L1      L1;
+typedef struct Label   Label;
+typedef struct Lock    Lock;
+typedef struct KMap    KMap;
+typedef struct MMMU    MMMU;
+typedef struct Mach    Mach;
+typedef struct Page    Page;
+typedef struct Proc    Proc;
+typedef struct PMMU    PMMU;
+typedef struct Ureg    Ureg;
+typedef struct ISAConf ISAConf;
+typedef uvlong         Tval;
+
+#pragma incomplete Ureg
+
+#define MAXSYSARG      5       /* for mount(fd, mpt, flag, arg, srv) */
+
+#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 FPsave
+{
+       ulong   exc, scr;
+       uchar   regs[256];
+};
+
+struct PFPU
+{
+       int     fpstate;
+       FPsave  fpsave[1];
+};
+
+enum
+{
+       FPinit,
+       FPactive,
+       FPinactive,
+       FPillegal = 0x100
+};
+
+struct Confmem
+{
+       uintptr base;
+       usize   npage;
+       uintptr kbase;
+       uintptr klimit;
+};
+
+struct Conf
+{
+       ulong   nmach;          /* processors */
+       ulong   nproc;          /* processes */
+       Confmem mem[2];         /* physical memory */
+       ulong   npage;          /* total physical pages of memory */
+       usize   upages;         /* user page pool */
+       ulong   copymode;       /* 0 is copy on write, 1 is copy on reference */
+       ulong   ialloc;         /* max interrupt time allocation in bytes */
+       ulong   pipeqsize;      /* size in bytes of pipe queues */
+       ulong   nimage;         /* number of page cache image headers */
+       ulong   nswap;          /* number of swap pages */
+       int     nswppo;         /* max # of pageouts per segment pass */
+       int     monitor;
+};
+
+/*
+ *  MMU stuff in proc
+ */
+#define NCOLOR 1
+
+struct PMMU
+{
+       L1 *l1;
+       Page *mmuused, *mmufree;
+       
+       int nkmap;
+       Page *kmaptable;
+};
+
+#include "../port/portdat.h"
+
+struct L1
+{
+       Ref;
+       uintptr pa;
+       ulong *va;
+       L1 *next;
+};
+
+struct MMMU
+{
+       L1 l1;
+       L1 *l1free;
+       int nfree;
+       uchar asid;
+};
+
+struct Mach
+{
+       /* known to assembly */
+       int     machno;                 /* physical id of processor */
+       uintptr splpc;                  /* pc of last caller to splhi */
+       Proc*   proc;                   /* current process */
+       ulong   excregs[3];
+       ulong   cycleshi;
+       /* end of known to assembly */
+
+       int     flushmmu;               /* flush current proc mmu state */
+
+       ulong   ticks;                  /* of the clock since boot time */
+       Label   sched;                  /* scheduler wakeup */
+       Lock    alarmlock;              /* access to alarm list */
+       void*   alarm;                  /* alarms bound to this clock */
+       int     inclockintr;
+
+       Proc*   readied;                /* for runproc */
+       ulong   schedticks;             /* next forced context switch */
+
+       ulong   delayloop;
+
+       /* stats */
+       int     tlbfault;
+       int     tlbpurge;
+       int     pfault;
+       int     cs;
+       int     syscall;
+       int     load;
+       int     intr;
+       int     lastintr;
+       int     ilockdepth;
+       Perf    perf;                   /* performance counters */
+
+
+       int     cpumhz;
+       uvlong  cpuhz;                  /* speed of cpu */
+       uvlong  cyclefreq;              /* Frequency of user readable cycle counter */
+       
+       MMMU;
+
+       int     stack[1];
+};
+
+#define NISAOPT                8
+struct ISAConf
+{
+       char    *type;
+       ulong   port;
+       int     irq;
+       int     nopt;
+       char    *opt[NISAOPT];
+};
+#define BUSUNKNOWN -1
+
+struct
+{
+       char    machs[MAXMACH];         /* active CPUs */
+       int     exiting;                /* shutdown */
+}active;
+
+extern register Mach* m;                       /* R10 */
+extern register Proc* up;                      /* R9 */
+
+extern int normalprint;
+
+void nope(void);
+#define NOPE nope();
+
+/*
+ *  hardware info about a device
+ */
+typedef struct {
+       ulong   port;
+       int     size;
+} Devport;
+
+struct DevConf
+{
+       ulong   intnum;                 /* interrupt number */
+       char    *type;                  /* card type, malloced */
+       int     nports;                 /* Number of ports */
+       Devport *ports;                 /* The ports themselves */
+};
+
+#define mpcore ((ulong*)MPCORE_BASE)
diff --git a/sys/src/9/cycv/devarch.c b/sys/src/9/cycv/devarch.c
new file mode 100644 (file)
index 0000000..00a368f
--- /dev/null
@@ -0,0 +1,389 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+enum {
+       Qdir = 0,
+       Qtemp,
+       Qpl,
+       Qfbctl,
+       Qbase,
+
+       Qmax = 16,
+};
+
+static Dirtab archdir[Qmax] = {
+       ".",            { Qdir, 0, QTDIR },     0,      0555,
+       "temp",         { Qtemp, 0},            0,      0440,
+       "pl",           { Qpl, 0 },             0,      0660,
+       "fbctl",        { Qfbctl, 0 },          0,      0660,
+};
+static int narchdir = Qbase;
+
+static int temp = -128;
+static ulong *devc;
+static int dmadone;
+enum { PLBUFSIZ = 8192 };
+static uchar *plbuf;
+static Rendez plinitr, pldoner, pldmar;
+static QLock plrlock, plwlock;
+static Ref plwopen;
+static Physseg *axi;
+
+enum {
+       DEVCTRL = 0,
+       DEVISTS = 0xc/4,
+       DEVMASK,
+       DEVSTS,
+       DMASRC = 0x18/4,
+       DMADST,
+       DMASRCL,
+       DMADSTL,
+       XADCCFG = 0x100/4,
+       XADCSTS,
+       XADCMASK,
+       XADCMSTS,
+       XADCCMD,
+       XADCREAD,
+       XADCMCTL,
+       
+       FPGA0_CLK_CTRL = 0x170/4,
+};
+
+enum {
+       PROG = 1<<30,
+       DONE = 1<<2,
+       INITPE = 1<<1,
+       INIT = 1<<4,
+       DMADONE = 1<<13,
+};
+
+static void
+scram(void)
+{
+       splhi();
+       slcr[0x100/4] |= 1<<4;
+       slcr[0x104/4] |= 1<<4;
+       slcr[0x108/4] |= 1<<4;
+       slcr[DEVCTRL] &= ~PROG;
+       slcr[0x244/4] = 1<<4|1<<5;
+}
+
+static void
+xadcirq(Ureg *, void *)
+{
+       int v;
+       static int al, notfirst;
+       
+       while((devc[XADCMSTS] & 1<<8) == 0){
+               v = ((u16int)devc[XADCREAD]) >> 4;
+               if(v == 0){
+                       if(notfirst)
+                               print("temperature sensor reads 0, shouldn't happen\n");
+                       break;
+               }
+               notfirst = 1;
+               temp = v * 5040 / 4096 - 2732;
+               if(temp >= 800){
+                       if(al == 0)
+                               print("temperature exceeds 80 deg C\n");
+                       al = 1;
+               }
+               if(temp <= 750)
+                       al = 0;
+               if(temp >= 900){
+                       print("chip temperature exceeds 90 deg C, shutting down");
+                       scram();
+               }
+       }
+       devc[XADCSTS] = -1;
+}
+
+static void
+xadctimer(void)
+{
+       devc[XADCCMD] = 1<<26 | 0<<16;
+}
+
+static void
+xadcinit(void)
+{
+       int i;
+       int x;
+
+       devc = vmap(DEVC_BASE, 0x11C);
+       devc[XADCMCTL] |= 1<<4;
+       devc[XADCMCTL] &= ~(1<<4);
+       devc[XADCCMD] = 0x08030000;
+       for(i = 0; i < 15; i++)
+               devc[XADCCMD] = 0;
+       while((devc[XADCMSTS] & 1<<10) == 0)
+               ;
+       while((devc[XADCMSTS] & 1<<8) == 0){
+               x = devc[XADCREAD];
+               USED(x);
+       }
+       devc[XADCCFG] = 0x80001114;
+       devc[XADCMASK] = ~(1<<8);
+       devc[XADCSTS] = -1;
+       intrenable(XADCIRQ, xadcirq, nil, LEVEL, "xadc");
+       addclock0link(xadctimer, XADCINTERVAL);
+}
+
+static int
+isplinit(void *)
+{
+       return devc[DEVSTS] & INIT;
+}
+
+static int
+ispldone(void *)
+{
+       return devc[DEVISTS] & DONE;
+}
+
+static int
+isdmadone(void *)
+{
+       return dmadone;
+}
+
+static void
+plirq(Ureg *, void *)
+{
+       ulong fl;
+       
+       fl = devc[DEVISTS];
+       if((fl & INITPE) != 0)
+               wakeup(&plinitr);
+       if((fl & DONE) != 0){
+               slcr[0x900/4] = 0xf;
+               slcr[0x240/4] = 0;
+               devc[DEVMASK] |= DONE;
+               axi->attr &= ~SG_FAULT;
+               wakeup(&pldoner);
+       }
+       if((fl & DMADONE) != 0){
+               dmadone++;
+               wakeup(&pldmar);
+       }
+       devc[DEVISTS] = fl;
+}
+
+static void
+plinit(void)
+{
+       Physseg seg;
+
+       memset(&seg, 0, sizeof seg);
+       seg.attr = SG_PHYSICAL | SG_DEVICE | SG_NOEXEC | SG_FAULT;
+       seg.name = "axi";
+       seg.pa = 0x40000000;
+       seg.size = 0x8000000;
+       axi = addphysseg(&seg);
+
+       devc[DEVCTRL] &= ~(PROG|1<<25);
+       devc[DEVCTRL] |= 3<<26|PROG;
+       devc[DEVISTS] = -1;
+       devc[DEVMASK] = ~(DONE|INITPE|DMADONE);
+       intrenable(DEVCIRQ, plirq, nil, LEVEL, "pl");
+       
+       slcr[FPGA0_CLK_CTRL] = 1<<20 | 10<<8;
+}
+
+static void
+plconf(void)
+{
+       axi->attr |= SG_FAULT;
+       procflushpseg(axi);
+       flushmmu();
+
+       slcr[0x240/4] = 0xf;
+       slcr[0x900/4] = 0xa;
+       devc[DEVISTS] = DONE|INITPE|DMADONE;
+       devc[DEVCTRL] |= PROG;
+       devc[DEVCTRL] &= ~PROG;
+       devc[DEVMASK] &= ~DONE;
+       devc[DEVCTRL] |= PROG;
+
+       while(waserror())
+               ;
+       sleep(&plinitr, isplinit, nil);
+       poperror();
+}
+
+static long
+plwrite(uintptr pa, long n)
+{
+       dmadone = 0;
+       coherence();
+       devc[DMASRC] = pa;
+       devc[DMADST] = -1;
+       devc[DMASRCL] = n>>2;
+       devc[DMADSTL] = 0;
+
+       while(waserror())
+               ;
+       sleep(&pldmar, isdmadone, nil);
+       poperror();
+
+       return n;
+}
+
+static long
+plcopy(uchar *d, long n)
+{
+       long ret;
+       ulong nn;
+       uintptr pa;
+       
+       if((n & 3) != 0 || n <= 0)
+               error(Eshort);
+
+       eqlock(&plwlock);
+       if(waserror()){
+               qunlock(&plwlock);
+               nexterror();
+       }
+
+       ret = n;
+       pa = PADDR(plbuf);
+       while(n > 0){
+               if(n > PLBUFSIZ)
+                       nn = PLBUFSIZ;
+               else
+                       nn = n;
+               memmove(plbuf, d, nn);
+               cleandse(plbuf, plbuf + nn);
+               clean2pa(pa, pa + nn);
+               n -= plwrite(pa, nn);
+       }
+
+       qunlock(&plwlock);
+       poperror();
+
+       return ret;
+}
+
+void
+archinit(void)
+{
+       slcr[2] = 0xDF0D;
+       xadcinit();
+       plinit();
+}
+
+static long
+archread(Chan *c, void *a, long n, vlong offset)
+{
+       char buf[64];
+
+       switch((ulong)c->qid.path){
+       case Qdir:
+               return devdirread(c, a, n, archdir, narchdir, devgen);
+       case Qtemp:
+               snprint(buf, sizeof(buf), "%d.%d\n", temp/10, temp%10);
+               return readstr(offset, a, n, buf);
+       case Qpl:
+               eqlock(&plrlock);
+               if(waserror()){
+                       qunlock(&plrlock);
+                       nexterror();
+               }
+               sleep(&pldoner, ispldone, nil);
+               qunlock(&plrlock);
+               poperror();
+               return 0;
+       case Qfbctl:
+               return fbctlread(c, a, n, offset);
+       default:
+               error(Egreg);
+               return -1;
+       }
+}
+
+static long
+archwrite(Chan *c, void *a, long n, vlong offset)
+{
+       switch((ulong)c->qid.path){
+       case Qpl:
+               return plcopy(a, n);
+       case Qfbctl:
+               return fbctlwrite(c, a, n, offset);
+       default:
+               error(Egreg);
+               return -1;
+       }
+}
+
+Walkqid*
+archwalk(Chan* c, Chan *nc, char** name, int nname)
+{
+       return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
+}
+
+static int
+archstat(Chan* c, uchar* dp, int n)
+{
+       return devstat(c, dp, n, archdir, narchdir, devgen);
+}
+
+static Chan*
+archopen(Chan* c, int omode)
+{
+       devopen(c, omode, archdir, narchdir, devgen);
+       if((ulong)c->qid.path == Qpl && (c->mode == OWRITE || c->mode == ORDWR)){
+               if(incref(&plwopen) != 1){
+                       c->flag &= ~COPEN;
+                       decref(&plwopen);
+                       error(Einuse);
+               }
+               plbuf = smalloc(PLBUFSIZ);
+               plconf();
+       }
+       return c;
+}
+
+static void
+archclose(Chan* c)
+{
+       if((c->flag & COPEN) != 0)
+       if((ulong)c->qid.path == Qpl && (c->mode == OWRITE || c->mode == ORDWR)){
+               free(plbuf);
+               plbuf = nil;
+               decref(&plwopen);
+       }
+}
+
+static Chan*
+archattach(char* spec)
+{
+       return devattach('P', spec);
+}
+
+Dev archdevtab = {
+       'P',
+       "arch",
+       
+       devreset,
+       devinit,
+       devshutdown,
+       archattach,
+       archwalk,
+       archstat,
+       archopen,
+       devcreate,
+       archclose,
+       archread,
+       devbread,
+       archwrite,
+       devbwrite,
+       devremove,
+       devwstat,
+};
+
diff --git a/sys/src/9/cycv/fns.h b/sys/src/9/cycv/fns.h
new file mode 100644 (file)
index 0000000..6606c4e
--- /dev/null
@@ -0,0 +1,78 @@
+#include "../port/portfns.h"
+
+int tas(void *);
+int cmpswap(long *, long, long);
+void evenaddr(uintptr);
+void* kaddr(uintptr);
+uintptr paddr(void *);
+uintptr cankaddr(uintptr);
+void procsave(Proc *);
+void procrestore(Proc *);
+void idlehands(void);
+void sendevent(void);
+void coherence(void);
+void procfork(Proc *);
+void procsetup(Proc *);
+KMap* kmap(Page *);
+void kunmap(KMap *);
+
+#define        waserror()      (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
+#define getpgcolor(a) 0
+#define kmapinval()
+#define KADDR(a) kaddr(a)
+#define PADDR(a) paddr((void*)(a))
+#define userureg(ur) (((ur)->psr & PsrMask) == PsrMusr)
+#define VA(k) ((void*)(k))
+#define PTR2UINT(p) ((uintptr)(p))
+
+void uartinit(void);
+void mmuinit(void);
+uintptr ttbget(void);
+void ttbput(uintptr);
+void cycles(uvlong *);
+void kexit(Ureg *);
+ulong getifsr(void);
+ulong getdfsr(void);
+uintptr getifar(void);
+uintptr getdfar(void);
+void links(void);
+void timerinit(void);
+void synccycles(void);
+void setpmcr(ulong);
+void setpmcnten(ulong);
+void* tmpmap(uintptr);
+void tmpunmap(void*);
+void flushpg(void *);
+void setasid(ulong);
+void flushtlb(void);
+void touser(void *);
+void noted(Ureg *, ulong);
+void l1switch(L1 *, int);
+void intrenable(int, void (*)(Ureg *, void *), void *, int, char *);
+void intrinit(void);
+void intr(Ureg *);
+int uartconsole(void);
+long fbctlread(Chan*,void*,long,vlong);
+long fbctlwrite(Chan*,void*,long,vlong);
+void fpoff(void);
+void fpsave(FPsave *);
+void fprestore(FPsave *);
+void fpinit(void);
+void fpclear(void);
+char* getconf(char *);
+void invalise(void *, void *);
+void cleandse(void *, void *);
+void invaldse(void *, void *);
+void clinvdse(void *, void *);
+void invaldln(void *);
+void cleandln(void *);
+void clinvdln(void *);
+void dmaflush(int, void*, ulong);
+void* ucalloc(ulong);
+void clean2pa(uintptr, uintptr);
+void inval2pa(uintptr, uintptr);
+void archinit(void);
+uintptr palookur(void *);
+void screeninit(void);
+int isaconfig(char*, int, ISAConf*);
+void cputhex(u32int);
diff --git a/sys/src/9/cycv/init9.s b/sys/src/9/cycv/init9.s
new file mode 100644 (file)
index 0000000..8d6f11d
--- /dev/null
@@ -0,0 +1,7 @@
+TEXT _main(SB), $-4
+       MOVW $setR12(SB), R12
+       MOVW 4(R13), R0
+       ADD $4, R13, R1
+       SUB $4, R13
+       MOVW R1, 8(R13)
+       MOVW $startboot(SB), R15
diff --git a/sys/src/9/cycv/intr.c b/sys/src/9/cycv/intr.c
new file mode 100644 (file)
index 0000000..45a68f9
--- /dev/null
@@ -0,0 +1,121 @@
+#include "u.h"
+#include <ureg.h>
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+enum {
+       NINTR = 212,
+       NPRIVATE = 32
+};
+
+static struct irq {
+       void (*f)(Ureg *, void *);
+       void *arg;
+       char *name;
+} irqs[NINTR];
+
+enum {
+       ICCICR = 0x100/4,
+       ICCPMR,
+       ICCBPR,
+       ICCIAR,
+       ICCEOIR,
+       ICDDCR = 0x1000/4,
+       ICDISR = 0x1080/4,
+       ICDISER = 0x1100/4,
+       ICDICER = 0x1180/4,
+       ICDICPR = 0x1280/4,
+       ICDABR  = 0x1300/4,
+       ICDIPRI = 0x1400/4,
+       ICDIPTR = 0x1800/4,
+       ICDICFR = 0x1C00/4,
+};
+
+void
+intrinit(void)
+{
+       int i;
+
+       mpcore[ICDDCR] = 3;
+       mpcore[ICCICR] = 7;
+       mpcore[ICCBPR] = 3;
+       mpcore[ICCPMR] = 255;
+
+       if(m->machno != 0)
+               return;
+       
+       /* disable all irqs and clear any pending interrupts */
+       for(i = 0; i < NINTR/32; i++){
+               mpcore[ICDISR + i] = -1;
+               mpcore[ICDICER + i] = -1;
+               mpcore[ICDICPR + i] = -1;
+               mpcore[ICDABR + i] = 0;
+       }
+}
+
+void
+intrenable(int irq, void (*f)(Ureg *, void *), void *arg, int type, char *name)
+{
+       ulong *e, s;
+       struct irq *i;
+
+       if(f == nil)
+               panic("intrenable: f == nil");
+       if(irq < 0 || irq >= NINTR)
+               panic("intrenable: invalid irq %d", irq);
+       if(type != LEVEL && type != EDGE)
+               panic("intrenable: invalid type %d", type);
+       if(irqs[irq].f != nil && irqs[irq].f != f)
+               panic("intrenable: handler already assigned");
+       if(irq >= NPRIVATE){
+               e = &mpcore[ICDIPTR + (irq >> 2)];
+               s = irq << 3 & 24;
+               *e = *e & ~(3 << s) | 1 << s;
+               e = &mpcore[ICDICFR + (irq >> 4)];
+               s = irq << 1 & 30 | 1;
+               *e = *e & ~(1 << s) | type << s;
+       }
+       ((uchar*)&mpcore[ICDIPRI])[irq] = 0;
+       i = &irqs[irq];
+       i->f = f;
+       i->arg = arg;
+       i->name = name;
+       mpcore[ICDISER + (irq >> 5)] = 1 << (irq & 31);
+       mpcore[ICDABR + (irq >> 5)] |= 1 << (irq & 31);
+}
+
+void
+intr(Ureg *ureg)
+{
+       ulong v;
+       int irq;
+       struct irq *i;
+
+       v = mpcore[ICCIAR];
+       irq = v & 0x3ff;
+       if(irq == 0x3ff)
+               return;
+               
+       m->intr++;
+       m->lastintr = irq;
+       i = &irqs[irq];
+       if(i->f == nil)
+               print("irq without handler %d\n", irq);
+       else
+               i->f(ureg, i->arg);
+       mpcore[ICCEOIR] = v;
+
+       if(up != nil){
+               if(irq == TIMERIRQ){
+                       if(up->delaysched){
+                               splhi();
+                               sched();
+                       }
+               }else
+                       preempted();
+       }
+}
diff --git a/sys/src/9/cycv/io.h b/sys/src/9/cycv/io.h
new file mode 100644 (file)
index 0000000..dd0d900
--- /dev/null
@@ -0,0 +1,13 @@
+#define UART_BASE 0xFFC02000
+#define MPCORE_BASE 0xFFFEC000
+#define L2_BASE 0xFFFEF000
+#define CLOCKMGR_BASE 0xFFD04000
+
+#define HPS_CLK 25
+
+#define TIMERIRQ 29
+#define UART0IRQ 194
+
+#define LEVEL 0
+#define EDGE 1
+
diff --git a/sys/src/9/cycv/l.s b/sys/src/9/cycv/l.s
new file mode 100644 (file)
index 0000000..2bbe00a
--- /dev/null
@@ -0,0 +1,502 @@
+#include "mem.h"
+#include "io.h"
+
+#define PUTC(c) MOVW $(c), R0; MOVW R0, (R8)
+
+TEXT _start(SB), $-4
+       MOVW $(KTZERO-KZERO), R13
+       MOVW $(UART_BASE), R8
+       
+       /* disable L2 cache */
+       MOVW $0, R0
+       MOVW $(L2_BASE+0x100), R1
+       MOVW R0, (R1)
+
+       PUTC('P')
+       /* disable MMU and L1 caches */
+       MOVW $0x20c5047a, R1
+       MOVW $_start0-KZERO(SB), R2
+       MCR 15, 0, R1, C(1), C(0), 0
+       MOVW R2, R15
+
+TEXT _start0(SB), $-4
+       DSB
+       ISB
+       PUTC('l')
+       
+       /* clean up to KTZERO */
+       MOVW $0, R0
+       MOVW R0, R1
+       MOVW $(KTZERO-KZERO), R2
+_clrstart:
+       MOVW.P R0, 4(R1)
+       CMP.S R1, R2
+       BGE _clrstart
+
+       /* clean BSS */
+       MOVW $edata-KZERO(SB), R1
+       MOVW $end-KZERO(SB), R2
+_clrbss:
+       MOVW.P R0, 4(R1)
+       CMP.S R1, R2
+       BGE _clrbss
+       
+       PUTC('a')
+       
+       /* KZERO to PERIPH is mapped to 0 */
+       MOVW $SECSZ, R0
+       MOVW $(MACHL1(0)-KZERO), R4
+       MOVW $KZERO, R1
+       ADD R1>>(SECSH-2), R4, R1
+       MOVW $(L1SEC|L1CACHED|L1KERRW), R2
+       MOVW $(PERIPH-KZERO), R3
+_start1:
+       MOVW.P R2, 4(R1)
+       ADD R0, R2
+       CMP.S R2, R3
+       BGE _start1
+
+       /* memory above PERIPH is mapped to itself */
+       MOVW $(PERIPH|L1SEC|L1DEVICE|L1NOEXEC|L1KERRW), R2
+_start2:
+       MOVW.P R2, 4(R1)
+       ADD.S R0, R2
+       BCC _start2
+
+       PUTC('n')
+
+       MOVW $(MACH(0)-KZERO), R(Rmach)
+_start3:
+       /* enable MMU permission checking */
+       MOVW $0x55555555, R0
+       MCR 15, 0, R0, C(3), C(0), 0
+
+       /* select page table and enable MMU */
+       MOVW $0, R0
+       MCR 15, 0, R0, C(8), C(7), 0
+       DSB
+       ORR $TTBATTR, R4, R1
+       MCR 15, 0, R1, C(2), C(0), 0
+       MOVW $0x20c5047b, R1
+       MOVW $_virt(SB), R2
+       PUTC(' ')
+       MCR 15, 0, R1, C(1), C(0), 0
+       MOVW R2, R15
+
+TEXT _virt(SB), $-4
+       DSB
+       ISB
+
+       ADD $KZERO, R(Rmach)
+       MOVW R(Rmach), R13
+       ADD $MACHSIZE, R13
+
+       MOVW R(Rmach), R0
+       ADD $12, R0
+       BL loadsp(SB)
+
+       MOVW $vectors(SB), R1
+       MCR 15, 0, R1, C(12), C(0)
+       
+       /* enable maths coprocessors in CPACR but disable them in FPEXC */
+       MRC 15, 0, R0, C(1), C(0), 2
+       ORR $(15<<20), R0
+       MCR 15, 0, R0, C(1), C(0), 2
+
+       VMRS(0xe, FPEXC, 0)
+       BIC $(3<<30), R0
+       VMSR(0xe, 0, FPEXC)
+       
+       /* enable L1 cache */
+       MOVW $0, R0
+       MCR 15, 0, R0, C(7), C(5), 0
+       MCR 15, 0, R0, C(7), C(5), 6
+       BL l1dclear(SB)
+       MRC 15, 0, R0, C(1), C(0), 1
+       ORR $(1|2|1<<6), R0
+       MCR 15, 0, R0, C(1), C(0), 1
+       MRC 15, 0, R0, C(1), C(0), 0
+       ORR $(3<<11|1<<2), R0
+       MCR 15, 0, R0, C(1), C(0), 0
+       DSB
+       ISB
+
+       MOVW $UART_BASE, R8
+       PUTC('9')
+
+       /* kernel Mach* in TPIDRPRW */
+       MCR 15, 0, R(Rmach), C(13), C(0), 4
+
+       MOVW $setR12(SB), R12
+       MOVW $0, R(Rup)
+
+       BL main(SB)
+       B idlehands(SB)
+
+       BL _div(SB) /* hack to load _div */
+
+TEXT touser(SB), $-4
+       CPS(CPSID)
+
+       SUB $12, R13
+       MOVW R0, (R13)
+       MOVW $0, R1
+       MOVW R1, 4(R13)
+       MOVW $(UTZERO+0x20), R1
+       MOVW R1, 8(R13)
+
+       MOVW CPSR, R1
+       BIC $(PsrMask|PsrDirq|PsrDfiq), R1
+       ORR $PsrMusr, R1
+       MOVW R1, SPSR
+
+       MOVW $(KTZERO-(15*4)), R0
+       MOVM.IA (R0), [R0-R12]
+
+       MOVM.IA.S (R13), [R13-R14]
+       ADD $8, R13
+       MOVM.IA.W.S (R13), [R15]
+
+TEXT forkret(SB), $-4
+       MOVW (16*4)(R13), R0
+       MOVW R0, SPSR
+       MOVM.IA.W (R13), [R0-R12]
+       MOVM.IA.S (R13), [R13-R14]
+       ADD $16, R13
+       DSB
+       ISB
+       MOVM.IA.W.S (R13), [R15]
+
+TEXT loadsp(SB), $0
+       CPS(CPSMODE | PsrMabt)
+       MOVW R0, R13
+       CPS(CPSMODE | PsrMund)
+       MOVW R0, R13
+       CPS(CPSMODE | PsrMirq)
+       MOVW R0, R13
+       CPS(CPSMODE | PsrMfiq)
+       MOVW R0, R13
+       CPS(CPSMODE | PsrMsvc)
+       RET
+
+TEXT cputhex(SB), $0
+       MOVW R0, R7
+       MOVW $UART_BASE, R8
+TEXT puthex(SB), $0
+_p0:
+       MOVW 0x14(R8), R6
+       AND.S $(1<<5), R6
+       BEQ _p0
+#define DIG MOVW R7>>28, R6; AND $15, R6; ADD $'0', R6; CMP $'9', R6; ADD.GT $7, R6; MOVW R6, (R8); MOVW R7<<4, R7
+       DIG; DIG; DIG; DIG
+       DIG; DIG; DIG; DIG
+       MOVW $13, R6
+       MOVW R6, (R8)
+       MOVW $10, R6
+       MOVW R6, (R8)
+       RET
+
+TEXT spllo(SB), $-4
+       MOVW CPSR, R0
+       CPS(CPSIE)
+       RET
+
+TEXT splhi(SB), $-4
+       MOVW R14, 4(R(Rmach))
+       MOVW CPSR, R0
+       CPS(CPSID)
+       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 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
+spincas:
+       LDREX   (R0), R3
+       CMP.S   R3, R1
+       BNE     fail
+       STREX   R2, (R0), R4
+       CMP.S   $0, R4
+       BNE     spincas
+       MOVW    $1, R0
+       DMB
+       RET
+fail:
+       CLREX
+       MOVW    $0, R0
+       RET
+
+TEXT tas(SB), $0
+TEXT _tas(SB), $0
+       MOVW $0xDEADDEAD, R2
+_tas1:
+       LDREX (R0), R1
+       STREX R2, (R0), R3
+       CMP.S $0, R3
+       BNE _tas1
+       MOVW R1, R0
+       DMB
+       RET
+
+TEXT coherence(SB), $0
+       DSB
+       RET
+
+TEXT idlehands(SB), $0
+       DSB
+       WFE
+       RET
+
+TEXT sendevent(SB), $0
+       SEV
+       RET
+
+TEXT ttbget(SB), $0
+       MRC 15, 0, R0, C(2), C(0), 0
+       BIC $0x7f, R0
+       RET
+       
+TEXT ttbput(SB), $0
+       ORR $TTBATTR, R0
+       MCR 15, 0, R0, C(2), C(0), 0
+       RET
+
+TEXT flushpg(SB), $0
+       MCR 15, 0, R0, C(8), C(7), 3
+       DSB
+       RET
+
+TEXT flushtlb(SB), $0
+       MCR 15, 0, R0, C(8), C(3), 0
+       DSB
+       RET
+
+TEXT setasid(SB), $0
+       DSB     /* errata */
+       MCR 15, 0, R0, C(13), C(0), 1
+       RET
+
+TEXT getifar(SB), $0
+       MRC 15, 0, R0, C(6), C(0), 2
+       RET
+
+TEXT getdfar(SB), $0
+       MRC 15, 0, R0, C(6), C(0), 0
+       RET
+
+TEXT getifsr(SB), $0
+       MRC 15, 0, R0, C(5), C(0), 1
+       RET
+
+TEXT getdfsr(SB), $0
+       MRC 15, 0, R0, C(5), C(0), 0
+       RET
+
+TEXT setpmcr(SB), $0
+       MCR 15, 0, R0, C(9), C(12), 0
+       RET
+
+TEXT setpmcnten(SB), $0
+       MCR 15, 0, R0, C(9), C(12), 1
+       RET
+
+TEXT perfticks(SB), $0
+       MRC 15, 0, R0, C(9), C(13), 0
+       RET
+
+TEXT cycles(SB), $0
+       MRC 15, 0, R1, C(9), C(13), 0
+       MOVW R1, (R0)
+       MOVW 24(R(Rmach)), R1
+       MRC 15, 0, R2, C(9), C(12), 3
+       AND.S $(1<<31), R2
+       BEQ _cycles0
+       MCR 15, 0, R2, C(9), C(12), 3
+       ADD $1, R1
+       MOVW R1, 24(R(Rmach))
+_cycles0:
+       MOVW R1, 4(R0)
+       RET
+
+TEXT fpinit(SB), $0
+       MOVW $(1<<30), R0
+       VMSR(0xe, 0, FPEXC)
+       MOVW $0, R0
+       VMSR(0xe, 0, FPSCR)
+       RET
+
+TEXT fprestore(SB), $0
+       MOVM.IA.W (R0), [R1-R2]
+       VMSR(0xe, 1, FPEXC)
+       VMSR(0xe, 2, FPSCR)
+       WORD $0xecb00b20
+       WORD $0xecf00b20
+       RET
+
+TEXT fpsave(SB), $0
+       VMRS(0xe, FPEXC, 1)
+       VMRS(0xe, FPSCR, 2)
+       MOVM.IA.W [R1-R2], (R0)
+       WORD $0xeca00b20
+       WORD $0xece00b20
+       /* wet floor */
+
+TEXT fpoff(SB), $0
+TEXT fpclear(SB), $0
+       MOVW $0, R1
+       VMSR(0xe, 1, FPEXC)
+       RET
+
+#define Rnoway R1
+#define Rwayinc R2
+#define Rmaxway R3
+#define Rsetinc R4
+#define Rmaxset R5
+
+TEXT l1dclear(SB), $0
+       MOVW $0, R0
+       MCR 15, 2, R0, C(0), C(0), 0
+       MRC 15, 1, R9, C(0), C(0), 0
+       AND $7, R9, R8
+       ADD $4, R8
+       MOVW $1, Rsetinc
+       MOVW Rsetinc<<R8, Rsetinc
+
+       MOVW R9>>13, Rmaxset
+       AND $0x7fff, Rmaxset
+       MOVW Rmaxset<<R8, Rmaxset
+       
+       MOVW R9>>3, R0
+       AND $0x3ff, R0
+       MOVW $(1<<31), Rwayinc
+       MOVW $(1<<31), Rnoway
+       MOVW R0, Rmaxway
+       ADD $1, R0
+_l1dclear0:
+       MOVW.S R0>>1, R0
+       BEQ _l1dclear1
+       MOVW Rwayinc>>1, Rwayinc
+       MOVW Rnoway->1, Rnoway
+       MOVW Rmaxway@>1, Rmaxway
+       B _l1dclear0
+_l1dclear1:
+       MOVW Rwayinc<<1, Rwayinc
+       MVN Rnoway<<1, Rnoway
+       BIC Rnoway, Rmaxway
+
+       MOVW $0, R0
+_l1dclear2:
+       MCR 15, 0, R0, C(7), C(14), 2
+       ADD Rwayinc, R0
+       CMP.S Rmaxway, R0
+       BLT _l1dclear2
+       AND Rnoway, R0
+       ADD Rsetinc, R0
+       CMP.S Rmaxset, R0
+       BLT _l1dclear2
+       RET
+
+TEXT invalise(SB), $0
+       MOVW 4(FP), R1
+       ADD $(LINSIZ - 1), R1
+       BIC $(LINSIZ - 1), R0
+       BIC $(LINSIZ - 1), R1
+_invalise0:
+       MCR 15, 0, R0, C(7), C(5), 1
+       ADD $LINSIZ, R0
+       CMP.S R1, R0
+       BLT _invalise0  
+       RET
+
+TEXT cleandse(SB), $0
+       DSB
+       MOVW 4(FP), R1
+       ADD $(LINSIZ - 1), R1
+       BIC $(LINSIZ - 1), R0
+       BIC $(LINSIZ - 1), R1
+_cleandse0:
+       MCR 15, 0, R0, C(7), C(10), 1
+       ADD $LINSIZ, R0
+       CMP.S R1, R0
+       BLT _cleandse0
+       DSB
+       RET
+       
+TEXT invaldse(SB), $0
+       MOVW 4(FP), R1
+       ADD $(LINSIZ - 1), R1
+       BIC $(LINSIZ - 1), R0
+       BIC $(LINSIZ - 1), R1
+_invaldse0:
+       MCR 15, 0, R0, C(7), C(6), 1
+       ADD $LINSIZ, R0
+       CMP.S R1, R0
+       BLT _invaldse0
+       DSB
+       RET
+
+TEXT clinvdse(SB), $0
+       DSB
+       MOVW 4(FP), R1
+       ADD $(LINSIZ - 1), R1
+       BIC $(LINSIZ - 1), R0
+       BIC $(LINSIZ - 1), R1
+_clinvdse0:
+       MCR 15, 0, R0, C(7), C(14), 1
+       ADD $LINSIZ, R0
+       CMP.S R1, R0
+       BLT _clinvdse0
+       DSB
+       RET
+
+TEXT cleandln(SB), $0
+       DSB
+       MCR 15, 0, R0, C(7), C(10), 1
+       DSB
+       RET
+
+TEXT invaldln(SB), $0
+       MCR 15, 0, R0, C(7), C(6), 1
+       DSB
+       RET
+
+TEXT clinvdln(SB), $0
+       DSB
+       MCR 15, 0, R0, C(7), C(14), 1
+       DSB
+       RET
+
+TEXT palookur(SB), $0
+       MCR 15, 0, R0, C(7), C(8), 2
+       DSB
+       MRC 15, 0, R0, C(7), C(4), 0
+       RET
+
diff --git a/sys/src/9/cycv/ltrap.s b/sys/src/9/cycv/ltrap.s
new file mode 100644 (file)
index 0000000..4334d22
--- /dev/null
@@ -0,0 +1,100 @@
+#include "mem.h"
+#include "io.h"
+
+TEXT vectors(SB), $-4
+       MOVW $_start-KZERO(SB), R15
+       MOVW $_vexc(SB), R15
+       MOVW $_vsvc(SB), R15
+       MOVW $_viabt(SB), R15
+       MOVW $_vexc(SB), R15
+       MOVW $vectors(SB), R15
+       MOVW $_vexc(SB), R15
+       MOVW $_vexc(SB), R15
+
+TEXT _viabt(SB), $-4
+       CPS(CPSID)
+       CLREX
+       DSB
+       MOVW R14, 8(R13)
+       MOVW SPSR, R14
+       MOVW R14, 4(R13)
+       MOVW CPSR, R14
+       AND $0x1e, R14
+       B _exc
+       
+
+TEXT _vexc(SB), $-4
+       CPS(CPSID)
+       CLREX
+       DSB
+       MOVW R14, 8(R13)
+       MOVW SPSR, R14
+       MOVW R14, 4(R13)
+       MOVW CPSR, R14
+       AND $0x1f, R14
+_exc:
+       MOVW R14, 0(R13)
+       CPS(CPSMODE | PsrMsvc)
+
+       SUB $(18*4), R13
+       MOVM.IA [R0-R14], (R13)
+
+       /* get Mach* from TPIDRPRW */
+       MRC 15, 0, R(Rmach), C(13), C(0), 4
+       MOVW 8(R(Rmach)), R(Rup)
+       MOVW $setR12(SB), R12
+       
+       ADD $12, R(Rmach), R0
+       MOVM.IA (R0), [R1-R3]
+       ADD $(15*4), R13, R0
+       MOVM.IA [R1-R3], (R0)
+       
+       AND.S $0xf, R2
+       ADD.NE $(18*4), R13, R0
+       MOVW.NE R0, (13*4)(R13)
+       ADD.EQ $(13*4), R13, R0
+       MOVM.IA.S.EQ [R13-R14], (R0)
+       
+       MOVW R13, R0
+       SUB $8, R13
+       BL trap(SB)
+       ADD $8, R13
+       
+       MOVW (16*4)(R13), R0
+       MOVW R0, SPSR
+       AND.S $0xf, R0
+       BEQ _uret
+       MOVW R(Rmach), (Rmach*4)(R13)
+       MOVM.IA (R13), [R0-R14]
+       DSB
+       MOVM.DB.S (R13), [R15]
+
+TEXT _vsvc(SB), $-4
+       CLREX
+       DSB
+       MOVW.W R14, -4(R13)
+       MOVW SPSR, R14
+       MOVW.W R14, -4(R13)
+       MOVW $PsrMsvc, R14
+       MOVW.W R14, -4(R13)
+       MOVM.DB.S [R0-R14], (R13)
+       SUB $(15*4), R13
+       
+       /* get Mach* from TPIDRPRW */
+       MRC 15, 0, R(Rmach), C(13), C(0), 4
+       MOVW 8(R(Rmach)), R(Rup)
+       MOVW $setR12(SB), R12
+       
+       MOVW R13, R0
+       SUB $8, R13
+       BL syscall(SB)
+       ADD $8, R13
+
+       MOVW (16*4)(R13), R0
+       MOVW R0, SPSR
+_uret:
+       MOVM.IA.S (R13), [R0-R14]
+       ADD $(17*4), R13
+       DSB
+       ISB
+       MOVM.IA.S.W (R13), [R15]
diff --git a/sys/src/9/cycv/main.c b/sys/src/9/cycv/main.c
new file mode 100644 (file)
index 0000000..48212fc
--- /dev/null
@@ -0,0 +1,316 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "init.h"
+#include "pool.h"
+#include "io.h"
+#include "../port/error.h"
+#include "tos.h"
+
+Conf conf;
+int normalprint, delaylink;
+
+enum { MAXCONF = 64 };
+
+char *confname[MAXCONF], *confval[MAXCONF];
+int nconf;
+
+void
+exit(int)
+{
+       cpushutdown();
+       for(;;) idlehands();
+}
+
+void
+reboot(void *, void *, ulong)
+{
+}
+
+void
+evenaddr(uintptr va)
+{
+       if((va & 3) != 0){
+               dumpstack();
+               postnote(up, 1, "sys: odd address", NDebug);
+               error(Ebadarg);
+       }
+}
+
+void
+procfork(Proc *p)
+{
+       ulong s;
+
+       p->kentry = up->kentry;
+       p->pcycles = -p->kentry;
+       
+       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
+procsetup(Proc *p)
+{
+       p->fpstate = FPinit;
+       fpoff();
+       
+       cycles(&p->kentry);
+       p->pcycles = -p->kentry;
+}
+
+void
+kexit(Ureg *)
+{
+       Tos *tos;
+       uvlong t;
+
+       tos = (Tos*)(USTKTOP-sizeof(Tos));
+       cycles(&t);
+       tos->kcycles += t - up->kentry;
+       tos->pcycles = t + up->pcycles;
+       tos->pid = up->pid;
+}
+
+static void
+options(void)
+{
+       long i, n;
+       char *cp, *line[MAXCONF], *p, *q;
+
+       cp = (char *) CONFADDR;
+
+       p = cp;
+       for(q = cp; *q; q++){
+               if(*q == '\r')
+                       continue;
+               if(*q == '\t')
+                       *q = ' ';
+               *p++ = *q;
+       }
+       *p = 0;
+
+       n = getfields(cp, line, MAXCONF, 1, "\n");
+       for(i = 0; i < n; i++){
+               if(*line[i] == '#')
+                       continue;
+               cp = strchr(line[i], '=');
+               if(cp == nil)
+                       continue;
+               *cp++ = '\0';
+               confname[nconf] = line[i];
+               confval[nconf] = cp;
+               nconf++;
+       }
+
+}
+
+void
+confinit(void)
+{
+       ulong kmem;
+       int i;
+
+       conf.nmach = 1;
+       conf.nproc = 2000;
+       conf.ialloc = 16*1024*1024;
+       conf.nimage = 200;
+       conf.mem[0].base = PGROUND((ulong)end - KZERO);
+       conf.mem[0].npage = (1024*1024*1024 - conf.mem[0].base) >> PGSHIFT;
+
+       ramdiskinit();
+
+       conf.npage = 0;
+       for(i = 0; i < nelem(conf.mem); i++)
+               conf.npage += conf.mem[i].npage;
+
+       kmem = 200*1024*1024;
+       conf.upages = conf.npage - kmem/BY2PG;
+       kmem -= conf.upages*sizeof(Page)
+               + conf.nproc*sizeof(Proc)
+               + conf.nimage*sizeof(Image);
+       mainmem->maxsize = kmem;
+       imagmem->maxsize = kmem - (kmem/10);
+}
+
+static void
+init0(void)
+{
+       char buf[ERRMAX], **sp;
+       int i;
+
+       up->nerrlab = 0;
+       spllo();
+       
+       up->slash = namec("#/", Atodir, 0, 0);
+       pathclose(up->slash->path);
+       up->slash->path = newpath("/");
+       up->dot = cclone(up->slash);
+       
+       chandevinit();
+       
+       if(!waserror()){
+               ksetenv("cputype", "arm", 0);
+               if(cpuserver)
+                       ksetenv("service", "cpu", 0);
+               else
+                       ksetenv("service", "terminal", 0);
+               ksetenv("console", "0", 0);
+               snprint(buf, sizeof(buf), "zynq %s", conffile);
+               ksetenv("terminal", buf, 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);
+
+       sp = (char**)(USTKTOP - sizeof(Tos) - 8 - sizeof(sp[0])*4);
+       sp[3] = sp[2] = nil;
+       strcpy(sp[1] = (char*)&sp[4], "boot");
+       sp[0] = nil;
+       touser(sp);
+}
+
+void
+userinit(void)
+{
+       Proc *p;
+       Segment *s;
+       void *v;
+       Page *pg;
+       
+       p = newproc();
+       p->pgrp = newpgrp();
+       p->egrp = smalloc(sizeof(Egrp));
+       p->egrp->ref = 1;
+       p->fgrp = dupfgrp(nil);
+       p->rgrp = newrgrp();
+       p->procmode = 0640;
+       
+       kstrdup(&eve, "");
+       kstrdup(&p->text, "*init*");
+       kstrdup(&p->user, eve);
+       
+       procsetup(p);
+       
+       p->sched.pc = (ulong)init0;
+       p->sched.sp = (ulong)p->kstack + KSTACK - (sizeof(Sargs) + BY2WD);
+       
+       s = newseg(SG_STACK, USTKTOP - USTKSIZE, USTKSIZE / BY2PG);
+       p->seg[SSEG] = s;
+       pg = newpage(0, 0, USTKTOP - BY2PG);
+       segpage(s, pg);
+       v = tmpmap(pg->pa);
+       memset(v, 0, BY2PG);
+       tmpunmap(v);
+       
+       s = newseg(SG_TEXT, UTZERO, 1);
+       s->flushme++;
+       p->seg[TSEG] = s;
+       pg = newpage(0, 0, UTZERO);
+       pg->txtflush = ~0;
+
+       segpage(s, pg);
+       v = tmpmap(pg->pa);
+       memset(v, 0, BY2PG);
+       memmove(v, initcode, sizeof(initcode));
+       tmpunmap(v);
+       
+       ready(p);
+}
+
+void
+sanity(void)
+{
+       static int dat = 0xdeadbeef;
+       extern ulong vectors[];
+
+       assert(dat == 0xdeadbeef);
+       assert(((uintptr)vectors & 31) == 0);
+       assert(sizeof(Mach) + KSTACK <= MACHSIZE);
+       assert((KZERO & SECSZ - 1) == 0);
+}
+
+char *
+getconf(char *n)
+{
+       int i;
+       
+       for(i = 0; i < nconf; i++)
+               if(cistrcmp(confname[i], n) == 0)
+                       return confval[i];
+       return nil;
+}
+
+int
+isaconfig(char *, int, ISAConf*)
+{
+       return 0;
+}
+
+void
+cpuidprint(void)
+{
+       print("cpu%d: %dMHz ARM Cortex-A9\n", m->machno, m->cpumhz);
+}
+
+void
+main(void)
+{
+       active.machs[m->machno] = 1;
+       if(m->machno != 0){
+               uartputs("\n", 1);
+               mmuinit();
+               intrinit();
+               timerinit();
+               cpuidprint();
+               synccycles();
+               timersinit();
+               schedinit();
+               return;
+       }
+       uartinit();
+       mmuinit();
+       intrinit();
+       options();
+       confinit();
+       timerinit();
+       uartputs(" from Bell Labs\n", 16);
+       xinit();
+       printinit();
+       quotefmtinstall();
+       cpuidprint();
+       sanity();
+       todinit();
+       timersinit();
+       procinit0();
+       initseg();
+       if(delaylink)
+               bootlinks();
+       else
+               links();
+       chandevreset();
+       pageinit();
+       userinit();
+       schedinit();
+}
+
+void
+setupwatchpts(Proc *, Watchpt *, int n)
+{
+       if(n > 0)
+               error("no watchpoints");
+}
diff --git a/sys/src/9/cycv/mem.h b/sys/src/9/cycv/mem.h
new file mode 100644 (file)
index 0000000..6df34dc
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Memory and machine-specific definitions.  Used in C and assembler.
+ */
+
+#define MIN(a, b)      ((a) < (b)? (a): (b))
+#define MAX(a, b)      ((a) > (b)? (a): (b))
+
+/*
+ * Sizes
+ */
+#define        BI2BY           8                       /* bits per byte */
+#define        BI2WD           32                      /* bits per word */
+#define        BY2WD           4                       /* bytes per word */
+#define        BY2V            8                       /* bytes per double word */
+#define        BY2PG           4096                    /* bytes per page */
+#define        WD2PG           (BY2PG/BY2WD)           /* words per page */
+#define        PGSHIFT         12                      /* log(BY2PG) */
+#define        ROUND(s, sz)    (((s)+((sz)-1))&~((sz)-1))
+#define        PGROUND(s)      ROUND(s, BY2PG)
+#define LINSIZ         32
+#define        BLOCKALIGN      LINSIZ
+#define        FPalign         16
+
+#define MAXMACH 2
+#define KSTACK 4096
+
+#define HZ (1000)
+#define MS2HZ (1000/HZ)
+#define TK2SEC(t) ((t)/HZ)
+
+#define KZERO 0xF0000000
+#define KTZERO (KZERO+0x100000)
+#define TMAPSZ SECSZ
+#define TMAP (KZERO - TMAPSZ)
+#define KMAPSZ SECSZ
+#define KMAP (TMAP - KMAPSZ)
+#define NKMAP (KMAPSZ / BY2PG - 1)
+#define MACHSIZE 8192
+#define MACH(n) (KZERO+(n)*MACHSIZE)
+#define MACHP(n) ((Mach *)MACH(n))
+#define MACHL1(n) (ROUND(MACH(MAXMACH), L1SZ) + (n)*L1SZ)
+#define TMAPL2(n) (MACHL1(MAXMACH) + (n) * L2SZ)
+#define TMAPL2SZ (MAXMACH * L2SZ)
+#define CONFSIZE 65536
+#define CONFADDR (KTZERO-CONFSIZE)
+
+#define PERIPH 0xFF000000
+
+#define UZERO 0
+#define UTZERO BY2PG
+#define UTROUND(t) ROUNDUP(t, BY2PG)
+#define USTKTOP 0xE0000000
+#define USTKSIZE (16*1024*1024)
+
+#define PTEMAPMEM (1024*1024)
+#define PTEPERTAB (PTEMAPMEM/BY2PG)
+#define SEGMAPSIZE 1984
+#define SSEGMAPSIZE 16
+
+#define PTEVALID L2VALID
+#define PTERONLY L2RONLY
+#define PTEWRITE L2WRITE
+#define PTENOEXEC L2NOEXEC
+#define PTECACHED L2CACHED
+#define PTEUNCACHED L2DEVICE
+#define PPN(x) ((x)&~(BY2PG-1))
+
+#define PsrDirq (1<<7)
+#define PsrDfiq (1<<6)
+#define PsrMask 0x1f
+#define PsrMusr 0x10
+#define PsrMfiq 0x11
+#define PsrMirq 0x12
+#define PsrMsvc 0x13
+#define PsrMabt 0x17
+#define PsrMiabt 0x16 /* not an actual mode; for ureg->type */
+#define PsrMund 0x1b
+
+#define DMB WORD $0xf57ff05f
+#define DSB WORD $0xf57ff04f
+#define ISB WORD $0xf57ff06f
+#define WFE WORD $0xe320f002
+#define SEV WORD $0xe320f004
+#define CPS(m) WORD $(0xf1000000|(m))
+#define CPSMODE (1<<17)
+#define CPSIE (3<<6|2<<18)
+#define CPSID (3<<6|3<<18)
+#define Rmach 10
+#define Rup 9
+
+#define VMSR(c, r1, r2) WORD $(0x0ee00a10|(c)<<28|(r2)<<16|(r1)<<12)
+#define VMRS(c, r1, r2) WORD $(0x0ef00a10|(c)<<28|(r2)<<12|(r1)<<16)
+#define FPSID 0x0
+#define FPSCR 0x1
+#define MVFR1 0x6
+#define MVFR0 0x7
+#define FPEXC 0x8
+
+#define L1PT 1
+#define L1SEC (2|1<<10)
+#define L1DEVICE 0
+#define L1CACHED (1<<16|1<<14|1<<12|1<<2)
+#define L1NOEXEC (1<<4)
+#define L1KERRW 0
+#define L1SZ (4096*4)
+#define L2SZ (256*4)
+#define SECSZ 1048576
+#define SECSH 20
+#define NL2 256
+
+#define L1X(va) (((ulong)(va)) >> 20)
+#define L1RX(va) (((ulong)(va)) >> 20 & ~3)
+#define L2X(va) (((ulong)(va)) >> 12 & 0xff)
+#define L2RX(va) (((ulong)(va)) >> 12 & 0x3ff)
+
+#define L2VALID (2|1<<4)
+#define L2CACHED (1<<10|1<<8|1<<6|1<<2)
+#define L2DEVICE 0
+#define L2NOEXEC (1<<0)
+#define L2KERRW L2KERNEL
+#define L2KERNEL 0
+#define L2USER (1<<5)
+#define L2RONLY (1<<9)
+#define L2WRITE 0
+#define L2LOCAL (1<<11)
+
+#define TTBATTR (1<<6|1<<3|1<<1)
diff --git a/sys/src/9/cycv/mkfile b/sys/src/9/cycv/mkfile
new file mode 100644 (file)
index 0000000..f2920a2
--- /dev/null
@@ -0,0 +1,89 @@
+CONF=cycv
+CONFLIST=cycv
+
+#must match mem.h
+KTZERO=0xf0100020
+
+objtype=arm
+</$objtype/mkfile
+p=9
+
+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\
+
+OBJ=\
+       ltrap.$O\
+       l.$O\
+       main.$O\
+       mmu.$O\
+       trap.$O\
+       intr.$O\
+       timer.$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\
+
+$p$CONF.u:D: $p$CONF
+       aux/aout2uimage $p$CONF
+
+$p$CONF:D: $CONF.c $OBJ $LIB mkfile
+       $CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
+       $LD -o $target -T$KTZERO -l $OBJ $CONF.$O $LIB
+
+<../boot/bootmkfile
+<../port/portmkfile
+<|../port/mkbootrules $CONF
+
+init.h:D: ../port/initcode.c init9.s
+       $CC ../port/initcode.c
+       $AS init9.s
+       $LD -l -R1 -s -o init.out init9.$O initcode.$O /arm/lib/libc.a
+       {echo 'uchar initcode[]={'
+        xd -1x <init.out |
+               sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
+        echo '};'} > init.h
+
+install:V:     $p$CONF $p$CONF.u
+       cp $p$CONF $p$CONF.u /$objtype/
+       for(i in $EXTRACOPIES)
+               import $i / /n/$i && cp $p$CONF $p$CONF.u /n/$i/$objtype/
diff --git a/sys/src/9/cycv/mmu.c b/sys/src/9/cycv/mmu.c
new file mode 100644 (file)
index 0000000..d7fef95
--- /dev/null
@@ -0,0 +1,376 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+void
+mmuinit(void)
+{
+       m->l1.pa = ttbget();
+       m->l1.va = KADDR(m->l1.pa);
+       memset((uchar*)TMAPL2(m->machno), 0, TMAPL2SZ);
+       m->l1.va[L1X(TMAP)] = PADDR(TMAPL2(m->machno)) | L1PT;
+       incref(&m->l1);
+}
+
+void
+l1switch(L1 *p, int flush)
+{
+       assert(!islo());
+
+       ttbput(p->pa);
+       if(flush){
+               if(++m->asid == 0)
+                       flushtlb();
+               setasid(m->asid);
+       }
+}
+
+static L1 *
+l1alloc(void)
+{
+       L1 *p;
+       int s;
+
+       s = splhi();
+       p = m->l1free;
+       if(p != nil){
+               m->l1free = p->next;
+               p->next = nil;
+               m->nfree--;
+               splx(s);
+               return p;
+       }
+       splx(s);
+       p = smalloc(sizeof(L1));
+       for(;;){
+               p->va = mallocalign(L1SZ, L1SZ, 0, 0);
+               if(p->va != nil)
+                       break;
+               if(!waserror()){
+                       resrcwait("no memory for L1 table");
+                       poperror();
+               }
+       }
+       p->pa = PADDR(p->va);
+       memmove(p->va, m->l1.va, L1SZ);
+       return p;
+}
+
+static void
+l1free(L1 *l1)
+{
+       if(islo())
+               panic("l1free: islo");
+       if(m->nfree >= 40){
+               free(l1->va);
+               free(l1);
+       }else{
+               l1->next = m->l1free;
+               m->l1free = l1;
+               m->nfree++;
+       }
+}
+
+static void
+upallocl1(void)
+{
+       L1 *p;
+       int s;
+
+       if(up->l1 != nil)
+               return;
+       p = l1alloc();
+       s = splhi();
+       if(up->l1 != nil)
+               panic("upalloc1: up->l1 != nil");
+       up->l1 = p;
+       l1switch(p, 1);
+       splx(s);
+}
+
+static void
+l2free(Proc *proc)
+{
+       ulong *t;
+       Page *p, **l;
+
+       if(proc->l1 == nil || proc->mmuused == nil)
+               return;
+       l = &proc->mmuused;
+       for(p = *l; p != nil; p = p->next){
+               t = proc->l1->va + p->daddr;
+               *t++ = 0;
+               *t++ = 0;
+               *t++ = 0;
+               *t = 0;
+               l = &p->next;
+       }
+       proc->l1->va[L1X(TMAP)] = 0;
+       *l = proc->mmufree;
+       proc->mmufree = proc->mmuused;
+       proc->mmuused = 0;
+}
+
+void
+mmuswitch(Proc *p)
+{
+       if(p->newtlb){
+               p->newtlb = 0;
+               l2free(p);
+       }
+       if(p->l1 != nil)
+               l1switch(p->l1, 1);
+       else
+               l1switch(&m->l1, 1);
+}
+
+void
+putmmu(uintptr va, uintptr pa, Page *pg)
+{
+       Page *p;
+       ulong *e;
+       ulong *l2;
+       ulong old;
+       uintptr l2p;
+       int s;
+
+       if(up->l1 == nil)
+               upallocl1();
+       e = &up->l1->va[L1RX(va)];
+       if((*e & 3) == 0){
+               p = up->mmufree;
+               if(p != nil)
+                       up->mmufree = p->next;
+               else
+                       p = newpage(0, 0, 0);
+               p->daddr = L1RX(va);
+               p->next = up->mmuused;
+               up->mmuused = p;
+               s = splhi();
+               l2p = p->pa;
+               l2 = tmpmap(l2p);
+               memset(l2, 0, BY2PG);
+               coherence();
+               e[0] = p->pa | L1PT;
+               e[1] = e[0] + L2SZ;
+               e[2] = e[1] + L2SZ;
+               e[3] = e[2] + L2SZ;
+               coherence();
+       }else{
+               s = splhi();
+               l2p = *e & ~(BY2PG - 1);
+               l2 = tmpmap(l2p);
+       }
+       e = &l2[L2RX(va)];
+       old = *e;
+       *e = pa | L2VALID | L2USER | L2LOCAL;
+       tmpunmap(l2);
+       splx(s);
+       if((old & L2VALID) != 0)
+               flushpg((void *) va);
+       if(pg->txtflush & (1<<m->machno)){
+               cleandse((void *) va, (void *) (va + BY2PG));
+               invalise((void *) va, (void *) (va + BY2PG));
+               pg->txtflush &= ~(1<<m->machno);
+       }
+}
+
+void
+checkmmu(uintptr, uintptr)
+{
+}
+
+void
+flushmmu(void)
+{
+       int s;
+
+       s = splhi();
+       up->newtlb = 1;
+       mmuswitch(up);
+       splx(s);
+}
+
+void
+mmurelease(Proc *proc)
+{
+       Page *p, *n;
+
+       if(islo())
+               panic("mmurelease: islo");
+       
+       l1switch(&m->l1, 0);
+       if(proc->kmaptable != nil){
+               if(proc->l1 == nil)
+                       panic("mmurelease: no l1");
+               if(decref(proc->kmaptable) != 0)
+                       panic("mmurelease: kmap ref %ld", proc->kmaptable->ref);
+               if(proc->nkmap)
+                       panic("mmurelease: nkmap %d", proc->nkmap);
+               if(PPN(proc->l1->va[L1X(KMAP)]) != proc->kmaptable->pa)
+                       panic("mmurelease: bad kmap l2 %#.8lux kmap %#.8lux", proc->l1->va[L1X(KMAP)], proc->kmaptable->pa);
+               proc->l1->va[L1X(KMAP)] = 0;
+               pagechainhead(proc->kmaptable);
+               proc->kmaptable = nil;
+       }
+       if(proc->l1 != nil){
+               l2free(proc);
+               l1free(proc->l1);
+               proc->l1 = nil;
+       }
+       for(p = proc->mmufree; p != nil; p = n){
+               n = p->next;
+               if(decref(p) != 0)
+                       panic("mmurelease: p->ref %ld", p->ref);
+               pagechainhead(p);
+       }
+       if(proc->mmufree != nil)
+               pagechaindone();
+       proc->mmufree = nil;
+}
+
+uintptr
+paddr(void *v)
+{
+       if((uintptr)v >= PERIPH)
+               return (uintptr)v;
+       if((uintptr)v >= KZERO)
+               return (uintptr)v-KZERO;
+       panic("paddr: va=%#p pc=%#p", v, getcallerpc(&v));
+       return 0;
+}
+
+void *
+kaddr(uintptr u)
+{
+       if(u >= (uintptr)PERIPH)
+               return (void *)u;
+       if(u < (uintptr)-KZERO)
+               return (void *)(u + KZERO);
+       panic("kaddr: pa=%#p pc=%#p", u, getcallerpc(&u));
+       return nil;
+}
+
+uintptr
+cankaddr(uintptr u)
+{
+       if(u >= (uintptr)PERIPH)
+               return -u;
+       if(u < (uintptr)-KZERO)
+               return PERIPH-KZERO - u;
+       return 0;
+}
+
+KMap *
+kmap(Page *page)
+{
+       ulong *e, *v;
+       int i, s;
+
+       if(cankaddr(page->pa))
+               return (KMap*)KADDR(page->pa);
+       if(up == nil)
+               panic("kmap: up=0 pc=%#.8lux", getcallerpc(&page));
+       if(up->l1 == nil)
+               upallocl1();
+       if(up->nkmap < 0)
+               panic("kmap %lud %s: nkmap=%d", up->pid, up->text, up->nkmap);
+       up->nkmap++;
+       e = &up->l1->va[L1X(KMAP)];
+       if((*e & 3) == 0){
+               if(up->kmaptable != nil)
+                       panic("kmaptable != nil");
+               up->kmaptable = newpage(0, 0, 0);
+               s = splhi();
+               v = tmpmap(up->kmaptable->pa);
+               memset(v, 0, BY2PG);
+               v[0] = page->pa | L2KERRW | L2VALID | L2CACHED | L2LOCAL;
+               v[NKMAP] = up->kmaptable->pa | L2KERRW | L2VALID | L2CACHED | L2LOCAL;
+               tmpunmap(v);
+               splx(s);
+               *e = up->kmaptable->pa | L1PT;
+               coherence();
+               return (KMap *) KMAP;
+       }
+       if(up->kmaptable == nil)
+               panic("kmaptable == nil");
+       e = (ulong *) (KMAP + NKMAP * BY2PG);
+       for(i = 0; i < NKMAP; i++)
+               if((e[i] & 3) == 0){
+                       e[i] = page->pa | L2KERRW | L2VALID | L2CACHED | L2LOCAL;
+                       coherence();
+                       return (KMap *) (KMAP + i * BY2PG);
+               }
+       panic("out of kmap");
+       return nil;
+}
+
+void
+kunmap(KMap *arg)
+{
+       uintptr va;
+       ulong *e;
+       
+       va = (uintptr) arg;
+       if(va >= KZERO)
+               return;
+       if(up->l1 == nil || (up->l1->va[L1X(KMAP)] & 3) == 0)
+               panic("kunmap: no kmaps");
+       if(va < KMAP || va >= KMAP + NKMAP * BY2PG)
+               panic("kunmap: bad address %#.8lux pc=%#p", va, getcallerpc(&arg));
+       e = (ulong *) (KMAP + NKMAP * BY2PG) + L2X(va);
+       if((*e & 3) == 0)
+               panic("kunmap: not mapped %#.8lux pc=%#p", va, getcallerpc(&arg));
+       up->nkmap--;
+       if(up->nkmap < 0)
+               panic("kunmap %lud %s: nkmap=%d", up->pid, up->text, up->nkmap);
+       *e = 0;
+       coherence();
+       flushpg((void *) va);
+}
+
+void *
+tmpmap(ulong pa)
+{
+       ulong *u, *ub, *ue;
+
+       if(islo())
+               panic("tmpmap: islow %#p", getcallerpc(&pa));
+       if(cankaddr(pa))
+               return KADDR(pa);
+       ub = (ulong *) TMAPL2(m->machno);
+       ue = ub + NL2;
+       for(u = ub; u < ue; u++)
+               if((*u & 3) == 0){
+                       *u = pa | L2VALID | L2CACHED | L2KERRW;
+
+                       assert(m->l1.va[L1X(TMAP)] != 0);
+                       if(up != nil && up->l1 != nil)
+                               up->l1->va[L1X(TMAP)] = m->l1.va[L1X(TMAP)];
+
+                       coherence();
+                       return (void *) ((u - ub) * BY2PG + TMAP);
+               }
+       panic("tmpmap: full (pa=%#.8lux)", pa);
+       return nil;
+}
+
+void
+tmpunmap(void *v)
+{
+       ulong *u;
+
+       if(v >= (void*) KZERO)
+               return;
+       if(v < (void*)TMAP || v >= (void*)(TMAP + TMAPSZ))
+               panic("tmpunmap: invalid address (va=%#.8lux)", (uintptr) v);
+       u = (ulong *) TMAPL2(m->machno) + L2X(v);
+       if((*u & 3) == 0)
+               panic("tmpunmap: double unmap (va=%#.8lux)", (uintptr) v);
+       *u = 0;
+       coherence();
+       flushpg(v);
+}
diff --git a/sys/src/9/cycv/timer.c b/sys/src/9/cycv/timer.c
new file mode 100644 (file)
index 0000000..68cd20f
--- /dev/null
@@ -0,0 +1,112 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+#define clockmgr ((u32int*)(CLOCKMGR_BASE))
+
+uvlong timerhz;
+
+enum {
+       TIMERDIV = 1,
+       LTIMERDIV = 1,
+
+       GTIMERVALL = 0x200/4,
+       GTIMERVALH,
+       GTIMERCTL,
+       LTIMERVAL = 0x604/4,
+       LTIMERCTL,
+       LTIMERISR,
+};
+
+void
+microdelay(int n)
+{
+       ulong now;
+
+       now = Âµs();
+       while(µs() - now < n);
+}
+
+void
+delay(int n)
+{
+       while(--n >= 0)
+               microdelay(1000);
+}
+
+uvlong
+fastticks(uvlong *hz)
+{
+       ulong lo, hi;
+
+       if(hz != nil)
+               *hz = timerhz;
+       do{
+               hi = mpcore[GTIMERVALH];
+               lo = mpcore[GTIMERVALL];
+       }while(hi != mpcore[GTIMERVALH]);
+       return lo | (uvlong)hi << 32;
+}
+
+ulong
+µs(void)
+{
+       return fastticks2us(fastticks(nil));
+}
+
+void
+timerset(Tval v)
+{
+       vlong w;
+
+       w = v - fastticks(nil);
+       if(w < 1)
+               w = 1;
+       if(w > 0xffffffffLL)
+               w = 0xffffffff;
+       mpcore[LTIMERCTL] &= ~1;
+       mpcore[LTIMERVAL] = w;
+       mpcore[LTIMERCTL] |= 1;
+}
+
+void
+timerirq(Ureg *u, void *)
+{
+       if((mpcore[LTIMERISR] & 1) != 0){
+               mpcore[LTIMERISR] |= 1;
+               timerintr(u, 0);
+       }
+}
+
+void
+timerinit(void)
+{
+       u32int vco;
+       u64int hz;
+       int denum, numer, mpuclk;
+       
+       vco = clockmgr[0x40 / 4];
+       denum = vco >> 16 & 0x3f;
+       numer = vco >> 3 & 0x1fff;
+       mpuclk = clockmgr[0x48 / 4] & 0x1ff;
+       
+       hz = HPS_CLK * 1000000 * (numer + 1) / ((denum + 1) * 2 * (mpuclk + 1));
+       m->cpumhz = (hz + 500000) / 1000000;
+       m->cpuhz = hz;
+       timerhz = m->cpuhz / 4;
+
+       mpcore[GTIMERCTL] = TIMERDIV - 1 << 8 | 3;
+       mpcore[LTIMERCTL] = LTIMERDIV - 1 << 8 | 4;
+       intrenable(TIMERIRQ, timerirq, nil, EDGE, "clock");
+}
+
+/*
+ * synchronize all cpu's cycle counter registers
+ */
+void
+synccycles(void)
+{
+}
diff --git a/sys/src/9/cycv/trap.c b/sys/src/9/cycv/trap.c
new file mode 100644 (file)
index 0000000..5dbe809
--- /dev/null
@@ -0,0 +1,591 @@
+#include "u.h"
+#include <ureg.h>
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+#include "tos.h"
+
+static void
+_dumpstack(Ureg *ureg)
+{
+       uintptr l, v, i, estack;
+       extern ulong etext;
+       int x;
+       char *s;
+
+       if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
+               iprint("dumpstack disabled\n");
+               return;
+       }
+       iprint("cpu%d: dumpstack\n", m->machno);
+
+       x = 0;
+       x += iprint("ktrace /arm/9cycv %.8lux %.8lux %.8lux <<EOF\n", ureg->pc, ureg->sp, ureg->r14);
+       i = 0;
+       if(up
+       && (uintptr)&l >= (uintptr)up->kstack
+       && (uintptr)&l <= (uintptr)up->kstack+KSTACK)
+               estack = (uintptr)up->kstack+KSTACK;
+       else if((uintptr)&l >= (uintptr)m->stack
+       && (uintptr)&l <= (uintptr)m+MACHSIZE)
+               estack = (uintptr)m+MACHSIZE;
+       else
+               return;
+       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");
+}
+
+static char*
+faulterr[0x20] = {
+[0x01] "alignement fault",
+[0x02] "debug event",
+[0x04] "fault on instruction cache maintenance",
+[0x08] "synchronous external abort",
+[0x0C] "synchronous external abort on translation table walk L1",
+[0x0E] "synchronous external abort on translation table walk L2",
+[0x10] "tlb conflict abort",
+[0x16] "asynchronous external abort",
+[0x19] "synchronous parity error on memory access",
+[0x1C] "synchronous parity error on translation table walk L1",
+[0x1E] "synchronous parity error on translation table walk L2",
+};
+
+static void
+faultarm(Ureg *ureg, ulong fsr, uintptr addr)
+{
+       int user, insyscall, read;
+       static char buf[ERRMAX];
+       char *err;
+
+       read = (fsr & (1<<11)) == 0;
+       user = userureg(ureg);
+       if(!user){
+               if(addr >= USTKTOP || up == nil)
+                       _dumpstack(ureg);
+               if(addr >= USTKTOP)
+                       panic("kernel fault: bad address pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr);
+               if(up == nil)
+                       panic("kernel fault: no user process pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr);
+       }
+       if(up == nil)
+               panic("user fault: up=nil pc=%#.8lux addr=%#.8lux fsr=%#.8lux", ureg->pc, addr, fsr);
+
+       insyscall = up->insyscall;
+       up->insyscall = 1;
+       switch(fsr & 0x1F){
+       case 0x05:      /* translation fault L1 */
+       case 0x07:      /* translation fault L2 */
+       case 0x03:      /* access flag fault L1 */
+       case 0x06:      /* access flag fault L2 */
+       case 0x09:      /* domain fault L1 */
+       case 0x0B:      /* domain fault L2 */
+       case 0x0D:      /* permission fault L1 */
+       case 0x0F:      /* permission fault L2 */
+               if(fault(addr, ureg->pc, read) == 0)
+                       break;
+               /* wet floor */
+       default:
+               err = faulterr[fsr & 0x1F];
+               if(err == nil)
+                       err = "fault";
+               if(!user){
+                       dumpregs(ureg);
+                       _dumpstack(ureg);
+                       panic("kernel %s: pc=%#.8lux addr=%#.8lux fsr=%#.8lux", err, ureg->pc, addr, fsr);
+               }
+               sprint(buf, "sys: trap: %s %s addr=%#.8lux", err, read ? "read" : "write", addr);
+               postnote(up, 1, buf, NDebug);
+       }
+       up->insyscall = insyscall;
+}
+
+static void
+mathtrap(Ureg *, ulong)
+{
+       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;
+       }
+}
+
+void
+trap(Ureg *ureg)
+{
+       int user;
+       ulong opc, cp;
+
+       user = userureg(ureg);
+       if(user){
+               if(up == nil)
+                       panic("user trap: up=nil");
+               up->dbgreg = ureg;
+               cycles(&up->kentry);
+       }
+       switch(ureg->type){
+       case PsrMund:
+               ureg->pc -= 4;
+               if(user){
+                       spllo();
+                       if(okaddr(ureg->pc, 4, 0)){
+                               opc = *(ulong*)ureg->pc;
+                               if((opc & 0x0f000000) == 0x0e000000 || (opc & 0x0e000000) == 0x0c000000){
+                                       cp = opc >> 8 & 15;
+                                       if(cp == 10 || cp == 11){
+                                               mathtrap(ureg, opc);
+                                               break;
+                                       }
+                               }
+                       }
+                       postnote(up, 1, "sys: trap: invalid opcode", NDebug);
+                       break;
+               }
+               dumpregs(ureg);
+               panic("invalid opcode at pc=%#.8lux lr=%#.8lux", ureg->pc, ureg->r14);
+               break;
+       case PsrMiabt:
+               ureg->pc -= 4;
+               faultarm(ureg, getifsr(), getifar());
+               break;
+       case PsrMabt:
+               ureg->pc -= 8;
+               faultarm(ureg, getdfsr(), getdfar());
+               break;
+       case PsrMirq:
+               ureg->pc -= 4;
+               intr(ureg);
+               break;
+       default:
+               iprint("cpu%d: unknown trap type %ulx\n", m->machno, ureg->type);
+       }
+       splhi();
+       if(user){
+               if(up->procctl || up->nnote)
+                       notify(ureg);
+               kexit(ureg);
+       }
+}
+
+#include "../port/systab.h"
+
+void
+syscall(Ureg *ureg)
+{
+       char *e;
+       uintptr sp;
+       long ret;
+       int i, s;
+       ulong scallnr;
+       vlong startns, stopns;
+       
+       if(!userureg(ureg))
+               panic("syscall: pc=%#.8lux", ureg->pc);
+       
+       cycles(&up->kentry);
+       
+       m->syscall++;
+       up->insyscall = 1;
+       up->pc = ureg->pc;
+       up->dbgreg = ureg;
+       
+       sp = ureg->sp;
+       up->scallnr = scallnr = ureg->r0;
+
+       spllo();
+       
+       up->nerrlab = 0;
+       ret = -1;
+       if(!waserror()){
+               if(sp < USTKTOP - BY2PG || sp > USTKTOP - sizeof(Sargs) - BY2WD){
+                       validaddr(sp, sizeof(Sargs)+BY2WD, 0);
+                       evenaddr(sp);
+               }
+               up->s = *((Sargs*) (sp + BY2WD));
+               
+               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);
+               }
+               
+               if(scallnr >= nsyscall || systab[scallnr] == 0){
+                       pprint("bad sys call number %lud pc %lux", scallnr, ureg->pc);
+                       postnote(up, 1, "sys: bad sys call", NDebug);
+                       error(Ebadarg);
+               }
+               up->psstate = sysctab[scallnr];
+               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();
+}
+
+int
+notify(Ureg *ureg)
+{
+       int l;
+       ulong s, sp;
+       Note *n;
+
+       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);
+       up->notepending = 0;
+       n = &up->note[0];
+       if(strncmp(n->msg, "sys:", 4) == 0){
+               l = strlen(n->msg);
+               if(l > ERRMAX-15)       /* " pc=0x12345678\0" */
+                       l = ERRMAX-15;
+               sprint(n->msg+l, " pc=0x%.8lux", ureg->pc);
+       }
+
+       if(n->flag!=NUser && (up->notified || up->notify==0)){
+               qunlock(&up->debug);
+               if(n->flag == NDebug)
+                       pprint("suicide: %s\n", n->msg);
+               pexit(n->msg, n->flag!=NDebug);
+       }
+
+       if(up->notified){
+               qunlock(&up->debug);
+               splhi();
+               return 0;
+       }
+
+       if(!up->notify){
+               qunlock(&up->debug);
+               pexit(n->msg, n->flag!=NDebug);
+       }
+       sp = ureg->sp;
+       sp -= 256;      /* debugging: preserve context causing problem */
+       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; /* word under Ureg is old up->ureg */
+       up->ureg = (void*)sp;
+       sp -= BY2WD+ERRMAX;
+       memmove((char*)sp, up->note[0].msg, ERRMAX);
+       sp -= 3*BY2WD;
+       *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;
+       *(ulong*)(sp+1*BY2WD) = (ulong)up->ureg;
+       ureg->r0 = (uintptr) up->ureg;
+       ureg->sp = sp;
+       ureg->pc = (uintptr) up->notify;
+       ureg->r14 = 0;
+       up->notified = 1;
+       up->nnote--;
+       memmove(&up->lastnote, &up->note[0], sizeof(Note));
+       memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
+
+       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);
+               pprint("call to noted() when not notified\n");
+               pexit("Suicide", 0);
+       }
+       up->notified = 0;
+       
+       nureg = up->ureg;
+       up->fpstate &= ~FPillegal;
+       
+       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 notified\n");
+               pexit("Suicide", 0);
+       }
+       
+       nureg->psr = nureg->psr & 0xf80f0000 | ureg->psr & 0x07f0ffff;
+       
+       memmove(ureg, nureg, sizeof(Ureg));
+       
+       switch(arg0){
+       case NCONT: case NRSTR:
+               if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0) ||
+                               (nureg->pc & 3) != 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) || !okaddr(nureg->sp, BY2WD, 0) ||
+                               (nureg->pc & 3) != 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;
+       
+       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);
+       }
+}
+
+
+void
+dumpstack(void)
+{
+       callwithureg(_dumpstack);
+}
+
+void
+dumpregs(Ureg *ureg)
+{
+       iprint("trap: %lux psr %8.8lux type %2.2lux pc %8.8lux link %8.8lux\n",
+               ureg->type, ureg->psr, ureg->type, ureg->pc, ureg->link);
+       iprint("R14 %8.8lux R13 %8.8lux R12 %8.8lux R11 %8.8lux R10 %8.8lux\n",
+               ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
+       iprint("R9  %8.8lux R8  %8.8lux R7  %8.8lux R6  %8.8lux R5  %8.8lux\n",
+               ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
+       iprint("R4  %8.8lux R3  %8.8lux R2  %8.8lux R1  %8.8lux R0  %8.8lux\n",
+               ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
+       iprint("pc %#lux link %#lux\n", ureg->pc, ureg->link);
+}
+
+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)
+{
+       ulong v;
+
+       v = ureg->psr;
+       memmove(pureg, uva, n);
+       ureg->psr = ureg->psr & 0xf80f0000 | v & 0x07f0ffff;
+}
+
+void
+callwithureg(void (*f) (Ureg *))
+{
+       Ureg u;
+       
+       u.pc = getcallerpc(&f);
+       u.sp = (uintptr) &f - 4;
+       f(&u);
+}
+
+uintptr
+userpc(void)
+{
+       Ureg *ur;
+       
+       ur = up->dbgreg;
+       return ur->pc;
+}
+
+uintptr
+dbgpc(Proc *)
+{
+       Ureg *ur;
+       
+       ur = up->dbgreg;
+       if(ur == nil)
+               return 0;
+       return ur->pc;
+}
+
+void
+procsave(Proc *p)
+{
+       uvlong t;
+
+       if(p->fpstate == FPactive){
+               if(p->state == Moribund)
+                       fpclear();
+               else
+                       fpsave(p->fpsave);
+               p->fpstate = FPinactive;
+       }
+       cycles(&t);
+       p->kentry -= t;
+       p->pcycles += t;
+
+       l1switch(&m->l1, 0);
+}
+
+void
+procrestore(Proc *p)
+{
+       uvlong t;
+
+       if(p->kp)
+               return;
+
+       cycles(&t);
+       p->kentry += t;
+       p->pcycles -= t;
+}
+
+static void
+linkproc(void)
+{
+       spllo();
+       up->kpfun(up->kparg);
+       pexit("kproc dying", 0);
+}
+
+void
+kprocchild(Proc* p, void (*func)(void*), void* arg)
+{
+       p->sched.pc = (uintptr) linkproc;
+       p->sched.sp = (uintptr) p->kstack + KSTACK;
+
+       p->kpfun = func;
+       p->kparg = arg;
+}
+
+void
+forkchild(Proc *p, Ureg *ureg)
+{
+       Ureg *cureg;
+
+       p->sched.pc = (uintptr) forkret;
+       p->sched.sp = (uintptr) p->kstack + KSTACK - sizeof(Ureg);
+
+       cureg = (Ureg*) p->sched.sp;
+       memmove(cureg, ureg, sizeof(Ureg));
+       cureg->r0 = 0;
+
+       p->psstate = 0;
+       p->insyscall = 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);
+}
diff --git a/sys/src/9/cycv/uartcycv.c b/sys/src/9/cycv/uartcycv.c
new file mode 100644 (file)
index 0000000..eebf3c7
--- /dev/null
@@ -0,0 +1,243 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum {
+       RBR = 0,
+       IER,
+       FCR,
+       LCR,
+       MCR,
+       LSR,
+       MSR,
+       SCR,
+       
+       IIR = FCR,
+};
+
+enum {
+       LSR_THRE = 1<<5,
+       LSR_DR = 1<<0,
+       
+       ENTXIRQ = 1<<1,
+       ENRXIRQ = 1<<0
+};
+
+typedef struct Ctlr {
+       Lock;
+       ulong *r;
+       int irq, iena;
+} Ctlr;
+
+Uart* uartenable(Uart *);
+
+extern PhysUart cycvphysuart;
+
+static Ctlr vctlr[1] = {
+       {
+               .r = (void *) UART_BASE,
+               .irq = UART0IRQ,
+       }
+};
+
+static Uart vuart[1] = {
+       {
+               .regs = &vctlr[0],
+               .name = "UART1",
+               .freq = 25000000,
+               .phys = &cycvphysuart,
+               .console = 1,
+               .baud = 115200,
+       }
+};
+
+void
+uartinit(void)
+{
+       consuart = vuart;
+}
+
+static Uart *
+vuartpnp(void)
+{
+       return vuart;
+}
+
+static void
+vuartkick(Uart *uart)
+{
+       Ctlr *ct;
+       int i;
+
+       if(uart->blocked)
+               return;
+       ct = uart->regs;
+       if((ct->r[LSR] & LSR_THRE) == 0)
+               return;
+       for(i = 0; i < 128; i++){
+               if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
+                       break;
+               ct->r[RBR] = *uart->op++;
+       }
+}
+
+static void
+vuartintr(Ureg *, void *arg)
+{
+       Uart *uart;
+       Ctlr *c;
+       int ch, f;
+       
+       uart = arg;
+       c = uart->regs;
+       for(;;){
+               f = c->r[IIR] & 15;
+               switch(f){
+               case 6: USED(c->r[LSR]); break;
+               case 4: case 8:
+                       while((c->r[LSR] & LSR_DR) != 0){
+                               ch = c->r[RBR];
+                               uartrecv(uart, ch);
+                       }
+                       break;
+               case 2:
+                       vuartkick(uart);
+                       break;
+               default:
+                       return;
+               }
+       }
+}
+
+static void
+vuartenable(Uart *uart, int ie)
+{
+       Ctlr *c;
+       
+       c = uart->regs;
+       ilock(c);
+       while((c->r[LSR] & LSR_THRE) == 0)
+               ;
+       c->r[LCR] = 0x03;
+       c->r[FCR] = 0x1;
+       c->r[IER] = 0x0;
+       if(ie){
+               if(!c->iena){
+                       intrenable(c->irq, vuartintr, uart, LEVEL, uart->name);
+                       c->iena = 1;
+               }
+               c->r[IER] = ENTXIRQ | ENRXIRQ;
+       }
+       iunlock(c);
+}
+
+static int
+vuartgetc(Uart *uart)
+{
+       Ctlr *c;
+       
+       c = uart->regs;
+       while((c->r[LSR] & LSR_DR) == 0)
+               ;
+       return c->r[RBR];
+}
+
+static void
+vuartputc(Uart *uart, int c)
+{
+       Ctlr *ct;
+       
+       ct = uart->regs;
+       while((ct->r[LSR] & LSR_THRE) == 0)
+               ;
+       ct->r[RBR] = c;
+       return;
+}
+
+int
+uartconsole(void)
+{
+       Uart *uart = vuart;
+
+       if(up == nil)
+               return -1;
+
+       if(uartenable(uart) != nil){
+               serialoq = uart->oq;
+               uart->opens++;
+               consuart = uart;
+       }
+       return 0;
+}
+
+int
+vuartbits(Uart *uart, int n)
+{
+       Ctlr *c;
+       
+       c = uart->regs;
+       switch(n){
+       case 5: c->r[LCR] = c->r[LCR] & ~3 | 0; return 0;
+       case 6: c->r[LCR] = c->r[LCR] & ~3 | 1; return 0;
+       case 7: c->r[LCR] = c->r[LCR] & ~3 | 2; return 0;
+       case 8: c->r[LCR] = c->r[LCR] & ~3 | 3; return 0;
+       default:
+               return -1;
+       }
+}
+
+int
+vuartbaud(Uart *, int n)
+{
+       print("uart baud %d\n", n);
+       return 0;
+}
+
+int
+vuartparity(Uart *uart, int p)
+{
+       Ctlr *c;
+       
+       c = uart->regs;
+       switch(p){
+       case 'n': c->r[LCR] = c->r[LCR] & ~0x38; return 0;
+       case 'o': c->r[LCR] = c->r[LCR] & ~0x38 | 0x08; return 0;
+       case 'e': c->r[LCR] = c->r[LCR] & ~0x38 | 0x18; return 0;
+       default:
+               return -1;
+       }
+}
+
+void
+vuartnop(Uart *, int)
+{
+}
+
+int
+vuartnope(Uart *, int)
+{
+       return -1;
+}
+
+
+PhysUart cycvphysuart = {
+       .pnp = vuartpnp,
+       .enable = vuartenable,
+       .kick = vuartkick,
+       .getc = vuartgetc,
+       .putc = vuartputc,
+       .bits = vuartbits,
+       .baud = vuartbaud,
+       .parity = vuartparity,
+       
+       .stop = vuartnope,
+       .rts = vuartnop,
+       .dtr = vuartnop,
+       .dobreak = vuartnop,
+       .fifo = vuartnop,
+       .power = vuartnop,
+       .modemctl = vuartnop,
+};
index 36c4f16789547d676fef046d2668bd22526293ae..d5a618dafde22c327a480f39a211bca5b516bcae 100644 (file)
@@ -1,5 +1,6 @@
 ARCH=\
        bcm\
+       cycv\
        kw\
        mtx\
        omap\
index ef3cd69e5c782af0a08101dc9e33deeeaa42aaef..efd89235607b5b0a24dc1934bf82a9c6caf4361a 100644 (file)
@@ -35,7 +35,7 @@ clean:V:
                mk $i.clean
 
 %.clean:V:
-       rm -f $stem.c [9bz]$stem [9bz]$stem.gz s[9bz]$stem boot$stem.*
+       rm -f $stem.c [9bz]$stem [9bz]$stem.gz [9bz]$stem.u s[9bz]$stem boot$stem.*
 
 nuke:V:        clean
        rm -f ../boot/libboot.a$O *.elf *.rr *.acid