plan 9 kernel history: overview | file list | diff list

2001/1027/pc/devlml.c (diff list | history)

pc/devlml.c on 1999/0422
1999/0422    
#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" 
 
1999/0520    
static void *		pciPhysBaseAddr; 
static ulong		pciBaseAddr; 
static Pcidev *		pcidev; 
1999/0515    
 
2001/1012    
#define DBGREAD	0x01 
#define DBGWRIT	0x02 
1999/0526    
#define DBGINTR	0x04 
#define DBGINTS	0x08 
1999/0520    
 
2001/0527    
int debug = -1; 
1999/0520    
 
1999/0422    
// Lml 22 driver 
 
enum{ 
1999/0513    
	Qdir, 
1999/0610    
	Qjpg, 
//	Qraw, 
1999/0422    
}; 
 
1999/0513    
static Dirtab lmldir[]={ 
2001/0630    
	".",		{Qdir, 0, QTDIR},	0,	DMDIR|0555, 
	"lmljpg",	{Qjpg},			0,	0444, 
//	"lmlraw",	{Qraw},			0,	0444, 
1999/0422    
}; 
 
1999/0610    
static CodeData *	codeData; 
1999/0422    
 
1999/0610    
static ulong		jpgframeno; 
//static ulong		rawframeno; 
 
//static FrameHeader	rawheader; 
 
static FrameHeader	jpgheader[NBUF] = { 
	{ 
		MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, 
		{ 'L', 'M', 'L', '\0'}, 
		-1, 0, 0, 0, 0 
	}, { 
		MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, 
		{ 'L', 'M', 'L', '\0'}, 
		-1, 0, 0, 0, 0 
	}, { 
		MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, 
		{ 'L', 'M', 'L', '\0'}, 
		-1, 0, 0, 0, 0 
	}, { 
		MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, 
		{ 'L', 'M', 'L', '\0'}, 
		-1, 0, 0, 0, 0 
	} 
}; 
 
1999/0513    
int		frameNo; 
2001/1027    
Rendez	sleepjpg; 
1999/0610    
//Rendez		sleepraw; 
1999/0513    
int		singleFrame; 
1999/0610    
int		jpgopens; 
//int		rawopens; 
1999/0424    
 
1999/0525    
#define writel(v, a) *(ulong *)(a) = (v) 
#define readl(a) *(ulong*)(a) 
1999/0515    
 
1999/0423    
static int 
1999/0526    
getbuffer(void){ 
	static last = NBUF-1; 
	int l = last; 
1999/0423    
 
1999/0526    
	for (;;) { 
		last = (last+1) % NBUF; 
		if (codeData->statCom[last] & STAT_BIT) 
			return last; 
		if (last == l) 
1999/0610    
			sleep(&sleepjpg, return0, 0); 
1999/0423    
	} 
1999/0526    
	return 0; 
1999/0423    
} 
 
1999/0526    
static long 
1999/0610    
jpgread(Chan *, void *va, long nbytes, vlong) { 
	int bufno; 
1999/0423    
 
1999/0610    
	// reads should be of size 1 or sizeof(FrameHeader) 
	// Frameno is the number of the buffer containing the data 
	bufno = getbuffer(); 
	if (nbytes == sizeof(FrameHeader)) { 
		memmove(va, &jpgheader[bufno], sizeof jpgheader[bufno]); 
		return sizeof jpgheader[bufno]; 
	} 
	if (nbytes == 1) { 
		*(char *)va = bufno; 
		return 1; 
	} 
	return 0; 
1999/0424    
} 
 
1999/0610    
/* 
static long 
rawread(Chan *, void *va, long nbytes, vlong) { 
 
	// reads should be at least sizeof(FrameHeader) long 
	// Frameno is the number of the buffer containing the data 
	if (nbytes < sizeof(FrameHeader)) return 0; 
	sleep(&sleepraw, return0, 0); 
	memmove(va, &rawheader, sizeof rawheader); 
	return sizeof rawheader; 
} 
*/ 
 
1999/0423    
static void lmlintr(Ureg *, void *); 
 
static void 
1999/0610    
prepbuf(void) { 
	int i; 
 
	for (i = 0; i < NBUF; i++) { 
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
		codeData->fragdesc[i].addr = PADDR(&(codeData->frag[i])); 
		// Length is in double words, in position 1..20 
		codeData->fragdesc[i].leng = ((sizeof codeData->frag[i]) >> 1) | FRAGM_FINAL_B; 
	} 
} 
 
static void 
1999/0513    
lmlreset(void) 
1999/0422    
{ 
1999/0522    
	Physseg segbuf; 
	Physseg segreg; 
1999/0527    
	Physseg seggrab; 
1999/0422    
	ulong regpa; 
1999/0525    
	ulong cdsize; 
1999/0529    
	void *grabbuf; 
1999/0527    
	ulong grablen; 
2001/1026    
	ISAConf isa; 
1999/0422    
 
2001/1012    
	if(isaconfig("lml", 0, &isa) == 0) { 
		if (debug) print("lml not in plan9.ini\n"); 
		return; 
	} 
1999/0423    
	pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067); 
	if (pcidev == nil) { 
		return; 
	} 
1999/0529    
	cdsize = CODEDATASIZE; 
2001/1027    
	codeData = (CodeData*)(((ulong)xalloc(cdsize+ BY2PG) + BY2PG-1) & ~(BY2PG-1)); 
1999/0422    
	if (codeData == nil) { 
2001/1019    
		print("devlml: xalloc(%lux, %ux, 0)\n", cdsize, BY2PG); 
1999/0422    
		return; 
	} 
 
1999/0529    
	grablen = GRABDATASIZE; 
2001/1027    
	grabbuf = (void*)(((ulong)xalloc(grablen+ BY2PG) + BY2PG-1) & ~(BY2PG-1)); 
1999/0529    
	if (grabbuf == nil) { 
2001/1019    
		print("devlml: xalloc(%lux, %ux, 0)\n", grablen, BY2PG); 
1999/0527    
		return; 
	} 
 
2001/1026    
	print("Installing Motion JPEG driver %s, irq %d\n", MJPG_VERSION, pcidev->intl);  
1999/0527    
	print("MJPG buffer at 0x%.8lux, size 0x%.8lux\n", codeData, cdsize);  
1999/0529    
	print("Grab buffer at 0x%.8lux, size 0x%.8lux\n", grabbuf, grablen);  
1999/0422    
 
	// Get access to DMA memory buffer 
1999/0529    
	codeData->pamjpg = PADDR(codeData->statCom); 
	codeData->pagrab = PADDR(grabbuf); 
1999/0422    
 
1999/0610    
	prepbuf(); 
 
1999/0423    
	pciPhysBaseAddr = (void *)(pcidev->mem[0].bar & ~0x0F); 
1999/0422    
 
1999/0513    
	print("zr36067 found at 0x%.8lux", pciPhysBaseAddr); 
1999/0422    
 
1999/0423    
	regpa = upamalloc(pcidev->mem[0].bar & ~0x0F, pcidev->mem[0].size, 0); 
1999/0422    
	if (regpa == 0) { 
		print("lml: failed to map registers\n"); 
		return; 
	} 
1999/0423    
	pciBaseAddr = (ulong)KADDR(regpa); 
1999/0513    
	print(", mapped at 0x%.8lux\n", pciBaseAddr); 
1999/0422    
 
1999/0522    
	memset(&segbuf, 0, sizeof(segbuf)); 
	segbuf.attr = SG_PHYSICAL; 
2001/0630    
	kstrdup(&segbuf.name, "lmlmjpg"); 
1999/0522    
	segbuf.pa = PADDR(codeData); 
1999/0525    
	segbuf.size = cdsize; 
	if (addphysseg(&segbuf) == -1) { 
		print("lml: physsegment: lmlmjpg\n"); 
		return; 
	} 
1999/0522    
 
	memset(&segreg, 0, sizeof(segreg)); 
	segreg.attr = SG_PHYSICAL; 
2001/0630    
	kstrdup(&segreg.name, "lmlregs"); 
1999/0522    
	segreg.pa = (ulong)regpa; 
	segreg.size = pcidev->mem[0].size; 
1999/0525    
	if (addphysseg(&segreg) == -1) { 
1999/0527    
		print("lml: physsegment: lmlregs\n"); 
		return; 
	} 
 
	memset(&seggrab, 0, sizeof(seggrab)); 
	seggrab.attr = SG_PHYSICAL; 
2001/0630    
	kstrdup(&seggrab.name, "lmlgrab"); 
1999/0529    
	seggrab.pa = PADDR(grabbuf); 
1999/0527    
	seggrab.size = grablen; 
	if (addphysseg(&seggrab) == -1) { 
		print("lml: physsegment: lmlgrab\n"); 
1999/0525    
		return; 
	} 
1999/0601    
 
	// Interrupt handler 
1999/0819    
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf, "lml"); 
1999/0601    
 
1999/0529    
	return; 
1999/0422    
} 
 
static Chan* 
1999/0513    
lmlattach(char *spec) 
1999/0422    
{ 
	return devattach('V', spec); 
} 
 
2001/0630    
static Walkqid* 
lmlwalk(Chan *c, Chan *nc, char **name, int nname) 
1999/0422    
{ 
2001/0630    
	return devwalk(c, nc, name, nname, lmldir, nelem(lmldir), devgen); 
1999/0422    
} 
 
2001/0630    
static int 
lmlstat(Chan *c, uchar *db, int n) 
1999/0422    
{ 
2001/0630    
	return devstat(c, db, n, lmldir, nelem(lmldir), devgen); 
1999/0422    
} 
 
static Chan* 
1999/0518    
lmlopen(Chan *c, int omode) { 
1999/0517    
 
1999/0422    
	c->aux = 0; 
2001/0630    
	switch((ulong)c->qid.path){ 
1999/0610    
	case Qjpg: 
1999/0601    
		// allow one open 
1999/0610    
		if (jpgopens) 
1999/0424    
			error(Einuse); 
1999/0610    
		jpgopens = 1; 
		jpgframeno = 0; 
		prepbuf(); 
1999/0422    
		break; 
1999/0610    
/*	case Qraw: 
		// allow one open 
		if (rawopens) 
			error(Einuse); 
		rawopens = 1; 
		rawframeno = 0; 
		break; 
*/ 
1999/0422    
	} 
1999/0513    
	return devopen(c, omode, lmldir, nelem(lmldir), devgen); 
1999/0422    
} 
 
static void 
1999/0518    
lmlclose(Chan *c) { 
 
2001/0630    
	switch((ulong)c->qid.path){ 
1999/0610    
	case Qjpg: 
		jpgopens = 0; 
		break; 
/*	case Qraw: 
		rawopens = 0; 
		break; 
*/ 
1999/0422    
	} 
} 
 
static long 
1999/0513    
lmlread(Chan *c, void *va, long n, vlong voff) { 
1999/0424    
	uchar *buf = va; 
1999/0513    
	long off = voff; 
1999/0423    
 
2001/0630    
	switch((ulong)c->qid.path){ 
1999/0513    
	case Qdir: 
		return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen); 
1999/0610    
	case Qjpg: 
		return jpgread(c, buf, n, off); 
/*	case Qraw: 
		return rawread(c, buf, n, off); 
*/ 
1999/0422    
	} 
} 
 
static long 
1999/0601    
lmlwrite(Chan *, void *, long, vlong) { 
1999/0423    
 
1999/0601    
	error(Eperm); 
	return 0; 
1999/0422    
} 
 
1999/0513    
Dev lmldevtab = { 
1999/0422    
	'V', 
	"video", 
 
1999/0513    
	lmlreset, 
1999/0422    
	devinit, 
1999/0513    
	lmlattach, 
	lmlwalk, 
	lmlstat, 
	lmlopen, 
1999/0422    
	devcreate, 
1999/0513    
	lmlclose, 
	lmlread, 
1999/0422    
	devbread, 
1999/0513    
	lmlwrite, 
1999/0422    
	devbwrite, 
	devremove, 
	devwstat, 
}; 
 
static void 
1999/0424    
lmlintr(Ureg *, void *) { 
1999/0610    
	ulong fstart, fno; 
1999/0520    
	ulong flags = readl(pciBaseAddr+INTR_STAT); 
1999/0424    
	 
	// Reset all interrupts from 067 
1999/0520    
	writel(0xff000000, pciBaseAddr + INTR_STAT); 
1999/0423    
 
1999/0520    
	if(flags & INTR_JPEGREP) { 
1999/0610    
		vlong thetime; 
2000/0716    
 
		if(debug&(DBGINTR)) 
			print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags); 
1999/0610    
 
		fstart = jpgframeno & 0x00000003; 
		for (;;) { 
			jpgframeno++; 
			fno = jpgframeno & 0x00000003; 
			if (codeData->statCom[fno] & STAT_BIT) 
				break; 
			if (fno == fstart) { 
				if (debug & DBGINTR) 
					print("Spurious lml jpg intr?\n"); 
				return; 
			} 
		} 
		thetime = todget(nil); 
		jpgheader[fno].sec  = (ulong)(thetime / 1000000000LL); 
1999/0909    
		jpgheader[fno].nsec = (ulong)(thetime % 1000000000LL); 
1999/0610    
		jpgheader[fno].frameSize = 
			(codeData->statCom[fno] & 0x00ffffff) >> 1; 
		jpgheader[fno].frameSeqNo = codeData->statCom[fno] >> 24; 
		jpgheader[fno].frameNo = jpgframeno; 
		wakeup(&sleepjpg); 
1999/0515    
	} 
1999/0424    
	return; 
1999/0422    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)