From 6480bd373a04c8ebc3afd3ad7266f2a5354ec090 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 3 Sep 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-09-03 --- bitsy/l.s | 70 +++---- pc/vgas3.c | 65 +++++-- pc/vgasavage.c | 490 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 574 insertions(+), 51 deletions(-) create mode 100644 pc/vgasavage.c diff --git a/bitsy/l.s b/bitsy/l.s index 865955a7ed735166b13f5170538c4b388f58915c..8b4820686f2b815fa6502da7392b59f5d3095d99 100644 --- a/bitsy/l.s +++ b/bitsy/l.s @@ -123,67 +123,71 @@ TEXT _vund(SB), $-4 /* undefined */ B _vswitch TEXT _vsvc(SB), $-4 /* reset or SWI or reserved */ - SUB $12, R13 - MOVW R14, 8(R13) - MOVW CPSR, R14 - MOVW R14, 4(R13) - MOVW $PsrMsvc, R14 - MOVW R14, (R13) - MOVW 8(R13), R14 + SUB $12, R13 /* make room for pc, psr, & type */ + MOVW R14, 8(R13) /* ureg->pc = interupted PC */ + MOVW SPSR, R14 /* ureg->psr = SPSR */ + MOVW R14, 4(R13) /* ... */ + MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */ + MOVW R14, (R13) /* ... */ B _vsaveu TEXT _vpab(SB), $-4 /* prefetch abort */ - MOVM.IA [R0-R3], (R13) - MOVW $PsrMabt, R0 + MOVM.IA [R0-R3], (R13) /* free some working space */ + MOVW $PsrMabt, R0 /* r0 = type */ B _vswitch TEXT _vdab(SB), $-4 /* data abort */ - MOVM.IA [R0-R3], (R13) - MOVW $(PsrMabt+1), R0 - B _vswitch + MOVM.IA [R0-R3], (R13) /* free some working space */ + MOVW $(PsrMabt+1), R0 /* r0 = type */ + B _vswitch /* TEXT _virq(SB), $-4 /* IRQ */ - MOVM.IA [R0-R3], (R13) - MOVW $PsrMirq, R0 + MOVM.IA [R0-R3], (R13) /* free some working space */ + MOVW $PsrMirq, R0 /* r0 = type */ B _vswitch TEXT _vfiq(SB), $-4 /* FIQ */ - MOVM.IA [R0-R3], (R13) - MOVW $PsrMfiq, R0 + MOVM.IA [R0-R3], (R13) /* free some working space */ + MOVW $PsrMfiq, R0 /* r0 = type */ B _vswitch + /* + * come here with type in R0 and R13 pointing above saved [r0-r3] + */ _vswitch: /* switch to svc, type in R0 */ - MOVW SPSR, R1 /* psr for ureg */ - MOVW R14, R2 /* saved pc for ureg */ + MOVW SPSR, R1 /* SPSR for ureg */ + MOVW R14, R2 /* interrupted pc for ureg */ MOVW R13, R3 /* [R0-R3] save area */ - MOVW CPSR, R14 /* switch */ + /* switch to svc mode, we get new R13 pointing to top of svc stack */ + MOVW CPSR, R14 BIC $PsrMask, R14 ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14 MOVW R14, CPSR - MOVM.DB.W [R0-R2], (R13) /* top of ureg */ - MOVM.IA (R3), [R0-R3] /* restore [R0-R3] */ + MOVM.DB.W [R0-R2], (R13) /* set ureg->{pc, psr, type}; r13 points to ureg->type */ + MOVM.IA (R3), [R0-R3] /* restore [R0-R3] from previous mode's stack */ B _vsaveu - /* push the registers as in ureg */ + /* + * come here with R13 pointing to ureg->type + */ _vsaveu: - SUB $4, R13 /* save link */ - MOVW R14, (R13) - MOVM.DB.W.S [R0-R14], (R13) /* save svc registers */ + MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, r13 points to ureg */ MOVW $setR12(SB), R12 /* the SB from user mode is different */ - MOVW R13, R0 /* argument is &ureg */ + + MOVW R13, R0 /* first arg is pointer to ureg */ SUB $8, R13 /* space for argument+link */ BL exception(SB) -_vrfe: - ADD $(8+4*15), R13 /* [r0-R14]+argument+link */ - MOVW (R13), R14 /* restore link */ - MOVW 8(R13), R0 /* restore SPSR */ - MOVW R0, SPSR - MOVM.DB.S (R13), [R0-R14] /* restore registers */ - ADD $12, R13 /* skip saved link+type+SPSR */ +_vrfe: + ADD $(8+4*15), R13 /* r13 points to ureg->type */ + MOVW 8(R13), R14 /* restore link */ + MOVW 4(R13), R0 /* restore SPSR */ + MOVW R0, SPSR /* ... */ + MOVM.DB.S (R13), [R0-R14] /* restore registers */ + ADD $8, R13 /* skip saved type+SPSR */ RFE /* MOVM.IA.S.W (R13), [R15] */ TEXT splhi(SB), $-4 diff --git a/pc/vgas3.c b/pc/vgas3.c index 1f8ede98aaa812c7fece4a0fe813de73f094e198..5b61efea0d7a55943d67bdb3cd013aa2a08ec469 100644 --- a/pc/vgas3.c +++ b/pc/vgas3.c @@ -12,6 +12,28 @@ #include #include "screen.h" +enum { + PCIS3 = 0x5333, /* PCI VID */ + + SAVAGE3D = 0x8A20, /* PCI DID */ + SAVAGE3DMV = 0x8A21, + SAVAGE4 = 0x8A22, + SAVAGEMXMV = 0x8C10, + SAVAGEMX = 0x8C11, + SAVAGEIXMV = 0x8C12, + SAVAGEIX = 0x8C13, + SAVAGE2000 = 0x9102, + + VIRGE = 0x5631, + VIRGEGX2 = 0x8A10, + VIRGEDXGX = 0x8A01, + VIRGEVX = 0x883D, + VIRGEMX = 0x8C01, + VIRGEMXP = 0x8C03, + + AURORA64VPLUS = 0x8812, +}; + static int s3pageset(VGAscr* scr, int page) { @@ -50,7 +72,7 @@ s3page(VGAscr* scr, int page) id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); switch(id){ - case 0x8A10: /* ViRGE/GX2 */ + case VIRGEGX2: break; default: @@ -78,7 +100,7 @@ s3linear(VGAscr* scr, int* size, int* align) mmiosize = 0; mmiobase = 0; mmioname = nil; - if(p = pcimatch(nil, 0x5333, 0)){ + if(p = pcimatch(nil, PCIS3, 0)){ for(i=0; imem); i++){ if(p->mem[i].size >= *size && ((p->mem[i].bar & ~0x0F) & (*align-1)) == 0) @@ -92,7 +114,7 @@ s3linear(VGAscr* scr, int* size, int* align) *size = p->mem[i].size; id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); - if(id == 0x8A22){ /* find Savage4 mmio */ + if(id == SAVAGE4){ /* find Savage4 mmio */ /* * We could assume that the MMIO registers * will be in the screen segment and just use @@ -108,6 +130,7 @@ s3linear(VGAscr* scr, int* size, int* align) if(p->mem[j].size==512*1024 || p->mem[j].size==16*1024*1024){ mmiobase = p->mem[j].bar & ~0x0F; mmiosize = 512*1024; + scr->mmio = (ulong*)upamalloc(mmiobase, mmiosize, 16*1024*1024); mmioname = "savage4mmio"; break; } @@ -196,12 +219,12 @@ s3load(VGAscr* scr, Cursor* curs) id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); switch(id){ - case 0x5631: /* ViRGE */ - case 0x8A01: /* ViRGE/[DG]X */ - case 0x8A10: /* ViRGE/GX2 */ - case 0x883D: /* ViRGE/VX */ - case 0x8C12: /* Savage4/IX-MV */ - case 0x8A22: /* Savage4 */ + case VIRGE: + case VIRGEDXGX: + case VIRGEGX2: + case VIRGEVX: + case SAVAGEIXMV: + case SAVAGE4: p += scr->storage; break; @@ -244,12 +267,12 @@ s3load(VGAscr* scr, Cursor* curs) switch(id){ - case 0x5631: /* ViRGE */ - case 0x8A01: /* ViRGE/[DG]X */ - case 0x8A10: /* ViRGE/GX2 */ - case 0x883D: /* ViRGE/VX */ - case 0x8C12: /* Savage4/IX-MV */ - case 0x8A22: /* Savage4 */ + case VIRGE: + case VIRGEDXGX: + case VIRGEGX2: + case VIRGEVX: + case SAVAGEIXMV: + case SAVAGE4: break; default: @@ -526,9 +549,11 @@ s3blank(int blank) vgaxo(Seqx, CursorSyncCtl, x); } + static void s3drawinit(VGAscr *scr) { + extern void savageinit(VGAscr*); /* vgasavage.c */ ulong id; id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E); @@ -542,13 +567,17 @@ s3drawinit(VGAscr *scr) * above. */ switch(id){ - case 0x5631: /* ViRGE */ - case 0x883D: /* ViRGE/VX */ - case 0x8A10: /* ViRGE/GX2 */ + case VIRGE: /* ViRGE */ + case VIRGEVX: /* ViRGE/VX */ + case VIRGEGX2: /* ViRGE/GX2 */ scr->mmio = (ulong*)(scr->aperture+0x1000000); scr->fill = hwfill; scr->scroll = hwscroll; /* scr->blank = hwblank; */ + break; + case SAVAGE4: + savageinit(scr); + break; } } diff --git a/pc/vgasavage.c b/pc/vgasavage.c new file mode 100644 index 0000000000000000000000000000000000000000..0fdd4567e47fb912cb2afacc036c64195bbb6193 --- /dev/null +++ b/pc/vgasavage.c @@ -0,0 +1,490 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +#define Image IMAGE +#include +#include +#include +#include "screen.h" + +enum { + PCIS3 = 0x5333, /* PCI VID */ + + SAVAGE3D = 0x8A20, /* PCI DID */ + SAVAGE3DMV = 0x8A21, + SAVAGE4 = 0x8A22, + SAVAGEMXMV = 0x8C10, + SAVAGEMX = 0x8C11, + SAVAGEIXMV = 0x8C12, + SAVAGEIX = 0x8C13, + SAVAGE2000 = 0x9102, + + VIRGE = 0x5631, + VIRGEGX2 = 0x8A10, + VIRGEDXGX = 0x8A01, + VIRGEVX = 0x883D, + VIRGEMX = 0x8C01, + VIRGEMXP = 0x8C03, + + AURORA64VPLUS = 0x8812, +}; + +/* + * Savage4 et al. acceleration. + * + * This is based only on the Savage4 documentation. + * It is expected to work on other Savage cards as well, + * but has not been tried. + * + * There are five ways to access the 2D graphics engine registers: + * - Old MMIO non-packed format + * - Old MMIO packed format + * - New MMIO non-packed format + * - New MMIO packed format + * - Burst Command Interface (BCI) + * + * Of these, the manual hints that the first three are deprecated, + * and it does not document any of those three well enough to use. + * + * I have tried for many hours with no success to understand the BCI + * interface well enough to use it. It is not well documented, and the + * XFree86 driver seems to completely contradict what little documentation + * there is. + * + * This leaves the packed new MMIO. + * The manual contradicts itself here, claming that the registers + * start at 0x2008100 as well as at 0x0008100 from the base of the + * mmio segment. Since the segment is only 512k, we assume that + * the latter is the correct offset. + * + * According to the manual, only 16-bit reads of the 2D registers + * are supported: 32-bit reads will return garbage in the upper word. + * 32-bit writes must be enabled explicitly. + * + * 32-bit reads of the status registers seem just fine. + */ + +/* 2D graphics engine registers */ +enum { + SubsystemStatus = 0x8504, /* Subsystem Status: read only */ + /* read only: whether we get interrupts on various events */ + VsyncInt = 1<<0, /* vertical sync */ + GeBusyInt = 1<<1, /* 2D graphics engine busy */ + BfifoFullInt = 1<<2, /* BIU FIFO full */ + BfifoEmptyInt = 1<<3, /* BIU FIFO empty */ + CfifoFullInt = 1<<4, /* command FIFO full */ + CfifoEmptyInt = 1<<5, /* command FIFO empty */ + BciInt = 1<<6, /* BCI */ + LpbInt = 1<<7, /* LPB */ + CbHiInt = 1<<16, /* COB upper threshold */ + CbLoInt = 1<<17, /* COB lower threshold */ + + SubsystemCtl = 0x8504, /* Subsystem Control: write only */ + /* clear interrupts for various events */ + VsyncClr = 1<<0, + GeBusyClr = 1<<1, + BfifoFullClr = 1<<2, + BfifoEmptyClr = 1<<3, + CfifoFullClr = 1<<4, + CfifoEmptyClr = 1<<5, + BciClr = 1<<6, + LpbClr = 1<<7, + CbHiClr = 1<<16, + CbLoClr = 1<<17, + + /* enable interrupts for various events */ + VsyncEna = 1<<8, + Busy2DEna = 1<<9, + BfifoFullEna = 1<<10, + BfifoEmptyEna = 1<<11, + CfifoFullEna = 1<<12, + CfifoEmptyEna = 1<<13, + SubsysBciEna = 1<<14, + CbHiEna = 1<<24, + CbLoEna = 1<<25, + + /* 2D graphics engine software reset */ + GeSoftReset = 1<<15, + + FifoStatus = 0x8508, /* FIFO status: read only */ + CwbEmpty = 1<<0, /* command write buffer empty */ + CrbEmpty = 1<<1, /* command read buffer empty */ + CobEmpty = 1<<2, /* command overflow buffer empty */ + CfifoEmpty = 1<<3, /* command FIFO empty */ + CwbFull = 1<<8, /* command write buffer full */ + CrbFull = 1<<9, /* command read buffer full */ + CobFull = 1<<10, /* command overflow buffer full */ + CfifoFull = 1<<11, /* command FIFO full */ + + AdvFunCtl = 0x850C, /* Advanced Function Control: read/write */ + GeEna = 1<<0, /* enable 2D/3D engine */ + /* + * according to the manual, BigPixel should be + * set when bpp >= 8 (bpp != 4), and then CR50_5-4 are + * used to figure out bpp example. however, it does bad things + * to the screen in 8bpp mode. + */ + BigPixel = 1<<2, /* 8 or more bpp enhanced mode */ + LaEna = 1<<3, /* linear addressing ena: or'ed with CR58_4 */ + Mclk_2 = 0<<8, /* 2D engine clock divide: MCLK/2 */ + Mclk_4 = 1<<8, /* " MCLK/4 */ + Mclk = 2<<8, /* " MCLK */ + /* Mclk = 3<<8, /* " MCLK */ + Ic33mhz = 1<<16, /* Internal clock 33 MHz (instead of 66) */ + + WakeupReg = 0x8510, /* Wakeup: read/write */ + WakeupBit = 1<<0, /* wake up: or'ed with 3C3_0 */ + + SourceY = 0x8100, /* UL corner of bitblt source */ + SourceX = 0x8102, /* " */ + RectY = 0x8100, /* UL corner of rectangle fill */ + RectX = 0x8102, /* " */ + DestY = 0x8108, /* UL corner of bitblt dest */ + DestX = 0x810A, /* " */ + Height = 0x8148, /* bitblt, image xfer rectangle height */ + Width = 0x814A, /* bitblt, image xfer rectangle width */ + + StartY = 0x8100, /* Line draw: first point*/ + StartX = 0x8102, /* " */ + /* + * For line draws, the following must be programmed: + * axial step constant = 2*min(|dx|,|dy|) + * diagonal step constant = 2*[min(|dx|,|dy|) - max(|dx|,|dy|)] + * error term = 2*min(|dx|,|dy|) - max(|dx|,|dy| - 1 + * [sic] when start X < end X + * error term = 2*min(|dx|,|dy|) - max(|dx|,|dy| + * [sic] when start X >= end X + */ + AxialStep = 0x8108, + DiagonalStep = 0x810A, + LineError = 0x8110, + MinorLength = 0x8148, /* pixel count along minor axis */ + MajorLength = 0x814A, /* pixel count along major axis */ + + DrawCmd = 0x8118, /* Drawing Command: write only */ + CmdMagic = 0<<1, + AcrossPlane = 1<<1, /* across the plane mode */ + LastPixelOff = 1<<2, /* last pixel of line or vector draw not drawn */ + Radial = 1<<3, /* enable radial direction (else axial) */ + DoDraw = 1<<4, /* draw pixels (else only move current pos) */ + + DrawRight = 1<<5, /* axial drawing direction: left to right */ + /* DrawLeft = 0<<5, */ + MajorY = 1<<6, + /* MajorX = 0<<6, */ + DrawDown = 1<<7, + /* DrawUp = 0<<7, */ + Degree0 = 0<<5, /* drawing direction when Radial */ + Degree45 = 1<<5, + /* ... */ + Degree315 = 7<<5, + + UseCPUData = 1<<8, + + /* image write bus transfer width */ + Bus8 = 0<<9, + Bus16 = 1<<9, + /* + * in Bus32 mode, doubleword bits beyond the image rect width are + * discarded. each line starts on a new doubleword. + * Bus32AP is intended for across-the-plane mode and + * rounds to byte boundaries instead. + */ + Bus32 = 2<<9, + Bus32AP = 3<<9, + + CmdNop = 0<<13, /* nop */ + CmdLine = 1<<13, /* draw line */ + CmdFill = 2<<13, /* fill rectangle */ + CmdBitblt = 6<<13, /* bitblt */ + CmdPatblt = 7<<13, /* 8x8 pattern blt */ + + SrcGBD = 0<<16, + SrcPBD = 1<<16, + SrcSBD = 2<<16, + + DstGBD = 0<<18, + DstPBD = 1<<18, + DstSBD = 2<<18, + + /* color sources, controls */ + BgColor = 0x8120, /* Background Color: read/write */ + FgColor = 0x8124, /* Foreground Color: read/write */ + BitplaneWmask = 0x8128, /* Bitplane Write Mask: read/write */ + BitplaneRmask = 0x812C, /* Bitplane Read Mask: read/write */ + CmpColor = 0x8130, /* Color Compare: read/write */ + BgMix = 0x8134, + FgMix = 0x8136, + MixNew = 7, + SrcBg = 0<<5, + SrcFg = 1<<5, + SrcCPU = 2<<5, + SrcDisp = 3<<5, + + /* clipping rectangle */ + TopScissors = 0x8138, /* Top Scissors: write only */ + LeftScissors = 0x813A, /* Left Scissors: write only */ + BottomScissors = 0x813C, /* Bottom Scissors: write only */ + RightScissors = 0x813E, /* Right Scissors: write only */ + + /* + * Registers with Magic were indirectly accessed in older modes. + * It is not clear whether the Magic is necessary. + * In the older modes, writes to these registers were pipelined, + * so that you had to issue an engine command and wait for engine + * idle before reading a write back. It is not clear if this is + * still the case either. + */ + PixCtl = 0x8140, /* Pixel Control: write only */ + PixMagic = 0xA<<12, + PixMixFg = 0<<6, /* foreground mix register always */ + PixMixCPU = 2<<6, /* CPU data determines mix register */ + PixMixDisp = 3<<6, /* display data determines mix register */ + + MfMisc2Ctl = 0x8142, /* Multifunction Control Misc. 2: write only */ + MfMisc2Magic = 0xD<<12, + DstShift = 0, /* 3 bits: destination base address in MB */ + SrcShift = 4, /* 3 bits: source base address in MB */ + WaitFifoEmpty = 2<<8, /* wait for write FIFO empty between draws */ + + MfMiscCtl = 0x8144, /* Multifunction Control Misc: write only */ + MfMiscMagic = 0xE<<12, + UseHighBits = 1<<4, /* select upper 16 bits for 32-bit reg access */ + ClipInvert = 1<<5, /* only touch pixels outside clip rectangle */ + SkipSame = 0<<6, /* ignore pixels with color CmpColor */ + SkipDifferent = 1<<7, /* ignore pixels not color CmpColor */ + CmpEna = 1<<8, /* enable color compare */ + W32Ena = 1<<9, /* enable 32-bit register write */ + ClipDis = 1<<11, /* disable clipping */ + + /* + * The bitmap descriptor 1 registers contain the starting + * address of the bitmap (in bytes). + * The bitmap descriptor 2 registesr contain stride (in pixels) + * in the lower 16 bits, depth (in bits) in the next 8 bits, + * and whether block write is disabled. + */ + GBD1 = 0x8168, /* Global Bitmap Descriptor 1: read/write */ + GBD2 = 0x816C, /* Global Bitmap Descriptor 2: read/write */ + /* GBD2-only bits */ + BDS64 = 1<<0, /* bitmap descriptor size 64 bits */ + GBDBciEna = 1<<3, /* BCI enable */ + /* generic BD2 bits */ + BlockWriteDis = 1<<28, + StrideShift = 0, + DepthShift = 16, + + PBD1 = 0x8170, /* Primary Bitmap Descriptor: read/write */ + PBD2 = 0x8174, + SBD1 = 0x8178, /* Secondary Bitmap Descriptor: read/write */ + SBD2 = 0x817C, +}; + +/* mastered data transfer registers */ + +/* configuration/status registers */ +enum { + XStatus0 = 0x48C00, /* Status Word 0: read only */ + /* rev. A silicon differs from rev. B; use AltStatus0 */ + CBEMaskA = 0x1FFFF, /* filled command buffer entries */ + CBEShiftA = 0, + BciIdleA = 1<<17, /* BCI idle */ + Ge3IdleA = 1<<18, /* 3D engine idle */ + Ge2IdleA = 1<<19, /* 2D engine idle */ + McpIdleA = 1<<20, /* motion compensation processor idle */ + MeIdleA = 1<<22, /* master engine idle */ + PfPendA = 1<<23, /* page flip pending */ + + CBEMaskB = 0x1FFFFF, + CBEShiftB = 0, + BciIdleB = 1<<25, + Ge3IdleB = 1<<26, + Ge2IdleB = 1<<27, + McpIdleB = 1<<28, + MeIdleB = 1<<30, + PfPendB = 1<<31, + + AltStatus0 = 0x48C60, /* Alternate Status Word 0: read only */ + CBEMask = 0x1FFFF, + CBEShift = 0, + /* the Savage4 manual says bits 17..23 for these, like Status0 */ + /* empirically, they are bits 21..26 */ + BciIdle = 1<<21, + Ge3Idle = 1<<22, + Ge2Idle = 1<<23, + McpIdle = 1<<24, + MeIdle = 1<<25, + PfPend = 1<<26, + + XStatus1 = 0x48C04, /* Status Word 1: read only */ + /* contains event tag 1, event tag 0, both 16 bits */ + + XStatus2 = 0x48C08, /* Status Word 2: read only */ + ScanMask = 0x3FF, /* current scan line */ + ScanShift = 0, + VRTMask = 0x7F100, /* vert retrace count */ + VRTShift = 11, + + CbThresh = 0x48C10, /* Command Buffer Thresholds: read/write */ + CobOff = 0x48C14, /* Command Overflow Buffer: read/write */ + + CobPtr = 0x48C18, /* Command Overflow Buffer Pointers: read/write */ + CobEna = 1<<2, /* command overflow buffer enable */ + CobBciEna = 1<<3, /* BCI function enable */ + CbeMask = 0xFFFF8000, /* no. of entries in command buffer */ + CbeShift = 15, + + AltStatus1 = 0x48C64, /* Alternate Status Word 1: read onnly */ + /* contains current texture surface tag, vertex buffer tag */ + +}; + +enum { + Maxloop = 1<<23 +}; + +static void +savagewaitidle(VGAscr *scr) +{ + long x; + ulong *statw; + + statw = (ulong*)((uchar*)scr->mmio+AltStatus0); + + for(x=0; xmmio; + + *(ulong*)(mmio+FgColor) = sval; + *(ulong*)(mmio+BgColor) = sval; + *(ulong*)(mmio+BgMix) = SrcFg|MixNew; + *(ulong*)(mmio+FgMix) = SrcFg|MixNew; + *(ushort*)(mmio+RectY) = r.min.y; + *(ushort*)(mmio+RectX) = r.min.x; + *(ushort*)(mmio+Width) = Dx(r)-1; + *(ushort*)(mmio+Height) = Dy(r)-1; + *(ulong*)(mmio+DrawCmd) = CmdMagic | DoDraw | CmdFill | DrawRight | DrawDown; + savagewaitidle(scr); + return 1; +} + +static int +savagescroll(VGAscr *scr, Rectangle r, Rectangle sr) +{ + uchar *mmio; + ulong cmd; + Point dp, sp; + + cmd = CmdMagic | DoDraw | CmdBitblt | SrcPBD | DstGBD; + + if(r.min.x <= sr.min.x){ + cmd |= DrawRight; + dp.x = r.min.x; + sp.x = sr.min.x; + }else{ + dp.x = r.max.x-1; + sp.x = sr.max.x-1; + } + + if(r.min.y <= sr.min.y){ + cmd |= DrawDown; + dp.y = r.min.y; + sp.y = sr.min.y; + }else{ + dp.y = r.max.y-1; + sp.y = sr.max.y-1; + } + + mmio = (uchar*)scr->mmio; + + *(ushort*)(mmio+SourceX) = sp.x; + *(ushort*)(mmio+SourceY) = sp.y; + *(ushort*)(mmio+DestX) = dp.x; + *(ushort*)(mmio+DestY) = dp.y; + *(ushort*)(mmio+Width) = Dx(r)-1; + *(ushort*)(mmio+Height) = Dy(r)-1; + *(ulong*)(mmio+BgMix) = SrcDisp|MixNew; + *(ulong*)(mmio+FgMix) = SrcDisp|MixNew; + *(ulong*)(mmio+DrawCmd) = cmd; + savagewaitidle(scr); + return 1; +} + +void +savageinit(VGAscr *scr) +{ + uchar *mmio; + ulong bd; + + mmio = (uchar*)scr->mmio; + + if(mmio == nil) { + print("savageinit: no mmio\n"); + return; + } + /* 2D graphics engine software reset */ + *(ushort*)(mmio+SubsystemCtl) = GeSoftReset; + delay(2); + *(ushort*)(mmio+SubsystemCtl) = 0; + savagewaitidle(scr); + + /* disable BCI as much as possible */ + *(ushort*)(mmio+CobPtr) &= ~CobBciEna; + *(ushort*)(mmio+GBD2) &= ~GBDBciEna; + savagewaitidle(scr); + + /* enable 32-bit writes, disable clipping */ + *(ushort*)(mmio+MfMiscCtl) = MfMiscMagic|W32Ena|ClipDis; + savagewaitidle(scr); + + /* enable all read, write planes */ + *(ulong*)(mmio+BitplaneRmask) = ~0; + *(ulong*)(mmio+BitplaneWmask) = ~0; + savagewaitidle(scr); + + /* turn on linear access, 2D engine */ + *(ulong*)(mmio+AdvFunCtl) |= GeEna|LaEna; + savagewaitidle(scr); + + /* set bitmap descriptors */ + bd = (scr->gscreen->depth<gscreen->r)<>16; + savagewaitidle(scr); + + scr->fill = savagefill; + scr->scroll = savagescroll; +} +