From f96852eceb879408150badd9d08bf8ccf56cad9e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 11 Dec 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-12-11 --- alphapc/devfloppy.c | 1077 +--------------------------- alphapc/ether2114x.c | 1582 +----------------------------------------- alphapc/etherif.h | 1 - alphapc/mouse.c | 312 +-------- alphapc/screen.h | 9 +- alphapc/uarti8250.c | 649 +---------------- alphapc/vga.c | 226 +----- alphapc/vgargb524.c | 238 +------ alphapc/vgas3.c | 507 +------------- alphapc/vgasavage.c | 1 + alphapc/vgatvp3026.c | 190 +---- alphapc/vgax.c | 104 +-- 12 files changed, 15 insertions(+), 4881 deletions(-) create mode 100644 alphapc/vgasavage.c diff --git a/alphapc/devfloppy.c b/alphapc/devfloppy.c index 55470ed369a384b66fb956de0fe4a2041d532865..be42920f1fbda4889d7d2c91d654b8d60875dd47 100644 --- a/alphapc/devfloppy.c +++ b/alphapc/devfloppy.c @@ -1,1076 +1 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "io.h" -#include "../port/error.h" - -#include "floppy.h" - -/* Intel 82077A (8272A compatible) floppy controller */ - -/* This module expects the following functions to be defined - * elsewhere: - * - * inb() - * outb() - * floppyexec() - * floppyeject() - * floppysetup0() - * floppysetup1() - * dmainit() - * dmasetup() - * dmaend() - * - * On DMA systems, floppyexec() should be an empty function; - * on non-DMA systems, dmaend() should be an empty function; - * dmasetup() may enforce maximum transfer sizes. - */ - -enum { - /* file types */ - Qdir= 0, - Qdata= (1<<2), - Qctl= (2<<2), - Qmask= (3<<2), - - DMAchan= 2, /* floppy dma channel */ -}; - -#define DPRINT if(floppydebug)print -int floppydebug = 0; - -/* - * types of drive (from PC equipment byte) - */ -enum -{ - Tnone= 0, - T360kb= 1, - T1200kb= 2, - T720kb= 3, - T1440kb= 4, -}; - -FType floppytype[] = -{ - { "3½HD", T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, }, - { "3½DD", T1440kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, }, - { "3½DD", T720kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, }, - { "5¼HD", T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, }, - { "5¼DD", T1200kb, 512, 9, 2, 2, 40, 0x2A, 0x50, 1, }, - { "ATT3B1", T1200kb, 512, 8, 2, 2, 48, 0x2A, 0x50, 1, }, - { "5¼DD", T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, }, -}; - -/* - * bytes per sector encoding for the controller. - * - index for b2c is is (bytes per sector/128). - * - index for c2b is code from b2c - */ -static int b2c[] = -{ -[1] 0, -[2] 1, -[4] 2, -[8] 3, -}; -static int c2b[] = -{ - 128, - 256, - 512, - 1024, -}; - -FController fl; - -#define MOTORBIT(i) (1<<((i)+4)) - -/* - * predeclared - */ -static int cmddone(void*); -static void floppyformat(FDrive*, Cmdbuf*); -static void floppykproc(void*); -static void floppypos(FDrive*,long); -static int floppyrecal(FDrive*); -static int floppyresult(void); -static void floppyrevive(void); -static long floppyseek(FDrive*, long); -static int floppysense(void); -static void floppywait(int); -static long floppyxfer(FDrive*, int, void*, long, long); - -Dirtab floppydir[]={ - ".", {Qdir, 0, QTDIR}, 0, 0550, - "fd0disk", {Qdata + 0}, 0, 0660, - "fd0ctl", {Qctl + 0}, 0, 0660, - "fd1disk", {Qdata + 1}, 0, 0660, - "fd1ctl", {Qctl + 1}, 0, 0660, - "fd2disk", {Qdata + 2}, 0, 0660, - "fd2ctl", {Qctl + 2}, 0, 0660, - "fd3disk", {Qdata + 3}, 0, 0660, - "fd3ctl", {Qctl + 3}, 0, 0660, -}; -#define NFDIR 2 /* directory entries/drive */ - -enum -{ - CMdebug, - CMeject, - CMformat, - CMreset, -}; - -static Cmdtab floppyctlmsg[] = -{ - CMdebug, "debug", 1, - CMeject, "eject", 1, - CMformat, "format", 0, - CMreset, "reset", 1, -}; - -static void -fldump(void) -{ - DPRINT("sra %ux srb %ux dor %ux msr %ux dir %ux\n", inb(Psra), inb(Psrb), - inb(Pdor), inb(Pmsr), inb(Pdir)); -} - -/* - * set floppy drive to its default type - */ -static void -floppysetdef(FDrive *dp) -{ - FType *t; - - for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++) - if(dp->dt == t->dt){ - dp->t = t; - floppydir[1+NFDIR*dp->dev].length = dp->t->cap; - break; - } -} - -static void -floppyreset(void) -{ - FDrive *dp; - FType *t; - ulong maxtsize; - - floppysetup0(&fl); - if(fl.ndrive == 0) - return; - - /* - * init dependent parameters - */ - maxtsize = 0; - for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){ - t->cap = t->bytes * t->heads * t->sectors * t->tracks; - t->bcode = b2c[t->bytes/128]; - t->tsize = t->bytes * t->sectors; - if(maxtsize < t->tsize) - maxtsize = t->tsize; - } - - dmainit(DMAchan, maxtsize); - - /* - * allocate the drive storage - */ - fl.d = xalloc(fl.ndrive*sizeof(FDrive)); - fl.selected = fl.d; - - /* - * stop the motors - */ - fl.motor = 0; - delay(10); - outb(Pdor, fl.motor | Fintena | Fena); - delay(10); - - /* - * init drives - */ - for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){ - dp->dev = dp - fl.d; - dp->dt = T1440kb; - floppysetdef(dp); - dp->cyl = -1; /* because we don't know */ - dp->cache = (uchar*)xspanalloc(maxtsize, BY2PG, 64*1024); - dp->ccyl = -1; - dp->vers = 0; - } - - /* - * first operation will recalibrate - */ - fl.confused = 1; - - floppysetup1(&fl); -} - -static Chan* -floppyattach(char *spec) -{ - static int kstarted; - - if(fl.ndrive == 0) - error(Enodev); - - if(kstarted == 0){ - /* - * watchdog to turn off the motors - */ - kstarted = 1; - kproc("floppy", floppykproc, 0); - } - return devattach('f', spec); -} - -static Walkqid* -floppywalk(Chan *c, Chan *nc, char **name, int nname) -{ - return devwalk(c, nc, name, nname, floppydir, 1+fl.ndrive*NFDIR, devgen); -} - -static int -floppystat(Chan *c, uchar *dp, int n) -{ - return devstat(c, dp, n, floppydir, 1+fl.ndrive*NFDIR, devgen); -} - -static Chan* -floppyopen(Chan *c, int omode) -{ - return devopen(c, omode, floppydir, 1+fl.ndrive*NFDIR, devgen); -} - -static void -floppyclose(Chan *) -{ -} - -static void -islegal(ulong offset, long n, FDrive *dp) -{ - if(offset % dp->t->bytes) - error(Ebadarg); - if(n % dp->t->bytes) - error(Ebadarg); -} - -/* - * check if the floppy has been replaced under foot. cause - * an error if it has. - * - * a seek and a read clears the condition. this was determined - * experimentally, there has to be a better way. - * - * if the read fails, cycle through the possible floppy - * density till one works or we've cycled through all - * possibilities for this drive. - */ -static void -changed(Chan *c, FDrive *dp) -{ - ulong old; - FType *start; - - /* - * if floppy has changed or first time through - */ - if((inb(Pdir)&Fchange) || dp->vers == 0){ - DPRINT("changed\n"); - fldump(); - dp->vers++; - start = dp->t; - dp->maxtries = 3; /* limit it when we're probing */ - - /* floppyon will fail if there's a controller but no drive */ - dp->confused = 1; /* make floppyon recal */ - if(floppyon(dp) < 0) - error(Eio); - - /* seek to the first track */ - floppyseek(dp, dp->t->heads*dp->t->tsize); - while(waserror()){ - /* - * if first attempt doesn't reset changed bit, there's - * no floppy there - */ - if(inb(Pdir)&Fchange) - nexterror(); - - while(++dp->t){ - if(dp->t == &floppytype[nelem(floppytype)]) - dp->t = floppytype; - if(dp->dt == dp->t->dt) - break; - } - floppydir[1+NFDIR*dp->dev].length = dp->t->cap; - - /* floppyon will fail if there's a controller but no drive */ - if(floppyon(dp) < 0) - error(Eio); - - DPRINT("changed: trying %s\n", dp->t->name); - fldump(); - if(dp->t == start) - nexterror(); - } - - /* if the read succeeds, we've got the density right */ - floppyxfer(dp, Fread, dp->cache, 0, dp->t->tsize); - poperror(); - dp->maxtries = 20; - } - - old = c->qid.vers; - c->qid.vers = dp->vers; - if(old && old != dp->vers) - error(Eio); -} - -static int -readtrack(FDrive *dp, int cyl, int head) -{ - int i, nn, sofar; - ulong pos; - - nn = dp->t->tsize; - if(dp->ccyl==cyl && dp->chead==head) - return nn; - pos = (cyl*dp->t->heads+head) * nn; - for(sofar = 0; sofar < nn; sofar += i){ - dp->ccyl = -1; - i = floppyxfer(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar); - if(i <= 0) - return -1; - } - dp->ccyl = cyl; - dp->chead = head; - return nn; -} - -static long -floppyread(Chan *c, void *a, long n, vlong off) -{ - FDrive *dp; - long rv; - int sec, head, cyl; - long len; - uchar *aa; - ulong offset = off; - - 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]; - switch ((int)(c->qid.path & Qmask)) { - case Qdata: - islegal(offset, n, dp); - aa = a; - - qlock(&fl); - if(waserror()){ - qunlock(&fl); - nexterror(); - } - floppyon(dp); - changed(c, dp); - for(rv = 0; rv < n; rv += len){ - /* - * all xfers come out of the track cache - */ - dp->len = n - rv; - floppypos(dp, offset+rv); - cyl = dp->tcyl; - head = dp->thead; - len = dp->len; - sec = dp->tsec; - if(readtrack(dp, cyl, head) < 0) - break; - memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len); - } - qunlock(&fl); - poperror(); - - break; - case Qctl: - return readstr(offset, a, n, dp->t->name); - default: - panic("floppyread: bad qid"); - } - - return rv; -} - -static long -floppywrite(Chan *c, void *a, long n, vlong off) -{ - FDrive *dp; - long rv, i; - char *aa = a; - Cmdbuf *cb; - Cmdtab *ct; - ulong offset = off; - - rv = 0; - dp = &fl.d[c->qid.path & ~Qmask]; - switch ((int)(c->qid.path & Qmask)) { - case Qdata: - islegal(offset, n, dp); - qlock(&fl); - if(waserror()){ - qunlock(&fl); - nexterror(); - } - floppyon(dp); - changed(c, dp); - for(rv = 0; rv < n; rv += i){ - floppypos(dp, offset+rv); - if(dp->tcyl == dp->ccyl) - dp->ccyl = -1; - i = floppyxfer(dp, Fwrite, aa+rv, offset+rv, n-rv); - if(i < 0) - break; - if(i == 0) - error(Eio); - } - qunlock(&fl); - poperror(); - break; - case Qctl: - rv = n; - cb = parsecmd(a, n); - if(waserror()){ - free(cb); - nexterror(); - } - qlock(&fl); - if(waserror()){ - qunlock(&fl); - nexterror(); - } - ct = lookupcmd(cb, floppyctlmsg, nelem(floppyctlmsg)); - switch(ct->index){ - case CMeject: - floppyeject(dp); - break; - case CMformat: - floppyformat(dp, cb); - break; - case CMreset: - fl.confused = 1; - floppyon(dp); - break; - case CMdebug: - floppydebug = 1; - break; - } - poperror(); - qunlock(&fl); - poperror(); - free(cb); - break; - default: - panic("floppywrite: bad qid"); - } - - return rv; -} - -static void -floppykproc(void *) -{ - FDrive *dp; - - while(waserror()) - ; - for(;;){ - for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++){ - if((fl.motor&MOTORBIT(dp->dev)) - && TK2SEC(m->ticks - dp->lasttouched) > 5 - && canqlock(&fl)){ - if(TK2SEC(m->ticks - dp->lasttouched) > 5) - floppyoff(dp); - qunlock(&fl); - } - } - tsleep(&fl.kr, return0, 0, 1000); - } -} - -/* - * start a floppy drive's motor. - */ -static int -floppyon(FDrive *dp) -{ - int alreadyon; - int tries; - - if(fl.confused) - floppyrevive(); - - /* start motor and select drive */ - alreadyon = fl.motor & MOTORBIT(dp->dev); - fl.motor |= MOTORBIT(dp->dev); - outb(Pdor, fl.motor | Fintena | Fena | dp->dev); - if(!alreadyon){ - /* wait for drive to spin up */ - tsleep(&dp->r, return0, 0, 750); - - /* clear any pending interrupts */ - floppysense(); - } - - /* set transfer rate */ - if(fl.rate != dp->t->rate){ - fl.rate = dp->t->rate; - outb(Pdsr, fl.rate); - } - - /* get drive to a known cylinder */ - if(dp->confused) - for(tries = 0; tries < 4; tries++) - if(floppyrecal(dp) >= 0) - break; - dp->lasttouched = m->ticks; - fl.selected = dp; - - /* return -1 if this didn't work */ - if(dp->confused) - return -1; - return 0; -} - -/* - * stop the floppy if it hasn't been used in 5 seconds - */ -static void -floppyoff(FDrive *dp) -{ - fl.motor &= ~MOTORBIT(dp->dev); - outb(Pdor, fl.motor | Fintena | Fena | dp->dev); -} - -/* - * send a command to the floppy - */ -static int -floppycmd(void) -{ - int i; - int tries; - - fl.nstat = 0; - for(i = 0; i < fl.ncmd; i++){ - for(tries = 0; ; tries++){ - if((inb(Pmsr)&(Ffrom|Fready)) == Fready) - break; - if(tries > 1000){ - DPRINT("cmd %ux can't be sent (%d)\n", fl.cmd[0], i); - fldump(); - - /* empty fifo, might have been a bad command */ - floppyresult(); - return -1; - } - microdelay(8); /* for machine independence */ - } - outb(Pfdata, fl.cmd[i]); - } - return 0; -} - -/* - * get a command result from the floppy - * - * when the controller goes ready waiting for a command - * (instead of sending results), we're done - * - */ -static int -floppyresult(void) -{ - int i, s; - int tries; - - /* get the result of the operation */ - for(i = 0; i < sizeof(fl.stat); i++){ - /* wait for status byte */ - for(tries = 0; ; tries++){ - s = inb(Pmsr)&(Ffrom|Fready); - if(s == Fready){ - fl.nstat = i; - return fl.nstat; - } - if(s == (Ffrom|Fready)) - break; - if(tries > 1000){ - DPRINT("floppyresult: %d stats\n", i); - fldump(); - fl.confused = 1; - return -1; - } - microdelay(8); /* for machine independence */ - } - fl.stat[i] = inb(Pfdata); - } - fl.nstat = sizeof(fl.stat); - return fl.nstat; -} - -/* - * calculate physical address of a logical byte offset into the disk - * - * truncate dp->length if it crosses a track boundary - */ -static void -floppypos(FDrive *dp, long off) -{ - int lsec; - int ltrack; - int end; - - lsec = off/dp->t->bytes; - ltrack = lsec/dp->t->sectors; - dp->tcyl = ltrack/dp->t->heads; - dp->tsec = (lsec % dp->t->sectors) + 1; - dp->thead = (lsec/dp->t->sectors) % dp->t->heads; - - /* - * can't read across track boundaries. - * if so, decrement the bytes to be read. - */ - end = (ltrack+1)*dp->t->sectors*dp->t->bytes; - if(off+dp->len > end) - dp->len = end - off; -} - -/* - * get the interrupt cause from the floppy. - */ -static int -floppysense(void) -{ - fl.ncmd = 0; - fl.cmd[fl.ncmd++] = Fsense; - if(floppycmd() < 0) - return -1; - if(floppyresult() < 2){ - DPRINT("can't read sense response\n"); - fldump(); - fl.confused = 1; - return -1; - } - return 0; -} - -static int -cmddone(void *) -{ - return fl.ncmd == 0; -} - -/* - * Wait for a floppy interrupt. If none occurs in 5 seconds, we - * may have missed one. This only happens on some portables which - * do power management behind our backs. Call the interrupt - * routine to try to clear any conditions. - */ -static void -floppywait(int slow) -{ - tsleep(&fl.r, cmddone, 0, slow ? 5000 : 1000); - if(!cmddone(0)){ - floppyintr(0); - fl.confused = 1; - } -} - -/* - * we've lost the floppy position, go to cylinder 0. - */ -static int -floppyrecal(FDrive *dp) -{ - dp->ccyl = -1; - dp->cyl = -1; - - fl.ncmd = 0; - fl.cmd[fl.ncmd++] = Frecal; - fl.cmd[fl.ncmd++] = dp->dev; - if(floppycmd() < 0) - return -1; - floppywait(1); - if(fl.nstat < 2){ - DPRINT("recalibrate: confused %ux\n", inb(Pmsr)); - fl.confused = 1; - return -1; - } - if((fl.stat[0] & (Codemask|Seekend)) != Seekend){ - DPRINT("recalibrate: failed\n"); - dp->confused = 1; - return -1; - } - dp->cyl = fl.stat[1]; - if(dp->cyl != 0){ - DPRINT("recalibrate: wrong cylinder %d\n", dp->cyl); - dp->cyl = -1; - dp->confused = 1; - return -1; - } - - dp->confused = 0; - return 0; -} - -/* - * if the controller or a specific drive is in a confused state, - * reset it and get back to a known state - */ -static void -floppyrevive(void) -{ - FDrive *dp; - - /* - * reset the controller if it's confused - */ - if(fl.confused){ - DPRINT("floppyrevive in\n"); - fldump(); - - /* reset controller and turn all motors off */ - splhi(); - fl.ncmd = 1; - fl.cmd[0] = 0; - outb(Pdor, 0); - delay(10); - outb(Pdor, Fintena|Fena); - delay(10); - spllo(); - fl.motor = 0; - fl.confused = 0; - floppywait(0); - - /* mark all drives in an unknown state */ - for(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++) - dp->confused = 1; - - /* set rate to a known value */ - outb(Pdsr, 0); - fl.rate = 0; - - DPRINT("floppyrevive out\n"); - fldump(); - } -} - -/* - * seek to the target cylinder - * - * interrupt, no results - */ -static long -floppyseek(FDrive *dp, long off) -{ - floppypos(dp, off); - if(dp->cyl == dp->tcyl) - return dp->tcyl; - dp->cyl = -1; - - fl.ncmd = 0; - fl.cmd[fl.ncmd++] = Fseek; - fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev; - fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps; - if(floppycmd() < 0) - return -1; - floppywait(1); - if(fl.nstat < 2){ - DPRINT("seek: confused\n"); - fl.confused = 1; - return -1; - } - if((fl.stat[0] & (Codemask|Seekend)) != Seekend){ - DPRINT("seek: failed\n"); - dp->confused = 1; - return -1; - } - - dp->cyl = dp->tcyl; - return dp->tcyl; -} - -/* - * read or write to floppy. try up to three times. - */ -static long -floppyxfer(FDrive *dp, int cmd, void *a, long off, long n) -{ - long offset; - int tries; - - if(off >= dp->t->cap) - return 0; - if(off + n > dp->t->cap) - n = dp->t->cap - off; - - /* retry on error (until it gets ridiculous) */ - tries = 0; - while(waserror()){ - if(tries++ >= dp->maxtries) - nexterror(); - DPRINT("floppyxfer: retrying\n"); - } - - dp->len = n; - if(floppyseek(dp, off) < 0){ - DPRINT("xfer: seek failed\n"); - dp->confused = 1; - error(Eio); - } - - /* - * set up the dma (dp->len may be trimmed) - */ - if(waserror()){ - dmaend(DMAchan); - nexterror(); - } - dp->len = dmasetup(DMAchan, a, dp->len, cmd==Fread); - if(dp->len < 0) - error(Eio); - - /* - * start operation - */ - fl.ncmd = 0; - fl.cmd[fl.ncmd++] = cmd | (dp->t->heads > 1 ? Fmulti : 0); - fl.cmd[fl.ncmd++] = (dp->thead<<2) | dp->dev; - fl.cmd[fl.ncmd++] = dp->tcyl; - fl.cmd[fl.ncmd++] = dp->thead; - fl.cmd[fl.ncmd++] = dp->tsec; - fl.cmd[fl.ncmd++] = dp->t->bcode; - fl.cmd[fl.ncmd++] = dp->t->sectors; - fl.cmd[fl.ncmd++] = dp->t->gpl; - fl.cmd[fl.ncmd++] = 0xFF; - if(floppycmd() < 0) - error(Eio); - - /* Poll ready bits and transfer data */ - floppyexec((char*)a, dp->len, cmd==Fread); - - /* - * give bus to DMA, floppyintr() will read result - */ - floppywait(0); - dmaend(DMAchan); - poperror(); - - /* - * check for errors - */ - if(fl.nstat < 7){ - DPRINT("xfer: confused\n"); - fl.confused = 1; - error(Eio); - } - if((fl.stat[0] & Codemask)!=0 || fl.stat[1] || fl.stat[2]){ - DPRINT("xfer: failed %ux %ux %ux\n", fl.stat[0], - fl.stat[1], fl.stat[2]); - DPRINT("offset %lud len %ld\n", off, dp->len); - if((fl.stat[0]&Codemask)==Cmdexec && fl.stat[1]==Overrun){ - DPRINT("DMA overrun: retry\n"); - } else - dp->confused = 1; - error(Eio); - } - - /* - * check for correct cylinder - */ - offset = fl.stat[3] * dp->t->heads + fl.stat[4]; - offset = offset*dp->t->sectors + fl.stat[5] - 1; - offset = offset * c2b[fl.stat[6]]; - if(offset != off+dp->len){ - DPRINT("xfer: ends on wrong cyl\n"); - dp->confused = 1; - error(Eio); - } - poperror(); - - dp->lasttouched = m->ticks; - return dp->len; -} - -/* - * format a track - */ -static void -floppyformat(FDrive *dp, Cmdbuf *cb) -{ - int cyl, h, sec; - ulong track; - uchar *buf, *bp; - FType *t; - - /* - * set the type - */ - if(cb->nf == 2){ - for(t = floppytype; t < &floppytype[nelem(floppytype)]; t++){ - if(strcmp(cb->f[1], t->name)==0 && t->dt==dp->dt){ - dp->t = t; - floppydir[1+NFDIR*dp->dev].length = dp->t->cap; - break; - } - } - if(t >= &floppytype[nelem(floppytype)]) - error(Ebadarg); - } else if(cb->nf == 1){ - floppysetdef(dp); - t = dp->t; - } else { - cmderror(cb, "invalid floppy format command"); - SET(t); - } - - /* - * buffer for per track info - */ - buf = smalloc(t->sectors*4); - if(waserror()){ - free(buf); - nexterror(); - } - - /* force a recalibrate to cylinder 0 */ - dp->confused = 1; - if(!waserror()){ - floppyon(dp); - poperror(); - } - - /* - * format a track at time - */ - for(track = 0; track < t->tracks*t->heads; track++){ - cyl = track/t->heads; - h = track % t->heads; - - /* - * seek to track, ignore errors - */ - floppyseek(dp, track*t->tsize); - dp->cyl = cyl; - dp->confused = 0; - - /* - * set up the dma (dp->len may be trimmed) - */ - bp = buf; - for(sec = 1; sec <= t->sectors; sec++){ - *bp++ = cyl; - *bp++ = h; - *bp++ = sec; - *bp++ = t->bcode; - } - if(waserror()){ - dmaend(DMAchan); - nexterror(); - } - if(dmasetup(DMAchan, buf, bp-buf, 0) < 0) - error(Eio); - - /* - * start operation - */ - fl.ncmd = 0; - fl.cmd[fl.ncmd++] = Fformat; - fl.cmd[fl.ncmd++] = (h<<2) | dp->dev; - fl.cmd[fl.ncmd++] = t->bcode; - fl.cmd[fl.ncmd++] = t->sectors; - fl.cmd[fl.ncmd++] = t->fgpl; - fl.cmd[fl.ncmd++] = 0x5a; - if(floppycmd() < 0) - error(Eio); - - /* Poll ready bits and transfer data */ - floppyexec((char *)buf, bp-buf, 0); - - /* - * give bus to DMA, floppyintr() will read result - */ - floppywait(1); - dmaend(DMAchan); - poperror(); - - /* - * check for errors - */ - if(fl.nstat < 7){ - DPRINT("format: confused\n"); - fl.confused = 1; - error(Eio); - } - if((fl.stat[0]&Codemask)!=0 || fl.stat[1]|| fl.stat[2]){ - DPRINT("format: failed %ux %ux %ux\n", - fl.stat[0], fl.stat[1], fl.stat[2]); - dp->confused = 1; - error(Eio); - } - } - free(buf); - dp->confused = 1; - poperror(); -} - -static void -floppyintr(Ureg *) -{ - switch(fl.cmd[0]&~Fmulti){ - case Fread: - case Fwrite: - case Fformat: - case Fdumpreg: - floppyresult(); - break; - case Fseek: - case Frecal: - default: - floppysense(); /* to clear interrupt */ - break; - } - fl.ncmd = 0; - wakeup(&fl.r); -} - -Dev floppydevtab = { - 'f', - "floppy", - - floppyreset, - devinit, - floppyattach, - floppywalk, - floppystat, - floppyopen, - devcreate, - floppyclose, - floppyread, - devbread, - floppywrite, - devbwrite, - devremove, - devwstat, -}; +#include "../pc/devfloppy.c" diff --git a/alphapc/ether2114x.c b/alphapc/ether2114x.c index 2144eefa33f0b3832a9650615ce5965b886444c6..3864d092fd6b809d9805a185245dbc124ebc11ce 100644 --- a/alphapc/ether2114x.c +++ b/alphapc/ether2114x.c @@ -1,1581 +1 @@ -/* - * Digital Semiconductor DECchip 2114x PCI Fast Ethernet LAN Controller. - * To do: - * thresholds; - * ring sizing; - * handle more error conditions; - * tidy setup packet mess; - * push initialisation back to attach; - * full SROM decoding. - */ -#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" - -#include "etherif.h" - -#define DEBUG (0) -#define debug if(DEBUG)print - -enum { - Nrde = 64, - Ntde = 64, -}; - -#define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4) - -enum { /* CRS0 - Bus Mode */ - Swr = 0x00000001, /* Software Reset */ - Bar = 0x00000002, /* Bus Arbitration */ - Dsl = 0x0000007C, /* Descriptor Skip Length (field) */ - Ble = 0x00000080, /* Big/Little Endian */ - Pbl = 0x00003F00, /* Programmable Burst Length (field) */ - Cal = 0x0000C000, /* Cache Alignment (field) */ - Cal8 = 0x00004000, /* 8 longword boundary alignment */ - Cal16 = 0x00008000, /* 16 longword boundary alignment */ - Cal32 = 0x0000C000, /* 32 longword boundary alignment */ - Tap = 0x000E0000, /* Transmit Automatic Polling (field) */ - Dbo = 0x00100000, /* Descriptor Byte Ordering Mode */ - Rml = 0x00200000, /* Read Multiple */ -}; - -enum { /* CSR[57] - Status and Interrupt Enable */ - Ti = 0x00000001, /* Transmit Interrupt */ - Tps = 0x00000002, /* Transmit Process Stopped */ - Tu = 0x00000004, /* Transmit buffer Unavailable */ - Tjt = 0x00000008, /* Transmit Jabber Timeout */ - Unf = 0x00000020, /* transmit UNderFlow */ - Ri = 0x00000040, /* Receive Interrupt */ - Ru = 0x00000080, /* Receive buffer Unavailable */ - Rps = 0x00000100, /* Receive Process Stopped */ - Rwt = 0x00000200, /* Receive Watchdog Timeout */ - Eti = 0x00000400, /* Early Transmit Interrupt */ - Gte = 0x00000800, /* General purpose Timer Expired */ - Fbe = 0x00002000, /* Fatal Bit Error */ - Ais = 0x00008000, /* Abnormal Interrupt Summary */ - Nis = 0x00010000, /* Normal Interrupt Summary */ - Rs = 0x000E0000, /* Receive process State (field) */ - Ts = 0x00700000, /* Transmit process State (field) */ - Eb = 0x03800000, /* Error bits */ -}; - -enum { /* CSR6 - Operating Mode */ - Hp = 0x00000001, /* Hash/Perfect receive filtering mode */ - Sr = 0x00000002, /* Start/stop Receive */ - Ho = 0x00000004, /* Hash-Only filtering mode */ - Pb = 0x00000008, /* Pass Bad frames */ - If = 0x00000010, /* Inverse Filtering */ - Sb = 0x00000020, /* Start/stop Backoff counter */ - Pr = 0x00000040, /* Promiscuous Mode */ - Pm = 0x00000080, /* Pass all Multicast */ - Fd = 0x00000200, /* Full Duplex mode */ - Om = 0x00000C00, /* Operating Mode (field) */ - Fc = 0x00001000, /* Force Collision */ - St = 0x00002000, /* Start/stop Transmission Command */ - Tr = 0x0000C000, /* ThReshold control bits (field) */ - Tr128 = 0x00000000, - Tr256 = 0x00004000, - Tr512 = 0x00008000, - Tr1024 = 0x0000C000, - Ca = 0x00020000, /* CApture effect enable */ - Ps = 0x00040000, /* Port Select */ - Hbd = 0x00080000, /* HeartBeat Disable */ - Imm = 0x00100000, /* IMMediate mode */ - Sf = 0x00200000, /* Store and Forward */ - Ttm = 0x00400000, /* Transmit Threshold Mode */ - Pcs = 0x00800000, /* PCS function */ - Scr = 0x01000000, /* SCRambler mode */ - Mbo = 0x02000000, /* Must Be One */ - Ra = 0x40000000, /* Receive All */ - Sc = 0x80000000, /* Special Capture effect enable */ - - TrMODE = Tr512, /* default transmission threshold */ -}; - -enum { /* CSR9 - ROM and MII Management */ - Scs = 0x00000001, /* serial ROM chip select */ - Sclk = 0x00000002, /* serial ROM clock */ - Sdi = 0x00000004, /* serial ROM data in */ - Sdo = 0x00000008, /* serial ROM data out */ - Ss = 0x00000800, /* serial ROM select */ - Wr = 0x00002000, /* write */ - Rd = 0x00004000, /* read */ - - Mdc = 0x00010000, /* MII management clock */ - Mdo = 0x00020000, /* MII management write data */ - Mii = 0x00040000, /* MII management operation mode (W) */ - Mdi = 0x00080000, /* MII management data in */ -}; - -enum { /* CSR12 - General-Purpose Port */ - Gpc = 0x00000100, /* General Purpose Control */ -}; - -typedef struct Des { - int status; - int control; - ulong addr; - Block* bp; -} Des; - -enum { /* status */ - Of = 0x00000001, /* Rx: OverFlow */ - Ce = 0x00000002, /* Rx: CRC Error */ - Db = 0x00000004, /* Rx: Dribbling Bit */ - Re = 0x00000008, /* Rx: Report on MII Error */ - Rw = 0x00000010, /* Rx: Receive Watchdog */ - Ft = 0x00000020, /* Rx: Frame Type */ - Cs = 0x00000040, /* Rx: Collision Seen */ - Tl = 0x00000080, /* Rx: Frame too Long */ - Ls = 0x00000100, /* Rx: Last deScriptor */ - Fs = 0x00000200, /* Rx: First deScriptor */ - Mf = 0x00000400, /* Rx: Multicast Frame */ - Rf = 0x00000800, /* Rx: Runt Frame */ - Dt = 0x00003000, /* Rx: Data Type (field) */ - De = 0x00004000, /* Rx: Descriptor Error */ - Fl = 0x3FFF0000, /* Rx: Frame Length (field) */ - Ff = 0x40000000, /* Rx: Filtering Fail */ - - Def = 0x00000001, /* Tx: DEFerred */ - Uf = 0x00000002, /* Tx: UnderFlow error */ - Lf = 0x00000004, /* Tx: Link Fail report */ - Cc = 0x00000078, /* Tx: Collision Count (field) */ - Hf = 0x00000080, /* Tx: Heartbeat Fail */ - Ec = 0x00000100, /* Tx: Excessive Collisions */ - Lc = 0x00000200, /* Tx: Late Collision */ - Nc = 0x00000400, /* Tx: No Carrier */ - Lo = 0x00000800, /* Tx: LOss of carrier */ - To = 0x00004000, /* Tx: Transmission jabber timeOut */ - - Es = 0x00008000, /* [RT]x: Error Summary */ - Own = 0x80000000, /* [RT]x: OWN bit */ -}; - -enum { /* control */ - Bs1 = 0x000007FF, /* [RT]x: Buffer 1 Size */ - Bs2 = 0x003FF800, /* [RT]x: Buffer 2 Size */ - - Ch = 0x01000000, /* [RT]x: second address CHained */ - Er = 0x02000000, /* [RT]x: End of Ring */ - - Ft0 = 0x00400000, /* Tx: Filtering Type 0 */ - Dpd = 0x00800000, /* Tx: Disabled PaDding */ - Ac = 0x04000000, /* Tx: Add CRC disable */ - Set = 0x08000000, /* Tx: SETup packet */ - Ft1 = 0x10000000, /* Tx: Filtering Type 1 */ - Fseg = 0x20000000, /* Tx: First SEGment */ - Lseg = 0x40000000, /* Tx: Last SEGment */ - Ic = 0x80000000, /* Tx: Interrupt on Completion */ -}; - -enum { /* PHY registers */ - Bmcr = 0, /* Basic Mode Control */ - Bmsr = 1, /* Basic Mode Status */ - Phyidr1 = 2, /* PHY Identifier #1 */ - Phyidr2 = 3, /* PHY Identifier #2 */ - Anar = 4, /* Auto-Negotiation Advertisment */ - Anlpar = 5, /* Auto-Negotiation Link Partner Ability */ - Aner = 6, /* Auto-Negotiation Expansion */ -}; - -enum { /* Variants */ - Tulip0 = (0x0009<<16)|0x1011, - Tulip3 = (0x0019<<16)|0x1011, - Pnic = (0x0002<<16)|0x11AD, - Pnic2 = (0xC115<<16)|0x11AD, -}; - -typedef struct Ctlr Ctlr; -typedef struct Ctlr { - int port; - Pcidev* pcidev; - Ctlr* next; - int active; - int id; /* (pcidev->did<<16)|pcidev->vid */ - - uchar* srom; - int sromsz; /* address size in bits */ - uchar* sromea; /* MAC address */ - uchar* leaf; - int sct; /* selected connection type */ - int k; /* info block count */ - uchar* infoblock[16]; - int sctk; /* sct block index */ - int curk; /* current block index */ - uchar* type5block; - - int phy[32]; /* logical to physical map */ - int phyreset; /* reset bitmap */ - int curphyad; - int fdx; - int ttm; - - uchar fd; /* option */ - int medium; /* option */ - - int csr6; /* CSR6 - operating mode */ - int mask; /* CSR[57] - interrupt mask */ - int mbps; - - Lock lock; - - Des* rdr; /* receive descriptor ring */ - int nrdr; /* size of rdr */ - int rdrx; /* index into rdr */ - - Lock tlock; - Des* tdr; /* transmit descriptor ring */ - int ntdr; /* size of tdr */ - int tdrh; /* host index into tdr */ - int tdri; /* interface index into tdr */ - int ntq; /* descriptors active */ - int ntqmax; - Block* setupbp; - - ulong of; /* receive statistics */ - ulong ce; - ulong cs; - ulong tl; - ulong rf; - ulong de; - - ulong ru; - ulong rps; - ulong rwt; - - ulong uf; /* transmit statistics */ - ulong ec; - ulong lc; - ulong nc; - ulong lo; - ulong to; - - ulong tps; - ulong tu; - ulong tjt; - ulong unf; -} Ctlr; - -static Ctlr* ctlrhead; -static Ctlr* ctlrtail; - -#define csr32r(c, r) (inl((c)->port+((r)*8))) -#define csr32w(c, r, l) (outl((c)->port+((r)*8), (ulong)(l))) - -static void -promiscuous(void* arg, int on) -{ - Ctlr *ctlr; - - ctlr = ((Ether*)arg)->ctlr; - ilock(&ctlr->lock); - if(on) - ctlr->csr6 |= Pr; - else - ctlr->csr6 &= ~Pr; - csr32w(ctlr, 6, ctlr->csr6); - iunlock(&ctlr->lock); -} - -static void -attach(Ether* ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(&ctlr->lock); - if(!(ctlr->csr6 & Sr)){ - ctlr->csr6 |= Sr; - csr32w(ctlr, 6, ctlr->csr6); - } - iunlock(&ctlr->lock); -} - -static long -ifstat(Ether* ether, void* a, long n, ulong offset) -{ - Ctlr *ctlr; - char *buf, *p; - int i, l, len; - - ctlr = ether->ctlr; - - ether->crcs = ctlr->ce; - ether->frames = ctlr->rf+ctlr->cs; - ether->buffs = ctlr->de+ctlr->tl; - ether->overflows = ctlr->of; - - if(n == 0) - return 0; - - p = malloc(READSTR); - l = snprint(p, READSTR, "Overflow: %lud\n", ctlr->of); - l += snprint(p+l, READSTR-l, "Ru: %lud\n", ctlr->ru); - l += snprint(p+l, READSTR-l, "Rps: %lud\n", ctlr->rps); - l += snprint(p+l, READSTR-l, "Rwt: %lud\n", ctlr->rwt); - l += snprint(p+l, READSTR-l, "Tps: %lud\n", ctlr->tps); - l += snprint(p+l, READSTR-l, "Tu: %lud\n", ctlr->tu); - l += snprint(p+l, READSTR-l, "Tjt: %lud\n", ctlr->tjt); - l += snprint(p+l, READSTR-l, "Unf: %lud\n", ctlr->unf); - l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->ce); - l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->cs); - l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->tl); - l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->rf); - l += snprint(p+l, READSTR-l, "Descriptor Error: %lud\n", ctlr->de); - l += snprint(p+l, READSTR-l, "Underflow Error: %lud\n", ctlr->uf); - l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec); - l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->lc); - l += snprint(p+l, READSTR-l, "No Carrier: %lud\n", ctlr->nc); - l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->lo); - l += snprint(p+l, READSTR-l, "Transmit Jabber Timeout: %lud\n", - ctlr->to); - l += snprint(p+l, READSTR-l, "csr6: %luX %uX\n", csr32r(ctlr, 6), - ctlr->csr6); - snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax); - ctlr->ntqmax = 0; - buf = a; - len = readstr(offset, buf, n, p); - if(offset > l) - offset -= l; - else - offset = 0; - buf += len; - n -= len; - - l = snprint(p, READSTR, "srom:"); - for(i = 0; i < (1<sromsz); i++){ - if(i && ((i & 0x0F) == 0)) - l += snprint(p+l, READSTR-l, "\n "); - l += snprint(p+l, READSTR-l, " %2.2uX", ctlr->srom[i]); - } - - snprint(p+l, READSTR-l, "\n"); - len += readstr(offset, buf, n, p); - free(p); - - return len; -} - -static void -txstart(Ether* ether) -{ - Ctlr *ctlr; - Block *bp; - Des *des; - int control; - - ctlr = ether->ctlr; - while(ctlr->ntq < (ctlr->ntdr-1)){ - if(ctlr->setupbp){ - bp = ctlr->setupbp; - ctlr->setupbp = 0; - control = Ic|Set|BLEN(bp); - } - else{ - bp = qget(ether->oq); - if(bp == nil) - break; - control = Ic|Lseg|Fseg|BLEN(bp); - } - - ctlr->tdr[PREV(ctlr->tdrh, ctlr->ntdr)].control &= ~Ic; - des = &ctlr->tdr[ctlr->tdrh]; - des->bp = bp; - des->addr = PCIWADDR(bp->rp); - des->control |= control; - ctlr->ntq++; - coherence(); - des->status = Own; - csr32w(ctlr, 1, 0); - ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr); - } - - if(ctlr->ntq > ctlr->ntqmax) - ctlr->ntqmax = ctlr->ntq; -} - -static void -transmit(Ether* ether) -{ - Ctlr *ctlr; - - ctlr = ether->ctlr; - ilock(&ctlr->tlock); - txstart(ether); - iunlock(&ctlr->tlock); -} - -static void -interrupt(Ureg*, void* arg) -{ - Ctlr *ctlr; - Ether *ether; - int len, status; - Des *des; - Block *bp; - - ether = arg; - ctlr = ether->ctlr; - - while((status = csr32r(ctlr, 5)) & (Nis|Ais)){ - /* - * Acknowledge the interrupts and mask-out - * the ones that are implicitly handled. - */ - csr32w(ctlr, 5, status); - status &= (ctlr->mask & ~(Nis|Ti)); - - if(status & Ais){ - if(status & Tps) - ctlr->tps++; - if(status & Tu) - ctlr->tu++; - if(status & Tjt) - ctlr->tjt++; - if(status & Ru) - ctlr->ru++; - if(status & Rps) - ctlr->rps++; - if(status & Rwt) - ctlr->rwt++; - status &= ~(Ais|Rwt|Rps|Ru|Tjt|Tu|Tps); - } - - /* - * Received packets. - */ - if(status & Ri){ - des = &ctlr->rdr[ctlr->rdrx]; - while(!(des->status & Own)){ - if(des->status & Es){ - if(des->status & Of) - ctlr->of++; - if(des->status & Ce) - ctlr->ce++; - if(des->status & Cs) - ctlr->cs++; - if(des->status & Tl) - ctlr->tl++; - if(des->status & Rf) - ctlr->rf++; - if(des->status & De) - ctlr->de++; - } - else if(bp = iallocb(Rbsz)){ - len = ((des->status & Fl)>>16)-4; - des->bp->wp = des->bp->rp+len; - etheriq(ether, des->bp, 1); - des->bp = bp; - des->addr = PCIWADDR(bp->rp); - } - - des->control &= Er; - des->control |= Rbsz; - coherence(); - des->status = Own; - - ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr); - des = &ctlr->rdr[ctlr->rdrx]; - } - status &= ~Ri; - } - - /* - * Check the transmit side: - * check for Transmit Underflow and Adjust - * the threshold upwards; - * free any transmitted buffers and try to - * top-up the ring. - */ - if(status & Unf){ - ctlr->unf++; - ilock(&ctlr->lock); - csr32w(ctlr, 6, ctlr->csr6 & ~St); - switch(ctlr->csr6 & Tr){ - case Tr128: - len = Tr256; - break; - case Tr256: - len = Tr512; - break; - case Tr512: - len = Tr1024; - break; - default: - case Tr1024: - len = Sf; - break; - } - ctlr->csr6 = (ctlr->csr6 & ~Tr)|len; - csr32w(ctlr, 6, ctlr->csr6); - iunlock(&ctlr->lock); - csr32w(ctlr, 5, Tps); - status &= ~(Unf|Tps); - } - - ilock(&ctlr->tlock); - while(ctlr->ntq){ - des = &ctlr->tdr[ctlr->tdri]; - if(des->status & Own) - break; - - if(des->status & Es){ - if(des->status & Uf) - ctlr->uf++; - if(des->status & Ec) - ctlr->ec++; - if(des->status & Lc) - ctlr->lc++; - if(des->status & Nc) - ctlr->nc++; - if(des->status & Lo) - ctlr->lo++; - if(des->status & To) - ctlr->to++; - ether->oerrs++; - } - - freeb(des->bp); - des->control &= Er; - - ctlr->ntq--; - ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr); - } - txstart(ether); - iunlock(&ctlr->tlock); - - /* - * Anything left not catered for? - */ - if(status) - panic("#l%d: status %8.8uX\n", ether->ctlrno, status); - } -} - -static void -ctlrinit(Ether* ether) -{ - Ctlr *ctlr; - Des *des; - Block *bp; - int i; - uchar bi[Eaddrlen*2]; - - ctlr = ether->ctlr; - - /* - * Allocate and initialise the receive ring; - * allocate and initialise the transmit ring; - * unmask interrupts and start the transmit side; - * create and post a setup packet to initialise - * the physical ethernet address. - */ - ctlr->rdr = xspanalloc(ctlr->nrdr*sizeof(Des), 8*sizeof(ulong), 0); - for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){ - des->bp = iallocb(Rbsz); - if(des->bp == nil) - panic("can't allocate ethernet receive ring\n"); - des->status = Own; - des->control = Rbsz; - des->addr = PCIWADDR(des->bp->rp); - } - ctlr->rdr[ctlr->nrdr-1].control |= Er; - ctlr->rdrx = 0; - csr32w(ctlr, 3, PCIWADDR(ctlr->rdr)); - - ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0); - ctlr->tdr[ctlr->ntdr-1].control |= Er; - ctlr->tdrh = 0; - ctlr->tdri = 0; - csr32w(ctlr, 4, PCIWADDR(ctlr->tdr)); - - /* - * Clear any bits in the Status Register (CSR5) as - * the PNIC has a different reset value from a true 2114x. - */ - ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti; - csr32w(ctlr, 5, ctlr->mask); - csr32w(ctlr, 7, ctlr->mask); - ctlr->csr6 |= St; - csr32w(ctlr, 6, ctlr->csr6); - - for(i = 0; i < Eaddrlen/2; i++){ - bi[i*4] = ether->ea[i*2]; - bi[i*4+1] = ether->ea[i*2+1]; - bi[i*4+2] = ether->ea[i*2+1]; - bi[i*4+3] = ether->ea[i*2]; - } - bp = iallocb(Eaddrlen*2*16); - if(bp == nil) - panic("can't allocate ethernet setup buffer\n"); - memset(bp->rp, 0xFF, sizeof(bi)); - for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi)) - memmove(bp->rp+i, bi, sizeof(bi)); - bp->wp += sizeof(bi)*16; - - ctlr->setupbp = bp; - ether->oq = qopen(256*1024, 1, 0, 0); - transmit(ether); -} - -static void -csr9w(Ctlr* ctlr, int data) -{ - csr32w(ctlr, 9, data); - microdelay(1); -} - -static int -miimdi(Ctlr* ctlr, int n) -{ - int data, i; - - /* - * Read n bits from the MII Management Register. - */ - data = 0; - for(i = n-1; i >= 0; i--){ - if(csr32r(ctlr, 9) & Mdi) - data |= (1<= 0; i--){ - if(bits & (1<id == Pnic){ - i = 1000; - csr32w(ctlr, 20, 0x60020000|(phyad<<23)|(regad<<18)); - do{ - microdelay(1); - data = csr32r(ctlr, 20); - }while((data & 0x80000000) && --i); - - if(i == 0) - return -1; - return data & 0xFFFF; - } - - /* - * Preamble; - * ST+OP+PHYAD+REGAD; - * TA + 16 data bits. - */ - miimdo(ctlr, 0xFFFFFFFF, 32); - miimdo(ctlr, 0x1800|(phyad<<5)|regad, 14); - data = miimdi(ctlr, 18); - - if(data & 0x10000) - return -1; - - return data & 0xFFFF; -} - -static void -miiw(Ctlr* ctlr, int phyad, int regad, int data) -{ - /* - * Preamble; - * ST+OP+PHYAD+REGAD+TA + 16 data bits; - * Z. - */ - miimdo(ctlr, 0xFFFFFFFF, 32); - data &= 0xFFFF; - data |= (0x05<<(5+5+2+16))|(phyad<<(5+2+16))|(regad<<(2+16))|(0x02<<16); - miimdo(ctlr, data, 32); - csr9w(ctlr, Mdc); - csr9w(ctlr, 0); -} - -static int -sromr(Ctlr* ctlr, int r) -{ - int i, op, data, size; - - if(ctlr->id == Pnic){ - i = 1000; - csr32w(ctlr, 19, 0x600|r); - do{ - microdelay(1); - data = csr32r(ctlr, 19); - }while((data & 0x80000000) && --i); - - if(ctlr->sromsz == 0) - ctlr->sromsz = 6; - - return csr32r(ctlr, 9) & 0xFFFF; - } - - /* - * This sequence for reading a 16-bit register 'r' - * in the EEPROM is taken straight from Section - * 7.4 of the 21140 Hardware Reference Manual. - */ -reread: - csr9w(ctlr, Rd|Ss); - csr9w(ctlr, Rd|Ss|Scs); - csr9w(ctlr, Rd|Ss|Sclk|Scs); - csr9w(ctlr, Rd|Ss); - - op = 0x06; - for(i = 3-1; i >= 0; i--){ - data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs; - csr9w(ctlr, data); - csr9w(ctlr, data|Sclk); - csr9w(ctlr, data); - } - - /* - * First time through must work out the EEPROM size. - */ - if((size = ctlr->sromsz) == 0) - size = 8; - - for(size = size-1; size >= 0; size--){ - data = Rd|Ss|(((r>>size) & 0x01)<<2)|Scs; - csr9w(ctlr, data); - csr9w(ctlr, data|Sclk); - csr9w(ctlr, data); - microdelay(1); - if(!(csr32r(ctlr, 9) & Sdo)) - break; - } - - data = 0; - for(i = 16-1; i >= 0; i--){ - csr9w(ctlr, Rd|Ss|Sclk|Scs); - if(csr32r(ctlr, 9) & Sdo) - data |= (1<sromsz == 0){ - ctlr->sromsz = 8-size; - goto reread; - } - - return data & 0xFFFF; -} - -static void -softreset(Ctlr* ctlr) -{ - /* - * Soft-reset the controller and initialise bus mode. - * Delay should be >= 50 PCI cycles (2×S @ 25MHz). - */ - csr32w(ctlr, 0, Swr); - microdelay(10); - csr32w(ctlr, 0, Rml|Cal16); - delay(1); -} - -static int -type5block(Ctlr* ctlr, uchar* block) -{ - int csr15, i, len; - - /* - * Reset or GPR sequence. Reset should be once only, - * before the GPR sequence. - * Note 'block' is not a pointer to the block head but - * a pointer to the data in the block starting at the - * reset length value so type5block can be used for the - * sequences contained in type 1 and type 3 blocks. - * The SROM docs state the 21140 type 5 block is the - * same as that for the 21143, but the two controllers - * use different registers and sequence-element lengths - * so the 21140 code here is a guess for a real type 5 - * sequence. - */ - len = *block++; - if(ctlr->id != Tulip3){ - for(i = 0; i < len; i++){ - csr32w(ctlr, 12, *block); - block++; - } - return len; - } - - for(i = 0; i < len; i++){ - csr15 = *block++<<16; - csr15 |= *block++<<24; - csr32w(ctlr, 15, csr15); - debug("%8.8uX ", csr15); - } - return 2*len; -} - -static int -typephylink(Ctlr* ctlr, uchar*) -{ - int an, bmcr, bmsr, csr6, x; - - /* - * Fail if - * auto-negotiataion enabled but not complete; - * no valid link established. - */ - bmcr = miir(ctlr, ctlr->curphyad, Bmcr); - miir(ctlr, ctlr->curphyad, Bmsr); - bmsr = miir(ctlr, ctlr->curphyad, Bmsr); - debug("bmcr 0x%2.2uX bmsr 0x%2.2uX\n", bmcr, bmsr); - if(((bmcr & 0x1000) && !(bmsr & 0x0020)) || !(bmsr & 0x0004)) - return 0; - - if(bmcr & 0x1000){ - an = miir(ctlr, ctlr->curphyad, Anar); - an &= miir(ctlr, ctlr->curphyad, Anlpar) & 0x3E0; - debug("an 0x%2.uX 0x%2.2uX 0x%2.2uX\n", - miir(ctlr, ctlr->curphyad, Anar), - miir(ctlr, ctlr->curphyad, Anlpar), - an); - - if(an & 0x0100) - x = 0x4000; - else if(an & 0x0080) - x = 0x2000; - else if(an & 0x0040) - x = 0x1000; - else if(an & 0x0020) - x = 0x0800; - else - x = 0; - } - else if((bmcr & 0x2100) == 0x2100) - x = 0x4000; - else if(bmcr & 0x2000){ - /* - * If FD capable, force it if necessary. - */ - if((bmsr & 0x4000) && ctlr->fd){ - miiw(ctlr, ctlr->curphyad, Bmcr, 0x2100); - x = 0x4000; - } - else - x = 0x2000; - } - else if(bmcr & 0x0100) - x = 0x1000; - else - x = 0x0800; - - csr6 = Sc|Mbo|Hbd|Ps|Ca|Sb|TrMODE; - if(ctlr->fdx & x) - csr6 |= Fd; - if(ctlr->ttm & x) - csr6 |= Ttm; - debug("csr6 0x%8.8uX 0x%8.8uX 0x%8.8luX\n", - csr6, ctlr->csr6, csr32r(ctlr, 6)); - if(csr6 != ctlr->csr6){ - ctlr->csr6 = csr6; - csr32w(ctlr, 6, csr6); - } - - return 1; -} - -static int -typephymode(Ctlr* ctlr, uchar* block, int wait) -{ - uchar *p; - int len, mc, nway, phyx, timeo; - - if(DEBUG){ - int i; - - len = (block[0] & ~0x80)+1; - for(i = 0; i < len; i++) - debug("%2.2uX ", block[i]); - debug("\n"); - } - - if(block[1] == 1) - len = 1; - else if(block[1] == 3) - len = 2; - else - return -1; - - /* - * Snarf the media capabilities, nway advertisment, - * FDX and TTM bitmaps. - */ - p = &block[5+len*block[3]+len*block[4+len*block[3]]]; - mc = *p++; - mc |= *p++<<8; - nway = *p++; - nway |= *p++<<8; - ctlr->fdx = *p++; - ctlr->fdx |= *p++<<8; - ctlr->ttm = *p++; - ctlr->ttm |= *p<<8; - debug("mc %4.4uX nway %4.4uX fdx %4.4uX ttm %4.4uX\n", - mc, nway, ctlr->fdx, ctlr->ttm); - USED(mc); - - phyx = block[2]; - ctlr->curphyad = ctlr->phy[phyx]; - - ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|Sb|TrMODE; - //csr32w(ctlr, 6, ctlr->csr6); - if(typephylink(ctlr, block)) - return 0; - - if(!(ctlr->phyreset & (1<type5block) - type5block(ctlr, &ctlr->type5block[2]); - else - type5block(ctlr, &block[4+len*block[3]]); - debug("\n"); - ctlr->phyreset |= (1<csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|Sb|TrMODE; - //csr32w(ctlr, 6, ctlr->csr6); - if(typephylink(ctlr, block)) - return 0; - - /* - * Turn off auto-negotiation, set the auto-negotiation - * advertisment register then start the auto-negotiation - * process again. - */ - miiw(ctlr, ctlr->curphyad, Bmcr, 0); - miiw(ctlr, ctlr->curphyad, Anar, nway|1); - miiw(ctlr, ctlr->curphyad, Bmcr, 0x1000); - - if(!wait) - return 0; - - for(timeo = 0; timeo < 30; timeo++){ - if(typephylink(ctlr, block)) - return 0; - delay(100); - } - - return -1; -} - -static int -typesymmode(Ctlr *ctlr, uchar *block, int wait) -{ - uint gpmode, gpdata, command; - - USED(wait); - gpmode = block[3] | ((uint) block[4] << 8); - gpdata = block[5] | ((uint) block[6] << 8); - command = (block[7] | ((uint) block[8] << 8)) & 0x71; - if (command & 0x8000) { - print("ether2114x.c: FIXME: handle type 4 mode blocks where cmd.active_invalid != 0\n"); - return -1; - } - csr32w(ctlr, 15, gpmode); - csr32w(ctlr, 15, gpdata); - ctlr->csr6 = (command & 0x71) << 18; - csr32w(ctlr, 6, ctlr->csr6); - return 0; -} - -static int -type0link(Ctlr* ctlr, uchar* block) -{ - int m, polarity, sense; - - m = (block[3]<<8)|block[2]; - sense = 1<<((m & 0x000E)>>1); - if(m & 0x0080) - polarity = sense; - else - polarity = 0; - - return (csr32r(ctlr, 12) & sense)^polarity; -} - -static int -type0mode(Ctlr* ctlr, uchar* block, int wait) -{ - int csr6, m, timeo; - - csr6 = Sc|Mbo|Hbd|Ca|Sb|TrMODE; -debug("type0: medium 0x%uX, fd %d: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n", - ctlr->medium, ctlr->fd, block[0], block[1], block[2], block[3]); - switch(block[0]){ - default: - break; - - case 0x04: /* 10BASE-TFD */ - case 0x05: /* 100BASE-TXFD */ - case 0x08: /* 100BASE-FXFD */ - /* - * Don't attempt full-duplex - * unless explicitly requested. - */ - if(!ctlr->fd) - return -1; - csr6 |= Fd; - break; - } - - m = (block[3]<<8)|block[2]; - if(m & 0x0001) - csr6 |= Ps; - if(m & 0x0010) - csr6 |= Ttm; - if(m & 0x0020) - csr6 |= Pcs; - if(m & 0x0040) - csr6 |= Scr; - - csr32w(ctlr, 12, block[1]); - microdelay(10); - csr32w(ctlr, 6, csr6); - ctlr->csr6 = csr6; - - if(!wait) - return 0; - - for(timeo = 0; timeo < 30; timeo++){ - if(type0link(ctlr, block)) - return 0; - delay(100); - } - - return -1; -} - -static int -mediaxx(Ether* ether, int wait) -{ - Ctlr* ctlr; - uchar *block; - - ctlr = ether->ctlr; - block = ctlr->infoblock[ctlr->curk]; - if(block[0] & 0x80){ - switch(block[1]){ - default: - return -1; - case 0: - if(ctlr->medium >= 0 && block[2] != ctlr->medium) - return 0; -/* need this test? */ if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[2]) - return 0; - if(type0mode(ctlr, block+2, wait)) - return 0; - break; - case 1: - if(typephymode(ctlr, block, wait)) - return 0; - break; - case 3: - if(typephymode(ctlr, block, wait)) - return 0; - break; - case 4: - if(typesymmode(ctlr, block, wait)) - return 0; - break; - } - } - else{ - if(ctlr->medium >= 0 && block[0] != ctlr->medium) - return 0; -/* need this test? */if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[0]) - return 0; - if(type0mode(ctlr, block, wait)) - return 0; - } - - if(ctlr->csr6){ - if(!(ctlr->csr6 & Ps) || (ctlr->csr6 & Ttm)) - return 10; - return 100; - } - - return 0; -} - -static int -media(Ether* ether, int wait) -{ - Ctlr* ctlr; - int k, mbps; - - ctlr = ether->ctlr; - for(k = 0; k < ctlr->k; k++){ - mbps = mediaxx(ether, wait); - if(mbps > 0) - return mbps; - if(ctlr->curk == 0) - ctlr->curk = ctlr->k-1; - else - ctlr->curk--; - } - - return 0; -} - -static char* mediatable[9] = { - "10BASE-T", /* TP */ - "10BASE-2", /* BNC */ - "10BASE-5", /* AUI */ - "100BASE-TX", - "10BASE-TFD", - "100BASE-TXFD", - "100BASE-T4", - "100BASE-FX", - "100BASE-FXFD", -}; - -static uchar en1207[] = { /* Accton EN1207-COMBO */ - 0x00, 0x00, 0xE8, /* [0] vendor ethernet code */ - 0x00, /* [3] spare */ - - 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */ - 0x1F, /* [6] general purpose control */ - 2, /* [7] block count */ - - 0x00, /* [8] media code (10BASE-TX) */ - 0x0B, /* [9] general purpose port data */ - 0x9E, 0x00, /* [10] command (LSB+MSB = 0x009E) */ - - 0x03, /* [8] media code (100BASE-TX) */ - 0x1B, /* [9] general purpose port data */ - 0x6D, 0x00, /* [10] command (LSB+MSB = 0x006D) */ - - /* There is 10BASE-2 as well, but... */ -}; - -static uchar ana6910fx[] = { /* Adaptec (Cogent) ANA-6910FX */ - 0x00, 0x00, 0x92, /* [0] vendor ethernet code */ - 0x00, /* [3] spare */ - - 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */ - 0x3F, /* [6] general purpose control */ - 1, /* [7] block count */ - - 0x07, /* [8] media code (100BASE-FX) */ - 0x03, /* [9] general purpose port data */ - 0x2D, 0x00 /* [10] command (LSB+MSB = 0x000D) */ -}; - -static uchar smc9332[] = { /* SMC 9332 */ - 0x00, 0x00, 0xC0, /* [0] vendor ethernet code */ - 0x00, /* [3] spare */ - - 0x00, 0x08, /* [4] connection (LSB+MSB = 0x0800) */ - 0x1F, /* [6] general purpose control */ - 2, /* [7] block count */ - - 0x00, /* [8] media code (10BASE-TX) */ - 0x00, /* [9] general purpose port data */ - 0x9E, 0x00, /* [10] command (LSB+MSB = 0x009E) */ - - 0x03, /* [8] media code (100BASE-TX) */ - 0x09, /* [9] general purpose port data */ - 0x6D, 0x00, /* [10] command (LSB+MSB = 0x006D) */ -}; - -static uchar* leaf21140[] = { - en1207, /* Accton EN1207-COMBO */ - ana6910fx, /* Adaptec (Cogent) ANA-6910FX */ - smc9332, /* SMC 9332 */ - nil, -}; - -/* - * Copied to ctlr->srom at offset 20. - */ -static uchar leafpnic[] = { - 0x00, 0x00, 0x00, 0x00, /* MAC address */ - 0x00, 0x00, - 0x00, /* controller 0 device number */ - 0x1E, 0x00, /* controller 0 info leaf offset */ - 0x00, /* reserved */ - 0x00, 0x08, /* selected connection type */ - 0x00, /* general purpose control */ - 0x01, /* block count */ - - 0x8C, /* format indicator and count */ - 0x01, /* block type */ - 0x00, /* PHY number */ - 0x00, /* GPR sequence length */ - 0x00, /* reset sequence length */ - 0x00, 0x78, /* media capabilities */ - 0xE0, 0x01, /* Nway advertisment */ - 0x00, 0x50, /* FDX bitmap */ - 0x00, 0x18, /* TTM bitmap */ -}; - -static int -srom(Ctlr* ctlr) -{ - int i, k, oui, phy, x; - uchar *p; - - /* - * This is a partial decoding of the SROM format described in - * 'Digital Semiconductor 21X4 Serial ROM Format, Version 4.05, - * 2-Mar-98'. Only the 2114[03] are handled, support for other - * controllers can be added as needed. - * Do a dummy read first to get the size and allocate ctlr->srom. - */ - sromr(ctlr, 0); - if(ctlr->srom == nil) - ctlr->srom = malloc((1<sromsz)*sizeof(ushort)); - for(i = 0; i < (1<sromsz); i++){ - x = sromr(ctlr, i); - ctlr->srom[2*i] = x; - ctlr->srom[2*i+1] = x>>8; - } - - /* - * There are 2 SROM layouts: - * e.g. Digital EtherWORKS station address at offset 20; - * this complies with the 21140A SROM - * application note from Digital; - * e.g. SMC9332 station address at offset 0 followed by - * 2 additional bytes, repeated at offset - * 6; the 8 bytes are also repeated in - * reverse order at offset 8. - * To check which it is, read the SROM and check for the repeating - * patterns of the non-compliant cards; if that fails use the one at - * offset 20. - */ - ctlr->sromea = ctlr->srom; - for(i = 0; i < 8; i++){ - x = ctlr->srom[i]; - if(x != ctlr->srom[15-i] || x != ctlr->srom[16+i]){ - ctlr->sromea = &ctlr->srom[20]; - break; - } - } - - /* - * Fake up the SROM for the PNIC. - * It looks like a 21140 with a PHY. - * The MAC address is byte-swapped in the orginal SROM data. - */ - if(ctlr->id == Pnic){ - memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic)); - for(i = 0; i < Eaddrlen; i += 2){ - ctlr->srom[20+i] = ctlr->srom[i+1]; - ctlr->srom[20+i+1] = ctlr->srom[i]; - } - } - - /* - * Next, try to find the info leaf in the SROM for media detection. - * If it's a non-conforming card try to match the vendor ethernet code - * and point p at a fake info leaf with compact 21140 entries. - */ - if(ctlr->sromea == ctlr->srom){ - p = nil; - for(i = 0; leaf21140[i] != nil; i++){ - if(memcmp(leaf21140[i], ctlr->sromea, 3) == 0){ - p = &leaf21140[i][4]; - break; - } - } - if(p == nil) - return -1; - } - else - p = &ctlr->srom[(ctlr->srom[28]<<8)|ctlr->srom[27]]; - - /* - * Set up the info needed for later media detection. - * For the 21140, set the general-purpose mask in CSR12. - * The info block entries are stored in order of increasing - * precedence, so detection will work backwards through the - * stored indexes into ctlr->srom. - * If an entry is found which matches the selected connection - * type, save the index. Otherwise, start at the last entry. - * If any MII entries are found (type 1 and 3 blocks), scan - * for PHYs. - */ - ctlr->leaf = p; - ctlr->sct = *p++; - ctlr->sct |= *p++<<8; - if(ctlr->id != Tulip3){ - csr32w(ctlr, 12, Gpc|*p++); - delay(200); - } - ctlr->k = *p++; - if(ctlr->k >= nelem(ctlr->infoblock)) - ctlr->k = nelem(ctlr->infoblock)-1; - ctlr->sctk = ctlr->k-1; - phy = 0; - for(k = 0; k < ctlr->k; k++){ - ctlr->infoblock[k] = p; - /* - * The RAMIX PMC665 has a badly-coded SROM, - * hence the test for 21143 and type 3. - */ - if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){ - *p |= 0x80; - if(*(p+1) == 1 || *(p+1) == 3) - phy = 1; - if(*(p+1) == 5) - ctlr->type5block = p; - p += (*p & ~0x80)+1; - } - else{ - debug("type0: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n", - p[0], p[1], p[2], p[3]); - if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF)) - ctlr->sctk = k; - p += 4; - } - } - ctlr->curk = ctlr->sctk; - debug("sct 0x%uX medium 0x%uX k %d curk %d phy %d\n", - ctlr->sct, ctlr->medium, ctlr->k, ctlr->curk, phy); - - if(phy){ - x = 0; - for(k = 0; k < nelem(ctlr->phy); k++){ - if((oui = miir(ctlr, k, 2)) == -1 || oui == 0) - continue; - if(DEBUG){ - oui = (oui & 0x3FF)<<6; - oui |= miir(ctlr, k, 3)>>10; - miir(ctlr, k, 1); - debug("phy%d: index %d oui %uX reg1 %uX\n", - x, k, oui, miir(ctlr, k, 1)); - USED(oui); - } - ctlr->phy[x] = k; - } - } - - ctlr->fd = 0; - ctlr->medium = -1; - - return 0; -} - -static void -dec2114xpci(void) -{ - Ctlr *ctlr; - Pcidev *p; - int x; - - p = nil; - while(p = pcimatch(p, 0, 0)){ - if(p->ccrb != 0x02 || p->ccru != 0) - continue; - switch((p->did<<16)|p->vid){ - default: - continue; - - case Tulip3: /* 21143 */ - /* - * Exit sleep mode. - */ - x = pcicfgr32(p, 0x40); - x &= ~0xc0000000; - pcicfgw32(p, 0x40, x); - /*FALLTHROUGH*/ - - case Pnic: /* PNIC */ - case Pnic2: /* PNIC-II */ - case Tulip0: /* 21140 */ - break; - } - - /* - * bar[0] is the I/O port register address and - * bar[1] is the memory-mapped register address. - */ - ctlr = malloc(sizeof(Ctlr)); - ctlr->port = p->mem[0].bar & ~0x01; - ctlr->pcidev = p; - ctlr->id = (p->did<<16)|p->vid; - - if(ioalloc(ctlr->port, p->mem[0].size, 0, "dec2114x") < 0){ - print("dec2114x: port 0x%uX in use\n", ctlr->port); - free(ctlr); - continue; - } - - /* - * Some cards (e.g. ANA-6910FX) seem to need the Ps bit - * set or they don't always work right after a hardware - * reset. - */ - csr32w(ctlr, 6, Mbo|Ps); - softreset(ctlr); - - if(srom(ctlr)){ - iofree(ctlr->port); - free(ctlr); - continue; - } - - switch(ctlr->id){ - default: - break; - - case Pnic: /* PNIC */ - /* - * Turn off the jabber timer. - */ - csr32w(ctlr, 15, 0x00000001); - break; - } - - if(ctlrhead != nil) - ctlrtail->next = ctlr; - else - ctlrhead = ctlr; - ctlrtail = ctlr; - } -} - -static int -reset(Ether* ether) -{ - Ctlr *ctlr; - int i, x; - uchar ea[Eaddrlen]; - static int scandone; - - if(scandone == 0){ - dec2114xpci(); - scandone = 1; - } - - /* - * Any adapter matches if no ether->port is supplied, - * otherwise the ports must match. - */ - for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){ - if(ctlr->active) - continue; - if(ether->port == 0 || ether->port == ctlr->port){ - ctlr->active = 1; - break; - } - } - if(ctlr == nil) - return -1; - - ether->ctlr = ctlr; - ether->port = ctlr->port; - ether->irq = ctlr->pcidev->intl; - ether->tbdf = ctlr->pcidev->tbdf; - - /* - * Check if the adapter's station address is to be overridden. - * If not, read it from the EEPROM and set in ether->ea prior to - * loading the station address in the hardware. - */ - memset(ea, 0, Eaddrlen); - if(memcmp(ea, ether->ea, Eaddrlen) == 0) - memmove(ether->ea, ctlr->sromea, Eaddrlen); - - /* - * Look for a medium override in case there's no autonegotiation - * (no MII) or the autonegotiation fails. - */ - for(i = 0; i < ether->nopt; i++){ - if(cistrcmp(ether->opt[i], "FD") == 0){ - ctlr->fd = 1; - continue; - } - for(x = 0; x < nelem(mediatable); x++){ - debug("compare <%s> <%s>\n", mediatable[x], - ether->opt[i]); - if(cistrcmp(mediatable[x], ether->opt[i])) - continue; - ctlr->medium = x; - - switch(ctlr->medium){ - default: - ctlr->fd = 0; - break; - - case 0x04: /* 10BASE-TFD */ - case 0x05: /* 100BASE-TXFD */ - case 0x08: /* 100BASE-FXFD */ - ctlr->fd = 1; - break; - } - break; - } - } - - ether->mbps = media(ether, 1); - - /* - * Initialise descriptor rings, ethernet address. - */ - ctlr->nrdr = Nrde; - ctlr->ntdr = Ntde; - pcisetbme(ctlr->pcidev); - ctlrinit(ether); - - /* - * Linkage to the generic ethernet driver. - */ - ether->attach = attach; - ether->transmit = transmit; - ether->interrupt = interrupt; - ether->ifstat = ifstat; - - ether->arg = ether; - ether->promiscuous = promiscuous; - - return 0; -} - -void -ether2114xlink(void) -{ - addethercard("21140", reset); - addethercard("2114x", reset); -} +#include "../pc/ether2114x.c" diff --git a/alphapc/etherif.h b/alphapc/etherif.h index 33a5ad045f1779142b925decdd3535a093134002..5af59e14629aa7a477e37d4e7114b5c506400fc5 100644 --- a/alphapc/etherif.h +++ b/alphapc/etherif.h @@ -13,7 +13,6 @@ struct Ether { int minmtu; int maxmtu; uchar ea[Eaddrlen]; - int encry; void (*attach)(Ether*); /* filled in by reset routine */ void (*transmit)(Ether*); diff --git a/alphapc/mouse.c b/alphapc/mouse.c index 701855dee72625c64cacf676fd3d16f408f938d1..b14a057dfb63e52dd21490ffe0703e47dc605984 100644 --- a/alphapc/mouse.c +++ b/alphapc/mouse.c @@ -1,311 +1 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" -#include "io.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -/* - * mouse types - */ -enum -{ - Mouseother= 0, - Mouseserial= 1, - MousePS2= 2, -}; -static int mousetype; -static int intellimouse; -static int packetsize; -static int resolution; -static int accelerated; - -enum -{ - CMaccelerated, - CMintellimouse, - CMlinear, - CMps2, - CMps2intellimouse, - CMres, - CMreset, - CMserial, -}; - -static Cmdtab mousectlmsg[] = -{ - CMaccelerated, "accelerated", 0, - CMintellimouse, "intellimouse", 1, - CMlinear, "linear", 1, - CMps2, "ps2", 1, - CMps2intellimouse, "ps2intellimouse", 1, - CMres, "res", 0, - CMreset, "reset", 1, - CMserial, "serial", 0, -}; - -/* - * setup a serial mouse - */ -static void -serialmouse(int port, char *type, int setspeed) -{ -#ifdef notdef - if(mousetype == Mouseserial) - error(Emouseset); - - if(port >= 3 || port < 0) - error(Ebadarg); - - /* set up /dev/eia? as the mouse */ - if(setspeed) - setspeed = 1200; - if(type && *type == 'M') - uartspecial(port, setspeed, 0, 0, m3mouseputc); - else - uartspecial(port, setspeed, 0, 0, mouseputc); - mousetype = Mouseserial; - packetsize = 3; -#else - error("serial mouse not supported yet"); - USED(port, type, setspeed); -#endif /* notdef */ -} - -/* - * ps/2 mouse message is three bytes - * - * byte 0 - 0 0 SDY SDX 1 M R L - * byte 1 - DX - * byte 2 - DY - * - * shift & right button is the same as middle button - * - * Intellimouse and AccuPoint with extra buttons deliver - * byte 3 - 00 or 01 or FF according to extra button state. - * extra buttons are mapped in this code to buttons 4 and 5. - * AccuPoint generates repeated events for these buttons; -* it and Intellimouse generate 'down' events only, so - * user-level code is required to generate button 'up' events - * if they are needed by the application. - * Also on laptops with AccuPoint AND external mouse, the - * controller may deliver 3 or 4 bytes according to the type - * of the external mouse; code must adapt. - * - * On the NEC Versa series (and perhaps others?) we seem to - * lose a byte from the packet every once in a while, which - * means we lose where we are in the instruction stream. - * To resynchronize, if we get a byte more than two seconds - * after the previous byte, we assume it's the first in a packet. - */ -static void -ps2mouseputc(int c, int shift) -{ - static short msg[4]; - static int nb; - static uchar b[] = {0, 1, 4, 5, 2, 3, 6, 7, 0, 1, 2, 3, 2, 3, 6, 7 }; - static ulong lasttick; - ulong m; - int buttons, dx, dy; - - /* - * Resynchronize in stream with timing; see comment above. - */ - m = MACHP(0)->ticks; - if(TK2SEC(m - lasttick) > 2) - nb = 0; - lasttick = m; - - /* - * check byte 0 for consistency - */ - if(nb==0 && (c&0xc8)!=0x08) - if(intellimouse && (c==0x00 || c==0x01 || c==0xFF)){ - /* last byte of 4-byte packet */ - packetsize = 4; - return; - } - - msg[nb] = c; - if(++nb == packetsize){ - nb = 0; - if(msg[0] & 0x10) - msg[1] |= 0xFF00; - if(msg[0] & 0x20) - msg[2] |= 0xFF00; - - buttons = b[(msg[0]&7) | (shift ? 8 : 0)]; - if(intellimouse && packetsize==4){ - if((msg[3]&0xc8) == 0x08){ - /* first byte of 3-byte packet */ - packetsize = 3; - msg[0] = msg[3]; - nb = 1; - /* fall through to emit previous packet */ - }else{ - /* the AccuPoint on the Toshiba 34[48]0CT encodes extra buttons as 4 and 5 */ - /* they repeat and don't release, however, so user-level timing code is required */ - if(msg[3] == 0xFF) - buttons |= 1<<3; - if(msg[3] == 0x01) - buttons |= 1<<4; - } - } - dx = msg[1]; - dy = -msg[2]; - mousetrack(dx, dy, buttons, TK2MS(MACHP(0)->ticks)); - } - return; -} - -/* - * set up a ps2 mouse - */ -static void -ps2mouse(void) -{ - if(mousetype == MousePS2) - return; - - i8042auxenable(ps2mouseputc); - /* make mouse streaming, enabled */ - i8042auxcmd(0xEA); - i8042auxcmd(0xF4); - - mousetype = MousePS2; - packetsize = 3; -} - -static void -setaccelerated(int x) -{ - accelerated = x; - switch(mousetype){ - case MousePS2: - i8042auxcmd(0xE7); - break; - default: - mouseaccelerate(x); - break; - } -} - -static void -setlinear(void) -{ - accelerated = 0; - switch(mousetype){ - case MousePS2: - i8042auxcmd(0xE6); - break; - default: - mouseaccelerate(0); - break; - } -} - -static void -setres(int n) -{ - resolution = n; - switch(mousetype){ - case MousePS2: - i8042auxcmd(0xE8); - i8042auxcmd(n); - break; - } -} - -static void -setintellimouse(void) -{ - intellimouse = 1; - packetsize = 4; - switch(mousetype){ - case MousePS2: - i8042auxcmd(0xF3); /* set sample */ - i8042auxcmd(0xC8); - i8042auxcmd(0xF3); /* set sample */ - i8042auxcmd(0x64); - i8042auxcmd(0xF3); /* set sample */ - i8042auxcmd(0x50); - break; - } -} - -static void -resetmouse(void) -{ - packetsize = 3; - switch(mousetype){ - case MousePS2: - i8042auxcmd(0xF6); - i8042auxcmd(0xEA); /* streaming */ - i8042auxcmd(0xE8); /* set resolution */ - i8042auxcmd(3); - i8042auxcmd(0xF4); /* enabled */ - break; - } -} - -void -mousectl(Cmdbuf *cb) -{ - Cmdtab *ct; - - ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg)); - switch(ct->index){ - case CMaccelerated: - setaccelerated(cb->nf == 1 ? 1 : atoi(cb->f[1])); - break; - case CMintellimouse: - setintellimouse(); - break; - case CMlinear: - setlinear(); - break; - case CMps2: - ps2mouse(); - break; - case CMps2intellimouse: - ps2mouse(); - setintellimouse(); - break; - case CMres: - if(cb->nf >= 2) - setres(atoi(cb->f[1])); - else - setres(1); - break; - case CMreset: - resetmouse(); - if(accelerated) - setaccelerated(accelerated); - if(resolution) - setres(resolution); - if(intellimouse) - setintellimouse(); - break; - case CMserial: - switch(cb->nf){ - case 1: - serialmouse(atoi(cb->f[0]+6), 0, 1); - break; - case 2: - serialmouse(atoi(cb->f[1]), 0, 0); - break; - case 3: - default: - serialmouse(atoi(cb->f[1]), cb->f[2], 0); - break; - } - break; - } -} +#include "../pc/mouse.c" diff --git a/alphapc/screen.h b/alphapc/screen.h index d30fb831310e00b970faa61ceec53dde6da3b9b1..38148570b3f58baf88f437539572e5a0e1bd5f71 100644 --- a/alphapc/screen.h +++ b/alphapc/screen.h @@ -125,9 +125,10 @@ enum { extern void mousectl(Cmdbuf*); /* 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 int hwaccel; /* use hw acceleration; default on */ +extern int hwblank; /* use hw blanking; default on */ +extern void addvgaseg(char*, ulong, ulong); +extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*); extern void flushmemscreen(Rectangle); extern int cursoron(int); extern void cursoroff(int); @@ -139,7 +140,7 @@ extern void blankscreen(int); /* devdraw.c */ extern void deletescreenimage(void); -extern int drawhasclients(void); +extern int drawhasclients(void); extern ulong blanktime; /* vga.c */ extern void vgascreenwin(VGAscr*); diff --git a/alphapc/uarti8250.c b/alphapc/uarti8250.c index b2ca39d58a0a3a1f00f37dde8c9d5863308c41a3..cf5937b3da9f2a3316c5a7bc05858c3491acda52 100644 --- a/alphapc/uarti8250.c +++ b/alphapc/uarti8250.c @@ -1,648 +1 @@ -#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; -} +#include "../pc/uarti8250.c" diff --git a/alphapc/vga.c b/alphapc/vga.c index 24a4fee38d4e36e078f47523631b3e69c144280c..00e7131534a5bcdceca0ef2ca4c5c72f071869f2 100644 --- a/alphapc/vga.c +++ b/alphapc/vga.c @@ -1,225 +1 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -static Memimage* back; -static Memimage *conscol; - -static Point curpos; -static Rectangle window; -static int *xp; -static int xbuf[256]; -static Lock vgascreenlock; -int drawdebug; - -void -vgaimageinit(ulong chan) -{ - if(back == nil){ - back = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */ - if(back == nil) - panic("back alloc"); /* RSC BUG */ - back->flags |= Frepl; - back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); - memfillcolor(back, DBlack); - } - - if(conscol == nil){ - conscol = allocmemimage(Rect(0,0,1,1), chan); /* RSC BUG */ - if(conscol == nil) - panic("conscol alloc"); /* RSC BUG */ - conscol->flags |= Frepl; - conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF); - memfillcolor(conscol, DWhite); - } -} - -static void -vgascroll(VGAscr* scr) -{ - int h, o; - Point p; - Rectangle r; - - h = scr->memdefont->height; - o = 8*h; - r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); - p = Pt(window.min.x, window.min.y+o); - memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p); - r = Rpt(Pt(window.min.x, window.max.y-o), window.max); - memimagedraw(scr->gscreen, r, back, ZP, nil, ZP); - - curpos.y -= o; -} - -static void -vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr) -{ - Point p; - int h, w, pos; - Rectangle r; - -// drawdebug = 1; - if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) - xp = xbuf; - - h = scr->memdefont->height; - switch(buf[0]){ - - case '\n': - if(curpos.y+h >= window.max.y){ - vgascroll(scr); - *flushr = window; - } - curpos.y += h; - vgascreenputc(scr, "\r", flushr); - break; - - case '\r': - xp = xbuf; - curpos.x = window.min.x; - break; - - case '\t': - p = memsubfontwidth(scr->memdefont, " "); - w = p.x; - if(curpos.x >= window.max.x-4*w) - vgascreenputc(scr, "\n", flushr); - - pos = (curpos.x-window.min.x)/w; - pos = 4-(pos%4); - *xp++ = curpos.x; - r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y+h); - memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP); - combinerect(flushr, r); - curpos.x += pos*w; - break; - - case '\b': - if(xp <= xbuf) - break; - xp--; - r = Rect(*xp, curpos.y, curpos.x, curpos.y+h); - memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP); - combinerect(flushr, r); - curpos.x = *xp; - break; - - case '\0': - break; - - default: - p = memsubfontwidth(scr->memdefont, buf); - w = p.x; - - if(curpos.x >= window.max.x-w) - vgascreenputc(scr, "\n", flushr); - - *xp++ = curpos.x; - r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h); - memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min); - memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf); - combinerect(flushr, r); - curpos.x += w; - } -// drawdebug = 0; -} - -static void -vgascreenputs(char* s, int n) -{ - int i; - Rune r; - char buf[4]; - VGAscr *scr; - Rectangle flushr; - - scr = &vgascreen[0]; - - if(!islo()){ - /* - * Don't deadlock trying to - * print in an interrupt. - */ - if(!canlock(&vgascreenlock)) - return; - } - else - lock(&vgascreenlock); - - flushr = Rect(10000, 10000, -10000, -10000); - - while(n > 0){ - i = chartorune(&r, s); - if(i == 0){ - s++; - --n; - continue; - } - memmove(buf, s, i); - buf[i] = 0; - n -= i; - s += i; - vgascreenputc(scr, buf, &flushr); - } - flushmemscreen(flushr); - - unlock(&vgascreenlock); -} - -void -vgascreenwin(VGAscr* scr) -{ - int h, w; - - h = scr->memdefont->height; - w = scr->memdefont->info[' '].width; - - window.min = Pt(48, 48); - window.max = addpt(window.min, Pt(10+w*80, 10+h*50)); - if(window.max.y >= scr->gscreen->r.max.y) - window.max.y = scr->gscreen->r.max.y-1; - if(window.max.x >= scr->gscreen->r.max.x) - window.max.x = scr->gscreen->r.max.x-1; - window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; - curpos = window.min; - - screenputs = vgascreenputs; -} - -/* - * Supposedly this is the way to turn DPMS - * monitors off using just the VGA registers. - * Unfortunately, it seems to mess up the video mode - * on the cards I've tried. - */ -void -vgablank(VGAscr*, int blank) -{ - uchar seq1, crtc17; - - if(blank) { - seq1 = 0x00; - crtc17 = 0x80; - } else { - seq1 = 0x20; - crtc17 = 0x00; - } - - outs(Seqx, 0x0100); /* synchronous reset */ - seq1 |= vgaxi(Seqx, 1) & ~0x20; - vgaxo(Seqx, 1, seq1); - crtc17 |= vgaxi(Crtx, 0x17) & ~0x80; - delay(10); - vgaxo(Crtx, 0x17, crtc17); - outs(Crtx, 0x0300); /* end synchronous reset */ -} +#include "../pc/vga.c" diff --git a/alphapc/vgargb524.c b/alphapc/vgargb524.c index 384901fc4228f9c4f642571bc165aa931fe67f4b..de1f389c6f9fb89f9268755c08b9dbf614e33130 100644 --- a/alphapc/vgargb524.c +++ b/alphapc/vgargb524.c @@ -1,237 +1 @@ -#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" - -/* - * IBM RGB524. - * 170/220MHz High Performance Palette DAC. - * - * Assumes hooked up to an S3 Vision96[48]. - */ -enum { - IndexLo = 0x00, - IndexHi = 0x01, - Data = 0x02, - IndexCtl = 0x03, -}; - -enum { /* index registers */ - CursorCtl = 0x30, - CursorXLo = 0x31, - CursorXHi = 0x32, - CursorYLo = 0x33, - CursorYHi = 0x34, - CursorHotX = 0x35, - CursorHotY = 0x36, - - CursorR1 = 0x40, - CursorG1 = 0x41, - CursorB1 = 0x42, - CursorR2 = 0x43, - CursorG2 = 0x44, - CursorB2 = 0x45, - CursorR3 = 0x46, - CursorG3 = 0x47, - CursorB3 = 0x48, - - CursorArray = 0x100, -}; - -/* - * Lower 2-bits of indirect DAC register - * addressing. - */ -static ushort dacxreg[4] = { - PaddrW, Pdata, Pixmask, PaddrR -}; - -static uchar -rgb524setrs2(void) -{ - uchar rs2; - - rs2 = vgaxi(Crtx, 0x55); - vgaxo(Crtx, 0x55, (rs2 & 0xFC)|0x01); - - return rs2; -} - -static void -rgb524xo(int index, uchar data) -{ - vgao(dacxreg[IndexLo], index & 0xFF); - vgao(dacxreg[IndexHi], (index>>8) & 0xFF); - vgao(dacxreg[Data], data); -} - -static void -rgb524disable(VGAscr*) -{ - uchar rs2; - - rs2 = rgb524setrs2(); - rgb524xo(CursorCtl, 0x00); - vgaxo(Crtx, 0x55, rs2); -} - -static void -rgb524enable(VGAscr*) -{ - uchar rs2; - - rs2 = rgb524setrs2(); - - /* - * Make sure cursor is off by initialising the cursor - * control to defaults. - */ - rgb524xo(CursorCtl, 0x00); - - /* - * Cursor colour 1 (white), - * cursor colour 2 (black). - */ - rgb524xo(CursorR1, Pwhite); rgb524xo(CursorG1, Pwhite); rgb524xo(CursorB1, Pwhite); - rgb524xo(CursorR2, Pblack); rgb524xo(CursorG2, Pblack); rgb524xo(CursorB2, Pblack); - - /* - * Enable the cursor, 32x32, mode 2. - */ - rgb524xo(CursorCtl, 0x23); - - vgaxo(Crtx, 0x55, rs2); -} - -static void -rgb524load(VGAscr*, Cursor* curs) -{ - uchar p, p0, p1, rs2; - int x, y; - - rs2 = rgb524setrs2(); - - /* - * Make sure cursor is off by initialising the cursor - * control to defaults. - */ - rgb524xo(CursorCtl, 0x00); - - /* - * Set auto-increment mode for index-register addressing - * and initialise the cursor array index. - */ - vgao(dacxreg[IndexCtl], 0x01); - vgao(dacxreg[IndexLo], CursorArray & 0xFF); - vgao(dacxreg[IndexHi], (CursorArray>>8) & 0xFF); - - /* - * Initialise the 32x32 cursor RAM array. There are 2 planes, - * p0 and p1. Data is written 4 pixels per byte, with p1 the - * MS bit of each pixel. - * The cursor is set in X-Windows mode which gives the following - * truth table: - * p1 p0 colour - * 0 0 underlying pixel colour - * 0 1 underlying pixel colour - * 1 0 cursor colour 1 - * 1 1 cursor colour 2 - * Put the cursor into the top-left of the 32x32 array. - */ - for(y = 0; y < 32; y++){ - for(x = 0; x < 32/8; x++){ - if(x < 16/8 && y < 16){ - p0 = curs->clr[x+y*2]; - p1 = curs->set[x+y*2]; - - p = 0x00; - if(p1 & 0x80) - p |= 0xC0; - else if(p0 & 0x80) - p |= 0x80; - if(p1 & 0x40) - p |= 0x30; - else if(p0 & 0x40) - p |= 0x20; - if(p1 & 0x20) - p |= 0x0C; - else if(p0 & 0x20) - p |= 0x08; - if(p1 & 0x10) - p |= 0x03; - else if(p0 & 0x10) - p |= 0x02; - vgao(dacxreg[Data], p); - - p = 0x00; - if(p1 & 0x08) - p |= 0xC0; - else if(p0 & 0x08) - p |= 0x80; - if(p1 & 0x04) - p |= 0x30; - else if(p0 & 0x04) - p |= 0x20; - if(p1 & 0x02) - p |= 0x0C; - else if(p0 & 0x02) - p |= 0x08; - if(p1 & 0x01) - p |= 0x03; - else if(p0 & 0x01) - p |= 0x02; - vgao(dacxreg[Data], p); - } - else{ - vgao(dacxreg[Data], 0x00); - vgao(dacxreg[Data], 0x00); - } - } - } - - /* - * Initialise the cursor hotpoint, - * enable the cursor and restore state. - */ - rgb524xo(CursorHotX, -curs->offset.x); - rgb524xo(CursorHotY, -curs->offset.y); - - rgb524xo(CursorCtl, 0x23); - - vgaxo(Crtx, 0x55, rs2); -} - -static int -rgb524move(VGAscr*, Point p) -{ - uchar rs2; - - rs2 = rgb524setrs2(); - - rgb524xo(CursorXLo, p.x & 0xFF); - rgb524xo(CursorXHi, (p.x>>8) & 0x0F); - rgb524xo(CursorYLo, p.y & 0xFF); - rgb524xo(CursorYHi, (p.y>>8) & 0x0F); - - vgaxo(Crtx, 0x55, rs2); - - return 0; -} - -VGAcur vgargb524cur = { - "rgb524hwgc", - - rgb524enable, - rgb524disable, - rgb524load, - rgb524move, -}; +#include "../pc/vgargb524.c" diff --git a/alphapc/vgas3.c b/alphapc/vgas3.c index 20165c5355093a8e3d43ec84d6bb9777f8de1167..8829ab607fb0503725355b2e90968fd8395794d9 100644 --- a/alphapc/vgas3.c +++ b/alphapc/vgas3.c @@ -1,506 +1 @@ -#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 int -s3pageset(VGAscr* scr, int page) -{ - uchar crt35, crt51; - int opage; - - crt35 = vgaxi(Crtx, 0x35); - if(scr->gscreen->depth >= 8){ - /* - * The S3 registers need to be unlocked for this. - * Let's hope they are already: - * vgaxo(Crtx, 0x38, 0x48); - * vgaxo(Crtx, 0x39, 0xA0); - * - * The page is 6 bits, the lower 4 bits in Crt35<3:0>, - * the upper 2 in Crt51<3:2>. - */ - vgaxo(Crtx, 0x35, page & 0x0F); - crt51 = vgaxi(Crtx, 0x51); - vgaxo(Crtx, 0x51, (crt51 & ~0x0C)|((page & 0x30)>>2)); - opage = ((crt51 & 0x0C)<<2)|(crt35 & 0x0F); - } - else{ - vgaxo(Crtx, 0x35, (page<<2) & 0x0C); - opage = (crt35>>2) & 0x03; - } - - return opage; -} - -static void -s3page(VGAscr* scr, int page) -{ - int id; - - id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); - switch(id){ - - case 0xE110: /* ViRGE/GX2 */ - break; - - default: - lock(&scr->devlock); - s3pageset(scr, page); - unlock(&scr->devlock); - break; - } -} - -static ulong -s3linear(VGAscr* scr, int* size, int* align) -{ - ulong aperture, oaperture, opciaddr; - int oapsize, wasupamem; - Pcidev *p; - - oaperture = scr->aperture; - oapsize = scr->apsize; - opciaddr = scr->pciaddr; - wasupamem = scr->isupamem; - if(wasupamem) - upafree(oaperture, oapsize); - scr->isupamem = 0; - scr->pciaddr = 0; - - if(p = pcimatch(nil, 0x5333, 0)){ - aperture = p->mem[0].bar & ~0x0F; - *size = p->mem[0].size; - } - else - aperture = 0; - - aperture = upamalloc(aperture, *size, *align); - if(aperture == 0){ - if(wasupamem && upamalloc(oaperture, oapsize, 0)){ - scr->isupamem = 1; - scr->pciaddr = opciaddr; - } - } - else{ - scr->pciaddr = p->mem[0].bar & ~0x0F; - scr->isupamem = 1; - } - - return aperture; -} - -static void -s3vsyncactive(void) -{ - /* - * Hardware cursor information is fetched from display memory - * during the horizontal blank active time. The 80x chips may hang - * if the cursor is turned on or off during this period. - */ - while((vgai(Status1) & 0x08) == 0) - ; -} - -static void -s3disable(VGAscr*) -{ - uchar crt45; - - /* - * Turn cursor off. - */ - crt45 = vgaxi(Crtx, 0x45) & 0xFE; - s3vsyncactive(); - vgaxo(Crtx, 0x45, crt45); -} - -static void -s3enable(VGAscr* scr) -{ - int i; - ulong storage; - - s3disable(scr); - - /* - * Cursor colours. Set both the CR0[EF] and the colour - * stack in case we are using a 16-bit RAMDAC. - */ - vgaxo(Crtx, 0x0E, Pwhite); - vgaxo(Crtx, 0x0F, Pblack); - vgaxi(Crtx, 0x45); - - for(i = 0; i < 3; i++) - vgaxo(Crtx, 0x4A, Pblack); - vgaxi(Crtx, 0x45); - for(i = 0; i < 3; i++) - vgaxo(Crtx, 0x4B, Pwhite); - - /* - * Find a place for the cursor data in display memory. - * Must be on a 1024-byte boundary. - */ - storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024; - vgaxo(Crtx, 0x4C, (storage>>8) & 0x0F); - vgaxo(Crtx, 0x4D, storage & 0xFF); - storage *= 1024; - scr->storage = storage; - - /* - * Enable the cursor in Microsoft Windows format. - */ - vgaxo(Crtx, 0x55, vgaxi(Crtx, 0x55) & ~0x10); - s3vsyncactive(); - vgaxo(Crtx, 0x45, 0x01); -} - -static void -s3load(VGAscr* scr, Cursor* curs) -{ - uchar *p; - int id, opage, x, y; - - /* - * Disable the cursor and - * set the pointer to the two planes. - */ - s3disable(scr); - - opage = 0; - p = KADDR(scr->aperture); - id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); - switch(id){ - - case 0xE131: /* ViRGE */ - case 0xE18A: /* ViRGE/[DG]X */ - case 0xE110: /* ViRGE/GX2 */ - case 0xE13D: /* ViRGE/VX */ - p += scr->storage; - break; - - default: - lock(&scr->devlock); - opage = s3pageset(scr, scr->storage>>16); - p += (scr->storage & 0xFFFF); - break; - } - - /* - * The cursor is set in Microsoft Windows format (the ViRGE/GX2 no - * longer supports the X11 format) which gives the following truth table: - * and xor colour - * 0 0 background colour - * 0 1 foreground colour - * 1 0 current screen pixel - * 1 1 NOT current screen pixel - * Put the cursor into the top-left of the 64x64 array. - * - * The cursor pattern in memory is interleaved words of - * AND and XOR patterns. - */ - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x += 2){ - if(x < 16/8 && y < 16){ - *p++ = ~(curs->clr[2*y + x]|curs->set[2*y + x]); - *p++ = ~(curs->clr[2*y + x+1]|curs->set[2*y + x+1]); - *p++ = curs->set[2*y + x]; - *p++ = curs->set[2*y + x+1]; - } - else { - *p++ = 0xFF; - *p++ = 0xFF; - *p++ = 0x00; - *p++ = 0x00; - } - } - } - - switch(id){ - - case 0xE131: /* ViRGE */ - case 0xE18A: /* ViRGE/[DG]X */ - case 0xE110: /* ViRGE/GX2 */ - case 0xE13D: /* ViRGE/VX */ - break; - - default: - s3pageset(scr, opage); - unlock(&scr->devlock); - break; - } - - /* - * Save the cursor hotpoint and enable the cursor. - */ - scr->offset = curs->offset; - s3vsyncactive(); - vgaxo(Crtx, 0x45, 0x01); -} - -static int -s3move(VGAscr* scr, Point p) -{ - int x, xo, y, yo; - - /* - * Mustn't position the cursor offscreen even partially, - * or it disappears. Therefore, if x or y is -ve, adjust the - * cursor offset instead. - * There seems to be a bug in that if the offset is 1, the - * cursor doesn't disappear off the left edge properly, so - * round it up to be even. - */ - if((x = p.x+scr->offset.x) < 0){ - xo = -x; - xo = ((xo+1)/2)*2; - x = 0; - } - else - xo = 0; - if((y = p.y+scr->offset.y) < 0){ - yo = -y; - y = 0; - } - else - yo = 0; - - vgaxo(Crtx, 0x46, (x>>8) & 0x07); - vgaxo(Crtx, 0x47, x & 0xFF); - vgaxo(Crtx, 0x49, y & 0xFF); - vgaxo(Crtx, 0x4E, xo); - vgaxo(Crtx, 0x4F, yo); - vgaxo(Crtx, 0x48, (y>>8) & 0x07); - - return 0; -} - -/* - * The manual gives byte offsets, but we want ulong offsets, hence /4. - */ -enum { - SrcBase = 0xA4D4/4, - DstBase = 0xA4D8/4, - Stride = 0xA4E4/4, - FgrdData = 0xA4F4/4, - WidthHeight = 0xA504/4, - SrcXY = 0xA508/4, - DestXY = 0xA50C/4, - Command = 0xA500/4, - SubStat = 0x8504/4, - FifoStat = 0x850C/4, -}; - -/* - * Wait for writes to VGA memory via linear aperture to flush. - */ -enum {Maxloop = 1<<24}; -struct { - ulong linear; - ulong fifo; - ulong idle; -} waitcount; - -static void -waitforlinearfifo(VGAscr *scr) -{ - ulong *mmio; - long x; - static ulong nwaitforlinearfifo; - ulong mask, val; - - switch(scr->id){ - default: - panic("unknown scr->id in s3 waitforlinearfifo"); - case 0xE131: /* ViRGE */ - case 0xE13D: /* ViRGE/VX */ - mask = 0x0F<<6; - val = 0x08<<6; - break; - case 0xE110: /* ViRGE/GX2 */ - mask = 0x1F<<6; - val = 0x10<<6; - break; - } - mmio = scr->mmio; - x = 0; - while((mmio[FifoStat]&mask) != val && x++ < Maxloop) - waitcount.linear++; -} - -static void -waitforfifo(VGAscr *scr, int entries) -{ - ulong *mmio; - long x; - static ulong nwaitforfifo; - - mmio = scr->mmio; - x = 0; - while((mmio[SubStat]&0x1F00) < ((entries+2)<<8) && x++ < Maxloop) - waitcount.fifo++; -} - -static void -waitforidle(VGAscr *scr) -{ - ulong *mmio; - long x; - - mmio = scr->mmio; - x = 0; - while((mmio[SubStat]&0x3F00) != 0x3000 && x++ < Maxloop) - waitcount.idle++; -} - -static int -hwscroll(VGAscr *scr, Rectangle r, Rectangle sr) -{ - enum { Bitbltop = 0xCC }; /* copy source */ - ulong *mmio; - ulong cmd, stride; - Point dp, sp; - int did, d; - - d = scr->gscreen->depth; - did = (d-8)/8; - cmd = 0x00000020|(Bitbltop<<17)|(did<<2); - stride = Dx(scr->gscreen->r)*d/8; - - if(r.min.x <= sr.min.x){ - cmd |= 1<<25; - dp.x = r.min.x; - sp.x = sr.min.x; - }else{ - dp.x = r.max.x-1; - sp.x = sr.max.x-1; - } - - if(r.min.y <= sr.min.y){ - cmd |= 1<<26; - dp.y = r.min.y; - sp.y = sr.min.y; - }else{ - dp.y = r.max.y-1; - sp.y = sr.max.y-1; - } - - mmio = scr->mmio; - waitforlinearfifo(scr); - waitforfifo(scr, 7); - mmio[SrcBase] = scr->aperture; - mmio[DstBase] = scr->aperture; - mmio[Stride] = (stride<<16)|stride; - mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r); - mmio[SrcXY] = (sp.x<<16)|sp.y; - mmio[DestXY] = (dp.x<<16)|dp.y; - mmio[Command] = cmd; - waitforidle(scr); - return 1; -} - -static int -hwfill(VGAscr *scr, Rectangle r, ulong sval) -{ - enum { Bitbltop = 0xCC }; /* copy source */ - ulong *mmio; - ulong cmd, stride; - int did, d; - - d = scr->gscreen->depth; - did = (d-8)/8; - cmd = 0x16000120|(Bitbltop<<17)|(did<<2); - stride = Dx(scr->gscreen->r)*d/8; - mmio = scr->mmio; - waitforlinearfifo(scr); - waitforfifo(scr, 8); - mmio[SrcBase] = scr->aperture; - mmio[DstBase] = scr->aperture; - mmio[DstBase] = scr->aperture; - mmio[Stride] = (stride<<16)|stride; - mmio[FgrdData] = sval; - mmio[WidthHeight] = ((Dx(r)-1)<<16)|Dy(r); - mmio[DestXY] = (r.min.x<<16)|r.min.y; - mmio[Command] = cmd; - waitforidle(scr); - return 1; -} - -enum { - CursorSyncCtl = 0x0D, /* in Seqx */ - VsyncHi = 0x80, - VsyncLo = 0x40, - HsyncHi = 0x20, - HsyncLo = 0x10, -}; - -static void -s3blank(int blank) -{ - uchar x; - - x = vgaxi(Seqx, CursorSyncCtl); - x &= ~0xF0; - if(blank) - x |= VsyncLo | HsyncLo; - vgaxo(Seqx, CursorSyncCtl, x); -} - -static void -s3drawinit(VGAscr *scr) -{ - ulong id; - - id = (vgaxi(Crtx, 0x30)<<8)|vgaxi(Crtx, 0x2E); - scr->id = id; - - /* - * It's highly likely that other ViRGEs will work without - * change to the driver, with the exception of the size of - * the linear aperture memory write FIFO. Since we don't - * know that size, I'm not turning them on. See waitforlinearfifo - * above. - */ - switch(id){ - case 0xE131: /* ViRGE */ - case 0xE13D: /* ViRGE/VX */ - case 0xE110: /* ViRGE/GX2 */ - scr->mmio = (ulong*)(scr->pciaddr+0x1000000); -/* - * Untested on the Alpha. - */ -/* - scr->fill = hwfill; - scr->scroll = hwscroll; -*/ - /* scr->blank = hwblank; */ - } -} - -VGAdev vgas3dev = { - "s3", - - 0, - 0, - s3page, - s3linear, - s3drawinit, -}; - -VGAcur vgas3cur = { - "s3hwgc", - - s3enable, - s3disable, - s3load, - s3move, -}; +#include "../pc/vgas3.c" diff --git a/alphapc/vgasavage.c b/alphapc/vgasavage.c new file mode 100644 index 0000000000000000000000000000000000000000..11f2630cf04926e9d9c854953147c83846a7594a --- /dev/null +++ b/alphapc/vgasavage.c @@ -0,0 +1 @@ +#include "../pc/vgasavage.c" diff --git a/alphapc/vgatvp3026.c b/alphapc/vgatvp3026.c index 1b97d1bf7a830af4cea6670618f8aff2b5dfe4ed..5e9878c0f34ac2c9ed6904ce85c2b368d94b3416 100644 --- a/alphapc/vgatvp3026.c +++ b/alphapc/vgatvp3026.c @@ -1,189 +1 @@ -#include "u.h" -#include "../port/lib.h" -#include "mem.h" -#include "dat.h" -#include "fns.h" -#include "../port/error.h" - -#define Image IMAGE -#include -#include -#include -#include "screen.h" - -/* - * TVP3026 Viewpoint Video Interface Pallette. - * Assumes hooked up to an S3 Vision968. - */ -enum { - Index = 0x00, /* Index */ - Data = 0x0A, /* Data */ - - CaddrW = 0x04, /* Colour Write Address */ - Cdata = 0x05, /* Colour Data */ - - Cctl = 0x09, /* Direct Cursor Control */ - Cram = 0x0B, /* Cursor Ram Data */ - Cxlsb = 0x0C, /* Cursor X LSB */ - Cxmsb = 0x0D, /* Cursor X MSB */ - Cylsb = 0x0E, /* Cursor Y LSB */ - Cymsb = 0x0F, /* Cursor Y MSB */ - - Icctl = 0x06, /* Indirect Cursor Control */ -}; - -/* - * Lower 2-bits of indirect DAC register - * addressing. - */ -static ushort dacxreg[4] = { - PaddrW, Pdata, Pixmask, PaddrR -}; - -static uchar -tvp3026io(uchar reg, uchar data) -{ - uchar crt55; - - crt55 = vgaxi(Crtx, 0x55) & 0xFC; - vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03)); - vgao(dacxreg[reg & 0x03], data); - - return crt55; -} - -static void -tvp3026o(uchar reg, uchar data) -{ - uchar crt55; - - crt55 = tvp3026io(reg, data); - vgaxo(Crtx, 0x55, crt55); -} - -void -tvp3026xo(uchar index, uchar data) -{ - uchar crt55; - - crt55 = tvp3026io(Index, index); - vgaxo(Crtx, 0x55, crt55|((Data>>2) & 0x03)); - vgao(dacxreg[Data & 0x03], data); - vgaxo(Crtx, 0x55, crt55); -} - -static void -tvp3026disable(VGAscr*) -{ - tvp3026xo(Icctl, 0x90); - tvp3026o(Cctl, 0x00); -} - -static void -tvp3026enable(VGAscr*) -{ - /* - * Make sure cursor is off and direct control enabled. - */ - tvp3026xo(Icctl, 0x90); - tvp3026o(Cctl, 0x00); - - /* - * Overscan colour, - * cursor colour 1 (white), - * cursor colour 2, 3 (black). - */ - tvp3026o(CaddrW, 0x00); - tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); - tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); tvp3026o(Cdata, Pwhite); - tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); - tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); tvp3026o(Cdata, Pblack); - - /* - * Enable the cursor in 3-colour mode. - */ - tvp3026o(Cctl, 0x01); -} - -static void -tvp3026load(VGAscr* scr, Cursor* curs) -{ - int x, y; - - /* - * Make sure cursor is off by initialising the cursor - * control to defaults. - * Write to the indirect control register to make sure - * direct register is enabled and upper 2 bits of cursor - * RAM address are 0. - * The LSBs of the cursor RAM address are in PaddrW. - */ - tvp3026xo(Icctl, 0x90); - tvp3026o(Cctl, 0x00); - vgao(PaddrW, 0x00); - - /* - * Initialise the 64x64 cursor RAM array. There are 2 planes, - * p0 and p1. Data is written 8 pixels per byte, with p0 in the - * first 512 bytes of the array and p1 in the second. - * The cursor is set in 3-colour mode which gives the following - * truth table: - * p1 p0 colour - * 0 0 transparent - * 0 1 cursor colour 0 - * 1 0 cursor colour 1 - * 1 1 cursor colour 2 - * Put the cursor into the top-left of the 64x64 array. - * The 0,0 cursor point is bottom-right, so positioning will - * have to take that into account. - */ - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x++){ - if(x < 16/8 && y < 16) - tvp3026o(Cram, curs->clr[x+y*2]); - else - tvp3026o(Cram, 0x00); - } - } - for(y = 0; y < 64; y++){ - for(x = 0; x < 64/8; x++){ - if(x < 16/8 && y < 16) - tvp3026o(Cram, curs->set[x+y*2]); - else - tvp3026o(Cram, 0x00); - } - } - - /* - * Initialise the cursor hotpoint - * and enable the cursor in 3-colour mode. - */ - scr->offset.x = 64+curs->offset.x; - scr->offset.y = 64+curs->offset.y; - tvp3026o(Cctl, 0x01); -} - -static int -tvp3026move(VGAscr* scr, Point p) -{ - int x, y; - - x = p.x+scr->offset.x; - y = p.y+scr->offset.y; - - tvp3026o(Cxlsb, x & 0xFF); - tvp3026o(Cxmsb, (x>>8) & 0x0F); - tvp3026o(Cylsb, y & 0xFF); - tvp3026o(Cymsb, (y>>8) & 0x0F); - - return 0; -} - -VGAcur vgatvp3026cur = { - "tvp3026hwgc", - - tvp3026enable, - tvp3026disable, - tvp3026load, - tvp3026move, -}; +#include "../pc/vgatvp3026.c" diff --git a/alphapc/vgax.c b/alphapc/vgax.c index 757ca171af4d8559ce7a2cd17307f3139bef8905..79ec3dcf4ff3f5d698b5abfa62315adc1ab52ab7 100644 --- a/alphapc/vgax.c +++ b/alphapc/vgax.c @@ -1,103 +1 @@ -#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 Lock vgaxlock; /* access to index registers */ - -int -vgaxi(long port, uchar index) -{ - uchar data; - - ilock(&vgaxlock); - switch(port){ - - case Seqx: - case Crtx: - case Grx: - outb(port, index); - data = inb(port+1); - break; - - case Attrx: - /* - * Allow processor access to the colour - * palette registers. Writes to Attrx must - * be preceded by a read from Status1 to - * initialise the register to point to the - * index register and not the data register. - * Processor access is allowed by turning - * off bit 0x20. - */ - inb(Status1); - if(index < 0x10){ - outb(Attrx, index); - data = inb(Attrx+1); - inb(Status1); - outb(Attrx, 0x20|index); - } - else{ - outb(Attrx, 0x20|index); - data = inb(Attrx+1); - } - break; - - default: - iunlock(&vgaxlock); - return -1; - } - iunlock(&vgaxlock); - - return data & 0xFF; -} - -int -vgaxo(long port, uchar index, uchar data) -{ - ilock(&vgaxlock); - switch(port){ - - case Seqx: - case Crtx: - case Grx: - /* - * We could use an outport here, but some chips - * (e.g. 86C928) have trouble with that for some - * registers. - */ - outb(port, index); - outb(port+1, data); - break; - - case Attrx: - inb(Status1); - if(index < 0x10){ - outb(Attrx, index); - outb(Attrx, data); - inb(Status1); - outb(Attrx, 0x20|index); - } - else{ - outb(Attrx, 0x20|index); - outb(Attrx, data); - } - break; - - default: - iunlock(&vgaxlock); - return -1; - } - iunlock(&vgaxlock); - - return 0; -} +#include "../pc/vgax.c"