M gnot/trap.c => gnot/trap.c +1 -0
@@ 148,6 148,7 @@ notify(Ureg *ur)
unlock(&u->p->debug);
return;
}
+ u->p->notepending = 0;
if(u->note[0].flag!=NUser && (u->notified || u->notify==0)){
if(u->note[0].flag == NDebug)
pprint("suicide: %s\n", u->note[0].msg);
A pc/devfloppy.c => pc/devfloppy.c +559 -0
@@ 0,0 1,559 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+
+typedef struct Drive Drive;
+typedef struct Controller Controller;
+typedef struct Type Type;
+
+enum
+{
+ Fmotor= 0x3f2, /* motor port */
+ Fintena= 0x4, /* enable floppy interrupt */
+ Fena= 0x8, /* 0 == reset controller */
+
+ Fstatus= 0x3f4, /* controller main status port */
+ Fready= 0x80, /* ready to be touched */
+ Ffrom= 0x40, /* data from controller */
+ Fbusy= 0x10, /* operation not over */
+
+ Fdata= 0x3f5, /* controller data port */
+ Frecal= 0x7, /* recalibrate cmd */
+ Fseek= 0xf, /* seek cmd */
+ Fsense= 0x8, /* sense cmd */
+ Fread= 0x66, /* read cmd */
+ Fwrite= 0x47, /* write cmd */
+ Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */
+
+ DMAmode0= 0xb,
+ DMAmode1= 0xc,
+ DMAaddr= 0x4,
+ DMAtop= 0x81,
+ DMAinit= 0xa,
+ DMAcount= 0x5,
+
+ Nfloppy= 4, /* floppies/controller */
+
+ /* sector size encodings */
+ S128= 0,
+ S256= 1,
+ S512= 2,
+ S1024= 3,
+
+ /* status 0 byte */
+ Drivemask= 3<<0,
+ Seekend= 1<<5,
+ Codemask= (3<<6)|(3<<3),
+};
+
+/*
+ * floppy types
+ */
+struct Type
+{
+ char *name;
+ int bytes; /* bytes/sector */
+ int sectors; /* sectors/track */
+ int heads; /* number of heads */
+ int steps; /* steps per cylinder */
+ int tracks; /* tracks/disk */
+ int gpl; /* intersector gap length for read/write */
+ int fgpl; /* intersector gap length for format */
+ long cap; /* drive capacity in bytes */
+};
+Type floppytype[] =
+{
+ { "MF2HD", S512, 18, 2, 1, 80, 0x1B, 0x54, 512*2*18*80 },
+ { "MF2DD", S512, 9, 2, 1, 80, 0x1B, 0x54, 512*2*9*80 },
+ { "F2HD", S512, 15, 2, 1, 80, 0x2A, 0x50, 512*15*2*80 },
+ { "F2DD", S512, 8, 2, 1, 40, 0x2A, 0x50, 512*8*2*40 },
+ { "F1DD", S512, 8, 1, 1, 40, 0x2A, 0x50, 512*8*1*40 },
+};
+static int secbytes[] =
+{
+ 128,
+ 256,
+ 512,
+ 1024
+};
+
+/*
+ * a floppy drive
+ */
+struct Drive
+{
+ QLock;
+ Type *t;
+ int dev;
+
+ ulong lasttouched; /* time last touched */
+ int motoron; /* motor is on */
+ int cyl; /* current cylinder */
+ long offset; /* current offset */
+ int confused; /* needs to be recalibrated (or worse) */
+
+ int tcyl; /* target cylinder */
+ int thead; /* target head */
+ int tsec; /* target sector */
+ long len;
+
+ int busy; /* true if drive is seeking */
+ Rendez r; /* waiting for operation termination */
+};
+
+/*
+ * NEC PD765A controller for 4 floppys
+ */
+struct Controller
+{
+ QLock;
+ Drive d[Nfloppy]; /* the floppy drives */
+ int busy; /* true if a read or write in progress */
+ uchar stat[8]; /* status of an operation */
+ int confused;
+};
+
+Controller floppy[1];
+
+/*
+ * start a floppy drive's motor. set an alarm for 1 second later to
+ * mark it as started (we get no interrupt to tell us).
+ *
+ * assume the caller qlocked the drive.
+ */
+void
+floppystart(Drive *dp)
+{
+ int cmd;
+
+ dp->lasttouched = m->ticks;
+ if(dp->motoron)
+ return;
+
+ cmd = (1<<(dp->dev+4)) | Fintena | Fena | dp->dev;
+ outb(Fmotor, cmd);
+ dp->busy = 1;
+ tsleep(&dp->r, noreturn, 0, 1000);
+ dp->motoron = 1;
+ dp->busy = 0;
+ dp->lasttouched = m->ticks;
+}
+
+/*
+ * stop the floppy if it hasn't been used in 5 seconds
+ */
+void
+floppystop(Drive *dp)
+{
+ int cmd;
+
+ if(!canqlock(dp))
+ return;
+ cmd = Fintena | Fena | dp->dev;
+ outb(Fmotor, cmd);
+ dp->motoron = 0;
+}
+void
+floppykproc(Alarm* a)
+{
+ Drive *dp;
+
+ if(waserror())
+ for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
+ if(dp->motoron && TK2SEC(m->ticks - dp->lasttouched) > 5)
+ floppystop(dp);
+ }
+
+ alarm(5*1000, floppyalarm, 0);
+ cancel(a);
+}
+
+int
+floppysend(int data)
+{
+ int tries;
+ uchar c;
+
+ for(tries = 0; tries < 100; tries++){
+ /*
+ * see if its ready for data
+ */
+ c = inb(Fstatus);
+ if((c&(Ffrom|Fready)) != Fready)
+ continue;
+
+ /*
+ * send the data
+ */
+ outb(Fdata, data);
+ return 0;
+ }
+ return -1;
+}
+
+int
+floppyrcv(void)
+{
+ int tries;
+ uchar c;
+
+ for(tries = 0; tries < 100; tries++){
+ /*
+ * see if its ready for data
+ */
+ c = inb(Fstatus);
+ if((c&(Ffrom|Fready)) != (Ffrom|Fready))
+ continue;
+
+ /*
+ * get data
+ */
+ return inb(Fdata)&0xff;
+ }
+ return -1;
+}
+
+int
+floppyrdstat(int n)
+{
+ int i;
+ int c;
+
+ for(i = 0; i < n; i++){
+ c = floppyrcv();
+ if(c < 0)
+ return -1;
+ floppy.stat[i] = c;
+ }
+ return 0;
+}
+
+void
+floppypos(Drive *dp, long off)
+{
+ int lsec;
+ int end;
+ int cyl;
+
+ lsec = off/secbytes[dp->t->bytes];
+ dp->tcyl = lsec/(dp->t->sectors*dp->t->heads);
+ dp->tsec = (lsec % dp->t->sectors) + 1;
+ dp->thead = (lsec/dp->t->sectors) % dp->t->heads;
+
+ /*
+ * can't read across cylinder boundaries.
+ * if so, decrement the bytes to be read.
+ */
+ lsec = (off+dp->len)/secbytes[dp->t->bytes];
+ cyl = lsec/(dp->t->sectors*dp->t->heads);
+ if(cyl != dp->tcyl){
+ dp->len -= (lsec % dp->t->sectors)*secbytes[dp->t->bytes];
+ dp->len -= ((lsec/dp->t->sectors) % dp->t->heads)*secbytes[dp->t->bytes]
+ *dp->t->sectors;
+ }
+
+ dp->lasttouched = m->ticks;
+ floppy.intr = 0;
+}
+
+void
+floppywait(void)
+{
+ int tries;
+
+ for(tries = 0; tries < 100 && floppy.intr == 0; tries++)
+ delay(5);
+ if(tries >= 100)
+ print("tired floopy\n");
+ floppy.intr = 0;
+}
+
+int
+floppysense(Drive *dp)
+{
+ /*
+ * ask for floppy status
+ */
+ if(floppysend(Fsense) < 0){
+ floppy.confused = 1;
+ return -1;
+ }
+ if(floppyrdstat(2) < 0){
+ floppy.confused = 1;
+ dp->confused = 1;
+ return -1;
+ }
+
+ /*
+ * make sure it's the right drive
+ */
+ if((floppy.stat[0] & Drivemask) != dp-floppy.d){
+ print("sense failed\n");
+ dp->confused = 1;
+ return -1;
+ }
+ return 0;
+}
+
+int
+floppyrecal(Drive *dp)
+{
+ floppy.intr = 0;
+ if(floppysend(Frecal) < 0
+ || floppysend(dp - floppy.d) < 0){
+ floppy.confused = 0;
+ return -1;
+ }
+ floppywait();
+
+ /*
+ * get return values
+ */
+ if(floppysense(dp) < 0)
+ return -1;
+
+ /*
+ * see if it worked
+ */
+ if((floppy.stat[0] & (Codemask|Seekend)) != Seekend){
+ print("recalibrate failed\n");
+ dp->confused = 1;
+ return -1;
+ }
+
+ /*
+ * see what cylinder we got to
+ */
+ dp->tcyl = 0;
+ dp->cyl = floppy.stat[1]/dp->t->steps;
+ if(dp->cyl != dp->tcyl){
+ print("recalibrate went to wrong cylinder %d\n", dp->cyl);
+ dp->confused = 1;
+ return -1;
+ }
+
+ dp->confused = 0;
+ return 0;
+}
+
+void
+floppyinit(void)
+{
+ Drive *dp;
+
+ for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
+ dp->t = &floppytype[0];
+ dp->cyl = -1;
+ dp->motoron = 1;
+ floppystop(dp);
+ }
+ setvec(22, floppyintr);
+ alarm(5*1000, floppyalarm, (void *)0);
+}
+
+void
+floppyreset(void)
+{
+ Drive *dp;
+
+ /*
+ * reset the floppy if'n it's confused
+ */
+ if(floppy.confused){
+ /* reset controller and turn all motors off */
+ floppy.intr = 0;
+ splhi();
+ outb(Fmotor, 0);
+ delay(1);
+ outb(Fmotor, Fintena|Fena);
+ spllo();
+ for(dp = floppy.d; dp < &floppy.d[Nfloppy]; dp++){
+ dp->motoron = 0;
+ dp->confused = 1;
+ }
+ floppywait();
+ floppy.confused = 0;
+ }
+
+ /*
+ * recalibrate any confused drives
+ */
+ for(dp = floppy.d; floppy.confused == 0 && dp < &floppy.d[Nfloppy]; dp++){
+ if(dp->confused == 0)
+ floppyrecal(dp);
+
+ }
+
+}
+
+long
+floppyseek(int dev, long off)
+{
+ Drive *dp;
+
+ dp = &floppy.d[dev];
+
+ if(floppy.confused || dp->confused)
+ floppyreset();
+
+ floppystart(dp);
+
+ floppypos(dp, off);
+ if(dp->cyl == dp->tcyl){
+ dp->offset = off;
+ return off;
+ }
+
+ /*
+ * tell floppy to seek
+ */
+ if(floppysend(Fseek) < 0
+ || floppysend((dp->thead<<2) | dev) < 0
+ || floppysend(dp->tcyl * dp->t->steps) < 0){
+ print("seek cmd failed\n");
+ floppy.confused = 1;
+ return -1;
+ }
+
+ /*
+ * wait for interrupt
+ */
+ floppywait();
+
+ /*
+ * get floppy status
+ */
+ if(floppysense(dp) < 0)
+ return -1;
+
+ /*
+ * see if it worked
+ */
+ if((floppy.stat[0] & (Codemask|Seekend)) != Seekend){
+ print("seek failed\n");
+ dp->confused = 1;
+ return -1;
+ }
+
+ /*
+ * see what cylinder we got to
+ */
+ dp->cyl = floppy.stat[1]/dp->t->steps;
+ if(dp->cyl != dp->tcyl){
+ print("seek went to wrong cylinder %d instead of %d\n", dp->cyl, dp->tcyl);
+ dp->confused = 1;
+ return -1;
+ }
+
+ dp->offset = off;
+ return dp->offset;
+}
+
+long
+floppyxfer(Drive *dp, int cmd, void *a, long n)
+{
+ int dev;
+ ulong addr;
+ long offset;
+
+ addr = (ulong)a;
+ dev = dp - floppy.d;
+
+ /*
+ * dma can't cross 64 k boundaries
+ */
+ if((addr & 0xffff0000) != ((addr+n) & 0xffff0000))
+ n -= (addr+n)&0xffff;
+
+ dp->len = n;
+ floppyseek(dev, dp->offset);
+
+/* print("tcyl %d, thead %d, tsec %d, addr %lux, n %d\n",
+ dp->tcyl, dp->thead, dp->tsec, addr, n);/**/
+
+ /*
+ * set up the dma
+ */
+ outb(DMAmode1, cmd==Fread ? 0x46 : 0x4a);
+ outb(DMAmode0, cmd==Fread ? 0x46 : 0x4a);
+ outb(DMAaddr, addr);
+ outb(DMAaddr, addr>>8);
+ outb(DMAtop, addr>>16);
+ outb(DMAcount, n-1);
+ outb(DMAcount, (n-1)>>8);
+ outb(DMAinit, 2);
+
+ /*
+ * tell floppy to go
+ */
+ cmd = cmd | (dp->t->heads > 1 ? Fmulti : 0);
+ if(floppysend(cmd) < 0
+ || floppysend((dp->thead<<2) | dev) < 0
+ || floppysend(dp->tcyl * dp->t->steps) < 0
+ || floppysend(dp->thead) < 0
+ || floppysend(dp->tsec) < 0
+ || floppysend(dp->t->bytes) < 0
+ || floppysend(dp->t->sectors) < 0
+ || floppysend(dp->t->gpl) < 0
+ || floppysend(0xFF) < 0){
+ print("xfer cmd failed\n");
+ floppy.confused = 1;
+ return -1;
+ }
+
+ floppywait();
+
+ /*
+ * get status
+ */
+ if(floppyrdstat(7) < 0){
+ print("xfer status failed\n");
+ floppy.confused = 1;
+ return -1;
+ }
+
+ if((floppy.stat[0] & Codemask)!=0 || floppy.stat[1] || floppy.stat[2]){
+print("xfer failed %lux %lux %lux\n", floppy.stat[0],
+ floppy.stat[1], floppy.stat[2]);
+ dp->confused = 1;
+ return -1;
+ }
+
+ offset = (floppy.stat[3]/dp->t->steps) * dp->t->heads + floppy.stat[4];
+ offset = offset*dp->t->sectors + floppy.stat[5] - 1;
+ offset = offset * secbytes[floppy.stat[6]];
+ if(offset != dp->offset+n){
+ print("new offset %d instead of %d\n", offset, dp->offset+dp->len);
+ dp->confused = 1;
+ return -1;/**/
+ }
+
+ dp->offset += dp->len;
+ return dp->len;
+}
+
+long
+floppyread(int dev, void *a, long n)
+{
+ Drive *dp;
+ long rv, i;
+ uchar *aa = a;
+
+ dp = &floppy.d[dev];
+ for(rv = 0; rv < n; rv += i){
+ i = floppyxfer(dp, Fread, aa+rv, n-rv);
+ if(i <= 0)
+ break;
+ }
+ return rv;
+}
+
+void
+floppyintr(Ureg *ur)
+{
+ floppy.intr = 1;
+}
M pc/headland.c => pc/headland.c +53 -0
@@ 18,6 18,35 @@ enum
};
/*
+ * ports used by the DMA controllers
+ */
+typedef struct DMA DMA;
+struct DMA {
+ uchar addr[4]; /* current address (4 channels) */
+ uchar count[4]; /* current count (4 channels) */
+ uchar page[4]; /* page registers (4 channels) */
+ uchar cmd; /* command status register */
+ uchar req; /* request registers */
+ uchar sbm; /* single bit mask register */
+ uchar mode; /* mode register */
+ uchar cbp; /* clear byte pointer */
+ uchar mc; /* master clear */
+ uchar cmask; /* clear mask register */
+ uchar wam; /* write all mask register bit */
+};
+
+DMA dma[2] = {
+ { 0x00, 0x02, 0x04, 0x06,
+ 0x01, 0x03, 0x05, 0x07,
+ 0x87, 0x83, 0x81, 0x82,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+ { 0xc0, 0xc6, 0xca, 0xce,
+ 0xc4, 0xc8, 0xcc, 0xcf,
+ 0x80, 0x8b, 0x89, 0x8a,
+ 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde },
+};
+
+/*
* enable address bit 20
*/
void
@@ 38,3 67,27 @@ exit(void)
print("exiting\n");
outb(Head, Reset);
}
+
+/*
+ * setup a dma transfer. return count actually set up. we DMA up
+ * to a page.
+ */
+long
+dmasetup(int d, int chan, Page *pg, long len, int isread)
+{
+ DMA *dp;
+ ulong addr;
+
+ dp = &dma[d];
+ addr = (ulong)a;
+ addr &= ~KZERO;
+
+ outb(dp->cbp, isread ? 0x46 : 0x4a);
+ outb(dp->mode, isread ? 0x46 : 0x4a);
+ outb(dp->addr, addr);
+ outb(dp->addr, addr>>8);
+ outb(dp->page, addr>>16);
+ outb(dp->count, len-1);
+ outb(dp->count, (len-1)>>8);
+ outb(dp->sbm, 2);
+}
M pc/main.c => pc/main.c +0 -1
@@ 19,7 19,6 @@ main(void)
screeninit();
printinit();
mmuinit();
- vgainit();
trapinit();
kbdinit();
clockinit();
M pc/trap.c => pc/trap.c +1 -0
@@ 279,6 279,7 @@ notify(Ureg *ur)
unlock(&u->p->debug);
return;
}
+ u->p->notepending = 0;
if(u->note[0].flag!=NUser && (u->notified || u->notify==0)){
if(u->note[0].flag == NDebug)
pprint("suicide: %s\n", u->note[0].msg);
M pc/vga.c => pc/vga.c +114 -16
@@ 8,44 8,142 @@
enum
{
GRX= 0x3CE, /* index to graphics registers */
- GR= 0x3CF, /* graphics registers 0-8 */
+ GR= 0x3CF, /* graphics registers */
+ Grot= 0x03, /* data rotate register */
+ Gmode= 0x05, /* mode register */
+ Gmisc= 0x06, /* miscillaneous register */
+ Grms= 0x04, /* read map select register */
SRX= 0x3C4, /* index to sequence registers */
- SR= 0x3C5, /* sequence registers 0-7 */
+ SR= 0x3C5, /* sequence registers */
+ Sclock= 0x01, /* clocking register */
+ Smode= 0x04, /* mode register */
+ Smmask= 0x02, /* map mask */
+ CRX= 0x3D4, /* index to crt registers */
+ CR= 0x3D5, /* crt registers */
+ Cmode= 0x17, /* mode register */
+ Cmsl= 0x09, /* max scan line */
+ ARX= 0x3C0, /* index to attribute registers */
+ AR= 0x3C1, /* attribute registers */
+ Amode= 0x10, /* mode register */
+ Acpe= 0x12, /* color plane enable */
};
+/*
+ * screen dimensions
+ */
+#define MAXX 640
+#define MAXY 480
+
+/*
+ * routines for setting vga registers
+ */
void
srout(int reg, int val)
{
outb(SRX, reg);
outb(SR, val);
}
-
void
grout(int reg, int val)
{
outb(GRX, reg);
outb(GR, val);
}
+void
+arout(int reg, int val)
+{
+ inb(0x3DA);
+ outb(ARX, reg | 0x20);
+ outb(AR, val);
+}
+void
+crout(int reg, int val)
+{
+ outb(CRX, reg);
+ outb(CR, val);
+}
+
+/*
+ * m is a bit mask of planes to be affected by CPU writes
+ */
+vgawrmask(int m)
+{
+ srout(Smmask, m&0xf);
+}
/*
- * look at VGA registers
+ * p is the plane that will respond to CPU reads
+ */
+vgardplane(int p)
+{
+ grout(Grms, p&3);
+}
+
+/*
+ * partial screen munching squares
+ */
+#define DELTA 1
+#define DADDR ((long *) 0)
+#define SIDE 256
+void
+munch(void)
+{
+ ulong x,y,i,d;
+ uchar *screen, tab[8], *p;
+
+ screen = (uchar *)(0xA0000 | KZERO);
+ d=0;
+ tab[0] = 0x80;
+ tab[1] = 0x40;
+ tab[2] = 0x20;
+ tab[3] = 0x10;
+ tab[4] = 0x08;
+ tab[5] = 0x04;
+ tab[6] = 0x02;
+ tab[7] = 0x01;
+
+ for(i=0; i<MAXY*(MAXX/8); i++)
+ screen[i]=0;
+
+ for(;;){
+ for(x=0; x<SIDE; x++){
+ y = (x^d) % SIDE;
+ p = &screen[y*(MAXX/8) + (x/8)];
+ y = *p;
+ *p = y ^ tab[x&7];
+ }
+ d+=DELTA;
+ }
+}
+
+/*
+ * Set up for 4 separately addressed bit planes. Each plane is
*/
void
vgainit(void)
{
uchar *display;
- int i;
+ int i, j, k;
+ int c;
- srout(2, 0x0f); /* enable all 4 color planes */
- srout(4, 0x08); /* quad mode */
- grout(5, 0x40); /* pixel bits are sequential */
- grout(6, 0x01); /* graphics mode - display starts at 0xA0000 */
+ display = (uchar *)(0xA0000 | KZERO);
+ arout(Acpe, 0x0f); /* enable all planes */
+ arout(Amode, 0x01); /* graphics mode - 4 bit pixels */
+ grout(Gmisc, 0x01); /* graphics mode */
+ grout(Gmode, 0x00); /* write mode 0, read mode 0 */
+ grout(Grot, 0x00); /* CPU writes bytes to video mem without modifications */
+ crout(Cmode, 0xe3); /* turn off address wrap & word mode */
+ crout(Cmsl, 0x40); /* 1 pixel per scan line */
+ srout(Smode, 0x06); /* extended memory, odd/even off */
+ srout(Sclock, 0x01); /* 8 bits/char */
- for(;;);
- display = (uchar*)(0xA0000 | KZERO);
- for(i = 0; i < 128*1024; i++)
- display[i] = 0x00;
-
- for(i = 0; i < 4*640; i++)
- display[i] = 0xff;
+ /*
+ * zero out display
+ */
+ srout(Smmask, 0x0f); /* enable all 4 color planes for writing */
+ for(i=0; i<MAXY*(MAXX/8); i++)
+ display[i] = 0;
+
+ munch();
}
+
M port/alarm.c => port/alarm.c +6 -6
@@ 73,8 73,8 @@ alarminit(void)
lock(&alarmtab[i]); /* allocate locks, as they are used at interrupt time */
unlock(&alarmtab[i]);
}
- qlock(&alarms);
- qunlock(&alarms);
+ lock(&alarms);
+ unlock(&alarms);
}
#define NA 10 /* alarms per clock tick */
@@ 111,7 111,7 @@ checkalarms(void)
unlock(&m->alarmlock);
}
- if(m == MACHP(0) && canqlock(&alarms)){
+ if(m == MACHP(0) && canlock(&alarms)){
now = MACHP(0)->ticks;
while((rp = alarms.head) && rp->alarm <= now){
if(rp->alarm != 0L){
@@ 124,7 124,7 @@ checkalarms(void)
}
alarms.head = rp->palarm;
}
- qunlock(&alarms);
+ unlock(&alarms);
}
}
@@ 143,7 143,7 @@ procalarm(ulong time)
else
when += MACHP(0)->ticks;
- qlock(&alarms);
+ lock(&alarms);
l = &alarms.head;
for(f = *l; f; f = f->palarm){
if(u->p == f){
@@ 170,7 170,7 @@ procalarm(ulong time)
alarms.head = u->p;
done:
u->p->alarm = when;
- qunlock(&alarms);
+ unlock(&alarms);
return TK2MS(old);
}
M port/chan.c => port/chan.c +11 -1
@@ 5,7 5,6 @@
#include "fns.h"
#include "errno.h"
-
struct{
Lock;
Chan *free;
@@ 612,6 611,7 @@ namec(char *name, int amode, int omode, ulong perm)
close(cc);
nexterror();
}
+ nameok(elem);
if((nc=walk(cc, elem, 1)) != 0){
poperror();
close(c);
@@ 665,6 665,16 @@ char isfrog[]={
[0x7f] 1,
};
+void
+nameok(char *elem)
+{
+ while(*elem) {
+ if((*elem&0x80) || isfrog[*elem])
+ error(Ebadchar);
+ elem++;
+ }
+}
+
/*
* name[0] should not be a slash.
* Advance name to next element in path, copying current element into elem.
M port/devcons.c => port/devcons.c +11 -0
@@ 235,6 235,17 @@ echo(int c)
}
/*
+ * turn '\r' into '\n' before putting it into the queue
+ */
+int
+kbdcr2nl(IOQ *q, int ch)
+{
+ if(ch == '\r')
+ ch = '\n';
+ return kbdputc(q, ch);
+}
+
+/*
* Put character into read queue at interrupt time.
* Always called splhi from proc 0.
*/
M port/devscc.c => port/devscc.c +8 -0
@@ 370,6 370,14 @@ sccspecial(int port, IOQ *oq, IOQ *iq, int baud)
sp->iq = iq;
sccenable(sp);
sccsetbaud(sp, baud);
+
+ if(iq){
+ /*
+ * Stupid HACK to undo a stupid hack
+ */
+ if(iq == &kbdq)
+ kbdq.putc = kbdcr2nl;
+ }
}
static void scctimer(Alarm*);
M port/portdat.h => port/portdat.h +2 -2
@@ 70,7 70,7 @@ struct Alarm
struct Alarms
{
- QLock;
+ Lock;
Proc *head;
};
@@ 492,7 492,7 @@ struct Proc
Lock debug; /* to access debugging elements of User */
Rendez *r; /* rendezvous point slept on */
Rendez sleep; /* place for tsleep and syssleep */
- int wokeup; /* whether sleep was interrupted */
+ int notepending; /* note issued but not acted on */
ulong pc; /* DEBUG only */
int kp; /* true if a kernel process */
Proc *palarm; /* Next alarm time */
M port/portfns.h => port/portfns.h +2 -0
@@ 96,6 96,7 @@ void isdir(Chan*);
int ispages(void*);
void kbdclock(void);
int kbdputc(IOQ*, int);
+int kbdcr2nl(IOQ*, int);
void kbdrepeat(int);
void kickpager(void);
int kprint(char*, ...);
@@ 113,6 114,7 @@ void mntdump(void);
int mount(Chan*, Chan*, int);
int mouseputc(IOQ*, int);
Chan* namec(char*, int, int, ulong);
+void nameok(char*);
Alarm* newalarm(void);
Chan* newchan(void);
Egrp* newegrp(void);
M port/proc.c => port/proc.c +25 -16
@@ 238,6 238,7 @@ loop:
p->fpstate = FPinit;
p->kp = 0;
p->procctl = 0;
+ p->notepending = 0;
memset(p->seg, 0, sizeof p->seg);
lock(&pidalloc);
p->pid = ++pidalloc.pid;
@@ 282,12 283,15 @@ sleep1(Rendez *r, int (*f)(void*), void *arg)
* at interrupt time. lock is mutual exclusion
*/
s = splhi();
+ p = u->p;
+ p->r = r; /* early so postnote knows */
lock(r);
/*
* if condition happened, never mind
*/
- if((*f)(arg)){
+ if((*f)(arg)){
+ p->r = 0;
unlock(r);
splx(s);
return;
@@ 297,11 301,8 @@ sleep1(Rendez *r, int (*f)(void*), void *arg)
* now we are committed to
* change state and call scheduler
*/
- p = u->p;
if(r->p)
print("double sleep %d %d\n", r->p->pid, p->pid);
- p->r = r;
- p->wokeup = 0;
p->state = Wakeme;
r->p = p;
unlock(r);
@@ 310,10 311,14 @@ sleep1(Rendez *r, int (*f)(void*), void *arg)
void
sleep(Rendez *r, int (*f)(void*), void *arg)
{
+ Proc *p;
+
+ p = u->p;
sleep1(r, f, arg);
- sched();
- if(u->p->wokeup){
- u->p->wokeup = 0;
+ if(p->notepending == 0)
+ sched(); /* notepending may go true while asleep */
+ if(p->notepending){
+ p->notepending = 0;
error(Eintr);
}
}
@@ 322,13 327,17 @@ void
tsleep(Rendez *r, int (*f)(void*), void *arg, int ms)
{
Alarm *a;
+ Proc *p;
+ p = u->p;
sleep1(r, f, arg);
- a = alarm(ms, twakeme, r);
- sched();
- cancel(a);
- if(u->p->wokeup){
- u->p->wokeup = 0;
+ if(p->notepending == 0){
+ a = alarm(ms, twakeme, r);
+ sched(); /* notepending may go true while asleep */
+ cancel(a);
+ }
+ if(p->notepending){
+ p->notepending = 0;
error(Eintr);
}
}
@@ 397,6 406,7 @@ postnote(Proc *p, int dolock, char *n, int flag)
kunmap(k);
return 0;
}
+ p->notepending = 1;
strcpy(up->note[up->nnote].msg, n);
up->note[up->nnote++].flag = flag;
if(up != u)
@@ 404,15 414,14 @@ postnote(Proc *p, int dolock, char *n, int flag)
if(dolock)
unlock(&p->debug);
- if(r = p->r) { /* assign = */
- /* wake up */
+ if(r = p->r){ /* assign = */
+ /* wake up; can't call wakeup itself because we're racing with it */
s = splhi();
lock(r);
- if(p->r==r && r->p==p){
+ if(p->r==r && r->p==p){ /* check we won the race */
r->p = 0;
if(p->state != Wakeme)
panic("postnote wakeup: not Wakeme");
- p->wokeup = 1;
p->r = 0;
ready(p);
}
M port/qlock.c => port/qlock.c +0 -3
@@ 53,10 53,7 @@ qunlock(QLock *q)
unlock(&q->queue);
ready(p);
}else{
- /* horrible botch because clock does a canqlock */
- int s = splhi();
unlock(&q->use);
unlock(&q->queue);
- splx(s);
}
}
M port/swap.c => port/swap.c +2 -1
@@ 123,7 123,8 @@ pager(void *junk)
executeio();
}
}
- else {
+ else
+ if(palloc.freecount < HIGHWATER) {
/* Emulate the old system if no swap channel */
print("no physical memory\n");
tsleep(&swapalloc.r, return0, 0, 1000);
M port/tcpinput.c => port/tcpinput.c +1 -1
@@ 9,7 9,7 @@
int tcpdbg = 0;
#define DPRINT if(tcpdbg) print
-#define LPRINT print
+#define LPRINT if(tcpdbg) print
extern Queue *Tcpoutput;
QLock reseqlock;
M power/devduart.c => power/devduart.c +8 -0
@@ 466,6 466,7 @@ void
duartspecial(int port, IOQ *oq, IOQ *iq, int baud)
{
Duartport *dp = &duartport[port];
+ IOQ *zq;
dp->nostream = 1;
if(oq){
@@ 476,6 477,13 @@ duartspecial(int port, IOQ *oq, IOQ *iq, int baud)
if(iq){
dp->iq = iq;
dp->iq->ptr = dp;
+
+ /*
+ * Stupid HACK to undo a stupid hack
+ */
+ zq = &kbdq;
+ if(iq == zq)
+ kbdq.putc = kbdcr2nl;
}
duartenable(dp);
duartbaud(dp, baud);
M power/devhotrod.c => power/devhotrod.c +4 -2
@@ 26,7 26,7 @@ ulong testbuf[NTESTBUF];
/*
* If 1, ENABCKSUM causes data transfers to have checksums
*/
-#define ENABCKSUM 0
+#define ENABCKSUM 1
typedef struct Hotrod Hotrod;
@@ 72,11 72,14 @@ hotsend(Hotrod *h, Hotmsg *m)
lock(h);
mp = (Hotmsg**)&h->addr->reqstq[h->wi];
+print("send 1 %lux\n", MP2VME(m)); delay(500);
*mp = (Hotmsg*)MP2VME(m);
+print("send 2\n"); delay(500);
h->wi++;
if(h->wi >= NRQ)
h->wi = 0;
unlock(h);
+print("send 3\n"); delay(500);
return mp;
}
@@ 211,7 214,6 @@ hotrodopen(Chan *c, int omode)
}
for(;;){
-for(;;);
print("-");
mem(hp->addr, &hp->addr->ram[(mp->param[0]-0x40000)/sizeof(ulong)], mp->param[1]);
}
M power/trap.c => power/trap.c +1 -0
@@ 377,6 377,7 @@ notify(Ureg *ur)
unlock(&u->p->debug);
return;
}
+ u->p->notepending = 0;
if(u->note[0].flag!=NUser && (u->notified || u->notify==0)){
if(u->note[0].flag == NDebug)
pprint("suicide: %s\n", u->note[0].msg);
M ss/trap.c => ss/trap.c +1 -0
@@ 218,6 218,7 @@ notify(Ureg *ur)
ulong sp;
lock(&u->p->debug);
+ u->p->notepending = 0;
if(u->nnote==0){
unlock(&u->p->debug);
return;