2 * Marvell 88SX[56]0[48][01] Serial ATA (SATA) driver
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.
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.
13 #include "../port/lib.h"
18 #include "../port/error.h"
19 #include "../port/sd.h"
22 #define dprint(...) // print(__VA_ARGS__)
23 #define idprint(...) print(__VA_ARGS__)
24 #define Ticks MACHP(0)->ticks
29 NDrive = NCtlr*NCtlrdrv,
33 /* Addresses of ATA register */
50 ATAobs = 1<<1 | 1<<2 | 1<<4,
52 ATAbad = ATAbusy|ATAdf|ATAdrq|ATAerr,
59 /* EDMA interrupt error cause register */
73 /* flags for sata 2 version */
77 /* EDMA Command Register */
82 /* Interrupt mask for errors we care about */
83 IEM = eDevDis | eDevCon | eSelfDis,
84 IEM2 = eDevDis | eDevCon | eSelfDis2,
93 /* general mmio registers */
111 typedef struct Arb Arb;
112 typedef struct Bridge Bridge;
113 typedef struct Chip Chip;
114 typedef struct Ctlr Ctlr;
115 typedef struct Drive Drive;
116 typedef struct Edma Edma;
117 typedef struct Prd Prd;
118 typedef struct Rx Rx;
119 typedef struct Srb Srb;
120 typedef struct Tx Tx;
123 * there are 4 drives per chip. thus an 8-port
124 * card has two chips.
150 ulong pm2; /* phymode 2 init state */
151 ulong intick; /* check for hung drives. */
153 int mode; /* DMautoneg, satai or sataii. */
170 int driveno; /* ctlr*NCtlrdrv + unit */
190 Drive drive[NCtlrdrv];
194 struct Srb /* request buffer */
215 * Memory-mapped I/O registers in many forms.
217 struct Bridge /* memory-mapped per-drive registers */
233 }; /* must be 0x100 hex in length */
235 struct Arb /* memory-mapped per-chip registers */
237 ulong config; /* satahc configuration register (sata2 only) */
238 ulong rqop; /* request queue out-pointer */
239 ulong rqip; /* response queue in pointer */
240 ulong ict; /* inerrupt caolescing threshold */
241 ulong itt; /* interrupt timer threshold */
242 ulong ic; /* interrupt cause */
243 ulong btc; /* bridges test control */
244 ulong bts; /* bridges test status */
245 ulong bpc; /* bridges pin configuration */
250 struct Edma /* memory-mapped per-drive DMA-related registers */
252 ulong config; /* configuration register */
254 ulong iec; /* interrupt error cause */
255 ulong iem; /* interrupt error mask */
257 ulong txbasehi; /* request queue base address high */
258 ulong txi; /* request queue in pointer */
259 ulong txo; /* request queue out pointer */
261 ulong rxbasehi; /* response queue base address high */
262 ulong rxi; /* response queue in pointer */
263 ulong rxo; /* response queue out pointer */
265 ulong ctl; /* command register */
266 ulong testctl; /* test control */
268 ulong iordyto; /* IORDY timeout */
270 ulong sataconfig; /* sata 2 */
272 ushort pio; /* data register */
274 uchar err; /* features and error */
276 uchar seccnt; /* sector count */
286 uchar cmdstat; /* cmd/status */
288 uchar altstat; /* alternate status */
291 char fill3[0x1c00]; /* pad to 0x2000 bytes */
295 * Memory structures shared with card.
297 struct Prd /* physical region descriptor */
299 ulong pa; /* byte address of physical memory */
300 ushort count; /* byte count (bit0 must be 0) */
302 ulong zero; /* high long of 64 bit address */
306 struct Tx /* command request block */
308 ulong prdpa; /* physical region descriptor table structures */
309 ulong zero; /* must be zero (high long of prd address) */
310 ushort flag; /* control flags */
314 struct Rx /* command response block */
316 ushort cid; /* cID of response */
317 uchar cEdmaSts; /* EDMA status */
318 uchar cDevSts; /* status from disk */
319 ulong ts; /* time stamp */
322 static Ctlr *mvsatactlr[NCtlr];
323 static Drive *mvsatadrive[NDrive];
324 static int nmvsatadrive;
325 static char *diskstates[Dlast] = {
334 extern SDifc sdmv50xxifc;
352 if((p = srblist.freechain) == nil){
355 p = smalloc(sizeof *p);
357 srblist.freechain = p->next;
367 p->next = srblist.freechain;
368 srblist.freechain = p;
373 satawait(uchar *p, uchar mask, uchar v, int ms)
377 for(i=0; i<ms && (*p & mask) != v; i++)
379 return (*p & mask) == v;
382 /* unmask in the pci registers err done */
384 portswitch(ulong *mmio, int port, uint coal, uint on)
388 m = 3<<(port&3)*2 | coal<<8;
392 mmio[Portswtch] |= m;
394 mmio[Portswtch] &= m;
401 return d->unit->name;
405 /* I give up, marvell. You win. */
410 enum { BadAutoCal = 0xf << 26, };
412 if(d->ctlr->type == 1){
413 /* set phyctrl bits [0:1] to 01 per MV-S102013-00 Rev C. */
414 n = d->bridge->phyctrl;
416 d->bridge->phyctrl = n | 1;
420 n = d->bridge->phymode2;
421 while ((n & BadAutoCal) == BadAutoCal) {
422 dprint("%s: badautocal\n", dnam(d));
425 d->bridge->phymode2 = n;
427 d->bridge->phymode2 &= ~(1<<16 | 1<<31);
429 n = d->bridge->phymode2;
432 d->bridge->phymode2 = n;
435 /* abra cadabra! (random magic) */
436 m = d->bridge->phymode3;
439 d->bridge->phymode3 = m;
442 m = d->bridge->phymode3;
443 n = d->bridge->phymode4;
446 switch(d->ctlr->rid){
449 d->bridge->phymode4 = n;
450 d->bridge->phymode3 = m;
453 d->bridge->phymode4 = n;
457 /* revert values of pre-emphasis and signal amps to the saved ones */
458 n = d->bridge->phymode2;
462 d->bridge->phymode2 = n;
466 edmacleanout(Drive *d)
471 for(i=0; i<nelem(d->srb); i++){
475 srb->flag |= SFerror|SFdone;
479 while(srb = d->srbhead){
480 d->srbhead = srb->next;
481 srb->flag |= SFerror|SFdone;
487 edmadisable(Drive *d, int reset)
492 if(!reset && (e->ctl & eEnEDMA) == 0)
500 if (satawait((uchar *)&e->ctl, eEnEDMA, 0, 3*1000) == 0){
501 print("%s: eEnEDMA never cleared on reset\n", dnam(d));
514 d->unit->sectors = 0;
515 if (d->ctlr->type == 2) {
517 * without bit 8 we can boot without disks, but
518 * inserted disks will never appear. :-X
520 n = d->edma->sataconfig;
523 d->edma->sataconfig = n;
524 n = d->edma->sataconfig; /* flush */
527 if(edmadisable(d, 1) == -1){
530 d->bridge->sctrl = 0x301 | d->mode<<4;
542 d->tx = xspanalloc(32*sizeof(Tx), 1024, 0);
543 d->rx = xspanalloc(32*sizeof(Rx), 256, 0);
544 d->prd = xspanalloc(32*sizeof(Prd), 32, 0);
545 for(i = 0; i < 32; i++)
546 d->tx[i].prdpa = PCIWADDR(&d->prd[i]);
551 configdrive(Ctlr *ctlr, Drive *d, SDunit *unit)
553 dprint("%s: configdrive\n", unit->name);
556 portswitch(ctlr->lmmio, d->driveno, 0, 1);
558 if(d->bridge->status){
559 dprint("%s: configdrive: found drive %lux\n", unit->name, d->bridge->status);
570 dprint("%s: enabledrive..", dnam(d));
572 if((d->bridge->status & 0xf) != 3){
573 dprint("%s: not present\n", dnam(d));
577 if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0){
578 dprint("%s: busy timeout\n", dnam(d));
582 d->chip->arb->ic &= ~(0x101 << d->chipx);
583 edma->config = 0x51f;
584 if (d->ctlr->type == 2)
585 edma->config |= 7<<11;
586 edma->txi = PCIWADDR(d->tx);
587 edma->txo = (ulong)d->tx & 0x3e0;
588 edma->rxi = (ulong)d->rx & 0xf8;
589 edma->rxo = PCIWADDR(d->rx);
590 edma->ctl |= 1; /* enable dma */
595 enabledrive(Drive *d)
597 dprint("%s: enabledrive..", dnam(d));
598 if(edmaenable(d) == 0){
599 switch(d->bridge->status){
607 print("mv50: enable reset\n");
613 disabledrive(Drive *d)
615 if(d->tx == nil) /* never enabled */
619 portswitch(d->ctlr->lmmio, d->driveno, 0, 0);
623 setudmamode(Drive *d, uchar mode)
627 dprint("%s: setudmamode %d\n", dnam(d), mode);
630 iprint("setudamode(m%d): zero d->edma\m", d->driveno);
633 if(satawait(&edma->cmdstat, ~ATAobs, ATAdrdy, 250) == 0){
634 iprint("%s: cmdstat 0x%.2ux ready timeout\n", dnam(d), edma->cmdstat);
637 edma->altstat = ATAeIEN;
639 edma->seccnt = 0x40 | mode;
640 edma->cmdstat = 0xef;
642 if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0){
643 iprint("%s: cmdstat 0x%.2ux busy timeout\n", dnam(d), edma->cmdstat);
650 identifydrive(Drive *d)
658 dprint("%s: identifydrive\n", dnam(d));
659 setfissig(d, 0); /* BOTCH; need to find and set signature */
660 if(setudmamode(d, 5) == 0) /* BOTCH; run after identify */
664 memset(d->info, 0, sizeof d->info);
666 if(satawait(&edma->cmdstat, ~ATAobs, ATAdrdy, 5*1000) == 0)
669 edma->altstat = ATAeIEN; /* no interrupts */
670 edma->cmdstat = 0xec;
672 if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0)
674 for(i = 0; i < 256; i++)
676 if(edma->cmdstat & ATAbad)
678 d->sectors = idfeat(d, id);
679 d->secsize = idss(d, id);
680 idmove(d->serial, id+10, 20);
681 idmove(d->firmware, id+23, 8);
682 idmove(d->model, id+27, 40);
683 d->wwn = idwwn(d, id);
686 memset(u->inquiry, 0, sizeof u->inquiry);
689 u->inquiry[4] = sizeof u->inquiry - 4;
690 idmove((char*)u->inquiry+8, id+27, 40);
692 if(enabledrive(d) == 0) {
698 idprint("%s: %sLBA %llud sectors\n", dnam(d), s, d->sectors);
701 if(d->state == Dready)
716 * B 8-to-10 encoding error
720 * S link sequence error
721 * T transport state transition error
722 * F unrecognized fis type
726 static char stab[] = {
730 [18] 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
732 static ulong sbad = 7<<20 | 3<<23;
735 serrdecode(ulong r, char *s, char *e)
740 for(i = 0; i < nelem(stab) && s < e; i++)
741 if(r & 1<<i && stab[i]){
749 static char *iectab[] = {
766 iecdecode(ulong cause)
770 for(i = 0; i < nelem(iectab); i++)
777 Cerror1 = ePrtDataErr|ePrtPRDErr|eOverrun|ePrtCRQBErr|ePrtCRPBErr|ePrtIntErr,
778 Cerror2 = ePrtDataErr|ePrtPRDErr|ePrtCRQBErr|
779 ePrtCRPBErr|ePrtIntErr|eDevErr|eSelfDis2,
783 updatedrive(Drive *d)
791 if((edma->ctl & eEnEDMA) == 0){
792 /* FEr SATA#4 40xx */
793 x = d->edma->cmdstat;
799 dprint("%s: cause %.8lux [%s]\n", dnam(d), cause, iecdecode(cause));
802 if(cause & eDevDis && d->state == Dready)
803 iprint("%s: pulled: st=%.8lux\n", dnam(d), cause);
804 switch(d->ctlr->type){
806 if(cause & eUnderrun){
807 /* FEr SATA#5 50xx for revs A0, B0 */
812 dprint("%s: underrun\n", dnam(d));
815 if(cause & (eDevErr | eSelfDis)){
817 * FEr SATA#7 60xx for refs A0, B0
818 * check for IRC error. we only check the
819 * ABORT flag as we don't get the upper nibble
822 if(edma->altstat & ATAerr && edma->err & ATAabort)
834 serrdecode(d->bridge->serror, buf, buf+sizeof buf);
835 dprint("%s: serror %.8lux [%s]\n", dnam(d), d->bridge->serror, buf);
836 d->bridge->serror = ~0; /*d->bridge->serror;*/
847 srbrw(int rw, Drive *d, uchar *data, uint sectors, uvlong lba)
851 static uchar cmd[2][2] = { 0xC8, 0x25, 0xCA, 0x35 };
857 srb->sectors = sectors;
858 srb->count = sectors * d->secsize;
863 srb->lba[i] = lba >> 8*i;
864 srb->cmd = cmd[srb->req!=SDread][(d->feat&Dllba)!=0];
868 #define CMD(r, v) (((r)<<8) | (v))
870 mvsatarequest(ushort *cmd, Srb *srb, int llba)
872 *cmd++ = CMD(ARseccnt, 0);
873 *cmd++ = CMD(ARseccnt, srb->sectors);
874 *cmd++ = CMD(ARfea, 0);
876 *cmd++ = CMD(ARlba0, srb->lba[3]);
877 *cmd++ = CMD(ARlba0, srb->lba[0]);
878 *cmd++ = CMD(ARlba1, srb->lba[4]);
879 *cmd++ = CMD(ARlba1, srb->lba[1]);
880 *cmd++ = CMD(ARlba2, srb->lba[5]);
881 *cmd++ = CMD(ARlba2, srb->lba[2]);
882 *cmd++ = CMD(ARdev, 0xe0);
884 *cmd++ = CMD(ARlba0, srb->lba[0]);
885 *cmd++ = CMD(ARlba1, srb->lba[1]);
886 *cmd++ = CMD(ARlba2, srb->lba[2]);
887 *cmd++ = CMD(ARdev, srb->lba[3] | 0xe0);
889 *cmd = CMD(ARcmd, srb->cmd) | 1<<15;
893 advance(uintptr pa, int shift)
898 n = (pa & mask) + (1<<shift);
899 return (pa & ~mask) | (n & mask);
903 startsrb(Drive *d, Srb *srb)
910 if(d->nsrb >= nelem(d->srb)){
913 d->srbtail->next = srb;
921 for(i=0; i<nelem(d->srb); i++)
924 if(i == nelem(d->srb))
925 panic("sdmv50xx: no free srbs");
929 tx = (Tx*)KADDR(edma->txi);
930 tx->flag = i<<1 | (srb->req == SDread);
931 prd = KADDR(tx->prdpa);
932 prd->pa = PCIWADDR(srb->data);
933 prd->count = srb->count;
935 mvsatarequest(tx->regs, srb, d->feat&Dllba);
937 edma->txi = advance(edma->txi, 5);
946 completesrb(Drive *d)
953 if((edma->ctl & eEnEDMA) == 0)
956 while((edma->rxo&Rpidx) != (edma->rxi&Rpidx)){
957 rx = (Rx*)KADDR(edma->rxo);
958 if(srb = d->srb[rx->cid]){
959 d->srb[rx->cid] = nil;
961 if(rx->cDevSts & ATAbad)
962 srb->flag |= SFerror;
964 iprint("cEdmaSts: %02ux\n", rx->cEdmaSts);
965 srb->sta = rx->cDevSts;
969 iprint("srb missing\n");
970 edma->rxo = advance(edma->rxo, 3);
971 if(srb = d->srbhead){
972 d->srbhead = srb->next;
984 return srb->flag & SFdone;
991 mv50interrupt(Ureg*, void *v)
1002 cause = ctlr->lmmio[0x1d60/4];
1003 // dprint("sd%c: mv50interrupt: %.8lux\n", ctlr->sdev->idno, cause);
1004 for(i=0; cause && i<ctlr->ndrive; i++)
1005 if(cause & (3<<(i*2+i/4))){
1006 drive = &ctlr->drive[i];
1007 if(drive->edma == 0)
1008 continue; /* not ready yet. */
1012 a = ctlr->chip[i/4].arb;
1017 if(TK2MS(Ticks - tk0) > 3000){
1018 print("%s: irq wedge\n", dnam(drive));
1019 drive->state = Dreset;
1030 Midwait = 16*1024/Nms - 1,
1031 Mphywait = 512/Nms - 1,
1041 && TK2MS(Ticks - d->intick) > 5*1000
1042 && (e->rxo&Rpidx) == (e->rxi&Rpidx)){
1043 print("%s: drive hung; resetting\n", dnam(d));
1049 checkdrive(Drive *d, int i)
1051 static ulong s, olds[NCtlr*NCtlrdrv];
1054 s = d->bridge->status;
1056 dprint("%s: status: %.8lux -> %.8lux: %s\n", dnam(d), olds[i], s, diskstates[d->state]);
1067 dprint("%s: unknown state %.8lux\n", dnam(d), s);
1069 if(++d->wait&Mphywait)
1071 reset: d->mode ^= 1;
1072 dprint("%s: reset; new mode %d\n", dnam(d), d->mode);
1077 s = d->edma->cmdstat;
1078 if(s == 0x7f || (s&~ATAobs) != ATAdrdy){
1079 if((++d->wait&Midwait) == 0)
1081 }else if(identifydrive(d) == -1)
1088 iprint("%s: pulled: st=%.8lux\n", dnam(d), s); /* never happens */
1091 dprint("%s reset: mode %d\n", dnam(d), d->mode);
1104 tsleep(&up->sleep, return0, 0, Nms);
1105 for(i = 0; i < nmvsatadrive; i++)
1106 checkdrive(mvsatadrive[i], i);
1115 if(d->ctlr->type == 1){
1117 d->bridge = &d->chip->arb->bridge[d->chipx];
1119 d->edma->iem = IEM2;
1120 d->bridge = &d->chip->edma[d->chipx].port;
1121 // d->edma->iem = ~(1<<6);
1123 if(d->ctlr->lmmio[0x180d8/4] & 1)
1124 d->pm2 = d->bridge->phymode2 & Mpreamp;
1137 SDev *head, *tail, *sdev;
1138 static int ctlrno, done;
1146 while((p = pcimatch(p, 0x11ab, 0)) != nil){
1147 if(p->ccrb != Pcibcstore || p->ccru + p->ccrp || p->did&0x0f00)
1158 print("mv50pnp: unknown did %ux ignored\n", (ushort)p->did);
1161 if (ctlrno >= NCtlr) {
1162 print("mv50pnp: too many controllers\n");
1165 nunit = (p->did&0xf0) >> 4;
1166 print("#S/sd%c: Marvell 88sx%ux: %d sata-%s ports with%s flash\n",
1167 'E' + ctlrno, (ushort)p->did, nunit,
1168 ((p->did&0xf000)==0x6000? "II": "I"),
1169 (p->did&1? "": "out"));
1170 if((sdev = malloc(sizeof *sdev)) == nil)
1172 if((ctlr = malloc(sizeof *ctlr)) == nil){
1176 io = p->mem[0].bar & ~0x0F;
1177 mem = (ulong*)vmap(io, p->mem[0].size);
1179 print("sdmv50xx: address 0x%luX in use\n", io);
1186 /* avert thine eyes! (what does this do?) */
1188 ctlr->type = (p->did >> 12) & 3;
1189 if(ctlr->type == 1){
1195 sdev->ifc = &sdmv50xxifc;
1197 sdev->nunit = nunit;
1200 ctlr->irq = p->intl;
1201 ctlr->tbdf = p->tbdf;
1204 ctlr->mmio = (uchar*)mem;
1205 ctlr->nchip = (nunit+3)/4;
1206 ctlr->ndrive = nunit;
1208 for(i = 0; i < ctlr->nchip; i++){
1209 base = ctlr->mmio+0x20000+0x10000*i;
1210 ctlr->chip[i].arb = (Arb*)base;
1211 ctlr->chip[i].edma = (Edma*)(base + 0x2000);
1213 for (i = 0; i < nunit; i++) {
1214 d = &ctlr->drive[i];
1215 snprint(d->name, sizeof d->name, "mv50%d.%d", ctlrno, i);
1218 d->driveno = ctlrno*NCtlrdrv + i;
1220 d->chip = &ctlr->chip[i/4];
1221 d->edma = &d->chip->edma[d->chipx];
1222 mvsatadrive[d->driveno] = d;
1225 mvsatactlr[ctlrno] = ctlr;
1226 nmvsatadrive += nunit;
1238 mv50enable(SDev *sdev)
1243 dprint("sd%c: enable\n", sdev->idno);
1249 kproc("mvsata", satakproc, 0);
1250 snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
1251 intrenable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
1256 mv50disable(SDev *sdev)
1263 dprint("sd%c: disable\n", sdev->idno);
1267 for(i=0; i<ctlr->sdev->nunit; i++){
1268 drive = &ctlr->drive[i];
1270 disabledrive(drive);
1274 snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
1275 intrdisable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
1280 * Check that there is a disk or at least a hot swap bay in the drive.
1283 mv50verify(SDunit *unit)
1289 dprint("%s: verify\n", unit->name);
1290 ctlr = unit->dev->ctlr;
1291 drive = &ctlr->drive[unit->subno];
1294 i = configdrive(ctlr, drive, unit);
1299 * If ctlr->type == 1, then the drives spin up whenever
1300 * the controller feels like it; if ctlr->type == 2, then
1301 * they spin up as a result of configdrive.
1303 * If there is a drive in the slot, give it 1.4s to spin up
1304 * before returning. There is a noticeable drag on the
1305 * power supply when spinning up fifteen drives
1306 * all at once (like in the Coraid enclosures).
1308 if(ctlr->type == 2 && i == 0)
1310 tsleep(&up->sleep, return0, 0, 1400);
1317 * Check whether the disk is online.
1320 mv50online(SDunit *unit)
1327 ctlr = unit->dev->ctlr;
1328 d = &ctlr->drive[unit->subno];
1333 if(d->state == Dnew)
1336 idprint("%s: online: %s -> %s\n", unit->name, diskstates[s0], diskstates[d->state]);
1338 unit->sectors = d->sectors;
1339 unit->secsize = d->secsize;
1341 } else if(d->state == Dready)
1350 typedef struct Regs Regs;
1357 static Regs regsctlr[] =
1359 0x0C28, "pci serr# mask",
1360 0x1D40, "pci err addr low",
1361 0x1D44, "pci err addr hi",
1362 0x1D48, "pci err attr",
1363 0x1D50, "pci err cmd",
1364 0x1D58, "pci intr cause",
1365 0x1D5C, "pci mask cause",
1366 0x1D60, "device micr",
1367 0x1D64, "device mimr",
1370 static Regs regsarb[] =
1382 static Regs regsbridge[] =
1384 0x0000, "bridge status",
1385 0x0004, "bridge serror",
1386 0x0008, "bridge sctrl",
1387 0x000C, "bridge phyctrl",
1388 0x003C, "bridge ctrl",
1389 0x0074, "bridge phymode",
1392 static Regs regsedma[] =
1394 0x0000, "edma config",
1395 0x0004, "edma timer",
1398 0x0010, "edma txbasehi",
1401 0x001C, "edma rxbasehi",
1406 0x0030, "edma status",
1407 0x0034, "edma iordyto",
1408 /* 0x0100, "edma pio",
1410 0x0108, "edma sectors",
1411 0x010C, "edma lba0",
1412 0x0110, "edma lba1",
1413 0x0114, "edma lba2",
1414 0x0118, "edma lba3",
1415 0x011C, "edma cmdstat",
1416 0x0120, "edma altstat",
1421 rdregs(char *p, char *e, void *base, Regs *r, int n, char *prefix)
1426 p = seprint(p, e, "%s%s%-19s %.8ux\n",
1427 prefix ? prefix : "", prefix ? ": " : "",
1428 r[i].name, *(u32int*)((uchar*)base+r[i].offset));
1433 mv50rctl(SDunit *unit, char *p, int l)
1439 if((ctlr = unit->dev->ctlr) == nil)
1441 drive = &ctlr->drive[unit->subno];
1445 if(drive->state == Dready){
1446 p = seprint(p, e, "model %s\n", drive->model);
1447 p = seprint(p, e, "serial %s\n", drive->serial);
1448 p = seprint(p, e, "firmware %s\n", drive->firmware);
1449 p = seprint(p, e, "wwn\t%llux\n", drive->wwn);
1450 p = seprint(p, e, "flag\t");
1451 p = pflag(p, e, drive);
1453 p = seprint(p, e, "no disk present\n");
1454 p = seprint(p, e, "geometry %llud %ud\n", drive->sectors, drive->secsize);
1455 p = rdregs(p, e, drive->bridge, regsbridge, nelem(regsbridge), nil);
1457 p = rdregs(p, e, drive->chip->arb, regsarb, nelem(regsarb), nil);
1458 p = rdregs(p, e, drive->bridge, regsbridge, nelem(regsbridge), nil);
1459 p = rdregs(p, e, drive->edma, regsedma, nelem(regsedma), nil);
1465 mv50wctl(SDunit *unit, Cmdbuf *cb)
1470 if(strcmp(cb->f[0], "reset") == 0){
1471 ctlr = unit->dev->ctlr;
1472 drive = &ctlr->drive[unit->subno];
1474 drive->state = Dreset;
1478 cmderror(cb, Ebadctl);
1487 for(i = 0; i < 120; i++){
1489 s = d->bridge->status;
1493 if(d->state == Dready)
1501 tsleep(&up->sleep, return0, 0, 1000);
1505 print("%s: not responding; error\n", dnam(d));
1510 mv50bio(SDunit *u, int /*lun*/, int write, void *a, long count, uvlong lba)
1518 ctlr = u->dev->ctlr;
1519 d = ctlr->drive + u->subno;
1523 if(waitready(d) != SDok)
1527 * Max is 128 sectors (64kB) because prd->count is 16 bits.
1533 if((d->edma->ctl&eEnEDMA) == 0 && edmaenable(d) == -1){
1537 srb = srbrw(write, d, data, n, lba);
1543 sleep(srb, srbdone, srb);
1549 tryagain: if(++try == 10){
1550 print("%s: bad disk\n", dnam(d));
1553 dprint("%s: retry\n", dnam(d));
1557 print("%s: i/o error\n", dnam(d));
1562 data += n*u->secsize;
1564 return data - (uchar*)a;
1570 int count, n, status, rw;
1577 ctlr = unit->dev->ctlr;
1578 d = &ctlr->drive[unit->subno];
1580 if((status = sdfakescsi(r)) != SDnostatus)
1581 return r->status = status;
1582 if((status = sdfakescsirw(r, &lba, &count, &rw)) == SDcheck)
1584 n = mv50bio(r->unit, r->lun, rw, r->data, count, lba);
1592 mkrfis(SDreq *r, Drive *d, Edma *e)
1599 if((d->feat & Dllba) && (r->ataproto & P28) == 0){
1600 u[Frerror] = e->err;
1601 u[Fsc8] = e->seccnt;
1603 u[Flba24] = e->lba0;
1605 u[Flba32] = e->lba1;
1607 u[Flba40] = e->lba2;
1608 u[Flba16] = e->lba2;
1610 u[Fstatus] = e->cmdstat;
1612 u[Frerror] = e->err;
1616 u[Flba16] = e->lba2;
1618 u[Fstatus] = e->cmdstat;
1623 piocmd(SDreq *r, Drive *d)
1626 int n, nsec, i, err;
1632 if(waitready(d) != SDok)
1636 nsec = r->dlen / u->secsize;
1637 if(r->dlen < nsec*u->secsize)
1638 nsec = r->dlen/u->secsize;
1640 error("can't do more than 256 sectors");
1644 if(edmadisable(d, 0) == -1) {
1646 error("can't disable edma");
1648 n = satawait(&e->cmdstat, ATAdrdy|ATAbusy, ATAdrdy, 3*1000);
1650 print("piocmd: notready %.2ux\n", e->cmdstat);
1652 return sdsetsense(r, SDcheck, 4, 8, 0);
1655 if(r->ataproto & P28){
1656 e->altstat = ATAeIEN;
1661 e->lba2 = c[Flba16];
1663 e->cmdstat = c[Fcmd];
1665 e->altstat = ATAeIEN;
1666 e->seccnt = c[Fsc8];
1669 e->lba0 = c[Flba24];
1671 e->lba1 = c[Flba32];
1673 e->lba1 = c[Flba40];
1674 e->lba2 = c[Flba16];
1676 e->cmdstat = c[Fcmd];
1680 if((r->ataproto & Pdatam) == Pnd)
1681 n = satawait(&e->cmdstat, ATAbusy, 0, 3*1000);
1683 n = satawait(&e->cmdstat, ATAbusy|ATAdrq, ATAdrq, 3*1000);
1684 if(n == 0 || e->cmdstat & ATAerr){
1689 for(; nsec > 0; nsec--)
1690 for (i = 0; i < u->secsize; i += 2) {
1691 n = satawait(&e->cmdstat, ATAbusy|ATAdrq, ATAdrq, 300);
1697 if(r->ataproto & Pout){
1698 n = (ushort)p[i + 1] << 8;
1713 return sdsetsense(r, SDcheck, 4, 8, 0);
1715 return sdsetsense(r, SDok, 0, 0, 0);
1719 * hack to allow udma mode to be set or unset
1720 * via direct ata command. it would be better
1721 * to move the assumptions about dma mode out
1722 * of some of the helper functions.
1730 if(c[Fcmd] == 0xef && c[Ffeat] == 0x03){
1738 fisreqchk(Sfis *f, SDreq *r)
1740 if((r->ataproto & Pprotom) == Ppkt)
1743 * handle oob requests;
1744 * restrict & sanitize commands
1748 if(r->cmd[0] == 0xf0){
1749 sigtofis(f, r->cmd);
1760 badf(SDreq *r, Drive*)
1762 print("badf %.2ux %2ux\n", r->cmd[2], r->ataproto);
1763 return sdsetsense(r, SDcheck, 2, 24, 0);
1767 ataio0(SDreq *r, Drive *d)
1769 int (*f)(SDreq*, Drive*);
1772 switch(r->ataproto & Pprotom){
1793 d = c->drive + u->subno;
1794 if((status = fisreqchk(d, r)) != SDnostatus)
1797 USED(udm); /* botch */
1805 switch(status = ataio0(r, d)){
1807 dprint("%s: status %d\n", dnam(d), status);
1810 dprint("%s: retry\n", dnam(d));
1813 sdsetsense(r, SDok, 0, 0, 0);
1818 return r->status = status;
1822 SDifc sdmv50xxifc = {
1823 "mv50xx", /* name */
1827 mv50enable, /* enable */
1828 mv50disable, /* disable */
1830 mv50verify, /* verify */
1831 mv50online, /* online */
1833 mv50rctl, /* rctl */
1834 mv50wctl, /* wctl */
1845 * The original driver on which this one is based came with the
1851 * This software is provided `as-is,' without any express or implied
1852 * warranty. In no event will the author be held liable for any damages
1853 * arising from the use of this software.
1855 * Permission is granted to anyone to use this software for any purpose,
1856 * including commercial applications, and to alter it and redistribute it
1857 * freely, subject to the following restrictions:
1859 * 1. The origin of this software must not be misrepresented; you must
1860 * not claim that you wrote the original software. If you use this
1861 * software in a product, an acknowledgment in the product documentation
1862 * would be appreciated but is not required.
1864 * 2. Altered source versions must be plainly marked as such, and must
1865 * not be misrepresented as being the original software.
1867 * 3. This notice may not be removed or altered from any source