we now list the disk directory even when disk has not been initialised.
we do allow rctl() and wctl() on such devices (e.g. to set "debug"
on the sdio driver before we try to init the disk). we also make
sure to not lose memory/corrupt state when initialisation fails or
is done again.
if initing partitions fails, the data file can still be accessed.
eg to write new mbr with partition table to the data file. a new
ctl "partinit" has been added to reinit the partition table without
having to reinit the device.
handle reading of non-aligned count and/or offset. no writes,
perhaps they will be needed later.
actually write to disk when requested (instead of reading...).
also fix crash when closing a file that was open while the disk
changed underneath.
kwsdio.c:
- add debug wctl
- improve locking
- use anonymous static struct with lock and state
- some cosmetic changes.
- add wctl option "preerase", whether to erase before write (off by
default).
part.c:
- allow both partition "plan9" and its child partitions.
- fix parsing table. entries start with literal word "part".
http://code.google.com/p/inferno-kirkwood/source/detail?r=422883067f
Modified:
/bs.h
/devbs.c
/kwsdio.c
/part.c
/sheeva
=======================================
--- /bs.h Tue Mar 30 11:04:14 2010
+++ /bs.h Wed Mar 31 04:09:52 2010
@@ -2,26 +2,29 @@
struct Store
{
- RWlock; /* devbs rlocks for: rctl,wctl,io,raw. wlocks for:
init,diskinit,modifying values */
+ RWlock; /* devbs rlocks for: rctl,wctl,io,raw. wlocks for:
init,diskinit,modifying values */
void *ctlr;
int vers; /* version, increased for each devinit. */
int ready; /* whether device initialised and ready for use */
int num;
char name[4+1]; /* "bs%02d", num */
- int alignmask; /* alignment, bits must be zero */
+ uint alignmask; /* alignment, bits must be zero */
char *descr; /* description, from device */
char devtype[KNAMELEN]; /* type of device, returned when reading bsXX/ctl
*/
/* set by init, used by devbs.c */
- Part *parts; /* first is always "data" for whole disk */
+ Part *parts; /* first is always "data" for whole disk */
int nparts;
vlong size;
+ /* called both when "ready" and not */
void (*init)(Store *d); /* init controller */
void (*devinit)(Store *d); /* find disk and set size */
long (*rctl)(Store *d, void *s, long n, vlong off);
long (*wctl)(Store *d, void *s, long n);
+
+ /* only called when "ready": */
long (*io)(void *d, int iswrite, void *buf, long n, vlong off);
long (*raw)(Store *d, void *s, long n, vlong off, void **r);
};
=======================================
--- /devbs.c Tue Mar 30 11:04:14 2010
+++ /devbs.c Wed Mar 31 04:09:52 2010
@@ -1,7 +1,9 @@
/*
- * hot-pluggable block storage devices
+ * hot-pluggable block storage devices. not specific to scsi or ata.
*
* todo:
+ * - check if plan 9 part start,end sectors are offset by 2 (for bootcode
& table)
+ * - allow misaligned writes, by reading the data before writing?
* - add hooks so devices can tell they have gone/arrived.
* - understand extended partitions
* - hotplug & events, make event-file per Qdiskpart too.
@@ -35,7 +37,7 @@
#define QPATH(p,d,t) ((p)<<16 | (d)<<8 | (t)<<0)
enum{
Qdir, Qbsctl, Qbsevent,
- Qdiskdir, Qdiskctl, Qdiskdevctl, Qdiskraw, Qdiskevent, Qdiskpart,
+ Qdiskdir, Qdiskctl, Qdiskdevctl, Qdiskevent, Qdiskraw, Qdiskpart,
};
static
Dirtab bstab[] = {
@@ -45,8 +47,8 @@
"xxx", {Qdiskdir,0,QTDIR}, 0, 0555,
"ctl", {Qdiskctl}, 0, 0660,
"devctl", {Qdiskdevctl}, 0, 0660,
- "raw", {Qdiskraw}, 0, 0660,
"event", {Qdiskevent}, 0, 0440,
+ "raw", {Qdiskraw}, 0, 0660,
"xxx", {Qdiskpart}, 0, 0660,
};
@@ -106,20 +108,25 @@
static void
diskinit(Store *d)
{
+ d->ready = 0;
+ d->nparts = 0;
d->vers++;
d->devinit(d);
- d->ready = 1;
-
- d->parts = smalloc(sizeof d->parts[0]);
+ if(d->size & d->alignmask)
+ error("misaligned size");
+
+ d->parts = realloc(d->parts, sizeof d->parts[0]);
partdata(&d->parts[0], d->size);
+ d->nparts = 1;
+ d->ready = 1;
+
if(waserror()) {
- free(d->parts);
- d->parts = nil;
- nexterror();
- }
+ print("partinit: %s\n", up->env->errstr);
+ return;
+ }
+
d->nparts = partinit(d->io, d, d->size, &d->parts);
- if(d->nparts < 0)
- error("partinit");
+
poperror();
}
@@ -135,6 +142,9 @@
xpartget(Store *d, int i)
{
Part *p;
+
+ if(d->ready == 0)
+ error(Enodisk);
p = partget(d, i);
if(p == nil)
error(Enopart);
@@ -145,11 +155,17 @@
io(Store *d, Part *p, int iswrite, void *buf, long n, vlong off)
{
vlong s, e;
-
+ long xn;
+ vlong xs;
+ char *origbuf;
+
+ if(d->ready == 0)
+ error(Enodisk);
if(off < 0 || n < 0)
error(Ebadarg);
- if(off & d->alignmask || n & d->alignmask)
+ if(iswrite && (off&d->alignmask || n&d->alignmask))
error(Ebadalign);
+
s = off;
e = off+n;
if(s > p->size)
@@ -158,7 +174,34 @@
e = p->size;
s += p->s;
e += p->s;
- return d->io(d, iswrite, buf, e-s, s);
+ n = e-s;
+
+ xs = s&~d->alignmask;
+ xn = n+(s&d->alignmask)+d->alignmask & ~d->alignmask;
+
+ origbuf = nil;
+ if(xs != s || xn != n) {
+ origbuf = buf;
+ buf = smalloc(xn);
+ if(waserror()) {
+ free(buf);
+ nexterror();
+ }
+ }
+
+ xn = d->io(d, iswrite, buf, xn, xs);
+
+ if(origbuf != nil) {
+ xn -= s-xs;
+ if(xn < 0)
+ xn = 0;
+ if(n < xn)
+ xn = n;
+ poperror();
+ memmove(origbuf, (uchar*)buf+(s-xs), xn);
+ free(buf);
+ }
+ return xn;
}
static int
@@ -168,6 +211,7 @@
Store *d;
Part *p;
Qid qid;
+ int qt;
//print("bsgen, c->qid.path %#llux, i %d\n", c->qid.path, i);
@@ -182,7 +226,7 @@
panic("devdotdot on non-dir qid.path %#llux\n", c->qid.path);
}
- switch(QTYPE(c->qid.path)) {
+ switch(qt = QTYPE(c->qid.path)) {
default:
panic("bsgen on non-dir qid.path %#llux\n", c->qid.path);
@@ -198,7 +242,7 @@
if(i > bs.maxdisk)
return -1;
d = diskget(i);
- if(d == nil || d->ready == 0)
+ if(d == nil)
return 0;
t = &bstab[Qdiskdir];
rlock(d);
@@ -210,19 +254,19 @@
case Qdiskdir:
case Qdiskctl:
case Qdiskdevctl:
- case Qdiskraw:
case Qdiskevent:
+ case Qdiskraw:
case Qdiskpart:
d = diskget(QDISK(c->qid.path));
- if(d == nil || d->ready == 0)
+ if(d == nil || d->ready == 0 && qt == Qdiskpart)
return -1;
- if(i >= 0 && i < Qdiskevent-Qdiskctl+1) {
+ if(i >= 0 && i < Qdiskraw-Qdiskctl+1) {
t = &bstab[Qdiskctl+i];
mkqid(&qid, QPATH(0,d->num,Qdiskctl+i), 0, QTFILE);
devdir(c, qid, t->name, t->length, eve, t->perm, dp);
return 1;
}
- i -= Qdiskevent-Qdiskctl+1;
+ i -= Qdiskraw-Qdiskctl+1;
if(i >= d->nparts)
return -1;
p = &d->parts[i];
@@ -258,7 +302,6 @@
continue;
wlock(d);
if(waserror()) {
- // xxx mark disk as bad/not yet initialized
wunlock(d);
continue;
}
@@ -296,7 +339,7 @@
storelock = QTYPE(c->qid.path) >= Qdiskdir;
if(storelock) {
d = diskget(QDISK(c->qid.path));
- if(d == nil || d->ready == 0)
+ if(d == nil)
error(Enodisk);
rlock(d);
if(waserror()) {
@@ -331,7 +374,7 @@
storelock = QTYPE(c->qid.path) >= Qdiskdir;
if(storelock) {
d = diskget(QDISK(c->qid.path));
- if(d == nil || d->ready == 0)
+ if(d == nil)
error(Enodisk);
rlock(d);
if(waserror()) {
@@ -374,7 +417,7 @@
unlockf = wunlock;
}
d = diskget(QDISK(c->qid.path));
- if(d == nil || d->ready == 0)
+ if(d == nil)
error(Enodisk);
lockf(d);
if(waserror()) {
@@ -456,10 +499,12 @@
nexterror();
}
- p = xpartget(d, QPART(c->qid.path));
- if(p->isopen != 1)
- panic("devclose on part.isopen != 1");
- p->isopen = 0;
+ if(c->qid.vers == d->vers) {
+ p = xpartget(d, QPART(c->qid.path));
+ if(p->isopen != 1)
+ panic("devclose on part.isopen != 1");
+ p->isopen = 0;
+ }
poperror();
wunlock(d);
@@ -505,11 +550,14 @@
s = buf;
e = buf+READSTR;
- s = seprint(s, e, "devtype %q\ndescr %q\nalign %ud\nsize %lld\n",
- d->devtype, d->descr, d->alignmask+1, d->size);
- for(i = 1; i < d->nparts; i++) {
- p = &d->parts[i];
- s = seprint(s, e, "part %q %lld %lld\n", p->name, p->s, p->e);
+ s = seprint(s, e, "devtype %q\n", d->devtype);
+ if(d->ready) {
+ s = seprint(s, e, "descr %q\nalign %ud\nsize %lld\n",
+ d->descr, d->alignmask+1, d->size);
+ for(i = 1; i < d->nparts; i++) {
+ p = &d->parts[i];
+ s = seprint(s, e, "part %q %lld %lld\n", p->name, p->s, p->e);
+ }
}
n = readstr(off, a, n, buf);
@@ -518,8 +566,10 @@
break;
case Qdiskdevctl:
- p = xpartget(d, 0);
- devpermcheck(p->uid, p->perm, OREAD);
+ if(!iseve()) {
+ p = xpartget(d, 0);
+ devpermcheck(p->uid, p->perm, OREAD);
+ }
n = d->rctl(d, a, n, off);
break;
@@ -555,7 +605,7 @@
storelock = QTYPE(c->qid.path) >= Qdiskdir;
if(storelock) {
d = diskget(QDISK(c->qid.path));
- if(d == nil || d->ready == 0)
+ if(d == nil)
error(Enodisk);
rlock(d);
if(waserror()) {
@@ -616,6 +666,9 @@
n = bsdevread(c, a, n, off);
break;
+ case Qdiskevent:
+ error("not yet");
+
case Qdiskraw:
if(c->aux == nil)
error("no command executed");
@@ -627,9 +680,6 @@
memmove(a, b->a+off, n);
break;
- case Qdiskevent:
- error("not yet");
-
default:
n = 0;
break;
@@ -644,10 +694,11 @@
CMinit, "init", 2,
};
enum {
- CMdiskinit,
+ CMdiskinit, CMpartinit,
};
static Cmdtab bsdiskctl[] = {
CMdiskinit, "init", 1,
+ CMpartinit, "partinit", 1,
};
static long
@@ -673,14 +724,21 @@
case Qdiskdevctl:
if(off != 0)
error(Ebadarg);
- p = xpartget(d, 0);
- devpermcheck(p->uid, p->perm, OWRITE);
+ if(!iseve()) {
+ p = xpartget(d, 0);
+ devpermcheck(p->uid, p->perm, OWRITE);
+ }
n = d->wctl(d, a, n);
break;
case Qdiskraw:
- p = xpartget(d, 0);
- devpermcheck(p->uid, p->perm, OWRITE);
+ if(d->ready == 0)
+ error(Enodisk);
+
+ if(!iseve()) {
+ p = xpartget(d, 0);
+ devpermcheck(p->uid, p->perm, OWRITE);
+ }
if(d->raw == nil)
error("raw commands not implemented by device");
b = c->aux;
@@ -696,7 +754,7 @@
case Qdiskpart:
p = xpartget(d, QPART(c->qid.path));
- n = io(d, p, 0, a, n, off);
+ n = io(d, p, 1, a, n, off);
break;
}
@@ -737,7 +795,6 @@
d = diskget(num);
if(d == nil)
error(Enodisk);
- // xxx if d->ready, might have to clean up first?
wlock(d);
if(waserror()) {
wunlock(d);
@@ -777,11 +834,10 @@
if(c->qid.vers != d->vers)
error(Estale);
- p = partget(d, 0);
- if(p != nil)
+ if(!iseve()) {
+ p = xpartget(d, 0);
devpermcheck(p->uid, p->perm, OWRITE);
- else if(!iseve())
- error(Eperm);
+ }
cb = parsecmd(a, n);
if(waserror()) {
@@ -792,7 +848,16 @@
switch(ct->index) {
case CMdiskinit:
diskinit(d);
- // xxx if d->ready, might have to clean up first?
+ break;
+
+ case CMpartinit:
+ if(d->ready == 0)
+ error(Enodisk);
+
+ d->parts = realloc(d->parts, sizeof d->parts[0]);
+ d->nparts = 1;
+ d->vers++;
+ d->nparts = partinit(d->io, d, d->size, &d->parts);
break;
}
poperror();
=======================================
--- /kwsdio.c Tue Mar 30 09:26:40 2010
+++ /kwsdio.c Wed Mar 31 04:09:52 2010
@@ -21,11 +21,18 @@
#include "bs.h"
-#define DEBUG 0
-#define dprint if(DEBUG)print
+static int debug = 0;
+#define dprint if(debug)print
char Enocard[] = "no card";
+static struct {
+ QLock;
+ Card card;
+ Rendez cmdr;
+ int preerase;
+} sdio;
+
enum {
/* keep in sync with errstrs[] */
SDOk = 0,
@@ -174,10 +181,6 @@
};
-static Card card;
-static Rendez cmdr;
-static QLock sdl;
-
/* for bits in st, est, acmd12st registers */
static const char *statusstrs[] = {
"cmdcomplete", "xfercomplete", "blockgapevent", "dmaintr",
@@ -250,27 +253,33 @@
"", "", "", "",
};
-static void
-printstatus(char *s, ulong st, ulong est, ulong acmd12st)
-{
- char *p, *e;
-
- USED(s);
- if(!DEBUG)
- return;
-
- p = up->genbuf;
- e = p+sizeof (up->genbuf);
-
- p = statusstr(p, e, st);
- p = seprint(p, e, ";");
- p = errstatusstr(p, e, est);
- p = seprint(p, e, ";");
- p = acmd12ststr(p, e, acmd12st);
- USED(p);
-
- print("status: %s%s\n", s, up->genbuf);
-}
+/*
+ p = buf = smalloc(READSTR);
+ e = p+READSTR;
+
+ p = seprint(p, e, "st: ");
+ p = statusstr(p, e, r->st);
+ p = seprint(p, e, "\nest: ");
+ p = errstatusstr(p, e, r->est);
+ p = seprint(p, e, "\nacmd12st: ");
+ p = acmd12ststr(p, e, r->acmd12st);
+
+ p = seprint(p, e, "\nstena: ");
+ p = statusstr(p, e, r->stena);
+ p = seprint(p, e, "\nestena: ");
+ p = errstatusstr(p, e, r->estena);
+
+ p = seprint(p, e, "\nstirq: ");
+ p = statusstr(p, e, r->stirq);
+ p = seprint(p, e, "\nestirq: ");
+ p = errstatusstr(p, e, r->estirq);
+
+ p = seprint(p, e, "\nhoststate %#lux\n", r->hoststate);
+ USED(p);
+
+ n = readstr(offset, a, n, buf);
+ free(buf);
+*/
static const char *errstrs[] = {
@@ -288,10 +297,10 @@
if(v != SDOk)
p = seprint(p, e, ": %s", errstrs[-v]);
if(v == SDBadstatus)
- p = seprint(p, e, " (r1status %#lux)", card.status);
+ p = seprint(p, e, " (r1status %#lux)", sdio.card.status);
if(v == SDError) {
- p = seprint(p, e, " (est %#lux", card.status);
- p = errstatusstr(p, e, card.status);
+ p = seprint(p, e, " (est %#lux", sdio.card.status);
+ p = errstatusstr(p, e, sdio.card.status);
p = seprint(p, e, ")");
}
USED(p);
@@ -325,7 +334,7 @@
ulong need, v;
uvlong w;
- print("sdcmd, cmd %lud, arg %lud, fl %#lux\n", cmd, arg, fl);
+ dprint("sdcmd, cmd %lud, arg %lud, fl %#lux\n", cmd, arg, fl);
i = 0;
for(;;) {
@@ -340,7 +349,7 @@
acmd = 55;
if(fl & Fappdata)
acmd = 56;
- s = sdcmd(c, acmd, card.rca<<16, R1, 0);
+ s = sdcmd(c, acmd, c->rca<<16, R1, 0);
if(s < 0)
return s;
if((c->resp[2]>>8 & SDappcmd) == 0)
@@ -351,8 +360,6 @@
r->st = ~0;
r->est = ~0;
r->acmd12st = ~0;
- // xxx remove?
- printstatus("before cmd: ", r->st, r->est, r->acmd12st);
/* prepare args & execute command */
r->arglo = arg>>0 & MASK(16);
@@ -381,30 +388,30 @@
r->cmd = cmd<<CMDshift|cmdopts|resptypes[rt];
/* Scmdcomplete/Sdma and errors signal completion */
- s = 0;
need = Scmdcomplete;
if(fl & (Fdmad2h|Fdmah2d))
need = Sdmaintr;
r->stirq = need|Sunexpresp|Serror;
r->estirq = ~0;
+ v = r->stirq;
+ s = 0;
while(waserror())
s = SDInterrupted;
- v = r->stirq;
- tsleep(&cmdr, sdiodone, &v, 5000);
+ tsleep(&sdio.cmdr, sdiodone, &v, 5000);
poperror();
- if(s == SDInterrupted)
+ if(s != 0)
return s;
if(r->st & (Sunexpresp|Serror)) {
- card.status = r->est;
+ c->status = r->est;
+ if(c->status & Ecmdtimeout)
+ return SDTimeout;
return SDError;
}
if((r->st & need) == 0)
return SDTimeout;
- printstatus("success", r->st, r->est, r->acmd12st);
-
/* fetch the response */
memset(c->resp, 0, sizeof c->resp);
switch(resptypes[rt]) {
@@ -468,7 +475,7 @@
sdclock(ulong v)
{
SDIOREG->clockdiv = ((100*1000*1000)/v)-1;
- delay(1);
+ tsleep(&up->sleep, return0, nil, 10);
}
static void
@@ -477,12 +484,13 @@
int i, s;
ulong v;
SdioReg *r = SDIOREG;
-
- sdclock(400*1000);
+ Card *c = &sdio.card;
+
r->hostctl &= ~HChighspeed;
+ sdclock(400*1000);
/* force card to idle state */
- s = sdcmd(&card, 0, 0, R0, 0);
+ s = sdcmd(c, 0, 0, R0, 0);
if(s < 0)
errorsd("reset failed", s);
@@ -490,15 +498,15 @@
* "send interface command". only >=2.00 cards will respond.
* we send a check pattern and supported voltage range.
*/
- card.mmc = 0;
- card.sd2 = 0;
- card.sdhc = 0;
- card.rca = 0;
- s = sdcmd(&card, 8, CMD8voltage|CMD8pattern, R7, 0);
+ c->mmc = 0;
+ c->sd2 = 0;
+ c->sdhc = 0;
+ c->rca = 0;
+ s = sdcmd(c, 8, CMD8voltage|CMD8pattern, R7, 0);
switch(s) {
case SDOk:
- card.sd2 = 1;
- v = card.resp[2]>>8;
+ c->sd2 = 1;
+ v = c->resp[2]>>8;
if((v & CMD8patternmask) != CMD8pattern)
error("check pattern mismatch");
if((v & CMD8voltagemask) != CMD8voltage)
@@ -508,7 +516,7 @@
case SDTimeout:
case SDError: /* "no response" from spec can result in error too
apparently */
/* sd 1.x or not an sd memory card */
- s = sdcmd(&card, 0, 0, R0, 0);
+ s = sdcmd(c, 0, 0, R0, 0);
if(s < 0)
errorsd("reset failed", s);
break;
@@ -525,149 +533,152 @@
i = 0;
for(;;) {
v = ACMD41voltagewindow;
- if(card.sd2)
+ if(c->sd2)
v |= ACMD41sdhcsupported;
- s = sdcmd(&card, 41, v, R3, Fapp);
+ s = sdcmd(c, 41, v, R3, Fapp);
if(s < 0) {
- if(s == SDTimeout && !card.sd2)
- card.mmc = 1;
+ if(s == SDTimeout && !c->sd2)
+ c->mmc = 1;
errorsd("exchange voltage/sdhc support info", s);
}
- v = card.resp[2]>>8;
+ v = c->resp[2]>>8;
if((v & ACMD41voltagewindow) == 0)
error("voltage not supported");
if(v & ACMD41ready) {
- card.sdhc = (v & ACMD41sdhcsupported) != 0;
+ c->sdhc = (v & ACMD41sdhcsupported) != 0;
break;
}
if(i++ >= 100)
error("sd card failed to power up");
- tsleep(&up->sleep, return0, nil, 10);
- }
- dprint("acmd41 done, mmc %d, sd2 %d, sdhc %d\n", card.mmc, card.sd2,
card.sdhc);
- if(card.mmc)
- error("mmc cards not yet supported"); // xxx p14 says this involves
sending cmd1
-
- s = sdcmd(&card, 2, 0, R2, 0);
+ tsleep(&up->sleep, return0, nil, i);
+ }
+ dprint("acmd41 done, mmc %d, sd2 %d, sdhc %d\n", c->mmc, c->sd2, c->sdhc);
+ if(c->mmc)
+ error("possibly mmc card, not yet supported"); // xxx p14 says this
involves sending cmd1
+
+ s = sdcmd(c, 2, 0, R2, 0);
if(s < 0)
errorsd("card identification", s);
- if(parsecid(&card.cid, card.resp) < 0)
+ if(parsecid(&c->cid, c->resp) < 0)
error("bad cid register");
i = 0;
for(;;) {
- s = sdcmd(&card, 3, 0, R6, 0);
+ s = sdcmd(c, 3, 0, R6, 0);
if(s < 0)
errorsd("getting relative address", s);
- card.rca = card.resp[2]>>24 & MASK(16);
- v = card.resp[2]>>8 & MASK(16);
- dprint("have card rca %ux, status %lux\n", card.rca, v);
+ c->rca = c->resp[2]>>24 & MASK(16);
+ v = c->resp[2]>>8 & MASK(16);
+ dprint("have card rca %ux, status %lux\n", c->rca, v);
USED(v);
- if(card.rca != 0)
+ if(c->rca != 0)
break;
if(i++ == 10)
error("card insists on invalid rca 0");
}
- s = sdcmd(&card, 9, card.rca<<16, R2, 0);
+ s = sdcmd(c, 9, c->rca<<16, R2, 0);
if(s < 0)
errorsd("get csd", s);
- if(parsecsd(&card.csd, card.resp) < 0)
+ if(parsecsd(&c->csd, c->resp) < 0)
error("bad csd register");
- if(card.csd.vers == 0) {
- card.bs = 1<<card.csd.rbl;
- card.size = card.csd.size+1;
- card.size *= 1<<(card.csd.v0.sizemult+2);
- card.size *= 1<<card.csd.rbl;
- print("csd0, block length read/write %d/%d, size %lld bytes,
eraseblock %d\n",
- 1<<card.csd.rbl,
- 1<<card.csd.wbl,
- card.size,
- (1<<card.csd.wbl)*(card.csd.erasesecsz+1));
+ if(c->csd.vers == 0) {
+ c->bs = 1<<c->csd.rbl;
+ c->size = c->csd.size+1;
+ c->size *= 1<<(c->csd.v0.sizemult+2);
+ c->size *= 1<<c->csd.rbl;
+ dprint("csd0, block length read/write %d/%d, size %lld bytes,
eraseblock %d\n",
+ 1<<c->csd.rbl,
+ 1<<c->csd.wbl,
+ c->size,
+ (1<<c->csd.wbl)*(c->csd.erasesecsz+1));
} else {
- card.bs = 512;
- card.size = (vlong)(card.csd.size+1)*card.bs*1024;
- print("csd1, fixed 512 block length, size %lld bytes, eraseblock fixed
512\n", card.size);
+ c->bs = 512;
+ c->size = (vlong)(c->csd.size+1)*c->bs*1024;
+ dprint("csd1, fixed 512 block length, size %lld bytes, eraseblock fixed
512\n", c->size);
}
- if(card.sdhc) {
+ if(c->sdhc) {
dprint("enabling sdhc & setting clock to 50mhz\n");
- sdclock(50*1000*1000);
r->hostctl |= HChighspeed;
+ sdclock(50*1000*1000);
} else {
dprint("leaving sdhc off & setting clock to 25mhz\n");
sdclock(25*1000*1000);
}
- s = sdcmd(&card, 7, card.rca<<16, R1b, 0);
+ s = sdcmd(c, 7, c->rca<<16, R1b, 0);
if(s < 0)
errorsd("selecting card", s);
/* xxx have to check with scr register if 4bit buswidth is supported by
card. have not been able to read it though... */
- s = sdcmd(&card, 6, 1<<1, R1, Fapp);
+ s = sdcmd(c, 6, 1<<1, R1, Fapp);
if(s < 0)
errorsd("setting buswidth to 4-bit", s);
- s = sdcmd(&card, 16, 512, R1, 0);
+ s = sdcmd(c, 16, 512, R1, 0);
if(s < 0)
errorsd("setting 512 byte blocksize", s);
- card.valid = 1;
-
- cardstr(up->genbuf, up->genbuf+sizeof (up->genbuf), &card);
- print("%s", up->genbuf);
+ c->valid = 1;
+
+ cardstr(up->genbuf, up->genbuf+sizeof (up->genbuf), c);
+ dprint("%s", up->genbuf);
}
static int
-sdstatus(uchar *p)
-{
- return sdcmddma(&card, 13, 0, p, 64, 1, R1, Fapp|Fdmad2h);
+sdstatus(Card *c, uchar *p)
+{
+ return sdcmddma(c, 13, 0, p, 64, 1, R1, Fapp|Fdmad2h);
}
static int
-erase(vlong offset, long n)
+erase(Card *c, vlong offset, long n)
{
vlong e;
int s;
e = offset+n;
- if(card.sdhc) {
+ if(c->sdhc) {
e -= 512;
offset /= 512;
e /= 512;
} else
e -= 1;
- s = sdcmd(&card, 32, offset, R1, 0); /* first addr to erase */
+ s = sdcmd(c, 32, offset, R1, 0); /* first addr to erase */
if(s >= 0)
- s = sdcmd(&card, 33, e, R1, 0); /* last addr to erase (inclusive) */
+ s = sdcmd(c, 33, e, R1, 0); /* last addr to erase (inclusive) */
if(s >= 0)
- s = sdcmd(&card, 38, 0, R1b, 0); /* start erasing */
+ s = sdcmd(c, 38, 0, R1b, 0); /* start erasing */
return s;
}
static long
-sdio(uchar *a, long n, vlong offset, int iswrite)
-{
+sdioio(void *dd, int iswrite, void *buf, long n, vlong off)
+{
+ char *a = buf;
ulong cmd, arg, fl, h, nn;
int s;
- qlock(&sdl);
+ USED(dd);
+
+ qlock(&sdio);
if(waserror()) {
- qunlock(&sdl);
+ qunlock(&sdio);
nexterror();
}
- if(card.valid == 0)
+ if(sdio.card.valid == 0)
error(Enocard);
/* xxx we should cover this case with a buffer, and then use the same
code to allow non-sector-aligned reads? */
if((ulong)a % 4 != 0)
error("bad buffer alignment...");
- if(offset & (512-1))
+ if(off & (512-1))
error("not sector aligned");
if(n & (512-1))
error("not multiple of sector size");
@@ -681,19 +692,19 @@
h = 0;
for(;;) {
- if(card.sdhc)
- arg = (offset+h)/512;
+ if(sdio.card.sdhc)
+ arg = (off+h)/512;
else
- arg = offset+h;
+ arg = off+h;
nn = n;
if(nn > 512*1024)
nn = 512*1024;
- if(iswrite) {
- s = sdcmd(&card, 23, nn/512, R1, Fapp);
+ if(iswrite && sdio.preerase) {
+ s = sdcmd(&sdio.card, 23, nn/512, R1, Fapp);
if(s < 0)
errorsd("erase before write", s);
}
- s = sdcmddma(&card, cmd, arg, a+h, 512, nn/512, R1, fl|Fmulti);
+ s = sdcmddma(&sdio.card, cmd, arg, a+h, 512, nn/512, R1, fl|Fmulti);
if(s < 0)
errorsd("io", s);
h += nn;
@@ -701,17 +712,12 @@
break;
/* give others a chance */
- if(waserror()) {
- qlock(&sdl);
- nexterror();
- }
- qunlock(&sdl);
- poperror();
- qlock(&sdl);
+ qunlock(&sdio);
+ qlock(&sdio);
}
poperror();
- qunlock(&sdl);
+ qunlock(&sdio);
return n;
}
@@ -724,7 +730,7 @@
r->stirq = 0;
r->estirq = 0;
intrclear(Irqlo, IRQ0sdio);
- wakeup(&cmdr);
+ wakeup(&sdio.cmdr);
}
static void
@@ -739,19 +745,19 @@
}
static void
-sdioinit(Store *)
+sdioinit0(void)
{
SdioReg *r = SDIOREG;
intrdisable(Irqlo, IRQ0sdio, sdiointr, nil, "sdio");
- card.valid = 0;
+ sdio.card.valid = 0;
/* reset the bus, forcing all cards to idle state */
r->swreset = SRresetall;
tsleep(&up->sleep, return0, nil, 50);
- sdclock(25*1000*1000);
+ sdclock(100*1000);
/* configure host controller */
r->hostctl = HCpushpull|HCcardmemonly|HCbigendian|HCdatawidth4|
HCtimeout(15)|HCtimeoutenable;
@@ -770,34 +776,20 @@
intrenable(Irqlo, IRQ0sdio, sdiointr, nil, "sdio");
}
-/*
- case Qstatus:
- p = buf = smalloc(READSTR);
- e = p+READSTR;
-
- p = seprint(p, e, "st: ");
- p = statusstr(p, e, r->st);
- p = seprint(p, e, "\nest: ");
- p = errstatusstr(p, e, r->est);
- p = seprint(p, e, "\nacmd12st: ");
- p = acmd12ststr(p, e, r->acmd12st);
-
- p = seprint(p, e, "\nstena: ");
- p = statusstr(p, e, r->stena);
- p = seprint(p, e, "\nestena: ");
- p = errstatusstr(p, e, r->estena);
-
- p = seprint(p, e, "\nstirq: ");
- p = statusstr(p, e, r->stirq);
- p = seprint(p, e, "\nestirq: ");
- p = errstatusstr(p, e, r->estirq);
-
- p = seprint(p, e, "\nhoststate %#lux\n", r->hoststate);
- USED(p);
-
- n = readstr(offset, a, n, buf);
- free(buf);
-*/
+static void
+sdioinit(Store *)
+{
+ qlock(&sdio);
+ if(waserror()) {
+ qunlock(&sdio);
+ nexterror();
+ }
+
+ sdioinit0();
+
+ poperror();
+ qunlock(&sdio);
+}
static long
sdiorctl(Store *d, void *a, long n, vlong off)
@@ -807,13 +799,13 @@
USED(d);
- qlock(&sdl);
+ qlock(&sdio);
if(waserror()) {
- qunlock(&sdl);
+ qunlock(&sdio);
nexterror();
}
- if(card.valid == 0)
+ if(sdio.card.valid == 0)
error(Enocard);
buf = smalloc(READSTR);
@@ -824,9 +816,12 @@
p = buf;
e = buf+READSTR;
- p = cardstr(p, e, &card);
- p = cidstr(p, e, &card.cid);
- p = csdstr(p, e, &card.csd);
+ p = seprint(p, e, "debug %d\n", debug);
+ p = cardstr(p, e, &sdio.card);
+ p = seprint(p, e, "cid:\n");
+ p = cidstr(p, e, &sdio.card.cid);
+ p = seprint(p, e, "csd:\n");
+ p = csdstr(p, e, &sdio.card.csd);
USED(p);
n = readstr(off, a, n, buf);
@@ -834,24 +829,47 @@
free(buf);
poperror();
- qunlock(&sdl);
+ qunlock(&sdio);
return n;
}
+enum {
+ CMdebug, CMpreerase,
+};
+static Cmdtab sdioctl[] = {
+ CMdebug, "debug", 2,
+ CMpreerase, "preerase", 2,
+};
static long
-sdiowctl(Store *d, void *s, long n)
-{
- USED(d, s, n);
- print("sdiowctl\n");
- return -1;
-}
-
-static long
-sdioio(void *dd, int iswrite, void *buf, long n, vlong off)
-{
- USED(dd);
- return sdio(buf, n, off, iswrite);
+sdiowctl(Store *d, void *a, long n)
+{
+ Cmdbuf *cb;
+ Cmdtab *ct;
+
+ USED(d);
+
+ cb = parsecmd(a, n);
+ if(waserror()) {
+ free(cb);
+ nexterror();
+ }
+
+ ct = lookupcmd(cb, sdioctl, nelem(sdioctl));
+ switch(ct->index) {
+ case CMdebug:
+ debug = atoi(cb->f[1]);
+ break;
+ case CMpreerase:
+ qlock(&sdio);
+ sdio.preerase = atoi(cb->f[1]);
+ qunlock(&sdio);
+ }
+
+ poperror();
+ free(cb);
+
+ return n;
}
static void
@@ -859,11 +877,21 @@
{
Cid *c;
+ qlock(&sdio);
+ if(waserror()) {
+ qunlock(&sdio);
+ nexterror();
+ }
+
+ sdioinit0();
sdinit();
- d->size = card.size;
- c = &card.cid;
+ d->size = sdio.card.size;
+ c = &sdio.card.cid;
d->descr = smprint("product %q, serial %#lux, rev %#lux, %d-%d, sdhc %d",
- c->prodname, c->serial, c->rev, c->year, c->mon, card.sdhc);
+ c->prodname, c->serial, c->rev, c->year, c->mon, sdio.card.sdhc);
+
+ qunlock(&sdio);
+ poperror();
}
@@ -880,7 +908,6 @@
void
kwsdiolink(void)
{
- print("kwsdiolink\n");
sdioreset();
sdiodisk.num = 2;
blockstoreadd(&sdiodisk);
=======================================
--- /part.c Mon Mar 29 10:29:30 2010
+++ /part.c Wed Mar 31 04:09:52 2010
@@ -95,7 +95,7 @@
}
static Part*
-partalloc(Part *p, int np)
+partrealloc(Part *p, int np)
{
p = realloc(p, sizeof p[0]*(np+1));
if(p == nil)
@@ -121,7 +121,7 @@
int nparts = 1;
Part *parts = *partsp;
char *s, *e;
- char *f[3];
+ char *f[4];
int nf;
n = r(disk, 0, p, 512, 0);
@@ -135,7 +135,7 @@
for(i = 0; i < 4; i++) {
o = 446+i*16;
- *partsp = parts = partalloc(parts, nparts);
+ *partsp = parts = partrealloc(parts, nparts);
pp = &parts[nparts];
partclear(pp);
pp->index = nparts;
@@ -170,19 +170,21 @@
break;
*e = 0;
nf = tokenize(s, f, nelem(f));
- if(nf != 3)
+ if(nf != nelem(f) || strcmp(f[0], "part") != 0)
error("bad plan 9 partition table");
s = e+1;
- *partsp = parts = partalloc(parts, nparts);
+ *partsp = parts = partrealloc(parts, nparts);
pp = &parts[nparts];
partclear(pp);
pp->index = nparts;
- partgenname(pp, parts, nparts, f[0], f[0]);
- pp->s = (vlong)strtoull(f[1], nil, 0)*512;
- pp->e = (vlong)strtoull(f[2], nil, 0)*512;
+ partgenname(pp, parts, nparts, f[1], f[1]);
+ pp->s = (vlong)strtoull(f[2], nil, 0)*512;
+ pp->e = (vlong)strtoull(f[3], nil, 0)*512;
pp->size = pp->e-pp->s;
- partcheck(pp, parts, nparts, size);
+ partcheck(pp, parts+i, nparts-i, parts[i].size);
+ pp->s += parts[i].s;
+ pp->e += parts[i].e;
nparts++;
printpartadd(pp);
}
=======================================
--- /sheeva Mon Mar 29 07:16:41 2010
+++ /sheeva Wed Mar 31 04:09:52 2010
@@ -121,9 +121,10 @@
/n/kfs
/dis/bind.dis
- /dis/calc.dis
/dis/cat.dis
/dis/cd.dis
+ /dis/cmp.dis
+ /dis/cp.dis
/dis/date.dis
/dis/dd.dis
/dis/dial.dis
@@ -164,6 +165,11 @@
/dis/zeros.dis
/dis/disk/kfs.dis
+ /dis/disk/fdisk.dis
+ /dis/disk/prep.dis
+ /dis/disk/mbr.dis
+ /dis/disk/pedit.dis
+ /dis/disk/calc.tab.dis
/dis/sh/std.dis
/dis/ip/dhcp.dis
@@ -180,6 +186,7 @@
/dis/lib/dhcpclient.dis
/dis/lib/dial.dis
/dis/lib/dis.dis
+ /dis/lib/disks.dis
/dis/lib/encoding/base64.dis
/dis/lib/env.dis
/dis/lib/factotum.dis