M carrera/fns.h => carrera/fns.h +1 -0
@@ 76,6 76,7 @@ void iomapinit(void);
void enetaddr(uchar*);
#define waserror() setlabel(&up->errlab[up->nerrlab++])
+#define kmapperm(x) kmap(x)
#define KADDR(a) ((void*)((ulong)(a)|KSEG0))
#define KADDR1(a) ((void*)((ulong)(a)|KSEG1))
M carrera/kbd.c => carrera/kbd.c +2 -1
@@ 6,7 6,8 @@
#include "io.h"
#include "../port/error.h"
-#include <libg.h>
+#define Image IMAGE
+#include <draw.h>
#include "screen.h"
enum
M carrera/main.c => carrera/main.c +6 -2
@@ 5,6 5,7 @@
#include "fns.h"
#include "io.h"
#include "init.h"
+#include "pool.h"
/*
* args passed by boot process
@@ 58,7 59,6 @@ main(void)
pageinit();
procinit0();
initseg();
- links();
chandevreset();
swapinit();
userinit();
@@ 456,7 456,11 @@ confinit(void)
conf.npage1 = 0;
conf.base1 = 0;
- conf.upages = (conf.npage*70)/100;
+ if(top > 16*MB){
+ conf.upages = (conf.npage*60)/100;
+ poolsetparam("Image", 0, 0, 4*1024*1024);
+ }else
+ conf.upages = (conf.npage*40)/100;
conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
conf.nmach = 1;
M carrera/memmove.s => carrera/memmove.s +142 -148
@@ 1,16 1,9 @@
/*
- * R4000 double-word version. Only works in kernel mode.
- * Requires low-core support to save R5 and R6 in a 64-bit hole.
+ * R4000-compatible memmove uses V instructions.
+ * The kernel uses the 3000 compilers, but we can
+ * use this procedure for speed.
*/
-
-/*
- * R4000 instructions
- */
-#define LD(offset, base, rt) WORD $((067<<26)|((base)<<21)|((rt)<<16)|((offset)&0xFFFF))
-#define STD(rt, offset, base) WORD $((077<<26)|((base)<<21)|((rt)<<16)|((offset)&0xFFFF))
-
TEXT memmove(SB), $0
-
JMP move
TEXT memcpy(SB), $0
@@ 19,141 12,140 @@ move:
MOVW n+8(FP), R3 /* R3 is count */
MOVW R1, R4 /* R4 is to-pointer */
- SGT R0, R3, R10
- BEQ R10, ok
+ SGT R0, R3, R5
+ BEQ R5, ok
MOVW (R0), R0 /* abort if negative count */
ok:
- MOVW s2+4(FP), R10 /* R10 is from-pointer */
- ADDU R3,R10, R7 /* R7 is end from-pointer */
- ADDU R3,R4, R11 /* R11 is end to-pointer */
+ MOVW s2+4(FP), R5 /* R5 is from-pointer */
+ ADDU R3,R5, R7 /* R7 is end from-pointer */
+ ADDU R3,R4, R6 /* R6 is end to-pointer */
/*
* easiest test is copy backwards if
* destination string has higher mem address
*/
- SGT $8,R3, R2
- SGTU R4,R10, R1
+ SGT $15,R3, R2
+ SGTU R4,R5, R1
BNE R1, back
/*
- * if not at least 8 chars,
- * dont even mess around.
+ * if not at least 15 chars,
+ * don't even mess around.
* 7 chars to guarantee any
* rounding up to a doubleword
* boundary and 8 characters
* to get at least maybe one
- * full doubleword store.
+ * doubleword store.
*/
BNE R2, fout
/*
- * test if both pointers
- * are similarly word aligned
- */
- XOR R4,R10, R1
- AND $3, R1
- BNE R1, fout
-
-/*
- * test if both pointers
- * are similarly double-word aligned
+ * byte at a time to doubleword align destination
*/
- XOR R4,R10, R1
- AND $7, R1
- BNE R1, f1
-
-/*
- * double-word aligned; start by byte at a time until aligned
- */
-fd1:
+f1:
AND $7,R4, R1
- BEQ R1, fd2
- MOVB 0(R10), R8
- ADDU $1, R10
+ BEQ R1, f2
+ MOVB 0(R5), R8
+ ADDU $1, R5
MOVB R8, 0(R4)
ADDU $1, R4
- JMP fd1
+ JMP f1
+
+/*
+ * test if source is now doubleword aligned
+ */
+f2:
+ AND $7, R5, R1
+ BNE R1, fun2
/*
* turn R3 into to-end pointer-31
- * copy 32 at a time while there's room.
- * R11 is smaller than R7 --
+ * copy 32 at a time while theres room.
+ * R6 is smaller than R7 --
* there are problems if R7 is 0.
*/
-fd2:
- ADDU $-31,R11, R3
-fd3:
+ ADDU $-31,R6, R3
+f3:
SGTU R3,R4, R1
BEQ R1, f4
- LD (0,(10), 5) /* MOVW 0(R10), R8 */
- LD (8,(10), 6) /* MOVW 4(R10), R9 */
- STD (5, 0,(4)) /* MOVW R8, 0(R4) */
- LD (16,(10), 5) /* MOVW 8(R10), R8 */
- STD (6, 8,(4)) /* MOVW R9, 4(R4) */
- LD (24,(10), 6) /* MOVW 12(R10), R9 */
- ADDU $32, R10
- STD (5, 16,(4)) /* MOVW R8, 8(R4) */
- STD (6, 24,(4)) /* MOVW R9, 12(R4) */
+ MOVV 0(R5), R8
+ MOVV 8(R5), R9
+ MOVV R8, 0(R4)
+ MOVV 16(R5), R8
+ MOVV R9, 8(R4)
+ MOVV 24(R5), R9
+ ADDU $32, R5
+ MOVV R8, 16(R4)
+ MOVV R9, 24(R4)
ADDU $32, R4
- JMP fd3
+ JMP f3
/*
- * byte at a time to word align
+ * turn R3 into to-end pointer-3
+ * copy 4 at a time while theres room
*/
-f1:
- AND $3,R4, R1
- BEQ R1, f2
- MOVB 0(R10), R8
- ADDU $1, R10
- MOVB R8, 0(R4)
- ADDU $1, R4
- JMP f1
+f4:
+ ADDU $-3,R6, R3
+f5:
+ SGTU R3,R4, R1
+ BEQ R1, fout
+ MOVW 0(R5), R8
+ ADDU $4, R5
+ MOVW R8, 0(R4)
+ ADDU $4, R4
+ JMP f5
/*
- * turn R3 into to-end pointer-15
- * copy 16 at a time while there's room.
- * R11 is smaller than R7 --
+ * forward copy, unaligned
+ * turn R3 into to-end pointer-31
+ * copy 32 at a time while theres room.
+ * R6 is smaller than R7 --
* there are problems if R7 is 0.
*/
-f2:
- ADDU $-15,R11, R3
-f3:
+fun2:
+ ADDU $-31,R6, R3
+fun3:
SGTU R3,R4, R1
- BEQ R1, f4
- MOVW 0(R10), R8
- MOVW 4(R10), R9
- MOVW R8, 0(R4)
- MOVW 8(R10), R8
- MOVW R9, 4(R4)
- MOVW 12(R10), R9
- ADDU $16, R10
- MOVW R8, 8(R4)
- MOVW R9, 12(R4)
- ADDU $16, R4
- JMP f3
+ BEQ R1, fun4
+ MOVVL 0(R5), R8
+ MOVVR 7(R5), R8
+ MOVVL 8(R5), R9
+ MOVVR 15(R5), R9
+ MOVV R8, 0(R4)
+ MOVVL 16(R5), R8
+ MOVVR 23(R5), R8
+ MOVV R9, 8(R4)
+ MOVVL 24(R5), R9
+ MOVVR 31(R5), R9
+ ADDU $32, R5
+ MOVV R8, 16(R4)
+ MOVV R9, 24(R4)
+ ADDU $32, R4
+ JMP fun3
/*
* turn R3 into to-end pointer-3
* copy 4 at a time while theres room
*/
-f4:
- ADDU $-3,R11, R3
-f5:
+fun4:
+ ADDU $-3,R6, R3
+fun5:
SGTU R3,R4, R1
BEQ R1, fout
- MOVW 0(R10), R8
- ADDU $4, R10
+ MOVWL 0(R5), R8
+ MOVWR 3(R5), R8
+ ADDU $4, R5
MOVW R8, 0(R4)
ADDU $4, R4
- JMP f5
+ JMP fun5
/*
* last loop, copy byte at a time
*/
fout:
- BEQ R7,R10, ret
- MOVB 0(R10), R8
- ADDU $1, R10
+ BEQ R7,R5, ret
+ MOVB 0(R5), R8
+ ADDU $1, R5
MOVB R8, 0(R4)
ADDU $1, R4
JMP fout
@@ 163,82 155,84 @@ fout:
*/
back:
BNE R2, bout
- XOR R11,R7, R1
- AND $3, R1
- BNE R1, bout
-
- XOR R11,R7, R1
- AND $7, R1
- BNE R1, b1
-
- /* double words */
-bd1:
- AND $7,R7, R1
- BEQ R1, bd2
- MOVB -1(R7), R8
- ADDU $-1, R7
- MOVB R8, -1(R11)
- ADDU $-1, R11
- JMP bd1
-bd2:
- ADDU $31,R10, R3
-bd3:
- SGTU R7,R3, R1
- BEQ R1, b4
- LD (-8,(7), 5) /* MOVW -4(R7), R8 */
- LD (-16,(7), 6) /* MOVW -8(R7), R9 */
- STD (5, -8,(11)) /* MOVW R8, -4(R11) */
- LD (-24,(7), 5) /* MOVW -12(R7), R8 */
- STD (6, -16,(11)) /* MOVW R9, -8(R11) */
- LD (-32,(7), 6) /* MOVW -16(R7), R9 */
- ADDU $-32, R7
- STD (5, -24,(11)) /* MOVW R8, -12(R11) */
- STD (6, -32,(11)) /* MOVW R9, -16(R11) */
- ADDU $-32, R11
- JMP bd3
-
- /* regular words */
b1:
- AND $3,R7, R1
+ AND $7,R6, R1
BEQ R1, b2
MOVB -1(R7), R8
ADDU $-1, R7
- MOVB R8, -1(R11)
- ADDU $-1, R11
+ MOVB R8, -1(R6)
+ ADDU $-1, R6
JMP b1
+
b2:
- ADDU $15,R10, R3
+ AND $7, R7, R1
+ BNE R1, bun2
+
+ ADDU $31,R5, R3
b3:
SGTU R7,R3, R1
BEQ R1, b4
- MOVW -4(R7), R8
- MOVW -8(R7), R9
- MOVW R8, -4(R11)
- MOVW -12(R7), R8
- MOVW R9, -8(R11)
- MOVW -16(R7), R9
- ADDU $-16, R7
- MOVW R8, -12(R11)
- MOVW R9, -16(R11)
- ADDU $-16, R11
+ MOVV -8(R7), R8
+ MOVV -16(R7), R9
+ MOVV R8, -8(R6)
+ MOVV -24(R7), R8
+ MOVV R9, -16(R6)
+ MOVV -32(R7), R9
+ ADDU $-32, R7
+ MOVV R8, -24(R6)
+ MOVV R9, -32(R6)
+ ADDU $-32, R6
JMP b3
b4:
- ADDU $3,R10, R3
+ ADDU $3,R5, R3
b5:
SGTU R7,R3, R1
BEQ R1, bout
MOVW -4(R7), R8
ADDU $-4, R7
- MOVW R8, -4(R11)
- ADDU $-4, R11
+ MOVW R8, -4(R6)
+ ADDU $-4, R6
JMP b5
+bun2:
+ ADDU $31,R5, R3
+bun3:
+ SGTU R7,R3, R1
+ BEQ R1, bun4
+ MOVVL -8(R7), R8
+ MOVVR -1(R7), R8
+ MOVVL -16(R7), R9
+ MOVVR -9(R7), R9
+ MOVV R8, -8(R6)
+ MOVVL -24(R7), R8
+ MOVVR -17(R7), R8
+ MOVV R9, -16(R6)
+ MOVVL -32(R7), R9
+ MOVVR -25(R7), R9
+ ADDU $-32, R7
+ MOVV R8, -24(R6)
+ MOVV R9, -32(R6)
+ ADDU $-32, R6
+ JMP bun3
+
+bun4:
+ ADDU $3,R5, R3
+bun5:
+ SGTU R7,R3, R1
+ BEQ R1, bout
+ MOVWL -4(R7), R8
+ MOVWR -1(R7), R8
+ ADDU $-4, R7
+ MOVW R8, -4(R6)
+ ADDU $-4, R6
+ JMP bun5
+
bout:
- BEQ R7,R10, ret
+ BEQ R7,R5, ret
MOVB -1(R7), R8
ADDU $-1, R7
- MOVB R8, -1(R11)
- ADDU $-1, R11
+ MOVB R8, -1(R6)
+ ADDU $-1, R6
JMP bout
ret:
M carrera/memset.s => carrera/memset.s +21 -32
@@ 1,16 1,10 @@
/*
- * R4000 double-word version. Only works in kernel mode.
- * Requires low-core support to save R5 in a 64-bit hole.
+ * R4000-compatible memset uses V instructions.
+ * The kernel uses the 3000 compilers, but we can
+ * use this procedure for speed.
*/
-
-/*
- * R4000 instructions
- */
-#define LD(base, rt) WORD $((067<<26)|((base)<<21)|((rt)<<16))
-#define STD(rt, offset, base) WORD $((077<<26)|((base)<<21)|((rt)<<16)|((offset)&0xFFFF))
-
- TEXT memset(SB),$16 /* $16 for hole to build temporary */
- MOVW R1, 0(FP)
+ TEXT memset(SB),$16
+ MOVW R1, 0(FP)
MOVW n+8(FP), R3 /* R3 is count */
MOVW p+0(FP), R4 /* R4 is pointer */
@@ 19,35 13,30 @@
/*
* if not at least 8 chars,
- * don't even mess around.
+ * dont even mess around.
* 7 chars to guarantee any
- * rounding up to a doubleword
+ * rounding up to a word
* boundary and 8 characters
* to get at least maybe one
- * full doubleword store.
+ * full word store.
*/
SGT $8,R3, R1
BNE R1, out
/*
- * turn R5 into a doubleword of characters.
- * build doubleword on stack; can't use OR on 64-bit registers
+ * turn R5 into a doubleword of characters
*/
AND $0xff, R5
- SLL $8,R5, R1
+ SLLV $8,R5, R1
+ OR R1, R5
+ SLLV $16,R5, R1
OR R1, R5
- SLL $16,R5, R1
+ SLLV $32,R5, R1
OR R1, R5
- MOVW R29, R1
- ADD $8, R1
- AND $~7, R1
- MOVW R5, 0(R1)
- MOVW R5, 4(R1)
- LD (1, 5)
-
+
/*
* store one byte at a time until pointer
- * is aligned on a doubleword boundary
+ * is alligned on a doubleword boundary
*/
l1:
AND $7,R4, R1
@@ 58,23 47,23 @@ l1:
/*
* turn R3 into end pointer-31
- * store 32 at a time while there's room
+ * store 32 at a time while theres room
*/
l2:
ADDU $-31,R6, R3
l3:
SGTU R3,R4, R1
BEQ R1, l4
- STD (5, 0, 4)
- STD (5, 8, 4)
+ MOVV R5, 0(R4)
+ MOVV R5, 8(R4)
ADDU $32, R4
- STD (5, -16, 4)
- STD (5, -8, 4)
+ MOVV R5, -16(R4)
+ MOVV R5, -8(R4)
JMP l3
/*
* turn R3 into end pointer-3
- * store 4 at a time while there's room
+ * store 4 at a time while theres room
*/
l4:
ADDU $-3,R6, R3
M carrera/screen.c => carrera/screen.c +186 -55
@@ 7,7 7,9 @@
#include "ureg.h"
#include "../port/error.h"
-#include <libg.h>
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
#include "screen.h"
#define MINX 8
@@ 27,8 29,9 @@ struct Dac
};
char s1[] = { 0x00, 0x00, 0xC0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+#define Backgnd 0x00
-extern Subfont defont0;
+ Memsubfont *memdefont;
static ulong rep(ulong, int);
struct{
@@ 38,28 41,108 @@ struct{
Lock screenlock;
-Bitmap gscreen =
+Point ZP = {0, 0};
+
+static Memdata hwcursordata;
+
+static Memdata gscreendata =
{
- { 0, 0, 1597, 1234 },
- { 0, 0, 1597, 1234 },
- 3,
- Screenvirt+0x000178D0,
- 0,
- 512,
- 0
+ nil,
+ (ulong*)(Screenvirt+0x000178D0),
+ 1,
+};
+
+Memimage gscreen =
+{
+ { 0, 0, 1597, 1234 }, /* r */
+ { 0, 0, 1597, 1234 }, /* clipr */
+ 3, /* ldepth */
+ 0, /* repl */
+ &gscreendata, /* data */
+ 0, /* zero */
+ 512, /* width */
+ 0, /* layer */
};
-static Bitmap hwcursor=
+static Memimage hwcursor=
{
{0, 0, 64, 64},
{0, 0, 64, 64},
1,
- 0, /* base filled in by malloc when needed */
+ 0,
+ &hwcursordata, /* base filled in by malloc when needed */
0,
4,
0,
};
+ulong consbits = ~0;
+Memdata consdata = {
+ nil,
+ &consbits
+};
+Memimage conscol =
+{
+ { 0, 0, 1, 1 },
+ { -100000, -100000, 100000, 100000 },
+ 3,
+ 1,
+ &consdata,
+ 0,
+ 1
+};
+
+ulong onesbits = ~0;
+Memdata onesdata = {
+ nil,
+ &onesbits,
+};
+Memimage xones =
+{
+ { 0, 0, 1, 1 },
+ { -100000, -100000, 100000, 100000 },
+ 3,
+ 1,
+ &onesdata,
+ 0,
+ 1
+};
+Memimage *memones = &xones;
+
+ulong zerosbits = 0;
+Memdata zerosdata = {
+ nil,
+ &zerosbits,
+};
+Memimage xzeros =
+{
+ { 0, 0, 1, 1 },
+ { -100000, -100000, 100000, 100000 },
+ 3,
+ 1,
+ &zerosdata,
+ 0,
+ 1
+};
+Memimage *memzeros = &xzeros;
+
+ulong backbits = (Backgnd<<24)|(Backgnd<<16)|(Backgnd<<8)|Backgnd;
+Memdata backdata = {
+ nil,
+ &backbits
+};
+Memimage xback =
+{
+ { 0, 0, 1, 1 },
+ { -100000, -100000, 100000, 100000 },
+ 3,
+ 1,
+ &backdata,
+ 0,
+ 1
+};
+Memimage *back = &xback;
+
static Rectangle window;
static Point curpos;
static int h, w;
@@ 68,31 151,35 @@ void
screenwin(void)
{
Dac *d;
- Point p;
- int i, y;
+ Point p, q;
+ int y;
Cursor zero;
+ char *greet;
memset((void*)Screenvirt, 0xff, 3*1024*1024);
for(y=gscreen.r.min.y; y<gscreen.r.max.y; y++)
- memset(byteaddr(&gscreen, Pt(gscreen.r.min.x, y)), 0xa0, Dx(gscreen.r));
+ memset(byteaddr(&gscreen, Pt(gscreen.r.min.x, y)), 0xba, Dx(gscreen.r));
- w = defont0.info[' '].width;
- h = defont0.height;
+ w = memdefont->info[' '].width;
+ h = memdefont->height;
window.min = Pt(100, 100);
- window.max = add(window.min, Pt(10+w*120, 10+h*60));
-
- bitblt(&gscreen, add(window.min, Pt(5, 5)), &gscreen, window, F);
- bitblt(&gscreen, window.min, &gscreen, window, Zero);
- border(&gscreen, window, 4, F);
- window = inset(window, 5);
- for(i = 0; i < h+6; i += 2) {
- y = window.min.y+i;
- bitblt(&gscreen, Pt(window.min.x, y),
- &gscreen, Rect(window.min.x, y, window.max.x, y+1), F);
- }
- p = add(window.min, Pt(10, 2));
- subfstring(&gscreen, p, &defont0, "Brazil Console ", S);
+ window.max = addpt(window.min, Pt(10+w*120, 10+h*60));
+
+ memimagedraw(&gscreen, window, memones, ZP, memones, ZP);
+ window = insetrect(window, 4);
+ memimagedraw(&gscreen, window, back, ZP, memones, ZP);
+ /* hack to get a grey color */
+ memzeros->data->data[0] = 0x33333333;
+ memimagedraw(&gscreen, Rect(window.min.x, window.min.y,
+ window.max.x, window.min.y+h+5+6), memzeros, ZP, memones, ZP);
+ memzeros->data->data[0] = 0;
+ window = insetrect(window, 5);
+
+ greet = " Brazil Console: Draw version ";
+ p = addpt(window.min, Pt(10, 0));
+ q = memsubfontwidth(memdefont, greet);
+ memimagestring(&gscreen, p, &conscol, memdefont, greet);
window.min.y += h+6;
curpos = window.min;
window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
@@ 152,7 239,7 @@ dacinit(void)
for(i = 0; i < 0x400; i++)
d->cr2 = 0xff;
- graphicscmap(0);
+ drawcmap(0);
/* Overlay Palette Ram */
d->cr0 = 0x00;
@@ 178,10 265,11 @@ screeninit(void)
{
dacinit();
- bitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, 0);
+ memdefont = getmemdefont();
+
out.pos.x = MINX;
out.pos.y = 0;
- out.bwid = defont0.info[' '].width;
+ out.bwid = memdefont->info[' '].width;
screenwin();
}
@@ 190,21 278,51 @@ static void
scroll(void)
{
int o;
+ Point p;
Rectangle r;
- o = 5*h;
- r = Rpt(Pt(window.min.x, window.min.y+o), window.max);
- bitblt(&gscreen, window.min, &gscreen, r, S);
+ o = 8*h;
+ r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
+ p = Pt(window.min.x, window.min.y+o);
+ memimagedraw(&gscreen, r, &gscreen, p, memones, p);
r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
- bitblt(&gscreen, r.min, &gscreen, r, Zero);
+ memimagedraw(&gscreen, r, back, ZP, memones, ZP);
+
curpos.y -= o;
}
+/*
+ * export screen to devdraw
+ */
+ulong*
+attachscreen(Rectangle *r, int *ld, int *width)
+{
+ *r = gscreen.r;
+ *ld = gscreen.ldepth;
+ *width = gscreen.width;
+
+ return gscreendata.data;
+}
+
+/*
+ * update screen (no-op: frame buffer is direct-mapped)
+ */
+void
+flushmemscreen(Rectangle)
+{
+}
+
static void
screenputc(char *buf)
{
- int pos;
+ Point p;
+ int w, pos;
Rectangle r;
+ static int *xp;
+ static int xbuf[256];
+
+ if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
+ xp = xbuf;
switch(buf[0]) {
case '\n':
@@ 214,27 332,39 @@ screenputc(char *buf)
screenputc("\r");
break;
case '\r':
+ xp = xbuf;
curpos.x = window.min.x;
break;
case '\t':
+ p = memsubfontwidth(memdefont, " ");
+ w = p.x;
+ *xp++ = curpos.x;
pos = (curpos.x-window.min.x)/w;
pos = 8-(pos%8);
+ r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
+ memimagedraw(&gscreen, r, back, back->r.min, memones, back->r.min);
curpos.x += pos*w;
break;
case '\b':
- if(curpos.x-w >= 0){
- r.min.x = curpos.x-w;
- r.max.x = curpos.x;
- r.min.y = curpos.y;
- r.max.y = curpos.y+defont0.height;
- bitblt(&gscreen, r.min, &gscreen, r, Zero);
- curpos.x -= w;
- }
+ if(xp <= xbuf)
+ break;
+ xp--;
+ r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
+ memimagedraw(&gscreen, r, back, back->r.min, memones, back->r.min);
+ curpos.x = *xp;
break;
default:
+ p = memsubfontwidth(memdefont, buf);
+ w = p.x;
+
if(curpos.x >= window.max.x-w)
screenputc("\n");
- curpos = subfstring(&gscreen, curpos, &defont0, buf, S);
+
+ *xp++ = curpos.x;
+ r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h);
+ memimagedraw(&gscreen, r, back, back->r.min, memones, back->r.min);
+ memimagestring(&gscreen, curpos, &conscol, memdefont, buf);
+ curpos.x += w;
}
}
@@ 381,17 511,18 @@ setcursor(Cursor *curs)
*p = curs->clr[2*i];
*(p+1) = curs->clr[2*i+1];
}
- hwcursor.base = (ulong *)malloc(1024);
- if(hwcursor.base == 0)
+ hwcursor.data->data = (ulong *)malloc(1024);
+ if(hwcursor.data->data == 0)
error(Enomem);
/* hw cursor is 64x64 with hot point at (32,32) */
- org = add(Pt(32,32), curs->offset);
- for(x = 0; x < 16; x++)
- for(y = 0; y < 16; y++) {
+ org = addpt(Pt(32,32), curs->offset);
+ for(y = 0; y < 16; y++)
+ for(x = 0; x < 16; x++) {
spix = (s[y]>>(31-(x&0x1F)))&1;
cpix = (c[y]>>(31-(x&0x1F)))&1;
dpix = (spix<<1) | cpix;
- point(&hwcursor, add(Pt(x,y), org), dpix, S);
+ /* point(&hwcursor, addpt(Pt(x,y), org), dpix, S), by hand */
+ *byteaddr(&hwcursor, Pt(x+org.x, y+org.y)) |= dpix<<(6-(2*((x+org.x)&3)));
}
d = DAC;
@@ 409,14 540,14 @@ setcursor(Cursor *curs)
d->cr1 = 0x04;
d->cr0 = 0x00;
for(x = 0; x < 1024; x++)
- d->cr2 = ((uchar *)hwcursor.base)[x];
+ d->cr2 = ((uchar *)hwcursor.data->data)[x];
/* set y back */
d->cr1 = 0x03;
d->cr0 = 0x03;
d->cr2 = ylow;
d->cr2 = yhigh;
- free(hwcursor.base);
+ free(hwcursor.data->data);
}
int
M carrera/trap.c => carrera/trap.c +55 -24
@@ 60,26 60,49 @@ char *fpexcname(Ureg*, ulong, char*);
void (*eisadma[8])(void); /* Eisa dma chain vectors */
-char *regname[]={
- "STATUS", "PC",
- "SP", "CAUSE",
- "BADADDR", "TLBVIRT",
- "HI", "LO",
- "R31", "R30",
- "R28", "R27",
- "R26", "R25",
- "R24", "R23",
- "R22", "R21",
- "R20", "R19",
- "R18", "R17",
- "R16", "R15",
- "R14", "R13",
- "R12", "R11",
- "R10", "R9",
- "R8", "R7",
- "R6", "R5",
- "R4", "R3",
- "R2", "R1",
+struct
+{
+ char *name;
+ int off;
+} regname[]={
+ "STATUS", Ureg_status,
+ "PC", Ureg_pc,
+ "SP", Ureg_sp,
+ "CAUSE", Ureg_cause,
+ "BADADDR", Ureg_badvaddr,
+ "TLBVIRT", Ureg_tlbvirt,
+ "HI", Ureg_hi,
+ "LO", Ureg_lo,
+ "R31", Ureg_r31,
+ "R30", Ureg_r30,
+ "R28", Ureg_r28,
+ "R27", Ureg_r27,
+ "R26", Ureg_r26,
+ "R25", Ureg_r25,
+ "R24", Ureg_r24,
+ "R23", Ureg_r23,
+ "R22", Ureg_r22,
+ "R21", Ureg_r21,
+ "R20", Ureg_r20,
+ "R19", Ureg_r19,
+ "R18", Ureg_r18,
+ "R17", Ureg_r17,
+ "R16", Ureg_r16,
+ "R15", Ureg_r15,
+ "R14", Ureg_r14,
+ "R13", Ureg_r13,
+ "R12", Ureg_r12,
+ "R11", Ureg_r11,
+ "R10", Ureg_r10,
+ "R9", Ureg_r9,
+ "R8", Ureg_r8,
+ "R7", Ureg_r7,
+ "R6", Ureg_r6,
+ "R5", Ureg_r5,
+ "R4", Ureg_r4,
+ "R3", Ureg_r3,
+ "R2", Ureg_r2,
+ "R1", Ureg_r1,
};
static char *
@@ 470,21 493,29 @@ dumpstack(void)
print("\n");
}
+ulong
+R(Ureg *ur, int i)
+{
+ uchar *s;
+
+ s = (uchar*)ur;
+ return *(ulong*)(s+regname[i].off-Uoffset);
+}
+
void
dumpregs(Ureg *ur)
{
int i;
- ulong *l;
if(up)
print("registers for %s %d\n", up->text, up->pid);
else
print("registers for kernel\n");
- l = &ur->status;
- for(i=0; i<nelem(regname); i+=2, l+=2)
+ for(i=0; i<nelem(regname); i+=2)
print("%s\t0x%.8lux\t%s\t0x%.8lux\n",
- regname[i], l[0], regname[i+1], l[1]);
+ regname[i].name, R(ur, i),
+ regname[i+1].name, R(ur, i+1));
}
int
M pc/cga.c => pc/cga.c +31 -49
@@ 3,7 3,6 @@
#include "mem.h"
#include "dat.h"
#include "fns.h"
-#include "io.h"
#include "../port/error.h"
enum {
@@ 15,10 14,9 @@ enum {
#define CGASCREENBASE ((uchar*)KADDR(0xB8000))
-static int pos;
+static int cgapos;
static int screeninitdone;
-QLock screenlock;
-void (*vgascreenputc)(char*);
+static Lock cgascreenlock;
static uchar
cgaregr(int index)
@@ 37,9 35,9 @@ cgaregw(int index, int data)
static void
movecursor(void)
{
- cgaregw(0x0E, (pos/2>>8) & 0xFF);
- cgaregw(0x0F, pos/2 & 0xFF);
- CGASCREENBASE[pos+1] = Attr;
+ cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
+ cgaregw(0x0F, cgapos/2 & 0xFF);
+ CGASCREENBASE[cgapos+1] = Attr;
}
static void
@@ 48,28 46,28 @@ cgascreenputc(int c)
int i;
if(c == '\n'){
- pos = pos/Width;
- pos = (pos+1)*Width;
+ cgapos = cgapos/Width;
+ cgapos = (cgapos+1)*Width;
}
else if(c == '\t'){
- i = 8 - ((pos/2)&7);
+ i = 8 - ((cgapos/2)&7);
while(i-->0)
cgascreenputc(' ');
}
else if(c == '\b'){
- if(pos >= 2)
- pos -= 2;
+ if(cgapos >= 2)
+ cgapos -= 2;
cgascreenputc(' ');
- pos -= 2;
+ cgapos -= 2;
}
else{
- CGASCREENBASE[pos++] = c;
- CGASCREENBASE[pos++] = Attr;
+ CGASCREENBASE[cgapos++] = c;
+ CGASCREENBASE[cgapos++] = Attr;
}
- if(pos >= Width*Height){
+ if(cgapos >= Width*Height){
memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
memset(&CGASCREENBASE[Width*(Height-1)], 0, Width);
- pos = Width*(Height-1);
+ cgapos = Width*(Height-1);
}
movecursor();
}
@@ 77,46 75,30 @@ cgascreenputc(int c)
void
screeninit(void)
{
- pos = cgaregr(0x0E)<<8;
- pos |= cgaregr(0x0F);
- pos *= 2;
+ cgapos = cgaregr(0x0E)<<8;
+ cgapos |= cgaregr(0x0F);
+ cgapos *= 2;
screeninitdone = 1;
}
-void
-screenputs(char* s, int n)
+static void
+cgascreenputs(char* s, int n)
{
- int i;
- Rune r;
- char buf[4];
-
if(!islo()){
- if(!canqlock(&screenlock))
+ /*
+ * Don't deadlock trying to
+ * print in an interrupt.
+ */
+ if(!canlock(&cgascreenlock))
return;
}
else
- qlock(&screenlock);
+ lock(&cgascreenlock);
- if(vgascreenputc == nil){
- while(n-- > 0)
- cgascreenputc(*s++);
- qunlock(&screenlock);
- return;
- }
-
- while(n > 0) {
- i = chartorune(&r, s);
- if(i == 0){
- s++;
- --n;
- continue;
- }
- memmove(buf, s, i);
- buf[i] = 0;
- n -= i;
- s += i;
- vgascreenputc(buf);
- }
+ while(n-- > 0)
+ cgascreenputc(*s++);
- qunlock(&screenlock);
+ unlock(&cgascreenlock);
}
+
+void (*screenputs)(char*, int) = cgascreenputs;
M pc/dat.h => pc/dat.h +1 -1
@@ 144,7 144,7 @@ struct Mach
int machno; /* physical id of processor */
ulong splpc; /* pc of last caller to splhi */
- void* pdb; /* page directory base for this processor (va) */
+ ulong* pdb; /* page directory base for this processor (va) */
Tss* tss; /* tss for this processor */
Segdesc gdt[6]; /* gdt for this processor */
M pc/devether.c => pc/devether.c +15 -9
@@ 230,13 230,15 @@ etherwrite(Chan* chan, void* buf, long n, ulong)
Ether *ether;
Block *bp;
- if(n > ETHERMAXTU)
- error(Ebadarg);
-
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid)
return netifwrite(ether, chan, buf, n);
+ if(n > ETHERMAXTU)
+ error(Etoobig);
+ if(n < ETHERMINTU)
+ error(Etoosmall);
+
bp = allocb(n);
if(waserror()){
freeb(bp);
@@ 257,11 259,6 @@ etherbwrite(Chan* chan, Block* bp, ulong)
long n;
n = BLEN(bp);
- if(n > ETHERMAXTU){
- freeb(bp);
- error(Ebadarg);
- }
-
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid){
n = netifwrite(ether, chan, bp->rp, n);
@@ 269,6 266,15 @@ etherbwrite(Chan* chan, Block* bp, ulong)
return n;
}
+ if(n > ETHERMAXTU){
+ freeb(bp);
+ error(Ebadarg);
+ }
+ if(n < ETHERMINTU){
+ freeb(bp);
+ error(Etoosmall);
+ }
+
return etheroq(ether, bp);
}
@@ 352,7 358,7 @@ etherreset(void)
i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
if(ether->mem)
- i += sprint(buf+i, " addr 0x%luX", ether->mem & ~KZERO);
+ i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem));
if(ether->size)
i += sprint(buf+i, " size 0x%luX", ether->size);
i += sprint(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX",
M pc/devi82365.c => pc/devi82365.c +1 -0
@@ 357,6 357,7 @@ pcmmap(int slotno, ulong offset, int len, int attr)
m->len = 0;
}
m->isa = umbmalloc(0, len, Mgran)&~KZERO;
+print("m->isa = 0x%uX, %d\n", m->isa, len);
if(m->isa == 0){
print("pcmmap: out of isa space\n");
unlock(&pp->mlock);
M pc/devvga.c => pc/devvga.c +162 -1139
@@ 1,129 1,40 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-
-#include <libg.h>
-#include "screen.h"
-#include "vga.h"
-
-enum
-{
- /* default footprint is 64k */
- Footshift= 16,
- Footprint= 1<<Footshift,
-};
/*
- * screen memory addresses
*/
-#define SCREENMEM (0xA0000 | KZERO)
-
-static ulong screenmem = SCREENMEM;
-static int footprint = Footprint;
-static int footshift = Footshift;
-static int screendisabled;
-
-/* imported */
-extern Subfont defont0;
-extern Cursor curs; /* barf */
-
-/* exported */
-Bitmap gscreen;
-Lock palettelock; /* access to DAC registers */
-Cursor curcursor; /* current cursor */
-static Lock vgaxlock; /* access to index registers */
-
-/* vga screen */
-extern QLock screenlock;
-static ulong colormap[Pcolours][3];
-static Lock myscreenlock;
-
-/* system window */
-static Rectangle window;
-static int h, w;
-static Point curpos;
-
-static void nopage(int);
-
-static Vgac vga = {
- "vga",
- nopage,
-
- 0,
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include "screen.h"
+
+enum {
+ Qdir,
+ Qvgaiob,
+ Qvgaiow,
+ Qvgaiol,
+ Qvgactl,
};
-static Vgac *vgactlr = &vga; /* available VGA ctlrs */
-static Vgac *vgac = &vga; /* current VGA ctlr */
-static Hwgc *hwgctlr; /* available HWGC's */
-Hwgc *hwgc; /* current HWGC */
-
-static char interlaced[2];
-
-/*
- * work areas for bitblting screen characters, scrolling, and cursor redraw
- */
-Bitmap chwork;
-Bitmap scrollwork;
-Bitmap cursorwork;
-
-/* predefined for the stupid compiler */
-static void setscreen(int, int, int);
-static void screenputc(char*);
-static void scroll(void);
-static void workinit(Bitmap*, int, int);
-extern void screenload(Rectangle, uchar*, int, int, int);
-extern void screenunload(Rectangle, uchar*, int, int, int);
-static void cursorlock(Rectangle);
-static void cursorunlock(void);
-static void cursorinit(void);
-
-extern void (*vgascreenputc)(char*);
-extern int graphicssubtile(uchar*, int, int, Rectangle, Rectangle, uchar**);
-
-/*
- * vga device
- */
-enum
-{
- Qdir = 0,
- Qvgaiob = 1,
- Qvgaiow = 2,
- Qvgaiol = 3,
- Qvgactl = 4,
-};
-Dirtab vgadir[]={
- "vgaiob", { Qvgaiob }, 0, 0666,
- "vgaiow", { Qvgaiow }, 0, 0666,
- "vgaiol", { Qvgaiol }, 0, 0666,
- "vgactl", { Qvgactl }, 0, 0666,
+static Dirtab vgadir[] = {
+ "vgaiob", { Qvgaiob, 0 }, 0, 0660,
+ "vgaiow", { Qvgaiow, 0 }, 0, 0660,
+ "vgaiol", { Qvgaiol, 0 }, 0, 0660,
+ "vgactl", { Qvgactl, 0 }, 0, 0660,
};
static void
vgareset(void)
{
- cursor.disable++;
conf.monitor = 1;
}
-static void
-vgainit(void)
-{
- int i;
- ulong *l;
-
- /*
- * swizzle the font longs.
- */
- l = defont0.bits->base;
- for(i = defont0.bits->width*Dy(defont0.bits->r); i > 0; i--, l++)
- *l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24);
-}
-
static Chan*
-vgaattach(char *spec)
+vgaattach(char* spec)
{
if(*spec && strcmp(spec, "0"))
error(Eio);
@@ 131,19 42,19 @@ vgaattach(char *spec)
}
int
-vgawalk(Chan *c, char *name)
+vgawalk(Chan* c, char* name)
{
return devwalk(c, name, vgadir, nelem(vgadir), devgen);
}
static void
-vgastat(Chan *c, char *dp)
+vgastat(Chan* c, char* dp)
{
devstat(c, dp, vgadir, nelem(vgadir), devgen);
}
static Chan*
-vgaopen(Chan *c, int omode)
+vgaopen(Chan* c, int omode)
{
return devopen(c, omode, vgadir, nelem(vgadir), devgen);
}
@@ 153,223 64,181 @@ vgaclose(Chan*)
{
}
-static int
-checkvgaport(int port, int len)
-{
- if((port == 0x102 || port == 0x46E8) && len == 1)
- return 0;
- if(port >= 0x3B0 && port+len < 0x3E0)
- return 0;
- return -1;
-}
-
static long
-vgaread(Chan *c, void *buf, long n, ulong offset)
+vgaread(Chan* c, void* a, long n, ulong offset)
{
- int port;
- uchar *cp;
- char cbuf[128];
+ int len, port;
+ char *p, *s;
ushort *sp;
ulong *lp;
- Vgac *vgacp;
+ VGAscr *scr;
+
+ switch(c->qid.path & ~CHDIR){
- switch(c->qid.path&~CHDIR){
case Qdir:
- return devdirread(c, buf, n, vgadir, nelem(vgadir), devgen);
+ return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
+
case Qvgactl:
- if(vgascreenputc == nil)
- return readstr(offset, buf, n, "type: cga\n");
- vgacp = vgac;
- port = sprint(cbuf, "type: %s\n", vgacp->name);
- port += sprint(cbuf+port, "size: %dx%dx%d%s\n",
- gscreen.r.max.x, gscreen.r.max.y,
- 1<<gscreen.ldepth, interlaced);
- port += sprint(cbuf+port, "hwgc: ");
- if(hwgc)
- port += sprint(cbuf+port, "%s\n", hwgc->name);
+ scr = &vgascreen[0];
+
+ p = malloc(READSTR);
+ if(waserror()){
+ free(p);
+ nexterror();
+ }
+ 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",
+ scr->gscreen->r.max.x, scr->gscreen->r.max.y,
+ 1<<scr->gscreen->ldepth);
+ if(scr->cur)
+ s = scr->cur->name;
else
- port += sprint(cbuf+port, "off\n");
- sprint(cbuf+port, "addr: 0x%lux\n", screenmem&~KZERO);
- return readstr(offset, buf, n, cbuf);
+ s = "off";
+ len += snprint(p+len, READSTR-len, "hwgc: %s\n", s);
+ snprint(p+len, READSTR-len, "addr: 0x%lux\n", scr->aperture);
+
+ n = readstr(offset, a, n, p);
+ poperror();
+ free(p);
+
+ return n;
+
case Qvgaiob:
port = offset;
- /*if(checkvgaport(port, n))
- error(Eperm);*/
- for(cp = buf; port < offset+n; port++)
- *cp++ = vgai(port);
+ for(p = a; port < offset+n; port++)
+ *p++ = inb(port);
return n;
+
case Qvgaiow:
- if((n & 01) || (offset & 01))
+ if((n & 0x01) || (offset & 0x01))
error(Ebadarg);
n /= 2;
- for (sp = buf, port=offset; port<offset+n; port+=2)
+ sp = a;
+ for(port = offset; port < offset+n; port += 2)
*sp++ = ins(port);
return n*2;
+
case Qvgaiol:
- if((n & 03) || (offset & 03))
+ if((n & 0x03) || (offset & 0x03))
error(Ebadarg);
n /= 4;
- for (lp = buf, port=offset; port<offset+n; port+=4)
+ lp = a;
+ for(port = offset; port < offset+n; port += 4)
*lp++ = inl(port);
return n*4;
+
+ default:
+ error(Egreg);
+ break;
}
- error(Eperm);
+
return 0;
}
static void
-vgactl(char *arg)
+vgactl(char* a)
{
- int n;
- ulong x, y, z;
- char *cp, *field[4];
- Hwgc *hwgcp;
- Vgac *vgacp;
- ulong mem, size, align;
+ int align, i, n, size, x, y, z;
+ char *field[4], *p;
+ VGAscr *scr;
+ extern VGAdev *vgadev[];
+ extern VGAcur *vgacur[];
- n = parsefields(arg, field, 4, " ");
+ n = parsefields(a, field, 4, " ");
if(n < 2)
error(Ebadarg);
- if(strcmp(field[0], "disable") == 0){
- screendisabled = 1;
- }
- else if(strcmp(field[0], "enable") == 0){
- screendisabled = 0;
- }
- else if(strcmp(field[0], "hwgc") == 0){
+ scr = &vgascreen[0];
+ if(strcmp(field[0], "hwgc") == 0){
if(n < 2)
error(Ebadarg);
if(strcmp(field[1], "off") == 0){
- if(hwgc){
- hwgc->disable();
- hwgc = 0;
- cursoron(1);
+ lock(&cursor);
+ if(scr->cur){
+ if(scr->cur->disable)
+ scr->cur->disable(scr);
+ scr->cur = nil;
}
+ unlock(&cursor);
return;
}
- for(hwgcp = hwgctlr; hwgcp; hwgcp = hwgcp->link){
- if(strcmp(field[1], hwgcp->name) == 0){
- if(hwgc)
- hwgc->disable();
- else
- cursoroff(1);
- hwgc = hwgcp;
- hwgc->enable();
- setcursor(&curs);
- cursoron(1);
- return;
- }
+ for(i = 0; vgacur[i]; i++){
+ if(strcmp(field[1], vgacur[i]->name))
+ continue;
+ lock(&cursor);
+ if(scr->cur && scr->cur->disable)
+ scr->cur->disable(scr);
+ scr->cur = vgacur[i];
+ if(scr->cur->enable)
+ scr->cur->enable(scr);
+ unlock(&cursor);
+ return;
}
}
else if(strcmp(field[0], "type") == 0){
if(n < 2)
error(Ebadarg);
- for(vgacp = vgactlr; vgacp; vgacp = vgacp->link){
- if(strcmp(field[1], vgacp->name) == 0){
- vgac = vgacp;
- return;
- }
+
+ for(i = 0; vgadev[i]; i++){
+ if(strcmp(field[1], vgadev[i]->name))
+ continue;
+ if(scr->dev && scr->dev->disable)
+ scr->dev->disable(scr);
+ scr->dev = vgadev[i];
+ if(scr->dev->enable)
+ scr->dev->enable(scr);
+ return;
}
}
else if(strcmp(field[0], "size") == 0){
if(n < 2)
error(Ebadarg);
- x = strtoul(field[1], &cp, 0);
+ x = strtoul(field[1], &p, 0);
if(x == 0 || x > 2048)
error(Ebadarg);
+ if(*p)
+ p++;
- if(*cp)
- cp++;
- y = strtoul(cp, &cp, 0);
+ y = strtoul(p, &p, 0);
if(y == 0 || y > 2048)
error(Ebadarg);
+ if(*p)
+ p++;
- if(*cp)
- cp++;
- switch(strtoul(cp, &cp, 0)){
+ switch(strtoul(p, &p, 0)){
case 8:
- z = 3; break;
- case 1:
- z = 0; break;
+ z = 3;
+ break;
+
default:
z = 0;
error(Ebadarg);
}
- interlaced[0] = *cp;
cursoroff(1);
- setscreen(x, y, z);
+ if(screensize(x, y, z))
+ error(Egreg);
+ vgascreenwin(scr);
cursoron(1);
return;
}
else if(strcmp(field[0], "linear") == 0){
if(n < 2)
error(Ebadarg);
+
size = strtoul(field[1], 0, 0);
if(n < 3)
align = 0;
else
align = strtoul(field[2], 0, 0);
-
- /* see if it fits in the usual place */
- if(size <= Footprint){
- if(screenmem != SCREENMEM)
- upafree(screenmem, footprint);
- screenmem = SCREENMEM;
- if(size == 0){
- footprint = Footprint;
- footshift = Footshift;
- } else {
- footprint = size;
- for(n = 0; n < 31; n++)
- if((1<<n) >= footprint)
- break;
- footshift = n;
- }
- gscreen.base = (void*)screenmem;
- return;
- }
-
- /* grab new space */
- if(align == 0 || (screenmem % (align-1)) == 0){
- if(footprint >= size)
- return;
- } else {
- int s, e;
-
- s = screenmem & ~KZERO;
- e = s + footprint;
- s = ROUND(s, align);
- if(e >= s + size)
- return;
- }
-
- mem = 0;
- if(vgac->linear)
- vgac->linear(&mem, &size, &align);
- else
- mem = upamalloc(0, size, align);
- if(mem == 0)
+ if(screenaperture(size, align))
error("not enough free address space");
-
- /*
- * Be very careful here, upamalloc now returns a
- * PHYSICAL address. This won't work once devices
- * start mapping PCI framebuffers at the address
- * the BIOS sets, but that hopefully will be after
- * conversion to the Draw kernel.
- */
- if(screenmem != SCREENMEM)
- upafree(screenmem, footprint);
- screenmem = (ulong)KADDR(mem);
- gscreen.base = (void*)screenmem;
- footprint = size;
- for(n = 0; n < 31; n++)
- if((1<<n) >= footprint)
- break;
- footshift = n;
return;
}
@@ 377,47 246,62 @@ vgactl(char *arg)
}
static long
-vgawrite(Chan *c, void *buf, long n, ulong offset)
+vgawrite(Chan* c, void* a, long n, ulong offset)
{
int port;
- uchar *cp;
- char cbuf[64];
+ char *p;
ushort *sp;
ulong *lp;
- switch(c->qid.path&~CHDIR){
+ switch(c->qid.path & ~CHDIR){
+
case Qdir:
error(Eperm);
+
case Qvgactl:
- if(offset != 0 || n >= sizeof(cbuf))
+ if(offset || n >= READSTR)
error(Ebadarg);
- memmove(cbuf, buf, n);
- cbuf[n] = 0;
- vgactl(cbuf);
+ p = malloc(READSTR);
+ if(waserror()){
+ free(p);
+ nexterror();
+ }
+ memmove(p, a, n);
+ p[n] = 0;
+ vgactl(p);
+ poperror();
+ free(p);
return n;
+
case Qvgaiob:
- port = offset;
- /*if(checkvgaport(port, n))
- error(Eperm);*/
- for(cp = buf; port < offset+n; port++)
- vgao(port, *cp++);
+ p = a;
+ for(port = offset; port < offset+n; port++)
+ outb(port, *p++);
return n;
+
case Qvgaiow:
if((n & 01) || (offset & 01))
error(Ebadarg);
n /= 2;
- for (sp = buf, port=offset; port<offset+n; port+=2)
+ sp = a;
+ for(port = offset; port < offset+n; port += 2)
outs(port, *sp++);
return n*2;
+
case Qvgaiol:
- if((n & 03) || (offset & 03))
+ if((n & 0x03) || (offset & 0x03))
error(Ebadarg);
n /= 4;
- for (lp = buf, port=offset; port<offset+n; port+=4)
+ lp = a;
+ for(port = offset; port < offset+n; port += 4)
outl(port, *lp++);
return n*4;
+
+ default:
+ error(Egreg);
+ break;
}
- error(Eperm);
+
return 0;
}
@@ 426,7 310,7 @@ Dev vgadevtab = {
"vga",
vgareset,
- vgainit,
+ devinit,
vgaattach,
devclone,
vgawalk,
@@ 441,864 325,3 @@ Dev vgadevtab = {
devremove,
devwstat,
};
-
-int
-vgaxi(long port, uchar index)
-{
- uchar data;
-
- ilock(&vgaxlock);
- switch(port){
-
- case Seqx:
- case Crtx:
- case Grx:
- outb(port, index);
- data = inb(port+1);
- break;
-
- case Attrx:
- /*
- * Allow processor access to the colour
- * palette registers. Writes to Attrx must
- * be preceded by a read from Status1 to
- * initialise the register to point to the
- * index register and not the data register.
- * Processor access is allowed by turning
- * off bit 0x20.
- */
- inb(Status1);
- if(index < 0x10){
- outb(Attrx, index);
- data = inb(Attrx+1);
- inb(Status1);
- outb(Attrx, 0x20|index);
- }
- else{
- outb(Attrx, 0x20|index);
- data = inb(Attrx+1);
- }
- break;
-
- default:
- iunlock(&vgaxlock);
- return -1;
- }
- iunlock(&vgaxlock);
-
- return data & 0xFF;
-}
-
-int
-vgaxo(long port, uchar index, uchar data)
-{
- ilock(&vgaxlock);
- switch(port){
-
- case Seqx:
- case Crtx:
- case Grx:
- /*
- * We could use an outport here, but some chips
- * (e.g. 86C928) have trouble with that for some
- * registers.
- */
- outb(port, index);
- outb(port+1, data);
- break;
-
- case Attrx:
- inb(Status1);
- if(index < 0x10){
- outb(Attrx, index);
- outb(Attrx, data);
- inb(Status1);
- outb(Attrx, 0x20|index);
- }
- else{
- outb(Attrx, 0x20|index);
- outb(Attrx, data);
- }
- break;
-
- default:
- iunlock(&vgaxlock);
- return -1;
- }
- iunlock(&vgaxlock);
-
- return 0;
-}
-
-static ulong
-xnto32(uchar x, int n)
-{
- int s;
- ulong y;
-
- x &= (1<<n)-1;
- y = 0;
- for(s = 32 - n; s > 0; s -= n)
- y |= x<<s;
- if(s < 0)
- y |= x>>(-s);
- return y;
-}
-
-/*
- * reconfigure screen shape
- */
-static void
-setscreen(int maxx, int maxy, int ldepth)
-{
- int i, x, l, tl;
- uchar *a;
- Rectangle r;
-
- if(waserror()){
- qunlock(&screenlock);
- nexterror();
- }
-
- qlock(&screenlock);
-
- /* setup a bitmap for the new size */
- gscreen.ldepth = ldepth;
- gscreen.width = (maxx*(1<<gscreen.ldepth)+31)/32;
- gscreen.base = (void*)screenmem;
- gscreen.r.min = Pt(0, 0);
- gscreen.r.max = Pt(maxx, maxy);
- gscreen.clipr = gscreen.r;
- for(i = 0; i < gscreen.width*BY2WD*maxy; i += footprint){
- vgac->page(i>>footshift);
- memset(gscreen.base, 0xff, footprint);
- }
-
- /* get size for a system window */
- h = defont0.height;
- w = defont0.info[' '].width;
- window.min = Pt(48, 48);
- window.max = add(window.min, Pt(10+w*80, 50*h));
- if(window.max.y >= gscreen.r.max.y)
- window.max.y = gscreen.r.max.y-1;
- if(window.max.x >= gscreen.r.max.x)
- window.max.x = gscreen.r.max.x-1;
- window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
- curpos = window.min;
-
- /* work areas change when dimensions change */
- workinit(&chwork, w, h);
- workinit(&scrollwork, 80*w, 1);
- workinit(&scrollwork, Dx(window), 1);
- cursorinit();
-
- /* clear the system window */
- l = scrollwork.width * BY2WD;
- memset(scrollwork.base, 0, l);
- tl = graphicssubtile(0, l, gscreen.ldepth, gscreen.r, window, &a);
- for(i = window.min.y; i < window.max.y; i++){
- r = Rect(window.min.x, i, window.max.x, i + 1);
- screenload(r, (uchar*)scrollwork.base, tl, l, 1);
- }
-
- /* switch software to graphics mode */
- if(vgascreenputc == nil)
- vgascreenputc = screenputc;
-
- qunlock(&screenlock);
- poperror();
-
- /* default color map (has to be outside the lock) */
- switch(ldepth){
- case 3:
- graphicscmap(0);
- break;
- case 2:
- case 1:
- case 0:
- for(i = 0; i < 16; i++){
- x = xnto32((i*63)/15, 6);
- setcolor(i, x, x, x);
- }
- break;
- }
-}
-
-/*
- * init a bitblt work area
- */
-static void
-workinit(Bitmap *bm, int maxx, int maxy)
-{
- bm->ldepth = gscreen.ldepth;
- bm->r = Rect(0, 0, maxx, maxy);
- if(gscreen.ldepth != 3)
- bm->r.max.x += 1<<(3-gscreen.ldepth);
- bm->clipr = bm->r;
- bm->width = ((bm->r.max.x << gscreen.ldepth) + 31) >> 5;
- if(bm->base == 0)
- bm->base = xalloc(maxx*maxy);
-}
-
-/*
- * Load a byte into screen memory. Assume that if the page
- * is wrong we just need to increment it.
- */
-static int
-byteload(uchar *q, uchar *data, int m, int *page, uchar *e)
-{
- int pg;
- int diff;
-
- diff = 0;
- if(q >= e){
- pg = ++*page;
- vgac->page(pg);
- q -= footprint;
- diff -= footprint;
- }
- *q ^= (*data^*q) & m;
- return diff;
-}
-
-/*
- * Load adjacent bytes into a screen memory. Assume that if the page
- * is wrong we just need to increment it.
- */
-static int
-lineload(uchar *q, uchar *data, int len, int *page, uchar *e)
-{
- int rem, pg;
- int diff;
-
- diff = 0;
- if(q >= e){
- pg = ++*page;
- vgac->page(pg);
- q -= footprint;
- diff -= footprint;
- }
-
- rem = e - q;
-
- if(rem < len){
- memmove(q, data, rem);
- pg = ++*page;
- vgac->page(pg);
- q -= footprint;
- diff -= footprint;
- memmove(q+rem, data+rem, len-rem);
- } else
- memmove(q, data, len);
-
- return diff;
-}
-
-/*
- * paste tile into hard screen.
- * tile is at location r, first pixel in *data. tl is length of scan line to insert,
- * l is amount to advance data after each scan line.
- */
-void
-screenload(Rectangle r, uchar *data, int tl, int l, int dolock)
-{
- int y, lpart, rpart, mx, m, mr, page, sw;
- ulong off;
- uchar *q, *e;
-
- if(screendisabled || vgascreenputc == nil || !rectclip(&r, gscreen.r) || tl<=0)
- return;
-
- if(dolock && hwgc == 0)
- cursorlock(r);
-
- lock(&myscreenlock);
- q = byteaddr(&gscreen, r.min);
- mx = 7>>gscreen.ldepth;
- lpart = (r.min.x & mx) << gscreen.ldepth;
- rpart = (r.max.x & mx) << gscreen.ldepth;
- m = 0xFF >> lpart;
- mr = 0xFF ^ (0xFF >> rpart);
-
- off = q - (uchar*)gscreen.base;
- page = off>>footshift;
- vgac->page(page);
- q = ((uchar*)gscreen.base) + (off&(footprint-1));
-
- sw = gscreen.width*sizeof(ulong);
- e = ((uchar*)gscreen.base) + footprint;
-
- /* may need to do bit insertion on edges */
- if(tl <= 0){
- ;
- }else if(tl == 1){ /* all in one byte */
- if(rpart)
- m &= mr;
- for(y=r.min.y; y<r.max.y; y++){
- if(q < e)
- *q ^= (*data^*q) & m;
- else
- q += byteload(q, data, m, &page, e);
- q += sw;
- data += l;
- }
- }else if(lpart==0 && rpart==0){ /* easy case */
- for(y=r.min.y; y<r.max.y; y++){
- if(q + tl <= e)
- memmove(q, data, tl);
- else
- q += lineload(q, data, tl, &page, e);
- q += sw;
- data += l;
- }
- }else if(rpart==0){
- for(y=r.min.y; y<r.max.y; y++){
- if(q + tl <= e){
- *q ^= (*data^*q) & m;
- memmove(q+1, data+1, tl-1);
- } else {
- q += byteload(q, data, m, &page, e);
- q += lineload(q+1, data+1, tl-1, &page, e);
- }
- q += sw;
- data += l;
- }
- }else if(lpart == 0){
- for(y=r.min.y; y<r.max.y; y++){
- if(q + tl <= e){
- memmove(q, data, tl-1);
- q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr;
- } else { /* new page */
- q += lineload(q, data, tl-1, &page, e);
- q += byteload(q+tl-1, data+tl-1, mr, &page, e);
- }
- q += sw;
- data += l;
- }
- }else for(y=r.min.y; y<r.max.y; y++){
- if(q + tl <= e){
- *q ^= (*data^*q) & m;
- if(tl > 2)
- memmove(q+1, data+1, tl-2);
- q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr;
- } else { /* new page */
- q += byteload(q, data, m, &page, e);
- if(tl > 2)
- q += lineload(q+1, data+1, tl-2, &page, e);
- q += byteload(q+tl-1, data+tl-1, mr, &page, e);
- }
- q += sw;
- data += l;
- }
-
- unlock(&myscreenlock);
- if(dolock && hwgc == 0)
- cursorunlock();
-}
-
-/*
- * Get a byte from screen memory. Assume that if the page
- * is wrong we just need to increment it.
- */
-static int
-byteunload(uchar *q, uchar *data, int m, int *page, uchar *e)
-{
- int pg;
- int diff;
-
- diff = 0;
- if(q >= e){
- pg = ++*page;
- vgac->page(pg);
- q -= footprint;
- diff -= footprint;
- }
- *data ^= (*q^*data) & m;
- return diff;
-}
-
-/*
- * Get a vector of bytes from screen memory. Assume that if the page
- * is wrong we just need to increment it.
- */
-static int
-lineunload(uchar *q, uchar *data, int len, int *page, uchar *e)
-{
- int rem, pg;
- int diff;
-
- diff = 0;
- if(q >= e){
- pg = ++*page;
- vgac->page(pg);
- q -= footprint;
- diff -= footprint;
- }
-
- rem = e - q;
-
- if(rem < len){
- memmove(data, q, rem);
- pg = ++*page;
- vgac->page(pg);
- q -= footprint;
- diff -= footprint;
- memmove(data+rem, q+rem, len-rem);
- } else
- memmove(data, q, len);
-
- return diff;
-}
-
-/*
- * get a tile from screen memory.
- * tile is at location r, first pixel in *data.
- * tl is length of scan line to insert,
- * l is amount to advance data after each scan line.
- */
-void
-screenunload(Rectangle r, uchar *data, int tl, int l, int dolock)
-{
- int y, lpart, rpart, mx, m, mr, page, sw;
- ulong off;
- uchar *q, *e;
-
- if(screendisabled || vgascreenputc == nil || !rectclip(&r, gscreen.r) || tl<=0)
- return;
-
- if(dolock && hwgc == 0)
- cursorlock(r);
-
- lock(&myscreenlock);
- q = byteaddr(&gscreen, r.min);
- mx = 7>>gscreen.ldepth;
- lpart = (r.min.x & mx) << gscreen.ldepth;
- rpart = (r.max.x & mx) << gscreen.ldepth;
- m = 0xFF >> lpart;
- mr = 0xFF ^ (0xFF >> rpart);
-
- off = q - (uchar*)gscreen.base;
- page = off>>footshift;
- vgac->page(page);
- q = ((uchar*)gscreen.base) + (off&(footprint-1));
-
- sw = gscreen.width*sizeof(ulong);
- e = ((uchar*)gscreen.base) + footprint;
-
- /* may need to do bit insertion on edges */
- if(tl <= 0){
- ;
- }else if(tl == 1){ /* all in one byte */
- if(rpart)
- m &= mr;
- for(y=r.min.y; y<r.max.y; y++){
- if(q < e)
- *data ^= (*q^*data) & m;
- else
- q += byteunload(q, data, m, &page, e);
- q += sw;
- data += l;
- }
- }else if(lpart==0 && rpart==0){ /* easy case */
- for(y=r.min.y; y<r.max.y; y++){
- if(q + tl <= e)
- memmove(data, q, tl);
- else
- q += lineunload(q, data, tl, &page, e);
- q += sw;
- data += l;
- }
- }else if(rpart==0){
- for(y=r.min.y; y<r.max.y; y++){
- if(q + tl <= e){
- *data ^= (*q^*data) & m;
- memmove(data+1, q+1, tl-1);
- } else {
- q += byteunload(q, data, m, &page, e);
- q += lineunload(q+1, data+1, tl-1, &page, e);
- }
- q += sw;
- data += l;
- }
- }else if(lpart == 0){
- for(y=r.min.y; y<r.max.y; y++){
- if(q + tl <= e){
- memmove(data, q, tl-1);
- data[tl-1] ^= (q[tl-1]^data[tl-1]) & mr;
- } else { /* new page */
- q += lineunload(q, data, tl-1, &page, e);
- q += byteunload(q+tl-1, data+tl-1, mr, &page, e);
- }
- q += sw;
- data += l;
- }
- }else for(y=r.min.y; y<r.max.y; y++){
- if(q + tl <= e){
- *data ^= (*q^*data) & m;
- if(tl > 2)
- memmove(data+1, q+1, tl-2);
- data[tl-1] ^= (q[tl-1]^data[tl-1]) & mr;
- } else { /* new page */
- q += byteunload(q, data, m, &page, e);
- if(tl > 2)
- q += lineunload(q+1, data+1, tl-2, &page, e);
- q += byteunload(q+tl-1, data+tl-1, mr, &page, e);
- }
- q += sw;
- data += l;
- }
-
- unlock(&myscreenlock);
- if(dolock && hwgc == 0)
- cursorunlock();
-}
-
-static void
-nopage(int)
-{
-}
-
-/*
- * graphics mode console
- */
-#define LINE2SCROLL 4
-static void
-scroll(void)
-{
- int from, tl, l, diff;
- uchar *a;
- Rectangle r;
-
- diff = h*LINE2SCROLL;
- l = scrollwork.width * BY2WD;
- tl = graphicssubtile(0, l, gscreen.ldepth, gscreen.r, window, &a);
-
- /* move lines up */
- for(from = window.min.y + diff; from < window.max.y; from++){
- r = Rect(window.min.x, from, window.max.x, from + 1);
- screenunload(r, (uchar*)scrollwork.base, tl, l, 1);
- r = Rect(window.min.x, from - diff, window.max.x, from - diff + 1);
- screenload(r, (uchar*)scrollwork.base, tl, l, 1);
- }
-
- /* clear bottom */
- memset(scrollwork.base, 0, l);
- for(from = window.max.y - diff; from < window.max.y; from++){
- r = Rect(window.min.x, from, window.max.x, from + 1);
- screenload(r, (uchar*)scrollwork.base, tl, l, 1);
- }
-
- curpos.y -= diff;
-}
-
-static void
-screenputc(char *buf)
-{
- int pos, l, tl, off;
- uchar *a;
- Rectangle r;
-
- switch(buf[0]) {
- case '\n':
- if(curpos.y+h >= window.max.y)
- scroll();
- curpos.y += h;
- screenputc("\r");
- break;
- case '\r':
- curpos.x = window.min.x;
- break;
- case '\t':
- pos = (curpos.x-window.min.x)/w;
- pos = 8-(pos%8);
- curpos.x += pos*w;
- break;
- case '\b':
- if(curpos.x-w >= window.min.x){
- curpos.x -= w;
- screenputc(" ");
- curpos.x -= w;
- }
- break;
- default:
- if(curpos.x >= window.max.x-w)
- screenputc("\n");
-
- /* tile width */
- r.min = curpos;
- r.max = add(r.min, Pt(w, h));
- off = ((1<<gscreen.ldepth)*r.min.x) & 7;
- l = chwork.width*BY2WD;
- tl = graphicssubtile(0, l, gscreen.ldepth, gscreen.r, r, &a);
-
- /* add char into work area */
- subfstring(&chwork, Pt(off, 0), &defont0, buf, S);
-
- /* move work area to screen */
- screenload(r, (uchar*)chwork.base, tl, l, 1);
-
- curpos.x += w;
- }
-}
-
-int
-screenbits(void)
-{
- return 1<<gscreen.ldepth; /* bits per pixel */
-}
-
-void
-getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
-{
- ulong x;
-
- switch(gscreen.ldepth){
- default:
- x = 0xF;
- break;
- case 3:
- x = 0xFF;
- break;
- }
- p &= x;
- p ^= x;
- lock(&palettelock);
- *pr = colormap[p][Pred];
- *pg = colormap[p][Pgreen];
- *pb = colormap[p][Pblue];
- unlock(&palettelock);
-}
-
-int
-setcolor(ulong p, ulong r, ulong g, ulong b)
-{
- ulong x;
-
- switch(gscreen.ldepth){
- default:
- x = 0xF;
- break;
- case 3:
- x = 0xFF;
- break;
- }
- p &= x;
- p ^= x;
- lock(&palettelock);
- colormap[p][Pred] = r;
- colormap[p][Pgreen] = g;
- colormap[p][Pblue] = b;
- vgao(PaddrW, p);
- vgao(Pdata, r>>(32-6));
- vgao(Pdata, g>>(32-6));
- vgao(Pdata, b>>(32-6));
- unlock(&palettelock);
- return ~0;
-}
-
-/*
- * software cursor
- * and hacks for hardware cursor
- */
-
-/*
- * area to store the bits that are behind the cursor
- */
-static ulong backbits[16*4];
-static ulong clrbits[16];
-static ulong setbits[16];
-
-/*
- * the white border around the cursor
- */
-Bitmap clr =
-{
- {0, 0, 16, 16},
- {0, 0, 16, 16},
- 0,
- clrbits,
- 0,
- 1,
-};
-
-/*
- * the black center of the cursor
- */
-Bitmap set =
-{
- {0, 0, 16, 16},
- {0, 0, 16, 16},
- 0,
- setbits,
- 0,
- 1,
-};
-
-static void
-cursorinit(void)
-{
- static int already;
-
- lock(&cursor);
-
- workinit(&cursorwork, 16, 16);
- cursor.l = cursorwork.width*BY2WD;
-
- if(!already){
- cursor.disable--;
- already = 1;
- }
-
- unlock(&cursor);
-}
-
-void
-setcursor(Cursor *curs)
-{
- uchar *p;
- int i;
-
- if(hwgc)
- hwgc->load(curs);
- else for(i=0; i<16; i++){
- p = (uchar*)&set.base[i];
- *p = curs->set[2*i];
- *(p+1) = curs->set[2*i+1];
- p = (uchar*)&clr.base[i];
- *p = curs->clr[2*i];
- *(p+1) = curs->clr[2*i+1];
- }
-}
-
-int
-cursoron(int dolock)
-{
- int xoff, yoff, s, ret;
- Rectangle r;
- uchar *a;
- struct {
- Bitmap *dm;
- Point p;
- Bitmap *sm;
- Rectangle r;
- Fcode f;
- } xx;
-
- if(cursor.disable)
- return 0;
- if(dolock){
- s = 0; /* to avoid compiler warning */
- lock(&cursor);
- } /*else
- s = spllo(); /* to avoid freezing out the eia ports */
-
- ret = 0;
- if(hwgc)
- ret = hwgc->move(mousexy());
- else if(cursor.visible++ == 0){
- cursor.r.min = mousexy();
- cursor.r.max = add(cursor.r.min, Pt(16, 16));
- cursor.r = raddp(cursor.r, cursor.offset);
-
- /* offsets into backup area and clr/set bitmaps */
- r.min = Pt(0, 0);
- if(cursor.r.min.x < 0){
- xoff = cursor.r.min.x;
- r.min.x = -xoff;
- } else
- xoff = ((1<<gscreen.ldepth)*cursor.r.min.x) & 7;
- if(cursor.r.min.y < 0){
- yoff = cursor.r.min.y;
- r.min.y = -yoff;
- } else
- yoff = 0;
- r.max = add(r.min, Pt(16, 16));
-
- /* clip the cursor rectangle */
- xx.dm = &cursorwork;
- xx.p = Pt(xoff, yoff);
- xx.sm = &gscreen;
- xx.r = cursor.r;
- bitbltclip(&xx);
-
- /* tile width */
- cursor.tl = graphicssubtile(0, cursor.l, gscreen.ldepth,
- gscreen.r, xx.r, &a);
- if(cursor.tl > 0){
- /* get tile */
- screenunload(xx.r, (uchar*)cursorwork.base, cursor.tl, cursor.l, 0);
-
- /* save for cursoroff */
- memmove(backbits, cursorwork.base, cursor.l*16);
-
- /* add mouse into work area */
- bitblt(&cursorwork, xx.p, &clr, r, D&~S);
- bitblt(&cursorwork, xx.p, &set, r, S|D);
-
- /* put back tile */
- cursor.clipr = xx.r;
- screenload(xx.r, (uchar*)cursorwork.base, cursor.tl, cursor.l, 0);
- }
- }
-
- if(dolock)
- unlock(&cursor);
- /*else
- splx(s);*/
-
- return ret;
-}
-
-void
-cursoroff(int dolock)
-{
- if(hwgc)
- return;
- if(cursor.disable)
- return;
- if(dolock)
- lock(&cursor);
-
- if(--cursor.visible == 0 && cursor.tl > 0)
- screenload(cursor.clipr, (uchar*)backbits, cursor.tl, cursor.l, 0);
-
- if(dolock)
- unlock(&cursor);
-}
-
-static void
-cursorlock(Rectangle r)
-{
- lock(&cursor);
- if(rectXrect(cursor.r, r)){
- cursoroff(0);
- cursor.frozen = 1;
- }
- cursor.disable++;
- unlock(&cursor);
-}
-
-static void
-cursorunlock(void)
-{
- lock(&cursor);
- cursor.disable--;
- if(cursor.frozen)
- cursoron(0);
- cursor.frozen = 0;
- unlock(&cursor);
-}
-
-void
-addhwgclink(Hwgc *hwgcp)
-{
- hwgcp->link = hwgctlr;
- hwgctlr = hwgcp;
-}
-
-void
-addvgaclink(Vgac *vgacp)
-{
- vgacp->link = vgactlr;
- vgactlr = vgacp;
-}
M pc/ether8003.c => pc/ether8003.c +2 -2
@@ 122,7 122,7 @@ reset8003(Ether* ether, uchar ea[Eaddrlen], uchar ic[8])
ctlr->width = 1;
}
- ether->mem = KZERO|((ic[Msr] & 0x3F)<<13);
+ ether->mem = (ulong)KADDR((ic[Msr] & 0x3F)<<13);
if(ctlr->width == 2)
ether->mem |= (ic[Laar] & 0x1F)<<19;
else
@@ 163,7 163,7 @@ reset8216(Ether* ether, uchar[8])
irq = inb(port+0x0D);
outb(port+Hcr, hcr);
- ether->mem = KZERO|(0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13));
+ ether->mem = (ulong)KADDR(0xC0000+((((addr>>2) & 0x30)|(addr & 0x0F))<<13));
ether->size = 8192*(1<<((addr>>4) & 0x03));
ether->irq = irq8216[((irq>>4) & 0x04)|((irq>>2) & 0x03)];
M pc/fns.h => pc/fns.h +2 -2
@@ 60,7 60,7 @@ void mmuinit(void);
ulong mmukmap(ulong, ulong, int);
int mmukmapsync(ulong);
#define mmunewpage(x)
-ulong* mmuwalk(ulong*, ulong, int);
+ulong* mmuwalk(ulong*, ulong, int, int);
void ns16552install(void);
void ns16552special(int, int, Queue**, Queue**, int (*)(Queue*, int));
uchar nvramread(int);
@@ 94,7 94,7 @@ void putcr4(ulong);
void rdmsr(int, ulong*, ulong*);
void screeninit(void);
int screenprint(char*, ...); /* debugging */
-void screenputs(char*, int);
+void (*screenputs)(char*, int);
void touser(void*);
void trapinit(void);
int tas(void*);
M pc/kbd.c => pc/kbd.c +1 -1
@@ 149,7 149,7 @@ inready(void)
void
i8042reset(void)
{
- ushort *s = (ushort*)(KZERO|0x472);
+ ushort *s = KADDR(0x472);
int i, x;
*s = 0x1234; /* BIOS warm-boot flag */
M pc/l.s => pc/l.s +269 -274
@@ 66,13 66,7 @@ _setpte:
ADDL $4, AX
LOOP _setpte
- MOVL $CPU0PDB, AX
- ADDL $PDO(MACHADDR), AX /* page directory offset for MACHADDR */
- MOVL $PADDR(CPU0MACHPTE), (AX) /* PTE's for 4MB containing MACHADDR */
- MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */
- ORL BX, (AX)
-
- MOVL $CPU0MACHPTE, AX
+ MOVL $CPU0PTE, AX
ADDL $PTO(MACHADDR), AX /* page table entry offset for MACHADDR */
MOVL $PADDR(CPU0MACH), (AX) /* PTE for Mach */
MOVL $(PTEWRITE|PTEVALID), BX /* page permissions */
@@ 436,22 430,23 @@ TEXT splhi(SB), $0
CLI
RET
+TEXT spllo(SB), $0
+ PUSHFL
+ POPL AX
+ STI
+ RET
+
TEXT splx(SB), $0
MOVL $(MACHADDR+0x04), AX /* save PC in m->splpc */
MOVL (SP), BX
MOVL BX, (AX)
+TEXT _splx(SB), $0 /* for iunlock */
MOVL s+0(FP), AX
PUSHL AX
POPFL
RET
-TEXT spllo(SB), $0
- PUSHFL
- POPL AX
- STI
- RET
-
TEXT spldone(SB), $0
RET
@@ 509,21 504,21 @@ TEXT setlabel(SB), $0
/*
* Interrupt/exception handling.
- * Each entry in the vector table calls either strayintr or strayintrx depending
+ * Each entry in the vector table calls either _strayintr or _strayintrx depending
* on whether an error code has beemn automatically pushed onto the stack
- * (strayintrx) or not, in which case a dummy entry must be pushed before retrieving
+ * (_strayintrx) or not, in which case a dummy entry must be pushed before retrieving
* the trap type from the vector table entry and placing it on the stack as part
* of the Ureg structure.
* The size of each entry in the vector table (6 bytes) is known in trapinit().
*/
-TEXT strayintr(SB), $0
+TEXT _strayintr(SB), $0
PUSHL AX /* save AX */
MOVL 4(SP), AX /* return PC from vectortable(SB) */
MOVBLZX (AX), AX /* trap type */
XCHGL AX, (SP) /* restore AX and put the type on the stack */
JMP intrcommon
-TEXT strayintrx(SB), $0
+TEXT _strayintrx(SB), $0
XCHGL AX, (SP) /* exchange AX with pointer to trap type */
MOVBLZX (AX), AX /* trap type -> AX */
XCHGL AX, (SP) /* exchange trap type with AX */
@@ 534,7 529,7 @@ intrcommon:
PUSHL FS
PUSHL GS
PUSHAL
- MOVL $(KDSEL),AX
+ MOVL $(KDSEL), AX
MOVW AX, DS
MOVW AX, ES
PUSHL SP
@@ 551,259 546,259 @@ TEXT forkret(SB), $0
IRETL
TEXT vectortable(SB), $0
- CALL strayintr(SB); BYTE $0x00 /* divide error */
- CALL strayintr(SB); BYTE $0x01 /* debug exception */
- CALL strayintr(SB); BYTE $0x02 /* NMI interrupt */
- CALL strayintr(SB); BYTE $0x03 /* breakpoint */
- CALL strayintr(SB); BYTE $0x04 /* overflow */
- CALL strayintr(SB); BYTE $0x05 /* bound */
- CALL strayintr(SB); BYTE $0x06 /* invalid opcode */
- CALL strayintr(SB); BYTE $0x07 /* no coprocessor available */
- CALL strayintrx(SB); BYTE $0x08 /* double fault */
- CALL strayintr(SB); BYTE $0x09 /* coprocessor segment overflow */
- CALL strayintrx(SB); BYTE $0x0A /* invalid TSS */
- CALL strayintrx(SB); BYTE $0x0B /* segment not available */
- CALL strayintrx(SB); BYTE $0x0C /* stack exception */
- CALL strayintrx(SB); BYTE $0x0D /* general protection error */
- CALL strayintrx(SB); BYTE $0x0E /* page fault */
- CALL strayintr(SB); BYTE $0x0F /* */
- CALL strayintr(SB); BYTE $0x10 /* coprocessor error */
- CALL strayintrx(SB); BYTE $0x11 /* alignment check */
- CALL strayintr(SB); BYTE $0x12 /* machine check */
- CALL strayintr(SB); BYTE $0x13
- CALL strayintr(SB); BYTE $0x14
- CALL strayintr(SB); BYTE $0x15
- CALL strayintr(SB); BYTE $0x16
- CALL strayintr(SB); BYTE $0x17
- CALL strayintr(SB); BYTE $0x18
- CALL strayintr(SB); BYTE $0x19
- CALL strayintr(SB); BYTE $0x1A
- CALL strayintr(SB); BYTE $0x1B
- CALL strayintr(SB); BYTE $0x1C
- CALL strayintr(SB); BYTE $0x1D
- CALL strayintr(SB); BYTE $0x1E
- CALL strayintr(SB); BYTE $0x1F
- CALL strayintr(SB); BYTE $0x20 /* VectorLAPIC */
- CALL strayintr(SB); BYTE $0x21
- CALL strayintr(SB); BYTE $0x22
- CALL strayintr(SB); BYTE $0x23
- CALL strayintr(SB); BYTE $0x24
- CALL strayintr(SB); BYTE $0x25
- CALL strayintr(SB); BYTE $0x26
- CALL strayintr(SB); BYTE $0x27
- CALL strayintr(SB); BYTE $0x28
- CALL strayintr(SB); BYTE $0x29
- CALL strayintr(SB); BYTE $0x2A
- CALL strayintr(SB); BYTE $0x2B
- CALL strayintr(SB); BYTE $0x2C
- CALL strayintr(SB); BYTE $0x2D
- CALL strayintr(SB); BYTE $0x2E
- CALL strayintr(SB); BYTE $0x2F
- CALL strayintr(SB); BYTE $0x30
- CALL strayintr(SB); BYTE $0x31
- CALL strayintr(SB); BYTE $0x32
- CALL strayintr(SB); BYTE $0x33
- CALL strayintr(SB); BYTE $0x34
- CALL strayintr(SB); BYTE $0x35
- CALL strayintr(SB); BYTE $0x36
- CALL strayintr(SB); BYTE $0x37
- CALL strayintr(SB); BYTE $0x38
- CALL strayintr(SB); BYTE $0x39
- CALL strayintr(SB); BYTE $0x3A
- CALL strayintr(SB); BYTE $0x3B
- CALL strayintr(SB); BYTE $0x3C
- CALL strayintr(SB); BYTE $0x3D
- CALL strayintr(SB); BYTE $0x3E
- CALL strayintr(SB); BYTE $0x3F
- CALL strayintr(SB); BYTE $0x40 /* VectorSYSCALL */
- CALL strayintr(SB); BYTE $0x41
- CALL strayintr(SB); BYTE $0x42
- CALL strayintr(SB); BYTE $0x43
- CALL strayintr(SB); BYTE $0x44
- CALL strayintr(SB); BYTE $0x45
- CALL strayintr(SB); BYTE $0x46
- CALL strayintr(SB); BYTE $0x47
- CALL strayintr(SB); BYTE $0x48
- CALL strayintr(SB); BYTE $0x49
- CALL strayintr(SB); BYTE $0x4A
- CALL strayintr(SB); BYTE $0x4B
- CALL strayintr(SB); BYTE $0x4C
- CALL strayintr(SB); BYTE $0x4D
- CALL strayintr(SB); BYTE $0x4E
- CALL strayintr(SB); BYTE $0x4F
- CALL strayintr(SB); BYTE $0x50
- CALL strayintr(SB); BYTE $0x51
- CALL strayintr(SB); BYTE $0x52
- CALL strayintr(SB); BYTE $0x53
- CALL strayintr(SB); BYTE $0x54
- CALL strayintr(SB); BYTE $0x55
- CALL strayintr(SB); BYTE $0x56
- CALL strayintr(SB); BYTE $0x57
- CALL strayintr(SB); BYTE $0x58
- CALL strayintr(SB); BYTE $0x59
- CALL strayintr(SB); BYTE $0x5A
- CALL strayintr(SB); BYTE $0x5B
- CALL strayintr(SB); BYTE $0x5C
- CALL strayintr(SB); BYTE $0x5D
- CALL strayintr(SB); BYTE $0x5E
- CALL strayintr(SB); BYTE $0x5F
- CALL strayintr(SB); BYTE $0x60
- CALL strayintr(SB); BYTE $0x61
- CALL strayintr(SB); BYTE $0x62
- CALL strayintr(SB); BYTE $0x63
- CALL strayintr(SB); BYTE $0x64
- CALL strayintr(SB); BYTE $0x65
- CALL strayintr(SB); BYTE $0x66
- CALL strayintr(SB); BYTE $0x67
- CALL strayintr(SB); BYTE $0x68
- CALL strayintr(SB); BYTE $0x69
- CALL strayintr(SB); BYTE $0x6A
- CALL strayintr(SB); BYTE $0x6B
- CALL strayintr(SB); BYTE $0x6C
- CALL strayintr(SB); BYTE $0x6D
- CALL strayintr(SB); BYTE $0x6E
- CALL strayintr(SB); BYTE $0x6F
- CALL strayintr(SB); BYTE $0x70
- CALL strayintr(SB); BYTE $0x71
- CALL strayintr(SB); BYTE $0x72
- CALL strayintr(SB); BYTE $0x73
- CALL strayintr(SB); BYTE $0x74
- CALL strayintr(SB); BYTE $0x75
- CALL strayintr(SB); BYTE $0x76
- CALL strayintr(SB); BYTE $0x77
- CALL strayintr(SB); BYTE $0x78
- CALL strayintr(SB); BYTE $0x79
- CALL strayintr(SB); BYTE $0x7A
- CALL strayintr(SB); BYTE $0x7B
- CALL strayintr(SB); BYTE $0x7C
- CALL strayintr(SB); BYTE $0x7D
- CALL strayintr(SB); BYTE $0x7E
- CALL strayintr(SB); BYTE $0x7F
- CALL strayintr(SB); BYTE $0x80 /* Vector[A]PIC */
- CALL strayintr(SB); BYTE $0x81
- CALL strayintr(SB); BYTE $0x82
- CALL strayintr(SB); BYTE $0x83
- CALL strayintr(SB); BYTE $0x84
- CALL strayintr(SB); BYTE $0x85
- CALL strayintr(SB); BYTE $0x86
- CALL strayintr(SB); BYTE $0x87
- CALL strayintr(SB); BYTE $0x88
- CALL strayintr(SB); BYTE $0x89
- CALL strayintr(SB); BYTE $0x8A
- CALL strayintr(SB); BYTE $0x8B
- CALL strayintr(SB); BYTE $0x8C
- CALL strayintr(SB); BYTE $0x8D
- CALL strayintr(SB); BYTE $0x8E
- CALL strayintr(SB); BYTE $0x8F
- CALL strayintr(SB); BYTE $0x90
- CALL strayintr(SB); BYTE $0x91
- CALL strayintr(SB); BYTE $0x92
- CALL strayintr(SB); BYTE $0x93
- CALL strayintr(SB); BYTE $0x94
- CALL strayintr(SB); BYTE $0x95
- CALL strayintr(SB); BYTE $0x96
- CALL strayintr(SB); BYTE $0x97
- CALL strayintr(SB); BYTE $0x98
- CALL strayintr(SB); BYTE $0x99
- CALL strayintr(SB); BYTE $0x9A
- CALL strayintr(SB); BYTE $0x9B
- CALL strayintr(SB); BYTE $0x9C
- CALL strayintr(SB); BYTE $0x9D
- CALL strayintr(SB); BYTE $0x9E
- CALL strayintr(SB); BYTE $0x9F
- CALL strayintr(SB); BYTE $0xA0
- CALL strayintr(SB); BYTE $0xA1
- CALL strayintr(SB); BYTE $0xA2
- CALL strayintr(SB); BYTE $0xA3
- CALL strayintr(SB); BYTE $0xA4
- CALL strayintr(SB); BYTE $0xA5
- CALL strayintr(SB); BYTE $0xA6
- CALL strayintr(SB); BYTE $0xA7
- CALL strayintr(SB); BYTE $0xA8
- CALL strayintr(SB); BYTE $0xA9
- CALL strayintr(SB); BYTE $0xAA
- CALL strayintr(SB); BYTE $0xAB
- CALL strayintr(SB); BYTE $0xAC
- CALL strayintr(SB); BYTE $0xAD
- CALL strayintr(SB); BYTE $0xAE
- CALL strayintr(SB); BYTE $0xAF
- CALL strayintr(SB); BYTE $0xB0
- CALL strayintr(SB); BYTE $0xB1
- CALL strayintr(SB); BYTE $0xB2
- CALL strayintr(SB); BYTE $0xB3
- CALL strayintr(SB); BYTE $0xB4
- CALL strayintr(SB); BYTE $0xB5
- CALL strayintr(SB); BYTE $0xB6
- CALL strayintr(SB); BYTE $0xB7
- CALL strayintr(SB); BYTE $0xB8
- CALL strayintr(SB); BYTE $0xB9
- CALL strayintr(SB); BYTE $0xBA
- CALL strayintr(SB); BYTE $0xBB
- CALL strayintr(SB); BYTE $0xBC
- CALL strayintr(SB); BYTE $0xBD
- CALL strayintr(SB); BYTE $0xBE
- CALL strayintr(SB); BYTE $0xBF
- CALL strayintr(SB); BYTE $0xC0
- CALL strayintr(SB); BYTE $0xC1
- CALL strayintr(SB); BYTE $0xC2
- CALL strayintr(SB); BYTE $0xC3
- CALL strayintr(SB); BYTE $0xC4
- CALL strayintr(SB); BYTE $0xC5
- CALL strayintr(SB); BYTE $0xC6
- CALL strayintr(SB); BYTE $0xC7
- CALL strayintr(SB); BYTE $0xC8
- CALL strayintr(SB); BYTE $0xC9
- CALL strayintr(SB); BYTE $0xCA
- CALL strayintr(SB); BYTE $0xCB
- CALL strayintr(SB); BYTE $0xCC
- CALL strayintr(SB); BYTE $0xCD
- CALL strayintr(SB); BYTE $0xCE
- CALL strayintr(SB); BYTE $0xCF
- CALL strayintr(SB); BYTE $0xD0
- CALL strayintr(SB); BYTE $0xD1
- CALL strayintr(SB); BYTE $0xD2
- CALL strayintr(SB); BYTE $0xD3
- CALL strayintr(SB); BYTE $0xD4
- CALL strayintr(SB); BYTE $0xD5
- CALL strayintr(SB); BYTE $0xD6
- CALL strayintr(SB); BYTE $0xD7
- CALL strayintr(SB); BYTE $0xD8
- CALL strayintr(SB); BYTE $0xD9
- CALL strayintr(SB); BYTE $0xDA
- CALL strayintr(SB); BYTE $0xDB
- CALL strayintr(SB); BYTE $0xDC
- CALL strayintr(SB); BYTE $0xDD
- CALL strayintr(SB); BYTE $0xDE
- CALL strayintr(SB); BYTE $0xDF
- CALL strayintr(SB); BYTE $0xE0
- CALL strayintr(SB); BYTE $0xE1
- CALL strayintr(SB); BYTE $0xE2
- CALL strayintr(SB); BYTE $0xE3
- CALL strayintr(SB); BYTE $0xE4
- CALL strayintr(SB); BYTE $0xE5
- CALL strayintr(SB); BYTE $0xE6
- CALL strayintr(SB); BYTE $0xE7
- CALL strayintr(SB); BYTE $0xE8
- CALL strayintr(SB); BYTE $0xE9
- CALL strayintr(SB); BYTE $0xEA
- CALL strayintr(SB); BYTE $0xEB
- CALL strayintr(SB); BYTE $0xEC
- CALL strayintr(SB); BYTE $0xED
- CALL strayintr(SB); BYTE $0xEE
- CALL strayintr(SB); BYTE $0xEF
- CALL strayintr(SB); BYTE $0xF0
- CALL strayintr(SB); BYTE $0xF1
- CALL strayintr(SB); BYTE $0xF2
- CALL strayintr(SB); BYTE $0xF3
- CALL strayintr(SB); BYTE $0xF4
- CALL strayintr(SB); BYTE $0xF5
- CALL strayintr(SB); BYTE $0xF6
- CALL strayintr(SB); BYTE $0xF7
- CALL strayintr(SB); BYTE $0xF8
- CALL strayintr(SB); BYTE $0xF9
- CALL strayintr(SB); BYTE $0xFA
- CALL strayintr(SB); BYTE $0xFB
- CALL strayintr(SB); BYTE $0xFC
- CALL strayintr(SB); BYTE $0xFD
- CALL strayintr(SB); BYTE $0xFE
- CALL strayintr(SB); BYTE $0xFF
+ CALL _strayintr(SB); BYTE $0x00 /* divide error */
+ CALL _strayintr(SB); BYTE $0x01 /* debug exception */
+ CALL _strayintr(SB); BYTE $0x02 /* NMI interrupt */
+ CALL _strayintr(SB); BYTE $0x03 /* breakpoint */
+ CALL _strayintr(SB); BYTE $0x04 /* overflow */
+ CALL _strayintr(SB); BYTE $0x05 /* bound */
+ CALL _strayintr(SB); BYTE $0x06 /* invalid opcode */
+ CALL _strayintr(SB); BYTE $0x07 /* no coprocessor available */
+ CALL _strayintrx(SB); BYTE $0x08 /* double fault */
+ CALL _strayintr(SB); BYTE $0x09 /* coprocessor segment overflow */
+ CALL _strayintrx(SB); BYTE $0x0A /* invalid TSS */
+ CALL _strayintrx(SB); BYTE $0x0B /* segment not available */
+ CALL _strayintrx(SB); BYTE $0x0C /* stack exception */
+ CALL _strayintrx(SB); BYTE $0x0D /* general protection error */
+ CALL _strayintrx(SB); BYTE $0x0E /* page fault */
+ CALL _strayintr(SB); BYTE $0x0F /* */
+ CALL _strayintr(SB); BYTE $0x10 /* coprocessor error */
+ CALL _strayintrx(SB); BYTE $0x11 /* alignment check */
+ CALL _strayintr(SB); BYTE $0x12 /* machine check */
+ CALL _strayintr(SB); BYTE $0x13
+ CALL _strayintr(SB); BYTE $0x14
+ CALL _strayintr(SB); BYTE $0x15
+ CALL _strayintr(SB); BYTE $0x16
+ CALL _strayintr(SB); BYTE $0x17
+ CALL _strayintr(SB); BYTE $0x18
+ CALL _strayintr(SB); BYTE $0x19
+ CALL _strayintr(SB); BYTE $0x1A
+ CALL _strayintr(SB); BYTE $0x1B
+ CALL _strayintr(SB); BYTE $0x1C
+ CALL _strayintr(SB); BYTE $0x1D
+ CALL _strayintr(SB); BYTE $0x1E
+ CALL _strayintr(SB); BYTE $0x1F
+ CALL _strayintr(SB); BYTE $0x20 /* VectorLAPIC */
+ CALL _strayintr(SB); BYTE $0x21
+ CALL _strayintr(SB); BYTE $0x22
+ CALL _strayintr(SB); BYTE $0x23
+ CALL _strayintr(SB); BYTE $0x24
+ CALL _strayintr(SB); BYTE $0x25
+ CALL _strayintr(SB); BYTE $0x26
+ CALL _strayintr(SB); BYTE $0x27
+ CALL _strayintr(SB); BYTE $0x28
+ CALL _strayintr(SB); BYTE $0x29
+ CALL _strayintr(SB); BYTE $0x2A
+ CALL _strayintr(SB); BYTE $0x2B
+ CALL _strayintr(SB); BYTE $0x2C
+ CALL _strayintr(SB); BYTE $0x2D
+ CALL _strayintr(SB); BYTE $0x2E
+ CALL _strayintr(SB); BYTE $0x2F
+ CALL _strayintr(SB); BYTE $0x30
+ CALL _strayintr(SB); BYTE $0x31
+ CALL _strayintr(SB); BYTE $0x32
+ CALL _strayintr(SB); BYTE $0x33
+ CALL _strayintr(SB); BYTE $0x34
+ CALL _strayintr(SB); BYTE $0x35
+ CALL _strayintr(SB); BYTE $0x36
+ CALL _strayintr(SB); BYTE $0x37
+ CALL _strayintr(SB); BYTE $0x38
+ CALL _strayintr(SB); BYTE $0x39
+ CALL _strayintr(SB); BYTE $0x3A
+ CALL _strayintr(SB); BYTE $0x3B
+ CALL _strayintr(SB); BYTE $0x3C
+ CALL _strayintr(SB); BYTE $0x3D
+ CALL _strayintr(SB); BYTE $0x3E
+ CALL _strayintr(SB); BYTE $0x3F
+ CALL _syscallintr(SB); BYTE $0x40 /* VectorSYSCALL */
+ CALL _strayintr(SB); BYTE $0x41
+ CALL _strayintr(SB); BYTE $0x42
+ CALL _strayintr(SB); BYTE $0x43
+ CALL _strayintr(SB); BYTE $0x44
+ CALL _strayintr(SB); BYTE $0x45
+ CALL _strayintr(SB); BYTE $0x46
+ CALL _strayintr(SB); BYTE $0x47
+ CALL _strayintr(SB); BYTE $0x48
+ CALL _strayintr(SB); BYTE $0x49
+ CALL _strayintr(SB); BYTE $0x4A
+ CALL _strayintr(SB); BYTE $0x4B
+ CALL _strayintr(SB); BYTE $0x4C
+ CALL _strayintr(SB); BYTE $0x4D
+ CALL _strayintr(SB); BYTE $0x4E
+ CALL _strayintr(SB); BYTE $0x4F
+ CALL _strayintr(SB); BYTE $0x50
+ CALL _strayintr(SB); BYTE $0x51
+ CALL _strayintr(SB); BYTE $0x52
+ CALL _strayintr(SB); BYTE $0x53
+ CALL _strayintr(SB); BYTE $0x54
+ CALL _strayintr(SB); BYTE $0x55
+ CALL _strayintr(SB); BYTE $0x56
+ CALL _strayintr(SB); BYTE $0x57
+ CALL _strayintr(SB); BYTE $0x58
+ CALL _strayintr(SB); BYTE $0x59
+ CALL _strayintr(SB); BYTE $0x5A
+ CALL _strayintr(SB); BYTE $0x5B
+ CALL _strayintr(SB); BYTE $0x5C
+ CALL _strayintr(SB); BYTE $0x5D
+ CALL _strayintr(SB); BYTE $0x5E
+ CALL _strayintr(SB); BYTE $0x5F
+ CALL _strayintr(SB); BYTE $0x60
+ CALL _strayintr(SB); BYTE $0x61
+ CALL _strayintr(SB); BYTE $0x62
+ CALL _strayintr(SB); BYTE $0x63
+ CALL _strayintr(SB); BYTE $0x64
+ CALL _strayintr(SB); BYTE $0x65
+ CALL _strayintr(SB); BYTE $0x66
+ CALL _strayintr(SB); BYTE $0x67
+ CALL _strayintr(SB); BYTE $0x68
+ CALL _strayintr(SB); BYTE $0x69
+ CALL _strayintr(SB); BYTE $0x6A
+ CALL _strayintr(SB); BYTE $0x6B
+ CALL _strayintr(SB); BYTE $0x6C
+ CALL _strayintr(SB); BYTE $0x6D
+ CALL _strayintr(SB); BYTE $0x6E
+ CALL _strayintr(SB); BYTE $0x6F
+ CALL _strayintr(SB); BYTE $0x70
+ CALL _strayintr(SB); BYTE $0x71
+ CALL _strayintr(SB); BYTE $0x72
+ CALL _strayintr(SB); BYTE $0x73
+ CALL _strayintr(SB); BYTE $0x74
+ CALL _strayintr(SB); BYTE $0x75
+ CALL _strayintr(SB); BYTE $0x76
+ CALL _strayintr(SB); BYTE $0x77
+ CALL _strayintr(SB); BYTE $0x78
+ CALL _strayintr(SB); BYTE $0x79
+ CALL _strayintr(SB); BYTE $0x7A
+ CALL _strayintr(SB); BYTE $0x7B
+ CALL _strayintr(SB); BYTE $0x7C
+ CALL _strayintr(SB); BYTE $0x7D
+ CALL _strayintr(SB); BYTE $0x7E
+ CALL _strayintr(SB); BYTE $0x7F
+ CALL _strayintr(SB); BYTE $0x80 /* Vector[A]PIC */
+ CALL _strayintr(SB); BYTE $0x81
+ CALL _strayintr(SB); BYTE $0x82
+ CALL _strayintr(SB); BYTE $0x83
+ CALL _strayintr(SB); BYTE $0x84
+ CALL _strayintr(SB); BYTE $0x85
+ CALL _strayintr(SB); BYTE $0x86
+ CALL _strayintr(SB); BYTE $0x87
+ CALL _strayintr(SB); BYTE $0x88
+ CALL _strayintr(SB); BYTE $0x89
+ CALL _strayintr(SB); BYTE $0x8A
+ CALL _strayintr(SB); BYTE $0x8B
+ CALL _strayintr(SB); BYTE $0x8C
+ CALL _strayintr(SB); BYTE $0x8D
+ CALL _strayintr(SB); BYTE $0x8E
+ CALL _strayintr(SB); BYTE $0x8F
+ CALL _strayintr(SB); BYTE $0x90
+ CALL _strayintr(SB); BYTE $0x91
+ CALL _strayintr(SB); BYTE $0x92
+ CALL _strayintr(SB); BYTE $0x93
+ CALL _strayintr(SB); BYTE $0x94
+ CALL _strayintr(SB); BYTE $0x95
+ CALL _strayintr(SB); BYTE $0x96
+ CALL _strayintr(SB); BYTE $0x97
+ CALL _strayintr(SB); BYTE $0x98
+ CALL _strayintr(SB); BYTE $0x99
+ CALL _strayintr(SB); BYTE $0x9A
+ CALL _strayintr(SB); BYTE $0x9B
+ CALL _strayintr(SB); BYTE $0x9C
+ CALL _strayintr(SB); BYTE $0x9D
+ CALL _strayintr(SB); BYTE $0x9E
+ CALL _strayintr(SB); BYTE $0x9F
+ CALL _strayintr(SB); BYTE $0xA0
+ CALL _strayintr(SB); BYTE $0xA1
+ CALL _strayintr(SB); BYTE $0xA2
+ CALL _strayintr(SB); BYTE $0xA3
+ CALL _strayintr(SB); BYTE $0xA4
+ CALL _strayintr(SB); BYTE $0xA5
+ CALL _strayintr(SB); BYTE $0xA6
+ CALL _strayintr(SB); BYTE $0xA7
+ CALL _strayintr(SB); BYTE $0xA8
+ CALL _strayintr(SB); BYTE $0xA9
+ CALL _strayintr(SB); BYTE $0xAA
+ CALL _strayintr(SB); BYTE $0xAB
+ CALL _strayintr(SB); BYTE $0xAC
+ CALL _strayintr(SB); BYTE $0xAD
+ CALL _strayintr(SB); BYTE $0xAE
+ CALL _strayintr(SB); BYTE $0xAF
+ CALL _strayintr(SB); BYTE $0xB0
+ CALL _strayintr(SB); BYTE $0xB1
+ CALL _strayintr(SB); BYTE $0xB2
+ CALL _strayintr(SB); BYTE $0xB3
+ CALL _strayintr(SB); BYTE $0xB4
+ CALL _strayintr(SB); BYTE $0xB5
+ CALL _strayintr(SB); BYTE $0xB6
+ CALL _strayintr(SB); BYTE $0xB7
+ CALL _strayintr(SB); BYTE $0xB8
+ CALL _strayintr(SB); BYTE $0xB9
+ CALL _strayintr(SB); BYTE $0xBA
+ CALL _strayintr(SB); BYTE $0xBB
+ CALL _strayintr(SB); BYTE $0xBC
+ CALL _strayintr(SB); BYTE $0xBD
+ CALL _strayintr(SB); BYTE $0xBE
+ CALL _strayintr(SB); BYTE $0xBF
+ CALL _strayintr(SB); BYTE $0xC0
+ CALL _strayintr(SB); BYTE $0xC1
+ CALL _strayintr(SB); BYTE $0xC2
+ CALL _strayintr(SB); BYTE $0xC3
+ CALL _strayintr(SB); BYTE $0xC4
+ CALL _strayintr(SB); BYTE $0xC5
+ CALL _strayintr(SB); BYTE $0xC6
+ CALL _strayintr(SB); BYTE $0xC7
+ CALL _strayintr(SB); BYTE $0xC8
+ CALL _strayintr(SB); BYTE $0xC9
+ CALL _strayintr(SB); BYTE $0xCA
+ CALL _strayintr(SB); BYTE $0xCB
+ CALL _strayintr(SB); BYTE $0xCC
+ CALL _strayintr(SB); BYTE $0xCD
+ CALL _strayintr(SB); BYTE $0xCE
+ CALL _strayintr(SB); BYTE $0xCF
+ CALL _strayintr(SB); BYTE $0xD0
+ CALL _strayintr(SB); BYTE $0xD1
+ CALL _strayintr(SB); BYTE $0xD2
+ CALL _strayintr(SB); BYTE $0xD3
+ CALL _strayintr(SB); BYTE $0xD4
+ CALL _strayintr(SB); BYTE $0xD5
+ CALL _strayintr(SB); BYTE $0xD6
+ CALL _strayintr(SB); BYTE $0xD7
+ CALL _strayintr(SB); BYTE $0xD8
+ CALL _strayintr(SB); BYTE $0xD9
+ CALL _strayintr(SB); BYTE $0xDA
+ CALL _strayintr(SB); BYTE $0xDB
+ CALL _strayintr(SB); BYTE $0xDC
+ CALL _strayintr(SB); BYTE $0xDD
+ CALL _strayintr(SB); BYTE $0xDE
+ CALL _strayintr(SB); BYTE $0xDF
+ CALL _strayintr(SB); BYTE $0xE0
+ CALL _strayintr(SB); BYTE $0xE1
+ CALL _strayintr(SB); BYTE $0xE2
+ CALL _strayintr(SB); BYTE $0xE3
+ CALL _strayintr(SB); BYTE $0xE4
+ CALL _strayintr(SB); BYTE $0xE5
+ CALL _strayintr(SB); BYTE $0xE6
+ CALL _strayintr(SB); BYTE $0xE7
+ CALL _strayintr(SB); BYTE $0xE8
+ CALL _strayintr(SB); BYTE $0xE9
+ CALL _strayintr(SB); BYTE $0xEA
+ CALL _strayintr(SB); BYTE $0xEB
+ CALL _strayintr(SB); BYTE $0xEC
+ CALL _strayintr(SB); BYTE $0xED
+ CALL _strayintr(SB); BYTE $0xEE
+ CALL _strayintr(SB); BYTE $0xEF
+ CALL _strayintr(SB); BYTE $0xF0
+ CALL _strayintr(SB); BYTE $0xF1
+ CALL _strayintr(SB); BYTE $0xF2
+ CALL _strayintr(SB); BYTE $0xF3
+ CALL _strayintr(SB); BYTE $0xF4
+ CALL _strayintr(SB); BYTE $0xF5
+ CALL _strayintr(SB); BYTE $0xF6
+ CALL _strayintr(SB); BYTE $0xF7
+ CALL _strayintr(SB); BYTE $0xF8
+ CALL _strayintr(SB); BYTE $0xF9
+ CALL _strayintr(SB); BYTE $0xFA
+ CALL _strayintr(SB); BYTE $0xFB
+ CALL _strayintr(SB); BYTE $0xFC
+ CALL _strayintr(SB); BYTE $0xFD
+ CALL _strayintr(SB); BYTE $0xFE
+ CALL _strayintr(SB); BYTE $0xFF
M pc/main.c => pc/main.c +17 -4
@@ 6,6 6,7 @@
#include "io.h"
#include "ureg.h"
#include "init.h"
+#include "pool.h"
Mach *m;
@@ 128,7 129,7 @@ main(void)
*/
conf.nmach = 1;
MACHP(0) = (Mach*)CPU0MACH;
- m->pdb = (void*)CPU0PDB;
+ m->pdb = (ulong*)CPU0PDB;
machinit();
active.machs = 1;
active.exiting = 0;
@@ 155,6 156,7 @@ main(void)
procinit0();
initseg();
links();
+conf.monitor = 1;
chandevreset();
swapinit();
userinit();
@@ 165,7 167,7 @@ void
machinit(void)
{
int machno;
- void *pdb;
+ ulong *pdb;
machno = m->machno;
pdb = m->pdb;
@@ 388,8 390,19 @@ confinit(void)
meminit(maxmem);
conf.npage = conf.npage0 + conf.npage1;
- if(pcnt < 10)
- pcnt = 70;
+ if(cpuserver) {
+ if(pcnt < 10)
+ pcnt = 70;
+ } else {
+ if(pcnt < 10) {
+ if(conf.npage*BY2PG < 16*MB)
+ pcnt = 40;
+ else
+ pcnt = 60;
+ }
+ if(conf.npage*BY2PG < 16*MB)
+ poolsetparam("Image", 0, 0, 4*1024*1024);
+ }
conf.upages = (conf.npage*pcnt)/100;
conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
M pc/mem.h => pc/mem.h +4 -7
@@ 16,8 16,7 @@
#define PGROUND(s) ROUND(s, BY2PG)
#define MAXMACH 8 /* max # cpus system can run */
-#define KSTACK 4096-16 /* Size of kernel stack */
- /* the -16 is room for the 2n allocator header */
+#define KSTACK 4096 /* Size of kernel stack */
/*
* Time
@@ 35,12 34,10 @@
#define APBOOTSTRAP 0x80001000 /* AP bootstrap code */
#define CONFADDR 0x80001200 /* info passed from boot loader */
#define CPU0PDB 0x80002000 /* bootstrap processor PDB */
-#define CPU0PTE 0x80003000 /* bootstrap processor PTE's for 0-2MB */
-#define CPU0MACHPTE 0x80004000 /* bootstrap processor PTE for MACHADDR */
+#define CPU0PTE 0x80003000 /* bootstrap processor PTE's for 0-4MB */
+#define MACHADDR 0x80004000 /* as seen by current processor */
#define CPU0MACH 0x80005000 /* Mach for bootstrap processor */
-
-#define MACHADDR 0xFEF00000 /* as seen by current processor */
-#define MACHSIZE 4096
+#define MACHSIZE BY2PG
/*
* Address spaces
M pc/memory.c => pc/memory.c +9 -6
@@ 74,6 74,7 @@ static RMap rmapumbrw = {
&mapumbrw[7],
};
+#define notdef
#ifdef notdef
void
dumpmembank(void)
@@ 302,7 303,7 @@ ramscan(ulong maxmem)
* pool later if it isn't needed.
*/
va = KADDR(pa);
- table = &((ulong*)m->pdb)[PDX(va)];
+ table = &m->pdb[PDX(va)];
if(*table == 0){
if(map == 0 && (map = mapalloc(&rmapram, 0, BY2PG, BY2PG)) == 0)
break;
@@ 365,7 366,7 @@ ramscan(ulong maxmem)
* initialised space for the page table.
*/
if((pa % (4*MB)) == 0){
- table = &((ulong*)m->pdb)[PDX(va)];
+ table = &m->pdb[PDX(va)];
if(nvalid[MemUPA] == (4*MB)/BY2PG)
*table = 0;
else if(nvalid[MemRAM] == (4*MB)/BY2PG && (m->cpuiddx & 0x08))
@@ 383,8 384,9 @@ ramscan(ulong maxmem)
mapfree(&rmapram, map, BY2PG);
if(pa < maxmem)
mapfree(&rmapupa, pa, maxmem-pa);
- if(maxmem < 0xFEC00000)
- mapfree(&rmapupa, maxmem, 0xFEC00000-maxmem);
+ if(maxmem < 0xFFE00000)
+ mapfree(&rmapupa, maxmem, 0xFFE00000-maxmem);
+print("maxmem %uX %uX\n", maxmem, 0xFFE00000-maxmem);
*k0 = kzero;
}
@@ 401,11 403,11 @@ meminit(ulong maxmem)
* then scan for useful memory.
*/
for(pa = 0xA0000; pa < 0xC0000; pa += BY2PG){
- pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 0);
+ pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0);
*pte |= PTEWT;
}
for(pa = 0xC0000; pa < 0x100000; pa += BY2PG){
- pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 0);
+ pte = mmuwalk(m->pdb, (ulong)KADDR(pa), 2, 0);
*pte |= PTEUNCACHED;
}
mmuflushtlb(PADDR(m->pdb));
@@ 432,6 434,7 @@ meminit(ulong maxmem)
conf.base1 = xmp->addr;
conf.npage1 = xmp->size/BY2PG;
}
+dumpmembank();
}
ulong
M pc/mmu.c => pc/mmu.c +116 -27
@@ 111,7 111,7 @@ mmuswitch(Proc* p)
if(p->mmupdb){
top = (ulong*)p->mmupdb->va;
- top[PDX(MACHADDR)] = ((ulong*)m->pdb)[PDX(MACHADDR)];
+ top[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)];
taskswitch(p->mmupdb->pa, (ulong)(p->kstack+KSTACK));
}
else
@@ 224,34 224,50 @@ putmmu(ulong va, ulong pa, Page* pg)
up->mmuused = pg;
}
- pt = (ulong*)(PPN(pdb[pdbx])|KZERO);
+ pt = KADDR(PPN(pdb[pdbx]));
pt[PTX(va)] = pa|PTEUSER;
s = splhi();
- pdb[PDX(MACHADDR)] = ((ulong*)m->pdb)[PDX(MACHADDR)];
+ pdb[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)];
mmuflushtlb(up->mmupdb->pa);
splx(s);
}
ulong*
-mmuwalk(ulong* pdb, ulong va, int create)
+mmuwalk(ulong* pdb, ulong va, int level, int create)
{
ulong pa, *table;
+ /*
+ * Walk the page-table pointed to by pdb and return a pointer
+ * to the entry for virtual address va at the requested level.
+ * If the entry is invalid and create isn't requested then bail
+ * out early. Otherwise, for the 2nd level walk, allocate a new
+ * page-table page and register it in the 1st level.
+ */
table = &pdb[PDX(va)];
- if(*table == 0){
- if(create == 0)
- return 0;
- pa = PADDR((ulong)xspanalloc(BY2PG, BY2PG, 0));
- *table = pa|PTEWRITE|PTEVALID;
- }
- if(*table & PTESIZE)
+ if(!(*table & PTEVALID) && create == 0)
+ return 0;
+
+ switch(level){
+
+ default:
+ return 0;
+
+ case 1:
return table;
- table = (ulong*)(KZERO|PPN(*table));
- va = PTX(va);
+ case 2:
+ if(*table & PTESIZE)
+ panic("mmuwalk2: va %uX entry %uX\n", va, *table);
+ if(!(*table & PTEVALID)){
+ pa = PADDR(xspanalloc(BY2PG, BY2PG, 0));
+ *table = pa|PTEWRITE|PTEVALID;
+ }
+ table = KADDR(PPN(*table));
- return &table[va];
+ return &table[PTX(va)];
+ }
}
static Lock mmukmaplock;
@@ 260,20 276,24 @@ int
mmukmapsync(ulong va)
{
Mach *mach0;
- ulong entry;
+ ulong entry, *pte;
mach0 = MACHP(0);
lock(&mmukmaplock);
- if(mmuwalk(mach0->pdb, va, 0) == nil){
+ if((pte = mmuwalk(mach0->pdb, va, 1, 0)) == nil){
+ unlock(&mmukmaplock);
+ return 0;
+ }
+ if(!(*pte & PTESIZE) && mmuwalk(mach0->pdb, va, 2, 0) == nil){
unlock(&mmukmaplock);
return 0;
}
- entry = ((ulong*)mach0->pdb)[PDX(va)];
+ entry = *pte;
- if(!(((ulong*)m->pdb)[PDX(va)] & PTEVALID))
- ((ulong*)m->pdb)[PDX(va)] = entry;
+ if(!(m->pdb[PDX(va)] & PTEVALID))
+ m->pdb[PDX(va)] = entry;
if(up && up->mmupdb){
((ulong*)up->mmupdb->va)[PDX(va)] = entry;
@@ 291,34 311,103 @@ ulong
mmukmap(ulong pa, ulong va, int size)
{
Mach *mach0;
- ulong ova, pae, *table, pgsz, *pte;
+ ulong ova, pae, *table, pgsz, *pte, x;
+ int pse, sync;
+
+ mach0 = MACHP(0);
+ if((mach0->cpuiddx & 0x08) && (getcr4() & 0x10))
+ pse = 1;
+ else
+ pse = 0;
+ sync = 0;
- pa &= ~(BY2PG-1);
+ pa = PPN(pa);
if(va == 0)
va = (ulong)KADDR(pa);
- va &= ~(BY2PG-1);
+ else
+ va = PPN(va);
ova = va;
pae = pa + size;
- mach0 = MACHP(0);
lock(&mmukmaplock);
while(pa < pae){
- table = &((ulong*)mach0->pdb)[PDX(va)];
- if((pa % (4*MB)) == 0 && (mach0->cpuiddx & 0x08)){
+ table = &mach0->pdb[PDX(va)];
+ /*
+ * Possibly already mapped.
+ */
+ if(*table & PTEVALID){
+ if(*table & PTESIZE){
+ /*
+ * Big page. Does it fit within?
+ * If it does, adjust pgsz so the correct end can be
+ * returned and get out.
+ * If not, adjust pgsz up to the next 4MB boundary
+ * and continue.
+ */
+ x = PPN(*table);
+ if(x != pa)
+ panic("mmukmap1: pa %ux entry %uX\n",
+ pa, *table);
+ x += 4*MB;
+ if(pae <= x){
+ pa = pae;
+ break;
+ }
+ pgsz = x - pa;
+ pa += pgsz;
+ va += pgsz;
+
+ continue;
+ }
+ else{
+ /*
+ * Little page. Walk to the entry.
+ * If the entry is valid, set pgsz and continue.
+ * If not, make it so, set pgsz, sync and continue.
+ */
+ pte = mmuwalk(mach0->pdb, va, 2, 0);
+ if(pte && *pte & PTEVALID){
+ x = PPN(*pte);
+ if(x != pa)
+ panic("mmukmap2: pa %ux entry %uX\n",
+ pa, *pte);
+ pgsz = BY2PG;
+ pa += pgsz;
+ va += pgsz;
+ sync++;
+
+ continue;
+ }
+ }
+ }
+
+ /*
+ * Not mapped. Check if it can be mapped using a big page -
+ * starts on a 4MB boundary, size >= 4MB and processor can do it.
+ * If not a big page, walk the walk, talk the talk.
+ * Sync is set.
+ */
+ if(pse && (pa % (4*MB)) == 0 && (pae >= pa+4*MB)){
*table = pa|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID;
pgsz = 4*MB;
}
else{
- pte = mmuwalk(mach0->pdb, va, 1);
+ pte = mmuwalk(mach0->pdb, va, 2, 1);
*pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID;
pgsz = BY2PG;
}
pa += pgsz;
va += pgsz;
+ sync++;
}
unlock(&mmukmaplock);
- mmukmapsync(ova);
+ /*
+ * If something was added
+ * then need to sync up.
+ */
+ if(sync)
+ mmukmapsync(ova);
return pa;
}
M pc/mouse.c => pc/mouse.c +14 -1
@@ 6,10 6,23 @@
#include "../port/error.h"
#include "io.h"
-#include <libg.h>
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
#include "screen.h"
/*
+ * mouse types
+ */
+enum
+{
+ Mouseother= 0,
+ Mouseserial= 1,
+ MousePS2= 2,
+};
+static int mousetype;
+
+/*
* setup a serial mouse
*/
static void
M pc/mp.c => pc/mp.c +23 -31
@@ 124,27 124,20 @@ static Apic*
mkioapic(PCMPioapic* p)
{
Apic *apic;
- ulong addr, *pte;
if(!(p->flags & PcmpEN) || p->apicno > MaxAPICNO)
return 0;
/*
- * Map the I/O APIC. This should be in the same 4MB segment
- * as MACHADDR so no new 2nd level table will be allocated.
+ * Map the I/O APIC.
*/
- addr = p->addr;
- if((pte = mmuwalk(m->pdb, addr, 1)) == 0)
+ if(mmukmap(p->addr, 0, 1024) == 0)
return 0;
- if(!(*pte & PTEVALID)){
- *pte = addr|PTEWRITE|PTEUNCACHED|PTEVALID;
- mmuflushtlb(PADDR(m->pdb));
- }
apic = &mpapic[p->apicno];
apic->type = PcmpIOAPIC;
apic->apicno = p->apicno;
- apic->addr = KADDR(addr);
+ apic->addr = KADDR(p->addr);
apic->flags = p->flags;
return apic;
@@ 290,8 283,7 @@ squidboy(Apic* apic)
{
int clkin;
- /*iprint("Hello Squidboy\n");*/
-
+// iprint("Hello Squidboy\n");
machinit();
mmuinit();
@@ 322,25 314,31 @@ static void
mpstartap(Apic* apic)
{
ulong *apbootp, *pdb, *pte;
- Mach *mach;
+ Mach *mach, *mach0;
int i, machno;
uchar *p;
+ mach0 = MACHP(0);
+
/*
- * Initialise the AP page-tables and Mach structure. These are
- * the same as for the bootstrap processor with the exception of
+ * Initialise the AP page-tables and Mach structure. The page-tables
+ * are the same as for the bootstrap processor with the exception of
* the PTE for the Mach structure.
* Xspanalloc will panic if an allocation can't be made.
*/
- pdb = xspanalloc(3*BY2PG, BY2PG, 0);
- memmove(pdb, (void*)CPU0PDB, BY2PG);
+ p = xspanalloc(3*BY2PG, BY2PG, 0);
+ pdb = (ulong*)p;
+ memmove(pdb, mach0->pdb, BY2PG);
+ p += BY2PG;
- pte = (ulong*)(((uchar*)pdb)+BY2PG);
- memmove(pte, (void*)CPU0MACHPTE, BY2PG);
- pdb[PDX(MACHADDR)] = PADDR(pte)|PTEWRITE|PTEVALID;
+ if((pte = mmuwalk(pdb, MACHADDR, 1, 0)) == nil)
+ return;
+ memmove(p, KADDR(PPN(*pte)), BY2PG);
+ *pte = PADDR(p)|PTEWRITE|PTEVALID;
+ p += BY2PG;
- mach = (Mach*)(((uchar*)pdb)+2*BY2PG);
- if((pte = mmuwalk(pdb, MACHADDR, 0)) == 0)
+ mach = (Mach*)p;
+ if((pte = mmuwalk(pdb, MACHADDR, 2, 0)) == nil)
return;
*pte = PADDR(mach)|PTEWRITE|PTEVALID;
@@ 386,7 384,6 @@ void
mpinit(void)
{
PCMP *pcmp;
- ulong *pte;
uchar *e, *p;
Apic *apic, *bpapic;
int clkin;
@@ 398,15 395,10 @@ mpinit(void)
pcmp = KADDR(_mp_->physaddr);
/*
- * Map the local APIC. This should be in the same 4MB segment
- * as MACHADDR so no new 2nd level table will be allocated.
+ * Map the local APIC.
*/
- if((pte = mmuwalk(m->pdb, pcmp->lapicbase, 1)) == 0)
+ if(mmukmap(pcmp->lapicbase, 0, 1024) == 0)
return;
- if(!(*pte & PTEVALID)){
- *pte = pcmp->lapicbase|PTEWRITE|PTEUNCACHED|PTEVALID;
- mmuflushtlb(PADDR(m->pdb));
- }
bpapic = 0;
@@ 633,7 625,7 @@ mpshutdown(void)
* warm-boot sequence is tried. The following is Intel specific and
* seems to perform a cold-boot, but at least it comes back.
*/
- *(ushort*)(KZERO|0x472) = 0x1234; /* BIOS warm-boot flag */
+ *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */
outb(0xCF9, 0x02);
outb(0xCF9, 0x06);
#else
M pc/pci.c => pc/pci.c +7 -2
@@ 29,6 29,7 @@ static int pcicfgmode = -1;
static int pcimaxdno;
static Pcidev* pciroot;
static Pcidev* pcilist;
+static Pcidev* pcitail;
static int pcicfgrw8(int, int, int, int);
static int pcicfgrw16(int, int, int, int);
@@ 62,8 63,12 @@ pciscan(int bno, Pcidev** list)
p->tbdf = tbdf;
p->vid = l;
p->did = l>>16;
- p->list = pcilist;
- pcilist = p;
+
+ if(pcilist != nil)
+ pcitail->list = p;
+ else
+ pcilist = p;
+ pcitail = p;
p->intl = pcicfgrw8(tbdf, PciINTL, 0, 1);
p->ccru = pcicfgrw16(tbdf, PciCCRu, 0, 1);
M pc/screen.c => pc/screen.c +244 -255
@@ 4,306 4,295 @@
#include "dat.h"
#include "fns.h"
#include "io.h"
+#include "ureg.h"
#include "../port/error.h"
-#include <libg.h>
-#include <gnot.h>
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
#include "screen.h"
-#include "vga.h"
-
-/*
- * CGA-only hack.
- */
-/* imported */
-extern GSubfont defont0;
-extern Cursor arrow;
-extern GBitmap cursorback;
-
-/* exported */
-GSubfont *defont;
-int islittle = 1; /* little endian bit ordering in bytes */
-GBitmap gscreen;
-
-/* local */
-static Lock vgalock;
-static ulong colormap[256][3];
-static Rectangle mbb;
-
-/*
- * reverse pixels into little endian order
- */
-uchar revtab0[] = {
- 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
- 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
- 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
- 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
- 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
- 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
- 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
- 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
- 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
- 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
- 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
- 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
- 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
- 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
- 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
- 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
- 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
- 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
- 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
- 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
- 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
- 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
- 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
- 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
- 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
- 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
- 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
- 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
- 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
- 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
- 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
- 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
-};
-uchar revtab1[] = {
- 0x00, 0x40, 0x80, 0xc0, 0x10, 0x50, 0x90, 0xd0,
- 0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0,
- 0x04, 0x44, 0x84, 0xc4, 0x14, 0x54, 0x94, 0xd4,
- 0x24, 0x64, 0xa4, 0xe4, 0x34, 0x74, 0xb4, 0xf4,
- 0x08, 0x48, 0x88, 0xc8, 0x18, 0x58, 0x98, 0xd8,
- 0x28, 0x68, 0xa8, 0xe8, 0x38, 0x78, 0xb8, 0xf8,
- 0x0c, 0x4c, 0x8c, 0xcc, 0x1c, 0x5c, 0x9c, 0xdc,
- 0x2c, 0x6c, 0xac, 0xec, 0x3c, 0x7c, 0xbc, 0xfc,
- 0x01, 0x41, 0x81, 0xc1, 0x11, 0x51, 0x91, 0xd1,
- 0x21, 0x61, 0xa1, 0xe1, 0x31, 0x71, 0xb1, 0xf1,
- 0x05, 0x45, 0x85, 0xc5, 0x15, 0x55, 0x95, 0xd5,
- 0x25, 0x65, 0xa5, 0xe5, 0x35, 0x75, 0xb5, 0xf5,
- 0x09, 0x49, 0x89, 0xc9, 0x19, 0x59, 0x99, 0xd9,
- 0x29, 0x69, 0xa9, 0xe9, 0x39, 0x79, 0xb9, 0xf9,
- 0x0d, 0x4d, 0x8d, 0xcd, 0x1d, 0x5d, 0x9d, 0xdd,
- 0x2d, 0x6d, 0xad, 0xed, 0x3d, 0x7d, 0xbd, 0xfd,
- 0x02, 0x42, 0x82, 0xc2, 0x12, 0x52, 0x92, 0xd2,
- 0x22, 0x62, 0xa2, 0xe2, 0x32, 0x72, 0xb2, 0xf2,
- 0x06, 0x46, 0x86, 0xc6, 0x16, 0x56, 0x96, 0xd6,
- 0x26, 0x66, 0xa6, 0xe6, 0x36, 0x76, 0xb6, 0xf6,
- 0x0a, 0x4a, 0x8a, 0xca, 0x1a, 0x5a, 0x9a, 0xda,
- 0x2a, 0x6a, 0xaa, 0xea, 0x3a, 0x7a, 0xba, 0xfa,
- 0x0e, 0x4e, 0x8e, 0xce, 0x1e, 0x5e, 0x9e, 0xde,
- 0x2e, 0x6e, 0xae, 0xee, 0x3e, 0x7e, 0xbe, 0xfe,
- 0x03, 0x43, 0x83, 0xc3, 0x13, 0x53, 0x93, 0xd3,
- 0x23, 0x63, 0xa3, 0xe3, 0x33, 0x73, 0xb3, 0xf3,
- 0x07, 0x47, 0x87, 0xc7, 0x17, 0x57, 0x97, 0xd7,
- 0x27, 0x67, 0xa7, 0xe7, 0x37, 0x77, 0xb7, 0xf7,
- 0x0b, 0x4b, 0x8b, 0xcb, 0x1b, 0x5b, 0x9b, 0xdb,
- 0x2b, 0x6b, 0xab, 0xeb, 0x3b, 0x7b, 0xbb, 0xfb,
- 0x0f, 0x4f, 0x8f, 0xcf, 0x1f, 0x5f, 0x9f, 0xdf,
- 0x2f, 0x6f, 0xaf, 0xef, 0x3f, 0x7f, 0xbf, 0xff,
+
+static ulong onesbits = ~0;
+static Memdata onesdata = {
+ nil,
+ &onesbits,
};
-uchar revtab2[] = {
- 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
- 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0,
- 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
- 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1, 0xf1,
- 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
- 0x82, 0x92, 0xa2, 0xb2, 0xc2, 0xd2, 0xe2, 0xf2,
- 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
- 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3,
- 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
- 0x84, 0x94, 0xa4, 0xb4, 0xc4, 0xd4, 0xe4, 0xf4,
- 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
- 0x85, 0x95, 0xa5, 0xb5, 0xc5, 0xd5, 0xe5, 0xf5,
- 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
- 0x86, 0x96, 0xa6, 0xb6, 0xc6, 0xd6, 0xe6, 0xf6,
- 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
- 0x87, 0x97, 0xa7, 0xb7, 0xc7, 0xd7, 0xe7, 0xf7,
- 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
- 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0xd8, 0xe8, 0xf8,
- 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
- 0x89, 0x99, 0xa9, 0xb9, 0xc9, 0xd9, 0xe9, 0xf9,
- 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a,
- 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa,
- 0x0b, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b,
- 0x8b, 0x9b, 0xab, 0xbb, 0xcb, 0xdb, 0xeb, 0xfb,
- 0x0c, 0x1c, 0x2c, 0x3c, 0x4c, 0x5c, 0x6c, 0x7c,
- 0x8c, 0x9c, 0xac, 0xbc, 0xcc, 0xdc, 0xec, 0xfc,
- 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d,
- 0x8d, 0x9d, 0xad, 0xbd, 0xcd, 0xdd, 0xed, 0xfd,
- 0x0e, 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e,
- 0x8e, 0x9e, 0xae, 0xbe, 0xce, 0xde, 0xee, 0xfe,
- 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f,
- 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff,
+static Memimage xones = {
+ { 0, 0, 1, 1 },
+ { -100000, -100000, 100000, 100000 },
+ 3,
+ 1,
+ &onesdata,
+ 0,
+ 1
};
+Memimage *memones = &xones;
-void
-pixreverse(uchar *p, int len, int ldepth)
-{
- uchar *e;
- uchar *tab;
+Point ZP = {0, 0};
- switch(ldepth){
- case 0:
- tab = revtab0;
- break;
- case 1:
- tab = revtab1;
- break;
- case 2:
- tab = revtab2;
- break;
- default:
- return;
- }
+Memdata gscreendata;
+Memimage gscreen;
- for(e = p + len; p < e; p++)
- *p = tab[*p];
-}
+VGAscr vgascreen[1];
-static void
-crout(int reg, int val)
+int
+screensize(int x, int y, int z)
{
- outb(CRX, reg);
- outb(CR, val);
-}
+ VGAscr *scr;
-void
-screeninit(void)
-{
- int i;
- ulong *l;
+ scr = &vgascreen[0];
/*
- * arrow is defined as a big endian
+ * BUG: need to check if any xalloc'ed memory needs to
+ * be given back if aperture is set.
*/
- pixreverse(arrow.set, 2*16, 0);
- pixreverse(arrow.clr, 2*16, 0);
+ if(scr->aperture == 0){
+ int width = (x*(1<<z))/BI2WD;
- /*
- * swizzle the font longs. we do both byte and bit swizzling
- * since the font is initialized with big endian longs.
- */
- defont = &defont0;
- l = defont->bits->base;
- for(i = defont->bits->width*Dy(defont->bits->r); i > 0; i--, l++)
- *l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24);
- pixreverse((uchar*)defont->bits->base,
- defont->bits->width*BY2WD*Dy(defont->bits->r), 0);
-
- crout(0x0a, 0xff); /* turn off cursor */
- memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT);
+ gscreendata.data = xalloc(width*BY2WD*y);
+ if(gscreendata.data == 0)
+ error("screensize: vga soft memory");
+ memset(gscreendata.data, Backgnd, width*BY2WD*y);
+ scr->useflush = 1;
+
+ scr->aperture = 0xA0000;
+ scr->apsize = 1<<16;
+ }
+ else
+ gscreendata.data = KADDR(scr->aperture);
+
+ gscreen.data = &gscreendata;
+ gscreen.ldepth = z;
+ gscreen.width = (x*(1<<gscreen.ldepth)+31)/32;
+ gscreen.r.min = ZP;
+ gscreen.r.max = Pt(x, y);
+ gscreen.clipr = gscreen.r;
+ gscreen.repl = 0;
+
+ scr->gscreendata = gscreen.data;
+ scr->memdefont = getmemdefont();
+ scr->gscreen = &gscreen;
+
+// memset(gscreen.data->data, Backgnd, scr->apsize);
+
+ drawcmap(0);
+
+ return 0;
}
-static void
-cgascreenputc(int c)
+int
+screenaperture(int size, int align)
{
- int i;
- static int color;
- static int pos;
-
- if(c == '\n'){
- pos = pos/CGAWIDTH;
- pos = (pos+1)*CGAWIDTH;
- } else if(c == '\t'){
- i = 8 - ((pos/2)&7);
- while(i-->0)
- cgascreenputc(' ');
- } else if(c == '\b'){
- if(pos >= 2)
- pos -= 2;
- cgascreenputc(' ');
- pos -= 2;
- } else {
- CGASCREEN[pos++] = c;
- CGASCREEN[pos++] = 2; /* green on black */
+ VGAscr *scr;
+ ulong aperture;
+
+ scr = &vgascreen[0];
+
+ if(size == 0){
+ if(scr->aperture && scr->isupamem)
+ upafree(scr->aperture, scr->apsize);
+ scr->aperture = 0;
+ scr->isupamem = 0;
+ return 0;
+ }
+ if(scr->dev && scr->dev->linear){
+ aperture = scr->dev->linear(scr, &size, &align);
+ if(aperture == 0)
+ return 1;
}
- if(pos >= CGAWIDTH*CGAHEIGHT){
- memmove(CGASCREEN, &CGASCREEN[CGAWIDTH], CGAWIDTH*(CGAHEIGHT-1));
- memset(&CGASCREEN[CGAWIDTH*(CGAHEIGHT-1)], 0, CGAWIDTH);
- pos = CGAWIDTH*(CGAHEIGHT-1);
+ else{
+ aperture = upamalloc(0, size, align);
+ if(aperture == 0)
+ return 1;
+
+ if(scr->aperture && scr->isupamem)
+ upafree(scr->aperture, scr->apsize);
+ scr->isupamem = 1;
}
+
+ scr->aperture = aperture;
+ scr->apsize = size;
+
+ return 0;
}
-void
-screenputs(char *s, int n)
+ulong*
+attachscreen(Rectangle* r, int* ld, int* width)
{
- while(n-- > 0)
- cgascreenputc(*s++);
+ VGAscr *scr;
+
+ scr = &vgascreen[0];
+ if(scr->gscreen == nil || scr->gscreendata == nil)
+ return nil;
+
+ *r = scr->gscreen->r;
+ *ld = scr->gscreen->ldepth;
+ *width = scr->gscreen->width;
+
+ return scr->gscreendata->data;
}
-/*
- * collect changes to the 'soft' screen
- */
void
-mbbrect(Rectangle r)
+flushmemscreen(Rectangle r)
{
- if (r.min.x < mbb.min.x)
- mbb.min.x = r.min.x;
- if (r.min.y < mbb.min.y)
- mbb.min.y = r.min.y;
- if (r.max.x > mbb.max.x)
- mbb.max.x = r.max.x;
- if (r.max.y > mbb.max.y)
- mbb.max.y = r.max.y;
- mousescreenupdate();
+ VGAscr *scr;
+ uchar *sp, *disp, *sdisp, *edisp;
+ int y, len, incs, off, page;
+
+ scr = &vgascreen[0];
+ if(scr->gscreen == nil || scr->useflush == 0)
+ return;
+ if(scr->dev == nil || scr->dev->page == nil)
+ return;
+
+ if(rectclip(&r, scr->gscreen->r) == 0)
+ return;
+
+ incs = scr->gscreen->width * BY2WD;
+
+ switch(scr->gscreen->ldepth){
+ default:
+ len = 0;
+ panic("flushmemscreen: ldepth\n");
+ break;
+ case 3:
+ len = Dx(r);
+ break;
+ }
+ if(len < 1)
+ return;
+
+ off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x>>(3-scr->gscreen->ldepth));
+ page = off/scr->apsize;
+ off %= scr->apsize;
+ disp = KADDR(scr->aperture);
+ sdisp = disp+off;
+ edisp = disp+scr->apsize;
+
+ off = r.min.y*scr->gscreen->width*BY2WD+(r.min.x>>(3-scr->gscreen->ldepth));
+ sp = ((uchar*)scr->gscreendata->data) + off;
+
+ scr->dev->page(scr, page);
+ for(y = r.min.y; y < r.max.y; y++) {
+ if(sdisp + incs < edisp) {
+ memmove(sdisp, sp, len);
+ sp += incs;
+ sdisp += incs;
+ }
+ else {
+ off = edisp - sdisp;
+ page++;
+ if(off <= len){
+ if(off > 0)
+ memmove(sdisp, sp, off);
+ scr->dev->page(scr, page);
+ if(len - off > 0)
+ memmove(disp, sp+off, len - off);
+ }
+ else {
+ memmove(sdisp, sp, len);
+ scr->dev->page(scr, page);
+ }
+ sp += incs;
+ sdisp += incs - scr->apsize;
+ }
+ }
}
void
-hwcursset(ulong *s, ulong *c, int ox, int oy)
+getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
{
- USED(s, c, ox, oy);
+ VGAscr *scr;
+ ulong x;
+
+ scr = &vgascreen[0];
+ if(scr->gscreen == nil)
+ return;
+
+ switch(scr->gscreen->ldepth){
+ default:
+ x = 0x0F;
+ break;
+ case 3:
+ x = 0xFF;
+ break;
+ }
+ p &= x;
+ p ^= x;
+
+ lock(&cursor);
+ *pr = scr->colormap[p][0];
+ *pg = scr->colormap[p][1];
+ *pb = scr->colormap[p][2];
+ unlock(&cursor);
}
-void
-hwcursmove(int x, int y)
+int
+setcolor(ulong p, ulong r, ulong g, ulong b)
{
- USED(x, y);
+ VGAscr *scr;
+ ulong x;
+
+ scr = &vgascreen[0];
+ if(scr->gscreen == nil)
+ return 0;
+
+ switch(scr->gscreen->ldepth){
+ default:
+ x = 0x0F;
+ break;
+ case 3:
+ x = 0xFF;
+ break;
+ }
+ p &= x;
+ p ^= x;
+
+ lock(&cursor);
+ scr->colormap[p][0] = r;
+ scr->colormap[p][1] = g;
+ scr->colormap[p][2] = b;
+ vgao(PaddrW, p);
+ vgao(Pdata, r>>(32-6));
+ vgao(Pdata, g>>(32-6));
+ vgao(Pdata, b>>(32-6));
+ unlock(&cursor);
+
+ return ~0;
}
-void
-screenload(Rectangle r, uchar *data, int tl, int l)
+int
+cursoron(int dolock)
{
- USED(r, data, tl, l);
+ VGAscr *scr;
+ int v;
+
+ scr = &vgascreen[0];
+ if(scr->cur == nil || scr->cur->move == nil)
+ return 0;
+
+ if(dolock)
+ lock(&cursor);
+ v = scr->cur->move(scr, mousexy());
+ if(dolock)
+ unlock(&cursor);
+
+ return v;
}
void
-getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
+cursoroff(int)
{
- p &= (1<<(1<<gscreen.ldepth))-1;
- lock(&vgalock);
- *pr = colormap[p][0];
- *pg = colormap[p][1];
- *pb = colormap[p][2];
- unlock(&vgalock);
}
void
-mousescreenupdate(void)
+setcursor(Cursor* curs)
{
-}
+ VGAscr *scr;
-/*
- * a fatter than usual cursor for the safari
- */
-Cursor fatarrow = {
- { -1, -1 },
- {
- 0xff, 0xff, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0c,
- 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
- 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8c, 0x04,
- 0x92, 0x08, 0x91, 0x10, 0xa0, 0xa0, 0xc0, 0x40,
- },
- {
- 0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfc, 0x7f, 0xf0,
- 0x7f, 0xe0, 0x7f, 0xe0, 0x7f, 0xf0, 0x7f, 0xf8,
- 0x7f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfc, 0x73, 0xf8,
- 0x61, 0xf0, 0x60, 0xe0, 0x40, 0x40, 0x00, 0x00,
- },
-};
+ scr = &vgascreen[0];
+ if(scr->cur == nil || scr->cur->load == nil)
+ return;
-void
-bigcursor(void)
-{
- memmove(&arrow, &fatarrow, sizeof(fatarrow));
- pixreverse(arrow.set, 2*16, 0);
- pixreverse(arrow.clr, 2*16, 0);
+ scr->cur->load(scr, curs);
}
M pc/screen.h => pc/screen.h +104 -30
@@ 1,40 1,114 @@
-typedef struct Cursorinfo Cursorinfo;
-
-struct Cursorinfo
-{
+typedef struct Cursorinfo Cursorinfo;
+struct Cursorinfo {
Cursor;
Lock;
- int visible; /* on screen */
- int disable; /* from being used */
- int frozen; /* from being used */
- Rectangle r; /* location */
- Rectangle clipr; /* r clipped into screen */
- int l; /* width of cursorwork (in bytes) */
- int tl; /* scan line byte width of mouse at r */
};
-Cursorinfo cursor;
-Cursor curs;
-extern int cursoron(int);
-extern void cursoroff(int);
-extern void setcursor(Cursor*);
+/* devmouse.c */
+extern void mousetrack(int, int, int);
+extern Point mousexy(void);
+
+extern void mouseaccelerate(char*);
+extern int m3mouseputc(void*, int);
+extern int mouseputc(void*, int);
+extern int mouseswap;
+
+extern Cursorinfo cursor;
+
+/* mouse.c */
+extern void mousectl(char*);
+
+/* screen.c */
+extern void flushmemscreen(Rectangle);
+extern int cursoron(int);
+extern void cursoroff(int);
+extern void setcursor(Cursor*);
+
+/*
+ * Generic VGA registers.
+ */
+enum {
+ MiscW = 0x03C2, /* Miscellaneous Output (W) */
+ MiscR = 0x03CC, /* Miscellaneous Output (R) */
+ Status0 = 0x03C2, /* Input status 0 (R) */
+ Status1 = 0x03DA, /* Input Status 1 (R) */
+ FeatureR = 0x03CA, /* Feature Control (R) */
+ FeatureW = 0x03DA, /* Feature Control (W) */
+
+ Seqx = 0x03C4, /* Sequencer Index, Data at Seqx+1 */
+ Crtx = 0x03D4, /* CRT Controller Index, Data at Crtx+1 */
+ Grx = 0x03CE, /* Graphics Controller Index, Data at Grx+1 */
+ Attrx = 0x03C0, /* Attribute Controller Index and Data */
+
+ PaddrW = 0x03C8, /* Palette Address Register, write */
+ Pdata = 0x03C9, /* Palette Data Register */
+ Pixmask = 0x03C6, /* Pixel Mask Register */
+ PaddrR = 0x03C7, /* Palette Address Register, read */
+ Pstatus = 0x03C7, /* DAC Status (RO) */
+
+ Pcolours = 256, /* Palette */
+ Pred = 0,
+ Pgreen = 1,
+ Pblue = 2,
+
+ Pblack = 0x00,
+ Pwhite = 0xFF,
+};
+
+#define vgai(port) inb(port)
+#define vgao(port, data) outb(port, data)
+
+extern int vgaxi(long, uchar);
+extern int vgaxo(long, uchar, uchar);
/*
- * mouse types
*/
-enum
-{
- Mouseother= 0,
- Mouseserial= 1,
- MousePS2= 2,
+typedef struct VGAdev VGAdev;
+typedef struct VGAcur VGAcur;
+typedef struct VGAscr VGAscr;
+
+struct VGAdev {
+ char* name;
+
+ void (*enable)(VGAscr*);
+ void (*disable)(VGAscr*);
+ void (*page)(VGAscr*, int);
+ ulong (*linear)(VGAscr*, int*, int*);
+};
+
+struct VGAcur {
+ char* name;
+
+ void (*enable)(VGAscr*);
+ void (*disable)(VGAscr*);
+ void (*load)(VGAscr*, Cursor*);
+ int (*move)(VGAscr*, Point);
};
-extern int mousetype;
-extern void mousectl(char*);
-extern void mousetrack(int, int, int);
-extern Point mousexy(void);
+/*
+ */
+struct VGAscr {
+ Lock devlock;
+ VGAdev* dev;
-extern void mouseaccelerate(char*);
-extern int m3mouseputc(void*, int);
-extern int mouseputc(void*, int);
-extern int mouseswap;
+ VGAcur* cur;
+ ulong storage;
+ Cursor;
+
+ int useflush;
+
+ ulong aperture; /* physical address */
+ int isupamem;
+ int apsize;
+
+ ulong colormap[Pcolours][3];
+
+ Memimage* gscreen;
+ Memdata* gscreendata;
+ Memsubfont* memdefont;
+};
+extern VGAscr vgascreen[];
+
+enum {
+ Backgnd = Pwhite,
+};
M pc/scsi.c => pc/scsi.c +1 -1
@@ 82,7 82,7 @@ scsireset(void)
ctlrno, ctlr->type, ctlr->port,
ctlr->irq, ctlr->mem, ctlr->size);
if(ctlr->mem)
- print(" addr 0x%luX", ctlr->mem & ~KZERO);
+ print(" addr 0x%luX", PADDR(ctlr->mem));
if(ctlr->size)
print(" size 0x%luX", ctlr->size);
print("\n");
M pc/trap.c => pc/trap.c +68 -60
@@ 11,7 11,6 @@ void noted(Ureg*, ulong);
static void debugbpt(Ureg*, void*);
static void fault386(Ureg*, void*);
-static void syscall(Ureg*, void*);
static Lock irqctllock;
static Irqctl *irqctl[256];
@@ 63,25 62,39 @@ nmienable(void)
void
trapinit(void)
{
- int v, pri;
+ int d1, v;
ulong vaddr;
Segdesc *idt;
idt = (Segdesc*)IDTADDR;
vaddr = (ulong)vectortable;
for(v = 0; v < 256; v++){
- if(v == VectorBPT || v == VectorSYSCALL)
- pri = 3;
- else
- pri = 0;
+ d1 = (vaddr & 0xFFFF0000)|SEGP;
+ switch(v){
+
+ case VectorBPT:
+ d1 |= SEGPL(3)|SEGIG;
+ break;
+
+ case VectorSYSCALL:
+ d1 |= SEGPL(3)|SEGTG;
+ break;
+
+ default:
+ d1 |= SEGPL(0)|SEGIG;
+ break;
+ }
idt[v].d0 = (vaddr & 0xFFFF)|(KESEL<<16);
- idt[v].d1 = (vaddr & 0xFFFF0000)|SEGP|SEGPL(pri)|SEGIG;
+ idt[v].d1 = d1;
vaddr += 6;
}
+ /*
+ * Special traps.
+ * Syscall() is called directly without going through trap().
+ */
intrenable(VectorBPT, debugbpt, 0, BUSUNKNOWN);
intrenable(VectorPF, fault386, 0, BUSUNKNOWN);
- intrenable(VectorSYSCALL, syscall, 0, BUSUNKNOWN);
nmienable();
}
@@ 113,7 126,8 @@ static int nspuriousintr;
/*
* All traps come here. It is slower to have all traps call trap() rather than
* directly vectoring the handler. However, this avoids a lot of code duplication
- * and possible bugs. trap is called splhi().
+ * and possible bugs. The only exception is VectorSYSCALL.
+ * Trap is called with interrupts disabled via interrupt-gates.
*/
void
trap(Ureg* ureg)
@@ 123,16 137,19 @@ trap(Ureg* ureg)
Irqctl *ctl;
Irq *irq;
- user = (ureg->cs & 0xFFFF) == UESEL;
- if(user)
+ user = 0;
+ if((ureg->cs & 0xFFFF) == UESEL){
+ user = 1;
up->dbgreg = ureg;
+ }
v = ureg->trap;
if(ctl = irqctl[v]){
- if(ctl->isintr)
+ if(ctl->isintr){
m->intr++;
- if(ctl->isr)
- ctl->isr(v);
+ if(ctl->isr)
+ ctl->isr(v);
+ }
for(irq = ctl->irq; irq; irq = irq->next)
irq->f(ureg, irq->a);
@@ 171,12 188,10 @@ trap(Ureg* ureg)
panic("unknown trap/intr: %d\n", v);
}
- /*
- * check user since syscall does its own notifying
- */
- splhi();
- if(v != VectorSYSCALL && user && (up->procctl || up->nnote))
+ if(user && (up->procctl || up->nnote)){
+ splhi();
notify(ureg);
+ }
}
/*
@@ 185,12 200,6 @@ trap(Ureg* ureg)
void
dumpregs2(Ureg* ureg)
{
- ureg->cs &= 0xFFFF;
- ureg->ds &= 0xFFFF;
- ureg->es &= 0xFFFF;
- ureg->fs &= 0xFFFF;
- ureg->gs &= 0xFFFF;
-
if(up)
print("cpu%d: registers for %s %d\n", m->machno, up->text, up->pid);
else
@@ 203,7 212,8 @@ dumpregs2(Ureg* ureg)
print(" SI %8.8luX DI %8.8luX BP %8.8luX\n",
ureg->si, ureg->di, ureg->bp);
print(" CS %4.4uX DS %4.4uX ES %4.4uX FS %4.4uX GS %4.4uX\n",
- ureg->cs, ureg->ds, ureg->es, ureg->fs, ureg->gs);
+ ureg->cs & 0xFFFF, ureg->ds & 0xFFFF, ureg->es & 0xFFFF,
+ ureg->fs & 0xFFFF, ureg->gs & 0xFFFF);
}
void
@@ 248,8 258,12 @@ dumpstack(void)
for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){
v = *(ulong*)l;
if(KTZERO < v && v < (ulong)&etext){
+ /*
+ * Pick off general CALL (0xE8) and CALL indirect
+ * through AX (0xFFD0).
+ */
p = (uchar*)v;
- if(*(p-5) == 0xE8){
+ if(*(p-5) == 0xE8 || (*(p-2) == 0xFF && *(p-1) == 0xD0)){
print("%lux ", p-5);
i++;
}
@@ 309,59 323,53 @@ fault386(Ureg* ureg, void*)
#include "../port/systab.h"
/*
- * syscall is called splhi()
+ * Syscall is called directly from assembler without going through trap().
*/
-static void
-syscall(Ureg* ureg, void*)
+void
+syscall(Ureg* ureg)
{
ulong sp;
long ret;
- int i;
+ int i, scallnr;
+
+ if((ureg->cs & 0xFFFF) != UESEL)
+ panic("syscall: cs 0x%4.4uX\n", ureg->cs);
m->syscall++;
up->insyscall = 1;
up->pc = ureg->pc;
up->dbgreg = ureg;
- if((ureg->cs)&0xffff == KESEL)
- panic("recursive system call");
-
- up->scallnr = ureg->ax;
- if(up->scallnr == RFORK && up->fpstate == FPactive){
- /*
- * so that the child starts out with the
- * same registers as the parent.
- * this must be atomic relative to this CPU, hence
- * the spl's.
- */
- if(up->fpstate == FPactive){
- fpsave(&up->fpsave);
- up->fpstate = FPinactive;
- }
+ scallnr = ureg->ax;
+ up->scallnr = scallnr;
+ if(scallnr == RFORK && up->fpstate == FPactive){
+ splhi();
+ fpsave(&up->fpsave);
+ up->fpstate = FPinactive;
+ spllo();
}
- spllo();
sp = ureg->usp;
up->nerrlab = 0;
ret = -1;
if(!waserror()){
- if(up->scallnr >= nsyscall){
- pprint("bad sys call number %d pc %lux\n", up->scallnr, ureg->pc);
+ if(scallnr >= nsyscall){
+ pprint("bad sys call number %d pc %lux\n", scallnr, ureg->pc);
postnote(up, 1, "sys: bad sys call", NDebug);
error(Ebadarg);
}
- if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-(1+MAXSYSARG)*BY2WD))
- validaddr(sp, (1+MAXSYSARG)*BY2WD, 0);
+ if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
+ validaddr(sp, sizeof(Sargs)+BY2WD, 0);
- up->s = *((Sargs*)(sp+1*BY2WD));
- up->psstate = sysctab[up->scallnr];
+ up->s = *((Sargs*)(sp+BY2WD));
+ up->psstate = sysctab[scallnr];
- ret = systab[up->scallnr](up->s.args);
+ ret = systab[scallnr](up->s.args);
poperror();
}
if(up->nerrlab){
- print("bad errstack [%d]: %d extra\n", up->scallnr, up->nerrlab);
+ print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
for(i = 0; i < NERR; i++)
print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
panic("error stack");
@@ 371,20 379,20 @@ syscall(Ureg* ureg, void*)
up->psstate = 0;
/*
- * Put return value in frame. On the safari the syscall is
+ * Put return value in frame. On the x86 the syscall is
* just another trap and the return value from syscall is
* ignored. On other machines the return value is put into
* the results register by caller of syscall.
*/
ureg->ax = ret;
- if(up->scallnr == NOTED)
+ if(scallnr == NOTED)
noted(ureg, *(ulong*)(sp+BY2WD));
- splhi();
- if(up->scallnr!=RFORK && (up->procctl || up->nnote))
+ if(scallnr!=RFORK && (up->procctl || up->nnote)){
+ splhi();
notify(ureg);
-
+ }
}
/*
M pc/vga.c => pc/vga.c +137 -726
@@ 1,567 1,158 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include <libg.h>
-#include <gnot.h>
-#include "screen.h"
-#include "vga.h"
-
-#define MINX 8
-
-struct{
- Point pos;
- int bwid;
-}out;
-
-/* imported */
-extern GSubfont defont0;
-extern Cursor arrow;
-extern GBitmap cursorback;
-
-/* exported */
-GSubfont *defont;
-int islittle = 1; /* little endian bit ordering in bytes */
-GBitmap gscreen;
-
-/* local */
-static Lock vgalock;
-static GBitmap vgascreen;
-static ulong colormap[256][3];
-static int cga = 1; /* true if in cga mode */
-
-/*
- * screen dimensions
- */
-#define MAXX 640
-#define MAXY 480
-
-/*
- * 'soft' screen bitmap
- */
-
-typedef struct VGAmode VGAmode;
-struct VGAmode
-{
- uchar general[2];
- uchar sequencer[5];
- uchar crt[0x19];
- uchar graphics[9];
- uchar attribute[0x15];
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include "screen.h"
+
+static ulong backbits = (Backgnd<<24)|(Backgnd<<16)|(Backgnd<<8)|Backgnd;
+static Memdata backdata = {
+ nil,
+ &backbits
};
-
-/*
- * 640x480 display, 1, 2, or 4 bit color.
- */
-VGAmode mode12 =
-{
- /* general */
- 0xe7, 0x00,
- /* sequence */
- 0x03, 0x01, 0x0f, 0x00, 0x06,
- /* crt */
- 0x65, 0x4f, 0x50, 0x88, 0x55, 0x9a, 0x09, 0x3e,
- 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xe8, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
- 0xff,
- /* graphics */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f,
- 0xff,
- /* attribute */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x01, 0x10, 0x0f, 0x00, 0x00,
+static Memimage xback = {
+ { 0, 0, 1, 1 },
+ { -100000, -100000, 100000, 100000 },
+ 3,
+ 1,
+ &backdata,
+ 0,
+ 1
};
+static Memimage* back = &xback;
-/*
- * 320x200 display, 8 bit color.
- */
-VGAmode mode13 =
-{
- /* general */
- 0x63, 0x00,
- /* sequence */
- 0x03, 0x01, 0x0f, 0x00, 0x0e,
- /* crt */
- 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
- 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28,
- 0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
- 0xff,
- /* graphics */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f,
- 0xff,
- /* attribute */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x41, 0x10, 0x0f, 0x00, 0x00,
+static ulong consbits = 0;
+static Memdata consdata = {
+ nil,
+ &consbits
+};
+static Memimage conscol = {
+ { 0, 0, 1, 1 },
+ { -100000, -100000, 100000, 100000 },
+ 3,
+ 1,
+ &consdata,
+ 0,
+ 1
};
-static Rectangle mbb;
-static Rectangle NULLMBB = {10000, 10000, -10000, -10000};
-
-void
-genout(int reg, int val)
-{
- if(reg == 0)
- outb(EMISCW, val);
- else if (reg == 1)
- outb(EFCW, val);
-}
-void
-srout(int reg, int val)
-{
- outb(SRX, reg);
- outb(SR, val);
-}
-void
-grout(int reg, int val)
-{
- outb(GRX, reg);
- outb(GR, val);
-}
-void
-arout(int reg, int val)
-{
- inb(0x3DA);
- if (reg <= 0xf) {
- outb(ARW, reg | 0x0);
- outb(ARW, val);
- inb(0x3DA);
- outb(ARW, reg | 0x20);
- } else {
- outb(ARW, reg | 0x20);
- outb(ARW, val);
- }
-}
-
-void
-crout(int reg, int val)
-{
- outb(CRX, reg);
- outb(CR, val);
-}
-
-void
-setmode(VGAmode *v)
-{
- int i;
-
- /* turn screen off (to avoid damage) */
- srout(1, 0x21);
-
- for(i = 0; i < sizeof(v->general); i++)
- genout(i, v->general[i]);
-
- for(i = 0; i < sizeof(v->sequencer); i++)
- if(i == 1)
- srout(i, v->sequencer[i]|0x20); /* avoid enabling screen */
- else
- srout(i, v->sequencer[i]);
-
- crout(Cvre, 0); /* allow writes to CRT registers 0-7 */
- for(i = 0; i < sizeof(v->crt); i++)
- crout(i, v->crt[i]);
-
- for(i = 0; i < sizeof(v->graphics); i++)
- grout(i, v->graphics[i]);
-
- for(i = 0; i < sizeof(v->attribute); i++)
- arout(i, v->attribute[i]);
-
- /* turn screen on */
- srout(1, v->sequencer[1]);
-}
-
-void
-getmode(VGAmode *v) {
- int i;
- v->general[0] = inb(0x3cc);
- v->general[1] = inb(0x3ca);
- for(i = 0; i < sizeof(v->sequencer); i++) {
- outb(SRX, i);
- v->sequencer[i] = inb(SR);
- }
- for(i = 0; i < sizeof(v->crt); i++) {
- outb(CRX, i);
- v->crt[i] = inb(CR);
- }
- for(i = 0; i < sizeof(v->graphics); i++) {
- outb(GRX, i);
- v->graphics[i] = inb(GR);
- }
- for(i = 0; i < sizeof(v->attribute); i++) {
- inb(0x3DA);
- outb(ARW, i | 0x20);
- v->attribute[i] = inb(ARR);
- }
-}
-
-void
-printmode(VGAmode *v) {
- int i;
- print("g %2.2x %2x\n",
- v->general[0], v->general[1]);
-
- print("s ");
- for(i = 0; i < sizeof(v->sequencer); i++) {
- print(" %2.2x", v->sequencer[i]);
- }
-
- print("\nc ");
- for(i = 0; i < sizeof(v->crt); i++) {
- print(" %2.2x", v->crt[i]);
- }
-
- print("\ng ");
- for(i = 0; i < sizeof(v->graphics); i++) {
- print(" %2.2x", v->graphics[i]);
- }
-
- print("\na ");
- for(i = 0; i < sizeof(v->attribute); i++) {
- print(" %2.2x", v->attribute[i]);
- }
- print("\n");
-}
-
-/*
- * expand 3 and 6 bits of color to 32
- */
-static ulong
-x3to32(uchar x)
-{
- ulong y;
-
- x = x&7;
- x= (x<<3)|x;
- y = (x<<(32-6))|(x<<(32-12))|(x<<(32-18))|(x<<(32-24))|(x<<(32-30));
- return y;
-}
-static ulong
-x6to32(uchar x)
-{
- ulong y;
-
- x = x&0x3f;
- y = (x<<(32-6))|(x<<(32-12))|(x<<(32-18))|(x<<(32-24))|(x<<(32-30));
- return y;
-}
-
-void
-setscreen(int maxx, int maxy, int ldepth)
-{
- int len, vgamaxy, width, i, x;
- uchar *p;
-
- if(ldepth == 3)
- setmode(&mode13);
- else
- setmode(&mode12);
-
- /* allocate a new soft bitmap area */
- width = (maxx*(1<<ldepth))/32;
- len = width * BY2WD * maxy;
- p = xalloc(len);
- if(p == 0)
- panic("can't alloc screen bitmap");
- mbb = NULLMBB;
-
- /*
- * zero hard screen and setup a bitmap for the new size
- */
- if(ldepth == 3)
- vgascreen.ldepth = 3;
- else
- vgascreen.ldepth = 0;
- vgascreen.width = (maxx*(1<<vgascreen.ldepth))/32;
- if(maxy > (64*1024)/(vgascreen.width*BY2WD))
- vgamaxy = (64*1024)/(vgascreen.width*BY2WD);
- else
- vgamaxy = maxy;
- vgascreen.base = (void*)SCREENMEM;
- vgascreen.r.min = Pt(0, 0);
- vgascreen.r.max = Pt(maxx, vgamaxy);
- vgascreen.clipr = vgascreen.r;
- memset(vgascreen.base, 0xff, vgascreen.width * BY2WD * vgamaxy);
-
- /*
- * setup new soft screen, free memory for old screen
- */
- if(gscreen.base)
- xfree(gscreen.base);
- gscreen.ldepth = ldepth;
- gscreen.width = width;
- gscreen.r.min = Pt(0, 0);
- gscreen.r.max = Pt(maxx, maxy);
- gscreen.clipr = gscreen.r;
- gscreen.base = (ulong*)p;
- memset(gscreen.base, 0xff, len);
-
- /*
- * set depth of cursor backup area
- */
- bitdepth();
-
- /*
- * set string pointer to upper left
- */
- out.pos.x = MINX;
- out.pos.y = 0;
- out.bwid = defont0.info[' '].width;
-
- /*
- * default color map
- */
- switch(ldepth){
- case 3:
- for(i = 0; i < 256; i++)
- setcolor(i, x3to32(i>>5), x3to32(i>>2), x3to32(i<<1));
- break;
- case 2:
- case 1:
- case 0:
- gscreen.ldepth = 3;
- for(i = 0; i < 16; i++){
- x = x6to32((i*63)/15);
- setcolor(i, x, x, x);
- }
- gscreen.ldepth = ldepth;
- break;
- }
- cga = 0;
-}
+static Point curpos;
+static Rectangle window;
+static int *xp;
+static int xbuf[256];
+static Lock vgascreenlock;
-void
-screeninit(void)
+static void
+vgascroll(VGAscr* scr)
{
- int i;
- ulong *l;
-
- /*
- * arrow is defined as a big endian
- */
- pixreverse(arrow.set, 2*16, 0);
- pixreverse(arrow.clr, 2*16, 0);
-
- /*
- * swizzle the font longs. we do both byte and bit swizzling
- * since the font is initialized with big endian longs.
- */
- defont = &defont0;
- l = defont->bits->base;
- for(i = defont->bits->width*Dy(defont->bits->r); i > 0; i--, l++)
- *l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24);
- pixreverse((uchar*)defont->bits->base,
- defont->bits->width*BY2WD*Dy(defont->bits->r), 0);
-
- cga = 1;
- crout(0x0a, 0xff); /* turn off cursor */
- memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT);
-}
+ int h, o;
+ Point p;
+ Rectangle r;
-/*
- * collect changes to the 'soft' screen
- */
-void
-mbbrect(Rectangle r)
-{
- if (r.min.x < mbb.min.x)
- mbb.min.x = r.min.x;
- if (r.min.y < mbb.min.y)
- mbb.min.y = r.min.y;
- if (r.max.x > mbb.max.x)
- mbb.max.x = r.max.x;
- if (r.max.y > mbb.max.y)
- mbb.max.y = r.max.y;
- if (Dy(mbb) > 32 || Dx(mbb) > 32)
- mousescreenupdate();
-}
+ h = scr->memdefont->height;
+ o = 8*h;
+ r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
+ p = Pt(window.min.x, window.min.y+o);
+ memimagedraw(scr->gscreen, r, scr->gscreen, p, memones, p);
+ r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
+ memimagedraw(scr->gscreen, r, back, ZP, memones, ZP);
-void
-mbbpt(Point p)
-{
- if (p.x < mbb.min.x)
- mbb.min.x = p.x;
- if (p.y < mbb.min.y)
- mbb.min.y = p.y;
- if (p.x >= mbb.max.x)
- mbb.max.x = p.x+1;
- if (p.y >= mbb.max.y)
- mbb.max.y = p.y+1;
+ curpos.y -= o;
}
-/*
- * copy litte endian soft screen to big endian hard screen
- */
static void
-vgaupdate(void)
+vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
{
- uchar *sp, *hp, *edisp;
- int y, len, incs, inch, off, page;
+ Point p;
+ int h, w, pos;
Rectangle r;
- void* (*f)(void*, void*, long);
-
- r = mbb;
- mbb = NULLMBB;
-
- if(Dy(r) < 0)
- return;
- if(r.min.x < 0)
- r.min.x = 0;
- if(r.min.y < 0)
- r.min.y = 0;
- if(r.max.x > gscreen.r.max.x)
- r.max.x = gscreen.r.max.x;
- if(r.max.y > gscreen.r.max.y)
- r.max.y = gscreen.r.max.y;
+ if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
+ xp = xbuf;
- incs = gscreen.width * BY2WD;
- inch = vgascreen.width * BY2WD;
+ h = scr->memdefont->height;
+ switch(buf[0]){
- off = r.min.y * vgascreen.width * BY2WD + (r.min.x>>(3 - vgascreen.ldepth));
- page = off>>16;
- off &= (1<<16)-1;
- hp = ((uchar*)vgascreen.base) + off;
- off = r.min.y * gscreen.width * BY2WD + (r.min.x>>(3 - gscreen.ldepth));
- sp = ((uchar*)gscreen.base) + off;
-
- switch(gscreen.ldepth){
- case 0:
- f = l0update;
- len = (r.max.x + 7)/8 - r.min.x/8;
+ case '\n':
+ if(curpos.y+h >= window.max.y){
+ vgascroll(scr);
+ *flushr = window;
+ }
+ curpos.y += h;
+ vgascreenputc(scr, "\r", flushr);
break;
- case 1:
- f = l1update;
- len = (r.max.x + 15)/8 - r.min.x/8;
+
+ case '\r':
+ xp = xbuf;
+ curpos.x = window.min.x;
break;
- case 2:
- f = l2update;
- len = (r.max.x + 7)/8 - r.min.x/8;
+
+ case '\t':
+ p = memsubfontwidth(scr->memdefont, " ");
+ w = p.x;
+ *xp++ = curpos.x;
+ pos = (curpos.x-window.min.x)/w;
+ pos = 4-(pos%4);
+ r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y+h);
+ memimagedraw(scr->gscreen, r, back, back->r.min, memones, back->r.min);
+ bbox(flushr, r);
+ curpos.x += pos*w;
break;
- case 3:
- f = memmove;
- len = r.max.x - r.min.x;
+
+ case '\b':
+ if(xp <= xbuf)
+ break;
+ xp--;
+ r = Rect(*xp, curpos.y, curpos.x, curpos.y+h);
+ memimagedraw(scr->gscreen, r, back, back->r.min, memones, back->r.min);
+ bbox(flushr, r);
+ curpos.x = *xp;
break;
- default:
- return;
- }
- if(len < 1)
- return;
- edisp = ((uchar*)vgascreen.base) + 64*1024;
- outb(0x3cd, (page<<4)|page);
- for(y = r.min.y; y < r.max.y; y++){
- if(hp + inch < edisp){
- f(hp, sp, len);
- sp += incs;
- hp += inch;
- } else {
- off = edisp - hp;
- if(off <= len){
- if(off > 0)
- f(hp, sp, off);
- page++;
- outb(0x3cd, (page<<4)|page);
- if(len - off > 0)
- f(vgascreen.base, sp+off, len - off);
- } else {
- f(hp, sp, len);
- page++;
- outb(0x3cd, (page<<4)|page);
- }
- sp += incs;
- hp += inch - 64*1024;
- }
- }
-}
+ default:
+ p = memsubfontwidth(scr->memdefont, buf);
+ w = p.x;
-void
-screenupdate(void)
-{
- lock(&vgalock);
- vgaupdate();
- unlock(&vgalock);
-}
+ if(curpos.x >= window.max.x-w)
+ vgascreenputc(scr, "\n", flushr);
-void
-mousescreenupdate(void)
-{
- if(canlock(&vgalock)){
- vgaupdate();
- unlock(&vgalock);
+ *xp++ = curpos.x;
+ r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);
+ memimagedraw(scr->gscreen, r, back, back->r.min, memones, back->r.min);
+ memimagestring(scr->gscreen, curpos, &conscol, scr->memdefont, buf);
+ bbox(flushr, r);
+ curpos.x += w;
}
}
static void
-cgascreenputc(int c)
+vgascreenputs(char* s, int n)
{
int i;
- static int color;
- static int pos;
-
- if(c == '\n'){
- pos = pos/CGAWIDTH;
- pos = (pos+1)*CGAWIDTH;
- } else if(c == '\t'){
- i = 8 - ((pos/2)&7);
- while(i-->0)
- cgascreenputc(' ');
- } else if(c == '\b'){
- if(pos >= 2)
- pos -= 2;
- cgascreenputc(' ');
- pos -= 2;
- } else {
- CGASCREEN[pos++] = c;
- CGASCREEN[pos++] = 2; /* green on black */
- }
- if(pos >= CGAWIDTH*CGAHEIGHT){
- memmove(CGASCREEN, &CGASCREEN[CGAWIDTH], CGAWIDTH*(CGAHEIGHT-1));
- memset(&CGASCREEN[CGAWIDTH*(CGAHEIGHT-1)], 0, CGAWIDTH);
- pos = CGAWIDTH*(CGAHEIGHT-1);
- }
-}
-
-void
-cgascreenputs(char *s, int n)
-{
- while(n-- > 0)
- cgascreenputc(*s++);
-}
-
-void
-screenputnl(void)
-{
- Rectangle r;
-
- out.pos.x = MINX;
- out.pos.y += defont0.height;
- if(out.pos.y > gscreen.r.max.y-defont0.height){
- vgaupdate();
- out.pos.y = gscreen.r.min.y;
- }
- r = Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height);
- gbitblt(&gscreen, r.min, &gscreen, r, flipD[0]);
- mbbrect(r);
- vgaupdate();
-}
-
-void
-screenputs(char *s, int n)
-{
Rune r;
- int i;
char buf[4];
- Rectangle rect;
+ VGAscr *scr;
+ Rectangle flushr;
+
+ scr = &vgascreen[0];
- if(cga) {
- cgascreenputs(s, n);
- return;
+ if(!islo()){
+ /*
+ * Don't deadlock trying to
+ * print in an interrupt.
+ */
+ if(!canlock(&vgascreenlock))
+ return;
}
+ else
+ lock(&vgascreenlock);
+
+ flushr = Rect(10000, 10000, -10000, -10000);
while(n > 0){
i = chartorune(&r, s);
@@ 574,209 165,29 @@ screenputs(char *s, int n)
buf[i] = 0;
n -= i;
s += i;
- if(r == '\n')
- screenputnl();
- else if(r == '\t'){
- out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid;
- if(out.pos.x >= gscreen.r.max.x)
- screenputnl();
- }else if(r == '\b'){
- if(out.pos.x >= out.bwid+MINX){
- out.pos.x -= out.bwid;
- gsubfstring(&gscreen, out.pos, defont, " ", flipD[S]);
- }
- rect.min = Pt(out.pos.x, out.pos.y);
- rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height);
- mbbrect(rect);
- }else{
- if(out.pos.x >= gscreen.r.max.x-out.bwid)
- screenputnl();
- rect.min = Pt(out.pos.x, out.pos.y);
- rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height);
- out.pos = gsubfstring(&gscreen, out.pos, defont, buf, flipD[S]);
- mbbrect(rect);
- }
+ vgascreenputc(scr, buf, &flushr);
}
- vgaupdate();
-}
+ flushmemscreen(flushr);
-int
-screenbits(void)
-{
- return 1<<gscreen.ldepth; /* bits per pixel */
+ unlock(&vgascreenlock);
}
void
-getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
+vgascreenwin(VGAscr* scr)
{
- p &= (1<<(1<<gscreen.ldepth))-1;
- lock(&vgalock);
- *pr = colormap[p][0];
- *pg = colormap[p][1];
- *pb = colormap[p][2];
- unlock(&vgalock);
-}
-
-int
-setcolor(ulong p, ulong r, ulong g, ulong b)
-{
- p &= (1<<(1<<gscreen.ldepth))-1;
- lock(&vgalock);
- colormap[p][0] = r;
- colormap[p][1] = g;
- colormap[p][2] = b;
- outb(CMWX, p);
- outb(CM, r>>(32-6));
- outb(CM, g>>(32-6));
- outb(CM, b>>(32-6));
- unlock(&vgalock);
- return ~0;
-}
-
-int
-hwcursset(uchar *s, uchar *c, int ox, int oy)
-{
- USED(s, c, ox, oy);
- return 0;
-}
-
-int
-hwcursmove(int x, int y)
-{
- USED(x, y);
- return 0;
-}
+ int h, w;
-void
-mouseclock(void)
-{
- spllo(); /* so we don't cause lost chars on the uart */
- mouseupdate(1);
-}
+ h = scr->memdefont->height;
+ w = scr->memdefont->info[' '].width;
-/*
- * a fatter than usual cursor for the safari
- */
-Cursor fatarrow = {
- { -1, -1 },
- {
- 0xff, 0xff, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0c,
- 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
- 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8c, 0x04,
- 0x92, 0x08, 0x91, 0x10, 0xa0, 0xa0, 0xc0, 0x40,
- },
- {
- 0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfc, 0x7f, 0xf0,
- 0x7f, 0xe0, 0x7f, 0xe0, 0x7f, 0xf0, 0x7f, 0xf8,
- 0x7f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfc, 0x73, 0xf8,
- 0x61, 0xf0, 0x60, 0xe0, 0x40, 0x40, 0x00, 0x00,
- },
-};
+ window.min = Pt(48, 48);
+ window.max = addpt(window.min, Pt(10+w*80, 10+h*50));
+ if(window.max.y >= scr->gscreen->r.max.y)
+ window.max.y = scr->gscreen->r.max.y-1;
+ if(window.max.x >= scr->gscreen->r.max.x)
+ window.max.x = scr->gscreen->r.max.x-1;
+ window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
+ curpos = window.min;
-void
-bigcursor(void)
-{
- memmove(&arrow, &fatarrow, sizeof(fatarrow));
- pixreverse(arrow.set, 2*16, 0);
- pixreverse(arrow.clr, 2*16, 0);
+ screenputs = vgascreenputs;
}
-
-/*
- * Table for separating and reversing bits in a ldepth 1 bitmap.
- * This aids in coverting a little endian ldepth 1 bitmap into the
- * 2 big-endian ldepth 0 bitmaps used for the VGA bit planes.
- *
- * if the bits in uchar x are labeled
- * 76543210
- * then l1revsep[x] yields a ushort with bits
- * ________1357________0246
- * where _ represents a bit whose value is 0.
- *
- * This table is used by l1update() in l.s. l1update is implemented
- * in assembler for speed.
- *
- */
-ulong l1revsep[] = {
- 0x00000, 0x00008, 0x80000, 0x80008, 0x00004, 0x0000c, 0x80004, 0x8000c,
- 0x40000, 0x40008, 0xc0000, 0xc0008, 0x40004, 0x4000c, 0xc0004, 0xc000c,
- 0x00002, 0x0000a, 0x80002, 0x8000a, 0x00006, 0x0000e, 0x80006, 0x8000e,
- 0x40002, 0x4000a, 0xc0002, 0xc000a, 0x40006, 0x4000e, 0xc0006, 0xc000e,
- 0x20000, 0x20008, 0xa0000, 0xa0008, 0x20004, 0x2000c, 0xa0004, 0xa000c,
- 0x60000, 0x60008, 0xe0000, 0xe0008, 0x60004, 0x6000c, 0xe0004, 0xe000c,
- 0x20002, 0x2000a, 0xa0002, 0xa000a, 0x20006, 0x2000e, 0xa0006, 0xa000e,
- 0x60002, 0x6000a, 0xe0002, 0xe000a, 0x60006, 0x6000e, 0xe0006, 0xe000e,
- 0x00001, 0x00009, 0x80001, 0x80009, 0x00005, 0x0000d, 0x80005, 0x8000d,
- 0x40001, 0x40009, 0xc0001, 0xc0009, 0x40005, 0x4000d, 0xc0005, 0xc000d,
- 0x00003, 0x0000b, 0x80003, 0x8000b, 0x00007, 0x0000f, 0x80007, 0x8000f,
- 0x40003, 0x4000b, 0xc0003, 0xc000b, 0x40007, 0x4000f, 0xc0007, 0xc000f,
- 0x20001, 0x20009, 0xa0001, 0xa0009, 0x20005, 0x2000d, 0xa0005, 0xa000d,
- 0x60001, 0x60009, 0xe0001, 0xe0009, 0x60005, 0x6000d, 0xe0005, 0xe000d,
- 0x20003, 0x2000b, 0xa0003, 0xa000b, 0x20007, 0x2000f, 0xa0007, 0xa000f,
- 0x60003, 0x6000b, 0xe0003, 0xe000b, 0x60007, 0x6000f, 0xe0007, 0xe000f,
- 0x10000, 0x10008, 0x90000, 0x90008, 0x10004, 0x1000c, 0x90004, 0x9000c,
- 0x50000, 0x50008, 0xd0000, 0xd0008, 0x50004, 0x5000c, 0xd0004, 0xd000c,
- 0x10002, 0x1000a, 0x90002, 0x9000a, 0x10006, 0x1000e, 0x90006, 0x9000e,
- 0x50002, 0x5000a, 0xd0002, 0xd000a, 0x50006, 0x5000e, 0xd0006, 0xd000e,
- 0x30000, 0x30008, 0xb0000, 0xb0008, 0x30004, 0x3000c, 0xb0004, 0xb000c,
- 0x70000, 0x70008, 0xf0000, 0xf0008, 0x70004, 0x7000c, 0xf0004, 0xf000c,
- 0x30002, 0x3000a, 0xb0002, 0xb000a, 0x30006, 0x3000e, 0xb0006, 0xb000e,
- 0x70002, 0x7000a, 0xf0002, 0xf000a, 0x70006, 0x7000e, 0xf0006, 0xf000e,
- 0x10001, 0x10009, 0x90001, 0x90009, 0x10005, 0x1000d, 0x90005, 0x9000d,
- 0x50001, 0x50009, 0xd0001, 0xd0009, 0x50005, 0x5000d, 0xd0005, 0xd000d,
- 0x10003, 0x1000b, 0x90003, 0x9000b, 0x10007, 0x1000f, 0x90007, 0x9000f,
- 0x50003, 0x5000b, 0xd0003, 0xd000b, 0x50007, 0x5000f, 0xd0007, 0xd000f,
- 0x30001, 0x30009, 0xb0001, 0xb0009, 0x30005, 0x3000d, 0xb0005, 0xb000d,
- 0x70001, 0x70009, 0xf0001, 0xf0009, 0x70005, 0x7000d, 0xf0005, 0xf000d,
- 0x30003, 0x3000b, 0xb0003, 0xb000b, 0x30007, 0x3000f, 0xb0007, 0xb000f,
- 0x70003, 0x7000b, 0xf0003, 0xf000b, 0x70007, 0x7000f, 0xf0007, 0xf000f,
-};
-
-/*
- * Table for separating and reversing bits in a ldepth 2 bitmap.
- * This aids in coverting a little endian ldepth 1 bitmap into the
- * 4 big-endian ldepth 0 bitmaps used for the VGA bit planes.
- *
- * if the bits in uchar x are labeled
- * 76543210
- * then l1revsep[x] yields a ushort with bits
- * ______37______26______15______04
- * where _ represents a bit whose value is 0.
- *
- * This table is used by l2update() in l.s. l2update is implemented
- * in assembler for speed.
- *
- */
-ulong l2revsep[] = {
- 0x0000000, 0x0000002, 0x0000200, 0x0000202, 0x0020000, 0x0020002, 0x0020200, 0x0020202,
- 0x2000000, 0x2000002, 0x2000200, 0x2000202, 0x2020000, 0x2020002, 0x2020200, 0x2020202,
- 0x0000001, 0x0000003, 0x0000201, 0x0000203, 0x0020001, 0x0020003, 0x0020201, 0x0020203,
- 0x2000001, 0x2000003, 0x2000201, 0x2000203, 0x2020001, 0x2020003, 0x2020201, 0x2020203,
- 0x0000100, 0x0000102, 0x0000300, 0x0000302, 0x0020100, 0x0020102, 0x0020300, 0x0020302,
- 0x2000100, 0x2000102, 0x2000300, 0x2000302, 0x2020100, 0x2020102, 0x2020300, 0x2020302,
- 0x0000101, 0x0000103, 0x0000301, 0x0000303, 0x0020101, 0x0020103, 0x0020301, 0x0020303,
- 0x2000101, 0x2000103, 0x2000301, 0x2000303, 0x2020101, 0x2020103, 0x2020301, 0x2020303,
- 0x0010000, 0x0010002, 0x0010200, 0x0010202, 0x0030000, 0x0030002, 0x0030200, 0x0030202,
- 0x2010000, 0x2010002, 0x2010200, 0x2010202, 0x2030000, 0x2030002, 0x2030200, 0x2030202,
- 0x0010001, 0x0010003, 0x0010201, 0x0010203, 0x0030001, 0x0030003, 0x0030201, 0x0030203,
- 0x2010001, 0x2010003, 0x2010201, 0x2010203, 0x2030001, 0x2030003, 0x2030201, 0x2030203,
- 0x0010100, 0x0010102, 0x0010300, 0x0010302, 0x0030100, 0x0030102, 0x0030300, 0x0030302,
- 0x2010100, 0x2010102, 0x2010300, 0x2010302, 0x2030100, 0x2030102, 0x2030300, 0x2030302,
- 0x0010101, 0x0010103, 0x0010301, 0x0010303, 0x0030101, 0x0030103, 0x0030301, 0x0030303,
- 0x2010101, 0x2010103, 0x2010301, 0x2010303, 0x2030101, 0x2030103, 0x2030301, 0x2030303,
- 0x1000000, 0x1000002, 0x1000200, 0x1000202, 0x1020000, 0x1020002, 0x1020200, 0x1020202,
- 0x3000000, 0x3000002, 0x3000200, 0x3000202, 0x3020000, 0x3020002, 0x3020200, 0x3020202,
- 0x1000001, 0x1000003, 0x1000201, 0x1000203, 0x1020001, 0x1020003, 0x1020201, 0x1020203,
- 0x3000001, 0x3000003, 0x3000201, 0x3000203, 0x3020001, 0x3020003, 0x3020201, 0x3020203,
- 0x1000100, 0x1000102, 0x1000300, 0x1000302, 0x1020100, 0x1020102, 0x1020300, 0x1020302,
- 0x3000100, 0x3000102, 0x3000300, 0x3000302, 0x3020100, 0x3020102, 0x3020300, 0x3020302,
- 0x1000101, 0x1000103, 0x1000301, 0x1000303, 0x1020101, 0x1020103, 0x1020301, 0x1020303,
- 0x3000101, 0x3000103, 0x3000301, 0x3000303, 0x3020101, 0x3020103, 0x3020301, 0x3020303,
- 0x1010000, 0x1010002, 0x1010200, 0x1010202, 0x1030000, 0x1030002, 0x1030200, 0x1030202,
- 0x3010000, 0x3010002, 0x3010200, 0x3010202, 0x3030000, 0x3030002, 0x3030200, 0x3030202,
- 0x1010001, 0x1010003, 0x1010201, 0x1010203, 0x1030001, 0x1030003, 0x1030201, 0x1030203,
- 0x3010001, 0x3010003, 0x3010201, 0x3010203, 0x3030001, 0x3030003, 0x3030201, 0x3030203,
- 0x1010100, 0x1010102, 0x1010300, 0x1010302, 0x1030100, 0x1030102, 0x1030300, 0x1030302,
- 0x3010100, 0x3010102, 0x3010300, 0x3010302, 0x3030100, 0x3030102, 0x3030300, 0x3030302,
- 0x1010101, 0x1010103, 0x1010301, 0x1010303, 0x1030101, 0x1030103, 0x1030301, 0x1030303,
- 0x3010101, 0x3010103, 0x3010301, 0x3010303, 0x3030101, 0x3030103, 0x3030301, 0x3030303,
-};
D pc/vga.h => pc/vga.h +0 -69
@@ 1,69 0,0 @@
-/*
- * Generic VGA registers.
- */
-enum {
- MiscW = 0x03C2, /* Miscellaneous Output (W) */
- MiscR = 0x03CC, /* Miscellaneous Output (R) */
- Status0 = 0x03C2, /* Input status 0 (R) */
- Status1 = 0x03DA, /* Input Status 1 (R) */
- FeatureR = 0x03CA, /* Feature Control (R) */
- FeatureW = 0x03DA, /* Feature Control (W) */
-
- Seqx = 0x03C4, /* Sequencer Index, Data at Seqx+1 */
- Crtx = 0x03D4, /* CRT Controller Index, Data at Crtx+1 */
- Grx = 0x03CE, /* Graphics Controller Index, Data at Grx+1 */
- Attrx = 0x03C0, /* Attribute Controller Index and Data */
-
- PaddrW = 0x03C8, /* Palette Address Register, write */
- Pdata = 0x03C9, /* Palette Data Register */
- Pixmask = 0x03C6, /* Pixel Mask Register */
- PaddrR = 0x03C7, /* Palette Address Register, read */
- Pstatus = 0x03C7, /* DAC Status (RO) */
-
- Pcolours = 256, /* Palette */
- Pred = 0,
- Pgreen = 1,
- Pblue = 2,
-
- Pblack = 0x00,
- Pwhite = 0xFF,
-};
-
-#define vgai(port) inb(port)
-#define vgao(port, data) outb(port, data)
-
-extern int vgaxi(long, uchar);
-extern int vgaxo(long, uchar, uchar);
-
-/*
- * Definitions of known VGA controllers.
- */
-typedef struct Vgac Vgac;
-struct Vgac {
- char *name;
- void (*page)(int);
- int (*linear)(ulong*, ulong*, ulong*);
-
- Vgac* link;
-};
-
-/*
- * Definition of known hardware graphics cursors.
- */
-typedef struct Hwgc Hwgc;
-struct Hwgc {
- char* name;
- void (*enable)(void);
- void (*load)(Cursor*);
- int (*move)(Point);
- void (*disable)(void);
-
- Hwgc* link;
-};
-
-extern void addvgaclink(Vgac*);
-extern void addhwgclink(Hwgc*);
-
-extern Hwgc *hwgc;
-
-extern Lock palettelock;
M pc/vgaark2000pv.c => pc/vgaark2000pv.c +55 -80
@@ 5,43 5,45 @@
#include "fns.h"
#include "../port/error.h"
-#include <libg.h>
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
#include "screen.h"
-#include "vga.h"
-extern Bitmap gscreen;
-extern Cursor curcursor;
+static int
+ark2000pvpageset(VGAscr*, int page)
+{
+ uchar seq15;
+
+ seq15 = vgaxi(Seqx, 0x15);
+ vgaxo(Seqx, 0x15, page);
+ vgaxo(Seqx, 0x16, page);
-static Lock ark2000pvlock;
-static ulong storage;
-static Point hotpoint;
+ return seq15;
+}
static void
-setark2000pvpage(int page)
+ark2000pvpage(VGAscr* scr, int page)
{
- vgaxo(Seqx, 0x15, page);
- vgaxo(Seqx, 0x16, page);
+ lock(&scr->devlock);
+ ark2000pvpageset(scr, page);
+ unlock(&scr->devlock);
}
static void
-disable(void)
+ark2000pvdisable(VGAscr*)
{
uchar seq20;
- lock(&ark2000pvlock);
-
seq20 = vgaxi(Seqx, 0x20) & ~0x08;
vgaxo(Seqx, 0x20, seq20);
-
- unlock(&ark2000pvlock);
}
static void
-enable(void)
+ark2000pvenable(VGAscr* scr)
{
uchar seq20;
-
- lock(&ark2000pvlock);
+ ulong storage;
/*
* Disable the cursor then configure for X-Windows style,
@@ 66,46 68,34 @@ enable(void)
storage = (vgaxi(Seqx, 0x10)>>6) & 0x03;
storage = (1024*1024)<<storage;
storage -= 256;
+ scr->storage = storage;
vgaxo(Seqx, 0x25, 0x3F);
/*
* Enable the cursor.
*/
vgaxo(Seqx, 0x20, seq20);
-
- unlock(&ark2000pvlock);
}
static void
-load(Cursor *c)
+ark2000pvload(VGAscr* scr, Cursor* curs)
{
- uchar *p;
- int x, y;
-
- /*
- * Lock the display memory so we can update the
- * cursor bitmap if necessary.
- * If it's the same as the last cursor we loaded,
- * just make sure it's enabled.
- */
- lock(&ark2000pvlock);
- if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){
- vgaxo(Seqx, 0x20, vgaxi(Seqx, 0x20)|0x08);
- unlock(&ark2000pvlock);
- return;
- }
- memmove(&curcursor, c, sizeof(Cursor));
+ uchar *p, seq10;
+ int opage, x, y;
/*
* Is linear addressing turned on? This will determine
* how we access the cursor storage.
*/
- if(vgaxi(Seqx, 0x10) & 0x10)
- p = ((uchar*)gscreen.base) + storage;
- else {
- setark2000pvpage(storage>>16);
- p = ((uchar*)gscreen.base) + (storage & 0xFFFF);
+ seq10 = vgaxi(Seqx, 0x10);
+ opage = 0;
+ p = KADDR(scr->aperture);
+ if(!(seq10 & 0x10)){
+ opage = ark2000pvpageset(scr, scr->storage>>16);
+ p += (scr->storage & 0xFFFF);
}
+ else
+ p += scr->storage;
/*
* The cursor is set in X11 mode which gives the following
@@ 122,8 112,8 @@ load(Cursor *c)
for(y = 0; y < 32; y++){
for(x = 0; x < 32/8; x++){
if(x < 16/8 && y < 16){
- *p++ = c->clr[2*y + x]|c->set[2*y + x];
- *p++ = c->set[2*y + x];
+ *p++ = curs->clr[2*y + x]|curs->set[2*y + x];
+ *p++ = curs->set[2*y + x];
}
else {
*p++ = 0x00;
@@ 132,34 122,34 @@ load(Cursor *c)
}
}
+ if(!(seq10 & 0x10)){
+ ark2000pvpageset(scr, opage);
+ unlock(&scr->devlock);
+ }
+
/*
- * Set the cursor hotpoint and enable the cursor.
+ * Save the cursor hotpoint.
*/
- hotpoint = c->offset;
-
- unlock(&ark2000pvlock);
+ scr->offset = curs->offset;
}
static int
-move(Point p)
+ark2000pvmove(VGAscr* scr, Point p)
{
int x, xo, y, yo;
- if(canlock(&ark2000pvlock) == 0)
- return 1;
-
/*
* Mustn't position the cursor offscreen even partially,
* or it might disappear. Therefore, if x or y is -ve, adjust the
* cursor origins instead.
*/
- if((x = p.x+hotpoint.x) < 0){
+ if((x = p.x+scr->offset.x) < 0){
xo = -x;
x = 0;
}
else
xo = 0;
- if((y = p.y+hotpoint.y) < 0){
+ if((y = p.y+scr->offset.y) < 0){
yo = -y;
y = 0;
}
@@ 176,38 166,23 @@ move(Point p)
vgaxo(Seqx, 0x23, (y>>8) & 0x0F);
vgaxo(Seqx, 0x24, y & 0xFF);
- unlock(&ark2000pvlock);
return 0;
}
-static Hwgc ark2000pvhwgc = {
- "ark2000pvhwgc",
- enable,
- load,
- move,
- disable,
+VGAdev vgaark2000pvdev = {
+ "ark2000pv",
0,
-};
-
-static void
-ark2000pvpage(int page)
-{
- lock(&ark2000pvlock);
- setark2000pvpage(page);
- unlock(&ark2000pvlock);
-}
-
-static Vgac ark2000pv = {
- "ark2000pv",
+ 0,
ark2000pvpage,
-
0,
};
-void
-vgaark2000pvlink(void)
-{
- addvgaclink(&ark2000pv);
- addhwgclink(&ark2000pvhwgc);
-}
+VGAcur vgaark2000pvcur = {
+ "ark2000pvhwgc",
+
+ ark2000pvenable,
+ ark2000pvdisable,
+ ark2000pvload,
+ ark2000pvmove,
+};
M pc/vgabt485.c => pc/vgabt485.c +74 -97
@@ 5,9 5,10 @@
#include "fns.h"
#include "../port/error.h"
-#include <libg.h>
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
#include "screen.h"
-#include "vga.h"
/*
* Hardware graphics cursor support for
@@ 103,16 104,71 @@ bt485o(uchar reg, uchar data)
vgaxo(Crtx, 0x55, crt55);
}
-static Point hotpoint;
+static void
+bt485disable(VGAscr*)
+{
+ uchar r;
+
+ /*
+ * Disable
+ * cursor mode 3;
+ * cursor control enable for Bt485 DAC;
+ * the hardware cursor external operation mode.
+ */
+ r = bt485i(Cmd2) & ~0x03;
+ bt485o(Cmd2, r);
+
+ r = vgaxi(Crtx, 0x45) & ~0x20;
+ vgaxo(Crtx, 0x45, r);
+
+ r = vgaxi(Crtx, 0x55) & ~0x20;
+ vgaxo(Crtx, 0x55, r);
+}
static void
-load(Cursor *c)
+bt485enable(VGAscr*)
{
uchar r;
- int x, y;
+ /*
+ * Turn cursor off.
+ */
+ r = bt485i(Cmd2) & 0xFC;
+ bt485o(Cmd2, r);
- lock(&palettelock);
+ /*
+ * Overscan colour,
+ * cursor colour 1 (white),
+ * cursor colour 2, 3 (black).
+ */
+ bt485o(ColorW, 0x00);
+ bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite);
+
+ bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite);
+
+ bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack);
+ bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack);
+
+ /*
+ * Finally, enable
+ * the hardware cursor external operation mode;
+ * cursor control enable for Bt485 DAC.
+ * The #9GXE cards seem to need the 86C928 Bt485 support
+ * enabled in order to work at all in enhanced mode.
+ */
+
+ r = vgaxi(Crtx, 0x55)|0x20;
+ vgaxo(Crtx, 0x55, r);
+
+ r = vgaxi(Crtx, 0x45)|0x20;
+ vgaxo(Crtx, 0x45, r);
+}
+
+static void
+bt485load(VGAscr* scr, Cursor* curs)
+{
+ uchar r;
+ int x, y;
/*
* Turn cursor off;
@@ 137,7 193,7 @@ load(Cursor *c)
for(y = 0; y < 64; y++){
for(x = 0; x < 64/8; x++){
if(x < 16/8 && y < 16)
- bt485o(Cram, c->clr[x+y*2]);
+ bt485o(Cram, curs->clr[x+y*2]);
else
bt485o(Cram, 0x00);
}
@@ 145,7 201,7 @@ load(Cursor *c)
for(y = 0; y < 64; y++){
for(x = 0; x < 64/8; x++){
if(x < 16/8 && y < 16)
- bt485o(Cram, c->set[x+y*2]);
+ bt485o(Cram, curs->set[x+y*2]);
else
bt485o(Cram, 0x00);
}
@@ 155,113 211,34 @@ load(Cursor *c)
* Initialise the cursor hot-point
* and enable the cursor.
*/
- hotpoint.x = 64+c->offset.x;
- hotpoint.y = 64+c->offset.y;
+ scr->offset.x = 64+curs->offset.x;
+ scr->offset.y = 64+curs->offset.y;
r = (bt485i(Cmd2) & 0xFC)|0x01;
bt485o(Cmd2, r);
-
- unlock(&palettelock);
-}
-
-static void
-enable(void)
-{
- uchar r;
-
- lock(&palettelock);
-
- /*
- * Turn cursor off.
- */
- r = bt485i(Cmd2) & 0xFC;
- bt485o(Cmd2, r);
-
- /*
- * Overscan colour,
- * cursor colour 1 (white),
- * cursor colour 2, 3 (black).
- */
- bt485o(ColorW, 0x00);
- bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite);
-
- bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite);
-
- bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack);
- bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack);
-
- unlock(&palettelock);
-
- /*
- * Finally, enable
- * the hardware cursor external operation mode;
- * cursor control enable for Bt485 DAC.
- * The #9GXE cards seem to need the 86C928 Bt485 support
- * enabled in order to work at all in enhanced mode.
- */
-
- r = vgaxi(Crtx, 0x55)|0x20;
- vgaxo(Crtx, 0x55, r);
-
- r = vgaxi(Crtx, 0x45)|0x20;
- vgaxo(Crtx, 0x45, r);
}
static int
-move(Point p)
+bt485move(VGAscr* scr, Point p)
{
int x, y;
- if(canlock(&palettelock) == 0)
- return 1;
-
- x = p.x+hotpoint.x;
- y = p.y+hotpoint.y;
+ x = p.x+scr->offset.x;
+ y = p.y+scr->offset.y;
bt485o(Cxlr, x & 0xFF);
bt485o(Cxhr, (x>>8) & 0x0F);
bt485o(Cylr, y & 0xFF);
bt485o(Cyhr, (y>>8) & 0x0F);
- unlock(&palettelock);
return 0;
}
-static void
-disable(void)
-{
- uchar r;
-
- /*
- * Disable
- * cursor mode 3;
- * cursor control enable for Bt485 DAC;
- * the hardware cursor external operation mode.
- */
- lock(&palettelock);
- r = bt485i(Cmd2) & ~0x03;
- bt485o(Cmd2, r);
- unlock(&palettelock);
-
- r = vgaxi(Crtx, 0x45) & ~0x20;
- vgaxo(Crtx, 0x45, r);
-
- r = vgaxi(Crtx, 0x55) & ~0x20;
- vgaxo(Crtx, 0x55, r);
-}
-
-Hwgc bt485hwgc = {
+VGAcur vgabt485cur = {
"bt485hwgc",
- enable,
- load,
- move,
- disable,
- 0,
+ bt485enable,
+ bt485disable,
+ bt485load,
+ bt485move,
};
-
-void
-vgabt485link(void)
-{
- addhwgclink(&bt485hwgc);
-}
M pc/vgaclgd542x.c => pc/vgaclgd542x.c +58 -82
@@ 6,58 6,51 @@
#include "io.h"
#include "../port/error.h"
-#include <libg.h>
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
#include "screen.h"
-#include "vga.h"
-
-extern Bitmap gscreen;
-extern Cursor curcursor;
-
-static Lock clgd542xlock;
-static ulong storage;
static int
-setclgd542xpage(int page)
+clgd542xpageset(VGAscr*, int page)
{
- uchar gr9;
+ uchar gr09;
int opage;
-
+
if(vgaxi(Seqx, 0x07) & 0xF0)
page = 0;
- gr9 = vgaxi(Grx, 0x09);
+ gr09 = vgaxi(Grx, 0x09);
if(vgaxi(Grx, 0x0B) & 0x20){
vgaxo(Grx, 0x09, page<<2);
- opage = gr9>>2;
+ opage = gr09>>2;
}
else{
vgaxo(Grx, 0x09, page<<4);
- opage = gr9>>4;
+ opage = gr09>>4;
}
return opage;
}
static void
-clgd542xpage(int page)
+clgd542xpage(VGAscr* scr, int page)
{
- lock(&clgd542xlock);
- setclgd542xpage(page);
- unlock(&clgd542xlock);
+ lock(&scr->devlock);
+ clgd542xpageset(scr, page);
+ unlock(&scr->devlock);
}
static void
-disable(void)
+clgd542xdisable(VGAscr*)
{
uchar sr12;
- lock(&clgd542xlock);
sr12 = vgaxi(Seqx, 0x12);
vgaxo(Seqx, 0x12, sr12 & ~0x01);
- unlock(&clgd542xlock);
}
static void
-enable(void)
+clgd542xenable(VGAscr* scr)
{
uchar sr12;
int mem, x;
@@ 65,16 58,22 @@ enable(void)
/*
* Disable the cursor.
*/
- lock(&clgd542xlock);
sr12 = vgaxi(Seqx, 0x12);
vgaxo(Seqx, 0x12, sr12 & ~0x01);
/*
- * Cursor colours.
+ * Cursor colours.
+ * Can't call setcolor here as cursor is already locked.
*/
vgaxo(Seqx, 0x12, sr12|0x02);
- setcolor(0x00, Pblack<<(32-6), Pblack<<(32-6), Pblack<<(32-6));
- setcolor(0x0F, Pwhite<<(32-6), Pwhite<<(32-6), Pwhite<<(32-6));
+ vgao(PaddrW, 0x00);
+ vgao(Pdata, Pwhite);
+ vgao(Pdata, Pwhite);
+ vgao(Pdata, Pwhite);
+ vgao(PaddrW, 0x0F);
+ vgao(Pdata, Pblack);
+ vgao(Pdata, Pblack);
+ vgao(Pdata, Pblack);
vgaxo(Seqx, 0x12, sr12);
mem = 0;
@@ 114,7 113,7 @@ enable(void)
default: /* uh, ah dunno */
break;
}
- storage = ((256<<mem)-16)*1024;
+ scr->storage = ((256<<mem)-16)*1024;
/*
* Set the current cursor to index 0
@@ 122,12 121,10 @@ enable(void)
*/
vgaxo(Seqx, 0x13, 0);
vgaxo(Seqx, 0x12, sr12|0x05);
-
- unlock(&clgd542xlock);
}
static void
-initcursor(Cursor* c, int xo, int yo, int index)
+clgd542xinitcursor(VGAscr* scr, int xo, int yo, int index)
{
uchar *p, seq07;
uint p0, p1;
@@ 139,18 136,19 @@ initcursor(Cursor* c, int xo, int yo, int index)
*/
seq07 = vgaxi(Seqx, 0x07);
opage = 0;
- p = ((uchar*)gscreen.base);
+ p = KADDR(scr->aperture);
if(!(seq07 & 0xF0)){
- opage = setclgd542xpage(storage>>16);
- p += (storage & 0xFFFF);
+ lock(&scr->devlock);
+ opage = clgd542xpageset(scr, scr->storage>>16);
+ p += (scr->storage & 0xFFFF);
}
else
- p += storage;
+ p += scr->storage;
p += index*1024;
for(y = yo; y < 16; y++){
- p0 = c->set[2*y];
- p1 = c->set[2*y+1];
+ p0 = scr->set[2*y];
+ p1 = scr->set[2*y+1];
if(xo){
p0 = (p0<<xo)|(p1>>(8-xo));
p1 <<= xo;
@@ 161,8 159,8 @@ initcursor(Cursor* c, int xo, int yo, int index)
for(x = 16; x < 64; x += 8)
*p++ = 0x00;
- p0 = c->clr[2*y]|c->set[2*y];
- p1 = c->clr[2*y+1]|c->set[2*y+1];
+ p0 = scr->clr[2*y]|scr->set[2*y];
+ p1 = scr->clr[2*y+1]|scr->set[2*y+1];
if(xo){
p0 = (p0<<xo)|(p1>>(8-xo));
p1 <<= xo;
@@ 181,60 179,46 @@ initcursor(Cursor* c, int xo, int yo, int index)
y++;
}
- if(!(seq07 & 0xF0))
- setclgd542xpage(opage);
+ if(!(seq07 & 0xF0)){
+ clgd542xpageset(scr, opage);
+ unlock(&scr->devlock);
+ }
}
static void
-load(Cursor* c)
+clgd542xload(VGAscr* scr, Cursor* curs)
{
uchar sr12;
/*
- * Lock the display memory so we can update the
- * cursor bitmap if necessary.
* Disable the cursor.
- * If it's the same as the last cursor loaded,
- * just make sure it's enabled and index 0.
*/
- lock(&clgd542xlock);
sr12 = vgaxi(Seqx, 0x12);
vgaxo(Seqx, 0x12, sr12 & ~0x01);
- if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){
- vgaxo(Seqx, 0x13, 0);
- vgaxo(Seqx, 0x12, sr12|0x05);
- unlock(&clgd542xlock);
- return;
- }
- memmove(&curcursor, c, sizeof(Cursor));
- initcursor(c, 0, 0, 0);
+ memmove(&scr->Cursor, curs, sizeof(Cursor));
+ clgd542xinitcursor(scr, 0, 0, 0);
/*
* Enable the cursor.
*/
vgaxo(Seqx, 0x13, 0);
vgaxo(Seqx, 0x12, sr12|0x05);
-
- unlock(&clgd542xlock);
}
static int
-move(Point p)
+clgd542xmove(VGAscr* scr, Point p)
{
int index, x, xo, y, yo;
- if(canlock(&clgd542xlock) == 0)
- return 1;
-
index = 0;
- if((x = p.x+curcursor.offset.x) < 0){
+ if((x = p.x+scr->offset.x) < 0){
xo = -x;
x = 0;
}
else
xo = 0;
- if((y = p.y+curcursor.offset.y) < 0){
+ if((y = p.y+scr->offset.y) < 0){
yo = -y;
y = 0;
}
@@ 242,7 226,7 @@ move(Point p)
yo = 0;
if(xo || yo){
- initcursor(&curcursor, xo, yo, 1);
+ clgd542xinitcursor(scr, xo, yo, 1);
index = 1;
}
vgaxo(Seqx, 0x13, index<<2);
@@ 250,31 234,23 @@ move(Point p)
vgaxo(Seqx, 0x10|((x & 0x07)<<5), (x>>3) & 0xFF);
vgaxo(Seqx, 0x11|((y & 0x07)<<5), (y>>3) & 0xFF);
- unlock(&clgd542xlock);
return 0;
}
-static Hwgc clgd542xhwgc = {
- "clgd542xhwgc",
- enable,
- load,
- move,
- disable,
+VGAdev vgaclgd542xdev = {
+ "clgd542x",
0,
-};
-
-static Vgac clgd542x = {
- "clgd542x",
- clgd542xpage,
0,
-
+ clgd542xpage,
0,
};
-void
-vgaclgd542xlink(void)
-{
- addvgaclink(&clgd542x);
- addhwgclink(&clgd542xhwgc);
-}
+VGAcur vgaclgd542xcur = {
+ "clgd542xhwgc",
+
+ clgd542xenable,
+ clgd542xdisable,
+ clgd542xload,
+ clgd542xmove,
+};
A pc/vgact65545.c => pc/vgact65545.c +147 -0
@@ 0,0 1,147 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include "screen.h"
+
+static void
+ct65545page(VGAscr*, int page)
+{
+ outb(0x3D6, 0x10);
+ outb(0x3D7, page<<6);
+}
+
+static void
+ct65545disable(VGAscr*)
+{
+ outl(0xA3D0, 0);
+}
+
+static void
+ct65545enable(VGAscr* scr)
+{
+ ulong storage;
+
+ /*
+ * Find a place for the cursor data in display memory.
+ * Must be on a 1024-byte boundary.
+ */
+ storage = ROUND(scr->gscreen->width*BY2WD*scr->gscreen->r.max.y, 1024);
+ outl(0xB3D0, storage);
+ scr->storage = storage;
+
+ /*
+ * Set the colours.
+ * Enable the cursor.
+ */
+ outl(0xA7D0, 0xFFFF0000);
+ outl(0xA3D0, 2);
+}
+
+static void
+ct65545initcursor(VGAscr* scr, int xo, int yo, int index)
+{
+ uchar *mem;
+ uint and, clr, set, xor;
+ int i, x, y;
+
+ mem = KADDR(scr->aperture);
+ mem += scr->storage + index*1024;
+
+ for(y = yo; y < 16; y++){
+ clr = (scr->clr[2*y]<<8)|scr->clr[2*y+1];
+ set = (scr->set[2*y]<<8)|scr->set[2*y+1];
+ if(xo){
+ clr <<= xo;
+ set <<= xo;
+ }
+
+ and = 0;
+ xor = 0;
+ for(i = 0; i < 16; i++){
+ if(set & (1<<i))
+ ;
+ else if(clr & (1<<i))
+ xor |= 1<<i;
+ else
+ and |= 1<<i;
+ }
+ *mem++ = and>>8;
+ *mem++ = xor>>8;
+ *mem++ = and;
+ *mem++ = xor;
+
+ for(x = 16; x < 64; x += 8){
+ *mem++ = 0xFF;
+ *mem++ = 0x00;
+ }
+ }
+ while(y < 64+yo){
+ for(x = 0; x < 64; x += 8){
+ *mem++ = 0xFF;
+ *mem++ = 0x00;
+ }
+ y++;
+ }
+}
+
+static void
+ct65545load(VGAscr* scr, Cursor* curs)
+{
+ memmove(&scr->Cursor, curs, sizeof(Cursor));
+ ct65545initcursor(scr, 0, 0, 0);
+}
+
+static int
+ct65545move(VGAscr* scr, Point p)
+{
+ int index, x, xo, y, yo;
+
+ index = 0;
+ if((x = p.x+scr->offset.x) < 0){
+ xo = -x;
+ x = 0;
+ }
+ else
+ xo = 0;
+ if((y = p.y+scr->offset.y) < 0){
+ yo = -y;
+ y = 0;
+ }
+ else
+ yo = 0;
+
+ if(xo || yo){
+ ct65545initcursor(scr, xo, yo, 1);
+ index = 1;
+ }
+ outl(0xB3D0, scr->storage + index*1024);
+
+ outl(0xAFD0, (y<<16)|x);
+
+ return 0;
+}
+
+VGAdev vgact65545dev = {
+ "ct65540", /* BUG: really 65545 */
+
+ 0,
+ 0,
+ ct65545page,
+ 0,
+};
+
+VGAcur vgact65545cur = {
+ "ct65545hwgc",
+
+ ct65545enable,
+ ct65545disable,
+ ct65545load,
+ ct65545move,
+};
D pc/vgamach32.c => pc/vgamach32.c +0 -47
@@ 1,47 0,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include <libg.h>
-#include "screen.h"
-#include "vga.h"
-
-static Lock mach32lock;
-
-static void
-mach32page(int page)
-{
- uchar ae, p;
-
- lock(&mach32lock);
-
- p = (page & 0x0F)<<1;
- p |= (page & 0x07)<<5;
- outs(0x1CE, (p<<8)|0xB2);
-
- outb(0x1CE, 0xAE);
- ae = inb(0x1CE+1);
-
- p = (page>>4) & 0x03;
- p |= p<<2;
- p |= ae & 0xF0;
- outs(0x1CE, (p<<8)|0xAE);
-
- unlock(&mach32lock);
-}
-
-static Vgac mach32 = {
- "mach32",
- mach32page,
-
- 0,
-};
-
-void
-vgamach32link(void)
-{
- addvgaclink(&mach32);
-}
M pc/vgargb524.c => pc/vgargb524.c +53 -92
@@ 5,11 5,10 @@
#include "fns.h"
#include "../port/error.h"
-#include <libg.h>
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
#include "screen.h"
-#include "vga.h"
-
-extern Cursor curcursor;
/*
* IBM RGB524.
@@ 55,7 54,7 @@ static ushort dacxreg[4] = {
};
static uchar
-setrs2(void)
+rgb524setrs2(void)
{
uchar rs2;
@@ 70,37 69,54 @@ rgb524xo(int index, uchar data)
{
vgao(dacxreg[IndexLo], index & 0xFF);
vgao(dacxreg[IndexHi], (index>>8) & 0xFF);
-
vgao(dacxreg[Data], data);
}
static void
-restorers2(uchar rs2)
+rgb524disable(VGAscr*)
{
+ uchar rs2;
+
+ rs2 = rgb524setrs2();
+ rgb524xo(CursorCtl, 0x00);
vgaxo(Crtx, 0x55, rs2);
}
static void
-load(Cursor *c)
+rgb524enable(VGAscr*)
{
- uchar p, p0, p1, rs2;
- int x, y;
+ uchar rs2;
+
+ rs2 = rgb524setrs2();
/*
- * Lock the DAC registers so we can update the
- * cursor bitmap if necessary.
- * If it's the same as the last cursor we loaded,
- * just make sure it's enabled.
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults.
*/
- lock(&palettelock);
- rs2 = setrs2();
- if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){
- rgb524xo(CursorCtl, 0x23);
- restorers2(rs2);
- unlock(&palettelock);
- return;
- }
- memmove(&curcursor, c, sizeof(Cursor));
+ rgb524xo(CursorCtl, 0x00);
+
+ /*
+ * Cursor colour 1 (white),
+ * cursor colour 2 (black).
+ */
+ rgb524xo(CursorR1, Pwhite); rgb524xo(CursorG1, Pwhite); rgb524xo(CursorB1, Pwhite);
+ rgb524xo(CursorR2, Pblack); rgb524xo(CursorG2, Pblack); rgb524xo(CursorB2, Pblack);
+
+ /*
+ * Enable the cursor, 32x32, mode 2.
+ */
+ rgb524xo(CursorCtl, 0x23);
+
+ vgaxo(Crtx, 0x55, rs2);
+}
+
+static void
+rgb524load(VGAscr*, Cursor* curs)
+{
+ uchar p, p0, p1, rs2;
+ int x, y;
+
+ rs2 = rgb524setrs2();
/*
* Make sure cursor is off by initialising the cursor
@@ 132,8 148,8 @@ load(Cursor *c)
for(y = 0; y < 32; y++){
for(x = 0; x < 32/8; x++){
if(x < 16/8 && y < 16){
- p0 = c->clr[x+y*2];
- p1 = c->set[x+y*2];
+ p0 = curs->clr[x+y*2];
+ p1 = curs->set[x+y*2];
p = 0x00;
if(p1 & 0x80)
@@ 181,94 197,39 @@ load(Cursor *c)
}
/*
- * Initialise the cursor hot-point,
+ * Initialise the cursor hotpoint,
* enable the cursor and restore state.
*/
- rgb524xo(CursorHotX, -c->offset.x);
- rgb524xo(CursorHotY, -c->offset.y);
+ rgb524xo(CursorHotX, -curs->offset.x);
+ rgb524xo(CursorHotY, -curs->offset.y);
rgb524xo(CursorCtl, 0x23);
- restorers2(rs2);
- unlock(&palettelock);
-}
-
-static void
-enable(void)
-{
- uchar rs2;
-
- lock(&palettelock);
- rs2 = setrs2();
-
- /*
- * Make sure cursor is off by initialising the cursor
- * control to defaults.
- */
- rgb524xo(CursorCtl, 0x00);
-
- /*
- * Cursor colour 1 (white),
- * cursor colour 2 (black).
- */
- rgb524xo(CursorR1, Pwhite); rgb524xo(CursorG1, Pwhite); rgb524xo(CursorB1, Pwhite);
- rgb524xo(CursorR2, Pblack); rgb524xo(CursorG2, Pblack); rgb524xo(CursorB2, Pblack);
-
- /*
- * Enable the cursor, 32x32, mode 2.
- */
- rgb524xo(CursorCtl, 0x23);
-
- restorers2(rs2);
- unlock(&palettelock);
+ vgaxo(Crtx, 0x55, rs2);
}
static int
-move(Point p)
+rgb524move(VGAscr*, Point p)
{
uchar rs2;
- if(canlock(&palettelock) == 0)
- return 1;
- rs2 = setrs2();
+ rs2 = rgb524setrs2();
rgb524xo(CursorXLo, p.x & 0xFF);
rgb524xo(CursorXHi, (p.x>>8) & 0x0F);
rgb524xo(CursorYLo, p.y & 0xFF);
rgb524xo(CursorYHi, (p.y>>8) & 0x0F);
- restorers2(rs2);
- unlock(&palettelock);
+ vgaxo(Crtx, 0x55, rs2);
return 0;
}
-static void
-disable(void)
-{
- uchar rs2;
-
- lock(&palettelock);
- rs2 = setrs2();
-
- rgb524xo(CursorCtl, 0x00);
-
- restorers2(rs2);
- unlock(&palettelock);
-}
-
-Hwgc rgb524hwgc = {
+VGAcur vgargb524cur = {
"rgb524hwgc",
- enable,
- load,
- move,
- disable,
- 0,
+ rgb524enable,
+ rgb524disable,
+ rgb524load,
+ rgb524move,
};
-
-void
-vgargb524link(void)
-{
- addhwgclink(&rgb524hwgc);
-}
M pc/vgas3.c => pc/vgas3.c +102 -106
@@ 3,30 3,22 @@
#include "mem.h"
#include "dat.h"
#include "fns.h"
+#include "io.h"
#include "../port/error.h"
-#include <libg.h>
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
#include "screen.h"
-#include "vga.h"
-/*
- * Hardware graphics cursor support for
- * generic S3 chipset.
- * Assume we're in enhanced mode.
- */
-static Lock s3lock;
-static ulong storage;
-static Point hotpoint;
-
-extern Bitmap gscreen;
-extern Cursor curcursor;
-
-static void
-sets3page(int page)
+static int
+s3pageset(VGAscr* scr, int page)
{
- uchar crt51;
+ uchar crt35, crt51;
+ int opage;
- if(gscreen.ldepth == 3){
+ crt35 = vgaxi(Crtx, 0x35);
+ if(scr->gscreen->ldepth == 3){
/*
* The S3 registers need to be unlocked for this.
* Let's hope they are already:
@@ 37,15 29,60 @@ sets3page(int page)
* the upper 2 in Crt51<3:2>.
*/
vgaxo(Crtx, 0x35, page & 0x0F);
- crt51 = vgaxi(Crtx, 0x51) & 0xF3;
- vgaxo(Crtx, 0x51, crt51|((page & 0x30)>>2));
+ crt51 = vgaxi(Crtx, 0x51);
+ vgaxo(Crtx, 0x51, (crt51 & ~0x0C)|((page & 0x30)>>2));
+ opage = ((crt51 & 0x0C)<<2)|(crt35 & 0x0F);
}
- else
+ else{
vgaxo(Crtx, 0x35, (page<<2) & 0x0C);
+ opage = (crt35>>2) & 0x03;
+ }
+
+ return opage;
+}
+
+static void
+s3page(VGAscr* scr, int page)
+{
+ lock(&scr->devlock);
+ s3pageset(scr, page);
+ unlock(&scr->devlock);
+}
+
+static ulong
+s3linear(VGAscr* scr, int* size, int* align)
+{
+ ulong aperture, oaperture;
+ int oapsize, wasupamem;
+ Pcidev *p;
+
+ oaperture = scr->aperture;
+ oapsize = scr->apsize;
+ wasupamem = scr->isupamem;
+ if(wasupamem)
+ upafree(oaperture, oapsize);
+ scr->isupamem = 0;
+
+ if(p = pcimatch(nil, 0x5333, 0)){
+ aperture = p->mem[0].bar & ~0x0F;
+ *size = p->mem[0].size;
+ }
+ else
+ aperture = 0;
+
+ aperture = upamalloc(aperture, *size, *align);
+ if(aperture == 0){
+ if(wasupamem && upamalloc(oaperture, oapsize, 0))
+ scr->isupamem = 1;
+ }
+ else
+ scr->isupamem = 1;
+
+ return aperture;
}
static void
-vsyncactive(void)
+s3vsyncactive(void)
{
/*
* Hardware cursor information is fetched from display memory
@@ 57,7 94,7 @@ vsyncactive(void)
}
static void
-_disable(void)
+s3disable(VGAscr*)
{
uchar crt45;
@@ 65,26 102,17 @@ _disable(void)
* Turn cursor off.
*/
crt45 = vgaxi(Crtx, 0x45) & 0xFE;
- vsyncactive();
+ s3vsyncactive();
vgaxo(Crtx, 0x45, crt45);
}
static void
-disable(void)
-{
- lock(&s3lock);
- _disable();
- unlock(&s3lock);
-}
-
-static void
-enable(void)
+s3enable(VGAscr* scr)
{
int i;
+ ulong storage;
- lock(&s3lock);
-
- _disable();
+ s3disable(scr);
/*
* Cursor colours. Set both the CR0[EF] and the colour
@@ 104,53 132,38 @@ enable(void)
* Find a place for the cursor data in display memory.
* Must be on a 1024-byte boundary.
*/
- storage = (gscreen.width*BY2WD*gscreen.r.max.y+1023)/1024;
+ storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024;
vgaxo(Crtx, 0x4C, (storage>>8) & 0x0F);
vgaxo(Crtx, 0x4D, storage & 0xFF);
storage *= 1024;
+ scr->storage = storage;
/*
* Enable the cursor in X11 mode.
*/
vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55)|0x10);
- vsyncactive();
+ s3vsyncactive();
vgaxo(Crtx, 0x45, 0x01);
-
- unlock(&s3lock);
}
static void
-load(Cursor *c)
+s3load(VGAscr* scr, Cursor* curs)
{
uchar *p;
- int x, y;
-
- /*
- * Lock the display memory so we can update the
- * cursor bitmap if necessary.
- * If it's the same as the last cursor we loaded,
- * just make sure it's enabled.
- */
- lock(&s3lock);
- if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){
- vsyncactive();
- vgaxo(Crtx, 0x45, 0x01);
- unlock(&s3lock);
- return;
- }
- memmove(&curcursor, c, sizeof(Cursor));
+ int opage, x, y;
/*
- * Disable the cursor.
- * Set the display page (do we need to restore
- * the current contents when done?) and the
- * pointer to the two planes. What if this crosses
- * into a new page?
+ * Disable the cursor and
+ * set the pointer to the two planes.
+ * Is linear addressing turned on? This will determine
+ * how we access the cursor storage.
*/
- _disable();
+ s3disable(scr);
- sets3page(storage>>16);
- p = ((uchar*)gscreen.base) + (storage & 0xFFFF);
+ p = KADDR(scr->aperture);
+ lock(&scr->devlock);
+ opage = s3pageset(scr, scr->storage>>16);
+ p += (scr->storage & 0xFFFF);
/*
* The cursor is set in X11 mode which gives the following
@@ 168,10 181,10 @@ load(Cursor *c)
for(y = 0; y < 64; y++){
for(x = 0; x < 64/8; x += 2){
if(x < 16/8 && y < 16){
- *p++ = c->clr[2*y + x]|c->set[2*y + x];
- *p++ = c->clr[2*y + x+1]|c->set[2*y + x+1];
- *p++ = c->set[2*y + x];
- *p++ = c->set[2*y + x+1];
+ *p++ = curs->clr[2*y + x]|curs->set[2*y + x];
+ *p++ = curs->clr[2*y + x+1]|curs->set[2*y + x+1];
+ *p++ = curs->set[2*y + x];
+ *p++ = curs->set[2*y + x+1];
}
else {
*p++ = 0x00;
@@ 182,24 195,22 @@ load(Cursor *c)
}
}
+ s3pageset(scr, opage);
+ unlock(&scr->devlock);
+
/*
- * Set the cursor hotpoint and enable the cursor.
+ * Save the cursor hotpoint and enable the cursor.
*/
- hotpoint = c->offset;
- vsyncactive();
+ scr->offset = curs->offset;
+ s3vsyncactive();
vgaxo(Crtx, 0x45, 0x01);
-
- unlock(&s3lock);
}
static int
-move(Point p)
+s3move(VGAscr* scr, Point p)
{
int x, xo, y, yo;
- if(canlock(&s3lock) == 0)
- return 1;
-
/*
* Mustn't position the cursor offscreen even partially,
* or it disappears. Therefore, if x or y is -ve, adjust the
@@ 208,14 219,14 @@ move(Point p)
* cursor doesn't disappear off the left edge properly, so
* round it up to be even.
*/
- if((x = p.x+hotpoint.x) < 0){
+ if((x = p.x+scr->offset.x) < 0){
xo = -x;
xo = ((xo+1)/2)*2;
x = 0;
}
else
xo = 0;
- if((y = p.y+hotpoint.y) < 0){
+ if((y = p.y+scr->offset.y) < 0){
yo = -y;
y = 0;
}
@@ 229,38 240,23 @@ move(Point p)
vgaxo(Crtx, 0x4F, yo);
vgaxo(Crtx, 0x48, (y>>8) & 0x07);
- unlock(&s3lock);
return 0;
}
-Hwgc s3hwgc = {
- "s3hwgc",
- enable,
- load,
- move,
- disable,
+VGAdev vgas3dev = {
+ "s3",
0,
+ 0,
+ s3page,
+ s3linear,
};
-static void
-s3page(int page)
-{
- lock(&s3lock);
- sets3page(page);
- unlock(&s3lock);
-}
-
-static Vgac s3 = {
- "s3",
- s3page,
+VGAcur vgas3cur = {
+ "s3hwgc",
- 0,
+ s3enable,
+ s3disable,
+ s3load,
+ s3move,
};
-
-void
-vgas3link(void)
-{
- addvgaclink(&s3);
- addhwgclink(&s3hwgc);
-}
M pc/vgatvp3020.c => pc/vgatvp3020.c +68 -107
@@ 5,24 5,18 @@
#include "fns.h"
#include "../port/error.h"
-#include <libg.h>
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
#include "screen.h"
-#include "vga.h"
-
-extern Cursor curcursor;
/*
* TVP3020 Viewpoint Video Interface Pallette.
* Assumes hooked up to an S3 86C928.
*/
enum {
- AddrW = 0x00, /* Palette address register - write mode */
- Palette = 0x01, /* Color palette holding register */
- Pmask = 0x02, /* Pixel read mask */
- AddrR = 0x03, /* Palette address register - read mode */
-
- Index = 0x06, /* Index register */
- Data = 0x07, /* Data register */
+ Index = 0x06, /* Index register */
+ Data = 0x07, /* Data register */
};
/*
@@ 56,24 50,62 @@ tvp3020xo(uchar index, uchar data)
}
static void
-load(Cursor *c)
+tvp3020disable(VGAscr*)
{
- uchar p, p0, p1;
- int x, y;
+ uchar r;
/*
- * Lock the DAC registers so we can update the
- * cursor bitmap if necessary.
- * If it's the same as the last cursor we loaded,
- * just make sure it's enabled.
+ * Disable
+ * cursor;
+ * cursor control enable for Bt485 DAC (!);
+ * the hardware cursor external operation mode.
*/
- lock(&palettelock);
- if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){
- tvp3020xo(0x06, 0x40|0x10); /* Cursor Control Register */
- unlock(&palettelock);
- return;
- }
- memmove(&curcursor, c, sizeof(Cursor));
+ tvp3020xo(0x06, 0x10); /* Cursor Control Register */
+
+ r = vgaxi(Crtx, 0x45) & ~0x20;
+ vgaxo(Crtx, 0x45, r);
+
+ r = vgaxi(Crtx, 0x55) & ~0x20;
+ vgaxo(Crtx, 0x55, r);
+}
+
+static void
+tvp3020enable(VGAscr*)
+{
+ uchar r;
+
+ /*
+ * Make sure cursor is off by initialising the cursor
+ * control to defaults + X-Windows cursor mode.
+ */
+ tvp3020xo(0x06, 0x10); /* Cursor Control Register */
+
+ /*
+ * Overscan colour,
+ * cursor colour 1 (white),
+ * cursor colour 2 (black).
+ */
+ tvp3020xo(0x20, Pwhite); tvp3020xo(0x21, Pwhite); tvp3020xo(0x22, Pwhite);
+ tvp3020xo(0x23, Pwhite); tvp3020xo(0x24, Pwhite); tvp3020xo(0x25, Pwhite);
+ tvp3020xo(0x26, Pblack); tvp3020xo(0x27, Pblack); tvp3020xo(0x28, Pblack);
+
+ /*
+ * Finally, enable
+ * the hardware cursor external operation mode;
+ * cursor control enable for Bt485 DAC (!).
+ */
+ r = vgaxi(Crtx, 0x55)|0x20;
+ vgaxo(Crtx, 0x55, r);
+
+ r = vgaxi(Crtx, 0x45)|0x20;
+ vgaxo(Crtx, 0x45, r);
+}
+
+static void
+tvp3020load(VGAscr*, Cursor* curs)
+{
+ uchar p, p0, p1;
+ int x, y;
/*
* Make sure cursor is off by initialising the cursor
@@ 104,8 136,8 @@ load(Cursor *c)
for(y = 0; y < 64; y++){
for(x = 0; x < 64/8; x++){
if(x < 16/8 && y < 16){
- p0 = c->clr[x+y*2];
- p1 = c->set[x+y*2];
+ p0 = curs->clr[x+y*2];
+ p1 = curs->set[x+y*2];
p = 0x00;
if(p1 & 0x10)
@@ 153,102 185,31 @@ load(Cursor *c)
}
/*
- * Initialise the cursor hot-point
+ * Initialise the cursor hotpoint
* and enable the cursor.
*/
- tvp3020xo(0x04, -c->offset.x); /* Sprite Origin X */
- tvp3020xo(0x05, -c->offset.y); /* Sprite Origin Y */
+ tvp3020xo(0x04, -curs->offset.x); /* Sprite Origin X */
+ tvp3020xo(0x05, -curs->offset.y); /* Sprite Origin Y */
tvp3020xo(0x06, 0x40|0x10); /* Cursor Control Register */
-
- unlock(&palettelock);
-}
-
-static void
-enable(void)
-{
- uchar r;
-
- lock(&palettelock);
-
- /*
- * Make sure cursor is off by initialising the cursor
- * control to defaults + X-Windows cursor mode.
- */
- tvp3020xo(0x06, 0x10); /* Cursor Control Register */
-
- /*
- * Overscan colour,
- * cursor colour 1 (white),
- * cursor colour 2 (black).
- */
- tvp3020xo(0x20, Pwhite); tvp3020xo(0x21, Pwhite); tvp3020xo(0x22, Pwhite);
- tvp3020xo(0x23, Pwhite); tvp3020xo(0x24, Pwhite); tvp3020xo(0x25, Pwhite);
- tvp3020xo(0x26, Pblack); tvp3020xo(0x27, Pblack); tvp3020xo(0x28, Pblack);
-
- unlock(&palettelock);
-
- /*
- * Finally, enable
- * the hardware cursor external operation mode;
- * cursor control enable for Bt485 DAC (!).
- */
- r = vgaxi(Crtx, 0x55)|0x20;
- vgaxo(Crtx, 0x55, r);
-
- r = vgaxi(Crtx, 0x45)|0x20;
- vgaxo(Crtx, 0x45, r);
}
static int
-move(Point p)
+tvp3020move(VGAscr*, Point p)
{
- if(canlock(&palettelock) == 0)
- return 1;
-
tvp3020xo(0x00, p.x & 0xFF); /* Cursor Position X LSB */
tvp3020xo(0x01, (p.x>>8) & 0x0F); /* Cursor Position X MSB */
tvp3020xo(0x02, p.y & 0xFF); /* Cursor Position Y LSB */
tvp3020xo(0x03, (p.y>>8) & 0x0F); /* Cursor Position Y MSB */
- unlock(&palettelock);
return 0;
}
-static void
-disable(void)
-{
- uchar r;
-
- /*
- * Disable
- * cursor;
- * cursor control enable for Bt485 DAC (!);
- * the hardware cursor external operation mode.
- */
- lock(&palettelock);
- tvp3020xo(0x06, 0x10); /* Cursor Control Register */
- unlock(&palettelock);
-
- r = vgaxi(Crtx, 0x45) & ~0x20;
- vgaxo(Crtx, 0x45, r);
-
- r = vgaxi(Crtx, 0x55) & ~0x20;
- vgaxo(Crtx, 0x55, r);
-}
-
-Hwgc tvp3020hwgc = {
+VGAcur vgatvp3020cur = {
"tvp3020hwgc",
- enable,
- load,
- move,
- disable,
- 0,
+ tvp3020enable,
+ tvp3020disable,
+ tvp3020load,
+ tvp3020move,
};
-
-void
-vgatvp3020link(void)
-{
- addhwgclink(&tvp3020hwgc);
-}
M pc/vgatvp3026.c => pc/vgatvp3026.c +48 -86
@@ 5,11 5,10 @@
#include "fns.h"
#include "../port/error.h"
-#include <libg.h>
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
#include "screen.h"
-#include "vga.h"
-
-extern Cursor curcursor;
/*
* TVP3026 Viewpoint Video Interface Pallette.
@@ 40,8 39,6 @@ static ushort dacxreg[4] = {
PaddrW, Pdata, Pixmask, PaddrR
};
-static Point hotpoint;
-
static uchar
tvp3026io(uchar reg, uchar data)
{
@@ 75,23 72,42 @@ tvp3026xo(uchar index, uchar data)
}
static void
-load(Cursor *c)
+tvp3026disable(VGAscr*)
{
- int x, y;
+ tvp3026xo(Icctl, 0x90);
+ tvp3026o(Cctl, 0x00);
+}
+static void
+tvp3026enable(VGAscr*)
+{
/*
- * Lock the DAC registers so we can update the
- * cursor bitmap if necessary.
- * If it's the same as the last cursor we loaded,
- * just make sure it's enabled.
+ * Make sure cursor is off and direct control enabled.
*/
- lock(&palettelock);
- if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){
- tvp3026o(Cctl, 0x01);
- unlock(&palettelock);
- return;
- }
- memmove(&curcursor, c, sizeof(Cursor));
+ tvp3026xo(Icctl, 0x90);
+ tvp3026o(Cctl, 0x00);
+
+ /*
+ * Overscan colour,
+ * cursor colour 1 (white),
+ * cursor colour 2, 3 (black).
+ */
+ tvp3026o(CaddrW, 0x00);
+ tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite);
+ tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite);
+ tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack);
+ tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack);
+
+ /*
+ * Enable the cursor in 3-colour mode.
+ */
+ tvp3026o(Cctl, 0x01);
+}
+
+static void
+tvp3026load(VGAscr* scr, Cursor* curs)
+{
+ int x, y;
/*
* Make sure cursor is off by initialising the cursor
@@ 123,7 139,7 @@ load(Cursor *c)
for(y = 0; y < 64; y++){
for(x = 0; x < 64/8; x++){
if(x < 16/8 && y < 16)
- tvp3026o(Cram, c->clr[x+y*2]);
+ tvp3026o(Cram, curs->clr[x+y*2]);
else
tvp3026o(Cram, 0x00);
}
@@ 131,96 147,42 @@ load(Cursor *c)
for(y = 0; y < 64; y++){
for(x = 0; x < 64/8; x++){
if(x < 16/8 && y < 16)
- tvp3026o(Cram, c->set[x+y*2]);
+ tvp3026o(Cram, curs->set[x+y*2]);
else
tvp3026o(Cram, 0x00);
}
}
/*
- * Initialise the cursor hot-point
+ * Initialise the cursor hotpoint
* and enable the cursor in 3-colour mode.
*/
- hotpoint.x = 64+c->offset.x;
- hotpoint.y = 64+c->offset.y;
-
- tvp3026o(Cctl, 0x01);
-
- unlock(&palettelock);
-}
-
-static void
-enable(void)
-{
- lock(&palettelock);
-
- /*
- * Make sure cursor is off and direct control enabled.
- */
- tvp3026xo(Icctl, 0x90);
- tvp3026o(Cctl, 0x00);
-
- /*
- * Overscan colour,
- * cursor colour 1 (white),
- * cursor colour 2, 3 (black).
- */
- tvp3026o(CaddrW, 0x00);
- tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite);
- tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite);
- tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack);
- tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack);
-
- /*
- * Enable the cursor in 3-colour mode.
- */
+ scr->offset.x = 64+curs->offset.x;
+ scr->offset.y = 64+curs->offset.y;
tvp3026o(Cctl, 0x01);
-
- unlock(&palettelock);
}
static int
-move(Point p)
+tvp3026move(VGAscr* scr, Point p)
{
int x, y;
- if(canlock(&palettelock) == 0)
- return 1;
-
- x = p.x+hotpoint.x;
- y = p.y+hotpoint.y;
+ x = p.x+scr->offset.x;
+ y = p.y+scr->offset.y;
tvp3026o(Cxlsb, x & 0xFF);
tvp3026o(Cxmsb, (x>>8) & 0x0F);
tvp3026o(Cylsb, y & 0xFF);
tvp3026o(Cymsb, (y>>8) & 0x0F);
- unlock(&palettelock);
-
return 0;
}
-static void
-disable(void)
-{
- lock(&palettelock);
- tvp3026xo(Icctl, 0x90);
- tvp3026o(Cctl, 0x00);
- unlock(&palettelock);
-}
-
-Hwgc tvp3026hwgc = {
+VGAcur vgatvp3026cur = {
"tvp3026hwgc",
- enable,
- load,
- move,
- disable,
- 0,
+ tvp3026enable,
+ tvp3026disable,
+ tvp3026load,
+ tvp3026move,
};
-
-void
-vgatvp3026link(void)
-{
- addhwgclink(&tvp3026hwgc);
-}
A pc/vgax.c => pc/vgax.c +101 -0
@@ 0,0 1,101 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include "screen.h"
+
+static Lock vgaxlock; /* access to index registers */
+
+int
+vgaxi(long port, uchar index)
+{
+ uchar data;
+
+ ilock(&vgaxlock);
+ switch(port){
+
+ case Seqx:
+ case Crtx:
+ case Grx:
+ outb(port, index);
+ data = inb(port+1);
+ break;
+
+ case Attrx:
+ /*
+ * Allow processor access to the colour
+ * palette registers. Writes to Attrx must
+ * be preceded by a read from Status1 to
+ * initialise the register to point to the
+ * index register and not the data register.
+ * Processor access is allowed by turning
+ * off bit 0x20.
+ */
+ inb(Status1);
+ if(index < 0x10){
+ outb(Attrx, index);
+ data = inb(Attrx+1);
+ inb(Status1);
+ outb(Attrx, 0x20|index);
+ }
+ else{
+ outb(Attrx, 0x20|index);
+ data = inb(Attrx+1);
+ }
+ break;
+
+ default:
+ iunlock(&vgaxlock);
+ return -1;
+ }
+ iunlock(&vgaxlock);
+
+ return data & 0xFF;
+}
+
+int
+vgaxo(long port, uchar index, uchar data)
+{
+ ilock(&vgaxlock);
+ switch(port){
+
+ case Seqx:
+ case Crtx:
+ case Grx:
+ /*
+ * We could use an outport here, but some chips
+ * (e.g. 86C928) have trouble with that for some
+ * registers.
+ */
+ outb(port, index);
+ outb(port+1, data);
+ break;
+
+ case Attrx:
+ inb(Status1);
+ if(index < 0x10){
+ outb(Attrx, index);
+ outb(Attrx, data);
+ inb(Status1);
+ outb(Attrx, 0x20|index);
+ }
+ else{
+ outb(Attrx, 0x20|index);
+ outb(Attrx, data);
+ }
+ break;
+
+ default:
+ iunlock(&vgaxlock);
+ return -1;
+ }
+ iunlock(&vgaxlock);
+
+ return 0;
+}
M port/alloc.c => port/alloc.c +519 -327
@@ 1,411 1,603 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
+#include "pool.h"
#include "dat.h"
#include "fns.h"
#include "error.h"
+#define left u.s.bhl
+#define right u.s.bhr
+#define fwd u.s.bhf
+#define prev u.s.bhv
+#define parent u.s.bhp
-/*
- * Plan 9 has two kernel allocators, the x... routines provide a first
- * fit hole allocator which should be used for permanent or large structures.
- * Routines are provided to allocate aligned memory which does not cross
- * arbitrary 2^n boundaries. A second allocator malloc, smalloc, free is
- * a 2n bucket allocator which steals from the x routines. This should
- * be used for small frequently used structures.
- */
-
-#define datoff ((ulong)((Xhdr*)0)->data)
-#define bdatoff ((ulong)((Bucket*)0)->data)
-
-enum
+struct Pool
{
- Maxpow = 19,
- CUTOFF = 12,
- Nhole = 128,
- Magichole = 0xDeadBabe,
- Magic2n = 0xFeedBeef,
- Spanlist = 64,
+ char* name;
+ ulong maxsize;
+ int quanta;
+ int chunk;
+ ulong cursize;
+ ulong arenasize;
+ ulong hw;
+ Lock l;
+ Bhdr* root;
+ Bhdr* chain;
+ int nalloc;
+ int nfree;
+ int nbrk;
+ int lastfree;
+ void (*move)(void*, void*);
};
-typedef struct Hole Hole;
-typedef struct Xalloc Xalloc;
-typedef struct Xhdr Xhdr;
-typedef struct Bucket Bucket;
-typedef struct Arena Arena;
-
-struct Hole
+struct
{
- ulong addr;
- ulong size;
- ulong top;
- Hole *link;
+ int n;
+ Pool pool[MAXPOOL];
+ Lock l;
+} table = {
+ 2,
+ {
+ { "Main", 4*1024*1024, 31, 128*1024 },
+ { "Image", 8*1024*1024, 31, 2*1024*1024 },
+ }
};
-struct Xhdr
-{
- ulong size;
- ulong magix;
- char data[1];
-};
+Pool* mainmem = &table.pool[0];
+Pool* imagmem = &table.pool[1];
-struct Xalloc
-{
- Lock;
- Hole hole[Nhole];
- Hole *flist;
- Hole *table;
-};
+int poolcompact(Pool*);
-struct Bucket
+Bhdr*
+poolchain(Pool *p)
{
- int size;
- int magic;
- Bucket *next;
- ulong pc;
- char data[1];
-};
+ return p->chain;
+}
-struct Arena
+void
+pooldel(Pool *p, Bhdr *t)
{
- Lock;
- Bucket *btab[Maxpow];
- int nbuck[Maxpow];
- QLock rq;
- Rendez r;
-};
+ Bhdr *s, *f, *rp, *q;
-static Arena arena;
-static Xalloc xlists;
+ if(t->parent == nil && p->root != t) {
+ t->prev->fwd = t->fwd;
+ t->fwd->prev = t->prev;
+ return;
+ }
+
+ if(t->fwd != t) {
+ f = t->fwd;
+ s = t->parent;
+ f->parent = s;
+ if(s == nil)
+ p->root = f;
+ else {
+ if(s->left == t)
+ s->left = f;
+ else
+ s->right = f;
+ }
+
+ rp = t->left;
+ f->left = rp;
+ if(rp != nil)
+ rp->parent = f;
+ rp = t->right;
+ f->right = rp;
+ if(rp != nil)
+ rp->parent = f;
+
+ t->prev->fwd = t->fwd;
+ t->fwd->prev = t->prev;
+ return;
+ }
-void
-xinit(void)
-{
- Hole *h, *eh;
- int upages, np0, np1;
-
- eh = &xlists.hole[Nhole-1];
- for(h = xlists.hole; h < eh; h++)
- h->link = h+1;
-
- xlists.flist = xlists.hole;
-
- upages = conf.upages;
- np1 = upages;
- if(np1 > conf.npage1)
- np1 = conf.npage1;
-
- palloc.p1 = conf.base1 + (conf.npage1 - np1)*BY2PG;
- conf.npage1 -= np1;
- xhole(conf.base1, conf.npage1*BY2PG);
- conf.npage1 = conf.base1+(conf.npage1*BY2PG);
- upages -= np1;
-
- np0 = upages;
- if(np0 > conf.npage0)
- np0 = conf.npage0;
-
- palloc.p0 = conf.base0 + (conf.npage0 - np0)*BY2PG;
- conf.npage0 -= np0;
- xhole(conf.base0, conf.npage0*BY2PG);
- conf.npage0 = conf.base0+(conf.npage0*BY2PG);
-
- palloc.np0 = np0;
- palloc.np1 = np1;
- /* Save the bounds of kernel alloc memory for kernel mmu mapping */
- conf.base0 = (ulong)KADDR(conf.base0);
- conf.base1 = (ulong)KADDR(conf.base1);
- conf.npage0 = (ulong)KADDR(conf.npage0);
- conf.npage1 = (ulong)KADDR(conf.npage1);
+ if(t->left == nil)
+ rp = t->right;
+ else {
+ if(t->right == nil)
+ rp = t->left;
+ else {
+ f = t;
+ rp = t->right;
+ s = rp->left;
+ while(s != nil) {
+ f = rp;
+ rp = s;
+ s = rp->left;
+ }
+ if(f != t) {
+ s = rp->right;
+ f->left = s;
+ if(s != nil)
+ s->parent = f;
+ s = t->right;
+ rp->right = s;
+ if(s != nil)
+ s->parent = rp;
+ }
+ s = t->left;
+ rp->left = s;
+ s->parent = rp;
+ }
+ }
+ q = t->parent;
+ if(q == nil)
+ p->root = rp;
+ else {
+ if(t == q->left)
+ q->left = rp;
+ else
+ q->right = rp;
+ }
+ if(rp != nil)
+ rp->parent = q;
}
-/*
- * NB. spanalloc memory will cause a panic if free'd
- */
-void*
-xspanalloc(ulong size, int align, ulong span)
+void
+pooladd(Pool *p, Bhdr *q)
{
- ulong a, v, t;
-
- a = (ulong)xalloc(size+align+span);
- if(a == 0)
- panic("xspanalloc: %d %d %lux\n", size, align, span);
-
- if(span > 2) {
- v = (a + span) & ~(span-1);
- t = v - a;
- if(t > 0)
- xhole(PADDR(a), t);
- t = a + span - v;
- if(t > 0)
- xhole(PADDR(v+size+align), t);
+ int size;
+ Bhdr *tp, *t;
+
+ q->magic = MAGIC_F;
+
+ q->left = nil;
+ q->right = nil;
+ q->parent = nil;
+ q->fwd = q;
+ q->prev = q;
+
+ t = p->root;
+ if(t == nil) {
+ p->root = q;
+ return;
}
- else
- v = a;
- if(align > 1)
- v = (v + align) & ~(align-1);
+ size = q->size;
- return (void*)v;
+ tp = nil;
+ while(t != nil) {
+ if(size == t->size) {
+ q->fwd = t->fwd;
+ q->fwd->prev = q;
+ q->prev = t;
+ t->fwd = q;
+ return;
+ }
+ tp = t;
+ if(size < t->size)
+ t = t->left;
+ else
+ t = t->right;
+ }
+
+ q->parent = tp;
+ if(size < tp->size)
+ tp->left = q;
+ else
+ tp->right = q;
}
void*
-xallocz(ulong size, int zero)
+poolalloc(Pool *p, int size)
{
- Xhdr *p;
- Hole *h, **l;
-
- size += BY2V + sizeof(Xhdr);
- size &= ~(BY2V-1);
-
- ilock(&xlists);
- l = &xlists.table;
- for(h = *l; h; h = h->link) {
- if(h->size >= size) {
- p = (Xhdr*)h->addr;
- h->addr += size;
- h->size -= size;
- if(h->size == 0) {
- *l = h->link;
- h->link = xlists.flist;
- xlists.flist = h;
- }
- iunlock(&xlists);
- p = KADDR(p);
- if(zero)
- memset(p, 0, size);
- p->magix = Magichole;
- p->size = size;
- return p->data;
+ Bhdr *q, *t;
+ int alloc, ldr, ns, frag;
+
+ size = (size + BHDRSIZE + p->quanta) & ~(p->quanta);
+
+ ilock(&p->l);
+ p->nalloc++;
+
+ t = p->root;
+ q = nil;
+ while(t) {
+ if(t->size == size) {
+ pooldel(p, t);
+ t->magic = MAGIC_A;
+ p->cursize += t->size;
+ if(p->cursize > p->hw)
+ p->hw = p->cursize;
+ iunlock(&p->l);
+ return B2D(t);
+ }
+ if(size < t->size) {
+ q = t;
+ t = t->left;
}
- l = &h->link;
+ else
+ t = t->right;
+ }
+ if(q != nil) {
+ pooldel(p, q);
+ q->magic = MAGIC_A;
+ frag = q->size - size;
+ if(frag < (size>>2)) {
+ p->cursize += q->size;
+ if(p->cursize > p->hw)
+ p->hw = p->cursize;
+ iunlock(&p->l);
+ return B2D(q);
+ }
+ /* Split */
+ ns = q->size - size;
+ q->size = size;
+ B2T(q)->hdr = q;
+ t = B2NB(q);
+ t->size = ns;
+ B2T(t)->hdr = t;
+ pooladd(p, t);
+ p->cursize += q->size;
+ if(p->cursize > p->hw)
+ p->hw = p->cursize;
+ iunlock(&p->l);
+ return B2D(q);
}
- iunlock(&xlists);
- return nil;
-}
-void
-xfree(void *p)
-{
- Xhdr *x;
+ ns = p->chunk;
+ if(size > ns)
+ ns = size;
+ ldr = p->quanta+1;
+
+ alloc = ns+ldr+sizeof(t->magic);
+ p->arenasize += alloc;
+ if(p->arenasize > p->maxsize) {
+ p->arenasize -= alloc;
+
+ if(poolcompact(p)) {
+ iunlock(&p->l);
+ return poolalloc(p, size);
+ }
+
+ iunlock(&p->l);
+ print("arena too large: size %d cursize %d arenasize %d maxsize %d\n",
+ size, p->cursize, p->arenasize, p->maxsize);
+ return nil;
+ }
- x = (Xhdr*)((ulong)p - datoff);
- if(x->magix != Magichole) {
- xsummary();
- panic("xfree(0x%lux) 0x%lux!=0x%lux", p, Magichole, x->magix);
+ p->nbrk++;
+ t = xalloc(alloc);
+ if(t == nil) {
+ iunlock(&p->l);
+ return nil;
}
- xhole(PADDR(x), x->size);
+
+ t->magic = MAGIC_E; /* Make a leader */
+ t->size = ldr;
+ t->csize = ns+ldr;
+ t->clink = p->chain;
+ p->chain = t;
+ B2T(t)->hdr = t;
+ t = B2NB(t);
+
+ t->magic = MAGIC_A; /* Make the block we are going to return */
+ t->size = size;
+ B2T(t)->hdr = t;
+ q = t;
+
+ ns -= size; /* Free the rest */
+ if(ns > 0) {
+ q = B2NB(t);
+ q->size = ns;
+ B2T(q)->hdr = q;
+ pooladd(p, q);
+ }
+ B2NB(q)->magic = MAGIC_E; /* Mark the end of the chunk */
+
+ p->cursize += t->size;
+ if(p->cursize > p->hw)
+ p->hw = p->cursize;
+ iunlock(&p->l);
+ return B2D(t);
}
void
-xhole(ulong addr, ulong size)
+poolfree(Pool *p, void *v)
{
- ulong top;
- Hole *h, *c, **l;
+ Bhdr *b, *c;
- if(size == 0)
- return;
+ D2B(b, v);
- top = addr + size;
- ilock(&xlists);
- l = &xlists.table;
- for(h = *l; h; h = h->link) {
- if(h->top == addr) {
- h->size += size;
- h->top = h->addr+h->size;
- c = h->link;
- if(c && h->top == c->addr) {
- h->top += c->size;
- h->size += c->size;
- h->link = c->link;
- c->link = xlists.flist;
- xlists.flist = c;
- }
- iunlock(&xlists);
- return;
- }
- if(h->addr > addr)
- break;
- l = &h->link;
- }
- if(h && top == h->addr) {
- h->addr -= size;
- h->size += size;
- iunlock(&xlists);
- return;
+ ilock(&p->l);
+ p->nfree++;
+ p->cursize -= b->size;
+
+ c = B2NB(b);
+ if(c->magic == MAGIC_F) { /* Join forward */
+ pooldel(p, c);
+ c->magic = 0;
+ b->size += c->size;
+ B2T(b)->hdr = b;
}
- if(xlists.flist == nil) {
- iunlock(&xlists);
- print("xfree: no free holes, leaked %d bytes\n", size);
- return;
+ c = B2PT(b)->hdr;
+ if(c->magic == MAGIC_F) { /* Join backward */
+ pooldel(p, c);
+ b->magic = 0;
+ c->size += b->size;
+ b = c;
+ B2T(b)->hdr = b;
}
- h = xlists.flist;
- xlists.flist = h->link;
- h->addr = addr;
- h->top = top;
- h->size = size;
- h->link = *l;
- *l = h;
- iunlock(&xlists);
+ pooladd(p, b);
+ iunlock(&p->l);
+}
+
+int
+poolread(char *va, int count, ulong offset)
+{
+ Pool *p;
+ int n, i, signed_off;
+
+ n = 0;
+ signed_off = offset;
+ for(i = 0; i < table.n; i++) {
+ p = &table.pool[i];
+ n += snprint(va+n, count-n, "%11d %11d %11d %11d %11d %11d %s\n",
+ p->cursize,
+ p->maxsize,
+ p->hw,
+ p->nalloc,
+ p->nfree,
+ p->nbrk,
+ p->name);
+
+ if(signed_off > 0) {
+ signed_off -= n;
+ if(signed_off < 0) {
+ memmove(va, va+n+signed_off, -signed_off);
+ n = -signed_off;
+ }
+ else
+ n = 0;
+ }
+
+ }
+ return n;
}
void*
-mallocz(ulong size, int zero)
+malloc(ulong size)
{
- int pow, n;
- Bucket *bp, **l;
+ void *v;
- for(pow = 3; pow <= Maxpow; pow++)
- if(size <= (1<<pow))
- goto good;
+ v = poolalloc(mainmem, size);
+ if(v != nil)
+ memset(v, 0, size);
+ return v;
+}
- return nil;
-good:
+void*
+smalloc(ulong size)
+{
+ void *v;
- /* Allocate off this list */
- ilock(&arena);
- bp = arena.btab[pow];
- if(bp) {
- arena.btab[pow] = bp->next;
- iunlock(&arena);
+ for(;;) {
+ v = poolalloc(mainmem, size);
+ if(v != nil)
+ break;
+ tsleep(&up->sleep, return0, 0, 100);
+ }
+ memset(v, 0, size);
+ return v;
+}
- if(bp->magic != 0)
- panic("malloc %lux %lux", bp->magic, bp->pc);
+void*
+mallocz(ulong size, int clr)
+{
+ void *v;
- bp->magic = Magic2n;
+ v = poolalloc(mainmem, size);
+ if(clr && v != nil)
+ memset(v, 0, size);
+ return v;
+}
- if(zero)
- memset(bp->data, 0, size);
- return bp->data;
- }
- iunlock(&arena);
-
- size = sizeof(Bucket)+(1<<pow);
- size += BY2V;
- size &= ~(BY2V-1);
-
- if(pow < CUTOFF) {
- n = (CUTOFF-pow)+2;
- bp = xalloc(size*n);
- if(bp == nil)
- return nil;
-
- ilock(&arena);
- arena.nbuck[pow] += n;
- l = &arena.btab[pow];
- /* add all but the last to the free list */
- while(--n){
- bp->size = pow;
- bp->next = *l;
- *l = bp;
- bp = (Bucket*)((ulong)bp+size);
- }
- iunlock(&arena);
+void
+free(void *v)
+{
+ Bhdr *b;
+
+ if(v != nil) {
+ D2B(b, v);
+ poolfree(mainmem, v);
}
- else {
- bp = xalloc(size);
- if(bp == nil)
- return nil;
+}
+
+void*
+realloc(void *v, ulong size)
+{
+ Bhdr *b;
+ void *nv;
+ int osize;
- arena.nbuck[pow]++;
+ if(v == nil)
+ return malloc(size);
+
+ D2B(b, v);
+
+ osize = b->size - BHDRSIZE;
+ if(osize >= size)
+ return v;
+
+ nv = poolalloc(mainmem, size);
+ if(nv != nil) {
+ memmove(nv, v, osize);
+ free(v);
}
+ return nv;
+}
- bp->size = pow;
- bp->magic = Magic2n;
+int
+msize(void *v)
+{
+ Bhdr *b;
- return bp->data;
+ D2B(b, v);
+ return b->size - BHDRSIZE;
}
void*
-malloc(ulong size)
+calloc(ulong n, ulong szelem)
{
- return mallocz(size, 1);
+ return malloc(n*szelem);
}
-void*
-smalloc(ulong size)
+/*
+void
+pooldump(Bhdr *b, int d, int c)
{
- char *s;
- void *p;
- int attempt;
-
- for(attempt = 0; attempt < 1000; attempt++) {
- p = malloc(size);
- if(p != nil)
- return p;
- s = up->psstate;
- up->psstate = "Malloc";
- qlock(&arena.rq);
- while(waserror())
- ;
- sleep(&arena.r, return0, nil);
- poperror();
- qunlock(&arena.rq);
- up->psstate = s;
+ Bhdr *t;
+
+ if(b == nil)
+ return;
+
+ print("%.8lux %.8lux %.8lux %c %4d %d (f %.8lux p %.8lux)\n",
+ b, b->left, b->right, c, d, b->size, b->fwd, b->prev);
+ d++;
+ for(t = b->fwd; t != b; t = t->fwd)
+ print("\t%.8lux %.8lux %.8lux\n", t, t->prev, t->fwd);
+ pooldump(b->left, d, 'l');
+ pooldump(b->right, d, 'r');
+}
+
+
+void
+poolshow(void)
+{
+ int i;
+
+ for(i = 0; i < table.n; i++) {
+ print("Arena: %s root=%.8lux\n", table.pool[i].name, table.pool[i].root);
+ pooldump(table.pool[i].root, 0, 'R');
}
- pexit(Enomem, 1);
- return 0;
}
+*/
-int
-msize(void *ptr)
+void
+poolsummary(void)
{
- Bucket *bp;
+ int i;
- bp = (Bucket*)((ulong)ptr - bdatoff);
- if(bp->magic != Magic2n)
- panic("msize");
- return 1<<bp->size;
+ for(i = 0; i < table.n; i++)
+ print("Arena: %s cursize=%d; maxsize=%d\n", table.pool[i].name, table.pool[i].cursize, table.pool[i].maxsize);
}
+/*
void
-free(void *ptr)
+pooldump(Pool *p)
{
- Bucket *bp, **l;
-
- bp = (Bucket*)((ulong)ptr - bdatoff);
- if(bp->magic != Magic2n)
- panic("free %lux %lux %lux", bp->magic, bp->pc, getcallerpc(ptr));
-
- bp->magic = 0;
- ilock(&arena);
- l = &arena.btab[bp->size];
- bp->next = *l;
- *l = bp;
- iunlock(&arena);
- if(arena.r.p)
- wakeup(&arena.r);
+ Bhdr *b, *base, *limit, *ptr;
+
+ b = p->chain;
+ if(b == nil)
+ return;
+ base = b;
+ ptr = b;
+ limit = B2LIMIT(b);
+
+ while(base != nil) {
+ print("\tbase #%.8lux ptr #%.8lux", base, ptr);
+ if(ptr->magic == MAGIC_A)
+ print("\tA%.5d\n", ptr->size);
+ else if(ptr->magic == MAGIC_E)
+ print("\tE\tL#%.8lux\tS#%.8lux\n", ptr->clink, ptr->csize);
+ else
+ print("\tF%.5d\tL#%.8lux\tR#%.8lux\tF#%.8lux\tP#%.8lux\tT#%.8lux\n",
+ ptr->size, ptr->left, ptr->right, ptr->fwd, ptr->prev, ptr->parent);
+ ptr = B2NB(ptr);
+ if(ptr >= limit) {
+ print("link to #%.8lux\n", base->clink);
+ base = base->clink;
+ if(base == nil)
+ break;
+ ptr = base;
+ limit = B2LIMIT(base);
+ }
+ }
+ return;
+}
+*/
+
+void
+poolsetcompact(Pool *p, void (*move)(void*, void*))
+{
+ p->move = move;
}
void
-xsummary(void)
+poolsetparam(char *name, ulong maxsize, int quanta, int chunk)
{
- Hole *h;
- Bucket *k;
- int i, nfree, nused;
-
- i = 0;
- for(h = xlists.flist; h; h = h->link)
- i++;
-
- print("%d holes free\n", i);
- i = 0;
- for(h = xlists.table; h; h = h->link) {
- print("%.8lux %.8lux %d\n", h->addr, h->top, h->size);
- i += h->size;
+ Pool *p;
+ int i;
+
+ for(i=0; i<table.n; i++){
+ p = &table.pool[i];
+ if(strcmp(name, p->name) == 0){
+ if(maxsize)
+ p->maxsize = maxsize;
+ if(quanta)
+ p->quanta = quanta;
+ if(chunk)
+ p->chunk = chunk;
+ return;
+ }
}
- print("%d bytes free\n", i);
- nused = 0;
- for(i = 3; i < Maxpow; i++) {
- if(arena.btab[i] == 0 && arena.nbuck[i] == 0)
- continue;
- nused += arena.nbuck[i]*(1<<i);
- nfree = 0;
- for(k = arena.btab[i]; k; k = k->next)
- nfree++;
- print("%8d %4d %4d\n", 1<<i, arena.nbuck[i], nfree);
+}
+
+int
+poolcompact(Pool *pool)
+{
+ Bhdr *base, *limit, *ptr, *end, *next;
+ int compacted, recov, nb;
+
+ if(pool->move == nil || pool->lastfree == pool->nfree)
+ return 0;
+
+ pool->lastfree = pool->nfree;
+
+ base = pool->chain;
+ ptr = B2NB(base); /* First Block in arena has clink */
+ limit = B2LIMIT(base);
+ compacted = 0;
+
+ pool->root = nil;
+ end = ptr;
+ recov = 0;
+ while(base != nil) {
+ next = B2NB(ptr);
+ if(ptr->magic == MAGIC_A) {
+ if(ptr != end) {
+ memmove(end, ptr, ptr->size);
+ pool->move(B2D(ptr), B2D(end));
+ recov = (uchar*)ptr - (uchar*)end;
+ compacted = 1;
+ }
+ end = B2NB(end);
+ }
+ if(next >= limit) {
+ nb = (uchar*)limit - (uchar*)end;
+ //print("recovered %d bytes\n", recov);
+ //print("%d bytes at end\n", nb);
+ USED(recov);
+ if(nb > 0){
+ if(nb < pool->quanta+1)
+ panic("poolcompact: leftover too small\n");
+ end->size = nb;
+ pooladd(pool, end);
+ }
+ base = base->clink;
+ if(base == nil)
+ break;
+ ptr = B2NB(base);
+ end = ptr; /* could do better by copying between chains */
+ limit = B2LIMIT(base);
+ recov = 0;
+ } else
+ ptr = next;
}
- print("%d bytes in pool\n", nused);
+
+ return compacted;
}
D port/devXXX.c => port/devXXX.c +0 -150
@@ 1,150 0,0 @@
-/*
- * template for making a new device
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-
-enum{
- Qdir,
- Qdata,
-};
-Dirtab XXXtab[]={
- "data", {Qdata, 0}, 0, 0600,
-};
-
-static void
-XXXreset(void) /* default in dev.c */
-{
-}
-
-static void
-XXXinit(void) /* default in dev.c */
-{
-}
-
-static Chan*
-XXXattach(char* spec)
-{
- return devattach('X', spec);
-}
-
-static Chan*
-XXXclone(Chan* c, Chan* nc) /* default in dev.c */
-{
- return devclone(c, nc);
-}
-
-static int
-XXXwalk(Chan* c, char* name)
-{
- return devwalk(c, name, XXXtab, nelem(XXXtab), devgen);
-}
-
-static void
-XXXstat(Chan* c, char* db)
-{
- devstat(c, db, XXXtab, nelem(XXXtab), devgen);
-}
-
-static Chan*
-XXXopen(Chan* c, int omode)
-{
- return devopen(c, omode, XXXtab, nelem(XXXtab), devgen);
-}
-
-static void
-XXXcreate(Chan* c, char* name, int omode, ulong perm) /* default in dev.c */
-{
- USED(c, name, omode, perm);
- error(Eperm);
-}
-
-static void
-XXXremove(Chan* c) /* default in dev.c */
-{
- USED(c);
- error(Eperm);
-}
-
-static void
-XXXwstat(Chan* c, char* dp) /* default in dev.c */
-{
- USED(c, dp);
- error(Eperm);
-}
-
-static void
-XXXclose(Chan* c)
-{
- USED(c);
-}
-
-static long
-XXXread(Chan* c, void* a, long n, ulong offset)
-{
- USED(offset);
-
- switch(c->qid.path & ~CHDIR){
- case Qdir:
- return devdirread(c, a, n, XXXtab, nelem(XXXtab), devgen);
- case Qdata:
- break;
- default:
- n=0;
- break;
- }
- return n;
-}
-
-static Block*
-XXXbread(Chan* c, long n, ulong offset) /* default in dev.c */
-{
- return devbread(c, n, offset);
-}
-
-static long
-XXXwrite(Chan* c, char* a, long n, ulong offset)
-{
- USED(a, offset);
-
- switch(c->qid.path & ~CHDIR){
- case Qdata:
- break;
- default:
- error(Ebadusefd);
- }
- return n;
-}
-
-static long
-XXXbwrite(Chan* c, Block* bp, ulong offset) /* default in dev.c */
-{
- return devbwrite(c, bp, offset);
-}
-
-Dev XXXdevtab = { /* defaults in dev.c */
- 'X',
- "XXX",
-
- XXXreset, /* devreset */
- XXXinit, /* devinit */
- XXXattach,
- XXXclone, /* devclone */
- XXXwalk,
- XXXstat,
- XXXopen,
- XXXcreate, /* devcreate */
- XXXclose,
- XXXread,
- XXXbread, /* devbread */
- XXXwrite,
- XXXbwrite, /* devbwrite */
- XXXremove, /* devremove */
- XXXwstat, /* devwstat */
-};
M port/devcons.c => port/devcons.c +2 -15
@@ 1,6 1,7 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
+#include "pool.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
@@ 149,21 150,6 @@ print(char *fmt, ...)
return n;
}
-int
-fprint(int, char *fmt, ...) /* needed so we can use user-level libg */
-{
- int n;
- va_list arg;
- char buf[PRINTSIZE];
-
- va_start(arg, fmt);
- n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
- va_end(arg);
- putstrn(buf, n);
-
- return n;
-}
-
void
panic(char *fmt, ...)
{
@@ 244,6 230,7 @@ echo(Rune r, char *buf, int n)
case 'x':
xsummary();
ixsummary();
+ poolsummary();
break;
case 'd':
if(consdebug != nil)
A port/devdraw.c => port/devdraw.c +1782 -0
@@ 0,0 1,1782 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "../port/error.h"
+
+#define Image IMAGE
+#include <draw.h>
+#include <memdraw.h>
+#include <memlayer.h>
+
+enum
+{
+ Qtopdir = 1,
+ Q2nd,
+ Qnew,
+ Q3rd,
+ Qcolormap,
+ Qctl,
+ Qdata,
+ Qrefresh,
+};
+
+/*
+ * Qid path is:
+ * 4 bits of file type (qids above)
+ * 24 bits of mux slot number +1; 0 means not attached to client
+ */
+#define QSHIFT 4 /* location in qid of client # */
+
+#define QID(q) (((q).path&0x0000000F)>>0)
+#define CLIENTPATH(q) ((q&0x07FFFFFF0)>>QSHIFT)
+#define CLIENT(q) CLIENTPATH((q).path)
+
+#define NHASH (1<<5)
+#define HASHMASK (NHASH-1)
+
+typedef struct Client Client;
+typedef struct Draw Draw;
+typedef struct DImage DImage;
+typedef struct DScreen DScreen;
+typedef struct CScreen CScreen;
+typedef struct FChar FChar;
+typedef struct Refresh Refresh;
+typedef struct Refx Refx;
+typedef struct DName DName;
+
+#define BLANKTIME 30*60*1000 /* half hour */
+
+struct Draw
+{
+ QLock;
+ int clientid;
+ int nclient;
+ Client** client;
+ int nname;
+ DName* name;
+ int vers;
+ int blanked; /* screen turned off */
+ ulong blanktime; /* time of last operation */
+ ulong savemap[3*256];
+};
+
+struct Client
+{
+ Ref r;
+ DImage* dimage[NHASH];
+ CScreen* cscreen;
+ Refresh* refresh;
+ Rendez refrend;
+ uchar* readdata;
+ int nreaddata;
+ int busy;
+ int clientid;
+ int slot;
+ int refreshme;
+ int infoid;
+};
+
+struct Refresh
+{
+ DImage* dimage;
+ Rectangle r;
+ Refresh* next;
+};
+
+struct Refx
+{
+ Client* client;
+ DImage* dimage;
+};
+
+struct DName
+{
+ char *name;
+ Client *client;
+ DImage* dimage;
+ int vers;
+};
+
+struct FChar
+{
+ int minx; /* left edge of bits */
+ int maxx; /* right edge of bits */
+ uchar miny; /* first non-zero scan-line */
+ uchar maxy; /* last non-zero scan-line + 1 */
+ schar left; /* offset of baseline */
+ uchar width; /* width of baseline */
+};
+
+/*
+ * Reference counts in DImages:
+ * one per open by original client
+ * one per screen image or fill
+ * Images published by name are not ref'ed, but protected by
+ * comparing version number with the DName entry.
+ */
+struct DImage
+{
+ int id;
+ int ref;
+ char *name;
+ int vers;
+ Memimage* image;
+ int ascent;
+ int nfchar;
+ FChar* fchar;
+ DScreen* dscreen; /* 0 if not a window */
+ DImage* next;
+};
+
+struct CScreen
+{
+ DScreen* dscreen;
+ CScreen* next;
+};
+
+struct DScreen
+{
+ int id;
+ int public;
+ int ref;
+ DImage *dimage;
+ DImage *dfill;
+ Memscreen* screen;
+ Client* owner;
+ DScreen* next;
+};
+
+static Draw sdraw;
+static Memimage screenimage;
+static Memdata screendata;
+static Rectangle flushrect;
+static DScreen* dscreen;
+extern void flushmemscreen(Rectangle);
+ void drawmesg(Client*, void*, int);
+ void drawuninstall(Client*, int);
+ void drawfreedimage(DImage*);
+
+static char Enodrawimage[] = "unknown id for draw image";
+static char Enodrawscreen[] = "unknown id for draw screen";
+static char Eshortdraw[] = "short draw message";
+static char Eshortread[] = "draw read too short";
+static char Eimageexists[] = "image id in use";
+static char Escreenexists[] = "screen id in use";
+static char Edrawmem[] = "image memory allocation failed";
+static char Ereadoutside[] = "readimage outside image";
+static char Ewriteoutside[] = "writeimage outside image";
+static char Enotfont[] = "image not a font";
+static char Eindex[] = "character index out of range";
+static char Enoclient[] = "no such draw client";
+static char Eldepth[] = "image has bad ldepth";
+static char Enameused[] = "image name in use";
+static char Enoname[] = "no image with that name";
+static char Eoldname[] = "named image no longer valid";
+static char Enamed[] = "image already has name";
+static char Ewrongname[] = "wrong name for image";
+
+static int
+drawgen(Chan *c, Dirtab *tab, int x, int s, Dir *dp)
+{
+ int t;
+ Qid q;
+ ulong path;
+ Client *cl;
+ char buf[NAMELEN];
+
+ USED(tab, x);
+ q.vers = 0;
+
+ /*
+ * Top level directory contains the name of the device.
+ */
+ if(c->qid.path == CHDIR){
+ switch(s){
+ case 0:
+ q = (Qid){CHDIR|Q2nd, 0};
+ devdir(c, q, "draw", 0, eve, 0555, dp);
+ break;
+ default:
+ return -1;
+ }
+ return 1;
+ }
+
+ /*
+ * Second level contains "new" plus all the clients.
+ */
+ t = QID(c->qid);
+ if(t == Q2nd || t == Qnew){
+ if(s == 0){
+ q = (Qid){Qnew, 0};
+ devdir(c, q, "new", 0, eve, 0666, dp);
+ }
+ else if(s <= sdraw.nclient){
+ cl = sdraw.client[s-1];
+ if(cl == 0)
+ return 0;
+ sprint(buf, "%d", cl->clientid);
+ q = (Qid){CHDIR|(s<<QSHIFT)|Q3rd, 0};
+ devdir(c, q, buf, 0, eve, 0555, dp);
+ return 1;
+ }
+ else
+ return -1;
+ return 1;
+ }
+
+ /*
+ * Third level.
+ */
+ path = c->qid.path&~(CHDIR|((1<<QSHIFT)-1)); /* slot component */
+ q.vers = c->qid.vers;
+ switch(s){
+ case 0:
+ q = (Qid){path|Qcolormap, c->qid.vers};
+ devdir(c, q, "colormap", 0, eve, 0600, dp);
+ break;
+ case 1:
+ q = (Qid){path|Qctl, c->qid.vers};
+ devdir(c, q, "ctl", 0, eve, 0600, dp);
+ break;
+ case 2:
+ q = (Qid){path|Qdata, c->qid.vers};
+ devdir(c, q, "data", 0, eve, 0600, dp);
+ break;
+ case 3:
+ q = (Qid){path|Qrefresh, c->qid.vers};
+ devdir(c, q, "refresh", 0, eve, 0400, dp);
+ break;
+ default:
+ return -1;
+ }
+ return 1;
+}
+
+static
+int
+drawrefactive(void *a)
+{
+ Client *c;
+
+ c = a;
+ return c->refreshme || c->refresh!=0;
+}
+
+static
+void
+drawrefresh(Memimage *l, Rectangle r, void *v)
+{
+ Refx *x;
+ DImage *d;
+ Client *c;
+ Refresh *ref;
+
+ USED(l);
+ if(v == 0)
+ return;
+ x = v;
+ c = x->client;
+ d = x->dimage;
+ for(ref=c->refresh; ref; ref=ref->next)
+ if(ref->dimage == d){
+ bbox(&ref->r, r);
+ return;
+ }
+ ref = malloc(sizeof(Refresh));
+ if(ref){
+ ref->dimage = d;
+ ref->r = r;
+ ref->next = c->refresh;
+ c->refresh = ref;
+ }
+}
+
+static
+void
+addflush(Rectangle r)
+{
+ bbox(&flushrect, r);
+}
+
+static
+void
+dstflush(int dstid, Memimage *dst, Rectangle r)
+{
+ if(dstid == 0){
+ bbox(&flushrect, r);
+ return;
+ }
+ if(dst->layer == nil)
+ return;
+ if(dst->layer->screen->image->data != screenimage.data)
+ return;
+ r = rectaddpt(r, dst->layer->delta);
+ bbox(&flushrect, r);
+}
+
+static
+void
+drawflush(void)
+{
+ flushmemscreen(flushrect);
+ flushrect = Rect(10000, 10000, -10000, -10000);
+}
+
+static
+int
+drawcmp(char *a, char *b, int n)
+{
+ if(strlen(a) != n)
+ return 1;
+ return memcmp(a, b, n);
+}
+
+DName*
+drawlookupname(int n, char *str)
+{
+ DName *name, *ename;
+
+ name = sdraw.name;
+ ename = &name[sdraw.nname];
+ for(; name<ename; name++)
+ if(drawcmp(name->name, str, n) == 0)
+ return name;
+ error(Enoname);
+ return 0;
+}
+
+int
+drawgoodname(DImage *d)
+{
+ DName *n;
+
+ if(d->name == nil)
+ return 1;
+ n = drawlookupname(strlen(d->name), d->name);
+ if(n==nil || n->vers!=d->vers)
+ return 0;
+ /* if window, validate the screen's own images */
+ if(d->dscreen == nil)
+ return 1;
+ if(drawgoodname(d->dscreen->dimage) && drawgoodname(d->dscreen->dfill))
+ return 1;
+ return 0;
+}
+
+DImage*
+drawlookup(Client *client, int id, int checkname)
+{
+ DImage *d;
+
+ d = client->dimage[id&HASHMASK];
+ while(d){
+ if(d->id == id){
+ if(checkname && !drawgoodname(d))
+ error("Eoldname");
+ return d;
+ }
+ d = d->next;
+ }
+ return 0;
+}
+
+DScreen*
+drawlookupdscreen(int id)
+{
+ DScreen *s;
+
+ s = dscreen;
+ while(s){
+ if(s->id == id)
+ return s;
+ s = s->next;
+ }
+ return 0;
+}
+
+DScreen*
+drawlookupscreen(Client *client, int id, CScreen **cs)
+{
+ CScreen *s;
+
+ s = client->cscreen;
+ while(s){
+ if(s->dscreen->id == id){
+ *cs = s;
+ return s->dscreen;
+ }
+ s = s->next;
+ }
+ error(Enodrawscreen);
+ return 0;
+}
+
+Memimage*
+drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
+{
+ DImage *d;
+
+ d = malloc(sizeof(DImage));
+ if(d == 0)
+ return 0;
+ d->id = id;
+ d->ref = 1;
+ d->name = 0;
+ d->image = i;
+ d->nfchar = 0;
+ d->fchar = 0;
+ d->dscreen = dscreen;
+ d->next = client->dimage[id&HASHMASK];
+ client->dimage[id&HASHMASK] = d;
+ return i;
+}
+
+Memscreen*
+drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *dfill, int public)
+{
+ Memscreen *s;
+ CScreen *c;
+
+ c = malloc(sizeof(CScreen));
+ if(c == 0)
+ return 0;
+ if(d == 0){
+ d = malloc(sizeof(DScreen));
+ if(d == 0){
+ free(c);
+ return 0;
+ }
+ s = malloc(sizeof(Memscreen));
+ if(s == 0){
+ free(c);
+ free(d);
+ return 0;
+ }
+ s->frontmost = 0;
+ s->rearmost = 0;
+ d->dimage = dimage;
+ if(dimage){
+ s->image = dimage->image;
+ dimage->ref++;
+ }
+ d->dfill = dfill;
+ if(dfill){
+ s->fill = dfill->image;
+ dfill->ref++;
+ }
+ d->ref = 0;
+ d->id = id;
+ d->screen = s;
+ d->public = public;
+ d->next = dscreen;
+ d->owner = client;
+ dscreen = d;
+ }
+ c->dscreen = d;
+ d->ref++;
+ c->next = client->cscreen;
+ client->cscreen = c;
+ return d->screen;
+}
+
+void
+drawdelname(DName *name)
+{
+ int i;
+
+ i = name-sdraw.name;
+ memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));
+ sdraw.nname--;
+}
+
+void
+drawfreedscreen(DScreen *this)
+{
+ DScreen *ds, *next;
+
+ this->ref--;
+ if(this->ref < 0)
+ print("negative ref in drawfreedscreen\n");
+ if(this->ref > 0)
+ return;
+ ds = dscreen;
+ if(ds == this){
+ dscreen = this->next;
+ goto Found;
+ }
+ while(next = ds->next){ /* assign = */
+ if(next == this){
+ ds->next = this->next;
+ goto Found;
+ }
+ ds = next;
+ }
+ error(Enodrawimage);
+
+ Found:
+ if(this->dimage)
+ drawfreedimage(this->dimage);
+ if(this->dfill)
+ drawfreedimage(this->dfill);
+ free(this->screen);
+ free(this);
+}
+
+void
+drawfreedimage(DImage *dimage)
+{
+ int i;
+ Memimage *l;
+ DScreen *ds;
+
+ dimage->ref--;
+ if(dimage->ref < 0)
+ print("negative ref in drawfreedimage\n");
+ if(dimage->ref > 0)
+ return;
+
+ /* any names? */
+ for(i=0; i<sdraw.nname; )
+ if(sdraw.name[i].dimage == dimage)
+ drawdelname(sdraw.name+i);
+ else
+ i++;
+ if(dimage->vers != 0) /* acquired by name; owned by someone else*/
+ goto Return;
+ if(dimage->image == &screenimage) /* don't free the display */
+ goto Return;
+ ds = dimage->dscreen;
+ if(ds){
+ l = dimage->image;
+ if(l->data == screenimage.data)
+ addflush(l->layer->screenr);
+ if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */
+ free(l->layer->refreshptr);
+ l->layer->refreshptr = nil;
+ if(drawgoodname(dimage))
+ memldelete(l);
+ else
+ memlfree(l);
+ drawfreedscreen(ds);
+ }else
+ freememimage(dimage->image);
+ Return:
+ free(dimage->fchar);
+ free(dimage);
+}
+
+void
+drawuninstallscreen(Client *client, CScreen *this)
+{
+ CScreen *cs, *next;
+
+ cs = client->cscreen;
+ if(cs == this){
+ client->cscreen = this->next;
+ drawfreedscreen(this->dscreen);
+ free(this);
+ return;
+ }
+ while(next = cs->next){ /* assign = */
+ if(next == this){
+ cs->next = this->next;
+ drawfreedscreen(this->dscreen);
+ free(this);
+ return;
+ }
+ cs = next;
+ }
+}
+
+void
+drawuninstall(Client *client, int id)
+{
+ DImage *d, *next;
+
+ /*
+ * If this image is a screen fill or image, don't drop it yet; save it
+ * in the DScreen and drawfreedscreen will ask again later.
+ */
+ d = client->dimage[id&HASHMASK];
+ if(d == 0)
+ error(Enodrawimage);
+ if(d->id == id){
+ client->dimage[id&HASHMASK] = d->next;
+ drawfreedimage(d);
+ return;
+ }
+ while(next = d->next){ /* assign = */
+ if(next->id == id){
+ d->next = next->next;
+ drawfreedimage(next);
+ return;
+ }
+ d = next;
+ }
+ error(Enodrawimage);
+}
+
+void
+drawaddname(Client *client, DImage *di, int n, char *str)
+{
+ DName *name, *ename, *new, *t;
+
+ name = sdraw.name;
+ ename = &name[sdraw.nname];
+ for(; name<ename; name++)
+ if(drawcmp(name->name, str, n) == 0)
+ error(Enameused);
+ t = smalloc((sdraw.nname+1)*sizeof(DName));
+ memmove(t, sdraw.name, sdraw.nname*sizeof(DName));
+ free(sdraw.name);
+ sdraw.name = t;
+ new = &sdraw.name[sdraw.nname++];
+ new->name = smalloc(n+1);
+ memmove(new->name, str, n);
+ new->name[n] = 0;
+ new->dimage = di;
+ new->client = client;
+ new->vers = ++sdraw.vers;
+}
+
+Client*
+drawnewclient(void)
+{
+ Client *cl, **cp;
+ int i;
+
+ for(i=0; i<sdraw.nclient; i++){
+ cl = sdraw.client[i];
+ if(cl == 0)
+ break;
+ }
+ if(i == sdraw.nclient){
+ cp = malloc((sdraw.nclient+1)*sizeof(Client*));
+ if(cp == 0)
+ return 0;
+ memmove(cp, sdraw.client, sdraw.nclient*sizeof(Client*));
+ free(sdraw.client);
+ sdraw.client = cp;
+ sdraw.nclient++;
+ cp[i] = 0;
+ }
+ cl = malloc(sizeof(Client));
+ if(cl == 0)
+ return 0;
+ memset(cl, 0, sizeof(Client));
+ cl->slot = i;
+ cl->clientid = ++sdraw.clientid;
+ sdraw.client[i] = cl;
+ return cl;
+}
+
+Client*
+drawclientofpath(ulong path)
+{
+ Client *cl;
+ int slot;
+
+ slot = CLIENTPATH(path);
+ if(slot == 0)
+ return nil;
+ cl = sdraw.client[slot-1];
+ if(cl==0 || cl->clientid==0)
+ return nil;
+ return cl;
+}
+
+
+Client*
+drawclient(Chan *c)
+{
+ Client *client;
+
+ client = drawclientofpath(c->qid.path);
+ if(client == nil)
+ error(Enoclient);
+ return client;
+}
+
+Memimage*
+drawimage(Client *client, uchar *a)
+{
+ DImage *d;
+
+ d = drawlookup(client, BGLONG(a), 1);
+ if(d == nil)
+ error(Enodrawimage);
+ return d->image;
+}
+
+void
+drawrectangle(Rectangle *r, uchar *a)
+{
+ r->min.x = BGLONG(a+0*4);
+ r->min.y = BGLONG(a+1*4);
+ r->max.x = BGLONG(a+2*4);
+ r->max.y = BGLONG(a+3*4);
+}
+
+void
+drawpoint(Point *p, uchar *a)
+{
+ p->x = BGLONG(a+0*4);
+ p->y = BGLONG(a+1*4);
+}
+
+Point
+drawchar(Memimage *dst, Point p, Memimage *src, Point *sp, DImage *font, int index)
+{
+ FChar *fc;
+ Rectangle r;
+ Point sp1;
+
+ fc = &font->fchar[index];
+ r.min.x = p.x+fc->left;
+ r.min.y = p.y-(font->ascent-fc->miny);
+ r.max.x = r.min.x+(fc->maxx-fc->minx);
+ r.max.y = r.min.y+(fc->maxy-fc->miny);
+ sp1.x = sp->x+fc->left;
+ sp1.y = sp->y+fc->miny;
+ memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny));
+ p.x += fc->width;
+ sp->x += fc->width;
+ return p;
+}
+
+Chan*
+drawattach(char *spec)
+{
+ int width;
+
+ if(screendata.data == nil){
+ screendata.base = nil;
+ screendata.data = attachscreen(&screenimage.r, &screenimage.ldepth, &width);
+ if(screendata.data != nil){
+ screendata.ref = 1;
+ screenimage.data = &screendata;
+ screenimage.width = width;
+ screenimage.clipr = screenimage.r;
+ }
+ }
+ return devattach('i', spec);
+}
+
+int
+drawwalk(Chan *c, char *name)
+{
+ if(screendata.data == nil)
+ error("no frame buffer");
+ if(strcmp(name, "..") == 0){
+ switch(QID(c->qid)){
+ case Qtopdir:
+ case Q2nd:
+ c->qid = (Qid){CHDIR|Qtopdir, 0};
+ break;
+ case Q3rd:
+ c->qid = (Qid){CHDIR|Q2nd, 0};
+ break;
+ default:
+ panic("drawwalk %lux", c->qid.path);
+ }
+ return 1;
+ }
+ return devwalk(c, name, 0, 0, drawgen);
+}
+
+static void
+drawstat(Chan *c, char *db)
+{
+ devstat(c, db, 0, 0, drawgen);
+}
+
+static Chan*
+drawopen(Chan *c, int omode)
+{
+ Client *cl;
+
+ if(c->qid.path & CHDIR)
+ return devopen(c, omode, 0, 0, drawgen);
+
+ qlock(&sdraw);
+ if(waserror()){
+ qunlock(&sdraw);
+ nexterror();
+ }
+
+ if(QID(c->qid) == Qnew){
+ cl = drawnewclient();
+ if(cl == 0)
+ error(Enodev);
+ c->qid.path = Qctl|((cl->slot+1)<<QSHIFT);
+ }
+
+ switch(QID(c->qid)){
+ case Qnew:
+ break;
+
+ case Qctl:
+ cl = drawclient(c);
+ if(cl->busy)
+ error(Einuse);
+ cl->busy = 1;
+ flushrect = Rect(10000, 10000, -10000, -10000);
+ drawinstall(cl, 0, &screenimage, 0);
+ incref(&cl->r);
+ break;
+ case Qcolormap:
+ case Qdata:
+ case Qrefresh:
+ cl = drawclient(c);
+ incref(&cl->r);
+ break;
+ }
+ qunlock(&sdraw);
+ poperror();
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+ return c;
+}
+
+static void
+drawclose(Chan *c)
+{
+ int i;
+ DImage *d, **dp;
+ Client *cl;
+ Refresh *r;
+
+ if(c->qid.path & CHDIR)
+ return;
+ qlock(&sdraw);
+ if(waserror()){
+ qunlock(&sdraw);
+ nexterror();
+ }
+
+ cl = drawclient(c);
+ if(QID(c->qid) == Qctl)
+ cl->busy = 0;
+ if((c->flag&COPEN) && (decref(&cl->r)==0)){
+ while(r = cl->refresh){ /* assign = */
+ cl->refresh = r->next;
+ free(r);
+ }
+ /* free names */
+ for(i=0; i<sdraw.nname; )
+ if(sdraw.name[i].client == cl)
+ drawdelname(sdraw.name+i);
+ else
+ i++;
+ while(cl->cscreen)
+ drawuninstallscreen(cl, cl->cscreen);
+ /* all screens are freed, so now we can free images */
+ dp = cl->dimage;
+ for(i=0; i<NHASH; i++){
+ while(d = *dp){ /* assign = */
+ *dp = d->next;
+ drawfreedimage(d);
+ }
+ dp++;
+ }
+ sdraw.client[cl->slot] = 0;
+ drawflush(); /* to erase visible, now dead windows */
+ free(cl);
+ }
+ qunlock(&sdraw);
+ poperror();
+}
+
+long
+drawread(Chan *c, void *a, long n, ulong offset)
+{
+ int index, m;
+ ulong red, green, blue;
+ Client *cl;
+ uchar *p;
+ Refresh *r;
+ DImage *di;
+ Memimage *i;
+
+ USED(offset);
+ if(c->qid.path & CHDIR)
+ return devdirread(c, a, n, 0, 0, drawgen);
+ cl = drawclient(c);
+ qlock(&sdraw);
+ if(waserror()){
+ qunlock(&sdraw);
+ nexterror();
+ }
+ switch(QID(c->qid)){
+ case Qctl:
+ if(n <= 12*12)
+ error(Eshortread);
+ if(cl->infoid < 0)
+ error(Enodrawimage);
+ if(cl->infoid == 0)
+ i = &screenimage;
+ else{
+ di = drawlookup(cl, cl->infoid, 1);
+ if(di == nil)
+ error(Enodrawimage);
+ i = di->image;
+ }
+ n = sprint(a, "%11d %11d %11d %11d %11d %11d %11d %11d %11d %11d %11d %11d ",
+ cl->clientid, cl->infoid, i->ldepth, i->repl,
+ i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y,
+ i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y);
+ cl->infoid = -1;
+ break;
+
+ case Qcolormap:
+ drawactive(1); /* to restore map from backup */
+ p = malloc(4*12*256);
+ if(p == 0)
+ error(Enomem);
+ m = 0;
+ for(index = 0; index < 256; index++){
+ getcolor(index, &red, &green, &blue);
+ m += sprint((char*)p+m, "%11d %11d %11d %11d\n", index, red>>24, green>>24, blue>>24);
+ }
+ n = readstr(offset, a, n, (char*)p);
+ free(p);
+ break;
+
+ case Qdata:
+ if(cl->readdata == nil)
+ error("no draw data");
+ if(n < cl->nreaddata)
+ error(Eshortread);
+ n = cl->nreaddata;
+ memmove(a, cl->readdata, cl->nreaddata);
+ free(cl->readdata);
+ cl->readdata = nil;
+ break;
+
+ case Qrefresh:
+ if(n < 5*4)
+ error(Ebadarg);
+ for(;;){
+ if(cl->refreshme || cl->refresh)
+ break;
+ qunlock(&sdraw);
+ sleep(&cl->refrend, drawrefactive, cl);
+ qlock(&sdraw);
+ }
+ p = a;
+ while(cl->refresh && n>=5*4){
+ r = cl->refresh;
+ BPLONG(p+0*4, r->dimage->id);
+ BPLONG(p+1*4, r->r.min.x);
+ BPLONG(p+2*4, r->r.min.y);
+ BPLONG(p+3*4, r->r.max.x);
+ BPLONG(p+4*4, r->r.max.y);
+ cl->refresh = r->next;
+ free(r);
+ p += 5*4;
+ n -= 5*4;
+ }
+ cl->refreshme = 0;
+ n = p-(uchar*)a;
+ }
+ qunlock(&sdraw);
+ poperror();
+ return n;
+}
+
+void
+drawwakeall(void)
+{
+ Client *cl;
+ int i;
+
+ for(i=0; i<sdraw.nclient; i++){
+ cl = sdraw.client[i];
+ if(cl && (cl->refreshme || cl->refresh))
+ wakeup(&cl->refrend);
+ }
+}
+
+static long
+drawwrite(Chan *c, void *a, long n, ulong offset)
+{
+ char buf[128], *fields[4], *q;
+ Client *cl;
+ int i, m, red, green, blue, x;
+
+ USED(offset);
+ if(c->qid.path & CHDIR)
+ error(Eisdir);
+ cl = drawclient(c);
+ qlock(&sdraw);
+ if(waserror()){
+ drawwakeall();
+ qunlock(&sdraw);
+ nexterror();
+ }
+ switch(QID(c->qid)){
+ case Qctl:
+ if(n != 4)
+ error("unknown draw control request");
+ cl->infoid = BGLONG((uchar*)a);
+ break;
+
+ case Qcolormap:
+ drawactive(1); /* to restore map from backup */
+ m = n;
+ n = 0;
+ while(m > 0){
+ x = m;
+ if(x > sizeof(buf)-1)
+ x = sizeof(buf)-1;
+ q = memccpy(buf, a, '\n', x);
+ if(q == 0)
+ break;
+ i = q-buf;
+ n += i;
+ a = (char*)a + i;
+ m -= i;
+ *q = 0;
+ if(parsefields(buf, fields, nelem(fields), " ") != 4)
+ error(Ebadarg);
+ i = strtoul(fields[0], 0, 0);
+ red = strtoul(fields[1], 0, 0);
+ green = strtoul(fields[2], 0, 0);
+ blue = strtoul(fields[3], &q, 0);
+ if(fields[3] == q)
+ error(Ebadarg);
+ if(red>255 || green>255 || blue>255 || i<0 || i>255)
+ error(Ebadarg);
+ red |= red<<8;
+ red |= red<<16;
+ green |= green<<8;
+ green |= green<<16;
+ blue |= blue<<8;
+ blue |= blue<<16;
+ setcolor(i, red, green, blue);
+ }
+ break;
+
+ case Qdata:
+ drawmesg(cl, a, n);
+ drawwakeall();
+ break;
+
+ default:
+ error(Ebadusefd);
+ }
+ qunlock(&sdraw);
+ poperror();
+ return n;
+}
+
+uchar*
+drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
+{
+ int b, x;
+
+ if(p >= maxp)
+ error(Eshortdraw);
+ b = *p++;
+ x = b & 0x7F;
+ if(b & 0x80){
+ if(p+1 >= maxp)
+ error(Eshortdraw);
+ x |= *p++ << 7;
+ x |= *p++ << 15;
+ if(x & (1<<22))
+ x |= ~0<<23;
+ }else{
+ if(b & 0x40)
+ x |= ~0<<7;
+ x += oldx;
+ }
+ *newx = x;
+ return p;
+}
+
+void
+drawmesg(Client *client, void *av, int n)
+{
+ int c, ldepth, repl, m, y, dstid, scrnid, ni, ci, j, nw, e0, e1, ox, oy, esize, doflush;
+ uchar *u, *a;
+ Rectangle r, clipr;
+ Point p, q, *pp, sp;
+ Memimage *i, *dst, *src, *mask;
+ Memimage *l, **lp;
+ Memscreen *scrn;
+ DImage *font, *ll, *di, *ddst, *dsrc;
+ DName *dn;
+ DScreen *dscrn;
+ FChar *fc;
+ Refx *refx;
+ CScreen *cs;
+ Refreshfn reffn;
+
+ a = av;
+ m = 0;
+ while((n-=m) > 0){
+ a += m;
+ switch(*a){
+ default:
+ error("bad draw command");
+ /* allocate: 'a' id[4] screenid[4] refresh[1] ldepth[2] repl[1] R[4*4] clipR[4*4] value[1] */
+ case 'a':
+ m = 1+4+4+1+2+1+4*4+4*4+1;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ if(drawlookup(client, dstid, 0))
+ error(Eimageexists);
+ ldepth = BGSHORT(a+10);
+ repl = a[12];
+ drawrectangle(&r, a+13);
+ scrnid = BGSHORT(a+5);
+ if(scrnid){
+ dscrn = drawlookupscreen(client, scrnid, &cs);
+ scrn = dscrn->screen;
+ if(repl || ldepth!=scrn->image->ldepth)
+ error("image parameters incompatible with screen");
+ reffn = nil;
+ switch(a[9]){
+ case Refbackup:
+ break;
+ case Refnone:
+ reffn = memlnorefresh;
+ break;
+ case Refmesg:
+ reffn = drawrefresh;
+ break;
+ default:
+ error("unknown refresh method");
+ }
+ l = memlalloc(scrn, r, reffn, 0, a[45]);
+ if(l == 0)
+ error(Edrawmem);
+ addflush(l->layer->screenr);
+ drawrectangle(&l->clipr, a+29);
+ rectclip(&l->clipr, r);
+ if(drawinstall(client, dstid, l, dscrn) == 0){
+ memldelete(l);
+ error(Edrawmem);
+ }
+ dscrn->ref++;
+ if(reffn){
+ refx = nil;
+ if(reffn == drawrefresh){
+ refx = malloc(sizeof(Refx));
+ if(refx == 0){
+ drawuninstall(client, dstid);
+ error(Edrawmem);
+ }
+ refx->client = client;
+ refx->dimage = drawlookup(client, dstid, 1);
+ }
+ memlsetrefresh(l, reffn, refx);
+ }
+ continue;
+ }
+ i = allocmemimage(r, ldepth);
+ if(i == 0)
+ error(Edrawmem);
+ i->repl = repl;
+ drawrectangle(&i->clipr, a+29);
+ if(!repl)
+ rectclip(&i->clipr, r);
+ if(drawinstall(client, dstid, i, 0) == 0){
+ freememimage(i);
+ error(Edrawmem);
+ }
+ memfillcolor(i, a[45]);
+ continue;
+
+ /* allocate screen: 'A' id[4] imageid[4] fillid[4] public[1] */
+ case 'A':
+ m = 1+4+4+4+1;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ if(dstid == 0)
+ error(Ebadarg);
+ if(drawlookupdscreen(dstid))
+ error(Escreenexists);
+ ddst = drawlookup(client, BGLONG(a+5), 1);
+ dsrc = drawlookup(client, BGLONG(a+9), 1);
+ if(ddst==0 || dsrc==0)
+ error(Enodrawimage);
+ if(drawinstallscreen(client, 0, dstid, ddst, dsrc, a[13]) == 0)
+ error(Edrawmem);
+ continue;
+
+ /* set repl and clip: 'c' dstid[4] repl[1] clipR[4*4] */
+ case 'c':
+ m = 1+4+1+4*4;
+ if(n < m)
+ error(Eshortdraw);
+ ddst = drawlookup(client, BGLONG(a+1), 1);
+ if(ddst == nil)
+ error(Enodrawimage);
+ if(ddst->name)
+ error("can't change repl/clipr of shared image");
+ dst = ddst->image;
+ dst->repl = a[5];
+ drawrectangle(&dst->clipr, a+6);
+ continue;
+
+ /* draw: 'd' dstid[4] srcid[4] maskid[4] R[4*4] P[2*4] P[2*4] */
+ case 'd':
+ m = 1+4+4+4+4*4+2*4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+ dst = drawimage(client, a+1);
+ dstid = BGLONG(a+1);
+ src = drawimage(client, a+5);
+ mask = drawimage(client, a+9);
+ drawrectangle(&r, a+13);
+ drawpoint(&p, a+29);
+ drawpoint(&q, a+37);
+ memdraw(dst, r, src, p, mask, q);
+ dstflush(dstid, dst, r);
+ continue;
+
+ /* ellipse: 'e' dstid[4] srcid[4] center[2*4] a[4] b[4] thick[4] sp[2*4] alpha[4] phi[4]*/
+ case 'e':
+ case 'E':
+ m = 1+4+4+2*4+4+4+4+2*4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+ dst = drawimage(client, a+1);
+ dstid = BGLONG(a+1);
+ src = drawimage(client, a+5);
+ drawpoint(&p, a+9);
+ e0 = BGLONG(a+17);
+ e1 = BGLONG(a+21);
+ if(e0<0 || e1<0)
+ error("invalid ellipse semidiameter");
+ j = BGLONG(a+25);
+ if(j < 0)
+ error("negative ellipse thickness");
+ drawpoint(&sp, a+29);
+ c = j;
+ if(*a == 'E')
+ c = -1;
+ ox = BGLONG(a+37);
+ oy = BGLONG(a+41);
+ /* high bit indicates arc angles are present */
+ if(ox & (1<<31)){
+ if((ox & (1<<30)) == 0)
+ ox &= ~(1<<31);
+ memarc(dst, p, e0, e1, c, src, sp, ox, oy);
+ }else
+ memellipse(dst, p, e0, e1, c, src, sp);
+ dstflush(dstid, dst, Rect(p.x-e0-j, p.y-e1-j, p.x+e0+j+1, p.y+e1+j+1));
+ continue;
+
+ /* free: 'f' id[4] */
+ case 'f':
+ m = 1+4;
+ if(n < m)
+ error(Eshortdraw);
+ ll = drawlookup(client, BGLONG(a+1), 0);
+ if(ll && ll->dscreen && ll->dscreen->owner != client)
+ ll->dscreen->owner->refreshme = 1;
+ drawuninstall(client, BGLONG(a+1));
+ continue;
+
+ /* free screen: 'F' id[4] */
+ case 'F':
+ m = 1+4;
+ if(n < m)
+ error(Eshortdraw);
+ drawlookupscreen(client, BGLONG(a+1), &cs);
+ drawuninstallscreen(client, cs);
+ continue;
+
+ /* initialize font: 'i' fontid[4] nchars[4] ascent[1] */
+ case 'i':
+ m = 1+4+4+1;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ if(dstid == 0)
+ error("can't use display as font");
+ font = drawlookup(client, dstid, 1);
+ if(font == 0)
+ error(Enodrawimage);
+ if(font->image->layer)
+ error("can't use window as font");
+ free(font->fchar); /* should we complain if non-zero? */
+ ni = BGLONG(a+5);
+ font->fchar = malloc(ni*sizeof(FChar));
+ if(font->fchar == 0)
+ error("no memory for font");
+ memset(font->fchar, 0, ni*sizeof(FChar));
+ font->nfchar = ni;
+ font->ascent = a[9];
+ continue;
+
+ /* load character: 'l' fontid[4] srcid[4] index[2] R[4*4] P[2*4] left[1] width[1] */
+ case 'l':
+ m = 1+4+4+2+4*4+2*4+1+1;
+ if(n < m)
+ error(Eshortdraw);
+ font = drawlookup(client, BGLONG(a+1), 1);
+ if(font == 0)
+ error(Enodrawimage);
+ if(font->nfchar == 0)
+ error(Enotfont);
+ src = drawimage(client, a+5);
+ ci = BGSHORT(a+9);
+ if(ci >= font->nfchar)
+ error(Eindex);
+ drawrectangle(&r, a+11);
+ drawpoint(&p, a+27);
+ memdraw(font->image, r, src, p, memones, p);
+ fc = &font->fchar[ci];
+ fc->minx = r.min.x;
+ fc->maxx = r.max.x;
+ fc->miny = r.min.y;
+ fc->maxy = r.max.y;
+ fc->left = a[35];
+ fc->width = a[36];
+ continue;
+
+ /* draw line: 'L' dstid[4] p0[2*4] p1[2*4] end0[4] end1[4] radius[4] srcid[4] sp[2*4] */
+ case 'L':
+ m = 1+4+2*4+2*4+4+4+4+4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+ dst = drawimage(client, a+1);
+ dstid = BGLONG(a+1);
+ drawpoint(&p, a+5);
+ drawpoint(&q, a+13);
+ e0 = BGLONG(a+21);
+ e1 = BGLONG(a+25);
+ j = BGLONG(a+29);
+ if(j < 0)
+ error("negative line width");
+ src = drawimage(client, a+33);
+ drawpoint(&sp, a+37);
+ memline(dst, p, q, e0, e1, j, src, sp);
+ /* avoid memlinebbox if possible */
+ if(dstid==0 || dst->layer!=nil){
+ /* BUG: this is terribly inefficient: update maximal containing rect*/
+ r = memlinebbox(p, q, e0, e1, j);
+ dstflush(dstid, dst, insetrect(r, -(1+1+j)));
+ }
+ continue;
+
+ /* attach to a named image: 'n' dstid[4] j[1] name[j] */
+ case 'n':
+ m = 1+4+1;
+ if(n < m)
+ error(Eshortdraw);
+ j = a[5];
+ if(j == 0) /* give me a non-empty name please */
+ error(Eshortdraw);
+ m += j;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ if(drawlookup(client, dstid, 0))
+ error(Eimageexists);
+ dn = drawlookupname(j, (char*)a+6);
+ if(drawinstall(client, dstid, dn->dimage->image, 0) == 0)
+ error(Edrawmem);
+ di = drawlookup(client, dstid, 0);
+ if(di == 0)
+ error("draw: can't happen");
+ di->vers = dn->vers;
+ di->name = smalloc(j+1);
+ memmove(di->name, a+6, j);
+ di->name[j] = 0;
+ client->infoid = dstid;
+ continue;
+
+ /* name an image: 'N' dstid[4] in[1] j[1] name[j] */
+ case 'N':
+ m = 1+4+1+1;
+ if(n < m)
+ error(Eshortdraw);
+ c = a[5];
+ j = a[6];
+ if(j == 0) /* give me a non-empty name please */
+ error(Eshortdraw);
+ m += j;
+ if(n < m)
+ error(Eshortdraw);
+ di = drawlookup(client, BGLONG(a+1), 0);
+ if(di == 0)
+ error(Enodrawimage);
+ if(di->name)
+ error(Enamed);
+ if(c)
+ drawaddname(client, di, j, (char*)a+7);
+ else{
+ dn = drawlookupname(j, (char*)a+7);
+ if(dn->dimage != di)
+ error(Ewrongname);
+ drawdelname(dn);
+ }
+ continue;
+
+ /* position window: 'o' id[4] r.min [2*4] screenr.min [2*4] */
+ case 'o':
+ m = 1+4+2*4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+ dst = drawimage(client, a+1);
+ if(dst->layer){
+ drawpoint(&p, a+5);
+ drawpoint(&q, a+13);
+ r = dst->layer->screenr;
+ ni = memlorigin(dst, p, q);
+ if(ni < 0)
+ error("image origin failed");
+ if(ni > 0){
+ addflush(r);
+ addflush(dst->layer->screenr);
+ ll = drawlookup(client, BGLONG(a+1), 1);
+ if(ll->dscreen->owner != client)
+ ll->dscreen->owner->refreshme = 1;
+ }
+ }
+ continue;
+
+ /* filled polygon: 'P' dstid[4] n[2] wind[4] ignore[2*4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */
+ /* polygon: 'p' dstid[4] n[2] end0[4] end1[4] radius[4] srcid[4] sp[2*4] p0[2*4] dp[2*2*n] */
+ case 'p':
+ case 'P':
+ m = 1+4+2+4+4+4+4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ dst = drawimage(client, a+1);
+ ni = BGSHORT(a+5);
+ if(ni < 0)
+ error("negative count in polygon");
+ e0 = BGLONG(a+7);
+ e1 = BGLONG(a+11);
+ j = 0;
+ if(*a == 'p'){
+ j = BGLONG(a+15);
+ if(j < 0)
+ error("negative polygon line width");
+ }
+ src = drawimage(client, a+19);
+ drawpoint(&sp, a+23);
+ drawpoint(&p, a+31);
+ ni++;
+ pp = malloc(ni*sizeof(Point));
+ if(pp == nil)
+ error(Enomem);
+ doflush = 0;
+ if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage.data))
+ doflush = 1; /* simplify test in loop */
+ ox = oy = 0;
+ u = a+m;
+ for(y=0; y<ni; y++){
+ u = drawcoord(u, a+n, ox, &p.x);
+ u = drawcoord(u, a+n, oy, &p.y);
+ ox = p.x;
+ oy = p.y;
+ if(doflush){
+ esize = j;
+ if(*a == 'p'){
+ if(y == 0){
+ c = memlineendsize(e0);
+ if(c > esize)
+ esize = c;
+ }
+ if(y == ni-1){
+ c = memlineendsize(e1);
+ if(c > esize)
+ esize = c;
+ }
+ }
+ if(*a=='P' && e0!=1 && e0 !=~0)
+ r = dst->clipr;
+ else
+ r = Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1);
+ dstflush(dstid, dst, r);
+ }
+ pp[y] = p;
+ }
+ if(*a == 'p')
+ mempoly(dst, pp, ni, e0, e1, j, src, sp);
+ else
+ memfillpoly(dst, pp, ni, e0, src, sp);
+ free(pp);
+ m = u-a;
+ continue;
+
+ /* read: 'r' id[4] R[4*4] */
+ case 'r':
+ m = 1+4+4*4;
+ if(n < m)
+ error(Eshortdraw);
+ i = drawimage(client, a+1);
+ if(i->layer)
+ error("readimage from window unimplemented");
+ drawrectangle(&r, a+5);
+ if(!rectinrect(r, i->r))
+ error(Ereadoutside);
+ free(client->readdata);
+ c = bytesperline(r, i->ldepth);
+ c *= Dy(r);
+ client->readdata = mallocz(c, 0);
+ if(client->readdata == nil)
+ error("readimage malloc failed");
+ client->nreaddata = unloadmemimage(i, r, client->readdata, c);
+ if(client->nreaddata < 0){
+ free(client->readdata);
+ client->readdata = nil;
+ error("bad readimage call");
+ }
+ continue;
+
+ /* string: 's' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] ni*(index[2]) */
+ /* stringbg: 'x' dstid[4] srcid[4] fontid[4] P[2*4] clipr[4*4] sp[2*4] ni[2] bgid[4] bgpt[2*4] ni*(index[2]) */
+ case 's':
+ case 'x':
+ m = 1+4+4+4+2*4+4*4+2*4+2;
+ if(*a == 'x')
+ m += 4+2*4;
+ if(n < m)
+ error(Eshortdraw);
+
+ CaseS:
+ dst = drawimage(client, a+1);
+ dstid = BGLONG(a+1);
+ src = drawimage(client, a+5);
+ font = drawlookup(client, BGLONG(a+9), 1);
+ if(font == 0)
+ error(Enodrawimage);
+ if(font->nfchar == 0)
+ error(Enotfont);
+ drawpoint(&p, a+13);
+ drawrectangle(&r, a+21);
+ drawpoint(&sp, a+37);
+ ni = BGSHORT(a+45);
+ u = a+m;
+ m += ni*2;
+ if(n < m)
+ error(Eshortdraw);
+ clipr = dst->clipr;
+ dst->clipr = r;
+ if(*a == 'x'){
+ /* paint background */
+ l = drawimage(client, a+47);
+ drawpoint(&q, a+51);
+ r.min.x = p.x;
+ r.min.y = p.y-font->ascent;
+ r.max.x = p.x;
+ r.max.y = r.min.y+Dy(font->image->r);
+ j = ni;
+ while(--j >= 0){
+ ci = BGSHORT(u);
+ if(ci<0 || ci>=font->nfchar){
+ dst->clipr = clipr;
+ error(Eindex);
+ }
+ r.max.x += font->fchar[ci].width;
+ u += 2;
+ }
+ memdraw(dst, r, l, q, memones, ZP);
+ u -= 2*ni;
+ }
+ q = p;
+ while(--ni >= 0){
+ ci = BGSHORT(u);
+ if(ci<0 || ci>=font->nfchar){
+ dst->clipr = clipr;
+ error(Eindex);
+ }
+ q = drawchar(dst, q, src, &sp, font, ci);
+ u += 2;
+ }
+ dst->clipr = clipr;
+ p.y -= font->ascent;
+ dstflush(dstid, dst, Rect(p.x, p.y, q.x, p.y+Dy(font->image->r)));
+ continue;
+
+ /* use public screen: 'S' id[4] ldepth[4] */
+ case 'S':
+ m = 1+4+4;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ if(dstid == 0)
+ error(Ebadarg);
+ dscrn = drawlookupdscreen(dstid);
+ if(dscrn==0 || (dscrn->public==0 && dscrn->owner!=client))
+ error(Enodrawscreen);
+ if(dscrn->screen->image->ldepth != BGLONG(a+5))
+ error("inconsistent ldepth");
+ if(drawinstallscreen(client, dscrn, 0, 0, 0, 0) == 0)
+ error(Edrawmem);
+ continue;
+
+ /* top or bottom windows: 't' top[1] nw[2] n*id[4] */
+ case 't':
+ m = 1+1+2;
+ if(n < m)
+ error(Eshortdraw);
+ nw = BGSHORT(a+2);
+ if(nw < 0)
+ error(Ebadarg);
+ if(nw == 0)
+ continue;
+ m += nw*4;
+ if(n < m)
+ error(Eshortdraw);
+ lp = malloc(nw*sizeof(Memimage*));
+ if(lp == 0)
+ error(Enomem);
+ if(waserror()){
+ free(lp);
+ nexterror();
+ }
+ for(j=0; j<nw; j++)
+ lp[j] = drawimage(client, a+1+1+2+j*4);
+ if(lp[0]->layer == 0)
+ error("images are not windows");
+ for(j=1; j<nw; j++)
+ if(lp[j]->layer->screen != lp[0]->layer->screen)
+ error("images not on same screen");
+ if(a[1])
+ memltofrontn(lp, nw);
+ else
+ memltorearn(lp, nw);
+ if(lp[0]->layer->screen->image->data == screenimage.data)
+ for(j=0; j<nw; j++)
+ addflush(lp[j]->layer->screenr);
+ ll = drawlookup(client, BGLONG(a+1+1+2), 1);
+ if(ll->dscreen->owner != client)
+ ll->dscreen->owner->refreshme = 1;
+ poperror();
+ free(lp);
+ continue;
+
+ /* visible: 'v' */
+ case 'v':
+ m = 1;
+ drawflush();
+ continue;
+
+ /* write: 'w' id[4] R[4*4] data[x*1] */
+ /* write from compressed data: 'W' id[4] R[4*4] data[x*1] */
+ case 'w':
+ case 'W':
+ m = 1+4+4*4;
+ if(n < m)
+ error(Eshortdraw);
+ dstid = BGLONG(a+1);
+ dst = drawimage(client, a+1);
+ drawrectangle(&r, a+5);
+ if(!rectinrect(r, dst->r))
+ error(Ewriteoutside);
+ y = memload(dst, r, a+m, n-m, *a=='W');
+ if(y < 0)
+ error("bad writeimage call");
+ dstflush(dstid, dst, r);
+ m += y;
+ continue;
+ }
+ }
+}
+
+Dev drawdevtab = {
+ 'i',
+ "draw",
+
+ devreset,
+ devinit,
+ drawattach,
+ devclone,
+ drawwalk,
+ drawstat,
+ drawopen,
+ devcreate,
+ drawclose,
+ drawread,
+ devbread,
+ drawwrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
+
+/*
+ * On 8 bit displays, load the default color map
+ */
+void
+drawcmap(invert){
+ int r, g, b, cr, cg, cb, v;
+ int num, den;
+ int i, j;
+ drawactive(1); /* to restore map from backup */
+ for(r=0,i=0;r!=4;r++) for(v=0;v!=4;v++,i+=16){
+ for(g=0,j=v-r;g!=4;g++) for(b=0;b!=4;b++,j++){
+ den=r;
+ if(g>den) den=g;
+ if(b>den) den=b;
+ if(den==0) /* divide check -- pick grey shades */
+ cr=cg=cb=v*17;
+ else{
+ num=17*(4*den+v);
+ cr=r*num/den;
+ cg=g*num/den;
+ cb=b*num/den;
+ }
+ if(invert)
+ setcolor(255-i-(j&15),
+ cr*0x01010101, cg*0x01010101, cb*0x01010101);
+ else
+ setcolor(i+(j&15),
+ cr*0x01010101, cg*0x01010101, cb*0x01010101);
+ }
+ }
+}
+
+void
+drawblankscreen(int blank)
+{
+ int i, nc;
+ ulong *p;
+
+ if(blank == sdraw.blanked)
+ return;
+ p = sdraw.savemap;
+ nc = 1<<(1<<screenimage.ldepth);
+ if(blank == 0) /* turn screen on */
+ for(i=0; i<nc; i++, p+=3)
+ setcolor(i, p[0], p[1], p[2]);
+ else /* turn screen off */
+ for(i=0; i<nc; i++, p+=3){
+ getcolor(i, &p[0], &p[1], &p[2]);
+ setcolor(i, 0, 0, 0);
+ }
+ sdraw.blanked = blank;
+}
+
+/*
+ * record activity on screen, changing blanking as appropriate
+ */
+void
+drawactive(int active)
+{
+ if(active){
+ drawblankscreen(0);
+ sdraw.blanktime = 0;
+ }else {
+ if(TK2MS(sdraw.blanktime) > BLANKTIME)
+ drawblankscreen(1);
+ else
+ sdraw.blanktime++;
+ }
+}
D port/devlance.c => port/devlance.c +0 -567
@@ 1,567 0,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-#include "../port/netif.h"
-
-enum {
- Ntypes= 9, /* max number of ethernet packet types */
- Maxrb= 128, /* max buffers in a ring */
-};
-#define RSUCC(x) (((x)+1)%l.nrrb)
-#define TSUCC(x) (((x)+1)%l.ntrb)
-
-/*
- * Communication with the lance is via a transmit and receive ring of
- * message descriptors. The Initblock contains pointers to and sizes of
- * these rings. The rings must be in RAM addressible by the lance
- */
-typedef struct {
- ushort laddr; /* low order piece of address */
- ushort flags; /* flags and high order piece of address */
- short size; /* size of buffer */
- ushort cntflags; /* (rcv)count of buffer; (xmt) more flags */
-} Msg;
-
-/*
- * lance memory map
- */
-struct Lancemem
-{
- /*
- * initialization block
- */
- ushort mode; /* chip control (see below) */
- ushort etheraddr[3]; /* the ethernet physical address */
- ushort multi[4]; /* multicast addresses, 1 bit for each of 64 */
- ushort rdralow; /* receive buffer ring */
- ushort rdrahigh; /* (top three bits define size of ring) */
- ushort tdralow; /* transmit buffer ring */
- ushort tdrahigh; /* (top three bits define size of ring) */
-
- /*
- * ring buffers
- * first receive, then transmit
- */
- Msg rmr[Maxrb]; /* recieve message ring */
- Msg tmr[Maxrb]; /* transmit message ring */
-};
-
-/*
- * Some macros for dealing with lance memory addresses. The lance splits
- * its 24 bit addresses across two 16 bit registers.
- */
-#define HADDR(a) ((((ulong)(a))>>16)&0xFF)
-#define LADDR(a) (((ulong)a)&0xFFFF)
-
-/*
- * The following functions exist to sidestep a quirk in the SGI IO3 lance
- * interface. In all other processors, the lance's initialization block and
- * descriptor rings look like normal memory. In the SGI IO3, the CPU sees a
- * 6 byte pad twixt all lance memory shorts. Therefore, we use the following
- * macros to compute the address whenever accessing the lance memory to make
- * the code portable. Sic transit gloria.
- */
-#define LANCEMEM ((Lancemem*)0)
-#define MPs(a) (*(short *)(l.lanceram + l.sep*((ushort*)&a - (ushort*)0)))
-#define MPus(a) (*(ushort *)(l.lanceram + l.sep*((ushort*)&a - (ushort*)0)))
-
-enum
-{
- PROM = 0x8000,
- INTL = 0x40,
- DRTY = 0x20,
- COLL = 0x10,
- DTCR = 0x8,
- LOOP = 0x4,
- DTX = 0x2,
- DRX = 0x1,
- ERR0 = 0x8000,
- BABL = 0x4000,
- CERR = 0x2000,
- MISS = 0x1000,
- MERR = 0x800,
- RINT = 0x400,
- TINT = 0x200,
- IDON = 0x100,
- INTR = 0x80,
- INEA = 0x40,
- RXON = 0x20,
- TXON = 0x10,
- TDMD = 0x8,
- STOP = 0x4,
- STRT = 0x2,
- INIT = 0x1,
- /* flag bits from a buffer descriptor in the rcv/xmt rings */
- LANCEOWNER= 0x8000, /* 1 means buffer can be used by the chip */
- ERR = 0x4000, /* error summary, the OR of all error bits */
- FRAM = 0x2000, /* CRC error */
- OFLO = 0x1000, /* (receive) lost some of the packet */
- MORE = 0x1000, /* (transmit) more than 1 retry to tx pkt */
- CRC = 0x800, /* (rcv) crc error reading packet */
- ONE = 0x800, /* (tx) one retry to transmit the packet */
- BUF = 0x400, /* (rcv) out of buffers */
- DEF = 0x400, /* (tx) deffered while transmitting packet */
- STP = 0x200, /* start of packet */
- ENP = 0x100, /* end of packet */
- /* cntflags bits from a buffer descriptor in the rcv/xmt rings */
- BUFF = 0x8000, /* buffer error (host screwed up?) */
- UFLO = 0x4000, /* underflow from memory */
- LCOL = 0x1000, /* late collision (ether too long?) */
- LCAR = 0x800, /* loss of carrier (ether broken?) */
- RTRY = 0x400, /* couldn't transmit (ether jammed?) */
- TTDR = 0x3FF, /* time domain reflectometer */
-};
-
-struct Softlance
-{
- Lance; /* host dependent lance params */
-
- uchar bcast[6];
-
- int wedged; /* the lance is wedged */
-
- ushort rl; /* first rcv Message belonging to Lance */
- ushort tc; /* next xmt Message CPU will try for */
-
- QLock tlock; /* lock for grabbing transmitter queue */
- Rendez tr; /* wait here for free xmit buffer */
-
- Netif;
-} l;
-
-static void promiscuous(void*, int);
-
-static void
-lancereset(void)
-{
- static int inited;
-
- if(inited == 0){
- inited = 1;
- lancesetup(&l);
-
- /* general network interface structure */
- netifinit(&l, "ether0", Ntypes, 32*1024);
- l.alen = 6;
- memmove(l.addr, l.ea, Eaddrlen);
- memset(l.bcast, 0xFF, Eaddrlen);
-
- l.promiscuous = promiscuous;
- l.arg = &l;
- }
-
- /*
- * stop the lance
- */
- *l.rap = 0;
- *l.rdp = STOP;
- l.wedged = 1;
-}
-
-/*
- * Initialize and start the lance.
- * This routine can be called only from a process.
- * It may be used to restart a dead lance.
- */
-static void
-lancestart(int mode)
-{
- int i;
- Msg *m;
- Lancemem *lm = LANCEMEM;
-
- /*
- * wait till both receiver and transmitter are
- * quiescent
- */
- qlock(&l.tlock);
-
- lancereset();
- l.rl = 0;
- l.tc = 0;
-
- /*
- * create the initialization block
- */
- MPus(lm->mode) = mode;
-
- /*
- * set ether addr from the value in the id prom.
- * the id prom has them in reverse order, the init
- * structure wants them in byte swapped order
- */
- MPus(lm->etheraddr[0]) = (l.ea[1]<<8) | l.ea[0];
- MPus(lm->etheraddr[1]) = (l.ea[3]<<8) | l.ea[2];
- MPus(lm->etheraddr[2]) = (l.ea[5]<<8) | l.ea[4];
-
- /*
- * ignore multicast addresses
- */
- MPus(lm->multi[0]) = 0;
- MPus(lm->multi[1]) = 0;
- MPus(lm->multi[2]) = 0;
- MPus(lm->multi[3]) = 0;
-
- /*
- * set up rcv message ring
- */
- m = lm->rmr;
- for(i = 0; i < l.nrrb; i++, m++){
- MPs(m->size) = -sizeof(Lancepkt);
- MPus(m->cntflags) = 0;
- MPus(m->laddr) = LADDR(&l.lrp[i]);
- MPus(m->flags) = HADDR(&l.lrp[i]);
- }
- MPus(lm->rdralow) = LADDR(l.lm->rmr);
- MPus(lm->rdrahigh) = (l.lognrrb<<13)|HADDR(l.lm->rmr);
-
-
- /*
- * give the lance all the rcv buffers except one (as a sentinel)
- */
- m = lm->rmr;
- for(i = 0; i < l.nrrb; i++, m++)
- MPus(m->flags) |= LANCEOWNER;
-
- /*
- * set up xmit message ring
- */
- m = lm->tmr;
- for(i = 0; i < l.ntrb; i++, m++){
- MPs(m->size) = 0;
- MPus(m->cntflags) = 0;
- MPus(m->laddr) = LADDR(&l.ltp[i]);
- MPus(m->flags) = HADDR(&l.ltp[i]);
- }
- MPus(lm->tdralow) = LADDR(l.lm->tmr);
- MPus(lm->tdrahigh) = (l.logntrb<<13)|HADDR(l.lm->tmr);
-
- /*
- * point lance to the initialization block
- */
- *l.rap = 1;
- *l.rdp = LADDR(l.lm);
- wbflush();
- *l.rap = 2;
- *l.rdp = HADDR(l.lm);
-
- /*
- * The lance byte swaps the ethernet packet unless we tell it not to
- */
- wbflush();
- *l.rap = 3;
- *l.rdp = l.busctl;
-
- /*
- * initialize lance, turn on interrupts, turn on transmit and rcv.
- */
- wbflush();
- *l.rap = 0;
- *l.rdp = INEA|INIT|STRT; /**/
-
- for(i = 0; i < 1000; i++)
- if(l.wedged == 0)
- break;
-
- qunlock(&l.tlock);
-}
-
-void
-lanceintr(void)
-{
- Msg *m;
- Lancepkt *p;
- Netfile *f, **fp;
- ushort csr, t, x;
- Lancemem *lm = LANCEMEM;
-
- csr = *l.rdp;
-
- /*
- * turn off the interrupt and any error indicators
- */
- *l.rdp = IDON|INEA|TINT|RINT|BABL|CERR|MISS|MERR;
-
- /*
- * see if an error occurred
- */
- if(csr & (BABL|MISS|MERR)){
- if(l.misses++ < 4)
- print("lance err #%ux\n", csr);
- else {
- print("lance stopped\n");
- l.wedged = 1;
- l.misses = 0;
- lancereset();
- wakeup(&l.tr);
- return;
- }
- }
-
- if(csr & IDON)
- l.wedged = 0;
-
- /*
- * the lance turns off if it gets strange output errors
- */
- if((csr & (TXON|RXON)) != (TXON|RXON))
- l.wedged = 1;
-
- /*
- * process incoming frames
- */
- if(csr & RINT) {
- m = &(lm->rmr[l.rl]);
- while((MPus(m->flags) & LANCEOWNER)==0){
- l.inpackets++;
- t = MPus(m->flags);
- if(t & ERR){
- if(t & FRAM)
- l.frames++;
- if(t & OFLO)
- l.overflows++;
- if(t & CRC)
- l.crcs++;
- if(t & BUFF)
- l.buffs++;
- } else {
- /* stuff packet up each queue that wants it */
- p = &l.rp[l.rl];
- x = MPus(m->cntflags) - 4;
- t = (p->type[0]<<8) | p->type[1];
-
- for(fp = l.f; fp < &l.f[Ntypes]; fp++){
- f = *fp;
- if(f == 0)
- continue;
- if(f->type == t || f->type < 0)
- qproduce(f->in, p->d, x);
- }
- }
-
- /*
- * stage the next input buffer
- */
- MPs(m->size) = -sizeof(Lancepkt);
- MPus(m->cntflags) = 0;
- MPus(m->laddr) = LADDR(&l.lrp[l.rl]);
- MPus(m->flags) = LANCEOWNER|HADDR(&l.lrp[l.rl]);
- wbflush();
- l.rl = RSUCC(l.rl);
- m = &(lm->rmr[l.rl]);
- }
- }
-
- /*
- * wake any process waiting for a transmit buffer
- */
- if(csr & TINT)
- wakeup(&l.tr);
-}
-
-/*
- * turn promiscuous mode on/off
- */
-static void
-promiscuous(void*, int on)
-{
- if(on)
- lancestart(PROM);
- else
- lancestart(0);;
-}
-
-static void
-lanceinit(void)
-{
- lancestart(0);
- print("lance ether: %.2x%.2x%.2x%.2x%.2x%.2x\n",
- l.ea[0], l.ea[1], l.ea[2], l.ea[3], l.ea[4], l.ea[5]);
-}
-
-static Chan*
-lanceattach(char *spec)
-{
- char *s;
-
- s = spec;
- if(s && *s && (*s != '0' || *(s+1)))
- error(Enodev);
-
- return devattach('l', spec);
-}
-
-static int
-lancewalk(Chan *c, char *name)
-{
- return netifwalk(&l, c, name);
-}
-
-static Chan*
-lanceopen(Chan *c, int omode)
-{
- return netifopen(&l, c, omode);
-}
-
-static void
-lancecreate(Chan*, char*, int, ulong)
-{
-}
-
-static void
-lanceclose(Chan *c)
-{
- netifclose(&l, c);
-}
-
-static long
-lanceread(Chan *c, void *buf, long n, ulong offset)
-{
- return netifread(&l, c, buf, n, offset);
-}
-
-static int
-isoutbuf(void *x)
-{
- Msg *m;
-
- m = x;
- return l.wedged || (MPus(m->flags)&LANCEOWNER) == 0;
-}
-
-static int
-etherloop(Etherpkt *p, long n)
-{
- int s, different;
- ushort t;
- Netfile *f, **fp;
-
- different = memcmp(p->d, p->s, sizeof(p->d));
- if(different && memcmp(p->d, l.bcast, sizeof(p->d)))
- return 0;
-
- s = splhi();
- t = (p->type[0]<<8) | p->type[1];
- for(fp = l.f; fp < &l.f[Ntypes]; fp++) {
- f = *fp;
- if(f == 0)
- continue;
- if(f->type == t || f->type < 0)
- qproduce(f->in, p->d, n);
- }
- splx(s);
- return !different;
-}
-
-static long
-lancewrite(Chan *c, void *buf, long n, ulong)
-{
- Msg *m;
- Lancepkt *p;
-
- if(n > ETHERMAXTU)
- error(Ebadarg);
-
- /* etherif.c handles structure */
- if(NETTYPE(c->qid.path) != Ndataqid)
- return netifwrite(&l, c, buf, n);
-
- /* we handle data */
- if(etherloop(buf, n))
- return n;
-
- qlock(&l.tlock);
- if(waserror()) {
- qunlock(&l.tlock);
- nexterror();
- }
-
- m = &(LANCEMEM->tmr[l.tc]);
- tsleep(&l.tr, isoutbuf, m, 10000);
- if(!isoutbuf(m) || l.wedged)
- print("lance transmitter jammed\n");
- else {
- p = &l.tp[l.tc];
- memmove(p->d, buf, n);
- if(n < 60) {
- memset(p->d+n, 0, 60-n);
- n = 60;
- }
- memmove(p->s, l.ea, sizeof(l.ea));
-
- l.outpackets++;
- MPs(m->size) = -n;
- MPus(m->cntflags) = 0;
- MPus(m->laddr) = LADDR(&l.ltp[l.tc]);
- MPus(m->flags) = LANCEOWNER|STP|ENP|HADDR(&l.ltp[l.tc]);
- l.tc = TSUCC(l.tc);
- *l.rdp = INEA|TDMD;
- }
- qunlock(&l.tlock);
- poperror();
- return n;
-}
-
-static void
-lanceremove(Chan*)
-{
-}
-
-static void
-lancestat(Chan *c, char *dp)
-{
- netifstat(&l, c, dp);
-}
-
-static void
-lancewstat(Chan *c, char *dp)
-{
- netifwstat(&l, c, dp);
-}
-
-int
-parseether(uchar *to, char *from)
-{
- char nip[4];
- char *p;
- int i;
-
- p = from;
- for(i = 0; i < 6; i++){
- if(*p == 0)
- return -1;
- nip[0] = *p++;
- if(*p == 0)
- return -1;
- nip[1] = *p++;
- nip[2] = 0;
- to[i] = strtoul(nip, 0, 16);
- if(*p == ':')
- p++;
- }
- return 0;
-}
-
-Dev lancedevtab = {
- 'l',
- "lance",
-
- lancereset,
- lanceinit,
- lanceattach,
- devclone,
- lancewalk,
- lancestat,
- lanceopen,
- lancecreate,
- lanceclose,
- lanceread,
- devbread,
- lancewrite,
- devbwrite,
- lanceremove,
- lancewstat,
-};
M port/devmouse.c => port/devmouse.c +9 -9
@@ 5,19 5,20 @@
#include "fns.h"
#include "../port/error.h"
-#include <libg.h>
+#define Image IMAGE
+#define mouse moose
+#include <draw.h>
+#undef mouse
+#include <memdraw.h>
#include "screen.h"
typedef struct Mouseinfo Mouseinfo;
struct Mouseinfo
{
- /*
- * First three fields are known in some l.s's
- */
int dx;
int dy;
- int track; /* l.s has updated dx & dy */
+ int track; /* dx & dy updated */
Mouse;
int redraw; /* update cursor on screen */
ulong counter; /* increments every update */
@@ 33,7 34,6 @@ struct Mouseinfo
Mouseinfo mouse;
Cursorinfo cursor;
int mouseshifted;
-int mousetype;
int mouseswap;
Cursor curs;
@@ 68,7 68,7 @@ Dirtab mousedir[]={
"mousectl", {Qmousectl}, 0, 0220,
};
-extern Bitmap gscreen;
+extern Memimage gscreen;
static void
mousereset(void)
@@ 336,7 336,7 @@ mouseclock(void)
mouse.redraw = cursoron(0);
unlock(&cursor);
}
- graphicsactive(0);
+ drawactive(0);
}
static int
@@ 395,7 395,7 @@ mousetrack(int b, int dx, int dy)
mouse.buttons = b;
mouse.redraw = 1;
wakeup(&mouse.r);
- graphicsactive(1);
+ drawactive(1);
}
/*
M port/portfns.h => port/portfns.h +3 -2
@@ 72,6 72,8 @@ void devstat(Chan*, char*, Dirtab*, int, Devgen*);
int devwalk(Chan*, char*, Dirtab*, int, Devgen*);
void devwstat(Chan*, char*);
Chan* domount(Chan*);
+void drawactive(int);
+void drawcmap(int);
void dumpaproc(Proc*);
void dumpqueues(void);
void dumpregs(Ureg*);
@@ 104,8 106,6 @@ void freesegs(int);
void freesession(Session*);
void getcolor(ulong, ulong*, ulong*, ulong*);
void gotolabel(Label*);
-void graphicsactive(int);
-void graphicscmap(int);
int haswaitq(void*);
long hostdomainwrite(char*, int);
long hostownerwrite(char*, int);
@@ 177,6 177,7 @@ void pgrpcpy(Pgrp*, Pgrp*);
void pgrpnote(ulong, char*, long, int);
Pgrp* pgrptab(int);
void pio(Segment *, ulong, ulong, Page **);
+void poolsummary(void);
#define poperror() up->nerrlab--
int postnote(Proc*, int, char*, int);
int pprint(char*, ...);
A port/xalloc.c => port/xalloc.c +232 -0
@@ 0,0 1,232 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+#define datoff ((ulong)((Xhdr*)0)->data)
+
+enum
+{
+ Chunk = 64*1024,
+ Nhole = 128,
+ Magichole = 0xDeadBabe,
+};
+
+typedef struct Hole Hole;
+typedef struct Xalloc Xalloc;
+typedef struct Xhdr Xhdr;
+
+struct Hole
+{
+ ulong addr;
+ ulong size;
+ ulong top;
+ Hole* link;
+};
+
+struct Xhdr
+{
+ ulong size;
+ ulong magix;
+ char data[1];
+};
+
+struct Xalloc
+{
+ Lock;
+ Hole hole[Nhole];
+ Hole* flist;
+ Hole* table;
+};
+
+static Xalloc xlists;
+
+void
+xinit(void)
+{
+ Hole *h, *eh;
+ int upages, np0, np1;
+
+ eh = &xlists.hole[Nhole-1];
+ for(h = xlists.hole; h < eh; h++)
+ h->link = h+1;
+
+ xlists.flist = xlists.hole;
+
+ upages = conf.upages;
+ np1 = upages;
+ if(np1 > conf.npage1)
+ np1 = conf.npage1;
+
+ palloc.p1 = conf.base1 + (conf.npage1 - np1)*BY2PG;
+ conf.npage1 -= np1;
+ xhole(conf.base1, conf.npage1*BY2PG);
+ conf.npage1 = conf.base1+(conf.npage1*BY2PG);
+ upages -= np1;
+
+ np0 = upages;
+ if(np0 > conf.npage0)
+ np0 = conf.npage0;
+
+ palloc.p0 = conf.base0 + (conf.npage0 - np0)*BY2PG;
+ conf.npage0 -= np0;
+ xhole(conf.base0, conf.npage0*BY2PG);
+ conf.npage0 = conf.base0+(conf.npage0*BY2PG);
+
+ palloc.np0 = np0;
+ palloc.np1 = np1;
+ /* Save the bounds of kernel alloc memory for kernel mmu mapping */
+ conf.base0 = (ulong)KADDR(conf.base0);
+ conf.base1 = (ulong)KADDR(conf.base1);
+ conf.npage0 = (ulong)KADDR(conf.npage0);
+ conf.npage1 = (ulong)KADDR(conf.npage1);
+}
+
+void*
+xspanalloc(ulong size, int align, ulong span)
+{
+ ulong a, v, t;
+
+ a = (ulong)xalloc(size+align+span);
+ if(a == 0)
+ panic("xspanalloc: %d %d %lux\n", size, align, span);
+
+ if(span > 2) {
+ v = (a + span) & ~(span-1);
+ t = v - a;
+ if(t > 0)
+ xhole(PADDR(a), t);
+ t = a + span - v;
+ if(t > 0)
+ xhole(PADDR(v+size+align), t);
+ }
+ else
+ v = a;
+
+ if(align > 1)
+ v = (v + align) & ~(align-1);
+
+ return (void*)v;
+}
+
+void*
+xallocz(ulong size, int zero)
+{
+ Xhdr *p;
+ Hole *h, **l;
+
+ size += BY2V + sizeof(Xhdr);
+ size &= ~(BY2V-1);
+
+ ilock(&xlists);
+ l = &xlists.table;
+ for(h = *l; h; h = h->link) {
+ if(h->size >= size) {
+ p = (Xhdr*)h->addr;
+ h->addr += size;
+ h->size -= size;
+ if(h->size == 0) {
+ *l = h->link;
+ h->link = xlists.flist;
+ xlists.flist = h;
+ }
+ iunlock(&xlists);
+ p = KADDR(p);
+ p->magix = Magichole;
+ p->size = size;
+ if(zero)
+ memset(p->data, 0, size);
+ return p->data;
+ }
+ l = &h->link;
+ }
+ iunlock(&xlists);
+ return nil;
+}
+
+void
+xfree(void *p)
+{
+ Xhdr *x;
+
+ x = (Xhdr*)((ulong)p - datoff);
+ if(x->magix != Magichole) {
+ xsummary();
+ panic("xfree(0x%lux) 0x%lux!=0x%lux", p, Magichole, x->magix);
+ }
+ xhole(PADDR(x), x->size);
+}
+
+void
+xhole(ulong addr, ulong size)
+{
+ ulong top;
+ Hole *h, *c, **l;
+
+ if(size == 0)
+ return;
+
+ top = addr + size;
+ ilock(&xlists);
+ l = &xlists.table;
+ for(h = *l; h; h = h->link) {
+ if(h->top == addr) {
+ h->size += size;
+ h->top = h->addr+h->size;
+ c = h->link;
+ if(c && h->top == c->addr) {
+ h->top += c->size;
+ h->size += c->size;
+ h->link = c->link;
+ c->link = xlists.flist;
+ xlists.flist = c;
+ }
+ iunlock(&xlists);
+ return;
+ }
+ if(h->addr > addr)
+ break;
+ l = &h->link;
+ }
+ if(h && top == h->addr) {
+ h->addr -= size;
+ h->size += size;
+ iunlock(&xlists);
+ return;
+ }
+
+ if(xlists.flist == nil) {
+ iunlock(&xlists);
+ print("xfree: no free holes, leaked %d bytes\n", size);
+ return;
+ }
+
+ h = xlists.flist;
+ xlists.flist = h->link;
+ h->addr = addr;
+ h->top = top;
+ h->size = size;
+ h->link = *l;
+ *l = h;
+ iunlock(&xlists);
+}
+
+void
+xsummary(void)
+{
+ int i;
+ Hole *h;
+
+ i = 0;
+ for(h = xlists.flist; h; h = h->link)
+ i++;
+
+ print("%d holes free\n", i);
+ i = 0;
+ for(h = xlists.table; h; h = h->link) {
+ print("%.8lux %.8lux %d\n", h->addr, h->top, h->size);
+ i += h->size;
+ }
+ print("%d bytes free\n", i);
+}