17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier
57dd7cddfSDavid du Colombier #include "pci.h"
69a747e4fSDavid du Colombier #include "vga.h"
77dd7cddfSDavid du Colombier
87dd7cddfSDavid du Colombier /*
97dd7cddfSDavid du Colombier * ATI Mach64 family.
107dd7cddfSDavid du Colombier */
117dd7cddfSDavid du Colombier enum {
127dd7cddfSDavid du Colombier HTotalDisp,
137dd7cddfSDavid du Colombier HSyncStrtWid,
147dd7cddfSDavid du Colombier VTotalDisp,
157dd7cddfSDavid du Colombier VSyncStrtWid,
167dd7cddfSDavid du Colombier VlineCrntVline,
177dd7cddfSDavid du Colombier OffPitch,
187dd7cddfSDavid du Colombier IntCntl,
197dd7cddfSDavid du Colombier CrtcGenCntl,
207dd7cddfSDavid du Colombier
217dd7cddfSDavid du Colombier OvrClr,
227dd7cddfSDavid du Colombier OvrWidLR,
237dd7cddfSDavid du Colombier OvrWidTB,
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier CurClr0,
267dd7cddfSDavid du Colombier CurClr1,
277dd7cddfSDavid du Colombier CurOffset,
287dd7cddfSDavid du Colombier CurHVposn,
297dd7cddfSDavid du Colombier CurHVoff,
307dd7cddfSDavid du Colombier
317dd7cddfSDavid du Colombier ScratchReg0,
327dd7cddfSDavid du Colombier ScratchReg1, /* Scratch Register (BIOS info) */
337dd7cddfSDavid du Colombier ClockCntl,
347dd7cddfSDavid du Colombier BusCntl,
357dd7cddfSDavid du Colombier MemCntl,
367dd7cddfSDavid du Colombier ExtMemCntl,
377dd7cddfSDavid du Colombier MemVgaWpSel,
387dd7cddfSDavid du Colombier MemVgaRpSel,
397dd7cddfSDavid du Colombier DacRegs,
407dd7cddfSDavid du Colombier DacCntl,
417dd7cddfSDavid du Colombier GenTestCntl,
427dd7cddfSDavid du Colombier ConfigCntl, /* Configuration control */
437dd7cddfSDavid du Colombier ConfigChipId,
447dd7cddfSDavid du Colombier ConfigStat0, /* Configuration status 0 */
457dd7cddfSDavid du Colombier ConfigStat1, /* Configuration status 1 */
4659cc4ca5SDavid du Colombier ConfigStat2,
477dd7cddfSDavid du Colombier DspConfig, /* Rage */
487dd7cddfSDavid du Colombier DspOnOff, /* Rage */
497dd7cddfSDavid du Colombier
507dd7cddfSDavid du Colombier DpBkgdClr,
517dd7cddfSDavid du Colombier DpChainMsk,
527dd7cddfSDavid du Colombier DpFrgdClr,
537dd7cddfSDavid du Colombier DpMix,
547dd7cddfSDavid du Colombier DpPixWidth,
557dd7cddfSDavid du Colombier DpSrc,
567dd7cddfSDavid du Colombier DpWriteMsk,
577dd7cddfSDavid du Colombier
587dd7cddfSDavid du Colombier LcdIndex,
597dd7cddfSDavid du Colombier LcdData,
607dd7cddfSDavid du Colombier
617dd7cddfSDavid du Colombier Nreg,
627dd7cddfSDavid du Colombier
637dd7cddfSDavid du Colombier TvIndex = 0x1D,
647dd7cddfSDavid du Colombier TvData = 0x27,
657dd7cddfSDavid du Colombier
667dd7cddfSDavid du Colombier LCD_ConfigPanel = 0,
677dd7cddfSDavid du Colombier LCD_GenCtrl,
687dd7cddfSDavid du Colombier LCD_DstnCntl,
697dd7cddfSDavid du Colombier LCD_HfbPitchAddr,
707dd7cddfSDavid du Colombier LCD_HorzStretch,
717dd7cddfSDavid du Colombier LCD_VertStretch,
727dd7cddfSDavid du Colombier LCD_ExtVertStretch,
737dd7cddfSDavid du Colombier LCD_LtGio,
747dd7cddfSDavid du Colombier LCD_PowerMngmnt,
757dd7cddfSDavid du Colombier LCD_ZvgPio,
767dd7cddfSDavid du Colombier Nlcd,
777dd7cddfSDavid du Colombier };
787dd7cddfSDavid du Colombier
7959cc4ca5SDavid du Colombier static char* iorname[Nreg] = {
8059cc4ca5SDavid du Colombier "HTotalDisp",
8159cc4ca5SDavid du Colombier "HSyncStrtWid",
8259cc4ca5SDavid du Colombier "VTotalDisp",
8359cc4ca5SDavid du Colombier "VSyncStrtWid",
8459cc4ca5SDavid du Colombier "VlineCrntVline",
8559cc4ca5SDavid du Colombier "OffPitch",
8659cc4ca5SDavid du Colombier "IntCntl",
8759cc4ca5SDavid du Colombier "CrtcGenCntl",
887dd7cddfSDavid du Colombier
8959cc4ca5SDavid du Colombier "OvrClr",
9059cc4ca5SDavid du Colombier "OvrWidLR",
9159cc4ca5SDavid du Colombier "OvrWidTB",
9259cc4ca5SDavid du Colombier
9359cc4ca5SDavid du Colombier "CurClr0",
9459cc4ca5SDavid du Colombier "CurClr1",
9559cc4ca5SDavid du Colombier "CurOffset",
9659cc4ca5SDavid du Colombier "CurHVposn",
9759cc4ca5SDavid du Colombier "CurHVoff",
9859cc4ca5SDavid du Colombier
9959cc4ca5SDavid du Colombier "ScratchReg0",
10059cc4ca5SDavid du Colombier "ScratchReg1",
10159cc4ca5SDavid du Colombier "ClockCntl",
10259cc4ca5SDavid du Colombier "BusCntl",
10359cc4ca5SDavid du Colombier "MemCntl",
10459cc4ca5SDavid du Colombier "ExtMemCntl",
10559cc4ca5SDavid du Colombier "MemVgaWpSel",
10659cc4ca5SDavid du Colombier "MemVgaRpSel",
10759cc4ca5SDavid du Colombier "DacRegs",
10859cc4ca5SDavid du Colombier "DacCntl",
10959cc4ca5SDavid du Colombier "GenTestCntl",
11059cc4ca5SDavid du Colombier "ConfigCntl",
11159cc4ca5SDavid du Colombier "ConfigChipId",
11259cc4ca5SDavid du Colombier "ConfigStat0",
11359cc4ca5SDavid du Colombier "ConfigStat1",
11459cc4ca5SDavid du Colombier "ConfigStat2",
11559cc4ca5SDavid du Colombier "DspConfig",
11659cc4ca5SDavid du Colombier "DspOnOff",
11759cc4ca5SDavid du Colombier
11859cc4ca5SDavid du Colombier "DpBkgdClr",
11959cc4ca5SDavid du Colombier "DpChainMsk",
12059cc4ca5SDavid du Colombier "DpFrgdClr",
12159cc4ca5SDavid du Colombier "DpMix",
12259cc4ca5SDavid du Colombier "DpPixWidth",
12359cc4ca5SDavid du Colombier "DpSrc",
12459cc4ca5SDavid du Colombier "DpWriteMsk",
12559cc4ca5SDavid du Colombier
12659cc4ca5SDavid du Colombier "LcdIndex",
12759cc4ca5SDavid du Colombier "LcdData",
12859cc4ca5SDavid du Colombier };
12959cc4ca5SDavid du Colombier
13059cc4ca5SDavid du Colombier static char* lcdname[Nlcd] = {
13159cc4ca5SDavid du Colombier "LCD ConfigPanel",
13259cc4ca5SDavid du Colombier "LCD GenCntl",
13359cc4ca5SDavid du Colombier "LCD DstnCntl",
13459cc4ca5SDavid du Colombier "LCD HfbPitchAddr",
13559cc4ca5SDavid du Colombier "LCD HorzStretch",
13659cc4ca5SDavid du Colombier "LCD VertStretch",
13759cc4ca5SDavid du Colombier "LCD ExtVertStretch",
13859cc4ca5SDavid du Colombier "LCD LtGio",
13959cc4ca5SDavid du Colombier "LCD PowerMngmnt",
14059cc4ca5SDavid du Colombier "LCD ZvgPio"
14159cc4ca5SDavid du Colombier };
14259cc4ca5SDavid du Colombier
14359cc4ca5SDavid du Colombier /*
14459cc4ca5SDavid du Colombier * Crummy hack: all io register offsets
14559cc4ca5SDavid du Colombier * here get IOREG or'ed in, so that we can
14659cc4ca5SDavid du Colombier * tell the difference between an uninitialized
14759cc4ca5SDavid du Colombier * array entry and HTotalDisp.
14859cc4ca5SDavid du Colombier */
14959cc4ca5SDavid du Colombier enum {
15059cc4ca5SDavid du Colombier IOREG = 0x10000,
15159cc4ca5SDavid du Colombier };
1527dd7cddfSDavid du Colombier static ushort ioregs[Nreg] = {
15359cc4ca5SDavid du Colombier [HTotalDisp] IOREG|0x0000,
15459cc4ca5SDavid du Colombier [HSyncStrtWid] IOREG|0x0100,
15559cc4ca5SDavid du Colombier [VTotalDisp] IOREG|0x0200,
15659cc4ca5SDavid du Colombier [VSyncStrtWid] IOREG|0x0300,
15759cc4ca5SDavid du Colombier [VlineCrntVline] IOREG|0x0400,
15859cc4ca5SDavid du Colombier [OffPitch] IOREG|0x0500,
15959cc4ca5SDavid du Colombier [IntCntl] IOREG|0x0600,
16059cc4ca5SDavid du Colombier [CrtcGenCntl] IOREG|0x0700,
16159cc4ca5SDavid du Colombier [OvrClr] IOREG|0x0800,
16259cc4ca5SDavid du Colombier [OvrWidLR] IOREG|0x0900,
16359cc4ca5SDavid du Colombier [OvrWidTB] IOREG|0x0A00,
16459cc4ca5SDavid du Colombier [CurClr0] IOREG|0x0B00,
16559cc4ca5SDavid du Colombier [CurClr1] IOREG|0x0C00,
16659cc4ca5SDavid du Colombier [CurOffset] IOREG|0x0D00,
16759cc4ca5SDavid du Colombier [CurHVposn] IOREG|0x0E00,
16859cc4ca5SDavid du Colombier [CurHVoff] IOREG|0x0F00,
16959cc4ca5SDavid du Colombier [ScratchReg0] IOREG|0x1000,
17059cc4ca5SDavid du Colombier [ScratchReg1] IOREG|0x1100,
17159cc4ca5SDavid du Colombier [ClockCntl] IOREG|0x1200,
17259cc4ca5SDavid du Colombier [BusCntl] IOREG|0x1300,
17359cc4ca5SDavid du Colombier [MemCntl] IOREG|0x1400,
17459cc4ca5SDavid du Colombier [MemVgaWpSel] IOREG|0x1500,
17559cc4ca5SDavid du Colombier [MemVgaRpSel] IOREG|0x1600,
17659cc4ca5SDavid du Colombier [DacRegs] IOREG|0x1700,
17759cc4ca5SDavid du Colombier [DacCntl] IOREG|0x1800,
17859cc4ca5SDavid du Colombier [GenTestCntl] IOREG|0x1900,
17959cc4ca5SDavid du Colombier [ConfigCntl] IOREG|0x1A00,
18059cc4ca5SDavid du Colombier [ConfigChipId] IOREG|0x1B00,
18159cc4ca5SDavid du Colombier [ConfigStat0] IOREG|0x1C00,
18259cc4ca5SDavid du Colombier [ConfigStat1] IOREG|0x1D00,
18359cc4ca5SDavid du Colombier /* [GpIo] IOREG|0x1E00, */
18459cc4ca5SDavid du Colombier /* [HTotalDisp] IOREG|0x1F00, duplicate, says XFree86 */
1857dd7cddfSDavid du Colombier };
1867dd7cddfSDavid du Colombier
1877dd7cddfSDavid du Colombier static ushort pciregs[Nreg] = {
1887dd7cddfSDavid du Colombier [HTotalDisp] 0x00,
1897dd7cddfSDavid du Colombier [HSyncStrtWid] 0x01,
1907dd7cddfSDavid du Colombier [VTotalDisp] 0x02,
1917dd7cddfSDavid du Colombier [VSyncStrtWid] 0x03,
1927dd7cddfSDavid du Colombier [VlineCrntVline] 0x04,
1937dd7cddfSDavid du Colombier [OffPitch] 0x05,
1947dd7cddfSDavid du Colombier [IntCntl] 0x06,
1957dd7cddfSDavid du Colombier [CrtcGenCntl] 0x07,
1967dd7cddfSDavid du Colombier [DspConfig] 0x08,
1977dd7cddfSDavid du Colombier [DspOnOff] 0x09,
1987dd7cddfSDavid du Colombier [OvrClr] 0x10,
1997dd7cddfSDavid du Colombier [OvrWidLR] 0x11,
2007dd7cddfSDavid du Colombier [OvrWidTB] 0x12,
2017dd7cddfSDavid du Colombier [CurClr0] 0x18,
2027dd7cddfSDavid du Colombier [CurClr1] 0x19,
2037dd7cddfSDavid du Colombier [CurOffset] 0x1A,
2047dd7cddfSDavid du Colombier [CurHVposn] 0x1B,
2057dd7cddfSDavid du Colombier [CurHVoff] 0x1C,
2067dd7cddfSDavid du Colombier [ScratchReg0] 0x20,
2077dd7cddfSDavid du Colombier [ScratchReg1] 0x21,
2087dd7cddfSDavid du Colombier [ClockCntl] 0x24,
2097dd7cddfSDavid du Colombier [BusCntl] 0x28,
2107dd7cddfSDavid du Colombier [LcdIndex] 0x29,
2117dd7cddfSDavid du Colombier [LcdData] 0x2A,
2127dd7cddfSDavid du Colombier [ExtMemCntl] 0x2B,
2137dd7cddfSDavid du Colombier [MemCntl] 0x2C,
2147dd7cddfSDavid du Colombier [MemVgaWpSel] 0x2D,
2157dd7cddfSDavid du Colombier [MemVgaRpSel] 0x2E,
2167dd7cddfSDavid du Colombier [DacRegs] 0x30,
2177dd7cddfSDavid du Colombier [DacCntl] 0x31,
2187dd7cddfSDavid du Colombier [GenTestCntl] 0x34,
2197dd7cddfSDavid du Colombier [ConfigCntl] 0x37,
2207dd7cddfSDavid du Colombier [ConfigChipId] 0x38,
2217dd7cddfSDavid du Colombier [ConfigStat0] 0x39,
22259cc4ca5SDavid du Colombier [ConfigStat1] 0x25, /* rsc: was 0x3A, but that's not what the LT manual says */
22359cc4ca5SDavid du Colombier [ConfigStat2] 0x26,
2247dd7cddfSDavid du Colombier [DpBkgdClr] 0xB0,
2257dd7cddfSDavid du Colombier [DpChainMsk] 0xB3,
2267dd7cddfSDavid du Colombier [DpFrgdClr] 0xB1,
2277dd7cddfSDavid du Colombier [DpMix] 0xB5,
2287dd7cddfSDavid du Colombier [DpPixWidth] 0xB4,
2297dd7cddfSDavid du Colombier [DpSrc] 0xB6,
2307dd7cddfSDavid du Colombier [DpWriteMsk] 0xB2,
2317dd7cddfSDavid du Colombier };
2327dd7cddfSDavid du Colombier
2337dd7cddfSDavid du Colombier enum {
2347dd7cddfSDavid du Colombier PLLm = 0x02,
2357dd7cddfSDavid du Colombier PLLp = 0x06,
2367dd7cddfSDavid du Colombier PLLn0 = 0x07,
2377dd7cddfSDavid du Colombier PLLn1 = 0x08,
2387dd7cddfSDavid du Colombier PLLn2 = 0x09,
2397dd7cddfSDavid du Colombier PLLn3 = 0x0A,
2407dd7cddfSDavid du Colombier PLLx = 0x0B, /* external divisor (Rage) */
2417dd7cddfSDavid du Colombier
2427dd7cddfSDavid du Colombier Npll = 32,
2437dd7cddfSDavid du Colombier Ntv = 1, /* actually 256, but not used */
2447dd7cddfSDavid du Colombier };
2457dd7cddfSDavid du Colombier
2467dd7cddfSDavid du Colombier typedef struct Mach64xx Mach64xx;
2477dd7cddfSDavid du Colombier struct Mach64xx {
2487dd7cddfSDavid du Colombier ulong io;
2497dd7cddfSDavid du Colombier Pcidev* pci;
2507dd7cddfSDavid du Colombier int bigmem;
2517dd7cddfSDavid du Colombier int lcdon;
25259cc4ca5SDavid du Colombier int lcdpanelid;
2537dd7cddfSDavid du Colombier
2547dd7cddfSDavid du Colombier ulong reg[Nreg];
2557dd7cddfSDavid du Colombier ulong lcd[Nlcd];
2567dd7cddfSDavid du Colombier ulong tv[Ntv];
2577dd7cddfSDavid du Colombier uchar pll[Npll];
2587dd7cddfSDavid du Colombier
2597dd7cddfSDavid du Colombier ulong (*ior32)(Mach64xx*, int);
2607dd7cddfSDavid du Colombier void (*iow32)(Mach64xx*, int, ulong);
2617dd7cddfSDavid du Colombier };
2627dd7cddfSDavid du Colombier
26359cc4ca5SDavid du Colombier static ulong
portior32(Mach64xx * mp,int r)26459cc4ca5SDavid du Colombier portior32(Mach64xx* mp, int r)
26559cc4ca5SDavid du Colombier {
26659cc4ca5SDavid du Colombier if((ioregs[r] & IOREG) == 0)
26759cc4ca5SDavid du Colombier return ~0;
26859cc4ca5SDavid du Colombier
26959cc4ca5SDavid du Colombier return inportl(((ioregs[r] & ~IOREG)<<2)+mp->io);
27059cc4ca5SDavid du Colombier }
27159cc4ca5SDavid du Colombier
27259cc4ca5SDavid du Colombier static void
portiow32(Mach64xx * mp,int r,ulong l)27359cc4ca5SDavid du Colombier portiow32(Mach64xx* mp, int r, ulong l)
27459cc4ca5SDavid du Colombier {
27559cc4ca5SDavid du Colombier if((ioregs[r] & IOREG) == 0)
27659cc4ca5SDavid du Colombier return;
27759cc4ca5SDavid du Colombier
27859cc4ca5SDavid du Colombier outportl(((ioregs[r] & ~IOREG)<<2)+mp->io, l);
27959cc4ca5SDavid du Colombier }
28059cc4ca5SDavid du Colombier
28159cc4ca5SDavid du Colombier static ulong
pciior32(Mach64xx * mp,int r)28259cc4ca5SDavid du Colombier pciior32(Mach64xx* mp, int r)
28359cc4ca5SDavid du Colombier {
28459cc4ca5SDavid du Colombier return inportl((pciregs[r]<<2)+mp->io);
28559cc4ca5SDavid du Colombier }
28659cc4ca5SDavid du Colombier
28759cc4ca5SDavid du Colombier static void
pciiow32(Mach64xx * mp,int r,ulong l)28859cc4ca5SDavid du Colombier pciiow32(Mach64xx* mp, int r, ulong l)
28959cc4ca5SDavid du Colombier {
29059cc4ca5SDavid du Colombier outportl((pciregs[r]<<2)+mp->io, l);
29159cc4ca5SDavid du Colombier }
29259cc4ca5SDavid du Colombier
2937dd7cddfSDavid du Colombier static uchar
pllr(Mach64xx * mp,int r)2947dd7cddfSDavid du Colombier pllr(Mach64xx* mp, int r)
2957dd7cddfSDavid du Colombier {
2967dd7cddfSDavid du Colombier int io;
2977dd7cddfSDavid du Colombier
29859cc4ca5SDavid du Colombier if(mp->ior32 == portior32)
29959cc4ca5SDavid du Colombier io = ((ioregs[ClockCntl]&~IOREG)<<2)+mp->io;
30059cc4ca5SDavid du Colombier else
30159cc4ca5SDavid du Colombier io = (pciregs[ClockCntl]<<2)+mp->io;
30259cc4ca5SDavid du Colombier
3037dd7cddfSDavid du Colombier outportb(io+1, r<<2);
3047dd7cddfSDavid du Colombier return inportb(io+2);
3057dd7cddfSDavid du Colombier }
3067dd7cddfSDavid du Colombier
3077dd7cddfSDavid du Colombier static void
pllw(Mach64xx * mp,int r,uchar b)3087dd7cddfSDavid du Colombier pllw(Mach64xx* mp, int r, uchar b)
3097dd7cddfSDavid du Colombier {
3107dd7cddfSDavid du Colombier int io;
3117dd7cddfSDavid du Colombier
31259cc4ca5SDavid du Colombier if(mp->ior32 == portior32)
31359cc4ca5SDavid du Colombier io = ((ioregs[ClockCntl]&~IOREG)<<2)+mp->io;
31459cc4ca5SDavid du Colombier else
31559cc4ca5SDavid du Colombier io = (pciregs[ClockCntl]<<2)+mp->io;
31659cc4ca5SDavid du Colombier
3177dd7cddfSDavid du Colombier outportb(io+1, (r<<2)|0x02);
3187dd7cddfSDavid du Colombier outportb(io+2, b);
3197dd7cddfSDavid du Colombier }
3207dd7cddfSDavid du Colombier
3217dd7cddfSDavid du Colombier static ulong
lcdr32(Mach64xx * mp,ulong r)3227dd7cddfSDavid du Colombier lcdr32(Mach64xx *mp, ulong r)
3237dd7cddfSDavid du Colombier {
3247dd7cddfSDavid du Colombier ulong or;
3257dd7cddfSDavid du Colombier
3267dd7cddfSDavid du Colombier or = mp->ior32(mp, LcdIndex);
3277dd7cddfSDavid du Colombier mp->iow32(mp, LcdIndex, (or&~0x0F) | (r&0x0F));
3287dd7cddfSDavid du Colombier return mp->ior32(mp, LcdData);
3297dd7cddfSDavid du Colombier }
3307dd7cddfSDavid du Colombier
3317dd7cddfSDavid du Colombier static void
lcdw32(Mach64xx * mp,ulong r,ulong v)3327dd7cddfSDavid du Colombier lcdw32(Mach64xx *mp, ulong r, ulong v)
3337dd7cddfSDavid du Colombier {
3347dd7cddfSDavid du Colombier ulong or;
3357dd7cddfSDavid du Colombier
3367dd7cddfSDavid du Colombier or = mp->ior32(mp, LcdIndex);
3377dd7cddfSDavid du Colombier mp->iow32(mp, LcdIndex, (or&~0x0F) | (r&0x0F));
3387dd7cddfSDavid du Colombier mp->iow32(mp, LcdData, v);
3397dd7cddfSDavid du Colombier }
3407dd7cddfSDavid du Colombier
3417dd7cddfSDavid du Colombier static ulong
tvr32(Mach64xx * mp,ulong r)3427dd7cddfSDavid du Colombier tvr32(Mach64xx *mp, ulong r)
3437dd7cddfSDavid du Colombier {
3447dd7cddfSDavid du Colombier outportb(mp->io+(TvIndex<<2), r&0x0F);
3457dd7cddfSDavid du Colombier return inportl(mp->io+(TvData<<2));
3467dd7cddfSDavid du Colombier }
3477dd7cddfSDavid du Colombier
3487dd7cddfSDavid du Colombier static void
tvw32(Mach64xx * mp,ulong r,ulong v)3497dd7cddfSDavid du Colombier tvw32(Mach64xx *mp, ulong r, ulong v)
3507dd7cddfSDavid du Colombier {
3517dd7cddfSDavid du Colombier outportb(mp->io+(TvIndex<<2), r&0x0F);
3527dd7cddfSDavid du Colombier outportl(mp->io+(TvData<<2), v);
3537dd7cddfSDavid du Colombier }
3547dd7cddfSDavid du Colombier
3557dd7cddfSDavid du Colombier static int smallmem[] = {
3567dd7cddfSDavid du Colombier 512*1024, 1024*1024, 2*1024*1024, 4*1024*1024,
3577dd7cddfSDavid du Colombier 6*1024*1024, 8*1024*1024, 12*1024*1024, 16*1024*1024,
3587dd7cddfSDavid du Colombier };
3597dd7cddfSDavid du Colombier
3607dd7cddfSDavid du Colombier static int bigmem[] = {
3617dd7cddfSDavid du Colombier 512*1024, 2*512*1024, 3*512*1024, 4*512*1024,
3627dd7cddfSDavid du Colombier 5*512*1024, 6*512*1024, 7*512*1024, 8*512*1024,
3637dd7cddfSDavid du Colombier 5*1024*1024, 6*1024*1024, 7*1024*1024, 8*1024*1024,
3647dd7cddfSDavid du Colombier 10*1024*1024, 12*1024*1024, 14*1024*1024, 16*1024*1024,
3657dd7cddfSDavid du Colombier };
3667dd7cddfSDavid du Colombier
3677dd7cddfSDavid du Colombier static void
snarf(Vga * vga,Ctlr * ctlr)3687dd7cddfSDavid du Colombier snarf(Vga* vga, Ctlr* ctlr)
3697dd7cddfSDavid du Colombier {
3707dd7cddfSDavid du Colombier Mach64xx *mp;
3717dd7cddfSDavid du Colombier int i;
3727dd7cddfSDavid du Colombier ulong v;
3737dd7cddfSDavid du Colombier
3747dd7cddfSDavid du Colombier if(vga->private == nil){
3757dd7cddfSDavid du Colombier vga->private = alloc(sizeof(Mach64xx));
3767dd7cddfSDavid du Colombier mp = vga->private;
3777dd7cddfSDavid du Colombier mp->io = 0x2EC;
3787dd7cddfSDavid du Colombier mp->ior32 = portior32;
3797dd7cddfSDavid du Colombier mp->iow32 = portiow32;
3807dd7cddfSDavid du Colombier mp->pci = pcimatch(0, 0x1002, 0);
3817dd7cddfSDavid du Colombier if (mp->pci) {
3827dd7cddfSDavid du Colombier if(v = mp->pci->mem[1].bar & ~0x3) {
3837dd7cddfSDavid du Colombier mp->io = v;
38459cc4ca5SDavid du Colombier mp->ior32 = pciior32;
38559cc4ca5SDavid du Colombier mp->iow32 = pciiow32;
3867dd7cddfSDavid du Colombier }
3877dd7cddfSDavid du Colombier }
3887dd7cddfSDavid du Colombier }
3897dd7cddfSDavid du Colombier
3907dd7cddfSDavid du Colombier mp = vga->private;
3917dd7cddfSDavid du Colombier for(i = 0; i < Nreg; i++)
3927dd7cddfSDavid du Colombier mp->reg[i] = mp->ior32(mp, i);
3937dd7cddfSDavid du Colombier
3947dd7cddfSDavid du Colombier for(i = 0; i < Npll; i++)
3957dd7cddfSDavid du Colombier mp->pll[i] = pllr(mp, i);
3967dd7cddfSDavid du Colombier
3977dd7cddfSDavid du Colombier switch(mp->reg[ConfigChipId] & 0xFFFF){
3987dd7cddfSDavid du Colombier default:
39959cc4ca5SDavid du Colombier mp->lcdpanelid = 0;
4007dd7cddfSDavid du Colombier break;
401223a736eSDavid du Colombier case ('L'<<8)|'B': /* 4C42: Rage LTPro AGP */
4027dd7cddfSDavid du Colombier case ('L'<<8)|'I': /* 4C49: Rage 3D LTPro */
4037dd7cddfSDavid du Colombier case ('L'<<8)|'M': /* 4C4D: Rage Mobility */
4047dd7cddfSDavid du Colombier case ('L'<<8)|'P': /* 4C50: Rage 3D LTPro */
4057dd7cddfSDavid du Colombier for(i = 0; i < Nlcd; i++)
4067dd7cddfSDavid du Colombier mp->lcd[i] = lcdr32(mp, i);
4077dd7cddfSDavid du Colombier if(mp->lcd[LCD_GenCtrl] & 0x02)
4087dd7cddfSDavid du Colombier mp->lcdon = 1;
40959cc4ca5SDavid du Colombier mp->lcdpanelid = ((mp->reg[ConfigStat2]>>14) & 0x1F);
4107dd7cddfSDavid du Colombier break;
4117dd7cddfSDavid du Colombier }
4127dd7cddfSDavid du Colombier
4137dd7cddfSDavid du Colombier /*
4147dd7cddfSDavid du Colombier * Check which memory size map we are using.
4157dd7cddfSDavid du Colombier */
4167dd7cddfSDavid du Colombier mp->bigmem = 0;
4177dd7cddfSDavid du Colombier switch(mp->reg[ConfigChipId] & 0xFFFF){
4187dd7cddfSDavid du Colombier case ('G'<<8)|'B': /* 4742: 264GT PRO */
4197dd7cddfSDavid du Colombier case ('G'<<8)|'D': /* 4744: 264GT PRO */
4207dd7cddfSDavid du Colombier case ('G'<<8)|'I': /* 4749: 264GT PRO */
42159cc4ca5SDavid du Colombier case ('G'<<8)|'M': /* 474D: Rage XL */
4227dd7cddfSDavid du Colombier case ('G'<<8)|'P': /* 4750: 264GT PRO */
4237dd7cddfSDavid du Colombier case ('G'<<8)|'Q': /* 4751: 264GT PRO */
4249a747e4fSDavid du Colombier case ('G'<<8)|'R': /* 4752: */
4257dd7cddfSDavid du Colombier case ('G'<<8)|'U': /* 4755: 264GT DVD */
4267dd7cddfSDavid du Colombier case ('G'<<8)|'V': /* 4756: Rage2C */
4277dd7cddfSDavid du Colombier case ('G'<<8)|'Z': /* 475A: Rage2C */
4287dd7cddfSDavid du Colombier case ('V'<<8)|'U': /* 5655: 264VT3 */
42959cc4ca5SDavid du Colombier case ('V'<<8)|'V': /* 5656: 264VT4 */
430223a736eSDavid du Colombier case ('L'<<8)|'B': /* 4C42: Rage LTPro AGP */
4317dd7cddfSDavid du Colombier case ('L'<<8)|'I': /* 4C49: Rage 3D LTPro */
4327dd7cddfSDavid du Colombier case ('L'<<8)|'M': /* 4C4D: Rage Mobility */
4337dd7cddfSDavid du Colombier case ('L'<<8)|'P': /* 4C50: Rage 3D LTPro */
4347dd7cddfSDavid du Colombier mp->bigmem = 1;
4357dd7cddfSDavid du Colombier break;
4367dd7cddfSDavid du Colombier case ('G'<<8)|'T': /* 4754: 264GT[B] */
4377dd7cddfSDavid du Colombier case ('V'<<8)|'T': /* 5654: 264VT/GT/VTB */
4387dd7cddfSDavid du Colombier /*
4397dd7cddfSDavid du Colombier * Only the VTB and GTB use the new memory encoding,
4407dd7cddfSDavid du Colombier * and they are identified by a nonzero ChipVersion,
4417dd7cddfSDavid du Colombier * apparently.
4427dd7cddfSDavid du Colombier */
4437dd7cddfSDavid du Colombier if((mp->reg[ConfigChipId] >> 24) & 0x7)
4447dd7cddfSDavid du Colombier mp->bigmem = 1;
4457dd7cddfSDavid du Colombier break;
4467dd7cddfSDavid du Colombier }
4477dd7cddfSDavid du Colombier
4487dd7cddfSDavid du Colombier /*
4497dd7cddfSDavid du Colombier * Memory size and aperture. It's recommended
4507dd7cddfSDavid du Colombier * to use an 8Mb aperture on a 16Mb boundary.
4517dd7cddfSDavid du Colombier */
4527dd7cddfSDavid du Colombier if(mp->bigmem)
4537dd7cddfSDavid du Colombier vga->vmz = bigmem[mp->reg[MemCntl] & 0x0F];
4547dd7cddfSDavid du Colombier else
4557dd7cddfSDavid du Colombier vga->vmz = smallmem[mp->reg[MemCntl] & 0x07];
4567dd7cddfSDavid du Colombier vga->vma = 16*1024*1024;
4577dd7cddfSDavid du Colombier
4587dd7cddfSDavid du Colombier switch(mp->reg[ConfigCntl]&0x3){
4597dd7cddfSDavid du Colombier case 0:
46014414594SDavid du Colombier vga->apz = 16*1024*1024; /* empirical -rsc */
46114414594SDavid du Colombier break;
4627dd7cddfSDavid du Colombier case 1:
4637dd7cddfSDavid du Colombier vga->apz = 4*1024*1024;
4647dd7cddfSDavid du Colombier break;
4657dd7cddfSDavid du Colombier case 2:
4667dd7cddfSDavid du Colombier vga->apz = 8*1024*1024;
4677dd7cddfSDavid du Colombier break;
4687dd7cddfSDavid du Colombier case 3:
46959cc4ca5SDavid du Colombier vga->apz = 2*1024*1024; /* empirical: mach64GX -rsc */
47059cc4ca5SDavid du Colombier break;
4717dd7cddfSDavid du Colombier }
4727dd7cddfSDavid du Colombier
4737dd7cddfSDavid du Colombier ctlr->flag |= Fsnarf;
4747dd7cddfSDavid du Colombier }
4757dd7cddfSDavid du Colombier
4767dd7cddfSDavid du Colombier static void
options(Vga *,Ctlr * ctlr)4777dd7cddfSDavid du Colombier options(Vga*, Ctlr* ctlr)
4787dd7cddfSDavid du Colombier {
4797dd7cddfSDavid du Colombier ctlr->flag |= Hlinear|Foptions;
4807dd7cddfSDavid du Colombier }
4817dd7cddfSDavid du Colombier
4827dd7cddfSDavid du Colombier static void
clock(Vga * vga,Ctlr * ctlr)4837dd7cddfSDavid du Colombier clock(Vga* vga, Ctlr* ctlr)
4847dd7cddfSDavid du Colombier {
4857dd7cddfSDavid du Colombier int clk, m, n, p;
4867dd7cddfSDavid du Colombier double f, q;
4877dd7cddfSDavid du Colombier Mach64xx *mp;
4887dd7cddfSDavid du Colombier
4897dd7cddfSDavid du Colombier mp = vga->private;
4907dd7cddfSDavid du Colombier
4917dd7cddfSDavid du Colombier /*
4927dd7cddfSDavid du Colombier * Don't compute clock timings for LCD panels.
4937dd7cddfSDavid du Colombier * Just use what's already there. We can't just use
4947dd7cddfSDavid du Colombier * the frequency in the vgadb for this because
4957dd7cddfSDavid du Colombier * the frequency being programmed into the PLLs
4967dd7cddfSDavid du Colombier * is not the frequency being used to compute the DSP
4977dd7cddfSDavid du Colombier * settings. The DSP-relevant frequency is the one
4987dd7cddfSDavid du Colombier * we keep in /lib/vgadb.
4997dd7cddfSDavid du Colombier */
5007dd7cddfSDavid du Colombier if(mp->lcdon){
5017dd7cddfSDavid du Colombier clk = mp->reg[ClockCntl] & 0x03;
5027dd7cddfSDavid du Colombier n = mp->pll[7+clk];
5037dd7cddfSDavid du Colombier p = (mp->pll[6]>>(clk*2)) & 0x03;
5047dd7cddfSDavid du Colombier p |= (mp->pll[11]>>(2+clk)) & 0x04;
5057dd7cddfSDavid du Colombier switch(p){
5067dd7cddfSDavid du Colombier case 0:
5077dd7cddfSDavid du Colombier case 1:
5087dd7cddfSDavid du Colombier case 2:
5097dd7cddfSDavid du Colombier case 3:
5107dd7cddfSDavid du Colombier p = 1<<p;
5117dd7cddfSDavid du Colombier break;
5127dd7cddfSDavid du Colombier case 4+0:
5137dd7cddfSDavid du Colombier p = 3;
5147dd7cddfSDavid du Colombier break;
5157dd7cddfSDavid du Colombier case 4+2:
5167dd7cddfSDavid du Colombier p = 6;
5177dd7cddfSDavid du Colombier break;
5187dd7cddfSDavid du Colombier case 4+3:
5197dd7cddfSDavid du Colombier p = 12;
5207dd7cddfSDavid du Colombier break;
5217dd7cddfSDavid du Colombier
5227dd7cddfSDavid du Colombier default:
5237dd7cddfSDavid du Colombier case 4+1:
5247dd7cddfSDavid du Colombier p = -1;
5257dd7cddfSDavid du Colombier break;
5267dd7cddfSDavid du Colombier }
5277dd7cddfSDavid du Colombier m = mp->pll[PLLm];
5287dd7cddfSDavid du Colombier f = (2.0*RefFreq*n)/(m*p) + 0.5;
5297dd7cddfSDavid du Colombier
5307dd7cddfSDavid du Colombier vga->m[0] = m;
5317dd7cddfSDavid du Colombier vga->p[0] = p;
5327dd7cddfSDavid du Colombier vga->n[0] = n;
5337dd7cddfSDavid du Colombier vga->f[0] = f;
5347dd7cddfSDavid du Colombier return;
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier
5377dd7cddfSDavid du Colombier if(vga->f[0] == 0)
5387dd7cddfSDavid du Colombier vga->f[0] = vga->mode->frequency;
5397dd7cddfSDavid du Colombier f = vga->f[0];
5407dd7cddfSDavid du Colombier
5417dd7cddfSDavid du Colombier /*
5427dd7cddfSDavid du Colombier * To generate a specific output frequency, the reference (m),
5437dd7cddfSDavid du Colombier * feedback (n), and post dividers (p) must be loaded with the
5447dd7cddfSDavid du Colombier * appropriate divide-down ratios. In the following r is the
5457dd7cddfSDavid du Colombier * XTALIN frequency (usually RefFreq) and t is the target frequency
5467dd7cddfSDavid du Colombier * (vga->f).
5477dd7cddfSDavid du Colombier *
5487dd7cddfSDavid du Colombier * Use the maximum reference divider left by the BIOS for now,
5497dd7cddfSDavid du Colombier * otherwise MCLK might be a concern. It can be calculated as
5507dd7cddfSDavid du Colombier * follows:
5517dd7cddfSDavid du Colombier * Upper Limit of PLL Lock Range
5527dd7cddfSDavid du Colombier * Minimum PLLREFCLK = -----------------------------
5537dd7cddfSDavid du Colombier * (2*255)
5547dd7cddfSDavid du Colombier *
5557dd7cddfSDavid du Colombier * XTALIN
5567dd7cddfSDavid du Colombier * m = Floor[-----------------]
5577dd7cddfSDavid du Colombier * Minimum PLLREFCLK
5587dd7cddfSDavid du Colombier *
5597dd7cddfSDavid du Colombier * For an upper limit of 135MHz and XTALIN of 14.318MHz m
5607dd7cddfSDavid du Colombier * would be 54.
5617dd7cddfSDavid du Colombier */
5627dd7cddfSDavid du Colombier m = mp->pll[PLLm];
5637dd7cddfSDavid du Colombier vga->m[0] = m;
5647dd7cddfSDavid du Colombier
5657dd7cddfSDavid du Colombier /*
5667dd7cddfSDavid du Colombier * The post divider may be 1, 2, 4 or 8 and is determined by
5677dd7cddfSDavid du Colombier * calculating
5687dd7cddfSDavid du Colombier * t*m
5697dd7cddfSDavid du Colombier * q = -----
5707dd7cddfSDavid du Colombier * (2*r)
5717dd7cddfSDavid du Colombier * and using the result to look-up p.
5727dd7cddfSDavid du Colombier */
5737dd7cddfSDavid du Colombier q = (f*m)/(2*RefFreq);
5747dd7cddfSDavid du Colombier if(ctlr->flag&Uenhanced){
5757dd7cddfSDavid du Colombier if(q > 255 || q < 10.6666666667)
5767dd7cddfSDavid du Colombier error("%s: vclk %lud out of range\n", ctlr->name, vga->f[0]);
5777dd7cddfSDavid du Colombier if(q > 127.5)
5787dd7cddfSDavid du Colombier p = 1;
5797dd7cddfSDavid du Colombier else if(q > 85)
5807dd7cddfSDavid du Colombier p = 2;
5817dd7cddfSDavid du Colombier else if(q > 63.75)
5827dd7cddfSDavid du Colombier p = 3;
5837dd7cddfSDavid du Colombier else if(q > 42.5)
5847dd7cddfSDavid du Colombier p = 4;
5857dd7cddfSDavid du Colombier else if(q > 31.875)
5867dd7cddfSDavid du Colombier p = 6;
5877dd7cddfSDavid du Colombier else if(q > 21.25)
5887dd7cddfSDavid du Colombier p = 8;
5897dd7cddfSDavid du Colombier else
5907dd7cddfSDavid du Colombier p = 12;
5917dd7cddfSDavid du Colombier }else{
5927dd7cddfSDavid du Colombier if(q > 255 || q < 16)
5937dd7cddfSDavid du Colombier error("%s: vclk %lud out of range\n", ctlr->name, vga->f[0]);
5947dd7cddfSDavid du Colombier if(q >= 127.5)
5957dd7cddfSDavid du Colombier p = 1;
5967dd7cddfSDavid du Colombier else if(q >= 63.5)
5977dd7cddfSDavid du Colombier p = 2;
5987dd7cddfSDavid du Colombier else if(q >= 31.5)
5997dd7cddfSDavid du Colombier p = 4;
6007dd7cddfSDavid du Colombier else
6017dd7cddfSDavid du Colombier p = 8;
6027dd7cddfSDavid du Colombier }
6037dd7cddfSDavid du Colombier vga->p[0] = p;
6047dd7cddfSDavid du Colombier
6057dd7cddfSDavid du Colombier /*
6067dd7cddfSDavid du Colombier * The feedback divider should be kept in the range 0x80 to 0xFF
6077dd7cddfSDavid du Colombier * and is found from
6087dd7cddfSDavid du Colombier * n = q*p
6097dd7cddfSDavid du Colombier * rounded to the nearest whole number.
6107dd7cddfSDavid du Colombier */
6117dd7cddfSDavid du Colombier vga->n[0] = (q*p)+0.5;
6127dd7cddfSDavid du Colombier }
6137dd7cddfSDavid du Colombier
6147dd7cddfSDavid du Colombier typedef struct Meminfo Meminfo;
6157dd7cddfSDavid du Colombier struct Meminfo {
6167dd7cddfSDavid du Colombier int latency;
6177dd7cddfSDavid du Colombier int latch;
6187dd7cddfSDavid du Colombier int trp; /* filled in from card */
6197dd7cddfSDavid du Colombier int trcd; /* filled in from card */
6207dd7cddfSDavid du Colombier int tcrd; /* filled in from card */
6217dd7cddfSDavid du Colombier int tras; /* filled in from card */
6227dd7cddfSDavid du Colombier };
6237dd7cddfSDavid du Colombier
6247dd7cddfSDavid du Colombier enum {
6257dd7cddfSDavid du Colombier Mdram,
6267dd7cddfSDavid du Colombier Medo,
6277dd7cddfSDavid du Colombier Msdram,
6287dd7cddfSDavid du Colombier Mwram,
6297dd7cddfSDavid du Colombier };
6307dd7cddfSDavid du Colombier
6317dd7cddfSDavid du Colombier /*
6327dd7cddfSDavid du Colombier * The manuals and documentation are silent on which settings
6337dd7cddfSDavid du Colombier * to use for Mwdram, or how to tell which to use.
6347dd7cddfSDavid du Colombier */
6357dd7cddfSDavid du Colombier static Meminfo meminfo[] = {
6367dd7cddfSDavid du Colombier [Mdram] { 1, 0 },
6377dd7cddfSDavid du Colombier [Medo] { 1, 2 },
6387dd7cddfSDavid du Colombier [Msdram] { 3, 1 },
6397dd7cddfSDavid du Colombier [Mwram] { 1, 3 }, /* non TYPE_A */
6407dd7cddfSDavid du Colombier };
6417dd7cddfSDavid du Colombier
6427dd7cddfSDavid du Colombier static ushort looplatencytab[2][2] = {
6437dd7cddfSDavid du Colombier { 8, 6 }, /* DRAM: ≤1M, > 1M */
6447dd7cddfSDavid du Colombier { 9, 8 }, /* SDRAM: ≤1M, > 1M */
6457dd7cddfSDavid du Colombier };
6467dd7cddfSDavid du Colombier
6477dd7cddfSDavid du Colombier static ushort cyclesperqwordtab[2][2] = {
6487dd7cddfSDavid du Colombier { 3, 2 }, /* DRAM: ≤1M, > 1M */
6497dd7cddfSDavid du Colombier { 2, 1 }, /* SDRAM: ≤1M, > 1M */
6507dd7cddfSDavid du Colombier };
6517dd7cddfSDavid du Colombier
6527dd7cddfSDavid du Colombier static int memtype[] = {
6537dd7cddfSDavid du Colombier -1, /* disable memory access */
6547dd7cddfSDavid du Colombier Mdram, /* basic DRAM */
6557dd7cddfSDavid du Colombier Medo, /* EDO */
6567dd7cddfSDavid du Colombier Medo, /* hyper page DRAM or EDO */
6577dd7cddfSDavid du Colombier Msdram, /* SDRAM */
6587dd7cddfSDavid du Colombier Msdram, /* SGRAM */
6597dd7cddfSDavid du Colombier Mwram,
6607dd7cddfSDavid du Colombier Mwram
6617dd7cddfSDavid du Colombier };
6627dd7cddfSDavid du Colombier
6637dd7cddfSDavid du Colombier /*
6647dd7cddfSDavid du Colombier * Calculate various memory parameters so that the card
6657dd7cddfSDavid du Colombier * fetches the right bytes at the right time. I don't claim to
6667dd7cddfSDavid du Colombier * understand the actual calculations very well.
6677dd7cddfSDavid du Colombier *
6687dd7cddfSDavid du Colombier * This is remarkably useful on laptops, since knowledge of
6697dd7cddfSDavid du Colombier * x lets us find the frequency that the screen is really running
6707dd7cddfSDavid du Colombier * at, which is not necessarily in the VCLKs.
6717dd7cddfSDavid du Colombier */
6727dd7cddfSDavid du Colombier static void
setdsp(Vga * vga,Ctlr *)6737dd7cddfSDavid du Colombier setdsp(Vga* vga, Ctlr*)
6747dd7cddfSDavid du Colombier {
6757dd7cddfSDavid du Colombier Mach64xx *mp;
6767dd7cddfSDavid du Colombier Meminfo *mem;
6777dd7cddfSDavid du Colombier ushort table, memclk, memtyp;
6787dd7cddfSDavid du Colombier int i, prec, xprec, fprec;
6797dd7cddfSDavid du Colombier ulong t;
6807dd7cddfSDavid du Colombier double pw, x, fifosz, fifoon, fifooff;
6817dd7cddfSDavid du Colombier ushort dspon, dspoff;
6827dd7cddfSDavid du Colombier int afifosz, lat, ncycle, pfc, rcc;
6837dd7cddfSDavid du Colombier
6847dd7cddfSDavid du Colombier mp = vga->private;
6857dd7cddfSDavid du Colombier
6867dd7cddfSDavid du Colombier /*
6877dd7cddfSDavid du Colombier * Get video ram configuration from BIOS and chip
6887dd7cddfSDavid du Colombier */
6897dd7cddfSDavid du Colombier table = *(ushort*)readbios(sizeof table, 0xc0048);
6907dd7cddfSDavid du Colombier trace("rom table offset %uX\n", table);
6917dd7cddfSDavid du Colombier table = *(ushort*)readbios(sizeof table, 0xc0000+table+16);
6927dd7cddfSDavid du Colombier trace("freq table offset %uX\n", table);
6937dd7cddfSDavid du Colombier memclk = *(ushort*)readbios(sizeof memclk, 0xc0000+table+18);
6947dd7cddfSDavid du Colombier trace("memclk %ud\n", memclk);
6957dd7cddfSDavid du Colombier memtyp = memtype[mp->reg[ConfigStat0]&07];
6967dd7cddfSDavid du Colombier mem = &meminfo[memtyp];
6977dd7cddfSDavid du Colombier
6987dd7cddfSDavid du Colombier /*
6997dd7cddfSDavid du Colombier * First we need to calculate x, the number of
7007dd7cddfSDavid du Colombier * XCLKs that one QWORD occupies in the display FIFO.
7017dd7cddfSDavid du Colombier *
7027dd7cddfSDavid du Colombier * For some reason, x gets stretched out if LCD stretching
7037dd7cddfSDavid du Colombier * is turned on.
7047dd7cddfSDavid du Colombier */
7057dd7cddfSDavid du Colombier
7067dd7cddfSDavid du Colombier x = ((double)memclk*640000.0) /
7077dd7cddfSDavid du Colombier ((double)vga->mode->frequency * (double)vga->mode->z);
7087dd7cddfSDavid du Colombier if(mp->lcd[LCD_HorzStretch] & (1<<31))
7097dd7cddfSDavid du Colombier x *= 4096.0 / (double)(mp->lcd[LCD_HorzStretch] & 0xFFFF);
7107dd7cddfSDavid du Colombier
7117dd7cddfSDavid du Colombier trace("memclk %d... x %f...", memclk, x);
7127dd7cddfSDavid du Colombier /*
7137dd7cddfSDavid du Colombier * We have 14 bits to specify x in. Decide where to
7147dd7cddfSDavid du Colombier * put the decimal (err, binary) point by counting how
7157dd7cddfSDavid du Colombier * many significant bits are in the integer portion of x.
7167dd7cddfSDavid du Colombier */
7177dd7cddfSDavid du Colombier t = x;
7187dd7cddfSDavid du Colombier for(i=31; i>=0; i--)
7197dd7cddfSDavid du Colombier if(t & (1<<i))
7207dd7cddfSDavid du Colombier break;
7217dd7cddfSDavid du Colombier xprec = i+1;
7227dd7cddfSDavid du Colombier trace("t %lud... xprec %d...", t, xprec);
7237dd7cddfSDavid du Colombier
7247dd7cddfSDavid du Colombier /*
7257dd7cddfSDavid du Colombier * The maximum FIFO size is the number of XCLKs per QWORD
7267dd7cddfSDavid du Colombier * multiplied by 32, for some reason. We have 11 bits to
7277dd7cddfSDavid du Colombier * specify fifosz.
7287dd7cddfSDavid du Colombier */
7297dd7cddfSDavid du Colombier fifosz = x * 32.0;
7307dd7cddfSDavid du Colombier trace("fifosz %f...", fifosz);
7317dd7cddfSDavid du Colombier t = fifosz;
7327dd7cddfSDavid du Colombier for(i=31; i>=0; i--)
7337dd7cddfSDavid du Colombier if(t & (1<<i))
7347dd7cddfSDavid du Colombier break;
7357dd7cddfSDavid du Colombier fprec = i+1;
7367dd7cddfSDavid du Colombier trace("fprec %d...", fprec);
7377dd7cddfSDavid du Colombier
7387dd7cddfSDavid du Colombier /*
7397dd7cddfSDavid du Colombier * Precision is specified as 3 less than the number of bits
7407dd7cddfSDavid du Colombier * in the integer part of x, and 5 less than the number of bits
7417dd7cddfSDavid du Colombier * in the integer part of fifosz.
7427dd7cddfSDavid du Colombier *
7437dd7cddfSDavid du Colombier * It is bounded by zero and seven.
7447dd7cddfSDavid du Colombier */
7457dd7cddfSDavid du Colombier prec = (xprec-3 > fprec-5) ? xprec-3 : fprec-5;
7467dd7cddfSDavid du Colombier if(prec < 0)
7477dd7cddfSDavid du Colombier prec = 0;
7487dd7cddfSDavid du Colombier if(prec > 7)
7497dd7cddfSDavid du Colombier prec = 7;
7507dd7cddfSDavid du Colombier
7517dd7cddfSDavid du Colombier xprec = prec+3;
7527dd7cddfSDavid du Colombier fprec = prec+5;
7537dd7cddfSDavid du Colombier trace("prec %d...", prec);
7547dd7cddfSDavid du Colombier
7557dd7cddfSDavid du Colombier /*
7567dd7cddfSDavid du Colombier * Actual fifo size
7577dd7cddfSDavid du Colombier */
7587dd7cddfSDavid du Colombier afifosz = (1<<fprec) / x;
7597dd7cddfSDavid du Colombier if(afifosz > 32)
7607dd7cddfSDavid du Colombier afifosz = 32;
7617dd7cddfSDavid du Colombier
76259cc4ca5SDavid du Colombier fifooff = ceil(x*(afifosz-1));
7637dd7cddfSDavid du Colombier
7647dd7cddfSDavid du Colombier /*
7657dd7cddfSDavid du Colombier * I am suspicious of this table, lifted from ATI docs,
7667dd7cddfSDavid du Colombier * because it doesn't agree with the Windows drivers.
7677dd7cddfSDavid du Colombier * We always get 0x0A for lat+2 while Windows uses 0x08.
7687dd7cddfSDavid du Colombier */
7697dd7cddfSDavid du Colombier lat = looplatencytab[memtyp > 1][vga->vmz > 1*1024*1024];
7707dd7cddfSDavid du Colombier trace("afifosz %d...fifooff %f...", afifosz, fifooff);
7717dd7cddfSDavid du Colombier
7727dd7cddfSDavid du Colombier /*
7737dd7cddfSDavid du Colombier * Page fault clock
7747dd7cddfSDavid du Colombier */
7757dd7cddfSDavid du Colombier t = mp->reg[MemCntl];
7767dd7cddfSDavid du Colombier mem->trp = (t>>8)&3; /* RAS precharge time */
7777dd7cddfSDavid du Colombier mem->trcd = (t>>10)&3; /* RAS to CAS delay */
7787dd7cddfSDavid du Colombier mem->tcrd = (t>>12)&1; /* CAS to RAS delay */
7797dd7cddfSDavid du Colombier mem->tras = (t>>16)&7; /* RAS low minimum pulse width */
7807dd7cddfSDavid du Colombier pfc = mem->trp + 1 + mem->trcd + 1 + mem->tcrd;
7817dd7cddfSDavid du Colombier trace("pfc %d...", pfc);
7827dd7cddfSDavid du Colombier
7837dd7cddfSDavid du Colombier /*
7847dd7cddfSDavid du Colombier * Maximum random access cycle clock.
7857dd7cddfSDavid du Colombier */
7867dd7cddfSDavid du Colombier ncycle = cyclesperqwordtab[memtyp > 1][vga->vmz > 1*1024*1024];
7877dd7cddfSDavid du Colombier rcc = mem->trp + 1 + mem->tras + 1;
7887dd7cddfSDavid du Colombier if(rcc < pfc+ncycle)
7897dd7cddfSDavid du Colombier rcc = pfc+ncycle;
7907dd7cddfSDavid du Colombier trace("rcc %d...", rcc);
7917dd7cddfSDavid du Colombier
79259cc4ca5SDavid du Colombier fifoon = (rcc > floor(x)) ? rcc : floor(x);
79359cc4ca5SDavid du Colombier fifoon += (3.0 * rcc) - 1 + pfc + ncycle;
7947dd7cddfSDavid du Colombier trace("fifoon %f...\n", fifoon);
7957dd7cddfSDavid du Colombier /*
7967dd7cddfSDavid du Colombier * Now finally put the bits together.
7977dd7cddfSDavid du Colombier * x is stored in a 14 bit field with xprec bits of integer.
7987dd7cddfSDavid du Colombier */
7997dd7cddfSDavid du Colombier pw = x * (1<<(14-xprec));
8007dd7cddfSDavid du Colombier mp->reg[DspConfig] = (ulong)pw | (((lat+2)&0xF)<<16) | ((prec&7)<<20);
8017dd7cddfSDavid du Colombier
8027dd7cddfSDavid du Colombier /*
8037dd7cddfSDavid du Colombier * These are stored in an 11 bit field with fprec bits of integer.
8047dd7cddfSDavid du Colombier */
8057dd7cddfSDavid du Colombier dspon = (ushort)fifoon << (11-fprec);
8067dd7cddfSDavid du Colombier dspoff = (ushort)fifooff << (11-fprec);
8077dd7cddfSDavid du Colombier mp->reg[DspOnOff] = ((dspon&0x7ff) << 16) | (dspoff&0x7ff);
8087dd7cddfSDavid du Colombier }
8097dd7cddfSDavid du Colombier
8107dd7cddfSDavid du Colombier static void
init(Vga * vga,Ctlr * ctlr)8117dd7cddfSDavid du Colombier init(Vga* vga, Ctlr* ctlr)
8127dd7cddfSDavid du Colombier {
8137dd7cddfSDavid du Colombier Mode *mode;
8147dd7cddfSDavid du Colombier Mach64xx *mp;
815223a736eSDavid du Colombier int p, x, y;
8167dd7cddfSDavid du Colombier
8177dd7cddfSDavid du Colombier mode = vga->mode;
8187dd7cddfSDavid du Colombier if((mode->x > 640 || mode->y > 480) && mode->z == 1)
8197dd7cddfSDavid du Colombier error("%s: no support for 1-bit mode other than 640x480x1\n",
8207dd7cddfSDavid du Colombier ctlr->name);
8217dd7cddfSDavid du Colombier
8227dd7cddfSDavid du Colombier mp = vga->private;
8237dd7cddfSDavid du Colombier if(mode->z > 8 && mp->pci == nil)
8247dd7cddfSDavid du Colombier error("%s: no support for >8-bit color without PCI\n",
8257dd7cddfSDavid du Colombier ctlr->name);
8267dd7cddfSDavid du Colombier
8277dd7cddfSDavid du Colombier /*
8287dd7cddfSDavid du Colombier * Check for Rage chip
8297dd7cddfSDavid du Colombier */
8307dd7cddfSDavid du Colombier switch (mp->reg[ConfigChipId]&0xffff) {
8317dd7cddfSDavid du Colombier case ('G'<<8)|'B': /* 4742: 264GT PRO */
8327dd7cddfSDavid du Colombier case ('G'<<8)|'D': /* 4744: 264GT PRO */
8337dd7cddfSDavid du Colombier case ('G'<<8)|'I': /* 4749: 264GT PRO */
83459cc4ca5SDavid du Colombier case ('G'<<8)|'M': /* 474D: Rage XL */
8357dd7cddfSDavid du Colombier case ('G'<<8)|'P': /* 4750: 264GT PRO */
8367dd7cddfSDavid du Colombier case ('G'<<8)|'Q': /* 4751: 264GT PRO */
8379a747e4fSDavid du Colombier case ('G'<<8)|'R': /* 4752: */
8387dd7cddfSDavid du Colombier case ('G'<<8)|'U': /* 4755: 264GT DVD */
8397dd7cddfSDavid du Colombier case ('G'<<8)|'V': /* 4756: Rage2C */
8407dd7cddfSDavid du Colombier case ('G'<<8)|'Z': /* 475A: Rage2C */
8417dd7cddfSDavid du Colombier case ('V'<<8)|'U': /* 5655: 264VT3 */
84259cc4ca5SDavid du Colombier case ('V'<<8)|'V': /* 5656: 264VT4 */
8437dd7cddfSDavid du Colombier case ('G'<<8)|'T': /* 4754: 264GT[B] */
8447dd7cddfSDavid du Colombier case ('V'<<8)|'T': /* 5654: 264VT/GT/VTB */
845223a736eSDavid du Colombier case ('L'<<8)|'B': /* 4C42: Rage LTPro AGP */
8467dd7cddfSDavid du Colombier case ('L'<<8)|'I': /* 4C49: 264LT PRO */
8477dd7cddfSDavid du Colombier case ('L'<<8)|'M': /* 4C4D: Rage Mobility */
8487dd7cddfSDavid du Colombier case ('L'<<8)|'P': /* 4C50: 264LT PRO */
8497dd7cddfSDavid du Colombier ctlr->flag |= Uenhanced;
8507dd7cddfSDavid du Colombier break;
8517dd7cddfSDavid du Colombier }
8527dd7cddfSDavid du Colombier
8537dd7cddfSDavid du Colombier /*
8547dd7cddfSDavid du Colombier * Always use VCLK2.
8557dd7cddfSDavid du Colombier */
8567dd7cddfSDavid du Colombier clock(vga, ctlr);
8577dd7cddfSDavid du Colombier mp->pll[PLLn2] = vga->n[0];
8587dd7cddfSDavid du Colombier mp->pll[PLLp] &= ~(0x03<<(2*2));
8597dd7cddfSDavid du Colombier switch(vga->p[0]){
8607dd7cddfSDavid du Colombier case 1:
8617dd7cddfSDavid du Colombier case 3:
8627dd7cddfSDavid du Colombier p = 0;
8637dd7cddfSDavid du Colombier break;
8647dd7cddfSDavid du Colombier
8657dd7cddfSDavid du Colombier case 2:
8667dd7cddfSDavid du Colombier p = 1;
8677dd7cddfSDavid du Colombier break;
8687dd7cddfSDavid du Colombier
8697dd7cddfSDavid du Colombier case 4:
8707dd7cddfSDavid du Colombier case 6:
8717dd7cddfSDavid du Colombier p = 2;
8727dd7cddfSDavid du Colombier break;
8737dd7cddfSDavid du Colombier
8747dd7cddfSDavid du Colombier case 8:
8757dd7cddfSDavid du Colombier case 12:
8767dd7cddfSDavid du Colombier p = 3;
8777dd7cddfSDavid du Colombier break;
8787dd7cddfSDavid du Colombier
8797dd7cddfSDavid du Colombier default:
8807dd7cddfSDavid du Colombier p = 3;
8817dd7cddfSDavid du Colombier break;
8827dd7cddfSDavid du Colombier }
8837dd7cddfSDavid du Colombier mp->pll[PLLp] |= p<<(2*2);
8847dd7cddfSDavid du Colombier if ((1<<p) != vga->p[0])
8857dd7cddfSDavid du Colombier mp->pll[PLLx] |= 1<<(4+2);
8867dd7cddfSDavid du Colombier else
8877dd7cddfSDavid du Colombier mp->pll[PLLx] &= ~(1<<(4+2));
8887dd7cddfSDavid du Colombier mp->reg[ClockCntl] = 2;
8897dd7cddfSDavid du Colombier
8907dd7cddfSDavid du Colombier mp->reg[ConfigCntl] = 0;
8917dd7cddfSDavid du Colombier
8927dd7cddfSDavid du Colombier mp->reg[CrtcGenCntl] = 0x02000000|(mp->reg[CrtcGenCntl] & ~0x01400700);
8937dd7cddfSDavid du Colombier switch(mode->z){
8947dd7cddfSDavid du Colombier default:
8957dd7cddfSDavid du Colombier case 1:
8967dd7cddfSDavid du Colombier mp->reg[CrtcGenCntl] |= 0x00000100;
8977dd7cddfSDavid du Colombier mp->reg[DpPixWidth] = 0x00000000;
8987dd7cddfSDavid du Colombier break;
8997dd7cddfSDavid du Colombier case 8:
9007dd7cddfSDavid du Colombier mp->reg[CrtcGenCntl] |= 0x01000200;
9017dd7cddfSDavid du Colombier mp->reg[DpPixWidth] = 0x00020202;
9027dd7cddfSDavid du Colombier break;
9037dd7cddfSDavid du Colombier case 15:
9047dd7cddfSDavid du Colombier mp->reg[CrtcGenCntl] |= 0x01000300;
9057dd7cddfSDavid du Colombier mp->reg[DpPixWidth] = 0x00030303;
9067dd7cddfSDavid du Colombier break;
9077dd7cddfSDavid du Colombier case 16:
9087dd7cddfSDavid du Colombier mp->reg[CrtcGenCntl] |= 0x01000400;
9097dd7cddfSDavid du Colombier mp->reg[DpPixWidth] = 0x00040404;
9107dd7cddfSDavid du Colombier break;
9117dd7cddfSDavid du Colombier case 24:
9127dd7cddfSDavid du Colombier mp->reg[CrtcGenCntl] |= 0x01000500;
9137dd7cddfSDavid du Colombier mp->reg[DpPixWidth] = 0x00050505;
9147dd7cddfSDavid du Colombier break;
9157dd7cddfSDavid du Colombier case 32:
9167dd7cddfSDavid du Colombier mp->reg[CrtcGenCntl] |= 0x01000600;
9177dd7cddfSDavid du Colombier mp->reg[DpPixWidth] = 0x00060606;
9187dd7cddfSDavid du Colombier break;
9197dd7cddfSDavid du Colombier }
9207dd7cddfSDavid du Colombier
9217dd7cddfSDavid du Colombier mp->reg[HTotalDisp] = (((mode->x>>3)-1)<<16)|((mode->ht>>3)-1);
9227dd7cddfSDavid du Colombier mp->reg[HSyncStrtWid] = (((mode->ehs - mode->shs)>>3)<<16)
9237dd7cddfSDavid du Colombier |((mode->shs>>3)-1);
9247dd7cddfSDavid du Colombier if(mode->hsync == '-')
9257dd7cddfSDavid du Colombier mp->reg[HSyncStrtWid] |= 0x00200000;
9267dd7cddfSDavid du Colombier mp->reg[VTotalDisp] = ((mode->y-1)<<16)|(mode->vt-1);
9277dd7cddfSDavid du Colombier mp->reg[VSyncStrtWid] = ((mode->vre - mode->vrs)<<16)|(mode->vrs-1);
9287dd7cddfSDavid du Colombier if(mode->vsync == '-')
9297dd7cddfSDavid du Colombier mp->reg[VSyncStrtWid] |= 0x00200000;
9307dd7cddfSDavid du Colombier mp->reg[IntCntl] = 0;
9317dd7cddfSDavid du Colombier
9327dd7cddfSDavid du Colombier /*
9337dd7cddfSDavid du Colombier * This used to set it to (mode->x/(8*2))<<22 for depths < 8,
9347dd7cddfSDavid du Colombier * but from the manual that seems wrong to me. -rsc
9357dd7cddfSDavid du Colombier */
9367dd7cddfSDavid du Colombier mp->reg[OffPitch] = (vga->virtx/8)<<22;
9377dd7cddfSDavid du Colombier
9387dd7cddfSDavid du Colombier mp->reg[OvrClr] = Pblack;
9397dd7cddfSDavid du Colombier
9407dd7cddfSDavid du Colombier if(vga->linear && mode->z != 1)
9417dd7cddfSDavid du Colombier ctlr->flag |= Ulinear;
9427dd7cddfSDavid du Colombier
9437dd7cddfSDavid du Colombier /*
9447dd7cddfSDavid du Colombier * Heuristic fiddling on LT PRO.
9457dd7cddfSDavid du Colombier * Do this before setdsp so the stretching is right.
9467dd7cddfSDavid du Colombier */
9477dd7cddfSDavid du Colombier if(mp->lcdon){
9487dd7cddfSDavid du Colombier /* use non-shadowed registers */
9497dd7cddfSDavid du Colombier mp->lcd[LCD_GenCtrl] &= ~0x00000404;
9507dd7cddfSDavid du Colombier mp->lcd[LCD_ConfigPanel] |= 0x00004000;
9517dd7cddfSDavid du Colombier
9527dd7cddfSDavid du Colombier mp->lcd[LCD_VertStretch] = 0;
953223a736eSDavid du Colombier y = ((mp->lcd[LCD_ExtVertStretch]>>11) & 0x7FF)+1;
954223a736eSDavid du Colombier if(mode->y < y){
955223a736eSDavid du Colombier x = (mode->y*1024)/y;
9567dd7cddfSDavid du Colombier mp->lcd[LCD_VertStretch] = 0xC0000000|x;
9577dd7cddfSDavid du Colombier }
9587dd7cddfSDavid du Colombier mp->lcd[LCD_ExtVertStretch] &= ~0x00400400;
959223a736eSDavid du Colombier
960223a736eSDavid du Colombier /*
961223a736eSDavid du Colombier * The x value doesn't seem to be available on all
962223a736eSDavid du Colombier * chips so intuit it from the y value which seems to
963223a736eSDavid du Colombier * be reliable.
964223a736eSDavid du Colombier */
965223a736eSDavid du Colombier mp->lcd[LCD_HorzStretch] &= ~0xC00000FF;
966223a736eSDavid du Colombier x = (mp->lcd[LCD_HorzStretch]>>20) & 0xFF;
967223a736eSDavid du Colombier if(x == 0){
968223a736eSDavid du Colombier switch(y){
969223a736eSDavid du Colombier default:
970223a736eSDavid du Colombier break;
971223a736eSDavid du Colombier case 480:
972223a736eSDavid du Colombier x = 640;
973223a736eSDavid du Colombier break;
974223a736eSDavid du Colombier case 600:
975223a736eSDavid du Colombier x = 800;
976223a736eSDavid du Colombier break;
977223a736eSDavid du Colombier case 768:
978223a736eSDavid du Colombier x = 1024;
979223a736eSDavid du Colombier break;
980223a736eSDavid du Colombier case 1024:
981223a736eSDavid du Colombier x = 1280;
982223a736eSDavid du Colombier break;
983223a736eSDavid du Colombier }
984223a736eSDavid du Colombier }
985223a736eSDavid du Colombier else
986223a736eSDavid du Colombier x = (x+1)*8;
987223a736eSDavid du Colombier if(mode->x < x){
988223a736eSDavid du Colombier x = (mode->x*4096)/x;
989223a736eSDavid du Colombier mp->lcd[LCD_HorzStretch] |= 0xC0000000|x;
990223a736eSDavid du Colombier }
9917dd7cddfSDavid du Colombier }
9927dd7cddfSDavid du Colombier
9937dd7cddfSDavid du Colombier if(ctlr->flag&Uenhanced)
9947dd7cddfSDavid du Colombier setdsp(vga, ctlr);
9957dd7cddfSDavid du Colombier
9967dd7cddfSDavid du Colombier ctlr->flag |= Finit;
9977dd7cddfSDavid du Colombier }
9987dd7cddfSDavid du Colombier
9997dd7cddfSDavid du Colombier static void
load(Vga * vga,Ctlr * ctlr)10007dd7cddfSDavid du Colombier load(Vga* vga, Ctlr* ctlr)
10017dd7cddfSDavid du Colombier {
10027dd7cddfSDavid du Colombier Mach64xx *mp;
10037dd7cddfSDavid du Colombier int i;
10047dd7cddfSDavid du Colombier
10057dd7cddfSDavid du Colombier mp = vga->private;
10067dd7cddfSDavid du Colombier
10077dd7cddfSDavid du Colombier /*
10087dd7cddfSDavid du Colombier * Unlock the CRTC and LCD registers.
10097dd7cddfSDavid du Colombier */
10107dd7cddfSDavid du Colombier mp->iow32(mp, CrtcGenCntl, mp->ior32(mp, CrtcGenCntl)&~0x00400000);
10117dd7cddfSDavid du Colombier if(mp->lcdon)
10127dd7cddfSDavid du Colombier lcdw32(mp, LCD_GenCtrl, mp->lcd[LCD_GenCtrl]|0x80000000);
10137dd7cddfSDavid du Colombier
10147dd7cddfSDavid du Colombier /*
10157dd7cddfSDavid du Colombier * Always use an aperture on a 16Mb boundary.
10167dd7cddfSDavid du Colombier */
10177dd7cddfSDavid du Colombier if(ctlr->flag & Ulinear)
10187dd7cddfSDavid du Colombier mp->reg[ConfigCntl] = ((vga->vmb/(4*1024*1024))<<4)|0x02;
10197dd7cddfSDavid du Colombier
10207dd7cddfSDavid du Colombier mp->iow32(mp, ConfigCntl, mp->reg[ConfigCntl]);
10217dd7cddfSDavid du Colombier
10227dd7cddfSDavid du Colombier mp->iow32(mp, GenTestCntl, 0);
10237dd7cddfSDavid du Colombier mp->iow32(mp, GenTestCntl, 0x100);
10247dd7cddfSDavid du Colombier
10257dd7cddfSDavid du Colombier if((ctlr->flag&Uenhanced) == 0)
10267dd7cddfSDavid du Colombier mp->iow32(mp, MemCntl, mp->reg[MemCntl] & ~0x70000);
10277dd7cddfSDavid du Colombier mp->iow32(mp, BusCntl, mp->reg[BusCntl]);
10287dd7cddfSDavid du Colombier mp->iow32(mp, HTotalDisp, mp->reg[HTotalDisp]);
10297dd7cddfSDavid du Colombier mp->iow32(mp, HSyncStrtWid, mp->reg[HSyncStrtWid]);
10307dd7cddfSDavid du Colombier mp->iow32(mp, VTotalDisp, mp->reg[VTotalDisp]);
10317dd7cddfSDavid du Colombier mp->iow32(mp, VSyncStrtWid, mp->reg[VSyncStrtWid]);
10327dd7cddfSDavid du Colombier mp->iow32(mp, IntCntl, mp->reg[IntCntl]);
10337dd7cddfSDavid du Colombier mp->iow32(mp, OffPitch, mp->reg[OffPitch]);
10347dd7cddfSDavid du Colombier if(mp->lcdon){
10357dd7cddfSDavid du Colombier for(i=0; i<Nlcd; i++)
10367dd7cddfSDavid du Colombier lcdw32(mp, i, mp->lcd[i]);
10377dd7cddfSDavid du Colombier }
10387dd7cddfSDavid du Colombier
10397dd7cddfSDavid du Colombier mp->iow32(mp, GenTestCntl, mp->reg[GenTestCntl]);
10407dd7cddfSDavid du Colombier mp->iow32(mp, ConfigCntl, mp->reg[ConfigCntl]);
10417dd7cddfSDavid du Colombier mp->iow32(mp, CrtcGenCntl, mp->reg[CrtcGenCntl]);
10427dd7cddfSDavid du Colombier mp->iow32(mp, OvrClr, mp->reg[OvrClr]);
10437dd7cddfSDavid du Colombier mp->iow32(mp, OvrWidLR, mp->reg[OvrWidLR]);
10447dd7cddfSDavid du Colombier mp->iow32(mp, OvrWidTB, mp->reg[OvrWidTB]);
10457dd7cddfSDavid du Colombier if(ctlr->flag&Uenhanced){
10467dd7cddfSDavid du Colombier mp->iow32(mp, DacRegs, mp->reg[DacRegs]);
10477dd7cddfSDavid du Colombier mp->iow32(mp, DacCntl, mp->reg[DacCntl]);
10487dd7cddfSDavid du Colombier mp->iow32(mp, CrtcGenCntl, mp->reg[CrtcGenCntl]&~0x02000000);
10497dd7cddfSDavid du Colombier mp->iow32(mp, DspOnOff, mp->reg[DspOnOff]);
10507dd7cddfSDavid du Colombier mp->iow32(mp, DspConfig, mp->reg[DspConfig]);
10517dd7cddfSDavid du Colombier mp->iow32(mp, CrtcGenCntl, mp->reg[CrtcGenCntl]);
10527dd7cddfSDavid du Colombier pllw(mp, PLLx, mp->pll[PLLx]);
10537dd7cddfSDavid du Colombier }
10547dd7cddfSDavid du Colombier pllw(mp, PLLn2, mp->pll[PLLn2]);
10557dd7cddfSDavid du Colombier pllw(mp, PLLp, mp->pll[PLLp]);
10567dd7cddfSDavid du Colombier pllw(mp, PLLn3, mp->pll[PLLn3]);
10577dd7cddfSDavid du Colombier
10587dd7cddfSDavid du Colombier mp->iow32(mp, ClockCntl, mp->reg[ClockCntl]);
10597dd7cddfSDavid du Colombier mp->iow32(mp, ClockCntl, 0x40|mp->reg[ClockCntl]);
10607dd7cddfSDavid du Colombier
10617dd7cddfSDavid du Colombier mp->iow32(mp, DpPixWidth, mp->reg[DpPixWidth]);
10627dd7cddfSDavid du Colombier
10637dd7cddfSDavid du Colombier if(vga->mode->z > 8){
10647dd7cddfSDavid du Colombier int sh, i;
10657dd7cddfSDavid du Colombier /*
10667dd7cddfSDavid du Colombier * We need to initialize the palette, since the DACs use it
10677dd7cddfSDavid du Colombier * in true color modes. First see if the card supports an
10687dd7cddfSDavid du Colombier * 8-bit DAC.
10697dd7cddfSDavid du Colombier */
10707dd7cddfSDavid du Colombier mp->iow32(mp, DacCntl, mp->reg[DacCntl] | 0x100);
10717dd7cddfSDavid du Colombier if(mp->ior32(mp, DacCntl)&0x100){
10727dd7cddfSDavid du Colombier /* card appears to support it */
10737dd7cddfSDavid du Colombier vgactlw("palettedepth", "8");
10747dd7cddfSDavid du Colombier mp->reg[DacCntl] |= 0x100;
10757dd7cddfSDavid du Colombier }
10767dd7cddfSDavid du Colombier
10777dd7cddfSDavid du Colombier if(mp->reg[DacCntl] & 0x100)
10787dd7cddfSDavid du Colombier sh = 0; /* 8-bit DAC */
10797dd7cddfSDavid du Colombier else
10807dd7cddfSDavid du Colombier sh = 2; /* 6-bit DAC */
10817dd7cddfSDavid du Colombier
10827dd7cddfSDavid du Colombier for(i=0; i<256; i++)
10837dd7cddfSDavid du Colombier setpalette(i, i>>sh, i>>sh, i>>sh);
10847dd7cddfSDavid du Colombier }
10857dd7cddfSDavid du Colombier
10867dd7cddfSDavid du Colombier ctlr->flag |= Fload;
10877dd7cddfSDavid du Colombier }
10887dd7cddfSDavid du Colombier
10897dd7cddfSDavid du Colombier static void
pixelclock(Vga * vga,Ctlr * ctlr)10907dd7cddfSDavid du Colombier pixelclock(Vga* vga, Ctlr* ctlr)
10917dd7cddfSDavid du Colombier {
10927dd7cddfSDavid du Colombier Mach64xx *mp;
10937dd7cddfSDavid du Colombier ushort table, s;
10947dd7cddfSDavid du Colombier int memclk, ref_freq, ref_divider, min_freq, max_freq;
10957dd7cddfSDavid du Colombier int feedback, nmult, pd, post, value;
10967dd7cddfSDavid du Colombier int clock;
10977dd7cddfSDavid du Colombier
10987dd7cddfSDavid du Colombier /*
10997dd7cddfSDavid du Colombier * Find the pixel clock from the BIOS and current
11007dd7cddfSDavid du Colombier * settings. Lifted from the ATI-supplied example code.
11017dd7cddfSDavid du Colombier * The clocks stored in the BIOS table are in kHz/10.
11027dd7cddfSDavid du Colombier *
11037dd7cddfSDavid du Colombier * This is the clock LCDs use in vgadb to set the DSP
11047dd7cddfSDavid du Colombier * values.
11057dd7cddfSDavid du Colombier */
11067dd7cddfSDavid du Colombier mp = vga->private;
11077dd7cddfSDavid du Colombier
11087dd7cddfSDavid du Colombier /*
11097dd7cddfSDavid du Colombier * GetPLLInfo()
11107dd7cddfSDavid du Colombier */
11117dd7cddfSDavid du Colombier table = *(ushort*)readbios(sizeof table, 0xc0048);
11127dd7cddfSDavid du Colombier trace("rom table offset %uX\n", table);
11137dd7cddfSDavid du Colombier table = *(ushort*)readbios(sizeof table, 0xc0000+table+16);
11147dd7cddfSDavid du Colombier trace("freq table offset %uX\n", table);
11157dd7cddfSDavid du Colombier s = *(ushort*)readbios(sizeof s, 0xc0000+table+18);
11167dd7cddfSDavid du Colombier memclk = s*10000;
11177dd7cddfSDavid du Colombier trace("memclk %ud\n", memclk);
11187dd7cddfSDavid du Colombier s = *(ushort*)readbios(sizeof s, 0xc0000+table+8);
11197dd7cddfSDavid du Colombier ref_freq = s*10000;
11207dd7cddfSDavid du Colombier trace("ref_freq %ud\n", ref_freq);
11217dd7cddfSDavid du Colombier s = *(ushort*)readbios(sizeof s, 0xc0000+table+10);
11227dd7cddfSDavid du Colombier ref_divider = s;
11237dd7cddfSDavid du Colombier trace("ref_divider %ud\n", ref_divider);
11247dd7cddfSDavid du Colombier s = *(ushort*)readbios(sizeof s, 0xc0000+table+2);
11257dd7cddfSDavid du Colombier min_freq = s*10000;
11267dd7cddfSDavid du Colombier trace("min_freq %ud\n", min_freq);
11277dd7cddfSDavid du Colombier s = *(ushort*)readbios(sizeof s, 0xc0000+table+4);
11287dd7cddfSDavid du Colombier max_freq = s*10000;
11297dd7cddfSDavid du Colombier trace("max_freq %ud\n", max_freq);
11307dd7cddfSDavid du Colombier
11317dd7cddfSDavid du Colombier /*
11327dd7cddfSDavid du Colombier * GetDivider()
11337dd7cddfSDavid du Colombier */
11347dd7cddfSDavid du Colombier pd = mp->pll[PLLp] & 0x03;
11357dd7cddfSDavid du Colombier value = (mp->pll[PLLx] & 0x10)>>2;
11367dd7cddfSDavid du Colombier trace("pd %uX value %uX (|%d)\n", pd, value, value|pd);
11377dd7cddfSDavid du Colombier value |= pd;
11387dd7cddfSDavid du Colombier post = 0;
11397dd7cddfSDavid du Colombier switch(value){
11407dd7cddfSDavid du Colombier case 0:
11417dd7cddfSDavid du Colombier post = 1;
11427dd7cddfSDavid du Colombier break;
11437dd7cddfSDavid du Colombier case 1:
11447dd7cddfSDavid du Colombier post = 2;
11457dd7cddfSDavid du Colombier break;
11467dd7cddfSDavid du Colombier case 2:
11477dd7cddfSDavid du Colombier post = 4;
11487dd7cddfSDavid du Colombier break;
11497dd7cddfSDavid du Colombier case 3:
11507dd7cddfSDavid du Colombier post = 8;
11517dd7cddfSDavid du Colombier break;
11527dd7cddfSDavid du Colombier case 4:
11537dd7cddfSDavid du Colombier post = 3;
11547dd7cddfSDavid du Colombier break;
11557dd7cddfSDavid du Colombier case 5:
11567dd7cddfSDavid du Colombier post = 0;
11577dd7cddfSDavid du Colombier break;
11587dd7cddfSDavid du Colombier case 6:
11597dd7cddfSDavid du Colombier post = 6;
11607dd7cddfSDavid du Colombier break;
11617dd7cddfSDavid du Colombier case 7:
11627dd7cddfSDavid du Colombier post = 12;
11637dd7cddfSDavid du Colombier break;
11647dd7cddfSDavid du Colombier }
11657dd7cddfSDavid du Colombier trace("post = %d\n", post);
11667dd7cddfSDavid du Colombier
11677dd7cddfSDavid du Colombier feedback = mp->pll[PLLn0];
11687dd7cddfSDavid du Colombier if(mp->pll[PLLx] & 0x08)
11697dd7cddfSDavid du Colombier nmult = 4;
11707dd7cddfSDavid du Colombier else
11717dd7cddfSDavid du Colombier nmult = 2;
11727dd7cddfSDavid du Colombier
11737dd7cddfSDavid du Colombier clock = (ref_freq/10000)*nmult*feedback;
11747dd7cddfSDavid du Colombier clock /= ref_divider*post;
11757dd7cddfSDavid du Colombier clock *= 10000;
11767dd7cddfSDavid du Colombier
11777dd7cddfSDavid du Colombier Bprint(&stdout, "%s pixel clock = %ud\n", ctlr->name, clock);
11787dd7cddfSDavid du Colombier }
11797dd7cddfSDavid du Colombier
118059cc4ca5SDavid du Colombier static void dumpmach64bios(Mach64xx*);
118159cc4ca5SDavid du Colombier
11827dd7cddfSDavid du Colombier static void
dump(Vga * vga,Ctlr * ctlr)11837dd7cddfSDavid du Colombier dump(Vga* vga, Ctlr* ctlr)
11847dd7cddfSDavid du Colombier {
11857dd7cddfSDavid du Colombier Mach64xx *mp;
11867dd7cddfSDavid du Colombier int i, m, n, p;
11877dd7cddfSDavid du Colombier double f;
118859cc4ca5SDavid du Colombier static int first = 1;
11897dd7cddfSDavid du Colombier
11907dd7cddfSDavid du Colombier if((mp = vga->private) == 0)
11917dd7cddfSDavid du Colombier return;
11927dd7cddfSDavid du Colombier
119359cc4ca5SDavid du Colombier Bprint(&stdout, "%s pci %p io %lux %s\n", ctlr->name,
119459cc4ca5SDavid du Colombier mp->pci, mp->io, mp->ior32 == pciior32 ? "pciregs" : "ioregs");
11957dd7cddfSDavid du Colombier if(mp->pci)
11967dd7cddfSDavid du Colombier Bprint(&stdout, "%s ccru %ux\n", ctlr->name, mp->pci->ccru);
11977dd7cddfSDavid du Colombier for(i = 0; i < Nreg; i++)
11987dd7cddfSDavid du Colombier Bprint(&stdout, "%s %-*s%.8luX\n",
11997dd7cddfSDavid du Colombier ctlr->name, 20, iorname[i], mp->reg[i]);
12007dd7cddfSDavid du Colombier
12017dd7cddfSDavid du Colombier printitem(ctlr->name, "PLL");
12027dd7cddfSDavid du Colombier for(i = 0; i < Npll; i++)
12037dd7cddfSDavid du Colombier printreg(mp->pll[i]);
12047dd7cddfSDavid du Colombier Bprint(&stdout, "\n");
12057dd7cddfSDavid du Colombier
12067dd7cddfSDavid du Colombier switch(mp->reg[ConfigChipId] & 0xFFFF){
12077dd7cddfSDavid du Colombier default:
12087dd7cddfSDavid du Colombier break;
1209223a736eSDavid du Colombier case ('L'<<8)|'B': /* 4C42: Rage LTPro AGP */
12107dd7cddfSDavid du Colombier case ('L'<<8)|'I': /* 4C49: Rage 3D LTPro */
12117dd7cddfSDavid du Colombier case ('L'<<8)|'M': /* 4C4D: Rage Mobility */
12127dd7cddfSDavid du Colombier case ('L'<<8)|'P': /* 4C50: Rage 3D LTPro */
12137dd7cddfSDavid du Colombier for(i = 0; i < Nlcd; i++)
12147dd7cddfSDavid du Colombier Bprint(&stdout, "%s %-*s%.8luX\n",
12157dd7cddfSDavid du Colombier ctlr->name, 20, lcdname[i], mp->lcd[i]);
12167dd7cddfSDavid du Colombier break;
12177dd7cddfSDavid du Colombier }
12187dd7cddfSDavid du Colombier
12197dd7cddfSDavid du Colombier /*
12207dd7cddfSDavid du Colombier * (2*r*n)
12217dd7cddfSDavid du Colombier * f = -------
12227dd7cddfSDavid du Colombier * (m*p)
12237dd7cddfSDavid du Colombier */
12247dd7cddfSDavid du Colombier m = mp->pll[2];
12257dd7cddfSDavid du Colombier for(i = 0; i < 4; i++){
12267dd7cddfSDavid du Colombier n = mp->pll[7+i];
12277dd7cddfSDavid du Colombier p = (mp->pll[6]>>(i*2)) & 0x03;
12287dd7cddfSDavid du Colombier p |= (mp->pll[11]>>(2+i)) & 0x04;
12297dd7cddfSDavid du Colombier switch(p){
12307dd7cddfSDavid du Colombier case 0:
12317dd7cddfSDavid du Colombier case 1:
12327dd7cddfSDavid du Colombier case 2:
12337dd7cddfSDavid du Colombier case 3:
12347dd7cddfSDavid du Colombier p = 1<<p;
12357dd7cddfSDavid du Colombier break;
12367dd7cddfSDavid du Colombier case 4+0:
12377dd7cddfSDavid du Colombier p = 3;
12387dd7cddfSDavid du Colombier break;
12397dd7cddfSDavid du Colombier case 4+2:
12407dd7cddfSDavid du Colombier p = 6;
12417dd7cddfSDavid du Colombier break;
12427dd7cddfSDavid du Colombier case 4+3:
12437dd7cddfSDavid du Colombier p = 12;
12447dd7cddfSDavid du Colombier break;
12457dd7cddfSDavid du Colombier
12467dd7cddfSDavid du Colombier default:
12477dd7cddfSDavid du Colombier case 4+1:
12487dd7cddfSDavid du Colombier p = -1;
12497dd7cddfSDavid du Colombier break;
12507dd7cddfSDavid du Colombier }
125159cc4ca5SDavid du Colombier if(m*p == 0)
125259cc4ca5SDavid du Colombier Bprint(&stdout, "unknown VCLK%d\n", i);
125359cc4ca5SDavid du Colombier else {
12547dd7cddfSDavid du Colombier f = (2.0*RefFreq*n)/(m*p) + 0.5;
12557dd7cddfSDavid du Colombier Bprint(&stdout, "%s VCLK%d\t%ud\n", ctlr->name, i, (int)f);
12567dd7cddfSDavid du Colombier }
125759cc4ca5SDavid du Colombier }
12587dd7cddfSDavid du Colombier
12597dd7cddfSDavid du Colombier pixelclock(vga, ctlr);
126059cc4ca5SDavid du Colombier
126159cc4ca5SDavid du Colombier if(first) {
126259cc4ca5SDavid du Colombier first = 0;
126359cc4ca5SDavid du Colombier dumpmach64bios(mp);
126459cc4ca5SDavid du Colombier }
126559cc4ca5SDavid du Colombier }
126659cc4ca5SDavid du Colombier
126759cc4ca5SDavid du Colombier enum {
126859cc4ca5SDavid du Colombier ClockFixed=0,
126959cc4ca5SDavid du Colombier ClockIcs2595,
127059cc4ca5SDavid du Colombier ClockStg1703,
127159cc4ca5SDavid du Colombier ClockCh8398,
127259cc4ca5SDavid du Colombier ClockInternal,
127359cc4ca5SDavid du Colombier ClockAtt20c408,
127459cc4ca5SDavid du Colombier ClockIbmrgb514
127559cc4ca5SDavid du Colombier };
127659cc4ca5SDavid du Colombier
127759cc4ca5SDavid du Colombier /*
127859cc4ca5SDavid du Colombier * mostly derived from the xfree86 probe routines.
127959cc4ca5SDavid du Colombier */
128059cc4ca5SDavid du Colombier static void
dumpmach64bios(Mach64xx * mp)128159cc4ca5SDavid du Colombier dumpmach64bios(Mach64xx *mp)
128259cc4ca5SDavid du Colombier {
128359cc4ca5SDavid du Colombier int i, romtable, clocktable, freqtable, lcdtable, lcdpanel;
1284*a8453668SDavid du Colombier uchar bios[0x10000];
128559cc4ca5SDavid du Colombier
128659cc4ca5SDavid du Colombier memmove(bios, readbios(sizeof bios, 0xC0000), sizeof bios);
128759cc4ca5SDavid du Colombier
128859cc4ca5SDavid du Colombier /* find magic string */
128959cc4ca5SDavid du Colombier for(i=0; i<1024; i++)
129059cc4ca5SDavid du Colombier if(strncmp((char*)bios+i, " 761295520", 10) == 0)
129159cc4ca5SDavid du Colombier break;
129259cc4ca5SDavid du Colombier
129359cc4ca5SDavid du Colombier if(i==1024) {
129459cc4ca5SDavid du Colombier Bprint(&stdout, "no ATI bios found\n");
129559cc4ca5SDavid du Colombier return;
129659cc4ca5SDavid du Colombier }
129759cc4ca5SDavid du Colombier
129859cc4ca5SDavid du Colombier /* this is horribly endian dependent. sorry. */
129959cc4ca5SDavid du Colombier romtable = *(ushort*)(bios+0x48);
130059cc4ca5SDavid du Colombier if(romtable+0x12 > sizeof(bios)) {
130159cc4ca5SDavid du Colombier Bprint(&stdout, "couldn't find ATI rom table\n");
130259cc4ca5SDavid du Colombier return;
130359cc4ca5SDavid du Colombier }
130459cc4ca5SDavid du Colombier
130559cc4ca5SDavid du Colombier clocktable = *(ushort*)(bios+romtable+0x10);
130659cc4ca5SDavid du Colombier if(clocktable+0x0C > sizeof(bios)) {
130759cc4ca5SDavid du Colombier Bprint(&stdout, "couldn't find ATI clock table\n");
130859cc4ca5SDavid du Colombier return;
130959cc4ca5SDavid du Colombier }
131059cc4ca5SDavid du Colombier
1311*a8453668SDavid du Colombier freqtable = *(ushort*)(bios+clocktable-2);
131259cc4ca5SDavid du Colombier if(freqtable+0x20 > sizeof(bios)) {
131359cc4ca5SDavid du Colombier Bprint(&stdout, "couldn't find ATI frequency table\n");
131459cc4ca5SDavid du Colombier return;
131559cc4ca5SDavid du Colombier }
131659cc4ca5SDavid du Colombier
131759cc4ca5SDavid du Colombier Bprint(&stdout, "ATI BIOS rom 0x%x freq 0x%x clock 0x%x\n", romtable, freqtable, clocktable);
131859cc4ca5SDavid du Colombier Bprint(&stdout, "clocks:");
131959cc4ca5SDavid du Colombier for(i=0; i<16; i++)
132059cc4ca5SDavid du Colombier Bprint(&stdout, " %d", *(ushort*)(bios+freqtable+2*i));
132159cc4ca5SDavid du Colombier Bprint(&stdout, "\n");
132259cc4ca5SDavid du Colombier
132359cc4ca5SDavid du Colombier Bprint(&stdout, "programmable clock: %d\n", bios[clocktable]);
132459cc4ca5SDavid du Colombier Bprint(&stdout, "clock to program: %d\n", bios[clocktable+6]);
132559cc4ca5SDavid du Colombier
132659cc4ca5SDavid du Colombier if(*(ushort*)(bios+clocktable+8) != 1430) {
132759cc4ca5SDavid du Colombier Bprint(&stdout, "reference numerator: %d\n", *(ushort*)(bios+clocktable+8)*10);
132859cc4ca5SDavid du Colombier Bprint(&stdout, "reference denominator: 1\n");
132959cc4ca5SDavid du Colombier } else {
133059cc4ca5SDavid du Colombier Bprint(&stdout, "default reference numerator: 157500\n");
133159cc4ca5SDavid du Colombier Bprint(&stdout, "default reference denominator: 11\n");
133259cc4ca5SDavid du Colombier }
133359cc4ca5SDavid du Colombier
133459cc4ca5SDavid du Colombier switch(bios[clocktable]) {
133559cc4ca5SDavid du Colombier case ClockIcs2595:
133659cc4ca5SDavid du Colombier Bprint(&stdout, "ics2595\n");
133759cc4ca5SDavid du Colombier Bprint(&stdout, "reference divider: %d\n", *(ushort*)(bios+clocktable+0x0A));
133859cc4ca5SDavid du Colombier break;
133959cc4ca5SDavid du Colombier case ClockStg1703:
134059cc4ca5SDavid du Colombier Bprint(&stdout, "stg1703\n");
134159cc4ca5SDavid du Colombier break;
134259cc4ca5SDavid du Colombier case ClockCh8398:
134359cc4ca5SDavid du Colombier Bprint(&stdout, "ch8398\n");
134459cc4ca5SDavid du Colombier break;
134559cc4ca5SDavid du Colombier case ClockInternal:
134659cc4ca5SDavid du Colombier Bprint(&stdout, "internal clock\n");
134759cc4ca5SDavid du Colombier Bprint(&stdout, "reference divider in plls\n");
134859cc4ca5SDavid du Colombier break;
134959cc4ca5SDavid du Colombier case ClockAtt20c408:
135059cc4ca5SDavid du Colombier Bprint(&stdout, "att 20c408\n");
135159cc4ca5SDavid du Colombier break;
135259cc4ca5SDavid du Colombier case ClockIbmrgb514:
135359cc4ca5SDavid du Colombier Bprint(&stdout, "ibm rgb514\n");
135459cc4ca5SDavid du Colombier Bprint(&stdout, "clock to program = 7\n");
135559cc4ca5SDavid du Colombier break;
135659cc4ca5SDavid du Colombier default:
135759cc4ca5SDavid du Colombier Bprint(&stdout, "unknown clock\n");
135859cc4ca5SDavid du Colombier break;
135959cc4ca5SDavid du Colombier }
136059cc4ca5SDavid du Colombier
136159cc4ca5SDavid du Colombier USED(mp);
136259cc4ca5SDavid du Colombier if(1 || mp->lcdpanelid) {
136359cc4ca5SDavid du Colombier lcdtable = *(ushort*)(bios+0x78);
136459cc4ca5SDavid du Colombier if(lcdtable+5 > sizeof bios || lcdtable+bios[lcdtable+5] > sizeof bios) {
136559cc4ca5SDavid du Colombier Bprint(&stdout, "can't find lcd bios table\n");
136659cc4ca5SDavid du Colombier goto NoLcd;
136759cc4ca5SDavid du Colombier }
136859cc4ca5SDavid du Colombier
136959cc4ca5SDavid du Colombier lcdpanel = *(ushort*)(bios+lcdtable+0x0A);
137059cc4ca5SDavid du Colombier if(lcdpanel+0x1D > sizeof bios /*|| bios[lcdpanel] != mp->lcdpanelid*/) {
137159cc4ca5SDavid du Colombier Bprint(&stdout, "can't find lcd bios table0\n");
137259cc4ca5SDavid du Colombier goto NoLcd;
137359cc4ca5SDavid du Colombier }
137459cc4ca5SDavid du Colombier
137559cc4ca5SDavid du Colombier Bprint(&stdout, "panelid %d x %d y %d\n", bios[lcdpanel], *(ushort*)(bios+lcdpanel+0x19), *(ushort*)(bios+lcdpanel+0x1B));
137659cc4ca5SDavid du Colombier }
137759cc4ca5SDavid du Colombier NoLcd:;
13787dd7cddfSDavid du Colombier }
13797dd7cddfSDavid du Colombier
13807dd7cddfSDavid du Colombier Ctlr mach64xx = {
13817dd7cddfSDavid du Colombier "mach64xx", /* name */
13827dd7cddfSDavid du Colombier snarf, /* snarf */
13837dd7cddfSDavid du Colombier 0, /* options */
13847dd7cddfSDavid du Colombier init, /* init */
13857dd7cddfSDavid du Colombier load, /* load */
13867dd7cddfSDavid du Colombier dump, /* dump */
13877dd7cddfSDavid du Colombier };
13887dd7cddfSDavid du Colombier
13897dd7cddfSDavid du Colombier Ctlr mach64xxhwgc = {
13907dd7cddfSDavid du Colombier "mach64xxhwgc", /* name */
13917dd7cddfSDavid du Colombier 0, /* snarf */
13927dd7cddfSDavid du Colombier 0, /* options */
13937dd7cddfSDavid du Colombier 0, /* init */
13947dd7cddfSDavid du Colombier 0, /* load */
13957dd7cddfSDavid du Colombier 0, /* dump */
13967dd7cddfSDavid du Colombier };
13977dd7cddfSDavid du Colombier
139859cc4ca5SDavid du Colombier
1399