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/pci.h"
19 #include "../port/error.h"
20 #include "../port/sd.h"
23 #define dprint(...) // print(__VA_ARGS__)
24 #define idprint(...) print(__VA_ARGS__)
25 #define Ticks MACHP(0)->ticks
30 NDrive = NCtlr*NCtlrdrv,
34 /* Addresses of ATA register */
51 ATAobs = 1<<1 | 1<<2 | 1<<4,
53 ATAbad = ATAbusy|ATAdf|ATAdrq|ATAerr,
60 /* EDMA interrupt error cause register */
74 /* flags for sata 2 version */
78 /* EDMA Command Register */
83 /* Interrupt mask for errors we care about */
84 IEM = eDevDis | eDevCon | eSelfDis,
85 IEM2 = eDevDis | eDevCon | eSelfDis2,
94 /* general mmio registers */
112 typedef struct Arb Arb;
113 typedef struct Bridge Bridge;
114 typedef struct Chip Chip;
115 typedef struct Ctlr Ctlr;
116 typedef struct Drive Drive;
117 typedef struct Edma Edma;
118 typedef struct Prd Prd;
119 typedef struct Rx Rx;
120 typedef struct Srb Srb;
121 typedef struct Tx Tx;
124 * there are 4 drives per chip. thus an 8-port
125 * card has two chips.
151 ulong pm2; /* phymode 2 init state */
152 ulong intick; /* check for hung drives. */
154 int mode; /* DMautoneg, satai or sataii. */
171 int driveno; /* ctlr*NCtlrdrv + unit */
191 Drive drive[NCtlrdrv];
195 struct Srb /* request buffer */
216 * Memory-mapped I/O registers in many forms.
218 struct Bridge /* memory-mapped per-drive registers */
234 }; /* must be 0x100 hex in length */
236 struct Arb /* memory-mapped per-chip registers */
238 ulong config; /* satahc configuration register (sata2 only) */
239 ulong rqop; /* request queue out-pointer */
240 ulong rqip; /* response queue in pointer */
241 ulong ict; /* inerrupt caolescing threshold */
242 ulong itt; /* interrupt timer threshold */
243 ulong ic; /* interrupt cause */
244 ulong btc; /* bridges test control */
245 ulong bts; /* bridges test status */
246 ulong bpc; /* bridges pin configuration */
251 struct Edma /* memory-mapped per-drive DMA-related registers */
253 ulong config; /* configuration register */
255 ulong iec; /* interrupt error cause */
256 ulong iem; /* interrupt error mask */
258 ulong txbasehi; /* request queue base address high */
259 ulong txi; /* request queue in pointer */
260 ulong txo; /* request queue out pointer */
262 ulong rxbasehi; /* response queue base address high */
263 ulong rxi; /* response queue in pointer */
264 ulong rxo; /* response queue out pointer */
266 ulong ctl; /* command register */
267 ulong testctl; /* test control */
269 ulong iordyto; /* IORDY timeout */
271 ulong sataconfig; /* sata 2 */
273 ushort pio; /* data register */
275 uchar err; /* features and error */
277 uchar seccnt; /* sector count */
287 uchar cmdstat; /* cmd/status */
289 uchar altstat; /* alternate status */
292 char fill3[0x1c00]; /* pad to 0x2000 bytes */
296 * Memory structures shared with card.
298 struct Prd /* physical region descriptor */
300 ulong pa; /* byte address of physical memory */
301 ushort count; /* byte count (bit0 must be 0) */
303 ulong zero; /* high long of 64 bit address */
307 struct Tx /* command request block */
309 ulong prdpa; /* physical region descriptor table structures */
310 ulong zero; /* must be zero (high long of prd address) */
311 ushort flag; /* control flags */
315 struct Rx /* command response block */
317 ushort cid; /* cID of response */
318 uchar cEdmaSts; /* EDMA status */
319 uchar cDevSts; /* status from disk */
320 ulong ts; /* time stamp */
323 static Ctlr *mvsatactlr[NCtlr];
324 static Drive *mvsatadrive[NDrive];
325 static int nmvsatadrive;
326 static char *diskstates[Dlast] = {
335 extern SDifc sdmv50xxifc;
353 if((p = srblist.freechain) == nil){
356 p = smalloc(sizeof *p);
358 srblist.freechain = p->next;
368 p->next = srblist.freechain;
369 srblist.freechain = p;
374 satawait(uchar *p, uchar mask, uchar v, int ms)
378 for(i=0; i<ms && (*p & mask) != v; i++)
380 return (*p & mask) == v;
383 /* unmask in the pci registers err done */
385 portswitch(ulong *mmio, int port, uint coal, uint on)
389 m = 3<<(port&3)*2 | coal<<8;
393 mmio[Portswtch] |= m;
395 mmio[Portswtch] &= m;
402 return d->unit->name;
406 /* I give up, marvell. You win. */
411 enum { BadAutoCal = 0xf << 26, };
413 if(d->ctlr->type == 1){
414 /* set phyctrl bits [0:1] to 01 per MV-S102013-00 Rev C. */
415 n = d->bridge->phyctrl;
417 d->bridge->phyctrl = n | 1;
421 n = d->bridge->phymode2;
422 while ((n & BadAutoCal) == BadAutoCal) {
423 dprint("%s: badautocal\n", dnam(d));
426 d->bridge->phymode2 = n;
428 d->bridge->phymode2 &= ~(1<<16 | 1<<31);
430 n = d->bridge->phymode2;
433 d->bridge->phymode2 = n;
436 /* abra cadabra! (random magic) */
437 m = d->bridge->phymode3;
440 d->bridge->phymode3 = m;
443 m = d->bridge->phymode3;
444 n = d->bridge->phymode4;
447 switch(d->ctlr->rid){
450 d->bridge->phymode4 = n;
451 d->bridge->phymode3 = m;
454 d->bridge->phymode4 = n;
458 /* revert values of pre-emphasis and signal amps to the saved ones */
459 n = d->bridge->phymode2;
463 d->bridge->phymode2 = n;
467 edmacleanout(Drive *d)
472 for(i=0; i<nelem(d->srb); i++){
476 srb->flag |= SFerror|SFdone;
480 while(srb = d->srbhead){
481 d->srbhead = srb->next;
482 srb->flag |= SFerror|SFdone;
488 edmadisable(Drive *d, int reset)
493 if(!reset && (e->ctl & eEnEDMA) == 0)
501 if (satawait((uchar *)&e->ctl, eEnEDMA, 0, 3*1000) == 0){
502 print("%s: eEnEDMA never cleared on reset\n", dnam(d));
515 d->unit->sectors = 0;
516 if (d->ctlr->type == 2) {
518 * without bit 8 we can boot without disks, but
519 * inserted disks will never appear. :-X
521 n = d->edma->sataconfig;
524 d->edma->sataconfig = n;
525 n = d->edma->sataconfig; /* flush */
528 if(edmadisable(d, 1) == -1){
531 d->bridge->sctrl = 0x301 | d->mode<<4;
543 d->tx = xspanalloc(32*sizeof(Tx), 1024, 0);
544 d->rx = xspanalloc(32*sizeof(Rx), 256, 0);
545 d->prd = xspanalloc(32*sizeof(Prd), 32, 0);
546 for(i = 0; i < 32; i++)
547 d->tx[i].prdpa = PCIWADDR(&d->prd[i]);
552 configdrive(Ctlr *ctlr, Drive *d, SDunit *unit)
554 dprint("%s: configdrive\n", unit->name);
557 portswitch(ctlr->lmmio, d->driveno, 0, 1);
559 if(d->bridge->status){
560 dprint("%s: configdrive: found drive %lux\n", unit->name, d->bridge->status);
571 dprint("%s: enabledrive..", dnam(d));
573 if((d->bridge->status & 0xf) != 3){
574 dprint("%s: not present\n", dnam(d));
578 if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0){
579 dprint("%s: busy timeout\n", dnam(d));
583 d->chip->arb->ic &= ~(0x101 << d->chipx);
584 edma->config = 0x51f;
585 if (d->ctlr->type == 2)
586 edma->config |= 7<<11;
587 edma->txi = PCIWADDR(d->tx);
588 edma->txo = (ulong)d->tx & 0x3e0;
589 edma->rxi = (ulong)d->rx & 0xf8;
590 edma->rxo = PCIWADDR(d->rx);
591 edma->ctl |= 1; /* enable dma */
596 enabledrive(Drive *d)
598 dprint("%s: enabledrive..", dnam(d));
599 if(edmaenable(d) == 0){
600 switch(d->bridge->status){
608 print("mv50: enable reset\n");
614 disabledrive(Drive *d)
616 if(d->tx == nil) /* never enabled */
620 portswitch(d->ctlr->lmmio, d->driveno, 0, 0);
624 setudmamode(Drive *d, uchar mode)
628 dprint("%s: setudmamode %d\n", dnam(d), mode);
631 iprint("setudamode(m%d): zero d->edma\m", d->driveno);
634 if(satawait(&edma->cmdstat, ~ATAobs, ATAdrdy, 250) == 0){
635 iprint("%s: cmdstat 0x%.2ux ready timeout\n", dnam(d), edma->cmdstat);
638 edma->altstat = ATAeIEN;
640 edma->seccnt = 0x40 | mode;
641 edma->cmdstat = 0xef;
643 if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0){
644 iprint("%s: cmdstat 0x%.2ux busy timeout\n", dnam(d), edma->cmdstat);
651 identifydrive(Drive *d)
659 dprint("%s: identifydrive\n", dnam(d));
660 setfissig(d, 0); /* BOTCH; need to find and set signature */
661 if(setudmamode(d, 5) == 0) /* BOTCH; run after identify */
665 memset(d->info, 0, sizeof d->info);
667 if(satawait(&edma->cmdstat, ~ATAobs, ATAdrdy, 5*1000) == 0)
670 edma->altstat = ATAeIEN; /* no interrupts */
671 edma->cmdstat = 0xec;
673 if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0)
675 for(i = 0; i < 256; i++)
677 if(edma->cmdstat & ATAbad)
679 d->sectors = idfeat(d, id);
680 d->secsize = idss(d, id);
681 idmove(d->serial, id+10, 20);
682 idmove(d->firmware, id+23, 8);
683 idmove(d->model, id+27, 40);
684 d->wwn = idwwn(d, id);
687 memset(u->inquiry, 0, sizeof u->inquiry);
690 u->inquiry[4] = sizeof u->inquiry - 4;
691 idmove((char*)u->inquiry+8, id+27, 40);
693 if(enabledrive(d) == 0) {
699 idprint("%s: %sLBA %llud sectors\n", dnam(d), s, d->sectors);
702 if(d->state == Dready)
717 * B 8-to-10 encoding error
721 * S link sequence error
722 * T transport state transition error
723 * F unrecognized fis type
727 static char stab[] = {
731 [18] 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
733 static ulong sbad = 7<<20 | 3<<23;
736 serrdecode(ulong r, char *s, char *e)
741 for(i = 0; i < nelem(stab) && s < e; i++)
742 if(r & 1<<i && stab[i]){
750 static char *iectab[] = {
767 iecdecode(ulong cause)
771 for(i = 0; i < nelem(iectab); i++)
778 Cerror1 = ePrtDataErr|ePrtPRDErr|eOverrun|ePrtCRQBErr|ePrtCRPBErr|ePrtIntErr,
779 Cerror2 = ePrtDataErr|ePrtPRDErr|ePrtCRQBErr|
780 ePrtCRPBErr|ePrtIntErr|eDevErr|eSelfDis2,
784 updatedrive(Drive *d)
792 if((edma->ctl & eEnEDMA) == 0){
793 /* FEr SATA#4 40xx */
794 x = d->edma->cmdstat;
800 dprint("%s: cause %.8lux [%s]\n", dnam(d), cause, iecdecode(cause));
803 if(cause & eDevDis && d->state == Dready)
804 iprint("%s: pulled: st=%.8lux\n", dnam(d), cause);
805 switch(d->ctlr->type){
807 if(cause & eUnderrun){
808 /* FEr SATA#5 50xx for revs A0, B0 */
813 dprint("%s: underrun\n", dnam(d));
816 if(cause & (eDevErr | eSelfDis)){
818 * FEr SATA#7 60xx for refs A0, B0
819 * check for IRC error. we only check the
820 * ABORT flag as we don't get the upper nibble
823 if(edma->altstat & ATAerr && edma->err & ATAabort)
835 serrdecode(d->bridge->serror, buf, buf+sizeof buf);
836 dprint("%s: serror %.8lux [%s]\n", dnam(d), d->bridge->serror, buf);
837 d->bridge->serror = ~0; /*d->bridge->serror;*/
848 srbrw(int rw, Drive *d, uchar *data, uint sectors, uvlong lba)
852 static uchar cmd[2][2] = { 0xC8, 0x25, 0xCA, 0x35 };
858 srb->sectors = sectors;
859 srb->count = sectors * d->secsize;
864 srb->lba[i] = lba >> 8*i;
865 srb->cmd = cmd[srb->req!=SDread][(d->feat&Dllba)!=0];
869 #define CMD(r, v) (((r)<<8) | (v))
871 mvsatarequest(ushort *cmd, Srb *srb, int llba)
873 *cmd++ = CMD(ARseccnt, 0);
874 *cmd++ = CMD(ARseccnt, srb->sectors);
875 *cmd++ = CMD(ARfea, 0);
877 *cmd++ = CMD(ARlba0, srb->lba[3]);
878 *cmd++ = CMD(ARlba0, srb->lba[0]);
879 *cmd++ = CMD(ARlba1, srb->lba[4]);
880 *cmd++ = CMD(ARlba1, srb->lba[1]);
881 *cmd++ = CMD(ARlba2, srb->lba[5]);
882 *cmd++ = CMD(ARlba2, srb->lba[2]);
883 *cmd++ = CMD(ARdev, 0xe0);
885 *cmd++ = CMD(ARlba0, srb->lba[0]);
886 *cmd++ = CMD(ARlba1, srb->lba[1]);
887 *cmd++ = CMD(ARlba2, srb->lba[2]);
888 *cmd++ = CMD(ARdev, srb->lba[3] | 0xe0);
890 *cmd = CMD(ARcmd, srb->cmd) | 1<<15;
894 advance(uintptr pa, int shift)
899 n = (pa & mask) + (1<<shift);
900 return (pa & ~mask) | (n & mask);
904 startsrb(Drive *d, Srb *srb)
911 if(d->nsrb >= nelem(d->srb)){
914 d->srbtail->next = srb;
922 for(i=0; i<nelem(d->srb); i++)
925 if(i == nelem(d->srb))
926 panic("sdmv50xx: no free srbs");
930 tx = (Tx*)KADDR(edma->txi);
931 tx->flag = i<<1 | (srb->req == SDread);
932 prd = KADDR(tx->prdpa);
933 prd->pa = PCIWADDR(srb->data);
934 prd->count = srb->count;
936 mvsatarequest(tx->regs, srb, d->feat&Dllba);
938 edma->txi = advance(edma->txi, 5);
947 completesrb(Drive *d)
954 if((edma->ctl & eEnEDMA) == 0)
957 while((edma->rxo&Rpidx) != (edma->rxi&Rpidx)){
958 rx = (Rx*)KADDR(edma->rxo);
959 if(srb = d->srb[rx->cid]){
960 d->srb[rx->cid] = nil;
962 if(rx->cDevSts & ATAbad)
963 srb->flag |= SFerror;
965 iprint("cEdmaSts: %02ux\n", rx->cEdmaSts);
966 srb->sta = rx->cDevSts;
970 iprint("srb missing\n");
971 edma->rxo = advance(edma->rxo, 3);
972 if(srb = d->srbhead){
973 d->srbhead = srb->next;
985 return srb->flag & SFdone;
992 mv50interrupt(Ureg*, void *v)
1003 cause = ctlr->lmmio[0x1d60/4];
1004 // dprint("sd%c: mv50interrupt: %.8lux\n", ctlr->sdev->idno, cause);
1005 for(i=0; cause && i<ctlr->ndrive; i++)
1006 if(cause & (3<<(i*2+i/4))){
1007 drive = &ctlr->drive[i];
1008 if(drive->edma == 0)
1009 continue; /* not ready yet. */
1013 a = ctlr->chip[i/4].arb;
1018 if(TK2MS(Ticks - tk0) > 3000){
1019 print("%s: irq wedge\n", dnam(drive));
1020 drive->state = Dreset;
1031 Midwait = 16*1024/Nms - 1,
1032 Mphywait = 512/Nms - 1,
1042 && TK2MS(Ticks - d->intick) > 5*1000
1043 && (e->rxo&Rpidx) == (e->rxi&Rpidx)){
1044 print("%s: drive hung; resetting\n", dnam(d));
1050 checkdrive(Drive *d, int i)
1052 static ulong s, olds[NCtlr*NCtlrdrv];
1055 s = d->bridge->status;
1057 dprint("%s: status: %.8lux -> %.8lux: %s\n", dnam(d), olds[i], s, diskstates[d->state]);
1068 dprint("%s: unknown state %.8lux\n", dnam(d), s);
1070 if(++d->wait&Mphywait)
1072 reset: d->mode ^= 1;
1073 dprint("%s: reset; new mode %d\n", dnam(d), d->mode);
1078 s = d->edma->cmdstat;
1079 if(s == 0x7f || (s&~ATAobs) != ATAdrdy){
1080 if((++d->wait&Midwait) == 0)
1082 }else if(identifydrive(d) == -1)
1089 iprint("%s: pulled: st=%.8lux\n", dnam(d), s); /* never happens */
1092 dprint("%s reset: mode %d\n", dnam(d), d->mode);
1107 tsleep(&up->sleep, return0, 0, Nms);
1108 for(i = 0; i < nmvsatadrive; i++)
1109 checkdrive(mvsatadrive[i], i);
1118 if(d->ctlr->type == 1){
1120 d->bridge = &d->chip->arb->bridge[d->chipx];
1122 d->edma->iem = IEM2;
1123 d->bridge = &d->chip->edma[d->chipx].port;
1124 // d->edma->iem = ~(1<<6);
1126 if(d->ctlr->lmmio[0x180d8/4] & 1)
1127 d->pm2 = d->bridge->phymode2 & Mpreamp;
1141 SDev *head, *tail, *sdev;
1142 static int ctlrno, done;
1150 while((p = pcimatch(p, 0x11ab, 0)) != nil){
1151 if(p->ccrb != Pcibcstore || p->ccru + p->ccrp || p->did&0x0f00)
1153 if(p->mem[0].size == 0 || (p->mem[0].bar & 1) != 0)
1164 print("mv50pnp: unknown did %ux ignored\n", (ushort)p->did);
1167 if (ctlrno >= NCtlr) {
1168 print("mv50pnp: too many controllers\n");
1171 nunit = (p->did&0xf0) >> 4;
1172 print("#S/sd%c: Marvell 88sx%ux: %d sata-%s ports with%s flash\n",
1173 'E' + ctlrno, (ushort)p->did, nunit,
1174 ((p->did&0xf000)==0x6000? "II": "I"),
1175 (p->did&1? "": "out"));
1176 io = p->mem[0].bar & ~0xF;
1177 mem = (ulong*)vmap(io, p->mem[0].size);
1179 print("sdmv50xx: can't map %llux\n", io);
1182 if((sdev = malloc(sizeof *sdev)) == nil)
1184 if((ctlr = malloc(sizeof *ctlr)) == nil){
1190 /* avert thine eyes! (what does this do?) */
1192 ctlr->type = (p->did >> 12) & 3;
1193 if(ctlr->type == 1){
1199 sdev->ifc = &sdmv50xxifc;
1201 sdev->nunit = nunit;
1204 ctlr->irq = p->intl;
1205 ctlr->tbdf = p->tbdf;
1208 ctlr->mmio = (uchar*)mem;
1209 ctlr->nchip = (nunit+3)/4;
1210 ctlr->ndrive = nunit;
1212 for(i = 0; i < ctlr->nchip; i++){
1213 base = ctlr->mmio+0x20000+0x10000*i;
1214 ctlr->chip[i].arb = (Arb*)base;
1215 ctlr->chip[i].edma = (Edma*)(base + 0x2000);
1217 for (i = 0; i < nunit; i++) {
1218 d = &ctlr->drive[i];
1219 snprint(d->name, sizeof d->name, "mv50%d.%d", ctlrno, i);
1222 d->driveno = ctlrno*NCtlrdrv + i;
1224 d->chip = &ctlr->chip[i/4];
1225 d->edma = &d->chip->edma[d->chipx];
1226 mvsatadrive[d->driveno] = d;
1229 mvsatactlr[ctlrno] = ctlr;
1230 nmvsatadrive += nunit;
1242 mv50enable(SDev *sdev)
1247 dprint("sd%c: enable\n", sdev->idno);
1253 kproc("mvsata", satakproc, 0);
1254 snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
1255 intrenable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
1260 mv50disable(SDev *sdev)
1267 dprint("sd%c: disable\n", sdev->idno);
1271 for(i=0; i<ctlr->sdev->nunit; i++){
1272 drive = &ctlr->drive[i];
1274 disabledrive(drive);
1278 snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
1279 intrdisable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
1284 * Check that there is a disk or at least a hot swap bay in the drive.
1287 mv50verify(SDunit *unit)
1293 dprint("%s: verify\n", unit->name);
1294 ctlr = unit->dev->ctlr;
1295 drive = &ctlr->drive[unit->subno];
1298 i = configdrive(ctlr, drive, unit);
1303 * If ctlr->type == 1, then the drives spin up whenever
1304 * the controller feels like it; if ctlr->type == 2, then
1305 * they spin up as a result of configdrive.
1307 * If there is a drive in the slot, give it 1.4s to spin up
1308 * before returning. There is a noticeable drag on the
1309 * power supply when spinning up fifteen drives
1310 * all at once (like in the Coraid enclosures).
1312 if(ctlr->type == 2 && i == 0)
1314 tsleep(&up->sleep, return0, 0, 1400);
1321 * Check whether the disk is online.
1324 mv50online(SDunit *unit)
1331 ctlr = unit->dev->ctlr;
1332 d = &ctlr->drive[unit->subno];
1337 if(d->state == Dnew)
1340 idprint("%s: online: %s -> %s\n", unit->name, diskstates[s0], diskstates[d->state]);
1342 unit->sectors = d->sectors;
1343 unit->secsize = d->secsize;
1345 } else if(d->state == Dready)
1354 typedef struct Regs Regs;
1361 static Regs regsctlr[] =
1363 0x0C28, "pci serr# mask",
1364 0x1D40, "pci err addr low",
1365 0x1D44, "pci err addr hi",
1366 0x1D48, "pci err attr",
1367 0x1D50, "pci err cmd",
1368 0x1D58, "pci intr cause",
1369 0x1D5C, "pci mask cause",
1370 0x1D60, "device micr",
1371 0x1D64, "device mimr",
1374 static Regs regsarb[] =
1386 static Regs regsbridge[] =
1388 0x0000, "bridge status",
1389 0x0004, "bridge serror",
1390 0x0008, "bridge sctrl",
1391 0x000C, "bridge phyctrl",
1392 0x003C, "bridge ctrl",
1393 0x0074, "bridge phymode",
1396 static Regs regsedma[] =
1398 0x0000, "edma config",
1399 0x0004, "edma timer",
1402 0x0010, "edma txbasehi",
1405 0x001C, "edma rxbasehi",
1410 0x0030, "edma status",
1411 0x0034, "edma iordyto",
1412 /* 0x0100, "edma pio",
1414 0x0108, "edma sectors",
1415 0x010C, "edma lba0",
1416 0x0110, "edma lba1",
1417 0x0114, "edma lba2",
1418 0x0118, "edma lba3",
1419 0x011C, "edma cmdstat",
1420 0x0120, "edma altstat",
1425 rdregs(char *p, char *e, void *base, Regs *r, int n, char *prefix)
1430 p = seprint(p, e, "%s%s%-19s %.8ux\n",
1431 prefix ? prefix : "", prefix ? ": " : "",
1432 r[i].name, *(u32int*)((uchar*)base+r[i].offset));
1437 mv50rctl(SDunit *unit, char *p, int l)
1443 if((ctlr = unit->dev->ctlr) == nil)
1445 drive = &ctlr->drive[unit->subno];
1449 if(drive->state == Dready){
1450 p = seprint(p, e, "model %s\n", drive->model);
1451 p = seprint(p, e, "serial %s\n", drive->serial);
1452 p = seprint(p, e, "firmware %s\n", drive->firmware);
1453 p = seprint(p, e, "wwn\t%llux\n", drive->wwn);
1454 p = seprint(p, e, "flag\t");
1455 p = pflag(p, e, drive);
1457 p = seprint(p, e, "no disk present\n");
1458 p = seprint(p, e, "geometry %llud %ud\n", drive->sectors, drive->secsize);
1459 p = rdregs(p, e, drive->bridge, regsbridge, nelem(regsbridge), nil);
1461 p = rdregs(p, e, drive->chip->arb, regsarb, nelem(regsarb), nil);
1462 p = rdregs(p, e, drive->bridge, regsbridge, nelem(regsbridge), nil);
1463 p = rdregs(p, e, drive->edma, regsedma, nelem(regsedma), nil);
1469 mv50wctl(SDunit *unit, Cmdbuf *cb)
1474 if(strcmp(cb->f[0], "reset") == 0){
1475 ctlr = unit->dev->ctlr;
1476 drive = &ctlr->drive[unit->subno];
1478 drive->state = Dreset;
1482 cmderror(cb, Ebadctl);
1491 for(i = 0; i < 120; i++){
1493 s = d->bridge->status;
1497 if(d->state == Dready)
1505 tsleep(&up->sleep, return0, 0, 1000);
1509 print("%s: not responding; error\n", dnam(d));
1514 mv50bio(SDunit *u, int /*lun*/, int write, void *a, long count, uvlong lba)
1522 ctlr = u->dev->ctlr;
1523 d = ctlr->drive + u->subno;
1527 if(waitready(d) != SDok)
1531 * Max is 128 sectors (64kB) because prd->count is 16 bits.
1537 if((d->edma->ctl&eEnEDMA) == 0 && edmaenable(d) == -1){
1541 srb = srbrw(write, d, data, n, lba);
1547 sleep(srb, srbdone, srb);
1553 tryagain: if(++try == 10){
1554 print("%s: bad disk\n", dnam(d));
1557 dprint("%s: retry\n", dnam(d));
1561 print("%s: i/o error\n", dnam(d));
1566 data += n*u->secsize;
1568 return data - (uchar*)a;
1574 int count, n, status, rw;
1581 ctlr = unit->dev->ctlr;
1582 d = &ctlr->drive[unit->subno];
1584 if((status = sdfakescsi(r)) != SDnostatus)
1585 return r->status = status;
1586 if((status = sdfakescsirw(r, &lba, &count, &rw)) == SDcheck)
1588 n = mv50bio(r->unit, r->lun, rw, r->data, count, lba);
1596 mkrfis(SDreq *r, Drive *d, Edma *e)
1603 if((d->feat & Dllba) && (r->ataproto & P28) == 0){
1604 u[Frerror] = e->err;
1605 u[Fsc8] = e->seccnt;
1607 u[Flba24] = e->lba0;
1609 u[Flba32] = e->lba1;
1611 u[Flba40] = e->lba2;
1612 u[Flba16] = e->lba2;
1614 u[Fstatus] = e->cmdstat;
1616 u[Frerror] = e->err;
1620 u[Flba16] = e->lba2;
1622 u[Fstatus] = e->cmdstat;
1627 piocmd(SDreq *r, Drive *d)
1630 int n, nsec, i, err;
1636 if(waitready(d) != SDok)
1640 nsec = r->dlen / u->secsize;
1641 if(r->dlen < nsec*u->secsize)
1642 nsec = r->dlen/u->secsize;
1644 error("can't do more than 256 sectors");
1648 if(edmadisable(d, 0) == -1) {
1650 error("can't disable edma");
1652 n = satawait(&e->cmdstat, ATAdrdy|ATAbusy, ATAdrdy, 3*1000);
1654 print("piocmd: notready %.2ux\n", e->cmdstat);
1656 return sdsetsense(r, SDcheck, 4, 8, 0);
1659 if(r->ataproto & P28){
1660 e->altstat = ATAeIEN;
1665 e->lba2 = c[Flba16];
1667 e->cmdstat = c[Fcmd];
1669 e->altstat = ATAeIEN;
1670 e->seccnt = c[Fsc8];
1673 e->lba0 = c[Flba24];
1675 e->lba1 = c[Flba32];
1677 e->lba1 = c[Flba40];
1678 e->lba2 = c[Flba16];
1680 e->cmdstat = c[Fcmd];
1684 if((r->ataproto & Pdatam) == Pnd)
1685 n = satawait(&e->cmdstat, ATAbusy, 0, 3*1000);
1687 n = satawait(&e->cmdstat, ATAbusy|ATAdrq, ATAdrq, 3*1000);
1688 if(n == 0 || e->cmdstat & ATAerr){
1693 for(; nsec > 0; nsec--)
1694 for (i = 0; i < u->secsize; i += 2) {
1695 n = satawait(&e->cmdstat, ATAbusy|ATAdrq, ATAdrq, 300);
1701 if(r->ataproto & Pout){
1702 n = (ushort)p[i + 1] << 8;
1717 return sdsetsense(r, SDcheck, 4, 8, 0);
1719 return sdsetsense(r, SDok, 0, 0, 0);
1723 * hack to allow udma mode to be set or unset
1724 * via direct ata command. it would be better
1725 * to move the assumptions about dma mode out
1726 * of some of the helper functions.
1734 if(c[Fcmd] == 0xef && c[Ffeat] == 0x03){
1742 fisreqchk(Sfis *f, SDreq *r)
1744 if((r->ataproto & Pprotom) == Ppkt)
1747 * handle oob requests;
1748 * restrict & sanitize commands
1752 if(r->cmd[0] == 0xf0){
1753 sigtofis(f, r->cmd);
1764 badf(SDreq *r, Drive*)
1766 print("badf %.2ux %2ux\n", r->cmd[2], r->ataproto);
1767 return sdsetsense(r, SDcheck, 2, 24, 0);
1771 ataio0(SDreq *r, Drive *d)
1773 int (*f)(SDreq*, Drive*);
1776 switch(r->ataproto & Pprotom){
1797 d = c->drive + u->subno;
1798 if((status = fisreqchk(d, r)) != SDnostatus)
1801 USED(udm); /* botch */
1809 switch(status = ataio0(r, d)){
1811 dprint("%s: status %d\n", dnam(d), status);
1814 dprint("%s: retry\n", dnam(d));
1817 sdsetsense(r, SDok, 0, 0, 0);
1822 return r->status = status;
1826 SDifc sdmv50xxifc = {
1827 "mv50xx", /* name */
1831 mv50enable, /* enable */
1832 mv50disable, /* disable */
1834 mv50verify, /* verify */
1835 mv50online, /* online */
1837 mv50rctl, /* rctl */
1838 mv50wctl, /* wctl */
1849 * The original driver on which this one is based came with the
1855 * This software is provided `as-is,' without any express or implied
1856 * warranty. In no event will the author be held liable for any damages
1857 * arising from the use of this software.
1859 * Permission is granted to anyone to use this software for any purpose,
1860 * including commercial applications, and to alter it and redistribute it
1861 * freely, subject to the following restrictions:
1863 * 1. The origin of this software must not be misrepresented; you must
1864 * not claim that you wrote the original software. If you use this
1865 * software in a product, an acknowledgment in the product documentation
1866 * would be appreciated but is not required.
1868 * 2. Altered source versions must be plainly marked as such, and must
1869 * not be misrepresented as being the original software.
1871 * 3. This notice may not be removed or altered from any source