M alphapc/devvga.c => alphapc/devvga.c +46 -29
@@ 1,4 1,5 @@
/*
+ * VGA controller
*/
#include "u.h"
#include "../port/lib.h"
@@ 69,6 70,20 @@ vgaclose(Chan*)
{
}
+static void
+checkport(int start, int end)
+{
+ /* standard vga regs are OK */
+ if(start >= 0x2b0 && end <= 0x2df+1)
+ return;
+ if(start >= 0x3c0 && end <= 0x3da+1)
+ return;
+
+ if(iounused(start, end))
+ return;
+ error(Eperm);
+}
+
static long
vgaread(Chan* c, void* a, long n, vlong off)
{
@@ 76,6 91,7 @@ vgaread(Chan* c, void* a, long n, vlong off)
char *p, *s;
VGAscr *scr;
ulong offset = off;
+ char chbuf[30];
switch(c->qid.path & ~CHDIR){
@@ 90,27 106,32 @@ vgaread(Chan* c, void* a, long n, vlong off)
free(p);
nexterror();
}
+
+ len = 0;
+
if(scr->dev)
s = scr->dev->name;
else
s = "cga";
- len = snprint(p, READSTR, "type: %s\n", s);
- if(scr->gscreen)
- len += snprint(p+len, READSTR-len, "size: %dx%dx%d\n",
+ len += snprint(p+len, READSTR-len, "type %s\n", s);
+
+ if(scr->gscreen) {
+ len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
scr->gscreen->r.max.x, scr->gscreen->r.max.y,
- scr->gscreen->depth);
- if(scr->cur)
- s = scr->cur->name;
- else
- s = "off";
- len += snprint(p+len, READSTR-len, "hwgc: %s\n", s);
+ scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
+
+ if(Dx(scr->gscreen->r) != Dx(physgscreenr)
+ || Dy(scr->gscreen->r) != Dy(physgscreenr))
+ len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
+ physgscreenr.max.x, physgscreenr.max.y);
+ }
+
+ len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
+ len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
if(scr->pciaddr)
- snprint(p+len, READSTR-len, "addr: 0x%lux\n",
- scr->pciaddr);
+ snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->pciaddr);
else
- snprint(p+len, READSTR-len, "addr: 0x%lux\n",
- scr->aperture);
-
+ snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->aperture);
n = readstr(offset, a, n, p);
poperror();
free(p);
@@ 159,10 180,6 @@ vgactl(char* a)
if(n < 2)
error(Ebadarg);
- /* BUG: drawinit should become a different message rather than piggybacking */
- if(scr && scr->dev && scr->dev->drawinit)
- scr->dev->drawinit(scr);
-
if(strcmp(field[1], "off") == 0){
lock(&cursor);
if(scr->cur){
@@ 277,17 294,8 @@ vgactl(char* a)
return;
}
else if(strcmp(field[0], "drawinit") == 0){
- /*
- * This is a separate message, but first we need to make
- * aux/vga send it; once everyone has the new vga, we
- * can take the drawinit stuff out of hwgc.
- */
-
- /*
if(scr && scr->dev && scr->dev->drawinit)
scr->dev->drawinit(scr);
- */
-
return;
}
else if(strcmp(field[0], "linear") == 0){
@@ 311,9 319,9 @@ vgactl(char* a)
}
*/
else if(strcmp(field[0], "blank") == 0){
- if(n < 2)
+ if(n < 1)
error(Ebadarg);
- drawblankscreen(atoi(field[1]));
+ drawblankscreen(1);
return;
}
else if(strcmp(field[0], "hwaccel") == 0){
@@ 325,6 333,15 @@ vgactl(char* a)
hwaccel = 0;
return;
}
+ else if(strcmp(field[0], "hwblank") == 0){
+ if(n < 2)
+ error(Ebadarg);
+ if(strcmp(field[1], "on") == 0)
+ hwblank = 1;
+ else if(strcmp(field[1], "off") == 0)
+ hwblank = 0;
+ return;
+ }
error(Ebadarg);
}
M alphapc/fns.h => alphapc/fns.h +1 -0
@@ 44,6 44,7 @@ void intrenable(int, void (*)(Ureg*, void*), void*, int, char*);
int ioalloc(int, int, int, char*);
void iofree(int);
void ioinit(void);
+int iounused(int, int);
int iprint(char*, ...);
int irqallocread(char*, long, vlong);
int isaconfig(char*, int, ISAConf*);
M alphapc/io.h => alphapc/io.h +1 -0
@@ 16,6 16,7 @@ enum {
IrqAUX = 12, /* PS/2 port */
IrqIRQ13 = 13, /* coprocessor on 386 */
IrqATA0 = 14,
+ IrqATA1 = 15,
MaxIrqPIC = 15,
VectorPIC = 64,
M alphapc/screen.c => alphapc/screen.c +18 -3
@@ 51,7 51,7 @@ screensize(int x, int y, int z, ulong chan)
* be given back if aperture is set.
*/
if(scr->aperture == 0){
- int width = (x*(1<<z))/BI2WD;
+ int width = (x*z)/BI2WD;
gscreendata.bdata = xalloc(width*BY2WD*y);
if(gscreendata.bdata == 0)
@@ 73,11 73,16 @@ screensize(int x, int y, int z, ulong chan)
if(gscreen == nil)
return -1;
+/* memset(gscreen->data->bdata, 0x15, (x*y*z+7)/8); /* RSC BUG */
+ memfillcolor(gscreen, DRed);
+
scr->palettedepth = 6; /* default */
scr->gscreendata = &gscreendata;
scr->memdefont = getmemdefont();
scr->gscreen = gscreen;
+ physgscreenr = gscreen->r;
+
drawcmap();
return 0;
}
@@ 101,8 106,7 @@ screenaperture(int size, int align)
aperture = scr->dev->linear(scr, &size, &align);
if(aperture == 0)
return 1;
- }
- else{
+ }else{
aperture = upamalloc(0, size, align);
if(aperture == 0)
return 1;
@@ 460,6 464,7 @@ Memimage *lastbadi;
Memdata *lastbad;
Memimage *lastbadsrc, *lastbaddst;
int hwaccel = 1;
+int hwblank = 1;
int
hwdraw(Memdrawparam *par)
@@ 513,3 518,13 @@ hwdraw(Memdrawparam *par)
return 0;
}
+
+void
+blankscreen(int blank)
+{
+ VGAscr *scr;
+
+ scr = &vgascreen[0];
+ if(hwblank && scr->blank)
+ scr->blank(scr, blank);
+}
M alphapc/screen.h => alphapc/screen.h +7 -0
@@ 104,14 104,17 @@ struct VGAscr {
ulong colormap[Pcolours][3];
int palettedepth;
+ ulong *mmio;
Memimage* gscreen;
Memdata* gscreendata;
Memsubfont* memdefont;
int (*fill)(VGAscr*, Rectangle, ulong);
int (*scroll)(VGAscr*, Rectangle, Rectangle);
+ void (*blank)(VGAscr*, int);
ulong id; /* internal identifier for driver use */
};
+
extern VGAscr vgascreen[];
enum {
@@ 123,6 126,7 @@ extern void mousectl(char*[], int);
/* screen.c */
extern int hwaccel; /* use hw acceleration; default on */
+extern int hwblank; /* use hw blanking; default on */
extern void flushmemscreen(Rectangle);
extern int cursoron(int);
extern void cursoroff(int);
@@ 130,6 134,7 @@ extern void setcursor(Cursor*);
extern int screensize(int, int, int, ulong);
extern int screenaperture(int, int);
extern Rectangle physgscreenr; /* actual monitor size */
+extern void blankscreen(int);
/* devdraw.c */
extern void deletescreenimage(void);
@@ 138,5 143,7 @@ extern int drawhasclients(void);
/* vga.c */
extern void vgascreenwin(VGAscr*);
extern void vgaimageinit(ulong);
+extern ulong vgapcilinear(VGAscr*, int*, int*, int, int);
extern void drawblankscreen(int);
+extern void vgablank(VGAscr*, int);
M alphapc/vga.c => alphapc/vga.c +28 -0
@@ 189,3 189,31 @@ vgascreenwin(VGAscr* scr)
screenputs = vgascreenputs;
}
+
+/*
+ * Supposedly this is the way to turn DPMS
+ * monitors off using just the VGA registers.
+ * Unfortunately, it seems to mess up the video mode
+ * on the cards I've tried.
+ */
+void
+vgablank(VGAscr*, int blank)
+{
+ uchar seq1, crtc17;
+
+ if(blank) {
+ seq1 = 0x00;
+ crtc17 = 0x80;
+ } else {
+ seq1 = 0x20;
+ crtc17 = 0x00;
+ }
+
+ outs(Seqx, 0x0100); /* synchronous reset */
+ seq1 |= vgaxi(Seqx, 1) & ~0x20;
+ vgaxo(Seqx, 1, seq1);
+ crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
+ delay(10);
+ vgaxo(Crtx, 0x17, crtc17);
+ outs(Crtx, 0x0300); /* end synchronous reset */
+}
M alphapc/vgas3.c => alphapc/vgas3.c +203 -0
@@ 284,6 284,208 @@ s3move(VGAscr* scr, Point p)
return 0;
}
+/*
+ * The manual gives byte offsets, but we want ulong offsets, hence /4.
+ */
+enum {
+ SrcBase = 0xA4D4/4,
+ DstBase = 0xA4D8/4,
+ Stride = 0xA4E4/4,
+ FgrdData = 0xA4F4/4,
+ WidthHeight = 0xA504/4,
+ SrcXY = 0xA508/4,
+ DestXY = 0xA50C/4,
+ Command = 0xA500/4,
+ SubStat = 0x8504/4,
+ FifoStat = 0x850C/4,
+};
+
+/*
+ * Wait for writes to VGA memory via linear aperture to flush.
+ */
+enum {Maxloop = 1<<24};
+struct {
+ ulong linear;
+ ulong fifo;
+ ulong idle;
+} waitcount;
+
+static void
+waitforlinearfifo(VGAscr *scr)
+{
+ ulong *mmio;
+ long x;
+ static ulong nwaitforlinearfifo;
+ ulong mask, val;
+
+ switch(scr->id){
+ default:
+ panic("unknown scr->id in s3 waitforlinearfifo");
+ case 0xE131: /* ViRGE */
+ case 0xE13D: /* ViRGE/VX */
+ mask = 0x0F<<6;
+ val = 0x08<<6;
+ break;
+ case 0xE110: /* ViRGE/GX2 */
+ mask = 0x1F<<6;
+ val = 0x10<<6;
+ break;
+ }
+ mmio = scr->mmio;
+ x = 0;
+ while((mmio[FifoStat]&mask) != val && x++ < Maxloop)
+ waitcount.linear++;
+}
+
+static void
+waitforfifo(VGAscr *scr, int entries)
+{
+ ulong *mmio;
+ long x;
+ static ulong nwaitforfifo;
+
+ mmio = scr->mmio;
+ x = 0;
+ while((mmio[SubStat]&0x1F00) < ((entries+2)<<8) && x++ < Maxloop)
+ waitcount.fifo++;
+}
+
+static void
+waitforidle(VGAscr *scr)
+{
+ ulong *mmio;
+ long x;
+
+ mmio = scr->mmio;
+ x = 0;
+ while((mmio[SubStat]&0x3F00) != 0x3000 && x++ < Maxloop)
+ waitcount.idle++;
+}
+
+static int
+hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
+{
+ enum { Bitbltop = 0xCC }; /* copy source */
+ ulong *mmio;
+ ulong cmd, stride;
+ Point dp, sp;
+ int did, d;
+
+ d = scr->gscreen->depth;
+ did = (d-8)/8;
+ cmd = 0x00000020|(Bitbltop<<17)|(did<<2);
+ stride = Dx(scr->gscreen->r)*d/8;
+
+ if(r.min.x <= sr.min.x){
+ cmd |= 1<<25;
+ dp.x = r.min.x;
+ sp.x = sr.min.x;
+ }else{
+ dp.x = r.max.x-1;
+ sp.x = sr.max.x-1;
+ }
+
+ if(r.min.y <= sr.min.y){
+ cmd |= 1<<26;
+ dp.y = r.min.y;
+ sp.y = sr.min.y;
+ }else{
+ dp.y = r.max.y-1;
+ sp.y = sr.max.y-1;
+ }
+
+ mmio = scr->mmio;
+ waitforlinearfifo(scr);
+ waitforfifo(scr, 7);
+ mmio[SrcBase] = scr->aperture;
+ mmio[DstBase] = scr->aperture;
+ mmio[Stride] = (stride<<16)|stride;
+ mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
+ mmio[SrcXY] = (sp.x<<16)|sp.y;
+ mmio[DestXY] = (dp.x<<16)|dp.y;
+ mmio[Command] = cmd;
+ waitforidle(scr);
+ return 1;
+}
+
+static int
+hwfill(VGAscr *scr, Rectangle r, ulong sval)
+{
+ enum { Bitbltop = 0xCC }; /* copy source */
+ ulong *mmio;
+ ulong cmd, stride;
+ int did, d;
+
+ d = scr->gscreen->depth;
+ did = (d-8)/8;
+ cmd = 0x16000120|(Bitbltop<<17)|(did<<2);
+ stride = Dx(scr->gscreen->r)*d/8;
+ mmio = scr->mmio;
+ waitforlinearfifo(scr);
+ waitforfifo(scr, 8);
+ mmio[SrcBase] = scr->aperture;
+ mmio[DstBase] = scr->aperture;
+ mmio[DstBase] = scr->aperture;
+ mmio[Stride] = (stride<<16)|stride;
+ mmio[FgrdData] = sval;
+ mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r);
+ mmio[DestXY] = (r.min.x<<16)|r.min.y;
+ mmio[Command] = cmd;
+ waitforidle(scr);
+ return 1;
+}
+
+enum {
+ CursorSyncCtl = 0x0D, /* in Seqx */
+ VsyncHi = 0x80,
+ VsyncLo = 0x40,
+ HsyncHi = 0x20,
+ HsyncLo = 0x10,
+};
+
+static void
+s3blank(int blank)
+{
+ uchar x;
+
+ x = vgaxi(Seqx, CursorSyncCtl);
+ x &= ~0xF0;
+ if(blank)
+ x |= VsyncLo | HsyncLo;
+ vgaxo(Seqx, CursorSyncCtl, x);
+}
+
+static void
+s3drawinit(VGAscr *scr)
+{
+ ulong id;
+
+ id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E);
+ scr->id = id;
+
+ /*
+ * It's highly likely that other ViRGEs will work without
+ * change to the driver, with the exception of the size of
+ * the linear aperture memory write FIFO. Since we don't
+ * know that size, I'm not turning them on. See waitforlinearfifo
+ * above.
+ */
+ switch(id){
+ case 0xE131: /* ViRGE */
+ case 0xE13D: /* ViRGE/VX */
+ case 0xE110: /* ViRGE/GX2 */
+ scr->mmio = (ulong*)(scr->pciaddr+0x1000000);
+/*
+ * Untested on the Alpha.
+ */
+/*
+ scr->fill = hwfill;
+ scr->scroll = hwscroll;
+*/
+ /* scr->blank = hwblank; */
+ }
+}
+
VGAdev vgas3dev = {
"s3",
@@ 291,6 493,7 @@ VGAdev vgas3dev = {
0,
s3page,
s3linear,
+ s3drawinit,
};
VGAcur vgas3cur = {
M boot/bootip.c => boot/bootip.c +2 -1
@@ 42,7 42,8 @@ configip(void)
case 'b':
case 'h':
case 'm':
- ARGF();
+ p = ARGF();
+ USED(p);
break;
} ARGEND;
M port/alloc.c => port/alloc.c +0 -1
@@ 76,7 76,6 @@ static void
ppanic(Pool *p, char *fmt, ...)
{
va_list v;
- int n;
Private *pv;
char msg[sizeof pv->msg];
M port/devaudio.c => port/devaudio.c +3 -1
@@ 1188,8 1188,10 @@ swab(uchar *a)
{
ulong *p, *ep, b;
- if(!SBswab)
+ if(!SBswab){
+ USED(a);
return;
+ }
p = (ulong*)a;
ep = p + (Bufsize>>2);
while(p < ep) {