/*
* ATI Mach64. Some hope. Kind of like a Mach32.
* No support for accelerator so can only do up to 1024x768.
*
* All ATI Extended Registers are addressed using the modified index
* index = (0x02<<6)|(index & 0x3F);
* so registers 0x00->0x3F map to 0x80->0xBF, but we will only ever
* look at a few in the range 0xA0->0xBF. In this way we can stash
* them in the vga->crt[] array.
*/
enum {
Configcntl = 0x6AEC, /* Configuration control */
Configstat = 0x72EC, /* Configuration status */
Memcntl = 0x52EC, /* Memory control */
Scratch1 = 0x46EC, /* Scratch Register (BIOS info) */
};
/*
* There are a number of possible clock generator chips for these
* boards. We can divide any frequency by 2 (bit<6> of b8).
*/
typedef struct {
ulong frequency;
uchar be; /* <4> - bit<3> of frequency index */
uchar b9; /* <1> - bit<2> of frequency index */
uchar genmo; /* <3:2> - bits <1:0> of frequency index */
} Pclk;
enum {
Npclkx = 16, /* number of clock entries per table */
};
/*
* Set the I/O address and offset for the ATI
* extended registers to something we know about.
*/
if(atix == 0){
outportw(Grx, (0xCE<<8)|0x50);
outportw(Grx, (0x81<<8)|0x51);
atix = 0x1CE;
}
/*
* Unlock the ATI Extended Registers.
* We leave them unlocked from now on.
* Why does this chip have so many
* lock bits?
*/
if((b = atixi(0xB8)) & 0x3F)
atixo(0xB8, b & 0xC0);
b = atixi(0xAB);
atixo(0xAB, b & ~0x18);
atixo(0xB4, 0x00);
b = atixi(0xB9);
atixo(0xB9, b & ~0x80);
b = atixi(0xBE);
atixo(0xBE, b|0x09);
/*
* Must somehow determine which clock chip to use here.
* For now, punt and assume ATI18818.
*/
pclkp = ati18818;
if(pclkp == 0)
error("%s: can't determine clock chip\n", ctlr->name);
/*
* Find a clock frequency close to what we want.
* 'Close' is within 1MHz.
*/
for(divisor = 0, index = 0; index < Npclkx; index++, divisor = 0){
divisor = 1;
f = pclkp[index].frequency/divisor;
if(f < vga->f[0]+1000000 && f >= vga->f[0]-1000000)
break;
divisor = 2;
f /= divisor;
if(f < vga->f[0]+1000000 && f >= vga->f[0]-1000000)
break;
}
if(divisor == 0)
error("%s: no suitable clock for %lud\n",
ctlr->name, vga->f[0]);
/*
* Turn off 128Kb CPU address bit so
* we only have a 64Kb aperture at 0xA0000.
*/
vga->crt[0xBD] &= ~0x04;
ctlr->type = mach32.name;
/*
* The Mach64 can only address 1Mb in VGA mode
*/
vga->vmz = 1*1024*1024;
ctlr->flag |= Finit;
}
static void
load(Vga* vga, Ctlr* ctlr)
{
/*
* We should probably do something here to make sure we that we
* have access to all the video memory through the 64Kb VGA aperture
* by disabling and linear aperture and memory boundary and then
* enabling the VGA controller.
* But for now, let's just assume it's ok, the Mach64 documentation
* is just as clear as the Mach32 documentation.
*/
atixo(0xB0, vga->crt[0xB0]);
atixo(0xB1, vga->crt[0xB1]);
atixo(0xB5, vga->crt[0xB5]);
atixo(0xB6, vga->crt[0xB6]);
atixo(0xB3, vga->crt[0xB3]);
atixo(0xA6, vga->crt[0xA6]);
atixo(0xA7, vga->crt[0xA7]);
atixo(0xB8, vga->crt[0xB8]);
atixo(0xB9, vga->crt[0xB9]);
atixo(0xBE, vga->crt[0xBE]);
vgao(MiscW, vga->misc);