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