xref: /inferno-os/os/pc/devmpeg.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1*74a4d8c2SCharles.Forsyth /*
2*74a4d8c2SCharles.Forsyth  *  Boffin MPEG decoder
3*74a4d8c2SCharles.Forsyth  */
4*74a4d8c2SCharles.Forsyth #include	"u.h"
5*74a4d8c2SCharles.Forsyth #include	"../port/lib.h"
6*74a4d8c2SCharles.Forsyth #include	"mem.h"
7*74a4d8c2SCharles.Forsyth #include	"dat.h"
8*74a4d8c2SCharles.Forsyth #include	"fns.h"
9*74a4d8c2SCharles.Forsyth #include	"../port/error.h"
10*74a4d8c2SCharles.Forsyth #include	"zoran.h"
11*74a4d8c2SCharles.Forsyth #include	"crystal.h"
12*74a4d8c2SCharles.Forsyth #include	"io.h"
13*74a4d8c2SCharles.Forsyth 
14*74a4d8c2SCharles.Forsyth enum
15*74a4d8c2SCharles.Forsyth {
16*74a4d8c2SCharles.Forsyth 
17*74a4d8c2SCharles.Forsyth 	CPUACCCTRL      = 0x20,	/* Trident Window Chip control registers */
18*74a4d8c2SCharles.Forsyth 	CPUACCMD        = 0x21,
19*74a4d8c2SCharles.Forsyth 	BNKADR          = 0x22,
20*74a4d8c2SCharles.Forsyth 	SYSCONFIG       = 0x23,
21*74a4d8c2SCharles.Forsyth 	VGACOMP         = 0x24,
22*74a4d8c2SCharles.Forsyth 	VGAMASK         = 0x25,
23*74a4d8c2SCharles.Forsyth 	VIDCOMPL        = 0x26,
24*74a4d8c2SCharles.Forsyth 	VIDCOMPH        = 0x27,
25*74a4d8c2SCharles.Forsyth 	MOS             = 0x28,
26*74a4d8c2SCharles.Forsyth 	DISPCTRL        = 0x29,
27*74a4d8c2SCharles.Forsyth 	CAPCTRL         = 0x2a,
28*74a4d8c2SCharles.Forsyth 	OVLKT           = 0x2b,
29*74a4d8c2SCharles.Forsyth 	OVLWINHSTRT     = 0x2c,
30*74a4d8c2SCharles.Forsyth 	OVLWINVSTRT     = 0x2d,
31*74a4d8c2SCharles.Forsyth 	OVLWINHEND      = 0x2e,
32*74a4d8c2SCharles.Forsyth 	OVLWINVEND      = 0x2f,
33*74a4d8c2SCharles.Forsyth 	RESERVED1       = 0x30,
34*74a4d8c2SCharles.Forsyth 	RESERVED2       = 0x31,
35*74a4d8c2SCharles.Forsyth 	DISPWINVSTRT1   = 0x32,
36*74a4d8c2SCharles.Forsyth 	DISPWINVSTRT2   = 0x33,
37*74a4d8c2SCharles.Forsyth 	DISPWINVEND     = 0x34,
38*74a4d8c2SCharles.Forsyth 	DISPWINHSTRT1   = 0x35,
39*74a4d8c2SCharles.Forsyth 	DISPWINHSTRT2   = 0x36,
40*74a4d8c2SCharles.Forsyth 	DISPWINHEND     = 0x37,
41*74a4d8c2SCharles.Forsyth 	CAPWINVSTRT     = 0x38,
42*74a4d8c2SCharles.Forsyth 	CAPWINHSTRT     = 0x39,
43*74a4d8c2SCharles.Forsyth 	CAPWINVMF       = 0x3a,
44*74a4d8c2SCharles.Forsyth 	CAPWINHMF       = 0x3b,
45*74a4d8c2SCharles.Forsyth 	RESERVED3       = 0x3c,
46*74a4d8c2SCharles.Forsyth 	CAPMASK         = 0x3d,
47*74a4d8c2SCharles.Forsyth 	BNKPOLATION     = 0x3e,
48*74a4d8c2SCharles.Forsyth 	SYNCPOL         = 0x3f,
49*74a4d8c2SCharles.Forsyth 	DISPVTOTAL      = 0x40,
50*74a4d8c2SCharles.Forsyth 	DISPHTOTAL      = 0x41,
51*74a4d8c2SCharles.Forsyth 	DISPVSTRT       = 0x42,
52*74a4d8c2SCharles.Forsyth 	DISPVEND        = 0x43,
53*74a4d8c2SCharles.Forsyth 	DISPHSTRT       = 0x44,
54*74a4d8c2SCharles.Forsyth 	DISPHEND        = 0x45,
55*74a4d8c2SCharles.Forsyth 	DISPSYNCW       = 0x46,
56*74a4d8c2SCharles.Forsyth 	DISPCRTCCTRL    = 0x47,
57*74a4d8c2SCharles.Forsyth 	CAPVTOTAL       = 0x48,
58*74a4d8c2SCharles.Forsyth 	CAPHTOTAL       = 0x49,
59*74a4d8c2SCharles.Forsyth 	CAPVSTRT        = 0x4a,
60*74a4d8c2SCharles.Forsyth 	CAPVEND         = 0x4b,
61*74a4d8c2SCharles.Forsyth 	CAPHSTRT        = 0x4c,
62*74a4d8c2SCharles.Forsyth 	CAPHEND         = 0x4d,
63*74a4d8c2SCharles.Forsyth 	CAPSYNCW        = 0x4e,
64*74a4d8c2SCharles.Forsyth 	CAPCRTCCTRL     = 0x4f,
65*74a4d8c2SCharles.Forsyth 	VIDLUTDACRW     = 0x50,
66*74a4d8c2SCharles.Forsyth 	VIDLUTDACRW0    = (VIDLUTDACRW),
67*74a4d8c2SCharles.Forsyth 	VIDLUTDACRW1    = (VIDLUTDACRW+1),
68*74a4d8c2SCharles.Forsyth 	VIDLUTDACRW2    = (VIDLUTDACRW+2),
69*74a4d8c2SCharles.Forsyth 	VIDLUTDACRW3    = (VIDLUTDACRW+3),
70*74a4d8c2SCharles.Forsyth 	VIDLUTDACRW4    = (VIDLUTDACRW+4),
71*74a4d8c2SCharles.Forsyth 	VIDLUTDACRW5    = (VIDLUTDACRW+5),
72*74a4d8c2SCharles.Forsyth 	VIDLUTDACRW6    = (VIDLUTDACRW+6),
73*74a4d8c2SCharles.Forsyth 	VIDLUTDACRW7    = (VIDLUTDACRW+7),
74*74a4d8c2SCharles.Forsyth 	VGALUTDACRW     = 0x58,
75*74a4d8c2SCharles.Forsyth 	VGALUTDACRW0    = (VGALUTDACRW),
76*74a4d8c2SCharles.Forsyth 	VGALUTDACRW1    = (VGALUTDACRW+1),
77*74a4d8c2SCharles.Forsyth 	VGALUTDACRW2    = (VGALUTDACRW+2),
78*74a4d8c2SCharles.Forsyth 	VGALUTDACRW3    = (VGALUTDACRW+3),
79*74a4d8c2SCharles.Forsyth 	VGALUTDACRW4    = (VGALUTDACRW+4),
80*74a4d8c2SCharles.Forsyth 	VGALUTDACRW5    = (VGALUTDACRW+5),
81*74a4d8c2SCharles.Forsyth 	VGALUTDACRW6    = (VGALUTDACRW+6),
82*74a4d8c2SCharles.Forsyth 	VGALUTDACRW7    = (VGALUTDACRW+7),
83*74a4d8c2SCharles.Forsyth 	HZOOMF          = 0x60,
84*74a4d8c2SCharles.Forsyth 	VZOOMF          = 0x61,
85*74a4d8c2SCharles.Forsyth 	DELAY1          = 0x62,
86*74a4d8c2SCharles.Forsyth 	DELAY2          = 0x63,
87*74a4d8c2SCharles.Forsyth 
88*74a4d8c2SCharles.Forsyth 	TRILO      	= 0,
89*74a4d8c2SCharles.Forsyth 	TRIHI     	= 1,
90*74a4d8c2SCharles.Forsyth 	TRIINDEX    	= 2,
91*74a4d8c2SCharles.Forsyth 
92*74a4d8c2SCharles.Forsyth 	SCL             = 0x02,
93*74a4d8c2SCharles.Forsyth 	SDA             = 0x01,
94*74a4d8c2SCharles.Forsyth 	I2CR		= 0x2B,
95*74a4d8c2SCharles.Forsyth 	SAA7110		= 0x9c,
96*74a4d8c2SCharles.Forsyth 	WRITE_C		= 0x00,
97*74a4d8c2SCharles.Forsyth 	I2DLY		= 5,
98*74a4d8c2SCharles.Forsyth };
99*74a4d8c2SCharles.Forsyth 
100*74a4d8c2SCharles.Forsyth enum
101*74a4d8c2SCharles.Forsyth {
102*74a4d8c2SCharles.Forsyth 	ZR36100		= 0x1e0,
103*74a4d8c2SCharles.Forsyth 	ZRIRQ		= 15,
104*74a4d8c2SCharles.Forsyth 	ZRDMA		= 6,
105*74a4d8c2SCharles.Forsyth 
106*74a4d8c2SCharles.Forsyth 	ZRIDREG		= 4,				/* offset */
107*74a4d8c2SCharles.Forsyth 	ZRMACH210   	= 6,				/* offset */
108*74a4d8c2SCharles.Forsyth 	ZRREG0      	= 8,				/* offset */
109*74a4d8c2SCharles.Forsyth 	ZRREG1		= 10,				/* offset */
110*74a4d8c2SCharles.Forsyth 	ZRSR		= ZRREG1,			/* offset */
111*74a4d8c2SCharles.Forsyth 	ZRRDY		= (1<<3),
112*74a4d8c2SCharles.Forsyth 	ZRIDLE		= (1<<2),
113*74a4d8c2SCharles.Forsyth 	ZRREG2		= 12,				/* offset */
114*74a4d8c2SCharles.Forsyth 	ZRREG3		= 14,				/* offset */
115*74a4d8c2SCharles.Forsyth 
116*74a4d8c2SCharles.Forsyth 	SIFwidth	= 320,
117*74a4d8c2SCharles.Forsyth 	SIFheight	= 240,
118*74a4d8c2SCharles.Forsyth 
119*74a4d8c2SCharles.Forsyth 	IDPCOUNT	= 3064,
120*74a4d8c2SCharles.Forsyth 	PMDPCOUNT	= 2048,
121*74a4d8c2SCharles.Forsyth 	SVMDPCOUNT	= 2048,
122*74a4d8c2SCharles.Forsyth 
123*74a4d8c2SCharles.Forsyth 	HIWAT		= 2*128*1024,
124*74a4d8c2SCharles.Forsyth 	DMABLK		= 16384,
125*74a4d8c2SCharles.Forsyth };
126*74a4d8c2SCharles.Forsyth 
127*74a4d8c2SCharles.Forsyth static struct {
128*74a4d8c2SCharles.Forsyth 	int	zrport;
129*74a4d8c2SCharles.Forsyth 	int	irq;
130*74a4d8c2SCharles.Forsyth 	int	dma;
131*74a4d8c2SCharles.Forsyth 	int	trport;
132*74a4d8c2SCharles.Forsyth } mpegconf;
133*74a4d8c2SCharles.Forsyth 
134*74a4d8c2SCharles.Forsyth static	char Evmode[] = "video format not supported";
135*74a4d8c2SCharles.Forsyth static	char Eaudio[] = "invalid audio layer";
136*74a4d8c2SCharles.Forsyth static	char Earate[] = "bad audio sample rate";
137*74a4d8c2SCharles.Forsyth 
138*74a4d8c2SCharles.Forsyth /* Status bits depend on board revision */
139*74a4d8c2SCharles.Forsyth static	short	STDBY;
140*74a4d8c2SCharles.Forsyth static	short	VIDSEL;
141*74a4d8c2SCharles.Forsyth static	short	VSNIRQn;
142*74a4d8c2SCharles.Forsyth static	short	INTENAn;
143*74a4d8c2SCharles.Forsyth static	short	DSPBOOT;
144*74a4d8c2SCharles.Forsyth static	short	DSPRST;
145*74a4d8c2SCharles.Forsyth static	short	MPGRST;
146*74a4d8c2SCharles.Forsyth static	int	machsr;
147*74a4d8c2SCharles.Forsyth static	int	dopen;
148*74a4d8c2SCharles.Forsyth static	int	started;
149*74a4d8c2SCharles.Forsyth static	int	stop;
150*74a4d8c2SCharles.Forsyth static	int	pause;
151*74a4d8c2SCharles.Forsyth static	int	sp2br;
152*74a4d8c2SCharles.Forsyth static	int	sp2cd;
153*74a4d8c2SCharles.Forsyth static	char	properties[] = "video mpeg1,sif\naudio musicam,I musicam,II\n";
154*74a4d8c2SCharles.Forsyth static	void	inittrident(void);
155*74a4d8c2SCharles.Forsyth static	int	initzoran(void);
156*74a4d8c2SCharles.Forsyth static	void	initcrystal(void);
157*74a4d8c2SCharles.Forsyth static	void	mpegintr(Ureg*, void*);
158*74a4d8c2SCharles.Forsyth static	void	setwindow(int, char**);
159*74a4d8c2SCharles.Forsyth static	void	freebufs(void);
160*74a4d8c2SCharles.Forsyth static	int	mkbuf(char*, int);
161*74a4d8c2SCharles.Forsyth 
162*74a4d8c2SCharles.Forsyth typedef struct Buf Buf;
163*74a4d8c2SCharles.Forsyth struct Buf
164*74a4d8c2SCharles.Forsyth {
165*74a4d8c2SCharles.Forsyth 	int	nchar;
166*74a4d8c2SCharles.Forsyth 	uchar*	ptr;
167*74a4d8c2SCharles.Forsyth 	Buf*	link;
168*74a4d8c2SCharles.Forsyth 	uchar	data[1];
169*74a4d8c2SCharles.Forsyth };
170*74a4d8c2SCharles.Forsyth 
171*74a4d8c2SCharles.Forsyth static struct
172*74a4d8c2SCharles.Forsyth {
173*74a4d8c2SCharles.Forsyth 	Lock;
174*74a4d8c2SCharles.Forsyth 	int	qlen;
175*74a4d8c2SCharles.Forsyth 	Buf*	head;
176*74a4d8c2SCharles.Forsyth 	Buf*	tail;
177*74a4d8c2SCharles.Forsyth 	Rendez	flow;
178*74a4d8c2SCharles.Forsyth } bqueue;
179*74a4d8c2SCharles.Forsyth 
180*74a4d8c2SCharles.Forsyth static int
zrstatus(void)181*74a4d8c2SCharles.Forsyth zrstatus(void)
182*74a4d8c2SCharles.Forsyth {
183*74a4d8c2SCharles.Forsyth 	return ins(mpegconf.zrport+ZRSR) & 0xf;
184*74a4d8c2SCharles.Forsyth }
185*74a4d8c2SCharles.Forsyth 
186*74a4d8c2SCharles.Forsyth static int
zrwaitrdy(int timo,char * msg)187*74a4d8c2SCharles.Forsyth zrwaitrdy(int timo, char *msg)
188*74a4d8c2SCharles.Forsyth {
189*74a4d8c2SCharles.Forsyth 	int i;
190*74a4d8c2SCharles.Forsyth 
191*74a4d8c2SCharles.Forsyth 	for(i = 0; i < timo; i++)
192*74a4d8c2SCharles.Forsyth 		if(ins(mpegconf.zrport+ZRSR) & ZRRDY)
193*74a4d8c2SCharles.Forsyth 			return 0;
194*74a4d8c2SCharles.Forsyth 
195*74a4d8c2SCharles.Forsyth 	print("devmpeg: device not ready %s\n", msg);
196*74a4d8c2SCharles.Forsyth 	return 1;
197*74a4d8c2SCharles.Forsyth }
198*74a4d8c2SCharles.Forsyth 
199*74a4d8c2SCharles.Forsyth static void
zrdma(Buf * b)200*74a4d8c2SCharles.Forsyth zrdma(Buf *b)
201*74a4d8c2SCharles.Forsyth {
202*74a4d8c2SCharles.Forsyth 	int n;
203*74a4d8c2SCharles.Forsyth 
204*74a4d8c2SCharles.Forsyth 	n = dmasetup(mpegconf.dma, b->ptr, b->nchar, 0);
205*74a4d8c2SCharles.Forsyth 	b->ptr += n;
206*74a4d8c2SCharles.Forsyth 	b->nchar -= n;
207*74a4d8c2SCharles.Forsyth 	bqueue.qlen -= n;
208*74a4d8c2SCharles.Forsyth }
209*74a4d8c2SCharles.Forsyth 
210*74a4d8c2SCharles.Forsyth static void
triwr(int reg,int val)211*74a4d8c2SCharles.Forsyth triwr(int reg, int val)
212*74a4d8c2SCharles.Forsyth {
213*74a4d8c2SCharles.Forsyth 	outb(mpegconf.trport+TRIINDEX, reg);
214*74a4d8c2SCharles.Forsyth 	outb(mpegconf.trport+TRILO, val);
215*74a4d8c2SCharles.Forsyth 	outb(mpegconf.trport+TRIHI, val>>8);
216*74a4d8c2SCharles.Forsyth }
217*74a4d8c2SCharles.Forsyth 
218*74a4d8c2SCharles.Forsyth static int
trird(int reg)219*74a4d8c2SCharles.Forsyth trird(int reg)
220*74a4d8c2SCharles.Forsyth {
221*74a4d8c2SCharles.Forsyth 	int v;
222*74a4d8c2SCharles.Forsyth 
223*74a4d8c2SCharles.Forsyth 	outb(mpegconf.trport+TRIINDEX, reg);
224*74a4d8c2SCharles.Forsyth 	v = inb(mpegconf.trport+TRILO);
225*74a4d8c2SCharles.Forsyth 	v |= inb(mpegconf.trport+TRIHI)<<8;
226*74a4d8c2SCharles.Forsyth 
227*74a4d8c2SCharles.Forsyth 	return v;
228*74a4d8c2SCharles.Forsyth }
229*74a4d8c2SCharles.Forsyth 
230*74a4d8c2SCharles.Forsyth enum
231*74a4d8c2SCharles.Forsyth {
232*74a4d8c2SCharles.Forsyth 	Qdir,
233*74a4d8c2SCharles.Forsyth 	Qdata,
234*74a4d8c2SCharles.Forsyth 	Qctl,
235*74a4d8c2SCharles.Forsyth };
236*74a4d8c2SCharles.Forsyth static Dirtab mpegtab[]=
237*74a4d8c2SCharles.Forsyth {
238*74a4d8c2SCharles.Forsyth 	"mpeg",		{Qdata, 0},	0,	0666,
239*74a4d8c2SCharles.Forsyth 	"mpegctl",	{Qctl,  0},	0,	0666,
240*74a4d8c2SCharles.Forsyth };
241*74a4d8c2SCharles.Forsyth 
242*74a4d8c2SCharles.Forsyth static void
mpegreset(void)243*74a4d8c2SCharles.Forsyth mpegreset(void)
244*74a4d8c2SCharles.Forsyth {
245*74a4d8c2SCharles.Forsyth 	ISAConf isa;
246*74a4d8c2SCharles.Forsyth 
247*74a4d8c2SCharles.Forsyth 	mpegconf.zrport = ZR36100;
248*74a4d8c2SCharles.Forsyth 	mpegconf.irq = ZRIRQ;
249*74a4d8c2SCharles.Forsyth 	mpegconf.dma = ZRDMA;
250*74a4d8c2SCharles.Forsyth 
251*74a4d8c2SCharles.Forsyth 	memset(&isa, 0, sizeof(isa));
252*74a4d8c2SCharles.Forsyth 	if(isaconfig("mpeg", 0, &isa) == 0)
253*74a4d8c2SCharles.Forsyth 		return;
254*74a4d8c2SCharles.Forsyth 	if(isa.port)
255*74a4d8c2SCharles.Forsyth 		mpegconf.zrport = isa.port;
256*74a4d8c2SCharles.Forsyth 	if(isa.irq)
257*74a4d8c2SCharles.Forsyth 		mpegconf.irq = isa.irq;
258*74a4d8c2SCharles.Forsyth 	if(isa.dma)
259*74a4d8c2SCharles.Forsyth 		mpegconf.dma = isa.dma;
260*74a4d8c2SCharles.Forsyth 	dmainit(mpegconf.dma, 64*1024);
261*74a4d8c2SCharles.Forsyth 	print("mpeg0: port 0x%uX, irq %d, dma %d\n",
262*74a4d8c2SCharles.Forsyth 		mpegconf.zrport, mpegconf.irq, mpegconf.dma);
263*74a4d8c2SCharles.Forsyth 	mpegconf.trport = mpegconf.zrport+0x100;
264*74a4d8c2SCharles.Forsyth 	intrenable(VectorPIC+mpegconf.irq, mpegintr, 0, BUSUNKNOWN);
265*74a4d8c2SCharles.Forsyth }
266*74a4d8c2SCharles.Forsyth 
267*74a4d8c2SCharles.Forsyth static void
mpeginit(void)268*74a4d8c2SCharles.Forsyth mpeginit(void)
269*74a4d8c2SCharles.Forsyth {
270*74a4d8c2SCharles.Forsyth 	if(mpegconf.trport == 0)
271*74a4d8c2SCharles.Forsyth 		return;
272*74a4d8c2SCharles.Forsyth 
273*74a4d8c2SCharles.Forsyth 	inittrident();
274*74a4d8c2SCharles.Forsyth 	setwindow(0, 0);
275*74a4d8c2SCharles.Forsyth }
276*74a4d8c2SCharles.Forsyth 
277*74a4d8c2SCharles.Forsyth static Chan*
mpegattach(char * spec)278*74a4d8c2SCharles.Forsyth mpegattach(char *spec)
279*74a4d8c2SCharles.Forsyth {
280*74a4d8c2SCharles.Forsyth 	if(mpegconf.trport == 0)
281*74a4d8c2SCharles.Forsyth 		error(Enodev);
282*74a4d8c2SCharles.Forsyth 
283*74a4d8c2SCharles.Forsyth 	return devattach('E', spec);
284*74a4d8c2SCharles.Forsyth }
285*74a4d8c2SCharles.Forsyth 
286*74a4d8c2SCharles.Forsyth static int
mpegwalk(Chan * c,char * name)287*74a4d8c2SCharles.Forsyth mpegwalk(Chan *c, char *name)
288*74a4d8c2SCharles.Forsyth {
289*74a4d8c2SCharles.Forsyth 	return devwalk(c, name, mpegtab, nelem(mpegtab), devgen);
290*74a4d8c2SCharles.Forsyth }
291*74a4d8c2SCharles.Forsyth 
292*74a4d8c2SCharles.Forsyth static void
mpegstat(Chan * c,char * db)293*74a4d8c2SCharles.Forsyth mpegstat(Chan *c, char *db)
294*74a4d8c2SCharles.Forsyth {
295*74a4d8c2SCharles.Forsyth 	devstat(c, db, mpegtab, nelem(mpegtab), devgen);
296*74a4d8c2SCharles.Forsyth }
297*74a4d8c2SCharles.Forsyth 
298*74a4d8c2SCharles.Forsyth static Chan*
mpegopen(Chan * c,int omode)299*74a4d8c2SCharles.Forsyth mpegopen(Chan *c, int omode)
300*74a4d8c2SCharles.Forsyth {
301*74a4d8c2SCharles.Forsyth 	switch(c->qid.path) {
302*74a4d8c2SCharles.Forsyth 	default:
303*74a4d8c2SCharles.Forsyth 		break;
304*74a4d8c2SCharles.Forsyth 	case Qdata:
305*74a4d8c2SCharles.Forsyth 		if(dopen)
306*74a4d8c2SCharles.Forsyth 			error(Einuse);
307*74a4d8c2SCharles.Forsyth 		dopen = 1;
308*74a4d8c2SCharles.Forsyth 		break;
309*74a4d8c2SCharles.Forsyth 	}
310*74a4d8c2SCharles.Forsyth 	return devopen(c, omode, mpegtab, nelem(mpegtab), devgen);
311*74a4d8c2SCharles.Forsyth }
312*74a4d8c2SCharles.Forsyth 
313*74a4d8c2SCharles.Forsyth static void
mpegclose(Chan * c)314*74a4d8c2SCharles.Forsyth mpegclose(Chan *c)
315*74a4d8c2SCharles.Forsyth {
316*74a4d8c2SCharles.Forsyth 	int i;
317*74a4d8c2SCharles.Forsyth 
318*74a4d8c2SCharles.Forsyth 	switch(c->qid.path) {
319*74a4d8c2SCharles.Forsyth 	default:
320*74a4d8c2SCharles.Forsyth 		break;
321*74a4d8c2SCharles.Forsyth 	case Qdata:
322*74a4d8c2SCharles.Forsyth 		if((c->flag & COPEN) == 0)
323*74a4d8c2SCharles.Forsyth 			break;
324*74a4d8c2SCharles.Forsyth 		if(started) {
325*74a4d8c2SCharles.Forsyth 			for(i = 0; i < 50; i++) {
326*74a4d8c2SCharles.Forsyth 				if(ins(mpegconf.zrport+ZRSR) & ZRIDLE)
327*74a4d8c2SCharles.Forsyth 					break;
328*74a4d8c2SCharles.Forsyth 				tsleep(&up->sleep, return0, 0, 100);
329*74a4d8c2SCharles.Forsyth 			}
330*74a4d8c2SCharles.Forsyth 		}
331*74a4d8c2SCharles.Forsyth 		if(stop != 0)
332*74a4d8c2SCharles.Forsyth 			outs(mpegconf.zrport+ZRREG1, 0x1000);
333*74a4d8c2SCharles.Forsyth 		microdelay(15);
334*74a4d8c2SCharles.Forsyth 		outs(mpegconf.zrport+ZRREG1, 0x8000);
335*74a4d8c2SCharles.Forsyth 		freebufs();
336*74a4d8c2SCharles.Forsyth 		dopen = 0;
337*74a4d8c2SCharles.Forsyth 	}
338*74a4d8c2SCharles.Forsyth }
339*74a4d8c2SCharles.Forsyth 
340*74a4d8c2SCharles.Forsyth static long
mpegread(Chan * c,void * a,long n,ulong off)341*74a4d8c2SCharles.Forsyth mpegread(Chan *c, void *a, long n, ulong off)
342*74a4d8c2SCharles.Forsyth {
343*74a4d8c2SCharles.Forsyth 	switch(c->qid.path & ~CHDIR){
344*74a4d8c2SCharles.Forsyth 	default:
345*74a4d8c2SCharles.Forsyth 		error(Eperm);
346*74a4d8c2SCharles.Forsyth 	case Qdir:
347*74a4d8c2SCharles.Forsyth 		return devdirread(c, a, n, mpegtab, nelem(mpegtab), devgen);
348*74a4d8c2SCharles.Forsyth 	case Qctl:
349*74a4d8c2SCharles.Forsyth 		return readstr(off, a, n, properties);
350*74a4d8c2SCharles.Forsyth 	}
351*74a4d8c2SCharles.Forsyth 	return 0;
352*74a4d8c2SCharles.Forsyth }
353*74a4d8c2SCharles.Forsyth 
354*74a4d8c2SCharles.Forsyth #define SCALE(a, b)	((((a)<<10)/(b))-1024)
355*74a4d8c2SCharles.Forsyth enum
356*74a4d8c2SCharles.Forsyth {
357*74a4d8c2SCharles.Forsyth 	CWINVF = 0x3ff,
358*74a4d8c2SCharles.Forsyth 	CWINHF = 0x1da,
359*74a4d8c2SCharles.Forsyth };
360*74a4d8c2SCharles.Forsyth 
361*74a4d8c2SCharles.Forsyth static void
setwindow(int nf,char ** field)362*74a4d8c2SCharles.Forsyth setwindow(int nf, char **field)
363*74a4d8c2SCharles.Forsyth {
364*74a4d8c2SCharles.Forsyth 	int minx, miny, maxx, maxy, width, height;
365*74a4d8c2SCharles.Forsyth 
366*74a4d8c2SCharles.Forsyth 	if(field == 0) {
367*74a4d8c2SCharles.Forsyth 		minx = 0;
368*74a4d8c2SCharles.Forsyth 		miny = 0;
369*74a4d8c2SCharles.Forsyth 		maxx = 0;
370*74a4d8c2SCharles.Forsyth 		maxy = 0;
371*74a4d8c2SCharles.Forsyth 	}
372*74a4d8c2SCharles.Forsyth 	else {
373*74a4d8c2SCharles.Forsyth 		if(nf != 5)
374*74a4d8c2SCharles.Forsyth 			error(Ebadarg);
375*74a4d8c2SCharles.Forsyth 
376*74a4d8c2SCharles.Forsyth 		minx = strtoul(field[1], 0, 0);
377*74a4d8c2SCharles.Forsyth 		miny = strtoul(field[2], 0, 0);
378*74a4d8c2SCharles.Forsyth 		maxx = strtoul(field[3], 0, 0) + 8;
379*74a4d8c2SCharles.Forsyth 		maxy = strtoul(field[4], 0, 0);
380*74a4d8c2SCharles.Forsyth 	}
381*74a4d8c2SCharles.Forsyth 
382*74a4d8c2SCharles.Forsyth 	triwr(OVLWINHSTRT, minx);
383*74a4d8c2SCharles.Forsyth 	triwr(OVLWINVSTRT, miny);
384*74a4d8c2SCharles.Forsyth 	triwr(OVLWINHEND, maxx+12);
385*74a4d8c2SCharles.Forsyth 	triwr(OVLWINVEND, maxy);
386*74a4d8c2SCharles.Forsyth 
387*74a4d8c2SCharles.Forsyth 	width = maxx - minx;
388*74a4d8c2SCharles.Forsyth 	height = maxy - miny;
389*74a4d8c2SCharles.Forsyth 	if(width >= SIFwidth) {
390*74a4d8c2SCharles.Forsyth 		triwr(HZOOMF, SCALE(width, SIFwidth));
391*74a4d8c2SCharles.Forsyth 		triwr(CAPWINHMF, CWINHF);
392*74a4d8c2SCharles.Forsyth 	}
393*74a4d8c2SCharles.Forsyth 	else {
394*74a4d8c2SCharles.Forsyth 		triwr(HZOOMF, SCALE(SIFwidth, SIFwidth));
395*74a4d8c2SCharles.Forsyth 		triwr(CAPWINHMF, width*CWINHF/SIFwidth);
396*74a4d8c2SCharles.Forsyth 	}
397*74a4d8c2SCharles.Forsyth 	if(height >= SIFheight) {
398*74a4d8c2SCharles.Forsyth 		triwr(VZOOMF, SCALE(height, SIFheight));
399*74a4d8c2SCharles.Forsyth 		triwr(CAPWINVMF, CWINVF);
400*74a4d8c2SCharles.Forsyth 	}
401*74a4d8c2SCharles.Forsyth 	else {
402*74a4d8c2SCharles.Forsyth 		triwr(VZOOMF, SCALE(SIFheight, SIFheight));
403*74a4d8c2SCharles.Forsyth 		triwr(CAPWINVMF, height*CWINVF/SIFheight);
404*74a4d8c2SCharles.Forsyth 	}
405*74a4d8c2SCharles.Forsyth }
406*74a4d8c2SCharles.Forsyth 
407*74a4d8c2SCharles.Forsyth static int
mpegflow(void *)408*74a4d8c2SCharles.Forsyth mpegflow(void*)
409*74a4d8c2SCharles.Forsyth {
410*74a4d8c2SCharles.Forsyth 	return bqueue.qlen < HIWAT || stop;
411*74a4d8c2SCharles.Forsyth }
412*74a4d8c2SCharles.Forsyth 
413*74a4d8c2SCharles.Forsyth static int
mkbuf(char * d,int n)414*74a4d8c2SCharles.Forsyth mkbuf(char *d, int n)
415*74a4d8c2SCharles.Forsyth {
416*74a4d8c2SCharles.Forsyth 	Buf *b;
417*74a4d8c2SCharles.Forsyth 
418*74a4d8c2SCharles.Forsyth 	b = malloc(sizeof(Buf)+n);
419*74a4d8c2SCharles.Forsyth 	if(b == 0)
420*74a4d8c2SCharles.Forsyth 		return 0;
421*74a4d8c2SCharles.Forsyth 
422*74a4d8c2SCharles.Forsyth 	memmove(b->data, d, n);
423*74a4d8c2SCharles.Forsyth 	b->ptr = b->data;
424*74a4d8c2SCharles.Forsyth 	b->nchar = n;
425*74a4d8c2SCharles.Forsyth 	b->link = 0;
426*74a4d8c2SCharles.Forsyth 
427*74a4d8c2SCharles.Forsyth 	ilock(&bqueue);
428*74a4d8c2SCharles.Forsyth 	bqueue.qlen += n;
429*74a4d8c2SCharles.Forsyth 	if(bqueue.head)
430*74a4d8c2SCharles.Forsyth 		bqueue.tail->link = b;
431*74a4d8c2SCharles.Forsyth 	else
432*74a4d8c2SCharles.Forsyth 		bqueue.head = b;
433*74a4d8c2SCharles.Forsyth 	bqueue.tail = b;
434*74a4d8c2SCharles.Forsyth 	iunlock(&bqueue);
435*74a4d8c2SCharles.Forsyth 
436*74a4d8c2SCharles.Forsyth 	return 1;
437*74a4d8c2SCharles.Forsyth }
438*74a4d8c2SCharles.Forsyth 
439*74a4d8c2SCharles.Forsyth static void
freebufs(void)440*74a4d8c2SCharles.Forsyth freebufs(void)
441*74a4d8c2SCharles.Forsyth {
442*74a4d8c2SCharles.Forsyth 	Buf *next;
443*74a4d8c2SCharles.Forsyth 
444*74a4d8c2SCharles.Forsyth 	ilock(&bqueue);
445*74a4d8c2SCharles.Forsyth 	bqueue.qlen = 0;
446*74a4d8c2SCharles.Forsyth 	while(bqueue.head) {
447*74a4d8c2SCharles.Forsyth 		next = bqueue.head->link;
448*74a4d8c2SCharles.Forsyth 		free(bqueue.head);
449*74a4d8c2SCharles.Forsyth 		bqueue.head = next;
450*74a4d8c2SCharles.Forsyth 	}
451*74a4d8c2SCharles.Forsyth 	iunlock(&bqueue);
452*74a4d8c2SCharles.Forsyth }
453*74a4d8c2SCharles.Forsyth 
454*74a4d8c2SCharles.Forsyth typedef struct Audio Audio;
455*74a4d8c2SCharles.Forsyth struct Audio {
456*74a4d8c2SCharles.Forsyth 	int rate;
457*74a4d8c2SCharles.Forsyth 	int cd;
458*74a4d8c2SCharles.Forsyth 	int br;
459*74a4d8c2SCharles.Forsyth };
460*74a4d8c2SCharles.Forsyth 
461*74a4d8c2SCharles.Forsyth static Audio AudioclkI[] =
462*74a4d8c2SCharles.Forsyth {
463*74a4d8c2SCharles.Forsyth 	 64000, 0x000000bb, 0x00071797,
464*74a4d8c2SCharles.Forsyth 	 96000, 0x0000007d, 0x00071c71,
465*74a4d8c2SCharles.Forsyth 	128000, 0x0000005d, 0x00070de1,
466*74a4d8c2SCharles.Forsyth 	160000, 0x0000004b, 0x00071c71,
467*74a4d8c2SCharles.Forsyth 	192000, 0x0000003e, 0x00070de1,
468*74a4d8c2SCharles.Forsyth 	224000, 0x00000035, 0x00070906,
469*74a4d8c2SCharles.Forsyth 	256000, 0x0000002e, 0x0006fa76,
470*74a4d8c2SCharles.Forsyth 	288000, 0x00000029, 0x0006ff51,
471*74a4d8c2SCharles.Forsyth 	320000, 0x00000025, 0x0007042b,
472*74a4d8c2SCharles.Forsyth 	352000, 0x00000022, 0x00071797,
473*74a4d8c2SCharles.Forsyth 	384000, 0x0000001f, 0x00070de1,
474*74a4d8c2SCharles.Forsyth 	416000, 0x0000001c, 0x0006e70b,
475*74a4d8c2SCharles.Forsyth 	448000, 0x0000001a, 0x0006e70b,
476*74a4d8c2SCharles.Forsyth };
477*74a4d8c2SCharles.Forsyth 
478*74a4d8c2SCharles.Forsyth static Audio  AudioclkII[] =
479*74a4d8c2SCharles.Forsyth {
480*74a4d8c2SCharles.Forsyth 	 48000, 0x000000fa, 0x00071c71,
481*74a4d8c2SCharles.Forsyth 	 56000, 0x000000d6, 0x00071a04,
482*74a4d8c2SCharles.Forsyth 	 64000, 0x000000bb, 0x00071797,
483*74a4d8c2SCharles.Forsyth 	 80000, 0x00000096, 0x00071c71,
484*74a4d8c2SCharles.Forsyth 	 96000, 0x0000007d, 0x00071c71,
485*74a4d8c2SCharles.Forsyth 	112000, 0x0000006b, 0x00071a04,
486*74a4d8c2SCharles.Forsyth 	128000, 0x0000005d, 0x00070de1,
487*74a4d8c2SCharles.Forsyth 	160000, 0x0000004b, 0x00071c71,
488*74a4d8c2SCharles.Forsyth 	192000, 0x0000003e, 0x00070de1,
489*74a4d8c2SCharles.Forsyth 	224000, 0x00000035, 0x00070906,
490*74a4d8c2SCharles.Forsyth 	256000, 0x0000002e, 0x0006fa76,
491*74a4d8c2SCharles.Forsyth 	320000, 0x00000025, 0x0007042b,
492*74a4d8c2SCharles.Forsyth 	384000, 0x0000001f, 0x00070de1,
493*74a4d8c2SCharles.Forsyth };
494*74a4d8c2SCharles.Forsyth 
495*74a4d8c2SCharles.Forsyth static long
mpegwrite(Chan * c,char * a,long n,vlong)496*74a4d8c2SCharles.Forsyth mpegwrite(Chan *c, char *a, long n, vlong)
497*74a4d8c2SCharles.Forsyth {
498*74a4d8c2SCharles.Forsyth 	Audio *t;
499*74a4d8c2SCharles.Forsyth 	int i, nf, l, x;
500*74a4d8c2SCharles.Forsyth 	char buf[128], *field[10];
501*74a4d8c2SCharles.Forsyth 
502*74a4d8c2SCharles.Forsyth 	switch(c->qid.path & ~CHDIR) {
503*74a4d8c2SCharles.Forsyth 	case Qctl:
504*74a4d8c2SCharles.Forsyth 		if(n > sizeof(buf)-1)
505*74a4d8c2SCharles.Forsyth 			n = sizeof(buf)-1;
506*74a4d8c2SCharles.Forsyth 		memmove(buf, a, n);
507*74a4d8c2SCharles.Forsyth 		buf[n] = '\0';
508*74a4d8c2SCharles.Forsyth 
509*74a4d8c2SCharles.Forsyth 		nf = getfields(buf, field, nelem(field), 1, " \t\n");
510*74a4d8c2SCharles.Forsyth 		if(nf < 1)
511*74a4d8c2SCharles.Forsyth 			error(Ebadarg);
512*74a4d8c2SCharles.Forsyth 
513*74a4d8c2SCharles.Forsyth 		if(strcmp(field[0], "stop") == 0) {
514*74a4d8c2SCharles.Forsyth 			if(started == 0)
515*74a4d8c2SCharles.Forsyth 				error("not started");
516*74a4d8c2SCharles.Forsyth 			if(pause) {
517*74a4d8c2SCharles.Forsyth 				pause = 0;
518*74a4d8c2SCharles.Forsyth 				outs(mpegconf.zrport+ZRREG1, 0x9000);
519*74a4d8c2SCharles.Forsyth 			}
520*74a4d8c2SCharles.Forsyth 			stop = 1;
521*74a4d8c2SCharles.Forsyth 			outs(mpegconf.zrport+ZRREG1, 0x1000);
522*74a4d8c2SCharles.Forsyth 			microdelay(15);
523*74a4d8c2SCharles.Forsyth 			outs(mpegconf.zrport+ZRREG1, 0x8000);
524*74a4d8c2SCharles.Forsyth 			wakeup(&bqueue.flow);
525*74a4d8c2SCharles.Forsyth 			return n;
526*74a4d8c2SCharles.Forsyth 		}
527*74a4d8c2SCharles.Forsyth 		if(strcmp(field[0], "pause") == 0) {
528*74a4d8c2SCharles.Forsyth 			if(started == 0)
529*74a4d8c2SCharles.Forsyth 				error("not started");
530*74a4d8c2SCharles.Forsyth 			if(pause == 0) {
531*74a4d8c2SCharles.Forsyth 				pause = 1;
532*74a4d8c2SCharles.Forsyth 				outs(mpegconf.zrport+ZRREG1, 0x1000);
533*74a4d8c2SCharles.Forsyth 			}
534*74a4d8c2SCharles.Forsyth 			else {
535*74a4d8c2SCharles.Forsyth 				pause = 0;
536*74a4d8c2SCharles.Forsyth 				outs(mpegconf.zrport+ZRREG1, 0x9000);
537*74a4d8c2SCharles.Forsyth 			}
538*74a4d8c2SCharles.Forsyth 			return n;
539*74a4d8c2SCharles.Forsyth 		}
540*74a4d8c2SCharles.Forsyth 		if(strcmp(field[0], "window") == 0) {
541*74a4d8c2SCharles.Forsyth 			setwindow(nf, field);
542*74a4d8c2SCharles.Forsyth 			return n;
543*74a4d8c2SCharles.Forsyth 		}
544*74a4d8c2SCharles.Forsyth 		if(strcmp(field[0], "audio") == 0) {
545*74a4d8c2SCharles.Forsyth 			if(nf < 3)
546*74a4d8c2SCharles.Forsyth 				error(Ebadarg);
547*74a4d8c2SCharles.Forsyth 			t = 0;
548*74a4d8c2SCharles.Forsyth 			if(strcmp(field[1], "musicam,I") == 0)
549*74a4d8c2SCharles.Forsyth 				t = AudioclkI;
550*74a4d8c2SCharles.Forsyth 			else
551*74a4d8c2SCharles.Forsyth 			if(strcmp(field[1], "musicam,II") == 0)
552*74a4d8c2SCharles.Forsyth 				t = AudioclkII;
553*74a4d8c2SCharles.Forsyth 			else
554*74a4d8c2SCharles.Forsyth 				error(Eaudio);
555*74a4d8c2SCharles.Forsyth 			x = strtoul(field[2], 0, 0);
556*74a4d8c2SCharles.Forsyth 			for(i = 0; t[i].rate != 0; i++) {
557*74a4d8c2SCharles.Forsyth 				if(t[i].rate == x) {
558*74a4d8c2SCharles.Forsyth 					sp2cd = t[i].cd;
559*74a4d8c2SCharles.Forsyth 					sp2br = t[i].br;
560*74a4d8c2SCharles.Forsyth 					return n;
561*74a4d8c2SCharles.Forsyth 				}
562*74a4d8c2SCharles.Forsyth 			}
563*74a4d8c2SCharles.Forsyth 			error(Earate);
564*74a4d8c2SCharles.Forsyth 		}
565*74a4d8c2SCharles.Forsyth 		if(strcmp(field[0], "video") == 0) {
566*74a4d8c2SCharles.Forsyth 			if(nf != 3)
567*74a4d8c2SCharles.Forsyth 				error(Ebadarg);
568*74a4d8c2SCharles.Forsyth 			if(strcmp(field[1], "iso11172") != 0)
569*74a4d8c2SCharles.Forsyth 				error(Evmode);
570*74a4d8c2SCharles.Forsyth 			if(strcmp(field[2], "mpeg1,sif") != 0)
571*74a4d8c2SCharles.Forsyth 				error(Evmode);
572*74a4d8c2SCharles.Forsyth 			return n;
573*74a4d8c2SCharles.Forsyth 		}
574*74a4d8c2SCharles.Forsyth 		if(strcmp(field[0], "init") == 0) {
575*74a4d8c2SCharles.Forsyth 			inittrident();
576*74a4d8c2SCharles.Forsyth 			for(i = 0; i < 3; i++)
577*74a4d8c2SCharles.Forsyth 				if(initzoran() != -1)
578*74a4d8c2SCharles.Forsyth 					break;
579*74a4d8c2SCharles.Forsyth 			initcrystal();
580*74a4d8c2SCharles.Forsyth 			started = 0;
581*74a4d8c2SCharles.Forsyth 			stop = 0;
582*74a4d8c2SCharles.Forsyth 			pause = 0;
583*74a4d8c2SCharles.Forsyth 			return n;
584*74a4d8c2SCharles.Forsyth 		}
585*74a4d8c2SCharles.Forsyth 		error(Ebadarg);
586*74a4d8c2SCharles.Forsyth 	case Qdata:
587*74a4d8c2SCharles.Forsyth 		if(n & 1)
588*74a4d8c2SCharles.Forsyth 			error("odd write");
589*74a4d8c2SCharles.Forsyth 
590*74a4d8c2SCharles.Forsyth 		while(!mpegflow(0))
591*74a4d8c2SCharles.Forsyth 			sleep(&bqueue.flow, mpegflow, 0);
592*74a4d8c2SCharles.Forsyth 
593*74a4d8c2SCharles.Forsyth 		if(stop)
594*74a4d8c2SCharles.Forsyth 			error("stopped");
595*74a4d8c2SCharles.Forsyth 
596*74a4d8c2SCharles.Forsyth 		x = n;
597*74a4d8c2SCharles.Forsyth 		while(x) {
598*74a4d8c2SCharles.Forsyth 			l = x;
599*74a4d8c2SCharles.Forsyth 			if(l > DMABLK)
600*74a4d8c2SCharles.Forsyth 				l = DMABLK;
601*74a4d8c2SCharles.Forsyth 			if(mkbuf(a, l) == 0)
602*74a4d8c2SCharles.Forsyth 				error(Enomem);
603*74a4d8c2SCharles.Forsyth 			x -= l;
604*74a4d8c2SCharles.Forsyth 			a += l;
605*74a4d8c2SCharles.Forsyth 		}
606*74a4d8c2SCharles.Forsyth 		if(started || bqueue.qlen < (HIWAT*3)/4)
607*74a4d8c2SCharles.Forsyth 			break;
608*74a4d8c2SCharles.Forsyth 
609*74a4d8c2SCharles.Forsyth 		zrdma(bqueue.head);
610*74a4d8c2SCharles.Forsyth 		outs(mpegconf.zrport+ZRREG1, 0x0000);
611*74a4d8c2SCharles.Forsyth 		outs(mpegconf.zrport+ZRREG1, 0x0000);
612*74a4d8c2SCharles.Forsyth 		started = 1;
613*74a4d8c2SCharles.Forsyth 		break;
614*74a4d8c2SCharles.Forsyth 	default:
615*74a4d8c2SCharles.Forsyth 		error(Ebadusefd);
616*74a4d8c2SCharles.Forsyth 	}
617*74a4d8c2SCharles.Forsyth 	return n;
618*74a4d8c2SCharles.Forsyth }
619*74a4d8c2SCharles.Forsyth 
620*74a4d8c2SCharles.Forsyth Dev mpegdevtab = {
621*74a4d8c2SCharles.Forsyth 	'E',
622*74a4d8c2SCharles.Forsyth 	"mpeg",
623*74a4d8c2SCharles.Forsyth 
624*74a4d8c2SCharles.Forsyth 	mpegreset,
625*74a4d8c2SCharles.Forsyth 	mpeginit,
626*74a4d8c2SCharles.Forsyth 	mpegattach,
627*74a4d8c2SCharles.Forsyth 	devdetach,
628*74a4d8c2SCharles.Forsyth 	devclone,
629*74a4d8c2SCharles.Forsyth 	mpegwalk,
630*74a4d8c2SCharles.Forsyth 	mpegstat,
631*74a4d8c2SCharles.Forsyth 	mpegopen,
632*74a4d8c2SCharles.Forsyth 	devcreate,
633*74a4d8c2SCharles.Forsyth 	mpegclose,
634*74a4d8c2SCharles.Forsyth 	mpegread,
635*74a4d8c2SCharles.Forsyth 	devbread,
636*74a4d8c2SCharles.Forsyth 	mpegwrite,
637*74a4d8c2SCharles.Forsyth 	devbwrite,
638*74a4d8c2SCharles.Forsyth 	devremove,
639*74a4d8c2SCharles.Forsyth 	devwstat,
640*74a4d8c2SCharles.Forsyth };
641*74a4d8c2SCharles.Forsyth 
642*74a4d8c2SCharles.Forsyth static void
initctl(void)643*74a4d8c2SCharles.Forsyth initctl(void)
644*74a4d8c2SCharles.Forsyth {
645*74a4d8c2SCharles.Forsyth 	int boardid;
646*74a4d8c2SCharles.Forsyth 	static int done;
647*74a4d8c2SCharles.Forsyth 
648*74a4d8c2SCharles.Forsyth 	if(done)
649*74a4d8c2SCharles.Forsyth 		return;
650*74a4d8c2SCharles.Forsyth 
651*74a4d8c2SCharles.Forsyth 	boardid = ins(mpegconf.zrport+ZRIDREG);
652*74a4d8c2SCharles.Forsyth 	if(boardid == 0xE3E3) {		/* REV c/d */
653*74a4d8c2SCharles.Forsyth 		STDBY   = 0x0000;
654*74a4d8c2SCharles.Forsyth 		VIDSEL  = 0x2020;
655*74a4d8c2SCharles.Forsyth 		VSNIRQn = 0x1010;
656*74a4d8c2SCharles.Forsyth 		INTENAn = 0x0808;
657*74a4d8c2SCharles.Forsyth 		DSPBOOT = 0x0404;
658*74a4d8c2SCharles.Forsyth 		DSPRST  = 0x0202;
659*74a4d8c2SCharles.Forsyth 		MPGRST  = 0x0101;
660*74a4d8c2SCharles.Forsyth 	}
661*74a4d8c2SCharles.Forsyth 	else {				/* REV b */
662*74a4d8c2SCharles.Forsyth 		STDBY   = 0x0404;
663*74a4d8c2SCharles.Forsyth 		VIDSEL  = 0x1010;
664*74a4d8c2SCharles.Forsyth 		VSNIRQn = 0x8080;
665*74a4d8c2SCharles.Forsyth 		INTENAn = 0x4040;
666*74a4d8c2SCharles.Forsyth 		DSPBOOT = 0x0202;
667*74a4d8c2SCharles.Forsyth 		DSPRST  = 0x0101;
668*74a4d8c2SCharles.Forsyth 		MPGRST  = 0x2020;
669*74a4d8c2SCharles.Forsyth 	}
670*74a4d8c2SCharles.Forsyth 	done = 1;
671*74a4d8c2SCharles.Forsyth 
672*74a4d8c2SCharles.Forsyth }
673*74a4d8c2SCharles.Forsyth 
674*74a4d8c2SCharles.Forsyth /*
675*74a4d8c2SCharles.Forsyth  * nbl (reg 0x1[ab]) was 0x0022, nblf (reg 1[cd]) was 0x0006
676*74a4d8c2SCharles.Forsyth  */
677*74a4d8c2SCharles.Forsyth static uchar
678*74a4d8c2SCharles.Forsyth zrparam[] =
679*74a4d8c2SCharles.Forsyth {
680*74a4d8c2SCharles.Forsyth /* 00 */  0xEF, 0x01, 0x01, 0x01, 0x80, 0x0E, 0x31, 0x00,
681*74a4d8c2SCharles.Forsyth /* 08 */  0x01, 0x60, 0x00, 0x00, 0x03, 0x5A, 0x00, 0x7A,
682*74a4d8c2SCharles.Forsyth /* 10 */  0x00, 0x10, 0x00, 0x08, 0x00, 0xF0, 0x00, 0x00,
683*74a4d8c2SCharles.Forsyth /* 18 */  0x02, 0x0D, 0x00, 0x1e, 0x00, 0x0a, 0x00, 0x02,
684*74a4d8c2SCharles.Forsyth /* 20 */  0x40, 0x06, 0x80, 0x00, 0x80, 0x00, 0x05, 0x9B,
685*74a4d8c2SCharles.Forsyth /* 28 */  0x07, 0x16, 0xFD, 0x25, 0xFE, 0xA0, 0x00, 0x00,
686*74a4d8c2SCharles.Forsyth /* 30 */  0x00, 0x07, 0x0d, 0xe1, 0x00, 0x00, 0x00, 0x3E,
687*74a4d8c2SCharles.Forsyth /* 38 */  0x00, 0x00, 0x09, 0x51, 0x00, 0x00, 0xCD, 0xFE,
688*74a4d8c2SCharles.Forsyth /* 40 */  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689*74a4d8c2SCharles.Forsyth /* 48 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690*74a4d8c2SCharles.Forsyth /* 50 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691*74a4d8c2SCharles.Forsyth /* 58 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
692*74a4d8c2SCharles.Forsyth /* 60 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
693*74a4d8c2SCharles.Forsyth /* 68 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
694*74a4d8c2SCharles.Forsyth /* 70 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
695*74a4d8c2SCharles.Forsyth /* 78 */  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
696*74a4d8c2SCharles.Forsyth };
697*74a4d8c2SCharles.Forsyth 
698*74a4d8c2SCharles.Forsyth static int
initzoran(void)699*74a4d8c2SCharles.Forsyth initzoran(void)
700*74a4d8c2SCharles.Forsyth {
701*74a4d8c2SCharles.Forsyth 	int i, nbytes, zrs;
702*74a4d8c2SCharles.Forsyth 
703*74a4d8c2SCharles.Forsyth 	initctl();
704*74a4d8c2SCharles.Forsyth 	freebufs();
705*74a4d8c2SCharles.Forsyth 
706*74a4d8c2SCharles.Forsyth 	machsr = DSPRST|VSNIRQn;
707*74a4d8c2SCharles.Forsyth 	outs(mpegconf.zrport+ZRMACH210, machsr);
708*74a4d8c2SCharles.Forsyth 	microdelay(4000);
709*74a4d8c2SCharles.Forsyth 
710*74a4d8c2SCharles.Forsyth 	machsr |= STDBY;
711*74a4d8c2SCharles.Forsyth 	outs(mpegconf.zrport+ZRMACH210, machsr);
712*74a4d8c2SCharles.Forsyth 	microdelay(4000);
713*74a4d8c2SCharles.Forsyth 
714*74a4d8c2SCharles.Forsyth 	machsr |= MPGRST;
715*74a4d8c2SCharles.Forsyth 	outs(mpegconf.zrport+ZRMACH210, machsr);
716*74a4d8c2SCharles.Forsyth 	microdelay(4000);
717*74a4d8c2SCharles.Forsyth 	machsr &= ~MPGRST;
718*74a4d8c2SCharles.Forsyth 	outs(mpegconf.zrport+ZRMACH210, machsr);
719*74a4d8c2SCharles.Forsyth 	microdelay(4000);
720*74a4d8c2SCharles.Forsyth 	machsr |= MPGRST;
721*74a4d8c2SCharles.Forsyth 	outs(mpegconf.zrport+ZRMACH210, machsr);
722*74a4d8c2SCharles.Forsyth 	microdelay(4000);
723*74a4d8c2SCharles.Forsyth 
724*74a4d8c2SCharles.Forsyth 	if(zrwaitrdy(2000, "load IDP"))
725*74a4d8c2SCharles.Forsyth 		return -1;
726*74a4d8c2SCharles.Forsyth 
727*74a4d8c2SCharles.Forsyth 	for(i = 0; i < IDPCOUNT; i++)
728*74a4d8c2SCharles.Forsyth 		outb(mpegconf.zrport+ZRREG2, zrmpeg1[i]);
729*74a4d8c2SCharles.Forsyth 
730*74a4d8c2SCharles.Forsyth 	if(((zrs = zrstatus()) & 3) != 3) {
731*74a4d8c2SCharles.Forsyth /*		print("devmpeg: error loading IDP sr=%2.2ux\n", zrs);	*/
732*74a4d8c2SCharles.Forsyth 		USED(zrs);
733*74a4d8c2SCharles.Forsyth 		return -1;
734*74a4d8c2SCharles.Forsyth 	}
735*74a4d8c2SCharles.Forsyth 
736*74a4d8c2SCharles.Forsyth 	if(zrwaitrdy(2000, "load PMDP"))
737*74a4d8c2SCharles.Forsyth 		return -1;
738*74a4d8c2SCharles.Forsyth 
739*74a4d8c2SCharles.Forsyth 	for(i = 0; i < PMDPCOUNT; i++)
740*74a4d8c2SCharles.Forsyth 		outb(mpegconf.zrport+ZRREG3, zrmpeg2[i]);
741*74a4d8c2SCharles.Forsyth 
742*74a4d8c2SCharles.Forsyth 	if(((zrs = zrstatus()) & 3) != 3) {
743*74a4d8c2SCharles.Forsyth /*		print("devmpeg: error loading PMDP sr=%2.2ux\n", zrs);	*/
744*74a4d8c2SCharles.Forsyth 		USED(zrs);
745*74a4d8c2SCharles.Forsyth 		return -1;
746*74a4d8c2SCharles.Forsyth 	}
747*74a4d8c2SCharles.Forsyth 
748*74a4d8c2SCharles.Forsyth 	zrparam[0x36] = sp2cd>>8;
749*74a4d8c2SCharles.Forsyth 	zrparam[0x37] = sp2cd>>0;
750*74a4d8c2SCharles.Forsyth 	zrparam[0x31] = sp2br>>16;
751*74a4d8c2SCharles.Forsyth 	zrparam[0x32] = sp2br>>8;
752*74a4d8c2SCharles.Forsyth 	zrparam[0x33] = sp2br>>0;
753*74a4d8c2SCharles.Forsyth 
754*74a4d8c2SCharles.Forsyth 	nbytes = 16;
755*74a4d8c2SCharles.Forsyth 	for(i = 0; i < 128; i++) {
756*74a4d8c2SCharles.Forsyth 		if(nbytes >= 16) {
757*74a4d8c2SCharles.Forsyth 			if(zrwaitrdy(2000, "load parameters"))
758*74a4d8c2SCharles.Forsyth 				return -1;
759*74a4d8c2SCharles.Forsyth 			nbytes = 0;
760*74a4d8c2SCharles.Forsyth 		}
761*74a4d8c2SCharles.Forsyth 		outb(mpegconf.zrport+ZRREG0, zrparam[i]);
762*74a4d8c2SCharles.Forsyth 		nbytes++;
763*74a4d8c2SCharles.Forsyth 	}
764*74a4d8c2SCharles.Forsyth 
765*74a4d8c2SCharles.Forsyth 	if(zrwaitrdy(2000, "load SVMDP"))
766*74a4d8c2SCharles.Forsyth 		return -1;
767*74a4d8c2SCharles.Forsyth 
768*74a4d8c2SCharles.Forsyth 	for(i = 0; i < SVMDPCOUNT; i++)
769*74a4d8c2SCharles.Forsyth 		outb(mpegconf.zrport+ZRREG3, zrmpeg3s[i]);
770*74a4d8c2SCharles.Forsyth 
771*74a4d8c2SCharles.Forsyth 	if(((zrs = zrstatus()) & 3) != 3) {
772*74a4d8c2SCharles.Forsyth /*		print("devmpeg: error loading SVMDP sr=%2.2ux\n", zrs);	*/
773*74a4d8c2SCharles.Forsyth 		USED(zrs);
774*74a4d8c2SCharles.Forsyth 		return -1;
775*74a4d8c2SCharles.Forsyth 	}
776*74a4d8c2SCharles.Forsyth 	return 0;
777*74a4d8c2SCharles.Forsyth }
778*74a4d8c2SCharles.Forsyth 
779*74a4d8c2SCharles.Forsyth static struct
780*74a4d8c2SCharles.Forsyth {
781*74a4d8c2SCharles.Forsyth 	short	reg;
782*74a4d8c2SCharles.Forsyth 	ushort	val;
783*74a4d8c2SCharles.Forsyth } trireg[] =
784*74a4d8c2SCharles.Forsyth {
785*74a4d8c2SCharles.Forsyth 	0x20, 0x0400,
786*74a4d8c2SCharles.Forsyth 	0x21, 0x00e9,
787*74a4d8c2SCharles.Forsyth 	0x22, 0x0000,
788*74a4d8c2SCharles.Forsyth 	0x23, 0x07ee,
789*74a4d8c2SCharles.Forsyth 	0x24, 0x0005,
790*74a4d8c2SCharles.Forsyth 	0x25, 0xff00,
791*74a4d8c2SCharles.Forsyth 	0x26, 0x0000,
792*74a4d8c2SCharles.Forsyth 	0x27, 0x7fff,
793*74a4d8c2SCharles.Forsyth 	0x28, 0x0004,
794*74a4d8c2SCharles.Forsyth 	0x29, 0x88a0,
795*74a4d8c2SCharles.Forsyth 	0x2a, 0x0011,
796*74a4d8c2SCharles.Forsyth 	0x2b, 0x8540,
797*74a4d8c2SCharles.Forsyth 	0x2c, 0x00c4,
798*74a4d8c2SCharles.Forsyth 	0x2d, 0x00ac,
799*74a4d8c2SCharles.Forsyth 	0x2e, 0x020f,
800*74a4d8c2SCharles.Forsyth 	0x2f, 0x019d,
801*74a4d8c2SCharles.Forsyth 	0x30, 0x00bd,
802*74a4d8c2SCharles.Forsyth 	0x31, 0x00ff,
803*74a4d8c2SCharles.Forsyth 	0x32, 0x0000,
804*74a4d8c2SCharles.Forsyth 	0x33, 0x0000,
805*74a4d8c2SCharles.Forsyth 	0x34, 0x03ff,
806*74a4d8c2SCharles.Forsyth 	0x35, 0x0000,
807*74a4d8c2SCharles.Forsyth 	0x36, 0x0000,
808*74a4d8c2SCharles.Forsyth 	0x37, 0x03ff,
809*74a4d8c2SCharles.Forsyth 	0x38, 0x0000,
810*74a4d8c2SCharles.Forsyth 	0x39, 0x0000,
811*74a4d8c2SCharles.Forsyth 	0x3a, 0x03ff,
812*74a4d8c2SCharles.Forsyth 	0x3b, 0x01da,
813*74a4d8c2SCharles.Forsyth 	0x3c, 0xe8ce,
814*74a4d8c2SCharles.Forsyth 	0x3d, 0x2ac0,
815*74a4d8c2SCharles.Forsyth 	0x3e, 0x891f,
816*74a4d8c2SCharles.Forsyth 	0x3f, 0x3e25,
817*74a4d8c2SCharles.Forsyth 	0x40, 0x03ff,
818*74a4d8c2SCharles.Forsyth 	0x41, 0x01ff,
819*74a4d8c2SCharles.Forsyth 	0x42, 0x001f,
820*74a4d8c2SCharles.Forsyth 	0x43, 0x01ff,
821*74a4d8c2SCharles.Forsyth 	0x44, 0x003b,
822*74a4d8c2SCharles.Forsyth 	0x45, 0x0186,
823*74a4d8c2SCharles.Forsyth 	0x46, 0x1d06,
824*74a4d8c2SCharles.Forsyth 	0x47, 0x1a4f,
825*74a4d8c2SCharles.Forsyth 	0x48, 0x020d,
826*74a4d8c2SCharles.Forsyth 	0x49, 0x01ad,
827*74a4d8c2SCharles.Forsyth 	0x4a, 0x001b,
828*74a4d8c2SCharles.Forsyth 	0x4b, 0x01fd,
829*74a4d8c2SCharles.Forsyth 	0x4c, 0x003a,
830*74a4d8c2SCharles.Forsyth 	0x4d, 0x034b,
831*74a4d8c2SCharles.Forsyth 	0x4e, 0x2006,
832*74a4d8c2SCharles.Forsyth 	0x4f, 0x0083,
833*74a4d8c2SCharles.Forsyth 	0x50, 0xef08,
834*74a4d8c2SCharles.Forsyth 	0x51, 0xef3a,
835*74a4d8c2SCharles.Forsyth 	0x52, 0xefff,
836*74a4d8c2SCharles.Forsyth 	0x53, 0xef08,
837*74a4d8c2SCharles.Forsyth 	0x54, 0xef08,
838*74a4d8c2SCharles.Forsyth 	0x55, 0xef15,
839*74a4d8c2SCharles.Forsyth 	0x56, 0xefc0,
840*74a4d8c2SCharles.Forsyth 	0x57, 0xef08,
841*74a4d8c2SCharles.Forsyth 	0x58, 0xefef,
842*74a4d8c2SCharles.Forsyth 	0x59, 0xefef,
843*74a4d8c2SCharles.Forsyth 	0x5a, 0xefef,
844*74a4d8c2SCharles.Forsyth 	0x5b, 0xefef,
845*74a4d8c2SCharles.Forsyth 	0x5c, 0xefef,
846*74a4d8c2SCharles.Forsyth 	0x5d, 0xefef,
847*74a4d8c2SCharles.Forsyth 	0x5e, 0xefef,
848*74a4d8c2SCharles.Forsyth 	0x5f, 0xefef,
849*74a4d8c2SCharles.Forsyth 	0x60, 0x0000,
850*74a4d8c2SCharles.Forsyth 	0x61, 0x0004,
851*74a4d8c2SCharles.Forsyth 	0x62, 0x0020,
852*74a4d8c2SCharles.Forsyth 	0x63, 0x8080,
853*74a4d8c2SCharles.Forsyth 	0x64, 0x0300,
854*74a4d8c2SCharles.Forsyth 	-1
855*74a4d8c2SCharles.Forsyth };
856*74a4d8c2SCharles.Forsyth 
857*74a4d8c2SCharles.Forsyth static void
clrI2C(uchar b)858*74a4d8c2SCharles.Forsyth clrI2C(uchar b)
859*74a4d8c2SCharles.Forsyth {
860*74a4d8c2SCharles.Forsyth 	uchar t;
861*74a4d8c2SCharles.Forsyth 
862*74a4d8c2SCharles.Forsyth 	outb(mpegconf.trport+TRIINDEX, I2CR);
863*74a4d8c2SCharles.Forsyth 	t = inb(mpegconf.trport+TRIHI);
864*74a4d8c2SCharles.Forsyth 	t &= ~b;
865*74a4d8c2SCharles.Forsyth 	outb(mpegconf.trport+TRIHI, t);
866*74a4d8c2SCharles.Forsyth }
867*74a4d8c2SCharles.Forsyth 
868*74a4d8c2SCharles.Forsyth static void
setI2C(uchar b)869*74a4d8c2SCharles.Forsyth setI2C(uchar b)
870*74a4d8c2SCharles.Forsyth {
871*74a4d8c2SCharles.Forsyth 	uchar t;
872*74a4d8c2SCharles.Forsyth 
873*74a4d8c2SCharles.Forsyth 	outb(mpegconf.trport+TRIINDEX, I2CR);
874*74a4d8c2SCharles.Forsyth 	t = inb(mpegconf.trport+TRIHI);
875*74a4d8c2SCharles.Forsyth 	t |= b;
876*74a4d8c2SCharles.Forsyth 	outb(mpegconf.trport+TRIHI, t);
877*74a4d8c2SCharles.Forsyth }
878*74a4d8c2SCharles.Forsyth 
879*74a4d8c2SCharles.Forsyth static void
startI2C(void)880*74a4d8c2SCharles.Forsyth startI2C(void)
881*74a4d8c2SCharles.Forsyth {
882*74a4d8c2SCharles.Forsyth 	setI2C(SDA);
883*74a4d8c2SCharles.Forsyth 	setI2C(SCL);
884*74a4d8c2SCharles.Forsyth 	microdelay(I2DLY);
885*74a4d8c2SCharles.Forsyth 	clrI2C(SDA);
886*74a4d8c2SCharles.Forsyth 	microdelay(I2DLY);
887*74a4d8c2SCharles.Forsyth 	clrI2C(SCL);
888*74a4d8c2SCharles.Forsyth 	microdelay(I2DLY);
889*74a4d8c2SCharles.Forsyth }
890*74a4d8c2SCharles.Forsyth 
891*74a4d8c2SCharles.Forsyth static void
endI2C(void)892*74a4d8c2SCharles.Forsyth endI2C(void)
893*74a4d8c2SCharles.Forsyth {
894*74a4d8c2SCharles.Forsyth 	clrI2C(SDA);
895*74a4d8c2SCharles.Forsyth 	clrI2C(SCL);
896*74a4d8c2SCharles.Forsyth 	microdelay(I2DLY);
897*74a4d8c2SCharles.Forsyth 	setI2C(SCL);
898*74a4d8c2SCharles.Forsyth 	microdelay(I2DLY);
899*74a4d8c2SCharles.Forsyth 	setI2C(SDA);
900*74a4d8c2SCharles.Forsyth 	microdelay(I2DLY);
901*74a4d8c2SCharles.Forsyth }
902*74a4d8c2SCharles.Forsyth 
903*74a4d8c2SCharles.Forsyth static void
wrI2Cbit(uchar b)904*74a4d8c2SCharles.Forsyth wrI2Cbit(uchar b)
905*74a4d8c2SCharles.Forsyth {
906*74a4d8c2SCharles.Forsyth 	clrI2C(SDA);
907*74a4d8c2SCharles.Forsyth 	clrI2C(SCL);
908*74a4d8c2SCharles.Forsyth 	microdelay(I2DLY);
909*74a4d8c2SCharles.Forsyth 	if(b & 1) {
910*74a4d8c2SCharles.Forsyth 		setI2C(SDA);
911*74a4d8c2SCharles.Forsyth 		microdelay(I2DLY);
912*74a4d8c2SCharles.Forsyth 		setI2C(SCL);
913*74a4d8c2SCharles.Forsyth 		microdelay(I2DLY);
914*74a4d8c2SCharles.Forsyth 		clrI2C(SCL);
915*74a4d8c2SCharles.Forsyth 		microdelay(I2DLY);
916*74a4d8c2SCharles.Forsyth 		clrI2C(SDA);
917*74a4d8c2SCharles.Forsyth 		microdelay(I2DLY);
918*74a4d8c2SCharles.Forsyth 	}
919*74a4d8c2SCharles.Forsyth 	else {
920*74a4d8c2SCharles.Forsyth 		setI2C(SCL);
921*74a4d8c2SCharles.Forsyth 		microdelay(I2DLY);
922*74a4d8c2SCharles.Forsyth 		clrI2C(SCL);
923*74a4d8c2SCharles.Forsyth 		microdelay(I2DLY);
924*74a4d8c2SCharles.Forsyth 	}
925*74a4d8c2SCharles.Forsyth }
926*74a4d8c2SCharles.Forsyth 
927*74a4d8c2SCharles.Forsyth static void
wrI2CB(unsigned char data)928*74a4d8c2SCharles.Forsyth wrI2CB(unsigned char data)
929*74a4d8c2SCharles.Forsyth {
930*74a4d8c2SCharles.Forsyth 	int i;
931*74a4d8c2SCharles.Forsyth 
932*74a4d8c2SCharles.Forsyth 	for(i = 0; i < 8; i++)
933*74a4d8c2SCharles.Forsyth 		wrI2Cbit(data >>(7-i));
934*74a4d8c2SCharles.Forsyth }
935*74a4d8c2SCharles.Forsyth 
936*74a4d8c2SCharles.Forsyth static int
rdI2CBit(void)937*74a4d8c2SCharles.Forsyth rdI2CBit(void)
938*74a4d8c2SCharles.Forsyth {
939*74a4d8c2SCharles.Forsyth 	int bit = 1;
940*74a4d8c2SCharles.Forsyth 
941*74a4d8c2SCharles.Forsyth 	setI2C(SDA);
942*74a4d8c2SCharles.Forsyth 	clrI2C(SCL);
943*74a4d8c2SCharles.Forsyth 	setI2C(SCL);
944*74a4d8c2SCharles.Forsyth 	outb(mpegconf.trport+TRIINDEX, I2CR);
945*74a4d8c2SCharles.Forsyth 	if(inb(mpegconf.trport+TRIHI) & SDA)
946*74a4d8c2SCharles.Forsyth 		bit = 0;
947*74a4d8c2SCharles.Forsyth 	clrI2C(SDA);
948*74a4d8c2SCharles.Forsyth 	clrI2C(SCL);
949*74a4d8c2SCharles.Forsyth 
950*74a4d8c2SCharles.Forsyth 	return bit;
951*74a4d8c2SCharles.Forsyth }
952*74a4d8c2SCharles.Forsyth 
953*74a4d8c2SCharles.Forsyth static int
wrI2CD(uchar data)954*74a4d8c2SCharles.Forsyth wrI2CD(uchar data)
955*74a4d8c2SCharles.Forsyth {
956*74a4d8c2SCharles.Forsyth 	int r;
957*74a4d8c2SCharles.Forsyth 	ulong s;
958*74a4d8c2SCharles.Forsyth 
959*74a4d8c2SCharles.Forsyth 	s = splhi();
960*74a4d8c2SCharles.Forsyth 	wrI2CB(data);
961*74a4d8c2SCharles.Forsyth 	r = rdI2CBit();
962*74a4d8c2SCharles.Forsyth 	splx(s);
963*74a4d8c2SCharles.Forsyth 	return r;
964*74a4d8c2SCharles.Forsyth }
965*74a4d8c2SCharles.Forsyth 
966*74a4d8c2SCharles.Forsyth static uchar
967*74a4d8c2SCharles.Forsyth setupSAA7110[] =
968*74a4d8c2SCharles.Forsyth {
969*74a4d8c2SCharles.Forsyth 	/* Digital */
970*74a4d8c2SCharles.Forsyth 	0x4c, 0x3c, 0x0d, 0xef, 0xbd, 0xf0, 0x40, 0x03,
971*74a4d8c2SCharles.Forsyth 	0xf8, 0xf8, 0x90, 0x90, 0x00, 0x02, 0x10, 0x77,
972*74a4d8c2SCharles.Forsyth 	0x00, 0x2c, 0x40, 0x40, 0x3b, 0x10, 0xfc, 0xd2,
973*74a4d8c2SCharles.Forsyth 	0xf0, 0x80,
974*74a4d8c2SCharles.Forsyth 
975*74a4d8c2SCharles.Forsyth 	/* Analog */
976*74a4d8c2SCharles.Forsyth 	0xd9, 0x16, 0x40, 0x40, 0x80, 0x40, 0x80, 0x4f,
977*74a4d8c2SCharles.Forsyth 	0xfe, 0x01, 0xcf, 0x0f, 0x03, 0x01, 0x81, 0x0a,
978*74a4d8c2SCharles.Forsyth 	0x40, 0x35, 0x02, 0x8c, 0x03
979*74a4d8c2SCharles.Forsyth };
980*74a4d8c2SCharles.Forsyth 
981*74a4d8c2SCharles.Forsyth static void
addrI2CB(int addr,int val)982*74a4d8c2SCharles.Forsyth addrI2CB(int addr, int val)
983*74a4d8c2SCharles.Forsyth {
984*74a4d8c2SCharles.Forsyth 	ulong s;
985*74a4d8c2SCharles.Forsyth 
986*74a4d8c2SCharles.Forsyth 	s = splhi();
987*74a4d8c2SCharles.Forsyth 	startI2C();
988*74a4d8c2SCharles.Forsyth 	wrI2CD(SAA7110|WRITE_C);
989*74a4d8c2SCharles.Forsyth 	wrI2CD(addr);
990*74a4d8c2SCharles.Forsyth 	wrI2CD(val);
991*74a4d8c2SCharles.Forsyth 	endI2C();
992*74a4d8c2SCharles.Forsyth 	splx(s);
993*74a4d8c2SCharles.Forsyth }
994*74a4d8c2SCharles.Forsyth 
995*74a4d8c2SCharles.Forsyth static void
inittrident(void)996*74a4d8c2SCharles.Forsyth inittrident(void)
997*74a4d8c2SCharles.Forsyth {
998*74a4d8c2SCharles.Forsyth 	int i;
999*74a4d8c2SCharles.Forsyth 
1000*74a4d8c2SCharles.Forsyth 	for(i = 0; trireg[i].reg != -1; i++)
1001*74a4d8c2SCharles.Forsyth 		triwr(trireg[i].reg, trireg[i].val);
1002*74a4d8c2SCharles.Forsyth 
1003*74a4d8c2SCharles.Forsyth 	for(i = 0; i < 47; i++)
1004*74a4d8c2SCharles.Forsyth 		addrI2CB(i, setupSAA7110[i]);
1005*74a4d8c2SCharles.Forsyth }
1006*74a4d8c2SCharles.Forsyth 
1007*74a4d8c2SCharles.Forsyth static void
initcrystal(void)1008*74a4d8c2SCharles.Forsyth initcrystal(void)
1009*74a4d8c2SCharles.Forsyth {
1010*74a4d8c2SCharles.Forsyth 	int i;
1011*74a4d8c2SCharles.Forsyth 	static int done;
1012*74a4d8c2SCharles.Forsyth 
1013*74a4d8c2SCharles.Forsyth 	if(done)
1014*74a4d8c2SCharles.Forsyth 		return;
1015*74a4d8c2SCharles.Forsyth 
1016*74a4d8c2SCharles.Forsyth 	done = 1;
1017*74a4d8c2SCharles.Forsyth 
1018*74a4d8c2SCharles.Forsyth 	initctl();
1019*74a4d8c2SCharles.Forsyth 
1020*74a4d8c2SCharles.Forsyth 	/* Reboot the Musicam decoder */
1021*74a4d8c2SCharles.Forsyth 	clrI2C(SCL);
1022*74a4d8c2SCharles.Forsyth 	clrI2C(SDA);
1023*74a4d8c2SCharles.Forsyth 	machsr |= DSPRST;
1024*74a4d8c2SCharles.Forsyth 	outs(mpegconf.zrport+ZRMACH210, machsr);
1025*74a4d8c2SCharles.Forsyth 	machsr |= DSPBOOT;
1026*74a4d8c2SCharles.Forsyth 	outs(mpegconf.zrport+ZRMACH210, machsr);
1027*74a4d8c2SCharles.Forsyth 	machsr &= ~DSPRST;
1028*74a4d8c2SCharles.Forsyth 	outs(mpegconf.zrport+ZRMACH210, machsr);
1029*74a4d8c2SCharles.Forsyth 	machsr |= DSPRST;
1030*74a4d8c2SCharles.Forsyth 	outs(mpegconf.zrport+ZRMACH210, machsr);
1031*74a4d8c2SCharles.Forsyth 	machsr &= ~DSPBOOT;
1032*74a4d8c2SCharles.Forsyth 	outs(mpegconf.zrport+ZRMACH210, machsr);
1033*74a4d8c2SCharles.Forsyth 
1034*74a4d8c2SCharles.Forsyth 	startI2C();
1035*74a4d8c2SCharles.Forsyth 	wrI2CD(0);
1036*74a4d8c2SCharles.Forsyth 	for(i = 0; i < sizeof(crystal); i++ )
1037*74a4d8c2SCharles.Forsyth 		wrI2CD(crystal[i]);
1038*74a4d8c2SCharles.Forsyth 	endI2C();
1039*74a4d8c2SCharles.Forsyth }
1040*74a4d8c2SCharles.Forsyth 
1041*74a4d8c2SCharles.Forsyth static void
mpegintr(Ureg *,void *)1042*74a4d8c2SCharles.Forsyth mpegintr(Ureg*, void*)
1043*74a4d8c2SCharles.Forsyth {
1044*74a4d8c2SCharles.Forsyth 	Buf *b;
1045*74a4d8c2SCharles.Forsyth 
1046*74a4d8c2SCharles.Forsyth 	b = bqueue.head;
1047*74a4d8c2SCharles.Forsyth 	if(b == 0 || dmadone(mpegconf.dma) == 0)
1048*74a4d8c2SCharles.Forsyth 		return;
1049*74a4d8c2SCharles.Forsyth 
1050*74a4d8c2SCharles.Forsyth 	dmaend(mpegconf.dma);
1051*74a4d8c2SCharles.Forsyth 	if(b->nchar == 0) {
1052*74a4d8c2SCharles.Forsyth 		bqueue.head = b->link;
1053*74a4d8c2SCharles.Forsyth 		free(b);
1054*74a4d8c2SCharles.Forsyth 
1055*74a4d8c2SCharles.Forsyth 		b = bqueue.head;
1056*74a4d8c2SCharles.Forsyth 		if(b == 0) {
1057*74a4d8c2SCharles.Forsyth 			started = 0;
1058*74a4d8c2SCharles.Forsyth 			return;
1059*74a4d8c2SCharles.Forsyth 		}
1060*74a4d8c2SCharles.Forsyth 	}
1061*74a4d8c2SCharles.Forsyth 	zrdma(b);
1062*74a4d8c2SCharles.Forsyth 	wakeup(&bqueue.flow);
1063*74a4d8c2SCharles.Forsyth }
1064