M bitsy/clock.c => bitsy/clock.c +1 -0
@@ 64,6 64,7 @@ clockintr(Ureg *ureg, void*)
/* post interrupt 1/HZ secs from now */
timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;
+ drawactive(0); /* screen saver */
portclock(ureg);
}
M bitsy/devpcmcia.c => bitsy/devpcmcia.c +0 -1
@@ 315,7 315,6 @@ slotinfo(Ureg*, void*)
static void
increfp(PCMslot *pp)
{
- slotinfo(nil, nil);
if(incref(&pcmcia) == 1){
egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 1);
egpiobits(EGPIO_pcmcia_reset, 0);
M bitsy/devpenmouse.c => bitsy/devpenmouse.c +1 -0
@@ 425,6 425,7 @@ penmousetrack(int b, int x, int y)
mouse.qfull = 1;
}
wakeup(&mouse.r);
+ drawactive(1);
}
int
M bitsy/devuda1341.c => bitsy/devuda1341.c +6 -4
@@ 922,10 922,12 @@ audioclose(Chan *c)
}
qunlock(&audio);
poperror();
- print("total dmas: %lud\n", iostats.totaldma);
- print("dmas while idle: %lud\n", iostats.idledma);
- print("dmas while busy: %lud\n", iostats.faildma);
- print("out of order dma: %lud\n", iostats.samedma);
+ if (debug) {
+ print("total dmas: %lud\n", iostats.totaldma);
+ print("dmas while idle: %lud\n", iostats.idledma);
+ print("dmas while busy: %lud\n", iostats.faildma);
+ print("out of order dma: %lud\n", iostats.samedma);
+ }
}
break;
}
M bitsy/fns.h => bitsy/fns.h +3 -1
@@ 13,6 13,8 @@ void clockinit(void);
void delay(int);
void µdelay(int);
void dmainit(void);
+void _doze(void);
+void (*doze)(void);
void egpiobits(ulong, int);
void evenaddr(ulong);
void exppackpower(int);
@@ 27,7 29,7 @@ void gpiointrenable(ulong, int, void (*)(Ureg*, void*), void*, char*);
void h3650uartsetup(void);
void icacheinvalidate(void);
void idle(void);
-#define idlehands() /* nothing to do in the runproc */
+void idlehands(void);
void intrenable(int, void (*)(Ureg*, void*), void*, char*);
int iprint(char*, ...);
void irpower(int);
M bitsy/l.s => bitsy/l.s +21 -0
@@ 431,3 431,24 @@ TEXT gotolabel(SB), $-4
MOVW 4(R0), R14 /* pc */
MOVW $1, R0
RET
+
+
+/* The first MCR instruction of this function needs to be on a cache-line
+ * boundary; to make this happen, it will be copied (in trap.c).
+ *
+ * Doze puts the machine into idle mode. Any interrupt will get it out
+ * at the next instruction (the RET, to be precise).
+ */
+TEXT _doze(SB), $-4
+ MOVW $UCDRAMZERO, R1
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MOVW R0,R0
+ MCR CpPWR, 0, R0, C(CpTest), C(0x2), 2
+ MOVW (R1), R0
+ MCR CpPWR, 0, R0, C(CpTest), C(0x8), 2
+ RET
M bitsy/mem.h => bitsy/mem.h +4 -1
@@ 51,8 51,10 @@
#define REGTOP 0xA8000000 /* ... */
#define FLASHZERO 0xB0000000 /* 128 meg for flash */
#define FLASHTOP 0xB8000000 /* ... */
-#define DRAMZERO 0xC0000000 /* 128 meg for memory */
+#define DRAMZERO 0xC0000000 /* 128 meg for dram */
#define DRAMTOP 0xC8000000 /* ... */
+#define UCDRAMZERO 0xC8000000 /* 128 meg for dram (uncached/unbuffered) */
+#define UCDRAMTOP 0xD0000000 /* ... */
#define NULLZERO 0xE0000000 /* 128 meg for cache flush zeroes */
#define NULLTOP 0xE8000000 /* ... */
#define USTKTOP 0x2000000 /* byte just beyond user stack */
@@ 143,6 145,7 @@
* Coprocessors
*/
#define CpMMU 15
+#define CpPWR 15
/*
* Internal MMU coprocessor registers
M bitsy/mmu.c => bitsy/mmu.c +5 -0
@@ 79,6 79,11 @@ mmuinit(void)
| L1Cached | L1Buffered
| ((PHYSDRAM0+o)&L1SectBaseMask);
+ /* uncached DRAM */
+ for(o = 0; o < UCDRAMTOP-UCDRAMZERO; o += OneMeg)
+ l1table[(UCDRAMZERO+o)>>20] = L1Section | L1KernelRW| L1Domain0
+ | ((PHYSDRAM0+o)&L1SectBaseMask);
+
/* map zeros area */
for(o = 0; o < NULLTOP-NULLZERO; o += OneMeg)
l1table[(NULLZERO+o)>>20] = L1Section | L1KernelRW | L1Domain0
M bitsy/power.c => bitsy/power.c +13 -1
@@ 5,11 5,11 @@
#include "fns.h"
#include "io.h"
#include "ureg.h"
-#include "init.h"
#include "pool.h"
/* Power management for the bitsy */
+#ifdef NOTDEF
enum {
pmcr_sf = 0,
@@ 66,3 66,15 @@ sa1100_power_off(void)
/* enter sleep mode */
powerregs->pmcr = 1<<pmcr_sf;
}
+
+void
+idlehands(void)
+{
+}
+#endif
+
+void
+idlehands(void)
+{
+ doze();
+}
M bitsy/screen.c => bitsy/screen.c +8 -1
@@ 244,6 244,8 @@ screeninit(void)
out.pos.y = 0;
out.bwid = memdefont->info[' '].width;
+ blanktime = 3; /* minutes */
+
screenwin();
}
@@ 301,7 303,12 @@ setcolor(ulong p, ulong r, ulong g, ulong b)
void
blankscreen(int blank)
{
- USED(blank);
+ if (blank) {
+ lcdpower(0);
+ } else {
+ lcdpower(1);
+ lcdinit();
+ }
}
void
M bitsy/screen.h => bitsy/screen.h +2 -0
@@ 1,6 1,8 @@
typedef struct Cursorinfo Cursorinfo;
typedef struct Cursor Cursor;
+extern ulong blanktime;
+
struct Cursorinfo {
Lock;
};
M bitsy/trap.c => bitsy/trap.c +110 -51
@@ 22,17 22,15 @@ struct Intrregs *intrregs;
typedef struct Vctl {
Vctl* next; /* handlers on this vector */
-
char name[NAMELEN]; /* of driver */
- int irq;
- ulong irqbit;
-
void (*f)(Ureg*, void*); /* handler to call */
void* a; /* argument to call it with */
} Vctl;
-static Lock vctllock;
-static Vctl *vctl;
+static Lock vctllock;
+static Vctl *vctl[32];
+static Vctl *gpiovctl[27];
+static int gpioirqref[12];
/*
* Layout at virtual address 0.
@@ 41,10 39,16 @@ typedef struct Vpage0 {
void (*vectors[8])(void);
ulong vtable[8];
- ulong hole[16];
+ /* Doze goes here because it needs to be on a cache-line boundary */
+ ulong doze[16];
} Vpage0;
Vpage0 *vpage0;
+void (*doze)(void);
+
+static void irq(Ureg*);
+static void gpiointr(Ureg*, void*);
+
/*
* set up for exceptioons
*/
@@ 55,8 59,13 @@ trapinit(void)
vpage0 = (Vpage0*)EVECTORS;
memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
- memset(vpage0->hole, 0, sizeof(vpage0->hole));
+
+ /* Move the twelve instructions of doze() to a cache-line boundary: */
+ memmove(vpage0->doze, _doze, 12*sizeof(long));
wbflush();
+
+ /* Set the doze function pointer to the moved _doze() routine */
+ doze = (void(*)(void))vpage0->doze;
/* use exception vectors at 0xFFFF0000 */
mappedIvecEnable();
@@ 112,18 121,19 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
{
Vctl *v;
+ if(irq >= nelem(vctl) || irq < 0)
+ panic("intrenable");
+
v = xalloc(sizeof(Vctl));
- v->irq = irq;
- v->irqbit = 1<<irq;
v->f = f;
v->a = a;
strncpy(v->name, name, NAMELEN-1);
v->name[NAMELEN-1] = 0;
lock(&vctllock);
- v->next = vctl;
- vctl = v;
- intrregs->icmr |= v->irqbit;
+ v->next = vctl[irq];
+ vctl[irq] = v;
+ intrregs->icmr |= 1<<irq;
unlock(&vctllock);
}
@@ 131,38 141,54 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
* enable an interrupt on gpio line. edge is encoded as follows
*/
void
-gpiointrenable(ulong bit, int edge, void (*f)(Ureg*, void*), void* a, char *name)
+gpiointrenable(ulong mask, int edge, void (*f)(Ureg*, void*), void* a, char *name)
{
- int irq;
+ int irq, bit;
+ Vctl *v;
- /* figure out which interrupt */
- for(irq = 0; irq < 28; irq++)
- if((1<<irq) & bit)
+ /* figure out which bit */
+ for(bit = 0; bit < 32; bit++)
+ if((1<<bit) == mask)
break;
- if(irq >= 28)
- panic("gpiointrenable %lux", bit);
- if(irq > 11)
+
+ irq = bit;
+ if(bit >= nelem(gpiovctl) || bit < 0)
+ panic("gpiointrenable");
+ if(bit > 11)
irq = 11;
- /* it had better be input */
- if(bit & gpioregs->direction)
- panic("gpiointrenable %lux of output pin", bit);
+ /* the pin had better be configured as input */
+ if((1<<bit) & gpioregs->direction)
+ panic("gpiointrenable of output pin %d", bit);
- /* set edge register */
+ /* create a second level vctl for the gpio edge interrupt */
+ v = xalloc(sizeof(Vctl));
+ v->f = f;
+ v->a = a;
+ strncpy(v->name, name, NAMELEN-1);
+ v->name[NAMELEN-1] = 0;
+
+ lock(&vctllock);
+ v->next = gpiovctl[bit];
+ gpiovctl[bit] = v;
+ unlock(&vctllock);
+
+ /* set edge register to enable interrupt */
switch(edge){
case GPIOboth:
- gpioregs->rising |= bit;
- gpioregs->falling |= bit;
+ gpioregs->rising |= mask;
+ gpioregs->falling |= mask;
break;
case GPIOfalling:
- gpioregs->falling |= bit;
+ gpioregs->falling |= mask;
break;
case GPIOrising:
- gpioregs->rising |= bit;
+ gpioregs->rising |= mask;
break;
}
- intrenable(irq, f, a, name);
+ if(gpioirqref[irq]++ == 0)
+ intrenable(irq, gpiointr, nil, "gpio edge");
}
/*
@@ 214,8 240,6 @@ void
trap(Ureg *ureg)
{
ulong inst;
- int found;
- Vctl *v;
int user, x, rv;
ulong va, fsr;
char buf[ERRLEN];
@@ 231,28 255,13 @@ trap(Ureg *ureg)
else
ureg->pc -= 4;
- if(ureg->type == PsrMirq){
- found = 0;
- va = intrregs->icip;
-
- /* clear any gpio edge interrupt */
- gpioregs->edgestatus = va & 0xFFF;
-
- for(v = vctl; v != nil; v = v->next){
- if(v->irqbit & va){
- v->f(ureg, v->a);
- found = 1;
- }
- }
- if(!found)
- print("unknown interrupt: %lux\n", intrregs->icip);
- goto out;
- }
-
switch(ureg->type){
default:
panic("unknown trap");
break;
+ case PsrMirq:
+ irq(ureg);
+ break;
case PsrMabt: /* prefetch fault */
faultarm(ureg, ureg->pc, user, 1);
break;
@@ 325,13 334,63 @@ trap(Ureg *ureg)
break;
}
-out:
splhi();
if(user && (up->procctl || up->nnote))
notify(ureg);
}
/*
+ * here on irq's
+ */
+static void
+irq(Ureg *ur)
+{
+ ulong va;
+ int i;
+ Vctl *v;
+
+ va = intrregs->icip;
+
+ for(i = 0; i < 32; i++){
+ if(((1<<i) & va) == 0)
+ continue;
+ for(v = vctl[i]; v != nil; v = v->next){
+ v->f(ur, v->a);
+ va &= ~(1<<i);
+ }
+ }
+ if(va)
+ print("unknown interrupt: %lux\n", va);
+}
+
+/*
+ * here on gpio interrupts
+ */
+static void
+gpiointr(Ureg *ur, void*)
+{
+ ulong va;
+ int i;
+ Vctl *v;
+
+ va = gpioregs->edgestatus;
+ gpioregs->edgestatus = va;
+
+iprint("gpio intr %lux\n", va);
+
+ for(i = 0; i < 27; i++){
+ if(((1<<i) & va) == 0)
+ continue;
+ for(v = gpiovctl[i]; v != nil; v = v->next){
+ v->f(ur, v->a);
+ va &= ~(1<<i);
+ }
+ }
+ if(va)
+ print("unknown gpio interrupt: %lux\n", va);
+}
+
+/*
* system calls
*/
#include "../port/systab.h"
M port/proc.c => port/proc.c +1 -1
@@ 200,7 200,6 @@ loop:
*/
spllo();
for(;;){
- idlehands();
if((++(m->fairness) & 0x3) == 0){
/*
* once in a while, run process that's been waiting longest
@@ 240,6 239,7 @@ loop:
}
}
}
+ idlehands();
}
found: