| plan 9 kernel history: overview | file list | diff list |
1999/0911/pc/vgamach64xx.c (diff list | history)
| 1999/0911/sys/src/9/pc/vgamach64xx.c:13,19 – 1999/1005/sys/src/9/pc/vgamach64xx.c:13,19 (short | long | prev | next) | ||
| 1998/0507 | #include "screen.h" /* | |
| 1998/0803 |
| |
| 1999/1005 | * ATI Mach64(CT|ET|G*|VT|VU|LP). | |
| 1998/0507 | */ static ushort mach64xxdid[] = { ('C'<<8)|'T', | |
| 1999/0911/sys/src/9/pc/vgamach64xx.c:25,37 – 1999/1005/sys/src/9/pc/vgamach64xx.c:25,40 | ||
| 1998/0803 | ('G'<<8)|'Q', | |
| 1998/0507 | ('G'<<8)|'T', ('G'<<8)|'U', | |
| 1999/0911 |
| |
| 1999/0909 |
| |
| 1998/0507 | ('V'<<8)|'T', ('V'<<8)|'U', | |
| 1999/1005 | ('L'<<8)|'P', | |
| 1998/0507 | 0, }; | |
| 1999/1005 | static int hwfill(VGAscr*, Rectangle, ulong); static int hwscroll(VGAscr*, Rectangle, Rectangle); static void initengine(VGAscr*); | |
| 1998/0507 | static Pcidev* mach64xxpci(void) { | |
| 1999/0911/sys/src/9/pc/vgamach64xx.c:66,71 – 1999/1005/sys/src/9/pc/vgamach64xx.c:69,75 | ||
| 1998/0508 | * this will do for now. */ scr->io = p->mem[1].bar & ~0x03; | |
| 1999/1005 | ||
| 1998/0508 | if(scr->io == 0 && p->did == ('C'<<8)|'T') scr->io = 0x2EC; } | |
| 1999/0911/sys/src/9/pc/vgamach64xx.c:74,83 – 1999/1005/sys/src/9/pc/vgamach64xx.c:78,89 | ||
| 1998/0507 | static ulong mach64xxlinear(VGAscr* scr, int* size, int* align) { | |
| 1999/1005 | ulong aperture, osize, oaperture; | |
| 1998/0507 | int oapsize, wasupamem; Pcidev *p; | |
| 1999/1005 | Physseg seg; | |
| 1998/0507 | ||
| 1999/1005 | osize = *size; | |
| 1998/0507 | oaperture = scr->aperture; oapsize = scr->apsize; wasupamem = scr->isupamem; | |
| 1999/0911/sys/src/9/pc/vgamach64xx.c:100,126 – 1999/1005/sys/src/9/pc/vgamach64xx.c:106,231 | ||
| 1998/0507 | else scr->isupamem = 1; | |
| 1999/1005 | 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); | |
| 1998/0507 | return aperture; } | |
| 1998/0511 | enum { | |
| 1999/1005 | CrtcOffPitch = 0x05, CrtcGenCtl = 0x07, | |
| 1998/0508 | CurClr0 = 0x0B, /* I/O Select */ CurClr1 = 0x0C, CurOffset = 0x0D, CurHVposn = 0x0E, CurHVoff = 0x0F, | |
| 1999/1005 | BusCntl = 0x13, | |
| 1998/0508 | GenTestCntl = 0x19, | |
| 1999/1005 | 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, | |
| 1998/0507 | }; | |
| 1998/0508 | static uchar mmoffset[] = { | |
| 1999/1005 | [CrtcOffPitch] 0x05, | |
| 1998/0508 | [CurClr0] 0x18, [CurClr1] 0x19, | |
| 1998/0511 | [CurOffset] 0x1A, [CurHVposn] 0x1B, [CurHVoff] 0x1C, | |
| 1998/0508 | ||
| 1999/1005 | [BusCntl] 0x28, | |
| 1998/0508 | [GenTestCntl] 0x34, | |
| 1999/1005 | [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, | |
| 1998/0508 | }; | |
| 1998/0507 | static ulong | |
| 1999/0911/sys/src/9/pc/vgamach64xx.c:128,133 – 1999/1005/sys/src/9/pc/vgamach64xx.c:233,240 | ||
| 1998/0507 | { | |
| 1998/0508 | if(scr->io == 0x2EC || scr->io == 0x1C8) return inl((r<<10)+scr->io); | |
| 1999/1005 | if(r >= 0x100 && scr->mmio != nil) return scr->mmio[mmoffset[r]]; | |
| 1998/0508 | return inl((mmoffset[r]<<2)+scr->io); | |
| 1998/0507 | } | |
| 1999/0911/sys/src/9/pc/vgamach64xx.c:136,141 – 1999/1005/sys/src/9/pc/vgamach64xx.c:243,250 | ||
| 1998/0507 | { | |
| 1998/0508 | if(scr->io == 0x2EC || scr->io == 0x1C8) outl(((r)<<10)+scr->io, l); | |
| 1999/1005 | else if(r >= 0x100 && scr->mmio != nil) scr->mmio[mmoffset[r]] = l; | |
| 1998/0508 | else outl((mmoffset[r]<<2)+scr->io, l); | |
| 1998/0507 | } | |
| 1999/0911/sys/src/9/pc/vgamach64xx.c:208,218 – 1999/1005/sys/src/9/pc/vgamach64xx.c:317,393 | ||
| 1998/0507 | } static int | |
| 1999/1005 | ptalmostinrect(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 int screenpan(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){ d = ((p.y+dy-1)&~(dy-1)) - physr->max.y; physr->min.y += d; physr->max.y += d; } if(p.x < physr->min.x){ d = physr->min.x - (p.x&~(dx-1)); physr->min.x -= d; physr->max.x -= d; } if(p.x > physr->max.x){ d = ((p.x+dx-1)&~(dx-1)) - physr->max.x; physr->min.x += d; physr->max.x += d; } return 1; } static int | |
| 1998/0507 | mach64xxcurmove(VGAscr* scr, Point p) { int x, xo, y, yo; | |
| 1999/1005 | int dx; ulong off, pitch; | |
| 1998/0507 | /* | |
| 1999/1005 | * If the point we want to display is outside the current * screen rectangle, pan the screen to display it. * * We have to move in 64-bit chunks. */ if(scr->gscreen->depth == 24) dx = (64*3)/24; else dx = 64 / scr->gscreen->depth; if(screenpan(p, &physgscreenr, dx, 1)){ off = (physgscreenr.min.y*Dx(scr->gscreen->r)+physgscreenr.min.x)/dx; pitch = Dx(scr->gscreen->r)/8; iow32(scr, CrtcOffPitch, (pitch<<22)|off); } p.x -= physgscreenr.min.x; p.y -= physgscreenr.min.y; /* | |
| 1998/0507 | * Mustn't position the cursor offscreen even partially, * or it disappears. Therefore, if x or y is -ve, adjust the * cursor presets instead. If y is negative also have to | |
| 1999/0911/sys/src/9/pc/vgamach64xx.c:276,281 – 1999/1005/sys/src/9/pc/vgamach64xx.c:451,669 | ||
| 1998/0507 | iow32(scr, GenTestCntl, 0x80|r); } | |
| 1999/1005 | static void waitforfifo(VGAscr *scr, int entries) { int x; x = 0; while((ior32(scr, FifoStat)&0xFF) > (0x8000>>entries) && x++ < 1000000) ; if(x >= 1000000) iprint("fifo %d stat %.8lux %.8lux scrio %.8lux mmio %p scr %p pc %luX\n", entries, ior32(scr, FifoStat), scr->mmio[mmoffset[FifoStat]], scr->io, scr->mmio, scr, getcallerpc(&scr)); } static void waitforidle(VGAscr *scr) { int x; waitforfifo(scr, 16); x = 0; while((ior32(scr, GuiStat)&1) && x++ < 1000000) ; if(x >= 1000000) iprint("idle stat %.8lux %.8lux scrio %.8lux mmio %p scr %p pc %luX\n", ior32(scr, GuiStat), scr->mmio[mmoffset[GuiStat]], scr->io, scr->mmio, scr, getcallerpc(&scr)); } static void resetengine(VGAscr *scr) { ulong x; x = ior32(scr, GenTestCntl); iow32(scr, GenTestCntl, x&~0x100); iow32(scr, GenTestCntl, x|0x100); iow32(scr, BusCntl, ior32(scr, BusCntl)|0x00A00000); } static void initengine(VGAscr *scr) { ulong pitch; pitch = Dx(scr->gscreen->r)/8; if(scr->gscreen->depth == 24) pitch *= 3; resetengine(scr); waitforfifo(scr, 14); iow32(scr, ContextMask, ~0); iow32(scr, DstOffPitch, pitch<<22); iow32(scr, DstYX, 0); iow32(scr, DstHeight, 0); iow32(scr, DstBresErr, 0); iow32(scr, DstBresInc, 0); iow32(scr, DstBresDec, 0); iow32(scr, DstCntl, 0x23); iow32(scr, SrcOffPitch, pitch<<22); iow32(scr, SrcYX, 0); iow32(scr, SrcHeight1Width1, 1); iow32(scr, SrcYXstart, 0); iow32(scr, SrcHeight2Width2, 1); iow32(scr, SrcCntl, 0x01); waitforfifo(scr, 13); iow32(scr, HostCntl, 0); iow32(scr, PatReg0, 0); iow32(scr, PatReg1, 0); iow32(scr, PatCntl, 0); iow32(scr, ScLeft, 0); iow32(scr, ScTop, 0); iow32(scr, ScBottom, 0xFFFF); iow32(scr, ScRight, 0xFFFF); iow32(scr, DpBkgdClr, 0); iow32(scr, DpFrgdClr, ~0); iow32(scr, DpWriteMask, ~0); iow32(scr, DpMix, 0x70003); iow32(scr, DpSrc, 0x00010100); waitforfifo(scr, 3); iow32(scr, ClrCmpClr, 0); iow32(scr, ClrCmpMask, ~0); iow32(scr, ClrCmpCntl, 0); waitforfifo(scr, 2); switch(scr->gscreen->depth){ case 8: case 24: /* [sic] */ iow32(scr, DpPixWidth, 0x00020202); iow32(scr, DpChainMask, 0x8080); break; case 16: iow32(scr, DpPixWidth, 0x00040404); iow32(scr, DpChainMask, 0x8410); break; case 32: iow32(scr, DpPixWidth, 0x00060606); iow32(scr, DpChainMask, 0x8080); break; } waitforidle(scr); } static int mach64hwfill(VGAscr *scr, Rectangle r, ulong sval) { ulong pitch; ulong ctl; if(drawdebug) iprint("hwfill %R val %lux...\n", r, sval); /* shouldn't happen */ if(scr->io == 0x2EC || scr->io == 0x1C8 || scr->io == 0) return 0; pitch = Dx(scr->gscreen->r)/8; ctl = 1|2; /* left-to-right, top-to-bottom */ if(scr->gscreen->depth == 24){ r.min.x *= 3; r.max.x *= 3; pitch *= 3; ctl |= (1<<7)|(((r.min.x/4)%6)<<8); } waitforfifo(scr, 11); iow32(scr, DpFrgdClr, sval); iow32(scr, DpWriteMask, 0xFFFFFFFF); iow32(scr, DpMix, 0x00070003); iow32(scr, DpSrc, 0x00000111); iow32(scr, ClrCmpCntl, 0x00000000); iow32(scr, ScLeftRight, 0x1FFF0000); iow32(scr, ScTopBottom, 0x1FFF0000); iow32(scr, DstOffPitch, pitch<<22); iow32(scr, DstCntl, ctl); iow32(scr, DstYX, (r.min.x<<16)|r.min.y); iow32(scr, DstHeightWidth, (Dx(r)<<16)|Dy(r)); waitforidle(scr); return 1; } static int mach64hwscroll(VGAscr *scr, Rectangle r, Rectangle sr) { ulong pitch; Point dp, sp; ulong ctl; int dx, dy; dx = Dx(r); dy = Dy(r); pitch = Dx(scr->gscreen->r)/8; if(scr->gscreen->depth == 24){ dx *= 3; pitch *= 3; r.min.x *= 3; sr.min.x *= 3; } ctl = 0; if(r.min.x <= sr.min.x){ ctl |= 1; dp.x = r.min.x; sp.x = sr.min.x; }else{ dp.x = r.min.x+dx-1; sp.x = sr.min.x+dx-1; } if(r.min.y <= sr.min.y){ ctl |= 2; dp.y = r.min.y; sp.y = sr.min.y; }else{ dp.y = r.min.y+dy-1; sp.y = sr.min.y+dy-1; } if(scr->gscreen->depth == 24) ctl |= (1<<7)|(((dp.x/4)%6)<<8); waitforfifo(scr, 6); iow32(scr, ScLeftRight, 0x1FFF0000); iow32(scr, ScTopBottom, 0x1FFF0000); iow32(scr, DpWriteMask, 0xFFFFFFFF); iow32(scr, DpMix, 0x00070003); iow32(scr, DpSrc, 0x00000300); iow32(scr, ClrCmpCntl, 0x00000000); waitforfifo(scr, 8); iow32(scr, SrcOffPitch, pitch<<22); iow32(scr, SrcCntl, 0x00000000); iow32(scr, SrcYX, (sp.x<<16)|sp.y); iow32(scr, SrcWidth1, dx); iow32(scr, DstOffPitch, pitch<<22); iow32(scr, DstCntl, ctl); iow32(scr, DstYX, (dp.x<<16)|dp.y); iow32(scr, DstHeightWidth, (dx<<16)|dy); waitforidle(scr); return 1; } static void mach64xxdrawinit(VGAscr *scr) { if(scr->io > 0x2FF){ initengine(scr); scr->fill = mach64hwfill; scr->scroll = mach64hwscroll; } } | |
| 1998/0507 | VGAdev vgamach64xxdev = { "mach64xx", | |
| 1999/0911/sys/src/9/pc/vgamach64xx.c:283,288 – 1999/1005/sys/src/9/pc/vgamach64xx.c:671,677 | ||
| 1998/0507 | 0, /* disable */ 0, /* page */ mach64xxlinear, /* linear */ | |
| 1999/1005 | mach64xxdrawinit, /* drawinit */ | |
| 1998/0507 | }; VGAcur vgamach64xxcur = { | |
| 1999/0911/sys/src/9/pc/vgamach64xx.c:292,295 – 1999/1005/sys/src/9/pc/vgamach64xx.c:681,686 | ||
| 1998/0507 | mach64xxcurdisable, /* disable */ mach64xxcurload, /* load */ mach64xxcurmove, /* move */ | |
| 1999/1005 | 1 /* doespanning */ | |
| 1998/0507 | }; | |