From f1c292848e331e5616ed0b966692ffb23c6580fd Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 19 Jun 2001 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2001-06-19 --- bitsy/dat.h | 14 ----- bitsy/devpcmcia.c | 19 +++--- bitsy/fns.h | 1 + bitsy/l.s | 2 - bitsy/main.c | 1 - bitsy/power.c | 39 +++++-------- bitsy/uartsa1110.c | 35 ++++++++++- pc/devi82365.c | 5 +- pc/io.h | 13 ----- pc/sdscsi.c | 2 + port/cis.c | 84 +++++++++++++++++++-------- port/devmnt.c | 142 ++++++++++++++++++++++++--------------------- port/devuart.c | 12 ++++ port/error.h | 6 +- port/portdat.h | 2 + port/portfns.h | 2 + port/qio.c | 131 ++++++++++++++++++++++++++--------------- 17 files changed, 301 insertions(+), 209 deletions(-) diff --git a/bitsy/dat.h b/bitsy/dat.h index d5b9c6c4a6aa2270cd61410d9b03495b3b207b94..f3071fb9783b73dbacdd0f3935899543cce29b72 100644 --- a/bitsy/dat.h +++ b/bitsy/dat.h @@ -226,17 +226,6 @@ struct PCMconftab ulong otherwait; }; -/* - * For walking a PCMCIA card's information structure - */ -struct Cisdat -{ - uchar *cisbase; - int cispos; - int cisskip; - int cislen; -}; - /* * PCMCIA card slot */ @@ -265,9 +254,6 @@ struct PCMslot PCMconftab ctab[8]; PCMconftab *def; /* default conftab */ - /* for walking through cis */ - Cisdat; - /* maps are fixed */ PCMmap memmap; PCMmap attrmap; diff --git a/bitsy/devpcmcia.c b/bitsy/devpcmcia.c index 2656bd1074d6cff27cf99f67d24a7c70a5d99835..aa8e744b3fd7f721b99e234e3a9e1c0a5ce3e839 100644 --- a/bitsy/devpcmcia.c +++ b/bitsy/devpcmcia.c @@ -44,7 +44,7 @@ static void slotinfo(Ureg*, void*); #define PATH(s,t) (((s)<<8)|(t)) static PCMslot* -slotno(Chan *c) +slotof(Chan *c) { ulong x; @@ -89,6 +89,7 @@ pcmgen(Chan *c, char *, Dirtab * , int, int i, Dir *dp) break; } qid.vers = 0; + qid.type = QTFILE; devdir(c, qid, up->genbuf, len, eve, 0660, dp); return 1; } @@ -148,12 +149,15 @@ pcmciastat(Chan *c, uchar *db, int n) static Chan* pcmciaopen(Chan *c, int omode) { - print("pcmciaopen\n"); + PCMslot *slotp; + if(c->qid.type & QTDIR){ if(omode != OREAD) error(Eperm); - } else - increfp(slotno(c)); + } else { + slotp = slotof(c); + increfp(slotp); + } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; @@ -165,7 +169,7 @@ pcmciaclose(Chan *c) { if(c->flag & COPEN) if((c->qid.type & QTDIR) == 0) - decrefp(slotno(c)); + decrefp(slotof(c)); } /* a memmove using only bytes */ @@ -244,7 +248,7 @@ pcmciaread(Chan *c, void *a, long n, vlong off) PCMslot *sp; ulong offset = off; - sp = slotno(c); + sp = slotof(c); switch(TYPE(c)){ case Qdir: @@ -356,7 +360,7 @@ pcmciawrite(Chan *c, void *a, long n, vlong off) PCMslot *sp; ulong offset = off; - sp = slotno(c); + sp = slotof(c); switch(TYPE(c)){ case Qmem: @@ -430,7 +434,6 @@ slotinfo(Ureg*, void*) static void increfp(PCMslot *sp) { - print("increfp\n"); wlock(sp); if(waserror()){ wunlock(sp); diff --git a/bitsy/fns.h b/bitsy/fns.h index 1cd2a73f1af58b30cfd1fe7a096eadd9f3af3cf8..6a3fa6319df397224ccd1bbd721b8dc143b42d44 100644 --- a/bitsy/fns.h +++ b/bitsy/fns.h @@ -91,6 +91,7 @@ void trapdump(char *tag); void trapinit(void); void trapresume(void); int tas(void*); +void uartpower(int); int uartstageoutput(Uart*); void uartkick(void*); void uartrecv(Uart*, char); diff --git a/bitsy/l.s b/bitsy/l.s index 84174dff66f4ba01671225540d008979869b9643..bf214bae92126373ae0d2dfed42664a0defc2973 100644 --- a/bitsy/l.s +++ b/bitsy/l.s @@ -624,8 +624,6 @@ TEXT sa1100_power_resume(SB), $-4 loop: B loop - - /* The first MCR instruction of this function needs to be on a cache-line * boundary; to make this happen, it will be copied (in trap.c). * diff --git a/bitsy/main.c b/bitsy/main.c index 2d05c000dc3fb7a0bdc102b10f1641ad0ef4ec4e..4f7227be40a3460c074ad8ff6c21e59d7bef5b59 100644 --- a/bitsy/main.c +++ b/bitsy/main.c @@ -364,7 +364,6 @@ PPCregs *ppcregs; MemConfRegs *memconfregs; PowerRegs *powerregs; ResetRegs *resetregs; -OSTimerRegs *timerregs = (OSTimerRegs*)OSTIMERREGS; /* * configure the machine diff --git a/bitsy/power.c b/bitsy/power.c index 056f722b834433938a373eac7d3fbbbb768ae9ea..6cc854dabb380603c3c58d52dad728f6b2cc9eb9 100644 --- a/bitsy/power.c +++ b/bitsy/power.c @@ -15,15 +15,14 @@ */ ulong power_resume[200/4]; -extern void sa1100_power_resume(void); -extern int setpowerlabel(void); - +extern void sa1100_power_resume(void); +extern int setpowerlabel(void); +extern Uart sa1110uart[]; GPIOregs savedgpioregs; -Uartregs saveduart3regs; -Uartregs saveduart1regs; Intrregs savedintrregs; +#define R(p) ((Uartregs*)((p)->regs)) static void dumpitall(void) @@ -36,8 +35,8 @@ dumpitall(void) gpioregs->direction, gpioregs->rising, gpioregs->falling, gpioregs->edgestatus, gpioregs->altfunc); iprint("uart1: %lux %lux %lux \nuart3: %lux %lux %lux\n", - uart1regs->ctl[0], uart1regs->status[0], uart1regs->status[1], - uart3regs->ctl[0], uart3regs->status[0], uart3regs->status[1]); + R(&sa1110uart[0])->ctl[0], R(&sa1110uart[0])->status[0], R(&sa1110uart[0])->status[1], + R(&sa1110uart[1])->ctl[0], R(&sa1110uart[1])->status[0], R(&sa1110uart[1])->status[1]); iprint("tmr: osmr %lux %lux %lux %lux oscr %lux ossr %lux oier %lux\n", timerregs->osmr[0], timerregs->osmr[1], timerregs->osmr[2], timerregs->osmr[3], @@ -61,16 +60,6 @@ intrcpy(Intrregs *to, Intrregs *from) to->icmr = from->icmr; // interrupts enabled } -static void -uartcpy(Uartregs *to, Uartregs *from) -{ - to->ctl[0] = from->ctl[0]; -// to->ctl[1] = from->ctl[1]; -// to->ctl[2] = from->ctl[2]; - to->ctl[3] = from->ctl[3]; - -} - static void gpiocpy(GPIOregs *to, GPIOregs *from) { @@ -83,8 +72,10 @@ gpiocpy(GPIOregs *to, GPIOregs *from) static void sa1100_power_off(void) { + iprint("11.."); /* enable wakeup by µcontroller, on/off switch or real-time clock alarm */ powerregs->pwer = 1 << IRQrtc | 1 << IRQgpio0 | 1 << IRQgpio1; + iprint("12.."); /* clear previous reset status */ resetregs->rcsr = RCSR_all; @@ -126,8 +117,6 @@ onoffintr(Ureg* , void*) cacheflush(); trapresume(); rs232power(1); - irpower(1); - audiopower(1); clockpower(1); gpclkregs->r0 = 1<<0; gpiocpy(gpioregs, &savedgpioregs); @@ -137,12 +126,11 @@ onoffintr(Ureg* , void*) gpioregs->edgestatus = (1<icip = (1<status[0] = uart3regs->status[0]; - uartcpy(uart1regs,&saveduart1regs); - uart1regs->status[0] = uart1regs->status[0]; + uartpower(1); µcpower(1); screenpower(1); + irpower(1); + audiopower(1); iprint("\nresuming execution\n"); // dumpitall(); delay(800); @@ -153,15 +141,16 @@ onoffintr(Ureg* , void*) iprint("\nentering suspend mode\n"); gpiocpy(&savedgpioregs, gpioregs); intrcpy(&savedintrregs, intrregs); - uartcpy(&saveduart3regs, uart3regs); - uartcpy(&saveduart1regs, uart1regs); delay(400); clockpower(0); irpower(0); audiopower(0); screenpower(0); µcpower(0); + uartpower(0); + iprint("rs\n"); rs232power(0); + iprint("10.."); sa1100_power_off(); /* no return */ } diff --git a/bitsy/uartsa1110.c b/bitsy/uartsa1110.c index f99d50d082079e9390101e3917e5f6b9a26f90ec..6c297bab7b86f87de6f61a846dc7e46f208ccd62 100644 --- a/bitsy/uartsa1110.c +++ b/bitsy/uartsa1110.c @@ -10,6 +10,8 @@ /* this isn't strictly an sa1110 driver. The rts/cts stuff is h3650 specific */ +static void sa1110_uartpower(Uart *, int); + enum { /* ctl[0] bits */ @@ -53,7 +55,8 @@ enum extern PhysUart sa1110physuart; -static Uart sa1110uart[2] = { +//static +Uart sa1110uart[2] = { { .regs = UART3REGS, .name = "serialport3", .freq = ClockFreq, @@ -80,7 +83,8 @@ static Uart sa1110uart[2] = { static Uart* consuart; static Uart* µcuart; -#define R(p) ((Uartregs*)(p->regs)) +#define R(p) ((Uartregs*)((p)->regs)) +#define SR(p) ((Uartregs*)((p)->saveregs)) /* * enable a port's interrupts. set DTR and RTS @@ -392,6 +396,7 @@ PhysUart sa1110physuart = { .rts= sa1110_uartrts, .dtr= sa1110_uartdtr, .status= sa1110_uartstatus, + .power= sa1110_uartpower, }; /* @@ -456,7 +461,7 @@ sa1110_uartsetup(int console) /* external serial port (eia0) */ p = &sa1110uart[0]; p->regs = mapspecial(UART3REGS, 64); - + p->saveregs = xalloc(sizeof(Uartregs)); /* set eia0 up as a console */ if(console){ uartctl(p, "b115200 l8 pn s1"); @@ -473,9 +478,33 @@ sa1110_uartsetup(int console) p = &sa1110uart[1]; p->regs = mapspecial(UART1REGS, 64); + p->saveregs = xalloc(sizeof(Uartregs)); uartctl(p, "b115200 l8 pn s1"); µcuart = p; p->special = 1; (*p->phys->enable)(p, 0); intrenable(IRQ, IRQuart1b, sa1110_uartintr, p, p->name); } + +static void +uartcpy(Uartregs *to, Uartregs *from) +{ + to->ctl[0] = from->ctl[0]; +// to->ctl[1] = from->ctl[1]; +// to->ctl[2] = from->ctl[2]; + to->ctl[3] = from->ctl[3]; + +} + +static void +sa1110_uartpower(Uart *p, int powerup) +{ + if (powerup) { + /* power up, restore the registers */ + uartcpy(R(p), SR(p)); + R(p)->status[0] = R(p)->status[0]; + } else { + /* power down, save the registers */ + uartcpy(SR(p), R(p)); + } +} diff --git a/pc/devi82365.c b/pc/devi82365.c index 67a6f551d4e1bddd7e7b7c4c16a798c29e004bcf..5ad17cc5b7630fc3ad9d3fa0bd0d670028598822 100644 --- a/pc/devi82365.c +++ b/pc/devi82365.c @@ -975,7 +975,10 @@ pcmio(int slotno, ISAConf *isa) x |= x<<4; wrreg(pp, Rio, x); - /* enable io port map 0 */ + /* + * enable io port map 0 + * the 'top' register value includes the last valid address + */ if(isa->port == 0) isa->port = ct->io[0].start; we = rdreg(pp, Rwe); diff --git a/pc/io.h b/pc/io.h index a0149acd9b15817e2c9fa0ade36dd926bbef1317..9d4378edab7bd6aa089c90a8c130e32cd3d3f692 100644 --- a/pc/io.h +++ b/pc/io.h @@ -241,7 +241,6 @@ struct SMBus { typedef struct PCMslot PCMslot; typedef struct PCMconftab PCMconftab; -typedef struct Cisdat Cisdat; /* * Map between ISA memory space and PCMCIA card memory space. @@ -275,15 +274,6 @@ struct PCMconftab ulong otherwait; }; -/* cis memory walking */ -struct Cisdat -{ - uchar *cisbase; - int cispos; - int cisskip; - int cislen; -}; - /* a card slot */ struct PCMslot { @@ -315,9 +305,6 @@ struct PCMslot PCMconftab ctab[8]; PCMconftab *def; /* default conftab */ - /* for walking through cis */ - Cisdat; - /* memory maps */ Lock mlock; /* lock down the maps */ int time; diff --git a/pc/sdscsi.c b/pc/sdscsi.c index 6c7bc094fd38aec099c37dd9fca73505e6595e5b..e98b4b0260e4d2a64c4a35ede3da7664ab842829 100644 --- a/pc/sdscsi.c +++ b/pc/sdscsi.c @@ -211,6 +211,8 @@ scsionline(SDunit* unit) break; case 0: unit->sectors = (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3]; + if(unit->sectors == 0) + continue; /* * Read-capacity returns the LBA of the last sector, * therefore the number of sectors must be incremented. diff --git a/port/cis.c b/port/cis.c index a3113f4fd2d6842e928b451bf4ca8033e8144b76..9c6166ab374cb3958f09bd47f6a2f74b1c58ba50 100644 --- a/port/cis.c +++ b/port/cis.c @@ -6,31 +6,29 @@ #include "../port/error.h" #include "io.h" - /* * read and crack the card information structure enough to set * important parameters like power */ +/* cis memory walking */ +typedef struct Cisdat { + uchar *cisbase; + int cispos; + int cisskip; + int cislen; +} Cisdat; + static void tcfig(PCMslot*, Cisdat*, int); static void tentry(PCMslot*, Cisdat*, int); static void tvers1(PCMslot*, Cisdat*, int); -struct { - int n; - void (*parse)(PCMslot*, Cisdat*, int); -} cistab[] = { - 0x15, tvers1, - 0x1A, tcfig, - 0x1B, tentry, -}; - static int -readc(Cisdat *pp, uchar *x) +readc(Cisdat *cis, uchar *x) { - if(pp->cispos >= pp->cislen) + if(cis->cispos >= cis->cislen) return 0; - *x = pp->cisbase[pp->cisskip*pp->cispos]; - pp->cispos++; + *x = cis->cisbase[cis->cisskip*cis->cispos]; + cis->cispos++; return 1; } @@ -102,9 +100,10 @@ pcmcistuple(int slotno, int tuple, int subtuple, void *v, int nv) void pcmcisread(PCMslot *pp) { - uchar v[256]; - int i, nv; + int this; Cisdat cis; + PCMmap *m; + uchar type, link; memset(pp->ctab, 0, sizeof(pp->ctab)); pp->caddr = 0; @@ -113,16 +112,47 @@ pcmcisread(PCMslot *pp) pp->nctab = 0; pp->verstr[0] = 0; - for(i = 0; i < nelem(cistab); i++) { - if((nv = pcmcistuple(pp->slotno, cistab[i].n, -1, v, sizeof(v))) >= 0) { - cis.cisbase = v; - cis.cispos = 0; - cis.cisskip = 1; - cis.cislen = nv; - - (*cistab[i].parse)(pp, &cis, cistab[i].n); + /* + * Read all tuples in attribute space. + */ + m = pcmmap(pp->slotno, 0, 0, 1); + if(m == 0) + return; + + cis.cisbase = KADDR(m->isa); + cis.cispos = 0; + cis.cisskip = 2; + cis.cislen = m->len; + + /* loop through all the tuples */ + for(;;){ + this = cis.cispos; + if(readc(&cis, &type) != 1) + break; + if(type == 0xFF) + break; + if(readc(&cis, &link) != 1) + break; + + switch(type){ + default: + break; + case 0x15: + tvers1(pp, &cis, type); + break; + case 0x1A: + tcfig(pp, &cis, type); + break; + case 0x1B: + tentry(pp, &cis, type); + break; } + + if(link == 0xFF) + break; + cis.cispos = this + (2+link); } + pcmunmap(pp->slotno, m); } static ulong @@ -301,10 +331,14 @@ iospaces(Cisdat *cis, PCMconftab *ct) if(readc(cis, &c) != 1) return; + /* + * For each of the range descriptions read the + * start address and the length (value is length-1). + */ nio = (c&0xf)+1; for(i = 0; i < nio; i++){ ct->io[i].start = getlong(cis, (c>>4)&0x3); - ct->io[i].len = getlong(cis, (c>>6)&0x3); + ct->io[i].len = getlong(cis, (c>>6)&0x3)+1; } ct->nio = nio; } diff --git a/port/devmnt.c b/port/devmnt.c index 404d506057262e104224dc6d2cf9e05314edb719..bfb041fe342bd23989f6bea5b2f8724943d51b68 100644 --- a/port/devmnt.c +++ b/port/devmnt.c @@ -12,10 +12,11 @@ struct Mntrpc Chan* c; /* Channel for whom we are working */ Mntrpc* list; /* Free/pending list */ Fcall request; /* Outgoing file system protocol message */ - Fcall reply; /* Incoming reply */ + Fcall reply; /* Incoming reply */ Mnt* m; /* Mount device during rpc */ Rendez r; /* Place to hang out */ uchar* rpc; /* I/O Data buffer */ + Block *b; /* reply blocks */ char done; /* Rpc completed */ uvlong stime; /* start time for mnt statistics */ ulong reqlen; /* request length for mnt statistics */ @@ -126,6 +127,7 @@ mntattach(char *muxattach) m->list = mntalloc.list; mntalloc.list = m; m->id = mntalloc.id++; + m->q = qopen(10*MAXRPC, 0, nil, nil); unlock(&mntalloc); lock(m); @@ -211,13 +213,6 @@ mntwalk(Chan *c, Chan *nc, char **name, int nname) Mntrpc *r; Walkqid *wq; -if(0){ - print("mntwalk "); - for(i=0; i MAXWELEM) error("devmnt: too many name elements"); alloc = 0; @@ -415,6 +410,7 @@ void mntpntfree(Mnt *m) { Mnt *f, **l; + Queue *q; lock(&mntalloc); l = &mntalloc.list; @@ -425,10 +421,12 @@ mntpntfree(Mnt *m) } l = &f->list; } - m->list = mntalloc.mntfree; mntalloc.mntfree = m; + q = m->q; unlock(&mntalloc); + + qfree(q); } static void @@ -553,7 +551,7 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off) nr = nreq; if(type == Tread) - memmove(uba, r->reply.data, nr); + r->b = bl2mem((uchar*)uba, r->b, nr); else if(cache) cwrite(c, (uchar*)uba, nr, off); @@ -660,68 +658,79 @@ mountio(Mnt *m, Mntrpc *r) mntflushfree(m, r); } -int -mntreadn(Chan *c, uchar *buf, int n, int uninterruptable) -{ - int m, dm; - - for(m=0; merror, "interrupt") == nil) - nexterror(); - dm = 0; - continue; - } - dm = devtab[c->type]->read(c, buf, n-m, 0); - if(uninterruptable) - poperror(); - if(dm <= 0) - return 0; - buf += dm; - } - return n; -} - int mntrpcread(Mnt *m, Mntrpc *r) { - int n, len; - ulong chunk; + int i, t, len, hlen; + Block *b, **l, *nb; - chunk = m->c->iounit; - if(chunk == 0 || chunk > m->c->iounit) - chunk = m->c->iounit; r->reply.type = 0; r->reply.tag = 0; - /* read size, then read exactly the right number of bytes */ - n = mntreadn(m->c, r->rpc, BIT32SZ, 0); - if(n != BIT32SZ){ - if(n > 0) - print("devmnt expected BIT32SZ got %d\n", n); - return -1; - } - len = GBIT32((uchar*)r->rpc); - if(len <= BIT32SZ || len > chunk){ - print("devmnt: len %d max messagesize %ld\n", len, m->c->iounit); - return -1; - } - n += mntreadn(m->c, r->rpc+BIT32SZ, len-BIT32SZ, 1); - if(n != len){ - print("devmnt: length %d expected %d\n", n, len); - return -1; + + /* read at least length, type, and tag and pullup to a single block */ + while(qlen(m->q) < BIT32SZ+BIT8SZ+BIT16SZ){ + b = devtab[m->c->type]->bread(m->c, 2*MAXRPC, 0); + if(b == nil) + return -1; + qadd(m->q, b); + } + nb = pullupqueue(m->q, BIT32SZ+BIT8SZ+BIT16SZ); + len = GBIT32(nb->rp); + + /* read in the rest of the message */ + while(qlen(m->q) < len){ + b = devtab[m->c->type]->bread(m->c, 2*MAXRPC, 0); + if(b == nil) + return -1; + qadd(m->q, b); + } + + /* pullup the header (i.e. everything except data) */ + t = nb->rp[BIT32SZ]; + switch(t){ + case Rread: + hlen = BIT32SZ+BIT8SZ+BIT16SZ+BIT32SZ; + break; + default: + hlen = len; + break; } + nb = pullupqueue(m->q, hlen); - r->replen = n; - if(convM2S(r->rpc, n, &r->reply) == 0){ - int i; - print("bad conversion of received message; %d bytes iounit %ld\n", n, m->c->iounit); - for(i=0; irpc[i]); - print("\n"); + if(convM2S(nb->rp, len, &r->reply) <= 0){ + /* bad message, dump it */ + print("mntrpcread: convM2S failed\n"); + qdiscard(m->q, len); return -1; } + + /* hang the data off of the fcall struct */ + l = &r->b; + *l = nil; + do { + b = qremove(m->q); + if(hlen > 0){ + b->rp += hlen; + len -= hlen; + hlen = 0; + } + i = BLEN(b); + if(i <= len){ + len -= i; + *l = b; + l = &(b->next); + } else { + /* split block and put unused bit back */ + nb = allocb(i-len); + memmove(nb->wp, b->rp+len, i-len); + b->wp = b->rp+len; + nb->wp += i-len; + qputback(m->q, nb); + *l = b; + return 0; + } + }while(len > 0); + return 0; } @@ -743,7 +752,6 @@ mntgate(Mnt *m) void mountmux(Mnt *m, Mntrpc *r) { - uchar *dp; Mntrpc **l, *q; lock(m); @@ -757,10 +765,9 @@ mountmux(Mnt *m, Mntrpc *r) * Completed someone else. * Trade pointers to receive buffer. */ - dp = q->rpc; - q->rpc = r->rpc; - r->rpc = dp; q->reply = r->reply; + q->b = r->b; + r->b = nil; } q->done = 1; unlock(m); @@ -857,12 +864,15 @@ mntralloc(Chan *c, ulong iounit) new->c = c; new->done = 0; new->flushed = nil; + new->b = nil; return new; } void mntfree(Mntrpc *r) { + if(r->b != nil) + freeblist(r->b); lock(&mntalloc); if(mntalloc.nrpcfree >= 10){ free(r->rpc); diff --git a/port/devuart.c b/port/devuart.c index 59c8a8a45d35d1050c9e42bc419e8648b06b00d2..64abd0d5c4379f58ded4fad59ee6fd9d9ab29b23 100644 --- a/port/devuart.c +++ b/port/devuart.c @@ -490,6 +490,17 @@ uartwstat(Chan *c, uchar *dp, int n) return n; } +void +uartpower(int on) +{ + Uart *p; + + for(p = uartlist; p != nil; p = p->next) { + if (p->phys->power) + (*p->phys->power)(p, on); + } +} + Dev uartdevtab = { 't', "uart", @@ -508,6 +519,7 @@ Dev uartdevtab = { devbwrite, devremove, uartwstat, + uartpower, }; /* diff --git a/port/error.h b/port/error.h index 5e571b947ff2cd9233a24e83fef454d0edd3b22b..2a02e920f1858b7e0ee186699715c1bafdc19de7 100644 --- a/port/error.h +++ b/port/error.h @@ -20,7 +20,7 @@ extern char Eio[]; /* i/o error */ extern char Etoobig[]; /* read or write too large */ extern char Etoosmall[]; /* read or write too small */ extern char Enoport[]; /* network port not available */ -extern char Ehungup[]; /* write to hungup channel */ +extern char Ehungup[]; /* i/o on hungup channel */ extern char Ebadctl[]; /* bad process or channel control request */ extern char Enodev[]; /* no free devices */ extern char Eprocdied[]; /* process exited */ @@ -28,7 +28,7 @@ extern char Enochild[]; /* no living children */ extern char Eioload[]; /* i/o error in demand load */ extern char Enovmem[]; /* virtual memory allocation failed */ extern char Ebadfd[]; /* fd out of range or not open */ -extern char Enofd[]; /* no free file descriptors */ +extern char Enofd[]; /* no free file descriptors */ extern char Eisstream[]; /* seek on a stream */ extern char Ebadexec[]; /* exec header invalid */ extern char Etimedout[]; /* connection timed out */ @@ -46,4 +46,4 @@ extern char Enoreg[]; /* process has no saved registers */ extern char Enoattach[]; /* mount/attach disallowed */ extern char Eshortstat[]; /* stat buffer too small */ extern char Ebadstat[]; /* malformed stat buffer */ -extern char Enegoff[]; /* negative i/o offset */ +extern char Enegoff[]; /* negative i/o offset */ diff --git a/port/portdat.h b/port/portdat.h index 07b3c4fe45634b7a3237847e1c50083352c060ac..674de22840739201f587609c7e2fae72595c348b 100644 --- a/port/portdat.h +++ b/port/portdat.h @@ -730,6 +730,7 @@ struct PhysUart void (*dtr)(Uart*, int); long (*status)(Uart*, void*, long, long); void (*fifo)(Uart*, int); + void (*power)(Uart*, int); }; enum { @@ -742,6 +743,7 @@ enum { struct Uart { void* regs; /* hardware stuff */ + void* saveregs; /* place to put registers on power down */ char* name; /* internal name */ ulong freq; /* clock frequency */ int bits; /* bits per character */ diff --git a/port/portfns.h b/port/portfns.h index 3849e08d6907e2d3023264a0d6b2c1e470f2fc3d..2ed3ea753048704fc0ea3907f8acc6e9d169d5ff 100644 --- a/port/portfns.h +++ b/port/portfns.h @@ -11,6 +11,7 @@ int anyready(void); void _assert(char*); Image* attachimage(int, Chan*, ulong, ulong); Page* auxpage(void); +Block* bl2mem(uchar*, Block*, int); int blocklen(Block*); void cachedel(Image*, ulong); void cachepage(Page*, Image*); @@ -155,6 +156,7 @@ void machinit(void); void* mallocz(ulong, int); void* malloc(ulong); void mallocsummary(void); +Block* mem2bl(uchar*, int); void mfreeseg(Segment*, ulong, int); void microdelay(int); void mkqid(Qid*, vlong, ulong, int); diff --git a/port/qio.c b/port/qio.c index 224f11e146888015d2a10c58e7c988c7174c8efc..d646deee404d89ca76f75738b5baf6b4581fa8b4 100644 --- a/port/qio.c +++ b/port/qio.c @@ -864,6 +864,68 @@ qremove(Queue *q) return b; } +/* + * copy the contents of a string of blocks into + * memory. emptied blocks are freed. return + * pointer to first unconsumed block. + */ +Block* +bl2mem(uchar *p, Block *b, int n) +{ + int i; + Block *next; + + for(; b != nil; b = next){ + i = BLEN(b); + if(i > n){ + memmove(p, b->rp, n); + b->rp += n; + return b; + } + memmove(p, b->rp, i); + n -= i; + p += i; + b->rp += i; + next = b->next; + freeb(b); + } + return nil; +} + +/* + * copy the contents of memory into a string of blocks. + * return nil on error. + */ +Block* +mem2bl(uchar *p, int len) +{ + int n; + Block *b, *first, **l; + + first = nil; + l = &first; + if(waserror()){ + freeblist(first); + nexterror(); + } + do { + n = len; + if(n > Maxatomic) + n = Maxatomic; + + *l = b = allocb(n); + setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]); + memmove(b->wp, p, n); + b->wp += n; + p += n; + len -= n; + l = &b->next; + } while(len > 0); + poperror(); + + return first; +} + /* * put a block back to the front of the queue * called with q ilocked @@ -965,12 +1027,8 @@ qbread(Queue *q, int len) long qread(Queue *q, void *vp, int len) { - Block *b, *first, *next, **l; - int m; - uchar *s, *e, *p; - - s = p = vp; - e = s+len; + Block *b, *first, **l; + int m, n; qlock(&q->rlock); if(waserror()){ @@ -1006,46 +1064,34 @@ again: * following blocks as will completely * fit in the read. */ + n = 0; l = &first; m = BLEN(b); for(;;) { *l = qremove(q); l = &b->next; - p += m; + n += m; b = q->bfirst; if(b == nil) break; m = BLEN(b); - if(p+m > e) + if(n+m > len) break; } } else { first = qremove(q); + n = BLEN(first); } /* copy to user space outside of the ilock */ iunlock(q); - p = s; - for(b = first; b != nil; b = next){ - m = BLEN(b); - if(m > e - p){ - m = e - p; - memmove(p, b->rp, m); - p += m; - b->rp += m; - break; - } - memmove(p, b->rp, m); - p += m; - next = b->next; - b->next = nil; - freeb(b); - } + b = bl2mem(vp, first, len); ilock(q); /* take care of any left over partial block */ if(b != nil){ + n -= BLEN(b); if(q->state & Qmsg) freeb(b); else @@ -1057,7 +1103,7 @@ again: poperror(); qunlock(&q->rlock); - return p-s; + return n; } static int @@ -1169,33 +1215,22 @@ qbwrite(Queue *q, Block *b) int qwrite(Queue *q, void *vp, int len) { - int n, sofar; - Block *b; - uchar *p = vp; + Block *b, *next; - QDEBUG if(islo() == 0) + QDEBUG if(!islo()) print("qwrite hi %lux\n", getcallerpc(&q)); - sofar = 0; - do { - n = len-sofar; - if(n > Maxatomic) - n = Maxatomic; - - b = allocb(n); - setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]); - if(waserror()){ - freeb(b); - nexterror(); - } - memmove(b->wp, p+sofar, n); - poperror(); - b->wp += n; - + b = mem2bl(vp, len); + if(waserror()){ + freeblist(b); + nexterror(); + } + for(; b != nil; b = next){ + next = b->next; + b->next = nil; qbwrite(q, b); - - sofar += n; - } while(sofar < len && (q->state & Qmsg) == 0); + } + poperror(); return len; }