⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 devirq.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"m8260.h"#include	"../port/error.h"enum{	IRQ0 = 18,	Level = 0,	Edge = 1,};enum{	Qdir,	Qirq1,	Qirq2,	Qirq3,	Qirq4,	Qirq5,	Qirq6,	Qirq7,	Qmstimer,	Qfpgareset,	NIRQ,};static Dirtab irqdir[]={	".",		{Qdir, 0, QTDIR},	0,	DMDIR|0555,	"irq1",		{Qirq1},		0,	0666,	"irq2",		{Qirq2},		0,	0666,	"irq3",		{Qirq1},		0,	0666,	"irq4",		{Qirq1},		0,	0666,	"irq5",		{Qirq1},		0,	0666,	"irq6",		{Qirq1},		0,	0666,	"irq7",		{Qirq1},		0,	0666,	"mstimer",	{Qmstimer},		0,	0666,	"fpgareset",	{Qfpgareset},		0,	0222,};enum{	CMinterrupt,	CMmode,	CMreset,	CMwait,	CMdebug,};Cmdtab irqmsg[] ={	CMinterrupt,	"interrupt",	2,	CMmode,		"mode",		2,	CMreset,	"reset",	1,	CMwait,		"wait",		1,	CMdebug,	"debug",	1,};typedef struct Irqconfig Irqconfig;struct Irqconfig {	int		intenable;	/* Interrupts are enabled */	int		mode;		/* level == 0; edge == 1 */	ulong		interrupts;	/* Count interrupts */	ulong		sleepints;	/* interrupt count when waiting */	Rendez		r;		/* Rendez-vous point for interrupt waiting */	Irqconfig	*next;	Timer;};Irqconfig *irqconfig[NIRQ];	/* irqconfig[0] is not used */Lock irqlock;static void interrupt(Ureg*, void*);void dumpvno(void);static voidticmstimer(Ureg*, Timer *t){	Irqconfig *ic;	ic = t->ta; 	ic->interrupts++;	wakeup(&ic->r);}voidirqenable(Irqconfig *ic, int irq){	/* call with ilock(&irqlock) held */	if (ic->intenable)		return;	if (irq == Qmstimer){		if (ic->tnext == nil)			ic->tns = MS2NS(ic->mode);		ic->tmode = Tperiodic;		timeradd(&ic->Timer);	}else{		if (irqconfig[irq]){			ic->next = irqconfig[irq];			irqconfig[irq] = ic;		}else{			ic->next = nil;			irqconfig[irq] = ic;			intrenable(IRQ0 + irq, interrupt, &irqconfig[irq], irqdir[irq].name);		}	}	ic->intenable = 1;}voidirqdisable(Irqconfig *ic, int irq){	Irqconfig **pic;	/* call with ilock(&irqlock) held */	if (ic->intenable == 0)		return;	if (irq == Qmstimer){		timerdel(&ic->Timer);	}else{		for(pic = &irqconfig[irq]; *pic != ic; pic = &(*pic)->next)			assert(*pic);		*pic = (*pic)->next;		if (irqconfig[irq] == nil)			intrdisable(IRQ0 + irq, interrupt, &irqconfig[irq], irqdir[irq].name);	}	ic->intenable = 0;}static Chan*irqattach(char *spec){	return devattach('b', spec);}static Walkqid*irqwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name,nname, irqdir, nelem(irqdir), devgen);}static intirqstat(Chan *c, uchar *dp, int n){	return devstat(c, dp, n, irqdir, nelem(irqdir), devgen);}static Chan*irqopen(Chan *c, int omode){	Irqconfig *ic;	int irq;	irq = (ulong)c->qid.path;	if(irq != Qdir){		ic = mallocz(sizeof(Irqconfig), 1);		ic->tf = ticmstimer;		ic->ta = ic;		if (irq == Qmstimer)			ic->mode = 1000;		c->aux = ic;	}	return devopen(c, omode, irqdir, nelem(irqdir), devgen);}static voidirqclose(Chan *c){	int irq;	Irqconfig *ic;	irq = (ulong)c->qid.path;	if(irq == Qdir)		return;	ic = c->aux;	if (irq > Qmstimer)		return;	ilock(&irqlock);	irqdisable(ic, irq);	iunlock(&irqlock);	free(ic);}static intirqtfn(void *arg){	Irqconfig *ic;	ic = arg;	return ic->sleepints != ic->interrupts;}static longirqread(Chan *c, void *buf, long n, vlong){	int irq;	Irqconfig *ic;	char tmp[24];	if(n <= 0)		return n;	irq = (ulong)c->qid.path;	if(irq == Qdir)		return devdirread(c, buf, n, irqdir, nelem(irqdir), devgen);	if(irq > Qmstimer){		print("irqread 0x%llux\n", c->qid.path);		error(Egreg);	}	ic = c->aux;	if (ic->intenable == 0)		error("disabled");	ic->sleepints = ic->interrupts;	sleep(&ic->r, irqtfn, ic);	if (irq == Qmstimer)		snprint(tmp, sizeof tmp, "%11lud %d", ic->interrupts, ic->mode);	else		snprint(tmp, sizeof tmp, "%11lud %s", ic->interrupts, ic->mode ?"edge":"level");	n = readstr(0, buf, n, tmp);	return n;}static longirqwrite(Chan *c, void *a, long n, vlong){	int irq;	Irqconfig *ic;	Cmdbuf *cb;	Cmdtab *ct;	if(n <= 0)		return n;	irq = (ulong)c->qid.path;	if(irq <= 0 || irq >= nelem(irqdir)){		print("irqwrite 0x%llux\n", c->qid.path);		error(Egreg);	}	if (irq == Qfpgareset){		if (strncmp(a, "reset", 5) == 0)			fpgareset();		else			error(Egreg);		return n;	}	ic = c->aux;	cb = parsecmd(a, n);	if(waserror()) {		free(cb);		nexterror();	}	ct = lookupcmd(cb, irqmsg, nelem(irqmsg));	switch(ct->index) {	case 	CMinterrupt:		/* Turn interrupts on or off */		if (strcmp(cb->f[1], "on") == 0){			ilock(&irqlock);			irqenable(ic, irq);			iomem->siprr = 0x65009770;			iunlock(&irqlock);		}else if (strcmp(cb->f[1], "off") == 0){			ilock(&irqlock);			irqdisable(ic, irq);			iunlock(&irqlock);		}else			error(Ebadarg);		break;	case CMmode:		/* Set mode */		if (irq == Qmstimer){			ic->mode = strtol(cb->f[1], nil, 0);			if (ic->mode <= 0){				ic->tns = MS2NS(1000);				ic->mode = 1000;				error(Ebadarg);			}			ic->tns = MS2NS(ic->mode);		}else if (strcmp(cb->f[1], "level") == 0){			ic->mode = Level;			iomem->siexr &= ~(0x8000 >> irq);		}else if (strcmp(cb->f[1], "edge") == 0){			ic->mode = Edge;			iomem->siexr |= 0x8000 >> irq;		}else			error(Ebadarg);		break;	case CMreset:		ic->interrupts = 0;		break;	case CMwait:		if (ic->intenable == 0)			error("interrupts are off");		ic->sleepints = ic->interrupts;		sleep(&ic->r, irqtfn, ic);		break;	case CMdebug:		print("simr h/l 0x%lux/0x%lux, sipnr h/l 0x%lux/0x%lux, siexr 0x%lux, siprr 0x%lux\n",			iomem->simr_h, iomem->simr_l,			iomem->sipnr_h, iomem->sipnr_l,			iomem->siexr, iomem->siprr);		dumpvno();	}	poperror();	free(cb);	/* Irqi */	return n;}static voidinterrupt(Ureg*, void *arg){	Irqconfig **pic, *ic;	int irq;	pic = arg;	irq = pic - irqconfig;	if (irq <= 0 || irq > nelem(irqdir)){		print("Unexpected interrupt: %d\n", irq);		return;	}	ilock(&irqlock);	if (irq <= Qirq7)		iomem->sipnr_h |= 0x8000 >> irq;	/* Clear the interrupt */	for(ic = *pic; ic; ic = ic->next){		ic->interrupts++;		wakeup(&ic->r);	}	iunlock(&irqlock);}Dev irqdevtab = {	'b',	"irq",	devreset,	devinit,	devshutdown,	irqattach,	irqwalk,	irqstat,	irqopen,	devcreate,	irqclose,	irqread,	devbread,	irqwrite,	devbwrite,	devremove,	devwstat,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -