1 
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5 
6 #include "apm.h"
7 #include "xf86cmap.h"
8 #include "shadowfb.h"
9 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
10 #include "xf86Resources.h"
11 #include "xf86RAC.h"
12 #endif
13 #include "xf86int10.h"
14 #include "vbe.h"
15 
16 #include "opaque.h"
17 #ifdef HAVE_XEXTPROTO_71
18 #include <X11/extensions/dpmsconst.h>
19 #else
20 #define DPMS_SERVER
21 #include <X11/extensions/dpms.h>
22 #endif
23 
24 
25 #define APM_VERSION		4000
26 #define APM_NAME		"APM"
27 #define APM_DRIVER_NAME		"apm"
28 #define APM_MAJOR_VERSION       PACKAGE_VERSION_MAJOR
29 #define APM_MINOR_VERSION       PACKAGE_VERSION_MINOR
30 #define APM_PATCHLEVEL          PACKAGE_VERSION_PATCHLEVEL
31 
32 #define PCI_VENDOR_ALLIANCE     0x1142
33 #define PCI_CHIP_AP6422         0x6422
34 #define PCI_CHIP_AT24           0x6424
35 #define PCI_CHIP_AT3D	        0x643D
36 
37 /* bytes to save for text/font data */
38 #define TEXT_AMOUNT 32768
39 
40 /* Mandatory functions */
41 static const OptionInfoRec *	ApmAvailableOptions(int chipid, int busid);
42 static void     ApmIdentify(int flags);
43 static Bool     ApmProbe(DriverPtr drv, int flags);
44 static Bool     ApmPreInit(ScrnInfoPtr pScrn, int flags);
45 static Bool     ApmScreenInit(SCREEN_INIT_ARGS_DECL);
46 static Bool     ApmEnterVT(VT_FUNC_ARGS_DECL);
47 static void     ApmLeaveVT(VT_FUNC_ARGS_DECL);
48 static Bool     ApmCloseScreen(CLOSE_SCREEN_ARGS_DECL);
49 static void     ApmFreeScreen(FREE_SCREEN_ARGS_DECL);
50 static ModeStatus ApmValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode,
51                                Bool verbose, int flags);
52 static Bool	ApmSaveScreen(ScreenPtr pScreen, int mode);
53 static void	ApmUnlock(ApmPtr pApm);
54 static void	ApmLock(ApmPtr pApm);
55 static void	ApmRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg,
56 			    ApmRegPtr ApmReg);
57 static void	ApmLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices,
58 				LOCO *colors, VisualPtr pVisual);
59 static void	ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn,
60 					     int PowerManagementMode,
61 					     int flags);
62 static void	ApmProbeDDC(ScrnInfoPtr pScrn, int index);
63 
64 #ifdef XF86RUSH
65 int ApmPixmapIndex = -1;
66 static unsigned long ApmGeneration = 0;
67 #endif
68 
69 _X_EXPORT DriverRec APM = {
70 	APM_VERSION,
71 	APM_DRIVER_NAME,
72 	ApmIdentify,
73 	ApmProbe,
74 	ApmAvailableOptions,
75 	NULL,
76 	0
77 };
78 
79 static SymTabRec ApmChipsets[] = {
80     { AP6422,	"AP6422"	},
81     { AT24,	"AT24"		},
82     { AT3D,	"AT3D"		},
83     { -1,	NULL		}
84 };
85 
86 static PciChipsets ApmPciChipsets[] = {
87     { PCI_CHIP_AP6422,	PCI_CHIP_AP6422,	RES_SHARED_VGA },
88     { PCI_CHIP_AT24,	PCI_CHIP_AT24,		RES_SHARED_VGA },
89     { PCI_CHIP_AT3D,	PCI_CHIP_AT3D,		RES_SHARED_VGA },
90     { -1,			-1,		RES_UNDEFINED }
91 };
92 
93 typedef enum {
94     OPTION_SET_MCLK,
95     OPTION_SW_CURSOR,
96     OPTION_HW_CURSOR,
97     OPTION_NOLINEAR,
98     OPTION_NOACCEL,
99     OPTION_SHADOW_FB,
100     OPTION_PCI_BURST,
101     OPTION_REMAP_DPMS_ON,
102     OPTION_REMAP_DPMS_STANDBY,
103     OPTION_REMAP_DPMS_SUSPEND,
104     OPTION_REMAP_DPMS_OFF,
105     OPTION_PCI_RETRY
106 } ApmOpts;
107 
108 static const OptionInfoRec ApmOptions[] =
109 {
110     {OPTION_SET_MCLK, "SetMclk", OPTV_FREQ,
111 	{0}, FALSE},
112     {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN,
113 	{0}, FALSE},
114     {OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN,
115 	{0}, TRUE},
116     {OPTION_NOLINEAR, "NoLinear", OPTV_BOOLEAN,
117 	{0}, FALSE},
118     {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN,
119 	{0}, FALSE},
120     {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN,
121 	{0}, FALSE},
122     {OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN,
123 	{0}, FALSE},
124     {OPTION_REMAP_DPMS_ON, "Remap_DPMS_On", OPTV_ANYSTR,
125 	{0}, FALSE},
126     {OPTION_REMAP_DPMS_STANDBY, "Remap_DPMS_Standby", OPTV_ANYSTR,
127 	{0}, FALSE},
128     {OPTION_REMAP_DPMS_SUSPEND, "Remap_DPMS_Suspend", OPTV_ANYSTR,
129 	{0}, FALSE},
130     {OPTION_REMAP_DPMS_OFF, "Remap_DPMS_Off", OPTV_ANYSTR,
131 	{0}, FALSE},
132     {OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN,
133 	{0}, FALSE},
134     {-1, NULL, OPTV_NONE,
135 	{0}, FALSE}
136 };
137 
138 #ifdef XFree86LOADER
139 
140 static XF86ModuleVersionInfo apmVersRec = {
141     "apm",
142     MODULEVENDORSTRING,
143     MODINFOSTRING1,
144     MODINFOSTRING2,
145     XORG_VERSION_CURRENT,
146     APM_MAJOR_VERSION, APM_MINOR_VERSION, APM_PATCHLEVEL,
147     ABI_CLASS_VIDEODRV,			/* This is a video driver */
148     ABI_VIDEODRV_VERSION,
149     MOD_CLASS_VIDEODRV,
150     {0,0,0,0}
151 };
152 
153 static MODULESETUPPROTO(apmSetup);
154 
155 /*
156  * This is the module init data.
157  * Its name has to be the driver name followed by ModuleData.
158  */
159 _X_EXPORT XF86ModuleData apmModuleData = { &apmVersRec, apmSetup, NULL };
160 
161 static pointer
apmSetup(pointer module,pointer opts,int * errmaj,int * errmain)162 apmSetup(pointer module, pointer opts, int *errmaj, int *errmain)
163 {
164     static Bool setupDone = FALSE;
165 
166     if (!setupDone) {
167 	setupDone = TRUE;
168 	xf86AddDriver(&APM, module, 0);
169 
170 	return (pointer)1;
171     }
172     else {
173 	if (errmaj) *errmaj = LDR_ONCEONLY;
174 	return NULL;
175     }
176 }
177 #endif
178 
179 static Bool
ApmGetRec(ScrnInfoPtr pScrn)180 ApmGetRec(ScrnInfoPtr pScrn)
181 {
182     if (pScrn->driverPrivate)
183 	return TRUE;
184     pScrn->driverPrivate = xnfcalloc(sizeof(ApmRec), 1);
185     /* pScrn->driverPrivate != NULL at this point */
186 
187     return TRUE;
188 }
189 
190 static void
ApmFreeRec(ScrnInfoPtr pScrn)191 ApmFreeRec(ScrnInfoPtr pScrn)
192 {
193     free(pScrn->driverPrivate);
194     pScrn->driverPrivate = NULL;
195 }
196 
197 
198 /* unlock Alliance registers */
199 static void
ApmUnlock(ApmPtr pApm)200 ApmUnlock(ApmPtr pApm)
201 {
202     if (pApm->Chipset >= AT3D)
203 	ApmWriteSeq(0x10, 0x12);
204     else
205 	wrinx(pApm->xport, 0x10, 0x12);
206 }
207 
208 /* lock Alliance registers */
209 static void
ApmLock(ApmPtr pApm)210 ApmLock(ApmPtr pApm)
211 {
212     if (pApm->Chipset >= AT3D)
213 	ApmWriteSeq(0x10, pApm->savedSR10 ? 0 : 0x12);
214     else
215 	wrinx(pApm->xport, 0x10, pApm->savedSR10 ? 0 : 0x12);
216 }
217 
218 static void
ApmIdentify(int flags)219 ApmIdentify(int flags)
220 {
221     xf86PrintChipsets(APM_NAME, "driver for the Alliance chipsets",
222 		      ApmChipsets);
223 }
224 
225 static const OptionInfoRec *
ApmAvailableOptions(int chipid,int busid)226 ApmAvailableOptions(int chipid, int busid)
227 {
228     return ApmOptions;
229 }
230 
231 static void
ApmAssignFPtr(ScrnInfoPtr pScrn)232 ApmAssignFPtr(ScrnInfoPtr pScrn)
233 {
234     pScrn->driverVersion	= APM_VERSION;
235     pScrn->driverName		= APM_DRIVER_NAME;
236     pScrn->name			= APM_NAME;
237     pScrn->Probe		= ApmProbe;
238     pScrn->PreInit		= ApmPreInit;
239     pScrn->ScreenInit		= ApmScreenInit;
240     pScrn->SwitchMode		= ApmSwitchMode;
241     pScrn->AdjustFrame		= ApmAdjustFrame;
242     pScrn->EnterVT		= ApmEnterVT;
243     pScrn->LeaveVT		= ApmLeaveVT;
244     pScrn->FreeScreen		= ApmFreeScreen;
245     pScrn->ValidMode		= ApmValidMode;
246 }
247 
248 static Bool
ApmProbe(DriverPtr drv,int flags)249 ApmProbe(DriverPtr drv, int flags)
250 {
251     int			numDevSections, numUsed, i;
252     GDevPtr		*DevSections;
253     int			*usedChips;
254     int			foundScreen = FALSE;
255 
256     /*
257      * Check if there is a chipset override in the config file
258      */
259     if ((numDevSections = xf86MatchDevice(APM_DRIVER_NAME,
260 					   &DevSections)) <= 0)
261 	return FALSE;
262 
263     /*
264      * We need to probe the hardware first. We then need to see how this
265      * fits in with what is given in the config file, and allow the config
266      * file info to override any contradictions.
267      */
268 
269 #ifndef XSERVER_LIBPCIACCESS
270     if (xf86GetPciVideoInfo() == NULL) {
271 	return FALSE;
272     }
273 #endif
274     numUsed = xf86MatchPciInstances(APM_NAME, PCI_VENDOR_ALLIANCE,
275 		    ApmChipsets, ApmPciChipsets, DevSections, numDevSections,
276 		    drv, &usedChips);
277 
278     if (numUsed > 0) {
279 	if (flags & PROBE_DETECT)
280 	    foundScreen = TRUE;
281 	else for (i = 0; i < numUsed; i++) {
282 	    ScrnInfoPtr	pScrn;
283 
284 	    /*
285 	     * Allocate a ScrnInfoRec and claim the slot
286 	     */
287 	    pScrn = NULL;
288 	    if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
289 						   ApmPciChipsets, NULL,
290 						   NULL,NULL,NULL,NULL))){
291 
292 		/*
293 		 * Fill in what we can of the ScrnInfoRec
294 		 */
295 		ApmAssignFPtr(pScrn);
296 		foundScreen = TRUE;
297 	    }
298 	}
299     }
300 
301 
302     free(DevSections);
303     return foundScreen;
304 }
305 
306 /*
307  * GetAccelPitchValues -
308  *
309  * This function returns a list of display width (pitch) values that can
310  * be used in accelerated mode.
311  */
312 static int *
GetAccelPitchValues(ScrnInfoPtr pScrn)313 GetAccelPitchValues(ScrnInfoPtr pScrn)
314 {
315     int *linePitches = NULL;
316     int linep[] = {640, 800, 1024, 1152, 1280, 0};
317 
318     if (sizeof linep > 0) {
319 	linePitches = (int *)xnfalloc(sizeof linep);
320 	memcpy(linePitches, linep, sizeof linep);
321     }
322 
323     return linePitches;
324 }
325 
326 static unsigned int
ddc1Read(ScrnInfoPtr pScrn)327 ddc1Read(ScrnInfoPtr pScrn)
328 {
329     APMDECL(pScrn);
330     unsigned char	tmp;
331 
332     tmp = RDXB_IOP(0xD0);
333     WRXB_IOP(0xD0, tmp & 0x07);
334     while (STATUS_IOP() & 0x800);
335     while (!(STATUS_IOP() & 0x800));
336     return (STATUS_IOP() & STATUS_SDA) != 0;
337 }
338 
339 static void
ApmProbeDDC(ScrnInfoPtr pScrn,int index)340 ApmProbeDDC(ScrnInfoPtr pScrn, int index)
341 {
342     vbeInfoPtr pVbe;
343 
344     if (xf86LoadSubModule(pScrn, "vbe")) {
345         pVbe = VBEInit(NULL, index);
346         ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
347 	vbeFree(pVbe);
348     }
349 }
350 
351 static Bool
ApmPreInit(ScrnInfoPtr pScrn,int flags)352 ApmPreInit(ScrnInfoPtr pScrn, int flags)
353 {
354     APMDECL(pScrn);
355     EntityInfoPtr	pEnt;
356     vgaHWPtr		hwp;
357     MessageType		from;
358     char		*mod = NULL;
359     const char		*s;
360     ClockRangePtr	clockRanges;
361     int			i;
362     xf86MonPtr		MonInfo = NULL;
363     double		real;
364 
365     /*
366      * Note: This function is only called once at server startup, and
367      * not at the start of each server generation.  This means that
368      * only things that are persistent across server generations can
369      * be initialised here.  xf86Screens[] is (pScrn is a pointer to one
370      * of these).  Privates allocated using xf86AllocateScrnInfoPrivateIndex()
371      * are too, and should be used for data that must persist across
372      * server generations.
373      *
374      * Per-generation data should be allocated with
375      * AllocateScreenPrivateIndex() from the ScreenInit() function.
376      */
377 
378     /* Check the number of entities, and fail if it isn't one. */
379     if (pScrn->numEntities != 1)
380 	return FALSE;
381 
382     /* Allocate the ApmRec driverPrivate */
383     if (!ApmGetRec(pScrn)) {
384 	return FALSE;
385     }
386     pApm = APMPTR(pScrn);
387 
388     /* Get the entity */
389     pEnt = pApm->pEnt	= xf86GetEntityInfo(pScrn->entityList[0]);
390     if (pEnt->location.type == BUS_PCI) {
391 	pApm->PciInfo	= xf86GetPciInfoForEntity(pEnt->index);
392 #ifndef XSERVER_LIBPCIACCESS
393 	pApm->PciTag	= pciTag(pApm->PciInfo->bus, pApm->PciInfo->device,
394 				 pApm->PciInfo->func);
395 #endif
396     }
397     else {
398 	pApm->PciInfo	= NULL;
399 #ifndef XSERVER_LIBPCIACCESS
400 	pApm->PciTag	= 0;
401 #endif
402     }
403 
404     if (flags & PROBE_DETECT) {
405         ApmProbeDDC(pScrn, pEnt->index);
406         return TRUE;
407     }
408 
409     /* The vgahw module should be allocated here when needed */
410     if (!xf86LoadSubModule(pScrn, "vgahw"))
411 	return FALSE;
412 
413     /*
414      * Allocate a vgaHWRec
415      */
416     if (!vgaHWGetHWRec(pScrn))
417 	return FALSE;
418 
419     hwp = VGAHWPTR(pScrn);
420     vgaHWSetStdFuncs(hwp);
421     vgaHWGetIOBase(hwp);
422 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
423 #define PIOOFFSET hwp->PIOOffset
424 #else
425 /* FIXME reintroduce domain support */
426 #define PIOOFFSET 0
427 #endif
428     pApm->iobase = PIOOFFSET;
429     pApm->xport = PIOOFFSET + 0x3C4;
430 
431     /* Set pScrn->monitor */
432     pScrn->monitor = pScrn->confScreen->monitor;
433 
434     /* XXX: Access funcs */
435     /*
436      * The first thing we should figure out is the depth, bpp, etc.
437      */
438     if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb)) {
439 	return FALSE;
440     } else {
441 	/* Check that the returned depth is one we support */
442 	switch (pScrn->depth) {
443 	case 4:
444 	case 8:
445 	case 15:
446 	case 16:
447 	case 24:
448 	    /* OK */
449 	    break;
450 	default:
451 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
452 		       "Given depth (%d) is not supported by this driver\n",
453 		       pScrn->depth);
454 	    return FALSE;
455 	}
456     }
457     xf86PrintDepthBpp(pScrn);
458 
459     /*
460      * This must happen after pScrn->display has been set because
461      * xf86SetWeight references it.
462      */
463     if (pScrn->depth > 8) {
464 	/* The defaults are OK for us */
465 	rgb zeros = {0, 0, 0};
466 
467 	if (!xf86SetWeight(pScrn, zeros, zeros)) {
468 	    return FALSE;
469 	} else {
470 	    /* XXX check that weight returned is supported */
471             ;
472         }
473     }
474 
475     if (!xf86SetDefaultVisual(pScrn, -1)) {
476 	return FALSE;
477     } else {
478 	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
479 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
480 		       " (%s) is not supported at depth %d\n",
481 		       xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
482 	    return FALSE;
483 	}
484     }
485 
486     /* We use a programmable clock */
487     pScrn->progClock = TRUE;
488 
489     /* Collect all of the relevant option flags (fill in pScrn->options) */
490     xf86CollectOptions(pScrn, NULL);
491 
492     /* Process the options */
493     if (!(pApm->Options = malloc(sizeof(ApmOptions))))
494 	return FALSE;
495     memcpy(pApm->Options, ApmOptions, sizeof(ApmOptions));
496     xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pApm->Options);
497 
498     pApm->scrnIndex = pScrn->scrnIndex;
499     /* Set the bits per RGB for 8bpp mode */
500     if (pScrn->depth > 1 && pScrn->depth <= 8) {
501 	/* Default to 8 */
502 	pScrn->rgbBits = 8;
503     }
504     from = X_DEFAULT;
505     pApm->hwCursor = FALSE;
506     if (xf86GetOptValBool(pApm->Options, OPTION_HW_CURSOR, &pApm->hwCursor))
507 	from = X_CONFIG;
508     if (xf86ReturnOptValBool(pApm->Options, OPTION_SW_CURSOR, FALSE)) {
509 	from = X_CONFIG;
510 	pApm->hwCursor = FALSE;
511     }
512     xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
513 		pApm->hwCursor ? "HW" : "SW");
514     from = X_DEFAULT;
515     if (pScrn->bitsPerPixel < 8)
516 	pApm->NoAccel = TRUE;
517     if (xf86ReturnOptValBool(pApm->Options, OPTION_NOACCEL, FALSE)) {
518 	from = X_CONFIG;
519 	pApm->NoAccel = TRUE;
520     }
521     if (pApm->NoAccel)
522 	xf86DrvMsg(pScrn->scrnIndex, from, "Acceleration disabled\n");
523     if (xf86GetOptValFreq(pApm->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) {
524 	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MCLK used is %.1f MHz\n", real);
525 	pApm->MemClk = (int)(real * 1000.0);
526     }
527     if (xf86ReturnOptValBool(pApm->Options, OPTION_SHADOW_FB, FALSE)) {
528 	pApm->ShadowFB = TRUE;
529 	pApm->NoAccel = TRUE;
530 	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
531 		"Using \"Shadow Framebuffer\" - acceleration disabled\n");
532     }
533     if (xf86ReturnOptValBool(pApm->Options, OPTION_PCI_RETRY, FALSE)) {
534 	if (xf86ReturnOptValBool(pApm->Options, OPTION_PCI_BURST, FALSE)) {
535 	  pApm->UsePCIRetry = TRUE;
536 	  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
537 	}
538 	else
539 	  xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"pci_retry\" option requires pci_burst \"on\".\n");
540     }
541     pApm->DPMSMask[DPMSModeOn]		= DPMSModeOn;
542     pApm->DPMSMask[DPMSModeStandby]	= DPMSModeStandby;
543     pApm->DPMSMask[DPMSModeSuspend]	= DPMSModeSuspend;
544     pApm->DPMSMask[DPMSModeOff]		= DPMSModeOff;
545     if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_ON))) {
546 	if (!strcmp(s, "on"))
547 	    pApm->DPMSMask[DPMSModeOn] = DPMSModeOn;
548 	else if (!strcmp(s, "standby"))
549 	    pApm->DPMSMask[DPMSModeOn] = DPMSModeStandby;
550 	else if (!strcmp(s, "suspend"))
551 	    pApm->DPMSMask[DPMSModeOn] = DPMSModeSuspend;
552 	else if (!strcmp(s, "off"))
553 	    pApm->DPMSMask[DPMSModeOn] = DPMSModeOff;
554 	else if (s[0] >= '0' && s[0] <= '9') {
555 	    pApm->DPMSMask[DPMSModeOn] = strtol(s, NULL, 0);
556 	    if (pApm->DPMSMask[DPMSModeOn] > (sizeof pApm->DPMSMask)-1)
557 		pApm->DPMSMask[DPMSModeOn] = (sizeof pApm->DPMSMask) - 1;
558 	}
559     }
560     if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_STANDBY))) {
561 	if (!strcmp(s, "on"))
562 	    pApm->DPMSMask[DPMSModeStandby] = DPMSModeOn;
563 	else if (!strcmp(s, "standby"))
564 	    pApm->DPMSMask[DPMSModeStandby] = DPMSModeStandby;
565 	else if (!strcmp(s, "suspend"))
566 	    pApm->DPMSMask[DPMSModeStandby] = DPMSModeSuspend;
567 	else if (!strcmp(s, "off"))
568 	    pApm->DPMSMask[DPMSModeStandby] = DPMSModeOff;
569 	else if (s[0] >= '0' && s[0] <= '9') {
570 	    pApm->DPMSMask[DPMSModeStandby] = strtol(s, NULL, 0);
571 	    if (pApm->DPMSMask[DPMSModeStandby] > (sizeof pApm->DPMSMask)-1)
572 		pApm->DPMSMask[DPMSModeStandby] = (sizeof pApm->DPMSMask) - 1;
573 	}
574     }
575     if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_SUSPEND))) {
576 	if (!strcmp(s, "on"))
577 	    pApm->DPMSMask[DPMSModeSuspend] = DPMSModeOn;
578 	else if (!strcmp(s, "standby"))
579 	    pApm->DPMSMask[DPMSModeSuspend] = DPMSModeStandby;
580 	else if (!strcmp(s, "suspend"))
581 	    pApm->DPMSMask[DPMSModeSuspend] = DPMSModeSuspend;
582 	else if (!strcmp(s, "off"))
583 	    pApm->DPMSMask[DPMSModeSuspend] = DPMSModeOff;
584 	else if (s[0] >= '0' && s[0] <= '9') {
585 	    pApm->DPMSMask[DPMSModeSuspend] = strtol(s, NULL, 0);
586 	    if (pApm->DPMSMask[DPMSModeSuspend] > (sizeof pApm->DPMSMask)-1)
587 		pApm->DPMSMask[DPMSModeSuspend] = (sizeof pApm->DPMSMask) - 1;
588 	}
589     }
590     if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_OFF))) {
591 	if (!strcmp(s, "on"))
592 	    pApm->DPMSMask[DPMSModeOff] = DPMSModeOn;
593 	else if (!strcmp(s, "standby"))
594 	    pApm->DPMSMask[DPMSModeOff] = DPMSModeStandby;
595 	else if (!strcmp(s, "suspend"))
596 	    pApm->DPMSMask[DPMSModeOff] = DPMSModeSuspend;
597 	else if (!strcmp(s, "off"))
598 	    pApm->DPMSMask[DPMSModeOff] = DPMSModeOff;
599 	else if (s[0] >= '0' && s[0] <= '9') {
600 	    pApm->DPMSMask[DPMSModeOff] = strtol(s, NULL, 0);
601 	    if (pApm->DPMSMask[DPMSModeOff] > (sizeof pApm->DPMSMask)-1)
602 		pApm->DPMSMask[DPMSModeOff] = (sizeof pApm->DPMSMask) - 1;
603 	}
604     }
605 
606     /*
607      * Set the Chipset and ChipRev, allowing config file entries to
608      * override.
609      */
610     if (pEnt->device->chipset && *pEnt->device->chipset) {
611 	pScrn->chipset = pEnt->device->chipset;
612         pApm->Chipset = xf86StringToToken(ApmChipsets, pScrn->chipset);
613         from = X_CONFIG;
614     } else if (pEnt->device->chipID >= 0) {
615 	pApm->Chipset = pEnt->device->chipID;
616 	pScrn->chipset = (char *)xf86TokenToString(ApmChipsets, pApm->Chipset);
617 
618 	from = X_CONFIG;
619 	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
620 		   pApm->Chipset);
621     } else {
622 	from = X_PROBED;
623 	if (pApm->PciInfo)
624 	    pApm->Chipset = PCI_DEV_DEVICE_ID(pApm->PciInfo);
625 	else
626 	    pApm->Chipset = pEnt->chipset;
627 	pScrn->chipset = (char *)xf86TokenToString(ApmChipsets, pApm->Chipset);
628     }
629     if (pScrn->bitsPerPixel == 24 && pApm->Chipset < AT24) {
630 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
631 		   "Given depth (%d) is not supported by this driver\n",
632 		   pScrn->depth);
633 	return FALSE;
634     }
635     if (pEnt->device->chipRev >= 0) {
636 	pApm->ChipRev = pEnt->device->chipRev;
637 	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
638 		   pApm->ChipRev);
639     } else if (pApm->PciInfo) {
640         pApm->ChipRev = PCI_DEV_REVISION(pApm->PciInfo);
641     }
642 
643     /*
644      * This shouldn't happen because such problems should be caught in
645      * ApmProbe(), but check it just in case.
646      */
647     if (pScrn->chipset == NULL) {
648 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
649 		   "ChipID 0x%04X is not recognised\n", pApm->Chipset);
650 	return FALSE;
651     }
652     if (pApm->Chipset < 0) {
653 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
654 		   "Chipset \"%s\" is not recognised\n", pScrn->chipset);
655 	return FALSE;
656     }
657 
658     xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
659 
660     if (pEnt->device->MemBase != 0) {
661 	pApm->LinAddress = pEnt->device->MemBase;
662 	from = X_CONFIG;
663     } else if (pApm->PciInfo) {
664         pApm->LinAddress = PCI_REGION_BASE(pApm->PciInfo, 0, REGION_MEM) & 0xFF800000;
665 	from = X_PROBED;
666     } else {
667 	/*
668 	 * VESA local bus.
669 	 * Pray that 2048MB works.
670 	 */
671 	pApm->LinAddress = 0x80000000;
672     }
673 
674     xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
675 	       (unsigned long)pApm->LinAddress);
676 
677     if (xf86LoadSubModule(pScrn, "ddc")) {
678 	if (xf86LoadSubModule(pScrn, "i2c")) {
679 	    pApm->I2C = TRUE;
680 	}
681     }
682 
683     if (pApm->Chipset >= AT3D)
684 	pApm->LinMapSize  = 16 * 1024 * 1024;
685     else
686 	pApm->LinMapSize  =  6 * 1024 * 1024;
687     pApm->FbMapSize   =  4 * 1024 * 1024;
688 
689     if (xf86LoadSubModule(pScrn, "int10")) {
690 	void	*ptr;
691 
692 	xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n");
693 	ptr = xf86InitInt10(pEnt->index);
694 	if (ptr)
695 	    xf86FreeInt10(ptr);
696     }
697 
698 #ifndef XSERVER_LIBPCIACCESS
699     xf86RegisterResources(pEnt->index, NULL, ResNone);
700     xf86SetOperatingState(resVga, pEnt->index, ResDisableOpr);
701     pScrn->racMemFlags = 0;	/* For noLinear, access to 0xA0000 */
702     if (pApm->VGAMap)
703 	pScrn->racIoFlags = 0;
704     else
705 	pScrn->racIoFlags = RAC_COLORMAP | RAC_VIEWPORT;
706 #endif
707     if (pEnt->device->videoRam != 0) {
708 	pScrn->videoRam = pEnt->device->videoRam;
709 	from = X_CONFIG;
710     } else if (pApm->Chipset >= AT3D) {
711 	unsigned char		d9, db, uc;
712 	/*unsigned long		save;*/
713 	volatile unsigned char	*LinMap;
714 
715 #ifndef XSERVER_LIBPCIACCESS
716 	LinMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
717 				     pApm->PciTag, pApm->LinAddress,
718 				     pApm->LinMapSize);
719 #else
720 	{
721 	    void** result = (void**)&LinMap;
722 	    int err = pci_device_map_range(pApm->PciInfo,
723 					   pApm->LinAddress,
724 					   pApm->LinMapSize,
725 					   PCI_DEV_MAP_FLAG_WRITABLE,
726 					   result);
727 
728 	    if (err)
729 		return FALSE;
730 	}
731 #endif
732 
733 	/*save = pciReadLong(pApm->PciTag, PCI_CMD_STAT_REG);
734 	pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save | PCI_CMD_MEM_ENABLE);*/
735 	d9 = LinMap[0xFFECD9];
736 	db = LinMap[0xFFECDB];
737 	LinMap[0xFFECDB] = (db & 0xF4) | 0x0A;
738 	LinMap[0xFFECD9] = (d9 & 0xCF) | 0x20;
739 	LinMap[0xFFF3C4] = 0x1C;
740 	uc = LinMap[0xFFF3C5];
741 	LinMap[0xFFF3C5] = 0x3F;
742 	LinMap[0xFFF3C4] = 0x20;
743 	pScrn->videoRam = LinMap[0xFFF3C5] * 64;
744 	LinMap[0xFFF3C4] = 0x10;
745 	pApm->savedSR10 = LinMap[0xFFF3C5];
746 	LinMap[0xFFF3C4] = 0x1E;
747 	pApm->xbase  = LinMap[0xFFF3C5];
748 	LinMap[0xFFF3C4] = 0x1F;
749 	pApm->xbase |= LinMap[0xFFF3C5] << 8;
750 	LinMap[0xFFF3C4] = 0x1C;
751 	LinMap[0xFFF3C5] = uc;
752 	LinMap[0xFFECDB] = db;
753 	LinMap[0xFFECD9] = d9;
754 	/*pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save);*/
755 #ifndef XSERVER_LIBPCIACCESS
756 	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)LinMap, pApm->LinMapSize);
757 #else
758 	pci_device_unmap_range(pApm->PciInfo, (pointer)LinMap, pApm->LinMapSize);
759 #endif
760 	from = X_PROBED;
761     }
762     else {
763 	/*unsigned long		save;
764 
765 	save = pciReadLong(pApm->PciTag, PCI_CMD_STAT_REG);
766 	pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save | PCI_CMD_IO_ENABLE);*/
767 	pApm->savedSR10 = rdinx(pApm->xport, 0x10);
768 	wrinx(pApm->xport, 0x10, 0x12);
769 	pScrn->videoRam = rdinx(pApm->xport, 0x20) * 64;
770 	pApm->xbase = rdinx(pApm->xport, 0x1F) << 8;
771 	pApm->xbase |= rdinx(pApm->xport, 0x1E);
772 	pApm->xbase += pApm->iobase;
773 	wrinx(pApm->xport, 0x10, pApm->savedSR10 ? 0 : 0x12);
774 	/*pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save);*/
775 	from = X_PROBED;
776     }
777     if (pApm->Chipset < AT3D && pScrn->videoRam >= 4096)
778 	pScrn->videoRam -= 32;
779 
780     xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
781                pScrn->videoRam);
782 
783 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
784     if (!xf86IsPc98())
785 #endif
786     {
787 	hwp->MapSize = 0x10000;
788 	vgaHWMapMem(pScrn);
789 	if (pApm->I2C) {
790 	    if (!ApmI2CInit(pScrn)) {
791 		xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"I2C initialization failed\n");
792 	    }
793 	    else {
794 		MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn),pApm->I2CPtr);
795 	    }
796 	}
797 	if (0 && !MonInfo)
798 	    MonInfo = xf86DoEDID_DDC1(XF86_SCRN_ARG(pScrn),vgaHWddc1SetSpeed,ddc1Read);
799 	if (MonInfo) {
800 	    xf86PrintEDID(MonInfo);
801 	    xf86SetDDCproperties(pScrn, MonInfo);
802 	}
803 	pScrn->monitor->DDC = MonInfo;
804     }
805 
806     /* The gamma fields must be initialised when using the new cmap code */
807     if (pScrn->depth > 1) {
808 	Gamma zeros = {0.0, 0.0, 0.0};
809 
810 	if (!xf86SetGamma(pScrn, zeros)) {
811 	    return FALSE;
812 	}
813     }
814 
815     pApm->MinClock = 23125;
816     xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock set to %d MHz\n",
817 	       pApm->MinClock / 1000);
818 
819     /*
820      * If the user has specified ramdac speed in the XF86Config
821      * file, we respect that setting.
822      */
823     from = X_DEFAULT;
824     if (pEnt->device->dacSpeeds[0]) {
825 	int speed = 0;
826 
827 	switch (pScrn->bitsPerPixel) {
828 	case 4:
829 	case 8:
830 	   speed = pEnt->device->dacSpeeds[DAC_BPP8];
831 	   break;
832 	case 16:
833 	   speed = pEnt->device->dacSpeeds[DAC_BPP16];
834 	   break;
835 	case 24:
836 	   speed = pEnt->device->dacSpeeds[DAC_BPP24];
837 	   break;
838 	case 32:
839 	   speed = pEnt->device->dacSpeeds[DAC_BPP32];
840 	   break;
841 	}
842 	if (speed == 0)
843 	    pApm->MaxClock = pEnt->device->dacSpeeds[0];
844 	else
845 	    pApm->MaxClock = speed;
846 	from = X_CONFIG;
847     } else {
848 	switch(pApm->Chipset)
849 	{
850 	  /* These values come from the Manual for AT24 and AT3D
851 	     in the overview of various modes. I've taken the largest
852 	     number for the different modes. Alliance wouldn't
853 	     tell me what the maximum frequency was, so...
854 	   */
855 	  case AT24:
856 	       switch(pScrn->bitsPerPixel)
857 	       {
858 		 case 4:
859 		 case 8:
860 		      pApm->MaxClock = 160000;
861 		      break;
862 		 case 16:
863 		      pApm->MaxClock = 144000;
864 		      break;
865 		 case 24:
866 		      pApm->MaxClock = 75000; /* Hmm. */
867 		      break;
868 		 case 32:
869 		      pApm->MaxClock = 94500;
870 		      break;
871 		 default:
872 		      return FALSE;
873 	       }
874 	       break;
875 	  case AT3D:
876 	       switch(pScrn->bitsPerPixel)
877 	       {
878 		 case 4:
879 		 case 8:
880 		      pApm->MaxClock = 175500;
881 		      break;
882 		 case 16:
883 		      pApm->MaxClock = 144000;
884 		      break;
885 		 case 24:
886 		      pApm->MaxClock = 94000; /* Changed from 75000 by Grenié */
887 		      break;
888 		 case 32:
889 		      pApm->MaxClock = 94500;
890 		      break;
891 		 default:
892 		      return FALSE;
893 	       }
894 	       break;
895 	  case AP6422:
896 	       switch(pScrn->bitsPerPixel)
897 	       {
898 		 case 4:
899 		 case 8:
900 		      pApm->MaxClock = 135000;
901 		      break;
902 		 case 16:
903 		      pApm->MaxClock = 75000;
904 		      break;
905 		 case 32:
906 		      pApm->MaxClock = 60000;
907 		      break;
908 		 default:
909 		      return FALSE;
910 	       }
911 	       break;
912 	  default:
913 	       pApm->MaxClock = 135000;
914 	       break;
915 	}
916     }
917     xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
918 	       pApm->MaxClock / 1000);
919 
920     /*
921      * Setup the ClockRanges, which describe what clock ranges are available,
922      * and what sort of modes they can be used for.
923      */
924     clockRanges = (ClockRangePtr)xnfcalloc(sizeof(ClockRange), 1);
925     clockRanges->next = NULL;
926     clockRanges->minClock = pApm->MinClock;
927     clockRanges->maxClock = pApm->MaxClock;
928     clockRanges->clockIndex = -1;		/* programmable */
929     clockRanges->interlaceAllowed = FALSE;	/* XXX change this */
930     clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
931 
932     /* Select valid modes from those available */
933     if (pApm->NoAccel) {
934 	/*
935 	 * XXX Assuming min pitch 256, max 2048
936 	 * XXX Assuming min height 128, max 1024 (changed EE)
937 	 */
938 	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
939 			      pScrn->display->modes, clockRanges,
940 			      NULL, 256, 2048,
941 			      pScrn->bitsPerPixel, 128, 1024,
942 			      pScrn->display->virtualX,
943 			      pScrn->display->virtualY,
944 			      pApm->FbMapSize,
945 			      LOOKUP_BEST_REFRESH);
946     } else {
947 	/*
948 	 * XXX Assuming min height 128, max 2048
949 	 */
950 	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
951 			      pScrn->display->modes, clockRanges,
952 			      GetAccelPitchValues(pScrn), 0, 0,
953 			      pScrn->bitsPerPixel, 128, 1024,
954 			      pScrn->display->virtualX,
955 			      pScrn->display->virtualY,
956 			      pApm->FbMapSize,
957 			      LOOKUP_BEST_REFRESH);
958     }
959 
960     if (i == -1) {
961 	ApmFreeRec(pScrn);
962 	return FALSE;
963     }
964 
965     /* Prune the modes marked as invalid */
966     xf86PruneDriverModes(pScrn);
967 
968     if (i == 0 || pScrn->modes == NULL) {
969 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
970 	ApmFreeRec(pScrn);
971 	return FALSE;
972     }
973 
974     xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
975 
976     /* Set the current mode to the first in the list */
977     pScrn->currentMode = pScrn->modes;
978 
979     /* Print the list of modes being used */
980     xf86PrintModes(pScrn);
981 
982     /* Set display resolution */
983     xf86SetDpi(pScrn, 0, 0);
984 
985     /* Load bpp-specific modules */
986     switch (pScrn->bitsPerPixel) {
987     case 8:
988     case 16:
989     case 24:
990     case 32:
991 	mod = "fb";
992 	break;
993     }
994 
995     if (mod && xf86LoadSubModule(pScrn, mod) == NULL) {
996 	ApmFreeRec(pScrn);
997 	return FALSE;
998     }
999 
1000     /* Load XAA if needed */
1001     if (!pApm->NoAccel) {
1002 #ifdef HAVE_XAA_H
1003 	if (!xf86LoadSubModule(pScrn, "xaa")) {
1004 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadowfb\n");
1005 	    pApm->NoAccel = TRUE;
1006 	    pApm->ShadowFB = TRUE;
1007 	}
1008 #else
1009 	pApm->NoAccel = TRUE;
1010 	pApm->ShadowFB = TRUE;
1011 #endif
1012     }
1013 
1014     /* Load ramdac if needed */
1015     if (pApm->hwCursor) {
1016 	if (!xf86LoadSubModule(pScrn, "ramdac")) {
1017 	    ApmFreeRec(pScrn);
1018 	    return FALSE;
1019 	}
1020     }
1021 
1022     /* Load shadowfb if needed */
1023     if (pApm->ShadowFB) {
1024 	if (!xf86LoadSubModule(pScrn, "shadowfb")) {
1025 	    ApmFreeRec(pScrn);
1026 	    return FALSE;
1027 	}
1028     }
1029 
1030     pApm->CurrentLayout.displayWidth	= pScrn->virtualX;
1031     pApm->CurrentLayout.displayHeight	= pScrn->virtualY;
1032     pApm->CurrentLayout.bitsPerPixel	= pScrn->bitsPerPixel;
1033     pApm->CurrentLayout.bytesPerScanline= (pApm->CurrentLayout.displayWidth * pApm->CurrentLayout.bitsPerPixel) >> 3;
1034     pApm->CurrentLayout.depth		= pScrn->depth;
1035     pApm->CurrentLayout.Scanlines	= 2 * (pScrn->videoRam << 10) / pApm->CurrentLayout.bytesPerScanline;
1036     if (pScrn->bitsPerPixel == 24)
1037 	pApm->CurrentLayout.mask32	= 3;
1038     else
1039 	pApm->CurrentLayout.mask32	= 32 / pScrn->bitsPerPixel - 1;
1040 
1041     return TRUE;
1042 }
1043 
1044 /*
1045  * Map the framebuffer and MMIO memory.
1046  */
1047 
1048 static Bool
ApmMapMem(ScrnInfoPtr pScrn)1049 ApmMapMem(ScrnInfoPtr pScrn)
1050 {
1051     APMDECL(pScrn);
1052     vgaHWPtr	hwp = VGAHWPTR(pScrn);
1053 
1054 #ifndef XSERVER_LIBPCIACCESS
1055     pApm->LinMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
1056 				 pApm->PciTag,
1057 				 (unsigned long)pApm->LinAddress,
1058 				 pApm->LinMapSize);
1059 #else
1060     {
1061 	void** result = (void**)&pApm->LinMap;
1062 	int err = pci_device_map_range(pApm->PciInfo,
1063 				       pApm->LinAddress,
1064 				       pApm->LinMapSize,
1065 				       PCI_DEV_MAP_FLAG_WRITABLE |
1066 				       PCI_DEV_MAP_FLAG_WRITE_COMBINE,
1067 				       result);
1068 
1069 	if (err)
1070 	    return FALSE;
1071     }
1072 #endif
1073 
1074 
1075     if (pApm->LinMap == NULL)
1076 	return FALSE;
1077 
1078     if (pApm->Chipset >= AT3D) {
1079 	pApm->FbBase = (void *)(((char *)pApm->LinMap) + 0x800000);
1080 	pApm->VGAMap = ((char *)pApm->LinMap) + 0xFFF000;
1081 	pApm->MemMap = ((char *)pApm->LinMap) + 0xFFEC00;
1082 	pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x3F8000);
1083     }
1084     else {
1085 	pApm->FbBase = (void *)pApm->LinMap;
1086 	pApm->VGAMap = NULL;
1087 	if (pScrn->videoRam == 6 * 1024 - 32) {
1088 	    pApm->MemMap = ((char *)pApm->LinMap) + 0x5FF800;
1089 	    pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x5F8000);
1090 	}
1091 	else {
1092 	    pApm->MemMap = ((char *)pApm->LinMap) + 0x3FF800;
1093 	    pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x3F8000);
1094 	}
1095     }
1096 
1097     /*
1098      * Initialize chipset
1099      */
1100     pApm->c9 = RDXB(0xC9);
1101     if (pApm->Chipset >= AT3D) {
1102 	pApm->d9 = RDXB(0xD9);
1103 	pApm->db = RDXB(0xDB);
1104 
1105 	/* If you change these two, change them also in apm_funcs.c */
1106 	WRXB(0xDB, (pApm->db & 0xF4) | 0x0A);
1107 	WRXB(0xD9, (pApm->d9 & 0xCF) | 0x20);
1108 
1109 	vgaHWSetMmioFuncs(hwp, (CARD8 *)pApm->LinMap, 0xFFF000);
1110     }
1111     if (pApm->Chipset >= AP6422)
1112 	WRXB(0xC9, pApm->c9 | 0x10);
1113 
1114     /*
1115      * Save color mode
1116      */
1117     pApm->MiscOut = hwp->readMiscOut(hwp);
1118 
1119     return TRUE;
1120 }
1121 
1122 /*
1123  * Unmap the framebuffer and MMIO memory
1124  */
1125 
1126 static Bool
ApmUnmapMem(ScrnInfoPtr pScrn)1127 ApmUnmapMem(ScrnInfoPtr pScrn)
1128 {
1129     APMDECL(pScrn);
1130     vgaHWPtr	hwp = VGAHWPTR(pScrn);
1131 
1132     /*
1133      * Reset color mode
1134      */
1135     hwp->writeMiscOut(hwp, pApm->MiscOut);
1136     if (pApm->LinMap) {
1137 	if (pApm->Chipset >= AT3D) {
1138 	    WRXB(0xD9, pApm->d9);
1139 	    WRXB(0xDB, pApm->db);
1140 	}
1141 	WRXB(0xC9, pApm->c9);
1142 #ifndef XSERVER_LIBPCIACCESS
1143 	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pApm->LinMap, pApm->LinMapSize);
1144 #else
1145 	pci_device_unmap_range(pApm->PciInfo, (pointer)pApm->LinMap, pApm->LinMapSize);
1146 #endif
1147 	pApm->LinMap = NULL;
1148     }
1149     else if (pApm->FbBase)
1150 #ifndef XSERVER_LIBPCIACCESS
1151 	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pApm->LinMap, 0x10000);
1152 #else
1153 	pci_device_unmap_range(pApm->PciInfo, (pointer)pApm->LinMap, 0x10000);
1154 #endif
1155 
1156     return TRUE;
1157 }
1158 
1159 /*
1160  * This function saves the video state.
1161  */
1162 static void
ApmSave(ScrnInfoPtr pScrn)1163 ApmSave(ScrnInfoPtr pScrn)
1164 {
1165     APMDECL(pScrn);
1166     ApmRegPtr	ApmReg = &pApm->SavedReg;
1167     vgaHWPtr	hwp    = VGAHWPTR(pScrn);
1168 
1169     if (pApm->VGAMap) {
1170 	ApmReg->SEQ[0x1B] = ApmReadSeq(0x1B);
1171 	ApmReg->SEQ[0x1C] = ApmReadSeq(0x1C);
1172 
1173 	/*
1174 	 * Save fonts
1175 	 */
1176 	if (!(hwp->SavedReg.Attribute[0x10] & 1)) {
1177 	    if (pApm->FontInfo || (pApm->FontInfo = malloc(TEXT_AMOUNT))) {
1178 		int locked;
1179 
1180 		locked = ApmReadSeq(0x10);
1181 		if (locked)
1182 		    ApmWriteSeq(0x10, 0x12);
1183 		ApmWriteSeq(0x1C, 0x3F);
1184 		memcpy(pApm->FontInfo, pApm->FbBase, TEXT_AMOUNT);
1185 		ApmWriteSeq(0x1C, ApmReg->SEQ[0x1C]);
1186 		if (locked)
1187 		    ApmWriteSeq(0x10, 0);
1188 	    }
1189 	}
1190 	/*
1191 	 * This function will handle creating the data structure and filling
1192 	 * in the generic VGA portion.
1193 	 */
1194 	vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_CMAP);
1195 
1196 	/* Hardware cursor registers. */
1197 	ApmReg->EX[XR140] = RDXL(0x140);
1198 	ApmReg->EX[XR144] = RDXW(0x144);
1199 	ApmReg->EX[XR148] = RDXL(0x148);
1200 	ApmReg->EX[XR14C] = RDXW(0x14C);
1201 
1202 	ApmReg->CRT[0x19] = ApmReadCrtc(0x19);
1203 	ApmReg->CRT[0x1A] = ApmReadCrtc(0x1A);
1204 	ApmReg->CRT[0x1B] = ApmReadCrtc(0x1B);
1205 	ApmReg->CRT[0x1C] = ApmReadCrtc(0x1C);
1206 	ApmReg->CRT[0x1D] = ApmReadCrtc(0x1D);
1207 	ApmReg->CRT[0x1E] = ApmReadCrtc(0x1E);
1208 
1209 	/* RAMDAC registers. */
1210 	ApmReg->EX[XRE8] = RDXL(0xE8);
1211 	ApmReg->EX[XREC] = RDXL(0xEC);
1212 
1213 	/* Color correction */
1214 	ApmReg->EX[XRE0] = RDXL(0xE0);
1215 
1216 	ApmReg->EX[XR80] = RDXB(0x80);
1217     }
1218     else {
1219 	/*
1220 	 * This function will handle creating the data structure and filling
1221 	 * in the generic VGA portion.
1222 	 */
1223 	vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL);
1224 
1225 	ApmReg->SEQ[0x1B] = rdinx(pApm->xport, 0x1B);
1226 	ApmReg->SEQ[0x1C] = rdinx(pApm->xport, 0x1C);
1227 
1228 	/* Hardware cursor registers. */
1229 	ApmReg->EX[XR140] = RDXL(0x140);
1230 	ApmReg->EX[XR144] = RDXW(0x144);
1231 	ApmReg->EX[XR148] = RDXL(0x148);
1232 	ApmReg->EX[XR14C] = RDXW(0x14C);
1233 
1234 	ApmReg->CRT[0x19] = rdinx(pApm->iobase + 0x3D4, 0x19);
1235 	ApmReg->CRT[0x1A] = rdinx(pApm->iobase + 0x3D4, 0x1A);
1236 	ApmReg->CRT[0x1B] = rdinx(pApm->iobase + 0x3D4, 0x1B);
1237 	ApmReg->CRT[0x1C] = rdinx(pApm->iobase + 0x3D4, 0x1C);
1238 	ApmReg->CRT[0x1D] = rdinx(pApm->iobase + 0x3D4, 0x1D);
1239 	ApmReg->CRT[0x1E] = rdinx(pApm->iobase + 0x3D4, 0x1E);
1240 
1241 	/* RAMDAC registers. */
1242 	ApmReg->EX[XRE8] = RDXL(0xE8);
1243 	ApmReg->EX[XREC] = RDXL(0xEC);
1244 
1245 	/* Color correction */
1246 	ApmReg->EX[XRE0] = RDXL(0xE0);
1247 
1248 	ApmReg->EX[XR80] = RDXB(0x80);
1249     }
1250 }
1251 
1252 #define WITHIN(v,c1,c2) (((v) >= (c1)) && ((v) <= (c2)))
1253 
1254 static unsigned
comp_lmn(ApmPtr pApm,long clock)1255 comp_lmn(ApmPtr pApm, long clock)
1256 {
1257   int     n, m, l, f;
1258   double  fvco;
1259   double  fout;
1260   double  fmax, fmin;
1261   double  fref;
1262   double  fvco_goal;
1263   double  k, c;
1264   double fout_best = 0;
1265   unsigned int best = 0;
1266 
1267   if (pApm->Chipset >= AT3D)
1268     fmax = 370000.0;
1269   else
1270     fmax = 250000.0;
1271 
1272   fref = 14318.0;
1273   fmin = fmax / 2.0;
1274 
1275   for (m = 1; m <= 5; m++)
1276   {
1277     for (l = 3; l >= 0; l--)
1278     {
1279       for (n = 8; n <= 127; n++)
1280       {
1281         fout = ((double)(n + 1) * fref)/((double)(m + 1) * (1 << l));
1282         fvco_goal = (double)clock * (double)(1 << l);
1283         fvco = fout * (double)(1 << l);
1284         if (!WITHIN(fvco, 0.99*fvco_goal, 1.01*fvco_goal))
1285           continue;
1286         if (!WITHIN(fvco, fmin, fmax))
1287           continue;
1288         if (!WITHIN(fvco / (double)(n+1), 300.0, 300000.0))
1289           continue;
1290         if (!WITHIN(fref / (double)(m+1), 300.0, 300000.0))
1291           continue;
1292 
1293 	if (fout_best != 0) {
1294 	    double diff_new = clock - fout;
1295 	    double diff_old = clock - best;
1296 	    diff_new = diff_new < 0 ? -diff_new : diff_new;
1297 	    diff_old = diff_old < 0 ? -diff_old : diff_old;
1298 	    if (diff_new > diff_old)
1299 		continue;
1300 	}
1301 	fout_best = fout;
1302 
1303         /* The following formula was empirically derived by
1304            matching a number of fvco values with acceptable
1305            values of f.
1306 
1307            (fvco can be 185MHz - 370MHz on AT3D)
1308            (fvco can be 125MHz - 250MHz on AT24/AP6422)
1309 
1310            The table that was measured up follows:
1311 
1312            AT3D
1313 
1314            fvco       f
1315            (125)     (x-7) guess
1316            200       5-7
1317            219       4-7
1318            253       3-6
1319            289       2-5
1320            320       0-4
1321            (400)     (0-x) guess
1322 
1323            AT24
1324 
1325            fvco       f
1326            126       7
1327            200       5-7
1328            211       4-7
1329 
1330            AP6422
1331 
1332            fvco       f
1333            126       7
1334            169       5-7
1335            200       4-5
1336            211       4-5
1337 
1338            From this, a function "f = k * fvco + c" was derived.
1339 
1340            For AT3D, this table was measured with MCLK == 50MHz.
1341            The driver has since been set to use MCLK == 57.3MHz for,
1342            but I don't think that makes a difference here.
1343          */
1344 
1345         if (pApm->Chipset >= AT24)
1346         {
1347           k = 7.0 / (175.0 - 380.0);
1348           c = -k * 380.0;
1349           f = (int)(k * fvco/1000.0 + c + 0.5);
1350           if (f > 7) f = 7;
1351           if (f < 0) f = 0;
1352         } else { /* i.e AP6422 */
1353           c = (211.0*6.0-169.0*4.5)/(211.0-169.0);
1354           k = (4.5-c)/211.0;
1355           f = (int)(k * fvco/1000.0 + c + 0.5);
1356           if (f > 7) f = 7;
1357           if (f < 0) f = 0;
1358         }
1359 
1360         best =  (n << 16) | (m << 8) | (l << 2) | (f << 4);
1361       }
1362     }
1363   }
1364 
1365   if (fout_best != 0)
1366       return best;
1367 
1368   xf86DrvMsg(pApm->scrnIndex, X_PROBED,
1369 		"Cannot find register values for clock %6.2f MHz. "
1370 		"Please use a (slightly) different clock.\n",
1371 		 (double)clock / 1000.0);
1372   return 0;
1373 }
1374 
1375 /*
1376  * Initialise a new mode.  This is currently still using the old
1377  * "initialise struct, restore/write struct to HW" model.  That could
1378  * be changed.
1379  */
1380 
1381 static Bool
ApmModeInit(ScrnInfoPtr pScrn,DisplayModePtr mode)1382 ApmModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
1383 {
1384     APMDECL(pScrn);
1385     ApmRegPtr	ApmReg = &pApm->ModeReg;
1386     vgaHWPtr	hwp;
1387 
1388 
1389     /* set clockIndex to "2" for programmable clocks */
1390     if (pScrn->progClock)
1391 	mode->ClockIndex = 2;
1392 
1393     /* prepare standard VGA register contents */
1394     if (!vgaHWInit(pScrn, mode))
1395 	return FALSE;
1396     pScrn->vtSema = TRUE;
1397     hwp = VGAHWPTR(pScrn);
1398 
1399     hwp->writeMiscOut(hwp, pApm->MiscOut | 0x0F);
1400 
1401 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
1402     if (xf86IsPc98())
1403        outb(0xFAC, 0xFF);
1404 #endif
1405 
1406     memcpy(ApmReg, &pApm->SavedReg, sizeof pApm->SavedReg);
1407 
1408     /*
1409      * The APM chips have a scale factor of 8 for the
1410      * scanline offset. There are four extended bit in addition
1411      * to the 8 VGA bits.
1412      */
1413     {
1414 	int offset;
1415 
1416 	offset = (pApm->CurrentLayout.displayWidth *
1417 		  pApm->CurrentLayout.bitsPerPixel / 8)	>> 3;
1418 	hwp->ModeReg.CRTC[0x13] = offset;
1419 	/* Bit 8 resides at CR1C bits 7:4. */
1420 	ApmReg->CRT[0x1C] = (offset & 0xF00) >> 4;
1421     }
1422 
1423     /* Set pixel depth. */
1424     switch(pApm->CurrentLayout.bitsPerPixel)
1425     {
1426     case 4:
1427 	 ApmReg->EX[XR80] = 0x01;
1428 	 break;
1429     case 8:
1430 	 ApmReg->EX[XR80] = 0x02;
1431 	 break;
1432     case 16:
1433 	 if (pApm->CurrentLayout.depth == 15)
1434 	     ApmReg->EX[XR80] = 0x0C;
1435 	 else
1436 	     ApmReg->EX[XR80] = 0x0D;
1437 	 break;
1438     case 24:
1439 	 ApmReg->EX[XR80] = 0x0E;
1440 	 break;
1441     case 32:
1442 	 ApmReg->EX[XR80] = 0x0F;
1443 	 break;
1444     default:
1445 	 FatalError("Unsupported bit depth %d\n", pApm->CurrentLayout.depth);
1446 	 break;
1447     }
1448 
1449     /* Set banking register to zero. */
1450     ApmReg->EX[XRC0] = 0;
1451 
1452     /* Handle the CRTC overflow bits. */
1453     {
1454 	unsigned char val;
1455 	/* Vertical Overflow. */
1456 	val = 0;
1457 	if ((mode->CrtcVTotal - 2) & 0x400)
1458 	    val |= 0x01;
1459 	if ((mode->CrtcVDisplay - 1) & 0x400)
1460 	    val |= 0x02;
1461 	/* VBlankStart is equal to VSyncStart + 1. */
1462 	if (mode->CrtcVSyncStart & 0x400)
1463 	    val |= 0x04;
1464 	/* VRetraceStart is equal to VSyncStart + 1. */
1465 	if (mode->CrtcVSyncStart & 0x400)
1466 	    val |= 0x08;
1467 	ApmReg->CRT[0x1A] = val;
1468 
1469 	/* Horizontal Overflow. */
1470 	val = 0;
1471 	if ((mode->CrtcHTotal / 8 - 5) & 0x100)
1472 	    val |= 1;
1473 	if ((mode->CrtcHDisplay / 8 - 1) & 0x100)
1474 	    val |= 2;
1475 	/* HBlankStart is equal to HSyncStart - 1. */
1476 	if ((mode->CrtcHSyncStart / 8 - 1) & 0x100)
1477 	    val |= 4;
1478 	/* HRetraceStart is equal to HSyncStart. */
1479 	if ((mode->CrtcHSyncStart / 8) & 0x100)
1480 	    val |= 8;
1481 	ApmReg->CRT[0x1B] = val;
1482 
1483 	/* Assume the CRTC is not KGA (see vgaHWInit) */
1484 	hwp->ModeReg.CRTC[3] = (hwp->ModeReg.CRTC[3] & 0xE0) |
1485 				(((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F);
1486 	hwp->ModeReg.CRTC[5]  = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
1487 				| (hwp->ModeReg.CRTC[5] & 0x7F);
1488 	hwp->ModeReg.CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1489     }
1490     ApmReg->CRT[0x1E] = 1;          /* disable autoreset feature */
1491 
1492     /* Program clock select. */
1493     ApmReg->EX[XREC] = comp_lmn(pApm, mode->Clock);
1494     if (!ApmReg->EX[XREC])
1495       return FALSE;
1496     hwp->ModeReg.MiscOutReg |= 0x0C;
1497 
1498     /* Set up the RAMDAC registers. */
1499 
1500     if (pApm->CurrentLayout.bitsPerPixel > 8)
1501 	/* Get rid of white border. */
1502 	hwp->ModeReg.Attribute[0x11] = 0x00;
1503     else
1504 	hwp->ModeReg.Attribute[0x11] = 0xFF;
1505     if (pApm->MemClk)
1506 	ApmReg->EX[XRE8] = comp_lmn(pApm, pApm->MemClk);
1507     else if (pApm->Chipset >= AT3D)
1508 	ApmReg->EX[XRE8] = 0x071F01E8; /* Enable 58MHz MCLK (actually 57.3 MHz)
1509 				       This is what is used in the Windows
1510 				       drivers. The BIOS sets it to 50MHz. */
1511     else
1512 	ApmReg->EX[XRE8] = RDXL(0xE8); /* No change */
1513 
1514     ApmReg->EX[XRE0] = 0x10;
1515 
1516     /* If you change it, change in apm_funcs.c as well */
1517     if (pApm->Chipset >= AT3D) {
1518 	ApmReg->SEQ[0x1B] = 0x20;
1519 	ApmReg->SEQ[0x1C] = 0x2F;
1520     }
1521     else {
1522 	ApmReg->SEQ[0x1B] = 0x24;
1523 	if (pScrn->videoRam >= 6 * 1024)
1524 	    ApmReg->SEQ[0x1C] = 0x2F;
1525 	else
1526 	    ApmReg->SEQ[0x1C] = 0x2D;
1527     }
1528 
1529     /* ICICICICI */
1530     ApmRestore(pScrn, &hwp->ModeReg, ApmReg);
1531 
1532     return TRUE;
1533 }
1534 
1535 /*
1536  * Restore the initial mode.
1537  */
1538 static void
ApmRestore(ScrnInfoPtr pScrn,vgaRegPtr vgaReg,ApmRegPtr ApmReg)1539 ApmRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, ApmRegPtr ApmReg)
1540 {
1541     APMDECL(pScrn);
1542 
1543     vgaHWProtect(pScrn, TRUE);
1544     ApmUnlock(pApm);
1545 
1546     if (pApm->VGAMap) {
1547 	/*
1548 	 * Restore fonts
1549 	 */
1550 	if (!(vgaReg->Attribute[0x10] & 1) && pApm->FontInfo) {
1551 	    ApmWriteSeq(0x1C, 0x3F);
1552 	    memcpy(pApm->FbBase, pApm->FontInfo, TEXT_AMOUNT);
1553 	}
1554 
1555 	/* Set aperture index to 0. */
1556 	WRXW(0xC0, 0);
1557 
1558 	/*
1559 	 * Write the extended registers first
1560 	 */
1561 	ApmWriteSeq(0x1B, ApmReg->SEQ[0x1B]);
1562 	ApmWriteSeq(0x1C, ApmReg->SEQ[0x1C]);
1563 
1564 	/* Hardware cursor registers. */
1565 	WRXL(0x140, ApmReg->EX[XR140]);
1566 	WRXW(0x144, ApmReg->EX[XR144]);
1567 	WRXL(0x148, ApmReg->EX[XR148]);
1568 	WRXW(0x14C, ApmReg->EX[XR14C]);
1569 
1570 	ApmWriteCrtc(0x19, ApmReg->CRT[0x19]);
1571 	ApmWriteCrtc(0x1A, ApmReg->CRT[0x1A]);
1572 	ApmWriteCrtc(0x1B, ApmReg->CRT[0x1B]);
1573 	ApmWriteCrtc(0x1D, ApmReg->CRT[0x1D]);
1574 	ApmWriteCrtc(0x1E, ApmReg->CRT[0x1E]);
1575 
1576 	/* RAMDAC registers. */
1577 	WRXL(0xE8, ApmReg->EX[XRE8]);
1578 
1579 	WRXL(0xEC, ApmReg->EX[XREC] & ~(1 << 7));
1580 	WRXL(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */
1581 
1582 	/* Color correction */
1583 	WRXL(0xE0, ApmReg->EX[XRE0]);
1584 
1585 	/*
1586 	 * This function handles restoring the generic VGA registers.
1587 	 */
1588 	vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
1589 
1590 	/* set these after setting the default VGA registers */
1591 	ApmWriteCrtc(0x1C, ApmReg->CRT[0x1C]);
1592 	WRXB(0x80, ApmReg->EX[XR80]);
1593     }
1594     else {
1595 	/* Set aperture index to 0. */
1596 	WRXW(0xC0, 0);
1597 
1598 	/*
1599 	 * Write the extended registers first
1600 	 */
1601 	wrinx(pApm->xport, 0x1B, ApmReg->SEQ[0x1B]);
1602 	wrinx(pApm->xport, 0x1C, ApmReg->SEQ[0x1C]);
1603 
1604 	/* Hardware cursor registers. */
1605 	WRXL(0x140, ApmReg->EX[XR140]);
1606 	WRXW(0x144, ApmReg->EX[XR144]);
1607 	WRXL(0x148, ApmReg->EX[XR148]);
1608 	WRXW(0x14C, ApmReg->EX[XR14C]);
1609 
1610 	wrinx(pApm->iobase + 0x3D4, 0x19, ApmReg->CRT[0x19]);
1611 	wrinx(pApm->iobase + 0x3D4, 0x1A, ApmReg->CRT[0x1A]);
1612 	wrinx(pApm->iobase + 0x3D4, 0x1B, ApmReg->CRT[0x1B]);
1613 	wrinx(pApm->iobase + 0x3D4, 0x1C, ApmReg->CRT[0x1C]);
1614 	wrinx(pApm->iobase + 0x3D4, 0x1D, ApmReg->CRT[0x1D]);
1615 	wrinx(pApm->iobase + 0x3D4, 0x1E, ApmReg->CRT[0x1E]);
1616 
1617 	/* RAMDAC registers. */
1618 	WRXL(0xE8, ApmReg->EX[XRE8]);
1619 	WRXL(0xEC, ApmReg->EX[XREC] & ~(1 << 7));
1620 	WRXL(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */
1621 
1622 	/* Color correction */
1623 	WRXL(0xE0, ApmReg->EX[XRE0]);
1624 
1625 	WRXB(0x80, ApmReg->EX[XR80]);
1626 
1627 	/*
1628 	 * This function handles restoring the generic VGA registers.
1629 	 */
1630 	vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL);
1631     }
1632 
1633     vgaHWProtect(pScrn, FALSE);
1634 }
1635 
1636 
1637 /* Refresh a region of the shadow framebuffer to the screen */
1638 static void
ApmRefreshArea(ScrnInfoPtr pScrn,int num,BoxPtr pbox)1639 ApmRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
1640 {
1641     APMDECL(pScrn);
1642     int width, height, Bpp, FBPitch;
1643     unsigned char *src, *dst;
1644 
1645     Bpp = pApm->CurrentLayout.bitsPerPixel >> 3;
1646     FBPitch = pApm->CurrentLayout.bytesPerScanline;
1647 
1648     while(num--) {
1649 	width = (pbox->x2 - pbox->x1) * Bpp;
1650 	height = pbox->y2 - pbox->y1;
1651 	src = pApm->ShadowPtr + (pbox->y1 * pApm->ShadowPitch) +
1652 						(pbox->x1 * Bpp);
1653 	dst = (unsigned char *)pApm->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp);
1654 
1655 	while(height--) {
1656 	    memcpy(dst, src, width);
1657 	    dst += FBPitch;
1658 	    src += pApm->ShadowPitch;
1659 	}
1660 
1661 	pbox++;
1662     }
1663 }
1664 
1665 
1666 /* Mandatory */
1667 
1668 /* This gets called at the start of each server generation */
1669 
1670 static Bool
ApmScreenInit(SCREEN_INIT_ARGS_DECL)1671 ApmScreenInit(SCREEN_INIT_ARGS_DECL)
1672 {
1673     ScrnInfoPtr		pScrn = xf86ScreenToScrn(pScreen);
1674     APMDECL(pScrn);
1675     int			ret;
1676     unsigned char	*FbBase;
1677 
1678     pApm->pScreen = pScreen;
1679 
1680     /* Map the chip memory and MMIO areas */
1681     if (!ApmMapMem(pScrn))
1682 	return FALSE;
1683 
1684     /* No memory reserved yet */
1685     pApm->OffscreenReserved = 0;
1686 
1687     /* Save the current state */
1688     ApmSave(pScrn);
1689 
1690     /* Initialise the first mode */
1691     ApmModeInit(pScrn, pScrn->currentMode);
1692     pApm->CurrentLayout.pMode = pScrn->currentMode;
1693 
1694     /* Darken the screen for aesthetic reasons and set the viewport */
1695     ApmSaveScreen(pScreen, SCREEN_SAVER_ON);
1696     ApmAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1697 
1698     /*
1699      * Reset fb's visual list.
1700      */
1701     miClearVisualTypes();
1702 
1703     /* Setup the visuals we support. */
1704 
1705     /*
1706      * For bpp > 8, the default visuals are not acceptable because we only
1707      * support TrueColor and not DirectColor.  To deal with this, call
1708      * miSetVisualTypes for each visual supported.
1709      */
1710 
1711     if (pApm->CurrentLayout.bitsPerPixel > 8) {
1712 	if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits,
1713 				pScrn->defaultVisual))
1714 	    return FALSE;
1715     } else {
1716 	if (!miSetVisualTypes(pScrn->depth,
1717 			      miGetDefaultVisualMask(pScrn->depth),
1718 			      pScrn->rgbBits, pScrn->defaultVisual))
1719 	    return FALSE;
1720     }
1721 
1722     /*
1723      * Call the framebuffer layer's ScreenInit function, and fill in other
1724      * pScreen fields.
1725      */
1726 
1727     if(pApm->ShadowFB) {
1728 	pApm->ShadowPitch =
1729 		((pScrn->virtualX * pScrn->bitsPerPixel >> 3) + 3) & ~3L;
1730 	pApm->ShadowPtr = malloc(pApm->ShadowPitch * pScrn->virtualY);
1731 	FbBase = pApm->ShadowPtr;
1732     } else {
1733 	pApm->ShadowPtr = NULL;
1734 	FbBase = pApm->FbBase;
1735     }
1736 
1737     /* Reserve memory */
1738     ApmHWCursorReserveSpace(pApm);
1739     ApmAccelReserveSpace(pApm);
1740 
1741     miSetPixmapDepths();
1742 
1743     switch (pScrn->bitsPerPixel) {
1744     case 8:
1745     case 16:
1746     case 24:
1747     case 32:
1748 	ret = fbScreenInit(pScreen, FbBase, pScrn->virtualX,
1749 	    pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
1750 	    pScrn->displayWidth, pScrn->bitsPerPixel);
1751 	break;
1752     default:
1753 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1754 	    "Internal error: invalid bpp (%d) in ApmScrnInit\n",
1755 	    pScrn->bitsPerPixel);
1756 	ret = FALSE;
1757 	break;
1758     }
1759     if (!ret)
1760 	return FALSE;
1761 
1762     if (pScrn->bitsPerPixel > 8) {
1763 	VisualPtr	visual;
1764 
1765 	/* Fixup RGB ordering */
1766 	visual = pScreen->visuals + pScreen->numVisuals;
1767 	while (--visual >= pScreen->visuals) {
1768 	    if ((visual->class | DynamicClass) == DirectColor) {
1769 		visual->offsetRed = pScrn->offset.red;
1770 		visual->offsetGreen = pScrn->offset.green;
1771 		visual->offsetBlue = pScrn->offset.blue;
1772 		visual->redMask = pScrn->mask.red;
1773 		visual->greenMask = pScrn->mask.green;
1774 		visual->blueMask = pScrn->mask.blue;
1775 	    }
1776 	}
1777     }
1778 
1779     /* must be after visual RGB order fixed */
1780     if (pScrn->bitsPerPixel > 4)
1781 	fbPictureInit(pScreen, 0, 0);
1782 
1783     xf86SetBlackWhitePixels(pScreen);
1784 
1785     if (!pApm->ShadowFB) {       /* hardware cursor needs to wrap this layer */
1786 	if(!ApmDGAInit(pScreen)) {
1787 	    xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"DGA initialization failed\n");
1788 	}
1789     }
1790 
1791     /*
1792      * Initialize the acceleration interface.
1793      */
1794 #ifdef HAVE_XAA_H
1795     if (!pApm->NoAccel) {
1796 	ApmAccelInit(pScreen);		/* set up XAA interface */
1797     }
1798 #endif
1799 
1800     xf86SetBackingStore(pScreen);
1801     xf86SetSilkenMouse(pScreen);
1802 
1803     /* Initialise cursor functions */
1804     miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
1805 
1806     /* Initialize HW cursor layer (after DGA and SW cursor) */
1807     if (pApm->hwCursor) {
1808 	if (!ApmHWCursorInit(pScreen))
1809             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1810                 "Hardware cursor initialization failed\n");
1811     }
1812 
1813 
1814     /* Initialise default colourmap */
1815     if (!miCreateDefColormap(pScreen))
1816 	return FALSE;
1817 
1818     /*
1819      * Initialize colormap layer.
1820      * Must follow initialization of the default colormap.
1821      */
1822     if (!xf86HandleColormaps(pScreen, 256, 8, ApmLoadPalette, NULL,
1823 				CMAP_RELOAD_ON_MODE_SWITCH)) {
1824 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Colormap initialization failed\n");
1825 	return FALSE;
1826     }
1827 
1828     if (pApm->ShadowFB)
1829 	ShadowFBInit(pScreen, ApmRefreshArea);
1830 
1831     xf86DPMSInit(pScreen, ApmDisplayPowerManagementSet, 0);
1832 
1833     ApmInitVideo(pScreen);
1834 
1835     pScreen->SaveScreen  = ApmSaveScreen;
1836 
1837     pApm->CloseScreen = pScreen->CloseScreen;
1838     pScreen->CloseScreen = ApmCloseScreen;
1839 
1840     pScrn->memPhysBase = pApm->LinAddress;
1841     pScrn->fbOffset = (((char *)pApm->FbBase) - ((char *)pApm->LinMap));
1842 
1843     /* Report any unused options (only for the first generation) */
1844     if (serverGeneration == 1) {
1845 	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1846     }
1847 
1848 #ifdef XF86RUSH
1849     if (ApmGeneration != serverGeneration) {
1850 	if ((ApmPixmapIndex = AllocatePixmapPrivateIndex()) < 0)
1851 	    return FALSE;
1852 	ApmGeneration = serverGeneration;
1853     }
1854 
1855     if (!AllocatePixmapPrivate(pScreen, ApmPixmapIndex, sizeof(ApmPixmapRec)))
1856 	return FALSE;
1857 #endif
1858 
1859     /* Done */
1860     return TRUE;
1861 }
1862 
1863 /* mandatory */
1864 static void
ApmLoadPalette(ScrnInfoPtr pScrn,int numColors,int * indices,LOCO * colors,VisualPtr pVisual)1865 ApmLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors,
1866 	       VisualPtr pVisual)
1867 {
1868     APMDECL(pScrn);
1869     int i, index, last = -1;
1870 
1871     if (pApm->VGAMap) {
1872 	for (i = 0; i < numColors; i++) {
1873 	    index = indices[i];
1874 	    if (index != last)
1875 		ApmWriteDacWriteAddr(index);
1876 	    last = index + 1;
1877 	    ApmWriteDacData(colors[index].red);
1878 	    ApmWriteDacData(colors[index].green);
1879 	    ApmWriteDacData(colors[index].blue);
1880 	}
1881     }
1882     else {
1883 	for (i = 0; i < numColors; i++) {
1884 	    index = indices[i];
1885 	    if (index != last)
1886 		outb(pApm->iobase + 0x3C8, index);
1887 	    last = index + 1;
1888 	    outb(pApm->iobase + 0x3C9, colors[index].red);
1889 	    outb(pApm->iobase + 0x3C9, colors[index].green);
1890 	    outb(pApm->iobase + 0x3C9, colors[index].blue);
1891 	}
1892     }
1893 }
1894 
1895 /* Usually mandatory */
1896 Bool
ApmSwitchMode(SWITCH_MODE_ARGS_DECL)1897 ApmSwitchMode(SWITCH_MODE_ARGS_DECL)
1898 {
1899     SCRN_INFO_PTR(arg);
1900     return ApmModeInit(pScrn, mode);
1901 }
1902 
1903 /*
1904  * This function is used to initialize the Start Address - the first
1905  * displayed location in the video memory.
1906  */
1907 /* Usually mandatory */
1908 void
ApmAdjustFrame(ADJUST_FRAME_ARGS_DECL)1909 ApmAdjustFrame(ADJUST_FRAME_ARGS_DECL)
1910 {
1911     SCRN_INFO_PTR(arg);
1912     APMDECL(pScrn);
1913     int Base;
1914 
1915     if (pApm->CurrentLayout.bitsPerPixel == 24)
1916 	x = (x + 3) & ~3;
1917     Base = ((y * pApm->CurrentLayout.displayWidth + x) * (pApm->CurrentLayout.bitsPerPixel / 8)) >> 2;
1918     /*
1919      * These are the generic starting address registers.
1920      */
1921     if (pApm->VGAMap) {
1922 	ApmWriteCrtc(0x0C, Base >> 8);
1923 	ApmWriteCrtc(0x0D, Base);
1924 
1925 	/*
1926 	 * Here the high-order bits are masked and shifted, and put into
1927 	 * the appropriate extended registers.
1928 	 */
1929 	ApmWriteCrtc(0x1C, (ApmReadCrtc(0x1C) & 0xF0) | ((Base & 0x0F0000) >> 16));
1930     }
1931     else {
1932 	outw(pApm->iobase + 0x3D4, (Base & 0x00FF00) | 0x0C);
1933 	outw(pApm->iobase + 0x3D4, ((Base & 0x00FF) << 8) | 0x0D);
1934 
1935 	/*
1936 	 * Here the high-order bits are masked and shifted, and put into
1937 	 * the appropriate extended registers.
1938 	 */
1939 	modinx(pApm->iobase + 0x3D4, 0x1C, 0x0F, (Base & 0x0F0000) >> 16);
1940     }
1941 }
1942 
1943 /*
1944  * This is called when VT switching back to the X server.  Its job is
1945  * to reinitialise the video mode.
1946  *
1947  * We may wish to unmap video/MMIO memory too.
1948  */
1949 
1950 /* Mandatory */
1951 static Bool
ApmEnterVT(VT_FUNC_ARGS_DECL)1952 ApmEnterVT(VT_FUNC_ARGS_DECL)
1953 {
1954     SCRN_INFO_PTR(arg);
1955     APMDECL(pScrn);
1956     vgaHWPtr	hwp = VGAHWPTR(pScrn);
1957 
1958     if (pApm->Chipset >= AT3D) {
1959 	/* If you change it, change it also in apm_funcs.c */
1960 	WRXB(0xDB, (pApm->db & 0xF4) | 0x0A | pApm->Rush);
1961 	WRXB(0xD9, (pApm->d9 & 0xCF) | 0x20);
1962     }
1963     if (pApm->Chipset >= AP6422)
1964 	WRXB(0xC9, pApm->c9 | 0x10);
1965     ApmUnlock(APMPTR(pScrn));
1966     vgaHWUnlock(hwp);
1967     /*
1968      * Set color mode
1969      */
1970     hwp->writeMiscOut(hwp, pApm->MiscOut | 0x0F);
1971 
1972     if (!ApmModeInit(pScrn, pScrn->currentMode))
1973 	return FALSE;
1974     ApmAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
1975 
1976     return TRUE;
1977 }
1978 
1979 /* Mandatory */
1980 static void
ApmLeaveVT(VT_FUNC_ARGS_DECL)1981 ApmLeaveVT(VT_FUNC_ARGS_DECL)
1982 {
1983     SCRN_INFO_PTR(arg);
1984     APMDECL(pScrn);
1985     vgaHWPtr	hwp = VGAHWPTR(pScrn);
1986 
1987     ApmRestore(pScrn, &hwp->SavedReg, &pApm->SavedReg);
1988     /*
1989      * Reset color mode
1990      */
1991     (*hwp->writeMiscOut)(hwp, pApm->MiscOut);
1992     vgaHWLock(hwp);
1993     ApmLock(pApm);
1994     if (pApm->Chipset >= AT3D) {
1995 	WRXB(0xD9, pApm->d9);
1996 	WRXB(0xDB, pApm->db);
1997     }
1998     WRXB(0xC9, pApm->c9);
1999 
2000 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
2001     if (xf86IsPc98())
2002 	outb(0xFAC, 0xFE);
2003 #endif
2004 }
2005 
2006 /*
2007  * This is called at the end of each server generation.  It restores the
2008  * original (text) mode.  It should really also unmap the video memory too.
2009  */
2010 
2011 /* Mandatory */
2012 static Bool
ApmCloseScreen(CLOSE_SCREEN_ARGS_DECL)2013 ApmCloseScreen(CLOSE_SCREEN_ARGS_DECL)
2014 {
2015     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2016     vgaHWPtr	hwp = VGAHWPTR(pScrn);
2017     APMDECL(pScrn);
2018 
2019     if (pScrn->vtSema) {
2020 	ApmRestore(pScrn, &hwp->SavedReg, &pApm->SavedReg);
2021 	vgaHWLock(hwp);
2022 	ApmUnmapMem(pScrn);
2023     }
2024 #ifdef HAVE_XAA_H
2025     if(pApm->AccelInfoRec)
2026 	XAADestroyInfoRec(pApm->AccelInfoRec);
2027     if(pApm->DGAXAAInfo)
2028 	XAADestroyInfoRec(pApm->DGAXAAInfo);
2029     pApm->AccelInfoRec = NULL;
2030 #endif
2031     if(pApm->CursorInfoRec)
2032 	xf86DestroyCursorInfoRec(pApm->CursorInfoRec);
2033     pApm->CursorInfoRec = NULL;
2034     free(pApm->DGAModes);
2035     free(pApm->adaptor);
2036 
2037     pScrn->vtSema = FALSE;
2038 
2039 #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
2040     if (xf86IsPc98())
2041 	outb(0xFAC, 0xFE);
2042 #endif
2043 
2044     pScreen->CloseScreen = pApm->CloseScreen;
2045     return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
2046 }
2047 
2048 /* Free up any per-generation data structures */
2049 
2050 /* Optional */
2051 static void
ApmFreeScreen(FREE_SCREEN_ARGS_DECL)2052 ApmFreeScreen(FREE_SCREEN_ARGS_DECL)
2053 {
2054     SCRN_INFO_PTR(arg);
2055     vgaHWFreeHWRec(pScrn);
2056     ApmFreeRec(pScrn);
2057 }
2058 
2059 /* Checks if a mode is suitable for the selected chipset. */
2060 
2061 /* Optional */
2062 static ModeStatus
ApmValidMode(SCRN_ARG_TYPE arg,DisplayModePtr mode,Bool verbose,int flags)2063 ApmValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags)
2064 {
2065     if (mode->Flags & V_INTERLACE)
2066 	return(MODE_BAD);
2067 
2068     return(MODE_OK);
2069 }
2070 
2071 
2072 /*
2073  * ApmDisplayPowerManagementSet --
2074  *
2075  * Sets VESA Display Power Management Signaling (DPMS) Mode.
2076  */
2077 static void
ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn,int PowerManagementMode,int flags)2078 ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
2079 			     int flags)
2080 {
2081     APMDECL(pScrn);
2082     unsigned char dpmsreg, tmp;
2083 
2084     if (PowerManagementMode < sizeof pApm->DPMSMask &&
2085 	    PowerManagementMode >= 0)
2086 	PowerManagementMode = pApm->DPMSMask[PowerManagementMode];
2087     switch (PowerManagementMode)
2088     {
2089     case DPMSModeOn:
2090 	/* Screen: On; HSync: On, VSync: On */
2091 	dpmsreg = 0x00;
2092 	break;
2093     case DPMSModeStandby:
2094 	/* Screen: Off; HSync: Off, VSync: On */
2095 	dpmsreg = 0x01;
2096 	break;
2097     case DPMSModeSuspend:
2098 	/* Screen: Off; HSync: On, VSync: Off */
2099 	dpmsreg = 0x02;
2100 	break;
2101     case DPMSModeOff:
2102 	/* Screen: Off; HSync: Off, VSync: Off */
2103 	dpmsreg = 0x03;
2104 	break;
2105     default:
2106 	dpmsreg = 0;
2107     }
2108     tmp = RDXB(0xD0);
2109     WRXB(0xD0, (tmp & 0xFC) | dpmsreg);
2110 }
2111 
2112 static Bool
ApmSaveScreen(ScreenPtr pScreen,int mode)2113 ApmSaveScreen(ScreenPtr pScreen, int mode)
2114 {
2115     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
2116     Bool unblank;
2117 
2118     unblank = xf86IsUnblank(mode);
2119 
2120     if (unblank)
2121 	SetTimeSinceLastInputEvent();
2122 
2123     if (pScrn->vtSema)
2124 	vgaHWBlankScreen(pScrn, unblank);
2125     return TRUE;
2126 }
2127 
2128 #ifdef APM_DEBUG
2129 unsigned char _L_ACR(unsigned char *x);
_L_ACR(unsigned char * x)2130 unsigned char _L_ACR(unsigned char *x)
2131 {
2132     return *x;
2133 }
2134 
2135 unsigned short _L_ASR(unsigned short *x);
_L_ASR(unsigned short * x)2136 unsigned short _L_ASR(unsigned short *x)
2137 {
2138     return *x;
2139 }
2140 
2141 unsigned int _L_AIR(unsigned int *x);
_L_AIR(unsigned int * x)2142 unsigned int _L_AIR(unsigned int *x)
2143 {
2144     return *x;
2145 }
2146 
2147 void _L_ACW(char *x, char y);
_L_ACW(char * x,char y)2148 void _L_ACW(char *x, char y)
2149 {
2150     *x = y;
2151 }
2152 
2153 void _L_ASW(short *x, short y);
_L_ASW(short * x,short y)2154 void _L_ASW(short *x, short y)
2155 {
2156     *x = y;
2157 }
2158 
2159 void _L_AIW(int *x, int y);
_L_AIW(int * x,int y)2160 void _L_AIW(int *x, int y)
2161 {
2162     *x = y;
2163 }
2164 #endif
2165