123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include "pci.h"
- #include "vga.h"
- /*
- * 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) */
- };
- typedef struct {
- ulong configcntl;
- ulong configstat;
- ulong memcntl;
- ulong scratch1;
- } Mach64;
- /*
- * 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 */
- };
- /*
- * ATI18811-0
- */
- static Pclk ati188110[Npclkx] = {
- { 42950000, 0x00, 0x00, 0x00 },
- { 48770000, 0x00, 0x00, 0x04 },
- { 92400000, 0x00, 0x00, 0x08 },
- { 36000000, 0x00, 0x00, 0x0C },
- { 50350000, 0x00, 0x02, 0x00 },
- { 56640000, 0x00, 0x02, 0x04 },
- { 0, 0x00, 0x02, 0x08 },
- { 44900000, 0x00, 0x02, 0x0C },
- { 30240000, 0x10, 0x00, 0x00 },
- { 32000000, 0x10, 0x00, 0x04 },
- { 110000000, 0x10, 0x00, 0x08 },
- { 80000000, 0x10, 0x00, 0x0C },
- { 39910000, 0x10, 0x02, 0x00 },
- { 44900000, 0x10, 0x02, 0x04 },
- { 75000000, 0x10, 0x02, 0x08 },
- { 65000000, 0x10, 0x02, 0x0C },
- };
- /*
- * ATI18811-1, ATI18811-2
- * PCLK_TABLE = 0 in Mach64 speak.
- */
- static Pclk ati188111[Npclkx] = {
- { 100000000, 0x00, 0x00, 0x00 },
- { 126000000, 0x00, 0x00, 0x04 },
- { 92400000, 0x00, 0x00, 0x08 },
- { 36000000, 0x00, 0x00, 0x0C },
- { 50350000, 0x00, 0x02, 0x00 },
- { 56640000, 0x00, 0x02, 0x04 },
- { 0, 0x00, 0x02, 0x08 },
- { 44900000, 0x00, 0x02, 0x0C },
- { 135000000, 0x10, 0x00, 0x00 },
- { 32000000, 0x10, 0x00, 0x04 },
- { 110000000, 0x10, 0x00, 0x08 },
- { 80000000, 0x10, 0x00, 0x0C },
- { 39910000, 0x10, 0x02, 0x00 },
- { 44900000, 0x10, 0x02, 0x04 },
- { 75000000, 0x10, 0x02, 0x08 },
- { 65000000, 0x10, 0x02, 0x0C },
- };
- /*
- * ATI18818
- * The first four entries are programmable and the default
- * settings are either those below or those below divided by 2
- * (PCLK_TABLE = 1 and PCLK_TABLE = 2 respectively in Mach64
- * speak).
- */
- static Pclk ati18818[Npclkx] = {
- { 50350000, 0x00, 0x00, 0x00 },
- { 56640000, 0x00, 0x00, 0x04 },
- { 63000000, 0x00, 0x00, 0x08 },
- { 72000000, 0x00, 0x00, 0x0C },
- { 40000000, 0x00, 0x02, 0x00 },
- { 44900000, 0x00, 0x02, 0x04 },
- { 49500000, 0x00, 0x02, 0x08 },
- { 50000000, 0x00, 0x02, 0x0C },
- { 0, 0x10, 0x00, 0x00 },
- { 110000000, 0x10, 0x00, 0x04 },
- { 126000000, 0x10, 0x00, 0x08 },
- { 135000000, 0x10, 0x00, 0x0C },
- { 0, 0x10, 0x02, 0x00 },
- { 80000000, 0x10, 0x02, 0x04 },
- { 75000000, 0x10, 0x02, 0x08 },
- { 65000000, 0x10, 0x02, 0x0C },
- };
- static Pclk *pclkp; /* which clock chip we are using */
- static ulong atix; /* index to extended regsiters */
- static uchar
- atixi(uchar index)
- {
- outportb(atix, index);
- return inportb(atix+1);
- }
- static void
- atixo(uchar index, uchar data)
- {
- outportw(atix, (data<<8)|index);
- }
- static void
- atixinit(Vga* vga, Ctlr*)
- {
- uchar b;
- /*
- * 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);
- if(vga->private == 0)
- vga->private = alloc(sizeof(Mach64));
- }
- static void
- snarf(Vga* vga, Ctlr* ctlr)
- {
- int i;
- Mach64 *mach64;
- atixinit(vga, ctlr);
- for(i = 0xA0; i < 0xC0; i++)
- vga->crt[i] = atixi(i);
- mach64 = vga->private;
- mach64->configcntl = inportl(Configcntl);
- mach64->configstat = inportl(Configstat);
- mach64->memcntl = inportl(Memcntl);
- mach64->scratch1 = inportl(Scratch1);
- /*
- * Memory size.
- */
- switch(mach64->memcntl & 0x07){
- case 0:
- vga->vmz = 512*1024;
- break;
- case 1:
- vga->vmz = 1024*1024;
- break;
- case 2:
- vga->vmz = 2*1024*1024;
- break;
- case 3:
- vga->vmz = 4*1024*1024;
- break;
- case 4:
- vga->vmz = 6*1024*1024;
- break;
- case 5:
- vga->vmz = 8*1024*1024;
- break;
- }
- ctlr->flag |= Fsnarf;
- }
- static void
- init(Vga* vga, Ctlr* ctlr)
- {
- Mode *mode;
- int f, divisor, index;
- mode = vga->mode;
- /*
- * 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);
- if(vga->f[0] == 0)
- vga->f[0] = vga->mode->frequency;
- /*
- * 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]);
- vga->d[0] = divisor;
- vga->i[0] = index;
- vga->crt[0xB0] &= 0xDA;
- vga->crt[0xB1] &= 0x87;
- vga->crt[0xB5] &= 0x7E;
- vga->crt[0xB6] &= 0xE2;
- vga->crt[0xB3] &= 0xAF;
- vga->crt[0xA6] &= 0xFE;
- vga->crt[0xA7] &= 0xF4;
- /*
- * 256-colour linear addressing.
- */
- if(mode->z == 8){
- vga->graphics[0x05] = 0x00;
- vga->attribute[0x10] &= ~0x40;
- vga->crt[0x13] = (mode->x/8)/2;
- vga->crt[0x14] = 0x00;
- vga->crt[0x17] = 0xE3;
- vga->crt[0xB0] |= 0x20;
- vga->crt[0xB6] |= 0x04;
- }
- vga->attribute[0x11] = 0x00;
- vga->crt[0xB6] |= 0x01;
- vga->crt[0xBE] &= ~0x04;
- /*
- * Do the clock index bits.
- */
- vga->crt[0xB8] &= 0x3F;
- vga->crt[0xB9] &= 0xFD;
- vga->crt[0xBE] &= 0xE5;
- if(vga->d[0] == 2)
- vga->crt[0xB8] |= 0x40;
- vga->crt[0xB9] |= pclkp[vga->i[0]].b9;
- vga->crt[0xBE] |= pclkp[vga->i[0]].be;
- vga->misc |= pclkp[vga->i[0]].genmo;
- if(vga->mode->interlace == 'v')
- vga->crt[0xBE] |= 0x02;
- /*
- * 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);
- ctlr->flag |= Fload;
- }
- static void
- dump(Vga* vga, Ctlr* ctlr)
- {
- int i;
- Mach64 *mach64;
- printitem(ctlr->name, "ATIX");
- for(i = 0xA0; i < 0xC0; i++)
- printreg(vga->crt[i]);
- if((mach64 = vga->private) == 0)
- return;
- printitem(ctlr->name, "CONFIGCNTL");
- Bprint(&stdout, "%.8lux\n", mach64->configcntl);
- printitem(ctlr->name, "CONFIGSTAT");
- Bprint(&stdout, "%.8lux\n", mach64->configstat);
- printitem(ctlr->name, "MEMCNTL");
- Bprint(&stdout, "%.8lux\n", mach64->memcntl);
- printitem(ctlr->name, "SCRATCH1");
- Bprint(&stdout, "%.8lux\n", mach64->scratch1);
- }
- Ctlr mach64 = {
- "mach64", /* name */
- snarf, /* snarf */
- 0, /* options */
- init, /* init */
- load, /* load */
- dump, /* dump */
- };
|