]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/pc/sdide.c
pc/ether*: use 64-bit physical addresses and check pci membar types and sizes
[plan9front.git] / sys / src / 9 / pc / sdide.c
index dfe6ef76397be793c48e2cccc7a38f68bccd35cb..7da95b2e8e3e2e8851589e1ef2236520af9fd777 100644 (file)
@@ -393,7 +393,7 @@ atadumpstate(Drive* drive, SDreq *r, uvlong lba, int count)
                prd = ctlr->prdt;
                print("bmicx %2.2uX bmisx %2.2uX prdt %8.8p\n",
                        inb(bmiba+Bmicx), inb(bmiba+Bmisx), prd);
-               for(;;){
+               while(prd){
                        print("pa 0x%8.8luX count %8.8uX\n",
                                prd->pa, prd->count);
                        if(prd->count & PrdEOT)
@@ -417,8 +417,12 @@ atadebug(int cmdport, int ctlport, char* fmt, ...)
        int i;
        va_list arg;
 
-       if(!(DEBUG & DbgPROBE))
+       if(!(DEBUG & DbgPROBE)){
+               USED(cmdport);
+               USED(ctlport);
+               USED(fmt);
                return;
+       }
 
        p = buf;
        e = buf + sizeof buf;
@@ -562,36 +566,31 @@ ataidentify(Ctlr*, int cmdport, int ctlport, int dev, int pkt, void* info)
        dev &= ~Lba;
        as = ataready(cmdport, ctlport, dev, Bsy|Drq, drdy, 103*1000);
        if(as < 0)
-               return as;
+               return -1;
        outb(cmdport+Command, command);
        microdelay(1);
 
        as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 400*1000);
-       if(as < 0)
-               return -1;
-       if(as & Err)
+       if(as < 0 || (as & Err))
                return as;
-
        memset(info, 0, 512);
        inss(cmdport+Data, info, 256);
-       ataready(cmdport, ctlport, dev, Bsy|Drq, Drdy, 3*1000);
        inb(cmdport+Status);
-
        return 0;
 }
 
 static Drive*
 atadrive(SDunit *unit, Drive *drive, int cmdport, int ctlport, int dev)
 {
-       int as, pkt;
+       int as, pkt, rlo, rhi;
        uchar buf[512], oserial[21];
        uvlong osectors;
        Ctlr *ctlr;
 
        if(DEBUG & DbgIDENTIFY)
                print("identify: port %ux dev %.2ux\n", cmdport, dev & ~Lba);
+
        atadebug(0, 0, "identify: port 0x%uX dev 0x%2.2uX\n", cmdport, dev);
-       pkt = 1;
        if(drive != nil){
                osectors = drive->sectors;
                memmove(oserial, drive->serial, sizeof drive->serial);
@@ -600,7 +599,20 @@ atadrive(SDunit *unit, Drive *drive, int cmdport, int ctlport, int dev)
                osectors = 0;
                memset(oserial, 0, sizeof drive->serial);
                ctlr = nil;
+
+               /* detect if theres a drive present */
+               outb(cmdport+Dh, dev & ~Lba);
+               microdelay(1);
+               outb(cmdport+Cyllo, 0xAA);
+               outb(cmdport+Cylhi, 0x55);
+               outb(cmdport+Sector, 0xFF);
+               rlo = inb(cmdport+Cyllo);
+               rhi = inb(cmdport+Cylhi);
+               if(rlo != 0xAA && (rlo == 0xFF || rhi != 0x55))
+                       return nil;
        }
+
+       pkt = 1;
 retry:
        as = ataidentify(ctlr, cmdport, ctlport, dev, pkt, buf);
        if(as < 0)
@@ -621,7 +633,7 @@ retry:
 
        memmove(drive->info, buf, sizeof(drive->info));
 
-       setfissig(drive, pkt? 0xeb140000: 0x0101);
+       setfissig(drive, pkt ? 0xeb140000 : 0x0101);
        drive->sectors = idfeat(drive, drive->info);
        drive->secsize = idss(drive, drive->info);
 
@@ -686,24 +698,12 @@ atasrst(int ctlport)
        microdelay(2*1000);
 }
 
-static int
-seldev(int dev, int map)
-{
-       if((dev & Devs) == Dev0 && map&1)
-               return dev;
-       if((dev & Devs) == Dev1 && map&2)
-               return dev;
-       return -1;
-}
-
 static SDev*
 ataprobe(int cmdport, int ctlport, int irq, int map)
 {
+       static int nonlegacy = 'C';
        Ctlr* ctlr;
        SDev *sdev;
-       Drive *drive;
-       int dev, error, rhi, rlo;
-       static int nonlegacy = 'C';
 
        if(ioalloc(cmdport, 8, 0, "atacmd") < 0) {
                print("ataprobe: Cannot allocate %X\n", cmdport);
@@ -715,142 +715,32 @@ ataprobe(int cmdport, int ctlport, int irq, int map)
                return nil;
        }
 
-       /*
-        * Try to detect a floating bus.
-        * Bsy should be cleared. If not, see if the cylinder registers
-        * are read/write capable.
-        * If the master fails, try the slave to catch slave-only
-        * configurations.
-        * There's no need to restore the tested registers as they will
-        * be reset on any detected drives by the Cedd command.
-        * All this indicates is that there is at least one drive on the
-        * controller; when the non-existent drive is selected in a
-        * single-drive configuration the registers of the existing drive
-        * are often seen, only command execution fails.
-        */
-       if((dev = seldev(Dev0, map)) == -1)
-       if((dev = seldev(Dev1, map)) == -1)
+       if((ctlr = malloc(sizeof(Ctlr))) == nil)
                goto release;
-       if(inb(ctlport+As) & Bsy){
-               outb(cmdport+Dh, dev);
-               microdelay(1);
-trydev1:
-               atadebug(cmdport, ctlport, "ataprobe bsy");
-               outb(cmdport+Cyllo, 0xAA);
-               outb(cmdport+Cylhi, 0x55);
-               outb(cmdport+Sector, 0xFF);
-               rlo = inb(cmdport+Cyllo);
-               rhi = inb(cmdport+Cylhi);
-               if(rlo != 0xAA && (rlo == 0xFF || rhi != 0x55)){
-                       if(dev == Dev1 || (dev = seldev(Dev1, map)) == -1){
-release:
-                               outb(cmdport+Dc, Nien);
-                               inb(cmdport+Status);
-                               /* further measures to prevent irqs? */
-                               iofree(cmdport);
-                               iofree(ctlport+As);
-                               return nil;
-                       }
-                       if(ataready(cmdport, ctlport, dev, Bsy, 0, 20*1000) < 0)
-                               goto trydev1;
-               }
-       }
-
-       /*
-        * Disable interrupts on any detected controllers.
-        */
-       outb(ctlport+Dc, Nien);
-tryedd1:
-       if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 105*1000) < 0){
-               /*
-                * There's something there, but it didn't come up clean,
-                * so try hitting it with a big stick. The timing here is
-                * wrong but this is a last-ditch effort and it sometimes
-                * gets some marginal hardware back online.
-                */
-               atasrst(ctlport);
-               if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 106*1000) < 0)
-                       goto release;
-       }
-
-       /*
-        * Can only get here if controller is not busy.
-        * If there are drives Bsy will be set within 400nS,
-        * must wait 2mS before testing Status.
-        * Wait for the command to complete (6 seconds max).
-        */
-       outb(cmdport+Command, Cedd);
-       delay(2);
-       if(ataready(cmdport, ctlport, dev, Bsy|Drq, 0, 6*1000*1000) < 0)
+       if((sdev = malloc(sizeof(SDev))) == nil){
+               free(ctlr);
                goto release;
-
-       /*
-        * If bit 0 of the error register is set then the selected drive
-        * exists. This is enough to detect single-drive configurations.
-        * However, if the master exists there is no way short of executing
-        * a command to determine if a slave is present.
-        * It appears possible to get here testing Dev0 although it doesn't
-        * exist and the EDD won't take, so try again with Dev1.
-        */
-       error = inb(cmdport+Error);
-       atadebug(cmdport, ctlport, "ataprobe: dev %uX", dev);
-       if((error & ~0x80) != 0x01){
-               if(dev == Dev1)
-                       goto release;
-               if((dev = seldev(Dev1, map)) == -1)
-                       goto release;
-               goto tryedd1;
        }
 
-       /*
-        * At least one drive is known to exist, try to
-        * identify it. If that fails, don't bother checking
-        * any further.
-        * If the one drive found is Dev0 and the EDD command
-        * didn't indicate Dev1 doesn't exist, check for it.
-        */
-       if((drive = atadrive(0, 0, cmdport, ctlport, dev)) == nil)
-               goto release;
-       if((ctlr = malloc(sizeof(Ctlr))) == nil){
-               free(drive);
-               goto release;
-       }
-       if((sdev = malloc(sizeof(SDev))) == nil){
+       if((map & 2) && (ctlr->drive[1] = atadrive(0, 0, cmdport, ctlport, Dev1)))
+               ctlr->drive[1]->ctlr = ctlr;
+       if((map & 1) && (ctlr->drive[0] = atadrive(0, 0, cmdport, ctlport, Dev0)))
+               ctlr->drive[0]->ctlr = ctlr;
+
+       if(ctlr->drive[0] == nil && ctlr->drive[1] == nil){
+               free(ctlr->drive[0]);
+               free(ctlr->drive[1]);
                free(ctlr);
-               free(drive);
+               free(sdev);
                goto release;
        }
-       drive->ctlr = ctlr;
-       if(dev == Dev0){
-               ctlr->drive[0] = drive;
-               if(!(error & 0x80)){
-                       /*
-                        * Always leave Dh pointing to a valid drive,
-                        * otherwise a subsequent call to ataready on
-                        * this controller may try to test a bogus Status.
-                        * Ataprobe is the only place possibly invalid
-                        * drives should be selected.
-                        */
-                       drive = atadrive(0, 0, cmdport, ctlport, Dev1);
-                       if(drive != nil){
-                               drive->ctlr = ctlr;
-                               ctlr->drive[1] = drive;
-                       }
-                       else{
-                               outb(cmdport+Dh, Dev0);
-                               microdelay(1);
-                       }
-               }
-       }
-       else
-               ctlr->drive[1] = drive;
 
        ctlr->cmdport = cmdport;
        ctlr->ctlport = ctlport;
        ctlr->irq = irq;
        ctlr->tbdf = BUSUNKNOWN;
-       ctlr->command = Cedd;           /* debugging */
-       
+       ctlr->command = Cnop;           /* debugging */
+
        switch(cmdport){
        default:
                sdev->idno = nonlegacy;
@@ -870,6 +760,12 @@ tryedd1:
        ctlr->sdev = sdev;
 
        return sdev;
+
+release:
+       iofree(cmdport);
+       iofree(ctlport+As);
+
+       return nil;
 }
 
 static void
@@ -1174,7 +1070,7 @@ static int
 atapktio0(Drive *drive, SDreq *r)
 {
        uchar *cmd;
-       int as, cmdport, ctlport, len, rv;
+       int as, len, cmdport, ctlport, rv;
        Ctlr *ctlr;
 
        rv = SDok;
@@ -1188,22 +1084,17 @@ atapktio0(Drive *drive, SDreq *r)
        cmdport = ctlr->cmdport;
        ctlport = ctlr->ctlport;
 
-       as = ataready(cmdport, ctlport, drive->dev, Bsy|Drq, Drdy, 107*1000);
+       as = ataready(cmdport, ctlport, drive->dev, Bsy|Drq, 0, 107*1000);
        /* used to test as&Chk as failure too, but some CD readers use that for media change */
        if(as < 0)
                return SDnostatus;
 
        ilock(ctlr);
-       if(drive->dlen && drive->dmactl && !atadmasetup(drive, drive->dlen)){
+       if(drive->dlen && drive->dmactl && !atadmasetup(drive, drive->dlen))
                drive->pktdma = Dma;
-               len = 0;                /* bytecount should be 0 for dma */
-       }else{
+       else
                drive->pktdma = 0;
-               if(drive->secsize)
-                       len = 16*drive->secsize;
-               else
-                       len = 0x8000;
-       }
+       len = drive->secsize > 0 ? 16*drive->secsize : 0x8000;
        outb(cmdport+Features, drive->pktdma);
        outb(cmdport+Count, 0);
        outb(cmdport+Sector, 0);
@@ -1215,26 +1106,27 @@ atapktio0(Drive *drive, SDreq *r)
        ctlr->command = Cpkt;           /* debugging */
        outb(cmdport+Command, Cpkt);
 
-       if((drive->info[Iconfig] & Mdrq) != 0x0020){
-               microdelay(1);
-               as = ataready(cmdport, ctlport, 0, Bsy, Drq|Chk, 4*1000);
-               if(as < 0 || (as & (Bsy|Chk))){
-                       drive->status = as<0 ? 0 : as;
-                       ctlr->curdrive = nil;
-                       ctlr->done = 1;
-                       rv = SDtimeout;
-               }else
-                       atapktinterrupt(drive);
-       }
+       microdelay(1);
+       as = ataready(cmdport, ctlport, 0, Bsy, Drq|Chk, 400*1000);
+       if(as < 0 || (as & (Bsy|Chk))){
+               drive->status = as<0 ? 0 : as;
+               ctlr->curdrive = nil;
+               ctlr->done = 1;
+               rv = SDtimeout;
+       }else
+               atapktinterrupt(drive);
        if(drive->pktdma)
                atadmastart(ctlr, drive->write);
        iunlock(ctlr);
 
-       if(iowait(drive, 20*1000, 1) <= 0){
-               ilock(ctlr);
+       while(iowait(drive, 30*1000, 1) == 0)
+               ;
+
+       ilock(ctlr);
+       if(!ctlr->done){
+               rv = SDcheck;
                ataabort(drive, 0);
-       } else
-               ilock(ctlr);
+       }
        if(drive->error){
                if(drive->pktdma)
                        atadmastop(ctlr);
@@ -1243,8 +1135,13 @@ atapktio0(Drive *drive, SDreq *r)
        }
        iunlock(ctlr);
 
-       if(drive->status & Chk)
+       if(rv != SDcheck && drive->status & Chk){
                rv = SDcheck;
+               if(drive->pktdma){
+                       print("atapktio: disabling dma\n");
+                       drive->dmactl = 0;
+               }
+       }
        return rv;
 }
 
@@ -1271,7 +1168,7 @@ static uchar cmd48[256] = {
 };
 
 enum{
-       Last28  = (1<<28) - 1 - 1,
+       Last28  = (1<<28) - 1,
 };
 
 static int
@@ -1282,7 +1179,7 @@ atageniostart(Drive* drive, uvlong lba)
        int as, c, cmdport, ctlport, h, len, s, use48;
 
        use48 = 0;
-       if((drive->flags&Lba48always) || lba > Last28 || drive->count > 256){
+       if((drive->flags&Lba48always) || (lba+drive->count) > Last28 || drive->count > 256){
                if((drive->feat & Dllba) == 0)
                        return -1;
                use48 = 1;
@@ -1360,8 +1257,7 @@ atageniostart(Drive* drive, uvlong lba)
        case Cws:
        case Cwsm:
                microdelay(1);
-               /* 10*1000 for flash ide drives - maybe detect them? */
-               as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 10*1000);
+               as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 400*1000);
                if(as < 0 || (as & Err)){
                        iunlock(ctlr);
                        return -1;
@@ -1442,7 +1338,7 @@ atagenio(Drive* drive, SDreq *r)
                        qunlock(ctlr);
                        return atagenioretry(drive, r, lba, count);
                }
-               iowait(drive, 60*1000, 0);
+               iowait(drive, 30*1000, 0);
                if(!ctlr->done){
                        /*
                         * What should the above timeout be? In
@@ -1479,10 +1375,8 @@ atario(SDreq* r)
        SDunit *unit;
 
        unit = r->unit;
-       if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil){
-               r->status = SDtimeout;
-               return SDtimeout;
-       }
+       if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil)
+               return r->status = SDtimeout;
        drive = ctlr->drive[unit->subno];
        qlock(drive);
        for(;;){
@@ -1541,7 +1435,7 @@ atagenatastart(Drive* d, SDreq *r)
        ctlr = d->ctlr;
        cmdport = ctlr->cmdport;
        ctlport = ctlr->ctlport;
-       if(ataready(cmdport, ctlport, d->dev, Bsy|Drq, d->pkt? 0: Drdy, 101*1000) < 0)
+       if(ataready(cmdport, ctlport, d->dev, Bsy|Drq, d->pkt ? 0 : Drdy, 101*1000) < 0)
                return -1;
 
        ilock(ctlr);
@@ -1583,8 +1477,7 @@ atagenatastart(Drive* d, SDreq *r)
                USED(d);
        else if(!isdma){
                microdelay(1);
-               /* 10*1000 for flash ide drives - maybe detect them? */
-               as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 10*1000);
+               as = ataready(cmdport, ctlport, 0, Bsy, Drq|Err, 400*1000);
                if(as < 0 || (as & Err)){
                        iunlock(ctlr);
                        return -1;
@@ -1894,11 +1787,8 @@ atainterrupt(Ureg*, void* arg)
                if(ctlr->irqack != nil)
                        ctlr->irqack(ctlr);
                iunlock(ctlr);
-               if((DEBUG & DbgINL) && ctlr->command != Cedd)
-                       print("Inil%2.2uX+", ctlr->command);
                return;
        }
-
        if(status & Err)
                drive->error = inb(cmdport+Error);
        else switch(drive->command){
@@ -1995,8 +1885,8 @@ badccru(Pcidev *p)
        switch(p->did<<16 | p->did){
        case 0x439c<<16 | 0x1002:
        case 0x438c<<16 | 0x1002:
-print("hi, anothy\n");
-print("%T: allowing bad ccru %.2ux for suspected ide controller\n", p->tbdf, p->ccru);
+               print("%T: allowing bad ccru %.2ux for suspected ide controller\n",
+                       p->tbdf, p->ccru);
                return 1;
        default:
                return 0;
@@ -2075,6 +1965,7 @@ atapnp(void)
                case (0x4D69<<16)|0x105A:       /* Promise Ultra/133 TX2 */
                case (0x3373<<16)|0x105A:       /* Promise 20378 RAID */
                case (0x3149<<16)|0x1106:       /* VIA VT8237 SATA/RAID */
+               case (0x0415<<16)|0x1106:       /* VIA VT6415 PATA IDE */
                case (0x3112<<16)|0x1095:       /* SiL 3112 SATA/RAID */
                        maxio = 15;
                        span = 8*1024;
@@ -2099,7 +1990,6 @@ atapnp(void)
                         */
                        break;
                case (0x7441<<16)|0x1022:       /* AMD 768 */
-               case (0x7800<<16)|0x1022:
                        /*
                         * Set:
                         *      0x41    prefetch, postwrite;
@@ -2130,6 +2020,7 @@ atapnp(void)
                case (0x0266<<16)|0x10DE:       /* nVidia nForce4 430 SATA */
                case (0x0265<<16)|0x10DE:       /* nVidia nForce 51 MCP */
                case (0x0267<<16)|0x10DE:       /* nVidia nForce 55 MCP SATA */
+               case (0x037f<<16)|0x10DE:       /* nVidia nForce 55 MCP SATA */
                case (0x03ec<<16)|0x10DE:       /* nVidia nForce 61 MCP SATA */
                case (0x03f6<<16)|0x10DE:       /* nVidia nForce 61 MCP PATA */
                case (0x0448<<16)|0x10DE:       /* nVidia nForce 65 MCP SATA */
@@ -2151,6 +2042,15 @@ atapnp(void)
                case (0x438c<<16)|0x1002:       /* ATI SB600 PATA */
                case (0x439c<<16)|0x1002:       /* SB7xx pata */
                        break;
+
+               case (0x6101<<16)|0x11ab:       /* Marvell PATA */
+               case (0x6121<<16)|0x11ab:       /* Marvell PATA */
+               case (0x6123<<16)|0x11ab:       /* Marvell PATA */
+               case (0x6145<<16)|0x11ab:       /* Marvell PATA */
+               case (0x1b4b<<16)|0x91a0:       /* Marvell PATA */
+               case (0x1b4b<<16)|0x91a4:       /* Marvell PATA */
+                       break;
+
                case (0x0211<<16)|0x1166:       /* ServerWorks IB6566 */
                        {
                                Pcidev *sb;
@@ -2185,6 +2085,10 @@ atapnp(void)
                case (0x7111<<16)|0x8086:       /* 82371[AE]B (PIIX4[E]) */
                        maxdma = 0x20000;
                        break;
+               case (0x1c00<<16)|0x8086:       /* SERIES6 SATA */
+               case (0x1c01<<16)|0x8086:       /* SERIES6 SATA */
+               case (0x1c08<<16)|0x8086:       /* SERIES6 SATA */
+               case (0x1c09<<16)|0x8086:       /* SERIES6 SATA */
                case (0x2411<<16)|0x8086:       /* 82801AA (ICH) */
                case (0x2421<<16)|0x8086:       /* 82801AB (ICH0) */
                case (0x244A<<16)|0x8086:       /* 82801BA (ICH2, Mobile) */
@@ -2198,6 +2102,7 @@ atapnp(void)
                case (0x25A2<<16)|0x8086:       /* 6300ESB pata */
                case (0x25A3<<16)|0x8086:       /* 6300ESB (E7210) */
                case (0x266F<<16)|0x8086:       /* 82801FB (ICH6) */
+               case (0x2651<<16)|0x8086:       /* 82801FB (ICH6) */
                case (0x2653<<16)|0x8086:       /* 82801FBM (ICH6, Mobile) */
                case (0x269e<<16)|0x8086:       /* 63xxESB (intel 5000) */
                case (0x27DF<<16)|0x8086:       /* 82801G PATA (ICH7) */
@@ -2206,6 +2111,7 @@ atapnp(void)
                case (0x27C5<<16)|0x8086:       /* 82801GBM SATA AHCI (ICH7) */
                case (0x2850<<16)|0x8086:       /* 82801HBM/HEM PATA */
                case (0x2820<<16)|0x8086:       /* 82801HB/HR/HH/HO SATA IDE */
+               case (0x2825<<16)|0x8086:       /* 82801IIH Intel Q35 IDE */
                case (0x2828<<16)|0x8086:       /* 82801HBM SATA (ICH8-M) */
                case (0x2829<<16)|0x8086:       /* 82801HBM SATA AHCI (ICH8-M) */
                case (0x2920<<16)|0x8086:       /* 82801(IB)/IR/IH/IO SATA (ICH9) port 0-3 */
@@ -2227,6 +2133,10 @@ atapnp(void)
                                map |= 2;
                        irqack = ichirqack;
                        break;
+               case (0x811a<<16)|0x8086:       /* Intel SCH (Poulsbo) */
+                       map = 1;
+                       irqack = ichirqack;
+                       break;
                }
                for(channel = 0; channel < 2; channel++){
                        if((map & 1<<channel) == 0)
@@ -2258,7 +2168,7 @@ atapnp(void)
                        ctlr->maxdma = maxdma;
                        ctlr->span = span;
                        ctlr->irqack = irqack;
-                       if(pi & 0x80)
+                       if((pi & 0x80) && (p->mem[4].bar & 0x01))
                                ctlr->bmiba = (p->mem[4].bar & ~0x01) + channel*8;
                        if(head != nil)
                                tail->next = sdev;
@@ -2353,7 +2263,8 @@ ataenable(SDev* sdev)
                atadmaclr(ctlr);
                if(ctlr->pcidev != nil)
                        pcisetbme(ctlr->pcidev);
-               ctlr->prdt = mallocalign(Nprd*sizeof(Prd), 4, 0, 64*1024);
+               /* Intel SCH requires 8 byte alignment, though datasheet says 4 m( */
+               ctlr->prdt = mallocalign(Nprd*sizeof(Prd), 8, 0, 64*1024);
        }
        snprint(name, sizeof(name), "%s (%s)", sdev->name, sdev->ifc->name);
        intrenable(ctlr->irq, atainterrupt, ctlr, ctlr->tbdf, name);
@@ -2380,6 +2291,7 @@ atadisable(SDev *sdev)
                if (ctlr->pcidev)
                        pciclrbme(ctlr->pcidev);
                free(ctlr->prdt);
+               ctlr->prdt = nil;
        }
        return 0;
 }
@@ -2387,21 +2299,31 @@ atadisable(SDev *sdev)
 static int
 ataonline(SDunit *unit)
 {
-       Ctlr *ctlr;
        Drive *drive;
+       Ctlr *ctlr;
+       int ret;
 
        if((ctlr = unit->dev->ctlr) == nil || ctlr->drive[unit->subno] == nil)
                return 0;
+       ret = 1;
        drive = ctlr->drive[unit->subno];
        if((drive->flags & Online) == 0){
                drive->flags |= Online;
                atadrive(unit, drive, ctlr->cmdport, ctlr->ctlport, drive->dev);
+               ret = 2;
        }
-       unit->sectors = drive->sectors;
-       unit->secsize = drive->secsize;
-       if(drive->feat & Datapi)
-               return scsionline(unit);
-       return 1;
+       if(drive->feat & Datapi){
+               ulong dma;
+
+               dma = drive->dmactl;
+               drive->dmactl = 0;
+               ret = scsionline(unit);
+               drive->dmactl = dma;
+       } else {
+               unit->sectors = drive->sectors;
+               unit->secsize = drive->secsize;
+       }
+       return ret;
 }
 
 static int
@@ -2436,6 +2358,8 @@ atarctl(SDunit* unit, char* p, int l)
                if(drive->pkt == 0 && (drive->feat & Dlba) == 0)
                        p = seprint(p, e, " %d %d %d", drive->c, drive->h, drive->s);
                p = seprint(p, e, "\n");
+               p = seprint(p, e, "alignment %d %d\n",
+                       drive->secsize<<drive->physshift, drive->physalign);
        }
        p = seprint(p, e, "missirq      %ud\n", drive->missirq);
        p = seprint(p, e, "sloop        %ud\n", drive->spurloop);
@@ -2514,7 +2438,7 @@ SDifc sdideifc = {
        "ide",                          /* name */
 
        atapnp,                         /* pnp */
-       nil,                    /* legacy */
+       nil,                            /* legacy */
        ataenable,                      /* enable */
        atadisable,                     /* disable */