The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/port/sdaoe.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * aoe sd driver, copyright © 2007 coraid
    3  */
    4 
    5 #include "u.h"
    6 #include "../port/lib.h"
    7 #include "mem.h"
    8 #include "dat.h"
    9 #include "fns.h"
   10 #include "io.h"
   11 #include "../port/error.h"
   12 #include "../port/sd.h"
   13 #include "../port/netif.h"
   14 #include "../port/aoe.h"
   15 
   16 extern  char    Echange[];
   17 extern  char    Enotup[];
   18 
   19 #define uprint(...)     snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__);
   20 
   21 enum {
   22         Nctlr   = 32,
   23         Maxpath = 128,
   24 
   25         Probeintvl      = 100,          /* ms. between probes */
   26         Probemax        = 10*1000,      /* max ms. to wait */
   27 };
   28 
   29 enum {
   30         /* sync with ahci.h */
   31         Dllba   = 1<<0,
   32         Dsmart  = 1<<1,
   33         Dpower  = 1<<2,
   34         Dnop    = 1<<3,
   35         Datapi  = 1<<4,
   36         Datapi16= 1<<5,
   37 };
   38 
   39 static char *flagname[] = {
   40         "llba",
   41         "smart",
   42         "power",
   43         "nop",
   44         "atapi",
   45         "atapi16",
   46 };
   47 
   48 typedef struct Ctlr Ctlr;
   49 struct Ctlr{
   50         QLock;
   51 
   52         Ctlr    *next;
   53         SDunit  *unit;
   54 
   55         char    path[Maxpath];
   56         Chan    *c;
   57 
   58         ulong   vers;
   59         uchar   mediachange;
   60         uchar   flag;
   61         uchar   smart;
   62         uchar   smartrs;
   63         uchar   feat;
   64 
   65         uvlong  sectors;
   66         char    serial[20+1];
   67         char    firmware[8+1];
   68         char    model[40+1];
   69         char    ident[0x100];
   70 };
   71 
   72 static  Lock    ctlrlock;
   73 static  Ctlr    *head;
   74 static  Ctlr    *tail;
   75 
   76 SDifc sdaoeifc;
   77 
   78 static void
   79 idmove(char *p, ushort *a, int n)
   80 {
   81         int i;
   82         char *op, *e;
   83 
   84         op = p;
   85         for(i = 0; i < n/2; i++){
   86                 *p++ = a[i] >> 8;
   87                 *p++ = a[i];
   88         }
   89         *p = 0;
   90         while(p > op && *--p == ' ')
   91                 *p = 0;
   92         e = p;
   93         p = op;
   94         while(*p == ' ')
   95                 p++;
   96         memmove(op, p, n - (e - p));
   97 }
   98 
   99 static ushort
  100 gbit16(void *a)
  101 {
  102         uchar *i;
  103 
  104         i = a;
  105         return i[1] << 8 | i[0];
  106 }
  107 
  108 static ulong
  109 gbit32(void *a)
  110 {
  111         ulong j;
  112         uchar *i;
  113 
  114         i = a;
  115         j  = i[3] << 24;
  116         j |= i[2] << 16;
  117         j |= i[1] << 8;
  118         j |= i[0];
  119         return j;
  120 }
  121 
  122 static uvlong
  123 gbit64(void *a)
  124 {
  125         uchar *i;
  126 
  127         i = a;
  128         return (uvlong)gbit32(i+4)<<32 | gbit32(i);
  129 }
  130 
  131 static int
  132 identify(Ctlr *c, ushort *id)
  133 {
  134         int i;
  135         uchar oserial[21];
  136         uvlong osectors, s;
  137 
  138         osectors = c->sectors;
  139         memmove(oserial, c->serial, sizeof c->serial);
  140 
  141         c->feat &= ~(Dllba|Dpower|Dsmart|Dnop);
  142         i = gbit16(id+83) | gbit16(id+86);
  143         if(i & (1<<10)){
  144                 c->feat |= Dllba;
  145                 s = gbit64(id+100);
  146         }else
  147                 s = gbit32(id+60);
  148 
  149         i = gbit16(id+83);
  150         if((i>>14) == 1) {
  151                 if(i & (1<<3))
  152                         c->feat |= Dpower;
  153                 i = gbit16(id+82);
  154                 if(i & 1)
  155                         c->feat |= Dsmart;
  156                 if(i & (1<<14))
  157                         c->feat |= Dnop;
  158         }
  159 
  160         idmove(c->serial, id+10, 20);
  161         idmove(c->firmware, id+23, 8);
  162         idmove(c->model, id+27, 40);
  163 
  164         if((osectors == 0 || osectors != s) &&
  165             memcmp(oserial, c->serial, sizeof oserial) != 0){
  166                 c->sectors = s;
  167                 c->mediachange = 1;
  168                 c->vers++;
  169         }
  170         return 0;
  171 }
  172 
  173 /* must call with d qlocked */
  174 static int
  175 aoeidentify(Ctlr *d, SDunit *u)
  176 {
  177         Chan *c;
  178 
  179         c = nil;
  180         if(waserror()){
  181                 if(c)
  182                         cclose(c);
  183                 iprint("aoeidentify: %s\n", up->errstr);
  184                 nexterror();
  185         }
  186 
  187         uprint("%s/ident", d->path);
  188         c = namec(up->genbuf, Aopen, OREAD, 0);
  189         devtab[c->type]->read(c, d->ident, sizeof d->ident, 0);
  190 
  191         poperror();
  192         cclose(c);
  193 
  194         d->feat = 0;
  195         d->smart = 0;
  196         identify(d, (ushort*)d->ident);
  197 
  198         memset(u->inquiry, 0, sizeof u->inquiry);
  199         u->inquiry[2] = 2;
  200         u->inquiry[3] = 2;
  201         u->inquiry[4] = sizeof u->inquiry - 4;
  202         memmove(u->inquiry+8, d->model, 40);
  203 
  204         return 0;
  205 }
  206 
  207 static Ctlr*
  208 ctlrlookup(char *path)
  209 {
  210         Ctlr *c;
  211 
  212         lock(&ctlrlock);
  213         for(c = head; c; c = c->next)
  214                 if(strcmp(c->path, path) == 0)
  215                         break;
  216         unlock(&ctlrlock);
  217         return c;
  218 }
  219 
  220 static Ctlr*
  221 newctlr(char *path)
  222 {
  223         Ctlr *c;
  224 
  225         /* race? */
  226         if(ctlrlookup(path))
  227                 error(Eexist);
  228 
  229         if((c = malloc(sizeof *c)) == nil)
  230                 return 0;
  231         kstrcpy(c->path, path, sizeof c->path);
  232         lock(&ctlrlock);
  233         if(head != nil)
  234                 tail->next = c;
  235         else
  236                 head = c;
  237         tail = c;
  238         unlock(&ctlrlock);
  239         return c;
  240 }
  241 
  242 static void
  243 delctlr(Ctlr *c)
  244 {
  245         Ctlr *x, *prev;
  246 
  247         lock(&ctlrlock);
  248 
  249         for(prev = 0, x = head; x; prev = x, x = c->next)
  250                 if(strcmp(c->path, x->path) == 0)
  251                         break;
  252         if(x == 0){
  253                 unlock(&ctlrlock);
  254                 error(Enonexist);
  255         }
  256 
  257         if(prev)
  258                 prev->next = x->next;
  259         else
  260                 head = x->next;
  261         if(x->next == nil)
  262                 tail = prev;
  263         unlock(&ctlrlock);
  264 
  265         if(x->c)
  266                 cclose(x->c);
  267         free(x);
  268 }
  269 
  270 static SDev*
  271 aoeprobe(char *path, SDev *s)
  272 {
  273         int n, i;
  274         char *p;
  275         Chan *c;
  276         Ctlr *ctlr;
  277 
  278         if((p = strrchr(path, '/')) == 0)
  279                 error(Ebadarg);
  280         *p = 0;
  281         uprint("%s/ctl", path);
  282         *p = '/';
  283 
  284         c = namec(up->genbuf, Aopen, OWRITE, 0);
  285         if(waserror()) {
  286                 cclose(c);
  287                 nexterror();
  288         }
  289         n = uprint("discover %s", p+1);
  290         devtab[c->type]->write(c, up->genbuf, n, 0);
  291         poperror();
  292         cclose(c);
  293 
  294         for(i = 0; i <= Probemax; i += Probeintvl){
  295                 tsleep(&up->sleep, return0, 0, Probeintvl);
  296                 uprint("%s/ident", path);
  297                 if(!waserror()) {
  298                         c = namec(up->genbuf, Aopen, OREAD, 0);
  299                         poperror();
  300                         cclose(c);
  301                         break;
  302                 }
  303         }
  304         if(i > Probemax)
  305                 error(Etimedout);
  306         uprint("%s/ident", path);
  307         ctlr = newctlr(path);
  308         if(ctlr == nil || s == nil && (s = malloc(sizeof *s)) == nil)
  309                 return nil;
  310         s->ctlr = ctlr;
  311         s->ifc = &sdaoeifc;
  312         s->nunit = 1;
  313         return s;
  314 }
  315 
  316 static char     *probef[32];
  317 static int      nprobe;
  318 
  319 static int
  320 pnpprobeid(char *s)
  321 {
  322         int id;
  323 
  324         if(strlen(s) < 2)
  325                 return 0;
  326         id = 'e';
  327         if(s[1] == '!')
  328                 id = s[0];
  329         return id;
  330 }
  331 
  332 static SDev*
  333 aoepnp(void)
  334 {
  335         int i, id;
  336         char *p;
  337         SDev *h, *t, *s;
  338 
  339         if((p = getconf("aoedev")) == 0)
  340                 return 0;
  341         nprobe = tokenize(p, probef, nelem(probef));
  342         h = t = 0;
  343         for(i = 0; i < nprobe; i++){
  344                 id = pnpprobeid(probef[i]);
  345                 if(id == 0)
  346                         continue;
  347                 s = malloc(sizeof *s);
  348                 if(s == nil)
  349                         break;
  350                 s->ctlr = 0;
  351                 s->idno = id;
  352                 s->ifc = &sdaoeifc;
  353                 s->nunit = 1;
  354 
  355                 if(h)
  356                         t->next = s;
  357                 else
  358                         h = s;
  359                 t = s;
  360         }
  361         return h;
  362 }
  363 
  364 static Ctlr*
  365 pnpprobe(SDev *sd)
  366 {
  367         int j;
  368         char *p;
  369         static int i;
  370 
  371         if(i > nprobe)
  372                 return 0;
  373         p = probef[i++];
  374         if(strlen(p) < 2)
  375                 return 0;
  376         if(p[1] == '!')
  377                 p += 2;
  378 
  379         for(j = 0; j <= Probemax; j += Probeintvl){
  380                 if(!waserror()){
  381                         sd = aoeprobe(p, sd);
  382                         poperror();
  383                         break;
  384                 }
  385                 tsleep(&up->sleep, return0, 0, Probeintvl);
  386         }
  387         if(j > Probemax){
  388                 print("#æ: pnpprobe failed in %d ms: %s: %s\n",
  389                         j, probef[i-1], up->errstr);
  390                 return nil;
  391         }
  392         print("#æ: pnpprobe established %s in %d ms\n", probef[i-1], j);
  393         return sd->ctlr;
  394 }
  395 
  396 
  397 static int
  398 aoeverify(SDunit *u)
  399 {
  400         SDev *s;
  401         Ctlr *c;
  402 
  403         s = u->dev;
  404         c = s->ctlr;
  405         if(c == nil && (s->ctlr = c = pnpprobe(s)) == nil)
  406                 return 0;
  407         c->mediachange = 1;
  408         return 1;
  409 }
  410 
  411 static int
  412 aoeconnect(SDunit *u, Ctlr *c)
  413 {
  414         qlock(c);
  415         if(waserror()){
  416                 qunlock(c);
  417                 return -1;
  418         }
  419 
  420         aoeidentify(u->dev->ctlr, u);
  421         if(c->c)
  422                 cclose(c->c);
  423         c->c = 0;
  424         uprint("%s/data", c->path);
  425         c->c = namec(up->genbuf, Aopen, ORDWR, 0);
  426         qunlock(c);
  427         poperror();
  428 
  429         return 0;
  430 }
  431 
  432 static int
  433 aoeonline(SDunit *u)
  434 {
  435         Ctlr *c;
  436         int r;
  437 
  438         c = u->dev->ctlr;
  439         r = 0;
  440 
  441         if((c->feat&Datapi) && c->mediachange){
  442                 if(aoeconnect(u, c) == 0 && (r = scsionline(u)) > 0)
  443                         c->mediachange = 0;
  444                 return r;
  445         }
  446 
  447         if(c->mediachange){
  448                 if(aoeconnect(u, c) == -1)
  449                         return 0;
  450                 r = 2;
  451                 c->mediachange = 0;
  452                 u->sectors = c->sectors;
  453                 u->secsize = Aoesectsz;
  454         } else
  455                 r = 1;
  456 
  457         return r;
  458 }
  459 
  460 static int
  461 aoerio(SDreq *r)
  462 {
  463         int i, count;
  464         uvlong lba;
  465         char *name;
  466         uchar *cmd;
  467         long (*rio)(Chan*, void*, long, vlong);
  468         Ctlr *c;
  469         SDunit *unit;
  470 
  471         unit = r->unit;
  472         c = unit->dev->ctlr;
  473 //      if(c->feat & Datapi)
  474 //              return aoeriopkt(r, d);
  475 
  476         cmd = r->cmd;
  477         name = unit->name;
  478 
  479         if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){
  480 //              qlock(c);
  481 //              i = flushcache();
  482 //              qunlock(c);
  483 //              if(i == 0)
  484 //                      return sdsetsense(r, SDok, 0, 0, 0);
  485                 return sdsetsense(r, SDcheck, 3, 0xc, 2);
  486         }
  487 
  488         if((i = sdfakescsi(r, c->ident, sizeof c->ident)) != SDnostatus){
  489                 r->status = i;
  490                 return i;
  491         }
  492 
  493         switch(*cmd){
  494         case 0x88:
  495         case 0x28:
  496                 rio = devtab[c->c->type]->read;
  497                 break;
  498         case 0x8a:
  499         case 0x2a:
  500                 rio = devtab[c->c->type]->write;
  501                 break;
  502         default:
  503                 print("%s: bad cmd %#.2ux\n", name, cmd[0]);
  504                 r->status = SDcheck;
  505                 return SDcheck;
  506         }
  507 
  508         if(r->data == nil)
  509                 return SDok;
  510 
  511         if(r->clen == 16){
  512                 if(cmd[2] || cmd[3])
  513                         return sdsetsense(r, SDcheck, 3, 0xc, 2);
  514                 lba = (uvlong)cmd[4]<<40 | (uvlong)cmd[5]<<32;
  515                 lba |=   cmd[6]<<24 |  cmd[7]<<16 |  cmd[8]<<8 | cmd[9];
  516                 count = cmd[10]<<24 | cmd[11]<<16 | cmd[12]<<8 | cmd[13];
  517         }else{
  518                 lba  = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];
  519                 count = cmd[7]<<8 | cmd[8];
  520         }
  521 
  522         count *= Aoesectsz;
  523 
  524         if(r->dlen < count)
  525                 count = r->dlen & ~0x1ff;
  526 
  527         if(waserror()){
  528                 if(strcmp(up->errstr, Echange) == 0 ||
  529                     strcmp(up->errstr, Enotup) == 0)
  530                         unit->sectors = 0;
  531                 nexterror();
  532         }
  533         r->rlen = rio(c->c, r->data, count, Aoesectsz * lba);
  534         poperror();
  535         r->status = SDok;
  536         return SDok;
  537 }
  538 
  539 static char *smarttab[] = {
  540         "unset",
  541         "error",
  542         "threshold exceeded",
  543         "normal"
  544 };
  545 
  546 static char *
  547 pflag(char *s, char *e, uchar f)
  548 {
  549         uchar i, m;
  550 
  551         for(i = 0; i < 8; i++){
  552                 m = 1 << i;
  553                 if(f & m)
  554                         s = seprint(s, e, "%s ", flagname[i]);
  555         }
  556         return seprint(s, e, "\n");
  557 }
  558 
  559 static int
  560 aoerctl(SDunit *u, char *p, int l)
  561 {
  562         Ctlr *c;
  563         char *e, *op;
  564 
  565         if((c = u->dev->ctlr) == nil)
  566                 return 0;
  567         e = p+l;
  568         op = p;
  569 
  570         p = seprint(p, e, "model\t%s\n", c->model);
  571         p = seprint(p, e, "serial\t%s\n", c->serial);
  572         p = seprint(p, e, "firm %s\n", c->firmware);
  573         if(c->smartrs == 0xff)
  574                 p = seprint(p, e, "smart\tenable error\n");
  575         else if(c->smartrs == 0)
  576                 p = seprint(p, e, "smart\tdisabled\n");
  577         else
  578                 p = seprint(p, e, "smart\t%s\n", smarttab[c->smart]);
  579         p = seprint(p, e, "flag ");
  580         p = pflag(p, e, c->feat);
  581         p = seprint(p, e, "geometry %llud %d\n", c->sectors, Aoesectsz);
  582         return p-op;
  583 }
  584 
  585 static int
  586 aoewctl(SDunit *, Cmdbuf *cmd)
  587 {
  588         cmderror(cmd, Ebadarg);
  589         return 0;
  590 }
  591 
  592 static SDev*
  593 aoeprobew(DevConf *c)
  594 {
  595         char *p;
  596 
  597         p = strchr(c->type, '/');
  598         if(p == nil || strlen(p) > Maxpath - 11)
  599                 error(Ebadarg);
  600         if(p[1] == '#')
  601                 p++;                    /* hack */
  602         if(ctlrlookup(p))
  603                 error(Einuse);
  604         return aoeprobe(p, 0);
  605 }
  606 
  607 static void
  608 aoeclear(SDev *s)
  609 {
  610         delctlr((Ctlr *)s->ctlr);
  611 }
  612 
  613 static char*
  614 aoertopctl(SDev *s, char *p, char *e)
  615 {
  616         Ctlr *c;
  617 
  618         c = s->ctlr;
  619         return seprint(p, e, "%s aoe %s\n", s->name, c->path);
  620 }
  621 
  622 static int
  623 aoewtopctl(SDev *, Cmdbuf *cmd)
  624 {
  625         switch(cmd->nf){
  626         default:
  627                 cmderror(cmd, Ebadarg);
  628         }
  629         return 0;
  630 }
  631 
  632 SDifc sdaoeifc = {
  633         "aoe",
  634 
  635         aoepnp,
  636         nil,            /* legacy */
  637         nil,            /* enable */
  638         nil,            /* disable */
  639 
  640         aoeverify,
  641         aoeonline,
  642         aoerio,
  643         aoerctl,
  644         aoewctl,
  645 
  646         scsibio,
  647         aoeprobew,      /* probe */
  648         aoeclear,       /* clear */
  649         aoertopctl,
  650         aoewtopctl,
  651 };

Cache object: 4ca91c12d72292aaf091d9d0894053da


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.