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;
104 addvgaseg("s3screen", scr->paddr, scr->apsize);
106 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
107 switch(id){ /* find mmio */
112 case SUPERSAVAGEIXC16:
114 * We could assume that the MMIO registers
115 * will be in the screen segment and just use
116 * that, but PCI software is allowed to move them
117 * if it feels like it, so we look for an aperture of
118 * the right size; only the first 512k actually means
119 * anything. The S3 engineers overestimated how
120 * much space they would need in the first design.
122 for(j=0; j<nelem(p->mem); j++){
123 if((p->mem[j].bar&1) == 0)
124 if((p->mem[j].bar&~0x0F) != scr->paddr)
125 if(p->mem[j].size==512*1024 || p->mem[j].size==16*1024*1024){
126 mmiobase = p->mem[j].bar & ~0x0F;
128 scr->mmio = vmap(mmiobase, mmiosize);
131 addvgaseg("savagemmio", mmiobase, mmiosize);
142 * Hardware cursor information is fetched from display memory
143 * during the horizontal blank active time. The 80x chips may hang
144 * if the cursor is turned on or off during this period.
146 while((vgai(Status1) & 0x08) == 0)
158 crt45 = vgaxi(Crtx, 0x45) & 0xFE;
160 vgaxo(Crtx, 0x45, crt45);
164 s3load(VGAscr* scr, Cursor* curs)
167 int id, dolock, opage, x, y;
170 * Disable the cursor and
171 * set the pointer to the two planes.
177 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
191 case SUPERSAVAGEIXC16:
199 opage = s3pageset(scr, scr->storage>>16);
200 p += (scr->storage & 0xFFFF);
205 * The cursor is set in Microsoft Windows format (the ViRGE/GX2 doesn't
206 * support the X11 format) which gives the following truth table:
208 * 0 0 background colour
209 * 0 1 foreground colour
210 * 1 0 current screen pixel
211 * 1 1 NOT current screen pixel
212 * Put the cursor into the top-left of the 64x64 array.
214 * The cursor pattern in memory is interleaved words of
215 * AND and XOR patterns.
217 for(y = 0; y < 64; y++){
218 for(x = 0; x < 64/8; x += 2){
219 if(x < 16/8 && y < 16){
220 *p++ = ~(curs->clr[2*y + x]|curs->set[2*y + x]);
221 *p++ = ~(curs->clr[2*y + x+1]|curs->set[2*y + x+1]);
222 *p++ = curs->set[2*y + x];
223 *p++ = curs->set[2*y + x+1];
235 s3pageset(scr, opage);
236 unlock(&scr->devlock);
240 * Save the cursor hotpoint and enable the cursor.
242 scr->offset = curs->offset;
244 vgaxo(Crtx, 0x45, 0x01);
248 s3move(VGAscr* scr, Point p)
253 * Mustn't position the cursor offscreen even partially,
254 * or it disappears. Therefore, if x or y is -ve, adjust the
255 * cursor offset instead.
256 * There seems to be a bug in that if the offset is 1, the
257 * cursor doesn't disappear off the left edge properly, so
258 * round it up to be even.
260 if((x = p.x+scr->offset.x) < 0){
267 if((y = p.y+scr->offset.y) < 0){
274 vgaxo(Crtx, 0x46, (x>>8) & 0x07);
275 vgaxo(Crtx, 0x47, x & 0xFF);
276 vgaxo(Crtx, 0x49, y & 0xFF);
277 vgaxo(Crtx, 0x4E, xo);
278 vgaxo(Crtx, 0x4F, yo);
279 vgaxo(Crtx, 0x48, (y>>8) & 0x07);
285 s3enable(VGAscr* scr)
293 * Cursor colours. Set both the CR0[EF] and the colour
294 * stack in case we are using a 16-bit RAMDAC.
296 vgaxo(Crtx, 0x0E, Pwhite);
297 vgaxo(Crtx, 0x0F, Pblack);
300 for(i = 0; i < 3; i++)
301 vgaxo(Crtx, 0x4A, Pblack);
303 for(i = 0; i < 3; i++)
304 vgaxo(Crtx, 0x4B, Pwhite);
307 * Find a place for the cursor data in display memory.
308 * Must be on a 1024-byte boundary.
310 storage = (scr->gscreen->width*sizeof(ulong)*scr->gscreen->r.max.y+1023)/1024;
311 vgaxo(Crtx, 0x4C, storage>>8);
312 vgaxo(Crtx, 0x4D, storage & 0xFF);
314 scr->storage = storage;
317 * Load, locate and enable the cursor
318 * in Microsoft Windows format.
322 vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10);
324 vgaxo(Crtx, 0x45, 0x01);
328 * The manual gives byte offsets, but we want ulong offsets, hence /4.
335 WidthHeight = 0xA504/4,
344 * Wait for writes to VGA memory via linear aperture to flush.
346 enum {Maxloop = 1<<24};
357 waitforlinearfifo(VGAscr *scr)
361 static ulong nwaitforlinearfifo;
366 panic("unknown scr->id in s3 waitforlinearfifo");
367 case 0x8A01: /* ViRGE/[DG]X. XFree86 says no waiting necessary */
369 case 0x5631: /* ViRGE */
370 case 0x883D: /* ViRGE/VX */
374 case 0x8A10: /* ViRGE/GX2 */
381 while((mmio[FifoStat]&mask) != val && x++ < Maxloop)
384 waitcount.lineartimeout++;
388 waitforfifo(VGAscr *scr, int entries)
392 static ulong nwaitforfifo;
396 while((mmio[SubStat]&0x1F00) < ((entries+2)<<8) && x++ < Maxloop)
399 waitcount.fifotimeout++;
403 waitforidle(VGAscr *scr)
410 while((mmio[SubStat]&0x3F00) != 0x3000 && x++ < Maxloop)
413 waitcount.idletimeout++;
417 hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
419 enum { Bitbltop = 0xCC }; /* copy source */
425 d = scr->gscreen->depth;
427 cmd = 0x00000020|(Bitbltop<<17)|(did<<2);
428 stride = Dx(scr->gscreen->r)*d/8;
430 if(r.min.x <= sr.min.x){
439 if(r.min.y <= sr.min.y){
449 waitforlinearfifo(scr);
451 mmio[SrcBase] = scr->paddr;
452 mmio[DstBase] = scr->paddr;
453 mmio[Stride] = (stride<<16)|stride;
454 mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
455 mmio[SrcXY] = (sp.x<<16)|sp.y;
456 mmio[DestXY] = (dp.x<<16)|dp.y;
463 hwfill(VGAscr *scr, Rectangle r, ulong sval)
465 enum { Bitbltop = 0xCC }; /* copy source */
470 d = scr->gscreen->depth;
472 cmd = 0x16000120|(Bitbltop<<17)|(did<<2);
473 stride = Dx(scr->gscreen->r)*d/8;
475 waitforlinearfifo(scr);
477 mmio[SrcBase] = scr->paddr;
478 mmio[DstBase] = scr->paddr;
479 mmio[DstBase] = scr->paddr;
480 mmio[Stride] = (stride<<16)|stride;
481 mmio[FgrdData] = sval;
482 mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
483 mmio[DestXY] = (r.min.x<<16)|r.min.y;
490 CursorSyncCtl = 0x0D, /* in Seqx */
498 s3blank(VGAscr*, int blank)
502 x = vgaxi(Seqx, CursorSyncCtl);
505 x |= VsyncLo | HsyncLo;
506 vgaxo(Seqx, CursorSyncCtl, x);
510 s3drawinit(VGAscr *scr)
512 extern void savageinit(VGAscr*); /* vgasavage.c */
515 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
519 * It's highly likely that other ViRGEs will work without
520 * change to the driver, with the exception of the size of
521 * the linear aperture memory write FIFO. Since we don't
522 * know that size, I'm not turning them on. See waitforlinearfifo
525 scr->blank = s3blank;
526 /* hwblank = 1; not known to work well */
532 scr->mmio = (ulong*)((char*)scr->vaddr+0x1000000);
534 scr->scroll = hwscroll;
538 scr->mmio = (ulong*)((char*)scr->vaddr+0x1000000);
541 case SUPERSAVAGEIXC16:
546 /* scr->mmio is set by s3linear */