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

1999/0517/pc/devlml.c (diff list | history)

1999/0422/sys/src/9/pc/devlml.c:13,221999/0423/sys/src/9/pc/devlml.c:13,20 (short | long)
1999/0422    
enum{ 
	Q819, 
	Q856, 
	Qi22, 
	Q060, 
	Q067, 
	Qstat, 
	Qvideo, 
	Qjframe, 
}; 
1999/0422/sys/src/9/pc/devlml.c:25,341999/0423/sys/src/9/pc/devlml.c:23,30
1999/0422    
//	 name,		 qid,	  size,		mode 
	"vid819",	{Q819},		0,		0644, 
	"vid856",	{Q856},		0,		0644, 
	"vidi22",	{Qi22},		0,		0644, 
	"vid060",	{Q060},		0,		0644, 
	"vid067",	{Q067},		0,		0644, 
	"vidstat",	{Qstat},	0,		0444, 
	"video",	{Qvideo},	0,		0666, 
	"jframe",	{Qjframe},	0,		0666, 
}; 
1999/0422/sys/src/9/pc/devlml.c:36,491999/0423/sys/src/9/pc/devlml.c:32,361
1999/0422    
CodeData *	codeData; 
MjpgDrv *	mjpgDrv; 
 
static void lmlintr(Ureg *ur, void *arg); 
1999/0423    
static void 
lml33_i2c_pause(void) { 
1999/0422    
 
1999/0423    
	microdelay(I2C_DELAY); 
} 
 
1999/0422    
static void 
1999/0423    
lml33_i2c_waitscl(void) { 
	int i; 
	ulong a; 
 
	for(i=0;;i++) { 
		a = readl(pciBaseAddr + ZR36057_I2C_BUS); 
		if (a & ZR36057_I2C_SCL) break; 
		if (i>I2C_TIMEOUT) error(Eio); 
	} 
} 
 
static void 
lml33_i2c_start(void) { 
 
	writel(ZR36057_I2C_SCL|ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_waitscl(); 
	lml33_i2c_pause(); 
 
	writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
 
	writel(0, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
} 
 
static void 
lml33_i2c_stop(void) { 
	// the clock should already be low, make sure data is 
	writel(0, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
 
	// set clock high and wait for device to catch up 
	writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_waitscl(); 
	lml33_i2c_pause(); 
 
	// set the data high to indicate the stop bit 
	writel(ZR36057_I2C_SCL|ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
} 
 
static void lml33_i2c_wrbit(int bit) { 
	if (bit){ 
		writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); // set data 
		lml33_i2c_pause(); 
		writel(ZR36057_I2C_SDA|ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
		lml33_i2c_waitscl(); 
		lml33_i2c_pause(); 
		writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
		lml33_i2c_pause(); 
	} else { 
		writel(0, pciBaseAddr + ZR36057_I2C_BUS); // clr data 
		lml33_i2c_pause(); 
		writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
		lml33_i2c_waitscl(); 
		lml33_i2c_pause(); 
		writel(0, pciBaseAddr + ZR36057_I2C_BUS); 
		lml33_i2c_pause(); 
	} 
} 
 
static int 
lml33_i2c_rdbit(void) { 
	int bit; 
	// the clk line should be low 
 
	// ensure we are not asserting the data line 
	writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
 
	// set the clock high and wait for device to catch up 
	writel(ZR36057_I2C_SDA|ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_waitscl(); 
	lml33_i2c_pause(); 
 
	// the data line should be a valid bit 
	bit = readl(pciBaseAddr+ZR36057_I2C_BUS); 
	if (bit & ZR36057_I2C_SDA){ 
		bit = 1; 
	} else { 
		bit = 0; 
	} 
 
	// set the clock low to indicate end of cycle 
	writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
 
	return bit; 
} 
 
static int 
lml33_i2c_rdbyte(uchar *v) { 
	int i, ack; 
	uchar res; 
 
	res = 0; 
	for (i=0;i<8;i++){ 
		res  = res << 1; 
		res += lml33_i2c_rdbit(); 
	} 
 
	ack = lml33_i2c_rdbit(); 
 
	*v = res; 
 
	return ack; 
} 
 
static int 
lml33_i2c_wrbyte(uchar v) { 
	int i, ack; 
 
	for (i=0;i<8;i++){ 
		lml33_i2c_wrbit(v & 0x80); 
		v = v << 1; 
	} 
 
	ack = lml33_i2c_rdbit(); 
 
	return ack; 
} 
 
static void 
lml33_i2c_write_bytes(uchar addr, uchar sub, uchar *bytes, long num) { 
	int ack; 
	long i; 
 
	lml33_i2c_start(); 
 
	ack = lml33_i2c_wrbyte(addr); 
	if (ack == 1) error(Eio); 
 
	ack = lml33_i2c_wrbyte(sub); 
	if (ack == 1) error(Eio); 
 
	for(i=0;i<num;i+=1){ 
		ack = lml33_i2c_wrbyte(bytes[i]); 
		if (ack == 1) error(Eio); 
	} 
 
	lml33_i2c_stop(); 
} 
 
static uchar 
lml33_i2c_rd8(int addr, int sub) 
{ 
	int ack; 
	uchar msb; 
 
	lml33_i2c_start(); 
 
	ack = lml33_i2c_wrbyte(addr); 
	if (ack == 1){ 
		lml33_i2c_stop(); 
		error(Eio); 
	} 
 
	ack = lml33_i2c_wrbyte(sub); 
	if (ack == 1){ 
		lml33_i2c_stop(); 
		error(Eio); 
	} 
 
	lml33_i2c_start(); 
 
	ack = lml33_i2c_wrbyte(addr+1); 
	if (ack == 1){ 
		lml33_i2c_stop(); 
		error(Eio); 
	} 
 
	ack = lml33_i2c_rdbyte(&msb); 
	if (ack == 0){ 
		lml33_i2c_stop(); 
		error(Eio); 
	} 
 
	lml33_i2c_stop(); 
 
	return msb; 
} 
 
/* 
 * The following mapping applies for the guests in the LML33 
 * 
 * Guest        Device 
 *   0          zr36060 
 *              uses subaddress GADR[0..1] 
 *   1          zr36060 START# 
 *   2          - 
 *   3          zr36060 RESET# 
 *   4          - 
 *   5          - 
 *   6          - 
 *   7          - 
 */ 
 
// lml33_post_idle waits for the guest bus to become free 
static int 
lml33_post_idle(void) { 
	ulong a; 
	int timeout; 
 
	for(timeout = 0;;timeout += 1){ 
		a = readl(pciBaseAddr + ZR36057_POST_OFFICE); 
		if ((a & ZR36057_POST_PEND) == 0)  
			return a; 
		if (timeout == GUEST_TIMEOUT)  
			return -1; 
	} 
} 
 
// lml33_post_write writes a byte to a guest using postoffice mechanism 
static void 
lml33_post_write(int guest, int reg, int v) { 
	int w; 
 
	// wait for postoffice not busy 
	lml33_post_idle(); 
 
	// Trim the values, just in case 
	guest &= 0x07; 
	reg   &= 0x07; 
	v     &= 0xFF; 
 
	// write postoffice operation 
	w = ZR36057_POST_DIR + (guest<<20) + (reg<<16) + v; 
	writel(w, pciBaseAddr + ZR36057_POST_OFFICE); 
 
	// wait for postoffice not busy 
	w = lml33_post_idle(); 
 
	// decide if write went ok 
	if (w == -1) error(Eio); 
} 
 
// lml33_post_read reads a byte from a guest using postoffice mechanism 
static uchar 
lml33_post_read(int guest, int reg) { 
	int w; 
 
	// wait for postoffice not busy 
	lml33_post_idle(); 
 
	// Trim the values, just in case 
	guest &= 0x07; 
	reg   &= 0x07; 
 
	// write postoffice operation 
	w = (guest<<20) + (reg<<16); 
	writel(w, pciBaseAddr + ZR36057_POST_OFFICE); 
 
	// wait for postoffice not busy, get result 
	w = lml33_post_idle(); 
 
	// decide if read went ok 
	if (w == -1) error(Eio); 
 
	return (uchar)(w & 0xFF); 
} 
 
static void 
lml33_zr060_write(int reg, int v) { 
	int guest_id; 
 
	guest_id = GID060; 
 
	lml33_post_write(guest_id, 1, reg>>8 & 0x03); 
	lml33_post_write(guest_id, 2, reg    & 0xff); 
	lml33_post_write(guest_id, 3, v); 
} 
 
static uchar 
lml33_zr060_read(int reg) { 
	int guest_id; 
 
	guest_id = GID060; 
 
	lml33_post_write(guest_id, 1, reg>>8 & 0x03); 
	lml33_post_write(guest_id, 2, reg    & 0xff); 
 
	return lml33_post_read(guest_id, 3); 
} 
 
long 
chipread(long addr, char *buf, long n, long off) { 
	long i; 
 
	for (i = 0; i < n; i++) { 
		*buf++ = lml33_i2c_rd8(addr, off++); 
	} 
	return i; 
} 
 
long 
post060read(char *buf, long n, long off) { 
	long i; 
 
	for (i = 0; i < n; i++) { 
		*buf++ = lml33_zr060_read(off++); 
	} 
	return i; 
} 
 
static void lmlintr(Ureg *, void *); 
 
static void 
1999/0422    
vidreset(void) 
{ 
	ulong regpa; 
	int i; 
 
1999/0423    
	pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067); 
	if (pcidev == nil) { 
		print("No zr36067 found.\n"); 
		return; 
	} 
1999/0422    
	codeData = (CodeData*)xspanalloc(sizeof(CodeData), BY2PG, 0); 
	if (codeData == nil) { 
		print("devlml: xspanalloc(%ux, %ux, 0)\n", sizeof(CodeData), BY2PG); 
1999/0422/sys/src/9/pc/devlml.c:61,671999/0423/sys/src/9/pc/devlml.c:373,379
1999/0422    
		codeData->statCom[i] = PADDR(&(codeData->fragmDescr[i])); 
		codeData->statComInitial[i] = codeData->statCom[i]; 
		codeData->fragmDescr[i].fragmAddress = 
			(H33_Fragment *)PADDR(&(codeData->frag[i])); 
1999/0423    
			(Fragment *)PADDR(&(codeData->frag[i])); 
1999/0422    
		// Length is in double words, in position 1..20 
		codeData->fragmDescr[i].fragmLength = (FRAGSIZE >> 1) | FRAGM_FINAL_B; 
	} 
1999/0422/sys/src/9/pc/devlml.c:71,1091999/0423/sys/src/9/pc/devlml.c:383,411
1999/0422    
		print("LML33: can't allocate dynamic memory for MjpgDrv\n"); 
		return; 
	} 
	if((lml33Board = xallocz(sizeof(LML33Board), 0)) == nil) { 
		print("LML33: can't allocate dynamic memory for lml33Board\n"); 
		return; 
	} 
 
	print("initializing LML33 board..."); 
 
	lml33Board->pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067); 
	if (lml33Board->pcidev == nil) { 
		print("zr36067 not found. Install aborted.\n"); 
		return; 
	} 
	lml33Board->pciPhysBaseAddr = 
		(void *)(lml33Board->pcidev->mem[0].bar & ~0x0F); 
1999/0423    
	pciPhysBaseAddr = (void *)(pcidev->mem[0].bar & ~0x0F); 
1999/0422    
 
	print("zr36067 found at %lux\n", lml33Board->pciPhysBaseAddr); 
1999/0423    
	print("zr36067 found at %lux\n", pciPhysBaseAddr); 
1999/0422    
 
	regpa = upamalloc(lml33Board->pcidev->mem[0].bar & ~0x0F, lml33Board->pcidev->mem[0].size, 0); 
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; 
	} 
	lml33Board->pciBaseAddr = KADDR(regpa); 
1999/0423    
	pciBaseAddr = (ulong)KADDR(regpa); 
1999/0422    
 
	// make sure the device will respond to mem accesses 
	// (pcicmd_master | pcicmd_memory) -- probably superfluous 
//	pcicfgw32(lml33Board->pcidev, PciPCR, 0x04 | 0x02); 
1999/0423    
//	pcicfgw32(pcidev, PciPCR, 0x04 | 0x02); 
1999/0422    
 
	// set bus latency -- probably superfluous 
//	pcicfgw8(lml33Board->pcidev, PciLTR, 64); 
1999/0423    
//	pcicfgw8(pcidev, PciLTR, 64); 
1999/0422    
 
	// Interrupt handler 
	intrenable(lml33Board->pcidev->intl, lmlintr, lml33Board, lml33Board->pcidev->tbdf); 
1999/0423    
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); 
1999/0422    
 
	print("LML33 Installed\n");  
	return;  
1999/0422/sys/src/9/pc/devlml.c:134,1471999/0423/sys/src/9/pc/devlml.c:436,445
1999/0422    
	switch(c->qid.path){ 
	case Q819: 
	case Q856: 
	case Qi22: 
	case Q060: 
	case Q067: 
		// allow one open per file 
		break; 
	case Qstat: 
		// allow many opens 
		break; 
	case Qvideo: 
	case Qjframe: 
		// allow one open total for these two 
1999/0422/sys/src/9/pc/devlml.c:156,1651999/0423/sys/src/9/pc/devlml.c:454,461
1999/0422    
	switch(c->qid.path){ 
	case Q819: 
	case Q856: 
	case Qi22: 
	case Q060: 
	case Q067: 
	case Qstat: 
	case Qvideo: 
	case Qjframe: 
		authclose(c); 
1999/0422/sys/src/9/pc/devlml.c:167,1831999/0423/sys/src/9/pc/devlml.c:463,485
1999/0422    
} 
 
static long 
vidread(Chan *c, void *buf, long n, vlong off) 
{ 
1999/0423    
vidread(Chan *c, void *buf, long n, vlong off) { 
 
1999/0422    
	switch(c->qid.path){ 
	case Q819: 
1999/0423    
		if (off < 0 || off + n > 20) 
			return 0; 
		return chipread(BT819Addr, buf, n, off); 
1999/0422    
	case Q856: 
	case Qi22: 
1999/0423    
		if (off < 0xda || off + n > 0xe0) 
			return 0; 
		return chipread(BT856Addr, buf, n, off); 
1999/0422    
	case Q060: 
1999/0423    
		return post060read(buf, n, off); 
1999/0422    
	case Q067: 
		return chipread(c, buf, n, off); 
	case Qstat: 
		return statread(c, buf, n, off); 
1999/0423    
		if (off < 0 || off + n > 20 || (off & 0x3) || n != 4) return 0; 
		*(long *)buf = readl(pciBaseAddr + off); 
		return 4; 
1999/0422    
	case Qvideo: 
	case Qjframe: 
		return videoread(c, buf, n, off); 
1999/0422/sys/src/9/pc/devlml.c:187,1921999/0423/sys/src/9/pc/devlml.c:489,514
1999/0422    
static long 
vidwrite(Chan *c, void *va, long n, vlong off) 
{ 
1999/0423    
 
	switch(c->qid.path){ 
	case Q819: 
		if (off < 0 || off + n > 20) 
			return 0; 
		return chipwrite(BT819Addr, buf, n, off); 
	case Q856: 
		if (off < 0xda || off + n > 0xe0) 
			return 0; 
		return chipwrite(BT856Addr, buf, n, off); 
	case Q060: 
		return post060write(buf, n, off); 
	case Q067: 
		if (off < 0 || off + n > 20 || (off & 0x3) || n != 4) return 0; 
		writel(*(long *)buf, pciBaseAddr + off); 
		return 4; 
	case Qvideo: 
	case Qjframe: 
		return videowrite(c, buf, n, off); 
	} 
1999/0422    
} 
 
Dev viddevtab = { 
1999/0422/sys/src/9/pc/devlml.c:211,2191999/0423/sys/src/9/pc/devlml.c:533,540
1999/0422    
}; 
 
static void 
lmlintr(Ureg *ur, void *arg) 
1999/0423    
lmlintr(Ureg *ur, void *) 
1999/0422    
{ 
	LML33Board *lml33Board = (Lml33Board *)arg; 
 
	                 
1999/0423    
 
1999/0422    
} 
1999/0423/sys/src/9/pc/devlml.c:30,371999/0424/sys/src/9/pc/devlml.c:30,52 (short | long)
1999/0422    
}; 
 
CodeData *	codeData; 
MjpgDrv *	mjpgDrv; 
 
1999/0424    
int			currentBuffer; 
int			currentBufferLength; 
void *		currentBufferPtr; 
int			frameNo; 
Rendez		sleeper; 
int			singleFrame; 
int			bufferPrepared; 
int			hdrPos; 
int			nopens; 
 
static FrameHeader frameHeader = { 
	MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, 
	{ 'L', 'M', 'L', '\0'}, 
	-1, 0, 0, 0, 0 
}; 
 
1999/0423    
static void 
lml33_i2c_pause(void) { 
1999/0422    
 
1999/0423/sys/src/9/pc/devlml.c:182,2261999/0424/sys/src/9/pc/devlml.c:197,243
1999/0423    
	lml33_i2c_stop(); 
} 
 
static uchar 
1999/0424    
static int 
1999/0423    
lml33_i2c_rd8(int addr, int sub) 
{ 
	int ack; 
	uchar msb; 
 
	lml33_i2c_start(); 
 
	ack = lml33_i2c_wrbyte(addr); 
	if (ack == 1){ 
1999/0424    
	if (lml33_i2c_wrbyte(addr) == 1 
	 || lml33_i2c_wrbyte(sub) == 1) { 
1999/0423    
		lml33_i2c_stop(); 
		error(Eio); 
1999/0424    
		return -1; 
1999/0423    
	} 
 
	ack = lml33_i2c_wrbyte(sub); 
	if (ack == 1){ 
		lml33_i2c_stop(); 
		error(Eio); 
	} 
                 
	lml33_i2c_start(); 
 
	ack = lml33_i2c_wrbyte(addr+1); 
	if (ack == 1){ 
1999/0424    
	if (lml33_i2c_wrbyte(addr+1) == 1 
	 || lml33_i2c_rdbyte(&msb) == 0){ 
1999/0423    
		lml33_i2c_stop(); 
		error(Eio); 
1999/0424    
		return -1; 
1999/0423    
	} 
 
	ack = lml33_i2c_rdbyte(&msb); 
	if (ack == 0){ 
		lml33_i2c_stop(); 
		error(Eio); 
	} 
                 
	lml33_i2c_stop(); 
 
	return msb; 
} 
 
1999/0424    
static int 
lml33_i2c_wr8(uchar addr, uchar sub, uchar msb) { 
	 
	lml33_i2c_start(); 
 
	if (lml33_i2c_wrbyte(addr) == 1 
	 || lml33_i2c_wrbyte(sub) == 1 
	 || lml33_i2c_wrbyte(msb) == 1) 
		return 0; 
	 
	lml33_i2c_stop(); 
	 
	return 1; 
} 
 
1999/0423    
/* 
 * The following mapping applies for the guests in the LML33 
 * 
1999/0423/sys/src/9/pc/devlml.c:252,2581999/0424/sys/src/9/pc/devlml.c:269,275
1999/0423    
} 
 
// lml33_post_write writes a byte to a guest using postoffice mechanism 
static void 
1999/0424    
static int 
1999/0423    
lml33_post_write(int guest, int reg, int v) { 
	int w; 
 
1999/0423/sys/src/9/pc/devlml.c:269,2821999/0424/sys/src/9/pc/devlml.c:286,296
1999/0423    
	writel(w, pciBaseAddr + ZR36057_POST_OFFICE); 
 
	// wait for postoffice not busy 
	w = lml33_post_idle(); 
                 
	// decide if write went ok 
	if (w == -1) error(Eio); 
1999/0424    
	return lml33_post_idle() == -1; 
1999/0423    
} 
 
// lml33_post_read reads a byte from a guest using postoffice mechanism 
static uchar 
1999/0424    
static int 
1999/0423    
lml33_post_read(int guest, int reg) { 
	int w; 
 
1999/0423/sys/src/9/pc/devlml.c:295,3061999/0424/sys/src/9/pc/devlml.c:309,320
1999/0423    
	w = lml33_post_idle(); 
 
	// decide if read went ok 
	if (w == -1) error(Eio); 
1999/0424    
	if (w == -1) return -1; 
1999/0423    
 
	return (uchar)(w & 0xFF); 
1999/0424    
	return w & 0xFF; 
1999/0423    
} 
 
static void 
1999/0424    
static int 
1999/0423    
lml33_zr060_write(int reg, int v) { 
	int guest_id; 
 
1999/0423/sys/src/9/pc/devlml.c:308,3171999/0424/sys/src/9/pc/devlml.c:322,331
1999/0423    
 
	lml33_post_write(guest_id, 1, reg>>8 & 0x03); 
	lml33_post_write(guest_id, 2, reg    & 0xff); 
	lml33_post_write(guest_id, 3, v); 
1999/0424    
	return lml33_post_write(guest_id, 3, v); 
1999/0423    
} 
 
static uchar 
1999/0424    
static int 
1999/0423    
lml33_zr060_read(int reg) { 
	int guest_id; 
 
1999/0423/sys/src/9/pc/devlml.c:323,3481999/0424/sys/src/9/pc/devlml.c:337,541
1999/0423    
	return lml33_post_read(guest_id, 3); 
} 
 
long 
chipread(long addr, char *buf, long n, long off) { 
	long i; 
1999/0424    
static int 
prepareBuffer(CodeData * this, int bufferNo) { 
  if(bufferNo >= 0 && bufferNo < NBUF && (this->statCom[bufferNo] & STAT_BIT)) { 
    this->statCom[bufferNo] = this->statComInitial[bufferNo]; 
    return this->fragmDescr[bufferNo].fragmLength; 
  } else 
    return -1; 
} 
1999/0423    
 
	for (i = 0; i < n; i++) { 
		*buf++ = lml33_i2c_rd8(addr, off++); 
1999/0424    
static int 
getProcessedBuffer(CodeData* this){ 
	static lastBuffer=NBUF-1; 
	int lastBuffer0 = lastBuffer; 
 
	while (1) {  
		lastBuffer = (lastBuffer+1) % NBUF; 
		if(this->statCom[lastBuffer]&STAT_BIT) 
			return lastBuffer; 
		if(lastBuffer==lastBuffer0) 
			break; 
1999/0423    
	} 
	return i; 
1999/0424    
	return -1; 
1999/0423    
} 
 
long 
post060read(char *buf, long n, long off) { 
	long i; 
1999/0424    
static int 
getBuffer(CodeData *this, int bufferNo, void** bufferPtr, int* frameNo) { 
	int codeLength; 
	if(this->statCom[bufferNo] & STAT_BIT) { 
		*bufferPtr = (void*)this->fragmDescr[bufferNo].fragmAddress; 
		*frameNo = this->statCom[bufferNo] >> 24; 
		codeLength=((this->statCom[bufferNo] & 0x00FFFFFF) >> 1); 
		return codeLength; 
	} else 
		return -1; 
} 
1999/0423    
 
	for (i = 0; i < n; i++) { 
		*buf++ = lml33_zr060_read(off++); 
1999/0424    
static long 
vread(Chan *, void *va, long count, vlong pos) { 
	int prevFrame; 
	//  how much bytes left to transfer for the header 
	int hdrLeft; 
	// Count of bytes that we need to copy into buf from code-buffer 
	// (different from count only while in header reading mode) 
	int cpcount = count; 
	// Count of bytes that we copied into buf altogether and will return 
	int retcount=0; 
	vlong thetime; 
	uchar *buf = va; 
 
	//print("devlml::vread() count=%ld pos=%lld\n", count, pos); 
 
	// If we just begin reading a file, pos would never be 0 otherwise 
	if (pos == 0 && hdrPos == -1) { 
		 currentBuffer = -1; 
		 currentBufferLength = 0; 
		 frameNo = -1; 
1999/0423    
	} 
	return i; 
1999/0424    
	prevFrame = frameNo; 
 
	// We get to the end of the current buffer, also covers just 
	// open file, since 0 >= -1 
	if(hdrPos == -1 && pos >= currentBufferLength) { 
		prepareBuffer(codeData, currentBuffer); 
		// if not the first buffer read and single frame mode - return EOF 
		if (currentBuffer != -1 && singleFrame) 
			return 0; 
		while((currentBuffer = getProcessedBuffer(codeData)) == -1) 
			sleep(&sleeper, return0, 0); 
		currentBufferLength = getBuffer(codeData, currentBuffer, 
			¤tBufferPtr, &frameNo); 
 
		pos = 0; // ?????????????? 
 
		// print("getBufffer %d -> %d 0x%x %d\n",currentBuffer, currentBufferLength, currentBufferPtr, frameNo); 
		if(frameNo != (prevFrame + 1) % 256) 
			print("Frames out of sequence: %d %d\n", prevFrame, frameNo); 
		// Fill in APP marker fields here 
		thetime = todget(); 
		frameHeader.sec = (ulong)(thetime / 1000000000LL); 
		frameHeader.usec = (ulong)(thetime % 1000000000LL) / 1000; 
		frameHeader.frameSize = currentBufferLength - 2 + sizeof(FrameHeader); 
		frameHeader.frameSeqNo++; 
		frameHeader.frameNo = frameNo; 
		hdrPos=0; 
	} 
 
	if (hdrPos != -1) { 
		hdrLeft = sizeof(FrameHeader) - hdrPos; 
		// Write the frame size here 
		if (count >= hdrLeft) { 
			memmove(buf, (char*)&frameHeader + hdrPos, hdrLeft); 
			retcount += hdrLeft; 
			cpcount = count - hdrLeft; 
			pos = sizeof(frameHeader.mrkSOI); 
			hdrPos = -1; 
		} else { 
			memmove(buf, (char*)&frameHeader + hdrPos, count); 
			hdrPos += count; 
			return count; 
		} 
	} 
 
	if(cpcount + pos > currentBufferLength) 
		cpcount = currentBufferLength - pos; 
 
	memmove(buf + retcount, (char *)currentBufferPtr + pos, cpcount); 
	retcount += cpcount; 
 
	//pr_debug("return %d %d\n",cpcount,retcount); 
	return retcount; 
1999/0423    
} 
 
1999/0424    
static long 
vwrite(Chan *, void *va, long count, vlong pos) { 
	//  how much bytes left to transfer for the header 
	int hdrLeft; 
	char *buf = va; 
 
	//print("devlml::vwrite() count=0x%x pos=0x%x\n", count, pos); 
 
	// We just started writing, not into the header copy 
	if(pos==0 && hdrPos == -1) { 
		 currentBuffer=-1; 
		 currentBufferLength=0; 
		 frameNo=-1; 
		 bufferPrepared = 0; 
	} 
 
	// We need next buffer to fill (either because we're done with the 
	// current buffer) of because we're just beginning (but not into the header) 
	if (hdrPos == -1 && pos >= currentBufferLength) { 
		while((currentBuffer = getProcessedBuffer(codeData)) == -1) 
			sleep(&sleeper, return0, 0); 
		// print("current buffer %d\n",currentBuffer); 
 
		getBuffer(codeData, currentBuffer, ¤tBufferPtr, &frameNo); 
		// We need to receive the header now 
		hdrPos = 0; 
	} 
	 
	// We're into the header processing  
	if (hdrPos != -1) { 
		// Calculate how many bytes we need to receive to fill the header 
		hdrLeft = sizeof(FrameHeader) - hdrPos; 
	 
		// If we complete or go over the header with this count 
		if (count >= hdrLeft) { 
			// Adjust count of bytes that remain to be copied into video buffer 
			count = count - hdrLeft;  
			memmove((char*)&frameHeader + hdrPos, buf, hdrLeft); 
			// Make sure we have a standard LML33 header 
			if (frameHeader.mrkSOI == MRK_SOI 
			 && frameHeader.mrkAPP3==MRK_APP3 
			 && strcmp(frameHeader.nm,APP_NAME) == 0) { 
				//print("Starting new buffer len=0x%x frame=%d\n", frameHeader.frameSize, frameHeader.frameSeqNo); 
				// Obtain values we need for playback process from the header 
				currentBufferLength = frameHeader.frameSize; 
			} else if (singleFrame) { 
				currentBufferLength = FRAGSIZE; 
			} else { 
				// We MUST have header for motion video decompression 
				print("No frame size (APP3 marker) in MJPEG file\n"); 
				error(Eio); 
			} 
			// Finish header processing 
			hdrPos = -1; 
			// Copy the header into the playback buffer 
			memmove(currentBufferPtr, (char*)&frameHeader, sizeof(FrameHeader)); 
			// And set position just behind header for playback buffer write 
			pos = sizeof(FrameHeader); 
		} else { 
			memmove((char*)&frameHeader + hdrPos, buf, count); 
			hdrPos += count; 
			return count; 
		} 
	} else 
		hdrLeft = 0; 
 
	if(count + pos > currentBufferLength) { 
		count = currentBufferLength - pos; 
	} 
 
	memmove((char *)currentBufferPtr + pos, buf + hdrLeft, count); 
 
	pos += count; 
	// print("return 0x%x 0x%x\n",pos,count); 
 
	// Now is the right moment to initiate playback of the frame (if it's full) 
	if(pos >= currentBufferLength) { 
		// We have written the frame, time to display it 
		//print("Passing written buffer to 067\n"); 
		prepareBuffer(codeData, currentBuffer); 
		bufferPrepared = 1; 
	} 
	//print("return 0x%lx 0x%x 0x%x 0x%x\n",pos,count,hdrLeft+count,currentBufferLength); 
 
	return hdrLeft + count; 
} 
 
1999/0423    
static void lmlintr(Ureg *, void *); 
 
static void 
1999/0423/sys/src/9/pc/devlml.c:378,3891999/0424/sys/src/9/pc/devlml.c:571,576
1999/0422    
		codeData->fragmDescr[i].fragmLength = (FRAGSIZE >> 1) | FRAGM_FINAL_B; 
	} 
 
	// Get dynamic kernel memory allocaton for the driver 
	if((mjpgDrv = xallocz(sizeof(MjpgDrv), 0)) == nil) { 
		print("LML33: can't allocate dynamic memory for MjpgDrv\n"); 
		return; 
	} 
                 
	print("initializing LML33 board..."); 
 
1999/0423    
	pciPhysBaseAddr = (void *)(pcidev->mem[0].bar & ~0x0F); 
1999/0423/sys/src/9/pc/devlml.c:438,4471999/0424/sys/src/9/pc/devlml.c:625,643
1999/0422    
	case Q856: 
	case Q060: 
	case Q067: 
		// allow one open per file 
		break; 
	case Qvideo: 
	case Qjframe: 
1999/0424    
		if (nopens) 
			error(Einuse); 
		nopens = 1; 
		singleFrame = (c->qid.path == Qjframe) ? 1 : 0;; 
		currentBuffer = 0; 
		currentBufferLength = 0; 
		currentBufferPtr = 0; 
		frameNo = 0; 
		bufferPrepared = 0; 
		hdrPos = -1; 
1999/0422    
		// allow one open total for these two 
		break; 
	} 
1999/0423/sys/src/9/pc/devlml.c:463,5131999/0424/sys/src/9/pc/devlml.c:659,747
1999/0422    
} 
 
static long 
1999/0423    
vidread(Chan *c, void *buf, long n, vlong off) { 
1999/0424    
vidread(Chan *c, void *va, long n, vlong off) { 
	int i, d; 
	uchar *buf = va; 
1999/0423    
 
1999/0422    
	switch(c->qid.path){ 
	case Q819: 
1999/0423    
		if (off < 0 || off + n > 20) 
1999/0424    
		if (off < 0 || off + n > 0x20) 
1999/0423    
			return 0; 
		return chipread(BT819Addr, buf, n, off); 
1999/0424    
		for (i = 0; i < n; i++) { 
			if ((d = lml33_i2c_rd8(BT819Addr, off++)) < 0) break; 
			*buf++ = d; 
		} 
		return n - i; 
1999/0422    
	case Q856: 
1999/0423    
		if (off < 0xda || off + n > 0xe0) 
			return 0; 
		return chipread(BT856Addr, buf, n, off); 
1999/0424    
		for (i = 0; i < n; i++) { 
			if ((d = lml33_i2c_rd8(BT856Addr, off++)) < 0) break; 
			*buf++ = d; 
		} 
		return n - i; 
1999/0422    
	case Q060: 
1999/0423    
		return post060read(buf, n, off); 
1999/0424    
		if (off < 0 || off + n > 0x60) 
			return 0; 
		for (i = 0; i < n; i++) { 
			if ((d = lml33_zr060_read(off++)) < 0) break; 
			*buf++ = d; 
		} 
		return n - i; 
1999/0422    
	case Q067: 
1999/0423    
		if (off < 0 || off + n > 20 || (off & 0x3) || n != 4) return 0; 
		*(long *)buf = readl(pciBaseAddr + off); 
		return 4; 
1999/0424    
		if (off < 0 || off + n > 0x200 || (off & 0x3)) 
			return 0; 
		for (i = n; i >= 4; i -= 4) { 
			*(long *)buf = readl(pciBaseAddr + off); 
			buf += 4; 
			off += 4; 
		} 
		return n-i; 
1999/0422    
	case Qvideo: 
	case Qjframe: 
		return videoread(c, buf, n, off); 
1999/0424    
		return vread(c, buf, n, off); 
1999/0422    
	} 
} 
 
static long 
vidwrite(Chan *c, void *va, long n, vlong off) 
{ 
1999/0424    
vidwrite(Chan *c, void *va, long n, vlong off) { 
	int i; 
	uchar *buf = va; 
1999/0423    
 
	switch(c->qid.path){ 
	case Q819: 
		if (off < 0 || off + n > 20) 
1999/0424    
		if (off < 0 || off + n > 0x20) 
1999/0423    
			return 0; 
		return chipwrite(BT819Addr, buf, n, off); 
1999/0424    
		for (i = n; i > 0; i--) 
			if (lml33_i2c_wr8(BT819Addr, off++, *buf++) == 0) 
				break; 
		return n - i; 
1999/0423    
	case Q856: 
		if (off < 0xda || off + n > 0xe0) 
			return 0; 
		return chipwrite(BT856Addr, buf, n, off); 
1999/0424    
		for (i = n; i > 0; i--) 
			if (lml33_i2c_wr8(BT856Addr, off++, *buf++) == 0) 
				break; 
		return n - i; 
1999/0423    
	case Q060: 
		return post060write(buf, n, off); 
1999/0424    
		if (off < 0 || off + n > 0x60) 
			return 0; 
		for (i = 0; i < n; i++) 
			if (lml33_zr060_write(off++, *buf++) < 0) 
				break; 
		return n - i; 
1999/0423    
	case Q067: 
		if (off < 0 || off + n > 20 || (off & 0x3) || n != 4) return 0; 
		writel(*(long *)buf, pciBaseAddr + off); 
		return 4; 
1999/0424    
		if (off < 0 || off + n > 0x200 || (off & 0x3)) 
			return 0; 
		for (i = n; i >= 4; i -= 4) { 
			writel(*(long *)buf, pciBaseAddr + off); 
			buf += 4; 
			off += 4; 
		} 
		return n-i; 
1999/0423    
	case Qvideo: 
	case Qjframe: 
		return videowrite(c, buf, n, off); 
1999/0424    
		return vwrite(c, buf, n, off); 
1999/0423    
	} 
1999/0422    
} 
 
1999/0423/sys/src/9/pc/devlml.c:533,5401999/0424/sys/src/9/pc/devlml.c:767,781
1999/0422    
}; 
 
static void 
1999/0423    
lmlintr(Ureg *ur, void *) 
1999/0422    
{ 
1999/0424    
lmlintr(Ureg *, void *) { 
	ulong flags = readl(pciBaseAddr+ZR36057_INTR_STAT); 
	 
//  print("MjpgDrv_intrHandler stat=0x%08x\n", flags); 
1999/0422    
 
1999/0424    
	// Reset all interrupts from 067 
	writel(0xff000000, pciBaseAddr + ZR36057_INTR_STAT); 
1999/0423    
 
1999/0424    
	if(flags & ZR36057_INTR_JPEGREP) 
			wakeup(&sleeper); 
	return; 
1999/0422    
} 
1999/0424/sys/src/9/pc/devlml.c:13,201999/0428/sys/src/9/pc/devlml.c:13,19 (short | long)
1999/0422    
enum{ 
	Q819, 
	Q856, 
	Q060, 
	Q067, 
1999/0428    
	Qreg, 
1999/0422    
	Qvideo, 
	Qjframe, 
}; 
1999/0424/sys/src/9/pc/devlml.c:23,301999/0428/sys/src/9/pc/devlml.c:22,28
1999/0422    
//	 name,		 qid,	  size,		mode 
	"vid819",	{Q819},		0,		0644, 
	"vid856",	{Q856},		0,		0644, 
	"vid060",	{Q060},		0,		0644, 
	"vid067",	{Q067},		0,		0644, 
1999/0428    
	"vidreg",	{Qreg},		0,		0644, 
1999/0422    
	"video",	{Qvideo},	0,		0666, 
	"jframe",	{Qjframe},	0,		0666, 
}; 
1999/0424/sys/src/9/pc/devlml.c:238,3431999/0428/sys/src/9/pc/devlml.c:236,242
1999/0424    
	return 1; 
} 
 
1999/0423    
/* 
 * The following mapping applies for the guests in the LML33 
 * 
 * Guest        Device 
 *   0          zr36060 
 *              uses subaddress GADR[0..1] 
 *   1          zr36060 START# 
 *   2          - 
 *   3          zr36060 RESET# 
 *   4          - 
 *   5          - 
 *   6          - 
 *   7          - 
 */ 
                 
// lml33_post_idle waits for the guest bus to become free 
static int 
lml33_post_idle(void) { 
	ulong a; 
	int timeout; 
                 
	for(timeout = 0;;timeout += 1){ 
		a = readl(pciBaseAddr + ZR36057_POST_OFFICE); 
		if ((a & ZR36057_POST_PEND) == 0)  
			return a; 
		if (timeout == GUEST_TIMEOUT)  
			return -1; 
	} 
} 
                 
// lml33_post_write writes a byte to a guest using postoffice mechanism 
1999/0424    
static int 
1999/0423    
lml33_post_write(int guest, int reg, int v) { 
	int w; 
                 
	// wait for postoffice not busy 
	lml33_post_idle(); 
                 
	// Trim the values, just in case 
	guest &= 0x07; 
	reg   &= 0x07; 
	v     &= 0xFF; 
                 
	// write postoffice operation 
	w = ZR36057_POST_DIR + (guest<<20) + (reg<<16) + v; 
	writel(w, pciBaseAddr + ZR36057_POST_OFFICE); 
                 
	// wait for postoffice not busy 
1999/0424    
	return lml33_post_idle() == -1; 
1999/0423    
} 
                 
// lml33_post_read reads a byte from a guest using postoffice mechanism 
1999/0424    
static int 
1999/0423    
lml33_post_read(int guest, int reg) { 
	int w; 
                 
	// wait for postoffice not busy 
	lml33_post_idle(); 
                 
	// Trim the values, just in case 
	guest &= 0x07; 
	reg   &= 0x07; 
                 
	// write postoffice operation 
	w = (guest<<20) + (reg<<16); 
	writel(w, pciBaseAddr + ZR36057_POST_OFFICE); 
                 
	// wait for postoffice not busy, get result 
	w = lml33_post_idle(); 
                 
	// decide if read went ok 
1999/0424    
	if (w == -1) return -1; 
1999/0423    
                 
1999/0424    
	return w & 0xFF; 
1999/0423    
} 
                 
1999/0424    
static int 
1999/0423    
lml33_zr060_write(int reg, int v) { 
	int guest_id; 
                 
	guest_id = GID060; 
                 
	lml33_post_write(guest_id, 1, reg>>8 & 0x03); 
	lml33_post_write(guest_id, 2, reg    & 0xff); 
1999/0424    
	return lml33_post_write(guest_id, 3, v); 
1999/0423    
} 
                 
1999/0424    
static int 
1999/0423    
lml33_zr060_read(int reg) { 
	int guest_id; 
                 
	guest_id = GID060; 
                 
	lml33_post_write(guest_id, 1, reg>>8 & 0x03); 
	lml33_post_write(guest_id, 2, reg    & 0xff); 
                 
	return lml33_post_read(guest_id, 3); 
} 
                 
1999/0424    
static int 
prepareBuffer(CodeData * this, int bufferNo) { 
  if(bufferNo >= 0 && bufferNo < NBUF && (this->statCom[bufferNo] & STAT_BIT)) { 
    this->statCom[bufferNo] = this->statComInitial[bufferNo]; 
1999/0424/sys/src/9/pc/devlml.c:623,6301999/0428/sys/src/9/pc/devlml.c:522,528
1999/0422    
	switch(c->qid.path){ 
	case Q819: 
	case Q856: 
	case Q060: 
	case Q067: 
1999/0428    
	case Qreg: 
1999/0422    
		break; 
	case Qvideo: 
	case Qjframe: 
1999/0424/sys/src/9/pc/devlml.c:650,6571999/0428/sys/src/9/pc/devlml.c:548,554
1999/0422    
	switch(c->qid.path){ 
	case Q819: 
	case Q856: 
	case Q060: 
	case Q067: 
1999/0428    
	case Qreg: 
1999/0422    
	case Qvideo: 
	case Qjframe: 
		authclose(c); 
1999/0424/sys/src/9/pc/devlml.c:680,7021999/0428/sys/src/9/pc/devlml.c:577,599
1999/0424    
			*buf++ = d; 
		} 
		return n - i; 
1999/0422    
	case Q060: 
1999/0424    
		if (off < 0 || off + n > 0x60) 
			return 0; 
		for (i = 0; i < n; i++) { 
			if ((d = lml33_zr060_read(off++)) < 0) break; 
			*buf++ = d; 
		} 
		return n - i; 
1999/0422    
	case Q067: 
1999/0428    
	case Qreg: 
1999/0424    
		if (off < 0 || off + n > 0x200 || (off & 0x3)) 
			return 0; 
		for (i = n; i >= 4; i -= 4) { 
1999/0428    
		switch(n) { 
		case 1: 
			*buf = readb(pciBaseAddr + off); 
			break; 
		case 2: 
			*(short *)buf = readw(pciBaseAddr + off); 
			break; 
		case 4: 
1999/0424    
			*(long *)buf = readl(pciBaseAddr + off); 
			buf += 4; 
			off += 4; 
1999/0428    
			break; 
		default: 
			return 0; 
1999/0424    
		} 
		return n-i; 
1999/0428    
		return n; 
1999/0422    
	case Qvideo: 
	case Qjframe: 
1999/0424    
		return vread(c, buf, n, off); 
1999/0424/sys/src/9/pc/devlml.c:723,7441999/0428/sys/src/9/pc/devlml.c:620,642
1999/0424    
			if (lml33_i2c_wr8(BT856Addr, off++, *buf++) == 0) 
				break; 
		return n - i; 
1999/0423    
	case Q060: 
1999/0424    
		if (off < 0 || off + n > 0x60) 
			return 0; 
		for (i = 0; i < n; i++) 
			if (lml33_zr060_write(off++, *buf++) < 0) 
				break; 
		return n - i; 
1999/0423    
	case Q067: 
1999/0428    
	case Qreg: 
1999/0424    
		if (off < 0 || off + n > 0x200 || (off & 0x3)) 
			return 0; 
		for (i = n; i >= 4; i -= 4) { 
1999/0428    
		switch (n) { 
		case 1: 
			writeb(*buf, pciBaseAddr + off); 
			break; 
		case 2: 
			writew(*(short *)buf, pciBaseAddr + off); 
			break; 
		case 4: 
1999/0424    
			writel(*(long *)buf, pciBaseAddr + off); 
			buf += 4; 
			off += 4; 
1999/0428    
			break; 
		default: 
			return 0; 
1999/0424    
		} 
		return n-i; 
1999/0428    
		return n; 
1999/0423    
	case Qvideo: 
	case Qjframe: 
1999/0424    
		return vwrite(c, buf, n, off); 
1999/0428/sys/src/9/pc/devlml.c:38,431999/0429/sys/src/9/pc/devlml.c:38,44 (short | long)
1999/0424    
int			bufferPrepared; 
int			hdrPos; 
int			nopens; 
1999/0429    
uchar		q856[3]; 
1999/0424    
 
static FrameHeader frameHeader = { 
	MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, 
1999/0428/sys/src/9/pc/devlml.c:46,581999/0429/sys/src/9/pc/devlml.c:47,59
1999/0424    
}; 
 
1999/0423    
static void 
lml33_i2c_pause(void) { 
1999/0429    
i2c_pause(void) { 
1999/0422    
 
1999/0423    
	microdelay(I2C_DELAY); 
} 
 
1999/0422    
static void 
1999/0423    
lml33_i2c_waitscl(void) { 
1999/0429    
i2c_waitscl(void) { 
1999/0423    
	int i; 
	ulong a; 
 
1999/0428/sys/src/9/pc/devlml.c:64,1311999/0429/sys/src/9/pc/devlml.c:65,132
1999/0423    
} 
 
static void 
lml33_i2c_start(void) { 
1999/0429    
i2c_start(void) { 
1999/0423    
 
	writel(ZR36057_I2C_SCL|ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_waitscl(); 
	lml33_i2c_pause(); 
1999/0429    
	i2c_waitscl(); 
	i2c_pause(); 
1999/0423    
 
	writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
1999/0429    
	i2c_pause(); 
1999/0423    
 
	writel(0, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
1999/0429    
	i2c_pause(); 
1999/0423    
} 
 
static void 
lml33_i2c_stop(void) { 
1999/0429    
i2c_stop(void) { 
1999/0423    
	// the clock should already be low, make sure data is 
	writel(0, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
1999/0429    
	i2c_pause(); 
1999/0423    
 
	// set clock high and wait for device to catch up 
	writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_waitscl(); 
	lml33_i2c_pause(); 
1999/0429    
	i2c_waitscl(); 
	i2c_pause(); 
1999/0423    
 
	// set the data high to indicate the stop bit 
	writel(ZR36057_I2C_SCL|ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
1999/0429    
	i2c_pause(); 
1999/0423    
} 
 
static void lml33_i2c_wrbit(int bit) { 
1999/0429    
static void i2c_wrbit(int bit) { 
1999/0423    
	if (bit){ 
		writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); // set data 
		lml33_i2c_pause(); 
1999/0429    
		i2c_pause(); 
1999/0423    
		writel(ZR36057_I2C_SDA|ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
		lml33_i2c_waitscl(); 
		lml33_i2c_pause(); 
1999/0429    
		i2c_waitscl(); 
		i2c_pause(); 
1999/0423    
		writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
		lml33_i2c_pause(); 
1999/0429    
		i2c_pause(); 
1999/0423    
	} else { 
		writel(0, pciBaseAddr + ZR36057_I2C_BUS); // clr data 
		lml33_i2c_pause(); 
1999/0429    
		i2c_pause(); 
1999/0423    
		writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
		lml33_i2c_waitscl(); 
		lml33_i2c_pause(); 
1999/0429    
		i2c_waitscl(); 
		i2c_pause(); 
1999/0423    
		writel(0, pciBaseAddr + ZR36057_I2C_BUS); 
		lml33_i2c_pause(); 
1999/0429    
		i2c_pause(); 
1999/0423    
	} 
} 
 
static int 
lml33_i2c_rdbit(void) { 
1999/0429    
i2c_rdbit(void) { 
1999/0423    
	int bit; 
	// the clk line should be low 
 
	// ensure we are not asserting the data line 
	writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
1999/0429    
	i2c_pause(); 
1999/0423    
 
	// set the clock high and wait for device to catch up 
	writel(ZR36057_I2C_SDA|ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_waitscl(); 
	lml33_i2c_pause(); 
1999/0429    
	i2c_waitscl(); 
	i2c_pause(); 
1999/0423    
 
	// the data line should be a valid bit 
	bit = readl(pciBaseAddr+ZR36057_I2C_BUS); 
1999/0428/sys/src/9/pc/devlml.c:137,1491999/0429/sys/src/9/pc/devlml.c:138,150
1999/0423    
 
	// set the clock low to indicate end of cycle 
	writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
	lml33_i2c_pause(); 
1999/0429    
	i2c_pause(); 
1999/0423    
 
	return bit; 
} 
 
static int 
lml33_i2c_rdbyte(uchar *v) { 
1999/0429    
i2c_rdbyte(uchar *v) { 
1999/0423    
	int i, ack; 
	uchar res; 
 
1999/0428/sys/src/9/pc/devlml.c:150,1591999/0429/sys/src/9/pc/devlml.c:151,160
1999/0423    
	res = 0; 
	for (i=0;i<8;i++){ 
		res  = res << 1; 
		res += lml33_i2c_rdbit(); 
1999/0429    
		res += i2c_rdbit(); 
1999/0423    
	} 
 
	ack = lml33_i2c_rdbit(); 
1999/0429    
	ack = i2c_rdbit(); 
1999/0423    
 
	*v = res; 
 
1999/0428/sys/src/9/pc/devlml.c:161,2371999/0429/sys/src/9/pc/devlml.c:162,254
1999/0423    
} 
 
static int 
lml33_i2c_wrbyte(uchar v) { 
1999/0429    
i2c_wrbyte(uchar v) { 
1999/0423    
	int i, ack; 
 
	for (i=0;i<8;i++){ 
		lml33_i2c_wrbit(v & 0x80); 
1999/0429    
		i2c_wrbit(v & 0x80); 
1999/0423    
		v = v << 1; 
	} 
 
	ack = lml33_i2c_rdbit(); 
1999/0429    
	ack = i2c_rdbit(); 
1999/0423    
 
	return ack; 
} 
 
static void 
lml33_i2c_write_bytes(uchar addr, uchar sub, uchar *bytes, long num) { 
1999/0429    
i2c_write_bytes(uchar addr, uchar sub, uchar *bytes, long num) { 
1999/0423    
	int ack; 
	long i; 
 
	lml33_i2c_start(); 
1999/0429    
	i2c_start(); 
1999/0423    
 
	ack = lml33_i2c_wrbyte(addr); 
1999/0429    
	ack = i2c_wrbyte(addr); 
1999/0423    
	if (ack == 1) error(Eio); 
 
	ack = lml33_i2c_wrbyte(sub); 
1999/0429    
	ack = i2c_wrbyte(sub); 
1999/0423    
	if (ack == 1) error(Eio); 
 
	for(i=0;i<num;i+=1){ 
		ack = lml33_i2c_wrbyte(bytes[i]); 
1999/0429    
		ack = i2c_wrbyte(bytes[i]); 
1999/0423    
		if (ack == 1) error(Eio); 
	} 
 
	lml33_i2c_stop(); 
1999/0429    
	i2c_stop(); 
1999/0423    
} 
 
1999/0424    
static int 
1999/0423    
lml33_i2c_rd8(int addr, int sub) 
1999/0429    
i2c_bt856rd8(void) { 
	uchar ret; 
 
	i2c_start (); 
 
	if (i2c_wrbyte(BT856Addr + 1) == 1 
	 || i2c_rdbyte(&ret) == 0) { 
		i2c_stop (); 
		return -1; 
	} 
 
	i2c_stop (); 
	return ret; 
} 
 
static int 
i2c_rd8(int addr, int sub) 
1999/0423    
{ 
	uchar msb; 
 
	lml33_i2c_start(); 
1999/0429    
	i2c_start(); 
1999/0423    
 
1999/0424    
	if (lml33_i2c_wrbyte(addr) == 1 
	 || lml33_i2c_wrbyte(sub) == 1) { 
1999/0423    
		lml33_i2c_stop(); 
1999/0429    
	if (i2c_wrbyte(addr) == 1 
	 || i2c_wrbyte(sub) == 1) { 
		i2c_stop(); 
1999/0424    
		return -1; 
1999/0423    
	} 
 
	lml33_i2c_start(); 
1999/0429    
	i2c_start(); 
1999/0423    
 
1999/0424    
	if (lml33_i2c_wrbyte(addr+1) == 1 
	 || lml33_i2c_rdbyte(&msb) == 0){ 
1999/0423    
		lml33_i2c_stop(); 
1999/0429    
	if (i2c_wrbyte(addr+1) == 1 
	 || i2c_rdbyte(&msb) == 0){ 
		i2c_stop(); 
1999/0424    
		return -1; 
1999/0423    
	} 
 
	lml33_i2c_stop(); 
1999/0429    
	i2c_stop(); 
1999/0423    
 
	return msb; 
} 
 
1999/0424    
static int 
lml33_i2c_wr8(uchar addr, uchar sub, uchar msb) { 
1999/0429    
i2c_wr8(uchar addr, uchar sub, uchar msb) { 
1999/0424    
	 
	lml33_i2c_start(); 
1999/0429    
	i2c_start(); 
1999/0424    
 
	if (lml33_i2c_wrbyte(addr) == 1 
	 || lml33_i2c_wrbyte(sub) == 1 
	 || lml33_i2c_wrbyte(msb) == 1) 
1999/0429    
	if (i2c_wrbyte(addr) == 1 
	 || i2c_wrbyte(sub) == 1 
	 || i2c_wrbyte(msb) == 1) 
1999/0424    
		return 0; 
	 
	lml33_i2c_stop(); 
1999/0429    
	i2c_stop(); 
1999/0424    
	 
	return 1; 
} 
1999/0428/sys/src/9/pc/devlml.c:565,5821999/0429/sys/src/9/pc/devlml.c:582,613
1999/0424    
		if (off < 0 || off + n > 0x20) 
1999/0423    
			return 0; 
1999/0424    
		for (i = 0; i < n; i++) { 
			if ((d = lml33_i2c_rd8(BT819Addr, off++)) < 0) break; 
1999/0429    
			if ((d = i2c_rd8(BT819Addr, off++)) < 0) break; 
1999/0424    
			*buf++ = d; 
		} 
		return n - i; 
1999/0422    
	case Q856: 
1999/0423    
		if (off < 0xda || off + n > 0xe0) 
1999/0429    
		if (n != 1) 
1999/0423    
			return 0; 
1999/0424    
		for (i = 0; i < n; i++) { 
			if ((d = lml33_i2c_rd8(BT856Addr, off++)) < 0) break; 
			*buf++ = d; 
1999/0429    
		switch ((int)off) { 
		case 0: 
			if ((d = i2c_bt856rd8()) < 0) 
				return 0; 
			*buf = d; 
			break; 
		case 0xDA: 
			*buf = q856[0]; 
			break; 
		case 0xDC: 
			*buf = q856[1]; 
			break; 
		case 0xDE: 
			*buf = q856[2]; 
			break; 
		default: 
			return 0; 
1999/0424    
		} 
		return n - i; 
1999/0429    
		return 1; 
1999/0428    
	case Qreg: 
1999/0424    
		if (off < 0 || off + n > 0x200 || (off & 0x3)) 
			return 0; 
1999/0428/sys/src/9/pc/devlml.c:610,6251999/0429/sys/src/9/pc/devlml.c:641,666
1999/0424    
		if (off < 0 || off + n > 0x20) 
1999/0423    
			return 0; 
1999/0424    
		for (i = n; i > 0; i--) 
			if (lml33_i2c_wr8(BT819Addr, off++, *buf++) == 0) 
1999/0429    
			if (i2c_wr8(BT819Addr, off++, *buf++) == 0) 
1999/0424    
				break; 
		return n - i; 
1999/0423    
	case Q856: 
		if (off < 0xda || off + n > 0xe0) 
1999/0429    
		if (n != 1 || off < 0xda || off + n > 0xe0) 
1999/0423    
			return 0; 
1999/0424    
		for (i = n; i > 0; i--) 
			if (lml33_i2c_wr8(BT856Addr, off++, *buf++) == 0) 
				break; 
		return n - i; 
1999/0429    
		if (i2c_wr8(BT856Addr, off, *buf) == 0) 
				return 0; 
		switch ((int)off) { 
		case 0xDA: 
			q856[0] = *buf; 
			break; 
		case 0xDC: 
			q856[1] = *buf; 
			break; 
		case 0xDE: 
			q856[2] = *buf; 
			break; 
		} 
		return 1; 
1999/0428    
	case Qreg: 
1999/0424    
		if (off < 0 || off + n > 0x200 || (off & 0x3)) 
			return 0; 
1999/0429/sys/src/9/pc/devlml.c:405,4121999/0430/sys/src/9/pc/devlml.c:405,412 (short | long)
1999/0424    
			memmove((char*)&frameHeader + hdrPos, buf, hdrLeft); 
			// Make sure we have a standard LML33 header 
			if (frameHeader.mrkSOI == MRK_SOI 
			 && frameHeader.mrkAPP3==MRK_APP3 
			 && strcmp(frameHeader.nm,APP_NAME) == 0) { 
1999/0430    
			 && frameHeader.mrkAPP3 == MRK_APP3 
			 && strcmp(frameHeader.nm, APP_NAME) == 0) { 
1999/0424    
				//print("Starting new buffer len=0x%x frame=%d\n", frameHeader.frameSize, frameHeader.frameSeqNo); 
				// Obtain values we need for playback process from the header 
				currentBufferLength = frameHeader.frameSize; 
1999/0429/sys/src/9/pc/devlml.c:609,6151999/0430/sys/src/9/pc/devlml.c:609,615
1999/0424    
		} 
1999/0429    
		return 1; 
1999/0428    
	case Qreg: 
1999/0424    
		if (off < 0 || off + n > 0x200 || (off & 0x3)) 
1999/0430    
		if (off < 0 || off + n > 0x400) 
1999/0424    
			return 0; 
1999/0428    
		switch(n) { 
		case 1: 
1999/0429/sys/src/9/pc/devlml.c:616,6241999/0430/sys/src/9/pc/devlml.c:616,626
1999/0428    
			*buf = readb(pciBaseAddr + off); 
			break; 
		case 2: 
1999/0430    
			if (off & (n-1)) return 0; 
1999/0428    
			*(short *)buf = readw(pciBaseAddr + off); 
			break; 
		case 4: 
1999/0430    
			if (off & (n-1)) return 0; 
1999/0424    
			*(long *)buf = readl(pciBaseAddr + off); 
1999/0428    
			break; 
		default: 
1999/0430/sys/src/9/pc/devlml.c:11,431999/0513/sys/src/9/pc/devlml.c:11,44 (short | long)
1999/0422    
// Lml 22 driver 
 
enum{ 
1999/0513    
	Qdir, 
1999/0422    
	Q819, 
	Q856, 
1999/0428    
	Qreg, 
1999/0422    
	Qvideo, 
1999/0513    
	Qjvideo, 
1999/0422    
	Qjframe, 
}; 
 
static Dirtab viddir[]={ 
//	 name,		 qid,	  size,		mode 
	"vid819",	{Q819},		0,		0644, 
	"vid856",	{Q856},		0,		0644, 
1999/0428    
	"vidreg",	{Qreg},		0,		0644, 
1999/0422    
	"video",	{Qvideo},	0,		0666, 
1999/0513    
static Dirtab lmldir[]={ 
//	 name,		 qid,		size,		mode 
	"lml819",	{Q819},		0,		0644, 
	"lml856",	{Q856},		0,		0644, 
	"lmlreg",	{Qreg},		0,		0644, 
	"jvideo",	{Qjvideo},	0,		0666, 
1999/0422    
	"jframe",	{Qjframe},	0,		0666, 
}; 
 
CodeData *	codeData; 
 
1999/0424    
int			currentBuffer; 
int			currentBufferLength; 
1999/0513    
int		currentBuffer; 
int		currentBufferLength; 
1999/0424    
void *		currentBufferPtr; 
int			frameNo; 
1999/0513    
int		frameNo; 
1999/0424    
Rendez		sleeper; 
int			singleFrame; 
int			bufferPrepared; 
int			hdrPos; 
int			nopens; 
1999/0513    
int		singleFrame; 
int		bufferPrepared; 
int		hdrPos; 
int		nopens; 
1999/0429    
uchar		q856[3]; 
1999/0424    
 
static FrameHeader frameHeader = { 
1999/0430/sys/src/9/pc/devlml.c:455,4611999/0513/sys/src/9/pc/devlml.c:456,462
1999/0423    
static void lmlintr(Ureg *, void *); 
 
static void 
1999/0422    
vidreset(void) 
1999/0513    
lmlreset(void) 
1999/0422    
{ 
	ulong regpa; 
	int i; 
1999/0430/sys/src/9/pc/devlml.c:462,4681999/0513/sys/src/9/pc/devlml.c:463,468
1999/0422    
 
1999/0423    
	pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067); 
	if (pcidev == nil) { 
		print("No zr36067 found.\n"); 
		return; 
	} 
1999/0422    
	codeData = (CodeData*)xspanalloc(sizeof(CodeData), BY2PG, 0); 
1999/0430/sys/src/9/pc/devlml.c:472,4781999/0513/sys/src/9/pc/devlml.c:472,478
1999/0422    
	} 
 
	print("Installing Motion JPEG driver %s\n", MJPG_VERSION);  
	print("Buffer size %ux\n", sizeof(CodeData));  
1999/0513    
	print("Buffer at 0x%.8lux, size 0x%.8ux\n", codeData, sizeof(CodeData));  
1999/0422    
 
	// Get access to DMA memory buffer 
	memset(codeData, 0xAA, sizeof(CodeData)); 
1999/0430/sys/src/9/pc/devlml.c:491,4971999/0513/sys/src/9/pc/devlml.c:491,497
1999/0422    
 
1999/0423    
	pciPhysBaseAddr = (void *)(pcidev->mem[0].bar & ~0x0F); 
1999/0422    
 
1999/0423    
	print("zr36067 found at %lux\n", pciPhysBaseAddr); 
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) { 
1999/0430/sys/src/9/pc/devlml.c:499,5041999/0513/sys/src/9/pc/devlml.c:499,505
1999/0422    
		return; 
	} 
1999/0423    
	pciBaseAddr = (ulong)KADDR(regpa); 
1999/0513    
	print(", mapped at 0x%.8lux\n", pciBaseAddr); 
1999/0422    
 
	// make sure the device will respond to mem accesses 
	// (pcicmd_master | pcicmd_memory) -- probably superfluous 
1999/0430/sys/src/9/pc/devlml.c:510,5391999/0513/sys/src/9/pc/devlml.c:511,539
1999/0422    
	// Interrupt handler 
1999/0423    
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); 
1999/0422    
 
	print("LML33 Installed\n");  
	return;  
} 
 
static Chan* 
vidattach(char *spec) 
1999/0513    
lmlattach(char *spec) 
1999/0422    
{ 
	return devattach('V', spec); 
} 
 
static int 
vidwalk(Chan *c, char *name) 
1999/0513    
lmlwalk(Chan *c, char *name) 
1999/0422    
{ 
	return devwalk(c, name, viddir, nelem(viddir), devgen); 
1999/0513    
	return devwalk(c, name, lmldir, nelem(lmldir), devgen); 
1999/0422    
} 
 
static void 
vidstat(Chan *c, char *dp) 
1999/0513    
lmlstat(Chan *c, char *dp) 
1999/0422    
{ 
	devstat(c, dp, viddir, nelem(viddir), devgen); 
1999/0513    
	devstat(c, dp, lmldir, nelem(lmldir), devgen); 
1999/0422    
} 
 
static Chan* 
vidopen(Chan *c, int omode) 
1999/0513    
lmlopen(Chan *c, int omode) 
1999/0422    
{ 
	c->aux = 0; 
	switch(c->qid.path){ 
1999/0430/sys/src/9/pc/devlml.c:541,5471999/0513/sys/src/9/pc/devlml.c:541,547
1999/0422    
	case Q856: 
1999/0428    
	case Qreg: 
1999/0422    
		break; 
	case Qvideo: 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0424    
		if (nopens) 
			error(Einuse); 
1999/0430/sys/src/9/pc/devlml.c:556,5721999/0513/sys/src/9/pc/devlml.c:556,572
1999/0422    
		// allow one open total for these two 
		break; 
	} 
	return devopen(c, omode, viddir, nelem(viddir), devgen); 
1999/0513    
	return devopen(c, omode, lmldir, nelem(lmldir), devgen); 
1999/0422    
} 
 
static void 
vidclose(Chan *c) 
1999/0513    
lmlclose(Chan *c) 
1999/0422    
{ 
	switch(c->qid.path){ 
	case Q819: 
	case Q856: 
1999/0428    
	case Qreg: 
1999/0422    
	case Qvideo: 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
		authclose(c); 
	} 
1999/0430/sys/src/9/pc/devlml.c:573,5831999/0513/sys/src/9/pc/devlml.c:573,589
1999/0422    
} 
 
static long 
1999/0424    
vidread(Chan *c, void *va, long n, vlong off) { 
1999/0513    
lmlread(Chan *c, void *va, long n, vlong voff) { 
1999/0424    
	int i, d; 
	uchar *buf = va; 
1999/0513    
	long off = voff; 
	long v; 
1999/0423    
 
1999/0422    
	switch(c->qid.path){ 
1999/0513    
	switch(c->qid.path & ~CHDIR){ 
 
	case Qdir: 
		return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen); 
 
1999/0422    
	case Q819: 
1999/0424    
		if (off < 0 || off + n > 0x20) 
1999/0423    
			return 0; 
1999/0430/sys/src/9/pc/devlml.c:621,6331999/0513/sys/src/9/pc/devlml.c:627,641
1999/0428    
			break; 
		case 4: 
1999/0430    
			if (off & (n-1)) return 0; 
1999/0424    
			*(long *)buf = readl(pciBaseAddr + off); 
1999/0513    
			v = readl(pciBaseAddr + off); 
			*(long *)buf = v; 
print("reading %lux at %lux (%lux)\n", v, pciBaseAddr + off, off); 
1999/0428    
			break; 
		default: 
			return 0; 
1999/0424    
		} 
1999/0428    
		return n; 
1999/0422    
	case Qvideo: 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0424    
		return vread(c, buf, n, off); 
1999/0422    
	} 
1999/0430/sys/src/9/pc/devlml.c:634,6441999/0513/sys/src/9/pc/devlml.c:642,656
1999/0422    
} 
 
static long 
1999/0424    
vidwrite(Chan *c, void *va, long n, vlong off) { 
1999/0513    
lmlwrite(Chan *c, void *va, long n, vlong off) { 
1999/0424    
	int i; 
	uchar *buf = va; 
1999/0423    
 
	switch(c->qid.path){ 
1999/0513    
	switch(c->qid.path & ~CHDIR){ 
 
	case Qdir: 
		error(Eperm); 
 
1999/0423    
	case Q819: 
1999/0424    
		if (off < 0 || off + n > 0x20) 
1999/0423    
			return 0; 
1999/0430/sys/src/9/pc/devlml.c:680,7071999/0513/sys/src/9/pc/devlml.c:692,719
1999/0428    
			return 0; 
1999/0424    
		} 
1999/0428    
		return n; 
1999/0423    
	case Qvideo: 
1999/0513    
	case Qjvideo: 
1999/0423    
	case Qjframe: 
1999/0424    
		return vwrite(c, buf, n, off); 
1999/0423    
	} 
1999/0422    
} 
 
Dev viddevtab = { 
1999/0513    
Dev lmldevtab = { 
1999/0422    
	'V', 
	"video", 
 
	vidreset, 
1999/0513    
	lmlreset, 
1999/0422    
	devinit, 
	vidattach, 
1999/0513    
	lmlattach, 
1999/0422    
	devclone, 
	vidwalk, 
	vidstat, 
	vidopen, 
1999/0513    
	lmlwalk, 
	lmlstat, 
	lmlopen, 
1999/0422    
	devcreate, 
	vidclose, 
	vidread, 
1999/0513    
	lmlclose, 
	lmlread, 
1999/0422    
	devbread, 
	vidwrite, 
1999/0513    
	lmlwrite, 
1999/0422    
	devbwrite, 
	devremove, 
	devwstat, 
1999/0513/sys/src/9/pc/devlml.c:642,6501999/0514/sys/src/9/pc/devlml.c:642,651 (short | long)
1999/0422    
} 
 
static long 
1999/0513    
lmlwrite(Chan *c, void *va, long n, vlong off) { 
1999/0514    
lmlwrite(Chan *c, void *va, long n, vlong voff) { 
1999/0424    
	int i; 
	uchar *buf = va; 
1999/0514    
	long off = voff; 
1999/0423    
 
1999/0513    
	switch(c->qid.path & ~CHDIR){ 
 
1999/0513/sys/src/9/pc/devlml.c:686,6911999/0514/sys/src/9/pc/devlml.c:687,693
1999/0428    
			writew(*(short *)buf, pciBaseAddr + off); 
			break; 
		case 4: 
1999/0514    
print("writing %lux to %lux (%lux)\n", *(long *)buf, pciBaseAddr + off, off); 
1999/0424    
			writel(*(long *)buf, pciBaseAddr + off); 
1999/0428    
			break; 
		default: 
1999/0514/sys/src/9/pc/devlml.c:8,131999/0515/sys/src/9/pc/devlml.c:8,18 (short | long)
1999/0422    
 
#include	"devlml.h" 
 
1999/0515    
#define DBGREGS 0x1 
#define DBGREAD 0x2 
#define DBGWRIT 0x4 
int debug = DBGREAD|DBGWRIT; 
 
1999/0422    
// Lml 22 driver 
 
enum{ 
1999/0514/sys/src/9/pc/devlml.c:15,201999/0515/sys/src/9/pc/devlml.c:20,26
1999/0422    
	Q819, 
	Q856, 
1999/0428    
	Qreg, 
1999/0515    
	Qmap, 
1999/0513    
	Qjvideo, 
1999/0422    
	Qjframe, 
}; 
1999/0514/sys/src/9/pc/devlml.c:24,291999/0515/sys/src/9/pc/devlml.c:30,36
1999/0513    
	"lml819",	{Q819},		0,		0644, 
	"lml856",	{Q856},		0,		0644, 
	"lmlreg",	{Qreg},		0,		0644, 
1999/0515    
	"lmlmap",	{Qmap},		0,		0444, 
1999/0513    
	"jvideo",	{Qjvideo},	0,		0666, 
1999/0422    
	"jframe",	{Qjframe},	0,		0666, 
}; 
1999/0514/sys/src/9/pc/devlml.c:41,461999/0515/sys/src/9/pc/devlml.c:48,59
1999/0513    
int		nopens; 
1999/0429    
uchar		q856[3]; 
1999/0424    
 
1999/0515    
struct { 
	ulong pci; 
	ulong dma; 
	ulong codedata; 
} lmlmap; 
 
1999/0424    
static FrameHeader frameHeader = { 
	MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, 
	{ 'L', 'M', 'L', '\0'}, 
1999/0514/sys/src/9/pc/devlml.c:47,521999/0515/sys/src/9/pc/devlml.c:60,122
1999/0424    
	-1, 0, 0, 0, 0 
}; 
 
1999/0515    
ulong 
writel(ulong v, ulong a) { 
	if (debug&DBGREGS) 
		pprint("writing %.8lux  to  %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
	return *(ulong *)a = v; 
} 
 
ushort 
writew(ushort v, ulong a) { 
	if (debug&DBGREGS) 
		pprint("writing     %.4ux  to  %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
	return *(ushort *)a = v; 
} 
 
uchar 
writeb(uchar v, ulong a) { 
	if (debug&DBGREGS) 
		pprint("writing       %.2ux  to  %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
	return *(uchar *)a = v; 
} 
 
ulong 
readl(ulong a) { 
	ulong v; 
 
	v = *(ulong*)a; 
	if (debug&DBGREGS) 
		pprint("reading %.8lux from %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
	return v; 
} 
 
ushort 
readw(ulong a) { 
	ushort v; 
 
	v = *(ushort*)a; 
	if (debug&DBGREGS) 
		pprint("reading     %.4ux from %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
	return v; 
} 
 
uchar 
readb(ulong a) { 
	uchar v; 
 
	v = *(uchar*)a; 
	if (debug&DBGREGS) 
		pprint("reading       %.2ux from %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
	return v; 
} 
 
1999/0423    
static void 
1999/0429    
i2c_pause(void) { 
1999/0422    
 
1999/0514/sys/src/9/pc/devlml.c:222,2271999/0515/sys/src/9/pc/devlml.c:292,298
1999/0423    
 
1999/0429    
	if (i2c_wrbyte(addr) == 1 
	 || i2c_wrbyte(sub) == 1) { 
1999/0515    
		if (debug&DBGREGS) pprint("i2c_rd8, failure 1\n"); 
1999/0429    
		i2c_stop(); 
1999/0424    
		return -1; 
1999/0423    
	} 
1999/0514/sys/src/9/pc/devlml.c:230,2351999/0515/sys/src/9/pc/devlml.c:301,307
1999/0423    
 
1999/0429    
	if (i2c_wrbyte(addr+1) == 1 
	 || i2c_rdbyte(&msb) == 0){ 
1999/0515    
		if (debug&DBGREGS) pprint("i2c_rd8, failure 2\n"); 
1999/0429    
		i2c_stop(); 
1999/0424    
		return -1; 
1999/0423    
	} 
1999/0514/sys/src/9/pc/devlml.c:303,3121999/0515/sys/src/9/pc/devlml.c:375,387
1999/0424    
	vlong thetime; 
	uchar *buf = va; 
 
	//print("devlml::vread() count=%ld pos=%lld\n", count, pos); 
1999/0515    
	if(debug&DBGREAD) 
		pprint("devlml::vread() count=%ld pos=%lld\n", count, pos); 
1999/0424    
 
	// If we just begin reading a file, pos would never be 0 otherwise 
	if (pos == 0 && hdrPos == -1) { 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::first read\n"); 
1999/0424    
		 currentBuffer = -1; 
		 currentBufferLength = 0; 
		 frameNo = -1; 
1999/0514/sys/src/9/pc/devlml.c:316,3271999/0515/sys/src/9/pc/devlml.c:391,408
1999/0424    
	// We get to the end of the current buffer, also covers just 
	// open file, since 0 >= -1 
	if(hdrPos == -1 && pos >= currentBufferLength) { 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::prepareBuffer\n"); 
1999/0424    
		prepareBuffer(codeData, currentBuffer); 
		// if not the first buffer read and single frame mode - return EOF 
		if (currentBuffer != -1 && singleFrame) 
			return 0; 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::sleep\n"); 
1999/0424    
		while((currentBuffer = getProcessedBuffer(codeData)) == -1) 
			sleep(&sleeper, return0, 0); 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::wokeup\n"); 
1999/0424    
		currentBufferLength = getBuffer(codeData, currentBuffer, 
			¤tBufferPtr, &frameNo); 
 
1999/0514/sys/src/9/pc/devlml.c:362,3681999/0515/sys/src/9/pc/devlml.c:443,449
1999/0424    
	memmove(buf + retcount, (char *)currentBufferPtr + pos, cpcount); 
	retcount += cpcount; 
 
	//pr_debug("return %d %d\n",cpcount,retcount); 
1999/0515    
	//pr_debug&DBGREGS("return %d %d\n",cpcount,retcount); 
1999/0424    
	return retcount; 
1999/0423    
} 
 
1999/0514/sys/src/9/pc/devlml.c:511,5161999/0515/sys/src/9/pc/devlml.c:592,601
1999/0422    
	// Interrupt handler 
1999/0423    
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); 
1999/0422    
 
1999/0515    
	lmlmap.pci = pciBaseAddr; 
	lmlmap.dma = PADDR(codeData); 
	lmlmap.codedata = (ulong)codeData; 
 
1999/0422    
	return;  
} 
 
1999/0514/sys/src/9/pc/devlml.c:540,5451999/0515/sys/src/9/pc/devlml.c:625,631
1999/0422    
	case Q819: 
	case Q856: 
1999/0428    
	case Qreg: 
1999/0515    
	case Qmap: 
1999/0422    
		break; 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0514/sys/src/9/pc/devlml.c:566,5731999/0515/sys/src/9/pc/devlml.c:652,663
1999/0422    
	case Q819: 
	case Q856: 
1999/0428    
	case Qreg: 
1999/0515    
	case Qmap: 
		authclose(c); 
		break; 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0515    
		nopens = 0; 
1999/0422    
		authclose(c); 
	} 
} 
1999/0514/sys/src/9/pc/devlml.c:577,5831999/0515/sys/src/9/pc/devlml.c:667,672
1999/0424    
	int i, d; 
	uchar *buf = va; 
1999/0513    
	long off = voff; 
	long v; 
1999/0423    
 
1999/0513    
	switch(c->qid.path & ~CHDIR){ 
 
1999/0514/sys/src/9/pc/devlml.c:591,5971999/0515/sys/src/9/pc/devlml.c:680,686
1999/0429    
			if ((d = i2c_rd8(BT819Addr, off++)) < 0) break; 
1999/0424    
			*buf++ = d; 
		} 
		return n - i; 
1999/0515    
		return i; 
1999/0422    
	case Q856: 
1999/0429    
		if (n != 1) 
1999/0423    
			return 0; 
1999/0514/sys/src/9/pc/devlml.c:614,6191999/0515/sys/src/9/pc/devlml.c:703,717
1999/0429    
			return 0; 
1999/0424    
		} 
1999/0429    
		return 1; 
1999/0515    
	case Qmap: 
		if (off < 0) 
			return 0; 
		for (i = 0; i < n; i++) { 
			if (off + i > sizeof lmlmap) 
				break; 
			buf[i] = ((uchar *)&lmlmap)[off + i]; 
		} 
		return i; 
1999/0428    
	case Qreg: 
1999/0430    
		if (off < 0 || off + n > 0x400) 
1999/0424    
			return 0; 
1999/0514/sys/src/9/pc/devlml.c:627,6351999/0515/sys/src/9/pc/devlml.c:725,731
1999/0428    
			break; 
		case 4: 
1999/0430    
			if (off & (n-1)) return 0; 
1999/0513    
			v = readl(pciBaseAddr + off); 
			*(long *)buf = v; 
print("reading %lux at %lux (%lux)\n", v, pciBaseAddr + off, off); 
1999/0515    
			*(long *)buf = readl(pciBaseAddr + off); 
1999/0428    
			break; 
		default: 
			return 0; 
1999/0514/sys/src/9/pc/devlml.c:658,6641999/0515/sys/src/9/pc/devlml.c:754,760
1999/0424    
		for (i = n; i > 0; i--) 
1999/0429    
			if (i2c_wr8(BT819Addr, off++, *buf++) == 0) 
1999/0424    
				break; 
		return n - i; 
1999/0515    
		return i; 
1999/0423    
	case Q856: 
1999/0429    
		if (n != 1 || off < 0xda || off + n > 0xe0) 
1999/0423    
			return 0; 
1999/0514/sys/src/9/pc/devlml.c:677,6831999/0515/sys/src/9/pc/devlml.c:773,779
1999/0429    
		} 
		return 1; 
1999/0428    
	case Qreg: 
1999/0424    
		if (off < 0 || off + n > 0x200 || (off & 0x3)) 
1999/0515    
		if (off < 0 || off + n > 0x400) 
1999/0424    
			return 0; 
1999/0428    
		switch (n) { 
		case 1: 
1999/0514/sys/src/9/pc/devlml.c:684,6931999/0515/sys/src/9/pc/devlml.c:780,792
1999/0428    
			writeb(*buf, pciBaseAddr + off); 
			break; 
		case 2: 
1999/0515    
			if (off & 0x1) 
				return 0; 
1999/0428    
			writew(*(short *)buf, pciBaseAddr + off); 
			break; 
		case 4: 
1999/0514    
print("writing %lux to %lux (%lux)\n", *(long *)buf, pciBaseAddr + off, off); 
1999/0515    
			if (off & 0x3) 
				return 0; 
1999/0424    
			writel(*(long *)buf, pciBaseAddr + off); 
1999/0428    
			break; 
		default: 
1999/0514/sys/src/9/pc/devlml.c:725,7361999/0515/sys/src/9/pc/devlml.c:824,839
1999/0424    
lmlintr(Ureg *, void *) { 
	ulong flags = readl(pciBaseAddr+ZR36057_INTR_STAT); 
	 
//  print("MjpgDrv_intrHandler stat=0x%08x\n", flags); 
1999/0515    
	if(debug&(DBGREAD|DBGWRIT)) 
		print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags); 
1999/0422    
 
1999/0424    
	// Reset all interrupts from 067 
	writel(0xff000000, pciBaseAddr + ZR36057_INTR_STAT); 
1999/0423    
 
1999/0424    
	if(flags & ZR36057_INTR_JPEGREP) 
			wakeup(&sleeper); 
1999/0515    
	if(flags & ZR36057_INTR_JPEGREP) { 
		if(debug&(DBGREAD|DBGWRIT)) 
			print("MjpgDrv_intrHandler wakeup\n"); 
		wakeup(&sleeper); 
	} 
1999/0424    
	return; 
1999/0422    
} 
1999/0515/sys/src/9/pc/devlml.c:11,201999/0517/sys/src/9/pc/devlml.c:11,26 (short | long)
1999/0515    
#define DBGREGS 0x1 
#define DBGREAD 0x2 
#define DBGWRIT 0x4 
int debug = DBGREAD|DBGWRIT; 
1999/0517    
int debug = DBGREAD|DBGWRIT|DBGREGS; 
1999/0515    
 
1999/0422    
// Lml 22 driver 
 
1999/0517    
struct { 
	ulong pci; 
	ulong dma; 
	ulong codedata; 
} lmlmap; 
 
1999/0422    
enum{ 
1999/0513    
	Qdir, 
1999/0422    
	Q819, 
1999/0515/sys/src/9/pc/devlml.c:29,361999/0517/sys/src/9/pc/devlml.c:35,42
1999/0513    
//	 name,		 qid,		size,		mode 
	"lml819",	{Q819},		0,		0644, 
	"lml856",	{Q856},		0,		0644, 
	"lmlreg",	{Qreg},		0,		0644, 
1999/0515    
	"lmlmap",	{Qmap},		0,		0444, 
1999/0517    
	"lmlreg",	{Qreg},		0x400,		0644, 
	"lmlmap",	{Qmap},		sizeof lmlmap,	0444, 
1999/0513    
	"jvideo",	{Qjvideo},	0,		0666, 
1999/0422    
	"jframe",	{Qjframe},	0,		0666, 
}; 
1999/0515/sys/src/9/pc/devlml.c:48,591999/0517/sys/src/9/pc/devlml.c:54,59
1999/0513    
int		nopens; 
1999/0429    
uchar		q856[3]; 
1999/0424    
 
1999/0515    
struct { 
	ulong pci; 
	ulong dma; 
	ulong codedata; 
} lmlmap; 
                 
1999/0424    
static FrameHeader frameHeader = { 
	MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, 
	{ 'L', 'M', 'L', '\0'}, 
1999/0515/sys/src/9/pc/devlml.c:63,701999/0517/sys/src/9/pc/devlml.c:63,70
1999/0515    
ulong 
writel(ulong v, ulong a) { 
	if (debug&DBGREGS) 
		pprint("writing %.8lux  to  %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
1999/0517    
		pprint("%.8lux (%.8lux) <-- %.8lux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return *(ulong *)a = v; 
} 
 
1999/0515/sys/src/9/pc/devlml.c:71,781999/0517/sys/src/9/pc/devlml.c:71,78
1999/0515    
ushort 
writew(ushort v, ulong a) { 
	if (debug&DBGREGS) 
		pprint("writing     %.4ux  to  %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
1999/0517    
		pprint("%.8lux (%.8lux) <--     %.4ux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return *(ushort *)a = v; 
} 
 
1999/0515/sys/src/9/pc/devlml.c:79,861999/0517/sys/src/9/pc/devlml.c:79,86
1999/0515    
uchar 
writeb(uchar v, ulong a) { 
	if (debug&DBGREGS) 
		pprint("writing       %.2ux  to  %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
1999/0517    
		pprint("%.8lux (%.8lux) <--       %.2ux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return *(uchar *)a = v; 
} 
 
1999/0515/sys/src/9/pc/devlml.c:90,971999/0517/sys/src/9/pc/devlml.c:90,97
1999/0515    
 
	v = *(ulong*)a; 
	if (debug&DBGREGS) 
		pprint("reading %.8lux from %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
1999/0517    
		pprint("%.8lux (%.8lux) --> %.8lux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return v; 
} 
 
1999/0515/sys/src/9/pc/devlml.c:101,1081999/0517/sys/src/9/pc/devlml.c:101,108
1999/0515    
 
	v = *(ushort*)a; 
	if (debug&DBGREGS) 
		pprint("reading     %.4ux from %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
1999/0517    
		pprint("%.8lux (%.8lux) -->     %.4ux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return v; 
} 
 
1999/0515/sys/src/9/pc/devlml.c:112,1191999/0517/sys/src/9/pc/devlml.c:112,119
1999/0515    
 
	v = *(uchar*)a; 
	if (debug&DBGREGS) 
		pprint("reading       %.2ux from %.8lux (%.4lux)\n", 
			v, a, (ulong)a-pciBaseAddr); 
1999/0517    
		pprint("%.8lux (%.8lux) -->       %.2ux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return v; 
} 
 
1999/0515/sys/src/9/pc/devlml.c:330,3361999/0517/sys/src/9/pc/devlml.c:330,336
1999/0424    
prepareBuffer(CodeData * this, int bufferNo) { 
  if(bufferNo >= 0 && bufferNo < NBUF && (this->statCom[bufferNo] & STAT_BIT)) { 
    this->statCom[bufferNo] = this->statComInitial[bufferNo]; 
    return this->fragmDescr[bufferNo].fragmLength; 
1999/0517    
    return this->fragdesc[bufferNo].leng; 
1999/0424    
  } else 
    return -1; 
} 
1999/0515/sys/src/9/pc/devlml.c:354,3601999/0517/sys/src/9/pc/devlml.c:354,360
1999/0424    
getBuffer(CodeData *this, int bufferNo, void** bufferPtr, int* frameNo) { 
	int codeLength; 
	if(this->statCom[bufferNo] & STAT_BIT) { 
		*bufferPtr = (void*)this->fragmDescr[bufferNo].fragmAddress; 
1999/0517    
		*bufferPtr = (void*)this->fragdesc[bufferNo].addr; 
1999/0424    
		*frameNo = this->statCom[bufferNo] >> 24; 
		codeLength=((this->statCom[bufferNo] & 0x00FFFFFF) >> 1); 
		return codeLength; 
1999/0515/sys/src/9/pc/devlml.c:560,5711999/0517/sys/src/9/pc/devlml.c:560,570
1999/0422    
	strncpy(codeData->idString, MJPG_VERSION, strlen(MJPG_VERSION)); 
 
	for(i = 0; i < NBUF; i++) { 
		codeData->statCom[i] = PADDR(&(codeData->fragmDescr[i])); 
1999/0517    
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
1999/0422    
		codeData->statComInitial[i] = codeData->statCom[i]; 
		codeData->fragmDescr[i].fragmAddress = 
1999/0423    
			(Fragment *)PADDR(&(codeData->frag[i])); 
1999/0517    
		codeData->fragdesc[i].addr = PADDR(&(codeData->frag[i])); 
1999/0422    
		// Length is in double words, in position 1..20 
		codeData->fragmDescr[i].fragmLength = (FRAGSIZE >> 1) | FRAGM_FINAL_B; 
1999/0517    
		codeData->fragdesc[i].leng = (FRAGSIZE >> 1) | FRAGM_FINAL_B; 
1999/0422    
	} 
 
	print("initializing LML33 board..."); 
1999/0515/sys/src/9/pc/devlml.c:620,6251999/0517/sys/src/9/pc/devlml.c:619,626
1999/0422    
static Chan* 
1999/0513    
lmlopen(Chan *c, int omode) 
1999/0422    
{ 
1999/0517    
	int i; 
 
1999/0422    
	c->aux = 0; 
	switch(c->qid.path){ 
	case Q819: 
1999/0515/sys/src/9/pc/devlml.c:639,6451999/0517/sys/src/9/pc/devlml.c:640,653
1999/0424    
		frameNo = 0; 
		bufferPrepared = 0; 
		hdrPos = -1; 
1999/0517    
 
		for (i = 0; i < 4; i++) { 
			codeData->statCom[i] = codeData->statComInitial[i]; 
			// Also memset the buffer with some fill value 
			memset(&(codeData->frag[i]),0x55,sizeof codeData->frag[i]); 
		} 
1999/0422    
		// allow one open total for these two 
1999/0517    
		intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); 
1999/0422    
		break; 
	} 
1999/0513    
	return devopen(c, omode, lmldir, nelem(lmldir), devgen); 
1999/0515/sys/src/9/pc/devlml.c:707,7131999/0517/sys/src/9/pc/devlml.c:715,721
1999/0515    
		if (off < 0) 
			return 0; 
		for (i = 0; i < n; i++) { 
			if (off + i > sizeof lmlmap) 
1999/0517    
			if (off + i >= sizeof lmlmap) 
1999/0515    
				break; 
			buf[i] = ((uchar *)&lmlmap)[off + i]; 
		} 
1999/0515/sys/src/9/pc/devlml.c:749,7551999/0517/sys/src/9/pc/devlml.c:757,763
1999/0513    
		error(Eperm); 
 
1999/0423    
	case Q819: 
1999/0424    
		if (off < 0 || off + n > 0x20) 
1999/0517    
		if (off < 0 || off + n >= 0x20) 
1999/0423    
			return 0; 
1999/0424    
		for (i = n; i > 0; i--) 
1999/0429    
			if (i2c_wr8(BT819Addr, off++, *buf++) == 0) 
1999/0517/sys/src/9/pc/devlml.c:17,231999/0518/sys/src/9/pc/devlml.c:17,23 (short | long)
1999/0422    
 
1999/0517    
struct { 
	ulong pci; 
	ulong dma; 
1999/0518    
	ulong statcom; 
1999/0517    
	ulong codedata; 
} lmlmap; 
 
1999/0517/sys/src/9/pc/devlml.c:27,321999/0518/sys/src/9/pc/devlml.c:27,33
1999/0422    
	Q856, 
1999/0428    
	Qreg, 
1999/0515    
	Qmap, 
1999/0518    
	Qbuf, 
1999/0513    
	Qjvideo, 
1999/0422    
	Qjframe, 
}; 
1999/0517/sys/src/9/pc/devlml.c:37,421999/0518/sys/src/9/pc/devlml.c:38,44
1999/0513    
	"lml856",	{Q856},		0,		0644, 
1999/0517    
	"lmlreg",	{Qreg},		0x400,		0644, 
	"lmlmap",	{Qmap},		sizeof lmlmap,	0444, 
1999/0518    
	"lmlbuf",	{Qbuf},		0,		0644, 
1999/0513    
	"jvideo",	{Qjvideo},	0,		0666, 
1999/0422    
	"jframe",	{Qjframe},	0,		0666, 
}; 
1999/0517/sys/src/9/pc/devlml.c:327,3501999/0518/sys/src/9/pc/devlml.c:329,352
1999/0424    
} 
 
1999/0423    
static int 
1999/0424    
prepareBuffer(CodeData * this, int bufferNo) { 
  if(bufferNo >= 0 && bufferNo < NBUF && (this->statCom[bufferNo] & STAT_BIT)) { 
    this->statCom[bufferNo] = this->statComInitial[bufferNo]; 
1999/0517    
    return this->fragdesc[bufferNo].leng; 
1999/0424    
  } else 
    return -1; 
1999/0518    
prepareBuffer(int i) { 
	if (i >= 0 && i < NBUF && (codeData->statCom[i] & STAT_BIT)) { 
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
    		return codeData->fragdesc[i].leng; 
	} else 
		return -1; 
1999/0424    
} 
1999/0423    
 
1999/0424    
static int 
getProcessedBuffer(CodeData* this){ 
	static lastBuffer=NBUF-1; 
	int lastBuffer0 = lastBuffer; 
1999/0518    
getProcessedBuffer(void){ 
	static lastBuffer = NBUF-1; 
	int l = lastBuffer; 
1999/0424    
 
	while (1) {  
		lastBuffer = (lastBuffer+1) % NBUF; 
		if(this->statCom[lastBuffer]&STAT_BIT) 
1999/0518    
		if (codeData->statCom[lastBuffer] & STAT_BIT) 
1999/0424    
			return lastBuffer; 
		if(lastBuffer==lastBuffer0) 
1999/0518    
		if (lastBuffer == l) 
1999/0424    
			break; 
1999/0423    
	} 
1999/0424    
	return -1; 
1999/0517/sys/src/9/pc/devlml.c:351,3631999/0518/sys/src/9/pc/devlml.c:353,364
1999/0423    
} 
 
1999/0424    
static int 
getBuffer(CodeData *this, int bufferNo, void** bufferPtr, int* frameNo) { 
	int codeLength; 
	if(this->statCom[bufferNo] & STAT_BIT) { 
1999/0517    
		*bufferPtr = (void*)this->fragdesc[bufferNo].addr; 
1999/0424    
		*frameNo = this->statCom[bufferNo] >> 24; 
		codeLength=((this->statCom[bufferNo] & 0x00FFFFFF) >> 1); 
		return codeLength; 
1999/0518    
getBuffer(int i, void** bufferPtr, int* frameNo) { 
 
	if(codeData->statCom[i] & STAT_BIT) { 
		*bufferPtr = (void*)(&codeData->frag[i]); 
		*frameNo = codeData->statCom[i] >> 24; 
		return (codeData->statCom[i] & 0x00FFFFFF) >> 1; 
1999/0424    
	} else 
		return -1; 
} 
1999/0517/sys/src/9/pc/devlml.c:393,4091999/0518/sys/src/9/pc/devlml.c:394,410
1999/0424    
	if(hdrPos == -1 && pos >= currentBufferLength) { 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::prepareBuffer\n"); 
1999/0424    
		prepareBuffer(codeData, currentBuffer); 
1999/0518    
		prepareBuffer(currentBuffer); 
1999/0424    
		// if not the first buffer read and single frame mode - return EOF 
		if (currentBuffer != -1 && singleFrame) 
			return 0; 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::sleep\n"); 
1999/0424    
		while((currentBuffer = getProcessedBuffer(codeData)) == -1) 
1999/0518    
		while((currentBuffer = getProcessedBuffer()) == -1) 
1999/0424    
			sleep(&sleeper, return0, 0); 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::wokeup\n"); 
1999/0424    
		currentBufferLength = getBuffer(codeData, currentBuffer, 
1999/0518    
		currentBufferLength = getBuffer(currentBuffer, 
1999/0424    
			¤tBufferPtr, &frameNo); 
 
		pos = 0; // ?????????????? 
1999/0517/sys/src/9/pc/devlml.c:466,4761999/0518/sys/src/9/pc/devlml.c:467,477
1999/0424    
	// We need next buffer to fill (either because we're done with the 
	// current buffer) of because we're just beginning (but not into the header) 
	if (hdrPos == -1 && pos >= currentBufferLength) { 
		while((currentBuffer = getProcessedBuffer(codeData)) == -1) 
1999/0518    
		while((currentBuffer = getProcessedBuffer()) == -1) 
1999/0424    
			sleep(&sleeper, return0, 0); 
		// print("current buffer %d\n",currentBuffer); 
 
		getBuffer(codeData, currentBuffer, ¤tBufferPtr, &frameNo); 
1999/0518    
		getBuffer(currentBuffer, ¤tBufferPtr, &frameNo); 
1999/0424    
		// We need to receive the header now 
		hdrPos = 0; 
	} 
1999/0517/sys/src/9/pc/devlml.c:526,5321999/0518/sys/src/9/pc/devlml.c:527,533
1999/0424    
	if(pos >= currentBufferLength) { 
		// We have written the frame, time to display it 
		//print("Passing written buffer to 067\n"); 
		prepareBuffer(codeData, currentBuffer); 
1999/0518    
		prepareBuffer(currentBuffer); 
1999/0424    
		bufferPrepared = 1; 
	} 
	//print("return 0x%lx 0x%x 0x%x 0x%x\n",pos,count,hdrLeft+count,currentBufferLength); 
1999/0517/sys/src/9/pc/devlml.c:557,5701999/0518/sys/src/9/pc/devlml.c:558,568
1999/0422    
 
	// Get access to DMA memory buffer 
	memset(codeData, 0xAA, sizeof(CodeData)); 
	strncpy(codeData->idString, MJPG_VERSION, strlen(MJPG_VERSION)); 
                 
	for(i = 0; i < NBUF; i++) { 
1999/0517    
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
1999/0422    
		codeData->statComInitial[i] = codeData->statCom[i]; 
1999/0517    
		codeData->fragdesc[i].addr = PADDR(&(codeData->frag[i])); 
1999/0422    
		// Length is in double words, in position 1..20 
1999/0517    
		codeData->fragdesc[i].leng = (FRAGSIZE >> 1) | FRAGM_FINAL_B; 
1999/0518    
		codeData->fragdesc[i].leng = ((sizeof codeData->frag[i]) >> 1) | FRAGM_FINAL_B; 
1999/0422    
	} 
 
	print("initializing LML33 board..."); 
1999/0517/sys/src/9/pc/devlml.c:592,5981999/0518/sys/src/9/pc/devlml.c:590,596
1999/0423    
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); 
1999/0422    
 
1999/0515    
	lmlmap.pci = pciBaseAddr; 
	lmlmap.dma = PADDR(codeData); 
1999/0518    
	lmlmap.statcom = PADDR(codeData->statCom); 
1999/0515    
	lmlmap.codedata = (ulong)codeData; 
 
1999/0422    
	return;  
1999/0517/sys/src/9/pc/devlml.c:617,6251999/0518/sys/src/9/pc/devlml.c:615,621
1999/0422    
} 
 
static Chan* 
1999/0513    
lmlopen(Chan *c, int omode) 
1999/0422    
{ 
1999/0517    
	int i; 
1999/0518    
lmlopen(Chan *c, int omode) { 
1999/0517    
 
1999/0422    
	c->aux = 0; 
	switch(c->qid.path){ 
1999/0517/sys/src/9/pc/devlml.c:627,6321999/0518/sys/src/9/pc/devlml.c:623,629
1999/0422    
	case Q856: 
1999/0428    
	case Qreg: 
1999/0515    
	case Qmap: 
1999/0518    
	case Qbuf: 
1999/0422    
		break; 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0517/sys/src/9/pc/devlml.c:641,6531999/0518/sys/src/9/pc/devlml.c:638,644
1999/0424    
		bufferPrepared = 0; 
		hdrPos = -1; 
1999/0517    
 
		for (i = 0; i < 4; i++) { 
			codeData->statCom[i] = codeData->statComInitial[i]; 
			// Also memset the buffer with some fill value 
			memset(&(codeData->frag[i]),0x55,sizeof codeData->frag[i]); 
		} 
1999/0422    
		// allow one open total for these two 
1999/0517    
		intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); 
1999/0422    
		break; 
	} 
1999/0513    
	return devopen(c, omode, lmldir, nelem(lmldir), devgen); 
1999/0517/sys/src/9/pc/devlml.c:654,6661999/0518/sys/src/9/pc/devlml.c:645,658
1999/0422    
} 
 
static void 
1999/0513    
lmlclose(Chan *c) 
1999/0422    
{ 
1999/0518    
lmlclose(Chan *c) { 
 
1999/0422    
	switch(c->qid.path){ 
	case Q819: 
	case Q856: 
1999/0428    
	case Qreg: 
1999/0515    
	case Qmap: 
1999/0518    
	case Qbuf: 
1999/0515    
		authclose(c); 
		break; 
1999/0513    
	case Qjvideo: 
1999/0517/sys/src/9/pc/devlml.c:721,7271999/0518/sys/src/9/pc/devlml.c:713,719
1999/0515    
		} 
		return i; 
1999/0428    
	case Qreg: 
1999/0430    
		if (off < 0 || off + n > 0x400) 
1999/0518    
		if (off < 0 || off + n >= 0x400) 
1999/0424    
			return 0; 
1999/0428    
		switch(n) { 
		case 1: 
1999/0517/sys/src/9/pc/devlml.c:739,7441999/0518/sys/src/9/pc/devlml.c:731,755
1999/0428    
			return 0; 
1999/0424    
		} 
1999/0428    
		return n; 
1999/0518    
	case Qbuf: 
		if (off < 0 || off + n >= sizeof *codeData) 
			return 0; 
		switch(n) { 
		case 1: 
			*buf = readb((ulong)codeData + off); 
			break; 
		case 2: 
			if (off & (n-1)) return 0; 
			*(short *)buf = readw((ulong)codeData + off); 
			break; 
		case 4: 
			if (off & (n-1)) return 0; 
			*(long *)buf = readl((ulong)codeData + off); 
			break; 
		default: 
			return 0; 
		} 
		return n; 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0424    
		return vread(c, buf, n, off); 
1999/0517/sys/src/9/pc/devlml.c:781,7871999/0518/sys/src/9/pc/devlml.c:792,798
1999/0429    
		} 
		return 1; 
1999/0428    
	case Qreg: 
1999/0515    
		if (off < 0 || off + n > 0x400) 
1999/0518    
		if (off < 0 || off + n >= 0x400) 
1999/0424    
			return 0; 
1999/0428    
		switch (n) { 
		case 1: 
1999/0517/sys/src/9/pc/devlml.c:796,8011999/0518/sys/src/9/pc/devlml.c:807,833
1999/0515    
			if (off & 0x3) 
				return 0; 
1999/0424    
			writel(*(long *)buf, pciBaseAddr + off); 
1999/0518    
			break; 
		default: 
			return 0; 
		} 
		return n; 
	case Qbuf: 
		if (off < 0 || off + n >= sizeof *codeData) 
			return 0; 
		switch (n) { 
		case 1: 
			writeb(*buf, (ulong)codeData + off); 
			break; 
		case 2: 
			if (off & 0x1) 
				return 0; 
			writew(*(short *)buf, (ulong)codeData + off); 
			break; 
		case 4: 
			if (off & 0x3) 
				return 0; 
			writel(*(long *)buf, (ulong)codeData + off); 
1999/0428    
			break; 
		default: 
			return 0; 
1999/0518/sys/src/9/pc/devlml.c:11,171999/0519/sys/src/9/pc/devlml.c:11,17 (short | long)
1999/0515    
#define DBGREGS 0x1 
#define DBGREAD 0x2 
#define DBGWRIT 0x4 
1999/0517    
int debug = DBGREAD|DBGWRIT|DBGREGS; 
1999/0519    
int debug = DBGREAD|DBGWRIT; 
1999/0515    
 
1999/0422    
// Lml 22 driver 
 
1999/0519/sys/src/9/pc/devlml.c:8,181999/0520/sys/src/9/pc/devlml.c:8,26 (short | long)
1999/0422    
 
#include	"devlml.h" 
 
1999/0515    
#define DBGREGS 0x1 
#define DBGREAD 0x2 
#define DBGWRIT 0x4 
1999/0519    
int debug = DBGREAD|DBGWRIT; 
1999/0520    
static void *		pciPhysBaseAddr; 
static ulong		pciBaseAddr; 
static Pcidev *		pcidev; 
1999/0515    
 
1999/0520    
#define DBGREGS 0x01 
#define DBGREAD 0x02 
#define DBGWRIT 0x04 
#define DBG819	0x08 
#define DBGINTR	0x10 
#define DBGINTS	0x20 
 
int debug = DBGREAD; 
 
1999/0422    
// Lml 22 driver 
 
1999/0517    
struct { 
1999/0519/sys/src/9/pc/devlml.c:23,281999/0520/sys/src/9/pc/devlml.c:31,37
1999/0517    
 
1999/0422    
enum{ 
1999/0513    
	Qdir, 
1999/0520    
	Q060, 
1999/0422    
	Q819, 
	Q856, 
1999/0428    
	Qreg, 
1999/0519/sys/src/9/pc/devlml.c:34,391999/0520/sys/src/9/pc/devlml.c:43,49
1999/0422    
 
1999/0513    
static Dirtab lmldir[]={ 
//	 name,		 qid,		size,		mode 
1999/0520    
	"lml060",	{Q060},		0x400,		0644, 
1999/0513    
	"lml819",	{Q819},		0,		0644, 
	"lml856",	{Q856},		0,		0644, 
1999/0517    
	"lmlreg",	{Qreg},		0x400,		0644, 
1999/0519/sys/src/9/pc/devlml.c:45,501999/0520/sys/src/9/pc/devlml.c:55,67
1999/0422    
 
CodeData *	codeData; 
 
1999/0520    
typedef enum { 
	New, 
	Header, 
	Body, 
	Error, 
} State; 
 
1999/0513    
int		currentBuffer; 
int		currentBufferLength; 
1999/0424    
void *		currentBufferPtr; 
1999/0519/sys/src/9/pc/devlml.c:55,601999/0520/sys/src/9/pc/devlml.c:72,78
1999/0513    
int		hdrPos; 
int		nopens; 
1999/0429    
uchar		q856[3]; 
1999/0520    
State		state = New; 
1999/0424    
 
static FrameHeader frameHeader = { 
	MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, 
1999/0519/sys/src/9/pc/devlml.c:128,1531999/0520/sys/src/9/pc/devlml.c:146,169
1999/0422    
static void 
1999/0429    
i2c_waitscl(void) { 
1999/0423    
	int i; 
	ulong a; 
 
	for(i=0;;i++) { 
		a = readl(pciBaseAddr + ZR36057_I2C_BUS); 
		if (a & ZR36057_I2C_SCL) break; 
		if (i>I2C_TIMEOUT) error(Eio); 
	} 
1999/0520    
	for (i = 0; i < I2C_TIMEOUT; i++) 
		if (readl(pciBaseAddr + I2C_BUS) & I2C_SCL) 
			return; 
	error(Eio); 
1999/0423    
} 
 
static void 
1999/0429    
i2c_start(void) { 
1999/0423    
 
	writel(ZR36057_I2C_SCL|ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
	writel(I2C_SCL|I2C_SDA, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_waitscl(); 
	i2c_pause(); 
1999/0423    
 
	writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
	writel(I2C_SCL, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
 
	writel(0, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
	writel(0, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
} 
 
1999/0519/sys/src/9/pc/devlml.c:154,1881999/0520/sys/src/9/pc/devlml.c:170,204
1999/0423    
static void 
1999/0429    
i2c_stop(void) { 
1999/0423    
	// the clock should already be low, make sure data is 
	writel(0, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
	writel(0, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
 
	// set clock high and wait for device to catch up 
	writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
	writel(I2C_SCL, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_waitscl(); 
	i2c_pause(); 
1999/0423    
 
	// set the data high to indicate the stop bit 
	writel(ZR36057_I2C_SCL|ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
	writel(I2C_SCL|I2C_SDA, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
} 
 
1999/0429    
static void i2c_wrbit(int bit) { 
1999/0423    
	if (bit){ 
		writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); // set data 
1999/0520    
		writel(I2C_SDA, pciBaseAddr + I2C_BUS); // set data 
1999/0429    
		i2c_pause(); 
1999/0423    
		writel(ZR36057_I2C_SDA|ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
		writel(I2C_SDA|I2C_SCL, pciBaseAddr + I2C_BUS); 
1999/0429    
		i2c_waitscl(); 
		i2c_pause(); 
1999/0423    
		writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
		writel(I2C_SDA, pciBaseAddr + I2C_BUS); 
1999/0429    
		i2c_pause(); 
1999/0423    
	} else { 
		writel(0, pciBaseAddr + ZR36057_I2C_BUS); // clr data 
1999/0520    
		writel(0, pciBaseAddr + I2C_BUS); // clr data 
1999/0429    
		i2c_pause(); 
1999/0423    
		writel(ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
		writel(I2C_SCL, pciBaseAddr + I2C_BUS); 
1999/0429    
		i2c_waitscl(); 
		i2c_pause(); 
1999/0423    
		writel(0, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
		writel(0, pciBaseAddr + I2C_BUS); 
1999/0429    
		i2c_pause(); 
1999/0423    
	} 
} 
1999/0519/sys/src/9/pc/devlml.c:193,2091999/0520/sys/src/9/pc/devlml.c:209,225
1999/0423    
	// the clk line should be low 
 
	// ensure we are not asserting the data line 
	writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
	writel(I2C_SDA, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
 
	// set the clock high and wait for device to catch up 
	writel(ZR36057_I2C_SDA|ZR36057_I2C_SCL, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
	writel(I2C_SDA|I2C_SCL, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_waitscl(); 
	i2c_pause(); 
1999/0423    
 
	// the data line should be a valid bit 
	bit = readl(pciBaseAddr+ZR36057_I2C_BUS); 
	if (bit & ZR36057_I2C_SDA){ 
1999/0520    
	bit = readl(pciBaseAddr+I2C_BUS); 
	if (bit & I2C_SDA){ 
1999/0423    
		bit = 1; 
	} else { 
		bit = 0; 
1999/0519/sys/src/9/pc/devlml.c:210,2161999/0520/sys/src/9/pc/devlml.c:226,232
1999/0423    
	} 
 
	// set the clock low to indicate end of cycle 
	writel(ZR36057_I2C_SDA, pciBaseAddr + ZR36057_I2C_BUS); 
1999/0520    
	writel(I2C_SDA, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
 
	return bit; 
1999/0519/sys/src/9/pc/devlml.c:222,2281999/0520/sys/src/9/pc/devlml.c:238,244
1999/0423    
	uchar res; 
 
	res = 0; 
	for (i=0;i<8;i++){ 
1999/0520    
	for (i = 0; i < 8; i++) { 
1999/0423    
		res  = res << 1; 
1999/0429    
		res += i2c_rdbit(); 
1999/0423    
	} 
1999/0519/sys/src/9/pc/devlml.c:238,2441999/0520/sys/src/9/pc/devlml.c:254,260
1999/0429    
i2c_wrbyte(uchar v) { 
1999/0423    
	int i, ack; 
 
	for (i=0;i<8;i++){ 
1999/0520    
	for (i = 0; i < 8; i++) { 
1999/0429    
		i2c_wrbit(v & 0x80); 
1999/0423    
		v = v << 1; 
	} 
1999/0519/sys/src/9/pc/devlml.c:261,2671999/0520/sys/src/9/pc/devlml.c:277,283
1999/0429    
	ack = i2c_wrbyte(sub); 
1999/0423    
	if (ack == 1) error(Eio); 
 
	for(i=0;i<num;i+=1){ 
1999/0520    
	for (i = 0; i < num; i++) { 
1999/0429    
		ack = i2c_wrbyte(bytes[i]); 
1999/0423    
		if (ack == 1) error(Eio); 
	} 
1999/0519/sys/src/9/pc/devlml.c:328,3341999/0520/sys/src/9/pc/devlml.c:344,444
1999/0424    
	return 1; 
} 
 
1999/0520    
/* 
 * The following mapping applies for the guests in the LML33 
 * 
 * Guest        Device 
 *   0          zr36060 
 *              uses subaddress GADR[0..1] 
 *   1          zr36060 START# 
 *   2          - 
 *   3          zr36060 RESET# 
 *   4          - 
 *   5          - 
 *   6          - 
 *   7          - 
 */ 
 
// post_idle waits for the guest bus to become free 
1999/0423    
static int 
1999/0520    
post_idle(void) { 
	ulong a; 
	int timeout; 
 
	for (timeout = 0; timeout < GUEST_TIMEOUT; timeout++){ 
		a = readl(pciBaseAddr + POST_OFFICE); 
		if ((a & POST_PEND) == 0)  
			return a; 
	} 
	pprint("post_idle timeout\n"); 
	return -1; 
} 
 
// post_write writes a byte to a guest using postoffice mechanism 
int 
post_write(unsigned int guest, unsigned int reg, unsigned int v) { 
	int w; 
 
	// wait for postoffice not busy 
	post_idle(); 
 
	// Trim the values, just in case 
	guest &= 0x07; 
	reg   &= 0x07; 
	v     &= 0xFF; 
 
	// write postoffice operation 
	w = POST_DIR | (guest<<20) | (reg<<16) | v; 
	writel(w, pciBaseAddr + POST_OFFICE); 
 
	// wait for postoffice not busy 
	return post_idle() == -1; 
} 
 
// post_read reads a byte from a guest using postoffice mechanism 
int 
post_read(int guest, int reg) { 
	int w; 
 
	// wait for postoffice not busy 
	post_idle(); 
 
	// Trim the values, just in case 
	guest &= 0x07; 
	reg   &= 0x07; 
 
	// write postoffice operation 
	w = (guest<<20) + (reg<<16); 
	writel(w, pciBaseAddr + POST_OFFICE); 
 
	// wait for postoffice not busy, get result 
	w = post_idle(); 
 
	// decide if read went ok 
	if (w == -1) return -1; 
 
	return w & 0xFF; 
} 
 
static int 
zr060_write(int reg, int v) { 
   
	if (post_write(GID060, 1, (reg>>8) & 0x03) 
	 || post_write(GID060, 2, reg & 0xff) 
	 || post_write(GID060, 3, v)) 
		return -1; 
} 
 
static int 
zr060_read(int reg) { 
   
	if (post_write(GID060, 1, (reg>>8) & 0x03) 
	 || post_write(GID060, 2, reg    & 0xff)) 
		return -1; 
	return post_read(GID060, 3); 
} 
 
static int 
1999/0518    
prepareBuffer(int i) { 
	if (i >= 0 && i < NBUF && (codeData->statCom[i] & STAT_BIT)) { 
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
1999/0519/sys/src/9/pc/devlml.c:353,3621999/0520/sys/src/9/pc/devlml.c:463,471
1999/0423    
} 
 
1999/0424    
static int 
1999/0518    
getBuffer(int i, void** bufferPtr, int* frameNo) { 
1999/0520    
getBuffer(int i, int* frameNo) { 
1999/0518    
 
	if(codeData->statCom[i] & STAT_BIT) { 
		*bufferPtr = (void*)(&codeData->frag[i]); 
		*frameNo = codeData->statCom[i] >> 24; 
		return (codeData->statCom[i] & 0x00FFFFFF) >> 1; 
1999/0424    
	} else 
1999/0519/sys/src/9/pc/devlml.c:364,3691999/0520/sys/src/9/pc/devlml.c:473,554
1999/0424    
} 
1999/0423    
 
1999/0424    
static long 
1999/0520    
vread(Chan *, void *va, long nbytes, vlong) { 
	static int bufpos; 
	static char *bufptr; 
	static int curbuf; 
	static int fragsize; 
	static int frameno; 
	static int frameprev; 
	char *p; 
	long count = nbytes; 
	int i; 
	vlong thetime; 
 
	p = (char *)va; 
	while (count > 0) { 
		switch (state) { 
		case New: 
			while((curbuf = getProcessedBuffer()) == -1) 
				sleep(&sleeper, return0, 0); 
			fragsize = getBuffer(curbuf, &frameno); 
			if (debug & DBGREAD) 
				pprint("devlml: got read buf %d, fr %d, size %d\n", 
					curbuf, frameNo, fragsize); 
			if(frameno != (frameprev + 1) % 256) 
				pprint("Frames out of sequence: %d %d\n", 
					frameno, frameprev); 
			frameprev = frameno; 
			// Fill in APP marker fields here 
			thetime = todget(); 
			frameHeader.sec = (ulong)(thetime / 1000000000LL); 
			frameHeader.usec = (ulong)(thetime % 1000000000LL) / 1000; 
			frameHeader.frameSize = fragsize - 2 + sizeof(FrameHeader); 
			frameHeader.frameSeqNo++; 
			frameHeader.frameNo = frameno; 
			bufpos = 0; 
			state = Body; 
			bufptr = (char *)(&frameHeader); 
			// Fall through 
		case Header: 
			i = sizeof(FrameHeader) - bufpos; 
			if (count <= i) { 
				memmove(p, bufptr, count); 
				bufptr += count; 
				bufpos += count; 
				return nbytes; 
			} 
			memmove(p, bufptr, i); 
			count -= i; 
			p += i; 
			bufpos = 2; 
			bufptr = codeData->frag[curbuf].fb; 
			state = Body; 
			// Fall through 
		case Body: 
			i = fragsize - bufpos; 
			if (count <= i) { 
				memmove(p, bufptr, count); 
				bufptr += count; 
				bufpos += count; 
				return nbytes; 
			} 
			memmove(p, bufptr, i); 
			count -= i; 
			p += i; 
 
			// Allow reuse of current buffer 
			prepareBuffer(curbuf); 
			state = New; 
			break; 
		case Error: 
			return 0; 
		} 
	} 
} 
 
/* 
static long 
1999/0424    
vread(Chan *, void *va, long count, vlong pos) { 
	int prevFrame; 
	//  how much bytes left to transfer for the header 
1999/0519/sys/src/9/pc/devlml.c:404,4171999/0520/sys/src/9/pc/devlml.c:589,602
1999/0424    
			sleep(&sleeper, return0, 0); 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::wokeup\n"); 
1999/0518    
		currentBufferLength = getBuffer(currentBuffer, 
1999/0424    
			¤tBufferPtr, &frameNo); 
1999/0520    
		currentBufferLength = getBuffer(currentBuffer, &frameNo); 
		currentBufferPtr = (void*)(&codeData->frag[currentBuffer]); 
1999/0424    
 
		pos = 0; // ?????????????? 
 
		// print("getBufffer %d -> %d 0x%x %d\n",currentBuffer, currentBufferLength, currentBufferPtr, frameNo); 
1999/0520    
		// pprint("getBufffer %d -> %d 0x%x %d\n",currentBuffer, currentBufferLength, currentBufferPtr, frameNo); 
1999/0424    
		if(frameNo != (prevFrame + 1) % 256) 
			print("Frames out of sequence: %d %d\n", prevFrame, frameNo); 
1999/0520    
			pprint("Frames out of sequence: %d %d\n", prevFrame, frameNo); 
1999/0424    
		// Fill in APP marker fields here 
		thetime = todget(); 
		frameHeader.sec = (ulong)(thetime / 1000000000LL); 
1999/0519/sys/src/9/pc/devlml.c:447,5381999/0520/sys/src/9/pc/devlml.c:632,723
1999/0515    
	//pr_debug&DBGREGS("return %d %d\n",cpcount,retcount); 
1999/0424    
	return retcount; 
1999/0423    
} 
1999/0520    
*/ 
1999/0423    
 
1999/0424    
static long 
vwrite(Chan *, void *va, long count, vlong pos) { 
	//  how much bytes left to transfer for the header 
	int hdrLeft; 
	char *buf = va; 
1999/0520    
vwrite(Chan *, void *va, long nbytes, vlong) { 
	static int bufpos; 
	static char *bufptr; 
	static int curbuf; 
	static int fragsize; 
	char *p; 
	long count = nbytes; 
	int i; 
1999/0424    
 
	//print("devlml::vwrite() count=0x%x pos=0x%x\n", count, pos); 
                 
	// We just started writing, not into the header copy 
	if(pos==0 && hdrPos == -1) { 
		 currentBuffer=-1; 
		 currentBufferLength=0; 
		 frameNo=-1; 
		 bufferPrepared = 0; 
	} 
                 
	// We need next buffer to fill (either because we're done with the 
	// current buffer) of because we're just beginning (but not into the header) 
	if (hdrPos == -1 && pos >= currentBufferLength) { 
1999/0518    
		while((currentBuffer = getProcessedBuffer()) == -1) 
1999/0424    
			sleep(&sleeper, return0, 0); 
		// print("current buffer %d\n",currentBuffer); 
                 
1999/0518    
		getBuffer(currentBuffer, ¤tBufferPtr, &frameNo); 
1999/0424    
		// We need to receive the header now 
		hdrPos = 0; 
	} 
	                 
	// We're into the header processing  
	if (hdrPos != -1) { 
		// Calculate how many bytes we need to receive to fill the header 
		hdrLeft = sizeof(FrameHeader) - hdrPos; 
	                 
		// If we complete or go over the header with this count 
		if (count >= hdrLeft) { 
			// Adjust count of bytes that remain to be copied into video buffer 
			count = count - hdrLeft;  
			memmove((char*)&frameHeader + hdrPos, buf, hdrLeft); 
			// Make sure we have a standard LML33 header 
			if (frameHeader.mrkSOI == MRK_SOI 
1999/0430    
			 && frameHeader.mrkAPP3 == MRK_APP3 
			 && strcmp(frameHeader.nm, APP_NAME) == 0) { 
1999/0424    
				//print("Starting new buffer len=0x%x frame=%d\n", frameHeader.frameSize, frameHeader.frameSeqNo); 
				// Obtain values we need for playback process from the header 
				currentBufferLength = frameHeader.frameSize; 
			} else if (singleFrame) { 
				currentBufferLength = FRAGSIZE; 
			} else { 
				// We MUST have header for motion video decompression 
				print("No frame size (APP3 marker) in MJPEG file\n"); 
				error(Eio); 
1999/0520    
	p = (char *)va; 
	while (count > 0) { 
		switch (state) { 
		case New: 
			while((curbuf = getProcessedBuffer()) == -1) { 
				if (debug&DBGWRIT) 
					pprint("devlml::sleep\n"); 
				sleep(&sleeper, return0, 0); 
1999/0424    
			} 
			// Finish header processing 
			hdrPos = -1; 
			// Copy the header into the playback buffer 
			memmove(currentBufferPtr, (char*)&frameHeader, sizeof(FrameHeader)); 
			// And set position just behind header for playback buffer write 
			pos = sizeof(FrameHeader); 
		} else { 
			memmove((char*)&frameHeader + hdrPos, buf, count); 
			hdrPos += count; 
			return count; 
1999/0520    
			if (debug&DBGWRIT) 
				pprint("current buffer %d\n", curbuf); 
			bufptr = codeData->frag[curbuf].fb; 
			bufpos = 0; 
			state = Header; 
			// Fall through 
		case Header: 
			if (count < sizeof(FrameHeader) - bufpos) { 
				memmove(bufptr, p, count); 
				bufptr += count; 
				bufpos += count; 
				return nbytes; 
			} 
			// Fill remainder of header 
			i = sizeof(FrameHeader) - bufpos; 
			memmove(bufptr, p, i); 
			bufptr += i; 
			bufpos += i; 
			p += i; 
			count -= i; 
			// verify header 
			if (codeData->frag[curbuf].fh.mrkSOI != MRK_SOI 
			 || codeData->frag[curbuf].fh.mrkAPP3 != MRK_APP3 
			 || strcmp(codeData->frag[curbuf].fh.nm, APP_NAME)) { 
				// Header is bad 
				pprint("devlml: header error: 0x%.4ux, 0x%.4ux, `%.4s'\n", 
					codeData->frag[curbuf].fh.mrkSOI, 
					codeData->frag[curbuf].fh.mrkAPP3, 
					codeData->frag[curbuf].fh.nm); 
				state = Error; 
				return p - (char *)va; 
			} 
			fragsize = codeData->frag[curbuf].fh.frameSize; 
			if (fragsize <= sizeof(FrameHeader) 
			 || fragsize  > sizeof(Fragment)) { 
				pprint("devlml: frame size error: 0x%.8ux\n", 
					fragsize); 
				state = Error; 
				return p - (char *)va; 
			} 
			state = Body; 
			// Fall through 
		case Body: 
			if (count < fragsize - bufpos) { 
				memmove(bufptr, p, count); 
				bufptr += count; 
				bufpos += count; 
				return nbytes; 
			} 
			i = fragsize - bufpos; 
			memmove(bufptr, p, i); 
			bufptr += i; 
			bufpos += i; 
			p += i; 
			count -= i; 
			// We have written the frame, time to display it 
			i = prepareBuffer(curbuf); 
			if (debug&DBGWRIT) 
				pprint("Sending buffer %d: %d\n", curbuf, i); 
			state = New; 
			break; 
		case Error: 
			return 0; 
1999/0424    
		} 
	} else 
		hdrLeft = 0; 
                 
	if(count + pos > currentBufferLength) { 
		count = currentBufferLength - pos; 
	} 
                 
	memmove((char *)currentBufferPtr + pos, buf + hdrLeft, count); 
                 
	pos += count; 
	// print("return 0x%x 0x%x\n",pos,count); 
                 
	// Now is the right moment to initiate playback of the frame (if it's full) 
	if(pos >= currentBufferLength) { 
		// We have written the frame, time to display it 
		//print("Passing written buffer to 067\n"); 
1999/0518    
		prepareBuffer(currentBuffer); 
1999/0424    
		bufferPrepared = 1; 
	} 
	//print("return 0x%lx 0x%x 0x%x 0x%x\n",pos,count,hdrLeft+count,currentBufferLength); 
                 
	return hdrLeft + count; 
} 
 
1999/0423    
static void lmlintr(Ureg *, void *); 
1999/0519/sys/src/9/pc/devlml.c:558,5641999/0520/sys/src/9/pc/devlml.c:743,749
1999/0422    
 
	// Get access to DMA memory buffer 
	memset(codeData, 0xAA, sizeof(CodeData)); 
	for(i = 0; i < NBUF; i++) { 
1999/0520    
	for (i = 0; i < NBUF; i++) { 
1999/0517    
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
		codeData->fragdesc[i].addr = PADDR(&(codeData->frag[i])); 
1999/0422    
		// Length is in double words, in position 1..20 
1999/0519/sys/src/9/pc/devlml.c:619,6241999/0520/sys/src/9/pc/devlml.c:804,810
1999/0517    
 
1999/0422    
	c->aux = 0; 
	switch(c->qid.path){ 
1999/0520    
	case Q060: 
1999/0422    
	case Q819: 
	case Q856: 
1999/0428    
	case Qreg: 
1999/0519/sys/src/9/pc/devlml.c:637,6421999/0520/sys/src/9/pc/devlml.c:823,829
1999/0424    
		frameNo = 0; 
		bufferPrepared = 0; 
		hdrPos = -1; 
1999/0520    
		state = New; 
1999/0517    
 
1999/0422    
		// allow one open total for these two 
		break; 
1999/0519/sys/src/9/pc/devlml.c:648,6531999/0520/sys/src/9/pc/devlml.c:835,841
1999/0518    
lmlclose(Chan *c) { 
 
1999/0422    
	switch(c->qid.path){ 
1999/0520    
	case Q060: 
1999/0422    
	case Q819: 
	case Q856: 
1999/0428    
	case Qreg: 
1999/0519/sys/src/9/pc/devlml.c:673,6781999/0520/sys/src/9/pc/devlml.c:861,874
1999/0513    
	case Qdir: 
		return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen); 
 
1999/0520    
	case Q060: 
		if (off < 0 || off + n > 0x400) 
			return 0; 
		for (i = 0; i < n; i++) { 
			if ((d = zr060_read(off + i)) < 0) break; 
			*buf++ = d; 
		} 
		return i; 
1999/0422    
	case Q819: 
1999/0424    
		if (off < 0 || off + n > 0x20) 
1999/0423    
			return 0; 
1999/0519/sys/src/9/pc/devlml.c:767,7771999/0520/sys/src/9/pc/devlml.c:963,980
1999/0513    
	case Qdir: 
		error(Eperm); 
 
1999/0520    
	case Q060: 
		if (off < 0 || off + n > 0x400) 
			return 0; 
		for (i = 0; i < n; i++) { 
			if (zr060_write(off + i, *buf++) < 0) break; 
		} 
		return i; 
1999/0423    
	case Q819: 
1999/0517    
		if (off < 0 || off + n >= 0x20) 
1999/0423    
			return 0; 
1999/0424    
		for (i = n; i > 0; i--) 
1999/0429    
			if (i2c_wr8(BT819Addr, off++, *buf++) == 0) 
1999/0520    
		for (i = 0; i < n; i++) 
			if (i2c_wr8(BT819Addr, off + i, *buf++) == 0) 
1999/0424    
				break; 
1999/0515    
		return i; 
1999/0423    
	case Q856: 
1999/0519/sys/src/9/pc/devlml.c:862,8771999/0520/sys/src/9/pc/devlml.c:1065,1081
1999/0422    
 
static void 
1999/0424    
lmlintr(Ureg *, void *) { 
	ulong flags = readl(pciBaseAddr+ZR36057_INTR_STAT); 
1999/0520    
	static count; 
	ulong flags = readl(pciBaseAddr+INTR_STAT); 
1999/0424    
	 
1999/0515    
	if(debug&(DBGREAD|DBGWRIT)) 
1999/0520    
	if(debug&(DBGINTR)) 
1999/0515    
		print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags); 
1999/0422    
 
1999/0424    
	// Reset all interrupts from 067 
	writel(0xff000000, pciBaseAddr + ZR36057_INTR_STAT); 
1999/0520    
	writel(0xff000000, pciBaseAddr + INTR_STAT); 
1999/0423    
 
1999/0515    
	if(flags & ZR36057_INTR_JPEGREP) { 
		if(debug&(DBGREAD|DBGWRIT)) 
1999/0520    
	if(flags & INTR_JPEGREP) { 
		if ((debug&DBGINTR) || ((debug&DBGINTS) && (count++ % 128) == 0)) 
1999/0515    
			print("MjpgDrv_intrHandler wakeup\n"); 
		wakeup(&sleeper); 
	} 
1999/0520/sys/src/9/pc/devlml.c:19,251999/0521/sys/src/9/pc/devlml.c:19,25 (short | long)
1999/0520    
#define DBGINTR	0x10 
#define DBGINTS	0x20 
 
int debug = DBGREAD; 
1999/0521    
int debug = 0; 
1999/0520    
 
1999/0422    
// Lml 22 driver 
 
1999/0520/sys/src/9/pc/devlml.c:62,751999/0521/sys/src/9/pc/devlml.c:62,70
1999/0520    
	Error, 
} State; 
 
1999/0513    
int		currentBuffer; 
int		currentBufferLength; 
1999/0424    
void *		currentBufferPtr; 
1999/0513    
int		frameNo; 
1999/0424    
Rendez		sleeper; 
1999/0513    
int		singleFrame; 
int		bufferPrepared; 
int		hdrPos; 
int		nopens; 
1999/0429    
uchar		q856[3]; 
1999/0520    
State		state = New; 
1999/0520/sys/src/9/pc/devlml.c:489,5041999/0521/sys/src/9/pc/devlml.c:484,505
1999/0520    
	while (count > 0) { 
		switch (state) { 
		case New: 
			while((curbuf = getProcessedBuffer()) == -1) 
1999/0521    
			while ((curbuf = getProcessedBuffer()) == -1) 
1999/0520    
				sleep(&sleeper, return0, 0); 
			fragsize = getBuffer(curbuf, &frameno); 
			if (debug & DBGREAD) 
				pprint("devlml: got read buf %d, fr %d, size %d\n", 
					curbuf, frameNo, fragsize); 
			if(frameno != (frameprev + 1) % 256) 
				pprint("Frames out of sequence: %d %d\n", 
					frameno, frameprev); 
1999/0521    
			if (frameno != (frameprev + 1) % 256) 
				pprint("Frame out of sequence: %d %d\n", 
					frameprev, frameno); 
1999/0520    
			frameprev = frameno; 
1999/0521    
			if (fragsize <= 0 || fragsize > sizeof(Fragment)) { 
				pprint("Wrong sized fragment, %d (ignored)\n", 
					fragsize); 
				prepareBuffer(curbuf); 
				break; 
			} 
1999/0520    
			// Fill in APP marker fields here 
			thetime = todget(); 
			frameHeader.sec = (ulong)(thetime / 1000000000LL); 
1999/0520/sys/src/9/pc/devlml.c:507,5131999/0521/sys/src/9/pc/devlml.c:508,514
1999/0520    
			frameHeader.frameSeqNo++; 
			frameHeader.frameNo = frameno; 
			bufpos = 0; 
			state = Body; 
1999/0521    
			state = Header; 
1999/0520    
			bufptr = (char *)(&frameHeader); 
			// Fall through 
		case Header: 
1999/0520/sys/src/9/pc/devlml.c:522,5331999/0521/sys/src/9/pc/devlml.c:523,534
1999/0520    
			count -= i; 
			p += i; 
			bufpos = 2; 
			bufptr = codeData->frag[curbuf].fb; 
1999/0521    
			bufptr = codeData->frag[curbuf].fb + 2; 
1999/0520    
			state = Body; 
			// Fall through 
		case Body: 
			i = fragsize - bufpos; 
			if (count <= i) { 
1999/0521    
			if (count < i) { 
1999/0520    
				memmove(p, bufptr, count); 
				bufptr += count; 
				bufpos += count; 
1999/0520/sys/src/9/pc/devlml.c:540,5451999/0521/sys/src/9/pc/devlml.c:541,550
1999/0520    
			// Allow reuse of current buffer 
			prepareBuffer(curbuf); 
			state = New; 
1999/0521    
			if (singleFrame) { 
				state = Error; 
				return nbytes - count; 
			} 
1999/0520    
			break; 
		case Error: 
			return 0; 
1999/0520/sys/src/9/pc/devlml.c:547,6401999/0521/sys/src/9/pc/devlml.c:552,558
1999/0520    
	} 
} 
 
/* 
static long 
1999/0424    
vread(Chan *, void *va, long count, vlong pos) { 
	int prevFrame; 
	//  how much bytes left to transfer for the header 
	int hdrLeft; 
	// Count of bytes that we need to copy into buf from code-buffer 
	// (different from count only while in header reading mode) 
	int cpcount = count; 
	// Count of bytes that we copied into buf altogether and will return 
	int retcount=0; 
	vlong thetime; 
	uchar *buf = va; 
                 
1999/0515    
	if(debug&DBGREAD) 
		pprint("devlml::vread() count=%ld pos=%lld\n", count, pos); 
1999/0424    
                 
	// If we just begin reading a file, pos would never be 0 otherwise 
	if (pos == 0 && hdrPos == -1) { 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::first read\n"); 
1999/0424    
		 currentBuffer = -1; 
		 currentBufferLength = 0; 
		 frameNo = -1; 
1999/0423    
	} 
1999/0424    
	prevFrame = frameNo; 
                 
	// We get to the end of the current buffer, also covers just 
	// open file, since 0 >= -1 
	if(hdrPos == -1 && pos >= currentBufferLength) { 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::prepareBuffer\n"); 
1999/0518    
		prepareBuffer(currentBuffer); 
1999/0424    
		// if not the first buffer read and single frame mode - return EOF 
		if (currentBuffer != -1 && singleFrame) 
			return 0; 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::sleep\n"); 
1999/0518    
		while((currentBuffer = getProcessedBuffer()) == -1) 
1999/0424    
			sleep(&sleeper, return0, 0); 
1999/0515    
		if(debug&DBGREAD) 
			pprint("devlml::wokeup\n"); 
1999/0520    
		currentBufferLength = getBuffer(currentBuffer, &frameNo); 
		currentBufferPtr = (void*)(&codeData->frag[currentBuffer]); 
1999/0424    
                 
		pos = 0; // ?????????????? 
                 
1999/0520    
		// pprint("getBufffer %d -> %d 0x%x %d\n",currentBuffer, currentBufferLength, currentBufferPtr, frameNo); 
1999/0424    
		if(frameNo != (prevFrame + 1) % 256) 
1999/0520    
			pprint("Frames out of sequence: %d %d\n", prevFrame, frameNo); 
1999/0424    
		// Fill in APP marker fields here 
		thetime = todget(); 
		frameHeader.sec = (ulong)(thetime / 1000000000LL); 
		frameHeader.usec = (ulong)(thetime % 1000000000LL) / 1000; 
		frameHeader.frameSize = currentBufferLength - 2 + sizeof(FrameHeader); 
		frameHeader.frameSeqNo++; 
		frameHeader.frameNo = frameNo; 
		hdrPos=0; 
	} 
                 
	if (hdrPos != -1) { 
		hdrLeft = sizeof(FrameHeader) - hdrPos; 
		// Write the frame size here 
		if (count >= hdrLeft) { 
			memmove(buf, (char*)&frameHeader + hdrPos, hdrLeft); 
			retcount += hdrLeft; 
			cpcount = count - hdrLeft; 
			pos = sizeof(frameHeader.mrkSOI); 
			hdrPos = -1; 
		} else { 
			memmove(buf, (char*)&frameHeader + hdrPos, count); 
			hdrPos += count; 
			return count; 
		} 
	} 
                 
	if(cpcount + pos > currentBufferLength) 
		cpcount = currentBufferLength - pos; 
                 
	memmove(buf + retcount, (char *)currentBufferPtr + pos, cpcount); 
	retcount += cpcount; 
                 
1999/0515    
	//pr_debug&DBGREGS("return %d %d\n",cpcount,retcount); 
1999/0424    
	return retcount; 
1999/0423    
} 
1999/0520    
*/ 
1999/0423    
                 
1999/0424    
static long 
1999/0520    
vwrite(Chan *, void *va, long nbytes, vlong) { 
	static int bufpos; 
	static char *bufptr; 
1999/0520/sys/src/9/pc/devlml.c:683,6891999/0521/sys/src/9/pc/devlml.c:601,607
1999/0520    
					codeData->frag[curbuf].fh.mrkAPP3, 
					codeData->frag[curbuf].fh.nm); 
				state = Error; 
				return p - (char *)va; 
1999/0521    
				return nbytes - count; 
1999/0520    
			} 
			fragsize = codeData->frag[curbuf].fh.frameSize; 
			if (fragsize <= sizeof(FrameHeader) 
1999/0520/sys/src/9/pc/devlml.c:691,7081999/0521/sys/src/9/pc/devlml.c:609,626
1999/0520    
				pprint("devlml: frame size error: 0x%.8ux\n", 
					fragsize); 
				state = Error; 
				return p - (char *)va; 
1999/0521    
				return nbytes - count; 
1999/0520    
			} 
			state = Body; 
			// Fall through 
		case Body: 
			if (count < fragsize - bufpos) { 
1999/0521    
			i = fragsize - bufpos; 
			if (count < i) { 
1999/0520    
				memmove(bufptr, p, count); 
				bufptr += count; 
				bufpos += count; 
				return nbytes; 
			} 
			i = fragsize - bufpos; 
			memmove(bufptr, p, i); 
			bufptr += i; 
			bufpos += i; 
1999/0520/sys/src/9/pc/devlml.c:712,7171999/0521/sys/src/9/pc/devlml.c:630,639
1999/0520    
			i = prepareBuffer(curbuf); 
			if (debug&DBGWRIT) 
				pprint("Sending buffer %d: %d\n", curbuf, i); 
1999/0521    
			if (singleFrame) { 
				state = Error; 
				return nbytes - count; 
			} 
1999/0520    
			state = New; 
			break; 
		case Error: 
1999/0520/sys/src/9/pc/devlml.c:801,8061999/0521/sys/src/9/pc/devlml.c:723,729
1999/0422    
 
static Chan* 
1999/0518    
lmlopen(Chan *c, int omode) { 
1999/0521    
	int i; 
1999/0517    
 
1999/0422    
	c->aux = 0; 
	switch(c->qid.path){ 
1999/0520/sys/src/9/pc/devlml.c:811,8291999/0521/sys/src/9/pc/devlml.c:734,748
1999/0515    
	case Qmap: 
1999/0518    
	case Qbuf: 
1999/0422    
		break; 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0521    
	case Qjvideo: 
1999/0424    
		if (nopens) 
			error(Einuse); 
		nopens = 1; 
		singleFrame = (c->qid.path == Qjframe) ? 1 : 0;; 
		currentBuffer = 0; 
		currentBufferLength = 0; 
		currentBufferPtr = 0; 
		frameNo = 0; 
		bufferPrepared = 0; 
		hdrPos = -1; 
1999/0520    
		state = New; 
1999/0521    
		for (i = 0; i < NBUF; i++) 
			codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
1999/0517    
 
1999/0422    
		// allow one open total for these two 
		break; 
1999/0521/sys/src/9/pc/devlml.c:647,6521999/0522/sys/src/9/pc/devlml.c:647,656 (short | long)
1999/0423    
static void 
1999/0513    
lmlreset(void) 
1999/0422    
{ 
1999/0522    
// LMLSEG 
	Physseg segbuf; 
	Physseg segreg; 
// 
1999/0422    
	ulong regpa; 
	int i; 
 
1999/0521/sys/src/9/pc/devlml.c:699,7041999/0522/sys/src/9/pc/devlml.c:703,726
1999/0515    
	lmlmap.pci = pciBaseAddr; 
1999/0518    
	lmlmap.statcom = PADDR(codeData->statCom); 
1999/0515    
	lmlmap.codedata = (ulong)codeData; 
1999/0522    
 
// LMLSEG 
	memset(&segbuf, 0, sizeof(segbuf)); 
	segbuf.attr = SG_PHYSICAL; 
	segbuf.name = smalloc(NAMELEN); 
	snprint(segbuf.name, NAMELEN, "lmlmjpg"); 
	segbuf.pa = PADDR(codeData); 
	segbuf.size = sizeof(CodeData); 
	addphysseg(&segbuf); 
 
	memset(&segreg, 0, sizeof(segreg)); 
	segreg.attr = SG_PHYSICAL; 
	segreg.name = smalloc(NAMELEN); 
	snprint(segreg.name, NAMELEN, "lmlregs"); 
	segreg.pa = (ulong)regpa; 
	segreg.size = pcidev->mem[0].size; 
	addphysseg(&segreg); 
// 
1999/0515    
 
1999/0422    
	return;  
} 
1999/0522/sys/src/9/pc/devlml.c:23,361999/0525/sys/src/9/pc/devlml.c:23,39 (short | long)
1999/0520    
 
1999/0422    
// Lml 22 driver 
 
1999/0525    
#ifdef MEMMAP 
1999/0517    
struct { 
	ulong pci; 
1999/0518    
	ulong statcom; 
1999/0517    
	ulong codedata; 
} lmlmap; 
1999/0525    
#endif 
1999/0517    
 
1999/0422    
enum{ 
1999/0513    
	Qdir, 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	Q060, 
1999/0422    
	Q819, 
	Q856, 
1999/0522/sys/src/9/pc/devlml.c:37,421999/0525/sys/src/9/pc/devlml.c:40,46
1999/0428    
	Qreg, 
1999/0515    
	Qmap, 
1999/0518    
	Qbuf, 
1999/0525    
#endif 
1999/0513    
	Qjvideo, 
1999/0422    
	Qjframe, 
}; 
1999/0522/sys/src/9/pc/devlml.c:43,481999/0525/sys/src/9/pc/devlml.c:47,53
1999/0422    
 
1999/0513    
static Dirtab lmldir[]={ 
//	 name,		 qid,		size,		mode 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	"lml060",	{Q060},		0x400,		0644, 
1999/0513    
	"lml819",	{Q819},		0,		0644, 
	"lml856",	{Q856},		0,		0644, 
1999/0522/sys/src/9/pc/devlml.c:49,541999/0525/sys/src/9/pc/devlml.c:54,60
1999/0517    
	"lmlreg",	{Qreg},		0x400,		0644, 
	"lmlmap",	{Qmap},		sizeof lmlmap,	0444, 
1999/0518    
	"lmlbuf",	{Qbuf},		0,		0644, 
1999/0525    
#endif 
1999/0513    
	"jvideo",	{Qjvideo},	0,		0666, 
1999/0422    
	"jframe",	{Qjframe},	0,		0666, 
}; 
1999/0522/sys/src/9/pc/devlml.c:75,801999/0525/sys/src/9/pc/devlml.c:81,91
1999/0424    
	-1, 0, 0, 0, 0 
}; 
 
1999/0525    
 
#ifndef MEMMAP 
#define writel(v, a) *(ulong *)(a) = (v) 
#define readl(a) *(ulong*)(a) 
#else 
1999/0515    
ulong 
writel(ulong v, ulong a) { 
	if (debug&DBGREGS) 
1999/0522/sys/src/9/pc/devlml.c:83,881999/0525/sys/src/9/pc/devlml.c:94,109
1999/0515    
	return *(ulong *)a = v; 
} 
 
1999/0525    
ulong 
readl(ulong a) { 
	ulong v; 
 
	v = *(ulong*)a; 
	if (debug&DBGREGS) 
		pprint("%.8lux (%.8lux) --> %.8lux\n", 
			a, (ulong)a-pciBaseAddr, v); 
	return v; 
} 
1999/0515    
ushort 
writew(ushort v, ulong a) { 
	if (debug&DBGREGS) 
1999/0522/sys/src/9/pc/devlml.c:99,1151999/0525/sys/src/9/pc/devlml.c:120,125
1999/0515    
	return *(uchar *)a = v; 
} 
 
ulong 
readl(ulong a) { 
	ulong v; 
                 
	v = *(ulong*)a; 
	if (debug&DBGREGS) 
1999/0517    
		pprint("%.8lux (%.8lux) --> %.8lux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return v; 
} 
                 
ushort 
readw(ulong a) { 
	ushort v; 
1999/0522/sys/src/9/pc/devlml.c:432,4371999/0525/sys/src/9/pc/devlml.c:442,448
1999/0520    
		return -1; 
	return post_read(GID060, 3); 
} 
1999/0525    
#endif 
1999/0520    
 
static int 
1999/0518    
prepareBuffer(int i) { 
1999/0522/sys/src/9/pc/devlml.c:652,6571999/0525/sys/src/9/pc/devlml.c:663,669
1999/0522    
	Physseg segreg; 
// 
1999/0422    
	ulong regpa; 
1999/0525    
	ulong cdsize; 
1999/0422    
	int i; 
 
1999/0423    
	pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067); 
1999/0522/sys/src/9/pc/devlml.c:658,6741999/0525/sys/src/9/pc/devlml.c:670,688
1999/0423    
	if (pcidev == nil) { 
		return; 
	} 
1999/0422    
	codeData = (CodeData*)xspanalloc(sizeof(CodeData), BY2PG, 0); 
1999/0525    
	cdsize = (sizeof(CodeData) + BY2PG - 1) & ~(BY2PG - 1); 
	codeData = (CodeData*)xspanalloc(cdsize, BY2PG, 0); 
1999/0422    
	if (codeData == nil) { 
		print("devlml: xspanalloc(%ux, %ux, 0)\n", sizeof(CodeData), BY2PG); 
1999/0525    
		print("devlml: xspanalloc(%lux, %ux, 0)\n", cdsize, BY2PG); 
1999/0422    
		return; 
	} 
 
	print("Installing Motion JPEG driver %s\n", MJPG_VERSION);  
1999/0513    
	print("Buffer at 0x%.8lux, size 0x%.8ux\n", codeData, sizeof(CodeData));  
1999/0525    
	print("Buffer at 0x%.8lux, size 0x%.8lux\n", codeData, cdsize);  
1999/0422    
 
	// Get access to DMA memory buffer 
	memset(codeData, 0xAA, sizeof(CodeData)); 
1999/0525    
	codeData->physaddr = PADDR(&(codeData->statCom[0])); 
1999/0520    
	for (i = 0; i < NBUF; i++) { 
1999/0517    
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
		codeData->fragdesc[i].addr = PADDR(&(codeData->frag[i])); 
1999/0522/sys/src/9/pc/devlml.c:700,7081999/0525/sys/src/9/pc/devlml.c:714,724
1999/0422    
	// Interrupt handler 
1999/0423    
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); 
1999/0422    
 
1999/0525    
#ifdef MEMMAP 
1999/0515    
	lmlmap.pci = pciBaseAddr; 
1999/0518    
	lmlmap.statcom = PADDR(codeData->statCom); 
1999/0515    
	lmlmap.codedata = (ulong)codeData; 
1999/0525    
#endif 
1999/0522    
 
// LMLSEG 
	memset(&segbuf, 0, sizeof(segbuf)); 
1999/0522/sys/src/9/pc/devlml.c:710,7171999/0525/sys/src/9/pc/devlml.c:726,736
1999/0522    
	segbuf.name = smalloc(NAMELEN); 
	snprint(segbuf.name, NAMELEN, "lmlmjpg"); 
	segbuf.pa = PADDR(codeData); 
	segbuf.size = sizeof(CodeData); 
	addphysseg(&segbuf); 
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; 
1999/0522/sys/src/9/pc/devlml.c:719,7251999/0525/sys/src/9/pc/devlml.c:738,747
1999/0522    
	snprint(segreg.name, NAMELEN, "lmlregs"); 
	segreg.pa = (ulong)regpa; 
	segreg.size = pcidev->mem[0].size; 
	addphysseg(&segreg); 
1999/0525    
	if (addphysseg(&segreg) == -1) { 
		print("lml: physsegment: lmlmjpg\n"); 
		return; 
	} 
1999/0522    
// 
1999/0515    
 
1999/0422    
	return;  
1999/0522/sys/src/9/pc/devlml.c:749,7541999/0525/sys/src/9/pc/devlml.c:771,777
1999/0517    
 
1999/0422    
	c->aux = 0; 
	switch(c->qid.path){ 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	case Q060: 
1999/0422    
	case Q819: 
	case Q856: 
1999/0522/sys/src/9/pc/devlml.c:756,7611999/0525/sys/src/9/pc/devlml.c:779,785
1999/0515    
	case Qmap: 
1999/0518    
	case Qbuf: 
1999/0422    
		break; 
1999/0525    
#endif 
1999/0422    
	case Qjframe: 
1999/0521    
	case Qjvideo: 
1999/0424    
		if (nopens) 
1999/0522/sys/src/9/pc/devlml.c:776,7811999/0525/sys/src/9/pc/devlml.c:800,806
1999/0518    
lmlclose(Chan *c) { 
 
1999/0422    
	switch(c->qid.path){ 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	case Q060: 
1999/0422    
	case Q819: 
	case Q856: 
1999/0522/sys/src/9/pc/devlml.c:784,7891999/0525/sys/src/9/pc/devlml.c:809,815
1999/0518    
	case Qbuf: 
1999/0515    
		authclose(c); 
		break; 
1999/0525    
#endif 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0515    
		nopens = 0; 
1999/0522/sys/src/9/pc/devlml.c:793,7991999/0525/sys/src/9/pc/devlml.c:819,827
1999/0422    
 
static long 
1999/0513    
lmlread(Chan *c, void *va, long n, vlong voff) { 
1999/0525    
#ifdef MEMMAP 
1999/0424    
	int i, d; 
1999/0525    
#endif 
1999/0424    
	uchar *buf = va; 
1999/0513    
	long off = voff; 
1999/0423    
 
1999/0522/sys/src/9/pc/devlml.c:802,8071999/0525/sys/src/9/pc/devlml.c:830,836
1999/0513    
	case Qdir: 
		return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen); 
 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	case Q060: 
		if (off < 0 || off + n > 0x400) 
			return 0; 
1999/0522/sys/src/9/pc/devlml.c:887,8921999/0525/sys/src/9/pc/devlml.c:916,922
1999/0518    
			return 0; 
		} 
		return n; 
1999/0525    
#endif 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0424    
		return vread(c, buf, n, off); 
1999/0522/sys/src/9/pc/devlml.c:895,9011999/0525/sys/src/9/pc/devlml.c:925,933
1999/0422    
 
static long 
1999/0514    
lmlwrite(Chan *c, void *va, long n, vlong voff) { 
1999/0525    
#ifdef MEMMAP 
1999/0424    
	int i; 
1999/0525    
#endif 
1999/0424    
	uchar *buf = va; 
1999/0514    
	long off = voff; 
1999/0423    
 
1999/0522/sys/src/9/pc/devlml.c:904,9091999/0525/sys/src/9/pc/devlml.c:936,942
1999/0513    
	case Qdir: 
		error(Eperm); 
 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	case Q060: 
		if (off < 0 || off + n > 0x400) 
			return 0; 
1999/0522/sys/src/9/pc/devlml.c:977,9821999/0525/sys/src/9/pc/devlml.c:1010,1016
1999/0428    
			return 0; 
1999/0424    
		} 
1999/0428    
		return n; 
1999/0525    
#endif 
1999/0513    
	case Qjvideo: 
1999/0423    
	case Qjframe: 
1999/0424    
		return vwrite(c, buf, n, off); 
1999/0525/sys/src/9/pc/devlml.c:12,621999/0526/sys/src/9/pc/devlml.c:12,38 (short | long)
1999/0520    
static ulong		pciBaseAddr; 
static Pcidev *		pcidev; 
1999/0515    
 
1999/0520    
#define DBGREGS 0x01 
#define DBGREAD 0x02 
#define DBGWRIT 0x04 
#define DBG819	0x08 
#define DBGINTR	0x10 
#define DBGINTS	0x20 
1999/0526    
#define DBGREAD 0x01 
#define DBGWRIT 0x02 
#define DBGINTR	0x04 
#define DBGINTS	0x08 
1999/0520    
 
1999/0521    
int debug = 0; 
1999/0520    
 
1999/0422    
// Lml 22 driver 
 
1999/0525    
#ifdef MEMMAP 
1999/0517    
struct { 
	ulong pci; 
1999/0518    
	ulong statcom; 
1999/0517    
	ulong codedata; 
} lmlmap; 
1999/0525    
#endif 
1999/0517    
                 
1999/0422    
enum{ 
1999/0513    
	Qdir, 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	Q060, 
1999/0422    
	Q819, 
	Q856, 
1999/0428    
	Qreg, 
1999/0515    
	Qmap, 
1999/0518    
	Qbuf, 
1999/0525    
#endif 
1999/0513    
	Qjvideo, 
1999/0422    
	Qjframe, 
1999/0526    
	Qjcount, 
1999/0422    
}; 
 
1999/0513    
static Dirtab lmldir[]={ 
//	 name,		 qid,		size,		mode 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	"lml060",	{Q060},		0x400,		0644, 
1999/0513    
	"lml819",	{Q819},		0,		0644, 
	"lml856",	{Q856},		0,		0644, 
1999/0517    
	"lmlreg",	{Qreg},		0x400,		0644, 
	"lmlmap",	{Qmap},		sizeof lmlmap,	0444, 
1999/0518    
	"lmlbuf",	{Qbuf},		0,		0644, 
1999/0525    
#endif 
1999/0513    
	"jvideo",	{Qjvideo},	0,		0666, 
1999/0422    
	"jframe",	{Qjframe},	0,		0666, 
1999/0526    
	"jcount",	{Qjcount},	0,		0444, 
1999/0422    
}; 
 
CodeData *	codeData; 
1999/0525/sys/src/9/pc/devlml.c:82,4831999/0526/sys/src/9/pc/devlml.c:58,91
1999/0424    
}; 
 
1999/0525    
 
#ifndef MEMMAP 
#define writel(v, a) *(ulong *)(a) = (v) 
#define readl(a) *(ulong*)(a) 
#else 
1999/0515    
ulong 
writel(ulong v, ulong a) { 
	if (debug&DBGREGS) 
1999/0517    
		pprint("%.8lux (%.8lux) <-- %.8lux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return *(ulong *)a = v; 
} 
 
1999/0525    
ulong 
readl(ulong a) { 
	ulong v; 
                 
	v = *(ulong*)a; 
	if (debug&DBGREGS) 
		pprint("%.8lux (%.8lux) --> %.8lux\n", 
			a, (ulong)a-pciBaseAddr, v); 
	return v; 
} 
1999/0515    
ushort 
writew(ushort v, ulong a) { 
	if (debug&DBGREGS) 
1999/0517    
		pprint("%.8lux (%.8lux) <--     %.4ux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return *(ushort *)a = v; 
} 
                 
uchar 
writeb(uchar v, ulong a) { 
	if (debug&DBGREGS) 
1999/0517    
		pprint("%.8lux (%.8lux) <--       %.2ux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return *(uchar *)a = v; 
} 
                 
ushort 
readw(ulong a) { 
	ushort v; 
                 
	v = *(ushort*)a; 
	if (debug&DBGREGS) 
1999/0517    
		pprint("%.8lux (%.8lux) -->     %.4ux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return v; 
} 
                 
uchar 
readb(ulong a) { 
	uchar v; 
                 
	v = *(uchar*)a; 
	if (debug&DBGREGS) 
1999/0517    
		pprint("%.8lux (%.8lux) -->       %.2ux\n", 
			a, (ulong)a-pciBaseAddr, v); 
1999/0515    
	return v; 
} 
                 
1999/0423    
static void 
1999/0429    
i2c_pause(void) { 
1999/0422    
                 
1999/0423    
	microdelay(I2C_DELAY); 
} 
                 
1999/0422    
static void 
1999/0429    
i2c_waitscl(void) { 
1999/0423    
	int i; 
                 
1999/0520    
	for (i = 0; i < I2C_TIMEOUT; i++) 
		if (readl(pciBaseAddr + I2C_BUS) & I2C_SCL) 
			return; 
	error(Eio); 
1999/0423    
} 
                 
static void 
1999/0429    
i2c_start(void) { 
1999/0423    
                 
1999/0520    
	writel(I2C_SCL|I2C_SDA, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_waitscl(); 
	i2c_pause(); 
1999/0423    
                 
1999/0520    
	writel(I2C_SCL, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
                 
1999/0520    
	writel(0, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
} 
                 
static void 
1999/0429    
i2c_stop(void) { 
1999/0423    
	// the clock should already be low, make sure data is 
1999/0520    
	writel(0, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
                 
	// set clock high and wait for device to catch up 
1999/0520    
	writel(I2C_SCL, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_waitscl(); 
	i2c_pause(); 
1999/0423    
                 
	// set the data high to indicate the stop bit 
1999/0520    
	writel(I2C_SCL|I2C_SDA, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
} 
                 
1999/0429    
static void i2c_wrbit(int bit) { 
1999/0423    
	if (bit){ 
1999/0520    
		writel(I2C_SDA, pciBaseAddr + I2C_BUS); // set data 
1999/0429    
		i2c_pause(); 
1999/0520    
		writel(I2C_SDA|I2C_SCL, pciBaseAddr + I2C_BUS); 
1999/0429    
		i2c_waitscl(); 
		i2c_pause(); 
1999/0520    
		writel(I2C_SDA, pciBaseAddr + I2C_BUS); 
1999/0429    
		i2c_pause(); 
1999/0423    
	} else { 
1999/0520    
		writel(0, pciBaseAddr + I2C_BUS); // clr data 
1999/0429    
		i2c_pause(); 
1999/0520    
		writel(I2C_SCL, pciBaseAddr + I2C_BUS); 
1999/0429    
		i2c_waitscl(); 
		i2c_pause(); 
1999/0520    
		writel(0, pciBaseAddr + I2C_BUS); 
1999/0429    
		i2c_pause(); 
1999/0423    
	} 
} 
                 
static int 
1999/0429    
i2c_rdbit(void) { 
1999/0423    
	int bit; 
	// the clk line should be low 
1999/0526    
getbuffer(void){ 
	static last = NBUF-1; 
	int l = last; 
1999/0423    
 
	// ensure we are not asserting the data line 
1999/0520    
	writel(I2C_SDA, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
                 
	// set the clock high and wait for device to catch up 
1999/0520    
	writel(I2C_SDA|I2C_SCL, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_waitscl(); 
	i2c_pause(); 
1999/0423    
                 
	// the data line should be a valid bit 
1999/0520    
	bit = readl(pciBaseAddr+I2C_BUS); 
	if (bit & I2C_SDA){ 
1999/0423    
		bit = 1; 
	} else { 
		bit = 0; 
1999/0526    
	for (;;) { 
		last = (last+1) % NBUF; 
		if (codeData->statCom[last] & STAT_BIT) 
			return last; 
		if (last == l) 
			sleep(&sleeper, return0, 0); 
1999/0423    
	} 
                 
	// set the clock low to indicate end of cycle 
1999/0520    
	writel(I2C_SDA, pciBaseAddr + I2C_BUS); 
1999/0429    
	i2c_pause(); 
1999/0423    
                 
	return bit; 
1999/0526    
	return 0; 
1999/0423    
} 
 
static int 
1999/0429    
i2c_rdbyte(uchar *v) { 
1999/0423    
	int i, ack; 
	uchar res; 
1999/0526    
static long 
vcount(Chan *, void *va, long nbytes, vlong) { 
	char *p = (char *)va; 
1999/0423    
 
	res = 0; 
1999/0520    
	for (i = 0; i < 8; i++) { 
1999/0423    
		res  = res << 1; 
1999/0429    
		res += i2c_rdbit(); 
1999/0423    
	} 
                 
1999/0429    
	ack = i2c_rdbit(); 
1999/0423    
                 
	*v = res; 
                 
	return ack; 
} 
                 
static int 
1999/0429    
i2c_wrbyte(uchar v) { 
1999/0423    
	int i, ack; 
                 
1999/0520    
	for (i = 0; i < 8; i++) { 
1999/0429    
		i2c_wrbit(v & 0x80); 
1999/0423    
		v = v << 1; 
	} 
                 
1999/0429    
	ack = i2c_rdbit(); 
1999/0423    
                 
	return ack; 
} 
                 
static void 
1999/0429    
i2c_write_bytes(uchar addr, uchar sub, uchar *bytes, long num) { 
1999/0423    
	int ack; 
	long i; 
                 
1999/0429    
	i2c_start(); 
1999/0423    
                 
1999/0429    
	ack = i2c_wrbyte(addr); 
1999/0423    
	if (ack == 1) error(Eio); 
                 
1999/0429    
	ack = i2c_wrbyte(sub); 
1999/0423    
	if (ack == 1) error(Eio); 
                 
1999/0520    
	for (i = 0; i < num; i++) { 
1999/0429    
		ack = i2c_wrbyte(bytes[i]); 
1999/0423    
		if (ack == 1) error(Eio); 
	} 
                 
1999/0429    
	i2c_stop(); 
1999/0423    
} 
                 
1999/0424    
static int 
1999/0429    
i2c_bt856rd8(void) { 
	uchar ret; 
                 
	i2c_start (); 
                 
	if (i2c_wrbyte(BT856Addr + 1) == 1 
	 || i2c_rdbyte(&ret) == 0) { 
		i2c_stop (); 
		return -1; 
	} 
                 
	i2c_stop (); 
	return ret; 
} 
                 
static int 
i2c_rd8(int addr, int sub) 
1999/0423    
{ 
	uchar msb; 
                 
1999/0429    
	i2c_start(); 
1999/0423    
                 
1999/0429    
	if (i2c_wrbyte(addr) == 1 
	 || i2c_wrbyte(sub) == 1) { 
1999/0515    
		if (debug&DBGREGS) pprint("i2c_rd8, failure 1\n"); 
1999/0429    
		i2c_stop(); 
1999/0424    
		return -1; 
1999/0423    
	} 
                 
1999/0429    
	i2c_start(); 
1999/0423    
                 
1999/0429    
	if (i2c_wrbyte(addr+1) == 1 
	 || i2c_rdbyte(&msb) == 0){ 
1999/0515    
		if (debug&DBGREGS) pprint("i2c_rd8, failure 2\n"); 
1999/0429    
		i2c_stop(); 
1999/0424    
		return -1; 
1999/0423    
	} 
                 
1999/0429    
	i2c_stop(); 
1999/0423    
                 
	return msb; 
} 
                 
1999/0424    
static int 
1999/0429    
i2c_wr8(uchar addr, uchar sub, uchar msb) { 
1999/0424    
	                 
1999/0429    
	i2c_start(); 
1999/0424    
                 
1999/0429    
	if (i2c_wrbyte(addr) == 1 
	 || i2c_wrbyte(sub) == 1 
	 || i2c_wrbyte(msb) == 1) 
1999/0424    
		return 0; 
	                 
1999/0429    
	i2c_stop(); 
1999/0424    
	                 
1999/0526    
	// reads always return one byte: the next available buffer number 
	if (nbytes <= 0) return 0; 
	*p = getbuffer(); 
1999/0424    
	return 1; 
} 
 
1999/0520    
/* 
 * The following mapping applies for the guests in the LML33 
 * 
 * Guest        Device 
 *   0          zr36060 
 *              uses subaddress GADR[0..1] 
 *   1          zr36060 START# 
 *   2          - 
 *   3          zr36060 RESET# 
 *   4          - 
 *   5          - 
 *   6          - 
 *   7          - 
 */ 
                 
// post_idle waits for the guest bus to become free 
1999/0423    
static int 
1999/0520    
post_idle(void) { 
	ulong a; 
	int timeout; 
                 
	for (timeout = 0; timeout < GUEST_TIMEOUT; timeout++){ 
		a = readl(pciBaseAddr + POST_OFFICE); 
		if ((a & POST_PEND) == 0)  
			return a; 
	} 
	pprint("post_idle timeout\n"); 
	return -1; 
} 
                 
// post_write writes a byte to a guest using postoffice mechanism 
int 
post_write(unsigned int guest, unsigned int reg, unsigned int v) { 
	int w; 
                 
	// wait for postoffice not busy 
	post_idle(); 
                 
	// Trim the values, just in case 
	guest &= 0x07; 
	reg   &= 0x07; 
	v     &= 0xFF; 
                 
	// write postoffice operation 
	w = POST_DIR | (guest<<20) | (reg<<16) | v; 
	writel(w, pciBaseAddr + POST_OFFICE); 
                 
	// wait for postoffice not busy 
	return post_idle() == -1; 
} 
                 
// post_read reads a byte from a guest using postoffice mechanism 
int 
post_read(int guest, int reg) { 
	int w; 
                 
	// wait for postoffice not busy 
	post_idle(); 
                 
	// Trim the values, just in case 
	guest &= 0x07; 
	reg   &= 0x07; 
                 
	// write postoffice operation 
	w = (guest<<20) + (reg<<16); 
	writel(w, pciBaseAddr + POST_OFFICE); 
                 
	// wait for postoffice not busy, get result 
	w = post_idle(); 
                 
	// decide if read went ok 
	if (w == -1) return -1; 
                 
	return w & 0xFF; 
} 
                 
static int 
zr060_write(int reg, int v) { 
                   
	if (post_write(GID060, 1, (reg>>8) & 0x03) 
	 || post_write(GID060, 2, reg & 0xff) 
	 || post_write(GID060, 3, v)) 
		return -1; 
} 
                 
static int 
zr060_read(int reg) { 
                   
	if (post_write(GID060, 1, (reg>>8) & 0x03) 
	 || post_write(GID060, 2, reg    & 0xff)) 
		return -1; 
	return post_read(GID060, 3); 
} 
1999/0525    
#endif 
1999/0520    
                 
static int 
1999/0518    
prepareBuffer(int i) { 
	if (i >= 0 && i < NBUF && (codeData->statCom[i] & STAT_BIT)) { 
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
    		return codeData->fragdesc[i].leng; 
	} else 
		return -1; 
1999/0424    
} 
1999/0423    
                 
1999/0424    
static int 
1999/0518    
getProcessedBuffer(void){ 
	static lastBuffer = NBUF-1; 
	int l = lastBuffer; 
1999/0424    
                 
	while (1) {  
		lastBuffer = (lastBuffer+1) % NBUF; 
1999/0518    
		if (codeData->statCom[lastBuffer] & STAT_BIT) 
1999/0424    
			return lastBuffer; 
1999/0518    
		if (lastBuffer == l) 
1999/0424    
			break; 
1999/0423    
	} 
1999/0424    
	return -1; 
1999/0423    
} 
                 
1999/0424    
static int 
1999/0520    
getBuffer(int i, int* frameNo) { 
1999/0518    
                 
	if(codeData->statCom[i] & STAT_BIT) { 
		*frameNo = codeData->statCom[i] >> 24; 
		return (codeData->statCom[i] & 0x00FFFFFF) >> 1; 
1999/0424    
	} else 
		return -1; 
} 
1999/0423    
                 
1999/0424    
static long 
1999/0520    
vread(Chan *, void *va, long nbytes, vlong) { 
	static int bufpos; 
1999/0525/sys/src/9/pc/devlml.c:495,5071999/0526/sys/src/9/pc/devlml.c:103,115
1999/0520    
	while (count > 0) { 
		switch (state) { 
		case New: 
1999/0521    
			while ((curbuf = getProcessedBuffer()) == -1) 
1999/0520    
				sleep(&sleeper, return0, 0); 
			fragsize = getBuffer(curbuf, &frameno); 
1999/0526    
			curbuf = getbuffer(); 
			frameNo = codeData->statCom[curbuf] >> 24; 
			fragsize = (codeData->statCom[curbuf] & 0x00ffffff)>>1; 
1999/0520    
			if (debug & DBGREAD) 
				pprint("devlml: got read buf %d, fr %d, size %d\n", 
					curbuf, frameNo, fragsize); 
1999/0521    
			if (frameno != (frameprev + 1) % 256) 
1999/0526    
			if (!singleFrame && frameno != (frameprev + 1) % 256) 
1999/0521    
				pprint("Frame out of sequence: %d %d\n", 
					frameprev, frameno); 
1999/0520    
			frameprev = frameno; 
1999/0525/sys/src/9/pc/devlml.c:508,5141999/0526/sys/src/9/pc/devlml.c:116,122
1999/0521    
			if (fragsize <= 0 || fragsize > sizeof(Fragment)) { 
				pprint("Wrong sized fragment, %d (ignored)\n", 
					fragsize); 
				prepareBuffer(curbuf); 
1999/0526    
				codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf])); 
1999/0521    
				break; 
			} 
1999/0520    
			// Fill in APP marker fields here 
1999/0525/sys/src/9/pc/devlml.c:550,5561999/0526/sys/src/9/pc/devlml.c:158,164
1999/0520    
			p += i; 
 
			// Allow reuse of current buffer 
			prepareBuffer(curbuf); 
1999/0526    
			codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf])); 
1999/0520    
			state = New; 
1999/0521    
			if (singleFrame) { 
				state = Error; 
1999/0525/sys/src/9/pc/devlml.c:577,5871999/0526/sys/src/9/pc/devlml.c:185,191
1999/0520    
	while (count > 0) { 
		switch (state) { 
		case New: 
			while((curbuf = getProcessedBuffer()) == -1) { 
				if (debug&DBGWRIT) 
					pprint("devlml::sleep\n"); 
				sleep(&sleeper, return0, 0); 
1999/0424    
			} 
1999/0526    
			curbuf = getbuffer(); 
1999/0520    
			if (debug&DBGWRIT) 
				pprint("current buffer %d\n", curbuf); 
			bufptr = codeData->frag[curbuf].fb; 
1999/0525/sys/src/9/pc/devlml.c:638,6461999/0526/sys/src/9/pc/devlml.c:242,250
1999/0520    
			p += i; 
			count -= i; 
			// We have written the frame, time to display it 
			i = prepareBuffer(curbuf); 
1999/0526    
			codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf])); 
1999/0520    
			if (debug&DBGWRIT) 
				pprint("Sending buffer %d: %d\n", curbuf, i); 
1999/0526    
				pprint("Sending buffer %d\n", curbuf); 
1999/0521    
			if (singleFrame) { 
				state = Error; 
				return nbytes - count; 
1999/0525/sys/src/9/pc/devlml.c:658,6671999/0526/sys/src/9/pc/devlml.c:262,269
1999/0423    
static void 
1999/0513    
lmlreset(void) 
1999/0422    
{ 
1999/0522    
// LMLSEG 
	Physseg segbuf; 
	Physseg segreg; 
// 
1999/0422    
	ulong regpa; 
1999/0525    
	ulong cdsize; 
1999/0422    
	int i; 
1999/0525/sys/src/9/pc/devlml.c:682,6881999/0526/sys/src/9/pc/devlml.c:284,290
1999/0422    
 
	// Get access to DMA memory buffer 
	memset(codeData, 0xAA, sizeof(CodeData)); 
1999/0525    
	codeData->physaddr = PADDR(&(codeData->statCom[0])); 
1999/0526    
	codeData->physaddr = PADDR(codeData->statCom); 
1999/0520    
	for (i = 0; i < NBUF; i++) { 
1999/0517    
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
		codeData->fragdesc[i].addr = PADDR(&(codeData->frag[i])); 
1999/0525/sys/src/9/pc/devlml.c:704,7261999/0526/sys/src/9/pc/devlml.c:306,314
1999/0423    
	pciBaseAddr = (ulong)KADDR(regpa); 
1999/0513    
	print(", mapped at 0x%.8lux\n", pciBaseAddr); 
1999/0422    
 
	// make sure the device will respond to mem accesses 
	// (pcicmd_master | pcicmd_memory) -- probably superfluous 
1999/0423    
//	pcicfgw32(pcidev, PciPCR, 0x04 | 0x02); 
1999/0422    
                 
	// set bus latency -- probably superfluous 
1999/0423    
//	pcicfgw8(pcidev, PciLTR, 64); 
1999/0422    
                 
	// Interrupt handler 
1999/0423    
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); 
1999/0422    
 
1999/0525    
#ifdef MEMMAP 
1999/0515    
	lmlmap.pci = pciBaseAddr; 
1999/0518    
	lmlmap.statcom = PADDR(codeData->statCom); 
1999/0515    
	lmlmap.codedata = (ulong)codeData; 
1999/0525    
#endif 
1999/0522    
                 
// LMLSEG 
	memset(&segbuf, 0, sizeof(segbuf)); 
	segbuf.attr = SG_PHYSICAL; 
	segbuf.name = smalloc(NAMELEN); 
1999/0525/sys/src/9/pc/devlml.c:742,7491999/0526/sys/src/9/pc/devlml.c:330,335
1999/0525    
		print("lml: physsegment: lmlmjpg\n"); 
		return; 
	} 
1999/0522    
// 
1999/0515    
                 
1999/0422    
	return;  
} 
 
1999/0525/sys/src/9/pc/devlml.c:771,7871999/0526/sys/src/9/pc/devlml.c:357,365
1999/0517    
 
1999/0422    
	c->aux = 0; 
	switch(c->qid.path){ 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	case Q060: 
1999/0422    
	case Q819: 
	case Q856: 
1999/0428    
	case Qreg: 
1999/0515    
	case Qmap: 
1999/0518    
	case Qbuf: 
1999/0422    
		break; 
1999/0525    
#endif 
1999/0422    
	case Qjframe: 
1999/0521    
	case Qjvideo: 
1999/0526    
	case Qjcount: 
1999/0424    
		if (nopens) 
			error(Einuse); 
		nopens = 1; 
1999/0525/sys/src/9/pc/devlml.c:800,8171999/0526/sys/src/9/pc/devlml.c:378,386
1999/0518    
lmlclose(Chan *c) { 
 
1999/0422    
	switch(c->qid.path){ 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	case Q060: 
1999/0422    
	case Q819: 
	case Q856: 
1999/0428    
	case Qreg: 
1999/0515    
	case Qmap: 
1999/0518    
	case Qbuf: 
1999/0515    
		authclose(c); 
		break; 
1999/0525    
#endif 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0526    
	case Qjcount: 
1999/0515    
		nopens = 0; 
1999/0422    
		authclose(c); 
	} 
1999/0525/sys/src/9/pc/devlml.c:819,8271999/0526/sys/src/9/pc/devlml.c:388,393
1999/0422    
 
static long 
1999/0513    
lmlread(Chan *c, void *va, long n, vlong voff) { 
1999/0525    
#ifdef MEMMAP 
1999/0424    
	int i, d; 
1999/0525    
#endif 
1999/0424    
	uchar *buf = va; 
1999/0513    
	long off = voff; 
1999/0423    
 
1999/0525/sys/src/9/pc/devlml.c:829,10161999/0526/sys/src/9/pc/devlml.c:395,417
1999/0513    
 
	case Qdir: 
		return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen); 
                 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	case Q060: 
		if (off < 0 || off + n > 0x400) 
			return 0; 
		for (i = 0; i < n; i++) { 
			if ((d = zr060_read(off + i)) < 0) break; 
			*buf++ = d; 
		} 
		return i; 
1999/0422    
	case Q819: 
1999/0424    
		if (off < 0 || off + n > 0x20) 
1999/0423    
			return 0; 
1999/0424    
		for (i = 0; i < n; i++) { 
1999/0429    
			if ((d = i2c_rd8(BT819Addr, off++)) < 0) break; 
1999/0424    
			*buf++ = d; 
		} 
1999/0515    
		return i; 
1999/0422    
	case Q856: 
1999/0429    
		if (n != 1) 
1999/0423    
			return 0; 
1999/0429    
		switch ((int)off) { 
		case 0: 
			if ((d = i2c_bt856rd8()) < 0) 
				return 0; 
			*buf = d; 
			break; 
		case 0xDA: 
			*buf = q856[0]; 
			break; 
		case 0xDC: 
			*buf = q856[1]; 
			break; 
		case 0xDE: 
			*buf = q856[2]; 
			break; 
		default: 
			return 0; 
1999/0424    
		} 
1999/0429    
		return 1; 
1999/0515    
	case Qmap: 
		if (off < 0) 
			return 0; 
		for (i = 0; i < n; i++) { 
1999/0517    
			if (off + i >= sizeof lmlmap) 
1999/0515    
				break; 
			buf[i] = ((uchar *)&lmlmap)[off + i]; 
		} 
		return i; 
1999/0428    
	case Qreg: 
1999/0518    
		if (off < 0 || off + n >= 0x400) 
1999/0424    
			return 0; 
1999/0428    
		switch(n) { 
		case 1: 
			*buf = readb(pciBaseAddr + off); 
			break; 
		case 2: 
1999/0430    
			if (off & (n-1)) return 0; 
1999/0428    
			*(short *)buf = readw(pciBaseAddr + off); 
			break; 
		case 4: 
1999/0430    
			if (off & (n-1)) return 0; 
1999/0515    
			*(long *)buf = readl(pciBaseAddr + off); 
1999/0428    
			break; 
		default: 
			return 0; 
1999/0424    
		} 
1999/0428    
		return n; 
1999/0518    
	case Qbuf: 
		if (off < 0 || off + n >= sizeof *codeData) 
			return 0; 
		switch(n) { 
		case 1: 
			*buf = readb((ulong)codeData + off); 
			break; 
		case 2: 
			if (off & (n-1)) return 0; 
			*(short *)buf = readw((ulong)codeData + off); 
			break; 
		case 4: 
			if (off & (n-1)) return 0; 
			*(long *)buf = readl((ulong)codeData + off); 
			break; 
		default: 
			return 0; 
		} 
		return n; 
1999/0525    
#endif 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0424    
		return vread(c, buf, n, off); 
1999/0526    
	case Qjcount: 
		return vcount(c, buf, n, off); 
1999/0422    
	} 
} 
 
static long 
1999/0514    
lmlwrite(Chan *c, void *va, long n, vlong voff) { 
1999/0525    
#ifdef MEMMAP 
1999/0424    
	int i; 
1999/0525    
#endif 
1999/0424    
	uchar *buf = va; 
1999/0514    
	long off = voff; 
1999/0423    
 
1999/0513    
	switch(c->qid.path & ~CHDIR){ 
                 
	case Qdir: 
1999/0526    
	case Qjcount: 
1999/0513    
		error(Eperm); 
                 
1999/0525    
#ifdef MEMMAP 
1999/0520    
	case Q060: 
		if (off < 0 || off + n > 0x400) 
			return 0; 
		for (i = 0; i < n; i++) { 
			if (zr060_write(off + i, *buf++) < 0) break; 
		} 
		return i; 
1999/0423    
	case Q819: 
1999/0517    
		if (off < 0 || off + n >= 0x20) 
1999/0423    
			return 0; 
1999/0520    
		for (i = 0; i < n; i++) 
			if (i2c_wr8(BT819Addr, off + i, *buf++) == 0) 
1999/0424    
				break; 
1999/0515    
		return i; 
1999/0423    
	case Q856: 
1999/0429    
		if (n != 1 || off < 0xda || off + n > 0xe0) 
1999/0423    
			return 0; 
1999/0429    
		if (i2c_wr8(BT856Addr, off, *buf) == 0) 
				return 0; 
		switch ((int)off) { 
		case 0xDA: 
			q856[0] = *buf; 
			break; 
		case 0xDC: 
			q856[1] = *buf; 
			break; 
		case 0xDE: 
			q856[2] = *buf; 
			break; 
		} 
		return 1; 
1999/0428    
	case Qreg: 
1999/0518    
		if (off < 0 || off + n >= 0x400) 
1999/0424    
			return 0; 
1999/0428    
		switch (n) { 
		case 1: 
			writeb(*buf, pciBaseAddr + off); 
			break; 
		case 2: 
1999/0515    
			if (off & 0x1) 
				return 0; 
1999/0428    
			writew(*(short *)buf, pciBaseAddr + off); 
			break; 
		case 4: 
1999/0515    
			if (off & 0x3) 
				return 0; 
1999/0424    
			writel(*(long *)buf, pciBaseAddr + off); 
1999/0518    
			break; 
		default: 
			return 0; 
		} 
		return n; 
	case Qbuf: 
		if (off < 0 || off + n >= sizeof *codeData) 
			return 0; 
		switch (n) { 
		case 1: 
			writeb(*buf, (ulong)codeData + off); 
			break; 
		case 2: 
			if (off & 0x1) 
				return 0; 
			writew(*(short *)buf, (ulong)codeData + off); 
			break; 
		case 4: 
			if (off & 0x3) 
				return 0; 
			writel(*(long *)buf, (ulong)codeData + off); 
1999/0428    
			break; 
		default: 
			return 0; 
1999/0424    
		} 
1999/0428    
		return n; 
1999/0525    
#endif 
1999/0513    
	case Qjvideo: 
1999/0423    
	case Qjframe: 
1999/0424    
		return vwrite(c, buf, n, off); 
1999/0526/sys/src/9/pc/devlml.c:264,2711999/0527/sys/src/9/pc/devlml.c:264,274 (short | long)
1999/0422    
{ 
1999/0522    
	Physseg segbuf; 
	Physseg segreg; 
1999/0527    
	Physseg seggrab; 
1999/0422    
	ulong regpa; 
1999/0525    
	ulong cdsize; 
1999/0527    
	ulong *grabpa; 
	ulong grablen; 
1999/0422    
	int i; 
 
1999/0423    
	pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067); 
1999/0526/sys/src/9/pc/devlml.c:279,2861999/0527/sys/src/9/pc/devlml.c:282,298
1999/0422    
		return; 
	} 
 
1999/0527    
	grablen = (720 * 480 * 2 * 2 + BY2PG - 1) & ~(BY2PG - 1); 
	grabpa = (ulong *)xspanalloc(grablen, BY2PG, 0); 
	if (grabpa == nil) { 
		print("devlml: xspanalloc(%lux, %ux, 0)\n", grablen, BY2PG); 
		return; 
	} 
	*grabpa = PADDR(grabpa); 
 
1999/0422    
	print("Installing Motion JPEG driver %s\n", MJPG_VERSION);  
1999/0525    
	print("Buffer at 0x%.8lux, size 0x%.8lux\n", codeData, cdsize);  
1999/0527    
	print("MJPG buffer at 0x%.8lux, size 0x%.8lux\n", codeData, cdsize);  
	print("Grab buffer at 0x%.8lux, size 0x%.8lux\n", grabpa, grablen);  
1999/0422    
 
	// Get access to DMA memory buffer 
	memset(codeData, 0xAA, sizeof(CodeData)); 
1999/0526/sys/src/9/pc/devlml.c:327,3331999/0527/sys/src/9/pc/devlml.c:339,356
1999/0522    
	segreg.pa = (ulong)regpa; 
	segreg.size = pcidev->mem[0].size; 
1999/0525    
	if (addphysseg(&segreg) == -1) { 
		print("lml: physsegment: lmlmjpg\n"); 
1999/0527    
		print("lml: physsegment: lmlregs\n"); 
		return; 
	} 
 
	memset(&seggrab, 0, sizeof(seggrab)); 
	seggrab.attr = SG_PHYSICAL; 
	seggrab.name = smalloc(NAMELEN); 
	snprint(seggrab.name, NAMELEN, "lmlgrab"); 
	seggrab.pa = (ulong)PADDR(grabpa); 
	seggrab.size = grablen; 
	if (addphysseg(&seggrab) == -1) { 
		print("lml: physsegment: lmlgrab\n"); 
1999/0525    
		return; 
	} 
1999/0422    
	return;  
1999/0527/sys/src/9/pc/devlml.c:267,2731999/0529/sys/src/9/pc/devlml.c:267,273 (short | long)
1999/0527    
	Physseg seggrab; 
1999/0422    
	ulong regpa; 
1999/0525    
	ulong cdsize; 
1999/0527    
	ulong *grabpa; 
1999/0529    
	void *grabbuf; 
1999/0527    
	ulong grablen; 
1999/0422    
	int i; 
 
1999/0527/sys/src/9/pc/devlml.c:275,2811999/0529/sys/src/9/pc/devlml.c:275,281
1999/0423    
	if (pcidev == nil) { 
		return; 
	} 
1999/0525    
	cdsize = (sizeof(CodeData) + BY2PG - 1) & ~(BY2PG - 1); 
1999/0529    
	cdsize = CODEDATASIZE; 
1999/0525    
	codeData = (CodeData*)xspanalloc(cdsize, BY2PG, 0); 
1999/0422    
	if (codeData == nil) { 
1999/0525    
		print("devlml: xspanalloc(%lux, %ux, 0)\n", cdsize, BY2PG); 
1999/0527/sys/src/9/pc/devlml.c:282,3021999/0529/sys/src/9/pc/devlml.c:282,304
1999/0422    
		return; 
	} 
 
1999/0527    
	grablen = (720 * 480 * 2 * 2 + BY2PG - 1) & ~(BY2PG - 1); 
	grabpa = (ulong *)xspanalloc(grablen, BY2PG, 0); 
	if (grabpa == nil) { 
1999/0529    
	grablen = GRABDATASIZE; 
	grabbuf = xspanalloc(grablen, BY2PG, 0); 
	if (grabbuf == nil) { 
1999/0527    
		print("devlml: xspanalloc(%lux, %ux, 0)\n", grablen, BY2PG); 
		return; 
	} 
	*grabpa = PADDR(grabpa); 
 
1999/0529    
	memset(grabbuf, 0x33, grablen); 
 
1999/0422    
	print("Installing Motion JPEG driver %s\n", MJPG_VERSION);  
1999/0527    
	print("MJPG buffer at 0x%.8lux, size 0x%.8lux\n", codeData, cdsize);  
	print("Grab buffer at 0x%.8lux, size 0x%.8lux\n", grabpa, grablen);  
1999/0529    
	print("Grab buffer at 0x%.8lux, size 0x%.8lux\n", grabbuf, grablen);  
1999/0422    
 
	// Get access to DMA memory buffer 
	memset(codeData, 0xAA, sizeof(CodeData)); 
1999/0526    
	codeData->physaddr = PADDR(codeData->statCom); 
1999/0529    
	codeData->pamjpg = PADDR(codeData->statCom); 
	codeData->pagrab = PADDR(grabbuf); 
1999/0520    
	for (i = 0; i < NBUF; i++) { 
1999/0517    
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
		codeData->fragdesc[i].addr = PADDR(&(codeData->frag[i])); 
1999/0527/sys/src/9/pc/devlml.c:347,3591999/0529/sys/src/9/pc/devlml.c:349,361
1999/0527    
	seggrab.attr = SG_PHYSICAL; 
	seggrab.name = smalloc(NAMELEN); 
	snprint(seggrab.name, NAMELEN, "lmlgrab"); 
	seggrab.pa = (ulong)PADDR(grabpa); 
1999/0529    
	seggrab.pa = PADDR(grabbuf); 
1999/0527    
	seggrab.size = grablen; 
	if (addphysseg(&seggrab) == -1) { 
		print("lml: physsegment: lmlgrab\n"); 
1999/0525    
		return; 
	} 
1999/0422    
	return;  
1999/0529    
	return; 
1999/0422    
} 
 
static Chan* 
1999/0529/sys/src/9/pc/devlml.c:120,1261999/0531/sys/src/9/pc/devlml.c:120,126 (short | long)
1999/0521    
				break; 
			} 
1999/0520    
			// Fill in APP marker fields here 
			thetime = todget(); 
1999/0531    
			thetime = todget(nil); 
1999/0520    
			frameHeader.sec = (ulong)(thetime / 1000000000LL); 
			frameHeader.usec = (ulong)(thetime % 1000000000LL) / 1000; 
			frameHeader.frameSize = fragsize - 2 + sizeof(FrameHeader); 
1999/0531/sys/src/9/pc/devlml.c:23,631999/0601/sys/src/9/pc/devlml.c:23,43 (short | long)
1999/0422    
 
enum{ 
1999/0513    
	Qdir, 
	Qjvideo, 
1999/0422    
	Qjframe, 
1999/0526    
	Qjcount, 
1999/0422    
}; 
 
1999/0513    
static Dirtab lmldir[]={ 
//	 name,		 qid,		size,		mode 
	"jvideo",	{Qjvideo},	0,		0666, 
1999/0422    
	"jframe",	{Qjframe},	0,		0666, 
1999/0526    
	"jcount",	{Qjcount},	0,		0444, 
1999/0422    
}; 
 
CodeData *	codeData; 
 
1999/0520    
typedef enum { 
	New, 
	Header, 
	Body, 
	Error, 
} State; 
                 
1999/0513    
int		frameNo; 
1999/0424    
Rendez		sleeper; 
1999/0513    
int		singleFrame; 
int		nopens; 
1999/0429    
uchar		q856[3]; 
1999/0520    
State		state = New; 
1999/0424    
 
static FrameHeader frameHeader = { 
	MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8, 
	{ 'L', 'M', 'L', '\0'}, 
	-1, 0, 0, 0, 0 
}; 
                 
1999/0525    
                 
#define writel(v, a) *(ulong *)(a) = (v) 
#define readl(a) *(ulong*)(a) 
1999/0515    
 
1999/0531/sys/src/9/pc/devlml.c:86,2621999/0601/sys/src/9/pc/devlml.c:66,71
1999/0424    
	return 1; 
} 
 
static long 
1999/0520    
vread(Chan *, void *va, long nbytes, vlong) { 
	static int bufpos; 
	static char *bufptr; 
	static int curbuf; 
	static int fragsize; 
	static int frameno; 
	static int frameprev; 
	char *p; 
	long count = nbytes; 
	int i; 
	vlong thetime; 
                 
	p = (char *)va; 
	while (count > 0) { 
		switch (state) { 
		case New: 
1999/0526    
			curbuf = getbuffer(); 
			frameNo = codeData->statCom[curbuf] >> 24; 
			fragsize = (codeData->statCom[curbuf] & 0x00ffffff)>>1; 
1999/0520    
			if (debug & DBGREAD) 
				pprint("devlml: got read buf %d, fr %d, size %d\n", 
					curbuf, frameNo, fragsize); 
1999/0526    
			if (!singleFrame && frameno != (frameprev + 1) % 256) 
1999/0521    
				pprint("Frame out of sequence: %d %d\n", 
					frameprev, frameno); 
1999/0520    
			frameprev = frameno; 
1999/0521    
			if (fragsize <= 0 || fragsize > sizeof(Fragment)) { 
				pprint("Wrong sized fragment, %d (ignored)\n", 
					fragsize); 
1999/0526    
				codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf])); 
1999/0521    
				break; 
			} 
1999/0520    
			// Fill in APP marker fields here 
1999/0531    
			thetime = todget(nil); 
1999/0520    
			frameHeader.sec = (ulong)(thetime / 1000000000LL); 
			frameHeader.usec = (ulong)(thetime % 1000000000LL) / 1000; 
			frameHeader.frameSize = fragsize - 2 + sizeof(FrameHeader); 
			frameHeader.frameSeqNo++; 
			frameHeader.frameNo = frameno; 
			bufpos = 0; 
1999/0521    
			state = Header; 
1999/0520    
			bufptr = (char *)(&frameHeader); 
			// Fall through 
		case Header: 
			i = sizeof(FrameHeader) - bufpos; 
			if (count <= i) { 
				memmove(p, bufptr, count); 
				bufptr += count; 
				bufpos += count; 
				return nbytes; 
			} 
			memmove(p, bufptr, i); 
			count -= i; 
			p += i; 
			bufpos = 2; 
1999/0521    
			bufptr = codeData->frag[curbuf].fb + 2; 
1999/0520    
			state = Body; 
			// Fall through 
		case Body: 
			i = fragsize - bufpos; 
1999/0521    
			if (count < i) { 
1999/0520    
				memmove(p, bufptr, count); 
				bufptr += count; 
				bufpos += count; 
				return nbytes; 
			} 
			memmove(p, bufptr, i); 
			count -= i; 
			p += i; 
                 
			// Allow reuse of current buffer 
1999/0526    
			codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf])); 
1999/0520    
			state = New; 
1999/0521    
			if (singleFrame) { 
				state = Error; 
				return nbytes - count; 
			} 
1999/0520    
			break; 
		case Error: 
			return 0; 
		} 
	} 
} 
                 
static long 
vwrite(Chan *, void *va, long nbytes, vlong) { 
	static int bufpos; 
	static char *bufptr; 
	static int curbuf; 
	static int fragsize; 
	char *p; 
	long count = nbytes; 
	int i; 
1999/0424    
                 
1999/0520    
	p = (char *)va; 
	while (count > 0) { 
		switch (state) { 
		case New: 
1999/0526    
			curbuf = getbuffer(); 
1999/0520    
			if (debug&DBGWRIT) 
				pprint("current buffer %d\n", curbuf); 
			bufptr = codeData->frag[curbuf].fb; 
			bufpos = 0; 
			state = Header; 
			// Fall through 
		case Header: 
			if (count < sizeof(FrameHeader) - bufpos) { 
				memmove(bufptr, p, count); 
				bufptr += count; 
				bufpos += count; 
				return nbytes; 
			} 
			// Fill remainder of header 
			i = sizeof(FrameHeader) - bufpos; 
			memmove(bufptr, p, i); 
			bufptr += i; 
			bufpos += i; 
			p += i; 
			count -= i; 
			// verify header 
			if (codeData->frag[curbuf].fh.mrkSOI != MRK_SOI 
			 || codeData->frag[curbuf].fh.mrkAPP3 != MRK_APP3 
			 || strcmp(codeData->frag[curbuf].fh.nm, APP_NAME)) { 
				// Header is bad 
				pprint("devlml: header error: 0x%.4ux, 0x%.4ux, `%.4s'\n", 
					codeData->frag[curbuf].fh.mrkSOI, 
					codeData->frag[curbuf].fh.mrkAPP3, 
					codeData->frag[curbuf].fh.nm); 
				state = Error; 
1999/0521    
				return nbytes - count; 
1999/0520    
			} 
			fragsize = codeData->frag[curbuf].fh.frameSize; 
			if (fragsize <= sizeof(FrameHeader) 
			 || fragsize  > sizeof(Fragment)) { 
				pprint("devlml: frame size error: 0x%.8ux\n", 
					fragsize); 
				state = Error; 
1999/0521    
				return nbytes - count; 
1999/0520    
			} 
			state = Body; 
			// Fall through 
		case Body: 
1999/0521    
			i = fragsize - bufpos; 
			if (count < i) { 
1999/0520    
				memmove(bufptr, p, count); 
				bufptr += count; 
				bufpos += count; 
				return nbytes; 
			} 
			memmove(bufptr, p, i); 
			bufptr += i; 
			bufpos += i; 
			p += i; 
			count -= i; 
			// We have written the frame, time to display it 
1999/0526    
			codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf])); 
1999/0520    
			if (debug&DBGWRIT) 
1999/0526    
				pprint("Sending buffer %d\n", curbuf); 
1999/0521    
			if (singleFrame) { 
				state = Error; 
				return nbytes - count; 
			} 
1999/0520    
			state = New; 
			break; 
		case Error: 
			return 0; 
1999/0424    
		} 
	} 
} 
                 
1999/0423    
static void lmlintr(Ureg *, void *); 
 
static void 
1999/0531/sys/src/9/pc/devlml.c:289,3021999/0601/sys/src/9/pc/devlml.c:98,108
1999/0527    
		return; 
	} 
 
1999/0529    
	memset(grabbuf, 0x33, grablen); 
                 
1999/0422    
	print("Installing Motion JPEG driver %s\n", MJPG_VERSION);  
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 
	memset(codeData, 0xAA, sizeof(CodeData)); 
1999/0529    
	codeData->pamjpg = PADDR(codeData->statCom); 
	codeData->pagrab = PADDR(grabbuf); 
1999/0520    
	for (i = 0; i < NBUF; i++) { 
1999/0531/sys/src/9/pc/devlml.c:306,3131999/0601/sys/src/9/pc/devlml.c:112,117
1999/0518    
		codeData->fragdesc[i].leng = ((sizeof codeData->frag[i]) >> 1) | FRAGM_FINAL_B; 
1999/0422    
	} 
 
	print("initializing LML33 board..."); 
                 
1999/0423    
	pciPhysBaseAddr = (void *)(pcidev->mem[0].bar & ~0x0F); 
1999/0422    
 
1999/0513    
	print("zr36067 found at 0x%.8lux", pciPhysBaseAddr); 
1999/0531/sys/src/9/pc/devlml.c:320,3281999/0601/sys/src/9/pc/devlml.c:124,129
1999/0423    
	pciBaseAddr = (ulong)KADDR(regpa); 
1999/0513    
	print(", mapped at 0x%.8lux\n", pciBaseAddr); 
1999/0422    
 
	// Interrupt handler 
1999/0423    
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); 
1999/0422    
                 
1999/0522    
	memset(&segbuf, 0, sizeof(segbuf)); 
	segbuf.attr = SG_PHYSICAL; 
	segbuf.name = smalloc(NAMELEN); 
1999/0531/sys/src/9/pc/devlml.c:355,3601999/0601/sys/src/9/pc/devlml.c:156,165
1999/0527    
		print("lml: physsegment: lmlgrab\n"); 
1999/0525    
		return; 
	} 
1999/0601    
 
	// Interrupt handler 
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); 
 
1999/0529    
	return; 
1999/0422    
} 
 
1999/0531/sys/src/9/pc/devlml.c:378,3991999/0601/sys/src/9/pc/devlml.c:183,196
1999/0422    
 
static Chan* 
1999/0518    
lmlopen(Chan *c, int omode) { 
1999/0521    
	int i; 
1999/0517    
 
1999/0422    
	c->aux = 0; 
	switch(c->qid.path){ 
	case Qjframe: 
1999/0521    
	case Qjvideo: 
1999/0526    
	case Qjcount: 
1999/0601    
		// allow one open 
1999/0424    
		if (nopens) 
			error(Einuse); 
		nopens = 1; 
		singleFrame = (c->qid.path == Qjframe) ? 1 : 0;; 
1999/0520    
		state = New; 
1999/0521    
		for (i = 0; i < NBUF; i++) 
			codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
1999/0517    
                 
1999/0422    
		// allow one open total for these two 
		break; 
	} 
1999/0513    
	return devopen(c, omode, lmldir, nelem(lmldir), devgen); 
1999/0531/sys/src/9/pc/devlml.c:403,4101999/0601/sys/src/9/pc/devlml.c:200,205
1999/0518    
lmlclose(Chan *c) { 
 
1999/0422    
	switch(c->qid.path){ 
1999/0513    
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0526    
	case Qjcount: 
1999/0515    
		nopens = 0; 
1999/0422    
		authclose(c); 
1999/0531/sys/src/9/pc/devlml.c:420,4281999/0601/sys/src/9/pc/devlml.c:215,220
1999/0513    
 
	case Qdir: 
		return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen); 
	case Qjvideo: 
1999/0422    
	case Qjframe: 
1999/0424    
		return vread(c, buf, n, off); 
1999/0526    
	case Qjcount: 
		return vcount(c, buf, n, off); 
1999/0422    
	} 
1999/0531/sys/src/9/pc/devlml.c:429,4461999/0601/sys/src/9/pc/devlml.c:221,230
1999/0422    
} 
 
static long 
1999/0514    
lmlwrite(Chan *c, void *va, long n, vlong voff) { 
1999/0424    
	uchar *buf = va; 
1999/0514    
	long off = voff; 
1999/0601    
lmlwrite(Chan *, void *, long, vlong) { 
1999/0423    
 
1999/0513    
	switch(c->qid.path & ~CHDIR){ 
	case Qdir: 
1999/0526    
	case Qjcount: 
1999/0513    
		error(Eperm); 
	case Qjvideo: 
1999/0423    
	case Qjframe: 
1999/0424    
		return vwrite(c, buf, n, off); 
1999/0423    
	} 
1999/0601    
	error(Eperm); 
	return 0; 
1999/0422    
} 
 
1999/0513    
Dev lmldevtab = { 
1999/0601/sys/src/9/pc/devlml.c:23,421999/0610/sys/src/9/pc/devlml.c:23,71 (short | long)
1999/0422    
 
enum{ 
1999/0513    
	Qdir, 
1999/0526    
	Qjcount, 
1999/0610    
	Qjpg, 
//	Qraw, 
1999/0422    
}; 
 
1999/0513    
static Dirtab lmldir[]={ 
//	 name,		 qid,		size,		mode 
1999/0526    
	"jcount",	{Qjcount},	0,		0444, 
1999/0610    
//	 name,		qid,	size,	mode 
	"lmljpg",	{Qjpg},	0,	0444, 
//	"lmlraw",	{Qraw},	0,	0444, 
1999/0422    
}; 
 
CodeData *	codeData; 
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; 
1999/0424    
Rendez		sleeper; 
1999/0610    
Rendez		sleepjpg; 
//Rendez		sleepraw; 
1999/0513    
int		singleFrame; 
int		nopens; 
1999/0610    
int		jpgopens; 
//int		rawopens; 
1999/0424    
 
1999/0525    
#define writel(v, a) *(ulong *)(a) = (v) 
#define readl(a) *(ulong*)(a) 
1999/0601/sys/src/9/pc/devlml.c:51,741999/0610/sys/src/9/pc/devlml.c:80,136
1999/0526    
		if (codeData->statCom[last] & STAT_BIT) 
			return last; 
		if (last == l) 
			sleep(&sleeper, return0, 0); 
1999/0610    
			sleep(&sleepjpg, return0, 0); 
1999/0423    
	} 
1999/0526    
	return 0; 
1999/0423    
} 
 
1999/0526    
static long 
vcount(Chan *, void *va, long nbytes, vlong) { 
	char *p = (char *)va; 
1999/0610    
jpgread(Chan *, void *va, long nbytes, vlong) { 
	int bufno; 
1999/0423    
 
1999/0526    
	// reads always return one byte: the next available buffer number 
	if (nbytes <= 0) return 0; 
	*p = getbuffer(); 
1999/0424    
	return 1; 
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; 
1999/0601/sys/src/9/pc/devlml.c:78,841999/0610/sys/src/9/pc/devlml.c:140,145
1999/0525    
	ulong cdsize; 
1999/0529    
	void *grabbuf; 
1999/0527    
	ulong grablen; 
1999/0422    
	int i; 
 
1999/0423    
	pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067); 
	if (pcidev == nil) { 
1999/0601/sys/src/9/pc/devlml.c:105,1171999/0610/sys/src/9/pc/devlml.c:166,174
1999/0422    
	// Get access to DMA memory buffer 
1999/0529    
	codeData->pamjpg = PADDR(codeData->statCom); 
	codeData->pagrab = PADDR(grabbuf); 
1999/0520    
	for (i = 0; i < NBUF; i++) { 
1999/0517    
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i])); 
		codeData->fragdesc[i].addr = PADDR(&(codeData->frag[i])); 
1999/0422    
		// Length is in double words, in position 1..20 
1999/0518    
		codeData->fragdesc[i].leng = ((sizeof codeData->frag[i]) >> 1) | FRAGM_FINAL_B; 
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/0601/sys/src/9/pc/devlml.c:186,1971999/0610/sys/src/9/pc/devlml.c:243,264
1999/0517    
 
1999/0422    
	c->aux = 0; 
	switch(c->qid.path){ 
1999/0526    
	case Qjcount: 
1999/0610    
	case Qjpg: 
1999/0601    
		// allow one open 
1999/0424    
		if (nopens) 
1999/0610    
		if (jpgopens) 
1999/0424    
			error(Einuse); 
		nopens = 1; 
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    
} 
1999/0601/sys/src/9/pc/devlml.c:200,2091999/0610/sys/src/9/pc/devlml.c:267,281
1999/0518    
lmlclose(Chan *c) { 
 
1999/0422    
	switch(c->qid.path){ 
1999/0526    
	case Qjcount: 
1999/0515    
		nopens = 0; 
1999/0422    
		authclose(c); 
1999/0610    
	case Qjpg: 
		jpgopens = 0; 
		break; 
/*	case Qraw: 
		rawopens = 0; 
		break; 
*/ 
1999/0422    
	} 
1999/0610    
	authclose(c); 
1999/0422    
} 
 
static long 
1999/0601/sys/src/9/pc/devlml.c:215,2221999/0610/sys/src/9/pc/devlml.c:287,297
1999/0513    
 
	case Qdir: 
		return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen); 
1999/0526    
	case Qjcount: 
		return vcount(c, buf, n, off); 
1999/0610    
	case Qjpg: 
		return jpgread(c, buf, n, off); 
/*	case Qraw: 
		return rawread(c, buf, n, off); 
*/ 
1999/0422    
	} 
} 
 
1999/0601/sys/src/9/pc/devlml.c:250,2561999/0610/sys/src/9/pc/devlml.c:325,331
1999/0422    
 
static void 
1999/0424    
lmlintr(Ureg *, void *) { 
1999/0520    
	static count; 
1999/0610    
	ulong fstart, fno; 
1999/0520    
	ulong flags = readl(pciBaseAddr+INTR_STAT); 
1999/0424    
	 
1999/0520    
	if(debug&(DBGINTR)) 
1999/0601/sys/src/9/pc/devlml.c:260,2681999/0610/sys/src/9/pc/devlml.c:335,362
1999/0520    
	writel(0xff000000, pciBaseAddr + INTR_STAT); 
1999/0423    
 
1999/0520    
	if(flags & INTR_JPEGREP) { 
		if ((debug&DBGINTR) || ((debug&DBGINTS) && (count++ % 128) == 0)) 
1999/0515    
			print("MjpgDrv_intrHandler wakeup\n"); 
		wakeup(&sleeper); 
1999/0610    
		vlong thetime; 
 
		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); 
		jpgheader[fno].usec = (ulong)(thetime % 1000000000LL) / 1000; 
		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    
} 
1999/0610/sys/src/9/pc/devlml.c:215,2211999/0819/sys/src/9/pc/devlml.c:215,221 (short | long)
1999/0525    
	} 
1999/0601    
 
	// Interrupt handler 
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf); 
1999/0819    
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf, "lml"); 
1999/0601    
 
1999/0529    
	return; 
1999/0422    
} 
1999/0819/sys/src/9/pc/devlml.c:351,3571999/0909/sys/src/9/pc/devlml.c:351,357 (short | long)
1999/0610    
		} 
		thetime = todget(nil); 
		jpgheader[fno].sec  = (ulong)(thetime / 1000000000LL); 
		jpgheader[fno].usec = (ulong)(thetime % 1000000000LL) / 1000; 
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; 
1999/0909/sys/src/9/pc/devlml.c:7,121999/0915/sys/src/9/pc/devlml.c:7,20 (short | long)
1999/0422    
#include	"io.h" 
 
#include	"devlml.h" 
1999/0915    
#include	"index.h" 
#include	"avctl.h" 
#include	"misc.h" 
 
Medium		*m; 
 
AVctl	*ctl = &ctlinit; 
 
1999/0422    
 
1999/0520    
static void *		pciPhysBaseAddr; 
static ulong		pciBaseAddr; 
1999/0915/sys/src/9/pc/devlml.c:7,201999/1005/sys/src/9/pc/devlml.c:7,12 (short | long)
1999/0422    
#include	"io.h" 
 
#include	"devlml.h" 
1999/0915    
#include	"index.h" 
#include	"avctl.h" 
#include	"misc.h" 
                 
Medium		*m; 
                 
AVctl	*ctl = &ctlinit; 
                 
1999/0422    
 
1999/0520    
static void *		pciPhysBaseAddr; 
static ulong		pciBaseAddr; 
Too many diffs (26 > 25). Stopping.


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