1
2/**************************************************************************
3
4Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5All Rights Reserved.
6
7Permission is hereby granted, free of charge, to any person obtaining a
8copy of this software and associated documentation files (the
9"Software"), to deal in the Software without restriction, including
10without limitation the rights to use, copy, modify, merge, publish,
11distribute, sub license, and/or sell copies of the Software, and to
12permit persons to whom the Software is furnished to do so, subject to
13the following conditions:
14
15The above copyright notice and this permission notice (including the
16next paragraph) shall be included in all copies or substantial portions
17of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
23ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27**************************************************************************/
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33/*
34 * Authors:
35 *   Keith Whitwell <keith@tungstengraphics.com>
36 *
37 * Add ARGB HW cursor support:
38 *   Alan Hourihane <alanh@tungstengraphics.com>
39 *
40 */
41
42/*
43 * This server does not support these XFree86 4.0 features yet
44 * shadowFb (if requested or acceleration is off)
45 * Overlay planes
46 * DGA
47 */
48
49#include <math.h>
50#include <string.h>
51#include <unistd.h>
52
53/*
54 * These are X and server generic header files.
55 */
56#include "xorg-server.h"
57#include "xf86.h"
58#include "xf86_OSproc.h"
59#include "xf86cmap.h"
60
61#include "compiler.h"
62#include "vgaHW.h"
63#include "mipointer.h"
64#include "micmap.h"
65
66#include "fb.h"
67#include "miscstruct.h"
68#include "xf86xv.h"
69#include <X11/extensions/Xv.h>
70#include "vbe.h"
71
72#include "i810.h"
73#include "i830.h"
74
75#ifdef XF86DRI
76#include "dri.h"
77#endif
78
79/* Required Functions: */
80
81static void I810Identify(int flags);
82static Bool I810DriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr);
83static Bool intel_pci_probe (DriverPtr		drv,
84			     int		entity_num,
85			     struct pci_device	*dev,
86			     intptr_t		match_data);
87
88#ifndef I830_ONLY
89static Bool I810PreInit(ScrnInfoPtr pScrn, int flags);
90static Bool I810ScreenInit(int Index, ScreenPtr pScreen, int argc,
91			   char **argv);
92static Bool I810EnterVT(int scrnIndex, int flags);
93static void I810LeaveVT(int scrnIndex, int flags);
94static Bool I810CloseScreen(int scrnIndex, ScreenPtr pScreen);
95static Bool I810SaveScreen(ScreenPtr pScreen, Bool unblank);
96static void I810FreeScreen(int scrnIndex, int flags);
97static void I810DisplayPowerManagementSet(ScrnInfoPtr pScrn,
98					  int PowerManagermentMode,
99					  int flags);
100static ModeStatus I810ValidMode(int scrnIndex, DisplayModePtr mode,
101				Bool verbose, int flags);
102#endif /* I830_ONLY */
103
104#define INTEL_DEVICE_MATCH(d,i) \
105    { 0x8086, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
106
107static const struct pci_id_match intel_device_match[] = {
108#ifndef I830_ONLY
109   INTEL_DEVICE_MATCH (PCI_CHIP_I810, 0 ),
110   INTEL_DEVICE_MATCH (PCI_CHIP_I810_DC100, 0 ),
111   INTEL_DEVICE_MATCH (PCI_CHIP_I810_E, 0 ),
112   INTEL_DEVICE_MATCH (PCI_CHIP_I815, 0 ),
113#endif
114   INTEL_DEVICE_MATCH (PCI_CHIP_I830_M, 0 ),
115   INTEL_DEVICE_MATCH (PCI_CHIP_845_G, 0 ),
116   INTEL_DEVICE_MATCH (PCI_CHIP_I855_GM, 0 ),
117   INTEL_DEVICE_MATCH (PCI_CHIP_I865_G, 0 ),
118   INTEL_DEVICE_MATCH (PCI_CHIP_I915_G, 0 ),
119   INTEL_DEVICE_MATCH (PCI_CHIP_E7221_G, 0 ),
120   INTEL_DEVICE_MATCH (PCI_CHIP_I915_GM, 0 ),
121   INTEL_DEVICE_MATCH (PCI_CHIP_I945_G, 0 ),
122   INTEL_DEVICE_MATCH (PCI_CHIP_I945_GM, 0 ),
123   INTEL_DEVICE_MATCH (PCI_CHIP_I945_GME, 0 ),
124   INTEL_DEVICE_MATCH (PCI_CHIP_IGD_GM, 0 ),
125   INTEL_DEVICE_MATCH (PCI_CHIP_IGD_G, 0 ),
126   INTEL_DEVICE_MATCH (PCI_CHIP_I965_G, 0 ),
127   INTEL_DEVICE_MATCH (PCI_CHIP_G35_G, 0 ),
128   INTEL_DEVICE_MATCH (PCI_CHIP_I965_Q, 0 ),
129   INTEL_DEVICE_MATCH (PCI_CHIP_I946_GZ, 0 ),
130   INTEL_DEVICE_MATCH (PCI_CHIP_I965_GM, 0 ),
131   INTEL_DEVICE_MATCH (PCI_CHIP_I965_GME, 0 ),
132   INTEL_DEVICE_MATCH (PCI_CHIP_G33_G, 0 ),
133   INTEL_DEVICE_MATCH (PCI_CHIP_Q35_G, 0 ),
134   INTEL_DEVICE_MATCH (PCI_CHIP_Q33_G, 0 ),
135   INTEL_DEVICE_MATCH (PCI_CHIP_GM45_GM, 0 ),
136   INTEL_DEVICE_MATCH (PCI_CHIP_IGD_E_G, 0 ),
137   INTEL_DEVICE_MATCH (PCI_CHIP_G45_G, 0 ),
138   INTEL_DEVICE_MATCH (PCI_CHIP_Q45_G, 0 ),
139   INTEL_DEVICE_MATCH (PCI_CHIP_G41_G, 0 ),
140   INTEL_DEVICE_MATCH (PCI_CHIP_B43_G, 0 ),
141   INTEL_DEVICE_MATCH (PCI_CHIP_IGDNG_D_G, 0 ),
142   INTEL_DEVICE_MATCH (PCI_CHIP_IGDNG_M_G, 0 ),
143    { 0, 0, 0 },
144};
145
146_X_EXPORT DriverRec I810 = {
147   I810_VERSION,
148   I810_DRIVER_NAME,
149   I810Identify,
150   NULL,
151   I810AvailableOptions,
152   NULL,
153   0,
154   I810DriverFunc,
155   intel_device_match,
156   intel_pci_probe
157};
158
159/* *INDENT-OFF* */
160/* Chipsets */
161static SymTabRec I810Chipsets[] = {
162#ifndef I830_ONLY
163   {PCI_CHIP_I810,		"i810"},
164   {PCI_CHIP_I810_DC100,	"i810-dc100"},
165   {PCI_CHIP_I810_E,		"i810e"},
166   {PCI_CHIP_I815,		"i815"},
167#endif
168   {PCI_CHIP_I830_M,		"i830M"},
169   {PCI_CHIP_845_G,		"845G"},
170   {PCI_CHIP_I855_GM,		"852GM/855GM"},
171   {PCI_CHIP_I865_G,		"865G"},
172   {PCI_CHIP_I915_G,		"915G"},
173   {PCI_CHIP_E7221_G,		"E7221 (i915)"},
174   {PCI_CHIP_I915_GM,		"915GM"},
175   {PCI_CHIP_I945_G,		"945G"},
176   {PCI_CHIP_I945_GM,		"945GM"},
177   {PCI_CHIP_I945_GME,		"945GME"},
178   {PCI_CHIP_IGD_GM,		"Pineview GM"},
179   {PCI_CHIP_IGD_G,		"Pineview G"},
180   {PCI_CHIP_I965_G,		"965G"},
181   {PCI_CHIP_G35_G,		"G35"},
182   {PCI_CHIP_I965_Q,		"965Q"},
183   {PCI_CHIP_I946_GZ,		"946GZ"},
184   {PCI_CHIP_I965_GM,		"965GM"},
185   {PCI_CHIP_I965_GME,		"965GME/GLE"},
186   {PCI_CHIP_G33_G,		"G33"},
187   {PCI_CHIP_Q35_G,		"Q35"},
188   {PCI_CHIP_Q33_G,		"Q33"},
189   {PCI_CHIP_GM45_GM,		"GM45"},
190   {PCI_CHIP_IGD_E_G,		"4 Series"},
191   {PCI_CHIP_G45_G,		"G45/G43"},
192   {PCI_CHIP_Q45_G,		"Q45/Q43"},
193   {PCI_CHIP_G41_G,		"G41"},
194   {PCI_CHIP_B43_G,		"B43"},
195   {PCI_CHIP_IGDNG_D_G,		"Clarkdale"},
196   {PCI_CHIP_IGDNG_M_G,		"Arrandale"},
197   {-1,				NULL}
198};
199
200static PciChipsets I810PciChipsets[] = {
201#ifndef I830_ONLY
202   {PCI_CHIP_I810,		PCI_CHIP_I810,		NULL},
203   {PCI_CHIP_I810_DC100,	PCI_CHIP_I810_DC100,	NULL},
204   {PCI_CHIP_I810_E,		PCI_CHIP_I810_E,	NULL},
205   {PCI_CHIP_I815,		PCI_CHIP_I815,		NULL},
206#endif
207   {PCI_CHIP_I830_M,		PCI_CHIP_I830_M,	NULL},
208   {PCI_CHIP_845_G,		PCI_CHIP_845_G,		NULL},
209   {PCI_CHIP_I855_GM,		PCI_CHIP_I855_GM,	NULL},
210   {PCI_CHIP_I865_G,		PCI_CHIP_I865_G,	NULL},
211   {PCI_CHIP_I915_G,		PCI_CHIP_I915_G,	NULL},
212   {PCI_CHIP_E7221_G,		PCI_CHIP_E7221_G,	NULL},
213   {PCI_CHIP_I915_GM,		PCI_CHIP_I915_GM,	NULL},
214   {PCI_CHIP_I945_G,		PCI_CHIP_I945_G,	NULL},
215   {PCI_CHIP_I945_GM,		PCI_CHIP_I945_GM,	NULL},
216   {PCI_CHIP_I945_GME,		PCI_CHIP_I945_GME,	NULL},
217   {PCI_CHIP_IGD_GM,		PCI_CHIP_IGD_GM,	NULL},
218   {PCI_CHIP_IGD_G,		PCI_CHIP_IGD_G,		NULL},
219   {PCI_CHIP_I965_G,		PCI_CHIP_I965_G,	NULL},
220   {PCI_CHIP_G35_G,		PCI_CHIP_G35_G,		NULL},
221   {PCI_CHIP_I965_Q,		PCI_CHIP_I965_Q,	NULL},
222   {PCI_CHIP_I946_GZ,		PCI_CHIP_I946_GZ,	NULL},
223   {PCI_CHIP_I965_GM,		PCI_CHIP_I965_GM,	NULL},
224   {PCI_CHIP_I965_GME,		PCI_CHIP_I965_GME,	NULL},
225   {PCI_CHIP_G33_G,		PCI_CHIP_G33_G,		NULL},
226   {PCI_CHIP_Q35_G,		PCI_CHIP_Q35_G,		NULL},
227   {PCI_CHIP_Q33_G,		PCI_CHIP_Q33_G,		NULL},
228   {PCI_CHIP_GM45_GM,		PCI_CHIP_GM45_GM,	NULL},
229   {PCI_CHIP_IGD_E_G,		PCI_CHIP_IGD_E_G,	NULL},
230   {PCI_CHIP_G45_G,		PCI_CHIP_G45_G,		NULL},
231   {PCI_CHIP_Q45_G,		PCI_CHIP_Q45_G,		NULL},
232   {PCI_CHIP_G41_G,		PCI_CHIP_G41_G,		NULL},
233   {PCI_CHIP_B43_G,		PCI_CHIP_B43_G,		NULL},
234   {PCI_CHIP_IGDNG_D_G,		PCI_CHIP_IGDNG_D_G,	NULL},
235   {PCI_CHIP_IGDNG_M_G,		PCI_CHIP_IGDNG_M_G,	NULL},
236   {-1,				-1, NULL }
237};
238
239#ifndef I830_ONLY
240typedef enum {
241   OPTION_NOACCEL,
242   OPTION_SW_CURSOR,
243   OPTION_COLOR_KEY,
244   OPTION_CACHE_LINES,
245   OPTION_DAC_6BIT,
246   OPTION_DRI,
247   OPTION_NO_DDC,
248   OPTION_SHOW_CACHE,
249   OPTION_XVMC_SURFACES,
250   OPTION_PAGEFLIP
251} I810Opts;
252
253static const OptionInfoRec I810Options[] = {
254   {OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE},
255   {OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE},
256   {OPTION_COLOR_KEY,		"ColorKey",	OPTV_INTEGER,	{0}, FALSE},
257   {OPTION_CACHE_LINES,		"CacheLines",	OPTV_INTEGER,	{0}, FALSE},
258   {OPTION_DAC_6BIT,		"Dac6Bit",	OPTV_BOOLEAN,	{0}, FALSE},
259   {OPTION_DRI,			"DRI",		OPTV_BOOLEAN,	{0}, FALSE},
260   {OPTION_NO_DDC,		"NoDDC",	OPTV_BOOLEAN,	{0}, FALSE},
261   {OPTION_SHOW_CACHE,		"ShowCache",	OPTV_BOOLEAN,	{0}, FALSE},
262   {OPTION_XVMC_SURFACES,	"XvMCSurfaces",	OPTV_INTEGER,	{0}, FALSE},
263   {OPTION_PAGEFLIP,            "PageFlip",     OPTV_BOOLEAN, {0},   FALSE},
264   {-1,				NULL,		OPTV_NONE,	{0}, FALSE}
265};
266/* *INDENT-ON* */
267#endif
268
269#ifndef I810_DEBUG
270int I810_DEBUG = (0
271/*     		  | DEBUG_ALWAYS_SYNC  */
272/*    		  | DEBUG_VERBOSE_ACCEL */
273/*  		  | DEBUG_VERBOSE_SYNC */
274/*  		  | DEBUG_VERBOSE_VGA */
275/*  		  | DEBUG_VERBOSE_RING */
276/*  		  | DEBUG_VERBOSE_OUTREG */
277/*  		  | DEBUG_VERBOSE_MEMORY */
278/*  		  | DEBUG_VERBOSE_CURSOR */
279      );
280#endif
281
282#ifndef I830_ONLY
283#ifdef XF86DRI
284static int i810_pitches[] = {
285   512,
286   1024,
287   2048,
288   4096,
289   0
290};
291#endif
292#endif
293
294int I830EntityIndex = -1;
295
296#ifdef XFree86LOADER
297
298static MODULESETUPPROTO(i810Setup);
299
300static XF86ModuleVersionInfo intelVersRec = {
301   "intel",
302   MODULEVENDORSTRING,
303   MODINFOSTRING1,
304   MODINFOSTRING2,
305   XORG_VERSION_CURRENT,
306   INTEL_VERSION_MAJOR, INTEL_VERSION_MINOR, INTEL_VERSION_PATCH,
307   ABI_CLASS_VIDEODRV,
308   ABI_VIDEODRV_VERSION,
309   MOD_CLASS_VIDEODRV,
310   {0, 0, 0, 0}
311};
312
313_X_EXPORT XF86ModuleData intelModuleData = { &intelVersRec, i810Setup, NULL };
314
315static pointer
316i810Setup(pointer module, pointer opts, int *errmaj, int *errmin)
317{
318   static Bool setupDone = 0;
319
320   /* This module should be loaded only once, but check to be sure.
321    */
322   if (!setupDone) {
323      setupDone = 1;
324      xf86AddDriver(&I810, module,
325		    HaveDriverFuncs
326		    );
327
328      /*
329       * The return value must be non-NULL on success even though there
330       * is no TearDownProc.
331       */
332      return (pointer) 1;
333   } else {
334      if (errmaj)
335	 *errmaj = LDR_ONCEONLY;
336      return NULL;
337   }
338}
339
340#endif
341
342#ifndef I830_ONLY
343/*
344 * I810GetRec and I810FreeRec --
345 *
346 * Private data for the driver is stored in the screen structure.
347 * These two functions create and destroy that private data.
348 *
349 */
350static Bool
351I810GetRec(ScrnInfoPtr pScrn)
352{
353   if (pScrn->driverPrivate)
354      return TRUE;
355
356   pScrn->driverPrivate = xnfcalloc(sizeof(I810Rec), 1);
357   return TRUE;
358}
359
360static void
361I810FreeRec(ScrnInfoPtr pScrn)
362{
363   if (!pScrn)
364      return;
365   if (!pScrn->driverPrivate)
366      return;
367   xfree(pScrn->driverPrivate);
368   pScrn->driverPrivate = NULL;
369}
370#endif
371
372/*
373 * I810Identify --
374 *
375 * Returns the string name for the driver based on the chipset. In this
376 * case it will always be an I810, so we can return a static string.
377 *
378 */
379static void
380I810Identify(int flags)
381{
382   xf86PrintChipsets(I810_NAME, "Driver for Intel Integrated Graphics Chipsets",
383		     I810Chipsets);
384}
385
386const OptionInfoRec *
387I810AvailableOptions(int chipid, int busid)
388{
389#ifndef I830_ONLY
390   const OptionInfoRec *pOptions;
391
392   if ((pOptions = I830AvailableOptions(chipid, busid)))
393      return pOptions;
394   return I810Options;
395#else
396   return I830AvailableOptions(chipid, busid);
397#endif
398}
399
400static Bool
401I810DriverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op, pointer ptr)
402{
403    xorgHWFlags *flag;
404
405    switch (op) {
406        case GET_REQUIRED_HW_INTERFACES:
407            flag = (CARD32*)ptr;
408#ifdef KMS_ONLY
409            (*flag) = 0;
410#else
411	    (*flag) = HW_IO | HW_MMIO;
412#endif
413            return TRUE;
414        default:
415	    /* Unknown or deprecated function */
416            return FALSE;
417    }
418}
419
420struct pci_device *
421intel_host_bridge (void)
422{
423    static const struct pci_slot_match bridge_match = {
424	0, 0, 0, PCI_MATCH_ANY, 0
425    };
426    struct pci_device_iterator	*slot_iterator;
427    struct pci_device		*bridge;
428
429    slot_iterator = pci_slot_match_iterator_create (&bridge_match);
430    bridge = pci_device_next (slot_iterator);
431    pci_iterator_destroy (slot_iterator);
432    return bridge;
433}
434
435/*
436 * intel_pci_probe --
437 *
438 * Look through the PCI bus to find cards that are intel boards.
439 * Setup the dispatch table for the rest of the driver functions.
440 *
441 */
442static Bool intel_pci_probe (DriverPtr		driver,
443			     int		entity_num,
444			     struct pci_device	*device,
445			     intptr_t		match_data)
446{
447    ScrnInfoPtr	    scrn = NULL;
448    EntityInfoPtr   entity;
449
450    scrn = xf86ConfigPciEntity (scrn, 0, entity_num, I810PciChipsets,
451				NULL,
452				NULL, NULL, NULL, NULL);
453    if (scrn != NULL)
454    {
455	scrn->driverVersion = I810_VERSION;
456	scrn->driverName = I810_DRIVER_NAME;
457	scrn->name = I810_NAME;
458	scrn->Probe = NULL;
459
460	entity = xf86GetEntityInfo (entity_num);
461
462	switch (DEVICE_ID(device)) {
463#ifndef I830_ONLY
464	case PCI_CHIP_I810:
465	case PCI_CHIP_I810_DC100:
466	case PCI_CHIP_I810_E:
467	case PCI_CHIP_I815:
468	    scrn->PreInit = I810PreInit;
469	    scrn->ScreenInit = I810ScreenInit;
470	    scrn->SwitchMode = I810SwitchMode;
471	    scrn->AdjustFrame = I810AdjustFrame;
472	    scrn->EnterVT = I810EnterVT;
473	    scrn->LeaveVT = I810LeaveVT;
474	    scrn->FreeScreen = I810FreeScreen;
475	    scrn->ValidMode = I810ValidMode;
476	    break;
477#endif
478	default:
479	    I830InitpScrn(scrn);
480	    break;
481	}
482    }
483    return scrn != NULL;
484}
485
486#ifndef I830_ONLY
487static void
488I810ProbeDDC(ScrnInfoPtr pScrn, int index)
489{
490   vbeInfoPtr pVbe;
491
492   if (xf86LoadSubModule(pScrn, "vbe")) {
493      pVbe = VBEInit(NULL, index);
494      ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
495      vbeFree(pVbe);
496   }
497}
498
499static xf86MonPtr
500I810DoDDC(ScrnInfoPtr pScrn, int index)
501{
502   vbeInfoPtr pVbe;
503   xf86MonPtr MonInfo = NULL;
504   I810Ptr pI810 = I810PTR(pScrn);
505
506   /* Honour Option "noDDC" */
507   if (xf86ReturnOptValBool(pI810->Options, OPTION_NO_DDC, FALSE)) {
508      return MonInfo;
509   }
510
511   if (xf86LoadSubModule(pScrn, "vbe") && (pVbe = VBEInit(NULL, index))) {
512      MonInfo = vbeDoEDID(pVbe, NULL);
513      xf86PrintEDID(MonInfo);
514      xf86SetDDCproperties(pScrn, MonInfo);
515      vbeFree(pVbe);
516   } else {
517      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
518		 "this driver cannot do DDC without VBE\n");
519   }
520
521   return MonInfo;
522}
523
524/*
525 * I810PreInit --
526 *
527 * Do initial setup of the board before we know what resolution we will
528 * be running at.
529 *
530 */
531static Bool
532I810PreInit(ScrnInfoPtr pScrn, int flags)
533{
534   vgaHWPtr hwp;
535   I810Ptr pI810;
536   ClockRangePtr clockRanges;
537   int i;
538   MessageType from;
539   int flags24;
540   rgb defaultWeight = { 0, 0, 0 };
541   int mem;
542   Bool enable;
543
544   if (pScrn->numEntities != 1)
545      return FALSE;
546
547   /* Allocate driverPrivate */
548   if (!I810GetRec(pScrn))
549      return FALSE;
550
551   pI810 = I810PTR(pScrn);
552
553   pI810->pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
554   if (pI810->pEnt->location.type != BUS_PCI)
555      return FALSE;
556
557   if (flags & PROBE_DETECT) {
558      I810ProbeDDC(pScrn, pI810->pEnt->index);
559      return TRUE;
560   }
561
562   /* The vgahw module should be loaded here when needed */
563   if (!xf86LoadSubModule(pScrn, "vgahw"))
564      return FALSE;
565
566   /* Allocate a vgaHWRec */
567   if (!vgaHWGetHWRec(pScrn))
568      return FALSE;
569   hwp = VGAHWPTR(pScrn);
570   pI810->ioBase = hwp->PIOOffset;
571
572   pI810->PciInfo = xf86GetPciInfoForEntity(pI810->pEnt->index);
573
574   /* Set pScrn->monitor */
575   pScrn->monitor = pScrn->confScreen->monitor;
576
577   flags24 = Support24bppFb | PreferConvert32to24 | SupportConvert32to24;
578   if (!xf86SetDepthBpp(pScrn, 16, 0, 16, flags24)) {
579      return FALSE;
580   } else {
581      switch (pScrn->depth) {
582      case 8:
583      case 15:
584      case 16:
585      case 24:
586	 break;
587      default:
588	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
589		    "Given depth (%d) is not supported by i810 driver\n",
590		    pScrn->depth);
591	 return FALSE;
592      }
593   }
594   xf86PrintDepthBpp(pScrn);
595
596   switch (pScrn->bitsPerPixel) {
597   case 8:
598   case 16:
599   case 24:
600      break;
601   default:
602      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
603		 "Given bpp (%d) is not supported by i810 driver\n",
604		 pScrn->bitsPerPixel);
605      return FALSE;
606   }
607
608   if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight))
609      return FALSE;
610
611   if (!xf86SetDefaultVisual(pScrn, -1))
612      return FALSE;
613
614   /* We use a programmable clock */
615   pScrn->progClock = TRUE;
616
617   pI810->cpp = pScrn->bitsPerPixel / 8;
618
619   /* Process the options */
620   xf86CollectOptions(pScrn, NULL);
621   if (!(pI810->Options = xalloc(sizeof(I810Options))))
622      return FALSE;
623   memcpy(pI810->Options, I810Options, sizeof(I810Options));
624   xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI810->Options);
625
626   pScrn->rgbBits = 8;
627   if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))
628      pScrn->rgbBits = 6;
629
630   if (xf86ReturnOptValBool(pI810->Options, OPTION_SHOW_CACHE, FALSE))
631     pI810->showCache = TRUE;
632   else
633     pI810->showCache = FALSE;
634
635   /* 6-BIT dac isn't reasonable for modes with > 8bpp */
636   if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE) &&
637       pScrn->bitsPerPixel > 8) {
638      OptionInfoPtr ptr;
639
640      ptr = xf86TokenToOptinfo(pI810->Options, OPTION_DAC_6BIT);
641      ptr->found = FALSE;
642   }
643
644   if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE))
645      pI810->noAccel = TRUE;
646
647   if (!pI810->noAccel) {
648      if (!xf86LoadSubModule(pScrn, "xaa")) {
649	 I810FreeRec(pScrn);
650	 return FALSE;
651      }
652   }
653
654#ifdef XF86DRI
655   pI810->directRenderingDisabled =
656     !xf86ReturnOptValBool(pI810->Options, OPTION_DRI, TRUE);
657
658   if (!pI810->directRenderingDisabled) {
659     if (pI810->noAccel) {
660       xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI is disabled because it "
661		  "needs 2D acceleration.\n");
662       pI810->directRenderingDisabled=TRUE;
663     } else if (pScrn->depth!=16) {
664       xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI is disabled because it "
665		  "runs only at 16-bit depth.\n");
666       pI810->directRenderingDisabled=TRUE;
667     }
668   }
669#endif
670
671   /* Get DDC info from monitor */
672   /* after xf86ProcessOptions,
673    * because it is controlled by options [no]vbe and [no]ddc
674    */
675   I810DoDDC(pScrn, pI810->pEnt->index);
676
677   /* We have to use PIO to probe, because we haven't mapped yet */
678   I810SetPIOAccess(pI810);
679
680   /*
681    * Set the Chipset and ChipRev, allowing config file entries to
682    * override.
683    */
684   if (pI810->pEnt->device->chipset && *pI810->pEnt->device->chipset) {
685      pScrn->chipset = pI810->pEnt->device->chipset;
686      from = X_CONFIG;
687   } else if (pI810->pEnt->device->chipID >= 0) {
688      pScrn->chipset = (char *)xf86TokenToString(I810Chipsets,
689						 pI810->pEnt->device->chipID);
690      from = X_CONFIG;
691      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
692		 pI810->pEnt->device->chipID);
693   } else {
694      from = X_PROBED;
695      pScrn->chipset = (char *)xf86TokenToString(I810Chipsets,
696						 DEVICE_ID(pI810->PciInfo));
697   }
698   if (pI810->pEnt->device->chipRev >= 0) {
699      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
700		 pI810->pEnt->device->chipRev);
701   }
702
703   xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n",
704	      (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i810");
705
706   pI810->LinearAddr = pI810->PciInfo->regions[0].base_addr;
707   xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
708	      (unsigned long)pI810->LinearAddr);
709
710   pI810->MMIOAddr = pI810->PciInfo->regions[1].base_addr;
711   xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n",
712	      (unsigned long)pI810->MMIOAddr);
713
714   /* AGP GART support is required.  Don't proceed any further if it isn't
715    * present.
716    */
717   if (!xf86AgpGARTSupported()) {
718      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
719		 "AGP GART support is not available.  Make sure your kernel has\n"
720		 "\tagpgart support or that the agpgart kernel module is loaded.\n");
721      return FALSE;
722   }
723
724   /* Find out memory bus frequency.
725    */
726   {
727      uint32_t whtcfg_pamr_drp;
728
729      pci_device_cfg_read_u32(pI810->PciInfo, & whtcfg_pamr_drp, WHTCFG_PAMR_DRP);
730
731      /* Need this for choosing watermarks.
732       */
733      if ((whtcfg_pamr_drp & LM_FREQ_MASK) == LM_FREQ_133)
734	 pI810->LmFreqSel = 133;
735      else
736	 pI810->LmFreqSel = 100;
737   }
738
739   /* Default to 4MB framebuffer, which is sufficient for all
740    * supported 2d resolutions.  If the user has specified a different
741    * size in the XF86Config, use that amount instead.
742    *
743    *  Changed to 8 Meg so we can have acceleration by default (Mark).
744    */
745   mem = I810CheckAvailableMemory(pScrn);
746   if (pI810->directRenderingDisabled || mem < 131072)  /* < 128 MB */
747       pScrn->videoRam = 8192;
748   else if (mem < 196608)
749       pScrn->videoRam = 16384;  /* < 192 MB */
750   else
751       pScrn->videoRam = 24576;
752
753   from = X_DEFAULT;
754
755   if (pI810->pEnt->device->videoRam) {
756      pScrn->videoRam = pI810->pEnt->device->videoRam;
757      from = X_CONFIG;
758   }
759
760   if (mem > 0 && mem < pScrn->videoRam) {
761      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%dk of memory was requested,"
762		 " but the\n\t maximum AGP memory available is %dk.\n",
763		 pScrn->videoRam, mem);
764      from = X_PROBED;
765      if (mem > (6 * 1024)) {
766	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
767		    "Reducing video memory to 4MB\n");
768	 pScrn->videoRam = 4096;
769      } else {
770	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Less than 6MB of AGP memory"
771		    " is available. Cannot proceed.\n");
772	 I810FreeRec(pScrn);
773	 return FALSE;
774      }
775   }
776
777   xf86DrvMsg(pScrn->scrnIndex, from,
778	      "Will alloc AGP framebuffer: %d kByte\n", pScrn->videoRam);
779
780   /* Calculate Fixed Offsets depending on graphics aperture size */
781   {
782      struct pci_device *bridge = intel_host_bridge ();
783      uint32_t   smram_miscc;
784
785      pci_device_cfg_read_u32 (bridge, & smram_miscc, SMRAM_MISCC);
786
787      if ((smram_miscc & GFX_MEM_WIN_SIZE) == GFX_MEM_WIN_32M) {
788	 pI810->FbMapSize = 0x1000000;
789	 pI810->DepthOffset = 0x1000000;
790	 pI810->BackOffset = 0x1800000;
791      } else {
792	 pI810->FbMapSize = 0x3000000;
793	 pI810->DepthOffset = 0x3000000;
794	 pI810->BackOffset = 0x3800000;
795      }
796   }
797
798   /*
799    * If the driver can do gamma correction, it should call xf86SetGamma()
800    * here.
801    */
802   {
803      Gamma zeros = { 0.0, 0.0, 0.0 };
804
805      if (!xf86SetGamma(pScrn, zeros)) {
806	 return FALSE;
807      }
808   }
809
810   pI810->MaxClock = 0;
811   if (pI810->pEnt->device->dacSpeeds[0]) {
812      switch (pScrn->bitsPerPixel) {
813      case 8:
814	 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP8];
815	 break;
816      case 16:
817	 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP16];
818	 break;
819      case 24:
820	 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP24];
821	 break;
822      case 32:				/* not supported */
823	 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP32];
824	 break;
825      }
826      if (!pI810->MaxClock)
827	 pI810->MaxClock = pI810->pEnt->device->dacSpeeds[0];
828      from = X_CONFIG;
829   } else {
830      switch (pScrn->bitsPerPixel) {
831      case 8:
832	 pI810->MaxClock = 203000;
833	 break;
834      case 16:
835	 pI810->MaxClock = 163000;
836	 break;
837      case 24:
838	 pI810->MaxClock = 136000;
839	 break;
840      case 32:				/* not supported */
841	 pI810->MaxClock = 86000;
842      }
843   }
844   clockRanges = xnfcalloc(sizeof(ClockRange), 1);
845   clockRanges->next = NULL;
846   /* 9.4MHz appears to be the smallest that works. */
847   clockRanges->minClock = 9500;
848   clockRanges->maxClock = pI810->MaxClock;
849   clockRanges->clockIndex = -1;
850   clockRanges->interlaceAllowed = TRUE;
851   clockRanges->doubleScanAllowed = FALSE;
852
853   i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
854			 pScrn->display->modes, clockRanges,
855#ifndef XF86DRI
856			 0, 320, 1600, 64 * pScrn->bitsPerPixel,
857#else
858			 i810_pitches, 0, 0, 64 * pScrn->bitsPerPixel,
859#endif
860			 200, 1200,
861			 pScrn->display->virtualX, pScrn->display->virtualY,
862			 pScrn->videoRam * 1024, LOOKUP_BEST_REFRESH);
863
864   if (i == -1) {
865      I810FreeRec(pScrn);
866      return FALSE;
867   }
868
869   xf86PruneDriverModes(pScrn);
870
871   if (!i || !pScrn->modes) {
872      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
873      I810FreeRec(pScrn);
874      return FALSE;
875   }
876
877   xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
878
879   pScrn->currentMode = pScrn->modes;
880
881   xf86PrintModes(pScrn);
882
883   xf86SetDpi(pScrn, 0, 0);
884
885   if (!xf86LoadSubModule(pScrn, "fb")) {
886      I810FreeRec(pScrn);
887      return FALSE;
888   }
889
890   if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
891      if (!xf86LoadSubModule(pScrn, "ramdac")) {
892	 I810FreeRec(pScrn);
893	 return FALSE;
894      }
895   }
896
897   if (xf86GetOptValInteger
898       (pI810->Options, OPTION_COLOR_KEY, &(pI810->colorKey))) {
899      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
900		 "video overlay key set to 0x%x\n", pI810->colorKey);
901   } else {
902      pI810->colorKey = (1 << pScrn->offset.red) |
903	    (1 << pScrn->offset.green) |
904	    (((pScrn->mask.blue >> pScrn->offset.blue) -
905	      1) << pScrn->offset.blue);
906   }
907
908   pI810->allowPageFlip=FALSE;
909   enable = xf86ReturnOptValBool(pI810->Options, OPTION_PAGEFLIP, FALSE);
910
911#ifdef XF86DRI
912   if (!pI810->directRenderingDisabled) {
913     pI810->allowPageFlip = enable;
914     if (pI810->allowPageFlip == TRUE)
915     {
916       if (!xf86LoadSubModule(pScrn, "shadowfb")) {
917	 pI810->allowPageFlip = 0;
918	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
919		    "Couldn't load shadowfb module:\n");
920       }
921     }
922
923     xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "page flipping %s\n",
924		enable ? "enabled" : "disabled");
925
926   }
927#endif
928
929   if (xf86GetOptValInteger(pI810->Options, OPTION_XVMC_SURFACES,
930			    &(pI810->numSurfaces))) {
931      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "%d XvMC Surfaces Requested.\n",
932		 pI810->numSurfaces);
933      if (pI810->numSurfaces > 7) {
934	 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
935		    "Using 7 XvMC Surfaces (Maximum Allowed).\n");
936	 pI810->numSurfaces = 7;
937      }
938      if (pI810->numSurfaces < 6) {
939	 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
940		    "Using 6 XvMC Surfaces (Minimum Allowed).\n");
941	 pI810->numSurfaces = 6;
942      }
943   } else {
944      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
945		 "XvMC is Disabled: use XvMCSurfaces config option to enable.\n");
946      pI810->numSurfaces = 0;
947   }
948
949#ifdef XF86DRI
950   /* Load the dri module if requested. */
951   if (xf86ReturnOptValBool(pI810->Options, OPTION_DRI, FALSE)) {
952      xf86LoadSubModule(pScrn, "dri");
953   }
954#endif
955
956   /*  We won't be using the VGA access after the probe */
957   I810SetMMIOAccess(pI810);
958   return TRUE;
959}
960
961static Bool
962I810MapMMIO(ScrnInfoPtr pScrn)
963{
964   int mmioFlags;
965   I810Ptr pI810 = I810PTR(pScrn);
966   struct pci_device *const device = pI810->PciInfo;
967   int err;
968
969#if !defined(__alpha__)
970   mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT;
971#else
972   mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT | VIDMEM_SPARSE;
973#endif
974
975   err = pci_device_map_range (device,
976			       pI810->MMIOAddr,
977			       I810_REG_SIZE,
978			       PCI_DEV_MAP_FLAG_WRITABLE,
979			       (void **) &pI810->MMIOBase);
980   if (err)
981   {
982      xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
983		  "Unable to map mmio BAR. %s (%d)\n",
984		  strerror (err), err);
985      return FALSE;
986   }
987   return TRUE;
988}
989
990static Bool
991I810MapMem(ScrnInfoPtr pScrn)
992{
993   I810Ptr pI810 = I810PTR(pScrn);
994   struct pci_device *const device = pI810->PciInfo;
995   int err;
996
997   if (!I810MapMMIO(pScrn))
998      return FALSE;
999
1000   err = pci_device_map_range (device,
1001			       pI810->LinearAddr,
1002			       pI810->FbMapSize,
1003			       PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE,
1004			       (void **) &pI810->FbBase);
1005   if (err)
1006   {
1007      xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
1008		  "Unable to map frame buffer BAR. %s (%d)\n",
1009		  strerror (err), err);
1010      return FALSE;
1011   }
1012
1013   pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start;
1014
1015   return TRUE;
1016}
1017
1018static void
1019I810UnmapMMIO(ScrnInfoPtr pScrn)
1020{
1021   I810Ptr pI810 = I810PTR(pScrn);
1022
1023   pci_device_unmap_range (pI810->PciInfo, pI810->MMIOBase, I810_REG_SIZE);
1024   pI810->MMIOBase = NULL;
1025}
1026
1027static Bool
1028I810UnmapMem(ScrnInfoPtr pScrn)
1029{
1030   I810Ptr pI810 = I810PTR(pScrn);
1031
1032   pci_device_unmap_range (pI810->PciInfo, pI810->FbBase, pI810->FbMapSize);
1033   pI810->FbBase = NULL;
1034   I810UnmapMMIO(pScrn);
1035   return TRUE;
1036}
1037
1038/* Famous last words
1039 */
1040void
1041I810PrintErrorState(ScrnInfoPtr pScrn)
1042{
1043   I810Ptr pI810 = I810PTR(pScrn);
1044
1045   ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n",
1046	  (unsigned long) INREG(PGETBL_CTL), (unsigned long) INREG(PGE_ERR));
1047
1048   ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long) INREG(IPEIR),
1049	  (unsigned long) INREG(IPEHR));
1050
1051   ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n",
1052	  (unsigned long) INREG(LP_RING + RING_TAIL),
1053	  (unsigned long) INREG(LP_RING + RING_HEAD) & HEAD_ADDR,
1054	  (unsigned long) INREG(LP_RING + RING_LEN),
1055	  (unsigned long) INREG(LP_RING + RING_START));
1056
1057   ErrorF("eir: %x esr: %x emr: %x\n",
1058	  INREG16(EIR), INREG16(ESR), INREG16(EMR));
1059
1060   ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM));
1061
1062   ErrorF("memmode: %lx instps: %lx\n", (unsigned long) INREG(MEMMODE),
1063	  (unsigned long) INREG(INST_PS));
1064
1065   ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n",
1066	  INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR));
1067}
1068
1069/*
1070 * I810Save --
1071 *
1072 * This function saves the video state.  It reads all of the SVGA registers
1073 * into the vgaI810Rec data structure.  There is in general no need to
1074 * mask out bits here - just read the registers.
1075 */
1076static void
1077DoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
1078       Bool saveFonts)
1079{
1080   I810Ptr pI810;
1081   vgaHWPtr hwp;
1082   int i;
1083
1084   pI810 = I810PTR(pScrn);
1085   hwp = VGAHWPTR(pScrn);
1086
1087   /*
1088    * This function will handle creating the data structure and filling
1089    * in the generic VGA portion.
1090    */
1091   if (saveFonts)
1092      vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_FONTS | VGA_SR_CMAP);
1093   else
1094      vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
1095
1096   /*
1097    * The port I/O code necessary to read in the extended registers
1098    * into the fields of the vgaI810Rec structure goes here.
1099    */
1100   i810Reg->IOControl = hwp->readCrtc(hwp, IO_CTNL);
1101   i810Reg->AddressMapping = pI810->readControl(pI810, GRX, ADDRESS_MAPPING);
1102   i810Reg->BitBLTControl = INREG8(BITBLT_CNTL);
1103   i810Reg->VideoClk2_M = INREG16(VCLK2_VCO_M);
1104   i810Reg->VideoClk2_N = INREG16(VCLK2_VCO_N);
1105   i810Reg->VideoClk2_DivisorSel = INREG8(VCLK2_VCO_DIV_SEL);
1106
1107   i810Reg->ExtVertTotal = hwp->readCrtc(hwp, EXT_VERT_TOTAL);
1108   i810Reg->ExtVertDispEnd = hwp->readCrtc(hwp, EXT_VERT_DISPLAY);
1109   i810Reg->ExtVertSyncStart = hwp->readCrtc(hwp, EXT_VERT_SYNC_START);
1110   i810Reg->ExtVertBlankStart = hwp->readCrtc(hwp, EXT_VERT_BLANK_START);
1111   i810Reg->ExtHorizTotal = hwp->readCrtc(hwp, EXT_HORIZ_TOTAL);
1112   i810Reg->ExtHorizBlank = hwp->readCrtc(hwp, EXT_HORIZ_BLANK);
1113   i810Reg->ExtOffset = hwp->readCrtc(hwp, EXT_OFFSET);
1114   i810Reg->InterlaceControl = hwp->readCrtc(hwp, INTERLACE_CNTL);
1115
1116   i810Reg->PixelPipeCfg0 = INREG8(PIXPIPE_CONFIG_0);
1117   i810Reg->PixelPipeCfg1 = INREG8(PIXPIPE_CONFIG_1);
1118   i810Reg->PixelPipeCfg2 = INREG8(PIXPIPE_CONFIG_2);
1119   i810Reg->DisplayControl = INREG8(DISPLAY_CNTL);
1120   i810Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC);
1121
1122   for (i = 0; i < 8; i++)
1123      i810Reg->Fence[i] = INREG(FENCE + i * 4);
1124
1125   i810Reg->LprbTail = INREG(LP_RING + RING_TAIL);
1126   i810Reg->LprbHead = INREG(LP_RING + RING_HEAD);
1127   i810Reg->LprbStart = INREG(LP_RING + RING_START);
1128   i810Reg->LprbLen = INREG(LP_RING + RING_LEN);
1129
1130   if ((i810Reg->LprbTail & TAIL_ADDR) != (i810Reg->LprbHead & HEAD_ADDR) &&
1131       i810Reg->LprbLen & RING_VALID) {
1132      I810PrintErrorState(pScrn);
1133      FatalError("Active ring not flushed\n");
1134   }
1135}
1136
1137static void
1138I810Save(ScrnInfoPtr pScrn)
1139{
1140   vgaHWPtr hwp;
1141   I810Ptr pI810;
1142   uint32_t temp;
1143
1144   hwp = VGAHWPTR(pScrn);
1145   pI810 = I810PTR(pScrn);
1146   DoSave(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);
1147
1148   temp = INREG(MEMMODE);
1149   temp |= 4;
1150   OUTREG(MEMMODE, temp);
1151}
1152
1153static void
1154i810PrintMode(vgaRegPtr vgaReg, I810RegPtr mode)
1155{
1156   int i;
1157
1158   ErrorF("   MiscOut: %x\n", vgaReg->MiscOutReg);
1159
1160   ErrorF("SEQ: ");
1161   for (i = 0; i < vgaReg->numSequencer; i++) {
1162      if ((i & 7) == 0)
1163	 ErrorF("\n");
1164      ErrorF("   %d: %x", i, vgaReg->Sequencer[i]);
1165   }
1166   ErrorF("\n");
1167
1168   ErrorF("CRTC: ");
1169   for (i = 0; i < vgaReg->numCRTC; i++) {
1170      if ((i & 3) == 0)
1171	 ErrorF("\n");
1172      ErrorF("   %d: %x", i, vgaReg->CRTC[i]);
1173   }
1174   ErrorF("\n");
1175
1176   ErrorF("GFX: ");
1177   for (i = 0; i < vgaReg->numGraphics; i++) {
1178      if ((i & 7) == 0)
1179	 ErrorF("\n");
1180      ErrorF("   %d: %x", i, vgaReg->Graphics[i]);
1181   }
1182   ErrorF("\n");
1183
1184   ErrorF("ATTR: ");
1185   for (i = 0; i < vgaReg->numAttribute; i++) {
1186      if ((i & 7) == 0)
1187	 ErrorF("\n");
1188      ErrorF("   %d: %x", i, vgaReg->Attribute[i]);
1189   }
1190   ErrorF("\n");
1191
1192   ErrorF("   DisplayControl: %x\n", mode->DisplayControl);
1193   ErrorF("   PixelPipeCfg0: %x\n", mode->PixelPipeCfg0);
1194   ErrorF("   PixelPipeCfg1: %x\n", mode->PixelPipeCfg1);
1195   ErrorF("   PixelPipeCfg2: %x\n", mode->PixelPipeCfg2);
1196   ErrorF("   VideoClk2_M: %x\n", mode->VideoClk2_M);
1197   ErrorF("   VideoClk2_N: %x\n", mode->VideoClk2_N);
1198   ErrorF("   VideoClk2_DivisorSel: %x\n", mode->VideoClk2_DivisorSel);
1199   ErrorF("   AddressMapping: %x\n", mode->AddressMapping);
1200   ErrorF("   IOControl: %x\n", mode->IOControl);
1201   ErrorF("   BitBLTControl: %x\n", mode->BitBLTControl);
1202   ErrorF("   ExtVertTotal: %x\n", mode->ExtVertTotal);
1203   ErrorF("   ExtVertDispEnd: %x\n", mode->ExtVertDispEnd);
1204   ErrorF("   ExtVertSyncStart: %x\n", mode->ExtVertSyncStart);
1205   ErrorF("   ExtVertBlankStart: %x\n", mode->ExtVertBlankStart);
1206   ErrorF("   ExtHorizTotal: %x\n", mode->ExtHorizTotal);
1207   ErrorF("   ExtHorizBlank: %x\n", mode->ExtHorizBlank);
1208   ErrorF("   ExtOffset: %x\n", mode->ExtOffset);
1209   ErrorF("   InterlaceControl: %x\n", mode->InterlaceControl);
1210   ErrorF("   LMI_FIFO_Watermark: %x\n", mode->LMI_FIFO_Watermark);
1211   ErrorF("   LprbTail: %x\n", mode->LprbTail);
1212   ErrorF("   LprbHead: %x\n", mode->LprbHead);
1213   ErrorF("   LprbStart: %x\n", mode->LprbStart);
1214   ErrorF("   LprbLen: %x\n", mode->LprbLen);
1215}
1216
1217static void
1218DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg,
1219	  Bool restoreFonts)
1220{
1221   I810Ptr pI810;
1222   vgaHWPtr hwp;
1223   unsigned char temp;
1224   unsigned int itemp;
1225   int i;
1226
1227   pI810 = I810PTR(pScrn);
1228   hwp = VGAHWPTR(pScrn);
1229
1230   if (I810_DEBUG & DEBUG_VERBOSE_VGA) {
1231      ErrorF("Setting mode in I810Restore:\n");
1232      i810PrintMode(vgaReg, i810Reg);
1233   }
1234
1235   vgaHWProtect(pScrn, TRUE);
1236
1237   usleep(50000);
1238
1239   /* Turn off DRAM Refresh */
1240   temp = INREG8(DRAM_ROW_CNTL_HI);
1241   temp &= ~DRAM_REFRESH_RATE;
1242   temp |= DRAM_REFRESH_DISABLE;
1243   OUTREG8(DRAM_ROW_CNTL_HI, temp);
1244
1245   usleep(1000);			/* Wait 1 ms */
1246
1247   /* Write the M, N and P values */
1248   OUTREG16(VCLK2_VCO_M, i810Reg->VideoClk2_M);
1249   OUTREG16(VCLK2_VCO_N, i810Reg->VideoClk2_N);
1250   OUTREG8(VCLK2_VCO_DIV_SEL, i810Reg->VideoClk2_DivisorSel);
1251
1252   /*
1253    * Turn on 8 bit dac mode, if requested.  This is needed to make
1254    * sure that vgaHWRestore writes the values into the DAC properly.
1255    * The problem occurs if 8 bit dac mode is requested and the HW is
1256    * in 6 bit dac mode.  If this happens, all the values are
1257    * automatically shifted left twice by the HW and incorrect colors
1258    * will be displayed on the screen.  The only time this can happen
1259    * is at server startup time and when switching back from a VT.
1260    */
1261   temp = INREG8(PIXPIPE_CONFIG_0);
1262   temp &= 0x7F;			/* Save all but the 8 bit dac mode bit */
1263   temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT);
1264   OUTREG8(PIXPIPE_CONFIG_0, temp);
1265
1266   /*
1267    * Code to restore any SVGA registers that have been saved/modified
1268    * goes here.  Note that it is allowable, and often correct, to
1269    * only modify certain bits in a register by a read/modify/write cycle.
1270    *
1271    * A special case - when using an external clock-setting program,
1272    * this function must not change bits associated with the clock
1273    * selection.  This condition can be checked by the condition:
1274    *
1275    *   if (i810Reg->std.NoClock >= 0)
1276    *           restore clock-select bits.
1277    */
1278   if (restoreFonts)
1279      vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);
1280   else
1281      vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
1282
1283   hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i810Reg->ExtVertTotal);
1284   hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd);
1285   hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart);
1286   hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart);
1287   hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal);
1288   hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank);
1289   hwp->writeCrtc(hwp, EXT_OFFSET, i810Reg->ExtOffset);
1290
1291   temp = hwp->readCrtc(hwp, INTERLACE_CNTL);
1292   temp &= ~INTERLACE_ENABLE;
1293   temp |= i810Reg->InterlaceControl;
1294   hwp->writeCrtc(hwp, INTERLACE_CNTL, temp);
1295
1296   temp = pI810->readControl(pI810, GRX, ADDRESS_MAPPING);
1297   temp &= 0xE0;			/* Save reserved bits 7:5 */
1298   temp |= i810Reg->AddressMapping;
1299   pI810->writeControl(pI810, GRX, ADDRESS_MAPPING, temp);
1300
1301   /* Setting the OVRACT Register for video overlay */
1302   {
1303       uint32_t LCD_TV_Control = INREG(LCD_TV_C);
1304       uint32_t TV_HTotal = INREG(LCD_TV_HTOTAL);
1305       uint32_t ActiveStart, ActiveEnd;
1306
1307       if((LCD_TV_Control & LCD_TV_ENABLE)
1308	  && !(LCD_TV_Control & LCD_TV_VGAMOD)
1309	   && TV_HTotal) {
1310	   ActiveStart = ((TV_HTotal >> 16) & 0xfff) - 31;
1311	   ActiveEnd = (TV_HTotal & 0x3ff) - 31;
1312       } else {
1313	   ActiveStart = i810Reg->OverlayActiveStart;
1314	   ActiveEnd = i810Reg->OverlayActiveEnd;
1315       }
1316       OUTREG(LCD_TV_OVRACT,
1317	      (ActiveEnd << 16) | ActiveStart);
1318   }
1319
1320   /* Turn on DRAM Refresh */
1321   temp = INREG8(DRAM_ROW_CNTL_HI);
1322   temp &= ~DRAM_REFRESH_RATE;
1323   temp |= DRAM_REFRESH_60HZ;
1324   OUTREG8(DRAM_ROW_CNTL_HI, temp);
1325
1326   temp = INREG8(BITBLT_CNTL);
1327   temp &= ~COLEXP_MODE;
1328   temp |= i810Reg->BitBLTControl;
1329   OUTREG8(BITBLT_CNTL, temp);
1330
1331   temp = INREG8(DISPLAY_CNTL);
1332   temp &= ~(VGA_WRAP_MODE | GUI_MODE);
1333   temp |= i810Reg->DisplayControl;
1334   OUTREG8(DISPLAY_CNTL, temp);
1335
1336   temp = INREG8(PIXPIPE_CONFIG_0);
1337   temp &= 0x64;			/* Save reserved bits 6:5,2 */
1338   temp |= i810Reg->PixelPipeCfg0;
1339   OUTREG8(PIXPIPE_CONFIG_0, temp);
1340
1341   temp = INREG8(PIXPIPE_CONFIG_2);
1342   temp &= 0xF3;			/* Save reserved bits 7:4,1:0 */
1343   temp |= i810Reg->PixelPipeCfg2;
1344   OUTREG8(PIXPIPE_CONFIG_2, temp);
1345
1346   temp = INREG8(PIXPIPE_CONFIG_1);
1347   temp &= ~DISPLAY_COLOR_MODE;
1348   temp &= 0xEF;			/* Restore the CRT control bit */
1349   temp |= i810Reg->PixelPipeCfg1;
1350   OUTREG8(PIXPIPE_CONFIG_1, temp);
1351
1352   OUTREG16(EIR, 0);
1353
1354   itemp = INREG(FWATER_BLC);
1355   itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK |
1356	      MM_BURST_LENGTH | MM_FIFO_WATERMARK);
1357   itemp |= i810Reg->LMI_FIFO_Watermark;
1358   OUTREG(FWATER_BLC, itemp);
1359
1360   for (i = 0; i < 8; i++) {
1361      OUTREG(FENCE + i * 4, i810Reg->Fence[i]);
1362      if (I810_DEBUG & DEBUG_VERBOSE_VGA)
1363	 ErrorF("Fence Register : %x\n", i810Reg->Fence[i]);
1364   }
1365
1366   /* First disable the ring buffer (Need to wait for empty first?, if so
1367    * should probably do it before entering this section)
1368    */
1369   itemp = INREG(LP_RING + RING_LEN);
1370   itemp &= ~RING_VALID_MASK;
1371   OUTREG(LP_RING + RING_LEN, itemp);
1372
1373   /* Set up the low priority ring buffer.
1374    */
1375   OUTREG(LP_RING + RING_TAIL, 0);
1376   OUTREG(LP_RING + RING_HEAD, 0);
1377
1378   pI810->LpRing->head = 0;
1379   pI810->LpRing->tail = 0;
1380
1381   itemp = INREG(LP_RING + RING_START);
1382   itemp &= ~(START_ADDR);
1383   itemp |= i810Reg->LprbStart;
1384   OUTREG(LP_RING + RING_START, itemp);
1385
1386   itemp = INREG(LP_RING + RING_LEN);
1387   itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
1388   itemp |= i810Reg->LprbLen;
1389   OUTREG(LP_RING + RING_LEN, itemp);
1390
1391   if (!(vgaReg->Attribute[0x10] & 0x1)) {
1392      usleep(50000);
1393      if (restoreFonts)
1394	 vgaHWRestore(pScrn, vgaReg,
1395		      VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP);
1396      else
1397	 vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP);
1398   }
1399
1400   vgaHWProtect(pScrn, FALSE);
1401
1402   temp = hwp->readCrtc(hwp, IO_CTNL);
1403   temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL);
1404   temp |= i810Reg->IOControl;
1405   hwp->writeCrtc(hwp, IO_CTNL, temp);
1406}
1407
1408static void
1409I810SetRingRegs(ScrnInfoPtr pScrn)
1410{
1411   unsigned int itemp;
1412   I810Ptr pI810 = I810PTR(pScrn);
1413
1414   OUTREG(LP_RING + RING_TAIL, 0);
1415   OUTREG(LP_RING + RING_HEAD, 0);
1416
1417   itemp = INREG(LP_RING + RING_START);
1418   itemp &= ~(START_ADDR);
1419   itemp |= pI810->LpRing->mem.Start;
1420   OUTREG(LP_RING + RING_START, itemp);
1421
1422   itemp = INREG(LP_RING + RING_LEN);
1423   itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK);
1424   itemp |= ((pI810->LpRing->mem.Size - 4096) | RING_NO_REPORT | RING_VALID);
1425   OUTREG(LP_RING + RING_LEN, itemp);
1426}
1427
1428static void
1429I810Restore(ScrnInfoPtr pScrn)
1430{
1431   vgaHWPtr hwp;
1432   I810Ptr pI810;
1433
1434   hwp = VGAHWPTR(pScrn);
1435   pI810 = I810PTR(pScrn);
1436
1437   DoRestore(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE);
1438}
1439
1440/*
1441 * I810CalcVCLK --
1442 *
1443 * Determine the closest clock frequency to the one requested.
1444 */
1445
1446#define MAX_VCO_FREQ 600.0
1447#define TARGET_MAX_N 30
1448#define REF_FREQ 24.0
1449
1450#define CALC_VCLK(m,n,p) \
1451    (double)m / ((double)n * (1 << p)) * 4 * REF_FREQ
1452
1453static void
1454I810CalcVCLK(ScrnInfoPtr pScrn, double freq)
1455{
1456   I810Ptr pI810 = I810PTR(pScrn);
1457   I810RegPtr i810Reg = &pI810->ModeReg;
1458   int m, n, p;
1459   double f_out, f_best;
1460   double f_err;
1461   double f_vco;
1462   int m_best = 0, n_best = 0, p_best = 0;
1463   double f_target = freq;
1464   double err_max = 0.005;
1465   double err_target = 0.001;
1466   double err_best = 999999.0;
1467
1468   p_best = p = log(MAX_VCO_FREQ / f_target) / log((double)2);
1469   /* Make sure p is within range. */
1470   if (p_best > 5) {
1471      p_best = p = 5;
1472   }
1473
1474   f_vco = f_target * (1 << p);
1475
1476   n = 2;
1477   do {
1478      n++;
1479      m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5;
1480      if (m < 3)
1481	 m = 3;
1482      f_out = CALC_VCLK(m, n, p);
1483      f_err = 1.0 - (f_target / f_out);
1484      if (fabs(f_err) < err_max) {
1485	 m_best = m;
1486	 n_best = n;
1487	 f_best = f_out;
1488	 err_best = f_err;
1489      }
1490   } while ((fabs(f_err) >= err_target) &&
1491	    ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max)));
1492
1493   if (fabs(f_err) < err_target) {
1494      m_best = m;
1495      n_best = n;
1496   }
1497
1498   i810Reg->VideoClk2_M = (m_best - 2) & 0x3FF;
1499   i810Reg->VideoClk2_N = (n_best - 2) & 0x3FF;
1500   i810Reg->VideoClk2_DivisorSel = (p_best << 4);
1501
1502   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3,
1503		  "Setting dot clock to %.1f MHz " "[ 0x%x 0x%x 0x%x ] "
1504		  "[ %d %d %d ]\n", CALC_VCLK(m_best, n_best, p_best),
1505		  i810Reg->VideoClk2_M, i810Reg->VideoClk2_N,
1506		  i810Reg->VideoClk2_DivisorSel, m_best, n_best, p_best);
1507}
1508
1509static Bool
1510I810SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
1511{
1512   I810Ptr pI810 = I810PTR(pScrn);
1513   I810RegPtr i810Reg = &pI810->ModeReg;
1514   vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;
1515   double dclk = mode->Clock / 1000.0;
1516
1517   switch (pScrn->bitsPerPixel) {
1518   case 8:
1519      pVga->CRTC[0x13] = pScrn->displayWidth >> 3;
1520      i810Reg->ExtOffset = pScrn->displayWidth >> 11;
1521      i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE;
1522      i810Reg->BitBLTControl = COLEXP_8BPP;
1523      break;
1524   case 16:
1525      if (pScrn->weight.green == 5) {
1526	 i810Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE;
1527      } else {
1528	 i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE;
1529      }
1530      pVga->CRTC[0x13] = pScrn->displayWidth >> 2;
1531      i810Reg->ExtOffset = pScrn->displayWidth >> 10;
1532      i810Reg->BitBLTControl = COLEXP_16BPP;
1533
1534      /* Enable Palette Programming for Direct Color visuals. -jens */
1535      i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
1536      break;
1537   case 24:
1538      pVga->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3;
1539      i810Reg->ExtOffset = (pScrn->displayWidth * 3) >> 11;
1540
1541      i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE;
1542      i810Reg->BitBLTControl = COLEXP_24BPP;
1543
1544      /* Enable Palette Programming for Direct Color visuals. -jens */
1545      i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE;
1546      break;
1547   default:
1548      break;
1549   }
1550
1551   /* Turn on 8 bit dac if requested */
1552   if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE))
1553      i810Reg->PixelPipeCfg0 = DAC_6_BIT;
1554   else
1555      i810Reg->PixelPipeCfg0 = DAC_8_BIT;
1556
1557   /* Do not delay CRT Blank: needed for video overlay */
1558   i810Reg->PixelPipeCfg1 |= 0x10;
1559
1560   /* Turn on Extended VGA Interpretation */
1561   i810Reg->IOControl = EXTENDED_CRTC_CNTL;
1562
1563   /* Turn on linear and page mapping */
1564   i810Reg->AddressMapping = (LINEAR_MODE_ENABLE | GTT_MEM_MAP_ENABLE);
1565
1566   /* Turn on GUI mode */
1567   i810Reg->DisplayControl = HIRES_MODE;
1568
1569   /* Calculate the extended CRTC regs */
1570   i810Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8;
1571   i810Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8;
1572   i810Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8;
1573   i810Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8;
1574   i810Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8;
1575   i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6;
1576
1577   /*
1578    * the KGA fix in vgaHW.c results in the first
1579    * scanline and the first character clock (8 pixels)
1580    * of each scanline thereafter on display with an i810
1581    * to be blank. Restoring CRTC 3, 5, & 22 to their
1582    * "theoretical" values corrects the problem. KAO.
1583    */
1584   pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80;
1585   pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2)
1586	 | (((mode->CrtcHSyncEnd >> 3)) & 0x1F);
1587   pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF;
1588
1589   i810Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0);
1590   vgaHWVBlankKGA(mode, pVga, 8, 0);
1591
1592   /*
1593    * The following workarounds are needed to get video overlay working
1594    * at 1024x768 and 1280x1024 display resolutions.
1595    */
1596   if ((mode->CrtcVDisplay == 768) && (i810Reg->ExtVertBlankStart == 3)) {
1597      i810Reg->ExtVertBlankStart = 2;
1598   }
1599   if ((mode->CrtcVDisplay == 1024) && (i810Reg->ExtVertBlankStart == 4)) {
1600      i810Reg->ExtVertBlankStart = 3;
1601   }
1602
1603   /* OVRACT Register */
1604   i810Reg->OverlayActiveStart = mode->CrtcHTotal - 32;
1605   i810Reg->OverlayActiveEnd = mode->CrtcHDisplay - 32;
1606
1607   /* Turn on interlaced mode if necessary */
1608   if (mode->Flags & V_INTERLACE) {
1609      i810Reg->InterlaceControl = INTERLACE_ENABLE;
1610      i810Reg->ExtVertDispEnd *= 2;
1611   } else
1612      i810Reg->InterlaceControl = INTERLACE_DISABLE;
1613
1614   /*
1615    * Set the overscan color to 0.
1616    * NOTE: This only affects >8bpp mode.
1617    */
1618   pVga->Attribute[0x11] = 0;
1619
1620   /*
1621    * Calculate the VCLK that most closely matches the requested dot
1622    * clock.
1623    */
1624   I810CalcVCLK(pScrn, dclk);
1625
1626   /* Since we program the clocks ourselves, always use VCLK2. */
1627   pVga->MiscOutReg |= 0x0C;
1628
1629   /* Calculate the FIFO Watermark and Burst Length. */
1630   i810Reg->LMI_FIFO_Watermark = I810CalcWatermark(pScrn, dclk, FALSE);
1631
1632   /* Setup the ring buffer */
1633   i810Reg->LprbTail = 0;
1634   i810Reg->LprbHead = 0;
1635   i810Reg->LprbStart = pI810->LpRing->mem.Start;
1636
1637   if (i810Reg->LprbStart)
1638      i810Reg->LprbLen = ((pI810->LpRing->mem.Size - 4096) |
1639			  RING_NO_REPORT | RING_VALID);
1640   else
1641      i810Reg->LprbLen = RING_INVALID;
1642
1643   return TRUE;
1644}
1645
1646static Bool
1647I810ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
1648{
1649   vgaHWPtr hwp;
1650   I810Ptr pI810;
1651
1652   hwp = VGAHWPTR(pScrn);
1653   pI810 = I810PTR(pScrn);
1654
1655   vgaHWUnlock(hwp);
1656
1657   if (!vgaHWInit(pScrn, mode))
1658      return FALSE;
1659
1660   pScrn->vtSema = TRUE;
1661
1662   if (!I810SetMode(pScrn, mode))
1663      return FALSE;
1664
1665#ifdef XF86DRI
1666   if (pI810->directRenderingEnabled) {
1667      DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
1668      pI810->LockHeld = 1;
1669   }
1670#endif
1671
1672   DoRestore(pScrn, &hwp->ModeReg, &pI810->ModeReg, FALSE);
1673
1674#ifdef XF86DRI
1675   if (pI810->directRenderingEnabled) {
1676      DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
1677      pI810->LockHeld = 0;
1678   }
1679#endif
1680
1681   return TRUE;
1682}
1683
1684static void
1685I810LoadPalette15(ScrnInfoPtr pScrn, int numColors, int *indices,
1686		  LOCO * colors, VisualPtr pVisual)
1687{
1688   I810Ptr pI810;
1689   vgaHWPtr hwp;
1690   int i, j, index;
1691   unsigned char r, g, b;
1692
1693   pI810 = I810PTR(pScrn);
1694   hwp = VGAHWPTR(pScrn);
1695
1696   for (i = 0; i < numColors; i++) {
1697      index = indices[i];
1698      r = colors[index].red;
1699      g = colors[index].green;
1700      b = colors[index].blue;
1701      for (j = 0; j < 8; j++) {
1702	 hwp->writeDacWriteAddr(hwp, (index << 3) + j);
1703	 hwp->writeDacData(hwp, r);
1704	 hwp->writeDacData(hwp, g);
1705	 hwp->writeDacData(hwp, b);
1706      }
1707   }
1708}
1709
1710static void
1711I810LoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices,
1712		  LOCO * colors, VisualPtr pVisual)
1713{
1714   I810Ptr pI810;
1715   vgaHWPtr hwp;
1716   int i, index;
1717   unsigned char r, g, b;
1718
1719   pI810 = I810PTR(pScrn);
1720   hwp = VGAHWPTR(pScrn);
1721
1722   /* Load all four entries in each of the 64 color ranges.  -jens */
1723   for (i = 0; i < numColors; i++) {
1724      index = indices[i / 2];
1725      r = colors[index].red;
1726      b = colors[index].blue;
1727      index = indices[i];
1728      g = colors[index].green;
1729
1730      hwp->writeDacWriteAddr(hwp, index << 2);
1731      hwp->writeDacData(hwp, r);
1732      hwp->writeDacData(hwp, g);
1733      hwp->writeDacData(hwp, b);
1734
1735      hwp->writeDacWriteAddr(hwp, (index << 2) + 1);
1736      hwp->writeDacData(hwp, r);
1737      hwp->writeDacData(hwp, g);
1738      hwp->writeDacData(hwp, b);
1739
1740      hwp->writeDacWriteAddr(hwp, (index << 2) + 2);
1741      hwp->writeDacData(hwp, r);
1742      hwp->writeDacData(hwp, g);
1743      hwp->writeDacData(hwp, b);
1744
1745      hwp->writeDacWriteAddr(hwp, (index << 2) + 3);
1746      hwp->writeDacData(hwp, r);
1747      hwp->writeDacData(hwp, g);
1748      hwp->writeDacData(hwp, b);
1749
1750      i++;
1751      index = indices[i];
1752      g = colors[index].green;
1753
1754      hwp->writeDacWriteAddr(hwp, index << 2);
1755      hwp->writeDacData(hwp, r);
1756      hwp->writeDacData(hwp, g);
1757      hwp->writeDacData(hwp, b);
1758
1759      hwp->writeDacWriteAddr(hwp, (index << 2) + 1);
1760      hwp->writeDacData(hwp, r);
1761      hwp->writeDacData(hwp, g);
1762      hwp->writeDacData(hwp, b);
1763
1764      hwp->writeDacWriteAddr(hwp, (index << 2) + 2);
1765      hwp->writeDacData(hwp, r);
1766      hwp->writeDacData(hwp, g);
1767      hwp->writeDacData(hwp, b);
1768
1769      hwp->writeDacWriteAddr(hwp, (index << 2) + 3);
1770      hwp->writeDacData(hwp, r);
1771      hwp->writeDacData(hwp, g);
1772      hwp->writeDacData(hwp, b);
1773   }
1774}
1775
1776static void
1777I810LoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices,
1778		  LOCO * colors, VisualPtr pVisual)
1779{
1780   I810Ptr pI810;
1781   vgaHWPtr hwp;
1782   int i, index;
1783   unsigned char r, g, b;
1784
1785   pI810 = I810PTR(pScrn);
1786   hwp = VGAHWPTR(pScrn);
1787
1788   for (i = 0; i < numColors; i++) {
1789      index = indices[i];
1790      r = colors[index].red;
1791      g = colors[index].green;
1792      b = colors[index].blue;
1793      hwp->writeDacWriteAddr(hwp, index);
1794      hwp->writeDacData(hwp, r);
1795      hwp->writeDacData(hwp, g);
1796      hwp->writeDacData(hwp, b);
1797   }
1798}
1799
1800Bool
1801I810AllocateFront(ScrnInfoPtr pScrn)
1802{
1803   I810Ptr pI810 = I810PTR(pScrn);
1804   int cache_lines = -1;
1805
1806   if (pI810->DoneFrontAlloc)
1807      return TRUE;
1808
1809   memset(&(pI810->FbMemBox), 0, sizeof(BoxRec));
1810   /* Alloc FrontBuffer/Ring/Accel memory */
1811   pI810->FbMemBox.x1 = 0;
1812   pI810->FbMemBox.x2 = pScrn->displayWidth;
1813   pI810->FbMemBox.y1 = 0;
1814   pI810->FbMemBox.y2 = pScrn->virtualY;
1815
1816   xf86GetOptValInteger(pI810->Options, OPTION_CACHE_LINES, &cache_lines);
1817
1818   if (cache_lines < 0) {
1819      /* make sure there is enough for two DVD sized YUV buffers */
1820      cache_lines = (pScrn->depth == 24) ? 256 : 384;
1821      if (pScrn->displayWidth <= 1024)
1822	 cache_lines *= 2;
1823   }
1824   /* Make sure there's enough space for cache_lines.
1825    *
1826    * Had a bug here where maxCacheLines was computed to be less than 0.
1827    * Not sure why 256 was initially subtracted from videoRam in the
1828    * maxCacheLines calculation, but that was causing a problem
1829    * for configurations that have exactly enough Ram for the framebuffer.
1830    * Common code should catch the case where there isn't enough space for
1831    * framebuffer, we'll just check for no space for cache_lines.  -jens
1832    *
1833    */
1834   {
1835      int maxCacheLines;
1836
1837      maxCacheLines = (pScrn->videoRam * 1024 /
1838		       (pScrn->bitsPerPixel / 8) /
1839		       pScrn->displayWidth) - pScrn->virtualY;
1840      if (maxCacheLines < 0)
1841	 maxCacheLines = 0;
1842      if (cache_lines > maxCacheLines)
1843	 cache_lines = maxCacheLines;
1844   }
1845   pI810->FbMemBox.y2 += cache_lines;
1846
1847   xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1848	      "Adding %i scanlines for pixmap caching\n", cache_lines);
1849
1850   /* Reserve room for the framebuffer and pixcache.  Put at the top
1851    * of memory so we can have nice alignment for the tiled regions at
1852    * the start of memory.
1853    */
1854
1855   if (!I810AllocLow(&(pI810->FrontBuffer),
1856		     &(pI810->SysMem),
1857		     ((pI810->FbMemBox.x2 *
1858		       pI810->FbMemBox.y2 * pI810->cpp) + 4095) & ~4095)) {
1859      xf86DrvMsg(pScrn->scrnIndex,
1860		 X_WARNING, "Framebuffer allocation failed\n");
1861      return FALSE;
1862   } else
1863      DPRINTF(PFX,
1864	      "Frame buffer at 0x%.8x (%luk, %lu bytes)\n",
1865	      pI810->FrontBuffer.Start,
1866	      pI810->FrontBuffer.Size / 1024, pI810->FrontBuffer.Size);
1867
1868   memset(pI810->LpRing, 0, sizeof(I810RingBuffer));
1869   if (I810AllocLow(&(pI810->LpRing->mem), &(pI810->SysMem), 16 * 4096)) {
1870      DPRINTF(PFX,
1871	      "Ring buffer at 0x%.8x (%luk, %lu bytes)\n",
1872	      pI810->LpRing->mem.Start,
1873	      pI810->LpRing->mem.Size / 1024, pI810->LpRing->mem.Size);
1874
1875      pI810->LpRing->tail_mask = pI810->LpRing->mem.Size - 1;
1876      pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start;
1877      pI810->LpRing->head = 0;
1878      pI810->LpRing->tail = 0;
1879      pI810->LpRing->space = 0;
1880   } else {
1881      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1882		 "Ring buffer allocation failed\n");
1883      return (FALSE);
1884   }
1885
1886   if (I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 64 * 1024) ||
1887       I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 16 * 1024)) {
1888      DPRINTF(PFX,
1889	      "Scratch memory at 0x%.8x (%luk, %lu bytes)\n",
1890	      pI810->Scratch.Start,
1891	      pI810->Scratch.Size / 1024, pI810->Scratch.Size);
1892
1893      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocated Scratch Memory\n");
1894   } else {
1895      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1896		 "Scratch memory allocation failed\n");
1897      return (FALSE);
1898   }
1899
1900   pI810->DoneFrontAlloc = TRUE;
1901   return TRUE;
1902}
1903
1904static Bool
1905I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1906{
1907   ScrnInfoPtr pScrn;
1908   vgaHWPtr hwp;
1909   I810Ptr pI810;
1910   VisualPtr visual;
1911   MessageType driFrom = X_DEFAULT;
1912
1913   pScrn = xf86Screens[pScreen->myNum];
1914   pI810 = I810PTR(pScrn);
1915   hwp = VGAHWPTR(pScrn);
1916
1917   pI810->LpRing = xcalloc(sizeof(I810RingBuffer),1);
1918   if (!pI810->LpRing) {
1919     xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1920		"Could not allocate lpring data structure.\n");
1921     return FALSE;
1922   }
1923
1924   miClearVisualTypes();
1925
1926   /* Re-implemented Direct Color support, -jens */
1927   if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
1928			 pScrn->rgbBits, pScrn->defaultVisual))
1929      return FALSE;
1930
1931   if (!miSetPixmapDepths())
1932      return FALSE;
1933
1934   {
1935      I810RegPtr i810Reg = &pI810->ModeReg;
1936      int i;
1937
1938      for (i = 0; i < 8; i++)
1939	 i810Reg->Fence[i] = 0;
1940   }
1941
1942   /* Have to init the DRM earlier than in other drivers to get agp
1943    * memory.  Wonder if this is going to be a problem...
1944    */
1945
1946#ifdef XF86DRI
1947   /*
1948    * Setup DRI after visuals have been established, but before fbScreenInit
1949    * is called.   fbScreenInit will eventually call into the drivers
1950    * InitGLXVisuals call back.
1951    */
1952   /*
1953    * pI810->directRenderingDisabled is set once in PreInit.  Reinitialise
1954    * pI810->directRenderingEnabled based on it each generation.
1955    */
1956   pI810->directRenderingEnabled = !pI810->directRenderingDisabled;
1957
1958   if (pI810->directRenderingEnabled==TRUE)
1959     pI810->directRenderingEnabled = I810DRIScreenInit(pScreen);
1960   else
1961     driFrom = X_CONFIG;
1962
1963#else
1964   pI810->directRenderingEnabled = FALSE;
1965   if (!I810AllocateGARTMemory(pScrn))
1966      return FALSE;
1967   if (!I810AllocateFront(pScrn))
1968      return FALSE;
1969#endif
1970
1971   if (!I810MapMem(pScrn))
1972      return FALSE;
1973
1974   pScrn->memPhysBase = (unsigned long)pI810->LinearAddr;
1975   pScrn->fbOffset = 0;
1976
1977   vgaHWSetMmioFuncs(hwp, pI810->MMIOBase, 0);
1978   vgaHWGetIOBase(hwp);
1979   if (!vgaHWMapMem(pScrn))
1980      return FALSE;
1981
1982   I810Save(pScrn);
1983   if (!I810ModeInit(pScrn, pScrn->currentMode))
1984      return FALSE;
1985
1986   I810SaveScreen(pScreen, FALSE);
1987   I810AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
1988
1989   if (!fbScreenInit(pScreen, pI810->FbBase + pScrn->fbOffset,
1990		     pScrn->virtualX, pScrn->virtualY,
1991		     pScrn->xDpi, pScrn->yDpi,
1992		     pScrn->displayWidth, pScrn->bitsPerPixel))
1993      return FALSE;
1994
1995   if (pScrn->bitsPerPixel > 8) {
1996      /* Fixup RGB ordering */
1997      visual = pScreen->visuals + pScreen->numVisuals;
1998      while (--visual >= pScreen->visuals) {
1999	 if ((visual->class | DynamicClass) == DirectColor) {
2000	    visual->offsetRed = pScrn->offset.red;
2001	    visual->offsetGreen = pScrn->offset.green;
2002	    visual->offsetBlue = pScrn->offset.blue;
2003	    visual->redMask = pScrn->mask.red;
2004	    visual->greenMask = pScrn->mask.green;
2005	    visual->blueMask = pScrn->mask.blue;
2006	 }
2007      }
2008   }
2009
2010   fbPictureInit(pScreen, NULL, 0);
2011
2012   xf86SetBlackWhitePixels(pScreen);
2013
2014#ifdef XF86DRI
2015   if (pI810->LpRing->mem.Start == 0 && pI810->directRenderingEnabled) {
2016      pI810->directRenderingEnabled = FALSE;
2017      driFrom = X_PROBED;
2018      I810DRICloseScreen(pScreen);
2019   }
2020
2021   if (!pI810->directRenderingEnabled) {
2022      pI810->DoneFrontAlloc = FALSE;
2023      if (!I810AllocateGARTMemory(pScrn))
2024	 return FALSE;
2025      if (!I810AllocateFront(pScrn))
2026	 return FALSE;
2027   }
2028#endif
2029
2030#ifdef XFreeXDGA
2031   I810DGAInit(pScreen);
2032#endif
2033
2034   if (!xf86InitFBManager(pScreen, &(pI810->FbMemBox))) {
2035      xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2036		 "Failed to init memory manager\n");
2037      return FALSE;
2038   }
2039
2040   if (!xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE)) {
2041      if (pI810->LpRing->mem.Size != 0) {
2042	 I810SetRingRegs(pScrn);
2043
2044	 if (!I810AccelInit(pScreen)) {
2045	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2046		       "Hardware acceleration initialization failed\n");
2047	 }  else /* PK added 16.02.2004 */
2048	     I810EmitFlush(pScrn);
2049      }
2050   }
2051
2052   xf86SetBackingStore(pScreen);
2053   xf86SetSilkenMouse(pScreen);
2054
2055   miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
2056
2057   if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) {
2058      if (!I810CursorInit(pScreen)) {
2059	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2060		    "Hardware cursor initialization failed\n");
2061      }
2062   }
2063
2064   if (!miCreateDefColormap(pScreen))
2065      return FALSE;
2066
2067   /* Use driver specific palette load routines for Direct Color support. -jens */
2068   if (pScrn->bitsPerPixel == 16) {
2069      if (pScrn->depth == 15) {
2070	 if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette15, NULL,
2071				  CMAP_PALETTED_TRUECOLOR |
2072				  CMAP_RELOAD_ON_MODE_SWITCH))
2073	    return FALSE;
2074      } else {
2075	 if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette16, NULL,
2076				  CMAP_PALETTED_TRUECOLOR |
2077				  CMAP_RELOAD_ON_MODE_SWITCH))
2078	    return FALSE;
2079      }
2080   } else {
2081      if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette24, NULL,
2082			       CMAP_PALETTED_TRUECOLOR |
2083			       CMAP_RELOAD_ON_MODE_SWITCH))
2084	 return FALSE;
2085   }
2086
2087   xf86DPMSInit(pScreen, I810DisplayPowerManagementSet, 0);
2088
2089   I810InitVideo(pScreen);
2090
2091#ifdef XF86DRI
2092   if (pI810->directRenderingEnabled) {
2093      /* Now that mi, fb, drm and others have done their thing,
2094       * complete the DRI setup.
2095       */
2096      pI810->directRenderingEnabled = I810DRIFinishScreenInit(pScreen);
2097   }
2098#ifdef XvMCExtension
2099   if ((pI810->directRenderingEnabled) && (pI810->numSurfaces)) {
2100      /* Initialize the hardware motion compensation code */
2101      I810InitMC(pScreen);
2102   }
2103#endif
2104#endif
2105
2106   if (pI810->directRenderingEnabled) {
2107      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
2108   } else {
2109      xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
2110   }
2111
2112   pScreen->SaveScreen = I810SaveScreen;
2113   pI810->CloseScreen = pScreen->CloseScreen;
2114   pScreen->CloseScreen = I810CloseScreen;
2115
2116   if (serverGeneration == 1)
2117      xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
2118
2119   return TRUE;
2120}
2121
2122Bool
2123I810SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
2124{
2125   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
2126#if 0
2127   I810Ptr pI810 = I810PTR(pScrn);
2128#endif
2129   if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
2130      ErrorF("I810SwitchMode %p %x\n", (void *)mode, flags);
2131
2132#if 0
2133/*
2134 * This has been added to prevent lockups on mode switch by modeling
2135 * it after I810Leave()/I810Enter() but the call to I810DRILeave()
2136 * was missing so it caused the opposite.
2137 * The version below works but it is doubtful it does any good.
2138 * If lockups on mode switch are still seen revisit this code. (EE)
2139 */
2140
2141# ifdef XF86DRI
2142   if (pI810->directRenderingEnabled) {
2143      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
2144	 ErrorF("calling dri lock\n");
2145      DRILock(screenInfo.screens[scrnIndex], 0);
2146      pI810->LockHeld = 1;
2147   }
2148# endif
2149   if (pI810->AccelInfoRec != NULL) {
2150      I810RefreshRing(pScrn);
2151      I810Sync(pScrn);
2152      pI810->AccelInfoRec->NeedToSync = FALSE;
2153   }
2154   I810Restore(pScrn);
2155
2156# ifdef XF86DRI
2157   if (pI810->directRenderingEnabled) {
2158       if (!I810DRILeave(pScrn))
2159	   return FALSE;
2160       if (!I810DRIEnter(pScrn))
2161	   return FALSE;
2162
2163       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
2164	   ErrorF("calling dri unlock\n");
2165       DRIUnlock(screenInfo.screens[scrnIndex]);
2166       pI810->LockHeld = 0;
2167   }
2168# endif
2169#endif
2170   return I810ModeInit(pScrn, mode);
2171}
2172
2173void
2174I810AdjustFrame(int scrnIndex, int x, int y, int flags)
2175{
2176   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
2177   I810Ptr pI810 = I810PTR(pScrn);
2178   vgaHWPtr hwp = VGAHWPTR(pScrn);
2179   int Base;
2180
2181#if 1
2182   if (pI810->showCache) {
2183     int lastline = pI810->FbMapSize /
2184       ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8);
2185     lastline -= pScrn->currentMode->VDisplay;
2186     if (y > 0)
2187       y += pScrn->currentMode->VDisplay;
2188     if (y > lastline) y = lastline;
2189   }
2190#endif
2191   Base = (y * pScrn->displayWidth + x) >> 2;
2192
2193   if (I810_DEBUG & DEBUG_VERBOSE_CURSOR)
2194      ErrorF("I810AdjustFrame %d,%d %x\n", x, y, flags);
2195
2196   switch (pScrn->bitsPerPixel) {
2197   case 8:
2198      break;
2199   case 16:
2200      Base *= 2;
2201      break;
2202   case 24:
2203      /* KW: Need to do 16-pixel alignment for i810, otherwise you
2204       * get bad watermark problems.  Need to fixup the mouse
2205       * pointer positioning to take this into account.
2206       */
2207      pI810->CursorOffset = (Base & 0x3) * 4;
2208      Base &= ~0x3;
2209      Base *= 3;
2210      break;
2211   case 32:
2212      Base *= 4;
2213      break;
2214   }
2215
2216   hwp->writeCrtc(hwp, START_ADDR_LO, Base & 0xFF);
2217   hwp->writeCrtc(hwp, START_ADDR_HI, (Base & 0xFF00) >> 8);
2218   hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base & 0x3FC00000) >> 22);
2219   hwp->writeCrtc(hwp, EXT_START_ADDR,
2220		  ((Base & 0x00eF0000) >> 16 | EXT_START_ADDR_ENABLE));
2221}
2222
2223/* These functions are usually called with the lock **not held**.
2224 */
2225static Bool
2226I810EnterVT(int scrnIndex, int flags)
2227{
2228   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
2229
2230#ifdef XF86DRI
2231   I810Ptr pI810 = I810PTR(pScrn);
2232#endif
2233
2234   if (I810_DEBUG & DEBUG_VERBOSE_DRI)
2235      ErrorF("\n\nENTER VT\n");
2236
2237   if (!I810BindGARTMemory(pScrn)) {
2238      return FALSE;
2239   }
2240#ifdef XF86DRI
2241   if (!I810DRIEnter(pScrn)) {
2242      return FALSE;
2243   }
2244   if (pI810->directRenderingEnabled) {
2245      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
2246	 ErrorF("calling dri unlock\n");
2247      DRIUnlock(screenInfo.screens[scrnIndex]);
2248      pI810->LockHeld = 0;
2249   }
2250#endif
2251
2252   if (!I810ModeInit(pScrn, pScrn->currentMode))
2253      return FALSE;
2254   I810AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
2255   return TRUE;
2256}
2257
2258static void
2259I810LeaveVT(int scrnIndex, int flags)
2260{
2261   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
2262   vgaHWPtr hwp = VGAHWPTR(pScrn);
2263   I810Ptr pI810 = I810PTR(pScrn);
2264
2265   if (I810_DEBUG & DEBUG_VERBOSE_DRI)
2266      ErrorF("\n\n\nLeave VT\n");
2267
2268#ifdef XF86DRI
2269   if (pI810->directRenderingEnabled) {
2270      if (I810_DEBUG & DEBUG_VERBOSE_DRI)
2271	 ErrorF("calling dri lock\n");
2272      DRILock(screenInfo.screens[scrnIndex], 0);
2273      pI810->LockHeld = 1;
2274   }
2275#endif
2276
2277   if (pI810->AccelInfoRec != NULL) {
2278      I810RefreshRing(pScrn);
2279      I810Sync(pScrn);
2280      pI810->AccelInfoRec->NeedToSync = FALSE;
2281   }
2282   I810Restore(pScrn);
2283
2284   if (!I810UnbindGARTMemory(pScrn))
2285      return;
2286#ifdef XF86DRI
2287   if (!I810DRILeave(pScrn))
2288      return;
2289#endif
2290
2291   vgaHWLock(hwp);
2292}
2293
2294static Bool
2295I810CloseScreen(int scrnIndex, ScreenPtr pScreen)
2296{
2297   ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
2298   vgaHWPtr hwp = VGAHWPTR(pScrn);
2299   I810Ptr pI810 = I810PTR(pScrn);
2300   XAAInfoRecPtr infoPtr = pI810->AccelInfoRec;
2301
2302   if (pScrn->vtSema == TRUE) {
2303      if (pI810->AccelInfoRec != NULL) {
2304	 I810RefreshRing(pScrn);
2305	 I810Sync(pScrn);
2306	 pI810->AccelInfoRec->NeedToSync = FALSE;
2307      }
2308      I810Restore(pScrn);
2309      vgaHWLock(hwp);
2310   }
2311#ifdef XF86DRI
2312   if (pI810->directRenderingEnabled) {
2313      I810DRICloseScreen(pScreen);
2314      pI810->directRenderingEnabled = FALSE;
2315   }
2316#endif
2317
2318   if (pScrn->vtSema == TRUE) {
2319      I810UnbindGARTMemory(pScrn);
2320      I810Restore(pScrn);
2321      vgaHWLock(hwp);
2322   }
2323
2324   I810UnmapMem(pScrn);
2325   vgaHWUnmapMem(pScrn);
2326
2327   if (pI810->ScanlineColorExpandBuffers) {
2328      xfree(pI810->ScanlineColorExpandBuffers);
2329      pI810->ScanlineColorExpandBuffers = NULL;
2330   }
2331
2332   if (infoPtr) {
2333      if (infoPtr->ScanlineColorExpandBuffers)
2334	 xfree(infoPtr->ScanlineColorExpandBuffers);
2335      XAADestroyInfoRec(infoPtr);
2336      pI810->AccelInfoRec = NULL;
2337   }
2338
2339   if (pI810->CursorInfoRec) {
2340      xf86DestroyCursorInfoRec(pI810->CursorInfoRec);
2341      pI810->CursorInfoRec = NULL;
2342   }
2343
2344   /* Free all allocated video ram.
2345    */
2346   pI810->SysMem = pI810->SavedSysMem;
2347   pI810->DcacheMem = pI810->SavedDcacheMem;
2348   pI810->DoneFrontAlloc = FALSE;
2349
2350   /* Need to actually close the gart fd, or the unbound memory will just sit
2351    * around.  Will prevent the Xserver from recycling.
2352    */
2353   xf86GARTCloseScreen(scrnIndex);
2354
2355   xfree(pI810->LpRing);
2356   pI810->LpRing = NULL;
2357
2358   pScrn->vtSema = FALSE;
2359   pScreen->CloseScreen = pI810->CloseScreen;
2360   return (*pScreen->CloseScreen) (scrnIndex, pScreen);
2361}
2362
2363static void
2364I810FreeScreen(int scrnIndex, int flags)
2365{
2366   I810FreeRec(xf86Screens[scrnIndex]);
2367   if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
2368      vgaHWFreeHWRec(xf86Screens[scrnIndex]);
2369}
2370
2371static ModeStatus
2372I810ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
2373{
2374   if (mode->Flags & V_INTERLACE) {
2375      if (verbose) {
2376	 xf86DrvMsg(scrnIndex, X_PROBED,
2377		    "Removing interlaced mode \"%s\"\n", mode->name);
2378      }
2379      return MODE_BAD;
2380   }
2381   return MODE_OK;
2382}
2383
2384static Bool
2385I810SaveScreen(ScreenPtr pScreen, Bool unblack)
2386{
2387   return vgaHWSaveScreen(pScreen, unblack);
2388}
2389
2390static void
2391I810DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
2392			      int flags)
2393{
2394   I810Ptr pI810;
2395   unsigned char SEQ01 = 0;
2396   int DPMSSyncSelect = 0;
2397
2398   pI810 = I810PTR(pScrn);
2399   switch (PowerManagementMode) {
2400   case DPMSModeOn:
2401      /* Screen: On; HSync: On, VSync: On */
2402      SEQ01 = 0x00;
2403      DPMSSyncSelect = HSYNC_ON | VSYNC_ON;
2404      break;
2405   case DPMSModeStandby:
2406      /* Screen: Off; HSync: Off, VSync: On */
2407      SEQ01 = 0x20;
2408      DPMSSyncSelect = HSYNC_OFF | VSYNC_ON;
2409      break;
2410   case DPMSModeSuspend:
2411      /* Screen: Off; HSync: On, VSync: Off */
2412      SEQ01 = 0x20;
2413      DPMSSyncSelect = HSYNC_ON | VSYNC_OFF;
2414      break;
2415   case DPMSModeOff:
2416      /* Screen: Off; HSync: Off, VSync: Off */
2417      SEQ01 = 0x20;
2418      DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF;
2419      break;
2420   }
2421
2422   /* Turn the screen on/off */
2423   SEQ01 |= pI810->readControl(pI810, SRX, 0x01) & ~0x20;
2424   pI810->writeControl(pI810, SRX, 0x01, SEQ01);
2425
2426   /* Set the DPMS mode */
2427   OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect);
2428}
2429#endif /* I830_ONLY */
2430