19ef1f84bSDavid du Colombier /*
29ef1f84bSDavid du Colombier * aoe sd driver, copyright © 2007 coraid
39ef1f84bSDavid du Colombier */
49ef1f84bSDavid du Colombier
59ef1f84bSDavid du Colombier #include "u.h"
69ef1f84bSDavid du Colombier #include "../port/lib.h"
79ef1f84bSDavid du Colombier #include "mem.h"
89ef1f84bSDavid du Colombier #include "dat.h"
99ef1f84bSDavid du Colombier #include "fns.h"
109ef1f84bSDavid du Colombier #include "../port/error.h"
119ef1f84bSDavid du Colombier
129ef1f84bSDavid du Colombier #include "../port/netif.h"
139ef1f84bSDavid du Colombier #include "../port/sd.h"
149ef1f84bSDavid du Colombier
159ef1f84bSDavid du Colombier #include "etherif.h"
169ef1f84bSDavid du Colombier #include "../port/aoe.h"
179ef1f84bSDavid du Colombier
189ef1f84bSDavid du Colombier #define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__);
199ef1f84bSDavid du Colombier
209ef1f84bSDavid du Colombier enum {
219ef1f84bSDavid du Colombier Nctlr = 32,
229ef1f84bSDavid du Colombier Maxpath = 128,
239ef1f84bSDavid du Colombier
249ef1f84bSDavid du Colombier Probeintvl = 100, /* ms. between probes */
259ef1f84bSDavid du Colombier Probemax = 20, /* max probes */
269ef1f84bSDavid du Colombier };
279ef1f84bSDavid du Colombier
289ef1f84bSDavid du Colombier enum {
299ef1f84bSDavid du Colombier /* sync with ahci.h */
309ef1f84bSDavid du Colombier Dllba = 1<<0,
319ef1f84bSDavid du Colombier Dsmart = 1<<1,
329ef1f84bSDavid du Colombier Dpower = 1<<2,
339ef1f84bSDavid du Colombier Dnop = 1<<3,
349ef1f84bSDavid du Colombier Datapi = 1<<4,
359ef1f84bSDavid du Colombier Datapi16= 1<<5,
369ef1f84bSDavid du Colombier };
379ef1f84bSDavid du Colombier
389ef1f84bSDavid du Colombier static char *flagname[] = {
399ef1f84bSDavid du Colombier "llba",
409ef1f84bSDavid du Colombier "smart",
419ef1f84bSDavid du Colombier "power",
429ef1f84bSDavid du Colombier "nop",
439ef1f84bSDavid du Colombier "atapi",
449ef1f84bSDavid du Colombier "atapi16",
459ef1f84bSDavid du Colombier };
469ef1f84bSDavid du Colombier
479ef1f84bSDavid du Colombier typedef struct Ctlr Ctlr;
489ef1f84bSDavid du Colombier struct Ctlr{
499ef1f84bSDavid du Colombier QLock;
509ef1f84bSDavid du Colombier
519ef1f84bSDavid du Colombier Ctlr *next;
529ef1f84bSDavid du Colombier SDunit *unit;
539ef1f84bSDavid du Colombier
549ef1f84bSDavid du Colombier char path[Maxpath];
559ef1f84bSDavid du Colombier Chan *c;
569ef1f84bSDavid du Colombier
579ef1f84bSDavid du Colombier ulong vers;
589ef1f84bSDavid du Colombier uchar mediachange;
599ef1f84bSDavid du Colombier uchar flag;
609ef1f84bSDavid du Colombier uchar smart;
619ef1f84bSDavid du Colombier uchar smartrs;
629ef1f84bSDavid du Colombier uchar feat;
639ef1f84bSDavid du Colombier
649ef1f84bSDavid du Colombier uvlong sectors;
659ef1f84bSDavid du Colombier char serial[20+1];
669ef1f84bSDavid du Colombier char firmware[8+1];
679ef1f84bSDavid du Colombier char model[40+1];
689ef1f84bSDavid du Colombier char ident[0x100];
699ef1f84bSDavid du Colombier };
709ef1f84bSDavid du Colombier
719ef1f84bSDavid du Colombier void aoeidmove(char *p, ushort *a, unsigned n);
729ef1f84bSDavid du Colombier
739ef1f84bSDavid du Colombier static Lock ctlrlock;
749ef1f84bSDavid du Colombier static Ctlr *head;
759ef1f84bSDavid du Colombier static Ctlr *tail;
769ef1f84bSDavid du Colombier
779ef1f84bSDavid du Colombier SDifc sdaoeifc;
789ef1f84bSDavid du Colombier
799ef1f84bSDavid du Colombier static ushort
gbit16(void * a)809ef1f84bSDavid du Colombier gbit16(void *a)
819ef1f84bSDavid du Colombier {
829ef1f84bSDavid du Colombier uchar *i;
839ef1f84bSDavid du Colombier
849ef1f84bSDavid du Colombier i = a;
859ef1f84bSDavid du Colombier return i[1] << 8 | i[0];
869ef1f84bSDavid du Colombier }
879ef1f84bSDavid du Colombier
889ef1f84bSDavid du Colombier static ulong
gbit32(void * a)899ef1f84bSDavid du Colombier gbit32(void *a)
909ef1f84bSDavid du Colombier {
919ef1f84bSDavid du Colombier ulong j;
929ef1f84bSDavid du Colombier uchar *i;
939ef1f84bSDavid du Colombier
949ef1f84bSDavid du Colombier i = a;
959ef1f84bSDavid du Colombier j = i[3] << 24;
969ef1f84bSDavid du Colombier j |= i[2] << 16;
979ef1f84bSDavid du Colombier j |= i[1] << 8;
989ef1f84bSDavid du Colombier j |= i[0];
999ef1f84bSDavid du Colombier return j;
1009ef1f84bSDavid du Colombier }
1019ef1f84bSDavid du Colombier
1029ef1f84bSDavid du Colombier static uvlong
gbit64(void * a)1039ef1f84bSDavid du Colombier gbit64(void *a)
1049ef1f84bSDavid du Colombier {
1059ef1f84bSDavid du Colombier uchar *i;
1069ef1f84bSDavid du Colombier
1079ef1f84bSDavid du Colombier i = a;
1089ef1f84bSDavid du Colombier return (uvlong)gbit32(i+4)<<32 | gbit32(i);
1099ef1f84bSDavid du Colombier }
1109ef1f84bSDavid du Colombier
1119ef1f84bSDavid du Colombier static int
identify(Ctlr * c,ushort * id)1129ef1f84bSDavid du Colombier identify(Ctlr *c, ushort *id)
1139ef1f84bSDavid du Colombier {
1149ef1f84bSDavid du Colombier int i;
1159ef1f84bSDavid du Colombier uchar oserial[21];
1169ef1f84bSDavid du Colombier uvlong osectors, s;
1179ef1f84bSDavid du Colombier
1189ef1f84bSDavid du Colombier osectors = c->sectors;
1199ef1f84bSDavid du Colombier memmove(oserial, c->serial, sizeof c->serial);
1209ef1f84bSDavid du Colombier
1219ef1f84bSDavid du Colombier c->feat &= ~(Dllba|Dpower|Dsmart|Dnop);
1229ef1f84bSDavid du Colombier i = gbit16(id+83) | gbit16(id+86);
1239ef1f84bSDavid du Colombier if(i & (1<<10)){
1249ef1f84bSDavid du Colombier c->feat |= Dllba;
1259ef1f84bSDavid du Colombier s = gbit64(id+100);
1269ef1f84bSDavid du Colombier }else
1279ef1f84bSDavid du Colombier s = gbit32(id+60);
1289ef1f84bSDavid du Colombier
1299ef1f84bSDavid du Colombier i = gbit16(id+83);
1309ef1f84bSDavid du Colombier if((i>>14) == 1) {
1319ef1f84bSDavid du Colombier if(i & (1<<3))
1329ef1f84bSDavid du Colombier c->feat |= Dpower;
1339ef1f84bSDavid du Colombier i = gbit16(id+82);
1349ef1f84bSDavid du Colombier if(i & 1)
1359ef1f84bSDavid du Colombier c->feat |= Dsmart;
1369ef1f84bSDavid du Colombier if(i & (1<<14))
1379ef1f84bSDavid du Colombier c->feat |= Dnop;
1389ef1f84bSDavid du Colombier }
1399ef1f84bSDavid du Colombier
1409ef1f84bSDavid du Colombier aoeidmove(c->serial, id+10, 20);
1419ef1f84bSDavid du Colombier aoeidmove(c->firmware, id+23, 8);
1429ef1f84bSDavid du Colombier aoeidmove(c->model, id+27, 40);
1439ef1f84bSDavid du Colombier
1449ef1f84bSDavid du Colombier if((osectors == 0 || osectors != s) &&
1459ef1f84bSDavid du Colombier memcmp(oserial, c->serial, sizeof oserial) != 0){
1469ef1f84bSDavid du Colombier c->sectors = s;
1479ef1f84bSDavid du Colombier c->mediachange = 1;
1489ef1f84bSDavid du Colombier c->vers++;
1499ef1f84bSDavid du Colombier }
1509ef1f84bSDavid du Colombier return 0;
1519ef1f84bSDavid du Colombier }
1529ef1f84bSDavid du Colombier
1539ef1f84bSDavid du Colombier /* must call with d qlocked */
1549ef1f84bSDavid du Colombier static int
aoeidentify(Ctlr * d,SDunit * u)1559ef1f84bSDavid du Colombier aoeidentify(Ctlr *d, SDunit *u)
1569ef1f84bSDavid du Colombier {
1579ef1f84bSDavid du Colombier Chan *c;
1589ef1f84bSDavid du Colombier
1599ef1f84bSDavid du Colombier c = nil;
1609ef1f84bSDavid du Colombier if(waserror()){
1619ef1f84bSDavid du Colombier if(c)
1629ef1f84bSDavid du Colombier cclose(c);
1639ef1f84bSDavid du Colombier iprint("aoeidentify: %s\n", up->errstr);
1649ef1f84bSDavid du Colombier nexterror();
1659ef1f84bSDavid du Colombier }
1669ef1f84bSDavid du Colombier
1679ef1f84bSDavid du Colombier uprint("%s/ident", d->path);
1689ef1f84bSDavid du Colombier c = namec(up->genbuf, Aopen, OREAD, 0);
1699ef1f84bSDavid du Colombier c->dev->read(c, d->ident, sizeof d->ident, 0);
1709ef1f84bSDavid du Colombier
1719ef1f84bSDavid du Colombier poperror();
1729ef1f84bSDavid du Colombier cclose(c);
1739ef1f84bSDavid du Colombier
1749ef1f84bSDavid du Colombier d->feat = 0;
1759ef1f84bSDavid du Colombier d->smart = 0;
1769ef1f84bSDavid du Colombier identify(d, (ushort*)d->ident);
1779ef1f84bSDavid du Colombier
1789ef1f84bSDavid du Colombier memset(u->inquiry, 0, sizeof u->inquiry);
1799ef1f84bSDavid du Colombier u->inquiry[2] = 2;
1809ef1f84bSDavid du Colombier u->inquiry[3] = 2;
1819ef1f84bSDavid du Colombier u->inquiry[4] = sizeof u->inquiry - 4;
1829ef1f84bSDavid du Colombier memmove(u->inquiry+8, d->model, 40);
1839ef1f84bSDavid du Colombier
1849ef1f84bSDavid du Colombier return 0;
1859ef1f84bSDavid du Colombier }
1869ef1f84bSDavid du Colombier
1879ef1f84bSDavid du Colombier static Ctlr*
ctlrlookup(char * path)1889ef1f84bSDavid du Colombier ctlrlookup(char *path)
1899ef1f84bSDavid du Colombier {
1909ef1f84bSDavid du Colombier Ctlr *c;
1919ef1f84bSDavid du Colombier
1929ef1f84bSDavid du Colombier lock(&ctlrlock);
1939ef1f84bSDavid du Colombier for(c = head; c; c = c->next)
1949ef1f84bSDavid du Colombier if(strcmp(c->path, path) == 0)
1959ef1f84bSDavid du Colombier break;
1969ef1f84bSDavid du Colombier unlock(&ctlrlock);
1979ef1f84bSDavid du Colombier return c;
1989ef1f84bSDavid du Colombier }
1999ef1f84bSDavid du Colombier
2009ef1f84bSDavid du Colombier static Ctlr*
newctlr(char * path)2019ef1f84bSDavid du Colombier newctlr(char *path)
2029ef1f84bSDavid du Colombier {
2039ef1f84bSDavid du Colombier Ctlr *c;
2049ef1f84bSDavid du Colombier
2059ef1f84bSDavid du Colombier /* race? */
2069ef1f84bSDavid du Colombier if(ctlrlookup(path))
2079ef1f84bSDavid du Colombier error(Eexist);
2089ef1f84bSDavid du Colombier
2099ef1f84bSDavid du Colombier if((c = malloc(sizeof *c)) == nil)
2109ef1f84bSDavid du Colombier return 0;
2119ef1f84bSDavid du Colombier kstrcpy(c->path, path, sizeof c->path);
2129ef1f84bSDavid du Colombier lock(&ctlrlock);
2139ef1f84bSDavid du Colombier if(head != nil)
2149ef1f84bSDavid du Colombier tail->next = c;
2159ef1f84bSDavid du Colombier else
2169ef1f84bSDavid du Colombier head = c;
2179ef1f84bSDavid du Colombier tail = c;
2189ef1f84bSDavid du Colombier unlock(&ctlrlock);
2199ef1f84bSDavid du Colombier return c;
2209ef1f84bSDavid du Colombier }
2219ef1f84bSDavid du Colombier
2229ef1f84bSDavid du Colombier static void
delctlr(Ctlr * c)2239ef1f84bSDavid du Colombier delctlr(Ctlr *c)
2249ef1f84bSDavid du Colombier {
2259ef1f84bSDavid du Colombier Ctlr *x, *prev;
2269ef1f84bSDavid du Colombier
2279ef1f84bSDavid du Colombier lock(&ctlrlock);
2289ef1f84bSDavid du Colombier
2299ef1f84bSDavid du Colombier for(prev = 0, x = head; x; prev = x, x = c->next)
2309ef1f84bSDavid du Colombier if(strcmp(c->path, x->path) == 0)
2319ef1f84bSDavid du Colombier break;
2329ef1f84bSDavid du Colombier if(x == 0){
2339ef1f84bSDavid du Colombier unlock(&ctlrlock);
2349ef1f84bSDavid du Colombier error(Enonexist);
2359ef1f84bSDavid du Colombier }
2369ef1f84bSDavid du Colombier
2379ef1f84bSDavid du Colombier if(prev)
2389ef1f84bSDavid du Colombier prev->next = x->next;
2399ef1f84bSDavid du Colombier else
2409ef1f84bSDavid du Colombier head = x->next;
2419ef1f84bSDavid du Colombier if(x->next == nil)
2429ef1f84bSDavid du Colombier tail = prev;
2439ef1f84bSDavid du Colombier unlock(&ctlrlock);
2449ef1f84bSDavid du Colombier
2459ef1f84bSDavid du Colombier if(x->c)
2469ef1f84bSDavid du Colombier cclose(x->c);
2479ef1f84bSDavid du Colombier free(x);
2489ef1f84bSDavid du Colombier }
2499ef1f84bSDavid du Colombier
2509ef1f84bSDavid du Colombier /* don't call aoeprobe from within a loop; it loops internally retrying open. */
2519ef1f84bSDavid du Colombier static SDev*
aoeprobe(char * path,SDev * s)2529ef1f84bSDavid du Colombier aoeprobe(char *path, SDev *s)
2539ef1f84bSDavid du Colombier {
2549ef1f84bSDavid du Colombier int n, i;
2559ef1f84bSDavid du Colombier char *p;
2569ef1f84bSDavid du Colombier Chan *c;
2579ef1f84bSDavid du Colombier Ctlr *ctlr;
2589ef1f84bSDavid du Colombier
2599ef1f84bSDavid du Colombier if((p = strrchr(path, '/')) == 0)
2609ef1f84bSDavid du Colombier error(Ebadarg);
2619ef1f84bSDavid du Colombier *p = 0;
2629ef1f84bSDavid du Colombier uprint("%s/ctl", path);
2639ef1f84bSDavid du Colombier *p = '/';
2649ef1f84bSDavid du Colombier
2659ef1f84bSDavid du Colombier c = namec(up->genbuf, Aopen, OWRITE, 0);
2669ef1f84bSDavid du Colombier if(waserror()) {
2679ef1f84bSDavid du Colombier cclose(c);
2689ef1f84bSDavid du Colombier nexterror();
2699ef1f84bSDavid du Colombier }
2709ef1f84bSDavid du Colombier n = uprint("discover %s", p+1);
2719ef1f84bSDavid du Colombier c->dev->write(c, up->genbuf, n, 0);
2729ef1f84bSDavid du Colombier poperror();
2739ef1f84bSDavid du Colombier cclose(c);
2749ef1f84bSDavid du Colombier
2759ef1f84bSDavid du Colombier for(i = 0; i < Probemax; i++){
2769ef1f84bSDavid du Colombier tsleep(&up->sleep, return0, 0, Probeintvl);
2779ef1f84bSDavid du Colombier uprint("%s/ident", path);
2789ef1f84bSDavid du Colombier if(!waserror()) {
2799ef1f84bSDavid du Colombier c = namec(up->genbuf, Aopen, OREAD, 0);
2809ef1f84bSDavid du Colombier poperror();
2819ef1f84bSDavid du Colombier cclose(c);
2829ef1f84bSDavid du Colombier break;
2839ef1f84bSDavid du Colombier }
2849ef1f84bSDavid du Colombier }
2859ef1f84bSDavid du Colombier if(i >= Probemax)
2869ef1f84bSDavid du Colombier error(Etimedout);
2879ef1f84bSDavid du Colombier uprint("%s/ident", path);
2889ef1f84bSDavid du Colombier ctlr = newctlr(path);
2899ef1f84bSDavid du Colombier if(ctlr == nil || s == nil && (s = malloc(sizeof *s)) == nil)
2909ef1f84bSDavid du Colombier return nil;
2919ef1f84bSDavid du Colombier s->ctlr = ctlr;
2929ef1f84bSDavid du Colombier s->ifc = &sdaoeifc;
2939ef1f84bSDavid du Colombier s->nunit = 1;
2949ef1f84bSDavid du Colombier return s;
2959ef1f84bSDavid du Colombier }
2969ef1f84bSDavid du Colombier
2979ef1f84bSDavid du Colombier static char *probef[32];
2989ef1f84bSDavid du Colombier static int nprobe;
2999ef1f84bSDavid du Colombier
3009ef1f84bSDavid du Colombier static int
pnpprobeid(char * s)3019ef1f84bSDavid du Colombier pnpprobeid(char *s)
3029ef1f84bSDavid du Colombier {
3039ef1f84bSDavid du Colombier if(strlen(s) < 2)
3049ef1f84bSDavid du Colombier return 0;
3059ef1f84bSDavid du Colombier return s[1] == '!'? s[0]: 'e';
3069ef1f84bSDavid du Colombier }
3079ef1f84bSDavid du Colombier
3089ef1f84bSDavid du Colombier static SDev*
aoepnp(void)3099ef1f84bSDavid du Colombier aoepnp(void)
3109ef1f84bSDavid du Colombier {
3119ef1f84bSDavid du Colombier int i, id;
3129ef1f84bSDavid du Colombier char *p;
3139ef1f84bSDavid du Colombier SDev *h, *t, *s;
3149ef1f84bSDavid du Colombier
3159ef1f84bSDavid du Colombier if((p = getconf("aoedev")) == 0)
3169ef1f84bSDavid du Colombier return 0;
3179ef1f84bSDavid du Colombier nprobe = tokenize(p, probef, nelem(probef));
3189ef1f84bSDavid du Colombier h = t = 0;
3199ef1f84bSDavid du Colombier for(i = 0; i < nprobe; i++){
3209ef1f84bSDavid du Colombier id = pnpprobeid(probef[i]);
3219ef1f84bSDavid du Colombier if(id == 0)
3229ef1f84bSDavid du Colombier continue;
3239ef1f84bSDavid du Colombier s = malloc(sizeof *s);
3249ef1f84bSDavid du Colombier if(s == nil)
3259ef1f84bSDavid du Colombier break;
3269ef1f84bSDavid du Colombier s->ctlr = 0;
3279ef1f84bSDavid du Colombier s->idno = id;
3289ef1f84bSDavid du Colombier s->ifc = &sdaoeifc;
3299ef1f84bSDavid du Colombier s->nunit = 1;
3309ef1f84bSDavid du Colombier
3319ef1f84bSDavid du Colombier if(h)
3329ef1f84bSDavid du Colombier t->next = s;
3339ef1f84bSDavid du Colombier else
3349ef1f84bSDavid du Colombier h = s;
3359ef1f84bSDavid du Colombier t = s;
3369ef1f84bSDavid du Colombier }
3379ef1f84bSDavid du Colombier return h;
3389ef1f84bSDavid du Colombier }
3399ef1f84bSDavid du Colombier
3409ef1f84bSDavid du Colombier static Ctlr*
pnpprobe(SDev * sd)3419ef1f84bSDavid du Colombier pnpprobe(SDev *sd)
3429ef1f84bSDavid du Colombier {
3439ef1f84bSDavid du Colombier ulong start;
3449ef1f84bSDavid du Colombier char *p;
3459ef1f84bSDavid du Colombier static int i;
3469ef1f84bSDavid du Colombier
3479ef1f84bSDavid du Colombier if(i > nprobe)
3489ef1f84bSDavid du Colombier return 0;
3499ef1f84bSDavid du Colombier p = probef[i++];
3509ef1f84bSDavid du Colombier if(strlen(p) < 2)
3519ef1f84bSDavid du Colombier return 0;
3529ef1f84bSDavid du Colombier if(p[1] == '!')
3539ef1f84bSDavid du Colombier p += 2;
3549ef1f84bSDavid du Colombier
3559ef1f84bSDavid du Colombier start = TK2MS(sys->ticks);
3569ef1f84bSDavid du Colombier if(waserror()){
3579ef1f84bSDavid du Colombier print("#æ: pnpprobe failed in %lud ms: %s: %s\n",
3589ef1f84bSDavid du Colombier TK2MS(sys->ticks) - start, probef[i-1],
3599ef1f84bSDavid du Colombier up->errstr);
3609ef1f84bSDavid du Colombier return nil;
3619ef1f84bSDavid du Colombier }
3629ef1f84bSDavid du Colombier sd = aoeprobe(p, sd); /* does a round of probing */
3639ef1f84bSDavid du Colombier poperror();
3649ef1f84bSDavid du Colombier print("#æ: pnpprobe established %s in %lud ms\n",
3659ef1f84bSDavid du Colombier probef[i-1], TK2MS(sys->ticks) - start);
3669ef1f84bSDavid du Colombier return sd->ctlr;
3679ef1f84bSDavid du Colombier }
3689ef1f84bSDavid du Colombier
3699ef1f84bSDavid du Colombier
3709ef1f84bSDavid du Colombier static int
aoeverify(SDunit * u)3719ef1f84bSDavid du Colombier aoeverify(SDunit *u)
3729ef1f84bSDavid du Colombier {
3739ef1f84bSDavid du Colombier SDev *s;
3749ef1f84bSDavid du Colombier Ctlr *c;
3759ef1f84bSDavid du Colombier
3769ef1f84bSDavid du Colombier s = u->dev;
3779ef1f84bSDavid du Colombier c = s->ctlr;
3789ef1f84bSDavid du Colombier if(c == nil && (s->ctlr = c = pnpprobe(s)) == nil)
3799ef1f84bSDavid du Colombier return 0;
3809ef1f84bSDavid du Colombier c->mediachange = 1;
3819ef1f84bSDavid du Colombier return 1;
3829ef1f84bSDavid du Colombier }
3839ef1f84bSDavid du Colombier
3849ef1f84bSDavid du Colombier static int
aoeconnect(SDunit * u,Ctlr * c)3859ef1f84bSDavid du Colombier aoeconnect(SDunit *u, Ctlr *c)
3869ef1f84bSDavid du Colombier {
3879ef1f84bSDavid du Colombier qlock(c);
3889ef1f84bSDavid du Colombier if(waserror()){
3899ef1f84bSDavid du Colombier qunlock(c);
3909ef1f84bSDavid du Colombier return -1;
3919ef1f84bSDavid du Colombier }
3929ef1f84bSDavid du Colombier
3939ef1f84bSDavid du Colombier aoeidentify(u->dev->ctlr, u);
3949ef1f84bSDavid du Colombier if(c->c)
3959ef1f84bSDavid du Colombier cclose(c->c);
3969ef1f84bSDavid du Colombier c->c = 0;
3979ef1f84bSDavid du Colombier uprint("%s/data", c->path);
3989ef1f84bSDavid du Colombier c->c = namec(up->genbuf, Aopen, ORDWR, 0);
3999ef1f84bSDavid du Colombier qunlock(c);
4009ef1f84bSDavid du Colombier poperror();
4019ef1f84bSDavid du Colombier
4029ef1f84bSDavid du Colombier return 0;
4039ef1f84bSDavid du Colombier }
4049ef1f84bSDavid du Colombier
4059ef1f84bSDavid du Colombier static int
aoeonline(SDunit * u)4069ef1f84bSDavid du Colombier aoeonline(SDunit *u)
4079ef1f84bSDavid du Colombier {
4089ef1f84bSDavid du Colombier Ctlr *c;
4099ef1f84bSDavid du Colombier int r;
4109ef1f84bSDavid du Colombier
4119ef1f84bSDavid du Colombier c = u->dev->ctlr;
4129ef1f84bSDavid du Colombier r = 0;
4139ef1f84bSDavid du Colombier
4149ef1f84bSDavid du Colombier if((c->feat&Datapi) && c->mediachange){
4159ef1f84bSDavid du Colombier if(aoeconnect(u, c) == 0 && (r = scsionline(u)) > 0)
4169ef1f84bSDavid du Colombier c->mediachange = 0;
4179ef1f84bSDavid du Colombier return r;
4189ef1f84bSDavid du Colombier }
4199ef1f84bSDavid du Colombier
4209ef1f84bSDavid du Colombier if(c->mediachange){
4219ef1f84bSDavid du Colombier if(aoeconnect(u, c) == -1)
4229ef1f84bSDavid du Colombier return 0;
4239ef1f84bSDavid du Colombier r = 2;
4249ef1f84bSDavid du Colombier c->mediachange = 0;
4259ef1f84bSDavid du Colombier u->sectors = c->sectors;
4269ef1f84bSDavid du Colombier u->secsize = Aoesectsz;
4279ef1f84bSDavid du Colombier } else
4289ef1f84bSDavid du Colombier r = 1;
4299ef1f84bSDavid du Colombier
4309ef1f84bSDavid du Colombier return r;
4319ef1f84bSDavid du Colombier }
4329ef1f84bSDavid du Colombier
4339ef1f84bSDavid du Colombier static int
aoerio(SDreq * r)4349ef1f84bSDavid du Colombier aoerio(SDreq *r)
4359ef1f84bSDavid du Colombier {
436*05ffe48fSDavid du Colombier int i;
437*05ffe48fSDavid du Colombier ulong count;
4389ef1f84bSDavid du Colombier uvlong lba;
4399ef1f84bSDavid du Colombier char *name;
4409ef1f84bSDavid du Colombier uchar *cmd;
4419ef1f84bSDavid du Colombier long (*rio)(Chan*, void*, long, vlong);
4429ef1f84bSDavid du Colombier Ctlr *c;
4439ef1f84bSDavid du Colombier SDunit *unit;
4449ef1f84bSDavid du Colombier
4459ef1f84bSDavid du Colombier unit = r->unit;
4469ef1f84bSDavid du Colombier c = unit->dev->ctlr;
4479ef1f84bSDavid du Colombier // if(c->feat & Datapi)
4489ef1f84bSDavid du Colombier // return aoeriopkt(r, d);
4499ef1f84bSDavid du Colombier
4509ef1f84bSDavid du Colombier cmd = r->cmd;
4519ef1f84bSDavid du Colombier name = unit->name;
4529ef1f84bSDavid du Colombier
453a72b0d60SDavid du Colombier if(*cmd == ScmdSynccache || *cmd == ScmdSynccache16)
4549ef1f84bSDavid du Colombier // qlock(c);
4559ef1f84bSDavid du Colombier // i = flushcache();
4569ef1f84bSDavid du Colombier // qunlock(c);
4579ef1f84bSDavid du Colombier // if(i == 0)
4589ef1f84bSDavid du Colombier // return sdsetsense(r, SDok, 0, 0, 0);
4599ef1f84bSDavid du Colombier return sdsetsense(r, SDcheck, 3, 0xc, 2);
4609ef1f84bSDavid du Colombier
4619ef1f84bSDavid du Colombier if((i = sdfakescsi(r, c->ident, sizeof c->ident)) != SDnostatus){
4629ef1f84bSDavid du Colombier r->status = i;
4639ef1f84bSDavid du Colombier return i;
4649ef1f84bSDavid du Colombier }
4659ef1f84bSDavid du Colombier
4669ef1f84bSDavid du Colombier switch(*cmd){
467a72b0d60SDavid du Colombier case ScmdRead16:
468a72b0d60SDavid du Colombier case ScmdExtread:
4699ef1f84bSDavid du Colombier rio = c->c->dev->read;
4709ef1f84bSDavid du Colombier break;
471a72b0d60SDavid du Colombier case ScmdWrite16:
472a72b0d60SDavid du Colombier case ScmdExtwrite:
4739ef1f84bSDavid du Colombier rio = c->c->dev->write;
4749ef1f84bSDavid du Colombier break;
4759ef1f84bSDavid du Colombier default:
4769ef1f84bSDavid du Colombier print("%s: bad cmd %#.2ux\n", name, cmd[0]);
4779ef1f84bSDavid du Colombier r->status = SDcheck;
4789ef1f84bSDavid du Colombier return SDcheck;
4799ef1f84bSDavid du Colombier }
4809ef1f84bSDavid du Colombier
4819ef1f84bSDavid du Colombier if(r->data == nil)
4829ef1f84bSDavid du Colombier return SDok;
4839ef1f84bSDavid du Colombier
4849ef1f84bSDavid du Colombier if(r->clen == 16){
485*05ffe48fSDavid du Colombier /* ata commands only go to 48-bit lba */
4869ef1f84bSDavid du Colombier if(cmd[2] || cmd[3])
4879ef1f84bSDavid du Colombier return sdsetsense(r, SDcheck, 3, 0xc, 2);
4889ef1f84bSDavid du Colombier }
489*05ffe48fSDavid du Colombier scsilbacount(cmd, r->clen, &lba, &count);
4909ef1f84bSDavid du Colombier count *= Aoesectsz;
4919ef1f84bSDavid du Colombier
4929ef1f84bSDavid du Colombier if(r->dlen < count)
4939ef1f84bSDavid du Colombier count = r->dlen & ~0x1ff;
4949ef1f84bSDavid du Colombier
4959ef1f84bSDavid du Colombier if(waserror()){
4969ef1f84bSDavid du Colombier if(strcmp(up->errstr, Echange) == 0 ||
497406c76faSDavid du Colombier strcmp(up->errstr, Eaoedown) == 0)
4989ef1f84bSDavid du Colombier unit->sectors = 0;
4999ef1f84bSDavid du Colombier nexterror();
5009ef1f84bSDavid du Colombier }
5019ef1f84bSDavid du Colombier r->rlen = rio(c->c, r->data, count, Aoesectsz * lba);
5029ef1f84bSDavid du Colombier poperror();
5039ef1f84bSDavid du Colombier r->status = SDok;
5049ef1f84bSDavid du Colombier return SDok;
5059ef1f84bSDavid du Colombier }
5069ef1f84bSDavid du Colombier
5079ef1f84bSDavid du Colombier static char *smarttab[] = {
5089ef1f84bSDavid du Colombier "unset",
5099ef1f84bSDavid du Colombier "error",
5109ef1f84bSDavid du Colombier "threshold exceeded",
5119ef1f84bSDavid du Colombier "normal"
5129ef1f84bSDavid du Colombier };
5139ef1f84bSDavid du Colombier
5149ef1f84bSDavid du Colombier static char *
pflag(char * s,char * e,uchar f)5159ef1f84bSDavid du Colombier pflag(char *s, char *e, uchar f)
5169ef1f84bSDavid du Colombier {
5179ef1f84bSDavid du Colombier uchar i;
5189ef1f84bSDavid du Colombier
5199ef1f84bSDavid du Colombier for(i = 0; i < 8; i++)
5209ef1f84bSDavid du Colombier if(f & (1 << i))
5219ef1f84bSDavid du Colombier s = seprint(s, e, "%s ", flagname[i]);
5229ef1f84bSDavid du Colombier return seprint(s, e, "\n");
5239ef1f84bSDavid du Colombier }
5249ef1f84bSDavid du Colombier
5259ef1f84bSDavid du Colombier static int
aoerctl(SDunit * u,char * p,int l)5269ef1f84bSDavid du Colombier aoerctl(SDunit *u, char *p, int l)
5279ef1f84bSDavid du Colombier {
5289ef1f84bSDavid du Colombier Ctlr *c;
5299ef1f84bSDavid du Colombier char *e, *op;
5309ef1f84bSDavid du Colombier
5319ef1f84bSDavid du Colombier if((c = u->dev->ctlr) == nil)
5329ef1f84bSDavid du Colombier return 0;
5339ef1f84bSDavid du Colombier e = p+l;
5349ef1f84bSDavid du Colombier op = p;
5359ef1f84bSDavid du Colombier
5369ef1f84bSDavid du Colombier p = seprint(p, e, "model\t%s\n", c->model);
5379ef1f84bSDavid du Colombier p = seprint(p, e, "serial\t%s\n", c->serial);
5389ef1f84bSDavid du Colombier p = seprint(p, e, "firm %s\n", c->firmware);
5399ef1f84bSDavid du Colombier if(c->smartrs == 0xff)
5409ef1f84bSDavid du Colombier p = seprint(p, e, "smart\tenable error\n");
5419ef1f84bSDavid du Colombier else if(c->smartrs == 0)
5429ef1f84bSDavid du Colombier p = seprint(p, e, "smart\tdisabled\n");
5439ef1f84bSDavid du Colombier else
5449ef1f84bSDavid du Colombier p = seprint(p, e, "smart\t%s\n", smarttab[c->smart]);
5459ef1f84bSDavid du Colombier p = seprint(p, e, "flag ");
5469ef1f84bSDavid du Colombier p = pflag(p, e, c->feat);
5479ef1f84bSDavid du Colombier p = seprint(p, e, "geometry %llud %d\n", c->sectors, Aoesectsz);
5489ef1f84bSDavid du Colombier return p-op;
5499ef1f84bSDavid du Colombier }
5509ef1f84bSDavid du Colombier
5519ef1f84bSDavid du Colombier static int
aoewctl(SDunit *,Cmdbuf * cmd)5529ef1f84bSDavid du Colombier aoewctl(SDunit *, Cmdbuf *cmd)
5539ef1f84bSDavid du Colombier {
5549ef1f84bSDavid du Colombier cmderror(cmd, Ebadarg);
5559ef1f84bSDavid du Colombier return 0;
5569ef1f84bSDavid du Colombier }
5579ef1f84bSDavid du Colombier
5589ef1f84bSDavid du Colombier static SDev*
aoeprobew(DevConf * c)5599ef1f84bSDavid du Colombier aoeprobew(DevConf *c)
5609ef1f84bSDavid du Colombier {
5619ef1f84bSDavid du Colombier char *p;
5629ef1f84bSDavid du Colombier
5639ef1f84bSDavid du Colombier p = strchr(c->type, '/');
5649ef1f84bSDavid du Colombier if(p == nil || strlen(p) > Maxpath - 11)
5659ef1f84bSDavid du Colombier error(Ebadarg);
5669ef1f84bSDavid du Colombier if(p[1] == '#')
5679ef1f84bSDavid du Colombier p++; /* hack */
5689ef1f84bSDavid du Colombier if(ctlrlookup(p))
5699ef1f84bSDavid du Colombier error(Einuse);
5709ef1f84bSDavid du Colombier return aoeprobe(p, 0);
5719ef1f84bSDavid du Colombier }
5729ef1f84bSDavid du Colombier
5739ef1f84bSDavid du Colombier static void
aoeclear(SDev * s)5749ef1f84bSDavid du Colombier aoeclear(SDev *s)
5759ef1f84bSDavid du Colombier {
5769ef1f84bSDavid du Colombier delctlr((Ctlr *)s->ctlr);
5779ef1f84bSDavid du Colombier }
5789ef1f84bSDavid du Colombier
5799ef1f84bSDavid du Colombier static char*
aoertopctl(SDev * s,char * p,char * e)5809ef1f84bSDavid du Colombier aoertopctl(SDev *s, char *p, char *e)
5819ef1f84bSDavid du Colombier {
5829ef1f84bSDavid du Colombier Ctlr *c;
5839ef1f84bSDavid du Colombier
5849ef1f84bSDavid du Colombier if(s == nil || (c = s->ctlr) == nil)
5859ef1f84bSDavid du Colombier return p;
5869ef1f84bSDavid du Colombier
5879ef1f84bSDavid du Colombier return seprint(p, e, "%s aoe %s\n", s->name, c->path);
5889ef1f84bSDavid du Colombier }
5899ef1f84bSDavid du Colombier
5909ef1f84bSDavid du Colombier static int
aoewtopctl(SDev *,Cmdbuf * cmd)5919ef1f84bSDavid du Colombier aoewtopctl(SDev *, Cmdbuf *cmd)
5929ef1f84bSDavid du Colombier {
5939ef1f84bSDavid du Colombier switch(cmd->nf){
5949ef1f84bSDavid du Colombier default:
5959ef1f84bSDavid du Colombier cmderror(cmd, Ebadarg);
5969ef1f84bSDavid du Colombier }
5979ef1f84bSDavid du Colombier return 0;
5989ef1f84bSDavid du Colombier }
5999ef1f84bSDavid du Colombier
6009ef1f84bSDavid du Colombier SDifc sdaoeifc = {
6019ef1f84bSDavid du Colombier "aoe",
6029ef1f84bSDavid du Colombier
6039ef1f84bSDavid du Colombier aoepnp,
6049ef1f84bSDavid du Colombier nil, /* legacy */
6059ef1f84bSDavid du Colombier nil, /* enable */
6069ef1f84bSDavid du Colombier nil, /* disable */
6079ef1f84bSDavid du Colombier
6089ef1f84bSDavid du Colombier aoeverify,
6099ef1f84bSDavid du Colombier aoeonline,
6109ef1f84bSDavid du Colombier aoerio,
6119ef1f84bSDavid du Colombier aoerctl,
6129ef1f84bSDavid du Colombier aoewctl,
6139ef1f84bSDavid du Colombier
6149ef1f84bSDavid du Colombier scsibio,
6159ef1f84bSDavid du Colombier aoeprobew, /* probe */
6169ef1f84bSDavid du Colombier aoeclear, /* clear */
6179ef1f84bSDavid du Colombier aoertopctl,
6189ef1f84bSDavid du Colombier aoewtopctl,
6199ef1f84bSDavid du Colombier };
620