From 5062c11bb3bca04a2a4982e45130ca93685822f3 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Thu, 1 Dec 1994 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1994-12-01 --- carrera/trap.c | 19 ++-- pc/clock.c | 64 ++++++------ pc/devvga.c | 18 +--- pc/vgaet4000.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 315 insertions(+), 55 deletions(-) create mode 100644 pc/vgaet4000.c diff --git a/carrera/trap.c b/carrera/trap.c index 46db9c160608be982ac444300f3e158a212db94b..83720ac35163e8002ca2381c9e723fdd425c521c 100644 --- a/carrera/trap.c +++ b/carrera/trap.c @@ -320,7 +320,7 @@ intr(Ureg *ur) { static uchar devint; ulong cause = ur->cause; - ulong isr, vec; + ulong isr; m->intr++; cause &= INTR7|INTR6|INTR5|INTR4|INTR3|INTR2|INTR1|INTR0; @@ -351,21 +351,22 @@ intr(Ureg *ur) cause &= ~INTR3; } - if(cause & INTR5) - panic("EISA NMI\n"); - if(cause & INTR2) { isr = IO(ulong, R4030Isr); if(isr) { - iprint("R4030 Interrupt\n"); - iprint(" ISR #%lux\n", IO(ulong, R4030Isr)); - iprint(" ET #%lux\n", IO(ulong, R4030Et)); - iprint(" RFA #%lux\n", IO(ulong, R4030Rfa)); - iprint(" MFA #%lux\n", IO(ulong, R4030Mfa)); + print("R4030 Interrupt PC %lux R31 %lux\n", ur->pc, ur->r31); + print(" ISR #%lux\n", IO(ulong, R4030Isr)); + print(" ET #%lux\n", IO(ulong, R4030Et)); + print(" RFA #%lux\n", IO(ulong, R4030Rfa)); + print(" MFA #%lux\n", IO(ulong, R4030Mfa)); } cause &= ~INTR2; } + if(cause & INTR5) + panic("EISA NMI\n"); + + if(cause & INTR4) { devint = IO(uchar, I386ack); switch(devint) { diff --git a/pc/clock.c b/pc/clock.c index 6861cbbfbe036d1d5049d78cb415df4cc4688f2f..2edab72d7cc15f4081d4a4e345ed85afad09fa74 100644 --- a/pc/clock.c +++ b/pc/clock.c @@ -142,7 +142,7 @@ void clockinit(void) { int x, y; /* change in counter */ - int family, model, loops; + int family, model, loops, incr; X86type *t; /* @@ -170,35 +170,37 @@ clockinit(void) outb(T0cntr, (Freq/HZ)); /* low byte */ outb(T0cntr, (Freq/HZ)>>8); /* high byte */ - /* use biggest loop that works */ - if(t->family == 3) - loops = 10000; - else - loops = 30000; + /* find biggest loop that doesn't wrap */ + incr = 16000000/(t->aalcycles*HZ*2); + for(loops = incr; loops < 64*1024; loops += incr) { + + /* + * measure time for the loop + * + * MOVL loops,CX + * aaml1: AAM + * LOOP aaml1 + * + * the time for the loop should be independent of external + * cache and memory system since it fits in the execution + * prefetch buffer. + * + */ + outb(Tmode, Latch0); + x = inb(T0cntr); + x |= inb(T0cntr)<<8; + aamloop(loops); + outb(Tmode, Latch0); + y = inb(T0cntr); + y |= inb(T0cntr)<<8; + x -= y; + + if(x < 0) + x += Freq/HZ; - /* - * measure time for the loop - * - * MOVL loops,CX - * aaml1: AAM - * LOOP aaml1 - * - * the time for the loop should be independent of external - * cache and memory system since it fits in the execution - * prefetch buffer. - * - */ - outb(Tmode, Latch0); - x = inb(T0cntr); - x |= inb(T0cntr)<<8; - aamloop(loops); - outb(Tmode, Latch0); - y = inb(T0cntr); - y |= inb(T0cntr)<<8; - x -= y; - - if(x < 0) - x += 2^16; + if(x > Freq/(3*HZ)) + break; + } /* * counter goes at twice the frequency, once per transition, @@ -213,7 +215,7 @@ clockinit(void) loopconst = (cpufreq/1000)/t->aalcycles; /* AAM+LOOP's for 1 ms */ /* - * add in possible .1% error and convert to MHz + * add in possible .2% error and convert to MHz */ - cpumhz = (cpufreq + cpufreq/1000)/1000000; + cpumhz = (cpufreq + cpufreq/500)/1000000; } diff --git a/pc/devvga.c b/pc/devvga.c index 08b4f2c3b4801ce96a78d9cff6e59fbada925eae..23be19254b687678ee4bb52fa90e029b6bb8eb17 100644 --- a/pc/devvga.c +++ b/pc/devvga.c @@ -60,7 +60,7 @@ struct Vgacard static void nopage(int); static void cirruspage(int); -static void et4000page(int); +extern void et4000page(int); extern void s3page(int); Vgacard vgachips[] = @@ -75,11 +75,13 @@ Vgacard vgachips[] = Vgacard *vgacard = &vgachips[0]; /* current vga card */ extern Hwgc bt485hwgc; +extern Hwgc et4000hwgc; extern Hwgc s3hwgc; extern Hwgc tvp3020hwgc; static Hwgc *hwcursor[] = { &bt485hwgc, + &et4000hwgc, &s3hwgc, &tvp3020hwgc, 0, @@ -1071,20 +1073,6 @@ nopage(int page) USED(page); } -static void -et4000page(int page) -{ - uchar p; - - p = page & 0x0F; - p |= p<<4; - outb(0x3CD, p); - - p = (page & 0x30); - p |= p>>4; - outb(0x3CB, p); -} - static void cirruspage(int page) { diff --git a/pc/vgaet4000.c b/pc/vgaet4000.c new file mode 100644 index 0000000000000000000000000000000000000000..449264b756e11c213da64ad7f6eca779c1761521 --- /dev/null +++ b/pc/vgaet4000.c @@ -0,0 +1,269 @@ +#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" + +extern Bitmap gscreen; +extern Cursor curcursor; + +static Lock et4000pagelock; +static ulong storage; +static Point hotpoint; + +static void +setet4000page(int page) +{ + uchar p; + + p = page & 0x0F; + p |= p<<4; + outb(0x3CD, p); + + p = (page & 0x30); + p |= p>>4; + outb(0x3CB, p); +} + +static void +disable(void) +{ + uchar imaF7; + + outb(0x217A, 0xF7); + imaF7 = inb(0x217B) & ~0x80; + outb(0x217B, imaF7); +} + +static void +enable(void) +{ + uchar imaF7; + + disable(); + + /* + * Configure CRTCB for Sprite, 64x64, + * CRTC pixel overlay. + */ + outb(0x217A, 0xEF); + outb(0x217B, 0x02); + + /* + * Cursor goes in the top left corner + * of the Sprite area, so the horizontal and + * vertical presets are 0. + */ + outb(0x217A, 0xE2); + outb(0x217B, 0x00); + outb(0x217A, 0xE3); + outb(0x217B, 0x00); + + outb(0x217A, 0xE6); + outb(0x217B, 0x00); + outb(0x217A, 0xE7); + outb(0x217B, 0x00); + + /* + * Find a place for the cursor data in display memory. + * Must be on a "doubleword" boundary, but put it on a + * 1024-byte boundary so that there's no danger of it + * crossing a page. + */ + storage = (gscreen.width*BY2WD*gscreen.r.max.y+1023)/1024; + storage *= 1024/4; + outb(0x217A, 0xE8); + outb(0x217B, storage & 0xFF); + outb(0x217A, 0xE9); + outb(0x217B, (storage>>8) & 0xFF); + outb(0x217A, 0xEA); + outb(0x217B, (storage>>16) & 0x0F); + storage *= 4; + + /* + * Row offset in "quadwords". Must be 2 for Sprite. + * Bag the pixel-panning. + * Colour depth, must be 2 for Sprite. + */ + outb(0x217A, 0xEB); + outb(0x217B, 0x02); + outb(0x217A, 0xEC); + outb(0x217B, 0x00); + + outb(0x217A, 0xED); + outb(0x217B, 0x00); + + outb(0x217A, 0xEE); + if(gscreen.ldepth == 3) + outb(0x217B, 0x01); + else + outb(0x217B, 0x00); + + /* + * Enable the CRTCB/Sprite. + */ + outb(0x217A, 0xF7); + imaF7 = inb(0x217B); + outb(0x217B, 0x80|imaF7); +} + +static void +load(Cursor *c) +{ + uchar p0, p1, *mem; + int i, x, y; + ushort p; + + /* + * Lock the display memory so we can update the + * cursor bitmap if necessary. + */ + lock(&et4000pagelock); + if(memcmp(c, &curcursor, sizeof(Cursor)) == 0){ + outb(0x217A, 0xF7); + p0 = inb(0x217B); + outb(0x217B, 0x80|p0); + unlock(&et4000pagelock); + return; + } + memmove(&curcursor, c, sizeof(Cursor)); + + /* + * 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(); + + setet4000page(storage>>16); + mem = ((uchar*)gscreen.base) + (storage & 0xFFFF); + + /* + * Initialise the 64x64 cursor RAM array. There are 2 planes, + * p0 and p1. Data is written 4 pixels per byte, with p1 the + * MS bit of each pixel. + * The cursor mode gives the following truth table: + * p1 p0 colour + * 0 0 Sprite Colour 0 (defined as 0x00) + * 0 1 Sprite Colour 1 (defined as 0xFF) + * 1 0 Transparent (allow CRTC pixel pass through) + * 1 1 Invert (allow CRTC pixel invert through) + * Put the cursor into the top-left of the 64x64 array. + */ + 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]; + + p = 0x0000; + for(i = 0; i < 8; i++){ + if(p0 & (1<<(7-i))) + ; + else if(p1 & (1<<(7-i))) + p |= 0x01<<(2*i); + else + p |= 0x02<<(2*i); + } + *mem++ = p & 0xFF; + *mem++ = (p>>8) & 0xFF; + } + else { + *mem++ = 0xAA; + *mem++ = 0xAA; + } + } + } + + /* + * Set the cursor hotpoint and enable the cursor. + */ + hotpoint = c->offset; + outb(0x217A, 0xF7); + p = inb(0x217B)|0x80; + outb(0x217B, p); + + unlock(&et4000pagelock); +} + +static int +move(Point p) +{ + int x, xo, y, yo; + + if(canlock(&et4000pagelock) == 0) + return 1; + + /* + * Mustn't position the cursor offscreen even partially, + * or it disappears. Therefore, if x or y is -ve, adjust the + * cursor presets instead. + */ + if((x = p.x+hotpoint.x) < 0){ + xo = -x; + x = 0; + } + else + xo = 0; + if((y = p.y+hotpoint.y) < 0){ + yo = -y; + y = 0; + } + else + yo = 0; + + /* + * The cursor image is jerky if we don't do this. + * The cursor information is probably fetched from + * display memory during the horizontal blank active + * time and it doesn't like it if the coordinates + * are changed underneath. + */ + while((vgai(Status1) & 0x08) == 0) + ; + + outb(0x217A, 0xE2); + outb(0x217B, xo); + + outb(0x217A, 0xE6); + outb(0x217B, yo); + + outb(0x217A, 0xE1); + outb(0x217B, (x>>8) & 0xFF); + outb(0x217A, 0xE0); + outb(0x217B, x & 0xFF); + outb(0x217A, 0xE5); + outb(0x217B, (y>>8) & 0xFF); + outb(0x217A, 0xE4); + outb(0x217B, y & 0xFF); + + unlock(&et4000pagelock); + return 0; +} + +Hwgc et4000hwgc = { + "et4000hwgc", + enable, + load, + move, + disable, +}; + +void +et4000page(int page) +{ + if(hwgc == &et4000hwgc){ + lock(&et4000pagelock); + setet4000page(page); + unlock(&et4000pagelock); + } + else + setet4000page(page); +}