M alphapc/devfloppy.c => alphapc/devfloppy.c +1 -1076
@@ 1,1076 1,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"
M alphapc/ether2114x.c => alphapc/ether2114x.c +1 -1581
@@ 1,1581 1,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<<ctlr->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<<i);
- csr9w(ctlr, Mii|Mdc);
- csr9w(ctlr, Mii);
- }
- csr9w(ctlr, 0);
-
- return data;
-}
-
-static void
-miimdo(Ctlr* ctlr, int bits, int n)
-{
- int i, mdo;
-
- /*
- * Write n bits to the MII Management Register.
- */
- for(i = n-1; i >= 0; i--){
- if(bits & (1<<i))
- mdo = Mdo;
- else
- mdo = 0;
- csr9w(ctlr, mdo);
- csr9w(ctlr, mdo|Mdc);
- csr9w(ctlr, mdo);
- }
-}
-
-static int
-miir(Ctlr* ctlr, int phyad, int regad)
-{
- int data, i;
-
- if(ctlr->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<<i);
- csr9w(ctlr, Rd|Ss|Scs);
- }
-
- csr9w(ctlr, 0);
-
- if(ctlr->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<<phyx))){
- debug("reset seq: len %d: ", block[3]);
- if(ctlr->type5block)
- type5block(ctlr, &ctlr->type5block[2]);
- else
- type5block(ctlr, &block[4+len*block[3]]);
- debug("\n");
- ctlr->phyreset |= (1<<phyx);
- }
-
- /*
- * GPR sequence.
- */
- debug("gpr seq: len %d: ", block[3]);
- type5block(ctlr, &block[3]);
- debug("\n");
-
- ctlr->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<<ctlr->sromsz)*sizeof(ushort));
- for(i = 0; i < (1<<ctlr->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"
M alphapc/etherif.h => alphapc/etherif.h +0 -1
@@ 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*);
M alphapc/mouse.c => alphapc/mouse.c +1 -311
@@ 1,311 1,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 <draw.h>
-#include <memdraw.h>
-#include <cursor.h>
-#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"
M alphapc/screen.h => alphapc/screen.h +5 -4
@@ 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*);
M alphapc/uarti8250.c => alphapc/uarti8250.c +1 -648
@@ 1,648 1,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"
M alphapc/vga.c => alphapc/vga.c +1 -225
@@ 1,225 1,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 <draw.h>
-#include <memdraw.h>
-#include <cursor.h>
-#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"
M alphapc/vgargb524.c => alphapc/vgargb524.c +1 -237
@@ 1,237 1,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 <draw.h>
-#include <memdraw.h>
-#include <cursor.h>
-#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"
M alphapc/vgas3.c => alphapc/vgas3.c +1 -506
@@ 1,506 1,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 <draw.h>
-#include <memdraw.h>
-#include <cursor.h>
-#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"
A alphapc/vgasavage.c => alphapc/vgasavage.c +1 -0
@@ 0,0 1,1 @@
+#include "../pc/vgasavage.c"
M alphapc/vgatvp3026.c => alphapc/vgatvp3026.c +1 -189
@@ 1,189 1,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 <draw.h>
-#include <memdraw.h>
-#include <cursor.h>
-#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"
M alphapc/vgax.c => alphapc/vgax.c +1 -103
@@ 1,103 1,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 <draw.h>
-#include <memdraw.h>
-#include <cursor.h>
-#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"