2 #include "../port/lib.h"
7 #include "../port/error.h"
16 PCIS3 = 0x5333, /* PCI VID */
18 SAVAGE3D = 0x8A20, /* PCI DID */
28 SUPERSAVAGEIXC16 = 0x8C2E,
38 VIRTUALPC2004 = 0x8810,
39 AURORA64VPLUS = 0x8812,
43 s3pageset(VGAscr* scr, int page)
48 crt35 = vgaxi(Crtx, 0x35);
49 if(scr->gscreen->depth >= 8){
51 * The S3 registers need to be unlocked for this.
52 * Let's hope they are already:
53 * vgaxo(Crtx, 0x38, 0x48);
54 * vgaxo(Crtx, 0x39, 0xA0);
56 * The page is 6 bits, the lower 4 bits in Crt35<3:0>,
57 * the upper 2 in Crt51<3:2>.
59 vgaxo(Crtx, 0x35, page & 0x0F);
60 crt51 = vgaxi(Crtx, 0x51);
61 vgaxo(Crtx, 0x51, (crt51 & ~0x0C)|((page & 0x30)>>2));
62 opage = ((crt51 & 0x0C)<<2)|(crt35 & 0x0F);
65 vgaxo(Crtx, 0x35, (page<<2) & 0x0C);
66 opage = (crt35>>2) & 0x03;
73 s3page(VGAscr* scr, int page)
77 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
86 unlock(&scr->devlock);
92 s3linear(VGAscr* scr, int, int)
95 ulong mmiobase, mmiosize;
98 vgalinearpciid(scr, PCIS3, 0);
100 if(scr->paddr == 0 || p == nil)
103 addvgaseg("s3screen", scr->paddr, scr->apsize);
105 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
106 switch(id){ /* find mmio */
111 case SUPERSAVAGEIXC16:
113 * We could assume that the MMIO registers
114 * will be in the screen segment and just use
115 * that, but PCI software is allowed to move them
116 * if it feels like it, so we look for an aperture of
117 * the right size; only the first 512k actually means
118 * anything. The S3 engineers overestimated how
119 * much space they would need in the first design.
121 for(j=0; j<nelem(p->mem); j++){
122 if((p->mem[j].bar&~0x0F) != scr->paddr)
123 if(p->mem[j].size==512*1024 || p->mem[j].size==16*1024*1024){
124 mmiobase = p->mem[j].bar & ~0x0F;
126 scr->mmio = vmap(mmiobase, mmiosize);
129 addvgaseg("savagemmio", mmiobase, mmiosize);
140 * Hardware cursor information is fetched from display memory
141 * during the horizontal blank active time. The 80x chips may hang
142 * if the cursor is turned on or off during this period.
144 while((vgai(Status1) & 0x08) == 0)
156 crt45 = vgaxi(Crtx, 0x45) & 0xFE;
158 vgaxo(Crtx, 0x45, crt45);
162 s3load(VGAscr* scr, Cursor* curs)
165 int id, dolock, opage, x, y;
168 * Disable the cursor and
169 * set the pointer to the two planes.
175 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
189 case SUPERSAVAGEIXC16:
197 opage = s3pageset(scr, scr->storage>>16);
198 p += (scr->storage & 0xFFFF);
203 * The cursor is set in Microsoft Windows format (the ViRGE/GX2 doesn't
204 * support the X11 format) which gives the following truth table:
206 * 0 0 background colour
207 * 0 1 foreground colour
208 * 1 0 current screen pixel
209 * 1 1 NOT current screen pixel
210 * Put the cursor into the top-left of the 64x64 array.
212 * The cursor pattern in memory is interleaved words of
213 * AND and XOR patterns.
215 for(y = 0; y < 64; y++){
216 for(x = 0; x < 64/8; x += 2){
217 if(x < 16/8 && y < 16){
218 *p++ = ~(curs->clr[2*y + x]|curs->set[2*y + x]);
219 *p++ = ~(curs->clr[2*y + x+1]|curs->set[2*y + x+1]);
220 *p++ = curs->set[2*y + x];
221 *p++ = curs->set[2*y + x+1];
233 s3pageset(scr, opage);
234 unlock(&scr->devlock);
238 * Save the cursor hotpoint and enable the cursor.
240 scr->offset = curs->offset;
242 vgaxo(Crtx, 0x45, 0x01);
246 s3move(VGAscr* scr, Point p)
251 * Mustn't position the cursor offscreen even partially,
252 * or it disappears. Therefore, if x or y is -ve, adjust the
253 * cursor offset instead.
254 * There seems to be a bug in that if the offset is 1, the
255 * cursor doesn't disappear off the left edge properly, so
256 * round it up to be even.
258 if((x = p.x+scr->offset.x) < 0){
265 if((y = p.y+scr->offset.y) < 0){
272 vgaxo(Crtx, 0x46, (x>>8) & 0x07);
273 vgaxo(Crtx, 0x47, x & 0xFF);
274 vgaxo(Crtx, 0x49, y & 0xFF);
275 vgaxo(Crtx, 0x4E, xo);
276 vgaxo(Crtx, 0x4F, yo);
277 vgaxo(Crtx, 0x48, (y>>8) & 0x07);
283 s3enable(VGAscr* scr)
291 * Cursor colours. Set both the CR0[EF] and the colour
292 * stack in case we are using a 16-bit RAMDAC.
294 vgaxo(Crtx, 0x0E, Pwhite);
295 vgaxo(Crtx, 0x0F, Pblack);
298 for(i = 0; i < 3; i++)
299 vgaxo(Crtx, 0x4A, Pblack);
301 for(i = 0; i < 3; i++)
302 vgaxo(Crtx, 0x4B, Pwhite);
305 * Find a place for the cursor data in display memory.
306 * Must be on a 1024-byte boundary.
308 storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024;
309 vgaxo(Crtx, 0x4C, storage>>8);
310 vgaxo(Crtx, 0x4D, storage & 0xFF);
312 scr->storage = storage;
315 * Load, locate and enable the cursor
316 * in Microsoft Windows format.
320 vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10);
322 vgaxo(Crtx, 0x45, 0x01);
326 * The manual gives byte offsets, but we want ulong offsets, hence /4.
333 WidthHeight = 0xA504/4,
342 * Wait for writes to VGA memory via linear aperture to flush.
344 enum {Maxloop = 1<<24};
355 waitforlinearfifo(VGAscr *scr)
359 static ulong nwaitforlinearfifo;
364 panic("unknown scr->id in s3 waitforlinearfifo");
365 case 0x8A01: /* ViRGE/[DG]X. XFree86 says no waiting necessary */
367 case 0x5631: /* ViRGE */
368 case 0x883D: /* ViRGE/VX */
372 case 0x8A10: /* ViRGE/GX2 */
379 while((mmio[FifoStat]&mask) != val && x++ < Maxloop)
382 waitcount.lineartimeout++;
386 waitforfifo(VGAscr *scr, int entries)
390 static ulong nwaitforfifo;
394 while((mmio[SubStat]&0x1F00) < ((entries+2)<<8) && x++ < Maxloop)
397 waitcount.fifotimeout++;
401 waitforidle(VGAscr *scr)
408 while((mmio[SubStat]&0x3F00) != 0x3000 && x++ < Maxloop)
411 waitcount.idletimeout++;
415 hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
417 enum { Bitbltop = 0xCC }; /* copy source */
423 d = scr->gscreen->depth;
425 cmd = 0x00000020|(Bitbltop<<17)|(did<<2);
426 stride = Dx(scr->gscreen->r)*d/8;
428 if(r.min.x <= sr.min.x){
437 if(r.min.y <= sr.min.y){
447 waitforlinearfifo(scr);
449 mmio[SrcBase] = scr->paddr;
450 mmio[DstBase] = scr->paddr;
451 mmio[Stride] = (stride<<16)|stride;
452 mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
453 mmio[SrcXY] = (sp.x<<16)|sp.y;
454 mmio[DestXY] = (dp.x<<16)|dp.y;
461 hwfill(VGAscr *scr, Rectangle r, ulong sval)
463 enum { Bitbltop = 0xCC }; /* copy source */
468 d = scr->gscreen->depth;
470 cmd = 0x16000120|(Bitbltop<<17)|(did<<2);
471 stride = Dx(scr->gscreen->r)*d/8;
473 waitforlinearfifo(scr);
475 mmio[SrcBase] = scr->paddr;
476 mmio[DstBase] = scr->paddr;
477 mmio[DstBase] = scr->paddr;
478 mmio[Stride] = (stride<<16)|stride;
479 mmio[FgrdData] = sval;
480 mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
481 mmio[DestXY] = (r.min.x<<16)|r.min.y;
488 CursorSyncCtl = 0x0D, /* in Seqx */
496 s3blank(VGAscr*, int blank)
500 x = vgaxi(Seqx, CursorSyncCtl);
503 x |= VsyncLo | HsyncLo;
504 vgaxo(Seqx, CursorSyncCtl, x);
508 s3drawinit(VGAscr *scr)
510 extern void savageinit(VGAscr*); /* vgasavage.c */
513 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
517 * It's highly likely that other ViRGEs will work without
518 * change to the driver, with the exception of the size of
519 * the linear aperture memory write FIFO. Since we don't
520 * know that size, I'm not turning them on. See waitforlinearfifo
523 scr->blank = s3blank;
524 /* hwblank = 1; not known to work well */
530 scr->mmio = (ulong*)((char*)scr->vaddr+0x1000000);
532 scr->scroll = hwscroll;
536 scr->mmio = (ulong*)((char*)scr->vaddr+0x1000000);
539 case SUPERSAVAGEIXC16:
544 /* scr->mmio is set by s3linear */