From 78ee7d5717807e6ac779293d0d3c78341de6130a Mon Sep 17 00:00:00 2001 From: "Konstantin Kirik (snegovick)" Date: Sun, 28 Dec 2025 12:27:31 +0300 Subject: Move existing boards into subdits split per arch --- os/pxa/clock.c | 318 --------------- os/pxa/devether.c | 617 ----------------------------- os/pxa/devrtc.c | 169 -------- os/pxa/devuart.c | 1073 -------------------------------------------------- os/pxa/dma.c | 244 ------------ os/pxa/etherif.h | 41 -- os/pxa/fpi.h | 61 --- os/pxa/fpiarm.c | 483 ----------------------- os/pxa/gpio.c | 88 ----- os/pxa/i2c.c | 561 -------------------------- os/pxa/l.s | 548 -------------------------- os/pxa/mmu.c | 252 ------------ os/pxa/pxaio.h | 383 ------------------ os/pxa/sa1110break.c | 360 ----------------- os/pxa/trap.c | 587 --------------------------- 15 files changed, 5785 deletions(-) delete mode 100644 os/pxa/clock.c delete mode 100644 os/pxa/devether.c delete mode 100644 os/pxa/devrtc.c delete mode 100644 os/pxa/devuart.c delete mode 100644 os/pxa/dma.c delete mode 100644 os/pxa/etherif.h delete mode 100644 os/pxa/fpi.h delete mode 100644 os/pxa/fpiarm.c delete mode 100644 os/pxa/gpio.c delete mode 100644 os/pxa/i2c.c delete mode 100644 os/pxa/l.s delete mode 100644 os/pxa/mmu.c delete mode 100644 os/pxa/pxaio.h delete mode 100644 os/pxa/sa1110break.c delete mode 100644 os/pxa/trap.c (limited to 'os/pxa') diff --git a/os/pxa/clock.c b/os/pxa/clock.c deleted file mode 100644 index 2fd6eba6..00000000 --- a/os/pxa/clock.c +++ /dev/null @@ -1,318 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#include "ureg.h" - -static ulong timer_incr[4] = { 0, 0, 0, -1 }; - -typedef struct Clock0link Clock0link; -typedef struct Clock0link { - void (*clock)(void); - Clock0link* link; -} Clock0link; - -static Clock0link *clock0link; -static Lock clock0lock; -static void (*prof_fcn)(Ureg *, int); - -Timer* -addclock0link(void (*clock)(void), int) -{ - Clock0link *lp; - - if((lp = malloc(sizeof(Clock0link))) == 0){ - print("addclock0link: too many links\n"); - return nil; - } - ilock(&clock0lock); - lp->clock = clock; - lp->link = clock0link; - clock0link = lp; - iunlock(&clock0lock); - return nil; -} - -static void -profintr(Ureg *ur, void*) -{ - OstmrReg *ost = OSTMRREG; - int t; - - if((ost->osmr[3] - ost->oscr) < 2*CLOCKFREQ) { - /* less than 2 seconds before reset, say something */ - setpanic(); - clockpoll(); - dumpregs(ur); - panic("Watchdog timer will expire"); - } - - /* advance the profile clock tick */ - ost->osmr[2] += timer_incr[2]; - ost->ossr = (1 << 2); /* Clear the SR */ - t = 1; - while((ost->osmr[2] - ost->oscr) > 0x80000000) { - ost->osmr[2] += timer_incr[2]; - t++; - } - if(prof_fcn) - prof_fcn(ur, t); -} - -static void -clockintr(Ureg*, void*) -{ - Clock0link *lp; - int losttick = 0; - OstmrReg *ost = OSTMRREG; - -{static int tag, led; if(++tag >= HZ){ledset(led ^= 1);tag=0;}} - m->ticks++; -// ost->osmr[3] = ost->oscr + timer_incr[3]; /* restart the watchdog */ - ost->osmr[0] += timer_incr[0]; /* advance the clock tick */ - ost->ossr = (1<<0); /* Clear the SR */ - - while((ost->osmr[0] - ost->oscr) >= 0x80000000) { - ost->osmr[0] += timer_incr[0]; - losttick++; - m->ticks++; - } - - checkalarms(); - - if(canlock(&clock0lock)){ - for(lp = clock0link; lp; lp = lp->link) - if(lp->clock) - lp->clock(); - unlock(&clock0lock); - } - - /* round robin time slice is done by trap.c and proc.c */ -} - -void -timerenable( int timer, int Hz, void (*f)(Ureg *, void*), void* a) -{ - OstmrReg *ost = OSTMRREG; - char name[KNAMELEN]; - - if(timer < 0 || timer > 3) - return; - timer_incr[timer] = CLOCKFREQ/Hz; /* set up freq */ - ost->osmr[timer] = ost->oscr+timer_incr[timer]; - snprint(name, sizeof(name), "timer%d", timer); - intrenable(IRQ, IRQtimer0+timer, f, a, name); - ost->ossr = (1 << timer); /* clear any pending interrupt */ - ost->oier |= (1 << timer); /* enable interrupt */ -} - -void -timerdisable( int timer ) -{ - OstmrReg *ost = OSTMRREG; - - if(timer < 0 || timer > 3) - return; - ost->osmr[timer] = 0; /* clear freq */ - ost->oier &= ~(1 << timer); /* disable interrupt */ -} - -void -installprof(void (*pf)(Ureg *, int)) -{ - int s; - - s = splfhi(); - prof_fcn = pf; - timerenable( 2, HZ+1, profintr, 0); - timer_incr[2] = timer_incr[0]+63; /* fine tuning */ - splx(s); -} - -void -clockinit(void) -{ - OstmrReg *ost = OSTMRREG; - m->ticks = 0; - /* Set up timer registers */ - ost->ossr = 0xf; /* clear all four OSSR trigger bits */ - ost->oier = 0; - ost->osmr[0] = 0; - ost->osmr[1] = 0; - ost->osmr[2] = 0; - // ost->osmr[3] = 0; - timerenable( 0, HZ, clockintr, 0); -// timer_incr[3] = CLOCKFREQ*10; /* 10 second watchdog */ -// timer_setwatchdog(timer_incr[3]); -// timerenable( 2, 1, profintr, 0); /* watch the watchdog */ -} - -void -clockpoll(void) -{ - OstmrReg *ost = OSTMRREG; -// ost->osmr[3] = ost->oscr + timer_incr[3]; /* restart the watchdog */ -} - -void -clockcheck(void) -{ - OstmrReg *ost = OSTMRREG; - - if((ost->osmr[3] - ost->oscr) < CLOCKFREQ) { - setpanic(); - clockpoll(); - dumpstack(); - panic("Watchdog timer will expire"); - } -} - -// macros for fixed-point math - -ulong _mularsv(ulong m0, ulong m1, ulong a, ulong s); - -/* truncated: */ -#define FXDPTDIV(a,b,n) ((ulong)(((uvlong)(a) << (n)) / (b))) -#define MAXMUL(a,n) ((ulong)((((uvlong)1<<(n))-1)/(a))) -#define MULDIV(x,a,b,n) (((x)*FXDPTDIV(a,b,n)) >> (n)) -#define MULDIV64(x,a,b,n) ((ulong)_mularsv(x, FXDPTDIV(a,b,n), 0, (n))) - -/* rounded: */ -#define FXDPTDIVR(a,b,n) ((ulong)((((uvlong)(a) << (n))+((b)/2)) / (b))) -#define MAXMULR(a,n) ((ulong)((((uvlong)1<<(n))-1)/(a))) -#define MULDIVR(x,a,b,n) (((x)*FXDPTDIVR(a,b,n)+(1<<((n)-1))) >> (n)) -#define MULDIVR64(x,a,b,n) ((ulong)_mularsv(x, FXDPTDIVR(a,b,n), 1<<((n)-1), (n))) - - -// these routines are all limited to a maximum of 1165 seconds, -// due to the wrap-around of the OSTIMER - -ulong -timer_start(void) -{ - return OSTMRREG->oscr; -} - -ulong -timer_ticks(ulong t0) -{ - return OSTMRREG->oscr - t0; -} - -int -timer_devwait(ulong *adr, ulong mask, ulong val, int ost) -{ - int i; - ulong t0 = timer_start(); - while((*adr & mask) != val) - if(timer_ticks(t0) > ost) - return ((*adr & mask) == val) ? 0 : -1; - else - for(i = 0; i < 10; i++); /* don't pound OSCR too hard! (why not?) */ - return 0; -} - -void -timer_setwatchdog(int t) -{ - OstmrReg *ost = OSTMRREG; - ost->osmr[3] = ost->oscr + t; - if(t) { - ost->ossr = (1<<3); - ost->oier |= (1<<3); - ost->ower = 1; - } else - ost->oier &= ~(1<<3); -} - -void -timer_delay(int t) -{ - ulong t0 = timer_start(); - while(timer_ticks(t0) < t) - ; -} - - -ulong -us2tmr(int us) -{ - return MULDIV64(us, CLOCKFREQ, 1000000, 24); -} - -int -tmr2us(ulong t) -{ - return MULDIV64(t, 1000000, CLOCKFREQ, 24); -} - -void -microdelay(int us) -{ - ulong t0 = timer_start(); - ulong t = us2tmr(us); - while(timer_ticks(t0) <= t) - ; -} - -ulong -ms2tmr(int ms) -{ - return MULDIV64(ms, CLOCKFREQ, 1000, 20); -} - -int -tmr2ms(ulong t) -{ - return MULDIV64(t, 1000, CLOCKFREQ, 32); -} - -void -delay(int ms) -{ - ulong t0 = timer_start(); - ulong t = ms2tmr(ms); - while(timer_ticks(t0) <= t) - clockpoll(); -} - -/* - * for devbench.c - */ -vlong -archrdtsc(void) -{ - return OSTMRREG->oscr; -} - -ulong -archrdtsc32(void) -{ - return OSTMRREG->oscr; -} - -/* - * for devkprof.c - */ -long -archkprofmicrosecondspertick(void) -{ - return MS2HZ*1000; -} - -void -archkprofenable(int) -{ - /* TO DO */ -} - -uvlong -fastticks(uvlong *hz) -{ - if(hz) - *hz = HZ; - return m->ticks; -} diff --git a/os/pxa/devether.c b/os/pxa/devether.c deleted file mode 100644 index 4b9da104..00000000 --- a/os/pxa/devether.c +++ /dev/null @@ -1,617 +0,0 @@ -#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" -#include "../port/netif.h" - -#include "etherif.h" - -static Ether *etherxx[MaxEther]; - -Chan* -etherattach(char* spec) -{ - ulong ctlrno; - char *p; - Chan *chan; - Ether *ether; - - ctlrno = 0; - if(spec && *spec){ - ctlrno = strtoul(spec, &p, 0); - if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther)) - error(Ebadarg); - } - if((ether = etherxx[ctlrno]) == 0) - error(Enodev); - rlock(ether); - if(waserror()){ - runlock(ether); - nexterror(); - } - chan = devattach('l', spec); - chan->dev = ctlrno; - if(ether->attach) - ether->attach(etherxx[ctlrno]); - poperror(); - runlock(ether); - return chan; -} - -static void -ethershutdown(void) -{ - Ether *ether; - int i; - - for(i=0; idetach != nil) - ether->detach(ether); - } -} - -static Walkqid* -etherwalk(Chan* chan, Chan *nchan, char **name, int nname) -{ - Walkqid *wq; - Ether *ether; - - ether = etherxx[chan->dev]; - rlock(ether); - if(waserror()) { - runlock(ether); - nexterror(); - } - wq = netifwalk(etherxx[chan->dev], chan, nchan, name, nname); - poperror(); - runlock(ether); - return wq; -} - -static int -etherstat(Chan* chan, uchar* dp, int n) -{ - int s; - Ether *ether; - - ether = etherxx[chan->dev]; - rlock(ether); - if(waserror()) { - runlock(ether); - nexterror(); - } - s = netifstat(ether, chan, dp, n); - poperror(); - runlock(ether); - return s; -} - -static Chan* -etheropen(Chan* chan, int omode) -{ - Chan *c; - Ether *ether; - - ether = etherxx[chan->dev]; - rlock(ether); - if(waserror()) { - runlock(ether); - nexterror(); - } - c = netifopen(ether, chan, omode); - poperror(); - runlock(ether); - return c; -} - -static void -ethercreate(Chan*, char*, int, ulong) -{ -} - -static void -etherclose(Chan* chan) -{ - Ether *ether; - - ether = etherxx[chan->dev]; - rlock(ether); - if(waserror()) { - runlock(ether); - nexterror(); - } - netifclose(ether, chan); - poperror(); - runlock(ether); -} - -static long -etherread(Chan* chan, void* buf, long n, vlong off) -{ - Ether *ether; - ulong offset = off; - long r; - - ether = etherxx[chan->dev]; - rlock(ether); - if(waserror()) { - runlock(ether); - nexterror(); - } - if((chan->qid.type & QTDIR) == 0 && ether->ifstat){ - /* - * With some controllers it is necessary to reach - * into the chip to extract statistics. - */ - if(NETTYPE(chan->qid.path) == Nifstatqid){ - r = ether->ifstat(ether, buf, n, offset); - goto out; - } - if(NETTYPE(chan->qid.path) == Nstatqid) - ether->ifstat(ether, buf, 0, offset); - } - r = netifread(ether, chan, buf, n, offset); -out: - poperror(); - runlock(ether); - return r; -} - -static Block* -etherbread(Chan* chan, long n, ulong offset) -{ - Block *b; - Ether *ether; - - ether = etherxx[chan->dev]; - rlock(ether); - if(waserror()) { - runlock(ether); - nexterror(); - } - b = netifbread(ether, chan, n, offset); - poperror(); - runlock(ether); - return b; -} - -static int -etherwstat(Chan* chan, uchar* dp, int n) -{ - Ether *ether; - int r; - - ether = etherxx[chan->dev]; - rlock(ether); - if(waserror()) { - runlock(ether); - nexterror(); - } - r = netifwstat(ether, chan, dp, n); - poperror(); - runlock(ether); - return r; -} - -static void -etherrtrace(Netfile* f, Etherpkt* pkt, int len) -{ - int i, n; - Block *bp; - - if(qwindow(f->in) <= 0) - return; - if(len > 58) - n = 58; - else - n = len; - bp = iallocb(64); - if(bp == nil) - return; - memmove(bp->wp, pkt->d, n); - i = TK2MS(MACHP(0)->ticks); - bp->wp[58] = len>>8; - bp->wp[59] = len; - bp->wp[60] = i>>24; - bp->wp[61] = i>>16; - bp->wp[62] = i>>8; - bp->wp[63] = i; - bp->wp += 64; - qpass(f->in, bp); -} - -Block* -etheriq(Ether* ether, Block* bp, int fromwire) -{ - Etherpkt *pkt; - ushort type; - int len, multi, tome, fromme; - Netfile **ep, *f, **fp, *fx; - Block *xbp; - - ether->inpackets++; - - pkt = (Etherpkt*)bp->rp; - len = BLEN(bp); - type = (pkt->type[0]<<8)|pkt->type[1]; - fx = 0; - ep = ðer->f[Ntypes]; - - multi = pkt->d[0] & 1; - /* check for valid multcast addresses */ - if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){ - if(!activemulti(ether, pkt->d, sizeof(pkt->d))){ - if(fromwire){ - freeb(bp); - bp = 0; - } - return bp; - } - } - - /* is it for me? */ - tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0; - fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0; - - /* - * Multiplex the packet to all the connections which want it. - * If the packet is not to be used subsequently (fromwire != 0), - * attempt to simply pass it into one of the connections, thereby - * saving a copy of the data (usual case hopefully). - */ - for(fp = ether->f; fp < ep; fp++){ - if((f = *fp) && (f->type == type || f->type < 0)) - if(tome || multi || f->prom){ - /* Don't want to hear bridged packets */ - if(f->bridge && !fromwire && !fromme) - continue; - if(!f->headersonly){ - if(fromwire && fx == 0) - fx = f; - else if(xbp = iallocb(len)){ - memmove(xbp->wp, pkt, len); - xbp->wp += len; - if(qpass(f->in, xbp) < 0) - ether->soverflows++; - } - else - ether->soverflows++; - } - else - etherrtrace(f, pkt, len); - } - } - - if(fx){ - if(qpass(fx->in, bp) < 0) - ether->soverflows++; - return 0; - } - if(fromwire){ - freeb(bp); - return 0; - } - - return bp; -} - -static int -etheroq(Ether* ether, Block* bp) -{ - int len, loopback, s; - Etherpkt *pkt; - - ether->outpackets++; - - /* - * Check if the packet has to be placed back onto the input queue, - * i.e. if it's a loopback or broadcast packet or the interface is - * in promiscuous mode. - * If it's a loopback packet indicate to etheriq that the data isn't - * needed and return, etheriq will pass-on or free the block. - * To enable bridging to work, only packets that were originated - * by this interface are fed back. - */ - pkt = (Etherpkt*)bp->rp; - len = BLEN(bp); - loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0; - if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){ - s = splhi(); - etheriq(ether, bp, 0); - splx(s); - } - - if(!loopback){ - qbwrite(ether->oq, bp); - if(ether->transmit != nil) - ether->transmit(ether); - }else - freeb(bp); - - return len; -} - -static long -etherwrite(Chan* chan, void* buf, long n, vlong) -{ - Ether *ether; - Block *bp; - int onoff; - Cmdbuf *cb; - long l; - - ether = etherxx[chan->dev]; - rlock(ether); - if(waserror()) { - runlock(ether); - nexterror(); - } - if(NETTYPE(chan->qid.path) != Ndataqid) { - l = netifwrite(ether, chan, buf, n); - if(l >= 0) - goto out; - cb = parsecmd(buf, n); - if(strcmp(cb->f[0], "nonblocking") == 0){ - if(cb->nf <= 1) - onoff = 1; - else - onoff = atoi(cb->f[1]); - qnoblock(ether->oq, onoff); - free(cb); - goto out; - } - free(cb); - if(ether->ctl!=nil){ - l = ether->ctl(ether,buf,n); - goto out; - } - error(Ebadctl); - } - - if(n > ether->maxmtu) - error(Etoobig); - if(n < ether->minmtu) - error(Etoosmall); - bp = allocb(n); - if(waserror()){ - freeb(bp); - nexterror(); - } - memmove(bp->rp, buf, n); - memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen); - bp->wp += n; - poperror(); - - l = etheroq(ether, bp); -out: - poperror(); - runlock(ether); - return l; -} - -static long -etherbwrite(Chan* chan, Block* bp, ulong) -{ - Ether *ether; - long n; - - n = BLEN(bp); - if(NETTYPE(chan->qid.path) != Ndataqid){ - if(waserror()) { - freeb(bp); - nexterror(); - } - n = etherwrite(chan, bp->rp, n, 0); - poperror(); - freeb(bp); - return n; - } - ether = etherxx[chan->dev]; - rlock(ether); - if(waserror()) { - runlock(ether); - nexterror(); - } - if(n > ether->maxmtu){ - freeb(bp); - error(Etoobig); - } - if(n < ether->minmtu){ - freeb(bp); - error(Etoosmall); - } - n = etheroq(ether, bp); - poperror(); - runlock(ether); - return n; -} - -static struct { - char* type; - int (*reset)(Ether*); -} cards[MaxEther+1]; - -void -addethercard(char* t, int (*r)(Ether*)) -{ - static int ncard; - - if(ncard == MaxEther) - panic("too many ether cards"); - cards[ncard].type = t; - cards[ncard].reset = r; - ncard++; -} - -int -parseether(uchar *to, char *from) -{ - char nip[4]; - char *p; - int i; - - p = from; - for(i = 0; i < Eaddrlen; i++){ - if(*p == 0) - return -1; - nip[0] = *p++; - if(*p == 0) - return -1; - nip[1] = *p++; - nip[2] = 0; - to[i] = strtoul(nip, 0, 16); - if(*p == ':') - p++; - } - return 0; -} - -static void -etherreset(void) -{ - Ether *ether; - int i, n, ctlrno; - char name[KNAMELEN], buf[128]; - - for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){ - if(ether == 0) - ether = malloc(sizeof(Ether)); - memset(ether, 0, sizeof(Ether)); - ether->ctlrno = ctlrno; - ether->mbps = 10; - ether->minmtu = ETHERMINTU; - ether->maxmtu = ETHERMAXTU; - ether->itype = -1; - - if(archether(ctlrno, ether) <= 0) - continue; - - for(n = 0; cards[n].type; n++){ - if(cistrcmp(cards[n].type, ether->type)) - continue; - for(i = 0; i < ether->nopt; i++){ - if(cistrncmp(ether->opt[i], "ea=", 3) == 0){ - if(parseether(ether->ea, ðer->opt[i][3]) == -1) - memset(ether->ea, 0, Eaddrlen); - }else if(cistrcmp(ether->opt[i], "fullduplex") == 0 || - cistrcmp(ether->opt[i], "10BASE-TFD") == 0) - ether->fullduplex = 1; - else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0) - ether->mbps = 100; - } - if(cards[n].reset(ether)) - break; - snprint(name, sizeof(name), "ether%d", ctlrno); - - if(ether->interrupt != nil) - intrenable(ether->itype, ether->irq, ether->interrupt, ether, name); - - i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %lud", - ctlrno, ether->type, ether->mbps, ether->port, ether->irq); - if(ether->mem) - i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem)); - if(ether->size) - i += sprint(buf+i, " size 0x%luX", ether->size); - i += sprint(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX", - ether->ea[0], ether->ea[1], ether->ea[2], - ether->ea[3], ether->ea[4], ether->ea[5]); - sprint(buf+i, "\n"); - iprint(buf); - - if(ether->mbps == 100){ - netifinit(ether, name, Ntypes, 256*1024); - if(ether->oq == 0) - ether->oq = qopen(256*1024, Qmsg, 0, 0); - } - else{ - netifinit(ether, name, Ntypes, 64*1024); - if(ether->oq == 0) - ether->oq = qopen(64*1024, Qmsg, 0, 0); - } - if(ether->oq == 0) - panic("etherreset %s", name); - ether->alen = Eaddrlen; - memmove(ether->addr, ether->ea, Eaddrlen); - memset(ether->bcast, 0xFF, Eaddrlen); - - etherxx[ctlrno] = ether; - ether = 0; - break; - } - } - if(ether) - free(ether); -} - -static void -etherpower(int on) -{ - int i; - Ether *ether; - - for(i = 0; i < MaxEther; i++){ - if((ether = etherxx[i]) == nil || ether->power == nil) - continue; - if(on){ - if(canrlock(ether)) - continue; - if(ether->power != nil) - ether->power(ether, on); - wunlock(ether); - }else{ - if(!canrlock(ether)) - continue; - wlock(ether); - if(ether->power != nil) - ether->power(ether, on); - /* Keep locked until power goes back on */ - } - } -} - -#define POLY 0xedb88320 - -/* really slow 32 bit crc for ethers */ -ulong -ethercrc(uchar *p, int len) -{ - int i, j; - ulong crc, b; - - crc = 0xffffffff; - for(i = 0; i < len; i++){ - b = *p++; - for(j = 0; j < 8; j++){ - crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0); - b >>= 1; - } - } - return crc; -} - -Dev etherdevtab = { - 'l', - "ether", - - etherreset, - devinit, - ethershutdown, - etherattach, - etherwalk, - etherstat, - etheropen, - ethercreate, - etherclose, - etherread, - etherbread, - etherwrite, - etherbwrite, - devremove, - etherwstat, - etherpower, -}; diff --git a/os/pxa/devrtc.c b/os/pxa/devrtc.c deleted file mode 100644 index ace6cc82..00000000 --- a/os/pxa/devrtc.c +++ /dev/null @@ -1,169 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#include "io.h" - -/* - * SA11x0 real time clock - * TO DO: alarms, wakeup, allow trim setting(?) - */ - -enum{ - Qdir, - Qrtc, - Qrtctrim, -}; - -static Dirtab rtcdir[]={ - ".", {Qdir,0,QTDIR}, 0, 0555, - "rtc", {Qrtc}, NUMSIZE, 0664, - "rtctrim", {Qrtctrim}, 0, 0664, -}; -#define NRTC (sizeof(rtcdir)/sizeof(rtcdir[0])) - -extern ulong boottime; - -enum { - RTSR_al= 1<<0, /* RTC alarm detected */ - RTSR_hz= 1<<1, /* 1-Hz rising-edge detected */ - RTSR_ale= 1<<2, /* RTC alarm interrupt enabled */ - RTSR_hze= 1<<3, /* 1-Hz interrupt enable */ -}; - -static void -rtcreset(void) -{ - RTCreg *r; - - r = RTCREG; - if((r->rttr & 0xFFFF) == 0){ /* reset state */ - r->rttr = 32768-1; - r->rcnr = boottime; /* typically zero */ - } - r->rtar = ~0; - r->rtsr = RTSR_al | RTSR_hz; -} - -static Chan* -rtcattach(char *spec) -{ - return devattach('r', spec); -} - -static Walkqid* -rtcwalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, rtcdir, NRTC, devgen); -} - -static int -rtcstat(Chan *c, uchar *dp, int n) -{ - return devstat(c, dp, n, rtcdir, NRTC, devgen); -} - -static Chan* -rtcopen(Chan *c, int omode) -{ - return devopen(c, omode, rtcdir, NRTC, devgen); -} - -static void -rtcclose(Chan*) -{ -} - -static long -rtcread(Chan *c, void *buf, long n, vlong off) -{ - if(c->qid.type & QTDIR) - return devdirread(c, buf, n, rtcdir, NRTC, devgen); - - switch((ulong)c->qid.path){ - case Qrtc: - return readnum(off, buf, n, RTCREG->rcnr, NUMSIZE); - case Qrtctrim: - return readnum(off, buf, n, RTCREG->rttr, NUMSIZE); - } - error(Egreg); - return 0; /* not reached */ -} - -static long -rtcwrite(Chan *c, void *buf, long n, vlong off) -{ - ulong offset = off; - ulong secs; - char *cp, sbuf[32]; - - switch((ulong)c->qid.path){ - case Qrtc: - /* - * write the time - */ - if(offset != 0 || n >= sizeof(sbuf)-1) - error(Ebadarg); - memmove(sbuf, buf, n); - sbuf[n] = '\0'; - cp = sbuf; - while(*cp){ - if(*cp>='0' && *cp<='9') - break; - cp++; - } - secs = strtoul(cp, 0, 0); - RTCREG->rcnr = secs; - return n; - - case Qrtctrim: - if(offset != 0 || n >= sizeof(sbuf)-1) - error(Ebadarg); - memmove(sbuf, buf, n); - sbuf[n] = '\0'; - RTCREG->rttr = strtoul(sbuf, 0, 0); - return n; - } - error(Egreg); - return 0; /* not reached */ -} - -static void -rtcpower(int on) -{ - if(on) - boottime = RTCREG->rcnr - TK2SEC(MACHP(0)->ticks); - else - RTCREG->rcnr = seconds(); -} - -long -rtctime(void) -{ - return RTCREG->rcnr; -} - -Dev rtcdevtab = { - 'r', - "rtc", - - rtcreset, - devinit, - devshutdown, - rtcattach, - rtcwalk, - rtcstat, - rtcopen, - devcreate, - rtcclose, - rtcread, - devbread, - rtcwrite, - devbwrite, - devremove, - devwstat, - rtcpower, -}; diff --git a/os/pxa/devuart.c b/os/pxa/devuart.c deleted file mode 100644 index 13b2107a..00000000 --- a/os/pxa/devuart.c +++ /dev/null @@ -1,1073 +0,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/netif.h" - -/* - * Driver for the uart. - * TO DO: replace by uartpxa.c - */ -enum -{ - /* - * register numbers - */ - Data= 0, /* xmit/rcv buffer */ - Iena= 1, /* interrupt enable */ - Ircv= (1<<0), /* for char rcv'd */ - Ixmt= (1<<1), /* for xmit buffer empty */ - Irstat=(1<<2), /* for change in rcv'er status */ - Imstat=(1<<3), /* for change in modem status */ - Rtoie= 1<<4, /* character timeout indication */ - Nrze= 1<<5, /* NRZ encoding enabled */ - Uue= 1<<6, /* Uart unit enabled */ - Dmae= 1<<7, /* DMA requests enabled */ - Istat= 2, /* interrupt flag (read) */ - Ipend= 1, /* interrupt pending (not) */ - Fenabd=(3<<6), /* on if fifo's enabled */ - Fifoctl=2, /* fifo control (write) */ - Fena= (1<<0), /* enable xmit/rcv fifos */ - Fdma= (1<<3), /* dma on */ - Ftrig= (1<<6), /* trigger after 4 input characters */ - Fclear=(3<<1), /* clear xmit & rcv fifos */ - Format= 3, /* byte format */ - Bits8= (3<<0), /* 8 bits/byte */ - Stop2= (1<<2), /* 2 stop bits */ - Pena= (1<<3), /* generate parity */ - Peven= (1<<4), /* even parity */ - Pforce=(1<<5), /* force parity */ - Break= (1<<6), /* generate a break */ - Dra= (1<<7), /* address the divisor */ - Mctl= 4, /* modem control */ - Dtr= (1<<0), /* data terminal ready */ - Rts= (1<<1), /* request to send */ - Ri= (1<<2), /* ring */ - Inton= (1<<3), /* turn on interrupts */ - Loop= (1<<4), /* loop back */ - Lstat= 5, /* line status */ - Inready=(1<<0), /* receive buffer full */ - Oerror=(1<<1), /* receiver overrun */ - Perror=(1<<2), /* receiver parity error */ - Ferror=(1<<3), /* rcv framing error */ - Berror=(1<<4), /* break alarm */ - Outready=(1<<5), /* output buffer full */ - Mstat= 6, /* modem status */ - Ctsc= (1<<0), /* clear to send changed */ - Dsrc= (1<<1), /* data set ready changed */ - Rire= (1<<2), /* rising edge of ring indicator */ - Dcdc= (1<<3), /* data carrier detect changed */ - Cts= (1<<4), /* complement of clear to send line */ - Dsr= (1<<5), /* complement of data set ready line */ - Ringl= (1<<6), /* complement of ring indicator line */ - Dcd= (1<<7), /* complement of data carrier detect line */ - Scratch=7, /* scratchpad */ - Dlsb= 0, /* divisor lsb */ - Dmsb= 1, /* divisor msb */ - - CTLS= 023, - CTLQ= 021, - - Stagesize= 1024, - Nuart= 4, /* max per machine */ -}; - -typedef struct Uart Uart; -struct Uart -{ - QLock; - int opens; - - int enabled; - Uart *elist; /* next enabled interface */ - char name[KNAMELEN]; - - ulong sticky[8]; /* sticky write register values */ - void* regs; - ulong port; - ulong freq; /* clock frequency */ - uchar mask; /* bits/char */ - int dev; - int baud; /* baud rate */ - - uchar istat; /* last istat read */ - int frame; /* framing errors */ - int overrun; /* rcvr overruns */ - - /* buffers */ - int (*putc)(Queue*, int); - Queue *iq; - Queue *oq; - - Lock flock; /* fifo */ - uchar fifoon; /* fifo's enabled */ - uchar nofifo; /* earlier chip version with nofifo */ - - Lock rlock; /* receive */ - uchar istage[Stagesize]; - uchar *ip; - uchar *ie; - - int haveinput; - - Lock tlock; /* transmit */ - uchar ostage[Stagesize]; - uchar *op; - uchar *oe; - - int modem; /* hardware flow control on */ - int xonoff; /* software flow control on */ - int blocked; - int cts, dsr, dcd; /* keep track of modem status */ - int ctsbackoff; - int hup_dsr, hup_dcd; /* send hangup upstream? */ - int dohup; - - Rendez r; -}; - -static Uart *uart[Nuart]; -static int nuart; - -struct Uartalloc { - Lock; - Uart *elist; /* list of enabled interfaces */ -} uartalloc; - -static void uartintr(Uart*); - -/* - * pick up architecture specific routines and definitions - */ -#include "uart.h" - -/* - * set the baud rate by calculating and setting the baudrate - * generator constant. This will work with fairly non-standard - * baud rates. - */ -static void -uartsetbaud(Uart *p, int rate) -{ - ulong brconst; - - if(rate <= 0) - return; - - p->freq = archuartclock(p->port, rate); - if(p->freq == 0) - return; - - brconst = (p->freq+8*rate-1)/(16*rate); - - uartwrreg(p, Format, Dra); - uartwr(p, Dmsb, (brconst>>8) & 0xff); - uartwr(p, Dlsb, brconst & 0xff); - uartwrreg(p, Format, 0); - - p->baud = rate; -} - -/* - * decide if we should hangup when dsr or dcd drops. - */ -static void -uartdsrhup(Uart *p, int n) -{ - p->hup_dsr = n; -} - -static void -uartdcdhup(Uart *p, int n) -{ - p->hup_dcd = n; -} - -static void -uartparity(Uart *p, char type) -{ - switch(type){ - case 'e': - p->sticky[Format] |= Pena|Peven; - break; - case 'o': - p->sticky[Format] &= ~Peven; - p->sticky[Format] |= Pena; - break; - default: - p->sticky[Format] &= ~(Pena|Peven); - break; - } - uartwrreg(p, Format, 0); -} - -/* - * set bits/character, default 8 - */ -void -uartbits(Uart *p, int bits) -{ - if(bits < 5 || bits > 8) - error(Ebadarg); - - p->sticky[Format] &= ~3; - p->sticky[Format] |= bits-5; - - uartwrreg(p, Format, 0); -} - - -/* - * toggle DTR - */ -void -uartdtr(Uart *p, int n) -{ - if(n) - p->sticky[Mctl] |= Dtr; - else - p->sticky[Mctl] &= ~Dtr; - - uartwrreg(p, Mctl, 0); -} - -/* - * toggle RTS - */ -void -uartrts(Uart *p, int n) -{ - if(n) - p->sticky[Mctl] |= Rts; - else - p->sticky[Mctl] &= ~Rts; - - uartwrreg(p, Mctl, 0); -} - -/* - * send break - */ -static void -uartbreak(Uart *p, int ms) -{ - if(ms == 0) - ms = 200; - - uartwrreg(p, Format, Break); - tsleep(&up->sleep, return0, 0, ms); - uartwrreg(p, Format, 0); -} - -static void -uartfifoon(Uart *p) -{ - ulong i, x; - - if(p->nofifo || uartrdreg(p, Istat) & Fenabd) - return; - - x = splhi(); - - /* reset fifos */ - p->sticky[Fifoctl] = 0; - uartwrreg(p, Fifoctl, Fclear); - - /* empty buffer and interrupt conditions */ - for(i = 0; i < 16; i++){ - if(uartrdreg(p, Istat)){ - /* nothing to do */ - } - if(uartrdreg(p, Data)){ - /* nothing to do */ - } - } - - /* turn on fifo */ - p->fifoon = 1; - p->sticky[Fifoctl] = Fena|Ftrig; - uartwrreg(p, Fifoctl, 0); - p->istat = uartrdreg(p, Istat); - if((p->istat & Fenabd) == 0) { - /* didn't work, must be an earlier chip type */ - p->nofifo = 1; - } - - splx(x); -} - -/* - * modem flow control on/off (rts/cts) - */ -static void -uartmflow(Uart *p, int n) -{ - ilock(&p->tlock); - if(n){ - p->sticky[Iena] |= Imstat; - uartwrreg(p, Iena, 0); - p->modem = 1; - p->cts = uartrdreg(p, Mstat) & Cts; - } else { - p->sticky[Iena] &= ~Imstat; - uartwrreg(p, Iena, 0); - p->modem = 0; - p->cts = 1; - } - iunlock(&p->tlock); - -// ilock(&p->flock); -// if(1) -// /* turn on fifo's */ -// uartfifoon(p); -// else { -// /* turn off fifo's */ -// p->fifoon = 0; -// p->sticky[Fifoctl] = 0; -// uartwrreg(p, Fifoctl, Fclear); -// } -// iunlock(&p->flock); -} - -/* - * turn on a port's interrupts. set DTR and RTS - */ -static void -uartenable(Uart *p) -{ - Uart **l; - - if(p->enabled) - return; - - uartportpower(p, 1); - - p->hup_dsr = p->hup_dcd = 0; - p->cts = p->dsr = p->dcd = 0; - - /* - * turn on interrupts - */ - p->sticky[Iena] = Ircv | Ixmt | Irstat | Uue; - uartwrreg(p, Iena, 0); - - /* - * turn on DTR and RTS - */ - uartdtr(p, 1); - uartrts(p, 1); - - uartfifoon(p); - - /* - * assume we can send - */ - ilock(&p->tlock); - p->cts = 1; - p->blocked = 0; - iunlock(&p->tlock); - - /* - * set baud rate to the last used - */ - uartsetbaud(p, p->baud); - - lock(&uartalloc); - for(l = &uartalloc.elist; *l; l = &(*l)->elist){ - if(*l == p) - break; - } - if(*l == 0){ - p->elist = uartalloc.elist; - uartalloc.elist = p; - } - p->enabled = 1; - unlock(&uartalloc); -} - -/* - * turn off a port's interrupts. reset DTR and RTS - */ -static void -uartdisable(Uart *p) -{ - Uart **l; - - /* - * turn off interrupts - */ - p->sticky[Iena] = Uue; - uartwrreg(p, Iena, 0); - - /* - * revert to default settings - */ - p->sticky[Format] = Bits8; - uartwrreg(p, Format, 0); - - /* - * turn off DTR, RTS, hardware flow control & fifo's - */ - uartdtr(p, 0); - uartrts(p, 0); - uartmflow(p, 0); - ilock(&p->tlock); - p->xonoff = p->blocked = 0; - iunlock(&p->tlock); - - uartportpower(p, 0); - - lock(&uartalloc); - for(l = &uartalloc.elist; *l; l = &(*l)->elist){ - if(*l == p){ - *l = p->elist; - break; - } - } - p->enabled = 0; - unlock(&uartalloc); -} - -/* - * put some bytes into the local queue to avoid calling - * qconsume for every character - */ -static int -stageoutput(Uart *p) -{ - int n; - - n = qconsume(p->oq, p->ostage, Stagesize); - if(n <= 0) - return 0; - p->op = p->ostage; - p->oe = p->ostage + n; - return n; -} - -/* - * (re)start output - */ -static void -uartkick0(Uart *p) -{ - int i; - if((p->modem && (p->cts == 0)) || p->blocked) - return; - - /* - * 128 here is an arbitrary limit to make sure - * we don't stay in this loop too long. If the - * chips output queue is longer than 128, too - * bad -- presotto - */ - for(i = 0; i < 128; i++){ - if(!(uartrdreg(p, Lstat) & Outready)) - break; - if(p->op >= p->oe && stageoutput(p) == 0) - break; - uartwr(p, Data, *p->op++); - } -} - -static void -uartkick(void *v) -{ - Uart *p; - - p = v; - ilock(&p->tlock); - uartkick0(p); - iunlock(&p->tlock); -} - -/* - * restart input if it's off - */ -static void -uartflow(void *v) -{ - Uart *p; - - p = v; - if(p->modem) - uartrts(p, 1); - ilock(&p->rlock); - p->haveinput = 1; - iunlock(&p->rlock); -} - -/* - * default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts, - * transmit and receive enabled, interrupts disabled. - */ -static void -uartsetup0(Uart *p) -{ - memset(p->sticky, 0, sizeof(p->sticky)); - /* - * set rate to 9600 baud. - * 8 bits/character. - * 1 stop bit. - * interrupts enabled. - */ - p->sticky[Format] = Bits8; - uartwrreg(p, Format, 0); - p->sticky[Mctl] |= Inton; - uartwrreg(p, Mctl, 0x0); - -// uartsetbaud(p, 9600); - uartsetbaud(p, 38400); - - p->iq = qopen(4*1024, 0, uartflow, p); - p->oq = qopen(4*1024, 0, uartkick, p); - if(p->iq == nil || p->oq == nil) - panic("uartsetup0"); - - p->ip = p->istage; - p->ie = &p->istage[Stagesize]; - p->op = p->ostage; - p->oe = p->ostage; -} - -/* - * called by uartinstall() to create a new duart - */ -void -uartsetup(ulong port, void *regs, ulong freq, char *name) -{ - Uart *p; - - if(nuart >= Nuart) - return; - - p = xalloc(sizeof(Uart)); - uart[nuart] = p; - strcpy(p->name, name); - p->dev = nuart; - nuart++; - p->port = port; - p->regs = regs; - p->freq = freq; - uartsetup0(p); -} - -/* - * called by main() to configure a duart port as a console or a mouse - */ -void -uartspecial(int port, int baud, Queue **in, Queue **out, int (*putc)(Queue*, int)) -{ - Uart *p = uart[port]; - uartenable(p); - if(baud) - uartsetbaud(p, baud); - p->putc = putc; - if(in) - *in = p->iq; - if(out) - *out = p->oq; - p->opens++; -} - -/* - * handle an interrupt to a single uart - */ -static void -uartintr(Uart *p) -{ - uchar ch; - int s, l; - - for (s = uartrdreg(p, Istat); !(s&Ipend); s = uartrdreg(p, Istat)) { - switch(s&0x3f){ - case 4: /* received data available */ - case 6: /* receiver line status (alarm or error) */ - case 12: /* character timeout indication */ - while ((l = uartrdreg(p, Lstat)) & Inready) { - if(l & Ferror) - p->frame++; - if(l & Oerror) - p->overrun++; - ch = uartrdreg(p, Data) & 0xff; - if (l & (Berror|Perror|Ferror)) { - /* ch came with break, parity or framing error - consume */ - continue; - } - if (ch == CTLS || ch == CTLQ) { - ilock(&p->tlock); - if(p->xonoff){ - if(ch == CTLS) - p->blocked = 1; - else - p->blocked = 0; /* clock gets output going again */ - } - iunlock(&p->tlock); - } - if(p->putc) - p->putc(p->iq, ch); - else { - ilock(&p->rlock); - if(p->ip < p->ie) - *p->ip++ = ch; - else - p->overrun++; - p->haveinput = 1; - iunlock(&p->rlock); - } - } - break; - - case 2: /* transmitter not full */ - uartkick(p); - break; - - case 0: /* modem status */ - ch = uartrdreg(p, Mstat); - if(ch & Ctsc){ - ilock(&p->tlock); - l = p->cts; - p->cts = ch & Cts; - if(l == 0 && p->cts) - p->ctsbackoff = 2; /* clock gets output going again */ - iunlock(&p->tlock); - } - if (ch & Dsrc) { - l = ch & Dsr; - if(p->hup_dsr && p->dsr && !l){ - ilock(&p->rlock); - p->dohup = 1; - iunlock(&p->rlock); - } - p->dsr = l; - } - if (ch & Dcdc) { - l = ch & Dcd; - if(p->hup_dcd && p->dcd && !l){ - ilock(&p->rlock); - p->dohup = 1; - iunlock(&p->rlock); - } - p->dcd = l; - } - break; - - default: - iprint("weird uart interrupt #%2.2ux\n", s); - break; - } - } - p->istat = s; -} - -/* - * we save up input characters till clock time - * - * There's also a bit of code to get a stalled print going. - * It shouldn't happen, but it does. Obviously I don't - * understand something. Since it was there, I bundled a - * restart after flow control with it to give some hysteresis - * to the hardware flow control. This makes compressing - * modems happier but will probably bother something else. - * -- presotto - */ -void -uartclock(void) -{ - int n; - Uart *p; - - for(p = uartalloc.elist; p; p = p->elist){ - - /* this amortizes cost of qproduce to many chars */ - if(p->haveinput){ - ilock(&p->rlock); - if(p->haveinput){ - n = p->ip - p->istage; - if(n > 0 && p->iq){ - if(n > Stagesize) - panic("uartclock"); - if(qproduce(p->iq, p->istage, n) < 0) - uartrts(p, 0); - else - p->ip = p->istage; - } - p->haveinput = 0; - } - iunlock(&p->rlock); - } - if(p->dohup){ - ilock(&p->rlock); - if(p->dohup){ - qhangup(p->iq, 0); - qhangup(p->oq, 0); - } - p->dohup = 0; - iunlock(&p->rlock); - } - - /* this adds hysteresis to hardware flow control */ - if(p->ctsbackoff){ - ilock(&p->tlock); - if(p->ctsbackoff){ - if(--(p->ctsbackoff) == 0) - uartkick0(p); - } - iunlock(&p->tlock); - } - } -} - -Dirtab *uartdir; -int ndir; - -static void -setlength(int i) -{ - Uart *p; - - if(i >= 0){ - p = uart[i]; - if(p && p->opens && p->iq) - uartdir[1+3*i].length = qlen(p->iq); - } else for(i = 0; i < nuart; i++){ - p = uart[i]; - if(p && p->opens && p->iq) - uartdir[1+3*i].length = qlen(p->iq); - } -} - -/* - * all uarts must be uartsetup() by this point or inside of uartinstall() - */ -static void -uartreset(void) -{ - int i; - Dirtab *dp; - uartinstall(); /* architecture specific */ - - ndir = 1+3*nuart; - uartdir = xalloc(ndir * sizeof(Dirtab)); - dp = uartdir; - strcpy(dp->name, "."); - mkqid(&dp->qid, 0, 0, QTDIR); - dp->length = 0; - dp->perm = DMDIR|0555; - dp++; - for(i = 0; i < nuart; i++){ - /* 3 directory entries per port */ - strcpy(dp->name, uart[i]->name); - dp->qid.path = NETQID(i, Ndataqid); - dp->perm = 0666; - dp++; - sprint(dp->name, "%sctl", uart[i]->name); - dp->qid.path = NETQID(i, Nctlqid); - dp->perm = 0666; - dp++; - sprint(dp->name, "%sstatus", uart[i]->name); - dp->qid.path = NETQID(i, Nstatqid); - dp->perm = 0444; - dp++; - } -} - -static Chan* -uartattach(char *spec) -{ - return devattach('t', spec); -} - -static Walkqid* -uartwalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, uartdir, ndir, devgen); -} - -static int -uartstat(Chan *c, uchar *dp, int n) -{ - if(NETTYPE(c->qid.path) == Ndataqid) - setlength(NETID(c->qid.path)); - return devstat(c, dp, n, uartdir, ndir, devgen); -} - -static Chan* -uartopen(Chan *c, int omode) -{ - Uart *p; - - c = devopen(c, omode, uartdir, ndir, devgen); - - switch(NETTYPE(c->qid.path)){ - case Nctlqid: - case Ndataqid: - p = uart[NETID(c->qid.path)]; - qlock(p); - if(p->opens++ == 0){ - uartenable(p); - qreopen(p->iq); - qreopen(p->oq); - } - qunlock(p); - break; - } - - return c; -} - -static void -uartclose(Chan *c) -{ - Uart *p; - - if(c->qid.type & QTDIR) - return; - if((c->flag & COPEN) == 0) - return; - switch(NETTYPE(c->qid.path)){ - case Ndataqid: - case Nctlqid: - p = uart[NETID(c->qid.path)]; - qlock(p); - if(--(p->opens) == 0){ - uartdisable(p); - qclose(p->iq); - qclose(p->oq); - p->ip = p->istage; - p->dcd = p->dsr = p->dohup = 0; - } - qunlock(p); - break; - } -} - -static long -uartstatus(Chan*, Uart *p, void *buf, long n, long offset) -{ - uchar mstat, fstat, istat, tstat; - char str[256]; - - str[0] = 0; - tstat = p->sticky[Mctl]; - mstat = uartrdreg(p, Mstat); - istat = p->sticky[Iena]; - fstat = p->sticky[Format]; - snprint(str, sizeof str, - "b%d c%d d%d e%d l%d m%d p%c r%d s%d\n" - "%d %d %d%s%s%s%s%s\n", - - p->baud, - p->hup_dcd, - (tstat & Dtr) != 0, - p->hup_dsr, - (fstat & Bits8) + 5, - (istat & Imstat) != 0, - (fstat & Pena) ? ((fstat & Peven) ? 'e' : 'o') : 'n', - (tstat & Rts) != 0, - (fstat & Stop2) ? 2 : 1, - - p->dev, - p->frame, - p->overrun, - uartrdreg(p, Istat) & Fenabd ? " fifo" : "", - (mstat & Cts) ? " cts" : "", - (mstat & Dsr) ? " dsr" : "", - (mstat & Dcd) ? " dcd" : "", - (mstat & Ringl) ? " ring" : "" - ); - return readstr(offset, buf, n, str); -} - -static long -uartread(Chan *c, void *buf, long n, vlong off) -{ - Uart *p; - ulong offset = off; - - if(c->qid.type & QTDIR){ - setlength(-1); - return devdirread(c, buf, n, uartdir, ndir, devgen); - } - - p = uart[NETID(c->qid.path)]; - switch(NETTYPE(c->qid.path)){ - case Ndataqid: - return qread(p->iq, buf, n); - case Nctlqid: - return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE); - case Nstatqid: - return uartstatus(c, p, buf, n, offset); - } - - return 0; -} - -static void -uartctl(Uart *p, char *cmd) -{ - int i, n; - - /* let output drain for a while */ - for(i = 0; i < 16 && qlen(p->oq); i++) - tsleep(&p->r, (int(*)(void*))qlen, p->oq, 125); - - if(strncmp(cmd, "break", 5) == 0){ - uartbreak(p, 0); - return; - } - - - n = atoi(cmd+1); - switch(*cmd){ - case 'B': - case 'b': - uartsetbaud(p, n); - break; - case 'C': - case 'c': - uartdcdhup(p, n); - break; - case 'D': - case 'd': - uartdtr(p, n); - break; - case 'E': - case 'e': - uartdsrhup(p, n); - break; - case 'f': - case 'F': - qflush(p->oq); - break; - case 'H': - case 'h': - qhangup(p->iq, 0); - qhangup(p->oq, 0); - break; - case 'L': - case 'l': - uartbits(p, n); - break; - case 'm': - case 'M': - uartmflow(p, n); - break; - case 'n': - case 'N': - qnoblock(p->oq, n); - break; - case 'P': - case 'p': - uartparity(p, *(cmd+1)); - break; - case 'K': - case 'k': - uartbreak(p, n); - break; - case 'R': - case 'r': - uartrts(p, n); - break; - case 'Q': - case 'q': - qsetlimit(p->iq, n); - qsetlimit(p->oq, n); - break; - case 'W': - case 'w': - /* obsolete */ - break; - case 'X': - case 'x': - ilock(&p->tlock); - p->xonoff = n; - iunlock(&p->tlock); - break; - } -} - -static long -uartwrite(Chan *c, void *buf, long n, vlong) -{ - Uart *p; - char cmd[32]; - - if(c->qid.type & QTDIR) - error(Eperm); - - p = uart[NETID(c->qid.path)]; - - /* - * The fifo's turn themselves off sometimes. - * It must be something I don't understand. -- presotto - */ - lock(&p->flock); - if((p->istat & Fenabd) == 0 && p->fifoon && p->nofifo == 0) - uartfifoon(p); - unlock(&p->flock); - - switch(NETTYPE(c->qid.path)){ - case Ndataqid: - return qwrite(p->oq, buf, n); - case Nctlqid: - if(n >= sizeof(cmd)) - n = sizeof(cmd)-1; - memmove(cmd, buf, n); - cmd[n] = 0; - uartctl(p, cmd); - return n; - default: - error(Egreg); - return n; - } -} - -static int -uartwstat(Chan *c, uchar *dp, int n) -{ - Dir d; - Dirtab *dt; - - if(!iseve()) - error(Eperm); - if(c->qid.type & QTDIR) - error(Eperm); - if(NETTYPE(c->qid.path) == Nstatqid) - error(Eperm); - - dt = &uartdir[1+3 * NETID(c->qid.path)]; - n = convM2D(dp, n, &d, nil); - if(n == 0) - error(Eshortstat); - if(d.mode != ~0UL){ - d.mode &= 0666; - dt[0].perm = dt[1].perm = d.mode; - } - return n; -} - -Dev uartdevtab = { - 't', - "uart", - - uartreset, - devinit, - devshutdown, - uartattach, - uartwalk, - uartstat, - uartopen, - devcreate, - uartclose, - uartread, - devbread, - uartwrite, - devbwrite, - devremove, - uartwstat, -}; diff --git a/os/pxa/dma.c b/os/pxa/dma.c deleted file mode 100644 index 9fcdbb4f..00000000 --- a/os/pxa/dma.c +++ /dev/null @@ -1,244 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "io.h" - -#define DMAREGS ((Dmaregs*)PHYSDMA) -typedef struct Dmadesc Dmadesc; -typedef struct Dmaregs Dmaregs; - -struct Dmadesc { - ulong ddadr; /* next descriptor address (0 mod 16) */ - ulong dsadr; /* source address (0 mod 8 if external, 0 mod 4 internal) */ - ulong dtadr; /* target address (same) */ - ulong dcmd; /* command */ -}; - -struct Dmaregs { - ulong dcsr[16]; /* control and status */ - uchar pad0[0xF0-0x40]; - ulong dint; /* mask of interrupting channels: 0 is bit 0 */ - uchar pad1[0x100-0xF4]; - ulong drcmr[40]; - Dmadesc chan[16]; /* offset 0x200 */ -}; - -enum { - /* dcsr */ - DcsRun= 1<<31, /* start the channel */ - DcsNodesc= 1<<30, /* set if channel is in no-descriptor fetch mode */ - DcsStopirq= 1<<29, /* enable interrupt if channel is uninitialised or stopped */ - DcsReqpend= 1<<8, /* channel has pending request */ - DcsStopstate= 1<<3, /* channel is uninitialised or stopped */ - DcsEndintr= 1<<2, /* transaction complete, length now 0 */ - DcsStartintr= 1<<1, /* successful descriptor fetch */ - DcsBuserr= 1<<0, /* bus error */ - - /* drcmr */ - DmrValid= 1<<7, /* mapped to channel given by bits 0-3 */ - DmrChan= 0xF, /* channel number mask */ - - /* ddadr */ - DdaStop= 1<<1, /* =0, run channel; =1, stop channel after this descriptor */ - - /* dcmd */ - DcmIncsrc= 1<<31, /* increment source address after use */ - DcmIncdest= 1<<30, /* increment destination address after use */ - DcmFlowsrc= 1<<29, /* enable flow control on source */ - DcmFlowdest= 1<<28, /* enable flow control on target */ - DcmStartirq= 1<<22, /* interrupt when descriptor loaded (fetch mode) */ - DcmEndirq= 1<<21, /* interrupt when transfer complete */ - DcmEndian= 1<<18, /* must be zero (little endian) */ - DcmBurst8= 1<<16, /* burst size in bytes */ - DcmBurst16= 2<<16, - DcmBurst32= 3<<16, - DcmWidth0= 0<<14, /* width for external memory */ - DcmWidth1= 1<<14, /* width of on-chip peripheral */ - DcmWidth2= 2<<14, - DcmWidth4= 3<<14, - DcmLength= (1<<13)-1, - - Ndma= 16, /* number of dma channels */ - MaxDMAbytes= 8192-1, /* annoyingly small limit */ -}; - -struct Dma { - int chan; - Dmadesc* desc; - Dmadesc stop; - ulong *csr; - void (*interrupt)(void*, ulong); - void* arg; - Rendez r; - ulong attrs; /* transfer attributes: flow control, burst size, width */ -}; - -static struct { - Lock; - ulong avail; - Dma dma[Ndma]; -} dmachans; - -static void dmaintr(Ureg*, void*); - -void -dmareset(void) -{ - int i; - Dma *d; - - for(i=0; ichan = i; - d->csr = &DMAREGS->dcsr[i]; - d->desc = &DMAREGS->chan[i]; - d->stop.ddadr = (ulong)&d->stop | DdaStop; - d->stop.dcmd = 0; - } - intrenable(IRQ, IRQdma, dmaintr, nil, "dma"); -} - -/* - * allocate a DMA channel, reset it, and configure it for the given device - */ -Dma* -dmasetup(int owner, void (*interrupt)(void*, ulong), void *arg, ulong attrs) -{ - Dma *d; - Dmadesc *dc; - int i; - - ilock(&dmachans); - for(i=0; (dmachans.avail & (1<= Ndma){ - iunlock(&dmachans); - return nil; - } - dmachans.avail &= ~(1<owner = owner; - d->interrupt = interrupt; - d->arg = arg; - d->attrs = attrs; - dc = d->desc; - dc->ddadr = (ulong)&d->stop | DdaStop; /* empty list */ - dc->dcmd = 0; - *d->csr = DcsEndintr | DcsStartintr | DcsBuserr; /* clear status, stopped */ - DMAREGS->drcmr[owner] = DmrValid | i; - return d; -} - -void -dmafree(Dma *dma) -{ - dmastop(dma); - DMAREGS->drcmr[d->owner] = 0; - ilock(&dmachans); - dmachans.avail |= 1<chan; - dma->interrupt = nil; - iunlock(&dmachans); -} - -/* - * simple dma transfer on a channel, using `no fetch descriptor' mode. - * virtual buffer addresses are assumed to refer to contiguous physical addresses. - */ -int -dmastart(Dma *dma, void *from, void *to, int nbytes) -{ - Dmadesc *dc; - - if((ulong)nbytes > MaxDMAbytes) - panic("dmastart"); - if((*dma->csr & DcsStopstate) == 0) - return 0; /* busy */ - dc = dma->desc; - dc->ddadr = DdaStop; - dc->dsadr = PADDR(from); - dc->dtadr = PADDR(to); - dc->dcmd = dma->attrs | DcmEndirq | nbytes; - *dma->csr = DcsRun | DcsNodesc | DcsEndintr | DcsStartintr | DcsBuserr; - return 1; -} - -/* - * stop dma on a channel - */ -void -dmastop(Dma *dma) -{ - *dma->csr = 0; - while((*dma->csr & DcsStopstate) == 0) - ; - *dma->csr = DcsStopstate; -} - -/* - * return nonzero if there was a memory error during DMA, - * and clear the error state - */ -int -dmaerror(Dma *dma) -{ - ulong e; - - e = *dma->csr & DcsBuserr; - *dma->csr |= e; - return e; -} - -/* - * return nonzero if the DMA channel is not busy - */ -int -dmaidle(Dma *d) -{ - return (*d->csr & DcsStopstate) == 0; -} - -static int -dmaidlep(void *a) -{ - return dmaidle((Dma*)a); -} - -void -dmawait(Dma *d) -{ - while(!dmaidle(d)) - sleep(&d->r, dmaidlep, d); -} - -/* - * this interface really only copes with one buffer at once - */ -static void -dmaintr(Ureg*, void*) -{ - Dma *d; - Dmaregs *dr; - int i; - ulong s, csr; - - dr = DMAREGS; - s = dr->dint; - dr->dint = s; - for(i=0; icsr; - if(csr & DcsBuserr) - iprint("DMA error, chan %d status #%8.8lux\n", d->chan, csr); - *d->csr = csr & (DcsRun | DcsNodesc | DcsEndintr | DcsStartintr | DcsBuserr); - if(d->interrupt != nil) - d->interrupt(d->arg, csr); - else - wakeup(&d->r); - } -} diff --git a/os/pxa/etherif.h b/os/pxa/etherif.h deleted file mode 100644 index 5c5c679b..00000000 --- a/os/pxa/etherif.h +++ /dev/null @@ -1,41 +0,0 @@ -enum { - MaxEther = 3, - Ntypes = 8, -}; - -typedef struct Ether Ether; -struct Ether { -RWlock; /* TO DO */ - ISAConf; /* hardware info */ - int ctlrno; - int minmtu; - int maxmtu; - uchar ea[Eaddrlen]; - int encry; - - void (*attach)(Ether*); /* filled in by reset routine */ - void (*closed)(Ether*); - void (*detach)(Ether*); - void (*transmit)(Ether*); - void (*interrupt)(Ureg*, void*); - long (*ifstat)(Ether*, void*, long, ulong); - long (*ctl)(Ether*, void*, long); /* custom ctl messages */ - void (*power)(Ether*, int); /* power on/off */ - void (*shutdown)(Ether*); /* shutdown hardware before reboot */ - void *ctlr; - int pcmslot; /* PCMCIA */ - int fullduplex; /* non-zero if full duplex */ - - Queue* oq; - - Netif; -}; - -extern Block* etheriq(Ether*, Block*, int); -extern void addethercard(char*, int(*)(Ether*)); -extern int archether(int, Ether*); - -#define NEXT(x, l) (((x)+1)%(l)) -#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1) -#define HOWMANY(x, y) (((x)+((y)-1))/(y)) -#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) diff --git a/os/pxa/fpi.h b/os/pxa/fpi.h deleted file mode 100644 index abaa7c12..00000000 --- a/os/pxa/fpi.h +++ /dev/null @@ -1,61 +0,0 @@ -typedef long Word; -typedef unsigned long Single; -typedef struct { - unsigned long l; - unsigned long h; -} Double; - -enum { - FractBits = 28, - CarryBit = 0x10000000, - HiddenBit = 0x08000000, - MsBit = HiddenBit, - NGuardBits = 3, - GuardMask = 0x07, - LsBit = (1<e >= ExpInfinity) -#define IsInfinity(n) (IsWeird(n) && (n)->h == HiddenBit && (n)->l == 0) -#define SetInfinity(n) ((n)->e = ExpInfinity, (n)->h = HiddenBit, (n)->l = 0) -#define IsNaN(n) (IsWeird(n) && (((n)->h & ~HiddenBit) || (n)->l)) -#define SetQNaN(n) ((n)->s = 0, (n)->e = ExpInfinity, \ - (n)->h = HiddenBit|(LsBit<<1), (n)->l = 0) -#define IsZero(n) ((n)->e == 1 && (n)->h == 0 && (n)->l == 0) -#define SetZero(n) ((n)->e = 1, (n)->h = 0, (n)->l = 0) - -/* - * fpi.c - */ -extern void fpiround(Internal *); -extern void fpiadd(Internal *, Internal *, Internal *); -extern void fpisub(Internal *, Internal *, Internal *); -extern void fpimul(Internal *, Internal *, Internal *); -extern void fpidiv(Internal *, Internal *, Internal *); -extern int fpicmp(Internal *, Internal *); -extern void fpinormalise(Internal*); - -/* - * fpimem.c - */ -extern void fpis2i(Internal *, void *); -extern void fpid2i(Internal *, void *); -extern void fpiw2i(Internal *, void *); -extern void fpii2s(void *, Internal *); -extern void fpii2d(void *, Internal *); -extern void fpii2w(Word *, Internal *); diff --git a/os/pxa/fpiarm.c b/os/pxa/fpiarm.c deleted file mode 100644 index 4acfcd1d..00000000 --- a/os/pxa/fpiarm.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * this doesn't attempt to implement ARM floating-point properties - * that aren't visible in the Inferno environment. - * all arithmetic is done in double precision. - * the FP trap status isn't updated. - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#include "ureg.h" - -#include "fpi.h" - -// #define R13OK undef this if correct kernel r13 isn't in Ureg; check calculation in fpiarm below - -#define REG(x) (*(long*)(((char*)(ur))+roff[(x)])) -#define FPENV (*(ufp)) -#define FR(x) (*(Internal*)(ufp)->regs[(x)&7]) - -/* BUG: check fetch (not worthwhile in Inferno) */ -#define getubyte(a) (*(uchar*)(a)) -#define getuword(a) (*(ushort*)(a)) -#define getulong(a) (*(ulong*)(a)) - -typedef struct FP2 FP2; -typedef struct FP1 FP1; - -struct FP2 { - char* name; - void (*f)(Internal, Internal, Internal*); -}; - -struct FP1 { - char* name; - void (*f)(Internal*, Internal*); -}; - -enum { - N = 1<<31, - Z = 1<<30, - C = 1<<29, - V = 1<<28, - REGPC = 15, -}; - -int fpemudebug = 0; - -#undef OFR -#define OFR(X) ((ulong)&((Ureg*)0)->X) - -static int roff[] = { - OFR(r0), OFR(r1), OFR(r2), OFR(r3), - OFR(r4), OFR(r5), OFR(r6), OFR(r7), - OFR(r8), OFR(r9), OFR(r10), OFR(r11), -#ifdef R13OK - OFR(r12), OFR(r13), OFR(r14), OFR(pc), -#else - OFR(r12), OFR(type), OFR(r14), OFR(pc), -#endif -}; - -static Internal fpconst[8] = { /* indexed by op&7 */ - /* s, e, l, h */ - {0, 0x1, 0x00000000, 0x00000000}, /* 0.0 */ - {0, 0x3FF, 0x00000000, 0x08000000}, /* 1.0 */ - {0, 0x400, 0x00000000, 0x08000000}, /* 2.0 */ - {0, 0x400, 0x00000000, 0x0C000000}, /* 3.0 */ - {0, 0x401, 0x00000000, 0x08000000}, /* 4.0 */ - {0, 0x401, 0x00000000, 0x0A000000}, /* 5.0 */ - {0, 0x3FE, 0x00000000, 0x08000000}, /* 0.5 */ - {0, 0x402, 0x00000000, 0x0A000000}, /* 10.0 */ -}; - -/* - * arm binary operations - */ - -static void -fadd(Internal m, Internal n, Internal *d) -{ - (m.s == n.s? fpiadd: fpisub)(&m, &n, d); -} - -static void -fsub(Internal m, Internal n, Internal *d) -{ - m.s ^= 1; - (m.s == n.s? fpiadd: fpisub)(&m, &n, d); -} - -static void -fsubr(Internal m, Internal n, Internal *d) -{ - n.s ^= 1; - (n.s == m.s? fpiadd: fpisub)(&n, &m, d); -} - -static void -fmul(Internal m, Internal n, Internal *d) -{ - fpimul(&m, &n, d); -} - -static void -fdiv(Internal m, Internal n, Internal *d) -{ - fpidiv(&m, &n, d); -} - -static void -fdivr(Internal m, Internal n, Internal *d) -{ - fpidiv(&n, &m, d); -} - -/* - * arm unary operations - */ - -static void -fmov(Internal *m, Internal *d) -{ - *d = *m; -} - -static void -fmovn(Internal *m, Internal *d) -{ - *d = *m; - d->s ^= 1; -} - -static void -fabsf(Internal *m, Internal *d) -{ - *d = *m; - d->s = 0; -} - -static void -frnd(Internal *m, Internal *d) -{ - short e; - - (m->s? fsub: fadd)(fpconst[6], *m, d); - if(IsWeird(d)) - return; - fpiround(d); - e = (d->e - ExpBias) + 1; - if(e <= 0) - SetZero(d); - else if(e > FractBits){ - if(e < 2*FractBits) - d->l &= ~((1<<(2*FractBits - e))-1); - }else{ - d->l = 0; - if(e < FractBits) - d->h &= ~((1<<(FractBits-e))-1); - } -} - -static FP1 optab1[16] = { /* Fd := OP Fm */ -[0] {"MOVF", fmov}, -[1] {"NEGF", fmovn}, -[2] {"ABSF", fabsf}, -[3] {"RNDF", frnd}, -[4] {"SQTF", /*fsqt*/0}, -/* LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN all `deprecated' */ -/* URD and NRM aren't implemented */ -}; - -static FP2 optab2[16] = { /* Fd := Fn OP Fm */ -[0] {"ADDF", fadd}, -[1] {"MULF", fmul}, -[2] {"SUBF", fsub}, -[3] {"RSUBF", fsubr}, -[4] {"DIVF", fdiv}, -[5] {"RDIVF", fdivr}, -/* POW, RPW deprecated */ -[8] {"REMF", /*frem*/0}, -[9] {"FMF", fmul}, /* fast multiply */ -[10] {"FDV", fdiv}, /* fast divide */ -[11] {"FRD", fdivr}, /* fast reverse divide */ -/* POL deprecated */ -}; - -static ulong -fcmp(Internal *n, Internal *m) -{ - int i; - - if(IsWeird(m) || IsWeird(n)){ - /* BUG: should trap if not masked */ - return V|C; - } - i = fpicmp(n, m); - if(i > 0) - return C; - else if(i == 0) - return C|Z; - else - return N; -} - -static void -fld(void (*f)(Internal*, void*), int d, ulong ea, int n, FPenv *ufp) -{ - void *mem; - - mem = (void*)ea; - (*f)(&FR(d), mem); - if(fpemudebug) - print("MOV%c #%lux, F%d\n", n==8? 'D': 'F', ea, d); -} - -static void -fst(void (*f)(void*, Internal*), ulong ea, int s, int n, FPenv *ufp) -{ - Internal tmp; - void *mem; - - mem = (void*)ea; - tmp = FR(s); - if(fpemudebug) - print("MOV%c F%d,#%lux\n", n==8? 'D': 'F', s, ea); - (*f)(mem, &tmp); -} - -static int -condok(int cc, int c) -{ - switch(c){ - case 0: /* Z set */ - return cc&Z; - case 1: /* Z clear */ - return (cc&Z) == 0; - case 2: /* C set */ - return cc&C; - case 3: /* C clear */ - return (cc&C) == 0; - case 4: /* N set */ - return cc&N; - case 5: /* N clear */ - return (cc&N) == 0; - case 6: /* V set */ - return cc&V; - case 7: /* V clear */ - return (cc&V) == 0; - case 8: /* C set and Z clear */ - return cc&C && (cc&Z) == 0; - case 9: /* C clear or Z set */ - return (cc&C) == 0 || cc&Z; - case 10: /* N set and V set, or N clear and V clear */ - return (~cc&(N|V))==0 || (cc&(N|V)) == 0; - case 11: /* N set and V clear, or N clear and V set */ - return (cc&(N|V))==N || (cc&(N|V))==V; - case 12: /* Z clear, and either N set and V set or N clear and V clear */ - return (cc&Z) == 0 && ((~cc&(N|V))==0 || (cc&(N|V))==0); - case 13: /* Z set, or N set and V clear or N clear and V set */ - return (cc&Z) || (cc&(N|V))==N || (cc&(N|V))==V; - case 14: /* always */ - return 1; - case 15: /* never (reserved) */ - return 0; - } - return 0; /* not reached */ -} - -static void -unimp(ulong pc, ulong op) -{ - char buf[60]; - - snprint(buf, sizeof(buf), "sys: fp: pc=%lux unimp fp 0x%.8lux", pc, op); - if(fpemudebug) - print("FPE: %s\n", buf); - error(buf); - /* no return */ -} - -static void -fpemu(ulong pc, ulong op, Ureg *ur, FPenv *ufp) -{ - int rn, rd, tag, o; - long off; - ulong ea; - Internal tmp, *fm, *fn; - - /* note: would update fault status here if we noted numeric exceptions */ - - /* - * LDF, STF; 10.1.1 - */ - if(((op>>25)&7) == 6){ - if(op & (1<<22)) - unimp(pc, op); /* packed or extended */ - rn = (op>>16)&0xF; - off = (op&0xFF)<<2; - if((op & (1<<23)) == 0) - off = -off; - ea = REG(rn); - if(rn == REGPC) - ea += 8; - if(op & (1<<24)) - ea += off; - rd = (op>>12)&7; - if(op & (1<<20)){ - if(op & (1<<15)) - fld(fpid2i, rd, ea, 8, ufp); - else - fld(fpis2i, rd, ea, 4, ufp); - }else{ - if(op & (1<<15)) - fst(fpii2d, ea, rd, 8, ufp); - else - fst(fpii2s, ea, rd, 4, ufp); - } - if((op & (1<<24)) == 0) - ea += off; - if(op & (1<<21)) - REG(rn) = ea; - return; - } - - /* - * CPRT/transfer, 10.3 - */ - if(op & (1<<4)){ - rd = (op>>12) & 0xF; - - /* - * compare, 10.3.1 - */ - if(rd == 15 && op & (1<<20)){ - rn = (op>>16)&7; - fn = &FR(rn); - if(op & (1<<3)){ - fm = &fpconst[op&7]; - tag = 'C'; - }else{ - fm = &FR(op&7); - tag = 'F'; - } - switch((op>>21)&7){ - default: - unimp(pc, op); - case 4: /* CMF: Fn :: Fm */ - case 6: /* CMFE: Fn :: Fm (with exception) */ - ur->psr &= ~(N|C|Z|V); - ur->psr |= fcmp(fn, fm); - break; - case 5: /* CNF: Fn :: -Fm */ - case 7: /* CNFE: Fn :: -Fm (with exception) */ - tmp = *fm; - tmp.s ^= 1; - ur->psr &= ~(N|C|Z|V); - ur->psr |= fcmp(fn, &tmp); - break; - } - if(fpemudebug) - print("CMPF %c%d,F%ld =%x\n", tag, rn, op&7, ur->psr>>28); - return; - } - - /* - * other transfer, 10.3 - */ - switch((op>>20)&0xF){ - default: - unimp(pc, op); - case 0: /* FLT */ - rn = (op>>16) & 7; - fpiw2i(&FR(rn), ®(rd)); - if(fpemudebug) - print("MOVW[FD] R%d, F%d\n", rd, rn); - break; - case 1: /* FIX */ - if(op & (1<<3)) - unimp(pc, op); - rn = op & 7; - tmp = FR(rn); - fpii2w(®(rd), &tmp); - if(fpemudebug) - print("MOV[FD]W F%d, R%d =%ld\n", rn, rd, REG(rd)); - break; - case 2: /* FPSR := Rd */ - FPENV.status = REG(rd); - if(fpemudebug) - print("MOVW R%d, FPSR\n", rd); - break; - case 3: /* Rd := FPSR */ - REG(rd) = FPENV.status; - if(fpemudebug) - print("MOVW FPSR, R%d\n", rd); - break; - case 4: /* FPCR := Rd */ - FPENV.control = REG(rd); - if(fpemudebug) - print("MOVW R%d, FPCR\n", rd); - break; - case 5: /* Rd := FPCR */ - REG(rd) = FPENV.control; - if(fpemudebug) - print("MOVW FPCR, R%d\n", rd); - break; - } - return; - } - - /* - * arithmetic - */ - - if(op & (1<<3)){ /* constant */ - fm = &fpconst[op&7]; - tag = 'C'; - }else{ - fm = &FR(op&7); - tag = 'F'; - } - rd = (op>>12)&7; - o = (op>>20)&0xF; - if(op & (1<<15)){ /* monadic */ - FP1 *fp; - fp = &optab1[o]; - if(fp->f == nil) - unimp(pc, op); - if(fpemudebug) - print("%s %c%ld,F%d\n", fp->name, tag, op&7, rd); - (*fp->f)(fm, &FR(rd)); - } else { - FP2 *fp; - fp = &optab2[o]; - if(fp->f == nil) - unimp(pc, op); - rn = (op>>16)&7; - if(fpemudebug) - print("%s %c%ld,F%d,F%d\n", fp->name, tag, op&7, rn, rd); - (*fp->f)(*fm, FR(rn), &FR(rd)); - } -} - -/* - * returns the number of FP instructions emulated - */ -int -fpiarm(Ureg *ur) -{ - ulong op, o; - FPenv *ufp; - int n; - -#ifndef R13OK -/* ur->type = &ur->pc+1; /* calculate kernel sp/R13 and put it here for roff[13] */ - ur->type = (ulong)(ur + 1); -#endif - if (up == nil) - panic("fpiarm not in a process"); - ufp = &up->env->fpu; /* because all the state is in Osenv, it need not be saved/restored */ - if(ufp->fpistate != FPACTIVE) { - ufp->fpistate = FPACTIVE; - ufp->control = 0; - ufp->status = (0x01<<28)|(1<<12); /* software emulation, alternative C flag */ - for(n = 0; n < 8; n++) - FR(n) = fpconst[0]; - } - for(n=0;;n++){ - op = getulong(ur->pc); - o = (op>>24) & 0xF; - if(((op>>8) & 0xF) != 1 || o != 0xE && (o&~1) != 0xC) - break; - if(condok(ur->psr, op>>28)) - fpemu(ur->pc, op, ur, ufp); - ur->pc += 4; - if(anyhigher()) - sched(); - } - return n; -} diff --git a/os/pxa/gpio.c b/os/pxa/gpio.c deleted file mode 100644 index 5914f8c4..00000000 --- a/os/pxa/gpio.c +++ /dev/null @@ -1,88 +0,0 @@ -#include "u.h" -#include "mem.h" -#include "../port/lib.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -static ulong gpioreserved[3]; -static Lock gpiolock; - -void -gpioreserve(int n) -{ - ulong mask, *r; - - r = &gpioreserved[GPR(n)]; - mask = GPB(n); - ilock(&gpiolock); - if(*r & mask) - panic("gpioreserve: duplicate use of GPIO %d", n); - *r |= mask; - iunlock(&gpiolock); -} - -/* - * set direction and alternative function bits in the GPIO control register, - * following the configuration bits in cfg. - */ -void -gpioconfig(int n, ulong cfg) -{ - GpioReg *g; - ulong o, m, *r; - - m = GPB(n); - o = n>>5; - ilock(&gpiolock); - g = GPIOREG; - r = &g->gpdr[o]; - if(cfg & Gpio_out) - *r |= m; - else - *r &= ~m; - r = &g->gafr[o*2]; - *r = (*r & ~GPAF(n, 3)) | GPAF(n, cfg&3); - iunlock(&gpiolock); -} - -ulong -gpioget(int n) -{ - ulong mask, o; - - mask = GPB(n); - o = GPR(n); - return GPIOREG->gplr[o] & mask; -} - -void -gpioset(int n, int v) -{ - GpioReg *g; - ulong mask, o; - - g = GPIOREG; - mask = GPB(n); - o = GPR(n); - ilock(&gpiolock); - if(v) - g->gpsr[o] = mask; - else - g->gpcr[o] = mask; - iunlock(&gpiolock); -} - -void -gpiorelease(int n) -{ - ulong mask, *r; - - mask = GPB(n); - r = &gpioreserved[GPR(n)]; - ilock(&gpiolock); - if((*r & mask) != mask) - panic("gpiorelease: unexpected release of GPIO %d", n); - *r &= ~mask; - iunlock(&gpiolock); -} diff --git a/os/pxa/i2c.c b/os/pxa/i2c.c deleted file mode 100644 index b45542ae..00000000 --- a/os/pxa/i2c.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * basic read/write interface to PXA25x I⁲C bus (master mode) - * 7 bit addressing only. - * TO DO: - * - enable unit clock - */ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "io.h" - -typedef struct Ctlr Ctlr; -typedef struct I2Cregs I2Cregs; -struct I2Cregs { - ulong ibmr; /* bus monitor */ - ulong pad0; - ulong idbr; /* data buffer */ - ulong pad1; - ulong icr; /* control */ - ulong pad2; - ulong isr; /* status */ - ulong pad3; - ulong isar; /* slave address */ -}; - -enum { - /* ibmr */ - Scls= 1<<1, /* SCL pin status */ - Sdas= 1<<0, /* SDA pin status */ - - /* icr */ - Fm= 1<<15, /* =0, 100 kb/sec; =1, 400 kb/sec */ - Ur= 1<<14, /* reset the i2c unit only */ - Sadie= 1<<13, /* slave address detected interrupt enable */ - Aldie= 1<<12, /* arbitration loss detected interrupt enable (master mode) */ - Ssdie= 1<<11, /* stop detected interrupt enable (slave mode) */ - Beie= 1<<10, /* bus error interrupt enable */ - Irfie= 1<<9, /* idbr receive full, interrupt enable */ - Iteie= 1<<8, /* idbr transmit empty interrupt enable */ - Gcd= 1<<7, /* disable response to general call message (slave); must be set if master uses g.c. */ - Scle= 1<<6, /* SCL enable: enable clock output for master mode */ - Iue= 1<<5, /* enable i2c (default: slave) */ - Ma= 1<<4, /* master abort (send STOP without data) */ - Tb= 1<<3, /* transfer byte on i2c bus */ - Ack= 0<<2, - Nak= 1<<2, - Stop= 1<<1, /* send a stop */ - Start= 1<<0, /* send a stop */ - - /* isr */ - Bed= 1<<10, /* bus error detected */ - Sad= 1<<9, /* slave address detected */ - Gcad= 1<<8, /* general call address detected */ - Irf= 1<<7, /* idbr receive full */ - Ite= 1<<6, /* idbr transmit empty */ - Ald= 1<<5, /* arbitration loss detected (multi-master) */ - Ssd= 1<<4, /* slave stop detected */ - Ibb= 1<<3, /* i2c bus is busy */ - Ub= 1<<2, /* unit is busy (between start and stop) */ - Nakrcv= 1<<1, /* nak received or sent a NAK */ - Rwm= 1<<0, /* =0, master transmit (or slave receive); =1, master receive (or slave transmit) */ - Err= Bed | Ssd, - - /* isar address (0x7F bits) */ - - /* others */ - Rbit = 1<<0, /* bit in address byte denoting read */ - Wbit= 0<<0, - - MaxIO = 8192, /* largest transfer done at once (can change) */ - MaxSA= 2, /* largest subaddress; could be FIFOsize */ - Bufsize = MaxIO, /* subaddress bytes don't go in buffer */ - Freq = 0, /* set to Fm for high-speed */ -// I2Ctimeout = 125, /* msec (can change) */ - I2Ctimeout = 10000, /* msec when Chatty */ - - Chatty = 0, -}; - -#define DPRINT if(Chatty)print - -/* - * I2C software structures - */ - -struct Ctlr { - Lock; - QLock io; - int init; - int polling; /* eg, when running before system set up */ - I2Cregs* regs; /* hardware registers */ - - /* controller state (see below) */ - int status; - int phase; - Rendez r; - - /* transfer parameters */ - int addr; - int salen; /* bytes remaining of subaddress */ - int offset; /* sub-addressed offset */ - int cntl; /* everything but transfer length */ - int rdcount; /* requested read transfer size */ - Block* b; -}; - -enum { - /* Ctlr.state */ - Idle, - Done, - Failed, - Busy, - Address, - Subaddress, - Read, - Write, - Halting, -}; - -static Ctlr i2cctlr[1]; - -static void interrupt(Ureg*, void*); -static int readyxfer(Ctlr*, int); -static void rxstart(Ctlr*); -static void txstart(Ctlr*); -static void stopxfer(Ctlr*); -static void txoffset(Ctlr*, ulong, int); -static int idlectlr(Ctlr*); - -static void -i2cdump(char *t, I2Cregs *i2c) -{ - iprint("i2c %s: ibmr=%.4lux icr=%.4lux isr=%.4lux\n", t, i2c->ibmr, i2c->icr, i2c->isr); -} - -static void -initialise(I2Cregs *i2c, int eintr) -{ - int ctl; - - /* initialisation (see p. 9-11 on) */ - i2c->isar = 0; - ctl = Freq | Gcd | Scle | Iue; - if(eintr) - ctl |= Beie | Irfie; /* Iteie set by txstart */ - i2c->icr = ctl; - if(Chatty) - iprint("ctl=%4.4ux icr=%4.4lux\n", ctl, i2c->icr); -} - -/* - * called by the reset routine of any driver using the IIC - */ -void -i2csetup(int polling) -{ - I2Cregs *i2c; - Ctlr *ctlr; - - ctlr = i2cctlr; - ctlr->polling = polling; - i2c = KADDR(PHYSI2C); - ctlr->regs = i2c; - if(!polling){ - if(ctlr->init == 0){ - initialise(i2c, 1); - ctlr->init = 1; - intrenable(IRQ, IRQi2c, interrupt, i2cctlr, "i2c"); - if(Chatty) - i2cdump("init", i2c); - } - }else - initialise(i2c, 0); -} - -static void -done(Ctlr *ctlr) -{ - ctlr->phase = Done; - wakeup(&ctlr->r); -} - -static void -failed(Ctlr *ctlr) -{ - ctlr->phase = Failed; - wakeup(&ctlr->r); -} - -static void -interrupt(Ureg*, void *arg) -{ - int sts, idl; - Ctlr *ctlr; - Block *b; - I2Cregs *i2c; - char xx[12]; - - ctlr = arg; - i2c = ctlr->regs; - idl = (i2c->ibmr & 3) == 3; - if(Chatty && ctlr->phase != Read && ctlr->phase != Write){ - snprint(xx, sizeof(xx), "intr %d", ctlr->phase); - i2cdump(xx, i2c); - } - sts = i2c->isr; - if(sts & (Bed | Sad | Gcad | Ald)) - iprint("i2c: unexpected status: %.4ux", sts); - i2c->isr = sts; - ctlr->status = sts; - i2c->icr &= ~(Start | Stop | Nak | Ma | Iteie); - if(sts & Err){ - failed(ctlr); - return; - } - switch(ctlr->phase){ - default: - iprint("i2c: unexpected interrupt: p-%d s=%.4ux\n", ctlr->phase, sts); - break; - - case Halting: - ctlr->phase = Idle; - break; - - case Subaddress: - if(ctlr->salen){ - /* push out next byte of subaddress */ - ctlr->salen -= 8; - i2c->idbr = ctlr->offset >> ctlr->salen; - i2c->icr |= Aldie | Tb | Iteie; - break; - } - /* subaddress finished */ - if(ctlr->cntl & Rbit){ - /* must readdress if reading to change mode */ - i2c->idbr = (ctlr->addr << 1) | Rbit; - i2c->icr |= Start | Tb | Iteie; - ctlr->phase = Address; /* readdress */ - break; - } - /* FALL THROUGH if writing */ - case Address: - /* if not sub-addressed, rxstart/txstart */ - if(ctlr->cntl & Rbit) - rxstart(ctlr); - else - txstart(ctlr); - break; - - case Read: - b = ctlr->b; - if(b == nil) - panic("i2c: no buffer"); - /* master receive: next byte */ - if(sts & Irf){ - ctlr->rdcount--; - if(b->wp < b->lim) - *b->wp++ = i2c->idbr; - } - if(ctlr->rdcount <= 0 || sts & Nakrcv || idl){ - if(Chatty) - iprint("done: %.4ux\n", sts); - done(ctlr); - break; - } - rxstart(ctlr); - break; - - case Write: - b = ctlr->b; - if(b == nil) - panic("i2c: no buffer"); - /* account for data transmitted */ - if(BLEN(b) <= 0 || sts & Nakrcv){ - done(ctlr); - break; - } - txstart(ctlr); - break; - } -} - -static int -isdone(void *a) -{ - return ((Ctlr*)a)->phase < Busy; -} - -static int -i2cerror(char *s) -{ - DPRINT("i2c error: %s\n", s); - if(up) - error(s); - /* no current process, don't call error */ - return -1; -} - -static char* -startxfer(I2Cdev *d, int op, Block *b, int n, ulong offset) -{ - I2Cregs *i2c; - Ctlr *ctlr; - int i, p, s; - - ctlr = i2cctlr; - if(up){ - qlock(&ctlr->io); - if(waserror()){ - qunlock(&ctlr->io); - nexterror(); - } - } - ilock(ctlr); - if(!idlectlr(ctlr)){ - iunlock(ctlr); - if(up) - error("bus confused"); - return "bus confused"; - } - if(ctlr->phase >= Busy) - panic("i2c: ctlr busy"); - ctlr->cntl = op; - ctlr->b = b; - ctlr->rdcount = n; - ctlr->addr = d->addr; - i2c = ctlr->regs; - ctlr->salen = d->salen*8; - ctlr->offset = offset; - if(ctlr->salen){ - ctlr->phase = Subaddress; - op = Wbit; - }else - ctlr->phase = Address; - i2c->idbr = (d->addr<<1) | op; /* 7-bit address + R/nW */ - i2c->icr |= Start | Tb | Iteie; - if(Chatty) - i2cdump("start", i2c); - iunlock(ctlr); - - /* wait for it */ - if(ctlr->polling){ - for(i=0; !isdone(ctlr); i++){ - delay(2); - interrupt(nil, ctlr); - } - }else - tsleep(&ctlr->r, isdone, ctlr, I2Ctimeout); - - ilock(ctlr); - p = ctlr->phase; - s = ctlr->status; - ctlr->b = nil; - if(ctlr->phase != Done && ctlr->phase != Idle) - stopxfer(ctlr); - iunlock(ctlr); - - if(up){ - poperror(); - qunlock(&ctlr->io); - } - if(p != Done || s & (Bed|Ald)){ /* CHECK; time out */ - if(s & Ald) - return "i2c lost arbitration"; - if(s & Bed) - return "i2c bus error"; - if(s & Ssd) - return "i2c transfer aborted"; /* ?? */ - if(0 && p != Done) - return "i2c timed out"; - sprint(up->genbuf, "i2c error: phase=%d status=%.4ux", p, s); - return up->genbuf; - } - return nil; -} - -long -i2csend(I2Cdev *d, void *buf, long n, ulong offset) -{ - Block *b; - char *e; - - if(n <= 0) - return 0; - if(n > MaxIO) - n = MaxIO; - - if(up){ - b = allocb(n); - if(b == nil) - error(Enomem); - if(waserror()){ - freeb(b); - nexterror(); - } - }else{ - b = iallocb(n); - if(b == nil) - return -1; - } - memmove(b->wp, buf, n); - b->wp += n; - e = startxfer(d, 0, b, 0, offset); - if(up) - poperror(); - n -= BLEN(b); /* residue */ - freeb(b); - if(e) - return i2cerror(e); - return n; -} - -long -i2crecv(I2Cdev *d, void *buf, long n, ulong offset) -{ - Block *b; - long nr; - char *e; - - if(n <= 0) - return 0; - if(n > MaxIO) - n = MaxIO; - - if(up){ - b = allocb(n); - if(b == nil) - error(Enomem); - if(waserror()){ - freeb(b); - nexterror(); - } - }else{ - b = iallocb(n); - if(b == nil) - return -1; - } - e = startxfer(d, Rbit, b, n, offset); - nr = BLEN(b); - if(nr > 0) - memmove(buf, b->rp, nr); - if(up) - poperror(); - freeb(b); - if(e) - return i2cerror(e); - return nr; -} - -/* - * the controller must be locked for the following functions - */ - -static int -readyxfer(Ctlr *ctlr, int phase) -{ - I2Cregs *i2c; - - i2c = ctlr->regs; - if((i2c->isr & Bed) != 0){ - failed(ctlr); - return 0; - } - ctlr->phase = phase; - return 1; -} - -/* - * start a master transfer to receive the next byte of data - */ -static void -rxstart(Ctlr *ctlr) -{ - Block *b; - int cntl; - - b = ctlr->b; - if(b == nil || ctlr->rdcount<= 0){ - done(ctlr); - return; - } - if(!readyxfer(ctlr, Read)) - return; - cntl = Aldie | Tb; - if(ctlr->rdcount == 1) - cntl |= Stop | Nak | Iteie; /* last byte of transfer */ - ctlr->regs->icr |= cntl; -} - -/* - * start a master transfer to send the next chunk of data - */ -static void -txstart(Ctlr *ctlr) -{ - Block *b; - int cntl; - long nb; - I2Cregs *i2c; - - b = ctlr->b; - if(b == nil || (nb = BLEN(b)) <= 0){ - done(ctlr); - return; - } - if(!readyxfer(ctlr, Write)) - return; - i2c = ctlr->regs; - i2c->idbr = *b->rp++; - cntl = Aldie | Tb | Iteie; - if(nb == 1) - cntl |= Stop; - i2c->icr |= cntl; -} - -/* - * stop a transfer if one is in progress - */ -static void -stopxfer(Ctlr *ctlr) -{ - I2Cregs *i2c; - - i2c = ctlr->regs; - if((i2c->isr & Ub) == 0){ - ctlr->phase = Idle; - return; - } - if((i2c->isr & Ibb) == 0 && ctlr->phase != Halting){ - ctlr->phase = Halting; /* interrupt will clear the state */ - i2c->icr |= Ma; - } - /* if that doesn't clear it by the next operation, idlectlr will do so below */ -} - -static int -idlectlr(Ctlr *ctlr) -{ - I2Cregs *i2c; - - i2c = ctlr->regs; - if((i2c->isr & Ibb) == 0){ - if((i2c->isr & Ub) == 0){ - ctlr->phase = Idle; - return 1; - } - iprint("i2c: bus free, ctlr busy: isr=%.4lux icr=%.4lux\n", i2c->isr, i2c->icr); - } - /* hit it with the hammer, soft reset */ - iprint("i2c: soft reset\n"); - i2c->icr = Ur; - iunlock(ctlr); - delay(1); - ilock(ctlr); - initialise(i2c, !ctlr->polling); - ctlr->phase = Idle; - return (i2c->isr & (Ibb | Ub)) == 0; -} diff --git a/os/pxa/l.s b/os/pxa/l.s deleted file mode 100644 index df246a04..00000000 --- a/os/pxa/l.s +++ /dev/null @@ -1,548 +0,0 @@ -#include "mem.h" - -#define CPWAIT MRC CpMMU, 0, R2, C(2), C(0), 0; MOVW R2, R2; SUB $4, R15 - -/* - * Entered here from the boot loader with - * supervisor mode, interrupts disabled; - * MMU, IDC and WB disabled. - */ - -TEXT _startup(SB), $-4 - MOVW $setR12(SB), R12 /* static base (SB) */ - MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R1 /* ensure SVC mode with interrupts disabled */ - MOVW R1, CPSR - MOVW $(MACHADDR+BY2PG-4), R13 /* stack; 4 bytes for link */ - - BL main(SB) -dead: - B dead - BL _div(SB) /* hack to get _div etc loaded */ - -TEXT getcpuid(SB), $-4 - MRC CpMMU, 0, R0, C(CpCPUID), C(0) - RET - -TEXT mmugetctl(SB), $-4 - MRC CpMMU, 0, R0, C(CpControl), C(0) - RET - -TEXT mmugetdac(SB), $-4 - MRC CpMMU, 0, R0, C(CpDAC), C(0) - RET - -TEXT mmugetfar(SB), $-4 - MRC CpMMU, 0, R0, C(CpFAR), C(0) - RET - -TEXT mmugetfsr(SB), $-4 - MRC CpMMU, 0, R0, C(CpFSR), C(0) - RET - -TEXT mmuputdac(SB), $-4 - MCR CpMMU, 0, R0, C(CpDAC), C(0) - CPWAIT - RET - -TEXT mmuputfsr(SB), $-4 - MCR CpMMU, 0, R0, C(CpFSR), C(0) - CPWAIT - RET - -TEXT mmuputttb(SB), $-4 - MCR CpMMU, 0, R0, C(CpTTB), C(0) - CPWAIT - RET - -TEXT mmuputctl(SB), $-4 - MCR CpMMU, 0, R0, C(CpControl), C(0) - CPWAIT - RET - -TEXT tlbinvalidateall(SB), $-4 - MCR CpMMU, 0, R0, C(CpTLBops), C(7) - CPWAIT - RET - -TEXT itlbinvalidate(SB), $-4 - MCR CpMMU, 0, R0, C(CpTLBops), C(5), 1 - CPWAIT - RET - -TEXT dtlbinvalidate(SB), $-4 - MCR CpMMU, 0, R0, C(CpTLBops), C(6), 1 - CPWAIT - RET - -TEXT mmuenable(SB), $-4 - - MOVW $1, R1 - MCR CpMMU, 0, R1, C(CpDAC), C(3) /* set domain 0 to client */ - - /* disable and invalidate all caches and TLB's before (re-)enabling MMU */ - MOVW $(CpCwpd | CpCsystem), R1 - MRC CpMMU, 0, R1, C(CpControl), C(0) - CPWAIT - - MOVW $0, R1 /* disable everything */ - MCR CpMMU, 0, R1, C(CpCacheCtl), C(7), 0 /* invalidate I&D Caches and BTB */ - MCR CpMMU, 0, R1, C(CpCacheCtl), C(10), 4 /* drain write and fill buffer */ - MCR CpMMU, 0, R1, C(CpTLBops), C(7), 0 /* invalidate I&D TLB */ - - /* enable desired mmu mode (R0) */ - MCR CpMMU, 0, R0, C(1), C(0) - CPWAIT - RET /* start running in remapped area */ - -TEXT setr13(SB), $-4 - MOVW 4(FP), R1 - - MOVW CPSR, R2 - BIC $PsrMask, R2, R3 - ORR R0, R3 - MOVW R3, CPSR - - MOVW R13, R0 - MOVW R1, R13 - - MOVW R2, CPSR - RET - -TEXT vectors(SB), $-4 - MOVW 0x18(R15), R15 /* reset */ - MOVW 0x18(R15), R15 /* undefined */ - MOVW 0x18(R15), R15 /* SWI */ - MOVW 0x18(R15), R15 /* prefetch abort */ - MOVW 0x18(R15), R15 /* data abort */ - MOVW 0x18(R15), R15 /* reserved */ - MOVW 0x18(R15), R15 /* IRQ */ - MOVW 0x18(R15), R15 /* FIQ */ - -TEXT vtable(SB), $-4 - WORD $_vsvc(SB) /* reset, in svc mode already */ - WORD $_vund(SB) /* undefined, switch to svc mode */ - WORD $_vsvc(SB) /* swi, in svc mode already */ - WORD $_vpab(SB) /* prefetch abort, switch to svc mode */ - WORD $_vdab(SB) /* data abort, switch to svc mode */ - WORD $_vsvc(SB) /* reserved */ - WORD $_virq(SB) /* IRQ, switch to svc mode */ - WORD $_vfiq(SB) /* FIQ, switch to svc mode */ - -TEXT _vund(SB), $-4 - MOVM.DB [R0-R3], (R13) - MOVW $PsrMund, R0 - B _vswitch - -TEXT _vsvc(SB), $-4 - MOVW.W R14, -4(R13) - MOVW CPSR, R14 - MOVW.W R14, -4(R13) - BIC $PsrMask, R14 - ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14 - MOVW R14, CPSR - MOVW $PsrMsvc, R14 - MOVW.W R14, -4(R13) - B _vsaveu - -TEXT _vpab(SB), $-4 - MOVM.DB [R0-R3], (R13) - MOVW $PsrMabt, R0 - B _vswitch - -TEXT _vdab(SB), $-4 - MOVM.DB [R0-R3], (R13) - MOVW $(PsrMabt+1), R0 - B _vswitch - -TEXT _vfiq(SB), $-4 /* FIQ */ - MOVM.DB [R0-R3], (R13) - MOVW $PsrMfiq, R0 - B _vswitch - -TEXT _virq(SB), $-4 /* IRQ */ - MOVM.DB [R0-R3], (R13) - MOVW $PsrMirq, R0 - -_vswitch: /* switch to svc mode */ - MOVW SPSR, R1 - MOVW R14, R2 - MOVW R13, R3 - - MOVW CPSR, R14 - BIC $PsrMask, R14 - ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14 - MOVW R14, CPSR - - MOVM.DB.W [R0-R2], (R13) - MOVM.DB (R3), [R0-R3] - -_vsaveu: /* Save Registers */ - MOVW.W R14, -4(R13) /* save link */ - MCR CpMMU, 0, R0, C(0), C(0), 0 - - SUB $8, R13 - MOVM.DB.W [R0-R12], (R13) - - MOVW R0, R0 /* gratuitous noop */ - - MOVW $setR12(SB), R12 /* static base (SB) */ - MOVW R13, R0 /* argument is ureg */ - SUB $8, R13 /* space for arg+lnk*/ - BL trap(SB) - -_vrfe: /* Restore Regs */ - MOVW CPSR, R0 /* splhi on return */ - ORR $(PsrDirq|PsrDfiq), R0, R1 - MOVW R1, CPSR - ADD $(8+4*15), R13 /* [r0-R14]+argument+link */ - MOVW (R13), R14 /* restore link */ - MOVW 8(R13), R0 - MOVW R0, SPSR - MOVM.DB.S (R13), [R0-R14] /* restore user registers */ - MOVW R0, R0 /* gratuitous nop */ - ADD $12, R13 /* skip saved link+type+SPSR*/ - RFE /* MOVM.IA.S.W (R13), [R15] */ - -TEXT splhi(SB), $-4 - MOVW CPSR, R0 - ORR $(PsrDirq), R0, R1 - MOVW R1, CPSR - MOVW $(MACHADDR), R6 - MOVW R14, (R6) /* m->splpc */ - RET - -TEXT spllo(SB), $-4 - MOVW CPSR, R0 - BIC $(PsrDirq|PsrDfiq), R0, R1 - MOVW R1, CPSR - RET - -TEXT splx(SB), $-4 - MOVW $(MACHADDR), R6 - MOVW R14, (R6) /* m->splpc */ - -TEXT splxpc(SB), $-4 - MOVW R0, R1 - MOVW CPSR, R0 - MOVW R1, CPSR - RET - -TEXT spldone(SB), $-4 - RET - -TEXT islo(SB), $-4 - MOVW CPSR, R0 - AND $(PsrDirq), R0 - EOR $(PsrDirq), R0 - RET - -TEXT splfhi(SB), $-4 - MOVW CPSR, R0 - ORR $(PsrDfiq|PsrDirq), R0, R1 - MOVW R1, CPSR - RET - -TEXT splflo(SB), $-4 - MOVW CPSR, R0 - BIC $(PsrDfiq), R0, R1 - MOVW R1, CPSR - RET - -TEXT getcpsr(SB), $-4 - MOVW CPSR, R0 - RET - -TEXT getspsr(SB), $-4 - MOVW SPSR, R0 - RET - -TEXT getcallerpc(SB), $-4 - MOVW 0(R13), R0 - RET - -TEXT _tas(SB), $-4 - MOVW R0, R1 - MOVW $0xDEADDEAD, R2 - SWPW R2, (R1), R0 - RET - -TEXT setlabel(SB), $-4 - MOVW R13, 0(R0) /* sp */ - MOVW R14, 4(R0) /* pc */ - MOVW $0, R0 - RET - -TEXT gotolabel(SB), $-4 - MOVW 0(R0), R13 /* sp */ - MOVW 4(R0), R14 /* pc */ - MOVW $1, R0 - RET - -/* - * flush (invalidate) the whole icache - */ -TEXT icflushall(SB), $-4 -_icflushall: - MCR CpMMU, 0, R0, C(CpCacheCtl), C(5), 0 /* clean i-cache and branch buffer */ - CPWAIT - RET - -/* - * invalidate part of i-cache and invalidate branch target buffer - */ -TEXT icflush(SB), $-4 - MOVW 4(FP), R1 - CMP $(CACHESIZE/2), R1 - BGE _icflushall - ADD R0, R1 - BIC $(CACHELINESZ-1), R0 -icflush1: - MCR CpMMU, 0, R0, C(CpCacheCtl), C(5), 1 /* clean entry */ - ADD $CACHELINESZ, R0 - CMP R1, R0 - BLO icflush1 - MCR CpMMU, 0, R0, C(CpCacheCtl), C(5), 6 /* invalidate branch target buffer */ - CPWAIT - RET - -/* - * write back whole data cache and drain write buffer - */ -TEXT dcflushall(SB), $-4 -_dcflushall: - MOVW $(DCFADDR), R0 - ADD $CACHESIZE, R0, R1 -dcflushall1: - MCR CpMMU, 0, R0, C(CpCacheCtl), C(2), 5 /* allocate line */ - ADD $CACHELINESZ, R0 - CMP R1,R0 - BNE dcflushall1 - MCR CpMMU, 0, R0, C(CpCacheCtl), C(10), 4 /* drain write buffer */ - CPWAIT - RET - -/* - * write back a given region and drain write buffer - */ -TEXT dcflush(SB), $-4 - MOVW 4(FP), R1 - CMP $(CACHESIZE/2), R1 - BGE _dcflushall - ADD R0, R1 - BIC $(CACHELINESZ-1), R0 -dcflush1: - MCR CpMMU, 0, R0, C(CpCacheCtl), C(10), 1 /* clean entry */ - ADD $CACHELINESZ, R0 - CMP R1, R0 - BLO dcflush1 - MCR CpMMU, 0, R0, C(CpCacheCtl), C(10), 4 /* drain write buffer */ - CPWAIT - RET - -#ifdef NOTYET -/* - * write back mini data cache - * TO DO: need to allocate pair of unused 2k blocks and read them alternately - */ -TEXT minidcflush(SB), $-4 - MOVW $(MCFADDR), R0 - ADD $(16*CACHELINESZ), R0, R1 - -wbbflush: - MOVW.P CACHELINESZ(R0), R2 - CMP R1,R0 - BNE wbbflush - MCR CpMMU, 0, R0, C(CpCacheCtl), C(10), 4 /* drain write buffer */ - CPWAIT - RET -#endif - -/* - * invalidate data caches (main and mini) - */ -TEXT dcinval(SB), $-4 - MCR CpMMU, 0, R0, C(CpCacheCtl), C(6), 0 - CPWAIT - RET - -/* for devboot */ -TEXT gotopc(SB), $-4 - MOVW R0, R1 - MOVW $0, R0 - MOVW R1, PC - RET - -TEXT idle(SB), $-4 - MOVW $1, R0 /* idle mode */ - MCR CpPWR, 0, R0, C(7), C(0), 0 - RET - -TEXT getcclkcfg(SB), $-4 - MRC CpPWR, 0, R0, C(6), C(0), 0 - RET - -TEXT putcclkcfg(SB), $-4 - MCR CpPWR, 0, R0, C(6), C(0), 0 - RET - -#ifdef NOTYET -/* - * the following code is considerably modified from the - * sleep code by nemo@gsyc.escet.urjc.es for Plan 9, but that's - * where it started. in particular, there's no need to save regs in all modes, - * since here we're called from kernel main level (a kproc) so nothing is live; - * the only regs needed are the various R13s, but we have trap restore them on resume. - * similarly there's no need to save SPSR, CPSR, etc. (even CpPID isn't really needed here). - */ - -#define MDREFR_k1db2 (1<<22) -#define MDREFR_slfrsh (1<<31) /* self refresh */ -#define MDREFR_e1pin (1<<20) -#define MSC_rt ((3<<16)|(3<<0)) -#define MDCFNG_de ((3<<16)|(3<<0)) /* dram enable, banks (3 2), (1 0) */ - -TEXT suspenditall(SB), $-4 - MOVW.W R14, -4(R13) - /* push mmu state on stack */ - MRC CpMMU, 0, R1, C(CpDAC), C(0) - MRC CpMMU, 0, R2, C(CpTTB), C(0) - MRC CpMMU, 0, R3, C(CpPID), C(0) - MRC CpMMU, 0, R4, C(CpControl), C(0) - MOVM.DB.W [R1-R4], (R13) - /* if pspr by convention held a stack pointer pointing to a pc we wouldn't need power_state */ - MOVW R13, power_state+0(SB) - - BL dcflushall(SB) - /* don't write DRAM after this */ - - MOVW $PHYSPOWER, R3 - - /* put resume address in scratchpad for boot loader */ - MOVW $power_resume+0(SB), R2 - MOVW R2, 0x8(R3) /* pspr */ - - /* disable clock switching */ - MCR CpPWR, 0, R1, C(CpTest), C(0x2), 2 - - /* adjust mem timing first to avoid processor bug causing hang */ - MOVW $MDCNFG, R5 - MOVW 0x1c(R5), R2 - ORR $(MDREFR_k1db2), R2 - MOVW R2, 0x1c(R5) - - /* set PLL to lower speed w/ delay */ - MOVW $(120*206),R0 -l11: SUB $1,R0 - BGT l11 - MOVW $0, R2 - MOVW R2, 0x14(R3) /* ppcr */ - MOVW $(120*206),R0 -l12: SUB $1,R0 - BGT l12 - - /* - * SA1110 fix for various suspend bugs in pre-B4 chips (err. 14-16, 18): - * set up register values here for use in code below that is at most - * one cache line (32 bytes) long, to run without DRAM. - */ - /* 1. clear RT in MSCx (R1, R7, R8) without changing other bits */ - MOVW 0x10(R5), R1 /* MSC0 */ - BIC $(MSC_rt), R1 - MOVW 0x14(R5), R7 /* MSC1 */ - BIC $(MSC_rt), R7 - MOVW 0x2c(R5), R8 /* MSC2 */ - BIC $(MSC_rt), R8 - /* 2. clear DRI0-11 in MDREFR (R4) without changing other bits */ - MOVW 0x1c(R5), R4 - BIC $(0xfff0), R4 - /* 3. set SLFRSH in MDREFR (R6) without changing other bits */ - ORR $(MDREFR_slfrsh), R4, R6 - /* 4. clear DE in MDCNFG (R9), and any other bits desired */ - MOVW 0x0(R5), R9 - BIC $(MDCFNG_de), R9 - /* 5. clear SLFRSH and E1PIN (R10), without changing other bits */ - BIC $(MDREFR_slfrsh), R4, R10 - BIC $(MDREFR_e1pin), R10 - /* 6. force sleep mode in PMCR (R2) */ - MOVW $1,R2 - MOVW suspendcode+0(SB), R0 - B (R0) /* off to do it */ - -/* - * the following is copied by trap.c to a cache-aligned area (suspendcode), - * so that it can all run during disabling of DRAM - */ -TEXT _suspendcode(SB), $-4 - /* 1: clear RT field of all MSCx registers */ - MOVW R1, 0x10(R5) - MOVW R7, 0x14(R5) - MOVW R8, 0x2c(R5) - /* 2: clear DRI field in MDREFR */ - MOVW R4, 0x1c(R5) - /* 3: set SLFRSH bit in MDREFR */ - MOVW R6, 0x1c(R5) - /* 4: clear DE bits in MDCFNG */ - MOVW R9, 0x0(R5) - /* 5: clear SLFRSH and E1PIN in MDREFR */ - MOVW R10, 0x1c(R5) - /* 6: suspend request */ - MOVW R2, 0x0(R3) /* pmcr */ - B 0(PC) /* wait for it */ - -/* - * The boot loader comes here after the resume. - */ -TEXT power_resume(SB), $-4 - MOVW $(PsrDirq|PsrDfiq|PsrMsvc), R0 - MOVW R0, CPSR /* svc mode, interrupts off */ - MOVW $setR12(SB), R12 - - /* flush caches */ - MCR CpMMU, 0, R0, C(CpCacheCtl), C(7), 0 - /* drain prefetch */ - MOVW R0,R0 - MOVW R0,R0 - MOVW R0,R0 - MOVW R0,R0 - /* drain write buffer */ - MCR CpMMU, 0, R0, C(CpCacheCtl), C(10), 4 - /* flush tlb */ - MCR CpMMU, 0, R0, C(CpTLBops), C(7) - - /* restore state */ - MOVW power_state+0(SB), R13 - MOVM.IA.W (R13), [R1-R4] - MOVW.P 4(R13), R14 - - MCR CpMMU, 0, R1, C(CpDAC), C(0x0) - MCR CpMMU, 0, R2, C(CpTTB), C(0x0) - MCR CpMMU, 0, R3, C(CpPID), C(0x0) - MCR CpMMU, 0, R4, C(CpControl), C(0x0) /* enable cache and mmu */ - MOVW R0,R0 - MOVW R0,R0 - MOVW R0,R0 - MOVW R0,R0 - /* flush i&d caches */ - MCR CpMMU, 0, R0, C(CpCacheCtl), C(7) - /* flush tlb */ - MCR CpMMU, 0, R0, C(CpTLBops), C(7) - /* drain prefetch */ - MOVW R0,R0 - MOVW R0,R0 - MOVW R0,R0 - MOVW R0,R0 - /* enable clock switching */ - MCR CpPWR, 0, R1, C(CpTest), C(1), 2 - RET -#endif - - GLOBL power_state+0(SB), $4 - -#ifdef YYY -/* for debugging sleep code: */ -TEXT fastreset(SB), $-4 - MOVW $PHYSRESET, R7 - MOVW $1, R1 - MOVW R1, (R7) - RET -#endif diff --git a/os/pxa/mmu.c b/os/pxa/mmu.c deleted file mode 100644 index 52326237..00000000 --- a/os/pxa/mmu.c +++ /dev/null @@ -1,252 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" - -/* - * Small pages: - * L1: 12-bit index -> 4096 descriptors -> 16Kb - * L2: 8-bit index -> 256 descriptors -> 1Kb - * Each L2 descriptor has access permissions for 4 1Kb sub-pages. - * - * TTB + L1Tx gives address of L1 descriptor - * L1 descriptor gives PTBA - * PTBA + L2Tx gives address of L2 descriptor - * L2 descriptor gives PBA - * - * on the Xscale, X, C & B are interpreted as follows: - * X = 0: - * C=0 B=0 uncached, unbuffered, stall until data access complete - * C=0 B=1 uncached, buffered (different from Strongarm) - * C=1 B=0 cached, buffered, write through, read allocate (different from Strongarm) - * C=1 B=1 cached, buffered, write back, read allocate - * X = 1: - * C=0 B=0 undefined - * C=0 B=1 uncached, buffered, writes will not coalesce - * C=1 B=0 mini data cache (policy set by auxiliary control reg) - * C=1 B=1 cached, buffered, write back, read/write allocate - * and the i-cache uses only the C bit (cached if non-zero). - */ -#define TTB(pa) ((pa) & ~0x3FFF) /* translation table base */ -#define L1x(pa) (((pa)>>20) & 0xFFF) /* L1 table index */ -#define PTBA(pa) ((pa) & ~0x3FF) /* page table base address */ -#define L2x(pa) (((pa)>>12) & 0xFF) /* L2 table index */ -#define PBA(pa) ((pa) & ~0xFFF) /* page base address */ -#define SBA(pa) ((pa) & ~0xFFFFF) /* section base address */ - -enum { - /* sizes */ - Section= 1<<20, - LargePage= 1<<16, - SmallPage= 1<<12, - EsmallPage= 1<<10, - SectionPages = Section/SmallPage, - PtAlign = 1<<10, - - /* L1 descriptor format */ - L1type= 3<<0, /* mask for type */ - L1page= 1<<0, /* descriptor is for L2 pages */ - L1section= 2<<0, /* descriptor is for section */ - L1fpage= 3<<0, /* descriptor is for fine (1k) L2 pages */ - L1buffered= 1<<2, - L1cached= 1<<3, - L1P= 1<<9, /* application-processor specific */ - L1sectionX= 1<<12, /* X bit in section descriptor */ - L1minicache= (L1sectionX | L1cached), - - /* L2 descriptor format for coarse page table */ - L2type= 3<<0, /* mask for type */ - L2invalid= 0<<0, - L2large= 1<<0, /* large page */ - L2small= 2<<0, /* small page */ - L2esmall= 3<<0, /* extended small page */ - L2buffered= 1<<2, - L2cached= 1<<3, - /* then access permissions */ - L2smallX= 1<<6, - L2largeX= 1<<12, - - /* domains */ - Dnone= 0, - Dclient= 1, - Dmanager= 3, - - /* access permissions */ - APsro= 0, /* supervisor ro if S|R */ - APsrw= 1, /* supervisor rw */ - APuro= 2, /* supervisor rw + user ro */ - APurw= 3, /* supervisor rw + user rw */ - - MINICACHED = 0x10000000, -}; - -#define L1dom(d) (((d) & 0xF)<<5) /* L1 domain */ -#define AP(i, v) ((v)<<(((i)*2)+4)) /* access permissions */ -#define L1AP(v) AP(3, (v)) -#define L2AP(v) AP(3, (v))|AP(2, (v))|AP(1, (v))|AP(0, (v)) - -#define L1krw (L1AP(APsrw) | L1dom(0)) - -/* - * return physical address corresponding to a given virtual address, - * or 0 if there is no such address - */ -ulong -va2pa(void *v) -{ - int idx; - ulong pte, ste, *ttb; - - idx = L1x((ulong)v); - ttb = (ulong*)KTTB; - ste = ttb[idx]; - switch(ste & L1type) { - case L1section: - return SBA(ste)|((ulong)v & 0x000fffff); - case L1page: - pte = ((ulong *)PTBA(ste))[L2x((ulong)v)]; - switch(pte & 3) { - case L2large: - return (pte & 0xffff0000)|((ulong)v & 0x0000ffff); - case L2small: - return (pte & 0xfffff000)|((ulong)v & 0x00000fff); - } - } - return 0; -} - -/* for debugging */ -void -prs(char *s) -{ - for(; *s; s++) - uartputc(*s); -} - -void -pr16(ulong n) -{ - int i, c; - - for(i=28; i>=0; i-=4){ - c = (n>>i) & 0xF; - if(c >= 0 && c <= 9) - c += '0'; - else - c += 'A'-10; - uartputc(c); - } -} - -void -xdelay(int n) -{ - int j; - - for(j=0; j<1000000/4; j++) - n++; - USED(n); -} - -void* -mmuphysmap(ulong phys, ulong) -{ - ulong *ttb; - void *va; - - ttb = (ulong*)KTTB; - va = KADDR(phys); - ttb[L1x((ulong)va)] = phys | L1krw | L1section; - return va; -} - -/* - * Set a 1-1 map of virtual to physical memory, except: - * doubly-map page0 at the alternative interrupt vector address, - * doubly-map physical memory at KZERO+256*MB as uncached but buffered, - * map flash to virtual space away from 0, - * disable access to 0 (nil pointers). - * - * Other section maps are added later as required by mmuphysmap. - */ -void -mmuinit(void) -{ - int i; - ulong *ttb, *ptable, va; - - ttb = (ulong*)KTTB; - for(i=0; i>5) -#define GPAF(n,v) ((v)<<(((n)&15)*2)) - -void gpioreserve(int); -void gpioconfig(int, ulong); -ulong gpioget(int); -void gpioset(int, int); -void gpiorelease(int); - -enum { - /* software configuration bits for gpioconfig */ - Gpio_gpio= 0<<0, - Gpio_Alt1= 1<<0, - Gpio_Alt2= 2<<0, - Gpio_Alt3= 3<<0, - Gpio_in= 1<<2, - Gpio_out= 1<<3, -}; - -/* - * software structures used by ../port/devi2c.c and iic.c - */ -struct I2Cdev { - int addr; - int salen; /* length in bytes of subaddress, if used; 0 otherwise */ - int tenbit; /* 10-bit addresses */ -}; - -long i2crecv(I2Cdev*, void*, long, ulong); -long i2csend(I2Cdev*, void*, long, ulong); -void i2csetup(int); - -#define COREREG ((Coreregs*)PHYSCORE) -typedef struct Coreregs Coreregs; -struct Coreregs { - ulong cccr; /* core clock config */ - ulong cken; /* clock enable */ - ulong oscc; /* oscillator configuration */ -}; - -#define RTCREG ((RTCreg*)PHYSRTC) -typedef struct RTCreg RTCreg; -struct RTCreg { - ulong rcnr; /* count */ - ulong rtar; /* alarm */ - ulong rtsr; /* status */ - ulong rttr; /* trim */ -}; - -#define OSTMRREG ((OstmrReg*)PHYSOSTMR) -typedef struct OstmrReg OstmrReg; -struct OstmrReg { - ulong osmr[4]; /* match */ - ulong oscr; /* counter */ - ulong ossr; /* status */ - ulong ower; /* watchdog */ - ulong oier; /* interrupt enable */ -}; - -#define PMGRREG ((PmgrReg*)PHYSPOWER) -typedef struct PmgrReg PmgrReg; -struct PmgrReg { - ulong pmcr; /* ctl register */ - ulong pssr; /* sleep status */ - ulong pspr; /* scratch pad */ - ulong pwer; /* wakeup enable */ - ulong prer; /* rising-edge detect enable */ - ulong pfer; /* falling-edge detect enable */ - ulong pedr; /* GPIO edge detect status */ - ulong pcfr; /* general configuration */ - ulong pgsr[3]; /* GPIO sleep state */ - ulong rsvd; - ulong rcsr; /* reset controller status register */ -}; - -enum { - /* pp. 3-25 to 3-31 */ - PWER_rtc = 1<<31, /* wakeup by RTC alarm */ - PWER_we0 = 1<<0, /* wake-up on GP0 edge detect */ - - PSSR_sss = 1<<0, /* software sleep status */ - PSSR_bfs = 1<<1, /* battery fault status */ - PSSR_vfs = 1<<2, /* VDD fault status */ - PSSR_ph = 1<<4, /* peripheral control hold */ - PSSR_rdh = 1<<5, /* read disable hold */ - - PMFW_fwake= 1<<1, /* fast wakeup enable (no power stabilisation delay) */ - - RSCR_gpr= 1<<3, /* gpio reset has occurred */ - RSCR_smr= 1<<2, /* sleep mode has occurred */ - RSCR_wdr= 1<<1, /* watchdog reset has occurred */ - RSCR_hwr= 1<<0, /* hardware reset has occurred */ -}; - -#define MEMCFGREG ((MemcfgReg*)PHYSMEMCFG) -typedef struct MemcfgReg MemcfgReg; -struct MemcfgReg { - ulong mdcnfg; /* SDRAM config */ - ulong mdrefr; /* dram refresh */ - ulong msc0; /* static memory or devices */ - ulong msc1; - ulong msc2; /* static memory or devices */ - ulong mecr; /* expansion bus (pcmcia, CF) */ - ulong sxcnfg; /* synchronous static memory control */ - ulong sxmrs; /* MRS value to write to SMROM */ - ulong mcmem0; /* card interface socket 0 memory timing */ - ulong mcmem1; /* card interface socket 1 memory timing */ - ulong mcatt0; /* socket 0 attribute memory timing */ - ulong mcatt1; /* socket 1 attribute memory timing */ - ulong mcio0; /* socket 0 i/o timing */ - ulong mcio1; /* socket 1 i/o timing */ - ulong mdmrs; /* MRS value to write to SDRAM */ - ulong boot_def; /* read-only boot-time register */ - ulong mdmrslp; /* low-power SDRAM mode register set config */ - ulong sa1111cr; /* SA1111 compatibility */ -}; - -#define LCDREG ((LcdReg*)PHYSLCD) -typedef struct LcdReg LcdReg; -struct LcdReg { - ulong lccr0; /* control 0 */ - ulong lccr1; /* control 1 */ - ulong lccr2; /* control 2 */ - ulong lccr3; /* control 3 */ - struct { - ulong fdadr; /* dma frame descriptor address register */ - ulong fsadr; /* dma frame source address register */ - ulong fidr; /* dma frame ID register */ - ulong ldcmd; /* dma command */ - } frame[2]; - ulong fbr[2]; /* frame branch register */ - ulong lcsr; /* status */ - ulong liidr; /* interrupt ID register */ - ulong trgbr; /* TMED RGB seed register */ - ulong tcr; /* TMED control register */ -}; - -#define USBREG ((UsbReg*)PHYSUSB) -typedef struct UsbReg UsbReg; -struct UsbReg { - ulong udccr; /* control */ - ulong udccs[16]; /* endpoint control/status */ - ulong ufnrh; /* frame number high */ - ulong ufnrl; /* frame number low */ - ulong udbcr2; - ulong udbcr4; - ulong udbcr7; - ulong udbcr9; - ulong udbcr12; - ulong udbcr14; - ulong uddr[16]; /* endpoint data */ - ulong uicr0; - ulong uicr1; - ulong usir0; - ulong usir1; -}; - -enum { - /* DMA configuration parameters */ - - /* DMA Direction */ - DmaOut= 0, - DmaIn= 1, - - /* dma devices */ - DmaDREQ0= 0, - DmaDREQ1, - DmaI2S_i, - DmaI2S_o, - DmaBTUART_i, - DmaBTUART_o, - DmaFFUART_i, - DmaFFUART_o, - DmaAC97mic, - DmaAC97modem_i, - DmaAC97modem_o, - DmaAC97audio_i, - DmaAC97audio_o, - DmaSSP_i, - DmaSSP_o, - DmaNSSP_i, - DmaNSSP_o, - DmaICP_i, - DmaICP_o, - DmaSTUART_i, - DmaSTUART_o, - DmaMMC_i, - DmaMMC_o, - DmaRsvd0, - DmaRsvd1, - DmaUSB1, - DmaUSB2, - DmaUSB3, - DmaUSB4, - DmaHWUART_i, - DmaUSB6, - DmaUSB7, - DmaUSB8, - DmaUSB9, - DmaHWUART_o, - DmaUSB11, - DmaUSB12, - DmaUSB13, - DmaUSB14, - DmaRsvd2, -}; - -/* - * Interface to platform-specific PCMCIA signals, in arch*.c - */ -enum { - /* argument to pcmpin() */ - PCMready, - PCMeject, - PCMstschng, -}; - -/* - * physical device addresses are mapped to the same virtual ones, - * allowing the same addresses to be used with or without mmu. - */ - -#define PCMCIAcard(n) (PHYSPCMCIA0+((n)*PCMCIASIZE)) -#define PCMCIAIO(n) (PCMCIAcard(n)+0x0) /* I/O space */ -#define PCMCIAAttr(n) (PCMCIAcard(n)+0x8000000) /* Attribute space*/ -#define PCMCIAMem(n) (PCMCIAcard(n)+0xC000000) /* Memory space */ - -/* - * PCMCIA structures known by both port/cis.c and the pcmcia driver - */ - -/* - * Map between ISA memory space and PCMCIA card memory space. - */ -struct PCMmap { - ulong ca; /* card address */ - ulong cea; /* card end address */ - ulong isa; /* local virtual address */ - int len; /* length of the ISA area */ - int attr; /* attribute memory */ -}; - -/* - * a PCMCIA configuration entry - */ -struct PCMconftab -{ - int index; - ushort irqs; /* legal irqs */ - uchar irqtype; - uchar bit16; /* true for 16 bit access */ - uchar nlines; - struct { - ulong start; - ulong len; - } io[16]; - int nio; - uchar vcc; - uchar vpp1; - uchar vpp2; - uchar memwait; - ulong maxwait; - ulong readywait; - ulong otherwait; -}; - -/* - * PCMCIA card slot - */ -struct PCMslot -{ - RWlock; - - Ref ref; - - long memlen; /* memory length */ - uchar slotno; /* slot number */ - void *regs; /* i/o registers */ - void *mem; /* memory */ - void *attr; /* attribute memory */ - - /* status */ - uchar occupied; /* card in the slot */ - uchar configed; /* card configured */ - uchar busy; - uchar powered; - uchar battery; - uchar wrprot; - uchar enabled; - uchar special; - uchar dsize; - - /* cis info */ - int cisread; /* set when the cis has been read */ - char verstr[512]; /* version string */ - uchar cpresent; /* config registers present */ - ulong caddr; /* relative address of config registers */ - int nctab; /* number of config table entries */ - PCMconftab ctab[8]; - PCMconftab *def; /* default conftab */ - - /* maps are fixed */ - PCMmap memmap; - PCMmap attrmap; -}; diff --git a/os/pxa/sa1110break.c b/os/pxa/sa1110break.c deleted file mode 100644 index 3ab87b06..00000000 --- a/os/pxa/sa1110break.c +++ /dev/null @@ -1,360 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "ureg.h" -#include "../port/error.h" - -// -// from trap.c -// -extern int (*breakhandler)(Ureg *ur, Proc*); -extern Instr BREAK; -extern void portbreakinit(void); - -// -// Instructions that can have the PC as a destination register -// -enum { - IADD = 1, - IBRANCH, - ILDM, - ILDR, - IMOV, - - // - // These should eventually be implemented - // - IADC, - IAND, - IBIC, - IEOR, - ILDRT, - IMRS, - IMVN, - IORR, - IRSB, - IRSC, - ISBC, - ISUB, -}; - -static int instrtype(Instr i); -static ulong iadd(Ureg *ur, Instr i); -static ulong ibranch(Ureg *ur, Instr i); -static ulong ildm(Ureg *ur, Instr i); -static ulong ildr(Ureg *ur, Instr i); -static ulong imov(Ureg *ur, Instr i); -static ulong shifterval(Ureg *ur, Instr i); -static int condpass(Instr i, ulong psr); -static ulong *address(Ureg *ur, Instr i); -static ulong* multiaddr(Ureg *ur, Instr i); -static int nbits(ulong v); - -#define COND_N(psr) (((psr) >> 31) & 1) -#define COND_Z(psr) (((psr) >> 30) & 1) -#define COND_C(psr) (((psr) >> 29) & 1) -#define COND_V(psr) (((psr) >> 28) & 1) -#define REG(i, a, b) (((i) & BITS((a), (b))) >> (a)) -#define REGVAL(ur, r) (*((ulong*)(ur) + (r))) -#define LSR(v, s) ((ulong)(v) >> (s)) -#define ASR(v, s) ((long)(v) >> (s)) -#define ROR(v, s) (LSR((v), (s)) | (((v) & ((1 << (s))-1)) << (32 - (s)))) - -void -machbreakinit(void) -{ - portbreakinit(); - breakhandler = breakhit; -} - -Instr -machinstr(ulong addr) -{ - if (addr < KTZERO) - error(Ebadarg); - return *(Instr*)addr; -} - -void -machbreakset(ulong addr) -{ - if (addr < KTZERO) - error(Ebadarg); - *(Instr*)addr = BREAK; - segflush((void*)addr, sizeof(Instr)); -} - -void -machbreakclear(ulong addr, Instr i) -{ - if (addr < KTZERO) - error(Ebadarg); - *(Instr*)addr = i; - segflush((void*)addr, sizeof(Instr)); -} - -// -// Return the address of the instruction that will be executed after the -// instruction at address ur->pc. -// -// This means decoding the instruction at ur->pc. -// -// In the simple case, the PC will simply be the address of the next -// sequential instruction following ur->pc. -// -// In the complex case, the instruction is a branch of some sort, so the -// value of the PC after the instruction must be computed by decoding -// and simulating the instruction enough to determine the PC. -// - -ulong -machnextaddr(Ureg *ur) -{ - Instr i; - i = machinstr(ur->pc); - switch(instrtype(i)) { - case IADD: return iadd(ur,i); - case IBRANCH: return ibranch(ur,i); - case ILDM: return ildm(ur,i); - case ILDR: return ildr(ur,i); - case IMOV: return imov(ur,i); - - case IADC: - case IAND: - case IBIC: - case IEOR: - case ILDRT: - case IMRS: - case IMVN: - case IORR: - case IRSB: - case IRSC: - case ISBC: - case ISUB: - // XXX - Tad: unimplemented - // - // any of these instructions could possibly have the - // PC as Rd. Eventually, these should all be - // checked just like the others. - default: - return ur->pc+4; - } - - return 0; -} - -static int -instrtype(Instr i) -{ - if(i & BITS(26,27) == 0) { - switch((i >> 21) & 0xF) { - case 0: return IAND; - case 1: return IEOR; - case 2: return ISUB; - case 3: return IRSB; - case 4: return IADD; - case 5: return IADC; - case 6: return ISBC; - case 7: return IRSC; - case 0xD: return IMOV; - case 0xC: return IORR; - case 0xE: return IBIC; - case 0xF: return IMVN; - } - if(((i & BIT(25)|BITS(23,24)|BITS(20,21))) >> 20 == 0x10) - return IMRS; - return 0; - } - - if(((i & BITS(27,25)|BIT(20)) >> 20) == 0x81) return ILDM; - if(((i & BITS(26,27)|BIT(22)|BIT(20)) >> 20) == 0x41) return ILDR; - if(((i & BITS(25,27)) >> 25) == 5) return IBRANCH; - - return 0; -} - -static ulong -iadd(Ureg *ur, Instr i) -{ - ulong Rd = REG(i, 12, 15); - ulong Rn = REG(i, 16, 19); - - if(Rd != 15 || !condpass(i, ur->psr)) - return ur->pc+4; - - return REGVAL(ur, Rn) + shifterval(ur, i); -} - -static ulong -ibranch(Ureg *ur, Instr i) -{ - if(!condpass(i, ur->psr)) - return ur->pc+4; - return ur->pc + ((signed long)(i << 8) >> 6) + 8; -} - -static ulong -ildm(Ureg *ur, Instr i) -{ - if((i & BIT(15)) == 0) - return ur->pc+4; - - return *(multiaddr(ur, i) + nbits(i & BITS(15, 0))); -} - -static ulong -ildr(Ureg *ur, Instr i) -{ - if(REG(i, 12, 19) != 15 || !condpass(i, ur->psr)) - return ur->pc+4; - - return *address(ur, i); -} - -static ulong -imov(Ureg *ur, Instr i) -{ - if(REG(i, 12, 15) != 15 || !condpass(i, ur->psr)) - return ur->pc+4; - - return shifterval(ur, i); -} - -static int -condpass(Instr i, ulong psr) -{ - uchar n = COND_N(psr); - uchar z = COND_Z(psr); - uchar c = COND_C(psr); - uchar v = COND_V(psr); - - switch(LSR(i,28)) { - case 0: return z; - case 1: return !z; - case 2: return c; - case 3: return !c; - case 4: return n; - case 5: return !n; - case 6: return v; - case 7: return !v; - case 8: return c && !z; - case 9: return !c || z; - case 10: return n == v; - case 11: return n != v; - case 12: return !z && (n == v); - case 13: return z && (n != v); - case 14: return 1; - case 15: return 0; - } -} - -static ulong -shifterval(Ureg *ur, Instr i) -{ - if(i & BIT(25)) { // IMMEDIATE - ulong imm = i & BITS(0,7); - ulong s = (i & BITS(8,11)) >> 7; // this contains the * 2 - return ROR(imm, s); - } else { - ulong Rm = REGVAL(ur, REG(i, 0, 3)); - ulong s = (i & BITS(7,11)) >> 7; - - switch((i & BITS(6,4)) >> 4) { - case 0: // LSL - return Rm << s; - case 1: // LSLREG - s = REGVAL(ur, s >> 1) & 0xFF; - if(s >= 32) return 0; - return Rm << s; - case 2: // LSRIMM - return LSR(Rm, s); - case 3: // LSRREG - s = REGVAL(ur, s >> 1) & 0xFF; - if(s >= 32) return 0; - return LSR(Rm, s); - case 4: // ASRIMM - if(s == 0) { - if(Rm & BIT(31) == 0) - return 0; - return 0xFFFFFFFF; - } - return ASR(Rm, s); - case 5: // ASRREG - s = REGVAL(ur, s >> 1) & 0xFF; - if(s >= 32) { - if(Rm & BIT(31) == 0) - return 0; - return 0xFFFFFFFF; - } - return ASR(Rm, s); - case 6: // RORIMM - if(s == 0) - return (COND_C(ur->psr) << 31) | LSR(Rm, 1); - return ROR(Rm, s); - case 7: // RORREG - s = REGVAL(ur, s >> 1) & 0xFF; - if(s == 0 || (s & 0xF) == 0) - return Rm; - return ROR(Rm, s & 0xF); - } - } -} - -static ulong* -address(Ureg *ur, Instr i) -{ - ulong Rn = REGVAL(ur, REG(i, 16, 19)); - - if(i & BIT(24) == 0) // POSTIDX - return (ulong*)REGVAL(ur, Rn); - if(i & BIT(25) == 0) { // OFFSET - if(i & BIT(23)) - return (ulong*)(REGVAL(ur, Rn) + (i & BITS(0, 11))); - return (ulong*)(REGVAL(ur, Rn) - (i & BITS(0, 11))); - } else { // REGOFF - ulong Rm = REGVAL(ur, REG(i, 0, 3)); - ulong index = 0; - switch(i & BITS(5,6) >> 5) { - case 0: index = Rm << ((i & BITS(7, 11)) >> 7); break; - case 1: index = LSR(Rm, ((i & BITS(7, 11)) >> 7)); break; - case 2: index = ASR(Rm, ((i & BITS(7, 11)) >> 7)); break; - case 3: - if(i & BITS(7, 11) == 0) - index = (COND_C(ur->psr) << 31) | LSR(Rm, 1); - else - index = ROR(Rm, (i & BITS(7, 11)) >> 7); - break; - } - if(i & BIT(23)) - return (ulong*)(Rn + index); - return (ulong*)(Rn - index); - } -} - -static ulong* -multiaddr(Ureg *ur, Instr i) -{ - ulong Rn = REGVAL(ur, REG(i, 16, 19)); - - switch((i >> 23) & 3) { - case 0: return (ulong*)(Rn - (nbits(i & BITS(0,15))*4)+4); - case 1: return (ulong*)Rn; - case 2: return (ulong*)(Rn - (nbits(i & BITS(0,15))*4)); - case 3: return (ulong*)(Rn + 4); - } -} - -static int -nbits(ulong v) -{ - int n = 0; - int i; - for(i = 0; i < 32; i++) { - if(v & 1) - ++n; - v = LSR(v, 1); - } - return n; -} diff --git a/os/pxa/trap.c b/os/pxa/trap.c deleted file mode 100644 index 43117330..00000000 --- a/os/pxa/trap.c +++ /dev/null @@ -1,587 +0,0 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "ureg.h" -#include "../port/error.h" - -#define waslo(sr) (!((sr) & (PsrDirq|PsrDfiq))) - -typedef struct Handler Handler; -struct Handler { - void (*r)(Ureg*, void*); - void *a; - char name[KNAMELEN]; - Handler *next; -}; - -static Handler irqvec[32]; -static Handler gpiovec[MaxGPIObit+1]; -static Lock veclock; - -Instr BREAK = 0xE6BAD010; - -int (*breakhandler)(Ureg*, Proc*); -int (*catchdbg)(Ureg *, uint); -void (*suspendcode)(void); - -extern void (*serwrite)(char *, int); - -/* - * Interrupt sources not masked by splhi(): special - * interrupt handlers (eg, profiler or watchdog), not allowed - * to share regular kernel data structures. All interrupts are - * masked by splfhi(), which should only be used sparingly. - * splflo enables FIQ but no others. - */ -enum { - IRQ_NONMASK = (1 << IRQtimer3) | (1 << IRQtimer2), -}; - -void -intrenable(int sort, int v, void (*f)(Ureg*, void*), void* a, char *name) -{ - int x, o; - ulong m; - GpioReg *g; - Handler *ie; - - ilock(&veclock); - switch(sort) { - case GPIOfalling: - case GPIOrising: - case GPIOboth: - if(v < 0 || v > MaxGPIObit) - panic("intrenable: gpio %d out of range", v); - g = GPIOREG; - o = GPR(v); - m = GPB(v); - switch(sort){ - case GPIOfalling: - g->gfer[o] |= m; - g->grer[o] &= ~m; - break; - case GPIOrising: - g->grer[o] |= m; - g->gfer[o] &= ~m; - break; - case GPIOboth: - g->grer[o] |= m; - g->gfer[o] |= m; - break; - } - g->gpdr[o] &= ~m; /* must be input */ - if(v > MaxGPIOIRQ) { - ie = &gpiovec[v]; - if(ie->r != nil) - iprint("duplicate gpio irq: %d (%s)\n", v, ie->name); - ie->r = f; - ie->a = a; - strncpy(ie->name, name, KNAMELEN-1); - ie->name[KNAMELEN-1] = 0; - iunlock(&veclock); - return; - } - v += IRQgpio0; - /*FALLTHROUGH for GPIO sources 0-MaxGPIOIRQ */ - case IRQ: - if(v < 0 || v > 31) - panic("intrenable: irq source %d out of range", v); - ie = &irqvec[v]; - if(ie->r != nil) - iprint("duplicate irq: %d (%s)\n", v, ie->name); - ie->r = f; - ie->a = a; - strncpy(ie->name, name, KNAMELEN-1); - ie->name[KNAMELEN-1] = 0; - - x = splfhi(); - /* Enable the interrupt by setting the mask bit */ - INTRREG->icmr |= 1 << v; - splx(x); - break; - default: - panic("intrenable: unknown irq bus %d", sort); - } - iunlock(&veclock); -} - -void -intrdisable(int sort, int v, void (*f)(Ureg*, void*), void* a, char *name) -{ - int x, o; - GpioReg *g; - Handler *ie; - ulong m; - - ilock(&veclock); - switch(sort) { - case GPIOfalling: - case GPIOrising: - case GPIOboth: - if(v < 0 || v > MaxGPIObit) - panic("intrdisable: gpio source %d out of range", v); - if(v > MaxGPIOIRQ) - ie = &gpiovec[v]; - else - ie = &irqvec[v]; - if(ie->r != f || ie->a != a || strcmp(ie->name, name) != 0) - break; - ie->r = nil; - if(v <= MaxGPIOIRQ){ - v += IRQgpio0; - x = splfhi(); - INTRREG->icmr &= ~(1<gfer[o] &= ~m; - break; - case GPIOrising: - g->grer[o] &= ~m; - break; - case GPIOboth: - g->grer[o] &= ~m; - g->gfer[o] &= ~m; - break; - } - break; - case IRQ: - if(v < 0 || v > 31) - panic("intrdisable: irq source %d out of range", v); - ie = &irqvec[v]; - if(ie->r != f || ie->a != a || strcmp(ie->name, name) != 0) - break; - ie->r = nil; - x = splfhi(); - INTRREG->icmr &= ~(1<gedr[o]; - GPIOREG->gedr[o] = e; - for(i = 0; i < 32 && e != 0; i++){ - if(e & (1<r != nil){ - cur->r(ur, cur->a); - e &= ~(1<gfer[o] &= ~e; - GPIOREG->grer[o] &= ~e; - iprint("spurious GPIO[%d] %8.8lux interrupt\n", o,e); - } - } -} - -static void -intrs(Ureg *ur, ulong ibits) -{ - Handler *cur; - int i, s; - - for(i=0; ir != nil){ - cur->r(ur, cur->a); - ibits &= ~(1<icmr &= ~ibits; - splx(s); - } -} - -/* - * initialise R13 in each trap mode, at the start and after suspend reset. - */ -void -trapstacks(void) -{ - setr13(PsrMfiq, m->fiqstack+nelem(m->fiqstack)); - setr13(PsrMirq, m->irqstack+nelem(m->irqstack)); - setr13(PsrMabt, m->abtstack+nelem(m->abtstack)); - setr13(PsrMund, m->undstack+nelem(m->undstack)); -} - -void -trapinit(void) -{ - IntrReg *intr = INTRREG; - - intr->icmr = 0; /* mask everything */ - intr->iccr = 1; /* only enabled and unmasked interrupts wake us */ - intr->iclr = IRQ_NONMASK; - - trapstacks(); - - memmove(page0->vectors, vectors, sizeof(page0->vectors)); - memmove(page0->vtable, vtable, sizeof(page0->vtable)); - dcflush(page0, sizeof(*page0)); - -#ifdef NOTYET - suspendcode = xspanalloc(16*sizeof(ulong), CACHELINESZ, 0); - memmove(suspendcode, _suspendcode, 16*sizeof(ulong)); - dcflush(suspendcode, 8*sizeof(ulong)); -#endif - - icflushall(); - - intrenable(IRQ, IRQgpio, gpiointr, nil, "gpio"); -} - -static char *trapnames[PsrMask+1] = { - [ PsrMfiq ] "Fiq interrupt", - [ PsrMirq ] "Mirq interrupt", - [ PsrMsvc ] "SVC/SWI Exception", - [ PsrMabt ] "Prefetch Abort/Data Abort", - [ PsrMabt+1 ] "Data Abort", - [ PsrMund ] "Undefined instruction", - [ PsrMsys ] "Sys trap" -}; - -static char * -trapname(int psr) -{ - char *s; - - s = trapnames[psr & PsrMask]; - if(s == nil) - s = "Undefined trap"; - return s; -} - -static void -sys_trap_error(int type) -{ - char errbuf[ERRMAX]; - sprint(errbuf, "sys: trap: %s\n", trapname(type)); - error(errbuf); -} - -static void -faultarm(Ureg *ureg, ulong far) -{ - char buf[ERRMAX]; - - sprint(buf, "sys: trap: fault pc=%8.8lux addr=0x%lux", (ulong)ureg->pc, far); - if(1){ - iprint("%s\n", buf); - dumpregs(ureg); - } - if(far == ~0) - disfault(ureg, "dereference of nil"); - disfault(ureg, buf); -} - -/* - * All traps come here. It might be slightly slower to have all traps call trap - * rather than directly vectoring the handler. - * However, this avoids a lot of code duplication and possible bugs. - * trap is called splfhi(). - */ -void -trap(Ureg* ureg) -{ - ulong far, fsr; - int rem, t, itype; - Proc *oup; - - if(up != nil) - rem = ((char*)ureg)-up->kstack; - else - rem = ((char*)ureg)-(char*)m->stack; - if(ureg->type != PsrMfiq && rem < 256) - panic("trap %d bytes remaining (%s), up=#%8.8lux ureg=#%8.8lux pc=#%8.8ux", - rem, up?up->text:"", up, ureg, ureg->pc); - - /* - * All interrupts/exceptions should be resumed at ureg->pc-4, - * except for Data Abort which resumes at ureg->pc-8. - */ - itype = ureg->type; - if(itype == PsrMabt+1) - ureg->pc -= 8; - else - ureg->pc -= 4; - ureg->sp = (ulong)(ureg+1); - if(itype == PsrMfiq){ /* fast interrupt (eg, profiler) */ - oup = up; - up = nil; - intrs(ureg, INTRREG->icfp); - up = oup; - return; - } - - /* All other traps */ - - if(0 && ureg->psr & PsrDfiq) - panic("FIQ disabled"); - - if(up){ - up->pc = ureg->pc; - up->dbgreg = ureg; - } - switch(itype) { - case PsrMirq: - t = m->ticks; /* CPU time per proc */ - up = nil; /* no process at interrupt level */ - splflo(); /* allow fast interrupts */ - intrs(ureg, INTRREG->icip); - up = m->proc; - preemption(m->ticks - t); - break; - - case PsrMund: /* Undefined instruction */ - if(*(ulong*)ureg->pc == BREAK && breakhandler) { - int s; - Proc *p; - - p = up; - /* if(!waslo(ureg->psr) || ureg->pc >= (ulong)splhi && ureg->pc < (ulong)islo) - p = 0; */ - s = breakhandler(ureg, p); - if(s == BrkSched) { - p->preempted = 0; - sched(); - } else if(s == BrkNoSched) { - p->preempted = 1; /* stop it being preempted until next instruction */ - if(up) - up->dbgreg = 0; - return; - } - break; - } - if(up == nil) - goto faultpanic; - spllo(); - if(waserror()) { - if(waslo(ureg->psr) && up->type == Interp) - disfault(ureg, up->env->errstr); - setpanic(); - dumpregs(ureg); - panic("%s", up->env->errstr); - } - if(!fpiarm(ureg)) { - dumpregs(ureg); - sys_trap_error(ureg->type); - } - poperror(); - break; - - case PsrMsvc: /* Jump through 0 or SWI */ - if(waslo(ureg->psr) && up && up->type == Interp) { - spllo(); - dumpregs(ureg); - sys_trap_error(ureg->type); - } - setpanic(); - dumpregs(ureg); - panic("SVC/SWI exception"); - break; - - case PsrMabt: /* Prefetch abort */ - if(catchdbg && catchdbg(ureg, 0)) - break; - /* FALL THROUGH */ - case PsrMabt+1: /* Data abort */ - fsr = mmugetfsr(); - far = mmugetfar(); - if(fsr & (1<<9)) { - mmuputfsr(fsr & ~(1<<9)); - if(catchdbg && catchdbg(ureg, fsr)) - break; - print("Debug/"); - } - if(waslo(ureg->psr) && up && up->type == Interp) { - spllo(); - faultarm(ureg, far); - } - iprint("Data Abort: FSR %8.8luX FAR %8.8luX\n", fsr, far); xdelay(1); - /* FALL THROUGH */ - - default: /* ??? */ -faultpanic: - setpanic(); - dumpregs(ureg); - panic("exception %uX %s\n", ureg->type, trapname(ureg->type)); - break; - } - - splhi(); - if(up) - up->dbgreg = 0; /* becomes invalid after return from trap */ -} - -void -setpanic(void) -{ - if(breakhandler != 0) /* don't mess up debugger */ - return; - INTRREG->icmr = 0; - spllo(); - consoleprint = 1; - serwrite = uartputs; -} - -int -isvalid_wa(void *v) -{ - return (ulong)v >= KZERO && (ulong)v < conf.topofmem && !((ulong)v & 3); -} - -int -isvalid_va(void *v) -{ - return (ulong)v >= KZERO && (ulong)v < conf.topofmem; -} - -void -dumplongs(char *msg, ulong *v, int n) -{ - int i, l; - - l = 0; - iprint("%s at %.8p: ", msg, v); - for(i=0; i= 4){ - iprint("\n %.8p: ", v); - l = 0; - } - if(isvalid_va(v)){ - iprint(" %.8lux", *v++); - l++; - }else{ - iprint(" invalid"); - break; - } - } - iprint("\n"); -} - -static void -_dumpstack(Ureg *ureg) -{ - ulong *v, *l; - ulong inst; - ulong *estack; - int i; - - l = (ulong*)(ureg+1); - if(!isvalid_wa(l)){ - iprint("invalid ureg/stack: %.8p\n", l); - return; - } - print("ktrace /kernel/path %.8ux %.8ux %.8ux\n", ureg->pc, ureg->sp, ureg->r14); - if(up != nil && l >= (ulong*)up->kstack && l <= (ulong*)(up->kstack+KSTACK-4)) - estack = (ulong*)(up->kstack+KSTACK); - else if(l >= (ulong*)m->stack && l <= (ulong*)((ulong)m+BY2PG-4)) - estack = (ulong*)((ulong)m+BY2PG-4); - else{ - iprint("unknown stack\n"); - return; - } - i = 0; - for(; ltype)); - if((ureg->psr & PsrMask) != PsrMsvc) - print(" in %s", trapname(ureg->psr)); - print("\n"); - print("PSR %8.8uX type %2.2uX PC %8.8uX LINK %8.8uX\n", - ureg->psr, ureg->type, ureg->pc, ureg->link); - print("R14 %8.8uX R13 %8.8uX R12 %8.8uX R11 %8.8uX R10 %8.8uX\n", - ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10); - print("R9 %8.8uX R8 %8.8uX R7 %8.8uX R6 %8.8uX R5 %8.8uX\n", - ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5); - print("R4 %8.8uX R3 %8.8uX R2 %8.8uX R1 %8.8uX R0 %8.8uX\n", - ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0); - print("Stack is at: %8.8luX\n", ureg); - print("PC %8.8lux LINK %8.8lux\n", (ulong)ureg->pc, (ulong)ureg->link); - - if(up) - print("Process stack: %8.8lux-%8.8lux\n", - up->kstack, up->kstack+KSTACK-4); - else - print("System stack: %8.8lux-%8.8lux\n", - (ulong)(m+1), (ulong)m+BY2PG-4); - dumplongs("stack", (ulong *)(ureg + 1), 16); - _dumpstack(ureg); -} - -/* - * Fill in enough of Ureg to get a stack trace, and call a function. - * Used by debugging interface rdb. - */ -void -callwithureg(void (*fn)(Ureg*)) -{ - Ureg ureg; - ureg.pc = getcallerpc(&fn); - ureg.sp = (ulong)&fn; - ureg.r14 = 0; - fn(&ureg); -} - -void -dumpstack(void) -{ - callwithureg(_dumpstack); -} - -void -trapspecial(int (*f)(Ureg *, uint)) -{ - catchdbg = f; -} -- cgit v1.2.3