ark_driver.c revision 943345d3
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ark/ark_driver.c,v 1.22 2003/08/23 15:02:53 dawes Exp $ */
2/*
3 *	Copyright 2000	Ani Joshi <ajoshi@unixbox.com>
4 *
5 *	XFree86 4.x driver for ARK Logic chipset
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that copyright
10 * notice and this permission notice appear in supporting documentation and
11 * that the name of Ani Joshi not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission.  Ani Joshi makes no representations
14 * about the suitability of this software for any purpose.  It is provided
15 * "as-is" without express or implied warranty.
16 *
17 * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
24 *
25 *
26 *	Based on the 3.3.x driver by:
27 *		Harm Hanemaayer <H.Hanemaayer@inter.nl.net>
28 *
29 */
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include "xf86.h"
36#include "xf86_OSproc.h"
37#include "xf86Pci.h"
38#include "xf86PciInfo.h"
39#include "xf86Version.h"
40#include "xf86Resources.h"
41#include "xf86fbman.h"
42#include "xf86cmap.h"
43#include "compiler.h"
44#include "xaa.h"
45#include "mipointer.h"
46#include "micmap.h"
47#include "mibstore.h"
48#include "fb.h"
49#include "ark.h"
50
51#include <string.h>
52
53/*
54 * prototypes
55 */
56static const OptionInfoRec * ARKAvailableOptions(int chipid, int busid);
57static void ARKIdentify(int flags);
58static Bool ARKProbe(DriverPtr drv, int flags);
59static Bool ARKPreInit(ScrnInfoPtr pScrn, int flags);
60static Bool ARKEnterVT(int scrnIndex, int flags);
61static void ARKLeaveVT(int scrnIndex, int flags);
62static void ARKSave(ScrnInfoPtr pScrn);
63static Bool ARKScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
64			  char **argv);
65static Bool ARKMapMem(ScrnInfoPtr pScrn);
66static void ARKUnmapMem(ScrnInfoPtr pScrn);
67static Bool ARKModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
68static void ARKAdjustFrame(int scrnIndex, int x, int y, int flags);
69Bool ARKSwitchMode(int scrnIndex, DisplayModePtr mode, int flags);
70Bool ARKCloseScreen(int scrnIndex, ScreenPtr pScreen);
71Bool ARKSaveScreen(ScreenPtr pScreen, int mode);
72static void ARKFreeScreen(int scrnIndex, int flags);
73static void ARKLoadPalette(ScrnInfoPtr pScrn, int numColors,
74			   int *indicies, LOCO *colors,
75			   VisualPtr pVisual);
76static void ARKWriteMode(ScrnInfoPtr pScrn, vgaRegPtr pVga, ARKRegPtr new);
77
78/* helpers */
79static unsigned char get_daccomm(IOADDRESS);
80static unsigned char set_daccom(IOADDRESS, unsigned char comm);
81
82
83_X_EXPORT DriverRec ARK =
84{
85	ARK_VERSION,
86	DRIVER_NAME,
87	ARKIdentify,
88	ARKProbe,
89	ARKAvailableOptions,
90	NULL,
91	0
92};
93
94/* supported chipsets */
95static SymTabRec ARKChipsets[] = {
96	{ PCI_CHIP_1000PV, "ark1000pv" },
97	{ PCI_CHIP_2000PV, "ark2000pv" },
98	{ PCI_CHIP_2000MT, "ark2000mt" },
99	{ -1,		   NULL }
100};
101
102static PciChipsets ARKPciChipsets[] = {
103	{ PCI_CHIP_1000PV, PCI_CHIP_1000PV, RES_SHARED_VGA },
104	{ PCI_CHIP_2000PV, PCI_CHIP_2000PV, RES_SHARED_VGA },
105	{ PCI_CHIP_2000MT, PCI_CHIP_2000MT, RES_SHARED_VGA },
106	{ -1,		   -1,		    RES_UNDEFINED }
107};
108
109typedef enum {
110	OPTION_NOACCEL
111} ARKOpts;
112
113static const OptionInfoRec ARKOptions[] = {
114	{ OPTION_NOACCEL, "noaccel", OPTV_BOOLEAN, {0}, FALSE },
115	{ -1,		  NULL,	     OPTV_NONE,	   {0}, FALSE }
116};
117
118static const char *fbSymbols[] = {
119	"fbPictureInit",
120	"fbScreenInit",
121	NULL
122};
123
124static const char *vgaHWSymbols[] = {
125	"vgaHWFreeHWRec",
126	"vgaHWGetHWRec",
127	"vgaHWGetIOBase",
128	"vgaHWGetIndex",
129	"vgaHWInit",
130	"vgaHWLock",
131	"vgaHWProtect",
132	"vgaHWRestore",
133	"vgaHWSave",
134	"vgaHWSaveScreen",
135	"vgaHWUnlock",
136	"vgaHWUnmapMem",
137	NULL
138};
139
140static const char *xaaSymbols[] = {
141	"XAACreateInfoRec",
142	"XAAInit",
143	NULL
144};
145
146#ifdef XFree86LOADER
147
148MODULESETUPPROTO(ARKSetup);
149
150static XF86ModuleVersionInfo ARKVersRec = {
151	"ark",
152	MODULEVENDORSTRING,
153	MODINFOSTRING1,
154	MODINFOSTRING2,
155	XORG_VERSION_CURRENT,
156	VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
157	ABI_CLASS_VIDEODRV,
158	ABI_VIDEODRV_VERSION,
159	MOD_CLASS_VIDEODRV,
160	{0, 0, 0, 0}
161};
162
163_X_EXPORT XF86ModuleData arkModuleData = { &ARKVersRec, ARKSetup, NULL };
164
165pointer ARKSetup(pointer module, pointer opts, int *errmaj, int *errmin)
166{
167	static Bool setupDone = FALSE;
168
169	if (!setupDone) {
170		setupDone = TRUE;
171		xf86AddDriver(&ARK, module, 0);
172		LoaderRefSymLists(fbSymbols, vgaHWSymbols, xaaSymbols, NULL);
173		return (pointer) 1;
174	} else {
175		if (errmaj)
176			*errmaj = LDR_ONCEONLY;
177		return NULL;
178	}
179}
180
181#endif /* XFree86LOADER */
182
183
184static Bool ARKGetRec(ScrnInfoPtr pScrn)
185{
186	if (pScrn->driverPrivate)
187		return TRUE;
188
189	pScrn->driverPrivate = xnfcalloc(sizeof(ARKRec), 1);
190
191	return TRUE;
192}
193
194static void ARKFreeRec(ScrnInfoPtr pScrn)
195{
196	if (!pScrn->driverPrivate)
197		return;
198
199	xfree(pScrn->driverPrivate);
200	pScrn->driverPrivate = NULL;
201}
202
203static const OptionInfoRec * ARKAvailableOptions(int chipid, int busid)
204{
205	return ARKOptions;
206}
207
208static void ARKIdentify(int flags)
209{
210	xf86PrintChipsets("ARK", "driver (version " DRIVER_VERSION " for ARK Logic chipset",
211			  ARKChipsets);
212}
213
214static Bool ARKProbe(DriverPtr drv, int flags)
215{
216	int i;
217	GDevPtr *devSections;
218	int *usedChips;
219	int numDevSections;
220	int numUsed;
221	Bool foundScreen = FALSE;
222
223	/* sanity check */
224	if ((numDevSections = xf86MatchDevice("ark", &devSections)) <= 0)
225		return FALSE;
226
227	/* do ISA later */
228	numUsed = xf86MatchPciInstances("ark", PCI_VENDOR_ARK,
229					ARKChipsets, ARKPciChipsets,
230					devSections, numDevSections, drv,
231					&usedChips);
232
233	xfree(devSections);
234
235	if (numUsed <= 0)
236		return FALSE;
237
238	if (flags & PROBE_DETECT)
239		foundScreen = TRUE;
240	else for (i=0; i<numUsed; i++) {
241		ScrnInfoPtr pScrn = xf86AllocateScreen(drv, 0);
242
243		pScrn->driverVersion = VERSION_MAJOR;
244		pScrn->driverName = DRIVER_NAME;
245		pScrn->name = "ark";
246		pScrn->Probe = ARKProbe;
247		pScrn->PreInit = ARKPreInit;
248		pScrn->ScreenInit = ARKScreenInit;
249		pScrn->SwitchMode = ARKSwitchMode;
250		pScrn->AdjustFrame = ARKAdjustFrame;
251		pScrn->EnterVT = ARKEnterVT;
252		pScrn->LeaveVT = ARKLeaveVT;
253		pScrn->FreeScreen = ARKFreeScreen;
254		foundScreen = TRUE;
255		xf86ConfigActivePciEntity(pScrn, usedChips[i], ARKPciChipsets,
256					  NULL, NULL, NULL, NULL, NULL);
257	}
258
259	xfree(usedChips);
260
261	return foundScreen;
262}
263
264
265static Bool ARKPreInit(ScrnInfoPtr pScrn, int flags)
266{
267	EntityInfoPtr pEnt;
268	ARKPtr pARK;
269	vgaHWPtr hwp;
270	int i;
271	ClockRangePtr clockRanges;
272	rgb zeros = {0, 0, 0};
273	Gamma gzeros = {0.0, 0.0, 0.0};
274	unsigned char tmp;
275
276	if (flags & PROBE_DETECT)
277		return FALSE;
278
279	if (!xf86LoadSubModule(pScrn, "vgahw"))
280		return FALSE;
281
282	xf86LoaderReqSymLists(vgaHWSymbols, NULL);
283
284	if (!vgaHWGetHWRec(pScrn))
285		return FALSE;
286
287	hwp = VGAHWPTR(pScrn);
288	vgaHWGetIOBase(hwp);
289
290	pScrn->monitor = pScrn->confScreen->monitor;
291
292	if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb))
293		return FALSE;
294	else {
295		switch (pScrn->depth) {
296			case 8:
297			case 16:
298			case 24:
299			case 32:
300				/* OK */
301				break;
302			default:
303				xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
304					   "Given depth (%d) is not supported by this driver\n",
305					   pScrn->depth);
306				return FALSE;
307		}
308	}
309
310	xf86PrintDepthBpp(pScrn);
311
312	if (pScrn->depth > 8) {
313		if (!xf86SetWeight(pScrn, zeros, zeros))
314			return FALSE;
315	}
316
317	if (pScrn->depth == 8)
318		pScrn->rgbBits = 8;
319
320	if (!xf86SetDefaultVisual(pScrn, -1))
321		return FALSE;
322
323	pScrn->progClock = TRUE;
324
325	if (!ARKGetRec(pScrn))
326		return FALSE;
327
328	pARK = ARKPTR(pScrn);
329
330	xf86CollectOptions(pScrn, NULL);
331	if (!(pARK->Options = xalloc(sizeof(ARKOptions))))
332		return FALSE;
333	memcpy(pARK->Options, ARKOptions, sizeof(ARKOptions));
334	xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pARK->Options);
335
336	if (xf86ReturnOptValBool(pARK->Options, OPTION_NOACCEL, FALSE)) {
337		pARK->NoAccel = TRUE;
338		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - acceleration disabled\n");
339	} else
340		pARK->NoAccel = FALSE;
341
342	if (pScrn->numEntities > 1) {
343		ARKFreeRec(pScrn);
344		return FALSE;
345	}
346
347	pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
348	if (pEnt->resources) {
349		xfree(pEnt);
350		ARKFreeRec(pScrn);
351		return FALSE;
352	}
353
354	pARK->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
355	xf86RegisterResources(pEnt->index, NULL, ResNone);
356	xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr);
357	xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr);
358
359	if (pEnt->device->chipset && *pEnt->device->chipset) {
360		pScrn->chipset = pEnt->device->chipset;
361		pARK->Chipset = xf86StringToToken(ARKChipsets, pScrn->chipset);
362	} else if (pEnt->device->chipID >= 0) {
363		pARK->Chipset = pEnt->device->chipID;
364		pScrn->chipset = (char *)xf86TokenToString(ARKChipsets,
365							   pARK->Chipset);
366		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
367			   pARK->Chipset);
368	} else {
369		pARK->Chipset = pARK->PciInfo->chipType;
370		pScrn->chipset = (char *)xf86TokenToString(ARKChipsets,
371							   pARK->Chipset);
372	}
373
374	if (pEnt->device->chipRev >= 0) {
375		pARK->ChipRev = pEnt->device->chipRev;
376		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
377			   pARK->ChipRev);
378	} else
379		pARK->ChipRev = pARK->PciInfo->chipRev;
380
381	xfree(pEnt);
382
383	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Chipset: \"%s\"\n", pScrn->chipset);
384
385	pARK->PciTag = pciTag(pARK->PciInfo->bus, pARK->PciInfo->device,
386			      pARK->PciInfo->func);
387
388	/* unlock CRTC[0-7] */
389	outb(hwp->PIOOffset + hwp->IOBase + 4, 0x11);
390	tmp = inb(hwp->PIOOffset + hwp->IOBase + 5);
391	outb(hwp->PIOOffset + hwp->IOBase + 5, tmp & 0x7f);
392	modinx(hwp->PIOOffset + 0x3c4, 0x1d, 0x01, 0x01);
393
394	/* use membase's later on ??? */
395	pARK->FBAddress = (rdinx(hwp->PIOOffset + 0x3c4, 0x13) << 16) +
396			  (rdinx(hwp->PIOOffset + 0x3c4, 0x14) << 24);
397
398	pScrn->memPhysBase = pARK->FBAddress;
399
400	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Framebuffer @ 0x%lx\n",
401		   (unsigned long)pARK->FBAddress);
402
403	if (!xf86SetGamma(pScrn, gzeros))
404		return FALSE;
405
406	if (!pScrn->videoRam) {
407		unsigned char sr10;
408
409		sr10 = rdinx(hwp->PIOOffset + 0x3c4, 0x10);
410		if (pARK->Chipset == PCI_CHIP_1000PV) {
411			if ((sr10 & 0x40) == 0)
412				pScrn->videoRam = 1024;
413			else
414				pScrn->videoRam = 2048;
415		}
416		if (pARK->Chipset == PCI_CHIP_2000PV ||
417		    pARK->Chipset == PCI_CHIP_2000MT) {
418			if ((sr10 & 0xc0) == 0)
419				pScrn->videoRam = 1024;
420			else if ((sr10 & 0xc0) == 0x40)
421				pScrn->videoRam = 2048;
422			else
423				pScrn->videoRam = 4096;
424		}
425
426		xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected %d bytes video ram\n",
427			   pScrn->videoRam);
428	}
429
430	/* try to detect the RAMDAC */
431	{
432		int man_id, dev_id;
433
434		inb(hwp->PIOOffset + 0x3c6);		/* skip cmd register */
435		man_id = inb(hwp->PIOOffset + 0x3c6);	/* manufacturer id */
436		dev_id = inb(hwp->PIOOffset + 0x3c6);	/* device id */
437		if (man_id == 0x84 && dev_id == 0x98) {
438			pARK->ramdac = ZOOMDAC;
439			pARK->dac_width = 16;
440			pARK->multiplex_threshold = 40000;
441			xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
442				   "Detected ZOOMDAC\n");
443		}
444	}
445
446	/* hack for this Bali32 */
447	pARK->ramdac = ATT490;
448	pARK->dac_width = 8;
449
450	pARK->clock_mult = 1;
451	if (pARK->dac_width == 16) {
452		if (pScrn->bitsPerPixel == 32)
453			pARK->clock_mult = 2;
454	}
455
456	clockRanges = xnfcalloc(sizeof(ClockRange), 1);
457	clockRanges->next = NULL;
458	clockRanges->minClock = 20000;
459	clockRanges->maxClock = 80000;
460	clockRanges->clockIndex = -1;
461	clockRanges->interlaceAllowed = FALSE; /* ? */
462	clockRanges->doubleScanAllowed = FALSE; /* ? */
463
464	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
465			      pScrn->display->modes, clockRanges,
466			      NULL, 256, 2048, pScrn->bitsPerPixel,
467			      128, 2048, pScrn->display->virtualX,
468			      pScrn->display->virtualY, pARK->videoRam * 1024,
469			      LOOKUP_BEST_REFRESH);
470	if (i == -1) {
471		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes left\n");
472		ARKFreeRec(pScrn);
473		return FALSE;
474	}
475
476	xf86PruneDriverModes(pScrn);
477
478	if (i == 0 || pScrn->modes == NULL) {
479		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes found\n");
480		ARKFreeRec(pScrn);
481		return FALSE;
482	}
483
484	xf86SetCrtcForModes(pScrn, 0);
485	pScrn->currentMode = pScrn->modes;
486	xf86PrintModes(pScrn);
487	xf86SetDpi(pScrn, 0, 0);
488
489	if (!xf86LoadSubModule(pScrn, "fb")) {
490	    ARKFreeRec(pScrn);
491	    return FALSE;
492	}
493
494	xf86LoaderReqSymLists(fbSymbols, NULL);
495
496	if (!pARK->NoAccel) {
497		if (!xf86LoadSubModule(pScrn, "xaa")) {
498			ARKFreeRec(pScrn);
499			return FALSE;
500		}
501		xf86LoaderReqSymLists(xaaSymbols, NULL);
502	}
503
504	return TRUE;
505}
506
507static Bool ARKScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
508			  char **argv)
509{
510	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
511	ARKPtr pARK = ARKPTR(pScrn);
512
513	pScrn->fbOffset = 0;
514
515	if (!ARKMapMem(pScrn)) {
516		ARKFreeRec(pScrn);
517		return FALSE;
518	}
519
520	ARKSave(pScrn);
521
522	vgaHWBlankScreen(pScrn, TRUE);
523
524	if (!ARKModeInit(pScrn, pScrn->currentMode))
525		return FALSE;
526
527	ARKSaveScreen(pScreen, SCREEN_SAVER_ON);
528
529	pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
530
531	miClearVisualTypes();
532	if (pScrn->bitsPerPixel > 8) {
533		if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
534				      pScrn->rgbBits, pScrn->defaultVisual))
535			return FALSE;
536	} else {
537		if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
538				      pScrn->rgbBits, pScrn->defaultVisual))
539			return FALSE;
540	}
541
542	miSetPixmapDepths ();
543
544	if (!fbScreenInit(pScreen, pARK->FBBase, pScrn->virtualX,
545			  pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
546			  pScrn->displayWidth, pScrn->bitsPerPixel))
547		return FALSE;
548
549	xf86SetBlackWhitePixels(pScreen);
550
551	if (pScrn->bitsPerPixel > 8) {
552		VisualPtr pVis;
553
554		pVis = pScreen->visuals + pScreen->numVisuals;
555		while (--pVis >= pScreen->visuals) {
556			if ((pVis->class | DynamicClass) == DirectColor) {
557				pVis->offsetRed = pScrn->offset.red;
558				pVis->offsetGreen = pScrn->offset.green;
559				pVis->offsetBlue = pScrn->offset.blue;
560				pVis->redMask = pScrn->mask.red;
561				pVis->greenMask = pScrn->mask.green;
562				pVis->blueMask = pScrn->mask.blue;
563			}
564		}
565	}
566
567	/* must be after RGB order fixed */
568
569	fbPictureInit (pScreen, 0, 0);
570
571	miInitializeBackingStore(pScreen);
572	xf86SetBackingStore(pScreen);
573
574	if (!pARK->NoAccel) {
575		if (ARKAccelInit(pScreen)) {
576			xf86DrvMsg(scrnIndex, X_INFO, "Acceleration enabled\n");
577		} else {
578			xf86DrvMsg(scrnIndex, X_ERROR, "Acceleration initialization failed\n");
579			xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
580		}
581	} else {
582			xf86DrvMsg(scrnIndex, X_INFO, "Acceleration disabled\n");
583	}
584
585	miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
586
587	if (!miCreateDefColormap(pScreen))
588		return FALSE;
589
590	if (!xf86HandleColormaps(pScreen, 256, 8, ARKLoadPalette, NULL,
591				 CMAP_RELOAD_ON_MODE_SWITCH))
592		return FALSE;
593
594	vgaHWBlankScreen(pScrn, FALSE);
595
596	pScreen->SaveScreen = ARKSaveScreen;
597	pARK->CloseScreen = pScreen->CloseScreen;
598	pScreen->CloseScreen = ARKCloseScreen;
599
600	return TRUE;
601}
602
603
604
605static void ARKSave(ScrnInfoPtr pScrn)
606{
607	ARKPtr pARK = ARKPTR(pScrn);
608	ARKRegPtr save = &pARK->SavedRegs;
609	vgaHWPtr hwp = VGAHWPTR(pScrn);
610	IOADDRESS isaIOBase = hwp->PIOOffset;
611	IOADDRESS vgaIOBase = isaIOBase + hwp->IOBase;
612
613	vgaHWUnlock(hwp);
614	vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL);
615	vgaHWLock(hwp);
616
617	/* set read and write aperture index to 0 */
618	wrinx(isaIOBase + 0x3c4, 0x15, 0x00);
619	wrinx(isaIOBase + 0x3c4, 0x16, 0x00);
620	outb(isaIOBase + 0x3c8, 0);	/* reset DAC register access mode */
621
622	save->sr10 = rdinx(isaIOBase + 0x3c4, 0x10);
623	save->sr11 = rdinx(isaIOBase + 0x3c4, 0x11);
624	save->sr12 = rdinx(isaIOBase + 0x3c4, 0x12);
625	save->sr13 = rdinx(isaIOBase + 0x3c4, 0x13);
626	save->sr14 = rdinx(isaIOBase + 0x3c4, 0x14);
627	save->sr15 = rdinx(isaIOBase + 0x3c4, 0x15);
628	save->sr16 = rdinx(isaIOBase + 0x3c4, 0x16);
629	save->sr17 = rdinx(isaIOBase + 0x3c4, 0x17);
630	save->sr18 = rdinx(isaIOBase + 0x3c4, 0x18);
631
632#if 0
633	save->sr1d = rdinx(isaIOBase + 0x3c4, 0x1d);
634	save->sr1c = rdinx(isaIOBase + 0x3c4, 0x1c);
635
636	save->sr20 = rdinx(isaIOBase + 0x3c4, 0x20);
637	save->sr21 = rdinx(isaIOBase + 0x3c4, 0x21);
638	save->sr22 = rdinx(isaIOBase + 0x3c4, 0x22);
639	save->sr23 = rdinx(isaIOBase + 0x3c4, 0x23);
640	save->sr24 = rdinx(isaIOBase + 0x3c4, 0x24);
641	save->sr25 = rdinx(isaIOBase + 0x3c4, 0x25);
642	save->sr26 = rdinx(isaIOBase + 0x3c4, 0x26);
643	save->sr27 = rdinx(isaIOBase + 0x3c4, 0x27);
644	save->sr29 = rdinx(isaIOBase + 0x3c4, 0x29);
645	save->sr2a = rdinx(isaIOBase + 0x3c4, 0x2a);
646	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
647	    (pARK->Chipset == PCI_CHIP_2000MT)) {
648		save->sr28 = rdinx(isaIOBase + 0x3c4, 0x28);
649		save->sr2b = rdinx(isaIOBase + 0x3c4, 0x2b);
650	}
651#endif
652
653	save->cr40 = rdinx(vgaIOBase + 4, 0x40);
654	save->cr41 = rdinx(vgaIOBase + 4, 0x41);
655	save->cr42 = rdinx(vgaIOBase + 4, 0x42);
656	save->cr44 = rdinx(vgaIOBase + 4, 0x44);
657
658	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
659	    (pARK->Chipset == PCI_CHIP_2000MT))
660		save->cr46 = rdinx(vgaIOBase + 4, 0x46);
661
662	/* save RAMDAC regs here, based on type */
663	save->dac_command = get_daccomm(isaIOBase);
664}
665
666
667
668static Bool ARKModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
669{
670	ARKPtr pARK = ARKPTR(pScrn);
671	ARKRegPtr new = &pARK->ModeRegs;
672	int multiplexing, dac16, modepitch;
673	vgaHWPtr hwp = VGAHWPTR(pScrn);
674	vgaRegPtr pVga = &hwp->ModeReg;
675	IOADDRESS isaIOBase = hwp->PIOOffset;
676	IOADDRESS vgaIOBase = isaIOBase + hwp->IOBase;
677	unsigned char tmp;
678	int offset;
679
680	multiplexing = 0;
681
682	if ((pScrn->bitsPerPixel == 8) && (pARK->dac_width == 16) &&
683	    (mode->Clock > pARK->multiplex_threshold))
684		multiplexing = 1;
685
686	if (pARK->clock_mult == 2) {
687		if (!mode->CrtcHAdjusted) {
688			mode->CrtcHDisplay <<= 1;
689			mode->CrtcHSyncStart <<= 1;
690			mode->CrtcHSyncEnd <<= 1;
691			mode->CrtcHTotal <<= 1;
692			mode->CrtcHSkew <<= 1;
693			mode->CrtcHAdjusted = TRUE;
694		}
695	}
696
697	if (multiplexing) {
698		if (!mode->CrtcHAdjusted) {
699			mode->CrtcHDisplay >>= 1;
700			mode->CrtcHSyncStart >>= 1;
701			mode->CrtcHSyncEnd >>= 1;
702			mode->CrtcHTotal >>= 1;
703			mode->CrtcHSkew >>= 1;
704			mode->CrtcHAdjusted = TRUE;
705		}
706	}
707
708	if (!vgaHWInit(pScrn, mode))
709		return FALSE;
710
711	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
712	    (pARK->Chipset == PCI_CHIP_2000MT)) {
713		new->cr46 = rdinx(vgaIOBase + 4, 0x46) & ~0x04;
714		dac16 = 0;
715		if (pScrn->bitsPerPixel > 8)
716			dac16 = 1;
717		if (dac16)
718			new->cr46 |= 0x04;
719	}
720
721	offset = (pScrn->displayWidth * (pScrn->bitsPerPixel / 8)) >> 3;
722	pVga->CRTC[0x13] = offset;
723	new->cr41 = (offset & 0x100) >> 5;
724
725	new->sr11 = 0x90;
726	switch (pScrn->bitsPerPixel) {
727		case 8:
728			new->sr11 |= 0x06;
729			break;
730		case 16:
731			new->sr11 |= 0x0a;
732			break;
733		case 24:
734			new->sr11 |= 0x06;
735			break;
736		case 32:
737			if ((pARK->Chipset == PCI_CHIP_2000PV) ||
738			    (pARK->Chipset == PCI_CHIP_2000MT))
739				new->sr11 |= 0x0e;
740			else
741				new->sr11 |= 0x0a;
742			break;
743		default:
744			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
745				   "Unsupported screen depth %d\n",
746				   pScrn->bitsPerPixel);
747			return FALSE;
748	}
749
750	switch (pScrn->displayWidth) {
751		case 640:
752			modepitch = 0;
753			break;
754		case 800:
755			modepitch = 1;
756			break;
757		case 1024:
758			modepitch = 2;
759			break;
760		case 1280:
761			modepitch = 4;
762			break;
763		case 1600:
764			modepitch = 5;
765			break;
766		case 2048:
767			modepitch = 6;
768			break;
769		default:
770			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
771				   "Unsupported screen width %d\n",
772				   pScrn->displayWidth);
773			return FALSE;
774	}
775
776	new->sr17 &= ~0xc7;
777	new->sr17 |= modepitch;
778
779	new->sr10 = rdinx(isaIOBase + 0x3c4, 0x10) & ~0x1f;
780	new->sr10 |= 0x1f;
781
782	new->sr13 = pARK->FBAddress >> 16;
783	new->sr14 = pARK->FBAddress >> 24;
784
785	new->sr12 = rdinx(isaIOBase + 0x3c4, 0x12) & ~0x03;
786	switch (pScrn->videoRam) {
787		case 1024:
788			new->sr12 |= 0x01;
789			break;
790		case 2048:
791			new->sr12 |= 0x02;
792			break;
793		case 4096:
794			new->sr12 |= 0x03;
795			break;
796		default:
797			new->sr12 |= 0x01;
798			break;
799	}
800
801	new->sr15 = new->sr16 = 0;
802
803	tmp = 0;
804	if ((mode->CrtcVTotal - 2) & 0x400)
805		tmp |= 0x80;
806	if ((mode->CrtcVDisplay - 1) & 0x400)
807		tmp |= 0x40;
808	if (mode->CrtcVSyncStart & 0x400)
809		tmp |= 0x10;
810	new->cr40 = tmp;
811
812	tmp = new->cr41;	/* initialized earlier */
813	if ((mode->CrtcHTotal / 8 - 5) & 0x100)
814		tmp |= 0x80;
815	if ((mode->CrtcHDisplay / 8 - 1) & 0x100)
816		tmp |= 0x40;
817	if ((mode->CrtcHSyncStart / 8 - 1) & 0x100)
818		tmp |= 0x20;
819	if ((mode->CrtcHSyncStart / 8) & 0x100)
820		tmp |= 0x10;
821	new->cr41 |= tmp;
822
823	new->cr44 = rdinx(vgaIOBase + 4, 0x44) & ~0x34;
824	new->cr44 &= ~0x01;
825	new->cr42 = 0;
826
827	/* check interlace here later */
828
829	/* set display FIFO threshold */
830	{
831		int threshold;
832		int bandwidthused, percentused;
833
834		/* mostly guesses here as I would need to know more about
835		 * and from the ramdac...
836		 */
837		bandwidthused = (mode->Clock / pARK->clock_mult) *
838				(pScrn->bitsPerPixel / 8);
839		/* 120000 is another guess */
840		percentused = (bandwidthused * 100) / 120000;
841		tmp = rdinx(isaIOBase + 0x3c4, 0x18);
842		if (pARK->Chipset == PCI_CHIP_1000PV) {
843			threshold = 4;
844			tmp |= 0x08;	/* enable full FIFO (8 deep) */
845			tmp &= ~0x07;
846			tmp |= threshold;
847		}
848		if ((pARK->Chipset == PCI_CHIP_2000PV) ||
849		    (pARK->Chipset == PCI_CHIP_2000MT)) {
850			threshold = 12;
851			if (percentused >= 45)
852				threshold = 8;
853			if (percentused >= 70)
854				threshold = 4;
855			tmp &= 0x40;
856			tmp |= 0x10;
857			tmp |= (threshold & 0x0e) >> 1;
858			if (threshold & 0x01)
859				tmp |= 0x80;
860			if (threshold & 0x10)
861				tmp |= 0x20;
862		}
863		new->sr18 = tmp;
864	}
865
866	/* setup the RAMDAC regs */
867	if (pARK->ramdac == ZOOMDAC) {
868		new->dac_command = 0x04;
869		if ((pScrn->bitsPerPixel == 8) && multiplexing)
870			new->dac_command = 0x24;
871		if ((pScrn->bitsPerPixel == 16) && (pARK->dac_width == 16))
872			/* assuming green weight is not 5 */
873			new->dac_command = 0x34;
874		if ((pScrn->bitsPerPixel == 16) && (pARK->dac_width == 8))
875			new->dac_command = 0x64;
876		if ((pScrn->bitsPerPixel == 24) && (pARK->dac_width == 16))
877			new->dac_command = 0xb4;	/* packed */
878		if ((pScrn->bitsPerPixel == 32) && (pARK->dac_width == 16))
879			new->dac_command = 0x54;
880	} else if (pARK->ramdac == ATT490) {
881		new->dac_command = 0x00;
882		if (pScrn->bitsPerPixel == 16)
883			/* assuming green weight is 6 */
884			new->dac_command = 0xc0;
885		if (pScrn->bitsPerPixel == 24)
886			new->dac_command = 0xe0;
887	}
888
889#if 0
890	/* hw cursor regs */
891	new->sr20 = rdinx(isaIOBase + 0x3c4, 0x20);
892	new->sr21 = rdinx(isaIOBase + 0x3c4, 0x21);
893	new->sr22 = rdinx(isaIOBase + 0x3c4, 0x22);
894	new->sr23 = rdinx(isaIOBase + 0x3c4, 0x23);
895	new->sr24 = rdinx(isaIOBase + 0x3c4, 0x24);
896	new->sr25 = rdinx(isaIOBase + 0x3c4, 0x25);
897	new->sr26 = rdinx(isaIOBase + 0x3c4, 0x26);
898	new->sr27 = rdinx(isaIOBase + 0x3c4, 0x27);
899	new->sr29 = rdinx(isaIOBase + 0x3c4, 0x29);
900	new->sr2a = rdinx(isaIOBase + 0x3c4, 0x2a);
901	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
902	    (pARK->Chipset == PCI_CHIP_2000MT)) {
903		new->sr28 = rdinx(isaIOBase + 0x3c4, 0x28);
904		new->sr2b = rdinx(isaIOBase + 0x3c4, 0x3b);
905	}
906#endif
907
908
909	ARKWriteMode(pScrn, pVga, new);
910
911	return TRUE;
912}
913
914
915static void ARKAdjustFrame(int scrnIndex, int x, int y, int flags)
916{
917	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
918	ARKPtr pARK = ARKPTR(pScrn);
919	vgaHWPtr hwp = VGAHWPTR(pScrn);
920	IOADDRESS vgaIOBase = hwp->PIOOffset + hwp->IOBase;
921	int base;
922
923	base = ((y * pScrn->displayWidth + x) *
924		(pScrn->bitsPerPixel / 8));
925
926	if (((pARK->Chipset == PCI_CHIP_2000PV) ||
927	     (pARK->Chipset == PCI_CHIP_2000MT)) &&
928	     (pScrn->videoRam >= 2048))
929		base >>= 3;
930	else
931		base >>= 2;
932	if (pScrn->bitsPerPixel == 24)
933		base -= base % 3;
934
935	outw(vgaIOBase + 4, (base & 0x00ff00) | 0x0c);
936	outw(vgaIOBase + 4, ((base & 0x00ff) << 8) | 0x0d);
937
938	modinx(vgaIOBase + 4, 0x40, 0x07, (base & 0x070000) >> 16);
939}
940
941
942
943static void ARKWriteMode(ScrnInfoPtr pScrn, vgaRegPtr pVga, ARKRegPtr new)
944{
945	ARKPtr pARK = ARKPTR(pScrn);
946	vgaHWPtr hwp = VGAHWPTR(pScrn);
947	IOADDRESS isaIOBase = hwp->PIOOffset;
948	IOADDRESS vgaIOBase = isaIOBase + hwp->IOBase;
949
950	vgaHWProtect(pScrn, TRUE);
951
952	/* set read and write aperture index to 0 */
953	wrinx(isaIOBase + 0x3c4, 0x15, 0x00);
954	wrinx(isaIOBase + 0x3c4, 0x16, 0x00);
955
956	/* write the extended registers first so that textmode font
957	 * restoration can suceed
958	 */
959	wrinx(isaIOBase + 0x3c4, 0x10, new->sr10);
960	wrinx(isaIOBase + 0x3c4, 0x11, new->sr11);
961	wrinx(isaIOBase + 0x3c4, 0x12, new->sr12);
962	wrinx(isaIOBase + 0x3c4, 0x13, new->sr13);
963	wrinx(isaIOBase + 0x3c4, 0x14, new->sr14);
964	wrinx(isaIOBase + 0x3c4, 0x15, new->sr15);
965	wrinx(isaIOBase + 0x3c4, 0x16, new->sr16);
966	wrinx(isaIOBase + 0x3c4, 0x17, new->sr17);
967
968#if 0
969	wrinx(isaIOBase + 0x3c4, 0x1c, new->sr1c);
970	wrinx(isaIOBase + 0x3c4, 0x1d, new->sr1d);
971
972	/* hw cursor regs */
973	wrinx(isaIOBase + 0x3c4, 0x20, new->sr20);
974	wrinx(isaIOBase + 0x3c4, 0x21, new->sr21);
975	wrinx(isaIOBase + 0x3c4, 0x22, new->sr22);
976	wrinx(isaIOBase + 0x3c4, 0x23, new->sr23);
977	wrinx(isaIOBase + 0x3c4, 0x24, new->sr24);
978	wrinx(isaIOBase + 0x3c4, 0x25, new->sr25);
979	wrinx(isaIOBase + 0x3c4, 0x26, new->sr26);
980	wrinx(isaIOBase + 0x3c4, 0x27, new->sr27);
981	wrinx(isaIOBase + 0x3c4, 0x29, new->sr29);
982	wrinx(isaIOBase + 0x3c4, 0x2a, new->sr2a);
983#endif
984
985	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
986	    (pARK->Chipset == PCI_CHIP_2000MT)) {
987		wrinx(isaIOBase + 0x3c4, 0x28, new->sr28);
988		wrinx(isaIOBase + 0x3c4, 0x2B, new->sr2b);
989	}
990
991	wrinx(vgaIOBase + 4, 0x40, new->cr40);
992	wrinx(vgaIOBase + 4, 0x41, new->cr41);
993	wrinx(vgaIOBase + 4, 0x42, new->cr42);
994	wrinx(vgaIOBase + 4, 0x44, new->cr44);
995
996	if ((pARK->Chipset == PCI_CHIP_2000PV) ||
997	    (pARK->Chipset == PCI_CHIP_2000MT))
998		wrinx(vgaIOBase + 4, 0x46, new->cr46);
999
1000	/* RAMDAC regs */
1001	if (pARK->ramdac == ZOOMDAC) {
1002		set_daccom(isaIOBase, new->dac_command);
1003	}
1004
1005	if (xf86IsPrimaryPci(pARK->PciInfo))
1006		vgaHWRestore(pScrn, pVga, VGA_SR_ALL);
1007	else
1008		vgaHWRestore(pScrn, pVga, VGA_SR_MODE);
1009
1010	vgaHWProtect(pScrn, FALSE);
1011}
1012
1013
1014static Bool ARKEnterVT(int scrnIndex, int flags)
1015{
1016	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1017
1018	if (!ARKModeInit(pScrn, pScrn->currentMode))
1019		return FALSE;
1020
1021	ARKAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
1022
1023	return TRUE;
1024}
1025
1026
1027
1028static void ARKLeaveVT(int scrnIndex, int flags)
1029{
1030	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1031	ARKPtr pARK = ARKPTR(pScrn);
1032	ARKRegPtr old = &pARK->SavedRegs;
1033	vgaHWPtr hwp = VGAHWPTR(pScrn);
1034
1035	ARKWriteMode(pScrn, &hwp->ModeReg, old);
1036
1037	vgaHWUnlock(hwp);
1038	vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_FONTS);
1039	vgaHWLock(hwp);
1040}
1041
1042
1043static Bool ARKMapMem(ScrnInfoPtr pScrn)
1044{
1045	ARKPtr pARK = ARKPTR(pScrn);
1046	vgaHWPtr hwp = VGAHWPTR(pScrn);
1047
1048	/* extended to cover MMIO space at 0xB8000 */
1049	hwp->MapSize = 0x20000;
1050
1051	pARK->MMIOBase = xf86MapDomainMemory(pScrn->scrnIndex, VIDMEM_MMIO,
1052					     pARK->PciTag, 0xb8000, 0x8000);
1053
1054	pARK->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
1055				     pARK->PciTag, pARK->FBAddress,
1056				     pScrn->videoRam * 1024);
1057	if (!pARK->FBBase) {
1058		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1059			   "Cound not map framebuffer\n");
1060		return FALSE;
1061	}
1062
1063	return TRUE;
1064}
1065
1066
1067static void ARKUnmapMem(ScrnInfoPtr pScrn)
1068{
1069	ARKPtr pARK = ARKPTR(pScrn);
1070
1071	/* XXX vgaHWMapMem() isn't called explicitly, so is this correct? */
1072	vgaHWUnmapMem(pScrn);
1073
1074	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pARK->FBBase,
1075			pScrn->videoRam * 1024);
1076}
1077
1078
1079Bool ARKCloseScreen(int scrnIndex, ScreenPtr pScreen)
1080{
1081	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1082	ARKPtr pARK = ARKPTR(pScrn);
1083	vgaHWPtr hwp = VGAHWPTR(pScrn);
1084
1085	if (pScrn->vtSema) {
1086		vgaHWUnlock(hwp);
1087		ARKWriteMode(pScrn, &hwp->SavedReg, &pARK->SavedRegs);
1088		vgaHWLock(hwp);
1089		ARKUnmapMem(pScrn);
1090	}
1091
1092	pScrn->vtSema = FALSE;
1093	pScreen->CloseScreen = pARK->CloseScreen;
1094
1095	/* XXX Shouldn't XAADestroyInfoRec() be called? */
1096
1097	return (*pScreen->CloseScreen)(scrnIndex, pScreen);
1098}
1099
1100
1101Bool ARKSaveScreen(ScreenPtr pScreen, int mode)
1102{
1103	return vgaHWSaveScreen(pScreen, mode);
1104}
1105
1106
1107Bool ARKSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
1108{
1109	return ARKModeInit(xf86Screens[scrnIndex], mode);
1110}
1111
1112
1113static void ARKLoadPalette(ScrnInfoPtr pScrn, int numColors,
1114			   int *indicies, LOCO *colors,
1115			   VisualPtr pVisual)
1116{
1117	IOADDRESS isaIOBase = pScrn->domainIOBase;
1118	int i, index;
1119
1120	for (i=0; i<numColors; i++) {
1121		index = indicies[i];
1122		outb(isaIOBase + 0x3c8, index);
1123		outb(isaIOBase + 0x3c9, colors[index].red);
1124		outb(isaIOBase + 0x3c9, colors[index].green);
1125		outb(isaIOBase + 0x3c9, colors[index].blue);
1126	}
1127}
1128
1129
1130static void ARKFreeScreen(int scrnIndex, int flags)
1131{
1132	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1133
1134	vgaHWFreeHWRec(pScrn);
1135
1136	ARKFreeRec(pScrn);
1137}
1138
1139
1140static unsigned char get_daccomm(IOADDRESS isaIOBase)
1141{
1142	unsigned char tmp;
1143
1144	outb(isaIOBase + 0x3c8, 0);
1145	inb(isaIOBase + 0x3c6);
1146	inb(isaIOBase + 0x3c6);
1147	inb(isaIOBase + 0x3c6);
1148	inb(isaIOBase + 0x3c6);
1149	tmp = inb(isaIOBase + 0x3c6);
1150	outb(isaIOBase + 0x3c8, 0);
1151
1152	return tmp;
1153}
1154
1155
1156static unsigned char set_daccom(IOADDRESS isaIOBase, unsigned char comm)
1157{
1158#if 0
1159	outb(isaIOBase + 0x3c8, 0);
1160#else
1161	inb(isaIOBase + 0x3c8);
1162#endif
1163	inb(isaIOBase + 0x3c6);
1164	inb(isaIOBase + 0x3c6);
1165	inb(isaIOBase + 0x3c6);
1166	inb(isaIOBase + 0x3c6);
1167	outb(isaIOBase + 0x3c6, comm);
1168#if 0
1169	outb(isaIOBase + 0x3c8, 0);
1170#else
1171	inb(isaIOBase + 0x3c8);
1172#endif
1173
1174	return inb(isaIOBase + 0x3c6);
1175}
1176