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

📄 devlml.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"#include	"io.h"#include	"devlml.h"#define DBGREAD	0x01#define DBGWRIT	0x02#define DBGINTR	0x04#define DBGINTS	0x08int debug = 0;// Lml 22 driverenum{	Qdir,	Qctl0,	Qjpg0,	Qraw0,	Qctl1,	Qjpg1,	Qraw1,};#define	QID(q)		((ulong)(q).path)#define	QIDLML(q)	((((ulong)(q).path)-1)>>1)static Dirtab lmldir[]={	".",			{Qdir, 0, QTDIR},	0,	DMDIR|0555,	"lml0ctl",		{Qctl0},			0,	0666,	"lml0jpg",		{Qjpg0},			0,	0444,	"lml0raw",	{Qraw0},			0,	0444,	"lml1ctl",		{Qctl1},			0,	0666,	"lml1jpg",		{Qjpg1},			0,	0444,	"lml1raw",	{Qraw1},			0,	0444,};typedef struct LML LML;struct LML {	// Hardware	Pcidev *		pcidev;	ulong		pciBaseAddr;	// Allocated memory	CodeData *	codedata;	// Software state	ulong		jpgframeno;	int			frameNo;	Rendez		sleepjpg;	int			jpgopens;} lmls[NLML];int nlml;static FrameHeader	jpgheader = {	MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8,	{ 'L', 'M', 'L', '\0'},	-1, 0, 0,  0};#define writel(v, a) *(ulong *)(a) = (v)#define readl(a) *(ulong*)(a)static intgetbuffer(void *x){	static last = NBUF-1;	int l = last;	LML *lml;	lml = x;	for (;;) {		last = (last+1) % NBUF;		if (lml->codedata->statCom[last] & STAT_BIT)			return last + 1;		if (last == l)			return 0;	}	return 0;}static longjpgread(LML *lml, void *va, long nbytes, vlong, int dosleep) {	int bufno;	FrameHeader *jpgheader;		// reads should be of size 1 or sizeof(FrameHeader)	// Frameno is the number of the buffer containing the data	while ((bufno = getbuffer(lml)) == 0 && dosleep)		sleep(&lml->sleepjpg, getbuffer, lml);	if (--bufno < 0)		return 0;	jpgheader = (FrameHeader*)(lml->codedata->frag[bufno].hdr+2);	if (nbytes == sizeof(FrameHeader)) {		memmove(va, jpgheader, sizeof(FrameHeader));		return sizeof(FrameHeader);	}	if (nbytes == 1) {		*(char *)va = bufno;		return 1;	}	return 0;}static void lmlintr(Ureg *, void *);static voidprepbuf(LML *lml) {	int i;	for (i = 0; i < NBUF; i++) {		lml->codedata->statCom[i] = PADDR(&(lml->codedata->fragdesc[i]));		lml->codedata->fragdesc[i].addr = PADDR(lml->codedata->frag[i].fb);		// Length is in double words, in position 1..20		lml->codedata->fragdesc[i].leng = (FRAGSIZE >> 1) | FRAGM_FINAL_B;		memmove(lml->codedata->frag[i].hdr+2, &jpgheader, sizeof(FrameHeader)-2);	}}static voidlmlreset(void){	Physseg segbuf;	ulong regpa;	void *regva;	ISAConf isa;	char name[32];	Pcidev *pcidev;	LML *lml;	pcidev = nil;		for (nlml = 0; nlml < NLML && (pcidev = pcimatch(pcidev, VENDOR_ZORAN, ZORAN_36067)); nlml++){		if(isaconfig("lml", nlml, &isa) == 0) {			if (debug) print("lml %d not in plan9.ini\n", nlml);			break;		}		lml = &lmls[nlml];		lml->pcidev = pcidev;		lml->codedata = (CodeData*)(((ulong)xalloc(Codedatasize+ BY2PG) + BY2PG-1) & ~(BY2PG-1));		if (lml->codedata == nil) {			print("devlml: xalloc(%ux, %ux, 0)\n", Codedatasize, BY2PG);			return;		}		print("Installing Motion JPEG driver %s, irq %d\n", MJPG_VERSION, pcidev->intl); 		print("MJPG buffer at 0x%.8lux, size 0x%.8ux\n", lml->codedata, Codedatasize); 		// Get access to DMA memory buffer		lml->codedata->pamjpg = PADDR(lml->codedata->statCom);		prepbuf(lml);		print("zr36067 found at 0x%.8lux", pcidev->mem[0].bar & ~0x0F);		regpa = pcidev->mem[0].bar & ~0x0F;		regva = vmap(regpa, pcidev->mem[0].size);		if (regva == 0) {			print("lml: failed to map registers\n");			return;		}		lml->pciBaseAddr = (ulong)regva;		print(", mapped at 0x%.8lux\n", lml->pciBaseAddr);		memset(&segbuf, 0, sizeof(segbuf));		segbuf.attr = SG_PHYSICAL;		sprint(name, "lml%d.mjpg", nlml);		kstrdup(&segbuf.name, name);		segbuf.pa = PADDR(lml->codedata);		segbuf.size = Codedatasize;		if (addphysseg(&segbuf) == -1) {			print("lml: physsegment: %s\n", name);			return;		}		memset(&segbuf, 0, sizeof(segbuf));		segbuf.attr = SG_PHYSICAL;		sprint(name, "lml%d.regs", nlml);		kstrdup(&segbuf.name, name);		segbuf.pa = (ulong)regpa;		segbuf.size = pcidev->mem[0].size;		if (addphysseg(&segbuf) == -1) {			print("lml: physsegment: %s\n", name);			return;		}		// Interrupt handler		intrenable(pcidev->intl, lmlintr, lml, pcidev->tbdf, "lml");	}	return;}static Chan*lmlattach(char *spec){	return devattach('V', spec);}static Walkqid*lmlwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, lmldir, nelem(lmldir), devgen);}static intlmlstat(Chan *c, uchar *db, int n){	return devstat(c, db, n, lmldir, nelem(lmldir), devgen);}static Chan*lmlopen(Chan *c, int omode) {	int i;	LML *lml;	if (omode != OREAD)		error(Eperm);	c->aux = 0;	i = 0;	switch((ulong)c->qid.path){	case Qctl1:		i++;	case Qctl0:		if (i >= nlml)			error(Eio);		break;	case Qjpg1:	case Qraw1:		i++;	case Qjpg0:	case Qraw0:		// allow one open		if (i >= nlml)			error(Eio);		lml = lmls+i;		if (lml->jpgopens)			error(Einuse);		lml->jpgopens = 1;		lml->jpgframeno = 0;		prepbuf(lml);		break;	}	return devopen(c, omode, lmldir, nelem(lmldir), devgen);}static voidlmlclose(Chan *c) {	int i;	i = 0;	switch((ulong)c->qid.path){	case Qjpg1:	case Qraw1:		i++;	case Qjpg0:	case Qraw0:		lmls[i].jpgopens = 0;		break;	}}static longlmlread(Chan *c, void *va, long n, vlong voff) {	int i;	uchar *buf = va;	long off = voff;	LML *lml;	static char lmlinfo[1024];	int len;	i = 0;	switch((ulong)c->qid.path){	case Qdir:		return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen);	case Qctl1:		i++;	case Qctl0:		if (i >= nlml)			error(Eio);		lml = lmls+i;		len = snprint(lmlinfo, sizeof lmlinfo, "lml%djpg	lml%draw\nlml%d.regs	0x%lux	0x%ux\nlml%d.mjpg	0x%lux	0x%ux\n",			i, i,			i, lml->pcidev->mem[0].bar & ~0x0F, lml->pcidev->mem[0].size,			i, PADDR(lml->codedata), Codedatasize);		if (voff > len)			return 0;		if (n > len - voff)			n = len - voff;		memmove(va, lmlinfo+voff, n);		return n;	case Qjpg1:		i++;	case Qjpg0:		if (i >= nlml)			error(Eio);		return jpgread(lmls+i, buf, n, off, 1);	case Qraw1:		i++;	case Qraw0:		if (i >= nlml)			error(Eio);		return jpgread(lmls+i, buf, n, off, 0);	}}static longlmlwrite(Chan *, void *, long, vlong) {	error(Eperm);	return 0;}Dev lmldevtab = {	'V',	"video",	lmlreset,	devinit,		devshutdown,	lmlattach,	lmlwalk,	lmlstat,	lmlopen,	devcreate,	lmlclose,	lmlread,	devbread,	lmlwrite,	devbwrite,	devremove,	devwstat,};static voidlmlintr(Ureg *, void *x) {	FrameHeader *jpgheader;	ulong fstart, fno, flags, statcom;	LML *lml;	lml = x;	flags = readl(lml->pciBaseAddr+INTR_STAT);	// Reset all interrupts from 067	writel(0xff000000, lml->pciBaseAddr + INTR_STAT);	if(flags & INTR_JPEGREP) {		if(debug&(DBGINTR))			print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags);		fstart = lml->jpgframeno & 0x00000003;		for (;;) {			lml->jpgframeno++;			fno = lml->jpgframeno & 0x00000003;			if (lml->codedata->statCom[fno] & STAT_BIT)				break;			if (fno == fstart) {				if (debug & DBGINTR)					print("Spurious lml jpg intr?\n");				return;			}		}		statcom = lml->codedata->statCom[fno];		jpgheader = (FrameHeader *)(lml->codedata->frag[fno].hdr+2);		jpgheader->frameNo = lml->jpgframeno;		jpgheader->ftime  = todget(nil);		jpgheader->frameSize = (statcom & 0x00ffffff) >> 1;		jpgheader->frameSeqNo = statcom >> 24;		wakeup(&lml->sleepjpg);	}	return;}

⌨️ 快捷键说明

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