17dd7cddfSDavid du Colombier #include "u.h"
27dd7cddfSDavid du Colombier #include "../port/lib.h"
37dd7cddfSDavid du Colombier #include "mem.h"
47dd7cddfSDavid du Colombier #include "dat.h"
57dd7cddfSDavid du Colombier #include "fns.h"
67dd7cddfSDavid du Colombier #include "io.h"
77dd7cddfSDavid du Colombier #include "../port/error.h"
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier #define Image IMAGE
107dd7cddfSDavid du Colombier #include <draw.h>
117dd7cddfSDavid du Colombier #include <memdraw.h>
127dd7cddfSDavid du Colombier #include <cursor.h>
137dd7cddfSDavid du Colombier #include "screen.h"
147dd7cddfSDavid du Colombier
159a747e4fSDavid du Colombier char Eunsupportedformat[] = "unsupported video format";
169a747e4fSDavid du Colombier char Enotconfigured[] = "device not configured";
179a747e4fSDavid du Colombier
189a747e4fSDavid du Colombier #define SCALE_ZERO_EXTEND 0x0
199a747e4fSDavid du Colombier #define SCALE_DYNAMIC 0x1
209a747e4fSDavid du Colombier #define SCALE_RED_TEMP_6500K 0x0
219a747e4fSDavid du Colombier #define SCALE_RED_TEMP_9800K 0x2
229a747e4fSDavid du Colombier #define SCALE_HORZ_BLEND 0x0
239a747e4fSDavid du Colombier #define SCALE_HORZ_REP 0x4
249a747e4fSDavid du Colombier #define SCALE_VERT_BLEND 0x0
259a747e4fSDavid du Colombier #define SCALE_VERT_REP 0x8
269a747e4fSDavid du Colombier #define SCALE_BANDWIDTH_NORMAL 0x0
279a747e4fSDavid du Colombier #define SCALE_BANDWIDTH_EXCEEDED 0x4000000
289a747e4fSDavid du Colombier #define SCALE_BANDWIDTH_RESET 0x4000000
299a747e4fSDavid du Colombier #define SCALE_CLK_ACTIVITY 0x0
309a747e4fSDavid du Colombier #define SCALE_CLK_CONTINUOUS 0x20000000
319a747e4fSDavid du Colombier #define OVERLAY_DISABLE 0x0
329a747e4fSDavid du Colombier #define OVERLAY_ENABLE 0x40000000
339a747e4fSDavid du Colombier #define SCALE_DISABLE 0x0
349a747e4fSDavid du Colombier #define SCALE_ENABLE 0x80000000
359a747e4fSDavid du Colombier
369a747e4fSDavid du Colombier #define SCALER_FRAME_READ_MODE_FULL 0x0
379a747e4fSDavid du Colombier #define SCALER_BUF_MODE_SINGLE 0x0
389a747e4fSDavid du Colombier #define SCALER_BUF_MODE_DOUBLE 0x40000
399a747e4fSDavid du Colombier #define SCALER_BUF_NEXT_0 0x0
409a747e4fSDavid du Colombier #define SCALER_BUF_NEXT_1 0x80000
419a747e4fSDavid du Colombier #define SCALER_BUF_STATUS_0 0x0
429a747e4fSDavid du Colombier #define SCALER_BUF_STATUS_1 0x100000
439a747e4fSDavid du Colombier
449a747e4fSDavid du Colombier #define OVERLAY_MIX_G_CMP 0x0
459a747e4fSDavid du Colombier #define OVERLAY_MIX_ALWAYS_G 0x100
469a747e4fSDavid du Colombier #define OVERLAY_MIX_ALWAYS_V 0x200
479a747e4fSDavid du Colombier #define OVERLAY_MIX_NOT_G 0x300
489a747e4fSDavid du Colombier #define OVERLAY_MIX_NOT_V 0x400
499a747e4fSDavid du Colombier #define OVERLAY_MIX_G_XOR_V 0x500
509a747e4fSDavid du Colombier #define OVERLAY_MIX_NOT_G_XOR_V 0x600
519a747e4fSDavid du Colombier #define OVERLAY_MIX_V_CMP 0x700
529a747e4fSDavid du Colombier #define OVERLAY_MIX_NOT_G_OR_NOT_V 0x800
539a747e4fSDavid du Colombier #define OVERLAY_MIX_G_OR_NOT_V 0x900
549a747e4fSDavid du Colombier #define OVERLAY_MIX_NOT_G_OR_V 0xA00
559a747e4fSDavid du Colombier #define OVERLAY_MIX_G_OR_V 0xB00
569a747e4fSDavid du Colombier #define OVERLAY_MIX_G_AND_V 0xC00
579a747e4fSDavid du Colombier #define OVERLAY_MIX_NOT_G_AND_V 0xD00
589a747e4fSDavid du Colombier #define OVERLAY_MIX_G_AND_NOT_V 0xE00
599a747e4fSDavid du Colombier #define OVERLAY_MIX_NOT_G_AND_NOT_V 0xF00
609a747e4fSDavid du Colombier #define OVERLAY_EXCLUSIVE_NORMAL 0x0
619a747e4fSDavid du Colombier #define OVERLAY_EXCLUSIVE_V_ONLY 0x80000000
629a747e4fSDavid du Colombier
639a747e4fSDavid du Colombier #define VIDEO_IN_8BPP 0x2
649a747e4fSDavid du Colombier #define VIDEO_IN_16BPP 0x4
659a747e4fSDavid du Colombier #define VIDEO_IN_32BPP 0x6
669a747e4fSDavid du Colombier #define VIDEO_IN_VYUY422 0xB /*16 bpp */
679a747e4fSDavid du Colombier #define VIDEO_IN_YVYU422 0xC /* 16 bpp */
689a747e4fSDavid du Colombier #define SCALE_IN_15BPP 0x30000 /* aRGB 1555 */
699a747e4fSDavid du Colombier #define SCALE_IN_16BPP 0x40000 /* RGB 565 */
709a747e4fSDavid du Colombier #define SCALE_IN_32BPP 0x60000 /* aRGB 8888 */
719a747e4fSDavid du Colombier #define SCALE_IN_YUV9 0x90000 /* planar */
729a747e4fSDavid du Colombier #define SCALE_IN_YUV12 0xA0000 /* planar */
739a747e4fSDavid du Colombier #define SCALE_IN_VYUY422 0xB0000 /* 16 bpp */
749a747e4fSDavid du Colombier #define SCALE_IN_YVYU422 0xC0000 /* 16 bpp */
759a747e4fSDavid du Colombier #define HOST_YUV_APERTURE_UPPER 0x0
769a747e4fSDavid du Colombier #define HOST_YUV_APERTURE_LOWER 0x20000000
779a747e4fSDavid du Colombier #define HOST_MEM_MODE_Y 0x40000000
789a747e4fSDavid du Colombier #define HOST_MEM_MODE_U 0x80000000
799a747e4fSDavid du Colombier #define HOST_MEM_MODE_V 0xC0000000
809a747e4fSDavid du Colombier #define HOST_MEM_MODE_NORMAL HOST_YUV_APERTURE_UPPER
819a747e4fSDavid du Colombier
829a747e4fSDavid du Colombier static Chan *ovl_chan; /* Channel of controlling process */
839a747e4fSDavid du Colombier static int ovl_width; /* Width of input overlay buffer */
849a747e4fSDavid du Colombier static int ovl_height; /* Height of input overlay buffer */
859a747e4fSDavid du Colombier static int ovl_format; /* Overlay format */
869a747e4fSDavid du Colombier static ulong ovl_fib; /* Frame in bytes */
879a747e4fSDavid du Colombier
889a747e4fSDavid du Colombier enum {
8941dd6b47SDavid du Colombier VTGTB1S1 = 0x01, /* Asic description for VTB1S1 and GTB1S1. */
9041dd6b47SDavid du Colombier VT4GTIIC = 0x3A, /* asic descr for VT4 and RAGE IIC */
9141dd6b47SDavid du Colombier GTB1U1 = 0x19, /* Asic description for GTB1U1. */
9241dd6b47SDavid du Colombier GTB1S2 = 0x41, /* Asic description for GTB1S2. */
939a747e4fSDavid du Colombier GTB2U1 = 0x1A,
949a747e4fSDavid du Colombier GTB2U2 = 0x5A,
959a747e4fSDavid du Colombier GTB2U3 = 0x9A,
9641dd6b47SDavid du Colombier GTIIIC1U1 = 0x1B, /* 3D RAGE PRO asic descrp. */
9741dd6b47SDavid du Colombier GTIIIC1U2 = 0x5B, /* 3D RAGE PRO asic descrp. */
9841dd6b47SDavid du Colombier GTIIIC2U1 = 0x1C, /* 3D RAGE PRO asic descrp. */
9941dd6b47SDavid du Colombier GTIIIC2U2 = 0x5C, /* 3D RAGE PRO asic descrp. */
10041dd6b47SDavid du Colombier GTIIIC2U3 = 0x7C, /* 3D RAGE PRO asic descrp. */
10141dd6b47SDavid du Colombier GTBC = 0x3A, /* 3D RAGE IIC asic descrp. */
10241dd6b47SDavid du Colombier LTPRO = 0x9C, /* 3D RAGE LT PRO */
1039a747e4fSDavid du Colombier };
1049a747e4fSDavid du Colombier
1057dd7cddfSDavid du Colombier /*
10659cc4ca5SDavid du Colombier * ATI Mach64(CT|ET|G*|V*|L*).
1077dd7cddfSDavid du Colombier */
10859c21d95SDavid du Colombier typedef struct Mach64types Mach64types;
10959c21d95SDavid du Colombier struct Mach64types {
1109a747e4fSDavid du Colombier ushort m64_id; /* Chip ID */
1119a747e4fSDavid du Colombier int m64_vtgt; /* Is this a VT or GT chipset? */
1129a747e4fSDavid du Colombier ulong m64_ovlclock; /* Max. overlay clock frequency */
1139a747e4fSDavid du Colombier int m64_pro; /* Is this a PRO? */
11459c21d95SDavid du Colombier };
1159a747e4fSDavid du Colombier
1169a747e4fSDavid du Colombier static ulong mach64refclock;
11759c21d95SDavid du Colombier static Mach64types *mach64type;
1189a747e4fSDavid du Colombier static int mach64revb; /* Revision B or greater? */
1199a747e4fSDavid du Colombier static ulong mach64overlay; /* Overlay buffer */
1209a747e4fSDavid du Colombier
12159c21d95SDavid du Colombier static Mach64types mach64s[] = {
1223ff48bf5SDavid du Colombier ('C'<<8)|'T', 0, 1350000, /*?*/ 0, /* 4354: CT */
1233ff48bf5SDavid du Colombier ('E'<<8)|'T', 0, 1350000, /*?*/ 0, /* 4554: ET */
1249a747e4fSDavid du Colombier ('G'<<8)|'B', 1, 1250000, 1, /* 4742: 264GT PRO */
1259a747e4fSDavid du Colombier ('G'<<8)|'D', 1, 1250000, 1, /* 4744: 264GT PRO */
1269a747e4fSDavid du Colombier ('G'<<8)|'I', 1, 1250000, 1, /* 4749: 264GT PRO */
1279a747e4fSDavid du Colombier ('G'<<8)|'M', 0, 1350000, 0, /* 474D: Rage XL */
1289a747e4fSDavid du Colombier ('G'<<8)|'P', 1, 1250000, 1, /* 4750: 264GT PRO */
1299a747e4fSDavid du Colombier ('G'<<8)|'Q', 1, 1250000, 1, /* 4751: 264GT PRO */
1309a747e4fSDavid du Colombier ('G'<<8)|'R', 1, 1250000, 1, /* 4752: */
1319a747e4fSDavid du Colombier ('G'<<8)|'T', 1, 800000, 0, /* 4754: 264GT[B] */
1329a747e4fSDavid du Colombier ('G'<<8)|'U', 1, 1000000, 0, /* 4755: 264GT DVD */
1339a747e4fSDavid du Colombier ('G'<<8)|'V', 1, 1000000, 0, /* 4756: Rage2C */
1349a747e4fSDavid du Colombier ('G'<<8)|'Z', 1, 1000000, 0, /* 475A: Rage2C */
1359a747e4fSDavid du Colombier ('V'<<8)|'T', 1, 800000, 0, /* 5654: 264VT/GT/VTB */
1369a747e4fSDavid du Colombier ('V'<<8)|'U', 1, 800000, 0, /* 5655: 264VT3 */
1379a747e4fSDavid du Colombier ('V'<<8)|'V', 1, 1000000, 0, /* 5656: 264VT4 */
1389a747e4fSDavid du Colombier ('L'<<8)|'B', 0, 1350000, 1, /* 4C42: Rage LTPro AGP */
1399a747e4fSDavid du Colombier ('L'<<8)|'I', 0, 1350000, 0, /* 4C49: Rage LTPro AGP */
1409a747e4fSDavid du Colombier ('L'<<8)|'M', 0, 1350000, 0, /* 4C4D: Rage Mobility */
1419a747e4fSDavid du Colombier ('L'<<8)|'P', 0, 1350000, 1, /* 4C50: 264LT PRO */
1427dd7cddfSDavid du Colombier };
1437dd7cddfSDavid du Colombier
1449a747e4fSDavid du Colombier
1457dd7cddfSDavid du Colombier static int hwfill(VGAscr*, Rectangle, ulong);
1467dd7cddfSDavid du Colombier static int hwscroll(VGAscr*, Rectangle, Rectangle);
1477dd7cddfSDavid du Colombier static void initengine(VGAscr*);
1487dd7cddfSDavid du Colombier
1497dd7cddfSDavid du Colombier static Pcidev*
mach64xxpci(void)1507dd7cddfSDavid du Colombier mach64xxpci(void)
1517dd7cddfSDavid du Colombier {
1527dd7cddfSDavid du Colombier Pcidev *p;
1539a747e4fSDavid du Colombier int i;
1547dd7cddfSDavid du Colombier
1557dd7cddfSDavid du Colombier if((p = pcimatch(nil, 0x1002, 0)) == nil)
1567dd7cddfSDavid du Colombier return nil;
1579a747e4fSDavid du Colombier
1589a747e4fSDavid du Colombier for (i = 0; i != nelem(mach64s); i++)
1599a747e4fSDavid du Colombier if (mach64s[i].m64_id == p->did) {
1609a747e4fSDavid du Colombier mach64type = &mach64s[i];
1617dd7cddfSDavid du Colombier return p;
1627dd7cddfSDavid du Colombier }
1637dd7cddfSDavid du Colombier return nil;
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier
1667dd7cddfSDavid du Colombier static void
mach64xxenable(VGAscr * scr)1677dd7cddfSDavid du Colombier mach64xxenable(VGAscr* scr)
1687dd7cddfSDavid du Colombier {
1697dd7cddfSDavid du Colombier Pcidev *p;
1707dd7cddfSDavid du Colombier
1717dd7cddfSDavid du Colombier if(scr->io)
1727dd7cddfSDavid du Colombier return;
1737dd7cddfSDavid du Colombier if(p = mach64xxpci()){
1747dd7cddfSDavid du Colombier scr->id = p->did;
1754de34a7eSDavid du Colombier scr->pci = p;
1767dd7cddfSDavid du Colombier
1777dd7cddfSDavid du Colombier /*
1787dd7cddfSDavid du Colombier * The CT doesn't always have the I/O base address
1797dd7cddfSDavid du Colombier * in the PCI base registers. There is a way to find
1807dd7cddfSDavid du Colombier * it via the vendor-specific PCI config space but
1817dd7cddfSDavid du Colombier * this will do for now.
1827dd7cddfSDavid du Colombier */
1837dd7cddfSDavid du Colombier scr->io = p->mem[1].bar & ~0x03;
1847dd7cddfSDavid du Colombier
18559cc4ca5SDavid du Colombier if(scr->io == 0)
1867dd7cddfSDavid du Colombier scr->io = 0x2EC;
1877dd7cddfSDavid du Colombier }
1887dd7cddfSDavid du Colombier }
1897dd7cddfSDavid du Colombier
1904de34a7eSDavid du Colombier static void
mach64xxlinear(VGAscr * scr,int size,int)1914de34a7eSDavid du Colombier mach64xxlinear(VGAscr* scr, int size, int)
1927dd7cddfSDavid du Colombier {
193*8498559bSDavid du Colombier ulong mmiophys;
194*8498559bSDavid du Colombier
1954de34a7eSDavid du Colombier vgalinearpci(scr);
1964de34a7eSDavid du Colombier if(scr->paddr == 0)
1974de34a7eSDavid du Colombier return;
198*8498559bSDavid du Colombier /*
199*8498559bSDavid du Colombier * vgalinearpci sets framebuffer into write combining mode.
200*8498559bSDavid du Colombier * Because mmio register page is inside framebuffer space,
201*8498559bSDavid du Colombier * set it back to uncached.
202*8498559bSDavid du Colombier */
203*8498559bSDavid du Colombier mmiophys = scr->paddr + size - BY2PG;
204*8498559bSDavid du Colombier if(!waserror()){
205*8498559bSDavid du Colombier mtrr(mmiophys, BY2PG, "uc");
206*8498559bSDavid du Colombier poperror();
207*8498559bSDavid du Colombier }
2084de34a7eSDavid du Colombier scr->mmio = (ulong*)((uchar*)scr->vaddr+size-1024);
209*8498559bSDavid du Colombier addvgaseg("mach64mmio", mmiophys, BY2PG);
2104de34a7eSDavid du Colombier addvgaseg("mach64screen", scr->paddr, scr->apsize);
2117dd7cddfSDavid du Colombier }
2127dd7cddfSDavid du Colombier
2137dd7cddfSDavid du Colombier enum {
2147dd7cddfSDavid du Colombier CrtcOffPitch = 0x05,
2157dd7cddfSDavid du Colombier CrtcGenCtl = 0x07,
2167dd7cddfSDavid du Colombier CurClr0 = 0x0B, /* I/O Select */
2177dd7cddfSDavid du Colombier CurClr1 = 0x0C,
2187dd7cddfSDavid du Colombier CurOffset = 0x0D,
2197dd7cddfSDavid du Colombier CurHVposn = 0x0E,
2207dd7cddfSDavid du Colombier CurHVoff = 0x0F,
2217dd7cddfSDavid du Colombier BusCntl = 0x13,
2227dd7cddfSDavid du Colombier GenTestCntl = 0x19,
2237dd7cddfSDavid du Colombier
2247dd7cddfSDavid du Colombier CrtcHsyncDis = 0x04,
2257dd7cddfSDavid du Colombier CrtcVsyncDis = 0x08,
2267dd7cddfSDavid du Colombier
2277dd7cddfSDavid du Colombier ContextMask = 0x100, /* not accessible via I/O */
2287dd7cddfSDavid du Colombier FifoStat,
2297dd7cddfSDavid du Colombier GuiStat,
2307dd7cddfSDavid du Colombier DpFrgdClr,
2317dd7cddfSDavid du Colombier DpBkgdClr,
2327dd7cddfSDavid du Colombier DpWriteMask,
2337dd7cddfSDavid du Colombier DpMix,
2347dd7cddfSDavid du Colombier DpPixWidth,
2357dd7cddfSDavid du Colombier DpSrc,
2367dd7cddfSDavid du Colombier ClrCmpCntl,
2377dd7cddfSDavid du Colombier GuiTrajCntl,
2387dd7cddfSDavid du Colombier ScLeftRight,
2397dd7cddfSDavid du Colombier ScTopBottom,
2407dd7cddfSDavid du Colombier DstOffPitch,
2417dd7cddfSDavid du Colombier DstYX,
2427dd7cddfSDavid du Colombier DstHeightWidth,
2437dd7cddfSDavid du Colombier DstCntl,
2447dd7cddfSDavid du Colombier DstHeight,
2457dd7cddfSDavid du Colombier DstBresErr,
2467dd7cddfSDavid du Colombier DstBresInc,
2477dd7cddfSDavid du Colombier DstBresDec,
2487dd7cddfSDavid du Colombier SrcCntl,
2497dd7cddfSDavid du Colombier SrcHeight1Width1,
2507dd7cddfSDavid du Colombier SrcHeight2Width2,
2517dd7cddfSDavid du Colombier SrcYX,
2527dd7cddfSDavid du Colombier SrcWidth1,
2537dd7cddfSDavid du Colombier SrcYXstart,
2547dd7cddfSDavid du Colombier HostCntl,
2557dd7cddfSDavid du Colombier PatReg0,
2567dd7cddfSDavid du Colombier PatReg1,
2577dd7cddfSDavid du Colombier PatCntl,
2587dd7cddfSDavid du Colombier ScBottom,
2597dd7cddfSDavid du Colombier ScLeft,
2607dd7cddfSDavid du Colombier ScRight,
2617dd7cddfSDavid du Colombier ScTop,
2627dd7cddfSDavid du Colombier ClrCmpClr,
2637dd7cddfSDavid du Colombier ClrCmpMask,
2647dd7cddfSDavid du Colombier DpChainMask,
2657dd7cddfSDavid du Colombier SrcOffPitch,
2667dd7cddfSDavid du Colombier LcdIndex,
2677dd7cddfSDavid du Colombier LcdData,
2689a747e4fSDavid du Colombier ClockCntl,
2699a747e4fSDavid du Colombier OverlayScaleCntl,
2709a747e4fSDavid du Colombier ConfigChipId,
2719a747e4fSDavid du Colombier Buf0Pitch,
2729a747e4fSDavid du Colombier ScalerBuf0Pitch,
2739a747e4fSDavid du Colombier CaptureConfig,
2749a747e4fSDavid du Colombier OverlayKeyCntl,
2759a747e4fSDavid du Colombier ScalerColourCntl,
2769a747e4fSDavid du Colombier ScalerHCoef0,
2779a747e4fSDavid du Colombier ScalerHCoef1,
2789a747e4fSDavid du Colombier ScalerHCoef2,
2799a747e4fSDavid du Colombier ScalerHCoef3,
2809a747e4fSDavid du Colombier ScalerHCoef4,
2819a747e4fSDavid du Colombier VideoFormat,
2829a747e4fSDavid du Colombier Buf0Offset,
2839a747e4fSDavid du Colombier ScalerBuf0Offset,
2849a747e4fSDavid du Colombier CrtcGenCntl,
2859a747e4fSDavid du Colombier OverlayScaleInc,
2869a747e4fSDavid du Colombier OverlayYX,
2879a747e4fSDavid du Colombier OverlayYXEnd,
2889a747e4fSDavid du Colombier ScalerHeightWidth,
2899a747e4fSDavid du Colombier HTotalDisp,
2909a747e4fSDavid du Colombier VTotalDisp,
2917dd7cddfSDavid du Colombier };
2927dd7cddfSDavid du Colombier
2937dd7cddfSDavid du Colombier enum {
2947dd7cddfSDavid du Colombier LCD_ConfigPanel = 0,
2957dd7cddfSDavid du Colombier LCD_GenCtrl,
2967dd7cddfSDavid du Colombier LCD_DstnCntl,
2977dd7cddfSDavid du Colombier LCD_HfbPitchAddr,
2987dd7cddfSDavid du Colombier LCD_HorzStretch,
2997dd7cddfSDavid du Colombier LCD_VertStretch,
3007dd7cddfSDavid du Colombier LCD_ExtVertStretch,
3017dd7cddfSDavid du Colombier LCD_LtGio,
3027dd7cddfSDavid du Colombier LCD_PowerMngmnt,
3037dd7cddfSDavid du Colombier LCD_ZvgPio,
3047dd7cddfSDavid du Colombier Nlcd,
3057dd7cddfSDavid du Colombier };
3067dd7cddfSDavid du Colombier
3079a747e4fSDavid du Colombier #define Bank1 (-0x100) /* 1KB */
3089a747e4fSDavid du Colombier
3099a747e4fSDavid du Colombier static int mmoffset[] = {
3109a747e4fSDavid du Colombier [HTotalDisp] 0x00,
3119a747e4fSDavid du Colombier [VTotalDisp] 0x02,
3127dd7cddfSDavid du Colombier [CrtcOffPitch] 0x05,
3139a747e4fSDavid du Colombier [CrtcGenCntl] 0x07,
3147dd7cddfSDavid du Colombier [CurClr0] 0x18,
3157dd7cddfSDavid du Colombier [CurClr1] 0x19,
3167dd7cddfSDavid du Colombier [CurOffset] 0x1A,
3177dd7cddfSDavid du Colombier [CurHVposn] 0x1B,
3187dd7cddfSDavid du Colombier [CurHVoff] 0x1C,
3199a747e4fSDavid du Colombier [ClockCntl] 0x24,
3207dd7cddfSDavid du Colombier [BusCntl] 0x28,
3217dd7cddfSDavid du Colombier [LcdIndex] 0x29,
3227dd7cddfSDavid du Colombier [LcdData] 0x2A,
3237dd7cddfSDavid du Colombier [GenTestCntl] 0x34,
3249a747e4fSDavid du Colombier [ConfigChipId] 0x38,
3257dd7cddfSDavid du Colombier [DstOffPitch] 0x40,
3267dd7cddfSDavid du Colombier [DstYX] 0x43,
3277dd7cddfSDavid du Colombier [DstHeight] 0x45,
3287dd7cddfSDavid du Colombier [DstHeightWidth] 0x46,
3297dd7cddfSDavid du Colombier [DstBresErr] 0x49,
3307dd7cddfSDavid du Colombier [DstBresInc] 0x4A,
3317dd7cddfSDavid du Colombier [DstBresDec] 0x4B,
3327dd7cddfSDavid du Colombier [DstCntl] 0x4C,
3337dd7cddfSDavid du Colombier [SrcOffPitch] 0x60,
3347dd7cddfSDavid du Colombier [SrcYX] 0x63,
3357dd7cddfSDavid du Colombier [SrcWidth1] 0x64,
3367dd7cddfSDavid du Colombier [SrcYXstart] 0x69,
3377dd7cddfSDavid du Colombier [SrcHeight1Width1] 0x66,
3387dd7cddfSDavid du Colombier [SrcHeight2Width2] 0x6C,
3397dd7cddfSDavid du Colombier [SrcCntl] 0x6D,
3407dd7cddfSDavid du Colombier [HostCntl] 0x90,
3417dd7cddfSDavid du Colombier [PatReg0] 0xA0,
3427dd7cddfSDavid du Colombier [PatReg1] 0xA1,
3437dd7cddfSDavid du Colombier [PatCntl] 0xA2,
3447dd7cddfSDavid du Colombier [ScLeft] 0xA8,
3457dd7cddfSDavid du Colombier [ScRight] 0xA9,
3467dd7cddfSDavid du Colombier [ScLeftRight] 0xAA,
3477dd7cddfSDavid du Colombier [ScTop] 0xAB,
3487dd7cddfSDavid du Colombier [ScBottom] 0xAC,
3497dd7cddfSDavid du Colombier [ScTopBottom] 0xAD,
3507dd7cddfSDavid du Colombier [DpBkgdClr] 0xB0,
3517dd7cddfSDavid du Colombier [DpFrgdClr] 0xB1,
3527dd7cddfSDavid du Colombier [DpWriteMask] 0xB2,
3537dd7cddfSDavid du Colombier [DpChainMask] 0xB3,
3547dd7cddfSDavid du Colombier [DpPixWidth] 0xB4,
3557dd7cddfSDavid du Colombier [DpMix] 0xB5,
3567dd7cddfSDavid du Colombier [DpSrc] 0xB6,
3577dd7cddfSDavid du Colombier [ClrCmpClr] 0xC0,
3587dd7cddfSDavid du Colombier [ClrCmpMask] 0xC1,
3597dd7cddfSDavid du Colombier [ClrCmpCntl] 0xC2,
3607dd7cddfSDavid du Colombier [FifoStat] 0xC4,
3617dd7cddfSDavid du Colombier [ContextMask] 0xC8,
3627dd7cddfSDavid du Colombier [GuiTrajCntl] 0xCC,
3637dd7cddfSDavid du Colombier [GuiStat] 0xCE,
3649a747e4fSDavid du Colombier
3659a747e4fSDavid du Colombier /* Bank1 */
3669a747e4fSDavid du Colombier [OverlayYX] Bank1 + 0x00,
3679a747e4fSDavid du Colombier [OverlayYXEnd] Bank1 + 0x01,
3689a747e4fSDavid du Colombier [OverlayKeyCntl] Bank1 + 0x06,
3699a747e4fSDavid du Colombier [OverlayScaleInc] Bank1 + 0x08,
3709a747e4fSDavid du Colombier [OverlayScaleCntl] Bank1 + 0x09,
3719a747e4fSDavid du Colombier [ScalerHeightWidth] Bank1 + 0x0A,
3729a747e4fSDavid du Colombier [ScalerBuf0Offset] Bank1 + 0x0D,
3739a747e4fSDavid du Colombier [ScalerBuf0Pitch] Bank1 + 0x0F,
3749a747e4fSDavid du Colombier [VideoFormat] Bank1 + 0x12,
3759a747e4fSDavid du Colombier [CaptureConfig] Bank1 + 0x14,
3769a747e4fSDavid du Colombier [Buf0Offset] Bank1 + 0x20,
3779a747e4fSDavid du Colombier [Buf0Pitch] Bank1 + 0x23,
3789a747e4fSDavid du Colombier [ScalerColourCntl] Bank1 + 0x54,
3799a747e4fSDavid du Colombier [ScalerHCoef0] Bank1 + 0x55,
3809a747e4fSDavid du Colombier [ScalerHCoef1] Bank1 + 0x56,
3819a747e4fSDavid du Colombier [ScalerHCoef2] Bank1 + 0x57,
3829a747e4fSDavid du Colombier [ScalerHCoef3] Bank1 + 0x58,
3839a747e4fSDavid du Colombier [ScalerHCoef4] Bank1 + 0x59,
3847dd7cddfSDavid du Colombier };
3857dd7cddfSDavid du Colombier
3867dd7cddfSDavid du Colombier static ulong
ior32(VGAscr * scr,int r)3877dd7cddfSDavid du Colombier ior32(VGAscr* scr, int r)
3887dd7cddfSDavid du Colombier {
3897dd7cddfSDavid du Colombier if(scr->io == 0x2EC || scr->io == 0x1C8)
3907dd7cddfSDavid du Colombier return inl((r<<10)+scr->io);
3917dd7cddfSDavid du Colombier if(r >= 0x100 && scr->mmio != nil)
3927dd7cddfSDavid du Colombier return scr->mmio[mmoffset[r]];
3937dd7cddfSDavid du Colombier return inl((mmoffset[r]<<2)+scr->io);
3947dd7cddfSDavid du Colombier }
3957dd7cddfSDavid du Colombier
3967dd7cddfSDavid du Colombier static void
iow32(VGAscr * scr,int r,ulong l)3977dd7cddfSDavid du Colombier iow32(VGAscr* scr, int r, ulong l)
3987dd7cddfSDavid du Colombier {
3997dd7cddfSDavid du Colombier if(scr->io == 0x2EC || scr->io == 0x1C8)
4007dd7cddfSDavid du Colombier outl(((r)<<10)+scr->io, l);
4017dd7cddfSDavid du Colombier else if(r >= 0x100 && scr->mmio != nil)
4027dd7cddfSDavid du Colombier scr->mmio[mmoffset[r]] = l;
4037dd7cddfSDavid du Colombier else
4047dd7cddfSDavid du Colombier outl((mmoffset[r]<<2)+scr->io, l);
4057dd7cddfSDavid du Colombier }
4067dd7cddfSDavid du Colombier
4077dd7cddfSDavid du Colombier static ulong
lcdr32(VGAscr * scr,ulong r)4087dd7cddfSDavid du Colombier lcdr32(VGAscr *scr, ulong r)
4097dd7cddfSDavid du Colombier {
4107dd7cddfSDavid du Colombier ulong or;
4117dd7cddfSDavid du Colombier
4127dd7cddfSDavid du Colombier or = ior32(scr, LcdIndex);
4137dd7cddfSDavid du Colombier iow32(scr, LcdIndex, (or&~0x0F) | (r&0x0F));
4147dd7cddfSDavid du Colombier return ior32(scr, LcdData);
4157dd7cddfSDavid du Colombier }
4167dd7cddfSDavid du Colombier
4177dd7cddfSDavid du Colombier static void
lcdw32(VGAscr * scr,ulong r,ulong v)4187dd7cddfSDavid du Colombier lcdw32(VGAscr *scr, ulong r, ulong v)
4197dd7cddfSDavid du Colombier {
4207dd7cddfSDavid du Colombier ulong or;
4217dd7cddfSDavid du Colombier
4227dd7cddfSDavid du Colombier or = ior32(scr, LcdIndex);
4237dd7cddfSDavid du Colombier iow32(scr, LcdIndex, (or&~0x0F) | (r&0x0F));
4247dd7cddfSDavid du Colombier iow32(scr, LcdData, v);
4257dd7cddfSDavid du Colombier }
4267dd7cddfSDavid du Colombier
4277dd7cddfSDavid du Colombier static void
mach64xxcurdisable(VGAscr * scr)4287dd7cddfSDavid du Colombier mach64xxcurdisable(VGAscr* scr)
4297dd7cddfSDavid du Colombier {
4307dd7cddfSDavid du Colombier ulong r;
4317dd7cddfSDavid du Colombier
4327dd7cddfSDavid du Colombier r = ior32(scr, GenTestCntl);
4337dd7cddfSDavid du Colombier iow32(scr, GenTestCntl, r & ~0x80);
4347dd7cddfSDavid du Colombier }
4357dd7cddfSDavid du Colombier
4367dd7cddfSDavid du Colombier static void
mach64xxcurload(VGAscr * scr,Cursor * curs)4377dd7cddfSDavid du Colombier mach64xxcurload(VGAscr* scr, Cursor* curs)
4387dd7cddfSDavid du Colombier {
4397dd7cddfSDavid du Colombier uchar *p;
4407dd7cddfSDavid du Colombier int i, y;
4417dd7cddfSDavid du Colombier ulong c, s, m, r;
4427dd7cddfSDavid du Colombier
4437dd7cddfSDavid du Colombier /*
4447dd7cddfSDavid du Colombier * Disable the cursor.
4457dd7cddfSDavid du Colombier */
4467dd7cddfSDavid du Colombier r = ior32(scr, GenTestCntl);
4477dd7cddfSDavid du Colombier iow32(scr, GenTestCntl, r & ~0x80);
4487dd7cddfSDavid du Colombier
4494de34a7eSDavid du Colombier p = scr->vaddr;
4507dd7cddfSDavid du Colombier p += scr->storage;
4517dd7cddfSDavid du Colombier
4527dd7cddfSDavid du Colombier /*
4537dd7cddfSDavid du Colombier * Initialise the 64x64 cursor RAM array.
4547dd7cddfSDavid du Colombier * The cursor mode gives the following truth table:
4557dd7cddfSDavid du Colombier * p1 p0 colour
4567dd7cddfSDavid du Colombier * 0 0 Cursor Colour 0
4577dd7cddfSDavid du Colombier * 0 1 Cursor Colour 1
4587dd7cddfSDavid du Colombier * 1 0 Transparent
4597dd7cddfSDavid du Colombier * 1 1 Complement
4607dd7cddfSDavid du Colombier * Put the cursor into the top-right of the 64x64 array.
4617dd7cddfSDavid du Colombier */
4627dd7cddfSDavid du Colombier for(y = 0; y < 16; y++){
4637dd7cddfSDavid du Colombier for(i = 0; i < (64-16)/8; i++){
4647dd7cddfSDavid du Colombier *p++ = 0xAA;
4657dd7cddfSDavid du Colombier *p++ = 0xAA;
4667dd7cddfSDavid du Colombier }
4677dd7cddfSDavid du Colombier
4687dd7cddfSDavid du Colombier c = (curs->clr[2*y]<<8)|curs->clr[y*2 + 1];
4697dd7cddfSDavid du Colombier s = (curs->set[2*y]<<8)|curs->set[y*2 + 1];
4707dd7cddfSDavid du Colombier
4717dd7cddfSDavid du Colombier m = 0x00000000;
4727dd7cddfSDavid du Colombier for(i = 0; i < 16; i++){
4737dd7cddfSDavid du Colombier if(s & (1<<(15-i)))
4747dd7cddfSDavid du Colombier m |= 0x01<<(2*i);
4759a747e4fSDavid du Colombier else if(c & (1<<(15-i))){
4769a747e4fSDavid du Colombier /* nothing to do */
4779a747e4fSDavid du Colombier }
4787dd7cddfSDavid du Colombier else
4797dd7cddfSDavid du Colombier m |= 0x02<<(2*i);
4807dd7cddfSDavid du Colombier }
4817dd7cddfSDavid du Colombier *p++ = m;
4827dd7cddfSDavid du Colombier *p++ = m>>8;
4837dd7cddfSDavid du Colombier *p++ = m>>16;
4847dd7cddfSDavid du Colombier *p++ = m>>24;
4857dd7cddfSDavid du Colombier }
4867dd7cddfSDavid du Colombier memset(p, 0xAA, (64-16)*16);
4877dd7cddfSDavid du Colombier
4887dd7cddfSDavid du Colombier /*
4897dd7cddfSDavid du Colombier * Set the cursor hotpoint and enable the cursor.
4907dd7cddfSDavid du Colombier */
4917dd7cddfSDavid du Colombier scr->offset = curs->offset;
4927dd7cddfSDavid du Colombier iow32(scr, GenTestCntl, 0x80|r);
4937dd7cddfSDavid du Colombier }
4947dd7cddfSDavid du Colombier
4957dd7cddfSDavid du Colombier static int
ptalmostinrect(Point p,Rectangle r)4967dd7cddfSDavid du Colombier ptalmostinrect(Point p, Rectangle r)
4977dd7cddfSDavid du Colombier {
4987dd7cddfSDavid du Colombier return p.x>=r.min.x && p.x<=r.max.x &&
4997dd7cddfSDavid du Colombier p.y>=r.min.y && p.y<=r.max.y;
5007dd7cddfSDavid du Colombier }
5017dd7cddfSDavid du Colombier
5027dd7cddfSDavid du Colombier /*
5037dd7cddfSDavid du Colombier * If necessary, translate the rectangle physr
5047dd7cddfSDavid du Colombier * some multiple of [dx dy] so that it includes p.
5057dd7cddfSDavid du Colombier * Return 1 if the rectangle changed.
5067dd7cddfSDavid du Colombier */
5077dd7cddfSDavid du Colombier static int
screenpan(Point p,Rectangle * physr,int dx,int dy)5087dd7cddfSDavid du Colombier screenpan(Point p, Rectangle *physr, int dx, int dy)
5097dd7cddfSDavid du Colombier {
5107dd7cddfSDavid du Colombier int d;
5117dd7cddfSDavid du Colombier
5127dd7cddfSDavid du Colombier if(ptalmostinrect(p, *physr))
5137dd7cddfSDavid du Colombier return 0;
5147dd7cddfSDavid du Colombier
5157dd7cddfSDavid du Colombier if(p.y < physr->min.y){
5167dd7cddfSDavid du Colombier d = physr->min.y - (p.y&~(dy-1));
5177dd7cddfSDavid du Colombier physr->min.y -= d;
5187dd7cddfSDavid du Colombier physr->max.y -= d;
5197dd7cddfSDavid du Colombier }
5207dd7cddfSDavid du Colombier if(p.y > physr->max.y){
5217dd7cddfSDavid du Colombier d = ((p.y+dy-1)&~(dy-1)) - physr->max.y;
5227dd7cddfSDavid du Colombier physr->min.y += d;
5237dd7cddfSDavid du Colombier physr->max.y += d;
5247dd7cddfSDavid du Colombier }
5257dd7cddfSDavid du Colombier
5267dd7cddfSDavid du Colombier if(p.x < physr->min.x){
5277dd7cddfSDavid du Colombier d = physr->min.x - (p.x&~(dx-1));
5287dd7cddfSDavid du Colombier physr->min.x -= d;
5297dd7cddfSDavid du Colombier physr->max.x -= d;
5307dd7cddfSDavid du Colombier }
5317dd7cddfSDavid du Colombier if(p.x > physr->max.x){
5327dd7cddfSDavid du Colombier d = ((p.x+dx-1)&~(dx-1)) - physr->max.x;
5337dd7cddfSDavid du Colombier physr->min.x += d;
5347dd7cddfSDavid du Colombier physr->max.x += d;
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier return 1;
5377dd7cddfSDavid du Colombier }
5387dd7cddfSDavid du Colombier
5397dd7cddfSDavid du Colombier static int
mach64xxcurmove(VGAscr * scr,Point p)5407dd7cddfSDavid du Colombier mach64xxcurmove(VGAscr* scr, Point p)
5417dd7cddfSDavid du Colombier {
5427dd7cddfSDavid du Colombier int x, xo, y, yo;
5437dd7cddfSDavid du Colombier int dx;
5447dd7cddfSDavid du Colombier ulong off, pitch;
5457dd7cddfSDavid du Colombier
5467dd7cddfSDavid du Colombier /*
5477dd7cddfSDavid du Colombier * If the point we want to display is outside the current
5487dd7cddfSDavid du Colombier * screen rectangle, pan the screen to display it.
5497dd7cddfSDavid du Colombier *
5507dd7cddfSDavid du Colombier * We have to move in 64-bit chunks.
5517dd7cddfSDavid du Colombier */
5527dd7cddfSDavid du Colombier if(scr->gscreen->depth == 24)
5537dd7cddfSDavid du Colombier dx = (64*3)/24;
5547dd7cddfSDavid du Colombier else
5557dd7cddfSDavid du Colombier dx = 64 / scr->gscreen->depth;
5567dd7cddfSDavid du Colombier
5579a747e4fSDavid du Colombier if(panning && screenpan(p, &physgscreenr, dx, 1)){
5587dd7cddfSDavid du Colombier off = (physgscreenr.min.y*Dx(scr->gscreen->r)+physgscreenr.min.x)/dx;
5597dd7cddfSDavid du Colombier pitch = Dx(scr->gscreen->r)/8;
5607dd7cddfSDavid du Colombier iow32(scr, CrtcOffPitch, (pitch<<22)|off);
5617dd7cddfSDavid du Colombier }
5627dd7cddfSDavid du Colombier
5637dd7cddfSDavid du Colombier p.x -= physgscreenr.min.x;
5647dd7cddfSDavid du Colombier p.y -= physgscreenr.min.y;
5657dd7cddfSDavid du Colombier
5667dd7cddfSDavid du Colombier /*
5677dd7cddfSDavid du Colombier * Mustn't position the cursor offscreen even partially,
5687dd7cddfSDavid du Colombier * or it disappears. Therefore, if x or y is -ve, adjust the
5697dd7cddfSDavid du Colombier * cursor presets instead. If y is negative also have to
5707dd7cddfSDavid du Colombier * adjust the starting offset.
5717dd7cddfSDavid du Colombier */
5727dd7cddfSDavid du Colombier if((x = p.x+scr->offset.x) < 0){
5737dd7cddfSDavid du Colombier xo = x;
5747dd7cddfSDavid du Colombier x = 0;
5757dd7cddfSDavid du Colombier }
5767dd7cddfSDavid du Colombier else
5777dd7cddfSDavid du Colombier xo = 0;
5787dd7cddfSDavid du Colombier if((y = p.y+scr->offset.y) < 0){
5797dd7cddfSDavid du Colombier yo = y;
5807dd7cddfSDavid du Colombier y = 0;
5817dd7cddfSDavid du Colombier }
5827dd7cddfSDavid du Colombier else
5837dd7cddfSDavid du Colombier yo = 0;
5847dd7cddfSDavid du Colombier
5857dd7cddfSDavid du Colombier iow32(scr, CurHVoff, ((64-16-yo)<<16)|(64-16-xo));
5867dd7cddfSDavid du Colombier iow32(scr, CurOffset, scr->storage/8 + (-yo*2));
5877dd7cddfSDavid du Colombier iow32(scr, CurHVposn, (y<<16)|x);
5887dd7cddfSDavid du Colombier
5897dd7cddfSDavid du Colombier return 0;
5907dd7cddfSDavid du Colombier }
5917dd7cddfSDavid du Colombier
5927dd7cddfSDavid du Colombier static void
mach64xxcurenable(VGAscr * scr)5937dd7cddfSDavid du Colombier mach64xxcurenable(VGAscr* scr)
5947dd7cddfSDavid du Colombier {
5957dd7cddfSDavid du Colombier ulong r, storage;
5967dd7cddfSDavid du Colombier
5977dd7cddfSDavid du Colombier mach64xxenable(scr);
5987dd7cddfSDavid du Colombier if(scr->io == 0)
5997dd7cddfSDavid du Colombier return;
6007dd7cddfSDavid du Colombier
6017dd7cddfSDavid du Colombier r = ior32(scr, GenTestCntl);
6027dd7cddfSDavid du Colombier iow32(scr, GenTestCntl, r & ~0x80);
6037dd7cddfSDavid du Colombier
6047dd7cddfSDavid du Colombier iow32(scr, CurClr0, (Pwhite<<24)|(Pwhite<<16)|(Pwhite<<8)|Pwhite);
6057dd7cddfSDavid du Colombier iow32(scr, CurClr1, (Pblack<<24)|(Pblack<<16)|(Pblack<<8)|Pblack);
6067dd7cddfSDavid du Colombier
6077dd7cddfSDavid du Colombier /*
6087dd7cddfSDavid du Colombier * Find a place for the cursor data in display memory.
6097dd7cddfSDavid du Colombier * Must be 64-bit aligned.
6107dd7cddfSDavid du Colombier */
6117dd7cddfSDavid du Colombier storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+7)/8;
6127dd7cddfSDavid du Colombier iow32(scr, CurOffset, storage);
6137dd7cddfSDavid du Colombier scr->storage = storage*8;
6147dd7cddfSDavid du Colombier
6157dd7cddfSDavid du Colombier /*
6167dd7cddfSDavid du Colombier * Cursor goes in the top right corner of the 64x64 array
6177dd7cddfSDavid du Colombier * so the horizontal and vertical presets are 64-16.
6187dd7cddfSDavid du Colombier */
6197dd7cddfSDavid du Colombier iow32(scr, CurHVposn, (0<<16)|0);
6207dd7cddfSDavid du Colombier iow32(scr, CurHVoff, ((64-16)<<16)|(64-16));
6217dd7cddfSDavid du Colombier
6227dd7cddfSDavid du Colombier /*
6237dd7cddfSDavid du Colombier * Load, locate and enable the 64x64 cursor.
6247dd7cddfSDavid du Colombier */
6257dd7cddfSDavid du Colombier mach64xxcurload(scr, &arrow);
6267dd7cddfSDavid du Colombier mach64xxcurmove(scr, ZP);
6277dd7cddfSDavid du Colombier iow32(scr, GenTestCntl, 0x80|r);
6287dd7cddfSDavid du Colombier }
6297dd7cddfSDavid du Colombier
6307dd7cddfSDavid du Colombier static void
waitforfifo(VGAscr * scr,int entries)6317dd7cddfSDavid du Colombier waitforfifo(VGAscr *scr, int entries)
6327dd7cddfSDavid du Colombier {
6337dd7cddfSDavid du Colombier int x;
63459c21d95SDavid du Colombier
6357dd7cddfSDavid du Colombier x = 0;
6367dd7cddfSDavid du Colombier while((ior32(scr, FifoStat)&0xFF) > (0x8000>>entries) && x++ < 1000000)
6377dd7cddfSDavid du Colombier ;
6387dd7cddfSDavid du Colombier if(x >= 1000000)
639567483c8SDavid du Colombier iprint("fifo %d stat %#.8lux %#.8lux scrio %#.8lux mmio %#p scr %#p pc %#p\n", entries, ior32(scr, FifoStat), scr->mmio[mmoffset[FifoStat]], scr->io, scr->mmio, scr, getcallerpc(&scr));
6407dd7cddfSDavid du Colombier }
6417dd7cddfSDavid du Colombier
6427dd7cddfSDavid du Colombier static void
waitforidle(VGAscr * scr)6437dd7cddfSDavid du Colombier waitforidle(VGAscr *scr)
6447dd7cddfSDavid du Colombier {
6457dd7cddfSDavid du Colombier int x;
64659c21d95SDavid du Colombier
6477dd7cddfSDavid du Colombier waitforfifo(scr, 16);
6487dd7cddfSDavid du Colombier x = 0;
6497dd7cddfSDavid du Colombier while((ior32(scr, GuiStat)&1) && x++ < 1000000)
6507dd7cddfSDavid du Colombier ;
6517dd7cddfSDavid du Colombier if(x >= 1000000)
652567483c8SDavid du Colombier iprint("idle stat %#.8lux %#.8lux scrio %#.8lux mmio %#p scr %#p pc %#p\n", ior32(scr, GuiStat), scr->mmio[mmoffset[GuiStat]], scr->io, scr->mmio, scr, getcallerpc(&scr));
6537dd7cddfSDavid du Colombier }
6547dd7cddfSDavid du Colombier
6557dd7cddfSDavid du Colombier static void
resetengine(VGAscr * scr)6567dd7cddfSDavid du Colombier resetengine(VGAscr *scr)
6577dd7cddfSDavid du Colombier {
6587dd7cddfSDavid du Colombier ulong x;
6597dd7cddfSDavid du Colombier x = ior32(scr, GenTestCntl);
6607dd7cddfSDavid du Colombier iow32(scr, GenTestCntl, x&~0x100);
6617dd7cddfSDavid du Colombier iow32(scr, GenTestCntl, x|0x100);
6627dd7cddfSDavid du Colombier iow32(scr, BusCntl, ior32(scr, BusCntl)|0x00A00000);
6637dd7cddfSDavid du Colombier }
6647dd7cddfSDavid du Colombier
6657dd7cddfSDavid du Colombier static void
init_overlayclock(VGAscr * scr)6669a747e4fSDavid du Colombier init_overlayclock(VGAscr *scr)
6679a747e4fSDavid du Colombier {
6689a747e4fSDavid du Colombier uchar *cc, save, pll_ref_div, pll_vclk_cntl, vclk_post_div,
6699a747e4fSDavid du Colombier vclk_fb_div, ecp_div;
6709a747e4fSDavid du Colombier int i;
6719a747e4fSDavid du Colombier ulong dotclock;
6729a747e4fSDavid du Colombier
6739a747e4fSDavid du Colombier /* Taken from GLX */
6749a747e4fSDavid du Colombier /* Get monitor dotclock, check for Overlay Scaler clock limit */
6759a747e4fSDavid du Colombier cc = (uchar *)&scr->mmio[mmoffset[ClockCntl]];
6769a747e4fSDavid du Colombier save = cc[1]; i = cc[0] & 3;
6779a747e4fSDavid du Colombier cc[1] = 2<<2; pll_ref_div = cc[2];
6789a747e4fSDavid du Colombier cc[1] = 5<<2; pll_vclk_cntl = cc[2];
6799a747e4fSDavid du Colombier cc[1] = 6<<2; vclk_post_div = (cc[2]>>(i+i)) & 3;
6809a747e4fSDavid du Colombier cc[1] = (7+i)<<2; vclk_fb_div = cc[2];
6819a747e4fSDavid du Colombier
6829a747e4fSDavid du Colombier dotclock = 2 * mach64refclock * vclk_fb_div /
6839a747e4fSDavid du Colombier (pll_ref_div * (1 << vclk_post_div));
6849a747e4fSDavid du Colombier /* ecp_div: 0=dotclock, 1=dotclock/2, 2=dotclock/4 */
6859a747e4fSDavid du Colombier ecp_div = dotclock / mach64type->m64_ovlclock;
6869a747e4fSDavid du Colombier if (ecp_div>2) ecp_div = 2;
6879a747e4fSDavid du Colombier
6889a747e4fSDavid du Colombier /* Force a scaler clock factor of 1 if refclock *
6899a747e4fSDavid du Colombier * is unknown (VCLK_SRC not PLLVCLK) */
6909a747e4fSDavid du Colombier if ((pll_vclk_cntl & 0x03) != 0x03)
6919a747e4fSDavid du Colombier ecp_div = 0;
6929a747e4fSDavid du Colombier if ((pll_vclk_cntl & 0x30) != ecp_div<<4) {
6939a747e4fSDavid du Colombier cc[1] = (5<<2)|2;
6949a747e4fSDavid du Colombier cc[2] = (pll_vclk_cntl&0xCF) | (ecp_div<<4);
6959a747e4fSDavid du Colombier }
6969a747e4fSDavid du Colombier
6979a747e4fSDavid du Colombier /* Restore PLL Register Index */
6989a747e4fSDavid du Colombier cc[1] = save;
6999a747e4fSDavid du Colombier }
7009a747e4fSDavid du Colombier
7019a747e4fSDavid du Colombier static void
initengine(VGAscr * scr)7027dd7cddfSDavid du Colombier initengine(VGAscr *scr)
7037dd7cddfSDavid du Colombier {
7047dd7cddfSDavid du Colombier ulong pitch;
7059a747e4fSDavid du Colombier uchar *bios;
7069a747e4fSDavid du Colombier ushort table;
7077dd7cddfSDavid du Colombier
7087dd7cddfSDavid du Colombier pitch = Dx(scr->gscreen->r)/8;
7097dd7cddfSDavid du Colombier if(scr->gscreen->depth == 24)
7107dd7cddfSDavid du Colombier pitch *= 3;
7117dd7cddfSDavid du Colombier
7127dd7cddfSDavid du Colombier resetengine(scr);
7137dd7cddfSDavid du Colombier waitforfifo(scr, 14);
7147dd7cddfSDavid du Colombier iow32(scr, ContextMask, ~0);
7157dd7cddfSDavid du Colombier iow32(scr, DstOffPitch, pitch<<22);
7167dd7cddfSDavid du Colombier iow32(scr, DstYX, 0);
7177dd7cddfSDavid du Colombier iow32(scr, DstHeight, 0);
7187dd7cddfSDavid du Colombier iow32(scr, DstBresErr, 0);
7197dd7cddfSDavid du Colombier iow32(scr, DstBresInc, 0);
7207dd7cddfSDavid du Colombier iow32(scr, DstBresDec, 0);
7217dd7cddfSDavid du Colombier iow32(scr, DstCntl, 0x23);
7227dd7cddfSDavid du Colombier iow32(scr, SrcOffPitch, pitch<<22);
7237dd7cddfSDavid du Colombier iow32(scr, SrcYX, 0);
7247dd7cddfSDavid du Colombier iow32(scr, SrcHeight1Width1, 1);
7257dd7cddfSDavid du Colombier iow32(scr, SrcYXstart, 0);
7267dd7cddfSDavid du Colombier iow32(scr, SrcHeight2Width2, 1);
7277dd7cddfSDavid du Colombier iow32(scr, SrcCntl, 0x01);
7287dd7cddfSDavid du Colombier
7297dd7cddfSDavid du Colombier waitforfifo(scr, 13);
7307dd7cddfSDavid du Colombier iow32(scr, HostCntl, 0);
7317dd7cddfSDavid du Colombier iow32(scr, PatReg0, 0);
7327dd7cddfSDavid du Colombier iow32(scr, PatReg1, 0);
7337dd7cddfSDavid du Colombier iow32(scr, PatCntl, 0);
7347dd7cddfSDavid du Colombier iow32(scr, ScLeft, 0);
7357dd7cddfSDavid du Colombier iow32(scr, ScTop, 0);
7367dd7cddfSDavid du Colombier iow32(scr, ScBottom, 0xFFFF);
7377dd7cddfSDavid du Colombier iow32(scr, ScRight, 0xFFFF);
7387dd7cddfSDavid du Colombier iow32(scr, DpBkgdClr, 0);
7397dd7cddfSDavid du Colombier iow32(scr, DpFrgdClr, ~0);
7407dd7cddfSDavid du Colombier iow32(scr, DpWriteMask, ~0);
7417dd7cddfSDavid du Colombier iow32(scr, DpMix, 0x70003);
7427dd7cddfSDavid du Colombier iow32(scr, DpSrc, 0x00010100);
7437dd7cddfSDavid du Colombier
7447dd7cddfSDavid du Colombier waitforfifo(scr, 3);
7457dd7cddfSDavid du Colombier iow32(scr, ClrCmpClr, 0);
7467dd7cddfSDavid du Colombier iow32(scr, ClrCmpMask, ~0);
7477dd7cddfSDavid du Colombier iow32(scr, ClrCmpCntl, 0);
7487dd7cddfSDavid du Colombier
7497dd7cddfSDavid du Colombier waitforfifo(scr, 2);
7507dd7cddfSDavid du Colombier switch(scr->gscreen->depth){
7517dd7cddfSDavid du Colombier case 8:
7527dd7cddfSDavid du Colombier case 24: /* [sic] */
7537dd7cddfSDavid du Colombier iow32(scr, DpPixWidth, 0x00020202);
7547dd7cddfSDavid du Colombier iow32(scr, DpChainMask, 0x8080);
7557dd7cddfSDavid du Colombier break;
7567dd7cddfSDavid du Colombier case 16:
7577dd7cddfSDavid du Colombier iow32(scr, DpPixWidth, 0x00040404);
7587dd7cddfSDavid du Colombier iow32(scr, DpChainMask, 0x8410);
7597dd7cddfSDavid du Colombier break;
7607dd7cddfSDavid du Colombier case 32:
7617dd7cddfSDavid du Colombier iow32(scr, DpPixWidth, 0x00060606);
7627dd7cddfSDavid du Colombier iow32(scr, DpChainMask, 0x8080);
7637dd7cddfSDavid du Colombier break;
7647dd7cddfSDavid du Colombier }
7657dd7cddfSDavid du Colombier
7669a747e4fSDavid du Colombier /* Get the base freq from the BIOS */
7674de34a7eSDavid du Colombier bios = kaddr(0xC000);
7689a747e4fSDavid du Colombier table = *(ushort *)(bios + 0x48);
7699a747e4fSDavid du Colombier table = *(ushort *)(bios + table + 0x10);
7709a747e4fSDavid du Colombier switch (*(ushort *)(bios + table + 0x08)) {
7719a747e4fSDavid du Colombier case 2700:
7729a747e4fSDavid du Colombier mach64refclock = 270000;
7739a747e4fSDavid du Colombier break;
7749a747e4fSDavid du Colombier case 2863:
7759a747e4fSDavid du Colombier case 2864:
7769a747e4fSDavid du Colombier mach64refclock = 286363;
7779a747e4fSDavid du Colombier break;
7789a747e4fSDavid du Colombier case 2950:
7799a747e4fSDavid du Colombier mach64refclock = 294989;
7809a747e4fSDavid du Colombier break;
7819a747e4fSDavid du Colombier case 1432:
7829a747e4fSDavid du Colombier default:
7839a747e4fSDavid du Colombier mach64refclock = 143181;
7849a747e4fSDavid du Colombier break ;
7859a747e4fSDavid du Colombier }
7869a747e4fSDavid du Colombier
7879a747e4fSDavid du Colombier /* Figure out which revision this chip is */
7889a747e4fSDavid du Colombier switch ((scr->mmio[mmoffset[ConfigChipId]] >> 24) & 0xFF) {
7899a747e4fSDavid du Colombier case VTGTB1S1:
7909a747e4fSDavid du Colombier case GTB1U1:
7919a747e4fSDavid du Colombier case GTB1S2:
7929a747e4fSDavid du Colombier case GTB2U1:
7939a747e4fSDavid du Colombier case GTB2U2:
7949a747e4fSDavid du Colombier case GTB2U3:
7959a747e4fSDavid du Colombier case GTBC:
7969a747e4fSDavid du Colombier case GTIIIC1U1:
7979a747e4fSDavid du Colombier case GTIIIC1U2:
7989a747e4fSDavid du Colombier case GTIIIC2U1:
7999a747e4fSDavid du Colombier case GTIIIC2U2:
8009a747e4fSDavid du Colombier case GTIIIC2U3:
8019a747e4fSDavid du Colombier case LTPRO:
8029a747e4fSDavid du Colombier mach64revb = 1;
8039a747e4fSDavid du Colombier break;
8049a747e4fSDavid du Colombier default:
8059a747e4fSDavid du Colombier mach64revb = 0;
8069a747e4fSDavid du Colombier break;
8079a747e4fSDavid du Colombier }
8089a747e4fSDavid du Colombier
8097dd7cddfSDavid du Colombier waitforidle(scr);
8107dd7cddfSDavid du Colombier }
8117dd7cddfSDavid du Colombier
8127dd7cddfSDavid du Colombier static int
mach64hwfill(VGAscr * scr,Rectangle r,ulong sval)8137dd7cddfSDavid du Colombier mach64hwfill(VGAscr *scr, Rectangle r, ulong sval)
8147dd7cddfSDavid du Colombier {
8157dd7cddfSDavid du Colombier ulong pitch;
8167dd7cddfSDavid du Colombier ulong ctl;
8177dd7cddfSDavid du Colombier
8187dd7cddfSDavid du Colombier if(drawdebug)
8197dd7cddfSDavid du Colombier iprint("hwfill %R val %lux...\n", r, sval);
8207dd7cddfSDavid du Colombier
8217dd7cddfSDavid du Colombier /* shouldn't happen */
8227dd7cddfSDavid du Colombier if(scr->io == 0x2EC || scr->io == 0x1C8 || scr->io == 0)
8237dd7cddfSDavid du Colombier return 0;
8247dd7cddfSDavid du Colombier
8257dd7cddfSDavid du Colombier pitch = Dx(scr->gscreen->r)/8;
8267dd7cddfSDavid du Colombier ctl = 1|2; /* left-to-right, top-to-bottom */
8277dd7cddfSDavid du Colombier if(scr->gscreen->depth == 24){
8287dd7cddfSDavid du Colombier r.min.x *= 3;
8297dd7cddfSDavid du Colombier r.max.x *= 3;
8307dd7cddfSDavid du Colombier pitch *= 3;
8317dd7cddfSDavid du Colombier ctl |= (1<<7)|(((r.min.x/4)%6)<<8);
8327dd7cddfSDavid du Colombier }
8337dd7cddfSDavid du Colombier
8347dd7cddfSDavid du Colombier waitforfifo(scr, 11);
8357dd7cddfSDavid du Colombier iow32(scr, DpFrgdClr, sval);
8367dd7cddfSDavid du Colombier iow32(scr, DpWriteMask, 0xFFFFFFFF);
8377dd7cddfSDavid du Colombier iow32(scr, DpMix, 0x00070003);
8387dd7cddfSDavid du Colombier iow32(scr, DpSrc, 0x00000111);
8397dd7cddfSDavid du Colombier iow32(scr, ClrCmpCntl, 0x00000000);
8407dd7cddfSDavid du Colombier iow32(scr, ScLeftRight, 0x1FFF0000);
8417dd7cddfSDavid du Colombier iow32(scr, ScTopBottom, 0x1FFF0000);
8427dd7cddfSDavid du Colombier iow32(scr, DstOffPitch, pitch<<22);
8437dd7cddfSDavid du Colombier iow32(scr, DstCntl, ctl);
8447dd7cddfSDavid du Colombier iow32(scr, DstYX, (r.min.x<<16)|r.min.y);
8457dd7cddfSDavid du Colombier iow32(scr, DstHeightWidth, (Dx(r)<<16)|Dy(r));
8467dd7cddfSDavid du Colombier
8477dd7cddfSDavid du Colombier waitforidle(scr);
8487dd7cddfSDavid du Colombier return 1;
8497dd7cddfSDavid du Colombier }
8507dd7cddfSDavid du Colombier
8517dd7cddfSDavid du Colombier static int
mach64hwscroll(VGAscr * scr,Rectangle r,Rectangle sr)8527dd7cddfSDavid du Colombier mach64hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
8537dd7cddfSDavid du Colombier {
8547dd7cddfSDavid du Colombier ulong pitch;
8557dd7cddfSDavid du Colombier Point dp, sp;
8567dd7cddfSDavid du Colombier ulong ctl;
8577dd7cddfSDavid du Colombier int dx, dy;
8587dd7cddfSDavid du Colombier
8597dd7cddfSDavid du Colombier dx = Dx(r);
8607dd7cddfSDavid du Colombier dy = Dy(r);
8617dd7cddfSDavid du Colombier pitch = Dx(scr->gscreen->r)/8;
8627dd7cddfSDavid du Colombier if(scr->gscreen->depth == 24){
8637dd7cddfSDavid du Colombier dx *= 3;
8647dd7cddfSDavid du Colombier pitch *= 3;
8657dd7cddfSDavid du Colombier r.min.x *= 3;
8667dd7cddfSDavid du Colombier sr.min.x *= 3;
8677dd7cddfSDavid du Colombier }
8687dd7cddfSDavid du Colombier
8697dd7cddfSDavid du Colombier ctl = 0;
8707dd7cddfSDavid du Colombier if(r.min.x <= sr.min.x){
8717dd7cddfSDavid du Colombier ctl |= 1;
8727dd7cddfSDavid du Colombier dp.x = r.min.x;
8737dd7cddfSDavid du Colombier sp.x = sr.min.x;
8747dd7cddfSDavid du Colombier }else{
8757dd7cddfSDavid du Colombier dp.x = r.min.x+dx-1;
8767dd7cddfSDavid du Colombier sp.x = sr.min.x+dx-1;
8777dd7cddfSDavid du Colombier }
8787dd7cddfSDavid du Colombier
8797dd7cddfSDavid du Colombier if(r.min.y <= sr.min.y){
8807dd7cddfSDavid du Colombier ctl |= 2;
8817dd7cddfSDavid du Colombier dp.y = r.min.y;
8827dd7cddfSDavid du Colombier sp.y = sr.min.y;
8837dd7cddfSDavid du Colombier }else{
8847dd7cddfSDavid du Colombier dp.y = r.min.y+dy-1;
8857dd7cddfSDavid du Colombier sp.y = sr.min.y+dy-1;
8867dd7cddfSDavid du Colombier }
8877dd7cddfSDavid du Colombier
8887dd7cddfSDavid du Colombier if(scr->gscreen->depth == 24)
8897dd7cddfSDavid du Colombier ctl |= (1<<7)|(((dp.x/4)%6)<<8);
8907dd7cddfSDavid du Colombier
8917dd7cddfSDavid du Colombier waitforfifo(scr, 6);
8927dd7cddfSDavid du Colombier iow32(scr, ScLeftRight, 0x1FFF0000);
8937dd7cddfSDavid du Colombier iow32(scr, ScTopBottom, 0x1FFF0000);
8947dd7cddfSDavid du Colombier iow32(scr, DpWriteMask, 0xFFFFFFFF);
8957dd7cddfSDavid du Colombier iow32(scr, DpMix, 0x00070003);
8967dd7cddfSDavid du Colombier iow32(scr, DpSrc, 0x00000300);
8977dd7cddfSDavid du Colombier iow32(scr, ClrCmpCntl, 0x00000000);
8987dd7cddfSDavid du Colombier
8997dd7cddfSDavid du Colombier waitforfifo(scr, 8);
9007dd7cddfSDavid du Colombier iow32(scr, SrcOffPitch, pitch<<22);
9017dd7cddfSDavid du Colombier iow32(scr, SrcCntl, 0x00000000);
9027dd7cddfSDavid du Colombier iow32(scr, SrcYX, (sp.x<<16)|sp.y);
9037dd7cddfSDavid du Colombier iow32(scr, SrcWidth1, dx);
9047dd7cddfSDavid du Colombier iow32(scr, DstOffPitch, pitch<<22);
9057dd7cddfSDavid du Colombier iow32(scr, DstCntl, ctl);
9067dd7cddfSDavid du Colombier
9077dd7cddfSDavid du Colombier iow32(scr, DstYX, (dp.x<<16)|dp.y);
9087dd7cddfSDavid du Colombier iow32(scr, DstHeightWidth, (dx<<16)|dy);
9097dd7cddfSDavid du Colombier
9107dd7cddfSDavid du Colombier waitforidle(scr);
9117dd7cddfSDavid du Colombier
9127dd7cddfSDavid du Colombier return 1;
9137dd7cddfSDavid du Colombier }
9147dd7cddfSDavid du Colombier
9157dd7cddfSDavid du Colombier /*
9167dd7cddfSDavid du Colombier * This should work, but doesn't.
9177dd7cddfSDavid du Colombier * It messes up the screen timings for some reason.
9187dd7cddfSDavid du Colombier */
9197dd7cddfSDavid du Colombier static void
mach64blank(VGAscr * scr,int blank)9207dd7cddfSDavid du Colombier mach64blank(VGAscr *scr, int blank)
9217dd7cddfSDavid du Colombier {
9227dd7cddfSDavid du Colombier ulong ctl;
9237dd7cddfSDavid du Colombier
9247dd7cddfSDavid du Colombier ctl = ior32(scr, CrtcGenCtl) & ~(CrtcHsyncDis|CrtcVsyncDis);
9257dd7cddfSDavid du Colombier if(blank)
9267dd7cddfSDavid du Colombier ctl |= CrtcHsyncDis|CrtcVsyncDis;
9277dd7cddfSDavid du Colombier iow32(scr, CrtcGenCtl, ctl);
9287dd7cddfSDavid du Colombier }
9297dd7cddfSDavid du Colombier
9307dd7cddfSDavid du Colombier /*
9317dd7cddfSDavid du Colombier * We squirrel away whether the LCD and/or CRT were
9327dd7cddfSDavid du Colombier * on when we were called to blank the screen, and
9337dd7cddfSDavid du Colombier * restore the old state. If we are called to blank the
9347dd7cddfSDavid du Colombier * screen when it is already blank, we don't update the state.
9357dd7cddfSDavid du Colombier * Such a call sequence should not happen, though.
9367dd7cddfSDavid du Colombier *
9377dd7cddfSDavid du Colombier * We could try forcing the chip into power management
9387dd7cddfSDavid du Colombier * mode instead, but I'm not sure how that would interact
9397dd7cddfSDavid du Colombier * with screen updates going on while the screen is blanked.
9407dd7cddfSDavid du Colombier */
9417dd7cddfSDavid du Colombier static void
mach64lcdblank(VGAscr * scr,int blank)9427dd7cddfSDavid du Colombier mach64lcdblank(VGAscr *scr, int blank)
9437dd7cddfSDavid du Colombier {
9447dd7cddfSDavid du Colombier static int crtlcd;
9457dd7cddfSDavid du Colombier ulong x;
9467dd7cddfSDavid du Colombier
9477dd7cddfSDavid du Colombier if(blank) {
9487dd7cddfSDavid du Colombier x = lcdr32(scr, LCD_GenCtrl);
9497dd7cddfSDavid du Colombier if(x & 3) {
9507dd7cddfSDavid du Colombier crtlcd = x & 3;
9517dd7cddfSDavid du Colombier lcdw32(scr, LCD_GenCtrl, x&~3);
9527dd7cddfSDavid du Colombier }
9537dd7cddfSDavid du Colombier } else {
9547dd7cddfSDavid du Colombier if(crtlcd == 0)
9557dd7cddfSDavid du Colombier crtlcd = 2; /* lcd only */
9567dd7cddfSDavid du Colombier x = lcdr32(scr, LCD_GenCtrl);
9577dd7cddfSDavid du Colombier lcdw32(scr, LCD_GenCtrl, x | crtlcd);
9587dd7cddfSDavid du Colombier }
9597dd7cddfSDavid du Colombier }
9607dd7cddfSDavid du Colombier
9617dd7cddfSDavid du Colombier static void
mach64xxdrawinit(VGAscr * scr)9627dd7cddfSDavid du Colombier mach64xxdrawinit(VGAscr *scr)
9637dd7cddfSDavid du Colombier {
9647dd7cddfSDavid du Colombier if(scr->io > 0x2FF){
9657dd7cddfSDavid du Colombier initengine(scr);
9667dd7cddfSDavid du Colombier scr->fill = mach64hwfill;
9677dd7cddfSDavid du Colombier scr->scroll = mach64hwscroll;
9687dd7cddfSDavid du Colombier }
9697dd7cddfSDavid du Colombier /* scr->blank = mach64blank; */
970223a736eSDavid du Colombier switch(scr->id){
971223a736eSDavid du Colombier default:
972223a736eSDavid du Colombier break;
973223a736eSDavid du Colombier case ('L'<<8)|'B': /* 4C42: Rage 3D LTPro */
974223a736eSDavid du Colombier case ('L'<<8)|'I': /* 4C49: Rage 3D LTPro */
975223a736eSDavid du Colombier case ('L'<<8)|'M': /* 4C4D: Rage Mobility */
976223a736eSDavid du Colombier case ('L'<<8)|'P': /* 4C50: Rage 3D LTPro */
9777dd7cddfSDavid du Colombier scr->blank = mach64lcdblank;
9789a747e4fSDavid du Colombier hwblank = 1;
979223a736eSDavid du Colombier break;
980223a736eSDavid du Colombier }
9817dd7cddfSDavid du Colombier }
9827dd7cddfSDavid du Colombier
9839a747e4fSDavid du Colombier static void
ovl_configure(VGAscr * scr,Chan * c,char ** field)9849a747e4fSDavid du Colombier ovl_configure(VGAscr *scr, Chan *c, char **field)
9859a747e4fSDavid du Colombier {
9869a747e4fSDavid du Colombier int w, h;
9879a747e4fSDavid du Colombier char *format;
9889a747e4fSDavid du Colombier
9899a747e4fSDavid du Colombier w = (int)strtol(field[1], nil, 0);
9909a747e4fSDavid du Colombier h = (int)strtol(field[2], nil, 0);
9919a747e4fSDavid du Colombier format = field[3];
9929a747e4fSDavid du Colombier
9939a747e4fSDavid du Colombier if (c != ovl_chan)
9949a747e4fSDavid du Colombier error(Einuse);
9959a747e4fSDavid du Colombier if (strcmp(format, "YUYV"))
9969a747e4fSDavid du Colombier error(Eunsupportedformat);
9979a747e4fSDavid du Colombier
9989a747e4fSDavid du Colombier ovl_width = w;
9999a747e4fSDavid du Colombier ovl_height = h;
10009a747e4fSDavid du Colombier ovl_fib = w * h * sizeof(ushort);
10019a747e4fSDavid du Colombier
10029a747e4fSDavid du Colombier waitforidle(scr);
10039a747e4fSDavid du Colombier scr->mmio[mmoffset[BusCntl]] |= 0x08000000; /* Enable regblock 1 */
10049a747e4fSDavid du Colombier scr->mmio[mmoffset[OverlayScaleCntl]] =
10059a747e4fSDavid du Colombier SCALE_ZERO_EXTEND|SCALE_RED_TEMP_6500K|
10069a747e4fSDavid du Colombier SCALE_HORZ_BLEND|SCALE_VERT_BLEND;
10079a747e4fSDavid du Colombier scr->mmio[mmoffset[!mach64revb? Buf0Pitch: ScalerBuf0Pitch]] = w;
10089a747e4fSDavid du Colombier scr->mmio[mmoffset[CaptureConfig]] =
10099a747e4fSDavid du Colombier SCALER_FRAME_READ_MODE_FULL|
10109a747e4fSDavid du Colombier SCALER_BUF_MODE_SINGLE|
10119a747e4fSDavid du Colombier SCALER_BUF_NEXT_0;
10129a747e4fSDavid du Colombier scr->mmio[mmoffset[OverlayKeyCntl]] = !mach64revb?
10139a747e4fSDavid du Colombier OVERLAY_MIX_ALWAYS_V|(OVERLAY_EXCLUSIVE_NORMAL << 28):
10149a747e4fSDavid du Colombier 0x011;
10159a747e4fSDavid du Colombier
10169a747e4fSDavid du Colombier if (mach64type->m64_pro) {
10179a747e4fSDavid du Colombier waitforfifo(scr, 6);
10189a747e4fSDavid du Colombier
10199a747e4fSDavid du Colombier /* set the scaler co-efficient registers */
10209a747e4fSDavid du Colombier scr->mmio[mmoffset[ScalerColourCntl]] =
10219a747e4fSDavid du Colombier (0x00) | (0x10 << 8) | (0x10 << 16);
10229a747e4fSDavid du Colombier scr->mmio[mmoffset[ScalerHCoef0]] =
10239a747e4fSDavid du Colombier (0x00) | (0x20 << 8);
10249a747e4fSDavid du Colombier scr->mmio[mmoffset[ScalerHCoef1]] =
10259a747e4fSDavid du Colombier (0x0D) | (0x20 << 8) | (0x06 << 16) | (0x0D << 24);
10269a747e4fSDavid du Colombier scr->mmio[mmoffset[ScalerHCoef2]] =
10279a747e4fSDavid du Colombier (0x0D) | (0x1C << 8) | (0x0A << 16) | (0x0D << 24);
10289a747e4fSDavid du Colombier scr->mmio[mmoffset[ScalerHCoef3]] =
10299a747e4fSDavid du Colombier (0x0C) | (0x1A << 8) | (0x0E << 16) | (0x0C << 24);
10309a747e4fSDavid du Colombier scr->mmio[mmoffset[ScalerHCoef4]] =
10319a747e4fSDavid du Colombier (0x0C) | (0x14 << 8) | (0x14 << 16) | (0x0C << 24);
10329a747e4fSDavid du Colombier }
10339a747e4fSDavid du Colombier
10349a747e4fSDavid du Colombier waitforfifo(scr, 3);
10359a747e4fSDavid du Colombier scr->mmio[mmoffset[VideoFormat]] = SCALE_IN_YVYU422 |
10369a747e4fSDavid du Colombier (!mach64revb? 0xC: 0);
10379a747e4fSDavid du Colombier
10389a747e4fSDavid du Colombier if (mach64overlay == 0)
10399a747e4fSDavid du Colombier mach64overlay = scr->storage + 64 * 64 * sizeof(uchar);
10409a747e4fSDavid du Colombier scr->mmio[mmoffset[!mach64revb? Buf0Offset: ScalerBuf0Offset]] =
10419a747e4fSDavid du Colombier mach64overlay;
10429a747e4fSDavid du Colombier }
10439a747e4fSDavid du Colombier
10449a747e4fSDavid du Colombier static void
ovl_enable(VGAscr * scr,Chan * c,char ** field)10459a747e4fSDavid du Colombier ovl_enable(VGAscr *scr, Chan *c, char **field)
10469a747e4fSDavid du Colombier {
10479a747e4fSDavid du Colombier int x, y, w, h;
10489a747e4fSDavid du Colombier long h_inc, v_inc;
10499a747e4fSDavid du Colombier
10509a747e4fSDavid du Colombier x = (int)strtol(field[1], nil, 0);
10519a747e4fSDavid du Colombier y = (int)strtol(field[2], nil, 0);
10529a747e4fSDavid du Colombier w = (int)strtol(field[3], nil, 0);
10539a747e4fSDavid du Colombier h = (int)strtol(field[4], nil, 0);
10549a747e4fSDavid du Colombier
10559a747e4fSDavid du Colombier if (x < 0 || x + w > physgscreenr.max.x ||
10569a747e4fSDavid du Colombier y < 0 || y + h > physgscreenr.max.y)
10579a747e4fSDavid du Colombier error(Ebadarg);
10589a747e4fSDavid du Colombier
10599a747e4fSDavid du Colombier if (c != ovl_chan)
10609a747e4fSDavid du Colombier error(Einuse);
10619a747e4fSDavid du Colombier if (scr->mmio[mmoffset[CrtcGenCntl]] & 1) { /* double scan enable */
10629a747e4fSDavid du Colombier y *= 2;
10639a747e4fSDavid du Colombier h *= 2;
10649a747e4fSDavid du Colombier }
10659a747e4fSDavid du Colombier
10669a747e4fSDavid du Colombier waitforfifo(scr, 2);
10679a747e4fSDavid du Colombier scr->mmio[mmoffset[OverlayYX]] =
10689a747e4fSDavid du Colombier ((x & 0xFFFF) << 16) | (y & 0xFFFF);
10699a747e4fSDavid du Colombier scr->mmio[mmoffset[OverlayYXEnd]] =
10709a747e4fSDavid du Colombier (((x + w) & 0xFFFF) << 16) | ((y + h) & 0xFFFF);
10719a747e4fSDavid du Colombier
10729a747e4fSDavid du Colombier h_inc = (ovl_width << 12) / (w >> 1); /* ??? */
10739a747e4fSDavid du Colombier v_inc = (ovl_height << 12) / h;
10749a747e4fSDavid du Colombier waitforfifo(scr, 2);
10759a747e4fSDavid du Colombier scr->mmio[mmoffset[OverlayScaleInc]] =
10769a747e4fSDavid du Colombier ((h_inc & 0xFFFF) << 16) | (v_inc & 0xFFFF);
10779a747e4fSDavid du Colombier scr->mmio[mmoffset[ScalerHeightWidth]] =
10789a747e4fSDavid du Colombier ((ovl_width & 0xFFFF) << 16) | (ovl_height & 0xFFFF);
10799a747e4fSDavid du Colombier waitforidle(scr);
10809a747e4fSDavid du Colombier scr->mmio[mmoffset[OverlayScaleCntl]] |=
10819a747e4fSDavid du Colombier (SCALE_ENABLE|OVERLAY_ENABLE);
10829a747e4fSDavid du Colombier }
10839a747e4fSDavid du Colombier
10849a747e4fSDavid du Colombier static void
ovl_status(VGAscr * scr,Chan *,char ** field)10859a747e4fSDavid du Colombier ovl_status(VGAscr *scr, Chan *, char **field)
10869a747e4fSDavid du Colombier {
1087e464ed1aSDavid du Colombier pprint("%s: %s %.4uX, VT/GT %s, PRO %s, ovlclock %lud, rev B %s, refclock %ld\n",
10889a747e4fSDavid du Colombier scr->dev->name, field[0], mach64type->m64_id,
10899a747e4fSDavid du Colombier mach64type->m64_vtgt? "yes": "no",
10909a747e4fSDavid du Colombier mach64type->m64_pro? "yes": "no",
10919a747e4fSDavid du Colombier mach64type->m64_ovlclock,
10929a747e4fSDavid du Colombier mach64revb? "yes": "no",
10939a747e4fSDavid du Colombier mach64refclock);
10949a747e4fSDavid du Colombier pprint("%s: storage @%.8luX, aperture @%8.ulX, ovl buf @%.8ulX\n",
10954de34a7eSDavid du Colombier scr->dev->name, scr->storage, scr->paddr,
10969a747e4fSDavid du Colombier mach64overlay);
10979a747e4fSDavid du Colombier }
10989a747e4fSDavid du Colombier
10999a747e4fSDavid du Colombier static void
ovl_openctl(VGAscr *,Chan * c,char **)11009a747e4fSDavid du Colombier ovl_openctl(VGAscr *, Chan *c, char **)
11019a747e4fSDavid du Colombier {
11029a747e4fSDavid du Colombier if (ovl_chan)
11039a747e4fSDavid du Colombier error(Einuse);
11049a747e4fSDavid du Colombier ovl_chan = c;
11059a747e4fSDavid du Colombier }
11069a747e4fSDavid du Colombier
11079a747e4fSDavid du Colombier static void
ovl_closectl(VGAscr * scr,Chan * c,char **)11089a747e4fSDavid du Colombier ovl_closectl(VGAscr *scr, Chan *c, char **)
11099a747e4fSDavid du Colombier {
11109a747e4fSDavid du Colombier if (c != ovl_chan) return;
11119a747e4fSDavid du Colombier
11129a747e4fSDavid du Colombier waitforidle(scr);
11139a747e4fSDavid du Colombier scr->mmio[mmoffset[OverlayScaleCntl]] &=
11149a747e4fSDavid du Colombier ~(SCALE_ENABLE|OVERLAY_ENABLE);
11159a747e4fSDavid du Colombier ovl_chan = nil;
11169a747e4fSDavid du Colombier ovl_width = ovl_height = ovl_fib = 0;
11179a747e4fSDavid du Colombier }
11189a747e4fSDavid du Colombier
11199a747e4fSDavid du Colombier enum
11209a747e4fSDavid du Colombier {
11219a747e4fSDavid du Colombier CMclosectl,
11229a747e4fSDavid du Colombier CMconfigure,
11239a747e4fSDavid du Colombier CMenable,
11249a747e4fSDavid du Colombier CMopenctl,
11259a747e4fSDavid du Colombier CMstatus,
11269a747e4fSDavid du Colombier };
11279a747e4fSDavid du Colombier
11289a747e4fSDavid du Colombier static void (*ovl_cmds[])(VGAscr *, Chan *, char **) =
11299a747e4fSDavid du Colombier {
11309a747e4fSDavid du Colombier [CMclosectl] ovl_closectl,
11319a747e4fSDavid du Colombier [CMconfigure] ovl_configure,
11329a747e4fSDavid du Colombier [CMenable] ovl_enable,
11339a747e4fSDavid du Colombier [CMopenctl] ovl_openctl,
11349a747e4fSDavid du Colombier [CMstatus] ovl_status,
11359a747e4fSDavid du Colombier };
11369a747e4fSDavid du Colombier
11379a747e4fSDavid du Colombier static Cmdtab mach64xxcmd[] =
11389a747e4fSDavid du Colombier {
11399a747e4fSDavid du Colombier CMclosectl, "closectl", 1,
11409a747e4fSDavid du Colombier CMconfigure, "configure", 4,
11419a747e4fSDavid du Colombier CMenable, "enable", 5,
11429a747e4fSDavid du Colombier CMopenctl, "openctl", 1,
11439a747e4fSDavid du Colombier CMstatus, "status", 1,
11449a747e4fSDavid du Colombier };
11459a747e4fSDavid du Colombier
11469a747e4fSDavid du Colombier static void
mach64xxovlctl(VGAscr * scr,Chan * c,void * a,int n)11479a747e4fSDavid du Colombier mach64xxovlctl(VGAscr *scr, Chan *c, void *a, int n)
11489a747e4fSDavid du Colombier {
11499a747e4fSDavid du Colombier Cmdbuf *cb;
11509a747e4fSDavid du Colombier Cmdtab *ct;
11519a747e4fSDavid du Colombier
11529a747e4fSDavid du Colombier if(!mach64type->m64_vtgt)
11539a747e4fSDavid du Colombier error(Enodev);
11549a747e4fSDavid du Colombier
1155fb7f0c93SDavid du Colombier if(!scr->overlayinit){
1156fb7f0c93SDavid du Colombier scr->overlayinit = 1;
1157fb7f0c93SDavid du Colombier init_overlayclock(scr);
1158fb7f0c93SDavid du Colombier }
11599a747e4fSDavid du Colombier cb = parsecmd(a, n);
11609a747e4fSDavid du Colombier if(waserror()){
11619a747e4fSDavid du Colombier free(cb);
11629a747e4fSDavid du Colombier nexterror();
11639a747e4fSDavid du Colombier }
11649a747e4fSDavid du Colombier
11659a747e4fSDavid du Colombier ct = lookupcmd(cb, mach64xxcmd, nelem(mach64xxcmd));
11669a747e4fSDavid du Colombier
11679a747e4fSDavid du Colombier ovl_cmds[ct->index](scr, c, cb->f);
11689a747e4fSDavid du Colombier
11699a747e4fSDavid du Colombier poperror();
11709a747e4fSDavid du Colombier free(cb);
11719a747e4fSDavid du Colombier }
11729a747e4fSDavid du Colombier
11739a747e4fSDavid du Colombier static int
mach64xxovlwrite(VGAscr * scr,void * a,int len,vlong offs)11749a747e4fSDavid du Colombier mach64xxovlwrite(VGAscr *scr, void *a, int len, vlong offs)
11759a747e4fSDavid du Colombier {
11769a747e4fSDavid du Colombier uchar *src;
11779a747e4fSDavid du Colombier int _len;
11789a747e4fSDavid du Colombier
11799a747e4fSDavid du Colombier if (ovl_chan == nil) return len; /* Acts as a /dev/null */
11809a747e4fSDavid du Colombier
11819a747e4fSDavid du Colombier /* Calculate the destination address */
11829a747e4fSDavid du Colombier _len = len;
11839a747e4fSDavid du Colombier src = (uchar *)a;
11849a747e4fSDavid du Colombier while (len > 0) {
11859a747e4fSDavid du Colombier ulong _offs;
11869a747e4fSDavid du Colombier int nb;
11879a747e4fSDavid du Colombier
11889a747e4fSDavid du Colombier _offs = (ulong)(offs % ovl_fib);
11899a747e4fSDavid du Colombier nb = (_offs + len > ovl_fib)? ovl_fib - _offs: len;
11904de34a7eSDavid du Colombier memmove((uchar *)scr->vaddr + mach64overlay + _offs,
11919a747e4fSDavid du Colombier src, nb);
11929a747e4fSDavid du Colombier offs += nb;
11939a747e4fSDavid du Colombier src += nb;
11949a747e4fSDavid du Colombier len -= nb;
11959a747e4fSDavid du Colombier }
11969a747e4fSDavid du Colombier return _len;
11979a747e4fSDavid du Colombier }
11989a747e4fSDavid du Colombier
11997dd7cddfSDavid du Colombier VGAdev vgamach64xxdev = {
12007dd7cddfSDavid du Colombier "mach64xx",
12017dd7cddfSDavid du Colombier
12027dd7cddfSDavid du Colombier mach64xxenable, /* enable */
12037dd7cddfSDavid du Colombier 0, /* disable */
12047dd7cddfSDavid du Colombier 0, /* page */
12057dd7cddfSDavid du Colombier mach64xxlinear, /* linear */
12067dd7cddfSDavid du Colombier mach64xxdrawinit, /* drawinit */
12079a747e4fSDavid du Colombier 0,
12089a747e4fSDavid du Colombier mach64xxovlctl, /* overlay control */
12099a747e4fSDavid du Colombier mach64xxovlwrite, /* write the overlay */
12107dd7cddfSDavid du Colombier };
12117dd7cddfSDavid du Colombier
12127dd7cddfSDavid du Colombier VGAcur vgamach64xxcur = {
12137dd7cddfSDavid du Colombier "mach64xxhwgc",
12147dd7cddfSDavid du Colombier
12157dd7cddfSDavid du Colombier mach64xxcurenable, /* enable */
12167dd7cddfSDavid du Colombier mach64xxcurdisable, /* disable */
12177dd7cddfSDavid du Colombier mach64xxcurload, /* load */
12187dd7cddfSDavid du Colombier mach64xxcurmove, /* move */
12197dd7cddfSDavid du Colombier
12207dd7cddfSDavid du Colombier 1 /* doespanning */
12217dd7cddfSDavid du Colombier };
122259cc4ca5SDavid du Colombier
1223