📄 vgamach64xx.c
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "../port/error.h"#define Image IMAGE#include <draw.h>#include <memdraw.h>#include <cursor.h>#include "screen.h"/* * ATI Mach64(CT|ET|G*|VT|VU|LP). */static ushort mach64xxdid[] = { ('C'<<8)|'T', ('E'<<8)|'T', ('G'<<8)|'B', ('G'<<8)|'D', ('G'<<8)|'I', ('G'<<8)|'P', ('G'<<8)|'Q', ('G'<<8)|'T', ('G'<<8)|'U', ('G'<<8)|'V', ('G'<<8)|'Z', ('V'<<8)|'T', ('V'<<8)|'U', ('L'<<8)|'I', ('L'<<8)|'M', ('L'<<8)|'P', 0,};static int hwfill(VGAscr*, Rectangle, ulong);static int hwscroll(VGAscr*, Rectangle, Rectangle);static void initengine(VGAscr*);static Pcidev*mach64xxpci(void){ Pcidev *p; ushort *did; if((p = pcimatch(nil, 0x1002, 0)) == nil) return nil; for(did = mach64xxdid; *did; did++){ if(*did == p->did) return p; } return nil;}static voidmach64xxenable(VGAscr* scr){ Pcidev *p; /* * Only once, can't be disabled for now. */ if(scr->io) return; if(p = mach64xxpci()){ scr->id = p->did; /* * The CT doesn't always have the I/O base address * in the PCI base registers. There is a way to find * it via the vendor-specific PCI config space but * this will do for now. */ scr->io = p->mem[1].bar & ~0x03; if(scr->io == 0 && p->did == ('C'<<8)|'T') scr->io = 0x2EC; }}static ulongmach64xxlinear(VGAscr* scr, int* size, int* align){ ulong aperture, osize, oaperture; int oapsize, wasupamem; Pcidev *p; Physseg seg; osize = *size; oaperture = scr->aperture; oapsize = scr->apsize; wasupamem = scr->isupamem; if(wasupamem) upafree(oaperture, oapsize); scr->isupamem = 0; if(p = mach64xxpci()){ aperture = p->mem[0].bar & ~0x0F; *size = p->mem[0].size; } else aperture = 0; aperture = upamalloc(aperture, *size, *align); if(aperture == 0){ if(wasupamem && upamalloc(oaperture, oapsize, 0)) scr->isupamem = 1; } else scr->isupamem = 1; scr->mmio = (ulong*)(aperture+osize-0x400); if(oaperture) print("warning (BUG): redefinition of aperture does not change mach64mmio segment\n"); memset(&seg, 0, sizeof(seg)); seg.attr = SG_PHYSICAL; seg.name = smalloc(NAMELEN); snprint(seg.name, NAMELEN, "mach64mmio"); seg.pa = aperture+osize - BY2PG; seg.size = BY2PG; addphysseg(&seg); seg.name = smalloc(NAMELEN); snprint(seg.name, NAMELEN, "mach64screen"); seg.pa = aperture; seg.size = osize; addphysseg(&seg); return aperture;}enum { CrtcOffPitch = 0x05, CrtcGenCtl = 0x07, CurClr0 = 0x0B, /* I/O Select */ CurClr1 = 0x0C, CurOffset = 0x0D, CurHVposn = 0x0E, CurHVoff = 0x0F, BusCntl = 0x13, GenTestCntl = 0x19, CrtcHsyncDis = 0x04, CrtcVsyncDis = 0x08, ContextMask = 0x100, /* not accessible via I/O */ FifoStat, GuiStat, DpFrgdClr, DpBkgdClr, DpWriteMask, DpMix, DpPixWidth, DpSrc, ClrCmpCntl, GuiTrajCntl, ScLeftRight, ScTopBottom, DstOffPitch, DstYX, DstHeightWidth, DstCntl, DstHeight, DstBresErr, DstBresInc, DstBresDec, SrcCntl, SrcHeight1Width1, SrcHeight2Width2, SrcYX, SrcWidth1, SrcYXstart, HostCntl, PatReg0, PatReg1, PatCntl, ScBottom, ScLeft, ScRight, ScTop, ClrCmpClr, ClrCmpMask, DpChainMask, SrcOffPitch, LcdIndex, LcdData,};enum { LCD_ConfigPanel = 0, LCD_GenCtrl, LCD_DstnCntl, LCD_HfbPitchAddr, LCD_HorzStretch, LCD_VertStretch, LCD_ExtVertStretch, LCD_LtGio, LCD_PowerMngmnt, LCD_ZvgPio, Nlcd,};static uchar mmoffset[] = { [CrtcOffPitch] 0x05, [CurClr0] 0x18, [CurClr1] 0x19, [CurOffset] 0x1A, [CurHVposn] 0x1B, [CurHVoff] 0x1C, [BusCntl] 0x28, [LcdIndex] 0x29, [LcdData] 0x2A, [GenTestCntl] 0x34, [DstOffPitch] 0x40, [DstYX] 0x43, [DstHeight] 0x45, [DstHeightWidth] 0x46, [DstBresErr] 0x49, [DstBresInc] 0x4A, [DstBresDec] 0x4B, [DstCntl] 0x4C, [SrcOffPitch] 0x60, [SrcYX] 0x63, [SrcWidth1] 0x64, [SrcYXstart] 0x69, [SrcHeight1Width1] 0x66, [SrcHeight2Width2] 0x6C, [SrcCntl] 0x6D, [HostCntl] 0x90, [PatReg0] 0xA0, [PatReg1] 0xA1, [PatCntl] 0xA2, [ScLeft] 0xA8, [ScRight] 0xA9, [ScLeftRight] 0xAA, [ScTop] 0xAB, [ScBottom] 0xAC, [ScTopBottom] 0xAD, [DpBkgdClr] 0xB0, [DpFrgdClr] 0xB1, [DpWriteMask] 0xB2, [DpChainMask] 0xB3, [DpPixWidth] 0xB4, [DpMix] 0xB5, [DpSrc] 0xB6, [ClrCmpClr] 0xC0, [ClrCmpMask] 0xC1, [ClrCmpCntl] 0xC2, [FifoStat] 0xC4, [ContextMask] 0xC8, [GuiTrajCntl] 0xCC, [GuiStat] 0xCE,};static ulongior32(VGAscr* scr, int r){ if(scr->io == 0x2EC || scr->io == 0x1C8) return inl((r<<10)+scr->io); if(r >= 0x100 && scr->mmio != nil) return scr->mmio[mmoffset[r]]; return inl((mmoffset[r]<<2)+scr->io);}static voidiow32(VGAscr* scr, int r, ulong l){ if(scr->io == 0x2EC || scr->io == 0x1C8) outl(((r)<<10)+scr->io, l); else if(r >= 0x100 && scr->mmio != nil) scr->mmio[mmoffset[r]] = l; else outl((mmoffset[r]<<2)+scr->io, l);}static ulonglcdr32(VGAscr *scr, ulong r){ ulong or; or = ior32(scr, LcdIndex); iow32(scr, LcdIndex, (or&~0x0F) | (r&0x0F)); return ior32(scr, LcdData);}static voidlcdw32(VGAscr *scr, ulong r, ulong v){ ulong or; or = ior32(scr, LcdIndex); iow32(scr, LcdIndex, (or&~0x0F) | (r&0x0F)); iow32(scr, LcdData, v);}static voidmach64xxcurdisable(VGAscr* scr){ ulong r; r = ior32(scr, GenTestCntl); iow32(scr, GenTestCntl, r & ~0x80);}static voidmach64xxcurload(VGAscr* scr, Cursor* curs){ uchar *p; int i, y; ulong c, s, m, r; /* * Disable the cursor. */ r = ior32(scr, GenTestCntl); iow32(scr, GenTestCntl, r & ~0x80); p = KADDR(scr->aperture); p += scr->storage; /* * Initialise the 64x64 cursor RAM array. * The cursor mode gives the following truth table: * p1 p0 colour * 0 0 Cursor Colour 0 * 0 1 Cursor Colour 1 * 1 0 Transparent * 1 1 Complement * Put the cursor into the top-right of the 64x64 array. */ for(y = 0; y < 16; y++){ for(i = 0; i < (64-16)/8; i++){ *p++ = 0xAA; *p++ = 0xAA; } c = (curs->clr[2*y]<<8)|curs->clr[y*2 + 1]; s = (curs->set[2*y]<<8)|curs->set[y*2 + 1]; m = 0x00000000; for(i = 0; i < 16; i++){ if(s & (1<<(15-i))) m |= 0x01<<(2*i); else if(c & (1<<(15-i))) ; else m |= 0x02<<(2*i); } *p++ = m; *p++ = m>>8; *p++ = m>>16; *p++ = m>>24; } memset(p, 0xAA, (64-16)*16); /* * Set the cursor hotpoint and enable the cursor. */ scr->offset = curs->offset; iow32(scr, GenTestCntl, 0x80|r);}static intptalmostinrect(Point p, Rectangle r){ return p.x>=r.min.x && p.x<=r.max.x && p.y>=r.min.y && p.y<=r.max.y;}/* * If necessary, translate the rectangle physr * some multiple of [dx dy] so that it includes p. * Return 1 if the rectangle changed. */static intscreenpan(Point p, Rectangle *physr, int dx, int dy){ int d; if(ptalmostinrect(p, *physr)) return 0; if(p.y < physr->min.y){ d = physr->min.y - (p.y&~(dy-1)); physr->min.y -= d; physr->max.y -= d; } if(p.y > physr->max.y){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -