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)
105 addvgaseg("s3screen", scr->paddr, scr->apsize);
107 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
108 switch(id){ /* find mmio */
113 case SUPERSAVAGEIXC16:
115 * We could assume that the MMIO registers
116 * will be in the screen segment and just use
117 * that, but PCI software is allowed to move them
118 * if it feels like it, so we look for an aperture of
119 * the right size; only the first 512k actually means
120 * anything. The S3 engineers overestimated how
121 * much space they would need in the first design.
123 for(j=0; j<nelem(p->mem); j++){
124 if((p->mem[j].bar&1) == 0)
125 if((p->mem[j].bar&~0x0F) != scr->paddr)
126 if(p->mem[j].size==512*1024 || p->mem[j].size==16*1024*1024){
127 mmiobase = p->mem[j].bar & ~0x0F;
129 scr->mmio = vmap(mmiobase, mmiosize);
132 addvgaseg("savagemmio", mmiobase, mmiosize);
143 * Hardware cursor information is fetched from display memory
144 * during the horizontal blank active time. The 80x chips may hang
145 * if the cursor is turned on or off during this period.
147 while((vgai(Status1) & 0x08) == 0)
159 crt45 = vgaxi(Crtx, 0x45) & 0xFE;
161 vgaxo(Crtx, 0x45, crt45);
165 s3load(VGAscr* scr, Cursor* curs)
168 int id, dolock, opage, x, y;
171 * Disable the cursor and
172 * set the pointer to the two planes.
178 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
192 case SUPERSAVAGEIXC16:
200 opage = s3pageset(scr, scr->storage>>16);
201 p += (scr->storage & 0xFFFF);
206 * The cursor is set in Microsoft Windows format (the ViRGE/GX2 doesn't
207 * support the X11 format) which gives the following truth table:
209 * 0 0 background colour
210 * 0 1 foreground colour
211 * 1 0 current screen pixel
212 * 1 1 NOT current screen pixel
213 * Put the cursor into the top-left of the 64x64 array.
215 * The cursor pattern in memory is interleaved words of
216 * AND and XOR patterns.
218 for(y = 0; y < 64; y++){
219 for(x = 0; x < 64/8; x += 2){
220 if(x < 16/8 && y < 16){
221 *p++ = ~(curs->clr[2*y + x]|curs->set[2*y + x]);
222 *p++ = ~(curs->clr[2*y + x+1]|curs->set[2*y + x+1]);
223 *p++ = curs->set[2*y + x];
224 *p++ = curs->set[2*y + x+1];
236 s3pageset(scr, opage);
237 unlock(&scr->devlock);
241 * Save the cursor hotpoint and enable the cursor.
243 scr->offset = curs->offset;
245 vgaxo(Crtx, 0x45, 0x01);
249 s3move(VGAscr* scr, Point p)
254 * Mustn't position the cursor offscreen even partially,
255 * or it disappears. Therefore, if x or y is -ve, adjust the
256 * cursor offset instead.
257 * There seems to be a bug in that if the offset is 1, the
258 * cursor doesn't disappear off the left edge properly, so
259 * round it up to be even.
261 if((x = p.x+scr->offset.x) < 0){
268 if((y = p.y+scr->offset.y) < 0){
275 vgaxo(Crtx, 0x46, (x>>8) & 0x07);
276 vgaxo(Crtx, 0x47, x & 0xFF);
277 vgaxo(Crtx, 0x49, y & 0xFF);
278 vgaxo(Crtx, 0x4E, xo);
279 vgaxo(Crtx, 0x4F, yo);
280 vgaxo(Crtx, 0x48, (y>>8) & 0x07);
286 s3enable(VGAscr* scr)
294 * Cursor colours. Set both the CR0[EF] and the colour
295 * stack in case we are using a 16-bit RAMDAC.
297 vgaxo(Crtx, 0x0E, Pwhite);
298 vgaxo(Crtx, 0x0F, Pblack);
301 for(i = 0; i < 3; i++)
302 vgaxo(Crtx, 0x4A, Pblack);
304 for(i = 0; i < 3; i++)
305 vgaxo(Crtx, 0x4B, Pwhite);
308 * Find a place for the cursor data in display memory.
309 * Must be on a 1024-byte boundary.
311 storage = (scr->gscreen->width*sizeof(ulong)*scr->gscreen->r.max.y+1023)/1024;
312 vgaxo(Crtx, 0x4C, storage>>8);
313 vgaxo(Crtx, 0x4D, storage & 0xFF);
315 scr->storage = storage;
318 * Load, locate and enable the cursor
319 * in Microsoft Windows format.
321 s3load(scr, &cursor);
323 vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10);
325 vgaxo(Crtx, 0x45, 0x01);
329 * The manual gives byte offsets, but we want ulong offsets, hence /4.
336 WidthHeight = 0xA504/4,
345 * Wait for writes to VGA memory via linear aperture to flush.
347 enum {Maxloop = 1<<24};
358 waitforlinearfifo(VGAscr *scr)
362 static ulong nwaitforlinearfifo;
367 panic("unknown scr->id in s3 waitforlinearfifo");
368 case 0x8A01: /* ViRGE/[DG]X. XFree86 says no waiting necessary */
370 case 0x5631: /* ViRGE */
371 case 0x883D: /* ViRGE/VX */
375 case 0x8A10: /* ViRGE/GX2 */
382 while((mmio[FifoStat]&mask) != val && x++ < Maxloop)
385 waitcount.lineartimeout++;
389 waitforfifo(VGAscr *scr, int entries)
393 static ulong nwaitforfifo;
397 while((mmio[SubStat]&0x1F00) < ((entries+2)<<8) && x++ < Maxloop)
400 waitcount.fifotimeout++;
404 waitforidle(VGAscr *scr)
411 while((mmio[SubStat]&0x3F00) != 0x3000 && x++ < Maxloop)
414 waitcount.idletimeout++;
418 hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
420 enum { Bitbltop = 0xCC }; /* copy source */
426 d = scr->gscreen->depth;
428 cmd = 0x00000020|(Bitbltop<<17)|(did<<2);
429 stride = Dx(scr->gscreen->r)*d/8;
431 if(r.min.x <= sr.min.x){
440 if(r.min.y <= sr.min.y){
450 waitforlinearfifo(scr);
452 mmio[SrcBase] = scr->paddr;
453 mmio[DstBase] = scr->paddr;
454 mmio[Stride] = (stride<<16)|stride;
455 mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
456 mmio[SrcXY] = (sp.x<<16)|sp.y;
457 mmio[DestXY] = (dp.x<<16)|dp.y;
464 hwfill(VGAscr *scr, Rectangle r, ulong sval)
466 enum { Bitbltop = 0xCC }; /* copy source */
471 d = scr->gscreen->depth;
473 cmd = 0x16000120|(Bitbltop<<17)|(did<<2);
474 stride = Dx(scr->gscreen->r)*d/8;
476 waitforlinearfifo(scr);
478 mmio[SrcBase] = scr->paddr;
479 mmio[DstBase] = scr->paddr;
480 mmio[DstBase] = scr->paddr;
481 mmio[Stride] = (stride<<16)|stride;
482 mmio[FgrdData] = sval;
483 mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
484 mmio[DestXY] = (r.min.x<<16)|r.min.y;
491 CursorSyncCtl = 0x0D, /* in Seqx */
499 s3blank(VGAscr*, int blank)
503 x = vgaxi(Seqx, CursorSyncCtl);
506 x |= VsyncLo | HsyncLo;
507 vgaxo(Seqx, CursorSyncCtl, x);
511 s3drawinit(VGAscr *scr)
513 extern void savageinit(VGAscr*); /* vgasavage.c */
516 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
520 * It's highly likely that other ViRGEs will work without
521 * change to the driver, with the exception of the size of
522 * the linear aperture memory write FIFO. Since we don't
523 * know that size, I'm not turning them on. See waitforlinearfifo
526 scr->blank = s3blank;
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 */