ark_driver.c revision 3e51e026
1943345d3Smrg/*
2943345d3Smrg *	Copyright 2000	Ani Joshi <ajoshi@unixbox.com>
3943345d3Smrg *
4943345d3Smrg *	XFree86 4.x driver for ARK Logic chipset
5943345d3Smrg *
6943345d3Smrg * Permission to use, copy, modify, distribute, and sell this software and its
7943345d3Smrg * documentation for any purpose is hereby granted without fee, provided that
8943345d3Smrg * the above copyright notice appear in all copies and that both that copyright
9943345d3Smrg * notice and this permission notice appear in supporting documentation and
10943345d3Smrg * that the name of Ani Joshi not be used in advertising or
11943345d3Smrg * publicity pertaining to distribution of the software without specific,
12943345d3Smrg * written prior permission.  Ani Joshi makes no representations
13943345d3Smrg * about the suitability of this software for any purpose.  It is provided
14943345d3Smrg * "as-is" without express or implied warranty.
15943345d3Smrg *
16943345d3Smrg * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17943345d3Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18943345d3Smrg * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19943345d3Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20943345d3Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21943345d3Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22943345d3Smrg * PERFORMANCE OF THIS SOFTWARE.
23943345d3Smrg *
24943345d3Smrg *
25943345d3Smrg *	Based on the 3.3.x driver by:
26943345d3Smrg *		Harm Hanemaayer <H.Hanemaayer@inter.nl.net>
27943345d3Smrg *
28943345d3Smrg */
29943345d3Smrg
30943345d3Smrg#ifdef HAVE_CONFIG_H
31943345d3Smrg#include "config.h"
32943345d3Smrg#endif
33943345d3Smrg
34943345d3Smrg#include "xf86.h"
35943345d3Smrg#include "xf86_OSproc.h"
36943345d3Smrg#include "xf86Pci.h"
37943345d3Smrg#include "xf86fbman.h"
38943345d3Smrg#include "xf86cmap.h"
39943345d3Smrg#include "compiler.h"
40943345d3Smrg#include "mipointer.h"
41943345d3Smrg#include "micmap.h"
42943345d3Smrg#include "mibstore.h"
43943345d3Smrg#include "fb.h"
44943345d3Smrg#include "ark.h"
45943345d3Smrg
465e695a52Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
475e695a52Smrg#include "xf86Resources.h"
485e695a52Smrg#endif
495e695a52Smrg
503e51e026Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
513e51e026Smrg#define PIOOFFSET hwp->PIOOffset
523e51e026Smrg#else
533e51e026Smrg#define PIOOFFSET 0
543e51e026Smrg#endif
553e51e026Smrg
56943345d3Smrg#include <string.h>
57943345d3Smrg
58943345d3Smrg/*
59943345d3Smrg * prototypes
60943345d3Smrg */
61943345d3Smrgstatic const OptionInfoRec * ARKAvailableOptions(int chipid, int busid);
62943345d3Smrgstatic void ARKIdentify(int flags);
63943345d3Smrgstatic Bool ARKProbe(DriverPtr drv, int flags);
64943345d3Smrgstatic Bool ARKPreInit(ScrnInfoPtr pScrn, int flags);
653e51e026Smrgstatic Bool ARKEnterVT(VT_FUNC_ARGS_DECL);
663e51e026Smrgstatic void ARKLeaveVT(VT_FUNC_ARGS_DECL);
67943345d3Smrgstatic void ARKSave(ScrnInfoPtr pScrn);
683e51e026Smrgstatic Bool ARKScreenInit(SCREEN_INIT_ARGS_DECL);
69943345d3Smrgstatic Bool ARKMapMem(ScrnInfoPtr pScrn);
70943345d3Smrgstatic void ARKUnmapMem(ScrnInfoPtr pScrn);
71943345d3Smrgstatic Bool ARKModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
723e51e026Smrgstatic void ARKAdjustFrame(ADJUST_FRAME_ARGS_DECL);
733e51e026SmrgBool ARKSwitchMode(SWITCH_MODE_ARGS_DECL);
743e51e026SmrgBool ARKCloseScreen(CLOSE_SCREEN_ARGS_DECL);
75943345d3SmrgBool ARKSaveScreen(ScreenPtr pScreen, int mode);
763e51e026Smrgstatic void ARKFreeScreen(FREE_SCREEN_ARGS_DECL);
77943345d3Smrgstatic void ARKLoadPalette(ScrnInfoPtr pScrn, int numColors,
78943345d3Smrg			   int *indicies, LOCO *colors,
79943345d3Smrg			   VisualPtr pVisual);
80943345d3Smrgstatic void ARKWriteMode(ScrnInfoPtr pScrn, vgaRegPtr pVga, ARKRegPtr new);
81943345d3Smrg
82943345d3Smrg/* helpers */
833e51e026Smrgstatic unsigned char get_daccomm(unsigned long);
843e51e026Smrgstatic unsigned char set_daccom(unsigned long, unsigned char comm);
85943345d3Smrg
86943345d3Smrg
87943345d3Smrg_X_EXPORT DriverRec ARK =
88943345d3Smrg{
89943345d3Smrg	ARK_VERSION,
90943345d3Smrg	DRIVER_NAME,
91943345d3Smrg	ARKIdentify,
92943345d3Smrg	ARKProbe,
93943345d3Smrg	ARKAvailableOptions,
94943345d3Smrg	NULL,
95943345d3Smrg	0
96943345d3Smrg};
97943345d3Smrg
98943345d3Smrg/* supported chipsets */
99943345d3Smrgstatic SymTabRec ARKChipsets[] = {
100943345d3Smrg	{ PCI_CHIP_1000PV, "ark1000pv" },
101943345d3Smrg	{ PCI_CHIP_2000PV, "ark2000pv" },
102943345d3Smrg	{ PCI_CHIP_2000MT, "ark2000mt" },
103943345d3Smrg	{ -1,		   NULL }
104943345d3Smrg};
105943345d3Smrg
106943345d3Smrgstatic PciChipsets ARKPciChipsets[] = {
107943345d3Smrg	{ PCI_CHIP_1000PV, PCI_CHIP_1000PV, RES_SHARED_VGA },
108943345d3Smrg	{ PCI_CHIP_2000PV, PCI_CHIP_2000PV, RES_SHARED_VGA },
109943345d3Smrg	{ PCI_CHIP_2000MT, PCI_CHIP_2000MT, RES_SHARED_VGA },
110943345d3Smrg	{ -1,		   -1,		    RES_UNDEFINED }
111943345d3Smrg};
112943345d3Smrg
113943345d3Smrgtypedef enum {
114943345d3Smrg	OPTION_NOACCEL
115943345d3Smrg} ARKOpts;
116943345d3Smrg
117943345d3Smrgstatic const OptionInfoRec ARKOptions[] = {
118943345d3Smrg	{ OPTION_NOACCEL, "noaccel", OPTV_BOOLEAN, {0}, FALSE },
119943345d3Smrg	{ -1,		  NULL,	     OPTV_NONE,	   {0}, FALSE }
120943345d3Smrg};
121943345d3Smrg
122943345d3Smrg#ifdef XFree86LOADER
123943345d3Smrg
124943345d3SmrgMODULESETUPPROTO(ARKSetup);
125943345d3Smrg
126943345d3Smrgstatic XF86ModuleVersionInfo ARKVersRec = {
127943345d3Smrg	"ark",
128943345d3Smrg	MODULEVENDORSTRING,
129943345d3Smrg	MODINFOSTRING1,
130943345d3Smrg	MODINFOSTRING2,
131943345d3Smrg	XORG_VERSION_CURRENT,
132943345d3Smrg	VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
133943345d3Smrg	ABI_CLASS_VIDEODRV,
134943345d3Smrg	ABI_VIDEODRV_VERSION,
135943345d3Smrg	MOD_CLASS_VIDEODRV,
136943345d3Smrg	{0, 0, 0, 0}
137943345d3Smrg};
138943345d3Smrg
139943345d3Smrg_X_EXPORT XF86ModuleData arkModuleData = { &ARKVersRec, ARKSetup, NULL };
140943345d3Smrg
141943345d3Smrgpointer ARKSetup(pointer module, pointer opts, int *errmaj, int *errmin)
142943345d3Smrg{
143943345d3Smrg	static Bool setupDone = FALSE;
144943345d3Smrg
145943345d3Smrg	if (!setupDone) {
146943345d3Smrg		setupDone = TRUE;
147943345d3Smrg		xf86AddDriver(&ARK, module, 0);
148943345d3Smrg		return (pointer) 1;
149943345d3Smrg	} else {
150943345d3Smrg		if (errmaj)
151943345d3Smrg			*errmaj = LDR_ONCEONLY;
152943345d3Smrg		return NULL;
153943345d3Smrg	}
154943345d3Smrg}
155943345d3Smrg
156943345d3Smrg#endif /* XFree86LOADER */
157943345d3Smrg
158943345d3Smrg
159943345d3Smrgstatic Bool ARKGetRec(ScrnInfoPtr pScrn)
160943345d3Smrg{
161943345d3Smrg	if (pScrn->driverPrivate)
162943345d3Smrg		return TRUE;
163943345d3Smrg
164943345d3Smrg	pScrn->driverPrivate = xnfcalloc(sizeof(ARKRec), 1);
165943345d3Smrg
166943345d3Smrg	return TRUE;
167943345d3Smrg}
168943345d3Smrg
169943345d3Smrgstatic void ARKFreeRec(ScrnInfoPtr pScrn)
170943345d3Smrg{
1713e51e026Smrg	free(pScrn->driverPrivate);
172943345d3Smrg	pScrn->driverPrivate = NULL;
173943345d3Smrg}
174943345d3Smrg
175943345d3Smrgstatic const OptionInfoRec * ARKAvailableOptions(int chipid, int busid)
176943345d3Smrg{
177943345d3Smrg	return ARKOptions;
178943345d3Smrg}
179943345d3Smrg
180943345d3Smrgstatic void ARKIdentify(int flags)
181943345d3Smrg{
182943345d3Smrg	xf86PrintChipsets("ARK", "driver (version " DRIVER_VERSION " for ARK Logic chipset",
183943345d3Smrg			  ARKChipsets);
184943345d3Smrg}
185943345d3Smrg
186943345d3Smrgstatic Bool ARKProbe(DriverPtr drv, int flags)
187943345d3Smrg{
188943345d3Smrg	int i;
189943345d3Smrg	GDevPtr *devSections;
190943345d3Smrg	int *usedChips;
191943345d3Smrg	int numDevSections;
192943345d3Smrg	int numUsed;
193943345d3Smrg	Bool foundScreen = FALSE;
194943345d3Smrg
195943345d3Smrg	/* sanity check */
196943345d3Smrg	if ((numDevSections = xf86MatchDevice("ark", &devSections)) <= 0)
197943345d3Smrg		return FALSE;
198943345d3Smrg
199943345d3Smrg	/* do ISA later */
200943345d3Smrg	numUsed = xf86MatchPciInstances("ark", PCI_VENDOR_ARK,
201943345d3Smrg					ARKChipsets, ARKPciChipsets,
202943345d3Smrg					devSections, numDevSections, drv,
203943345d3Smrg					&usedChips);
204943345d3Smrg
2053e51e026Smrg	free(devSections);
206943345d3Smrg
207943345d3Smrg	if (numUsed <= 0)
208943345d3Smrg		return FALSE;
209943345d3Smrg
210943345d3Smrg	if (flags & PROBE_DETECT)
211943345d3Smrg		foundScreen = TRUE;
212943345d3Smrg	else for (i=0; i<numUsed; i++) {
2135e695a52Smrg	        ScrnInfoPtr pScrn = NULL;
2145e695a52Smrg
2155e695a52Smrg		pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], ARKPciChipsets,
2165e695a52Smrg					    NULL, NULL, NULL, NULL, NULL);
217943345d3Smrg
218943345d3Smrg		pScrn->driverVersion = VERSION_MAJOR;
219943345d3Smrg		pScrn->driverName = DRIVER_NAME;
220943345d3Smrg		pScrn->name = "ark";
221943345d3Smrg		pScrn->Probe = ARKProbe;
222943345d3Smrg		pScrn->PreInit = ARKPreInit;
223943345d3Smrg		pScrn->ScreenInit = ARKScreenInit;
224943345d3Smrg		pScrn->SwitchMode = ARKSwitchMode;
225943345d3Smrg		pScrn->AdjustFrame = ARKAdjustFrame;
226943345d3Smrg		pScrn->EnterVT = ARKEnterVT;
227943345d3Smrg		pScrn->LeaveVT = ARKLeaveVT;
228943345d3Smrg		pScrn->FreeScreen = ARKFreeScreen;
229943345d3Smrg		foundScreen = TRUE;
230943345d3Smrg	}
231943345d3Smrg
2323e51e026Smrg	free(usedChips);
233943345d3Smrg
234943345d3Smrg	return foundScreen;
235943345d3Smrg}
236943345d3Smrg
237943345d3Smrg
238943345d3Smrgstatic Bool ARKPreInit(ScrnInfoPtr pScrn, int flags)
239943345d3Smrg{
240943345d3Smrg	EntityInfoPtr pEnt;
241943345d3Smrg	ARKPtr pARK;
242943345d3Smrg	vgaHWPtr hwp;
243943345d3Smrg	int i;
244943345d3Smrg	ClockRangePtr clockRanges;
245943345d3Smrg	rgb zeros = {0, 0, 0};
246943345d3Smrg	Gamma gzeros = {0.0, 0.0, 0.0};
247943345d3Smrg	unsigned char tmp;
248943345d3Smrg
249943345d3Smrg	if (flags & PROBE_DETECT)
250943345d3Smrg		return FALSE;
251943345d3Smrg
252943345d3Smrg	if (!xf86LoadSubModule(pScrn, "vgahw"))
253943345d3Smrg		return FALSE;
254943345d3Smrg
255943345d3Smrg	if (!vgaHWGetHWRec(pScrn))
256943345d3Smrg		return FALSE;
257943345d3Smrg
258943345d3Smrg	hwp = VGAHWPTR(pScrn);
2593e51e026Smrg	vgaHWSetStdFuncs(hwp);
260943345d3Smrg	vgaHWGetIOBase(hwp);
261943345d3Smrg
262943345d3Smrg	pScrn->monitor = pScrn->confScreen->monitor;
263943345d3Smrg
264943345d3Smrg	if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb))
265943345d3Smrg		return FALSE;
266943345d3Smrg	else {
267943345d3Smrg		switch (pScrn->depth) {
268943345d3Smrg			case 8:
269943345d3Smrg			case 16:
270943345d3Smrg			case 24:
271943345d3Smrg			case 32:
272943345d3Smrg				/* OK */
273943345d3Smrg				break;
274943345d3Smrg			default:
275943345d3Smrg				xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
276943345d3Smrg					   "Given depth (%d) is not supported by this driver\n",
277943345d3Smrg					   pScrn->depth);
278943345d3Smrg				return FALSE;
279943345d3Smrg		}
280943345d3Smrg	}
281943345d3Smrg
282943345d3Smrg	xf86PrintDepthBpp(pScrn);
283943345d3Smrg
284943345d3Smrg	if (pScrn->depth > 8) {
285943345d3Smrg		if (!xf86SetWeight(pScrn, zeros, zeros))
286943345d3Smrg			return FALSE;
287943345d3Smrg	}
288943345d3Smrg
289943345d3Smrg	if (pScrn->depth == 8)
290943345d3Smrg		pScrn->rgbBits = 8;
291943345d3Smrg
292943345d3Smrg	if (!xf86SetDefaultVisual(pScrn, -1))
293943345d3Smrg		return FALSE;
294943345d3Smrg
295943345d3Smrg	pScrn->progClock = TRUE;
296943345d3Smrg
297943345d3Smrg	if (!ARKGetRec(pScrn))
298943345d3Smrg		return FALSE;
299943345d3Smrg
300943345d3Smrg	pARK = ARKPTR(pScrn);
301943345d3Smrg
302943345d3Smrg	xf86CollectOptions(pScrn, NULL);
3033e51e026Smrg	if (!(pARK->Options = malloc(sizeof(ARKOptions))))
304943345d3Smrg		return FALSE;
305943345d3Smrg	memcpy(pARK->Options, ARKOptions, sizeof(ARKOptions));
306943345d3Smrg	xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pARK->Options);
307943345d3Smrg
308943345d3Smrg	if (xf86ReturnOptValBool(pARK->Options, OPTION_NOACCEL, FALSE)) {
309943345d3Smrg		pARK->NoAccel = TRUE;
310943345d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - acceleration disabled\n");
311943345d3Smrg	} else
312943345d3Smrg		pARK->NoAccel = FALSE;
313943345d3Smrg
314943345d3Smrg	if (pScrn->numEntities > 1) {
315943345d3Smrg		ARKFreeRec(pScrn);
316943345d3Smrg		return FALSE;
317943345d3Smrg	}
318943345d3Smrg
319943345d3Smrg	pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
320943345d3Smrg	pARK->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
321943345d3Smrg
322943345d3Smrg	if (pEnt->device->chipset && *pEnt->device->chipset) {
323943345d3Smrg		pScrn->chipset = pEnt->device->chipset;
324943345d3Smrg		pARK->Chipset = xf86StringToToken(ARKChipsets, pScrn->chipset);
325943345d3Smrg	} else if (pEnt->device->chipID >= 0) {
326943345d3Smrg		pARK->Chipset = pEnt->device->chipID;
327943345d3Smrg		pScrn->chipset = (char *)xf86TokenToString(ARKChipsets,
328943345d3Smrg							   pARK->Chipset);
329943345d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
330943345d3Smrg			   pARK->Chipset);
331943345d3Smrg	} else {
332f67b85aaSmrg#ifndef XSERVER_LIBPCIACCESS
333943345d3Smrg		pARK->Chipset = pARK->PciInfo->chipType;
334f67b85aaSmrg#else
335f67b85aaSmrg		pARK->Chipset = pARK->PciInfo->device_id;
336f67b85aaSmrg#endif
337943345d3Smrg		pScrn->chipset = (char *)xf86TokenToString(ARKChipsets,
338943345d3Smrg							   pARK->Chipset);
339943345d3Smrg	}
340943345d3Smrg
341943345d3Smrg	if (pEnt->device->chipRev >= 0) {
342943345d3Smrg		pARK->ChipRev = pEnt->device->chipRev;
343943345d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
344943345d3Smrg			   pARK->ChipRev);
345f67b85aaSmrg	} else {
346f67b85aaSmrg#ifndef XSERVER_LIBPCIACCESS
347943345d3Smrg		pARK->ChipRev = pARK->PciInfo->chipRev;
348f67b85aaSmrg#else
349f67b85aaSmrg		pARK->ChipRev = pARK->PciInfo->revision;
350f67b85aaSmrg#endif
351f67b85aaSmrg	}
3523e51e026Smrg	free(pEnt);
353943345d3Smrg
354943345d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Chipset: \"%s\"\n", pScrn->chipset);
355943345d3Smrg
356f67b85aaSmrg#ifndef XSERVER_LIBPCIACCESS
357943345d3Smrg	pARK->PciTag = pciTag(pARK->PciInfo->bus, pARK->PciInfo->device,
358943345d3Smrg			      pARK->PciInfo->func);
359f67b85aaSmrg#endif
360943345d3Smrg
361943345d3Smrg	/* unlock CRTC[0-7] */
3623e51e026Smrg	outb(PIOOFFSET + hwp->IOBase + 4, 0x11);
3633e51e026Smrg	tmp = inb(PIOOFFSET + hwp->IOBase + 5);
3643e51e026Smrg	outb(PIOOFFSET + hwp->IOBase + 5, tmp & 0x7f);
3653e51e026Smrg	modinx(PIOOFFSET + 0x3c4, 0x1d, 0x01, 0x01);
366943345d3Smrg
3673e51e026Smrg#ifndef XSERVER_LIBPCIACCESS
3683e51e026Smrg	pScrn->memPhysBase = pARK->PciInfo->memBase[0];
3693e51e026Smrg#else
3703e51e026Smrg	pScrn->memPhysBase = pARK->PciInfo->regions[0].base_addr;
3713e51e026Smrg#endif
372943345d3Smrg
373943345d3Smrg	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Framebuffer @ 0x%lx\n",
3743e51e026Smrg		   (unsigned long)pScrn->memPhysBase);
375943345d3Smrg
376943345d3Smrg	if (!xf86SetGamma(pScrn, gzeros))
377943345d3Smrg		return FALSE;
378943345d3Smrg
379943345d3Smrg	if (!pScrn->videoRam) {
380943345d3Smrg		unsigned char sr10;
381943345d3Smrg
3823e51e026Smrg		sr10 = rdinx(PIOOFFSET + 0x3c4, 0x10);
383943345d3Smrg		if (pARK->Chipset == PCI_CHIP_1000PV) {
384943345d3Smrg			if ((sr10 & 0x40) == 0)
385943345d3Smrg				pScrn->videoRam = 1024;
386943345d3Smrg			else
387943345d3Smrg				pScrn->videoRam = 2048;
388943345d3Smrg		}
389943345d3Smrg		if (pARK->Chipset == PCI_CHIP_2000PV ||
390943345d3Smrg		    pARK->Chipset == PCI_CHIP_2000MT) {
391943345d3Smrg			if ((sr10 & 0xc0) == 0)
392943345d3Smrg				pScrn->videoRam = 1024;
393943345d3Smrg			else if ((sr10 & 0xc0) == 0x40)
394943345d3Smrg				pScrn->videoRam = 2048;
395943345d3Smrg			else
396943345d3Smrg				pScrn->videoRam = 4096;
397943345d3Smrg		}
398943345d3Smrg
399943345d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected %d bytes video ram\n",
400943345d3Smrg			   pScrn->videoRam);
401943345d3Smrg	}
402943345d3Smrg
403943345d3Smrg	/* try to detect the RAMDAC */
404943345d3Smrg	{
405943345d3Smrg		int man_id, dev_id;
406943345d3Smrg
4073e51e026Smrg		inb(PIOOFFSET + 0x3c6);		/* skip cmd register */
4083e51e026Smrg		man_id = inb(PIOOFFSET + 0x3c6);	/* manufacturer id */
4093e51e026Smrg		dev_id = inb(PIOOFFSET + 0x3c6);	/* device id */
410943345d3Smrg		if (man_id == 0x84 && dev_id == 0x98) {
411943345d3Smrg			pARK->ramdac = ZOOMDAC;
412943345d3Smrg			pARK->dac_width = 16;
413943345d3Smrg			pARK->multiplex_threshold = 40000;
414943345d3Smrg			xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
415943345d3Smrg				   "Detected ZOOMDAC\n");
416943345d3Smrg		}
417943345d3Smrg	}
418943345d3Smrg
419943345d3Smrg	/* hack for this Bali32 */
420943345d3Smrg	pARK->ramdac = ATT490;
421943345d3Smrg	pARK->dac_width = 8;
422943345d3Smrg
423943345d3Smrg	pARK->clock_mult = 1;
424943345d3Smrg	if (pARK->dac_width == 16) {
425943345d3Smrg		if (pScrn->bitsPerPixel == 32)
426943345d3Smrg			pARK->clock_mult = 2;
427943345d3Smrg	}
428943345d3Smrg
429943345d3Smrg	clockRanges = xnfcalloc(sizeof(ClockRange), 1);
430943345d3Smrg	clockRanges->next = NULL;
431943345d3Smrg	clockRanges->minClock = 20000;
432943345d3Smrg	clockRanges->maxClock = 80000;
433943345d3Smrg	clockRanges->clockIndex = -1;
434943345d3Smrg	clockRanges->interlaceAllowed = FALSE; /* ? */
435943345d3Smrg	clockRanges->doubleScanAllowed = FALSE; /* ? */
436943345d3Smrg
437943345d3Smrg	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
438943345d3Smrg			      pScrn->display->modes, clockRanges,
439943345d3Smrg			      NULL, 256, 2048, pScrn->bitsPerPixel,
440943345d3Smrg			      128, 2048, pScrn->display->virtualX,
441943345d3Smrg			      pScrn->display->virtualY, pARK->videoRam * 1024,
442943345d3Smrg			      LOOKUP_BEST_REFRESH);
443943345d3Smrg	if (i == -1) {
444943345d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes left\n");
445943345d3Smrg		ARKFreeRec(pScrn);
446943345d3Smrg		return FALSE;
447943345d3Smrg	}
448943345d3Smrg
449943345d3Smrg	xf86PruneDriverModes(pScrn);
450943345d3Smrg
451943345d3Smrg	if (i == 0 || pScrn->modes == NULL) {
452943345d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes found\n");
453943345d3Smrg		ARKFreeRec(pScrn);
454943345d3Smrg		return FALSE;
455943345d3Smrg	}
456943345d3Smrg
457943345d3Smrg	xf86SetCrtcForModes(pScrn, 0);
458943345d3Smrg	pScrn->currentMode = pScrn->modes;
459943345d3Smrg	xf86PrintModes(pScrn);
460943345d3Smrg	xf86SetDpi(pScrn, 0, 0);
461943345d3Smrg
462943345d3Smrg	if (!xf86LoadSubModule(pScrn, "fb")) {
463943345d3Smrg	    ARKFreeRec(pScrn);
464943345d3Smrg	    return FALSE;
465943345d3Smrg	}
466943345d3Smrg
467943345d3Smrg	if (!pARK->NoAccel) {
468943345d3Smrg		if (!xf86LoadSubModule(pScrn, "xaa")) {
4693e51e026Smrg			xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
4703e51e026Smrg				   "XAA not available\n");
4713e51e026Smrg			pARK->NoAccel = 1;
472943345d3Smrg		}
473943345d3Smrg	}
474943345d3Smrg
475943345d3Smrg	return TRUE;
476943345d3Smrg}
477943345d3Smrg
4783e51e026Smrgstatic Bool ARKScreenInit(SCREEN_INIT_ARGS_DECL)
479943345d3Smrg{
4803e51e026Smrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
481943345d3Smrg	ARKPtr pARK = ARKPTR(pScrn);
482943345d3Smrg
483943345d3Smrg	pScrn->fbOffset = 0;
484943345d3Smrg
485943345d3Smrg	if (!ARKMapMem(pScrn)) {
486943345d3Smrg		ARKFreeRec(pScrn);
487943345d3Smrg		return FALSE;
488943345d3Smrg	}
489943345d3Smrg
490943345d3Smrg	ARKSave(pScrn);
491943345d3Smrg
492943345d3Smrg	vgaHWBlankScreen(pScrn, TRUE);
493943345d3Smrg
494943345d3Smrg	if (!ARKModeInit(pScrn, pScrn->currentMode))
495943345d3Smrg		return FALSE;
496943345d3Smrg
497943345d3Smrg	ARKSaveScreen(pScreen, SCREEN_SAVER_ON);
498943345d3Smrg
4993e51e026Smrg	pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
500943345d3Smrg
501943345d3Smrg	miClearVisualTypes();
502943345d3Smrg	if (pScrn->bitsPerPixel > 8) {
503943345d3Smrg		if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
504943345d3Smrg				      pScrn->rgbBits, pScrn->defaultVisual))
505943345d3Smrg			return FALSE;
506943345d3Smrg	} else {
507943345d3Smrg		if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
508943345d3Smrg				      pScrn->rgbBits, pScrn->defaultVisual))
509943345d3Smrg			return FALSE;
510943345d3Smrg	}
511943345d3Smrg
512943345d3Smrg	miSetPixmapDepths ();
513943345d3Smrg
514943345d3Smrg	if (!fbScreenInit(pScreen, pARK->FBBase, pScrn->virtualX,
515943345d3Smrg			  pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
516943345d3Smrg			  pScrn->displayWidth, pScrn->bitsPerPixel))
517943345d3Smrg		return FALSE;
518943345d3Smrg
519943345d3Smrg	xf86SetBlackWhitePixels(pScreen);
520943345d3Smrg
521943345d3Smrg	if (pScrn->bitsPerPixel > 8) {
522943345d3Smrg		VisualPtr pVis;
523943345d3Smrg
524943345d3Smrg		pVis = pScreen->visuals + pScreen->numVisuals;
525943345d3Smrg		while (--pVis >= pScreen->visuals) {
526943345d3Smrg			if ((pVis->class | DynamicClass) == DirectColor) {
527943345d3Smrg				pVis->offsetRed = pScrn->offset.red;
528943345d3Smrg				pVis->offsetGreen = pScrn->offset.green;
529943345d3Smrg				pVis->offsetBlue = pScrn->offset.blue;
530943345d3Smrg				pVis->redMask = pScrn->mask.red;
531943345d3Smrg				pVis->greenMask = pScrn->mask.green;
532943345d3Smrg				pVis->blueMask = pScrn->mask.blue;
533943345d3Smrg			}
534943345d3Smrg		}
535943345d3Smrg	}
536943345d3Smrg
537943345d3Smrg	/* must be after RGB order fixed */
538943345d3Smrg
539943345d3Smrg	fbPictureInit (pScreen, 0, 0);
540943345d3Smrg
541943345d3Smrg	miInitializeBackingStore(pScreen);
542943345d3Smrg	xf86SetBackingStore(pScreen);
543943345d3Smrg
544943345d3Smrg	if (!pARK->NoAccel) {
545943345d3Smrg		if (ARKAccelInit(pScreen)) {
5463e51e026Smrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration enabled\n");
547943345d3Smrg		} else {
5483e51e026Smrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Acceleration initialization failed\n");
5493e51e026Smrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration disabled\n");
550943345d3Smrg		}
551943345d3Smrg	} else {
5523e51e026Smrg			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Acceleration disabled\n");
553943345d3Smrg	}
554943345d3Smrg
555943345d3Smrg	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
556943345d3Smrg
557943345d3Smrg	if (!miCreateDefColormap(pScreen))
558943345d3Smrg		return FALSE;
559943345d3Smrg
560943345d3Smrg	if (!xf86HandleColormaps(pScreen, 256, 8, ARKLoadPalette, NULL,
561943345d3Smrg				 CMAP_RELOAD_ON_MODE_SWITCH))
562943345d3Smrg		return FALSE;
563943345d3Smrg
564943345d3Smrg	vgaHWBlankScreen(pScrn, FALSE);
565943345d3Smrg
566943345d3Smrg	pScreen->SaveScreen = ARKSaveScreen;
567943345d3Smrg	pARK->CloseScreen = pScreen->CloseScreen;
568943345d3Smrg	pScreen->CloseScreen = ARKCloseScreen;
569943345d3Smrg
570943345d3Smrg	return TRUE;
571943345d3Smrg}
572943345d3Smrg
573943345d3Smrg
574943345d3Smrg
575943345d3Smrgstatic void ARKSave(ScrnInfoPtr pScrn)
576943345d3Smrg{
577943345d3Smrg	ARKPtr pARK = ARKPTR(pScrn);
578943345d3Smrg	ARKRegPtr save = &pARK->SavedRegs;
579943345d3Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
5803e51e026Smrg	unsigned long isaIOBase = PIOOFFSET;
5813e51e026Smrg	unsigned long vgaIOBase = isaIOBase + hwp->IOBase;
582943345d3Smrg
583943345d3Smrg	vgaHWUnlock(hwp);
584943345d3Smrg	vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL);
585943345d3Smrg	vgaHWLock(hwp);
586943345d3Smrg
587943345d3Smrg	/* set read and write aperture index to 0 */
588943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x15, 0x00);
589943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x16, 0x00);
590943345d3Smrg	outb(isaIOBase + 0x3c8, 0);	/* reset DAC register access mode */
591943345d3Smrg
592943345d3Smrg	save->sr10 = rdinx(isaIOBase + 0x3c4, 0x10);
593943345d3Smrg	save->sr11 = rdinx(isaIOBase + 0x3c4, 0x11);
594943345d3Smrg	save->sr12 = rdinx(isaIOBase + 0x3c4, 0x12);
595943345d3Smrg	save->sr13 = rdinx(isaIOBase + 0x3c4, 0x13);
596943345d3Smrg	save->sr14 = rdinx(isaIOBase + 0x3c4, 0x14);
597943345d3Smrg	save->sr15 = rdinx(isaIOBase + 0x3c4, 0x15);
598943345d3Smrg	save->sr16 = rdinx(isaIOBase + 0x3c4, 0x16);
599943345d3Smrg	save->sr17 = rdinx(isaIOBase + 0x3c4, 0x17);
600943345d3Smrg	save->sr18 = rdinx(isaIOBase + 0x3c4, 0x18);
601943345d3Smrg
602943345d3Smrg#if 0
603943345d3Smrg	save->sr1d = rdinx(isaIOBase + 0x3c4, 0x1d);
604943345d3Smrg	save->sr1c = rdinx(isaIOBase + 0x3c4, 0x1c);
605943345d3Smrg
606943345d3Smrg	save->sr20 = rdinx(isaIOBase + 0x3c4, 0x20);
607943345d3Smrg	save->sr21 = rdinx(isaIOBase + 0x3c4, 0x21);
608943345d3Smrg	save->sr22 = rdinx(isaIOBase + 0x3c4, 0x22);
609943345d3Smrg	save->sr23 = rdinx(isaIOBase + 0x3c4, 0x23);
610943345d3Smrg	save->sr24 = rdinx(isaIOBase + 0x3c4, 0x24);
611943345d3Smrg	save->sr25 = rdinx(isaIOBase + 0x3c4, 0x25);
612943345d3Smrg	save->sr26 = rdinx(isaIOBase + 0x3c4, 0x26);
613943345d3Smrg	save->sr27 = rdinx(isaIOBase + 0x3c4, 0x27);
614943345d3Smrg	save->sr29 = rdinx(isaIOBase + 0x3c4, 0x29);
615943345d3Smrg	save->sr2a = rdinx(isaIOBase + 0x3c4, 0x2a);
616943345d3Smrg	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
617943345d3Smrg	    (pARK->Chipset == PCI_CHIP_2000MT)) {
618943345d3Smrg		save->sr28 = rdinx(isaIOBase + 0x3c4, 0x28);
619943345d3Smrg		save->sr2b = rdinx(isaIOBase + 0x3c4, 0x2b);
620943345d3Smrg	}
621943345d3Smrg#endif
622943345d3Smrg
623943345d3Smrg	save->cr40 = rdinx(vgaIOBase + 4, 0x40);
624943345d3Smrg	save->cr41 = rdinx(vgaIOBase + 4, 0x41);
625943345d3Smrg	save->cr42 = rdinx(vgaIOBase + 4, 0x42);
626943345d3Smrg	save->cr44 = rdinx(vgaIOBase + 4, 0x44);
627943345d3Smrg
628943345d3Smrg	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
629943345d3Smrg	    (pARK->Chipset == PCI_CHIP_2000MT))
630943345d3Smrg		save->cr46 = rdinx(vgaIOBase + 4, 0x46);
631943345d3Smrg
632943345d3Smrg	/* save RAMDAC regs here, based on type */
633943345d3Smrg	save->dac_command = get_daccomm(isaIOBase);
634943345d3Smrg}
635943345d3Smrg
636943345d3Smrg
637943345d3Smrg
638943345d3Smrgstatic Bool ARKModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
639943345d3Smrg{
640943345d3Smrg	ARKPtr pARK = ARKPTR(pScrn);
641943345d3Smrg	ARKRegPtr new = &pARK->ModeRegs;
642943345d3Smrg	int multiplexing, dac16, modepitch;
643943345d3Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
644943345d3Smrg	vgaRegPtr pVga = &hwp->ModeReg;
6453e51e026Smrg	unsigned long isaIOBase = PIOOFFSET;
6463e51e026Smrg	unsigned long vgaIOBase = isaIOBase + hwp->IOBase;
647943345d3Smrg	unsigned char tmp;
648943345d3Smrg	int offset;
649943345d3Smrg
650943345d3Smrg	multiplexing = 0;
651943345d3Smrg
652943345d3Smrg	if ((pScrn->bitsPerPixel == 8) && (pARK->dac_width == 16) &&
653943345d3Smrg	    (mode->Clock > pARK->multiplex_threshold))
654943345d3Smrg		multiplexing = 1;
655943345d3Smrg
656943345d3Smrg	if (pARK->clock_mult == 2) {
657943345d3Smrg		if (!mode->CrtcHAdjusted) {
658943345d3Smrg			mode->CrtcHDisplay <<= 1;
659943345d3Smrg			mode->CrtcHSyncStart <<= 1;
660943345d3Smrg			mode->CrtcHSyncEnd <<= 1;
661943345d3Smrg			mode->CrtcHTotal <<= 1;
662943345d3Smrg			mode->CrtcHSkew <<= 1;
663943345d3Smrg			mode->CrtcHAdjusted = TRUE;
664943345d3Smrg		}
665943345d3Smrg	}
666943345d3Smrg
667943345d3Smrg	if (multiplexing) {
668943345d3Smrg		if (!mode->CrtcHAdjusted) {
669943345d3Smrg			mode->CrtcHDisplay >>= 1;
670943345d3Smrg			mode->CrtcHSyncStart >>= 1;
671943345d3Smrg			mode->CrtcHSyncEnd >>= 1;
672943345d3Smrg			mode->CrtcHTotal >>= 1;
673943345d3Smrg			mode->CrtcHSkew >>= 1;
674943345d3Smrg			mode->CrtcHAdjusted = TRUE;
675943345d3Smrg		}
676943345d3Smrg	}
677943345d3Smrg
678943345d3Smrg	if (!vgaHWInit(pScrn, mode))
679943345d3Smrg		return FALSE;
680943345d3Smrg
681943345d3Smrg	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
682943345d3Smrg	    (pARK->Chipset == PCI_CHIP_2000MT)) {
683943345d3Smrg		new->cr46 = rdinx(vgaIOBase + 4, 0x46) & ~0x04;
684943345d3Smrg		dac16 = 0;
685943345d3Smrg		if (pScrn->bitsPerPixel > 8)
686943345d3Smrg			dac16 = 1;
687943345d3Smrg		if (dac16)
688943345d3Smrg			new->cr46 |= 0x04;
689943345d3Smrg	}
690943345d3Smrg
691943345d3Smrg	offset = (pScrn->displayWidth * (pScrn->bitsPerPixel / 8)) >> 3;
692943345d3Smrg	pVga->CRTC[0x13] = offset;
693943345d3Smrg	new->cr41 = (offset & 0x100) >> 5;
694943345d3Smrg
695943345d3Smrg	new->sr11 = 0x90;
696943345d3Smrg	switch (pScrn->bitsPerPixel) {
697943345d3Smrg		case 8:
698943345d3Smrg			new->sr11 |= 0x06;
699943345d3Smrg			break;
700943345d3Smrg		case 16:
701943345d3Smrg			new->sr11 |= 0x0a;
702943345d3Smrg			break;
703943345d3Smrg		case 24:
704943345d3Smrg			new->sr11 |= 0x06;
705943345d3Smrg			break;
706943345d3Smrg		case 32:
707943345d3Smrg			if ((pARK->Chipset == PCI_CHIP_2000PV) ||
708943345d3Smrg			    (pARK->Chipset == PCI_CHIP_2000MT))
709943345d3Smrg				new->sr11 |= 0x0e;
710943345d3Smrg			else
711943345d3Smrg				new->sr11 |= 0x0a;
712943345d3Smrg			break;
713943345d3Smrg		default:
714943345d3Smrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
715943345d3Smrg				   "Unsupported screen depth %d\n",
716943345d3Smrg				   pScrn->bitsPerPixel);
717943345d3Smrg			return FALSE;
718943345d3Smrg	}
719943345d3Smrg
720943345d3Smrg	switch (pScrn->displayWidth) {
721943345d3Smrg		case 640:
722943345d3Smrg			modepitch = 0;
723943345d3Smrg			break;
724943345d3Smrg		case 800:
725943345d3Smrg			modepitch = 1;
726943345d3Smrg			break;
727943345d3Smrg		case 1024:
728943345d3Smrg			modepitch = 2;
729943345d3Smrg			break;
730943345d3Smrg		case 1280:
731943345d3Smrg			modepitch = 4;
732943345d3Smrg			break;
733943345d3Smrg		case 1600:
734943345d3Smrg			modepitch = 5;
735943345d3Smrg			break;
736943345d3Smrg		case 2048:
737943345d3Smrg			modepitch = 6;
738943345d3Smrg			break;
739943345d3Smrg		default:
740943345d3Smrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
741943345d3Smrg				   "Unsupported screen width %d\n",
742943345d3Smrg				   pScrn->displayWidth);
743943345d3Smrg			return FALSE;
744943345d3Smrg	}
745943345d3Smrg
746943345d3Smrg	new->sr17 &= ~0xc7;
747943345d3Smrg	new->sr17 |= modepitch;
748943345d3Smrg
749943345d3Smrg	new->sr10 = rdinx(isaIOBase + 0x3c4, 0x10) & ~0x1f;
750943345d3Smrg	new->sr10 |= 0x1f;
751943345d3Smrg
7523e51e026Smrg#ifndef XSERVER_LIBPCIACCESS
7533e51e026Smrg	new->sr13 = pARK->PciInfo->memBase[0] >> 16;
7543e51e026Smrg	new->sr14 = pARK->PciInfo->memBase[0] >> 24;
7553e51e026Smrg#else
7563e51e026Smrg	new->sr13 = pARK->PciInfo->regions[0].base_addr >> 16;
7573e51e026Smrg	new->sr14 = pARK->PciInfo->regions[0].base_addr >> 24;
7583e51e026Smrg#endif
759943345d3Smrg
760943345d3Smrg	new->sr12 = rdinx(isaIOBase + 0x3c4, 0x12) & ~0x03;
761943345d3Smrg	switch (pScrn->videoRam) {
762943345d3Smrg		case 1024:
763943345d3Smrg			new->sr12 |= 0x01;
764943345d3Smrg			break;
765943345d3Smrg		case 2048:
766943345d3Smrg			new->sr12 |= 0x02;
767943345d3Smrg			break;
768943345d3Smrg		case 4096:
769943345d3Smrg			new->sr12 |= 0x03;
770943345d3Smrg			break;
771943345d3Smrg		default:
772943345d3Smrg			new->sr12 |= 0x01;
773943345d3Smrg			break;
774943345d3Smrg	}
775943345d3Smrg
776943345d3Smrg	new->sr15 = new->sr16 = 0;
777943345d3Smrg
778943345d3Smrg	tmp = 0;
779943345d3Smrg	if ((mode->CrtcVTotal - 2) & 0x400)
780943345d3Smrg		tmp |= 0x80;
781943345d3Smrg	if ((mode->CrtcVDisplay - 1) & 0x400)
782943345d3Smrg		tmp |= 0x40;
783943345d3Smrg	if (mode->CrtcVSyncStart & 0x400)
784943345d3Smrg		tmp |= 0x10;
785943345d3Smrg	new->cr40 = tmp;
786943345d3Smrg
787943345d3Smrg	tmp = new->cr41;	/* initialized earlier */
788943345d3Smrg	if ((mode->CrtcHTotal / 8 - 5) & 0x100)
789943345d3Smrg		tmp |= 0x80;
790943345d3Smrg	if ((mode->CrtcHDisplay / 8 - 1) & 0x100)
791943345d3Smrg		tmp |= 0x40;
792943345d3Smrg	if ((mode->CrtcHSyncStart / 8 - 1) & 0x100)
793943345d3Smrg		tmp |= 0x20;
794943345d3Smrg	if ((mode->CrtcHSyncStart / 8) & 0x100)
795943345d3Smrg		tmp |= 0x10;
796943345d3Smrg	new->cr41 |= tmp;
797943345d3Smrg
798943345d3Smrg	new->cr44 = rdinx(vgaIOBase + 4, 0x44) & ~0x34;
799943345d3Smrg	new->cr44 &= ~0x01;
800943345d3Smrg	new->cr42 = 0;
801943345d3Smrg
802943345d3Smrg	/* check interlace here later */
803943345d3Smrg
804943345d3Smrg	/* set display FIFO threshold */
805943345d3Smrg	{
806943345d3Smrg		int threshold;
807943345d3Smrg		int bandwidthused, percentused;
808943345d3Smrg
809943345d3Smrg		/* mostly guesses here as I would need to know more about
810943345d3Smrg		 * and from the ramdac...
811943345d3Smrg		 */
812943345d3Smrg		bandwidthused = (mode->Clock / pARK->clock_mult) *
813943345d3Smrg				(pScrn->bitsPerPixel / 8);
814943345d3Smrg		/* 120000 is another guess */
815943345d3Smrg		percentused = (bandwidthused * 100) / 120000;
816943345d3Smrg		tmp = rdinx(isaIOBase + 0x3c4, 0x18);
817943345d3Smrg		if (pARK->Chipset == PCI_CHIP_1000PV) {
818943345d3Smrg			threshold = 4;
819943345d3Smrg			tmp |= 0x08;	/* enable full FIFO (8 deep) */
820943345d3Smrg			tmp &= ~0x07;
821943345d3Smrg			tmp |= threshold;
822943345d3Smrg		}
823943345d3Smrg		if ((pARK->Chipset == PCI_CHIP_2000PV) ||
824943345d3Smrg		    (pARK->Chipset == PCI_CHIP_2000MT)) {
825943345d3Smrg			threshold = 12;
826943345d3Smrg			if (percentused >= 45)
827943345d3Smrg				threshold = 8;
828943345d3Smrg			if (percentused >= 70)
829943345d3Smrg				threshold = 4;
830943345d3Smrg			tmp &= 0x40;
831943345d3Smrg			tmp |= 0x10;
832943345d3Smrg			tmp |= (threshold & 0x0e) >> 1;
833943345d3Smrg			if (threshold & 0x01)
834943345d3Smrg				tmp |= 0x80;
835943345d3Smrg			if (threshold & 0x10)
836943345d3Smrg				tmp |= 0x20;
837943345d3Smrg		}
838943345d3Smrg		new->sr18 = tmp;
839943345d3Smrg	}
840943345d3Smrg
841943345d3Smrg	/* setup the RAMDAC regs */
842943345d3Smrg	if (pARK->ramdac == ZOOMDAC) {
843943345d3Smrg		new->dac_command = 0x04;
844943345d3Smrg		if ((pScrn->bitsPerPixel == 8) && multiplexing)
845943345d3Smrg			new->dac_command = 0x24;
846943345d3Smrg		if ((pScrn->bitsPerPixel == 16) && (pARK->dac_width == 16))
847943345d3Smrg			/* assuming green weight is not 5 */
848943345d3Smrg			new->dac_command = 0x34;
849943345d3Smrg		if ((pScrn->bitsPerPixel == 16) && (pARK->dac_width == 8))
850943345d3Smrg			new->dac_command = 0x64;
851943345d3Smrg		if ((pScrn->bitsPerPixel == 24) && (pARK->dac_width == 16))
852943345d3Smrg			new->dac_command = 0xb4;	/* packed */
853943345d3Smrg		if ((pScrn->bitsPerPixel == 32) && (pARK->dac_width == 16))
854943345d3Smrg			new->dac_command = 0x54;
855943345d3Smrg	} else if (pARK->ramdac == ATT490) {
856943345d3Smrg		new->dac_command = 0x00;
857943345d3Smrg		if (pScrn->bitsPerPixel == 16)
858943345d3Smrg			/* assuming green weight is 6 */
859943345d3Smrg			new->dac_command = 0xc0;
860943345d3Smrg		if (pScrn->bitsPerPixel == 24)
861943345d3Smrg			new->dac_command = 0xe0;
862943345d3Smrg	}
863943345d3Smrg
864943345d3Smrg#if 0
865943345d3Smrg	/* hw cursor regs */
866943345d3Smrg	new->sr20 = rdinx(isaIOBase + 0x3c4, 0x20);
867943345d3Smrg	new->sr21 = rdinx(isaIOBase + 0x3c4, 0x21);
868943345d3Smrg	new->sr22 = rdinx(isaIOBase + 0x3c4, 0x22);
869943345d3Smrg	new->sr23 = rdinx(isaIOBase + 0x3c4, 0x23);
870943345d3Smrg	new->sr24 = rdinx(isaIOBase + 0x3c4, 0x24);
871943345d3Smrg	new->sr25 = rdinx(isaIOBase + 0x3c4, 0x25);
872943345d3Smrg	new->sr26 = rdinx(isaIOBase + 0x3c4, 0x26);
873943345d3Smrg	new->sr27 = rdinx(isaIOBase + 0x3c4, 0x27);
874943345d3Smrg	new->sr29 = rdinx(isaIOBase + 0x3c4, 0x29);
875943345d3Smrg	new->sr2a = rdinx(isaIOBase + 0x3c4, 0x2a);
876943345d3Smrg	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
877943345d3Smrg	    (pARK->Chipset == PCI_CHIP_2000MT)) {
878943345d3Smrg		new->sr28 = rdinx(isaIOBase + 0x3c4, 0x28);
879943345d3Smrg		new->sr2b = rdinx(isaIOBase + 0x3c4, 0x3b);
880943345d3Smrg	}
881943345d3Smrg#endif
882943345d3Smrg
883943345d3Smrg
884943345d3Smrg	ARKWriteMode(pScrn, pVga, new);
885943345d3Smrg
886943345d3Smrg	return TRUE;
887943345d3Smrg}
888943345d3Smrg
889943345d3Smrg
8903e51e026Smrgstatic void ARKAdjustFrame(ADJUST_FRAME_ARGS_DECL)
891943345d3Smrg{
8923e51e026Smrg	SCRN_INFO_PTR(arg);
893943345d3Smrg	ARKPtr pARK = ARKPTR(pScrn);
894943345d3Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
8953e51e026Smrg	unsigned long vgaIOBase = PIOOFFSET + hwp->IOBase;
896943345d3Smrg	int base;
897943345d3Smrg
898943345d3Smrg	base = ((y * pScrn->displayWidth + x) *
899943345d3Smrg		(pScrn->bitsPerPixel / 8));
900943345d3Smrg
901943345d3Smrg	if (((pARK->Chipset == PCI_CHIP_2000PV) ||
902943345d3Smrg	     (pARK->Chipset == PCI_CHIP_2000MT)) &&
903943345d3Smrg	     (pScrn->videoRam >= 2048))
904943345d3Smrg		base >>= 3;
905943345d3Smrg	else
906943345d3Smrg		base >>= 2;
907943345d3Smrg	if (pScrn->bitsPerPixel == 24)
908943345d3Smrg		base -= base % 3;
909943345d3Smrg
910943345d3Smrg	outw(vgaIOBase + 4, (base & 0x00ff00) | 0x0c);
911943345d3Smrg	outw(vgaIOBase + 4, ((base & 0x00ff) << 8) | 0x0d);
912943345d3Smrg
913943345d3Smrg	modinx(vgaIOBase + 4, 0x40, 0x07, (base & 0x070000) >> 16);
914943345d3Smrg}
915943345d3Smrg
916943345d3Smrg
917943345d3Smrg
918943345d3Smrgstatic void ARKWriteMode(ScrnInfoPtr pScrn, vgaRegPtr pVga, ARKRegPtr new)
919943345d3Smrg{
920943345d3Smrg	ARKPtr pARK = ARKPTR(pScrn);
921943345d3Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
9223e51e026Smrg	unsigned long isaIOBase = PIOOFFSET;
9233e51e026Smrg	unsigned long vgaIOBase = isaIOBase + hwp->IOBase;
924943345d3Smrg
925943345d3Smrg	vgaHWProtect(pScrn, TRUE);
926943345d3Smrg
927943345d3Smrg	/* set read and write aperture index to 0 */
928943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x15, 0x00);
929943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x16, 0x00);
930943345d3Smrg
931943345d3Smrg	/* write the extended registers first so that textmode font
932943345d3Smrg	 * restoration can suceed
933943345d3Smrg	 */
934943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x10, new->sr10);
935943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x11, new->sr11);
936943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x12, new->sr12);
937943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x13, new->sr13);
938943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x14, new->sr14);
939943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x15, new->sr15);
940943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x16, new->sr16);
941943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x17, new->sr17);
942943345d3Smrg
943943345d3Smrg#if 0
944943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x1c, new->sr1c);
945943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x1d, new->sr1d);
946943345d3Smrg
947943345d3Smrg	/* hw cursor regs */
948943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x20, new->sr20);
949943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x21, new->sr21);
950943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x22, new->sr22);
951943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x23, new->sr23);
952943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x24, new->sr24);
953943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x25, new->sr25);
954943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x26, new->sr26);
955943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x27, new->sr27);
956943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x29, new->sr29);
957943345d3Smrg	wrinx(isaIOBase + 0x3c4, 0x2a, new->sr2a);
958943345d3Smrg#endif
959943345d3Smrg
960943345d3Smrg	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
961943345d3Smrg	    (pARK->Chipset == PCI_CHIP_2000MT)) {
962943345d3Smrg		wrinx(isaIOBase + 0x3c4, 0x28, new->sr28);
963943345d3Smrg		wrinx(isaIOBase + 0x3c4, 0x2B, new->sr2b);
964943345d3Smrg	}
965943345d3Smrg
966943345d3Smrg	wrinx(vgaIOBase + 4, 0x40, new->cr40);
967943345d3Smrg	wrinx(vgaIOBase + 4, 0x41, new->cr41);
968943345d3Smrg	wrinx(vgaIOBase + 4, 0x42, new->cr42);
969943345d3Smrg	wrinx(vgaIOBase + 4, 0x44, new->cr44);
970943345d3Smrg
971943345d3Smrg	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
972943345d3Smrg	    (pARK->Chipset == PCI_CHIP_2000MT))
973943345d3Smrg		wrinx(vgaIOBase + 4, 0x46, new->cr46);
974943345d3Smrg
975943345d3Smrg	/* RAMDAC regs */
976943345d3Smrg	if (pARK->ramdac == ZOOMDAC) {
977943345d3Smrg		set_daccom(isaIOBase, new->dac_command);
978943345d3Smrg	}
979943345d3Smrg
980943345d3Smrg	if (xf86IsPrimaryPci(pARK->PciInfo))
981943345d3Smrg		vgaHWRestore(pScrn, pVga, VGA_SR_ALL);
982943345d3Smrg	else
983943345d3Smrg		vgaHWRestore(pScrn, pVga, VGA_SR_MODE);
984943345d3Smrg
985943345d3Smrg	vgaHWProtect(pScrn, FALSE);
986943345d3Smrg}
987943345d3Smrg
988943345d3Smrg
9893e51e026Smrgstatic Bool ARKEnterVT(VT_FUNC_ARGS_DECL)
990943345d3Smrg{
9913e51e026Smrg	SCRN_INFO_PTR(arg);
992943345d3Smrg
993943345d3Smrg	if (!ARKModeInit(pScrn, pScrn->currentMode))
994943345d3Smrg		return FALSE;
995943345d3Smrg
9963e51e026Smrg	ARKAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
997943345d3Smrg
998943345d3Smrg	return TRUE;
999943345d3Smrg}
1000943345d3Smrg
1001943345d3Smrg
1002943345d3Smrg
10033e51e026Smrgstatic void ARKLeaveVT(VT_FUNC_ARGS_DECL)
1004943345d3Smrg{
10053e51e026Smrg	SCRN_INFO_PTR(arg);
1006943345d3Smrg	ARKPtr pARK = ARKPTR(pScrn);
1007943345d3Smrg	ARKRegPtr old = &pARK->SavedRegs;
1008943345d3Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
1009943345d3Smrg
1010943345d3Smrg	ARKWriteMode(pScrn, &hwp->ModeReg, old);
1011943345d3Smrg
1012943345d3Smrg	vgaHWUnlock(hwp);
1013943345d3Smrg	vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS);
1014943345d3Smrg	vgaHWLock(hwp);
1015943345d3Smrg}
1016943345d3Smrg
1017943345d3Smrg
1018943345d3Smrgstatic Bool ARKMapMem(ScrnInfoPtr pScrn)
1019943345d3Smrg{
1020943345d3Smrg	ARKPtr pARK = ARKPTR(pScrn);
1021943345d3Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
1022943345d3Smrg
1023943345d3Smrg	/* extended to cover MMIO space at 0xB8000 */
1024943345d3Smrg	hwp->MapSize = 0x20000;
1025943345d3Smrg
1026f67b85aaSmrg#ifndef XSERVER_LIBPCIACCESS
1027943345d3Smrg	pARK->MMIOBase = xf86MapDomainMemory(pScrn->scrnIndex, VIDMEM_MMIO,
1028943345d3Smrg					     pARK->PciTag, 0xb8000, 0x8000);
1029943345d3Smrg
1030943345d3Smrg	pARK->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
10313e51e026Smrg				     pARK->PciTag, pARK->PciInfo->memBase[0],
1032943345d3Smrg				     pScrn->videoRam * 1024);
1033f67b85aaSmrg#else
1034f67b85aaSmrg
10353e51e026Smrg	(void) pci_device_map_legacy(pARK->PciInfo, 0xb8000, 0x8000,
10363e51e026Smrg				     PCI_DEV_MAP_FLAG_WRITABLE,
10373e51e026Smrg				     &pARK->MMIOBase);
1038f67b85aaSmrg
1039f67b85aaSmrg	{
10403e51e026Smrg		void** result = &pARK->FBBase;
1041f67b85aaSmrg		int err = pci_device_map_range(pARK->PciInfo,
10423e51e026Smrg					       pARK->PciInfo->regions[0].base_addr,
1043f67b85aaSmrg					       pScrn->videoRam * 1024,
1044f67b85aaSmrg					       PCI_DEV_MAP_FLAG_WRITABLE |
1045f67b85aaSmrg					       PCI_DEV_MAP_FLAG_WRITE_COMBINE,
1046f67b85aaSmrg					       result);
1047f67b85aaSmrg
10483e51e026Smrg		if (err) {
10493e51e026Smrg			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
10503e51e026Smrg			   "Cound not map framebuffer: %d\n", err);
1051f67b85aaSmrg			return FALSE;
10523e51e026Smrg		}
1053f67b85aaSmrg	}
1054f67b85aaSmrg#endif
1055f67b85aaSmrg
1056943345d3Smrg	if (!pARK->FBBase) {
1057943345d3Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1058943345d3Smrg			   "Cound not map framebuffer\n");
1059943345d3Smrg		return FALSE;
1060943345d3Smrg	}
1061943345d3Smrg
1062943345d3Smrg	return TRUE;
1063943345d3Smrg}
1064943345d3Smrg
1065943345d3Smrg
1066943345d3Smrgstatic void ARKUnmapMem(ScrnInfoPtr pScrn)
1067943345d3Smrg{
1068943345d3Smrg	ARKPtr pARK = ARKPTR(pScrn);
1069943345d3Smrg
1070943345d3Smrg	/* XXX vgaHWMapMem() isn't called explicitly, so is this correct? */
1071943345d3Smrg	vgaHWUnmapMem(pScrn);
1072943345d3Smrg
1073f67b85aaSmrg#ifndef XSERVER_LIBPCIACCESS
10743e51e026Smrg	xf86UnMapVidMem(pScrn->scrnIndex, pARK->FBBase,
1075943345d3Smrg			pScrn->videoRam * 1024);
1076f67b85aaSmrg#else
1077f67b85aaSmrg	pci_device_unmap_range(pARK->PciInfo, pARK->FBBase, pScrn->videoRam * 1024);
1078f67b85aaSmrg#endif
1079943345d3Smrg}
1080943345d3Smrg
1081943345d3Smrg
10823e51e026SmrgBool ARKCloseScreen(CLOSE_SCREEN_ARGS_DECL)
1083943345d3Smrg{
10843e51e026Smrg	ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1085943345d3Smrg	ARKPtr pARK = ARKPTR(pScrn);
1086943345d3Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
1087943345d3Smrg
1088943345d3Smrg	if (pScrn->vtSema) {
1089943345d3Smrg		vgaHWUnlock(hwp);
1090943345d3Smrg		ARKWriteMode(pScrn, &hwp->SavedReg, &pARK->SavedRegs);
1091943345d3Smrg		vgaHWLock(hwp);
1092943345d3Smrg		ARKUnmapMem(pScrn);
1093943345d3Smrg	}
1094943345d3Smrg
1095943345d3Smrg	pScrn->vtSema = FALSE;
1096943345d3Smrg	pScreen->CloseScreen = pARK->CloseScreen;
1097943345d3Smrg
1098943345d3Smrg	/* XXX Shouldn't XAADestroyInfoRec() be called? */
1099943345d3Smrg
11003e51e026Smrg	return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
1101943345d3Smrg}
1102943345d3Smrg
1103943345d3Smrg
1104943345d3SmrgBool ARKSaveScreen(ScreenPtr pScreen, int mode)
1105943345d3Smrg{
1106943345d3Smrg	return vgaHWSaveScreen(pScreen, mode);
1107943345d3Smrg}
1108943345d3Smrg
1109943345d3Smrg
11103e51e026SmrgBool ARKSwitchMode(SWITCH_MODE_ARGS_DECL)
1111943345d3Smrg{
11123e51e026Smrg	SCRN_INFO_PTR(arg);
11133e51e026Smrg	return ARKModeInit(pScrn, mode);
1114943345d3Smrg}
1115943345d3Smrg
1116943345d3Smrg
1117943345d3Smrgstatic void ARKLoadPalette(ScrnInfoPtr pScrn, int numColors,
1118943345d3Smrg			   int *indicies, LOCO *colors,
1119943345d3Smrg			   VisualPtr pVisual)
1120943345d3Smrg{
11213e51e026Smrg	unsigned long isaIOBase = 0;
11223e51e026Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
11233e51e026Smrg	isaIOBase += pScrn->domainIOBase;
11243e51e026Smrg#endif
1125943345d3Smrg	int i, index;
1126943345d3Smrg
1127943345d3Smrg	for (i=0; i<numColors; i++) {
1128943345d3Smrg		index = indicies[i];
1129943345d3Smrg		outb(isaIOBase + 0x3c8, index);
1130943345d3Smrg		outb(isaIOBase + 0x3c9, colors[index].red);
1131943345d3Smrg		outb(isaIOBase + 0x3c9, colors[index].green);
1132943345d3Smrg		outb(isaIOBase + 0x3c9, colors[index].blue);
1133943345d3Smrg	}
1134943345d3Smrg}
1135943345d3Smrg
1136943345d3Smrg
11373e51e026Smrgstatic void ARKFreeScreen(FREE_SCREEN_ARGS_DECL)
1138943345d3Smrg{
11393e51e026Smrg	SCRN_INFO_PTR(arg);
1140943345d3Smrg
1141943345d3Smrg	vgaHWFreeHWRec(pScrn);
1142943345d3Smrg
1143943345d3Smrg	ARKFreeRec(pScrn);
1144943345d3Smrg}
1145943345d3Smrg
1146943345d3Smrg
11473e51e026Smrgstatic unsigned char get_daccomm(unsigned long isaIOBase)
1148943345d3Smrg{
1149943345d3Smrg	unsigned char tmp;
1150943345d3Smrg
1151943345d3Smrg	outb(isaIOBase + 0x3c8, 0);
1152943345d3Smrg	inb(isaIOBase + 0x3c6);
1153943345d3Smrg	inb(isaIOBase + 0x3c6);
1154943345d3Smrg	inb(isaIOBase + 0x3c6);
1155943345d3Smrg	inb(isaIOBase + 0x3c6);
1156943345d3Smrg	tmp = inb(isaIOBase + 0x3c6);
1157943345d3Smrg	outb(isaIOBase + 0x3c8, 0);
1158943345d3Smrg
1159943345d3Smrg	return tmp;
1160943345d3Smrg}
1161943345d3Smrg
1162943345d3Smrg
11633e51e026Smrgstatic unsigned char set_daccom(unsigned long isaIOBase, unsigned char comm)
1164943345d3Smrg{
1165943345d3Smrg#if 0
1166943345d3Smrg	outb(isaIOBase + 0x3c8, 0);
1167943345d3Smrg#else
1168943345d3Smrg	inb(isaIOBase + 0x3c8);
1169943345d3Smrg#endif
1170943345d3Smrg	inb(isaIOBase + 0x3c6);
1171943345d3Smrg	inb(isaIOBase + 0x3c6);
1172943345d3Smrg	inb(isaIOBase + 0x3c6);
1173943345d3Smrg	inb(isaIOBase + 0x3c6);
1174943345d3Smrg	outb(isaIOBase + 0x3c6, comm);
1175943345d3Smrg#if 0
1176943345d3Smrg	outb(isaIOBase + 0x3c8, 0);
1177943345d3Smrg#else
1178943345d3Smrg	inb(isaIOBase + 0x3c8);
1179943345d3Smrg#endif
1180943345d3Smrg
1181943345d3Smrg	return inb(isaIOBase + 0x3c6);
1182943345d3Smrg}
1183