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

📄 devastar.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 3 页
字号:
	} else if(strncmp(cmsg, "run", 3) == 0){		/* start up downloaded program */		startcp(a);	} else		error(Ebadarg);	qunlock(a);	poperror();}/* *  Send a command to a channel *  (must be called with ac qlocked) */static intchancmddone(void *arg){	Astarchan *ac = arg;	int x;	LOCKPAGE(ac->a, 0);	x = ac->ccb->cmd;	UNLOCKPAGE(ac->a);	return !x;}static voidchancmd(Astarchan *ac, int cmd){	CCB *ccb;	int status;	ccb = ac->ccb;	LOCKPAGE(ac->a, 0);	ccb->cmd = cmd;	UNLOCKPAGE(ac->a);	/* wait outside of lock */	tsleep(&ac->r, chancmddone, ac, 1000);	LOCKPAGE(ac->a, 0);	status = ccb->status;	cmd = ccb->cmd;	UNLOCKPAGE(ac->a);	if(cmd){		print("#G%d: cmd didn't terminate\n", ac->a->id);		error(Eio);	}	if(status){		print("#G%d: cmd status %ux\n", ac->a->id, status);		error(Eio);	}}/* *  enable a channel for IO, set standard params. *  (must be called with ac qlocked) */static voidenable(Astarchan *ac){	Astar *a = ac->a;	int n;	/* make sure we control RTS, DTR and break */	LOCKPAGE(a, 0);	n = LEUS(ac->ccb->proto) | Cmctl;	ac->ccb->proto = LEUS(n);	ac->ccb->outlow = 64;	UNLOCKPAGE(a);	chancmd(ac, Cconfall);	astarctl(ac, "l8");	astarctl(ac, "p0");	astarctl(ac, "d1");	astarctl(ac, "r1");	chancmd(ac, Crcvena|Cxmtena|Cconfall);}/* *  disable a channel for IO *  (must be called with ac qlocked) */static voiddisable(Astarchan *ac){	int n;	astarctl(ac, "d0");	astarctl(ac, "r0");	LOCKPAGE(ac->a, 0);	n = LEUS(ac->ccb->proto) | Cmctl;	ac->ccb->proto = LEUS(n);	UNLOCKPAGE(ac->a);	chancmd(ac, Crcvdis|Cxmtdis|Cflushin|Cflushout|Cconfall);	ac->dsr = ac->dcd = 0;}/* *  change channel parameters *  (must be called with ac qlocked) */static voidastarctl(Astarchan *ac, char *cmd){	int i, n;	int command;	CCB *ccb;	Astar *a;	/* let output drain for a while */	for(i = 0; i < 16 && qlen(ac->oq); i++)		tsleep(&ac->r, (int (*)(void*))qlen, ac->oq, 125);	if(strncmp(cmd, "break", 5) == 0)		cmd = "k";	ccb = ac->ccb;	command = 0;	i = atoi(cmd+1);	a = ac->a;	LOCKPAGE(a, 0);	switch(*cmd){	case 'B':	case 'b':		/* set baud rate (high rates are special - only 16 bits) */		switch(i){		case 76800:			ccb->baud = LEUS(Cb76800);			break;		case 115200:			ccb->baud = LEUS(Cb115200);			break;		default:			ccb->baud = LEUS(i);			break;		}		ac->baud = i;		/* set trigger level to about 50  per second */		n = i/500;		i = (LEUS(ccb->inlim) - LEUS(ccb->inbase))/2;		if(n > i)			n = i;		ccb->intrigger = LEUS(n);		command = Cconfall;		break;	case 'D':	case 'd':		n = LEUS(ccb->mctl);		if(i)			 n |= Cdtrctl;		else			 n &= ~Cdtrctl;		ac->dtr = i;		ccb->mctl = LEUS(n);		break;	case 'f':	case 'F':		qflush(ac->oq);		break;	case 'H':	case 'h':		qhangup(ac->iq, nil);		qhangup(ac->oq, nil);		break;	case 'L':	case 'l':		n = i - 5;		if(n < 0 || n > 3)			error(Ebadarg);		n |= LEUS(ccb->format) & ~Clenmask;		ccb->format = LEUS(n);		command = Cconfall;		break;	case 'm':	case 'M':		/* turn on cts */		n = LEUS(ccb->proto);		if(i){			n |= Cobeycts|Cgenrts;			n &= ~Cmctl;		} else {			n &= ~(Cobeycts|Cgenrts);			n |= Cmctl;		}		ccb->proto = LEUS(n);		command = Cconfall;		break;	case 'n':	case 'N':		qnoblock(ac->oq, i);		break;	case 'P':	case 'p':		switch(*(cmd+1)){		case 'e':			n = Cevenpar;			break;		case 'o':			n = Coddpar;			break;		default:			n = Cnopar;			break;		}		n |= LEUS(ccb->format) & ~Cparmask;		ccb->format = LEUS(n);		command = Cconfall;		break;	case 'K':	case 'k':		if(i <= 0)			i = 250;		n = LEUS(ccb->mctl) | Cbreakctl;		ccb->mctl = LEUS(n);		UNLOCKPAGE(a);		tsleep(&ac->r, return0, 0, i);		LOCKPAGE(a, 0);		n &= ~Cbreakctl;		ccb->mctl = LEUS(n);		break;	case 'R':	case 'r':		n = LEUS(ccb->mctl);		if(i)			 n |= Crtsctl;		else			 n &= ~Crtsctl;		ccb->mctl = LEUS(n);		ac->rts = i;		break;	case 'Q':	case 'q':		qsetlimit(ac->iq, i);		qsetlimit(ac->oq, i);		break;	case 'X':	case 'x':		n = LEUS(ccb->proto);		if(i)			n |= Cobeyxon;		else			n &= ~Cobeyxon;		ccb->proto = LEUS(n);		command = Cconfall;		break;	}	UNLOCKPAGE(a);	if(command)		chancmd(ac, command);}static longastarwrite(Chan *c, void *buf, long n, vlong off){	Astar *a;	Astarchan *ac;	char cmsg[32];	ulong offset = off;	if(c->qid.path & CHDIR)		error(Eperm);	a = astar[BOARD(c->qid.path)];	switch(TYPE(c->qid.path)){	case Qmem:		if(a->pci)			return pcimemwrite(a, buf, n, offset);		return isamemwrite(a, buf, n, offset);	case Qbctl:		if(n > sizeof cmsg)			n = sizeof(cmsg) - 1;		memmove(cmsg, buf, n);		cmsg[n] = 0;		bctlwrite(a, cmsg);		return n;	case Qdata:		ac = a->c + CHAN(c->qid.path);		return qwrite(ac->oq, buf, n);	case Qctl:		ac = a->c + CHAN(c->qid.path);		if(n > sizeof cmsg)			n = sizeof(cmsg) - 1;		memmove(cmsg, buf, n);		cmsg[n] = 0;		if(waserror()){			qunlock(ac);			nexterror();		}		qlock(ac);		astarctl(ac, cmsg);		qunlock(ac);		poperror();	}	return 0;}static voidastarwstat(Chan *c, char *dp){	Dir d;	Astarchan *ac;	if(!iseve())		error(Eperm);	if(CHDIR & c->qid.path)		error(Eperm);	if(TYPE(c->qid.path) != Qdata && TYPE(c->qid.path) != Qctl)		error(Eperm);	ac = astar[BOARD(c->qid.path)]->c + CHAN(c->qid.path);	convM2D(dp, &d);	d.mode &= 0666;	ac->perm = d.mode;}Dev astardevtab = {	'G',	"astar",	astarreset,	devinit,	astarattach,	devclone,	astarwalk,	astarstat,	astaropen,	devcreate,	astarclose,	astarread,	devbread,	astarwrite,	devbwrite,	devremove,	astarwstat,};/* *  get output going */static voidastaroutput(Astarchan *ac){	Astar *a = ac->a;	CCB *ccb = ac->ccb;	uchar buf[256];	uchar *rp, *wp, *bp, *ep, *p, *e;	int n;	if(a->needpage)		setpage(a, 0);	ep = a->addr;	rp = ep + LEUS(ccb->outrp);	wp = ep + LEUS(ccb->outwp);	bp = ep + LEUS(ccb->outbase);	ep = ep + LEUS(ccb->outlim);	for(;;){		n = rp - wp - 1;		if(n < 0)			n += ep - bp + 1;		if(n == 0)			break;		if(n > sizeof(buf))			n = sizeof(buf);		n = qconsume(ac->oq, buf, n);		if(n <= 0)			break;		if(a->needpage)			setpage(a, bp - a->addr);		e = buf + n;		for(p = buf; p < e;){			*wp++ = *p++;			if(wp > ep)				wp = bp;		}		if(a->needpage)			setpage(a, 0);		ccb->outwp = LEUS(wp - a->addr);	}}static voidastarkick(void *v){	Astarchan *ac;	ac = v;	ilock(&ac->a->pagelock);	astaroutput(ac);	iunlock(&ac->a->pagelock);}/* *  process input */static voidastarinput(Astarchan *ac){	Astar *a = ac->a;	CCB *ccb = ac->ccb;	uchar buf[256];	uchar *rp, *wp, *bp, *ep, *p, *e;	int n;	if(a->needpage)		setpage(a, 0);	ep = a->addr;	rp = ep + LEUS(ccb->inrp);	wp = ep + LEUS(ccb->inwp);	bp = ep + LEUS(ccb->inbase);	ep = ep + LEUS(ccb->inlim);	for(;;){		n = wp - rp;		if(n == 0)			break;		if(n < 0)			n += ep - bp + 1;		if(n > sizeof(buf))			n = sizeof(buf);		if(a->needpage)			setpage(a, bp - a->addr);		e = buf + n;		for(p = buf; p < e;){			*p++ = *rp++;			if(rp > ep)				rp = bp;		}		if(ac->opens == 0 || qproduce(ac->iq, buf, n) < 0)			break;	/* flow controlled or not open */		if(a->needpage)			setpage(a, 0);		ccb->inrp = LEUS(rp - a->addr);	}	if(a->needpage)		setpage(a, 0);}/* *  get flow controlled input going again */static voidastarkickin(void *v){	Astarchan *ac;	ac = v;	ilock(&ac->a->pagelock);	astarinput(ac);	iunlock(&ac->a->pagelock);}static voidastarmodemchange(Astarchan *ac){	Astar *a = ac->a;	int mstat;	if(a->needpage)		setpage(a, 0);	mstat = LEUS(ac->ccb->mstat);	if(ac->hup_dsr && ac->dsr == 1 && (mstat & Cdsrstat) == 0	|| ac->hup_dcd && ac->dcd == 1 && (mstat & Cdcdstat) == 0){		qhangup(ac->iq, nil);		qhangup(ac->oq, nil);	}	ac->dsr = mstat & Cdsrstat;	ac->dcd = mstat & Cdcdstat;}/* *  handle an interrupt */static voidastarintr(Ureg *ur, void *arg){	Astar *a = arg;	Astarchan *ac;	ulong globvec, vec, invec, outvec, errvec, mvec, cmdvec;	int c, status;	USED(ur);	if(a->running == 0)		panic("#G%d: interrupt but cp not running\n", a->id);	lock(&a->pagelock);	if(a->needpage)		setpage(a, 0);	/* get causes */	globvec = LEUS(xchgw(&a->gcb->serv, 0));	USED(globvec);	invec = LEUS(xchgw(&a->gcb->inserv, 0));	outvec = LEUS(xchgw(&a->gcb->outserv, 0));	errvec = LEUS(xchgw(&a->gcb->errserv, 0));	mvec = LEUS(xchgw(&a->gcb->modemserv, 0));	cmdvec = LEUS(xchgw(&a->gcb->cmdserv, 0));	/* reenable interrupts */	if(a->pci){		/*		 * Only the PCI doorbell interrupt is expected.		 */		status = inl(a->port+PCIstatus);		if((status & 0x0810E000) != 0x00002000)			print("#G%d: unexpected interrupt %uX\n", a->id, status);		if(status & 0x00002000)			outl(a->port+PCIdoorbell1, 1);	}	a->gcb->cmd2 = LEUS(Gintack);	/* service interrupts */	ac = a->c;	for(vec = invec; vec; vec >>= 1){		if(vec&1)			astarinput(ac);		ac++;	}	ac = a->c;	for(vec = outvec; vec; vec >>= 1){		if(vec&1)			astaroutput(ac);		ac++;	}	ac = a->c;	for(vec = cmdvec; vec; vec >>= 1){		if(vec&1)			wakeup(&ac->r);		ac++;	}	ac = a->c;	for(vec = mvec; vec; vec >>= 1){		if(vec&1)			astarmodemchange(ac);		ac++;	}	ac = a->c;	for(vec = errvec; vec; vec >>= 1){		c = LEUS(ac->ccb->errstat);		if(c & Cframing)			ac->framing++;		if(c & Coverrun)			ac->overrun++;		ac++;	}	unlock(&a->pagelock);}

⌨️ 快捷键说明

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