Copyright (c) 2004-2005 Advanced Micro Devices, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Neither the name of the Advanced Micro Devices, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. --- xc/config/cf/xorg.cf 2005-12-14 12:12:08.471825920 -0700 +++ xc.new/config/cf/xorg.cf 2005-09-30 15:38:05.000000000 -0600 @@ -160,12 +160,8 @@ * a full build. */ #ifndef BuildXFree86ConfigTools -#ifdef BuildServersOnly -#define BuildXFree86ConfigTools !BuildServersOnly -#else #define BuildXFree86ConfigTools YES #endif -#endif #ifndef BuildLibrariesForConfigTools #define BuildLibrariesForConfigTools BuildXFree86ConfigTools @@ -399,9 +395,9 @@ /* Pure PCI drivers should go first */ # ifndef XF86CardDrivers -# /* Don't build the nsc driver on IA64 */ +# /* Don't build the amd geode driver on IA64 */ # ifndef ia64Architecture -# define i386Drivers nsc i810 +# define i386Drivers amd i810 # else # define i386Drivers /**/ # endif @@ -446,8 +442,8 @@ # ifndef XF86CardDrivers # define XF86CardDrivers mga glint nv tga s3 s3virge sis rendition \ neomagic tdfx savage cirrus tseng trident \ - chips apm i128 ati ark cyrix siliconmotion \ - vga dummy vesa \ + chips apm i128 ati i810 ark cyrix \ + siliconmotion vga dummy vesa \ XF86OSCardDrivers XF86ExtraCardDrivers # endif --- xc/config/cf/xfree86.cf 2005-12-14 12:12:08.472825768 -0700 +++ xc.new/config/cf/xfree86.cf 2005-09-30 15:31:40.000000000 -0600 @@ -365,16 +365,16 @@ /* Pure PCI drivers should go first */ # ifndef XF86CardDrivers -# /* Don't build the nsc driver on IA64 */ +# /* Don't build the amd geode driver on IA64 */ # ifndef ia64Architecture -# define NscDriver nsc +# define geodeDriver amd # else -# define NscDriver /**/ +# define geodeDriver /**/ # endif # define XF86CardDrivers mga glint nv tga s3 s3virge sis rendition \ neomagic i740 tdfx savage \ cirrus vmware tseng trident chips apm \ - GlideDriver i128 NscDriver \ + GlideDriver i128 geodeDriver \ ati i810 AgpGartDrivers DevelDrivers ark \ cyrix siliconmotion via \ fbdev vesa vga \ --- xc/programs/x11perf/x11perf.c 2005-12-14 12:12:08.473825616 -0700 +++ xc.new/programs/x11perf/x11perf.c 2005-09-30 15:02:28.000000000 -0600 @@ -24,6 +24,8 @@ /* $XFree86: xc/programs/x11perf/x11perf.c,v 3.6 2001/11/03 21:59:20 dawes Exp $ */ #include +#include +#include #include #include @@ -44,8 +46,14 @@ static Bool drawToFakeServer = False; static Pixmap tileToQuery = None; static char *displayName; +static int window_x, window_y; + int abortTest; +char *crcfn; +unsigned long ckcrc; +FILE *crcfp; + typedef struct _RopNames { char *name; int rop; } RopNameRec, *RopNamePtr; RopNameRec ropNames[] = { @@ -182,6 +190,247 @@ static struct timeval start; +static void +DumpProc(XParms xp, Parms p, + void(*init)(int w,int h), + void(*putb)(int ch)) +{ + int i, n, x, y, w, h; + Window rw; + XImage *image; + Visual *visual; + XWindowAttributes xwa; + Colormap colormap; + unsigned char *data; + + if( !XGetWindowAttributes(xp->d, xp->w, &xwa) ) + return; + w = xwa.width; + h = xwa.height; + +#if 0 + x = y = 0; + image = XGetImage(xp->d, xp->w, x,y, w,h, AllPlanes, ZPixmap); +#else + rw = DefaultRootWindow(xp->d); +#ifdef NO_WINDOW_DRESSING + x = xwa.x + xwa.border_width; + y = xwa.y + xwa.border_width; + image = XGetImage(xp->d, rw, x,y, w,h, AllPlanes, ZPixmap); +#else + x = xwa.x; w += 2*xwa.border_width; + y = xwa.y; h += 2*xwa.border_width; + image = XGetImage(xp->d, rw, x,y, w,h, AllPlanes, ZPixmap); +#endif +#endif + visual = xwa.visual; + + if( init != NULL ) init(w,h); + + switch( visual->class ) { + case TrueColor: { + int b0; /* Byte 0 index */ + int bi; /* Byte index increment */ + + /* develop pixel format */ + + int rmask = image->red_mask; double fr = 255.0 / rmask; + int gmask = image->green_mask; double fg = 255.0 / gmask; + int bmask = image->blue_mask; double fb = 255.0 / bmask; + + int nbyte = (image->bits_per_pixel+7)/8; /* bytes per pixel */ + + /* A/R/G/B or A/B/G/R byte ordering */ + + if( image->byte_order == MSBFirst ) { + b0 = 0; + bi = 1; + } + else { + b0 = nbyte-1; + bi = -1; + } + + data = (unsigned char *)image->data; + + /* scan output rows */ + + for( y=0; ybytes_per_line]; + + /* scan output columns */ + + for( x=0; x0; n|=*cp ) { + cp += bi; + n <<= 8; + } + + /* decompose pixel to R/G/B */ + + putb((int)((double)(n&rmask)*fr + 0.5)); + putb((int)((double)(n&gmask)*fg + 0.5)); + putb((int)((double)(n&bmask)*fb + 0.5)); + } + } + break; + } + + + case PseudoColor: { + XColor xcolors[256]; + unsigned char rgbColors[256][3]; + + /* access color map */ + + for( i = 0; i < 256; i++ ) + xcolors[i].pixel = i; + + colormap = xwa.colormap; + XQueryColors(xp->d, colormap, xcolors, 256 ); + for( i = 0; i<256; i++ ) { + rgbColors[i][0] = xcolors[i].red * 255 / 65535; + rgbColors[i][1] = xcolors[i].green * 255 / 65535; + rgbColors[i][2] = xcolors[i].blue * 255 / 65535; + } + + /* scan output rows */ + + data = (unsigned char *)image->data; + for( y=0; ybytes_per_line]; + + /* scan output columns */ + + for( x=0; xclass); + break; + } + + XDestroyImage(image); +} + +static FILE *DumpFp = NULL; +static char *dump = NULL; + +void DumpInit(int w,int h) +{ + fprintf(DumpFp,"%d %d\n",w,h); + fprintf(DumpFp,"255\n"); +} + +void DumpPutc(int ch) +{ + putc(ch,DumpFp); +} + +void +DumpTest(XParms xp, Parms p, char *opt, int func, unsigned long pm) +{ + int cycle = 0; + char filename[1024]; + sprintf(&filename[0],"%s/%s_%02d.pgm",dump,&opt[1],func); + for(;;){ + if( access(&filename[0],F_OK) < 0 && errno == ENOENT ) break; + sprintf(&filename[0],"%s/%s.%d_%02d.pgm",dump,&opt[1],++cycle,func); + } + DumpFp = fopen(&filename[0],"w"); + if( DumpFp == NULL ) { + perror("DumpPixmap fopen"); + return; + } + sprintf(&filename[0],"%s_%02d.pgm",&opt[1],func); + fprintf(DumpFp,"P6\n"); + fprintf(DumpFp,"# %s\n",&filename[0]); + DumpProc(xp,p,DumpInit,DumpPutc); + fclose(DumpFp); + DumpFp = NULL; +} + +static char *swfn = NULL; +static long sw_crc; +static unsigned long sw_pix; +static int sw_byt; + +#define sw_crc_reset(p) sw_crc=1,sw_byt=3 +#define sw_crc_pixel(p) (sw_crc=(sw_crc<<1)^(sw_crc<0?0x04C11DB7:0)^(p)) +#define sw_crc_byte(ch) (sw_pix=(sw_pix<<8)|(ch)) + +void SwCrcb(int ch) +{ + sw_crc_byte(ch); + if( --sw_byt > 0 ) return; + sw_byt = 3; + sw_crc_pixel(sw_pix&0xffffff); +} + +unsigned long +swcrcTest(XParms xp, Parms p,char *opt, int func, unsigned long pm) +{ + sw_crc_reset(); + DumpProc(xp,p,NULL,SwCrcb); + return (unsigned long)sw_crc; +} + +void +SwcrcTest(XParms xp, Parms p,char *opt, int func, unsigned long pm) +{ + FILE *fp; + ckcrc = swcrcTest(xp,p,opt,func,pm); + if( swfn == NULL ) return; + if( (fp=fopen(swfn,"a")) != NULL ) { + fprintf(fp,"%s_%02d %08lx\n",&opt[1],func,ckcrc); + fclose(fp); + } + else + perror("SwcrcTest fopen"); +} + +void CheckTest(XParms xp, Test *test, int func, unsigned long pm) +{ + int do_dump; + char tstnm[64]; + unsigned long crc; + if (swfn != NULL) + SwcrcTest(xp, &test->parms, test->option, func, pm); + if (crcfp != NULL) { + if( swfn == NULL ) + ckcrc = swcrcTest(xp,&test->parms,test->option,func,pm); + do_dump = 0; + if( fscanf(crcfp,"%63s %lx\n",&tstnm[0],&crc) == 2 ) { + if( ckcrc != crc ) { + do_dump = 1; + fprintf(stderr,"crcck %s %08lx!=%08lx\n",&tstnm[0],crc,ckcrc); + } + } + } + else + do_dump = 1; + if( dump != NULL && do_dump != 0 ) { + DumpTest(xp, &test->parms, test->option, func, pm); + XSetWindowBorder(xp->d, xp->w, xp->background); + XFlush(xp->d); + XSetWindowBorder(xp->d, xp->w, xp->foreground); + XFlush(xp->d); + } +} + static void PrintTime(void) { @@ -452,6 +701,11 @@ " -v1.3 perform only v1.3 tests using old semantics", " -su request save unders on windows", " -bs WhenMapped or Always (default = NotUseful)", +" -dump dump each pixmap to /_.pgm", +" -swcrc dump each pixmap swcrc to ", +" -crcck read and cmpr crcs, dump only errs", +" -wx x-coord of test window", +" -wy y-coord of test window", NULL}; fflush(stdout); @@ -583,7 +837,7 @@ static double -DoTest(XParms xp, Test *test, int reps) +DoTest(XParms xp, Test *test, int reps, int func, unsigned long pm) { double time; unsigned int ret_width, ret_height; @@ -601,6 +855,7 @@ if (drawToFakeServer) XQueryBestSize(xp->d, TileShape, tileToQuery, 32, 32, &ret_width, &ret_height); + CheckTest(xp, test, func, pm); (*test->passCleanup) (xp, &test->parms); return time; } @@ -711,7 +966,7 @@ gcvbg.background = gcvfg.background = bg; /* Double Dash GCs (This doesn't make a huge amount of sense) */ gcvddbg.foreground = gcvddfg.foreground = bg ^ fg; - gcvddbg.background = gcvddfg.foreground = bg ^ ddbg; + gcvddbg.background = gcvddfg.background = bg ^ ddbg; } else { gcvfg.foreground = fg; gcvfg.background = bg; @@ -816,7 +1071,7 @@ totalTime = 0.0; for (j = 0; j != repeat; j++) { DisplayStatus(xp->d, "Testing", label, j+1); - time = DoTest(xp, test, reps); + time = DoTest(xp, test, reps, func, pm); if (abortTest) AbortTest (); totalTime += time; @@ -854,7 +1109,6 @@ XGCValues tgcv; int screen; int rop, pm; - int window_y, window_x; XVisualInfo *vinfolist, vinfotempl; unsigned long vmask; @@ -963,6 +1217,31 @@ } else if (strcmp(argv[i], "-rop") == 0) { skip = GetRops (i+1, argc, argv, rops, &numRops); i += skip; + } else if (strcmp(argv[i], "-dump") == 0) { + i++; + if (argc <= i) usage (); + dump = argv[i]; + } else if (strcmp(argv[i], "-swcrc") == 0) { + i++; + if (argc <= i) usage (); + swfn = argv[i]; + } else if (strcmp(argv[i], "-crcck") == 0) { + i++; + if (argc <= i) usage (); + crcfn = argv[i]; + crcfp = fopen(crcfn,"r"); + if( crcfp == NULL ) { + fprintf(stderr, "unable to open crc check file - %s\n",crcfn); + exit(1); + } + } else if (strcmp(argv[i], "-wx") == 0) { + i++; + if (argc <= i) usage (); + window_x = atoi(argv[i]); + } else if (strcmp(argv[i], "-wy") == 0) { + i++; + if (argc <= i) usage (); + window_y = atoi(argv[i]); } else if (strcmp(argv[i], "-pm") == 0) { skip = GetNumbers (i+1, argc, argv, planemasks, &numPlanemasks); i += skip; @@ -1109,6 +1388,7 @@ if (!foundOne) usage (); + xparms.d = Open_Display (displayName); screen = DefaultScreen(xparms.d); @@ -1212,10 +1492,8 @@ AllocateColor(xparms.d, background, WhitePixel(xparms.d, screen)); xparms.ddbackground = AllocateColor(xparms.d, ddbackground, WhitePixel(xparms.d, screen)); - window_x = 2; if (DisplayWidth(xparms.d, screen) < WIDTH + window_x + 1) window_x = -1; - window_y = 2; if (DisplayHeight(xparms.d, screen) < HEIGHT + window_y + 1) window_y = -1; xparms.w = CreatePerfWindow(&xparms, window_x, window_y, WIDTH, HEIGHT); @@ -1225,7 +1503,7 @@ HSy = HEIGHT-1; if (window_y + 1 + HEIGHT > DisplayHeight(xparms.d, screen)) HSy = DisplayHeight(xparms.d, screen) - (1 + window_y + 1); - status = CreatePerfWindow(&xparms, window_x, HEIGHT+5, WIDTH, 20); + status = CreatePerfWindow(&xparms, window_x, window_y+HEIGHT+3, WIDTH, 20); tgcv.foreground = AllocateColor(xparms.d, "black", BlackPixel(xparms.d, screen)); tgcv.background = --- xc/programs/x11perf/x11perf.h 2005-12-14 12:12:08.476825160 -0700 +++ xc.new/programs/x11perf/x11perf.h 2005-09-30 14:57:01.000000000 -0600 @@ -299,6 +299,11 @@ extern void DoPopUps ( XParms xp, Parms p, int reps ); extern void EndPopups ( XParms xp, Parms p ); +/* do_paint.c */ +extern int InitPaint ( XParms xp, Parms p, int reps ); +extern void DoPaint ( XParms xp, Parms p, int reps ); +extern void EndPaint ( XParms xp, Parms p ); + /***************************************************************************** --- xc/programs/x11perf/Imakefile 2005-12-14 12:12:08.914758584 -0700 +++ xc.new/programs/x11perf/Imakefile 2005-09-30 14:48:00.000000000 -0600 @@ -33,13 +33,13 @@ do_lines.c do_segs.c \ do_dots.c do_windows.c do_movewin.c do_text.c \ do_blt.c do_arcs.c \ - do_tris.c do_complex.c do_traps.c + do_tris.c do_complex.c do_traps.c do_paint.c OBJS = x11perf.o bitmaps.o do_tests.o \ do_simple.o do_rects.o do_valgc.o \ do_lines.o do_segs.o \ do_dots.o do_windows.o do_movewin.o do_text.o \ do_blt.o do_arcs.o \ - do_tris.o do_complex.o do_traps.o + do_tris.o do_complex.o do_traps.o do_paint.o LOCAL_LIBRARIES = $(XFTLIBS) $(XRENDERLIBS) $(XMUULIB) $(XLIB) DEPLIBS = $(XFTDEPS) $(XRENDERDEPS) $(DEPXMUULIB) $(DEPXLIB) SYS_LIBRARIES = MathLibrary --- xc/programs/x11perf/do_tests.c 2005-12-14 12:12:09.615652032 -0700 +++ xc.new/programs/x11perf/do_tests.c 2005-09-30 14:56:21.000000000 -0600 @@ -1005,6 +1005,18 @@ {30, False, "-adobe-times-medium-r-normal--24-240-75-75-p-124-iso8859-1", NULL}}, + {"-paint8", "Paint window 8x8 color pixmap", NULL, + InitPaint, DoPaint, NullProc, EndPaint, + V1_5FEATURE, NONROP, 0, + {1, 8, NULL, NULL }}, + {"-paint33", "Paint window 33x33 color pixmap", NULL, + InitPaint, DoPaint, NullProc, EndPaint, + V1_5FEATURE, NONROP, 0, + {1, 33, NULL, NULL }}, + {"-paint65", "Paint window 65x65 color pixmap", NULL, + InitPaint, DoPaint, NullProc, EndPaint, + V1_5FEATURE, NONROP, 0, + {1, 65, NULL, NULL }}, #ifdef XFT {"-aa10text", "Char in 80-char aa line (Charter 10)", NULL, InitAAText, DoAAText, ClearTextWin, EndAAText, --- xc/programs/x11perf/do_paint.c 1969-12-31 17:00:00.000000000 -0700 +++ xc.new/programs/x11perf/do_paint.c 2005-07-13 13:16:48.000000000 -0600 @@ -0,0 +1,211 @@ +/* $Xorg: do_dots.c,v 1.3 2000/08/17 19:54:09 cpqbld Exp $ */ +/***************************************************************************** +Copyright 1988, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************************/ +/* $XFree86: xc/programs/x11perf/do_dots.c,v 1.4 2000/11/29 08:58:19 keithp Exp $ */ + +/* + * Copyright (c) 2003-2005 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * */ +/* + * */ +/* + * */ + +#include "x11perf.h" + +static GC pgc; +static int pwidth; +static int pheight; +static int ipix; + +static Pixmap bg_pixmap[2]; +static XImage *image; +static unsigned char rgbColors[256][4]; + +static unsigned long XlateColor(unsigned long pixel) +{ + unsigned char r, g, b, *cp; + int i, se, te, re, ge, be; + + b = pixel; pixel >>= 8; + g = pixel; pixel >>= 8; + r = pixel; pixel = 0; + + cp = &rgbColors[0][0]; + re = cp[0] - r; + ge = cp[1] - g; + be = cp[2] - b; + se = re*re + ge*ge + be*be; + + for( i=1; i<256; ++i ) { + cp += 4; + re = cp[0] - r; + ge = cp[1] - g; + be = cp[2] - b; + te = re*re + ge*ge + be*be; + if( te < se ) { + se = te; + pixel = i; + } + } + + return pixel; +} + +#undef iabs +#define iabs(n) ((n)<0?-(n):(n)) + +int +InitPaint(XParms xp, Parms p, int reps) +{ + int n, x, y, w1, h1, wh1; + int depth, depthfactor; + int trueColor, psize; + XColor xcolors[256]; + XWindowAttributes xwa; + Colormap colormap; + unsigned long pixel, rpix, gpix, bpix; + unsigned long rmask, gmask, bmask; + Visual *visual; + char *pixels; + + pgc = xp->fggc; + pwidth = pheight = p->special; + depth = xp->vinfo.depth; + depthfactor = (depth+7)/8; + if( depthfactor == 3 ) depthfactor = 4; + visual = xp->vinfo.visual; + psize = pheight*pwidth*depthfactor; + pixels = (char *) malloc(psize); + psize = pwidth*depthfactor; + image = XCreateImage(xp->d, visual, depth, ZPixmap, 0, + pixels, pwidth, pheight, 8, psize); + + if( visual->class != TrueColor ) { + XGetWindowAttributes(xp->d, xp->w, &xwa); + colormap = xwa.colormap; + trueColor = 0; + for( n=0; n<256; n++ ) + xcolors[n].pixel = n; + XQueryColors(xp->d,colormap,xcolors,256); + for( n = 0; n<256; n++ ) { + rgbColors[n][0] = xcolors[n].red * 255 / 65535; + rgbColors[n][1] = xcolors[n].green * 255 / 65535; + rgbColors[n][2] = xcolors[n].blue * 255 / 65535; + } + rmask = 0xff0000; + gmask = 0x00ff00; + bmask = 0x0000ff; + } + else { + trueColor = 1; + rmask = visual->red_mask; + gmask = visual->green_mask; + bmask = visual->blue_mask; + } + + w1 = pwidth - 1; + h1 = pheight - 1; + wh1 = w1 + h1; + for( x=0; xd, xp->w, pwidth,pheight, depth); + XPutImage(xp->d,bg_pixmap[0],pgc,image, 0,0, 0,0, pwidth, pheight); + + w1 = pwidth - 1; + h1 = pheight - 1; + wh1 = w1; + if( h1 > wh1 ) wh1 = h1; + for( x=0; xd, xp->w, pwidth,pheight, depth); + XPutImage(xp->d,bg_pixmap[1],pgc,image, 0,0, 0,0, pwidth, pheight); + + XDestroyImage(image); + ipix = 0; + return reps; +} + +void +DoPaint(XParms xp, Parms p, int reps) +{ + int i; + + for (i = 0; i != reps; i++) { + XSetWindowBackgroundPixmap(xp->d, xp->w, bg_pixmap[ipix]); + ipix = 1-ipix; + XClearWindow(xp->d, xp->w); + } +} + +void +EndPaint(XParms xp, Parms p) +{ + XSetWindowBackground(xp->d, xp->w, xp->background); + XClearWindow(xp->d, xp->w); + XFreePixmap(xp->d, bg_pixmap[0]); + XFreePixmap(xp->d, bg_pixmap[1]); +} + --- xc/programs/Xserver/hw/xfree86/drivers/amd/durango.c 1969-12-31 17:00:00.000000000 -0700 +++ xc.new/programs/Xserver/hw/xfree86/drivers/amd/durango.c 2005-08-03 13:15:14.000000000 -0600 @@ -0,0 +1,630 @@ +/* + * $Workfile: durango.c $ + * $Revision: #2 $ + * $Author: raymondd $ + * + * This is the main file used to add Durango graphics support to a software + * project. The main reason to have a single file include the other files + * is that it centralizes the location of the compiler options. This file + * should be tuned for a specific implementation, and then modified as needed + * for new Durango releases. The releases.txt file indicates any updates to + * this main file, such as a new definition for a new hardware platform. + * + * In other words, this file should be copied from the Durango source files + * once when a software project starts, and then maintained as necessary. + * It should not be recopied with new versions of Durango unless the + * developer is willing to tune the file again for the specific project. + */ + +/* + * Copyright (c) 2003-2005 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * */ +/* + * */ +/* + * */ + + +/* COMPILER OPTIONS + * These compiler options specify how the Durango routines are compiled + * for the different hardware platforms. For best performance, a driver + * would build for a specific platform. The "dynamic" switches are set + * by diagnostic applications such as Darwin that will run on a variety + * of platforms and use the appropriate code at runtime. Each component + * may be separately dynamic, so that a driver has the option of being + * tuned for a specific 2D accelerator, but will still run with a variety + * of chipsets. + */ + +#define GFX_DISPLAY_DYNAMIC 0 /* runtime selection */ +#define GFX_DISPLAY_GU1 0 /* 1st generation display controller */ +#define GFX_DISPLAY_GU2 1 /* 2nd generation display controller */ +#define GFX_DISPLAY_GU3 0 /* 3nd generation display controller */ + +#define GFX_INIT_DYNAMIC 0 /* runtime selection */ +#define GFX_INIT_GU1 0 /* Geode family */ +#define GFX_INIT_GU2 1 /* Redcloud */ +#define GFX_INIT_GU3 0 /* Castle */ + +#define GFX_MSR_DYNAMIC 1 /* runtime selection */ +#define GFX_MSR_REDCLOUD 1 /* Redcloud */ + +#define GFX_2DACCEL_DYNAMIC 0 /* runtime selection */ +#define GFX_2DACCEL_GU1 0 /* 1st generation 2D accelerator */ +#define GFX_2DACCEL_GU2 1 /* 2nd generation 2D accelerator */ + +#define GFX_VIDEO_DYNAMIC 0 /* runtime selection */ +#define GFX_VIDEO_CS5530 0 /* support for CS5530 */ +#define GFX_VIDEO_SC1200 0 /* support for SC1200 */ +#define GFX_VIDEO_REDCLOUD 1 /* support for Redcloud */ +#define GFX_VIDEO_CASTLE 0 /* support for Castle */ + +#define GFX_VIP_DYNAMIC 0 /* runtime selection */ +#define GFX_VIP_SC1200 0 /* support for SC1200 */ + +#define GFX_DECODER_DYNAMIC 0 /* runtime selection */ +#define GFX_DECODER_SAA7114 0 /* Philips SAA7114 decoder */ + +#define GFX_TV_DYNAMIC 0 /* runtime selection */ +#define GFX_TV_FS451 0 /* Focus Enhancements FS450 */ +#define GFX_TV_SC1200 0 /* SC1200 integrated TV encoder */ + +#define GFX_I2C_DYNAMIC 0 /* runtime selection */ +#define GFX_I2C_ACCESS 0 /* support for ACCESS.BUS */ +#define GFX_I2C_GPIO 0 /* support for CS5530 GPIOs */ + +#define GFX_VGA_DYNAMIC 0 /* runtime selection */ +#define GFX_VGA_GU1 0 /* 1st generation graphics unit */ + +#define FB4MB 1 /* Set to use 4Mb video ram for Pyramid */ + +#define GFX_NO_IO_IN_WAIT_MACROS 1 /* Set to remove I/O accesses in GP bit testing */ + +/* ROUTINES TO READ VALUES + * These are routines used by Darwin or other diagnostics to read the + * current state of the hardware. Display drivers or embedded applications can + * reduce the size of the Durango code by not including these routines. + */ +#define GFX_READ_ROUTINES 1 /* add routines to read values */ + +/* HEADER FILE FOR DURANGO ROUTINE DEFINITIONS + * Needed since some of the Durango routines call other Durango routines. + * Also defines the size of chipset array (GFX_CSPTR_SIZE). + */ +#include "gfx_rtns.h" /* routine definitions */ +#include "gfx_priv.h" +/* VARIABLES USED FOR RUNTIME SELECTION + * If part of the graphics subsystem is declared as dynamic, then the + * following variables are used to specify which platform has been detected. + * The variables are set in the "gfx_detect_cpu" routine. The values should + * be bit flags to allow masks to be used to check for multiple platforms. + */ + +#if GFX_DISPLAY_DYNAMIC +int gfx_display_type = 0; +#endif + +#if GFX_INIT_DYNAMIC +int gfx_init_type = 0; +#endif + +#if GFX_MSR_DYNAMIC +int gfx_msr_type = 0; +#endif + +#if GFX_2DACCEL_DYNAMIC +int gfx_2daccel_type = 0; +#endif + +#if GFX_VIDEO_DYNAMIC +int gfx_video_type = 0; +#endif + +#if GFX_VIP_DYNAMIC +int gfx_vip_type = 0; +#endif + +#if GFX_DECODER_DYNAMIC +int gfx_decoder_type = 0; +#endif + +#if GFX_TV_DYNAMIC +int gfx_tv_type = 0; +#endif + +#if GFX_I2C_DYNAMIC +int gfx_i2c_type = 0; +#endif + +#if GFX_VGA_DYNAMIC +int gfx_vga_type = 0; +#endif + +/* DEFINE POINTERS TO MEMORY MAPPED REGIONS + * These pointers are used by the Durango routines to access the hardware. + * The variables must be set by the project's initialization code after + * mapping the regions in the appropriate manner. + */ + +/* DEFINE VIRTUAL ADDRESSES */ +/* Note: These addresses define the starting base expected by all */ +/* Durango offsets. Under an OS that requires these pointers */ +/* to be mapped to linear addresses (i.e Windows), it may not */ +/* be possible to keep these base offsets. In these cases, */ +/* the addresses are modified to point to the beginning of the */ +/* relevant memory region and the access macros are adjusted */ +/* to subtract the offset from the default base. For example, */ +/* the register pointer could be moved to be 0x40008000, while */ +/* the WRITE_REG* macros are modified to subtract 0x8000 from */ +/* the offset. */ + +unsigned char *gfx_virt_regptr = (unsigned char *)0x40000000; +unsigned char *gfx_virt_fbptr = (unsigned char *)0x40800000; +unsigned char *gfx_virt_vidptr = (unsigned char *)0x40010000; +unsigned char *gfx_virt_vipptr = (unsigned char *)0x40015000; +unsigned char *gfx_virt_spptr = (unsigned char *)0x40000000; +unsigned char *gfx_virt_gpptr = (unsigned char *)0x40000000; + +/* DEFINE PHYSICAL ADDRESSES */ + +unsigned char *gfx_phys_regptr = (unsigned char *)0x40000000; +unsigned char *gfx_phys_fbptr = (unsigned char *)0x40800000; +unsigned char *gfx_phys_vidptr = (unsigned char *)0x40010000; +unsigned char *gfx_phys_vipptr = (unsigned char *)0x40015000; + +/* HEADER FILE FOR GRAPHICS REGISTER DEFINITIONS + * This contains only constant definitions, so it should be able to be + * included in any software project as is. + */ +#include "gfx_regs.h" /* graphics register definitions */ + +/* HEADER FILE FOR REGISTER ACCESS MACROS + * This file contains the definitions of the WRITE_REG32 and similar macros + * used by the Durango routines to access the hardware. The file assumes + * that the environment can handle 32-bit pointer access. If this is not + * the case, or if there are special requirements, then this header file + * should not be included and the project must define the macros itself. + * (A project may define WRITE_REG32 to call a routine, for example). + */ +#include "gfx_defs.h" /* register access macros */ + +/* IO MACROS AND ROUTINES + * These macros must be defined before the initialization or I2C + * routines will work properly. + */ + +#if defined(OS_WIN32) /* For Windows */ + +/* VSA II CALL */ + +void +gfx_msr_asm_read(unsigned short msrReg, unsigned long msrAddr, + unsigned long *ptrHigh, unsigned long *ptrLow) +{ + unsigned long temp1, temp2; + + _asm { + mov dx, 0x0AC1C + mov eax, 0x0FC530007 + out dx, eax + add dl, 2 + mov ecx, msrAddr + mov cx, msrReg + in ax, dx; + ;EDX:EAX will contain MSR contents. + mov temp1, edx + mov temp2, eax + } + + *ptrHigh = temp1; + *ptrLow = temp2; +} + +void +gfx_msr_asm_write(unsigned short msrReg, unsigned long msrAddr, + unsigned long *ptrHigh, unsigned long *ptrLow) +{ + unsigned long temp1 = *ptrHigh; + unsigned long temp2 = *ptrLow; + + _asm { + mov dx, 0x0AC1C + mov eax, 0x0FC530007 + out dx, eax i + add dl, 2 + ;ECX contains msrAddr | msrReg + mov ecx, msrAddr + mov cx, msrReg + ; + mov ebx, temp1 + + ; + mov eax, temp2 + ; + mov esi, 0 + ; + mov edi, 0 + ;MSR is written at this point + out dx, ax + } +} + +unsigned char +gfx_inb(unsigned short port) +{ + unsigned char data; + + _asm { + pushf + mov dx, port + in al, dx + mov data, al + popf + } + return (data); +} + +unsigned short +gfx_inw(unsigned short port) +{ + unsigned short data; + + _asm { + pushf + mov dx, port + in ax, dx + mov data, ax + popf + } + return (data); +} + +unsigned long +gfx_ind(unsigned short port) +{ + unsigned long data; + + _asm { + pushf + mov dx, port + in eax, dx + mov data, eax + popf + } + return (data); +} + +void +gfx_outb(unsigned short port, unsigned char data) +{ + _asm { + pushf + mov al, data + mov dx, port + out dx, al + popf + } +} + +void +gfx_outw(unsigned short port, unsigned short data) +{ + _asm { + pushf + mov ax, data + mov dx, port + out dx, ax + popf + } +} + +void +gfx_outd(unsigned short port, unsigned long data) +{ + _asm { + pushf + mov eax, data + mov dx, port + out dx, eax + popf + } +} + +#elif defined(OS_VXWORKS) || defined (OS_LINUX) /* VxWorks and Linux */ + +extern unsigned long amd_asm_msr_vsa_rd(unsigned long, unsigned long *, + unsigned long *); +extern unsigned long amd_asm_msr_vsa_wr(unsigned long, unsigned long, + unsigned long); + +void +gfx_msr_asm_read(unsigned short msrReg, unsigned long msrAddr, + unsigned long *ptrHigh, unsigned long *ptrLow) +{ + unsigned long addr, val1, val2; + + addr = msrAddr | (unsigned long)msrReg; + amd_asm_msr_vsa_rd(addr, &val2, &val1); + *ptrHigh = val2; + *ptrLow = val1; +} + +void +gfx_msr_asm_write(unsigned short msrReg, unsigned long msrAddr, + unsigned long *ptrHigh, unsigned long *ptrLow) +{ + unsigned long addr, val1, val2; + + val2 = *ptrHigh; + val1 = *ptrLow; + addr = (msrAddr & 0xFFFF0000) | (unsigned long)msrReg; + amd_asm_msr_vsa_wr(addr, val2, val1); +} + +unsigned char +gfx_inb(unsigned short port) +{ + unsigned char value; + __asm__ volatile ("inb %1,%0":"=a" (value):"d"(port)); + + return value; +} + +unsigned short +gfx_inw(unsigned short port) +{ + unsigned short value; + __asm__ volatile ("in %1,%0":"=a" (value):"d"(port)); + + return value; +} + +unsigned long +gfx_ind(unsigned short port) +{ + unsigned long value; + __asm__ volatile ("inl %1,%0":"=a" (value):"d"(port)); + + return value; +} + +void +gfx_outb(unsigned short port, unsigned char data) +{ + __asm__ volatile ("outb %0,%1"::"a" (data), "d"(port)); +} + +void +gfx_outw(unsigned short port, unsigned short data) +{ + __asm__ volatile ("out %0,%1"::"a" (data), "d"(port)); +} + +void +gfx_outd(unsigned short port, unsigned long data) +{ + __asm__ volatile ("outl %0,%1"::"a" (data), "d"(port)); +} + +#elif defined(XFree86Server) + +#include +#include +#define INB(port) inb(port) +#define INW(port) inw(port) +#define IND(port) inl(port) +#define OUTB(port,data) outb(port, data) +#define OUTW(port,data) outw(port, data) +#define OUTD(port,data) outl(port, data) + +unsigned char gfx_inb(unsigned short port); +unsigned short gfx_inw(unsigned short port); +unsigned long gfx_ind(unsigned short port); +void gfx_outb(unsigned short port, unsigned char data); +void gfx_outw(unsigned short port, unsigned short data); +void gfx_outd(unsigned short port, unsigned long data); + +unsigned char +gfx_inb(unsigned short port) +{ + return inb(port); +} + +unsigned short +gfx_inw(unsigned short port) +{ + return inw(port); +} + +unsigned long +gfx_ind(unsigned short port) +{ + return inl(port); +} + +void +gfx_outb(unsigned short port, unsigned char data) +{ + outb(port, data); +} + +void +gfx_outw(unsigned short port, unsigned short data) +{ + outw(port, data); +} + +void +gfx_outd(unsigned short port, unsigned long data) +{ + outl(port, data); +} + +/*----------------------------------------------------------------- + * gfx_msr_asm_read + * Read the contents of a 64 bit MSR into address pointers + *-----------------------------------------------------------------*/ + +#define gfx_msr_asm_read(msr,adr,high,low) \ + __asm__ __volatile__( \ + " mov $0x0AC1C, %%edx\n" \ + " mov $0xFC530007, %%eax\n" \ + " out %%eax,%%dx\n" \ + " add $2,%%dl\n" \ + " in %%dx, %%ax" \ + : "=a" (*(low)), "=d" (*(high)) \ + : "c" (msr | adr)) + +/*----------------------------------------------------------------- + * gfx_msr_asm_write + * Write the contents of address pointers to a MSR. + *-----------------------------------------------------------------*/ + +#define gfx_msr_asm_write(msr,adr,high,low) \ + { int d0, d1, d2, d3, d4; \ + __asm__ __volatile__( \ + " mov $0x0AC1C, %%edx\n" \ + " mov $0xFC530007, %%eax\n" \ + " out %%eax,%%dx\n" \ + " add $2,%%dl\n" \ + " mov %6, %1\n" \ + " mov %7, %0\n" \ + " mov %5, %4\n" \ + " xor %3, %3\n" \ + " xor %2, %2\n" \ + " out %%ax, %%dx" \ + : "=a" (d0), "=b" (d1), "=&D" (d2), "=&S" (d3), "=c" (d4) \ + : "2" (msr | adr), "3" (*(high)), "4" (*(low))); \ + } + +#else /* else nothing */ + +unsigned char +gfx_inb(unsigned short port) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ + return (0); +} + +unsigned short +gfx_inw(unsigned short port) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ + return (0); +} + +unsigned long +gfx_ind(unsigned short port) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ + return (0); +} + +void +gfx_outb(unsigned short port, unsigned char data) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ +} + +void +gfx_outw(unsigned short port, unsigned short data) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ +} + +void +gfx_outd(unsigned short port, unsigned long data) +{ + /* ADD OS SPECIFIC IMPLEMENTATION */ +} +#endif + +#ifndef XFree86Server +#define INB(port) gfx_inb(port) +#define INW(port) gfx_inw(port) +#define IND(port) gfx_ind(port) +#define OUTB(port, data) gfx_outb(port, data) +#define OUTW(port, data) gfx_outw(port, data) +#define OUTD(port, data) gfx_outd(port, data) +#endif + +/* INITIALIZATION ROUTINES + * These routines are used during the initialization of the driver to + * perform such tasks as detecting the type of CPU and video hardware. + * The routines require the use of IO, so the above IO routines need + * to be implemented before the initialization routines will work + * properly. + */ + +#include "gfx_init.c" + +/* INCLUDE MSR ACCESS ROUTINES */ + +#include "gfx_msr.c" + +/* INCLUDE GRAPHICS ENGINE ROUTINES + * These routines are used to program the 2D graphics accelerator. If + * the project does not use graphics acceleration (direct frame buffer + * access only), then this file does not need to be included. + */ +#include "gfx_rndr.c" /* graphics engine routines */ + +/* INCLUDE DISPLAY CONTROLLER ROUTINES + * These routines are used if the display mode is set directly. If the + * project uses VGA registers to set a display mode, then these files + * do not need to be included. + */ +#include "gfx_mode.h" /* display mode tables */ +#include "gfx_disp.c" /* display controller routines */ + +/* INCLUDE VIDEO OVERLAY ROUTINES + * These routines control the video overlay hardware. + */ +#include "gfx_vid.c" /* video overlay routines */ + +/* VIDEO PORT AND VIDEO DECODER ROUTINES + * These routines rely on the I2C routines. + */ +#include "gfx_vip.c" /* video port routines */ +#include "gfx_dcdr.c" /* video decoder routines */ + +/* I2C BUS ACCESS ROUTINES + * These routines are used by the video decoder and possibly an + * external TV encoer. + */ +#include "gfx_i2c.c" /* I2C bus access routines */ + +/* TV ENCODER ROUTINES + * This file does not need to be included if the system does not + * support TV output. + */ +#include "gfx_tv.c" /* TV encoder routines */ + +/* VGA ROUTINES + * This file is used if setting display modes using VGA registers. + */ +#include "gfx_vga.c" /* VGA routines */ + +/* END OF FILE */ --- xc/programs/Xserver/hw/xfree86/drivers/amd/cim/cim_version.h 1969-12-31 17:00:00.000000000 -0700 +++ xc.new/programs/Xserver/hw/xfree86/drivers/amd/cim/cim_version.h 2005-12-14 11:38:18.000000000 -0700 @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2005 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * */ +/* + * */ +/* + * Cimarron Version information + * */ + +#define CIMARRON_REVISION 30103 \ No newline at end of file --- xc/programs/Xserver/hw/xfree86/drivers/amd/cim/cim_defs.h 1969-12-31 17:00:00.000000000 -0700 +++ xc.new/programs/Xserver/hw/xfree86/drivers/amd/cim/cim_defs.h 2005-12-14 11:39:42.000000000 -0700 @@ -0,0 +1,734 @@ +/* + * Copyright (c) 2005 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * */ +/* + * */ +/* + * Cimarron hardware access macros. + * */ + +#ifndef _cim_defs_h +#define _cim_defs_h + +/*-----------------------------------------*/ +/* MEMORY ACCESS MACROS */ +/*-----------------------------------------*/ + +#ifndef CIMARRON_EXCLUDE_REGISTER_ACCESS_MACROS + +#define READ_GP32(offset) \ + (*(volatile unsigned long *)(cim_gp_ptr + (offset))) + +#define READ_REG32(offset) \ + (*(volatile unsigned long *)(cim_vg_ptr + (offset))) + +#define READ_FB32(offset) \ + (*(volatile unsigned long *)(cim_fb_ptr + (offset))) + +#define WRITE_GP32(offset, value) \ + (*(volatile unsigned long *)(cim_gp_ptr + (offset))) = (value) + +#define WRITE_REG32(offset, value) \ + (*(volatile unsigned long *)(cim_vg_ptr + (offset))) = (value) + +#define WRITE_COMMAND32(offset, value) \ + (*(unsigned long *)(cim_cmd_ptr + (offset))) = (value) + +#define WRITE_COMMAND8(offset, value) \ + (*(unsigned char *)(cim_cmd_ptr + (offset))) = (value) + +#define WRITE_FB32(offset, value) \ + (*(unsigned long *)(cim_fb_ptr + (offset))) = (value) + +#define READ_VID32(offset) \ + (*(volatile unsigned long *)(cim_vid_ptr + (offset))) + +#define WRITE_VID32(offset, value) \ + (*(volatile unsigned long *)(cim_vid_ptr + (offset))) = (value) + +#define READ_VIP32(offset) \ + (*(volatile unsigned long *)(cim_vip_ptr + (offset))) + +#define WRITE_VIP32(offset, value) \ + (*(volatile unsigned long *)(cim_vip_ptr + (offset))) = (value) + +#define READ_VOP32(offset) \ + (*(volatile unsigned long *)(cim_vid_ptr + (offset))) + +#define WRITE_VOP32(offset, value) \ + (*(volatile unsigned long *)(cim_vid_ptr + (offset))) = (value) + +#endif + +/*-----------------------------------------*/ +/* GP POLLING MACROS */ +/*-----------------------------------------*/ + +#define GP3_WAIT_WRAP(variable) \ + while(((variable = READ_GP32 (GP3_CMD_READ)) > gp3_cmd_current) || \ + (variable <= (gp3_cmd_top + GP3_BLT_COMMAND_SIZE + GP3_BLT_COMMAND_SIZE + 96))) + +#define GP3_WAIT_PRIMITIVE(variable) \ + while (((variable = READ_GP32 (GP3_CMD_READ)) > gp3_cmd_current) && \ + (variable <= (gp3_cmd_next + 96))) + +#define GP3_WAIT_BUSY \ + while(READ_GP32 (GP3_BLT_STATUS) & GP3_BS_BLT_BUSY) + +#define GP3_WAIT_PENDING \ + while(READ_GP32 (GP3_BLT_STATUS) & GP3_BS_BLT_PENDING) + +/*-----------------------------------------------------------------*/ +/* MSR MACROS */ +/* These macros facilitate interaction with the model specific */ +/* registers in GeodeLX. There are two included methods, direct */ +/* access using the rdmsr and wrmsr opcodes and an indirect method */ +/* using VSAII. */ +/*-----------------------------------------------------------------*/ + +#ifdef CIMARRON_INCLUDE_MSR_MACROS + +#if CIMARRON_MSR_DIRECT_ASM + +/*----------------------------------------------------------------- + * MSR_READ + * Read the contents of a 64 bit MSR into a data structure + *-----------------------------------------------------------------*/ + +#define MSR_READ(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \ + unsigned long data_high, data_low; \ + _asm { mov ecx, msr_add } \ + _asm { rdmsr } \ + _asm { mov data_high, edx } \ + _asm { mov data_low, eax } \ + \ + ((Q_WORD *)(data64_ptr))->high = data_high; \ + ((Q_WORD *)(data64_ptr))->low = data_low; \ +} + +/*----------------------------------------------------------------- + * MSR_WRITE + * Write the contents of a 64 bit data structure to a MSR. + *-----------------------------------------------------------------*/ + +#define MSR_WRITE(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \ + unsigned long data_high, data_low; \ + \ + data_high = ((Q_WORD *)(data64_ptr))->high; \ + data_low = ((Q_WORD *)(data64_ptr))->low; \ + \ + _asm { mov ecx, msr_add } \ + _asm { mov edx, data_high } \ + _asm { mov eax, data_low } \ + _asm { wrmsr } \ +} + +#elif CIMARRON_MSR_VSA_IO + +/*----------------------------------------------------------------- + * MSR_READ + * Read the contents of a 64 bit MSR into a data structure + *-----------------------------------------------------------------*/ + +#define MSR_READ(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \ + unsigned long data_high, data_low; \ + \ + _asm { mov dx, 0x0AC1C } \ + _asm { mov eax, 0x0FC530007 } \ + _asm { out dx, eax } \ + \ + _asm { add dl, 2 } \ + _asm { mov ecx, msr_add } \ + _asm { in ax, dx } \ + _asm { mov data_high, edx } \ + _asm { mov data_low, eax } \ + \ + ((Q_WORD *)(data64_ptr))->high = data_high; \ + ((Q_WORD *)(data64_ptr))->low = data_low; \ +} + +/*----------------------------------------------------------------- + * MSR_WRITE + * Write the contents of a 64 bit data structure to a MSR. + *-----------------------------------------------------------------*/ + +#define MSR_WRITE(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long msr_add = (unsigned long)(msr_reg) | (unsigned long)(device_add); \ + unsigned long data_high, data_low; \ + \ + data_high = ((Q_WORD *)(data64_ptr))->high; \ + data_low = ((Q_WORD *)(data64_ptr))->low; \ + \ + _asm { mov dx, 0x0AC1C } \ + _asm { mov eax, 0x0FC530007 } \ + _asm { out dx, eax } \ + \ + _asm { add dl, 2 } \ + _asm { mov ecx, msr_add } \ + _asm { mov ebx, data_high } \ + _asm { mov eax, data_low } \ + \ + _asm { mov esi, 0 } \ + _asm { mov edi, 0 } \ + _asm { out dx, ax } \ +} + +#elif CIMARRON_MSR_ABSTRACTED_ASM + +/*----------------------------------------------------------------- + * MSR_READ + * Read the contents of a 64 bit MSR into a data structure + *-----------------------------------------------------------------*/ + +#define MSR_READ(msr,adr,val) \ + __asm__ __volatile__( \ + " mov $0x0AC1C, %%edx\n" \ + " mov $0xFC530007, %%eax\n" \ + " out %%eax,%%dx\n" \ + " add $2,%%dl\n" \ + " in %%dx, %%ax" \ + : "=a" ((val)->low), "=d" ((val)->high) \ + : "c" (msr | adr)) + +/*----------------------------------------------------------------- + * MSR_WRITE + * Write the contents of a 64 bit data structure to a MSR. + *-----------------------------------------------------------------*/ + +#define MSR_WRITE(msr,adr,val) \ + { int d0, d1, d2, d3, d4; \ + __asm__ __volatile__( \ + " mov $0x0AC1C, %%edx\n" \ + " mov $0xFC530007, %%eax\n" \ + " out %%eax,%%dx\n" \ + " add $2,%%dl\n" \ + " mov %5, %4\n" \ + " mov 0(%6), %1\n" \ + " mov 4(%6), %0\n" \ + " xor %3, %3\n" \ + " xor %2, %2\n" \ + " out %%ax, %%dx" \ + : "=a" (d0), "=b" (d1), "=&D" (d2), "=&S" (d3), "=c" (d4) \ + : "2" (msr | adr), "3" (val)); \ + } + +#elif CIMARRON_MSR_KERNEL_ROUTINE + +#include "asm/msr.h" + +/*----------------------------------------------------------------- + * MSR_READ + * Read the contents of a 64 bit MSR into a data structure + *-----------------------------------------------------------------*/ + +#define MSR_READ(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long addr, val1, val2; \ + \ + addr = device_add | msr_reg; \ + rdmsr (addr, val1, val2); \ + \ + ((Q_WORD *)(data64_ptr))->high = val2; \ + ((Q_WORD *)(data64_ptr))->low = val1; \ +} + +/*----------------------------------------------------------------- + * MSR_WRITE + * Read the contents of a 64 bit data structure to a MSR. + *-----------------------------------------------------------------*/ + +#define MSR_WRITE(msr_reg, device_add, data64_ptr) \ +{ \ + unsigned long addr, val1, val2; \ + \ + val2 = ((Q_WORD *)(data64_ptr))->high; \ + val1 = ((Q_WORD *)(data64_ptr))->low; \ + \ + addr = (device_add & 0xFFFF0000) | (unsigned long)msr_reg; \ + wrmsr(addr, val1, val2); \ +} + +#endif + +#endif /* #ifdef CIMARRON_INCLUDE_MSR_MACROS */ + +/*-----------------------------------------------------------------*/ +/* STRING MACROS */ +/* These macros are included to facilitate the optimization of */ +/* routines that write or copy large amounts of data. Two vesions */ +/* of these macros are included. One is intended for operating */ +/* systems that allow the use of inline assembly, while the other */ +/* is a pure C implementation for stricter operating systems. */ +/*-----------------------------------------------------------------*/ + +#ifdef CIMARRON_INCLUDE_STRING_MACROS + +#if CIMARRON_OPTIMIZE_ASSEMBLY + +/*----------------------------------------------------------------- + * WRITE_COMMAND_STRING32 + * Write a series of DWORDs to the current command buffer offset + *-----------------------------------------------------------------*/ + +#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \ +{ \ + _asm { cld } \ + _asm { mov edi, cim_cmd_ptr } \ + _asm { add edi, offset } \ + _asm { mov esi, dataptr } \ + _asm { add esi, dataoffset } \ + _asm { mov ecx, dword_count } \ + _asm { rep movsd } \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_STRING32 + * Write a series of DWORDS to video memory. + *-----------------------------------------------------------------*/ + +#define WRITE_FB_STRING32(offset, dataptr, dword_count) \ +{ \ + unsigned long temp = (unsigned long)(dataptr); \ + _asm { cld } \ + _asm { mov edi, cim_fb_ptr } \ + _asm { add edi, offset } \ + _asm { mov esi, temp } \ + _asm { mov ecx, dword_count } \ + _asm { rep movsd } \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_CONSTANT + * Write a constant DWORD to multiple video memory addresses + *-----------------------------------------------------------------*/ + +#define WRITE_FB_CONSTANT(offset, value, dword_count) \ +{ \ + unsigned long outptr = (unsigned long)cim_fb_ptr + offset; \ + unsigned long dwords = dword_count; \ + _asm { cld } \ + _asm { mov edi, outptr } \ + _asm { mov eax, value } \ + _asm { mov ecx, dwords } \ + _asm { rep stosd } \ +} + +/*----------------------------------------------------------------- + * WRITE_HOST_SOURCE_STRING32 + * Write a series of DWORDs to the GP host source register + *-----------------------------------------------------------------*/ + +#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \ +{ \ + _asm { cld } \ + _asm { mov edi, cim_gp_ptr } \ + _asm { add edi, GP3_HST_SRC_RANGE } \ + _asm { mov esi, dataptr } \ + _asm { add esi, dataoffset } \ + _asm { mov ecx, dword_count } \ + _asm { rep movsd } \ +} + +#elif CIMARRON_OPTIMIZE_FORLOOP + +/*----------------------------------------------------------------- + * WRITE_COMMAND_STRING32 + * Write a series of DWORDs to the current command buffer offset + *-----------------------------------------------------------------*/ + +#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempdata = (unsigned long)dataptr + (dataoffset); \ + unsigned long byte_off = 0; \ + for (i = 0; i < dword_count; i++, byte_off += 4) \ + WRITE_COMMAND32 ((offset) + byte_off, *((unsigned long *)(tempdata + byte_off))); \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_STRING32 + * Write a series of DWORDS to video memory. + *-----------------------------------------------------------------*/ + +#define WRITE_FB_STRING32(offset, dataptr, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempdata = (unsigned long)dataptr; \ + unsigned long byte_off = 0; \ + for (i = 0; i < dword_count; i++, byte_off += 4) \ + WRITE_FB32 ((offset) + byte_off, *((unsigned long *)(tempdata + byte_off))); \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_CONSTANT + * Write a constant DWORD to multiple video memory addresses + *-----------------------------------------------------------------*/ + +#define WRITE_FB_CONSTANT(offset, value, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempoffset = offset; \ + for (i = 0; i < dword_count; i++, tempoffset += 4) \ + WRITE_FB32 (tempoffset, value); \ +} + +/*----------------------------------------------------------------- + * WRITE_HOST_SOURCE_STRING32 + * Write a series of DWORDs to the GP host source register + *-----------------------------------------------------------------*/ + +#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempdata = (unsigned long)dataptr + (dataoffset); \ + unsigned long byte_off = 0; \ + for (i = 0; i < dword_count; i++, byte_off += 4) \ + WRITE_GP32 (byte_off + GP3_HST_SRC_RANGE, *((unsigned long *)(tempdata + byte_off))); \ +} + +#elif CIMARRON_OPTIMIZE_ABSTRACTED_ASM + +#define move_dw(d,s,n) \ + __asm__ __volatile__( \ + " rep\n" \ + " movsl\n" \ + : "=&c" (d0), "=&S" (d1), "=&D" (d2) \ + : "0" (n), "1" ((const char *)s), "2" ((char *)d) \ + : "memory") + +/*----------------------------------------------------------------- + * WRITE_COMMAND_STRING32 + * Write a series of DWORDs to the current command buffer offset + *-----------------------------------------------------------------*/ + +#define WRITE_COMMAND_STRING32(offset, dataptr, dataoffset, dword_count) \ +{ \ + int d0, d1, d2; \ + move_dw (cim_cmd_ptr+ ((unsigned long)(offset)), \ + ((unsigned long)(dataptr)+(dataoffset)), \ + dword_count); \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_STRING32 + * Write a series of DWORDS to video memory. + *-----------------------------------------------------------------*/ + +#define WRITE_FB_STRING32(offset, dataptr, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempdata = (unsigned long)dataptr; \ + unsigned long byte_off = 0; \ + for (i = 0; i < dword_count; i++, byte_off += 4) \ + WRITE_FB32 ((offset) + byte_off, *((unsigned long *)(tempdata + byte_off))); \ +} + +/*----------------------------------------------------------------- + * WRITE_FB_CONSTANT + * Write a constant DWORD to multiple video memory addresses + *-----------------------------------------------------------------*/ + +#define WRITE_FB_CONSTANT(offset, value, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempoffset = offset; \ + for (i = 0; i < dword_count; i++, tempoffset += 4) \ + WRITE_FB32 (tempoffset, value); \ +} + +/*----------------------------------------------------------------- + * WRITE_HOST_SOURCE_STRING32 + * Write a series of DWORDs to the GP host source register + *-----------------------------------------------------------------*/ + +#define WRITE_HOST_SOURCE_STRING32(dataptr, dataoffset, dword_count) \ +{ \ + unsigned long i; \ + unsigned long tempdata = (unsigned long)dataptr + (dataoffset); \ + unsigned long byte_off = 0; \ + for (i = 0; i < dword_count; i++, byte_off += 4) \ + WRITE_GP32 (byte_off + GP3_HST_SRC_RANGE, *((unsigned long *)(tempdata + byte_off))); \ +} + +#endif + +#endif /* #ifdef CIMARRON_INCLUDE_STRING_MACROS */ + +/*----------------------------------------------------------------- + * WRITE_COMMAND_STRING8 + * Write a series of bytes to the current command buffer offset + *-----------------------------------------------------------------*/ + +#define WRITE_COMMAND_STRING8(offset, dataptr, dataoffset, byte_count) \ +{ \ + unsigned long i; \ + unsigned long array = (unsigned long)dataptr + (dataoffset); \ + for (i = 0; i < byte_count; i++) \ + WRITE_COMMAND8 ((offset) + i, *((unsigned char *)(array + i))); \ +} + +/*----------------------------------------------------------------- + * WRITE_HOST_SOURCE_STRING8 + * Write a series of bytes to the host source register + *-----------------------------------------------------------------*/ + +#define WRITE_HOST_SOURCE_STRING8(dataptr, dataoffset, byte_count) \ +{ \ + unsigned long temp1 = (unsigned long)dataptr + (dataoffset); \ + unsigned long temp2 = 0; \ + unsigned long shift = 0; \ + unsigned long counter; \ + if (byte_count) \ + { \ + for (counter = 0; counter < byte_count; counter++) \ + { \ + temp2 |= ((unsigned long)(*((unsigned char *)(temp1 + counter)))) << shift; \ + shift += 8; \ + } \ + WRITE_GP32 (GP3_HST_SRC, temp2); \ + } \ +} + +/*-----------------------------------------*/ +/* CUSTOM STRING MACROS */ +/*-----------------------------------------*/ + +#ifndef CIMARRON_EXCLUDE_CUSTOM_MACROS + +#define WRITE_CUSTOM_COMMAND_STRING32 WRITE_COMMAND_STRING32 +#define WRITE_CUSTOM_COMMAND_STRING8 WRITE_COMMAND_STRING8 + +#endif + +/*-----------------------------------------*/ +/* IO ACCESS MACROS */ +/*-----------------------------------------*/ + +#ifdef CIMARRON_INCLUDE_IO_MACROS + +#if CIMARRON_IO_DIRECT_ACCESS + +/*------------------------------------------- + * OUTD + * Writes one DWORD to a single I/O address. + *-------------------------------------------*/ + +#define OUTD(port, data) cim_outd(port, data) +void cim_outd (unsigned short port, unsigned long data) +{ + _asm { + pushf + mov eax, data + mov dx, port + out dx, eax + popf + } +} + +/*------------------------------------------- + * IND + * Reads one DWORD from a single I/O address. + *-------------------------------------------*/ + +#define IND(port) cim_ind(port) +unsigned long cim_ind (unsigned short port) +{ + unsigned long data; + _asm { + pushf + mov dx, port + in eax, dx + mov data, eax + popf + } + return data; +} + +/*------------------------------------------- + * OUTW + * Writes one WORD to a single I/O address. + *-------------------------------------------*/ + +#define OUTW(port, data) cim_outw(port, data) +void cim_outw (unsigned short port, unsigned short data) +{ + _asm { + pushf + mov ax, data + mov dx, port + out dx, ax + popf + } +} + +/*------------------------------------------- + * INW + * Reads one WORD from a single I/O address. + *-------------------------------------------*/ + +#define INW(port) cim_inw(port) +unsigned short cim_inw (unsigned short port) +{ + unsigned short data; + _asm { + pushf + mov dx, port + in ax, dx + mov data, ax + popf + } + return data; +} + +/*------------------------------------------- + * OUTB + * Writes one BYTE to a single I/O address. + *-------------------------------------------*/ + +#define OUTB(port, data) cim_outb(port, data) +void cim_outb (unsigned short port, unsigned char data) +{ + _asm { + pushf + mov al, data + mov dx, port + out dx, al + popf + } +} + +/*------------------------------------------- + * INB + * Reads one BYTE from a single I/O address. + *-------------------------------------------*/ + +#define INB(port) cim_inb(port) +unsigned char cim_inb (unsigned short port) +{ + unsigned char data; + _asm { + pushf + mov dx, port + in al, dx + mov data, al + popf + } + return data; +} + +#elif CIMARRON_IO_ABSTRACTED_ASM + +/*------------------------------------------- + * OUTD + * Writes one DWORD to a single I/O address. + *-------------------------------------------*/ + +#define OUTD(port, data) cim_outd(port, data) +void cim_outd (unsigned short port, unsigned long data); +void cim_outd (unsigned short port, unsigned long data) +{ + __asm__ __volatile__ ("outl %0,%w1" : : "a" (data), "Nd" (port)); +} + +/*------------------------------------------- + * IND + * Reads one DWORD from a single I/O address. + *-------------------------------------------*/ + +#define IND(port) cim_ind(port) +unsigned long cim_ind (unsigned short port); +unsigned long cim_ind (unsigned short port) +{ + unsigned long value; + __asm__ __volatile__ ("inl %w1,%0" : "=a" (value) : "Nd" (port) ); + + return value; +} + +/*------------------------------------------- + * OUTW + * Writes one WORD to a single I/O address. + *-------------------------------------------*/ + +#define OUTW(port, data) cim_outw(port, data) +void cim_outw (unsigned short port, unsigned short data); +void cim_outw (unsigned short port, unsigned short data) +{ + __asm__ volatile ("out %0,%1" : : "a" (data),"d" (port)); +} + +/*------------------------------------------- + * INW + * Reads one WORD from a single I/O address. + *-------------------------------------------*/ + +#define INW(port) cim_inw(port) +unsigned short cim_inw (unsigned short port); +unsigned short cim_inw (unsigned short port) +{ + unsigned short value; + __asm__ volatile ("in %1,%0" : "=a" (value) : "d" (port)); + return value; +} + +/*------------------------------------------- + * INB + * Reads one BYTE from a single I/O address. + *-------------------------------------------*/ + +#define INB(port) cim_inb(port) +unsigned char cim_inb(unsigned short port); +unsigned char cim_inb(unsigned short port) +{ + unsigned char value; + __asm__ volatile ("inb %1,%0":"=a" (value):"d"(port)); + + return value; +} + +/*------------------------------------------- + * OUTB + * Writes one BYTE to a single I/O address. + *-------------------------------------------*/ + +#define OUTB(port) cim_outb(port) +void cim_outb(unsigned short port, unsigned char data); +void cim_outb(unsigned short port, unsigned char data) +{ + __asm__ volatile ("outb %0,%1"::"a" (data), "d"(port)); +} + +#endif + +#endif /* CIMARRON_INCLUDE_IO_MACROS */ + +#endif --- xc/programs/Xserver/hw/xfree86/drivers/amd/cim/cim_init.c 1969-12-31 17:00:00.000000000 -0700 +++ xc.new/programs/Xserver/hw/xfree86/drivers/amd/cim/cim_init.c 2005-12-14 11:39:08.000000000 -0700 @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2005 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * */ +/* + * */ +/* + * Cimarron initialization routines. These routines detect a Geode LX and read + * all hardware base addresses. + * */ + +CIMARRON_STATIC unsigned long init_video_base = 0x80000900; + +/*--------------------------------------------------------------------------- + * init_detect_cpu + * + * This routine verifies that a Geode LX is present and returns the processor revision + * ID. For compatibility, this routine can also detect a Redcloud processor. + * bits[24:16] = minor version + * bits[15:8] = major version + * bits[7:0] = type (1 = Geode GX, 2 = Geode LX) + *---------------------------------------------------------------------------*/ + +int init_detect_cpu (unsigned long *cpu_revision, unsigned long *companion_revision) +{ + unsigned long bus, device, i; + unsigned long cpu_bus = 0, cpu_device = 0; + unsigned long address, data; + unsigned long num_bars, function; + int cpu_found, sb_found; + Q_WORD msr_value; + + /* SEARCH THROUGH PCI BUS */ + /* We search the PCI bus for the Geode LX or Geode GX northbridge. */ + /* We then verify that one of its functions is the graphics */ + /* controller and that all bars are filled in. */ + + cpu_found = sb_found = 0; + for (bus = 0; bus < 256; bus++) + { + for (device = 0; device < 21; device++) + { + address = 0x80000000 | (bus << 16) | (device << 11); + + data = init_read_pci (address); + + if (data == PCI_VENDOR_DEVICE_GEODEGX || data == PCI_VENDOR_DEVICE_GEODELX) + { + cpu_found = 1; + cpu_device = device; + cpu_bus = bus; + if (data == PCI_VENDOR_DEVICE_GEODEGX) + *cpu_revision = CIM_CPU_GEODEGX; + else + *cpu_revision = CIM_CPU_GEODELX; + } + else if (data == PCI_VENDOR_5535 || data == PCI_VENDOR_5536) + { + sb_found = 1; + if (data == PCI_VENDOR_5535) + *companion_revision = CIM_SB_5535; + else + *companion_revision = CIM_SB_5536; + } + + if (cpu_found && sb_found) + break; + } + if (device != 21) + break; + } + + if (bus == 256) + { + *cpu_revision = 0; + return CIM_STATUS_CPUNOTFOUND; + } + + msr_init_table(); + + if (msr_read64 (MSR_DEVICE_GEODELX_GLCP, GLCP_REVID, &msr_value) != CIM_STATUS_OK) + { + *cpu_revision = 0; + return CIM_STATUS_CPUNOTFOUND; + } + + *cpu_revision |= ((msr_value.low & 0xF0) << 4) | + ((msr_value.low & 0x0F) << 16); + + if (msr_read64 (MSR_DEVICE_5535_GLCP, GLCP_REVID, &msr_value) != CIM_STATUS_OK) + { + *cpu_revision = 0; + return CIM_STATUS_CPUNOTFOUND; + } + + *companion_revision |= ((msr_value.low & 0xF0) << 4) | + ((msr_value.low & 0x0F) << 16); + + /* SEARCH ALL FUNCTIONS FOR INTEGRATED GRAPHICS */ + + num_bars = 0; + for (function = 0; function < 7; function++) + { + address = 0x80000000 | (cpu_bus << 16) | (cpu_device << 11) | (function << 8); + data = init_read_pci (address); + + if (data == PCI_VENDOR_DEVICE_GEODEGX_VIDEO) + { + num_bars = 4; + break; + } + else if (data == PCI_VENDOR_DEVICE_GEODELX_VIDEO) + { + num_bars = 5; + break; + } + } + + /* VERIFY THAT ALL BARS ARE PRESENT */ + + if (function == 7) + return CIM_STATUS_DISPLAYUNAVAILABLE; + + for (i = 0; i < num_bars; i++) + { + data = init_read_pci (address + 0x10 + (i << 2)); + + if (data == 0 || data == 0xFFFFFFFF) + break; + } + + if (i != num_bars) + return CIM_STATUS_DISPLAYUNAVAILABLE; + + /* SAVE VIDEO BASE ADDRESS FOR FUTURE CALLS */ + + init_video_base = address; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * init_read_pci + * + * This routine reads an unsigned long value from a PCI address. + *---------------------------------------------------------------------------*/ + +unsigned long init_read_pci (unsigned long address) +{ + OUTD (0xCF8, address); + return IND (0xCFC); +} + +/*--------------------------------------------------------------------------- + * init_read_base_addresses + * + * This routine reads all base addresses for the peripherals from the PCI BARs. + *---------------------------------------------------------------------------*/ + +int init_read_base_addresses (INIT_BASE_ADDRESSES *base_addresses) +{ + unsigned long value; + + /* READ ALL BASE ADDRESSES */ + + base_addresses->framebuffer_base = init_read_pci (init_video_base + 0x10); + base_addresses->gp_register_base = init_read_pci (init_video_base + 0x14); + base_addresses->vg_register_base = init_read_pci (init_video_base + 0x18); + base_addresses->df_register_base = init_read_pci (init_video_base + 0x1C); + base_addresses->vip_register_base = init_read_pci (init_video_base + 0x20); + + /* READ FRAME BUFFER SIZE */ + /* The frame buffer size is reported by a VSM in VSA II */ + /* Virtual Register Class = 0x02 */ + /* VG_MEM_SIZE (1MB units) = 0x00 */ + + OUTW (0xAC1C, 0xFC53); + OUTW (0xAC1C, 0x0200); + + value = (unsigned long)(INW (0xAC1E)) & 0xFE; + + base_addresses->framebuffer_size = value << 20; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * init_read_cpu_frequency + * + * This routine returns the current CPU core frequency, in MHz. + *---------------------------------------------------------------------------*/ + +int init_read_cpu_frequency (unsigned long *cpu_frequency) +{ + /* CPU SPEED IS REPORTED BY A VSM IN VSA II */ + /* Virtual Register Class = 0x12 (Sysinfo) */ + /* CPU Speed Register = 0x01 */ + + OUTW (0xAC1C, 0xFC53); + OUTW (0xAC1C, 0x1201); + + *cpu_frequency = (unsigned long)(INW (0xAC1E)); + + return CIM_STATUS_OK; +} --- xc/programs/Xserver/hw/xfree86/drivers/amd/cim/cim_msr.c 1969-12-31 17:00:00.000000000 -0700 +++ xc.new/programs/Xserver/hw/xfree86/drivers/amd/cim/cim_msr.c 2005-12-14 11:38:53.000000000 -0700 @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2005 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * */ +/* + * */ +/* + * Cimarron MSR access routines. These routines allow the user to query the + * state of the GeodeLink Bus and read and write model-specfic registers. + * */ + +/*--------------------------------------------------------------*/ +/* MSR GLOBALS */ +/* These variables hold a local copy of the GeodeLink mapping */ +/* as well as a lookup table for easy device addressing. */ +/*--------------------------------------------------------------*/ + +GEODELINK_NODE gliu_nodes[24]; +GEODELINK_NODE msr_dev_lookup[MSR_DEVICE_EMPTY]; + +#define GET_DEVICE_ID(macrohigh, macrolow) ((macrolow >> 12) & 0xFF) + +/*--------------------------------------------------------------------------- + * msr_init_table + * + * This routine intializes the internal MSR table in Cimarron. This table is + * used for any MSR device accesses. + *---------------------------------------------------------------------------*/ + +int msr_init_table (void) +{ + Q_WORD msr_value; + unsigned int i, j; + int return_value = CIM_STATUS_OK; + + /* CHECK FOR VALID GEODELINK CONFIGURATION */ + /* The CPU and the three GLIUs are assumed to be at known static addresses, so */ + /* we will check the device IDs at these addresses as proof of a valid */ + /* GeodeLink configuration */ + + MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_VAIL, &msr_value); + if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_VAIL) + return_value = CIM_STATUS_ERROR; + + MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU0, &msr_value); + if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU) + return_value = CIM_STATUS_ERROR; + + MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU1, &msr_value); + if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU) + return_value = CIM_STATUS_ERROR; + + MSR_READ (MSR_GEODELINK_CAP, MSR_ADDRESS_GLIU2, &msr_value); + if (GET_DEVICE_ID (msr_value.high, msr_value.low) != MSR_CLASS_CODE_GLIU) + return_value = CIM_STATUS_ERROR; + + if (return_value == CIM_STATUS_OK) + { + /* BUILD LOCAL COPY OF THE GEODELINK BUS */ + + msr_create_geodelink_table (gliu_nodes); + + /* CLEAR TABLE STATUS */ + + for (i = 0; i < MSR_DEVICE_EMPTY; i++) + msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND; + + /* CREATE EASY LOOKUP TABLE FOR FUTURE HARDWARE ACCESS */ + /* Note that MSR_DEVICE_EMPTY is the index after the last */ + /* available device. Also note that we fill in known */ + /* devices before filling in the rest of the table. */ + + msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].address_from_cpu = MSR_ADDRESS_GLIU0; + msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU0].device_id = MSR_DEVICE_PRESENT; + msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].address_from_cpu = MSR_ADDRESS_GLIU1; + msr_dev_lookup[MSR_DEVICE_GEODELX_GLIU1].device_id = MSR_DEVICE_PRESENT; + msr_dev_lookup[MSR_DEVICE_5535_GLIU].address_from_cpu = MSR_ADDRESS_GLIU2; + msr_dev_lookup[MSR_DEVICE_5535_GLIU].device_id = MSR_DEVICE_PRESENT; + msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].address_from_cpu = MSR_ADDRESS_VAIL; + msr_dev_lookup[MSR_DEVICE_GEODELX_VAIL].device_id = MSR_DEVICE_PRESENT; + + for (i = 0; i < MSR_DEVICE_EMPTY; i++) + { + if (msr_dev_lookup[i].device_id == MSR_DEVICE_NOTFOUND) + { + for (j = 0; j < 24; j++) + { + if (gliu_nodes[j].device_id == i) + break; + } + + if (j == 24) + msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND; + else + { + msr_dev_lookup[i].device_id = MSR_DEVICE_PRESENT; + msr_dev_lookup[i].address_from_cpu = gliu_nodes[j].address_from_cpu; + } + } + } + } + else + { + /* ERROR OUT THE GEODELINK TABLES */ + + for (i = 0; i < 24; i++) + { + gliu_nodes[i].address_from_cpu = 0xFFFFFFFF; + gliu_nodes[i].device_id = MSR_DEVICE_EMPTY; + } + + for (i = 0; i < MSR_DEVICE_EMPTY; i++) + { + msr_dev_lookup[i].address_from_cpu = 0xFFFFFFFF; + msr_dev_lookup[i].device_id = MSR_DEVICE_NOTFOUND; + } + } + return return_value; +} + +/*--------------------------------------------------------------------------- + * msr_create_geodelink_table + * + * This routine dumps the contents of the GeodeLink bus into an array of + * 24 GEODELINK_NODE structures. Indexes 0-7 represent ports 0-7 of GLIU0, + * indexes 8-15 represent ports 0-7 of GLIU1 and indexes 16-23 represent + * ports 0-7 of GLIU2 (5535). + *---------------------------------------------------------------------------*/ + +int msr_create_geodelink_table (GEODELINK_NODE *gliu_nodes) +{ + unsigned long mbiu_port_count, reflective; + unsigned long port, index; + unsigned long gliu_count = 0; + int glcp_count = 0; + int usb_count = 0; + int mpci_count = 0; + Q_WORD msr_value; + + /* ALL THREE GLIUS ARE IN ONE ARRAY */ + /* Entries 0-7 contain the port information for GLIU0, entries */ + /* 8-15 contain GLIU1 and 15-23 contain GLIU2. We perform the */ + /* enumeration in two passes. The first simply fills in the */ + /* addresses and class codes at each node. The second pass */ + /* translates the class codes into indexes into Cimarron's device */ + /* lookup table. */ + + /* COUNT GLIU0 PORTS */ + + MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU0, &msr_value); + mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; + + /* FIND REFLECTIVE PORT */ + /* Query the GLIU for the port through which we are communicating. */ + /* We will avoid accesses to this port to avoid a self-reference. */ + + MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU0, &msr_value); + reflective = msr_value.low & WHOAMI_MASK; + + /* SPECIAL CASE FOR PORT 0 */ + /* GLIU0 port 0 is a special case, as it points back to GLIU0. GLIU0 */ + /* responds at address 0x10000xxx, which does not equal 0 << 29. */ + + gliu_nodes[0].address_from_cpu = MSR_ADDRESS_GLIU0; + gliu_nodes[0].device_id = MSR_CLASS_CODE_GLIU; + + /* ENUMERATE ALL PORTS */ + + for (port = 1; port < 8; port++) + { + /* FILL IN ADDRESS */ + + gliu_nodes[port].address_from_cpu = port << 29; + + if (port == reflective) + gliu_nodes[port].device_id = MSR_CLASS_CODE_REFLECTIVE; + else if (port > mbiu_port_count) + gliu_nodes[port].device_id = MSR_CLASS_CODE_UNPOPULATED; + else + { + MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[port].address_from_cpu, &msr_value); + gliu_nodes[port].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low); + } + } + + /* COUNT GLIU1 PORTS */ + + MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU1, &msr_value); + mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; + + /* FIND REFLECTIVE PORT */ + + MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU1, &msr_value); + reflective = msr_value.low & WHOAMI_MASK; + + /* ENUMERATE ALL PORTS */ + + for (port = 0; port < 8; port++) + { + index = port + 8; + + /* FILL IN ADDRESS */ + + gliu_nodes[index].address_from_cpu = (0x02l << 29) + (port << 26); + + if (port == reflective) + gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE; + else if (port > mbiu_port_count) + gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED; + else + { + MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, &msr_value); + gliu_nodes[index].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low); + } + } + + /* COUNT GLIU2 PORTS */ + + MSR_READ (MSR_GLIU_CAP, MSR_ADDRESS_GLIU2, &msr_value); + mbiu_port_count = (msr_value.high >> NUM_PORTS_SHIFT) & 7; + + /* FIND REFLECTIVE PORT */ + + MSR_READ (MSR_GLIU_WHOAMI, MSR_ADDRESS_GLIU2, &msr_value); + reflective = msr_value.low & WHOAMI_MASK; + + /* FILL IN PORT 0 AND 1 */ + /* Port 0 on 5535 is MBIU2. Port 1 is MPCI, but it is referenced at */ + /* a special address. */ + + gliu_nodes[16].address_from_cpu = MSR_ADDRESS_GLIU2; + gliu_nodes[16].device_id = MSR_CLASS_CODE_GLIU; + + gliu_nodes[17].address_from_cpu = MSR_ADDRESS_5535MPCI; + gliu_nodes[17].device_id = MSR_CLASS_CODE_MPCI; + + /* ENUMERATE ALL PORTS */ + + for (port = 2; port < 8; port++) + { + index = port + 16; + + /* FILL IN ADDRESS */ + + gliu_nodes[index].address_from_cpu = + (0x02l << 29) + (0x04l << 26) + (0x02l << 23) + (port << 20); + + if (port == reflective) + gliu_nodes[index].device_id = MSR_CLASS_CODE_REFLECTIVE; + else if (port > mbiu_port_count) + gliu_nodes[index].device_id = MSR_CLASS_CODE_UNPOPULATED; + else + { + MSR_READ (MSR_GEODELINK_CAP, gliu_nodes[index].address_from_cpu, &msr_value); + gliu_nodes[index].device_id = GET_DEVICE_ID (msr_value.high, msr_value.low); + } + } + + /* SECOND PASS - TRANSLATION */ + /* Now that the class codes for each device are stored in the */ + /* array, we walk through the array and translate the class */ + /* codes to table indexes. For class codes that have multiple */ + /* instances, the table indexes are sequential. */ + + for (port = 0; port < 24; port++) + { + /* SPECIAL CASE FOR GLIU UNITS */ + /* A GLIU can be both on another port and on its own port. These */ + /* end up as the same address, but are shown as duplicate nodes in */ + /* the GeodeLink table. */ + + if ((port & 7) == 0) + gliu_count = port >> 3; + + switch (gliu_nodes[port].device_id) + { + /* UNPOPULATED OR REFLECTIVE NODES */ + + case MSR_CLASS_CODE_UNPOPULATED: index = MSR_DEVICE_EMPTY; break; + case MSR_CLASS_CODE_REFLECTIVE: index = MSR_DEVICE_REFLECTIVE; break; + + /* KNOWN CLASS CODES */ + + case MSR_CLASS_CODE_GLIU: index = MSR_DEVICE_GEODELX_GLIU0 + gliu_count++; break; + case MSR_CLASS_CODE_GLCP: index = MSR_DEVICE_GEODELX_GLCP + glcp_count++; break; + case MSR_CLASS_CODE_MPCI: index = MSR_DEVICE_GEODELX_MPCI + mpci_count++; break; + case MSR_CLASS_CODE_USB: index = MSR_DEVICE_5535_USB2 + usb_count++; break; + case MSR_CLASS_CODE_USB2: index = MSR_DEVICE_5536_USB_2_0; break; + case MSR_CLASS_CODE_ATAC: index = MSR_DEVICE_5535_ATAC; break; + case MSR_CLASS_CODE_MDD: index = MSR_DEVICE_5535_MDD; break; + case MSR_CLASS_CODE_ACC: index = MSR_DEVICE_5535_ACC; break; + case MSR_CLASS_CODE_MC: index = MSR_DEVICE_GEODELX_MC; break; + case MSR_CLASS_CODE_GP: index = MSR_DEVICE_GEODELX_GP; break; + case MSR_CLASS_CODE_VG: index = MSR_DEVICE_GEODELX_VG; break; + case MSR_CLASS_CODE_DF: index = MSR_DEVICE_GEODELX_DF; break; + case MSR_CLASS_CODE_FG: index = MSR_DEVICE_GEODELX_FG; break; + case MSR_CLASS_CODE_VIP: index = MSR_DEVICE_GEODELX_VIP; break; + case MSR_CLASS_CODE_AES: index = MSR_DEVICE_GEODELX_AES; break; + case MSR_CLASS_CODE_VAIL: index = MSR_DEVICE_GEODELX_VAIL; break; + default: index = MSR_DEVICE_EMPTY; break; + } + + gliu_nodes[port].device_id = index; + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * msr_create_device_list + * + * This routine dumps a list of all known GeodeLX/5535 devices as well as their + * respective status and address. + *---------------------------------------------------------------------------*/ + +int msr_create_device_list (GEODELINK_NODE *gliu_nodes, int max_devices) +{ + int i, count; + + if (max_devices < MSR_DEVICE_EMPTY) count = max_devices; + else count = MSR_DEVICE_EMPTY; + + for (i = 0; i < count; i++) + { + gliu_nodes[i].address_from_cpu = msr_dev_lookup[i].address_from_cpu; + gliu_nodes[i].device_id = msr_dev_lookup[i].device_id; + } + + return CIM_STATUS_OK; +} + +/*-------------------------------------------------------------------- + * msr_read64 + * + * Performs a 64-bit read from 'msr_register' in device 'device'. 'device' is + * an index into Cimarron's table of known GeodeLink devices. + *-------------------------------------------------------------------*/ + +int msr_read64 (unsigned long device, unsigned long msr_register, + Q_WORD *msr_value) +{ + if (device < MSR_DEVICE_EMPTY) + { + if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT) + { + MSR_READ (msr_register, msr_dev_lookup[device].address_from_cpu, msr_value); + return CIM_STATUS_OK; + } + } + + msr_value->low = msr_value->high = 0; + return CIM_STATUS_DEVNOTFOUND; +} + +/*-------------------------------------------------------------------- + * msr_write64 + * + * Performs a 64-bit write to 'msr_register' in device 'device'. 'device' is + * an index into Cimarron's table of known GeodeLink devices. + *-------------------------------------------------------------------*/ + +int msr_write64 (unsigned long device, unsigned long msr_register, + Q_WORD *msr_value) +{ + if (device < MSR_DEVICE_EMPTY) + { + if (msr_dev_lookup[device].device_id == MSR_DEVICE_PRESENT) + { + MSR_WRITE (msr_register, msr_dev_lookup[device].address_from_cpu, msr_value); + return CIM_STATUS_OK; + } + } + return CIM_STATUS_DEVNOTFOUND; +} + --- xc/programs/Xserver/hw/xfree86/drivers/amd/cim/cim_vip.c 1969-12-31 17:00:00.000000000 -0700 +++ xc.new/programs/Xserver/hw/xfree86/drivers/amd/cim/cim_vip.c 2005-12-14 11:38:01.000000000 -0700 @@ -0,0 +1,1582 @@ +/* + * Copyright (c) 2005 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Neither the name of the Advanced Micro Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * */ +/* + * */ +/* + * Cimarron VIP configuration routines. + * */ + +/*--------------------------------------------------------------------------- + * vip_initialize + * + * This routine initializes the internal module state and prepares the + * module for subsequent VIP orientated activities. + *---------------------------------------------------------------------------*/ + +int vip_initialize(VIPSETMODEBUFFER *buffer) +{ + unsigned long vip_control1, vip_control2, vip_control3; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + vip_control1 = 0; + vip_control2 = 0; + vip_control3 = 0; + + /* CONFIGURE CONTROL WORDS BASED ON MODE STRUCTURE */ + /* Note that some of the input parameters match the register fields */ + /* they represent. */ + + /* STREAM ENABLES */ + + vip_control1 |= buffer->stream_enables; + + /* VIP CAPTURE MODE */ + + vip_control1 |= buffer->operating_mode; + + /* HANDLE PLANAR CAPTURE */ + + if (buffer->flags & VIP_MODEFLAG_PLANARCAPTURE) + { + vip_control1 |= VIP_CONTROL1_PLANAR; + + if (buffer->planar_capture == VIP_420CAPTURE_EVERYLINE) + { + vip_control1 |= VIP_CONTROL1_DISABLE_DECIMATION; + } + else if (buffer->planar_capture == VIP_420CAPTURE_ALTERNATINGFIELDS) + { + if (buffer->flags & VIP_MODEFLAG_PROGRESSIVE) + return CIM_STATUS_INVALIDPARAMS; + + vip_control1 |= VIP_CONTROL1_DISABLE_DECIMATION; + vip_control3 |= VIP_CONTROL3_DECIMATE_EVEN; + } + else if (buffer->planar_capture != VIP_420CAPTURE_ALTERNATINGLINES) + return CIM_STATUS_INVALIDPARAMS; + + /* CONFIGURE THE VIDEO FIFO THRESHOLD BASED ON THE FIFO DEPTH */ + + vip_control2 |= VIP_CONTROL2_DEFAULT_VIDTH_420 << VIP_CONTROL2_VIDTH_SHIFT; + + } + else + { + vip_control2 |= VIP_CONTROL2_DEFAULT_VIDTH_422 << VIP_CONTROL2_VIDTH_SHIFT; + } + + /* CONFIGURE DEFAULT ANCILARRY THRESHOLD AND VIDEO FLUSH VALUES */ + + vip_control2 |= VIP_CONTROL2_DEFAULT_ANCTH << VIP_CONTROL2_ANCTH_SHIFT; + vip_control1 |= VIP_CONTROL1_DEFAULT_ANC_FF << VIP_CONTROL1_ANC_FF_SHIFT; + vip_control1 |= VIP_CONTROL1_DEFAULT_VID_FF << VIP_CONTROL1_VID_FF_SHIFT; + + /* PROGRAM VIP OPTIONS */ + /* The options are sanitized based on the current configuration. */ + + if (buffer->flags & VIP_MODEFLAG_PROGRESSIVE) + vip_control1 |= VIP_CONTROL1_NON_INTERLACED; + else + { + if (buffer->flags & VIP_MODEFLAG_TOGGLEEACHFIELD) + vip_control3 |= VIP_CONTROL3_BASE_UPDATE; + if (buffer->flags & VIP_MODEFLAG_INVERTPOLARITY) + vip_control2 |= VIP_CONTROL2_INVERT_POLARITY; + } + + if ((buffer->operating_mode == VIP_MODE_MSG || + buffer->operating_mode == VIP_MODE_DATA) && + (buffer->flags & VIP_MODEFLAG_FLIPMESSAGEWHENFULL)) + { + vip_control1 |= VIP_CONTROL1_MSG_STRM_CTRL; + } + + else if (buffer->operating_mode == VIP_MODE_VIP2_8BIT || + buffer->operating_mode == VIP_MODE_VIP2_16BIT) + { + if (buffer->flags & VIP_MODEFLAG_ENABLEREPEATFLAG) + vip_control2 |= VIP_CONTROL2_REPEAT_ENABLE; + if (buffer->flags & VIP_MODEFLAG_INVERTTASKPOLARITY) + vip_control3 |= VIP_CONTROL3_TASK_POLARITY; + } + + if (buffer->flags & VIP_MODEFLAG_DISABLEZERODETECT) + vip_control1 |= VIP_CONTROL1_DISABLE_ZERO_DETECT; + if (buffer->flags & VIP_MODEFLAG_10BITANCILLARY) + vip_control2 |= VIP_CONTROL2_ANC10; + + /* WRITE THE CONTROL REGISTERS */ + /* The control registers are kept 'live' to allow separate instances of */ + /* Cimarron to control the VIP hardware. */ + + WRITE_VIP32 (VIP_CONTROL1, vip_control1); + WRITE_VIP32 (VIP_CONTROL2, vip_control2); + WRITE_VIP32 (VIP_CONTROL3, vip_control3); + + /* CONFIGURE 601 PARAMETERS */ + + if (buffer->operating_mode == VIP_MODE_8BIT601 || + buffer->operating_mode == VIP_MODE_16BIT601) + { + vip_update_601_params (&buffer->vip601_settings); + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_update_601_params + * + * This routine configures all aspects of 601 VIP data capture, including + * start and stop timings and input polarities. + *---------------------------------------------------------------------------*/ + +int vip_update_601_params (VIP_601PARAMS *buffer) +{ + unsigned long vip_control3, vip_control1; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + vip_control1 = READ_VIP32 (VIP_CONTROL3); + vip_control3 = READ_VIP32 (VIP_CONTROL3); + + if (buffer->flags & VIP_MODEFLAG_VSYNCACTIVEHIGH) vip_control3 |= VIP_CONTROL3_VSYNC_POLARITY; + else vip_control3 &= ~VIP_CONTROL3_VSYNC_POLARITY; + if (buffer->flags & VIP_MODEFLAG_HSYNCACTIVEHIGH) vip_control3 |= VIP_CONTROL3_HSYNC_POLARITY; + else vip_control3 &= ~VIP_CONTROL3_HSYNC_POLARITY; + + WRITE_VIP32 (VIP_CONTROL3, vip_control3); + WRITE_VIP32 (VIP_601_HORZ_START, buffer->horz_start); + WRITE_VIP32 (VIP_601_VBI_START, buffer->vbi_start); + WRITE_VIP32 (VIP_601_VBI_END, buffer->vbi_start + buffer->vbi_height - 1); + WRITE_VIP32 (VIP_601_EVEN_START_STOP, + buffer->vert_start_even | ((buffer->vert_start_even + buffer->even_height - 1) << 16)); + WRITE_VIP32 (VIP_601_ODD_START_STOP, + buffer->vert_start_odd | ((buffer->vert_start_odd + buffer->odd_height - 1) << 16)); + WRITE_VIP32 (VIP_ODD_FIELD_DETECT, + buffer->odd_detect_start | (buffer->odd_detect_end << 16)); + + /* SPECIAL CASE FOR HORIZONTAL DATA */ + /* 601 horizontal parameters are based on the number of clocks and not the */ + /* number of pixels. */ + + if ((vip_control1 & VIP_CONTROL1_MODE_MASK) == VIP_MODE_16BIT601) + WRITE_VIP32 (VIP_601_HORZ_END, buffer->horz_start + (buffer->width << 1) + 3); + else + WRITE_VIP32 (VIP_601_HORZ_END, buffer->horz_start + buffer->width + 3); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_configure_capture_buffers + * + * This routine configures the base offsets for video, ancillary or message + * mode capture. The input structure can also contain multiple offsets, such + * that the calling application can avoid updating the structure for each flip. + * + * The new buffer addresses are written to the hardware registers although + * they may not be latched immediately. Calling vip_is_buffer_update_latched + * allows the determination of whether the update has occured. + * + * Review the Cimarron VIP API documentation to determine which buffer addresses are + * latched immediately. + *---------------------------------------------------------------------------*/ + +int vip_configure_capture_buffers (int buffer_type, VIPINPUTBUFFER *buffer) +{ + VIPINPUTBUFFER_ADDR *offsets; + unsigned long cur_buffer = buffer->current_buffer; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + if (buffer_type == VIP_BUFFER_A || buffer_type == VIP_BUFFER_601) + { + offsets = &buffer->offsets[VIP_BUFFER_TASK_A]; + + /* SET VIDEO PITCH */ + + WRITE_VIP32 (VIP_TASKA_VID_PITCH, offsets->y_pitch | (offsets->uv_pitch << 16)); + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + { + WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->even_base[cur_buffer]); + WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->odd_base[cur_buffer]); + if (buffer->flags & VIP_INPUTFLAG_VBI) + { + WRITE_VIP32 (VIP_TASKA_VBI_ODD_BASE, offsets->vbi_even_base); + WRITE_VIP32 (VIP_TASKA_VBI_EVEN_BASE, offsets->vbi_odd_base); + } + } + else + { + WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->odd_base[cur_buffer]); + WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->even_base[cur_buffer]); + if (buffer->flags & VIP_INPUTFLAG_VBI) + { + WRITE_VIP32 (VIP_TASKA_VBI_ODD_BASE, offsets->vbi_odd_base); + WRITE_VIP32 (VIP_TASKA_VBI_EVEN_BASE, offsets->vbi_even_base); + } + } + + /* SET 4:2:0 OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_PLANAR) + { + WRITE_VIP32 (VIP_TASKA_U_OFFSET, offsets->odd_uoffset); + WRITE_VIP32 (VIP_TASKA_V_OFFSET, offsets->odd_voffset); + WRITE_VIP32 (VIP_TASKA_U_EVEN_OFFSET, offsets->even_uoffset); + WRITE_VIP32 (VIP_TASKA_V_EVEN_OFFSET, offsets->even_voffset); + } + } + else if (buffer_type == VIP_BUFFER_B) + { + offsets = &buffer->offsets[VIP_BUFFER_TASK_B]; + + /* SET VIDEO PITCH */ + + WRITE_VIP32 (VIP_TASKB_VID_PITCH, offsets->y_pitch | (offsets->uv_pitch << 16)); + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + { + WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->even_base[cur_buffer]); + WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->odd_base[cur_buffer]); + if (buffer->flags & VIP_INPUTFLAG_VBI) + { + WRITE_VIP32 (VIP_TASKB_VBI_ODD_BASE, offsets->vbi_even_base); + WRITE_VIP32 (VIP_TASKB_VBI_EVEN_BASE, offsets->vbi_odd_base); + } + } + else + { + WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->odd_base[cur_buffer]); + WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->even_base[cur_buffer]); + if (buffer->flags & VIP_INPUTFLAG_VBI) + { + WRITE_VIP32 (VIP_TASKB_VBI_ODD_BASE, offsets->vbi_odd_base); + WRITE_VIP32 (VIP_TASKB_VBI_EVEN_BASE, offsets->vbi_even_base); + } + } + + /* SET 4:2:0 OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_PLANAR) + { + WRITE_VIP32 (VIP_TASKB_U_OFFSET, offsets->odd_uoffset); + WRITE_VIP32 (VIP_TASKB_V_OFFSET, offsets->odd_voffset); + } + } + else if (buffer_type == VIP_BUFFER_ANC || buffer_type == VIP_BUFFER_MSG) + { + WRITE_VIP32(VIP_ANC_MSG1_BASE, buffer->ancillaryData.msg1_base); + WRITE_VIP32(VIP_ANC_MSG2_BASE, buffer->ancillaryData.msg2_base); + WRITE_VIP32(VIP_ANC_MSG_SIZE, buffer->ancillaryData.msg_size); + } + else + { + return CIM_STATUS_INVALIDPARAMS; + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_toggle_vip_video_offsets + * + * This routine updates the offsets for video capture. It is a simplified + * version of vip_configure_capture_buffers that is designed to be called from + * interrupt service routines or other buffer flipping applications that + * require low latency. + *---------------------------------------------------------------------------*/ + +int vip_toggle_video_offsets (int buffer_type, VIPINPUTBUFFER *buffer) +{ + unsigned long cur_buffer = buffer->current_buffer; + VIPINPUTBUFFER_ADDR *offsets; + + if (buffer_type == VIP_BUFFER_A) + { + offsets = &buffer->offsets[VIP_BUFFER_TASK_A]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + { + WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->even_base[cur_buffer]); + WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->odd_base[cur_buffer]); + } + else + { + WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->odd_base[cur_buffer]); + WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->even_base[cur_buffer]); + } + } + else if (buffer_type == VIP_BUFFER_B) + { + offsets = &buffer->offsets[VIP_BUFFER_TASK_B]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + { + WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->even_base[cur_buffer]); + WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->odd_base[cur_buffer]); + } + else + { + WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->odd_base[cur_buffer]); + WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->even_base[cur_buffer]); + } + } + else if (buffer_type == VIP_BUFFER_A_ODD) + { + offsets = &buffer->offsets[VIP_BUFFER_TASK_A]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->even_base[cur_buffer]); + else + WRITE_VIP32 (VIP_TASKA_VID_ODD_BASE, offsets->odd_base[cur_buffer]); + } + else if (buffer_type == VIP_BUFFER_A_EVEN) + { + offsets = &buffer->offsets[VIP_BUFFER_TASK_A]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->odd_base[cur_buffer]); + else + WRITE_VIP32 (VIP_TASKA_VID_EVEN_BASE, offsets->even_base[cur_buffer]); + } + else if (buffer_type == VIP_BUFFER_B_ODD) + { + offsets = &buffer->offsets[VIP_BUFFER_TASK_B]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->even_base[cur_buffer]); + else + WRITE_VIP32 (VIP_TASKB_VID_ODD_BASE, offsets->odd_base[cur_buffer]); + } + else if (buffer_type == VIP_BUFFER_B_EVEN) + { + offsets = &buffer->offsets[VIP_BUFFER_TASK_B]; + + /* SET BASE OFFSETS */ + + if (buffer->flags & VIP_INPUTFLAG_INVERTPOLARITY) + WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->odd_base[cur_buffer]); + else + WRITE_VIP32 (VIP_TASKB_VID_EVEN_BASE, offsets->even_base[cur_buffer]); + } + else + return CIM_STATUS_INVALIDPARAMS; + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_capture_state + * + * This routine takes the current control word definition ( stored in locals ) + * adds in the specified state, and writes the control word. + *---------------------------------------------------------------------------*/ + +int vip_set_capture_state (unsigned long state) +{ + unsigned long vip_control1, vip_control3; + + /* UPDATE THE CURRENT CAPTURE MODE */ + + vip_control1 = READ_VIP32 (VIP_CONTROL1); + vip_control3 = READ_VIP32 (VIP_CONTROL3); + vip_control1 &= ~VIP_CONTROL1_RUNMODE_MASK; + vip_control1 |= (state << VIP_CONTROL1_RUNMODE_SHIFT); + + WRITE_VIP32 (VIP_CONTROL1, vip_control1); + + if (state >= VIP_STARTCAPTUREATNEXTLINE) + { + /* WHACK VIP RESET */ + /* The VIP can get confused when switching between capture settings, such as */ + /* between linear and planar. We will thus whack VIP reset when enabling */ + /* capture to ensure a pristine VIP state. */ + + WRITE_VIP32 (VIP_CONTROL1, vip_control1 | VIP_CONTROL1_RESET); + WRITE_VIP32 (VIP_CONTROL1, vip_control1 & ~VIP_CONTROL1_RESET); + WRITE_VIP32 (VIP_CONTROL3, vip_control3 | VIP_CONTROL3_FIFO_RESET); + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_terminate + * + * This routine stops VIP capture and resets the VIP internal state. + *---------------------------------------------------------------------------*/ + +int vip_terminate (void) +{ + unsigned long timeout = 50000; + + /* DISABLE AND CLEAR ALL VIP INTERRUPTS */ + + WRITE_VIP32 (VIP_INTERRUPT, VIP_ALL_INTERRUPTS | (VIP_ALL_INTERRUPTS >> 16)); + + /* DISABLE VIP CAPTURE */ + /* We will try to let the VIP FIFO flush before shutting it down. */ + + WRITE_VIP32 (VIP_CONTROL1, 0); + while (timeout) + { + timeout--; + if (READ_VIP32 (VIP_STATUS) & VIP_STATUS_WRITES_COMPLETE) + break; + } + + /* RESET THE HARDWARE REGISTERS */ + /* Note that we enable VIP reset to allow clock gating to lower VIP */ + /* power consumption. */ + + WRITE_VIP32 (VIP_CONTROL1, VIP_CONTROL1_RESET); + WRITE_VIP32 (VIP_CONTROL3, VIP_CONTROL3_FIFO_RESET); + WRITE_VIP32 (VIP_CONTROL2, 0); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_configure_fifo + * + * This routine sets the desired threshold or flush for the specified fifo. + *---------------------------------------------------------------------------*/ + +int vip_configure_fifo (unsigned long fifo_type, unsigned long fifo_size) +{ + unsigned long vip_control1, vip_control2; + + vip_control1 = READ_VIP32 (VIP_CONTROL1); + vip_control2 = READ_VIP32 (VIP_CONTROL2); + + switch (fifo_type) + { + case VIP_VIDEOTHRESHOLD: + vip_control2 &= ~VIP_CONTROL2_VIDTH_MASK; + vip_control2 |= (fifo_size << VIP_CONTROL2_VIDTH_SHIFT) & VIP_CONTROL2_VIDTH_MASK; + break; + + case VIP_ANCILLARYTHRESHOLD: + vip_control2 &= ~VIP_CONTROL2_ANCTH_MASK; + vip_control2 |= (fifo_size << VIP_CONTROL2_ANCTH_SHIFT) & VIP_CONTROL2_ANCTH_MASK; + break; + + case VIP_VIDEOFLUSH: + vip_control1 &= ~VIP_CONTROL1_VID_FF_MASK; + vip_control1 |= ((fifo_size >> 2) << VIP_CONTROL1_VID_FF_SHIFT) & VIP_CONTROL1_VID_FF_MASK; + break; + + case VIP_ANCILLARYFLUSH: + vip_control1 &= ~VIP_CONTROL1_ANC_FF_MASK; + vip_control1 |= ((fifo_size >> 2) << VIP_CONTROL1_ANC_FF_SHIFT) & VIP_CONTROL1_ANC_FF_MASK; + break; + + default: + return CIM_STATUS_INVALIDPARAMS; + } + + WRITE_VIP32 (VIP_CONTROL1, vip_control1); + WRITE_VIP32 (VIP_CONTROL2, vip_control2); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_interrupt_enable + * + * This routine accepts a mask of interrupts to be enabled/disabled and + * an enable flag. + * + * For each mask match, the interrupt will be enabled or disabled based on + * enable + *---------------------------------------------------------------------------*/ + +int vip_set_interrupt_enable (unsigned long mask, int enable) +{ + /* CHECK IF ANY VALID INTERRUPTS ARE BEING CHANGED */ + + if (mask & VIP_ALL_INTERRUPTS) + { + unsigned long int_enable = READ_VIP32(VIP_INTERRUPT) & 0xFFFF; + + /* SET OR CLEAR THE MASK BITS */ + /* Note that the upper 16-bits of the register are 0 after this */ + /* operation. This prevents us from indadvertently clearing a */ + /* pending interrupt by enabling/disabling another one. */ + + if (enable) int_enable &= ~(mask >> 16); + else int_enable |= (mask >> 16); + + WRITE_VIP32 (VIP_INTERRUPT, int_enable); + } + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_vsync_error + * + * This routine defines a region that is used to determine if the vsync is + * within an acceptable range. This definition is accomplished using + * a count and a vertical window. The count specifies the exact number + * of clocks expected for one field. The window parameters specify the number + * of clocks variation allowed before and after the expected vsync. For + * example, if vertical_count is 1000, window_before is 5 and window_after + * is 12, VSync will be considered valid if it occurs between 995 and 1012 + * clocks after the last VSync. The total window size (window_before + window_after) + * cannot exceed 255. + *---------------------------------------------------------------------------*/ + +int vip_set_vsync_error (unsigned long vertical_count, unsigned long window_before, + unsigned long window_after, int enable) +{ + unsigned long vip_control2 = READ_VIP32 (VIP_CONTROL2); + unsigned long temp; + + if (enable) + { + /* CREATE THE VERTICAL WINDOW */ + /* The VIP uses two counters. The first counter defines the minimum clock count */ + /* before a valid VSync can occur. The second counter starts after the first */ + /* completes and defines the acceptable region of variation. */ + + temp = ((window_before + window_after) << VIP_VSYNC_ERR_WINDOW_SHIFT) & VIP_VSYNC_ERR_WINDOW_MASK; + temp |= (vertical_count - window_before) & VIP_VSYNC_ERR_COUNT_MASK; + + vip_control2 |= VIP_CONTROL2_VERTERROR_ENABLE; + + WRITE_VIP32(VIP_VSYNC_ERR_COUNT, temp); + } + else + { + vip_control2 &= ~VIP_CONTROL2_VERTERROR_ENABLE; + } + WRITE_VIP32 (VIP_CONTROL2, vip_control2); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_max_address_enable + * + * This routine specifies the maximum address to which the the hardware should + * write during data storage. If this value is exceeded an error is generated, + * (this may be monitored using the appropriate interrupt flags - see + * vip_set_interrupt_enable) + *---------------------------------------------------------------------------*/ + +int vip_max_address_enable (unsigned long max_address, int enable) +{ + unsigned long vip_control2 = READ_VIP32 (VIP_CONTROL2); + + if (enable) + { + /* ENABLE THE CONTROL BIT */ + + vip_control2 |= VIP_CONTROL2_ADD_ERROR_ENABLE; + + WRITE_VIP32(VIP_MAX_ADDRESS, max_address & VIP_MAXADDR_MASK); + } + else + { + /* DISABLE DETECTION */ + + vip_control2 &= ~VIP_CONTROL2_ADD_ERROR_ENABLE; + } + WRITE_VIP32 (VIP_CONTROL2, vip_control2); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_loopback_enable + * + * This routine enables/disables internal loopback functionality. When + * loopback is enabled, the VOP outputs are rerouted to the VIP inputs + * internal to the chip. No loopback connector is required. + *---------------------------------------------------------------------------*/ + +int vip_set_loopback_enable(int enable) +{ + unsigned long vip_control2 = READ_VIP32 (VIP_CONTROL2); + + if (enable) vip_control2 |= VIP_CONTROL2_LOOPBACK_ENABLE; + else vip_control2 &= ~VIP_CONTROL2_LOOPBACK_ENABLE; + + WRITE_VIP32 (VIP_CONTROL2, vip_control2); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_configure_genlock + * + * This routine configures genlock functionality. + *---------------------------------------------------------------------------*/ + +int vip_configure_genlock (VIPGENLOCKBUFFER *buffer) +{ + unsigned long vip_control1, vip_control2; + unsigned long unlock, genlk_ctl; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + unlock = READ_REG32 (DC3_UNLOCK); + genlk_ctl = READ_REG32 (DC3_GENLK_CTL); + vip_control1 = READ_VIP32 (VIP_CONTROL1); + vip_control2 = READ_VIP32 (VIP_CONTROL2); + + /* UPDATE VIDEO DETECTION */ + /* These flags are used to indicate the ways in which the VIP signal can */ + /* be considered 'lost'. */ + + vip_control1 &= ~VIP_CONTROL1_VDE_FF_MASK; + vip_control2 &= ~(VIP_CONTROL2_FIELD2VG_MASK | VIP_CONTROL2_SYNC2VG_MASK); + vip_control1 |= buffer->vip_signal_loss; + + /* UPDATE FIELD AND VSYNC INFORMATION */ + /* These flags control how and when the even/odd field and Vsync */ + /* information is communicated to the VG. */ + + vip_control2 |= buffer->field_to_vg; + vip_control2 |= buffer->vsync_to_vg; + + /* ENABLE OR DISABLE GENLOCK TIMEOUT */ + /* Enabling genlock timeout allows the VG to revert to its own sync */ + /* timings when the VIP input is lost. Note that the VIP will not */ + /* know the signal is lost unless the appropriate error detection */ + /* flags have been enabled inside vip_initialize. */ + + if (buffer->enable_timeout) genlk_ctl |= DC3_GC_GENLOCK_TO_ENABLE; + else genlk_ctl &= ~DC3_GC_GENLOCK_TO_ENABLE; + + genlk_ctl &= ~DC3_GC_GENLOCK_SKEW_MASK; + genlk_ctl |= buffer->genlock_skew & DC3_GC_GENLOCK_SKEW_MASK; + + WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32 (DC3_GENLK_CTL, genlk_ctl); + WRITE_VIP32 (VIP_CONTROL1, vip_control1); + WRITE_VIP32 (VIP_CONTROL2, vip_control2); + WRITE_REG32 (DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_genlock_enable + * + * This routine enables/disables genlock inside the VG. + *---------------------------------------------------------------------------*/ + +int vip_set_genlock_enable (int enable) +{ + unsigned long unlock, temp; + + unlock = READ_REG32 (DC3_UNLOCK); + temp = READ_REG32 (DC3_GENLK_CTL); + + if (enable) temp |= DC3_GC_GENLOCK_ENABLE; + else temp &= ~DC3_GC_GENLOCK_ENABLE; + + WRITE_REG32 (DC3_UNLOCK, DC3_UNLOCK_VALUE); + WRITE_REG32 (DC3_GENLK_CTL, temp); + WRITE_REG32 (DC3_UNLOCK, unlock); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_power_characteristics + * + * This routine takes a VIPPOWERBUFFER structure, and selectively sets the + * GeodeLink power and/or Vip clock power states. + *---------------------------------------------------------------------------*/ + +int vip_set_power_characteristics (VIPPOWERBUFFER *buffer) +{ + Q_WORD q_word; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + q_word.low = q_word.high = 0; + + /* ENABLE GEODELINK CLOCK GATING */ + + if (buffer->glink_clock_mode) + q_word.low |= VIP_MSR_POWER_GLINK; + + /* ENABLE VIP CLOCK GATING */ + + if (buffer->vip_clock_mode) + q_word.low |= VIP_MSR_POWER_CLOCK; + + /* WRITE THE NEW VALUE */ + + msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_PM, &q_word); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_priority_characteristics + * + * This routine programs the VIP GeodeLink priority characteristics + *---------------------------------------------------------------------------*/ + +int vip_set_priority_characteristics (VIPPRIORITYBUFFER *buffer) +{ + Q_WORD q_word; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + q_word.low = q_word.high = 0; + + q_word.low |= (buffer->secondary << VIP_MSR_MCR_SECOND_PRIORITY_SHIFT) & VIP_MSR_MCR_SECOND_PRIORITY_MASK; + q_word.low |= (buffer->primary << VIP_MSR_MCR_PRIMARY_PRIORITY_SHIFT) & VIP_MSR_MCR_PRIMARY_PRIORITY_MASK; + q_word.low |= (buffer->pid << VIP_MSR_MCR_PID_SHIFT) & VIP_MSR_MCR_PID_MASK; + + msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_CONFIG, &q_word); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_set_debug_characteristics + * + * This routine configures the debug data that is exposed over the diag bus. + *---------------------------------------------------------------------------*/ + +int vip_set_debug_characteristics (VIPDEBUGBUFFER *buffer) +{ + Q_WORD q_word; + + if (!buffer) + return CIM_STATUS_INVALIDPARAMS; + + q_word.low = q_word.high = 0; + + q_word.high |= (buffer->bist << VIP_MSR_DIAG_BIST_SHIFT) & VIP_MSR_DIAG_BIST_WMASK; + q_word.low |= (buffer->enable_upper ? VIP_MSR_DIAG_MSB_ENABLE : 0x00000000); + q_word.low |= (buffer->select_upper << VIP_MSR_DIAG_SEL_UPPER_SHIFT) & VIP_MSR_DIAG_SEL_UPPER_MASK; + q_word.low |= (buffer->enable_lower ? VIP_MSR_DIAG_LSB_ENABLE : 0x00000000 ); + q_word.low |= (buffer->select_lower << VIP_MSR_DIAG_SEL_LOWER_SHIFT) & VIP_MSR_DIAG_SEL_LOWER_MASK; + + msr_write64 (MSR_DEVICE_GEODELX_VIP, MSR_GEODELINK_DIAG, &q_word); + + return CIM_STATUS_OK; +} + +/*--------------------------------------------------------------------------- + * vip_configure_pages + * + * This routine sets the number of pages, and their offset from each other. + *---------------------------------------------------------------------------*/ + +int vip_configure_pages (int page_count, unsigned long page_offset) +{ + unsigned long vip_control2 = READ_VIP32 (VIP_CONTROL2); + + /* SET THE NEW PAGE COUNT */ + + vip_control2 &= ~VIP_CONTROL2_PAGECNT_MASK; + vip_control2 |= (page_count << VIP_CONTR