/******************************Module*Header*******************************\ * Module Name: hw.h * * All the hardware specific driver file stuff. Parts are mirrored in * 'hw.inc'. * * Copyright (c) 1992-1995 Microsoft Corporation * \**************************************************************************/ // // Private IOCTL definitions for communicating with the Weitek miniport. // // NOTE: These must match the Weitek miniport definitions! // #define IOCTL_VIDEO_GET_BASE_ADDR \ CTL_CODE (FILE_DEVICE_VIDEO, 2048, METHOD_BUFFERED, FILE_ANY_ACCESS) typedef struct _VIDEO_COPROCESSOR_INFORMATION { ULONG CoprocessorID; // 0 == p9000, 1 = p9100 ULONG FrameBufferBase; ULONG CoprocessorBase; } VIDEO_COPROCESSOR_INFORMATION, *PVIDEO_COPROCESSOR_INFORMATION; ////////////////////////////////////////////////////////////////////// // Shared p9000 and p9100 Coproc Registers Address Constant definitions // #define Status 0x80000 //status register #define Wmin 0x80220 //pixel clipping window minimum register #define Wmax 0x80224 //and maximum register #define Woffset 0x80190 //window offset register #define Quad 0x80008 //draw a quadrilateral #define Bitblt 0x80004 //screen to screen blit #define Pixel8 0xE000C //host to screen color pixel transfer #define Pixel1 0xE0080 //host to screen mono pixel transfer w/ expansion #define Pixel1Full 0xE00FC //same as above w/ 32bit wide pixels #define Nextpixel 0x80014 //next pixel #define PatternOrgX 0x80210 //pattern orgin x #define PatternOrgY 0x80214 //pattern orgin y #define PatternRAM 0xE0280 //pattern ram #define Raster 0x80218 //raster register to write #define Metacord 0x81218 //meta-coordinate register #define Xy0 0x81018 //abs screen addr #define Xy1 0x81058 //r/w 16-bit x (hi) #define Xy2 0x81098 // and #define Xy3 0x810D8 // 16-bit y (lo) #define X0 0x81008 //abs screen addr #define X1 0x81048 #define X2 0x81088 #define X3 0x810C8 #define Y0 0x81010 //abs screen addr #define Y1 0x81050 #define Y2 0x81090 #define Y3 0x810D0 #define WoffsetBit 0x00020 //bit to set for coordinates relative //to window offset // // p9000 Coproc Registers Address Constant definitions // #define Foreground 0x80200 //P9000 foreground color register #define Background 0x80204 //P9000 background color register // // p9100 Coproc Registers Address Constant definitions // #define Wmin_b 0x802A0 //byte clipping window minimum register #define Wmax_b 0x802A4 //and maximum register #define Color0 0xE0200 //P9100 color[0] register #define Color1 0xE0204 //P9100 color[1] register #define Color2 0xE0238 //P9100 color[2] register #define Color3 0xE023C //P9100 color[3] register // We try to share as many register constants as we can between the // P9000 and the P9100, so that we don't have to duplicate code. // But the base offset for the registers we used changed somewhat; // we apply this corrector to the I/O base pointer to compensate: #define P9100_BASE_CORRECTION (0x2000L - 0x80000L) ////////////////////////////////////////////////////////////////////// // Shared p9000 and p9100 Coproc Registers bit template definitions // #define BUSY 0x40000000L //busy, but can start quad or bitblit #define QBUSY 0x80000000L //busy, cannot start quad or bitblt #define QUADFAIL 0x10 //QUAD failed, use software to draw this #define MetaRect 0x100 //or with METACORD when entering rectangles #define MetaLine 0x040 //or with METACORD when entering line #define MetaQuad 0x0C0 //or with METACORD when entering quad #define MetaTri 0x080 //or with METACORD when entering triangle // // p9000 Coproc Registers bit template definitions // // For the raster register: #define P9000_ENABLE_PATTERN 0x20000 //enable pattern #define P9000_OVERSIZED 0x10000 //enable oversized mode #define P9000_F 0xff00L #define P9000_B 0xf0f0L #define P9000_S 0xccccL #define P9000_D 0xaaaaL #define P9000_OPAQUE_EXPAND 0xfc30L #define P9000_TRANSPARENT_EXPAND 0xee22L // // p9100 Coproc Registers bit template definitions // // For the raster register: #define P9100_TRANSPARENT_PATTERN 0x20000 //enable transparent pattern #define P9100_OVERSIZED 0x10000 //enable oversized mode #define P9100_PIXEL1_TRANSPARENT 0x08000 //enable pixel1 transparent mode #define P9100_FOUR_COLOR_PATTERN 0x04000 //4 colour pattern (8bpp only) #define P9100_ENABLE_PATTERN 0x02000 //enable pattern #define P9100_P 0x00f0L #define P9100_S 0x00ccL #define P9100_D 0x00aaL #define P9100_OPAQUE_EXPAND P9100_S #define P9100_TRANSPARENT_EXPAND (P9100_S | P9100_PIXEL1_TRANSPARENT) ////////////////////////////////////////////////////////////////////// // Alpha and PowerPC considerations // // Both the Alpha and the PowerPC do not guarantee that I/O to // separate addresses will be executed in order. The Alpha and // PowerPC differ, however, in that the PowerPC guarantees that // output to the same address will be executed in order, while the // Alpha may cache and 'collapse' consecutive output to become only // one output. // // Consequently, we use the following synchronization macros. They // are relatively expensive in terms of performance, so we try to avoid // them whereever possible. // // CP_EIEIO() 'Ensure In-order Execution of I/O' // - Used to flush any pending I/O in situations where we wish to // avoid out-of-order execution of I/O to separate addresses. // // CP_MEMORY_BARRIER() // - Used to flush any pending I/O in situations where we wish to // avoid out-of-order execution or 'collapsing' of I/O to // the same address. On the PowerPC, this will be defined as // a null operation. #if defined(_PPC_) // On PowerPC, CP_MEMORY_BARRIER doesn't do anything. #define CP_EIEIO() MEMORY_BARRIER() #define CP_MEMORY_BARRIER() #else // On Alpha, CP_EIEIO is the same thing as a CP_MEMORY_BARRIER. // On other systems, both CP_EIEIO and CP_MEMORY_BARRIER don't do anything. #define CP_EIEIO() MEMORY_BARRIER() #define CP_MEMORY_BARRIER() MEMORY_BARRIER() #endif ////////////////////////////////////////////////////////////////////// // Access macros: // #define MAX_COORD 0x3fff #define CP_OUT(pjBase, cjOffset, ul) \ WRITE_REGISTER_ULONG((BYTE*) pjBase + (cjOffset), (ULONG) (ul)) #define CP_IN(pjBase, cjOffset) \ READ_REGISTER_ULONG((BYTE*) pjBase + (cjOffset)) // Note that we have to be careful if 'y' is negative that its signed // bits don't get ORed into the 'x' component: #define PACKXY(x, y) (((x) << 16) | ((y) & 0xffff)) #define CP_WAIT(ppdev, pjBase) \ { \ do {CP_EIEIO();} while (CP_IN(pjBase, Status) & BUSY); \ CP_EIEIO(); \ } #define CP_RASTER(ppdev, pjBase, x) \ { \ ASSERTDD(P9000(ppdev) || ((x) & 0x01f00) == 0, \ "Illegal P9100 raster value"); \ CP_OUT(pjBase, Raster, (x)); \ } #define CP_NEXT_PIXELS(ppdev, pjBase, x) \ CP_OUT(pjBase, Nextpixel, (x)); #define CP_START_QUAD(ppdev, pjBase) \ { \ CP_EIEIO(); \ CP_IN(pjBase, Quad); \ CP_EIEIO(); \ } #define CP_START_QUAD_STAT(ppdev, pjBase, stat) \ { \ CP_EIEIO(); \ stat = CP_IN(pjBase, Quad); \ CP_EIEIO(); \ } #define CP_START_QUAD_WAIT(ppdev, pjBase) \ { \ do { \ CP_EIEIO(); \ } while (CP_IN(pjBase, Quad) & QBUSY); \ CP_EIEIO(); \ } #define CP_START_BLT(ppdev, pjBase) \ { \ CP_EIEIO(); \ CP_IN(pjBase, Bitblt); \ CP_EIEIO(); \ } #define CP_START_BLT_WAIT(ppdev, pjBase) \ { \ do { \ CP_EIEIO(); \ } while (CP_IN(pjBase, Bitblt) & QBUSY); \ CP_EIEIO(); \ } #define CP_START_QUAD(ppdev, pjBase) \ { \ CP_EIEIO(); \ CP_IN(pjBase, Quad); \ CP_EIEIO(); \ } #define CP_START_PIXEL8(ppdev, pjBase) \ CP_EIEIO(); #define CP_END_PIXEL8(ppdev, pjBase) \ CP_EIEIO(); #define CP_PIXEL8(ppdev, pjBase, x) \ { \ CP_OUT(pjBase, Pixel8, (x)); \ CP_MEMORY_BARRIER(); \ } #define CP_START_PIXEL1(ppdev, pjBase) \ CP_EIEIO(); #define CP_END_PIXEL1(ppdev, pjBase) \ CP_EIEIO(); #define CP_PIXEL1(ppdev, pjBase, x) \ { \ CP_OUT(pjBase, Pixel1Full, (x)); \ CP_MEMORY_BARRIER(); \ } // Note: 'count' must be pre-decremented by 1 #define CP_PIXEL1_REM(ppdev, pjBase, count, x) \ { \ /* This EIEIO is to ensure we don't get out of */ \ /* order with normal full CP_PIXEL1 writes */ \ CP_EIEIO(); \ CP_OUT(pjBase, Pixel1 + ((count) << 2), (x)); \ } #define CP_PIXEL1_REM_REGISTER(ppdev, pjBase, count)\ ((BYTE*) (pjBase) + Pixel1 + ((count) << 2)) #define CP_PIXEL1_VIA_REGISTER(ppdev, pReg, x) \ { \ /* This EIEIO is to ensure we don't get out of */ \ /* order with normal full CP_PIXEL1 writes */ \ CP_EIEIO(); \ WRITE_REGISTER_ULONG(pReg, (x)); \ } #define CP_PATTERN(ppdev, pjBase, index, x) \ CP_OUT(pjBase, PatternRAM + ((index) << 2), (x)) #define CP_PATTERN_ORGX(ppdev, pjBase, x) \ CP_OUT(pjBase, PatternOrgX, (x)) #define CP_PATTERN_ORGY(ppdev, pjBase, x) \ CP_OUT(pjBase, PatternOrgY, (x)) // #define CP_METALINE(ppdev, pjBase, x, y) \ { \ CP_OUT(pjBase, Metacord | MetaLine, \ PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset));\ CP_MEMORY_BARRIER(); \ } #define CP_METARECT(ppdev, pjBase, x, y) \ { \ CP_OUT(pjBase, Metacord | MetaRect, \ PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset));\ CP_MEMORY_BARRIER(); \ } #define CP_METAQUAD(ppdev, pjBase, x, y) \ { \ CP_OUT(pjBase, Metacord | MetaQuad, \ PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset));\ CP_MEMORY_BARRIER(); \ } #define CP_METATRI(ppdev, pjBase, x, y) \ { \ CP_OUT(pjBase, Metacord | MetaTri, \ PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset));\ CP_MEMORY_BARRIER(); \ } #define CP_WOFFSET(ppdev, pjBase, x, y) \ CP_OUT(pjBase, Woffset, PACKXY((x), (y))) #define CP_WMIN(ppdev, pjBase, x, y) \ CP_OUT(pjBase, P9000(ppdev) ? Wmin : Wmin_b, \ PACKXY(((x) + ppdev->xOffset) * ppdev->cjPel, (y) + ppdev->yOffset)) #define CP_WMAX(ppdev, pjBase, x, y) \ CP_OUT(pjBase, P9000(ppdev) ? Wmax : Wmax_b, \ PACKXY(((x) + ppdev->xOffset + 1) * ppdev->cjPel - 1, (y) + ppdev->yOffset)) #define CP_WLEFT(ppdev, pjBase, x) \ CP_OUT(pjBase, P9000(ppdev) ? Wmin : Wmin_b, \ PACKXY(((x) + ppdev->xOffset) * ppdev->cjPel, 0)) #define CP_WRIGHT(ppdev, pjBase, x) \ CP_OUT(pjBase, P9000(ppdev) ? Wmax : Wmax_b, \ PACKXY(((x) + ppdev->xOffset + 1) * ppdev->cjPel - 1, MAX_COORD)) #define CP_XY0(ppdev, pjBase, x, y) \ CP_OUT(pjBase, Xy0, PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset)) #define CP_XY1(ppdev, pjBase, x, y) \ CP_OUT(pjBase, Xy1, PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset)) #define CP_XY2(ppdev, pjBase, x, y) \ CP_OUT(pjBase, Xy2, PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset)) #define CP_XY3(ppdev, pjBase, x, y) \ CP_OUT(pjBase, Xy3, PACKXY((x) + ppdev->xOffset, (y) + ppdev->yOffset)) #define CP_X0(ppdev, pjBase, x) \ CP_OUT(pjBase, X0, (x) + ppdev->xOffset) #define CP_X1(ppdev, pjBase, x) \ CP_OUT(pjBase, X1, (x) + ppdev->xOffset) #define CP_X2(ppdev, pjBase, x) \ CP_OUT(pjBase, X2, (x) + ppdev->xOffset) #define CP_X3(ppdev, pjBase, x) \ CP_OUT(pjBase, X3, (x) + ppdev->xOffset) #define CP_Y0(ppdev, pjBase, y) \ CP_OUT(pjBase, Y0, (y) + ppdev->yOffset) #define CP_Y1(ppdev, pjBase, y) \ CP_OUT(pjBase, Y1, (y) + ppdev->yOffset) #define CP_Y2(ppdev, pjBase, y) \ CP_OUT(pjBase, Y2, (y) + ppdev->yOffset) #define CP_Y3(ppdev, pjBase, y) \ CP_OUT(pjBase, Y3, (y) + ppdev->yOffset) // #define CP_WOFF_PACKED_XY0(ppdev, pjBase, xy) \ CP_OUT(pjBase, Xy0 | WoffsetBit, (xy)) #define CP_WOFF_PACKED_XY1(ppdev, pjBase, xy) \ CP_OUT(pjBase, Xy1 | WoffsetBit, (xy)) #define CP_WOFF_PACKED_XY2(ppdev, pjBase, xy) \ CP_OUT(pjBase, Xy2 | WoffsetBit, (xy)) #define CP_WOFF_PACKED_XY3(ppdev, pjBase, xy) \ CP_OUT(pjBase, Xy3 | WoffsetBit, (xy)) #define CP_ABS_PACKED_XY0(ppdev, pjBase, xy) \ CP_OUT(pjBase, Xy0, (xy)) #define CP_ABS_PACKED_XY1(ppdev, pjBase, xy) \ CP_OUT(pjBase, Xy1, (xy)) #define CP_ABS_PACKED_XY2(ppdev, pjBase, xy) \ CP_OUT(pjBase, Xy2, (xy)) #define CP_ABS_PACKED_XY3(ppdev, pjBase, xy) \ CP_OUT(pjBase, Xy3, (xy)) // #define CP_ABS_WMIN(ppdev, pjBase, x, y) \ CP_OUT(pjBase, P9000(ppdev) ? Wmin : Wmin_b, \ PACKXY((x) * ppdev->cjPel, (y))) #define CP_ABS_WMAX(ppdev, pjBase, x, y) \ CP_OUT(pjBase, P9000(ppdev) ? Wmax : Wmax_b, \ PACKXY(((x) + 1) * ppdev->cjPel - 1, (y))) #define CP_ABS_WLEFT(ppdev, pjBase, x) \ CP_OUT(pjBase, P9000(ppdev) ? Wmin : Wmin_b, \ PACKXY((x) * ppdev->cjPel, 0)) #define CP_ABS_WRIGHT(ppdev, pjBase, x) \ CP_OUT(pjBase, P9000(ppdev) ? Wmax : Wmax_b, \ PACKXY(((x) + 1) * ppdev->cjPel - 1, MAX_COORD)) #define CP_ABS_METARECT(ppdev, pjBase, x, y) \ { \ CP_OUT(pjBase, Metacord | MetaRect, PACKXY((x), (y)));\ CP_MEMORY_BARRIER(); \ } #define CP_ABS_XY0(ppdev, pjBase, x, y) \ CP_OUT(pjBase, Xy0, PACKXY((x), (y))) #define CP_ABS_XY1(ppdev, pjBase, x, y) \ CP_OUT(pjBase, Xy1, PACKXY((x), (y))) #define CP_ABS_XY2(ppdev, pjBase, x, y) \ CP_OUT(pjBase, Xy2, PACKXY((x), (y))) #define CP_ABS_XY3(ppdev, pjBase, x, y) \ CP_OUT(pjBase, Xy3, PACKXY((x), (y))) #define CP_ABS_PACKED_XY0(ppdev, pjBase, x) \ CP_OUT(pjBase, Xy0, (x)) #define CP_ABS_PACKED_XY1(ppdev, pjBase, x) \ CP_OUT(pjBase, Xy1, (x)) #define CP_ABS_PACKED_XY2(ppdev, pjBase, x) \ CP_OUT(pjBase, Xy2, (x)) #define CP_ABS_PACKED_XY3(ppdev, pjBase, x) \ CP_OUT(pjBase, Xy3, (x)) #define CP_ABS_X0(ppdev, pjBase, y) \ CP_OUT(pjBase, X0, (y)) #define CP_ABS_X1(ppdev, pjBase, y) \ CP_OUT(pjBase, X1, (y)) #define CP_ABS_X2(ppdev, pjBase, y) \ CP_OUT(pjBase, X2, (y)) #define CP_ABS_X3(ppdev, pjBase, y) \ CP_OUT(pjBase, X3, (y)) #define CP_ABS_Y0(ppdev, pjBase, y) \ CP_OUT(pjBase, Y0, (y)) #define CP_ABS_Y1(ppdev, pjBase, y) \ CP_OUT(pjBase, Y1, (y)) #define CP_ABS_Y2(ppdev, pjBase, y) \ CP_OUT(pjBase, Y2, (y)) #define CP_ABS_Y3(ppdev, pjBase, y) \ CP_OUT(pjBase, Y3, (y)) /////////////////////////////////////////////////////////////////// // P9000 only macros // #define CP_FOREGROUND(ppdev, pjBase, x) \ { \ ASSERTDD(ppdev->flStat & STAT_P9000, "Foreground"); \ CP_OUT(pjBase, Foreground, (x)); \ } #define CP_BACKGROUND(ppdev, pjBase, x) \ { \ ASSERTDD(ppdev->flStat & STAT_P9000, "Background"); \ CP_OUT(pjBase, Background, (x)); \ } /////////////////////////////////////////////////////////////////// // P9100 only macros // #define PACK_COLOR(ppdev, x, ulResult) \ { \ ulResult = (x); \ if (ppdev->flStat & STAT_8BPP) \ { \ ulResult |= (ulResult << 8); \ ulResult |= (ulResult << 16); \ } \ else if (ppdev->flStat & STAT_16BPP) \ ulResult |= (ulResult << 16); \ else if (ppdev->flStat & STAT_24BPP) \ ulResult |= (ulResult << 24); \ } #define CP_COLOR0(ppdev, pjBase, x) \ { \ ULONG ul; \ ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color0"); \ PACK_COLOR(ppdev, (x), ul); \ CP_OUT(pjBase, Color0, ul); \ } #define CP_COLOR1(ppdev, pjBase, x) \ { \ ULONG ul; \ ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color1"); \ PACK_COLOR(ppdev, (x), ul); \ CP_OUT(pjBase, Color1, ul); \ } // The _FAST colour macros take colours that are pre-packed for // the P9100: #define CP_COLOR0_FAST(ppdev, pjBase, x) \ { \ ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color0"); \ CP_OUT(pjBase, Color0, (x)); \ } #define CP_COLOR1_FAST(ppdev, pjBase, x) \ { \ ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color1"); \ CP_OUT(pjBase, Color1, (x)); \ } #define CP_COLOR2_FAST(ppdev, pjBase, x) \ { \ ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color2"); \ ASSERTDD(ppdev->flStat & STAT_8BPP, "Color2"); \ CP_OUT(pjBase, Color2, (x)); \ } #define CP_COLOR3_FAST(ppdev, pjBase, x) \ { \ ASSERTDD(!(ppdev->flStat & STAT_P9000), "Color3"); \ ASSERTDD(ppdev->flStat & STAT_8BPP, "Color3"); \ CP_OUT(pjBase, Color3, (x)); \ }