From 9875fbff1f23d4f6d27c8cfe77000c3b80e2e1c5 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sat, 1 Nov 1997 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1997-11-01 --- carrera/fns.h | 1 + carrera/kbd.c | 3 +- carrera/main.c | 8 +- carrera/memmove.s | 290 ++++---- carrera/memset.s | 53 +- carrera/screen.c | 241 ++++-- carrera/trap.c | 79 +- pc/cga.c | 80 +- pc/dat.h | 2 +- pc/devether.c | 24 +- pc/devi82365.c | 1 + pc/devvga.c | 1301 +++++---------------------------- pc/ether8003.c | 4 +- pc/fns.h | 4 +- pc/kbd.c | 2 +- pc/l.s | 543 +++++++------- pc/main.c | 21 +- pc/mem.h | 11 +- pc/memory.c | 15 +- pc/mmu.c | 143 +++- pc/mouse.c | 15 +- pc/mp.c | 54 +- pc/pci.c | 9 +- pc/screen.c | 499 +++++++------ pc/screen.h | 134 +++- pc/scsi.c | 2 +- pc/trap.c | 128 ++-- pc/vga.c | 863 ++++------------------ pc/vga.h | 69 -- pc/vgaark2000pv.c | 135 ++-- pc/vgabt485.c | 171 ++--- pc/vgaclgd542x.c | 140 ++-- pc/vgact65545.c | 147 ++++ pc/vgamach32.c | 47 -- pc/vgargb524.c | 145 ++-- pc/vgas3.c | 208 +++--- pc/vgatvp3020.c | 175 ++--- pc/vgatvp3026.c | 134 ++-- pc/vgax.c | 101 +++ port/alloc.c | 846 ++++++++++++--------- port/devXXX.c | 150 ---- port/devcons.c | 17 +- port/devdraw.c | 1782 +++++++++++++++++++++++++++++++++++++++++++++ port/devlance.c | 567 --------------- port/devmouse.c | 18 +- port/portfns.h | 5 +- port/xalloc.c | 232 ++++++ 47 files changed, 4894 insertions(+), 4725 deletions(-) delete mode 100644 pc/vga.h create mode 100644 pc/vgact65545.c delete mode 100644 pc/vgamach32.c create mode 100644 pc/vgax.c delete mode 100644 port/devXXX.c create mode 100644 port/devdraw.c delete mode 100644 port/devlance.c create mode 100644 port/xalloc.c diff --git a/carrera/fns.h b/carrera/fns.h index fe8dcfcd6a611799fc52346ed1aad8927036fa50..4c0a815db8a4f6d904ad9420a06015efe32c203f 100644 --- a/carrera/fns.h +++ b/carrera/fns.h @@ -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)) diff --git a/carrera/kbd.c b/carrera/kbd.c index d9759ca1d05c816a54f15e07a36a96fa14453971..f02fd2651d1beede3059f20eb080fc6a87e97833 100644 --- a/carrera/kbd.c +++ b/carrera/kbd.c @@ -6,7 +6,8 @@ #include "io.h" #include "../port/error.h" -#include +#define Image IMAGE +#include #include "screen.h" enum diff --git a/carrera/main.c b/carrera/main.c index a264f64beeca73ec29c38d844c2027c855d72e85..f0aca329830e99427cd328c59791ab6565329117 100644 --- a/carrera/main.c +++ b/carrera/main.c @@ -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; diff --git a/carrera/memmove.s b/carrera/memmove.s index f36900e33378a60ad014cdbb7f30316ea3b9fd4b..c617eaec9380cdaaf136d1e720fd6d7c0480f013 100644 --- a/carrera/memmove.s +++ b/carrera/memmove.s @@ -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: diff --git a/carrera/memset.s b/carrera/memset.s index bd36f0b10b1c8e30a5e568ae39ac0d1ff6a8d5f9..4b99a9155ad5bf15d25d48d2dcba457d0bf11a83 100644 --- a/carrera/memset.s +++ b/carrera/memset.s @@ -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 diff --git a/carrera/screen.c b/carrera/screen.c index 14ba871ca945ec4612dd9fdbf477ea5efcd4a890..f12b0ceac654c2031a78959901638525fd3a8053 100644 --- a/carrera/screen.c +++ b/carrera/screen.c @@ -7,7 +7,9 @@ #include "ureg.h" #include "../port/error.h" -#include +#define Image IMAGE +#include +#include #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; yinfo[' '].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 diff --git a/carrera/trap.c b/carrera/trap.c index 0c375f37a278fd2fa783417a04ef39dbf6e7605c..68896ed84bf363397874bf4825535d3e6ed3e43e 100644 --- a/carrera/trap.c +++ b/carrera/trap.c @@ -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>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; diff --git a/pc/dat.h b/pc/dat.h index fad2a42453cfeb0284ff457abcd4831eb375fb5b..800e82ab143a32b7179ca2001a33d3acaf03ef7e 100644 --- a/pc/dat.h +++ b/pc/dat.h @@ -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 */ diff --git a/pc/devether.c b/pc/devether.c index c28580f6d7a7f25a8594490161b913a63a0e3581..8684d64f95deecf670fc897478074ecbb5a854bd 100644 --- a/pc/devether.c +++ b/pc/devether.c @@ -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", diff --git a/pc/devi82365.c b/pc/devi82365.c index 8ecdacc38853111f7b3addd566821726aa285465..e7529ef4e37fe1837689a1d03771bc2b821eefa8 100644 --- a/pc/devi82365.c +++ b/pc/devi82365.c @@ -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); diff --git a/pc/devvga.c b/pc/devvga.c index 44188f7b8aeb1cf059539ad60f6d7d53739c3cfd..0f7b3b158f0c2452d5c495521df6d838d5bf0c1d 100644 --- a/pc/devvga.c +++ b/pc/devvga.c @@ -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 -#include "screen.h" -#include "vga.h" - -enum -{ - /* default footprint is 64k */ - Footshift= 16, - Footprint= 1< +#include +#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<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<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; portdisable(); - 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<= 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<= 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 0; s -= n) - 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<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 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 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<>(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< 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; -} diff --git a/pc/ether8003.c b/pc/ether8003.c index 66b03998ff6e0e1f296ce4f5076f6bedc7fd74ca..40fddfe81cbd99c5b6f15678340d412dc20807f4 100644 --- a/pc/ether8003.c +++ b/pc/ether8003.c @@ -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)]; diff --git a/pc/fns.h b/pc/fns.h index fd3ec63e121769af1dddac453d0092f2cc52b4d8..b2cf2fe5374b89d6a658a824d119b5dffa001053 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -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*); diff --git a/pc/kbd.c b/pc/kbd.c index 4405d7db3b75cbae20e9380083736f9a31614a2e..e7575fb265c4932c3d28748833709cfef322e9d4 100644 --- a/pc/kbd.c +++ b/pc/kbd.c @@ -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 */ diff --git a/pc/l.s b/pc/l.s index 1384fa1cdc6993a968d783459bcf173e7d1ee1b2..549d6332e808466f82a23030e764a251c35a0ba5 100644 --- a/pc/l.s +++ b/pc/l.s @@ -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 diff --git a/pc/main.c b/pc/main.c index 07aceeb9cac93ed2bbfc3500c6531465fed12d6e..29f3e43bed7f23fdfc2bfd94c5421693ad138d43 100644 --- a/pc/main.c +++ b/pc/main.c @@ -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; diff --git a/pc/mem.h b/pc/mem.h index 084a3064913287cbd572b39f52439589dbf7b7f6..18360eddefdef0ae369ef1bb9e6e1bf60be65183 100644 --- a/pc/mem.h +++ b/pc/mem.h @@ -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 diff --git a/pc/memory.c b/pc/memory.c index fe65979c8594e056cff5538d6b1586d4c4cbc937..baed43aacd40b36cf2a0aff5964179cf3f7c9a3b 100644 --- a/pc/memory.c +++ b/pc/memory.c @@ -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 diff --git a/pc/mmu.c b/pc/mmu.c index 58c47c354ef03b93de7bdc2cfd41c93d5184a374..cb2ad68f6375083d927fc88071180985a892815c 100644 --- a/pc/mmu.c +++ b/pc/mmu.c @@ -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; } diff --git a/pc/mouse.c b/pc/mouse.c index 3bb898113485c2ad4707bb5dc4f6d08b44c68360..e1165d0bd434689b0965d0ce1d6af60ada3ebc76 100644 --- a/pc/mouse.c +++ b/pc/mouse.c @@ -6,9 +6,22 @@ #include "../port/error.h" #include "io.h" -#include +#define Image IMAGE +#include +#include #include "screen.h" +/* + * mouse types + */ +enum +{ + Mouseother= 0, + Mouseserial= 1, + MousePS2= 2, +}; +static int mousetype; + /* * setup a serial mouse */ diff --git a/pc/mp.c b/pc/mp.c index ab2d9673896f03800c40f0fa80f8eb9340018096..a97b966bf2e7301050e3119fcb69925c2cedad01 100644 --- a/pc/mp.c +++ b/pc/mp.c @@ -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 diff --git a/pc/pci.c b/pc/pci.c index d0bc2f123be417866643e98039dd3685984e5bda..e58e6db42c4df4c8a8a9986d497a55bfd0d77da0 100644 --- a/pc/pci.c +++ b/pc/pci.c @@ -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); diff --git a/pc/screen.c b/pc/screen.c index 3925a1d6b7660be65d2b939cad31d693dcc5a71e..1d8a36c720a2bfa3bd4eefaa874f2a7db268e238 100644 --- a/pc/screen.c +++ b/pc/screen.c @@ -4,306 +4,295 @@ #include "dat.h" #include "fns.h" #include "io.h" +#include "ureg.h" #include "../port/error.h" -#include -#include +#define Image IMAGE +#include +#include #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<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<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<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); } diff --git a/pc/screen.h b/pc/screen.h index 6b7600460ca983fcdf3a42cc48afc9385dea72c6..f81200471ae853b627d308e33db293c466529eca 100644 --- a/pc/screen.h +++ b/pc/screen.h @@ -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, +}; diff --git a/pc/scsi.c b/pc/scsi.c index bfc0ffad1fa10a13f34649ff6000c341bc03121d..ef20ab4369238077d4351f7bec670e4fdc336499 100644 --- a/pc/scsi.c +++ b/pc/scsi.c @@ -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"); diff --git a/pc/trap.c b/pc/trap.c index 9dfc62a13a5665a3c1bd4410911cbd0f14ae5e09..cc54a14cba250a19d83c0b0748f595a237a3238e 100644 --- a/pc/trap.c +++ b/pc/trap.c @@ -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); - + } } /* diff --git a/pc/vga.c b/pc/vga.c index 245f40a55ab598f606127b77a258bf347805b443..fa101c78ddccd95ae8d24e9926092d98a00ff2f4 100644 --- a/pc/vga.c +++ b/pc/vga.c @@ -1,567 +1,158 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" - -#include -#include -#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 +#include +#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< (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<>(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, -}; diff --git a/pc/vga.h b/pc/vga.h deleted file mode 100644 index 53edbfba069aa3044e26e0568253a49d5d1666f1..0000000000000000000000000000000000000000 --- a/pc/vga.h +++ /dev/null @@ -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; diff --git a/pc/vgaark2000pv.c b/pc/vgaark2000pv.c index a20ffb3c7b494f43fd6be5cba4d76c8c22ca73aa..2cf937b0b409f77bf69cf2587d15fe4492f8ec59 100644 --- a/pc/vgaark2000pv.c +++ b/pc/vgaark2000pv.c @@ -5,43 +5,45 @@ #include "fns.h" #include "../port/error.h" -#include +#define Image IMAGE +#include +#include #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; 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, +}; diff --git a/pc/vgabt485.c b/pc/vgabt485.c index 6af4a75507a237c2a15e34a1beb793d5e4144d5e..72c28674219be5e175c31cebef20f12a115e2dee 100644 --- a/pc/vgabt485.c +++ b/pc/vgabt485.c @@ -5,9 +5,10 @@ #include "fns.h" #include "../port/error.h" -#include +#define Image IMAGE +#include +#include #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); -} diff --git a/pc/vgaclgd542x.c b/pc/vgaclgd542x.c index 8d78b9fcee59b6fdf971c2e3d41c3818b685c450..ff9ab5ba1a47259dbfa660090761fe758c6ff676 100644 --- a/pc/vgaclgd542x.c +++ b/pc/vgaclgd542x.c @@ -6,58 +6,51 @@ #include "io.h" #include "../port/error.h" -#include +#define Image IMAGE +#include +#include #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<storage = ((256<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<>(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<>(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, +}; diff --git a/pc/vgact65545.c b/pc/vgact65545.c new file mode 100644 index 0000000000000000000000000000000000000000..5be49fe0bf6ea3a605b060fd73fc46859914e14a --- /dev/null +++ b/pc/vgact65545.c @@ -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 +#include +#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<>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, +}; diff --git a/pc/vgamach32.c b/pc/vgamach32.c deleted file mode 100644 index f5f2ae21d6b7d316977317dbcdb90208420a3ad1..0000000000000000000000000000000000000000 --- a/pc/vgamach32.c +++ /dev/null @@ -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 -#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); -} diff --git a/pc/vgargb524.c b/pc/vgargb524.c index ab01c77967a0bb9454a009525cdada6c30a54ad0..44eb7df4d9221a1d845375b5b57f1792bc73de8e 100644 --- a/pc/vgargb524.c +++ b/pc/vgargb524.c @@ -5,11 +5,10 @@ #include "fns.h" #include "../port/error.h" -#include +#define Image IMAGE +#include +#include #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); -} diff --git a/pc/vgas3.c b/pc/vgas3.c index 6ebe91369f031bddbce01026c9c89b85841850da..78815490d6369ba06d9e080231b3b2a0cd89ff48 100644 --- a/pc/vgas3.c +++ b/pc/vgas3.c @@ -3,30 +3,22 @@ #include "mem.h" #include "dat.h" #include "fns.h" +#include "io.h" #include "../port/error.h" -#include +#define Image IMAGE +#include +#include #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); -} diff --git a/pc/vgatvp3020.c b/pc/vgatvp3020.c index 77d7224931b386c1b5a69b1e014edd663e556cf3..1ca7348a96d54c09f99294200fb5a43b28cabee6 100644 --- a/pc/vgatvp3020.c +++ b/pc/vgatvp3020.c @@ -5,24 +5,18 @@ #include "fns.h" #include "../port/error.h" -#include +#define Image IMAGE +#include +#include #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); -} diff --git a/pc/vgatvp3026.c b/pc/vgatvp3026.c index ba274a22374eb7981196c8cdf06df9264dbba446..7080fe06e903747315779da4576c478e1e8313db 100644 --- a/pc/vgatvp3026.c +++ b/pc/vgatvp3026.c @@ -5,11 +5,10 @@ #include "fns.h" #include "../port/error.h" -#include +#define Image IMAGE +#include +#include #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); -} diff --git a/pc/vgax.c b/pc/vgax.c new file mode 100644 index 0000000000000000000000000000000000000000..9ca7720a6ff322a2187ed71df3c229f303f0d8c2 --- /dev/null +++ b/pc/vgax.c @@ -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 +#include +#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; +} diff --git a/port/alloc.c b/port/alloc.c index f4b2c2b3e0a6efead76941762be4990cab5ff8d2..66d4ae0e51e8a92608d124d584eb65562f0c65b9 100644 --- a/port/alloc.c +++ b/port/alloc.c @@ -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<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<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<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; iname) == 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<next) - nfree++; - print("%8d %4d %4d\n", 1<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; } diff --git a/port/devXXX.c b/port/devXXX.c deleted file mode 100644 index 7c77a4a4f7a93dbe1923c231484162539956269b..0000000000000000000000000000000000000000 --- a/port/devXXX.c +++ /dev/null @@ -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 */ -}; diff --git a/port/devcons.c b/port/devcons.c index 2fd2e97087d8a057207582ce7ffce001dcfca145..6276dd23db0fdfd036a3dbb3622c9b2883c42d27 100644 --- a/port/devcons.c +++ b/port/devcons.c @@ -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) diff --git a/port/devdraw.c b/port/devdraw.c new file mode 100644 index 0000000000000000000000000000000000000000..b8fe66d5c746cae725a177b40392762d6a53575c --- /dev/null +++ b/port/devdraw.c @@ -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 +#include +#include + +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<qid.path&~(CHDIR|((1<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(; namename, 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; ivers != 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(; namename, 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; islot = 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)<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; icscreen) + drawuninstallscreen(cl, cl->cscreen); + /* all screens are freed, so now we can free images */ + dp = cl->dimage; + for(i=0; inext; + 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; irefreshme || 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 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; jlayer == 0) + error("images are not windows"); + for(j=1; jlayer->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; jlayer->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< BLANKTIME) + drawblankscreen(1); + else + sdraw.blanktime++; + } +} diff --git a/port/devlance.c b/port/devlance.c deleted file mode 100644 index a9a97502ac536c262c57f85143ddff0950f737c6..0000000000000000000000000000000000000000 --- a/port/devlance.c +++ /dev/null @@ -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, -}; diff --git a/port/devmouse.c b/port/devmouse.c index 574b56ae53e14af102e7a854a3f2b18c96d22dfc..c2a56a3a3b9154edf85174712e2154213038011c 100644 --- a/port/devmouse.c +++ b/port/devmouse.c @@ -5,19 +5,20 @@ #include "fns.h" #include "../port/error.h" -#include +#define Image IMAGE +#define mouse moose +#include +#undef mouse +#include #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); } /* diff --git a/port/portfns.h b/port/portfns.h index 7ecc133b337dac6fafed99d1bd49116f710c9849..7b5eb6379e8fc73f413feec934a60571128e7d22 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -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*, ...); diff --git a/port/xalloc.c b/port/xalloc.c new file mode 100644 index 0000000000000000000000000000000000000000..27ff5cb71ba0303f75901f4af74f8385462d2f38 --- /dev/null +++ b/port/xalloc.c @@ -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); +}