2 * Marvell 88SX[56]0[48][01] fileserver 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"
20 #include "../port/sd.h"
22 #define dprint if(!0){}else iprint
23 #define idprint if(!0){}else iprint
24 #define ioprint if(!0){}else iprint
29 NDrive = NCtlr*NCtlrdrv,
40 /* Addresses of ATA register */
57 ATAobs = (1<<1 | 1<<2 | 1<<4),
61 ATAbad = (ATAbusy|ATAdf|ATAdrq|ATAerr),
75 RQread = 1, /* data coming IN from device */
79 /* EDMA interrupt error cause register */
90 ePrtCRPBErr = (1<<10),
94 /* flags for sata 2 version */
98 /* EDMA Command Register */
104 /* Interrupt mask for errors we care about */
105 IEM = (eDevDis | eDevCon | eSelfDis),
106 IEM2 = (eDevDis | eDevCon | eSelfDis2),
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 */
124 /* phyerrata magic crap */
133 static char* diskstates[Dlast] = {
142 extern SDifc sdmv50xxifc;
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;
156 * there are 4 drives per chip. thus an 8-port
157 * card has two chips.
189 ulong pm2; /* phymode 2 init state */
190 ulong intick; /* check for hung western digital drives. */
192 int mode; /* DMautoneg, satai or sataii. */
208 int driveno; /* ctlr*NCtlrdrv + unit */
228 Drive drive[NCtlrdrv];
232 struct Srb /* request buffer */
253 * Memory-mapped I/O registers in many forms.
255 struct Bridge /* memory-mapped per-Drive registers */
271 }; /* length must be 0x100 */
273 struct Arb /* memory-mapped per-Chip registers */
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 */
288 struct Edma /* memory-mapped per-Drive DMA-related registers */
290 ulong config; /* configuration register */
292 ulong iec; /* interrupt error cause */
293 ulong iem; /* interrupt error mask */
295 ulong txbasehi; /* request queue base address high */
296 ulong txi; /* request queue in pointer */
297 ulong txo; /* request queue out pointer */
299 ulong rxbasehi; /* response queue base address high */
300 ulong rxi; /* response queue in pointer */
301 ulong rxo; /* response queue out pointer */
303 ulong ctl; /* command register */
304 ulong testctl; /* test control */
306 ulong iordyto; /* IORDY timeout */
308 ulong sataconfig; /* sata 2 */
310 ushort pio; /* data register */
312 uchar err; /* features and error */
314 uchar seccnt; /* sector count */
324 uchar cmdstat; /* cmd/status */
326 uchar altstat; /* alternate status */
329 char fill3[0x1c00]; /* pad to 0x2000 bytes */
333 * Memory structures shared with card.
335 struct Prd /* physical region descriptor */
337 ulong pa; /* byte address of physical memory */
338 ushort count; /* byte count (bit0 must be 0) */
340 ulong zero; /* high long of 64 bit address */
344 struct Tx /* command request block */
346 ulong prdpa; /* physical region descriptor table structures */
347 ulong zero; /* must be zero (high long of prd address) */
348 ushort flag; /* control flags */
352 struct Rx /* command response block */
354 ushort cid; /* cID of response */
355 uchar cEdmaSts; /* EDMA status */
356 uchar cDevSts; /* status from disk */
357 ulong ts; /* time stamp */
360 static Drive *mvsatadrive[NDrive];
361 static int nmvsatadrive;
364 * Little-endian parsing for drive data.
370 return ((ushort) a[1] << 8) | a[0];
377 return ((ulong) lhgets(a+2) << 16) | lhgets(a);
384 return ((uvlong) lhgetl(a+4) << 32) | lhgetl(a);
388 idmove(char *p, ushort *a, int n)
394 for(i=0; i<n/2; i++){
398 while(p>op && *--p == ' ')
418 if((p = srblist.freechain) == nil){
421 p = smalloc(sizeof *p);
423 srblist.freechain = p->next;
433 p->next = srblist.freechain;
434 srblist.freechain = p;
439 * Wait for a byte to be a particular value.
442 satawait(uchar *p, uchar mask, uchar v, int ms)
446 for(i=0; i<ms && (*p & mask) != v; i++)
448 return (*p & mask) == v;
452 * Drive initialization
454 /* unmask in the pci registers err done */
456 unmask(ulong *mmio, int port, int coal)
462 mmio[0x1d64/4] |= (3 << (((port&3)*2)) | (coal<<8));
464 mmio[0x1d64/4] |= (3 << (((port&3)*2+9)) | (coal<<17));
468 mask(ulong *mmio, int port, int coal)
474 mmio[0x1d64/4] &= ~(3 << (((port&3)*2)) | (coal<<8));
476 mmio[0x1d64/4] &= ~(3 << (((port&3)*2+9)) | (coal<<17));
479 /* I give up, marvell. You win. */
484 enum { BadAutoCal = 0xf << 26, };
486 if (d->ctlr->type == 1)
489 n = d->bridge->phymode2;
490 while ((n & BadAutoCal) == BadAutoCal) {
491 dprint("%s: badautocal\n", d->unit->name);
494 d->bridge->phymode2 = n;
496 d->bridge->phymode2 &= ~((1<<16) | (1<<31));
498 n = d->bridge->phymode2;
501 d->bridge->phymode2 = n;
504 /* abra cadabra! (random magic) */
505 m = d->bridge->phymode3;
508 d->bridge->phymode3 = m;
511 m = d->bridge->phymode3;
512 n = d->bridge->phymode4;
515 switch(d->ctlr->rid){
518 d->bridge->phymode4 = n;
519 d->bridge->phymode3 = m;
522 d->bridge->phymode4 = n;
526 /* revert values of pre-emphasis and signal amps to the saved ones */
527 n = d->bridge->phymode2;
531 d->bridge->phymode2 = n;
535 edmacleanout(Drive *d)
540 for(i=0; i<nelem(d->srb); i++){
544 srb->flag |= SFerror|SFdone;
548 while(srb = d->srbhead){
549 d->srbhead = srb->next;
550 srb->flag |= SFerror|SFdone;
561 d->unit->sectors = 0;
562 if (d->ctlr->type == 2) {
564 * without bit 8 we can boot without disks, but
565 * inserted disks will never appear. :-X
567 n = d->edma->sataconfig;
570 d->edma->sataconfig = n;
571 n = d->edma->sataconfig; /* flush */
574 d->edma->ctl = eDsEDMA;
576 d->edma->ctl = eAtaRst;
579 if (satawait((uchar *)&d->edma->ctl, eEnEDMA, 0, 3*1000) == 0)
580 print("%s: eEnEDMA never cleared on reset\n", d->unit->name);
583 d->bridge->sctrl = 0x301 | (d->mode << 4);
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]);
604 configdrive(Ctlr *ctlr, Drive *d, SDunit *unit)
606 dprint("%s: configdrive\n", unit->name);
608 panic("mv50xx: configdrive: unset driveno\n");
612 if(d->ctlr->type == 1){
614 d->bridge = &d->chip->arb->bridge[d->chipx];
617 d->bridge = &d->chip->edma[d->chipx].port;
618 d->edma->iem = ~(1<<6);
620 if(d->ctlr->lmmio[0x180d8/4] & 1)
621 d->pm2 = d->bridge->phymode2 & Mpreamp;
624 unmask(ctlr->lmmio, d->driveno, 0);
626 if(d->bridge->status){
627 dprint("%s: configdrive: found drive %lx\n", unit->name, d->bridge->status);
634 enabledrive(Drive *d)
638 dprint("%s: enabledrive..", d->unit->name);
640 if((d->bridge->status & 0xf) != 3){
641 dprint("%s: not present\n", d->unit->name);
646 if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0){
647 dprint("%s: busy timeout\n", d->unit->name);
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 */
662 if(d->bridge->status = 0x113){
663 dprint("%s: new\n", d->unit->name);
666 print("%s: status not forced (should be okay)\n", d->unit->name);
671 disabledrive(Drive *d)
676 dprint("%s: disabledrive\n", d->unit->name);
678 if(d->tx == nil) /* never enabled */
684 r = (ulong*)(d->ctlr->mmio + 0x1d64);
689 *r |= ~(3 << (i*2+9));
693 setudmamode(Drive *d, uchar mode)
697 dprint("%s: setudmamode %d\n", d->unit->name, mode);
701 iprint("setudamode(m%d): zero d->edma\m", d->driveno);
704 if(satawait(&edma->cmdstat, ~ATAobs, ATAdrdy, 9*1000) == 0){
705 iprint("%s: cmdstat 0x%.2ux ready timeout\n", d->unit->name, edma->cmdstat);
708 edma->altstat = ATAeIEN;
710 edma->seccnt = 0x40 | mode;
711 edma->cmdstat = 0xef;
713 if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0){
714 iprint("%s: cmdstat 0x%.2ux busy timeout\n", d->unit->name, edma->cmdstat);
721 identifydrive(Drive *d)
728 dprint("%s: identifydrive\n", d->unit->name);
730 if(setudmamode(d, 5) == 0) /* do all SATA support 5? */
734 memset(d->info, 0, sizeof d->info);
736 if(satawait(&edma->cmdstat, ~ATAobs, ATAdrdy, 5*1000) == 0)
739 edma->altstat = ATAeIEN; /* no interrupts */
740 edma->cmdstat = 0xec;
742 if(satawait(&edma->cmdstat, ATAbusy, 0, 5*1000) == 0)
744 for(i = 0; i < 256; i++)
746 if(edma->cmdstat & ATAbad)
748 i = lhgets(id+83) | lhgets(id+86);
751 d->sectors = lhgetv(id+100);
754 d->sectors = lhgetl(id+60);
756 idmove(d->serial, id+10, 20);
757 idmove(d->firmware, id+23, 8);
758 idmove(d->model, id+27, 40);
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);
767 if(enabledrive(d) == 0) {
770 idprint("%s: LLBA %lld sectors\n", d->unit->name, d->sectors);
773 if(d->state == Dready)
787 B 8-to-10 encoding error
791 S link sequence error
792 T transport state transition error
793 F unrecognized fis type
797 static char stab[] = {
801 [18] 'W', 'B', 'D', 'C', 'H', 'S', 'T', 'F', 'X'
803 static ulong sbad = (7<<20)|(3<<23);
806 serrdecode(ulong r, char *s, char *e)
811 for(i = 0; i < nelem(stab) && s < e; i++){
812 if((r&(1<<i)) && stab[i]){
838 iecdecode(ulong cause)
842 for(i = 0; i < nelem(iectab); i++)
849 Cerror = ePrtDataErr|ePrtPRDErr|eDevErr|eSelfDis2|ePrtCRPBErr|ePrtIntErr,
853 updatedrive(Drive *d)
861 if((edma->ctl&eEnEDMA) == 0){
862 /* FEr SATA#4 40xx */
863 x = d->edma->cmdstat;
869 dprint("%s: cause %08ulx [%s]\n", d->unit->name, cause, iecdecode(cause));
872 if(cause&eDevDis && d->state == Dready)
873 iprint("%s: pulled: st=%08ulx\n", d->unit->name, cause);
874 switch(d->ctlr->type){
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;
895 srbrw(int req, Drive *d, uchar *data, uint sectors, uvlong lba)
899 static uchar cmd[2][2] = { 0xC8, 0x25, 0xCA, 0x35 };
905 srb->sectors = sectors;
906 srb->count = sectors*512;
911 srb->lba[i] = lba >> (8*i);
912 srb->cmd = cmd[srb->req!=SRBread][(d->flag&Dext)!=0];
917 advance(uintptr pa, int shift)
922 n = (pa & mask) + (1<<shift);
923 return (pa & ~mask) | (n & mask);
926 #define CMD(r, v) (((r)<<8) | ((v)&0xFF))
928 mvsatarequest(ushort *cmd, Srb *srb, int ext)
930 *cmd++ = CMD(ARseccnt, 0);
931 *cmd++ = CMD(ARseccnt, srb->sectors);
932 *cmd++ = CMD(ARfea, 0);
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);
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);
947 *cmd = CMD(ARcmd, srb->cmd) | (1<<15);
951 startsrb(Drive *d, Srb *srb)
958 if(d->nsrb >= nelem(d->srb)){
961 d->srbtail->next = srb;
969 for(i=0; i<nelem(d->srb); i++)
972 if(i == nelem(d->srb))
973 panic("sdmv50xx: no free srbs");
974 d->intick = MACHP(0)->ticks;
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;
983 mvsatarequest(tx->regs, srb, d->flag&Dext);
985 edma->txi = advance(edma->txi, 5);
986 d->intick = MACHP(0)->ticks;
994 completesrb(Drive *d)
1001 if((edma->ctl & eEnEDMA) == 0)
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;
1009 if(rx->cDevSts & ATAbad)
1010 srb->flag |= SFerror;
1012 iprint("cEdmaSts: %02ux\n", rx->cEdmaSts);
1013 srb->sta = rx->cDevSts;
1014 srb->flag |= SFdone;
1017 iprint("srb missing\n");
1018 edma->rxo = advance(edma->rxo, 3);
1019 if(srb = d->srbhead){
1020 d->srbhead = srb->next;
1032 return srb->flag & SFdone;
1039 mv50interrupt(Ureg*, void *a)
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. */
1057 while(ctlr->chip[i/4].arb->ic & (0x0101 << (i%4))){
1058 ctlr->chip[i/4].arb->ic = ~(0x101 << (i%4));
1068 Midwait = 16*1024/Nms-1,
1069 Mphywait = 512/Nms-1,
1073 westerndigitalhung(Drive *d)
1079 && TK2MS(MACHP(0)->ticks-d->intick) > 5*1000
1080 && (e->rxo&Rpidx) == (e->rxi&Rpidx)){
1081 dprint("westerndigital drive hung; resetting\n");
1087 checkdrive(Drive *d, int i)
1089 static ulong s, olds[NCtlr*NCtlrdrv];
1093 name = d->unit->name;
1094 s = d->bridge->status;
1096 dprint("%s: status: %08lx -> %08lx: %s\n", name, olds[i], s, diskstates[d->state]);
1099 /* westerndigitalhung(d); */
1107 dprint("%s: unknown state %8lx\n", name, s);
1109 if(++d->wait&Mphywait)
1111 reset: d->mode ^= 1;
1112 dprint("%s: reset; new mode %d\n", name, d->mode);
1117 s = d->edma->cmdstat;
1118 if(s == 0x7f || (s&~ATAobs) != ATAdrdy){
1119 if((++d->wait&Midwait) == 0)
1121 }else if(identifydrive(d) == -1)
1128 iprint("%s: pulled: st=%08ulx\n", name, s); /* never happens */
1131 dprint("%s reset: mode %d\n", name, d->mode);
1147 tsleep(&up->sleep, return0, 0, Nms);
1148 for(i = 0; i < nmvsatadrive; i++)
1149 checkdrive(mvsatadrive[i], i);
1164 SDev *head, *tail, *sdev;
1166 static int ctlrno, done;
1168 dprint("mv50pnp\n");
1175 while((p = pcimatch(p, 0x11ab, 0)) != nil){
1185 print("mv50pnp: unknown did %ux ignored\n", (ushort)p->did);
1188 if (ctlrno >= NCtlr) {
1189 print("mv50pnp: too many controllers\n");
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)
1199 if((ctlr = malloc(sizeof(Ctlr))) == nil){
1203 memset(sdev, 0, sizeof *sdev);
1204 memset(ctlr, 0, sizeof *ctlr);
1206 io = p->mem[0].bar & ~0x0F;
1207 mem = (ulong*)vmap(io, p->mem[0].size);
1209 print("sdmv50xx: address 0x%luX in use\n", io);
1216 /* avert thine eyes! (what does this do?) */
1218 ctlr->type = (p->did >> 12) & 3;
1219 if(ctlr->type == 1){
1225 sdev->ifc = &sdmv50xxifc;
1227 sdev->nunit = nunit;
1230 ctlr->irq = p->intl;
1231 ctlr->tbdf = p->tbdf;
1234 ctlr->mmio = (uchar*)mem;
1235 ctlr->nchip = (nunit+3)/4;
1236 ctlr->ndrive = nunit;
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);
1243 for (i = 0; i < nunit; i++) {
1244 d = &ctlr->drive[i];
1247 d->driveno = ctlrno*NCtlrdrv + i;
1249 d->chip = &ctlr->chip[i/4];
1250 d->edma = &d->chip->edma[d->chipx];
1251 mvsatadrive[d->driveno] = d;
1253 nmvsatadrive += nunit;
1265 * Enable the controller. Each disk has its own interrupt mask,
1266 * and those get enabled as the disks are brought online.
1269 mv50enable(SDev *sdev)
1274 dprint("sd%c: enable\n", sdev->idno);
1279 snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
1280 intrenable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
1286 * Disable the controller.
1289 mv50disable(SDev *sdev)
1296 dprint("sd%c: disable\n", sdev->idno);
1300 for(i=0; i<ctlr->sdev->nunit; i++){
1301 drive = &ctlr->drive[i];
1303 disabledrive(drive);
1307 snprint(name, sizeof name, "%s (%s)", sdev->name, sdev->ifc->name);
1308 intrdisable(ctlr->irq, mv50interrupt, ctlr, ctlr->tbdf, name);
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.
1318 mv50clear(SDev *sdev)
1324 dprint("sd%c: clear\n", sdev->idno);
1327 for(i=0; i<ctlr->ndrive; i++){
1328 d = &ctlr->drive[i];
1337 * Check that there is a disk or at least a hot swap bay in the drive.
1340 mv50verify(SDunit *unit)
1346 dprint("%s: verify\n", unit->name);
1347 ctlr = unit->dev->ctlr;
1348 drive = &ctlr->drive[unit->subno];
1351 i = configdrive(ctlr, drive, unit);
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.
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).
1365 if(ctlr->type != 1 && i == 0){
1367 tsleep(&up->sleep, return0, 0, 1500);
1375 * Check whether the disk is online.
1378 mv50online(SDunit *unit)
1386 kproc("mvsata", satakproc, 0);
1388 ctlr = unit->dev->ctlr;
1389 d = &ctlr->drive[unit->subno];
1394 if(d->state == Dnew)
1397 idprint("%s: online: %s -> %s\n", unit->name, diskstates[s0], diskstates[d->state]);
1399 unit->sectors = d->sectors;
1400 unit->secsize = 512;
1402 } else if(d->state == Dready)
1411 typedef struct Regs Regs;
1418 static Regs regsctlr[] =
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",
1431 static Regs regsarb[] =
1443 static Regs regsbridge[] =
1445 0x0000, "bridge status",
1446 0x0004, "bridge serror",
1447 0x0008, "bridge sctrl",
1448 0x000C, "bridge phyctrl",
1449 0x003C, "bridge ctrl",
1450 0x0074, "bridge phymode",
1453 static Regs regsedma[] =
1455 0x0000, "edma config",
1456 0x0004, "edma timer",
1459 0x0010, "edma txbasehi",
1462 0x001C, "edma rxbasehi",
1467 0x0030, "edma status",
1468 0x0034, "edma iordyto",
1469 /* 0x0100, "edma pio",
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",
1482 rdregs(char *p, char *e, void *base, Regs *r, int n, char *prefix)
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));
1494 rdinfo(char *p, char *e, ushort *info)
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": "");
1506 mv50rctl(SDunit *unit, char *p, int l)
1512 if((ctlr = unit->dev->ctlr) == nil)
1514 drive = &ctlr->drive[unit->subno];
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);
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);
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);
1535 mv50wctl(SDunit *unit, Cmdbuf *cb)
1541 if(strcmp(cb->f[0], "reset") == 0){
1542 ctlr = unit->dev->ctlr;
1543 drive = &ctlr->drive[unit->subno];
1545 drive->state = Dreset;
1549 cmderror(cb, Ebadctl);
1554 * sd(3): ``Reading /dev/sdctl yields information about each controller,
1555 * one line per controller.''
1558 mv50rtopctl(SDev *sdev, char *p, char *e)
1567 snprint(name, sizeof name, "sd%c", sdev->idno);
1568 p = rdregs(p, e, ctlr->mmio, regsctlr, nelem(regsctlr), name);
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);
1586 for(i = 0; i < 120; i++){
1588 s = d->bridge->status;
1592 if (d->state == Dready)
1600 tsleep(&up->sleep, return0, 0, 1000);
1604 print("%s: not responding after 2 minutes\n", d->unit->name);
1611 int count, max, n, status, try, flag;
1620 ctlr = unit->dev->ctlr;
1621 drive = &ctlr->drive[unit->subno];
1624 if((status = sdfakescsi(r, drive->info, sizeof drive->info)) != SDnostatus){
1625 /* XXX check for SDcheck here */
1631 case 0x28: /* read */
1632 case 0x2A: /* write */
1635 iprint("%s: bad cmd 0x%.2ux\n", drive->unit->name, cmd[0]);
1636 r->status = SDcheck;
1640 lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5];
1641 count = (cmd[7]<<8)|cmd[8];
1644 if(r->dlen < count*unit->secsize)
1645 count = r->dlen/unit->secsize;
1649 if(waitready(drive) != SDok)
1652 * Could arrange here to have an Srb always outstanding:
1655 * while(count > 0 || lsrb != nil){
1658 * srb = issue next srb;
1661 * sleep on lsrb and handle it
1665 * On the disks I tried, this didn't help. If anything,
1666 * it's a little slower. -rsc
1671 * Max is 128 sectors (64kB) because prd->count is 16 bits.
1677 if((drive->edma->ctl&eEnEDMA) == 0)
1679 srb = srbrw(cmd[0]==0x28 ? SRBread : SRBwrite, drive, data, n, lba);
1681 startsrb(drive, srb);
1684 /* Don't let user interrupt DMA. */
1687 sleep(srb, srbdone, srb);
1695 print("%s: bad disk\n", drive->unit->name);
1698 dprint("%s: retry\n", drive->unit->name);
1700 tsleep(&up->sleep, return0, 0, 1000);
1706 print("%s: i/o error\n", drive->unit->name);
1711 data += n*unit->secsize;
1713 r->rlen = data - (uchar*)r->data;
1717 SDifc sdmv50xxifc = {
1718 "mv50xx", /* name */
1722 mv50enable, /* enable */
1723 mv50disable, /* disable */
1725 mv50verify, /* verify */
1726 mv50online, /* online */
1728 mv50rctl, /* rctl */
1729 mv50wctl, /* wctl */
1733 mv50clear, /* clear */
1734 mv50rtopctl, /* rtopctl */
1738 * The original driver on which this one is based came with the
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.
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:
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.
1757 * 2. Altered source versions must be plainly marked as such, and must
1758 * not be misrepresented as being the original software.
1760 * 3. This notice may not be removed or altered from any source