From c7b71a77642fd47c18c232a5087ad5d2591dc550 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 27 Jul 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-07-27 --- alphapc/clock.c | 73 +---- alphapc/dat.h | 19 +- alphapc/devarch.c | 142 ++++++---- alphapc/devether.c | 25 +- alphapc/devfloppy.c | 27 +- alphapc/devvga.c | 18 +- alphapc/ether2114x.c | 2 +- alphapc/etherif.h | 4 + alphapc/faultalpha.c | 8 +- alphapc/fns.h | 6 +- alphapc/fptrap.c | 2 +- alphapc/io.h | 8 +- alphapc/main.c | 92 +++--- alphapc/mem.h | 1 - alphapc/mmu.c | 16 ++ alphapc/mouse.c | 12 +- alphapc/screen.h | 3 +- alphapc/sd53c8xx.c | 4 +- alphapc/trap.c | 24 +- alphapc/uarti8250.c | 648 +++++++++++++++++++++++++++++++++++++++++++ pc/sdata.c | 18 +- port/sysfile.c | 34 ++- 22 files changed, 917 insertions(+), 269 deletions(-) create mode 100644 alphapc/uarti8250.c diff --git a/alphapc/clock.c b/alphapc/clock.c index e7d3b041d859b8f264fcc388bda836b00d95fdb8..edf573cac5fc5f560a2045fccf4c464082812ccf 100644 --- a/alphapc/clock.c +++ b/alphapc/clock.c @@ -5,36 +5,8 @@ #include "fns.h" #include "io.h" #include "axp.h" - #include "ureg.h" -void (*kproftimer)(ulong); - -typedef struct Clock0link Clock0link; -typedef struct Clock0link { - void (*clock)(void); - Clock0link* link; -} Clock0link; - -static Clock0link *clock0link; -static Lock clock0lock; - -void -addclock0link(void (*clock)(void)) -{ - Clock0link *lp; - - if((lp = malloc(sizeof(Clock0link))) == 0){ - print("addclock0link: too many links\n"); - return; - } - ilock(&clock0lock); - lp->clock = clock; - lp->link = clock0link; - clock0link = lp; - iunlock(&clock0lock); -} - void clockinit(void) { @@ -97,58 +69,23 @@ microdelay(int us) } void -/*milli*/delay(int ms) +delay(int millisecs) { - microdelay(ms*1000); + microdelay(millisecs*1000); } void -clock(Ureg *ur) +clock(Ureg *ureg) { - Clock0link *lp; static int count; cycletimer(); + /* HZ == 100, timer == 1024Hz. error < 1ms */ count += 100; if (count < 1024) return; count -= 1024; - m->ticks++; - if(m->proc) - m->proc->pc = ur->pc; - - accounttime(); - - if(kproftimer != nil) - kproftimer(ur->pc); - - if((active.machs&(1<machno)) == 0) - return; - - if(active.exiting && (active.machs & (1<machno))) { - print("someone's exiting\n"); - exit(0); - } - - checkalarms(); - if(m->machno == 0){ - lock(&clock0lock); - for(lp = clock0link; lp; lp = lp->link) - lp->clock(); - unlock(&clock0lock); - } - - if(up == 0 || up->state != Running) - return; - - if(anyready()) - sched(); - - /* user profiling clock */ - if(ur->status & UMODE) { - (*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1); - segclock(ur->pc); - } + portclock(ureg); } diff --git a/alphapc/dat.h b/alphapc/dat.h index 3299d5a348ce7f96b4013516314351af57df6338..c9911707e770cbb86253fc580cabecbacde6eaf3 100644 --- a/alphapc/dat.h +++ b/alphapc/dat.h @@ -132,30 +132,32 @@ struct Mach Proc *proc; /* current process on this processor */ /* ordering from here on irrelevant */ - int tlbfault; /* only used by devproc; no access to tlb */ - int tlbpurge; /* ... */ + ulong ticks; /* of the clock since boot time */ Label sched; /* scheduler wakeup */ Lock alarmlock; /* access to alarm list */ void *alarm; /* alarms bound to this clock */ - Page *ufreeme; /* address of upage of exited process */ - int nrdy; + int inclockintr; + ulong fairness; /* for runproc */ - int lastintr; ulong cpuhz; /* hwrpb->cfreq */ ulong pcclast; uvlong fastclock; vlong intrts; /* time stamp of last interrupt */ + int tlbfault; /* only used by devproc; no access to tlb */ + int tlbpurge; /* ... */ int pfault; int cs; int syscall; int load; int intr; - int spuriousintr; int flushmmu; /* make current proc flush it's mmu state */ + ulong spuriousintr; + int lastintr; + PCB; /* MUST BE LAST */ @@ -203,11 +205,10 @@ struct PCArch /* * a parsed plan9.ini line */ -#define ISAOPTLEN 16 #define NISAOPT 8 struct ISAConf { - char type[NAMELEN]; + char *type; ulong port; ulong irq; ulong dma; @@ -216,7 +217,7 @@ struct ISAConf { ulong freq; int nopt; - char opt[NISAOPT][ISAOPTLEN]; + char *opt[NISAOPT]; }; extern PCArch *arch; diff --git a/alphapc/devarch.c b/alphapc/devarch.c index 09f1eb7a960ddd6363ed956881e7ad4d2cd28053..5ee9a37f97ea6b78d2ade43444ae207179072675 100644 --- a/alphapc/devarch.c +++ b/alphapc/devarch.c @@ -27,23 +27,69 @@ static struct } iomap; enum { - Qdir, - Qcputype, - Qioalloc, + Qdir = 0, + Qioalloc = 1, 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[] = { + ".", { Qdir, 0, QTDIR }, 0, 0555, "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; itag[sizeof(m->tag)-1] = 0; *l = m; - ioallocdir[0].qid.vers++; + archdir[0].qid.vers++; unlock(&iomap); return m->start; @@ -138,7 +182,7 @@ iofree(int port) if((*l)->start > port) break; } - ioallocdir[0].qid.vers++; + archdir[0].qid.vers++; unlock(&iomap); } @@ -175,22 +219,22 @@ archattach(char* spec) return devattach('P', spec); } -int -archwalk(Chan* c, char* name) +Walkqid* +archwalk(Chan* c, Chan *nc, char** name, int nname) { - return devwalk(c, name, ioallocdir, nelem(ioallocdir), devgen); + return devwalk(c, nc, name, nname, archdir, narchdir, devgen); } -static void -archstat(Chan* c, char* dp) +static int +archstat(Chan* c, uchar* dp, int n) { - devstat(c, dp, ioallocdir, nelem(ioallocdir), devgen); + return devstat(c, dp, n, archdir, narchdir, devgen); } static Chan* archopen(Chan* c, int omode) { - return devopen(c, omode, ioallocdir, nelem(ioallocdir), devgen); + return devopen(c, omode, archdir, nelem(archdir), devgen); } static void @@ -206,17 +250,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((ulong)c->qid.path){ case Qdir: - return devdirread(c, a, n, ioallocdir, nelem(ioallocdir), devgen); + return devdirread(c, a, n, archdir, nelem(archdir), devgen); case Qiob: port = offset; @@ -248,13 +292,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; } @@ -281,12 +321,13 @@ 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){ + switch((ulong)c->qid.path){ case Qiob: p = a; @@ -316,6 +357,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; } @@ -329,7 +372,6 @@ Dev archdevtab = { devreset, devinit, archattach, - devclone, archwalk, archstat, archopen, @@ -365,22 +407,6 @@ static char *cpunames[] = [7] "21164A", }; -void -archinit(void) -{ - PCArch **p; - - arch = 0; - for(p = knownarch; *p; p++){ - if((*p)->ident && (*p)->ident() == 0){ - arch = *p; - break; - } - } - if(arch == 0) - arch = &archgeneric; -} - void cpuidprint(void) { @@ -419,7 +445,7 @@ cpuidprint(void) } static long -cputyperead(char *a, int n, ulong offset) +cputyperead(Chan*, void *a, long n, vlong offset) { char str[32], *cputype; ulong mhz, maj; @@ -435,3 +461,21 @@ cputyperead(char *a, int n, ulong offset) snprint(str, sizeof(str), "%s %lud\n", cputype, mhz); return readstr(offset, a, n, str); } + +void +archinit(void) +{ + PCArch **p; + + arch = 0; + for(p = knownarch; *p; p++){ + if((*p)->ident && (*p)->ident() == 0){ + arch = *p; + break; + } + } + if(arch == 0) + arch = &archgeneric; + + addarchfile("cputype", 0444, cputyperead, nil); +} diff --git a/alphapc/devether.c b/alphapc/devether.c index 2746614468029f08f86238497d2efe0046024986..e9266a16584ed79e8e3b94126732e9603dce6896 100644 --- a/alphapc/devether.c +++ b/alphapc/devether.c @@ -35,16 +35,16 @@ etherattach(char* spec) return chan; } -static int -etherwalk(Chan* chan, char* name) +static Walkqid* +etherwalk(Chan* chan, Chan* nchan, char** name, int nname) { - return netifwalk(etherxx[chan->dev], chan, name); + return netifwalk(etherxx[chan->dev], chan, nchan, name, nname); } -static void -etherstat(Chan* chan, char* dp) +static int +etherstat(Chan* chan, uchar* dp, int n) { - netifstat(etherxx[chan->dev], chan, dp); + return netifstat(etherxx[chan->dev], chan, dp, n); } static Chan* @@ -71,7 +71,7 @@ etherread(Chan* chan, void* buf, long n, vlong off) ulong offset = off; ether = etherxx[chan->dev]; - if((chan->qid.path & CHDIR) == 0 && ether->ifstat){ + if((chan->qid.type & QTDIR) == 0 && ether->ifstat){ /* * With some controllers it is necessary to reach * into the chip to extract statistics. @@ -96,10 +96,10 @@ etherremove(Chan*) { } -static void -etherwstat(Chan* chan, char* dp) +static int +etherwstat(Chan* chan, uchar* dp, int n) { - netifwstat(etherxx[chan->dev], chan, dp); + return netifwstat(etherxx[chan->dev], chan, dp, n); } static void @@ -338,7 +338,7 @@ etherreset(void) { Ether *ether; int i, n, ctlrno; - char name[NAMELEN], buf[128]; + char name[32], buf[128]; for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){ if(ether == 0) @@ -347,6 +347,8 @@ etherreset(void) ether->ctlrno = ctlrno; ether->tbdf = BUSUNKNOWN; ether->mbps = 10; + ether->minmtu = ETHERMINTU; + ether->maxmtu = ETHERMAXTU; if(isaconfig("ether", ctlrno, ether) == 0) continue; for(n = 0; cards[n].type; n++){ @@ -435,7 +437,6 @@ Dev etherdevtab = { etherreset, devinit, etherattach, - devclone, etherwalk, etherstat, etheropen, diff --git a/alphapc/devfloppy.c b/alphapc/devfloppy.c index 2f8da2e89f2df3055c799ba6b843e3067f0c0f21..1195ebb83b36eb611a45fff318b3dffe2902bbc0 100644 --- a/alphapc/devfloppy.c +++ b/alphapc/devfloppy.c @@ -104,7 +104,7 @@ static void floppywait(void); static long floppyxfer(FDrive*, int, void*, long, long); Dirtab floppydir[]={ -// "fd0disk", {Qdata + 0}, 0, 0660, + ".", {Qdir, 0, QTDIR}, 0, 0550, "fd0disk", {Qdata + 0}, 0, 0666, "fd0ctl", {Qctl + 0}, 0, 0660, "fd1disk", {Qdata + 1}, 0, 0660, @@ -134,7 +134,7 @@ floppysetdef(FDrive *dp) for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++) if(dp->dt == t->dt){ dp->t = t; - floppydir[NFDIR*dp->dev].length = dp->t->cap; + floppydir[1+NFDIR*dp->dev].length = dp->t->cap; break; } } @@ -212,22 +212,22 @@ floppyattach(char *spec) return devattach('f', spec); } -static int -floppywalk(Chan *c, char *name) +static Walkqid* +floppywalk(Chan *c, Chan *nc, char **name, int nname) { - return devwalk(c, name, floppydir, fl.ndrive*NFDIR, devgen); + return devwalk(c, nc, name, nname, floppydir, 1+fl.ndrive*NFDIR, devgen); } -static void -floppystat(Chan *c, char *dp) +static int +floppystat(Chan *c, uchar *dp, int n) { - devstat(c, dp, floppydir, fl.ndrive*NFDIR, devgen); + return devstat(c, dp, n, floppydir, 1+fl.ndrive*NFDIR, devgen); } static Chan* floppyopen(Chan *c, int omode) { - return devopen(c, omode, floppydir, fl.ndrive*NFDIR, devgen); + return devopen(c, omode, floppydir, 1+fl.ndrive*NFDIR, devgen); } static void @@ -280,7 +280,7 @@ changed(Chan *c, FDrive *dp) if(dp->dt == dp->t->dt) break; } - floppydir[NFDIR*dp->dev].length = dp->t->cap; + floppydir[1+NFDIR*dp->dev].length = dp->t->cap; floppyon(dp); DPRINT("changed: trying %s\n", dp->t->name); fldump(); @@ -328,8 +328,8 @@ floppyread(Chan *c, void *a, long n, vlong off) uchar *aa; ulong offset = off; - if(c->qid.path == CHDIR) - return devdirread(c, a, n, floppydir, fl.ndrive*NFDIR, devgen); + if(c->qid.type & QTDIR) + return devdirread(c, a, n, floppydir, 1+fl.ndrive*NFDIR, devgen); rv = 0; dp = &fl.d[c->qid.path & ~Qmask]; @@ -915,7 +915,7 @@ floppyformat(FDrive *dp, char *params) for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){ if(strcmp(f[1], t->name)==0 && t->dt==dp->dt){ dp->t = t; - floppydir[NFDIR*dp->dev].length = dp->t->cap; + floppydir[1+NFDIR*dp->dev].length = dp->t->cap; break; } } @@ -1043,7 +1043,6 @@ Dev floppydevtab = { floppyreset, devinit, floppyattach, - devclone, floppywalk, floppystat, floppyopen, diff --git a/alphapc/devvga.c b/alphapc/devvga.c index 452a3cf42a9b0519934d47e9f85505e6a42d72e4..88ebe5d0e2154c7946413bcebca59858c3b9c46c 100644 --- a/alphapc/devvga.c +++ b/alphapc/devvga.c @@ -24,6 +24,7 @@ enum { }; static Dirtab vgadir[] = { + ".", { Qdir, 0, QTDIR }, 0, 0550, "vgactl", { Qvgactl, 0 }, 0, 0660, "vgabios", { Qvgabios, 0 }, 0x10000, 0440, }; @@ -47,16 +48,16 @@ vgaattach(char* spec) return devattach('v', spec); } -int -vgawalk(Chan* c, char* name) +Walkqid* +vgawalk(Chan* c, Chan *nc, char** name, int nname) { - return devwalk(c, name, vgadir, nelem(vgadir), devgen); + return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen); } -static void -vgastat(Chan* c, char* dp) +static int +vgastat(Chan* c, uchar* dp, int n) { - devstat(c, dp, vgadir, nelem(vgadir), devgen); + return devstat(c, dp, n, vgadir, nelem(vgadir), devgen); } static Chan* @@ -93,7 +94,7 @@ vgaread(Chan* c, void* a, long n, vlong off) ulong offset = off; char chbuf[30]; - switch(c->qid.path & ~CHDIR){ + switch((ulong)c->qid.path){ case Qdir: return devdirread(c, a, n, vgadir, nelem(vgadir), devgen); @@ -359,7 +360,7 @@ vgawrite(Chan* c, void* a, long n, vlong off) char *p; ulong offset = off; - switch(c->qid.path & ~CHDIR){ + switch((ulong)c->qid.path){ case Qdir: error(Eperm); @@ -394,7 +395,6 @@ Dev vgadevtab = { vgareset, devinit, vgaattach, - devclone, vgawalk, vgastat, vgaopen, diff --git a/alphapc/ether2114x.c b/alphapc/ether2114x.c index efcfb5f70a140a1356abfb8ea88a7591ca93e8c7..614ecada1d828f8347739a11712fd1d2d30ffadd 100644 --- a/alphapc/ether2114x.c +++ b/alphapc/ether2114x.c @@ -19,7 +19,7 @@ #include "etherif.h" -#define DEBUG (1) +#define DEBUG (0) #define debug if(DEBUG)print enum { diff --git a/alphapc/etherif.h b/alphapc/etherif.h index 271b506b0fca23a14f1e271cad6d0310a7ddc16b..33a5ad045f1779142b925decdd3535a093134002 100644 --- a/alphapc/etherif.h +++ b/alphapc/etherif.h @@ -10,12 +10,16 @@ struct Ether { int ctlrno; int tbdf; /* type+busno+devno+funcno */ int mbps; /* Mbps */ + int minmtu; + int maxmtu; uchar ea[Eaddrlen]; + int encry; void (*attach)(Ether*); /* filled in by reset routine */ void (*transmit)(Ether*); void (*interrupt)(Ureg*, void*); long (*ifstat)(Ether*, void*, long, ulong); + long (*ctl)(Ether*, void*, long); /* custom ctl messages */ void *ctlr; Queue* oq; diff --git a/alphapc/faultalpha.c b/alphapc/faultalpha.c index 9e18619a052fbf2e6c6f10dbdb71d75e0858352e..cc26c6b2e070b22aa34da209d7df6fca7af3c82f 100644 --- a/alphapc/faultalpha.c +++ b/alphapc/faultalpha.c @@ -15,7 +15,7 @@ faultalpha(Ureg *ur) { ulong addr, cause; int read, user; - char buf[ERRLEN]; + char buf[ERRMAX]; uvlong x; x = ur->a0&0xffffffff80000000LL; @@ -42,10 +42,8 @@ faultalpha(Ureg *ur) } iprint("kernel %s vaddr=0x%lux\n", read? (cause != 0) ? "ifetch" : "read" : "write", (ulong)ur->a0); -iprint("ptbr %lux up %lux\n", (ulong)m->ptbr, up); -if(up) iprint("top %lux lvl2 %lux\n", up->mmutop->va, up->mmulvl2->va); -if(up) iprint("top[N-1] %lux\n", ((uvlong *)up->mmutop->va)[PTE2PG-1]); - iprint("st=0x%lux pc=0x%lux sp=0x%lux\n", (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp); + if(0) + mmudump(); dumpregs(ur); panic("fault"); } diff --git a/alphapc/fns.h b/alphapc/fns.h index 4b55bddd843bb970f5c0a3c9d31ed949add246c1..e1e5f45df6c91e9224cd9e8ba978ecde9c1f77a9 100644 --- a/alphapc/fns.h +++ b/alphapc/fns.h @@ -1,6 +1,6 @@ #include "../port/portfns.h" -void addclock0link(void (*)(void)); +Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong)); void archinit(void); void arginit(void); void arith(void); @@ -34,6 +34,7 @@ void gotopc(ulong); int i8042auxcmd(int); void i8042auxenable(void (*)(int, int)); void i8042reset(void); +void i8250console(void); void i8259init(void); int i8259enable(int, int, Vctl*); #define idlehands() /* nothing to do in the runproc */ @@ -49,6 +50,7 @@ int iprint(char*, ...); int irqallocread(char*, long, vlong); int isaconfig(char*, int, ISAConf*); void kbdinit(void); +#define kmapinval() void *kmapv(uvlong, int); int kprint(char*, ...); void launchinit(void); @@ -57,6 +59,7 @@ void links(void); void mb(void); void memholes(void); ulong meminit(void); +void mmudump(void); void mmuinit(void); #define mmunewpage(x) void mntdump(void); @@ -95,6 +98,7 @@ void upafree(ulong, int); #define userureg(ur) ((ur)->status & UMODE) void wrent(int, void*); void wrvptptr(uvlong); +ulong TK2MS(ulong); /* ticks to milliseconds */ #define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1])) #define kmapperm(x) kmap(x) diff --git a/alphapc/fptrap.c b/alphapc/fptrap.c index 0166d3603ed05eb08007510b0e863740b1d2fccb..7b3c5a86845ecff5434674d259e11c86154e43a3 100644 --- a/alphapc/fptrap.c +++ b/alphapc/fptrap.c @@ -21,7 +21,7 @@ char *fpexcname(Ureg*, ulong, char*); void fptrap(Ureg *ur) { - char buf[ERRLEN]; + char buf[ERRMAX]; int i; ulong reason; diff --git a/alphapc/io.h b/alphapc/io.h index 740314105965e5baeda29dd6fb27fffb4dbd92c8..457877252dc98bb6f1b2fb226bbd34149d9958f9 100644 --- a/alphapc/io.h +++ b/alphapc/io.h @@ -1,9 +1,3 @@ -enum { - Uart0 = 0x3F8, - Uart1 = 0x2F8, - UartFREQ = 1843200, -}; - enum { IrqCLOCK = 0, IrqKBD = 1, @@ -27,7 +21,7 @@ enum { typedef struct Vctl { Vctl* next; /* handlers on this vector */ - char name[NAMELEN]; /* of driver */ + char name[KNAMELEN]; /* of driver */ int isintr; /* interrupt or fault/trap */ int irq; int tbdf; diff --git a/alphapc/main.c b/alphapc/main.c index 7295870555d155c0dadb1815e748de5388e8d4df..ec4d73f27cfb3d9da8da421674bfb699e2107cc1 100644 --- a/alphapc/main.c +++ b/alphapc/main.c @@ -26,23 +26,34 @@ int nconf; static void options(void) { - char *cp, *line[MAXCONF]; - int i, n; + long i, n; + char *cp, *line[MAXCONF], *p, *q; cp = bootconf->bootargs; cp[BOOTARGSLEN-1] = 0; strcpy(bootargs, cp); - n = getcfields(bootargs, line, MAXCONF, "\n"); + /* + * Strip out '\r', change '\t' -> ' '. + */ + p = cp; + for(q = cp; *q; q++){ + if(*q == '\r') + continue; + if(*q == '\t') + *q = ' '; + *p++ = *q; + } + *p = 0; + + n = getfields(cp, line, MAXCONF, 1, "\n"); for(i = 0; i < n; i++){ if(*line[i] == '#') continue; cp = strchr(line[i], '='); - if(cp == 0) + if(cp == nil) continue; - *cp++ = 0; - if(cp - line[i] >= NAMELEN+1) - *(line[i]+NAMELEN-1) = 0; + *cp++ = '\0'; confname[nconf] = line[i]; confval[nconf] = cp; nconf++; @@ -56,8 +67,8 @@ main(void) hwrpb = (Hwrpb*)(KZERO|hwrpb->phys); arginit(); machinit(); - ioinit(); options(); + ioinit(); clockinit(); confinit(); archinit(); @@ -69,11 +80,9 @@ main(void) trapinit(); screeninit(); printinit(); - - /* console */ - ns16552install(); - ns16552special(0, 9600, 0, &printq, kbdcr2nl); kbdinit(); + i8250console(); + print("\nPlan 9\n"); cpuidprint(); if(arch->corehello) @@ -123,7 +132,9 @@ void init0(void) { int i; - char buf[2*NAMELEN]; + char tstr[32]; + + up->nerrlab = 0; spllo(); @@ -134,15 +145,14 @@ init0(void) up->slash = namec("#/", Atodir, 0, 0); cnameclose(up->slash->name); up->slash->name = newcname("/"); - up->dot = cclone(up->slash, 0); + up->dot = cclone(up->slash); chandevinit(); if(!waserror()){ ksetenv("cputype", "alpha"); - sprint(buf, "alpha %s alphapc", conffile); - ksetenv("terminal", buf); - ksetenv("sysname", sysname); + sprint(tstr, "alpha %s alphapc", conffile); + ksetenv("terminal", tstr); if(cpuserver) ksetenv("service", "cpu"); else @@ -174,8 +184,9 @@ userinit(void) p->rgrp = newrgrp(); p->procmode = 0640; - strcpy(p->text, "*init*"); - strcpy(p->user, eve); + kstrdup(&eve, ""); + kstrdup(&p->text, "*init*"); + kstrdup(&p->user, eve); procsetup(p); @@ -398,7 +409,7 @@ confinit(void) imagmem->maxsize = kpages; } - conf.monitor = 1; /* BUG */ +// conf.monitor = 1; /* BUG */ } void @@ -454,29 +465,18 @@ getconf(char *name) int isaconfig(char *class, int ctlrno, ISAConf *isa) { - char cc[NAMELEN], *p, *q, *r; - int n; + char cc[32], *p; + int i, n; - sprint(cc, "%s%d", class, ctlrno); + snprint(cc, sizeof cc, "%s%d", class, ctlrno); for(n = 0; n < nconf; n++){ - if(cistrncmp(confname[n], cc, NAMELEN)) + if(cistrcmp(confname[n], cc) != 0) continue; - isa->nopt = 0; - p = confval[n]; - while(*p){ - while(*p == ' ' || *p == '\t') - p++; - if(*p == '\0') - break; - if(cistrncmp(p, "type=", 5) == 0){ - p += 5; - for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){ - if(*p == '\0' || *p == ' ' || *p == '\t') - break; - *q = *p++; - } - *q = '\0'; - } + isa->nopt = tokenize(confval[n], isa->opt, NISAOPT); + for(i = 0; i < isa->nopt; i++){ + p = isa->opt[i]; + if(cistrncmp(p, "type=", 5) == 0) + isa->type = p + 5; else if(cistrncmp(p, "port=", 5) == 0) isa->port = strtoul(p+5, &p, 0); else if(cistrncmp(p, "irq=", 4) == 0) @@ -489,18 +489,6 @@ isaconfig(char *class, int ctlrno, ISAConf *isa) isa->size = strtoul(p+5, &p, 0); else if(cistrncmp(p, "freq=", 5) == 0) isa->freq = strtoul(p+5, &p, 0); - else if(isa->nopt < NISAOPT){ - r = isa->opt[isa->nopt]; - while(*p && *p != ' ' && *p != '\t'){ - *r++ = *p++; - if(r-isa->opt[isa->nopt] >= ISAOPTLEN-1) - break; - } - *r = '\0'; - isa->nopt++; - } - while(*p && *p != ' ' && *p != '\t') - p++; } return 1; } diff --git a/alphapc/mem.h b/alphapc/mem.h index 98ab31060b34f797fb42695641798debd346f55f..0f738ff1640f6a038837254e6419cdde0ae26f7e 100644 --- a/alphapc/mem.h +++ b/alphapc/mem.h @@ -29,7 +29,6 @@ #define HZ 100 /* clock frequency */ #define MS2HZ (1000/HZ) #define TK2SEC(t) ((t)/HZ) /* ticks to seconds */ -#define TK2MS(t) ((t)*MS2HZ) /* ticks to milliseconds */ #define MS2TK(t) (((t)*HZ+500)/1000) /* milliseconds to closest tick */ /* diff --git a/alphapc/mmu.c b/alphapc/mmu.c index 36e0e40e20fe427fee359c541ba84f0da9bb1ced..4293652d43a4e002e103d104982330af1c04d3f3 100644 --- a/alphapc/mmu.c +++ b/alphapc/mmu.c @@ -254,3 +254,19 @@ upafree(ulong, int) { print("upafree: virtual mapping not freed\n"); } + +void +mmudump(void) +{ + Page *top, *lvl2; + + iprint("ptbr %lux up %lux\n", (ulong)m->ptbr, up); + if(up) { + top = up->mmutop; + if(top != nil) + iprint("top %lux top[N-1] %lux\n", top->va, ((uvlong *)top->va)[PTE2PG-1]); + lvl2 = up->mmulvl2; + if(lvl2 != nil) + iprint("lvl2 %lux\n", lvl2->va); + } +} diff --git a/alphapc/mouse.c b/alphapc/mouse.c index a5aec038466ef7b9b860529a3e96c6488e79778a..d148d97cece8f7e24411982db1e1578d57afa095 100644 --- a/alphapc/mouse.c +++ b/alphapc/mouse.c @@ -29,6 +29,7 @@ static int mousetype; static void serialmouse(int port, char *type, int setspeed) { +#ifdef notdef if(mousetype == Mouseserial) error(Emouseset); @@ -39,10 +40,15 @@ serialmouse(int port, char *type, int setspeed) if(setspeed) setspeed = 1200; if(type && *type == 'M') - ns16552special(port, setspeed, 0, 0, m3mouseputc); + uartspecial(port, setspeed, 0, 0, m3mouseputc); else - ns16552special(port, setspeed, 0, 0, mouseputc); + uartspecial(port, setspeed, 0, 0, mouseputc); mousetype = Mouseserial; + packetsize = 3; +#else + error("serial mouse not supported yet"); + USED(port, type, setspeed); +#endif /* notdef */ } /* @@ -79,7 +85,7 @@ ps2mouseputc(int c, int shift) buttons = b[(msg[0]&7) | (shift ? 8 : 0)]; dx = msg[1]; dy = -msg[2]; - mousetrack(buttons, dx, dy); + mousetrack(buttons, dx, dy, TK2MS(MACHP(0)->ticks)); } return; } diff --git a/alphapc/screen.h b/alphapc/screen.h index 0358a2479cf2e3ef3399535f454f34c73cb4c30b..933be68e711ecd86df670b9e2b7513ee81e49b96 100644 --- a/alphapc/screen.h +++ b/alphapc/screen.h @@ -6,7 +6,7 @@ struct Cursorinfo { }; /* devmouse.c */ -extern void mousetrack(int, int, int); +extern void mousetrack(int, int, int, int); extern Point mousexy(void); extern void mouseaccelerate(int); @@ -127,6 +127,7 @@ extern void mousectl(char*[], int); /* screen.c */ extern int hwaccel; /* use hw acceleration; default on */ extern int hwblank; /* use hw blanking; default on */ +extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*); extern void flushmemscreen(Rectangle); extern int cursoron(int); extern void cursoroff(int); diff --git a/alphapc/sd53c8xx.c b/alphapc/sd53c8xx.c index 316bdd2f89f04e06ea841aef8042921f443f1a49..c19cf3deab556df4350b203377932114fa027e00 100644 --- a/alphapc/sd53c8xx.c +++ b/alphapc/sd53c8xx.c @@ -2030,13 +2030,13 @@ symenable(SDev* sdev) { Pcidev *pcidev; Controller *ctlr; - char name[NAMELEN]; + char name[32]; ctlr = sdev->ctlr; pcidev = ctlr->pcidev; pcisetbme(pcidev); - snprint(name, NAMELEN, "%s (%s)", sdev->name, sdev->ifc->name); + snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name); intrenable(pcidev->intl, interrupt, ctlr, pcidev->tbdf, name); ilock(ctlr); diff --git a/alphapc/trap.c b/alphapc/trap.c index 878ba992013daa26bc03260b4e976bf3d4b06398..32fe4919a6afdf9796cbd38fd374a994e80fa647 100644 --- a/alphapc/trap.c +++ b/alphapc/trap.c @@ -44,8 +44,8 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) v->tbdf = tbdf; v->f = f; v->a = a; - strncpy(v->name, name, NAMELEN-1); - v->name[NAMELEN-1] = 0; + strncpy(v->name, name, KNAMELEN-1); + v->name[KNAMELEN-1] = 0; ilock(&vctllock); vno = arch->intrenable(v); @@ -79,7 +79,7 @@ irqallocread(char *buf, long n, vlong offset) int vno; Vctl *v; long oldn; - char str[11+1+NAMELEN+1], *p; + char str[11+1+KNAMELEN+1], *p; int m; if(n < 0 || offset < 0) @@ -88,7 +88,7 @@ irqallocread(char *buf, long n, vlong offset) oldn = n; for(vno=0; vnonext){ - m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, NAMELEN, v->name); + m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name); if(m <= offset) /* if do not want this, skip entry */ offset -= m; else{ @@ -252,7 +252,7 @@ intr(Ureg *ur) void trap(Ureg *ur) { - char buf[ERRLEN]; + char buf[ERRMAX]; int user, x; m->intrts = fastticks(nil); @@ -335,7 +335,7 @@ trapinit(void) void fataltrap(Ureg *ur, char *reason) { - char buf[ERRLEN]; + char buf[ERRMAX]; if(ur->status&UMODE) { spllo(); @@ -474,8 +474,8 @@ notify(Ureg *ur) n = &up->note[0]; if(strncmp(n->msg, "sys:", 4) == 0) { l = strlen(n->msg); - if(l > ERRLEN-15) /* " pc=0x12345678\0" */ - l = ERRLEN-15; + if(l > ERRMAX-15) /* " pc=0x12345678\0" */ + l = ERRMAX-15; sprint(n->msg+l, " pc=0x%lux", (ulong)ur->pc); } @@ -501,7 +501,7 @@ notify(Ureg *ur) sp -= sizeof(Ureg); if(!okaddr((ulong)up->notify, BY2WD, 0) - || !okaddr(sp-ERRLEN-6*BY2WD, sizeof(Ureg)+ERRLEN-6*BY2WD, 1)) { + || !okaddr(sp-ERRMAX-6*BY2WD, sizeof(Ureg)+ERRMAX-6*BY2WD, 1)) { pprint("suicide: bad address or sp in notify\n"); print("suicide: bad address or sp in notify\n"); qunlock(&up->debug); @@ -511,8 +511,8 @@ print("suicide: bad address or sp in notify\n"); memmove((Ureg*)sp, ur, sizeof(Ureg)); *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */ up->ureg = (void*)sp; - sp -= 2*BY2WD+ERRLEN; - memmove((char*)sp, up->note[0].msg, ERRLEN); + sp -= 2*BY2WD+ERRMAX; + memmove((char*)sp, up->note[0].msg, ERRMAX); sp -= 4*BY2WD; *(ulong*)(sp+3*BY2WD) = sp+4*BY2WD; /* arg 2 is string */ ur->r0 = (ulong)up->ureg; /* arg 1 (R0) is ureg* */ @@ -603,7 +603,7 @@ print("suicide: trap in noted\n"); pexit("Suicide", 0); } qunlock(&up->debug); - sp = oureg-4*BY2WD-ERRLEN; + sp = oureg-4*BY2WD-ERRMAX; splhi(); (*urp)->sp = sp; ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */ diff --git a/alphapc/uarti8250.c b/alphapc/uarti8250.c new file mode 100644 index 0000000000000000000000000000000000000000..b2ca39d58a0a3a1f00f37dde8c9d5863308c41a3 --- /dev/null +++ b/alphapc/uarti8250.c @@ -0,0 +1,648 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" + +/* + * 8250 UART and compatibles. + */ +enum { + Uart0 = 0x3F8, /* COM1 */ + Uart0IRQ = 4, + Uart1 = 0x2F8, /* COM2 */ + Uart1IRQ = 3, + + UartFREQ = 1843200, +}; + +enum { /* I/O ports */ + Rbr = 0, /* Receiver Buffer (RO) */ + Thr = 0, /* Transmitter Holding (WO) */ + Ier = 1, /* Interrupt Enable */ + Iir = 2, /* Interrupt Identification (RO) */ + Fcr = 2, /* FIFO Control (WO) */ + Lcr = 3, /* Line Control */ + Mcr = 4, /* Modem Control */ + Lsr = 5, /* Line Status */ + Msr = 6, /* Modem Status */ + Scr = 7, /* Scratch Pad */ + Dll = 0, /* Divisor Latch LSB */ + Dlm = 1, /* Divisor Latch MSB */ +}; + +enum { /* Ier */ + Erda = 0x01, /* Enable Received Data Available */ + Ethre = 0x02, /* Enable Thr Empty */ + Erls = 0x04, /* Enable Receiver Line Status */ + Ems = 0x08, /* Enable Modem Status */ +}; + +enum { /* Iir */ + Ims = 0x00, /* Ms interrupt */ + Ip = 0x01, /* Interrupt Pending (not) */ + Ithre = 0x02, /* Thr Empty */ + Irda = 0x04, /* Received Data Available */ + Irls = 0x06, /* Receiver Line Status */ + Ictoi = 0x0C, /* Character Time-out Indication */ + IirMASK = 0x3F, + Ife = 0xC0, /* FIFOs enabled */ +}; + +enum { /* Fcr */ + FIFOena = 0x01, /* FIFO enable */ + FIFOrclr = 0x02, /* clear Rx FIFO */ + FIFOtclr = 0x04, /* clear Tx FIFO */ + FIFO1 = 0x00, /* Rx FIFO trigger level 1 byte */ + FIFO4 = 0x40, /* 4 bytes */ + FIFO8 = 0x80, /* 8 bytes */ + FIFO14 = 0xC0, /* 14 bytes */ +}; + +enum { /* Lcr */ + Wls5 = 0x00, /* Word Length Select 5 bits/byte */ + Wls6 = 0x01, /* 6 bits/byte */ + Wls7 = 0x02, /* 7 bits/byte */ + Wls8 = 0x03, /* 8 bits/byte */ + WlsMASK = 0x03, + Stb = 0x04, /* 2 stop bits */ + Pen = 0x08, /* Parity Enable */ + Eps = 0x10, /* Even Parity Select */ + Stp = 0x20, /* Stick Parity */ + Brk = 0x40, /* Break */ + Dlab = 0x80, /* Divisor Latch Access Bit */ +}; + +enum { /* Mcr */ + Dtr = 0x01, /* Data Terminal Ready */ + Rts = 0x02, /* Ready To Send */ + Out1 = 0x04, /* no longer in use */ + Ie = 0x08, /* IRQ Enable */ + Dm = 0x10, /* Diagnostic Mode loopback */ +}; + +enum { /* Lsr */ + Dr = 0x01, /* Data Ready */ + Oe = 0x02, /* Overrun Error */ + Pe = 0x04, /* Parity Error */ + Fe = 0x08, /* Framing Error */ + Bi = 0x10, /* Break Interrupt */ + Thre = 0x20, /* Thr Empty */ + Temt = 0x40, /* Tramsmitter Empty */ + FIFOerr = 0x80, /* error in receiver FIFO */ +}; + +enum { /* Msr */ + Dcts = 0x01, /* Delta Cts */ + Ddsr = 0x02, /* Delta Dsr */ + Teri = 0x04, /* Trailing Edge of Ri */ + Ddcd = 0x08, /* Delta Dcd */ + Cts = 0x10, /* Clear To Send */ + Dsr = 0x20, /* Data Set Ready */ + Ri = 0x40, /* Ring Indicator */ + Dcd = 0x80, /* Data Set Ready */ +}; + +typedef struct Ctlr { + int io; + int irq; + int tbdf; + int iena; + + uchar sticky[8]; + + Lock; + int fifo; + int fena; +} Ctlr; + +extern PhysUart i8250physuart; + +static Ctlr i8250ctlr[2] = { +{ .io = Uart0, + .irq = Uart0IRQ, + .tbdf = BUSUNKNOWN, }, + +{ .io = Uart1, + .irq = Uart1IRQ, + .tbdf = BUSUNKNOWN, }, +}; + +static Uart i8250uart[2] = { +{ .regs = &i8250ctlr[0], + .name = "COM1", + .freq = UartFREQ, + .phys = &i8250physuart, + .special=0, + .next = &i8250uart[1], }, + +{ .regs = &i8250ctlr[1], + .name = "COM2", + .freq = UartFREQ, + .phys = &i8250physuart, + .special=0, + .next = nil, }, +}; + +static Uart* consuart; + +#define csr8r(c, r) inb((c)->io+(r)) +#define csr8w(c, r, v) outb((c)->io+(r), (c)->sticky[(r)]|(v)) + +static long +i8250status(Uart* uart, void* buf, long n, long offset) +{ + char *p; + Ctlr *ctlr; + uchar ier, lcr, mcr, msr; + + ctlr = uart->regs; + p = malloc(READSTR); + mcr = ctlr->sticky[Mcr]; + msr = csr8r(ctlr, Msr); + ier = ctlr->sticky[Ier]; + lcr = ctlr->sticky[Lcr]; + snprint(p, READSTR, + "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", + + uart->baud, + uart->hup_dcd, + (msr & Dsr) != 0, + uart->hup_dsr, + (lcr & WlsMASK) + 5, + (ier & Ems) != 0, + (lcr & Pen) ? ((lcr & Eps) ? 'e': 'o'): 'n', + (mcr & Rts) != 0, + (lcr & Stb) ? 2: 1, + ctlr->fena, + + uart->dev, + uart->type, + uart->ferr, + uart->oerr, + (msr & Cts) ? " cts": "", + (msr & Dsr) ? " dsr": "", + (msr & Dcd) ? " dcd": "", + (msr & Ri) ? " ring": "" + ); + n = readstr(offset, buf, n, p); + free(p); + + return n; +} + +static void +i8250fifo(Uart* uart, int on) +{ + int i; + Ctlr *ctlr; + + /* + * Toggle FIFOs: + * if none, do nothing; + * reset the Rx and Tx FIFOs; + * empty the Rx buffer and clear any interrupt conditions; + * if enabling, try to turn them on. + */ + ctlr = uart->regs; + + ilock(ctlr); + if(!ctlr->fifo){ + csr8w(ctlr, Fcr, FIFOtclr|FIFOrclr); + for(i = 0; i < 16; i++){ + csr8r(ctlr, Iir); + csr8r(ctlr, Rbr); + } + + ctlr->fena = 0; + if(on){ + csr8w(ctlr, Fcr, FIFO4|FIFOena); + if(!(csr8r(ctlr, Iir) & Ife)) + ctlr->fifo = 1; + ctlr->fena = 1; + } + } + iunlock(ctlr); +} + +static void +i8250dtr(Uart* uart, int on) +{ + Ctlr *ctlr; + + /* + * Toggle DTR. + */ + ctlr = uart->regs; + if(on) + ctlr->sticky[Mcr] |= Dtr; + else + ctlr->sticky[Mcr] &= ~Dtr; + csr8w(ctlr, Mcr, 0); +} + +static void +i8250rts(Uart* uart, int on) +{ + Ctlr *ctlr; + + /* + * Toggle RTS. + */ + ctlr = uart->regs; + if(on) + ctlr->sticky[Mcr] |= Rts; + else + ctlr->sticky[Mcr] &= ~Rts; + csr8w(ctlr, Mcr, 0); +} + +static void +i8250modemctl(Uart* uart, int on) +{ + Ctlr *ctlr; + + ctlr = uart->regs; + ilock(&uart->tlock); + if(on){ + ctlr->sticky[Ier] |= Ems; + csr8w(ctlr, Ier, 0); + uart->modem = 1; + uart->cts = csr8r(ctlr, Msr) & Cts; + } + else{ + ctlr->sticky[Ier] &= ~Ems; + csr8w(ctlr, Ier, 0); + uart->modem = 0; + uart->cts = 1; + } + iunlock(&uart->tlock); + + /* modem needs fifo */ + (*uart->phys->fifo)(uart, on); +} + +static int +i8250parity(Uart* uart, int parity) +{ + int lcr; + Ctlr *ctlr; + + ctlr = uart->regs; + lcr = ctlr->sticky[Lcr] & ~(Eps|Pen); + + switch(parity){ + case 'e': + lcr |= Eps|Pen; + break; + case 'o': + lcr |= Pen; + break; + case 'n': + default: + break; + } + ctlr->sticky[Lcr] = lcr; + csr8w(ctlr, Lcr, 0); + + uart->parity = parity; + + return 0; +} + +static int +i8250stop(Uart* uart, int stop) +{ + int lcr; + Ctlr *ctlr; + + ctlr = uart->regs; + lcr = ctlr->sticky[Lcr] & ~Stb; + + switch(stop){ + case 1: + break; + case 2: + lcr |= Stb; + break; + default: + return -1; + } + ctlr->sticky[Lcr] = lcr; + csr8w(ctlr, Lcr, 0); + + uart->stop = stop; + + return 0; +} + +static int +i8250bits(Uart* uart, int bits) +{ + int lcr; + Ctlr *ctlr; + + ctlr = uart->regs; + lcr = ctlr->sticky[Lcr] & ~WlsMASK; + + switch(bits){ + case 5: + lcr |= Wls5; + break; + case 6: + lcr |= Wls6; + break; + case 7: + lcr |= Wls7; + break; + case 8: + lcr |= Wls8; + break; + default: + return -1; + } + ctlr->sticky[Lcr] = lcr; + csr8w(ctlr, Lcr, 0); + + uart->bits = bits; + + return 0; +} + +static int +i8250baud(Uart* uart, int baud) +{ + ulong bgc; + Ctlr *ctlr; + + /* + * Set the Baud rate by calculating and setting the Baud rate + * Generator Constant. This will work with fairly non-standard + * Baud rates. + */ + if(uart->freq == 0 || baud <= 0) + return -1; + bgc = (uart->freq+8*baud-1)/(16*baud); + + ctlr = uart->regs; + csr8w(ctlr, Lcr, Dlab); + outb(ctlr->io+Dlm, bgc>>8); + outb(ctlr->io+Dll, bgc); + csr8w(ctlr, Lcr, 0); + + uart->baud = baud; + + return 0; +} + +static void +i8250break(Uart* uart, int ms) +{ + Ctlr *ctlr; + + /* + * Send a break. + */ + if(ms == 0) + ms = 200; + + ctlr = uart->regs; + csr8w(ctlr, Lcr, Brk); + tsleep(&up->sleep, return0, 0, ms); + csr8w(ctlr, Lcr, 0); +} + +static void +i8250kick(Uart* uart) +{ + int i; + Ctlr *ctlr; + + if(uart->cts == 0 || uart->blocked) + return; + + /* + * 128 here is an arbitrary limit to make sure + * we don't stay in this loop too long. If the + * chip's output queue is longer than 128, too + * bad -- presotto + */ + ctlr = uart->regs; + for(i = 0; i < 128; i++){ + if(!(csr8r(ctlr, Lsr) & Thre)) + break; + if(uart->op >= uart->oe && uartstageoutput(uart) == 0) + break; + outb(ctlr->io+Thr, *(uart->op++)); + } +} + +static void +i8250interrupt(Ureg*, void* arg) +{ + Ctlr *ctlr; + Uart *uart; + int iir, lsr, old, r; + + uart = arg; + + ctlr = uart->regs; + for(iir = csr8r(ctlr, Iir); !(iir & Ip); iir = csr8r(ctlr, Iir)){ + switch(iir & IirMASK){ + case Ims: /* Ms interrupt */ + r = csr8r(ctlr, Msr); + if(r & Dcts){ + ilock(&uart->tlock); + old = uart->cts; + uart->cts = r & Cts; + if(old == 0 && uart->cts) + uart->ctsbackoff = 2; + iunlock(&uart->tlock); + } + if(r & Ddsr){ + old = r & Dsr; + if(uart->hup_dsr && uart->dsr && !old) + uart->dohup = 1; + uart->dsr = old; + } + if(r & Ddcd){ + old = r & Dcd; + if(uart->hup_dcd && uart->dcd && !old) + uart->dohup = 1; + uart->dcd = old; + } + break; + case Ithre: /* Thr Empty */ + uartkick(uart); + break; + case Irda: /* Received Data Available */ + case Ictoi: /* Character Time-out Indication */ + /* + * Consume any received data. + * If the received byte came in with a break, + * parity or framing error, throw it away; + * overrun is an indication that something has + * already been tossed. + */ + while((lsr = csr8r(ctlr, Lsr)) & Dr){ + if(lsr & Oe) + uart->oerr++; + if(lsr & Pe) + uart->perr++; + if(lsr & Fe) + uart->ferr++; + r = csr8r(ctlr, Rbr); + if(!(lsr & (Bi|Fe|Pe))) + uartrecv(uart, r); + } + break; + default: + iprint("weird uart interrupt 0x%2.2uX\n", iir); + break; + } + } +} + +static void +i8250disable(Uart* uart) +{ + Ctlr *ctlr; + + /* + * Turn off DTR and RTS, disable interrupts and fifos. + */ + (*uart->phys->dtr)(uart, 0); + (*uart->phys->rts)(uart, 0); + (*uart->phys->fifo)(uart, 0); + + ctlr = uart->regs; + ctlr->sticky[Ier] = 0; + csr8w(ctlr, Ier, 0); +} + +static void +i8250enable(Uart* uart, int ie) +{ + Ctlr *ctlr; + + /* + * Enable interrupts and turn on DTR and RTS. + * Be careful if this is called to set up a polled serial line + * early on not to try to enable interrupts as interrupt- + * -enabling mechanisms might not be set up yet. + */ + ctlr = uart->regs; + if(ie){ + if(ctlr->iena == 0){ + intrenable(ctlr->irq, i8250interrupt, uart, ctlr->tbdf, uart->name); + ctlr->iena = 1; + } + ctlr->sticky[Ier] = Ethre|Erda; + ctlr->sticky[Mcr] |= Ie; + } + else{ + ctlr->sticky[Ier] = 0; + ctlr->sticky[Mcr] = 0; + } + csr8w(ctlr, Ier, ctlr->sticky[Ier]); + csr8w(ctlr, Mcr, ctlr->sticky[Mcr]); + + (*uart->phys->dtr)(uart, 1); + (*uart->phys->rts)(uart, 1); +} + +static Uart* +i8250pnp(void) +{ + return i8250uart; +} + +PhysUart i8250physuart = { + .name = "i8250", + .pnp = i8250pnp, + .enable = i8250enable, + .disable = i8250disable, + .kick = i8250kick, + .dobreak = i8250break, + .baud = i8250baud, + .bits = i8250bits, + .stop = i8250stop, + .parity = i8250parity, + .modemctl = i8250modemctl, + .rts = i8250rts, + .dtr = i8250dtr, + .status = i8250status, + .fifo = i8250fifo, +}; + +int +serialgetc(void) +{ + return -1; +} + +static void +i8250putc(Ctlr* ctlr, int c) +{ + int i; + + for(i = 0; i < 128; i++){ + if(csr8r(ctlr, Lsr) & Thre) + break; + delay(1); + } + outb(ctlr->io+Thr, c); +} + +static void +i8250puts(char* s, int n) +{ + Ctlr *ctlr; + Uart *uart; + + if((uart = consuart) == nil) + return; + + ctlr = uart->regs; + while(n--){ + if(*s == '\n') + i8250putc(ctlr, '\r'); + i8250putc(ctlr, *s++); + } +} + +void +i8250console(void) +{ + Uart *uart; + int n; + char *cmd, *p; + + if((p = getconf("console")) == nil) + return; + n = strtoul(p, &cmd, 0); + if(p == cmd) + return; + switch(n){ + default: + return; + case 0: + uart = &i8250uart[0]; + break; + case 1: + uart = &i8250uart[1]; + break; + } + + if(*cmd == 0) + cmd = "b9600 l8 pn s1"; + uartctl(uart, cmd); + (*uart->phys->enable)(uart, 0); + + consuart = uart; + serialputs = i8250puts; + uart->console = 1; +} diff --git a/pc/sdata.c b/pc/sdata.c index bc57d805c76011c364753bf2ef8e7062bde14833..d936fa8357d488222010801c40cecc2d86cd93fd 100644 --- a/pc/sdata.c +++ b/pc/sdata.c @@ -531,10 +531,10 @@ ataidentify(int cmdport, int ctlport, int dev, int pkt, void* info) static Drive* atadrive(int cmdport, int ctlport, int dev) { - ushort *sp; Drive *drive; int as, i, pkt; uchar buf[512], *p; + ushort iconfig, *sp; atadebug(0, 0, "identify: port 0x%uX dev 0x%2.2uX\n", cmdport, dev); pkt = 1; @@ -567,8 +567,18 @@ retry: } drive->secsize = 512; - if((drive->info[Iconfig] & 0xC000) == 0x8000){ - if(drive->info[Iconfig] & 0x01) + + /* + * Beware the CompactFlash Association feature set. + * Now, why this value in Iconfig just walks all over the bit + * definitions used in the other parts of the ATA/ATAPI standards + * is a mystery and a sign of true stupidity on someone's part. + * Anyway, the standard says if this value is 0x848A then it's + * CompactFlash and it's NOT a packet device. + */ + iconfig = drive->info[Iconfig]; + if(iconfig != 0x848A && (iconfig & 0xC000) == 0x8000){ + if(iconfig & 0x01) drive->pkt = 16; else drive->pkt = 12; @@ -598,7 +608,7 @@ retry: if(DEBUG & DbgCONFIG){ print("dev %2.2uX port %uX config %4.4uX capabilities %4.4uX", dev, cmdport, - drive->info[Iconfig], drive->info[Icapabilities]); + iconfig, drive->info[Icapabilities]); print(" mwdma %4.4uX", drive->info[Imwdma]); if(drive->info[Ivalid] & 0x04) print(" udma %4.4uX", drive->info[Iudma]); diff --git a/port/sysfile.c b/port/sysfile.c index 17a7c4a29e28467dae525c931591644f31331aa2..5fb38bcf14cd0712bf98ccb0b6c09aaf4842cc88 100644 --- a/port/sysfile.c +++ b/port/sysfile.c @@ -414,18 +414,17 @@ sys_read(ulong *arg) long syspread(ulong *arg) { - union { - uvlong v; - ulong u[2]; - } o; + uvlong v; + va_list list; - if(arg[3]==~0UL && arg[4]==~0UL) - return read(arg, nil); + va_start(list, arg[2]); + v = va_arg(list, uvlong); + va_end(list); - o.u[0] = arg[3]; - o.u[1] = arg[4]; + if(v ==~0ULL) + return read(arg, nil); - return read(arg, &o.v); + return read(arg, &v); } static long @@ -487,18 +486,17 @@ sys_write(ulong *arg) long syspwrite(ulong *arg) { - union { - uvlong v; - ulong u[2]; - } o; + uvlong v; + va_list list; - if(arg[3]==~0UL && arg[4]==~0UL) - return write(arg, nil); + va_start(list, arg[2]); + v = va_arg(list, uvlong); + va_end(list); - o.u[0] = arg[3]; - o.u[1] = arg[4]; + if(v ==~0ULL) + return write(arg, nil); - return write(arg, &o.v); + return write(arg, &v); } static void