M carrera/io.h => carrera/io.h +4 -0
@@ 1,5 1,8 @@
/*
* These register addresses have already been adjusted for BE operation
+ *
+ * The EISA memory address is completely fictional. Look at mmu.c for
+ * a translation of Eisamphys into a 33 bit address.
*/
enum
{
@@ 35,6 38,7 @@ enum
I386ack = 0xE000023f,
EisaControl = 0xE0010000, /* Second 64K Page from Devicevirt */
Eisamphys = 0x91000000,
+ Eisavgaphys = Eisamphys+0xA0000,
Eisamvirt = 0xE0300000, /* Second 1M page entry from Intctl */
Intctlphys = 0xF0000000,
Intctlvirt = 0xE0200000,
M carrera/main.c => carrera/main.c +2 -2
@@ 51,8 51,8 @@ main(void)
pageinit();
procinit0();
initseg();
+ links();
chandevreset();
- rootfiles();
swapinit();
userinit();
schedinit();
@@ 179,7 179,7 @@ ioinit(void)
* Map Interrupt control & Eisa memory
*/
intphys = IOPTE|PPN(Intctlphys);
- isamphys = IOPTE|PPN(Eisamphys);
+ isamphys = /* IOPTE|PPN(Eisamphys) */ PTEGLOBL;
puttlbx(2, Intctlvirt, intphys, isamphys, PGSZ1M);
M carrera/mmu.c => carrera/mmu.c +10 -1
@@ 3,6 3,7 @@
#include "mem.h"
#include "dat.h"
#include "fns.h"
+#include "io.h"
/*
* tlb entry 0 is used only by mmuswitch() to set the current tlb pid.
@@ 258,16 259,24 @@ newtlbpid(Proc *p)
void
putmmu(ulong tlbvirt, ulong tlbphys, Page *pg)
{
+ int s;
short tp;
char *ctl;
Softtlb *entry;
- int s;
s = splhi();
tp = up->pidonmach[m->machno];
if(tp == 0)
tp = newtlbpid(up);
+ /*
+ * Fix up EISA memory address which are greater
+ * than 32 bits physical: 0x100000000
+ */
+ if((tlbphys&0xffff0000) == PPN(Eisamphys)) {
+ tlbphys &= ~PPN(Eisamphys);
+ tlbphys |= 0x04000000;
+ }
tlbvirt |= PTEPID(tp);
if((tlbphys & PTEALGMASK) != PTEUNCACHED) {
tlbphys &= ~PTEALGMASK;
M carrera/segment.h => carrera/segment.h +5 -4
@@ 4,8 4,9 @@
Physseg physseg[] =
{
- { SG_SHARED, "shared", 0, SEGMAXSIZE, 0, 0 },
- { SG_BSS, "memory", 0, SEGMAXSIZE, 0, 0 },
- { SG_PHYSICAL, "eisaio", Eisaphys, 64*1024, 0, 0 },
- { 0, 0, 0, 0, 0, 0 },
+ { SG_SHARED, "shared", 0, SEGMAXSIZE, 0, 0 },
+ { SG_BSS, "memory", 0, SEGMAXSIZE, 0, 0 },
+ { SG_PHYSICAL, "eisaio", Eisaphys, 64*1024, 0, 0 },
+ { SG_PHYSICAL, "eisavga", Eisavgaphys, 128*1024, 0, 0 },
+ { 0, 0, 0, 0, 0, 0 },
};
M pc/adaptec.c => pc/adaptec.c +37 -79
@@ 1,5 1,9 @@
/*
- * Adaptec AHA-154[02]B Intelligent Host Adapter.
+ * Adaptec AHA-154[02][BC] Intelligent Host Adapter.
+ * Needs work:
+ * handle multiple controllers;
+ * set options from user-level;
+ * split out to handle ultrastor too;
*/
#include "u.h"
#include "../port/lib.h"
@@ 11,12 15,6 @@
#include "ureg.h"
-/*
- * Uniprocessors can't (don't need to) lock.
- */
-#define lock(l)
-#define unlock(l)
-
enum {
NCtlr = 1,
NTarget = 8, /* targets per controller */
@@ 314,7 312,8 @@ scsiio(int bus, Scsi *p, int rw)
* requests off the queue in any order.
*/
s = splhi();
- lock(ctlr);
+ if(active.machs > 1)
+ lock(ctlr);
tp->done = 0;
tp->active = ctlr->active;
@@ 334,7 333,8 @@ scsiio(int bus, Scsi *p, int rw)
if(ctlr->mbox >= &ctlr->mb[NTarget])
ctlr->mbox = ctlr->mb;
- unlock(ctlr);
+ if(active.machs > 1)
+ unlock(ctlr);
splx(s);
/*
@@ 364,8 364,8 @@ scsiio(int bus, Scsi *p, int rw)
return status;
}
-int
-scsiexec(Scsi *p, int rw)
+static int
+aha1542exec(Scsi *p, int rw)
{
Ctlr *ctlr = &softctlr[0];
@@ 387,7 387,8 @@ interrupt(Ureg *ur)
USED(ur);
- lock(ctlr);
+ if(active.machs > 1)
+ lock(ctlr);
/*
* Save and clear the interrupt(s). The only
@@ 430,7 431,8 @@ interrupt(Ureg *ur)
ctlr->mbix = &ctlr->mb[NTarget];
}
- unlock(ctlr);
+ if(active.machs > 1)
+ unlock(ctlr);
}
static void
@@ 465,83 467,39 @@ reset(Ctlr *ctlr, ulong port, ulong id)
issue(ctlr);
}
-void
-resetscsi(void)
+static ISAConf aha1542 = {
+ "aha1542",
+ Port,
+ Irq,
+ 0,
+ 0,
+};
+
+int (*
+aha1542reset(void))(Scsi*, int)
{
- ulong port;
+ ISAConf *isa = &aha1542;
/*
- * For the moment assume the factory default settings.
+ * See if we have any configuration info.
+ * Only one controller for now.
*/
- port = Port;
+ if(isaconfig("scsi", 0, &aha1542) == 0)
+ return 0;
/*
- * Attempt to soft-reset the board and reset
+ * Attempt to hard-reset the board and reset
* the SCSI bus. If the board state doesn't settle to
* idle with mailbox initialisation required, either
* it isn't an Adaptec or it's broken.
*/
- outb(port+Rc, Srst|Scrst);
+ outb(isa->port+Rc, Hrst|Scrst);
delay(500);
- if(inb(port+Rs) != (Init|Idle))
- return;
-
- setvec(Int0vec+Irq, interrupt);
- reset(&softctlr[0], port, CtlrID);
-}
-
-/*
- * Known to devscsi.c.
- */
-int scsidebugs[8];
-int scsiownid = CtlrID;
-
-void
-initscsi(void)
-{
-}
-
-/*
- * Quick hack. Need to do a better job of dynamic initialisation
- * for machines with peculiar memory/cache restictions.
- * Also, what about 16Mb address limit on the Adaptec?
- */
-static ulong bufdatasize;
-
-void
-scsibufreset(ulong datasize)
-{
- bufdatasize = datasize;
-}
-
-Scsibuf *
-scsibuf(void)
-{
- Scsibuf *b;
+ if(inb(isa->port+Rs) != (Init|Idle))
+ return 0;
- b = smalloc(sizeof(*b));
- b->virt = smalloc(bufdatasize);
- b->phys = (void *)(PADDR(b->virt));
- return b;
-}
-
-void
-scsifree(Scsibuf *b)
-{
- free(b->virt);
- free(b);
-}
-
-/*
- * Hack for devvid
- */
-Scsibuf *
-scsialloc(ulong n)
-{
- Scsibuf *b;
+ setvec(Int0vec+isa->irq, interrupt);
+ reset(&softctlr[0], isa->port, CtlrID);
- b = smalloc(sizeof(*b));
- b->virt = smalloc(n);
- b->phys = (void *)(PADDR(b->virt));
- return b;
+ return aha1542exec;
}
M pc/clock.c => pc/clock.c +11 -17
@@ 72,7 72,7 @@ clockinit(void)
x -= y;
/*
- * fix count, the factor of 2 is a hack
+ * fix count
*/
delayloop = (delayloop*1193*10)/x;
if(delayloop == 0)
@@ 104,20 104,14 @@ clock(Ureg *ur)
nrun = (nrdy+nrun)*1000;
MACHP(0)->load = (MACHP(0)->load*19+nrun)/20;
- if(u && p && p->state==Running){
- /*
- * preemption
- */
- if(anyready()){
- if(p->hasspin)
- p->hasspin = 0;
- else
- sched();
- }
- if((ur->cs&0xffff) == UESEL){
- spllo(); /* in case we fault */
- (*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1); /* profiling clock */
- splhi();
- }
- }
+ if(up == 0 || (ur->cs&0xffff) != UESEL || up->state != Running)
+ return;
+
+ if(anyready())
+ sched();
+
+ /* user profiling clock */
+ spllo(); /* in case we fault */
+ (*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1);
+ splhi();
}
M pc/dat.h => pc/dat.h +16 -36
@@ 1,5 1,6 @@
typedef struct Conf Conf;
typedef struct FPsave FPsave;
+typedef struct ISAConf ISAConf;
typedef struct Label Label;
typedef struct Lock Lock;
typedef struct MMU MMU;
@@ 9,7 10,6 @@ typedef struct Page Page;
typedef struct PMMU PMMU;
typedef struct Segdesc Segdesc;
typedef struct Ureg Ureg;
-typedef struct User User;
#define MACHP(n) (n==0? &mach0 : *(Mach**)0)
@@ 88,6 88,7 @@ struct Conf
*/
#define MAXMMU 4
#define MAXSMMU 1
+#define NCOLOR 1
struct PMMU
{
Page *mmutop; /* 1st level table */
@@ 131,36 132,6 @@ typedef void KMap;
#define kmap(p) (KMap*)((p)->pa|KZERO)
#define kunmap(k)
-#define NERR 15
-#define NNOTE 5
-struct User
-{
- Proc *p;
- FPsave fpsave; /* address of this is known by vdb */
- int scallnr; /* sys call number - known by db */
- Sargs s; /* address of this is known by db */
- int nerrlab;
- Label errlab[NERR];
- char error[ERRLEN];
- char elem[NAMELEN]; /* last name element from namec */
- Chan *slash;
- Chan *dot;
- /*
- * Rest of structure controlled by devproc.c and friends.
- * lock(&p->debug) to modify.
- */
- Note note[NNOTE];
- short nnote;
- short notified; /* sysnoted is due */
- Note lastnote;
- int (*notify)(void*, char*);
- void *ureg;
- void *dbgreg; /* User registers for debugging in proc */
- ulong svcs; /* cs before a notify */
- ulong svss; /* ss before a notify */
- ulong svflags; /* flags before a notify */
-};
-
/*
* segment descriptor/gate
*/
@@ 192,11 163,20 @@ struct PCArch
int (*extvga)(int); /* 1 == external, 0 == internal */
};
-extern Mach *m;
-extern User *u;
+struct ISAConf {
+ char type[NAMELEN];
+ ulong port;
+ ulong irq;
+ ulong mem;
+ ulong size;
+ uchar ea[6];
+};
-extern int flipD[]; /* for flipping bitblt destination polarity */
+#define MAXPCMCIA 8 /* maximum number of PCMCIA cards */
+#define BOOTLINE ((char *)0x80000100) /* bootline passed by boot program */
-#define BOOTLINE ((char *)0x80000100) /* bootline passed by boot program */
+extern int flipD[]; /* for flipping bitblt destination polarity */
+extern PCArch *arch; /* PC architecture */
-extern PCArch *arch; /* PC architecture */
+extern Mach *m;
+extern Proc *up;
M pc/devfloppy.c => pc/devfloppy.c +26 -21
@@ 440,12 440,33 @@ changed(Chan *c, Drive *dp)
error(Eio);
}
+static int
+readtrack(Drive *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;
+}
+
long
floppyread(Chan *c, void *a, long n, ulong offset)
{
Drive *dp;
- long rv, i;
- int nn, sec, head, cyl;
+ long rv;
+ int sec, head, cyl;
long len;
uchar *aa;
@@ 468,7 489,7 @@ floppyread(Chan *c, void *a, long n, ulong offset)
changed(c, dp);
for(rv = 0; rv < n; rv += len){
/*
- * truncate xfer at track boundary
+ * all xfers come out of the track cache
*/
dp->len = n - rv;
floppypos(dp, offset+rv);
@@ 476,24 497,8 @@ floppyread(Chan *c, void *a, long n, ulong offset)
head = dp->thead;
len = dp->len;
sec = dp->tsec;
- nn = dp->t->tsize;
-
- /*
- * read the track
- */
- if(dp->ccyl!=cyl || dp->chead!=head){
- dp->ccyl = -1;
- i = floppyxfer(dp, Fread, dp->cache,
- (cyl*dp->t->heads+head)*nn, nn);
- if(i != nn){
- if(i == 0)
- break;
- len = 0;
- continue;
- }
- dp->ccyl = cyl;
- dp->chead = head;
- }
+ if(readtrack(dp, cyl, head) < 0)
+ break;
memmove(aa+rv, dp->cache + (sec-1)*dp->t->bytes, len);
}
qunlock(&fl);
M pc/devhard.c => pc/devhard.c +31 -13
@@ 155,7 155,7 @@ hardgen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp)
name[NAMELEN] = 0;
qid.path = MKQID(drive, s);
l = (pp->end - pp->start) * dp->bytes;
- devdir(c, qid, name, l, eve, 0666, dirp);
+ devdir(c, qid, name, l, eve, 0660, dirp);
return 1;
}
@@ 447,7 447,7 @@ hardxfer(Drive *dp, Partition *pp, int cmd, long start, long len, char *buf)
Controller *cp;
long lblk;
int cyl, sec, head;
- int loop, s;
+ int loop, s, stat;
if(dp->online == 0)
error(Eio);
@@ 502,12 502,15 @@ hardxfer(Drive *dp, Partition *pp, int cmd, long start, long len, char *buf)
outb(cp->pbase+Pcmd, cmd);
if(cmd == Cwrite){
loop = 0;
- while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
+ while((stat = inb(cp->pbase+Pstatus) & (Serr|Sdrq)) == 0)
if(++loop > 10000)
panic("hardxfer");
outss(cp->pbase+Pdata, cp->buf, dp->bytes/2);
- }
+ } else
+ stat = 0;
splx(s);
+ if(stat & Serr)
+ error(Eio);
/*
* wait for command to complete. if we get a note,
@@ 856,15 859,30 @@ hardpart(Drive *dp)
}
/*
- * read partition table from disk, null terminate
+ * read last sector from disk, null terminate. This used
+ * to be the sector we used for the partition tables.
+ * However, this sector is special on some PC's so we've
+ * started to use the second last sector as the partition
+ * table instead. To avoid reconfiguring all our old systems
+ * we first look to see if there is a valid partition
+ * table in the last sector. If so, we use it. Otherwise
+ * we switch to the second last.
*/
hardxfer(dp, pp, Cread, 0, dp->bytes, buf);
buf[dp->bytes-1] = 0;
+ n = getfields(buf, line, Npart+1, '\n');
+ if(n == 0 || strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1)){
+ dp->p[0].end--;
+ dp->p[1].start--;
+ dp->p[1].end--;
+ hardxfer(dp, pp, Cread, 0, dp->bytes, buf);
+ buf[dp->bytes-1] = 0;
+ n = getfields(buf, line, Npart+1, '\n');
+ }
/*
* parse partition table.
*/
- n = getfields(buf, line, Npart+1, '\n');
if(n && strncmp(line[0], PARTMAGIC, sizeof(PARTMAGIC)-1) == 0){
for(i = 1; i < n; i++){
pp++;
@@ 946,13 964,6 @@ hardintr(Ureg *ur)
break;
case Cread:
case Cident:
- loop = 0;
- while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
- if(++loop > 10000) {
- DPRINT("cmd=%lux status=%lux\n",
- cp->cmd, inb(cp->pbase+Pstatus));
- panic("hardintr: read/ident");
- }
if(cp->status & Serr){
cp->lastcmd = cp->cmd;
cp->cmd = 0;
@@ 960,6 971,13 @@ hardintr(Ureg *ur)
wakeup(&cp->r);
return;
}
+ loop = 0;
+ while((inb(cp->pbase+Pstatus) & Sdrq) == 0)
+ if(++loop > 10000) {
+ DPRINT("cmd=%lux status=%lux\n",
+ cp->cmd, inb(cp->pbase+Pstatus));
+ panic("hardintr: read/ident");
+ }
addr = cp->buf;
if(addr){
addr += cp->sofar*dp->bytes;
M pc/devincon.c => pc/devincon.c +28 -9
@@ 184,6 184,19 @@ Dirtab incondir[]={
#define NINCON (sizeof incondir/sizeof incondir[0])
static void
+nop(void)
+{
+}
+
+static int
+slowinb(int x)
+{
+ nop();
+ nop();
+ return inb(x);
+}
+
+static void
reset(int dev) /* hardware reset */
{
outb(dev+Qpcr, Finitbar);
@@ 261,9 274,9 @@ irdstatus(Incon *ip) /* read status at interrupt level */
outb(dev+Qdlr, 0x01);
outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
- data = (inb(dev+Qpsr)&0xf8)<<2;
+ data = (slowinb(dev+Qpsr)&0xf8)<<2;
outb(dev+Qpcr, Finitbar|Faf|Fsi);
- data |= inb(dev+Qpsr)>>3;
+ data |= slowinb(dev+Qpsr)>>3;
if(data&(OVERFLOW|CRC_ERROR)){
if(data&OVERFLOW)
ip->overflow++;
@@ 281,9 294,9 @@ irddata(int dev) /* read data at interrupt level */
outb(dev+Qdlr, 0x00);
outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
- data = (inb(dev+Qpsr)&0xf8)<<2;
+ data = (slowinb(dev+Qpsr)&0xf8)<<2;
outb(dev+Qpcr, Finitbar|Faf|Fsi);
- data |= inb(dev+Qpsr)>>3;
+ data |= slowinb(dev+Qpsr)>>3;
return data;
}
@@ 311,6 324,7 @@ irdnop(int dev, int pcr) /* read nop (mux reset) */
int Irdnext(int);
#define irdnext Irdnext
+/**/
/*
* set the incon parameters
@@ 366,11 380,6 @@ inconsetctl(Incon *ip, Block *bp)
freeb(bp);
}
-static void
-nop(void)
-{
-}
-
/*
* poll for a station number
*/
@@ 472,6 481,14 @@ void
inconreset(void)
{
int i;
+ char *p;
+
+ /*
+ * get incondev from p9rc
+ */
+ p = getconf("incondev");
+ if(p)
+ incondev = atoi(p);
/*
* state is Selected if we used incon as the boot device
@@ 1089,6 1106,8 @@ inconintr(Ureg *ur)
USED(ur);
ip = &incon[0];
pcr = inb(ip->dev+Qpcr);
+ if(!(pcr & Fie))
+ return;
status = irdstatus(ip);
if(incondebug){
kprint("pcr=%2.2x status=%2.2x\n", pcr, status);
M pc/devrtc.c => pc/devrtc.c +5 -5
@@ 23,7 23,7 @@ enum {
Status= 0x0A,
Nvoff= 128, /* where usable nvram lives */
- Nvsize= 128,
+ Nvsize= 256,
Nbcd= 6,
};
@@ 48,8 48,8 @@ enum{
#define NRTC 2
Dirtab rtcdir[]={
- "nvram", {Qnvram, 0}, Nvsize, 0666,
- "rtc", {Qrtc, 0}, 0, 0666,
+ "nvram", {Qnvram, 0}, Nvsize, 0664,
+ "rtc", {Qrtc, 0}, 0, 0664,
};
ulong rtc2sec(Rtc*);
@@ 96,11 96,11 @@ rtcopen(Chan *c, int omode)
omode = openmode(omode);
switch(c->qid.path){
case Qrtc:
- if(strcmp(u->p->user, eve)!=0 && omode!=OREAD)
+ if(strcmp(up->user, eve)!=0 && omode!=OREAD)
error(Eperm);
break;
case Qnvram:
- if(strcmp(u->p->user, eve)!=0)
+ if(strcmp(up->user, eve)!=0)
error(Eperm);
}
return devopen(c, omode, rtcdir, NRTC, devgen);
M pc/devuart.c => pc/devuart.c +267 -237
@@ 7,7 7,7 @@
#include "../port/error.h"
#include "devtab.h"
-
+#define nelem(x) (sizeof(x)/sizeof(x[0]))
/*
* Driver for an NS16450 serial port
*/
@@ 17,12 17,12 @@ enum
* register numbers
*/
Data= 0, /* xmit/rcv buffer */
- Iena= 1, /* interrupt enable */
+ Iena= 1, /* interrdpt enable */
Ircv= (1<<0), /* for char rcv'd */
Ixmt= (1<<1), /* for xmit buffer empty */
Irstat=(1<<2), /* for change in rcv'er status */
Imstat=(1<<3), /* for change in modem status */
- Istat= 2, /* interrupt flag (read) */
+ Istat= 2, /* interrdpt flag (read) */
Tctl= 2, /* test control (write) */
Format= 3, /* byte format */
Bits8= (3<<0), /* 8 bits/byte */
@@ 36,7 36,7 @@ enum
Dtr= (1<<0), /* data terminal ready */
Rts= (1<<1), /* request to send */
Ri= (1<<2), /* ring */
- Inton= (1<<3), /* turn on interrupts */
+ Inton= (1<<3), /* turn on interrdpts */
Loop= (1<<4), /* loop back */
Lstat= 5, /* line status */
Inready=(1<<0), /* receive buffer full */
@@ 86,9 86,12 @@ struct Uart
ulong overrun;
};
-Uart uart[2];
+Uart uart[34];
+int Nuart; /* total no of uarts in the machine */
+int Nscard; /* number of serial cards */
+ISAConf scard[5]; /* configs for the serial card */
-#define UartFREQ 1846200
+#define UartFREQ 1843200
#define uartwrreg(u,r,v) outb((u)->port + r, (u)->sticky[r] | (v))
#define uartrdreg(u,r) inb((u)->port + r)
@@ 96,6 99,7 @@ Uart uart[2];
void uartintr(Uart*);
void uartintr0(Ureg*);
void uartintr1(Ureg*);
+void uartintr2(Ureg*);
void uartsetup(void);
/*
@@ 104,135 108,136 @@ void uartsetup(void);
* baud rates.
*/
void
-uartsetbaud(Uart *up, int rate)
+uartsetbaud(Uart *dp, int rate)
{
ulong brconst;
brconst = (UartFREQ+8*rate-1)/(16*rate);
- uartwrreg(up, Format, Dra);
- outb(up->port+Dmsb, (brconst>>8) & 0xff);
- outb(up->port+Dlsb, brconst & 0xff);
- uartwrreg(up, Format, 0);
+ uartwrreg(dp, Format, Dra);
+ outb(dp->port+Dmsb, (brconst>>8) & 0xff);
+ outb(dp->port+Dlsb, brconst & 0xff);
+ uartwrreg(dp, Format, 0);
}
/*
* toggle DTR
*/
void
-uartdtr(Uart *up, int n)
+uartdtr(Uart *dp, int n)
{
if(n)
- up->sticky[Mctl] |= Dtr;
+ dp->sticky[Mctl] |= Dtr;
else
- up->sticky[Mctl] &= ~Dtr;
- uartwrreg(up, Mctl, 0);
+ dp->sticky[Mctl] &= ~Dtr;
+ uartwrreg(dp, Mctl, 0);
}
/*
* toggle RTS
*/
void
-uartrts(Uart *up, int n)
+uartrts(Uart *dp, int n)
{
if(n)
- up->sticky[Mctl] |= Rts;
+ dp->sticky[Mctl] |= Rts;
else
- up->sticky[Mctl] &= ~Rts;
- uartwrreg(up, Mctl, 0);
+ dp->sticky[Mctl] &= ~Rts;
+ uartwrreg(dp, Mctl, 0);
}
/*
* send break
*/
void
-uartbreak(Uart *up, int ms)
+uartbreak(Uart *dp, int ms)
{
if(ms == 0)
ms = 200;
- uartwrreg(up, Format, Break);
- tsleep(&u->p->sleep, return0, 0, ms);
- uartwrreg(up, Format, 0);
+ uartwrreg(dp, Format, Break);
+ tsleep(&dp->sleep, return0, 0, ms);
+ uartwrreg(dp, Format, 0);
}
/*
* set bits/char
*/
void
-uartbits(Uart *up, int bits)
+uartbits(Uart *dp, int bits)
{
if(bits < 5 || bits > 8)
error(Ebadarg);
- up->sticky[Format] &= ~3;
- up->sticky[Format] |= bits-5;
- uartwrreg(up, Format, 0);
+ dp->sticky[Format] &= ~3;
+ dp->sticky[Format] |= bits-5;
+ uartwrreg(dp, Format, 0);
}
/*
* set parity
*/
void
-uartparity(Uart *up, int c)
+uartparity(Uart *dp, int c)
{
switch(c&0xff){
case 'e':
- up->sticky[Format] |= Pena|Peven;
+ dp->sticky[Format] |= Pena|Peven;
break;
case 'o':
- up->sticky[Format] &= ~Peven;
- up->sticky[Format] |= Pena;
+ dp->sticky[Format] &= ~Peven;
+ dp->sticky[Format] |= Pena;
break;
default:
- up->sticky[Format] &= ~(Pena|Peven);
+ dp->sticky[Format] &= ~(Pena|Peven);
break;
}
- uartwrreg(up, Format, 0);
+ uartwrreg(dp, Format, 0);
}
/*
* set stop bits
*/
void
-uartstop(Uart *up, int n)
+uartstop(Uart *dp, int n)
{
switch(n){
case 1:
- up->sticky[Format] &= ~Stop2;
+ dp->sticky[Format] &= ~Stop2;
break;
case 2:
default:
- up->sticky[Format] |= Stop2;
+ dp->sticky[Format] |= Stop2;
break;
}
- uartwrreg(up, Format, 0);
+ uartwrreg(dp, Format, 0);
}
/*
* modem flow control on/off (rts/cts)
*/
void
-uartmflow(Uart *up, int n)
+uartmflow(Uart *dp, int n)
{
if(n){
- up->sticky[Iena] |= Imstat;
- uartwrreg(up, Iena, 0);
- up->cts = uartrdreg(up, Mstat) & Cts;
+ dp->sticky[Iena] |= Imstat;
+ uartwrreg(dp, Iena, 0);
+ dp->cts = uartrdreg(dp, Mstat) & Cts;
} else {
- up->sticky[Iena] &= ~Imstat;
- uartwrreg(up, Iena, 0);
- up->cts = 1;
+ dp->sticky[Iena] &= ~Imstat;
+ uartwrreg(dp, Iena, 0);
+ dp->cts = 1;
}
}
/*
- * default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts,
- * transmit and receive enabled, interrupts disabled.
+ * default is 9600 baud, 1 stop bit, 8 bit chars, no interrdpts,
+ * transmit and receive enabled, interrdpts disabled.
*/
void
uartsetup(void)
{
- Uart *up;
+ Uart *dp;
+ int i, j, baddr;
static int already;
if(already)
@@ 246,21 251,34 @@ uartsetup(void)
uart[1].port = 0x2F8;
setvec(Uart0vec, uartintr0);
setvec(Uart1vec, uartintr1);
-
- for(up = uart; up < &uart[2]; up++){
- memset(up->sticky, 0, sizeof(up->sticky));
-
+ Nuart = 2;
+ for(i = 0; isaconfig("serial", i, &scard[i]) && i < nelem(scard); i++) {
+ /*
+ * mem gives base port address for uarts
+ * irq is interrdpt
+ * port is the polling port
+ * size is the number of serial ports on the same polling port
+ */
+ setvec(Int0vec + scard[i].irq, uartintr2);
+ baddr = scard[i].mem;
+ for(j=0, dp = &uart[Nuart]; j < scard[i].size; baddr += 8, j++, dp++)
+ dp->port = baddr;
+ Nuart += scard[i].size;
+ }
+ Nscard = i;
+ for(dp = uart; dp < &uart[Nuart]; dp++){
+ memset(dp->sticky, 0, sizeof(dp->sticky));
/*
* set rate to 9600 baud.
* 8 bits/character.
* 1 stop bit.
- * interrupts enabled.
+ * interrdpts enabled.
*/
- uartsetbaud(up, 9600);
- up->sticky[Format] = Bits8;
- uartwrreg(up, Format, 0);
- up->sticky[Mctl] |= Inton;
- uartwrreg(up, Mctl, 0x0);
+ uartsetbaud(dp, 9600);
+ dp->sticky[Format] = Bits8;
+ uartwrreg(dp, Format, 0);
+ dp->sticky[Mctl] |= Inton;
+ uartwrreg(dp, Mctl, 0x0);
}
}
@@ 271,7 289,7 @@ uartsetup(void)
void
uartputs(IOQ *cq, char *s, int n)
{
- Uart *up = cq->ptr;
+ Uart *dp = cq->ptr;
int ch, x, multiprocessor;
int tries;
@@ 280,14 298,14 @@ uartputs(IOQ *cq, char *s, int n)
if(multiprocessor)
lock(cq);
puts(cq, s, n);
- if(up->printing == 0){
+ if(dp->printing == 0){
ch = getc(cq);
if(ch >= 0){
- up->printing = 1;
- for(tries = 0; tries<10000 && !(uartrdreg(up, Lstat)&Outready);
+ dp->printing = 1;
+ for(tries = 0; tries<10000 && !(uartrdreg(dp, Lstat)&Outready);
tries++)
;
- outb(up->port + Data, ch);
+ outb(dp->port + Data, ch);
}
}
if(multiprocessor)
@@ 296,10 314,10 @@ uartputs(IOQ *cq, char *s, int n)
}
/*
- * a uart interrupt (a damn lot of work for one character)
+ * a uart interrdpt (a damn lot of work for one character)
*/
void
-uartintr(Uart *up)
+uartintr(Uart *dp)
{
int ch;
IOQ *cq;
@@ 307,19 325,19 @@ uartintr(Uart *up)
multiprocessor = active.machs > 1;
for(;;){
- s = uartrdreg(up, Istat);
+ s = uartrdreg(dp, Istat);
switch(s){
case 6: /* receiver line status */
- l = uartrdreg(up, Lstat);
+ l = uartrdreg(dp, Lstat);
if(l & Ferror)
- up->frame++;
+ dp->frame++;
if(l & Oerror)
- up->overrun++;
+ dp->overrun++;
break;
case 4: /* received data available */
- ch = uartrdreg(up, Data) & 0xff;
- cq = up->iq;
+ ch = uartrdreg(dp, Data) & 0xff;
+ cq = dp->iq;
if(cq == 0)
break;
if(cq->putc)
@@ 329,41 347,41 @@ uartintr(Uart *up)
break;
case 2: /* transmitter empty */
- cq = up->oq;
+ cq = dp->oq;
if(cq == 0)
break;
if(multiprocessor)
lock(cq);
- if(up->cts == 0)
- up->printing = 0;
+ if(dp->cts == 0)
+ dp->printing = 0;
else {
ch = getc(cq);
if(ch < 0){
- up->printing = 0;
- wakeup(&cq->r);
+ dp->printing = 0;
+ wakedp(&cq->r);
}else
- outb(up->port + Data, ch);
+ outb(dp->port + Data, ch);
}
if(multiprocessor)
unlock(cq);
break;
case 0: /* modem status */
- ch = uartrdreg(up, Mstat);
+ ch = uartrdreg(dp, Mstat);
if(ch & Ctsc){
- up->cts = ch & Cts;
- cq = up->oq;
+ dp->cts = ch & Cts;
+ cq = dp->oq;
if(cq == 0)
break;
if(multiprocessor)
lock(cq);
- if(up->cts && up->printing == 0){
+ if(dp->cts && dp->printing == 0){
ch = getc(cq);
if(ch >= 0){
- up->printing = 1;
- outb(up->port + Data, getc(cq));
+ dp->printing = 1;
+ outb(dp->port + Data, getc(cq));
} else
- wakeup(&cq->r);
+ wakedp(&cq->r);
}
if(multiprocessor)
unlock(cq);
@@ 373,7 391,7 @@ uartintr(Uart *up)
default:
if(s&1)
return;
- print("weird modem interrupt\n");
+ print("weird modem interrdpt #%2.2ux\n", s);
break;
}
}
@@ 390,125 408,142 @@ uartintr1(Ureg *ur)
USED(ur);
uartintr(&uart[1]);
}
+void
+uartintr2(Ureg *ur)
+{
+ uchar i, j, nuart, n;
+
+ USED(ur);
+ for(nuart=2, j = 0; j < Nscard; nuart += scard[j].size, j++) {
+ n = ~inb(scard[j].port);
+ if(n == 0)
+ continue;
+ for(i = 0; n; i++){
+ if(n & 1)
+ uartintr(&uart[nuart + i]);
+ n >>= 1;
+ }
+ }
+}
void
uartclock(void)
{
- Uart *up;
+ Uart *dp;
IOQ *cq;
- for(up = uart; up < &uart[2]; up++){
- cq = up->iq;
- if(up->wq && cangetc(cq))
- wakeup(&cq->r);
+ for(dp = uart; dp < &uart[Nuart]; dp++){
+ cq = dp->iq;
+ if(dp->wq && cangetc(cq))
+ wakedp(&cq->r);
}
}
/*
- * turn on a port's interrupts. set DTR and RTS
+ * turn on a port's interrdpts. set DTR and RTS
*/
void
-uartenable(Uart *up)
+uartenable(Uart *dp)
{
/*
* turn on power to the port
*/
- if(up == &uart[Serial]){
- if(serial(1) < 0)
- print("can't turn on serial port power\n");
- } else {
+ if(dp == &uart[Modem]){
if(modem(1) < 0)
print("can't turn on modem speaker\n");
+ } else {
+ if(serial(1) < 0)
+ print("can't turn on serial port power\n");
}
/*
- * set up i/o routines
+ * set dp i/o routines
*/
- if(up->oq){
- up->oq->puts = uartputs;
- up->oq->ptr = up;
+ if(dp->oq){
+ dp->oq->puts = uartputs;
+ dp->oq->ptr = dp;
}
- if(up->iq){
- up->iq->ptr = up;
+ if(dp->iq){
+ dp->iq->ptr = dp;
}
- up->enabled = 1;
+ dp->enabled = 1;
/*
- * turn on interrupts
+ * turn on interrdpts
*/
- up->sticky[Iena] = Ircv | Ixmt | Irstat;
- uartwrreg(up, Iena, 0);
+ dp->sticky[Iena] = Ircv | Ixmt | Irstat;
+ uartwrreg(dp, Iena, 0);
/*
* turn on DTR and RTS
*/
- uartdtr(up, 1);
- uartrts(up, 1);
+ uartdtr(dp, 1);
+ uartrts(dp, 1);
/*
* assume we can send
*/
- up->cts = 1;
+ dp->cts = 1;
}
/*
* turn off the uart
*/
void
-uartdisable(Uart *up)
+uartdisable(Uart *dp)
{
/*
- * turn off interrupts
+ * turn off interrdpts
*/
- up->sticky[Iena] = 0;
- uartwrreg(up, Iena, 0);
+ dp->sticky[Iena] = 0;
+ uartwrreg(dp, Iena, 0);
/*
* revert to default settings
*/
- up->sticky[Format] = Bits8;
- uartwrreg(up, Format, 0);
+ dp->sticky[Format] = Bits8;
+ uartwrreg(dp, Format, 0);
/*
* turn off DTR and RTS
*/
- uartdtr(up, 0);
- uartrts(up, 0);
- up->enabled = 0;
+ uartdtr(dp, 0);
+ uartrts(dp, 0);
+ dp->enabled = 0;
/*
* turn off power
*/
- if(up == &uart[Serial]){
- if(serial(0) < 0)
- print("can't turn off serial power\n");
- } else {
+ if(dp == &uart[Modem]){
if(modem(0) < 0)
print("can't turn off modem speaker\n");
+ } else {
+ if(serial(0) < 0)
+ print("can't turn off serial power\n");
}
}
/*
- * set up an uart port as something other than a stream
+ * set dp an uart port as something other than a stream
*/
void
uartspecial(int port, IOQ *oq, IOQ *iq, int baud)
{
- Uart *up = &uart[port];
+ Uart *dp = &uart[port];
uartsetup();
- up->special = 1;
- up->oq = oq;
- up->iq = iq;
- uartenable(up);
+ dp->special = 1;
+ dp->oq = oq;
+ dp->iq = iq;
+ uartenable(dp);
if(baud)
- uartsetbaud(up, baud);
+ uartsetbaud(dp, baud);
if(iq){
/*
- * Stupid HACK to undo a stupid hack
+ * Stdpid HACK to undo a stdpid hack
*/
if(iq == &kbdq)
kbdq.putc = kbdcr2nl;
@@ 532,57 567,57 @@ Qinfo uartinfo =
static void
uartstopen(Queue *q, Stream *s)
{
- Uart *up;
+ Uart *dp;
char name[NAMELEN];
- up = &uart[s->id];
- up->iq->putc = 0;
- uartenable(up);
+ dp = &uart[s->id];
+ dp->iq->putc = 0;
+ uartenable(dp);
- qlock(up);
- up->wq = WR(q);
- WR(q)->ptr = up;
- RD(q)->ptr = up;
- qunlock(up);
+ qlock(dp);
+ dp->wq = WR(q);
+ WR(q)->ptr = dp;
+ RD(q)->ptr = dp;
+ qunlock(dp);
- if(up->kstarted == 0){
- up->kstarted = 1;
+ if(dp->kstarted == 0){
+ dp->kstarted = 1;
sprint(name, "uart%d", s->id);
- kproc(name, uartkproc, up);
+ kproc(name, uartkproc, dp);
}
}
static void
uartstclose(Queue *q)
{
- Uart *up = q->ptr;
+ Uart *dp = q->ptr;
- if(up->special)
+ if(dp->special)
return;
- uartdisable(up);
+ uartdisable(dp);
- qlock(up);
- kprint("uartstclose: q=0x%ux, id=%d\n", q, up-uart);
- up->wq = 0;
- up->iq->putc = 0;
+ qlock(dp);
+ kprint("uartstclose: q=0x%ux, id=%d\n", q, dp-uart);
+ dp->wq = 0;
+ dp->iq->putc = 0;
WR(q)->ptr = 0;
RD(q)->ptr = 0;
- qunlock(up);
+ qunlock(dp);
}
static void
uartoput(Queue *q, Block *bp)
{
- Uart *up = q->ptr;
+ Uart *dp = q->ptr;
IOQ *cq;
int n, m;
- if(up == 0){
+ if(dp == 0){
freeb(bp);
return;
}
- cq = up->oq;
+ cq = dp->oq;
if(waserror()){
freeb(bp);
nexterror();
@@ 594,35 629,37 @@ uartoput(Queue *q, Block *bp)
switch(*bp->rptr){
case 'B':
case 'b':
- uartsetbaud(up, n);
+ if(n <= 0)
+ error(Ebadctl);
+ uartsetbaud(dp, n);
break;
case 'D':
case 'd':
- uartdtr(up, n);
+ uartdtr(dp, n);
break;
case 'K':
case 'k':
- uartbreak(up, n);
+ uartbreak(dp, n);
break;
case 'L':
case 'l':
- uartbits(up, n);
+ uartbits(dp, n);
break;
case 'm':
case 'M':
- uartmflow(up, n);
+ uartmflow(dp, n);
break;
case 'P':
case 'p':
- uartparity(up, *(bp->rptr+1));
+ uartparity(dp, *(bp->rptr+1));
break;
case 'R':
case 'r':
- uartrts(up, n);
+ uartrts(dp, n);
break;
case 'S':
case 's':
- uartstop(up, n);
+ uartstop(dp, n);
break;
}
}else while((m = BLEN(bp)) > 0){
@@ 639,13 676,13 @@ uartoput(Queue *q, Block *bp)
}
/*
- * process to send bytes upstream for a port
+ * process to send bytes dpstream for a port
*/
static void
uartkproc(void *a)
{
- Uart *up = a;
- IOQ *cq = up->iq;
+ Uart *dp = a;
+ IOQ *cq = dp->iq;
Block *bp;
int n;
ulong frame, overrun;
@@ 661,44 698,33 @@ uartkproc(void *a)
sleep(&cq->r, cangetc, cq);
if((ints++ & 0x1f) == 0)
lights((ints>>5)&1);
- qlock(up);
- if(up->wq == 0){
+ qlock(dp);
+ if(dp->wq == 0){
cq->out = cq->in;
}else{
n = cangetc(cq);
bp = allocb(n);
bp->flags |= S_DELIM;
bp->wptr += gets(cq, bp->wptr, n);
- PUTNEXT(RD(up->wq), bp);
+ PUTNEXT(RD(dp->wq), bp);
}
- qunlock(up);
- if(up->frame != frame){
- kprint("uart%d: %d framing\n", up-uart, up->frame);
- frame = up->frame;
+ qunlock(dp);
+ if(dp->frame != frame){
+ kprint("uart%d: %d framing\n", dp-uart, dp->frame);
+ frame = dp->frame;
}
- if(up->overrun != overrun){
- kprint("uart%d: %d overruns\n", up-uart, up->overrun);
- overrun = up->overrun;
+ if(dp->overrun != overrun){
+ kprint("uart%d: %d overruns\n", dp-uart, dp->overrun);
+ overrun = dp->overrun;
}
}
}
enum{
Qdir= 0,
- Qeia0= STREAMQID(0, Sdataqid),
- Qeia0ctl= STREAMQID(0, Sctlqid),
- Qeia1= STREAMQID(1, Sdataqid),
- Qeia1ctl= STREAMQID(1, Sctlqid),
-};
-
-Dirtab uartdir[]={
- "eia0", {Qeia0}, 0, 0666,
- "eia0ctl", {Qeia0ctl}, 0, 0666,
- "eia1", {Qeia1}, 0, 0666,
- "eia1ctl", {Qeia1ctl}, 0, 0666,
};
-#define NUart (sizeof uartdir/sizeof(Dirtab))
+Dirtab uartdir[2*nelem(uart)];
/*
* allocate the queues if no one else has
@@ 706,28 732,41 @@ Dirtab uartdir[]={
void
uartreset(void)
{
- Uart *up;
+ Uart *dp;
uartsetup();
- for(up = uart; up < &uart[2]; up++){
- if(up->special)
+ for(dp = uart; dp < &uart[Nuart]; dp++){
+ if(dp->special)
continue;
- up->iq = xalloc(sizeof(IOQ));
- initq(up->iq);
- up->oq = xalloc(sizeof(IOQ));
- initq(up->oq);
+ dp->iq = xalloc(sizeof(IOQ));
+ initq(dp->iq);
+ dp->oq = xalloc(sizeof(IOQ));
+ initq(dp->oq);
}
}
void
uartinit(void)
{
+ int i;
+
+ for(i=0; i < 2*Nuart; ++i) {
+ if(i & 1 != 0) {
+ sprint(uartdir[i].name, "eia%dctl", i/2);
+ uartdir[i].qid.path = STREAMQID(i/2, Sctlqid);
+ } else {
+ sprint(uartdir[i].name, "eia%d", i/2);
+ uartdir[i].qid.path = STREAMQID(i/2, Sdataqid);
+ }
+ uartdir[i].length = 0;
+ uartdir[i].perm = 0666;
+ }
}
Chan*
-uartattach(char *upec)
+uartattach(char *dpec)
{
- return devattach('t', upec);
+ return devattach('t', dpec);
}
Chan*
@@ 739,50 778,40 @@ uartclone(Chan *c, Chan *nc)
int
uartwalk(Chan *c, char *name)
{
- return devwalk(c, name, uartdir, NUart, devgen);
+ return devwalk(c, name, uartdir, Nuart * 2, devgen);
}
void
-uartstat(Chan *c, char *dp)
+uartstat(Chan *c, char *dir)
{
- switch(c->qid.path){
- case Qeia0:
- streamstat(c, dp, uartdir[0].name, uartdir[0].perm);
- break;
- case Qeia1:
- streamstat(c, dp, uartdir[2].name, uartdir[2].perm);
- break;
- default:
- devstat(c, dp, uartdir, NUart, devgen);
- break;
- }
+ int i;
+
+ for(i=0; i < 2*Nuart; i += 2)
+ if(c->qid.path == uartdir[i].qid.path) {
+ streamstat(c, dir, uartdir[i].name, uartdir[i].perm);
+ return;
+ }
+ devstat(c, dir, uartdir, Nuart * 2, devgen);
}
Chan*
uartopen(Chan *c, int omode)
{
- Uart *up;
+ Uart *dp;
+ int i;
- switch(c->qid.path){
- case Qeia0:
- case Qeia0ctl:
- up = &uart[0];
- break;
- case Qeia1:
- case Qeia1ctl:
- up = &uart[1];
- break;
- default:
- up = 0;
- break;
- }
+ dp = 0;
+ for(i=0; i < 2*Nuart; ++i)
+ if(c->qid.path == uartdir[i].qid.path) {
+ dp = &uart[i/2];
+ break;
+ }
- if(up && up->special)
+ if(dp && dp->special)
error(Einuse);
-
if((c->qid.path & CHDIR) == 0)
streamopen(c, &uartinfo);
- return devopen(c, omode, uartdir, NUart, devgen);
+ return devopen(c, omode, uartdir, Nuart * 2, devgen);
}
void
@@ 800,15 829,15 @@ uartclose(Chan *c)
}
long
-uartstatus(Uart *up, void *buf, long n, ulong offset)
+uartstatus(Uart *dp, void *buf, long n, ulong offset)
{
uchar mstat;
uchar tstat;
char str[128];
str[0] = 0;
- tstat = up->sticky[Mctl];
- mstat = uartrdreg(up, Mstat);
+ tstat = dp->sticky[Mctl];
+ mstat = uartrdreg(dp, Mstat);
if(mstat & Cts)
strcat(str, " cts");
if(mstat & Dsr)
@@ 827,15 856,16 @@ uartstatus(Uart *up, void *buf, long n, ulong offset)
long
uartread(Chan *c, void *buf, long n, ulong offset)
{
+ int i;
+ long qpath;
+
USED(offset);
- switch(c->qid.path&~CHDIR){
- case Qdir:
- return devdirread(c, buf, n, uartdir, NUart, devgen);
- case Qeia1ctl:
- return uartstatus(&uart[1], buf, n, offset);
- case Qeia0ctl:
- return uartstatus(&uart[0], buf, n, offset);
- }
+ qpath = c->qid.path & ~CHDIR;
+ if(qpath == Qdir)
+ return devdirread(c, buf, n, uartdir, Nuart * 2, devgen);
+ for(i=1; i < 2*Nuart; i += 2)
+ if(qpath == uartdir[i].qid.path)
+ return uartstatus(&uart[i/2], buf, n, offset);
return streamread(c, buf, n);
}
@@ 854,8 884,8 @@ uartremove(Chan *c)
}
void
-uartwstat(Chan *c, char *dp)
+uartwstat(Chan *c, char *dir)
{
- USED(c, dp);
+ USED(c, dir);
error(Eperm);
}
M pc/devvga.c => pc/devvga.c +13 -8
@@ 103,7 103,7 @@ VGAmode mode13 =
static Rectangle mbb;
static Rectangle NULLMBB = {10000, 10000, -10000, -10000};
static void nopage(int), tsengpage(int), tridentpage(int), parapage(int);
-static void atipage(int);
+static void atipage(int), cirruspage(int);
static void vgaupdate(void);
/*
@@ 122,6 122,7 @@ enum
Pvga1a, /* paradise */
Trident, /* Trident 8900 */
Tseng, /* tseng labs te4000 */
+ Cirrus, /* Cirrus CLGD542X */
Generic,
};
@@ 131,6 132,7 @@ Vgacard vgachips[] =
[Pvga1a] { "pvga1a", parapage, },
[Trident] { "trident", tridentpage, },
[Tseng] { "tseng", tsengpage, },
+[Cirrus] { "cirrus", cirruspage, },
[Generic] { "generic", nopage, },
{ 0, 0, },
};
@@ 659,7 661,7 @@ atipage(int page)
static void
tridentpage(int page)
{
- srout(0x0e, (srin(0x0e)&0xf0) | page^0x02);
+ srout(0xe, (srin(0xe)&0xf0) | page^0x2);
}
static void
tsengpage(int page)
@@ 667,9 669,14 @@ tsengpage(int page)
outb(0x3cd, (page<<4)|page);
}
static void
+cirruspage(int page)
+{
+ grout(0x9, page<<4);
+}
+static void
parapage(int page)
{
- grout(9, page<<4);
+ grout(0x9, page<<4);
}
/*
@@ 918,18 925,16 @@ setcolor(ulong p, ulong r, ulong g, ulong b)
return ~0;
}
-int
-hwcursset(uchar *s, uchar *c, int ox, int oy)
+void
+hwcursset(ulong *s, ulong *c, int ox, int oy)
{
USED(s, c, ox, oy);
- return 0;
}
-int
+void
hwcursmove(int x, int y)
{
USED(x, y);
- return 0;
}
/*
M pc/dma.c => pc/dma.c +30 -10
@@ 33,7 33,7 @@ enum
*/
struct DMAxfer
{
- Page *pg; /* page used by dma */
+ Page pg; /* page used by dma */
void *va; /* virtual address destination/src */
long len; /* bytes to be transferred */
int isread;
@@ 79,6 79,27 @@ DMA dma[2] = {
};
/*
+ * DMA must be in the first 16 meg. This gets called early by main() to
+ * ensure that.
+ */
+void
+dmainit(void)
+{
+ int i, chan;
+ DMA *dp;
+ DMAxfer *xp;
+
+ for(i = 0; i < 2; i++){
+ dp = &dma[i];
+ for(chan = 0; chan < 4; chan++){
+ xp = &dp->x[chan];
+ xp->pg.pa = (ulong)xspanalloc(BY2PG, BY2PG, 0);
+ xp->pg.va = KZERO|xp->pg.pa;
+ }
+ }
+}
+
+/*
* setup a dma transfer. if the destination is not in kernel
* memory, allocate a page for the transfer.
*
@@ 101,22 122,21 @@ dmasetup(int chan, void *va, long len, int isread)
xp = &dp->x[chan];
/*
- * if this isn't kernel memory (or crossing 64k boundary),
- * allocate a page for the DMA.
+ * if this isn't kernel memory or crossing 64k boundary or above 16 meg
+ * use the allocated low memory page.
*/
- pa = ((ulong)va) & ~KZERO;
+ pa = PADDR(va);
if((((ulong)va)&0xF0000000) != KZERO
- || (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)){
- if(xp->pg == 0)
- xp->pg = newpage(1, 0, 0);
+ || (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)
+ || pa > 16*MB){
if(len > BY2PG)
len = BY2PG;
if(!isread)
- memmove((void*)(KZERO|xp->pg->pa), va, len);
+ memmove((void*)(xp->pg.va), va, len);
xp->va = va;
xp->len = len;
xp->isread = isread;
- pa = xp->pg->pa;
+ pa = xp->pg.pa;
} else
xp->len = 0;
@@ 168,6 188,6 @@ dmaend(int chan)
/*
* copy out of temporary page
*/
- memmove(xp->va, (void*)(KZERO|xp->pg->pa), xp->len);
+ memmove(xp->va, (void*)(xp->pg.va), xp->len);
xp->len = 0;
}
M pc/ether.h => pc/ether.h +7 -6
@@ 10,7 10,7 @@ typedef struct Ctlr Ctlr;
* Hardware interface.
*/
struct Card {
- char id[NAMELEN]; /* type of card */
+ ISAConf;
int (*reset)(Ctlr*);
void (*init)(Ctlr*);
@@ 26,13 26,8 @@ struct Card {
void (*watch)(Ctlr*);
void (*overflow)(Ctlr*);
- ulong io; /* card I/O base address */
- uchar irq; /* interrupt level */
uchar bit16; /* true if a 16 bit interface */
-
uchar ram; /* true if card has shared memory */
- ulong ramstart; /* card shared memory address start */
- ulong ramstop; /* card shared memory address end */
ulong dp8390; /* I/O address of 8390 (if any) */
ulong data; /* I/O data port if no shared memory */
@@ 85,6 80,8 @@ enum {
*/
struct Ctlr {
QLock;
+ int ctlrno;
+ Ctlr *next;
Card card; /* hardware info */
int present;
@@ 140,6 137,7 @@ struct Ctlr {
extern void dp8390reset(Ctlr*);
extern void dp8390attach(Ctlr*);
extern void dp8390mode(Ctlr*, int);
+extern void dp8390getea(Ctlr*);
extern void dp8390setea(Ctlr*);
extern void *dp8390read(Ctlr*, void*, ulong, ulong);
extern void *dp8390write(Ctlr*, ulong, void*, ulong);
@@ 166,3 164,6 @@ extern void dp8390outb(ulong, uchar);
enum {
Dp8390BufSz = 256, /* hardware ring buffer size */
};
+
+
+extern void addethercard(char*, int (*)(Ctlr*));
M pc/ether2000.c => pc/ether2000.c +59 -62
@@ 25,44 25,68 @@ enum {
Reset = 0x18, /* offset from I/O base of reset port */
};
-static int
-reset(Ctlr *ctlr)
+int
+ne2000reset(Ctlr *ctlr)
{
ushort buf[16];
int i;
/*
- * We look for boards.
- * We look for boards to make us barf.
+ * Set up the software configuration.
+ * Use defaults for port, irq, mem and size
+ * if not specified.
*/
- for(ctlr->card.io = 0x300; ctlr->card.io < 0x380; ctlr->card.io += 0x20){
- /*
- * Reset the board. This is done by doing a read
- * followed by a write to the Reset address.
- */
- buf[0] = inb(ctlr->card.io+Reset);
- delay(2);
- outb(ctlr->card.io+Reset, buf[0]);
+ if(ctlr->card.port == 0)
+ ctlr->card.port = 0x300;
+ if(ctlr->card.irq == 0)
+ ctlr->card.irq = 2;
+ if(ctlr->card.mem == 0)
+ ctlr->card.mem = 0x4000;
+ if(ctlr->card.size == 0)
+ ctlr->card.size = 16*1024;
- /*
- * Init the (possible) chip, then use the (possible)
- * chip to read the (possible) PROM for ethernet address
- * and a marker byte.
- * We could just look at the DP8390 command register after
- * initialisation has been tried, but that wouldn't be
- * enough, there are other ethernet boards which could
- * match.
- */
- ctlr->card.dp8390 = ctlr->card.io;
- ctlr->card.data = ctlr->card.io+Data;
- dp8390reset(ctlr);
- memset(buf, 0, sizeof(buf));
- dp8390read(ctlr, buf, 0, sizeof(buf));
- if((buf[0x0E] & 0xFF) == 0x57 && (buf[0x0F] & 0xFF) == 0x57)
- break;
- }
- if(ctlr->card.io >= 0x380)
+ ctlr->card.reset = ne2000reset;
+ ctlr->card.attach = dp8390attach;
+ ctlr->card.mode = dp8390mode;
+ ctlr->card.read = dp8390read;
+ ctlr->card.write = dp8390write;
+ ctlr->card.receive = dp8390receive;
+ ctlr->card.transmit = dp8390transmit;
+ ctlr->card.intr = dp8390intr;
+ ctlr->card.watch = dp8390watch;
+ ctlr->card.overflow = dp8390overflow;
+
+ ctlr->card.bit16 = 1;
+ ctlr->card.dp8390 = ctlr->card.port;
+ ctlr->card.data = ctlr->card.port+Data;
+
+ ctlr->card.tstart = HOWMANY(ctlr->card.mem, Dp8390BufSz);
+ ctlr->card.pstart = ctlr->card.tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
+ ctlr->card.pstop = ctlr->card.tstart + HOWMANY(ctlr->card.size, Dp8390BufSz);
+
+ /*
+ * Reset the board. This is done by doing a read
+ * followed by a write to the Reset address.
+ */
+ buf[0] = inb(ctlr->card.port+Reset);
+ delay(2);
+ outb(ctlr->card.port+Reset, buf[0]);
+
+ /*
+ * Init the (possible) chip, then use the (possible)
+ * chip to read the (possible) PROM for ethernet address
+ * and a marker byte.
+ * We could just look at the DP8390 command register after
+ * initialisation has been tried, but that wouldn't be
+ * enough, there are other ethernet boards which could
+ * match.
+ */
+ dp8390reset(ctlr);
+ memset(buf, 0, sizeof(buf));
+ dp8390read(ctlr, buf, 0, sizeof(buf));
+ if((buf[0x0E] & 0xFF) != 0x57 || (buf[0x0F] & 0xFF) != 0x57)
return -1;
+
/*
* Stupid machine. We asked for shorts, we got shorts,
* although the PROM is a byte array.
@@ 75,35 99,8 @@ reset(Ctlr *ctlr)
return 0;
}
-Card ether2000 = {
- "NE2000", /* ident */
-
- reset, /* reset */
- 0, /* init */
- dp8390attach, /* attach */
- dp8390mode, /* mode */
-
- dp8390read, /* read */
- dp8390write, /* write */
-
- dp8390receive, /* receive */
- dp8390transmit, /* transmit */
- dp8390intr, /* interrupt */
- dp8390watch, /* watch */
- dp8390overflow, /* overflow */
-
- 0x300, /* addr */
- 2, /* irq */
- 1, /* bit16 */
-
- 0, /* ram */
- 0x4000, /* ramstart */
- 0x4000+16*1024, /* ramstop */
-
- 0x300, /* dp8390 */
- 0x300+Data, /* data */
- 0, /* software bndry */
- 0x4000/Dp8390BufSz, /* tstart */
- 0x4600/Dp8390BufSz, /* pstart */
- 0x8000/Dp8390BufSz, /* pstop */
-};
+void
+ether2000link(void)
+{
+ addethercard("NE2000", ne2000reset);
+}
M pc/ether503.c => pc/ether503.c +6 -0
@@ 338,3 338,9 @@ Card ether503 = {
(RamOffset+0x600)/Dp8390BufSz, /* pstart */
(RamOffset+8*1024)/Dp8390BufSz, /* pstop */
};
+
+void
+ether503link(void)
+{
+ addethercard("3C503", ccc503reset);
+}
M pc/ether509.c => pc/ether509.c +194 -180
@@ 84,145 84,14 @@ enum {
RxReceiving = 0x8000, /* RX Receiving */
};
-#define COMMAND(ctlr, cmd, a) outs(ctlr->card.io+Command, ((cmd)<<11)|(a))
-
-/*
- * Write two 0 bytes to identify the IDport and then reset the
- * ID sequence. Then send the ID sequence to the card to get
- * the card into command state.
- */
-static void
-idseq(void)
-{
- int i;
- uchar al;
-
- outb(IDport, 0);
- outb(IDport, 0);
- for(al = 0xFF, i = 0; i < 255; i++){
- outb(IDport, al);
- if(al & 0x80){
- al <<= 1;
- al ^= 0xCF;
- }
- else
- al <<= 1;
- }
-}
-
-/*
- * Get configuration parameters.
- */
-static int
-reset(Ctlr *ctlr)
-{
- int i, ea;
- ushort x, acr;
-
- /*
- * Do the little configuration dance. We only look
- * at the first card that responds, if we ever have more
- * than one we'll need to modify this sequence.
- *
- * 2. get to command state, reset, then return to command state
- */
- idseq();
- outb(IDport, 0xC1);
- delay(2);
- idseq();
-
- /*
- * 3. Read the Product ID from the EEPROM.
- * This is done by writing the IDPort with 0x83 (0x80
- * is the 'read EEPROM command, 0x03 is the offset of
- * the Product ID field in the EEPROM).
- * The data comes back 1 bit at a time.
- * We seem to need a delay here between reading the bits.
- *
- * If the ID doesn't match the 3C509 ID code, the adapter
- * probably isn't there, so barf.
- */
- outb(IDport, 0x83);
- for(x = 0, i = 0; i < 16; i++){
- delay(5);
- x <<= 1;
- x |= inb(IDport) & 0x01;
- }
- if((x & 0xF0FF) != 0x9050)
- return -1;
-
- /*
- * 3. Read the Address Configuration from the EEPROM.
- * The Address Configuration field is at offset 0x08 in the EEPROM).
- * 6. Activate the adapter by writing the Activate command
- * (0xFF).
- */
- outb(IDport, 0x88);
- for(acr = 0, i = 0; i < 16; i++){
- delay(20);
- acr <<= 1;
- acr |= inb(IDport) & 0x01;
- }
- outb(IDport, 0xFF);
-
- /*
- * 8. Now we can talk to the adapter's I/O base addresses.
- * We get the I/O base address from the acr just read.
- *
- * Enable the adapter.
- */
- ctlr->card.io = (acr & 0x1F)*0x10 + 0x200;
- outb(ctlr->card.io+ConfigControl, 0x01);
-
- /*
- * Read the IRQ from the Resource Configuration Register
- * and the ethernet address from the EEPROM.
- * The EEPROM command is 8bits, the lower 6 bits being
- * the address offset.
- */
- ctlr->card.irq = (ins(ctlr->card.io+ResourceConfig)>>12) & 0x0F;
- for(ea = 0, i = 0; i < 3; i++, ea += 2){
- while(ins(ctlr->card.io+EEPROMcmd) & 0x8000)
- ;
- outs(ctlr->card.io+EEPROMcmd, (2<<6)|i);
- while(ins(ctlr->card.io+EEPROMcmd) & 0x8000)
- ;
- x = ins(ctlr->card.io+EEPROMdata);
- ctlr->ea[ea] = (x>>8) & 0xFF;
- ctlr->ea[ea+1] = x & 0xFF;
- }
-
- /*
- * Finished with window 0. Now set the ethernet address
- * in window 2.
- * Commands have the format 'CCCCCAAAAAAAAAAA' where C
- * is a bit in the command and A is a bit in the argument.
- */
- COMMAND(ctlr, SelectWindow, 2);
- for(i = 0; i < 6; i++)
- outb(ctlr->card.io+i, ctlr->ea[i]);
-
- /*
- * Finished with window 2.
- * Set window 1 for normal operation.
- */
- COMMAND(ctlr, SelectWindow, 1);
-
- /*
- * If we have a 10BASE2 transceiver, start the DC-DC
- * converter. Wait > 800 microseconds.
- */
- if(((acr>>14) & 0x03) == 0x03){
- COMMAND(ctlr, StartCoax, 0);
- delay(1);
- }
-
- return 0;
-}
+#define COMMAND(port, cmd, a) outs(port+Command, ((cmd)<<11)|(a))
static void
attach(Ctlr *ctlr)
{
+ ulong port;
+
+ port = ctlr->card.port;
/*
* Set the receiver packet filter for our own and
* and broadcast addresses, set the interrupt masks
@@ 231,20 100,23 @@ attach(Ctlr *ctlr)
* is the receiver interrupt. If the transmit FIFO fills up,
* we will also see TxAvailable interrupts.
*/
- COMMAND(ctlr, SetRxFilter, Broadcast|MyEtherAddr);
- COMMAND(ctlr, SetReadZeroMask, AllIntr|Latch);
- COMMAND(ctlr, SetIntrMask, AllIntr|Latch);
- COMMAND(ctlr, RxEnable, 0);
- COMMAND(ctlr, TxEnable, 0);
+ COMMAND(port, SetRxFilter, Broadcast|MyEtherAddr);
+ COMMAND(port, SetReadZeroMask, AllIntr|Latch);
+ COMMAND(port, SetIntrMask, AllIntr|Latch);
+ COMMAND(port, RxEnable, 0);
+ COMMAND(port, TxEnable, 0);
}
static void
mode(Ctlr *ctlr, int on)
{
+ ulong port;
+
+ port = ctlr->card.port;
if(on)
- COMMAND(ctlr, SetRxFilter, Promiscuous|Broadcast|MyEtherAddr);
+ COMMAND(port, SetRxFilter, Promiscuous|Broadcast|MyEtherAddr);
else
- COMMAND(ctlr, SetRxFilter, Broadcast|MyEtherAddr);
+ COMMAND(port, SetRxFilter, Broadcast|MyEtherAddr);
}
static void
@@ 253,8 125,10 @@ receive(Ctlr *ctlr)
ushort status;
RingBuf *rb;
int len;
+ ulong port;
- while(((status = ins(ctlr->card.io+RxStatus)) & RxEmpty) == 0){
+ port = ctlr->card.port;
+ while(((status = ins(port+RxStatus)) & RxEmpty) == 0){
/*
* If we had an error, log it and continue
* without updating the ring.
@@ 295,9 169,9 @@ receive(Ctlr *ctlr)
* doubleword. We can pick them out 16-bits
* at a time (can try 32-bits at a time
* later).
- insl(ctlr->card.io+Fifo, rb->pkt, HOWMANY(len, 4));
+ insl(port+Fifo, rb->pkt, HOWMANY(len, 4));
*/
- inss(ctlr->card.io+Fifo, rb->pkt, HOWMANY(len, 2));
+ inss(port+Fifo, rb->pkt, HOWMANY(len, 2));
/*
* Update the ring.
@@ 311,8 185,8 @@ receive(Ctlr *ctlr)
* Discard the packet as we're done with it.
* Wait for discard to complete.
*/
- COMMAND(ctlr, RxDiscard, 0);
- while(ins(ctlr->card.io+Status) & CmdInProgress)
+ COMMAND(port, RxDiscard, 0);
+ while(ins(port+Status) & CmdInProgress)
;
}
}
@@ 322,7 196,9 @@ transmit(Ctlr *ctlr)
{
RingBuf *tb;
ushort len;
+ ulong port;
+ port = ctlr->card.port;
for(tb = &ctlr->tb[ctlr->ti]; tb->owner == Interface; tb = &ctlr->tb[ctlr->ti]){
/*
* If there's no room in the FIFO for this packet,
@@ 331,8 207,8 @@ transmit(Ctlr *ctlr)
* we need 4 bytes for the preamble.
*/
len = ROUNDUP(tb->len, 4);
- if(len+4 > ins(ctlr->card.io+TxFreeBytes)){
- COMMAND(ctlr, SetTxAvailable, len);
+ if(len+4 > ins(port+TxFreeBytes)){
+ COMMAND(port, SetTxAvailable, len);
break;
}
@@ 340,9 216,9 @@ transmit(Ctlr *ctlr)
* There's room, copy the packet to the FIFO and free
* the buffer back to the host.
*/
- outs(ctlr->card.io+Fifo, tb->len);
- outs(ctlr->card.io+Fifo, 0);
- outss(ctlr->card.io+Fifo, tb->pkt, len/2);
+ outs(port+Fifo, tb->len);
+ outs(port+Fifo, 0);
+ outss(port+Fifo, tb->pkt, len/2);
tb->owner = Host;
ctlr->ti = NEXT(ctlr->ti, ctlr->ntb);
}
@@ 352,10 228,12 @@ static ushort
getdiag(Ctlr *ctlr)
{
ushort bytes;
+ ulong port;
- COMMAND(ctlr, SelectWindow, 4);
- bytes = ins(ctlr->card.io+FIFOdiag);
- COMMAND(ctlr, SelectWindow, 1);
+ port = ctlr->card.port;
+ COMMAND(port, SelectWindow, 4);
+ bytes = ins(port+FIFOdiag);
+ COMMAND(port, SelectWindow, 1);
return bytes & 0xFFFF;
}
@@ 364,8 242,10 @@ interrupt(Ctlr *ctlr)
{
ushort status, diag;
uchar txstatus, x;
+ ulong port;
- status = ins(ctlr->card.io+Status);
+ port = ctlr->card.port;
+ status = ins(port+Status);
if(status & Failure){
/*
@@ 379,12 259,12 @@ interrupt(Ctlr *ctlr)
print("ether509: status #%ux, diag #%ux\n", status, diag);
if(diag & TxOverrun){
- COMMAND(ctlr, TxReset, 0);
- COMMAND(ctlr, TxEnable, 0);
+ COMMAND(port, TxReset, 0);
+ COMMAND(port, TxEnable, 0);
}
if(diag & RxUnderrun){
- COMMAND(ctlr, RxReset, 0);
+ COMMAND(port, RxReset, 0);
attach(ctlr);
}
@@ 409,14 289,14 @@ interrupt(Ctlr *ctlr)
*/
txstatus = 0;
do{
- if(x = inb(ctlr->card.io+TxStatus))
- outb(ctlr->card.io+TxStatus, 0);
+ if(x = inb(port+TxStatus))
+ outb(port+TxStatus, 0);
txstatus |= x;
- }while(ins(ctlr->card.io+Status) & TxComplete);
+ }while(ins(port+Status) & TxComplete);
if(txstatus & (TxJabber|TxUnderrun))
- COMMAND(ctlr, TxReset, 0);
- COMMAND(ctlr, TxEnable, 0);
+ COMMAND(port, TxReset, 0);
+ COMMAND(port, TxEnable, 0);
ctlr->oerrs++;
}
@@ 425,7 305,7 @@ interrupt(Ctlr *ctlr)
* Reset the Tx FIFO threshold.
*/
if(status & TxAvailable)
- COMMAND(ctlr, AckIntr, TxAvailable);
+ COMMAND(port, AckIntr, TxAvailable);
transmit(ctlr);
wakeup(&ctlr->tr);
status &= ~(TxAvailable|TxComplete);
@@ 439,23 319,157 @@ interrupt(Ctlr *ctlr)
if(status & AllIntr)
panic("ether509 interrupt: #%lux, #%ux\n", status, getdiag(ctlr));
- COMMAND(ctlr, AckIntr, Latch);
+ COMMAND(port, AckIntr, Latch);
}
-Card ether509 = {
- "3Com509", /* ident */
+/*
+ * Write two 0 bytes to identify the IDport and then reset the
+ * ID sequence. Then send the ID sequence to the card to get
+ * the card into command state.
+ */
+static void
+idseq(void)
+{
+ int i;
+ uchar al;
- reset, /* reset */
- 0, /* init */
- attach, /* attach */
- mode, /* mode */
+ outb(IDport, 0);
+ outb(IDport, 0);
+ for(al = 0xFF, i = 0; i < 255; i++){
+ outb(IDport, al);
+ if(al & 0x80){
+ al <<= 1;
+ al ^= 0xCF;
+ }
+ else
+ al <<= 1;
+ }
+}
- 0, /* read */
- 0, /* write */
+/*
+ * Get configuration parameters.
+ */
+int
+ccc509reset(Ctlr *ctlr)
+{
+ int i, ea;
+ ushort x, acr;
+ ulong port;
- 0, /* receive */
- transmit, /* transmit */
- interrupt, /* interrupt */
- 0, /* watch */
- 0, /* overflow */
-};
+ /*
+ * Do the little configuration dance. We only look
+ * at the first card that responds, if we ever have more
+ * than one we'll need to modify this sequence.
+ *
+ * 2. get to command state, reset, then return to command state
+ */
+ idseq();
+ outb(IDport, 0xC1);
+ delay(2);
+ idseq();
+
+ /*
+ * 3. Read the Product ID from the EEPROM.
+ * This is done by writing the IDPort with 0x83 (0x80
+ * is the 'read EEPROM command, 0x03 is the offset of
+ * the Product ID field in the EEPROM).
+ * The data comes back 1 bit at a time.
+ * We seem to need a delay here between reading the bits.
+ *
+ * If the ID doesn't match the 3C509 ID code, the adapter
+ * probably isn't there, so barf.
+ */
+ outb(IDport, 0x83);
+ for(x = 0, i = 0; i < 16; i++){
+ delay(5);
+ x <<= 1;
+ x |= inb(IDport) & 0x01;
+ }
+ if((x & 0xF0FF) != 0x9050)
+ return -1;
+
+ /*
+ * 3. Read the Address Configuration from the EEPROM.
+ * The Address Configuration field is at offset 0x08 in the EEPROM).
+ * 6. Activate the adapter by writing the Activate command
+ * (0xFF).
+ */
+ outb(IDport, 0x88);
+ for(acr = 0, i = 0; i < 16; i++){
+ delay(20);
+ acr <<= 1;
+ acr |= inb(IDport) & 0x01;
+ }
+ outb(IDport, 0xFF);
+
+ /*
+ * 8. Now we can talk to the adapter's I/O base addresses.
+ * We get the I/O base address from the acr just read.
+ *
+ * Enable the adapter.
+ */
+ ctlr->card.port = (acr & 0x1F)*0x10 + 0x200;
+ port = ctlr->card.port;
+ outb(port+ConfigControl, 0x01);
+
+ /*
+ * Read the IRQ from the Resource Configuration Register
+ * and the ethernet address from the EEPROM.
+ * The EEPROM command is 8bits, the lower 6 bits being
+ * the address offset.
+ */
+ ctlr->card.irq = (ins(port+ResourceConfig)>>12) & 0x0F;
+ for(ea = 0, i = 0; i < 3; i++, ea += 2){
+ while(ins(port+EEPROMcmd) & 0x8000)
+ ;
+ outs(port+EEPROMcmd, (2<<6)|i);
+ while(ins(port+EEPROMcmd) & 0x8000)
+ ;
+ x = ins(port+EEPROMdata);
+ ctlr->ea[ea] = (x>>8) & 0xFF;
+ ctlr->ea[ea+1] = x & 0xFF;
+ }
+
+ /*
+ * Finished with window 0. Now set the ethernet address
+ * in window 2.
+ * Commands have the format 'CCCCCAAAAAAAAAAA' where C
+ * is a bit in the command and A is a bit in the argument.
+ */
+ COMMAND(port, SelectWindow, 2);
+ for(i = 0; i < 6; i++)
+ outb(port+i, ctlr->ea[i]);
+
+ /*
+ * Finished with window 2.
+ * Set window 1 for normal operation.
+ */
+ COMMAND(port, SelectWindow, 1);
+
+ /*
+ * If we have a 10BASE2 transceiver, start the DC-DC
+ * converter. Wait > 800 microseconds.
+ */
+ if(((acr>>14) & 0x03) == 0x03){
+ COMMAND(port, StartCoax, 0);
+ delay(1);
+ }
+
+ /*
+ * Set up the software configuration.
+ */
+ ctlr->card.reset = ccc509reset;
+ ctlr->card.attach = attach;
+ ctlr->card.mode = mode;
+ ctlr->card.transmit = transmit;
+ ctlr->card.intr = interrupt;
+ ctlr->card.bit16 = 1;
+
+ return 0;
+}
+
+void
+ether509link(void)
+{
+ addethercard("3C509", ccc509reset);
+}
M pc/ether8003.c => pc/ether8003.c +105 -109
@@ 57,37 57,105 @@ static int intrmap[] = {
9, 3, 5, 7, 10, 11, 15, 4,
};
+static void*
+read(Ctlr *ctlr, void *to, ulong from, ulong len)
+{
+ /*
+ * In this case, 'from' is an index into the shared memory.
+ */
+ memmove(to, (void*)(ctlr->card.mem+from), len);
+ return to;
+}
+
+static void*
+write(Ctlr *ctlr, ulong to, void *from, ulong len)
+{
+ /*
+ * In this case, 'to' is an index into the shared memory.
+ */
+ memmove((void*)(ctlr->card.mem+to), from, len);
+ return (void*)to;
+}
+
+static void
+watch(Ctlr *ctlr)
+{
+ uchar msr;
+ int s;
+
+ s = splhi();
+ msr = inb(ctlr->card.port+Msr);
+ /*
+ * If the card has reset itself,
+ * start again.
+ */
+ if((msr & Menb) == 0){
+ delay(100);
+
+ dp8390reset(ctlr);
+ etherinit();
+
+ wakeup(&ctlr->tr);
+ wakeup(&ctlr->rr);
+ }
+ splx(s);
+}
+
/*
* Get configuration parameters, enable memory.
* There are opportunities here for buckets of code.
* We'll try to resist.
*/
-static int
-reset(Ctlr *ctlr)
+int
+wd8003reset(Ctlr *ctlr)
{
int i;
uchar ic[8], sum;
+ ulong wd8003;
/*
+ * Set up the software configuration.
+ * Use defaults for port, irq, mem and size if not specified.
+ * Defaults are set for the dumb 8003E which can't be
+ * autoconfigured.
+ */
+ if(ctlr->card.port == 0)
+ ctlr->card.port = 0x280;
+ if(ctlr->card.irq == 0)
+ ctlr->card.irq = 3;
+ if(ctlr->card.mem == 0)
+ ctlr->card.mem = 0xD0000;
+ if(ctlr->card.size == 0)
+ ctlr->card.size = 8*1024;
+
+ ctlr->card.reset = wd8003reset;
+ ctlr->card.attach = dp8390attach;
+ ctlr->card.mode = dp8390mode;
+ ctlr->card.read = read;
+ ctlr->card.write = write;
+ ctlr->card.receive = dp8390receive;
+ ctlr->card.transmit = dp8390transmit;
+ ctlr->card.intr = dp8390intr;
+ ctlr->card.watch = watch;
+ ctlr->card.ram = 1;
+
+ wd8003 = ctlr->card.port;
+ /*
* Look for the interface. We read the LAN address ROM
* and validate the checksum - the sum of all 8 bytes
* should be 0xFF.
* While we're at it, get the (possible) interface chip
* registers, we'll use them to check for aliasing later.
*/
- for(ctlr->card.io = 0x200; ctlr->card.io < 0x400; ctlr->card.io += 0x20){
- sum = 0;
- for(i = 0; i < sizeof(ctlr->ea); i++){
- ctlr->ea[i] = inb(ctlr->card.io+Lar+i);
- sum += ctlr->ea[i];
- ic[i] = inb(ctlr->card.io+i);
- }
- sum += inb(ctlr->card.io+Id);
- sum += inb(ctlr->card.io+Cksum);
- if(sum == 0xFF)
- break;
+ sum = 0;
+ for(i = 0; i < sizeof(ctlr->ea); i++){
+ ctlr->ea[i] = inb(wd8003+Lar+i);
+ sum += ctlr->ea[i];
+ ic[i] = inb(wd8003+i);
}
- if(ctlr->card.io >= 0x400)
+ sum += inb(wd8003+Id);
+ sum += inb(wd8003+Cksum);
+ if(sum != 0xFF)
return -1;
/*
@@ 101,7 169,7 @@ reset(Ctlr *ctlr)
*/
if(memcmp(&ctlr->ea[1], &ic[1], 5) == 0){
memset(ic, 0, sizeof(ic));
- ic[Msr] = (((ulong)ctlr->card.ramstart)>>13) & 0x3F;
+ ic[Msr] = (((ulong)ctlr->card.mem)>>13) & 0x3F;
ctlr->card.watch = 0;
}
else{
@@ 110,13 178,12 @@ reset(Ctlr *ctlr)
* the 83C584 interface chip, but has 2 real registers, write Gp2 and if
* it reads back the same, it's not an 8013EBT.
*/
- outb(ctlr->card.io+Gp2, 0xAA);
- inb(ctlr->card.io+Msr); /* wiggle bus */
- if(inb(ctlr->card.io+Gp2) != 0xAA){
+ outb(wd8003+Gp2, 0xAA);
+ inb(wd8003+Msr); /* wiggle bus */
+ if(inb(wd8003+Gp2) != 0xAA){
memset(ic, 0, sizeof(ic));
- ic[Msr] = (((ulong)ctlr->card.ramstart)>>13) & 0x3F;
+ ic[Msr] = (((ulong)ctlr->card.mem)>>13) & 0x3F;
ctlr->card.watch = 0;
- ctlr->card.irq = 2; /* special */
}
else
ctlr->card.irq = intrmap[((ic[Irr]>>5) & 0x3)|(ic[Icr] & 0x4)];
@@ 126,46 193,43 @@ reset(Ctlr *ctlr)
* If Bit16 is read/write, then we have an 8-bit card.
* If Bit16 is set, we're in a 16-bit slot.
*/
- outb(ctlr->card.io+Icr, ic[Icr]^Bit16);
- inb(ctlr->card.io+Msr); /* wiggle bus */
- if((inb(ctlr->card.io+Icr) & Bit16) == (ic[Icr] & Bit16)){
+ outb(wd8003+Icr, ic[Icr]^Bit16);
+ inb(wd8003+Msr); /* wiggle bus */
+ if((inb(wd8003+Icr) & Bit16) == (ic[Icr] & Bit16)){
ctlr->card.bit16 = 1;
ic[Icr] &= ~Bit16;
}
- outb(ctlr->card.io+Icr, ic[Icr]);
+ outb(wd8003+Icr, ic[Icr]);
- if(ctlr->card.bit16 && (inb(ctlr->card.io+Icr) & Bit16) == 0)
+ if(ctlr->card.bit16 && (inb(wd8003+Icr) & Bit16) == 0)
ctlr->card.bit16 = 0;
}
- ctlr->card.ramstart = KZERO|((ic[Msr] & 0x3F)<<13);
+ ctlr->card.mem = KZERO|((ic[Msr] & 0x3F)<<13);
if(ctlr->card.bit16)
- ctlr->card.ramstart |= (ic[Laar] & 0x1F)<<19;
+ ctlr->card.mem |= (ic[Laar] & 0x1F)<<19;
else
- ctlr->card.ramstart |= 0x80000;
+ ctlr->card.mem |= 0x80000;
if(ic[Icr] & (1<<3))
- ctlr->card.ramstop = 32*1024;
- else
- ctlr->card.ramstop = 8*1024;
+ ctlr->card.size = 32*1024;
if(ctlr->card.bit16)
- ctlr->card.ramstop <<= 1;
- ctlr->card.ramstop += ctlr->card.ramstart;
+ ctlr->card.size <<= 1;
/*
* Set the DP8390 ring addresses.
*/
- ctlr->card.dp8390 = ctlr->card.io+0x10;
- ctlr->card.pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
- ctlr->card.pstop = HOWMANY(ctlr->card.ramstop-ctlr->card.ramstart, Dp8390BufSz);
+ ctlr->card.dp8390 = wd8003+0x10;
ctlr->card.tstart = 0;
+ ctlr->card.pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
+ ctlr->card.pstop = HOWMANY(ctlr->card.size, Dp8390BufSz);
/*
* Enable interface RAM, set interface width.
*/
- outb(ctlr->card.io+Msr, ic[Msr]|Menb);
+ outb(wd8003+Msr, ic[Msr]|Menb);
if(ctlr->card.bit16)
- outb(ctlr->card.io+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
+ outb(wd8003+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
/*
* Finally, init the 8390 and set the
@@ 177,76 241,8 @@ reset(Ctlr *ctlr)
return 0;
}
-static void*
-read(Ctlr *ctlr, void *to, ulong from, ulong len)
-{
- /*
- * In this case, 'from' is an index into the shared memory.
- */
- memmove(to, (void*)(ctlr->card.ramstart+from), len);
- return to;
-}
-
-static void*
-write(Ctlr *ctlr, ulong to, void *from, ulong len)
-{
- /*
- * In this case, 'to' is an index into the shared memory.
- */
- memmove((void*)(ctlr->card.ramstart+to), from, len);
- return (void*)to;
-}
-
-static void
-watch(Ctlr *ctlr)
+void
+ether8003link(void)
{
- uchar msr;
- int s;
-
- s = splhi();
- msr = inb(ctlr->card.io+Msr);
- /*
- * If the card has reset itself,
- * start again.
- */
- if((msr & Menb) == 0){
- delay(100);
-
- dp8390reset(ctlr);
- etherinit();
-
- wakeup(&ctlr->tr);
- wakeup(&ctlr->rr);
- }
- splx(s);
+ addethercard("WD8003", wd8003reset);
}
-
-/*
- * Defaults are set for the dumb 8003E
- * which can't be autoconfigured.
- */
-Card ether8003 = {
- "WD8003", /* ident */
-
- reset, /* reset */
- 0, /* init */
- dp8390attach, /* attach */
- dp8390mode, /* mode */
-
- read, /* read */
- write, /* write */
-
- dp8390receive, /* receive */
- dp8390transmit, /* transmit */
- dp8390intr, /* interrupt */
- watch, /* watch */
- 0, /* overflow */
-
- 0x280, /* io */
- 3, /* irq */
- 0, /* bit16 */
-
- 1, /* ram */
- 0xD0000, /* ramstart */
- 0xD0000+8*1024, /* ramstop */
-};
M pc/ether8390.c => pc/ether8390.c +133 -91
@@ 149,8 149,10 @@ typedef struct {
static void
dp8390disable(Ctlr *ctlr)
{
+ ulong dp8390;
int timo;
+ dp8390 = ctlr->card.dp8390;
/*
* Stop the chip. Set the Stp bit and wait for the chip
* to finish whatever was on its tiny mind before it sets
@@ 159,23 161,26 @@ dp8390disable(Ctlr *ctlr)
* chip there if this is called when probing for a device
* at boot.
*/
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp);
- dp8390outb(ctlr->card.dp8390+Rbcr0, 0);
- dp8390outb(ctlr->card.dp8390+Rbcr1, 0);
- for(timo = 10000; (dp8390inb(ctlr->card.dp8390+Isr) & Rst) == 0 && timo; timo--)
+ dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
+ dp8390outb(dp8390+Rbcr0, 0);
+ dp8390outb(dp8390+Rbcr1, 0);
+ for(timo = 10000; (dp8390inb(dp8390+Isr) & Rst) == 0 && timo; timo--)
;
}
static void
dp8390ring(Ctlr *ctlr)
{
- dp8390outb(ctlr->card.dp8390+Pstart, ctlr->card.pstart);
- dp8390outb(ctlr->card.dp8390+Pstop, ctlr->card.pstop);
- dp8390outb(ctlr->card.dp8390+Bnry, ctlr->card.pstop-1);
+ ulong dp8390;
- dp8390outb(ctlr->card.dp8390+Cr, Page1|RDMAabort|Stp);
- dp8390outb(ctlr->card.dp8390+Curr, ctlr->card.pstart);
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp);
+ dp8390 = ctlr->card.dp8390;
+ dp8390outb(dp8390+Pstart, ctlr->card.pstart);
+ dp8390outb(dp8390+Pstop, ctlr->card.pstop);
+ dp8390outb(dp8390+Bnry, ctlr->card.pstop-1);
+
+ dp8390outb(dp8390+Cr, Page1|RDMAabort|Stp);
+ dp8390outb(dp8390+Curr, ctlr->card.pstart);
+ dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
ctlr->card.nxtpkt = ctlr->card.pstart;
}
@@ 183,6 188,9 @@ dp8390ring(Ctlr *ctlr)
void
dp8390reset(Ctlr *ctlr)
{
+ ulong dp8390;
+
+ dp8390 = ctlr->card.dp8390;
/*
* This is the initialisation procedure described
* as 'mandatory' in the datasheet, with references
@@ 190,15 198,15 @@ dp8390reset(Ctlr *ctlr)
*/
dp8390disable(ctlr);
if(ctlr->card.bit16)
- dp8390outb(ctlr->card.dp8390+Dcr, Ft4|Ls|Wts);
+ dp8390outb(dp8390+Dcr, Ft4|Ls|Wts);
else
- dp8390outb(ctlr->card.dp8390+Dcr, Ft4|Ls);
+ dp8390outb(dp8390+Dcr, Ft4|Ls);
- dp8390outb(ctlr->card.dp8390+Rbcr0, 0);
- dp8390outb(ctlr->card.dp8390+Rbcr1, 0);
+ dp8390outb(dp8390+Rbcr0, 0);
+ dp8390outb(dp8390+Rbcr1, 0);
- dp8390outb(ctlr->card.dp8390+Tcr, 0);
- dp8390outb(ctlr->card.dp8390+Rcr, Mon);
+ dp8390outb(dp8390+Tcr, 0);
+ dp8390outb(dp8390+Rcr, Mon);
/*
* Init the ring hardware and software ring pointers.
@@ 206,16 214,16 @@ dp8390reset(Ctlr *ctlr)
* it yet.
*/
dp8390ring(ctlr);
- dp8390outb(ctlr->card.dp8390+Tpsr, ctlr->card.tstart);
+ dp8390outb(dp8390+Tpsr, ctlr->card.tstart);
- dp8390outb(ctlr->card.dp8390+Isr, 0xFF);
- dp8390outb(ctlr->card.dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
+ dp8390outb(dp8390+Isr, 0xFF);
+ dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
/*
* Leave the chip initialised,
* but in monitor mode.
*/
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta);
+ dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
}
void
@@ 246,9 254,33 @@ dp8390mode(Ctlr *ctlr, int on)
void
dp8390setea(Ctlr *ctlr)
{
+ ulong dp8390;
+ uchar cr;
+ int i;
+
+ dp8390 = ctlr->card.dp8390;
+ /*
+ * Set the ethernet address into the chip.
+ * Take care to restore the command register
+ * afterwards. We don't care about multicast
+ * addresses as we never set the multicast
+ * enable.
+ */
+ cr = dp8390inb(dp8390+Cr) & ~Txp;
+ dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
+ for(i = 0; i < sizeof(ctlr->ea); i++)
+ dp8390outb(dp8390+Par0+i, ctlr->ea[i]);
+ dp8390outb(dp8390+Cr, cr);
+}
+
+void
+dp8390getea(Ctlr *ctlr)
+{
+ ulong dp8390;
uchar cr;
int i;
+ dp8390 = ctlr->card.dp8390;
/*
* Set the ethernet address into the chip.
* Take care to restore the command register
@@ 256,43 288,45 @@ dp8390setea(Ctlr *ctlr)
* addresses as we never set the multicast
* enable.
*/
- cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp;
- dp8390outb(ctlr->card.dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
+ cr = dp8390inb(dp8390+Cr) & ~Txp;
+ dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
for(i = 0; i < sizeof(ctlr->ea); i++)
- dp8390outb(ctlr->card.dp8390+Par0+i, ctlr->ea[i]);
- dp8390outb(ctlr->card.dp8390+Cr, cr);
+ ctlr->ea[i] = dp8390inb(dp8390+Par0+i);
+ dp8390outb(dp8390+Cr, cr);
}
void*
dp8390read(Ctlr *ctlr, void *to, ulong from, ulong len)
{
+ ulong dp8390;
uchar cr;
int timo;
+ dp8390 = ctlr->card.dp8390;
/*
* Read some data at offset 'from' in the card's memory
* using the DP8390 remote DMA facility, and place it at
* 'to' in main memory, via the I/O data port.
*/
- cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp;
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta);
- dp8390outb(ctlr->card.dp8390+Isr, Rdc);
+ cr = dp8390inb(dp8390+Cr) & ~Txp;
+ dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
+ dp8390outb(dp8390+Isr, Rdc);
/*
* Set up the remote DMA address and count.
*/
if(ctlr->card.bit16)
len = ROUNDUP(len, 2);
- dp8390outb(ctlr->card.dp8390+Rbcr0, len & 0xFF);
- dp8390outb(ctlr->card.dp8390+Rbcr1, (len>>8) & 0xFF);
- dp8390outb(ctlr->card.dp8390+Rsar0, from & 0xFF);
- dp8390outb(ctlr->card.dp8390+Rsar1, (from>>8) & 0xFF);
+ dp8390outb(dp8390+Rbcr0, len & 0xFF);
+ dp8390outb(dp8390+Rbcr1, (len>>8) & 0xFF);
+ dp8390outb(dp8390+Rsar0, from & 0xFF);
+ dp8390outb(dp8390+Rsar1, (from>>8) & 0xFF);
/*
* Start the remote DMA read and suck the data
* out of the I/O port.
*/
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAread|Sta);
+ dp8390outb(dp8390+Cr, Page0|RDMAread|Sta);
if(ctlr->card.bit16)
inss(ctlr->card.data, to, len/2);
else
@@ 305,28 339,29 @@ dp8390read(Ctlr *ctlr, void *to, ulong from, ulong len)
* to the miracles of the bus, we could get this far
* and still be talking to a slot full of nothing.
*/
- for(timo = 10000; (dp8390inb(ctlr->card.dp8390+Isr) & Rdc) == 0 && timo; timo--)
+ for(timo = 10000; (dp8390inb(dp8390+Isr) & Rdc) == 0 && timo; timo--)
;
- dp8390outb(ctlr->card.dp8390+Isr, Rdc);
- dp8390outb(ctlr->card.dp8390+Cr, cr);
+ dp8390outb(dp8390+Isr, Rdc);
+ dp8390outb(dp8390+Cr, cr);
return to;
}
void*
dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len)
{
+ ulong dp8390, crda;
uchar cr;
- ulong crda;
+ dp8390 = ctlr->card.dp8390;
/*
* Write some data to offset 'to' in the card's memory
* using the DP8390 remote DMA facility, reading it at
* 'from' in main memory, via the I/O data port.
*/
- cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp;
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta);
- dp8390outb(ctlr->card.dp8390+Isr, Rdc);
+ cr = dp8390inb(dp8390+Cr) & ~Txp;
+ dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
+ dp8390outb(dp8390+Isr, Rdc);
if(ctlr->card.bit16)
len = ROUNDUP(len, 2);
@@ 337,24 372,24 @@ dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len)
* the initial set up for read.
*/
crda = to-1-ctlr->card.bit16;
- dp8390outb(ctlr->card.dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF);
- dp8390outb(ctlr->card.dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF);
- dp8390outb(ctlr->card.dp8390+Rsar0, crda & 0xFF);
- dp8390outb(ctlr->card.dp8390+Rsar1, (crda>>8) & 0xFF);
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAread|Sta);
+ dp8390outb(dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF);
+ dp8390outb(dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF);
+ dp8390outb(dp8390+Rsar0, crda & 0xFF);
+ dp8390outb(dp8390+Rsar1, (crda>>8) & 0xFF);
+ dp8390outb(dp8390+Cr, Page0|RDMAread|Sta);
for(;;){
- crda = dp8390inb(ctlr->card.dp8390+Crda0);
- crda |= dp8390inb(ctlr->card.dp8390+Crda1)<<8;
+ crda = dp8390inb(dp8390+Crda0);
+ crda |= dp8390inb(dp8390+Crda1)<<8;
if(crda == to){
/*
* Start the remote DMA write and make sure
* the registers are correct.
*/
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAwrite|Sta);
+ dp8390outb(dp8390+Cr, Page0|RDMAwrite|Sta);
- crda = dp8390inb(ctlr->card.dp8390+Crda0);
- crda |= dp8390inb(ctlr->card.dp8390+Crda1)<<8;
+ crda = dp8390inb(dp8390+Crda0);
+ crda |= dp8390inb(dp8390+Crda1)<<8;
if(crda != to)
panic("crda write %d to %d\n", crda, to);
@@ 375,28 410,28 @@ dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len)
* a timeout here if this ever gets called before
* we know there really is a chip there.
*/
- while((dp8390inb(ctlr->card.dp8390+Isr) & Rdc) == 0)
+ while((dp8390inb(dp8390+Isr) & Rdc) == 0)
;
- dp8390outb(ctlr->card.dp8390+Isr, Rdc);
- dp8390outb(ctlr->card.dp8390+Cr, cr);
+ dp8390outb(dp8390+Isr, Rdc);
+ dp8390outb(dp8390+Cr, cr);
return (void*)to;
}
static uchar
-getcurr(Ctlr *ctlr)
+getcurr(ulong dp8390)
{
uchar cr, curr;
- cr = dp8390inb(ctlr->card.dp8390+Cr) & ~Txp;
- dp8390outb(ctlr->card.dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
- curr = dp8390inb(ctlr->card.dp8390+Curr);
- dp8390outb(ctlr->card.dp8390+Cr, cr);
+ cr = dp8390inb(dp8390+Cr) & ~Txp;
+ dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
+ curr = dp8390inb(dp8390+Curr);
+ dp8390outb(dp8390+Cr, cr);
return curr;
}
static void
-cldaquiet(Ctlr *ctlr)
+cldaquiet(ulong dp8390)
{
uchar a, b, c;
@@ 409,11 444,11 @@ cldaquiet(Ctlr *ctlr)
*/
for(;;delay(10)){
- a = dp8390inb(ctlr->card.dp8390+Clda0);
- b = dp8390inb(ctlr->card.dp8390+Clda0);
+ a = dp8390inb(dp8390+Clda0);
+ b = dp8390inb(dp8390+Clda0);
if(a != b)
continue;
- c = dp8390inb(ctlr->card.dp8390+Clda0);
+ c = dp8390inb(dp8390+Clda0);
if(c != b)
continue;
break;
@@ 426,11 461,12 @@ dp8390receive(Ctlr *ctlr)
RingBuf *ring;
uchar curr, len1, *pkt;
Hdr hdr;
- ulong data, len;
+ ulong dp8390, data, len;
- for(curr = getcurr(ctlr); ctlr->card.nxtpkt != curr; curr = getcurr(ctlr)){
+ dp8390 = ctlr->card.dp8390;
+ for(curr = getcurr(dp8390); ctlr->card.nxtpkt != curr; curr = getcurr(dp8390)){
if(strcmp(arch->id, "NCRD.0") == 0)
- cldaquiet(ctlr);
+ cldaquiet(dp8390);
ctlr->inpackets++;
@@ 458,9 494,9 @@ dp8390receive(Ctlr *ctlr)
|| len < 60 || len > sizeof(Etherpkt)){
print("H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d|",
hdr.status, hdr.next, hdr.len0, hdr.len1, len);
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp);
+ dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
dp8390ring(ctlr);
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta);
+ dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
return;
}
@@ 500,7 536,7 @@ dp8390receive(Ctlr *ctlr)
hdr.next--;
if(hdr.next < ctlr->card.pstart)
hdr.next = ctlr->card.pstop-1;
- dp8390outb(ctlr->card.dp8390+Bnry, hdr.next);
+ dp8390outb(dp8390+Bnry, hdr.next);
}
}
@@ 510,8 546,10 @@ dp8390receive(Ctlr *ctlr)
void
dp8390transmit(Ctlr *ctlr)
{
+ ulong dp8390;
RingBuf *ring;
+ dp8390 = ctlr->card.dp8390;
ring = &ctlr->tb[ctlr->ti];
if(ctlr->tbusy == 0 && ring->owner == Interface){
@@ 519,41 557,43 @@ dp8390transmit(Ctlr *ctlr)
(*ctlr->card.write)(ctlr, ctlr->card.tstart*Dp8390BufSz, ring->pkt, ring->len);
- dp8390outb(ctlr->card.dp8390+Tbcr0, ring->len & 0xFF);
- dp8390outb(ctlr->card.dp8390+Tbcr1, (ring->len>>8) & 0xFF);
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Txp|Sta);
+ dp8390outb(dp8390+Tbcr0, ring->len & 0xFF);
+ dp8390outb(dp8390+Tbcr1, (ring->len>>8) & 0xFF);
+ dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta);
}
}
void
dp8390overflow(Ctlr *ctlr)
{
+ ulong dp8390;
uchar txp;
int resend;
+ dp8390 = ctlr->card.dp8390;
/*
* The following procedure is taken from the DP8390[12D] datasheet,
* it seems pretty adamant that this is what has to be done.
*/
- txp = dp8390inb(ctlr->card.dp8390+Cr) & Txp;
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Stp);
+ txp = dp8390inb(dp8390+Cr) & Txp;
+ dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
delay(2);
- dp8390outb(ctlr->card.dp8390+Rbcr0, 0);
- dp8390outb(ctlr->card.dp8390+Rbcr1, 0);
+ dp8390outb(dp8390+Rbcr0, 0);
+ dp8390outb(dp8390+Rbcr1, 0);
resend = 0;
- if(txp && (dp8390inb(ctlr->card.dp8390+Isr) & (Txe|Ptx)) == 0)
+ if(txp && (dp8390inb(dp8390+Isr) & (Txe|Ptx)) == 0)
resend = 1;
- dp8390outb(ctlr->card.dp8390+Tcr, Lb);
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Sta);
+ dp8390outb(dp8390+Tcr, Lb);
+ dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
(*ctlr->card.receive)(ctlr);
- dp8390outb(ctlr->card.dp8390+Isr, Ovw);
+ dp8390outb(dp8390+Isr, Ovw);
wakeup(&ctlr->rr);
- dp8390outb(ctlr->card.dp8390+Tcr, 0);
+ dp8390outb(dp8390+Tcr, 0);
if(resend)
- dp8390outb(ctlr->card.dp8390+Cr, Page0|RDMAabort|Txp|Sta);
+ dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta);
}
void
@@ 577,20 617,22 @@ dp8390watch(Ctlr *ctlr)
void
dp8390intr(Ctlr *ctlr)
{
+ ulong dp8390;
RingBuf *ring;
uchar isr, r;
+ dp8390 = ctlr->card.dp8390;
/*
* While there is something of interest,
* clear all the interrupts and process.
*/
- dp8390outb(ctlr->card.dp8390+Imr, 0x00);
- while(isr = dp8390inb(ctlr->card.dp8390+Isr)){
+ dp8390outb(dp8390+Imr, 0x00);
+ while(isr = dp8390inb(dp8390+Isr)){
if(isr & Ovw){
if(ctlr->card.overflow)
(*ctlr->card.overflow)(ctlr);
- dp8390outb(ctlr->card.dp8390+Isr, Ovw);
+ dp8390outb(dp8390+Isr, Ovw);
ctlr->overflows++;
}
@@ 601,7 643,7 @@ dp8390intr(Ctlr *ctlr)
*/
if(isr & (Rxe|Prx)){
(*ctlr->card.receive)(ctlr);
- dp8390outb(ctlr->card.dp8390+Isr, Rxe|Prx);
+ dp8390outb(dp8390+Isr, Rxe|Prx);
wakeup(&ctlr->rr);
}
@@ 611,14 653,14 @@ dp8390intr(Ctlr *ctlr)
* and wake the output routine.
*/
if(isr & (Txe|Ptx)){
- r = dp8390inb(ctlr->card.dp8390+Tsr);
+ r = dp8390inb(dp8390+Tsr);
if(isr & Txe){
if((r & (Cdh|Fu|Crs|Abt)) && ctlr->debug)
print("Tsr#%2.2ux|", r);
ctlr->oerrs++;
}
- dp8390outb(ctlr->card.dp8390+Isr, Txe|Ptx);
+ dp8390outb(dp8390+Isr, Txe|Ptx);
if(isr & Ptx)
ctlr->outpackets++;
@@ 632,11 674,11 @@ dp8390intr(Ctlr *ctlr)
}
if(isr & Cnt){
- ctlr->frames += dp8390inb(ctlr->card.dp8390+Cntr0);
- ctlr->crcs += dp8390inb(ctlr->card.dp8390+Cntr1);
- ctlr->buffs += dp8390inb(ctlr->card.dp8390+Cntr2);
- dp8390outb(ctlr->card.dp8390+Isr, Cnt);
+ ctlr->frames += dp8390inb(dp8390+Cntr0);
+ ctlr->crcs += dp8390inb(dp8390+Cntr1);
+ ctlr->buffs += dp8390inb(dp8390+Cntr2);
+ dp8390outb(dp8390+Isr, Cnt);
}
}
- dp8390outb(ctlr->card.dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
+ dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
}
M pc/fault386.c => pc/fault386.c +5 -4
@@ 18,24 18,25 @@ fault386(Ureg *ur)
int insyscall;
char buf[ERRLEN];
- insyscall = u->p->insyscall;
- u->p->insyscall = 1;
+ insyscall = up->insyscall;
+ up->insyscall = 1;
addr = getcr2();
read = !(ur->ecode & 2);
user = (ur->cs&0xffff) == UESEL;
spllo();
+/* print("F%d:A#%lux:U%d:R%d|", up->pid, addr, user, read);/**/
n = fault(addr, read);
if(n < 0){
if(user){
sprint(buf, "sys: trap: fault %s addr=0x%lux",
read? "read" : "write", addr);
- postnote(u->p, 1, buf, NDebug);
+ postnote(up, 1, buf, NDebug);
return;
}
dumpregs(ur);
panic("fault: 0x%lux", addr);
}
- u->p->insyscall = insyscall;
+ up->insyscall = insyscall;
}
void
M pc/fns.h => pc/fns.h +15 -2
@@ 1,6 1,6 @@
#include "../port/portfns.h"
-void meminit(void);
+void addconf(char*, char*);
void bbinit(void);
void bigcursor(void);
void bootargs(ulong);
@@ 11,6 11,7 @@ void config(int);
int cpuspeed(int);
void delay(int);
void dmaend(int);
+void dmainit(void);
long dmasetup(int, void*, long, int);
#define evenaddr(x) /* 386 doesn't care */
void fault386(Ureg*);
@@ 25,6 26,7 @@ void fpsave(FPsave*);
ulong fpstatus(void);
ulong getcr0(void);
ulong getcr2(void);
+char* getconf(char*);
void i8042a20(void);
void i8042reset(void);
void ident(void);
@@ 33,13 35,17 @@ int inb(int);
void insb(int, void*, int);
ushort ins(int);
void inss(int, void*, int);
+ulong inl(int);
void insl(int, void*, int);
+int isaconfig(char*, int, ISAConf*);
ulong isamem(int);
void kbdinit(void);
void* l0update(uchar*, uchar*, long);
void* l1update(uchar*, uchar*, long);
void* l2update(uchar*, uchar*, long);
+long* mapaddr(ulong);
void mathinit(void);
+void meminit(void);
void mmuinit(void);
#define mmunewpage(x)
int modem(int);
@@ 49,12 55,19 @@ void outb(int, int);
void outsb(int, void*, int);
void outs(int, ushort);
void outss(int, void*, int);
+void outl(int, ulong);
void outsl(int, void*, int);
void pcicreset(void);
+int pcmio(int, ISAConf*);
+long pcmread(int, int, void*, long, ulong);
+int pcmspecial(int);
+void pcmspecialclose(int);
+long pcmwrite(int, int, void*, long, ulong);
void prhex(ulong);
void procrestore(Proc*);
void procsave(Proc*);
void procsetup(Proc*);
+void ps2poll(void);
void putgdt(Segdesc*, int);
void putidt(Segdesc*, int);
void putcr3(ulong);
@@ 73,7 86,7 @@ void uartclock(void);
void uartintr0(Ureg*);
void uartspecial(int, IOQ*, IOQ*, int);
void vgainit(void);
-#define waserror() (u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))
+#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
#define kmapperm(x) kmap(x)
#define getcallerpc(x) (*(ulong*)(x))
#define KADDR(a) ((void*)((ulong)(a)|KZERO))
M pc/kbd.c => pc/kbd.c +81 -1
@@ 25,6 25,17 @@ enum {
Cmd= 0x64, /* command port (write only) */
+ CTdata= 0x0, /* chips & Technologies ps2 data port */
+ CTstatus= 0x1, /* chips & Technologies ps2 status port */
+ Enable= 1<<7,
+ Clear= 1<<6,
+ Error= 1<<5,
+ Intenable= 1<<4,
+ Reset= 1<<3,
+ Tready= 1<<2,
+ Rready= 1<<1,
+ Idle= 1<<0,
+
Spec= 0x80,
PF= Spec|0x20, /* num pad function key */
@@ 112,6 123,7 @@ KIOQ kbdq;
static int keybuttons;
static uchar ccc;
static int shift;
+ulong ctport;
enum
{
@@ 125,6 137,7 @@ enum
};
static void kbdintr(Ureg*);
+static void ctps2intr(Ureg*);
static int ps2mouseputc(IOQ*, int);
/*
@@ 171,7 184,7 @@ mousecmd(int cmd)
c = 0;
tries = 0;
do{
- if(tries++ > 5)
+ if(tries++ > 2)
break;
if(outready() < 0)
break;
@@ 227,6 240,7 @@ i8042reset(void)
outready();
}
+
void
kbdinit(void)
{
@@ 279,6 293,54 @@ serialmouse(int port, char *type, int setspeed)
mousetype = Mouseserial;
}
+static void nop(void){};
+
+/*
+ * look for a chips & technologies 82c710 ps2 mouse on a TI travelmate
+ */
+static int
+ct82c710(void)
+{
+ int c;
+
+ /* on non-C&T 2fa and 3fa are input only ports */
+ /* get chips attention */
+ outb(0x2fa, 0x55); nop(); nop();
+ outb(0x3fa, ~0x55); nop(); nop();
+ outb(0x3fa, 0x36); nop(); nop();
+
+ /* tell it where its config register should be */
+ outb(0x3fa, 0x390>>2); nop(); nop();
+ outb(0x2fa, ~(0x390>>2)); nop(); nop();
+
+ /* see if this is really a 710 */
+ outb(0x390, 0xf); nop(); nop();
+ if(inb(0x391) != (0x390>>2))
+ return -1;
+
+ /* get data port address */
+ outb(0x390, 0xd); nop(); nop();
+ c = inb(0x391);
+ if(c == 0 || c == 0xff)
+ return -1;
+ ctport = c<<2;
+
+ /* turn off config mode */
+ outb(0x390, 0xf); nop(); nop();
+ outb(0x391, 0xf);
+
+ setvec(Mousevec, ctps2intr);
+
+ /* enable for interrupts */
+ c = inb(ctport + CTstatus);
+ c &= ~(Clear|Reset);
+ c |= Enable|Intenable;
+ outb(ctport + CTstatus, c);
+
+ mousetype = MousePS2;
+ return 0;
+}
+
/*
* set up a ps2 mouse
*/
@@ 290,6 352,9 @@ ps2mouse(void)
if(mousetype)
error(Emouseset);
+ if(ct82c710() == 0)
+ return;
+
/* enable kbd/mouse xfers and interrupts */
setvec(Mousevec, kbdintr);
x = splhi();
@@ 563,3 628,18 @@ kbdintr(Ureg *ur)
USED(ur);
kbdintr0();
}
+
+void
+ctps2intr(Ureg *ur)
+{
+ uchar c;
+
+ USED(ur);
+ c = inb(ctport + CTstatus);
+ if(c & Error)
+ return;
+ if((c & Rready) == 0)
+ return;
+ c = inb(ctport + CTdata);
+ ps2mouseputc(&mouseq, c);
+}
M pc/l.s => pc/l.s +67 -91
@@ 1,89 1,16 @@
#include "mem.h"
#define OP16 BYTE $0x66
+#define NOP XCHGL AX,AX
/*
- * about to walk all over ms/dos - turn off interrupts
+ * We assume that b.com got us into 32 bit mode already. We are now
+ * running with a PC == origin & ~KZERO.
*/
TEXT origin(SB),$0
CLI
-#ifdef BOOT
-/*
- * This part of l.s is used only in the boot kernel.
- * It assumes that we are in real address mode, i.e.,
- * that we look like an 8086.
- */
-/*
- * relocate everything to a half meg and jump there
- * - looks wierd because it is being assembled by a 32 bit
- * assembler for a 16 bit world
- */
- MOVL $0,BX
- INCL BX
- SHLL $15,BX
- MOVL BX,CX
- MOVW BX,ES
- MOVL $0,SI
- MOVL SI,DI
- CLD; REP; MOVSL
-/* JMPFAR 0X8000:$lowcore(SB) /**/
- BYTE $0xEA
- WORD $lowcore(SB)
- WORD $0X8000
-
-TEXT lowcore(SB),$0
-
-/*
- * now that we're in low core, update the DS
- */
-
- MOVW BX,DS
-
-/*
- * goto protected mode
- */
-/* MOVL tgdtptr(SB),GDTR /**/
- BYTE $0x0f
- BYTE $0x01
- BYTE $0x16
- WORD $tgdtptr(SB)
- MOVL CR0,AX
- ORL $1,AX
- MOVL AX,CR0
-
-/*
- * clear prefetch queue (weird code to avoid optimizations)
- */
- CLC
- JCC flush
- MOVL AX,AX
-flush:
-
-/*
- * set all segs
- */
-/* MOVW $SELECTOR(1, SELGDT, 0),AX /**/
- BYTE $0xc7
- BYTE $0xc0
- WORD $SELECTOR(1, SELGDT, 0)
- MOVW AX,DS
- MOVW AX,SS
- MOVW AX,ES
- MOVW AX,FS
- MOVW AX,GS
-
-/* JMPFAR SELECTOR(2, SELGDT, 0):$mode32bit(SB) /**/
- BYTE $0x66
- BYTE $0xEA
- LONG $mode32bit-KZERO(SB)
- WORD $SELECTOR(2, SELGDT, 0)
-
-TEXT mode32bit(SB),$0
-
-#endif BOOT
-
/*
* Clear BSS
*/
@@ 104,8 31,8 @@ TEXT mode32bit(SB),$0
LEAL tpt-KZERO(SB),AX /* get phys addr of temporary page table */
ADDL $(BY2PG-1),AX /* must be page alligned */
ANDL $(~(BY2PG-1)),AX /* ... */
- MOVL $(4*1024),CX /* pte's per page */
- MOVL $((((4*1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
+ MOVL $(1024),CX /* pte's per page */
+ MOVL $((((1024)-1)<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE),BX
setpte:
MOVL BX,-4(AX)(CX*4)
SUBL $(1<<PGSHIFT),BX
@@ 116,19 43,10 @@ setpte:
* 16 meg of memory to 0 thru 16meg and to KZERO thru KZERO+16meg
*/
MOVL AX,BX
- ADDL $(4*BY2PG),AX
+ ADDL $(BY2PG),AX
ADDL $(PTEVALID|PTEKERNEL|PTEWRITE),BX
MOVL BX,0(AX)
MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+0)(AX)
- ADDL $BY2PG,BX
- MOVL BX,4(AX)
- MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+4)(AX)
- ADDL $BY2PG,BX
- MOVL BX,8(AX)
- MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+8)(AX)
- ADDL $BY2PG,BX
- MOVL BX,12(AX)
- MOVL BX,((((KZERO>>1)&0x7FFFFFFF)>>(2*PGSHIFT-1-4))+12)(AX)
/*
* point processor to top level page & turn on paging
@@ 155,7 73,7 @@ TEXT tokzero(SB),$0
MOVL SP,m(SB)
MOVL $0,0(SP)
ADDL $(MACHSIZE-4),SP /* start stack under machine struct */
- MOVL $0, u(SB)
+ MOVL $0, up(SB)
/*
* clear flags
@@ 172,7 90,7 @@ loop:
GLOBL mach0+0(SB), $MACHSIZE
GLOBL u(SB), $4
GLOBL m(SB), $4
-GLOBL tpt(SB), $(BY2PG*6)
+GLOBL tpt(SB), $(BY2PG*3)
/*
* gdt to get us to 32-bit/segmented/unpaged mode
@@ 251,7 169,6 @@ TEXT ins(SB), $0
OP16; INL
RET
-
/*
* input a string of shorts from a port
*/
@@ 264,6 181,16 @@ TEXT inss(SB),$0
RET
/*
+ * input a long from a port
+ */
+TEXT inl(SB), $0
+
+ MOVL p+0(FP), DX
+ XORL AX, AX
+ INL
+ RET
+
+/*
* input a string of longs from a port
*/
TEXT insl(SB),$0
@@ 295,6 222,15 @@ TEXT outss(SB),$0
RET
/*
+ * output a long to a port
+ */
+TEXT outl(SB), $0
+ MOVL p+0(FP), DX
+ MOVL s+4(FP), AX
+ OUTL
+ RET
+
+/*
* output a string of longs to a port
*/
TEXT outsl(SB),$0
@@ 553,10 489,12 @@ intrcommon:
CALL trap(SB)
POPL AX
POPAL
+ NOP
POPL GS
POPL FS
POPL ES
POPL DS
+ NOP
ADDL $8,SP /* error code and trap type */
IRETL
@@ 574,10 512,12 @@ intrscommon:
CALL trap(SB)
POPL AX
POPAL
+ NOP
POPL GS
POPL FS
POPL ES
POPL DS
+ NOP
ADDL $8,SP /* error code and trap type */
IRETL
@@ 794,3 734,39 @@ TEXT dp8390outb(SB), $0
_dp8390outb0:
RET
+
+/*
+ * dsp outb string called from devdsp.c
+ */
+ TEXT dspoutb+0(SB), $0
+
+ MOVL a+4(FP), BX
+ MOVL n+8(FP), CX
+
+ MOVL base+0(FP), DX
+ ADDL $2, DX /* Pcontrol */
+
+ MOVL c2+12(FP), DI
+ MOVL c3+16(FP), SI
+
+dsploop:
+ MOVL DI, AX /* normal */
+ OUTB
+
+ SUBL $1, CX
+ CMPL CX, $0
+ JLT dspout
+
+ SUBL $2, DX /* Pdata */
+ MOVB (BX), AX
+ ADDL $1, BX
+ OUTB
+
+ ADDL $2, DX /* Pcontrol */
+ MOVL SI, AX /* strobe */
+ OUTB
+
+ JMP dsploop
+
+dspout:
+ RET
M pc/main.c => pc/main.c +208 -75
@@ 26,10 26,15 @@ PCArch *knownarch[] =
#define BOOTARGSLEN 1024
#define MAXCONF 32
+char bootdisk[NAMELEN];
char *confname[MAXCONF];
char *confval[MAXCONF];
int nconf;
+/* memory map */
+#define MAXMEG 64
+char mmap[MAXMEG+2];
+
void
main(void)
{
@@ 40,6 45,7 @@ main(void)
active.machs = 1;
confinit();
xinit();
+ dmainit();
screeninit();
printinit();
mmuinit();
@@ 51,8 57,8 @@ main(void)
kbdinit();
procinit0();
initseg();
+ links();
chandevreset();
- streaminit();
swapinit();
userinit();
schedinit();
@@ 94,10 100,10 @@ init0(void)
int i;
char tstr[32];
- u->nerrlab = 0;
- m->proc = u->p;
- u->p->state = Running;
- u->p->mach = m;
+ up->nerrlab = 0;
+ m->proc = up->p;
+ up->state = Running;
+ up->mach = m;
spllo();
@@ 105,21 111,23 @@ init0(void)
* These are o.k. because rootinit is null.
* Then early kproc's will have a root and dot.
*/
- u->slash = (*devtab[0].attach)(0);
- u->dot = clone(u->slash, 0);
+ up->slash = namec("#/", Atodir, 0, 0);
+ up->dot = clone(up->slash, 0);
- kproc("alarm", alarmkproc, 0);
+ iallocinit();
chandevinit();
if(!waserror()){
- for(i = 0; i < nconf; i++)
- ksetenv(confname[i], confval[i]);
strcpy(tstr, arch->id);
strcat(tstr, " %s");
ksetterm(tstr);
ksetenv("cputype", "386");
+ for(i = 0; i < nconf; i++)
+ if(confname[i])
+ ksetenv(confname[i], confval[i]);
poperror();
}
+ kproc("alarm", alarmkproc, 0);
touser(sp);
}
@@ 152,21 160,12 @@ userinit(void)
* 4 bytes for gotolabel's return PC
*/
p->sched.pc = (ulong)init0;
- p->sched.sp = USERADDR + BY2PG - 4;
- p->upage = newpage(1, 0, USERADDR|(p->pid&0xFFFF));
-
- /*
- * User
- */
- k = kmap(p->upage);
- up = (User*)VA(k);
- up->p = p;
- kunmap(k);
+ p->sched.sp = (ulong)p->kstack+KSTACK-(1+MAXSYSARG)*BY2WD;
/*
* User Stack
*/
- s = newseg(SG_STACK, USTKTOP-BY2PG, 1);
+ s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
p->seg[SSEG] = s;
pg = newpage(1, 0, USTKTOP-BY2PG);
segpage(s, pg);
@@ 178,8 177,11 @@ userinit(void)
* Text
*/
s = newseg(SG_TEXT, UTZERO, 1);
+ s->flushme++;
p->seg[TSEG] = s;
- segpage(s, newpage(1, 0, UTZERO));
+ pg = newpage(1, 0, UTZERO);
+ memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
+ segpage(s, pg);
k = kmap(s->map[0]->pages[0]);
memmove((ulong*)VA(k), initcode, sizeof initcode);
kunmap(k);
@@ 213,13 215,30 @@ bootargs(ulong base)
av[ac++] = pusharg("/386/9safari");
av[ac++] = pusharg("-p");
cp[64] = 0;
+ buf[0] = 0;
if(strncmp(cp, "fd!", 3) == 0){
sprint(buf, "local!#f/fd%ddisk", atoi(cp+3));
av[ac++] = pusharg(buf);
+ } else if(strncmp(cp, "h!", 2) == 0){
+ sprint(buf, "local!#H/hd%dfs", atoi(cp+2));
+ av[ac++] = pusharg(buf);
} else if(strncmp(cp, "hd!", 3) == 0){
- sprint(buf, "local!#h/hd%ddisk", atoi(cp+3));
+ sprint(buf, "local!#H/hd%ddisk", atoi(cp+3));
+ av[ac++] = pusharg(buf);
+ } else if(strncmp(cp, "s!", 2) == 0){
+ sprint(buf, "local!#w/sd%dfs", atoi(cp+2));
+ av[ac++] = pusharg(buf);
+ } else if(strncmp(cp, "sd!", 3) == 0){
+ sprint(buf, "local!#w/sd%ddisk", atoi(cp+3));
av[ac++] = pusharg(buf);
}
+ if(buf[0]){
+ cp = strchr(buf, '!');
+ if(cp){
+ strcpy(bootdisk, cp+1);
+ addconf("bootdisk", bootdisk);
+ }
+ }
/* 4 byte word align stack */
sp = (uchar*)((ulong)sp & ~3);
@@ 236,9 255,30 @@ bootargs(ulong base)
Conf conf;
void
+addconf(char *name, char *val)
+{
+ if(nconf >= MAXCONF)
+ return;
+ confname[nconf] = name;
+ confval[nconf] = val;
+ nconf++;
+}
+
+char*
+getconf(char *name)
+{
+ int i;
+
+ for(i = 0; i < nconf; i++)
+ if(strcmp(confname[i], name) == 0)
+ return confval[i];
+ return 0;
+}
+
+void
confinit(void)
{
- long x, i, j, n, *l;
+ long x, i, j, n;
int pcnt;
ulong ktop;
char *cp;
@@ 249,7 289,7 @@ confinit(void)
/*
* parse configuration args from dos file p9rc
*/
- cp = BOOTARGS; /* where b.com leaves it's config */
+ cp = BOOTARGS; /* where b.com leaves its config */
cp[BOOTARGSLEN-1] = 0;
n = getfields(cp, line, MAXCONF, '\n');
for(j = 0; j < n; j++){
@@ 268,60 308,83 @@ confinit(void)
pcnt = 100 - atoi(confval[nconf]);
nconf++;
}
-
/*
- * the first 640k is the standard useful memory
- * the next 128K is the display, I/O mem, and BIOS
- * the last 256k belongs to the roms and other devices
- */
- conf.npage0 = 640/4;
- conf.base0 = 0;
-
- /*
- * size the non-standard memory
+ * size memory above 1 meg. Kernel sits at 1 meg. We
+ * only recognize MB size chunks.
*/
+ memset(mmap, ' ', sizeof(mmap));
x = 0x12345678;
- for(i=2; i<17; i++){
+ for(i = 1; i <= MAXMEG; i++){
/*
- * write the word
+ * write the first & last word in a megabyte of memory
*/
- l = (long*)(KZERO|(i*MB));
- l--;
- *l = x;
+ *mapaddr(KZERO|(i*MB)) = x;
+ *mapaddr(KZERO|((i+1)*MB-BY2WD)) = x;
+
/*
- * take care of wraps
+ * write the first and last word in all previous megs to
+ * handle address wrap around
*/
for(j = 1; j < i; j++){
- l = (long*)(KZERO|(j*MB));
- l--;
- *l = ~x;
+ *mapaddr(KZERO|(j*MB)) = ~x;
+ *mapaddr(KZERO|((j+1)*MB-BY2WD)) = ~x;
}
+
/*
- * check
+ * check for correct value
*/
- l = (long*)(KZERO|(i*MB));
- l--;
- if(*l != x)
- break;
- memset((char*)(KZERO|((i-1)*MB)), 0, MB);
+ if(*mapaddr(KZERO|(i*MB)) == x && *mapaddr(KZERO|((i+1)*MB-BY2WD)) == x){
+ mmap[i] = 'x';
+ /*
+ * zero memory to set ECC but skip over the kernel
+ */
+ if(i != 1)
+ for(j = 0; j < MB/BY2PG; j += BY2PG)
+ memset(mapaddr(KZERO|(i*MB+j)), 0, BY2PG);
+ }
x += 0x3141526;
}
- i--;
- conf.base1 = 1*MB;
- conf.npage1 = (i*MB - conf.base1)/BY2PG;
+ /*
+ * bank0 usually goes from the end of kernel bss to the end of memory
+ */
+ ktop = PGROUND((ulong)end);
+ ktop = PADDR(ktop);
+ conf.base0 = ktop;
+ for(i = 1; mmap[i] == 'x'; i++)
+ ;
+ conf.npage0 = (i*MB - ktop)/BY2PG;
+ conf.topofmem = i*MB;
+
+ /*
+ * bank1 usually goes from the end of BOOTARGS to 640k
+ */
+ conf.base1 = (ulong)(BOOTARGS+BOOTARGSLEN);
+ conf.base1 = PGROUND(conf.base1);
+ conf.base1 = PADDR(conf.base1);
+ conf.npage1 = (640*1024-conf.base1)/BY2PG;
+
+ /*
+ * if there is a hole in memory (due to a shadow BIOS) make the
+ * memory after the hole be bank 1. The memory from 0 to 640k
+ * is lost.
+ */
+ for(; i <= MAXMEG; i++)
+ if(mmap[i] == 'x'){
+ conf.base1 = i*MB;
+ for(j = i+1; mmap[j] == 'x'; j++)
+ ;
+ conf.npage1 = (j - i)*MB/BY2PG;
+ conf.topofmem = j*MB;
+ break;
+ }
+
conf.npage = conf.npage0 + conf.npage1;
conf.ldepth = 0;
if(pcnt < 10)
pcnt = 70;
conf.upages = (conf.npage*pcnt)/100;
- ktop = PGROUND((ulong)end);
- ktop = PADDR(ktop);
- conf.npage0 -= ktop/BY2PG;
- conf.base0 += ktop;
-
- conf.topofmem = i*MB;
- conf.nproc = 30 + i*5;
+ conf.nproc = 30 + ((conf.npage*BY2PG)/MB)*5;
conf.monitor = 1;
conf.nswap = conf.nproc*80;
conf.nimage = 50;
@@ 363,24 426,24 @@ matherror(Ureg *ur)
/*
* save floating point state to check out error
*/
- fpenv(&u->fpsave);
- status = u->fpsave.status;
+ fpenv(&up->fpsave);
+ status = up->fpsave.status;
msg = 0;
for(i = 0; i < 8; i++)
if((1<<i) & status){
msg = mathmsg[i];
- sprint(note, "sys: fp: %s fppc=0x%lux", msg, u->fpsave.pc);
- postnote(u->p, 1, note, NDebug);
+ sprint(note, "sys: fp: %s fppc=0x%lux", msg, up->fpsave.pc);
+ postnote(up->p, 1, note, NDebug);
break;
}
if(msg == 0){
- sprint(note, "sys: fp: unknown fppc=0x%lux", u->fpsave.pc);
- postnote(u->p, 1, note, NDebug);
+ sprint(note, "sys: fp: unknown fppc=0x%lux", up->fpsave.pc);
+ postnote(up->p, 1, note, NDebug);
}
if(ur->pc & KZERO)
panic("fp: status %lux fppc=0x%lux pc=0x%lux", status,
- u->fpsave.pc, ur->pc);
+ up->fpsave.pc, ur->pc);
}
/*
@@ 390,14 453,14 @@ void
mathemu(Ureg *ur)
{
USED(ur);
- switch(u->p->fpstate){
+ switch(up->fpstate){
case FPinit:
fpinit();
- u->p->fpstate = FPactive;
+ up->fpstate = FPactive;
break;
case FPinactive:
- fprestore(&u->fpsave);
- u->p->fpstate = FPactive;
+ fprestore(&up->fpsave);
+ up->fpstate = FPactive;
break;
case FPactive:
panic("math emu", 0);
@@ 412,7 475,7 @@ void
mathover(Ureg *ur)
{
USED(ur);
-print("sys: fp: math overrun pc 0x%lux pid %d\n", ur->pc, u->p->pid);
+print("sys: fp: math overrun pc 0x%lux pid %d\n", ur->pc, up->pid);
pexit("math overrun", 0);
}
@@ 445,7 508,7 @@ procsave(Proc *p)
if(p->state == Moribund)
fpoff();
else
- fpsave(&u->fpsave);
+ fpsave(&up->fpsave);
p->fpstate = FPinactive;
}
}
@@ 473,8 536,12 @@ exit(int ispanic)
{
u = 0;
print("exiting\n");
- if(ispanic)
- for(;;);
+ if(ispanic){
+ if(cpuflag)
+ delay(10000);
+ else
+ for(;;);
+ }
(*arch->reset)();
}
@@ 541,3 608,69 @@ modem(int onoff)
else
return 0;
}
+
+static int
+parseether(uchar *to, char *from)
+{
+ char nip[4];
+ char *p;
+ int i;
+
+ p = from;
+ for(i = 0; i < 6; i++){
+ if(*p == 0)
+ return -1;
+ nip[0] = *p++;
+ if(*p == 0)
+ return -1;
+ nip[1] = *p++;
+ nip[2] = 0;
+ to[i] = strtoul(nip, 0, 16);
+ if(*p == ':')
+ p++;
+ }
+ return 0;
+}
+
+int
+isaconfig(char *class, int ctlrno, ISAConf *isa)
+{
+ char cc[NAMELEN], *p, *q;
+ int n;
+
+ sprint(cc, "%s%d", class, ctlrno);
+ for(n = 0; n < nconf; n++){
+ if(strncmp(confname[n], cc, NAMELEN))
+ continue;
+ p = confval[n];
+ while(*p){
+ while(*p == ' ' || *p == '\t')
+ p++;
+ if(*p == '\0')
+ break;
+ if(strncmp(p, "type=", 5) == 0){
+ p += 5;
+ for(q = isa->type; q < &isa->type[NAMELEN-1]; q++){
+ if(*p == '\0' || *p == ' ' || *p == '\t')
+ break;
+ *q = *p++;
+ }
+ *q = '\0';
+ }
+ else if(strncmp(p, "port=", 5) == 0)
+ isa->port = strtoul(p+5, &p, 0);
+ else if(strncmp(p, "irq=", 4) == 0)
+ isa->irq = strtoul(p+4, &p, 0);
+ else if(strncmp(p, "mem=", 4) == 0)
+ isa->mem = strtoul(p+4, &p, 0);
+ else if(strncmp(p, "size=", 5) == 0)
+ isa->size = strtoul(p+5, &p, 0);
+ else if(strncmp(p, "ea=", 3) == 0)
+ parseether(isa->ea, p+3);
+ while(*p && *p != ' ' && *p != '\t')
+ p++;
+ }
+ return 1;
+ }
+ return 0;
+}
M pc/mem.h => pc/mem.h +2 -3
@@ 42,12 42,11 @@
#define UTZERO (UZERO+BY2PG) /* first address in user text */
#define KZERO 0x80000000 /* base of kernel address space */
#define KTZERO KZERO /* first address in kernel text */
-#define USERADDR 0xC0000000 /* struct User */
-#define UREGADDR (USERADDR+BY2PG-4*19)
-#define TSTKTOP USERADDR /* end of new stack in sysexec */
+#define TSTKTOP 0xC0000000 /* end of new stack in sysexec */
#define TSTKSIZ 10
#define USTKTOP (TSTKTOP-TSTKSIZ*BY2PG) /* byte just beyond user stack */
#define USTKSIZE (16*1024*1024 - TSTKSIZ*BY2PG) /* size of user stack */
+#define KSTACK 4096 /* Size of kernel stack */
#define ROMBIOS (KZERO|0xF0000)
#define ISAMEMSIZE (4*MB) /* mem space reserved for ISA */
M pc/mmu.c => pc/mmu.c +63 -56
@@ 71,7 71,6 @@ Segdesc gdt[] =
static Page ktoppg; /* prototype top level page table
* containing kernel mappings */
static ulong *kpt; /* 2nd level page tables for kernel mem */
-static ulong *upt; /* 2nd level page table for struct User */
#define ROUNDUP(s,v) (((s)+(v-1))&~(v-1))
/*
@@ 97,6 96,21 @@ struct
} isamemalloc;
/*
+ * Change current page table and the stack to use for exceptions
+ * (traps & interrupts). The exception stack comes from the tss.
+ * Since we use only one tss, (we hope) there's no need for a
+ * puttr().
+ */
+static void
+taskswitch(ulong pagetbl, ulong stack)
+{
+ putcr3(pagetbl);
+ tss.ss0 = KDSEL;
+ tss.sp0 = stack;
+ tss.cr3 = pagetbl;
+}
+
+/*
* Create a prototype page map that maps all of memory into
* kernel (KZERO) space. This is the default map. It is used
* whenever the processor not running a process or whenever running
@@ 147,21 161,11 @@ mmuinit(void)
for(i = 0; i < nkpt; i++)
top[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE;
- /* page table for u-> */
- upt = xspanalloc(BY2PG, BY2PG, 0);
- x = TOPOFF(USERADDR);
- y = ((ulong)upt)&~KZERO;
- top[x] = y | PTEVALID | PTEKERNEL | PTEWRITE;
-
- putcr3(ktoppg.pa);
-
/*
* set up the task segment
*/
memset(&tss, 0, sizeof(tss));
- tss.sp0 = USERADDR+BY2PG;
- tss.ss0 = KDSEL;
- tss.cr3 = ktoppg.pa;
+ taskswitch(ktoppg.pa, BY2BG + (ulong)m);
puttr(TSSSEL);
}
@@ 174,28 178,22 @@ flushmmu(void)
int s;
s = splhi();
- if(u){
- u->p->newtlb = 1;
- mapstack(u->p);
- } else
- putcr3(ktoppg.pa);
+ up->newtlb = 1;
+ mmuswitch(up);
splx(s);
}
/*
* Switch to a process's memory map. If the process doesn't
* have a map yet, just use the prototype one that contains
- * mappings for only the kernel and the User struct.
+ * mappings for only the kernel.
*/
void
-mapstack(Proc *p)
+mmuswitch(Proc *p)
{
Page *pg;
ulong *top;
- if(p->upage->va != (USERADDR|(p->pid&0xFFFF)) && p->pid != 0)
- panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va);
-
if(p->newtlb){
/*
* newtlb set means that they are inconsistent
@@ 218,17 216,11 @@ mapstack(Proc *p)
p->newtlb = 0;
}
- /* map in u area */
- upt[0] = PPN(p->upage->pa) | PTEVALID | PTEKERNEL | PTEWRITE;
-
/* tell processor about new page table (flushes cached entries) */
if(p->mmutop)
- pg = p->mmutop;
+ taskswitch(p->mmutop->pa, p->kstack+KSTACK);
else
- pg = &ktoppg;
- putcr3(pg->pa);
-
- u = (User*)USERADDR;
+ taskswitch(ktoppg.pa, p->kstack+KSTACK);
}
/*
@@ 241,8 233,8 @@ mmurelease(Proc *p)
Page *pg;
Page *next;
- /* point 386 to protoype page map */
- putcr3(ktoppg.pa);
+ /* point 386 to protoype page map and m->stack */
+ taskswitch(ktoppg.pa, BY2PG + (ulong)m);
/* give away page table pages */
for(pg = p->mmufree; pg; pg = next){
@@ 269,24 261,19 @@ putmmu(ulong va, ulong pa, Page *pg)
int topoff;
ulong *top;
ulong *pt;
- Proc *p;
int s;
- if(u==0)
- panic("putmmu");
- p = u->p;
-
/*
* create a top level page if we don't already have one.
* copy the kernel top level page into it for kernel mappings.
*/
- if(p->mmutop == 0){
+ if(up->mmutop == 0){
pg = newpage(0, 0, 0);
pg->va = VA(kmap(pg));
memmove((void*)pg->va, (void*)ktoppg.va, BY2PG);
- p->mmutop = pg;
+ up->mmutop = pg;
}
- top = (ulong*)p->mmutop->va;
+ top = (ulong*)up->mmutoup->va;
topoff = TOPOFF(va);
/*
@@ 295,20 282,20 @@ putmmu(ulong va, ulong pa, Page *pg)
*/
s = splhi();
if(PPN(top[topoff]) == 0){
- if(p->mmufree == 0){
+ if(up->mmufree == 0){
spllo();
pg = newpage(1, 0, 0);
pg->va = VA(kmap(pg));
splhi();
} else {
- pg = p->mmufree;
- p->mmufree = pg->next;
+ pg = up->mmufree;
+ up->mmufree = pg->next;
memset((void*)pg->va, 0, BY2PG);
}
top[topoff] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE;
pg->daddr = topoff;
- pg->next = p->mmuused;
- p->mmuused = pg;
+ pg->next = up->mmuused;
+ up->mmuused = pg;
}
/*
@@ 318,20 305,10 @@ putmmu(ulong va, ulong pa, Page *pg)
pt[BTMOFF(va)] = pa | PTEUSER;
/* flush cached mmu entries */
- putcr3(p->mmutop->pa);
+ taskswitch(up->mmutoup->pa, up->kstack);
splx(s);
}
-void
-invalidateu(void)
-{
- /* unmap u area */
- upt[0] = 0;
-
- /* flush cached mmu entries */
- putcr3(ktoppg.pa);
-}
-
/*
* allocate some address space (already mapped into the kernel)
* for ISA bus memory.
@@ 351,3 328,33 @@ isamem(int len)
unlock(&isamemalloc);
return a;
}
+
+/*
+ * used to map a page into 16 meg - BY2PG for confinit(). tpt is the temporary
+ * page table set up by l.s.
+ */
+long*
+mapaddr(ulong addr)
+{
+ ulong base;
+ ulong off;
+ static ulong *pte, top;
+ extern ulong tpt[];
+
+ if(pte == 0){
+ top = (((ulong)tpt)+(BY2PG-1))&~(BY2PG-1);
+ pte = (ulong*)top;
+ top &= ~KZERO;
+ top += BY2PG;
+ pte += (4*1024*1024-BY2PG)>>PGSHIFT;
+ }
+
+ base = off = addr;
+ base &= ~(KZERO|(BY2PG-1));
+ off &= BY2PG-1;
+
+ *pte = base|PTEVALID|PTEKERNEL|PTEWRITE; /**/
+ putcr3((ulong)top);
+
+ return (long*)(KZERO | 4*1024*1024-BY2PG | off);
+}
A pc/scsi.c => pc/scsi.c +84 -0
@@ 0,0 1,84 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+/*
+ * Known to devscsi.c.
+int scsidebugs[8];
+int scsiownid = CtlrID;
+ */
+
+void
+initscsi(void)
+{
+}
+
+/*
+ * Quick hack. Need to do a better job of dynamic initialisation
+ * for machines with peculiar memory/cache restictions.
+ * Also, what about 16Mb address limit on the Adaptec?
+ */
+static ulong bufdatasize;
+
+void
+scsibufreset(ulong datasize)
+{
+ bufdatasize = datasize;
+}
+
+Scsibuf *
+scsibuf(void)
+{
+ Scsibuf *b;
+
+ b = smalloc(sizeof(*b));
+ b->virt = smalloc(bufdatasize);
+ b->phys = (void *)(PADDR(b->virt));
+ return b;
+}
+
+void
+scsifree(Scsibuf *b)
+{
+ free(b->virt);
+ free(b);
+}
+
+/*
+ * Hack for devvid
+ */
+Scsibuf *
+scsialloc(ulong n)
+{
+ Scsibuf *b;
+
+ b = smalloc(sizeof(*b));
+ b->virt = smalloc(n);
+ b->phys = (void *)(PADDR(b->virt));
+ return b;
+}
+
+extern int (*aha1542reset(void))(Scsi*, int);
+extern int (*ultra14freset(void))(Scsi*, int);
+
+static int (*exec)(Scsi*, int);
+
+int
+scsiexec(Scsi *p, int rflag)
+{
+ if(exec == 0)
+ error(Enonexist);
+ return (*exec)(p, rflag);
+}
+
+void
+resetscsi(void)
+{
+ if(exec = aha1542reset())
+ return;
+ exec = ultra14freset();
+}
M pc/trap.c => pc/trap.c +91 -73
@@ 98,12 98,12 @@ debugbpt(Ureg *ur)
{
char buf[ERRLEN];
- if(u == 0)
+ if(up == 0)
panic("kernel bpt");
/* restore pc to instruction that caused the trap */
ur->pc--;
sprint(buf, "sys: breakpoint");
- postnote(u->p, 1, buf, NDebug);
+ postnote(up->p, 1, buf, NDebug);
}
/*
@@ 218,6 218,9 @@ char *excname[] =
[13] "general protection violation",
};
+Ureg lasttrap, *lastur;
+
+
/*
* All traps
*/
@@ 233,7 236,7 @@ trap(Ureg *ur)
user = ((ur->cs)&0xffff)!=KESEL && v!=Syscallvec;
if(user)
- u->dbgreg = ur;
+ up->dbgreg = ur;
/*
* tell the 8259 that we're done with the
@@ 248,6 251,8 @@ trap(Ureg *ur)
}
if(v>=256 || (h = halloc.ivec[v]) == 0){
+lasttrap = *ur;
+lastur = ur;
/* an old 386 generates these fairly often, no idea why */
if(v == 13)
return;
@@ 256,7 261,7 @@ trap(Ureg *ur)
if(v <= 16){
if(user){
sprint(buf, "sys: trap: %s", excname[v]);
- postnote(u->p, 1, buf, NDebug);
+ postnote(up->p, 1, buf, NDebug);
return;
} else {
dumpregs(ur);
@@ 267,7 272,7 @@ trap(Ureg *ur)
if(v >= Int0vec || v < Int0vec+16){
/* an unknown interrupts */
v -= Int0vec;
- if(badintr[v]++ == 0 || (badintr[v]%1000) == 0)
+ if(badintr[v]++ == 0 || (badintr[v]%100000) == 0)
print("unknown interrupt %d pc=0x%lux: total %d\n", v,
ur->pc, badintr[v]);
} else {
@@ 284,21 289,24 @@ trap(Ureg *ur)
} while(h);
/* check user since syscall does its own notifying */
- if(user && (u->p->procctl || u->nnote))
+ splhi();
+ if(user && (up->procctl || up->nnote))
notify(ur);
+lasttrap = *ur;
+lastur = ur;
}
/*
* dump registers
*/
void
-dumpregs(Ureg *ur)
+dumpregs2(Ureg *ur)
{
- if(u)
- print("registers for %s %d\n", u->p->text, u->p->pid);
+ if(up)
+ print("registers for %s %d\n", up->text, up->pid);
else
print("registers for kernel\n");
- print("FLAGS=%lux ECODE=%lux CS=%lux PC=%lux", ur->flags,
+ print("FLAGS=%lux TRAP=%lux ECODE=%lux CS=%lux PC=%lux", ur->flags, ur->trap,
ur->ecode, ur->cs&0xff, ur->pc);
if(ur == (Ureg*)UREGADDR)
print(" SS=%lux USP=%lux\n", ur->ss&0xff, ur->usp);
@@ 310,6 318,16 @@ dumpregs(Ureg *ur)
ur->si, ur->di, ur->bp);
print(" DS %4.4ux ES %4.4ux FS %4.4ux GS %4.4ux\n",
ur->ds&0xffff, ur->es&0xffff, ur->fs&0xffff, ur->gs&0xffff);
+
+}
+
+void
+dumpregs(Ureg *ur)
+{
+ dumpregs2(ur);
+ print(" ur %lux\n", ur);
+ dumpregs2(&lasttrap);
+ print(" lastur %lux\n", lastur);
}
void
@@ 318,11 336,11 @@ dumpstack(void)
ulong l, v, i;
extern ulong etext;
- if(u == 0)
+ if(up == 0)
return;
i = 0;
- for(l=(ulong)&l; l<USERADDR+BY2PG; l+=4){
+ for(l=(ulong)&l; l<up->kstack+BY2PG; l+=4){
v = *(ulong*)l;
if(KTZERO < v && v < (ulong)&etext){
print("%lux ", v);
@@ 369,52 387,52 @@ syscall(Ureg *ur)
long ret;
int i;
- u->p->insyscall = 1;
- u->p->pc = ur->pc;
+ up->insyscall = 1;
+ up->pc = ur->pc;
if((ur->cs)&0xffff == KESEL)
panic("recursive system call");
- u->scallnr = ur->ax;
- if(u->scallnr == RFORK && u->p->fpstate == FPactive){
+ up->scallnr = ur->ax;
+ if(up->scallnr == RFORK && up->fpstate == FPactive){
/*
* so that the child starts out with the
* same registers as the parent
*/
splhi();
- if(u->p->fpstate == FPactive){
- fpsave(&u->fpsave);
- u->p->fpstate = FPinactive;
+ if(up->fpstate == FPactive){
+ fpsave(&up->fpsave);
+ up->fpstate = FPinactive;
}
spllo();
}
sp = ur->usp;
- u->nerrlab = 0;
+ up->nerrlab = 0;
ret = -1;
if(!waserror()){
- if(u->scallnr >= sizeof systab/BY2WD){
- pprint("bad sys call number %d pc %lux\n", u->scallnr, ur->pc);
- postnote(u->p, 1, "sys: bad sys call", NDebug);
+ if(up->scallnr >= sizeof systab/BY2WD){
+ pprint("bad sys call number %d pc %lux\n", up->scallnr, ur->pc);
+ postnote(up->p, 1, "sys: bad sys call", NDebug);
error(Ebadarg);
}
if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-(1+MAXSYSARG)*BY2WD))
validaddr(sp, (1+MAXSYSARG)*BY2WD, 0);
- u->s = *((Sargs*)(sp+1*BY2WD));
- u->p->psstate = sysctab[u->scallnr];
+ up->s = *((Sargs*)(sp+1*BY2WD));
+ up->psstate = sysctab[up->scallnr];
- ret = (*systab[u->scallnr])(u->s.args);
+ ret = (*systab[up->scallnr])(up->s.args);
poperror();
}
- if(u->nerrlab){
- print("bad errstack [%d]: %d extra\n", u->scallnr, u->nerrlab);
+ if(up->nerrlab){
+ print("bad errstack [%d]: %d extra\n", up->scallnr, up->nerrlab);
for(i = 0; i < NERR; i++)
- print("sp=%lux pc=%lux\n", u->errlab[i].sp, u->errlab[i].pc);
+ print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
panic("error stack");
}
- u->p->insyscall = 0;
- u->p->psstate = 0;
+ up->insyscall = 0;
+ up->psstate = 0;
/*
* Put return value in frame. On the safari the syscall is
@@ 424,11 442,11 @@ syscall(Ureg *ur)
*/
ur->ax = ret;
- if(u->scallnr == NOTED)
+ if(up->scallnr == NOTED)
noted(ur, *(ulong*)(sp+BY2WD));
splhi(); /* avoid interrupts during the iret */
- if(u->scallnr!=RFORK && (u->p->procctl || u->nnote))
+ if(up->scallnr!=RFORK && (up->procctl || up->nnote))
notify(ur);
return ret;
@@ 445,61 463,61 @@ notify(Ureg *ur)
ulong s, sp;
Note *n;
- if(u->p->procctl)
- procctl(u->p);
- if(u->nnote == 0)
+ if(up->procctl)
+ procctl(up->p);
+ if(up->nnote == 0)
return 0;
s = spllo();
- qlock(&u->p->debug);
- u->p->notepending = 0;
- n = &u->note[0];
+ qlock(&up->debug);
+ up->notepending = 0;
+ n = &up->note[0];
if(strncmp(n->msg, "sys:", 4) == 0){
l = strlen(n->msg);
if(l > ERRLEN-15) /* " pc=0x12345678\0" */
l = ERRLEN-15;
sprint(n->msg+l, " pc=0x%.8lux", ur->pc);
}
- if(n->flag!=NUser && (u->notified || u->notify==0)){
+ if(n->flag!=NUser && (up->notified || up->notify==0)){
+ qunlock(&up->debug);
if(n->flag == NDebug)
pprint("suicide: %s\n", n->msg);
- qunlock(&u->p->debug);
pexit(n->msg, n->flag!=NDebug);
}
sent = 0;
- if(!u->notified){
- if(!u->notify){
- qunlock(&u->p->debug);
+ if(!up->notified){
+ if(!up->notify){
+ qunlock(&up->debug);
pexit(n->msg, n->flag!=NDebug);
}
sent = 1;
- u->svcs = ur->cs;
- u->svss = ur->ss;
- u->svflags = ur->flags;
+ up->svcs = ur->cs;
+ up->svss = ur->ss;
+ up->svflags = ur->flags;
sp = ur->usp;
sp -= sizeof(Ureg);
- if(!okaddr((ulong)u->notify, 1, 0)
+ if(!okaddr((ulong)up->notify, 1, 0)
|| !okaddr(sp-ERRLEN-3*BY2WD, sizeof(Ureg)+ERRLEN-3*BY2WD, 0)){
+ qunlock(&up->debug);
pprint("suicide: bad address in notify\n");
- qunlock(&u->p->debug);
pexit("Suicide", 0);
}
- u->ureg = (void*)sp;
+ up->ureg = (void*)sp;
memmove((Ureg*)sp, ur, sizeof(Ureg));
sp -= ERRLEN;
- memmove((char*)sp, u->note[0].msg, ERRLEN);
+ memmove((char*)sp, up->note[0].msg, ERRLEN);
sp -= 3*BY2WD;
*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
- *(ulong*)(sp+1*BY2WD) = (ulong)u->ureg; /* arg 1 is ureg* */
+ *(ulong*)(sp+1*BY2WD) = (ulong)up->ureg; /* arg 1 is ureg* */
*(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
ur->usp = sp;
- ur->pc = (ulong)u->notify;
- u->notified = 1;
- u->nnote--;
- memmove(&u->lastnote, &u->note[0], sizeof(Note));
- memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note));
+ ur->pc = (ulong)up->notify;
+ up->notified = 1;
+ up->nnote--;
+ memmove(&up->lastnote, &up->note[0], sizeof(Note));
+ memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
}
- qunlock(&u->p->debug);
+ qunlock(&up->debug);
splx(s);
return sent;
}
@@ 512,43 530,43 @@ noted(Ureg *ur, ulong arg0)
{
Ureg *nur;
- nur = u->ureg; /* pointer to user returned Ureg struct */
- if(nur->cs!=u->svcs || nur->ss!=u->svss
- || (nur->flags&0xff00)!=(u->svflags&0xff00)){
+ nur = up->ureg; /* pointer to user returned Ureg struct */
+ if(nur->cs!=up->svcs || nur->ss!=up->svss
+ || (nur->flags&0xff00)!=(up->svflags&0xff00)){
pprint("bad noted ureg cs %ux ss %ux flags %ux\n", nur->cs, nur->ss,
nur->flags);
Die:
pexit("Suicide", 0);
}
- qlock(&u->p->debug);
- if(!u->notified){
+ qlock(&up->debug);
+ if(!up->notified){
pprint("call to noted() when not notified\n");
- qunlock(&u->p->debug);
+ qunlock(&up->debug);
return;
}
- u->notified = 0;
- nur->flags = (u->svflags&0xffffff00) | (nur->flags&0xff);
+ up->notified = 0;
+ nur->flags = (up->svflags&0xffffff00) | (nur->flags&0xff);
memmove(ur, nur, sizeof(Ureg));
switch(arg0){
case NCONT:
if(!okaddr(nur->pc, 1, 0) || !okaddr(nur->usp, BY2WD, 0)){
pprint("suicide: trap in noted\n");
- qunlock(&u->p->debug);
+ qunlock(&up->debug);
goto Die;
}
- qunlock(&u->p->debug);
+ qunlock(&up->debug);
return;
default:
pprint("unknown noted arg 0x%lux\n", arg0);
- u->lastnote.flag = NDebug;
+ up->lastnote.flag = NDebug;
/* fall through */
case NDFLT:
- if(u->lastnote.flag == NDebug)
- pprint("suicide: %s\n", u->lastnote.msg);
- qunlock(&u->p->debug);
- pexit(u->lastnote.msg, u->lastnote.flag!=NDebug);
+ if(up->lastnote.flag == NDebug)
+ pprint("suicide: %s\n", up->lastnote.msg);
+ qunlock(&up->debug);
+ pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
}
}
A pc/ultrastor.c => pc/ultrastor.c +484 -0
@@ 0,0 1,484 @@
+/*
+ * Ultrastor [13]4f SCSI Host Adapter.
+ * Originally written by Charles Forsyth, forsyth@minster.york.ac.uk.
+ * Needs work:
+ * handle multiple controllers;
+ * set options from user-level;
+ * split out to handle adaptec too;
+ */
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#include "ureg.h"
+
+typedef struct Ctlr Ctlr;
+typedef struct Mailbox Mailbox;
+typedef struct Scatter Scatter;
+
+enum {
+ Nctl = 1, /* only support one */
+ Nmbox = 8, /* number of Mailboxes; up to 16? */
+ Nscatter = 33, /* s/g list limit fixed by Ultrastor controller */
+
+ Port = 0x330, /* factory defaults: I/O port */
+ CtlrID = 7, /* adapter SCSI id */
+ Irq = 14, /* interrupt request level */
+};
+
+struct Scatter {
+ ulong start; /* physical address; Intel byte order */
+ ulong len; /* length in bytes; Intel byte order */
+};
+
+/*
+ * Ultrastor mailbox pointers point to one of these structures
+ */
+struct Mailbox {
+ uchar op; /* Adapter operation */
+ uchar addr; /* lun, chan, scsi ID */
+ uchar datap[4]; /* transfer data phys. pointer */
+ uchar datalen[4]; /* transfer data length */
+ uchar cmdlink[4]; /* command link phys. pointer */
+ uchar linkid; /* SCSI command link ID */
+ uchar nscatter; /* scatter/gather length (8 bytes per entry) */
+ uchar senselen; /* length of sense data */
+ uchar cmdlen; /* length of CDB */
+ uchar cmd[12]; /* SCSI command */
+ uchar adapterstatus;
+ uchar targetstatus;
+ uchar sensep[4]; /* sense data phys. pointer */
+
+ /* the remainder is used by software, not the device */
+ uchar sensedata[64]; /* enough for AdapterInquiry data too */
+ Scatter sglist[Nscatter];
+ Rendez iodone;
+ int busy; /* interrupt pending */
+ ulong physaddr; /* physical address of this Mailbox */
+ int p9status; /* p9 status value */
+ Mailbox *next; /* next Mailbox in free list */
+};
+
+/* pack pointer as Intel order bytes (can simply assign) */
+#define PL(buf,p) (*(ulong*)(buf)=(ulong)(p))
+
+enum {
+ /* bits in Mailbox.op[0] */
+ /* 3 bit opcode */
+ OpAdapter = 0x01, /* adapter command, not SCSI command */
+ OpTarget = 0x02, /* SCSI command for device */
+ OpReset = 0x04, /* device reset */
+ /* 2 bit transfer direction */
+ CmdDirection = 0<<3, /* transfer direction determined by SCSI command */
+ DataIn = 1<<3, /* SCSI Data In */
+ DataOut = 2<<3, /* SCSI Data Out */
+ NoTransfer = 3<<3,
+ Nodiscon= 1<<5, /* disable disconnect */
+ Usecache= 1<<6, /* use adapter cache (if available) */
+ Scattered= 1<<7, /* transfer pointer refers to S/G list */
+
+ /* OpAdapter commands in Mailbox.cmd[0] */
+ AdapterInquiry = 0x01,
+ AdapterSelftest = 0x02,
+ AdapterRead = 0x03, /* read adapter's buffer */
+ AdapterWrite = 0x04, /* write to adapter's buffer */
+
+ /* IO port offsets and bits */
+ AdapterMask = 0x00, /* local doorbell mask register */
+ OGMIntEnable = 0x01,
+ SoftResetEnable = 0x40,
+ AdapterReady = 0xe1, /* adapter ready for work when all these set */
+ AdapterIntr = 0x01, /* adapter interrupt/status; set by host, reset by adapter */
+ SignalAdapter = 0x01, /* tell adapter to read OGMpointer */
+ BusReset = 0x20, /* SCSI Bus Reset */
+ SoftReset = 0x40, /* Adapter Soft Reset */
+ HostMask = 0x02, /* host doorbell mask register */
+ ICMIntEnable = 0x01, /* incoming mail enable */
+ SIntEnable = 0x80, /* enable interrupt from HostIntr reg */
+ HostIntr = 0x03, /* host doorbell interrupt/status; set by adapter, reset by host */
+ IntPending = 0x80, /* interrupt pending for host */
+ SignalHost = 0x01, /* Incoming Mail Interrupt */
+ ProductID = 0x04, /* two byte product ID */
+ Config1 = 0x06,
+ Config2 = 0x07,
+ OGMpointer = 0x08, /* pointer to Outgoing Mail */
+ ICMpointer = 0x0c, /* pointer to Incoming Mail */
+};
+
+#define OUT(c,v) outb(ctlr->io+(c), (v))
+#define IN(c) inb(ctlr->io+(c))
+
+struct Ctlr {
+ Lock;
+ QLock;
+ int io; /* io port */
+ int irq; /* interrupt vector */
+ int dma; /* DMA channel */
+ int ownid; /* adapter's SCSI ID */
+ Mailbox mbox[Nmbox];
+ Mailbox *free; /* next free Mailbox */
+ Rendez mboxes; /* wait for free mbox */
+ QLock mboxq; /* mutex for mboxes */
+ Rendez ogm; /* wait for free OGM slot with Ctlr qlocked */
+};
+
+static Ctlr ultra[Nctl];
+
+int scsidebugs[8] = {0};
+int scsiownid = 7;
+
+static void
+prmbox(Mailbox *m)
+{
+ int i;
+
+ print("scsi %lx: op=%2.2x dir=%x cmd=%d [", m->physaddr, m->op&07, (m->op>>3)&3, m->cmdlen);
+ for(i=0; i<m->cmdlen; i++)
+ print(" %2.2x", m->cmd[i]);
+ print("] id=%d lun=%d chan=%d", m->addr&7, (m->addr>>5)&7, (m->addr>>3)&3);
+ print(" dlen=%lx dptr=%lx\n", *(long*)m->datalen, *(long*)m->datap);
+ print(" astat=%2.2x dstat=%2.2x sc=%d [", m->adapterstatus, m->targetstatus, m->nscatter);
+ for(i=0; i<m->nscatter; i++)
+ print(" %lx,%ld", m->sglist[i].start, m->sglist[i].len);
+ print("]\n");
+ /*for(i=0; i<10; i++)
+ print(" %2.2x", m->sensedata[i]);*/
+ print("\n");
+}
+
+static void
+resetadapter(int busreset)
+{
+ Ctlr *ctlr = &ultra[0];
+ int i;
+
+ if(IN(AdapterMask) & SoftResetEnable){
+ OUT(AdapterIntr, SoftReset|busreset);
+ for(i=50000; IN(AdapterIntr) & (SoftReset|busreset);)
+ if(--i<0) {
+ print("Ultrastor reset timed out\n");
+ break;
+ }
+ }
+}
+
+static void
+freebox(Ctlr *ctlr, Mailbox *m)
+{
+ lock(ctlr);
+ if((m->next = ctlr->free) == 0)
+ wakeup(&ctlr->mboxes);
+ ctlr->free = m;
+ unlock(ctlr);
+}
+
+static int
+boxavail(void *a)
+{
+ return ((Ctlr*)a)->free != 0;
+}
+
+static int
+scatter(Scatter *list, void *va, ulong nb)
+{
+ char *p = (char *)va;
+ Scatter *sp = list;
+ int limit = Nscatter;
+
+ for(; nb != 0; sp++){
+ if(--limit < 0)
+ panic("Ultrastor I/O too scattered");
+ sp->start = PADDR(p);
+ sp->len = BY2PG - (sp->start&(BY2PG-1)); /* the rest of that page */
+ if(sp->len > nb)
+ sp->len = nb;
+ nb -= sp->len;
+ p += sp->len;
+ }
+ return sp - list;
+}
+
+static int
+isready(void *a)
+{
+ Ctlr *ctlr = (Ctlr*)a;
+
+ return (IN(AdapterIntr) & SignalAdapter) == 0;
+}
+
+static int
+isdone(void *a)
+{
+ return ((Mailbox*)a)->busy == 0;
+}
+
+static int
+ultra14fexec(Scsi *p, int rflag)
+{
+ Ctlr *ctlr = &ultra[0];
+ Mailbox *m;
+ long n;
+ uchar *cp;
+
+ if (p == 0 || ctlr->io == 0)
+ return 0x0200; /* device not available */
+
+ /*
+ * get a free Mailbox and build an Ultrastor command
+ */
+ while(lock(ctlr), (m = ctlr->free) == 0){
+ unlock(ctlr);
+ qlock(&ctlr->mboxq);
+ if(waserror()){
+ qunlock(&ctlr->mboxq);
+ nexterror();
+ }
+ sleep(&ctlr->mboxes, boxavail, ctlr);
+ poperror();
+ qunlock(&ctlr->mboxq);
+ }
+ ctlr->free = m->next;
+ unlock(ctlr);
+ p->rflag = rflag;
+ m->p9status = 0;
+ m->op = OpTarget | CmdDirection | Usecache; /* BUG? is it safe always to Usecache? */
+ m->addr = p->target | (p->lun<<5);
+ if(p->cmd.lim - p->cmd.ptr > sizeof(m->cmd))
+ panic("scsiexec");
+ m->cmdlen = p->cmd.lim - p->cmd.ptr;
+ for(cp = m->cmd; p->cmd.ptr < p->cmd.lim;)
+ *cp++ = *p->cmd.ptr++;
+ n = p->data.lim - p->data.ptr;
+ if(n){
+ PL(m->datap, PADDR(m->sglist));
+ m->op |= Scattered;
+ m->nscatter = scatter(m->sglist, p->data.ptr, n);
+ } else {
+ m->nscatter = 0; /* controller will not allow s/g when n==0 */
+ PL(m->datap, 0);
+ }
+ PL(m->datalen, n);
+ m->adapterstatus = 0;
+ m->targetstatus = 0;
+
+ /*
+ * send the command to the host adapter
+ */
+ while(lock(ctlr), IN(AdapterIntr) & SignalAdapter) { /* adapter busy: infrequent? */
+ static int fred;
+ if(fred == 0){
+ print("ultrastor busy\n");
+ fred = 1;
+ }
+ unlock(ctlr);
+ qlock(ctlr);
+ if(waserror()) {
+ freebox(ctlr, m);
+ qunlock(ctlr);
+ nexterror();
+ }
+ sleep(&ctlr->ogm, isready, ctlr);
+ poperror();
+ qunlock(ctlr);
+ }
+ m->busy = 1;
+ outl(ctlr->io+OGMpointer, m->physaddr);
+ OUT(AdapterIntr, SignalAdapter);
+ unlock(ctlr);
+
+ /*
+ * wait for reply
+ */
+ while(waserror())
+ ; /* could send MSCP abort request to adapter */
+ while(m->busy)
+ sleep(&m->iodone, isdone, m);
+ poperror();
+ p->status = m->p9status;
+ if(scsidebugs[2])
+ prmbox(m);
+ if(p->status == 0x6000)
+ p->data.ptr = p->data.lim; /* can only assume no residue */
+ freebox(ctlr, m);
+ return p->status;
+}
+
+static void
+scsimoan(char *msg, Mailbox *m)
+{
+ /*int i;*/
+
+ print("SCSI error: %s:", msg);
+ print("id=%d cmd=%2.2x status=%2.2x adapter=%2.2x", m->addr&7, m->cmd[0], m->targetstatus, m->adapterstatus);
+ /*print(" sense:");
+ for(i=0; i<10; i++)
+ print(" %2.2x", m->sensedata[i]);*/
+ print("\n");
+}
+
+static void
+interrupt(Ureg *ur)
+{
+ Ctlr *ctlr = &ultra[0];
+ Mailbox *m;
+ ulong pa;
+
+ USED(ur);
+ if(ctlr->ogm.p && (IN(AdapterIntr) & SignalAdapter) == 0)
+ wakeup(&ctlr->ogm);
+ if((IN(HostIntr) & SignalHost) == 0)
+ return; /* no incoming mail */
+ pa = inl(ctlr->io+ICMpointer);
+ OUT(HostIntr, SignalHost); /* release ICM slot */
+ for(m = &ctlr->mbox[0]; m->physaddr != pa;)
+ if(++m >= &ctlr->mbox[Nmbox]) {
+ /* these sometimes happen in response to a scsi bus reset; ignore them */
+ print("ultrastor: invalid ICM pointer #%lux\n", pa);
+ return;
+ }
+ if(scsidebugs[1])
+ prmbox(m);
+
+ m->p9status = 0x1000 | m->adapterstatus;
+ switch(m->adapterstatus){
+ default:
+ scsimoan("adapter", m);
+ if(m->adapterstatus >= 0x92) /* ie, scsi command protocol error */
+ resetadapter(BusReset);
+ /* might adapter reset be required in other cases? */
+ break;
+
+ case 0x91: /* selection timed out */
+ m->p9status = 0x0200;
+ if(scsidebugs[0])
+ scsimoan("timeout", m);
+ break;
+
+ case 0xA3:
+ scsimoan("SCSI bus reset error", m);
+ break;
+
+ case 0x00:
+ m->p9status = 0x6000 | m->targetstatus;
+ if(m->targetstatus && scsidebugs[0])
+ scsimoan("device", m);
+ break;
+ }
+ m->busy = 0;
+ wakeup(&m->iodone);
+}
+
+static ISAConf ultra14f = {
+ "ultra14f",
+ Port,
+ Irq,
+ 0,
+ 0,
+};
+
+static int irq[4] = {
+ 15, 14, 11, 10,
+};
+
+int (*
+ultra14freset(void))(Scsi*, int)
+{
+ ISAConf *isa = &ultra14f;
+ Ctlr *ctlr = &ultra[0];
+ Mailbox *m;
+ int i, model;
+
+ /*
+ * See if we have any configuration info
+ * and check it is an Ultrastor [13]4f.
+ * Only one controller for now.
+ */
+ if(isaconfig("scsi", 0, &ultra14f) == 0)
+ return 0;
+ memset(ctlr, 0, sizeof(Ctlr));
+ ctlr->io = isa->port;
+
+ if(IN(ProductID) != 0x56)
+ return 0;
+ model = IN(ProductID+1);
+ switch(model){
+
+ case 0x40:
+ model = 14;
+ break;
+
+ case 0x41:
+ model = 34;
+ break;
+
+ default:
+ return 0;
+ }
+
+ i = IN(Config1);
+ ctlr->irq = irq[((i>>4)&03)];
+ if(model == 14)
+ ctlr->dma = 5 + ((i>>6)&03);
+ ctlr->ownid = IN(Config2)&07;
+ /*print("Ultrastor %dF id %d io 0x%x irq %d dma %d\n",
+ model, ctlr->ownid, ctlr->io, ctlr->irq, ctlr->dma);*/
+
+ /*
+ * set the DMA controller to cascade mode for bus master
+ */
+ switch(ctlr->dma){
+ case 5:
+ outb(0xd6, 0xc1); outb(0xd4, 1); break;
+ case 6:
+ outb(0xd6, 0xc2); outb(0xd4, 2); break;
+ case 7:
+ outb(0xd6, 0xc3); outb(0xd4, 3); break;
+ }
+
+ resetadapter(0);
+ ctlr->free = 0;
+ for(i=0; i<Nmbox; i++){
+ m = &ctlr->mbox[i];
+ memset(m, 0, sizeof(*m));
+ m->physaddr = PADDR(m);
+ PL(m->sensep, 0); /* DON'T collect sense data automatically: messes up scuzz? */
+ m->senselen = 0;
+ m->next = ctlr->free;
+ ctlr->free = m;
+ }
+
+ setvec(Int0vec+ctlr->irq, interrupt);
+
+ /*
+ * issue AdapterInquiry command to check it's alive
+ * -- could check enquiry data
+ */
+ OUT(HostMask, 0); /* mask interrupts */
+ m = &ctlr->mbox[0];
+ m->op = OpAdapter | CmdDirection;
+ m->addr = ctlr->ownid;
+ m->cmdlen = 1;
+ m->cmd[0] = AdapterInquiry;
+ PL(m->datap, PADDR(m->sensedata));
+ PL(m->datalen, 38);
+ while(IN(AdapterIntr) & SignalAdapter)
+ ;
+ outl(ctlr->io+OGMpointer, m->physaddr);
+ OUT(AdapterIntr, SignalAdapter);
+ for(i=100000; (IN(HostIntr)&SignalHost)==0;)
+ if(--i < 0){
+ print("No response to UltraStor Inquiry\n");
+ ctlr->io = 0;
+ return 0;
+ }
+ OUT(HostIntr, SignalHost);
+
+ OUT(HostMask, ICMIntEnable|SIntEnable);
+ scsiownid = ctlr->ownid;
+
+ return ultra14fexec;
+}
M port/portdat.h => port/portdat.h +1 -1
@@ 488,7 488,7 @@ enum
*/
enum
{
- SSEG, TSEG, DSEG, BSEG, ESEG, LSEG, SEG1, SEG2, NSEG
+ SSEG, TSEG, DSEG, BSEG, ESEG, LSEG, SEG1, SEG2, SEG3, SEG4, NSEG
};
enum
M port/portfns.h => port/portfns.h +1 -1
@@ 113,6 113,7 @@ void kproftimer(ulong);
void ksetenv(char*, char*);
long latin1(uchar*);
void lights(int);
+void links(void);
void lock(Lock*);
void lockinit(void);
Page* lookpage(Image*, ulong);
@@ 199,7 200,6 @@ void resetscsi(void);
void resrcwait(char*);
int return0(void*);
void rlock(RWlock*);
-void rootfiles(void);
void rootrecover(Path*, char*);
void rootreq(Chan*, Mnt*);
void runlock(RWlock*);
M power/main.c => power/main.c +1 -1
@@ 38,8 38,8 @@ main(void)
initseg();
clockinit();
ioboardinit();
+ links();
chandevreset();
- rootfiles();
swapinit();
userinit();
launchinit();