M bitsy/clock.c => bitsy/clock.c +1 -0
@@ 30,6 30,7 @@ clockpower(int on)
timerregs->oier = 1<<0;
timerregs->osmr[0] = timerregs->oscr + ClockFreq/HZ;
}
+ clockinited = on;
}
void
M bitsy/power.c => bitsy/power.c +50 -35
@@ 19,6 19,7 @@ ulong powerflag = 0; /* set to start power-off sequence */
extern void sa1100_power_resume(void);
extern int setpowerlabel(void);
+extern void _start(void);
extern Uart sa1110uart[];
GPIOregs savedgpioregs;
@@ 71,29 72,40 @@ gpiocpy(GPIOregs *to, GPIOregs *from)
to->direction = from->direction;
}
+void (*restart)(void) = nil;
+
static void
sa1100_power_off(void)
{
+ cacheflush();
+ mmuinvalidate();
+ mmudisable();
+
/* enable wakeup by µcontroller, on/off switch or real-time clock alarm */
powerregs->pwer = 1 << IRQrtc | 1 << IRQgpio0 | 1 << IRQgpio1;
/* clear previous reset status */
resetregs->rcsr = RCSR_all;
+sa1100_power_resume();
+
/* disable internal oscillator, float CS lines */
powerregs->pcfr = PCFR_opde | PCFR_fp | PCFR_fs;
powerregs->pgsr = 0;
/* set resume address. The loader jumps to it */
- powerregs->pspr = (ulong)sa1100_power_resume;
+// powerregs->pspr = (ulong)sa1100_power_resume;
+// powerregs->pspr = (ulong)_start;
/* set lowest clock; delay to avoid resume hangs on fast sa1110 */
+
delay(90);
- powerregs->ppcr = 0;
+// powerregs->ppcr = 0;
delay(90);
/* set all GPIOs to input mode */
gpioregs->direction = 0;
delay(100);
/* enter sleep mode */
+
powerregs->pmcr = PCFR_suspend;
for(;;);
}
@@ 109,28 121,6 @@ bitno(ulong x)
return i;
}
-void
-onoffintr(Ureg* , void*)
-{
- int i;
-
- /* Power down interrupt comes on power button release.
- * Act only after button has been released a full 100 ms
- */
-
- if (powerflag)
- return;
-
- for (i = 0; i < 100; i++) {
- delay(1);
- if ((gpioregs->level & GPIO_PWR_ON_i) == 0)
- return; /* bounced */
- }
-
- powerflag = 1;
- wakeup(&powerr);
-}
-
int
powerdown(void *)
{
@@ 140,8 130,13 @@ powerdown(void *)
void
deepsleep(void) {
static int power_pl;
+ void *xsp, *xlink;
power_pl = splhi();
+ xsp = getsp();
+ xlink = getlink();
+ iprint("starting power down, sp = %lux, link = %lux\n", xsp, xlink);
+ delay(1000);
cachewb();
delay(500);
if (setpowerlabel()) {
@@ 167,6 162,11 @@ deepsleep(void) {
iprint("\nresuming execution\n");
// dumpitall();
delay(800);
+ delay(1000);
+ xsp = getsp();
+ xlink = getlink();
+ iprint("power restored, sp = %lux, link = %lux\n", xsp, xlink);
+
splx(power_pl);
return;
}
@@ 189,33 189,48 @@ deepsleep(void) {
void
powerkproc(void*)
{
- void *xsp, *xlink;
for(;;){
while(powerflag == 0)
sleep(&powerr, powerdown, 0);
+
+ deepsleep();
+
+ delay(2000);
+
powerflag = 0;
- xsp = getsp();
- xlink = getlink();
- iprint("starting power down, sp = %lux, link = %lux\n", xsp, xlink);
- delay(1000);
+ }
+}
- deepsleep();
+void
+onoffintr(Ureg* , void*)
+{
+ int i;
- delay(1000);
- xsp = getsp();
- xlink = getlink();
- iprint("power restored, sp = %lux, link = %lux\n", xsp, xlink);
+ /* Power down interrupt comes on power button release.
+ * Act only after button has been released a full 100 ms
+ */
+ if (powerflag)
+ return;
+
+ for (i = 0; i < 100; i++) {
+ delay(1);
+ if ((gpioregs->level & GPIO_PWR_ON_i) == 0)
+ return; /* bounced */
}
+
+ deepsleep();
+// powerflag = 1;
+// wakeup(&powerr);
}
void
powerinit(void)
{
- intrenable(GPIOrising, bitno(GPIO_PWR_ON_i), onoffintr, (void*)0x12344321, "on/off");
+ intrenable(GPIOrising, bitno(GPIO_PWR_ON_i), onoffintr, nil, "on/off");
}
void
M bitsy/screen.c => bitsy/screen.c +333 -1
@@ 151,4 151,336 @@ Point curpos;
int h, w;
int drawdebug;
-static ulong rep(u
+static ulong rep(ulong, int);
+static void screenwin(void);
+static void screenputc(char *buf);
+static void bitsyscreenputs(char *s, int n);
+static void scroll(void);
+
+static void
+lcdstop(void) {
+ lcd->lccr0 &= ~(0<<LEN); /* disable the LCD */
+ while((lcd->lcsr & LDD) == 0)
+ delay(10);
+ lcdpower(0);
+}
+
+static void
+lcdinit(void)
+{
+ /* the following line works because main memory is direct mapped */
+ lcd->dbar1 = framebuf->palette;
+ lcd->lccr3 = pcd<<PCD | 0<<ACB | 0<<API | 1<<VSP | 1<<HSP | 0<<PCP | 0<<OEP;
+ lcd->lccr2 = (Wid-1)<<LPP | vsw<<VSW | efw<<EFW | bfw<<BFW;
+ lcd->lccr1 = (Ht-16)<<PPL | hsw<<HSW | elw<<ELW | blw<<BLW;
+ lcd->lccr0 = 1<<LEN | 0<<CMS | 0<<SDS | 1<<LDM | 1<<BAM | 1<<ERM | 1<<PAS | 0<<BLE | 0<<DPD | 0<<PDD;
+}
+
+void
+flipscreen(int ls) {
+ if (ls == landscape)
+ return;
+ if (ls) {
+ gscreen->r = Rect(0, 0, Ht, Wid);
+ gscreen->clipr = gscreen->r;
+ xgdata.bdata = (uchar *)framebuf->pixel;
+ } else {
+ gscreen->r = Rect(0, 0, Wid, Ht);
+ gscreen->clipr = gscreen->r;
+ xgdata.bdata = (uchar *)vscreen;
+ }
+ landscape = ls;
+}
+
+void
+lcdtweak(Cmdbuf *cmd)
+{
+ if(cmd->nf < 4)
+ return;
+ if(*cmd->f[0] == 'h')
+ lcd->lccr1 = ((Ht-16)<<PPL)
+ | (atoi(cmd->f[1])<<HSW)
+ | (atoi(cmd->f[2])<<ELW)
+ | (atoi(cmd->f[3])<<BLW);
+ if(*cmd->f[0] == 'v')
+ lcd->lccr2 = ((Wid-1)<<LPP)
+ | (atoi(cmd->f[1])<<VSW)
+ | (atoi(cmd->f[2])<<EFW)
+ | (atoi(cmd->f[3])<<BFW);
+}
+
+void
+screenpower(int on)
+{
+ if (on == 0){
+ memmove(savedpalette, framebuf->palette, sizeof framebuf->palette);
+ blankscreen(1);
+ } else {
+ memmove(framebuf->palette, savedpalette, sizeof framebuf->palette);
+ blankscreen(0);
+ }
+}
+
+void
+screeninit(void)
+{
+ int i;
+
+ /* map the lcd regs into the kernel's virtual space */
+ lcd = (struct sa1110regs*)mapspecial(LCDREGS, sizeof(struct sa1110regs));;
+
+ framebuf = xspanalloc(sizeof *framebuf, 0x100, 0);
+
+ vscreen = xalloc(sizeof(ushort)*Wid*Ht);
+
+ framebuf->palette[0] = Pal0;
+
+ lcdpower(1);
+ lcdinit();
+
+ gscreen = &xgscreen;
+ xgdata.ref = 1;
+ i = 0;
+ if (landscape) {
+ xgdata.bdata = (uchar *)framebuf->pixel;
+ while (i < Wid*Ht*1/3) framebuf->pixel[i++] = 0xf800; /* red */
+ while (i < Wid*Ht*2/3) framebuf->pixel[i++] = 0xffff; /* white */
+ while (i < Wid*Ht*3/3) framebuf->pixel[i++] = 0x001f; /* blue */
+ } else {
+ xgdata.bdata = (uchar *)vscreen;
+ while (i < Wid*Ht*1/3) vscreen[i++] = 0xf800; /* red */
+ while (i < Wid*Ht*2/3) vscreen[i++] = 0xffff; /* white */
+ while (i < Wid*Ht*3/3) vscreen[i++] = 0x001f; /* blue */
+ flushmemscreen(gscreen->r);
+ }
+ memimageinit();
+ memdefont = getmemdefont();
+
+ out.pos.x = MINX;
+ out.pos.y = 0;
+ out.bwid = memdefont->info[' '].width;
+
+ blanktime = 3; /* minutes */
+
+ screenwin();
+ screenputs = bitsyscreenputs;
+}
+
+void
+flushmemscreen(Rectangle r)
+{
+ int x, y;
+ ulong start, end;
+
+ if (landscape == 0) {
+ if (r.min.x < 0) r.min.x = 0;
+ if (r.max.x > Wid) r.max.x = Wid;
+ if (r.min.y < 0) r.min.y = 0;
+ if (r.max.y > Ht) r.max.y = Ht;
+ for (x = r.min.x; x < r.max.x; x++)
+ for (y = r.min.y; y < r.max.y; y++)
+ framebuf->pixel[(x+1)*Ht-1-y] = gamma[vscreen[y*Wid+x]];
+ start = (ulong)&framebuf->pixel[(r.min.x+1)*Ht-1-(r.max.y-1)];
+ end = (ulong)&framebuf->pixel[(r.max.x-1+1)*Ht-1-(r.min.y)];
+ } else {
+ start = (ulong)&framebuf->pixel[r.min.y*Ht + r.min.x];
+ end = (ulong)&framebuf->pixel[(r.max.y-1)*Ht + r.max.x - 1];
+ }
+ cachewbregion(start, end-start);
+}
+
+/*
+ * export screen to devdraw
+ */
+uchar*
+attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
+{
+ *r = gscreen->r;
+ *d = gscreen->depth;
+ *chan = gscreen->chan;
+ *width = gscreen->width;
+ *softscreen = (landscape == 0);
+
+ return (uchar*)gscreen->data->bdata;
+}
+
+void
+getcolor(ulong p, ulong* pr, ulong* pg, ulong* pb)
+{
+ USED(p, pr, pg, pb);
+}
+
+int
+setcolor(ulong p, ulong r, ulong g, ulong b)
+{
+ USED(p,r,g,b);
+ return 0;
+}
+
+void
+blankscreen(int blank)
+{
+ if (blank) {
+ lcdpower(0);
+ } else {
+ lcdpower(1);
+ lcdinit();
+ }
+}
+
+static void
+bitsyscreenputs(char *s, int n)
+{
+ int i;
+ Rune r;
+ char buf[4];
+
+ if(!islo()) {
+ /* don't deadlock trying to print in interrupt */
+ if(!canlock(&screenlock))
+ return;
+ }
+ else
+ lock(&screenlock);
+
+ while(n > 0){
+ i = chartorune(&r, s);
+ if(i == 0){
+ s++;
+ --n;
+ continue;
+ }
+ memmove(buf, s, i);
+ buf[i] = 0;
+ n -= i;
+ s += i;
+ screenputc(buf);
+ }
+ unlock(&screenlock);
+}
+
+static void
+screenwin(void)
+{
+ Point p, q;
+ char *greet;
+ Memimage *orange;
+ Rectangle r;
+
+ memsetchan(gscreen, RGB16);
+
+ back = memwhite;
+ conscol = memblack;
+
+ orange = allocmemimage(Rect(0,0,1,1), RGB16);
+ orange->flags |= Frepl;
+ orange->clipr = gscreen->r;
+ orange->data->bdata[0] = 0x40;
+ orange->data->bdata[1] = 0xfd;
+
+ w = memdefont->info[' '].width;
+ h = memdefont->height;
+
+ r = insetrect(gscreen->r, 4);
+
+ memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP);
+ window = insetrect(r, 4);
+ memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP);
+
+ memimagedraw(gscreen, Rect(window.min.x, window.min.y,
+ window.max.x, window.min.y+h+5+6), orange, ZP, nil, ZP);
+ freememimage(orange);
+ window = insetrect(window, 5);
+
+ greet = " Plan 9 Console ";
+ p = addpt(window.min, Pt(10, 0));
+ q = memsubfontwidth(memdefont, greet);
+ memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
+ flushmemscreen(r);
+ window.min.y += h+6;
+ curpos = window.min;
+ window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
+}
+
+static void
+screenputc(char *buf)
+{
+ Point p;
+ int w, pos;
+ Rectangle r;
+ static int *xp;
+ static int xbuf[256];
+
+ if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
+ xp = xbuf;
+
+ switch(buf[0]) {
+ case '\n':
+ if(curpos.y+h >= window.max.y)
+ scroll();
+ curpos.y += h;
+ screenputc("\r");
+ break;
+ case '\r':
+ xp = xbuf;
+ curpos.x = window.min.x;
+ break;
+ case '\t':
+ p = memsubfontwidth(memdefont, " ");
+ w = p.x;
+ if(curpos.x >= window.max.x-4*w)
+ screenputc("\n");
+
+ pos = (curpos.x-window.min.x)/w;
+ pos = 4-(pos%4);
+ *xp++ = curpos.x;
+ r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
+ memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min);
+ flushmemscreen(r);
+ curpos.x += pos*w;
+ break;
+ case '\b':
+ if(xp <= xbuf)
+ break;
+ xp--;
+ r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
+ memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min);
+ flushmemscreen(r);
+ curpos.x = *xp;
+ break;
+ case '\0':
+ break;
+ default:
+ p = memsubfontwidth(memdefont, buf);
+ w = p.x;
+
+ if(curpos.x >= window.max.x-w)
+ screenputc("\n");
+
+ *xp++ = curpos.x;
+ r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h);
+ memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min);
+ memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
+ flushmemscreen(r);
+ curpos.x += w;
+ }
+}
+
+static void
+scroll(void)
+{
+ int o;
+ Point p;
+ Rectangle r;
+
+ o = 8*h;
+ r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
+ p = Pt(window.min.x, window.min.y+o);
+ memimagedraw(gscreen, r, gscreen, p, nil, p);
+ flushmemscreen(r);
+ r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
+ memimagedraw(gscreen, r, back, ZP, nil, ZP);
+ flushmemscreen(r);
+
+ curpos.y -= o;
+}
M pc/devarch.c => pc/devarch.c +55 -0
@@ 11,6 11,7 @@ typedef struct IOMap IOMap;
struct IOMap
{
IOMap *next;
+ int reserved;
char tag[13];
ulong start;
ulong end;
@@ 103,6 104,54 @@ ioinit(void)
// a dummy entry at 2^16
ioalloc(0x10000, 1, 0, "dummy");
+ ioalloc(0x1000, 1, 0, "dummy");
+}
+
+// Reserve a range to be ioalloced later. This is in particular useful for exchangable cards, such
+// as pcmcia and cardbus cards.
+int
+ioreserve(int port, int size, int align, char *tag)
+{
+ IOMap *m, **l;
+ int i;
+
+ lock(&iomap);
+ // find a free port above 0x400 and below 0x1000
+ port = 0x400;
+ for(l = &iomap.m; *l; l = &(*l)->next){
+ m = *l;
+ if (m->start < 0x400) continue;
+ i = m->start - port;
+ if(i > size)
+ break;
+ if(align > 0)
+ port = ((port+align-1)/align)*align;
+ else
+ port = m->end;
+ }
+ if(*l == nil){
+ unlock(&iomap);
+ return -1;
+ }
+ m = iomap.free;
+ if(m == nil){
+ print("ioalloc: out of maps");
+ unlock(&iomap);
+ return port;
+ }
+ iomap.free = m->next;
+ m->next = *l;
+ m->start = port;
+ m->end = port + size;
+ m->reserved = 1;
+ strncpy(m->tag, tag, sizeof(m->tag));
+ m->tag[sizeof(m->tag)-1] = 0;
+ *l = m;
+
+ archdir[0].qid.vers++;
+
+ unlock(&iomap);
+ return m->start;
}
//
@@ 121,6 170,7 @@ ioalloc(int port, int size, int align, char *tag)
port = 0x400;
for(l = &iomap.m; *l; l = &(*l)->next){
m = *l;
+ if (m->start < 0x400) continue;
i = m->start - port;
if(i > size)
break;
@@ 144,6 194,11 @@ ioalloc(int port, int size, int align, char *tag)
m = *l;
if(m->end <= port)
continue;
+ if(m->reserved && m->start == port && m->end == port + size) {
+ m->reserved = 0;
+ unlock(&iomap);
+ return m->start;
+ }
if(m->start >= port+size)
break;
unlock(&iomap);
M pc/devether.c => pc/devether.c +1 -0
@@ 354,6 354,7 @@ etherreset(void)
int i, n, ctlrno;
char name[32], buf[128];
+ print("Searching for ethernet devices\n");
for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
if(ether == 0)
ether = malloc(sizeof(Ether));
M pc/etherelnk3.c => pc/etherelnk3.c +51 -12
@@ 167,6 167,7 @@ enum { /* Window 0 - setup */
auiAvailable9 = 0x2000,
/* EepromCommand bits */
EepromReadRegister = 0x0080,
+ EepromRead8bRegister = 0x0230,
EepromBusy = 0x8000,
};
@@ 571,6 572,13 @@ multicast(void* arg, uchar *addr, int on)
COMMAND(port, SetRxFilter, filter);
}
+/* On the 575B and C, interrupts need to be acknowledged in CardBus memory space */
+static void
+intrack3c575(ulong *cbfns)
+{
+ cbfns[1] = 0x8000;
+}
+
static void
attach(Ether* ether)
{
@@ 604,10 612,13 @@ attach(Ether* ether)
}
COMMAND(port, SetIndicationEnable, x);
COMMAND(port, SetInterruptEnable, x);
-
COMMAND(port, RxEnable, 0);
COMMAND(port, TxEnable, 0);
+ if (ether->mem)
+ /* This must be a cardbus card. Acknowledge the interrupt */
+ intrack3c575(KADDR(ether->mem));
+
/*
* Prime the busmaster channel for receiving directly into a
* receive packet buffer if necessary.
@@ 1127,6 1138,8 @@ interrupt(Ureg*, void* arg)
panic("#l%d: interrupt mask 0x%uX\n", ether->ctlrno, status);
COMMAND(port, AcknowledgeInterrupt, interruptLatch);
+ if (ether->mem) intrack3c575((ulong *)KADDR(ether->mem));
+
}while((status = STATUS(port)) & (interruptMask|interruptLatch));
if(ctlr->busmaster == 2)
@@ 1220,11 1233,13 @@ typedef struct Adapter {
int port;
int irq;
int tbdf;
+ int did;
+ ulong cbfns;
} Adapter;
static Block* adapter;
static void
-tcmadapter(int port, int irq, int tbdf)
+tcmadapter(int port, int irq, int tbdf, int did, ulong cbfns)
{
Block *bp;
Adapter *ap;
@@ 1236,6 1251,8 @@ tcmadapter(int port, int irq, int tbdf)
ap->port = port;
ap->irq = irq;
ap->tbdf = tbdf;
+ ap->did = did;
+ ap->cbfns = cbfns;
bp->next = adapter;
adapter = bp;
@@ 1385,7 1402,7 @@ tcm509isa(void)
COMMAND(port, AcknowledgeInterrupt, 0xFF);
irq = (ins(port+ResourceConfig)>>12) & 0x0F;
- tcmadapter(port, irq, BUSUNKNOWN);
+ tcmadapter(port, irq, BUSUNKNOWN, 0, 0);
}
}
@@ 1431,7 1448,7 @@ tcm5XXeisa(void)
COMMAND(port, AcknowledgeInterrupt, 0xFF);
irq = (ins(port+ResourceConfig)>>12) & 0x0F;
- tcmadapter(port, irq, BUSUNKNOWN);
+ tcmadapter(port, irq, BUSUNKNOWN, 0, 0);
}
}
@@ 1443,6 1460,8 @@ tcm59Xpci(void)
p = nil;
while(p = pcimatch(p, 0x10B7, 0)){
+ ulong bar;
+
/*
* Not prepared to deal with memory-mapped
* devices yet.
@@ 1459,7 1478,14 @@ tcm59Xpci(void)
while(STATUS(port) & commandInProgress)
;
- tcmadapter(port, irq, p->tbdf);
+ bar = 0;
+ if (p->did == 0x5157) {
+ /* Map the CardBus functions */
+ bar = pcicfgr32(p, PciBAR2);
+ print("tcmp59Xpci: CardBus functions at %.8uX\n", bar & ~KZERO);
+ }
+
+ tcmadapter(port, irq, p->tbdf, p->did, bar);
pcisetbme(p);
}
}
@@ 1711,12 1737,12 @@ autoselect(int port, int xcvr, int is9)
}
static int
-eepromdata(int port, int offset)
+eepromdata(int did, int port, int offset)
{
COMMAND(port, SelectRegisterWindow, Wsetup);
while(EEPROMBUSY(port))
;
- EEPROMCMD(port, EepromReadRegister, offset);
+ EEPROMCMD(port, (did == 0x5157)? EepromRead8bRegister: EepromReadRegister, offset);
while(EEPROMBUSY(port))
;
return EEPROMDATA(port);
@@ 1750,13 1776,16 @@ etherelnk3reset(Ether* ether)
* otherwise the ports must match.
*/
port = 0;
+ did = 0;
bpp = &adapter;
for(bp = *bpp; bp; bp = bp->next){
ap = (Adapter*)bp->rp;
if(ether->port == 0 || ether->port == ap->port){
port = ap->port;
+ did = ap->did;
ether->irq = ap->irq;
ether->tbdf = ap->tbdf;
+ ether->mem = ap->cbfns;
*bpp = bp->next;
freeb(bp);
break;
@@ 1770,7 1799,7 @@ etherelnk3reset(Ether* ether)
* Read the DeviceID from the EEPROM, it's at offset 0x03,
* and do something depending on capabilities.
*/
- switch(did = eepromdata(port, 0x03)){
+ switch(did = eepromdata(did, port, 0x03)){
case 0x9000:
case 0x9001:
@@ 1779,6 1808,7 @@ etherelnk3reset(Ether* ether)
case 0x9051:
case 0x9055:
case 0x9200:
+ case 0x5157: /* 3C575 Cyclone */
if(BUSTYPE(ether->tbdf) != BusPCI)
goto buggery;
busmaster = 2;
@@ 1822,7 1852,7 @@ etherelnk3reset(Ether* ether)
memset(ea, 0, Eaddrlen);
if(memcmp(ea, ether->ea, Eaddrlen) == 0){
for(i = 0; i < Eaddrlen/2; i++){
- x = eepromdata(port, i);
+ x = eepromdata(did, port, i);
ether->ea[2*i] = x>>8;
ether->ea[2*i+1] = x;
}
@@ 1854,10 1884,18 @@ etherelnk3reset(Ether* ether)
/*
* forgive me, but i am weak
*/
- if(did == 0x9055 || did == 0x9200){
+ if(did == 0x9055 || did == 0x9200 || did == 0x5157){
xcvr = xcvrMii;
txrxreset(port);
XCVRDEBUG("905[BC] reset ops 0x%uX\n", ins(port+ResetOp905B));
+ if (did == 0x5157) {
+ ushort reset_opts;
+
+ COMMAND(port, SelectRegisterWindow, Wstation);
+ reset_opts = ins(port + ResetOp905B);
+ reset_opts |= 0x0010; /* Invert LED */
+ outs(port + ResetOp905B, reset_opts);
+ }
}
else if(xcvr & autoSelect)
xcvr = autoselect(port, xcvr, rxstatus9);
@@ 1870,7 1908,7 @@ etherelnk3reset(Ether* ether)
* Quick hack.
scanphy(port);
*/
- phyaddr = 24;
+ phyaddr = (did == 0x5157)? 0: 24;
for(i = 0; i < 7; i++)
XCVRDEBUG(" %2.2uX", miir(port, phyaddr, i));
XCVRDEBUG("\n");
@@ 2016,7 2054,7 @@ etherelnk3reset(Ether* ether)
* until the whole packet has been received.
*/
ctlr->upenabled = 1;
- x = eepromdata(port, 0x0F);
+ x = eepromdata(did, port, 0x0F);
if(!(x & 0x01))
outl(port+PktStatus, upRxEarlyEnable);
@@ 2072,4 2110,5 @@ etherelnk3link(void)
{
addethercard("elnk3", etherelnk3reset);
addethercard("3C509", etherelnk3reset);
+ addethercard("3C575", etherelnk3reset);
}
M pc/fns.h => pc/fns.h +4 -0
@@ 6,6 6,7 @@ Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,v
//void addscsilink(char*, Scsiio (*)(int, ISAConf*));
void archinit(void);
void bootargs(ulong);
+void cbinit(void);
vlong checkcycintr(Ureg*, void*);
int cistrcmp(char*, char*);
int cistrncmp(char*, char*, int);
@@ 59,6 60,7 @@ void iofree(int);
void ioinit(void);
int iounused(int, int);
int ioalloc(int, int, int, char*);
+int ioreserve(int, int, int, char*);
int iprint(char*, ...);
int isaconfig(char*, int, ISAConf*);
void kbdinit(void);
@@ 83,6 85,8 @@ void outs(int, ushort);
void outss(int, void*, int);
void outl(int, ulong);
void outsl(int, void*, int);
+int pciscan(int, Pcidev **);
+ulong pcibarsize(Pcidev *, int);
int pcicfgr8(Pcidev*, int);
int pcicfgr16(Pcidev*, int);
int pcicfgr32(Pcidev*, int);
M pc/io.h => pc/io.h +4 -0
@@ 191,6 191,10 @@ struct Pcidev
int size;
} mem[6];
+ struct {
+ ulong bar;
+ int size;
+ } rom;
uchar intl; /* interrupt line */
Pcidev* list;
M pc/pci.c => pc/pci.c +31 -11
@@ 57,7 57,7 @@ enum
};
static Lock pcicfglock;
-static Lock pcicfginitlock;
+static QLock pcicfginitlock;
static int pcicfgmode = -1;
static int pcimaxbno = 7;
static int pcimaxdno;
@@ 359,7 359,7 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg)
}
static int
-pciscan(int bno, Pcidev** list)
+pcilscan(int bno, Pcidev** list)
{
Pcidev *p, *head, *tail;
int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
@@ 482,20 482,31 @@ pciscan(int bno, Pcidev** list)
l = (MaxUBN<<16)|(sbn<<8)|bno;
pcicfgw32(p, PciPBN, l);
pcicfgw16(p, PciSPSR, 0xFFFF);
- maxubn = pciscan(sbn, &p->bridge);
+ maxubn = pcilscan(sbn, &p->bridge);
l = (maxubn<<16)|(sbn<<8)|bno;
pcicfgw32(p, PciPBN, l);
}
else {
maxubn = ubn;
- pciscan(sbn, &p->bridge);
+ pcilscan(sbn, &p->bridge);
}
}
return maxubn;
}
+int
+pciscan(int bno, Pcidev **list)
+{
+ int ubn;
+
+ qlock(&pcicfginitlock);
+ ubn = pcilscan(bno, list);
+ qunlock(&pcicfginitlock);
+ return ubn;
+}
+
static void
pcicfginit(void)
{
@@ 504,7 515,7 @@ pcicfginit(void)
Pcidev **list;
ulong mema, ioa;
- lock(&pcicfginitlock);
+ qlock(&pcicfginitlock);
if(pcicfgmode != -1)
goto out;
@@ 543,7 554,7 @@ pcicfginit(void)
list = &pciroot;
for(bno = 0; bno <= pcimaxbno; bno++) {
- bno = pciscan(bno, list);
+ bno = pcilscan(bno, list);
while(*list)
list = &(*list)->link;
}
@@ 573,11 584,12 @@ pcicfginit(void)
pcibusmap(pciroot, &mema, &ioa, 1);
DBG("Sizes2: mem=%lux io=%lux\n", mema, ioa);
- unlock(&pcicfginitlock);
+ qunlock(&pcicfginitlock);
return;
}
out:
- unlock(&pcicfginitlock);
+ qunlock(&pcicfginitlock);
+ cbinit();
}
static int
@@ 785,8 797,8 @@ pcimatchtbdf(int tbdf)
return pcidev;
}
-void
-pcihinv(Pcidev* p)
+static void
+pcilhinv(Pcidev* p)
{
int i;
Pcidev *t;
@@ 819,7 831,15 @@ pcihinv(Pcidev* p)
if(p->bridge != nil)
pcihinv(p->bridge);
p = p->link;
- }
+ }
+}
+
+void
+pcihinv(Pcidev* p)
+{
+ qlock(&pcicfginitlock);
+ pcilhinv(p);
+ qunlock(&pcicfginitlock);
}
void