M bitsy/dat.h => bitsy/dat.h +0 -14
@@ 227,17 227,6 @@ struct PCMconftab
};
/*
- * For walking a PCMCIA card's information structure
- */
-struct Cisdat
-{
- uchar *cisbase;
- int cispos;
- int cisskip;
- int cislen;
-};
-
-/*
* PCMCIA card slot
*/
struct PCMslot
@@ 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;
M bitsy/devpcmcia.c => bitsy/devpcmcia.c +11 -8
@@ 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);
M bitsy/fns.h => bitsy/fns.h +1 -0
@@ 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);
M bitsy/l.s => bitsy/l.s +0 -2
@@ 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).
*
M bitsy/main.c => bitsy/main.c +0 -1
@@ 364,7 364,6 @@ PPCregs *ppcregs;
MemConfRegs *memconfregs;
PowerRegs *powerregs;
ResetRegs *resetregs;
-OSTimerRegs *timerregs = (OSTimerRegs*)OSTIMERREGS;
/*
* configure the machine
M bitsy/power.c => bitsy/power.c +14 -25
@@ 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<<IRQgpio0);
intrregs->icip = (1<<IRQgpio0);
}
- uartcpy(uart3regs,&saveduart3regs);
- uart3regs->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 */
}
M bitsy/uartsa1110.c => bitsy/uartsa1110.c +32 -3
@@ 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));
+ }
+}
M pc/devi82365.c => pc/devi82365.c +4 -1
@@ 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);
M pc/io.h => pc/io.h +0 -13
@@ 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;
M pc/sdscsi.c => pc/sdscsi.c +2 -0
@@ 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.
M port/cis.c => port/cis.c +59 -25
@@ 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;
}
M port/devmnt.c => port/devmnt.c +76 -66
@@ 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<nname; i++)
- print("%s/", name[i]);
- print("\n");
-}
-
if(nname > 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);
@@ 661,67 659,78 @@ mountio(Mnt *m, Mntrpc *r)
}
int
-mntreadn(Chan *c, uchar *buf, int n, int uninterruptable)
-{
- int m, dm;
-
- for(m=0; m<n; m+=dm){
- if(uninterruptable)
- if(waserror()){
- /* user DEL may stop assembly; wait for full 9P msg. */
- if(strstr(up->error, "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; i<n; i++)
- print("%.2ux ", (uchar)r->rpc[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);
M port/devuart.c => port/devuart.c +12 -0
@@ 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,
};
/*
M port/error.h => port/error.h +3 -3
@@ 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 */
M port/portdat.h => port/portdat.h +2 -0
@@ 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 */
M port/portfns.h => port/portfns.h +2 -0
@@ 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);
M port/qio.c => port/qio.c +83 -48
@@ 865,6 865,68 @@ qremove(Queue *q)
}
/*
+ * 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;
}