~kris/9p

9hist

868e661a0eeffb9ebbe4d79a844bb8fbc80ef7b5 — David du Colombier 25 years ago c2a804b
Plan 9 from Bell Labs 2000-11-30
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: