2 #include "../port/lib.h"
7 #include "../port/pci.h"
8 #include "../port/error.h"
17 PCIS3 = 0x5333, /* PCI VID */
19 SAVAGE3D = 0x8A20, /* PCI DID */
29 SUPERSAVAGEIXC16 = 0x8C2E,
39 VIRTUALPC2004 = 0x8810,
40 AURORA64VPLUS = 0x8812,
44 s3pageset(VGAscr* scr, int page)
49 crt35 = vgaxi(Crtx, 0x35);
50 if(scr->gscreen->depth >= 8){
52 * The S3 registers need to be unlocked for this.
53 * Let's hope they are already:
54 * vgaxo(Crtx, 0x38, 0x48);
55 * vgaxo(Crtx, 0x39, 0xA0);
57 * The page is 6 bits, the lower 4 bits in Crt35<3:0>,
58 * the upper 2 in Crt51<3:2>.
60 vgaxo(Crtx, 0x35, page & 0x0F);
61 crt51 = vgaxi(Crtx, 0x51);
62 vgaxo(Crtx, 0x51, (crt51 & ~0x0C)|((page & 0x30)>>2));
63 opage = ((crt51 & 0x0C)<<2)|(crt35 & 0x0F);
66 vgaxo(Crtx, 0x35, (page<<2) & 0x0C);
67 opage = (crt35>>2) & 0x03;
74 s3page(VGAscr* scr, int page)
78 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
87 unlock(&scr->devlock);
93 s3linear(VGAscr* scr, int, int)
106 addvgaseg("s3screen", scr->paddr, scr->apsize);
108 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
109 switch(id){ /* find mmio */
114 case SUPERSAVAGEIXC16:
116 * We could assume that the MMIO registers
117 * will be in the screen segment and just use
118 * that, but PCI software is allowed to move them
119 * if it feels like it, so we look for an aperture of
120 * the right size; only the first 512k actually means
121 * anything. The S3 engineers overestimated how
122 * much space they would need in the first design.
124 for(j=0; j<nelem(p->mem); j++){
125 if((p->mem[j].bar&1) == 0)
126 if((p->mem[j].bar&~0x0F) != scr->paddr)
127 if(p->mem[j].size==512*1024 || p->mem[j].size==16*1024*1024){
128 mmiobase = p->mem[j].bar & ~0x0F;
130 scr->mmio = vmap(mmiobase, mmiosize);
133 addvgaseg("savagemmio", mmiobase, mmiosize);
144 * Hardware cursor information is fetched from display memory
145 * during the horizontal blank active time. The 80x chips may hang
146 * if the cursor is turned on or off during this period.
148 while((vgai(Status1) & 0x08) == 0)
160 crt45 = vgaxi(Crtx, 0x45) & 0xFE;
162 vgaxo(Crtx, 0x45, crt45);
166 s3load(VGAscr* scr, Cursor* curs)
169 int id, dolock, opage, x, y;
172 * Disable the cursor and
173 * set the pointer to the two planes.
179 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
193 case SUPERSAVAGEIXC16:
201 opage = s3pageset(scr, scr->storage>>16);
202 p += (scr->storage & 0xFFFF);
207 * The cursor is set in Microsoft Windows format (the ViRGE/GX2 doesn't
208 * support the X11 format) which gives the following truth table:
210 * 0 0 background colour
211 * 0 1 foreground colour
212 * 1 0 current screen pixel
213 * 1 1 NOT current screen pixel
214 * Put the cursor into the top-left of the 64x64 array.
216 * The cursor pattern in memory is interleaved words of
217 * AND and XOR patterns.
219 for(y = 0; y < 64; y++){
220 for(x = 0; x < 64/8; x += 2){
221 if(x < 16/8 && y < 16){
222 *p++ = ~(curs->clr[2*y + x]|curs->set[2*y + x]);
223 *p++ = ~(curs->clr[2*y + x+1]|curs->set[2*y + x+1]);
224 *p++ = curs->set[2*y + x];
225 *p++ = curs->set[2*y + x+1];
237 s3pageset(scr, opage);
238 unlock(&scr->devlock);
242 * Save the cursor hotpoint and enable the cursor.
244 scr->offset = curs->offset;
246 vgaxo(Crtx, 0x45, 0x01);
250 s3move(VGAscr* scr, Point p)
255 * Mustn't position the cursor offscreen even partially,
256 * or it disappears. Therefore, if x or y is -ve, adjust the
257 * cursor offset instead.
258 * There seems to be a bug in that if the offset is 1, the
259 * cursor doesn't disappear off the left edge properly, so
260 * round it up to be even.
262 if((x = p.x+scr->offset.x) < 0){
269 if((y = p.y+scr->offset.y) < 0){
276 vgaxo(Crtx, 0x46, (x>>8) & 0x07);
277 vgaxo(Crtx, 0x47, x & 0xFF);
278 vgaxo(Crtx, 0x49, y & 0xFF);
279 vgaxo(Crtx, 0x4E, xo);
280 vgaxo(Crtx, 0x4F, yo);
281 vgaxo(Crtx, 0x48, (y>>8) & 0x07);
287 s3enable(VGAscr* scr)
295 * Cursor colours. Set both the CR0[EF] and the colour
296 * stack in case we are using a 16-bit RAMDAC.
298 vgaxo(Crtx, 0x0E, Pwhite);
299 vgaxo(Crtx, 0x0F, Pblack);
302 for(i = 0; i < 3; i++)
303 vgaxo(Crtx, 0x4A, Pblack);
305 for(i = 0; i < 3; i++)
306 vgaxo(Crtx, 0x4B, Pwhite);
309 * Find a place for the cursor data in display memory.
310 * Must be on a 1024-byte boundary.
312 storage = (scr->gscreen->width*sizeof(ulong)*scr->gscreen->r.max.y+1023)/1024;
313 vgaxo(Crtx, 0x4C, storage>>8);
314 vgaxo(Crtx, 0x4D, storage & 0xFF);
316 scr->storage = storage;
319 * Load, locate and enable the cursor
320 * in Microsoft Windows format.
322 s3load(scr, &cursor);
324 vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10);
326 vgaxo(Crtx, 0x45, 0x01);
330 * The manual gives byte offsets, but we want ulong offsets, hence /4.
337 WidthHeight = 0xA504/4,
346 * Wait for writes to VGA memory via linear aperture to flush.
348 enum {Maxloop = 1<<24};
359 waitforlinearfifo(VGAscr *scr)
363 static ulong nwaitforlinearfifo;
368 panic("unknown scr->id in s3 waitforlinearfifo");
369 case 0x8A01: /* ViRGE/[DG]X. XFree86 says no waiting necessary */
371 case 0x5631: /* ViRGE */
372 case 0x883D: /* ViRGE/VX */
376 case 0x8A10: /* ViRGE/GX2 */
383 while((mmio[FifoStat]&mask) != val && x++ < Maxloop)
386 waitcount.lineartimeout++;
390 waitforfifo(VGAscr *scr, int entries)
394 static ulong nwaitforfifo;
398 while((mmio[SubStat]&0x1F00) < ((entries+2)<<8) && x++ < Maxloop)
401 waitcount.fifotimeout++;
405 waitforidle(VGAscr *scr)
412 while((mmio[SubStat]&0x3F00) != 0x3000 && x++ < Maxloop)
415 waitcount.idletimeout++;
419 hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
421 enum { Bitbltop = 0xCC }; /* copy source */
427 d = scr->gscreen->depth;
429 cmd = 0x00000020|(Bitbltop<<17)|(did<<2);
430 stride = Dx(scr->gscreen->r)*d/8;
432 if(r.min.x <= sr.min.x){
441 if(r.min.y <= sr.min.y){
451 waitforlinearfifo(scr);
453 mmio[SrcBase] = scr->paddr;
454 mmio[DstBase] = scr->paddr;
455 mmio[Stride] = (stride<<16)|stride;
456 mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
457 mmio[SrcXY] = (sp.x<<16)|sp.y;
458 mmio[DestXY] = (dp.x<<16)|dp.y;
465 hwfill(VGAscr *scr, Rectangle r, ulong sval)
467 enum { Bitbltop = 0xCC }; /* copy source */
472 d = scr->gscreen->depth;
474 cmd = 0x16000120|(Bitbltop<<17)|(did<<2);
475 stride = Dx(scr->gscreen->r)*d/8;
477 waitforlinearfifo(scr);
479 mmio[SrcBase] = scr->paddr;
480 mmio[DstBase] = scr->paddr;
481 mmio[DstBase] = scr->paddr;
482 mmio[Stride] = (stride<<16)|stride;
483 mmio[FgrdData] = sval;
484 mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
485 mmio[DestXY] = (r.min.x<<16)|r.min.y;
492 CursorSyncCtl = 0x0D, /* in Seqx */
500 s3blank(VGAscr*, int blank)
504 x = vgaxi(Seqx, CursorSyncCtl);
507 x |= VsyncLo | HsyncLo;
508 vgaxo(Seqx, CursorSyncCtl, x);
512 s3drawinit(VGAscr *scr)
514 extern void savageinit(VGAscr*); /* vgasavage.c */
517 id = (vgaxi(Crtx, 0x2D)<<8)|vgaxi(Crtx, 0x2E);
521 * It's highly likely that other ViRGEs will work without
522 * change to the driver, with the exception of the size of
523 * the linear aperture memory write FIFO. Since we don't
524 * know that size, I'm not turning them on. See waitforlinearfifo
527 scr->blank = s3blank;
533 scr->mmio = (ulong*)((char*)scr->vaddr+0x1000000);
535 scr->scroll = hwscroll;
539 scr->mmio = (ulong*)((char*)scr->vaddr+0x1000000);
542 case SUPERSAVAGEIXC16:
547 /* scr->mmio is set by s3linear */