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