M bitsy/clock.c => bitsy/clock.c +1 -1
@@ 31,7 31,7 @@ clockinit(void)
/* enable interrupts on match register 0, turn off all others */
timerregs->ossr |= 1<<0;
- intrenable(IRQtimer0, clockintr, nil, "clock");
+ intrenable(IRQ, IRQtimer0, clockintr, nil, "clock");
timerregs->oier = 1<<0;
/* figure out processor frequency */
M bitsy/dat.h => bitsy/dat.h +20 -10
@@ 4,6 4,7 @@ typedef struct Cycintr Cycintr;
typedef struct FPU FPU;
typedef struct FPenv FPenv;
typedef struct FPsave FPsave;
+typedef struct DevConf DevConf;
typedef struct Label Label;
typedef struct Lock Lock;
typedef struct MMU MMU;
@@ 21,6 22,8 @@ typedef struct Ureg Ureg;
typedef struct Vctl Vctl;
typedef struct Uart Uart;
+typedef void IntrHandler(Ureg*, void*);
+
/*
* parameters for sysproc.c
*/
@@ 316,6 319,8 @@ struct Cisdat
*/
struct PCMslot
{
+ RWlock;
+
Ref ref;
long memlen; /* memory length */
@@ 325,19 330,11 @@ struct PCMslot
void *attr; /* attribute memory */
/* status */
- uchar special; /* in use for a special device */
- uchar already; /* already inited */
- uchar occupied;
- uchar battery;
- uchar wrprot;
- uchar powered;
- uchar configed;
- uchar enabled;
- uchar busy;
+ uchar occupied; /* card in the slot */
+ uchar configed; /* card configured */
/* cis info */
int cisread; /* set when the cis has been read */
- ulong msec; /* time of last slotinfo call */
char verstr[512]; /* version string */
uchar cpresent; /* config registers present */
ulong caddr; /* relative address of config registers */
@@ 352,3 349,16 @@ struct PCMslot
PCMmap memmap;
PCMmap attrmap;
};
+
+/*
+ * hardware info about a device
+ */
+struct DevConf
+{
+ ulong mem; /* mapped memory address */
+ ulong port; /* mapped i/o regs */
+ int size; /* access size */
+ int itype; /* type of interrupt */
+ ulong interrupt; /* interrupt number */
+ char type[NAMELEN]; /* card type */
+};
M bitsy/devether.c => bitsy/devether.c +93 -94
@@ 12,6 12,97 @@
static Ether *etherxx[MaxEther];
+static struct {
+ char* type;
+ int (*reset)(Ether*);
+} cards[MaxEther+1];
+
+void
+addethercard(char* t, int (*r)(Ether*))
+{
+ static int ncard;
+
+ if(ncard == MaxEther)
+ panic("too many ether cards");
+ cards[ncard].type = t;
+ cards[ncard].reset = r;
+ ncard++;
+}
+
+int
+etherconfig(int on, char *spec, DevConf *cf)
+{
+ Ether *ether;
+ int n, ctlrno;
+ char name[NAMELEN], buf[128];
+ char *p, *e;
+
+ /* can't unconfigure yet */
+ if(on == 0)
+ return -1;
+
+ ctlrno = atoi(spec);
+ if(etherxx[ctlrno] != nil)
+ return -1;
+
+ ether = malloc(sizeof(Ether));
+ if(ether == nil)
+ panic("etherconfig");
+ memset(ether, 0, sizeof(Ether));
+ *(DevConf*)ether = *cf;
+
+print("looking for card type %s\n", ether->type);
+ for(n = 0; cards[n].type; n++){
+ if(strcmp(cards[n].type, ether->type) != 0)
+ continue;
+print("found card type %s\n", ether->type);
+ if(cards[n].reset(ether))
+ break;
+ sprint(name, "ether%d", ctlrno);
+
+ if(ether->mbps >= 100){
+ netifinit(ether, name, Ntypes, 256*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(256*1024, 1, 0, 0);
+ }
+ else{
+ netifinit(ether, name, Ntypes, 65*1024);
+ if(ether->oq == 0)
+ ether->oq = qopen(65*1024, 1, 0, 0);
+ }
+ if(ether->oq == 0)
+ panic("etherreset %s", name);
+ ether->alen = Eaddrlen;
+ memmove(ether->addr, ether->ea, Eaddrlen);
+ memset(ether->bcast, 0xFF, Eaddrlen);
+
+ if(ether->interrupt != nil)
+ intrenable(cf->itype, cf->interrupt, ether->interrupt, ether, name);
+
+ p = buf;
+ e = buf+sizeof(buf);
+ p = seprint(p, e, "#l%d: %s: %dMbps port 0x%luX",
+ ctlrno, ether->type, ether->mbps, ether->port);
+ if(ether->mem)
+ p = seprint(p, e, " addr 0x%luX", PADDR(ether->mem));
+ if(ether->size)
+ p = seprint(p, e, " size 0x%luX", ether->size);
+ p = seprint(p, e, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX",
+ ether->ea[0], ether->ea[1], ether->ea[2],
+ ether->ea[3], ether->ea[4], ether->ea[5]);
+ seprint(p, e, "\n");
+ print(buf);
+
+ etherxx[ctlrno] = ether;
+ return 0;
+ }
+
+ free(ether);
+ return -1;
+}
+
+
+
Chan*
etherattach(char* spec)
{
@@ 302,23 393,6 @@ etherbwrite(Chan* chan, Block* bp, ulong)
return etheroq(ether, bp);
}
-static struct {
- char* type;
- int (*reset)(Ether*);
-} cards[MaxEther+1];
-
-void
-addethercard(char* t, int (*r)(Ether*))
-{
- static int ncard;
-
- if(ncard == MaxEther)
- panic("too many ether cards");
- cards[ncard].type = t;
- cards[ncard].reset = r;
- ncard++;
-}
-
int
parseether(uchar *to, char *from)
{
@@ 345,83 419,6 @@ parseether(uchar *to, char *from)
static void
etherreset(void)
{
- Ether *ether;
- int i, n, ctlrno;
- char name[NAMELEN], buf[128];
-
- for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
- if(ether == 0)
- ether = malloc(sizeof(Ether));
- memset(ether, 0, sizeof(Ether));
- ether->ctlrno = ctlrno;
- ether->tbdf = BUSUNKNOWN;
- ether->mbps = 10;
- ether->minmtu = ETHERMINTU;
- ether->maxmtu = ETHERMAXTU;
- if(isaconfig("ether", ctlrno, ether) == 0)
- continue;
- for(n = 0; cards[n].type; n++){
- if(cistrcmp(cards[n].type, ether->type))
- continue;
- for(i = 0; i < ether->nopt; i++){
- if(strncmp(ether->opt[i], "ea=", 3))
- continue;
- if(parseether(ether->ea, ðer->opt[i][3]) == -1)
- memset(ether->ea, 0, Eaddrlen);
- }
- if(cards[n].reset(ether))
- break;
-
- /*
- * IRQ2 doesn't really exist, it's used to gang the interrupt
- * controllers together. A device set to IRQ2 will appear on
- * the second interrupt controller as IRQ9.
- */
- if(ether->irq == 2)
- ether->irq = 9;
- snprint(name, sizeof(name), "ether%d", ctlrno);
-
- /* If ether->irq is less than 0, it is a hack to indicate no interrupt
- * used for the second logical ethernet for the wavelan card
- */
- if(ether->irq >= 0)
- intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);
-
- i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %lud",
- ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
- if(ether->mem)
- i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem));
- if(ether->size)
- i += sprint(buf+i, " size 0x%luX", ether->size);
- i += sprint(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX",
- ether->ea[0], ether->ea[1], ether->ea[2],
- ether->ea[3], ether->ea[4], ether->ea[5]);
- sprint(buf+i, "\n");
- print(buf);
-
- if(ether->mbps >= 100){
- netifinit(ether, name, Ntypes, 256*1024);
- if(ether->oq == 0)
- ether->oq = qopen(256*1024, 1, 0, 0);
- }
- else{
- netifinit(ether, name, Ntypes, 65*1024);
- if(ether->oq == 0)
- ether->oq = qopen(65*1024, 1, 0, 0);
- }
- if(ether->oq == 0)
- panic("etherreset %s", name);
- ether->alen = Eaddrlen;
- memmove(ether->addr, ether->ea, Eaddrlen);
- memset(ether->bcast, 0xFF, Eaddrlen);
-
- etherxx[ctlrno] = ether;
- ether = 0;
- break;
- }
- }
- if(ether)
- free(ether);
}
#define POLY 0xedb88320
@@ 463,4 460,6 @@ Dev etherdevtab = {
etherbwrite,
etherremove,
etherwstat,
+ nil, /* no power management */
+ etherconfig,
};
M bitsy/devpcmcia.c => bitsy/devpcmcia.c +181 -67
@@ 23,6 23,17 @@ enum
Nents = 3,
};
+enum
+{
+ /*
+ * configuration registers - they start at an offset in attribute
+ * memory found in the CIS.
+ */
+ Rconfig= 0,
+ Creset= (1<<7), /* reset device */
+ Clevel= (1<<6), /* level sensitive interrupt line */
+};
+
#define SLOTNO(c) ((c->qid.path>>8)&0xff)
#define TYPE(c) (c->qid.path&0xff)
#define QID(s,t) (((s)<<8)|(t))
@@ 39,7 50,7 @@ pcmgen(Chan *c, Dirtab *, int , int i, Dir *dp)
int slotno;
Qid qid;
long len;
- PCMslot *pp;
+ PCMslot *sp;
char name[NAMELEN];
if(i == DEVDOTDOT){
@@ 51,18 62,18 @@ pcmgen(Chan *c, Dirtab *, int , int i, Dir *dp)
return -1;
slotno = i/Nents;
- pp = slot + slotno;
+ sp = slot + slotno;
len = 0;
switch(i%Nents){
case 0:
qid.path = QID(slotno, Qmem);
sprint(name, "pcm%dmem", slotno);
- len = pp->memlen;
+ len = sp->memlen;
break;
case 1:
qid.path = QID(slotno, Qattr);
sprint(name, "pcm%dattr", slotno);
- len = pp->memlen;
+ len = sp->memlen;
break;
case 2:
qid.path = QID(slotno, Qctl);
@@ 74,6 85,17 @@ pcmgen(Chan *c, Dirtab *, int , int i, Dir *dp)
return 1;
}
+static int
+bitno(ulong x)
+{
+ int i;
+
+ for(i = 0; i < 8*sizeof(x); i++)
+ if((1<<i) & x)
+ break;
+ return i;
+}
+
/*
* set up the cards, default timing is 300 ns
*/
@@ 88,9 110,13 @@ pcmciareset(void)
slottiming(0, 300, 300, 300, 0);
slottiming(1, 300, 300, 300, 0);
- /* interrupt on card insertion/removal */
- gpiointrenable(GPIO_CARD_IND1_i, GPIOboth, slotinfo, nil, "pcmcia slot1 status");
- gpiointrenable(GPIO_CARD_IND0_i, GPIOboth, slotinfo, nil, "pcmcia slot0 status");
+ /* if there's no pcmcia sleave, no interrupts */
+ if(gpioregs->level & GPIO_OPT_IND_i)
+ return;
+
+ /* sleave there, interrupt on card removal */
+ intrenable(GPIOrising, bitno(GPIO_CARD_IND1_i), slotinfo, nil, "pcmcia slot1 status");
+ intrenable(GPIOrising, bitno(GPIO_CARD_IND0_i), slotinfo, nil, "pcmcia slot0 status");
}
static Chan*
@@ 160,18 186,25 @@ memmoves(uchar *to, uchar *from, int n)
}
static long
-pcmread(void *a, long n, ulong off, uchar *start, ulong len)
+pcmread(void *a, long n, ulong off, PCMslot *sp, uchar *start, ulong len)
{
+ rlock(sp);
+ if(waserror()){
+ runlock(sp);
+ nexterror();
+ }
if(off > len)
return 0;
if(off + n > len)
n = len - off;
memmoveb(a, start+off, n);
+ runlock(sp);
+ poperror();
return n;
}
static long
-pcmctlread(void *a, long n, ulong off, PCMslot *pp)
+pcmctlread(void *a, long n, ulong off, PCMslot *sp)
{
char *p, *buf, *e;
@@ 183,10 216,10 @@ pcmctlread(void *a, long n, ulong off, PCMslot *pp)
e = p + READSTR;
buf[0] = 0;
- if(pp->occupied){
+ if(sp->occupied){
p = seprint(p, e, "occupied\n");
- if(pp->verstr[0])
- p = seprint(p, e, "version %s\n", pp->verstr);
+ if(sp->verstr[0])
+ p = seprint(p, e, "version %s\n", sp->verstr);
}
USED(p);
@@ 199,70 232,137 @@ pcmctlread(void *a, long n, ulong off, PCMslot *pp)
static long
pcmciaread(Chan *c, void *a, long n, vlong off)
{
- PCMslot *pp;
+ PCMslot *sp;
ulong offset = off;
- pp = slot + SLOTNO(c);
+ sp = slot + SLOTNO(c);
switch(TYPE(c)){
case Qdir:
return devdirread(c, a, n, 0, 0, pcmgen);
case Qmem:
- if(!pp->occupied)
+ if(!sp->occupied)
error(Eio);
- return pcmread(a, n, offset, pp->mem, 64*OneMeg);
+ return pcmread(a, n, offset, sp, sp->mem, 64*OneMeg);
case Qattr:
- if(!pp->occupied)
+ if(!sp->occupied)
error(Eio);
- return pcmread(a, n, offset, pp->attr, OneMeg);
+ return pcmread(a, n, offset, sp, sp->attr, OneMeg);
case Qctl:
- return pcmctlread(a, n, offset, pp);
+ return pcmctlread(a, n, offset, sp);
}
error(Ebadarg);
return -1; /* not reached */
}
static long
-pcmwrite(void *a, long n, ulong off, uchar *start, ulong len)
+pcmwrite(void *a, long n, ulong off, PCMslot *sp, uchar *start, ulong len)
{
+ rlock(sp);
+ if(waserror()){
+ runlock(sp);
+ nexterror();
+ }
if(off > len)
error(Eio);
if(off + n > len)
error(Eio);
memmoveb(start+off, a, n);
+ poperror();
+ runlock(sp);
return n;
}
static long
-pcmctlwrite(char *p, long n, ulong off, PCMslot *pp)
+pcmctlwrite(char *p, long n, ulong, PCMslot *sp)
{
- /* nothing yet */
- USED(p, n, off, pp);
- error(Ebadarg);
+ Cmdbuf *cmd;
+ uchar *cp;
+ int index, i, dtx;
+ Rune r;
+ DevConf cf;
+
+ cmd = parsecmd(p, n);
+ if(strcmp(cmd->f[0], "configure") == 0){
+ wlock(sp);
+ if(waserror()){
+ wunlock(sp);
+ nexterror();
+ }
+
+ /* see if driver exists and is configurable */
+ if(cmd->nf < 3)
+ error(Ebadarg);
+ p = cmd->f[1];
+ if(*p++ != '#')
+ error(Ebadarg);
+ p += chartorune(&r, p);
+ dtx = devno(r, 1);
+ if(dtx < 0)
+ error("no such device type");
+ if(devtab[dtx]->config == nil)
+ error("not a dynamicly configurable device");
+
+ /* set pcmcia card configuration */
+ index = 0;
+ if(sp->def != nil)
+ index = sp->def->index;
+ if(cmd->nf > 3){
+ i = atoi(cmd->f[3]);
+ if(i < 0 || i >= sp->nctab)
+ error("bad configuration index");
+ index = i;
+ }
+ if(sp->cpresent & (1<<Rconfig)){
+ cp = sp->attr;
+ cp += sp->caddr + Rconfig;
+print("writing configuration register (%lux) with index %d\n", cp, index);
+ *cp = index;
+ }
+
+ /* configure device */
+ strncpy(cf.type, cmd->f[2], sizeof(cf.type)-1);
+ cf.type[sizeof(cf.type)-1] = 0;
+ cf.mem = (ulong)sp->mem;
+ cf.port = (ulong)sp->regs;
+ cf.itype = GPIOfalling;
+ cf.interrupt = bitno(sp == slot ? GPIO_CARD_IRQ0_i : GPIO_CARD_IRQ1_i);
+ cf.size = 0;
+ if(devtab[dtx]->config(1, p, &cf) < 0)
+ error("couldn't configure device");
+
+ wunlock(sp);
+ poperror();
+
+ /* don't let the power turn off */
+ increfp(sp);
+ }
+ free(cmd);
+
return 0;
}
static long
pcmciawrite(Chan *c, void *a, long n, vlong off)
{
- PCMslot *pp;
+ PCMslot *sp;
ulong offset = off;
- pp = slot + SLOTNO(c);
+ sp = slot + SLOTNO(c);
switch(TYPE(c)){
case Qmem:
- if(!pp->occupied)
+ if(!sp->occupied)
error(Eio);
- return pcmwrite(a, n, offset, pp->mem, 64*OneMeg);
+ return pcmwrite(a, n, offset, sp, sp->mem, 64*OneMeg);
case Qattr:
- if(!pp->occupied)
+ if(!sp->occupied)
error(Eio);
- return pcmwrite(a, n, offset, pp->attr, OneMeg);
+ return pcmwrite(a, n, offset, sp, sp->attr, OneMeg);
case Qctl:
- if(!pp->occupied)
+ if(!sp->occupied)
error(Eio);
- return pcmctlwrite(a, n, offset, pp);
+ return pcmctlwrite(a, n, offset, sp);
}
error(Ebadarg);
return -1; /* not reached */
@@ 303,71 403,85 @@ slotinfo(Ureg*, void*)
if(x & GPIO_CARD_IND0_i){
slot[0].occupied = 0;
slot[0].cisread = 0;
- } else if(slot[0].occupied == 0){
+ } else {
+ if(slot[0].occupied == 0)
+ slot[0].cisread = 0;
slot[0].occupied = 1;
- slot[0].cisread = 0;
}
if(x & GPIO_CARD_IND1_i){
slot[1].occupied = 0;
slot[1].cisread = 0;
- } else if(slot[1].occupied == 0){
+ } else {
+ if(slot[1].occupied == 0)
+ slot[1].cisread = 0;
slot[1].occupied = 1;
- slot[1].cisread = 0;
}
}
}
/* use reference card to turn cards on and off */
static void
-increfp(PCMslot *pp)
+increfp(PCMslot *sp)
{
+ wlock(sp);
+ if(waserror()){
+ wunlock(sp);
+ nexterror();
+ }
+
if(incref(&pcmcia) == 1){
egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 1);
+ delay(200);
+ egpiobits(EGPIO_pcmcia_reset, 1);
+ delay(100);
egpiobits(EGPIO_pcmcia_reset, 0);
- delay(200); /* time to power up */
+ delay(500);
}
- incref(&pp->ref);
- if(pp->occupied && pp->cisread == 0)
- pcmcisread(pp);
+ incref(&sp->ref);
+ slotinfo(nil, nil);
+ if(sp->occupied && sp->cisread == 0)
+ pcmcisread(sp);
+
+ wunlock(sp);
+ poperror();
}
static void
-decrefp(PCMslot *pp)
+decrefp(PCMslot *sp)
{
- decref(&pp->ref);
+ decref(&sp->ref);
if(decref(&pcmcia) == 0)
egpiobits(EGPIO_exp_nvram_power|EGPIO_exp_full_power, 0);
}
/*
- * the regions are staticly mapped
+ * the regions are staticly masped
*/
static void
slotmap(int slotno, ulong regs, ulong attr, ulong mem)
{
- PCMslot *pp;
-
- pp = &slot[slotno];
- pp->slotno = slotno;
- pp->memlen = 64*OneMeg;
- pp->msec = ~0;
- pp->verstr[0] = 0;
-
- pp->mem = mapmem(mem, 64*OneMeg, 0);
- pp->memmap.ca = 0;
- pp->memmap.cea = 64*MB;
- pp->memmap.isa = (ulong)mem;
- pp->memmap.len = 64*OneMeg;
- pp->memmap.attr = 0;
-
- pp->attr = mapmem(attr, OneMeg, 0);
- pp->attrmap.ca = 0;
- pp->attrmap.cea = MB;
- pp->attrmap.isa = (ulong)attr;
- pp->attrmap.len = OneMeg;
- pp->attrmap.attr = 1;
-
- pp->regs = mapspecial(regs, 32*1024);
+ PCMslot *sp;
+
+ sp = &slot[slotno];
+ sp->slotno = slotno;
+ sp->memlen = 64*OneMeg;
+ sp->verstr[0] = 0;
+
+ sp->mem = mapmem(mem, 64*OneMeg, 0);
+ sp->memmap.ca = 0;
+ sp->memmap.cea = 64*MB;
+ sp->memmap.isa = (ulong)mem;
+ sp->memmap.len = 64*OneMeg;
+ sp->memmap.attr = 0;
+
+ sp->attr = mapmem(attr, OneMeg, 0);
+ sp->attrmap.ca = 0;
+ sp->attrmap.cea = MB;
+ sp->attrmap.isa = (ulong)attr;
+ sp->attrmap.len = OneMeg;
+ sp->attrmap.attr = 1;
+
+ sp->regs = mapspecial(regs, 32*1024);
}
PCMmap*
pcmmap(int slotno, ulong, int, int attr)
M bitsy/etherif.h => bitsy/etherif.h +3 -0
@@ 5,7 5,10 @@ enum {
typedef struct Ether Ether;
struct Ether {
+ DevConf;
+
int ctlrno;
+ int tbdf; /* type+busno+devno+funcno */
int mbps; /* Mbps */
int minmtu;
int maxmtu;
M bitsy/fns.h => bitsy/fns.h +8 -4
@@ 10,6 10,7 @@ int cistrcmp(char*, char*);
int cistrncmp(char*, char*, int);
void clockinit(void);
#define coherence()
+#define dcflush(a, b)
void delay(int);
void µdelay(int);
void dmainit(void);
@@ 30,7 31,10 @@ void h3650uartsetup(void);
void icacheinvalidate(void);
void idle(void);
void idlehands(void);
-void intrenable(int, void (*)(Ureg*, void*), void*, char*);
+uchar inb(ulong);
+ushort ins(ulong);
+ulong inl(ulong);
+void intrenable(int, int, void (*)(Ureg*, void*), void*, char*);
int iprint(char*, ...);
void irpower(int);
void lcdpower(int);
@@ 49,6 53,9 @@ ulong mmu_paddr(ulong);
int µcputc(Queue*, int);
void noted(Ureg*, ulong);
int notify(Ureg*);
+void outb(ulong, uchar);
+void outs(ulong, ushort);
+void outl(ulong, ulong);
void pcmcisread(PCMslot*);
int pcmcistuple(int, int, int, void*, int);
PCMmap* pcmmap(int, ulong, int, int);
@@ 62,7 69,6 @@ void putdac(ulong);
void putttb(ulong);
void putpid(ulong);
void qpanic(char *, ...);
-void reset(void);
void rs232power(int);
Uart* uartsetup(PhysUart*, void*, ulong, char*);
void uartspecial(Uart*, int, Queue**, Queue**, int (*)(Queue*, int));
@@ 89,5 95,3 @@ void wbflush(void);
#define PADDR(a) mmu_paddr((ulong)(a))
#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
-
-#define dcflush(a, b)
M bitsy/io.h => bitsy/io.h +2 -1
@@ 110,13 110,14 @@ enum
};
/*
- * edge argument for gpiointrenable
+ * types of interrupts
*/
enum
{
GPIOrising,
GPIOfalling,
GPIOboth,
+ IRQ,
};
/* hardware registers */
M bitsy/l.s => bitsy/l.s +1 -1
@@ 222,7 222,7 @@ TEXT vtable(SB), $-4
WORD $_vfiq(SB) /* FIQ, switch to svc mode */
TEXT _vrst(SB), $-4
- BL reset(SB)
+ BL resettrap(SB)
TEXT _vsvc(SB), $-4 /* SWI */
MOVW.W R14, -4(R13) /* ureg->pc = interupted PC */
M bitsy/main.c => bitsy/main.c +47 -0
@@ 43,6 43,7 @@ main(void)
clockinit();
procinit0();
initseg();
+ links();
chandevreset();
pageinit();
swapinit();
@@ 430,3 431,49 @@ flashprogpower(int on)
{
egpiobits(EGPIO_prog_flash, on);
}
+
+/* here on hardware reset */
+void
+resettrap(void)
+{
+}
+
+/*
+ * for drivers that used to run on x86's
+ */
+void
+outb(ulong a, uchar v)
+{
+ *(uchar*)a = v;
+ µdelay(2);
+}
+void
+outs(ulong a, ushort v)
+{
+ *(ushort*)a = v;
+ µdelay(2);
+}
+void
+outl(ulong a, ulong v)
+{
+ *(ulong*)a = v;
+ µdelay(2);
+}
+uchar
+inb(ulong a)
+{
+ µdelay(2);
+ return *(uchar*)a;
+}
+ushort
+ins(ulong a)
+{
+ µdelay(2);
+ return *(ushort*)a;
+}
+ulong
+inl(ulong a)
+{
+ µdelay(2);
+ return *(ulong*)a;
+}
M bitsy/sa1110dma.c => bitsy/sa1110dma.c +1 -1
@@ 74,7 74,7 @@ dmainit(void) {
if (debug) print("dma: dmaalloc registers 0x%ux mapped at 0x%p\n",
DMAREGS, dmaregs);
for (i = 0; i < NDMA; i++) {
- intrenable(IRQdma0+i, dmaintr, &dmaregs[i], "DMA");
+ intrenable(IRQ, IRQdma0+i, dmaintr, &dmaregs[i], "DMA");
}
}
M bitsy/sa1110uart.c => bitsy/sa1110uart.c +2 -2
@@ 424,7 424,7 @@ sa1100_uartsetup(int console)
/* external serial port (eia0) */
uart3regs = mapspecial(UART3REGS, 64);
p = uartsetup(&sa1100_uart, uart3regs, ClockFreq, "serialport3");
- intrenable(IRQuart3, sa1100_uartintr, p, p->name);
+ intrenable(IRQ, IRQuart3, sa1100_uartintr, p, p->name);
/* set eia0 up as a console */
if(console)
@@ 436,5 436,5 @@ sa1100_uartsetup(int console)
uart1regs = mapspecial(UART1REGS, 64);
p = uartsetup(&sa1100_uart, uart1regs, ClockFreq, "serialport1");
uartspecial(p, 115200, 0, 0, µcputc);
- intrenable(IRQuart1b, sa1100_uartintr, p, p->name);
+ intrenable(IRQ, IRQuart1b, sa1100_uartintr, p, p->name);
}
M bitsy/trap.c => bitsy/trap.c +24 -33
@@ 114,10 114,10 @@ warnregs(Ureg *ur, char *tag)
}
/*
- * enable an interrupt and attach a function to it
+ * enable an irq interrupt
*/
void
-intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
+irqenable(int irq, IntrHandler *f, void* a, char *name)
{
Vctl *v;
@@ 138,28 138,29 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
}
/*
- * enable an interrupt on gpio line. edge is encoded as follows
+ * enable an interrupt
*/
void
-gpiointrenable(ulong mask, int edge, void (*f)(Ureg*, void*), void* a, char *name)
+intrenable(int type, int which, IntrHandler *f, void* a, char *name)
{
- int irq, bit;
+ int irq;
Vctl *v;
- /* figure out which bit */
- for(bit = 0; bit < 32; bit++)
- if((1<<bit) == mask)
- break;
+ if(type == IRQ){
+ irqenable(which, f, a, name);
+ return;
+ }
- irq = bit;
- if(bit >= nelem(gpiovctl) || bit < 0)
+ /* from here down, it must be a GPIO edge interrupt */
+ irq = which;
+ if(which >= nelem(gpiovctl) || which < 0)
panic("gpiointrenable");
- if(bit > 11)
+ if(which > 11)
irq = 11;
/* the pin had better be configured as input */
- if((1<<bit) & gpioregs->direction)
- panic("gpiointrenable of output pin %d", bit);
+ if((1<<which) & gpioregs->direction)
+ panic("gpiointrenable of output pin %d", which);
/* create a second level vctl for the gpio edge interrupt */
v = xalloc(sizeof(Vctl));
@@ 169,26 170,27 @@ gpiointrenable(ulong mask, int edge, void (*f)(Ureg*, void*), void* a, char *nam
v->name[NAMELEN-1] = 0;
lock(&vctllock);
- v->next = gpiovctl[bit];
- gpiovctl[bit] = v;
+ v->next = gpiovctl[which];
+ gpiovctl[which] = v;
unlock(&vctllock);
/* set edge register to enable interrupt */
- switch(edge){
+ switch(type){
case GPIOboth:
- gpioregs->rising |= mask;
- gpioregs->falling |= mask;
+ gpioregs->rising |= 1<<which;
+ gpioregs->falling |= 1<<which;
break;
case GPIOfalling:
- gpioregs->falling |= mask;
+ gpioregs->falling |= 1<<which;
break;
case GPIOrising:
- gpioregs->rising |= mask;
+ gpioregs->rising |= 1<<which;
break;
}
+ /* point the irq to the gpio interrupt handler */
if(gpioirqref[irq]++ == 0)
- intrenable(irq, gpiointr, nil, "gpio edge");
+ irqenable(irq, gpiointr, nil, "gpio edge");
}
/*
@@ 376,8 378,6 @@ gpiointr(Ureg *ur, void*)
va = gpioregs->edgestatus;
gpioregs->edgestatus = va;
-iprint("gpio intr %lux\n", va);
-
for(i = 0; i < 27; i++){
if(((1<<i) & va) == 0)
continue;
@@ 792,12 792,3 @@ evenaddr(ulong addr)
error(Ebadarg);
}
}
-
-
-/*
- * here on a hardware reset
- */
-void
-reset(void)
-{
-}
M port/cis.c => port/cis.c +8 -2
@@ 411,21 411,27 @@ tentry(PCMslot *pp, Cisdat *cis, int )
static void
tvers1(PCMslot *pp, Cisdat *cis, int )
{
- uchar c, major, minor;
+ uchar c, major, minor, last;
int i;
if(readc(cis, &major) != 1)
return;
if(readc(cis, &minor) != 1)
return;
+ last = 0;
for(i = 0; i < sizeof(pp->verstr)-1; i++){
if(readc(cis, &c) != 1)
return;
if(c == 0)
- c = '\n';
+ c = ';';
+ if(c == '\n')
+ c = ';';
if(c == 0xff)
break;
+ if(c == ';' && last == ';')
+ continue;
pp->verstr[i] = c;
+ last = c;
}
pp->verstr[i] = 0;
}
M port/portdat.h => port/portdat.h +2 -0
@@ 9,6 9,7 @@ typedef struct Dirtab Dirtab;
typedef struct Egrp Egrp;
typedef struct Evalue Evalue;
typedef struct Fgrp Fgrp;
+typedef struct DevConf DevConf;
typedef struct Image Image;
typedef struct List List;
typedef struct Log Log;
@@ 194,6 195,7 @@ struct Dev
void (*remove)(Chan*);
void (*wstat)(Chan*, char*);
void (*power)(int); /* power mgt: power(1) → on, power (0) → off */
+ int (*config)(int, char*, DevConf*);
};
struct Dirtab