1/*
2 * Driver for the SGI Indy's Newport graphics card
3 *
4 * This driver is based on the newport.c & newport_con.c kernel code
5 *
6 * (c) 2000-2002 Guido Guenther <agx@sigxcpu.org>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is fur-
13 * nished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
20 * NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21 * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
23 * NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 * Except as contained in this notice, the name of the XFree86 Project shall not
26 * be used in advertising or otherwise to promote the sale, use or other deal-
27 * ings in this Software without prior written authorization from the XFree86
28 * Project.
29 *
30 */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#if defined(__NetBSD__)
37#include <fcntl.h>
38#include <dev/wscons/wsconsio.h>
39#include <sys/ioctl.h>
40#endif
41
42/* function prototypes, common data structures & generic includes */
43#include "newport.h"
44
45/* Drivers using the mi SW cursor need: */
46#include "mipointer.h"
47/* Drivers using the mi colourmap code need: */
48#include "micmap.h"
49
50/* Drivers using fb need: */
51#include "fb.h"
52
53/* Drivers using the shadow frame buffer need: */
54#include "shadowfb.h"
55
56/* Xv Extension */
57#include "xf86xv.h"
58#include <X11/extensions/Xv.h>
59
60#include <string.h>
61#include <stdio.h>
62#include <unistd.h>
63
64#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) > 6
65#define xf86LoaderReqSymLists(...) do {} while (0)
66#define LoaderRefSymLists(...) do {} while (0)
67#endif
68
69#define NEWPORT_VERSION		4000
70#define NEWPORT_NAME		"NEWPORT"
71#define NEWPORT_DRIVER_NAME	"newport"
72#define NEWPORT_MAJOR_VERSION	PACKAGE_VERSION_MAJOR
73#define NEWPORT_MINOR_VERSION	PACKAGE_VERSION_MINOR
74#define NEWPORT_PATCHLEVEL	PACKAGE_VERSION_PATCHLEVEL
75
76
77/* Prototypes ------------------------------------------------------- */
78static void	NewportIdentify(int flags);
79static const OptionInfoRec * NewportAvailableOptions(int chipid, int busid);
80static Bool NewportProbe(DriverPtr drv, int flags);
81static Bool NewportPreInit(ScrnInfoPtr pScrn, int flags);
82static Bool NewportScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv);
83static Bool NewportEnterVT(int scrnIndex, int flags);
84static void NewportLeaveVT(int scrnIndex, int flags);
85static Bool NewportCloseScreen(int scrnIndex, ScreenPtr pScreen);
86static Bool NewportSaveScreen(ScreenPtr pScreen, int mode);
87static unsigned NewportHWProbe(unsigned probedIDs[]);	/* return number of found boards */
88static Bool NewportModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
89static void NewportRestore(ScrnInfoPtr pScrn, Bool Closing);
90static Bool NewportGetRec(ScrnInfoPtr pScrn);
91static Bool NewportFreeRec(ScrnInfoPtr pScrn);
92static Bool NewportMapRegs(ScrnInfoPtr pScrn);
93static void NewportUnmapRegs(ScrnInfoPtr pScrn);
94static Bool NewportProbeCardInfo(ScrnInfoPtr pScrn);
95/* ------------------------------------------------------------------ */
96
97_X_EXPORT DriverRec NEWPORT = {
98        NEWPORT_VERSION,
99	NEWPORT_DRIVER_NAME,
100        NewportIdentify,
101        NewportProbe,
102        NewportAvailableOptions,
103        NULL,
104	0
105};
106
107/* Supported "chipsets" */
108#define CHIP_XL		0x1
109
110static SymTabRec NewportChipsets[] = {
111    { CHIP_XL, "XL" },
112    {-1, NULL }
113};
114
115static MODULESETUPPROTO(newportSetup);
116
117static XF86ModuleVersionInfo newportVersRec =
118{
119	"newport",
120	MODULEVENDORSTRING,
121	MODINFOSTRING1,
122	MODINFOSTRING2,
123	XORG_VERSION_CURRENT,
124/*
125	XF86_VERSION_CURRENT,
126*/
127	NEWPORT_MAJOR_VERSION, NEWPORT_MINOR_VERSION, NEWPORT_PATCHLEVEL,
128	ABI_CLASS_VIDEODRV,
129	ABI_VIDEODRV_VERSION,
130	MOD_CLASS_VIDEODRV,
131	{0,0,0,0}
132};
133
134_X_EXPORT XF86ModuleData newportModuleData = {
135	&newportVersRec,
136	newportSetup,
137	NULL
138};
139
140static pointer
141newportSetup(pointer module, pointer opts, int *errmaj, int *errmin)
142{
143	static Bool setupDone = FALSE;
144
145/* This module should be loaded only once, but check to be sure. */
146	if (!setupDone) {
147		/*
148		 * Modules that this driver always requires may be loaded
149		 * here  by calling LoadSubModule().
150		 */
151		setupDone = TRUE;
152		xf86AddDriver(&NEWPORT, module, 0);
153
154		/*
155		 * The return value must be non-NULL on success even though
156		 * there is no TearDownProc.
157		 */
158	return (pointer)1;
159       } else {
160	if (errmaj) *errmaj = LDR_ONCEONLY;
161	return NULL;
162       }
163}
164
165typedef enum {
166	OPTION_BITPLANES,
167	OPTION_BUS_ID,
168	OPTION_HWCURSOR,
169	OPTION_NOACCEL
170} NewportOpts;
171
172/* Supported options */
173static const OptionInfoRec NewportOptions [] = {
174	{ OPTION_BITPLANES, "bitplanes", OPTV_INTEGER, {0}, FALSE },
175	{ OPTION_BUS_ID, "BusID", OPTV_INTEGER, {0}, FALSE },
176	{ OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE },
177	{ OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
178	{ -1, NULL, OPTV_NONE, {0}, FALSE }
179};
180
181/* ------------------------------------------------------------------ */
182
183static Bool
184NewportGetRec(ScrnInfoPtr pScrn)
185{
186	NewportPtr pNewport;
187	if (pScrn->driverPrivate != NULL)
188		return TRUE;
189	pScrn->driverPrivate = xnfcalloc(sizeof(NewportRec), 1);
190
191	pNewport = NEWPORTPTR(pScrn);
192	pNewport->pNewportRegs = NULL;
193
194	return TRUE;
195}
196
197static Bool
198NewportFreeRec(ScrnInfoPtr pScrn)
199{
200	free(pScrn->driverPrivate);
201	pScrn->driverPrivate = NULL;
202	return TRUE;
203}
204
205static void
206NewportIdentify(int flags)
207{
208	xf86PrintChipsets( NEWPORT_NAME, "driver for Newport Graphics Card",
209	    NewportChipsets);
210}
211
212static Bool
213NewportProbe(DriverPtr drv, int flags)
214{
215	int numDevSections, numUsed, i, j, busID;
216	Bool foundScreen = FALSE;
217	GDevPtr *devSections;
218	GDevPtr dev = NULL;
219#ifndef XSERVER_LIBPCIACCESS
220	resRange range[] = { {ResExcMemBlock ,0,0}, _END };
221#endif
222	unsigned probedIDs[NEWPORT_MAX_BOARDS];
223	memType base;
224	if ((numDevSections = xf86MatchDevice(NEWPORT_DRIVER_NAME, &devSections)) <= 0)
225                return FALSE;
226
227	numUsed = NewportHWProbe(probedIDs);
228	if ( numUsed <= 0 )
229		return FALSE;
230
231	if ( xf86DoConfigure && xf86DoConfigurePass1 ) {
232		GDevPtr pGDev;
233		for (i = 0; i < numUsed; i++) {
234			pGDev = xf86AddBusDeviceToConfigure(NEWPORT_DRIVER_NAME,
235				BUS_NONE, NULL, 0);
236			if (pGDev) {
237				/*
238				 * XF86Match???Instances() treat chipID and
239				 * chipRev as overrides, so clobber them here.
240				 */
241				pGDev->chipID = pGDev->chipRev = -1;
242			}
243	    	}
244	}
245
246	if(flags & PROBE_DETECT) {
247		foundScreen = TRUE;
248	} else {
249		for (i = 0; i < numDevSections; i++) {
250			dev = devSections[i];
251			busID =  xf86SetIntOption(dev->options, "BusID", 0);
252
253			for( j = 0; j < numUsed; j++) {
254				if ( busID == probedIDs[j] ) {
255					int entity;
256					ScrnInfoPtr pScrn = NULL;
257
258					entity = xf86ClaimNoSlot(drv, 0, dev, TRUE);
259#ifndef XSERVER_LIBPCIACCESS
260					base = (NEWPORT_BASE_ADDR0
261						+ busID * NEWPORT_BASE_OFFSET);
262					RANGE(range[0], base, base + sizeof(NewportRegs),\
263							ResExcMemBlock);
264#endif
265					pScrn = xf86AllocateScreen(drv, 0);
266					xf86AddEntityToScreen(pScrn, entity);
267					pScrn->driverVersion = NEWPORT_VERSION;
268					pScrn->driverName    = NEWPORT_DRIVER_NAME;
269					pScrn->name          = NEWPORT_NAME;
270					pScrn->Probe         = NewportProbe;
271					pScrn->PreInit       = NewportPreInit;
272					pScrn->ScreenInit    = NewportScreenInit;
273					pScrn->EnterVT       = NewportEnterVT;
274					pScrn->LeaveVT       = NewportLeaveVT;
275					pScrn->driverPrivate = (void*)(long)busID;
276					foundScreen = TRUE;
277					break;
278				}
279			}
280		}
281	}
282	free(devSections);
283	return foundScreen;
284}
285
286/* most of this is from DESIGN.TXT s20.3.6 */
287static Bool
288NewportPreInit(ScrnInfoPtr pScrn, int flags)
289{
290	int i, busID;
291	NewportPtr pNewport;
292	MessageType from;
293	ClockRangePtr clockRanges;
294
295	if (flags & PROBE_DETECT) return FALSE;
296
297	if (pScrn->numEntities != 1)
298		return FALSE;
299
300	busID = (long)(pScrn->driverPrivate);
301	pScrn->driverPrivate = NULL;
302
303	/* Fill in the monitor field */
304	pScrn->monitor = pScrn->confScreen->monitor;
305
306#ifdef NEWPORT_USE32BPP
307	if (!xf86SetDepthBpp(pScrn, 24, 32, 32, Support32bppFb))
308		return FALSE;
309#else
310	if (!xf86SetDepthBpp(pScrn, 24, 0, 0,
311			Support24bppFb | SupportConvert32to24 |
312				PreferConvert32to24 ))
313		return FALSE;
314#endif
315	switch( pScrn->depth ) {
316			/* check if the returned depth is one we support */
317		case 8:
318		case 24:
319			/* OK */
320			break;
321		default:
322			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
323			"Given depth (%d) is not supported by Newport driver\n",
324			pScrn->depth);
325			return FALSE;
326	}
327	xf86PrintDepthBpp(pScrn);
328
329	/* Set bits per RGB for 8bpp */
330	if( pScrn->depth == 8)
331		pScrn->rgbBits = 8;
332
333	/* Set Default Weight */
334	if( pScrn->depth > 8 ) {
335#ifdef NEWPORT_USE32BPP
336		rgb w = {8, 8, 8};
337		rgb m = {0x0000FF, 0x00FF00, 0xFF0000};
338		if (!xf86SetWeight(pScrn, w, m))
339			return FALSE;
340#else
341		rgb zeros = {0, 0, 0};
342		if (!xf86SetWeight(pScrn, zeros, zeros))
343			return FALSE;
344#endif
345	}
346
347	if (!xf86SetDefaultVisual(pScrn, -1)) {
348		return FALSE;
349	} else {
350		if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
351			xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
352			" (%s) is not supported at depth %d\n",
353			xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
354			return FALSE;
355        	}
356	}
357
358	{ /* Set default Gamma */
359		Gamma zeros = {0.0, 0.0, 0.0};
360
361		if (!xf86SetGamma(pScrn, zeros)) {
362			return FALSE;
363         	}
364	}
365
366	/* Allocate the NewportRec driverPrivate */
367	if (!NewportGetRec(pScrn)) {
368		return FALSE;
369	}
370	pNewport = NEWPORTPTR(pScrn);
371	pNewport->busID = busID;
372
373	pScrn->memPhysBase = 0;
374	pScrn->fbOffset = 0;
375
376	/* We use a programmable clock */
377	pScrn->progClock = TRUE;
378
379	/* Fill in pScrn->options) */
380	xf86CollectOptions(pScrn, NULL);
381	if (!(pNewport->Options = malloc(sizeof(NewportOptions))))
382		return FALSE;
383	memcpy(pNewport->Options, NewportOptions, sizeof(NewportOptions));
384	xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pNewport->Options);
385
386	/* Set fields in ScreenInfoRec && NewportRec */
387    	pScrn->videoRam = 1280 * (pScrn->bitsPerPixel >> 3);
388
389	/* get revisions of REX3, etc. */
390	if( ! NewportMapRegs(pScrn))
391		return FALSE;
392	NewportProbeCardInfo(pScrn);
393	NewportUnmapRegs(pScrn);
394
395	from=X_PROBED;
396	xf86DrvMsg(pScrn->scrnIndex, from,
397		"Newport Graphics Revisions: Board: %d, Rex3: %c, Cmap: %c, Xmap9: %c\n",
398		pNewport->board_rev, pNewport->rex3_rev,
399		pNewport->cmap_rev, pNewport->xmap9_rev);
400
401	if ( (xf86GetOptValInteger(pNewport->Options, OPTION_BITPLANES,
402	    &pNewport->bitplanes)))
403	from = X_CONFIG;
404	xf86DrvMsg(pScrn->scrnIndex, from, "Newport has %d bitplanes\n",
405	    pNewport->bitplanes);
406
407	if ( pScrn->depth > pNewport->bitplanes ) {
408		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \
409			"Display depth(%d) > number of bitplanes on Newport board(%d)\n", \
410			pScrn->depth, pNewport->bitplanes);
411		return FALSE;
412	}
413	if ( ( pNewport->bitplanes != 8 ) && ( pNewport->bitplanes != 24 ) ) {
414		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \
415			"Number of bitplanes on newport must be either 8 or 24 not %d\n", \
416			pNewport->bitplanes);
417		return FALSE;
418	}
419
420	from=X_DEFAULT;
421	pNewport->hwCursor = TRUE;
422    	if (xf86GetOptValBool(pNewport->Options, OPTION_HWCURSOR, &pNewport->hwCursor))
423        	from = X_CONFIG;
424	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
425        	pNewport->hwCursor ? "HW" : "SW");
426
427	/* Set up clock ranges that are alway ok */
428	/* XXX: Use information from VC2 here */
429	clockRanges = xnfcalloc(sizeof(ClockRange),1);
430	clockRanges->next = NULL;
431	clockRanges->minClock = 10000;
432	clockRanges->maxClock = 300000;
433	clockRanges->clockIndex = -1;         /* programmable */
434	clockRanges->interlaceAllowed = TRUE;
435	clockRanges->doubleScanAllowed = TRUE;
436
437	/* see above note */
438	/* There is currently only an 1280x1024 mode */
439	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
440			pScrn->display->modes, clockRanges,
441			NULL, 256, 2048,
442			pScrn->bitsPerPixel, 128, 2048,
443			pScrn->display->virtualX,
444			pScrn->display->virtualY,
445			pScrn->videoRam * 1024,
446			LOOKUP_BEST_REFRESH);
447
448	if (i == -1) {
449		NewportFreeRec(pScrn);
450		return FALSE;
451	}
452
453	xf86PruneDriverModes(pScrn);
454	if( i == 0 || pScrn->modes == NULL) {
455		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
456		NewportFreeRec(pScrn);
457		return FALSE;
458	}
459
460	/* unnecessary, but do it to get a valid ScrnInfoRec */
461	xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
462
463	/* Set the current mode to the first in the list */
464	pScrn->currentMode = pScrn->modes;
465
466  	/* Print the list of modes being used */
467	xf86PrintModes(pScrn);
468	xf86SetDpi (pScrn, 0, 0);
469
470	/* Load FB module */
471	if (!xf86LoadSubModule (pScrn, "fb")) {
472		NewportFreeRec(pScrn);
473		return FALSE;
474	}
475
476	/* Load ramdac modules */
477    	if (pNewport->hwCursor) {
478        	if (!xf86LoadSubModule(pScrn, "ramdac")) {
479			NewportFreeRec(pScrn);
480            		return FALSE;
481        	}
482    	}
483
484	/* Load ShadowFB module */
485	if (!xf86LoadSubModule(pScrn, "shadowfb")) {
486		NewportFreeRec(pScrn);
487		return FALSE;
488	}
489
490	/* Load XAA module */
491	if (!xf86LoadSubModule(pScrn, "xaa")) {
492		NewportFreeRec(pScrn);
493		return FALSE;
494	}
495	xf86LoaderReqSymLists(xaaSymbols, NULL);
496	return TRUE;
497}
498
499
500Bool
501NewportXAAScreenInit(ScreenPtr pScreen);
502
503
504static Bool
505NewportScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
506{
507	ScrnInfoPtr pScrn;
508	NewportPtr pNewport;
509	VisualPtr visual;
510	BOOL ret;
511	int i;
512
513	/* First get a pointer to our private info */
514	pScrn = xf86Screens[pScreen->myNum];
515	pNewport = NEWPORTPTR(pScrn);
516
517	/* map the Newportregs until the server dies */
518	if( ! NewportMapRegs(pScrn))
519		return FALSE;
520
521	/* Reset visual list. */
522	miClearVisualTypes();
523
524	if (!miSetVisualTypes(pScrn->depth, pScrn->depth != 8 ? TrueColorMask :
525					miGetDefaultVisualMask(pScrn->depth),
526				pScrn->rgbBits, pScrn->defaultVisual))
527		return FALSE;
528
529	miSetPixmapDepths ();
530
531	pNewport->Bpp = pScrn->bitsPerPixel >> 3;
532	/* Setup the stuff for the shadow framebuffer */
533	pNewport->ShadowPitch = (( pScrn->virtualX * pNewport->Bpp ) + 3) & ~3L;
534	pNewport->ShadowPtr = xnfalloc(pNewport->ShadowPitch * pScrn->virtualY);
535
536	if (!NewportModeInit(pScrn, pScrn->currentMode))
537			return FALSE;
538
539	ret = fbScreenInit(pScreen, pNewport->ShadowPtr,
540			   pScrn->virtualX, pScrn->virtualY,
541			   pScrn->xDpi, pScrn->yDpi,
542			   pScrn->displayWidth,
543			   pScrn->bitsPerPixel);
544
545	if(!ret)
546		return FALSE;
547
548	/* we need rgb ordering if bitsPerPixel > 8 */
549	if (pScrn->bitsPerPixel > 8) {
550		for (i = 0, visual = pScreen->visuals;
551			i < pScreen->numVisuals; i++, visual++) {
552			if ((visual->class | DynamicClass) == DirectColor) {
553				visual->offsetRed = pScrn->offset.red;
554				visual->offsetGreen = pScrn->offset.green;
555				visual->offsetBlue = pScrn->offset.blue;
556				visual->redMask = pScrn->mask.red;
557				visual->greenMask = pScrn->mask.green;
558				visual->blueMask = pScrn->mask.blue;
559				/*
560				xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Bitplanes R:%d:%08X G:%d:%08X B:%d:%08X\n",
561				           visual->offsetRed, visual->redMask,
562					   visual->offsetGreen, visual->greenMask,
563					   visual->offsetBlue, visual->blueMask);
564				*/
565			}
566		}
567	}
568
569	/* must be after RGB ordering fixed */
570	if (!fbPictureInit(pScreen, NULL, 0))
571		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
572			   "RENDER extension initialisation failed.\n");
573
574	xf86SetBackingStore(pScreen);
575
576	xf86SetBlackWhitePixels(pScreen);
577#ifdef NEWPORT_ACCEL
578	pNewport->NoAccel = FALSE;
579	if (xf86ReturnOptValBool(pNewport->Options, OPTION_NOACCEL, FALSE))
580	{
581	    pNewport->NoAccel = TRUE;
582	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
583	}
584	if (!pNewport->NoAccel) {
585	    if (!xf86LoadSubModule(pScrn, "xaa"))
586		pNewport->NoAccel = TRUE;
587	}
588#if 0
589	if (pScrn->bitsPerPixel < 24)
590	{ /* not implemented yet */
591	    pNewport->NoAccel = TRUE;
592	}
593#endif
594	pNewport->pXAAInfoRec = NULL;
595	if (!pNewport->NoAccel)
596	{
597	    if (!NewportXAAScreenInit(pScreen))
598		return FALSE;
599	}
600#endif
601	/* Initialize software cursor */
602	if(!miDCInitialize(pScreen, xf86GetPointerScreenFuncs()))
603		return FALSE;
604
605	/* Initialize hardware cursor */
606	if(pNewport->hwCursor)
607		if(!NewportHWCursorInit(pScreen)) {
608			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
609               		"Hardware cursor initialization failed\n");
610			return FALSE;
611	}
612
613	/* Initialise default colourmap */
614	if (!miCreateDefColormap(pScreen))
615		return FALSE;
616
617	/* Install our LoadPalette funciton */
618	if(!xf86HandleColormaps(pScreen, 256, 8, NewportLoadPalette, 0,
619				CMAP_RELOAD_ON_MODE_SWITCH )) {
620		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
621                   "Colormap initialization failed\n");
622		return FALSE;
623	}
624#ifdef NEWPORT_ACCEL
625	if (pNewport->NoAccel)
626#endif
627	/* Initialise shadow frame buffer */
628	if(!ShadowFBInit(pScreen, (pNewport->Bpp == 1) ? &NewportRefreshArea8 :
629				&NewportRefreshArea24)) {
630		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
631                   "ShadowFB initialization failed\n");
632		return FALSE;
633	}
634
635	{
636		XF86VideoAdaptorPtr *ptr;
637		int n;
638
639		n = xf86XVListGenericAdaptors(pScrn,&ptr);
640		if (n) {
641			xf86XVScreenInit(pScreen, ptr, n);
642	        }
643        }
644
645	pScreen->SaveScreen = NewportSaveScreen;
646	/* Wrap the current CloseScreen function */
647	pNewport->CloseScreen = pScreen->CloseScreen;
648	pScreen->CloseScreen = NewportCloseScreen;
649
650	if (serverGeneration == 1) {
651		xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
652	}
653	NewportModeInit(pScrn, pScrn->currentMode);
654	return TRUE;
655}
656
657/* called when switching away from a VT */
658static Bool
659NewportEnterVT(int scrnIndex, int flags)
660{
661	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
662	return NewportModeInit(pScrn, pScrn->currentMode);
663}
664
665/* called when switching to a VT */
666static void
667NewportLeaveVT(int scrnIndex, int flags)
668{
669	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
670	NewportRestore(pScrn, FALSE);
671}
672
673/* called at the end of each server generation */
674static Bool
675NewportCloseScreen(int scrnIndex, ScreenPtr pScreen)
676{
677	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
678	NewportPtr pNewport = NEWPORTPTR(pScrn);
679#ifdef NEWPORT_ACCEL
680	if (pNewport->pXAAInfoRec && !pNewport->NoAccel)
681	{
682	    XAADestroyInfoRec(pNewport->pXAAInfoRec);
683	    pNewport->pXAAInfoRec = NULL;
684	}
685#endif
686
687	NewportRestore(pScrn, TRUE);
688	free(pNewport->ShadowPtr);
689
690	/* unmap the Newport's registers from memory */
691	NewportUnmapRegs(pScrn);
692	pScrn->vtSema = FALSE;
693
694	pScreen->CloseScreen = pNewport->CloseScreen;
695	return (*pScreen->CloseScreen)(scrnIndex, pScreen);
696}
697
698/* Blank or unblank the screen */
699static Bool
700NewportSaveScreen(ScreenPtr pScreen, int mode)
701{
702	ScrnInfoPtr pScrn;
703	NewportPtr pNewport;
704	NewportRegsPtr pNewportRegs;
705	Bool unblank;
706
707	if (!pScreen)
708		return TRUE;
709
710	unblank = xf86IsUnblank(mode);
711	pScrn = xf86Screens[pScreen->myNum];
712
713	if (!pScrn->vtSema)
714		return TRUE;
715
716	pNewport = NEWPORTPTR(pScrn);
717	pNewportRegs = NEWPORTPTR(pScrn)->pNewportRegs;
718
719	if (unblank)
720		pNewport->vc2ctrl |= VC2_CTRL_EDISP;
721	else
722		pNewport->vc2ctrl &= ~VC2_CTRL_EDISP;
723	NewportVc2Set( pNewportRegs, VC2_IREG_CONTROL, pNewport->vc2ctrl);
724	return TRUE;
725}
726
727
728static const OptionInfoRec *
729NewportAvailableOptions(int chipid, int busid)
730{
731	return NewportOptions;
732}
733
734
735/* This sets up the actual mode on the Newport */
736static Bool
737NewportModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
738{
739	int width, height;
740	NewportPtr pNewport = NEWPORTPTR(pScrn);
741	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);
742
743	width = mode->HDisplay;
744	height = mode->VDisplay;
745	if ((width > 1280) || (width < 1024) ||
746	    (height < 768) || (height > 1024)) {
747		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, \
748		"Width = %d and height = %d is not supported by by this driver\n", width, height);
749		return FALSE;
750	}
751
752	pScrn->vtSema = TRUE;
753	/* first backup the necessary registers... */
754	NewportBackupRex3(pScrn);
755	if( pNewport->hwCursor )
756		NewportBackupVc2Cursor( pScrn );
757	NewportBackupVc2(pScrn);
758	NewportBackupPalette(pScrn);
759	NewportBackupXmap9s( pScrn );
760	/* ...then  setup the hardware */
761	pNewport->drawmode1 = DM1_RGBPLANES |
762				NPORT_DMODE1_CCLT |
763				NPORT_DMODE1_CCEQ |
764				NPORT_DMODE1_CCGT |
765				NPORT_DMODE1_LOSRC;
766	if( pNewport->Bpp == 1) { /* 8bpp */
767		pNewport->drawmode1 |=  NPORT_DMODE1_DD8 |
768					NPORT_DMODE1_HD8 |
769					NPORT_DMODE1_RWPCKD;
770	} else { /* 24bpp */
771		CARD32 mode = 0L;
772		LOCO col;
773		int i;
774
775		/* tell the xmap9s that we are using 24bpp */
776		NewportBfwait(pNewport->pNewportRegs);
777		pNewportRegs->set.dcbmode = (DCB_XMAP_ALL |
778		    W_DCB_XMAP9_PROTOCOL | XM9_CRS_CONFIG | NPORT_DMODE_W1 );
779		pNewportRegs->set.dcbdata0.bytes.b3 &=
780		    ~(XM9_8_BITPLANES | XM9_PUPMODE);
781		NewportBfwait(pNewport->pNewportRegs);
782		/* set up the mode register for 24bpp */
783		mode = XM9_MREG_PIX_SIZE_24BPP | XM9_MREG_PIX_MODE_RGB2
784				| XM9_MREG_GAMMA_BYPASS;
785		for (i = 0; i < 32; i++)
786			NewportXmap9SetModeRegister( pNewportRegs , i, mode);
787
788		/* select the set up mode register */
789		NewportBfwait(pNewport->pNewportRegs);
790		pNewportRegs->set.dcbmode = (DCB_XMAP_ALL | W_DCB_XMAP9_PROTOCOL |
791				XM9_CRS_MODE_REG_INDEX | NPORT_DMODE_W1 );
792		pNewportRegs->set.dcbdata0.bytes.b3 = 0;
793
794		pNewport->drawmode1 |=
795					/* set drawdepth to 24 bit */
796					NPORT_DMODE1_DD24 |
797					/* turn on RGB mode */
798					NPORT_DMODE1_RGBMD |
799					/* turn on 8888 = RGBA pixel packing */
800					NPORT_DMODE1_HD32 | NPORT_DMODE1_RWPCKD;
801		/*
802		 * After setting up XMAP9 we have to reinitialize the CMAP for
803		 * whatever reason (the docs say nothing about it).
804		 */
805
806
807		for (i = 0; i < 256; i++) {
808			col.red = col.green = col.blue = i;
809			NewportCmapSetRGB(NEWPORTREGSPTR(pScrn), i, col);
810		}
811		for (i = 0; i < 256; i++) {
812			col.red = col.green = col.blue = i;
813			NewportCmapSetRGB(NEWPORTREGSPTR(pScrn), i + 0x1f00,
814			    col);
815		}
816
817	}
818	/* blank the framebuffer */
819	NewportWait(pNewportRegs);
820	pNewportRegs->set.drawmode0 = (NPORT_DMODE0_DRAW |
821				       NPORT_DMODE0_DOSETUP |
822				       NPORT_DMODE0_STOPX | NPORT_DMODE0_STOPY |
823				       NPORT_DMODE0_BLOCK);
824	pNewportRegs->set.drawmode1 = pNewport->drawmode1 |
825					NPORT_DMODE1_FCLR |
826					NPORT_DMODE1_RGBMD;
827	pNewportRegs->set.colorvram = 0;
828	pNewportRegs->set.xystarti = 0;
829	pNewportRegs->go.xyendi = ( (1279+64) << 16) | 1023;
830
831	/* default drawmode */
832	NewportWait(pNewportRegs);
833	pNewportRegs->set.drawmode1 = pNewport->drawmode1;
834
835	/* XXX: Lazy mode on: just use the textmode value */
836	pNewport->vc2ctrl = pNewport->txt_vc2ctrl;
837
838	return TRUE;
839}
840
841
842/*
843 * This will actually restore the saved state
844 * (either when switching back to a VT or when the server is going down)
845 * Closing is true if the X server is really going down
846 */
847static void
848NewportRestore(ScrnInfoPtr pScrn, Bool Closing)
849{
850	NewportPtr pNewport = NEWPORTPTR(pScrn);
851
852	/* Restore backed up registers */
853	NewportRestoreRex3( pScrn );
854	if( pNewport->hwCursor )
855		NewportRestoreVc2Cursor( pScrn );
856	NewportRestoreVc2( pScrn );
857	NewportRestorePalette( pScrn );
858	NewportRestoreXmap9s( pScrn );
859}
860
861
862/* Probe for the Newport card ;) */
863/* XXX: we need a better probe here in order to support multihead! */
864static unsigned
865NewportHWProbe(unsigned probedIDs[])
866{
867	unsigned hasNewport = 0;
868
869#if defined(__NetBSD__)
870	int fd, type, i;
871
872	probedIDs[0] = 0;
873
874	fd = open("/dev/ttyE0", O_RDONLY, 0);
875	i = ioctl(fd, WSDISPLAYIO_GTYPE, &type);
876	close(fd);
877
878	if ( (i == 0) && ( type == WSDISPLAY_TYPE_NEWPORT) )
879		hasNewport = 1;
880#else
881	FILE* cpuinfo;
882	char line[80];
883	if ((cpuinfo = fopen("/proc/cpuinfo", "r"))) {
884		while(fgets(line, 80, cpuinfo) != NULL) {
885			if(strstr(line, "SGI Indy") != NULL) {
886				hasNewport = 1;
887				probedIDs[0] = 0;
888				break;
889			}
890			if(strstr(line, "SGI Indigo2") != NULL) {
891				hasNewport = 1;
892				probedIDs[0] = 1;
893				break;
894			}
895		}
896		fclose(cpuinfo);
897	}
898#endif
899	return hasNewport;
900}
901
902/* Probe for Chipset revisions */
903static Bool NewportProbeCardInfo(ScrnInfoPtr pScrn)
904{
905	unsigned int tmp,cmap_rev;
906	NewportPtr pNewport = NEWPORTPTR(pScrn);
907	NewportRegsPtr pNewportRegs = pNewport->pNewportRegs;
908
909	NewportWait(pNewportRegs);
910	pNewportRegs->set.dcbmode = (DCB_CMAP0 | NCMAP_PROTOCOL |
911			NCMAP_REGADDR_RREG | NPORT_DMODE_W1);
912	tmp = pNewportRegs->set.dcbdata0.bytes.b3;
913	pNewport->board_rev = (tmp >> 4) & 7;
914	pNewport->bitplanes = ((pNewport->board_rev > 1) && (tmp & 0x80)) ? 8 : 24;
915	cmap_rev = tmp & 7;
916	pNewport->cmap_rev = (char)('A'+(cmap_rev ? (cmap_rev+1):0));
917	pNewport->rex3_rev = (char)('A'+(pNewportRegs->cset.ustat & 7));
918
919	pNewportRegs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL |
920					XM9_CRS_REVISION | NPORT_DMODE_W1);
921	pNewport->xmap9_rev = (char)('A'+(pNewportRegs->set.dcbdata0.bytes.b3 & 7));
922
923	/* XXX: read possible modes from VC2 here */
924	return TRUE;
925}
926
927
928/* map NewportRegs */
929static Bool
930NewportMapRegs(ScrnInfoPtr pScrn)
931{
932	NewportPtr pNewport = NEWPORTPTR(pScrn);
933
934#if defined(__NetBSD__)
935	pNewport->pNewportRegs = xf86MapVidMem(pScrn->scrnIndex,
936			VIDMEM_MMIO, NEWPORT_REGISTERS, sizeof(NewportRegs));
937#else
938	pNewport->pNewportRegs = xf86MapVidMem(pScrn->scrnIndex,
939			VIDMEM_MMIO,
940			NEWPORT_BASE_ADDR0 + pNewport->busID *
941			    NEWPORT_BASE_OFFSET, sizeof(NewportRegs));
942#endif
943	if ( ! pNewport->pNewportRegs ) {
944		xf86Msg(X_ERROR, "can't map registers\n");
945		return FALSE;
946	}
947	return TRUE;
948}
949
950/* unmap NewportRegs */
951static void
952NewportUnmapRegs(ScrnInfoPtr pScrn)
953{
954	NewportPtr pNewport = NEWPORTPTR(pScrn);
955
956	xf86UnMapVidMem( pScrn->scrnIndex, pNewport->pNewportRegs,
957			sizeof(NewportRegs));
958	pNewport->pNewportRegs = NULL;
959}
960