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/pc/sdmv50xx.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  * Marvell 88SX[56]0[48][01] fileserver Serial ATA (SATA) driver
    3  *
    4  * See MV-S101357-00 Rev B Marvell PCI/PCI-X to 8-Port/4-Port
    5  * SATA Host Controller, ATA-5 ANSI NCITS 340-2000.
    6  *
    7  * This is a heavily-modified version (by Coraid) of a heavily-modified
    8  * version (from The Labs) of a driver written by Coraid, Inc.
    9  * The original copyright notice appears at the end of this file.
   10  */
   11 
   12 #include "u.h"
   13 #include "../port/lib.h"
   14 #include "mem.h"
   15 #include "dat.h"
   16 #include "fns.h"
   17 #include "io.h"
   18 #include "../port/error.h"
   19 
   20 #include "../port/sd.h"
   21 
   22 #define dprint if(!0){}else iprint
   23 #define idprint if(!0){}else iprint
   24 #define ioprint if(!0){}else iprint
   25 
   26 enum {
   27         NCtlr           = 4,
   28         NCtlrdrv        = 8,
   29         NDrive          = NCtlr*NCtlrdrv,
   30 
   31         Read            = 0,
   32         Write,
   33 
   34         Coraiddebug     = 0,
   35 };
   36 
   37 enum {
   38         SrbRing = 32,
   39 
   40         /* Addresses of ATA register */
   41         ARcmd           = 027,
   42         ARdev           = 026,
   43         ARerr           = 021,
   44         ARfea           = 021,
   45         ARlba2          = 025,
   46         ARlba1          = 024,
   47         ARlba0          = 023,
   48         ARseccnt        = 022,
   49         ARstat          = 027,
   50 
   51         ATAerr          = (1<<0),
   52         ATAdrq          = (1<<3),
   53         ATAdf           = (1<<5),
   54         ATAdrdy         = (1<<6),
   55         ATAbusy         = (1<<7),
   56         ATAabort        = (1<<2),
   57         ATAobs          = (1<<1 | 1<<2 | 1<<4),
   58         ATAeIEN         = (1<<1),
   59         ATAsrst         = (1<<2),
   60         ATAhob          = (1<<7),
   61         ATAbad          = (ATAbusy|ATAdf|ATAdrq|ATAerr),
   62 
   63         SFdone          = (1<<0),
   64         SFerror         = (1<<1),
   65 
   66         SRBident        = 0,
   67         SRBread,
   68         SRBwrite,
   69         SRBsmart,
   70 
   71         SRBnodata = 0,
   72         SRBdatain,
   73         SRBdataout,
   74 
   75         RQread          = 1,            /* data coming IN from device */
   76 
   77         PRDeot          = (1<<15),
   78 
   79         /* EDMA interrupt error cause register */
   80 
   81         ePrtDataErr     = (1<<0),
   82         ePrtPRDErr      = (1<<1),
   83         eDevErr         = (1<<2),
   84         eDevDis         = (1<<3),
   85         eDevCon         = (1<<4),
   86         eOverrun        = (1<<5),
   87         eUnderrun       = (1<<6),
   88         eSelfDis        = (1<<8),
   89         ePrtCRQBErr     = (1<<9),
   90         ePrtCRPBErr     = (1<<10),
   91         ePrtIntErr      = (1<<11),
   92         eIORdyErr       = (1<<12),
   93 
   94         /* flags for sata 2 version */
   95         eSelfDis2       = (1<<7),
   96         SerrInt         = (1<<5),
   97 
   98         /* EDMA Command Register */
   99 
  100         eEnEDMA = (1<<0),
  101         eDsEDMA         = (1<<1),
  102         eAtaRst         = (1<<2),
  103 
  104         /* Interrupt mask for errors we care about */
  105         IEM             = (eDevDis | eDevCon | eSelfDis),
  106         IEM2            = (eDevDis | eDevCon | eSelfDis2),
  107 
  108         /* drive states */
  109         Dnull           = 0,
  110         Dnew,
  111         Dready,
  112         Derror,
  113         Dmissing,
  114         Dreset,
  115         Dlast,
  116 
  117         /* drive flags */
  118         Dext            = (1<<0),       /* use ext commands */
  119         Dpio            = (1<<1),       /* doing pio */
  120         Dwanted         = (1<<2),       /* someone wants an srb entry */
  121         Dedma           = (1<<3),       /* device in edma mode */
  122         Dpiowant        = (1<<4),       /* some wants to use the pio mode */
  123 
  124         /* phyerrata magic crap */
  125         Mpreamp = 0x7e0,
  126         Dpreamp = 0x720,
  127 
  128         REV60X1B2       = 0x7,
  129         REV60X1C0       = 0x9,
  130 
  131 };
  132 
  133 static char* diskstates[Dlast] = {
  134         "null",
  135         "new",
  136         "ready",
  137         "error",
  138         "missing",
  139         "reset",
  140 };
  141 
  142 extern SDifc sdmv50xxifc;
  143 
  144 typedef struct Arb Arb;
  145 typedef struct Bridge Bridge;
  146 typedef struct Chip Chip;
  147 typedef struct Ctlr Ctlr;
  148 typedef struct Drive Drive;
  149 typedef struct Edma Edma;
  150 typedef struct Prd Prd;
  151 typedef struct Rx Rx;
  152 typedef struct Srb Srb;
  153 typedef struct Tx Tx;
  154 
  155 /*
  156  * there are 4 drives per chip.  thus an 8-port
  157  * card has two chips.
  158  */
  159 struct Chip
  160 {
  161         Arb     *arb;
  162         Edma    *edma;
  163 };
  164 
  165 enum {
  166         DMautoneg,
  167         DMsatai,
  168         DMsataii,
  169 };
  170 
  171 struct Drive
  172 {
  173         Lock;
  174 
  175         Ctlr    *ctlr;
  176         SDunit  *unit;
  177         char    name[10];
  178         ulong   magic;
  179 
  180         Bridge  *bridge;
  181         Edma    *edma;
  182         Chip    *chip;
  183         int     chipx;
  184 
  185         int     mediachange;
  186         int     state;
  187         int     flag;
  188         uvlong  sectors;
  189         ulong   pm2;            /* phymode 2 init state */
  190         ulong   intick;         /* check for hung western digital drives. */
  191         int     wait;
  192         int     mode;           /* DMautoneg, satai or sataii. */
  193 
  194         char    serial[20+1];
  195         char    firmware[8+1];
  196         char    model[40+1];
  197 
  198         ushort  info[256];
  199 
  200         Srb     *srb[SrbRing-1];
  201         int     nsrb;
  202         Prd     *prd;
  203         Tx      *tx;
  204         Rx      *rx;
  205 
  206         Srb     *srbhead;
  207         Srb     *srbtail;
  208         int     driveno;        /* ctlr*NCtlrdrv + unit */
  209 };
  210 
  211 struct Ctlr
  212 {
  213         Lock;
  214 
  215         int     irq;
  216         int     tbdf;
  217         int     rid;
  218         ulong   magic;
  219         int     enabled;
  220         int     type;
  221         SDev    *sdev;
  222         Pcidev  *pcidev;
  223 
  224         uchar   *mmio;
  225         ulong   *lmmio;
  226         Chip    chip[2];
  227         int     nchip;
  228         Drive   drive[NCtlrdrv];
  229         int     ndrive;
  230 };
  231 
  232 struct Srb                      /* request buffer */
  233 {
  234         Lock;
  235         Rendez;
  236         Srb     *next;
  237 
  238         Drive   *drive;
  239         uvlong  blockno;
  240         int     count;
  241         int     req;
  242         int     flag;
  243         uchar   *data;
  244 
  245         uchar   cmd;
  246         uchar   lba[6];
  247         uchar   sectors;
  248         int     sta;
  249         int     err;
  250 };
  251 
  252 /*
  253  * Memory-mapped I/O registers in many forms.
  254  */
  255 struct Bridge                   /* memory-mapped per-Drive registers */
  256 {
  257         ulong   status;
  258         ulong   serror;
  259         ulong   sctrl;
  260         ulong   phyctrl;
  261         ulong   phymode3;
  262         ulong   phymode4;
  263         uchar   fill0[0x14];
  264         ulong   phymode1;
  265         ulong   phymode2;
  266         char    fill1[8];
  267         ulong   ctrl;
  268         char    fill2[0x34];
  269         ulong   phymode;
  270         char    fill3[0x88];
  271 };                              /* length must be 0x100 */
  272 
  273 struct Arb                      /* memory-mapped per-Chip registers */
  274 {
  275         ulong   config;         /* satahc configuration register (sata2 only) */
  276         ulong   rqop;           /* request queue out-pointer */
  277         ulong   rqip;           /* response queue in pointer */
  278         ulong   ict;            /* inerrupt caolescing threshold */
  279         ulong   itt;            /* interrupt timer threshold */
  280         ulong   ic;             /* interrupt cause */
  281         ulong   btc;            /* bridges test control */
  282         ulong   bts;            /* bridges test status */
  283         ulong   bpc;            /* bridges pin configuration */
  284         char    fill1[0xdc];
  285         Bridge  bridge[4];
  286 };
  287 
  288 struct Edma                     /* memory-mapped per-Drive DMA-related registers */
  289 {
  290         ulong   config;         /* configuration register */
  291         ulong   timer;
  292         ulong   iec;            /* interrupt error cause */
  293         ulong   iem;            /* interrupt error mask */
  294 
  295         ulong   txbasehi;               /* request queue base address high */
  296         ulong   txi;            /* request queue in pointer */
  297         ulong   txo;            /* request queue out pointer */
  298 
  299         ulong   rxbasehi;               /* response queue base address high */
  300         ulong   rxi;            /* response queue in pointer */
  301         ulong   rxo;            /* response queue out pointer */
  302 
  303         ulong   ctl;            /* command register */
  304         ulong   testctl;                /* test control */
  305         ulong   status;
  306         ulong   iordyto;                /* IORDY timeout */
  307         char    fill[0x18];
  308         ulong   sataconfig;     /* sata 2 */
  309         char    fill[0xac];
  310         ushort  pio;            /* data register */
  311         char    pad0[2];
  312         uchar   err;            /* features and error */
  313         char    pad1[3];
  314         uchar   seccnt;         /* sector count */
  315         char    pad2[3];
  316         uchar   lba0;
  317         char    pad3[3];
  318         uchar   lba1;
  319         char    pad4[3];
  320         uchar   lba2;
  321         char    pad5[3];
  322         uchar   lba3;
  323         char    pad6[3];
  324         uchar   cmdstat;                /* cmd/status */
  325         char    pad7[3];
  326         uchar   altstat;                /* alternate status */
  327         uchar   fill2[0x1df];
  328         Bridge  port;
  329         char    fill3[0x1c00];  /* pad to 0x2000 bytes */
  330 };
  331 
  332 /*
  333  * Memory structures shared with card.
  334  */
  335 struct Prd                      /* physical region descriptor */
  336 {
  337         ulong   pa;             /* byte address of physical memory */
  338         ushort  count;          /* byte count (bit0 must be 0) */
  339         ushort  flag;
  340         ulong   zero;           /* high long of 64 bit address */
  341         ulong   reserved;
  342 };
  343 
  344 struct Tx                               /* command request block */
  345 {
  346         ulong   prdpa;          /* physical region descriptor table structures */
  347         ulong   zero;           /* must be zero (high long of prd address) */
  348         ushort  flag;           /* control flags */
  349         ushort  regs[11];
  350 };
  351 
  352 struct Rx                               /* command response block */
  353 {
  354         ushort  cid;            /* cID of response */
  355         uchar   cEdmaSts;       /* EDMA status */
  356         uchar   cDevSts;                /* status from disk */
  357         ulong   ts;             /* time stamp */
  358 };
  359 
  360 static Drive    *mvsatadrive[NDrive];
  361 static int      nmvsatadrive;
  362 
  363 /*
  364  * Little-endian parsing for drive data.
  365  */
  366 static ushort
  367 lhgets(void *p)
  368 {
  369         uchar *a = p;
  370         return ((ushort) a[1] << 8) | a[0];
  371 }
  372 
  373 static ulong
  374 lhgetl(void *p)
  375 {
  376         uchar *a = p;
  377         return ((ulong) lhgets(a+2) << 16) | lhgets(a);
  378 }
  379 
  380 static uvlong
  381 lhgetv(void *p)
  382 {
  383         uchar *a = p;
  384         return ((uvlong) lhgetl(a+4) << 32) | lhgetl(a);
  385 }
  386 
  387 static void
  388 idmove(char *p, ushort *a, int n)
  389 {
  390         char *op;
  391         int i;
  392 
  393         op = p;
  394         for(i=0; i<n/2; i++){
  395                 *p++ = a[i]>>8;
  396                 *p++ = a[i];
  397         }
  398         while(p>op && *--p == ' ')
  399                 *p = 0;
  400 }
  401 
  402 /*
  403  * Request buffers.
  404  */
  405 struct
  406 {
  407         Lock;
  408         Srb *freechain;
  409         int nalloc;
  410 } srblist;
  411 
  412 static Srb*
  413 allocsrb(void)
  414 {
  415         Srb *p;
  416 
  417         ilock(&srblist);
  418         if((p = srblist.freechain) == nil){
  419                 srblist.nalloc++;
  420                 iunlock(&srblist);
  421                 p = smalloc(sizeof *p);
  422         }else{
  423                 srblist.freechain = p->next;
  424                 iunlock(&srblist);
  425         }
  426         return p;
  427 }
  428 
  429 static void
  430 freesrb(Srb *p)
  431 {
  432         ilock(&srblist);
  433         p->next = srblist.freechain;
  434         srblist.freechain = p;
  435         iunlock(&srblist);
  436 }
  437 
  438 /*
  439  * Wait for a byte to be a particular value.
  440  */
  441 static int
  442 satawait(uchar *p, uchar mask, uchar v, int ms)
  443 {
  444         int i;
  445 
  446         for(i=0; i<ms && (*p & mask) != v; i++)
  447                 microdelay(1000);
  448         return (*p & mask) == v;
  449 }
  450 
  451 /*
  452  * Drive initialization
  453  */
  454 /* unmask in the pci registers err done */
  455 static void
  456 unmask(ulong *mmio, int port, int coal)
  457 {
  458         port &= 7;
  459         if(coal)
  460                 coal = 1;
  461         if (port < 4)
  462                 mmio[0x1d64/4] |= (3 << (((port&3)*2)) | (coal<<8));
  463         else
  464                 mmio[0x1d64/4] |= (3 << (((port&3)*2+9)) | (coal<<17));
  465 }
  466 
  467 static void
  468 mask(ulong *mmio, int port, int coal)
  469 {
  470         port &= 7;
  471         if(coal)
  472                 coal = 1;
  473         if (port < 4)
  474                 mmio[0x1d64/4] &= ~(3 << (((port&3)*2)) | (coal<<8));
  475         else
  476                 mmio[0x1d64/4] &= ~(3 << (((port&3)*2+9)) | (coal<<17));
  477 }
  478 
  479 /* I give up, marvell.  You win. */
  480 static void
  481 phyerrata(Drive *d)
  482 {
  483         ulong n, m;
  484         enum { BadAutoCal = 0xf << 26, };
  485 
  486         if (d->ctlr->type == 1)
  487                 return;
  488         microdelay(200);
  489         n = d->bridge->phymode2;
  490         while ((n & BadAutoCal) == BadAutoCal) {
  491                 dprint("%s: badautocal\n", d->unit->name);
  492                 n &= ~(1<<16);
  493                 n |= (1<<31);
  494                 d->bridge->phymode2 = n;
  495                 microdelay(200);
  496                 d->bridge->phymode2 &= ~((1<<16) | (1<<31));
  497                 microdelay(200);
  498                 n = d->bridge->phymode2;
  499         }
  500         n &= ~(1<<31);
  501         d->bridge->phymode2 = n;
  502         microdelay(200);
  503 
  504         /* abra cadabra!  (random magic) */
  505         m = d->bridge->phymode3;
  506         m &= ~0x7f800000;
  507         m |= 0x2a800000;
  508         d->bridge->phymode3 = m;
  509 
  510         /* fix phy mode 4 */
  511         m = d->bridge->phymode3;
  512         n = d->bridge->phymode4;
  513         n &= ~(1<<1);
  514         n |= 1;
  515         switch(d->ctlr->rid){
  516         case REV60X1B2:
  517         default:
  518                 d->bridge->phymode4 = n;
  519                 d->bridge->phymode3 = m;
  520                 break;
  521         case REV60X1C0:
  522                 d->bridge->phymode4 = n;
  523                 break;
  524         }
  525 
  526         /* revert values of pre-emphasis and signal amps to the saved ones */
  527         n = d->bridge->phymode2;
  528         n &= ~Mpreamp;
  529         n |= d->pm2;
  530         n &= ~(1<<16);
  531         d->bridge->phymode2 = n;
  532 }
  533 
  534 static void
  535 edmacleanout(Drive *d)
  536 {
  537         int i;
  538         Srb *srb;
  539 
  540         for(i=0; i<nelem(d->srb); i++){
  541                 if(srb = d->srb[i]){
  542                         d->srb[i] = nil;
  543                         d->nsrb--;
  544                         srb->flag |= SFerror|SFdone;
  545                         wakeup(srb);
  546                 }
  547         }
  548         while(srb = d->srbhead){
  549                 d->srbhead = srb->next;
  550                 srb->flag |= SFerror|SFdone;
  551                 wakeup(srb);
  552         }
  553 }
  554 
  555 static void
  556 resetdisk(Drive *d)
  557 {
  558         ulong n;
  559 
  560         d->sectors = 0;
  561         d->unit->sectors = 0;
  562         if (d->ctlr->type == 2) {
  563                 /*
  564                  * without bit 8 we can boot without disks, but
  565                  * inserted disks will never appear.  :-X
  566                  */
  567                 n = d->edma->sataconfig;
  568                 n &= 0xff;
  569                 n |= 0x9b1100;
  570                 d->edma->sataconfig = n;
  571                 n = d->edma->sataconfig;        /* flush */
  572                 USED(n);
  573         }
  574         d->edma->ctl = eDsEDMA;
  575         microdelay(1);
  576         d->edma->ctl = eAtaRst;
  577         microdelay(25);
  578         d->edma->ctl = 0;
  579         if (satawait((uchar *)&d->edma->ctl, eEnEDMA, 0, 3*1000) == 0)
  580                 print("%s: eEnEDMA never cleared on reset\n", d->unit->name);
  581         edmacleanout(d);
  582         phyerrata(d);
  583         d->bridge->sctrl = 0x301 | (d->mode << 4);
  584         d->state = Dmissing;
  585 }
  586 
  587 static void
  588 edmainit(Drive *d)
  589 {
  590         int i;
  591 
  592         if(d->tx != nil)
  593                 return;
  594 
  595         d->tx = xspanalloc(32*sizeof(Tx), 1024, 0);
  596         d->rx = xspanalloc(32*sizeof(Rx), 256, 0);
  597         d->prd = xspanalloc(32*sizeof(Prd), 32, 0);
  598         for(i = 0; i < 32; i++)
  599                 d->tx[i].prdpa = PADDR(&d->prd[i]);
  600         coherence();
  601 }
  602 
  603 static int
  604 configdrive(Ctlr *ctlr, Drive *d, SDunit *unit)
  605 {
  606         dprint("%s: configdrive\n", unit->name);
  607         if(d->driveno < 0)
  608                 panic("mv50xx: configdrive: unset driveno\n");
  609         d->unit = unit;
  610         edmainit(d);
  611         d->mode = DMsatai;
  612         if(d->ctlr->type == 1){
  613                 d->edma->iem = IEM;
  614                 d->bridge = &d->chip->arb->bridge[d->chipx];
  615         }else{
  616                 d->edma->iem = IEM2;
  617                 d->bridge = &d->chip->edma[d->chipx].port;
  618                 d->edma->iem = ~(1<<6);
  619                 d->pm2 = Dpreamp;
  620                 if(d->ctlr->lmmio[0x180d8/4] & 1)
  621                         d->pm2 = d->bridge->phymode2 & Mpreamp;
  622         }
  623         resetdisk(d);
  624         unmask(ctlr->lmmio, d->driveno, 0);
  625         delay(100);
  626         if(d->bridge->status){
  627                 dprint("%s: configdrive: found drive %lx\n", unit->name, d->bridge->status);
  628                 return 0;
  629         }
  630         return -1;
  631 }
  632 
  633 static int
  634 enabledrive(Drive *d)
  635 {
  636         Edma *edma;
  637 
  638         dprint("%s: enabledrive..", d->unit->name);
  639 
  640         if((d->bridge->status & 0xf) != 3){
  641                 dprint("%s: not present\n", d->unit->name);
  642                 d->state = Dmissing;
  643                 return -1;
  644         }
  645         edma = d->edma;
  646         if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0){
  647                 dprint("%s: busy timeout\n", d->unit->name);
  648                 d->state = Dmissing;
  649                 return -1;
  650         }
  651         edma->iec = 0;
  652         d->chip->arb->ic &= ~(0x101 << d->chipx);
  653         edma->config = 0x51f;
  654         if (d->ctlr->type == 2)
  655                 edma->config |= 7<<11;
  656         edma->txi = PADDR(d->tx);
  657         edma->txo = (ulong)d->tx & 0x3e0;
  658         edma->rxi = (ulong)d->rx & 0xf8;
  659         edma->rxo = PADDR(d->rx);
  660         edma->ctl |= 1;         /* enable dma */
  661 
  662         if(d->bridge->status = 0x113){
  663                 dprint("%s: new\n", d->unit->name);
  664                 d->state = Dnew;
  665         }else
  666                 print("%s: status not forced (should be okay)\n", d->unit->name);
  667         return 0;
  668 }
  669 
  670 static void
  671 disabledrive(Drive *d)
  672 {
  673         int i;
  674         ulong *r;
  675 
  676         dprint("%s: disabledrive\n", d->unit->name);
  677 
  678         if(d->tx == nil)        /* never enabled */
  679                 return;
  680 
  681         d->edma->ctl = 0;
  682         d->edma->iem = 0;
  683 
  684         r = (ulong*)(d->ctlr->mmio + 0x1d64);
  685         i = d->chipx;
  686         if(d->chipx < 4)
  687                 *r &= ~(3 << (i*2));
  688         else
  689                 *r |= ~(3 << (i*2+9));
  690 }
  691 
  692 static int
  693 setudmamode(Drive *d, uchar mode)
  694 {
  695         Edma *edma;
  696 
  697         dprint("%s: setudmamode %d\n", d->unit->name, mode);
  698 
  699         edma = d->edma;
  700         if (edma == nil) {
  701                 iprint("setudamode(m%d): zero d->edma\m", d->driveno);
  702                 return 0;
  703         }
  704         if(satawait(&edma->cmdstat, ~ATAobs, ATAdrdy, 9*1000) == 0){
  705                 iprint("%s: cmdstat 0x%.2ux ready timeout\n", d->unit->name, edma->cmdstat);
  706                 return 0;
  707         }
  708         edma->altstat = ATAeIEN;
  709         edma->err = 3;
  710         edma->seccnt = 0x40 | mode;
  711         edma->cmdstat = 0xef;
  712         microdelay(1);
  713         if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0){
  714                 iprint("%s: cmdstat 0x%.2ux busy timeout\n", d->unit->name, edma->cmdstat);
  715                 return 0;
  716         }
  717         return 1;
  718 }
  719 
  720 static int
  721 identifydrive(Drive *d)
  722 {
  723         int i;
  724         ushort *id;
  725         Edma *edma;
  726         SDunit *unit;
  727 
  728         dprint("%s: identifydrive\n", d->unit->name);
  729 
  730         if(setudmamode(d, 5) == 0)      /* do all SATA support 5? */
  731                 goto Error;
  732 
  733         id = d->info;
  734         memset(d->info, 0, sizeof d->info);
  735         edma = d->edma;
  736         if(satawait(&edma->cmdstat, ~ATAobs, ATAdrdy, 5*1000) == 0)
  737                 goto Error;
  738 
  739         edma->altstat = ATAeIEN;        /* no interrupts */
  740         edma->cmdstat = 0xec;
  741         microdelay(1);
  742         if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0)
  743                 goto Error;
  744         for(i = 0; i < 256; i++)
  745                 id[i] = edma->pio;
  746         if(edma->cmdstat & ATAbad)
  747                 goto Error;
  748         i = lhgets(id+83) | lhgets(id+86);
  749         if(i & (1<<10)){
  750                 d->flag |= Dext;
  751                 d->sectors = lhgetv(id+100);
  752         }else{
  753                 d->flag &= ~Dext;
  754                 d->sectors = lhgetl(id+60);
  755         }
  756         idmove(d->serial, id+10, 20);
  757         idmove(d->firmware, id+23, 8);
  758         idmove(d->model, id+27, 40);
  759 
  760         unit = d->unit;
  761         memset(unit->inquiry, 0, sizeof unit->inquiry);
  762         unit->inquiry[2] = 2;
  763         unit->inquiry[3] = 2;
  764         unit->inquiry[4] = sizeof(unit->inquiry)-4;
  765         idmove((char*)unit->inquiry+8, id+27, 40);
  766 
  767         if(enabledrive(d) == 0) {
  768                 d->state = Dready;
  769                 d->mediachange = 1;
  770                 idprint("%s: LLBA %lld sectors\n", d->unit->name, d->sectors);
  771         } else
  772                 d->state = Derror;
  773         if(d->state == Dready)
  774                 return 0;
  775         return -1;
  776 Error:
  777         dprint("error...");
  778         d->state = Derror;
  779         return -1;
  780 }
  781 
  782 /* p. 163:
  783         M       recovered error
  784         P       protocol error
  785         N       PhyRdy change
  786         W       CommWake
  787         B       8-to-10 encoding error
  788         D       disparity error
  789         C       crc error
  790         H       handshake error
  791         S       link sequence error
  792         T       transport state transition error
  793         F       unrecognized fis type
  794         X       device changed
  795 */
  796 
  797 static char stab[] = {
  798 [1]     'M',
  799 [10]    'P',
  800 [16]    'N',
  801 [18]    'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
  802 };
  803 static ulong sbad = (7<<20)|(3<<23);
  804 
  805 static void
  806 serrdecode(ulong r, char *s, char *e)
  807 {
  808         int i;
  809 
  810         e -= 3;
  811         for(i = 0; i < nelem(stab) && s < e; i++){
  812                 if((r&(1<<i)) && stab[i]){
  813                         *s++ = stab[i];
  814                         if(sbad&(1<<i))
  815                                 *s++ = '*';
  816                 }
  817         }
  818         *s = 0;
  819 }
  820 
  821 char *iectab[] = {
  822         "ePrtDataErr",
  823         "ePrtPRDErr",
  824         "eDevErr",
  825         "eDevDis",
  826         "eDevCon",
  827         "SerrInt",
  828         "eUnderrun",
  829         "eSelfDis2",
  830         "eSelfDis",
  831         "ePrtCRQBErr",
  832         "ePrtCRPBErr",
  833         "ePrtIntErr",
  834         "eIORdyErr",
  835 };
  836 
  837 static char*
  838 iecdecode(ulong cause)
  839 {
  840         int i;
  841 
  842         for(i = 0; i < nelem(iectab); i++)
  843                 if(cause&(1<<i))
  844                         return iectab[i];
  845         return "";
  846 }
  847 
  848 enum{
  849         Cerror = ePrtDataErr|ePrtPRDErr|eDevErr|eSelfDis2|ePrtCRPBErr|ePrtIntErr,
  850 };
  851 
  852 static void
  853 updatedrive(Drive *d)
  854 {
  855         int x;
  856         ulong cause;
  857         Edma *edma;
  858         char buf[32+4+1];
  859 
  860         edma = d->edma;
  861         if((edma->ctl&eEnEDMA) == 0){
  862                 /* FEr SATA#4 40xx */
  863                 x = d->edma->cmdstat;
  864                 USED(x);
  865         }
  866         cause = edma->iec;
  867         if(cause == 0)
  868                 return;
  869         dprint("%s: cause %08ulx [%s]\n", d->unit->name, cause, iecdecode(cause));
  870         if(cause & eDevCon)
  871                 d->state = Dnew;
  872         if(cause&eDevDis && d->state == Dready)
  873                 iprint("%s: pulled: st=%08ulx\n", d->unit->name, cause);
  874         switch(d->ctlr->type){
  875         case 1:
  876                 if(cause&eSelfDis)
  877                         d->state = Derror;
  878                 break;
  879         case 2:
  880                 if(cause&Cerror)
  881                         d->state = Derror;
  882                 if(cause&SerrInt){
  883                         serrdecode(d->bridge->serror, buf, buf+sizeof buf);
  884                         dprint("%s: serror %08ulx [%s]\n", d->unit->name, (ulong)d->bridge->serror, buf);
  885                         d->bridge->serror = d->bridge->serror;
  886                 }
  887         }
  888         edma->iec = ~cause;
  889 }
  890 
  891 /*
  892  * Requests
  893  */
  894 static Srb*
  895 srbrw(int req, Drive *d, uchar *data, uint sectors, uvlong lba)
  896 {
  897         int i;
  898         Srb *srb;
  899         static uchar cmd[2][2] = { 0xC8, 0x25, 0xCA, 0x35 };
  900 
  901         srb = allocsrb();
  902         srb->req = req;
  903         srb->drive = d;
  904         srb->blockno = lba;
  905         srb->sectors = sectors;
  906         srb->count = sectors*512;
  907         srb->flag = 0;
  908         srb->data = data;
  909 
  910         for(i=0; i<6; i++)
  911                 srb->lba[i] = lba >> (8*i);
  912         srb->cmd = cmd[srb->req!=SRBread][(d->flag&Dext)!=0];
  913         return srb;
  914 }
  915 
  916 static uintptr
  917 advance(uintptr pa, int shift)
  918 {
  919         int n, mask;
  920 
  921         mask = 0x1F<<shift;
  922         n = (pa & mask) + (1<<shift);
  923         return (pa & ~mask) | (n & mask);
  924 }
  925 
  926 #define CMD(r, v) (((r)<<8) | ((v)&0xFF))
  927 static void
  928 mvsatarequest(ushort *cmd, Srb *srb, int ext)
  929 {
  930         *cmd++ = CMD(ARseccnt, 0);
  931         *cmd++ = CMD(ARseccnt, srb->sectors);
  932         *cmd++ = CMD(ARfea, 0);
  933         if(ext){
  934                 *cmd++ = CMD(ARlba0, srb->lba[3]);
  935                 *cmd++ = CMD(ARlba0, srb->lba[0]);
  936                 *cmd++ = CMD(ARlba1, srb->lba[4]);
  937                 *cmd++ = CMD(ARlba1, srb->lba[1]);
  938                 *cmd++ = CMD(ARlba2, srb->lba[5]);
  939                 *cmd++ = CMD(ARlba2, srb->lba[2]);
  940                 *cmd++ = CMD(ARdev, 0xe0);
  941         }else{
  942                 *cmd++ = CMD(ARlba0, srb->lba[0]);
  943                 *cmd++ = CMD(ARlba1, srb->lba[1]);
  944                 *cmd++ = CMD(ARlba2, srb->lba[2]);
  945                 *cmd++ = CMD(ARdev, srb->lba[3] | 0xe0);
  946         }
  947         *cmd = CMD(ARcmd, srb->cmd) | (1<<15);
  948 }
  949 
  950 static void
  951 startsrb(Drive *d, Srb *srb)
  952 {
  953         int i;
  954         Edma *edma;
  955         Prd *prd;
  956         Tx *tx;
  957 
  958         if(d->nsrb >= nelem(d->srb)){
  959                 srb->next = nil;
  960                 if(d->srbhead)
  961                         d->srbtail->next = srb;
  962                 else
  963                         d->srbhead = srb;
  964                 d->srbtail = srb;
  965                 return;
  966         }
  967 
  968         d->nsrb++;
  969         for(i=0; i<nelem(d->srb); i++)
  970                 if(d->srb[i] == nil)
  971                         break;
  972         if(i == nelem(d->srb))
  973                 panic("sdmv50xx: no free srbs");
  974         d->intick = MACHP(0)->ticks;
  975         d->srb[i] = srb;
  976         edma = d->edma;
  977         tx = (Tx*)KADDR(edma->txi);
  978         tx->flag = (i<<1) | (srb->req == SRBread);
  979         prd = KADDR(tx->prdpa);
  980         prd->pa = PADDR(srb->data);
  981         prd->count = srb->count;
  982         prd->flag = PRDeot;
  983         mvsatarequest(tx->regs, srb, d->flag&Dext);
  984         coherence();
  985         edma->txi = advance(edma->txi, 5);
  986         d->intick = MACHP(0)->ticks;
  987 }
  988 
  989 enum{
  990         Rpidx   = 0x1f<<3,
  991 };
  992 
  993 static void
  994 completesrb(Drive *d)
  995 {
  996         Edma *edma;
  997         Rx *rx;
  998         Srb *srb;
  999 
 1000         edma = d->edma;
 1001         if((edma->ctl & eEnEDMA) == 0)
 1002                 return;
 1003 
 1004         while((edma->rxo&Rpidx) != (edma->rxi&Rpidx)){
 1005                 rx = (Rx*)KADDR(edma->rxo);
 1006                 if(srb = d->srb[rx->cid]){
 1007                         d->srb[rx->cid] = nil;
 1008                         d->nsrb--;
 1009                         if(rx->cDevSts & ATAbad)
 1010                                 srb->flag |= SFerror;
 1011                         if (rx->cEdmaSts)
 1012                                 iprint("cEdmaSts: %02ux\n", rx->cEdmaSts);
 1013                         srb->sta = rx->cDevSts;
 1014                         srb->flag |= SFdone;
 1015                         wakeup(srb);
 1016                 }else
 1017                         iprint("srb missing\n");
 1018                 edma->rxo = advance(edma->rxo, 3);
 1019                 if(srb = d->srbhead){
 1020                         d->srbhead = srb->next;
 1021                         startsrb(d, srb);
 1022                 }
 1023         }
 1024 }
 1025 
 1026 static int
 1027 srbdone(void *v)
 1028 {
 1029         Srb *srb;
 1030 
 1031         srb = v;
 1032         return srb->flag & SFdone;
 1033 }
 1034 
 1035 /*
 1036  * Interrupts
 1037  */
 1038 static void
 1039 mv50interrupt(Ureg*, void *a)
 1040 {
 1041         int i;
 1042         ulong cause;
 1043         Ctlr *ctlr;
 1044         Drive *drive;
 1045 
 1046         ctlr = a;
 1047         ilock(ctlr);
 1048         cause = ctlr->lmmio[0x1d60/4];
 1049 //      dprint("sd%c: mv50interrupt: 0x%lux\n", ctlr->sdev->idno, cause);
 1050         for(i=0; i<ctlr->ndrive; i++)
 1051                 if(cause & (3<<(i*2+i/4))){
 1052                         drive = &ctlr->drive[i];
 1053                         if(drive->edma == 0)
 1054                                 continue;       /* not ready yet. */
 1055                         ilock(drive);
 1056                         updatedrive(drive);
 1057                         while(ctlr->chip[i/4].arb->ic & (0x0101 << (i%4))){
 1058                                 ctlr->chip[i/4].arb->ic = ~(0x101 << (i%4));
 1059                                 completesrb(drive);
 1060                         }
 1061                         iunlock(drive);
 1062                 }
 1063         iunlock(ctlr);
 1064 }
 1065 
 1066 enum{
 1067         Nms             = 256,
 1068         Midwait         = 16*1024/Nms-1,
 1069         Mphywait        = 512/Nms-1,
 1070 };
 1071 
 1072 static void
 1073 westerndigitalhung(Drive *d)
 1074 {
 1075         Edma *e;
 1076 
 1077         e = d->edma;
 1078         if(d->srb
 1079         && TK2MS(MACHP(0)->ticks-d->intick) > 5*1000
 1080         && (e->rxo&Rpidx) == (e->rxi&Rpidx)){
 1081                 dprint("westerndigital drive hung; resetting\n");
 1082                 d->state = Dreset;
 1083         }
 1084 }
 1085 
 1086 static void
 1087 checkdrive(Drive *d, int i)
 1088 {
 1089         static ulong s, olds[NCtlr*NCtlrdrv];
 1090         char *name;
 1091 
 1092         ilock(d);
 1093         name = d->unit->name;
 1094         s = d->bridge->status;
 1095         if(s != olds[i]){
 1096                 dprint("%s: status: %08lx -> %08lx: %s\n", name, olds[i], s, diskstates[d->state]);
 1097                 olds[i] = s;
 1098         }
 1099         /* westerndigitalhung(d); */
 1100         switch(d->state){
 1101         case Dnew:
 1102         case Dmissing:
 1103                 switch(s){
 1104                 case 0x000:
 1105                         break;
 1106                 default:
 1107                         dprint("%s: unknown state %8lx\n", name, s);
 1108                 case 0x100:
 1109                         if(++d->wait&Mphywait)
 1110                                 break;
 1111                 reset:  d->mode ^= 1;
 1112                         dprint("%s: reset; new mode %d\n", name, d->mode);
 1113                         resetdisk(d);
 1114                         break;
 1115                 case 0x123:
 1116                 case 0x113:
 1117                         s = d->edma->cmdstat;
 1118                         if(s == 0x7f || (s&~ATAobs) != ATAdrdy){
 1119                                 if((++d->wait&Midwait) == 0)
 1120                                         goto reset;
 1121                         }else if(identifydrive(d) == -1)
 1122                                 goto reset;
 1123                 }
 1124                 break;
 1125         case Dready:
 1126                 if(s != 0)
 1127                         break;
 1128                 iprint("%s: pulled: st=%08ulx\n", name, s);     /* never happens */
 1129         case Dreset:
 1130         case Derror:
 1131                 dprint("%s reset: mode %d\n", name, d->mode);
 1132                 resetdisk(d);
 1133                 break;
 1134         }
 1135         iunlock(d);
 1136 }
 1137 
 1138 static void
 1139 satakproc(void*)
 1140 {
 1141         int i;
 1142 
 1143         while(waserror())
 1144                 ;
 1145 
 1146         for(;;){
 1147                 tsleep(&up->sleep, return0, 0, Nms);
 1148                 for(i = 0; i < nmvsatadrive; i++)
 1149                         checkdrive(mvsatadrive[i], i);
 1150         }
 1151 }
 1152 
 1153 /*
 1154  * Device discovery
 1155  */
 1156 static SDev*
 1157 mv50pnp(void)
 1158 {
 1159         int i, nunit;
 1160         uchar *base;
 1161         ulong io, n, *mem;
 1162         Ctlr *ctlr;
 1163         Pcidev *p;
 1164         SDev *head, *tail, *sdev;
 1165         Drive *d;
 1166         static int ctlrno, done;
 1167 
 1168         dprint("mv50pnp\n");
 1169         if(done++)
 1170                 return nil;
 1171 
 1172         p = nil;
 1173         head = nil;
 1174         tail = nil;
 1175         while((p = pcimatch(p, 0x11ab, 0)) != nil){
 1176                 switch(p->did){
 1177                 case 0x5040:
 1178                 case 0x5041:
 1179                 case 0x5080:
 1180                 case 0x5081:
 1181                 case 0x6041:
 1182                 case 0x6081:
 1183                         break;
 1184                 default:
 1185                         print("mv50pnp: unknown did %ux ignored\n", (ushort)p->did);
 1186                         continue;
 1187                 }
 1188                 if (ctlrno >= NCtlr) {
 1189                         print("mv50pnp: too many controllers\n");
 1190                         break;
 1191                 }
 1192                 nunit = (p->did&0xf0) >> 4;
 1193                 print("Marvell 88SX%ux: %d SATA-%s ports with%s flash\n",
 1194                         (ushort)p->did, nunit,
 1195                         ((p->did&0xf000)==0x6000? "II": "I"),
 1196                         (p->did&1? "": "out"));
 1197                 if((sdev = malloc(sizeof(SDev))) == nil)
 1198                         continue;
 1199                 if((ctlr = malloc(sizeof(Ctlr))) == nil){
 1200                         free(sdev);
 1201                         continue;
 1202                 }
 1203                 memset(sdev, 0, sizeof *sdev);
 1204                 memset(ctlr, 0, sizeof *ctlr);
 1205 
 1206                 io = p->mem[0].bar & ~0x0F;
 1207                 mem = (ulong*)vmap(io, p->mem[0].size);
 1208                 if(mem == 0){
 1209                         print("sdmv50xx: address 0x%luX in use\n", io);
 1210                         free(sdev);
 1211                         free(ctlr);
 1212                         continue;
 1213                 }
 1214                 ctlr->rid = p->rid;
 1215 
 1216                 /* avert thine eyes!  (what does this do?) */
 1217                 mem[0x104f0/4] = 0;
 1218                 ctlr->type = (p->did >> 12) & 3;
 1219                 if(ctlr->type == 1){
 1220                         n = mem[0xc00/4];
 1221                         n &= ~(3<<4);
 1222                         mem[0xc00/4] = n;
 1223                 }
 1224 
 1225                 sdev->ifc = &sdmv50xxifc;
 1226                 sdev->ctlr = ctlr;
 1227                 sdev->nunit = nunit;
 1228                 sdev->idno = 'E';
 1229                 ctlr->sdev = sdev;
 1230                 ctlr->irq = p->intl;
 1231                 ctlr->tbdf = p->tbdf;
 1232                 ctlr->pcidev = p;
 1233                 ctlr->lmmio = mem;
 1234                 ctlr->mmio = (uchar*)mem;
 1235                 ctlr->nchip = (nunit+3)/4;
 1236                 ctlr->ndrive = nunit;
 1237                 ctlr->enabled = 0;
 1238                 for(i = 0; i < ctlr->nchip; i++){
 1239                         base = ctlr->mmio+0x20000+0x10000*i;
 1240                         ctlr->chip[i].arb = (Arb*)base;
 1241                         ctlr->chip[i].edma = (Edma*)(base + 0x2000);
 1242                 }
 1243                 for (i = 0; i < nunit; i++) {
 1244                         d = &ctlr->drive[i];
 1245                         d->sectors = 0;
 1246                         d->ctlr = ctlr;
 1247                         d->driveno = ctlrno*NCtlrdrv + i;
 1248                         d->chipx = i%4;
 1249                         d->chip = &ctlr->chip[i/4];
 1250                         d->edma = &d->chip->edma[d->chipx];
 1251                         mvsatadrive[d->driveno] = d;
 1252                 }
 1253                 nmvsatadrive += nunit;
 1254                 ctlrno++;
 1255                 if(head)
 1256                         tail->next = sdev;
 1257                 else
 1258                         head = sdev;
 1259                 tail = sdev;
 1260         }
 1261         return head;
 1262 }
 1263 
 1264 /*
 1265  * Enable the controller.  Each disk has its own interrupt mask,
 1266  * and those get enabled as the disks are brought online.
 1267  */
 1268 static int
 1269 mv50enable(SDev *sdev)
 1270 {
 1271         char name[32];
 1272         Ctlr *ctlr;
 1273 
 1274         dprint("sd%c: enable\n", sdev->idno);
 1275 
 1276         ctlr = sdev->ctlr;
 1277         if (ctlr->enabled)
 1278                 return 1;
 1279         snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
 1280         intrenable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
 1281         ctlr->enabled = 1;
 1282         return 1;
 1283 }
 1284 
 1285 /*
 1286  * Disable the controller.
 1287  */
 1288 static int
 1289 mv50disable(SDev *sdev)
 1290 {
 1291         char name[32];
 1292         int i;
 1293         Ctlr *ctlr;
 1294         Drive *drive;
 1295 
 1296         dprint("sd%c: disable\n", sdev->idno);
 1297 
 1298         ctlr = sdev->ctlr;
 1299         ilock(ctlr);
 1300         for(i=0; i<ctlr->sdev->nunit; i++){
 1301                 drive = &ctlr->drive[i];
 1302                 ilock(drive);
 1303                 disabledrive(drive);
 1304                 iunlock(drive);
 1305         }
 1306         iunlock(ctlr);
 1307         snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
 1308         intrdisable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
 1309         return 0;
 1310 }
 1311 
 1312 /*
 1313  * Clean up all disk structures.  Already disabled.
 1314  * Could keep count of number of allocated controllers
 1315  * and free the srblist when it drops to zero.
 1316  */
 1317 static void
 1318 mv50clear(SDev *sdev)
 1319 {
 1320         int i;
 1321         Ctlr *ctlr;
 1322         Drive *d;
 1323 
 1324         dprint("sd%c: clear\n", sdev->idno);
 1325 
 1326         ctlr = sdev->ctlr;
 1327         for(i=0; i<ctlr->ndrive; i++){
 1328                 d = &ctlr->drive[i];
 1329                 free(d->tx);
 1330                 free(d->rx);
 1331                 free(d->prd);
 1332         }
 1333         free(ctlr);
 1334 }
 1335 
 1336 /*
 1337  * Check that there is a disk or at least a hot swap bay in the drive.
 1338  */
 1339 static int
 1340 mv50verify(SDunit *unit)
 1341 {
 1342         Ctlr *ctlr;
 1343         Drive *drive;
 1344         int i;
 1345 
 1346         dprint("%s: verify\n", unit->name);
 1347         ctlr = unit->dev->ctlr;
 1348         drive = &ctlr->drive[unit->subno];
 1349         ilock(ctlr);
 1350         ilock(drive);
 1351         i = configdrive(ctlr, drive, unit);
 1352         iunlock(drive);
 1353         iunlock(ctlr);
 1354 
 1355         /*
 1356          * If ctlr->type == 1, then the drives spin up whenever
 1357          * the controller feels like it; if ctlr->type != 1, then
 1358          * they spin up as a result of configdrive.
 1359          *
 1360          * If there is a drive in the slot, give it 1.5s to spin up
 1361          * before returning.  There is a noticeable drag on the
 1362          * power supply when spinning up fifteen drives
 1363          * all at once (like in the Coraid enclosures).
 1364          */
 1365         if(ctlr->type != 1 && i == 0){
 1366                 if(!waserror()){
 1367                         tsleep(&up->sleep, return0, 0, 1500);
 1368                         poperror();
 1369                 }
 1370         }
 1371         return 1;
 1372 }
 1373 
 1374 /*
 1375  * Check whether the disk is online.
 1376  */
 1377 static int
 1378 mv50online(SDunit *unit)
 1379 {
 1380         Ctlr *ctlr;
 1381         Drive *d;
 1382         int r, s0;
 1383         static int once;
 1384 
 1385         if(once++ == 0)
 1386                 kproc("mvsata", satakproc, 0);
 1387 
 1388         ctlr = unit->dev->ctlr;
 1389         d = &ctlr->drive[unit->subno];
 1390         r = 0;
 1391         ilock(d);
 1392         s0 = d->state;
 1393         USED(s0);
 1394         if(d->state == Dnew)
 1395                 identifydrive(d);
 1396         if(d->mediachange){
 1397                 idprint("%s: online: %s -> %s\n", unit->name, diskstates[s0], diskstates[d->state]);
 1398                 r = 2;
 1399                 unit->sectors = d->sectors;
 1400                 unit->secsize = 512;
 1401                 d->mediachange = 0;
 1402         } else if(d->state == Dready)
 1403                 r = 1;
 1404         iunlock(d);
 1405         return r;
 1406 }
 1407 
 1408 /*
 1409  * Register dumps
 1410  */
 1411 typedef struct Regs Regs;
 1412 struct Regs
 1413 {
 1414         ulong offset;
 1415         char *name;
 1416 };
 1417 
 1418 static Regs regsctlr[] =
 1419 {
 1420         0x0C28, "pci serr# mask",
 1421         0x1D40, "pci err addr low",
 1422         0x1D44, "pci err addr hi",
 1423         0x1D48, "pci err attr",
 1424         0x1D50, "pci err cmd",
 1425         0x1D58, "pci intr cause",
 1426         0x1D5C, "pci mask cause",
 1427         0x1D60, "device micr",
 1428         0x1D64, "device mimr",
 1429 };
 1430 
 1431 static Regs regsarb[] =
 1432 {
 1433         0x0004, "arb rqop",
 1434         0x0008, "arb rqip",
 1435         0x000C, "arb ict",
 1436         0x0010, "arb itt",
 1437         0x0014, "arb ic",
 1438         0x0018, "arb btc",
 1439         0x001C, "arb bts",
 1440         0x0020, "arb bpc",
 1441 };
 1442 
 1443 static Regs regsbridge[] =
 1444 {
 1445         0x0000, "bridge status",
 1446         0x0004, "bridge serror",
 1447         0x0008, "bridge sctrl",
 1448         0x000C, "bridge phyctrl",
 1449         0x003C, "bridge ctrl",
 1450         0x0074, "bridge phymode",
 1451 };
 1452 
 1453 static Regs regsedma[] =
 1454 {
 1455         0x0000, "edma config",
 1456         0x0004, "edma timer",
 1457         0x0008, "edma iec",
 1458         0x000C, "edma iem",
 1459         0x0010, "edma txbasehi",
 1460         0x0014, "edma txi",
 1461         0x0018, "edma txo",
 1462         0x001C, "edma rxbasehi",
 1463         0x0020, "edma rxi",
 1464         0x0024, "edma rxo",
 1465         0x0028, "edma c",
 1466         0x002C, "edma tc",
 1467         0x0030, "edma status",
 1468         0x0034, "edma iordyto",
 1469 /*      0x0100, "edma pio",
 1470         0x0104, "edma err",
 1471         0x0108, "edma sectors",
 1472         0x010C, "edma lba0",
 1473         0x0110, "edma lba1",
 1474         0x0114, "edma lba2",
 1475         0x0118, "edma lba3",
 1476         0x011C, "edma cmdstat",
 1477         0x0120, "edma altstat",
 1478 */
 1479 };
 1480 
 1481 static char*
 1482 rdregs(char *p, char *e, void *base, Regs *r, int n, char *prefix)
 1483 {
 1484         int i;
 1485 
 1486         for(i = 0; i < n; i++)
 1487                 p = seprint(p, e, "%s%s%-19s %.8lux\n",
 1488                         prefix? prefix: "", prefix? ": ": "",
 1489                         r[i].name, *(ulong *)((uchar*)base + r[i].offset));
 1490         return p;
 1491 }
 1492 
 1493 static char*
 1494 rdinfo(char *p, char *e, ushort *info)
 1495 {
 1496         int i;
 1497 
 1498         p = seprint(p, e, "info");
 1499         for(i = 0; i < 256; i++)
 1500                 p = seprint(p, e, "%s%.4ux%s", i%8 == 0? "\t": "", info[i],
 1501                         i%8 == 7? "\n": "");
 1502         return p;
 1503 }
 1504 
 1505 static int
 1506 mv50rctl(SDunit *unit, char *p, int l)
 1507 {
 1508         char *e, *op;
 1509         Ctlr *ctlr;
 1510         Drive *drive;
 1511 
 1512         if((ctlr = unit->dev->ctlr) == nil)
 1513                 return 0;
 1514         drive = &ctlr->drive[unit->subno];
 1515 
 1516         e = p+l;
 1517         op = p;
 1518         if(drive->state == Dready){
 1519                 p = seprint(p, e, "model    %s\n", drive->model);
 1520                 p = seprint(p, e, "serial   %s\n", drive->serial);
 1521                 p = seprint(p, e, "firmware %s\n", drive->firmware);
 1522         }else
 1523                 p = seprint(p, e, "no disk present\n");
 1524         p = seprint(p, e, "geometry %llud 512\n", drive->sectors);
 1525         p = rdinfo(p, e, drive->info);
 1526 
 1527         p = rdregs(p, e, drive->chip->arb, regsarb, nelem(regsarb), nil);
 1528         p = rdregs(p, e, drive->bridge, regsbridge, nelem(regsbridge), nil);
 1529         p = rdregs(p, e, drive->edma, regsedma, nelem(regsedma), nil);
 1530 
 1531         return p-op;
 1532 }
 1533 
 1534 static int
 1535 mv50wctl(SDunit *unit, Cmdbuf *cb)
 1536 {
 1537         Ctlr *ctlr;
 1538         Drive *drive;
 1539 
 1540         USED(unit);
 1541         if(strcmp(cb->f[0], "reset") == 0){
 1542                 ctlr = unit->dev->ctlr;
 1543                 drive = &ctlr->drive[unit->subno];
 1544                 ilock(drive);
 1545                 drive->state = Dreset;
 1546                 iunlock(drive);
 1547                 return 0;
 1548         }
 1549         cmderror(cb, Ebadctl);
 1550         return -1;
 1551 }
 1552 
 1553 /*
 1554  * sd(3): ``Reading /dev/sdctl yields information about each controller,
 1555  * one line per controller.''
 1556  */
 1557 static char*
 1558 mv50rtopctl(SDev *sdev, char *p, char *e)
 1559 {
 1560         char name[10];
 1561         Ctlr *ctlr;
 1562 
 1563         ctlr = sdev->ctlr;
 1564         if(ctlr == nil)
 1565                 return p;
 1566 
 1567         snprint(name, sizeof name, "sd%c", sdev->idno);
 1568         p = rdregs(p, e, ctlr->mmio, regsctlr, nelem(regsctlr), name);
 1569         if (Coraiddebug) {
 1570                 /* info for first disk.  BUG: this shouldn't be here. */
 1571                 p = rdregs(p, e, ctlr->chip[0].arb,
 1572                         regsarb, nelem(regsarb), name);
 1573                 p = rdregs(p, e, &ctlr->chip[0].arb->bridge[0],
 1574                         regsbridge, nelem(regsbridge), name);
 1575                 p = rdregs(p, e, &ctlr->chip[0].edma[0],
 1576                         regsedma, nelem(regsedma), name);
 1577         }
 1578         return p;
 1579 }
 1580 
 1581 static int
 1582 waitready(Drive *d)
 1583 {
 1584         ulong s, i;
 1585 
 1586         for(i = 0; i < 120; i++){
 1587                 ilock(d);
 1588                 s = d->bridge->status;
 1589                 iunlock(d);
 1590                 if(s == 0)
 1591                         return SDeio;
 1592                 if (d->state == Dready)
 1593                         return SDok;
 1594                 if ((i+1)%60 == 0){
 1595                         ilock(d);
 1596                         resetdisk(d);
 1597                         iunlock(d);
 1598                 }
 1599                 if(!waserror()){
 1600                         tsleep(&up->sleep, return0, 0, 1000);
 1601                         poperror();
 1602                 }
 1603         }
 1604         print("%s: not responding after 2 minutes\n", d->unit->name);
 1605         return SDeio;
 1606 }
 1607 
 1608 static int
 1609 mv50rio(SDreq *r)
 1610 {
 1611         int count, max, n, status, try, flag;
 1612         uchar *cmd, *data;
 1613         uvlong lba;
 1614         Ctlr *ctlr;
 1615         Drive *drive;
 1616         SDunit *unit;
 1617         Srb *srb;
 1618 
 1619         unit = r->unit;
 1620         ctlr = unit->dev->ctlr;
 1621         drive = &ctlr->drive[unit->subno];
 1622         cmd = r->cmd;
 1623 
 1624         if((status = sdfakescsi(r, drive->info, sizeof drive->info)) != SDnostatus){
 1625                 /* XXX check for SDcheck here */
 1626                 r->status = status;
 1627                 return status;
 1628         }
 1629 
 1630         switch(cmd[0]){
 1631         case 0x28:      /* read */
 1632         case 0x2A:      /* write */
 1633                 break;
 1634         default:
 1635                 iprint("%s: bad cmd 0x%.2ux\n", drive->unit->name, cmd[0]);
 1636                 r->status = SDcheck;
 1637                 return SDcheck;
 1638         }
 1639 
 1640         lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5];
 1641         count = (cmd[7]<<8)|cmd[8];
 1642         if(r->data == nil)
 1643                 return SDok;
 1644         if(r->dlen < count*unit->secsize)
 1645                 count = r->dlen/unit->secsize;
 1646 
 1647         try = 0;
 1648 retry:
 1649         if(waitready(drive) != SDok)
 1650                 return SDeio;
 1651         /*
 1652          * Could arrange here to have an Srb always outstanding:
 1653          *
 1654          *      lsrb = nil;
 1655          *      while(count > 0 || lsrb != nil){
 1656          *              srb = nil;
 1657          *              if(count > 0){
 1658          *                      srb = issue next srb;
 1659          *              }
 1660          *              if(lsrb){
 1661          *                      sleep on lsrb and handle it
 1662          *              }
 1663          *      }
 1664          *
 1665          * On the disks I tried, this didn't help.  If anything,
 1666          * it's a little slower.                -rsc
 1667          */
 1668         data = r->data;
 1669         while(count > 0){
 1670                 /*
 1671                  * Max is 128 sectors (64kB) because prd->count is 16 bits.
 1672                  */
 1673                 max = 128;
 1674                 n = count;
 1675                 if(n > max)
 1676                         n = max;
 1677                 if((drive->edma->ctl&eEnEDMA) == 0)
 1678                         goto tryagain;
 1679                 srb = srbrw(cmd[0]==0x28 ? SRBread : SRBwrite, drive, data, n, lba);
 1680                 ilock(drive);
 1681                 startsrb(drive, srb);
 1682                 iunlock(drive);
 1683 
 1684                 /* Don't let user interrupt DMA. */
 1685                 while(waserror())
 1686                         ;
 1687                 sleep(srb, srbdone, srb);
 1688                 poperror();
 1689 
 1690                 flag = srb->flag;
 1691                 freesrb(srb);
 1692                 if(flag == 0){
 1693 tryagain:
 1694                         if(++try == 10){
 1695                                 print("%s: bad disk\n", drive->unit->name);
 1696                                 return SDeio;
 1697                         }
 1698                         dprint("%s: retry\n", drive->unit->name);
 1699                         if(!waserror()){
 1700                                 tsleep(&up->sleep, return0, 0, 1000);
 1701                                 poperror();
 1702                         }
 1703                         goto retry;
 1704                 }
 1705                 if(flag & SFerror){
 1706                         print("%s: i/o error\n", drive->unit->name);
 1707                         return SDeio;
 1708                 }
 1709                 count -= n;
 1710                 lba += n;
 1711                 data += n*unit->secsize;
 1712         }
 1713         r->rlen = data - (uchar*)r->data;
 1714         return SDok;
 1715 }
 1716 
 1717 SDifc sdmv50xxifc = {
 1718         "mv50xx",                       /* name */
 1719 
 1720         mv50pnp,                        /* pnp */
 1721         nil,                            /* legacy */
 1722         mv50enable,                     /* enable */
 1723         mv50disable,                    /* disable */
 1724 
 1725         mv50verify,                     /* verify */
 1726         mv50online,                     /* online */
 1727         mv50rio,                                /* rio */
 1728         mv50rctl,                       /* rctl */
 1729         mv50wctl,                       /* wctl */
 1730 
 1731         scsibio,                        /* bio */
 1732         nil,                            /* probe */
 1733         mv50clear,                      /* clear */
 1734         mv50rtopctl,                    /* rtopctl */
 1735 };
 1736 
 1737 /*
 1738  * The original driver on which this one is based came with the
 1739  * following notice:
 1740  *
 1741  * Copyright 2005
 1742  * Coraid, Inc.
 1743  *
 1744  * This software is provided `as-is,' without any express or implied
 1745  * warranty.  In no event will the author be held liable for any damages
 1746  * arising from the use of this software.
 1747  *
 1748  * Permission is granted to anyone to use this software for any purpose,
 1749  * including commercial applications, and to alter it and redistribute it
 1750  * freely, subject to the following restrictions:
 1751  *
 1752  * 1.  The origin of this software must not be misrepresented; you must
 1753  * not claim that you wrote the original software.  If you use this
 1754  * software in a product, an acknowledgment in the product documentation
 1755  * would be appreciated but is not required.
 1756  *
 1757  * 2.  Altered source versions must be plainly marked as such, and must
 1758  * not be misrepresented as being the original software.
 1759  *
 1760  * 3.  This notice may not be removed or altered from any source
 1761  * distribution.
 1762  */

Cache object: bfbe01960659951d284f7b3cfdeec898


[ 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.