M bitsy/clock.c => bitsy/clock.c +1 -72
@@ 7,44 7,6 @@
#include "ureg.h"
#include "../port/error.h"
-typedef struct OSTimer
-{
- ulong osmr[4]; /* match registers */
- ulong oscr; /* counter register */
- ulong ossr; /* status register */
- ulong ower; /* watchdog enable register */
- ulong oier; /* timer interrupt enable register */
-} OSTimer;
-
-static OSTimer *timerregs = (OSTimer*)OSTIMERREGS;
-static int clockinited;
-
-static void clockintr(Ureg*, void*);
-
-typedef struct Clock0link Clock0link;
-typedef struct Clock0link {
- void (*clock)(void);
- Clock0link* link;
-} Clock0link;
-
-static Clock0link *clock0link;
-static Lock clock0lock;
-
-void
-addclock0link(void (*clock)(void))
-{
- Clock0link *lp;
-
- if((lp = malloc(sizeof(Clock0link))) == 0){
- print("addclock0link: too many links\n");
- return;
- }
- ilock(&clock0lock);
- lp->clock = clock;
- lp->link = clock0link;
- clock0link = lp;
- iunlock(&clock0lock);
-}
void
clockinit(void)
@@ 83,40 45,7 @@ clockintr(Ureg *ureg, void*)
/* post interrupt 1/HZ secs from now */
timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;
- m->ticks++;
-
- if(m->proc)
- m->proc->pc = ureg->pc;
-
- if(inclockintr)
- return; /* interrupted ourself */
-
- inclockintr = 1;
-
- accounttime();
- if(kproftimer != nil)
- (*kproftimer)(ureg->pc);
-
- checkalarms();
- ilock(&clock0lock);
- for(lp = clock0link; lp; lp = lp->link)
- lp->clock();
- iunlock(&clock0lock);
-
- if(active.exiting && (active.machs & (1<<m->machno)))
- exit(0);
- inclockintr = 0;
-
- if(up == 0 || up->state != Running)
- return;
-
- if(anyready())
- sched();
-
- if((ureg->psr & PsrMask) == PsrMusr) {
- (*(ulong*)(USTKTOP-BY2WD)) += TK2MS(1);
- segclock(ureg->pc);
- }
+ portclock();
}
void
M bitsy/devflash.c => bitsy/devflash.c +57 -0
@@ 15,3 15,60 @@ struct FlashPart
ulong start; /* byte offsets */
ulong end;
};
+
+static ulong *flash = (ulong*)FLASHZERO;
+
+/*
+ * on the bitsy, all 32 bit accesses to flash are mapped to two 16 bit
+ * accesses, one to the low half of the chip and the other to the high
+ * half. Therefore for all command accesses, ushort indices in the
+ * manuals turn into ulong indices in our code. Also, by copying all
+ * 16 bit commands to both halves of a 32 bit command, we erase 2
+ * sectors for each request erase request.
+ */
+
+/*
+ * common flash memory interface
+ */
+enum
+{
+ CFIidoff= 0x10,
+ CFIsysoff= 0x1B,
+ CFIgeomoff= 0x27,
+};
+
+struct CFIid
+{
+ ulong q;
+ ulong r;
+ ulong y;
+ ulong cmd_set;
+ ulong vendor_alg;
+ ulong ext_alg_addr[2];
+ ulong alt_cmd_set;
+ ulong alt_vendor_alg;
+ ulong alt_ext_ald_addr[2];
+
+};
+
+struct CFIsys
+{
+ ulong vcc_min; /* 100 mv */
+ ulong vcc_max;
+ ulong vpp_min;
+ ulong vpp_max;
+ ulong word_wr_to; /* 2**n µs */
+ ulong buf_wr_to; /* 2**n µs */
+ ulong block_erase_to; /* 2**n ms */
+ ulong chip_erase_to; /* 2**n ms */
+ ulong max_word_wr_to; /* 2**n µs */
+ ulong max_buf_wr_to; /* 2**n µs */
+ ulong max_block_erase_to; /* 2**n ms */
+ ulong max_chip_erase_to; /* 2**n ms */
+};
+
+struct CFIgeom
+{
+ ulong size; /* 2**n bytes */
+ ulong
+};
M bitsy/devuda1341.c => bitsy/devuda1341.c +373 -0
@@ 460,3 460,376 @@ audioinit(void)
return 0;
}
+
+static void
+audioinit(void)
+{}
+
+
+static Chan*
+audioattach(char *param)
+{
+ return devattach('A', param);
+}
+
+static int
+audiowalk(Chan *c, char *name)
+{
+ return devwalk(c, name, audiodir, nelem(audiodir), devgen);
+}
+
+static void
+audiostat(Chan *c, char *db)
+{
+ devstat(c, db, audiodir, nelem(audiodir), devgen);
+}
+
+static Chan*
+audioopen(Chan *c, int omode)
+{
+ int amode;
+
+ switch(c->qid.path & ~CHDIR) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qstatus:
+ if((omode&7) != OREAD)
+ error(Eperm);
+ case Qvolume:
+ case Qdir:
+ break;
+
+ case Qaudio:
+ amode = Awrite;
+ switch (omode & 0x7)
+ case OREAD:
+ break;
+ case OWRITE
+ qlock(&audio);
+ if(audio.amode != Aclosed){
+ qunlock(&audio);
+ error(Einuse);
+ }
+ if(audio.bufinit == 0) {
+ audio.bufinit = 1;
+ sbbufinit();
+ }
+ audio.amode = amode;
+ setempty();
+ audio.curcount = 0;
+ qunlock(&audio);
+ mxvolume();
+ break;
+ }
+ c = devopen(c, omode, audiodir, nelem(audiodir), devgen);
+ c->mode = openmode(omode);
+ c->flag |= COPEN;
+ c->offset = 0;
+
+ return c;
+}
+
+static void
+audioclose(Chan *c)
+{
+ Buf *b;
+
+ switch(c->qid.path & ~CHDIR) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qdir:
+ case Qvolume:
+ case Qstatus:
+ break;
+
+ case Qaudio:
+ if(c->flag & COPEN) {
+ qlock(&audio);
+ if(audio.amode == Awrite) {
+ /* flush out last partial buffer */
+ b = audio.filling;
+ if(b) {
+ audio.filling = 0;
+ memset(b->virt+audio.curcount, 0, Bufsize-audio.curcount);
+ swab(b->virt);
+ putbuf(&audio.full, b);
+ }
+ if(!audio.active && audio.full.first)
+ pokeaudio();
+ }
+ audio.amode = Aclosed;
+ if(waserror()){
+ qunlock(&audio);
+ nexterror();
+ }
+ while(audio.active)
+ waitaudio();
+ setempty();
+ poperror();
+ qunlock(&audio);
+ }
+ break;
+ }
+}
+
+static long
+audioread(Chan *c, void *v, long n, vlong off)
+{
+ int liv, riv, lov, rov;
+ long m, n0;
+ char buf[300];
+ Buf *b;
+ int j;
+ ulong offset = off;
+ char *a;
+
+ n0 = n;
+ a = v;
+ switch(c->qid.path & ~CHDIR) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qdir:
+ return devdirread(c, a, n, audiodir, nelem(audiodir), devgen);
+
+ case Qaudio:
+ if(audio.amode != Aread)
+ error(Emode);
+ qlock(&audio);
+ if(waserror()){
+ qunlock(&audio);
+ nexterror();
+ }
+ while(n > 0) {
+ b = audio.filling;
+ if(b == 0) {
+ b = getbuf(&audio.full);
+ if(b == 0) {
+ waitaudio();
+ continue;
+ }
+ audio.filling = b;
+ swab(b->virt);
+ audio.curcount = 0;
+ }
+ m = Bufsize-audio.curcount;
+ if(m > n)
+ m = n;
+ memmove(a, b->virt+audio.curcount, m);
+
+ audio.curcount += m;
+ n -= m;
+ a += m;
+ if(audio.curcount >= Bufsize) {
+ audio.filling = 0;
+ putbuf(&audio.empty, b);
+ }
+ }
+ poperror();
+ qunlock(&audio);
+ break;
+
+ case Qstatus:
+ buf[0] = 0;
+ snprint(buf, sizeof(buf), "bytes %lud\ntime %lld\n",
+ audio.totcount, audio.tottime);
+ return readstr(offset, a, n, buf);
+
+ case Qvolume:
+ j = 0;
+ buf[0] = 0;
+ for(m=0; volumes[m].name; m++){
+ liv = audio.livol[m];
+ riv = audio.rivol[m];
+ lov = audio.lovol[m];
+ rov = audio.rovol[m];
+ j += snprint(buf+j, sizeof(buf)-j, "%s", volumes[m].name);
+ if((volumes[m].flag & Fmono) || liv==riv && lov==rov){
+ if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) && liv==lov)
+ j += snprint(buf+j, sizeof(buf)-j, " %d", liv);
+ else{
+ if(volumes[m].flag & Fin)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " in %d", liv);
+ if(volumes[m].flag & Fout)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " out %d", lov);
+ }
+ }else{
+ if((volumes[m].flag&(Fin|Fout))==(Fin|Fout) &&
+ liv==lov && riv==rov)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " left %d right %d",
+ liv, riv);
+ else{
+ if(volumes[m].flag & Fin)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " in left %d right %d",
+ liv, riv);
+ if(volumes[m].flag & Fout)
+ j += snprint(buf+j, sizeof(buf)-j,
+ " out left %d right %d",
+ lov, rov);
+ }
+ }
+ j += snprint(buf+j, sizeof(buf)-j, "\n");
+ }
+ return readstr(offset, a, n, buf);
+ }
+ return n0-n;
+}
+
+static long
+audiowrite(Chan *c, void *vp, long n, vlong)
+{
+ long m, n0;
+ int i, nf, v, left, right, in, out;
+ char buf[255], *field[Ncmd];
+ Buf *b;
+ char *a;
+
+ a = vp;
+ n0 = n;
+ switch(c->qid.path & ~CHDIR) {
+ default:
+ error(Eperm);
+ break;
+
+ case Qvolume:
+ v = Vaudio;
+ left = 1;
+ right = 1;
+ in = 1;
+ out = 1;
+ if(n > sizeof(buf)-1)
+ n = sizeof(buf)-1;
+ memmove(buf, a, n);
+ buf[n] = '\0';
+
+ nf = getfields(buf, field, Ncmd, 1, " \t\n");
+ for(i = 0; i < nf; i++){
+ /*
+ * a number is volume
+ */
+ if(field[i][0] >= '0' && field[i][0] <= '9') {
+ m = strtoul(field[i], 0, 10);
+ if(left && out)
+ audio.lovol[v] = m;
+ if(left && in)
+ audio.livol[v] = m;
+ if(right && out)
+ audio.rovol[v] = m;
+ if(right && in)
+ audio.rivol[v] = m;
+ mxvolume();
+ goto cont0;
+ }
+
+ for(m=0; volumes[m].name; m++) {
+ if(strcmp(field[i], volumes[m].name) == 0) {
+ v = m;
+ in = 1;
+ out = 1;
+ left = 1;
+ right = 1;
+ goto cont0;
+ }
+ }
+
+ if(strcmp(field[i], "reset") == 0) {
+ resetlevel();
+ mxvolume();
+ goto cont0;
+ }
+ if(strcmp(field[i], "in") == 0) {
+ in = 1;
+ out = 0;
+ goto cont0;
+ }
+ if(strcmp(field[i], "out") == 0) {
+ in = 0;
+ out = 1;
+ goto cont0;
+ }
+ if(strcmp(field[i], "left") == 0) {
+ left = 1;
+ right = 0;
+ goto cont0;
+ }
+ if(strcmp(field[i], "right") == 0) {
+ left = 0;
+ right = 1;
+ goto cont0;
+ }
+ error(Evolume);
+ break;
+ cont0:;
+ }
+ break;
+
+ case Qaudio:
+ if(audio.amode != Awrite)
+ error(Emode);
+ qlock(&audio);
+ if(waserror()){
+ qunlock(&audio);
+ nexterror();
+ }
+ while(n > 0) {
+ b = audio.filling;
+ if(b == 0) {
+ b = getbuf(&audio.empty);
+ if(b == 0) {
+ waitaudio();
+ continue;
+ }
+ audio.filling = b;
+ audio.curcount = 0;
+ }
+
+ m = Bufsize-audio.curcount;
+ if(m > n)
+ m = n;
+ memmove(b->virt+audio.curcount, a, m);
+
+ audio.curcount += m;
+ n -= m;
+ a += m;
+ if(audio.curcount >= Bufsize) {
+ audio.filling = 0;
+ swab(b->virt);
+ putbuf(&audio.full, b);
+ }
+ }
+ poperror();
+ qunlock(&audio);
+ break;
+ }
+ return n0 - n;
+}
+
+Dev audiodevtab = {
+ 'A',
+ "audio",
+
+ devreset,
+ audioinit,
+ audioattach,
+ devclone,
+ audiowalk,
+ audiostat,
+ audioopen,
+ devcreate,
+ audioclose,
+ audioread,
+ devbread,
+ audiowrite,
+ devbwrite,
+ devremove,
+ devwstat,
+};
M boot/boot.c => boot/boot.c +29 -1
@@ 199,6 199,34 @@ findmethod(char *a)
return 0;
}
+int
+parsecmd(char *s, char **av, int n)
+{
+ int ac;
+
+ n--;
+ for(ac = 0; ac < n; ac++){
+ while(*s == ' ' || *s == '\t')
+ s++;
+ if(*s == 0 || *s == '\n' || *s == '\r')
+ break;
+ if(*s == '\''){
+ s++;
+ av[ac] = s;
+ while(*s && *s != '\'')
+ s++;
+ } else {
+ av[ac] = s;
+ while(*s && *s != ' ' && *s != '\t')
+ s++;
+ }
+ if(*s != 0)
+ *s++ = 0;
+ }
+ av[ac] = 0;
+ return ac;
+}
+
/*
* ask user from whence cometh the root file system
*/
@@ 234,7 262,7 @@ rootserver(char *arg)
outin(prompt, reply, sizeof(reply));
mp = findmethod(reply);
if(mp){
- bargc = getfields(reply, bargv, Nbarg-1, 1, " ");
+ bargc = parsecmd(reply, bargv, Nbarg);
cp = strchr(reply, '!');
if(cp)
strcpy(sys, cp+1);
M boot/boot.h => boot/boot.h +1 -1
@@ 22,7 22,7 @@ extern uchar hostkey[];
extern char username[NAMELEN];
enum
{
- Nbarg= 16,
+ Nbarg= 32,
};
extern int bargc;
extern char *bargv[Nbarg];
M boot/bootip.c => boot/bootip.c +1 -0
@@ 43,6 43,7 @@ configip(void)
case 'b':
case 'h':
case 'm':
+ case 'c':
p = ARGF();
USED(p);
break;
M pc/devi82365.c => pc/devi82365.c +21 -11
@@ 178,6 178,7 @@ struct Slot
uchar busy;
/* cis info */
+ ulong msec; /* time of last slotinfo call */
char verstr[512]; /* version string */
uchar cpresent; /* config registers present */
ulong caddr; /* relative address of config registers */
@@ 236,6 237,7 @@ slotinfo(Slot *pp)
pp->battery = (isr & 3) == 3;
pp->wrprot = isr & (1<<4);
pp->busy = isr & (1<<5);
+ pp->msec = TK2MS(MACHP(0)->ticks);
}
static int
@@ 438,28 440,35 @@ pcmspecial(char *idstr, ISAConf *isa)
{
Slot *pp;
extern char *strstr(char*, char*);
- static int resetdone;
+ int enabled;
i82365reset();
-print("pcmcia: looking for %s: ", idstr);
for(pp = slot; pp < lastslot; pp++){
if(pp->special)
continue; /* already taken */
- increfp(pp);
+ enabled = 0;
+ /* make sure we don't power on cards when we already know what's
+ * in them. We'll reread every two minutes if necessary
+ */
+ if (pp->msec == ~0 || TK2MS(MACHP(0)->ticks) - pp->msec > 120000) {
+ increfp(pp);
+ enabled++;
+ }
if(pp->occupied) {
-print("[%8.8s]", pp->verstr);
- if(strstr(pp->verstr, idstr))
- if(isa == 0 || pcmio(pp->slotno, isa) == 0){
- pp->special = 1;
-print(" - found\n");
- return pp->slotno;
+ if(strstr(pp->verstr, idstr)) {
+ if (!enabled)
+ increfp(pp);
+ if(isa == 0 || pcmio(pp->slotno, isa) == 0){
+ pp->special = 1;
+ return pp->slotno;
+ }
}
} else
pp->special = 1;
- decrefp(pp);
+ if (enabled)
+ decrefp(pp);
}
-print("\n");
return -1;
}
@@ 680,6 689,7 @@ i82365reset(void)
pp->memlen = 64*MB;
pp->base = (cp->dev<<7) | (j<<6);
pp->cp = cp;
+ pp->msec = ~0;
slotdis(pp);
/* interrupt on status change */
M port/netif.c => port/netif.c +2 -1
@@ 318,7 318,8 @@ netifwrite(Netif *nif, Chan *c, void *a, long n)
p = netmulti(nif, f, binaddr, 0);
if(p)
error(p);
- }
+ } else
+ n = -1;
qunlock(nif);
poperror();
return n;