M bitsy/fns.h => bitsy/fns.h +6 -1
@@ 1,7 1,10 @@
#include "../port/portfns.h"
void cacheflush(void);
-void cacheflushaddr(ulong);
+void cachewb(void);
+void cachewbaddr(void*);
+void cachewbregion(void*, int);
+void dcacheinvalidate(void);
int cistrcmp(char*, char*);
int cistrncmp(char*, char*, int);
void clockinit(void);
@@ 14,6 17,7 @@ ulong getfar(void);
ulong getfsr(void);
#define getpgcolor(a) 0
void h3650uartsetup(void);
+void icacheinvalidate(void);
void idle(void);
#define idlehands() /* nothing to do in the runproc */
void intrenable(int, void (*)(Ureg*, void*), void*, char*);
@@ 28,6 32,7 @@ void mmuinit(void);
void mmuenable(void);
void mmudisable(void);
void mmuinvalidate(void);
+void mmuinvalidateaddr(ulong);
void noted(Ureg*, ulong);
int notify(Ureg*);
#define procrestore(p)
M bitsy/l.s => bitsy/l.s +51 -7
@@ 39,17 39,22 @@ TEXT mmuinvalidate(SB), $-4
MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x7)
RET
+/* flush tlb's */
+TEXT mmuinvalidateaddr(SB), $-4
+ MCR CpMMU, 0, R0, C(CpTLBFlush), C(0x6), 1
+ RET
+
/* write back and invalidate i and d caches */
TEXT cacheflush(SB), $-4
/* write back any dirty data */
MOVW $0xe0000000,R0
ADD $(8*1024),R0,R1
-_wbloop:
- MOVW.W 32(R0),R2
+_cfloop:
+ MOVW.P 32(R0),R2
CMP R0,R1
- BNE _wbloop
+ BNE _cfloop
- /* drain write buffer and flush i&d cache contents */
+ /* drain write buffer and invalidate i&d cache contents */
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x7), 0
@@ 60,13 65,52 @@ _wbloop:
MOVW R0,R0
RET
-/* clean a single virtual address */
-TEXT cacheflushaddr(SB), $-4
+/* write back and invalidate i and d caches */
+TEXT cachewb(SB), $-4
+ /* write back any dirty data */
+ MOVW $0xe0000000,R0
+ ADD $(8*1024),R0,R1
+_cwbloop:
+ MOVW.P 32(R0),R2
+ CMP R0,R1
+ BNE _cfloop
+
+ /* drain write buffer */
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
+ RET
+
+/* write back a single cache line */
+TEXT cachewbaddr(SB), $-4
+ BIC $31,R0
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
+ B _wbflush
+
+/* write back a region of cache lines */
+TEXT cachewbregion(SB), $-4
+ MOVW 4(FP),R1
+ BIC $31,R0
+ ADD R0,R1
+ ADD $32,R1
+_cfrloop:
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 1
+ ADD $32,R0
+ CMP.S R0,R1
+ BNE _cfrloop
+ B _wbflush
+
+/* invalidate the dcache */
+TEXT dcacheinvalidate(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x6)
+ RET
+
+/* invalidate the icache */
+TEXT icacheinvalidate(SB), $-4
+ MCR CpMMU, 0, R0, C(CpCacheFlush), C(0x9)
RET
/* drain write buffer */
TEXT wbflush(SB), $-4
+_wbflush:
MCR CpMMU, 0, R0, C(CpCacheFlush), C(0xa), 4
RET
@@ 100,7 144,7 @@ TEXT putttb(SB), $-4
*/
TEXT mmuenable(SB), $-4
MRC CpMMU, 0, R0, C(CpControl), C(0x0)
- ORR $(CpCmmuena|CpCwb|CpCdcache), R0
+ ORR $(CpCmmuena|CpCdcache|CpCwb), R0
MCR CpMMU, 0, R0, C(CpControl), C(0x0)
RET
M bitsy/main.c => bitsy/main.c +3 -24
@@ 29,12 29,13 @@ main(void)
m->ticks = 1;
rs232power(1);
- iprint("bitsy kernel\n");
+ iprint("\nPlan 9 bitsy kernel\n");
confinit();
xinit();
mmuinit();
gpioinit();
trapinit();
+ screeninit();
sa1100_uartsetup(1);
printinit(); /* from here on, print works, before this we need iprint */
clockinit();
@@ 44,7 45,6 @@ main(void)
pageinit();
swapinit();
userinit();
-//iprint("schedinit(), death soon\n");
schedinit();
}
@@ 60,34 60,13 @@ exit(int ispanic)
delay(1000);
iprint("it's a wonderful day to die\n");
+ cacheflush();
mmuinvalidate();
mmudisable();
f = nil;
(*f)();
}
-/*
- * quicker panic
- */
-void
-qpanic(char *fmt, ...)
-{
- int n;
- va_list arg;
- char buf[PRINTSIZE];
-
- splhi();
- strcpy(buf, "panic: ");
- va_start(arg, fmt);
- n = doprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
- va_end(arg);
- buf[n] = '\n';
- serialputs(buf, n+1);
-
- exit(1);
-}
-
-
static uchar *sp;
/*
M bitsy/mem.h => bitsy/mem.h +1 -1
@@ 21,7 21,7 @@
/*
* Time
*/
-#define HZ (10) /* clock frequency */
+#define HZ (20) /* clock frequency */
#define MS2HZ (1000/HZ) /* millisec per clock tick */
#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
#define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */
M bitsy/mmu.c => bitsy/mmu.c +47 -30
@@ 220,40 220,57 @@ static ulong mmubits[16] =
* add an entry to the current map
*/
void
-putmmu(ulong va, ulong pa, Page*)
+putmmu(ulong va, ulong pa, Page *pg)
{
- Page *pg;
- ulong *t;
+ Page *l2pg;
+ ulong *t, *l1p, *l2p;
+ int s;
-print("putmmu(0x%.8lux, 0x%.8lux)\n", va, pa);
- /* always point L1 entry to L2 page, can't hurt */
- pg = up->l1page[va>>20];
- if(pg == nil){
- pg = up->mmufree;
- if(pg != nil){
- up->mmufree = pg->next;
+ s = splhi();
+
+ /* clear out the current entry */
+ mmuinvalidateaddr(va);
+
+ l2pg = up->l1page[va>>20];
+ if(l2pg == nil){
+ l2pg = up->mmufree;
+ if(l2pg != nil){
+ up->mmufree = l2pg->next;
} else {
- pg = auxpage();
- if(pg == nil)
+ l2pg = auxpage();
+ if(l2pg == nil)
pexit("out of memory", 1);
}
- pg->va = VA(kmap(pg));
- up->l1page[va>>20] = pg;
- memset((uchar*)(pg->va), 0, BY2PG);
+ l2pg->va = VA(kmap(l2pg));
+ up->l1page[va>>20] = l2pg;
+ memset((uchar*)(l2pg->va), 0, BY2PG);
}
- l1table[va>>20] = L1PageTable | L1Domain0 | (pg->pa & L1PTBaseMask);
- cacheflushaddr((ulong)&l1table[va>>20]);
-print("%lux[%lux] = %lux\n", l1table, va>>20, l1table[va>>20]);
- up->l1table[va>>20] = l1table[va>>20];
- t = (ulong*)pg->va;
+
+ /* always point L1 entry to L2 page, can't hurt */
+ l1p = &l1table[va>>20];
+ *l1p = L1PageTable | L1Domain0 | (l2pg->pa & L1PTBaseMask);
+ up->l1table[va>>20] = *l1p;
+ t = (ulong*)l2pg->va;
/* set L2 entry */
- t[(va & (OneMeg-1))>>PGSHIFT] = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)]
+ l2p = &t[(va & (OneMeg-1))>>PGSHIFT];
+ *l2p = mmubits[pa & (PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE)]
| (pa & ~(PTEKERNEL|PTEVALID|PTEUNCACHED|PTEWRITE));
-print("%lux[%lux] = %lux\n", (ulong)t, (va & (OneMeg-1))>>PGSHIFT, t[(va & (OneMeg-1))>>PGSHIFT]);
- cacheflushaddr((ulong)&t[(va & (OneMeg-1))>>PGSHIFT]);
- wbflush();
+ /* write back dirty entries - we need this because the pio() in
+ * fault.c is writing via a different virt addr and won't clean
+ * its changes out of the dcache. Page coloring doesn't work
+ * on this mmu because the virtual cache is set associative
+ * rather than direct mapped.
+ */
+ cachewb();
+ if(pg->cachectl[0] == PG_TXTFLUSH){
+ /* pio() sets PG_TXTFLUSH whenever a text page has been written */
+ icacheinvalidate();
+ pg->cachectl[0] = PG_NOFLUSH;
+ }
+
+ splx(s);
}
/*
@@ 300,6 317,7 @@ mmurelease(Proc* p)
p->mmufree = nil;
memset(l1table, 0, sizeof(p->l1table));
+ cachewbregion(l1table, sizeof(p->l1table));
}
void
@@ 309,20 327,19 @@ mmuswitch(Proc *p)
return;
m->mmupid = p->pid;
+ /* write back dirty cache entries and invalidate all cache entries */
+ cacheflush();
+
if(p->newtlb){
mmuptefree(p);
p->newtlb = 0;
}
- /* write back dirty cache entries before changing map */
- cacheflush();
-
/* move in new map */
memmove(l1table, p->l1table, sizeof(p->l1table));
- /* make sure map is in memory and drain write buffer */
- cacheflushaddr((ulong)l1table);
- wbflush();
+ /* make sure map is in memory */
+ cachewbregion(l1table, sizeof(p->l1table));
/* lose any possible stale tlb entries */
mmuinvalidate();
A bitsy/sa1110uart.c => bitsy/sa1110uart.c +400 -0
@@ 0,0 1,400 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#include "../port/netif.h"
+
+/* this isn't strictly a sa1100 driver. The rts/cts stuff is h3650 specific */
+
+/* hardware registers */
+typedef struct Uartregs Uartregs;
+struct Uartregs
+{
+ ulong ctl[4];
+ ulong dummya;
+ ulong data;
+ ulong dummyb;
+ ulong status[2];
+};
+
+enum
+{
+ /* ctl[0] bits */
+ Parity= 1<<0,
+ Even= 1<<1,
+ Stop2= 1<<2,
+ Bits8= 1<<3,
+ SCE= 1<<4, /* synchronous clock enable */
+ RCE= 1<<5, /* rx on falling edge of clock */
+ TCE= 1<<6, /* tx on falling edge of clock */
+
+ /* ctl[3] bits */
+ Rena= 1<<0, /* receiver enable */
+ Tena= 1<<1, /* transmitter enable */
+ Break= 1<<2, /* force TXD3 low */
+ Rintena= 1<<3, /* enable receive interrupt */
+ Tintena= 1<<4, /* enable transmitter interrupt */
+ Loopback= 1<<5, /* loop back data */
+
+ /* data bits */
+ DEparity= 1<<8, /* parity error */
+ DEframe= 1<<9, /* framing error */
+ DEoverrun= 1<<10, /* overrun error */
+
+ /* status[0] bits */
+ Tint= 1<<0, /* transmit fifo half full interrupt */
+ Rint0= 1<<1, /* receiver fifo 1/3-2/3 full */
+ Rint1= 1<<2, /* receiver fifo not empty and receiver idle */
+ Breakstart= 1<<3,
+ Breakend= 1<<4,
+ Fifoerror= 1<<5, /* fifo error */
+
+ /* status[1] bits */
+ Tbusy= 1<<0, /* transmitting */
+ Rnotempty= 1<<1, /* receive fifo not empty */
+ Tnotfull= 1<<2, /* transmit fifo not full */
+ ParityError= 1<<3,
+ FrameError= 1<<4,
+ Overrun= 1<<5,
+};
+
+Uartregs *uart3regs = UART3REGS;
+
+static void sa1100_uartbaud(Uart *p, int rate);
+static void sa1100_uartkick(Uart *p);
+static void sa1100_uartrts(Uart *p, int on);
+static void sa1100_uartintr(Ureg*, void*);
+static void sa1100_uartbreak(Uart*, int);
+static void sa1100_uartbits(Uart*, int);
+static void sa1100_uartparity(Uart*, int);
+static void sa1100_uartmodemctl(Uart*, int);
+static void sa1100_uartstop(Uart*, int);
+static void sa1100_uartdtr(Uart*, int);
+static long sa1100_uartstatus(Uart*, void*, long, long);
+static void sa1100_uartenable(Uart*, int);
+static void sa1100_uartdisable(Uart*);
+
+PhysUart sa1100_uart = {
+ .enable= sa1100_uartenable,
+ .disable= sa1100_uartdisable,
+ .bits= sa1100_uartbits,
+ .kick= sa1100_uartkick,
+ .intr= sa1100_uartintr,
+ .modemctl= sa1100_uartmodemctl,
+ .baud= sa1100_uartbaud,
+ .stop= sa1100_uartstop,
+ .parity= sa1100_uartparity,
+ .dobreak= sa1100_uartbreak,
+ .rts= sa1100_uartrts,
+ .dtr= sa1100_uartdtr,
+ .status= sa1100_uartstatus,
+};
+
+#define R(p) ((Uartregs*)(p->regs))
+
+/*
+ * enable a port's interrupts. set DTR and RTS
+ */
+static void
+sa1100_uartenable(Uart *p, int intena)
+{
+ ulong s;
+
+ s = R(p)->ctl[3] & ~(Rintena|Tintena|Rena|Tena);
+ if(intena)
+ R(p)->ctl[3] = s |Rintena|Tintena|Rena|Tena;
+ else
+ R(p)->ctl[3] = s | Rena|Tena;
+}
+
+/*
+ * disable interrupts. clear DTR, and RTS
+ */
+static void
+sa1100_uartdisable(Uart *p)
+{
+ R(p)->ctl[3] &= ~(Rintena|Tintena|Rena|Tena);
+}
+
+static long
+sa1100_uartstatus(Uart *p, void *buf, long n, long offset)
+{
+ char str[256];
+ ulong ctl0;
+
+ ctl0 = R(p)->ctl[0];
+ snprint(str, sizeof(str),
+ "b%d c%d d%d e%d l%d m%d p%c r%d s%d i%d\n"
+ "dev(%d) type(%d) framing(%d) overruns(%d)%s%s%s%s\n",
+
+ p->baud,
+ p->hup_dcd,
+ 0,
+ p->hup_dsr,
+ (ctl0 & Bits8) ? 8 : 7,
+ 0,
+ (ctl0 & Parity) ? ((ctl0 & Even) ? 'e' : 'o') : 'n',
+ 0,
+ (ctl0 & Stop2) ? 2 : 1,
+ 1,
+
+ p->dev,
+ p->type,
+ p->frame,
+ p->overrun,
+ "",
+ "",
+ "",
+ "" );
+ return readstr(offset, buf, n, str);
+}
+
+/*
+ * set the buad rate
+ */
+static void
+sa1100_uartbaud(Uart *p, int rate)
+{
+ ulong brconst;
+
+ if(rate <= 0)
+ return;
+
+ brconst = p->freq/(16*rate) - 1;
+ R(p)->ctl[1] = (brconst>>8) & 0xf;
+ R(p)->ctl[2] = brconst;
+
+ p->baud = rate;
+}
+
+/*
+ * send a break
+ */
+static void
+sa1100_uartbreak(Uart *p, int ms)
+{
+ if(ms == 0)
+ ms = 200;
+
+ R(p)->ctl[3] |= Break;
+ tsleep(&up->sleep, return0, 0, ms);
+ R(p)->ctl[3] &= ~Break;
+}
+
+/*
+ * set bits/char
+ */
+static void
+sa1100_uartbits(Uart *p, int n)
+{
+ switch(n){
+ case 7:
+ R(p)->ctl[0] &= ~Bits8;
+ break;
+ case 8:
+ R(p)->ctl[0] |= Bits8;
+ break;
+ default:
+ error(Ebadarg);
+ }
+}
+
+/*
+ * set stop bits
+ */
+static void
+sa1100_uartstop(Uart *p, int n)
+{
+ switch(n){
+ case 1:
+ R(p)->ctl[0] &= ~Stop2;
+ break;
+ case 2:
+ R(p)->ctl[0] |= Stop2;
+ break;
+ default:
+ error(Ebadarg);
+ }
+}
+
+/*
+ * turn on/off rts
+ */
+static void
+sa1100_uartrts(Uart*, int)
+{
+}
+
+/*
+ * turn on/off dtr
+ */
+static void
+sa1100_uartdtr(Uart*, int)
+{
+}
+
+/*
+ * turn on/off modem flow control on/off (rts/cts)
+ */
+static void
+sa1100_uartmodemctl(Uart *p, int on)
+{
+ if(on) {
+ } else {
+ p->cts = 1;
+ }
+}
+
+/*
+ * set parity
+ */
+static void
+sa1100_uartparity(Uart *p, int type)
+{
+ switch(type){
+ case 'e':
+ R(p)->ctl[0] |= Parity|Even;
+ break;
+ case 'o':
+ R(p)->ctl[0] |= Parity;
+ break;
+ default:
+ R(p)->ctl[0] &= ~(Parity|Even);
+ break;
+ }
+}
+
+/*
+ * restart output if not blocked and OK to send
+ */
+static void
+sa1100_uartkick(Uart *p)
+{
+ int i;
+
+ R(p)->ctl[3] &= ~Tintena;
+
+ if(p->cts == 0 || p->blocked)
+ return;
+
+ /*
+ * 128 here is an arbitrary limit to make sure
+ * we don't stay in this loop too long. If the
+ * chips output queue is longer than 128, too
+ * bad -- presotto
+ */
+ for(i = 0; i < 128; i++){
+ if(!(R(p)->status[1] & Tnotfull)){
+ R(p)->ctl[3] |= Tintena;
+ break;
+ }
+ if(p->op >= p->oe && uartstageoutput(p) == 0)
+ break;
+ R(p)->data = *p->op++;
+ }
+}
+
+/*
+ * for iprint, just write it
+ */
+void
+serialputs(char *str, int n)
+{
+ Uartregs *ur;
+
+ ur = uart3regs;
+ while(n-- > 0){
+ /* wait for output ready */
+ while((ur->status[1] & Tnotfull) == 0)
+ ;
+ ur->data = *str++;
+ }
+ while((ur->status[1] & Tbusy))
+ ;
+}
+
+/*
+ * take an interrupt
+ */
+static void
+sa1100_uartintr(Ureg*, void *x)
+{
+ Uart *p;
+ ulong s;
+ Uartregs *regs;
+
+ p = x;
+ regs = p->regs;
+
+ /* remember and reset interrupt causes */
+ s = regs->status[0];
+ regs->status[0] |= s;
+
+ if(s & Tint){
+ /* transmitter interrupt, restart */
+ uartkick(p);
+ }
+
+ /* receiver interrupt, snarf bytes */
+ while(regs->status[1] & Rnotempty)
+ uartrecv(p, regs->data);
+
+ if(s & (ParityError|FrameError|Overrun)){
+ if(s & ParityError)
+ p->parity++;
+ if(s & FrameError)
+ p->frame++;
+ if(s & Overrun)
+ p->overrun++;
+ }
+}
+
+typedef struct Gpclkregs Gpclkregs;
+struct Gpclkregs
+{
+ ulong r0;
+ ulong r1;
+ ulong dummya;
+ ulong r2;
+ ulong r3;
+};
+
+enum
+{
+ /* gpclk register 0 */
+ Gpclk_sus= 1<<0, /* set uart mode */
+};
+
+Gpclkregs *gpclkregs;
+
+/*
+ * setup all uarts (called early by main() to allow debugging output to
+ * a serial port)
+ */
+void
+sa1100_uartsetup(int console)
+{
+ Uart *p;
+ Uartregs *uartregs;
+
+ /* external serial port (eia0) */
+ uart3regs = mapspecial(UART3REGS, 64);
+ p = uartsetup(&sa1100_uart, uart3regs, ClockFreq, "serialport3");
+ intrenable(IRQuart3, sa1100_uartintr, p, p->name);
+
+ /* set eia0 up as a console */
+ if(console)
+ uartspecial(p, 115200, &kbdq, &printq, kbdcr2nl);
+
+ /* port for talking to microcontroller (eia1) */
+ gpclkregs = mapspecial(GPCLKREGS, 64);
+ gpclkregs->r0 = Gpclk_sus; /* set uart mode */
+ uartregs = mapspecial(UART1REGS, 64);
+ p = uartsetup(&sa1100_uart, uartregs, ClockFreq, "serialport1");
+ sa1100_uartbaud(p, 115200);
+ intrenable(IRQuart1b, sa1100_uartintr, p, p->name);
+}
M bitsy/screen.c => bitsy/screen.c +41 -20
@@ 18,13 18,13 @@ enum {
Ht = 240,
Pal0 = 0x2000, /* 16-bit pixel data in active mode (12 in passive) */
- hsw = 0x4,
+ hsw = 0x04,
elw = 0x11,
- blw = 0xc,
+ blw = 0x0c,
- vsw = 0x3,
- efw = 0x1,
- bfw = 0xa,
+ vsw = 0x03,
+ efw = 0x01,
+ bfw = 0x0a,
pcd = 0x10,
};
@@ 93,16 93,16 @@ enum {
};
struct sa1110regs {
- ulong lccr0; /* 0xb0100000 */
- ulong lcsr; /* 0xb0100004 */
- ulong dummies[2]; /* unused 0xb0100008 and 0xb010000c */
- short* dbar1; /* 0xb0100010 */
- ulong dcar1; /* 0xb0100014 */
- ulong dbar2; /* 0xb0100018 */
- ulong dcar2; /* 0xb010001c */
- ulong lccr1; /* 0xb0100020 */
- ulong lccr2; /* 0xb0100024 */
- ulong lccr3; /* 0xb0100028 */
+ ulong lccr0;
+ ulong lcsr;
+ ulong dummies[2];
+ short* dbar1;
+ ulong dcar1;
+ ulong dbar2;
+ ulong dcar2;
+ ulong lccr1;
+ ulong lccr2;
+ ulong lccr3;
} *lcd;
Point ZP = {0, 0};
@@ 128,15 128,31 @@ Memimage *back;
Memimage *hwcursor;
static void
+lcdstop(void) {
+ ulong lccr0;
+
+ lcd->lccr0 &= ~(0<<LEN); /* disable the LCD */
+ while((lcd->lcsr & LDD) == 0)
+ sleep(1);
+ lcdpower(0);
+}
+
+static void
lcdinit(void)
{
- lcd = (struct sa1110regs*)0xb0100000;
+ /* map the lcd regs into the kernel's virtual space */
+ lcd = (struct sa1110regs*)mapspecial(LCDREGS, sizeof(struct sa1110regs));;
+
+ /* the following works because main memory is direct mapped */
+ lcd->lccr0 &= ~(0<<LEN); /* disable the LCD */
+ while((lcd->lcsr & LDD) == 0)
+ sleep(1);
lcd->dbar1 = framebuf->palette;
- lcd->lccr3 = (pcd << PCD) | (0 << ACB) | (0 << API) | (1 << VSP) | (1 << HSP);
- lcd->lccr2 = ((Ht-1) << LPP) | (vsw << VSW) | (efw << EFW) | (bfw << BFW);
- lcd->lccr1 = (Wid << PPL) | (hsw << HSW) | (elw << ELW) | (blw << BLW);
- lcd->lccr0 = 1<<LEN | 1 << CMS | 0<<SDS | 1<<LDM | 1<<BAM | 1<<ERM | 1<<PAS | 0<<BLE | 0<<PDD;
+ lcd->lccr3 = pcd<<PCD | 0<<ACB | 0<<API | 1<<VSP | 1<<HSP | 0<<PCP | 0<<OEP;
+ lcd->lccr2 = (Ht-1)<<LPP | vsw<<VSW | efw<<EFW | bfw<<BFW;
+ lcd->lccr1 = (Wid-16)<<PPL | hsw<<HSW | elw<<ELW | blw<<BLW;
+ lcd->lccr0 = 1<<LEN | 0<<CMS | 0<<SDS | 1<<LDM | 1<<BAM | 1<<ERM | 1<<PAS | 0<<BLE | 0<<DPD | 0<<PDD;
}
@@ 145,9 161,14 @@ screeninit(void)
{
framebuf = xspanalloc(sizeof *framebuf, 0x10, 0);
memset(framebuf->palette, 0, sizeof framebuf->palette);
+ memset(framebuf->pixel, 0xf8, sizeof framebuf->pixel);
framebuf->palette[0] = Pal0;
+ print("LCD status before power up: 0x%lux\n", lcd->lcsr);
+ lcdpower(1);
+ print("LCD status after power up: 0x%lux\n", lcd->lcsr);
lcdinit();
+ print("LCD status after lcdinit: 0x%lux\n", lcd->lcsr);
gscreen = &xgscreen;
gscreen->data = (struct Memdata *)framebuf->pixel;
M bitsy/screen.h => bitsy/screen.h +1 -0
@@ 1,2 1,3 @@
extern void blankscreen(int);
extern void flushmemscreen(Rectangle);
+
M bitsy/trap.c => bitsy/trap.c +47 -27
@@ 79,23 79,30 @@ trapinit(void)
void
trapdump(char *tag)
{
- iprint("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n",
+ print("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n",
tag, intrregs->icip, intrregs->icmr, intrregs->iclr,
intrregs->iccr, intrregs->icfp);
}
void
-dumpregs(Ureg *ur)
+warnregs(Ureg *ur, char *tag)
{
- iprint("r0 0x%.8lux r1 0x%.8lux r2 0x%.8lux r3 0x%.8lux\n",
+ char buf[512];
+ char *e = buf+sizeof(buf);
+ char *p;
+
+ p = seprint(buf, e, "%s:\n", tag);
+ p = seprint(p, e, "r0 0x%.8lux r1 0x%.8lux r2 0x%.8lux r3 0x%.8lux\n",
ur->r0, ur->r1, ur->r2, ur->r3);
- iprint("r4 0x%.8lux r5 0x%.8lux r6 0x%.8lux r7 0x%.8lux\n",
+ p = seprint(p, e, "r4 0x%.8lux r5 0x%.8lux r6 0x%.8lux r7 0x%.8lux\n",
ur->r4, ur->r5, ur->r6, ur->r7);
- iprint("r8 0x%.8lux r9 0x%.8lux r10 0x%.8lux r11 0x%.8lux\n",
+ p = seprint(p, e, "r8 0x%.8lux r9 0x%.8lux r10 0x%.8lux r11 0x%.8lux\n",
ur->r8, ur->r9, ur->r10, ur->r11);
- iprint("r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n",
+ p = seprint(p, e, "r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n",
ur->r12, ur->r13, ur->r14);
- iprint("type %.8lux psr %.8lux pc %.8lux\n", ur->type, ur->psr, ur->pc);
+ seprint(p, e, "type %.8lux psr %.8lux pc %.8lux\n",
+ ur->type, ur->psr, ur->pc);
+ print("%s", buf);
}
/*
@@ 131,29 138,36 @@ faultarm(Ureg *ureg, ulong va, int user, int read)
insyscall = up->insyscall;
up->insyscall = 1;
-//peekmmu(va);
n = fault(va, read);
-//iprint("fault returns %d\n", n);
if(n < 0){
if(!user){
- dumpregs(ureg);
- panic("fault: 0x%lux\n", va);
+ warnregs(ureg, "kernel fault");
+ panic("fault: kernel accessing 0x%lux\n", va);
}
- dumpregs(ureg);
- sprint(buf, "sys: trap: fault %s va=0x%lux",
- read? "read" : "write", va);
+// warnregs(ureg, "user fault");
+ sprint(buf, "sys: trap: fault %s va=0x%lux", read ? "read" : "write", va);
postnote(up, 1, buf, NDebug);
}
up->insyscall = insyscall;
}
-/* all Pabt+1 faults are caused by loads or stores. The Lbit of
- * the instruction distinquishes between them.
+/*
+ * returns 1 if the instruction writes memory, 0 otherwise
*/
-enum
+int
+writetomem(ulong inst)
{
- Lbit = 1<<20, /* load instruction */
-};
+ /* swap always write memory */
+ if((inst & 0x0FC00000) == 0x01000000)
+ return 1;
+
+ /* loads and stores are distinguished by bit 20 */
+ if(inst & (1<<20))
+ return 0;
+
+ return 1;
+}
+
/*
* here on all exceptions other than syscall (SWI)
@@ 179,18 193,21 @@ trap(Ureg *ureg)
else
ureg->pc -= 4;
+ if((user && (ureg->r13 & 0xf0000000)) || (ureg->psr & 0x10) != 0x10){
+ warnregs(ureg, "wierd ureg");
+ panic("bad ureg\n");
+ }
+
switch(ureg->type){
default:
panic("unknown trap");
break;
case PsrMabt: /* prefetch fault */
-print("%d: prefetch abort at 0x%lux\n", m->lastpid, ureg->pc);
faultarm(ureg, ureg->pc, user, 1);
break;
case PsrMabt+1: /* data fault */
va = getfar();
inst = *(ulong*)(ureg->pc);
-print("%d: data fault pc 0x%lux(0x%lux) va 0x%lux fsr 0x%lux\n", m->lastpid, ureg->pc, inst, va, getfsr());
switch(getfsr() & 0xf){
case 0x0:
panic("vector exception at %lux\n", ureg->pc);
@@ 218,21 235,23 @@ print("%d: data fault pc 0x%lux(0x%lux) va 0x%lux fsr 0x%lux\n", m->lastpid, ure
case 0x5:
case 0x7:
/* translation fault, i.e., no pte entry */
- faultarm(ureg, va, user, inst & Lbit);
+ faultarm(ureg, va, user, !writetomem(inst));
break;
case 0x9:
case 0xb:
/* domain fault, accessing something we shouldn't */
if(user){
- sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va);
+ sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n",
+ ureg->pc, va);
postnote(up, 1, buf, NDebug);
} else
- panic("kernel access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va);
+ panic("kernel access violation: pc 0x%lux va 0x%lux\n",
+ ureg->pc, va);
break;
case 0xd:
case 0xf:
/* permission error, copy on write or real permission error */
- faultarm(ureg, va, user, inst & Lbit);
+ faultarm(ureg, va, user, !writetomem(inst));
break;
}
break;
@@ 552,10 571,11 @@ forkchild(Proc *p, Ureg *ureg)
{
Ureg *cureg;
+//print("%lud setting up for forking child %lud\n", up->pid, p->pid);
p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg);
p->sched.pc = (ulong)forkret;
- cureg = (Ureg*)(p->sched.sp+2*BY2WD);
+ cureg = (Ureg*)(p->sched.sp);
memmove(cureg, ureg, sizeof(Ureg));
/* syscall returns 0 for child */
@@ 582,7 602,7 @@ execregs(ulong entry, ulong ssize, ulong nargs)
memset(ureg, 0, 15*sizeof(ulong));
ureg->r13 = (ulong)sp;
ureg->pc = entry;
-print("execregs pc 0x%lux sp 0x%lux\n", ureg->pc, ureg->r13);
+//print("%lud: EXECREGS pc 0x%lux sp 0x%lux\n", up->pid, ureg->pc, ureg->r13);
return USTKTOP-BY2WD; /* address of user-level clock */
}
M boot/local.c => boot/local.c +18 -8
@@ 4,6 4,7 @@
static char diskname[2*NAMELEN];
static char *disk;
+static char **args;
void
configlocal(Method *mp)
@@ 56,12 57,12 @@ authlocal(void)
int
connectlocal(void)
{
- int p[2];
+ int i, p[2];
Dir dir;
char d[DIRLEN];
char partition[2*NAMELEN];
char *dev;
- char *args[16], **argp;
+ char **arg, **argp;
if(stat("/kfs", d) < 0)
return -1;
@@ 87,17 88,26 @@ connectlocal(void)
case -1:
fatal("fork");
case 0:
- dup(p[0], 0);
- dup(p[1], 1);
- close(p[0]);
- close(p[1]);
- argp = args;
+ arg = malloc((bargc+5)*sizeof(char*));
+ argp = arg;
*argp++ = "kfs";
*argp++ = "-f";
*argp++ = partition;
*argp++ = "-s";
+ for(i=1; i<bargc; i++)
+ *argp++ = bargv[i];
*argp = 0;
- exec("/kfs", args);
+
+ print("kfs");
+ for(argp=arg; *argp; argp++)
+ print(" %s", *argp);
+ print("\n");
+
+ dup(p[0], 0);
+ dup(p[1], 1);
+ close(p[0]);
+ close(p[1]);
+ exec("/kfs", arg);
fatal("can't exec kfs");
default:
break;
A pc/apm.c => pc/apm.c +160 -0
@@ 0,0 1,160 @@
+/*
+ * Advanced Power Management 1.2 driver
+ */
+
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+extern int apmfarcall(ushort, ulong, Ureg*); /* apmjump.s */
+
+static int
+getreg(ulong *reg, ISAConf *isa, char *name)
+{
+ int i;
+ int nl;
+
+ nl = strlen(name);
+ for(i=0; i<isa->nopt; i++){
+ if(cistrncmp(isa->opt[i], name, nl)==0 && isa->opt[i][nl] == '='){
+ *reg = strtoul(isa->opt[i]+nl+1, nil, 16);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+/*
+ * Segment descriptors look like this.
+ *
+ * d1: [base 31:24] [gran] [is32bit] [0] [unused] [limit 19:16]
+ [present] [privlev] [type 3:0] [base 23:16]
+ * d0: [base 15:00] [limit 15:00]
+ *
+ * gran is 0 for 1-byte granularity, 1 for 4k granularity
+ * type is 0 for system segment, 1 for code/data.
+ *
+ * clearly we know way too much about the memory unit.
+ *
+ * what a crock.
+ */
+static void
+setgdt(int sel, ulong base, ulong limit, int flag)
+{
+ if(sel < 0 || sel >= NGDT)
+ panic("setgdt");
+
+ base = (ulong)KADDR(base);
+ m->gdt[sel].d0 = (base<<16) | (limit&0xFFFF);
+ m->gdt[sel].d1 = (base&0xFF000000) | (limit&0x000F0000) |
+ ((base>>16)&0xFF) | SEGP | SEGPL(0) | flag;
+}
+
+static void
+loadgdt(void)
+{
+ ulong x;
+ ushort ptr[3];
+
+ ptr[0] = sizeof(m->gdt);
+ x = (ulong)m->gdt;
+ ptr[1] = x & 0xFFFF;
+ ptr[2] = (x>>16) & 0xFFFF;
+ lgdt(ptr);
+}
+
+/*
+ * Must run before mmuinit, since we modify the GDT that
+ * we want the processor to inherit. I think (but am not sure)
+ * that we could run after mmuinit on processor 0 and just
+ * modify m->gdt and then call lgdt() as mmuinit() does,
+ * but this is a bit simpler and safer.
+ */
+static ulong ax, cx, dx, di, ebx, esi;
+static Ureg apmu;
+static long
+apmread(Chan*, void *a, long n, vlong off)
+{
+ if(off < 0)
+ error("badarg");
+
+ if(n+off > sizeof apmu)
+ n = sizeof apmu - off;
+ if(n <= 0)
+ return 0;
+ memmove(a, (char*)&apmu+off, n);
+ return n;
+}
+
+static long
+apmwrite(Chan*, void *a, long n, vlong off)
+{
+ int s;
+ if(off || n != sizeof apmu){
+// if(n == 5 && strncmp(a, "ether", 5) == 0){
+// ether589reset();
+// return 5;
+// }
+ error("write a Ureg");
+ }
+
+ memmove(&apmu, a, sizeof apmu);
+ s = splhi();
+ apmfarcall(APMCSEL, ebx, &apmu);
+ splx(s);
+ return n;
+}
+
+void
+apmlink(void)
+{
+ ISAConf isa;
+ char *s;
+
+ if(isaconfig("apm", 0, &isa) == 0)
+ return;
+
+ /*
+ * APM info passed from boot loader.
+ * Now we need to set up the GDT entries for APM.
+ *
+ * AX = 32-bit code segment base address
+ * EBX = 32-bit code segment offset
+ * CX = 16-bit code segment base address
+ * DX = 32-bit data segment base address
+ * ESI = <16-bit code segment length> <32-bit code segment length> (hi then lo)
+ * DI = 32-bit data segment length
+ */
+
+ if(getreg(&ax, &isa, s="ax") < 0
+ || getreg(&ebx, &isa, s="ebx") < 0
+ || getreg(&cx, &isa, s="cx") < 0
+ || getreg(&dx, &isa, s="dx") < 0
+ || getreg(&esi, &isa, s="esi") < 0
+ || getreg(&di, &isa, s="di") < 0){
+ print("apm: missing register %s\n", s);
+ return;
+ }
+
+ /*
+ * We are required by the BIOS to set up three consecutive segments,
+ * one for the APM 32-bit code, one for the APM 16-bit code, and
+ * one for the APM data. The BIOS handler uses the code segment it
+ * get called with to determine the other two segment selector.
+ */
+ setgdt(APMCSEG, ax<<4, ((esi&0xFFFF)-1)&0xFFFF, SEGEXEC|SEGR|SEGD);
+ setgdt(APMCSEG16, cx<<4, ((esi>>16)-1)&0xFFFF, SEGEXEC|SEGR);
+ setgdt(APMDSEG, dx<<4, (di-1)&0xFFFF, SEGDATA|SEGW|SEGD);
+ loadgdt();
+
+ addarchfile("apm", 0660, apmread, apmwrite);
+
+print("apm0: configured cbase %.8lux off %.8lux\n", ax<<4, ebx);
+
+ return;
+}
+
A pc/apmjump.s => pc/apmjump.s +98 -0
@@ 0,0 1,98 @@
+/*
+ * Far call, absolute indirect.
+ * The argument is the offset.
+ * We use a global structure for the jump params,
+ * so this is *not* reentrant or thread safe.
+ */
+
+#include "mem.h"
+
+#define SSOVERRIDE BYTE $0x36
+#define CSOVERRIDE BYTE $0x2E
+#define RETF BYTE $0xCB
+
+GLOBL apmjumpstruct+0(SB), $8
+
+TEXT fortytwo(SB), $0
+ MOVL $42, AX
+ RETF
+
+TEXT getcs(SB), $0
+ PUSHL CS
+ POPL AX
+ RET
+
+TEXT apmfarcall(SB), $0
+ /*
+ * We call push and pop ourselves.
+ * As soon as we do the first push or pop,
+ * we can't use FP anymore.
+ */
+ MOVL off+4(FP), BX
+ MOVL seg+0(FP), CX
+ MOVL BX, apmjumpstruct+0(SB)
+ MOVL CX, apmjumpstruct+4(SB)
+
+ /* load necessary registers from Ureg */
+ MOVL ureg+8(FP), DI
+ MOVL 28(DI), AX
+ MOVL 16(DI), BX
+ MOVL 24(DI), CX
+ MOVL 20(DI), DX
+
+ /* save registers, segments */
+ PUSHL DS
+ PUSHL ES
+ PUSHL FS
+ PUSHL GS
+ PUSHL BP
+ PUSHL DI
+
+ /*
+ * paranoia: zero the segments, since it's the
+ * BIOS's responsibility to initialize them.
+ * (trick picked up from Linux driver).
+ PUSHL DX
+ XORL DX, DX
+ PUSHL DX
+ POPL DS
+ PUSHL DX
+ POPL ES
+ PUSHL DX
+ POPL FS
+ PUSHL DX
+ POPL GS
+ POPL DX
+ */
+
+ PUSHL $APMDSEG
+ POPL DS
+
+ /*
+ * The actual call.
+ */
+ CSOVERRIDE; BYTE $0xFF; BYTE $0x1D
+ LONG $apmjumpstruct+0(SB)
+
+ /* restore segments, registers */
+ POPL DI
+ POPL BP
+ POPL GS
+ POPL FS
+ POPL ES
+ POPL DS
+
+ PUSHFL
+ POPL 64(DI)
+
+ /* store interesting registers back in Ureg */
+ MOVL AX, 28(DI)
+ MOVL BX, 16(DI)
+ MOVL CX, 24(DI)
+ MOVL DX, 20(DI)
+ MOVL SI, 4(DI)
+
+ PUSHFL
+ POPL AX
+ ANDL $1, AX /* carry flag */
+ RET
M pc/dat.h => pc/dat.h +1 -1
@@ 148,7 148,7 @@ struct Mach
ulong* pdb; /* page directory base for this processor (va) */
Tss* tss; /* tss for this processor */
- Segdesc gdt[6]; /* gdt for this processor */
+ Segdesc gdt[NGDT]; /* gdt for this processor */
Proc* proc; /* current process on this processor */
Proc* externup; /* extern register Proc *up */
M pc/devarch.c => pc/devarch.c +71 -28
@@ 7,7 7,6 @@
#include "ureg.h"
#include "../port/error.h"
-
typedef struct IOMap IOMap;
struct IOMap
{
@@ 28,23 27,68 @@ static struct
} iomap;
enum {
- Qdir,
- Qcputype,
- Qioalloc,
+ Qdir = CHDIR,
+ Qioalloc = 0,
Qiob,
Qiow,
Qiol,
- Qirqalloc,
+ Qbase,
+
+ Qmax = 16,
};
-static Dirtab ioallocdir[] = {
- "cputype", { Qcputype, 0 }, 0, 0444,
+typedef long Rdwrfn(Chan*, void*, long, vlong);
+
+static Rdwrfn *readfn[Qmax];
+static Rdwrfn *writefn[Qmax];
+
+static Dirtab archdir[Qmax] = {
"ioalloc", { Qioalloc, 0 }, 0, 0444,
"iob", { Qiob, 0 }, 0, 0660,
"iow", { Qiow, 0 }, 0, 0660,
"iol", { Qiol, 0 }, 0, 0660,
- "irqalloc", { Qirqalloc, 0}, 0, 0444,
};
+Lock archwlock; /* the lock is only for changing archdir */
+int narchdir = Qbase;
+
+/*
+ * Add a file to the #P listing. Once added, you can't delete it.
+ * You can't add a file with the same name as one already there,
+ * and you get a pointer to the Dirtab entry so you can do things
+ * like change the Qid version. Changing the Qid path is disallowed.
+ */
+Dirtab*
+addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
+{
+ int i;
+ Dirtab d;
+ Dirtab *dp;
+
+ memset(&d, 0, sizeof d);
+ strcpy(d.name, name);
+ d.perm = perm;
+
+ lock(&archwlock);
+ if(narchdir >= Qmax){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ for(i=0; i<narchdir; i++)
+ if(strcmp(archdir[i].name, name) == 0){
+ unlock(&archwlock);
+ return nil;
+ }
+
+ d.qid.path = narchdir;
+ archdir[narchdir] = d;
+ readfn[narchdir] = rdfn;
+ writefn[narchdir] = wrfn;
+ dp = &archdir[narchdir++];
+ unlock(&archwlock);
+
+ return dp;
+}
void
ioinit(void)
@@ 60,8 104,6 @@ ioinit(void)
ioalloc(0x10000, 1, 0, "dummy");
}
-static long cputyperead(char*, int, ulong);
-
//
// alloc some io port space and remember who it was
// alloced to. if port < 0, find a free region.
@@ 116,7 158,7 @@ ioalloc(int port, int size, int align, char *tag)
m->tag[sizeof(m->tag)-1] = 0;
*l = m;
- ioallocdir[0].qid.vers++;
+ archdir[0].qid.vers++;
unlock(&iomap);
return m->start;
@@ 139,7 181,7 @@ iofree(int port)
if((*l)->start > port)
break;
}
- ioallocdir[0].qid.vers++;
+ archdir[0].qid.vers++;
unlock(&iomap);
}
@@ 179,19 221,19 @@ archattach(char* spec)
int
archwalk(Chan* c, char* name)
{
- return devwalk(c, name, ioallocdir, nelem(ioallocdir), devgen);
+ return devwalk(c, name, archdir, narchdir, devgen);
}
static void
archstat(Chan* c, char* dp)
{
- devstat(c, dp, ioallocdir, nelem(ioallocdir), devgen);
+ devstat(c, dp, archdir, narchdir, devgen);
}
static Chan*
archopen(Chan* c, int omode)
{
- return devopen(c, omode, ioallocdir, nelem(ioallocdir), devgen);
+ return devopen(c, omode, archdir, narchdir, devgen);
}
static void
@@ 207,17 249,17 @@ enum
static long
archread(Chan *c, void *a, long n, vlong offset)
{
- char *p;
- IOMap *m;
- char buf[Linelen+1];
+ char buf[Linelen+1], *p;
int port;
ushort *sp;
ulong *lp;
+ IOMap *m;
+ Rdwrfn *fn;
- switch(c->qid.path & ~CHDIR){
+ switch(c->qid.path){
case Qdir:
- return devdirread(c, a, n, ioallocdir, nelem(ioallocdir), devgen);
+ return devdirread(c, a, n, archdir, narchdir, devgen);
case Qiob:
port = offset;
@@ 249,13 291,9 @@ archread(Chan *c, void *a, long n, vlong offset)
case Qioalloc:
break;
- case Qirqalloc:
- return irqallocread(a, n, offset);
-
- case Qcputype:
- return cputyperead(a, n, offset);
-
default:
+ if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
+ return fn(c, a, n, offset);
error(Eperm);
break;
}
@@ 282,10 320,11 @@ archread(Chan *c, void *a, long n, vlong offset)
static long
archwrite(Chan *c, void *a, long n, vlong offset)
{
+ char *p;
int port;
ushort *sp;
ulong *lp;
- char *p;
+ Rdwrfn *fn;
switch(c->qid.path & ~CHDIR){
@@ 317,6 356,8 @@ archwrite(Chan *c, void *a, long n, vlong offset)
return n*4;
default:
+ if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
+ return fn(c, a, n, offset);
error(Eperm);
break;
}
@@ 537,7 578,7 @@ cpuidentify(void)
}
static long
-cputyperead(char *a, int n, ulong offset)
+cputyperead(Chan*, void *a, long n, vlong offset)
{
char str[32];
ulong mhz;
@@ 592,6 633,8 @@ archinit(void)
if(X86FAMILY(m->cpuidax) >= 5)
coherence = wbflush;
+
+ addarchfile("cputype", 0444, cputyperead, nil);
}
void
M pc/fns.h => pc/fns.h +1 -1
@@ 2,6 2,7 @@
void aamloop(int);
void addconf(char*, char*);
+Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong));
//void addscsilink(char*, Scsiio (*)(int, ISAConf*));
void archinit(void);
void bootargs(ulong);
@@ 59,7 60,6 @@ void ioinit(void);
int iounused(int, int);
int ioalloc(int, int, int, char*);
int iprint(char*, ...);
-int irqallocread(char*, long, vlong);
int isaconfig(char*, int, ISAConf*);
void kbdinit(void);
void lgdt(ushort[3]);
M pc/mem.h => pc/mem.h +9 -0
@@ 63,6 63,11 @@
#define UDSEG 3 /* user data/stack */
#define UESEG 4 /* user executable */
#define TSSSEG 5 /* task segment */
+#define APMCSEG 6 /* APM code segment */
+#define APMCSEG16 7 /* APM 16-bit code segment */
+#define APMDSEG 8 /* APM data segment */
+#define NGDT 10 /* number of GDT entries required */
+/* #define APM40SEG 8 /* APM segment 0x40 */
#define SELGDT (0<<2) /* selector is in gdt */
#define SELLDT (1<<2) /* selector is in ldt */
@@ 75,6 80,10 @@
#define UESEL SELECTOR(UESEG, SELGDT, 3)
#define UDSEL SELECTOR(UDSEG, SELGDT, 3)
#define TSSSEL SELECTOR(TSSSEG, SELGDT, 0)
+#define APMCSEL SELECTOR(APMCSEG, SELGDT, 0)
+#define APMCSEL16 SELECTOR(APMCSEG16, SELGDT, 0)
+#define APMDSEL SELECTOR(APMDSEG, SELGDT, 0)
+/* #define APM40SEL SELECTOR(APM40SEG, SELGDT, 0) */
/*
* fields in segment descriptors
M pc/trap.c => pc/trap.c +8 -6
@@ 50,19 50,19 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
iunlock(&vctllock);
}
-int
-irqallocread(char *buf, long n, vlong offset)
+static long
+irqallocread(Chan*, void *vbuf, long n, vlong offset)
{
- int vno;
- Vctl *v;
+ char *buf, *p, str[11+1+NAMELEN+1];
+ int m, vno;
long oldn;
- char str[11+1+NAMELEN+1], *p;
- int m;
+ Vctl *v;
if(n < 0 || offset < 0)
error(Ebadarg);
oldn = n;
+ buf = vbuf;
for(vno=0; vno<nelem(vctl); vno++){
for(v=vctl[vno]; v; v=v->next){
m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, NAMELEN, v->name);
@@ 164,6 164,8 @@ trapinit(void)
trapenable(VectorPF, fault386, 0, "fault386");
nmienable();
+
+ addarchfile("irqalloc", 0444, irqallocread, nil);
}
static char* excname[32] = {
M port/log.c => port/log.c +47 -18
@@ 7,10 7,6 @@
static char Ebadlogctl[] = "unknown log ctl message";
-enum {
- Nlog = 4*1024,
-};
-
void
logopen(Log *alog)
{
@@ 20,10 16,15 @@ logopen(Log *alog)
nexterror();
}
if(alog->opens == 0){
+ if(alog->nlog == 0)
+ alog->nlog = 4*1024;
+ if(alog->minread == 0)
+ alog->minread = 1;
if(alog->buf == nil)
- alog->buf = malloc(Nlog);
+ alog->buf = malloc(alog->nlog);
alog->rptr = alog->buf;
- alog->end = alog->buf + Nlog;
+ alog->end = alog->buf + alog->nlog;
+ alog->len = 0;
}
alog->opens++;
unlock(alog);
@@ 52,7 53,7 @@ logready(void *a)
{
Log *alog = a;
- return alog->len;
+ return alog->len >= alog->minread;
}
long
@@ 69,7 70,7 @@ logread(Log *alog, void *a, ulong, long n)
for(;;){
lock(alog);
- if(alog->len){
+ if(alog->len >= alog->minread || alog->len >= n){
if(n > alog->len)
n = alog->len;
d = 0;
@@ 132,24 133,22 @@ logctl(Log *alog, int argc, char *argv[], Logflag *flags)
}
void
-log(Log *alog, int mask, char *fmt, ...)
+logn(Log *alog, int mask, void *buf, int n)
{
- char buf[128], *t, *fp;
- int i, n;
- va_list arg;
+ char *fp, *t;
+ int dowake, i;
if(!(alog->logmask & mask))
return;
- va_start(arg, fmt);
- n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
- va_end(arg);
-
if(alog->opens == 0)
return;
+ if(n > alog->nlog)
+ return;
+
lock(alog);
- i = alog->len + n - Nlog;
+ i = alog->len + n - alog->nlog;
if(i > 0){
alog->len -= i;
alog->rptr += i;
@@ 164,7 163,37 @@ log(Log *alog, int mask, char *fmt, ...)
t = alog->buf + (t - alog->end);
*t++ = *fp++;
}
+ dowake = alog->len >= alog->minread;
unlock(alog);
- wakeup(&alog->readr);
+ if(dowake)
+ wakeup(&alog->readr);
+}
+
+void
+vlog(Log *alog, int mask, char *fmt, va_list arg)
+{
+ char buf[128];
+ int n;
+
+ if(!(alog->logmask & mask))
+ return;
+
+ if(alog->opens == 0)
+ return;
+
+ n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
+
+ logn(alog, mask, buf, n);
+}
+
+void
+log(Log *alog, int mask, char *fmt, ...)
+{
+ va_list arg;
+
+ va_start(arg, fmt);
+ vlog(alog, mask, fmt, arg);
+ va_end(arg);
}
+
M port/portdat.h => port/portdat.h +2 -0
@@ 698,6 698,8 @@ struct Log {
char *end;
char *rptr;
int len;
+ int nlog;
+ int minread;
int logmask; /* mask of things to debug */
M port/portfns.h => port/portfns.h +2 -0
@@ 153,8 153,10 @@ void lockinit(void);
void logopen(Log*);
void logclose(Log*);
char* logctl(Log*, int, char**, Logflag*);
+void logn(Log*, int, void*, int);
long logread(Log*, void*, ulong, long);
void log(Log*, int, char*, ...);
+void vlog(Log*, int, char*, va_list);
Page* lookpage(Image*, ulong);
void machinit(void);
void* mallocz(ulong, int);
M port/proc.c => port/proc.c +1 -0
@@ 1056,6 1056,7 @@ kproc(char *name, void (*func)(void *), void *arg)
* any mmu info about this process is now stale
* and has to be discarded.
*/
+ p->newtlb = 1;
flushmmu();
}