From b1beaa16e1e4f6ab50aaf756d291286c407d10e6 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Mon, 4 Sep 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-09-04 --- bitsy/devuart.c | 506 ++++++++++++++++++++++++++++++++++++++++++++++++ bitsy/fns.h | 1 + bitsy/io.h | 117 +---------- bitsy/l.s | 132 +++++++------ bitsy/main.c | 7 +- bitsy/mem.h | 17 +- pc/vga3dfx.c | 78 ++++++++ pc/vgas3.c | 11 +- pc/vgasavage.c | 52 ++++- port/chan.c | 2 +- port/fault.c | 2 +- port/sysproc.c | 4 +- 12 files changed, 740 insertions(+), 189 deletions(-) create mode 100644 bitsy/devuart.c create mode 100644 pc/vga3dfx.c diff --git a/bitsy/devuart.c b/bitsy/devuart.c new file mode 100644 index 0000000000000000000000000000000000000000..a65382823473625b0ea4efdacf5b669d7ca00a95 --- /dev/null +++ b/bitsy/devuart.c @@ -0,0 +1,506 @@ +#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" + +enum +{ + Nuart = 1, + Stagesize= 1024, +}; + +/* hardware registers */ +typedef struct Uartregs Uartregs; +struct Uartregs +{ + ulong ctl0; + ulong ctl1; + ulong ctl2; + ulong ctl3; + uchar dummyd[4]; + ulong data; + uchar dummyf[4]; + ulong status0; + ulong status1; +}; +#define UART3REGS IOA(Uartregs, 0x50000) + +/* ctl0 bits */ +enum +{ + XmitNotFull = (1 << 2), +}; + +/* software representation */ +typedef struct Uart Uart; +struct Uart +{ + QLock; + int opens; + + int enabled; + Uart *elist; /* next enabled interface */ + char name[NAMELEN]; + + uchar sticky[8]; /* sticky write register values */ + uchar osticky[8]; /* kernel saved sticky write register values */ + ulong port; /* io ports */ + ulong freq; /* clock frequency */ + uchar mask; /* bits/char */ + int dev; + int baud; /* baud rate */ + + uchar istat; /* last istat read */ + int frame; /* framing errors */ + int overrun; /* rcvr overruns */ + + /* buffers */ + int (*putc)(Queue*, int); + Queue *iq; + Queue *oq; + + Lock flock; /* fifo */ + uchar fifoon; /* fifo's enabled */ + uchar type; /* chip version */ + + Lock rlock; /* receive */ + uchar istage[Stagesize]; + uchar *ip; + uchar *ie; + + int haveinput; + + Lock tlock; /* transmit */ + uchar ostage[Stagesize]; + uchar *op; + uchar *oe; + + int modem; /* hardware flow control on */ + int xonoff; /* software flow control on */ + int blocked; + int cts, dsr, dcd, dcdts; /* keep track of modem status */ + int ctsbackoff; + int hup_dsr, hup_dcd; /* send hangup upstream? */ + int dohup; + + int kinuse; /* device in use by kernel */ + + Rendez r; +}; +static Uart* uart[Nuart]; +static int nuart; + +static Dirtab *uartdir; +static int uartndir; + +/* + * means the kernel is using this for debugging output + */ +static char Ekinuse[] = "device in use by kernel"; + +/* + * default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts, + * transmit and receive enabled, interrupts disabled. + */ +static void +uartsetup0(Uart *p) +{ + memset(p->sticky, 0, sizeof(p->sticky)); + /* + * set rate to 9600 baud. + * 8 bits/character. + * 1 stop bit. + * interrupts enabled. + */ +// p->sticky[Format] = Bits8; +// uartwrreg(p, Format, 0); +// p->sticky[Mctl] |= Inton; +// uartwrreg(p, Mctl, 0x0); + +// uartsetbaud(p, 9600); + +// p->iq = qopen(4*1024, 0, uartflow, p); +// p->oq = qopen(4*1024, 0, uartkick, p); + if(p->iq == nil || p->oq == nil) + panic("uartsetup0"); + + p->ip = p->istage; + p->ie = &p->istage[Stagesize]; + p->op = p->ostage; + p->oe = p->ostage; +} + +/* + * called by main() to create a new duart + */ +void +uartsetup(ulong port, ulong freq, char *name, int type) +{ + Uart *p; + + if(nuart >= Nuart) + return; + + p = xalloc(sizeof(Uart)); + uart[nuart] = p; + strcpy(p->name, name); + p->dev = nuart; + nuart++; + p->port = port; + p->freq = freq; + p->type = type; + uartsetup0(p); +} + +static void +uartenable(Uart *p) +{ + USED(p); +} + +static void +uartdisable(Uart *p) +{ + USED(p); +} + +static long +uartstatus(Chan*, Uart *p, void *buf, long n, long offset) +{ + USED(p); +// "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", + return readstr(offset, buf, n, ""); +} + +static void +setlength(int i) +{ + Uart *p; + + if(i > 0){ + p = uart[i]; + if(p && p->opens && p->iq) + uartdir[3*i].length = qlen(p->iq); + } else for(i = 0; i < nuart; i++){ + p = uart[i]; + if(p && p->opens && p->iq) + uartdir[3*i].length = qlen(p->iq); + } +} + +static void +uartreset(void) +{ + int i; + Dirtab *dp; + + nuart = Nuart; + + uartndir = 3*nuart; + uartdir = xalloc(uartndir * sizeof(Dirtab)); + dp = uartdir; + for(i = 0; i < nuart; i++){ + /* 3 directory entries per port */ + sprint(dp->name, "eia%d", i); + dp->qid.path = NETQID(i, Ndataqid); + dp->perm = 0660; + dp++; + sprint(dp->name, "eia%dctl", i); + dp->qid.path = NETQID(i, Nctlqid); + dp->perm = 0660; + dp++; + sprint(dp->name, "eia%dstat", i); + dp->qid.path = NETQID(i, Nstatqid); + dp->perm = 0444; + dp++; + } + +} + + +static Chan* +uartattach(char *spec) +{ + return devattach('t', spec); +} + +static int +uartwalk(Chan *c, char *name) +{ + return devwalk(c, name, uartdir, uartndir, devgen); +} + +static void +uartstat(Chan *c, char *dp) +{ + if(NETTYPE(c->qid.path) == Ndataqid) + setlength(NETID(c->qid.path)); + devstat(c, dp, uartdir, uartndir, devgen); +} + +static Chan* +uartopen(Chan *c, int omode) +{ + Uart *p; + + c = devopen(c, omode, uartdir, uartndir, devgen); + + switch(NETTYPE(c->qid.path)){ + case Nctlqid: + case Ndataqid: + p = uart[NETID(c->qid.path)]; + if(p->kinuse) + error(Ekinuse); + qlock(p); + if(p->opens++ == 0){ + uartenable(p); + qreopen(p->iq); + qreopen(p->oq); + } + qunlock(p); + break; + } + + return c; +} + +static void +uartclose(Chan *c) +{ + Uart *p; + + if(c->qid.path & CHDIR) + return; + if((c->flag & COPEN) == 0) + return; + switch(NETTYPE(c->qid.path)){ + case Ndataqid: + case Nctlqid: + p = uart[NETID(c->qid.path)]; + if(p->kinuse) + error(Ekinuse); + qlock(p); + if(--(p->opens) == 0){ + uartdisable(p); + qclose(p->iq); + qclose(p->oq); + p->ip = p->istage; + p->dcd = p->dsr = p->dohup = 0; + } + qunlock(p); + break; + } +} + +static long +uartread(Chan *c, void *buf, long n, vlong off) +{ + Uart *p; + ulong offset = off; + + if(c->qid.path & CHDIR){ + setlength(-1); + return devdirread(c, buf, n, uartdir, uartndir, devgen); + } + + p = uart[NETID(c->qid.path)]; + if(p->kinuse) + error(Ekinuse); + switch(NETTYPE(c->qid.path)){ + case Ndataqid: + return qread(p->iq, buf, n); + case Nctlqid: + return readnum(offset, buf, n, NETID(c->qid.path), NUMSIZE); + case Nstatqid: + return uartstatus(c, p, buf, n, offset); + } + + return 0; +} + +static void +uartctl(Uart *p, char *cmd) +{ + int i, n; + char *f[32]; + int nf; + + /* let output drain for a while */ + for(i = 0; i < 16 && qlen(p->oq); i++) + tsleep(&p->r, (int(*)(void*))qlen, p->oq, 125); + + nf = getfields(cmd, f, nelem(f), 1, " \t\n"); + + for(i = 0; i < nf; i++){ + + if(strncmp(f[i], "break", 5) == 0){ +// uartbreak(p, 0); + continue; + } + + n = atoi(f[i]+1); + switch(*f[i]){ + case 'B': + case 'b': +// uartsetbaud(p, n); + break; + case 'C': + case 'c': +// uartdcdhup(p, n); + break; + case 'D': + case 'd': +// uartdtr(p, n); + break; + case 'E': + case 'e': +// uartdsrhup(p, n); + break; + case 'f': + case 'F': + qflush(p->oq); + break; + case 'H': + case 'h': + qhangup(p->iq, 0); + qhangup(p->oq, 0); + break; + case 'i': + case 'I': +// lock(&p->flock); +// uartfifo(p, n); +// unlock(&p->flock); + break; + case 'L': + case 'l': +// uartbits(p, n); + break; + case 'm': + case 'M': +// uartmflow(p, n); + break; + case 'n': + case 'N': + qnoblock(p->oq, n); + break; + case 'P': + case 'p': +// uartparity(p, *(cmd+1)); + break; + case 'K': + case 'k': +// uartbreak(p, n); + break; + case 'R': + case 'r': +// uartrts(p, n); + break; + case 'Q': + case 'q': + qsetlimit(p->iq, n); + qsetlimit(p->oq, n); + break; + case 'T': + case 't': +// uartdcdts(p, n); + break; + case 'W': + case 'w': + /* obsolete */ + break; + case 'X': + case 'x': + ilock(&p->tlock); + p->xonoff = n; + iunlock(&p->tlock); + break; + } + } +} + +static long +uartwrite(Chan *c, void *buf, long n, vlong) +{ + Uart *p; + char cmd[32]; + + if(c->qid.path & CHDIR) + error(Eperm); + + p = uart[NETID(c->qid.path)]; + if(p->kinuse) + error(Ekinuse); + + switch(NETTYPE(c->qid.path)){ + case Ndataqid: + return qwrite(p->oq, buf, n); + case Nctlqid: + if(n >= sizeof(cmd)) + n = sizeof(cmd)-1; + memmove(cmd, buf, n); + cmd[n] = 0; + uartctl(p, cmd); + return n; + } +} + +static void +uartwstat(Chan *c, char *dp) +{ + Dir d; + Dirtab *dt; + + if(!iseve()) + error(Eperm); + if(CHDIR & c->qid.path) + error(Eperm); + if(NETTYPE(c->qid.path) == Nstatqid) + error(Eperm); + + dt = &uartdir[3 * NETID(c->qid.path)]; + convM2D(dp, &d); + d.mode &= 0666; + dt[0].perm = dt[1].perm = d.mode; +} + +Dev uartdevtab = { + 't', + "uart", + + uartreset, + devinit, + uartattach, + devclone, + uartwalk, + uartstat, + uartopen, + devcreate, + uartclose, + uartread, + devbread, + uartwrite, + devbwrite, + devremove, + uartwstat, +}; + +void +putuartstr(char *str) +{ + Uartregs *ur; + + ur = UART3REGS; + while(*str){ + /* wait for output ready */ + while(ur->status1 & XmitNotFull) + ; + ur->data = *str++; + + } +} diff --git a/bitsy/fns.h b/bitsy/fns.h index 672769b76ae2dbc06ce8cba7664a331eacd7581a..bf63b7404d2f40985fb57ecbd5ce9d47717ffe63 100644 --- a/bitsy/fns.h +++ b/bitsy/fns.h @@ -15,6 +15,7 @@ int iprint(char*, ...); #define procrestore(p) void procsave(Proc*); void procsetup(Proc*); +void putuartstr(char*); void screeninit(void); int screenprint(char*, ...); /* debugging */ void (*screenputs)(char*, int); diff --git a/bitsy/io.h b/bitsy/io.h index b379ee0f18cff66f76b33eadd774b57479a5d71d..6f32142dfbe829652e5aaecfc82c053bdbefba3f 100644 --- a/bitsy/io.h +++ b/bitsy/io.h @@ -1,112 +1,5 @@ -/* replicated in part from the boot code, for now */ - -#define XTAL 3686400 -#define CORECLOCK 199066000 -#define MONITOR 0x00020000 - -#define SYS_REGBASE 0x90000000 - -#define SYSR_FIRQ 0x1000 -#define SYSR_IRQ 0x1400 -#define SIRQ_PCI (1<<2) -#define SIRQ_UART (1<<8) -#define SYSR_UART_SR 0x3400 /* UART Status Register */ -#define SYSR_UART_CR 0x3800 /* UART Control Register */ -#define SYSR_UART_DR 0x3C00 /* UART Data Register */ - -#define SYS_FIRQ (0x90000000+SYSR_FIRQ) -#define SYS_IRQ (0x90000000+SYSR_IRQ) - -#define PCI_REGBASE 0x42000000 -#define PCI_IPXRESET 0x07C -#define PCI_IRQSTATUS 0x180 -#define PCI_IRQRSTATUS 0x184 -#define PCI_IRQENABLE 0x188 -#define PCI_IRQENA_SET 0x188 -#define PCI_IRQENA_CLR 0x18C -#define PCI_IRQSOFT 0x190 -#define PCI_FIRQSTATUS 0x280 -#define PCI_FIRQRSTATUS 0x284 -#define PCI_FIRQENABLE 0x288 -#define PCI_FIRQENA_SET 0x288 -#define PCI_FIRQENA_CLR 0x28C -#define PCI_FIRQSOFT 0x290 -#define PCI_TIMERLOAD 0x300 -#define PCI_TIMERVALUE 0x304 -#define PCI_TIMERCTL 0x308 -#define PCI_TIMERCLEAR 0x30C - -#define TIMER_OFF 0x020 - -#define TIMER1_LOAD (PCI_REGBASE+PCI_TIMERLOAD) -#define TIMER1_VALUE (PCI_REGBASE+PCI_TIMERVALUE) -#define TIMER1_CTL (PCI_REGBASE+PCI_TIMERCTL) -#define TIMER1_CLEAR (PCI_REGBASE+PCI_TIMERCLEAR) - -#define TIMER_PERIODIC (1<<6) -#define TIMER_ENABLE (1<<7) - -#define IRQ_STATUS (PCI_REGBASE+PCI_IRQSTATUS) -#define IRQ_ENABLE_SET (PCI_REGBASE+PCI_IRQENA_SET) -#define IRQ_ENABLE_CLR (PCI_REGBASE+PCI_IRQENA_CLR) - -#define FIRQ_OFF 0x100 - -#define IRQ_SOFT 1 -#define IRQ_TIMER1 4 -#define IRQ_TIMER2 5 -#define IRQ_TIMER3 6 -#define IRQ_TIMER4 7 -#define IRQ_DOOR 15 -#define IRQ_DMA1 16 -#define IRQ_DMA2 17 -#define IRQ_PCI 18 -#define IRQ_DMA1NB 20 -#define IRQ_DMA2NB 21 -#define IRQ_BIST 22 -#define IRQ_SERR 23 -#define IRQ_I2OIN 25 -#define IRQ_POWER 26 -#define IRQ_DTIMER 27 -#define IRQ_PARITY 28 -#define IRQ_MABORT 29 -#define IRQ_TABORT 30 -#define IRQ_DPARITY 31 - -#define PCI_CONF1_BASE 0x52000000 -#define PCI_CONF0_BASE 0x53000000 -#define PCI_IO_BASE 0x54000000 -#define PCI_IO_SIZE 0x00010000 -#define PCI_MEM_BASE 0x60000000 -#define PCI_MEM_SIZE 0x20000000 - -/* MMU. */ - -#define MMUCR_M_ENABLE (1<<0) /* MMU enable */ -#define MMUCR_A_ENABLE (1<<1) /* Address alignment fault enable */ -#define MMUCR_C_ENABLE (1<<2) /* (data) cache enable */ -#define MMUCR_W_ENABLE (1<<3) /* write buffer enable */ -#define MMUCR_PROG32 (1<<4) /* PROG32 */ -#define MMUCR_DATA32 (1<<5) /* DATA32 */ -#define MMUCR_L_ENABLE (1<<6) /* Late abort on earlier CPUs */ -#define MMUCR_BIGEND (1<<7) /* Big-endian (=1), little-endian (=0) */ -#define MMUCR_SYSTEM (1<<8) /* System bit, modifies MMU protections */ -#define MMUCR_ROM (1<<9) /* ROM bit, modifies MMU protections */ -#define MMUCR_F (1<<10) /* Should Be Zero */ -#define MMUCR_Z_ENABLE (1<<11) /* Branch prediction enable on 810 */ -#define MMUCR_I_ENABLE (1<<12) /* Instruction cache enable on SA110 */ - -#define SDRAM_BASE 0xC0000000 -#define SDRAM_RESV (16*1024*1024) -#define SDRAM_SIZE (32*1024*1024) - -#define PMEM_BASE (SDRAM_BASE+SDRAM_RESV) -#define PMEM_TOP (SDRAM_BASE+SDRAM_SIZE) -#define KTOP (KZERO + (SDRAM_SIZE - SDRAM_RESV)) - -#define SLOW_BASE 0x38400000 -#define SLEDOFFSET 0x00108000 - -#define LEDADDR (SLOW_BASE+SLEDOFFSET) - -#define SACADDR 0x08100000 +/* + * all register offsets are relative to 0x8000000 so that + * IOZERO can be changed at some future point + */ +#define IOA(t, x) ((t*)(IOZERO|x)) diff --git a/bitsy/l.s b/bitsy/l.s index 8b4820686f2b815fa6502da7392b59f5d3095d99..7fbd027a66c0099693d593adda6fa1f58a74f79e 100644 --- a/bitsy/l.s +++ b/bitsy/l.s @@ -25,9 +25,9 @@ _main: BL main(SB) BL exit(SB) /* we shouldn't get here */ - BL _div(SB) /* hack to get _div etc loaded */ _mainloop: B _mainloop + BL _div(SB) /* hack to get _div etc loaded */ /* flush tlb's */ TEXT flushmmu(SB), $-4 @@ -79,10 +79,13 @@ TEXT getfar(SB), $-4 MRC CpMMU, 0, R0, C(CpFAR), C(0x0) RET -/* st the translation table base */ +/* set the translation table base */ TEXT setttb(SB), $-4 MCR CpMMU, 0, R0, C(CpTTB), C(0x0) +/* + * set the stack value for the mode passed in R0 + */ TEXT setr13(SB), $-4 MOVW 4(FP), R1 @@ -97,97 +100,108 @@ TEXT setr13(SB), $-4 MOVW R2, CPSR RET +/* + * exception vectors, copied by trapinit() to somewhere useful + */ TEXT vectors(SB), $-4 - MOVW 0x18(R15), R15 /* reset */ - MOVW 0x18(R15), R15 /* undefined */ - MOVW 0x18(R15), R15 /* SWI */ - MOVW 0x18(R15), R15 /* prefetch abort */ - MOVW 0x18(R15), R15 /* data abort */ - MOVW 0x18(R15), R15 /* reserved */ - MOVW 0x18(R15), R15 /* IRQ */ - MOVW 0x18(R15), R15 /* FIQ */ - -TEXT vtable(SB), $-4 - WORD $_vsvc(SB) /* reset, in svc mode already */ - WORD $_vund(SB) /* undefined, switch to svc mode */ - WORD $_vsvc(SB) /* swi, in svc mode already */ - WORD $_vpab(SB) /* prefetch abort, switch to svc mode */ - WORD $_vdab(SB) /* data abort, switch to svc mode */ - WORD $_vsvc(SB) /* reserved */ - WORD $_virq(SB) /* IRQ, switch to svc mode */ - WORD $_vfiq(SB) /* FIQ, switch to svc mode */ - -TEXT _vund(SB), $-4 /* undefined */ - MOVM.IA [R0-R3], (R13) + MOVW 0x18(R15), R15 /* reset */ + MOVW 0x18(R15), R15 /* undefined */ + MOVW 0x18(R15), R15 /* SWI */ + MOVW 0x18(R15), R15 /* prefetch abort */ + MOVW 0x18(R15), R15 /* data abort */ + MOVW 0x18(R15), R15 /* reserved */ + MOVW 0x18(R15), R15 /* IRQ */ + MOVW 0x18(R15), R15 /* FIQ */ + WORD $_vsvc(SB) /* reset, in svc mode already */ + WORD $_vund(SB) /* undefined, switch to svc mode */ + WORD $_vsvc(SB) /* swi, in svc mode already */ + WORD $_vpab(SB) /* prefetch abort, switch to svc mode */ + WORD $_vdab(SB) /* data abort, switch to svc mode */ + WORD $_vsvc(SB) /* reserved */ + WORD $_virq(SB) /* IRQ, switch to svc mode */ + WORD $_vfiq(SB) /* FIQ, switch to svc mode */ + +TEXT _vsvc(SB), $-4 /* reset or SWI or reserved */ + SUB $12, R13 /* make room for pc, psr, & type */ + MOVW R14, 8(R13) /* ureg->pc = interupted PC */ + MOVW SPSR, R14 /* ureg->psr = SPSR */ + MOVW R14, 4(R13) /* ... */ + MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */ + MOVW R14, (R13) /* ... */ + MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */ + B _vexcep /* call the exception handler */ + +TEXT _vund(SB), $-4 /* undefined */ + MOVM.IA [R0-R3], (R13) /* free some working space */ MOVW $PsrMund, R0 B _vswitch -TEXT _vsvc(SB), $-4 /* reset or SWI or reserved */ - SUB $12, R13 /* make room for pc, psr, & type */ - MOVW R14, 8(R13) /* ureg->pc = interupted PC */ - MOVW SPSR, R14 /* ureg->psr = SPSR */ - MOVW R14, 4(R13) /* ... */ - MOVW $PsrMsvc, R14 /* ureg->type = PsrMsvc */ - MOVW R14, (R13) /* ... */ - B _vsaveu - -TEXT _vpab(SB), $-4 /* prefetch abort */ - MOVM.IA [R0-R3], (R13) /* free some working space */ - MOVW $PsrMabt, R0 /* r0 = type */ +TEXT _vpab(SB), $-4 /* prefetch abort */ + MOVM.IA [R0-R3], (R13) /* free some working space */ + MOVW $PsrMabt, R0 /* r0 = type */ B _vswitch -TEXT _vdab(SB), $-4 /* data abort */ - MOVM.IA [R0-R3], (R13) /* free some working space */ - MOVW $(PsrMabt+1), R0 /* r0 = type */ - B _vswitch /* - -TEXT _virq(SB), $-4 /* IRQ */ - MOVM.IA [R0-R3], (R13) /* free some working space */ - MOVW $PsrMirq, R0 /* r0 = type */ +TEXT _vdab(SB), $-4 /* data abort */ + MOVM.IA [R0-R3], (R13) /* free some working space */ + MOVW $(PsrMabt+1), R0 /* r0 = type */ B _vswitch -TEXT _vfiq(SB), $-4 /* FIQ */ - MOVM.IA [R0-R3], (R13) /* free some working space */ - MOVW $PsrMfiq, R0 /* r0 = type */ +TEXT _virq(SB), $-4 /* IRQ */ + MOVM.IA [R0-R3], (R13) /* free some working space */ + MOVW $PsrMirq, R0 /* r0 = type */ B _vswitch +TEXT _vfiq(SB), $-4 /* FIQ */ + RFE /* RIQ is special, ignore it for now */ + /* * come here with type in R0 and R13 pointing above saved [r0-r3] */ _vswitch: /* switch to svc, type in R0 */ - MOVW SPSR, R1 /* SPSR for ureg */ - MOVW R14, R2 /* interrupted pc for ureg */ - MOVW R13, R3 /* [R0-R3] save area */ + MOVW SPSR, R1 /* save SPSR for ureg */ + MOVW R14, R2 /* save interrupted pc for ureg */ + MOVW R13, R3 /* save pointer to where the original [R0-R3] are */ - /* switch to svc mode, we get new R13 pointing to top of svc stack */ + /* switch to svc mode */ MOVW CPSR, R14 BIC $PsrMask, R14 ORR $(PsrDirq|PsrDfiq|PsrMsvc), R14 MOVW R14, CPSR + /* + * R13 and R14 is now R13_SVC and R14_SVC. The values of the previous mode's + * R13 and R14 are no longer accessible. That's why R3 was left to point to where + * the old [r0-r3] are stored. + */ MOVM.DB.W [R0-R2], (R13) /* set ureg->{pc, psr, type}; r13 points to ureg->type */ MOVM.IA (R3), [R0-R3] /* restore [R0-R3] from previous mode's stack */ - B _vsaveu + MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, at end r13 points to ureg */ - /* - * come here with R13 pointing to ureg->type + /* + * if the original interrupt happened while executing SVC mode, the User R14 in the Ureg is + * wrong. We need to save the SVC one there. */ -_vsaveu: - MOVM.DB.W.S [R0-R14], (R13) /* save user level registers, r13 points to ureg */ - - MOVW $setR12(SB), R12 /* the SB from user mode is different */ + MOVW 0x40(R13), R1 + AND.S $0xf, R1 + MOVW.NE R14,0x38(R13) + B _vexcep + /* + * call the exception routine, the ureg is at the bottom of the stack + */ +_vexcep: + MOVW $setR12(SB), R12 /* Make sure we've got the kernel's SB loaded */ MOVW R13, R0 /* first arg is pointer to ureg */ SUB $8, R13 /* space for argument+link */ BL exception(SB) _vrfe: - ADD $(8+4*15), R13 /* r13 points to ureg->type */ + ADD $(8+4*15), R13 /* make r13 point to ureg->type */ MOVW 8(R13), R14 /* restore link */ MOVW 4(R13), R0 /* restore SPSR */ MOVW R0, SPSR /* ... */ MOVM.DB.S (R13), [R0-R14] /* restore registers */ - ADD $8, R13 /* skip saved type+SPSR */ + ADD $8, R13 /* pop past ureg->{type+psr} */ RFE /* MOVM.IA.S.W (R13), [R15] */ TEXT splhi(SB), $-4 diff --git a/bitsy/main.c b/bitsy/main.c index f10e2c85a57e9d2bc121a6f11852899561d748ce..9306df8beea9a38d33b9971f68d1f37298c430bc 100644 --- a/bitsy/main.c +++ b/bitsy/main.c @@ -14,7 +14,7 @@ Conf conf; void main(void) { - + putuartstr("hello ken"); } /* @@ -23,7 +23,10 @@ main(void) void exit(int ispanic) { - USED(ispanic); + void (*f)(); + + f = nil; + (*f)(); } /* diff --git a/bitsy/mem.h b/bitsy/mem.h index cdfd8e0e630f4c2040ccccb678f3705e7423ff08..d5c81f3c01eb304b56116699f8c71fba456efe4f 100644 --- a/bitsy/mem.h +++ b/bitsy/mem.h @@ -33,13 +33,26 @@ #define MACHADDR (KZERO+0x00001000) /* - * Address spaces + * Address spaces: + * + * We've direct mapped the DRAM's and all the + * special use space. Since the DRAM's lie at + * 0xc0000000 and since the Compaq boot loader + * copies the kernel to the start of DRAM, we've + * made KZERO 0xc0000000. We've also direct mapped + * the special use io space between 0x8000000 and KZERO. + * That means we can leave the MMU off till we're pretty + * far into the boot. + * + * Both these decisions can be changed by putting an MMU setup in + * l.s and changing the definitions below. */ #define UZERO 0 /* base of user address space */ #define UTZERO (UZERO+BY2PG) /* first address in user text */ #define KZERO 0xC0000000 /* base of kernel address space */ #define KTZERO 0xC0008000 /* first address in kernel text */ -#define USTKTOP (KZERO-BY2PG) /* byte just beyond user stack */ +#define IOZERO 0x80000000 /* 1 gig of special regs */ +#define USTKTOP (IOZERO-BY2PG) /* byte just beyond user stack */ #define USTKSIZE (16*1024*1024) /* size of user stack */ #define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */ #define TSTKSIZ 100 diff --git a/pc/vga3dfx.c b/pc/vga3dfx.c new file mode 100644 index 0000000000000000000000000000000000000000..2169abf03c81de0fc5e937ecf603e579dfe6d5ab --- /dev/null +++ b/pc/vga3dfx.c @@ -0,0 +1,78 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +#define Image IMAGE +#include +#include +#include +#include "screen.h" + +static ulong +tdfxlinear(VGAscr* scr, int* size, int* align) +{ + ulong aperture, oaperture; + int oapsize, wasupamem; + Pcidev *p; + + oaperture = scr->aperture; + oapsize = scr->apsize; + wasupamem = scr->isupamem; + + aperture = 0; + if(p = pcimatch(nil, 0x121A, 0)){ + switch(p->did){ + case 0x0005: /* Voodoo 3 3000 */ + aperture = p->mem[1].bar & ~0x0F; + *size = p->mem[1].size; + break; + default: + break; + } + } + + if(wasupamem){ + if(oaperture == aperture) + return oaperture; + upafree(oaperture, oapsize); + } + scr->isupamem = 0; + + aperture = upamalloc(aperture, *size, *align); + if(aperture == 0){ + if(wasupamem && upamalloc(oaperture, oapsize, 0)){ + aperture = oaperture; + scr->isupamem = 1; + } + else + scr->isupamem = 0; + } + else + scr->isupamem = 1; + + return aperture; +} + +VGAdev vga3dfxdev = { + "3dfx", + + nil, /* enable */ + nil, /* disable */ + nil, /* page */ + tdfxlinear, /* linear */ + nil, /* drawinit */ + nil, /* fill */ +}; + +VGAcur vga3dfxcur = { + "3dfxhwgc", + + nil, /* enable */ + nil, /* disable */ + nil, /* load */ + nil, /* move */ +}; diff --git a/pc/vgas3.c b/pc/vgas3.c index 5b61efea0d7a55943d67bdb3cd013aa2a08ec469..91d2e383ba7e83172a99be5ffd3c7c39a9f98faa 100644 --- a/pc/vgas3.c +++ b/pc/vgas3.c @@ -567,15 +567,20 @@ s3drawinit(VGAscr *scr) * above. */ switch(id){ - case VIRGE: /* ViRGE */ - case VIRGEVX: /* ViRGE/VX */ - case VIRGEGX2: /* ViRGE/GX2 */ + case VIRGE: + case VIRGEVX: + case VIRGEGX2: scr->mmio = (ulong*)(scr->aperture+0x1000000); scr->fill = hwfill; scr->scroll = hwscroll; /* scr->blank = hwblank; */ break; + case SAVAGEIXMV: + scr->mmio = (ulong*)(scr->aperture+0x1000000); + savageinit(scr); + break; case SAVAGE4: + /* scr->mmio is set by s3linear */ savageinit(scr); break; } diff --git a/pc/vgasavage.c b/pc/vgasavage.c index 0fdd4567e47fb912cb2afacc036c64195bbb6193..4a40fd51fc797562e5740533acaa5b9b39f6dc50 100644 --- a/pc/vgasavage.c +++ b/pc/vgasavage.c @@ -69,7 +69,7 @@ enum { * 32-bit reads of the status registers seem just fine. */ -/* 2D graphics engine registers */ +/* 2D graphics engine registers for Savage4; others appear to be mostly the same */ enum { SubsystemStatus = 0x8504, /* Subsystem Status: read only */ /* read only: whether we get interrupts on various events */ @@ -344,21 +344,49 @@ enum { }; +struct { + ulong idletimeout; +} savagestats; + enum { - Maxloop = 1<<23 + Maxloop = 1<<25 }; static void savagewaitidle(VGAscr *scr) { long x; - ulong *statw; - - statw = (ulong*)((uchar*)scr->mmio+AltStatus0); + ulong *statw, mask, goal; + + switch(scr->id){ + case SAVAGE4: + statw = (ulong*)((uchar*)scr->mmio+AltStatus0); + mask = Ge2Idle; + goal = 0; + break; + /* case SAVAGEMXMV: ? */ + /* case SAVAGEMX: ? */ + /* case SAVAGEIXMV: ? */ + /* case SAVAGEIX: ? */ + case SAVAGEIXMV: + /* wait for engine idle and FIFO empty */ + statw = (ulong*)((uchar*)scr->mmio+XStatus0); + mask = 0x0008FFFF; + goal = 0x00080000; + break; + default: + /* + * best we can do: can't print or we'll call ourselves. + * savageinit is supposed to not let this happen. + */ + return; + } for(x=0; xmmio; + /* if you add chip IDs here be sure to update savagewaitidle */ + switch(scr->id){ + case SAVAGE4: + case SAVAGEIXMV: + break; + default: + print("unknown savage %.4lux\n", scr->id); + return; + } + mmio = (uchar*)scr->mmio; if(mmio == nil) { print("savageinit: no mmio\n"); return; } + /* 2D graphics engine software reset */ *(ushort*)(mmio+SubsystemCtl) = GeSoftReset; delay(2); diff --git a/port/chan.c b/port/chan.c index 28038652b2729f91b9d4831a2838dee733197cdd..c9ba9f3717543fd384df8a2e65ad3dc7617c160a 100644 --- a/port/chan.c +++ b/port/chan.c @@ -641,7 +641,7 @@ namec(char *name, int amode, int omode, ulong perm) if(name[0] == 0) error(Enonexist); - if(!((ulong)name & KZERO)) { + if(((ulong)name & KZERO) != KZERO) { p = name; t = BY2PG-((ulong)p&(BY2PG-1)); while(vmemchr(p, 0, t) == 0) { diff --git a/port/fault.c b/port/fault.c index 131b65f462b0b3a12fbae4ec92cb03eeb938b42d..83d947f8b48a4793a9f940c75a591ce7b5db2591 100644 --- a/port/fault.c +++ b/port/fault.c @@ -345,7 +345,7 @@ vmemchr(void *s, int c, int n) t = vmemchr(s, c, m); if(t) return t; - if(!(a & KZERO)) + if((a & KZERO) != KZERO) validaddr(a+m, 1, 0); return vmemchr((void*)(a+m), c, n-m); } diff --git a/port/sysproc.c b/port/sysproc.c index 3242bbaa0a31299bd72fbedfb6e4e9fcf147d950..4dc60186198b824622f9aa56bb9c119f2f095827 100644 --- a/port/sysproc.c +++ b/port/sysproc.c @@ -242,7 +242,7 @@ sysexec(ulong *arg) text = l2be(exec.text); entry = l2be(exec.entry); if(n==sizeof(Exec) && (magic == AOUT_MAGIC)){ - if((text&KZERO) + if((text&KZERO) == KZERO || entry < UTZERO+sizeof(Exec) || entry >= UTZERO+sizeof(Exec)+text) error(Ebadexec); @@ -278,7 +278,7 @@ sysexec(ulong *arg) d = (t + data + (BY2PG-1)) & ~(BY2PG-1); bssend = t + data + bss; b = (bssend + (BY2PG-1)) & ~(BY2PG-1); - if((t|d|b) & KZERO) + if(((t|d|b) & KZERO) == KZERO) error(Ebadexec); /*