Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/pc/devlml.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname pc/devlml.c 1999/0422
## diff -e /dev/null /n/emeliedump/1999/0422/sys/src/brazil/pc/devlml.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"../port/error.h"
#include	"io.h"

#include	"devlml.h"

// Lml 22 driver

enum{
	Q819,
	Q856,
	Qi22,
	Q060,
	Q067,
	Qstat,
	Qvideo,
	Qjframe,
};

static Dirtab viddir[]={
//	 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,
};

CodeData *	codeData;
MjpgDrv *	mjpgDrv;

static void lmlintr(Ureg *ur, void *arg);

static void
vidreset(void)
{
	ulong regpa;
	int i;

	codeData = (CodeData*)xspanalloc(sizeof(CodeData), BY2PG, 0);
	if (codeData == nil) {
		print("devlml: xspanalloc(%ux, %ux, 0)\n", sizeof(CodeData), BY2PG);
		return;
	}

	print("Installing Motion JPEG driver %s\n", MJPG_VERSION); 
	print("Buffer size %ux\n", sizeof(CodeData)); 

	// 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++) {
		codeData->statCom[i] = PADDR(&(codeData->fragmDescr[i]));
		codeData->statComInitial[i] = codeData->statCom[i];
		codeData->fragmDescr[i].fragmAddress =
			(H33_Fragment *)PADDR(&(codeData->frag[i]));
		// Length is in double words, in position 1..20
		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;
	}
	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);

	print("zr36067 found at %lux\n", lml33Board->pciPhysBaseAddr);

	regpa = upamalloc(lml33Board->pcidev->mem[0].bar & ~0x0F, lml33Board->pcidev->mem[0].size, 0);
	if (regpa == 0) {
		print("lml: failed to map registers\n");
		return;
	}
	lml33Board->pciBaseAddr = KADDR(regpa);

	// make sure the device will respond to mem accesses
	// (pcicmd_master | pcicmd_memory) -- probably superfluous
//	pcicfgw32(lml33Board->pcidev, PciPCR, 0x04 | 0x02);

	// set bus latency -- probably superfluous
//	pcicfgw8(lml33Board->pcidev, PciLTR, 64);

	// Interrupt handler
	intrenable(lml33Board->pcidev->intl, lmlintr, lml33Board, lml33Board->pcidev->tbdf);

	print("LML33 Installed\n"); 
	return; 
}

static Chan*
vidattach(char *spec)
{
	return devattach('V', spec);
}

static int
vidwalk(Chan *c, char *name)
{
	return devwalk(c, name, viddir, nelem(viddir), devgen);
}

static void
vidstat(Chan *c, char *dp)
{
	devstat(c, dp, viddir, nelem(viddir), devgen);
}

static Chan*
vidopen(Chan *c, int omode)
{
	c->aux = 0;
	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
		break;
	}
	return devopen(c, omode, viddir, nelem(viddir), devgen);
}

static void
vidclose(Chan *c)
{
	switch(c->qid.path){
	case Q819:
	case Q856:
	case Qi22:
	case Q060:
	case Q067:
	case Qstat:
	case Qvideo:
	case Qjframe:
		authclose(c);
	}
}

static long
vidread(Chan *c, void *buf, long n, vlong off)
{
	switch(c->qid.path){
	case Q819:
	case Q856:
	case Qi22:
	case Q060:
	case Q067:
		return chipread(c, buf, n, off);
	case Qstat:
		return statread(c, buf, n, off);
	case Qvideo:
	case Qjframe:
		return videoread(c, buf, n, off);
	}
}

static long
vidwrite(Chan *c, void *va, long n, vlong off)
{
}

Dev viddevtab = {
	'V',
	"video",

	vidreset,
	devinit,
	vidattach,
	devclone,
	vidwalk,
	vidstat,
	vidopen,
	devcreate,
	vidclose,
	vidread,
	devbread,
	vidwrite,
	devbwrite,
	devremove,
	devwstat,
};

static void
lmlintr(Ureg *ur, void *arg)
{
	LML33Board *lml33Board = (Lml33Board *)arg;

	
}
.
## diffname pc/devlml.c 1999/0423
## diff -e /n/emeliedump/1999/0422/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0423/sys/src/brazil/pc/devlml.c
218c

.
216d
214c
lmlintr(Ureg *ur, void *)
.
189a

	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);
	}
.
178,180c
		if (off < 0 || off + n > 20 || (off & 0x3) || n != 4) return 0;
		*(long *)buf = readl(pciBaseAddr + off);
		return 4;
.
176a
		return post060read(buf, n, off);
.
175c
		if (off < 0xda || off + n > 0xe0)
			return 0;
		return chipread(BT856Addr, buf, n, off);
.
173a
		if (off < 0 || off + n > 20)
			return 0;
		return chipread(BT819Addr, buf, n, off);
.
170,171c
vidread(Chan *c, void *buf, long n, vlong off) {

.
162d
159d
142,144d
137d
106c
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf);
.
103c
//	pcicfgw8(pcidev, PciLTR, 64);
.
100c
//	pcicfgw32(pcidev, PciPCR, 0x04 | 0x02);
.
96c
	pciBaseAddr = (ulong)KADDR(regpa);
.
91c
	regpa = upamalloc(pcidev->mem[0].bar & ~0x0F, pcidev->mem[0].size, 0);
.
89c
	print("zr36067 found at %lux\n", pciPhysBaseAddr);
.
81,87c
	pciPhysBaseAddr = (void *)(pcidev->mem[0].bar & ~0x0F);
.
74,77d
64c
			(Fragment *)PADDR(&(codeData->frag[i]));
.
46a
	pcidev = pcimatch(nil, PCI_VENDOR_ZORAN, PCI_DEVICE_ZORAN_36067);
	if (pcidev == nil) {
		print("No zr36067 found.\n");
		return;
	}
.
41a
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
.
40a
	microdelay(I2C_DELAY);
}

.
39c
static void
lml33_i2c_pause(void) {
.
31d
28d
19d
16d
## diffname pc/devlml.c 1999/0424
## diff -e /n/emeliedump/1999/0423/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0424/sys/src/brazil/pc/devlml.c
539a
	if(flags & ZR36057_INTR_JPEGREP)
			wakeup(&sleeper);
	return;
.
538a
	// Reset all interrupts from 067
	writel(0xff000000, pciBaseAddr + ZR36057_INTR_STAT);
.
536,537c
lmlintr(Ureg *, void *) {
	ulong flags = readl(pciBaseAddr+ZR36057_INTR_STAT);
	
//  print("MjpgDrv_intrHandler stat=0x%08x\n", flags);
.
510c
		return vwrite(c, buf, n, off);
.
505,507c
		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;
.
503c
		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;
.
501c
		for (i = n; i > 0; i--)
			if (lml33_i2c_wr8(BT856Addr, off++, *buf++) == 0)
				break;
		return n - i;
.
497c
		for (i = n; i > 0; i--)
			if (lml33_i2c_wr8(BT819Addr, off++, *buf++) == 0)
				break;
		return n - i;
.
495c
		if (off < 0 || off + n > 0x20)
.
490,491c
vidwrite(Chan *c, void *va, long n, vlong off) {
	int i;
	uchar *buf = va;
.
485c
		return vread(c, buf, n, off);
.
480,482c
		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;
.
478c
		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;
.
476c
		for (i = 0; i < n; i++) {
			if ((d = lml33_i2c_rd8(BT856Addr, off++)) < 0) break;
			*buf++ = d;
		}
		return n - i;
.
472c
		for (i = 0; i < n; i++) {
			if ((d = lml33_i2c_rd8(BT819Addr, off++)) < 0) break;
			*buf++ = d;
		}
		return n - i;
.
470c
		if (off < 0 || off + n > 0x20)
.
466c
vidread(Chan *c, void *va, long n, vlong off) {
	int i, d;
	uchar *buf = va;
.
444a
		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;
.
441d
381,386d
345a
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, &currentBufferPtr, &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;
}

.
343c
	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,
			&currentBufferPtr, &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;
.
340,341c
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;
.
336,338c
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;
}
.
333c
	return -1;
.
330,331c
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;
.
326,328c
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;
}
.
314c
static int
.
311c
	return lml33_post_write(guest_id, 3, v);
.
303c
static int
.
300c
	return w & 0xFF;
.
298c
	if (w == -1) return -1;
.
279c
static int
.
272,275c
	return lml33_post_idle() == -1;
.
255c
static int
.
223a
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;
}

.
213,218d
210c
		return -1;
.
207,208c
	if (lml33_i2c_wrbyte(addr+1) == 1
	 || lml33_i2c_rdbyte(&msb) == 0){
.
199,204d
196c
		return -1;
.
193,194c
	if (lml33_i2c_wrbyte(addr) == 1
	 || lml33_i2c_wrbyte(sub) == 1) {
.
188d
185c
static int
.
34a
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
};

.
33d
## diffname pc/devlml.c 1999/0428
## diff -e /n/emeliedump/1999/0424/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0428/sys/src/brazil/pc/devlml.c
741c
		return n;
.
738,739c
			break;
		default:
			return 0;
.
736c
		switch (n) {
		case 1:
			writeb(*buf, pciBaseAddr + off);
			break;
		case 2:
			writew(*(short *)buf, pciBaseAddr + off);
			break;
		case 4:
.
726,733c
	case Qreg:
.
699c
		return n;
.
696,697c
			break;
		default:
			return 0;
.
694c
		switch(n) {
		case 1:
			*buf = readb(pciBaseAddr + off);
			break;
		case 2:
			*(short *)buf = readw(pciBaseAddr + off);
			break;
		case 4:
.
683,691c
	case Qreg:
.
653,654c
	case Qreg:
.
626,627c
	case Qreg:
.
258,340d
241,256d
26,27c
	"vidreg",	{Qreg},		0,		0644,
.
16,17c
	Qreg,
.
## diffname pc/devlml.c 1999/0429
## diff -e /n/emeliedump/1999/0428/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0429/sys/src/brazil/pc/devlml.c
619,622c
		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;
.
617c
		if (n != 1 || off < 0xda || off + n > 0xe0)
.
613c
			if (i2c_wr8(BT819Addr, off++, *buf++) == 0)
.
579c
		return 1;
.
575,577c
		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;
.
573c
		if (n != 1)
.
568c
			if ((d = i2c_rd8(BT819Addr, off++)) < 0) break;
.
234c
	i2c_stop();
.
229,231c
	if (i2c_wrbyte(addr) == 1
	 || i2c_wrbyte(sub) == 1
	 || i2c_wrbyte(msb) == 1)
.
227c
	i2c_start();
.
225c
i2c_wr8(uchar addr, uchar sub, uchar msb) {
.
219c
	i2c_stop();
.
213,215c
	if (i2c_wrbyte(addr+1) == 1
	 || i2c_rdbyte(&msb) == 0){
		i2c_stop();
.
211c
	i2c_start();
.
205,207c
	if (i2c_wrbyte(addr) == 1
	 || i2c_wrbyte(sub) == 1) {
		i2c_stop();
.
203c
	i2c_start();
.
199c
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)
.
195c
	i2c_stop();
.
191c
		ack = i2c_wrbyte(bytes[i]);
.
187c
	ack = i2c_wrbyte(sub);
.
184c
	ack = i2c_wrbyte(addr);
.
182c
	i2c_start();
.
178c
i2c_write_bytes(uchar addr, uchar sub, uchar *bytes, long num) {
.
172c
	ack = i2c_rdbit();
.
168c
		i2c_wrbit(v & 0x80);
.
164c
i2c_wrbyte(uchar v) {
.
156c
	ack = i2c_rdbit();
.
153c
		res += i2c_rdbit();
.
146c
i2c_rdbyte(uchar *v) {
.
140c
	i2c_pause();
.
127,128c
	i2c_waitscl();
	i2c_pause();
.
123c
	i2c_pause();
.
117c
i2c_rdbit(void) {
.
112c
		i2c_pause();
.
109,110c
		i2c_waitscl();
		i2c_pause();
.
107c
		i2c_pause();
.
104c
		i2c_pause();
.
101,102c
		i2c_waitscl();
		i2c_pause();
.
99c
		i2c_pause();
.
96c
static void i2c_wrbit(int bit) {
.
93c
	i2c_pause();
.
88,89c
	i2c_waitscl();
	i2c_pause();
.
84c
	i2c_pause();
.
81c
i2c_stop(void) {
.
77c
	i2c_pause();
.
74c
	i2c_pause();
.
70,71c
	i2c_waitscl();
	i2c_pause();
.
67c
i2c_start(void) {
.
55c
i2c_waitscl(void) {
.
49c
i2c_pause(void) {
.
40a
uchar		q856[3];
.
## diffname pc/devlml.c 1999/0430
## diff -e /n/emeliedump/1999/0429/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0430/sys/src/brazil/pc/devlml.c
621a
			if (off & (n-1)) return 0;
.
618a
			if (off & (n-1)) return 0;
.
612c
		if (off < 0 || off + n > 0x400)
.
408,409c
			 && frameHeader.mrkAPP3 == MRK_APP3
			 && strcmp(frameHeader.nm, APP_NAME) == 0) {
.
## diffname pc/devlml.c 1999/0513
## diff -e /n/emeliedump/1999/0430/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0513/sys/src/brazil/pc/devlml.c
704c
	lmlwrite,
.
701,702c
	lmlclose,
	lmlread,
.
697,699c
	lmlwalk,
	lmlstat,
	lmlopen,
.
695c
	lmlattach,
.
693c
	lmlreset,
.
689c
Dev lmldevtab = {
.
683c
	case Qjvideo:
.
641c
	switch(c->qid.path & ~CHDIR){

	case Qdir:
		error(Eperm);

.
637c
lmlwrite(Chan *c, void *va, long n, vlong off) {
.
630c
	case Qjvideo:
.
624c
			v = readl(pciBaseAddr + off);
			*(long *)buf = v;
print("reading %lux at %lux (%lux)\n", v, pciBaseAddr + off, off);
.
580c
	switch(c->qid.path & ~CHDIR){

	case Qdir:
		return devdirread(c, (char *)buf, n, lmldir, nelem(lmldir), devgen);

.
578a
	long off = voff;
	long v;
.
576c
lmlread(Chan *c, void *va, long n, vlong voff) {
.
569c
	case Qjvideo:
.
563c
lmlclose(Chan *c)
.
559c
	return devopen(c, omode, lmldir, nelem(lmldir), devgen);
.
544c
	case Qjvideo:
.
536c
lmlopen(Chan *c, int omode)
.
532c
	devstat(c, dp, lmldir, nelem(lmldir), devgen);
.
530c
lmlstat(Chan *c, char *dp)
.
526c
	return devwalk(c, name, lmldir, nelem(lmldir), devgen);
.
524c
lmlwalk(Chan *c, char *name)
.
518c
lmlattach(char *spec)
.
513d
501a
	print(", mapped at 0x%.8lux\n", pciBaseAddr);
.
494c
	print("zr36067 found at 0x%.8lux", pciPhysBaseAddr);
.
475c
	print("Buffer at 0x%.8lux, size 0x%.8ux\n", codeData, sizeof(CodeData)); 
.
465d
458c
lmlreset(void)
.
37,40c
int		singleFrame;
int		bufferPrepared;
int		hdrPos;
int		nopens;
.
35c
int		frameNo;
.
32,33c
int		currentBuffer;
int		currentBufferLength;
.
21,26c
static Dirtab lmldir[]={
//	 name,		 qid,		size,		mode
	"lml819",	{Q819},		0,		0644,
	"lml856",	{Q856},		0,		0644,
	"lmlreg",	{Qreg},		0,		0644,
	"jvideo",	{Qjvideo},	0,		0666,
.
17c
	Qjvideo,
.
13a
	Qdir,
.
## diffname pc/devlml.c 1999/0514
## diff -e /n/emeliedump/1999/0513/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0514/sys/src/brazil/pc/devlml.c
688a
print("writing %lux to %lux (%lux)\n", *(long *)buf, pciBaseAddr + off, off);
.
647a
	long off = voff;
.
645c
lmlwrite(Chan *c, void *va, long n, vlong voff) {
.
## diffname pc/devlml.c 1999/0515
## diff -e /n/emeliedump/1999/0514/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0515/sys/src/brazil/pc/devlml.c
733,734c
	if(flags & ZR36057_INTR_JPEGREP) {
		if(debug&(DBGREAD|DBGWRIT))
			print("MjpgDrv_intrHandler wakeup\n");
		wakeup(&sleeper);
	}
.
728c
	if(debug&(DBGREAD|DBGWRIT))
		print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags);
.
690c
			if (off & 0x3)
				return 0;
.
686a
			if (off & 0x1)
				return 0;
.
680c
		if (off < 0 || off + n > 0x400)
.
661c
		return i;
.
630,632c
			*(long *)buf = readl(pciBaseAddr + off);
.
616a
	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;
.
594c
		return i;
.
580d
570a
		nopens = 0;
.
568a
	case Qmap:
		authclose(c);
		break;
.
542a
	case Qmap:
.
513a
	lmlmap.pci = pciBaseAddr;
	lmlmap.dma = PADDR(codeData);
	lmlmap.codedata = (ulong)codeData;

.
365c
	//pr_debug&DBGREGS("return %d %d\n",cpcount,retcount);
.
324a
		if(debug&DBGREAD)
			pprint("devlml::wokeup\n");
.
322a
		if(debug&DBGREAD)
			pprint("devlml::sleep\n");
.
318a
		if(debug&DBGREAD)
			pprint("devlml::prepareBuffer\n");
.
309a
		if(debug&DBGREAD)
			pprint("devlml::first read\n");
.
306c
	if(debug&DBGREAD)
		pprint("devlml::vread() count=%ld pos=%lld\n", count, pos);
.
232a
		if (debug&DBGREGS) pprint("i2c_rd8, failure 2\n");
.
224a
		if (debug&DBGREGS) pprint("i2c_rd8, failure 1\n");
.
49a
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;
}

.
43a
struct {
	ulong pci;
	ulong dma;
	ulong codedata;
} lmlmap;

.
26a
	"lmlmap",	{Qmap},		0,		0444,
.
17a
	Qmap,
.
10a
#define DBGREGS 0x1
#define DBGREAD 0x2
#define DBGWRIT 0x4
int debug = DBGREAD|DBGWRIT;

.
## diffname pc/devlml.c 1999/0517
## diff -e /n/emeliedump/1999/0515/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0517/sys/src/brazil/pc/devlml.c
752c
		if (off < 0 || off + n >= 0x20)
.
710c
			if (off + i >= sizeof lmlmap)
.
642a
		intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf);
.
641a

		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]);
		}
.
622a
	int i;

.
568c
		codeData->fragdesc[i].leng = (FRAGSIZE >> 1) | FRAGM_FINAL_B;
.
565,566c
		codeData->fragdesc[i].addr = PADDR(&(codeData->frag[i]));
.
563c
		codeData->statCom[i] = PADDR(&(codeData->fragdesc[i]));
.
357c
		*bufferPtr = (void*)this->fragdesc[bufferNo].addr;
.
333c
    return this->fragdesc[bufferNo].leng;
.
115,116c
		pprint("%.8lux (%.8lux) -->       %.2ux\n",
			a, (ulong)a-pciBaseAddr, v);
.
104,105c
		pprint("%.8lux (%.8lux) -->     %.4ux\n",
			a, (ulong)a-pciBaseAddr, v);
.
93,94c
		pprint("%.8lux (%.8lux) --> %.8lux\n",
			a, (ulong)a-pciBaseAddr, v);
.
82,83c
		pprint("%.8lux (%.8lux) <--       %.2ux\n",
			a, (ulong)a-pciBaseAddr, v);
.
74,75c
		pprint("%.8lux (%.8lux) <--     %.4ux\n",
			a, (ulong)a-pciBaseAddr, v);
.
66,67c
		pprint("%.8lux (%.8lux) <-- %.8lux\n",
			a, (ulong)a-pciBaseAddr, v);
.
51,56d
32,33c
	"lmlreg",	{Qreg},		0x400,		0644,
	"lmlmap",	{Qmap},		sizeof lmlmap,	0444,
.
17a
struct {
	ulong pci;
	ulong dma;
	ulong codedata;
} lmlmap;

.
14c
int debug = DBGREAD|DBGWRIT|DBGREGS;
.
## diffname pc/devlml.c 1999/0518
## diff -e /n/emeliedump/1999/0517/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0518/sys/src/brazil/pc/devlml.c
798a
			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);
.
784c
		if (off < 0 || off + n >= 0x400)
.
741a
	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;
.
724c
		if (off < 0 || off + n >= 0x400)
.
663a
	case Qbuf:
.
657,658c
lmlclose(Chan *c) {

.
650d
644,648d
629a
	case Qbuf:
.
620,622c
lmlopen(Chan *c, int omode) {
.
595c
	lmlmap.statcom = PADDR(codeData->statCom);
.
567c
		codeData->fragdesc[i].leng = ((sizeof codeData->frag[i]) >> 1) | FRAGM_FINAL_B;
.
564d
560,561d
529c
		prepareBuffer(currentBuffer);
.
473c
		getBuffer(currentBuffer, &currentBufferPtr, &frameNo);
.
469c
		while((currentBuffer = getProcessedBuffer()) == -1)
.
406c
		currentBufferLength = getBuffer(currentBuffer,
.
402c
		while((currentBuffer = getProcessedBuffer()) == -1)
.
396c
		prepareBuffer(currentBuffer);
.
354,360c
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;
.
347c
		if (lastBuffer == l)
.
345c
		if (codeData->statCom[lastBuffer] & STAT_BIT)
.
339,341c
getProcessedBuffer(void){
	static lastBuffer = NBUF-1;
	int l = lastBuffer;
.
330,335c
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;
.
39a
	"lmlbuf",	{Qbuf},		0,		0644,
.
29a
	Qbuf,
.
20c
	ulong statcom;
.
## diffname pc/devlml.c 1999/0519
## diff -e /n/emeliedump/1999/0518/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0519/sys/src/brazil/pc/devlml.c
14c
int debug = DBGREAD|DBGWRIT;
.
## diffname pc/devlml.c 1999/0520
## diff -e /n/emeliedump/1999/0519/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0520/sys/src/brazil/pc/devlml.c
873,874c
	if(flags & INTR_JPEGREP) {
		if ((debug&DBGINTR) || ((debug&DBGINTS) && (count++ % 128) == 0))
.
871c
	writel(0xff000000, pciBaseAddr + INTR_STAT);
.
867c
	if(debug&(DBGINTR))
.
865c
	static count;
	ulong flags = readl(pciBaseAddr+INTR_STAT);
.
773,774c
		for (i = 0; i < n; i++)
			if (i2c_wr8(BT819Addr, off + i, *buf++) == 0)
.
769a
	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;
.
675a
	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;
.
650a
	case Q060:
.
639a
		state = New;
.
621a
	case Q060:
.
561c
	for (i = 0; i < NBUF; i++) {
.
520,535d
514,518d
503,512c
			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;
.
457,501c
	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);
.
452,455c
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;
.
449a
*/
.
414c
			pprint("Frames out of sequence: %d %d\n", prevFrame, frameNo);
.
412c
		// pprint("getBufffer %d -> %d 0x%x %d\n",currentBuffer, currentBufferLength, currentBufferPtr, frameNo);
.
407,408c
		currentBufferLength = getBuffer(currentBuffer, &frameNo);
		currentBufferPtr = (void*)(&codeData->frag[currentBuffer]);
.
366a
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
.
359d
356c
getBuffer(int i, int* frameNo) {
.
331a
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
.
330a
/*
 * 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
.
264c
	for (i = 0; i < num; i++) {
.
241c
	for (i = 0; i < 8; i++) {
.
225c
	for (i = 0; i < 8; i++) {
.
213c
	writel(I2C_SDA, pciBaseAddr + I2C_BUS);
.
205,206c
	bit = readl(pciBaseAddr+I2C_BUS);
	if (bit & I2C_SDA){
.
200c
	writel(I2C_SDA|I2C_SCL, pciBaseAddr + I2C_BUS);
.
196c
	writel(I2C_SDA, pciBaseAddr + I2C_BUS);
.
185c
		writel(0, pciBaseAddr + I2C_BUS);
.
182c
		writel(I2C_SCL, pciBaseAddr + I2C_BUS);
.
180c
		writel(0, pciBaseAddr + I2C_BUS); // clr data
.
177c
		writel(I2C_SDA, pciBaseAddr + I2C_BUS);
.
174c
		writel(I2C_SDA|I2C_SCL, pciBaseAddr + I2C_BUS);
.
172c
		writel(I2C_SDA, pciBaseAddr + I2C_BUS); // set data
.
166c
	writel(I2C_SCL|I2C_SDA, pciBaseAddr + I2C_BUS);
.
161c
	writel(I2C_SCL, pciBaseAddr + I2C_BUS);
.
157c
	writel(0, pciBaseAddr + I2C_BUS);
.
150c
	writel(0, pciBaseAddr + I2C_BUS);
.
147c
	writel(I2C_SCL, pciBaseAddr + I2C_BUS);
.
143c
	writel(I2C_SCL|I2C_SDA, pciBaseAddr + I2C_BUS);
.
133,137c
	for (i = 0; i < I2C_TIMEOUT; i++)
		if (readl(pciBaseAddr + I2C_BUS) & I2C_SCL)
			return;
	error(Eio);
.
131d
57a
State		state = New;
.
47a
typedef enum {
	New,
	Header,
	Body,
	Error,
} State;

.
36a
	"lml060",	{Q060},		0x400,		0644,
.
25a
	Q060,
.
15a
#define DBGREGS 0x01
#define DBGREAD 0x02
#define DBGWRIT 0x04
#define DBG819	0x08
#define DBGINTR	0x10
#define DBGINTS	0x20

int debug = DBGREAD;

.
11,14c
static void *		pciPhysBaseAddr;
static ulong		pciBaseAddr;
static Pcidev *		pcidev;
.
## diffname pc/devlml.c 1999/0521
## diff -e /n/emeliedump/1999/0520/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0521/sys/src/brazil/pc/devlml.c
826a
		for (i = 0; i < NBUF; i++)
			codeData->statCom[i] = PADDR(&(codeData->fragdesc[i]));
.
820,825d
815a
	case Qjvideo:
.
814d
803a
	int i;
.
714a
			if (singleFrame) {
				state = Error;
				return nbytes - count;
			}
.
705d
699c
			i = fragsize - bufpos;
			if (count < i) {
.
694c
				return nbytes - count;
.
686c
				return nbytes - count;
.
552,637d
550d
542a
			if (singleFrame) {
				state = Error;
				return nbytes - count;
			}
.
530c
			if (count < i) {
.
525c
			bufptr = codeData->frag[curbuf].fb + 2;
.
510c
			state = Header;
.
501a
			if (fragsize <= 0 || fragsize > sizeof(Fragment)) {
				pprint("Wrong sized fragment, %d (ignored)\n",
					fragsize);
				prepareBuffer(curbuf);
				break;
			}
.
498,500c
			if (frameno != (frameprev + 1) % 256)
				pprint("Frame out of sequence: %d %d\n",
					frameprev, frameno);
.
492c
			while ((curbuf = getProcessedBuffer()) == -1)
.
71,72d
65,67d
22c
int debug = 0;
.
## diffname pc/devlml.c 1999/0522
## diff -e /n/emeliedump/1999/0521/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0522/sys/src/brazil/pc/devlml.c
701a

// 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);
//
.
649a
// LMLSEG
	Physseg segbuf;
	Physseg segreg;
//
.
## diffname pc/devlml.c 1999/0525
## diff -e /n/emeliedump/1999/0522/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0525/sys/src/brazil/pc/devlml.c
979a
#endif
.
906a
#ifdef MEMMAP
.
898a
#endif
.
897a
#ifdef MEMMAP
.
889a
#endif
.
804a
#ifdef MEMMAP
.
796a
#endif
.
795a
#ifdef MEMMAP
.
786a
#endif
.
778a
#ifdef MEMMAP
.
758a
#endif
.
751a
#ifdef MEMMAP
.
722c
	if (addphysseg(&segreg) == -1) {
		print("lml: physsegment: lmlmjpg\n");
		return;
	}
.
713,714c
	segbuf.size = cdsize;
	if (addphysseg(&segbuf) == -1) {
		print("lml: physsegment: lmlmjpg\n");
		return;
	}
.
705a
#endif
.
702a
#ifdef MEMMAP
.
671a
	codeData->physaddr = PADDR(&(codeData->statCom[0]));
.
668c
	print("Buffer at 0x%.8lux, size 0x%.8lux\n", codeData, cdsize); 
.
663c
		print("devlml: xspanalloc(%lux, %ux, 0)\n", cdsize, BY2PG);
.
661c
	cdsize = (sizeof(CodeData) + BY2PG - 1) & ~(BY2PG - 1);
	codeData = (CodeData*)xspanalloc(cdsize, BY2PG, 0);
.
654a
	ulong cdsize;
.
434a
#endif
.
102,112d
85a
ulong
readl(ulong a) {
	ulong v;

	v = *(ulong*)a;
	if (debug&DBGREGS)
		pprint("%.8lux (%.8lux) --> %.8lux\n",
			a, (ulong)a-pciBaseAddr, v);
	return v;
}
.
77a

#ifndef MEMMAP
#define writel(v, a) *(ulong *)(a) = (v)
#define readl(a) *(ulong*)(a)
#else
.
51a
#endif
.
45a
#ifdef MEMMAP
.
39a
#endif
.
33a
#ifdef MEMMAP
.
30a
#endif
.
25a
#ifdef MEMMAP
.
## diffname pc/devlml.c 1999/0526
## diff -e /n/emeliedump/1999/0525/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0526/sys/src/brazil/pc/devlml.c
938,1013d
936a
	case Qjcount:
.
935d
928,930d
922a
	case Qjcount:
		return vcount(c, buf, n, off);
.
832,919d
822,824d
814a
	case Qjcount:
.
803,812d
784a
	case Qjcount:
.
774,782d
745,746d
717,723d
707,713d
685c
	codeData->physaddr = PADDR(codeData->statCom);
.
664d
661d
643c
				pprint("Sending buffer %d\n", curbuf);
.
641c
			codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf]));
.
580,584c
			curbuf = getbuffer();
.
553c
			codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf]));
.
511c
				codeData->statCom[curbuf] = PADDR(&(codeData->fragdesc[curbuf]));
.
504c
			if (!singleFrame && frameno != (frameprev + 1) % 256)
.
498,500c
			curbuf = getbuffer();
			frameNo = codeData->statCom[curbuf] >> 24;
			fragsize = (codeData->statCom[curbuf] & 0x00ffffff)>>1;
.
352,480d
245,348c
	// reads always return one byte: the next available buffer number
	if (nbytes <= 0) return 0;
	*p = getbuffer();
.
240,243c
static long
vcount(Chan *, void *va, long nbytes, vlong) {
	char *p = (char *)va;
.
232,237c
	return 0;
.
216,230c
	for (;;) {
		last = (last+1) % NBUF;
		if (codeData->statCom[last] & STAT_BIT)
			return last;
		if (last == l)
			sleep(&sleeper, return0, 0);
.
212,214c
getbuffer(void){
	static last = NBUF-1;
	int l = last;
.
97,210d
88,95d
85d
59a
	"jcount",	{Qjcount},	0,		0444,
.
50,57d
45a
	Qjcount,
.
36,43d
26,33d
15,20c
#define DBGREAD 0x01
#define DBGWRIT 0x02
#define DBGINTR	0x04
#define DBGINTS	0x08
.
## diffname pc/devlml.c 1999/0527
## diff -e /n/emeliedump/1999/0526/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0527/sys/src/brazil/pc/devlml.c
330c
		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");
.
283c
	print("MJPG buffer at 0x%.8lux, size 0x%.8lux\n", codeData, cdsize); 
	print("Grab buffer at 0x%.8lux, size 0x%.8lux\n", grabpa, grablen); 
.
281a
	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);

.
268a
	ulong *grabpa;
	ulong grablen;
.
266a
	Physseg seggrab;
.
## diffname pc/devlml.c 1999/0529
## diff -e /n/emeliedump/1999/0527/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0529/sys/src/brazil/pc/devlml.c
356c
	return;
.
350c
	seggrab.pa = PADDR(grabbuf);
.
299c
	codeData->pamjpg = PADDR(codeData->statCom);
	codeData->pagrab = PADDR(grabbuf);
.
295c
	print("Grab buffer at 0x%.8lux, size 0x%.8lux\n", grabbuf, grablen); 
.
292a
	memset(grabbuf, 0x33, grablen);

.
291d
285,287c
	grablen = GRABDATASIZE;
	grabbuf = xspanalloc(grablen, BY2PG, 0);
	if (grabbuf == nil) {
.
278c
	cdsize = CODEDATASIZE;
.
270c
	void *grabbuf;
.
## diffname pc/devlml.c 1999/0531
## diff -e /n/emeliedump/1999/0529/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0531/sys/src/brazil/pc/devlml.c
123c
			thetime = todget(nil);
.
## diffname pc/devlml.c 1999/0601
## diff -e /n/emeliedump/1999/0531/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0601/sys/src/brazil/pc/devlml.c
436,443c
	error(Eperm);
	return 0;
.
432,434c
lmlwrite(Chan *, void *, long, vlong) {
.
423,425d
406,407d
391,396d
387a
		// allow one open
.
385,386d
381d
357a

	// Interrupt handler
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf);

.
323,325d
309,310d
299d
292,293d
89,259d
54,60d
51,52d
40,46d
33,34d
26,27d
## diffname pc/devlml.c 1999/0610
## diff -e /n/emeliedump/1999/0601/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0610/sys/src/brazil/pc/devlml.c
263,265c
		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);
.
253c
	ulong fstart, fno;
.
218,219c
	case Qjpg:
		return jpgread(c, buf, n, off);
/*	case Qraw:
		return rawread(c, buf, n, off);
*/
.
206a
	authclose(c);
.
203,205c
	case Qjpg:
		jpgopens = 0;
		break;
/*	case Qraw:
		rawopens = 0;
		break;
*/
.
194a
/*	case Qraw:
		// allow one open
		if (rawopens)
			error(Einuse);
		rawopens = 1;
		rawframeno = 0;
		break;
*/
.
193c
		jpgopens = 1;
		jpgframeno = 0;
		prepbuf();
.
191c
		if (jpgopens)
.
189c
	case Qjpg:
.
114a
	prepbuf();

.
108,113d
81d
71a
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
.
68a
/*
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;
}
*/

.
63,66c
	// 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;
.
60,61c
jpgread(Chan *, void *va, long nbytes, vlong) {
	int bufno;
.
54c
			sleep(&sleepjpg, return0, 0);
.
39c
int		jpgopens;
//int		rawopens;
.
37c
Rendez		sleepjpg;
//Rendez		sleepraw;
.
35a
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
	}
};

.
34c
static CodeData *	codeData;
.
30,31c
//	 name,		qid,	size,	mode
	"lmljpg",	{Qjpg},	0,	0444,
//	"lmlraw",	{Qraw},	0,	0444,
.
26c
	Qjpg,
//	Qraw,
.
## diffname pc/devlml.c 1999/0819
## diff -e /n/emeliedump/1999/0610/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0819/sys/src/brazil/pc/devlml.c
218c
	intrenable(pcidev->intl, lmlintr, nil, pcidev->tbdf, "lml");
.
## diffname pc/devlml.c 1999/0909
## diff -e /n/emeliedump/1999/0819/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0909/sys/src/brazil/pc/devlml.c
354c
		jpgheader[fno].nsec = (ulong)(thetime % 1000000000LL);
.
## diffname pc/devlml.c 1999/0915
## diff -e /n/emeliedump/1999/0909/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/0915/sys/src/brazil/pc/devlml.c
9a
#include	"index.h"
#include	"avctl.h"
#include	"misc.h"

Medium		*m;

AVctl	*ctl = &ctlinit;

.
## diffname pc/devlml.c 1999/1005
## diff -e /n/emeliedump/1999/0915/sys/src/brazil/pc/devlml.c /n/emeliedump/1999/1005/sys/src/brazil/pc/devlml.c
10,17d
## diffname pc/devlml.c 2000/0716
## diff -e /n/emeliedump/1999/1005/sys/src/brazil/pc/devlml.c /n/emeliedump/2000/0716/sys/src/9/pc/devlml.c
338a

		if(debug&(DBGINTR))
			print("MjpgDrv_intrHandler stat=0x%.8lux\n", flags);
.
331,333d
20c
int debug = -1;
.
## diffname pc/devlml.c 2001/0221
## diff -e /n/emeliedump/2000/0716/sys/src/9/pc/devlml.c /n/emeliedump/2001/0221/sys/src/9/pc/devlml.c
20c
int debug = 0;
.
## diffname pc/devlml.c 2001/0527
## diff -e /n/emeliedump/2001/0221/sys/src/9/pc/devlml.c /n/emeliedump/2001/0527/sys/src/9/pc/devlml.c
20c
int debug = -1;
.
## diffname pc/devlml.c 2001/0630
## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/devlml.c /n/emeliedump/2001/0630/sys/src/9/pc/devlml.c
312d
286,287c
	switch((ulong)c->qid.path){
.
278d
269c
	switch((ulong)c->qid.path){
.
245c
	switch((ulong)c->qid.path){
.
238c
	return devstat(c, db, n, lmldir, nelem(lmldir), devgen);
.
235,236c
static int
lmlstat(Chan *c, uchar *db, int n)
.
232c
	return devwalk(c, nc, name, nname, lmldir, nelem(lmldir), devgen);
.
229,230c
static Walkqid*
lmlwalk(Chan *c, Chan *nc, char **name, int nname)
.
208,209c
	kstrdup(&seggrab.name, "lmlgrab");
.
197,198c
	kstrdup(&segreg.name, "lmlregs");
.
186,187c
	kstrdup(&segbuf.name, "lmlmjpg");
.
31,33c
	".",		{Qdir, 0, QTDIR},	0,	DMDIR|0555,
	"lmljpg",	{Qjpg},			0,	0444,
//	"lmlraw",	{Qraw},			0,	0444,
.
## diffname pc/devlml.c 2001/1012
## diff -e /n/emeliedump/2001/0630/sys/src/9/pc/devlml.c /n/emeliedump/2001/1012/sys/src/9/pc/devlml.c
143a
	if(isaconfig("lml", 0, &isa) == 0) {
		if (debug) print("lml not in plan9.ini\n");
		return;
	}
.
15,16c
#define DBGREAD	0x01
#define DBGWRIT	0x02
.
## diffname pc/devlml.c 2001/1019
## diff -e /n/emeliedump/2001/1012/sys/src/9/pc/devlml.c /n/emeliedump/2001/1019/sys/src/9/pc/devlml.c
162c
		print("devlml: xalloc(%lux, %ux, 0)\n", grablen, BY2PG);
.
160c
	grabbuf = (void*)(((ulong*)xalloc(grablen+ BY2PG) +BY2PG-1)&~(BY2PG-1));
.
155c
		print("devlml: xalloc(%lux, %ux, 0)\n", cdsize, BY2PG);
.
153c
	codeData = (CodeData*)(((ulong*)xalloc(cdsize+ BY2PG) +BY2PG-1)&~(BY2PG-1));
.
## diffname pc/devlml.c 2001/1026
## diff -e /n/emeliedump/2001/1019/sys/src/9/pc/devlml.c /n/emeliedump/2001/1026/sys/src/9/pc/devlml.c
166c
	print("Installing Motion JPEG driver %s, irq %d\n", MJPG_VERSION, pcidev->intl); 
.
160c
	grabbuf = (void*)(((ulong)xalloc(grablen+ BY2PG) +BY2PG-1)&~(BY2PG-1));
.
153c
	codeData = (CodeData*)(((ulong)xalloc(cdsize+ BY2PG) +BY2PG-1)&~(BY2PG-1));
.
142a
	ISAConf isa;
.
## diffname pc/devlml.c 2001/1027
## diff -e /n/emeliedump/2001/1026/sys/src/9/pc/devlml.c /n/emeliedump/2001/1027/sys/src/9/pc/devlml.c
161c
	grabbuf = (void*)(((ulong)xalloc(grablen+ BY2PG) + BY2PG-1) & ~(BY2PG-1));
.
154c
	codeData = (CodeData*)(((ulong)xalloc(cdsize+ BY2PG) + BY2PG-1) & ~(BY2PG-1));
.
64c
Rendez	sleepjpg;
.
## diffname pc/devlml.c 2001/1101
## diff -e /n/emeliedump/2001/1027/sys/src/9/pc/devlml.c /n/emeliedump/2001/1101/sys/src/9/pc/devlml.c
351,353c
		jpgheader[fno].ftime  = todget(nil);
.
334d
59c
		-1, 0, 0,  0
.
55c
		-1, 0, 0,  0
.
51c
		-1, 0, 0,  0
.
47c
		-1, 0, 0,  0
.
20c
int debug = 0;
.
## diffname pc/devlml.c 2001/1102
## diff -e /n/emeliedump/2001/1101/sys/src/9/pc/devlml.c /n/emeliedump/2001/1102/sys/src/9/pc/devlml.c
217a

	iprint("%.8uX: %.8uX\n", pciBaseAddr + INTR_STAT,
			*((unsigned long *)(pciBaseAddr + INTR_STAT)));
.
152a

.
143a
	uchar ipin, intl;
.
## diffname pc/devlml.c 2001/1106
## diff -e /n/emeliedump/2001/1102/sys/src/9/pc/devlml.c /n/emeliedump/2001/1106/sys/src/9/pc/devlml.c
358,359c
		jpgheader->frameSeqNo = codeData->statCom[fno] >> 24;
		jpgheader->frameNo = jpgframeno;
.
355,356c
		jpgheader = (FrameHeader *)codeData->frag[fno].hdr;
		jpgheader->ftime  = todget(nil);
		jpgheader->frameSize =
.
333a
	FrameHeader *jpgheader;
.
221,223d
144d
129c
		codeData->fragdesc[i].leng = (FRAGSIZE >> 1) | FRAGM_FINAL_B;
		memmove(codeData->frag[i].hdr, &jpgheader, sizeof(FrameHeader)-2);
.
127c
		codeData->fragdesc[i].addr = PADDR(codeData->frag[i].fb);
.
96,97c
		memmove(va, jpgheader, sizeof(FrameHeader));
		return sizeof(FrameHeader);
.
94a
	jpgheader = (FrameHeader*)codeData->frag[bufno].hdr;
.
90a
	FrameHeader *jpgheader;
.
43,60c
static FrameHeader	jpgheader = {
	MRK_SOI, MRK_APP3, (sizeof(FrameHeader)-4) << 8,
	{ 'L', 'M', 'L', '\0'},
	-1, 0, 0,  0
.
## diffname pc/devlml.c 2001/1107
## diff -e /n/emeliedump/2001/1106/sys/src/9/pc/devlml.c /n/emeliedump/2001/1107/sys/src/9/pc/devlml.c
341,346c
		if (jpgopens && jpgmode == OREAD){
			jpgheader = (FrameHeader *)(codeData->frag[fno].hdr+2);
			jpgheader->frameNo = jpgframeno;
			jpgheader->ftime  = todget(nil);
			jpgheader->frameSize =
				(codeData->statCom[fno] & 0x00ffffff) >> 1;
			jpgheader->frameSeqNo = codeData->statCom[fno] >> 24;
		}
.
281,284c
		return jpgread(c, buf, n, off, 1);
	case Qraw:
		return jpgread(c, buf, n, off, 0);
.
265,268d
262a
	case Qraw:
.
246,253d
243a
		jpgmode = omode;
.
238a
	case Qraw:
.
118c
		memmove(codeData->frag[i].hdr+2, &jpgheader, sizeof(FrameHeader)-2);
.
94,106d
81,82c
	while ((bufno = getbuffer(nil)) == 0 && dosleep)
		sleep(&sleepjpg, getbuffer, 0);
	if (--bufno < 0)
		return 0;

	jpgheader = (FrameHeader*)(codeData->frag[bufno].hdr+2);
.
75c
jpgread(Chan *, void *va, long nbytes, vlong, int dosleep) {
.
69c
			return 0;
.
67c
			return last + 1;
.
60c
getbuffer(void *){
.
53a
int		jpgmode;
.
33c
	"lmlraw",	{Qraw},			0,	0444,
.
27c
	Qraw,
.
## diffname pc/devlml.c 2001/1108
## diff -e /n/emeliedump/2001/1107/sys/src/9/pc/devlml.c /n/emeliedump/2001/1108/sys/src/9/pc/devlml.c
323,331c
		statcom = lml->codedata->statCom[fno];
		jpgheader = (FrameHeader *)(lml->codedata->frag[fno].hdr+2);
		jpgheader->frameNo = lml->jpgframeno;
		jpgheader->ftime  = todget(nil);
		jpgheader->frameSize = (statcom & 0x00ffffff) >> 1;
		jpgheader->frameSeqNo = statcom >> 24;
		wakeup(&lml->sleepjpg);
.
313,315c
			lml->jpgframeno++;
			fno = lml->jpgframeno & 0x00000003;
			if (lml->codedata->statCom[fno] & STAT_BIT)
.
311c
		fstart = lml->jpgframeno & 0x00000003;
.
304c
	writel(0xff000000, lml->pciBaseAddr + INTR_STAT);
.
302c
	ulong fstart, fno, flags, statcom;
	LML *lml;

	lml = x;
	flags = readl(lml->pciBaseAddr+INTR_STAT);
.
298,300c
lmlintr(Ureg *, void *x) {
.
263,266c
	case Qctl1:
		i++;
	case Qctl0:
		if (i >= nlml)
			error(Eio);
		lml = lmls+i;
		len = snprint(lmlinfo, sizeof lmlinfo, "lml%djpg	lml%draw\nlml%d.regs	0x%lux	0x%ux\nlml%d.mjpg	0x%lux	0x%ux\n",
			i, i,
			i, lml->pcidev->mem[0].bar & ~0x0F, lml->pcidev->mem[0].size,
			i, PADDR(lml->codedata), Codedatasize);
		if (voff > len)
			return 0;
		if (n > len - voff)
			n = len - voff;
		memmove(va, lmlinfo+voff, n);
		return n;
	case Qjpg1:
		i++;
	case Qjpg0:
		if (i >= nlml)
			error(Eio);
		return jpgread(lmls+i, buf, n, off, 1);
	case Qraw1:
		i++;
	case Qraw0:
		if (i >= nlml)
			error(Eio);
		return jpgread(lmls+i, buf, n, off, 0);
.
259a
	i = 0;
.
258a
	LML *lml;
	static char lmlinfo[1024];
	int len;
.
256a
	int i;
.
248,250c
	case Qjpg1:
	case Qraw1:
		i++;
	case Qjpg0:
	case Qraw0:
		lmls[i].jpgopens = 0;
.
246a
	i = 0;
.
245a
	int i;
.
235,238c
		lml->jpgopens = 1;
		lml->jpgframeno = 0;
		prepbuf(lml);
.
233c
		if (i >= nlml)
			error(Eio);
		lml = lmls+i;
		if (lml->jpgopens)
.
230,231c
	case Qctl1:
		i++;
	case Qctl0:
		if (i >= nlml)
			error(Eio);
		break;
	case Qjpg1:
	case Qraw1:
		i++;
	case Qjpg0:
	case Qraw0:
.
228a
	i = 0;
.
227a
	if (omode != OREAD)
		error(Eperm);
.
226a
	int i;
	LML *lml;
.
168,203d
163,166c
		// Interrupt handler
		intrenable(pcidev->intl, lmlintr, lml, pcidev->tbdf, "lml");
.
161c
		memset(&segbuf, 0, sizeof(segbuf));
		segbuf.attr = SG_PHYSICAL;
		sprint(name, "lml%d.regs", nlml);
		kstrdup(&segbuf.name, name);
		segbuf.pa = (ulong)regpa;
		segbuf.size = pcidev->mem[0].size;
		if (addphysseg(&segbuf) == -1) {
			print("lml: physsegment: %s\n", name);
			return;
		}
.
159c
		memset(&segbuf, 0, sizeof(segbuf));
		segbuf.attr = SG_PHYSICAL;
		sprint(name, "lml%d.mjpg", nlml);
		kstrdup(&segbuf.name, name);
		segbuf.pa = PADDR(lml->codedata);
		segbuf.size = Codedatasize;
		if (addphysseg(&segbuf) == -1) {
			print("lml: physsegment: %s\n", name);
			return;
		}
.
157c
		regpa = upamalloc(pcidev->mem[0].bar & ~0x0F, pcidev->mem[0].size, 0);
		if (regpa == 0) {
			print("lml: failed to map registers\n");
			return;
		}
		lml->pciBaseAddr = (ulong)KADDR(regpa);
		print(", mapped at 0x%.8lux\n", lml->pciBaseAddr);
.
153,155c
		print("zr36067 found at 0x%.8lux", pcidev->mem[0].bar & ~0x0F);
.
149,151c
		prepbuf(lml);
.
142,147c
		// Get access to DMA memory buffer
		lml->codedata->pamjpg = PADDR(lml->codedata->statCom);
.
135,140c
		print("Installing Motion JPEG driver %s, irq %d\n", MJPG_VERSION, pcidev->intl); 
		print("MJPG buffer at 0x%.8lux, size 0x%.8ux\n", lml->codedata, Codedatasize); 
.
126,133c
	pcidev = nil;
	
	for (nlml = 0; nlml < NLML && (pcidev = pcimatch(pcidev, VENDOR_ZORAN, ZORAN_36067)); nlml++){
		if(isaconfig("lml", nlml, &isa) == 0) {
			if (debug) print("lml %d not in plan9.ini\n", nlml);
			break;
		}
		lml = &lmls[nlml];
		lml->pcidev = pcidev;
		lml->codedata = (CodeData*)(((ulong)xalloc(Codedatasize+ BY2PG) + BY2PG-1) & ~(BY2PG-1));
		if (lml->codedata == nil) {
			print("devlml: xalloc(%ux, %ux, 0)\n", Codedatasize, BY2PG);
			return;
		}
.
124a
	char name[32];
	Pcidev *pcidev;
	LML *lml;
.
121,123d
118,119d
109,110c
		lml->codedata->fragdesc[i].leng = (FRAGSIZE >> 1) | FRAGM_FINAL_B;
		memmove(lml->codedata->frag[i].hdr+2, &jpgheader, sizeof(FrameHeader)-2);
.
106,107c
		lml->codedata->statCom[i] = PADDR(&(lml->codedata->fragdesc[i]));
		lml->codedata->fragdesc[i].addr = PADDR(lml->codedata->frag[i].fb);
.
102c
prepbuf(LML *lml) {
.
87c
	jpgheader = (FrameHeader*)(lml->codedata->frag[bufno].hdr+2);
.
82,83c
	while ((bufno = getbuffer(lml)) == 0 && dosleep)
		sleep(&lml->sleepjpg, getbuffer, lml);
.
79c
	
.
76c
jpgread(LML *lml, void *va, long nbytes, vlong, int dosleep) {
.
67c
		if (lml->codedata->statCom[last] & STAT_BIT)
.
64a
	lml = x;
.
63a
	LML *lml;
.
61c
getbuffer(void *x){
.
49,56d
41c
int nlml;
.
38,39c
struct LML {
	// Hardware
	Pcidev *		pcidev;
	ulong		pciBaseAddr;
	// Allocated memory
	CodeData *	codedata;
	// Software state
	ulong		jpgframeno;
	int			frameNo;
	Rendez		sleepjpg;
	int			jpgopens;
} lmls[NLML];
.
36c
typedef struct LML LML;
.
31,33c
	".",			{Qdir, 0, QTDIR},	0,	DMDIR|0555,
	"lml0ctl",		{Qctl0},			0,	0666,
	"lml0jpg",		{Qjpg0},			0,	0444,
	"lml0raw",	{Qraw0},			0,	0444,
	"lml1ctl",		{Qctl1},			0,	0666,
	"lml1jpg",		{Qjpg1},			0,	0444,
	"lml1raw",	{Qraw1},			0,	0444,
.
29a
#define	QID(q)		((ulong)(q).path)
#define	QIDLML(q)	((((ulong)(q).path)-1)>>1)

.
26,27c
	Qctl0,
	Qjpg0,
	Qraw0,
	Qctl1,
	Qjpg1,
	Qraw1,
.
11,14d
## diffname pc/devlml.c 2002/0109
## diff -e /n/emeliedump/2001/1108/sys/src/9/pc/devlml.c /n/emeliedump/2002/0109/sys/src/9/pc/devlml.c
321c
	devinit,	
	devshutdown,
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.