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

📄 devtv.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	dev = DEV(c->qid);	switch (TYPE(c->qid)) {	case Qdir:		if (i == DEVDOTDOT) {			mkqid(&qid, Qdir, 0, QTDIR);			devdir(c, qid, "#V", 0, eve, 0555, dp);			return 1;		}		if (i >= ntvs)			return -1;			mkqid(&qid, QID(i, Qsubdir), 0, QTDIR);		snprint(up->genbuf, sizeof(up->genbuf), "tv%d", i);		devdir(c, qid, up->genbuf, 0, eve, 0555, dp);		return 1;	case Qsubdir:		if (i == DEVDOTDOT) {			mkqid(&qid, QID(dev, Qdir), 0, QTDIR);			snprint(up->genbuf, sizeof(up->genbuf), "tv%d", dev);			devdir(c, qid, up->genbuf, 0, eve, 0555, dp);			return 1;		}				return tv1gen(c, i + Qsubbase, dp);		case Qvdata:	case Qadata:	case Qctl:	case Qregs:		return tv1gen(c, TYPE(c->qid), dp);	default:		return -1;	}}static Walkqid *tvwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, 0, 0, tvgen);}static inttvstat(Chan *c, uchar *db, int n){	return devstat(c, db, n, 0, 0, tvgen);}static Chan*tvopen(Chan *c, int omode){	if (omode != OREAD && 		TYPE(c->qid) != Qctl && TYPE(c->qid) != Qvdata)		error(Eperm);	switch (TYPE(c->qid)) {	case Qdir:		return devopen(c, omode, nil, 0, tvgen);	case Qadata:		if (tvs[DEV(c->qid)].bt878 == nil)			error(Enonexist);		break;	}	c->mode = openmode(omode);	c->flag |= COPEN;	c->offset = 0;	if (TYPE(c->qid) == Qadata)		c->aux = nil;	return c;}static voidtvclose(Chan *){}static intaudioblock(void *){	return 1;}	static longtvread(Chan *c, void *a, long n, vlong offset){	static char regs[10 * K];	static int regslen;	Tv *tv;	char *e, *p;	uchar *src;	USED(offset);	switch(TYPE(c->qid)) {	case Qdir:	case Qsubdir:		return devdirread(c, a, n, 0, 0, tvgen);	case Qvdata: {		int bpf, nb;		tv = &tvs[DEV(c->qid)];		bpf = ntsc_hactive * ntsc_vactive * getbitspp(tv) / 8;		if (offset >= bpf) 			return 0;		nb = n;		if (offset + nb > bpf)			nb = bpf - offset;		ilock(tv);		if (tv->frames == nil || tv->lvframe >= tv->nframes ||			tv->frames[tv->lvframe].fbase == nil) {			iunlock(tv);			return 0;		}		src = tv->frames[tv->lvframe].fbase;		incref(&tv->fref);		iunlock(tv);		memmove(a, src + offset, nb);		decref(&tv->fref);		return nb;	}	case Qadata: {		ulong uablock = (ulong)c->aux, bnum, tvablock;		int boffs, nbytes;		tv = &tvs[DEV(c->qid)];		if (tv->bt878 == nil)			error("#V: No audio device");		if (tv->absize == 0)			error("#V: audio not initialized");		bnum = offset / tv->absize;		boffs = offset % tv->absize;		nbytes = tv->absize - boffs;		incref(&tv->aref);		while (1) {			tvablock = tv->narblocks;	// Current tv block.			if (uablock == 0)				uablock = tvablock - 1;			if (tvablock >= uablock + bnum + tv->narblocks)				uablock = tvablock - 1 - bnum;			if (uablock + bnum == tvablock) {				sleep(tv, audioblock, nil);				continue;			}			break;		}		print("uablock %ld, bnum %ld, boffs %d, nbytes %d, tvablock %ld\n",				uablock, bnum, boffs, nbytes, tvablock);		src = tv->abuf + ((uablock + bnum) % tv->nablocks) * tv->absize;		print("copying from %.8ulX (abuf %.8ulX), nbytes %d (block %ld.%ld)\n", 				src + boffs, tv->abuf, nbytes, uablock, bnum);		memmove(a, src + boffs, nbytes);		decref(&tv->aref);				uablock += (boffs + nbytes) % tv->absize;		c->aux = (void*)uablock;		return nbytes;	}	case Qctl: {		char str[128];		tv = &tvs[DEV(c->qid)];		snprint(str, sizeof str, "%dx%dx%d %s channel %d %s\n", 				ntsc_hactive, ntsc_vactive, getbitspp(tv),				getcolormode(tv->cfmt), tv->channel,				tv->ainfo);		return readstr(offset, a, strlen(str) + 1, str);	}			case Qregs:		if (offset == 0) {			Bt848 *bt848;			int i;			tv = &tvs[DEV(c->qid)];			bt848 = tv->bt848;			e = regs + sizeof(regs);			p = regs;			for (i = 0; i < 0x300 >> 2; i++)				p = seprint(p, e, "%.3X %.8ulX\n", i << 2, ((ulong *)bt848)[i]);			if (tv->bt878) {				bt848 = tv->bt878;				for (i = 0; i < 0x300 >> 2; i++)					p = seprint(p, e, "%.3X %.8ulX\n", 							i << 2, ((ulong *)bt848)[i]);			}						regslen = p - regs;		}		if (offset >= regslen) 			return 0;		if (offset + n > regslen)			n = regslen - offset;		return readstr(offset, a, n, &regs[offset]);	default:		n = 0;		break;	}	return n;}static longtvwrite(Chan *c, void *a, long n, vlong){	Cmdbuf *cb;	Cmdtab *ct;	Tv *tv;	tv = &tvs[DEV(c->qid)];	switch(TYPE(c->qid)) {	case Qctl:		cb = parsecmd(a, n);		if(waserror()){			free(cb);			nexterror();		}		ct = lookupcmd(cb, tvctlmsg, nelem(tvctlmsg));		switch (ct->index) {		case CMvstart:			vstart(tv, (int)strtol(cb->f[1], (char **)nil, 0), 					ntsc_hactive, ntsc_vactive, ntsc_hactive);			break;		case CMastart:			astart(tv, cb->f[1], (uint)strtol(cb->f[2], (char **)nil, 0),					(uint)strtol(cb->f[3], (char **)nil, 0),					(uint)strtol(cb->f[4], (char **)nil, 0));			break;		case CMastop:			astop(tv);			break;		case CMvgastart:			vgastart(tv, strtoul(cb->f[1], (char **)nil, 0),					(int)strtoul(cb->f[2], (char **)nil, 0));			break;		case CMvstop:			vstop(tv);			break;		case CMchannel:			frequency(tv, (int)strtol(cb->f[1], (char **)nil, 0), 				(int)strtol(cb->f[2], (char **)nil, 0));			break;		case CMcolormode:			colormode(tv, cb->f[1]);			break;		case CMvolume:			if (!tv->msp)				error("#V: No volume control");			mspvolume(tv, 0, (int)strtol(cb->f[1], (char **)nil, 0), 						(int)strtol(cb->f[2], (char **)nil, 0));			break;		case CMmute:			if (!tv->msp)				error("#V: No volume control");			mspvolume(tv, 1, 0, 0);			break;		}		poperror();		free(cb);		break;	default:		error(Eio);	}	return n;}Dev tvdevtab = {	'V',	"tv",	devreset,	tvinit,	devshutdown,	tvattach,	tvwalk,	tvstat,	tvopen,	devcreate,	tvclose,	tvread,	devbread,	tvwrite,	devbwrite,	devremove,	devwstat,};static voidtvinterrupt(Ureg *, Tv *tv){	Bt848 *bt848 = tv->bt848,		*bt878 = tv->bt878;	while (1) {		ulong vstat, astat;		uchar fnum;		vstat = bt848->intstat;		fnum = (vstat >> intstat_riscstatshift) & 0xf;		vstat &= bt848->intmask;		if (bt878)			astat = bt878->intstat & bt878->intmask;		else			astat = 0;		if (vstat == 0 && astat == 0)			break;		if (astat)		print("vstat %.8luX, astat %.8luX\n", vstat, astat);		bt848->intstat = vstat;		if (bt878)			bt878->intstat = astat;		if ((vstat & intstat_fmtchg) == intstat_fmtchg) {			iprint("int: fmtchg\n");			vstat &= ~intstat_fmtchg;		}		if ((vstat & intstat_vpress) == intstat_vpress) {//			iprint("int: vpress\n");			vstat &= ~intstat_vpress;		}				if ((vstat & intstat_vsync) == intstat_vsync) {			vstat &= ~intstat_vsync;		}		if ((vstat & intstat_scerr) == intstat_scerr) {			iprint("int: scerr\n");			bt848->gpiodmactl &= 				~(gpiodmactl_riscenable|gpiodmactl_fifoenable);			bt848->gpiodmactl |= gpiodmactl_fifoenable;			bt848->gpiodmactl |= gpiodmactl_riscenable;			vstat &= ~intstat_scerr;		}		if ((vstat & intstat_risci) == intstat_risci) {			tv->lvframe = fnum;			vstat &= ~intstat_risci;		}					if ((vstat & intstat_ocerr) == intstat_ocerr) {			iprint("int: ocerr\n");			vstat &= ~intstat_ocerr;		}		if ((vstat & intstat_fbus) == intstat_fbus) {			iprint("int: fbus\n");			vstat &= ~intstat_fbus;		}		if (vstat)			iprint("int: (v) ignored interrupts %.8ulX\n", vstat);		if ((astat & intstat_risci) == intstat_risci) {			tv->narblocks++;			if ((tv->narblocks % 100) == 0)				print("a");			wakeup(tv);			astat &= ~intstat_risci;		}		if ((astat & intstat_fdsr) == intstat_fdsr) {			iprint("int: (a) fdsr\n");			bt848->gpiodmactl &= 				~(gpiodmactl_acapenable | 					gpiodmactl_riscenable | gpiodmactl_fifoenable);			astat &= ~intstat_fdsr;		}					if (astat)			iprint("int: (a) ignored interrupts %.8ulX\n", astat);	}}static inti2cread(Tv *tv, uchar off, uchar *v){		Bt848 *bt848 = tv->bt848;	ulong intstat;	int i;	bt848->intstat	= intstat_i2cdone;	bt848->i2c = (off << 24) | tv->i2ccmd;	intstat = -1;	for (i = 0; i != 1000; i++) {		if ((intstat = bt848->intstat) & intstat_i2cdone)			break;		microdelay(1000);	}	if (i == 1000) {		print("i2cread: timeout\n");		return 0;	}	if ((intstat & intstat_i2crack) == 0)		return 0;	*v = bt848->i2c >> 8;	return 1;}static inti2cwrite(Tv *tv, uchar addr, uchar sub, uchar data, int both){	Bt848 *bt848 = tv->bt848;	ulong intstat, d;	int i;	bt848->intstat	= intstat_i2cdone;	d = (addr << 24) | (sub << 16) | tv->i2ccmd;	if (both)		d |= (data << 8) | i2c_bt848w3b;	bt848->i2c = d;	intstat = 0;	for (i = 0; i != 1000; i++) {		if ((intstat = bt848->intstat) & intstat_i2cdone)			break;		microdelay(1000);	}	if (i == i2c_timeout) {		print("i2cwrite: timeout\n");		return 0;	}	if ((intstat & intstat_i2crack) == 0)		return 0;	return 1;}static ulong *riscpacked(ulong pa, int fnum, int w, int h, int stride, ulong **lastjmp){	ulong *p, *pbase;	int i;	pbase = p = (ulong *)malloc((h + 6) * 2 * sizeof(ulong));	assert(p);	assert(w <= 0x7FF);	*p++ = riscsync | riscsync_resync | riscsync_vre;	*p++ = 0;	*p++ = riscsync | riscsync_fm1;	*p++ = 0;	for (i = 0; i != h / 2; i++) {		*p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;		*p++ = pa + i * 2 * stride;	}	*p++ = riscsync | riscsync_resync | riscsync_vro;	*p++ = 0;	*p++ = riscsync | riscsync_fm1;	*p++ = 0;	for (i = 0; i != h / 2; i++) {		*p++ = riscwrite | w | riscwrite_sol | riscwrite_eol;		*p++ = pa + (i * 2 + 1) * stride;	}	// reset status.  you really need two instructions ;-(.	*p++ = riscjmp | (0xf << risclabelshift_reset); 		*p++ = PADDR(p);	*p++ = riscjmp | riscirq | (fnum << risclabelshift_set);	*lastjmp = p;	return pbase;}static ulong *riscplanar411(ulong pa, int fnum, int w, int h, ulong **lastjmp){	ulong *p, *pbase, Cw, Yw, Ch;	uchar *Ybase, *Cbbase, *Crbase;	int i, bitspp;	bitspp = 6;	assert(w * bitspp / 8 <= 0x7FF);	pbase = p = (ulong *)malloc((h + 6) * 5 * sizeof(ulong));	assert(p);	Yw = w;	Ybase = (uchar *)pa;	Cw = w >> 1;	Ch = h >> 1;	Cbbase = Ybase + Yw * h;	Crbase = Cbbase + Cw * Ch; 	*p++ = riscsync | riscsync_resync | riscsync_vre;	*p++ = 0;	*p++ = riscsync | riscsync_fm3;	*p++ = 0;	for (i = 0; i != h / 2; i++) {		*p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;		*p++ = (Cw << 16) | Cw;			*p++ = (ulong)(Ybase + i * 2 * Yw);		*p++ = (ulong)(Cbbase + i * Cw);		// Do not interlace		*p++ = (ulong)(Crbase + i * Cw);	}	*p++ = riscsync | riscsync_resync | riscsync_vro;	*p++ = 0;	*p++ = riscsync | riscsync_fm3;	*p++ = 0;	for (i = 0; i != h / 2; i++) {		*p++ = riscwrite1s23 | Yw | riscwrite_sol | riscwrite_eol;		*p++ = (Cw << 16) | Cw;			*p++ = (ulong)(Ybase + (i * 2 + 1) * Yw);	}	// reset status.  you really need two instructions ;-(.	*p++ = riscjmp | (0xf << risclabelshift_reset); 		*p++ = PADDR(p);	*p++ = riscjmp | riscirq | (fnum << risclabelshift_set);	*lastjmp = p;	return pbase;}static ulong *riscplanar422(ulong pa, int fnum, int w, int h, ulong **lastjmp){	ulong *p, *pbase, Cw, Yw;	uchar *Ybase, *Cbbase, *Crbase;	int i, bpp;	bpp = 2;	assert(w * bpp <= 0x7FF);	pbase = p = (ulong *)malloc((h + 6) * 5 * sizeof(ulong));	assert(p);	Yw = w;	Ybase = (uchar *)pa;	Cw = w >> 1;	Cbbase = Ybase + Yw * h;	Crbase = Cbbase + Cw * h;	*p++ = riscsync | riscsync_resync | riscsync_vre;	*p++ = 0;	*p++ = riscsync | riscsync_fm3;	*p++ = 0;	for (i = 0; i != h / 2; i++) {		*p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;		*p++ = (Cw << 16) | Cw;			*p++ = (ulong)(Ybase + i * 2 * Yw);		*p++ = (ulong)(Cbbase + i * 2 * Cw);		*p++ = (ulong)(Crbase + i * 2 * Cw);	}	*p++ = riscsync | riscsync_resync | riscsync_vro;	*p++ = 0;	*p++ = riscsync | riscsync_fm3;	*p++ = 0;	for (i = 0; i != h / 2; i++) {		*p++ = riscwrite123 | Yw | riscwrite_sol | riscwrite_eol;		*p++ = (Cw << 16) | Cw;			*p++ = (ulong)(Ybase + (i * 2 + 1) * Yw);		*p++ = (ulong)(Cbbase + (i * 2 + 1) * Cw);		*p++ = (ulong)(Crbase + (i * 2 + 1) * Cw);	}	// reset status.  you really need two instructions ;-(.	*p++ = riscjmp | (0xf << risclabelshift_reset); 		*p++ = PADDR(p);	*p++ = riscjmp | riscirq | (fnum << risclabelshift_set);	*lastjmp = p;	return pbase;}static ulong *riscaudio(ulong pa, int nblocks, int bsize){	ulong *p, *pbase;	int i;	pbase = p = (ulong *)malloc((nblocks + 3) * 2 * sizeof(ulong));	assert(p);	*p++ = riscsync|riscsync_fm1;	*p++ = 0;		for (i = 0; i != nblocks; i++) {		*p++ = riscwrite | riscwrite_sol | riscwrite_eol | bsize | riscirq |				((i & 0xf) << risclabelshift_set) | 				((~i & 0xf) << risclabelshift_reset);		*p++ = pa + i * bsize;	}	*p++ = riscsync | riscsync_vro;	*p++ = 0;	*p++ = riscjmp;	*p++ = PADDR(pbase);	USED(p);	return pbase;}static voidvactivate(Tv *tv, Frame *frames, int nframes){	Bt848 *bt848 = tv->bt848;	ilock(tv);	if (tv->frames) {		iunlock(tv);		error(Einuse);	}	poperror();	tv->frames = frames;	tv->nframes = nframes;	bt848->riscstrtadd = PADDR(tv->frames[0].fstart);	bt848->capctl |= capctl_captureodd|capctl_captureeven;	bt848->gpiodmactl |= gpiodmactl_fifoenable;	bt848->gpiodmactl |= gpiodmactl_riscenable;		iunlock(tv);}static voidvstart(Tv *tv, int nframes, int w, int h, int stride){	Frame *frames;	int bitspp, i, bpf;	if (nframes >= 0x10)		error(Ebadarg);	bitspp = getbitspp(tv);	bpf = w * h * bitspp / 8;	// Add one as a spare.	frames = (Frame *)malloc(nframes * sizeof(Frame));	assert(frames);	if (waserror()) {		for (i = 0; i != nframes; i++)			if (frames[i].fbase)				free(frames[i].fbase);		free(frames);		nexterror();	}	memset(frames, 0, nframes * sizeof(Frame));	for (i = 0; i != nframes; i++) {		if ((frames[i].fbase = (uchar *)malloc(bpf)) == nil)			error(Enomem);				switch (tv->cfmt) {		case colorfmt_YCbCr422:			frames[i].fstart = riscplanar422(PADDR(frames[i].fbase), i, 									 w, h, &frames[i].fjmp);			break;		case colorfmt_YCbCr411:			frames[i].fstart = riscplanar411(PADDR(frames[i].fbase), i, 									 w, h, &frames[i].fjmp);			break;		case colorfmt_rgb16:			frames[i].fstart = riscpacked(PADDR(frames[i].fbase), i, 								     w * bitspp / 8, h, stride * bitspp / 8, 								     &frames[i].fjmp);			break;		default:			panic("vstart: Unsupport colorformat\n");		}	}	for (i = 0; i != nframes; i++)		*frames[i].fjmp = 			PADDR((i == nframes - 1)? frames[0].fstart: frames[i + 1].fstart);	vactivate(tv, frames, nframes);}static voidastart(Tv *tv, char *input, uint rate, uint nab, uint nasz){	Bt848 *bt878 = tv->bt878;	ulong *arisc;	int selector;

⌨️ 快捷键说明

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