xref: /plan9/sys/src/cmd/aux/vga/mga4xx.c (revision 0792d947be768a877eb2f61da0eec05e1238d60b)
19a747e4fSDavid du Colombier /* Philippe Anel <philippe.anel@noos.fr>
29a747e4fSDavid du Colombier 	- 2001-08-12 : First release.
39a747e4fSDavid du Colombier 	- 2001-08-15 : Added G450, with source code "adapted from" from Xfree86 4.1.0
49a747e4fSDavid du Colombier 	- 2001-08-23 : Added 'palettedepth 8' and a few 'ultradebug' ...
59a747e4fSDavid du Colombier 	- 2001-08-24 : Removed a possible lock in initialization.
69a747e4fSDavid du Colombier 	- 2001-08-30 : Hey ! The 32 bits mode is PALETIZED (Gamma Control I presume) !
79a747e4fSDavid du Colombier 				  And it seems plan9 assume the frame buffer is organized in
89a747e4fSDavid du Colombier 				  Big Endian format ! (+ Fix for the palette init. )
99a747e4fSDavid du Colombier 	- 2001-09-06 : Added Full 2D Accel ! (see drivers in /sys/src/9/pc)
109a747e4fSDavid du Colombier 	- 2001-10-01 : Rid Fix.
11816336a7SDavid du Colombier 	- 2006-04-01 : Add MGA550 support.
121066d6deSDavid du Colombier 	- 2006-08-07 : Add support for 16 and 24bits modes.
131066d6deSDavid du Colombier 				HW accel now works for the G200 cards too (see kernel).
141066d6deSDavid du Colombier 				by Leonardo Valencia <leoval@anixcorp.com>
159a747e4fSDavid du Colombier 
169a747e4fSDavid du Colombier      Greets and Acknowledgements go to :
179a747e4fSDavid du Colombier      	- Sylvain Chipaux <a.k.a. asle>.
189a747e4fSDavid du Colombier 	- Nigel Roles.
199a747e4fSDavid du Colombier 	- Jean Mehat (the man who introduced me into the world of plan9).
209a747e4fSDavid du Colombier 	- Nicolas Stojanovic.
219a747e4fSDavid du Colombier 		... and for those who wrote plan9 of course ... :)
229a747e4fSDavid du Colombier */
239a747e4fSDavid du Colombier 
249a747e4fSDavid du Colombier #include <u.h>
259a747e4fSDavid du Colombier #include <libc.h>
269a747e4fSDavid du Colombier #include <bio.h>
279a747e4fSDavid du Colombier 
289a747e4fSDavid du Colombier #include "pci.h"
299a747e4fSDavid du Colombier #include "vga.h"
309a747e4fSDavid du Colombier 
319a747e4fSDavid du Colombier static int	 ultradebug = 0;
329a747e4fSDavid du Colombier 
339a747e4fSDavid du Colombier /*
349a747e4fSDavid du Colombier  * Matrox G4xx 3D graphics accelerators
359a747e4fSDavid du Colombier  */
369a747e4fSDavid du Colombier enum {
379a747e4fSDavid du Colombier 	Kilo			= 1024,
389a747e4fSDavid du Colombier 	Meg			= 1024*1024,
399a747e4fSDavid du Colombier 
409a747e4fSDavid du Colombier 	MATROX			= 0x102B,	/* pci chip manufacturer */
41816336a7SDavid du Colombier 	MGA550			= 0x2527, /* pci chip device ids */
42816336a7SDavid du Colombier 	MGA4XX			= 0x0525,
439a747e4fSDavid du Colombier 	MGA200			= 0x0521,
449a747e4fSDavid du Colombier 
459a747e4fSDavid du Colombier 	/* Pci configuration space mapping */
469a747e4fSDavid du Colombier 	PCfgMgaFBAA		= 0x10,		/* Frame buffer Aperture Address */
479a747e4fSDavid du Colombier 	PCfgMgaCAA		= 0x14,		/* Control Aperture Address base */
489a747e4fSDavid du Colombier 	PCfgMgaIAA		= 0x18,		/* ILOAD Aperture base Address */
499a747e4fSDavid du Colombier 	PCfgMgaOption1		= 0x40,		/* Option Register 1 */
509a747e4fSDavid du Colombier 	PCfgMgaOption2		= 0x50,		/* Option Register 2 */
519a747e4fSDavid du Colombier 	PCfgMgaOption3		= 0x54,		/* Option Register 3 */
529a747e4fSDavid du Colombier 	PCfgMgaDevCtrl		= 0x04,		/* Device Control */
539a747e4fSDavid du Colombier 
549a747e4fSDavid du Colombier 	/* control aperture offsets */
559a747e4fSDavid du Colombier 	DMAWIN			= 0x0000,	/* 7KByte Pseudo-DMA Window */
569a747e4fSDavid du Colombier 
579a747e4fSDavid du Colombier 	STATUS0			= 0x1FC2,	/* Input Status 0 */
589a747e4fSDavid du Colombier 	STATUS1			= 0x1FDA,	/* Input Status 1 */
599a747e4fSDavid du Colombier 
609a747e4fSDavid du Colombier 	SEQIDX			= 0x1FC4,	/* Sequencer Index */
619a747e4fSDavid du Colombier 	SEQDATA			= 0x1FC5,	/* Sequencer Data */
629a747e4fSDavid du Colombier 
639a747e4fSDavid du Colombier 	MISC_W			= 0x1FC2,	/* Misc. WO */
649a747e4fSDavid du Colombier 	MISC_R			= 0x1FCC,	/* Misc. RO */
659a747e4fSDavid du Colombier 
669a747e4fSDavid du Colombier 	GCTLIDX			= 0x1FCE,	/* Graphic Controler Index */
679a747e4fSDavid du Colombier 	GCTLDATA		= 0x1FCF,	/* Graphic Controler Data */
689a747e4fSDavid du Colombier 
699a747e4fSDavid du Colombier 	CRTCIDX			= 0x1FD4,	/* CRTC Index */
709a747e4fSDavid du Colombier 	CRTCDATA		= 0x1FD5,	/* CRTC Data */
719a747e4fSDavid du Colombier 
729a747e4fSDavid du Colombier 	CRTCEXTIDX		= 0x1FDE,	/* CRTC Extension Index */
739a747e4fSDavid du Colombier 	CRTCEXTDATA		= 0x1FDF,	/* CRTC Extension Data */
749a747e4fSDavid du Colombier 
759a747e4fSDavid du Colombier 	RAMDACIDX		= 0x3C00,	/* RAMDAC registers Index */
769a747e4fSDavid du Colombier 	RAMDACDATA		= 0x3C0A,	/* RAMDAC Indexed Data */
779a747e4fSDavid du Colombier 	RAMDACPALDATA		= 0x3C01,
789a747e4fSDavid du Colombier 
799a747e4fSDavid du Colombier 	ATTRIDX			= 0x1FC0,	/* Attribute Index */
809a747e4fSDavid du Colombier 	ATTRDATA		= 0x1FC1,	/* Attribute Data */
819a747e4fSDavid du Colombier 
829a747e4fSDavid du Colombier 	CACHEFLUSH		= 0x1FFF,
839a747e4fSDavid du Colombier 
849a747e4fSDavid du Colombier 	C2_CTL			= 0X3C10,
859a747e4fSDavid du Colombier 	MGA_STATUS		= 0X1E14,
869a747e4fSDavid du Colombier 	Z_DEPTH_ORG		= 0X1C0C,
879a747e4fSDavid du Colombier 
889a747e4fSDavid du Colombier  	/* ... */
899a747e4fSDavid du Colombier 	Seq_ClockingMode =	0x01,
909a747e4fSDavid du Colombier 		Dotmode =		(1<<0),
919a747e4fSDavid du Colombier 		Shftldrt =		(1<<2),
929a747e4fSDavid du Colombier 		Dotclkrt =		(1<<3),
939a747e4fSDavid du Colombier 		Shiftfour =		(1<<4),
949a747e4fSDavid du Colombier 		Scroff =		(1<<5),
959a747e4fSDavid du Colombier 
969a747e4fSDavid du Colombier 	CrtcExt_Horizontcount =	0x01,
979a747e4fSDavid du Colombier 		Htotal =		(1<<0),
989a747e4fSDavid du Colombier 		Hblkstr =		(1<<1),
999a747e4fSDavid du Colombier 		Hsyncstr =		(1<<2),
1009a747e4fSDavid du Colombier 		Hrsten =		(1<<3),
1019a747e4fSDavid du Colombier 		Hsyncoff =		(1<<4),
1029a747e4fSDavid du Colombier 		Vsyncoff =		(1<<5),
1039a747e4fSDavid du Colombier 		Hblkend =		(1<<6),
1049a747e4fSDavid du Colombier 		Vrsten =		(1<<7),
1059a747e4fSDavid du Colombier 
1069a747e4fSDavid du Colombier 	CrtcExt_Miscellaneous =	0x03,
1079a747e4fSDavid du Colombier 		Mgamode =		(1<<7),
1089a747e4fSDavid du Colombier 
1099a747e4fSDavid du Colombier 	Dac_Xpixclkctrl =	0x1a,
1109a747e4fSDavid du Colombier 		Pixclksl = 		(3<<0),
1119a747e4fSDavid du Colombier 		Pixclkdis =		(1<<2),
1129a747e4fSDavid du Colombier 		Pixpllpdn =		(1<<3),
1139a747e4fSDavid du Colombier 
1149a747e4fSDavid du Colombier 	Dac_Xpixpllstat =	0x4f,
1159a747e4fSDavid du Colombier 		Pixlock = 		(1<<6),
1169a747e4fSDavid du Colombier 
1179a747e4fSDavid du Colombier 	Dac_Xpixpllan =		0x45,
1189a747e4fSDavid du Colombier 	Dac_Xpixpllbn =		0x49,
1199a747e4fSDavid du Colombier 	Dac_Xpixpllcn  =	0x4d,
1209a747e4fSDavid du Colombier 
1219a747e4fSDavid du Colombier 	Dac_Xpixpllam =		0x44,
1229a747e4fSDavid du Colombier 	Dac_Xpixpllbm =		0x48,
1239a747e4fSDavid du Colombier 	Dac_Xpixpllcm =		0x4c,
1249a747e4fSDavid du Colombier 
1259a747e4fSDavid du Colombier 	Dac_Xpixpllap =		0x46,
1269a747e4fSDavid du Colombier 	Dac_Xpixpllbp =		0x4a,
1279a747e4fSDavid du Colombier 	Dac_Xpixpllcp =		0x4e,
1289a747e4fSDavid du Colombier 
1299a747e4fSDavid du Colombier 	Dac_Xmulctrl =		0x19,
1309a747e4fSDavid du Colombier 		ColorDepth =		(7<<0),
1319a747e4fSDavid du Colombier 			_8bitsPerPixel = 		0,
1329a747e4fSDavid du Colombier 			_15bitsPerPixel =		1,
1339a747e4fSDavid du Colombier 			_16bitsPerPixel =		2,
1349a747e4fSDavid du Colombier 			_24bitsPerPixel =		3,
1359a747e4fSDavid du Colombier 			_32bitsPerPixelWithOv = 	4,
1369a747e4fSDavid du Colombier 			_32bitsPerPixel	=		7,
1379a747e4fSDavid du Colombier 
1389a747e4fSDavid du Colombier 	Dac_Xpanelmode =	0x1f,
1399a747e4fSDavid du Colombier 
1409a747e4fSDavid du Colombier 	Dac_Xmiscctrl =		0x1e,
1419a747e4fSDavid du Colombier 		Dacpdn =		(1<<0),
1429a747e4fSDavid du Colombier 		Mfcsel =		(3<<1),
1439a747e4fSDavid du Colombier 		Vga8dac =		(1<<3),
1449a747e4fSDavid du Colombier 		Ramcs =			(1<<4),
1459a747e4fSDavid du Colombier 		Vdoutsel =		(7<<5),
1469a747e4fSDavid du Colombier 
1479a747e4fSDavid du Colombier 	Dac_Xcurctrl =		0x06,
1489a747e4fSDavid du Colombier 		CursorDis = 		0,
1499a747e4fSDavid du Colombier 		Cursor3Color = 		1,
1509a747e4fSDavid du Colombier 		CursorXGA = 		2,
1519a747e4fSDavid du Colombier 		CursorX11 = 		3,
1529a747e4fSDavid du Colombier 		Cursor16Color = 	4,
1539a747e4fSDavid du Colombier 
1549a747e4fSDavid du Colombier 	Dac_Xzoomctrl =		0x38,
1559a747e4fSDavid du Colombier 
1569a747e4fSDavid du Colombier 	Misc_loaddsel =			(1<<0),
1579a747e4fSDavid du Colombier 	Misc_rammapen =			(1<<1),
1589a747e4fSDavid du Colombier 	Misc_clksel =			(3<<2),
1599a747e4fSDavid du Colombier 	Misc_videodis =			(1<<4),
1609a747e4fSDavid du Colombier 	Misc_hpgoddev = 		(1<<5),
1619a747e4fSDavid du Colombier 	Misc_hsyncpol =			(1<<6),
1629a747e4fSDavid du Colombier 	Misc_vsyncpol =			(1<<7),
1639a747e4fSDavid du Colombier 
1649a747e4fSDavid du Colombier 	MNP_TABLE_SIZE =	64,
1659a747e4fSDavid du Colombier 
1669a747e4fSDavid du Colombier 	TRUE = 	(1 == 1),
1679a747e4fSDavid du Colombier 	FALSE = (1 == 0),
1689a747e4fSDavid du Colombier };
1699a747e4fSDavid du Colombier 
1709a747e4fSDavid du Colombier typedef struct {
1719a747e4fSDavid du Colombier 	Pcidev*	pci;
1729a747e4fSDavid du Colombier 	int	devid;
1739a747e4fSDavid du Colombier 	int	revid;
1749a747e4fSDavid du Colombier 
17574f16c81SDavid du Colombier 	uchar*	mmio;
17674f16c81SDavid du Colombier 	uchar*	mmfb;
1779a747e4fSDavid du Colombier 	int	fbsize;
1789a747e4fSDavid du Colombier 	ulong	iload;
1799a747e4fSDavid du Colombier 
1809a747e4fSDavid du Colombier 	uchar	syspll_m;
1819a747e4fSDavid du Colombier 	uchar	syspll_n;
1829a747e4fSDavid du Colombier 	uchar	syspll_p;
1839a747e4fSDavid du Colombier 	uchar	syspll_s;
1849a747e4fSDavid du Colombier 
1859a747e4fSDavid du Colombier 	uchar	pixpll_m;
1869a747e4fSDavid du Colombier 	uchar	pixpll_n;
1879a747e4fSDavid du Colombier 	uchar	pixpll_p;
1889a747e4fSDavid du Colombier 	uchar	pixpll_s;
1899a747e4fSDavid du Colombier 
1909a747e4fSDavid du Colombier 	ulong	option1;
1919a747e4fSDavid du Colombier 	ulong	option2;
1929a747e4fSDavid du Colombier 	ulong	option3;
1939a747e4fSDavid du Colombier 
1949a747e4fSDavid du Colombier 	ulong	Fneeded;
1959a747e4fSDavid du Colombier 
1969a747e4fSDavid du Colombier 	/* From plan9.ini ... later */
1979a747e4fSDavid du Colombier 	uchar	sdram;
1989a747e4fSDavid du Colombier 	uchar	colorkey;
1999a747e4fSDavid du Colombier 	uchar	maskkey;
2009a747e4fSDavid du Colombier 	ulong	maxpclk;
2019a747e4fSDavid du Colombier 
2029a747e4fSDavid du Colombier 	uchar	graphics[9];
2039a747e4fSDavid du Colombier 	uchar	attribute[0x14];
2049a747e4fSDavid du Colombier 	uchar	sequencer[5];
2059a747e4fSDavid du Colombier 	uchar	crtc[0x19];
2069a747e4fSDavid du Colombier 	uchar	crtcext[9];
2079a747e4fSDavid du Colombier 
2089a747e4fSDavid du Colombier 	ulong	htotal;
2099a747e4fSDavid du Colombier 	ulong	hdispend;
2109a747e4fSDavid du Colombier 	ulong	hblkstr;
2119a747e4fSDavid du Colombier 	ulong	hblkend;
2129a747e4fSDavid du Colombier 	ulong	hsyncstr;
2139a747e4fSDavid du Colombier 	ulong	hsyncend;
2149a747e4fSDavid du Colombier 	ulong	vtotal;
2159a747e4fSDavid du Colombier 	ulong	vdispend;
2169a747e4fSDavid du Colombier 	ulong	vblkstr;
2179a747e4fSDavid du Colombier 	ulong	vblkend;
2189a747e4fSDavid du Colombier 	ulong	vsyncstr;
2199a747e4fSDavid du Colombier 	ulong	vsyncend;
2209a747e4fSDavid du Colombier 	ulong	linecomp;
2219a747e4fSDavid du Colombier 	ulong	hsyncsel;
2229a747e4fSDavid du Colombier 	ulong	startadd;
2239a747e4fSDavid du Colombier 	ulong	offset;
2249a747e4fSDavid du Colombier 	ulong	maxscan;
2259a747e4fSDavid du Colombier 	ulong 	curloc;
2269a747e4fSDavid du Colombier 	ulong	prowscan;
2279a747e4fSDavid du Colombier 	ulong	currowstr;
2289a747e4fSDavid du Colombier 	ulong	currowend;
2299a747e4fSDavid du Colombier 	ulong	curoff;
2309a747e4fSDavid du Colombier 	ulong	undrow;
2319a747e4fSDavid du Colombier 	ulong	curskew;
2329a747e4fSDavid du Colombier 	ulong	conv2t4;
2339a747e4fSDavid du Colombier 	ulong	interlace;
2349a747e4fSDavid du Colombier 	ulong	hsyncdel;
2359a747e4fSDavid du Colombier 	ulong	hdispskew;
2369a747e4fSDavid du Colombier 	ulong	bytepan;
2379a747e4fSDavid du Colombier 	ulong	dotclkrt;
2389a747e4fSDavid du Colombier 	ulong	dword;
2399a747e4fSDavid du Colombier 	ulong	wbmode;
2409a747e4fSDavid du Colombier 	ulong	addwrap;
2419a747e4fSDavid du Colombier 	ulong	selrowscan;
2429a747e4fSDavid du Colombier 	ulong	cms;
2439a747e4fSDavid du Colombier 	ulong	csynccen;
2449a747e4fSDavid du Colombier 	ulong	hrsten;
2459a747e4fSDavid du Colombier 	ulong	vrsten;
2469a747e4fSDavid du Colombier 	ulong	vinten;
2479a747e4fSDavid du Colombier 	ulong	vintclr;
2489a747e4fSDavid du Colombier 	ulong	hsyncoff;
2499a747e4fSDavid du Colombier 	ulong	vsyncoff;
2509a747e4fSDavid du Colombier 	ulong	crtcrstN;
2519a747e4fSDavid du Colombier 	ulong	mgamode;
2529a747e4fSDavid du Colombier 	ulong	scale;
2539a747e4fSDavid du Colombier 	ulong	hiprilvl;
2549a747e4fSDavid du Colombier 	ulong	maxhipri;
2559a747e4fSDavid du Colombier 	ulong	c2hiprilvl;
2569a747e4fSDavid du Colombier 	ulong	c2maxhipri;
2579a747e4fSDavid du Colombier 	ulong	misc;
2589a747e4fSDavid du Colombier 	ulong	crtcprotect;
2599a747e4fSDavid du Colombier 	ulong	winsize;
2609a747e4fSDavid du Colombier 	ulong	winfreq;
2619a747e4fSDavid du Colombier 
2629a747e4fSDavid du Colombier 	ulong	mgaapsize;
2639a747e4fSDavid du Colombier } Mga;
2649a747e4fSDavid du Colombier 
2659a747e4fSDavid du Colombier static void
mgawrite32(Mga * mga,int index,ulong val)2669a747e4fSDavid du Colombier mgawrite32(Mga* mga, int index, ulong val)
2679a747e4fSDavid du Colombier {
2689a747e4fSDavid du Colombier 	((ulong*)mga->mmio)[index] = val;
2699a747e4fSDavid du Colombier }
2709a747e4fSDavid du Colombier 
2719a747e4fSDavid du Colombier static ulong
mgaread32(Mga * mga,int index)2729a747e4fSDavid du Colombier mgaread32(Mga* mga, int index)
2739a747e4fSDavid du Colombier {
2749a747e4fSDavid du Colombier 	return ((ulong*)mga->mmio)[index];
2759a747e4fSDavid du Colombier }
2769a747e4fSDavid du Colombier 
2779a747e4fSDavid du Colombier static void
mgawrite8(Mga * mga,int index,uchar val)2789a747e4fSDavid du Colombier mgawrite8(Mga* mga, int index, uchar val)
2799a747e4fSDavid du Colombier {
28074f16c81SDavid du Colombier 	mga->mmio[index] = val;
2819a747e4fSDavid du Colombier }
2829a747e4fSDavid du Colombier 
2839a747e4fSDavid du Colombier static uchar
mgaread8(Mga * mga,int index)2849a747e4fSDavid du Colombier mgaread8(Mga* mga, int index)
2859a747e4fSDavid du Colombier {
28674f16c81SDavid du Colombier 	return mga->mmio[index];
2879a747e4fSDavid du Colombier }
2889a747e4fSDavid du Colombier 
2899a747e4fSDavid du Colombier static uchar
seqget(Mga * mga,int index)2909a747e4fSDavid du Colombier seqget(Mga* mga, int index)
2919a747e4fSDavid du Colombier {
2929a747e4fSDavid du Colombier 	mgawrite8(mga, SEQIDX, index);
2939a747e4fSDavid du Colombier 	return mgaread8(mga, SEQDATA);
2949a747e4fSDavid du Colombier }
2959a747e4fSDavid du Colombier 
2969a747e4fSDavid du Colombier static uchar
seqset(Mga * mga,int index,uchar set,uchar clr)2979a747e4fSDavid du Colombier seqset(Mga* mga, int index, uchar set, uchar clr)
2989a747e4fSDavid du Colombier {
2999a747e4fSDavid du Colombier 	uchar	tmp;
3009a747e4fSDavid du Colombier 
3019a747e4fSDavid du Colombier 	mgawrite8(mga, SEQIDX, index);
3029a747e4fSDavid du Colombier 	tmp = mgaread8(mga, SEQDATA);
3039a747e4fSDavid du Colombier 	mgawrite8(mga, SEQIDX, index);
3049a747e4fSDavid du Colombier 	mgawrite8(mga, SEQDATA, (tmp & ~clr) | set);
3059a747e4fSDavid du Colombier 	return tmp;
3069a747e4fSDavid du Colombier }
3079a747e4fSDavid du Colombier 
3089a747e4fSDavid du Colombier static uchar
crtcget(Mga * mga,int index)3099a747e4fSDavid du Colombier crtcget(Mga* mga, int index)
3109a747e4fSDavid du Colombier {
3119a747e4fSDavid du Colombier 	mgawrite8(mga, CRTCIDX, index);
3129a747e4fSDavid du Colombier 	return mgaread8(mga, CRTCDATA);
3139a747e4fSDavid du Colombier }
3149a747e4fSDavid du Colombier 
3159a747e4fSDavid du Colombier static uchar
crtcset(Mga * mga,int index,uchar set,uchar clr)3169a747e4fSDavid du Colombier crtcset(Mga* mga, int index, uchar set, uchar clr)
3179a747e4fSDavid du Colombier {
3189a747e4fSDavid du Colombier 	uchar	tmp;
3199a747e4fSDavid du Colombier 
3209a747e4fSDavid du Colombier 	mgawrite8(mga, CRTCIDX, index);
3219a747e4fSDavid du Colombier 	tmp = mgaread8(mga, CRTCDATA);
3229a747e4fSDavid du Colombier 	mgawrite8(mga, CRTCIDX, index);
3239a747e4fSDavid du Colombier 	mgawrite8(mga, CRTCDATA, (tmp & ~clr) | set);
3249a747e4fSDavid du Colombier 	return tmp;
3259a747e4fSDavid du Colombier }
3269a747e4fSDavid du Colombier 
3279a747e4fSDavid du Colombier static uchar
crtcextget(Mga * mga,int index)3289a747e4fSDavid du Colombier crtcextget(Mga* mga, int index)
3299a747e4fSDavid du Colombier {
3309a747e4fSDavid du Colombier 	mgawrite8(mga, CRTCEXTIDX, index);
3319a747e4fSDavid du Colombier 	return mgaread8(mga, CRTCEXTDATA);
3329a747e4fSDavid du Colombier }
3339a747e4fSDavid du Colombier 
3349a747e4fSDavid du Colombier static uchar
crtcextset(Mga * mga,int index,uchar set,uchar clr)3359a747e4fSDavid du Colombier crtcextset(Mga* mga, int index, uchar set, uchar clr)
3369a747e4fSDavid du Colombier {
3379a747e4fSDavid du Colombier 	uchar	tmp;
3389a747e4fSDavid du Colombier 
3399a747e4fSDavid du Colombier 	mgawrite8(mga, CRTCEXTIDX, index);
3409a747e4fSDavid du Colombier 	tmp = mgaread8(mga, CRTCEXTDATA);
3419a747e4fSDavid du Colombier 	mgawrite8(mga, CRTCEXTIDX, index);
3429a747e4fSDavid du Colombier 	mgawrite8(mga, CRTCEXTDATA, (tmp & ~clr) | set);
3439a747e4fSDavid du Colombier 	return tmp;
3449a747e4fSDavid du Colombier }
3459a747e4fSDavid du Colombier 
3469a747e4fSDavid du Colombier static uchar
dacget(Mga * mga,int index)3479a747e4fSDavid du Colombier dacget(Mga* mga, int index)
3489a747e4fSDavid du Colombier {
3499a747e4fSDavid du Colombier 	mgawrite8(mga, RAMDACIDX, index);
3509a747e4fSDavid du Colombier 	return mgaread8(mga, RAMDACDATA);
3519a747e4fSDavid du Colombier }
3529a747e4fSDavid du Colombier 
3539a747e4fSDavid du Colombier static uchar
dacset(Mga * mga,int index,uchar set,uchar clr)3549a747e4fSDavid du Colombier dacset(Mga* mga, int index, uchar set, uchar clr)
3559a747e4fSDavid du Colombier {
3569a747e4fSDavid du Colombier 	uchar	tmp;
3579a747e4fSDavid du Colombier 
3589a747e4fSDavid du Colombier 	mgawrite8(mga, RAMDACIDX, index);
3599a747e4fSDavid du Colombier 	tmp = mgaread8(mga, RAMDACDATA);
3609a747e4fSDavid du Colombier 	mgawrite8(mga, RAMDACIDX, index);
3619a747e4fSDavid du Colombier 	mgawrite8(mga, RAMDACDATA, (tmp & ~clr) | set);
3629a747e4fSDavid du Colombier 	return	tmp;
3639a747e4fSDavid du Colombier }
3649a747e4fSDavid du Colombier 
3659a747e4fSDavid du Colombier static uchar
gctlget(Mga * mga,int index)3669a747e4fSDavid du Colombier gctlget(Mga* mga, int index)
3679a747e4fSDavid du Colombier {
3689a747e4fSDavid du Colombier 	mgawrite8(mga, GCTLIDX, index);
3699a747e4fSDavid du Colombier 	return mgaread8(mga, GCTLDATA);
3709a747e4fSDavid du Colombier }
3719a747e4fSDavid du Colombier 
3729a747e4fSDavid du Colombier static uchar
gctlset(Mga * mga,int index,uchar set,uchar clr)3739a747e4fSDavid du Colombier gctlset(Mga* mga, int index, uchar set, uchar clr)
3749a747e4fSDavid du Colombier {
3759a747e4fSDavid du Colombier 	uchar	tmp;
3769a747e4fSDavid du Colombier 
3779a747e4fSDavid du Colombier 	mgawrite8(mga, GCTLIDX, index);
3789a747e4fSDavid du Colombier 	tmp = mgaread8(mga, GCTLDATA);
3799a747e4fSDavid du Colombier 	mgawrite8(mga, GCTLIDX, index);
3809a747e4fSDavid du Colombier 	mgawrite8(mga, GCTLDATA, (tmp & ~clr) | set);
3819a747e4fSDavid du Colombier 	return	tmp;
3829a747e4fSDavid du Colombier }
3839a747e4fSDavid du Colombier 
3849a747e4fSDavid du Colombier static uchar
attrget(Mga * mga,int index)3859a747e4fSDavid du Colombier attrget(Mga* mga, int index)
3869a747e4fSDavid du Colombier {
3879a747e4fSDavid du Colombier 	mgawrite8(mga, ATTRIDX, index);
3889a747e4fSDavid du Colombier 	return mgaread8(mga, ATTRDATA);
3899a747e4fSDavid du Colombier }
3909a747e4fSDavid du Colombier 
3919a747e4fSDavid du Colombier static uchar
attrset(Mga * mga,int index,uchar set,uchar clr)3929a747e4fSDavid du Colombier attrset(Mga* mga, int index, uchar set, uchar clr)
3939a747e4fSDavid du Colombier {
3949a747e4fSDavid du Colombier 	uchar	tmp;
3959a747e4fSDavid du Colombier 
3969a747e4fSDavid du Colombier 	mgawrite8(mga, ATTRIDX, index);
3979a747e4fSDavid du Colombier 	tmp = mgaread8(mga, ATTRDATA);
3989a747e4fSDavid du Colombier 	mgawrite8(mga, ATTRIDX, index);
3999a747e4fSDavid du Colombier 	mgawrite8(mga, ATTRDATA, (tmp & ~clr) | set);
4009a747e4fSDavid du Colombier 	return	tmp;
4019a747e4fSDavid du Colombier }
4029a747e4fSDavid du Colombier 
4039a747e4fSDavid du Colombier static uchar
miscget(Mga * mga)4049a747e4fSDavid du Colombier miscget(Mga* mga)
4059a747e4fSDavid du Colombier {
4069a747e4fSDavid du Colombier 	return mgaread8(mga, MISC_R);
4079a747e4fSDavid du Colombier }
4089a747e4fSDavid du Colombier 
4099a747e4fSDavid du Colombier static uchar
miscset(Mga * mga,uchar set,uchar clr)4109a747e4fSDavid du Colombier miscset(Mga* mga, uchar set, uchar clr)
4119a747e4fSDavid du Colombier {
4129a747e4fSDavid du Colombier 	uchar	tmp;
4139a747e4fSDavid du Colombier 
4149a747e4fSDavid du Colombier 	tmp = mgaread8(mga, MISC_R);
4159a747e4fSDavid du Colombier 	mgawrite8(mga, MISC_W, (tmp & ~clr) | set);
4169a747e4fSDavid du Colombier 	return	tmp;
4179a747e4fSDavid du Colombier }
4189a747e4fSDavid du Colombier 
4199a747e4fSDavid du Colombier /* ************************************************************ */
4209a747e4fSDavid du Colombier 
4219a747e4fSDavid du Colombier static void
dump_all_regs(Mga * mga)4229a747e4fSDavid du Colombier dump_all_regs(Mga* mga)
4239a747e4fSDavid du Colombier {
4249a747e4fSDavid du Colombier 	int	i;
4259a747e4fSDavid du Colombier 
4269a747e4fSDavid du Colombier 	for (i = 0; i < 25; i++)
4279a747e4fSDavid du Colombier 		trace("crtc[%d] = 0x%x\n", i, crtcget(mga, i));
4289a747e4fSDavid du Colombier 	for (i = 0; i < 9; i++)
4299a747e4fSDavid du Colombier 		trace("crtcext[%d] = 0x%x\n", i, crtcextget(mga, i));
4309a747e4fSDavid du Colombier 	for (i = 0; i < 5; i++)
4319a747e4fSDavid du Colombier 		trace("seq[%d] = 0x%x\n", i, seqget(mga, i));
4329a747e4fSDavid du Colombier 	for (i = 0; i < 9; i++)
4339a747e4fSDavid du Colombier 		trace("gctl[%d] = 0x%x\n", i, gctlget(mga, i));
4349a747e4fSDavid du Colombier 	trace("misc = 0x%x\n", mgaread8(mga, MISC_R));
4359a747e4fSDavid du Colombier 	for (i = 0; i < 0x87; i++)
4369a747e4fSDavid du Colombier 		trace("dac[%d] = 0x%x\n", i, dacget(mga, i));
4379a747e4fSDavid du Colombier }
4389a747e4fSDavid du Colombier 
4399a747e4fSDavid du Colombier /* ************************************************************ */
4409a747e4fSDavid du Colombier 
4419a747e4fSDavid du Colombier static void
dump(Vga * vga,Ctlr * ctlr)4429a747e4fSDavid du Colombier dump(Vga* vga, Ctlr* ctlr)
4439a747e4fSDavid du Colombier {
4449a747e4fSDavid du Colombier 	dump_all_regs(vga->private);
4459a747e4fSDavid du Colombier 	ctlr->flag |= Fdump;
4469a747e4fSDavid du Colombier }
4479a747e4fSDavid du Colombier 
4489a747e4fSDavid du Colombier static void
setpalettedepth(int depth)4499a747e4fSDavid du Colombier setpalettedepth(int depth)
4509a747e4fSDavid du Colombier {
4519a747e4fSDavid du Colombier 	int	fd;
4529a747e4fSDavid du Colombier 	char *cmd = strdup("palettedepth X");
4539a747e4fSDavid du Colombier 
4549a747e4fSDavid du Colombier 	if ((depth != 8) && (depth != 6) && (depth != 16))
4559a747e4fSDavid du Colombier 		error("mga: invalid palette depth %d\n", depth);
4569a747e4fSDavid du Colombier 
4579a747e4fSDavid du Colombier 	fd = open("#v/vgactl", OWRITE);
4589a747e4fSDavid du Colombier 	if(fd < 0)
4599a747e4fSDavid du Colombier 		error("mga: can't open vgactl\n");
4609a747e4fSDavid du Colombier 
4619a747e4fSDavid du Colombier 	cmd[13] = '0' + depth;
4629a747e4fSDavid du Colombier 	if(write(fd, cmd, 14) != 14)
4639a747e4fSDavid du Colombier 		error("mga: can't set palette depth to %d\n", depth);
4649a747e4fSDavid du Colombier 
4659a747e4fSDavid du Colombier 	close(fd);
4669a747e4fSDavid du Colombier }
4679a747e4fSDavid du Colombier 
4689a747e4fSDavid du Colombier static void
mapmga4xx(Vga * vga,Ctlr * ctlr)4699a747e4fSDavid du Colombier mapmga4xx(Vga* vga, Ctlr* ctlr)
4709a747e4fSDavid du Colombier {
4719a747e4fSDavid du Colombier 	int 	f;
47274f16c81SDavid du Colombier 	uchar* 	m;
4739a747e4fSDavid du Colombier 	Mga *	mga;
4749a747e4fSDavid du Colombier 
4759a747e4fSDavid du Colombier 	if(vga->private == nil)
4769a747e4fSDavid du Colombier 		error("%s: g4xxio: no *mga4xx\n", ctlr->name);
4779a747e4fSDavid du Colombier 	mga = vga->private;
4789a747e4fSDavid du Colombier 
4799a747e4fSDavid du Colombier 	f = open("#v/vgactl", OWRITE);
4809a747e4fSDavid du Colombier 	if(f < 0)
4819a747e4fSDavid du Colombier 		error("%s: can't open vgactl\n", ctlr->name);
4829a747e4fSDavid du Colombier 
4839a747e4fSDavid du Colombier 	if(write(f, "type mga4xx", 11) != 11)
4849a747e4fSDavid du Colombier 		error("%s: can't set mga type\n", ctlr->name);
4859a747e4fSDavid du Colombier 
4869a747e4fSDavid du Colombier 	m = segattach(0, "mga4xxmmio", 0, 16*Kilo);
48774f16c81SDavid du Colombier 	if(m == (void*)-1)
4889a747e4fSDavid du Colombier 		error("%s: can't attach mga4xxmmio segment\n", ctlr->name);
4899a747e4fSDavid du Colombier 	mga->mmio = m;
49074f16c81SDavid du Colombier 	trace("%s: mmio at %#p\n", ctlr->name, mga->mmio);
4919a747e4fSDavid du Colombier 
4929a747e4fSDavid du Colombier 	m = segattach(0, "mga4xxscreen", 0, 32*Meg);
49374f16c81SDavid du Colombier 	if(m == (void*)-1) {
4949a747e4fSDavid du Colombier 		mga->mgaapsize = 8*Meg;
4959a747e4fSDavid du Colombier 		m = segattach(0, "mga4xxscreen", 0, 8*Meg);
49674f16c81SDavid du Colombier 		if(m == (void*)-1)
4979a747e4fSDavid du Colombier 			error("%s: can't attach mga4xxscreen segment\n", ctlr->name);
4989a747e4fSDavid du Colombier 	} else {
4999a747e4fSDavid du Colombier 		mga->mgaapsize = 32*Meg;
5009a747e4fSDavid du Colombier 	}
5019a747e4fSDavid du Colombier 	mga->mmfb = m;
50274f16c81SDavid du Colombier 	trace("%s: frame buffer at %#p\n", ctlr->name, mga->mmfb);
5039a747e4fSDavid du Colombier 
5049a747e4fSDavid du Colombier 	close(f);
5059a747e4fSDavid du Colombier }
5069a747e4fSDavid du Colombier 
5079a747e4fSDavid du Colombier static void
snarf(Vga * vga,Ctlr * ctlr)5089a747e4fSDavid du Colombier snarf(Vga* vga, Ctlr* ctlr)
5099a747e4fSDavid du Colombier {
5109a747e4fSDavid du Colombier 	int 	i, k, n;
5119a747e4fSDavid du Colombier 	uchar *	p;
5129a747e4fSDavid du Colombier 	uchar	x[16];
5139a747e4fSDavid du Colombier 	Pcidev *	pci;
5149a747e4fSDavid du Colombier 	Mga *	mga;
5159a747e4fSDavid du Colombier 	uchar	crtcext3;
5169a747e4fSDavid du Colombier 	uchar	rid;
5179a747e4fSDavid du Colombier 
5189a747e4fSDavid du Colombier 	trace("%s->snarf\n", ctlr->name);
5199a747e4fSDavid du Colombier 	if(vga->private == nil) {
5209a747e4fSDavid du Colombier 		pci = pcimatch(nil, MATROX, MGA4XX);
521816336a7SDavid du Colombier 		if(pci == nil)
522816336a7SDavid du Colombier 			pci = pcimatch(nil, MATROX, MGA550);
523816336a7SDavid du Colombier 		if(pci == nil)
5249a747e4fSDavid du Colombier 			pci = pcimatch(nil, MATROX, MGA200);
525816336a7SDavid du Colombier 		if(pci == nil)
526816336a7SDavid du Colombier 			error("%s: cannot find matrox adapter\n", ctlr->name);
5279a747e4fSDavid du Colombier 
5289a747e4fSDavid du Colombier 		rid = pcicfgr8(pci, PciRID); // PciRID = 0x08
5299a747e4fSDavid du Colombier 
530816336a7SDavid du Colombier 		trace("%s: G%d%d0 rev %d\n", ctlr->name,
531816336a7SDavid du Colombier 			2*(pci->did==MGA200)
532816336a7SDavid du Colombier 			+4*(pci->did==MGA4XX)
533816336a7SDavid du Colombier 			+5*(pci->did==MGA550),
534816336a7SDavid du Colombier 			rid&0x80 ? 5 : 0,
535816336a7SDavid du Colombier 			rid&~0x80);
5369a747e4fSDavid du Colombier 		i = pcicfgr32(pci, PCfgMgaDevCtrl);
5379a747e4fSDavid du Colombier 		if ((i & 2) != 2)
5389a747e4fSDavid du Colombier 			error("%s: Memory Space not enabled ... Aborting ...\n", ctlr->name);
5399a747e4fSDavid du Colombier 
5409a747e4fSDavid du Colombier 		vga->private = alloc(sizeof(Mga));
5419a747e4fSDavid du Colombier 		mga = (Mga*)vga->private;
5429a747e4fSDavid du Colombier 		mga->devid = 	pci->did;
5439a747e4fSDavid du Colombier 		mga->revid =	rid;
5449a747e4fSDavid du Colombier 		mga->pci = 	pci;
5459a747e4fSDavid du Colombier 
5469a747e4fSDavid du Colombier 		mapmga4xx(vga, ctlr);
5479a747e4fSDavid du Colombier 	}
5489a747e4fSDavid du Colombier 	else {
5499a747e4fSDavid du Colombier 		mga = (Mga*)vga->private;
5509a747e4fSDavid du Colombier 	}
5519a747e4fSDavid du Colombier 
5529a747e4fSDavid du Colombier 	/* Find out how much memory is here, some multiple of 2Meg */
5539a747e4fSDavid du Colombier 
5549a747e4fSDavid du Colombier 	/* First Set MGA Mode ... */
5559a747e4fSDavid du Colombier 	crtcext3 = crtcextset(mga, 3, 0x80, 0x00);
5569a747e4fSDavid du Colombier 
55774f16c81SDavid du Colombier 	p = mga->mmfb;
5589a747e4fSDavid du Colombier 	n = (mga->mgaapsize / Meg) / 2;
5599a747e4fSDavid du Colombier 	for (i = 0; i < n; i++) {
5609a747e4fSDavid du Colombier 		k = (2*i+1)*Meg;
5619a747e4fSDavid du Colombier 		p[k] = 0;
5629a747e4fSDavid du Colombier 		p[k] = i+1;
56374f16c81SDavid du Colombier 		*(mga->mmio + CACHEFLUSH) = 0;
5649a747e4fSDavid du Colombier 		x[i] = p[k];
5659a747e4fSDavid du Colombier 		trace("x[%d]=%d\n", i, x[i]);
5669a747e4fSDavid du Colombier 	}
5679a747e4fSDavid du Colombier 	for(i = 1; i < n; i++)
5689a747e4fSDavid du Colombier 		if(x[i] != i+1)
5699a747e4fSDavid du Colombier 			break;
5709a747e4fSDavid du Colombier 	vga->vmz = mga->fbsize = 2*i*Meg;
5719a747e4fSDavid du Colombier 	trace("probe found %d megabytes\n", 2*i);
5729a747e4fSDavid du Colombier 
5739a747e4fSDavid du Colombier 	crtcextset(mga, 3, crtcext3, 0xff);
5749a747e4fSDavid du Colombier 
5759a747e4fSDavid du Colombier 	ctlr->flag |= Fsnarf;
5769a747e4fSDavid du Colombier }
5779a747e4fSDavid du Colombier 
5789a747e4fSDavid du Colombier static void
options(Vga * vga,Ctlr * ctlr)5799a747e4fSDavid du Colombier options(Vga* vga, Ctlr* ctlr)
5809a747e4fSDavid du Colombier {
5819a747e4fSDavid du Colombier 	if(vga->virtx & 127)
5829a747e4fSDavid du Colombier 		vga->virtx = (vga->virtx+127)&~127;
5839a747e4fSDavid du Colombier 	ctlr->flag |= Foptions;
5849a747e4fSDavid du Colombier }
5859a747e4fSDavid du Colombier 
5869a747e4fSDavid du Colombier /* ************************************************************ */
5879a747e4fSDavid du Colombier 
5889a747e4fSDavid du Colombier static void
G450ApplyPFactor(Mga *,uchar ucP,ulong * pulFIn)5899a747e4fSDavid du Colombier G450ApplyPFactor(Mga*, uchar ucP, ulong *pulFIn)
5909a747e4fSDavid du Colombier {
5919a747e4fSDavid du Colombier 	if(!(ucP & 0x40))
5929a747e4fSDavid du Colombier 	{
5939a747e4fSDavid du Colombier 		*pulFIn = *pulFIn / (2L << (ucP & 3));
5949a747e4fSDavid du Colombier 	}
5959a747e4fSDavid du Colombier }
5969a747e4fSDavid du Colombier 
5979a747e4fSDavid du Colombier 
5989a747e4fSDavid du Colombier static void
G450RemovePFactor(Mga *,uchar ucP,ulong * pulFIn)5999a747e4fSDavid du Colombier G450RemovePFactor(Mga*, uchar ucP, ulong *pulFIn)
6009a747e4fSDavid du Colombier {
6019a747e4fSDavid du Colombier 	if(!(ucP & 0x40))
6029a747e4fSDavid du Colombier 	{
6039a747e4fSDavid du Colombier 		*pulFIn = *pulFIn * (2L << (ucP & 3));
6049a747e4fSDavid du Colombier 	}
6059a747e4fSDavid du Colombier }
6069a747e4fSDavid du Colombier 
6079a747e4fSDavid du Colombier static void
G450CalculVCO(Mga *,ulong ulMNP,ulong * pulF)6089a747e4fSDavid du Colombier G450CalculVCO(Mga*, ulong ulMNP, ulong *pulF)
6099a747e4fSDavid du Colombier {
6109a747e4fSDavid du Colombier 	uchar ucM, ucN;
6119a747e4fSDavid du Colombier 
6129a747e4fSDavid du Colombier 	ucM = (uchar)((ulMNP >> 16) & 0xff);
6139a747e4fSDavid du Colombier 	ucN = (uchar)((ulMNP >>  8) & 0xff);
6149a747e4fSDavid du Colombier 
6159a747e4fSDavid du Colombier 	*pulF = (27000 * (2 * (ucN + 2)) + ((ucM + 1) >> 1)) / (ucM + 1);
6169a747e4fSDavid du Colombier 	trace("G450CalculVCO: ulMNP %lx, pulF %ld\n", ulMNP, *pulF);
6179a747e4fSDavid du Colombier }
6189a747e4fSDavid du Colombier 
6199a747e4fSDavid du Colombier 
6209a747e4fSDavid du Colombier static void
G450CalculDeltaFreq(Mga *,ulong ulF1,ulong ulF2,ulong * pulDelta)6219a747e4fSDavid du Colombier G450CalculDeltaFreq(Mga*, ulong ulF1, ulong ulF2, ulong *pulDelta)
6229a747e4fSDavid du Colombier {
6239a747e4fSDavid du Colombier 	if(ulF2 < ulF1)
6249a747e4fSDavid du Colombier 	{
6259a747e4fSDavid du Colombier 		*pulDelta = ((ulF1 - ulF2) * 1000) / ulF1;
6269a747e4fSDavid du Colombier 	}
6279a747e4fSDavid du Colombier 	else
6289a747e4fSDavid du Colombier 	{
6299a747e4fSDavid du Colombier 		*pulDelta = ((ulF2 - ulF1) * 1000) / ulF1;
6309a747e4fSDavid du Colombier 	}
6319a747e4fSDavid du Colombier 	trace("G450CalculDeltaFreq: ulF1 %ld, ulF2 %ld, pulDelta %ld\n", ulF1, ulF2, *pulDelta);
6329a747e4fSDavid du Colombier }
6339a747e4fSDavid du Colombier 
6349a747e4fSDavid du Colombier static void
G450FindNextPLLParam(Mga * mga,ulong ulFout,ulong * pulPLLMNP)6359a747e4fSDavid du Colombier G450FindNextPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP)
6369a747e4fSDavid du Colombier {
6379a747e4fSDavid du Colombier 	uchar ucM, ucN, ucP, ucS;
6389a747e4fSDavid du Colombier 	ulong ulVCO, ulVCOMin;
6399a747e4fSDavid du Colombier 
6409a747e4fSDavid du Colombier 	ucM = (uchar)((*pulPLLMNP >> 16) & 0xff);
6419a747e4fSDavid du Colombier 	/* ucN = (uchar)((*pulPLLMNP >>  8) & 0xff); */
6429a747e4fSDavid du Colombier 	ucP = (uchar)(*pulPLLMNP &  0x43);
6439a747e4fSDavid du Colombier 
6449a747e4fSDavid du Colombier 	ulVCOMin = 256000;
6459a747e4fSDavid du Colombier 
6469a747e4fSDavid du Colombier 	if(ulVCOMin >= (255L * 8000))
6479a747e4fSDavid du Colombier 	{
6489a747e4fSDavid du Colombier 		ulVCOMin = 230000;
6499a747e4fSDavid du Colombier 	}
6509a747e4fSDavid du Colombier 
6519a747e4fSDavid du Colombier 	if((ucM == 9) && (ucP & 0x40))
6529a747e4fSDavid du Colombier 	{
6539a747e4fSDavid du Colombier 		*pulPLLMNP = 0xffffffff;
6549a747e4fSDavid du Colombier 	} else if (ucM == 9)
6559a747e4fSDavid du Colombier 	{
6569a747e4fSDavid du Colombier 		if(ucP)
6579a747e4fSDavid du Colombier 		{
6589a747e4fSDavid du Colombier 			ucP--;
6599a747e4fSDavid du Colombier 		}
6609a747e4fSDavid du Colombier 		else
6619a747e4fSDavid du Colombier 		{
6629a747e4fSDavid du Colombier 			ucP = 0x40;
6639a747e4fSDavid du Colombier 		}
6649a747e4fSDavid du Colombier 		ucM = 0;
6659a747e4fSDavid du Colombier 	}
6669a747e4fSDavid du Colombier 	else
6679a747e4fSDavid du Colombier 	{
6689a747e4fSDavid du Colombier 		ucM++;
6699a747e4fSDavid du Colombier 	}
6709a747e4fSDavid du Colombier 
6719a747e4fSDavid du Colombier 	ulVCO = ulFout;
6729a747e4fSDavid du Colombier 
6739a747e4fSDavid du Colombier 	G450RemovePFactor(mga, ucP, &ulVCO);
6749a747e4fSDavid du Colombier 
6759a747e4fSDavid du Colombier 	if(ulVCO < ulVCOMin)
6769a747e4fSDavid du Colombier 	{
6779a747e4fSDavid du Colombier 		*pulPLLMNP = 0xffffffff;
6789a747e4fSDavid du Colombier 	}
6799a747e4fSDavid du Colombier 
6809a747e4fSDavid du Colombier 	if(*pulPLLMNP != 0xffffffff)
6819a747e4fSDavid du Colombier 	{
6829a747e4fSDavid du Colombier 		ucN = (uchar)(((ulVCO * (ucM+1) + 27000)/(27000 * 2)) - 2);
6839a747e4fSDavid du Colombier 
6849a747e4fSDavid du Colombier 		ucS = 5;
6859a747e4fSDavid du Colombier 		if(ulVCO < 1300000) ucS = 4;
6869a747e4fSDavid du Colombier 		if(ulVCO < 1100000) ucS = 3;
6879a747e4fSDavid du Colombier 		if(ulVCO <  900000) ucS = 2;
6889a747e4fSDavid du Colombier 		if(ulVCO <  700000) ucS = 1;
6899a747e4fSDavid du Colombier 		if(ulVCO <  550000) ucS = 0;
6909a747e4fSDavid du Colombier 
6919a747e4fSDavid du Colombier 		ucP |= (uchar)(ucS << 3);
6929a747e4fSDavid du Colombier 
6939a747e4fSDavid du Colombier 		*pulPLLMNP &= 0xff000000;
6949a747e4fSDavid du Colombier 		*pulPLLMNP |= (ulong)ucM << 16;
6959a747e4fSDavid du Colombier 		*pulPLLMNP |= (ulong)ucN << 8;
6969a747e4fSDavid du Colombier 		*pulPLLMNP |= (ulong)ucP;
6979a747e4fSDavid du Colombier 	}
6989a747e4fSDavid du Colombier }
6999a747e4fSDavid du Colombier 
7009a747e4fSDavid du Colombier static void
G450FindFirstPLLParam(Mga * mga,ulong ulFout,ulong * pulPLLMNP)7019a747e4fSDavid du Colombier G450FindFirstPLLParam(Mga* mga, ulong ulFout, ulong *pulPLLMNP)
7029a747e4fSDavid du Colombier {
7039a747e4fSDavid du Colombier 	uchar ucP;
7049a747e4fSDavid du Colombier 	ulong ulVCO;
7059a747e4fSDavid du Colombier 	ulong ulVCOMax;
7069a747e4fSDavid du Colombier 
7079a747e4fSDavid du Colombier 	/* Default value */
7089a747e4fSDavid du Colombier 	ulVCOMax = 1300000;
7099a747e4fSDavid du Colombier 
7109a747e4fSDavid du Colombier 	if(ulFout > (ulVCOMax/2))
7119a747e4fSDavid du Colombier 	{
7129a747e4fSDavid du Colombier 		ucP = 0x40;
7139a747e4fSDavid du Colombier 		ulVCO = ulFout;
7149a747e4fSDavid du Colombier 	}
7159a747e4fSDavid du Colombier 	else
7169a747e4fSDavid du Colombier 	{
7179a747e4fSDavid du Colombier 		ucP = 3;
7189a747e4fSDavid du Colombier 		ulVCO = ulFout;
7199a747e4fSDavid du Colombier 		G450RemovePFactor(mga, ucP, &ulVCO);
7209a747e4fSDavid du Colombier 		while(ucP && (ulVCO > ulVCOMax))
7219a747e4fSDavid du Colombier 		{
7229a747e4fSDavid du Colombier 			ucP--;
7239a747e4fSDavid du Colombier 			ulVCO = ulFout;
7249a747e4fSDavid du Colombier 			G450RemovePFactor(mga, ucP, &ulVCO);
7259a747e4fSDavid du Colombier 		}
7269a747e4fSDavid du Colombier 	}
7279a747e4fSDavid du Colombier 
7289a747e4fSDavid du Colombier 	if(ulVCO > ulVCOMax)
7299a747e4fSDavid du Colombier 	{
7309a747e4fSDavid du Colombier 		*pulPLLMNP = 0xffffffff;
7319a747e4fSDavid du Colombier 	}
7329a747e4fSDavid du Colombier 	else
7339a747e4fSDavid du Colombier 	{
7349a747e4fSDavid du Colombier 		/* Pixel clock: 1 */
7359a747e4fSDavid du Colombier 		*pulPLLMNP = (1 << 24) + 0xff0000 + ucP;
7369a747e4fSDavid du Colombier 		G450FindNextPLLParam(mga, ulFout, pulPLLMNP);
7379a747e4fSDavid du Colombier 	}
7389a747e4fSDavid du Colombier }
7399a747e4fSDavid du Colombier 
7409a747e4fSDavid du Colombier 
7419a747e4fSDavid du Colombier static void
G450WriteMNP(Mga * mga,ulong ulMNP)7429a747e4fSDavid du Colombier G450WriteMNP(Mga* mga, ulong ulMNP)
7439a747e4fSDavid du Colombier {
7449a747e4fSDavid du Colombier 	if (0) trace("G450WriteMNP : 0x%lx\n", ulMNP);
7459a747e4fSDavid du Colombier 	dacset(mga, Dac_Xpixpllcm, (uchar)(ulMNP >> 16), 0xff);
7469a747e4fSDavid du Colombier 	dacset(mga, Dac_Xpixpllcn, (uchar)(ulMNP >>  8), 0xff);
7479a747e4fSDavid du Colombier 	dacset(mga, Dac_Xpixpllcp, (uchar)ulMNP, 0xff);
7489a747e4fSDavid du Colombier }
7499a747e4fSDavid du Colombier 
7509a747e4fSDavid du Colombier 
7519a747e4fSDavid du Colombier static void
G450CompareMNP(Mga * mga,ulong ulFout,ulong ulMNP1,ulong ulMNP2,long * pulResult)7529a747e4fSDavid du Colombier G450CompareMNP(Mga* mga, ulong ulFout, ulong ulMNP1,
7539a747e4fSDavid du Colombier 			    ulong ulMNP2, long *pulResult)
7549a747e4fSDavid du Colombier {
7559a747e4fSDavid du Colombier 	ulong ulFreq, ulDelta1, ulDelta2;
7569a747e4fSDavid du Colombier 
7579a747e4fSDavid du Colombier 	G450CalculVCO(mga, ulMNP1, &ulFreq);
7589a747e4fSDavid du Colombier 	G450ApplyPFactor(mga, (uchar) ulMNP1, &ulFreq);
7599a747e4fSDavid du Colombier 	G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta1);
7609a747e4fSDavid du Colombier 
7619a747e4fSDavid du Colombier 	G450CalculVCO(mga, ulMNP2, &ulFreq);
7629a747e4fSDavid du Colombier 	G450ApplyPFactor(mga, (uchar) ulMNP2, &ulFreq);
7639a747e4fSDavid du Colombier 	G450CalculDeltaFreq(mga, ulFout, ulFreq, &ulDelta2);
7649a747e4fSDavid du Colombier 
7659a747e4fSDavid du Colombier 	if(ulDelta1 < ulDelta2)
7669a747e4fSDavid du Colombier 	{
7679a747e4fSDavid du Colombier 		*pulResult = -1;
7689a747e4fSDavid du Colombier 	}
7699a747e4fSDavid du Colombier 	else if(ulDelta1 > ulDelta2)
7709a747e4fSDavid du Colombier 	{
7719a747e4fSDavid du Colombier 		*pulResult = 1;
7729a747e4fSDavid du Colombier 	}
7739a747e4fSDavid du Colombier 	else
7749a747e4fSDavid du Colombier 	{
7759a747e4fSDavid du Colombier 		*pulResult = 0;
7769a747e4fSDavid du Colombier 	}
7779a747e4fSDavid du Colombier 
7789a747e4fSDavid du Colombier 	if((ulDelta1 <= 5) && (ulDelta2 <= 5))
7799a747e4fSDavid du Colombier 	{
7809a747e4fSDavid du Colombier 		if((ulMNP1 & 0xff0000) < (ulMNP2 & 0xff0000))
7819a747e4fSDavid du Colombier 		{
7829a747e4fSDavid du Colombier 			*pulResult = -1;
7839a747e4fSDavid du Colombier 		}
7849a747e4fSDavid du Colombier 		else if((ulMNP1 & 0xff0000) > (ulMNP2 & 0xff0000))
7859a747e4fSDavid du Colombier 		{
7869a747e4fSDavid du Colombier 			*pulResult = 1;
7879a747e4fSDavid du Colombier 		}
7889a747e4fSDavid du Colombier 	}
7899a747e4fSDavid du Colombier }
7909a747e4fSDavid du Colombier 
7919a747e4fSDavid du Colombier 
7929a747e4fSDavid du Colombier static void
G450IsPllLocked(Mga * mga,int * lpbLocked)7939a747e4fSDavid du Colombier G450IsPllLocked(Mga* mga, int *lpbLocked)
7949a747e4fSDavid du Colombier {
7959a747e4fSDavid du Colombier 	ulong ulFallBackCounter, ulLockCount, ulCount;
7969a747e4fSDavid du Colombier 	uchar  ucPLLStatus;
7979a747e4fSDavid du Colombier 
7989a747e4fSDavid du Colombier 	/* Pixel PLL */
7999a747e4fSDavid du Colombier 	mgawrite8(mga, 0x3c00, 0x4f);
8009a747e4fSDavid du Colombier 	ulFallBackCounter = 0;
8019a747e4fSDavid du Colombier 
8029a747e4fSDavid du Colombier 	do
8039a747e4fSDavid du Colombier 	{
8049a747e4fSDavid du Colombier 		ucPLLStatus = mgaread8(mga, 0x3c0a);
8059a747e4fSDavid du Colombier 		if (0) trace("ucPLLStatus[1] : 0x%x\n", ucPLLStatus);
8069a747e4fSDavid du Colombier 		ulFallBackCounter++;
8079a747e4fSDavid du Colombier 	} while(!(ucPLLStatus & 0x40) && (ulFallBackCounter < 1000));
8089a747e4fSDavid du Colombier 
8099a747e4fSDavid du Colombier 	ulLockCount = 0;
8109a747e4fSDavid du Colombier 	if(ulFallBackCounter < 1000)
8119a747e4fSDavid du Colombier 	{
8129a747e4fSDavid du Colombier 		for(ulCount = 0; ulCount < 100; ulCount++)
8139a747e4fSDavid du Colombier 		{
8149a747e4fSDavid du Colombier 			ucPLLStatus = mgaread8(mga, 0x3c0a);
8159a747e4fSDavid du Colombier 			if (0) trace("ucPLLStatus[2] : 0x%x\n", ucPLLStatus);
8169a747e4fSDavid du Colombier 			if(ucPLLStatus & 0x40)
8179a747e4fSDavid du Colombier 			{
8189a747e4fSDavid du Colombier 				ulLockCount++;
8199a747e4fSDavid du Colombier 			}
8209a747e4fSDavid du Colombier 		}
8219a747e4fSDavid du Colombier 	}
8229a747e4fSDavid du Colombier 
8239a747e4fSDavid du Colombier 	*lpbLocked = ulLockCount >= 90;
8249a747e4fSDavid du Colombier }
8259a747e4fSDavid du Colombier 
8269a747e4fSDavid du Colombier static void
G450SetPLLFreq(Mga * mga,long f_out)8279a747e4fSDavid du Colombier G450SetPLLFreq(Mga* mga, long f_out)
8289a747e4fSDavid du Colombier {
8299a747e4fSDavid du Colombier 	int bFoundValidPLL;
8309a747e4fSDavid du Colombier 	int bLocked;
8319a747e4fSDavid du Colombier 	ulong ulMaxIndex;
8329a747e4fSDavid du Colombier 	ulong ulMNP;
8339a747e4fSDavid du Colombier 	ulong ulMNPTable[MNP_TABLE_SIZE];
8349a747e4fSDavid du Colombier 	ulong ulIndex;
8359a747e4fSDavid du Colombier 	ulong ulTryMNP;
8369a747e4fSDavid du Colombier 	long lCompareResult;
8379a747e4fSDavid du Colombier 
8389a747e4fSDavid du Colombier 	trace("f_out : %ld\n", f_out);
8399a747e4fSDavid du Colombier 
8409a747e4fSDavid du Colombier 	G450FindFirstPLLParam(mga, f_out, &ulMNP);
8419a747e4fSDavid du Colombier 	ulMNPTable[0] = ulMNP;
8429a747e4fSDavid du Colombier 	G450FindNextPLLParam(mga, f_out, &ulMNP);
8439a747e4fSDavid du Colombier 	ulMaxIndex = 1;
8449a747e4fSDavid du Colombier 	while(ulMNP != 0xffffffff)
8459a747e4fSDavid du Colombier 	{
8469a747e4fSDavid du Colombier 		int ulIndex;
8479a747e4fSDavid du Colombier 		int bSkipValue;
8489a747e4fSDavid du Colombier 
8499a747e4fSDavid du Colombier 		bSkipValue = FALSE;
8509a747e4fSDavid du Colombier 		if(ulMaxIndex == MNP_TABLE_SIZE)
8519a747e4fSDavid du Colombier 		{
8529a747e4fSDavid du Colombier 			G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[MNP_TABLE_SIZE - 1],
8539a747e4fSDavid du Colombier 				       &lCompareResult);
8549a747e4fSDavid du Colombier 
8559a747e4fSDavid du Colombier 			if(lCompareResult > 0)
8569a747e4fSDavid du Colombier 			{
8579a747e4fSDavid du Colombier 				bSkipValue = TRUE;
8589a747e4fSDavid du Colombier 			}
8599a747e4fSDavid du Colombier 			else
8609a747e4fSDavid du Colombier 			{
8619a747e4fSDavid du Colombier 				ulMaxIndex--;
8629a747e4fSDavid du Colombier 			}
8639a747e4fSDavid du Colombier 		}
8649a747e4fSDavid du Colombier 
8659a747e4fSDavid du Colombier 		if(!bSkipValue)
8669a747e4fSDavid du Colombier 		{
8679a747e4fSDavid du Colombier 			for(ulIndex = ulMaxIndex; !bSkipValue && (ulIndex > 0); ulIndex--)
8689a747e4fSDavid du Colombier 			{
8699a747e4fSDavid du Colombier 				G450CompareMNP(mga, f_out, ulMNP, ulMNPTable[ulIndex - 1],
8709a747e4fSDavid du Colombier 					       &lCompareResult);
8719a747e4fSDavid du Colombier 
8729a747e4fSDavid du Colombier 				if(lCompareResult < 0)
8739a747e4fSDavid du Colombier 				{
8749a747e4fSDavid du Colombier 					ulMNPTable[ulIndex] = ulMNPTable[ulIndex - 1];
8759a747e4fSDavid du Colombier 				}
8769a747e4fSDavid du Colombier 				else
8779a747e4fSDavid du Colombier 				{
8789a747e4fSDavid du Colombier 					break;
8799a747e4fSDavid du Colombier 				}
8809a747e4fSDavid du Colombier 			}
8819a747e4fSDavid du Colombier 			ulMNPTable[ulIndex] = ulMNP;
8829a747e4fSDavid du Colombier 			ulMaxIndex++;
8839a747e4fSDavid du Colombier 		}
8849a747e4fSDavid du Colombier 
8859a747e4fSDavid du Colombier 		G450FindNextPLLParam(mga, f_out, &ulMNP);
8869a747e4fSDavid du Colombier 	}
8879a747e4fSDavid du Colombier 
8889a747e4fSDavid du Colombier 	bFoundValidPLL = FALSE;
8899a747e4fSDavid du Colombier 	ulMNP = 0;
8909a747e4fSDavid du Colombier 
8919a747e4fSDavid du Colombier 	for(ulIndex = 0; !bFoundValidPLL && (ulIndex < ulMaxIndex); ulIndex++)
8929a747e4fSDavid du Colombier 	{
8939a747e4fSDavid du Colombier 		ulTryMNP = ulMNPTable[ulIndex];
8949a747e4fSDavid du Colombier 
8959a747e4fSDavid du Colombier 		{
8969a747e4fSDavid du Colombier 			bLocked = TRUE;
8979a747e4fSDavid du Colombier 			if((ulMNPTable[ulIndex] & 0xff00) < 0x300 ||
8989a747e4fSDavid du Colombier 			   (ulMNPTable[ulIndex] & 0xff00) > 0x7a00)
8999a747e4fSDavid du Colombier 			{
9009a747e4fSDavid du Colombier 				bLocked = FALSE;
9019a747e4fSDavid du Colombier 			}
9029a747e4fSDavid du Colombier 
9039a747e4fSDavid du Colombier 			if(bLocked)
9049a747e4fSDavid du Colombier 			{
9059a747e4fSDavid du Colombier 				G450WriteMNP(mga, ulTryMNP - 0x300);
9069a747e4fSDavid du Colombier 				G450IsPllLocked(mga, &bLocked);
9079a747e4fSDavid du Colombier 			}
9089a747e4fSDavid du Colombier 
9099a747e4fSDavid du Colombier 			if(bLocked)
9109a747e4fSDavid du Colombier 			{
9119a747e4fSDavid du Colombier 				G450WriteMNP(mga, ulTryMNP + 0x300);
9129a747e4fSDavid du Colombier 				G450IsPllLocked(mga, &bLocked);
9139a747e4fSDavid du Colombier 			}
9149a747e4fSDavid du Colombier 
9159a747e4fSDavid du Colombier 			if(bLocked)
9169a747e4fSDavid du Colombier 			{
9179a747e4fSDavid du Colombier 				G450WriteMNP(mga, ulTryMNP - 0x200);
9189a747e4fSDavid du Colombier 				G450IsPllLocked(mga, &bLocked);
9199a747e4fSDavid du Colombier 			}
9209a747e4fSDavid du Colombier 
9219a747e4fSDavid du Colombier 			if(bLocked)
9229a747e4fSDavid du Colombier 			{
9239a747e4fSDavid du Colombier 				G450WriteMNP(mga, ulTryMNP + 0x200);
9249a747e4fSDavid du Colombier 				G450IsPllLocked(mga, &bLocked);
9259a747e4fSDavid du Colombier 			}
9269a747e4fSDavid du Colombier 
9279a747e4fSDavid du Colombier 			if(bLocked)
9289a747e4fSDavid du Colombier 			{
9299a747e4fSDavid du Colombier 				G450WriteMNP(mga, ulTryMNP - 0x100);
9309a747e4fSDavid du Colombier 				G450IsPllLocked(mga, &bLocked);
9319a747e4fSDavid du Colombier 			}
9329a747e4fSDavid du Colombier 
9339a747e4fSDavid du Colombier 			if(bLocked)
9349a747e4fSDavid du Colombier 			{
9359a747e4fSDavid du Colombier 				G450WriteMNP(mga, ulTryMNP + 0x100);
9369a747e4fSDavid du Colombier 				G450IsPllLocked(mga, &bLocked);
9379a747e4fSDavid du Colombier 			}
9389a747e4fSDavid du Colombier 
9399a747e4fSDavid du Colombier 			if(bLocked)
9409a747e4fSDavid du Colombier 			{
9419a747e4fSDavid du Colombier 				G450WriteMNP(mga, ulTryMNP);
9429a747e4fSDavid du Colombier 				G450IsPllLocked(mga, &bLocked);
9439a747e4fSDavid du Colombier 			}
9449a747e4fSDavid du Colombier 			else if(!ulMNP)
9459a747e4fSDavid du Colombier 			{
9469a747e4fSDavid du Colombier 				G450WriteMNP(mga, ulTryMNP);
9479a747e4fSDavid du Colombier 				G450IsPllLocked(mga, &bLocked);
9489a747e4fSDavid du Colombier 				if(bLocked)
9499a747e4fSDavid du Colombier 				{
9509a747e4fSDavid du Colombier 					ulMNP = ulMNPTable[ulIndex];
9519a747e4fSDavid du Colombier 				}
9529a747e4fSDavid du Colombier 				bLocked = FALSE;
9539a747e4fSDavid du Colombier 			}
9549a747e4fSDavid du Colombier 
9559a747e4fSDavid du Colombier 			if(bLocked)
9569a747e4fSDavid du Colombier 			{
9579a747e4fSDavid du Colombier 				bFoundValidPLL = TRUE;
9589a747e4fSDavid du Colombier 			}
9599a747e4fSDavid du Colombier 		}
9609a747e4fSDavid du Colombier 	}
9619a747e4fSDavid du Colombier 
9629a747e4fSDavid du Colombier 	if(!bFoundValidPLL)
9639a747e4fSDavid du Colombier 	{
9649a747e4fSDavid du Colombier 		if(ulMNP)
9659a747e4fSDavid du Colombier 		{
9669a747e4fSDavid du Colombier 			G450WriteMNP(mga, ulMNP);
9679a747e4fSDavid du Colombier 		}
9689a747e4fSDavid du Colombier 		else
9699a747e4fSDavid du Colombier 		{
9709a747e4fSDavid du Colombier 			G450WriteMNP(mga, ulMNPTable[0]);
9719a747e4fSDavid du Colombier 		}
9729a747e4fSDavid du Colombier 	}
9739a747e4fSDavid du Colombier }
9749a747e4fSDavid du Colombier 
9759a747e4fSDavid du Colombier 
9769a747e4fSDavid du Colombier /* ************************************************************ */
9779a747e4fSDavid du Colombier 
9789a747e4fSDavid du Colombier /*
9799a747e4fSDavid du Colombier 	calcclock - Calculate the PLL settings (m, n, p, s).
9809a747e4fSDavid du Colombier */
9819a747e4fSDavid du Colombier static double
g400_calcclock(Mga * mga,long Fneeded)9829a747e4fSDavid du Colombier g400_calcclock(Mga* mga, long Fneeded)
9839a747e4fSDavid du Colombier {
9849a747e4fSDavid du Colombier 	double	Fpll;
9859a747e4fSDavid du Colombier 	double	Fvco;
9869a747e4fSDavid du Colombier 	double 	Fref;
9879a747e4fSDavid du Colombier 	int		pixpll_m_min;
9889a747e4fSDavid du Colombier 	int		pixpll_m_max;
9899a747e4fSDavid du Colombier 	int		pixpll_n_min;
9909a747e4fSDavid du Colombier 	int		pixpll_n_max;
9919a747e4fSDavid du Colombier 	int		pixpll_p_max;
9929a747e4fSDavid du Colombier 	double 	Ferr, Fcalc;
9939a747e4fSDavid du Colombier 	int		m, n, p;
9949a747e4fSDavid du Colombier 
995816336a7SDavid du Colombier 	if (mga->devid == MGA4XX || mga->devid == MGA550) {
9969a747e4fSDavid du Colombier 		/* These values are taken from Matrox G400 Specification - p 4-91 */
9979a747e4fSDavid du Colombier 		Fref     		= 27000000.0;
9989a747e4fSDavid du Colombier 		pixpll_n_min 	= 7;
9999a747e4fSDavid du Colombier 		pixpll_n_max 	= 127;
10009a747e4fSDavid du Colombier 		pixpll_m_min	= 1;
10019a747e4fSDavid du Colombier 		pixpll_m_max	= 31;
10029a747e4fSDavid du Colombier 		pixpll_p_max 	= 7;
1003816336a7SDavid du Colombier 	} else { 				/* MGA200 */
10049a747e4fSDavid du Colombier 		/* These values are taken from Matrox G200 Specification - p 4-77 */
10059a747e4fSDavid du Colombier 		//Fref     		= 14318180.0;
10069a747e4fSDavid du Colombier 		Fref     		= 27050500.0;
10079a747e4fSDavid du Colombier 		pixpll_n_min 	= 7;
10089a747e4fSDavid du Colombier 		pixpll_n_max 	= 127;
10099a747e4fSDavid du Colombier 		pixpll_m_min	= 1;
10109a747e4fSDavid du Colombier 		pixpll_m_max	= 6;
10119a747e4fSDavid du Colombier 		pixpll_p_max 	= 7;
10129a747e4fSDavid du Colombier 	}
10139a747e4fSDavid du Colombier 
10149a747e4fSDavid du Colombier 	Fvco = ( double ) Fneeded;
10159a747e4fSDavid du Colombier 	for (p = 0;  p <= pixpll_p_max && Fvco < mga->maxpclk; p = p * 2 + 1, Fvco *= 2.0)
10169a747e4fSDavid du Colombier 		;
10179a747e4fSDavid du Colombier 	mga->pixpll_p = p;
10189a747e4fSDavid du Colombier 
10199a747e4fSDavid du Colombier 	Ferr = Fneeded;
10209a747e4fSDavid du Colombier 	for ( m = pixpll_m_min ; m <= pixpll_m_max ; m++ )
10219a747e4fSDavid du Colombier 		for ( n = pixpll_n_min; n <= pixpll_n_max; n++ )
10229a747e4fSDavid du Colombier 		{
10239a747e4fSDavid du Colombier 			Fcalc = Fref * (n + 1) / (m + 1) ;
10249a747e4fSDavid du Colombier 
10259a747e4fSDavid du Colombier 			/*
10269a747e4fSDavid du Colombier 			 * Pick the closest frequency.
10279a747e4fSDavid du Colombier 			 */
10289a747e4fSDavid du Colombier 			if ( labs(Fcalc - Fvco) < Ferr ) {
10299a747e4fSDavid du Colombier 				Ferr = abs(Fcalc - Fvco);
10309a747e4fSDavid du Colombier 				mga->pixpll_m = m;
10319a747e4fSDavid du Colombier 				mga->pixpll_n = n;
10329a747e4fSDavid du Colombier 			}
10339a747e4fSDavid du Colombier 		}
10349a747e4fSDavid du Colombier 
10359a747e4fSDavid du Colombier 	Fvco = Fref * (mga->pixpll_n + 1) / (mga->pixpll_m + 1);
10369a747e4fSDavid du Colombier 
1037816336a7SDavid du Colombier 	if (mga->devid == MGA4XX || mga->devid == MGA550) {
10389a747e4fSDavid du Colombier 		if ( (50000000.0 <= Fvco) && (Fvco < 110000000.0) )
10399a747e4fSDavid du Colombier 			mga->pixpll_p |= 0;
10409a747e4fSDavid du Colombier 		if ( (110000000.0 <= Fvco) && (Fvco < 170000000.0) )
10419a747e4fSDavid du Colombier 			mga->pixpll_p |= (1<<3);
10429a747e4fSDavid du Colombier 		if ( (170000000.0 <= Fvco) && (Fvco < 240000000.0) )
10439a747e4fSDavid du Colombier 			mga->pixpll_p |= (2<<3);
10449a747e4fSDavid du Colombier 		if ( (300000000.0 <= Fvco) )
10459a747e4fSDavid du Colombier 			mga->pixpll_p |= (3<<3);
10469a747e4fSDavid du Colombier 	} else {
10479a747e4fSDavid du Colombier 		if ( (50000000.0 <= Fvco) && (Fvco < 100000000.0) )
10489a747e4fSDavid du Colombier 			mga->pixpll_p |= 0;
10499a747e4fSDavid du Colombier 		if ( (100000000.0 <= Fvco) && (Fvco < 140000000.0) )
10509a747e4fSDavid du Colombier 			mga->pixpll_p |= (1<<3);
10519a747e4fSDavid du Colombier 		if ( (140000000.0 <= Fvco) && (Fvco < 180000000.0) )
10529a747e4fSDavid du Colombier 			mga->pixpll_p |= (2<<3);
10539a747e4fSDavid du Colombier 		if ( (250000000.0 <= Fvco) )
10549a747e4fSDavid du Colombier 			mga->pixpll_p |= (3<<3);
10559a747e4fSDavid du Colombier 	}
10569a747e4fSDavid du Colombier 
10579a747e4fSDavid du Colombier 	Fpll = Fvco / (p + 1);
10589a747e4fSDavid du Colombier 
10599a747e4fSDavid du Colombier 	return Fpll;
10609a747e4fSDavid du Colombier }
10619a747e4fSDavid du Colombier 
10629a747e4fSDavid du Colombier /* ************************************************************ */
10639a747e4fSDavid du Colombier 
10649a747e4fSDavid du Colombier static void
init(Vga * vga,Ctlr * ctlr)10659a747e4fSDavid du Colombier init(Vga* vga, Ctlr* ctlr)
10669a747e4fSDavid du Colombier {
10679a747e4fSDavid du Colombier 	Mode*	mode;
10689a747e4fSDavid du Colombier 	Mga*	mga;
10699a747e4fSDavid du Colombier 	double	Fpll;
10709a747e4fSDavid du Colombier 	Ctlr*	c;
10719a747e4fSDavid du Colombier 	int	i;
10729a747e4fSDavid du Colombier 	ulong	t;
10731066d6deSDavid du Colombier 	int     bppShift;
10749a747e4fSDavid du Colombier 
10759a747e4fSDavid du Colombier 	mga = vga->private;
10769a747e4fSDavid du Colombier 	mode = vga->mode;
10779a747e4fSDavid du Colombier 
107874f16c81SDavid du Colombier 	trace("mga mmio at %#p\n", mga->mmio);
10799a747e4fSDavid du Colombier 
10809a747e4fSDavid du Colombier 	ctlr->flag |= Ulinear;
10819a747e4fSDavid du Colombier 
10821066d6deSDavid du Colombier 	/*
1083*0792d947SDavid du Colombier 	 * Set the right bppShift based on depth
10841066d6deSDavid du Colombier 	 */
10851066d6deSDavid du Colombier 
10861066d6deSDavid du Colombier 	switch(mode->z) {
10871066d6deSDavid du Colombier 	case 8:
10881066d6deSDavid du Colombier 		bppShift = 0;
10891066d6deSDavid du Colombier 		break;
10901066d6deSDavid du Colombier 	case 16:
10911066d6deSDavid du Colombier 		bppShift = 1;
10921066d6deSDavid du Colombier 		break;
10931066d6deSDavid du Colombier 	case 24:
10941066d6deSDavid du Colombier 		bppShift = 0;
10951066d6deSDavid du Colombier 		break;
10961066d6deSDavid du Colombier 	case 32:
10971066d6deSDavid du Colombier 		bppShift = 2;
10981066d6deSDavid du Colombier 		break;
10991066d6deSDavid du Colombier 	default:
11001066d6deSDavid du Colombier 		bppShift = 0;
11019a747e4fSDavid du Colombier 		error("depth %d not supported !\n", mode->z);
11021066d6deSDavid du Colombier 	}
11039a747e4fSDavid du Colombier 
11049a747e4fSDavid du Colombier 	if (mode->interlace)
11059a747e4fSDavid du Colombier 		error("interlaced mode not supported !\n");
11069a747e4fSDavid du Colombier 
11079a747e4fSDavid du Colombier 	trace("%s: Initializing mode %dx%dx%d on %s\n", ctlr->name, mode->x, mode->y, mode->z, mode->type);
11089a747e4fSDavid du Colombier 	trace("%s: Suggested Dot Clock : %d\n", 	ctlr->name, mode->frequency);
11099a747e4fSDavid du Colombier 	trace("%s: Horizontal Total = %d\n", 		ctlr->name, mode->ht);
11109a747e4fSDavid du Colombier 	trace("%s: Start Horizontal Blank = %d\n", ctlr->name, mode->shb);
11119a747e4fSDavid du Colombier 	trace("%s: End Horizontal Blank = %d\n", 	ctlr->name, mode->ehb);
11129a747e4fSDavid du Colombier 	trace("%s: Vertical Total = %d\n", 		ctlr->name, mode->vt);
11139a747e4fSDavid du Colombier 	trace("%s: Vertical Retrace Start = %d\n", 	ctlr->name, mode->vrs);
11149a747e4fSDavid du Colombier 	trace("%s: Vertical Retrace End = %d\n", 	ctlr->name, mode->vre);
11159a747e4fSDavid du Colombier 	trace("%s: Start Horizontal Sync = %d\n", 	ctlr->name, mode->shs);
11169a747e4fSDavid du Colombier 	trace("%s: End Horizontal Sync = %d\n", 	ctlr->name, mode->ehs);
11179a747e4fSDavid du Colombier 	trace("%s: HSync = %c\n", 			ctlr->name, mode->hsync);
11189a747e4fSDavid du Colombier 	trace("%s: VSync = %c\n", 				ctlr->name, mode->vsync);
11199a747e4fSDavid du Colombier 	trace("%s: Interlace = %d\n", 			ctlr->name, mode->interlace);
11209a747e4fSDavid du Colombier 
11219a747e4fSDavid du Colombier 	/* TODO : G400 Max : 360000000 */
1122816336a7SDavid du Colombier 	if (mga->devid == MGA4XX || mga->devid == MGA550)
11239a747e4fSDavid du Colombier 		mga->maxpclk	= 300000000;
11249a747e4fSDavid du Colombier 	else
11259a747e4fSDavid du Colombier 		mga->maxpclk	= 250000000;
11269a747e4fSDavid du Colombier 
11279a747e4fSDavid du Colombier 	if (mode->frequency < 50000)
11288cf6001eSDavid du Colombier 		error("mga: Too little Frequency %d : Minimum supported by PLL is %d\n",
11299a747e4fSDavid du Colombier 			mode->frequency, 50000);
11309a747e4fSDavid du Colombier 
11319a747e4fSDavid du Colombier 	if (mode->frequency > mga->maxpclk)
11328cf6001eSDavid du Colombier 		error("mga: Too big Frequency %d : Maximum supported by PLL is %ld\n",
11339a747e4fSDavid du Colombier 			mode->frequency, mga->maxpclk);
11349a747e4fSDavid du Colombier 
11359a747e4fSDavid du Colombier 	trace("mga: revision ID is %x\n", mga->revid);
1136816336a7SDavid du Colombier 	if ((mga->devid == MGA200) || ((mga->devid == MGA4XX) && (mga->revid & 0x80) == 0x00)) {
11379a747e4fSDavid du Colombier 		/* Is it G200/G400 or G450 ? */
11389a747e4fSDavid du Colombier 		Fpll = g400_calcclock(mga, mode->frequency);
11399a747e4fSDavid du Colombier 		trace("Fpll set to %f\n", Fpll);
11409a747e4fSDavid du Colombier 		trace("pixclks : n = %d m = %d p = %d\n", mga->pixpll_n, mga->pixpll_m, mga->pixpll_p & 0x7);
11419a747e4fSDavid du Colombier 	} else
11429a747e4fSDavid du Colombier 		mga->Fneeded = mode->frequency;
11439a747e4fSDavid du Colombier 
11449a747e4fSDavid du Colombier 	trace("PCI Option1 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption1));
11459a747e4fSDavid du Colombier 	trace("PCI Option2 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption2));
11469a747e4fSDavid du Colombier 	trace("PCI Option3 = 0x%x\n", pcicfgr32(mga->pci, PCfgMgaOption3));
11479a747e4fSDavid du Colombier 
11489a747e4fSDavid du Colombier 	mga->htotal =			(mode->ht >> 3) - 5;
11499a747e4fSDavid du Colombier 	mga->hdispend =		(mode->x >> 3) - 1;
11509a747e4fSDavid du Colombier 	mga->hblkstr =		mga->hdispend; 		/* (mode->shb >> 3); */
11519a747e4fSDavid du Colombier 	mga->hblkend =		mga->htotal + 4;		/* (mode->ehb >> 3); */
11529a747e4fSDavid du Colombier 	mga->hsyncstr =		(mode->shs >> 3) - 1;	// Was (mode->shs >> 3);
11539a747e4fSDavid du Colombier 	mga->hsyncend =		(mode->ehs >> 3) - 1;	// Was (mode->ehs >> 3);
11549a747e4fSDavid du Colombier 	mga->hsyncdel = 		0;
11559a747e4fSDavid du Colombier 	mga->vtotal =			mode->vt - 2;
11569a747e4fSDavid du Colombier 	mga->vdispend = 		mode->y - 1;
11579a747e4fSDavid du Colombier 	mga->vblkstr = 		mode->y - 1;
11589a747e4fSDavid du Colombier 	mga->vblkend = 		mode->vt - 1;
11599a747e4fSDavid du Colombier 	mga->vsyncstr = 		mode->vrs;
11609a747e4fSDavid du Colombier 	mga->vsyncend = 		mode->vre;
11619a747e4fSDavid du Colombier 	mga->linecomp =		mode->y;
11629a747e4fSDavid du Colombier 	mga->hsyncsel = 		0;					/* Do not double lines ... */
11639a747e4fSDavid du Colombier 	mga->startadd =		0;
11641066d6deSDavid du Colombier 	mga->offset =		(mode->z==24) ? (vga->virtx * 3) >> (4 - bppShift) : vga->virtx >> (4-bppShift);
11659a747e4fSDavid du Colombier 	/* No Zoom */
11669a747e4fSDavid du Colombier 	mga->maxscan = 		0;
11679a747e4fSDavid du Colombier 	/* Not used in Power Graphic mode */
11689a747e4fSDavid du Colombier 	mga->curloc =			0;
11699a747e4fSDavid du Colombier 	mga->prowscan = 		0;
11709a747e4fSDavid du Colombier 	mga->currowstr = 		0;
11719a747e4fSDavid du Colombier 	mga->currowend = 		0;
11729a747e4fSDavid du Colombier 	mga->curoff = 		1;
11739a747e4fSDavid du Colombier 	mga->undrow = 		0;
11749a747e4fSDavid du Colombier 	mga->curskew = 		0;
11759a747e4fSDavid du Colombier 	mga->conv2t4 = 		0;
11769a747e4fSDavid du Colombier 	mga->interlace =		0;
11779a747e4fSDavid du Colombier 	mga->hdispskew =		0;
11789a747e4fSDavid du Colombier 	mga->bytepan = 		0;
11799a747e4fSDavid du Colombier 	mga->dotclkrt = 		0;
11809a747e4fSDavid du Colombier 	mga->dword =			0;
11819a747e4fSDavid du Colombier 	mga->wbmode =		1;
11829a747e4fSDavid du Colombier 	mga->addwrap = 		0;	/* Not Used ! */
11839a747e4fSDavid du Colombier 	mga->selrowscan =		1;
11849a747e4fSDavid du Colombier 	mga->cms =			1;
11859a747e4fSDavid du Colombier 	mga->csynccen =		0; 	/* Disable composite sync */
11869a747e4fSDavid du Colombier 
11879a747e4fSDavid du Colombier 	/* VIDRST Pin */
11889a747e4fSDavid du Colombier 	mga->hrsten =			0; 	// Was 1;
11899a747e4fSDavid du Colombier 	mga->vrsten =			0; 	// Was 1;
11909a747e4fSDavid du Colombier 
11919a747e4fSDavid du Colombier 	/* vertical interrupt control ... disabled */
11929a747e4fSDavid du Colombier 	mga->vinten = 		1;
11939a747e4fSDavid du Colombier 	mga->vintclr = 		0;
11949a747e4fSDavid du Colombier 
11959a747e4fSDavid du Colombier 	/* Let [hv]sync run freely */
11969a747e4fSDavid du Colombier 	mga->hsyncoff =		0;
11979a747e4fSDavid du Colombier 	mga->vsyncoff =		0;
11989a747e4fSDavid du Colombier 
11999a747e4fSDavid du Colombier 	mga->crtcrstN =		1;
12009a747e4fSDavid du Colombier 
12019a747e4fSDavid du Colombier 	mga->mgamode = 		1;
12021066d6deSDavid du Colombier 	mga->scale   =		(mode->z == 24) ? ((1 << bppShift)*3)-1 : (1 << bppShift)-1;
12039a747e4fSDavid du Colombier 
12049a747e4fSDavid du Colombier 	mga->crtcprotect =      1;
12059a747e4fSDavid du Colombier 	mga->winsize = 		0;
12069a747e4fSDavid du Colombier 	mga->winfreq = 		0;
12079a747e4fSDavid du Colombier 
12089a747e4fSDavid du Colombier 	if ((mga->htotal == 0)
12099a747e4fSDavid du Colombier 	    || (mga->hblkend <= (mga->hblkstr + 1))
12109a747e4fSDavid du Colombier 	    || ((mga->htotal - mga->hdispend) == 0)
12119a747e4fSDavid du Colombier 	    || ((mga->htotal - mga->bytepan + 2) <= mga->hdispend)
12129a747e4fSDavid du Colombier 	    || (mga->hsyncstr <= (mga->hdispend + 2))
12139a747e4fSDavid du Colombier 	    || (mga->vtotal == 0))
12149a747e4fSDavid du Colombier 	{
12159a747e4fSDavid du Colombier 		error("Invalid Power Graphic Mode :\n"
12169a747e4fSDavid du Colombier 		      "mga->htotal = %ld\n"
12179a747e4fSDavid du Colombier 		      "mga->hdispend = %ld\n"
12189a747e4fSDavid du Colombier 		      "mga->hblkstr = %ld\n"
12199a747e4fSDavid du Colombier 		      "mga->hblkend = %ld\n"
12209a747e4fSDavid du Colombier 		      "mga->hsyncstr = %ld\n"
12219a747e4fSDavid du Colombier 		      "mga->hsyncend = %ld\n"
12229a747e4fSDavid du Colombier 		      "mga->hsyncdel = %ld\n"
12239a747e4fSDavid du Colombier 		      "mga->vtotal = %ld\n"
12249a747e4fSDavid du Colombier 		      "mga->vdispend = %ld\n"
12259a747e4fSDavid du Colombier 		      "mga->vblkstr = %ld\n"
12269a747e4fSDavid du Colombier 		      "mga->vblkend = %ld\n"
12279a747e4fSDavid du Colombier 		      "mga->vsyncstr = %ld\n"
12289a747e4fSDavid du Colombier 		      "mga->vsyncend = %ld\n"
12299a747e4fSDavid du Colombier 		      "mga->linecomp = %ld\n",
12309a747e4fSDavid du Colombier 		      mga->htotal,
12319a747e4fSDavid du Colombier 		      mga->hdispend,
12329a747e4fSDavid du Colombier 		      mga->hblkstr,
12339a747e4fSDavid du Colombier 		      mga->hblkend,
12349a747e4fSDavid du Colombier 		      mga->hsyncstr,
12359a747e4fSDavid du Colombier 		      mga->hsyncend,
12369a747e4fSDavid du Colombier 		      mga->hsyncdel,
12379a747e4fSDavid du Colombier 		      mga->vtotal,
12389a747e4fSDavid du Colombier 		      mga->vdispend,
12399a747e4fSDavid du Colombier 		      mga->vblkstr,
12409a747e4fSDavid du Colombier 		      mga->vblkend,
12419a747e4fSDavid du Colombier 		      mga->vsyncstr,
12429a747e4fSDavid du Colombier 		      mga->vsyncend,
12439a747e4fSDavid du Colombier 		      mga->linecomp
12449a747e4fSDavid du Colombier 		      );
12459a747e4fSDavid du Colombier 	}
12469a747e4fSDavid du Colombier 
12479a747e4fSDavid du Colombier 	mga->hiprilvl = 0;
12489a747e4fSDavid du Colombier 	mga->maxhipri = 0;
12499a747e4fSDavid du Colombier 	mga->c2hiprilvl = 0;
12509a747e4fSDavid du Colombier 	mga->c2maxhipri = 0;
12519a747e4fSDavid du Colombier 
12529a747e4fSDavid du Colombier 	mga->misc = ((mode->hsync != '-')?0:(1<<6)) | ((mode->vsync != '-')?0:(1<<7));
12539a747e4fSDavid du Colombier 
12549a747e4fSDavid du Colombier 	trace("mga->htotal = %ld\n"
12559a747e4fSDavid du Colombier 		      "mga->hdispend = %ld\n"
12569a747e4fSDavid du Colombier 		      "mga->hblkstr = %ld\n"
12579a747e4fSDavid du Colombier 		      "mga->hblkend = %ld\n"
12589a747e4fSDavid du Colombier 		      "mga->hsyncstr = %ld\n"
12599a747e4fSDavid du Colombier 		      "mga->hsyncend = %ld\n"
12609a747e4fSDavid du Colombier 		      "mga->hsyncdel = %ld\n"
12619a747e4fSDavid du Colombier 		      "mga->vtotal = %ld\n"
12629a747e4fSDavid du Colombier 		      "mga->vdispend = %ld\n"
12639a747e4fSDavid du Colombier 		      "mga->vblkstr = %ld\n"
12649a747e4fSDavid du Colombier 		      "mga->vblkend = %ld\n"
12659a747e4fSDavid du Colombier 		      "mga->vsyncstr = %ld\n"
12669a747e4fSDavid du Colombier 		      "mga->vsyncend = %ld\n"
12679a747e4fSDavid du Colombier 		      "mga->linecomp = %ld\n",
12689a747e4fSDavid du Colombier 		      mga->htotal,
12699a747e4fSDavid du Colombier 		      mga->hdispend,
12709a747e4fSDavid du Colombier 		      mga->hblkstr,
12719a747e4fSDavid du Colombier 		      mga->hblkend,
12729a747e4fSDavid du Colombier 		      mga->hsyncstr,
12739a747e4fSDavid du Colombier 		      mga->hsyncend,
12749a747e4fSDavid du Colombier 		      mga->hsyncdel,
12759a747e4fSDavid du Colombier 		      mga->vtotal,
12769a747e4fSDavid du Colombier 		      mga->vdispend,
12779a747e4fSDavid du Colombier 		      mga->vblkstr,
12789a747e4fSDavid du Colombier 		      mga->vblkend,
12799a747e4fSDavid du Colombier 		      mga->vsyncstr,
12809a747e4fSDavid du Colombier 		      mga->vsyncend,
12819a747e4fSDavid du Colombier 		      mga->linecomp
12829a747e4fSDavid du Colombier 		      );
12839a747e4fSDavid du Colombier 
12849a747e4fSDavid du Colombier 	mga->crtc[0x00] = 0xff & mga->htotal;
12859a747e4fSDavid du Colombier 
12869a747e4fSDavid du Colombier 	mga->crtc[0x01] = 0xff & mga->hdispend;
12879a747e4fSDavid du Colombier 
12889a747e4fSDavid du Colombier 	mga->crtc[0x02] = 0xff & mga->hblkstr;
12899a747e4fSDavid du Colombier 
12909a747e4fSDavid du Colombier 	mga->crtc[0x03] = (0x1f & mga->hblkend)
12919a747e4fSDavid du Colombier 		| ((0x03 & mga->hdispskew) << 5)
12929a747e4fSDavid du Colombier 		| 0x80	/* cf 3-304 */
12939a747e4fSDavid du Colombier 		;
12949a747e4fSDavid du Colombier 
12959a747e4fSDavid du Colombier 	mga->crtc[0x04] = 0xff & mga->hsyncstr;
12969a747e4fSDavid du Colombier 
12979a747e4fSDavid du Colombier 	mga->crtc[0x05] = (0x1f & mga->hsyncend)
12989a747e4fSDavid du Colombier 		| ((0x03 & mga->hsyncdel) << 5)
12999a747e4fSDavid du Colombier 		| ((0x01 & (mga->hblkend >> 5)) << 7)
13009a747e4fSDavid du Colombier 		;
13019a747e4fSDavid du Colombier 
13029a747e4fSDavid du Colombier 	mga->crtc[0x06] = 0xff & mga->vtotal;
13039a747e4fSDavid du Colombier 
13049a747e4fSDavid du Colombier 	t = ((0x01 & (mga->vtotal >> 8)) << 0)
13059a747e4fSDavid du Colombier 	  | ((0x01 & (mga->vdispend >> 8)) << 1)
13069a747e4fSDavid du Colombier 	  | ((0x01 & (mga->vsyncstr >> 8)) << 2)
13079a747e4fSDavid du Colombier 	  | ((0x01 & (mga->vblkstr >> 8)) << 3)
13089a747e4fSDavid du Colombier 	  | ((0x01 & (mga->linecomp >> 8)) << 4)
13099a747e4fSDavid du Colombier 	  | ((0x01 & (mga->vtotal >> 9)) << 5)
13109a747e4fSDavid du Colombier 	  | ((0x01 & (mga->vdispend >> 9)) << 6)
13119a747e4fSDavid du Colombier 	  | ((0x01 & (mga->vsyncstr >> 9)) << 7)
13129a747e4fSDavid du Colombier 	  ;
13139a747e4fSDavid du Colombier 	mga->crtc[0x07] = 0xff & t;
13149a747e4fSDavid du Colombier 
13159a747e4fSDavid du Colombier 	mga->crtc[0x08] = (0x1f & mga->prowscan)
13169a747e4fSDavid du Colombier 		| ((0x03 & mga->bytepan) << 5)
13179a747e4fSDavid du Colombier 		;
13189a747e4fSDavid du Colombier 
13199a747e4fSDavid du Colombier 	mga->crtc[0x09] = (0x1f & mga->maxscan)
13209a747e4fSDavid du Colombier 		| ((0x01 & (mga->vblkstr >> 9)) << 5)
13219a747e4fSDavid du Colombier 		| ((0x01 & (mga->linecomp >> 9)) << 6)
13229a747e4fSDavid du Colombier 		| ((0x01 & mga->conv2t4) << 7)
13239a747e4fSDavid du Colombier 		;
13249a747e4fSDavid du Colombier 
13259a747e4fSDavid du Colombier 	mga->crtc[0x0a] = (0x1f & mga->currowstr)
13269a747e4fSDavid du Colombier 		| ((0x01 & mga->curoff) << 5)
13279a747e4fSDavid du Colombier 		;
13289a747e4fSDavid du Colombier 
13299a747e4fSDavid du Colombier 	mga->crtc[0x0b] = (0x1f & mga->currowend)
13309a747e4fSDavid du Colombier 		| ((0x03 & mga->curskew) << 5)
13319a747e4fSDavid du Colombier 		;
13329a747e4fSDavid du Colombier 
13339a747e4fSDavid du Colombier 	mga->crtc[0x0c] = 0xff & (mga->startadd >> 8);
13349a747e4fSDavid du Colombier 
13359a747e4fSDavid du Colombier 	mga->crtc[0x0d] = 0xff & mga->startadd;
13369a747e4fSDavid du Colombier 
13379a747e4fSDavid du Colombier 	mga->crtc[0x0e] = 0xff & (mga->curloc >> 8);
13389a747e4fSDavid du Colombier 
13399a747e4fSDavid du Colombier 	mga->crtc[0x0f] = 0xff & mga->curloc;
13409a747e4fSDavid du Colombier 
13419a747e4fSDavid du Colombier 	mga->crtc[0x10] = 0xff & mga->vsyncstr;
13429a747e4fSDavid du Colombier 
13439a747e4fSDavid du Colombier 	mga->crtc[0x11] = (0x0f & mga->vsyncend)
13449a747e4fSDavid du Colombier 		| ((0x01 & mga->vintclr) << 4)
13459a747e4fSDavid du Colombier 		| ((0x01 & mga->vinten) << 5)
13469a747e4fSDavid du Colombier 		| ((0x01 & mga->crtcprotect) << 7)
13479a747e4fSDavid du Colombier 		;
13489a747e4fSDavid du Colombier 
13499a747e4fSDavid du Colombier 	mga->crtc[0x12] = 0xff & mga->vdispend;
13509a747e4fSDavid du Colombier 
13519a747e4fSDavid du Colombier 	mga->crtc[0x13] = 0xff & mga->offset;
13529a747e4fSDavid du Colombier 
13539a747e4fSDavid du Colombier 	mga->crtc[0x14] = 0x1f & mga->undrow;	/* vga only */
13549a747e4fSDavid du Colombier 
13559a747e4fSDavid du Colombier 	mga->crtc[0x15] = 0xff & mga->vblkstr;
13569a747e4fSDavid du Colombier 
13579a747e4fSDavid du Colombier 	mga->crtc[0x16] = 0xff & mga->vblkend;
13589a747e4fSDavid du Colombier 
13599a747e4fSDavid du Colombier 	mga->crtc[0x17] = ((0x01 & mga->cms) << 0)
13609a747e4fSDavid du Colombier 		| ((0x01 & mga->selrowscan) << 1)
13619a747e4fSDavid du Colombier 		| ((0x01 & mga->hsyncsel) << 2)
13629a747e4fSDavid du Colombier 		| ((0x01 & mga->addwrap) << 5)
13639a747e4fSDavid du Colombier 		| ((0x01 & mga->wbmode) << 6)
13649a747e4fSDavid du Colombier 		| ((0x01 & mga->crtcrstN) << 7)
13659a747e4fSDavid du Colombier 		;
13669a747e4fSDavid du Colombier 
13679a747e4fSDavid du Colombier 	mga->crtc[0x18] = 0xff & mga->linecomp;
13689a747e4fSDavid du Colombier 
13699a747e4fSDavid du Colombier 	mga->crtcext[0] = (0x0f & (mga->startadd >> 16))
13709a747e4fSDavid du Colombier 		| ((0x03 & (mga->offset >> 8)) << 4)
13719a747e4fSDavid du Colombier 		| ((0x01 & (mga->startadd >> 20)) << 6)
13729a747e4fSDavid du Colombier 		| ((0x01 & mga->interlace) << 7)
13739a747e4fSDavid du Colombier 		;
13749a747e4fSDavid du Colombier 
13759a747e4fSDavid du Colombier 	mga->crtcext[1] = ((0x01 & (mga->htotal >> 8)) << 0)
13769a747e4fSDavid du Colombier 		| ((0x01 & (mga->hblkstr >> 8)) << 1)
13779a747e4fSDavid du Colombier 		| ((0x01 & (mga->hsyncstr >> 8)) << 2)
13789a747e4fSDavid du Colombier 		| ((0x01 & mga->hrsten) << 3)
13799a747e4fSDavid du Colombier 		| ((0x01 & mga->hsyncoff) << 4)
13809a747e4fSDavid du Colombier 		| ((0x01 & mga->vsyncoff) << 5)
13819a747e4fSDavid du Colombier 		| ((0x01 & (mga->hblkend >> 6)) << 6)
13829a747e4fSDavid du Colombier 		| ((0x01 & mga->vrsten) << 7)
13839a747e4fSDavid du Colombier 		;
13849a747e4fSDavid du Colombier 
13859a747e4fSDavid du Colombier 	mga->crtcext[2] = ((0x03 & (mga->vtotal >> 10)) << 0)
13869a747e4fSDavid du Colombier 		| ((0x01 & (mga->vdispend >> 10)) << 2)
13879a747e4fSDavid du Colombier 		| ((0x03 & (mga->vblkstr >> 10)) << 3)
13889a747e4fSDavid du Colombier 		| ((0x03 & (mga->vsyncstr >> 10)) << 5)
13899a747e4fSDavid du Colombier 		| ((0x01 & (mga->linecomp >> 10)) << 7)
13909a747e4fSDavid du Colombier 		;
13919a747e4fSDavid du Colombier 
13929a747e4fSDavid du Colombier 	mga->crtcext[3] = ((0x07 & mga->scale) << 0)
13939a747e4fSDavid du Colombier 		| ((0x01 & mga->csynccen) << 6)
13949a747e4fSDavid du Colombier 		| ((0x01 & mga->mgamode) << 7)
13959a747e4fSDavid du Colombier 		;
13969a747e4fSDavid du Colombier 
13979a747e4fSDavid du Colombier 	mga->crtcext[4] = 0;	/* memory page ... not used in Power Graphic Mode */
13989a747e4fSDavid du Colombier 
13999a747e4fSDavid du Colombier 	mga->crtcext[5] = 0;	/* Not used in non-interlaced mode */
14009a747e4fSDavid du Colombier 
14019a747e4fSDavid du Colombier 	mga->crtcext[6] = ((0x07 & mga->hiprilvl) << 0)
14029a747e4fSDavid du Colombier 		| ((0x07 & mga->maxhipri) << 4)
14039a747e4fSDavid du Colombier 		;
14049a747e4fSDavid du Colombier 
14059a747e4fSDavid du Colombier 	mga->crtcext[7] = ((0x07 & mga->winsize) << 1)
14069a747e4fSDavid du Colombier 		| ((0x07 & mga->winfreq) << 5)
14079a747e4fSDavid du Colombier 		;
14089a747e4fSDavid du Colombier 
14099a747e4fSDavid du Colombier 	mga->crtcext[8] = (0x01 & (mga->startadd >> 21)) << 0;
14109a747e4fSDavid du Colombier 
14119a747e4fSDavid du Colombier 	/* Initialize Sequencer */
14129a747e4fSDavid du Colombier 	mga->sequencer[0] = 0;
14139a747e4fSDavid du Colombier 	mga->sequencer[1] = 0;
14149a747e4fSDavid du Colombier 	mga->sequencer[2] = 0x03;
14159a747e4fSDavid du Colombier 	mga->sequencer[3] = 0;
14169a747e4fSDavid du Colombier 	mga->sequencer[4] = 0x02;
14179a747e4fSDavid du Colombier 
14189a747e4fSDavid du Colombier 	/* Graphic Control registers are ignored when not using 0xA0000 aperture */
14199a747e4fSDavid du Colombier 	for (i = 0; i < 9; i++)
14209a747e4fSDavid du Colombier 		mga->graphics[i] = 0;
14219a747e4fSDavid du Colombier 
14229a747e4fSDavid du Colombier 	/* The Attribute Controler is not available in Power Graphics mode */
14239a747e4fSDavid du Colombier 	for (i = 0; i < 0x15; i++)
14249a747e4fSDavid du Colombier 		mga->attribute[i] = i;
14259a747e4fSDavid du Colombier 
14269a747e4fSDavid du Colombier 	/* disable vga load (want to do fields in different order) */
14279a747e4fSDavid du Colombier 	for(c = vga->link; c; c = c->link)
14289a747e4fSDavid du Colombier 		if (strncmp(c->name, "vga", 3) == 0)
14299a747e4fSDavid du Colombier 			c->load = nil;
14309a747e4fSDavid du Colombier }
14319a747e4fSDavid du Colombier 
14329a747e4fSDavid du Colombier static void
load(Vga * vga,Ctlr * ctlr)14339a747e4fSDavid du Colombier load(Vga* vga, Ctlr* ctlr)
14349a747e4fSDavid du Colombier {
14359a747e4fSDavid du Colombier 	Mga*	mga;
14369a747e4fSDavid du Colombier 	int	i;
14379a747e4fSDavid du Colombier 	uchar*	p;
14389a747e4fSDavid du Colombier 	Mode*	mode;
14399a747e4fSDavid du Colombier 	uchar	cursor;
14409a747e4fSDavid du Colombier 
14419a747e4fSDavid du Colombier 	mga = vga->private;
14429a747e4fSDavid du Colombier 	mode = vga->mode;
14439a747e4fSDavid du Colombier 
14449a747e4fSDavid du Colombier 	trace("mga: Loading ...\n");
14459a747e4fSDavid du Colombier 	dump_all_regs(mga);
14469a747e4fSDavid du Colombier 
14479a747e4fSDavid du Colombier 	if (mode->z == 8)
14489a747e4fSDavid du Colombier 		setpalettedepth(mode->z);
14499a747e4fSDavid du Colombier 
145074f16c81SDavid du Colombier 	trace("mga mmio at %#p\n", mga->mmio);
14519a747e4fSDavid du Colombier 	trace("mga: loading vga registers ...\n" );
14529a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
14539a747e4fSDavid du Colombier 
14549a747e4fSDavid du Colombier 	/* Initialize Sequencer registers */
14559a747e4fSDavid du Colombier 	for(i = 0; i < 5; i++)
14569a747e4fSDavid du Colombier 		seqset(mga, i, mga->sequencer[i], 0xff);
14579a747e4fSDavid du Colombier 
14589a747e4fSDavid du Colombier 	/* Initialize Attribute register */
14599a747e4fSDavid du Colombier 	for(i = 0; i < 0x15; i++)
14609a747e4fSDavid du Colombier 		attrset(mga, i, mga->attribute[i], 0xff);
14619a747e4fSDavid du Colombier 
14629a747e4fSDavid du Colombier 	/* Initialize Graphic Control registers */
14639a747e4fSDavid du Colombier 	for(i = 0; i < 9; i++)
14649a747e4fSDavid du Colombier 		gctlset(mga, i, mga->graphics[i], 0xff);
14659a747e4fSDavid du Colombier 
14669a747e4fSDavid du Colombier 	/* Wait VSYNC */
14679a747e4fSDavid du Colombier 	while (mgaread8(mga, STATUS1) & 0x08);
14689a747e4fSDavid du Colombier 	while (! (mgaread8(mga, STATUS1) & ~0x08));
14699a747e4fSDavid du Colombier 
14709a747e4fSDavid du Colombier 	/* Turn off the video. */
14719a747e4fSDavid du Colombier 	seqset(mga, Seq_ClockingMode, Scroff, 0);
14729a747e4fSDavid du Colombier 
14739a747e4fSDavid du Colombier 	/* Crtc2 Off */
14749a747e4fSDavid du Colombier 	mgawrite32(mga, C2_CTL, 0);
14759a747e4fSDavid du Colombier 
14769a747e4fSDavid du Colombier 	/* Disable Cursor */
14779a747e4fSDavid du Colombier 	cursor = dacset(mga, Dac_Xcurctrl, CursorDis, 0xff);
14789a747e4fSDavid du Colombier 
14799a747e4fSDavid du Colombier 	/* Pixel Pll UP and set Pixel clock source to Pixel Clock PLL */
14809a747e4fSDavid du Colombier 	dacset(mga, Dac_Xpixclkctrl, 0x01 | 0x08, 0x0f);
14819a747e4fSDavid du Colombier 
14829a747e4fSDavid du Colombier 	trace("mga: waiting for the clock source becomes stable ...\n");
14839a747e4fSDavid du Colombier 	while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
14849a747e4fSDavid du Colombier 		;
14859a747e4fSDavid du Colombier 	trace("mga: pixpll locked !\n");
14869a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
14879a747e4fSDavid du Colombier 
14889a747e4fSDavid du Colombier 	/* Enable LUT, Disable MAFC */
14899a747e4fSDavid du Colombier 	dacset(mga, Dac_Xmiscctrl, Ramcs | Mfcsel, Vdoutsel);
14909a747e4fSDavid du Colombier 
14919a747e4fSDavid du Colombier 	/* Disable Dac */
14929a747e4fSDavid du Colombier 	dacset(mga, Dac_Xmiscctrl, 0, Dacpdn);
14939a747e4fSDavid du Colombier 
14949a747e4fSDavid du Colombier 	/* Initialize Panel Mode */
14959a747e4fSDavid du Colombier 	dacset(mga, Dac_Xpanelmode, 0, 0xff);
14969a747e4fSDavid du Colombier 
14979a747e4fSDavid du Colombier 	/* Disable the PIXCLK and set Pixel clock source to Pixel Clock PLL */
14989a747e4fSDavid du Colombier 	dacset(mga, Dac_Xpixclkctrl, Pixclkdis | 0x01, 0x3);
14999a747e4fSDavid du Colombier 
15009a747e4fSDavid du Colombier 	/* Disable mapping of the memory */
15019a747e4fSDavid du Colombier 	miscset(mga, 0, Misc_rammapen);
15029a747e4fSDavid du Colombier 
15039a747e4fSDavid du Colombier 	/* Enable 8 bit palette */
15049a747e4fSDavid du Colombier 	dacset(mga, Dac_Xmiscctrl, Vga8dac, 0);
15059a747e4fSDavid du Colombier 
15069a747e4fSDavid du Colombier 	/* Select MGA Pixel Clock */
15079a747e4fSDavid du Colombier 	miscset(mga, Misc_clksel, 0);
15089a747e4fSDavid du Colombier 
15099a747e4fSDavid du Colombier 	/* Initialize Z Buffer ... (useful?) */
15109a747e4fSDavid du Colombier 	mgawrite32(mga, Z_DEPTH_ORG, 0);
15119a747e4fSDavid du Colombier 
15129a747e4fSDavid du Colombier 	/* Wait */
15139a747e4fSDavid du Colombier 	for (i = 0; i < 50; i++)
15149a747e4fSDavid du Colombier 		mgaread32(mga, MGA_STATUS);
15159a747e4fSDavid du Colombier 
1516816336a7SDavid du Colombier 	if ((mga->devid == MGA200) || ((mga->devid == MGA4XX) && (mga->revid & 0x80) == 0x00)) {
15179a747e4fSDavid du Colombier 		dacset(mga, Dac_Xpixpllcm, mga->pixpll_m, 0xff);
15189a747e4fSDavid du Colombier 		dacset(mga, Dac_Xpixpllcn, mga->pixpll_n, 0xff);
15199a747e4fSDavid du Colombier 		dacset(mga, Dac_Xpixpllcp, mga->pixpll_p, 0xff);
15209a747e4fSDavid du Colombier 
15219a747e4fSDavid du Colombier 		/* Wait until new clock becomes stable */
15229a747e4fSDavid du Colombier 		trace("mga: waiting for the clock source becomes stable ...\n");
15239a747e4fSDavid du Colombier 		while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
15249a747e4fSDavid du Colombier 			;
15259a747e4fSDavid du Colombier 		trace("mga: pixpll locked !\n");
15269a747e4fSDavid du Colombier 	} else {
1527816336a7SDavid du Colombier 	/* MGA450 and MGA550 */
15289a747e4fSDavid du Colombier 		/* Wait until new clock becomes stable */
15299a747e4fSDavid du Colombier 		trace("mga450: waiting for the clock source becomes stable ...\n");
15309a747e4fSDavid du Colombier 		while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
15319a747e4fSDavid du Colombier 			;
15329a747e4fSDavid du Colombier 		trace("mga: pixpll locked !\n");
15339a747e4fSDavid du Colombier 
15349a747e4fSDavid du Colombier 		G450SetPLLFreq(mga, (long) mga->Fneeded / 1000);
15359a747e4fSDavid du Colombier 	}
15369a747e4fSDavid du Colombier 
15379a747e4fSDavid du Colombier 	/* Enable Pixel Clock Oscillation */
15389a747e4fSDavid du Colombier 	dacset(mga, Dac_Xpixclkctrl, 0, Pixclkdis);
15399a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
15409a747e4fSDavid du Colombier 
15419a747e4fSDavid du Colombier 	/* Enable Dac */
15429a747e4fSDavid du Colombier 	dacset(mga, Dac_Xmiscctrl, Dacpdn, 0);
15439a747e4fSDavid du Colombier 
15449a747e4fSDavid du Colombier 	/* Set Video Mode */
15459a747e4fSDavid du Colombier 	switch (mode->z) {
15469a747e4fSDavid du Colombier 	case 8:
15479a747e4fSDavid du Colombier 		dacset(mga, Dac_Xmulctrl, _8bitsPerPixel, ColorDepth);
15489a747e4fSDavid du Colombier 		break;
15491066d6deSDavid du Colombier 	case 16:
15501066d6deSDavid du Colombier 		dacset(mga, Dac_Xmulctrl, _16bitsPerPixel, ColorDepth);
15511066d6deSDavid du Colombier 		break;
15521066d6deSDavid du Colombier 	case 24:
15531066d6deSDavid du Colombier 		dacset(mga, Dac_Xmulctrl, _24bitsPerPixel, ColorDepth);
15541066d6deSDavid du Colombier 		break;
15559a747e4fSDavid du Colombier 	case 32:
15569a747e4fSDavid du Colombier 		dacset(mga, Dac_Xmulctrl, _32bitsPerPixel, ColorDepth);
15579a747e4fSDavid du Colombier 		break;
15589a747e4fSDavid du Colombier 	default:
15599a747e4fSDavid du Colombier 		error("Unsupported depth %d\n", mode->z);
15609a747e4fSDavid du Colombier 	}
15619a747e4fSDavid du Colombier 
15629a747e4fSDavid du Colombier 	/* Wait */
15639a747e4fSDavid du Colombier 	for (i = 0; i < 50; i++)
15649a747e4fSDavid du Colombier 		mgaread32(mga, MGA_STATUS);
15659a747e4fSDavid du Colombier 
15669a747e4fSDavid du Colombier 	/* Wait until new clock becomes stable */
15679a747e4fSDavid du Colombier 	trace("mga: waiting for the clock source becomes stable ...\n");
15689a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
15699a747e4fSDavid du Colombier 	while ((dacget(mga, Dac_Xpixpllstat) & Pixlock) != Pixlock)
15709a747e4fSDavid du Colombier 		;
15719a747e4fSDavid du Colombier 	trace("mga: pixpll locked !\n");
15729a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
15739a747e4fSDavid du Colombier 
15749a747e4fSDavid du Colombier 	/* Initialize CRTC registers and remove irq */
15759a747e4fSDavid du Colombier 	crtcset(mga, 0x11, (1<<4), (1<<5)|0x80);
15769a747e4fSDavid du Colombier 	for (i = 0; i < 25; i++)
15779a747e4fSDavid du Colombier 		crtcset(mga, i, mga->crtc[i], 0xff);
15789a747e4fSDavid du Colombier 
15799a747e4fSDavid du Colombier 	trace("mga: crtc loaded !\n");
15809a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
15819a747e4fSDavid du Colombier 
15829a747e4fSDavid du Colombier 	/* Initialize CRTC Extension registers */
15839a747e4fSDavid du Colombier 	for (i = 0; i < 9; i++)
15849a747e4fSDavid du Colombier 		crtcextset(mga, i, mga->crtcext[i], 0xff);
15859a747e4fSDavid du Colombier 
15869a747e4fSDavid du Colombier 	trace("mga: ext loaded !\n");
15879a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
15889a747e4fSDavid du Colombier 
15899a747e4fSDavid du Colombier 	/* Disable Zoom */
15909a747e4fSDavid du Colombier 	dacset(mga, Dac_Xzoomctrl, 0, 0xff);
15919a747e4fSDavid du Colombier 
15929a747e4fSDavid du Colombier 	trace("mga: XzoomCtrl Loaded !\n");
15939a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
15949a747e4fSDavid du Colombier 
15959a747e4fSDavid du Colombier 	/* Enable mga mode again ... Just in case :) */
15969a747e4fSDavid du Colombier 	crtcextset(mga, CrtcExt_Miscellaneous, Mgamode, 0);
15979a747e4fSDavid du Colombier 
15989a747e4fSDavid du Colombier 	trace("mga: crtcext MgaMode loaded !\n");
15999a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
16009a747e4fSDavid du Colombier 
16011066d6deSDavid du Colombier 	if (mode->z == 32 || mode->z == 24 ) {
16029a747e4fSDavid du Colombier 		/* Initialize Big Endian Mode ! */
16039a747e4fSDavid du Colombier 		mgawrite32(mga, 0x1e54, 0x02 << 16);
16049a747e4fSDavid du Colombier 	}
16059a747e4fSDavid du Colombier 
16061066d6deSDavid du Colombier 
16079a747e4fSDavid du Colombier 	/* Set final misc ... enable mapping ... */
16089a747e4fSDavid du Colombier 	miscset(mga, mga->misc | Misc_rammapen, 0);
16099a747e4fSDavid du Colombier 
16109a747e4fSDavid du Colombier 	trace("mga: mapping enabled !\n");
16119a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
16129a747e4fSDavid du Colombier 
16139a747e4fSDavid du Colombier 	/* Enable Screen */
16149a747e4fSDavid du Colombier 	seqset(mga, 1, 0, 0xff);
16159a747e4fSDavid du Colombier 
16169a747e4fSDavid du Colombier 	trace("screen enabled ...\n");
16179a747e4fSDavid du Colombier 
16189a747e4fSDavid du Colombier 	if (0) {
161974f16c81SDavid du Colombier 		p = mga->mmfb;
16209a747e4fSDavid du Colombier 		for (i = 0; i < mga->fbsize; i++)
16219a747e4fSDavid du Colombier 			*p++ = (0xff & i);
16229a747e4fSDavid du Colombier 	}
16239a747e4fSDavid du Colombier 
16249a747e4fSDavid du Colombier 	trace("mga: Loaded !\n" );
16259a747e4fSDavid du Colombier 	dump_all_regs(mga);
16269a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
16279a747e4fSDavid du Colombier 
16289a747e4fSDavid du Colombier 	trace("mga: Loaded [bis]!\n" );
16299a747e4fSDavid du Colombier 
16301066d6deSDavid du Colombier 	/*
16311066d6deSDavid du Colombier 	 * TODO: In 16bpp mode, what is the correct palette ?
16321066d6deSDavid du Colombier 	 *       in the meantime lets use the default one,
16331066d6deSDavid du Colombier 	 *       which has a weird color combination.
16341066d6deSDavid du Colombier 	 */
16351066d6deSDavid du Colombier 
16361066d6deSDavid du Colombier 	if (mode->z != 8 && mode ->z != 16) {
16379a747e4fSDavid du Colombier 		/* Initialize Palette */
16389a747e4fSDavid du Colombier 		mgawrite8(mga, RAMDACIDX, 0);
16399a747e4fSDavid du Colombier 		for (i = 0; i < 0x100; i++) {
16409a747e4fSDavid du Colombier 			mgawrite8(mga, RAMDACPALDATA, i);
16419a747e4fSDavid du Colombier 			mgawrite8(mga, RAMDACPALDATA, i);
16429a747e4fSDavid du Colombier 			mgawrite8(mga, RAMDACPALDATA, i);
16439a747e4fSDavid du Colombier 		}
16449a747e4fSDavid du Colombier 	}
16451066d6deSDavid du Colombier 
16469a747e4fSDavid du Colombier 	trace("mga: Palette initialised !\n");
16479a747e4fSDavid du Colombier 
16489a747e4fSDavid du Colombier 	/* Enable Cursor */
16499a747e4fSDavid du Colombier 	dacset(mga, Dac_Xcurctrl, cursor, 0xff);
16509a747e4fSDavid du Colombier 
16519a747e4fSDavid du Colombier 	ctlr->flag |= Fload;
16529a747e4fSDavid du Colombier 	if (ultradebug) Bflush(&stdout);
16539a747e4fSDavid du Colombier }
16549a747e4fSDavid du Colombier 
16559a747e4fSDavid du Colombier Ctlr mga4xx = {
16569a747e4fSDavid du Colombier 	"mga4xx",			/* name */
16579a747e4fSDavid du Colombier 	snarf,				/* snarf */
16589a747e4fSDavid du Colombier 	options,				/* options */
16599a747e4fSDavid du Colombier 	init,					/* init */
16609a747e4fSDavid du Colombier 	load,					/* load */
16619a747e4fSDavid du Colombier 	dump,				/* dump */
16629a747e4fSDavid du Colombier };
16639a747e4fSDavid du Colombier 
16649a747e4fSDavid du Colombier Ctlr mga4xxhwgc = {
16659a747e4fSDavid du Colombier 	"mga4xxhwgc",		/* name */
16669a747e4fSDavid du Colombier 	0,					/* snarf */
16679a747e4fSDavid du Colombier 	0,					/* options */
16689a747e4fSDavid du Colombier 	0,					/* init */
16699a747e4fSDavid du Colombier 	0,					/* load */
16709a747e4fSDavid du Colombier 	dump,				/* dump */
16719a747e4fSDavid du Colombier };
1672