forsyth20121205-174063a80cc13 years agoHistory
1063 lines · 18.4 KB · C
RawDownload
/* *  Boffin MPEG decoder */#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"#include	"zoran.h"#include	"crystal.h"#include	"io.h" enum{ 	CPUACCCTRL      = 0x20,	/* Trident Window Chip control registers */	CPUACCMD        = 0x21,	BNKADR          = 0x22,	SYSCONFIG       = 0x23,	VGACOMP         = 0x24,	VGAMASK         = 0x25,	VIDCOMPL        = 0x26,	VIDCOMPH        = 0x27,	MOS             = 0x28,	DISPCTRL        = 0x29,	CAPCTRL         = 0x2a,	OVLKT           = 0x2b,	OVLWINHSTRT     = 0x2c,	OVLWINVSTRT     = 0x2d,	OVLWINHEND      = 0x2e,	OVLWINVEND      = 0x2f,	RESERVED1       = 0x30,	RESERVED2       = 0x31,	DISPWINVSTRT1   = 0x32,	DISPWINVSTRT2   = 0x33,	DISPWINVEND     = 0x34,	DISPWINHSTRT1   = 0x35,	DISPWINHSTRT2   = 0x36,	DISPWINHEND     = 0x37,	CAPWINVSTRT     = 0x38,	CAPWINHSTRT     = 0x39,	CAPWINVMF       = 0x3a,	CAPWINHMF       = 0x3b,	RESERVED3       = 0x3c,	CAPMASK         = 0x3d,	BNKPOLATION     = 0x3e,	SYNCPOL         = 0x3f,	DISPVTOTAL      = 0x40,	DISPHTOTAL      = 0x41,	DISPVSTRT       = 0x42,	DISPVEND        = 0x43,	DISPHSTRT       = 0x44,	DISPHEND        = 0x45,	DISPSYNCW       = 0x46,	DISPCRTCCTRL    = 0x47,	CAPVTOTAL       = 0x48,	CAPHTOTAL       = 0x49,	CAPVSTRT        = 0x4a,	CAPVEND         = 0x4b,	CAPHSTRT        = 0x4c,	CAPHEND         = 0x4d,	CAPSYNCW        = 0x4e,	CAPCRTCCTRL     = 0x4f,	VIDLUTDACRW     = 0x50,	VIDLUTDACRW0    = (VIDLUTDACRW),	VIDLUTDACRW1    = (VIDLUTDACRW+1),	VIDLUTDACRW2    = (VIDLUTDACRW+2),	VIDLUTDACRW3    = (VIDLUTDACRW+3),	VIDLUTDACRW4    = (VIDLUTDACRW+4),	VIDLUTDACRW5    = (VIDLUTDACRW+5),	VIDLUTDACRW6    = (VIDLUTDACRW+6),	VIDLUTDACRW7    = (VIDLUTDACRW+7),	VGALUTDACRW     = 0x58,	VGALUTDACRW0    = (VGALUTDACRW),	VGALUTDACRW1    = (VGALUTDACRW+1),	VGALUTDACRW2    = (VGALUTDACRW+2),	VGALUTDACRW3    = (VGALUTDACRW+3),	VGALUTDACRW4    = (VGALUTDACRW+4),	VGALUTDACRW5    = (VGALUTDACRW+5),	VGALUTDACRW6    = (VGALUTDACRW+6),	VGALUTDACRW7    = (VGALUTDACRW+7),	HZOOMF          = 0x60,	VZOOMF          = 0x61,	DELAY1          = 0x62,	DELAY2          = 0x63, 	TRILO      	= 0,	TRIHI     	= 1,	TRIINDEX    	= 2, 	SCL             = 0x02,	SDA             = 0x01,	I2CR		= 0x2B,	SAA7110		= 0x9c,	WRITE_C		= 0x00,	I2DLY		= 5,}; enum{	ZR36100		= 0x1e0,	ZRIRQ		= 15,	ZRDMA		= 6, 	ZRIDREG		= 4,				/* offset */	ZRMACH210   	= 6,				/* offset */	ZRREG0      	= 8,				/* offset */	ZRREG1		= 10,				/* offset */	ZRSR		= ZRREG1,			/* offset */	ZRRDY		= (1<<3),	ZRIDLE		= (1<<2),	ZRREG2		= 12,				/* offset */	ZRREG3		= 14,				/* offset */ 	SIFwidth	= 320,	SIFheight	= 240, 	IDPCOUNT	= 3064,	PMDPCOUNT	= 2048,	SVMDPCOUNT	= 2048, 	HIWAT		= 2*128*1024,	DMABLK		= 16384,}; static struct {	int	zrport;	int	irq;	int	dma;	int	trport;} mpegconf; static	char Evmode[] = "video format not supported";static	char Eaudio[] = "invalid audio layer";static	char Earate[] = "bad audio sample rate"; /* Status bits depend on board revision */static	short	STDBY;static	short	VIDSEL;static	short	VSNIRQn;static	short	INTENAn;static	short	DSPBOOT;static	short	DSPRST;static	short	MPGRST;static	int	machsr;static	int	dopen;static	int	started;static	int	stop;static	int	pause;static	int	sp2br;static	int	sp2cd;static	char	properties[] = "video mpeg1,sif\naudio musicam,I musicam,II\n";static	void	inittrident(void);static	int	initzoran(void);static	void	initcrystal(void);static	void	mpegintr(Ureg*, void*);static	void	setwindow(int, char**);static	void	freebufs(void);static	int	mkbuf(char*, int); typedef struct Buf Buf;struct Buf{	int	nchar;	uchar*	ptr;	Buf*	link;	uchar	data[1];}; static struct{	Lock;	int	qlen;	Buf*	head;	Buf*	tail;	Rendez	flow;} bqueue; static intzrstatus(void){	return ins(mpegconf.zrport+ZRSR) & 0xf;} static intzrwaitrdy(int timo, char *msg){	int i; 	for(i = 0; i < timo; i++)		if(ins(mpegconf.zrport+ZRSR) & ZRRDY)			return 0; 	print("devmpeg: device not ready %s\n", msg);	return 1;} static voidzrdma(Buf *b){	int n; 	n = dmasetup(mpegconf.dma, b->ptr, b->nchar, 0);	b->ptr += n;	b->nchar -= n;	bqueue.qlen -= n;} static voidtriwr(int reg, int val){	outb(mpegconf.trport+TRIINDEX, reg);	outb(mpegconf.trport+TRILO, val);	outb(mpegconf.trport+TRIHI, val>>8);} static inttrird(int reg){	int v; 	outb(mpegconf.trport+TRIINDEX, reg);	v = inb(mpegconf.trport+TRILO);	v |= inb(mpegconf.trport+TRIHI)<<8; 	return v;} enum{	Qdir,	Qdata,	Qctl,};static Dirtab mpegtab[]={	"mpeg",		{Qdata, 0},	0,	0666,	"mpegctl",	{Qctl,  0},	0,	0666,}; static voidmpegreset(void){	ISAConf isa; 	mpegconf.zrport = ZR36100;	mpegconf.irq = ZRIRQ;	mpegconf.dma = ZRDMA; 	memset(&isa, 0, sizeof(isa));	if(isaconfig("mpeg", 0, &isa) == 0)		return;		if(isa.port)		mpegconf.zrport = isa.port;	if(isa.irq)		mpegconf.irq = isa.irq;	if(isa.dma)		mpegconf.dma = isa.dma;	dmainit(mpegconf.dma, 64*1024);	print("mpeg0: port 0x%uX, irq %d, dma %d\n",		mpegconf.zrport, mpegconf.irq, mpegconf.dma);	mpegconf.trport = mpegconf.zrport+0x100;	intrenable(VectorPIC+mpegconf.irq, mpegintr, 0, BUSUNKNOWN);} static voidmpeginit(void){	if(mpegconf.trport == 0)		return; 	inittrident();	setwindow(0, 0);} static Chan*mpegattach(char *spec){	if(mpegconf.trport == 0)		error(Enodev); 	return devattach('E', spec);} static intmpegwalk(Chan *c, char *name){	return devwalk(c, name, mpegtab, nelem(mpegtab), devgen);} static voidmpegstat(Chan *c, char *db){	devstat(c, db, mpegtab, nelem(mpegtab), devgen);} static Chan*mpegopen(Chan *c, int omode){	switch(c->qid.path) {	default:		break;	case Qdata:		if(dopen)			error(Einuse);		dopen = 1;		break;	}	return devopen(c, omode, mpegtab, nelem(mpegtab), devgen);} static voidmpegclose(Chan *c){	int i; 	switch(c->qid.path) {	default:		break;	case Qdata:		if((c->flag & COPEN) == 0)			break;		if(started) {			for(i = 0; i < 50; i++) {				if(ins(mpegconf.zrport+ZRSR) & ZRIDLE)					break;				tsleep(&up->sleep, return0, 0, 100);			}		}		if(stop != 0)			outs(mpegconf.zrport+ZRREG1, 0x1000);		microdelay(15);		outs(mpegconf.zrport+ZRREG1, 0x8000);		freebufs();		dopen = 0;	}} static longmpegread(Chan *c, void *a, long n, ulong off){	switch(c->qid.path & ~CHDIR){	default:		error(Eperm);	case Qdir:		return devdirread(c, a, n, mpegtab, nelem(mpegtab), devgen);	case Qctl:		return readstr(off, a, n, properties);	}	return 0;} #define SCALE(a, b)	((((a)<<10)/(b))-1024)enum{	CWINVF = 0x3ff,	CWINHF = 0x1da,}; static voidsetwindow(int nf, char **field){	int minx, miny, maxx, maxy, width, height; 	if(field == 0) {		minx = 0;		miny = 0;		maxx = 0;		maxy = 0;	}	else {		if(nf != 5)			error(Ebadarg); 		minx = strtoul(field[1], 0, 0);		miny = strtoul(field[2], 0, 0);		maxx = strtoul(field[3], 0, 0) + 8;		maxy = strtoul(field[4], 0, 0);	} 	triwr(OVLWINHSTRT, minx);	triwr(OVLWINVSTRT, miny);	triwr(OVLWINHEND, maxx+12);	triwr(OVLWINVEND, maxy); 	width = maxx - minx;	height = maxy - miny;	if(width >= SIFwidth) {		triwr(HZOOMF, SCALE(width, SIFwidth));		triwr(CAPWINHMF, CWINHF);	}	else {		triwr(HZOOMF, SCALE(SIFwidth, SIFwidth));		triwr(CAPWINHMF, width*CWINHF/SIFwidth);	}	if(height >= SIFheight) {		triwr(VZOOMF, SCALE(height, SIFheight));		triwr(CAPWINVMF, CWINVF);	}	else {		triwr(VZOOMF, SCALE(SIFheight, SIFheight));		triwr(CAPWINVMF, height*CWINVF/SIFheight);	}} static intmpegflow(void*){	return bqueue.qlen < HIWAT || stop;} static intmkbuf(char *d, int n){	Buf *b; 	b = malloc(sizeof(Buf)+n);	if(b == 0)		return 0; 	memmove(b->data, d, n);	b->ptr = b->data;	b->nchar = n;	b->link = 0; 	ilock(&bqueue);	bqueue.qlen += n;	if(bqueue.head)		bqueue.tail->link = b;	else		bqueue.head = b;	bqueue.tail = b;	iunlock(&bqueue); 	return 1;} static voidfreebufs(void){	Buf *next; 	ilock(&bqueue);	bqueue.qlen = 0;	while(bqueue.head) {		next = bqueue.head->link;		free(bqueue.head);		bqueue.head = next;	}	iunlock(&bqueue);} typedef struct Audio Audio;struct Audio {	int rate;	int cd;	int br;}; static Audio AudioclkI[] = {	 64000, 0x000000bb, 0x00071797,	 96000, 0x0000007d, 0x00071c71,	128000, 0x0000005d, 0x00070de1,	160000, 0x0000004b, 0x00071c71,	192000, 0x0000003e, 0x00070de1,	224000, 0x00000035, 0x00070906,	256000, 0x0000002e, 0x0006fa76,	288000, 0x00000029, 0x0006ff51,	320000, 0x00000025, 0x0007042b,	352000, 0x00000022, 0x00071797,	384000, 0x0000001f, 0x00070de1,	416000, 0x0000001c, 0x0006e70b,	448000, 0x0000001a, 0x0006e70b,}; static Audio  AudioclkII[] = {	 48000, 0x000000fa, 0x00071c71,	 56000, 0x000000d6, 0x00071a04,	 64000, 0x000000bb, 0x00071797,	 80000, 0x00000096, 0x00071c71,	 96000, 0x0000007d, 0x00071c71,	112000, 0x0000006b, 0x00071a04,	128000, 0x0000005d, 0x00070de1,	160000, 0x0000004b, 0x00071c71,	192000, 0x0000003e, 0x00070de1,	224000, 0x00000035, 0x00070906,	256000, 0x0000002e, 0x0006fa76,	320000, 0x00000025, 0x0007042b,	384000, 0x0000001f, 0x00070de1,}; static longmpegwrite(Chan *c, char *a, long n, vlong){	Audio *t;	int i, nf, l, x;	char buf[128], *field[10];

Lines 1–500 of 1063.